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.