简体   繁体   中英

Python 3 - IndexError: list index out of range when trying to find determinant of a matrix

I am trying to find determinant with a nested list representing a two-dimensional matrix. But it is infinitely calling the getMinor() function and continuously deleting from the same list, which should not happend because I am creating new list every time. Below is the code. Also all the functions are defined in a class named 'Matrix()'.

def __init__(self):
    self.matrix_list = []
    self.no_of_row = 0
    self.no_of_col = 0

def getMinor(self, matrix, j):
    del matrix[0]
    for i in range(len(matrix)):
        del matrix[i][j]

    m = Matrix()
    m.matrix_list = matrix[:]
    m.no_of_row = len(m.matrix_list)
    #print(m.no_of_row)
    print(m.matrix_list)
    m.no_of_col = len(m.matrix_list[0])
    return m.detMatrix()

def detMatrix(self):
    if self.no_of_row == 2 and self.no_of_col == 2:
        return self.matrix_list[0][0] * self.matrix_list[1][1] - self.matrix_list[0][1] * self.matrix_list[1][0]
    else:
        matrix = self.matrix_list[:]
        det = 0
        for i in range(self.no_of_col):
            det += ((-1)**i) * self.matrix_list[0][i] * self.getMinor(matrix, i)
        return det

You have two problems. One is alluded to by user2357112 who unfortunately didn't bother to explain. When you use the expression x[:] you get a shallow copy of the list x. Often there is no practical difference between deep and shallow copies; for example if x contains numbers or strings. But in your case the elements of x are lists. Each element of the new list, x[:], will be the same sub-list that was in the original x - not a copy. When you delete one element of those nested lists (del matrix[i][j]), you are therefore deleting some of your original data.

The second problem is that you aren't handling the recursion properly. You create a new variable, matrix, in the function detMatrix. Even if you make a deep copy here, that won't fix the problem. You pass matrix to getMinor, which deletes some data from it. Now in the next step through your for loop, you have messed up the data. You need to make a deep copy inside the function getMinor.

Here is a program that runs, at least. I didn't check your algebra :-)

I will also add that it's very inefficient. The idea of making a copy and then deleting pieces from the copy doesn't make much sense. I didn't address this.

import copy
class Matrix:
    def __init__(self):
        self.matrix_list = []
        self.no_of_row = 0
        self.no_of_col = 0

    def getMinor(self, matrix_list, j):
        print("Entry:", matrix_list)
        matrix = copy.deepcopy(matrix_list)
        del matrix[0]
        for i in range(len(matrix)):
            del matrix[i][j]
        print("After deletions", matrix_list)

        m = Matrix()
        m.matrix_list = matrix[:]
        m.no_of_row = len(m.matrix_list)
        m.no_of_col = len(m.matrix_list[0])
        x = m.detMatrix()
        print(m.matrix_list, m.no_of_row, m.no_of_col)
        return x

    def detMatrix(self):
        if self.no_of_row == 2 and self.no_of_col == 2:
            return self.matrix_list[0][0] * self.matrix_list[1][1] - self.matrix_list[0][1] * self.matrix_list[1][0]
        else:
            det = 0
            for i in range(self.no_of_col):
                det += ((-1)**i) * self.matrix_list[0][i] * self.getMinor(self.matrix_list, i)
            return det

m = Matrix()
m.matrix_list.append([0.0,1.0,2.0,3.0])
m.matrix_list.append([1.0,2.0,3.0,4.0])
m.matrix_list.append([2.0,3.0,4.0,5.0])
m.matrix_list.append([3.0,5.0,7.0,9.0])
m.no_of_row = 4
m.no_of_col = 4

print(m.detMatrix())

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM