Skip to content

Graph containers

pbcgraph.graph.PeriodicDiGraph

Directed periodic graph on Z^d.

The quotient is stored as a NetworkX :class:networkx.MultiDiGraph, but this container enforces an important invariant:

For any fixed triple (u, v, tvec), at most one edge exists.

This means that the translation vector is treated as part of the edge identity. Parallel edges between the same ordered node pair are still possible as long as their translation vectors differ.

Attributes:

Name Type Description
structural_version int

Incremented when the quotient structure changes (nodes/edges added or removed).

data_version int

Incremented when user data changes without structural changes (node/edge attribute updates).

Notes
  • Quotient nodes are NodeId values.
  • Each directed edge stores a translation vector (TVec) that describes how the cell shift changes when traversing that edge in the infinite periodic lift.

_dim instance-attribute

_dim = int(dim)

_g instance-attribute

_g: MultiDiGraph = MultiDiGraph()

structural_version instance-attribute

structural_version: int = 0

data_version instance-attribute

data_version: int = 0

dim property

dim: int

Lattice dimension d.

is_undirected property

is_undirected: bool

Whether this container should be treated as undirected by algorithms.

is_multigraph property

is_multigraph: bool

Whether this container allows multiple edges per (u, v, tvec).

__init__

__init__(dim: int = 3)

__len__

__len__() -> int

number_of_nodes

number_of_nodes() -> int

Return the number of quotient nodes.

number_of_edges

number_of_edges() -> int

Return the number of directed quotient edges (counts parallel edges).

add_node

add_node(u: NodeId, **attrs: Any) -> None

Add a quotient node.

Parameters:

Name Type Description Default
u NodeId

Node id.

required
**attrs Any

User attributes.

{}
Notes
  • Increments structural_version if the node is new.
  • If the node already exists and attrs are provided, this updates attributes and increments data_version.
  • If the node is new, attributes provided at creation do not increment data_version (pure structural change semantics).

remove_node

remove_node(u: NodeId) -> None

Remove a quotient node and all incident edges.

Parameters:

Name Type Description Default
u NodeId

Node id.

required

Raises:

Type Description
KeyError

If u is not present.

has_node

has_node(u: NodeId) -> bool

Return True if the node exists.

nodes

nodes(data: bool = False) -> Iterable

Iterate quotient nodes in deterministic order.

Parameters:

Name Type Description Default
data bool

If True, yield (u, attrs) where attrs is a read-only live view of the node attribute mapping.

False

Returns:

Type Description
Iterable

Iterable of node ids or (node, attrs) pairs.

get_node_data

get_node_data(u: NodeId) -> MappingProxyType

Return a read-only live view of the node attribute mapping.

Parameters:

Name Type Description Default
u NodeId

Node id.

required

Raises:

Type Description
KeyError

If node is missing.

set_node_attrs

set_node_attrs(u: NodeId, **attrs: Any) -> None

Update node attributes and increment data_version.

Parameters:

Name Type Description Default
u NodeId

Node id.

required
**attrs Any

Attributes to set.

{}

Raises:

Type Description
KeyError

If node is missing.

_alloc_key_directed

_alloc_key_directed(u: NodeId, v: NodeId) -> EdgeKey

Allocate a new edge key for a directed edge (u -> v).

Mirrors NetworkX's new_edge_key behavior: start from len(keys), then increment until unused.

_alloc_key_undirected

_alloc_key_undirected(u: NodeId, v: NodeId) -> EdgeKey

Allocate a new edge key for an undirected edge between u and v.

Keys are allocated in public base-key space. Undirected containers store directed realizations using private _UKey objects, so the internal MultiDiGraph keys are not necessarily ints.

_key_for_tvec

_key_for_tvec(
    u: NodeId, v: NodeId, tvec: TVec
) -> Optional[EdgeKey]

Return an existing edge key for a given directed (u, v, tvec).

Parameters:

Name Type Description Default
u NodeId

Source node.

required
v NodeId

Target node.

required
tvec TVec

Translation vector.

required

Returns:

Type Description
Optional[EdgeKey]

The corresponding edge key if an edge with this translation exists,

Optional[EdgeKey]

otherwise None.

_add_edge_impl

_add_edge_impl(
    u: NodeId,
    v: NodeId,
    tvec: TVec,
    *,
    key: Optional[EdgeKey],
    attrs: Dict[str, Any],
) -> EdgeKey

