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
-~----------~----~----~----~------~----~------~--~---

Reply via email to