互动Shell

在本教程的大部分内容中,我们假定您使用 sage 指挥部。这将启动IPythonShell的定制版本,并导入许多函数和类,以便可以从命令提示符使用它们。进一步的定制可以通过编辑 $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或键入 quitexit

sage: quit
Exiting Sage (CPU time 0m0.00s, Wall time 0m0.89s)

挂钟时间就是挂在墙上的时钟所经过的时间。这一点很重要,因为CPU时间不跟踪GAP或Single等子进程使用的时间。

(避免使用以下命令终止Sage进程 kill -9 从终端,因为Sage可能不会删除子进程,例如Maple进程,或从 $HOME/.sage/tmp 。)

您的Sage会议

会话是从启动Sage到退出的输入和输出序列。Sage通过IPython记录所有Sage输入。事实上,如果您使用的是交互式Shell(而不是笔记本界面),那么您可以随时输入 %history (或 %hist )以获取到目前为止输入的所有输入行的列表。你可以打字 ? 在Sage提示符下查找有关IPython的更多信息,例如,“IPython提供编号提示……具有输入和输出缓存。所有输入都被保存,并且可以作为变量检索(除了通常的箭头键调用)。以下全局变量始终存在(所以不要覆盖它们!)”:

_:  previous input (interactive shell and notebook)
__: next previous input (interactive shell only)
_oh : list of all inputs (interactive shell only)

下面是一个例子:

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

在本教程的其余部分和其他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).
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

在使用交互式Shell时,可以在Sage中执行任何UNIXShell命令,只需在其前面加上感叹号 ! 。例如,

sage: !ls
auto  example.sage glossary.tex  t  tmp  tut.log  tut.tex

返回当前目录的列表。

这个 PATH 在前面有Sage bin目录,所以如果您运行 gpgapsingularmaxima 等等,您可以获得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    \

记录输入和输出

记录您的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终端中使用Sage konsole 然后,您可以按如下方式保存会话:在中启动Sage之后 konsole ,选择“设置”,然后选择“历史...”,然后选择“设置无限制”。当您准备好保存会话时,选择“编辑”,然后选择“将历史记录另存为...”并键入名称以将会话的文本保存到您的计算机。保存此文件后,您可以将其加载到一个编辑器(如xemacs)中并打印它。

粘贴忽略提示

假设您正在阅读Sage或Python计算的会话,并希望将它们复制到Sage中。但也有令人讨厌的 >>>sage: 提示人们要担心。事实上,您可以将一个示例复制并粘贴到Sage中,如果需要的话,还可以包括提示。换句话说,默认情况下,Sage解析器会去掉所有前导 >>>sage: 在将其传递给Python之前进行提示。例如,

sage: 2^10
1024
sage: sage: sage: 2^10
1024
sage: >>> 2^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

这意味着总共花费了0.66秒,而“挂钟时间”,也就是挂钟所用的时间,也是0.66秒。如果您的计算机上加载了大量其他程序,则挂起时间可能会比CPU时间长得多。

也可以使用 timeit 函数尝试在命令的大量迭代中获取计时。这会给出稍有不同的信息,并且需要输入一个字符串和您想要计时的命令。

sage: timeit("int(1938)^int(99484)")
5 loops, best of 3: 44.8 ms per loop

接下来,我们使用本机Sage Integer类型进行时间求幂,该类型是使用GMP库实现的(在Cython中):

sage: %time a = 1938^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

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
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

这个 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: gap(0)
0
sage: time g = gap.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的任何命令和特性。您可以阅读 full IPython documentation 。同时,这里有一些有趣的技巧--这些在IPython中被称为“魔术命令”:

  • 您可以使用 %edit (或 %eded )打开一个编辑器,如果您想要键入一些复杂的代码。在启动Sage之前,请确保 EDITOR 环境变量设置为您最喜欢的编辑器(通过将 export EDITOR=/usr/bin/emacsexport EDITOR=/usr/bin/vim 或在适当的位置使用类似的内容,如 .profile 文件)。在Sage提示符下,执行 %edit 将打开指定的编辑器。然后,您可以在编辑器中定义一个函数:

    def some_function(n):
        return n**2 + 3*n + 2
    

    从编辑器中保存和退出。对于您的Sage会话的其余部分,您可以使用 some_function 。如果要修改它,请键入 %edit some_function 从Sage提示符。

  • 如果您有计算,并且想要修改其输出以用于其他用途,请执行计算并输入 %rep :这将把上一条命令的输出放在Sage提示符下,以便您进行编辑。**

    sage: f(x) = cos(x)
    sage: f(x).derivative(x)
    -sin(x)
    

    此时,如果您键入 %rep 在Sage提示符下,您将看到一个新的Sage提示符,然后是 -sin(x) ,并将光标放在行尾。

