SAGE入门编程教程

Sage Document是为MAA预备研讨会“SAGE:在本科生中使用开源数学软件”开发的教程之一(由国家科学基金会提供,截止日期0817071)。它是在知识共享署名-Share Alike 3.0许可证下授权的 (CC BY-SA )。

本教程将涵盖以下主题(以及贯穿始终的各种其他主题):

我们将使用基本矩阵和课堂上日常使用矩阵时可能需要处理的情况来激发我们的例子。

方法和点符号

在Sage中,创建新的矩阵并不太难。

sage: A = matrix([[1,2],[3,4]])

正如我们所看到的,这给出了在两个带括号的集合中给出行的矩阵。

sage: A
[1 2]
[3 4]

有些命令可以立即使用,比如衍生品。这就是决定因素。

sage: det(A)
-2

但有些东西不能以这种方式获得,例如,减少了行的梯形表格。我们可以在这之后‘标签’,以确保。

sage: r

因此,正如我们在之前的教程中所看到的, many Sage中的命令中有对象的“方法”。

也就是说,我们通过键入以下命令来访问它们:

  • 数学对象的名称,

  • 点/句点,

  • 方法的名称,以及

  • 圆括号(可能带有参数)。

这是一个巨大的优势,一旦你熟悉它,因为它允许你做 only 那些可能的事情,以及 all 这类事情。

首先,让我们再做一次行列式。

sage: A.det()
-2

然后我们做减排梯形。

sage: A.rref()
[1 0]
[0 1]

把它放在括号里是非常重要的。

备注

没有它们就合法的东西将被称为‘属性’,但Sage更喜欢在风格上隐藏它们,因为数学是由函数而不是集合的元素组成的。或者一个范畴理论家会这么说。

sage: A.det # Won't work
<built-in method det of sage.matrix.matrix_integer_dense.Matrix_integer_dense object at ...>

这是非常有用的,因为我们可以使用‘Tab’键,记住!

sage: A.

有时你会有惊喜。对象中的细微变化可能会影响可用的命令或它们的结果。

sage: A.echelon_form()
[1 0]
[0 2]

这是因为我们的原始矩阵只有整数系数,除非乘以有理数,否则无法通过初等运算得到最后一项!

sage: B = A.change_ring(QQ); B.echelon_form()
[1 0]
[0 1]

另一个问题是,人们是否需要论证。请记住,只需阅读文档就可以轻松实现!

下面,让我们来看看我们是否需要一个参数来获得一个专栏。

sage: A.column?

看起来我们有。让我们输入 1

sage: A.column(1)
(2, 4)

注意,这给出了第二列!

sage: A
[1 2]
[3 4]

这是怎么回事?

列表、循环和集合生成器

(尤其是列表理解!)

在上一个示例中,我们看到 1 对矩阵列的选择提供了 second 纵队。

sage: matrix([[1,2],[3,4]]).column(1)
(2, 4)

您可能认为会给出第一列,但Sage(以及Python编程语言)开始对任何类似于零的序列进行编号。我们以前提到过这一点,但记住这一点非常重要。

为了强调这一点,让我们正式介绍一个我们以前见过一两次的基本对象,称为 list

您应该将列表视为有序集合,其中集合的元素几乎可以是任何东西--包括其他列表。

sage: my_list=[2,'Grover',[3,2,1]]; my_list
[2, 'Grover', [3, 2, 1]]

您可以使用方括号非常轻松地访问此类列表中的任何元素。只要记住,计数是从零开始的。

sage: my_list[0]; my_list[2]
2
[3, 2, 1]

人们可以用列表做很多高级的事情。

sage: my_list[0:2]
[2, 'Grover']

然而,正如我们现在看到的那样,我们引入这一点的主要原因是更实际的。

  • 在教室里,计算机最好的用途之一就是快速显示乏味的东西。

  • 在线性代数中,手工做的最繁琐的事情之一就是求矩阵的幂。

  • 在这里,我们用“手工”制作矩阵的前四次方。

