Ask Your Question
2

How can extract different terms from a symbolic expression?

asked 2013-06-19 01:23:35 -0600

stan gravatar image

updated 2013-06-19 21:51:00 -0600

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[0]

a*x^2

ex1[1]

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 flag offensive close merge delete

3 answers

Sort by » oldest newest most voted
1

answered 2013-06-19 02:53:12 -0600

ndomes gravatar image

updated 2013-06-20 00:41:06 -0600

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)
edit flag offensive delete link more

Comments

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?

stan gravatar imagestan ( 2013-06-19 21:44:49 -0600 )edit

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

rws gravatar imagerws ( 2015-03-11 04:36:01 -0600 )edit
1

answered 2013-06-21 08:40:34 -0600

ndomes gravatar image

updated 2013-06-22 03:00:59 -0600

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[0]
        operands = expr[1]
    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[0]),
                           right=create_tree((op,operands[1:])))
        elif len(operands) == 2:
            return Tree(op,left=create_tree(operands[0]),
                           right=create_tree(operands[1])) 
        else:    
            # unary operation , not testet
            return Tree(op,right=create_tree(operands[0]))


T=create_tree(5+x+x^2)
#T.show()
T.evaluate()
edit flag offensive delete link more
0

answered 2015-03-10 08:05:45 -0600

stan gravatar image

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][1][0]
sage: ops = list_elements[level][1][1]
sage: t1 = ops[0]
sage: for i in srange(1,len(ops)):    t1 = opr(t1, ops[i])
sage: t1

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

edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2013-06-19 01:23:35 -0600

Seen: 796 times

Last updated: Mar 10 '15