def steiner_tree(graph):
        leaf_nodes = graph.find_non_terminal_leaves()
        # Get a copy of the graph edges
        # we are going to delete edges from this dictionary (by setting their value to an empty list)
        new_edges = graph.edges.copy()
        # Same with the nodes
        new_nodes = graph.nodes.copy()
        # For all non-terminal leaves in the MST
        for leaf in leaf_nodes:
            node_num = leaf[0]
            edge_num = list(leaf[1].values())[0]
            leaf_edge = graph.edges[edge_num]
            # Second node connected to the edge
            second_node = leaf_edge[0] if leaf_edge[
                1] == node_num else leaf_edge[1]
            # Setting the value of the chosen edge and node to [] (as if we have deleted it)
            new_edges[edge_num] = []
            new_nodes[node_num] = []

            # Update the second node's degree and edges dictionary
            graph.nodes[second_node][0] -= 1
            graph.nodes[second_node][1].pop(node_num)

            # Checking if the remaining node is a leaf and not a terminal
            while graph.nodes[second_node][2] == 0 and graph.nodes[
                    second_node][0] == 1:
                node_num = second_node
                node_edges = graph.nodes[second_node][1]
                edge_num = list(node_edges.values())[0]
                leaf_edge = graph.edges[edge_num]

                second_node = leaf_edge[0] if leaf_edge[
                    1] == node_num else leaf_edge[1]

                new_edges[edge_num] = []
                new_nodes[node_num] = []

                graph.nodes[second_node][0] -= 1
                graph.nodes[second_node][1].pop(node_num)

        # Making new dictionaries of the updated nodes and edges to make a graph from them
        new_graph_nodes = {k: v[2] for k, v in new_nodes.items() if v != []}
        edge_number = 1
        new_graph_edges = {}
        for k, v in new_edges.items():
            if v:
                new_graph_edges[edge_number] = v
                edge_number += 1

        steiner_tree = Graph(len(new_graph_nodes), len(new_graph_edges),
                             new_graph_nodes, new_graph_edges)

        return steiner_tree, steiner_tree.graph_weight()
Ejemplo n.º 2
0
    def kruskal_algorithm(graph):
        union_find = UnionFind(graph.number_of_nodes)
        sorted_edges_list = graph.sort_edges()
        mst_nodes = {}
        mst_edges = {}
        edge_number = 1
        for edge in sorted_edges_list:
            first_node = graph.edges[edge[0]][0]
            second_node = graph.edges[edge[0]][1]
            weight = edge[1]
            result = union_find.union(first_node - 1, second_node - 1)
            # The nodes were in different sets and union was successful, update the graph
            if result == 1:
                # Adding the nodes to the MST, also setting their terminal status
                mst_nodes[first_node] = graph.nodes[first_node][2]
                mst_nodes[second_node] = graph.nodes[second_node][2]

                # Adding the edge to the MST
                mst_edges[edge_number] = [first_node, second_node, weight]
                edge_number += 1

        minimum_spanning_tree = Graph(len(mst_nodes), len(mst_edges),
                                      mst_nodes, mst_edges)
        return minimum_spanning_tree, minimum_spanning_tree.graph_weight()