Esempio n. 1
0
def make_dag(g: DirectedGraph,
             s: int,
             t: int,
             pmap_vpreds: ReadPropertyMap,
             single_path: bool = False) -> set:
    """
    Extracts the arcs related to shortest paths from `s`
    to `t` in a graph `g` given the predecessors map computed
    using `dijkstra_shortest_paths` from `s`.
    Args:
        g: The graph.
        s: The target's vertex descriptor.
        t: The target's vertex descriptor.
        pmap_vpreds: The `ReadPropertyMap{int : set(int)}` mapping each
            vertex with its set of (direct) predecessors.
        single_path: Pass True to extract a single path. If multiple
            paths exist from `s` to `t`, this extracts an arbitrary
            path instead of all of them.
    Returns:
        The corresponding set of `EdgeDescriptor`s.
    """
    kept_edges = set()
    n_prev = -1
    n = 0
    to_process = {t}
    done = set()
    while to_process:
        es = {e for u in to_process if pmap_vpreds[u] for e in pmap_vpreds[u]}
        if single_path and es:
            es = {es.pop()}
        kept_edges |= es
        predecessors = {source(e, g) for e in es if e not in done}
        done |= to_process
        to_process = predecessors - done
    return kept_edges
Esempio n. 2
0
 def examine_relevant_edge(self, e: EdgeDescriptor, g: Graph):
     u = source(e, g)
     v = target(e, g)
     u_dup = self.m_pmap_vertices[u]
     v_dup = self.m_pmap_vertices[
         v] if v in self.m_dup_vertices else self.dup_vertex(v, g)
     (e_dup, _) = add_edge(u_dup, v_dup, self.m_g_dup)
     if self.m_pmap_edges:
         self.m_pmap_edges[e] = e_dup
     if self.m_callback_dup_edge:
         self.m_callback_dup_edge(e, g, e_dup, self.m_g_dup)
Esempio n. 3
0
def make_gdp2() -> GraphDp:
    g = make_g()
    vlabel = {u : "v%s" % u for u in vertices(g)}
    elabel = {e : "e%s%s" % (source(e, g), target(e, g)) for e in edges(g)}
    gdp = GraphDp(
        g,
        dpv = {
            "label" : make_assoc_property_map(vlabel),
            "color" : make_func_property_map(lambda q: "red" if q % 2 else "green"),
        },
        dpe = {
            "label" : make_assoc_property_map(elabel),
            "color" : make_func_property_map(lambda e: "red" if target(e, g) % 2 else "green"),
        }
    )
    return gdp
Esempio n. 4
0
def edge_color(e, g, pmap_component, pmap_color, default_color = "black"):
    """
    Returns the color assigned to an edge.
    Args:
        e: An EdgeDescriptor.
        g: A DirectedGraph.
        pmap_component: A ReadPropertyMap, mapping a vertex with its strongly
            connected component.
        pmap_color: A ReadPropertyMap, mapping a component ID with a color.
        default_color: color returned if the color of the source and the
            target of e mismatch.
    """
    u = source(e, g)
    v = target(e, g)
    color_u = pmap_color[pmap_component[u]]
    color_v = pmap_color[pmap_component[v]]
    return color_u if color_u == color_v else default_color
Esempio n. 5
0
File: cut.py Progetto: nokia/PyBGL
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}
def test_directed_graph(links: list = LINKS):
    map_eweight = dict()
    pmap_eweight = make_assoc_property_map(map_eweight)
    g = make_graph(LINKS,
                   pmap_eweight,
                   directed=True,
                   build_reverse_edge=False)

    map_vpreds = defaultdict(set)
    map_vdist = dict()
    dijkstra_shortest_paths(g, 0, pmap_eweight,
                            make_assoc_property_map(map_vpreds),
                            make_assoc_property_map(map_vdist))

    infty = sys.maxsize
    E = {(source(e, g), target(e, g)): e for e in edges(g)}

    assert map_vpreds == {
        1: {E[0, 1]},
        2: {E[1, 2]},
        3: {E[1, 3]},
        4: {E[3, 4]},
        5: {E[4, 5]},
        6: {E[4, 6]},
        7: {E[6, 7]},
        8: {E[7, 8]},
        9: {E[7, 9]}
    }
    assert map_vdist == {
        0: 0,
        1: 1,
        2: 2,
        3: 4,
        4: 5,
        5: 6,
        6: 6,
        7: 14,
        8: 15,
        9: 15,
        10: infty
    }
