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

Reply via email to