有关更多信息,请键入 %quickref 获取IPython的快速参考指南。在撰写本文时(2011年4月),Sage使用的是IPython0.9.1版, documentation for its magic commands 可以在网上找到。记录了魔术指挥系统的各种略微高级的方面 here 在IPython中。

错误和例外

当出现问题时,您通常会看到一个Python“异常”。Python甚至试图提出是什么引发了这一异常。通常您会看到异常的名称,例如, NameErrorValueError (请参阅《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

交互式调试器有时对于了解哪里出了问题很有用。您可以使用以下命令打开或关闭它 %pdb (默认为禁用)。提示符 ipdb> 如果引发异常且调试器处于打开状态,则显示。在调试器中,您可以打印任何局部变量的状态,并在执行堆栈中上下移动。例如,

sage: %pdb
Automatic pdb calling has been turned ON
sage: EllipticCurve([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 回到赛奇身边。

反向搜索和制表符完成

反向搜索:键入命令的开头,然后 Ctrl-p (或只需按向上箭头键)返回到以该方式开始输入的每一行。即使您完全退出Sage并稍后重新启动,这也是有效的。还可以使用以下命令对历史记录进行反向搜索 Ctrl-r 。所有这些功能都使用 readline 包,它在大多数版本的Linux上都可用。

为了演示制表符补全,首先创建三维向量空间 \(V=\QQ^3\) 详情如下:

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

您还可以使用以下更简洁的表示法:

sage: V = QQ^3

然后,很容易列出的所有成员函数 \(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

如果键入函数的前几个字母,则 Tab 键,则只能获得按指示开始的函数。

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

如果您想知道某个特定的函数是做什么的,例如坐标函数,输入 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]

如上所述,输出将告诉您对象的类型、在其中定义对象的文件以及对函数的有用描述,以及可以粘贴到当前会话中的示例。几乎所有这些示例都会定期自动测试,以确保它们的工作和行为与声称的完全相同。

另一个非常符合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()

这告诉我们,所有的 coordinates 函数的作用是调用 coordinate_vector 函数并将结果更改为列表。什么是 coordinate_vector 函数做什么?

sage: V = QQ^3
sage: 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)

(如果您认为实现效率低下,请注册以帮助优化线性代数。)

您也可以键入 help(command_name)help(class) 获取有关给定类的手册页般的帮助文件。

sage: help(VectorSpace)
Help on class VectorSpace ...

class VectorSpace(__builtin__.object)
 |  Create a Vector Space.
 |
 |  To 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 `` ?``

保存和加载单个对象

假设您计算了一个矩阵,或者更糟,一个由模符号组成的复杂空间,并且想要保存它以备后用。你能做什么?计算机代数系统有几种方法来保存单个对象。

  1. Save your Game: 仅支持保存和加载完整的会话(如GAP、MAGMA)。

  2. Unified Input/Output: 使每个对象以可回读的方式打印(GP/PAI)。

  3. Eval :使在解释器中评估任意代码(例如,单数、Pari)变得容易。

因为Sage使用的是Python,所以它采用了一种不同的方法,即每个对象都可以被序列化,也就是说,可以将其转换为可以从中恢复该对象的字符串。这在本质上类似于Pari的统一I/O方法,除了它没有对象以太复杂的方式打印到屏幕上的缺点。此外,对保存和加载的支持(在大多数情况下)是完全自动的,不需要额外的编程;它只是一种从头设计到语言中的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')

您现在应该退出Sage并重启。然后你就可以得到 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

已保存的版本 E 占用153千字节,因为它存储前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、Single、Maxima等。它们在标记为“INVALID”的状态下重新加载。在GAP中,尽管许多对象以可以重建的形式打印,但许多对象不能,因此故意不允许从他们的打印表示进行重建。

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/PAI对象,因为它们的打印表示足以重建它们。

sage: a = gp(2)
sage: a.save('a')
sage: 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()

保存和加载完整会话

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

接下来,我们保存会话,该会话将上述每个变量保存到一个文件中。然后我们查看文件,它的大小约为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

最后,我们重新启动Sage,定义一个额外的变量,并加载我们保存的会话。

sage: b = 19
sage: 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