在 Wolfram 语言的后续版本中引入了与本教程内容相关的附加功能. 最新信息请见矩阵和线性代数.

矩阵与张量运算

这一教程将对 Wolfram 语言所提供的用于构造和操控矩阵、向量和张量的函数进行评述. 它着重介绍 Wolfram 语言的专用函数,并使用矩阵作为例子. 然而,所有函数都是一般的,同样适用于向量和张量.

构造矩阵

在 Wolfram 语言中矩阵用列表表示. 它们可以直接用所提供给列表的 { } 符号进行输入. 这里是一个矩阵的例子;默认时,矩阵的显示带有列表符号:

Wolfram 语言提供了许多构造矩阵的方式.

Table[f,{i,m},{j,n}]建立一个 m×n 矩阵,其中 fij 的函数,它给出第 i,j 项的值
Array[f,{m,n}]建立一个 m×n 矩阵,其中第 i,j 项是 f[i,j]
DiagonalMatrix[list]建立一个对角矩阵,对角线上是 list 的元素
IdentityMatrix[n]建立一个 n×n 单位阵
ConstantArray[val,{m,n}]]建立一个 m×n 矩阵,其中每一个元素都是 val
RandomReal[{0,val},{m,n}]]建立一个各项随机产生的 m×n 矩阵
Normal[SparseArray[{{i1,j1}->v1,{i2,j2}->v2,},{m,n}]]
建立一个 m×n 矩阵,其中在位置{ik,jk}处的值为非零值 νk
当没有内置函数来生成您的矩阵时,函数 Table 对于生成矩阵尤其重要. Wolfram 语言文档包含更多关于 Table 的信息. 这个例子中构建了一个 3×3 矩阵:
MatrixForm 将该矩阵以二维形式显示:
在 Wolfram 语言中构建矩阵的另一种方式是通过 Array 命令. 这里用该命令建立一个3×3 矩阵:
Wolfram 语言有一些建立某些专门矩阵的函数. 这里建立了单位矩阵:
注意生成的单位矩阵是一个整数矩阵. 如果想要进行关于浮点数的计算,使用包含浮点项的矩阵可能会很有利;这一点在"矩阵内容"中有更详细地介绍. 如果想要以整数矩阵(例如先前生成的单位矩阵等)开始,通过函数 N 可以将其转换为浮点矩阵. 下面将说明这一点:
这里构建了一个对角矩阵:
在这个例子中,元素被放置在第一个对角线上. 结果通过 MatrixForm 显示:
这里生成了一个元素均为2的5×5矩阵:
这里建成了一个2×4矩阵,其中各个元素均是范围在0到5之间的伪随机实数:
这里建成了一个3×4矩阵,其中各个元素均是范围在-5到5之间的伪随机整数:
这里建成了一个3×4矩阵,并填入两个非零值. SparseArray 表达式在"稀疏数组的运用"一节中介绍:
SparseArray[{},{n,n}]一个零矩阵
SparseArray[{i_,i_}->1,{n,n}]一个 n×n 单位矩阵
SparseArray[{i_,j_}/;i>=j->1,{n,n}]
一个下三角矩阵

通过 SparseArray 构建特殊类型的矩阵.

这里设置了一个一般意义的下三角矩阵:

能够将文件读入矩阵的函数在矩阵的"导入和导出" 一节中介绍.

特殊矩阵

Wolfram 语言包含许多特殊矩阵的定义.

HilbertMatrix[n]创建一个 n×n Hilbert 矩阵,其中元素通过 1/(i+j-1) 给出
HilbertMatrix[{m,n}]创建一个 m×n Hilbert 矩阵
HankelMatrix[n]创建一个 n×n Hankel 矩阵,其中第一列通过1, 2, , n 给出,且主反对角线下方的各元素均为零
HankelMatrix[list]创建一个 Hankel 矩阵,其中第一列通过 list 给出, 且主反对角线下方的各元素均为零
HankelMatrix[col,row]创建一个 Hankel 矩阵,其中第一列通过列表 col 给出,最后一行通过列表 row 给出

特殊矩阵.

