Hi everyone.

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.

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