Implementation for adding a directed edge (no (u, v, tvec) checks).

add_edge

add_edge(
    u: NodeId,
    v: NodeId,
    tvec: TVec,
    key: Optional[EdgeKey] = None,
    **attrs: Any,
) -> EdgeKey

Add a directed periodic edge.

Parameters:

Name Type Description Default
u NodeId

Source node id.

required
v NodeId

Target node id.

required
tvec TVec

Translation vector in Z^d.

required
key Optional[EdgeKey]

Optional explicit edge key. If None, a fresh deterministic key is assigned.

None
**attrs Any

User attributes.

{}

Returns:

Type Description
EdgeKey

The edge key used.

Raises:

Type Description
ValueError

If tvec has wrong dimension.

has_edge

has_edge(
    u: NodeId, v: NodeId, key: Optional[EdgeKey] = None
) -> bool

Return True if a directed edge exists.

Parameters:

Name Type Description Default
u NodeId

Source node id.

required
v NodeId

Target node id.

required
key Optional[EdgeKey]

If provided, check existence of that specific edge key.

None

Returns:

Type Description
bool

True if edge exists.

edge_tvec

edge_tvec(u: NodeId, v: NodeId, key: EdgeKey) -> TVec

Return the structural translation vector for an edge.

get_edge_data

get_edge_data(
    u: NodeId, v: NodeId, key: EdgeKey, default: Any = None
) -> Any

Return a read-only live view of the user attribute mapping.

Parameters:

Name Type Description Default
u NodeId

Source node id.

required
v NodeId

Target node id.

required
key EdgeKey

Edge key.

required
default Any

Value to return if edge is missing.

None

Returns:

Type Description
Any

A read-only live view of the user attribute mapping, or default

Any

if missing.

set_edge_attrs

set_edge_attrs(
    u: NodeId, v: NodeId, key: EdgeKey, **attrs: Any
) -> None

Update user attributes for an edge and increment data_version.

remove_edge

remove_edge(u: NodeId, v: NodeId, key: EdgeKey) -> None

Remove a directed edge.

Raises:

Type Description
KeyError

If the edge does not exist.

edges

edges(
    keys: bool = False,
    data: bool = False,
    tvec: bool = False,
) -> Iterable

Iterate directed edges in deterministic order.

Parameters:

Name Type Description Default
keys bool

If True, include the multiedge key.

False
data bool

If True, include the read-only user attribute mapping.

False
tvec bool

If True, include the translation vector.

False

Returns:

Type Description
Iterable

An iterable of: - (u, v) - (u, v, attrs) - (u, v, key) - (u, v, tvec) - (u, v, tvec, key) - (u, v, key, attrs) - (u, v, tvec, attrs) - (u, v, tvec, key, attrs)

undirected_edges_unique

undirected_edges_unique(
    keys: bool = False,
    data: bool = False,
    tvec: bool = False,
) -> Iterable

Iterate unique undirected edges in deterministic order.

This iterator is only defined for undirected containers (PeriodicGraph / PeriodicMultiGraph). It returns each undirected quotient edge exactly once, in a canonical orientation.

Canonicalization rules
  • For u != v, the returned endpoints satisfy u <= v under the same ordering policy used elsewhere in pbcgraph.
  • For quotient self-loops with nonzero translation, the returned translation vector is canonicalized to min(tvec, -tvec).

Parameters:

Name Type Description Default
keys bool

If True, include the public base edge key.

False
data bool

If True, include the read-only user attribute mapping.

False
tvec bool

If True, include the translation vector.

False

Returns:

Type Description
Iterable

An iterable of: - (u, v) - (u, v, attrs) - (u, v, key) - (u, v, tvec) - (u, v, tvec, key) - (u, v, key, attrs) - (u, v, tvec, attrs) - (u, v, tvec, key, attrs)

Raises:

Type Description
TypeError

If called on a directed container.

neighbors

neighbors(
    u: NodeId, keys: bool = False, data: bool = False
) -> Iterable

Iterate outgoing periodic edges from quotient node u.

Yields:

Type Description
Iterable

Depending on flags:

Iterable
  • (v, tvec)
Iterable
  • (v, tvec, key)
Iterable
  • (v, tvec, attrs)
