使用 Python 求解行列式而不使用 scipy.linalg.det 的代码

发布于 2024-09-25 19:42:23 字数 178 浏览 5 评论 0 原文

描述(这是一个 hwk 问题):

我不知道从哪里开始。我计划使用拉普拉斯展开式,但我不确定如何将其应用于 nxn 矩阵。任何帮助将不胜感激。

注意:我已经有一个为 nxn 矩阵生成随机矩阵的函数。计算的时间也不是问题。我唯一遇到的问题是如何计算行列式。

必须删除我的班级政策的问题描述 b/c。

Description(this is a hwk question):

I am not sure where to start here. I plan to use Laplace's Expansion but I am not sure how to implement it for nxn matrices. Any help would be appreciated.

Note: I already have a function to generate random matrices for a nxn matrix. Also the timing the calculation isn't a problem. The only thing I have an issue is how to calculate the determinant.

Had to delete the question description b/c of my class policy.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

烦人精 2024-10-02 19:42:23

下面是用于查找矩阵行列式的 adjucate 方法的递归 python 代码。

def getMatrixMinor(m,i,j):
    return [row[:j] + row[j+1:] for row in (m[:i]+m[i+1:])]

def getMatrixDeternminant(m):
    #base case for 2x2 matrix
    if len(m) == 2:
        return m[0][0]*m[1][1]-m[0][1]*m[1][0]

    determinant = 0
    for c in range(len(m)):
        determinant += ((-1)**c)*m[0][c]*getMatrixDeternminant(getMatrixMinor(m,0,c))
    return determinant

请注意,输入是表示 nxn 矩阵的数组数组

Here is recursive python code for the adjucate method for finding a matrix's determinant.

def getMatrixMinor(m,i,j):
    return [row[:j] + row[j+1:] for row in (m[:i]+m[i+1:])]

def getMatrixDeternminant(m):
    #base case for 2x2 matrix
    if len(m) == 2:
        return m[0][0]*m[1][1]-m[0][1]*m[1][0]

    determinant = 0
    for c in range(len(m)):
        determinant += ((-1)**c)*m[0][c]*getMatrixDeternminant(getMatrixMinor(m,0,c))
    return determinant

Note that the input is an array of arrays representing the nxn matrix

删除→记忆 2024-10-02 19:42:23