这是一个2×4 Hilbert 矩阵:
Hankel 矩阵的元素可以以列表形式给出:
Hankel 矩阵可以通过给出最后一行来以非零值填充. 这也允许非方矩阵的生成. 注意第一列的最后一个元素与最后一行的第一个元素必定相同:

结构操作

这些操作全部与矩阵结构有关. 这一节中所介绍的许多技术可以应用于 Wolfram 语言表达式,并非矩阵专用.

获得矩阵的一部分

使用 Wolfram 语言函数 Part 可以直接提取矩阵的元素、行或列. 通常 Part 可以使用[[ ]] 符号进行输入.

m[[i,j]]i,j
m[[i]]i
m[[i;;i]]ij
m[[All,i]]i
m[[All,i;;j]]ij 列
m[[{i1,,ir},{j1,,js}]]r×s 子矩阵,其中元素的行标为 ik, 列标为 jk
Tr[m,List]m 的对角元素列表

得到矩阵某一部分的途径.

定义下面的矩阵:
这里得到了第一行中的第二个元素:
得到第3行:
通过 All 指定所有行也可以得到一列:
负指标用于指矩阵的结束. 下面获取最后一行的最后一个元素:
可以使用;;得到矩阵的一定范围. 这里得到了第二至第四行:
这里得到了了第二至第四列:
也可以给出一个梯度. 这里将矩阵隔列给出:
函数 Tr 作用于矩阵的对角线元素. 该单参数形式将这些值相加:
Tr 也可取一个函数作为第二个参数应用于对角线元素. 如果使用 List,将返回对角线元素:

应该注意到这些用于矩阵部分提取的命令适用于任何 Wolfram 语言表达式.

获得多个部分

通过使用指标列表可以提取多个元素. 这通过下面的样本矩阵说明:
下面得到第二行的第一和第三个元素:
下面得到第二行和第四行:
下面得到第二行和第四行的第一个和第三个元素:

设置矩阵的部分

使用任务左方的 Wolfram 语言函数 Part 可以设置矩阵的元素、行和列从而直接更新矩阵.

m={{a11,a12,},{a21,a22,},}指定 m 为一个矩阵
m[[i,j]]=v重新设置元素{i,j}v
m[[i]]=v重新设置行 i 的全部元素为 v
m[[i]]={v1,v2,}重新设置行 i 的全部元素为{v1,v2,}
m[[All,j]]=v重新设置列 j 的全部元素为 v
m[[All,j]]={v1,v2,}重新设置列 j 的全部元素为{v1,v2,}

重置部分矩阵.

这是一个5×5矩阵:

可以使用任务左方的函数 Part 来更新部分矩阵.

设置第三行的第三个元素:
设置第二行使之含有特殊值:
设置第二列:
可以使用负指标指示矩阵的结束. 下面的例子设置了最后一行的最后一个元素:
也可以使用范围语法设置部分矩阵. 这里将隔行元素设置为z

设置多个部分

通过使用指标列表可以设置多个元素. 这通过下面的样本矩阵说明:
下面设置第二行的第一和第三个元素:
如果该设置命令的右方是一个列表,并且列表中元素的个数与要设置的元素个数一致,则各元素按次序逐个设置. 因此,下例中第二行的第一个和第三个元素被给定了两个不同的值:
下面设置第二行和第四行:
第二行和第四行的值不同:
设置第二行和第四行的第一个和第三个元素:
下面分别为第二行和第四行的第一个和第三个元素赋上不同的值:

提取子矩阵

范围语法对于提取子矩阵是非常有用的.

m[[i0;;i1,j0;;j1]]提取行 i0i1 及列 j0j1 组成的子矩阵
m[[i0;;i1]]提取行 i0i1 组成的子矩阵
m[[All,j0;;j1]]提取列 j0j1 组成的子矩阵

提取子矩阵.

提取 m2,1m3,2,组成子矩阵:
提取行1至3组成的子矩阵:
提取列2至4组成的子矩阵:

可使用负指标从后向前计数.

这里返回的矩阵中第一列和最后一列被除掉了:

删除行与列

