我希望能够在 Python 中简化字符串中的数学表达式。 有几种“交换”方法可以做到这一点。 是否存在非交换函数?
我知道 sympy 中的 sympify 可以做一些非交换性的工作,这里有一个例子:
from sympy import *
x=Symbol('x',commutative=False)
y=Symbol('y',commutative=False)
print sympify(3*x*y - y*x - 2*x*y)
它将打印 xy -yx,但是如果我们对字符串应用 sympify,即
print sympify('3*x*y - y*x - 2*x*y')
结果是0。
有没有一种方法可以简化上述字符串以保持x 和y 的非交换性?
我发现这里已经有人问过了http://osdir.com/ml/python-sympy/2012-02/msg00250.html有人回答了http://osdir.com/ml/python-sympy/2012-02/msg00255.html ,但是该解决方案似乎通常不起作用。
我更喜欢先问,如果没有立即解决方案,我想我将不得不自己编写代码。
最佳答案
你仍然需要告诉 Sympy 对符号 x 和 y 有约束。为此,仍然创建 Symbol
它们的实例,然后将这些参数作为 locals
传递至 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
。在 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
关于python - 非交换符号化(或化简),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32157468/