def __shortest_path_lengths_noinf(g, src): """Compute shortest-path distances from src to reachable vertices of g without python inf notation.""" dist = {} # dist[v] is upper bound from s to v cloud = {} # map reachable v to its dist[v] value pq = AdaptableHeapPriorityQueue() # vertex v will have key dist[v] pq_locator = {} # map from vertex to its pq locator dist[src] = 0 pq_locator[src] = pq.add(0, src) while not pq.is_empty(): key, u = pq.remove_min() cloud[u] = key # its correct dist[u] value del pq_locator[u] # u is no longer needed for edge in g.incident_edges(u): # outgoing edges (u, v) v = edge.opposite(u) if v not in cloud: # perform relaxation step on edge (u, v) new_dist = dist[u] + edge.element() if v not in dist: # add an vertex to dist until after an edge reaches it dist[v] = new_dist # and add it to the priority queue and save locator for # future updates pq_locator[v] = pq.add(new_dist, v) elif dist[v] > new_dist: # If better path to v exists... dist[v] = new_dist # update the distance, and... pq.update(pq_locator[v], new_dist, v) # the pq entry # Now, dist and cloud are the same, they both only include the reachable # vertices. return cloud
def MST_PrimJarnik(g): # O((n+m)logn) """Compute a minimum spanning tree of simple connected weighted graph g. Return a list of edges that comprise the MST (in arbitrary order). """ dist = {} # dist[v] is bound on distance to tree tree = [] # list of edges in spanning tree pq = AdaptableHeapPriorityQueue() # dist[v] maps to value (v, e=(u, v)) pq_locator = {} # map from vertex to its pq locator # for each vertex v of the graph, add an entry to the priority queue, # with the source having distance 0 and all others having infinite dist- # ance. for v in g.vertices(): dist[v] = float("inf") if len(dist) > 0 else 0 pq_locator[v] = pq.add(dist[v], (v, None)) while not pq.is_empty(): _, (u, edge) = pq.remove_min() # unpack tuple from pq del pq_locator[u] # u is no longer in pq if edge is not None: tree.append(edge) # add edge to tree for link in g.incident_edges(u): v = link.opposite(u) if v in pq_locator: # thus v not yet in tree # see if edge (u, v) better connects v to the growing tree wgt = link.element() if wgt < dist[v]: dist[v] = wgt # update the distance and ... pq.update(pq_locator[v], wgt, (v, link)) # the pq entry return tree
def __shortest_path_lengths_inf(g, src): """Compute shortest-path distances from src to reachable vertices of g with python inf notation.""" dist = {} # dist[v] is upper bound from s to v cloud = {} # map reachable v to its dist[v] value pq = AdaptableHeapPriorityQueue() # vertex v will have key dist[v] pq_locator = {} # map from vertex to its pq locator # for each vertex v of the graph, add an entry to the priority queue, with # the source having distance 0 and all others having infinite distance for v in g.vertices(): if v is src: dist[v] = 0 else: dist[v] = float('inf') # syntax for positive infinity pq_locator[v] = pq.add(dist[v], v) # save locator for future updates while not pq.is_empty(): key, u = pq.remove_min() cloud[u] = key # its correct dist[u] value del pq_locator[u] # u is no longer in pq for e in g.incident_edges(u): # outgoing edges (u,v) v = e.opposite(u) if v not in cloud: # perform relaxation step on edge (u,v) wgt = e.element() if dist[u] + wgt < dist[v]: # better path to v? dist[v] = dist[u] + wgt # update the distance, and pq.update(pq_locator[v], dist[v], v) # the pq entry return cloud # only includes reachable vertices