better _new_rawargs

7 views
Skip to first unread message

smichr

unread,
Feb 21, 2011, 2:45:34 AM2/21/11
to sympy
AssocOp (from which Mul and Add derive) and QExpr both have
_new_rawargs methods.

This method is for very quickly rebuilding an expression from the args
given. No checking of any kind is done. It's ideally suited for the
situation where you remove a single argument from an Add, for example,
and want to rebuild the Add without that term:

h[4] >>> a = Add(3,x,y);args=a.args;args
(3, y, x)
h[4] >>> a._new_rawargs(*(args[:1]+args[2:])) # skipping arg 1
3 + x
h[4] >>>

The problem I see with the method is that it's hard to use in anything
but this rebuild case. A handy place to use this is in a method of
simplification (like factor) where you want to keep the coefficient
from becoming distributed into an Add as is normally done by Mul:

>>> 2*(1+x)
2 + 2*x

So I want to multiply 2 and 1+x but not do the distribution. Although
one can use Mul(2, 1+x, evaluate=False), this is slower than the
_new_rawargs method (by about a factor of 3). But in order to use the
_new_rawargs you already have to have a Mul in hand. You can't do

Mul._new_rawargs(Mul, S(2), 1+x)

so that defeats the speed of the method. Does anyone see a better way
to be doing this?

Brian Granger

unread,
Mar 8, 2011, 12:17:22 AM3/8/11
to sy...@googlegroups.com, smichr
Hi,

> This method is for very quickly rebuilding an expression from the args
> given. No checking of any kind is done. It's ideally suited for the
> situation where you remove a single argument from an Add, for example,
> and want to rebuild the Add without that term:
>
>    h[4] >>> a = Add(3,x,y);args=a.args;args
>    (3, y, x)
>    h[4] >>> a._new_rawargs(*(args[:1]+args[2:])) # skipping arg 1
>    3 + x
>    h[4] >>>
>
> The problem I see with the method is that it's hard to use in anything
> but this rebuild case. A handy place to use this is in a method of
> simplification (like factor) where you want to keep the coefficient
> from becoming distributed into an Add as is normally done by Mul:
>
>    >>> 2*(1+x)
>    2 + 2*x

From my experience with these types of things, it is dangerous to try
to bypass the logic in __new__ to avoid automatic manipulations from
being done. Every time I have done something like this, the trick
only works as long as I don't do further computations with the result.
There are so many things that call __new__ (rather than _new_rawargs)
it just isn't reliable. Mathematica has an option to "hold" a
computation to prevent things from happening that otherwise would.

> So I want to multiply 2 and 1+x but not do the distribution. Although
> one can use Mul(2, 1+x, evaluate=False), this is slower than the
> _new_rawargs method (by about a factor of 3). But in order to use the
> _new_rawargs you already have to have a Mul in hand. You can't do
>
>    Mul._new_rawargs(Mul, S(2), 1+x)
>
> so that defeats the speed of the method. Does anyone see a better way
> to be doing this?

I would think about implementing something like Mathematicas hold:

http://reference.wolfram.com/mathematica/ref/Hold.html

Cheers,

Brian

> --
> You received this message because you are subscribed to the Google Groups "sympy" group.
> To post to this group, send email to sy...@googlegroups.com.
> To unsubscribe from this group, send email to sympy+un...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/sympy?hl=en.
>
>

--
Brian E. Granger, Ph.D.
Assistant Professor of Physics
Cal Poly State University, San Luis Obispo
bgra...@calpoly.edu
elli...@gmail.com

Reply all
Reply to author
Forward
0 new messages