NumPy

NumPy最初并没有导入sage。要使用NumPy,首先需要导入它。

sage: import numpy

NumPy中计算的基本对象是数组。创建数组很简单。

sage: l=numpy.array([1,2,3])
sage: l
array([1, 2, 3])

NumPy数组可以存储任何类型的python对象。但是,对于速度,数字类型会自动转换为本机硬件类型(即。, intfloat 等)可能的话。如果一个数字的值或精度不能由本机硬件类型处理,那么将创建一个Sage对象数组。您可以对这些数组进行计算,但它们可能比使用本机类型慢。当numpy数组包含Sage或python对象时,数据类型显式打印为 object . 如果NumPy打印数组时没有显式显示数据类型,那么类型要么是硬件浮点型,要么是int型。

sage: l=numpy.array([2**40, 3**40, 4**40])
sage: l
array([1099511627776, 12157665459056928801, 1208925819614629174706176], dtype=object)
sage: a=2.0000000000000000001
sage: a.prec() # higher precision than hardware floating point numbers
67
sage: numpy.array([a,2*a,3*a])
array([2.000000000000000000, 4.000000000000000000, 6.000000000000000000], dtype=object)

这个 dtype 属性告诉您数组的类型。对于快速数值计算,您通常希望这是某种浮点数。如果数据类型是float,那么数组存储为machine float数组,它占用的空间要少得多,并且可以更快地进行操作。

sage: l=numpy.array([1.0, 2.0, 3.0])
sage: l.dtype
dtype('float64')

可以通过指定 dtype 参数。如果您想确保您正在处理机器浮动,最好指定 dtype=float 创建数组时。

sage: l=numpy.array([1,2,3], dtype=float)
sage: l.dtype
dtype('float64')

您可以像访问任何列表一样访问NumPy数组的元素,也可以获取切片

sage: l=numpy.array(range(10),dtype=float)
sage: l[3]
3.0
sage: l[3:6]
array([3., 4., 5.])

你可以做基本的算术运算

sage: l+l
array([  0.,   2.,   4.,   6.,   8.,  10.,  12.,  14.,  16.,  18.])
sage: 2.5*l
array([  0. ,   2.5,   5. ,   7.5,  10. ,  12.5,  15. ,  17.5,  20. ,  22.5])

注意 l*l 会使 l 组件方面。要获得点积,请使用 numpy.dot() .

sage: l*l
array([  0.,   1.,   4.,   9.,  16.,  25.,  36.,  49.,  64.,  81.])
sage: numpy.dot(l,l)
285.0

我们也可以创建二维数组

sage: m = numpy.array([[1,2],[3,4]])
sage: m
array([[1, 2],
       [3, 4]])
sage: m[1,1]
4

这基本上相当于

sage: m=numpy.matrix([[1,2],[3,4]])
sage: m
matrix([[1, 2],
        [3, 4]])
sage: m[0,1]
2

不同的是 numpy.array()m 被视为一个数据数组。特别地 m*m 将乘组件,但是 numpy.matrix()m*m 会做矩阵乘法。我们也可以做矩阵向量乘法和矩阵加法

sage: n = numpy.matrix([[1,2],[3,4]],dtype=float)
sage: v = numpy.array([[1],[2]],dtype=float)
sage: n*v
matrix([[ 5.],
        [11.]])
sage: n+n
matrix([[2., 4.],
        [6., 8.]])

如果 n 创建时使用 numpy.array() ,然后要进行矩阵向量乘法,可以使用 numpy.dot(n,v) .

所有NumPy数组都有一个shape属性。这是一个很有用的属性

sage: n = numpy.array(range(25),dtype=float)
sage: n
array([  0.,   1.,   2.,   3.,   4.,   5.,   6.,   7.,   8.,   9.,  10.,
        11.,  12.,  13.,  14.,  15.,  16.,  17.,  18.,  19.,  20.,  21.,
        22.,  23.,  24.])
sage: n.shape=(5,5)
sage: n
array([[ 0.,  1.,  2.,  3.,  4.],
       [ 5.,  6.,  7.,  8.,  9.],
       [10., 11., 12., 13., 14.],
       [15., 16., 17., 18., 19.],
       [20., 21., 22., 23., 24.]])

这会将一维数组更改为 5times 5 数组。

NumPy数组也可以被切片

sage: n=numpy.array(range(25),dtype=float)
sage: n.shape=(5,5)
sage: n[2:4,1:3]
array([[11., 12.],
       [16., 17.]])

需要注意的是,切片矩阵是对原始矩阵的引用

sage: m=n[2:4,1:3]
sage: m[0,0]=100
sage: n
array([[   0.,    1.,    2.,    3.,    4.],
       [   5.,    6.,    7.,    8.,    9.],
       [  10.,  100.,   12.,   13.,   14.],
       [  15.,   16.,   17.,   18.,   19.],
       [  20.,   21.,   22.,   23.,   24.]])

