> As many of you may know, the main thing blocking the merge of my work
> on the Risch algorithm (see my integration3 branch) is not any
> deficiency in the algorithm, though there are several parts that are
> still not implemented, but the lack of a so called "atomic
> substitution" framework.  The relevant issue here is 2026
> (http://code.google.com/p/sympy/issues/detail?id=2026).
>
> Basically, the following breaks the preprocessing code in risch_integrate:
>
> In [1]: exp(2*x).subs(exp(x), y)
> Out[1]:
>  2
> y
>
> I need a way for subs to behave exactly, so the above would return
> exp(2*x).   Thus, I have disabled this completely in my integration3
> branch, but this is only a temporary solution, as there is a lot of
> code that relies on this behavior (especially in the series/limits
> code), and it would be a regression anyway.

I have always thought that subs should not know about any mathematical
relationships, but should behave as you are proposing (atomic or
exact=True).  In my mind, subs is a foundation that can be used to
build more advanced pattern matching and rule capabilities.  But those
more advanced rules (such as done by power) should be in subs itself,
but in that higher level.  Thus.

I am +1 on the exact or atomic keyword to subs (I prefer exact).

I am ++1 on having that be the default behavior

Cheers,

Brian

> So there needs to be a way to do
>
>>>> exp(2*x).subs(exp(x), y, atomic=True)
> exp(2*x)
>
> Now, as it turns out, it has come up in other places that people want
> control over the way that subs works in other ways.  In the issue, I
> talk about something called integer_powers, which would work like
>
>>>> exp(2*x).subs(exp(x), y, integer_powers=True)
> y**2
>>>> exp(x).subs(exp(2*x), y, integer_powers=True)
> exp(x)
>
> In other words, it does not do power manipulation in the replacement
> unless the resulting power is an integer.  This is needed in some
> places such as the heurisch algorithm to ensure that the resulting
> expression will be a polynomial (actually, a rational function) in the
> substitution variable.  In addition, there is also some concern about
> the assumptions validity of certain algebraic substitution rules.  See
> issues 2081 and 2552.
>
> So in the interest of doing this right, I think there needs to be some
> kind of hints mechanism to subs.  My question is, what do you think
> would be the best way to implement this?  Presently the expand
> function has something like this, but I'm not really convinced that
> the way that it's implemented is a very good one.
>
> Here's (roughly) the way that subs works now:  Basic defines two
> methods, .subs and ._eval_subs.  Basic.subs() is of course the user
> level function that everyone calls, and pretty much no subclass of
> Basic overrides it.  The actual substitution happens in ._eval_subs,
> which is also responsible for recursing the substitution down the
> .args.  Basic has a simple implementation, but most classes end up
> overriding it (for example, exp has overridden it to allow the above
> fancy algebraic substitution).
>
> What's the best way to implement the various hints I want to add to
> .subs()?  A few things to take into consideration:
>
> - .expand() works, as I mentioned earlier, by having
> ._eval_expand_hint() methods.  I don't think this is the best way, so
> that's why I'm asking here to see if anyone has any better ideas.
>
> - It should remain backwards compatible with any class that defines
> ._eval_subs(self, old, new).  Unfortunately, there wasn't much
> foresight when this was originally designed, so the protocol does not
> call for any *args or **kwargs.  However, that doesn't necessarily
> weigh those options out, as we could easily make Basic.subs() check
> for an old style definition and ignore hints in that case.
>
> - I haven't looked at it, but we might be able to implement at least
> atomic substitution entirely in Basic (no class need override any
> methods to get it to work).  This is because it is so simple that the
> default agnostic method might be able to do it entirely.  The rule for
> atomic substitution by the way is that expr.subs(old, new,
> atomic=True) should replace old with new in expr if and only if old is
> in expr.atoms(old.__class__).
>
> So I'm open to any ideas on how to implement this, API-wise.
>
> Also, Chris, did you start this at all in any of your branches and/or
> are you willing to help with this?
>
> Aaron Meurer
>
> --
> You received this message because you are subscribed to the Google Groups 
> "sympy" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to 
> [email protected].
> For more options, visit this group at 
> http://groups.google.com/group/sympy?hl=en.
>
>



-- 
Brian E. Granger
Cal Poly State University, San Luis Obispo
[email protected] and [email protected]

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

Reply via email to