用矩阵代替SymPy中的标量

时间:2017-09-07 13:14:50

标签: python sympy

这是我在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'>

为什么这是一个问题?对于我想要做的事情,是否有解决方法?

1 个答案:

答案 0 :(得分:1)

我怀疑发生的事情是在替换矩阵之前,你用0代替0*matrix_symbol = 0而不是零的矩阵。最终为矩阵的术语不能添加到0,从而导致错误。我尝试使用simultaneous标志或xreplace而不是subs给出了相同的结果(在sympy.live.org上)。然后我尝试以相反的顺序进行替换,首先将它们作为带有矩阵的列表传递。仍然没有工作。看起来sub认为0*foo为0.如果尚未存在问题,则应提出sympy issues的问题。

解决方法是首先进行标量替换,允许零项消失。然后用矩阵做一个子。所以这需要2次调用潜艇。

用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)))