Search code examples
pythonrecursionmatrixdeterminants

Program to find determinant of a n x n matrix not working


when i give a 3X3 matrix as input,it returns index error at line: m[0][0]*m[1][1]-m[0][1]*m[1][0]

import copy

def matrixdeterminant(m):
    if len(m)==1:
        return m[0]
    elif len(m)==2:
        return m[0][0]*m[1][1]-m[0][1]*m[1][0]
    else:
        matrixdeterminantlist=copy.deepcopy(m)
        determinantlist=[]
        m.pop(0)

        for i in range(len(matrixdeterminantlist[0])):
            for j in range(len(m)):
                m[j].pop(i)
            determinantlist.append(matrixdeterminantlist[0][i]*matrixdeterminant(m)*(-1)**(i+2))

            m=copy.deepcopy(matrixdeterminantlist)
   
    return sum(determinantlist)

Solution

  • First issue I can spot: you wrote return m[0] rather than return m[0][0] for the case where len(m) == 1.

    If m is a 1x1 matrix, then m looks something like [[x]], and you want to return x, not [x], so you have to return m[0][0], not m[0].

    Another important issue in your code is the way you pop elements from m and then try to restore m from its copies. This is overly complicated and you restore m wrongly inside the loop, so at some points the dimensions of m are all screwed-up. I recommend to avoid using .pop at all, and instead, build the submatrices using list comprehensions.

    Here is a simplified version:

    def matrixdeterminant(m):
        if len(m)==1:
            return m[0][0]
        elif len(m)==2:
            return m[0][0]*m[1][1]-m[0][1]*m[1][0]
        else:
            determinantlist=[]
            sign = 1
            for i in range(len(m)):
                submatrix = [row[1:] for j,row in enumerate(m) if j != i]
                minor = matrixdeterminant(submatrix)
                determinantlist.append(sign * m[i][0] * minor)
                sign *= -1
            return sum(determinantlist)
    

    And here is yet another version:

    from itertools import cycle
    
    def matdet(m):
        if len(m) == 1:
            return m[0][0]
        else:
            return sum(
                s * mj[0] * matdet([row[1:] for i,row in enumerate(m) if i != j])
                for s,(j,mj) in zip(cycle([1,-1]), enumerate(m))
            )
    

    Once it's producing numerical values instead of error messages, I strongly encourage you to test your determinant function by comparing its output on big random matrices, against the output of a matrix determinant function from a standard python module such as numpy or sympy or scipy: