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()
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()