Iterable
  • (v, tvec, key, attrs)

in_neighbors

in_neighbors(
    u: NodeId, keys: bool = False, data: bool = False
) -> Iterable

Iterate incoming periodic edges into quotient node u.

The returned translation vector is the one stored on the directed edge v -> u (i.e. not negated).

Yields:

Type Description
Iterable

Depending on flags:

Iterable
  • (v, tvec)
Iterable
  • (v, tvec, key)
Iterable
  • (v, tvec, attrs)
Iterable
  • (v, tvec, key, attrs)

neighbors_inst

neighbors_inst(
    node_inst: NodeInst,
    keys: bool = False,
    data: bool = False,
) -> Iterable

Iterate outgoing lifted neighbors from a node instance.

Parameters:

Name Type Description Default
node_inst NodeInst

(u, shift).

required

Yields:

Type Description
Iterable

Depending on flags:

Iterable
  • (v, shift + tvec)
Iterable
  • (v, shift + tvec, key)
Iterable
  • (v, shift + tvec, attrs)
Iterable
  • (v, shift + tvec, key, attrs)

in_neighbors_inst

in_neighbors_inst(
    node_inst: NodeInst,
    keys: bool = False,
    data: bool = False,
) -> Iterable

Iterate incoming lifted neighbors into a node instance.

For an incoming edge v -> u with translation tvec, the lifted neighbor instance for v is shift - tvec.

successors

successors(u: NodeId) -> Iterable[NodeId]

Return successor nodes (quotient) in deterministic order.

predecessors

predecessors(u: NodeId) -> Iterable[NodeId]

Return predecessor nodes (quotient) in deterministic order.

from_edges classmethod

from_edges(
    dim: int,
    nodes: Optional[Iterable[Any]] = None,
    edges: Optional[Iterable[Any]] = None,
) -> "PeriodicDiGraph"

Construct a graph from nodes and edges.

Parameters:

Name Type Description Default
dim int

Lattice dimension.

required
nodes Optional[Iterable[Any]]

Optional iterable of node ids or (node_id, attrs_dict) pairs.

None
edges Optional[Iterable[Any]]

Optional iterable of edges, each one of: - (u, v, tvec) - (u, v, tvec, attrs_dict) - (u, v, tvec, key, attrs_dict)

None

Returns:

Type Description
'PeriodicDiGraph'

A graph instance of type cls.

components

components() -> List['PeriodicComponent']

Return connected components as PeriodicComponent objects.

lift_patch

lift_patch(
    seed: NodeInst,
    *,
    radius: Optional[int] = None,
    box: Optional[Tuple[Tuple[int, int], ...]] = None,
    box_rel: Optional[Tuple[Tuple[int, int], ...]] = None,
    include_edges: bool = True,
    max_nodes: Optional[int] = None,
    node_order: Optional[Callable[[NodeInst], Any]] = None,
    edge_order: Optional[
        Callable[[Tuple[Any, ...]], Any]
    ] = None,
) -> "LiftPatch"

Extract a finite patch of the lifted graph.

This is a thin wrapper over :func:pbcgraph.alg.lift.lift_patch.

Notes

For directed containers this patch is directed by default (exported as nx.DiGraph / nx.MultiDiGraph). Use patch.to_networkx(as_undirected=True, ...) for undirected views.

pbcgraph.graph.PeriodicGraph

Bases: PeriodicDiGraph

Undirected periodic graph.

Internally, an undirected periodic edge is represented by two directed realizations:

  • u -> v with translation tvec
  • v -> u with translation -tvec

Both realizations share the same underlying user-attributes dict. The public API returns read-only live views of that mapping.

Important: a crystallographically common pattern is a quotient self-loop with non-zero translation (u == v and tvec != 0), representing a bond to a periodic image of the same motif.

NetworkX identifies multiedges by (u, v, key). For self-loops, the two directed realizations would collide if they shared the same key.

To avoid this, PeriodicGraph stores directed realizations using a private internal key type _UKey(base, dir), where base is the user-visible integer key and dir is +1 / -1. The public API always exposes the base key.

In addition to the undirected-invariant pairing, this container enforces an invariant analogous to PeriodicDiGraph:

For any undirected triple {u, v, tvec} (up to reversal), at most one edge exists.

To allow multiple contacts for the same motif pair and translation, use PeriodicMultiGraph.

