Determinants of Matrices

Hawkeye Python 0 Tallied Votes 3K Views Share

Hello :) I'm from Brazil, so sorry about my english.

This is the first code I post here - I'm a begginer in Python. It is a function to calculate determinants of matrices. You can attach it to a class if you wish.

Please leave a comment if you wish about what could be improved in the code. Thanks!

#
#   det(x):
#       x = Matrix Order
#       x can be 2, 3 or 4
#
#       Supports negatives and decimals
#

def det(x):
    if not x == 2 or x == 3 or x ==4:
        print 'Supports only 2x2, 3x3 and 4x4 matrices.'
        x = input('Order = ')
        print ''
    result_msg = 'The determinant of'
    if x == 2 or x == 3:
        print 'You choosed a matrix of order 2 or 3.'
        print 'Just fill the extra lines with any numbers'
        print 'They wont be calculated.'
        print ''
    print 'Do not use fractions. Use decimals.'
    print ''
    print 'Separete the elements following the example below:'
    print 'w, x, y, z'
    print ''
    l0 = input("Line 1: ")
    l1 = input("Line 2: ")
    l2 = input("Line 3: ")
    l3 = input("Line 4: ")
    m00 = l0[0]
    m01 = l0[1]
    if x == 3 or x == 4:
        m02 = l0[2]
        if x == 4:
            m03 = l0[3]
    m10 = l1[0]
    m11 = l1[1]
    if x == 3 or x == 4:
        m12 = l1[2]
        if x == 4:
             m13 = l1[3]
    m20 = l2[0]
    m21 = l2[1]
    if x == 3 or x == 4:
        m22 = l2[2]
        if x == 4:
            m23 = l2[3]
    m30 = l3[0]
    m31 = l3[1]
    if x == 3 or x == 4:
        m32 = l3[2]
        if x == 4:
            m33 = l3[3]
            det = m03 * m12 * m21 * m30 - m02 * m13 * m21 * m30 - m03 * m11 * m22 * m30+m01 * m13 * m22 * m30 + m02 * m11 * m23 * m30-m01 * m12 * m23 * m30 - m03 * m12 * m20 * m31+m02 * m13 * m20 * m31 + m03 * m10 * m22 * m31-m00 * m13 * m22 * m31 - m02 * m10 * m23 * m31+m00 * m12 * m23 * m31 + m03 * m11 * m20 * m32-m01 * m13 * m20 * m32 - m03 * m10 * m21 * m32+m00 * m13 * m21 * m32 + m01 * m10 * m23 * m32-m00 * m11 * m23 * m32 - m02 * m11 * m20 * m33+m01 * m12 * m20 * m33 + m02 * m10 * m21 * m33-m00 * m12 * m21 * m33 - m01 * m10 * m22 * m33+m00 * m11 * m22 * m33
            print ''
            print result_msg
            print l0
            print l1
            print l2
            print l3
            print 'Is', det
        elif x == 3:
            det = m00 * m11 * m22 + m01 * m12 * m20 + m02 * m10 * m21 - m00 * m12 * m21 - m01  * m10 * m22 - m02 * m11 * m20
            print ''
            print result_msg
            print l0
            print l1
            print l2
            print 'Is', det
    elif x == 2:
        det = m00 * m11 - m01 * m10
        print ''
        print result_msg
        print l0
        print l1
        print 'Is', det
Hawkeye Python 0 Light Poster

