Skip to main content

MultiGraph

Struct MultiGraph 

Source
pub struct MultiGraph { /* private fields */ }

Implementations§

Source§

impl MultiGraph

Source

pub fn clone_with_fresh_policy(&self) -> Self

br-r37-c1-7dpyg: structural clone with a FRESH RuntimePolicy — see Graph::clone_with_fresh_policy.

Source

pub fn reorder_rows_for_nx_copy_walk(&mut self)

br-r37-c1-s0d4x: reorder every adjacency row into NetworkX’s MultiGraph.copy() walk order — the multigraph counterpart of Graph::reorder_rows_for_nx_copy_walk (cells move wholesale). A pair’s cells enter both rows at the first u-major touch: row u = earlier-position neighbors sorted by (pos(v), index of u within row v), then the rest (self-loops included) in original order.

Source

pub fn apply_row_orders(&mut self, orders: &[(String, Vec<String>)])

br-r37-c1-u3qyn: restore explicit adjacency row orders (pickle round-trip) — see Graph::apply_row_orders. Multigraph rows are keyed cells (neighbor -> key set); the cells move wholesale.

Source

pub fn reorder_rows_like(&mut self, source: &Self)

br-r37-c1-36v6r: order each row as source’s row for the node of the same name - a graph built from a filtered view of source by a copy-shaped walk, whose rows the view shows as source’s rows filtered (see Graph::reorder_rows_like). Cells move wholesale; like apply_row_orders, drops the int-adjacency memo rather than moving revision.

Source

pub fn new(mode: CompatibilityMode) -> Self

Source

pub fn with_runtime_policy(runtime_policy: RuntimePolicy) -> Self

Source

pub fn strict() -> Self

Source

pub fn hardened() -> Self

Source

pub fn mode(&self) -> CompatibilityMode

Source

pub fn node_count(&self) -> usize

Source

pub fn edge_count(&self) -> usize

Source

pub fn number_of_selfloops(&self) -> usize

Source

pub fn edge_keys(&self, left: &str, right: &str) -> Option<Vec<usize>>

Return edge keys as Vec (needed by Python bindings).

Source

pub fn edge_keys_iter(&self, left: &str, right: &str) -> Option<MgEdgeKeys<'_>>

Return an iterator over keys for edges between left and right.

Source

pub fn revision(&self) -> u64

Source

pub fn has_node(&self, node: &str) -> bool

Source

pub fn has_edge(&self, left: &str, right: &str) -> bool

Source

pub fn has_edge_by_indices(&self, li: usize, ri: usize) -> bool

br-r37-c1-04z53 (cc): resolve has_edge straight from insertion-order indices, skipping the i.to_string() heap alloc the Python binding pays for int nodes. The names come from the node table by index (borrowed, no alloc); the caller (PyMultiGraph::has_edge) guards each index with node_index_matches_int so the identity index == int-value holds (any removal / remap that broke it fails the guard and falls through to the String path). Mirror of Graph::has_edge_by_indices.

br-r37-c1-2ndmw: THIS TAKES A POSITION AND THE EDGE MAP IS KEYED BY SLOT, which is the whole subtlety. It used to bridge the two spaces by resolving both positions back to NAMES and calling the string has_edge, which re-hashes both node keys – so this was O(node key length) while Graph::has_edge_by_indices was a genuine O(1) contains_key, and every caller taking the “index fast path” (PyMultiGraph::has_edge, the edge-view probe, the algorithms bulk paths) still paid for the key length it was trying to avoid.

slot_at_position bridges the same gap in O(1) with no hashing, and substitutes an EQUAL value rather than changing behaviour: MgSlabStorage::has_edge(l, r) is itself defined as node_order.get(l) and node_order.get(r) followed by has_edge_by_pair, and the slot get(name) returns for an entry is the slot get_index(position) returns for that same entry.

What must NEVER happen is passing the position straight to has_edge_by_pair: the spaces coincide only until a node is removed, after which that reports a real edge as absent. Pinned by multigraph_node_slot_and_position_are_distinct_index_spaces, and the equivalence pinned by multigraph_has_edge_by_indices_matches_the_string_path_across_removals.

Source

pub fn edge_attrs_by_indices( &self, li: usize, ri: usize, key: usize, ) -> Option<&AttrMap>

br-r37-c1-s8dj1: attributes of a KEYED edge, addressed by node POSITION.

The keyed sibling of Self::has_edge_by_indices, and it exists for the same reason: PyMultiGraph::has_edge had an O(1) path only while key was None, so (u, v) in G.edges – which passes key 0 – paid two canonicalisations and several node-key hashes and grew 3.6x from 2- to 2000-character keys while the keyless form stayed flat.

Takes POSITIONS and converts them to SLOTS, exactly as the keyless sibling does. Passing a position straight to the slot-keyed store reports a real edge as absent after any node removal – see multigraph_node_slot_and_position_are_distinct_index_spaces.

Source

