This is the relevant code from Mul.flatten() (line 305 in core/mul.py): if len(c_part)==2 and c_part[0].is_Number and c_part[1].is_Add: # 2*(1+a) -> 2 + 2 * a coeff = c_part[0] c_part = [Add(*[coeff*f for f in c_part[1].args])]
So it autocombines only if there are exactly two terms, and the first one is a Number and the second one is an Add. Mul combines ieteravely, so this combines more often than you would think. But because of the iterative nature of it, it can depend on the order of the terms! >>> 2*(x+y)*z z⋅(2⋅x + 2⋅y) >>> (x + y)*2*z z⋅(2⋅x + 2⋅y) >>> z*(x + y)*2 2⋅z⋅(x + y) >>> z*2*(x + y) 2⋅z⋅(x + y) >>> 2*z*(x + y) 2⋅z⋅(x + y) This is also related to issue 1497. -(x + y)/z combines into (-x - y)/ z, but (x + y)/-z is left alone. And here are the below tests in actual Maple. They seem to be the same as Matlab with Maple. I also included my ones from above: > exp1:=x*(x-y); x (x - y) > exp2:=x*x-x*y; 2 x - x y > exp3:=4*(x-y); 4 x - 4 y > exp4:=4*x-4*y; 4 x - 4 y > factor(exp1); x (x - y) > factor(exp2); x (x - y) > factor(exp3); 4 x - 4 y > factor(exp4); 4 x - 4 y > 2*(x+y)*z; 2 (x + y) z > (x + y)*2*z; 2 (x + y) z > z*(x + y)*2; 2 (x + y) z > z*2*(x + y); 2 (x + y) z > 2*z*(x + y); 2 (x + y) z > factor(z*(2*x + 2*y)); 2 (x + y) z So it looks like Maple only does it when there are two terms and one is a number and the other is an Add. I think this is what was intended with the above code, but because of the iterative nature of Mul, it is impossible to tell how many terms there really are. I think this is another example of why it would be better for Mul and Add to somehow wait until iterative building is complete until autosimplifying (such as with handler logic). I don't see how you could have 4*(x + y) sometimes distribute and sometimes not. What would be the rules for when it is supposed to distribute and when it is supposed to stay? There is no way for Mul to tell if the user has input 4*(x + y) or if it has been returned from factor(). And even if it could, if the user did something like a = factor(4*x + 4*y), and then print a, it would just go back to 4*x + 4*y because the print a would be "user input". I vote to remove it. As I pointed out above, it doesn't even work consistently, and cannot as long as Mul.flatten() is called iteratively. Several tests will have to be fixed (it breaks Sum if I remember correctly. Probably others too). You may be able to just apply expand_mul to the relevant code blocks, or you may need to write a special function that only distributes in the way that is presently automatic. Or you may need to just restructure whatever algorithm to take non-distribution into account. Aaron Meurer On Jul 28, 2009, at 5:09 PM, Luke wrote: > > I'm exploring Sympy's behavior with regard to automatic distribution > of expressions. Purely from experimenting, I noticed a few things: > In [1]: exp1 = x*(x-y) > In [2]: exp2 = x*x-x*y > In [3]: exp3 = 4*(x-y) > In [4]: exp4 = 4*x-4*y > In [5]: exp1 > Out[5]: x⋅(x - y) > In [6]: exp2 > Out[6]: > 2 > -x⋅y + x > In [7]: exp3 > Out[7]: -4⋅y + 4⋅x > In [8]: exp4 > Out[8]: -4⋅y + 4⋅x > In [9]: factor(exp1) > Out[9]: x⋅(x - y) > In [10]: factor(exp2) > Out[10]: x⋅(x - y) > In [11]: factor(exp3) > Out[11]: -4⋅y + 4⋅x > In [12]: factor(exp4) > Out[12]: -4⋅y + 4⋅x > > I compared these four expressions in Sympy, Mathematica 7, Matlab > 2008a (Maple under the hood), Matlab 2008b (Mupad under the hood). > The results are as follows: > Mathematica 7 > In[5]:= x*(x-y) > Out[5]= x (x-y) > In[6]:= x*x-x*y > Out[6]= x^2-x y > In[7]:= 4*(x-y) > Out[7]= 4 (x-y) > In[8]:= 4*x-4*y > Out[8]= 4 x-4 y > In[9]:= Factor[In[5]] > Out[9]= x (x-y) > In[10]:= Factor[In[6]] > Out[10]= x (x-y) > In[11]:= Factor[In[7]] > Out[11]= 4 (x-y) > In[12]:= Factor[In[8]] > Out[12]= 4 (x-y) > > Matlab 2008a (Maple) >>> exp1 = x*(x-y) > exp1 = > x*(x-y) >>> exp2 = x*x-x*y > exp2 = > x^2-x*y >>> exp3 = 4*(x-y) > exp3 = > 4*x-4*y >>> exp4=4*x-4*y > exp4 = > 4*x-4*y >>> factor(exp1) > ans = > x*(x-y) >>> factor(exp2) > ans = > x*(x-y) >>> factor(exp3) > ans = > 4*x-4*y >>> factor(exp4) > ans > 4*x-4*y >>> > > Matlab 2008b (MuPad): >>> exp1 = x*(x-y) > exp1 = > x*(x - y) >>> exp2=x*x-x*y > exp2 = > x^2 - x*y >>> exp3=4*(x-y) > exp3 = > 4*x - 4*y >>> exp4=4*x-4*y > exp4 = > 4*x - 4*y >>> factor(exp1) > ans = > x*(x - y) >>> factor(exp2) > ans = > x*(x - y) >>> factor(exp3) > ans = > 4*(x - y) >>> factor(exp4) > ans = > 4*(x - y) >>> > > So three out of 4 automatically distribute things like 4*(x-y), but > not things like x*(x-y). In the case of Sympy and Matlab 2008a, this > automatic distribution is not easily reversible by a simple call to > factor. It seems to me that: > 1) there should be a way to control whether or not distribution occurs > automatically, and > 2) that if distribution does occur automatically, it should be easily > reversible, i.e. through something like factor > > Is there a way to keep 4*(x-y) as 4*(x-y) instead of -4*y+4*x? > > Thoughts? > > ~Luke > > > > --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---