There were some bugs :( Sorry
Improved and fully working (apparently):

#
#   det(x):
#       x = Matrix Order
#       x can be 2, 3 or 4
#
#       Supports negatives and decimals
#

def det(x):
    if not x <= 4 or x == 0:
        print 'Supports only 2x2, 3x3 and 4x4 matrices.'
        x = input('Order = ')
        print ''
    result_msg = 'The determinant of'
    if x < 4:
        print 'You choosed a matrix of order 2 or 3.'
        print 'Just fill the extra lines with any numbers'
        print 'They wont be calculated.'
        print ''
    print 'Do not use fractions. Use decimals.'
    print ''
    print 'Separete the elements following the example below:'
    print 'w, x, y, z'
    print ''
    l0 = input("Line 1: ")
    l1 = input("Line 2: ")
    l2 = input("Line 3: ")
    l3 = input("Line 4: ")
    m00 = l0[0]
    m01 = l0[1]
    if x > 2:
        m02 = l0[2]
        if x == 4:
            m03 = l0[3]
    m10 = l1[0]
    m11 = l1[1]
    if x > 2:
        m12 = l1[2]
        if x == 4:
             m13 = l1[3]
    m20 = l2[0]
    m21 = l2[1]
    if x > 2:
        m22 = l2[2]
        if x == 4:
            m23 = l2[3]
    m30 = l3[0]
    m31 = l3[1]
    if x > 2:
        m32 = l3[2]
        if x == 4:
            m33 = l3[3]
            det = m03 * m12 * m21 * m30 - m02 * m13 * m21 * m30 - m03 * m11 * m22 * m30+m01 * m13 * m22 * m30 + m02 * m11 * m23 * m30-m01 * m12 * m23 * m30 - m03 * m12 * m20 * m31+m02 * m13 * m20 * m31 + m03 * m10 * m22 * m31-m00 * m13 * m22 * m31 - m02 * m10 * m23 * m31+m00 * m12 * m23 * m31 + m03 * m11 * m20 * m32-m01 * m13 * m20 * m32 - m03 * m10 * m21 * m32+m00 * m13 * m21 * m32 + m01 * m10 * m23 * m32-m00 * m11 * m23 * m32 - m02 * m11 * m20 * m33+m01 * m12 * m20 * m33 + m02 * m10 * m21 * m33-m00 * m12 * m21 * m33 - m01 * m10 * m22 * m33+m00 * m11 * m22 * m33
            print ''
            print result_msg
            print l0
            print l1
            print l2
            print l3
            print 'Is', det
        elif x == 3:
            det = m00 * m11 * m22 + m01 * m12 * m20 + m02 * m10 * m21 - m00 * m12 * m21 - m01  * m10 * m22 - m02 * m11 * m20
            print ''
            print result_msg
            print l0
            print l1
            print l2
            print 'Is', det
    elif x == 2:
        det = m00 * m11 - m01 * m10
        print ''
        print result_msg
        print l0
        print l1
        print 'Is', det
Hawkeye Python 0 Light Poster

I coudn't edit my posts so I'm adding another one (sry)

Those codes were pretty bad so I remade it all:

This way it uses a input but you don't have to fill the extra lines:

def det(x):
    if x == 2:
        L1 = input('Line 1 = ')
        L2 = input('Line 2 = ')
        det = L1[0] * L2[1] - L1[1] * L2[0]
        print ''
        return det
    if x == 3:
        L1 = input('Line 1 = ')
        L2 = input('Line 2 = ')
        L3 = input('Line 3 = ')
        det = L1[0] * L2[1] * L3[2] + L1[1] * L2[2] * L3[0] + L1[2] * L2[0] * L3[1] - L1[0] * L2[2] * L3[1] - L1[1]  * L2[0] * L3[2] - L1[2] * L2[1] * L3[0]
        print ''
        return det
    if x == 4:
        L1 = input('Line 1 = ')
        L2 = input('Line 2 = ')
        L3 = input('Line 3 = ')
        L4 = input('Line 4 = ')
        det = L1[3] * L2[2] * L3[1] * L4[0] - L1[2] * L2[3] * L3[1] * L4[0] - L1[3] * L2[1] * L3[2] * L4[0] + L1[1] * L2[3] * L3[2] * L4[0] + L1[2] * L2[1] * L3[3] * L4[0] - L1[1] * L2[2] * L3[3] * L4[0] - L1[3] *L2[2] * L3[0] * L4[1] + L1[2] * L2[3] * L3[0] * L4[1] + L1[3] * L2[0] * L3[2] * L4[1] - L1[0] * L2[3] * L3[2] * L4[1] - L1[2] * L2[0] * L3[3] * L4[1] + L1[0] * L2[2] * L3[3] * L4[1] + L1[3] * L2[1] * L3[0] * L4[2] - L1[1] * L2[3] * L3[0] * L4[2] - L1[3] * L2[0] * L3[1] * L4[2] + L1[0] * L2[3] * L3[1] * L4[2] + L1[1] * L2[0] * L3[3] * L4[2] - L1[0] * L2[1] * L3[3] * L4[2] - L1[2] * L2[1] * L3[0] * L4[3] + L1[1] * L2[2] * L3[0] * L4[3] + L1[2] * L2[0] * L3[1] * L4[3] - L1[0] * L2[2] * L3[1] * L4[3] - L1[1] * L2[0] * L3[2] * L4[3] + L1[0] * L2[1] * L3[2] * L4[3]
        print ''
        return det
    else:
        return 'This function supports only matrices of order 2, 3 and 4'

Use 'n' to fill extra elements and to line break:

def det(a00, a01, a02, a03, a10, a11, a12, a13, a20, a21, a22, a23, a30, a31, a32, a33):
    if a02 == 'n':
        det = a00 * a10 - a01 * a03
        return det
    if a03 == 'n':
        det = a00 * a11 * a22 + a01 * a12 * a20 + a02 * a10 * a21 - a00 * a12 * a21 - a01  * a10 * a22 - a02 * a11 * a20
        return det
    else:
        det = a03 * a12 * a21 * a30 - a02 * a13 * a21 * a30 - a03 * a11 * a22 * a30 + a01 * a13 * a22 * a30 + a02 * a11 * a23 * a30 - a01 * a12 * a23 * a30 - a03 *a12 * a20 * a31 + a02 * a13 * a20 * a31 + a03 * a10 * a22 * a31 - a00 * a13 * a22 * a31 - a02 * a10 * a23 * a31 + a00 * a12 * a23 * a31 + a03 * a11 * a20 * a32 - a01 * a13 * a20 * a32 - a03 * a10 * a21 * a32 + a00 * a13 * a21 * a32 + a01 * a10 * a23 * a32 - a00 * a11 * a23 * a32 - a02 * a11 * a20 * a33 + a01 * a12 * a20 * a33 + a02 * a10 * a21 * a33 - a00 * a12 * a21 * a33 - a01 * a10 * a22 * a33 + a00 * a11 * a22 * a33
        return det
-ordi- 6 Junior Poster in Training
Gribouillis 1,391 Programming Explorer Team Colleague

@-ordi- : did you test this code ? is it yours ? the algorithm looks like the worst possible algorithm :)

