Sympy普通符号表达式中替换逐元素乘法为矩阵乘法的方案咨询
你提出的先用普通符号完成表达式计算操作,最后替换乘法运算符为numpy.matmul的方案完全可行,同时也有更轻量的实现方案,具体如下:
方案1:直接修改lambdify的运算映射(推荐,无侵入)
不用修改任何表达式构建逻辑,只需要在生成函数时通过modules参数覆盖SymPy默认的乘法映射规则即可:
import numpy as np import sympy # 原有表达式构建逻辑完全不变 a = sympy.symbols("a") ad = sympy.symbols("ad") x = sympy.symbols("x") c = sympy.symbols("c") f = (ad*a)*c + x # 生成函数时指定乘法映射为矩阵乘法 func = sympy.lambdify( (a, ad, x, c), f, modules=[{'Mul': np.matmul}, 'numpy'] )
调用func(M_A, M_B, 0, 1)时,原本的逐元素乘法会自动替换为矩阵乘法,你之前用普通符号实现的trans_mat.dot(x_vars)这类操作完全不受影响。
方案2:主动替换表达式中的乘法节点
如果你需要区分部分逐元素乘法和矩阵乘法,可以先遍历表达式树替换指定乘法节点,再生成函数:
from sympy import Function, Mul # 自定义矩阵乘法符号 mat_mul = Function('mat_mul') # 替换所有乘法节点为自定义矩阵乘法(可自定义匹配规则只替换需要的部分) f_mat = f.replace( lambda expr: isinstance(expr, Mul), # 匹配所有乘法节点,可修改规则过滤 lambda expr: mat_mul(*expr.args) ) # 生成函数时绑定自定义符号的实现 func = sympy.lambdify( (a, ad, x, c), f_mat, modules=[{'mat_mul': np.matmul}, 'numpy'] )
注意:该方案灵活性更高,你可以修改匹配规则,只替换包含矩阵变量的乘法节点,避免标量运算受到影响。
补充说明
你场景中用到的对角矩阵,逐元素乘法和矩阵乘法结果一致,两种方案都可以正常运行,且不需要切换到MatrixSymbol,完全兼容你现有表达式构建逻辑。
内容的提问来源于stack exchange,提问作者lattitude
相关产品推荐
相关产品推荐