pub fn nodes_ordered(&self) -> Vec<&str>

Source

pub fn get_node_index(&self, node: &str) -> Option<usize>

Resolve a node through the insertion-ordered node table without rebuilding a query-local name-to-index map.

Source

pub fn get_node_name(&self, index: usize) -> Option<&str>

Resolve the current node name for an insertion-order index.

Source

pub fn node_index_matches_int(&self, idx: usize) -> bool

br-cc-nbunchbulk: int membership fast path for _nbunch_present — see the simple-Graph accessor.

Source

pub fn node_names_are_positions(&self) -> bool

br-r37-c1-qaqog: every node’s name is the decimal of its position, so an int key k IS the node at position k when k < node_count() and is absent otherwise - Graph::node_names_are_positions. O(V) on first use, kept current in O(1) after.

Source

pub fn neighbors(&self, node: &str) -> Option<Vec<&str>>

Source

pub fn neighbors_iter(&self, node: &str) -> Option<MgNeighborNames<'_>>

Source

pub fn with_int_adjacency<R>(&self, f: impl FnOnce(&[Vec<usize>]) -> R) -> R

br-r37-c1-thp6w slice 1: run f with the integer adjacency (hash-free neighbor rows), built lazily from the stable-slot rows and memoized until the next mutation. The memo is keyed on revision (bumped by every content mutation) and cleared by apply_row_orders (the one order-only mutator), so the rows always match the current storage byte-for-byte. The closure form lets a whole traversal borrow the rows under one read lock without a per-node allocation. Foundation for the epoch’s neighbors_indices traversal; no caller yet (infrastructure).

Source

pub fn edge_keys_vec(&self, left: &str, right: &str) -> Vec<usize>

Source

pub fn node_attrs(&self, node: &str) -> Option<&AttrMap>

Source

pub fn edge_attrs( &self, left: &str, right: &str, key: usize, ) -> Option<&AttrMap>

Source

pub fn edge_attr_values( &self, left: &str, right: &str, ) -> Option<impl Iterator<Item = &AttrMap> + '_>

Iterator over the AttrMaps of every parallel edge between left and right (undirected: the single canonical bucket), yielded in the SAME order as edge_keys / edge_keys_iter. The adjacency IndexSet<usize> and this edges IndexMap<usize, AttrMap> are appended together on add and both shift_removed on per-key remove (whole bucket dropped on node/endpoint removal), so their key order stays identical — callers that need adjacency-order iteration (e.g. the order-sensitive Neumaier weighted degree) may consume this directly instead of re-looking-up each key. Undirected sibling of MultiDiGraph::edge_attr_values.

Source

pub fn evidence_ledger(&self) -> &EvidenceLedger

Source

pub fn drain_decision_records(&mut self) -> Vec<DecisionRecord>

Source

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 that skipped a malformed input line in hardened mode) in this graph’s evidence ledger, so decision_records() reports it like a native one.

Source

pub fn runtime_policy(&self) -> &RuntimePolicy

Source

pub fn set_runtime_policy(&mut self, runtime_policy: RuntimePolicy)

Source

pub fn is_directed(&self) -> bool

Source

pub fn is_multigraph(&self) -> bool

Source

pub fn degree(&self, node: &str) -> usize

Return the degree of a node (total number of parallel edges incident). Self-loops contribute 2 to the degree each (NetworkX convention).

Source

pub fn isolates(&self) -> Vec<String>

br-r37-c1-mgisol (cc): native isolate detection for MultiGraph. A node is isolated iff it has no incident edges (empty/absent adjacency row); a self-loop keeps a node non-isolated (the loop records the node in its own row, matching nx’s degree-2 self-loop convention). Yields nodes in insertion order — identical to the G.degree()-driven nx generator and to the old multigraph_to_simple_graph projection path, but WITHOUT the per-call O(V+E) simple-graph rebuild that dominated the binding.

Source

pub fn number_of_isolates(&self) -> usize

br-r37-c1-mgisol (cc): isolate count without the simple-graph projection.

Source

pub fn is_isolate(&self, node: &str) -> bool

br-r37-c1-mgisol (cc): O(1) isolate predicate. Absent node -> false (mirrors is_isolate(&Graph)); the binding validates presence first.

Source

pub fn add_node(&mut self, node: impl AsRef<str>) -> bool

Source

pub fn add_node_with_attrs( &mut self, node: impl AsRef<str>, attrs: AttrMap, ) -> bool

Source

pub fn add_edge( &mut self, left: impl Into<String>, right: impl Into<String>, ) -> Result<usize, GraphError>

Source

pub fn add_edge_with_attrs( &mut self, left: impl Into<String>, right: impl Into<String>, attrs: AttrMap, ) -> Result<usize, GraphError>

Source

pub fn add_edge_with_key_and_attrs( &mut self, left: impl Into<String>, right: impl Into<String>, key: usize, attrs: AttrMap, ) -> Result<usize, GraphError>

