交互式 Shell¶
在本教程的大部分内容中,我们假定你使用 sage 命令启动 Sage 解释器。
这将启动一个定制版的 IPython Shell,并导入许多函数和类,使它们可以直接从命令提示符使用。
可以通过编辑 $SAGE_ROOT/ipythonrc 文件进行进一步的自定义。
启动 Sage 后,会输出以下类似内容:
┌────────────────────────────────────────────────────────────────────┐
│ SageMath version 9.7, Release Date: 2022-01-10 │
│ Using Python 3.10.4. Type "help()" for help. │
└────────────────────────────────────────────────────────────────────┘
sage:
要退出 Sage 只需按 Ctrl-D 或输入 quit 或 exit。
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)
Wall time 指的是墙上的挂钟走过的时间。因为 CPU 时间不会跟踪子进程(如 GAP 或 Singular)消耗的时间。
(请避免在终端中使用 kill -9 杀死 Sage 进程,
因为 Sage 可能无法终止子进程,例如 Maple 进程,或清理 $HOME/.sage/tmp 中的临时文件。)
Sage 会话¶
会话是从 Sage 启动到退出期间的输入输出序列。Sage 通过IPython 记录所有 Sage 输入。
实际上,如果你使用的是交互式 Shell(而不是 notebook 界面),
你可以随时输入 %history (或 %hist)来列出迄今为止输入的所有命令行。
在 Sage 提示符下输入 ? 可以了解有关 IPython 的更多信息,例如,
“IPython 提供带编号的提示符...并缓存输入和输出。所有输入都会保存,
并且可以作为变量检索(除了常用的箭头键召回外)。以下全局变量始终存在(所以不要覆盖它们!)”:
_: 上一次输入 (交互式 SHell 和 notebook 均适用)
__: 上两次输入 (仅交互式 Shell 适用)
_oh : 所有输入的列表 (仅交互式 Shell 适用)
例如:
sage: factor(100)
_1 = 2^2 * 5^2
sage: kronecker_symbol(3,5)
_2 = -1
sage: %hist # This only works from the interactive shell, not the notebook.
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 # This only works from the interactive shell, not the notebook.
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
我们在本教程和其他 Sage 文档中均省略了输出编号。
你还可以在会话中将输入列表储存在宏中。
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
在使用交互式 Shell 时,任何 UNIX Shell 命令都可以通过在 Sage 前面加上感叹号 ! 来执行。例如:
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
返回当前目录的列表。
PATH 变量将 Sage 的 bin 目录放在最前端,
因此如果运行 gp, gap, singular, maxima 等等,你会得到随 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 \
>>> 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-0-1
0<
by: G.-M. Greuel, G. Pfister, H. Schoenemann \ October 2005
FB Mathematik der Universitaet, D-67653 Kaiserslautern \
记录输入和输出¶
记录 Sage 会话不同于保存会话(参见 保存和加载完整会话)。
要记录输入(和可选输出),请使用 logstart 命令。输入 logstart? 了解更多详情。
你可以使用这个命令记录你输入的所有内容、所有输出,甚至可以在未来的会话中重现输入(通过重新加载日志文件)。
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)]
如果你在 Linux KDE 终端 konsole 中使用 Sage,那么可以按照以下步骤保存会话:
在 konsole 中启动 Sage 后,选择“设置”,然后“历史记录...”,然后“设置为无限制”。
当你准备保存会话时,选择“编辑”,然后“保存历史记录为...”,并输入一个名称将会话的文本保存到你的计算机。
保存这个文件后,你可以将其加载到编辑器(例如 xemacs)并打印出来。
粘贴忽略提示符¶
假设你正在阅读 Sage 或 Python 计算的会话,并希望将它们复制到 Sage 中。
但是有 >>> 或 sage: 提示符很烦人。实际上,你可以将包含提示符的示例复制并粘贴到 Sage 中。
换句话说,默认情况下,Sage 解析器在传递给 Python 之前会删除任何前导 >>> 或 sage: 提示符。例如:
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
命令计时¶
如果你在输入的开头放置 %time 命令,那么命令执行的时间将显示在输出后。
例如,我们可以比较几种幂运算的运行时间。
这些计时在你电脑上可能会有很大不同,甚至在不同版本的 Sage 之间也会有所不同。
首先是原生 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
这意味着总共耗时 0.66 秒,"Wall time" 即墙上挂钟的时间为 0.66 秒。 如果你的计算机负载较重,wall time 可能比 CPU 时间长很多。
还可以使用 timeit 函数来尝试在大量迭代命令下获取时间。
这提供了稍微不同的信息,并且需要输入命令字符串来计时。
sage: timeit("int(1938)^int(99484)")
5 loops, best of 3: 44.8 ms per loop
>>> from sage.all import *
>>> timeit("int(1938)^int(99484)")
5 loops, best of 3: 44.8 ms per loop
接下来我们使用原生 Sage Integer 类型,它是用 Cython 调用 GMP 库实现的:
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
使用 PARI 的 C 语言接口:
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 表现稍好(预料之中,因为为 Sage 构建的 PARI 版本使用 GMP 进行整数运算)。
还可以使用 cputime 命令计时一组命令块,如下所示:
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
>>> 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) # 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
>>> 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
walltime 命令的行为与 cputime 命令类似,只是它计算的是挂钟时间。
我们也可以用 Sage 包含的计算机代数系统计算上面的幂。以下每种情况下,我们执行一个简单命令以启动该程序的服务器。 最相关的时间是挂钟时间。然而,如果挂钟时间和 CPU 时间之间存在显著差异,则可能表明存在值得优化的性能问题。
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
注意,在这项测试中 GAP 和 Maxima 最慢(运行在 sage.math.washington.edu 机器上)。
由于 pexpect 接口的开销,将它们与最快的 Sage 相比可能不太公平。
其他 IPython 技巧¶
如上文所述,Sage 使用 IPython 作为前端,因此你可以使用任何 IPython 的命令和功能。 你可以阅读 完整的 IPython 文档 。 下面是一些有趣的技巧 -- 在 IPython 中,这些被称为 "Magic 命令":
如果你想输入一些复杂代码,可以使用
%edit(或%ed或ed)打开一个编辑器。 在启动 Sage 之前,请确保EDITOR环境变量设置为你喜欢的编辑器 (通过在适当位置如.profile文件中放置export EDITOR=/usr/bin/emacs或export EDITOR=/usr/bin/vim等)。在 Sage 提示符下执行%edit会打开指定的编辑器。 然后在编辑器中你可以定义一个函数:def some_function(n): return n**2 + 3*n + 2
保存并退出编辑器。在剩下的 Sage 会话期间,你可以使用
some_function。 如果你想修改它,可以在 Sage 提示符下输入%edit some_function。如果你有一个计算,并且想修改其输出以便用于其他用途,可执行计算并输入
%rep: 这会将上一个命令的输出放置到 Sage 提示符,供你编辑。:sage: f(x) = cos(x) sage: f(x).derivative(x) -sin(x)
>>> from sage.all import * >>> __tmp__=var("x"); f = symbolic_expression(cos(x)).function(x) >>> f(x).derivative(x) -sin(x)
此时如果你在 Sage 提示符下输入
%rep, 你会得到一个新的 Sage 提示符,后面跟着-sin(x), 光标在行尾。
要了解更多信息,请输入 %quickref 以获得 IPython 快速参考指南。
截止本文撰写时间(2011 年 4 月),Sage 使用的 IPython 版本为 0.9.1,
Magic 命令文档
可以在线访问。各种较为高级的 Magic 命令系统的内容记载在
这里 。
错误与异常¶
出现问题时,通常会看到 Python “异常”。Python 甚至会尝试给出引发异常的原因。
通常可以看到异常的名称,例如:NameError 或 ValueError
(详细异常列表请参见 Python 库参考 [PyLR] )。例如:
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
有时交互式调试器对理解问题很有用。可以使用 %pdb 切换它(默认是关闭的)。
如果打开调试器,出现异常时会出现提示符 ipdb>。在调试器中,可以打印任意局部变量的状态,
并在执行栈中上下移动。例如:
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>
在 ipdb> 提示符下输入 ? 以获取调试器命令列表:
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
输入 Ctrl-D 或 quit 返回 Sage。
反向搜索与 Tab 补全¶
反向搜索:
输入命令的开头,然后按 Ctrl-p (或直接按上箭头键)查看以前输入的以该命令开头的命令行。
即使你完全退出 Sage 并稍后重新启动,这些功能仍然可以使用。也可以使用 Ctrl-r 通过历史记录进行反向搜索。
所有这些功能均使用 readline 软件包,可在大多数 Linux 版本中使用。
为了演示 Tab 补全,首先创建三维向量空间 \(V=\QQ^3\) 如下:
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
也可以使用如下更简洁的表示法:
sage: V = QQ^3
>>> from sage.all import *
>>> V = QQ**Integer(3)
然后可以很容易地使用 Tab 补全列出 \(V\) 的所有成员函数。只需输入 V., 然后按键盘上的 Tab 键:
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
如果输入函数的前几个字母,然后按 Tab 键,只会显示以这些字母开头的函数。
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
如果想知道某函数的作用,例如 coordinates 函数,
输入 V.coordinates? 来获取帮助或 V.coordinates?? 查看源码,如下一节所述。
集成帮助系统¶
Sage 拥有集成帮助系统。输入函数名后跟 ? 可以查看该函数的文档。
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]
如上所示,输出告诉你对象的类型,定义它的文件,以及有用的函数描述及示例, 可以将这些示例粘贴到当前会话中。几乎所有这些示例都会定期自动测试,以确保它们正常工作并完全按照描述运行。
另一个非常符合 Sage 开源精神的功能是,如果 f 是一个 Python 函数,
那么输入 f?? 会显示定义 f 的源代码。例如:
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()
这告诉我们 coordinates 函数所做的就是调用 coordinate_vector 函数并将结果转换为列表。
coordinate_vector 函数做什么?
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)
coordinate_vector 函数将其输入强制转化环绕空间,
其效果是以 \(V\) 的形式计算 \(v\) 的系数向量。
空间 \(V\) 已经是环绕空间,因为它就是 \(\QQ^3\)。
子空间也有 coordinate_vector 函数,它是不同的。我们创建一个子空间并看到:
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)
(如果你认为实现效率低下,请注册以帮助优化线性代数。)
你也可以输入 help(command_name) 或 help(class) 来获取给定类的帮助文档(类似 manpage )。
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--
当你输入 q 退出帮助系统时,你的会话内容将保持不变。
帮助列表不会使你的会话变得杂乱,而 function_name? 的输出有时会造成这种情况。
输入 help(module_name) 特别有用。例如,向量空间在 sage.modules.free_module 中定义,
输入 help(sage.modules.free_module) 即可获得有关整个模块的文档。
使用帮助查看文档时,可以通过输入 / 进行搜索,也可以通过输入 ? 反向搜索。
保存和加载单个对象¶
假设你计算出一个矩阵或更复杂的模符号空间,并希望将其保存以供日后使用。你要怎么办呢? 计算机代数系统采用多种方法来保存单个对象。
保存游戏: 仅支持保存和加载完整会话(如 GAP、Magma)。
统一输入输出: 使每个对象都以可读的方式打印(GP/PARI)。
Eval: 轻松在解释器中计算任意代码(如 Singular、PARI)。
由于 Sage 使用 Python,因此采用不同的方法,即每个对象都可以序列化, 转化为一个可以从中恢复该对象的字符串。这与 PARI 的统一输入输出方法精神相似, 只不过对象打印到屏幕的方式不会过于复杂。此外,保存和加载在大多数情况下是完全自动的, 不需要额外编程;这是 Python 的设计特性。
几乎所有 Sage 对象 x 都可以以压缩形式保存到磁盘,
使用 save(x, filename) (或在许多情况下 x.save(filename))。
要加载对象,使用 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')
>>> 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')
现在你应该退出 Sage 并重新启动。然后便可以恢复 A:
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]
可以使用同样的方法处理更复杂的对象,如椭圆曲线。缓存对象的所有数据都与对象一同保存。例如:
sage: E = EllipticCurve('11a')
sage: v = E.anlist(100000) # takes a while
sage: save(E, 'E')
sage: quit
>>> from sage.all import *
>>> E = EllipticCurve('11a')
>>> v = E.anlist(Integer(100000)) # takes a while
>>> save(E, 'E')
>>> quit
E 的存储版占 153K 字节,因为它储存了前 100000 个 \(a_n\).
~/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!
(在 Python 中,保存和加载使用 cPickle 模块实现。
具体来说,Sage 对象 x 可以通过 cPickle.dumps(x, 2) 保存。注意 2!)
Sage 无法保存和加载某些其它计算机代数系统(例如 GAP、Singular、Maxima)创建的单个对象。 它们重新加载时状态显示为“无效 (invalid)”。在 GAP 中,虽然许多对象的打印方式可以重新构建, 但很多对象却不行,因此特意不允许从其打印表示进行重建。
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 对象可以保存和加载,因为它们的打印表示足以重构它们。
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
保存的对象稍后可以在不同架构或操作系统的计算机上重新加载,
例如,你可以在 32 位 OS X 上保存一个大矩阵,然后在 64 位 Linux 上重新加载它,
计算阶梯形式,然后再保存回去。此外,在许多情况下,即使在不同版本的 Sage 中也能加载对象,
只要该对象的代码没有太大差异。对象的所有属性,以及定义对象的类(但不包括源代码)都会被保存。
如果该类在新版本的 Sage 中不再存在,那么该对象就无法在新版本中重新加载。
但你可以在老版本中加载它,获取其对象字典(使用 x.__dict__),保存该字典,并将其加载到新版本中。
保存为文本¶
你还可以将对象的 ASCII 文本表示保存到纯文本文件中, 只需以写入模式打开文件并写入对象的字符串表示即可(你也可以通过这种方式写入许多对象)。 写完对象后,关闭文件。
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()
保存和加载完整会话¶
Sage 对于保存和加载完整会话有非常灵活的支持。
save_session(sessionname) 命令将所有在当前会话中定义的变量保存为给定 sessionname 的字典。
(在少数情况下,如果某个变量不支持保存,则不会保存到字典。)生成的文件为 .sobj 文件,
可以像保存的其它对象一样加载。加载会话保存的对象时,会得到一个字典,字典的键为变量名,值为对象。
可以使用 load_session(sessionname) 命令将 sessionname 中定义的变量加载到当前会话。
注意,这不会清除当前会话中已经定义的变量;而是合并两个会话。
首先启动 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
>>> 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
接下来保存会话,将上面定义的每个变量保存至文件。然后查看文件,大小约为 3K。
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
最后重新启动 Sage,定义一个额外的变量,并加载保存的会话。
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
每个保存的变量再次可用。此外,变量 b 没有被覆盖。
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