pelegs
pelegs

Reputation: 337

Re-arrange sympy output

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

Answers (2)

Oscar Benjamin
Oscar Benjamin

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

smichr
smichr

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

Related Questions