Ask Your Question

Revision history [back]

One way to do this would be to modify the original tree function to parse the list; another would be to build the graph directly. The second one is slightly trickier because the names of graph vertices must be unique, so you have to ensure this with some kind of global counter. Here's one version I made by writing a class to contain both the counter, the graph, and the recursive tree builder:

class ExpressionGraph():
    def __init__(self,expr):
        self.G = Graph()
        self.i = 0
        print self.i
        print "(init)"
        self.expr = expr
        self.graph_expr(self.expr)
    def graph_expr(self,expr):
        if expr.operator() is None:
            name = "[{0}] {1}".format(self.i,expr)
            self.i += 1
            print self.i
            print "(leaf) "+str(expr)
            self.G.add_vertex(name)
            return name
        else:
            name = "[{0}] {1}".format(self.i,expr.operator().__name__)
            self.i += 1
            print self.i
            print "(node) "+str(expr)
            new_nodes = []
            for opnd in expr.operands():
                new_nodes += [self.graph_expr(opnd)]
            self.G.add_vertex(name)
            self.G.add_edges([(name,node) for node in new_nodes])
            return name

Note that I've included some print statements so you can see how it's working:

f = x^2 + 3*x + 5
E1 = ExpressionGraph(f)

prints out

0
(init)
1
(node) x^2 + 3*x + 5
2
(node) x^2
3
(leaf) x
4
(leaf) 2
5
(node) 3*x
6
(leaf) x
7
(leaf) 3
8
(leaf) 5

and E.G.show() plots the tree:

image description

click to hide/show revision 2
plot _rooted_ tree, and other minor improvements

One way to do this would be to modify the original tree function to parse the list; another would be to build the graph directly. The second one is slightly trickier because the names of graph vertices must be unique, so you have to ensure this with some kind of global counter. Here's one version I made by writing a class to contain both the counter, the graph, and the recursive tree builder:

class ExpressionGraph():
    def __init__(self,expr):
        self.G = Graph()
        self.i = 0
        self.expr = expr
        self.root = None
        self.graph_expr(self.expr)
    def plot(self,*args,**kwds):
        #print "root is {0}".format(self.root)
        return self.G.plot(*args,layout='tree',tree_root=self.root,**kwds)
    def graph_expr(self,expr):
        try:
            operator = expr.operator()
        except AttributeError: # e.g. if expr is an integer
            operator = None

        if operator is None:
            name = "[{0}] {1}".format(self.i,expr)
            print self.i
         print "(init)"
        self.expr = expr
        self.graph_expr(self.expr)
    def graph_expr(self,expr):
        if expr.operator() is None:
            name = "[{0}] {1}".format(self.i,expr)
"(leaf) {0}".format(expr)
            self.i += 1
            self.G.add_vertex(name)
            return name
        else:
            name = "[{0}] {1}".format(self.i,expr.operator().__name__)
            print self.i
            print "(leaf) "+str(expr)
            self.G.add_vertex(name)
            return "(node) {0}; {1}".format(expr,expr.operator().__name__)
            if self.i == 0:
                self.root = name
        else:
            name = "[{0}] {1}".format(self.i,expr.operator().__name__)
        print "  ** root is '{0}' **".format(self.root)
            self.i += 1
            print self.i
            print "(node) "+str(expr)
            new_nodes = []
            for opnd in expr.operands():
                new_nodes += [self.graph_expr(opnd)]
            self.G.add_vertex(name)
            self.G.add_edges([(name,node) for node in new_nodes])
            return name

Note that I've included some print statements so you can see how it's working:

f = x^2 + 3*x + 5
E1 2*(x+2^x)
E = ExpressionGraph(f)

prints out

0
(init)
(node) 2*2^x + 2*x; add
  ** root is '[0] add' **
1
(node) x^2 + 3*x + 5
2*2^x; mul
2
(node) x^2
2^x; pow
3
(leaf) x
2
4
(leaf) x
5
(leaf) 2
5
6
(node) 3*x
6
2*x; mul
7
(leaf) x
7
(leaf) 3
8
(leaf) 5
2

and E.G.show()E.plot() plots the tree:tree, with additional arguments passed to the underlying graph. For example:

E.plot(vertex_size=2000,vertex_colors='#ffccff')

image descriptionimage description