Well, that's not surprising.  99% of the time, when sympy hangs (but still 
finishes) it is hanging in expand().   This is a place where a slight machine 
difference can make a difference, too, because of the way expand works.  
Basically, it places all the expansion hints in a dictionary, and then executes 
them in whatever order it pops them out in a for loop (see sympy/core/expr.py, 
line 895).  So if you have a slightly different order for expansion, it can 
easily make a difference.  For example, consider

(x + 1)*(x + 2)**10.  

If you first expand (x + 2)**10 using the expand_multinomial hint you get x + 1 
times 11 terms.  You then expand the (x + 1) around it using the expand_mul 
hint.  

But if you instead first expand using the expand_mul hint, you will get x*(x + 
2)**10 + (x + 2)**10, and then when you apply the expand_multinomial hint, you 
have to expand the (x + 2)**10 part TWICE.  (You will actually then have to run 
the expand_mul hint again to get the completely expanded expression). You can 
see how this can result in different execution times depending on the hint 
order.

The solution here, by the way, is to rewrite the expand() system using poly, 
which can expand (x + 1)*(x + 2)**10 all at once (i.e., in the most efficient 
way possible).  It is actually possible to do that now, using the poly() 
function.  So poly((x + 1)*(x + 2)**10).as_basic() would be the most efficient 
way to expand this:

In [1]: poly((x + 1)*(x + 2)**10).as_basic()
Out[1]: 
                       2          3          4          5          6         7  
       8        9       10    11
1024 + 6144⋅x + 16640⋅x  + 26880⋅x  + 28800⋅x  + 21504⋅x  + 11424⋅x  + 4320⋅x  
+ 1140⋅x  + 200⋅x  + 21⋅x   + x  

In [2]: %timeit poly((x + 1)*(x + 2)**10).as_basic()
1000 loops, best of 3: 906 us per loop

In [3]: ((x + 1)*(x + 2)**10).expand()
Out[3]: 
                       2          3          4          5          6         7  
       8        9       10    11
1024 + 6144⋅x + 16640⋅x  + 26880⋅x  + 28800⋅x  + 21504⋅x  + 11424⋅x  + 4320⋅x  
+ 1140⋅x  + 200⋅x  + 21⋅x   + x  

In [4]: %timeit ((x + 1)*(x + 2)**10).expand()
100 loops, best of 3: 7.93 ms per loop

In [5]: expand_multinomial((x + 1)*(x + 2)**10)
Out[5]: 
        ⎛                       2          3          4         5         6     
   7        8       9    10⎞
(1 + x)⋅⎝1024 + 5120⋅x + 11520⋅x  + 15360⋅x  + 13440⋅x  + 8064⋅x  + 3360⋅x  + 
960⋅x  + 180⋅x  + 20⋅x  + x  ⎠

In [6]: expand_mul((x + 1)*(x + 2)**10)
Out[6]: 
       10            10
(2 + x)   + x⋅(2 + x)  

In [7]: expand_multinomial(expand_mul((x + 1)*(x + 2)**10))
Out[7]: 
                  ⎛                       2          3          4         5     
    6        7        8       9    10⎞          2          3          4         
5         6        7        8       9   
1024 + 5120⋅x + x⋅⎝1024 + 5120⋅x + 11520⋅x  + 15360⋅x  + 13440⋅x  + 8064⋅x  + 
3360⋅x  + 960⋅x  + 180⋅x  + 20⋅x  + x  ⎠ + 11520⋅x  + 15360⋅x  + 13440⋅x  + 
8064⋅x  + 3360⋅x  + 960⋅x  + 180⋅x  + 20⋅x  + 

 10
x  

In [8]: expand_mul(expand_multinomial(expand_mul((x + 1)*(x + 2)**10)))
Out[8]: 
                       2          3          4          5          6         7  
       8        9       10    11
1024 + 6144⋅x + 16640⋅x  + 26880⋅x  + 28800⋅x  + 21504⋅x  + 11424⋅x  + 4320⋅x  
+ 1140⋅x  + 200⋅x  + 21⋅x   + x  

In [9]: %timeit expand_mul(expand_multinomial(expand_mul((x + 1)*(x + 2)**10)))
1000 loops, best of 3: 1.69 ms per loop

In [10]: expand_multinomial((x + 1)*(x + 2)**10)
Out[10]: 
        ⎛                       2          3          4         5         6     
   7        8       9    10⎞
(1 + x)⋅⎝1024 + 5120⋅x + 11520⋅x  + 15360⋅x  + 13440⋅x  + 8064⋅x  + 3360⋅x  + 
960⋅x  + 180⋅x  + 20⋅x  + x  ⎠

In [11]: expand_mul(expand_multinomial((x + 1)*(x + 2)**10))
Out[11]: 
                       2          3          4          5          6         7  
       8        9       10    11
1024 + 6144⋅x + 16640⋅x  + 26880⋅x  + 28800⋅x  + 21504⋅x  + 11424⋅x  + 4320⋅x  
+ 1140⋅x  + 200⋅x  + 21⋅x   + x  

