Much of SAGEis written in Python. No Python background is needed to read this tutorial. Some background on Python will be needed by the heavy SAGEuser, but this is not the place for that. For those who just want to just try out SAGE, this is the place to start.
See the document Installing SAGE at [SA] for instructions on installing SAGEon your computer. Here we merely make two comments.
sage
. (In windows,
cygwin is required though-see www.cygwin.com.)
You can use SAGEeither via an interactive shell, or you can write
Python programs that use the SAGElibrary.
To use SAGEas 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 SAGEusing 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 SAGEyou 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:
SAGE(via IPython) logs all SAGEinput (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 SAGEprompt 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 SAGEby prefacing it by an exclamation point (!). For example,
sage: !ls ...
sage: execfile("filename")
sage: load filename.py
sage: run -i filename.py
For much more about the extensive features of the interactive interpreter see the IPython documentation.
Suppose you are reading a session of SAGEor 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 SAGEparser 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
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 = 1938^99484 CPU times: user 0.04 s, sys: 0.00 s, total: 0.04 s Wall time: 0.04
sage: time a = ZZ(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.50 s, sys: 0.00 s, total: 0.50 s Wall time: 0.50 327040
sage: time a = pari(1938)^99484 CPU times: user 0.18 s, sys: 0.00 s, total: 0.18 s Wall time: 0.19
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 = 1938^99484 sage: b = ZZ(1938)^99484 sage: c = pari(1938)^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
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
3_2
) wasn't so bad--SAGE
actually returned a prompt--thus giving us an opportunity
to try to define the ``elliptic curve''
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)
(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.
We illustrate commutative rings in SAGEwith
the field of rational numbers.
sage: QQ = RationalField()
sage: a, b = 4/3, 2/3 # a neat Python feature 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.766666666666666666667 #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 SAGEparser 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 SAGEis 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.
First create the three dimensional vector space
.
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 SAGEand 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 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.
sage: V.i[tab key] V.is_ambient V.is_dense V.is_full V.is_sparse sage: V.is_
SAGEcontains 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 SAGEsyntax conversions (e.g.,
^
**
) are incorporated in these examples. These
examples are viewed by the authors of SAGEas 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]
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 :
sage: help(VectorSpace) sage:
The vector space 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 . In most other math
software systems, these would be called using the notation foo(V,...). In SAGE, the functions belong to the class of
, 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()
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 , 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 :
sage: L=[factor(n) for n in range(20)] sage: L [[], [], [(2, 1)], [(3, 1)], [(2, 2)], [(5, 1)], [(2, 1), (3, 1)], [(7, 1)], [(2, 3)], [(3, 2)], [(2, 1), (5, 1)], [(11, 1)], [(2, 2), (3, 1)], [(13, 1)], [(2, 1), (7, 1)], [(3, 1), (5, 1)], [(2, 4)], [(17, 1)], [(2, 1), (3, 2)], [(19, 1)]] sage: L[0] [] sage: L[12] [(2, 2), (3, 1)]
sage: L[5:10] [[(5, 1)], [(2, 1), (3, 1)], [(7, 1)], [(2, 3)], [(3, 2)]] sage: L[:5] [[], [], [(2, 1)], [(3, 1)], [(2, 2)]] sage: L[15:~5] [] sage: L[15:] [[(3, 1), (5, 1)], [(2, 4)], [(17, 1)], [(2, 1), (3, 2)], [(19, 1)]]
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
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
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 sage:
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 objects are the same us is
. For example,
sage: 1 is 2/2 False sage: 1 == 2/2 True
False
, because the object on the left is
an integer, and the one on the right is a rational, so they can't
be the same object. The second is true, since the rational on
the right can be coerced into the integers.