在 Python 中使用 MatrixSymbol 简化矩阵表达式

abk*_*abk 5 python sympy

我使用 SymPy 进行符号矩阵计算,但是某些语句非常大。似乎有一种方法可以进一步简化它们。我已经使用过simplify(),但没有成功地得到我想要的东西。

例如,下图是一个矩阵,它是执行一长串先前矩阵计算的结果而获得的。 一系列矩阵计算的输出,需要进一步简化

最后的语句有两次加法和一次矩阵乘法。我想知道是否有什么方法可以同时执行右侧的矩阵乘法,这样我们就可以简单地得到 3 个矩阵求和?

我知道这可以通过手动进行某些代数操作来完成,但我对要执行的命令更感兴趣,这样该命令将整个语句作为输入,并进行所有简化,包括任何乘法和加法,并输出我需要的内容。这一切都应该使用sympy. 换句话说,如果可以进行加法或乘法,那么我希望它完成而不是被搁置。

这是 MCVE,它模仿了我的问题

from sympy import *
init_printing()
J_22 = MatrixSymbol('J_22', 3, 3)
COV_b=Matrix([[2,1,1],[1,2,1],[1,1,2]])
(COV_b+J_22)*COV_b
Run Code Online (Sandbox Code Playgroud)

这段代码的输出是

MCVE 的输出

但是,我想将此作为输出

所需的输出

我知道在这个简单的例子中我可以通过以下代码简单地解决问题

from sympy import *
init_printing()
J_22 = MatrixSymbol('J_22', 3, 3)
COV_b=Matrix([[2,1,1],[1,2,1],[1,1,2]])
(COV_b*COV_b+J_22*COV_b)
Run Code Online (Sandbox Code Playgroud)

然而,这只是一个简单的例子,在实际问题中,在生成输出之前是看不到这一点的。因此,我希望能够使用一个命令,它将第一个提供的代码的输出作为输入并输出所需的输出。

更新:@WelcometoStackOverflow 提供了一个函数,它大大简化了事情,但仍然没有完成矩阵加法。

from sympy import *
init_printing()
J_22 = MatrixSymbol('J_22', 3, 3)
COV_b=Matrix([[2,1,1],[1,2,1],[1,1,2]])
T=(COV_b+J_22)*COV_b+COV_b
def expand_matmul(expr):
    import itertools
    for a in preorder_traversal(expr):
        if isinstance(a, MatMul):
            terms = [f.args if isinstance(f, MatAdd) else [f] for f in a.args]
            expanded = Add(*[MatMul(*t) for t in itertools.product(*terms)])
            if a != expanded:
                expr = expr.xreplace({a: expanded})
                return expand_matmul(expr)
    return expr
expand_matmul(T)
Run Code Online (Sandbox Code Playgroud)

输出是

在此输入图像描述[4]

前两个矩阵之间的求和仍未执行。

小智 4

这是 SymPy 表达式的一个已知的老问题:Can\t Expand Matrix expression。矩阵表达式模块很有用,但不是 SymPy 中维护最活跃的模块。我组合了一个函数来扩展这些东西。

\n\n
def expand_matmul(expr):\n    import itertools\n    for a in preorder_traversal(expr):\n        if isinstance(a, MatMul) and any(isinstance(f, MatAdd) for f in a.args):\n            terms = [f.args if isinstance(f, MatAdd) else [f] for f in a.args]\n            expanded = MatAdd(*[MatMul(*t) for t in itertools.product(*terms)])\n            if a != expanded:\n                expr = expr.xreplace({a: expanded})\n                return expand_matmul(expr)\n    return expr\n
Run Code Online (Sandbox Code Playgroud)\n\n

该函数从最高层开始遍历表达式树,寻找扩展 MatMul 的机会。返回的表达式可能受益于doit方法调用来执行显式矩阵的任何未完成的乘法,如下例所示。

\n\n
J_22 = MatrixSymbol(\'J_22\', 3, 3)\nCOV_b=Matrix([[2,1,1],[1,2,1],[1,1,2]])\nT=(COV_b+J_22)*COV_b+COV_b  \npprint(expand_matmul(T).doit())\n
Run Code Online (Sandbox Code Playgroud)\n\n

印刷

\n\n
\xe2\x8e\xa18  6  6\xe2\x8e\xa4       \xe2\x8e\xa12  1  1\xe2\x8e\xa4\n\xe2\x8e\xa2       \xe2\x8e\xa5       \xe2\x8e\xa2       \xe2\x8e\xa5\n\xe2\x8e\xa26  8  6\xe2\x8e\xa5 + J\xe2\x82\x82\xe2\x82\x82\xe2\x8b\x85\xe2\x8e\xa21  2  1\xe2\x8e\xa5\n\xe2\x8e\xa2       \xe2\x8e\xa5       \xe2\x8e\xa2       \xe2\x8e\xa5\n\xe2\x8e\xa36  6  8\xe2\x8e\xa6       \xe2\x8e\xa31  1  2\xe2\x8e\xa6\n
Run Code Online (Sandbox Code Playgroud)\n