SymPy substitute Symbol for Vector

橙三吉。 提交于 2020-07-22 05:05:27

问题


I have an expression of type Mul called term in the code below. Within term is a type Symbol called zhat. I want to perform something like term.subs(zhat, vec) where vec is of type BaseVector. I am subbing a symbol for a vector. The output is assigned to out_actual in the code.

The issue is that out_actual is of type Mul when I need it to be of type VectorMul. The variable out_ideal is what I would expect from the substitution. Any way to obtain out_ideal?

import sympy as sp
from sympy.vector import CoordSys3D
N = CoordSys3D('N')
Q, eps, zhat = sp.symbols('Q \epsilon_0 \\hat{\\mathbf{z}}')

vec = N.k
term = Q*eps*zhat
out_ideal = Q*eps*vec
out_actual = term.subs(zhat, vec)

回答1:


It's not particularly pleasant or generalizable, but you could do the following to convert any Mul into a VectorMul whenever appropriate (and leaving it as a Mul otherwise):

import sympy as sp
from sympy.vector import CoordSys3D
from sympy.core.mul import Mul

N = CoordSys3D('N')

def multiply_args(obj):
    '''Gets the result of multiplying all of the Mul's args together.'''
    if not isinstance(obj, Mul):
        raise ValueError('Input must be an instance of Mul')
    args = obj.args
    prod = args[0]
    for e in args[1:]:
        prod = prod * e
    return prod

Q, eps, zhat = sp.symbols('Q \epsilon_0 \\hat{\\mathbf{z}}')
vec = N.k

term = Q*eps*zhat
sub_result = term.subs(zhat, vec)
sub_result = multiply_args(sub_result)

The reason this is necessary is that subs, a method which belongs to the Basic class, simply looks at all of the arguments (e.g. Q, eps, zhat) of the Mul object (term) and replaces each that matches the substitution target, and gives the result as a Mul but with an amended list of args (i.e. zhat has been replaced with vec). It doesn't do any further evaluation on the result, and leaves the argument as a Mul.

To convert it to a VectorMul, you can just multiply the resulting arguments together manually, like you did to get out_ideal. All multiply_args does is manually multiplies the arguments together, which then promotes to a VectorMul if any of the arguments is a Vector. Obviously this only works because you know you have started with a Mul; you'd need to generalize this to deal with other types if you needed to.

If could be worth putting in a feature reqeust to the SymPy Github repository for this functionality.



来源:https://stackoverflow.com/questions/62844801/sympy-substitute-symbol-for-vector

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!