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.