def path(self, source, target): if source == target: return starting_source, starting_target = source, target vertices_seen = set([source, target]) s_iter = self.__parent_edge.get(source) t_iter = self.__parent_edge.get(target) s_path, t_path = [], [] while s_iter != t_iter: if s_iter is not None: s_path.append(s_iter) source = other_vertex(s_iter, source) if source in vertices_seen: break vertices_seen.add(source) s_iter = self.__parent_edge.get(source) if t_iter is not None: t_path.append(t_iter) target = other_vertex(t_iter, target) if target in vertices_seen: break vertices_seen.add(target) t_iter = self.__parent_edge.get(target) if s_iter is None and t_iter is None: raise NoPathExistsError if source == starting_target or source == target: for edge in s_path: yield reverse_edge(edge) if target == starting_source or source == target: for edge in reversed(t_path): yield edge
def remove_vertex(self, v): if v not in self.__parent_edge: raise VertexNotFoundError(v) parent_edge = self.__parent_edge.pop(v) if parent_edge is not None: parent = other_vertex(parent_edge, v) self.__child_edges[parent].remove(parent_edge) for edge in self.__child_edges[v]: self.__parent_edge[other_vertex(edge, v)] = None del self.__child_edges[v]
def path(v,w): if v == w: return [v] v_mate = other_vertex(matching[v], v) if vertex_state[v] == EVEN: return [v, v_mate] + \ path(forest.get_tree(v_mate).parent().vertex, w) else: #vertex_state[v] == ODD x = bridge[v][0] y = other_vertex(bridge[v][1], bridge[v][0]) return [v] + [i for i in reversed(path(x, v_mate))] + path(y,w)
def make_tree(graph, source, edge_weight = None): parent = ydict(backend=graph) heap = yheap(backend=graph) distance = ydict(backend=graph) u, distance[u] = source, 0 while True: for e in graph.edges(source = u): if edge_weight[e] < 0: raise NegativeEdgeWeightError(e) v = other_vertex(e,u) distance_to_v = distance.get(v) relaxed_length = distance[u] + edge_weight[e] if distance_to_v is None or relaxed_length < distance_to_v: parent[v] = e distance[v] = relaxed_length if v in heap: heap.modifykey(v, relaxed_length) else: heap.insert(v, relaxed_length) try: u = heap.deletemin() except: return parent
def make_tree(graph, source, edge_weight = None): parent = ydict(backend=graph) distance = ydict(backend=graph) queue = ydeque(backend=graph) queue_members = ydict(backend=graph) queue.append(source) queue_members[source] = True distance[source] = 0 curr_pass = 0 curr_last = source num_vertices = sum(1 for v in graph.vertices()) while queue: v = queue.popleft() del queue_members[v] for e in graph.edges(source = v): w = other_vertex(e, v) dw, dv, e_weight = distance.get(w), distance[v], edge_weight[e] if dw is None or dv + e_weight < dw: distance[w] = dv + e_weight parent[w] = e if w not in queue_members: queue.append(w) queue_members[w] = True if v == curr_last and queue: curr_pass += 1 curr_last = queue[-1] if curr_pass >= num_vertices: raise NegativeCycleError return parent
def split(self, v): """ Given a vertex u, remove the edge from u to u's parent so they are in separate trees """ edge = self.__parent_edge.get(v) if edge is None: return w = other_vertex(edge, v) self.__parent_edge[v] = None self.__child_edges[w].remove(edge)
def reroot(self, v): current_node = v deferred_edges = list() while self.__parent_edge[current_node] is not None: parent_edge = self.__parent_edge[current_node] self.split(current_node) deferred_edges.append(reverse_edge(parent_edge)) current_node = other_vertex(parent_edge, current_node) for edge in deferred_edges: self.add_edge(*edge)
def __call__(self, **kwargs): if self.tree_type == "from_source": v = kwargs["target"] else: v = kwargs["source"] # TODO: simplify this mess edges = [] while self.tree.get(v) is not None: edges.append(self.tree[v]) v = other_vertex(self.tree[v], v) if self.tree_type == "from_source": for e in reversed(edges): yield e else: for e in edges: yield reverse_edge(e)
def walkup(self, v): PRINT('--- Starting walkup from %s ---' % v, 1) PRINT('--- edges to consider: %s ---' % \ [e for e in self.g.edges(source=v)]) for e in self.g.edges(source = v): w = other_vertex(e, v) PRINT('Looking at (v,w) = (%s,%s)' % (v,w), 4) if v == w: self.self_loops.append(e) continue if self.vis.DiscoverTime[w] < self.vis.DiscoverTime[v] or \ e == self.vis.ParentEdge[w]: continue self.backedges[w].append(e) timestamp = self.vis.DiscoverTime[v] self.backedge_flag[w] = timestamp for face_itr in chain((w,),self.first_face_iter(w)): PRINT('Traveler: %s' % face_itr) if face_itr == v or self.visited[face_itr] == timestamp: break elif self.is_bicomp_root(face_itr): PRINT('Setting visited/pertinent roots for %s' % face_itr) dfs_child = self.canonical_df_child[face_itr] parent = self.vis.Parent.get(dfs_child, dfs_child) handle = self.df_face_handle[dfs_child] PRINT('Handle: %s' % handle) if handle.vertex is not None: self.visited[handle.first_endpoint()] = timestamp self.visited[handle.second_endpoint()] = timestamp v_df_number = self.vis.DiscoverTime[v] if self.vis.LowPoint[dfs_child] < v_df_number or \ self.vis.LeastAncestor[dfs_child] < v_df_number: PRINT('Appending %s to %s''s prs' % (handle, parent)) self.pertinent_roots[parent].append(handle) else: PRINT("Prepending %s to %s's prs" % (handle, parent)) self.pertinent_roots[parent].insert(0,handle) self.visited[face_itr] = timestamp PRINT('--- Done with walkup from %s ---' % v, 1) PRINT('Visited: %s' % self.visited, 1)
def find_augmenting_path(g, initial_matching = None): vertex_state = dict() if initial_matching is None: matching = dict() else: matching = initial_matching even_edges = list() forest = tree.Forest(Vertices = g.vertices()) blossoms = UnionFind(g.vertices()) origin = dict((v,v) for v in g.vertices()) bridge = dict() for v in g.vertices(): if v not in matching: vertex_state[v] = EVEN for e in g.adjacent_edges(v): even_edges.append((v,other_vertex(e,v),e)) else: vertex_state[v] = UNREACHED augmenting_path_edge = None while even_edges: u,v,current_edge \ = even_edges.pop(int(random.uniform(0,len(even_edges)))) u_prime = origin[blossoms.find(u)] v_prime = origin[blossoms.find(v)] if vertex_state[v_prime] == UNREACHED: vertex_state[v_prime] = ODD; v_prime_mate = other_vertex(matching[v_prime], v_prime) vertex_state[v_prime_mate] = EVEN; forest.add_edge(parent = u, child = v_prime, parent_edge = current_edge ) forest.add_edge(parent = v_prime, child = v_prime_mate, parent_edge = matching[v_prime] ) for e in g.adjacent_edges(v_prime_mate): even_edges.append((v_prime_mate, other_vertex(e,v_prime_mate),e)) elif vertex_state[v_prime] == EVEN and u_prime != v_prime: try: nca = forest.nearest_common_ancestor(u_prime, v_prime) except tree.VertexNotFound: nca = None if nca is None: augmenting_path_edge = current_edge break for x in (u_prime, v_prime): prev_vertex = None for y in forest.get_tree(x).path_to_root(): if y == nca: break curr_vertex = origin[blossoms.find(y.vertex)] if curr_vertex == prev_vertex: continue blossoms.link(curr_vertex, nca.vertex) bridge[curr_vertex] = (x, current_edge) prev_vertex = curr_vertex origin[blossoms.find(nca.vertex)] = nca.vertex def path(v,w): if v == w: return [v] v_mate = other_vertex(matching[v], v) if vertex_state[v] == EVEN: return [v, v_mate] + \ path(forest.get_tree(v_mate).parent().vertex, w) else: #vertex_state[v] == ODD x = bridge[v][0] y = other_vertex(bridge[v][1], bridge[v][0]) return [v] + [i for i in reversed(path(x, v_mate))] + path(y,w) if augmenting_path_edge: x = g.source(augmenting_path_edge) y = g.target(augmenting_path_edge) x_up = path(x, forest.get_tree(x).get_root().vertex) y_up = path(y, forest.get_tree(y).get_root().vertex) print [i for i in reversed(x_up)] + y_up matching[g.source(augmenting_path_edge)] = augmenting_path_edge matching[g.target(augmenting_path_edge)] = augmenting_path_edge for path in (x_up,y_up): for x,y in izip(islice(path,1,None,2),islice(path,2,None,2)): matching[x] = matching[y] = forest.get_tree(x).parent_edge return matching