\(\LaTeX\)中绘制矩阵的基本语法是:1
2
3
4
5
6
7\left[
\begin{array}{ccc}
0 & y & \alpha \\
\omega g & x^2 & 5 \\
e^{i\pi} & ab & \omega \\
\end{array}
\right]
此外使用bmatrix
等环境也ok。这种语法对于小型矩阵比如例子中的\(3\times 3\)矩阵来说,是很方便的。然而对于比较大型的矩阵,比如\(12\times 12\)的矩阵,直接用\(\LaTeX\)来写就显得有点蛋疼了,光是实现有效编写大型\(\LaTeX\)矩阵的前提——&
对齐,就足以使人痛不欲生。如果能指定矩阵的逻辑,然后自动生成\(\LaTeX\)代码就好了!Python
的sympy
库就可以很好地完成这个任务。
举例来说,如果我要绘制一个\(12\times 12\)的矩阵,按中线分为四块,每一块有不同的逻辑,可以首先用sympy
构建这个矩阵:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import sympy as sp
dim = 12
x, y, z = sp.symbols('x, y, z')
matrix = sp.Matrix.zeros(dim, dim)
for i in range(dim):
for j in range(dim):
left = i < dim // 2
up = j < dim // 2
if left and up:
elem = x * y
elif left and not up:
elem = (-1) ** (i + j) * y
elif not left and up:
elem = z ** (i - j)
else:
elem = -z
matrix[i, j] = elem
sympy
操作矩阵的语法和常见的numpy
相似而又有所不同,不同之处在这一小段代码中体现在两个方面。
- 调用
zeros
方法初始化一个矩阵元都是0的矩阵时,numpy
要求把矩阵大小写在一个tuple
里,而sympy
中没有这个要求。其原因是sympy
中的Matrix
都是只有两个指标的,而numpy
中的ndarray
可能有多个指标。实际上对于方阵sympy
的zeros
方法可以只接受一个参数,numpy
如果也这么做就显得意义不明。 - 操作矩阵元时
sympy
需要将两个指标写在同一个中括号内,比如m[0, 0]
,而numpy
需要两个(依据指标数量而定)的中括号,比如m[0][0]
。numpy
的逻辑是每一个中括号都取出了矩阵的一个特定维度,比如m[0]
就取出了第一行,然后取出第一行第一列m[0][0]
就显得很自然。而sympy
中m[0]
就直接取出了矩阵第一个元素即第一行第一列,至于m[0][0]
则是对矩阵元做index了,大多数情况下是未定义的。这么来看好像numpy
的接口要好一些,其实不然。numpy
在做多维数组切片的时候还是要回到把指标都放在同一个中括号内的写法,否则永远只能对第一个维度做切片,相当于对indexing做了两套接口,对初学者来说还是有点confusing的。所以这两套接口哪个更优可能是见仁见智的问题。
言归正传,在获得sympy
矩阵m
后,接下来执行:1
print(sp.printing.latex(matrix))
就可以得到如下输出,即我们所绘制矩阵的\(\LaTeX\)代码:1
\left[\begin{array}{cccccccccccc}x y & x y & x y & x y & x y & x y & y & - y & y & - y & y & - y\\x y & x y & x y & x y & x y & x y & - y & y & - y & y & - y & y\\x y & x y & x y & x y & x y & x y & y & - y & y & - y & y & - y\\x y & x y & x y & x y & x y & x y & - y & y & - y & y & - y & y\\x y & x y & x y & x y & x y & x y & y & - y & y & - y & y & - y\\x y & x y & x y & x y & x y & x y & - y & y & - y & y & - y & y\\z^{6} & z^{5} & z^{4} & z^{3} & z^{2} & z & - z & - z & - z & - z & - z & - z\\z^{7} & z^{6} & z^{5} & z^{4} & z^{3} & z^{2} & - z & - z & - z & - z & - z & - z\\z^{8} & z^{7} & z^{6} & z^{5} & z^{4} & z^{3} & - z & - z & - z & - z & - z & - z\\z^{9} & z^{8} & z^{7} & z^{6} & z^{5} & z^{4} & - z & - z & - z & - z & - z & - z\\z^{10} & z^{9} & z^{8} & z^{7} & z^{6} & z^{5} & - z & - z & - z & - z & - z & - z\\z^{11} & z^{10} & z^{9} & z^{8} & z^{7} & z^{6} & - z & - z & - z & - z & - z & - z\end{array}\right]
这段代码放在equation
环境里编译即可得到:
比起手写来显然让人愉悦得多了~
题外话,如果我们再引入\(\LaTeX\)的arydshln
包,对sympy
输出的\(\LaTeX\)代码做点小修改:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17\left[\
begin{array}{cccccc;{2pt/2pt}cccccc}
x y & x y & x y & x y & x y & x y & y & - y & y & - y & y & - y\\
x y & x y & x y & x y & x y & x y & - y & y & - y & y & - y & y\\
x y & x y & x y & x y & x y & x y & y & - y & y & - y & y & - y\\
x y & x y & x y & x y & x y & x y & - y & y & - y & y & - y & y\\
x y & x y & x y & x y & x y & x y & y & - y & y & - y & y & - y\\
x y & x y & x y & x y & x y & x y & - y & y & - y & y & - y & y\\
\hdashline[2pt/2pt]
z^{6} & z^{5} & z^{4} & z^{3} & z^{2} & z & - z & - z & - z & - z & - z & - z\\
z^{7} & z^{6} & z^{5} & z^{4} & z^{3} & z^{2} & - z & - z & - z & - z & - z & - z\\
z^{8} & z^{7} & z^{6} & z^{5} & z^{4} & z^{3} & - z & - z & - z & - z & - z & - z\\
z^{9} & z^{8} & z^{7} & z^{6} & z^{5} & z^{4} & - z & - z & - z & - z & - z & - z\\
z^{10} & z^{9} & z^{8} & z^{7} & z^{6} & z^{5} & - z & - z & - z & - z & - z & - z\\
z^{11} & z^{10} & z^{9} & z^{8} & z^{7} & z^{6} & - z & - z & - z & - z & - z & - z
\end{array}
\right]
就可以让分块的结构更加清晰: