用矩阵代替SymPy中的标量标量、矩阵、SymPy

2023-09-03 09:25:37 作者:欲妄 tangle

以下是我在SymPy会话中执行的操作:

from sympy import *
xi1,xi2,xi3 = symbols('xi_1,xi_2,xi_3')
N1 = 1-xi1-xi2-xi3
N2 = xi3
N3 = xi1
N4 = xi2
x1,x2,x3,x4 = symbols('x_1, x_2, x_3, x_4')
x = N1*x1+N2*x2+N3*x3+N2*x4
subdict = {x1:Matrix([0.025,1.0,0.0]), x2 : Matrix([0,1,0]), x3:Matrix([0, 0.975, 0]), x4:Matrix([0,0.975,0.025])}
x.subs(subdict)
test.subs({xi1:1, xi2:0,xi3:0})
对我来说,我们只是简单地将一些标量与一些向量相乘,然后将它们相加。然而,SymPy不会同意并抛出一个巨大的错误,最后一行是:

TypeError: cannot add <class 'sympy.matrices.immutable.ImmutableDenseMatrix'> and <class 'sympy.core.numbers.Zero'>

为什么这是一个问题?我正在尝试的操作是否有解决办法?

推荐答案

闲话矩阵求导

我怀疑发生的情况是,在替换矩阵之前,您将替换为0,这将使0*matrix_symbol = 0替换为零矩阵。以矩阵结尾的项不能加到0上,从而导致错误。我尝试使用simultaneous标志或xplace,而不是subs,得到了相同的结果(在symmy.live.org上)。然后,我尝试以相反的顺序进行替换,首先将它们与矩阵一起作为列表传递。还是不管用。看起来,subs假定0*foo为0。如果不存在现有问题,则应在sympy issues处引发问题。

解决方法是首先进行标量替换,允许零项消失。然后用矩阵做替补。因此,这将需要2次调用subs。

使用0进行替换的一种真实、老套的解决方法是:

def remul(m):
  rv = 1
  for i in m.args:
    rv *= i
  return rv

expr = x*y
mat = expr.subs(x, randMatrix(2)) # replace x with matrix
expr = mat.replace( # replace y with scalar 0
    lambda m: m.is_Mul,
    lambda m: remul(Mul(*[i.subs(y, 0) for i in m.args], evaluate=False)))