def graph_extract(s: int, g: Graph, pmap_vrelevant=None, pmap_erelevant=None, callback_vertex_extract=None, callback_edge_extract=None): """ Extract the edges of a given Graph according to an edge-based filtering starting from a given source node. Args: s: The VertexDescriptor of the source node. g: A Graph instance. pmap_vrelevant: A ReadPropertyMap{VertexDescriptor : bool} which indicates for each vertex whether if it must be duped or not. pmap_erelevant: A ReadPropertyMap{EdgeDescriptor : bool} which indicates each edge of the Graph with a boolean equal to True iff the edge is relevant. callback_vertex_extract: callback_edge_extract: """ if not pmap_vrelevant: pmap_vrelevant = make_func_property_map(lambda u: True) if not pmap_erelevant: pmap_erelevant = make_func_property_map(lambda e: True) map_vcolor = defaultdict(int) pmap_vcolor = make_assoc_property_map(map_vcolor) vis = DepthFirstSearchExtractVisitor(pmap_vrelevant, pmap_erelevant, pmap_vcolor, callback_vertex_extract, callback_edge_extract) depth_first_search(s, g, pmap_vcolor, vis, if_push=lambda e, g: pmap_erelevant[e] and pmap_vrelevant[target(e, g)])
def test_all(): for directed in [True, False]: for (i, g) in enumerate([make_g1(directed), make_g2(directed)]): print("Processing G%s (directed = %s)" % (i, directed)) vis = MyDepthFirstSearchVisitor(verbose=False) map_color = defaultdict(int) depth_first_search(0, g, make_assoc_property_map(map_color), vis) n = num_vertices(g) m = num_edges(g) n_ = vis.num_vertices m_ = vis.num_edges # Our graph are connected, so these assertion should be verified assert n_ == n, "Visited %s/%s vertices" % (n_, n) if directed: assert m_ == m, "Visited %s/%s edges" % (m_, m) else: # Undirected edges are visited forward and backward, so they are visited "twice" # Not that (u -> u) arc would be only visited once. assert m_ == 2 * m, "Visited %s/%s edges" % (m_, m) # Finally, all vertices should all be BLACK for u in vertices(g): assert map_color[u] == BLACK
def graph_copy(s: int, g: Graph, g_dup: Graph, pmap_vrelevant: ReadPropertyMap = None, pmap_erelevant: ReadPropertyMap = None, pmap_vertices: ReadWritePropertyMap = None, pmap_edges: ReadWritePropertyMap = None, callback_dup_vertex=None, callback_dup_edge=None): """ Copy a sub-graph from a Graph according to an edge-based filtering starting from a given source node. Args: s: The VertexDescriptor of the source node. g: A Graph instance. pmap_vrelevant: A ReadPropertyMap{VertexDescriptor : bool} which indicates for each vertex whether if it must be duped or not. Only used if vis == None. pmap_erelevant: A ReadPropertyMap{EdgeDescriptor : bool} which indicates for each edge whether if it must be duped or not. Only used if vis == None. callback_dup_vertex: Callback(u, g, u_dup, g_dup). Pass None if irrelevant. callback_dup_edge: Callback(e, g, e_dup, g_dup). Pass None if irrelevant. vis: Pass a custom DepthFirstSearchExtractVisitor or None. This visitor must overload super()'s methods. """ # Prepare the needed mappings. map_vcolor = defaultdict(int) pmap_vcolor = make_assoc_property_map(map_vcolor) if not pmap_vrelevant: pmap_vrelevant = make_func_property_map(lambda u: True) if not pmap_erelevant: pmap_erelevant = make_func_property_map(lambda e: True) # Prepare the DepthFirstSearchCopyVisitor. if not pmap_vertices: map_vertices = dict() pmap_vertices = make_assoc_property_map(map_vertices) if not pmap_edges: map_edges = dict() pmap_edges = make_assoc_property_map(map_edges) vis = DepthFirstSearchCopyVisitor(g_dup, pmap_vrelevant, pmap_erelevant, pmap_vertices, pmap_edges, pmap_vcolor, callback_dup_vertex, callback_dup_edge) # Copy g to g_copy according to pmap_erelevant using a DFS from s. depth_first_search(s, g, pmap_vcolor, vis, if_push=lambda e, g: pmap_erelevant[e] and pmap_vrelevant[target(e, g)])
def cut(s: int, g: Graph, in_cut) -> set: """ Find a vertex cut given an edge cut. Args: g: A `Graph` instance corresponding to an acyclic graph. s: The `VertexDescriptor` corresponding to the source vertex. in_cut: `Callback(EdgeDescriptor, Graph) -> bool` indicating whether an edge belong to the considered cut. """ class LeavesVisitor(DefaultDepthFirstSearchVisitor): def __init__(self, leaves: set): self.leaves = leaves def examine_edge(self, e: EdgeDescriptor, g: Graph): u = source(e, g) self.leaves.discard(u) def discover_vertex(self, u: int, g: Graph): self.leaves.add(u) class IfPush: def __init__(self, in_cut, cutting_edges: set): self.in_cut = in_cut self.cutting_edges = cutting_edges def __call__(self, e: EdgeDescriptor, g: Graph) -> bool: is_cutting_edge = self.in_cut(e, g) if is_cutting_edge: self.cutting_edges.add(e) return not is_cutting_edge leaves = set() cutting_edges = set() map_vcolor = defaultdict(int) depth_first_search(s, g, pmap_vcolor=make_assoc_property_map(map_vcolor), vis=LeavesVisitor(leaves), if_push=IfPush(in_cut, cutting_edges)) return {target(e, g) for e in cutting_edges } | {u for u in leaves} - {source(e, g) for e in cutting_edges}