你会注意到原来的矩阵改变了。这可能是你想要的,也可能不是。如果你想在不改变原始矩阵的情况下改变切片矩阵,你应该复制一份

m=n[2:4,1:3].copy()

一些特别有用的命令是

sage: x=numpy.arange(0,2,.1,dtype=float)
sage: x
array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. , 1.1, 1.2,
       1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9])

你可以看到 numpy.arange() 创建从0到2递增0.1的浮点数组。有一个有用的命令 numpy.r_() 这最好用例子来解释

sage: from numpy import r_
sage: j=numpy.complex(0,1)
sage: RealNumber=float
sage: Integer=int
sage: n=r_[0.0:5.0]
sage: n
array([0., 1., 2., 3., 4.])
sage: n=r_[0.0:5.0, [0.0]*5]
sage: n
array([0., 1., 2., 3., 4., 0., 0., 0., 0., 0.])

numpy.r_() 为高效地构造NumPy数组提供了一个速记。以上注意事项 0.0:5.0 是简写的 0.0, 1.0, 2.0, 3.0, 4.0 . 假设我们要把0到5的区间分成10个区间。我们可以这样做

sage: r_[0.0:5.0:11*j]
array([0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5, 5. ])

符号 0.0:5.0:11*j 展开为包含11个间距相等的0到5点的列表,包括两个端点。请注意 j 是NumPy虚数,但它有创建数组的特殊语法。我们可以把所有这些技术结合起来

sage: n=r_[0.0:5.0:11*j,int(5)*[0.0],-5.0:0.0]
sage: n
array([ 0. ,  0.5,  1. ,  1.5,  2. ,  2.5,  3. ,  3.5,  4. ,  4.5,  5. ,
        0. ,  0. ,  0. ,  0. ,  0. , -5. , -4. , -3. , -2. , -1. ])

另一个有用的命令是 numpy.meshgrid() 生成网格。作为一个例子,假设您想评估 f(x,y)=x^2+y^2 在等间距网格上 Delta x = Delta y = .25 对于 0le x,yle 1 . 你可以这样做

sage: import numpy
sage: j=numpy.complex(0,1)
sage: def f(x,y):
....:     return x**2+y**2
sage: from numpy import meshgrid
sage: x=numpy.r_[0.0:1.0:5*j]
sage: y=numpy.r_[0.0:1.0:5*j]
sage: xx,yy= meshgrid(x,y)
sage: xx
array([[0.  , 0.25, 0.5 , 0.75, 1.  ],
       [0.  , 0.25, 0.5 , 0.75, 1.  ],
       [0.  , 0.25, 0.5 , 0.75, 1.  ],
       [0.  , 0.25, 0.5 , 0.75, 1.  ],
       [0.  , 0.25, 0.5 , 0.75, 1.  ]])
sage: yy
array([[0.  , 0.  , 0.  , 0.  , 0.  ],
       [0.25, 0.25, 0.25, 0.25, 0.25],
       [0.5 , 0.5 , 0.5 , 0.5 , 0.5 ],
       [0.75, 0.75, 0.75, 0.75, 0.75],
       [1.  , 1.  , 1.  , 1.  , 1.  ]])
sage: f(xx,yy)
array([[0.    , 0.0625, 0.25  , 0.5625, 1.    ],
       [0.0625, 0.125 , 0.3125, 0.625 , 1.0625],
       [0.25  , 0.3125, 0.5   , 0.8125, 1.25  ],
       [0.5625, 0.625 , 0.8125, 1.125 , 1.5625],
       [1.    , 1.0625, 1.25  , 1.5625, 2.    ]])

你可以看到 numpy.meshgrid() 产生一对矩阵,这里表示 xxyy ,这样 (xx[i,j],yy[i,j]) 有坐标 (x[i],y[j]) . 这很有用,因为 f 在网格上,我们只需要在 xxyy . 由于NumPy在数组组件上自动执行算术运算,所以用很少的代码就可以很容易地在网格上计算函数。

一个有用的模块是 numpy.linalg 模块。如果你想解一个方程 Ax=b

sage: import numpy
sage: from numpy import linalg
sage: A=numpy.random.randn(5,5)
sage: b=numpy.array(range(1,6))
sage: x=linalg.solve(A,b)
sage: numpy.dot(A,x)
array([1., 2., 3., 4., 5.])

这将创建一个随机的5x5矩阵 A ,并求解 Ax=b 在哪里? b=[0.0,1.0,2.0,3.0,4.0] . 在 numpy.linalg 基本上是不言自明的模块。例如有 qrlu 进行QR和LU分解的例程。还有一个命令 eigs 用于计算矩阵的特征值。你总能做到 <function name>? 获取对这些例程非常有用的文档。

希望这能给你一个什么样的NumPy是什么样的感觉。您应该研究一下这个包,因为它有更多的功能。