sage: A = matrix([[1,2],[3,4]])
sage: A^0; A^1; A^2; A^3; A^4
[1 0]
[0 1]
[1 2]
[3 4]
[ 7 10]
[15 22]
[ 37  54]
[ 81 118]
[199 290]
[435 634]

这并不可怕,但也不是很好,特别是如果你想做一些事情 with 这些新的矩阵。

相反,我们可以做一种众所周知的 loop 建筑。请看下面的符号;它至少是模糊的数学。

sage: for i in [0,1,2,3,4]:
....:     A^i
[1 0]
[0 1]
[1 2]
[3 4]
[ 7 10]
[15 22]
[ 37  54]
[ 81 118]
[199 290]
[435 634]

我们做了什么?

  • 对于每个 \(i\) 在片场里 \(\{0,1,2,3,4\}\) ,返回 \(A^i\)

是啊,这说得通。方括号创建了一个列表,原始矩阵的幂的顺序与列表相同。

(第一行的冒号和第二行的缩进是 extremely 重要;它们是Python的基本语法结构。)

对于好奇的人:这是更好的,但仍然不是完美的。最好是找到一种更快的方法来编写可能的值 \(i\) 。在Sage中,有两种方法可以做到这一点。

sage: for i in [0..4]:
....:     det(A^i)
1
-2
4
-8
16
sage: for i in range(5):
....:     det(A^i)
1
-2
4
-8
16

这些构建列表的方法非常有用,它们表明,像许多Sage/Python一样,计数从零开始,以比“end”小一结束,比如 range

下面,我们展示了一个人也可以得到除1以外的步长。

sage: list(range(3, 23, 2))
[3, 5, 7, 9, 11, 13, 15, 17, 19, 21]
sage: [3,5..21]
[3, 5, 7, 9, 11, 13, 15, 17, 19, 21]

备注

还必须强调的是, range 命令可以执行 not 包括它的最后一个值!要进行快速测验,请在上面的示例中确认这一点。

这一切都运行良好。然而,在很短的时间内,这也会看起来很乏味(在这一点上,您可能必须信任我们)。事实证明,有一种非常强大的方法来创建这样的列表,这种方法非常类似于所谓的集合构建器表示法,称为 list comprehension

我们从一个相对简单的例子开始:

\[\{n^2\mid n\in\ZZ, 3 \leq n \leq 12\}\]

谁没有在课程中的某个时候写过这样的东西?

这对于列表理解是很自然的,在Sage中使用时会非常强大。

sage: [n^2 for n in [3..12]]
[9, 16, 25, 36, 49, 64, 81, 100, 121, 144]

就这样。这在某种程度上扭转了循环。

  • 如果你从数学的角度来考虑,这个符号是最简单的; \(n^2\) ,用于(所有) \(n\) 在3到13的范围内。

这是非常有用的。下面是一个很好的绘图示例:

sage: plot([x^n for n in [2..6]],(x,0,1))
Graphics object consisting of 5 graphics primitives

现在,我们将其应用于我们最初所做的示例。请注意,我们现在对这些矩阵的所有行列式有了很好的简明描述,没有冒号和缩进的语法:

sage: [det(A^i) for i in [0..4]]
[1, -2, 4, -8, 16]

表格

最后,从严格的编程中解脱出来,这里有一个有用的提示。

你们中的一些人可能熟悉一种从其他程序中获取此类数据并将其以表格形式存储的方法。这个 table 命令为我们执行此操作::

sage: table( [ (i,det(A^i)) for i in [0..4] ] )
  0   1
  1   -2
  2   4
  3   -8
  4   16

请注意,每个元素 this 列表是两个圆括号中的项目(所谓的 tuple )。

更好的是,我们可以在它上面放一个标题行,通过添加列表来真正清楚地表明我们正在做什么。我们已经看到了像这样的关键词 header=True 在做一些我们的计划和限制的时候。你认为如果在页眉的标签周围贴上美元符号会发生什么?

sage: table( [('i', 'det(A^i)')] + [ (i,det(A^i)) for i in [0..4] ], header_row=True)
    i   det(A^i)
  ├───┼──────────┤
    0   1
    1   -2
    2   4
    3   -8
    4   16

