How to find determinant of large matrix

后端 未结 5 1022
抹茶落季
抹茶落季 2020-12-05 06:00

I found some C++ code for finding the determinant of matrix, for 4x4 to 8x8. It works ok, but my project needs matrices that are 18x18 or more, and the code is too slow. The

5条回答
  •  佛祖请我去吃肉
    2020-12-05 06:15

    The function det_recursive works for a square matrix of any size. However, since it is using recursive naive method of expanding Laplace's formula it is very slow for matrices of large size.

    Another technique is to transform the matrix into an upper triangular form using gauss elimination technique. Then the determinant of the matrix is simply the products of diagonal elements of the triangular transformed form of the original matrix.

    Basically numpy is the fastest but internally it uses some sort of linear matrix transformation method similar to what gauss elimination does. However, I am not sure what exactly it is!

    In[1]
    import numpy as np
    
    In[2]
    mat = np.random.rand(9,9)
    print("numpy asnwer = ", np.linalg.det(mat))
    
    Out[2] 
    numpy asnwer =  0.016770106020608373
    
    In[3]
    def det_recursive(A):
        if A.shape[0] != A.shape[1]:
            raise ValueError('matrix {} is not Square'.format(A))
    
        sol = 0
        if A.shape != (1,1):
            for i in range(A.shape[0]):
                sol = sol +  (-1)**i * A[i, 0] * det_recursive(np.delete(np.delete(A, 0, axis= 1), i, axis= 0))
            return sol
        else:
            return A[0,0]
    ​
    
    In[4]
    print("recursive asnwer = ", det_recursive(mat))
    
    Out[4]
    recursive asnwer =  0.016770106020608397
    
    In[5]
    def det_gauss_elimination(a,tol=1.0e-9):
        """
        calculate determinant using gauss-elimination method
        """
        a = np.copy(a)
    
        assert(a.shape[0] == a.shape[1])
        n = a.shape[0]
    
        # Set up scale factors
        s = np.zeros(n)
    
        mult = 0
        for i in range(n):
            s[i] = max(np.abs(a[i,:])) # find the max of each row
        for k in range(0, n-1): #pivot row
            # Row interchange, if needed
            p = np.argmax(np.abs(a[k:n,k])/s[k:n]) + k 
            if abs(a[p,k]) < tol: 
                print("Matrix is singular")
                return 0
            if p != k: 
                a[[k,p],:] = a[[p, k],:] 
                s[k],s[p] = s[p],s[k]
                mult = mult + 1
    ​
            # convert a to upper triangular matrix
            for i in range(k+1,n):
                if a[i,k] != 0.0: # skip if a(i,k) is already zero
                    lam = a [i,k]/a[k,k] 
                    a[i,k:n] = a[i,k:n] - lam*a[k,k:n]
    ​
        deter = np.prod(np.diag(a))* (-1)**mult   
        return deter
    
    In[6] 
    print("gauss elimination asnwer = ", det_gauss_elimination(mat))
    
    Out[6] 
    gauss elimination asnwer =  0.016770106020608383
    
    In[7] 
    print("numpy time")
    %timeit -n3 -r3 np.linalg.det(mat)
    print("\nrecursion time")
    %timeit -n3 -r3 det_recursive(mat)
    print("\ngauss_elimination time")
    %timeit -n3 -r3 det_gauss_elimination(mat)
    
    Out[7]
    numpy time
    40.8 µs ± 17.2 µs per loop (mean ± std. dev. of 3 runs, 3 loops each)
    
    recursion time
    10.1 s ± 128 ms per loop (mean ± std. dev. of 3 runs, 3 loops each)
    
    gauss_elimination time
    472 µs ± 106 µs per loop (mean ± std. dev. of 3 runs, 3 loops each)
    

提交回复
热议问题