2

I have multiple independent trees with in a graph. I want to extract them separately. I am using pydot for graphs. I want parent 1 graph and parent 2 graph separately. In my use case trees will grow randomly(not one by one).

graph = pydot.Dot(graph_type="digraph")

parent_node_1 = pydot.Node(name='Parent_1', style='filled', fillcolor='yellow')
parent_node_2 = pydot.Node(name='Parent_2', style='filled', fillcolor='yellow')

child_node_1 = pydot.Node(name='Child 1', style='filled', fillcolor='yellow')
child_node_2 = pydot.Node(name='Child 2', style='filled', fillcolor='yellow')

e1 = pydot.Edge('Parent_1', 'Child 1')
e2 = pydot.Edge('Parent_2', 'Child 2')

graph.add_node(parent_node_1)
graph.add_node(parent_node_2)

graph.add_node(child_node_1)
graph.add_node(child_node_2)

graph.add_edge(e1)
graph.add_edge(e2)

graph.write_png('dummy_graph.png')

Output of program

1 Answers1

1

This is a cumbersome problem in pydot, since you need to be able to traverse the graph in a simple way. It is possible, but I wouldn't recommend it. A simple code that works in your test case is in the snippet below. I can bet there is some mistake in it somewhere, so use it with caution.

def get_out_edges_and_children(g, node):
    out_edges = {e for e in g.get_edges() if e.get_source() == node.get_name()}
    children_names = {e.get_destination() for e in out_edges}
    children = [n for n in graph.get_nodes() if n.get_name() in children_names]
    return out_edges, children


all_node_names = {n.get_name() for n in graph.get_nodes()}
all_children_names = {e.get_destination() for e in graph.get_edges()}
all_roots = all_node_names - all_children_names #roots are children to noone

trees = []
for r in all_roots:
    nodes_to_process= graph.get_node(r)
    t = pydot.Dot()
    t.add_node(nodes_to_process[0])

    i = 0
    while i < len(nodes_to_process):
        current_node=nodes_to_process[i]
        edges,children = get_out_edges_and_children(graph,current_node)
        for c in children: t.add_node(c)
        for e in edges: t.add_edge(e)
        nodes_to_process += children
        i += 1

    trees.append(t)

Look at other graph libraries instead for more robust solutions, such as networkx. It can also import pydot objects, so the transition should be smooth!

LudvigH
  • 3,662
  • 5
  • 31
  • 49