Esempio n. 7
0
def make_path(g: DirectedGraph, s: int, t: int,
              pmap_vpreds: ReadPropertyMap) -> list:
    """
    Extract the path from `s` to `t` in a graph `g` gien
    to `t` in a graph `g` given the predecessors map computed
    using `dijkstra_shortest_paths` from `s`.
    Args:
        g: The graph.
        s: The target's vertex descriptor.
        t: The target's vertex descriptor.
        pmap_vpreds: A `ReadPropertyMap{int : set(int)}` mapping each
            vertex with its set of (direct) predecessors.
    Returns:
        A list of consecutive arcs forming a shortest path from `s` of `t`.
        If several shortest paths exist from `s` to `t`, this function returns
        an arbitrary path.
    """
    arcs = make_dag(g, s, t, pmap_vpreds, single_path=True)
    path = list(arcs)
    path.sort(key=lambda e: (source(e, g), target(e, g)))
    return path
Esempio n. 8
0
 def edge_to_pair(e: EdgeDescriptor, g: DirectedGraph) -> tuple:
     return (source(e, g), target(e, g))
Esempio n. 9
0
def test_graph_copy_small(threshold :int = 50):
    g = DirectedGraph(5)
    (e01, _) = add_edge(0, 1, g)
    (e02, _) = add_edge(0, 2, g)
    (e04, _) = add_edge(0, 4, g)
    (e12, _) = add_edge(1, 2, g)
    (e23, _) = add_edge(2, 3, g)
    (e24, _) = add_edge(2, 4, g)
    (e40, _) = add_edge(4, 0, g)
    (e44, _) = add_edge(4, 4, g)
    map_eweight = {
        e01 : 83,
        e02 : 3,
        e04 : 78,
        e12 : 92,
        e23 : 7,
        e24 : 18,
        e40 : 51,
        e44 : 84,
    }
    pmap_eweight = make_assoc_property_map(map_eweight)
    pmap_erelevant = make_func_property_map(lambda e: pmap_eweight[e] >= threshold)

    g_dup = DirectedGraph(0)

    # Edge duplicate
    map_eweight_dup = dict()
    pmap_eweight_dup = make_assoc_property_map(map_eweight_dup)
    def callback_dup_edge(e, g, e_dup, g_dup):
        pmap_eweight_dup[e_dup] = pmap_eweight[e]

    # Vertex mapping
    map_vertices = dict()
    pmap_vertices = make_assoc_property_map(map_vertices)
    map_edges = dict()
    pmap_edges = make_assoc_property_map(map_edges)

    graph_copy(
        0, g, g_dup,
        pmap_erelevant    = pmap_erelevant,
        pmap_vertices     = pmap_vertices,
        pmap_edges        = pmap_edges,
        callback_dup_edge = callback_dup_edge
    )

    if in_ipynb():
        ori_html = dotstr_to_html(
            GraphDp(
                g,
                dpv = {
                    "label" : make_func_property_map(lambda u: "%s<br/>(becomes %s)" % (u, pmap_vertices[u]))
                },
                dpe = {
                    "color" : make_func_property_map(lambda e : "darkgreen" if pmap_erelevant[e] else "lightgrey"),
                    "style" : make_func_property_map(lambda e : "solid"     if pmap_erelevant[e] else "dashed"),
                    "label" : pmap_eweight,
                }
            ).to_dot()
        )
        dup_html = dotstr_to_html(
            GraphDp(
                g_dup,
                dpe = {
                    "label" : pmap_eweight_dup,
                }
            ).to_dot()
        )
        html(
            """
            <table>
                <tr>
                    <th>Original</th>
                    <th>Extracted</th>
                </tr><tr>
                    <td>%s</td>
                    <td>%s</td>
                </tr>
            </table>
            """ % (ori_html, dup_html)
        )

    if threshold == 50:
        expected_num_edges = 5
        assert map_vertices == {
            0 : 0,
            1 : 1,
            2 : 2,
            4 : 3
        }
        for e, e_dup in map_edges.items():
            u = source(e, g)
            v = target(e, g)
            u_dup = source(e_dup, g_dup)
            v_dup = target(e_dup, g_dup)
            assert u_dup == pmap_vertices[u], "u_dup = %s ; pmap_vertices[%s] = %s" % (u_dup, u, pmap_vertices[u])
            assert v_dup == pmap_vertices[v], "v_dup = %s ; pmap_vertices[%s] = %s" % (v_dup, v, pmap_vertices[v])
            assert pmap_eweight[e] == pmap_eweight_dup[e_dup]
    elif threshold < min([w for w in map_eweight.values()]):
        expected_num_edges = num_edges(g)
    elif threshold > max([w for w in map_eweight.values()]):
        expected_num_edges = 0

    assert expected_num_edges == num_edges(g_dup), \
        """
        Invalid edge number:
          Expected: %s
          Obtained: %s
        """ % (expected_num_edges, num_edges(g_dup))
Esempio n. 10
0
File: cut.py Progetto: nokia/PyBGL
 def examine_edge(self, e: EdgeDescriptor, g: Graph):
     u = source(e, g)
     self.leaves.discard(u)