OK, there is probably a cleaner way to implement this, but the following seems to be working:
def _print_Add(self, expr): args = list(expr.args) if self._mainvar is not None: mainvar = self._mainvar def compare_exponents(a, b): p1, p2, p3 = Wild("p1"), Wild("p2"), Wild("p3") r_a = a.match(p1 * mainvar**p3) r_b = b.match(p1 * mainvar**p3) if r_a is None and r_b is None: c = Basic._compare_pretty(a,b) return c elif r_a is not None: if r_b is None: return 1 else: c = Basic.compare(r_a[p3], r_b[p3]) if c!=0: return c else: c = Basic._compare_pretty(a,b) return c elif r_b is not None and r_a is None: return -1 args.sort(compare_exponents) else: args.sort(Basic._compare_pretty) if self._descending: args.reverse() tex = str(self._print(args[0])) for term in args[1:]: coeff = term.as_coeff_terms()[0] if coeff.is_negative: tex += r" %s" % self._print(term) else: tex += r" + %s" % self._print(term) return tex In [1]: mylist = ['m', 's', 'b', 'x', 'y', 's', 'x', 'y', 's', 'EI'] In [2]: import sympy In [3]: sympy.var(mylist) Out[3]: (m, s, b, x, y, s, x, y, s, EI) In [4]: test = m*s**2+b*x*y*s+x**2+y**2+s+EI+x**3 In [5]: sympy.latex(test) Out[5]: '$EI + s + b s x y + {x}^{2} + {y}^{2} + m {s}^{2} + {x}^{3}$' In [6]: sympy.latex(test, mainvar=s) Out[6]: '$EI + {x}^{2} + {y}^{2} + {x}^{3} + s + b s x y + m {s}^{2}$' In [7]: sympy.latex(test, mainvar=s, descending=True) Out[7]: '$m {s}^{2} + b s x y + s + {x}^{3} + {y}^{2} + {x}^{2} + EI$' In [8]: sympy.latex(test, mainvar=x, descending=True) Out[8]: '${x}^{3} + {x}^{2} + b s x y + {y}^{2} + s + EI + m {s}^{2}$' Any thoughts? Ryan On Tue, Jun 2, 2009 at 9:16 AM, Ryan Krauss <ryanli...@gmail.com> wrote: > OK, I further hacked up compare_exponents and think I have a solution: > > > def compare_exponents(a, b): > print('================') > print('a = %s' % a) > print('b = %s' % b) > print('mainvar = %s' % mainvar) > p1, p2, p3 = Wild("p1"), Wild("p2"), Wild("p3") > r_a = a.match(p1 * mainvar**p3) > r_b = b.match(p1 * mainvar**p3) > print('r_a = %s' % r_a) > print('r_b = %s' % r_b) > if r_a is not None and r_b is not None: > print('r_a[p3] = %s' % r_a[p3]) > print('r_b[p3] = %s' % r_b[p3]) > c = Basic.compare(r_a[p3], r_b[p3]) > print('c = %s' % c) > if c!=0: > return c > > c = Basic._compare_pretty(a,b) > print('c = %s' % c) > return c > > > This is the case I think is wrong: > > ================ > a = x**2 > b = m*s**2 > mainvar = x > r_a = {p1_: 1, p3_: 2} > r_b = None > c = -1 > > because r_b is None, it goes out to Basic_compare_pretty. If I am > understanding how this works, compare_exponents should return 1 if a should > be before b in the sort and -1 if a should be after b. So, I think if r_a > is not None but r_b is, we should return 1. Similarly, if r_b is not None > and r_a is, we should return -1. Is that right? > > Ryan > > > On Tue, Jun 2, 2009 at 9:06 AM, Ryan Krauss <ryanli...@gmail.com> wrote: > >> I have an approach. It is fairly rough and not completely working: >> >> In printing/latex.py >> >> def latex(expr, inline=True, matstr=None, matdelim=None, \ >> mainvar=None, descending=False): >> if inline: >> if matstr is None: >> matstr = 'smallmatrix' >> if matdelim is None: >> matdelim = '(' >> else: >> if matstr is None: >> matstr = 'bmatrix' >> >> myprinter = LatexPrinter(inline, matstr=matstr, matdelim=matdelim, \ >> mainvar=mainvar, descending=descending) >> >> return myprinter.doprint(expr) >> >> class LatexPrinter(Printer): >> printmethod = "_latex_" >> >> def __init__(self, inline=True, matstr='bmatrix', matdelim=None, \ >> mainvar=None, descending=False): >> Printer.__init__(self) >> self._inline = inline >> self._matstr = matstr >> self._matdelim = matdelim >> self._delim_dict = {'(':')','[':']'} >> self._mainvar = mainvar >> self._descending = descending >> >> def _print_Add(self, expr): >> args = list(expr.args) >> if self._mainvar is not None: >> mainvar = self._mainvar >> >> def compare_exponents(a, b): >> p1, p2, p3 = Wild("p1"), Wild("p2"), Wild("p3") >> r_a = a.match(p1 * mainvar**p3) >> r_b = b.match(p1 * mainvar**p3) >> if r_a is not None and r_b is not None: >> c = Basic.compare(r_a[p3], r_b[p3]) >> if c!=0: >> return c >> >> return Basic._compare_pretty(a,b) >> >> args.sort(compare_exponents) >> else: >> args.sort(Basic._compare_pretty) >> if self._descending: >> args.reverse() >> tex = str(self._print(args[0])) >> >> for term in args[1:]: >> coeff = term.as_coeff_terms()[0] >> >> if coeff.is_negative: >> tex += r" %s" % self._print(term) >> else: >> tex += r" + %s" % self._print(term) >> >> return tex >> >> >> The part that seems hackish to me is that I have to define >> compare_exponents inside _print_Add. I don't know how else to set mainvar >> in a namespace that will be checked by compare_exponents while still >> allowing sympy.latex to change it. >> >> This more or less works for my first few tests: >> import sympy >> mylist = ['m', 's', 'b', 'x', 'y', 's', 'x', 'y', 's', 'EI'] >> sympy.var(mylist) >> test = m*s**2+b*x*y*s+x**2+y**2+s+EI+x**3 >> >> In [15]: sympy.latex(test) >> Out[15]: '$EI + s + b s x y + {x}^{2} + {y}^{2} + m {s}^{2} + {x}^{3}$' >> >> In [16]: sympy.latex(test, mainvar=s) >> Out[16]: '$EI + {x}^{2} + {y}^{2} + {x}^{3} + s + b s x y + m {s}^{2}$' >> >> In [17]: sympy.latex(test, mainvar=s, descending=True) >> Out[17]: '$m {s}^{2} + b s x y + s + {x}^{3} + {y}^{2} + {x}^{2} + EI$' >> >> But this test I can't explain: >> In [18]: sympy.latex(test, mainvar=x, descending=True) >> Out[18]: '${x}^{3} + m {s}^{2} + {x}^{2} + b s x y + {y}^{2} + s + EI$' >> >> why does m*s**2 get printed before x**2? >> >> Ryan >> >> >> >> On Tue, Jun 2, 2009 at 8:42 AM, Ryan Krauss <ryanli...@gmail.com> wrote: >> >>> Thanks. I think I understand what this code does. How do you want it >>> patched? Am I just writing my own alternative to sympy.latex? Are mainvar >>> and descending keyword arguments to sympy.latex or some other printing >>> function? I assume not everyone wants their polynomials in order of >>> descending powers or you guys would have already done this. >>> >>> Ryan >>> >>> On Mon, Jun 1, 2009 at 10:49 PM, Ondrej Certik <ond...@certik.cz> wrote: >>> >>>> >>>> On Mon, Jun 1, 2009 at 9:33 PM, Ryan Krauss <ryanli...@gmail.com> >>>> wrote: >>>> > So, I think I have a good test and a better understanding of the >>>> problem: >>>> > >>>> > mylist = ['m', 's', 'b', 'x', 'y', 's', 'x', 'y', 's', 'EI'] >>>> > sympy.var(mylist) >>>> > test = m*s**2+b*x*y*s+x**2+y**2+s+EI >>>> > args = list(test.args) >>>> > args.sort(sympy.Basic._compare_pretty) >>>> > args.reverse() >>>> > >>>> > >>>> > This doesn't get my list in the right order because of the number of >>>> > variables or whatever _compare_pretty does. >>>> > >>>> > It seems like I need to make a dictionary or something that uses the >>>> powers >>>> > of my main variable as the keys (this could cause issues if there is >>>> more >>>> > than one arg with the same power). What is the best way to sort based >>>> on >>>> > powers of the main variable? Is this the right approach: >>>> > args[1].as_coeff_exponent('s') >>>> > >>>> > (returns (y**2, 0) in this case) stepping through args in a for loop. >>>> >>>> I would just do it as I suggested above, e.g. like in >>>> sympy/core/basic.py:Basic._compare_pretty: >>>> >>>> @staticmethod >>>> def _compare_pretty(a, b): >>>> from sympy.series.order import Order >>>> if isinstance(a, Order) and not isinstance(b, Order): >>>> return 1 >>>> if not isinstance(a, Order) and isinstance(b, Order): >>>> return -1 >>>> >>>> # FIXME this produces wrong ordering for 1 and 0 >>>> # e.g. the ordering will be 1 0 2 3 4 ... >>>> # because 1 = x^0, but 0 2 3 4 ... = x^1 >>>> p1, p2, p3 = Wild("p1"), Wild("p2"), Wild("p3") >>>> r_a = a.match(p1 * p2**p3) >>>> r_b = b.match(p1 * p2**p3) >>>> if r_a is not None and r_b is not None: >>>> c = Basic.compare(r_a[p3], r_b[p3]) >>>> if c!=0: >>>> return c >>>> >>>> return Basic.compare(a,b) >>>> >>>> >>>> So for example this code: >>>> >>>> from sympy import Wild, var, Basic >>>> >>>> mylist = ['m', 's', 'b', 'x', 'y', 's', 'x', 'y', 's', 'EI'] >>>> var(mylist) >>>> test = m*s**2+b*x*y*s+x**2+y**2+s+EI >>>> args = list(test.args) >>>> >>>> def my_compare(a, b): >>>> main_var = s >>>> p1, p2, p3 = Wild("p1"), Wild("p2"), Wild("p3") >>>> r_a = a.match(p1 * s**p3) >>>> r_b = b.match(p1 * s**p3) >>>> if r_a is not None and r_b is not None: >>>> c = Basic.compare(r_a[p3], r_b[p3]) >>>> if c!=0: >>>> return c >>>> >>>> return Basic._compare_pretty(a,b) >>>> >>>> print args >>>> args.sort(my_compare) >>>> print args >>>> >>>> >>>> produces: >>>> >>>> [m*s**2, b*s*x*y, y**2, s, EI, x**2] >>>> [EI, x**2, y**2, s, b*s*x*y, m*s**2] >>>> >>>> >>>> This should fix your problem. Please send a patch. :) >>>> >>>> Ondrej >>>> >>>> >>>> >>>> >>> >> > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "sympy" group. To post to this group, send email to sympy@googlegroups.com To unsubscribe from this group, send email to sympy+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/sympy?hl=en -~----------~----~----~----~------~----~------~--~---