计算符号二元矩阵的调整或逆的单个元素

问题描述

我正在尝试获取矩阵 A_adj 的调节 A 的单个元素,这两个元素都需要是符号表达式,其中符号 x_i 是二进制的,而矩阵 A 是对称且稀疏的。 Python 的 sympy 非常适合解决小问题:

from sympy import zeros,symbols

size = 4
A = zeros(size,size)
x_i = [x for x in symbols(f'x0:{size}')]

for i in range(size-1):
    A[i,i] += 0.5*x_i[i]
    A[i+1,i+1] += 0.5*x_i[i]
    A[i,i+1] = A[i+1,i] = -0.3*(i+1)*x_i[i]

A_adj_0 = A[1:,1:].det()

A_adj_0

这将计算辅因子矩阵的第一个元素 A_adj_0(即对应的 minor)并正确地给我 0.125x_0x_1x_2 - 0.28x_2x_2^2 - 0.055x_1^2x_2 - 0.28x_1x_2^2,这是我需要的表达方式,但有两个问题:

  1. 这对于较大的矩阵是完全不可行的(对于 size 的 ~100,我需要这个)。
  2. x_i 是二元变量(即 0 或 1),sympy 似乎无法简化二元变量的表达式,即简化多项式 x_i^n = x_i。立>

第一个问题可以通过求解线性方程组 Ay = b 来部分解决,其中 b 被设置为第一个基向量 [1,0],这样 yA 的倒数的第一列。 y 的第一个条目是 A 的逆的第一个元素:

b = zeros(size,1)
b[0] = 1

y = A.LUsolve(b)

s = {x_i[i]: 1 for i in range(size)}

print(y[0].subs(s) * A.subs(s).det())
print(A_adj_0.subs(s))

这里的问题是 y 的第一个元素的表达式极其复杂,即使使用了 simplify() 等等。这将是一个非常简单的表达式,并简化了上面第 2 点中提到的二进制表达式。这是一种更快的方法,但对于较大的矩阵仍然不可行。

这归结为我的实际问题:

是否有一种有效的方法来计算稀疏对称符号矩阵的调整的单个元素,其中符号是二进制值?

我也愿意使用其他软件。

附录 1:
似乎可以使用我不知道的简单自定义替换来简化 sympy 中的二进制表达式:

A_subs = A_adj_0

for i in range(size):
    A_subs = A_subs.subs(x_i[i]*x_i[i],x_i[i])

A_subs

解决方法

您应该确保在 sympy 中使用 Rational 而不是浮动,因此使用 S(1)/2Rational(1,2) 而不是 0.5

sympy 中有一个新的(未记录的,目前是内部的)矩阵实现,称为 DomainMatrix。对于这样的问题,它可能要快得多,并且总是以完全扩展的形式产生多项式结果。我预计这种问题会快得多,但它似乎仍然相当慢,因为内部并不稀疏(但 - 这可能会在下一个版本中改变)并且它没有利用简化来自二进制值的符号。它可以在 GF(2) 上工作,但不能与假定在 GF(2) 中的符号一起工作,这是不同的东西。

如果它有帮助,尽管这是您在 sympy 1.7.1 中使用它的方式:

from sympy import zeros,symbols,Rational
from sympy.polys.domainmatrix import DomainMatrix


size = 10
A = zeros(size,size)
x_i = [x for x in symbols(f'x0:{size}')]

for i in range(size-1):
    A[i,i] += Rational(1,2)*x_i[i]
    A[i+1,i+1] += Rational(1,2)*x_i[i]
    A[i,i+1] = A[i+1,i] = -Rational(3,10)*(i+1)*x_i[i]

# Convert to DomainMatrix:
dM = DomainMatrix.from_list_sympy(size-1,size-1,A[1:,1:].tolist())

# Compute determinant and convert back to normal sympy expression:
# Could also use dM.det().as_expr() although it might be slower
A_adj_0 = dM.charpoly()[-1].as_expr()

# Reduce powers:
A_adj_0 = A_adj_0.replace(lambda e: e.is_Pow,lambda e: e.args[0])

print(A_adj_0)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...