Comment #15 on issue 2552 by [email protected]: (1/(x*y)).subs(x*y, whatever) doesn't work
http://code.google.com/p/sympy/issues/detail?id=2552

Well, I think it's clear that we should either automatically convert (1/x)*(1/y) to 1/(x*y) or 1/(x*y) to (1/x)*(1/y) (otherwise, very simple cancelations will not work).

Remember that this behavior exists also for all powers, when the assumptions are valid. That's why we have sqrt(x*y) => sqrt(x)*sqrt(y) when x and y are positive. Note that this is consistant with the behavior with numerical arguments:

In [26]: sqrt(4*3)
Out[26]:
    ___
2⋅╲╱ 3

This can be thought of as converting it first to sqrt(4)*sqrt(3), and then reducing sqrt(4) because 4 is a perfect square (to be sure, the actual routine is a little different, because the number must first be factorized).

Also, note that this behavior is a little more apparent when the power is a negative integer less than -1:

In [27]: 1/(x*y)**2
Out[27]:
  1
─────
 2  2
x ⋅y

This is the equivalent of

In [28]: (x*y)**2
Out[28]:
 2  2
x ⋅y

So, in order to be consistant, we must have the same behavior for all powers, or at least all integer powers (of course, powers of 1 and 0 are trivial, so we don't consider them). So which is better, to have (x*y)**2 -> x**2*y**2 or x**2*y**2 -> (x*y)**2.

I think it should be clear that the former is what we want. Otherwise, things like (x**2*y**2)/y would not cancel without significantly complicating the logic of Mul.flatten, because the internal {base:exp} dict would be {x*y:2, y:-1} (right now, it becomes {x:2, y:2 - 1}).

So if you look at things like this, in terms of the Mul.flatten logic, we have to have 1/(x*y) become (1/x)*(1/y) internally. Otherwise, things will simply not cancel. Of course, we can make the printer smart enough to hide this from the user, and we have. And we also have to make things like subs smart enough to handle it.

I think that if we fix (1/(x*y)).subs(x*y, whatever) to work, then we should make (x**n*y**n).subs(x*y, whatever) work for any n where (x*y)**n == x**n*y**n (this will be at least all integers, and also fractional n if x and y are positive). This again, is for consistency.

Now, as it turns out, this *does* work, if n is a positive integer. This is because:

In [29]: (x**2*y**2).as_base_exp()
Out[29]: (x⋅y, 2)

So I think Chris is right. We need to just fix as_base_exp() to be completely consistant in this regard, and work for negative and fractional (when the assumptions on the base are correct) powers.

--
You received this message because you are subscribed to the Google Groups 
"sympy-issues" 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-issues?hl=en.

Reply via email to