可以使用 Drop 进行行或列的删除.

Drop[m,{i0,i1}]删除行 i0i1
Drop[m,{},{j0,j1}]删除列 j0j1
Drop[m,{i0,i1},{j0,j1}]删除行 i0i1以及列 j0j1

删除行与列.

这里去掉了行2至4:
这里去掉了列2至4:
这个例子中,行2和3以及列1、2和3 都被删除:

插入行与列

可以使用 Insert 进行行或列的插入.

Insert[m,r,i]在矩阵 m 的位置 i 处插入行 r

插入一行.

在第3行之前插入一行:
如果想要插入一列,则必须转置矩阵,将该列作为行插入,然后再次转置矩阵. 这里在第5列之前插入一列:

扩展矩阵

可以通过 PadLeftPadRight 填充矩阵来增大其尺寸:
PadLeft 将元素添加到矩阵的左端:
PadRight 将元素添加到矩阵的右端:
填充函数的一个重要用途是进行矩阵的复制和平铺. 在这个例子中,输入矩阵被扩展,各行被复制两次,各列被复制三次:
PadLeftPadRight 含有一系列完全通用的额外功能,因此对于任意阶张量也有效. 这些在 Wolfram 语言文档中介绍:

转置

元素的转置是一个一般的矩阵操作:
Transpose 按照指定的指标进行元素的互换:
如果要计算一个矩阵的共轭转置,则使用函数 ConjugateTranspose
如果一个矩阵与其共轭转置相同,则该矩阵被称作 Hermitian:
也可以使用函数 HermitianMatrixQ 进行测试:

元素的轮换

另一个结构操作是在指标内部轮换元素. 这可以通过函数 RotateLeftRotateRight 完成:
第一层向左轮换一步,这作用于各行:
第二层向左轮换一步,这作用于各列:
向相反方向轮换各列:

矩阵的测试

Wolfram 语言提供了一系列用于测试矩阵及提取尺寸信息的函数.

MatrixQ[expr]如果 expr 是矩阵的形式,则给出 True,否则给出 False
Dimensions[expr]向量或矩阵的维数列表
mi==mj比较两个矩阵中元素的等价性

用于测试向量、矩阵和数组结构的函数.

如果想要测试一个表达式是否是矩阵,可以使用 MatrixQ
整数5不是一个矩阵:
一个矩阵在每个维度上必须具有相等的长度:
MatrixQ 有一个第二参数可选,用于指定将测试应用于每个元素. 在这个例子中,每一个元素都被测试,看其是否是一个整数:
在这个例子中,每一个元素都必须是大于1的整数:
命令 Dimensions 用于提取尺寸信息:
要比较两个矩阵的元素是否相等,可以使用 Equal,它通常的快捷输入符号是==. 例如,将矩阵与其自身比较将返回 True
Equal 使用数字的值因此可用于比较整数和实数值:

应该注意到 Equal 可用于任何 Wolfram 语言表达式. 如果想要使用矩阵的整体属性比较两个矩阵相等与否,比较矩阵范数可能更好. 这将在后面讨论.

进一步的结构操作

本节讨论有关矩阵的进一步的结构操作.

Flatten[m]展平 m 中的嵌套列表
Flatten[m,n]m 中的嵌套列表展平至层 n
Partition[m,n]m 分成长度为 n 的子列表
Join[m1,m2]m1m2 串联
Append[m,r]m 的尾部插入行 r
Prepend[m,r]m 的头部插入行 r
这会产生一个示范样本矩阵:
将矩阵展平为一个向量:
这里用 Partition 将这个向量重新变回一个行长为4的矩阵:
矩阵可以通过函数 Join 连接在一起. 将这个新矩阵作为新行插入:
另外,也可以将新矩阵以列的形式连在一起:
通过 Append 可以将一个新行插入矩阵的尾部:

应该注意到这也可以通过 Insert 完成;参见"插入行和列"一节.

元素相关的操作

