Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python-用LU分解求解线性方程组的数值问题 信息_Python_Python 3.x_Numpy_Numerical Methods - Fatal编程技术网

Python-用LU分解求解线性方程组的数值问题 信息

Python-用LU分解求解线性方程组的数值问题 信息,python,python-3.x,numpy,numerical-methods,Python,Python 3.x,Numpy,Numerical Methods,操作系统:Manjaro Linux 开发环境:Spyder4(Python 3.7) Libs:Numpy 问题 嗨 我用以下三种方法编写了一些求解线性方程组的函数: LU分解 雅可比法 高斯-赛德尔法 程序运行得很好。然而,LU分解的结果让我感到困扰。 例如,如果我的矩阵A和向量b是 A = np.array([[10., -1., 2., 0.], [-1., 11., -1., 3.], [2., -1., 10., -1.],

操作系统:Manjaro Linux

开发环境:Spyder4(Python 3.7)

Libs:Numpy

问题 嗨

我用以下三种方法编写了一些求解线性方程组的函数:

  • LU分解
  • 雅可比法
  • 高斯-赛德尔法
  • 程序运行得很好。然而,LU分解的结果让我感到困扰。 例如,如果我的矩阵A和向量b是

    A = np.array([[10., -1., 2., 0.],
              [-1., 11., -1., 3.],
              [2., -1., 10., -1.],
              [0., 3., -1., 8.]])
    b = np.array([6., 25., -11., 15.])
    
    那么我的结果是

  • 卢:[0.95034091 1.67840909-0.9125 1.875]
  • 雅各比:[1.2.-1.1]
  • 高斯·塞德尔:[1.2.-1.1]
  • 正如你所看到的,LU给了我一个稍微不同的结果。这是一个舍入或截断错误的问题吗?如有任何建议或帮助,将不胜感激

    干杯


    编辑1: 我修复了这个问题,它只是LU分解期间代码中的一个bug。感谢大家的反馈


    共享代码如下:
    您的代码中有许多内容需要解决:

    • Python不需要;为了结束一行,python知道行何时结束。Python只使用;将两行代码放在同一物理行上。比如“x=7;打印(x)”
    • 如果在列表理解中不使用变量,则习惯上使用x。例如,[0表示范围(10)]。当然,python有更好的方法“[0]*10”
    • 我注意到您导入了numpy,但没有对numpy数组使用操作。这将大大改进您的代码(并使其更快),使其更易于阅读。例如,您可以一次写入和读取整行或整列。“矩阵[0,:]”(第1行),“矩阵[:,0]”(第1列)
    • 不需要在python中包含对象的长度,因为python会自动存储其对象的长度,这总是可以使用len()内置函数进行检索
    • 对于您的代码来说并不重要(因为您可能是为了练习而这样做的),但您可能已经知道,lu分解已经存在,例如scipy.linalg.lu()。事实上,快速检查linalg.lu(a,True)可以发现,您的L和U中都有bug
    • 看到您手动生成L和U矩阵,然后继续在L和U上使用np.linalg.inv(),这真的很奇怪。如果您愿意使用np.linalg.inv()函数,那么您的答案是一行,“np.linalg.inv(A)@b”。通常,人们会发现L和U更容易为X手动求解。找到L和U,然后使用numpy的反函数,有点达不到目的
    • 尽管python有时会有所帮助,但它并不要求您在创建对象之前在内存中留出空间。Python自动管理内存的创建和删除(无需创建空的零列表)
    • 点()只是python中手动访问“@”操作符的方法
    一些例子:

    import numpy as np
    from scipy import linalg
    
    def lu_dec_solver_v1(A,b):
        return np.linalg.inv(A) @ b
    
    def lu_dec_solver_v2(A,b):
        L, U  = linalg.lu(A,True)
        L_inv = np.linalg.inv(L)
        U_inv = np.linalg.inv(U)
        return U_inv @ (L_inv @ b)
    
    def lu_dec_solver_v3(A,b):
        U = A.copy()
        L = np.identity(len(A))
        for n in range(0,len(A)-1):
            for m in range(n+1,len(A)):
                L[m,n]  = U[m,n]/U[n,n]
                U[m,:] += -L[m,n]*U[n,:]
        L_inv = np.linalg.inv(L)
        U_inv = np.linalg.inv(U)
        return U_inv @ (L_inv @ b)
    

    如果您想自己实现LU分解,那么这段代码不需要任何外部库。我把它附加在这里,以防你只是想复制它

    def Abs(x):
        '''
        Input x  and you'll get the abs.
        '''
        #Not the best way, but it is an easy way to not use numpy
        return (x**2)**0.5
    
    
    def ind_max(row,N):
        '''
        Find the index of the maximum of a list (row) of lentgth N.
        '''
        _in=0
        _max=row[0]
        i=0
        while i<N:#the end of the row should be included (convension in how I use LUP..)
            if row[i]>_max:
                _max=row[i]
                _in=i
            i+=1
                
        return _in
    
    
    def Sum(List,N):
        '''
        Calculates the sum of a List of size N
        '''
        s=0
        for i in range(N):
            s+=List[i]
        return s
    
    
    def index_swap(A,index_1,index_2):
        '''
            index_swap takes an array and interchanges 
             A[index_1] with A[index_2].
             
             Example:
                 A=[0,1,2,3]
                 index_swap(A,0,2)
                 A
                 >>[2, 1, 0, 3]
        '''
        
        tmp=A[index_1]
        A[index_1]=A[index_2]
        A[index_2]=tmp
        
        
    def apply_permutations_vector(A,P,N):
        '''
        Applies the permutations given by P from LUP
        to a list A of length N, and returns the result.
        Example:
        A=[1,2,5,8,3]
        P=[2,4,0,3,1]
    
        apply_permutations_vector(A,P,5)
        >>[5, 3, 1, 8, 2]
        '''
        #that is, you make a list like this (P basically gives you the indices of A):)
        
        Ap=[A[ P[i] ] for i in range(N)]
    
        return Ap
        
    def apply_permutations_matrix(M,P,N):
        '''
        Applies the permutations given by P from LUP
        to a N*N array M of length N, and returns the result.
        
        M=[
        [ 0,  2,  2 , 3 , 5],
        [-3, -1,  1 , 5 , 9],
        [ 1, -1,  1 , 4 , 7],
        [ 1, -1,  1 , 0 , 2],
        [ 1, -1,  1 , 0 , 3]
        ]
    
        P=[2,0,1,4,3]
    
        apply_permutations_matrix(M,P,5)
        >>[
          [ 1, -1, 1, 4, 7],
          [ 0,  2, 2, 3, 5],
          [-3, -1, 1, 5, 9],
          [ 1, -1, 1, 0, 3],
          [ 1, -1, 1, 0, 2]
          ]
        '''
        Mp=[ [M[ P[i] ][j]for j in range(N)] for i in range(N) ]
        
    
        return Mp
    
    
    
    
    def LUP(M,N,_tiny=1e-20):
        U=[  [ M[i][j] for j in range(N)] for i in range(N) ]
        L=[  [ 0 if i!=j else 1 for j in range(N)] for i in range(N) ]
        #this is the "permutation vector". if it is e.g. [2 1 0 3] it means you make 0<->2
        P=[  i for i in range(N) ]
        
        for k in range(1,N):
            for i in range(k,N):
                #find the index of the maximum in column
                _col=[Abs(U[_r][k-1]) for _r in range(k-1,N)]
                
                #find the index of the maximum of _col
                # notice that the length of _col is N-(k-1)
                len_col=N-(k-1)
                pivot=ind_max( _col ,len_col) + k - 1 #convert the index of _col (it has a length of len_col) to the index of  a row of U   
                
                ##################################################
                #if you remove it, then you get a lot of infinities
                #it has to do with the fact that if U[pivot][k-1] <_tiny , then U[k-1][k-1] will be a zero, 
                #L[i][k-1] explodes. 
                #You are allowed to skip this i, then, because if U[pivot][k-1] <_tiny , then all U[i][k-1] are small!
                #Check that this is true by  uncommenting print(_col)
                if Abs(U[pivot][k-1]) < _tiny  :         
                    #print(_col)
                    break
                ###################################################
                #if the maximum is not at k-1, swap!
                if pivot != k-1 : 
                    # Permute rows k-1 and pivot in U
                    
                    index_swap(P,k-1,pivot)
                    
                    tmpU=[U[k-1][_r] for _r in range(k-1,N)]
                    
                    #print(U)
                    for _r in range(k-1,N):
                        U[k-1][_r]=U[pivot][_r]
                    #print(U)
                    for _r in range(k-1,N):
                        U[pivot][_r]=tmpU[_r-(k-1)]#again we have to convert the index of tmpU
                    #print(U)
                    #print("=========================")
                    tmpL=[L[k-1][_r] for _r in range(k-1)]
                    #print(L)
                    for _r in range(k-1):
                        L[k-1][_r]=L[pivot][_r]
                    #print(L)
                    for _r in range(k-1):
                        L[pivot][_r]=tmpL[_r]
                        
                    #print(L)
                    #print("========================")
                    
                L[i][k-1]=U[i][k-1]/U[k-1][k-1]
               
            
                for j in range(k-1,N):
                    U[i][j]=U[i][j]-L[i][k-1]*U[k-1][j]
    
                    
        return L,U,P
    
    
    def Abs(x):
    '''
    输入x,你就会得到abs。
    '''
    #这不是最好的方法,但这是一种不使用numpy的简单方法
    返回(x**2)**0.5
    def ind_max(第N行):
    '''
    查找lentgth N的列表(行)的最大值的索引。
    '''
    _in=0
    _最大值=行[0]
    i=0
    而我(马克斯):
    _最大值=行[i]
    _in=i
    i+=1
    返回
    定义和(列表,N):
    '''
    计算大小为N的列表的总和
    '''
    s=0
    对于范围(N)中的i:
    s+=列表[i]
    返回s
    def索引交换(A、索引1、索引2):
    '''
    索引交换采用数组并交换
    带[index_2]的[index_1]。
    例子:
    A=[0,1,2,3]
    指数交换(A,0,2)
    A.
    >>[2, 1, 0, 3]
    '''
    tmp=A[指数1]
    A[index_1]=A[index_2]
    A[index_2]=tmp
    定义应用置换向量(A,P,N):
    '''
    应用LUP中P给出的置换
    返回长度为N的列表,并返回结果。
    例子:
    A=[1,2,5,8,3]
    P=[2,4,0,3,1]
    应用置换向量(A,P,5)
    >>[5, 3, 1, 8, 2]
    '''
    #也就是说,你做了一个这样的列表(P基本上给出了a的索引):)
    Ap=[A[P[i]]表示范围(N)内的i]
    返回Ap
    def应用置换矩阵(M,P,N):
    '''
    应用LUP中P给出的置换
    到长度为N的N*N数组M,并返回结果。
    M=[
    [ 0,  2,  2 , 3 , 5],
    [-3, -1,  1 , 5 , 9],
    [ 1, -1,  1 , 4 , 7],
    [ 1, -1,  1 , 0 , 2],
    [ 1, -1,  1 , 0 , 3]
    ]
    P=[2,0,1,4,3]
    应用置换矩阵(M,P,5)
    >>[
    [ 1, -1, 1, 4, 7],
    [ 0,  2, 2, 3, 5],
    [-3, -1, 1, 5, 9],
    [ 1, -1, 1, 0, 3],
    [ 1, -1, 1, 0, 2]
    ]
    '''
    Mp=[[M[P[i][j]表示范围(N)中的j]表示范围(N)中的i]
    返回Mp
    def LUP(M,N,_-tiny=1e-20):
    U=[[M[i][j]表示范围(N)中的j]表示范围(N)中的i]
    L=[[0如果i!=j,则范围(N)中的j为1]范围(N)中的i为1]
    #这是“排列向量”。如果它是例如[2 1 0 3],则意味着您获得了02
    P=[i代表范围(N)内的i]
    对于范围(1,N)内的k:
    对于范围(k,N)内的i:
    #查找列中最大值的索引
    _col=[Abs(U[_-r][k-1]),表示范围(k-1,N)]
    #查找_col的最大值的索引
    #请注意_col的长度是N-(k-1)
    len_col=N-(k-1)
    pivot=ind_max(_col,len_col)+k-1#将_col的索引(长度为len_col)转换为一行U的索引
    ##################################################
    #如果你去掉它,你会得到很多无穷大
    
    #这与事实有关,如果U[pivot][k-1],我认为对于这种尺寸,舍入误差太大了
    def Abs(x):
        '''
        Input x  and you'll get the abs.
        '''
        #Not the best way, but it is an easy way to not use numpy
        return (x**2)**0.5
    
    
    def ind_max(row,N):
        '''
        Find the index of the maximum of a list (row) of lentgth N.
        '''
        _in=0
        _max=row[0]
        i=0
        while i<N:#the end of the row should be included (convension in how I use LUP..)
            if row[i]>_max:
                _max=row[i]
                _in=i
            i+=1
                
        return _in
    
    
    def Sum(List,N):
        '''
        Calculates the sum of a List of size N
        '''
        s=0
        for i in range(N):
            s+=List[i]
        return s
    
    
    def index_swap(A,index_1,index_2):
        '''
            index_swap takes an array and interchanges 
             A[index_1] with A[index_2].
             
             Example:
                 A=[0,1,2,3]
                 index_swap(A,0,2)
                 A
                 >>[2, 1, 0, 3]
        '''
        
        tmp=A[index_1]
        A[index_1]=A[index_2]
        A[index_2]=tmp
        
        
    def apply_permutations_vector(A,P,N):
        '''
        Applies the permutations given by P from LUP
        to a list A of length N, and returns the result.
        Example:
        A=[1,2,5,8,3]
        P=[2,4,0,3,1]
    
        apply_permutations_vector(A,P,5)
        >>[5, 3, 1, 8, 2]
        '''
        #that is, you make a list like this (P basically gives you the indices of A):)
        
        Ap=[A[ P[i] ] for i in range(N)]
    
        return Ap
        
    def apply_permutations_matrix(M,P,N):
        '''
        Applies the permutations given by P from LUP
        to a N*N array M of length N, and returns the result.
        
        M=[
        [ 0,  2,  2 , 3 , 5],
        [-3, -1,  1 , 5 , 9],
        [ 1, -1,  1 , 4 , 7],
        [ 1, -1,  1 , 0 , 2],
        [ 1, -1,  1 , 0 , 3]
        ]
    
        P=[2,0,1,4,3]
    
        apply_permutations_matrix(M,P,5)
        >>[
          [ 1, -1, 1, 4, 7],
          [ 0,  2, 2, 3, 5],
          [-3, -1, 1, 5, 9],
          [ 1, -1, 1, 0, 3],
          [ 1, -1, 1, 0, 2]
          ]
        '''
        Mp=[ [M[ P[i] ][j]for j in range(N)] for i in range(N) ]
        
    
        return Mp
    
    
    
    
    def LUP(M,N,_tiny=1e-20):
        U=[  [ M[i][j] for j in range(N)] for i in range(N) ]
        L=[  [ 0 if i!=j else 1 for j in range(N)] for i in range(N) ]
        #this is the "permutation vector". if it is e.g. [2 1 0 3] it means you make 0<->2
        P=[  i for i in range(N) ]
        
        for k in range(1,N):
            for i in range(k,N):
                #find the index of the maximum in column
                _col=[Abs(U[_r][k-1]) for _r in range(k-1,N)]
                
                #find the index of the maximum of _col
                # notice that the length of _col is N-(k-1)
                len_col=N-(k-1)
                pivot=ind_max( _col ,len_col) + k - 1 #convert the index of _col (it has a length of len_col) to the index of  a row of U   
                
                ##################################################
                #if you remove it, then you get a lot of infinities
                #it has to do with the fact that if U[pivot][k-1] <_tiny , then U[k-1][k-1] will be a zero, 
                #L[i][k-1] explodes. 
                #You are allowed to skip this i, then, because if U[pivot][k-1] <_tiny , then all U[i][k-1] are small!
                #Check that this is true by  uncommenting print(_col)
                if Abs(U[pivot][k-1]) < _tiny  :         
                    #print(_col)
                    break
                ###################################################
                #if the maximum is not at k-1, swap!
                if pivot != k-1 : 
                    # Permute rows k-1 and pivot in U
                    
                    index_swap(P,k-1,pivot)
                    
                    tmpU=[U[k-1][_r] for _r in range(k-1,N)]
                    
                    #print(U)
                    for _r in range(k-1,N):
                        U[k-1][_r]=U[pivot][_r]
                    #print(U)
                    for _r in range(k-1,N):
                        U[pivot][_r]=tmpU[_r-(k-1)]#again we have to convert the index of tmpU
                    #print(U)
                    #print("=========================")
                    tmpL=[L[k-1][_r] for _r in range(k-1)]
                    #print(L)
                    for _r in range(k-1):
                        L[k-1][_r]=L[pivot][_r]
                    #print(L)
                    for _r in range(k-1):
                        L[pivot][_r]=tmpL[_r]
                        
                    #print(L)
                    #print("========================")
                    
                L[i][k-1]=U[i][k-1]/U[k-1][k-1]
               
            
                for j in range(k-1,N):
                    U[i][j]=U[i][j]-L[i][k-1]*U[k-1][j]
    
                    
        return L,U,P