def _kahn_adjacency_list(graph: Graph) -> list: S = Queue() in_degree = {u: 0 for u in graph.vertices} for u in graph.vertices: for v in graph.neighbors(u): in_degree[v.name] += 1 for u in graph.vertices: if in_degree[u] == 0: S.append(u) in_degree.pop(u) L = [] while S: n = S.popleft() L.append(n) for m in graph.neighbors(n): graph.remove_edge(n, m.name) in_degree[m.name] -= 1 if in_degree[m.name] == 0: S.append(m.name) in_degree.pop(m.name) if in_degree: raise ValueError("Graph is not acyclic.") return L
def _kahn_adjacency_list_parallel(graph: Graph, num_threads: int) -> list: num_vertices = len(graph.vertices) def _collect_source_nodes(graph: Graph) -> list: S = [] in_degree = {u: 0 for u in graph.vertices} for u in graph.vertices: for v in graph.neighbors(u): in_degree[v.name] += 1 for u in in_degree: if in_degree[u] == 0: S.append(u) return list(S) def _job(graph: Graph, u: str): for v in graph.neighbors(u): graph.remove_edge(u, v.name) L = [] source_nodes = _collect_source_nodes(graph) while source_nodes: with ThreadPoolExecutor(max_workers=num_threads) as Executor: for node in source_nodes: L.append(node) Executor.submit(_job, graph, node) for node in source_nodes: graph.remove_vertex(node) source_nodes = _collect_source_nodes(graph) if len(L) != num_vertices: raise ValueError("Graph is not acyclic.") return L
def _minimum_spanning_tree_kruskal_adjacency_matrix(graph): mst = Graph(*[getattr(graph, str(v)) for v in graph.vertices]) sort_key = lambda item: item[1].value dsf = DisjointSetForest() for v in graph.vertices: dsf.make_set(v) for _, edge in sorted(graph.edge_weights.items(), key=sort_key): u, v = edge.source.name, edge.target.name if dsf.find_root(u) is not dsf.find_root(v): mst.add_edge(u, v, edge.value) dsf.union(u, v) return mst
def _collect_source_nodes(graph: Graph) -> list: S = [] in_degree = {u: 0 for u in graph.vertices} for u in graph.vertices: for v in graph.neighbors(u): in_degree[v.name] += 1 for u in in_degree: if in_degree[u] == 0: S.append(u) return list(S)
def _minimum_spanning_tree_parallel_prim_adjacency_list(graph, num_threads): q = [ PriorityQueue(implementation='binomial_heap') for _ in range(num_threads) ] e = [dict() for _ in range(num_threads)] v2q = dict() mst = Graph(implementation='adjacency_list') itr = iter(graph.vertices) for i in range(len(graph.vertices)): v2q[next(itr)] = i % len(q) q[0].push(next(iter(graph.vertices)), 0) while True: _vs = [None for _ in range(num_threads)] with ThreadPoolExecutor(max_workers=num_threads) as Executor: for i in range(num_threads): Executor.submit(_find_min, q[i], _vs, i).result() v = None for i in range(num_threads): if _comp(_vs[i], v, lambda u, v: u.key < v.key): v = _vs[i] if v is None: break v = v.data idx = v2q[v] q[idx].pop() if not hasattr(mst, v): mst.add_vertex(graph.__getattribute__(v)) if e[idx].get(v, None) is not None: edge = e[idx][v] mst.add_vertex(edge.target) mst.add_edge(edge.source.name, edge.target.name, edge.value) mst.add_edge(edge.target.name, edge.source.name, edge.value) for w_node in graph.neighbors(v): w = w_node.name vw = graph.edge_weights[v + '_' + w] j = v2q[w] q[j].push(w, vw.value) if e[j].get(w, None) is None or \ e[j][w].value > vw.value: e[j][w] = vw return mst
def _minimum_spanning_tree_prim_adjacency_list(graph): q = PriorityQueue(implementation='binomial_heap') e = {} mst = Graph(implementation='adjacency_list') q.push(next(iter(graph.vertices)), 0) while not q.is_empty: v = q.pop() if not hasattr(mst, v): mst.add_vertex(graph.__getattribute__(v)) if e.get(v, None) is not None: edge = e[v] mst.add_vertex(edge.target) mst.add_edge(edge.source.name, edge.target.name, edge.value) mst.add_edge(edge.target.name, edge.source.name, edge.value) for w_node in graph.neighbors(v): w = w_node.name vw = graph.edge_weights[v + '_' + w] q.push(w, vw.value) if e.get(w, None) is None or e[w].value > vw.value: e[w] = vw return mst
def _generate_mst_object(graph): mst = Graph(*[getattr(graph, str(v)) for v in graph.vertices]) return mst
def _job(graph: Graph, u: str): for v in graph.neighbors(u): graph.remove_edge(u, v.name)