Sandra Silva
Sandra Silva

Reputation: 47

How to caculate an inverse of a matrix object without numpy

I've created a class Matrix and have to define some methods to do calculus over matrix.

def __init__(self, rows = 0, columns =0, data=None, code =''):
        if data is None:
            data = []
        self.code = ''
        self.rows = rows
        self.columns = columns
        self.data = data
        self.code = code
        self.matrix = [[]]
        assert self.columns != 0 and self.rows != 0
        if code == 'z':
            self.matrix = np.zeros([self.rows, self.columns], int)
        elif code == 'u':
            self.matrix = np.ones([self.rows, self.columns], int)
        elif code == 'i':
            self.matrix = np.identity(self.rows, int)
        else:
            if code == '' and len(self.data) != 0:
                self.matrix = np.reshape(self.data, (-1, self.columns))

    def __str__(self):
        return f'Matrix: {self.matrix}'

Now I'm struggling with inverse matrix. I cannot use numpy methods to do it.

I've created a method to get the minor matrix and a method to calculate a determinant. But I'm not getting the right code to calculate the determinant of a nxn matrix. How can I do it?

    def copy_matrix(self):
    rows = self.rows
    columns = self.columns
    new_matrix = np.zeros([rows,columns], int)
    for i in range(rows):
        for j in range(columns):
            new_matrix[i][j] = self.matrix[i][j]
    return new_matrix

def delete_row_column(self, i, j):
    rows = self.rows
    columns = self.columns
    return [[self.matrix[row][col] for col in range(columns) if col != j] for row in range(rows) if row != i]

def minor(self, i, j):
    matrix = self.delete_row_column(i,j)
    new_matrix = np.reshape(matrix, (-1, len(matrix)))
    while len(new_matrix) != 2:
        self.minor(i,j)
    return new_matrix

def det(self):
    assert self.rows == self.columns, "matrix should be square"
    order = len(self.matrix)
    # print(order)
    matrix = self.matrix
    if order == 2:
        determinant = (self.matrix[0][0] * self.matrix[1][1]) - (
                self.matrix[0][1] * self.matrix[1][0])  # ad - bc
        return determinant
    else:
        determinant = 0
        for i in range(order):
            coefficient = matrix[0][i]
            print(coefficient)
            if i % 2 != 1 and i % 2 != 0:
                coefficient *= -1
                print(self.minor(0, i))
            determinant += coefficient * self.det()
        return determinant

and obtained:

Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "C:/Users/sandr/PycharmProjects/Trabalho 2/teste2.py", line 105, in det
    determinant += coefficient * self.det()
  File "C:/Users/sandr/PycharmProjects/Trabalho 2/teste2.py", line 105, in det
    determinant += coefficient * self.det()
  File "C:/Users/sandr/PycharmProjects/Trabalho 2/teste2.py", line 105, in det
    determinant += coefficient * self.det()
  [Previous line repeated 984 more times]
  File "C:/Users/sandr/PycharmProjects/Trabalho 2/teste2.py", line 101, in det
    print(coefficient)
RecursionError: maximum recursion depth exceeded while calling a Python object

Upvotes: 1

Views: 254

Answers (1)

Rishabh Kumar
Rishabh Kumar

Reputation: 2430

The changes below should fix your determinant calculation.

Change-1 : In minor method

def minor(self, i, j):
    matrix = self.delete_row_column(i,j)
    new_matrix = np.reshape(matrix, (-1, len(matrix)))
    while len(new_matrix) != 2:
        self.minor(i,j)
    return Matrix(rows=self.rows-1,columns = self.columns-1,data=new_matrix)  #change 1  

Note : I have assumed class-name to be Matrix, change it to whatever class name you have in your code

Reason behind change 1:

minor should essentially return a new Matrix class instance, to perform instance specific tasks like calculating det on the smaller (minor) matrix (see change 3,4)

Change-2,3,4 in det method

def det(self):
        
    assert self.rows == self.columns, "matrix should be square"
    order = len(self.matrix)
    matrix = self.matrix
    if order == 2:
        determinant = (self.matrix[0][0] * self.matrix[1][1]) - (
                self.matrix[0][1] * self.matrix[1][0])  # ad - bc
        return determinant
    else:
        determinant = 0
        for i in range(order):
            coefficient = matrix[0][i]
            if i % 2 != 0:                                            #change 2
                coefficient *= -1
            minor = self.minor(0,i)                                   #change 3
            determinant += coefficient * minor.det()                  #change 4
        return determinant

Reason behind change 2:

Earlier you had a condition i%2 != 1 and i%2 != 0 . which meant execute this if block when remainder of i on division with 2 gives a remainder something other than 0 and 1, which in real integer math is never going to happen.

Reason behind change 3 and 4:

In accordance to change 1, the incoming Matrix class instance from minor method, is stored (in change 3) and its det method is called in change 4.

Upvotes: 2

Related Questions