数值分析之三角分解法求线性方程组

@数值分析之线性方程组AX=B求解

一、三角分解法

问:高斯偏序选主元、上三角回代解法已经可以解一切线性方程组,为什么还要三角分解法呢?
答:如果是单独处理一个方程组,三角分解和高斯分解的区别只是,三角分解保存了分解因子但如果多次求解某个系数矩阵A相同,列矩阵B不同的方程组,就省去三角分解过程。同时A可以直接使用,节省了资源。

1.1 三角分解法

三角分解法:A = LU,AX=B,即LUX=B,令Y=UX,即LY=B,先前向替代求解Y,在回代求解X。该算法关键是将A拆分为下三角L(L(k,k)=1)和上三角U的矩阵乘,在分解A的过程中,将分解因子L、U保存在一个矩阵R中,只保存L的非0非1部分,U的非0部分。
为了避免和高斯消去同样的问题,三角分解法也采用偏序选主元策略,只是在变换A的过程中,还要保存行变换信息

1.2 matlab算法

在这里插入图片描述

二、题目

2.1 题目

为求解一个线性方程组,首先采用偏序选主元策略的三角分解法构造矩阵L,U和P,再用前向替换法对方程组LY=PB求解Y,最后用回代法对方程组UX=Y求解X。

2.2 输入输出格式

【输入形式】在屏幕上依次输入方阵阶数n,系数矩阵A和常数矩阵B。

【输出形式】先输出LU分解结果,再输出方程解。

2.3 样例

输入

4
1 2 4 1
2 8 6 4
3 10 8 8
4 12 10 6
21
52
79
82

输入说明:输入:第1行为方阵阶数4,第2行至5行为系数矩阵A,第6行至9行为常数矩阵B。

输出

[[ 4. 12. 10. 6. ]
[ 0.5 2. 1. 1. ]
[ 0.25 -0.5 2. 0. ]
[ 0.75 0.5 0. 3. ]]
[[1.]
[2.]
[3.]
[4.]]

输出说明:第1至第4行输出LU分解结果,,第5行至第8行依次输出方程解:x1, x2, x3, x4。

2.4 思路和要点

(1)要注意,三角分解法与高斯消去不同。高斯分解采用偏序选主元时,是对[A|B]增广矩阵变换,而三角分解法只对A行交换。所以在A交换行时,要保存交换行索引,便于解下三角矩阵时,找到B中的对应行。
(2)三角分解的核心在于构建这个分解因子——两个三角矩阵,在代码中,我将两个矩阵合在了一个矩阵中,也就是LU分解结果。只保存了上三角非0的部分和下三角中非1非0的部分。同时因为互不干扰,为了节省内存,可以将LU保存在A上。

2.5 代码

import numpy as np

def lufact(A,R):
    n = len(A)
    for i in range(n):# 对i列处理
        row = np.argmax(abs(A[i:,i]))
        A[[i, row+i], :] = A[[i+row, i], :]
        R[i],R[row+i] = R[row+i],R[i]
        #因为交换的只是系数矩阵A的行,所以将A中行交换的信息保存,使得与B匹配
        #每次交换行并不影响X的值的顺序,保证了backsub时不用考虑行交换
        for k in range(i+1,n):  #对第k行处理
            m = A[k,i]/A[i,i]
            A[k,i] = m
            temp = m*A[i,i+1:]
            A[k,i+1:] =A[k,i+1:] -  temp
    return A

def forsub(A,B,R,Y):#下三角前向替代
    n = len(Y)
    Y[0] = B[R[0]]
    for i in range(1,n):
        temp = np.reshape(A[i,0:i],(1,len(Y[0:i]))).dot(Y[0:i])
        Y[i] = B[R[i]]-temp
    return Y

def backsub(A, X): #上三角回代求解
    #因为每一位处理后的Y都能得到对应位的x,所以可以在X矩阵中替换,节省资源
    n = len(X)
    X[n - 1] = X[n - 1] / A[n - 1, n - 1]
    for i in range(n - 2, -1, -1):
        temp = np.reshape(A[i, i + 1:], (1, len(X[i + 1:]))).dot(X[i + 1:])
        # 截断的A虽然看似可以和X想点乘,但是程序会判断为形状不同,所以要重新赋予形状
        X[i] = (X[i] - temp) / A[i, i]
    return X
    
