sage
command. This starts a customized version of the
IPython shell, and imports many functions and classes, so they are
ready to use from the command prompt. Further customization is
possible by editing the $SAGE_ROOT/ipythonrc
file. Upon
starting SAGE you get output similar to the following:
-------------------------------------------------------- | SAGE Version 1.0.0.1, Build Date: 2006-02-05-0745 | | Distributed under the GNU General Public License V2 | | For help type <object>?, <object>??, %magic, or help | -------------------------------------------------------- sage:
quit
or exit
.
sage: quit Exiting SAGE (CPU time 0m0.00s, Wall time 0m0.89s)
Note:
Avoid killing a SAGE process with kill -9
from a terminal,
since SAGE might not kill child processes, e.g.,
maple processes, or cleanup tempoary files from
$HOME/.sage/tmp
.
The session is the sequence of input and output from
when you start SAGE until you quit.
SAGE via IPython logs all SAGE input. In fact, at any point,
you may type
%hist
to get a listing of all input lines typed so far.
You can type ?
at the SAGE prompt to find out more about
IPython, e.g., ``IPython offers
numbered prompts ... 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!)'':
_: previous input. __: next previous. _oh : output entry for all lines that generated input
Here is an example:
sage: factor(100) _1 = 2^2 * 5^2 sage: kronecker_symbol(3,5) _2 = -1 sage: %hist 1: factor(100) 2: kronecker_symbol(3,5) 3: %hist sage: _oh _4 = {1: 2^2 * 5^2, 2: -1} sage: _i1 _5 = 'factor(ZZ(100))\n' sage: eval(_i1) _6 = 2^2 * 5^2 sage: %hist 1: factor(100) 2: kronecker_symbol(3,5) 3: %hist 4: _oh 5: _i1 6: eval(_i1) 7: %hist
You can also store a list of input from session in a macro for that session.
sage: E = EllipticCurve([1,2,3,4,5]) sage: M = ModularSymbols(37) sage: %hist 1: E = EllipticCurve([1,2,3,4,5]) 2: M = ModularSymbols(37) 3: %hist sage: %macro em 1-2 Macro `em` created. To execute, type its name (without quotes).
sage: E Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field sage: E = 5 sage: M = None sage: em Executing Macro... sage: E Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field
Any UNIX shell command can be executed from SAGE by prefacing it by an exclamation point (!). For example,
sage: !ls auto example.sage glossary.tex t tmp tut.log tut.tex
The $PATH
has the SAGE bin directory at the front, so if
you run gp
, gap
, singular
, maxima
,
etc., you get the versions included with SAGE.
sage: !gp Reading GPRC: /etc/gprc ...Done. GP/PARI CALCULATOR Version 2.2.11 (alpha) i686 running linux (ix86/GMP-4.1.4 kernel) 32-bit version ... sage: !singular SINGULAR / Development A Computer Algebra System for Polynomial Computations / version 3-0-1 0< by: G.-M. Greuel, G. Pfister, H. Schoenemann \ October 2005 FB Mathematik der Universitaet, D-67653 Kaiserslautern \
Logging your SAGE session is not the same as
saving it (see §3.9 for that).
To log input (and optionally output) use the logstart
command.
Type logstart?
for more details. You can use this command to
log all input you type, all output, and even play back that input in a
future session (by simply reloading the log file).
was@form:~$ sage -------------------------------------------------------- | SAGE Version 0.10.11, Build Date: 2006-01-28-0723 | | Distributed under the GNU General Public License V2 | | For help type <object>?, <object>??, %magic, or help | -------------------------------------------------------- sage: logstart setup Activating auto-logging. Current session state plus future input saved. Filename : setup Mode : backup Output logging : False Timestamping : False State : active sage: E = EllipticCurve([1,2,3,4,5]).minimal_model() sage: F = QQ^3 sage: x,y = QQ['x,y'].gens() sage: G = E.gens() sage: Exiting SAGE (CPU time 0m0.61s, Wall time 0m50.39s). was@form:~$ sage -------------------------------------------------------- | SAGE Version 0.10.11, Build Date: 2006-01-28-0723 | | Distributed under the GNU General Public License V2 | | For help type <object>?, <object>??, %magic, or help | -------------------------------------------------------- sage: load "setup" Loading log file <setup> one line at a time... Finished replaying log file <setup> sage: E Elliptic Curve defined by y^2 + x*y = x^3 - x^2 + 4*x + 3 over Rational Field sage: x*y x*y sage: G [(2 : 3 : 1)]
Suppose you are reading a session of SAGE or Python computations and
want to copy them into SAGE. But there are 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 Python. For example,
sage: 2^10 1024 sage: sage: sage: 2^10 1024 sage: >>> 2^10 1024
If you place the time
command at the beginning of an input
line, the time the command takes to run will be displayed after the
output. For example, we can compare the running time for a certain
exponentiation operation in several ways. The timings below
will probably be much different on your computer, or even between
different versions of SAGE. 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 we time exponentiation using the native SAGE Integer type, which is implemented (in Pyrex) using the GMP 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 a = pari(1938)^pari(99484) CPU times: user 0.05 s, sys: 0.00 s, total: 0.05 s Wall time: 0.05
You can also time a block of commands using the cputime
command,
as illustrated below:
sage: t = cputime() sage: a = int(1938)^int(99484) sage: b = 1938^99484 sage: c = pari(1938)^pari(99484) sage: cputime(t) # somewhat random output 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
The walltime
command behaves just like the cputime
command, except that it measures wall time.
We can also compute the above power in some of the computer algebra systems that SAGE includes. In each case we execute a trivial command in the system, in order to start up the server for that program. The most relavant time is the wall time. However, if there is a significant difference between the wall time and the cpu time then this may indicate a performanve issue worth looking into.
sage: gp(0) 0 sage: time g=gp('1938^99484') CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s Wall time: 0.09 sage: maxima(0) 0 sage: time g=maxima('1938^99484') CPU times: user 4.91 s, sys: 0.27 s, total: 5.18 s Wall time: 24.93 sage: kash(0) 0 sage: time g=kash('1938^99484') CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s Wall time: 0.07 sage: mathematica(0) 0 sage: time g=mathematica('1938^99484') CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s Wall time: 0.07 sage: maple(0) 0 sage: time g=maple('1938^99484') CPU times: user 3.74 s, sys: 0.04 s, total: 3.79 s Wall time: 5.25 sage: gap(0) 0 sage: time g=gap.eval('a:=1938^99484;; 1;') CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s Wall time: 8.84
When something goes wrong, you will usually see a Python
``exception''. Python 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 a complete list of exceptions). For example,
sage: 3_2 ------------------------------------------------------------ File "<console>", line 1 ZZ(3)_2 ^ SyntaxError: invalid syntax sage: EllipticCurve([0,infinity]) ------------------------------------------------------------ Traceback (most recent call last): ... TypeError: Unable to coerce Infinity (<class 'sage...Infinity'>) to Rational
The interactive debugger is sometimes useful for understanding what
went wrong. You can toggle it being on or off using
%pdb
(the default is off).
The prompt (Pdb)
appears if an exception is raised and the
debugger is on. From within the debugger, 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): ... TypeError: Unable to coerce Infinity (<class 'sage.rings.infinity.Infinity'>) to Rational > /home/was/sage/sage-doc/tut/_rational.pyx(147)_rational.Rational.__set_value() (Pdb)
?
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 or quit
to return to SAGE.
First create the three dimensional vector space
as
follows:
sage: V = VectorSpace(QQ,3) sage: V Vector space of dimension 3 over Rational Field
sage: V = QQ^3
Type the beginning of a line, then Ctrl-p
to go back to each
line you have entered that begins in that way. This works even if
you completely exit SAGE and restart later. You can also do a
reverse search through the history using Ctrl-r
. You can also
hit the up arrow key to go back though previous commands (even if
you completely exit SAGE and restart). All these features use the
readline
package, which is available on most flavors of linux.
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.ambient_space V.base_field V.base_ring V.basis V.coordinates ... V.zero_vector
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
If you wonder what a particular function does, e.g., the
coordinates function, type V.coordinates?
for
help or V.coordinates??
for the source code,
as explained in the next section.
SAGE features an integrated help facility. Type a function name followed by ? for the documentation for that function.
sage: V = QQ^3 sage: V.coordinates? Type: instancemethod Base Class: <type 'instancemethod'> String Form: <bound method FreeModule_ambient_field.coordinates of Vector space of dimension 3 over Rational Field> Namespace: Interactive File: /home/was/s/local/lib/python2.4/site-packages/sage/modules/free_module.py Definition: V.coordinates(self, v) Docstring: Write v in terms of the basis for self. Returns a list c such that if B is the basis for self, then sum c_i B_i = v. If v is not in self, raises an ArithmeticError exception. EXAMPLES: sage: M = FreeModule(IntegerRing(), 2); M0,M1=M.gens() sage: W = M.submodule([M0 + M1, M0 - 2*M1]) sage: W.coordinates(2*M0-M1) [2, -1]
As shown above, the output tells you the type of the object, the file in which it is defined, and a useful description of the function with examples that you can paste into your current session. Almost all of these examples are regularly automatically tested to make sure they work and behave exactly as claimed.
Another feature that is very much in the spirit of the open source
nature of SAGE is that if f
is a Python function, then
typing f??
displays the source code that defines f
.
For example,
sage: V = QQ^3 sage: V.coordinates?? Type: instancemethod ... Source: def coordinates(self, v): """ Write $v$ in terms of the basis for self. ... """ return self.coordinate_vector(v).list()
This tells us that all the coordinates
function does is call
the coordinate_vector
function and change the result
into a list. What does the coordinate_vector
function do?
sage: V = QQ^3 sage: V.coordinate_vector?? ... def coordinate_vector(self, v): ... return self.ambient_vector_space()(v)
coordinate_vector
function coerces its
input into the ambient space, which has the affect of
computing the vector of coefficients of coordinate_vector
function for subspaces, and it's different. We create
a subspace and see:
sage: V = QQ^3; W = V.span_of_basis([V.0, V.1]) sage: W.coordinate_vector?? ... def coordinate_vector(self, v): """ ... """ # First find the coordinates of v wrt echelon basis. w = self.echelon_coordinate_vector(v) # Next use transformation matrix from echelon basis to # user basis. T = self.echelon_to_user_matrix() return T.linear_combination_of_rows(w)
You may also type help(command_name)
or help(class)
for a manpage-like help file about a given class.
sage: help(VectorSpace) Help on class VectorSpace ... class VectorSpace(__builtin__.object) | Create a Vector Space. | | Two create an ambient space over a field with given dimension | using the calling syntax ... : :
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?
sometimes does. It's
particularly helpful to type help(module_name)
. For example,
vector spaces are defined in sage.modules.free_module
, so type
help(sage.modules.free_module)
for documentation about that
whole module. When viewing documentation using help you can search by
typing /
and in reverse by typing ?
.
Suppose you compute a matrix or worse, a complicated space of modular symbols, and would like to save it for later use. What can you do? There are several approaches that computer algebra systems take to saving individual objects.
Because SAGE uses Python it takes a different approach, which is that every object can be serialized, i.e., turned into a string from which that object can be recovered. This is in spirit similar to the unified I/O approach of PARI, except it doesn't have the drawback that objects print to screen in too complicated of a way. Also, support for saving and loading is (in most cases) completely automatic, requiring no extra programming; it's simply a feature of Python that was designed into the language from the ground up.
Almost all SAGE objects x can be saved in compressed form to disk
using save(x, filename)
(or in many cases
x.save(filename)
). To load the object back in use
load(filename)
.
sage: A = MatrixSpace(QQ,3)(range(9))^2 sage: A [ 15 18 21] [ 42 54 66] [ 69 90 111] sage: save(A, 'A')
sage: A = load('A') sage: A [ 15 18 21] [ 42 54 66] [ 69 90 111]
sage: E = EllipticCurve('11a') sage: v = E.anlist(100000) # takes a while sage: save(E, 'E') sage: quit
The saved version of
takes 153 kilobytes, since it
stores the first 100000
with it.
~/tmp$ ls -l E.sobj -rw-r--r-- 1 was was 153500 2006-01-28 19:23 E.sobj ~/tmp$ sage [...] sage: E = load('E') sage: v = E.anlist(100000) # instant!
Note:
In Python saving and loading is accomplished using
the cPickle module. In particular, a SAGE object x
can be saved via cPickle.dumps(x, 2)
. Note the
!
SAGE cannot save and load individual objects created in some other computer algebra systems, e.g., GAP, Singular, Maxima, etc. They reload in a state marked ``invalid''. In GAP, though many objects print in a form from which they can be reconstructed, many don't, so reconstructing from their print representation is purposely not allowed.
sage: a = gap(2) sage: a.save('a') sage: load('a') Traceback (most recent call last): ... ValueError: The session in which this object was defined is no longer running.
GP/PARI objects can be saved and loaded since their print representation is enough to reconstruct them.
sage: a = gp(2) sage: a.save('a') sage: load('a') 2
Saved objects can be re-loaded later on computers with different
architectures or operating systems, e.g., you could save a huge matrix
on 32-bit OS X and reload it on 64-bit Linux, find the echelon form,
then move it back. Also, in many cases you can even load objects into
version of SAGE that are different than they were saved in, as long
as the code for that object isn't too different. All the attributes
of the objects are saved, along with the class (but not source code)
that defines the object. If that class no longer exists in a new
version of SAGE, then the object can't be reloaded in that newer
version. But you could load it in an old version, get the objects
dictionary (with x.__dict__
), and save the dictionary, and load
that into the newer version.
sage: R.<x,y> = PolynomialRing(QQ,2) sage: f = (x+y)^7 sage: o = open('file.txt','w') sage: o.write(str(f)) sage: o.close()
SAGE has very flexible support for saving and loading complete sessions.
The command save_session(sessionname)
saves all the variables
you've defined in the current session as a dictionary in the given
sessionname
. (In the rare case when a variable does not support saving,
it is simply not saved to the dictionary.) The resulting file
is an .sobj
file and can be loading just like any other
object that was saved. When you load the objects saved in a session,
you get a dictionary whose keys are the variables names and whose
values are the objects.
You can use the load_session(sessionname)
command to load the
variables defined in sessionname
into the current session. Note
that this does not wipe out variables you've already defined in
your current session; instead, the two sessions are merged.
First we start SAGE and define some variables.
~/tmp$ sage sage: E = EllipticCurve('11a') sage: M = ModularSymbols(37) sage: a = 389 sage: t = M.T(2003).matrix(); t.charpoly().factor() _4 = (x - 2004) * (x - 12)^2 * (x + 54)^2
Next we save our session, which saves each of the above variables into a file. Then we view the file, which is about 3K in size.
sage: save_session('misc') Saving a Saving M Saving t Saving E sage: quit was@form:~/tmp$ ls -l misc.sobj -rw-r--r-- 1 was was 2979 2006-01-28 19:47 misc.sobj
Finally we restart SAGE, define an extra variable, and load our saved session.
~/tmp$ sage [...] sage: b = 19 sage: load_session('misc') Loading a Loading M Loading E Loading t
sage: M Full Modular Symbols space for Gamma_0(37) of weight 2 with sign 0 and dimension 5 over Rational Field sage: E Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field sage: b 19 sage: a 389
See About this document... for information on suggesting changes.