Source

pub fn add_fresh_edge_unrecorded( &mut self, left: impl Into<String>, right: impl Into<String>, ) -> Option<usize>

Insert one attribute-free edge for a pair known to have no existing parallel edge bucket. Returns None if the pair already exists.

Source

pub fn add_fresh_edge_with_key_unrecorded( &mut self, left: impl Into<String>, right: impl Into<String>, key: usize, ) -> Option<usize>

Insert one attribute-free edge with an explicit key for a pair known to have no existing parallel edge bucket. Returns None if the pair already exists.

Source

pub fn extend_nodes_with_attrs_unrecorded<I>(&mut self, nodes: I) -> usize
where I: IntoIterator<Item = (String, AttrMap)>,

br-r37-c1-l5ve7: bulk node insert WITH attrs, one ledger record — MultiGraph mirror of MultiDiGraph::extend_nodes_with_attrs_unrecorded. Existing nodes merge attrs (extend).

Source

pub fn extend_nodes_unrecorded<I, N>(&mut self, nodes: I) -> usize
where I: IntoIterator<Item = N>, N: AsRef<str>,

Bulk node insert without attrs, one summary ledger record.

Source

pub fn extend_keyed_edges_with_attrs_unrecorded<I>(&mut self, edges: I) -> usize
where I: IntoIterator<Item = (String, String, usize, AttrMap)>,

br-r37-c1-l5ve7: bulk KEYED edge insert WITH attrs, one ledger record — MultiGraph mirror of MultiDiGraph::extend_keyed_edges_with_attrs_unrecorded (add_edge_impl pays TWO record_decision calls per edge). Endpoint nodes are created on demand; an existing (u, v, key) cell merges attrs (extend), matching add_edge_with_key_and_attrs.

Source

pub fn extend_fresh_int_prefix_keyed_edges_unrecorded<I>( &mut self, node_count: usize, edges: I, ) -> usize
where I: IntoIterator<Item = (usize, usize, usize)>,

Bulk-load attribute-free keyed edges for a freshly-created integer prefix graph. The caller has already validated that node first-seen order is exactly 0..node_count and that internal keys are sequential per undirected pair, so this builds the string-keyed MultiGraph state directly from indices instead of canonicalizing both endpoints for every edge in the Python boundary layer.

Source

pub fn extend_fresh_index_keyed_edges_with_attrs_unrecorded<I, N>( &mut self, nodes: N, edges: I, ) -> usize
where I: IntoIterator<Item = (usize, usize, usize, AttrMap)>, N: IntoIterator<Item = String>,

Bulk-load attributed keyed edges for a freshly-created integer-indexed graph. The caller has already assigned NetworkX-compatible node labels and per-undirected-pair keys, so this avoids endpoint string hashing in the Python boundary layer while preserving the normal MultiGraph storage layout.

Source

pub fn replace_edge_attrs( &mut self, left: &str, right: &str, key: usize, attrs: AttrMap, ) -> bool

br-r37-c1-sjf4t: overwrite the attribute map for an existing (u, v, key) edge. Returns whether the edge existed.

Source

pub fn replace_node_attrs(&mut self, node: &str, attrs: AttrMap) -> bool

br-r37-c1-sjf4t: overwrite the attribute map for an existing node.

Source

pub fn remove_edge( &mut self, left: &str, right: &str, key: Option<usize>, ) -> bool

Source

pub fn clear_edges(&mut self)

Source

pub fn remove_node(&mut self, node: &str) -> bool

Source

pub fn remove_nodes_from<'a, I>(&mut self, nodes: I) -> (usize, usize)
where I: IntoIterator<Item = &'a str>,

br-r37-c1-mgrnf: batch node removal — one O(|V|+|E|) retain pass, matching the simple-Graph batch (Graph::remove_nodes_from) that the directed types already carry. (remove_node itself is O(degree) since yr2oc.1, so this pays off only for a large share of the graph.) Returns (removed_node_count, removed_edge_instance_count).

Source

pub fn edges_ordered(&self) -> Vec<MultiEdgeSnapshot>

Source

pub fn edges_ordered_borrowed(&self) -> Vec<(&str, &str, usize, &AttrMap)>

Source

pub fn weighted_size_int(&self, weight: &str) -> Option<i128>

br-r37-c1-wsize (cc): integer size(weight) from the store — the multigraph twin of Graph::weighted_size_int. Each parallel edge is one bucket entry in self.edges and contributes its weight once (size halves degree’s double count); a self-loop key is one stored edge counted once. Returns None on any non-integer weight (caller uses the exact float/PyObject degree path); missing weight defaults to nx’s int 1.

Source

pub fn edges_ordered_indices_borrowed( &self, ) -> Vec<(usize, usize, usize, &AttrMap)>

Source

pub fn snapshot(&self) -> MultiGraphSnapshot

Trait Implementations§

Source§

impl Clone for MultiGraph

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for MultiGraph

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.