Ask Your Question
0

can sage stop ordering terms?

asked 2013-10-24 01:58:50 -0500

frnhr gravatar image

updated 2015-01-13 14:22:17 -0500

FrédéricC gravatar image

Noob question incoming...

sage: var('A B C x y')
(A, B, C, x, y)
sage: y == (C - Ax) / B
y == -(A
x - C)/B

What I would like/expect to get here is y == (C - Ax)/B. Is there a way to tell Sage to stop ordering terms?

Rationale - the expression ultimately goes to latex() and I'd like to be able to control how the result looks like.

edit retag flag offensive close merge delete

3 answers

Sort by » oldest newest most voted
2

answered 2013-10-24 03:30:42 -0500

kcrisman gravatar image

Short answer is "probably not, unless you want to muck about in the internals of Ginac/Pynac, our symbolics engine". Even this one reorders:

sage: B.add(A,hold=True)
A + B

I think that some symbolics programs find a semi-canonical ordering and stick with that... Interestingly,

sage: C - A*x
-A*x + C

so the minus sign comes out only with the fraction. It's conceivable that one could consider this inconsistency a bug, though I am not qualified to assess that.

That said, perhaps one could make a feature request to control this, though I suspect this would be harder than one thinks.

edit flag offensive delete link more

Comments

If I had to guess, I'd say that Sage tries to guess the order of each term and sorts them accordingly. `x^3` will probably come before `x^2`, etc.

frnhr gravatar imagefrnhr ( 2013-10-25 06:54:56 -0500 )edit
1

answered 2013-10-24 04:48:49 -0500

updated 2013-10-24 12:21:14 -0500

Definitely we want that Sage reorders... We want A+B+A to become 2A + B...

I do not think it would be hard to manage a pretty print that put first the "positive" terms and then the negative ones (knowing that negative are considered as mul(x,-1)).

Here is a simple function that do it on the first level.

def pretty_print(E):
    if E.operator() == operator.add:
        pos = []
        neg = []
        for elt in E.operands():
            if (elt.operator() == operator.mul and elt.operands()[-1] < 0) or (elt.is_numeric() and elt < 0):
                neg.append(-elt)
            else:
                pos.append(elt)
        pos_str = ' + '.join(map(repr,pos))
        neg_str = ' + '.join(map(repr,neg))
        if len(neg) == 0:
            print pos_str
        elif len(neg) == 1:
            print pos_str + ' - ' + neg_str
        else:
            print ' + '.join(map(str,pos)) + ' - (' + ' + '.join(map(str,neg)) + ')'

    else:
        print E

Then inside Sage

sage: var('x,y,z,t')
sage: pretty_print(x-y+z)
x + z - y
sage: pretty_print(z-x-y)
z - (x + y)
sage: pretty_print(y-x-3*z+t)
t + y - (x + 3*z)
sage: pretty_print(3*x*y - 2*z*t - 3)
3*x*y - (2*t*z + 3)
edit flag offensive delete link more

Comments

Eek, tree walkers! Cool stuff. Any way to make this recursive for more complicated ones? :-)

kcrisman gravatar imagekcrisman ( 2013-10-24 05:52:11 -0500 )edit

We definitely want B+A+B to become 2A+B, but I'm in a situation that I don't want B+2A to become 2A+B. That pretty much sums it up :) Thanks for the effort on the function! Looks good for simple expressions, though I doubt this approach can be flexible enough for more complex expressions, e.g. fractions, several parenthesis etc.

frnhr gravatar imagefrnhr ( 2013-10-24 06:15:23 -0500 )edit

Sure my code does not work for more complicated expressions (and I do not want to do it). If you are really interested in that feature for more complex expressions either you walk on the tree as kcricsman pointed out (.operator and .operands makes you go one level down). You could also access to ginac which is the library used for symbolic expression.

vdelecroix gravatar imagevdelecroix ( 2013-10-24 12:30:16 -0500 )edit
1

answered 2013-10-24 22:17:08 -0500

ndomes gravatar image

Your example:

sage: y == C.add(-A*x,hold=True)/B
y == (C - A*x)/B

Another example:

sage: a = (-2*x).add(x^2,-x^3, hold=True); a
-2*x + x^2 - x^3

Further operations reorder the expression

sage: -2*a
2*x^3 - 2*x^2 + 4*x

You have to start with a symbolic expression:

sage: -2.mul(a,hold=True)
AttributeError: 'sage.rings.integer.Integer' object has no attribute
'mul'

sage: Expression(SR,-2).mul(a,hold=True)
-2*(-2*x + x^2 - x^3)

sage: a.mul(-2,hold=True)
-2*(-2*x + x^2 - x^3)

Don't know why kcrisman gets a reordered expression

sage: B.add(A,hold=True)
B + A
edit flag offensive delete link more

Comments

This does not work for me on 5.12.

tmonteil gravatar imagetmonteil ( 2013-10-24 23:59:41 -0500 )edit

I used an older version (5.6)

ndomes gravatar imagendomes ( 2013-10-25 03:34:25 -0500 )edit

I just tried Sage Cell Server (aleph.sagemath.org) x.add(x^2,hold=True) reorders to x^2 + x

ndomes gravatar imagendomes ( 2013-10-25 03:56:48 -0500 )edit

Yeah, this is probably because Pynac was upgraded a few times ago.

kcrisman gravatar imagekcrisman ( 2013-10-25 04:35:40 -0500 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

Stats

Asked: 2013-10-24 01:58:50 -0500

Seen: 256 times

Last updated: Oct 24 '13