Ask Your Question
1

substituting expressions for numbers

asked 2011-02-28 02:30:23 +0200

DSM gravatar image

Say you have some formula in the form of an expression:

sage: x,y,a,b = var("x y a b")
sage: f = 10*x+2*y
sage: type(f)
<type 'sage.symbolic.expression.Expression'>

Now I want to replace the 10 by the variable a. What's the easiest way to do this? It's the opposite of the typical substitution, so the functions I'd usually throw at it all fail.

So far I can only up with (1) string techniques, which are bugs waiting to happen, or (2) walking the entire expression tree and constructing a new expression from each operator/operand triplet.

edit retag flag offensive close merge delete

3 Answers

Sort by ยป oldest newest most voted
5

answered 2011-02-28 11:26:39 +0200

Mike Hansen gravatar image

If you don't want to use strings, then I think you do have to walk the expression tree at the moment. Sage does come with some tools to help with this in sage.symbolic.expression_conversions, but they could be improved. For example, something like the following should be added to the Sage library:

from sage.symbolic.expression_conversions import Converter

class DoNothing(Converter):
    def arithmetic(self, ex, operator):
        return reduce(operator, map(self, ex.operands()))
    def pyobject(self, ex, obj):
        return ex
    def symbol(self, ex):
        return ex
    def relation(self, ex, operator):
        return operator(*map(self, ex.operands()))
    def derivative(self, ex, operator):
        #We'll just ignore this for now
        return ex 
    def composition(self, ex, operator):
        return operator(*map(self, ex.operands()))

Then,

sage: f = 10*x + 3
sage: d = DoNothing()
sage: d(f)
10*x + 3

With this little utility class in place, you can write:

class TenReplacer(DoNothing):
    def pyobject(self, ex, obj):
        return 99 if obj == 10 else obj

and have

sage: f = 10*x + 3
sage: t = TenReplacer()
sage: t(f)
99*x + 3
sage: t(f == 10)
99*x + 3 == 99
sage: t(f == 100)
99*x + 3 == 100
edit flag offensive delete link more

Comments

That is pretty cool. If you open a ticket for this, please copy me. I sadly don't understand quite enough about how this works yet to contribute to it, but could help review. Walking expression trees is a constant support request, so this would be great. If that's what this does?

kcrisman gravatar imagekcrisman ( 2011-02-28 14:13:21 +0200 )edit
1

Nice. Expression hacking is too handy not to have better support; maybe Expressions should grow some more methods to handle common cases? Even a convert-to/from-sequence representation method would have made a question a while back a two-liner. I still can't help feeling that .subs({10:a}) should Just Work, though.

DSM gravatar imageDSM ( 2011-02-28 19:49:16 +0200 )edit
0

answered 2011-02-28 10:44:56 +0200

kcrisman gravatar image

Yikes! I assume you are doing an explicit example and now want to generalize.

Sorry, I think you will have to walk the expression tree. Hopefully I am wrong, but Sage just doesn't have methods for this built in yet. I don't even know that Maxima does. Axiom/Fricas might be more along those lines, I don't know. Honestly, I'd probably even do a string thing, as long as I could watch it step by step - like in a text editor - to make sure I wasn't making any erroneous replacements.

edit flag offensive delete link more

Comments

That was exactly the cause: there was a specific troublesome function and I wanted to see if I could find a smaller example when I realized I didn't know how..

DSM gravatar imageDSM ( 2011-02-28 19:37:55 +0200 )edit
1

answered 2011-02-28 19:35:01 +0200

DSM gravatar image

So that this is recorded somewhere, here's the simplest way I found (thanks @kcrisman-- I always forget that we can access maxima functionality). It turns out maxima's subst is pretty powerful:

sage: var("x a")
(x, a)
sage: f = 10*x+3
sage: f
10*x + 3
sage: maxima.subst(a, 10, f).sage()
a*x + 3

but then you have to live with any changes induced on the trip, whereas with Mike's solution you don't have to worry about that, and you can replace the "==" comparison by something which is as finely-tuned as you want.

I'd like f.subs({10:a}) to work, but I get lost in the code as soon as _gobjs start showing up..

edit flag offensive delete link more

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: 2011-02-28 02:30:23 +0200

Seen: 1,045 times

Last updated: Feb 28 '11