def main():
    n = int(input())
    A = np.zeros([n,n],dtype = np.double)
    B = np.zeros([n,1],dtype = np.double)
    X = np.zeros([n,1],dtype = np.double)
    R = np.arange(n)  #A发生行交换后保存交换的行索引,使得与B匹配
    for i in range(n):
        A[i,:] = np.array(input().split(),dtype = np.double)
    for i in range(n):
        B[i] = np.array(input(),dtype = np.double)
    lufact(A,R)
    forsub(A,B,R,X)
    backsub(A,X)
    print(A)
    print(X)
    
if __name__ == '__main__':
    main()    

2.6 结果

样例:
在这里插入图片描述

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: b'lu\xe5\x88\x86\xe8\xa7\xa3\xe6\xb3\x95\xe6\xb1\x82\xe7\xba\xbf\xe6\x80\xa7\xe6\x96\xb9\xe7\xa8\x8b\xe7\xbb\x84\xe9\x80\x9a\xe7\x94\xa8\xe7\xa8\x8b\xe5\xba\x8f matlab' 是用 matlab 语言编写的一种组件通用程序,其作用是实现 b'lu' 分解法求线性方程组,可用于矩阵运算、数值计算等方面。 ### 回答2: LU分解法是一种解决线性方程组的方法,可以将线性方程组的系数矩阵分解为一个下三角矩阵和一个上三角矩阵的乘积,从而简化方程组的求解。 在matlab中,我们可以编写一个通用的程序来实现LU分解法: 1.定义输入矩阵A和常数向量b。这里假设输入的矩阵A是一个方阵。 2.进行LU分解。具体方法是使用matlab自带的lu函数,该函数会将输入的矩阵A分解为一个下三角矩阵L和一个上三角矩阵U。 3.解方程组。对于方程组Ax=b,我们首先需要将其转化为LUx=b,然后进行两步,分别是先解Ly=b,再解Ux=y,即可得到方程组的解x。 4.输出结果。输出求解得到的x向量,即方程组的解。 以下是该程序的matlab代码: function x = lu_solve(A,b) [n,m] = size(A); assert(n == m); [L,U] = lu(A); %LU分解 y = zeros(n,1); %解Ly=b for i=1:n y(i) = b(i); for j=1:i-1 y(i) = y(i) - L(i,j)*y(j); end end x = zeros(n,1); %解Ux=y for i=n:-1:1 x(i) = y(i); for j=i+1:n x(i) = x(i) - U(i,j)*x(j); end x(i) = x(i) / U(i,i); end end 使用该程序时,只需要将输入矩阵A和常数向量b输入即可调用该函数。该程序可以解决任意大小的线性方程组,具有广泛的适用性。 ### 回答3: LU分解法是求解线性方程组的一种方法,它将矩阵A分解成一下两个矩阵的乘积:L和U,其中L为下三角矩阵,U为上三角矩阵,同时这两个矩阵的乘积等于原矩阵A,用其解方程组时可以分别解Lz=b,Ux=z,即可得出方程组的解x。 在MATLAB中,我们可以使用lu(A)命令求解线性方程组的LU分解法,其中A为系数矩阵,返回值为一个元胞数组,其中第一个元素为下三角矩阵L,第二个元素为上三角矩阵U,而且在上三角矩阵中主对角线上的元素为1。具体用法如下: [l,u] = lu(A); z = l\b; x = u\z; 其中b为方程组右边的常数向量。这样,我们就可以得到方程组的解x了。 同时,MATLAB中还提供了矩阵分解后直接求解的命令,即x = A\b,这样可以更加方便地求解线性方程组。 总的来说,MATLAB中求解LU分解法的通用程序非常简单,只需使用lu(A)命令求解L和U矩阵,然后再进行分别解Lz=b和Ux=z的计算即可。同时,MATLAB还提供了其他多种求解线性方程组的方法,如高斯消元法和QR分解法等,用户可以根据实际情况选择合适的方法进行求解。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值