如果您想要进行矩阵元素的操作,使用 Wolfram 语言可以轻松完成. 首先建立一个由浮点数组成的矩阵:
应用于矩阵的算术运算贯穿至每个元素. 因此,如果矩阵被加上5,其结果相当于增加5至每个元素:
这里,矩阵的每个元素都变成原来的两倍:
这里,矩阵的每个元素都变成原来的平方:
如果一个矩阵除以另一个矩阵,则除法是逐个元素进行. 如果两个矩阵的维数不一致,则会出现错误
要将 Sin 函数应用于每个元素,可以将 Sin 应用于整个矩阵:
如果一个运算的两个参数都是矩阵,则该运算在对应的元素上进行:
注意这两个矩阵的维数必须协调:
如果一个参数是矩阵,而另一个参数是向量,则运算在矩阵的行与向量的元素之间进行:
注意使用算符 Times (通常,将两个参数放在一起可以实现其输入)进行两个矩阵的相乘,所生成的矩阵中各元素是两个矩阵中对应元素的乘积. 如果想要进行矩阵相乘,可以通过函数 Dot,这在 "矩阵乘法" 一节中介绍. 下面是一个元素相乘的例子:

可列表性

如果要在矩阵的每个元素上应用用户自定义的函数,可以通过给该函数赋上 Listable 的属性实现. 这个函数将每个元素平方后除以3:
当然,这个函数同样适用于符号化的矩阵:

映射

除了利用可列表性外,还可以使用 Map 将一个函数应用于矩阵中的各个元素:
这里说明函数 f 应该作用到矩阵中的各个元素:
这里,一个将参数进行平方再将结果除以3的函数被应用的矩阵中的各个元素:

向量和张量

除了支持矩阵外,Wolfram 语言也同样支持向量和张量. 所有这一切都通过列表建立. 正如在 "Wolfram 语言中的线性代数引言"一节所介绍的, Wolfram 语言使用张量一词来指广义化的矩阵. 构建矩阵的所有操作可以被推广到向量和张量. Wolfram 语言向量的列表为1层.

这里构建了一个向量:

另外还有一些生成向量的函数.

Table[f,{i,n}]通过计算 fi=1,2, ,n 的值,建立一个长度为 n 的向量
Array[a,n]建立一个长为 n,形如 {a[1],a[2],} 的向量
Range[n]创建列表{1,2,3, ,n}
Range[n1,n2]创建列表 {n1,n1+1,n2}
Range[n1,n2,dn]创建列表 {n1,n1+dn ,n2}

用于生成向量的函数.

生成向量的一个非常有效的途径是使用 Wolfram 语言函数 Range. 这里生成了一个整数向量:
这里生成了一个实数向量,从1开始,依次递增0.1,并在4结束:
Table 也可以用于程序化的构建一个向量;如果想要执行一个函数以确定向量的元素,这往往是很有用的:
尽管使用可列表运算往往会更有效:
有与上面几节所讨论的操作和函数等价的版本应用于向量:

应该注意的是,Wolfram 语言中没有行或列向量的概念;向量只有一个指标,用于指定该向量的一个元素.

张量也可以通过使用 Table 命令建立. 这里,使用了三个迭代程序来生成一个2×3×4的张量:
使用带有三个指标的 Part,可以提取一个元素:

向量和张量的测试

Wolfram 语言提供了一系列测试向量和张量并提取尺寸信息的函数.

VectorQ[expr]如果 expr 具有向量的形式则返回 True,否则返回 False
MatrixQ[expr]如果 expr 具有矩阵的形式则返回 True,否则返回 False
ArrayQ[t,n]测试 t 是否是一个 n 阶张量
Dimensions[expr]一个向量或矩阵的维数列表
ArrayDepth[t]找到一个张量的阶
ti==tj比较两个张量中的元素是否相等

用于测试向量、矩阵和数组结构的函数.