In [12]: %timeit expand_mul(expand_multinomial((x + 1)*(x + 2)**10))
1000 loops, best of 3: 1.04 ms per loop

You can see from [4] that there is also a bottle neck from running the 
unnecessary hints (though I don't know how that scales).  

Aaron Meurer

On Oct 21, 2010, at 7:27 AM, Ryan Krauss wrote:

> So, I was surprised by the results of interrupting the code after
> different execution times.  I assumed it was hanging in the matrix
> inverse.  It actually completes the inverse in a minute or so and then
> spends the rest of the time trying to use the results of the inverse
> to compute several vectors.  The full traceback is below, but it hangs
> on this line:
> 
> /home/ryan/git/sympy/sympy/core/power.pyc in _eval_expand_basic(self)
>    258         (a+b+..) ** n -> a**n + n*a**(n-1)*b + .., n is positive 
> integer
>    259         """
> --> 260         b = self.base._eval_expand_basic()
>    261         e = self.exp._eval_expand_basic()
>    262
> 
> 
> The toplevel calculation that is causing the problem is here:
> /home/ryan/git/research/sympy_TMM.pyc in find_base_vector(Uin)
>    310     submati = find_submat_inv(Uin)
>    311     Uc4 = Uin[2:4,4]
> --> 312     MbVb = -1.0*(submati*Uc4)
>    313     z_b = zeros((5,1))
>    314     z_b[2] = MbVb[0]
> 
> submati is a 2x2 matrix of fairly complicated terms.  Uc4 is a 2x1
> column vector.
> 
> Ryan
> 
> Full traceback:
> 
> In [5]: run symbolic_poles_and_zeros.py
> ^C---------------------------------------------------------------------------
> KeyboardInterrupt                         Traceback (most recent call last)
> 
> /home/ryan/siue/Research/papers/SFLR_2010_paper/python/symbolic_poles_and_zeros.py
> in <module>()
>    6
>    7 mymodel = JVC_model.model_w_bm()
> ----> 8 mymodel.find_symbolic_bodes(save=0)
>    9
>     10
> 
> /home/ryan/siue/Research/papers/SFLR_2010_paper/python/JVC_model.pyc
> in find_symbolic_bodes(self, save)
>    740         U6 = beam2.Get_Aug_Mat(s)
>    741         Usys = U6*(U5*(U4*(U3*(U2*(U1*U0)))))
> --> 742         z_b = sympy_TMM.find_base_vector(Usys)
>    743         z_enc = U2*(U1*(U0*z_b))
>    744         enc_gain = 180.0/pi*1024.0/360.0
> 
> /home/ryan/git/research/sympy_TMM.pyc in find_base_vector(Uin)
>    310     submati = find_submat_inv(Uin)
>    311     Uc4 = Uin[2:4,4]
> --> 312     MbVb = -1.0*(submati*Uc4)
>    313     z_b = zeros((5,1))
>    314     z_b[2] = MbVb[0]
> 
> /home/ryan/git/sympy/sympy/matrices/matrices.pyc in __mul__(self, a)
>    399     def __mul__(self,a):
>    400         if hasattr(a, "__array__"):
> --> 401             return matrix_multiply(self,a)
>    402         out = Matrix(self.lines,self.cols,map(lambda i: i*a,self.mat))
>    403         return out
> 
> /home/ryan/git/sympy/sympy/matrices/matrices.pyc in matrix_multiply(A, B)
>   1483     blst = B.T.tolist()
>   1484     alst = A.tolist()
> -> 1485     return Matrix(A.shape[0], B.shape[1], lambda i,j:
>   1486                                         reduce(lambda k,l: k+l,
>   1487                                         map(lambda n,m: n*m,
> 
> /home/ryan/git/sympy/sympy/matrices/matrices.pyc in __init__(self, *args)
>     87             for i in range(self.lines):
>     88                 for j in range(self.cols):
> ---> 89                     self.mat.append(sympify(operation(i, j)))
>     90         elif len(args)==3 and isinstance(args[0],int) and \
>     91                 isinstance(args[1],int) and
> isinstance(args[2], (list, tuple)):
> 
> /home/ryan/git/sympy/sympy/matrices/matrices.pyc in <lambda>(i, j)
>   1487                                         map(lambda n,m: n*m,
>   1488                                         alst[i],
> -> 1489                                         blst[j])).expand())
>   1490                                         # .expand() is a test
> 
>   1491
> 
> /home/ryan/git/sympy/sympy/core/basic.pyc in expand(self, **hints)
>   1477         if not 'basic' in hints:
>   1478             if not expr.is_Atom:
> -> 1479                 result = expr._eval_expand_basic()
>   1480
>   1481                 if result is not None:
> 
> /home/ryan/git/sympy/sympy/core/basic.pyc in _eval_expand_basic(self)
>   1403                 terms.append(term)
>   1404             else:
> -> 1405                 T = term._eval_expand_basic()
>   1406
>   1407                 if T is None:
> 
> /home/ryan/git/sympy/sympy/core/mul.pyc in _eval_expand_basic(self)
>    396         else:
>    397             if sums:
> --> 398                 terms = Mul._expandsums(sums)
>    399
>    400                 if isinstance(terms, Basic):
> 
> /home/ryan/git/sympy/sympy/core/mul.pyc in _expandsums(sums)
>    363         for a in left:
>    364             for b in right:
> --> 365                 terms.append(Mul(a,b).expand())
>    366             added = Add(*terms)
>    367             if added.is_Add:
> 
> /home/ryan/git/sympy/sympy/core/basic.pyc in expand(self, **hints)
>   1477         if not 'basic' in hints:
>   1478             if not expr.is_Atom:
> -> 1479                 result = expr._eval_expand_basic()
>   1480
>   1481                 if result is not None:
> 
> /home/ryan/git/sympy/sympy/core/mul.pyc in _eval_expand_basic(self)
>    375
>    376         for factor in self.args:
> --> 377             terms = factor._eval_expand_basic()
>    378
>    379             if terms is not None:
> 
> /home/ryan/git/sympy/sympy/core/power.pyc in _eval_expand_basic(self)
>    258         (a+b+..) ** n -> a**n + n*a**(n-1)*b + .., n is positive 
> integer
>    259         """
> --> 260         b = self.base._eval_expand_basic()
>    261         e = self.exp._eval_expand_basic()
>    262
> 
> /home/ryan/git/sympy/sympy/core/basic.pyc in _eval_expand_basic(self)
>   1403                 terms.append(term)
>   1404             else:
> -> 1405                 T = term._eval_expand_basic()
>   1406
>   1407                 if T is None:
> 
> /home/ryan/git/sympy/sympy/core/mul.pyc in _eval_expand_basic(self)
>    375
>    376         for factor in self.args:
> --> 377             terms = factor._eval_expand_basic()
>    378
>    379             if terms is not None:
> 
> /home/ryan/git/sympy/sympy/core/power.pyc in _eval_expand_basic(self)
>    258         (a+b+..) ** n -> a**n + n*a**(n-1)*b + .., n is positive 
> integer
>    259         """
> --> 260         b = self.base._eval_expand_basic()
>    261         e = self.exp._eval_expand_basic()
>    262
> 
> /home/ryan/git/sympy/sympy/core/basic.pyc in _eval_expand_basic(self)
>   1403                 terms.append(term)
>   1404             else:
> -> 1405                 T = term._eval_expand_basic()
>   1406
>   1407                 if T is None:
> 
> /home/ryan/git/sympy/sympy/core/mul.pyc in _eval_expand_basic(self)
>    390
>    391                 if terms is not None:
> --> 392                     rewrite = True
>    393
>    394         if not rewrite:
> 
> KeyboardInterrupt:
> WARNING: Failure executing file: <symbolic_poles_and_zeros.py>
> 
> 
> 
> On Thu, Oct 21, 2010 at 7:16 AM, Øyvind Jensen <[email protected]> 
> wrote:
>> to., 21.10.2010 kl. 06.43 -0500, skrev Ryan Krauss:
>>> Thanks for the suggestion.  I will see if I can find a place to clear
>>> the cache.  Ironically, the slower machine has more RAM than the fast
>>> one.
>> 
>> Oh, well then maybe the problem is something else.  clear_cache is only
>> useful if you are running out of RAM.
>> 
>>> 
>>> I didn't know what generic-pae meant until I just googled it.  I guess
>>> it is a way to allow 32-bit machines to have more than 3 GB of RAM.
>>> The laptop has 4 GB.  Does the fact that the kernel is using a generic
>>> processor cause problems?
>>> 
>> 
>> Sorry, I don't know much about hardware.
>> 
>> Sometimes Sympy can behave slightly different on two computers because
>> certain functionalities in Python are platform dependent, like the hash.
>> However, differences should only occur for unimportant things, such as
>> the order of terms in an expression.
>> 
>> If there is a specific statement where a hang occurs, it may indicate an
>> issue that is triggered only on certain platforms.  Could you see if you
>> get the same traceback every time you kill the hanging script?  (or
>> almost the same)  In that case, could you post it here?
>> 
>> Øyvind
>> 
>>> Thanks,
>>> 
>>> Ryan
>>> 
>>> On Thu, Oct 21, 2010 at 6:37 AM, Øyvind Jensen <[email protected]> 
>>> wrote:
>>>>> Any idea what could make this machine so unhappy to run sympy?
>>>> 
>>>> In my (limited) experience, memory is the bottle-neck when you see the
>>>> kind of slow down you describe.  You may try to clear the cache at some
>>>> point in your calculation.
>>>> 
>>>>>>> from sympy.core.cache import clear_cache
>>>>>>> clear_cache()
>>>> 
>>>> Øyvind
>>>> 
>>>>> 
>>>>> Thanks,
>>>>> 
>>>>> Ryan
>>>>> 
>>>> 
>>>> --
>>>> You received this message because you are subscribed to the Google Groups 
>>>> "sympy" 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?hl=en.
>>>> 
>>>> 
>>> 
>> 
>> --
>> You received this message because you are subscribed to the Google Groups 
>> "sympy" 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?hl=en.
>> 
>> 
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "sympy" 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?hl=en.
> 

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

Reply via email to