-ordi- 6 Junior Poster in Training

@-ordi- : did you test this code ? is it yours ? the algorithm looks like the worst possible algorithm :)

1.) No
2.) No
3.) Why?

Gribouillis 1,391 Programming Explorer Team Colleague

Because apparently, it computes the determinant using cofactor expansion (see http://en.wikipedia.org/wiki/Cofactor_%28linear_algebra%29). In the best case, to compute a nxn determinant, you must compute n ((n-1)x(n-1)) subdeterminants. The complexity of this algorithm is wildly exponential.

The good generic algorithm for the determinant is Gauss elimination (with n**3 complexity)

Gribouillis 1,391 Programming Explorer Team Colleague

Here is a simple gaussian elimination implementation

# python 2 and 3
# See also the function numpy.linalg.det
import sys
if sys.version_info >= (3,):
    xrange = range

def det(M):
    """Compute the determinant of a square matrix by Gaussian elimination"""
    M = [ list(row) for row in M ]
    n = len(M)
    res = 1.0
    for j in xrange(n-1, 0, -1):
        pivot, i = max((abs(M[k][j]), k) for k in xrange(j+1))
        pivot = M[i][j]
        if pivot == 0.0:
            return 0.0
        M[i], M[j] = M[j], M[i]
        if i != j:
            res = -res
        res *= pivot
        fact = -1.0/pivot
        for i in xrange(j):
            f = fact * M[i][j]
            for k in xrange(j):
                M[i][k] += f * M[j][k]
    res *= M[0][0]
    return res

data = """
    0.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.
    1.  0.  1.  4.  1.  9.  4.  4.  1.  1.  4.  9.  4.  9.
    1.  1.  0.  1.  4.  4.  9.  9.  4.  4.  1.  4.  1.  4.
    1.  4.  1.  0.  9.  1.  4.  4.  9.  1.  4.  1.  4.  1.
    1.  1.  4.  9.  0.  4.  4.  4.  1.  4.  1.  9.  4.  9.
    1.  9.  4.  1.  4.  0.  4.  4.  9.  4.  1.  1.  4.  1.
    1.  4.  9.  4.  4.  4.  0.  1.  1.  1.  9.  1.  9.  4.
    1.  4.  9.  4.  4.  4.  1.  0.  4.  1.  9.  4.  4.  1.
    1.  1.  4.  9.  1.  9.  1.  4.  0.  4.  4.  4.  4.  9.
    1.  1.  4.  1.  4.  4.  1.  1.  4.  0.  9.  4.  9.  4.
    1.  4.  1.  4.  1.  1.  9.  9.  4.  9.  0.  4.  1.  4.
    1.  9.  4.  1.  9.  1.  1.  4.  4.  4.  4.  0.  4.  1.
    1.  4.  1.  4.  4.  4.  9.  4.  4.  9.  1.  4.  0.  1.
    1.  9.  4.  1.  9.  1.  4.  1.  9.  4.  4.  1.  1.  0.
"""

if __name__ == "__main__":
    M = [ [float(x) for x in line.strip().split()] for line in data.strip().split("\n") ]
    print(det(M))

""" my output -->
2774532096.0
"""
ultimatebuster 14 Posting Whiz in Training

Lol nice. Although a n x n determinant will be much more impressive

anyhow now make it compatible with my matrix class that i quickly written a couple weeks ago :P

class Matrix(object):
    def __init__(self, matrix, numcolumn=-1):
        self.rows = matrix
        
        if numcolumn == -1:
            numcolumn = len(matrix[0])
            
        for row in matrix:
            if len(row) != numcolumn:
                raise TypeError("Columns must be in the same length.")
            
        self.columns = []
        for i in range(numcolumn):
            self.columns.append([])
            
        for row in matrix:
            for i in range(numcolumn):
                self.columns[i].append(row[i])
    
    def prettify(self, decimal=1):
        txt = ""
        decimal = str(decimal)
        formatstr = "%."+decimal+"f  "
        for row in self.rows:
            for num in row:
                txt += formatstr % num
            txt += "\n"
        return txt

    def _addsubtractcheck(self, other):
        if len(self.rows) != len(other.rows):
            raise ValueError("The number of rows doesn't match!")

        if len(self.columns) != len(other.columns):
            raise ValueError("The number of columns doesn't match!")

    def _doaddsubtract(self, other, add=True):
        self._addsubtractcheck(other)
        newMatrix = []
        for i in range(len(self.rows)):
            newMatrix.append([])
            for j in range(len(self.columns)):
                if add:
                    newMatrix[i].append(self.rows[i][j] + other.rows[i][j])
                else:
                    newMatrix[i].append(self.rows[i][j] - other.rows[i][j])
        return Matrix(newMatrix)

    def transform(self):
        return Matrix(self.columns)
    
    def __add__(self, other):
        return self._doaddsubtract(other)
        

    def __sub__(self, other):
        return self._doaddsubtract(other, False)

    def __mul__(self, other):
        newMatrix = []
        if type(other) == int:
            for i in range(len(self.rows)):
                newMatrix.append([])
                for j in range(len(self.columns)):
                    newMatrix[i].append(self.rows[i][j] * other)

            return Matrix(newMatrix)
            
        if len(self.columns) != len(other.rows):
            raise ValueError("The number of the columns in the first matrix doesn't match the number of the rows in the second matrix.")

        for rownum in range(len(self.rows)):
            newMatrix.append([])
            for colnum in range(len(other.columns)):
                value = 0
                for i in range(len(self.rows[rownum])):
                    value += self.rows[rownum][i] * other.columns[colnum][i]
                newMatrix[rownum].append(value)
                
        return Matrix(newMatrix)
Gribouillis 1,391 Programming Explorer Team Colleague

Lol nice. Although a n x n determinant will be much more impressive

anyhow now make it compatible with my matrix class that i quickly written a couple weeks ago :P

To add it to your matrix class, write

class Matrix(object):
    ...

    def det(self):
        M = [ list(row) for row in self.rows ] # first line changed
        # rest of the code unchanged

What do you mean by a n x n determinant ? This computes the determinant of a n x n matrix !

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.