用Python中的MatrixSymbol简化矩阵表达式

用Python中的MatrixSymbol简化矩阵表达式,python,sympy,Python,Sympy,我使用Symphy进行符号矩阵计算,但是,某些语句非常大。似乎有一种方法可以进一步简化它们。我已经使用了simplify(),但是我没有成功地得到我想要的东西 例如,下图是一个矩阵,该矩阵是通过执行之前矩阵计算的长列表而获得的。 final语句有两个加法和一个矩阵乘法。我想知道是否有任何方法也可以执行右边的矩阵乘法,这样我们就可以简单地得到3个矩阵求和 我知道这可以通过手工进行某些代数运算来实现,但我更感兴趣的是要执行的命令,例如,该命令将整个语句作为输入,并进行所有简化,包括我需要的乘法、加

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

例如,下图是一个矩阵,该矩阵是通过执行之前矩阵计算的长列表而获得的。

final语句有两个加法和一个矩阵乘法。我想知道是否有任何方法也可以执行右边的矩阵乘法,这样我们就可以简单地得到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
这段代码的输出是

但是,我希望将此作为输出

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

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

更新:@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)
输出是


前两个矩阵之间的求和仍然没有执行

这是Symphy表达式的一个已知的老问题:。矩阵表达式模块很有用,但不是Symphy中维护最活跃的模块。我用一个函数来扩展这些东西

def expand_matmul(expr):
    import itertools
    for a in preorder_traversal(expr):
        if isinstance(a, MatMul) and any(isinstance(f, MatAdd) for f in a.args):
            terms = [f.args if isinstance(f, MatAdd) else [f] for f in a.args]
            expanded = MatAdd(*[MatMul(*t) for t in itertools.product(*terms)])
            if a != expanded:
                expr = expr.xreplace({a: expanded})
                return expand_matmul(expr)
    return expr
函数从最高级别遍历表达式树,寻找扩展MatMul的机会。返回的表达式可能受益于
doit
方法调用,以从显式矩阵执行任何未完成的乘法,如下例所示

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  
pprint(expand_matmul(T).doit())
印刷品

⎡8  6  6⎤       ⎡2  1  1⎤
⎢       ⎥       ⎢       ⎥
⎢6  8  6⎥ + J₂₂⋅⎢1  2  1⎥
⎢       ⎥       ⎢       ⎥
⎣6  6  8⎦       ⎣1  1  2⎦

@WelcometoStackOverflow谢谢你。是的,我理解,我将尝试编辑此。不幸的是,实际代码非常长。我试着做一个代码来模拟我的问题。谢谢你花时间编写这个函数。它工作得很好!但是,矩阵加法仍然未完成!我将更新问题以反映这一点。我不认为我可以在注释中添加代码块。一小段代码,如
(COV_b+J_22)*COV_b+COV_b
,可以在注释中添加(在反勾之间)。我稍微更新了这个函数,所以它现在也可以处理这个表达式。