【问题标题】:Find values for which matrix becomes singular in Python在 Python 中查找矩阵变为奇异的值
【发布时间】:2021-08-19 06:40:44
【问题描述】:

让我们采用以下方阵:

import numpy as np
A = np.array([[10.0, -498.0],
             [-2.0, 100.0]])

如果行列式 (A[0,0]*A[1,1]-A[0,1]*A[1,0]) 为零,则 A 将是奇异的。例如,如果 A[0,1] 取值 -500.0(其他所有内容不变),则 A 将是单数:

from sympy import symbols, Eq, solve

y = symbols('y')
eq = Eq(A[0,0]*A[1,1]-y*A[1,0])
sol = solve(eq)
sol

如何找到所有值 (A[0,0],A[0,1],...) 使 A(或任何给定的方阵)有效地变为奇异值(我使用大型矩阵)?非常感谢。

【问题讨论】:

  • 我认为除了暴力破解之外,没有办法找到矩阵奇点的每种可能性,也许递归函数可以在这里派上用场,而不是 for 循环......(我猜)
  • 做 SVD 解压缩并将奇异值之一设置为 0
  • 我不知道为什么我之前的评论被赞成,我认为这不是 OP 想要的,但可能值得研究,所以我不会删除它。这就是我认为您需要的:省略您要更改的值的列。如果生成的矩阵是奇异的,请找到行的线性组合,该组合为您提供要更改您省略的值的行。使用您找到的线性组合找到新值。
  • 嘿,你接受寻找方阵奇异的蛮力类型吗?
  • @yannziselman 感谢您的建议,我会试试这个。

标签: python numpy matrix linear-algebra


【解决方案1】:

诀窍是使用拉普拉斯展开来计算行列式。公式是

det(A) = sum (-1)^(i+j) * a_ij * M_ij

所以要使矩阵奇异,你只需要使用上面的公式,将主语改为a_ij并设置det(A) = 0。可以这样:

import numpy as np

def cofactor(A, i, j):
    A = np.delete(A, (i), axis=0)
    A = np.delete(A, (j), axis=1)
    return (-1)**(i+j) * np.linalg.det(A)


def make_singular(A, I, J):
    n = A.shape[0]
    s = 0
    for i in range(n):
        if i != J:
            s += A[I, i] * cofactor(A, I, i)

    M = cofactor(A, I, J)
    if M == 0:
        return 'No solution'
    else:
        return -s / M

测试:

>>> M = np.array([[10.0, -498.0],
                  [-2.0, 100.0]])
>>> make_singular(M, 0, 1)
-500.0000000000002

>>> M = np.array([[10.0, -498.0],
                  [0, 100.0]])
>>> make_singular(M, 0, 1)
'No solution'

【讨论】:

  • 谢谢,您的方法似乎按预期工作。我想知道是否有机会让它更快一点?将它与我正在使用的矩阵 (7872x7872) 一起使用时,计算每个坐标的解需要 13 个小时。
  • 为了提高速度,您可以先计算 7872x7872 的辅因子,然后将值保存在矩阵中。然后,重用make_singular()中的辅因子矩阵。
  • 顺便说一句,辅因子矩阵可以简单地使用数学公式计算:C = det(A) * inv(A).T,所以你不需要遍历每一行、每一列的索引。
  • 从 13 小时到 20 秒,这就是我所说的速度提升!再次感谢您!
【解决方案2】:

这东西适用于方阵...

它的作用是对矩阵中的每个项目进行暴力破解并检查其是否为单数,(所以有很多混乱的输出,如果你喜欢的话,可以使用它)

同样非常重要的是,它是一个递归函数,如果它是奇异的,则返回一个矩阵。所以它递归地抛出 RecursiveError....:|

这是我想出来的代码,如果你觉得可以的话,你可以使用它

import numpy as np

def is_singular(_temp_int:str, matrix_size:int):
  kwargs = [int(i) for i in _temp_int]

  arr = [] # Creates the matrix from the given size
  temp_count = 0
  for i in range(matrix_size):
    arr.append([])
    m = arr[i]
    for j in range(matrix_size):
      m.append(int(_temp_int[temp_count]))
      temp_count += 1

  n_array = np.array(arr)
  if int(np.linalg.det(n_array)) == 0:
    print(n_array) # print(n_array) for a pretty output or print(arr) for single line output of the determinant matrix
  _temp_int = str(_temp_int[:-len(str(int(_temp_int)+1))] + str(int(_temp_int)+1))
  is_singular(_temp_int, matrix_size)

# Only square matrices, so only one-digit integer as input
print("List of singular matrices in the size of '3x3': ")
is_singular('112278011', 3)
# Just give a temporary integer string which will be converted to matrix like [[1, 1, 2], [2, 7, 8], [0, 1, 1]]
# From the provided integer string, it adds up 1 after every iteration

我认为这是你想要的代码,如果它不起作用,请告诉我

【讨论】:

    猜你喜欢
    • 2012-10-11
    • 1970-01-01
    • 2015-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多