Notes

PeriodicGraph is a subclass of PeriodicDiGraph, but restricts some operations (for example, directed connectivity modes in algorithms).

is_undirected property

is_undirected: bool

Whether this container should be treated as undirected by algorithms.

edges

edges(
    keys: bool = False,
    data: bool = False,
    tvec: bool = False,
) -> Iterable

Iterate directed realizations in deterministic order.

This iterator yields directed realizations of undirected edges.

Note

For self-loop periodic edges (u == v and tvec != 0), the two directed realizations share the same (u, v, key) triple and differ only by the translation vector. If keys=True but tvec=False, this may yield duplicate (u, u, key) records. Use tvec=True to disambiguate.

See PeriodicDiGraph.edges for the record formats.

_internal_keys_for_base

_internal_keys_for_base(
    u: NodeId, v: NodeId, key: EdgeKey
) -> List[object]

Return internal keys on (u -> v) whose public base key equals key.

_choose_internal_key

_choose_internal_key(
    u: NodeId, v: NodeId, key: EdgeKey
) -> object

Choose a deterministic internal key for accessing shared attrs/tvec.

_has_undirected_base

_has_undirected_base(
    u: NodeId, v: NodeId, key: EdgeKey
) -> bool

Return True if an undirected edge with base key exists between u and v.

add_edge

add_edge(
    u: NodeId,
    v: NodeId,
    tvec: TVec,
    key: Optional[EdgeKey] = None,
    **attrs: Any,
) -> EdgeKey

_add_undirected_impl

_add_undirected_impl(
    u: NodeId,
    v: NodeId,
    tvec: TVec,
    *,
    key: Optional[EdgeKey],
    attrs: Dict[str, Any],
) -> EdgeKey

Implementation for adding an undirected edge (no tvec checks).

has_edge

has_edge(
    u: NodeId, v: NodeId, key: Optional[EdgeKey] = None
) -> bool

edge_tvec

edge_tvec(u: NodeId, v: NodeId, key: EdgeKey) -> TVec

get_edge_data

get_edge_data(
    u: NodeId, v: NodeId, key: EdgeKey, default: Any = None
) -> Any

set_edge_attrs

set_edge_attrs(
    u: NodeId, v: NodeId, key: EdgeKey, **attrs: Any
) -> None

remove_edge

remove_edge(u: NodeId, v: NodeId, key: EdgeKey) -> None

check_invariants

check_invariants(*, strict: bool = False) -> Dict[str, Any]

Check undirected pairing invariants.

Returns a structured report and optionally raises on errors.

Invariants checked
  • For every directed realization there is a paired reverse one.
  • Translation vectors satisfy t(v,u,rev) = -t(u,v,fwd).
  • The user-attributes dict is the same object for paired realizations.

Parameters:

Name Type Description Default
strict bool

If True, raise ValueError on the first violation.

False

Returns:

Type Description
Dict[str, Any]

A dict with keys: ok, errors, n_edges.

pbcgraph.graph.PeriodicMultiDiGraph

Bases: PeriodicDiGraph

Directed periodic multigraph on Z^d.

Unlike PeriodicDiGraph, this container allows multiple edges for the same directed triple (u, v, tvec). Such parallel edges are distinguished by their edge keys.

is_multigraph property

is_multigraph: bool

Whether this container allows multiple edges per (u, v, tvec).

add_edge

add_edge(
    u: NodeId,
    v: NodeId,
    tvec: TVec,
    key: Optional[EdgeKey] = None,
    **attrs: Any,
) -> EdgeKey

Add a directed periodic edge (parallel edges allowed).

pbcgraph.graph.PeriodicMultiGraph

Bases: PeriodicGraph

Undirected periodic multigraph.

Unlike PeriodicGraph, this container allows multiple undirected edges for the same motif pair and translation (i.e. multiple edges for the same undirected {u, v, tvec} up to reversal). Parallel edges are distinguished by their edge keys.

is_multigraph property

is_multigraph: bool

Whether this container allows multiple edges per (u, v, tvec).

add_edge

add_edge(
    u: NodeId,
    v: NodeId,
    tvec: TVec,
    key: Optional[EdgeKey] = None,
    **attrs: Any,
) -> EdgeKey

Add an undirected periodic edge (parallel edges allowed).