pythonmatrixmatrix-inverse

I have made a copy of the list , and have executed certain operations on it. But after a point the real matrix ,that is the list gets affected


Error while executing code to find inverse of a matrix (via gauss elimination using lists as arrays). To find the inverse using row operations, first I duplicated the matrix and attempted to swap rows in case of zero elements on the diagonals and then tried executing the function to make the lower triangular region of the matrix all 0, that is to convert into row echelon form. But at this point the code also affecting the original matrix. (Reason for keeping a copy of the matrix is to check the matrix A times its found inverse gives identity matrix)

I tried debugging and found where the operation affect the original matrix(spot quoted as comment in the code below). But still am unable to figure out where I have gone wrong. A fresh eye could really help.

    A = [[2,4], 
         [3,0]] 

    def inverse(A):
        A_id = A[:]       #appling operations on a copy of matrix A   
        A_id = squaremat(A_id)
        indentitymat=identity(A_id)

        return (lowertriangle(A_id,indentitymat))


    def squaremat(A_id):       
        for i in range(len(A_id)):          
            if len(A_id)!=len(A_id[i]):
                error="Sorry Matrix not invertible" # checks given matrix is a square matrix
                return error
                break
        return swap(A_id)

    def swap(A_id):
            for j in range(len(A_id)):            
                if j!=len(A_id)-1 and A_id[j][j]==0:     
                    Temp= A_id[j]  
                    A_id[j]=A_id[j+1]
                    A_id[j+1]=Temp  
                elif j == len(A_id)-1 and A_id[j][j]==0:
                    Temp1= A_id[0]
                    A_id[0]=A_id[j]
                    A_id[j]=Temp1
            for k in range(len(A_id)):
                if A_id[k][k]==0:
                    return swap(A_id)
            return A_id

    def identity(A_id):
        iden=[]
        for i in range(len(A_id)):
            iden.append([0]*len(A_id))
            iden[i][i]=1  
        return iden

    def lowertriangle(A_id,invert):
        print(A_id)
        for i in range(len(A_id)):
            divisor = A_id[i][i]
            for j in range(len(A_id)):
                if divisor!=0:
                    A_id[i][j]=A_id[i][j]/divisor # to make diagonal one 
                    invert[i][j]=invert[i][j]/divisor

            for p in range(len(A_id)):
                if p>i:
                    multiplier=A_id[p][i]
                    for k in range(len(A_id)):                   
                        A_id[p][k] = A_id[p][k] - multiplier*A_id[i][k] # to make the lower triangle all zero, (here the original matrix is being affected)
                        invert[p][k] = invert[p][k] - multiplier*invert[i][k]

        print(A)

        return uppertriangle(A_idlower,invert)

    def uppertriangle(A_idlower,invert):
        for i in range(len(A_idlower)):
            for j in range(len(A_idlower)):
                if j<i:
                    multiplier2= A_idlower[j][i]
                    for k in range(len(A_idlower)):
                        A_idlower[j][k] = A_idlower[j][k] - multiplier2*A_idlower[i][k]
                        invert[j][k] = invert[j][k] - multiplier2*invert[i][k]
        return invert



    print(inverse(A))

Solution

  • The problem is here:

    A_id = A[:]       #appling operations on a copy of matrix A
    

    This performs a shallow copy of A. In other words, it creates a new list with references to each row in the original list. But the rows are not themselves copied.

    To fix the problem, you need to create a deep copy of the original matrix instead. One way to do it is with a list comprehension:

    A_id = [row[:] for row in A]
    

    This will work in the specific case of the question here, but is still not a general solution for deep copying any arbitrarily nested list.