Subsections

1. Using SAGE

Much of SAGE is written in Python. No Python background is needed to read this tutorial. Some background on Python will be needed by the heavy SAGE user, but this is not the place for that. For those who just want to just try out SAGE, this is the place to start.

1.1 Installation

See the document Installing SAGE at [SA] for instructions on installing SAGE on your computer. Here we merely make two comments.

(1)
The SAGE download file comes with ``everything including batteries''. In other words, although SAGE uses Python, IPython, PARI, GMP, and so on, you do not need to install them separately as they are included with the SAGE distribution.

(2)
The ``binary'' version of SAGE (found on the SAGE website) is the easist to install (compared to the ``source'' version). Basically, just unpack the file and run sage. (In windows, cygwin is required though-see www.cygwin.com.)

1.2 Input and Output

You can use SAGE either via an interactive shell, or you can write Python programs that use the SAGE library. To use SAGE as a Python module, set the shell environmental variables LD_LIBRARY_PATH, SAGE_HOME, PYTHONPATH correctly (see bin/sage), then run the Python 2.4 interpreter included with SAGE (bin/python), and type

>>> from all import *

In this tutorial we assume you start SAGE using the sage command located in the bin/sage subdirectory. This starts a customized version of the excellent IPython shell, and imports many functions and classes, so they are ready to use from the command prompt. Even further customization is possible by editing the conf/ipythonrc file to your taste. Upon starting SAGE you get output similar to the following:

SAGE Version 0.3, Export Date: 2005-07-01-0851
Copyright (C) 2005 William Stein <was@math.harvard.edu>
Distributed under the terms of the GNU General Public License (GPL)

sage:
To quit SAGE, do one of the following:

  1. Type quit.
  2. Ctrl-D (or EOF)
  3. Use the IPython magic command %Exit or %Quit.

