线性代数Python计算:线性方程组的通解

本文介绍了齐次和非齐次线性方程组的解的性质,包括秩、基础解系和通解的概念。当系数矩阵的秩小于未知量个数时,方程组有非零解。对于非齐次线性方程组,如果系数矩阵的秩等于增广矩阵的秩,则方程组有解。通过Python实现了一个名为mySolve的函数,利用消元法和回代法求解线性方程组,能够处理无解、唯一解和无穷多解的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述
对齐次线性方程组
{ 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=0am1x1+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,,snr构成的基础解系,使得方程组的通解可表为
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++cnrsnr.
其中 c 1 , c 2 , ⋯   , c n − r c_1,c_2,\cdots,c_{n-r} c1,c2,,cnr为任意常数。也可以更一般地表示成 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++cnrsnr,其中 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=b2am1x1+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,,snr,则方程组的通解为
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++cnrsnr(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×(nr)矩阵。第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+4x25x3+7x4=02x13x2+3x32x4=04x1+11x213x3+16x4=07x12x2+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 1713172001
例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}. x1x2x3=22x1x23x3=13x1+2x25x3=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+2x2x3=23x1x2+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+x2x3+x4=14x1+2x22x3+x4=22x1+x2x3x4=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学,读正版书好

### 线性代数中的通解与特解 在线性代数中,对于线性方程组 \( Ax=b \),其求解过程涉及到找到满足该系统的特定解(即特解),以及描述所有可能解的一般形式(即通解)。当讨论的是齐次线性方程组\(Ax=0\)时,任何非零解都称为这个方程的一个基础解系的一部分;而非齐次线性方程组则不仅有特解还有对应于齐次部分的基础解系构成的通解。 #### 非齐次线性方程组的特解 为了获得非齐次线性方程组 \( Ax=b \) 的一个特解,可以直接应用数值方法来计算。例如,在Python环境中利用`scipy.linalg.solve`函数能够方便地得到这样的特解[^2]: ```python from scipy.linalg import solve A = [[3, 2], [-1, 5]] b = [7, -4] solution_particular = solve(A, b) print(solution_particular) ``` #### 对应齐次方程组的通解 针对给定矩阵 \( A \),可以通过寻找它的核空间或者说是零空间内的向量来构建齐次方程组 \( Ax=0 \) 的基本解集。这些向量形成的空间维度等于未知变量数目减去秩(rank)的数量。一旦获得了基础解系,则整个解空间可通过将各个基底按不同系数组合而成。假设已知一组基底\[v_1,v_2,\ldots , v_k\],那么通解可表示为: \[x_c=c_1v_1+c_2v_2+\cdots +c_kv_k\] 这里 \( c_i \in R \)(实数域), 并且每一个\(v_j(j=1,...k)\)都是齐次方程组的一个独立解。 因此,完整的解表达式将是上述两者的叠加——即将特解加上由齐次方程组产生的任意多个自由度所组成的通解: \[x=x_p+x_c=solution\_particular+c_1v_1+c_2v_2+\cdots +c_kv_k\] 其中 \( x_p \) 表示通过 `solve()` 函数获取到的那个具体的特解矢量。 #### 示例说明 考虑到具体例子,比如下面给出的简单情况下的非齐次线性方程组: \[ \begin{cases} 3x+2y &=& 7\\ -x+5y & =&-4 \\ \end{cases} \] 使用之前提到的方法先算得特解之后再考虑如何处理相应的齐次问题即可得出最终答案。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值