在Sympy中求解包含符号大小的MatrixSymbol的矩阵方程?

时间:2019-06-24 14:35:28

标签: sympy

作为引言,我想指出,如果一个矩阵A由2x2模式的4个子矩阵组成,其中对角矩阵是正方形,那么如果我们将其逆表示为X子矩阵X22 = (A22-A21(A11^-1)A12)^-1,这很容易用手显示。

我试图对4x4子矩阵做同样的事情,但是手工起来却很繁琐。所以我认为Sympy会有所帮助。但是我不知道怎么做(我只是尝试重现2x2结果而已。)

我尝试过:

import sympy as s

def blockmatrix(name, sizes, names=None):
    if names is None:
        names = sizes
    ll = []
    for i, (s1, n1) in enumerate(zip(sizes, names)):
        l = []
        for j, (s2, n2) in enumerate(zip(sizes, names)):
            l.append(s.MatrixSymbol(name+str(n1)+str(n2), s1, s2))
        ll.append(l)
    return ll

def eyes(*sizes):
    ll = []
    for i, s1 in enumerate(sizes):
        l = []
        for j, s2 in enumerate(sizes):
            if i==j:
                l.append(s.Identity(s1))
                continue
            l.append(s.ZeroMatrix(s1, s2))
        ll.append(l)
    return ll

n1, n2 = s.symbols("n1, n2", integer=True, positive=True, nonzero=True)
M = s.Matrix(blockmatrix("m", (n1, n2)))
X = s.Matrix(blockmatrix("x", (n1, n2)))
I = s.Matrix(eyes(n1, n2))
s.solve(M*X[:, 1:]-I[:, 1:], X[:, 1:])

但是它只返回一个空列表而不是结果。

我也尝试过:

  • 使用M*X==I,但仅返回False(布尔值,而不是表达式)
  • 输入方程式列表
  • 使用带有commutative=False的'普通'符号而不是MatrixSymbols-这给出了GeneratorsError: non-commutative generators: (x12, x22)的例外情况

但没有运气。

您能展示一下如何使用Sympy得出与我作为X22示例给出的结果类似的结果吗?

关于使用MatrixSymbols求解的最相似的其他问题似乎已经通过使用内部符号数组或类似的符号来解决,从而得以解决。但是由于我要处理具有符号大小的MatrixSymbol,所以这对我来说不是一个选择。

1 个答案:

答案 0 :(得分:1)

这是2x2矩阵矩阵的意思吗?

>>> a = [MatrixSymbol(i,2,2) for i in symbols('a1:5')]
>>> A = Matrix(2,2,a)
>>> X = A.inv()
>>> print(X[1,1])  # [1,1] instead of [2,2] because indexing starts at 0
a1*(a1*a3 - a3*a1)**(-1)

[您表示不正确,并指出以上内容不正确-这似乎是一个应解决的问题。]

我不确定为什么不执行此操作,但是我们可以按以下步骤手动解决:

>>> n = 2
>>> v = symbols('b:%s'%n**2,commutative=False)
>>> A = Matrix(n,n,symbols('a:%s'%n**2,commutative=False))
>>> B = Matrix(n,n,v)
>>> eqs = list(A*B - eye(n))
>>> for i in range(n**2):
...   s = solve(eqs[i],v[i])[0]
...   eqs[i+1:] = [e.subs(v[i],s) for e in eqs[i+1:]]
...
>>> s  # solution for v[3] which is B22
(-a2*a0**(-1)*a1 + a3)**(-1)

您可以将n更改为3,然后看到一个适度复杂的表达式。将其更改为4并手动检查结果以对“乏味”一词重新定义;-)

要解决的方程的特殊结构也可以提供更快的解决方案:感兴趣的变量是包含它的每个项中的最后一个因素:

>>> for i in range(n**2):
...   c,d = eqs[i].expand().as_independent(v[i])
...   assert all(j.args[-1]==v[i] for j in Add.make_args(d))
...   s = 1/d.subs(v[i], 1)*-c
...   eqs[i+1:] = [e.subs(v[i], s) for e in eqs[i+1:]]
相关问题