This commit is contained in:
@@ -1,5 +1,13 @@
|
||||
import heapq
|
||||
from typing import Callable, Iterable, TypeVar, overload
|
||||
from typing import (
|
||||
Callable,
|
||||
Iterable,
|
||||
Iterator,
|
||||
Mapping,
|
||||
TypeVar,
|
||||
cast,
|
||||
overload,
|
||||
)
|
||||
|
||||
_Node = TypeVar("_Node")
|
||||
|
||||
@@ -116,3 +124,63 @@ def dijkstra(
|
||||
return preds
|
||||
|
||||
return preds.get(target, None)
|
||||
|
||||
|
||||
def iter_max_cliques(
|
||||
neighbors: Mapping[_Node, Iterable[_Node]], nodes: Iterable[_Node] | None = None
|
||||
) -> Iterator[list[_Node]]:
|
||||
"""
|
||||
Find max cliques from the given set of neighbors containing the given set of nodes.
|
||||
|
||||
This is simply the networkx implementation with typing (and using a simple mapping
|
||||
to avoid requiring networkx).
|
||||
"""
|
||||
if len(neighbors) == 0:
|
||||
return
|
||||
|
||||
# remove the node itself from the neighbors
|
||||
adj = {u: {v for v in neighbors[u] if v != u} for u in neighbors}
|
||||
|
||||
# Initialize Q with the given nodes and subg, cand with their nbrs
|
||||
Q: list[_Node | None] = list(nodes or [])
|
||||
cand = set(neighbors)
|
||||
for node in Q:
|
||||
if node not in cand:
|
||||
raise ValueError(f"The given `nodes` {nodes} do not form a clique")
|
||||
cand &= adj[node]
|
||||
|
||||
if not cand:
|
||||
yield cast(list[_Node], Q[:])
|
||||
return
|
||||
|
||||
subg = cand.copy()
|
||||
stack: list[tuple[set[_Node], set[_Node], set[_Node]]] = []
|
||||
Q.append(None)
|
||||
|
||||
u = max(subg, key=lambda u: len(cand & adj[u]))
|
||||
ext_u = cand - adj[u]
|
||||
|
||||
try:
|
||||
while True:
|
||||
if ext_u:
|
||||
q = ext_u.pop()
|
||||
cand.remove(q)
|
||||
Q[-1] = q
|
||||
adj_q = adj[q]
|
||||
subg_q = subg & adj_q
|
||||
if not subg_q:
|
||||
yield cast(list[_Node], Q[:])
|
||||
else:
|
||||
cand_q = cand & adj_q
|
||||
if cand_q:
|
||||
stack.append((subg, cand, ext_u))
|
||||
Q.append(None)
|
||||
subg = subg_q
|
||||
cand = cand_q
|
||||
u = max(subg, key=lambda u: len(cand & adj[u]))
|
||||
ext_u = cand - adj[u]
|
||||
else:
|
||||
Q.pop()
|
||||
subg, cand, ext_u = stack.pop()
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user