I would like to be able to simplify mathematical expressions from a string in Python. There are several \"commutative\" ways of doing it. Is there a non-commutative function f
You still need to tell Sympy that there are constraints on the symbols x and y. To do this, still create Symbol
instances for them, and then just pass those parameters in as 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
To do it programmatically, SymPy provides some nice parsing tools for extracting symbols from a string expression. The key idea is that you have to suppress evaluation since normal evaluation will make commutativity assumptions that ruin your ability to extract what you need:
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}
It does not appear that there is a direct way to mutate the assumption state of an already-created Symbol
, which is unfortunate. But you can iterate through these symbols, and make a new collection of symbols with the same names and the non-commutative assumption, and use that for 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)
Which gives, e.g.:
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