I'm trying to nice print some divisions with Sympy but I noticed it didn't display aligned.
import sympy
sympy.init_printing(use_unicode=True)
sympy.pprint(sympy.Mul(-1, sympy.Pow(-5, -1, evaluate=False), evaluate=False))
# Output:
# -1
# ───
# -5 # Note that "-5" is displayed slightly more on the right than "-1".
Reason/fix for this?
EDIT: I did a lot of reverse-engineering using inspect.getsource
and inspect.getsourcefile
but it didn't really help out in the end.
Pretty Printing in Sympy seems to be relying on the Prettyprinter by Jurjen Bos.
import sympy
from sympy.printing.pretty.stringpict import *
sympy.init_printing(use_unicode=True)
prettyForm("-1")/prettyForm("-5")
# Displays:
# -1
# --
# -5
So it does display aligned, but I can't get it to use unicode.
The PrettyPrinter is called from the file sympy/printing/pretty/pretty.py
in the method PrettyPrinter._print_Mul
which simply return prettyForm.__mul__(*a)/prettyForm.__mul__(*b)
with, I thought, a
and b
simply being ['-1']
and ['-5']
but it wouldn't work.
Negative denominators are not standard and badly handled. If you really need them, you can modify the string outpout given by the pretty function :
import sympy
sympy.init_printing(use_unicode=True)
def ppprint(expr):
p=sympy.pretty(expr)
s=p.split('\n')
if len(s)==3 and int(s[2])<0:
s[0]=" "+s[0]
s[1]=s[1][0]+s[1]
p2="\n".join(s)
print(p2)
else: print(p)
This extend the bar and the numerator of one unit for negative denominators. No warranty of robustness on big expressions.
>>>> ppprint(sympy.Mul(sympy.Pow(-5, -1,evaluate=False),-1,evaluate=False))
-1
────
-5
Found out where the weird part is coming from:
stringpict.py
line 417:
if num.binding==prettyForm.NEG:
num = num.right(" ")[0]
This is being done ONLY for the numerator. It adds a space after the numerator if the numerator is negative… Weird!
I'm not sure if there can be a fixed other than directly editing the file. I'm going to report this on Github.
Thanks all for your help and suggestion.
PS: In the end, I used pdb
to help me debug and figure out what was actually going out!
EDIT: Hotfix if you can't / don't want to edit the code source:
import sympy
sympy.init_printing(use_unicode=True)
from sympy.printing.pretty.stringpict import prettyForm, stringPict
def newDiv(self, den, slashed=False):
if slashed:
raise NotImplementedError("Can't do slashed fraction yet")
num = self
if num.binding == prettyForm.DIV:
num = stringPict(*num.parens())
if den.binding == prettyForm.DIV:
den = stringPict(*den.parens())
return prettyForm(binding=prettyForm.DIV, *stringPict.stack(
num,
stringPict.LINE,
den))
prettyForm.__div__ = newDiv
sympy.pprint(sympy.Mul(-1, sympy.Pow(-5, -1, evaluate=False), evaluate=False))
# Displays properly:
# -1
# ──
# -5
I just copied the function from the code source and removed the incriminated line.
Possible improvement could be to functools.wraps
the new function with the original one.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With