Die interaktive Kommandozeile¶
In den meisten Teilen dieses Tutorials gehen wir davon aus, dass Sie
Sage mit dem sage
-Befehl starten. Dieser startet eine angepasste
Version der IPython Kommandozeile und lädt Funktionen und Klassen,
sodass sie in der Kommandozeile genutzt werden können. Weitere
Anpassungen können Sie in der Datei $SAGE_ROOT/ipythonrc
vornehmen. Nach dem Start von Sage sehen Sie etwa folgendes:
┌────────────────────────────────────────────────────────────────────┐
│ SageMath version 9.7, Release Date: 2022-01-10 │
│ Using Python 3.10.4. Type "help()" for help. │
└────────────────────────────────────────────────────────────────────┘
sage:
Um Sage zu beenden drücken Sie Strg-D oder geben Sie
quit
oder exit
ein.
sage: quit
Exiting Sage (CPU time 0m0.00s, Wall time 0m0.89s)
>>> from sage.all import *
>>> quit
Exiting Sage (CPU time 0m0.00s, Wall time 0m0.89s)
Unter „wall time“ finden Sie die vergangene Echtzeit (der Uhr an Ihrer Wand). Diese ist nötig, da die CPU Zeit Unterprozesse wie GAP oder Singular nicht berücksichtigt.
(Vermeiden Sie es den Sage Prozess mit kill -9
in der Konsole zu
beenden, da so möglicherweise Unterprozesse wie z.B. Maple-Prozesse
nicht beendet oder temporäre Dateien in $HOME/.sage/tmp
nicht
gelöscht würden.)
Ihre Sage Sitzung¶
Unter einer Sitzung verstehen wir die Ein- und Ausgaben von Sage vom
Starten bis zum Beenden. Sage speichert alle Eingaben mittels IPython. Wenn
Sie die interaktive Kommandozeile nutzen (im Gegensatz zur
Browser-Oberfläche „Notebook“), so können Sie jederzeit mittels
%hist
eine Liste aller bisher getätigten Eingaben sehen. Sie
können auch ?
eingeben, um mehr über IPython zu
erfahren. Z.B. „IPython unterstützt Zeilennummerierung … sowie Ein-
und Ausgabezwischenspeicherung. Alle Eingaben werden gespeichert und
können in Variablen abgerufen werden (neben der normalen
Pfeiltasten-Navigation). Die folgenden globalen Variablen existieren
immer (also bitte überschreiben Sie sie nicht!)“:
_: letzte Eingabe (interaktive Kommandozeile und Browser-Oberfläche)
__: vorletzte Eingabe (nur in der Kommandozeile)
_oh: Liste aller Eingaben (nur in der Kommandozeile)
Hier ein Beispiel:
sage: factor(100)
_1 = 2^2 * 5^2
sage: kronecker_symbol(3,5)
_2 = -1
sage: %hist # funktioniert nur in der Kommandozeile, nicht im Browser.
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
>>> from sage.all import *
>>> factor(Integer(100))
_1 = 2^2 * 5^2
>>> kronecker_symbol(Integer(3),Integer(5))
_2 = -1
>>> %hist # funktioniert nur in der Kommandozeile, nicht im Browser.
1: factor(100)
2: kronecker_symbol(3,5)
3: %hist
>>> _oh
_4 = {1: 2^2 * 5^2, 2: -1}
>>> _i1
_5 = 'factor(ZZ(100))\n'
>>> eval(_i1)
_6 = 2^2 * 5^2
>>> %hist
1: factor(100)
2: kronecker_symbol(3,5)
3: %hist
4: _oh
5: _i1
6: eval(_i1)
7: %hist
Wir lassen die Zeilennummerierung im restlichen Tutorial sowie in der weiteren Sage-Dokumentation weg. Sie können auch eine Liste von Eingaben einer Sitzung in einem Makro für diese Sitzung speichern.
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).
>>> from sage.all import *
>>> E = EllipticCurve([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)])
>>> M = ModularSymbols(Integer(37))
>>> %hist
1: E = EllipticCurve([1,2,3,4,5])
2: M = ModularSymbols(37)
3: %hist
>>> %macro em Integer(1)-Integer(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
>>> from sage.all import *
>>> E
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over
Rational Field
>>> E = Integer(5)
>>> M = None
>>> em
Executing Macro...
>>> E
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over
Rational Field
Während Sie die interaktive Kommandozeile nutzen, können Sie jeden
UNIX-Kommandozeilenbefehl in Sage ausführen, indem Sie ihm ein
Ausrufezeichen !
voranstellen. Zum Beispiel gibt
sage: !ls
auto example.sage glossary.tex t tmp tut.log tut.tex
>>> from sage.all import *
>>> !ls
auto example.sage glossary.tex t tmp tut.log tut.tex
den Inhalt des aktuellen Verzeichnisses aus.
In der PATH
-Variablen steht das Sage „bin“ Verzeichnis vorne. Wenn
Sie also gp
, gap
, singular
, maxima
, usw. eingeben,
starten Sie die in Sage enthaltenden Versionen.
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-1-0
0<
by: G.-M. Greuel, G. Pfister, H. Schoenemann \ Mar 2009
FB Mathematik der Universitaet, D-67653 Kaiserslautern \
>>> from sage.all import *
>>> !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
...
>>> !singular
SINGULAR / Development
A Computer Algebra System for Polynomial Computations / version 3-1-0
0<
by: G.-M. Greuel, G. Pfister, H. Schoenemann \ Mar 2009
FB Mathematik der Universitaet, D-67653 Kaiserslautern \
Ein- und Ausgaben loggen¶
Die Sage Sitzung loggen bzw. speichern ist nicht das Gleiche (siehe
Speichern und Laden kompletter Sitzungen). Um Eingaben (und optional auch Ausgaben) zu
loggen nutzen Sie den Befehl logstart
. Geben Sie logstart?
ein
um weitere Informationen zu erhalten. Sie können diesen Befehl nutzen
um alle Eingaben und Ausgaben zu loggen, und diese sogar wiederholen
in einer zukünftigen Sitzung (indem Sie einfach die Log-Datei laden).
was@form:~$ sage
┌────────────────────────────────────────────────────────────────────┐
│ SageMath version 9.7, Release Date: 2022-01-10 │
│ Using Python 3.10.4. Type "help()" for 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
┌────────────────────────────────────────────────────────────────────┐
│ SageMath version 9.7, Release Date: 2022-01-10 │
│ Using Python 3.10.4. Type "help()" for 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)]
Wenn Sie Sage in der Linux KDE Konsole konsole
verwenden, können
Sie Ihre Sitzung wie folgt speichern: Nachdem Sie Sage in konsole
gestartet haben, wählen Sie „Einstellungen“, dann „Verlauf…“, dann
„auf unbegrenzt“ setzen. Wenn Sie soweit sind Ihre Sitzung zu
speichern, wählen Sie „Bearbeiten“ und dann „Verlauf speichern
unter…“ und geben einen Namen ein, um den Text ihrer Sitzung
auf dem Computer zu speichern. Nach dem Speichern der Datei können Sie
jene in einem Editor wie GNU Emacs öffnen und ausdrucken.
Einfügen ignoriert Eingabeaufforderungen¶
Stellen Sie sich vor, Sie lesen eine Sitzung von Sage oder Python
Berechnungen und wollen sie in Sage kopieren, aber überall sind noch
die störenden >>>
oder sage:
Eingabeaufforderungen. Tatsächlich können Sie einfach die gewünschte
Stelle mit Eingabeaufforderungen in Sage einfügen. Der Sage Parser
wird standardmäßig die führenden >>>
oder sage:
Eingabeaufforderungen entfernen bevor er es an Python weitergibt. Zum
Beispiel:
sage: 2^10
1024
sage: sage: sage: 2^10
1024
sage: >>> 2^10
1024
>>> from sage.all import *
>>> Integer(2)**Integer(10)
1024
>>> sage: sage: Integer(2)**Integer(10)
1024
>>> >>> Integer(2)**Integer(10)
1024
Befehle zur Zeitmessung¶
Wenn Sie den %time
Befehl vor eine Eingabe schreiben wird die
Zeit, die der Aufruf benötigt, ausgegeben nachdem er gelaufen ist.
Zum Beispiel können wir die Laufzeit einer bestimmten Potenzierung auf
verschiedene Arten vergleichen. Die unten genannte Laufzeit wird unter
Umständen weit von der Laufzeit auf Ihrem Computer oder sogar zwischen
verschiedenen SageMath Versionen abweichen. Zuerst natives 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
>>> from sage.all import *
>>> %time a = int(Integer(1938))**int(Integer(99484))
CPU times: user 0.66 s, sys: 0.00 s, total: 0.66 s
Wall time: 0.66
Das bedeutet insgesamt 0,66 Sekunden wurden benötigt und die vergangene „Wall time“, also die vergangene Echtzeit (auf Ihrer Wanduhr), betrug auch 0,66 Sekunden. Wenn auf Ihrem Computer viele andere Programme gleichzeitig laufen kann die „Wall time“ wesentlich größer als die CPU Zeit sein.
Als nächstes messen wir die Laufzeit der Potenzierung unter Verwendung des nativen Sage Ganzzahl-Typs, der (in Cython implementiert ist und) die GMP Bibliothek nutzt:
sage: %time a = 1938^99484
CPU times: user 0.04 s, sys: 0.00 s, total: 0.04 s
Wall time: 0.04
>>> from sage.all import *
>>> %time a = Integer(1938)**Integer(99484)
CPU times: user 0.04 s, sys: 0.00 s, total: 0.04 s
Wall time: 0.04
Unter Verwendung der PARI C-Bibliothek:
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
>>> from sage.all import *
>>> %time a = pari(Integer(1938))**pari(Integer(99484))
CPU times: user 0.05 s, sys: 0.00 s, total: 0.05 s
Wall time: 0.05
GMP ist also ein bisschen besser (wie erwartet, da die für Sage
verwendete PARI Version GMP für Ganzzahlarithmetik nutzt).
Sie können ebenso Befehlsblöcke messen, indem Sie cputime
wie
unten verwenden:
sage: t = cputime()
sage: a = int(1938)^int(99484)
sage: b = 1938^99484
sage: c = pari(1938)^pari(99484)
sage: cputime(t) # random output
0.64
>>> from sage.all import *
>>> t = cputime()
>>> a = int(Integer(1938))**int(Integer(99484))
>>> b = Integer(1938)**Integer(99484)
>>> c = pari(Integer(1938))**pari(Integer(99484))
>>> cputime(t) # 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
>>> from sage.all import *
>>> 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
Der walltime
Befehl entspricht cputime
, nur misst dieser die Echtzeit.
Wir können die oben genannte Potenz auch in einigen der Computer Algebra Systeme, die Sage mitbringt berechnen. In jedem Fall führen wir einen trivialen Befehl aus, um den entsprechenden Server dieses Programms zu starten. Sollte es erhebliche Unterschiede zwischen Echtzeit und CPU-Zeit geben, deutet dies auf ein Leistungsproblem hin, dem man nachgehen sollte.
sage: time 1938^99484;
CPU times: user 0.01 s, sys: 0.00 s, total: 0.01 s
Wall time: 0.01
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.04
sage: maxima(0)
0
sage: time g = maxima('1938^99484')
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 0.30
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.04
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.03
sage: maple(0)
0
sage: time g = maple('1938^99484')
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 0.11
sage: libgap(0)
0
sage: time g = libgap.eval('1938^99484;')
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 1.02
>>> from sage.all import *
>>> time Integer(1938)**Integer(99484);
CPU times: user 0.01 s, sys: 0.00 s, total: 0.01 s
Wall time: 0.01
>>> gp(Integer(0))
0
>>> time g = gp('1938^99484')
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 0.04
>>> maxima(Integer(0))
0
>>> time g = maxima('1938^99484')
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 0.30
>>> kash(Integer(0))
0
>>> time g = kash('1938^99484')
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 0.04
>>> mathematica(Integer(0))
0
>>> time g = mathematica('1938^99484')
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 0.03
>>> maple(Integer(0))
0
>>> time g = maple('1938^99484')
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 0.11
>>> libgap(Integer(0))
0
>>> time g = libgap.eval('1938^99484;')
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 1.02
Achten Sie darauf, dass GAP und Maxima am langsamsten in diesem Test
sind (er lief auf dem Computer sage.math.washington.edu
). Aufgrund
des Pexpect-Schnittstellen-Overheads ist es aber vielleicht unfair
diese mit Sage zu vergleichen, welches am schnellsten war.
Fehlerbehandlung¶
Wenn irgendetwas schief geht, werden Sie normalerweise eine
Python-Fehlermeldung sehen. Python macht sogar einen Vorschlag, was den
Fehler ausgelöst hat. Oft sehen Sie den Namen der Fehlermeldung,
z.B. NameError
oder ValueError
(vgl. Python Library Reference
[PyLR] für eine komplette Liste der Fehlermeldungen). Zum Beispiel:
sage: 3_2
------------------------------------------------------------
File "<console>", line 1
ZZ(3)_2
^
SyntaxError: invalid ...
sage: EllipticCurve([0,infinity])
------------------------------------------------------------
Traceback (most recent call last):
...
TypeError: Unable to coerce Infinity (<class 'sage...Infinity'>) to Rational
>>> from sage.all import *
>>> Integer(3_2)
------------------------------------------------------------
File "<console>", line 1
ZZ(3)_2
^
SyntaxError: invalid ...
>>> EllipticCurve([Integer(0),infinity])
------------------------------------------------------------
Traceback (most recent call last):
...
TypeError: Unable to coerce Infinity (<class 'sage...Infinity'>) to Rational
Der interaktive Debugger ist manchmal hilfreich um zu verstehen was
schiefgelaufen ist. Sie können ihn ein- oder ausschalten indem Sie
%pdb
eingeben (standardmäßig ist er ausgeschaltet). Die
Eingabeaufforderung ipdb>
erscheint wenn eine Fehlermeldung
geworfen wird und der Debugger eingeschaltet ist. Im Debugger können
Sie den Status jeder lokalen Variable ausgeben oder im Ausführungstack
hoch- und runterspringen.
Zum Beispiel:
sage: %pdb
Automatic pdb calling has been turned ON
sage: EllipticCurve([1,infinity])
---------------------------------------------------------------------------
<class 'exceptions.TypeError'> Traceback (most recent call last)
...
ipdb>
>>> from sage.all import *
>>> %pdb
Automatic pdb calling has been turned ON
>>> EllipticCurve([Integer(1),infinity])
---------------------------------------------------------------------------
<class 'exceptions.TypeError'> Traceback (most recent call last)
...
ipdb>
Tippen Sie ?
in der ipdb>
-Eingabeaufforderung um eine Liste
der Befehle des Debuggers zu erhalten.
ipdb> ?
Documented commands (type help <topic>):
========================================
EOF break commands debug h l pdef quit tbreak
a bt condition disable help list pdoc r u
alias c cont down ignore n pinfo return unalias
args cl continue enable j next pp s up
b clear d exit jump p q step w
whatis where
Miscellaneous help topics:
==========================
exec pdb
Undocumented commands:
======================
retval rv
Drücken Sie Strg-D oder geben Sie quit
ein um zu Sage zurückzukehren.
Rückwärtssuche und Tab-Vervollständigung¶
Definieren Sie zuerst einen dreidimensionalen Vektorraum \(V=\QQ^3\) wie folgt:
sage: V = VectorSpace(QQ,3)
sage: V
Vector space of dimension 3 over Rational Field
>>> from sage.all import *
>>> V = VectorSpace(QQ,Integer(3))
>>> V
Vector space of dimension 3 over Rational Field
Sie können auch die folgende verkürzte Schreibweise verwenden:
sage: V = QQ^3
>>> from sage.all import *
>>> V = QQ**Integer(3)
Schreiben Sie den Anfang eines Befehls und drücken Sie dann Strg-p
(oder drücken Sie einfach die Pfeil-nach-oben-Taste) um zur vorher
eingegebenen Zeile zu gelangen, die ebenfalls so beginnt. Das
funktioniert auch nach einem kompletten Sage-Neustart noch. Sie können
den Verlauf auch mit Strg-r
rückwärts durchsuchen. Diese
Funktionalität wird vom readline
-Paket bereitgestellt, welches in
nahezu jeder Linux-Distribution verfügbar ist.
Es ist sehr einfach alle Unterfunktionen für \(V\) mittels
Tab-Vervollständigung aufzulisten, indem Sie erst V.
eingeben,
und dann die [Tabulator Taste]
drücken:
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
>>> from sage.all import *
>>> V.[tab key]
V._VectorSpace_generic__base_field
...
V.ambient_space
V.base_field
V.base_ring
V.basis
V.coordinates
...
V.zero_vector
Wenn Sie die ersten paar Buchstaben einer Funktion tippen und dann die
[Tabulator Taste]
drücken, bekommen Sie nur die Funktionen, die so
beginnen angezeigt.
sage: V.i[tab key]
V.is_ambient V.is_dense V.is_full V.is_sparse
>>> from sage.all import *
>>> V.i[tab key]
V.is_ambient V.is_dense V.is_full V.is_sparse
Wenn sie wissen wollen, was eine bestimmte Funktion tut, z.B. die
„coordinates“-Funktion, so geben Sie V.coordinates?
ein um die
Hilfe, und V.coordinates??
um den Quelltext der Funktion zu
sehen.
Integriertes Hilfesystem¶
Sage hat ein integriertes Hilfesystem. Hängen Sie an einen beliebigen
Funktionsnamen ein ?
an, um die Dokumentation dazu aufzurufen.
sage: V = QQ^3
sage: V.coordinates?
Type: instancemethod
Base Class: <class '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/f
ree_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]
>>> from sage.all import *
>>> V = QQ**Integer(3)
>>> V.coordinates?
Type: instancemethod
Base Class: <class '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/f
ree_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:
>>> M = FreeModule(IntegerRing(), Integer(2)); M0,M1=M.gens()
>>> W = M.submodule([M0 + M1, M0 - Integer(2)*M1])
>>> W.coordinates(Integer(2)*M0-M1)
[2, -1]
Wie Sie sehen, beinhaltet die Ausgabe den Typ des Objekts, den Dateinamen in welcher die Funktion definiert ist und eine Beschreibung der Funktionalität mit Beispielen, die Sie direkt in Ihre aktuelle Sitzung einfügen können. Fast alle dieser Beispiele werden regelmäßig automatisch getestet um sicherzustellen, dass sie genau wie beschrieben funktionieren.
Eine andere Funktionalität, die sehr eng in Verbindung mit Open-Source-Gedanken steht ist,
dass Sie sich zu jeder Funktion den Quelltext anzeigen lassen
können. Sei f
eine Sage oder Python Funktion, dann können Sie mit
f??
den Quellcode, der f
definiert anzeigen. Zum Beispiel:
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()
>>> from sage.all import *
>>> V = QQ**Integer(3)
>>> V.coordinates??
Type: instancemethod
...
Source:
def coordinates(self, v):
"""
Write $v$ in terms of the basis for self.
...
"""
return self.coordinate_vector(v).list()
Das zeigt uns, dass die coordinates
-Funktion nichts anderes tut,
als coordinates_vector
-Funktion aufruft und das Ergebnis in eine
Liste umwandelt. Aber was tut die coordinates
-Funktion?
sage: V = QQ^3
sage: V.coordinate_vector??
...
def coordinate_vector(self, v):
...
return self.ambient_vector_space()(v)
>>> from sage.all import *
>>> V = QQ**Integer(3)
>>> V.coordinate_vector??
...
def coordinate_vector(self, v):
...
return self.ambient_vector_space()(v)
Die coordinate_vector
-Funktion steckt ihre Eingabe in den
umgebenden Raum, was zur Folge hat, dass der Koeffizientenvektor von
\(v\) zur Basis des Vektorraums \(V\) ausgerechnet wird.
Der Raum \(V\) ist schon der umgebende, nämlich gerade
\(\QQ^3\). Es gibt auch eine coordinate_vector
-Funktion für
Unterräume, und sie funktioniert anders.
Wir definieren einen Unterraum und schauen uns das an:
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)
>>> from sage.all import *
>>> V = QQ**Integer(3); W = V.span_of_basis([V.gen(0), V.gen(1)])
>>> 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)
(Wenn Sie der Meinung sind, dass diese Implementation ineffizient ist, helfen Sie uns bitte unsere Lineare Algebra zu optimieren.)
Sie können auch help(command_name)
oder help(class)
eingeben
um eine manpage-artige Hilfe zu bekommen.
sage: help(VectorSpace)
Help on function VectorSpace in module sage.modules.free_module:
VectorSpace(K, dimension_or_basis_keys=None, sparse=False, inner_product_matrix=None, *,
with_basis='standard', dimension=None, basis_keys=None, **args)
EXAMPLES:
The base can be complicated, as long as it is a field.
::
sage: V = VectorSpace(FractionField(PolynomialRing(ZZ,'x')),3)
sage: V
Vector space of dimension 3 over Fraction Field of Univariate Polynomial Ring in x
over Integer Ring
sage: V.basis()
[
(1, 0, 0),
(0, 1, 0),
--More--
>>> from sage.all import *
>>> help(VectorSpace)
Help on function VectorSpace in module sage.modules.free_module:
VectorSpace(K, dimension_or_basis_keys=None, sparse=False, inner_product_matrix=None, *,
with_basis='standard', dimension=None, basis_keys=None, **args)
EXAMPLES:
The base can be complicated, as long as it is a field.
::
>>> V = VectorSpace(FractionField(PolynomialRing(ZZ,'x')),Integer(3))
>>> V
Vector space of dimension 3 over Fraction Field of Univariate Polynomial Ring in x
over Integer Ring
>>> V.basis()
[
(1, 0, 0),
(0, 1, 0),
--More--
Wenn Sie q
drücken um das Hilfesystem zu verlassen, kommen Sie genau
dahin zurück, wo Sie Ihre Sitzung verlassen haben. Die help
Anzeige
bleibt nicht in Ihrer Sitzung zurück im Gegensatz zu funktion?
.
Es ist besonders hilfreich help(modul_name)
zu nutzen. Zum Beispiel sind
Vektorräume in sage.modules.free_module
definiert. Geben Sie also
help(sage.modules.free_module)
ein, um die Dokumentation des
ganzen Moduls zu sehen. Wenn Sie sich Die Dokumentation mit help
ansehen, können Sie mit /
vorwärts und mit ?
rückwärts suchen.
Speichern und Laden von individuellen Objekten¶
Angenommen Sie berechnen eine Matrix oder schlimmer, einen komplizierten Modulsymbolraum, und Sie wollen ihn für später speichern. Was können Sie tun? Es gibt mehrere Möglichkeiten für Computer Algebra Systeme solche individuellen Objekte zu speichern.
speichern Ihres Spiels: Unterstützt nur das Speichern und Laden kompletter Sitzungen (z.B. GAP, Magma).
- Einheitliche Ein-/Ausgabe: Bringen Sie jedes Objekt in eine Form, die
Sie wieder einlesen können in (GP/PARI).
Eval: Machen Sie beliebigen Code auswertbar im Interpreter (z.B. Sigular, PARI).
Da Sage Python nutzt, braucht es einen anderen Ansatz, nämlich dass jedes Objekt serialisiert werden kann. Das heißt es in eine Zeichenkette umzuwandeln, die man wieder einlesen kann. Das ist im Prinzip ähnlich zum einheitlichen Ein-/Ausgabe Ansatz von PARI, abgesehen von der zu komplizierten Darstellung auf dem Bildschirm. Außerdem ist das Laden und Speichern (meistens) vollautomatisch und benötigt nicht einmal speziellen Programmieraufwand; es ist einfach ein Merkmal, das von Grund auf in Python war.
Fast alle Objekte x in Sage können in komprimierter Form gespeichert werden
via save(x, Dateiname)
(oder in vielen Fällen x.save(Dateiname)
).
Um das Objekt wieder zu laden, nutzen Sie load(Dateiname)
.
sage: A = MatrixSpace(QQ,3)(range(9))^2
sage: A
[ 15 18 21]
[ 42 54 66]
[ 69 90 111]
sage: save(A, 'A')
>>> from sage.all import *
>>> A = MatrixSpace(QQ,Integer(3))(range(Integer(9)))**Integer(2)
>>> A
[ 15 18 21]
[ 42 54 66]
[ 69 90 111]
>>> save(A, 'A')
Sie sollten Sage nun schließen und neu starten. Dann können Sie A
wieder laden:
sage: A = load('A')
sage: A
[ 15 18 21]
[ 42 54 66]
[ 69 90 111]
>>> from sage.all import *
>>> A = load('A')
>>> A
[ 15 18 21]
[ 42 54 66]
[ 69 90 111]
Sie können das selbe mit komplizierteren Objekten, wie etwa elliptischen Kurven machen. Alle Daten über das Objekt sind zwischengespeichert und werden mit dem Objekt gespeichert. Zum Beispiel:
sage: E = EllipticCurve('11a')
sage: v = E.anlist(100000) # dauert etwas länger
sage: save(E, 'E')
sage: quit
>>> from sage.all import *
>>> E = EllipticCurve('11a')
>>> v = E.anlist(Integer(100000)) # dauert etwas länger
>>> save(E, 'E')
>>> quit
Die gespeicherte Version von E
braucht 153 Kilobyte, da die ersten
100000 \(a_n\) mitgespeichert werden.
~/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) # sofort!
(In Python wird das Laden und Speichern mittels des cPickle
Moduls umgesetzt. Genauer: Ein Sage Objekt x
kann mit
cPickle.dumps(x, 2)
gespeichert werden. Beachten Sie die 2
!)
Sage kann allerdings keine individuellen Objekte anderer Computer Algebra Systeme wie GAP, Singular, Maxima, usw. laden und speichern. Sie sind mit „invalid“ gekennzeichnet nach dem Laden. In GAP werden viele Objekte in einer Form dargestellt, die man wiederherstellen kann, viele andere allerdings nicht. Deshalb ist das Wiederherstellen aus ihren Druckdarstellungen nicht erlaubt.
sage: a = libgap(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.
>>> from sage.all import *
>>> a = libgap(Integer(2))
>>> a.save('a')
>>> load('a')
Traceback (most recent call last):
...
ValueError: The session in which this object was defined is no longer
running.
GP/PARI Objekte können hingegen gespeichert und geladen werden, da ihre Druckdarstellung ausreicht um sie wiederherzustellen.
sage: a = gp(2)
sage: a.save('a')
sage: load('a')
2
>>> from sage.all import *
>>> a = gp(Integer(2))
>>> a.save('a')
>>> load('a')
2
Gespeicherte Objekte können auch auf Computern mit anderen Architekturen
oder Betriebssystemen wieder geladen werden. Zum Beispiel können Sie
eine riesige Matrix auf einem 32 Bit Mac OS X speichern und später auf
einem 64 Bit Linux System laden, dort die Stufenform herstellen und dann
wieder zurückladen. Außerdem können Sie in den meisten Fällen auch Objekte
laden, die mit anderen SageMath Versionen gespeichert wurden, solange der Quelltext
des Objekts nicht zu verschieden ist. Alle Attribute eines Objekts werden zusammen
mit seiner Klasse (aber nicht dem Quellcode) gespeichert. Sollte diese Klasse
in einer neueren SageMath Version nicht mehr existieren, kann das Objekt in dieser
neueren SageMath Version nicht mehr geladen werden. Aber Sie könnten es in der alten
SageMath Version laden, die Objekt Dictionaries mit x.__dict__
laden und das Objekt
zusammen mit diesem in der neuen SageMath Version laden.
Als Text speichern¶
Sie können die ASCII Text Darstellung eines Objekts in eine Klartextdatei schreiben, indem Sie die Datei einfach mit Schreibzugriff öffnen und die Textdarstellung des Objekts hineinkopieren. (Sie können auch viele andere Objekte auf diese Art speichern.) Wenn Sie alle Objekte hineinkopiert haben, schließen Sie die Datei einfach.
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()
>>> from sage.all import *
>>> R = PolynomialRing(QQ,Integer(2), names=('x', 'y',)); (x, y,) = R._first_ngens(2)
>>> f = (x+y)**Integer(7)
>>> o = open('file.txt','w')
>>> o.write(str(f))
>>> o.close()
Speichern und Laden kompletter Sitzungen¶
Sage hat eine sehr flexible Unterstützung für das Speichern und Laden kompletter Sitzungen.
Der Befehl save_session(sitzungsname)
speichert alle Variablen,
die Sie während dieser Sitzung definiert haben als ein Dictionary
sessionname
. (Im seltenen Fall, dass eine Variable nicht gespeichert
werden kann, fehlt sie anschließend einfach im Dictionary.)
Die erzeugte Datei ist eine .sobj
-Datei und kann genau wie jedes andere
Objekt geladen werden. Wenn Sie Objekte aus einer Sitzung laden, werden Sie
diese in einem Dictionary finden. Dessen Schlüssel sind die Variablen und
dessen Werte sind die Objekte.
Sie können den load_session(sitzungsname)
Befehl nutzen um die Variablen
aus sitzungsname
in die aktuelle Sitzung zu laden. Beachten Sie, dass
dieses Vorgehen nicht die Variablen der aktuellen Sitzung löscht, vielmehr
werden beide Sitzungen vereinigt.
Starten wir also zunächst Sage und definieren einige Variablen.
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
>>> from sage.all import *
>>> E = EllipticCurve('11a')
>>> M = ModularSymbols(Integer(37))
>>> a = Integer(389)
>>> t = M.T(Integer(2003)).matrix(); t.charpoly().factor()
_4 = (x - 2004) * (x - 12)^2 * (x + 54)^2
Als nächstes speichern wir unsere Sitzung, was jede der Variablen in eine Datei speichert. Dann sehen wir uns die Datei, die etwa 3 Kilobyte groß ist an.
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
>>> from sage.all import *
>>> save_session('misc')
Saving a
Saving M
Saving t
Saving E
>>> quit
was@form:~/tmp$ ls -l misc.sobj
-rw-r--r-- 1 was was 2979 2006-01-28 19:47 misc.sobj
Zuletzt starten wir Sage neu, definieren uns eine extra Variable, und laden unsere gespeicherte Sitzung.
sage: b = 19
sage: load_session('misc')
Loading a
Loading M
Loading E
Loading t
>>> from sage.all import *
>>> b = Integer(19)
>>> load_session('misc')
Loading a
Loading M
Loading E
Loading t
Jede der gespeicherten Variablen ist wieder verfügbar und die
Variable b
wurde nicht überschrieben.
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
>>> from sage.all import *
>>> M
Full Modular Symbols space for Gamma_0(37) of weight 2 with sign 0
and dimension 5 over Rational Field
>>> E
Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational
Field
>>> b
19
>>> a
389