You should also know about pre/post_order_traversal (both must be imported from 
sympy.utilities.iterables), which let you dig all the way down in an expression 
tree.

In [109]: from sympy.utilities.iterables import preorder_traversal, 
postorder_traversal

In [110]: preorder_traversal(sin(x**2) + 4*x**3)
Out[110]: <generator object preorder_traversal at 0x102415a00>

In [111]: list(preorder_traversal(sin(x**2) + 4*x**3))
Out[111]: 
⎡   ⎛ 2⎞      3     3      3           ⎛ 2⎞   2      ⎤
⎣sin⎝x ⎠ + 4⋅x , 4⋅x , 4, x , x, 3, sin⎝x ⎠, x , x, 2⎦

In [112]: list(postorder_traversal(sin(x**2) + 4*x**3))
Out[112]: 
⎡          3     3         2     ⎛ 2⎞     ⎛ 2⎞      3⎤
⎣4, x, 3, x , 4⋅x , x, 2, x , sin⎝x ⎠, sin⎝x ⎠ + 4⋅x ⎦

Also, as Chris said, using .atoms() to find what IndexedElements there are is 
useful.  There maybe ought to be some .is_IndexedElement attribute on 
IndexedElement, just as there is for every other major class.  Øyvind, what do 
you think?

Aaron Meurer

On Sep 23, 2010, at 3:26 PM, Nicholas Kinar wrote:

> 
>> h[1]>>>  from sympy.tensor import *
>> h[1]>>>  M=Indexed('M')
>> h[1]>>>  var('i j k', integer=1)
>> (i, j, k)
>> h[2]>>>  eq=1+2*M(i,1)+3*j+4*M(i,2); eq
>> 1 + 2*M(i, 1) + 3*j + 4*M(i, 2)
>> h[3]>>>  for a in eq.as_Add():
>>      ...   ie = []
>>      ...   co = []
>>      ...   for m in a.as_Mul():
>>      ...     if isinstance(m, IndexedElement):
>>      ...       ie.append(m)
>>      ...     else:
>>      ...       co.append(m)
>>      ...   if ie:
>>      ...     print Mul(*co), Mul(*ie)
>>      ...
>> 4 M(i, 2)
>> 2 M(i, 1)
>> h[3]>>>
>> 
>> If there's always only going to be one IndexedElement per term then
>> you could find them all with atoms and then find their coefficients
>> with coeff. But if you are worried about efficiency then you could
>> just check for an IndexedElement atom in a given term and find the
>> coeff of it when found:
>> 
>> h[3]>>>  for a in eq.as_Add():
>>      ...   ie = a.atoms(IndexedElement)
>>      ...   if ie:
>>      ...     assert len(ie) == 1
>>      ...     ie = ie.pop()
>>      ...     print a.coeff(ie), ie
>>      ...
>> 4 M(i, 2)
>> 2 M(i, 1)
>> 
>> If you need to know which argument it was then you can use the
>> enumerate to keep track of which "a" it was that had that term:
>> 
>> h[3]>>>  for i, a in enumerate(eq.as_Add()):
>>      ...   ie = a.atoms(IndexedElement)
>>      ...   if ie:
>>      ...     assert len(ie) == 1
>>      ...     ie = ie.pop()
>>      ...     print i, a.coeff(ie), ie
>>      ...
>> 2 4 M(i, 2)
>> 3 2 M(i, 1)
>> h[3]>>>  print eq.args
>> (1, 3*j, 4*M(i, 2), 2*M(i, 1))
>> 
>>   
> Thanks Chris; that is exactly what I wanted, and the code snippets that you 
> gave demonstrates quite a few exciting features of sympy.
> 
> Nicholas
> 
> 
> 
> 
> 
> 
> 
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "sympy" group.
> To post to this group, send email to sy...@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.
> 

-- 
You received this message because you are subscribed to the Google Groups 
"sympy" group.
To post to this group, send email to sy...@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