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打印数组时没有显式显示数据类型,则类型为硬件浮点型或整型。

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,则数组存储为机器浮点数的数组,这样占用的空间少得多,操作速度也快得多。

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数组都有一个形状属性。这是一个可操作的有用属性

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 = 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 扩展到包括两个端点在内的0到5之间的11个等间距点的列表。请注意 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. ])

Another useful command is numpy.meshgrid(), it produces meshed grids. As an example suppose you want to evaluate f(x,y)=x^2+y^2 on a an equally spaced grid with Delta x = Delta y = .25 for 0le x,yle 1. You can do that as follows

sage: import numpy
sage: j = 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是什么样子的。您应该探索这个包,因为它有相当多的功能。