可以使用 MatrixQ 测试一个表达式是否是一个矩阵:
除了 MatrixQVectorQArrayQ 可以用于测试向量和张量:
ArrayQ 也可以用一个阶参数测试数组的大小:
ArrayQ 还可用一个第三参数测试每个元素. 在这个例子中,由于部分元素不满足 NumberQ,结果为 False
命令 Dimensions 用于提取尺寸信息:
当输入是一个矩阵时,Dimensions 返回一个长度为2的列表,表示的是采用了两个指标来定位矩阵中的各个元素. 测试定位元素所需指标个数的另一种方式是通过 ArrayDepth. 这个例子的结果是2:
比较两个张量的元素是否相等可以使用 Equal,通常使用 == 作为快捷符号. 例如,一个张量与其自身比较将返回 True
Equal 采用的是数字值,因此可以用于比较整数和实数值:
图过两个对象的结构不一致则它们不相等:

矩阵的可视化

这一节将回顾现有的用于矩阵格式化和图形绘制的函数.

MatrixForm[mat]显示一个矩阵,其元素以二维数组方式排列
MatrixPlot[mat]显示 mat 的结构模式

矩阵格式化

矩阵可以使用函数 MatrixForm 进行格式化:
MatrixForm 也适用于向量和高阶张量;括号可以帮助您了解分组:

绘制矩阵

绘制矩阵的一个方便途径是使用函数 MatrixPlot

MatrixPlot 有一系列图形选项来控制图形的外观. 其中许多是 Wolfram 语言 DensityGraphics 对象的常规选项. 该函数会有一个特殊选项 MaxPlotPoints 来控制矩阵显示的最大尺寸. 尺寸在此之上的矩阵将被降低采样率. 一些重要的选项归纳如下.

选项名称
默认值
MaxPlotPoints200矩阵显示的最大尺寸
AspectRatio1缩放最终图像形状
ColorRulesAutomatic为每个元素着色
ColorFunctionAutomatic为每个元素着色的函数
MeshFalse是否绘制网格
MeshStyleGrayLevel[1]网格样式

MatrixPlot 选项.

MatrixPlot 的一个有用属性是能够绘制大型矩阵. 这里生成了一个非常大的稀疏矩阵:
仍可用 MatrixPlot 将其绘制. 这里所绘制的点数减小至100:
默认时,元素周围不绘制网格;这可以使用 Mesh 选项启用. 如果矩阵非常大,您通常不会要绘制网格. 当绘制网格时,有需要用到 MeshStyle 选项来改变网格样式:
可以使用 ColorRules 选项改变着色方式. 这个例子中,0绘制成白色,其它值均为黑色:
可以使用 ColorFunction 选项来添加色彩:

导入和导出矩阵

这一节将回顾现有的用于矩阵导入和导出的函数.

Import[file,format]按照指定格式从一个文件中导入数据
Export[file,mat,format]将矩阵导出至一个文件,并将其转换成指定格式

Wolfram 语言提供了一系列用于导入和导出的不同工具. 如果想将数据保存在文件中,以便以后您或同事可以继续在 Wolfram 语言中使用,您可能想使用一些适用于文件中 Wolfram 语言表达式的函数. 这些将在"表达式的导入和导出"中讨论.

如果想要使用特定的数据格式来操作来自 Wolfram 语言外部的矩阵,函数 ImportExport 将非常有用. 函数 Import 支持各种不同的格式,其中一些与矩阵相关:
Table 格式将把表格数据读入 Wolfram 语言. 该格式不是矩阵专用的,能够处理如数字、日期和货币等不同类型的信息. 然而,在矩阵中来读取往往是一个简单的方法. 这个例子显示一个示例数据文件:
现在,通过使用 Table 格式的 Import 命令,数据文件被读入 Wolfram 语言:
Export 可用某种特定格式将矩阵写出. 这里使用的是 Table 格式:
这个例子说明的是如何将矩阵写成 CSV 格式. 这种个是可以被另一个应用程序如电子表格读入:

还存在其它矩阵格式. 例如,HarwellBoeing 用于稀疏矩阵以及 Matrix Market 用于稀疏和稠密矩阵.这些将在"稀疏矩阵的导入和导出"中讨论. 此外,MAT 矩阵格式以及 FITS 天文数据格式也是有用的导入和导出格式.

矩阵乘法

