Sage编程入门教程

这个 Sage 该文件是为MAA预习班“Sage:在本科生中使用开源数学软件”开发的教程之一(NSF提供资金,到期日:0817071)。它是根据Creative Commons Attribution -ShareLiked 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 ...>

这是如此有用,因为我们可以使用'标签'键,记住!

sage: A.

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

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

这是因为我们的原始矩阵只有整数系数,并且你不能通过初等运算使最后一个输入是1,除非你乘以一个有理数!

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 选择矩阵的列可以得到 第二 列。

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\) .

是的,这很有道理。方括号创建了一个列表,原始矩阵的幂次顺序与列表的顺序相同。

(第一行的冒号和第二行的缩进是 极其 重要的是,它们是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 .

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

sage: range(3, 23, 2)   # py2
[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 包括它的最后一个值!对于快速测验,请在上面的示例中确认这一点。

这一切都很好。然而,很短的时间之后,这看起来也很乏味(你可能必须相信我们)。事实证明,有一种非常强大的方法来创建这样的列表,这种方法非常类似于所谓的set builder符号,称为 列表理解 .

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

\[{n^2mid ninZZ,3leq nleq 12}\]

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

这是一个自然的列表理解,可以非常强大的时候使用在Sage。

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

就这样。这样可以扭转局面。

  • 如果你用数学的方法来考虑,这个符号是最简单的 \(n^2\) ,for(全部) \(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 列表是括号中的两项(所谓 元组

更妙的是,我们可以在上面加一个标题行,通过添加列表,使我们真正清楚地知道我们在做什么。我们见过像 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 ? 仔细看上面,看看这是什么时候发生的。

  • 这给我们上了宝贵的一课; 任何时候 你使用的名字有可能被重命名。

这可能看起来很糟糕,但可能是相当合乎逻辑的,例如,如果你只处理实矩阵。不过,这绝对是一个聪明的用户需要知道的。

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

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

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

sage: type(x)
<type '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)
\[λ^{2}-1\]

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

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

这实际上使B和A引用同一个矩阵。B不像A,是吗 is A. copy command可以绕过这个问题(尽管不总是这样)。

sage: A[0,0]=987
sage: show([A,B,C])
\[左 [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]\]

这是非常微妙的,如果你从来没有编程。只要说让每个人 = 符号代表一件事,避免多余的等号(不同于学生有时)。

附录:高级入门主题

有几件事是很有用的,但在编程中并不总是立即介绍。我们在这里给出了一些例子,但它们主要是为了确保你已经看到它们,这样当它们再次出现时,它们不会完全令人惊讶。

我们在前面看到了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表示语法的主要方式,就像英语中的逗号和空格一样。

另一个有用的概念是 词典 . 这可以看作是从“键”到“值”的数学映射。命令是 not 重要和 not 放心。词典用大括号分隔,对应关系用冒号表示。

再次,我们将给出一个小例子来说明这个想法。

如果只想用非零项指定一个矩阵怎么办?字典是一个很好的方法。

这个把3放在 \((2,3)\) 例如spot(记住,这是 第三的 row和 第四 列,因为我们从零开始)。

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)
Symbolic Ring
sage: parent(e)
Symbolic Ring