def del_edge(self, graph, edge): if edge not in set(self._mst): return self._mst # init disjoint set with iterable object uf = GenericUnionFind([(e.either(), e.other(e.either())) for e in self._mst if e is not edge]) pq = MinPQ() for e in graph.edges(): if e is not edge: pq.insert(e) tmp = Queue([e for e in self._mst if e is not edge]) # find the minimum edge with both vertices is not connected while not pq.is_empty(): min_edge = pq.del_min() vertx_a = min_edge.either() vertx_b = min_edge.other(vertx_a) if uf.connected(vertx_a, vertx_b): continue # only need one edge tmp.enqueue(min_edge) break self._mst = tmp return self._mst
def _init_priority_queue(self, vertices, forest): dup_set = set() pq = MinPQ() for v in vertices: for edge in forest.adjacent_edges(v): if edge not in dup_set: pq.insert(edge) dup_set.add(edge) return pq
class LazyPrimMST(object): """ Lazy version Prim-Minimum-Spanning-Tree. This algorithm is a greedy strategy. First input a start vertex, then visit all the adjacent edges, if the other side of the vertex is not marked, put the edge into a priority queue. The result queue only enqueue those edges with small weight and either vertex is not marked. The cost of space is proportional to number of edges, and the worst case of running time is proportional to O(ElogE) (E is the number of edges). >>> test_data = ((4, 5, 0.35), (4, 7, 0.37), (5, 7, 0.28), (0, 7, 0.16), (1, 5, 0.32), ... (0, 4, 0.38), (2, 3, 0.17), (1, 7, 0.19), (0, 2, 0.26), (1, 2, 0.36), ... (1, 3, 0.29), (2, 7, 0.34), (6, 2, 0.4), (3, 6, 0.52), (6, 0, 0.58), ... (6, 4, 0.93)) >>> ewg = EdgeWeightedGraph() >>> for a, b, weight in test_data: ... edge = Edge(a, b, weight) ... ewg.add_edge(edge) ... >>> lazy_prim_mst = LazyPrimMST(ewg, 0) >>> lazy_prim_mst.weight() 1.81 >>> [edge for edge in lazy_prim_mst.edges()] [0-7 0.16, 1-7 0.19, 0-2 0.26, 2-3 0.17, 5-7 0.28, 4-5 0.35, 6-2 0.4] """ def __init__(self, graph, start_vertex): self._pq = MinPQ() self._marked = defaultdict(bool) self._mst = Queue() self.visit(graph, start_vertex) while not self._pq.is_empty(): edge = self._pq.del_min() a = edge.either() b = edge.other(a) if self._marked[a] and self._marked[b]: continue self._mst.enqueue(edge) if not self._marked[a]: self.visit(graph, a) if not self._marked[b]: self.visit(graph, b) def visit(self, graph, vertex): self._marked[vertex] = True for edge in graph.adjacent_edges(vertex): if not self._marked[edge.other(vertex)]: self._pq.insert(edge) def edges(self): return self._mst # 4.3.31 practice, lazy weight implementation def weight(self): return sum(i.weight for i in self._mst)
def build_trie(freq): min_pq = MinPQ() for i in range(256): if freq[i]: min_pq.insert(chr(i), freq, None, None) while min_pq.size() > 1: left = min_pq.del_min() right = min_pq.del_min() parent = Node('\0', left.freq + right.freq, left, right) min_pq.insert(parent) return min_pq.del_min()
def __init__(self, graph, start_vertex): self._marked = defaultdict(bool) self._mst = Queue() self.pq = MinPQ() self.visit(graph, start_vertex) while not self.pq.is_empty(): edge = self.pq.del_min() if self._marked[edge[1]] and self._marked[edge[2]]: continue self._mst.enqueue(edge) if not self._marked[edge[1]]: self.visit(graph, edge[1]) if not self._marked[edge[2]]: self.visit(graph, edge[2])
def __init__(self, graph, start_vertex): self._pq = MinPQ() self._marked = defaultdict(bool) self._mst = Queue() self.visit(graph, start_vertex) while not self._pq.is_empty(): edge = self._pq.del_min() a = edge.either() b = edge.other(a) if self._marked[a] and self._marked[b]: continue self._mst.enqueue(edge) if not self._marked[a]: self.visit(graph, a) if not self._marked[b]: self.visit(graph, b)
class PrimitiveLazyPrimMST(object): """ >>> test_data = ((0.35, 4, 5), (0.37, 4, 7), (0.28, 5, 7), (0.16, 0, 7), (0.32, 1, 5), ... (0.38, 0, 4), (0.17, 2, 3), (0.19, 1, 7), (0.26, 0, 2), (0.36, 1, 2), ... (0.29, 1, 3), (0.34, 2, 7), (0.4, 6, 2), (0.52, 3, 6), (0.58, 6, 0), ... (0.93, 6, 4)) >>> wg = WeightedGraph() >>> for edge in test_data: ... wg.add_edge(edge) ... >>> primitive_mst = PrimitiveLazyPrimMST(wg, 0) >>> [edge for edge in primitive_mst.edges()] [(0.16, 0, 7), (0.19, 1, 7), (0.26, 0, 2), (0.17, 2, 3), (0.28, 5, 7), (0.35, 4, 5), (0.4, 6, 2)] """ def __init__(self, graph, start_vertex): self._marked = defaultdict(bool) self._mst = Queue() self.pq = MinPQ() self.visit(graph, start_vertex) while not self.pq.is_empty(): edge = self.pq.del_min() if self._marked[edge[1]] and self._marked[edge[2]]: continue self._mst.enqueue(edge) if not self._marked[edge[1]]: self.visit(graph, edge[1]) if not self._marked[edge[2]]: self.visit(graph, edge[2]) def visit(self, graph, vertex): self._marked[vertex] = True for edge in graph.adjacent_edges(vertex): if edge[1] == vertex and not self._marked[edge[2]]: self.pq.insert(edge) elif edge[2] == vertex and not self._marked[edge[1]]: self.pq.insert(edge) def edges(self): return self._mst def weight(self): return sum(edge[0] for edge in self._mst)
def _init_priority_queue(self, graph): pq = MinPQ() for edge in graph.edges(): pq.insert(edge) return pq
def _init_priority_queue(self, graph, contain_edges): pq = MinPQ() for edge in graph.edges(): if edge not in contain_edges: pq.insert(edge) return pq