矩阵乘法(也称作点积或内积)在 Wolfram 语言中通过函数 Dot 实现,通常用原点作为简写输入:
这里将矩阵与其自身相乘:
将矩阵乘以一个向量:
对于两个大小不同的矩阵,只要它们的尺寸是协调的,就可以计算出它们的乘积. 对于矩阵来说,如果一个 m1×n1 矩阵乘以一个m2×n2 矩阵,这意味着 n1 必须等于 m2. 这里,一个 2×3 矩阵与一个 3×2 矩阵相乘:
这将生成一个2×2的矩阵:
这生成一个3×3的矩阵:
如果维数不匹配,将生成一个错误信息:
Dot 可用于相等长度的向量相乘;结果将是一个标量:
矩阵与向量的乘法工作原理相同. 这里是一个2×3矩阵乘以一个长度为3的向量:
这里是将长度为3的向量乘以一个3×2矩阵:

矩阵乘法的定义按下式给定,其中 是两个矩阵 的乘积,即 .

该定义可以进行推广,下式给出的是两个任意阶张量 的乘积,乘积用 表示.

因此,将 Dot 作用到一个 阶张量和一个 阶张量的结果是一个 阶张量. 下面是一个例子.

首先定义一个2×3×4张量:
现在定义一个4×2×1张量:
tensor1 乘以 tensor2. 两者是可乘的,因为 tensor1 的最内部的指标的长度等于tensor2 的最外部的指标的长度:
结果是一个2×3×2×1张量:

外积

外积是一种由低阶张量建立高阶张量的方式. Wolfram 语言通过函数 Outer 提供了这种功能. 它的一个作用是将两个向量结合形成一个矩阵作为外积:
用于将对应元素结合的函数最为第一个参数给出. 如下面的例子所示,它也可以是一个未知函数:

外积的可视化

Outer 的操作可视化的一种途径在这个例子中展示. 首先创建一列点:
这里显示 Outer 如何将每个点与其它任何一个点相连:

广义内积

矩阵乘法是线性代数计算的一项基础运算. 因此,Wolfram 语言提供了 Dot 作为一个极度优化的专用函数. 然而,广义的矩阵乘法由 Inner 提供. 这使得形成乘积的两种运算可以被明确指定.

这是两个向量:
这是一个作为乘积的标量:
这是使用 Inner 进行的等价运算:
现在使用的是 Power 而不是 Times

矩阵置换

许多矩阵技术依赖于对矩阵进行特殊方式的排序. 例如,有些技术试图对矩阵排序使得元素被放在对角线上,也有一些技术试图将某些元素组合到密集块上. Wolfram 语言函数 Part 非常适用于将置换作用于矩阵的行和列上.

m[[perm]]将置换作用在一个矩阵的行上
m[[All,perm]]将置换作用在一个矩阵的列上
m[[perm,perm]]将置换作用在一个矩阵的行与列上
m[[perm]]=m将逆置换作用在一个矩阵的行上
m[[All,perm]]=m将逆置换作用在一个矩阵的列上

对矩阵进行置换.

生成一个随机矩阵:

现在矩阵将被重新排列,使得各行按照2范数递增的次序排列.(有关范数的讨论见"矩阵计算:范数".)

首先计算每一行的范数:
这里计算得到的置换使得最小的数字放在第一位:
对矩阵的行进行排序:结果中各行按照2范数递增的顺序排列:
现在通过部分指定进行逆置换. 注意这样作改变了由符号 pmat 所代表的矩阵. 关于部分指定的介绍见前面
如果对置换后的矩阵应用逆置换,则原矩阵被恢复:

置换矩阵

另一种置换方式是通过乘法将置换作用于矩阵. 例如,这里生成一个4×4矩阵:
计算置换,使得各行按照2范数递增的顺序进行排序:
置换矩阵通常是一个稀疏矩阵,相关讨论见"稀疏数组的运用". 这个输入生成一个稀疏单位矩阵:
如果将置换应用于单位矩阵,则得到一个置换矩阵:
这里应用了置换. 注意具有最小范数的行在最顶部:
应用逆置换:

通常,使用 Wolfram 语言函数 Part 来应用一个置换速度较快,但有时采用置换矩阵会比较方便.