Reputation: 337
Is there a way to control the order by which sympy outputs expressions? For example:
>>> p
a*(-b*exp(x) + 1)
Can I force sympy to write
a*(1 - b*exp(x))
instead?
(if anyone is wondering - it goes directly in a LaTeX document via pylatex, so the order matters to me for formatting reasons)
Upvotes: 1
Views: 139
Reputation: 14480
There is no way to do that I'm afraid. The main problem I think is just that the order is naturally "wrong" for sums involving minus signs. Some cases have been fixed so that e.g. 1 - x
prints as you might expect in
https://github.com/sympy/sympy/pull/15985
There is another open PR to fix the problem more generally:
https://github.com/sympy/sympy/issues/16090
EDIT: There is init_printing(order='old')
which I didn't know about before:
In [26]: a*(1 - b*exp(x))
Out[26]:
⎛ x ⎞
a⋅⎝- b⋅ℯ + 1⎠
In [27]: init_printing(order='old')
In [28]: a*(1 - b*exp(x))
Out[28]:
⎛ x⎞
a⋅⎝1 - b⋅ℯ ⎠
In [29]: latex(a*(1 - b*exp(x)))
Out[29]: 'a \\left(1 - b e^{x}\\right)'
I haven't tested that extensively but it seems to work the way I would want.
Upvotes: 3
Reputation: 19077
As a workaround, consider the following which puts a symbol that should appear first in place of the one that appears 2nd and then uses unevaluated sympification with replacement to restore the original term:
def pos1st(expr):
from sympy.core.function import _coeff_isneg
a2 = []
for i in expr.atoms(Add):
if len(i.args) == 2:
a = i.as_ordered_terms()
if list(map(_coeff_isneg, i.as_ordered_terms())) == [
True, False]:
a2.append(a[1])
reps = [(i, Dummy(str(j))) for j,i in enumerate(a2)]
return S(str(expr.xreplace(dict(reps))), {str(i): j for j,i in reps},
evaluate=False)
>>> expr = x*(1 - b*exp(x))
>>> pos1st(expr)
x*(1 - b*exp(x))
>>> latex(_)
'x \\left(1 - b e^{x}\\right)'
Upvotes: 0