Ejemplo n.º 1
0
def test_degeneracy_ordering_nonempty(adjacencies: List[Set[Vertex]]) -> None:
    g = UndirectedGraph(adjacencies=adjacencies)
    connected_vertices = g.connected_vertices()

    ordering = list(degeneracy_ordering(g))
    assert set(ordering) == connected_vertices
    assert all(g.degree(ordering[0]) <= g.degree(v) for v in ordering[1:])

    ordering_min1 = list(degeneracy_ordering(g, drop=1))
    assert ordering_min1 == ordering[:-1]
Ejemplo n.º 2
0
def degeneracy_ordering(graph: UndirectedGraph,
                        drop: int = 0) -> Generator[Vertex, None, None]:
    """
    Iterate connected vertices, lowest degree first.
    drop=N: omit last N vertices
    """
    assert drop >= 0
    priority_per_node = [-2] * graph.order
    max_degree = 0
    num_candidates = 0
    for c in range(graph.order):
        if degree := graph.degree(c):
            priority_per_node[c] = degree
            max_degree = max(max_degree, degree)
            num_candidates += 1
Ejemplo n.º 3
0
def visit(graph: UndirectedGraph, reporter: Reporter, pivot_choice_X: bool,
          candidates: Set[Vertex], excluded: Set[Vertex],
          clique: List[Vertex]) -> None:
    assert all(graph.degree(v) > 0 for v in candidates)
    assert all(graph.degree(v) > 0 for v in excluded)
    assert candidates.isdisjoint(excluded)
    assert len(candidates) >= 1
    if len(candidates) == 1:
        # Same logic as below, stripped down for this common case
        for v in candidates:
            neighbours = graph.adjacencies[v]
            assert neighbours
            if excluded.isdisjoint(neighbours):
                reporter.record(clique + [v])
        return

    # Quickly handle locally unconnected candidates while finding pivot
    remaining_candidates = []
    seen_local_degree = 0
    for v in candidates:
        neighbours = graph.adjacencies[v]
        local_degree = len(candidates.intersection(neighbours))
        if local_degree == 0:
            # Same logic as below, stripped down
            if neighbours.isdisjoint(excluded):
                reporter.record(clique + [v])
        else:
            if seen_local_degree < local_degree:
                seen_local_degree = local_degree
                pivot = v
            remaining_candidates.append(v)
    if seen_local_degree == 0:
        return
    if pivot_choice_X:
        for v in excluded:
            neighbours = graph.adjacencies[v]
            local_degree = len(candidates.intersection(neighbours))
            if seen_local_degree < local_degree:
                seen_local_degree = local_degree
                pivot = v

    for v in remaining_candidates:
        neighbours = graph.adjacencies[v]
        assert neighbours
        if pivot not in neighbours:
            candidates.remove(v)
            if neighbouring_candidates := candidates.intersection(neighbours):
                neighbouring_excluded = excluded.intersection(neighbours)
                visit(graph=graph,
                      reporter=reporter,
                      pivot_choice_X=pivot_choice_X,
                      candidates=neighbouring_candidates,
                      excluded=neighbouring_excluded,
                      clique=clique + [v])
            elif excluded.isdisjoint(neighbours):
                reporter.record(clique + [v])
            excluded.add(v)
Ejemplo n.º 4
0
def visit(graph: UndirectedGraph, reporter: Reporter, candidates: Set[Vertex],
          excluded: Set[Vertex], clique: List[Vertex]) -> None:
    assert all(graph.degree(v) > 0 for v in candidates)
    assert all(graph.degree(v) > 0 for v in excluded)
    assert candidates.isdisjoint(excluded)
    assert candidates
    while candidates:
        v = candidates.pop()
        neighbours = graph.adjacencies[v]
        neighbouring_candidates = candidates.intersection(neighbours)
        if neighbouring_candidates:
            neighbouring_excluded = excluded.intersection(neighbours)
            visit(graph,
                  reporter,
                  candidates=neighbouring_candidates,
                  excluded=neighbouring_excluded,
                  clique=clique + [v])
        elif excluded.isdisjoint(neighbours):
            reporter.record(clique + [v])
        excluded.add(v)