def min_steiner_tree(g,
                     obs_nodes,
                     p=None,
                     return_type='tree',
                     debug=False,
                     verbose=False):
    assert len(obs_nodes) > 0, 'no terminals'

    if g.num_vertices() == len(obs_nodes):
        print('it\'s a minimum spanning tree problem')

    gc, eweight, r2pred = build_closure(g,
                                        obs_nodes,
                                        p=p,
                                        debug=debug,
                                        verbose=verbose)
    # print('gc', gc)

    tree_map = min_spanning_tree(gc, eweight, root=None)
    tree = GraphView(gc, directed=False, efilt=tree_map)

    tree_edges = set()

    for e in tree.edges():
        u, v = map(int, e)
        recovered_edges = extract_edges_from_pred(u, v, r2pred[u])
        assert recovered_edges, 'empty!'
        for i, j in recovered_edges:
            tree_edges.add((i, j))

    tree_nodes = list(set(itertools.chain(*tree_edges)))

    if return_type == 'nodes':
        return tree_nodes
    elif return_type == 'edges':
        return list(map(edge2tuple, tree_edges))
    elif return_type == 'tree':
        vfilt = g.new_vertex_property('bool')
        vfilt.set_value(False)
        for n in tree_nodes:
            vfilt[n] = True

        efilt = g.new_edge_property('bool')
        for i, j in tree_edges:
            efilt[g.edge(i, j)] = 1
        subg = GraphView(g, efilt=efilt, vfilt=vfilt, directed=False)

        if p is not None:
            weights = subg.new_edge_property('float')
            for e in subg.edges():
                weights[e] = p[e]
        else:
            weights = None
        # remove cycles
        tree_map = min_spanning_tree(subg, weights, root=None)
        t = GraphView(g, directed=False, vfilt=vfilt, efilt=tree_map)
        return t
def min_steiner_tree(g, obs_nodes, debug=False, verbose=False):
    if g.num_vertices() == len(obs_nodes):
        print('it\'s a minimum spanning tree problem')

    gc, eweight, r2pred = build_closure(g,
                                        obs_nodes,
                                        debug=debug,
                                        verbose=verbose)
    # print('gc', gc)

    tree_map = min_spanning_tree(gc, eweight, root=None)
    tree = GraphView(gc, directed=False, efilt=tree_map)

    tree_edges = set()
    # print('tree', tree)
    for e in tree.edges():
        u, v = map(int, e)
        recovered_edges = extract_edges_from_pred(u, v, r2pred[u])
        assert recovered_edges, 'empty!'
        for i, j in recovered_edges:
            tree_edges.add(((i, j)))

    tree_nodes = list(set(itertools.chain(*tree_edges)))

    vfilt = g.new_vertex_property('bool')
    vfilt.set_value(False)
    for n in tree_nodes:
        vfilt[n] = True

    efilt = g.new_edge_property('bool')
    for i, j in tree_edges:
        efilt[g.edge(i, j)] = 1
    return GraphView(g, efilt=efilt, vfilt=vfilt)
def get_steiner_tree(g, root, obs_nodes, debug=False, verbose=False):
    gc, eweight, r2pred = build_closure(g, obs_nodes,
                                        debug=debug, verbose=verbose)

    tree_map = min_spanning_tree(gc, eweight, root=None)
    tree = GraphView(gc, directed=False, efilt=tree_map)

    tree_edges = set()
    for e in tree.edges():
        u, v = map(int, e)
        for i, j in extract_edges_from_pred(g, u, v, r2pred[u]):
            tree_edges.add((j, i))

    # a bit involved...
    und_tree = edges_to_directed_tree(g, root, tree_edges)
    return build_minimum_tree(g, root, obs_nodes, extract_edges(und_tree))
def get_steiner_tree(g, root, obs_nodes, debug=False, verbose=False):
    gc, eweight, r2pred = build_closure(g,
                                        obs_nodes,
                                        debug=debug,
                                        verbose=verbose)

    tree_map = min_spanning_tree(gc, eweight, root=None)
    tree = GraphView(gc, directed=False, efilt=tree_map)

    tree_edges = set()
    for e in tree.edges():
        u, v = map(int, e)
        for i, j in extract_edges_from_pred(g, u, v, r2pred[u]):
            tree_edges.add((j, i))

    # a bit involved...
    und_tree = edges_to_directed_tree(g, root, tree_edges)
    return build_minimum_tree(g, root, obs_nodes, extract_edges(und_tree))