Compute as a graphviz.Graph instance the given graph.

    If given BubbleTree instance is oriented, returned value
    is a graphviz.Digraph.

    See http://graphviz.readthedocs.io/en/latest/examples.html#cluster-py
    for graphviz API

def tree_to_graph(bbltree:BubbleTree) -> Graph or Digraph:
    """Compute as a graphviz.Graph instance the given graph.

    If given BubbleTree instance is oriented, returned value
    is a graphviz.Digraph.

    See http://graphviz.readthedocs.io/en/latest/examples.html#cluster-py
    for graphviz API

    """
    GraphObject = Digraph if bbltree.oriented else Graph
    def create(name:str):
        """Return a graphviz graph figurating a powernode"""
        ret = GraphObject('cluster_' + name)
        # dirty hack to get links between clusters: add a blank node inside
        # so the subgraph don't take it's name directly, but the blank node do.
        # ret.body.append('label = "{}"'.format(name))  # replaced by:
        ret.node(name, style='invis', shape='point')
        # ret.body.append('style=plaintext')
        ret.body.append('color=lightgrey')
        ret.body.append('label=""')
        ret.body.append('shape=ellipse')
        ret.body.append('penwidth=2')
        ret.body.append('pencolor=black')
        return ret
    nodes = frozenset(bbltree.nodes())
    subgraphs = {}
    # build for each powernode the associated subgraph, and add its successors
    for powernode in bbltree.powernodes():
        if powernode not in subgraphs:
            subgraphs[powernode] = create(powernode)
        for succ in bbltree.inclusions[powernode]:
            if succ not in subgraphs:
                if succ not in nodes:
                    subgraphs[succ] = create(succ)
                else:
                    subgraphs[powernode].node(succ)
    # add to Graph instances the Graph of successors as subgraphs 
    for powernode, succs in bbltree.inclusions.items():
        for succ in succs:
            if succ not in nodes:
                subgraphs[powernode].subgraph(subgraphs[succ])
    # build the final graph by adding to it subgraphs of roots
    graph = GraphObject('graph', graph_attr={'compound': 'true'})
    for root in bbltree.roots:
        if root in subgraphs:
            graph.subgraph(subgraphs[root])
    # add the edges to the final graph
    for source, targets in bbltree.edges.items():
        for target in targets:
            if source <= target:
                attrs = {}
                if source not in nodes:
                    attrs.update({'ltail': 'cluster_' + source})
                if target not in nodes:
                    attrs.update({'lhead': 'cluster_' + target})
                graph.edge(source, target, **attrs)
    # print(graph)  # debug line
    # graph.view()  # debug line
    return graph