Source code for stupidb.associative.bitgraph
"""Implementation of a graph whose vertices are unsigned integers."""
from __future__ import annotations
from typing import AbstractSet, Any, Iterable, Iterator, Mapping, MutableMapping
import toolz
from .bitset import BitSet
[docs]class BitGraph:
"""An immutable graph whose vertices are unsigned integers."""
__slots__ = "_nodes", "_predecessors"
def __init__(self, nodes: Mapping[int, Iterable[int]]) -> None:
self._nodes: Mapping[int, AbstractSet[int]] = toolz.valmap(BitSet, nodes)
self._predecessors: MutableMapping[int, int] = {}
for parent, children in self._nodes.items():
for child in children:
self._predecessors[child] = parent
[docs] @classmethod
def from_vertices_and_edges(
cls,
*,
vertices: Iterable[int],
edges: Iterable[tuple[int, int]],
) -> BitGraph:
"""Construct a `BitGraph` from `vertices` and `edges`."""
nodes = {vertex: BitSet() for vertex in vertices}
for source, dest in edges:
nodes[source].add(dest)
return cls(nodes)
@property
def nodes(self) -> Mapping[int, AbstractSet[int]]:
"""Return a mapping from node to connected nodes."""
return self._nodes
@property
def predecessors(self) -> Mapping[int, int]:
"""Return a mapping of predecessors."""
return self._predecessors
@property
def in_edges(self) -> Iterator[int]:
"""Return the nodes with indegree zero."""
return (source for source, nodes in self._nodes.items() if not nodes)
def __eq__(self, other: Any) -> bool:
return self.nodes == other.nodes and self.predecessors == other.predecessors