定义函数

或者,扩展Sage

通常的情况是,Sage可以做一些事情,但没有简单的命令。例如,您可能想要获取一个矩阵,并输出该矩阵减去原始矩阵的平方。

sage: A = matrix([[1,2],[3,4]])
sage: A^2-A
[ 6  8]
[12 18]

对于其他矩阵,如何做到这一点呢?当然,你可以一直这样做 \(A^2-A\) 再三。但这将是乏味的,很难跟上,因为有太多的事情激励着一些小编程。以下是我们解决这个问题的方法。

sage: def square_and_subtract(mymatrix):
....:     return mymatrix^2-mymatrix

这个 def 命令创建了一个名为 square_and_subtract 。它甚至应该可以使用制表符完成。

关于它的建设,以下是一些需要注意的事情:

  • 输入内容在括号内。

  • 如上所述,缩进和冒号是至关重要的。

  • 通常会有一个返回值,由 return 。这是Sage将在输入单元格下方提供的内容。

sage: square_and_subtract(A)
[ 6  8]
[12 18]
sage: square_and_subtract(matrix([[1.5,0],[0,2]]))
[0.750000000000000 0.000000000000000]
[0.000000000000000  2.00000000000000]

我们可以通过将文档字符串放在三个引号中来获得它 """

sage: def square_and_subtract(mymatrix):
....:     """
....:     Return `A^2-A`
....:     """
....:     return mymatrix^2-mymatrix
sage: square_and_subtract?

太酷了!而且可能对学生和你都很有帮助,特别是如果函数很复杂的话。这个 \(A\) 正确的排版,因为我们把它放在反号中(见上文)。

非常细心的读者 may 我注意到没有任何需要输入的内容 mymatrix 成为一个母体。Sage只会试着平方你给它的任何东西,然后减去原来的东西。

sage: square_and_subtract(sqrt(5))
-sqrt(5) + 5

这是一个需要注意的典型问题;仅仅因为您定义了某事并不意味着它是有用的(尽管在本例中它是有用的)。

尝试定义一个函数,该函数输入一个矩阵并返回该矩阵的立方体的行列式。(当然,有几种方法可以做到这一点!)

从名字和副本中得到的信息

或者,名字里有什么

在我们结束本教程之前,我们想指出一些与编程相关的事情,它们经常会让人绊倒。

第一个“问题”是有可能破坏常量!

sage: i
4

你能想出原因吗 i=4 ?仔细看上面,看看这是什么时候发生的。

  • 这给了我们一个宝贵的教训; any time 您使用的名称可能会被重新命名。

这看起来可能很糟糕,但这样做可能是非常合乎逻辑的,例如,如果您只处理实数矩阵。不过,这绝对是一个Sage用户需要知道的事情。

幸运的是,可以恢复符号常量。

sage: reset('i')
sage: i; i^2
I
-1
sage: type(e)
<class 'sage.symbolic.expression.E'>
sage: type(pi)
<class 'sage.symbolic.expression.Expression'>

变量是另一件需要牢记的事情。正如在前面的教程中简要提到的,为了保持最大的灵活性,同时不允许不应该发生的事情发生,只是 x 是预定义的,没有其他东西。

sage: type(x)
<class 'sage.symbolic.expression.Expression'>
sage: type(y)
Traceback (most recent call last):
...
NameError: name 'y' is not defined

警告

那里 is 一种绕过这一点的方法,但它释放了一大批潜在的滥用。如果您对此感兴趣,请参阅下面的单元格。

sage: automatic_names(True) # not tested
sage: trig_expand((2*x + 4*y + sin(2*theta))^2) # not tested
4*(sin(theta)*cos(theta) + x + 2*y)^2

这只适用于笔记本电脑。现在我们要把它关掉。

sage: automatic_names(False) # not tested

另一个相关的问题是,一些名称是由Python/Sage“保留”的,并且不允许作为变量名称。

不允许使用‘for’并不奇怪,但‘lambda’也不允许 (\(\lambda\) )!人们经常要求解决这个问题。

sage: var('lambda')
Traceback (most recent call last):
...
ValueError: The name "lambda" is not a valid Python identifier.

有很多方法可以绕过这一点。一种流行但令人恼火的方式是这样的。

sage: var('lambda_')
lambda_
sage: lambda_^2-1
lambda_^2 - 1

尽管如此,在这个例子中,这个表达仍然显示了希腊字母。

sage: show(lambda_^2-1)
\[\lambda^{2}-1\]

最后,如果重命名过于松散,还可能发生另一件事。

sage: A = matrix(QQ,[[1,2],[3,4]])
sage: B = A
sage: C = copy(A)

这实际上使B和A引用了相同的矩阵。B不像A,它是 is A. copy 命令可以绕过这个问题(尽管并不总是如此)。

sage: A[0,0]=987
sage: show([A,B,C])
\[\begin{split}\left[\left(\begin{array}{rr} 987 & 2 \\ 3 & 4 \end{array}\right), \left(\begin{array}{rr} 987 & 2 \\ 3 & 4 \end{array}\right), \left(\begin{array}{rr} 1 & 2 \\ 3 & 4 \end{array}\right)\right]\end{split}\]

如果您以前从未编程过,这是非常微妙的。可以说,最安全的做法是让每一个人 = 符号代表一件事,避免多余的等号(不像有时的学生)。

附录:高级介绍性主题

有几件事情是很有用的,但在编程中并不总是立即引入。我们在这里举了几个例子,但它们主要是为了确保您已经看到了它们,这样当它们再次出现时,它们就不会完全令人惊讶。

我们在前面看到了带有缩进的Python的“块”结构。这提供了引入条件语句和比较的机会。在这里,我们只给那些以前看过条件句(“if”从句)的人举个例子。

sage: B = matrix([[0,1,0,0],[0,0,1,0],[0,0,0,1],[0,0,0,0]])
sage: for i in range(5): # all integers from 0 to 4, remember
....:     if B^i==0: # We ask if the power is the zero matrix
....:         print(i)
4

我们使用双等号来测试是否相等,因为 = 为变量名分配一些内容。再次注意,冒号和缩进是Sage/Python表示语法的主要方式,就像英语中的逗号和空格一样。

另一个有用的概念是 dictionary 。这可以被认为是从“键”到“值”的数学映射。顺序是 not 重要且 not 有保证。词典用大括号分隔,对应用冒号表示。

同样,我们将只举一个小例子来说明这一想法。

如果只想使用非零项来指定矩阵,该怎么办?词典是一个很好的方法来做到这一点。

此命令将3作为条目放入 \((2,3)\) Spot,例如(请记住,这是 third 行和 fourth 列,因为我们从零开始)。

sage: D = {(2,3):3, (4,5):6, (6,0):-3}
sage: C = matrix(D)
sage: C
[ 0  0  0  0  0  0]
[ 0  0  0  0  0  0]
[ 0  0  0  3  0  0]
[ 0  0  0  0  0  0]
[ 0  0  0  0  0  6]
[ 0  0  0  0  0  0]
[-3  0  0  0  0  0]

这比输入整个矩阵要容易得多!

最后,尽管Sage试图预测您想要什么,但有时您如何定义Sage中的给定元素确实很重要。

  • 例如,我们在上面的有理数对整数的矩阵中看到了这一点。

这里有一个直接数字的例子。

sage: a = 2
sage: b = 2/1
sage: c = 2.0
sage: d = 2 + 0*I
sage: e = 2.0 + 0.0*I

我们也不会深入讨论这一点,但它值得了解。请注意,这些类型的数字中的每一种都有或没有 \(I=\sqrt{-1}\) 、小数点或除法。

sage: parent(a)
Integer Ring
sage: parent(b)
Rational Field
sage: parent(c)
Real Field with 53 bits of precision
sage: parent(d)
Number Field in I with defining polynomial x^2 + 1 with I = 1*I
sage: parent(e)
Complex Field with 53 bits of precision