目录
1 线性方程组分类
2 线性方程组解的情况和对应条件
2.1 齐次线性方程组
2.2 非齐次方程
3 线性方程组求解——Python
3.1 齐次线性方程
3.2 非齐次方程
1 线性方程组分类
线性方程组按常数项是否为0可分为:齐次线性方程组Ax=0和非齐次方程组Ax=b。
线性方程组按照方程个数和未知数个数的比较结果可分为:超定方程、欠定方程、适定方程。超定方程指方程个数大于未知数个数;欠定方程指方程个数小于未知数个数;适定方程指的是方程个数等于未知数个数。
2 线性方程组解的情况和对应条件
2.1 齐次线性方程组
齐次线性方程组可表示为:
,A为m×n的矩阵
从上式可以看出,齐次线性方程组一定有解,即零解。所以齐次线性方程组的解有两种情况:① 只有零解;② 有非零解。
通用判定条件:
如果R(A)=n,则只有零解;
如果R(A)<n,则有非零解。
如果A是方阵,还可以采用行列式来进行判定(行列式为0时,一定不是满秩,即R(A)<n):
如果
,只有零解;
如果
,有非零解。
2.2 非齐次方程
齐次方程可表示为:
,A为m×n的矩阵
非齐次方程的解有三种情况:① 无解;② 唯一解;③ 无穷解。
通用判定条件:
如果R(A)<R(A:b),则无解;
如果R(A)=R(A:b)=n,则有唯一解;
如果R(A)=R(A:b)<n,则有无穷解。
注:文中(A:b)均表示增广矩阵
3 线性方程组求解——Python
无论是齐次方程还是非齐次方程求解之前都需要判断方程解的情况,然后再求解。
3.1 齐次线性方程
① R(A)=n,此时方程只有零解,即x=0;
② R(A)<n,方程有非零解,即无穷解,方程组的通解可表示为基础解系的线性组合基础解系中含有的向量个数为n-R(A)。在Python中可以通过求解A的化零矩阵求出方程组的特解,如果求得的向量个数大于1,取其中一列即为方程的一个特解。
化零矩阵:对于非满秩矩阵A,若存在矩阵X使 A∗X = 0 ,且 X∗X= I ,即X不等于0,则称矩阵X为矩阵A的化零矩阵.
Python代码如下:
import numpy as np
import scipy
A=np.array([[1,1,1,1,1],[3,2,1,1,-3],[0,1,2,2,6],[5,4,3,3,-1]]) #创建矩阵A
m=A.shape[0] #行数
n=A.shape[0] #列数
rank_A=np.linalg.matrix_rank(A) #求解A的秩,rank(A)
print(f"rank_A={rank_A},n={n}")
if rank_A==n: #判断解的情况
print("ran(A)=n,方程只有零解")
x = np.zeros(m)
print(f"x={x}")
else:
print("ran(A)<n,方程有非零解")
x=scipy.linalg.null_space(A) #求解A的化零矩阵x,特解
x=x[:,1][:,np.newaxis] #取其中的任意一列即为方程的一个特解
print(f"x={x}")
result=A@x #验证解的正确性
print(f"Ax={result}")
测试用例是有非零解的方程,运行结果如下:
rank_A=2,n=4
ran(A)<n,方程有非零解
x=[[-0.10532109]
[-0.66853066]
[ 0.49682248]
[ 0.49682248]
[-0.21979321]]
Ax=[[ 1.11022302e-16]
[ 1.11022302e-15]
[-8.88178420e-16]
[ 1.38777878e-15]]
3.2 非齐次方程
① R(A)=R(A:b)=n,有唯一解,即
。② R(A)=R(A:b)<n,有无穷多个解,通解可由齐次方程组的通解和非齐次方程组的一个特解表示。在Python可以求A的逆矩阵来求得一个特解,即
。③ R(A)<R(A:b),无解。这种情况在Python里面可以求解出线性方程组的最小二乘解。对于线性方程组,如果存在
,使得
最小,则称
为线性方程组的最小二乘解。
Python代码如下:
import numpy as np
import scipy
A=np.array([[1,2,3,4],[2,2,1,1],[2,4,6,8],[4,4,2,2]]) #创建矩阵A
b=np.array([[1],[3],[2],[6]]) #矩阵b
C=np.append(A,b,axis=1) #增广矩阵
m=A.shape[0] #行数
n=A.shape[0] #列数
rank_A=np.linalg.matrix_rank(A) #求解A的秩,rank(A)
rank_C=np.linalg.matrix_rank(C) #求增广矩阵(A:b)的秩,rank(A:b)
print(f"rank_A={rank_A},rank_C={rank_C},n={n}")
if rank_A==rank_C==n: #判断解的情况
print("ran(A)=rank(C)=n,方程有唯一解")
x=np.linalg.inv(A)@b #逆矩阵求解,A^-1*B
print(f"x={x}")
elif rank_A==rank_C<n:
print("ran(A)=rank(C)<n,方程有无穷解")
x=np.linalg.pinv(A)@b #可以得到一个特解
print(f"x={x}")
else:
print("ran(A)<rank(C),方程有无解")
x=np.linalg.pinv(A)@b #求解方程的最小二乘解,是一个近似解
print(f"x={x}")
result=A@x-b #验证解的正确性
print(f"Ax-b={result}")
从代码可以看出无论是哪种情况,对于非齐次线性方程组来说都可以采用的这条代码来进行求解。
测试用例采用的是有无穷解的方程,运行结果如下:
rank_A=2,rank_B=2,n=4
ran(A)=rank(B)<n,方程有无穷解
x=[[ 0.95419847]
[ 0.73282443]
[-0.07633588]
[-0.29770992]]
Ax-b=[[ 2.22044605e-16]
[-8.88178420e-16]
[ 4.44089210e-16]
[-1.77635684e-15]]
有兴趣的可以采用其它测试用例(无解、唯一解)来测试代码的运行结果。