# How can extract different terms from a symbolic expression?

I am trying to dissect an equation into its terms for statements such as "the first term in the denominator...". Optimally, I would like a list of terms, e.g.:

var('a b c x')
ex1 = a*x^2 + b/x - c
ex1.terms()


[a*x^2, b/x, c]

This used to be possible ages ago by just typing

ex1


a*x^2

ex1


b/x

etc.

Similarly, I would like to be able to extract the terms inside a log or exponent, nominator, denominator... Is there a structured way to do this?

UPDATE: Following on from the first answer given below, I tried:

var('a b c x')
ex1 = a*x^2 + b/x - c
print ex1.operands()
print ex1.operator()


[a*x^2, -c, b/x] <built-in function="" add="">

Other examples:

var('a b c x')
ex1 = a*x^2*b*c
print ex1.operands()
print ex1.operator()


[a, b, c, x^2] <built-in function="" mul="">

var('a b c x')
ex1 = a+x^2+b+c
print ex1.operands()
print ex1.operator()


[x^2, a, b, c] <built-in function="" add="">

I could now iterate through each list and link the terms with the top operator given by ex1.operator() to recover the original equation. Does anyone know how to do this?

How can I use the outputs of .operands() and .operator() to recover the original equation?

Thanks again!

edit retag close merge delete

Sort by » oldest newest most voted You can write your own parse tree class. It should be possible to plot the tree as graph.

class Tree(object):

    def __init__(self,item,left=None,right=None):
self.item = item
self.left = left
self.right = right

def show(self):
if self.left: self.left.show()
print self.item,
if self.right: self.right.show()

def evaluate(self):
"""
if self.item is an operator, it is a callable function,
so you can call it with left and right sub-tree as arguments
"""
if self.left==None and self.right==None:  # self.item is a 'leaf'
return self.item
elif self.left==None:  # unary operation
return self.item(self.right.evaluate())
else:                  # binary operation
return self.item(self.left.evaluate(),self.right.evaluate())

def create_tree(expr):
"""
expr is an expression  or(!)  a tuple containing an operation
and its list of operands
"""
if type(expr)==tuple:
op = expr
operands = expr
else:
try:
op = expr.operator()
operands = expr.operands()
except:
return Tree(expr)
if not op:
return Tree(expr)
else:
if len(operands) > 2:
return Tree(op,left=create_tree(operands),
right=create_tree((op,operands[1:])))
elif len(operands) == 2:
return Tree(op,left=create_tree(operands),
right=create_tree(operands))
else:
# unary operation , not testet
return Tree(op,right=create_tree(operands))

T=create_tree(5+x+x^2)
#T.show()
T.evaluate()

more Try ex1.operands(), ex1.operator() , ex1.op

var('a b c x')
ex1 = a*x^2 + b/x - c
ex1.operands()

[a*x^2, -c, b/x]


UPDATE: To show the parse tree, let us use a recursive function:

def print_tree(expr,k=0):
op = expr.operator()
operands = expr.operands()
if op:
print k*' ---',op, operands
k += 1
for operand in operands:
print_tree(operand,k)

print_tree(ex1)

more

Thank you, that's what I was looking for. I updated my question, considering these methods. *UPDATE*: The parse tree is helpful, but how do I put the equation back together?

There is code in symbolic/expression_conversions.pythat shows how to do this. See http://sagemath.org/doc/reference/cal...

I found a way to save the above tree to a list and reconstruct the original equation from its elements:

def fun_tree(expr,k=0):
list_elements = []
op = expr.operator()
operands = expr.operands()
if op:
print k*' ---',op, operands
list_elements.append((k,(op, operands)))
k += 1
for operand in operands:
list_elements.append(fun_tree(operand,k))
return list_elements


Example:

sage: var('a b c x')
sage: E = -a*x^3+x^2+b*(x-c)-a^x
sage: list_elements = fun_tree(E)
sage: level = 0
sage: opr = list_elements[level]
sage: ops = list_elements[level]
sage: t1 = ops
sage: for i in srange(1,len(ops)):    t1 = opr(t1, ops[i])
sage: t1


-ax^3 - b(c - x) + x^2 - a^x

more