SAGE (via IPython) logs all SAGE input (not the output). You may use the set_verbose command to log the output as well. In fact, at any point, you may type %hist to get a listing of all lines typed so far. You can type ? at the SAGE prompt to find out more about IPython. Here is a piece of this information: ``IPython offers numbered prompts (In/Out) with input and output caching. All input is saved and can be retrieved as variables (besides the usual arrow key recall). The following GLOBAL variables always exist (so don't overwrite them!):

  _i: stores previous input.
  _ii: next previous.
  _iii: next-next previous.
  _ih : a list of all input _ih[n] is the input from line n.

Here is an example:

was@form:~$ sage
...
Copyright (C) 2005 William Stein <was@math.harvard.edu>
Distributed under the terms of the GNU General Public License (GPL)

sage: factor(100)
      2^2 * 5^2
sage: kronecker(3,5)
      -1
sage: %hist
1: factor(100)
2: kronecker(3,5)
sage: _i1
      'factor(100)\n'
sage: eval(_i1)
      [(2, 2), (5, 2)]
sage: %hist
1: factor(100)
2: kronecker(3,5)
3: %hist
4: _i1
5: eval(_i1)
sage: _ih
      ['\n', 'factor(100)\n', 'kronecker(3,5)\n', '#%hist\n', '_i1\n', 
                'eval(_i1)\n', '#%hist\n', '_ih\n']

In UNIX, any shell command can be executed from SAGE by prefacing it by an exclamation point (!). For example,

sage: !ls
...
returns the listing of the current directory. To read in a python file, type

sage: execfile("filename")
However, this file must contain pure Python, not SAGE commands (e.g., use ** for exponentiation and must explicitly import the SAGE library). To input a file of commands exactly as if you were typing them into the interpreter, type

sage: load "filename.py"
or

sage: run -i "filename.py"

For much more about the extensive features of the interactive interpreter see the IPython documentation.

1.3 Copy and Paste

Suppose you are reading a session of SAGE or Python computations and want to copy them into SAGE. But there are these annoying >>> or sage: prompts to worry about. In fact, you can copy and paste an example, including the prompts if you want, into SAGE. In other words, by default the SAGE parser strips any leading >>> or sage: prompt before passing it to Python1.1. For example,

sage: 2^10
      1024
sage: sage: 2^10
      1024
sage: >>> 2^10
      1024

1.4 Timing Commands

If you place the time comand at the beginning of an input line, the time the command takes will be displayed after the output. For example, we can compare the running time for a certain exponentiation operation using three large integer arithmetic packages: First, native Python:

sage: time a = int(1938)^int(99484)
CPU times: user 0.66 s, sys: 0.00 s, total: 0.66 s
Wall time: 0.66
Next the SAGE Integer type, which is implemented using the GMP C library:

sage: time a = 1938^99484
CPU times: user 0.04 s, sys: 0.00 s, total: 0.04 s
Wall time: 0.04
sage: time len(str(a))         # computing decimal digits takes awhile.
CPU times: user 0.51 s, sys: 0.00 s, total: 0.51 s
Wall time: 0.68
327040
Finally using the PARI C-library interface:

sage: time a = pari(1938)^pari(99484)
CPU times: user 0.05 s, sys: 0.00 s, total: 0.05 s
Wall time: 0.05
GMP wins, but only slightly (as expected, since PARI uses GMP for integer arithmetic).

You can also time a block of commands using the cputime command, defined in sage.misc.misc, and available by default in the interpreter.

sage: t = cputime()
sage: a = int(1938)^int(99484)
sage: b = 1938^99484
sage: c = pari(1938)^pari(99484)
sage: print cputime(t)
0.64
sage: cputime?
...
    Return the time in CPU second since \SAGE{}  started, or with optional
    argument t, return the time since time t.
    INPUT:
        t -- (optional) float, time in CPU seconds
    OUTPUT:
        float -- time in CPU seconds

1.5 Errors and Exceptions

When you make a syntax error, you will see what Python calls an ``exception''. It even tries to suggest what it is that it that raised the exception. Often you see the name of the exception, e.g., NameError or ValueError (see the Python Reference Manual [Py] for more details). For example,

sage: 3_2
------------------------------------------------------------
   File "<console>", line 1
     ZZ(3)_2
           ^
SyntaxError: invalid syntax

sage: EllipticCurve([0,infinity])
------------------------------------------------------------
Traceback (most recent call last):
  File "<console>", line 1, in ?
  File "/home/wdj/.../ellcurve.py", line 139, in __new__
    return EllipticCurve_RationalField(*args, **kwds)
  File "/home/wdj/.../ellcurve.py", line 661, in __init__
    EllipticCurve_generic.__init__(self, [Q(x) for x in ainvs])
  File "/home/wdj/.../rational_field.py", line 79, in __call__
    return sage.rings.rational.Rational(x)
  File "_rational.pyx", line 82, in _rational.Rational.__init__
  File "_rational.pyx", line 116, in _rational.Rational.__set_value
TypeError: Unable to coerce Infinity (<class 'sage...Infinity'>) to Rational
Note that the first error (3_2) wasn't so bad-- SAGE actually returned a prompt--thus giving us an opportunity to try to define the ``elliptic curve'' $y^2=x^3+\infty$.

The prompt (Pdb) is a for the interactive debugger, which you can toggle on/off using %pdb (the default is off). You can print the state of any local variable, and move up and down the execution stack. For example,

sage: %pdb
Automatic pdb calling has been turned ON
sage: EllipticCurve([1,infinity])
------------------------------------------------------------
Traceback (most recent call last):
  File "<console>", line 1, in ?
  File "/home/wdj/.../ellcurve.py", line 139, in __new__
    return EllipticCurve_RationalField(*args, **kwds)
  File "/home/wdj/.../ellcurve.py", line 661, in __init__
    EllipticCurve_generic.__init__(self, [Q(x) for x in ainvs])
  File "/home/wdj/.../rational_field.py", line 79, in __call__
    return sage.rings.rational.Rational(x)
  File "_rational.pyx", line 82, in _rational.Rational.__init__
  File "_rational.pyx", line 116, in _rational.Rational.__set_value
TypeError: Unable to coerce Infinity (<class 'sage...Infinity'>) to Rational

> /home/wdj/.../_rational.pyx(116)_rational.Rational.__set_value()
(Pdb)
For a list of commands in the debugger type ? at the (Pdb) prompt:

(Pdb) ?

Documented commands (type help <topic>):
========================================
EOF    break  condition  disable  help    list  q       step     w
a      bt     cont       down     ignore  n     quit    tbreak   whatis
alias  c      continue   enable   j       next  r       u        where
args   cl     d          exit     jump    p     return  unalias
b      clear  debug      h        l       pp    s       up

Type Ctrl-D to return to SAGE.

1.6 Rings: Rational Numbers

We illustrate commutative rings in SAGE with the field $\mathbf{Q}$ of rational numbers.

sage: QQ = RationalField()
In fact, both Q and QQ are already known to SAGE to be the field of rationals. But don't worry, if you use both names as variables, you can still fetch the rational numbers using the command RationalField(). By the way, other pre-defined SAGE rings are the (GMP arbitrary precision) integers ZZ, the (Python float) reals RR, and the (Python) complexes CC (which uses i, as usual, for the square root of $-1$). Rings of polynomials are covered later in this tutorial.

sage: (a, b) = (4/3, 2/3)     
sage: a + b
      2
sage: 2*b == a
      True
sage: ZZ                   # pre-defined
      Integer Ring
sage: ZZ(2) / ZZ(3) == b   # quotient of two integers is a rational if necessary
      True
sage: type(ZZ(3)/ZZ(2))
      <type 'rational.Rational'>
sage: type(ZZ(4)/ZZ(2))
      <type 'rational.Rational'>
sage: 2/3+0.1
      0.766666666666666666661       #automatic coersion before addition
sage: z=a+b*i
sage: z
      1.33333333333333333333 + 0.666666666666666666667*I
sage: z.real()==a       #automatic coersion before comparision
      True

A basic rule to keep in mind when using SAGE : the type of everything other than predefined Python objects (like strings, integers, lists, ...), must be specified before SAGE can compute with it. But every rule has its exception. In this case, the exception is for the rational numbers. The SAGE parser in IPython automatically converts the 4/3 you type in to ZZ(4)/ZZ(3) before evalution1.2. However one can assign a value to a variable before specifying its type. Thus SAGE is weakly-typed (or dynamically typed), unlike Java or C++, which both require that the type of a variable be specified before it can be assigned to.


1.7 Tab Completion

First create the three dimensional vector space $V=\mathbf{Q}^3$.

sage: V = VectorSpace(QQ,3)
sage: V              
      Full Vector space of degree 3 over Rational Field

Using the readline library1.3, type the beginning of a line, then Ctrl-p to go back to each line you've ever entered that begins in that way. This even works if you completely exit SAGE and restart later, at least if you don't update to a new version in the mean-time. You can also do a reverse search through the history using Ctrl-r.

Another feature of readline is that it is easy to list all member functions for $V$ using tab completion. Just type V., then type the [tab key] key on your keyboard:

sage: V.[tab key]
V._VectorSpace_generic__base_field
V._VectorSpace_generic__degree
V._VectorSpace_generic__is_sparse
V._VectorSpace_generic__set_vector_class
V._VectorSpace_generic__vector_class
V._echelon_coordinates
V.ambient_space
V.base_field
V.base_ring
V.basis
V.coordinates
V.degree
V.dimension
V.echelonized_basis
V.gen
V.gens
V.is_ambient
V.is_dense
V.is_full
V.is_sparse
V.list
V.matrix
V.ngens
V.random
V.random_element
V.subspace
V.subspace_with_basis
V.vector
V.vector_space
V.zero_vector
sage: V.
If you type the first few letters of a function, then [tab key], you get only functions that begin as indicated.

sage: V.i[tab key]
V.is_ambient  V.is_dense    V.is_full     V.is_sparse
sage: V.is_

1.8 Integrated Help System

SAGE contains an integrated help facility, which is actually a feature implemented by IPython. Type a function name followed by ? for the documentation for that function. The documentation contains (or will contain!) the file in which the function is defined, a description of each input argument, a description of each output argument, and examples illustrating usage. The examples assume only that the file in which the command is defined has been included. This means that if you import that file in your own Python programs, then the examples will work; in particular, no special SAGE syntax conversions (e.g., ^ $\to$ **) are incorporated in these examples. These examples are viewed by the authors of SAGE as being extremely important, and are regularly automatically tested to make sure they work exactly as claimed.

Another useful feature is that if f is a Python function, then typing ?f? displays the source code that defines f.

sage: V = VectorSpace(QQ,10)
sage: V
      Full Vector space of degree 10 over Rational Field
sage: V.subspace?
Type:           instancemethod
Base Class:     <type 'instancemethod'>
String Form:    <bound method VectorSpace_ambient.subspace of Full 
                 Vector space of degree 3 overRational Field>
Namespace:      Interactive
File:           /home/was/sage/src/sage/linalg/vector_space.py
Definition:     V.subspace(self, gens)
Docstring:
    Create a subspace of self.

    INPUT:
        gens -- a list of vector in self
    OUTPUT:
        VectorSpace -- the subspace spanned by the vectors in the 
        list gens. The basis for the subspace is always put in 
        reduced row echelon form.
    EXAMPLES:
        >>> import sage.rings.rings as rings
        >>> V = VectorSpace(rings.RationalField(), 3)
        >>> B = V.basis()
        >>> W = V.subspace([B[0]+B[1], 2*B[1]-B[2]])
        >>> W
        Vector space of degree 3, dimension 2 over Rational Field
        Basis matrix:
        [   1    0  1/2]
        [   0    1 -1/2]
You may also type help(command_name) or help(class) for a man page like help file about a given class. This documentation is automatically extracted from the source code.

sage: help(VectorSpace)
Help on class VectorSpace in module sage.linalg.vector_space:

class VectorSpace(__builtin__.object)
 |  Create a Vector Space.
 |
 |  Two create an ambient space over a field with given dimension
 |  using the calling syntax
 |      VectorSpace(field, dimension, sparse=True)
 |  and to create a subspace use
 |      VectorSpace(list_of_vectors),
 |  where list_of_vectors is a list of vectors in a VectorSpace.
 |
 |  EXAMPLES:
 |  First we create some ambient spaces.
 |      >>> from sage.rings.rings import RationalField, CyclotomicField
 |      >>> V = VectorSpace(RationalField(), 389); V
 |      Full Vector space of degree 389 over Rational Field
 |      >>> V.dimension()
 |      389
 :
When you type q to exit the help system, your session appears just as it was. The help listing does not clutter up your session, unlike the output of function_name?.

sage: help(VectorSpace)

sage:

1.9 Data Types

The vector space $V$ is an object of type VectorSpace_ambient, which is defined in the file sage/linalg/vector_space.py.

sage: V = VectorSpace(QQ,10)
sage: type(V)
      <class 'sage.linalg.vector_space.VectorSpace_ambient'>

Only certain functions can be called on $V$. In most other math software systems, these would be called using the notation foo(V,...). In SAGE, the functions belong to the class of $V$, and are called using an object-oriented syntax like in Java or C++, i.e., V.foo(...). This helps keep the global namespace from being polluted with thousands of functions.

In many cases functional notation is still allowed, for convenience and because mathematical expressions often look funny using object oriented notation. The file sage/all.py contains function definitions such as

def basis(x): return x.basis()
which transform the usual functional notation into the object oriented notation in some cases. For example

sage: V = VectorSpace(QQ,2)
sage: V.basis()
      [(1 0), (0 1)]
sage: basis(V)
      [(1 0), (0 1)]
sage: sage: M = MatrixSpace(GF(7), 2)
sage: M
      Full MatrixSpace of 2 by 2 dense matrices over Finite field of size 7
sage: A = M([1,2,3,4])
sage: A

[1 2]
[3 4]

sage: powers=[A^i for i in range(2,100)]
sage: powers.index(A)
      47
sage: A^49 #the range of powers was shifted by 2, so 47 shifts to 49.

[1 2]
[3 4]

sage: A.charpoly()
      x^2 + 2*x + 5
sage: charpoly(A)
      x^2 + 2*x + 5

It is easy to list all member functions for $A$, using tab completion from the readline library. Just type A., then type the [tab key] key on your keyboard, as explained in Section 1.7.

Other data types include lists, whose elements are indexed starting from $0$:

sage: L = [factor(n) for n in range(20)]
sage: L
[(1),
 (1),
 2,
 3,
 2^2,
 5,
 2 * 3,
 7,
 2^3,
 3^2,
 2 * 5,
 11,
 2^2 * 3,
 13,
 2 * 7,
 3 * 5,
 2^4,
 17,
 2 * 3^2,
 19]
sage: L[0]
      (1)
sage: L[12]
      2^2 * 3
sage: type(L[12])
 _5 = <class 'sage.structure.factorization.Factorization'>

Array slicing is supported (L[m:n] starts at the $m^{th}$ element and stops at the $(n-1)^{st}$ element):

sage: L[5:10]
      [5, 2 * 3, 7, 2^3, 3^2]
sage: L[:5]
      [(1), (1), 2, 3, 2^2]
sage: L[15:5]
      []
sage: L[15:]
      [3 * 5, 2^4, 17, 2 * 3^2, 19]

1.10 Control Statements and Comparisons

We have seen a few examples already of some common uses of for loops. In Python, a for loop has an indented structure, such as

>>> for i in range(5):
       print(i)
   
0
1
2
3
4
Note the colon at the end of the for statement (there is no ``do'' or ``od'' as in GAP or Maple), and the indentation before the ``body'' of the loop, namely print(i). This indentation is important. In SAGE, the indentation is automatically put in for you when you hit enter after a ``:'', as illustrated below.

sage: for i in range(5):
   ....:    print(i)  # now hit enter twice
   ....:
0
1
2
3
4
sage:

The symbol = is used for assignment. The symbol == is used to check for equality:

sage: for i in range(15):
   ....:    if gcd(i,15)==1:
   ....:        print(i)
   ....:
1
2
4
7
8
11
13
14
Programming in SAGE is not too hard if you keep in mind the indentation requirement for if and for statements:

sage: def legendre(a,p):
   ....:    is_sqr_modp=-1
   ....:    for i in range(p):
   ....:        if a % p == i^2 % p:
   ....:            is_sqr_modp=1
   ....:    return is_sqr_modp
   ....:
sage: legendre(2,7)
      1
sage: legendre(3,7)
      -1
(Of course this is not an efficient implementation of the Legendre symbol! It is meant to illustrate various aspects of Python/SAGE programming. The function kronecker, which comes with SAGE, computes the Legendre symbol efficiently via a C-library call to PARI.)

Finally, we note that comparisons, such as ==, !=, <=, >=, >, <, between numbers will automatically convert both numbers into the same type if possible:

sage: 2 < 3.1; 3.1 <= 1; 2 < 3.1 <= 1
      True
      False
      False
sage: 2/3<3/2; 3/2 < 3/1
      True
      True
sage: 2 < 3.1+0.0*i; 3.1+2*i<4+3*i; 3.1+2*i<4+1.5*i
      True
      True
      False

Usually when comparing objects of different types in SAGE, the object on the right side is coerced to the parent of the object on the left. For testing whether two variables reference the same object use is. For example,

sage: 1 is 2/2
False
sage: 1 is 1
False
sage: 1 == 2/2
True
The first is False, because the object on the left is an integer, and the one on the right is a rational, so they are not the same object. The second is False, because the 1's are constructed separately, so are not the same object (even though they are considered equal). The third is True, since the rational on the right can be coerced into the integers.



Footnotes

... Python1.1
Implementation Note: This is implemented in sage/misc/interpreter.py, which contains code to remove »> or sage: from the beginning of a line.
... evalution1.2
Otherwise, 4/3 would be passed to Python as is, and in Python 4/3 is the same as the integer quotient of 4 divided by 3, which is 1.
... library1.3
Currently not working on some versions of 64-bit Linux.
See About this document... for information on suggesting changes.