对齐次线性方程组
{
a
11
x
1
+
a
12
x
2
+
⋯
+
a
1
n
x
n
=
0
a
21
x
1
+
a
22
x
2
+
⋯
+
a
2
n
x
n
=
0
⋯
⋯
⋯
a
m
1
x
1
+
a
m
2
x
2
+
⋯
+
a
m
n
x
n
=
0
(1)
\begin{cases}a_{11}x_1+a_{12}x_2+\cdots+a_{1n}x_n=0\\a_{21}x_1+a_{22}x_2+\cdots+a_{2n}x_n=0\\\quad\quad\quad\cdots\quad\cdots\quad\cdots\quad\\a_{m1}x_1+a_{m2}x_2+\cdots+a_{mn}x_n=0\end{cases}\tag{1}
⎩
⎨
⎧a11x1+a12x2+⋯+a1nxn=0a21x1+a22x2+⋯+a2nxn=0⋯⋯⋯am1x1+am2x2+⋯+amnxn=0(1)
至少有零解。若系数矩阵
A
\boldsymbol{A}
A的秩(即博文《消元法与矩阵初等变换》中定义的rowLadder函数算得的rank)rank
A
<
n
\boldsymbol{A}<n
A<n时,方程组有非零解
s
1
,
s
2
,
⋯
,
s
n
−
r
\boldsymbol{s}_1,\boldsymbol{s}_2,\cdots,\boldsymbol{s}_{n-r}
s1,s2,⋯,sn−r构成的基础解系,使得方程组的通解可表为
x
=
c
1
s
1
+
c
2
s
2
+
⋯
+
c
n
−
r
s
n
−
r
.
\boldsymbol{x}=c_1\boldsymbol{s}_1+c_2\boldsymbol{s}_2+\cdots+c_{n-r}\boldsymbol{s}_{n-r}.
x=c1s1+c2s2+⋯+cn−rsn−r.
其中
c
1
,
c
2
,
⋯
,
c
n
−
r
c_1,c_2,\cdots,c_{n-r}
c1,c2,⋯,cn−r为任意常数。也可以更一般地表示成
x
=
o
+
c
1
s
1
+
c
2
s
2
+
⋯
+
c
n
−
r
s
n
−
r
\boldsymbol{x}=\boldsymbol{o}+c_1\boldsymbol{s}_1+c_2\boldsymbol{s}_2+\cdots+c_{n-r}\boldsymbol{s}_{n-r}
x=o+c1s1+c2s2+⋯+cn−rsn−r,其中
o
\boldsymbol{o}
o表示零解。对非齐次线性方程组
{
a
11
x
1
+
a
12
x
2
+
⋯
+
a
1
n
x
n
=
b
1
a
21
x
1
+
a
22
x
2
+
⋯
+
a
2
n
x
n
=
b
2
⋯
⋯
⋯
a
m
1
x
1
+
a
m
2
x
2
+
⋯
+
a
m
n
x
n
=
b
n
(2)
\begin{cases}a_{11}x_1+a_{12}x_2+\cdots+a_{1n}x_n=b_1\\a_{21}x_1+a_{22}x_2+\cdots+a_{2n}x_n=b_2\\\quad\quad\quad\cdots\quad\cdots\quad\cdots\quad\\a_{m1}x_1+a_{m2}x_2+\cdots+a_{mn}x_n=b_n\end{cases}\tag{2}
⎩
⎨
⎧a11x1+a12x2+⋯+a1nxn=b1a21x1+a22x2+⋯+a2nxn=b2⋯⋯⋯am1x1+am2x2+⋯+amnxn=bn(2)
设其增广矩阵
B
=
(
A
,
b
)
\boldsymbol{B}=(\boldsymbol{A},\boldsymbol{b})
B=(A,b),若rank
A
\boldsymbol{A}
A<rank
(
A
,
b
)
(\boldsymbol{A},\boldsymbol{b})
(A,b)则方程组(2)无解。若rank
A
=
r
=
\boldsymbol{A}=r=
A=r=rank
(
A
,
b
)
(\boldsymbol{A},\boldsymbol{b})
(A,b),则方程组(2)必有解。设有一特解为
x
0
\boldsymbol{x}_0
x0(即
A
x
0
=
b
\boldsymbol{Ax}_0=\boldsymbol{b}
Ax0=b)。方程组(2)的导出组(1)的基础解系
s
1
,
s
2
,
⋯
,
s
n
−
r
\boldsymbol{s}_1,\boldsymbol{s}_2,\cdots,\boldsymbol{s}_{n-r}
s1,s2,⋯,sn−r,则方程组的通解为
x
=
x
0
+
c
1
s
1
+
c
2
s
2
+
⋯
+
c
n
−
r
s
n
−
r
(3)
\boldsymbol{x}=\boldsymbol{x}_0+c_1\boldsymbol{s}_1+c_2\boldsymbol{s}_2+\cdots+c_{n-r}\boldsymbol{s}_{n-r}\tag{3}
x=x0+c1s1+c2s2+⋯+cn−rsn−r(3)
如果将
o
\boldsymbol{o}
o视为齐次线性方程组(1)的特解,则方程组(1)和(2)在有解的情况下,通解具有相同的表示形式(3)。
利用博文《消元法与矩阵初等变换》中定义的消元过程函数rowLadder和回代过程函数simplestLadder,可定义如下的线性方程组的通解函数:
import numpy as np #导入numpy
def mySolve(A,b):
m,n=A.shape #系数矩阵结构
b=b.reshape(b.size, 1) #常量列向量
B=np.hstack((A, b)) #构造增广矩阵
r, order=rowLadder(B, m, n) #消元
X=np.array([]) #解集初始化为空
index=np.where(abs(B[:,n])>1e-10) #常数列非零元下标
nonhomo=index[0].size>0 #判断是否非齐次
r1=r #初始化增广矩阵秩
if nonhomo: #非齐次
r1=np.max(index)+1 #修改增广阵秩
solvable=(r>=r1) #判断是否可解
if solvable: #若可解
simplestLadder(B, r) #回代
X=np.vstack((B[:r,n].reshape(r,1), #特解
np.zeros((n-r,1))))
if r<n: #导出组基础解系
x1=np.vstack((-B[:r,r:n],np.eye(n-r)))
X=np.hstack((X,x1))
X=X[order]
return X
程序的第2~22行定义函数mySolve,参数A和b分别表示线性方程组(2)的系数矩阵
A
\boldsymbol{A}
A和常数矩阵
b
\boldsymbol{b}
b。
第3行读取2维数组A的shape属性表示的行数m(方程个数)和列数n(未知量个数)。第4行调用b的reshape方法将其设置为
n
×
1
n\times1
n×1的列矩阵。第5行调用numpy(第1行导入)的hstack函数将A和b横向连接成增广矩阵
(
A
,
b
)
(\boldsymbol{A},\boldsymbol{b})
(A,b)为数组B。
第6行调用博文《消元法与矩阵初等变换》中定义的函数rowLadder函数将B变换成与之等价的行阶梯阵并返回系数矩阵的秩r和未知量顺序order。第7行将解集X初始化为空数组。第8行调用numpy的where函数,计算变换后常数矩阵中非零元素的下标集合index。第9行根据index是否为空设置标志nonhomo:非空,即常数矩阵b有非零元素(b.size>0),为True;否则,即b的所有元素均为0,为False。第10行将增广矩阵的秩r1初始化为系数矩阵的秩r。第11~12行对非齐次方程组更新增广矩阵的秩r1:变换后b中最后非零元素的下标,因为Python中数组下标时从0开始编排,故还需加1。
第13行根据r与r2的大小比较算得线性方程组是否有解的标志solvable。第14~21行的if语句对有解方程组求解。具体而言,第15行调用博文《消元法与矩阵初等变换》中定义的simplestLadder函数将行阶梯矩阵B准换成最简行阶梯矩阵。第16~17截取行阶梯阵B中前r行最后一列(对应常数矩阵b)B[:r,n].reshape(n-r,1)与n-r个0构成的列矩阵(由numpy的zeros((n-r,1)))通过numpy的vstack函数纵向连接为特解。第18~20行的if语句构造解集X:第19行算得齐次方程组或非齐次方程组的导出组的基础解系x1:截取矩阵B的前r行后n-r列B[:r,r:n],取反后与numpy的eye函数生成的n-r阶单位阵纵向连接(调用numpy的vstack)成一个
n
×
(
n
−
r
)
n\times(n-r)
n×(n−r)矩阵。第20行调用hstack函数将x1连接到X的右方。21行用order调整解集X中各行顺序(使之符合未知量顺序)。
第22行将解集X返回,有3种情况:若方程组无解,返回的是空列表;方程组有唯一解,返回的是一个列矩阵;方程组有无穷多个解,齐次方程组的零解位于X首列,基础解系位于X的后n-r列;非齐次方程组的特解位于X的首列,后n-r列表示导出组的基础解系。
例1 利用上述程序定义的mySolve函数解齐次线性方程组
{
3
x
1
+
4
x
2
−
5
x
3
+
7
x
4
=
0
2
x
1
−
3
x
2
+
3
x
3
−
2
x
4
=
0
4
x
1
+
11
x
2
−
13
x
3
+
16
x
4
=
0
7
x
1
−
2
x
2
+
x
3
+
3
x
4
=
0
.
\begin{cases}3x_1+4x_2-5x_3+7x_4=0\\2x_1-3x_2+3x_3-2x_4=0\\4x_1+11x_2-13x_3+16x_4=0\\7x_1-2x_2+x_3+3x_4=0\end{cases}.
⎩
⎨
⎧3x1+4x2−5x3+7x4=02x1−3x2+3x3−2x4=04x1+11x2−13x3+16x4=07x1−2x2+x3+3x4=0.
import numpy as np #导入numpy
from fractions import Fraction as F #导入Fraction
np.set_printoptions(formatter= #设置输出数据格式
{'all':lambda x:str(F(x).limit_denominator())})
A=np.array([[3,4,-5,7], #系数矩阵
[2,-3,3,-2],
[4,11,-13,16],
[7,-2,1,3]],dtype='float')
b=np.array([0,0,0,0]) #常数矩阵
X=mySolve(A,b) #解方程
print(X)
程序的第5~9行按题设设置系数矩阵和常数矩阵。第10行调用mySolve函数解方程组,返回值赋予X。运行程序,输出
[[0 3/17 -13/17]
[0 19/17 -20/17]
[0 1 0 ]
[0 0 1 ]]
三列数据分别对应零解
(
0
0
0
0
)
\begin{pmatrix}0\\0\\0\\0\end{pmatrix}
0000
和基础解系
(
3
17
19
17
1
0
)
,
(
−
13
17
−
20
17
0
1
)
\begin{pmatrix}\frac{3}{17}\\\frac{19}{17}\\1\\0\end{pmatrix}\text{,}\begin{pmatrix}-\frac{13}{17}\\-\frac{20}{17}\\0\\1\end{pmatrix}
173171910
,
−1713−172001
。
例2 用Python解线性方程组
{
x
1
−
x
2
−
x
3
=
2
2
x
1
−
x
2
−
3
x
3
=
1
3
x
1
+
2
x
2
−
5
x
3
=
0
.
\begin{cases}x_1-x_2-x_3=2\\ 2x_1-x_2-3x_3=1\\ 3x_1+2x_2-5x_3=0 \end{cases}.
⎩
⎨
⎧x1−x2−x3=22x1−x2−3x3=13x1+2x2−5x3=0.
import numpy as np #导入numpy
from fractions import Fraction as F #导入Fraction
np.set_printoptions(formatter= #设置输出数据格式
{'all':lambda x:str(F(x).limit_denominator())})
A=np.array([[1,-1,-1], #系数矩阵
[2,-1,-3],
[3,2,-5]],dtype='float')
b=np.array([2,1,0]) #常数矩阵
X=mySolve(A,b) #解方程
print(X)
运行程序,输出
[[5]
[0]
[3]]
表示唯一解
(
x
1
x
2
x
3
)
=
(
5
0
3
)
\begin{pmatrix}x_1\\x_2\\x_3\end{pmatrix}=\begin{pmatrix}5\\0\\3\end{pmatrix}
x1x2x3
=
503
。
例3 用Python解线性方程组
{
4
x
1
+
2
x
2
−
x
3
=
2
3
x
1
−
x
2
+
2
x
3
=
10
11
x
1
+
3
x
2
=
8
\begin{cases}4x_1+2x_2-x_3=2\\3x_1-x_2+2x_3=10\\11x_1+3x_2\quad\quad=8\end{cases}
⎩
⎨
⎧4x1+2x2−x3=23x1−x2+2x3=1011x1+3x2=8。
import numpy as np #导入numpy
A=np.array([[4,2,-1], #系数矩阵
[3,-1,2],
[11,3,0]],dtype='float')
b=np.array([2,10,8]) #常数矩阵
X=mySolve(A,b) #解方程
print(X)
运行程序,输出
[]
表示无解。
例4 用Python解线性方程组
{
2
x
1
+
x
2
−
x
3
+
x
4
=
1
4
x
1
+
2
x
2
−
2
x
3
+
x
4
=
2
2
x
1
+
x
2
−
x
3
−
x
4
=
1
\begin{cases} 2x_1+x_2-x_3+x_4=1\\ 4x_1+2x_2-2x_3+x_4=2\\ 2x_1+x_2-x_3-x_4=1 \end{cases}
⎩
⎨
⎧2x1+x2−x3+x4=14x1+2x2−2x3+x4=22x1+x2−x3−x4=1。
import numpy as np #导入numpy
from utility import mySolve #导入mySolve
from fractions import Fraction as F #导入Fraction
np.set_printoptions(formatter= #设置输出数据格式
{'all':lambda x:str(F(x).limit_denominator())})
A=np.array([[2,1,-1,1], #系数矩阵
[4,2,-2,1],
[2,1,-1,-1]],dtype='float')
b=np.array([1,2,1]) #常数矩阵
X=mySolve(A,b) #解方程组
print(X)
运行程序,输出
[[1/2 1/2 -1/2]
[ 0 0 1]
[ 0 1 0]
[ 0 0 0]]
对应特解
x
0
=
(
x
1
x
2
x
3
x
4
)
=
(
1
2
0
0
0
)
\boldsymbol{x}_0=\begin{pmatrix}x_1\\x_2\\x_3\\x_4\end{pmatrix}=\begin{pmatrix}\frac{1}{2}\\0\\0\\0\end{pmatrix}
x0=
x1x2x3x4
=
21000
和导出组的基础解系
s
1
=
(
x
1
x
2
x
3
x
4
)
=
(
1
2
0
1
0
)
\boldsymbol{s}_1=\begin{pmatrix}x_1\\x_2\\x_3\\x_4\end{pmatrix}=\begin{pmatrix}\frac{1}{2}\\0\\1\\0\end{pmatrix}
s1=
x1x2x3x4
=
21010
,
s
2
=
(
x
1
x
2
x
3
x
4
)
=
(
−
1
2
1
0
0
)
\boldsymbol{s}_2=\begin{pmatrix}x_1\\x_2\\x_3\\x_4\end{pmatrix}=\begin{pmatrix}-\frac{1}{2}\\1\\0\\0\end{pmatrix}
s2=
x1x2x3x4
=
−21100
。
由例1、例2、例3和例4可见,此处定义的mySolve函数适用于解实数域ℝ上的各种情形的线性方程组。而numpy提供的solve函数只适用于可逆系数矩阵的特殊情形(见博文《解可逆系数矩阵线性方程组》)。
写博不易,敬请支持:
如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!
代码诚可贵,原理价更高。若为AI学,读正版书好。