您仍然需要告诉 Sympy 符号 x 和 y 存在约束。为此,仍然创建Symbol
它们的实例,然后将这些参数传递为locals
to sympify
:
In [120]: x = sympy.Symbol('x', commutative=False)
In [121]: y = sympy.Symbol('y', commutative=False)
In [122]: sympy.sympify('3*x*y - y*x - 2*x*y', locals={'x':x, 'y':y})
Out[122]: x*y - y*x
为了以编程方式完成此操作,SymPy 提供了一些很好的解析工具,用于从字符串表达式中提取符号。关键的想法是你必须抑制评价因为正常的评估会做出交换性假设,从而破坏您提取所需内容的能力:
In [155]: s = sympy.parsing.sympy_parser.parse_expr('3*x*y - y*x - 2*x*y', evaluate=False)
In [156]: s.atoms(sympy.Symbol)
Out[156]: {x, y}
似乎没有直接的方法来改变已经创建的假设状态Symbol
,这是不幸的。但是您可以迭代这些符号,并创建具有相同名称和非交换假设的新符号集合,并将其用于locals
in sympify
.
def non_commutative_sympify(expr_string):
parsed_expr = sympy.parsing.sympy_parser.parse_expr(
expr_string,
evaluate=False
)
new_locals = {sym.name:sympy.Symbol(sym.name, commutative=False)
for sym in parsed_expr.atoms(sympy.Symbol)}
return sympy.sympify(expr_string, locals=new_locals)
例如:
In [184]: non_commutative_sympify('3*x*y - y*x - 2*x*y')
Out[184]: x*y - y*x
In [185]: non_commutative_sympify('x*y*z - y*z*x - 2*x*y*z + z*y*x')
Out[185]: -x*y*z - y*z*x + z*y*x