pub struct DiGraph { /* private fields */ }Implementations§
Source§impl DiGraph
impl DiGraph
Sourcepub fn clear_edges(&mut self)
pub fn clear_edges(&mut self)
br-r37-c1-clearedgesinplace (cc): drop all edges in place, keeping nodes (index, order, attrs). O(E)+O(V): clear the edges map + every succ/pred index row; the revision bump invalidates the CSR + all-int caches. Sibling of Graph::clear_edges and MultiDiGraph::clear_edges. The binding’s prior path collected the mirror keys and called remove_edge per edge (each an O(degree) row retain -> O(E*degree), measured ~0.003-0.011x vs nx); this is the in-place fix.
Sourcepub fn clone_with_fresh_policy(&self) -> Self
pub fn clone_with_fresh_policy(&self) -> Self
br-r37-c1-7dpyg: structural clone with a FRESH RuntimePolicy — see Graph::clone_with_fresh_policy.
pub fn new(mode: CompatibilityMode) -> Self
pub fn with_runtime_policy(runtime_policy: RuntimePolicy) -> Self
Sourcepub fn induced_subgraph_ordered(
&self,
order: &[usize],
runtime_policy: RuntimePolicy,
) -> Self
pub fn induced_subgraph_ordered( &self, order: &[usize], runtime_policy: RuntimePolicy, ) -> Self
br-r37-c1-indsub: directed twin of Graph::induced_subgraph_ordered —
build the induced subgraph over order (parent node indices, already in
the caller’s output order) with no node-name hashing.
add_edge_with_attrs costs two String allocations, four name hashes
and TWO record_decision ledger entries per arc (the second carrying
four EvidenceTerms, eight more String allocations). Everything it
re-derives is already known here. Invariants reproduced directly:
edges keyed by the ORIENTED new-index pair (direction is identity for
a directed edge, so no canonicalization), and a succ/pred row records
its endpoint when the arc is emitted, so both row orders are the walk
order — matching nx’s add_edges_from over the induced walk.
order must contain distinct, in-range parent indices.
pub fn strict() -> Self
pub fn hardened() -> Self
pub fn mode(&self) -> CompatibilityMode
pub fn node_count(&self) -> usize
pub fn edge_count(&self) -> usize
pub fn revision(&self) -> u64
Sourcepub fn csr(&self) -> Arc<DiCsr> ⓘ
pub fn csr(&self) -> Arc<DiCsr> ⓘ
br-r37-c1-d58s8 P1: revision-keyed integer CSR of both row families. O(V+E) rebuild only when the graph changed since the cached build; kernels get index walks identical to the String walks (per-row order preserved).
Sourcepub fn edge_weights_all_int(&self, attr: &str) -> bool
pub fn edge_weights_all_int(&self, attr: &str) -> bool
br-r37-c1-d58s8: revision-keyed memo of “every edge’s attr
value is an integer (missing = default 1 = int)”.
pub fn has_node(&self, node: &str) -> bool
Sourcepub fn successors_indices(&self, idx: usize) -> Option<&[usize]>
pub fn successors_indices(&self, idx: usize) -> Option<&[usize]>
br-r37-c1-1l8s0: direct slice access to the eager succ index row, by node position (through the position view while slots are not dense).
Sourcepub fn predecessors_indices(&self, idx: usize) -> Option<&[usize]>
pub fn predecessors_indices(&self, idx: usize) -> Option<&[usize]>
Direct slice access to the eager pred index row, by node position.
pub fn has_edge(&self, source: &str, target: &str) -> bool
Sourcepub fn has_edge_by_indices(&self, source_idx: usize, target_idx: usize) -> bool
pub fn has_edge_by_indices(&self, source_idx: usize, target_idx: usize) -> bool
br-r37-c1-04z53 (cc): directed has_edge straight from insertion-order
indices (source-major), skipping the i.to_string() heap alloc for int
nodes. Names come from the node table by index (borrowed); the caller
guards each index with node_index_matches_int. Mirror of
Graph::has_edge_by_indices.
br-r37-c1-p1tvg: this used to resolve both indices back to NAMES and
call has_edge, which hashes two Strings to rediscover the very
indices it was handed — exactly the cost a caller pays an index route
to avoid. The edges map has been keyed by the ORIENTED
(source_idx, target_idx) pair since the d58s8 flip, so the pair IS
the key. An out-of-range index still answers false: every key in the
map names two live nodes, so no key can carry one.
pub fn nodes_ordered(&self) -> Vec<&str>
Sourcepub fn node_index_matches_int(&self, idx: usize) -> bool
pub fn node_index_matches_int(&self, idx: usize) -> bool
br-cc-nbunchbulk: does the node at contiguous index idx have the exact int
name idx? O(1) index probe + no-alloc parse — the int membership fast path
for _nbunch_present (sibling of the undirected Graph accessor).
Sourcepub fn node_names_are_positions(&self) -> bool
pub fn node_names_are_positions(&self) -> bool
sfq4w.3: see Graph::node_names_are_positions.
pub fn get_node_index(&self, node: &str) -> Option<usize>
pub fn get_node_name(&self, index: usize) -> Option<&str>
Sourcepub fn successors(&self, node: &str) -> Option<Vec<&str>>
pub fn successors(&self, node: &str) -> Option<Vec<&str>>
Successors of node (outgoing neighbors). Returns None if node absent.
pub fn successors_iter( &self, node: &str, ) -> Option<impl Iterator<Item = &str> + '_>
Sourcepub fn out_edge_attrs(
&self,
node: &str,
) -> Option<impl Iterator<Item = &AttrMap> + '_>
pub fn out_edge_attrs( &self, node: &str, ) -> Option<impl Iterator<Item = &AttrMap> + '_>
yr2oc.4: the attribute maps of node’s out-edges in successor-row
order. Read by slot: no position translation after a removal.
Sourcepub fn in_edge_attrs(
&self,
node: &str,
) -> Option<impl Iterator<Item = &AttrMap> + '_>
pub fn in_edge_attrs( &self, node: &str, ) -> Option<impl Iterator<Item = &AttrMap> + '_>
yr2oc.4: the attribute maps of node’s in-edges in predecessor-row
order. Read by slot: no position translation after a removal.
Sourcepub fn predecessors(&self, node: &str) -> Option<Vec<&str>>
pub fn predecessors(&self, node: &str) -> Option<Vec<&str>>
Predecessors of node (incoming neighbors). Returns None if node absent.
Sourcepub fn apply_row_orders(&mut self, orders: &[(String, Vec<String>)], pred: bool)
pub fn apply_row_orders(&mut self, orders: &[(String, Vec<String>)], pred: bool)
br-r37-c1-u3qyn: restore explicit succ/pred row orders (pickle
round-trip) — see Graph::apply_row_orders. which selects the
adjacency side.
Sourcepub fn reorder_pred_rows_for_nx_copy_walk(&mut self)
pub fn reorder_pred_rows_for_nx_copy_walk(&mut self)
br-r37-c1-0ek49: reorder every PRED row into NetworkX’s
DiGraph.copy() walk order. nx copy rebuilds via the u-major
succ walk ((u, v, d) for u in _adj for v in _adj[u]), which
recreates succ rows in their original order but fills each pred
row in walk order: (pos(u), index of v within succ[u]). Call on
a fresh clone inside copy-shaped constructors; graph content is
unchanged, only pred row order moves.
Sourcepub fn reorder_rows_like(&mut self, source: &Self, swap: bool)
pub fn reorder_rows_like(&mut self, source: &Self, swap: bool)
br-r37-c1-36v6r: order each successor and predecessor row as
source’s row for the node of the same name - its succ / pred rows,
or its pred / succ rows when swap (a reverse view’s). A graph built
from a filtered or reverse view of source by a copy-shaped walk
fills pred rows in succ-walk order (networkx’s view.copy() does the
same), where the view’s pred row is source’s row filtered. Entries
source’s row lacks keep their relative order after the matched
ones. Graph content is unchanged; revision moves if any row does.
Sourcepub fn set_row_orders(
&mut self,
succ_rows: &[Vec<usize>],
pred_rows: &[Vec<usize>],
) -> bool
pub fn set_row_orders( &mut self, succ_rows: &[Vec<usize>], pred_rows: &[Vec<usize>], ) -> bool
br-r37-c1-36v6r: order every successor and predecessor row as given -
succ_rows[i] / pred_rows[i] are the rows of the node at position
i, neighbours as positions - for a row order no graph holds, such
as a to_directed(as_view=True) view’s (both rows the undirected
graph’s row). All or nothing: false, and nothing changes, unless every
given row is a permutation of the current one.
pub fn predecessors_iter( &self, node: &str, ) -> Option<impl Iterator<Item = &str> + '_>
Sourcepub fn neighbors(&self, node: &str) -> Option<Vec<&str>>
pub fn neighbors(&self, node: &str) -> Option<Vec<&str>>
Neighbors = successors (matches NetworkX DiGraph.neighbors() convention).
pub fn neighbors_iter( &self, node: &str, ) -> Option<impl Iterator<Item = &str> + '_>
pub fn neighbor_count(&self, node: &str) -> usize
Sourcepub fn out_degree(&self, node: &str) -> usize
pub fn out_degree(&self, node: &str) -> usize
Out-degree: number of successors.
Sourcepub fn out_degree_by_index(&self, idx: usize) -> usize
pub fn out_degree_by_index(&self, idx: usize) -> usize
br-r37-c1-degidx: index-based degree accessors — O(1), zero String hashing (the &str path costs get_index_of per call; degree pays it twice). Used by the directed DegreeView iterator which walks nodes in index order.
pub fn in_degree_by_index(&self, idx: usize) -> usize
pub fn degree_by_index(&self, idx: usize) -> usize
Sourcepub fn out_edges<'a>(&'a self, node: &'a str) -> Vec<(&'a str, &'a str)>
pub fn out_edges<'a>(&'a self, node: &'a str) -> Vec<(&'a str, &'a str)>
Outgoing edges from node as (source, target) pairs.
Sourcepub fn in_edges<'a>(&'a self, node: &'a str) -> Vec<(&'a str, &'a str)>
pub fn in_edges<'a>(&'a self, node: &'a str) -> Vec<(&'a str, &'a str)>
Incoming edges to node as (source, target) pairs.
pub fn node_attrs(&self, node: &str) -> Option<&AttrMap>
pub fn node_attrs_by_index(&self, idx: usize) -> Option<&AttrMap>
Sourcepub fn edge_attrs(&self, source: &str, target: &str) -> Option<&AttrMap>
pub fn edge_attrs(&self, source: &str, target: &str) -> Option<&AttrMap>
Attributes of directed edge source→target.
Sourcepub fn edge_attrs_by_indices(
&self,
source_idx: usize,
target_idx: usize,
) -> Option<&AttrMap>
pub fn edge_attrs_by_indices( &self, source_idx: usize, target_idx: usize, ) -> Option<&AttrMap>
br-r37-c1-d58s8: index-keyed attr access (oriented). Zero node-map probes for callers already holding indices.
Sourcepub fn any_edge_has_attr(&self, key: &str) -> bool
pub fn any_edge_has_attr(&self, key: &str) -> bool
br-r37-c1-hasattrlazyfix: does ANY directed edge carry the attribute key in the
authoritative Rust storage (the inner edges AttrMaps), regardless of whether the
lazy edge_py_attrs Python mirror has been materialized? ~O(E) key checks.
Sourcepub fn all_edge_attr_values_scalar(&self) -> bool
pub fn all_edge_attr_values_scalar(&self) -> bool
Directed twin of Graph::all_edge_attr_values_scalar: true if EVERY inner
edge attr value is a faithful scalar (Int/Float/Bool). No-alloc scan over
the edge store values — contrast edges_ordered_borrowed, which allocates
an O(E) Vec and resolves node names per edge. Used by the reverse gate.
Sourcepub fn any_node_has_attrs(&self) -> bool
pub fn any_node_has_attrs(&self) -> bool
br-r37-c1-hasanyattrlazyfix: any node / any edge carries a Python-visible attr per
the authoritative inner storage (not the lazy *_py_attrs mirrors).
pub fn any_edge_has_attrs(&self) -> bool
Sourcepub fn edges_indexed(
&self,
) -> impl Iterator<Item = ((usize, usize), &AttrMap)> + '_
pub fn edges_indexed( &self, ) -> impl Iterator<Item = ((usize, usize), &AttrMap)> + '_
br-r37-c1-prdir: iterate every directed edge as
((source_idx, target_idx), &AttrMap) straight from the index-keyed edge
store, in insertion order. Lets COO/CSR exporters read each edge’s weight
with ONE attr lookup instead of the per-edge edges.get(&(u,v)) hash that
the successors-then-edge_attrs_by_indices path pays.
pub fn evidence_ledger(&self) -> &EvidenceLedger
pub fn drain_decision_records(&mut self) -> Vec<DecisionRecord>
Sourcepub fn record_external_recovery(
&mut self,
operation: impl Into<Cow<'static, str>>,
rationale: impl Into<Cow<'static, str>>,
)
pub fn record_external_recovery( &mut self, operation: impl Into<Cow<'static, str>>, rationale: impl Into<Cow<'static, str>>, )
Record a bounded recovery performed outside the graph (e.g. a reader skipping a malformed line in hardened mode) in this graph’s ledger.
pub fn runtime_policy(&self) -> &RuntimePolicy
pub fn set_runtime_policy(&mut self, runtime_policy: RuntimePolicy)
Sourcepub fn is_directed(&self) -> bool
pub fn is_directed(&self) -> bool
Type identity: always true for DiGraph.
Sourcepub fn is_multigraph(&self) -> bool
pub fn is_multigraph(&self) -> bool
Type identity: always false for DiGraph (not a multigraph).
pub fn add_node(&mut self, node: impl AsRef<str> + Into<String>) -> bool
pub fn add_node_with_attrs( &mut self, node: impl AsRef<str> + Into<String>, attrs: AttrMap, ) -> bool
pub fn apply_node_defaults(&mut self, defaults: &AttrMap) -> bool
pub fn add_edge( &mut self, source: impl AsRef<str>, target: impl AsRef<str>, ) -> Result<(), GraphError>
Sourcepub fn add_edge_with_attrs(
&mut self,
source: impl AsRef<str>,
target: impl AsRef<str>,
attrs: AttrMap,
) -> Result<(), GraphError>
pub fn add_edge_with_attrs( &mut self, source: impl AsRef<str>, target: impl AsRef<str>, attrs: AttrMap, ) -> Result<(), GraphError>
br-r37-c1-jc9e4: the directed mirror of the Graph sibling — the
endpoint keys are never owned here, and each is resolved with ONE map
probe. This used to own both keys, clone each again for autocreation,
and then hash each up to three times (contains_key, get_index_of
for the edge key, get_index_of again for the successor/predecessor
rows). The census measured the directed pair at the undirected pair’s
pre-lever numbers, so none of that transferred on its own.
Sourcepub fn extend_edges_unrecorded<I, S, T>(&mut self, edges: I) -> usize
pub fn extend_edges_unrecorded<I, S, T>(&mut self, edges: I) -> usize
Bulk-add a sequence of attribute-free directed edges. Bypasses
the per-edge runtime_policy.record_decision call that
[add_edge_with_attrs] makes. Instead, emit one summary record
for the whole batch.
Intended for fnx-internal callers that build a fresh graph
from a known-good edge list where per-edge compatibility
accounting would add constant-factor overhead without adding
useful policy evidence. Nodes referenced by edges are
auto-created if absent, matching add_edge semantics.
Sourcepub fn extend_existing_index_edges_unrecorded<I>(&mut self, edges: I) -> usize
pub fn extend_existing_index_edges_unrecorded<I>(&mut self, edges: I) -> usize
br-r37-c1-tcidx: bulk-add directed edges by EXISTING node index — the directed sibling of
Graph::extend_existing_index_edges_unrecorded. All endpoints MUST already exist (callers
gate on all nodes being pre-added). A new edge takes an empty AttrMap; a duplicate
(source_idx, target_idx) pair is skipped. Emits the IDENTICAL succ/pred adjacency,
revision bump, and batch ledger summary as extend_edges_unrecorded given the same
resolved index sequence — but with ZERO String hashing (endpoints arrive as integer
indices). Unblocks the O(|V|²)-closure transitive_closure from paying a per-edge
get_index_of on both endpoints.
Sourcepub fn extend_nodes_unrecorded<I, N>(&mut self, nodes: I) -> usize
pub fn extend_nodes_unrecorded<I, N>(&mut self, nodes: I) -> usize
br-r37-c1-digbatch: bulk-add plain nodes (no attrs), one summary ledger
record — the directed sibling of Graph::extend_nodes_unrecorded, backing
PyDiGraph’s fast integer-node path (add_nodes_from(range) / int list).
First insertion wins order; existing nodes are skipped.
Sourcepub fn extend_nodes_with_attrs_unrecorded<I>(&mut self, nodes: I) -> usize
pub fn extend_nodes_with_attrs_unrecorded<I>(&mut self, nodes: I) -> usize
br-r37-c1-dgctor: bulk-add nodes WITH attrs, one summary ledger
record — the directed sibling of Graph::extend_nodes_unrecorded
extended with per-node AttrMaps. First insertion wins the order;
re-inserting an existing node merges attrs (matching
add_node_with_attrs).
Sourcepub fn extend_edges_with_attrs_unrecorded<I>(&mut self, edges: I) -> usize
pub fn extend_edges_with_attrs_unrecorded<I>(&mut self, edges: I) -> usize
br-r37-c1-dgctor: bulk-add ATTRIBUTED directed edges without
per-edge ledger records — the directed sibling of
Graph::extend_edges_with_attrs_unrecorded. Insert-or-MERGE
(duplicate (source, target) extends the existing AttrMap, matching
add_edge_with_attrs); nodes auto-created in first-appearance
order. Callers must pre-screen “__fnx_incompatible” attr keys.
Sourcepub fn extend_prepared_edges_with_attrs_row_staged_unrecorded<I, N>(
&mut self,
new_nodes: N,
edges: I,
) -> usize
pub fn extend_prepared_edges_with_attrs_row_staged_unrecorded<I, N>( &mut self, new_nodes: N, edges: I, ) -> usize
Bulk-add ATTRIBUTED directed edges when the caller has already identified newly-created nodes. This keeps edge-map insertion in global input order, then stages successor and predecessor row commits by row so adjacency maps are probed once per touched row rather than once per edge.
Sourcepub fn extend_existing_index_edges_with_attrs_unrecorded<I>(
&mut self,
edges: I,
) -> usize
pub fn extend_existing_index_edges_with_attrs_unrecorded<I>( &mut self, edges: I, ) -> usize
Bulk-add attributed directed edges into a fresh graph when the caller has already assigned NetworkX-compatible node indices in first-seen order.
This bypasses the string-key lookup path in
[extend_prepared_edges_with_attrs_row_staged_unrecorded]: node labels
are installed once, then edges are committed directly by (source_idx, target_idx). Duplicate directed edges merge attributes without appending
another successor/predecessor entry, matching DiGraph.add_edges_from.
br-r37-c1-dodattrbatch: bulk-add ATTRIBUTED directed edges by EXISTING
node index. All endpoints MUST already exist (callers gate on int-labeled
nodes). A new edge takes the AttrMap; a duplicate (source, target) MERGES
last-wins like add_edge_with_attrs. Sibling of the fresh-index attr extend
minus node creation; integer index rows only (no String hashing).
pub fn extend_fresh_index_edges_with_attrs_unrecorded<I, N>( &mut self, nodes: N, edges: I, ) -> usize
pub fn apply_edge_defaults(&mut self, defaults: &AttrMap) -> bool
Sourcepub fn replace_edge_attrs(
&mut self,
source: &str,
target: &str,
attrs: AttrMap,
) -> bool
pub fn replace_edge_attrs( &mut self, source: &str, target: &str, attrs: AttrMap, ) -> bool
br-r37-c1-sjf4t: overwrite the attribute map for an existing edge.
Sourcepub fn replace_node_attrs(&mut self, node: &str, attrs: AttrMap) -> bool
pub fn replace_node_attrs(&mut self, node: &str, attrs: AttrMap) -> bool
br-r37-c1-sjf4t: overwrite the attribute map for an existing node.
Sourcepub fn remove_edge(&mut self, source: &str, target: &str) -> bool
pub fn remove_edge(&mut self, source: &str, target: &str) -> bool
Remove directed edge source→target. Returns true if it existed.
Sourcepub fn remove_node(&mut self, node: &str) -> bool
pub fn remove_node(&mut self, node: &str) -> bool
Remove node and all incident edges (both incoming and outgoing).
pub fn remove_nodes_from<'a, I>(&mut self, nodes: I) -> (usize, usize)where
I: IntoIterator<Item = &'a str>,
Sourcepub fn is_compact(&self) -> bool
pub fn is_compact(&self) -> bool
Nothing removed since the last compaction: every node’s slot is its position (O(1)).
pub fn ensure_compact(&mut self)
Sourcepub fn edges_ordered(&self) -> Vec<EdgeSnapshot>
pub fn edges_ordered(&self) -> Vec<EdgeSnapshot>
Edges in deterministic order: iterate nodes in insertion order, then each node’s successors in insertion order.
pub fn edges_ordered_indices_borrowed(&self) -> Vec<(usize, usize, &AttrMap)>
pub fn edges_ordered_borrowed(&self) -> Vec<(&str, &str, &AttrMap)>
Sourcepub fn weighted_size_int(&self, weight: &str) -> Option<i128>
pub fn weighted_size_int(&self, weight: &str) -> Option<i128>
br-r37-c1-wsize (cc): integer size(weight) from the store — directed
twin of Graph::weighted_size_int. A directed edge (u,v,w) adds w to
out_degree(u) and in_degree(v), so sum(degree)/2 halves back to each
edge’s weight once; a self-loop adds w to both in and out of one node →
2w → halves to w, again one stored edge counted once. Returns None on
any non-integer weight (caller uses the exact degree path); missing weight
defaults to nx’s int 1.
Sourcepub fn reversed(&self) -> Self
pub fn reversed(&self) -> Self
br-r37-c1-revborrow: O(V+E) directed transpose. The reverse of a
DiGraph keeps the SAME node table (identical insertion order, identical
indices), so reversing is a pure topology flip — no String hashing, no
per-edge node-index lookups, no re-insertion through the name table (the
edge-iterate + edges_ordered() clone + extend_edges_with_attrs_*
re-hash path is O(E) String/hash work this avoids entirely).
Successor rows are rebuilt by walking the ORIGINAL successor rows in
node-major (ascending source index) order and appending the reversed
endpoint, so the reversed graph’s edges_ordered() stream is
byte-identical to NetworkX’s reverse(), which walks self.edges()
(u-major successor order) and adds each (v, u). pred_indices[u] ends
up equal to the original succ_indices[u], matching NetworkX’s reversed
pred order as well. Node + edge attribute maps are cloned verbatim.
Sourcepub fn edges_ordered_indices(&self) -> Vec<(usize, usize)>
pub fn edges_ordered_indices(&self) -> Vec<(usize, usize)>
Directed edge endpoints in the same order as edges_ordered_borrowed.
pub fn snapshot(&self) -> DiGraphSnapshot
Sourcepub fn to_undirected(&self) -> Graph
pub fn to_undirected(&self) -> Graph
Convert to an undirected Graph by dropping directionality. Both (u→v) and (v→u) merge into a single undirected edge. When both exist, the latter’s attributes overwrite the former’s.