好的,这是一个提示。

  1. 编写一个函数来计算小矩阵。 (提示,使用切片)
  2. 编写一个函数来计算辅因子(这应该调用第一个函数和确定函数)
  3. 确定函数调用第二步中的函数并将结果相加。 (提示:使用sum

中提琴,你有一个行列式。

另外,不要忘记,由于我们在 python 中编写列表的方式,索引会被颠倒。也就是说,如果

M = [[1, 2, 3],
     [4, 5, 6],
     [7, 8, 9]]

m0,1 是 2 而不是正常表示法中的 4。您可以将其视为转置或使用 zip

Ok, here's a hint.

  1. write a function to calculate the minor matrices. (hint, use slices)
  2. write a function to calculate the cofactors (this should call the first function, and the determinate function)
  3. the determinate function calls the function in step two and adds the results together. (hint: use sum)

viola, you have a determinant.

Also, don't forget that because of the way we write lists in python, the indices get reversed. That is if

M = [[1, 2, 3],
     [4, 5, 6],
     [7, 8, 9]]

then m0,1 is 2 and not 4 as it would be in normal notation. you can think of it as a transpose or use zip

南汐寒笙箫 2024-10-02 19:42:23
def minor(array,i,j):
    c = array
    c = c[:i] + c[i+1:]
    for k in range(0,len(c)):
        c[k] = c[k][:j]+c[k][j+1:]
    return c
def det(array,n):
    if n == 1 :return array[0][0]
    if n == 2 :return array[0][0]*array[1][1] - array[0][1]*array[1][0]
    sum = 0
    for i in range(0,n):
        m = minor(array,0,i)
        sum =sum + ((-1)**i)*array[0][i] * det(m,n-1)
    return sum
def minor(array,i,j):
    c = array
    c = c[:i] + c[i+1:]
    for k in range(0,len(c)):
        c[k] = c[k][:j]+c[k][j+1:]
    return c
def det(array,n):
    if n == 1 :return array[0][0]
    if n == 2 :return array[0][0]*array[1][1] - array[0][1]*array[1][0]
    sum = 0
    for i in range(0,n):
        m = minor(array,0,i)
        sum =sum + ((-1)**i)*array[0][i] * det(m,n-1)
    return sum
很糊涂小朋友 2024-10-02 19:42:23

对于大型矩阵,不建议使用拉普拉斯方法进行行列式计算,因为它的计算成本很高(递归函数)。相反,更好的方法是使用高斯消元法将原始矩阵转换为上三角矩阵。下三角矩阵或上三角矩阵的行列式只是对角元素的乘积。

这里我们展示一个例子。

import numpy as np
from scipy import linalg

def determinant(a):
    assert len(a.shape) == 2 # check if a is a two diamentional matrix
    assert a.shape[0] == a.shape[1] # check if matrix is square
    n = a.shape[0]
   
    for k in range(0, n-1):
       
        for i in range(k+1, n):
            if a[i,k] != 0.0:
                lam = a [i,k]/a[k,k]
                a[i,k:n] = a[i,k:n] - lam*a[k,k:n]

               
    # the matrix (a) is now in the upper triangular form
                
    return np.prod(np.diag(a))

matrix = np.random.rand(50, 50)


print(linalg.det(matrix))
print(determinant(matrix))

结果与 Scipy 行列式得到的结果类似!

-3032.573716363944

-3032.573716915967

但是,该函数仍然可以制定为包括旋转。此外,通过使用 numba 库,它可以达到与 scipy 类似的效率。

For large matrices, it is not recommended to use Laplace's method for determinant calculation, since it is computationally expensive (recursive functions). Instead, a better approach is to use the Gauss Elimination method to convert the original matrix into an upper triangular matrix. The determinant of a lower or an upper triangular matrix is simply the product of the diagonal elements.

Here we show an example.

import numpy as np
from scipy import linalg

def determinant(a):
    assert len(a.shape) == 2 # check if a is a two diamentional matrix
    assert a.shape[0] == a.shape[1] # check if matrix is square
    n = a.shape[0]
   
    for k in range(0, n-1):
       
        for i in range(k+1, n):
            if a[i,k] != 0.0:
                lam = a [i,k]/a[k,k]
                a[i,k:n] = a[i,k:n] - lam*a[k,k:n]

               
    # the matrix (a) is now in the upper triangular form
                
    return np.prod(np.diag(a))

matrix = np.random.rand(50, 50)


print(linalg.det(matrix))
print(determinant(matrix))

The result is similar to the one obtained from the Scipy determinant!

-3032.573716363944

-3032.573716915967

However, the function can still be formulated to include pivoting. Additionally, it can be brought to a similar efficiency as the one from scipy by using numba library.

夏末染殇 2024-10-02 19:42:23

我使用 Peyman Naseri 作为基本思想,并希望与我的实现分享,

import numpy as np
import time

def minor(arr,i,j):
    c = arr[:]
    c = np.delete(c, (i),axis=0)
    return [np.delete(row, (j),axis=0) for row in (c)]
    

def det(arr):
    n = len(arr)
    if n == 1 :return arr[0][0]
    if n == 2 :return arr[0][0]*arr[1][1] - arr[0][1]*arr[1][0]
    sum = 0
    for i in range(0,n):
        m = minor(arr,0,i)
        sum =sum + ((-1)**i)*arr[0][i] * det(m)
    return sum

matrix = np.random.randint(-5, 5, size=(10, 10)) # martix nxn with integer values in interval [-5, 5)

print(matrix)
start_time = time.time()
print("started:", start_time)
det(matrix)
end_time = time.time()
print("finished:", end_time)
print("--- %s seconds ---" % (end_time - start_time))

作为矩阵的结果行列式计算我的笔记本电脑上的 10*10 大约需要 1 分钟,我知道我的代码不是最佳的,但这是此实现的主要原因(也许我丢失了一些东西)我只需要在 Peyman Naseri 解决方案在我看来非常漂亮。

[[ 2 -1 -1  0 -2  0  4  4  3  4]
 [-3  1 -1  3  0 -3 -2  0  3 -1]
 [ 2 -1 -4  3  0 -2 -2 -5  3 -5]
 [-2 -1  2 -2  4 -3 -5 -1 -5  3]
 [ 1 -4  1 -5 -5  4 -3 -5  3  1]
 [ 2  4  0 -1 -1 -5 -2 -2 -3 -5]
 [ 1  4 -3 -4 -5  0  0  0 -5 -1]
 [ 0 -5 -5  4 -3 -2  2 -4  2 -5]
 [-3  1 -1 -4  4 -5  3 -3 -4  0]
 [ 0 -2  2 -3  1  3  2  0 -1  4]]
started: 1636896388.0213237
finished: 1636896442.846928
--- 54.82560420036316 seconds ---

I've used as base idea of Peyman Naseri and want to share with my implementation,

import numpy as np
import time

def minor(arr,i,j):
    c = arr[:]
    c = np.delete(c, (i),axis=0)
    return [np.delete(row, (j),axis=0) for row in (c)]
    

def det(arr):
    n = len(arr)
    if n == 1 :return arr[0][0]
    if n == 2 :return arr[0][0]*arr[1][1] - arr[0][1]*arr[1][0]
    sum = 0
    for i in range(0,n):
        m = minor(arr,0,i)
        sum =sum + ((-1)**i)*arr[0][i] * det(m)
    return sum

matrix = np.random.randint(-5, 5, size=(10, 10)) # martix nxn with integer values in interval [-5, 5)

print(matrix)
start_time = time.time()
print("started:", start_time)
det(matrix)
end_time = time.time()
print("finished:", end_time)
print("--- %s seconds ---" % (end_time - start_time))

as result determinant calculation for matrix 10*10 on my laptop takes about 1 minute, I understand that my code not optimal but main reason for this implementation (maybe I lost something) I just need to get working code base on Peyman Naseri solution which seems to me very pretty.

[[ 2 -1 -1  0 -2  0  4  4  3  4]
 [-3  1 -1  3  0 -3 -2  0  3 -1]
 [ 2 -1 -4  3  0 -2 -2 -5  3 -5]
 [-2 -1  2 -2  4 -3 -5 -1 -5  3]
 [ 1 -4  1 -5 -5  4 -3 -5  3  1]
 [ 2  4  0 -1 -1 -5 -2 -2 -3 -5]
 [ 1  4 -3 -4 -5  0  0  0 -5 -1]
 [ 0 -5 -5  4 -3 -2  2 -4  2 -5]
 [-3  1 -1 -4  4 -5  3 -3 -4  0]
 [ 0 -2  2 -3  1  3  2  0 -1  4]]
started: 1636896388.0213237
finished: 1636896442.846928
--- 54.82560420036316 seconds ---
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文