From 8cdfa445d6629ffef4cb84967ff7017654045bc2 Mon Sep 17 00:00:00 2001 From: mo khan Date: Wed, 2 Jul 2025 18:36:06 -0600 Subject: chore: add vendor directory --- vendor/petgraph/src/acyclic.rs | 867 +++++++ vendor/petgraph/src/acyclic/order_map.rs | 193 ++ vendor/petgraph/src/adj.rs | 653 ++++++ vendor/petgraph/src/algo/astar.rs | 178 ++ vendor/petgraph/src/algo/bellman_ford.rs | 244 ++ vendor/petgraph/src/algo/coloring.rs | 96 + vendor/petgraph/src/algo/dijkstra.rs | 122 + vendor/petgraph/src/algo/dominators.rs | 333 +++ vendor/petgraph/src/algo/feedback_arc_set.rs | 449 ++++ vendor/petgraph/src/algo/floyd_warshall.rs | 143 ++ vendor/petgraph/src/algo/ford_fulkerson.rs | 196 ++ vendor/petgraph/src/algo/isomorphism.rs | 994 ++++++++ vendor/petgraph/src/algo/k_shortest_path.rs | 115 + vendor/petgraph/src/algo/matching.rs | 606 +++++ vendor/petgraph/src/algo/min_spanning_tree.rs | 117 + vendor/petgraph/src/algo/mod.rs | 867 +++++++ vendor/petgraph/src/algo/page_rank.rs | 185 ++ vendor/petgraph/src/algo/simple_paths.rs | 199 ++ vendor/petgraph/src/algo/tred.rs | 162 ++ vendor/petgraph/src/csr.rs | 1151 ++++++++++ vendor/petgraph/src/data.rs | 478 ++++ vendor/petgraph/src/dot.rs | 371 +++ vendor/petgraph/src/generate.rs | 133 ++ vendor/petgraph/src/graph6/graph6_decoder.rs | 200 ++ vendor/petgraph/src/graph6/graph6_encoder.rs | 154 ++ vendor/petgraph/src/graph6/mod.rs | 7 + vendor/petgraph/src/graph_impl/frozen.rs | 108 + vendor/petgraph/src/graph_impl/mod.rs | 2411 ++++++++++++++++++++ vendor/petgraph/src/graph_impl/serialization.rs | 355 +++ vendor/petgraph/src/graph_impl/stable_graph/mod.rs | 2103 +++++++++++++++++ .../src/graph_impl/stable_graph/serialization.rs | 298 +++ vendor/petgraph/src/graphmap.rs | 1504 ++++++++++++ vendor/petgraph/src/iter_format.rs | 102 + vendor/petgraph/src/iter_utils.rs | 32 + vendor/petgraph/src/lib.rs | 305 +++ vendor/petgraph/src/macros.rs | 108 + vendor/petgraph/src/matrix_graph.rs | 1814 +++++++++++++++ vendor/petgraph/src/operator.rs | 83 + vendor/petgraph/src/prelude.rs | 21 + vendor/petgraph/src/quickcheck.rs | 216 ++ vendor/petgraph/src/scored.rs | 93 + vendor/petgraph/src/serde_utils.rs | 95 + vendor/petgraph/src/traits_graph.rs | 73 + vendor/petgraph/src/unionfind.rs | 146 ++ vendor/petgraph/src/util.rs | 16 + vendor/petgraph/src/visit/dfsvisit.rs | 314 +++ vendor/petgraph/src/visit/filter.rs | 583 +++++ vendor/petgraph/src/visit/macros.rs | 135 ++ vendor/petgraph/src/visit/mod.rs | 481 ++++ vendor/petgraph/src/visit/reversed.rs | 184 ++ vendor/petgraph/src/visit/traversal.rs | 536 +++++ vendor/petgraph/src/visit/undirected_adaptor.rs | 111 + 52 files changed, 21440 insertions(+) create mode 100644 vendor/petgraph/src/acyclic.rs create mode 100644 vendor/petgraph/src/acyclic/order_map.rs create mode 100644 vendor/petgraph/src/adj.rs create mode 100644 vendor/petgraph/src/algo/astar.rs create mode 100644 vendor/petgraph/src/algo/bellman_ford.rs create mode 100644 vendor/petgraph/src/algo/coloring.rs create mode 100644 vendor/petgraph/src/algo/dijkstra.rs create mode 100644 vendor/petgraph/src/algo/dominators.rs create mode 100644 vendor/petgraph/src/algo/feedback_arc_set.rs create mode 100644 vendor/petgraph/src/algo/floyd_warshall.rs create mode 100644 vendor/petgraph/src/algo/ford_fulkerson.rs create mode 100644 vendor/petgraph/src/algo/isomorphism.rs create mode 100644 vendor/petgraph/src/algo/k_shortest_path.rs create mode 100644 vendor/petgraph/src/algo/matching.rs create mode 100644 vendor/petgraph/src/algo/min_spanning_tree.rs create mode 100644 vendor/petgraph/src/algo/mod.rs create mode 100644 vendor/petgraph/src/algo/page_rank.rs create mode 100644 vendor/petgraph/src/algo/simple_paths.rs create mode 100644 vendor/petgraph/src/algo/tred.rs create mode 100644 vendor/petgraph/src/csr.rs create mode 100644 vendor/petgraph/src/data.rs create mode 100644 vendor/petgraph/src/dot.rs create mode 100644 vendor/petgraph/src/generate.rs create mode 100644 vendor/petgraph/src/graph6/graph6_decoder.rs create mode 100644 vendor/petgraph/src/graph6/graph6_encoder.rs create mode 100644 vendor/petgraph/src/graph6/mod.rs create mode 100644 vendor/petgraph/src/graph_impl/frozen.rs create mode 100644 vendor/petgraph/src/graph_impl/mod.rs create mode 100644 vendor/petgraph/src/graph_impl/serialization.rs create mode 100644 vendor/petgraph/src/graph_impl/stable_graph/mod.rs create mode 100644 vendor/petgraph/src/graph_impl/stable_graph/serialization.rs create mode 100644 vendor/petgraph/src/graphmap.rs create mode 100644 vendor/petgraph/src/iter_format.rs create mode 100644 vendor/petgraph/src/iter_utils.rs create mode 100644 vendor/petgraph/src/lib.rs create mode 100644 vendor/petgraph/src/macros.rs create mode 100644 vendor/petgraph/src/matrix_graph.rs create mode 100644 vendor/petgraph/src/operator.rs create mode 100644 vendor/petgraph/src/prelude.rs create mode 100644 vendor/petgraph/src/quickcheck.rs create mode 100644 vendor/petgraph/src/scored.rs create mode 100644 vendor/petgraph/src/serde_utils.rs create mode 100644 vendor/petgraph/src/traits_graph.rs create mode 100644 vendor/petgraph/src/unionfind.rs create mode 100644 vendor/petgraph/src/util.rs create mode 100644 vendor/petgraph/src/visit/dfsvisit.rs create mode 100644 vendor/petgraph/src/visit/filter.rs create mode 100644 vendor/petgraph/src/visit/macros.rs create mode 100644 vendor/petgraph/src/visit/mod.rs create mode 100644 vendor/petgraph/src/visit/reversed.rs create mode 100644 vendor/petgraph/src/visit/traversal.rs create mode 100644 vendor/petgraph/src/visit/undirected_adaptor.rs (limited to 'vendor/petgraph/src') diff --git a/vendor/petgraph/src/acyclic.rs b/vendor/petgraph/src/acyclic.rs new file mode 100644 index 00000000..801a7b3a --- /dev/null +++ b/vendor/petgraph/src/acyclic.rs @@ -0,0 +1,867 @@ +//! A wrapper around graph types that enforces an acyclicity invariant. + +use std::{ + cell::RefCell, + cmp::Ordering, + collections::{BTreeMap, BTreeSet}, + convert::TryFrom, + ops::{Deref, RangeBounds}, +}; + +use crate::{ + adj::IndexType, + algo::Cycle, + data::{Build, Create, DataMap, DataMapMut}, + graph::NodeIndex, + prelude::DiGraph, + visit::{ + dfs_visitor, Control, Data, DfsEvent, EdgeCount, EdgeIndexable, GetAdjacencyMatrix, + GraphBase, GraphProp, IntoEdgeReferences, IntoEdges, IntoEdgesDirected, IntoNeighbors, + IntoNeighborsDirected, IntoNodeIdentifiers, IntoNodeReferences, NodeCompactIndexable, + NodeCount, NodeIndexable, Reversed, Time, Visitable, + }, + Direction, +}; + +#[cfg(feature = "stable_graph")] +use crate::stable_graph::StableDiGraph; + +mod order_map; +use fixedbitset::FixedBitSet; +use order_map::OrderMap; +pub use order_map::TopologicalPosition; + +/// A directed acyclic graph. +/// +/// Wrap directed acyclic graphs and expose an API that ensures the invariant +/// is maintained, i.e. no cycles can be created. This uses a topological order +/// that is dynamically updated when edges are added. In the worst case, the +/// runtime may be linear in the number of vertices, but it has been shown to +/// be fast in practice, particularly on sparse graphs (Pierce and Kelly, 2004). +/// +/// To be modifiable (and hence to be useful), the graphs of generic type `G` +/// should implement the [`Build`] trait. Good candidates for `G` are thus +/// [`crate::graph::DiGraph`] and [`crate::stable_graph::StableDiGraph`]. +/// +/// ## Algorithm +/// This implements the PK algorithm for dynamic topological sort described in +/// "A Dynamic Topological Sort Algorithm for Directed Acyclic Graphs" by +/// D. Pierce and P. Kelly, JEA, 2004. It maintains a topological order of the +/// nodes that can be efficiently updated when edges are added. Achieves a good +/// balance between simplicity and performance in practice, see the paper for +/// discussions of the running time. +/// +/// ## Graph traits +/// All graph traits are delegated to the inner graph, with the exception of +/// the graph construction trait [`Build`]. The wrapped graph can thus only +/// be modified through the wrapped API that ensures no cycles are created. +/// +/// ## Behaviour on cycles +/// By design, edge additions to this datatype may fail. It is recommended to +/// prefer the dedicated [`Acyclic::try_add_edge`] and +/// [`Acyclic::try_update_edge`] methods whenever possible. The +/// [`Build::update_edge`] methods will panic if it is attempted to add an edge +/// that would create a cycle. The [`Build::add_edge`] on the other hand method +/// will return `None` if the edge cannot be added (either it already exists on +/// a graph type that does not support it or would create a cycle). +#[derive(Clone, Debug)] +pub struct Acyclic { + /// The underlying graph, accessible through the `inner` method. + graph: G, + /// The current topological order of the nodes. + order_map: OrderMap, + + // We fix the internal DFS maps to FixedBitSet instead of G::VisitMap to do + // faster resets (by just setting bits to false) + /// Helper map for DFS tracking discovered nodes. + discovered: RefCell, + /// Helper map for DFS tracking finished nodes. + finished: RefCell, +} + +/// An error that can occur during edge addition for acyclic graphs. +#[derive(Clone, Debug, PartialEq)] +pub enum AcyclicEdgeError { + /// The edge would create a cycle. + Cycle(Cycle), + /// The edge would create a self-loop. + SelfLoop, + /// Could not successfully add the edge to the underlying graph. + InvalidEdge, +} + +impl From> for AcyclicEdgeError { + fn from(cycle: Cycle) -> Self { + AcyclicEdgeError::Cycle(cycle) + } +} + +impl Acyclic { + /// Create a new empty acyclic graph. + pub fn new() -> Self + where + G: Default, + { + Default::default() + } + + /// Get an iterator over the nodes, ordered by their position. + pub fn nodes_iter(&self) -> impl Iterator + '_ { + self.order_map.nodes_iter() + } + + /// Get an iterator over the nodes within the range of positions. + /// + /// The nodes are ordered by their position in the topological sort. + pub fn range<'r>( + &'r self, + range: impl RangeBounds + 'r, + ) -> impl Iterator + 'r { + self.order_map.range(range) + } + + /// Get the underlying graph. + pub fn inner(&self) -> &G { + &self.graph + } + + /// Get the underlying graph mutably. + /// + /// This cannot be public because it might break the acyclicity invariant. + fn inner_mut(&mut self) -> &mut G { + &mut self.graph + } + + /// Consume the `Acyclic` wrapper and return the underlying graph. + pub fn into_inner(self) -> G { + self.graph + } +} + +impl Acyclic +where + for<'a> &'a G: IntoNeighborsDirected + IntoNodeIdentifiers + GraphBase, +{ + /// Wrap a graph into an acyclic graph. + /// + /// The graph types [`DiGraph`] and [`StableDiGraph`] also implement + /// [`TryFrom`], which can be used instead of this method and have looser + /// type bounds. + pub fn try_from_graph(graph: G) -> Result> { + let order_map = OrderMap::try_from_graph(&graph)?; + let discovered = RefCell::new(FixedBitSet::with_capacity(graph.node_bound())); + let finished = RefCell::new(FixedBitSet::with_capacity(graph.node_bound())); + Ok(Self { + graph, + order_map, + discovered, + finished, + }) + } + + /// Add an edge to the graph using [`Build::add_edge`]. + /// + /// Returns the id of the added edge, or an [`AcyclicEdgeError`] if the edge + /// would create a cycle, a self-loop or if the edge addition failed in + /// the underlying graph. + /// + /// In cases where edge addition cannot fail in the underlying graph (e.g. + /// when multi-edges are allowed, as in [`DiGraph`] and [`StableDiGraph`]), + /// this will return an error if and only if [`Self::is_valid_edge`] + /// returns `false`. + pub fn try_add_edge( + &mut self, + a: G::NodeId, + b: G::NodeId, + weight: G::EdgeWeight, + ) -> Result> + where + G: Build, + G::NodeId: IndexType, + { + if a == b { + // No self-loops allowed + return Err(AcyclicEdgeError::SelfLoop); + } + self.update_ordering(a, b)?; + self.graph + .add_edge(a, b, weight) + .ok_or(AcyclicEdgeError::InvalidEdge) + } + + /// Update an edge in a graph using [`Build::update_edge`]. + /// + /// Returns the id of the updated edge, or an [`AcyclicEdgeError`] if the edge + /// would create a cycle or a self-loop. If the edge does not exist, the + /// edge is created. + /// + /// This will return an error if and only if [`Self::is_valid_edge`] returns + /// `false`. + pub fn try_update_edge( + &mut self, + a: G::NodeId, + b: G::NodeId, + weight: G::EdgeWeight, + ) -> Result> + where + G: Build, + G::NodeId: IndexType, + { + if a == b { + // No self-loops allowed + return Err(AcyclicEdgeError::SelfLoop); + } + self.update_ordering(a, b)?; + Ok(self.graph.update_edge(a, b, weight)) + } + + /// Check if an edge would be valid, i.e. adding it would not create a cycle. + pub fn is_valid_edge(&self, a: G::NodeId, b: G::NodeId) -> bool + where + G::NodeId: IndexType, + { + if a == b { + false // No self-loops + } else if self.get_position(a) < self.get_position(b) { + true // valid edge in the current topological order + } else { + // Check if the future of `b` is disjoint from the past of `a` + // (in which case the topological order could be adjusted) + self.causal_cones(b, a).is_ok() + } + } + + /// Update the ordering of the nodes in the order map resulting from adding an + /// edge a -> b. + /// + /// If a cycle is detected, an error is returned and `self` remains unchanged. + /// + /// Implements the core update logic of the PK algorithm. + fn update_ordering(&mut self, a: G::NodeId, b: G::NodeId) -> Result<(), Cycle> + where + G::NodeId: IndexType, + { + let min_order = self.get_position(b); + let max_order = self.get_position(a); + if min_order >= max_order { + // Order is already correct + return Ok(()); + } + + // Get the nodes reachable from `b` and the nodes that can reach `a` + // between `min_order` and `max_order` + let (b_fut, a_past) = self.causal_cones(b, a)?; + + // Now reorder of nodes in a_past and b_fut such that + // i) within each vec, the nodes are in topological order, + // ii) all elements of b_fut come before all elements of a_past in the new order. + let all_positions: BTreeSet<_> = b_fut.keys().chain(a_past.keys()).copied().collect(); + let all_nodes = a_past.values().chain(b_fut.values()).copied(); + + debug_assert_eq!(all_positions.len(), b_fut.len() + a_past.len()); + + for (pos, node) in all_positions.into_iter().zip(all_nodes) { + self.order_map.set_position(node, pos, &self.graph); + } + Ok(()) + } + + /// Use DFS to find the future causal cone of `min_node` and the past causal + /// cone of `max_node`. + /// + /// The cones are trimmed to the range `[min_order, max_order]`. The cones + /// are returned if they are disjoint. Otherwise, a [`Cycle`] error is returned. + /// + /// If `return_result` is false, then the cones are not constructed and the + /// method only checks for disjointness. + #[allow(clippy::type_complexity)] + fn causal_cones( + &self, + min_node: G::NodeId, + max_node: G::NodeId, + ) -> Result< + ( + BTreeMap, + BTreeMap, + ), + Cycle, + > + where + G::NodeId: IndexType, + { + debug_assert!(self.discovered.borrow().is_clear()); + debug_assert!(self.finished.borrow().is_clear()); + + let min_order = self.get_position(min_node); + let max_order = self.get_position(max_node); + + // Prepare DFS scratch space: make sure the maps have enough capacity + if self.discovered.borrow().len() < self.graph.node_bound() { + self.discovered.borrow_mut().grow(self.graph.node_bound()); + self.finished.borrow_mut().grow(self.graph.node_bound()); + } + + // Get all nodes reachable from b with min_order <= order < max_order + let mut forward_cone = BTreeMap::new(); + let mut backward_cone = BTreeMap::new(); + + // The main logic: run DFS twice. We run this in a closure to catch + // errors and reset the maps properly at the end. + let mut run_dfs = || { + // Get all nodes reachable from min_node with min_order < order <= max_order + self.future_cone(min_node, min_order, max_order, &mut forward_cone)?; + + // Get all nodes that can reach a with min_order < order <= max_order + // These are disjoint from the nodes in the forward cone, otherwise + // we would have a cycle. + self.past_cone(max_node, min_order, max_order, &mut backward_cone) + .expect("cycles already detected in future_cone"); + + Ok(()) + }; + + let success = run_dfs(); + + // Cleanup: reset map to 0. This is faster than a full reset, especially + // on large sparse graphs. + for &v in forward_cone.values().chain(backward_cone.values()) { + self.discovered.borrow_mut().set(v.index(), false); + self.finished.borrow_mut().set(v.index(), false); + } + debug_assert!(self.discovered.borrow().is_clear()); + debug_assert!(self.finished.borrow().is_clear()); + + match success { + Ok(()) => Ok((forward_cone, backward_cone)), + Err(cycle) => Err(cycle), + } + } + + fn future_cone( + &self, + start: G::NodeId, + min_position: TopologicalPosition, + max_position: TopologicalPosition, + res: &mut BTreeMap, + ) -> Result<(), Cycle> + where + G::NodeId: IndexType, + { + dfs( + &self.graph, + start, + &self.order_map, + |order| { + debug_assert!(order >= min_position, "invalid topological order"); + match order.cmp(&max_position) { + Ordering::Less => Ok(true), // node within [min_node, max_node] + Ordering::Equal => Err(Cycle(start)), // cycle! + Ordering::Greater => Ok(false), // node beyond [min_node, max_node] + } + }, + res, + &mut self.discovered.borrow_mut(), + &mut self.finished.borrow_mut(), + ) + } + + fn past_cone( + &self, + start: G::NodeId, + min_position: TopologicalPosition, + max_position: TopologicalPosition, + res: &mut BTreeMap, + ) -> Result<(), Cycle> + where + G::NodeId: IndexType, + { + dfs( + Reversed(&self.graph), + start, + &self.order_map, + |order| { + debug_assert!(order <= max_position, "invalid topological order"); + match order.cmp(&min_position) { + Ordering::Less => Ok(false), // node beyond [min_node, max_node] + Ordering::Equal => panic!("found by future_cone"), // cycle! + Ordering::Greater => Ok(true), // node within [min_node, max_node] + } + }, + res, + &mut self.discovered.borrow_mut(), + &mut self.finished.borrow_mut(), + ) + } +} + +impl GraphBase for Acyclic { + type NodeId = G::NodeId; + type EdgeId = G::EdgeId; +} + +impl Default for Acyclic { + fn default() -> Self { + let graph: G = Default::default(); + let order_map = Default::default(); + let discovered = RefCell::new(FixedBitSet::default()); + let finished = RefCell::new(FixedBitSet::default()); + Self { + graph, + order_map, + discovered, + finished, + } + } +} + +impl Build for Acyclic +where + for<'a> &'a G: IntoNeighborsDirected + + IntoNodeIdentifiers + + Visitable + + GraphBase, + G::NodeId: IndexType, +{ + fn add_node(&mut self, weight: Self::NodeWeight) -> Self::NodeId { + let n = self.graph.add_node(weight); + self.order_map.add_node(n, &self.graph); + n + } + + fn add_edge( + &mut self, + a: Self::NodeId, + b: Self::NodeId, + weight: Self::EdgeWeight, + ) -> Option { + self.try_add_edge(a, b, weight).ok() + } + + fn update_edge( + &mut self, + a: Self::NodeId, + b: Self::NodeId, + weight: Self::EdgeWeight, + ) -> Self::EdgeId { + self.try_update_edge(a, b, weight).unwrap() + } +} + +impl Create for Acyclic +where + for<'a> &'a G: IntoNeighborsDirected + + IntoNodeIdentifiers + + Visitable + + GraphBase, + G::NodeId: IndexType, +{ + fn with_capacity(nodes: usize, edges: usize) -> Self { + let graph = G::with_capacity(nodes, edges); + let order_map = OrderMap::with_capacity(nodes); + let discovered = FixedBitSet::with_capacity(nodes); + let finished = FixedBitSet::with_capacity(nodes); + Self { + graph, + order_map, + discovered: RefCell::new(discovered), + finished: RefCell::new(finished), + } + } +} + +impl Deref for Acyclic { + type Target = G; + + fn deref(&self) -> &Self::Target { + &self.graph + } +} + +/// Traverse nodes in `graph` in DFS order, starting from `start`, for as long +/// as the predicate `valid_order` returns `true` on the current node's order. +fn dfs( + graph: G, + start: G::NodeId, + order_map: &OrderMap, + // A predicate that returns whether to continue the search from a node, + // or an error to stop and shortcircuit the search. + mut valid_order: impl FnMut(TopologicalPosition) -> Result>, + res: &mut BTreeMap, + discovered: &mut FixedBitSet, + finished: &mut FixedBitSet, +) -> Result<(), Cycle> +where + G::NodeId: IndexType, +{ + dfs_visitor( + graph, + start, + &mut |ev| -> Result, Cycle> { + match ev { + DfsEvent::Discover(u, _) => { + // We are visiting u + let order = order_map.get_position(u, &graph); + res.insert(order, u); + Ok(Control::Continue) + } + DfsEvent::TreeEdge(_, u) => { + // Should we visit u? + let order = order_map.get_position(u, &graph); + match valid_order(order) { + Ok(true) => Ok(Control::Continue), + Ok(false) => Ok(Control::Prune), + Err(cycle) => Err(cycle), + } + } + _ => Ok(Control::Continue), + } + }, + discovered, + finished, + &mut Time::default(), + )?; + + Ok(()) +} + +/////////////////////// Pass-through graph traits /////////////////////// +// We implement all the following traits by delegating to the inner graph: +// - Data +// - DataMap +// - DataMapMut +// - EdgeCount +// - EdgeIndexable +// - GetAdjacencyMatrix +// - GraphProp +// - NodeCompactIndexable +// - NodeCount +// - NodeIndexable +// - Visitable +// +// Furthermore, we also implement the `remove_node` and `remove_edge` methods, +// as well as the following traits for `DiGraph` and `StableDiGraph` (these +// are hard/impossible to implement generically): +// - TryFrom +// - IntoEdgeReferences +// - IntoEdges +// - IntoEdgesDirected +// - IntoNeighbors +// - IntoNeighborsDirected +// - IntoNodeIdentifiers +// - IntoNodeReferences + +impl Data for Acyclic { + type NodeWeight = G::NodeWeight; + type EdgeWeight = G::EdgeWeight; +} + +impl DataMap for Acyclic { + fn node_weight(&self, id: Self::NodeId) -> Option<&Self::NodeWeight> { + self.inner().node_weight(id) + } + + fn edge_weight(&self, id: Self::EdgeId) -> Option<&Self::EdgeWeight> { + self.inner().edge_weight(id) + } +} + +impl DataMapMut for Acyclic { + fn node_weight_mut(&mut self, id: Self::NodeId) -> Option<&mut Self::NodeWeight> { + self.inner_mut().node_weight_mut(id) + } + + fn edge_weight_mut(&mut self, id: Self::EdgeId) -> Option<&mut Self::EdgeWeight> { + self.inner_mut().edge_weight_mut(id) + } +} + +impl EdgeCount for Acyclic { + fn edge_count(&self) -> usize { + self.inner().edge_count() + } +} + +impl EdgeIndexable for Acyclic { + fn edge_bound(&self) -> usize { + self.inner().edge_bound() + } + + fn to_index(&self, a: Self::EdgeId) -> usize { + self.inner().to_index(a) + } + + fn from_index(&self, i: usize) -> Self::EdgeId { + self.inner().from_index(i) + } +} + +impl GetAdjacencyMatrix for Acyclic { + type AdjMatrix = G::AdjMatrix; + + fn adjacency_matrix(&self) -> Self::AdjMatrix { + self.inner().adjacency_matrix() + } + + fn is_adjacent(&self, matrix: &Self::AdjMatrix, a: Self::NodeId, b: Self::NodeId) -> bool { + self.inner().is_adjacent(matrix, a, b) + } +} + +impl GraphProp for Acyclic { + type EdgeType = G::EdgeType; +} + +impl NodeCompactIndexable for Acyclic {} + +impl NodeCount for Acyclic { + fn node_count(&self) -> usize { + self.inner().node_count() + } +} + +impl NodeIndexable for Acyclic { + fn node_bound(&self) -> usize { + self.inner().node_bound() + } + + fn to_index(&self, a: Self::NodeId) -> usize { + self.inner().to_index(a) + } + + fn from_index(&self, i: usize) -> Self::NodeId { + self.inner().from_index(i) + } +} + +impl Visitable for Acyclic { + type Map = G::Map; + + fn visit_map(&self) -> Self::Map { + self.inner().visit_map() + } + + fn reset_map(&self, map: &mut Self::Map) { + self.inner().reset_map(map) + } +} + +macro_rules! impl_graph_traits { + ($graph_type:ident) => { + // Remove edge and node methods (not available through traits) + impl Acyclic<$graph_type> { + /// Remove an edge and return its edge weight, or None if it didn't exist. + /// + /// Pass through to underlying graph. + pub fn remove_edge( + &mut self, + e: <$graph_type as GraphBase>::EdgeId, + ) -> Option { + self.graph.remove_edge(e) + } + + /// Remove a node from the graph if it exists, and return its + /// weight. If it doesn't exist in the graph, return None. + /// + /// This updates the order in O(v) runtime and removes the node in + /// the underlying graph. + pub fn remove_node( + &mut self, + n: <$graph_type as GraphBase>::NodeId, + ) -> Option { + self.order_map.remove_node(n, &self.graph); + self.graph.remove_node(n) + } + } + + impl TryFrom<$graph_type> + for Acyclic<$graph_type> + { + type Error = Cycle>; + + fn try_from(graph: $graph_type) -> Result { + let order_map = OrderMap::try_from_graph(&graph)?; + let discovered = RefCell::new(FixedBitSet::with_capacity(graph.node_bound())); + let finished = RefCell::new(FixedBitSet::with_capacity(graph.node_bound())); + Ok(Self { + graph, + order_map, + discovered, + finished, + }) + } + } + + impl<'a, N, E, Ix: IndexType> IntoEdgeReferences for &'a Acyclic<$graph_type> { + type EdgeRef = <&'a $graph_type as IntoEdgeReferences>::EdgeRef; + type EdgeReferences = <&'a $graph_type as IntoEdgeReferences>::EdgeReferences; + + fn edge_references(self) -> Self::EdgeReferences { + self.inner().edge_references() + } + } + + impl<'a, N, E, Ix: IndexType> IntoEdges for &'a Acyclic<$graph_type> { + type Edges = <&'a $graph_type as IntoEdges>::Edges; + + fn edges(self, a: Self::NodeId) -> Self::Edges { + self.inner().edges(a) + } + } + + impl<'a, N, E, Ix: IndexType> IntoEdgesDirected for &'a Acyclic<$graph_type> { + type EdgesDirected = <&'a $graph_type as IntoEdgesDirected>::EdgesDirected; + + fn edges_directed(self, a: Self::NodeId, dir: Direction) -> Self::EdgesDirected { + self.inner().edges_directed(a, dir) + } + } + + impl<'a, N, E, Ix: IndexType> IntoNeighbors for &'a Acyclic<$graph_type> { + type Neighbors = <&'a $graph_type as IntoNeighbors>::Neighbors; + + fn neighbors(self, a: Self::NodeId) -> Self::Neighbors { + self.inner().neighbors(a) + } + } + + impl<'a, N, E, Ix: IndexType> IntoNeighborsDirected for &'a Acyclic<$graph_type> { + type NeighborsDirected = + <&'a $graph_type as IntoNeighborsDirected>::NeighborsDirected; + + fn neighbors_directed(self, n: Self::NodeId, d: Direction) -> Self::NeighborsDirected { + self.inner().neighbors_directed(n, d) + } + } + + impl<'a, N, E, Ix: IndexType> IntoNodeIdentifiers for &'a Acyclic<$graph_type> { + type NodeIdentifiers = + <&'a $graph_type as IntoNodeIdentifiers>::NodeIdentifiers; + + fn node_identifiers(self) -> Self::NodeIdentifiers { + self.inner().node_identifiers() + } + } + + impl<'a, N, E, Ix: IndexType> IntoNodeReferences for &'a Acyclic<$graph_type> { + type NodeRef = <&'a $graph_type as IntoNodeReferences>::NodeRef; + type NodeReferences = <&'a $graph_type as IntoNodeReferences>::NodeReferences; + + fn node_references(self) -> Self::NodeReferences { + self.inner().node_references() + } + } + }; +} + +impl_graph_traits!(DiGraph); +#[cfg(feature = "stable_graph")] +impl_graph_traits!(StableDiGraph); + +#[cfg(test)] +mod tests { + use super::*; + use crate::prelude::DiGraph; + #[cfg(feature = "stable_graph")] + use crate::prelude::StableDiGraph; + use crate::visit::IntoNodeReferences; + + #[test] + fn test_acyclic_graph() { + // Create an acyclic DiGraph + let mut graph = DiGraph::<(), ()>::new(); + let a = graph.add_node(()); + let c = graph.add_node(()); + let b = graph.add_node(()); + graph.add_edge(a, b, ()); + graph.add_edge(b, c, ()); + + // Create an Acyclic object + let mut acyclic = Acyclic::try_from_graph(graph).unwrap(); + + // Test initial topological order + assert_valid_topological_order(&acyclic); + + // Add a valid edge + assert!(acyclic.try_add_edge(a, c, ()).is_ok()); + assert_valid_topological_order(&acyclic); + + // Try to add an edge that would create a cycle + assert!(acyclic.try_add_edge(c, a, ()).is_err()); + + // Add another valid edge + let d = acyclic.add_node(()); + assert!(acyclic.try_add_edge(c, d, ()).is_ok()); + assert_valid_topological_order(&acyclic); + + // Try to add an edge that would create a cycle (using the Build trait) + assert!(acyclic.add_edge(d, a, ()).is_none()); + } + + #[cfg(feature = "stable_graph")] + #[test] + fn test_acyclic_graph_add_remove() { + // Create an initial Acyclic graph with two nodes and one edge + let mut acyclic = Acyclic::>::new(); + let a = acyclic.add_node(()); + let b = acyclic.add_node(()); + assert!(acyclic.try_add_edge(a, b, ()).is_ok()); + + // Check initial topological order + assert_valid_topological_order(&acyclic); + + // Add a new node and an edge + let c = acyclic.add_node(()); + assert!(acyclic.try_add_edge(b, c, ()).is_ok()); + + // Check topological order after addition + assert_valid_topological_order(&acyclic); + + // Remove the node connected to two edges (node b) + acyclic.remove_node(b); + + // Check topological order after removal + assert_valid_topological_order(&acyclic); + + // Verify the remaining structure + let remaining_nodes: Vec<_> = acyclic + .inner() + .node_references() + .map(|(id, _)| id) + .collect(); + assert_eq!(remaining_nodes.len(), 2); + assert!(remaining_nodes.contains(&a)); + assert!(remaining_nodes.contains(&c)); + assert!(!acyclic.inner().contains_edge(a, c)); + } + + fn assert_valid_topological_order<'a, G>(acyclic: &'a Acyclic) + where + G: Visitable + NodeCount + NodeIndexable, + &'a G: NodeIndexable + + IntoNodeReferences + + IntoNeighborsDirected + + GraphBase, + G::NodeId: std::fmt::Debug, + { + let ordered_nodes: Vec<_> = acyclic.nodes_iter().collect(); + assert_eq!(ordered_nodes.len(), acyclic.node_count()); + let nodes: Vec<_> = acyclic.inner().node_identifiers().collect(); + + // Check that the nodes are in topological order + let mut last_position = None; + for (idx, &node) in ordered_nodes.iter().enumerate() { + assert!(nodes.contains(&node)); + + // Check that the node positions are monotonically increasing + let pos = acyclic.get_position(node); + assert!(Some(pos) > last_position); + last_position = Some(pos); + + // Check that the neighbors are in the future of the current node + for neighbor in acyclic.inner().neighbors(node) { + let neighbour_idx = ordered_nodes.iter().position(|&n| n == neighbor).unwrap(); + assert!(neighbour_idx > idx); + } + } + } +} diff --git a/vendor/petgraph/src/acyclic/order_map.rs b/vendor/petgraph/src/acyclic/order_map.rs new file mode 100644 index 00000000..4938041a --- /dev/null +++ b/vendor/petgraph/src/acyclic/order_map.rs @@ -0,0 +1,193 @@ +//! A bijective map between node indices and a `TopologicalPosition`, to store +//! the total topological order of the graph. +//! +//! This data structure is an implementation detail and is not exposed in the +//! public API. +use std::{collections::BTreeMap, fmt, ops::RangeBounds}; + +use crate::{ + algo::{toposort, Cycle}, + visit::{GraphBase, IntoNeighborsDirected, IntoNodeIdentifiers, NodeIndexable, Visitable}, +}; + +/// A position in the topological order of the graph. +/// +/// This defines a total order over the set of nodes in the graph. +/// +/// Note that the positions of all nodes in a graph may not form a contiguous +/// interval. +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Default)] +#[repr(transparent)] +pub struct TopologicalPosition(pub(super) usize); + +/// A bijective map between node indices and their position in a topological order. +/// +/// Note that this map does not check for injectivity or surjectivity, this +/// must be enforced by the user. Map mutations that invalidate these properties +/// are allowed to make it easy to perform batch modifications that temporarily +/// break the invariants. +#[derive(Clone)] +pub(super) struct OrderMap { + /// Map topological position to node index. + pos_to_node: BTreeMap, + /// The inverse of `pos_to_node`, i.e. map node indices to their position. + /// + /// This is a Vec, relying on `N: NodeIndexable` for indexing. + node_to_pos: Vec, +} + +impl Default for OrderMap { + fn default() -> Self { + Self { + pos_to_node: Default::default(), + node_to_pos: Default::default(), + } + } +} + +impl fmt::Debug for OrderMap { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("OrderMap") + .field("order", &self.pos_to_node) + .finish() + } +} + +impl OrderMap { + pub(super) fn try_from_graph(graph: G) -> Result> + where + G: NodeIndexable + IntoNeighborsDirected + IntoNodeIdentifiers + Visitable, + { + // Compute the topological order. + let topo_vec = toposort(graph, None)?; + + // Create the two map directions. + let mut pos_to_node = BTreeMap::new(); + let mut node_to_pos = vec![TopologicalPosition::default(); graph.node_bound()]; + + // Populate the maps. + for (i, &id) in topo_vec.iter().enumerate() { + let pos = TopologicalPosition(i); + pos_to_node.insert(pos, id); + node_to_pos[graph.to_index(id)] = pos; + } + + Ok(Self { + pos_to_node, + node_to_pos, + }) + } + + pub(super) fn with_capacity(nodes: usize) -> Self { + Self { + pos_to_node: BTreeMap::new(), + node_to_pos: Vec::with_capacity(nodes), + } + } + + /// Map a node to its position in the topological order. + /// + /// Panics if the node index is out of bounds. + pub(super) fn get_position( + &self, + id: N, + graph: impl NodeIndexable, + ) -> TopologicalPosition { + let idx = graph.to_index(id); + assert!(idx < self.node_to_pos.len()); + self.node_to_pos[idx] + } + + /// Map a position in the topological order to a node, if it exists. + pub(super) fn at_position(&self, pos: TopologicalPosition) -> Option { + self.pos_to_node.get(&pos).copied() + } + + /// Get an iterator over the nodes, ordered by their position. + pub(super) fn nodes_iter(&self) -> impl Iterator + '_ { + self.pos_to_node.values().copied() + } + + /// Get an iterator over the nodes within the range of positions. + pub(super) fn range( + &self, + range: impl RangeBounds, + ) -> impl Iterator + '_ { + self.pos_to_node.range(range).map(|(_, &n)| n) + } + + /// Add a node to the order map and assign it an arbitrary position. + /// + /// Return the position of the new node. + pub(super) fn add_node( + &mut self, + id: N, + graph: impl NodeIndexable, + ) -> TopologicalPosition { + // The position and node index + let new_pos = self + .pos_to_node + .iter() + .next_back() + .map(|(TopologicalPosition(idx), _)| TopologicalPosition(idx + 1)) + .unwrap_or_default(); + let idx = graph.to_index(id); + + // Make sure the order_inv is large enough. + if idx >= self.node_to_pos.len() { + self.node_to_pos + .resize(graph.node_bound(), TopologicalPosition::default()); + } + + // Insert both map directions. + self.pos_to_node.insert(new_pos, id); + self.node_to_pos[idx] = new_pos; + + new_pos + } + + /// Remove a node from the order map. + /// + /// Panics if the node index is out of bounds. + pub(super) fn remove_node(&mut self, id: N, graph: impl NodeIndexable) { + let idx = graph.to_index(id); + assert!(idx < self.node_to_pos.len()); + + let pos = self.node_to_pos[idx]; + self.node_to_pos[idx] = TopologicalPosition::default(); + self.pos_to_node.remove(&pos); + } + + /// Set the position of a node. + /// + /// Panics if the node index is out of bounds. + pub(super) fn set_position( + &mut self, + id: N, + pos: TopologicalPosition, + graph: impl NodeIndexable, + ) { + let idx = graph.to_index(id); + assert!(idx < self.node_to_pos.len()); + + self.pos_to_node.insert(pos, id); + self.node_to_pos[idx] = pos; + } +} + +impl super::Acyclic { + /// Get the position of a node in the topological sort. + /// + /// Panics if the node index is out of bounds. + pub fn get_position<'a>(&'a self, id: G::NodeId) -> TopologicalPosition + where + &'a G: NodeIndexable + GraphBase, + { + self.order_map.get_position(id, &self.graph) + } + + /// Get the node at a given position in the topological sort, if it exists. + pub fn at_position(&self, pos: TopologicalPosition) -> Option { + self.order_map.at_position(pos) + } +} diff --git a/vendor/petgraph/src/adj.rs b/vendor/petgraph/src/adj.rs new file mode 100644 index 00000000..0d107bfc --- /dev/null +++ b/vendor/petgraph/src/adj.rs @@ -0,0 +1,653 @@ +//! Simple adjacency list. +use crate::data::{Build, DataMap, DataMapMut}; +use crate::iter_format::NoPretty; +use crate::visit::{ + self, EdgeCount, EdgeRef, GetAdjacencyMatrix, IntoEdgeReferences, IntoNeighbors, NodeCount, +}; +use fixedbitset::FixedBitSet; +use std::fmt; +use std::ops::Range; + +#[doc(no_inline)] +pub use crate::graph::{DefaultIx, IndexType}; + +/// Adjacency list node index type, a plain integer. +pub type NodeIndex = Ix; + +/// Adjacency list edge index type, a pair of integers. +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct EdgeIndex +where + Ix: IndexType, +{ + /// Source of the edge. + from: NodeIndex, + /// Index of the sucessor in the successor list. + successor_index: usize, +} + +iterator_wrap! { +impl (Iterator) for +/// An Iterator over the indices of the outgoing edges from a node. +/// +/// It does not borrow the graph during iteration. +#[derive(Debug, Clone)] +struct OutgoingEdgeIndices where { Ix: IndexType } +item: EdgeIndex, +iter: std::iter::Map, std::iter::Repeat>>, fn((usize, NodeIndex)) -> EdgeIndex>, +} + +/// Weighted sucessor +#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +struct WSuc { + /// Index of the sucessor. + suc: Ix, + /// Weight of the edge to `suc`. + weight: E, +} + +/// One row of the adjacency list. +type Row = Vec>; +type RowIter<'a, E, Ix> = std::slice::Iter<'a, WSuc>; + +iterator_wrap! { +impl (Iterator DoubleEndedIterator ExactSizeIterator) for +/// An iterator over the indices of the neighbors of a node. +#[derive(Debug, Clone)] +struct Neighbors<'a, E, Ix> where { Ix: IndexType } +item: NodeIndex, +iter: std::iter::Map, fn(&WSuc) -> NodeIndex>, +} + +/// A reference to an edge of the graph. +#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)] +pub struct EdgeReference<'a, E, Ix: IndexType> { + /// index of the edge + id: EdgeIndex, + /// a reference to the corresponding item in the adjacency list + edge: &'a WSuc, +} + +impl Copy for EdgeReference<'_, E, Ix> {} +impl Clone for EdgeReference<'_, E, Ix> { + fn clone(&self) -> Self { + *self + } +} + +impl visit::EdgeRef for EdgeReference<'_, E, Ix> { + type NodeId = NodeIndex; + type EdgeId = EdgeIndex; + type Weight = E; + fn source(&self) -> Self::NodeId { + self.id.from + } + fn target(&self) -> Self::NodeId { + self.edge.suc + } + fn id(&self) -> Self::EdgeId { + self.id + } + fn weight(&self) -> &Self::Weight { + &self.edge.weight + } +} + +#[derive(Debug, Clone)] +pub struct EdgeIndices<'a, E, Ix: IndexType> { + rows: std::iter::Enumerate>>, + row_index: usize, + row_len: usize, + cur: usize, +} + +impl Iterator for EdgeIndices<'_, E, Ix> { + type Item = EdgeIndex; + fn next(&mut self) -> Option> { + loop { + if self.cur < self.row_len { + let res = self.cur; + self.cur += 1; + return Some(EdgeIndex { + from: Ix::new(self.row_index), + successor_index: res, + }); + } else { + match self.rows.next() { + Some((index, row)) => { + self.row_index = index; + self.cur = 0; + self.row_len = row.len(); + } + None => return None, + } + } + } + } +} + +iterator_wrap! { + impl (Iterator DoubleEndedIterator ExactSizeIterator) for + /// An iterator over all node indices in the graph. + #[derive(Debug, Clone)] + struct NodeIndices where {} + item: Ix, + iter: std::iter::Map, fn(usize) -> Ix>, +} + +/// An adjacency list with labeled edges. +/// +/// Can be interpreted as a directed graph +/// with unweighted nodes. +/// +/// This is the most simple adjacency list you can imagine. [`Graph`](../graph/struct.Graph.html), in contrast, +/// maintains both the list of successors and predecessors for each node, +/// which is a different trade-off. +/// +/// Allows parallel edges and self-loops. +/// +/// This data structure is append-only (except for [`clear`](#method.clear)), so indices +/// returned at some point for a given graph will stay valid with this same +/// graph until it is dropped or [`clear`](#method.clear) is called. +/// +/// Space consumption: **O(|E|)**. +#[derive(Clone, Default)] +pub struct List +where + Ix: IndexType, +{ + suc: Vec>, +} + +impl List { + /// Creates a new, empty adjacency list. + pub fn new() -> List { + List { suc: Vec::new() } + } + + /// Creates a new, empty adjacency list tailored for `nodes` nodes. + pub fn with_capacity(nodes: usize) -> List { + List { + suc: Vec::with_capacity(nodes), + } + } + + /// Removes all nodes and edges from the list. + pub fn clear(&mut self) { + self.suc.clear() + } + + /// Returns the number of edges in the list + /// + /// Computes in **O(|V|)** time. + pub fn edge_count(&self) -> usize { + self.suc.iter().map(|x| x.len()).sum() + } + + /// Adds a new node to the list. This allocates a new `Vec` and then should + /// run in amortized **O(1)** time. + pub fn add_node(&mut self) -> NodeIndex { + let i = self.suc.len(); + self.suc.push(Vec::new()); + Ix::new(i) + } + + /// Adds a new node to the list. This allocates a new `Vec` and then should + /// run in amortized **O(1)** time. + pub fn add_node_with_capacity(&mut self, successors: usize) -> NodeIndex { + let i = self.suc.len(); + self.suc.push(Vec::with_capacity(successors)); + Ix::new(i) + } + + /// Adds a new node to the list by giving its list of successors and the corresponding + /// weigths. + pub fn add_node_from_edges, E)>>( + &mut self, + edges: I, + ) -> NodeIndex { + let i = self.suc.len(); + self.suc + .push(edges.map(|(suc, weight)| WSuc { suc, weight }).collect()); + Ix::new(i) + } + + /// Add an edge from `a` to `b` to the graph, with its associated + /// data `weight`. + /// + /// Return the index of the new edge. + /// + /// Computes in **O(1)** time. + /// + /// **Panics** if the source node does not exist.
+ /// + /// **Note:** `List` allows adding parallel (“duplicate”) edges. If you want + /// to avoid this, use [`.update_edge(a, b, weight)`](#method.update_edge) instead. + pub fn add_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> EdgeIndex { + if b.index() >= self.suc.len() { + panic!( + "{} is not a valid node index for a {} nodes adjacency list", + b.index(), + self.suc.len() + ); + } + let row = &mut self.suc[a.index()]; + let rank = row.len(); + row.push(WSuc { suc: b, weight }); + EdgeIndex { + from: a, + successor_index: rank, + } + } + + fn get_edge(&self, e: EdgeIndex) -> Option<&WSuc> { + self.suc + .get(e.from.index()) + .and_then(|row| row.get(e.successor_index)) + } + + fn get_edge_mut(&mut self, e: EdgeIndex) -> Option<&mut WSuc> { + self.suc + .get_mut(e.from.index()) + .and_then(|row| row.get_mut(e.successor_index)) + } + + /// Accesses the source and target of edge `e` + /// + /// Computes in **O(1)** + pub fn edge_endpoints(&self, e: EdgeIndex) -> Option<(NodeIndex, NodeIndex)> { + self.get_edge(e).map(|x| (e.from, x.suc)) + } + + pub fn edge_indices_from(&self, a: NodeIndex) -> OutgoingEdgeIndices { + let proj: fn((usize, NodeIndex)) -> EdgeIndex = + |(successor_index, from)| EdgeIndex { + from, + successor_index, + }; + let iter = (0..(self.suc[a.index()].len())) + .zip(std::iter::repeat(a)) + .map(proj); + OutgoingEdgeIndices { iter } + } + + /// Lookups whether there is an edge from `a` to `b`. + /// + /// Computes in **O(e')** time, where **e'** is the number of successors of `a`. + pub fn contains_edge(&self, a: NodeIndex, b: NodeIndex) -> bool { + match self.suc.get(a.index()) { + None => false, + Some(row) => row.iter().any(|x| x.suc == b), + } + } + + /// Lookups whether there is an edge from `a` to `b`. + /// + /// Computes in **O(e')** time, where **e'** is the number of successors of `a`. + pub fn find_edge(&self, a: NodeIndex, b: NodeIndex) -> Option> { + self.suc.get(a.index()).and_then(|row| { + row.iter() + .enumerate() + .find(|(_, x)| x.suc == b) + .map(|(i, _)| EdgeIndex { + from: a, + successor_index: i, + }) + }) + } + + /// Returns an iterator over all node indices of the graph. + /// + /// Consuming the whole iterator take **O(|V|)**. + pub fn node_indices(&self) -> NodeIndices { + NodeIndices { + iter: (0..self.suc.len()).map(Ix::new), + } + } + + /// Returns an iterator over all edge indices of the graph. + /// + /// Consuming the whole iterator take **O(|V| + |E|)**. + pub fn edge_indices(&self) -> EdgeIndices { + EdgeIndices { + rows: self.suc.iter().enumerate(), + row_index: 0, + row_len: 0, + cur: 0, + } + } +} + +/// A very simple adjacency list with no node or label weights. +pub type UnweightedList = List<(), Ix>; + +impl Build for List { + /// Adds a new node to the list. This allocates a new `Vec` and then should + /// run in amortized **O(1)** time. + fn add_node(&mut self, _weight: ()) -> NodeIndex { + self.add_node() + } + + /// Add an edge from `a` to `b` to the graph, with its associated + /// data `weight`. + /// + /// Return the index of the new edge. + /// + /// Computes in **O(1)** time. + /// + /// **Panics** if the source node does not exist.
+ /// + /// **Note:** `List` allows adding parallel (“duplicate”) edges. If you want + /// to avoid this, use [`.update_edge(a, b, weight)`](#method.update_edge) instead. + fn add_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> Option> { + Some(self.add_edge(a, b, weight)) + } + + /// Updates or adds an edge from `a` to `b` to the graph, with its associated + /// data `weight`. + /// + /// Return the index of the new edge. + /// + /// Computes in **O(e')** time, where **e'** is the number of successors of `a`. + /// + /// **Panics** if the source node does not exist.
+ fn update_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> EdgeIndex { + let row = &mut self.suc[a.index()]; + for (i, info) in row.iter_mut().enumerate() { + if info.suc == b { + info.weight = weight; + return EdgeIndex { + from: a, + successor_index: i, + }; + } + } + let rank = row.len(); + row.push(WSuc { suc: b, weight }); + EdgeIndex { + from: a, + successor_index: rank, + } + } +} + +impl fmt::Debug for EdgeReferences<'_, E, Ix> +where + E: fmt::Debug, + Ix: IndexType, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut edge_list = f.debug_list(); + let iter: Self = self.clone(); + for e in iter { + if std::mem::size_of::() != 0 { + edge_list.entry(&( + NoPretty((e.source().index(), e.target().index())), + e.weight(), + )); + } else { + edge_list.entry(&NoPretty((e.source().index(), e.target().index()))); + } + } + edge_list.finish() + } +} + +impl fmt::Debug for List +where + E: fmt::Debug, + Ix: IndexType, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut fmt_struct = f.debug_struct("adj::List"); + fmt_struct.field("node_count", &self.node_count()); + fmt_struct.field("edge_count", &self.edge_count()); + if self.edge_count() > 0 { + fmt_struct.field("edges", &self.edge_references()); + } + fmt_struct.finish() + } +} + +impl visit::GraphBase for List +where + Ix: IndexType, +{ + type NodeId = NodeIndex; + type EdgeId = EdgeIndex; +} + +impl visit::Visitable for List +where + Ix: IndexType, +{ + type Map = FixedBitSet; + fn visit_map(&self) -> FixedBitSet { + FixedBitSet::with_capacity(self.node_count()) + } + fn reset_map(&self, map: &mut Self::Map) { + map.clear(); + map.grow(self.node_count()); + } +} + +impl visit::IntoNodeIdentifiers for &List { + type NodeIdentifiers = NodeIndices; + fn node_identifiers(self) -> NodeIndices { + self.node_indices() + } +} + +impl visit::NodeRef for NodeIndex { + type NodeId = NodeIndex; + type Weight = (); + fn id(&self) -> Self::NodeId { + *self + } + fn weight(&self) -> &Self::Weight { + &() + } +} + +impl visit::IntoNodeReferences for &List { + type NodeRef = NodeIndex; + type NodeReferences = NodeIndices; + fn node_references(self) -> Self::NodeReferences { + self.node_indices() + } +} + +impl visit::Data for List { + type NodeWeight = (); + type EdgeWeight = E; +} + +impl<'a, E, Ix: IndexType> IntoNeighbors for &'a List { + type Neighbors = Neighbors<'a, E, Ix>; + /// Returns an iterator of all nodes with an edge starting from `a`. + /// Panics if `a` is out of bounds. + /// Use [`List::edge_indices_from`] instead if you do not want to borrow the adjacency list while + /// iterating. + fn neighbors(self, a: NodeIndex) -> Self::Neighbors { + let proj: fn(&WSuc) -> NodeIndex = |x| x.suc; + let iter = self.suc[a.index()].iter().map(proj); + Neighbors { iter } + } +} + +type SomeIter<'a, E, Ix> = std::iter::Map< + std::iter::Zip>, std::iter::Repeat>, + fn(((usize, &'a WSuc), Ix)) -> EdgeReference<'a, E, Ix>, +>; + +iterator_wrap! { +impl (Iterator) for +/// An iterator over the [`EdgeReference`] of all the edges of the graph. +struct EdgeReferences<'a, E, Ix> where { Ix: IndexType } +item: EdgeReference<'a, E, Ix>, +iter: std::iter::FlatMap< + std::iter::Enumerate< + std::slice::Iter<'a, Row> + >, + SomeIter<'a, E, Ix>, + fn( + (usize, &'a Vec>) + ) -> SomeIter<'a, E, Ix>, +>, +} + +impl Clone for EdgeReferences<'_, E, Ix> { + fn clone(&self) -> Self { + EdgeReferences { + iter: self.iter.clone(), + } + } +} + +fn proj1( + ((successor_index, edge), from): ((usize, &WSuc), Ix), +) -> EdgeReference { + let id = EdgeIndex { + from, + successor_index, + }; + EdgeReference { id, edge } +} +fn proj2((row_index, row): (usize, &Vec>)) -> SomeIter { + row.iter() + .enumerate() + .zip(std::iter::repeat(Ix::new(row_index))) + .map(proj1 as _) +} + +impl<'a, Ix: IndexType, E> visit::IntoEdgeReferences for &'a List { + type EdgeRef = EdgeReference<'a, E, Ix>; + type EdgeReferences = EdgeReferences<'a, E, Ix>; + fn edge_references(self) -> Self::EdgeReferences { + let iter = self.suc.iter().enumerate().flat_map(proj2 as _); + EdgeReferences { iter } + } +} + +iterator_wrap! { +impl (Iterator) for +/// Iterator over the [`EdgeReference`] of the outgoing edges from a node. +#[derive(Debug, Clone)] +struct OutgoingEdgeReferences<'a, E, Ix> where { Ix: IndexType } +item: EdgeReference<'a, E, Ix>, +iter: SomeIter<'a, E, Ix>, +} + +impl<'a, Ix: IndexType, E> visit::IntoEdges for &'a List { + type Edges = OutgoingEdgeReferences<'a, E, Ix>; + fn edges(self, a: Self::NodeId) -> Self::Edges { + let iter = self.suc[a.index()] + .iter() + .enumerate() + .zip(std::iter::repeat(a)) + .map(proj1 as _); + OutgoingEdgeReferences { iter } + } +} + +impl visit::GraphProp for List { + type EdgeType = crate::Directed; + fn is_directed(&self) -> bool { + true + } +} + +impl NodeCount for List { + /// Returns the number of nodes in the list + /// + /// Computes in **O(1)** time. + fn node_count(&self) -> usize { + self.suc.len() + } +} + +impl EdgeCount for List { + /// Returns the number of edges in the list + /// + /// Computes in **O(|V|)** time. + fn edge_count(&self) -> usize { + List::edge_count(self) + } +} + +impl visit::NodeIndexable for List { + fn node_bound(&self) -> usize { + self.node_count() + } + #[inline] + fn to_index(&self, a: Self::NodeId) -> usize { + a.index() + } + #[inline] + fn from_index(&self, i: usize) -> Self::NodeId { + Ix::new(i) + } +} + +impl visit::NodeCompactIndexable for List {} + +impl DataMap for List { + fn node_weight(&self, n: Self::NodeId) -> Option<&()> { + if n.index() < self.suc.len() { + Some(&()) + } else { + None + } + } + + /// Accesses the weight of edge `e` + /// + /// Computes in **O(1)** + fn edge_weight(&self, e: EdgeIndex) -> Option<&E> { + self.get_edge(e).map(|x| &x.weight) + } +} + +impl DataMapMut for List { + fn node_weight_mut(&mut self, n: Self::NodeId) -> Option<&mut ()> { + if n.index() < self.suc.len() { + // A hack to produce a &'static mut () + // It does not actually allocate according to godbolt + let b = Box::new(()); + Some(Box::leak(b)) + } else { + None + } + } + /// Accesses the weight of edge `e` + /// + /// Computes in **O(1)** + fn edge_weight_mut(&mut self, e: EdgeIndex) -> Option<&mut E> { + self.get_edge_mut(e).map(|x| &mut x.weight) + } +} + +/// The adjacency matrix for **List** is a bitmap that's computed by +/// `.adjacency_matrix()`. +impl GetAdjacencyMatrix for List +where + Ix: IndexType, +{ + type AdjMatrix = FixedBitSet; + + fn adjacency_matrix(&self) -> FixedBitSet { + let n = self.node_count(); + let mut matrix = FixedBitSet::with_capacity(n * n); + for edge in self.edge_references() { + let i = edge.source().index() * n + edge.target().index(); + matrix.put(i); + } + matrix + } + + fn is_adjacent(&self, matrix: &FixedBitSet, a: NodeIndex, b: NodeIndex) -> bool { + let n = self.node_count(); + let index = n * a.index() + b.index(); + matrix.contains(index) + } +} diff --git a/vendor/petgraph/src/algo/astar.rs b/vendor/petgraph/src/algo/astar.rs new file mode 100644 index 00000000..183542c0 --- /dev/null +++ b/vendor/petgraph/src/algo/astar.rs @@ -0,0 +1,178 @@ +use std::collections::hash_map::Entry::{Occupied, Vacant}; +use std::collections::{BinaryHeap, HashMap}; + +use std::hash::Hash; + +use crate::scored::MinScored; +use crate::visit::{EdgeRef, GraphBase, IntoEdges, Visitable}; + +use crate::algo::Measure; + +/// \[Generic\] A* shortest path algorithm. +/// +/// Computes the shortest path from `start` to `finish`, including the total path cost. +/// +/// `finish` is implicitly given via the `is_goal` callback, which should return `true` if the +/// given node is the finish node. +/// +/// The function `edge_cost` should return the cost for a particular edge. Edge costs must be +/// non-negative. +/// +/// The function `estimate_cost` should return the estimated cost to the finish for a particular +/// node. For the algorithm to find the actual shortest path, it should be admissible, meaning that +/// it should never overestimate the actual cost to get to the nearest goal node. Estimate costs +/// must also be non-negative. +/// +/// The graph should be `Visitable` and implement `IntoEdges`. +/// +/// # Example +/// ``` +/// use petgraph::Graph; +/// use petgraph::algo::astar; +/// +/// let mut g = Graph::new(); +/// let a = g.add_node((0., 0.)); +/// let b = g.add_node((2., 0.)); +/// let c = g.add_node((1., 1.)); +/// let d = g.add_node((0., 2.)); +/// let e = g.add_node((3., 3.)); +/// let f = g.add_node((4., 2.)); +/// g.extend_with_edges(&[ +/// (a, b, 2), +/// (a, d, 4), +/// (b, c, 1), +/// (b, f, 7), +/// (c, e, 5), +/// (e, f, 1), +/// (d, e, 1), +/// ]); +/// +/// // Graph represented with the weight of each edge +/// // Edges with '*' are part of the optimal path. +/// // +/// // 2 1 +/// // a ----- b ----- c +/// // | 4* | 7 | +/// // d f | 5 +/// // | 1* | 1* | +/// // \------ e ------/ +/// +/// let path = astar(&g, a, |finish| finish == f, |e| *e.weight(), |_| 0); +/// assert_eq!(path, Some((6, vec![a, d, e, f]))); +/// ``` +/// +/// Returns the total cost + the path of subsequent `NodeId` from start to finish, if one was +/// found. +pub fn astar( + graph: G, + start: G::NodeId, + mut is_goal: IsGoal, + mut edge_cost: F, + mut estimate_cost: H, +) -> Option<(K, Vec)> +where + G: IntoEdges + Visitable, + IsGoal: FnMut(G::NodeId) -> bool, + G::NodeId: Eq + Hash, + F: FnMut(G::EdgeRef) -> K, + H: FnMut(G::NodeId) -> K, + K: Measure + Copy, +{ + let mut visit_next = BinaryHeap::new(); + let mut scores = HashMap::new(); // g-values, cost to reach the node + let mut estimate_scores = HashMap::new(); // f-values, cost to reach + estimate cost to goal + let mut path_tracker = PathTracker::::new(); + + let zero_score = K::default(); + scores.insert(start, zero_score); + visit_next.push(MinScored(estimate_cost(start), start)); + + while let Some(MinScored(estimate_score, node)) = visit_next.pop() { + if is_goal(node) { + let path = path_tracker.reconstruct_path_to(node); + let cost = scores[&node]; + return Some((cost, path)); + } + + // This lookup can be unwrapped without fear of panic since the node was necessarily scored + // before adding it to `visit_next`. + let node_score = scores[&node]; + + match estimate_scores.entry(node) { + Occupied(mut entry) => { + // If the node has already been visited with an equal or lower score than now, then + // we do not need to re-visit it. + if *entry.get() <= estimate_score { + continue; + } + entry.insert(estimate_score); + } + Vacant(entry) => { + entry.insert(estimate_score); + } + } + + for edge in graph.edges(node) { + let next = edge.target(); + let next_score = node_score + edge_cost(edge); + + match scores.entry(next) { + Occupied(mut entry) => { + // No need to add neighbors that we have already reached through a shorter path + // than now. + if *entry.get() <= next_score { + continue; + } + entry.insert(next_score); + } + Vacant(entry) => { + entry.insert(next_score); + } + } + + path_tracker.set_predecessor(next, node); + let next_estimate_score = next_score + estimate_cost(next); + visit_next.push(MinScored(next_estimate_score, next)); + } + } + + None +} + +struct PathTracker +where + G: GraphBase, + G::NodeId: Eq + Hash, +{ + came_from: HashMap, +} + +impl PathTracker +where + G: GraphBase, + G::NodeId: Eq + Hash, +{ + fn new() -> PathTracker { + PathTracker { + came_from: HashMap::new(), + } + } + + fn set_predecessor(&mut self, node: G::NodeId, previous: G::NodeId) { + self.came_from.insert(node, previous); + } + + fn reconstruct_path_to(&self, last: G::NodeId) -> Vec { + let mut path = vec![last]; + + let mut current = last; + while let Some(&previous) = self.came_from.get(¤t) { + path.push(previous); + current = previous; + } + + path.reverse(); + + path + } +} diff --git a/vendor/petgraph/src/algo/bellman_ford.rs b/vendor/petgraph/src/algo/bellman_ford.rs new file mode 100644 index 00000000..52fbd44c --- /dev/null +++ b/vendor/petgraph/src/algo/bellman_ford.rs @@ -0,0 +1,244 @@ +//! Bellman-Ford algorithms. + +use crate::prelude::*; + +use crate::visit::{IntoEdges, IntoNodeIdentifiers, NodeCount, NodeIndexable, VisitMap, Visitable}; + +use super::{FloatMeasure, NegativeCycle}; + +#[derive(Debug, Clone)] +pub struct Paths { + pub distances: Vec, + pub predecessors: Vec>, +} + +/// \[Generic\] Compute shortest paths from node `source` to all other. +/// +/// Using the [Bellman–Ford algorithm][bf]; negative edge costs are +/// permitted, but the graph must not have a cycle of negative weights +/// (in that case it will return an error). +/// +/// On success, return one vec with path costs, and another one which points +/// out the predecessor of a node along a shortest path. The vectors +/// are indexed by the graph's node indices. +/// +/// [bf]: https://en.wikipedia.org/wiki/Bellman%E2%80%93Ford_algorithm +/// +/// # Example +/// ```rust +/// use petgraph::Graph; +/// use petgraph::algo::bellman_ford; +/// use petgraph::prelude::*; +/// +/// let mut g = Graph::new(); +/// let a = g.add_node(()); // node with no weight +/// let b = g.add_node(()); +/// let c = g.add_node(()); +/// let d = g.add_node(()); +/// let e = g.add_node(()); +/// let f = g.add_node(()); +/// g.extend_with_edges(&[ +/// (0, 1, 2.0), +/// (0, 3, 4.0), +/// (1, 2, 1.0), +/// (1, 5, 7.0), +/// (2, 4, 5.0), +/// (4, 5, 1.0), +/// (3, 4, 1.0), +/// ]); +/// +/// // Graph represented with the weight of each edge +/// // +/// // 2 1 +/// // a ----- b ----- c +/// // | 4 | 7 | +/// // d f | 5 +/// // | 1 | 1 | +/// // \------ e ------/ +/// +/// let path = bellman_ford(&g, a); +/// assert!(path.is_ok()); +/// let path = path.unwrap(); +/// assert_eq!(path.distances, vec![ 0.0, 2.0, 3.0, 4.0, 5.0, 6.0]); +/// assert_eq!(path.predecessors, vec![None, Some(a),Some(b),Some(a), Some(d), Some(e)]); +/// +/// // Node f (indice 5) can be reach from a with a path costing 6. +/// // Predecessor of f is Some(e) which predecessor is Some(d) which predecessor is Some(a). +/// // Thus the path from a to f is a <-> d <-> e <-> f +/// +/// let graph_with_neg_cycle = Graph::<(), f32, Undirected>::from_edges(&[ +/// (0, 1, -2.0), +/// (0, 3, -4.0), +/// (1, 2, -1.0), +/// (1, 5, -25.0), +/// (2, 4, -5.0), +/// (4, 5, -25.0), +/// (3, 4, -1.0), +/// ]); +/// +/// assert!(bellman_ford(&graph_with_neg_cycle, NodeIndex::new(0)).is_err()); +/// ``` +pub fn bellman_ford( + g: G, + source: G::NodeId, +) -> Result, NegativeCycle> +where + G: NodeCount + IntoNodeIdentifiers + IntoEdges + NodeIndexable, + G::EdgeWeight: FloatMeasure, +{ + let ix = |i| g.to_index(i); + + // Step 1 and Step 2: initialize and relax + let (distances, predecessors) = bellman_ford_initialize_relax(g, source); + + // Step 3: check for negative weight cycle + for i in g.node_identifiers() { + for edge in g.edges(i) { + let j = edge.target(); + let w = *edge.weight(); + if distances[ix(i)] + w < distances[ix(j)] { + return Err(NegativeCycle(())); + } + } + } + + Ok(Paths { + distances, + predecessors, + }) +} + +/// \[Generic\] Find the path of a negative cycle reachable from node `source`. +/// +/// Using the [find_negative_cycle][nc]; will search the Graph for negative cycles using +/// [Bellman–Ford algorithm][bf]. If no negative cycle is found the function will return `None`. +/// +/// If a negative cycle is found from source, return one vec with a path of `NodeId`s. +/// +/// The time complexity of this algorithm should be the same as the Bellman-Ford (O(|V|·|E|)). +/// +/// [nc]: https://blogs.asarkar.com/assets/docs/algorithms-curated/Negative-Weight%20Cycle%20Algorithms%20-%20Huang.pdf +/// [bf]: https://en.wikipedia.org/wiki/Bellman%E2%80%93Ford_algorithm +/// +/// # Example +/// ```rust +/// use petgraph::Graph; +/// use petgraph::algo::find_negative_cycle; +/// use petgraph::prelude::*; +/// +/// let graph_with_neg_cycle = Graph::<(), f32, Directed>::from_edges(&[ +/// (0, 1, 1.), +/// (0, 2, 1.), +/// (0, 3, 1.), +/// (1, 3, 1.), +/// (2, 1, 1.), +/// (3, 2, -3.), +/// ]); +/// +/// let path = find_negative_cycle(&graph_with_neg_cycle, NodeIndex::new(0)); +/// assert_eq!( +/// path, +/// Some([NodeIndex::new(1), NodeIndex::new(3), NodeIndex::new(2)].to_vec()) +/// ); +/// ``` +pub fn find_negative_cycle(g: G, source: G::NodeId) -> Option> +where + G: NodeCount + IntoNodeIdentifiers + IntoEdges + NodeIndexable + Visitable, + G::EdgeWeight: FloatMeasure, +{ + let ix = |i| g.to_index(i); + let mut path = Vec::::new(); + + // Step 1: initialize and relax + let (distance, predecessor) = bellman_ford_initialize_relax(g, source); + + // Step 2: Check for negative weight cycle + 'outer: for i in g.node_identifiers() { + for edge in g.edges(i) { + let j = edge.target(); + let w = *edge.weight(); + if distance[ix(i)] + w < distance[ix(j)] { + // Step 3: negative cycle found + let start = j; + let mut node = start; + let mut visited = g.visit_map(); + // Go backward in the predecessor chain + loop { + let ancestor = match predecessor[ix(node)] { + Some(predecessor_node) => predecessor_node, + None => node, // no predecessor, self cycle + }; + // We have only 2 ways to find the cycle and break the loop: + // 1. start is reached + if ancestor == start { + path.push(ancestor); + break; + } + // 2. some node was reached twice + else if visited.is_visited(&ancestor) { + // Drop any node in path that is before the first ancestor + let pos = path + .iter() + .position(|&p| p == ancestor) + .expect("we should always have a position"); + path = path[pos..path.len()].to_vec(); + + break; + } + + // None of the above, some middle path node + path.push(ancestor); + visited.visit(ancestor); + node = ancestor; + } + // We are done here + break 'outer; + } + } + } + if !path.is_empty() { + // Users will probably need to follow the path of the negative cycle + // so it should be in the reverse order than it was found by the algorithm. + path.reverse(); + Some(path) + } else { + None + } +} + +// Perform Step 1 and Step 2 of the Bellman-Ford algorithm. +#[inline(always)] +fn bellman_ford_initialize_relax( + g: G, + source: G::NodeId, +) -> (Vec, Vec>) +where + G: NodeCount + IntoNodeIdentifiers + IntoEdges + NodeIndexable, + G::EdgeWeight: FloatMeasure, +{ + // Step 1: initialize graph + let mut predecessor = vec![None; g.node_bound()]; + let mut distance = vec![<_>::infinite(); g.node_bound()]; + let ix = |i| g.to_index(i); + distance[ix(source)] = <_>::zero(); + + // Step 2: relax edges repeatedly + for _ in 1..g.node_count() { + let mut did_update = false; + for i in g.node_identifiers() { + for edge in g.edges(i) { + let j = edge.target(); + let w = *edge.weight(); + if distance[ix(i)] + w < distance[ix(j)] { + distance[ix(j)] = distance[ix(i)] + w; + predecessor[ix(j)] = Some(i); + did_update = true; + } + } + } + if !did_update { + break; + } + } + (distance, predecessor) +} diff --git a/vendor/petgraph/src/algo/coloring.rs b/vendor/petgraph/src/algo/coloring.rs new file mode 100644 index 00000000..96c1e273 --- /dev/null +++ b/vendor/petgraph/src/algo/coloring.rs @@ -0,0 +1,96 @@ +use std::collections::{BinaryHeap, HashMap, HashSet}; +use std::hash::Hash; + +use crate::scored::MaxScored; +use crate::visit::{IntoEdges, IntoNodeIdentifiers, NodeIndexable, VisitMap, Visitable}; + +/// \[Generic\] DStatur algorithm to properly color a non weighted undirected graph. +/// https://en.wikipedia.org/wiki/DSatur +/// +/// This is a heuristic. So, it does not necessarily return a minimum coloring. +/// +/// The graph must be undirected. It should not contain loops. +/// It must implement `IntoEdges`, `IntoNodeIdentifiers` and `Visitable` +/// Returns a tuple composed of a HashMap that associates to each `NodeId` its color and the number of used colors. +/// +/// Computes in **O((|V| + |E|)*log(|V|)** time +/// +/// # Example +/// ```rust +/// use petgraph::{Graph, Undirected}; +/// use petgraph::algo::dsatur_coloring; +/// +/// let mut graph: Graph<(), (), Undirected> = Graph::new_undirected(); +/// let a = graph.add_node(()); +/// let b = graph.add_node(()); +/// let c = graph.add_node(()); +/// let d = graph.add_node(()); +/// let e = graph.add_node(()); +/// let f = graph.add_node(()); +/// +/// graph.extend_with_edges(&[ +/// (a, b), +/// (b, c), +/// (c, d), +/// (d, e), +/// (e, f), +/// (f, a), +/// ]); +/// +/// // a ----- b ----- c +/// // | | +/// // | | +/// // | | +/// // f ----- e------ d +/// +/// let (coloring, nb_colors) = dsatur_coloring(&graph); +/// assert_eq!(nb_colors, 2); +/// assert_ne!(coloring[&a], coloring[&b]); +/// ``` + +pub fn dsatur_coloring(graph: G) -> (HashMap, usize) +where + G: IntoEdges + IntoNodeIdentifiers + Visitable + NodeIndexable, + G::NodeId: Eq + Hash, +{ + let ix = |v| graph.to_index(v); + let n = graph.node_bound(); + + let mut degree_map = vec![0; n]; + let mut queue = BinaryHeap::with_capacity(n); + let mut colored = HashMap::with_capacity(n); + let mut adj_color_map = vec![HashSet::new(); n]; + let mut seen = graph.visit_map(); + let mut max_color = 0; + + for node in graph.node_identifiers() { + let degree = graph.edges(node).count(); + queue.push(MaxScored((0, degree), node)); + degree_map[ix(node)] = degree; + } + + while let Some(MaxScored(_, node)) = queue.pop() { + if seen.is_visited(&node) { + continue; + } + seen.visit(node); + + let adj_color = &adj_color_map[ix(node)]; + let mut color = 0; + while adj_color.contains(&color) { + color += 1; + } + + colored.insert(node, color); + max_color = max_color.max(color); + + for nbor in graph.neighbors(node) { + if let Some(adj_color) = adj_color_map.get_mut(ix(nbor)) { + adj_color.insert(color); + queue.push(MaxScored((adj_color.len(), degree_map[ix(nbor)]), nbor)); + } + } + } + + (colored, max_color + 1) +} diff --git a/vendor/petgraph/src/algo/dijkstra.rs b/vendor/petgraph/src/algo/dijkstra.rs new file mode 100644 index 00000000..b2876b26 --- /dev/null +++ b/vendor/petgraph/src/algo/dijkstra.rs @@ -0,0 +1,122 @@ +use std::collections::hash_map::Entry::{Occupied, Vacant}; +use std::collections::{BinaryHeap, HashMap}; + +use std::hash::Hash; + +use crate::algo::Measure; +use crate::scored::MinScored; +use crate::visit::{EdgeRef, IntoEdges, VisitMap, Visitable}; + +/// \[Generic\] Dijkstra's shortest path algorithm. +/// +/// Compute the length of the shortest path from `start` to every reachable +/// node. +/// +/// The graph should be `Visitable` and implement `IntoEdges`. The function +/// `edge_cost` should return the cost for a particular edge, which is used +/// to compute path costs. Edge costs must be non-negative. +/// +/// If `goal` is not `None`, then the algorithm terminates once the `goal` node's +/// cost is calculated. +/// +/// Returns a `HashMap` that maps `NodeId` to path cost. +/// # Example +/// ```rust +/// use petgraph::Graph; +/// use petgraph::algo::dijkstra; +/// use petgraph::prelude::*; +/// use std::collections::HashMap; +/// +/// let mut graph: Graph<(), (), Directed> = Graph::new(); +/// let a = graph.add_node(()); // node with no weight +/// let b = graph.add_node(()); +/// let c = graph.add_node(()); +/// let d = graph.add_node(()); +/// let e = graph.add_node(()); +/// let f = graph.add_node(()); +/// let g = graph.add_node(()); +/// let h = graph.add_node(()); +/// // z will be in another connected component +/// let z = graph.add_node(()); +/// +/// graph.extend_with_edges(&[ +/// (a, b), +/// (b, c), +/// (c, d), +/// (d, a), +/// (e, f), +/// (b, e), +/// (f, g), +/// (g, h), +/// (h, e), +/// ]); +/// // a ----> b ----> e ----> f +/// // ^ | ^ | +/// // | v | v +/// // d <---- c h <---- g +/// +/// let expected_res: HashMap = [ +/// (a, 3), +/// (b, 0), +/// (c, 1), +/// (d, 2), +/// (e, 1), +/// (f, 2), +/// (g, 3), +/// (h, 4), +/// ].iter().cloned().collect(); +/// let res = dijkstra(&graph, b, None, |_| 1); +/// assert_eq!(res, expected_res); +/// // z is not inside res because there is not path from b to z. +/// ``` +pub fn dijkstra( + graph: G, + start: G::NodeId, + goal: Option, + mut edge_cost: F, +) -> HashMap +where + G: IntoEdges + Visitable, + G::NodeId: Eq + Hash, + F: FnMut(G::EdgeRef) -> K, + K: Measure + Copy, +{ + let mut visited = graph.visit_map(); + let mut scores = HashMap::new(); + //let mut predecessor = HashMap::new(); + let mut visit_next = BinaryHeap::new(); + let zero_score = K::default(); + scores.insert(start, zero_score); + visit_next.push(MinScored(zero_score, start)); + while let Some(MinScored(node_score, node)) = visit_next.pop() { + if visited.is_visited(&node) { + continue; + } + if goal.as_ref() == Some(&node) { + break; + } + for edge in graph.edges(node) { + let next = edge.target(); + if visited.is_visited(&next) { + continue; + } + let next_score = node_score + edge_cost(edge); + match scores.entry(next) { + Occupied(ent) => { + if next_score < *ent.get() { + *ent.into_mut() = next_score; + visit_next.push(MinScored(next_score, next)); + //predecessor.insert(next.clone(), node.clone()); + } + } + Vacant(ent) => { + ent.insert(next_score); + visit_next.push(MinScored(next_score, next)); + //predecessor.insert(next.clone(), node.clone()); + } + } + } + visited.visit(node); + } + scores +} diff --git a/vendor/petgraph/src/algo/dominators.rs b/vendor/petgraph/src/algo/dominators.rs new file mode 100644 index 00000000..9e709352 --- /dev/null +++ b/vendor/petgraph/src/algo/dominators.rs @@ -0,0 +1,333 @@ +//! Compute dominators of a control-flow graph. +//! +//! # The Dominance Relation +//! +//! In a directed graph with a root node **R**, a node **A** is said to *dominate* a +//! node **B** iff every path from **R** to **B** contains **A**. +//! +//! The node **A** is said to *strictly dominate* the node **B** iff **A** dominates +//! **B** and **A ≠ B**. +//! +//! The node **A** is said to be the *immediate dominator* of a node **B** iff it +//! strictly dominates **B** and there does not exist any node **C** where **A** +//! dominates **C** and **C** dominates **B**. + +use std::cmp::Ordering; +use std::collections::{hash_map::Iter, HashMap, HashSet}; +use std::hash::Hash; + +use crate::visit::{DfsPostOrder, GraphBase, IntoNeighbors, Visitable, Walker}; + +/// The dominance relation for some graph and root. +#[derive(Debug, Clone)] +pub struct Dominators +where + N: Copy + Eq + Hash, +{ + root: N, + dominators: HashMap, +} + +impl Dominators +where + N: Copy + Eq + Hash, +{ + /// Get the root node used to construct these dominance relations. + pub fn root(&self) -> N { + self.root + } + + /// Get the immediate dominator of the given node. + /// + /// Returns `None` for any node that is not reachable from the root, and for + /// the root itself. + pub fn immediate_dominator(&self, node: N) -> Option { + if node == self.root { + None + } else { + self.dominators.get(&node).cloned() + } + } + + /// Iterate over the given node's strict dominators. + /// + /// If the given node is not reachable from the root, then `None` is + /// returned. + pub fn strict_dominators(&self, node: N) -> Option> { + if self.dominators.contains_key(&node) { + Some(DominatorsIter { + dominators: self, + node: self.immediate_dominator(node), + }) + } else { + None + } + } + + /// Iterate over all of the given node's dominators (including the given + /// node itself). + /// + /// If the given node is not reachable from the root, then `None` is + /// returned. + pub fn dominators(&self, node: N) -> Option> { + if self.dominators.contains_key(&node) { + Some(DominatorsIter { + dominators: self, + node: Some(node), + }) + } else { + None + } + } + + /// Iterate over all nodes immediately dominated by the given node (not + /// including the given node itself). + pub fn immediately_dominated_by(&self, node: N) -> DominatedByIter { + DominatedByIter { + iter: self.dominators.iter(), + node, + } + } +} + +/// Iterator for a node's dominators. +#[derive(Debug, Clone)] +pub struct DominatorsIter<'a, N> +where + N: 'a + Copy + Eq + Hash, +{ + dominators: &'a Dominators, + node: Option, +} + +impl<'a, N> Iterator for DominatorsIter<'a, N> +where + N: 'a + Copy + Eq + Hash, +{ + type Item = N; + + fn next(&mut self) -> Option { + let next = self.node.take(); + if let Some(next) = next { + self.node = self.dominators.immediate_dominator(next); + } + next + } +} + +/// Iterator for nodes dominated by a given node. +#[derive(Debug, Clone)] +pub struct DominatedByIter<'a, N> +where + N: 'a + Copy + Eq + Hash, +{ + iter: Iter<'a, N, N>, + node: N, +} + +impl<'a, N> Iterator for DominatedByIter<'a, N> +where + N: 'a + Copy + Eq + Hash, +{ + type Item = N; + + fn next(&mut self) -> Option { + for (dominator, dominated) in self.iter.by_ref() { + // The root node dominates itself, but it should not be included in + // the results. + if dominated == &self.node && dominated != dominator { + return Some(*dominator); + } + } + None + } + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } +} + +/// The undefined dominator sentinel, for when we have not yet discovered a +/// node's dominator. +const UNDEFINED: usize = ::std::usize::MAX; + +/// This is an implementation of the engineered ["Simple, Fast Dominance +/// Algorithm"][0] discovered by Cooper et al. +/// +/// This algorithm is **O(|V|²)**, and therefore has slower theoretical running time +/// than the Lengauer-Tarjan algorithm (which is **O(|E| log |V|)**. However, +/// Cooper et al found it to be faster in practice on control flow graphs of up +/// to ~30,000 vertices. +/// +/// [0]: http://www.hipersoft.rice.edu/grads/publications/dom14.pdf +pub fn simple_fast(graph: G, root: G::NodeId) -> Dominators +where + G: IntoNeighbors + Visitable, + ::NodeId: Eq + Hash, +{ + let (post_order, predecessor_sets) = simple_fast_post_order(graph, root); + let length = post_order.len(); + debug_assert!(length > 0); + debug_assert!(post_order.last() == Some(&root)); + + // From here on out we use indices into `post_order` instead of actual + // `NodeId`s wherever possible. This greatly improves the performance of + // this implementation, but we have to pay a little bit of upfront cost to + // convert our data structures to play along first. + + // Maps a node to its index into `post_order`. + let node_to_post_order_idx: HashMap<_, _> = post_order + .iter() + .enumerate() + .map(|(idx, &node)| (node, idx)) + .collect(); + + // Maps a node's `post_order` index to its set of predecessors's indices + // into `post_order` (as a vec). + let idx_to_predecessor_vec = + predecessor_sets_to_idx_vecs(&post_order, &node_to_post_order_idx, predecessor_sets); + + let mut dominators = vec![UNDEFINED; length]; + dominators[length - 1] = length - 1; + + let mut changed = true; + while changed { + changed = false; + + // Iterate in reverse post order, skipping the root. + + for idx in (0..length - 1).rev() { + debug_assert!(post_order[idx] != root); + + // Take the intersection of every predecessor's dominator set; that + // is the current best guess at the immediate dominator for this + // node. + + let new_idom_idx = { + let mut predecessors = idx_to_predecessor_vec[idx] + .iter() + .filter(|&&p| dominators[p] != UNDEFINED); + let new_idom_idx = predecessors.next().expect( + "Because the root is initialized to dominate itself, and is the \ + first node in every path, there must exist a predecessor to this \ + node that also has a dominator", + ); + predecessors.fold(*new_idom_idx, |new_idom_idx, &predecessor_idx| { + intersect(&dominators, new_idom_idx, predecessor_idx) + }) + }; + + debug_assert!(new_idom_idx < length); + + if new_idom_idx != dominators[idx] { + dominators[idx] = new_idom_idx; + changed = true; + } + } + } + + // All done! Translate the indices back into proper `G::NodeId`s. + + debug_assert!(!dominators.iter().any(|&dom| dom == UNDEFINED)); + + Dominators { + root, + dominators: dominators + .into_iter() + .enumerate() + .map(|(idx, dom_idx)| (post_order[idx], post_order[dom_idx])) + .collect(), + } +} + +fn intersect(dominators: &[usize], mut finger1: usize, mut finger2: usize) -> usize { + loop { + match finger1.cmp(&finger2) { + Ordering::Less => finger1 = dominators[finger1], + Ordering::Greater => finger2 = dominators[finger2], + Ordering::Equal => return finger1, + } + } +} + +fn predecessor_sets_to_idx_vecs( + post_order: &[N], + node_to_post_order_idx: &HashMap, + mut predecessor_sets: HashMap>, +) -> Vec> +where + N: Copy + Eq + Hash, +{ + post_order + .iter() + .map(|node| { + predecessor_sets + .remove(node) + .map(|predecessors| { + predecessors + .into_iter() + .map(|p| *node_to_post_order_idx.get(&p).unwrap()) + .collect() + }) + .unwrap_or_default() + }) + .collect() +} + +type PredecessorSets = HashMap>; + +fn simple_fast_post_order( + graph: G, + root: G::NodeId, +) -> (Vec, PredecessorSets) +where + G: IntoNeighbors + Visitable, + ::NodeId: Eq + Hash, +{ + let mut post_order = vec![]; + let mut predecessor_sets = HashMap::new(); + + for node in DfsPostOrder::new(graph, root).iter(graph) { + post_order.push(node); + + for successor in graph.neighbors(node) { + predecessor_sets + .entry(successor) + .or_insert_with(HashSet::new) + .insert(node); + } + } + + (post_order, predecessor_sets) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_iter_dominators() { + let doms: Dominators = Dominators { + root: 0, + dominators: [(2, 1), (1, 0), (0, 0)].iter().cloned().collect(), + }; + + let all_doms: Vec<_> = doms.dominators(2).unwrap().collect(); + assert_eq!(vec![2, 1, 0], all_doms); + + assert_eq!(None::<()>, doms.dominators(99).map(|_| unreachable!())); + + let strict_doms: Vec<_> = doms.strict_dominators(2).unwrap().collect(); + assert_eq!(vec![1, 0], strict_doms); + + assert_eq!( + None::<()>, + doms.strict_dominators(99).map(|_| unreachable!()) + ); + + let dom_by: Vec<_> = doms.immediately_dominated_by(1).collect(); + assert_eq!(vec![2], dom_by); + assert_eq!(None, doms.immediately_dominated_by(99).next()); + assert_eq!(1, doms.immediately_dominated_by(0).count()); + } +} diff --git a/vendor/petgraph/src/algo/feedback_arc_set.rs b/vendor/petgraph/src/algo/feedback_arc_set.rs new file mode 100644 index 00000000..9b9c95d4 --- /dev/null +++ b/vendor/petgraph/src/algo/feedback_arc_set.rs @@ -0,0 +1,449 @@ +use std::{ + collections::{HashMap, VecDeque}, + ops::{Index, IndexMut}, +}; + +use crate::{ + graph::{GraphIndex, NodeIndex}, + visit::{EdgeRef, GraphProp, IntoEdgeReferences}, + Directed, +}; + +use self::linked_list::{LinkedList, LinkedListEntry}; + +/// \[Generic\] Finds a [feedback arc set]: a set of edges in the given directed graph, which when +/// removed, make the graph acyclic. +/// +/// Uses a [greedy heuristic algorithm] to select a small number of edges, but does not necessarily +/// find the minimum feedback arc set. Time complexity is roughly **O(|E|)** for an input graph with +/// edges **E**. +/// +/// Does not consider edge/node weights when selecting edges for the feedback arc set. +/// +/// Loops (edges to and from the same node) are always included in the returned set. +/// +/// # Example +/// +/// ``` +/// # #[cfg(feature = "stable_graph")] { +/// use petgraph::{ +/// algo::{greedy_feedback_arc_set, is_cyclic_directed}, +/// graph::EdgeIndex, +/// stable_graph::StableGraph, +/// visit::EdgeRef, +/// }; +/// +/// let mut g: StableGraph<(), ()> = StableGraph::from_edges(&[ +/// (0, 1), +/// (1, 2), +/// (2, 3), +/// (3, 4), +/// (4, 5), +/// (5, 0), +/// (4, 1), +/// (1, 3), +/// ]); +/// +/// assert!(is_cyclic_directed(&g)); +/// +/// let fas: Vec = greedy_feedback_arc_set(&g).map(|e| e.id()).collect(); +/// +/// // Remove edges in feedback arc set from original graph +/// for edge_id in fas { +/// g.remove_edge(edge_id); +/// } +/// +/// assert!(!is_cyclic_directed(&g)); +/// # } +/// ``` +/// +/// [feedback arc set]: https://en.wikipedia.org/wiki/Feedback_arc_set +/// [greedy heuristic algorithm]: https://doi.org/10.1016/0020-0190(93)90079-O +pub fn greedy_feedback_arc_set(g: G) -> impl Iterator +where + G: IntoEdgeReferences + GraphProp, + G::NodeId: GraphIndex, + G: crate::visit::NodeCount, +{ + let node_seq = good_node_sequence(g.edge_references().map(|e| { + ( + NodeIndex::new(e.source().index()), + NodeIndex::new(e.target().index()), + ) + })); + + g.edge_references() + .filter(move |e| node_seq[&e.source().index()] >= node_seq[&e.target().index()]) +} + +fn good_node_sequence( + edge_refs: impl Iterator, NodeIndex)>, +) -> HashMap { + let mut nodes = FasNodeContainer { nodes: Vec::new() }; + let mut buckets = Buckets { + sinks_or_isolated: NodeLinkedList::new(), + sources: NodeLinkedList::new(), + bidirectional_pve_dd: Vec::new(), + bidirectional_nve_dd: Vec::new(), + }; + // Lookup of node indices from input graph to indices into `nodes` + let mut graph_ix_lookup = HashMap::new(); + + // Build node entries + for (from_g_ix, to_g_ix) in edge_refs { + let mut fas_node_entry = |g_ix: NodeIndex| -> FasNodeIndex { + match graph_ix_lookup.get(&g_ix) { + Some(fas_ix) => *fas_ix, + None => { + let fas_ix = FasNodeIndex(nodes.nodes.len()); + + nodes.nodes.push(LinkedListEntry::new(FasNode { + graph_ix: g_ix, + out_edges: Vec::new(), + in_edges: Vec::new(), + out_degree: 0, + in_degree: 0, + })); + + graph_ix_lookup.insert(g_ix, fas_ix); + + fas_ix + } + } + }; + + let from_fas_ix = fas_node_entry(from_g_ix); + let to_fas_ix = fas_node_entry(to_g_ix); + + nodes[from_fas_ix].data().out_edges.push(to_fas_ix); + nodes[to_fas_ix].data().in_edges.push(from_fas_ix); + } + + // Set initial in/out-degrees + for entry in nodes.nodes.iter_mut() { + let node = entry.data(); + node.out_degree = node.out_edges.len(); + node.in_degree = node.in_edges.len(); + } + + // Add nodes to initial lists + for i in 0..nodes.nodes.len() { + let fas_ix = FasNodeIndex(i); + buckets + .suitable_bucket(fas_ix, &mut nodes) + .push_front(fas_ix, &mut nodes); + } + + let mut s_1 = VecDeque::new(); + let mut s_2 = VecDeque::new(); + + loop { + let mut some_moved = false; + + while let Some(sink_fas_ix) = buckets.sinks_or_isolated.pop(&mut nodes) { + some_moved = true; + buckets.update_neighbour_node_buckets(sink_fas_ix, &mut nodes); + s_2.push_front(nodes[sink_fas_ix].data().graph_ix); + } + + while let Some(source_fas_ix) = buckets.sources.pop(&mut nodes) { + some_moved = true; + buckets.update_neighbour_node_buckets(source_fas_ix, &mut nodes); + s_1.push_back(nodes[source_fas_ix].data().graph_ix); + } + + if let Some(list) = buckets + .bidirectional_pve_dd + .iter_mut() + .rev() + .chain(buckets.bidirectional_nve_dd.iter_mut()) + .find(|b| b.start.is_some()) + { + let highest_dd_fas_ix = list.pop(&mut nodes).unwrap(); + some_moved = true; + buckets.update_neighbour_node_buckets(highest_dd_fas_ix, &mut nodes); + s_1.push_back(nodes[highest_dd_fas_ix].data().graph_ix); + + Buckets::trim_bucket_list(&mut buckets.bidirectional_pve_dd); + Buckets::trim_bucket_list(&mut buckets.bidirectional_nve_dd); + } + + if !some_moved { + break; + } + } + + s_1.into_iter() + .chain(s_2) + .enumerate() + .map(|(seq_order, node_index)| (node_index.index(), seq_order)) + .collect() +} + +type NodeLinkedList = LinkedList; + +#[derive(Debug)] +struct FasNodeContainer { + nodes: Vec>, +} + +impl Index for FasNodeContainer { + type Output = LinkedListEntry; + + fn index(&self, index: FasNodeIndex) -> &Self::Output { + &self.nodes[index.0] + } +} + +impl IndexMut for FasNodeContainer { + fn index_mut(&mut self, index: FasNodeIndex) -> &mut Self::Output { + &mut self.nodes[index.0] + } +} + +#[derive(Debug)] +struct Buckets { + sinks_or_isolated: NodeLinkedList, + sources: NodeLinkedList, + /// Bidirectional nodes with positive-or-0 delta degree + bidirectional_pve_dd: Vec, + /// Bidirectional nodes with negative delta degree (index 0 is -1 dd, 1 is -2 etc) + bidirectional_nve_dd: Vec, +} + +#[derive(Clone, Copy, PartialEq, Debug)] +struct FasNodeIndex(usize); + +/// Represents a node from the input graph, tracking its current delta degree +#[derive(Debug)] +struct FasNode { + /// Node index in input graph. + graph_ix: NodeIndex, + + /// All outward edges from this node (not removed during processing) + out_edges: Vec, + + /// All inward edges from this node (not removed during processing) + in_edges: Vec, + + /// Current out-degree of this node (decremented during processing as connected nodes are + /// removed) + out_degree: usize, + + /// Current in-degree of this node (decremented during processing as connected nodes are + /// removed) + in_degree: usize, +} + +impl Buckets { + fn suitable_bucket( + &mut self, + ix: FasNodeIndex, + nodes: &mut FasNodeContainer, + ) -> &mut NodeLinkedList { + let node = nodes[ix].data(); + + if node.out_degree == 0 { + &mut self.sinks_or_isolated + } else if node.in_degree == 0 { + &mut self.sources + } else { + let delta_degree = node.out_degree as isize - node.in_degree as isize; + + if delta_degree >= 0 { + let bucket_ix = delta_degree as usize; + + if self.bidirectional_pve_dd.len() <= bucket_ix { + self.bidirectional_pve_dd + .resize_with(bucket_ix + 1, NodeLinkedList::new); + } + + &mut self.bidirectional_pve_dd[bucket_ix] + } else { + let bucket_ix = (-delta_degree - 1) as usize; + + if self.bidirectional_nve_dd.len() <= bucket_ix { + self.bidirectional_nve_dd + .resize_with(bucket_ix + 1, NodeLinkedList::new); + } + + &mut self.bidirectional_nve_dd[bucket_ix] + } + } + } + + fn update_neighbour_node_buckets(&mut self, ix: FasNodeIndex, nodes: &mut FasNodeContainer) { + for i in 0..nodes[ix].data().out_edges.len() { + let out_ix = nodes[ix].data().out_edges[i]; + + if out_ix == ix { + continue; + } + + // Ignore nodes which have already been moved to the good sequence + if !nodes[out_ix].is_in_list() { + continue; + } + + self.suitable_bucket(out_ix, nodes).remove(out_ix, nodes); + + // Other node has lost an in-edge; reduce in-degree by 1 + nodes[out_ix].data().in_degree -= 1; + + self.suitable_bucket(out_ix, nodes) + .push_front(out_ix, nodes); + } + + for i in 0..nodes[ix].data().in_edges.len() { + let in_ix = nodes[ix].data().in_edges[i]; + + if in_ix == ix { + continue; + } + + // Ignore nodes which have already been moved to the good sequence + if !nodes[in_ix].is_in_list() { + continue; + } + + self.suitable_bucket(in_ix, nodes).remove(in_ix, nodes); + + // Other node has lost an out-edge; reduce out-degree by 1 + nodes[in_ix].data().out_degree -= 1; + + self.suitable_bucket(in_ix, nodes).push_front(in_ix, nodes); + } + } + + fn trim_bucket_list(list: &mut Vec) { + let trunc_len = if let Some(highest_populated_index) = + (0..list.len()).rev().find(|i| list[*i].start.is_some()) + { + highest_populated_index + 1 + } else { + 0 + }; + + list.truncate(trunc_len); + } +} + +mod linked_list { + use std::{marker::PhantomData, ops::IndexMut}; + + #[derive(PartialEq, Debug)] + pub struct LinkedList { + pub start: Option, + marker: PhantomData<(Data, Container)>, + } + + #[derive(Debug)] + pub struct LinkedListEntry { + pos: Option>, + data: Data, + } + + #[derive(Debug)] + struct LinkedListPosition { + prev: Option, + next: Option, + } + + impl LinkedListEntry { + pub fn new(data: Data) -> Self { + LinkedListEntry { pos: None, data } + } + + pub fn data(&mut self) -> &mut Data { + &mut self.data + } + + pub fn is_in_list(&mut self) -> bool { + self.pos.is_some() + } + + fn pos_mut(&mut self) -> &mut LinkedListPosition { + self.pos + .as_mut() + .expect("expected linked list entry to have populated position") + } + } + + impl LinkedList + where + Container: IndexMut>, + Ix: PartialEq + Copy, + { + pub fn new() -> Self { + LinkedList { + start: None, + marker: PhantomData, + } + } + + pub fn push_front(&mut self, push_ix: Ix, container: &mut Container) { + if let Some(start_ix) = self.start { + let entry = &mut container[start_ix]; + entry.pos_mut().prev = Some(push_ix); + } + + let push_entry = &mut container[push_ix]; + push_entry.pos = Some(LinkedListPosition { + next: self.start, + prev: None, + }); + + self.start = Some(push_ix); + } + + pub fn pop(&mut self, container: &mut Container) -> Option { + if let Some(remove_ix) = self.start { + self.remove(remove_ix, container); + Some(remove_ix) + } else { + None + } + } + + /// `remove_ix` **must** be a member of the list headed by `self` + pub fn remove(&mut self, remove_ix: Ix, container: &mut Container) { + debug_assert!( + self.to_vec(container).contains(&remove_ix), + "node to remove should be member of current linked list" + ); + + let remove_entry = &mut container[remove_ix]; + let ll_entry = remove_entry.pos.take().unwrap(); + + if let Some(prev_ix) = ll_entry.prev { + let prev_node = &mut container[prev_ix]; + prev_node.pos_mut().next = ll_entry.next; + } + + if let Some(next_ix) = ll_entry.next { + let next_node = &mut container[next_ix]; + next_node.pos_mut().prev = ll_entry.prev; + } + + // If the removed node was head of the list + if self.start == Some(remove_ix) { + self.start = ll_entry.next; + } + } + + /// For debug purposes + fn to_vec(&self, container: &mut Container) -> Vec { + let mut ixs = Vec::new(); + + let mut node_ix = self.start; + + while let Some(n_ix) = node_ix { + ixs.push(n_ix); + + node_ix = container[n_ix].pos_mut().next; + } + + ixs + } + } +} diff --git a/vendor/petgraph/src/algo/floyd_warshall.rs b/vendor/petgraph/src/algo/floyd_warshall.rs new file mode 100644 index 00000000..2ac94d50 --- /dev/null +++ b/vendor/petgraph/src/algo/floyd_warshall.rs @@ -0,0 +1,143 @@ +use std::collections::HashMap; + +use std::hash::Hash; + +use crate::algo::{BoundedMeasure, NegativeCycle}; +use crate::visit::{ + EdgeRef, GraphProp, IntoEdgeReferences, IntoNodeIdentifiers, NodeCompactIndexable, +}; + +#[allow(clippy::type_complexity, clippy::needless_range_loop)] +/// \[Generic\] [Floyd–Warshall algorithm](https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm) is an algorithm for all pairs shortest path problem +/// +/// Compute shortest paths in a weighted graph with positive or negative edge weights (but with no negative cycles) +/// +/// # Arguments +/// * `graph`: graph with no negative cycle +/// * `edge_cost`: closure that returns cost of a particular edge +/// +/// # Returns +/// * `Ok`: (if graph contains no negative cycle) a hashmap containing all pairs shortest paths +/// * `Err`: if graph contains negative cycle. +/// +/// # Examples +/// ```rust +/// use petgraph::{prelude::*, Graph, Directed}; +/// use petgraph::algo::floyd_warshall; +/// use std::collections::HashMap; +/// +/// let mut graph: Graph<(), (), Directed> = Graph::new(); +/// let a = graph.add_node(()); +/// let b = graph.add_node(()); +/// let c = graph.add_node(()); +/// let d = graph.add_node(()); +/// +/// graph.extend_with_edges(&[ +/// (a, b), +/// (a, c), +/// (a, d), +/// (b, c), +/// (b, d), +/// (c, d) +/// ]); +/// +/// let weight_map: HashMap<(NodeIndex, NodeIndex), i32> = [ +/// ((a, a), 0), ((a, b), 1), ((a, c), 4), ((a, d), 10), +/// ((b, b), 0), ((b, c), 2), ((b, d), 2), +/// ((c, c), 0), ((c, d), 2) +/// ].iter().cloned().collect(); +/// // ----- b -------- +/// // | ^ | 2 +/// // | 1 | 4 v +/// // 2 | a ------> c +/// // | 10 | | 2 +/// // | v v +/// // ---> d <------- +/// +/// let inf = std::i32::MAX; +/// let expected_res: HashMap<(NodeIndex, NodeIndex), i32> = [ +/// ((a, a), 0), ((a, b), 1), ((a, c), 3), ((a, d), 3), +/// ((b, a), inf), ((b, b), 0), ((b, c), 2), ((b, d), 2), +/// ((c, a), inf), ((c, b), inf), ((c, c), 0), ((c, d), 2), +/// ((d, a), inf), ((d, b), inf), ((d, c), inf), ((d, d), 0), +/// ].iter().cloned().collect(); +/// +/// +/// let res = floyd_warshall(&graph, |edge| { +/// if let Some(weight) = weight_map.get(&(edge.source(), edge.target())) { +/// *weight +/// } else { +/// inf +/// } +/// }).unwrap(); +/// +/// let nodes = [a, b, c, d]; +/// for node1 in &nodes { +/// for node2 in &nodes { +/// assert_eq!(res.get(&(*node1, *node2)).unwrap(), expected_res.get(&(*node1, *node2)).unwrap()); +/// } +/// } +/// ``` +pub fn floyd_warshall( + graph: G, + mut edge_cost: F, +) -> Result, NegativeCycle> +where + G: NodeCompactIndexable + IntoEdgeReferences + IntoNodeIdentifiers + GraphProp, + G::NodeId: Eq + Hash, + F: FnMut(G::EdgeRef) -> K, + K: BoundedMeasure + Copy, +{ + let num_of_nodes = graph.node_count(); + + // |V|x|V| matrix + let mut dist = vec![vec![K::max(); num_of_nodes]; num_of_nodes]; + + // init distances of paths with no intermediate nodes + for edge in graph.edge_references() { + let i = graph.to_index(edge.source()); + let j = graph.to_index(edge.target()); + let cost = edge_cost(edge); + + if dist[i][j] > cost { + dist[i][j] = cost; + if !graph.is_directed() { + dist[j][i] = cost; + } + } + } + + // distance of each node to itself is 0(default value) + for node in graph.node_identifiers() { + dist[graph.to_index(node)][graph.to_index(node)] = K::default(); + } + + for k in 0..num_of_nodes { + for i in 0..num_of_nodes { + for j in 0..num_of_nodes { + let (result, overflow) = dist[i][k].overflowing_add(dist[k][j]); + if !overflow && dist[i][j] > result { + dist[i][j] = result; + } + } + } + } + + // value less than 0(default value) indicates a negative cycle + for i in 0..num_of_nodes { + if dist[i][i] < K::default() { + return Err(NegativeCycle(())); + } + } + + let mut distance_map: HashMap<(G::NodeId, G::NodeId), K> = + HashMap::with_capacity(num_of_nodes * num_of_nodes); + + for i in 0..num_of_nodes { + for j in 0..num_of_nodes { + distance_map.insert((graph.from_index(i), graph.from_index(j)), dist[i][j]); + } + } + + Ok(distance_map) +} diff --git a/vendor/petgraph/src/algo/ford_fulkerson.rs b/vendor/petgraph/src/algo/ford_fulkerson.rs new file mode 100644 index 00000000..3b2127f3 --- /dev/null +++ b/vendor/petgraph/src/algo/ford_fulkerson.rs @@ -0,0 +1,196 @@ +use std::{collections::VecDeque, ops::Sub}; + +use crate::{ + data::DataMap, + visit::{ + EdgeCount, EdgeIndexable, IntoEdges, IntoEdgesDirected, NodeCount, NodeIndexable, VisitMap, + Visitable, + }, +}; + +use super::{EdgeRef, PositiveMeasure}; +use crate::prelude::Direction; + +fn residual_capacity( + network: N, + edge: N::EdgeRef, + vertex: N::NodeId, + flow: N::EdgeWeight, +) -> N::EdgeWeight +where + N: NodeIndexable + IntoEdges, + N::EdgeWeight: Sub + PositiveMeasure, +{ + if vertex == edge.source() { + // backward edge + flow + } else if vertex == edge.target() { + // forward edge + return *edge.weight() - flow; + } else { + let end_point = NodeIndexable::to_index(&network, vertex); + panic!("Illegal endpoint {}", end_point); + } +} + +/// Gets the other endpoint of graph edge, if any, otherwise panics. +fn other_endpoint(network: N, edge: N::EdgeRef, vertex: N::NodeId) -> N::NodeId +where + N: NodeIndexable + IntoEdges, +{ + if vertex == edge.source() { + edge.target() + } else if vertex == edge.target() { + edge.source() + } else { + let end_point = NodeIndexable::to_index(&network, vertex); + panic!("Illegal endpoint {}", end_point); + } +} + +/// Tells whether there is an augmented path in the graph +fn has_augmented_path( + network: N, + source: N::NodeId, + destination: N::NodeId, + edge_to: &mut [Option], + flows: &[N::EdgeWeight], +) -> bool +where + N: NodeCount + IntoEdgesDirected + NodeIndexable + EdgeIndexable + Visitable, + N::EdgeWeight: Sub + PositiveMeasure, +{ + let mut visited = network.visit_map(); + let mut queue = VecDeque::new(); + visited.visit(source); + queue.push_back(source); + + while let Some(vertex) = queue.pop_front() { + let out_edges = network.edges_directed(vertex, Direction::Outgoing); + let in_edges = network.edges_directed(vertex, Direction::Incoming); + for edge in out_edges.chain(in_edges) { + let next = other_endpoint(&network, edge, vertex); + let edge_index: usize = EdgeIndexable::to_index(&network, edge.id()); + let residual_cap = residual_capacity(&network, edge, next, flows[edge_index]); + if !visited.is_visited(&next) && (residual_cap > N::EdgeWeight::zero()) { + visited.visit(next); + edge_to[NodeIndexable::to_index(&network, next)] = Some(edge); + if destination == next { + return true; + } + queue.push_back(next); + } + } + } + false +} + +fn adjust_residual_flow( + network: N, + edge: N::EdgeRef, + vertex: N::NodeId, + flow: N::EdgeWeight, + delta: N::EdgeWeight, +) -> N::EdgeWeight +where + N: NodeIndexable + IntoEdges, + N::EdgeWeight: Sub + PositiveMeasure, +{ + if vertex == edge.source() { + // backward edge + flow - delta + } else if vertex == edge.target() { + // forward edge + flow + delta + } else { + let end_point = NodeIndexable::to_index(&network, vertex); + panic!("Illegal endpoint {}", end_point); + } +} + +/// \[Generic\] Ford-Fulkerson algorithm. +/// +/// Computes the [maximum flow][ff] of a weighted directed graph. +/// +/// If it terminates, it returns the maximum flow and also the computed edge flows. +/// +/// [ff]: https://en.wikipedia.org/wiki/Ford%E2%80%93Fulkerson_algorithm +/// +/// # Example +/// ```rust +/// use petgraph::Graph; +/// use petgraph::algo::ford_fulkerson; +/// // Example from CLRS book +/// let mut graph = Graph::::new(); +/// let source = graph.add_node(0); +/// let _ = graph.add_node(1); +/// let _ = graph.add_node(2); +/// let _ = graph.add_node(3); +/// let _ = graph.add_node(4); +/// let destination = graph.add_node(5); +/// graph.extend_with_edges(&[ +/// (0, 1, 16), +/// (0, 2, 13), +/// (1, 2, 10), +/// (1, 3, 12), +/// (2, 1, 4), +/// (2, 4, 14), +/// (3, 2, 9), +/// (3, 5, 20), +/// (4, 3, 7), +/// (4, 5, 4), +/// ]); +/// let (max_flow, _) = ford_fulkerson(&graph, source, destination); +/// assert_eq!(23, max_flow); +/// ``` +pub fn ford_fulkerson( + network: N, + source: N::NodeId, + destination: N::NodeId, +) -> (N::EdgeWeight, Vec) +where + N: NodeCount + + EdgeCount + + IntoEdgesDirected + + EdgeIndexable + + NodeIndexable + + DataMap + + Visitable, + N::EdgeWeight: Sub + PositiveMeasure, +{ + let mut edge_to = vec![None; network.node_count()]; + let mut flows = vec![N::EdgeWeight::zero(); network.edge_count()]; + let mut max_flow = N::EdgeWeight::zero(); + while has_augmented_path(&network, source, destination, &mut edge_to, &flows) { + let mut path_flow = N::EdgeWeight::max(); + + // Find the bottleneck capacity of the path + let mut vertex = destination; + let mut vertex_index = NodeIndexable::to_index(&network, vertex); + while let Some(edge) = edge_to[vertex_index] { + let edge_index = EdgeIndexable::to_index(&network, edge.id()); + let residual_capacity = residual_capacity(&network, edge, vertex, flows[edge_index]); + // Minimum between the current path flow and the residual capacity. + path_flow = if path_flow > residual_capacity { + residual_capacity + } else { + path_flow + }; + vertex = other_endpoint(&network, edge, vertex); + vertex_index = NodeIndexable::to_index(&network, vertex); + } + + // Update the flow of each edge along the path + let mut vertex = destination; + let mut vertex_index = NodeIndexable::to_index(&network, vertex); + while let Some(edge) = edge_to[vertex_index] { + let edge_index = EdgeIndexable::to_index(&network, edge.id()); + flows[edge_index] = + adjust_residual_flow(&network, edge, vertex, flows[edge_index], path_flow); + vertex = other_endpoint(&network, edge, vertex); + vertex_index = NodeIndexable::to_index(&network, vertex); + } + max_flow = max_flow + path_flow; + } + (max_flow, flows) +} diff --git a/vendor/petgraph/src/algo/isomorphism.rs b/vendor/petgraph/src/algo/isomorphism.rs new file mode 100644 index 00000000..76ca2c99 --- /dev/null +++ b/vendor/petgraph/src/algo/isomorphism.rs @@ -0,0 +1,994 @@ +use std::convert::TryFrom; + +use crate::data::DataMap; +use crate::visit::EdgeCount; +use crate::visit::EdgeRef; +use crate::visit::GetAdjacencyMatrix; +use crate::visit::GraphBase; +use crate::visit::GraphProp; +use crate::visit::IntoEdgesDirected; +use crate::visit::IntoNeighborsDirected; +use crate::visit::NodeCompactIndexable; +use crate::{Incoming, Outgoing}; + +use self::semantic::EdgeMatcher; +use self::semantic::NoSemanticMatch; +use self::semantic::NodeMatcher; +use self::state::Vf2State; + +mod state { + use super::*; + + #[derive(Debug)] + // TODO: make mapping generic over the index type of the other graph. + pub struct Vf2State<'a, G: GetAdjacencyMatrix> { + /// A reference to the graph this state was built from. + pub graph: &'a G, + /// The current mapping M(s) of nodes from G0 → G1 and G1 → G0, + /// `usize::MAX` for no mapping. + pub mapping: Vec, + /// out[i] is non-zero if i is in either M_0(s) or Tout_0(s) + /// These are all the next vertices that are not mapped yet, but + /// have an outgoing edge from the mapping. + out: Vec, + /// ins[i] is non-zero if i is in either M_0(s) or Tin_0(s) + /// These are all the incoming vertices, those not mapped yet, but + /// have an edge from them into the mapping. + /// Unused if graph is undirected -- it's identical with out in that case. + ins: Vec, + pub out_size: usize, + pub ins_size: usize, + pub adjacency_matrix: G::AdjMatrix, + generation: usize, + } + + impl<'a, G> Vf2State<'a, G> + where + G: GetAdjacencyMatrix + GraphProp + NodeCompactIndexable + IntoNeighborsDirected, + { + pub fn new(g: &'a G) -> Self { + let c0 = g.node_count(); + Vf2State { + graph: g, + mapping: vec![std::usize::MAX; c0], + out: vec![0; c0], + ins: vec![0; c0 * (g.is_directed() as usize)], + out_size: 0, + ins_size: 0, + adjacency_matrix: g.adjacency_matrix(), + generation: 0, + } + } + + /// Return **true** if we have a complete mapping + pub fn is_complete(&self) -> bool { + self.generation == self.mapping.len() + } + + /// Add mapping **from** <-> **to** to the state. + pub fn push_mapping(&mut self, from: G::NodeId, to: usize) { + self.generation += 1; + self.mapping[self.graph.to_index(from)] = to; + // update T0 & T1 ins/outs + // T0out: Node in G0 not in M0 but successor of a node in M0. + // st.out[0]: Node either in M0 or successor of M0 + for ix in self.graph.neighbors_directed(from, Outgoing) { + if self.out[self.graph.to_index(ix)] == 0 { + self.out[self.graph.to_index(ix)] = self.generation; + self.out_size += 1; + } + } + if self.graph.is_directed() { + for ix in self.graph.neighbors_directed(from, Incoming) { + if self.ins[self.graph.to_index(ix)] == 0 { + self.ins[self.graph.to_index(ix)] = self.generation; + self.ins_size += 1; + } + } + } + } + + /// Restore the state to before the last added mapping + pub fn pop_mapping(&mut self, from: G::NodeId) { + // undo (n, m) mapping + self.mapping[self.graph.to_index(from)] = std::usize::MAX; + + // unmark in ins and outs + for ix in self.graph.neighbors_directed(from, Outgoing) { + if self.out[self.graph.to_index(ix)] == self.generation { + self.out[self.graph.to_index(ix)] = 0; + self.out_size -= 1; + } + } + if self.graph.is_directed() { + for ix in self.graph.neighbors_directed(from, Incoming) { + if self.ins[self.graph.to_index(ix)] == self.generation { + self.ins[self.graph.to_index(ix)] = 0; + self.ins_size -= 1; + } + } + } + + self.generation -= 1; + } + + /// Find the next (least) node in the Tout set. + pub fn next_out_index(&self, from_index: usize) -> Option { + self.out[from_index..] + .iter() + .enumerate() + .find(move |&(index, &elt)| { + elt > 0 && self.mapping[from_index + index] == std::usize::MAX + }) + .map(|(index, _)| index) + } + + /// Find the next (least) node in the Tin set. + pub fn next_in_index(&self, from_index: usize) -> Option { + if !self.graph.is_directed() { + return None; + } + self.ins[from_index..] + .iter() + .enumerate() + .find(move |&(index, &elt)| { + elt > 0 && self.mapping[from_index + index] == std::usize::MAX + }) + .map(|(index, _)| index) + } + + /// Find the next (least) node in the N - M set. + pub fn next_rest_index(&self, from_index: usize) -> Option { + self.mapping[from_index..] + .iter() + .enumerate() + .find(|&(_, &elt)| elt == std::usize::MAX) + .map(|(index, _)| index) + } + } +} + +mod semantic { + use super::*; + + pub struct NoSemanticMatch; + + pub trait NodeMatcher { + fn enabled() -> bool; + fn eq(&mut self, _g0: &G0, _g1: &G1, _n0: G0::NodeId, _n1: G1::NodeId) -> bool; + } + + impl NodeMatcher for NoSemanticMatch { + #[inline] + fn enabled() -> bool { + false + } + #[inline] + fn eq(&mut self, _g0: &G0, _g1: &G1, _n0: G0::NodeId, _n1: G1::NodeId) -> bool { + true + } + } + + impl NodeMatcher for F + where + G0: GraphBase + DataMap, + G1: GraphBase + DataMap, + F: FnMut(&G0::NodeWeight, &G1::NodeWeight) -> bool, + { + #[inline] + fn enabled() -> bool { + true + } + #[inline] + fn eq(&mut self, g0: &G0, g1: &G1, n0: G0::NodeId, n1: G1::NodeId) -> bool { + if let (Some(x), Some(y)) = (g0.node_weight(n0), g1.node_weight(n1)) { + self(x, y) + } else { + false + } + } + } + + pub trait EdgeMatcher { + fn enabled() -> bool; + fn eq( + &mut self, + _g0: &G0, + _g1: &G1, + e0: (G0::NodeId, G0::NodeId), + e1: (G1::NodeId, G1::NodeId), + ) -> bool; + } + + impl EdgeMatcher for NoSemanticMatch { + #[inline] + fn enabled() -> bool { + false + } + #[inline] + fn eq( + &mut self, + _g0: &G0, + _g1: &G1, + _e0: (G0::NodeId, G0::NodeId), + _e1: (G1::NodeId, G1::NodeId), + ) -> bool { + true + } + } + + impl EdgeMatcher for F + where + G0: GraphBase + DataMap + IntoEdgesDirected, + G1: GraphBase + DataMap + IntoEdgesDirected, + F: FnMut(&G0::EdgeWeight, &G1::EdgeWeight) -> bool, + { + #[inline] + fn enabled() -> bool { + true + } + #[inline] + fn eq( + &mut self, + g0: &G0, + g1: &G1, + e0: (G0::NodeId, G0::NodeId), + e1: (G1::NodeId, G1::NodeId), + ) -> bool { + let w0 = g0 + .edges_directed(e0.0, Outgoing) + .find(|edge| edge.target() == e0.1) + .and_then(|edge| g0.edge_weight(edge.id())); + let w1 = g1 + .edges_directed(e1.0, Outgoing) + .find(|edge| edge.target() == e1.1) + .and_then(|edge| g1.edge_weight(edge.id())); + if let (Some(x), Some(y)) = (w0, w1) { + self(x, y) + } else { + false + } + } + } +} + +mod matching { + use super::*; + + #[derive(Copy, Clone, PartialEq, Debug)] + enum OpenList { + Out, + In, + Other, + } + + #[derive(Clone, PartialEq, Debug)] + enum Frame + where + G0: GraphBase, + G1: GraphBase, + { + Outer, + Inner { + nodes: (G0::NodeId, G1::NodeId), + open_list: OpenList, + }, + Unwind { + nodes: (G0::NodeId, G1::NodeId), + open_list: OpenList, + }, + } + + fn is_feasible( + st: &mut (Vf2State<'_, G0>, Vf2State<'_, G1>), + nodes: (G0::NodeId, G1::NodeId), + node_match: &mut NM, + edge_match: &mut EM, + ) -> bool + where + G0: GetAdjacencyMatrix + GraphProp + NodeCompactIndexable + IntoNeighborsDirected, + G1: GetAdjacencyMatrix + GraphProp + NodeCompactIndexable + IntoNeighborsDirected, + NM: NodeMatcher, + EM: EdgeMatcher, + { + macro_rules! field { + ($x:ident, 0) => { + $x.0 + }; + ($x:ident, 1) => { + $x.1 + }; + ($x:ident, 1 - 0) => { + $x.1 + }; + ($x:ident, 1 - 1) => { + $x.0 + }; + } + + macro_rules! r_succ { + ($j:tt) => {{ + let mut succ_count = 0; + for n_neigh in field!(st, $j) + .graph + .neighbors_directed(field!(nodes, $j), Outgoing) + { + succ_count += 1; + // handle the self loop case; it's not in the mapping (yet) + let m_neigh = if field!(nodes, $j) != n_neigh { + field!(st, $j).mapping[field!(st, $j).graph.to_index(n_neigh)] + } else { + field!(st, 1 - $j).graph.to_index(field!(nodes, 1 - $j)) + }; + if m_neigh == std::usize::MAX { + continue; + } + let has_edge = field!(st, 1 - $j).graph.is_adjacent( + &field!(st, 1 - $j).adjacency_matrix, + field!(nodes, 1 - $j), + field!(st, 1 - $j).graph.from_index(m_neigh), + ); + if !has_edge { + return false; + } + } + succ_count + }}; + } + + macro_rules! r_pred { + ($j:tt) => {{ + let mut pred_count = 0; + for n_neigh in field!(st, $j) + .graph + .neighbors_directed(field!(nodes, $j), Incoming) + { + pred_count += 1; + // the self loop case is handled in outgoing + let m_neigh = field!(st, $j).mapping[field!(st, $j).graph.to_index(n_neigh)]; + if m_neigh == std::usize::MAX { + continue; + } + let has_edge = field!(st, 1 - $j).graph.is_adjacent( + &field!(st, 1 - $j).adjacency_matrix, + field!(st, 1 - $j).graph.from_index(m_neigh), + field!(nodes, 1 - $j), + ); + if !has_edge { + return false; + } + } + pred_count + }}; + } + + // Check syntactic feasibility of mapping by ensuring adjacencies + // of nx map to adjacencies of mx. + // + // nx == map to => mx + // + // R_succ + // + // Check that every neighbor of nx is mapped to a neighbor of mx, + // then check the reverse, from mx to nx. Check that they have the same + // count of edges. + // + // Note: We want to check the lookahead measures here if we can, + // R_out: Equal for G0, G1: Card(Succ(G, n) ^ Tout); for both Succ and Pred + // R_in: Same with Tin + // R_new: Equal for G0, G1: Ñ n Pred(G, n); both Succ and Pred, + // Ñ is G0 - M - Tin - Tout + // last attempt to add these did not speed up any of the testcases + if r_succ!(0) > r_succ!(1) { + return false; + } + // R_pred + if st.0.graph.is_directed() && r_pred!(0) > r_pred!(1) { + return false; + } + + // // semantic feasibility: compare associated data for nodes + if NM::enabled() && !node_match.eq(st.0.graph, st.1.graph, nodes.0, nodes.1) { + return false; + } + // semantic feasibility: compare associated data for edges + if EM::enabled() { + macro_rules! edge_feasibility { + ($j:tt) => {{ + for n_neigh in field!(st, $j) + .graph + .neighbors_directed(field!(nodes, $j), Outgoing) + { + let m_neigh = if field!(nodes, $j) != n_neigh { + field!(st, $j).mapping[field!(st, $j).graph.to_index(n_neigh)] + } else { + field!(st, 1 - $j).graph.to_index(field!(nodes, 1 - $j)) + }; + if m_neigh == std::usize::MAX { + continue; + } + + let e0 = (field!(nodes, $j), n_neigh); + let e1 = ( + field!(nodes, 1 - $j), + field!(st, 1 - $j).graph.from_index(m_neigh), + ); + let edges = (e0, e1); + if !edge_match.eq( + st.0.graph, + st.1.graph, + field!(edges, $j), + field!(edges, 1 - $j), + ) { + return false; + } + } + if field!(st, $j).graph.is_directed() { + for n_neigh in field!(st, $j) + .graph + .neighbors_directed(field!(nodes, $j), Incoming) + { + // the self loop case is handled in outgoing + let m_neigh = + field!(st, $j).mapping[field!(st, $j).graph.to_index(n_neigh)]; + if m_neigh == std::usize::MAX { + continue; + } + + let e0 = (n_neigh, field!(nodes, $j)); + let e1 = ( + field!(st, 1 - $j).graph.from_index(m_neigh), + field!(nodes, 1 - $j), + ); + let edges = (e0, e1); + if !edge_match.eq( + st.0.graph, + st.1.graph, + field!(edges, $j), + field!(edges, 1 - $j), + ) { + return false; + } + } + } + }}; + } + + edge_feasibility!(0); + edge_feasibility!(1); + } + true + } + + fn next_candidate( + st: &mut (Vf2State<'_, G0>, Vf2State<'_, G1>), + ) -> Option<(G0::NodeId, G1::NodeId, OpenList)> + where + G0: GetAdjacencyMatrix + GraphProp + NodeCompactIndexable + IntoNeighborsDirected, + G1: GetAdjacencyMatrix + GraphProp + NodeCompactIndexable + IntoNeighborsDirected, + { + let mut from_index = None; + let mut open_list = OpenList::Out; + let mut to_index = st.1.next_out_index(0); + + // Try the out list + if to_index.is_some() { + from_index = st.0.next_out_index(0); + open_list = OpenList::Out; + } + // Try the in list + if to_index.is_none() || from_index.is_none() { + to_index = st.1.next_in_index(0); + + if to_index.is_some() { + from_index = st.0.next_in_index(0); + open_list = OpenList::In; + } + } + // Try the other list -- disconnected graph + if to_index.is_none() || from_index.is_none() { + to_index = st.1.next_rest_index(0); + if to_index.is_some() { + from_index = st.0.next_rest_index(0); + open_list = OpenList::Other; + } + } + match (from_index, to_index) { + (Some(n), Some(m)) => Some(( + st.0.graph.from_index(n), + st.1.graph.from_index(m), + open_list, + )), + // No more candidates + _ => None, + } + } + + fn next_from_ix( + st: &mut (Vf2State<'_, G0>, Vf2State<'_, G1>), + nx: G1::NodeId, + open_list: OpenList, + ) -> Option + where + G0: GetAdjacencyMatrix + GraphProp + NodeCompactIndexable + IntoNeighborsDirected, + G1: GetAdjacencyMatrix + GraphProp + NodeCompactIndexable + IntoNeighborsDirected, + { + // Find the next node index to try on the `to` side of the mapping + let start = st.1.graph.to_index(nx) + 1; + let cand1 = match open_list { + OpenList::Out => st.1.next_out_index(start), + OpenList::In => st.1.next_in_index(start), + OpenList::Other => st.1.next_rest_index(start), + } + .map(|c| c + start); // compensate for start offset. + match cand1 { + None => None, // no more candidates + Some(ix) => { + debug_assert!(ix >= start); + Some(st.1.graph.from_index(ix)) + } + } + } + + fn pop_state( + st: &mut (Vf2State<'_, G0>, Vf2State<'_, G1>), + nodes: (G0::NodeId, G1::NodeId), + ) where + G0: GetAdjacencyMatrix + GraphProp + NodeCompactIndexable + IntoNeighborsDirected, + G1: GetAdjacencyMatrix + GraphProp + NodeCompactIndexable + IntoNeighborsDirected, + { + st.0.pop_mapping(nodes.0); + st.1.pop_mapping(nodes.1); + } + + fn push_state( + st: &mut (Vf2State<'_, G0>, Vf2State<'_, G1>), + nodes: (G0::NodeId, G1::NodeId), + ) where + G0: GetAdjacencyMatrix + GraphProp + NodeCompactIndexable + IntoNeighborsDirected, + G1: GetAdjacencyMatrix + GraphProp + NodeCompactIndexable + IntoNeighborsDirected, + { + st.0.push_mapping(nodes.0, st.1.graph.to_index(nodes.1)); + st.1.push_mapping(nodes.1, st.0.graph.to_index(nodes.0)); + } + + /// Return Some(bool) if isomorphism is decided, else None. + pub fn try_match( + st: &mut (Vf2State<'_, G0>, Vf2State<'_, G1>), + node_match: &mut NM, + edge_match: &mut EM, + match_subgraph: bool, + ) -> Option + where + G0: NodeCompactIndexable + + EdgeCount + + GetAdjacencyMatrix + + GraphProp + + IntoNeighborsDirected, + G1: NodeCompactIndexable + + EdgeCount + + GetAdjacencyMatrix + + GraphProp + + IntoNeighborsDirected, + NM: NodeMatcher, + EM: EdgeMatcher, + { + let mut stack = vec![Frame::Outer]; + if isomorphisms(st, node_match, edge_match, match_subgraph, &mut stack).is_some() { + Some(true) + } else { + None + } + } + + fn isomorphisms( + st: &mut (Vf2State<'_, G0>, Vf2State<'_, G1>), + node_match: &mut NM, + edge_match: &mut EM, + match_subgraph: bool, + stack: &mut Vec>, + ) -> Option> + where + G0: NodeCompactIndexable + + EdgeCount + + GetAdjacencyMatrix + + GraphProp + + IntoNeighborsDirected, + G1: NodeCompactIndexable + + EdgeCount + + GetAdjacencyMatrix + + GraphProp + + IntoNeighborsDirected, + NM: NodeMatcher, + EM: EdgeMatcher, + { + if st.0.is_complete() { + return Some(st.0.mapping.clone()); + } + + // A "depth first" search of a valid mapping from graph 1 to graph 2 + // F(s, n, m) -- evaluate state s and add mapping n <-> m + // Find least T1out node (in st.out[1] but not in M[1]) + let mut result = None; + while let Some(frame) = stack.pop() { + match frame { + Frame::Unwind { nodes, open_list } => { + pop_state(st, nodes); + + match next_from_ix(st, nodes.1, open_list) { + None => continue, + Some(nx) => { + let f = Frame::Inner { + nodes: (nodes.0, nx), + open_list, + }; + stack.push(f); + } + } + } + Frame::Outer => match next_candidate(st) { + None => continue, + Some((nx, mx, open_list)) => { + let f = Frame::Inner { + nodes: (nx, mx), + open_list, + }; + stack.push(f); + } + }, + Frame::Inner { nodes, open_list } => { + if is_feasible(st, nodes, node_match, edge_match) { + push_state(st, nodes); + if st.0.is_complete() { + result = Some(st.0.mapping.clone()); + } + // Check cardinalities of Tin, Tout sets + if (!match_subgraph + && st.0.out_size == st.1.out_size + && st.0.ins_size == st.1.ins_size) + || (match_subgraph + && st.0.out_size <= st.1.out_size + && st.0.ins_size <= st.1.ins_size) + { + let f0 = Frame::Unwind { nodes, open_list }; + stack.push(f0); + stack.push(Frame::Outer); + continue; + } + pop_state(st, nodes); + } + match next_from_ix(st, nodes.1, open_list) { + None => continue, + Some(nx) => { + let f = Frame::Inner { + nodes: (nodes.0, nx), + open_list, + }; + stack.push(f); + } + } + } + } + if result.is_some() { + return result; + } + } + result + } + + pub struct GraphMatcher<'a, 'b, 'c, G0, G1, NM, EM> + where + G0: NodeCompactIndexable + + EdgeCount + + GetAdjacencyMatrix + + GraphProp + + IntoNeighborsDirected, + G1: NodeCompactIndexable + + EdgeCount + + GetAdjacencyMatrix + + GraphProp + + IntoNeighborsDirected, + NM: NodeMatcher, + EM: EdgeMatcher, + { + st: (Vf2State<'a, G0>, Vf2State<'b, G1>), + node_match: &'c mut NM, + edge_match: &'c mut EM, + match_subgraph: bool, + stack: Vec>, + } + + impl<'a, 'b, 'c, G0, G1, NM, EM> GraphMatcher<'a, 'b, 'c, G0, G1, NM, EM> + where + G0: NodeCompactIndexable + + EdgeCount + + GetAdjacencyMatrix + + GraphProp + + IntoNeighborsDirected, + G1: NodeCompactIndexable + + EdgeCount + + GetAdjacencyMatrix + + GraphProp + + IntoNeighborsDirected, + NM: NodeMatcher, + EM: EdgeMatcher, + { + pub fn new( + g0: &'a G0, + g1: &'b G1, + node_match: &'c mut NM, + edge_match: &'c mut EM, + match_subgraph: bool, + ) -> Self { + let stack = vec![Frame::Outer]; + Self { + st: (Vf2State::new(g0), Vf2State::new(g1)), + node_match, + edge_match, + match_subgraph, + stack, + } + } + } + + impl Iterator for GraphMatcher<'_, '_, '_, G0, G1, NM, EM> + where + G0: NodeCompactIndexable + + EdgeCount + + GetAdjacencyMatrix + + GraphProp + + IntoNeighborsDirected, + G1: NodeCompactIndexable + + EdgeCount + + GetAdjacencyMatrix + + GraphProp + + IntoNeighborsDirected, + NM: NodeMatcher, + EM: EdgeMatcher, + { + type Item = Vec; + + fn next(&mut self) -> Option { + isomorphisms( + &mut self.st, + self.node_match, + self.edge_match, + self.match_subgraph, + &mut self.stack, + ) + } + + fn size_hint(&self) -> (usize, Option) { + // To calculate the upper bound of results we use n! where n is the + // number of nodes in graph 1. n! values fit into a 64-bit usize up + // to n = 20, so we don't estimate an upper limit for n > 20. + let n = self.st.0.graph.node_count(); + + // We hardcode n! values into an array that accounts for architectures + // with smaller usizes to get our upper bound. + let upper_bounds: Vec> = [ + 1u64, + 1, + 2, + 6, + 24, + 120, + 720, + 5040, + 40320, + 362880, + 3628800, + 39916800, + 479001600, + 6227020800, + 87178291200, + 1307674368000, + 20922789888000, + 355687428096000, + 6402373705728000, + 121645100408832000, + 2432902008176640000, + ] + .iter() + .map(|n| usize::try_from(*n).ok()) + .collect(); + + if n > upper_bounds.len() { + return (0, None); + } + + (0, upper_bounds[n]) + } + } +} + +/// \[Generic\] Return `true` if the graphs `g0` and `g1` are isomorphic. +/// +/// Using the VF2 algorithm, only matching graph syntactically (graph +/// structure). +/// +/// The graphs should not be multigraphs. +/// +/// **Reference** +/// +/// * Luigi P. Cordella, Pasquale Foggia, Carlo Sansone, Mario Vento; +/// *A (Sub)Graph Isomorphism Algorithm for Matching Large Graphs* +pub fn is_isomorphic(g0: G0, g1: G1) -> bool +where + G0: NodeCompactIndexable + EdgeCount + GetAdjacencyMatrix + GraphProp + IntoNeighborsDirected, + G1: NodeCompactIndexable + + EdgeCount + + GetAdjacencyMatrix + + GraphProp + + IntoNeighborsDirected, +{ + if g0.node_count() != g1.node_count() || g0.edge_count() != g1.edge_count() { + return false; + } + + let mut st = (Vf2State::new(&g0), Vf2State::new(&g1)); + self::matching::try_match(&mut st, &mut NoSemanticMatch, &mut NoSemanticMatch, false) + .unwrap_or(false) +} + +/// \[Generic\] Return `true` if the graphs `g0` and `g1` are isomorphic. +/// +/// Using the VF2 algorithm, examining both syntactic and semantic +/// graph isomorphism (graph structure and matching node and edge weights). +/// +/// The graphs should not be multigraphs. +pub fn is_isomorphic_matching( + g0: G0, + g1: G1, + mut node_match: NM, + mut edge_match: EM, +) -> bool +where + G0: NodeCompactIndexable + + EdgeCount + + DataMap + + GetAdjacencyMatrix + + GraphProp + + IntoEdgesDirected, + G1: NodeCompactIndexable + + EdgeCount + + DataMap + + GetAdjacencyMatrix + + GraphProp + + IntoEdgesDirected, + NM: FnMut(&G0::NodeWeight, &G1::NodeWeight) -> bool, + EM: FnMut(&G0::EdgeWeight, &G1::EdgeWeight) -> bool, +{ + if g0.node_count() != g1.node_count() || g0.edge_count() != g1.edge_count() { + return false; + } + + let mut st = (Vf2State::new(&g0), Vf2State::new(&g1)); + self::matching::try_match(&mut st, &mut node_match, &mut edge_match, false).unwrap_or(false) +} + +/// \[Generic\] Return `true` if `g0` is isomorphic to a subgraph of `g1`. +/// +/// Using the VF2 algorithm, only matching graph syntactically (graph +/// structure). +/// +/// The graphs should not be multigraphs. +/// +/// # Subgraph isomorphism +/// +/// (adapted from [`networkx` documentation](https://networkx.github.io/documentation/stable/reference/algorithms/isomorphism.vf2.html)) +/// +/// Graph theory literature can be ambiguous about the meaning of the above statement, +/// and we seek to clarify it now. +/// +/// In the VF2 literature, a mapping **M** is said to be a *graph-subgraph isomorphism* +/// iff **M** is an isomorphism between **G2** and a subgraph of **G1**. Thus, to say +/// that **G1** and **G2** are graph-subgraph isomorphic is to say that a subgraph of +/// **G1** is isomorphic to **G2**. +/// +/// Other literature uses the phrase ‘subgraph isomorphic’ as in +/// ‘**G1** does not have a subgraph isomorphic to **G2**’. Another use is as an in adverb +/// for isomorphic. Thus, to say that **G1** and **G2** are subgraph isomorphic is to say +/// that a subgraph of **G1** is isomorphic to **G2**. +/// +/// Finally, the term ‘subgraph’ can have multiple meanings. In this context, +/// ‘subgraph’ always means a ‘node-induced subgraph’. Edge-induced subgraph +/// isomorphisms are not directly supported. For subgraphs which are not +/// induced, the term ‘monomorphism’ is preferred over ‘isomorphism’. +/// +/// **Reference** +/// +/// * Luigi P. Cordella, Pasquale Foggia, Carlo Sansone, Mario Vento; +/// *A (Sub)Graph Isomorphism Algorithm for Matching Large Graphs* +pub fn is_isomorphic_subgraph(g0: G0, g1: G1) -> bool +where + G0: NodeCompactIndexable + EdgeCount + GetAdjacencyMatrix + GraphProp + IntoNeighborsDirected, + G1: NodeCompactIndexable + + EdgeCount + + GetAdjacencyMatrix + + GraphProp + + IntoNeighborsDirected, +{ + if g0.node_count() > g1.node_count() || g0.edge_count() > g1.edge_count() { + return false; + } + + let mut st = (Vf2State::new(&g0), Vf2State::new(&g1)); + self::matching::try_match(&mut st, &mut NoSemanticMatch, &mut NoSemanticMatch, true) + .unwrap_or(false) +} + +/// \[Generic\] Return `true` if `g0` is isomorphic to a subgraph of `g1`. +/// +/// Using the VF2 algorithm, examining both syntactic and semantic +/// graph isomorphism (graph structure and matching node and edge weights). +/// +/// The graphs should not be multigraphs. +pub fn is_isomorphic_subgraph_matching( + g0: G0, + g1: G1, + mut node_match: NM, + mut edge_match: EM, +) -> bool +where + G0: NodeCompactIndexable + + EdgeCount + + DataMap + + GetAdjacencyMatrix + + GraphProp + + IntoEdgesDirected, + G1: NodeCompactIndexable + + EdgeCount + + DataMap + + GetAdjacencyMatrix + + GraphProp + + IntoEdgesDirected, + NM: FnMut(&G0::NodeWeight, &G1::NodeWeight) -> bool, + EM: FnMut(&G0::EdgeWeight, &G1::EdgeWeight) -> bool, +{ + if g0.node_count() > g1.node_count() || g0.edge_count() > g1.edge_count() { + return false; + } + + let mut st = (Vf2State::new(&g0), Vf2State::new(&g1)); + self::matching::try_match(&mut st, &mut node_match, &mut edge_match, true).unwrap_or(false) +} + +/// Using the VF2 algorithm, examine both syntactic and semantic graph +/// isomorphism (graph structure and matching node and edge weights) and, +/// if `g0` is isomorphic to a subgraph of `g1`, return the mappings between +/// them. +/// +/// The graphs should not be multigraphs. +pub fn subgraph_isomorphisms_iter<'a, G0, G1, NM, EM>( + g0: &'a G0, + g1: &'a G1, + node_match: &'a mut NM, + edge_match: &'a mut EM, +) -> Option> + 'a> +where + G0: 'a + + NodeCompactIndexable + + EdgeCount + + DataMap + + GetAdjacencyMatrix + + GraphProp + + IntoEdgesDirected, + G1: 'a + + NodeCompactIndexable + + EdgeCount + + DataMap + + GetAdjacencyMatrix + + GraphProp + + IntoEdgesDirected, + NM: 'a + FnMut(&G0::NodeWeight, &G1::NodeWeight) -> bool, + EM: 'a + FnMut(&G0::EdgeWeight, &G1::EdgeWeight) -> bool, +{ + if g0.node_count() > g1.node_count() || g0.edge_count() > g1.edge_count() { + return None; + } + + Some(self::matching::GraphMatcher::new( + g0, g1, node_match, edge_match, true, + )) +} diff --git a/vendor/petgraph/src/algo/k_shortest_path.rs b/vendor/petgraph/src/algo/k_shortest_path.rs new file mode 100644 index 00000000..1243eec6 --- /dev/null +++ b/vendor/petgraph/src/algo/k_shortest_path.rs @@ -0,0 +1,115 @@ +use std::collections::{BinaryHeap, HashMap}; + +use std::hash::Hash; + +use crate::algo::Measure; +use crate::scored::MinScored; +use crate::visit::{EdgeRef, IntoEdges, NodeCount, NodeIndexable, Visitable}; + +/// \[Generic\] k'th shortest path algorithm. +/// +/// Compute the length of the k'th shortest path from `start` to every reachable +/// node. +/// +/// The graph should be `Visitable` and implement `IntoEdges`. The function +/// `edge_cost` should return the cost for a particular edge, which is used +/// to compute path costs. Edge costs must be non-negative. +/// +/// If `goal` is not `None`, then the algorithm terminates once the `goal` node's +/// cost is calculated. +/// +/// Computes in **O(k * (|E| + |V|*log(|V|)))** time (average). +/// +/// Returns a `HashMap` that maps `NodeId` to path cost. +/// # Example +/// ```rust +/// use petgraph::Graph; +/// use petgraph::algo::k_shortest_path; +/// use petgraph::prelude::*; +/// use std::collections::HashMap; +/// +/// let mut graph : Graph<(),(),Directed>= Graph::new(); +/// let a = graph.add_node(()); // node with no weight +/// let b = graph.add_node(()); +/// let c = graph.add_node(()); +/// let d = graph.add_node(()); +/// let e = graph.add_node(()); +/// let f = graph.add_node(()); +/// let g = graph.add_node(()); +/// let h = graph.add_node(()); +/// // z will be in another connected component +/// let z = graph.add_node(()); +/// +/// graph.extend_with_edges(&[ +/// (a, b), +/// (b, c), +/// (c, d), +/// (d, a), +/// (e, f), +/// (b, e), +/// (f, g), +/// (g, h), +/// (h, e) +/// ]); +/// // a ----> b ----> e ----> f +/// // ^ | ^ | +/// // | v | v +/// // d <---- c h <---- g +/// +/// let expected_res: HashMap = [ +/// (a, 7), +/// (b, 4), +/// (c, 5), +/// (d, 6), +/// (e, 5), +/// (f, 6), +/// (g, 7), +/// (h, 8) +/// ].iter().cloned().collect(); +/// let res = k_shortest_path(&graph,b,None,2, |_| 1); +/// assert_eq!(res, expected_res); +/// // z is not inside res because there is not path from b to z. +/// ``` +pub fn k_shortest_path( + graph: G, + start: G::NodeId, + goal: Option, + k: usize, + mut edge_cost: F, +) -> HashMap +where + G: IntoEdges + Visitable + NodeCount + NodeIndexable, + G::NodeId: Eq + Hash, + F: FnMut(G::EdgeRef) -> K, + K: Measure + Copy, +{ + let mut counter: Vec = vec![0; graph.node_count()]; + let mut scores = HashMap::new(); + let mut visit_next = BinaryHeap::new(); + let zero_score = K::default(); + + visit_next.push(MinScored(zero_score, start)); + + while let Some(MinScored(node_score, node)) = visit_next.pop() { + counter[graph.to_index(node)] += 1; + let current_counter = counter[graph.to_index(node)]; + + if current_counter > k { + continue; + } + + if current_counter == k { + scores.insert(node, node_score); + } + + //Already reached goal k times + if goal.as_ref() == Some(&node) && current_counter == k { + break; + } + + for edge in graph.edges(node) { + visit_next.push(MinScored(node_score + edge_cost(edge), edge.target())); + } + } + scores +} diff --git a/vendor/petgraph/src/algo/matching.rs b/vendor/petgraph/src/algo/matching.rs new file mode 100644 index 00000000..b5751a5c --- /dev/null +++ b/vendor/petgraph/src/algo/matching.rs @@ -0,0 +1,606 @@ +use std::collections::VecDeque; +use std::hash::Hash; + +use crate::visit::{ + EdgeRef, GraphBase, IntoEdges, IntoNeighbors, IntoNodeIdentifiers, NodeCount, NodeIndexable, + VisitMap, Visitable, +}; + +/// Computed +/// [*matching*](https://en.wikipedia.org/wiki/Matching_(graph_theory)#Definitions) +/// of the graph. +pub struct Matching { + graph: G, + mate: Vec>, + n_edges: usize, +} + +impl Matching +where + G: GraphBase, +{ + fn new(graph: G, mate: Vec>, n_edges: usize) -> Self { + Self { + graph, + mate, + n_edges, + } + } +} + +impl Matching +where + G: NodeIndexable, +{ + /// Gets the matched counterpart of given node, if there is any. + /// + /// Returns `None` if the node is not matched or does not exist. + pub fn mate(&self, node: G::NodeId) -> Option { + self.mate.get(self.graph.to_index(node)).and_then(|&id| id) + } + + /// Iterates over all edges from the matching. + /// + /// An edge is represented by its endpoints. The graph is considered + /// undirected and every pair of matched nodes is reported only once. + pub fn edges(&self) -> MatchedEdges<'_, G> { + MatchedEdges { + graph: &self.graph, + mate: self.mate.as_slice(), + current: 0, + } + } + + /// Iterates over all nodes from the matching. + pub fn nodes(&self) -> MatchedNodes<'_, G> { + MatchedNodes { + graph: &self.graph, + mate: self.mate.as_slice(), + current: 0, + } + } + + /// Returns `true` if given edge is in the matching, or `false` otherwise. + /// + /// If any of the nodes does not exist, `false` is returned. + pub fn contains_edge(&self, a: G::NodeId, b: G::NodeId) -> bool { + match self.mate(a) { + Some(mate) => mate == b, + None => false, + } + } + + /// Returns `true` if given node is in the matching, or `false` otherwise. + /// + /// If the node does not exist, `false` is returned. + pub fn contains_node(&self, node: G::NodeId) -> bool { + self.mate(node).is_some() + } + + /// Gets the number of matched **edges**. + pub fn len(&self) -> usize { + self.n_edges + } + + /// Returns `true` if the number of matched **edges** is 0. + pub fn is_empty(&self) -> bool { + self.len() == 0 + } +} + +impl Matching +where + G: NodeCount, +{ + /// Returns `true` if the matching is perfect. + /// + /// A matching is + /// [*perfect*](https://en.wikipedia.org/wiki/Matching_(graph_theory)#Definitions) + /// if every node in the graph is incident to an edge from the matching. + pub fn is_perfect(&self) -> bool { + let n_nodes = self.graph.node_count(); + n_nodes % 2 == 0 && self.n_edges == n_nodes / 2 + } +} + +trait WithDummy: NodeIndexable { + fn dummy_idx(&self) -> usize; + /// Convert `i` to a node index, returns None for the dummy node + fn try_from_index(&self, i: usize) -> Option; +} + +impl WithDummy for G { + fn dummy_idx(&self) -> usize { + // Gabow numbers the vertices from 1 to n, and uses 0 as the dummy + // vertex. Our vertex indices are zero-based and so we use the node + // bound as the dummy node. + self.node_bound() + } + + fn try_from_index(&self, i: usize) -> Option { + if i != self.dummy_idx() { + Some(self.from_index(i)) + } else { + None + } + } +} + +pub struct MatchedNodes<'a, G: GraphBase> { + graph: &'a G, + mate: &'a [Option], + current: usize, +} + +impl Iterator for MatchedNodes<'_, G> +where + G: NodeIndexable, +{ + type Item = G::NodeId; + + fn next(&mut self) -> Option { + while self.current != self.mate.len() { + let current = self.current; + self.current += 1; + + if self.mate[current].is_some() { + return Some(self.graph.from_index(current)); + } + } + + None + } +} + +pub struct MatchedEdges<'a, G: GraphBase> { + graph: &'a G, + mate: &'a [Option], + current: usize, +} + +impl Iterator for MatchedEdges<'_, G> +where + G: NodeIndexable, +{ + type Item = (G::NodeId, G::NodeId); + + fn next(&mut self) -> Option { + while self.current != self.mate.len() { + let current = self.current; + self.current += 1; + + if let Some(mate) = self.mate[current] { + // Check if the mate is a node after the current one. If not, then + // do not report that edge since it has been already reported (the + // graph is considered undirected). + if self.graph.to_index(mate) > current { + let this = self.graph.from_index(current); + return Some((this, mate)); + } + } + } + + None + } +} + +/// \[Generic\] Compute a +/// [*matching*](https://en.wikipedia.org/wiki/Matching_(graph_theory)) using a +/// greedy heuristic. +/// +/// The input graph is treated as if undirected. The underlying heuristic is +/// unspecified, but is guaranteed to be bounded by *O(|V| + |E|)*. No +/// guarantees about the output are given other than that it is a valid +/// matching. +/// +/// If you require a maximum matching, use [`maximum_matching`][1] function +/// instead. +/// +/// [1]: fn.maximum_matching.html +pub fn greedy_matching(graph: G) -> Matching +where + G: Visitable + IntoNodeIdentifiers + NodeIndexable + IntoNeighbors, + G::NodeId: Eq + Hash, + G::EdgeId: Eq + Hash, +{ + let (mates, n_edges) = greedy_matching_inner(&graph); + Matching::new(graph, mates, n_edges) +} + +#[inline] +fn greedy_matching_inner(graph: &G) -> (Vec>, usize) +where + G: Visitable + IntoNodeIdentifiers + NodeIndexable + IntoNeighbors, +{ + let mut mate = vec![None; graph.node_bound()]; + let mut n_edges = 0; + let visited = &mut graph.visit_map(); + + for start in graph.node_identifiers() { + let mut last = Some(start); + + // Function non_backtracking_dfs does not expand the node if it has been + // already visited. + non_backtracking_dfs(graph, start, visited, |next| { + // Alternate matched and unmatched edges. + if let Some(pred) = last.take() { + mate[graph.to_index(pred)] = Some(next); + mate[graph.to_index(next)] = Some(pred); + n_edges += 1; + } else { + last = Some(next); + } + }); + } + + (mate, n_edges) +} + +fn non_backtracking_dfs(graph: &G, source: G::NodeId, visited: &mut G::Map, mut visitor: F) +where + G: Visitable + IntoNeighbors, + F: FnMut(G::NodeId), +{ + if visited.visit(source) { + for target in graph.neighbors(source) { + if !visited.is_visited(&target) { + visitor(target); + non_backtracking_dfs(graph, target, visited, visitor); + + // Non-backtracking traversal, stop iterating over the + // neighbors. + break; + } + } + } +} + +#[derive(Clone, Copy)] +enum Label { + None, + Start, + // If node v is outer node, then label(v) = w is another outer node on path + // from v to start u. + Vertex(G::NodeId), + // If node v is outer node, then label(v) = (r, s) are two outer vertices + // (connected by an edge) + Edge(G::EdgeId, [G::NodeId; 2]), + // Flag is a special label used in searching for the join vertex of two + // paths. + Flag(G::EdgeId), +} + +impl Label { + fn is_outer(&self) -> bool { + self != &Label::None + && !match self { + Label::Flag(_) => true, + _ => false, + } + } + + fn is_inner(&self) -> bool { + !self.is_outer() + } + + fn to_vertex(&self) -> Option { + match *self { + Label::Vertex(v) => Some(v), + _ => None, + } + } + + fn is_flagged(&self, edge: G::EdgeId) -> bool { + match self { + Label::Flag(flag) if flag == &edge => true, + _ => false, + } + } +} + +impl Default for Label { + fn default() -> Self { + Label::None + } +} + +impl PartialEq for Label { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (Label::None, Label::None) => true, + (Label::Start, Label::Start) => true, + (Label::Vertex(v1), Label::Vertex(v2)) => v1 == v2, + (Label::Edge(e1, _), Label::Edge(e2, _)) => e1 == e2, + (Label::Flag(e1), Label::Flag(e2)) => e1 == e2, + _ => false, + } + } +} + +/// \[Generic\] Compute the [*maximum +/// matching*](https://en.wikipedia.org/wiki/Matching_(graph_theory)) using +/// [Gabow's algorithm][1]. +/// +/// [1]: https://dl.acm.org/doi/10.1145/321941.321942 +/// +/// The input graph is treated as if undirected. The algorithm runs in +/// *O(|V|³)*. An algorithm with a better time complexity might be used in the +/// future. +/// +/// **Panics** if `g.node_bound()` is `std::usize::MAX`. +/// +/// # Examples +/// +/// ``` +/// use petgraph::prelude::*; +/// use petgraph::algo::maximum_matching; +/// +/// // The example graph: +/// // +/// // +-- b ---- d ---- f +/// // / | | +/// // a | | +/// // \ | | +/// // +-- c ---- e +/// // +/// // Maximum matching: { (a, b), (c, e), (d, f) } +/// +/// let mut graph: UnGraph<(), ()> = UnGraph::new_undirected(); +/// let a = graph.add_node(()); +/// let b = graph.add_node(()); +/// let c = graph.add_node(()); +/// let d = graph.add_node(()); +/// let e = graph.add_node(()); +/// let f = graph.add_node(()); +/// graph.extend_with_edges(&[(a, b), (a, c), (b, c), (b, d), (c, e), (d, e), (d, f)]); +/// +/// let matching = maximum_matching(&graph); +/// assert!(matching.contains_edge(a, b)); +/// assert!(matching.contains_edge(c, e)); +/// assert_eq!(matching.mate(d), Some(f)); +/// assert_eq!(matching.mate(f), Some(d)); +/// ``` +pub fn maximum_matching(graph: G) -> Matching +where + G: Visitable + NodeIndexable + IntoNodeIdentifiers + IntoEdges, +{ + // The dummy identifier needs an unused index + assert_ne!( + graph.node_bound(), + std::usize::MAX, + "The input graph capacity should be strictly less than std::usize::MAX." + ); + + // Greedy algorithm should create a fairly good initial matching. The hope + // is that it speeds up the computation by doing les work in the complex + // algorithm. + let (mut mate, mut n_edges) = greedy_matching_inner(&graph); + + // Gabow's algorithm uses a dummy node in the mate array. + mate.push(None); + let len = graph.node_bound() + 1; + debug_assert_eq!(mate.len(), len); + + let mut label: Vec> = vec![Label::None; len]; + let mut first_inner = vec![std::usize::MAX; len]; + let visited = &mut graph.visit_map(); + + for start in 0..graph.node_bound() { + if mate[start].is_some() { + // The vertex is already matched. A start must be a free vertex. + continue; + } + + // Begin search from the node. + label[start] = Label::Start; + first_inner[start] = graph.dummy_idx(); + graph.reset_map(visited); + + // start is never a dummy index + let start = graph.from_index(start); + + // Queue will contain outer vertices that should be processed next. The + // start vertex is considered an outer vertex. + let mut queue = VecDeque::new(); + queue.push_back(start); + // Mark the start vertex so it is not processed repeatedly. + visited.visit(start); + + 'search: while let Some(outer_vertex) = queue.pop_front() { + for edge in graph.edges(outer_vertex) { + if edge.source() == edge.target() { + // Ignore self-loops. + continue; + } + + let other_vertex = edge.target(); + let other_idx = graph.to_index(other_vertex); + + if mate[other_idx].is_none() && other_vertex != start { + // An augmenting path was found. Augment the matching. If + // `other` is actually the start node, then the augmentation + // must not be performed, because the start vertex would be + // incident to two edges, which violates the matching + // property. + mate[other_idx] = Some(outer_vertex); + augment_path(&graph, outer_vertex, other_vertex, &mut mate, &label); + n_edges += 1; + + // The path is augmented, so the start is no longer free + // vertex. We need to begin with a new start. + break 'search; + } else if label[other_idx].is_outer() { + // The `other` is an outer vertex (a label has been set to + // it). An odd cycle (blossom) was found. Assign this edge + // as a label to all inner vertices in paths P(outer) and + // P(other). + find_join( + &graph, + edge, + &mate, + &mut label, + &mut first_inner, + |labeled| { + if visited.visit(labeled) { + queue.push_back(labeled); + } + }, + ); + } else { + let mate_vertex = mate[other_idx]; + let mate_idx = mate_vertex.map_or(graph.dummy_idx(), |id| graph.to_index(id)); + + if label[mate_idx].is_inner() { + // Mate of `other` vertex is inner (no label has been + // set to it so far). But it actually is an outer vertex + // (it is on a path to the start vertex that begins with + // a matched edge, since it is a mate of `other`). + // Assign the label of this mate to the `outer` vertex, + // so the path for it can be reconstructed using `mate` + // and this label. + label[mate_idx] = Label::Vertex(outer_vertex); + first_inner[mate_idx] = other_idx; + } + + // Add the vertex to the queue only if it's not the dummy and this is its first + // discovery. + if let Some(mate_vertex) = mate_vertex { + if visited.visit(mate_vertex) { + queue.push_back(mate_vertex); + } + } + } + } + } + + // Reset the labels. All vertices are inner for the next search. + for lbl in label.iter_mut() { + *lbl = Label::None; + } + } + + // Discard the dummy node. + mate.pop(); + + Matching::new(graph, mate, n_edges) +} + +fn find_join( + graph: &G, + edge: G::EdgeRef, + mate: &[Option], + label: &mut [Label], + first_inner: &mut [usize], + mut visitor: F, +) where + G: IntoEdges + NodeIndexable + Visitable, + F: FnMut(G::NodeId), +{ + // Simultaneously traverse the inner vertices on paths P(source) and + // P(target) to find a join vertex - an inner vertex that is shared by these + // paths. + let source = graph.to_index(edge.source()); + let target = graph.to_index(edge.target()); + + let mut left = first_inner[source]; + let mut right = first_inner[target]; + + if left == right { + // No vertices can be labeled, since both paths already refer to a + // common vertex - the join. + return; + } + + // Flag the (first) inner vertices. This ensures that they are assigned the + // join as their first inner vertex. + let flag = Label::Flag(edge.id()); + label[left] = flag; + label[right] = flag; + + // Find the join. + let join = loop { + // Swap the sides. Do not swap if the right side is already finished. + if right != graph.dummy_idx() { + std::mem::swap(&mut left, &mut right); + } + + // Set left to the next inner vertex in P(source) or P(target). + // The unwraps are safe because left is not the dummy node. + let left_mate = graph.to_index(mate[left].unwrap()); + let next_inner = label[left_mate].to_vertex().unwrap(); + left = first_inner[graph.to_index(next_inner)]; + + if !label[left].is_flagged(edge.id()) { + // The inner vertex is not flagged yet, so flag it. + label[left] = flag; + } else { + // The inner vertex is already flagged. It means that the other side + // had to visit it already. Therefore it is the join vertex. + break left; + } + }; + + // Label all inner vertices on P(source) and P(target) with the found join. + for endpoint in [source, target].iter().copied() { + let mut inner = first_inner[endpoint]; + while inner != join { + // Notify the caller about labeling a vertex. + if let Some(ix) = graph.try_from_index(inner) { + visitor(ix); + } + + label[inner] = Label::Edge(edge.id(), [edge.source(), edge.target()]); + first_inner[inner] = join; + let inner_mate = graph.to_index(mate[inner].unwrap()); + let next_inner = label[inner_mate].to_vertex().unwrap(); + inner = first_inner[graph.to_index(next_inner)]; + } + } + + for (vertex_idx, vertex_label) in label.iter().enumerate() { + // To all outer vertices that are on paths P(source) and P(target) until + // the join, se the join as their first inner vertex. + if vertex_idx != graph.dummy_idx() + && vertex_label.is_outer() + && label[first_inner[vertex_idx]].is_outer() + { + first_inner[vertex_idx] = join; + } + } +} + +fn augment_path( + graph: &G, + outer: G::NodeId, + other: G::NodeId, + mate: &mut [Option], + label: &[Label], +) where + G: NodeIndexable, +{ + let outer_idx = graph.to_index(outer); + + let temp = mate[outer_idx]; + let temp_idx = temp.map_or(graph.dummy_idx(), |id| graph.to_index(id)); + mate[outer_idx] = Some(other); + + if mate[temp_idx] != Some(outer) { + // We are at the end of the path and so the entire path is completely + // rematched/augmented. + } else if let Label::Vertex(vertex) = label[outer_idx] { + // The outer vertex has a vertex label which refers to another outer + // vertex on the path. So we set this another outer node as the mate for + // the previous mate of the outer node. + mate[temp_idx] = Some(vertex); + if let Some(temp) = temp { + augment_path(graph, vertex, temp, mate, label); + } + } else if let Label::Edge(_, [source, target]) = label[outer_idx] { + // The outer vertex has an edge label which refers to an edge in a + // blossom. We need to augment both directions along the blossom. + augment_path(graph, source, target, mate, label); + augment_path(graph, target, source, mate, label); + } else { + panic!("Unexpected label when augmenting path"); + } +} diff --git a/vendor/petgraph/src/algo/min_spanning_tree.rs b/vendor/petgraph/src/algo/min_spanning_tree.rs new file mode 100644 index 00000000..19cefcf5 --- /dev/null +++ b/vendor/petgraph/src/algo/min_spanning_tree.rs @@ -0,0 +1,117 @@ +//! Minimum Spanning Tree algorithms. + +use std::collections::{BinaryHeap, HashMap}; + +use crate::prelude::*; + +use crate::data::Element; +use crate::scored::MinScored; +use crate::unionfind::UnionFind; +use crate::visit::{Data, IntoNodeReferences, NodeRef}; +use crate::visit::{IntoEdgeReferences, NodeIndexable}; + +/// \[Generic\] Compute a *minimum spanning tree* of a graph. +/// +/// The input graph is treated as if undirected. +/// +/// Using Kruskal's algorithm with runtime **O(|E| log |E|)**. We actually +/// return a minimum spanning forest, i.e. a minimum spanning tree for each connected +/// component of the graph. +/// +/// The resulting graph has all the vertices of the input graph (with identical node indices), +/// and **|V| - c** edges, where **c** is the number of connected components in `g`. +/// +/// Use `from_elements` to create a graph from the resulting iterator. +pub fn min_spanning_tree(g: G) -> MinSpanningTree +where + G::NodeWeight: Clone, + G::EdgeWeight: Clone + PartialOrd, + G: IntoNodeReferences + IntoEdgeReferences + NodeIndexable, +{ + // Initially each vertex is its own disjoint subgraph, track the connectedness + // of the pre-MST with a union & find datastructure. + let subgraphs = UnionFind::new(g.node_bound()); + + let edges = g.edge_references(); + let mut sort_edges = BinaryHeap::with_capacity(edges.size_hint().0); + for edge in edges { + sort_edges.push(MinScored( + edge.weight().clone(), + (edge.source(), edge.target()), + )); + } + + MinSpanningTree { + graph: g, + node_ids: Some(g.node_references()), + subgraphs, + sort_edges, + node_map: HashMap::new(), + node_count: 0, + } +} + +/// An iterator producing a minimum spanning forest of a graph. +#[derive(Debug, Clone)] +pub struct MinSpanningTree +where + G: Data + IntoNodeReferences, +{ + graph: G, + node_ids: Option, + subgraphs: UnionFind, + #[allow(clippy::type_complexity)] + sort_edges: BinaryHeap>, + node_map: HashMap, + node_count: usize, +} + +impl Iterator for MinSpanningTree +where + G: IntoNodeReferences + NodeIndexable, + G::NodeWeight: Clone, + G::EdgeWeight: PartialOrd, +{ + type Item = Element; + + fn next(&mut self) -> Option { + let g = self.graph; + if let Some(ref mut iter) = self.node_ids { + if let Some(node) = iter.next() { + self.node_map.insert(g.to_index(node.id()), self.node_count); + self.node_count += 1; + return Some(Element::Node { + weight: node.weight().clone(), + }); + } + } + self.node_ids = None; + + // Kruskal's algorithm. + // Algorithm is this: + // + // 1. Create a pre-MST with all the vertices and no edges. + // 2. Repeat: + // + // a. Remove the shortest edge from the original graph. + // b. If the edge connects two disjoint trees in the pre-MST, + // add the edge. + while let Some(MinScored(score, (a, b))) = self.sort_edges.pop() { + // check if the edge would connect two disjoint parts + let (a_index, b_index) = (g.to_index(a), g.to_index(b)); + if self.subgraphs.union(a_index, b_index) { + let (&a_order, &b_order) = + match (self.node_map.get(&a_index), self.node_map.get(&b_index)) { + (Some(a_id), Some(b_id)) => (a_id, b_id), + _ => panic!("Edge references unknown node"), + }; + return Some(Element::Edge { + source: a_order, + target: b_order, + weight: score, + }); + } + } + None + } +} diff --git a/vendor/petgraph/src/algo/mod.rs b/vendor/petgraph/src/algo/mod.rs new file mode 100644 index 00000000..218ca20e --- /dev/null +++ b/vendor/petgraph/src/algo/mod.rs @@ -0,0 +1,867 @@ +//! Graph algorithms. +//! +//! It is a goal to gradually migrate the algorithms to be based on graph traits +//! so that they are generally applicable. For now, some of these still require +//! the `Graph` type. + +pub mod astar; +pub mod bellman_ford; +pub mod coloring; +pub mod dijkstra; +pub mod dominators; +pub mod feedback_arc_set; +pub mod floyd_warshall; +pub mod ford_fulkerson; +pub mod isomorphism; +pub mod k_shortest_path; +pub mod matching; +pub mod min_spanning_tree; +pub mod page_rank; +pub mod simple_paths; +pub mod tred; + +use std::num::NonZeroUsize; + +use crate::prelude::*; + +use super::graph::IndexType; +use super::unionfind::UnionFind; +use super::visit::{ + GraphBase, GraphRef, IntoEdgeReferences, IntoNeighbors, IntoNeighborsDirected, + IntoNodeIdentifiers, NodeCompactIndexable, NodeIndexable, Reversed, VisitMap, Visitable, +}; +use super::EdgeType; +use crate::visit::Walker; + +pub use astar::astar; +pub use bellman_ford::{bellman_ford, find_negative_cycle}; +pub use coloring::dsatur_coloring; +pub use dijkstra::dijkstra; +pub use feedback_arc_set::greedy_feedback_arc_set; +pub use floyd_warshall::floyd_warshall; +pub use ford_fulkerson::ford_fulkerson; +pub use isomorphism::{ + is_isomorphic, is_isomorphic_matching, is_isomorphic_subgraph, is_isomorphic_subgraph_matching, + subgraph_isomorphisms_iter, +}; +pub use k_shortest_path::k_shortest_path; +pub use matching::{greedy_matching, maximum_matching, Matching}; +pub use min_spanning_tree::min_spanning_tree; +pub use page_rank::page_rank; +pub use simple_paths::all_simple_paths; + +/// \[Generic\] Return the number of connected components of the graph. +/// +/// For a directed graph, this is the *weakly* connected components. +/// # Example +/// ```rust +/// use petgraph::Graph; +/// use petgraph::algo::connected_components; +/// use petgraph::prelude::*; +/// +/// let mut graph : Graph<(),(),Directed>= Graph::new(); +/// let a = graph.add_node(()); // node with no weight +/// let b = graph.add_node(()); +/// let c = graph.add_node(()); +/// let d = graph.add_node(()); +/// let e = graph.add_node(()); +/// let f = graph.add_node(()); +/// let g = graph.add_node(()); +/// let h = graph.add_node(()); +/// +/// graph.extend_with_edges(&[ +/// (a, b), +/// (b, c), +/// (c, d), +/// (d, a), +/// (e, f), +/// (f, g), +/// (g, h), +/// (h, e) +/// ]); +/// // a ----> b e ----> f +/// // ^ | ^ | +/// // | v | v +/// // d <---- c h <---- g +/// +/// assert_eq!(connected_components(&graph),2); +/// graph.add_edge(b,e,()); +/// assert_eq!(connected_components(&graph),1); +/// ``` +pub fn connected_components(g: G) -> usize +where + G: NodeCompactIndexable + IntoEdgeReferences, +{ + let mut vertex_sets = UnionFind::new(g.node_bound()); + for edge in g.edge_references() { + let (a, b) = (edge.source(), edge.target()); + + // union the two vertices of the edge + vertex_sets.union(g.to_index(a), g.to_index(b)); + } + let mut labels = vertex_sets.into_labeling(); + labels.sort_unstable(); + labels.dedup(); + labels.len() +} + +/// \[Generic\] Return `true` if the input graph contains a cycle. +/// +/// Always treats the input graph as if undirected. +pub fn is_cyclic_undirected(g: G) -> bool +where + G: NodeIndexable + IntoEdgeReferences, +{ + let mut edge_sets = UnionFind::new(g.node_bound()); + for edge in g.edge_references() { + let (a, b) = (edge.source(), edge.target()); + + // union the two vertices of the edge + // -- if they were already the same, then we have a cycle + if !edge_sets.union(g.to_index(a), g.to_index(b)) { + return true; + } + } + false +} + +/// \[Generic\] Perform a topological sort of a directed graph. +/// +/// If the graph was acyclic, return a vector of nodes in topological order: +/// each node is ordered before its successors. +/// Otherwise, it will return a `Cycle` error. Self loops are also cycles. +/// +/// To handle graphs with cycles, use the scc algorithms or `DfsPostOrder` +/// instead of this function. +/// +/// If `space` is not `None`, it is used instead of creating a new workspace for +/// graph traversal. The implementation is iterative. +pub fn toposort( + g: G, + space: Option<&mut DfsSpace>, +) -> Result, Cycle> +where + G: IntoNeighborsDirected + IntoNodeIdentifiers + Visitable, +{ + // based on kosaraju scc + with_dfs(g, space, |dfs| { + dfs.reset(g); + let mut finished = g.visit_map(); + + let mut finish_stack = Vec::new(); + for i in g.node_identifiers() { + if dfs.discovered.is_visited(&i) { + continue; + } + dfs.stack.push(i); + while let Some(&nx) = dfs.stack.last() { + if dfs.discovered.visit(nx) { + // First time visiting `nx`: Push neighbors, don't pop `nx` + for succ in g.neighbors(nx) { + if succ == nx { + // self cycle + return Err(Cycle(nx)); + } + if !dfs.discovered.is_visited(&succ) { + dfs.stack.push(succ); + } + } + } else { + dfs.stack.pop(); + if finished.visit(nx) { + // Second time: All reachable nodes must have been finished + finish_stack.push(nx); + } + } + } + } + finish_stack.reverse(); + + dfs.reset(g); + for &i in &finish_stack { + dfs.move_to(i); + let mut cycle = false; + while let Some(j) = dfs.next(Reversed(g)) { + if cycle { + return Err(Cycle(j)); + } + cycle = true; + } + } + + Ok(finish_stack) + }) +} + +/// \[Generic\] Return `true` if the input directed graph contains a cycle. +/// +/// This implementation is recursive; use `toposort` if an alternative is +/// needed. +pub fn is_cyclic_directed(g: G) -> bool +where + G: IntoNodeIdentifiers + IntoNeighbors + Visitable, +{ + use crate::visit::{depth_first_search, DfsEvent}; + + depth_first_search(g, g.node_identifiers(), |event| match event { + DfsEvent::BackEdge(_, _) => Err(()), + _ => Ok(()), + }) + .is_err() +} + +type DfsSpaceType = DfsSpace<::NodeId, ::Map>; + +/// Workspace for a graph traversal. +#[derive(Clone, Debug)] +pub struct DfsSpace { + dfs: Dfs, +} + +impl DfsSpace +where + N: Copy + PartialEq, + VM: VisitMap, +{ + pub fn new(g: G) -> Self + where + G: GraphRef + Visitable, + { + DfsSpace { dfs: Dfs::empty(g) } + } +} + +impl Default for DfsSpace +where + VM: VisitMap + Default, +{ + fn default() -> Self { + DfsSpace { + dfs: Dfs { + stack: <_>::default(), + discovered: <_>::default(), + }, + } + } +} + +/// Create a Dfs if it's needed +fn with_dfs(g: G, space: Option<&mut DfsSpaceType>, f: F) -> R +where + G: GraphRef + Visitable, + F: FnOnce(&mut Dfs) -> R, +{ + let mut local_visitor; + let dfs = if let Some(v) = space { + &mut v.dfs + } else { + local_visitor = Dfs::empty(g); + &mut local_visitor + }; + f(dfs) +} + +/// \[Generic\] Check if there exists a path starting at `from` and reaching `to`. +/// +/// If `from` and `to` are equal, this function returns true. +/// +/// If `space` is not `None`, it is used instead of creating a new workspace for +/// graph traversal. +pub fn has_path_connecting( + g: G, + from: G::NodeId, + to: G::NodeId, + space: Option<&mut DfsSpace>, +) -> bool +where + G: IntoNeighbors + Visitable, +{ + with_dfs(g, space, |dfs| { + dfs.reset(g); + dfs.move_to(from); + dfs.iter(g).any(|x| x == to) + }) +} + +/// Renamed to `kosaraju_scc`. +#[deprecated(note = "renamed to kosaraju_scc")] +pub fn scc(g: G) -> Vec> +where + G: IntoNeighborsDirected + Visitable + IntoNodeIdentifiers, +{ + kosaraju_scc(g) +} + +/// \[Generic\] Compute the *strongly connected components* using [Kosaraju's algorithm][1]. +/// +/// [1]: https://en.wikipedia.org/wiki/Kosaraju%27s_algorithm +/// +/// Return a vector where each element is a strongly connected component (scc). +/// The order of node ids within each scc is arbitrary, but the order of +/// the sccs is their postorder (reverse topological sort). +/// +/// For an undirected graph, the sccs are simply the connected components. +/// +/// This implementation is iterative and does two passes over the nodes. +pub fn kosaraju_scc(g: G) -> Vec> +where + G: IntoNeighborsDirected + Visitable + IntoNodeIdentifiers, +{ + let mut dfs = DfsPostOrder::empty(g); + + // First phase, reverse dfs pass, compute finishing times. + // http://stackoverflow.com/a/26780899/161659 + let mut finish_order = Vec::with_capacity(0); + for i in g.node_identifiers() { + if dfs.discovered.is_visited(&i) { + continue; + } + + dfs.move_to(i); + while let Some(nx) = dfs.next(Reversed(g)) { + finish_order.push(nx); + } + } + + let mut dfs = Dfs::from_parts(dfs.stack, dfs.discovered); + dfs.reset(g); + let mut sccs = Vec::new(); + + // Second phase + // Process in decreasing finishing time order + for i in finish_order.into_iter().rev() { + if dfs.discovered.is_visited(&i) { + continue; + } + // Move to the leader node `i`. + dfs.move_to(i); + let mut scc = Vec::new(); + while let Some(nx) = dfs.next(g) { + scc.push(nx); + } + sccs.push(scc); + } + sccs +} + +#[derive(Copy, Clone, Debug)] +struct NodeData { + rootindex: Option, +} + +/// A reusable state for computing the *strongly connected components* using [Tarjan's algorithm][1]. +/// +/// [1]: https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm +#[derive(Debug)] +pub struct TarjanScc { + index: usize, + componentcount: usize, + nodes: Vec, + stack: Vec, +} + +impl Default for TarjanScc { + fn default() -> Self { + Self::new() + } +} + +impl TarjanScc { + /// Creates a new `TarjanScc` + pub fn new() -> Self { + TarjanScc { + index: 1, // Invariant: index < componentcount at all times. + componentcount: std::usize::MAX, // Will hold if componentcount is initialized to number of nodes - 1 or higher. + nodes: Vec::new(), + stack: Vec::new(), + } + } + + /// \[Generic\] Compute the *strongly connected components* using Algorithm 3 in + /// [A Space-Efficient Algorithm for Finding Strongly Connected Components][1] by David J. Pierce, + /// which is a memory-efficient variation of [Tarjan's algorithm][2]. + /// + /// + /// [1]: https://homepages.ecs.vuw.ac.nz/~djp/files/P05.pdf + /// [2]: https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm + /// + /// Calls `f` for each strongly strongly connected component (scc). + /// The order of node ids within each scc is arbitrary, but the order of + /// the sccs is their postorder (reverse topological sort). + /// + /// For an undirected graph, the sccs are simply the connected components. + /// + /// This implementation is recursive and does one pass over the nodes. + pub fn run(&mut self, g: G, mut f: F) + where + G: IntoNodeIdentifiers + IntoNeighbors + NodeIndexable, + F: FnMut(&[N]), + N: Copy + PartialEq, + { + self.nodes.clear(); + self.nodes + .resize(g.node_bound(), NodeData { rootindex: None }); + + for n in g.node_identifiers() { + let visited = self.nodes[g.to_index(n)].rootindex.is_some(); + if !visited { + self.visit(n, g, &mut f); + } + } + + debug_assert!(self.stack.is_empty()); + } + + fn visit(&mut self, v: G::NodeId, g: G, f: &mut F) + where + G: IntoNeighbors + NodeIndexable, + F: FnMut(&[N]), + N: Copy + PartialEq, + { + macro_rules! node { + ($node:expr) => { + self.nodes[g.to_index($node)] + }; + } + + let node_v = &mut node![v]; + debug_assert!(node_v.rootindex.is_none()); + + let mut v_is_local_root = true; + let v_index = self.index; + node_v.rootindex = NonZeroUsize::new(v_index); + self.index += 1; + + for w in g.neighbors(v) { + if node![w].rootindex.is_none() { + self.visit(w, g, f); + } + if node![w].rootindex < node![v].rootindex { + node![v].rootindex = node![w].rootindex; + v_is_local_root = false + } + } + + if v_is_local_root { + // Pop the stack and generate an SCC. + let mut indexadjustment = 1; + let c = NonZeroUsize::new(self.componentcount); + let nodes = &mut self.nodes; + let start = self + .stack + .iter() + .rposition(|&w| { + if nodes[g.to_index(v)].rootindex > nodes[g.to_index(w)].rootindex { + true + } else { + nodes[g.to_index(w)].rootindex = c; + indexadjustment += 1; + false + } + }) + .map(|x| x + 1) + .unwrap_or_default(); + nodes[g.to_index(v)].rootindex = c; + self.stack.push(v); // Pushing the component root to the back right before getting rid of it is somewhat ugly, but it lets it be included in f. + f(&self.stack[start..]); + self.stack.truncate(start); + self.index -= indexadjustment; // Backtrack index back to where it was before we ever encountered the component. + self.componentcount -= 1; + } else { + self.stack.push(v); // Stack is filled up when backtracking, unlike in Tarjans original algorithm. + } + } + + /// Returns the index of the component in which v has been assigned. Allows for using self as a lookup table for an scc decomposition produced by self.run(). + pub fn node_component_index(&self, g: G, v: N) -> usize + where + G: IntoNeighbors + NodeIndexable, + N: Copy + PartialEq, + { + let rindex: usize = self.nodes[g.to_index(v)] + .rootindex + .map(NonZeroUsize::get) + .unwrap_or(0); // Compiles to no-op. + debug_assert!( + rindex != 0, + "Tried to get the component index of an unvisited node." + ); + debug_assert!( + rindex > self.componentcount, + "Given node has been visited but not yet assigned to a component." + ); + std::usize::MAX - rindex + } +} + +/// \[Generic\] Compute the *strongly connected components* using [Tarjan's algorithm][1]. +/// +/// [1]: https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm +/// [2]: https://homepages.ecs.vuw.ac.nz/~djp/files/P05.pdf +/// +/// Return a vector where each element is a strongly connected component (scc). +/// The order of node ids within each scc is arbitrary, but the order of +/// the sccs is their postorder (reverse topological sort). +/// +/// For an undirected graph, the sccs are simply the connected components. +/// +/// This implementation is recursive and does one pass over the nodes. It is based on +/// [A Space-Efficient Algorithm for Finding Strongly Connected Components][2] by David J. Pierce, +/// to provide a memory-efficient implementation of [Tarjan's algorithm][1]. +pub fn tarjan_scc(g: G) -> Vec> +where + G: IntoNodeIdentifiers + IntoNeighbors + NodeIndexable, +{ + let mut sccs = Vec::new(); + { + let mut tarjan_scc = TarjanScc::new(); + tarjan_scc.run(g, |scc| sccs.push(scc.to_vec())); + } + sccs +} + +/// [Graph] Condense every strongly connected component into a single node and return the result. +/// +/// If `make_acyclic` is true, self-loops and multi edges are ignored, guaranteeing that +/// the output is acyclic. +/// # Example +/// ```rust +/// use petgraph::Graph; +/// use petgraph::algo::condensation; +/// use petgraph::prelude::*; +/// +/// let mut graph : Graph<(),(),Directed> = Graph::new(); +/// let a = graph.add_node(()); // node with no weight +/// let b = graph.add_node(()); +/// let c = graph.add_node(()); +/// let d = graph.add_node(()); +/// let e = graph.add_node(()); +/// let f = graph.add_node(()); +/// let g = graph.add_node(()); +/// let h = graph.add_node(()); +/// +/// graph.extend_with_edges(&[ +/// (a, b), +/// (b, c), +/// (c, d), +/// (d, a), +/// (b, e), +/// (e, f), +/// (f, g), +/// (g, h), +/// (h, e) +/// ]); +/// +/// // a ----> b ----> e ----> f +/// // ^ | ^ | +/// // | v | v +/// // d <---- c h <---- g +/// +/// let condensed_graph = condensation(graph,false); +/// let A = NodeIndex::new(0); +/// let B = NodeIndex::new(1); +/// assert_eq!(condensed_graph.node_count(), 2); +/// assert_eq!(condensed_graph.edge_count(), 9); +/// assert_eq!(condensed_graph.neighbors(A).collect::>(), vec![A, A, A, A]); +/// assert_eq!(condensed_graph.neighbors(B).collect::>(), vec![A, B, B, B, B]); +/// ``` +/// If `make_acyclic` is true, self-loops and multi edges are ignored: +/// +/// ```rust +/// # use petgraph::Graph; +/// # use petgraph::algo::condensation; +/// # use petgraph::prelude::*; +/// # +/// # let mut graph : Graph<(),(),Directed> = Graph::new(); +/// # let a = graph.add_node(()); // node with no weight +/// # let b = graph.add_node(()); +/// # let c = graph.add_node(()); +/// # let d = graph.add_node(()); +/// # let e = graph.add_node(()); +/// # let f = graph.add_node(()); +/// # let g = graph.add_node(()); +/// # let h = graph.add_node(()); +/// # +/// # graph.extend_with_edges(&[ +/// # (a, b), +/// # (b, c), +/// # (c, d), +/// # (d, a), +/// # (b, e), +/// # (e, f), +/// # (f, g), +/// # (g, h), +/// # (h, e) +/// # ]); +/// let acyclic_condensed_graph = condensation(graph, true); +/// let A = NodeIndex::new(0); +/// let B = NodeIndex::new(1); +/// assert_eq!(acyclic_condensed_graph.node_count(), 2); +/// assert_eq!(acyclic_condensed_graph.edge_count(), 1); +/// assert_eq!(acyclic_condensed_graph.neighbors(B).collect::>(), vec![A]); +/// ``` +pub fn condensation( + g: Graph, + make_acyclic: bool, +) -> Graph, E, Ty, Ix> +where + Ty: EdgeType, + Ix: IndexType, +{ + let sccs = kosaraju_scc(&g); + let mut condensed: Graph, E, Ty, Ix> = Graph::with_capacity(sccs.len(), g.edge_count()); + + // Build a map from old indices to new ones. + let mut node_map = vec![NodeIndex::end(); g.node_count()]; + for comp in sccs { + let new_nix = condensed.add_node(Vec::new()); + for nix in comp { + node_map[nix.index()] = new_nix; + } + } + + // Consume nodes and edges of the old graph and insert them into the new one. + let (nodes, edges) = g.into_nodes_edges(); + for (nix, node) in nodes.into_iter().enumerate() { + condensed[node_map[nix]].push(node.weight); + } + for edge in edges { + let source = node_map[edge.source().index()]; + let target = node_map[edge.target().index()]; + if make_acyclic { + if source != target { + condensed.update_edge(source, target, edge.weight); + } + } else { + condensed.add_edge(source, target, edge.weight); + } + } + condensed +} + +/// An algorithm error: a cycle was found in the graph. +#[derive(Clone, Debug, PartialEq)] +pub struct Cycle(pub(crate) N); + +impl Cycle { + /// Return a node id that participates in the cycle + pub fn node_id(&self) -> N + where + N: Copy, + { + self.0 + } +} + +/// An algorithm error: a cycle of negative weights was found in the graph. +#[derive(Clone, Debug, PartialEq)] +pub struct NegativeCycle(pub ()); + +/// Return `true` if the graph is bipartite. A graph is bipartite if its nodes can be divided into +/// two disjoint and indepedent sets U and V such that every edge connects U to one in V. This +/// algorithm implements 2-coloring algorithm based on the BFS algorithm. +/// +/// Always treats the input graph as if undirected. +pub fn is_bipartite_undirected(g: G, start: N) -> bool +where + G: GraphRef + Visitable + IntoNeighbors, + N: Copy + PartialEq + std::fmt::Debug, + VM: VisitMap, +{ + let mut red = g.visit_map(); + red.visit(start); + let mut blue = g.visit_map(); + + let mut stack = ::std::collections::VecDeque::new(); + stack.push_front(start); + + while let Some(node) = stack.pop_front() { + let is_red = red.is_visited(&node); + let is_blue = blue.is_visited(&node); + + assert!(is_red ^ is_blue); + + for neighbour in g.neighbors(node) { + let is_neigbour_red = red.is_visited(&neighbour); + let is_neigbour_blue = blue.is_visited(&neighbour); + + if (is_red && is_neigbour_red) || (is_blue && is_neigbour_blue) { + return false; + } + + if !is_neigbour_red && !is_neigbour_blue { + //hasn't been visited yet + + match (is_red, is_blue) { + (true, false) => { + blue.visit(neighbour); + } + (false, true) => { + red.visit(neighbour); + } + (_, _) => { + panic!("Invariant doesn't hold"); + } + } + + stack.push_back(neighbour); + } + } + } + + true +} + +use std::fmt::Debug; +use std::ops::Add; + +/// Associated data that can be used for measures (such as length). +pub trait Measure: Debug + PartialOrd + Add + Default + Clone {} + +impl Measure for M where M: Debug + PartialOrd + Add + Default + Clone {} + +/// A floating-point measure. +pub trait FloatMeasure: Measure + Copy { + fn zero() -> Self; + fn infinite() -> Self; +} + +impl FloatMeasure for f32 { + fn zero() -> Self { + 0. + } + fn infinite() -> Self { + 1. / 0. + } +} + +impl FloatMeasure for f64 { + fn zero() -> Self { + 0. + } + fn infinite() -> Self { + 1. / 0. + } +} + +pub trait BoundedMeasure: Measure + std::ops::Sub { + fn min() -> Self; + fn max() -> Self; + fn overflowing_add(self, rhs: Self) -> (Self, bool); +} + +macro_rules! impl_bounded_measure_integer( + ( $( $t:ident ),* ) => { + $( + impl BoundedMeasure for $t { + fn min() -> Self { + std::$t::MIN + } + + fn max() -> Self { + std::$t::MAX + } + + fn overflowing_add(self, rhs: Self) -> (Self, bool) { + self.overflowing_add(rhs) + } + } + )* + }; +); + +impl_bounded_measure_integer!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); + +macro_rules! impl_bounded_measure_float( + ( $( $t:ident ),* ) => { + $( + impl BoundedMeasure for $t { + fn min() -> Self { + std::$t::MIN + } + + fn max() -> Self { + std::$t::MAX + } + + fn overflowing_add(self, rhs: Self) -> (Self, bool) { + // for an overflow: a + b > max: both values need to be positive and a > max - b must be satisfied + let overflow = self > Self::default() && rhs > Self::default() && self > std::$t::MAX - rhs; + + // for an underflow: a + b < min: overflow can not happen and both values must be negative and a < min - b must be satisfied + let underflow = !overflow && self < Self::default() && rhs < Self::default() && self < std::$t::MIN - rhs; + + (self + rhs, overflow || underflow) + } + } + )* + }; +); + +impl_bounded_measure_float!(f32, f64); + +/// A floating-point measure that can be computed from `usize` +/// and with a default measure of proximity. +pub trait UnitMeasure: + Measure + + std::ops::Sub + + std::ops::Mul + + std::ops::Div + + std::iter::Sum +{ + fn zero() -> Self; + fn one() -> Self; + fn from_usize(nb: usize) -> Self; + fn default_tol() -> Self; +} + +macro_rules! impl_unit_measure( + ( $( $t:ident ),* )=> { + $( + impl UnitMeasure for $t { + fn zero() -> Self { + 0 as $t + } + fn one() -> Self { + 1 as $t + } + + fn from_usize(nb: usize) -> Self { + nb as $t + } + + fn default_tol() -> Self { + 1e-6 as $t + } + + } + + )* + } +); +impl_unit_measure!(f32, f64); + +/// Some measure of positive numbers, assuming positive +/// float-pointing numbers +pub trait PositiveMeasure: Measure + Copy { + fn zero() -> Self; + fn max() -> Self; +} + +macro_rules! impl_positive_measure( + ( $( $t:ident ),* )=> { + $( + impl PositiveMeasure for $t { + fn zero() -> Self { + 0 as $t + } + fn max() -> Self { + std::$t::MAX + } + } + + )* + } +); + +impl_positive_measure!(u8, u16, u32, u64, u128, usize, f32, f64); diff --git a/vendor/petgraph/src/algo/page_rank.rs b/vendor/petgraph/src/algo/page_rank.rs new file mode 100644 index 00000000..e859d905 --- /dev/null +++ b/vendor/petgraph/src/algo/page_rank.rs @@ -0,0 +1,185 @@ +use crate::visit::{EdgeRef, IntoEdges, NodeCount, NodeIndexable}; + +#[cfg(feature = "rayon")] +use rayon::prelude::*; + +use super::UnitMeasure; +/// \[Generic\] Page Rank algorithm. +/// +/// Computes the ranks of every node in a graph using the [Page Rank algorithm][pr]. +/// +/// Returns a `Vec` container mapping each node index to its rank. +/// +/// # Panics +/// The damping factor should be a number of type `f32` or `f64` between 0 and 1 (0 and 1 included). Otherwise, it panics. +/// +/// # Complexity +/// Time complexity is **O(N|V|²|E|)**. +/// Space complexity is **O(|V| + |E|)** +/// where **N** is the number of iterations, **|V|** the number of vertices (i.e nodes) and **|E|** the number of edges. +/// +/// [pr]: https://en.wikipedia.org/wiki/PageRank +/// +/// # Example +/// ```rust +/// use petgraph::Graph; +/// use petgraph::algo::page_rank; +/// let mut g: Graph<(), usize> = Graph::new(); +/// assert_eq!(page_rank(&g, 0.5_f64, 1), vec![]); // empty graphs have no node ranks. +/// let a = g.add_node(()); +/// let b = g.add_node(()); +/// let c = g.add_node(()); +/// let d = g.add_node(()); +/// let e = g.add_node(()); +/// g.extend_with_edges(&[(0, 1), (0, 3), (1, 2), (1, 3)]); +/// // With the following dot representation. +/// //digraph { +/// // 0 [ label = "()" ] +/// // 1 [ label = "()" ] +/// // 2 [ label = "()" ] +/// // 3 [ label = "()" ] +/// // 4 [ label = "()" ] +/// // 0 -> 1 [ label = "0.0" ] +/// // 0 -> 3 [ label = "0.0" ] +/// // 1 -> 2 [ label = "0.0" ] +/// // 1 -> 3 [ label = "0.0" ] +/// //} +/// let damping_factor = 0.7_f32; +/// let number_iterations = 10; +/// let output_ranks = page_rank(&g, damping_factor, number_iterations); +/// let expected_ranks = vec![0.14685437, 0.20267677, 0.22389607, 0.27971846, 0.14685437]; +/// assert_eq!(expected_ranks, output_ranks); +/// ``` +pub fn page_rank(graph: G, damping_factor: D, nb_iter: usize) -> Vec +where + G: NodeCount + IntoEdges + NodeIndexable, + D: UnitMeasure + Copy, +{ + let node_count = graph.node_count(); + if node_count == 0 { + return vec![]; + } + assert!( + D::zero() <= damping_factor && damping_factor <= D::one(), + "Damping factor should be between 0 et 1." + ); + let nb = D::from_usize(node_count); + let mut ranks = vec![D::one() / nb; node_count]; + let nodeix = |i| graph.from_index(i); + let out_degrees: Vec = (0..node_count) + .map(|i| graph.edges(nodeix(i)).map(|_| D::one()).sum::()) + .collect(); + + for _ in 0..nb_iter { + let pi = (0..node_count) + .enumerate() + .map(|(v, _)| { + ranks + .iter() + .enumerate() + .map(|(w, r)| { + let mut w_out_edges = graph.edges(nodeix(w)); + if w_out_edges.any(|e| e.target() == nodeix(v)) { + damping_factor * *r / out_degrees[w] + } else if out_degrees[w] == D::zero() { + damping_factor * *r / nb // stochastic matrix condition + } else { + (D::one() - damping_factor) * *r / nb // random jumps + } + }) + .sum::() + }) + .collect::>(); + let sum = pi.iter().copied().sum::(); + ranks = pi.iter().map(|r| *r / sum).collect::>(); + } + ranks +} + +#[allow(dead_code)] +fn out_edges_info(graph: G, index_w: usize, index_v: usize) -> (D, bool) +where + G: NodeCount + IntoEdges + NodeIndexable + std::marker::Sync, + D: UnitMeasure + Copy + std::marker::Send + std::marker::Sync, +{ + let node_w = graph.from_index(index_w); + let node_v = graph.from_index(index_v); + let mut out_edges = graph.edges(node_w); + let mut out_edge = out_edges.next(); + let mut out_degree = D::zero(); + let mut flag_points_to = false; + while let Some(edge) = out_edge { + out_degree = out_degree + D::one(); + if edge.target() == node_v { + flag_points_to = true; + } + out_edge = out_edges.next(); + } + (out_degree, flag_points_to) +} +/// \[Generic\] Parallel Page Rank algorithm. +/// +/// See [`page_rank`]. +#[cfg(feature = "rayon")] +pub fn parallel_page_rank( + graph: G, + damping_factor: D, + nb_iter: usize, + tol: Option, +) -> Vec +where + G: NodeCount + IntoEdges + NodeIndexable + std::marker::Sync, + D: UnitMeasure + Copy + std::marker::Send + std::marker::Sync, +{ + let node_count = graph.node_count(); + if node_count == 0 { + return vec![]; + } + assert!( + D::zero() <= damping_factor && damping_factor <= D::one(), + "Damping factor should be between 0 et 1." + ); + let mut tolerance = D::default_tol(); + if let Some(_tol) = tol { + tolerance = _tol; + } + let nb = D::from_usize(node_count); + let mut ranks: Vec = (0..node_count) + .into_par_iter() + .map(|_| D::one() / nb) + .collect(); + for _ in 0..nb_iter { + let pi = (0..node_count) + .into_par_iter() + .map(|v| { + ranks + .iter() + .enumerate() + .map(|(w, r)| { + let (out_deg, w_points_to_v) = out_edges_info(graph, w, v); + if w_points_to_v { + damping_factor * *r / out_deg + } else if out_deg == D::zero() { + damping_factor * *r / nb // stochastic matrix condition + } else { + (D::one() - damping_factor) * *r / nb // random jumps + } + }) + .sum::() + }) + .collect::>(); + let sum = pi.par_iter().map(|score| *score).sum::(); + let new_ranks = pi.par_iter().map(|r| *r / sum).collect::>(); + let squared_norm_2 = new_ranks + .par_iter() + .zip(&ranks) + .map(|(new, old)| (*new - *old) * (*new - *old)) + .sum::(); + if squared_norm_2 <= tolerance { + return ranks; + } else { + ranks = new_ranks; + } + } + ranks +} diff --git a/vendor/petgraph/src/algo/simple_paths.rs b/vendor/petgraph/src/algo/simple_paths.rs new file mode 100644 index 00000000..4169b95f --- /dev/null +++ b/vendor/petgraph/src/algo/simple_paths.rs @@ -0,0 +1,199 @@ +use std::{ + hash::Hash, + iter::{from_fn, FromIterator}, +}; + +use indexmap::IndexSet; + +use crate::{ + visit::{IntoNeighborsDirected, NodeCount}, + Direction::Outgoing, +}; + +/// Returns an iterator that produces all simple paths from `from` node to `to`, which contains at least `min_intermediate_nodes` nodes +/// and at most `max_intermediate_nodes`, if given, or limited by the graph's order otherwise. The simple path is a path without repetitions. +/// +/// This algorithm is adapted from . +/// +/// # Example +/// ``` +/// use petgraph::{algo, prelude::*}; +/// +/// let mut graph = DiGraph::<&str, i32>::new(); +/// +/// let a = graph.add_node("a"); +/// let b = graph.add_node("b"); +/// let c = graph.add_node("c"); +/// let d = graph.add_node("d"); +/// +/// graph.extend_with_edges(&[(a, b, 1), (b, c, 1), (c, d, 1), (a, b, 1), (b, d, 1)]); +/// +/// let paths = algo::all_simple_paths::, _>(&graph, a, d, 0, None) +/// .collect::>(); +/// +/// assert_eq!(paths.len(), 4); +/// +/// +/// // Take only 2 paths. +/// let paths = algo::all_simple_paths::, _>(&graph, a, d, 0, None) +/// .take(2) +/// .collect::>(); +/// +/// assert_eq!(paths.len(), 2); +/// +/// ``` +/// +/// # Note +/// +/// The number of simple paths between a given pair of vertices almost always grows exponentially, +/// reaching `O(V!)` on a dense graphs at `V` vertices. +/// +/// So if you have a large enough graph, be prepared to wait for the results for years. +/// Or consider extracting only part of the simple paths using the adapter [`Iterator::take`]. +pub fn all_simple_paths( + graph: G, + from: G::NodeId, + to: G::NodeId, + min_intermediate_nodes: usize, + max_intermediate_nodes: Option, +) -> impl Iterator +where + G: NodeCount, + G: IntoNeighborsDirected, + G::NodeId: Eq + Hash, + TargetColl: FromIterator, +{ + // how many nodes are allowed in simple path up to target node + // it is min/max allowed path length minus one, because it is more appropriate when implementing lookahead + // than constantly add 1 to length of current path + let max_length = if let Some(l) = max_intermediate_nodes { + l + 1 + } else { + graph.node_count() - 1 + }; + + let min_length = min_intermediate_nodes + 1; + + // list of visited nodes + let mut visited: IndexSet = IndexSet::from_iter(Some(from)); + // list of childs of currently exploring path nodes, + // last elem is list of childs of last visited node + let mut stack = vec![graph.neighbors_directed(from, Outgoing)]; + + from_fn(move || { + while let Some(children) = stack.last_mut() { + if let Some(child) = children.next() { + if visited.len() < max_length { + if child == to { + if visited.len() >= min_length { + let path = visited + .iter() + .cloned() + .chain(Some(to)) + .collect::(); + return Some(path); + } + } else if !visited.contains(&child) { + visited.insert(child); + stack.push(graph.neighbors_directed(child, Outgoing)); + } + } else { + if (child == to || children.any(|v| v == to)) && visited.len() >= min_length { + let path = visited + .iter() + .cloned() + .chain(Some(to)) + .collect::(); + return Some(path); + } + stack.pop(); + visited.pop(); + } + } else { + stack.pop(); + visited.pop(); + } + } + None + }) +} + +#[cfg(test)] +mod test { + use std::{collections::HashSet, iter::FromIterator}; + + use itertools::assert_equal; + + use crate::{dot::Dot, prelude::DiGraph}; + + use super::all_simple_paths; + + #[test] + fn test_all_simple_paths() { + let graph = DiGraph::::from_edges(&[ + (0, 1), + (0, 2), + (0, 3), + (1, 2), + (1, 3), + (2, 3), + (2, 4), + (3, 2), + (3, 4), + (4, 2), + (4, 5), + (5, 2), + (5, 3), + ]); + + let expexted_simple_paths_0_to_5 = vec![ + vec![0usize, 1, 2, 3, 4, 5], + vec![0, 1, 2, 4, 5], + vec![0, 1, 3, 2, 4, 5], + vec![0, 1, 3, 4, 5], + vec![0, 2, 3, 4, 5], + vec![0, 2, 4, 5], + vec![0, 3, 2, 4, 5], + vec![0, 3, 4, 5], + ]; + + println!("{}", Dot::new(&graph)); + let actual_simple_paths_0_to_5: HashSet> = + all_simple_paths(&graph, 0u32.into(), 5u32.into(), 0, None) + .map(|v: Vec<_>| v.into_iter().map(|i| i.index()).collect()) + .collect(); + assert_eq!(actual_simple_paths_0_to_5.len(), 8); + assert_eq!( + HashSet::from_iter(expexted_simple_paths_0_to_5), + actual_simple_paths_0_to_5 + ); + } + + #[test] + fn test_one_simple_path() { + let graph = DiGraph::::from_edges(&[(0, 1), (2, 1)]); + + let expexted_simple_paths_0_to_1 = &[vec![0usize, 1]]; + println!("{}", Dot::new(&graph)); + let actual_simple_paths_0_to_1: Vec> = + all_simple_paths(&graph, 0u32.into(), 1u32.into(), 0, None) + .map(|v: Vec<_>| v.into_iter().map(|i| i.index()).collect()) + .collect(); + + assert_eq!(actual_simple_paths_0_to_1.len(), 1); + assert_equal(expexted_simple_paths_0_to_1, &actual_simple_paths_0_to_1); + } + + #[test] + fn test_no_simple_paths() { + let graph = DiGraph::::from_edges(&[(0, 1), (2, 1)]); + + println!("{}", Dot::new(&graph)); + let actual_simple_paths_0_to_2: Vec> = + all_simple_paths(&graph, 0u32.into(), 2u32.into(), 0, None) + .map(|v: Vec<_>| v.into_iter().map(|i| i.index()).collect()) + .collect(); + + assert_eq!(actual_simple_paths_0_to_2.len(), 0); + } +} diff --git a/vendor/petgraph/src/algo/tred.rs b/vendor/petgraph/src/algo/tred.rs new file mode 100644 index 00000000..9fe080e1 --- /dev/null +++ b/vendor/petgraph/src/algo/tred.rs @@ -0,0 +1,162 @@ +//! Compute the transitive reduction and closure of a directed acyclic graph +//! +//! ## Transitive reduction and closure +//! The *transitive closure* of a graph **G = (V, E)** is the graph **Gc = (V, Ec)** +//! such that **(i, j)** belongs to **Ec** if and only if there is a path connecting +//! **i** to **j** in **G**. The *transitive reduction* of **G** is the graph **Gr +//! = (V, Er)** such that **Er** is minimal wrt. inclusion in **E** and the transitive +//! closure of **Gr** is the same as that of **G**. +//! The transitive reduction is well-defined for acyclic graphs only. + +use crate::adj::{List, UnweightedList}; +use crate::graph::IndexType; +use crate::visit::{ + GraphBase, IntoNeighbors, IntoNeighborsDirected, NodeCompactIndexable, NodeCount, +}; +use crate::Direction; +use fixedbitset::FixedBitSet; + +/// Creates a representation of the same graph respecting topological order for use in `tred::dag_transitive_reduction_closure`. +/// +/// `toposort` must be a topological order on the node indices of `g` (for example obtained +/// from [`toposort`]). +/// +/// [`toposort`]: ../fn.toposort.html +/// +/// Returns a pair of a graph `res` and the reciprocal of the topological sort `revmap`. +/// +/// `res` is the same graph as `g` with the following differences: +/// * Node and edge weights are stripped, +/// * Node indices are replaced by the corresponding rank in `toposort`, +/// * Iterating on the neighbors of a node respects topological order. +/// +/// `revmap` is handy to get back to map indices in `g` to indices in `res`. +/// ``` +/// use petgraph::prelude::*; +/// use petgraph::graph::DefaultIx; +/// use petgraph::visit::IntoNeighbors; +/// use petgraph::algo::tred::dag_to_toposorted_adjacency_list; +/// +/// let mut g = Graph::<&str, (), Directed, DefaultIx>::new(); +/// let second = g.add_node("second child"); +/// let top = g.add_node("top"); +/// let first = g.add_node("first child"); +/// g.extend_with_edges(&[(top, second), (top, first), (first, second)]); +/// +/// let toposort = vec![top, first, second]; +/// +/// let (res, revmap) = dag_to_toposorted_adjacency_list(&g, &toposort); +/// +/// // let's compute the children of top in topological order +/// let children: Vec = res +/// .neighbors(revmap[top.index()]) +/// .map(|ix: NodeIndex| toposort[ix.index()]) +/// .collect(); +/// assert_eq!(children, vec![first, second]) +/// ``` +/// +/// Runtime: **O(|V| + |E|)**. +/// +/// Space complexity: **O(|V| + |E|)**. +pub fn dag_to_toposorted_adjacency_list( + g: G, + toposort: &[G::NodeId], +) -> (UnweightedList, Vec) +where + G: GraphBase + IntoNeighborsDirected + NodeCompactIndexable + NodeCount, + G::NodeId: IndexType, +{ + let mut res = List::with_capacity(g.node_count()); + // map from old node index to rank in toposort + let mut revmap = vec![Ix::default(); g.node_bound()]; + for (ix, &old_ix) in toposort.iter().enumerate() { + let ix = Ix::new(ix); + revmap[old_ix.index()] = ix; + let iter = g.neighbors_directed(old_ix, Direction::Incoming); + let new_ix: Ix = res.add_node_with_capacity(iter.size_hint().0); + debug_assert_eq!(new_ix.index(), ix.index()); + for old_pre in iter { + let pre: Ix = revmap[old_pre.index()]; + res.add_edge(pre, ix, ()); + } + } + (res, revmap) +} + +/// Computes the transitive reduction and closure of a DAG. +/// +/// The algorithm implemented here comes from [On the calculation of +/// transitive reduction-closure of +/// orders](https://www.sciencedirect.com/science/article/pii/0012365X9390164O) by Habib, Morvan +/// and Rampon. +/// +/// The input graph must be in a very specific format: an adjacency +/// list such that: +/// * Node indices are a toposort, and +/// * The neighbors of all nodes are stored in topological order. +/// +/// To get such a representation, use the function [`dag_to_toposorted_adjacency_list`]. +/// +/// [`dag_to_toposorted_adjacency_list`]: ./fn.dag_to_toposorted_adjacency_list.html +/// +/// The output is the pair of the transitive reduction and the transitive closure. +/// +/// Runtime complexity: **O(|V| + \sum_{(x, y) \in Er} d(y))** where **d(y)** +/// denotes the outgoing degree of **y** in the transitive closure of **G**. +/// This is still **O(|V|³)** in the worst case like the naive algorithm but +/// should perform better for some classes of graphs. +/// +/// Space complexity: **O(|E|)**. +pub fn dag_transitive_reduction_closure( + g: &List, +) -> (UnweightedList, UnweightedList) { + let mut tred = List::with_capacity(g.node_count()); + let mut tclos = List::with_capacity(g.node_count()); + let mut mark = FixedBitSet::with_capacity(g.node_count()); + for i in g.node_indices() { + tred.add_node(); + tclos.add_node_with_capacity(g.neighbors(i).len()); + } + // the algorithm relies on this iterator being toposorted + for i in g.node_indices().rev() { + // the algorighm relies on this iterator being toposorted + for x in g.neighbors(i) { + if !mark[x.index()] { + tred.add_edge(i, x, ()); + tclos.add_edge(i, x, ()); + for e in tclos.edge_indices_from(x) { + let y = tclos.edge_endpoints(e).unwrap().1; + if !mark[y.index()] { + mark.insert(y.index()); + tclos.add_edge(i, y, ()); + } + } + } + } + for y in tclos.neighbors(i) { + mark.set(y.index(), false); + } + } + (tred, tclos) +} + +#[cfg(test)] +#[test] +fn test_easy_tred() { + let mut input = List::new(); + let a: u8 = input.add_node(); + let b = input.add_node(); + let c = input.add_node(); + input.add_edge(a, b, ()); + input.add_edge(a, c, ()); + input.add_edge(b, c, ()); + let (tred, tclos) = dag_transitive_reduction_closure(&input); + assert_eq!(tred.node_count(), 3); + assert_eq!(tclos.node_count(), 3); + assert!(tred.find_edge(a, b).is_some()); + assert!(tred.find_edge(b, c).is_some()); + assert!(tred.find_edge(a, c).is_none()); + assert!(tclos.find_edge(a, b).is_some()); + assert!(tclos.find_edge(b, c).is_some()); + assert!(tclos.find_edge(a, c).is_some()); +} diff --git a/vendor/petgraph/src/csr.rs b/vendor/petgraph/src/csr.rs new file mode 100644 index 00000000..b4c1f3a0 --- /dev/null +++ b/vendor/petgraph/src/csr.rs @@ -0,0 +1,1151 @@ +//! Compressed Sparse Row (CSR) is a sparse adjacency matrix graph. + +use std::cmp::{max, Ordering}; +use std::iter::{Enumerate, Zip}; +use std::marker::PhantomData; +use std::ops::{Index, IndexMut, Range}; +use std::slice::Windows; + +use crate::visit::{ + Data, EdgeCount, EdgeRef, GetAdjacencyMatrix, GraphBase, GraphProp, IntoEdgeReferences, + IntoEdges, IntoNeighbors, IntoNodeIdentifiers, IntoNodeReferences, NodeCompactIndexable, + NodeCount, NodeIndexable, Visitable, +}; + +use crate::util::zip; + +#[doc(no_inline)] +pub use crate::graph::{DefaultIx, IndexType}; + +use crate::{Directed, EdgeType, IntoWeightedEdge}; + +/// Csr node index type, a plain integer. +pub type NodeIndex = Ix; +/// Csr edge index type, a plain integer. +pub type EdgeIndex = usize; + +const BINARY_SEARCH_CUTOFF: usize = 32; + +/// Compressed Sparse Row ([`CSR`]) is a sparse adjacency matrix graph. +/// +/// `CSR` is parameterized over: +/// +/// - Associated data `N` for nodes and `E` for edges, called *weights*. +/// The associated data can be of arbitrary type. +/// - Edge type `Ty` that determines whether the graph edges are directed or undirected. +/// - Index type `Ix`, which determines the maximum size of the graph. +/// +/// +/// Using **O(|E| + |V|)** space. +/// +/// Self loops are allowed, no parallel edges. +/// +/// Fast iteration of the outgoing edges of a vertex. +/// +/// [`CSR`]: https://en.wikipedia.org/wiki/Sparse_matrix#Compressed_sparse_row_(CSR,_CRS_or_Yale_format) +#[derive(Debug)] +pub struct Csr { + /// Column of next edge + column: Vec>, + /// weight of each edge; lock step with column + edges: Vec, + /// Index of start of row Always node_count + 1 long. + /// Last element is always equal to column.len() + row: Vec, + node_weights: Vec, + edge_count: usize, + ty: PhantomData, +} + +impl Default for Csr +where + Ty: EdgeType, + Ix: IndexType, +{ + fn default() -> Self { + Self::new() + } +} + +impl Clone for Csr { + fn clone(&self) -> Self { + Csr { + column: self.column.clone(), + edges: self.edges.clone(), + row: self.row.clone(), + node_weights: self.node_weights.clone(), + edge_count: self.edge_count, + ty: self.ty, + } + } +} + +impl Csr +where + Ty: EdgeType, + Ix: IndexType, +{ + /// Create an empty `Csr`. + pub fn new() -> Self { + Csr { + column: vec![], + edges: vec![], + row: vec![0; 1], + node_weights: vec![], + edge_count: 0, + ty: PhantomData, + } + } + + /// Create a new `Csr` with `n` nodes. `N` must implement [`Default`] for the weight of each node. + /// + /// [`Default`]: https://doc.rust-lang.org/nightly/core/default/trait.Default.html + /// + /// # Example + /// ```rust + /// use petgraph::csr::Csr; + /// use petgraph::prelude::*; + /// + /// let graph = Csr::::with_nodes(5); + /// assert_eq!(graph.node_count(),5); + /// assert_eq!(graph.edge_count(),0); + /// + /// assert_eq!(graph[0],0); + /// assert_eq!(graph[4],0); + /// ``` + pub fn with_nodes(n: usize) -> Self + where + N: Default, + { + Csr { + column: Vec::new(), + edges: Vec::new(), + row: vec![0; n + 1], + node_weights: (0..n).map(|_| N::default()).collect(), + edge_count: 0, + ty: PhantomData, + } + } +} + +/// Csr creation error: edges were not in sorted order. +#[derive(Clone, Debug)] +pub struct EdgesNotSorted { + #[allow(unused)] + first_error: (usize, usize), +} + +impl Csr +where + Ix: IndexType, +{ + /// Create a new `Csr` from a sorted sequence of edges + /// + /// Edges **must** be sorted and unique, where the sort order is the default + /// order for the pair *(u, v)* in Rust (*u* has priority). + /// + /// Computes in **O(|E| + |V|)** time. + /// # Example + /// ```rust + /// use petgraph::csr::Csr; + /// use petgraph::prelude::*; + /// + /// let graph = Csr::<(),()>::from_sorted_edges(&[ + /// (0, 1), (0, 2), + /// (1, 0), (1, 2), (1, 3), + /// (2, 0), + /// (3, 1), + /// ]); + /// ``` + pub fn from_sorted_edges(edges: &[Edge]) -> Result + where + Edge: Clone + IntoWeightedEdge>, + N: Default, + { + let max_node_id = match edges + .iter() + .map(|edge| { + let (x, y, _) = edge.clone().into_weighted_edge(); + max(x.index(), y.index()) + }) + .max() + { + None => return Ok(Self::with_nodes(0)), + Some(x) => x, + }; + let mut self_ = Self::with_nodes(max_node_id + 1); + let mut iter = edges.iter().cloned().peekable(); + { + let mut rows = self_.row.iter_mut(); + + let mut rstart = 0; + let mut last_target; + 'outer: for (node, r) in (&mut rows).enumerate() { + *r = rstart; + last_target = None; + 'inner: loop { + if let Some(edge) = iter.peek() { + let (n, m, weight) = edge.clone().into_weighted_edge(); + // check that the edges are in increasing sequence + if node > n.index() { + return Err(EdgesNotSorted { + first_error: (n.index(), m.index()), + }); + } + /* + debug_assert!(node <= n.index(), + concat!("edges are not sorted, ", + "failed assertion source {:?} <= {:?} ", + "for edge {:?}"), + node, n, (n, m)); + */ + if n.index() != node { + break 'inner; + } + // check that the edges are in increasing sequence + /* + debug_assert!(last_target.map_or(true, |x| m > x), + "edges are not sorted, failed assertion {:?} < {:?}", + last_target, m); + */ + if !last_target.map_or(true, |x| m > x) { + return Err(EdgesNotSorted { + first_error: (n.index(), m.index()), + }); + } + last_target = Some(m); + self_.column.push(m); + self_.edges.push(weight); + rstart += 1; + } else { + break 'outer; + } + iter.next(); + } + } + for r in rows { + *r = rstart; + } + } + + Ok(self_) + } +} + +impl Csr +where + Ty: EdgeType, + Ix: IndexType, +{ + pub fn node_count(&self) -> usize { + self.row.len() - 1 + } + + pub fn edge_count(&self) -> usize { + if self.is_directed() { + self.column.len() + } else { + self.edge_count + } + } + + pub fn is_directed(&self) -> bool { + Ty::is_directed() + } + + /// Remove all edges + pub fn clear_edges(&mut self) { + self.column.clear(); + self.edges.clear(); + for r in &mut self.row { + *r = 0; + } + if !self.is_directed() { + self.edge_count = 0; + } + } + + /// Adds a new node with the given weight, returning the corresponding node index. + pub fn add_node(&mut self, weight: N) -> NodeIndex { + let i = self.row.len() - 1; + self.row.insert(i, self.column.len()); + self.node_weights.insert(i, weight); + Ix::new(i) + } + + /// Return `true` if the edge was added + /// + /// If you add all edges in row-major order, the time complexity + /// is **O(|V|·|E|)** for the whole operation. + /// + /// **Panics** if `a` or `b` are out of bounds. + pub fn add_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> bool + where + E: Clone, + { + let ret = self.add_edge_(a, b, weight.clone()); + if ret && !self.is_directed() { + self.edge_count += 1; + } + if ret && !self.is_directed() && a != b { + let _ret2 = self.add_edge_(b, a, weight); + debug_assert_eq!(ret, _ret2); + } + ret + } + + // Return false if the edge already exists + fn add_edge_(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> bool { + assert!(a.index() < self.node_count() && b.index() < self.node_count()); + // a x b is at (a, b) in the matrix + + // find current range of edges from a + let pos = match self.find_edge_pos(a, b) { + Ok(_) => return false, /* already exists */ + Err(i) => i, + }; + self.column.insert(pos, b); + self.edges.insert(pos, weight); + // update row vector + for r in &mut self.row[a.index() + 1..] { + *r += 1; + } + true + } + + fn find_edge_pos(&self, a: NodeIndex, b: NodeIndex) -> Result { + let (index, neighbors) = self.neighbors_of(a); + if neighbors.len() < BINARY_SEARCH_CUTOFF { + for (i, elt) in neighbors.iter().enumerate() { + match elt.cmp(&b) { + Ordering::Equal => return Ok(i + index), + Ordering::Greater => return Err(i + index), + Ordering::Less => {} + } + } + Err(neighbors.len() + index) + } else { + match neighbors.binary_search(&b) { + Ok(i) => Ok(i + index), + Err(i) => Err(i + index), + } + } + } + + /// Computes in **O(log |V|)** time. + /// + /// **Panics** if the node `a` does not exist. + pub fn contains_edge(&self, a: NodeIndex, b: NodeIndex) -> bool { + self.find_edge_pos(a, b).is_ok() + } + + fn neighbors_range(&self, a: NodeIndex) -> Range { + let index = self.row[a.index()]; + let end = self + .row + .get(a.index() + 1) + .cloned() + .unwrap_or(self.column.len()); + index..end + } + + fn neighbors_of(&self, a: NodeIndex) -> (usize, &[Ix]) { + let r = self.neighbors_range(a); + (r.start, &self.column[r]) + } + + /// Computes in **O(1)** time. + /// + /// **Panics** if the node `a` does not exist. + pub fn out_degree(&self, a: NodeIndex) -> usize { + let r = self.neighbors_range(a); + r.end - r.start + } + + /// Computes in **O(1)** time. + /// + /// **Panics** if the node `a` does not exist. + pub fn neighbors_slice(&self, a: NodeIndex) -> &[NodeIndex] { + self.neighbors_of(a).1 + } + + /// Computes in **O(1)** time. + /// + /// **Panics** if the node `a` does not exist. + pub fn edges_slice(&self, a: NodeIndex) -> &[E] { + &self.edges[self.neighbors_range(a)] + } + + /// Return an iterator of all edges of `a`. + /// + /// - `Directed`: Outgoing edges from `a`. + /// - `Undirected`: All edges connected to `a`. + /// + /// **Panics** if the node `a` does not exist.
+ /// Iterator element type is `EdgeReference`. + pub fn edges(&self, a: NodeIndex) -> Edges { + let r = self.neighbors_range(a); + Edges { + index: r.start, + source: a, + iter: zip(&self.column[r.clone()], &self.edges[r]), + ty: self.ty, + } + } +} + +#[derive(Clone, Debug)] +pub struct Edges<'a, E: 'a, Ty = Directed, Ix: 'a = DefaultIx> { + index: usize, + source: NodeIndex, + iter: Zip>, SliceIter<'a, E>>, + ty: PhantomData, +} + +#[derive(Debug)] +pub struct EdgeReference<'a, E: 'a, Ty, Ix: 'a = DefaultIx> { + index: EdgeIndex, + source: NodeIndex, + target: NodeIndex, + weight: &'a E, + ty: PhantomData, +} + +impl Clone for EdgeReference<'_, E, Ty, Ix> { + fn clone(&self) -> Self { + *self + } +} + +impl Copy for EdgeReference<'_, E, Ty, Ix> {} + +impl<'a, Ty, E, Ix> EdgeReference<'a, E, Ty, Ix> +where + Ty: EdgeType, +{ + /// Access the edge’s weight. + /// + /// **NOTE** that this method offers a longer lifetime + /// than the trait (unfortunately they don't match yet). + pub fn weight(&self) -> &'a E { + self.weight + } +} + +impl EdgeRef for EdgeReference<'_, E, Ty, Ix> +where + Ty: EdgeType, + Ix: IndexType, +{ + type NodeId = NodeIndex; + type EdgeId = EdgeIndex; + type Weight = E; + + fn source(&self) -> Self::NodeId { + self.source + } + fn target(&self) -> Self::NodeId { + self.target + } + fn weight(&self) -> &E { + self.weight + } + fn id(&self) -> Self::EdgeId { + self.index + } +} + +impl<'a, E, Ty, Ix> Iterator for Edges<'a, E, Ty, Ix> +where + Ty: EdgeType, + Ix: IndexType, +{ + type Item = EdgeReference<'a, E, Ty, Ix>; + fn next(&mut self) -> Option { + self.iter.next().map(move |(&j, w)| { + let index = self.index; + self.index += 1; + EdgeReference { + index, + source: self.source, + target: j, + weight: w, + ty: PhantomData, + } + }) + } + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +impl Data for Csr +where + Ty: EdgeType, + Ix: IndexType, +{ + type NodeWeight = N; + type EdgeWeight = E; +} + +impl<'a, N, E, Ty, Ix> IntoEdgeReferences for &'a Csr +where + Ty: EdgeType, + Ix: IndexType, +{ + type EdgeRef = EdgeReference<'a, E, Ty, Ix>; + type EdgeReferences = EdgeReferences<'a, E, Ty, Ix>; + fn edge_references(self) -> Self::EdgeReferences { + EdgeReferences { + index: 0, + source_index: Ix::new(0), + edge_ranges: self.row.windows(2).enumerate(), + column: &self.column, + edges: &self.edges, + iter: zip(&[], &[]), + ty: self.ty, + } + } +} + +#[derive(Debug, Clone)] +pub struct EdgeReferences<'a, E: 'a, Ty, Ix: 'a> { + source_index: NodeIndex, + index: usize, + edge_ranges: Enumerate>, + column: &'a [NodeIndex], + edges: &'a [E], + iter: Zip>, SliceIter<'a, E>>, + ty: PhantomData, +} + +impl<'a, E, Ty, Ix> Iterator for EdgeReferences<'a, E, Ty, Ix> +where + Ty: EdgeType, + Ix: IndexType, +{ + type Item = EdgeReference<'a, E, Ty, Ix>; + fn next(&mut self) -> Option { + loop { + if let Some((&j, w)) = self.iter.next() { + let index = self.index; + self.index += 1; + return Some(EdgeReference { + index, + source: self.source_index, + target: j, + weight: w, + ty: PhantomData, + }); + } + if let Some((i, w)) = self.edge_ranges.next() { + let a = w[0]; + let b = w[1]; + self.iter = zip(&self.column[a..b], &self.edges[a..b]); + self.source_index = Ix::new(i); + } else { + return None; + } + } + } +} + +impl<'a, N, E, Ty, Ix> IntoEdges for &'a Csr +where + Ty: EdgeType, + Ix: IndexType, +{ + type Edges = Edges<'a, E, Ty, Ix>; + fn edges(self, a: Self::NodeId) -> Self::Edges { + self.edges(a) + } +} + +impl GraphBase for Csr +where + Ty: EdgeType, + Ix: IndexType, +{ + type NodeId = NodeIndex; + type EdgeId = EdgeIndex; // index into edges vector +} + +use fixedbitset::FixedBitSet; + +impl Visitable for Csr +where + Ty: EdgeType, + Ix: IndexType, +{ + type Map = FixedBitSet; + fn visit_map(&self) -> FixedBitSet { + FixedBitSet::with_capacity(self.node_count()) + } + fn reset_map(&self, map: &mut Self::Map) { + map.clear(); + map.grow(self.node_count()); + } +} + +use std::slice::Iter as SliceIter; + +#[derive(Clone, Debug)] +pub struct Neighbors<'a, Ix: 'a = DefaultIx> { + iter: SliceIter<'a, NodeIndex>, +} + +impl Iterator for Neighbors<'_, Ix> +where + Ix: IndexType, +{ + type Item = NodeIndex; + + fn next(&mut self) -> Option { + self.iter.next().cloned() + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +impl<'a, N, E, Ty, Ix> IntoNeighbors for &'a Csr +where + Ty: EdgeType, + Ix: IndexType, +{ + type Neighbors = Neighbors<'a, Ix>; + + /// Return an iterator of all neighbors of `a`. + /// + /// - `Directed`: Targets of outgoing edges from `a`. + /// - `Undirected`: Opposing endpoints of all edges connected to `a`. + /// + /// **Panics** if the node `a` does not exist.
+ /// Iterator element type is `NodeIndex`. + fn neighbors(self, a: Self::NodeId) -> Self::Neighbors { + Neighbors { + iter: self.neighbors_slice(a).iter(), + } + } +} + +impl NodeIndexable for Csr +where + Ty: EdgeType, + Ix: IndexType, +{ + fn node_bound(&self) -> usize { + self.node_count() + } + fn to_index(&self, a: Self::NodeId) -> usize { + a.index() + } + fn from_index(&self, ix: usize) -> Self::NodeId { + Ix::new(ix) + } +} + +impl NodeCompactIndexable for Csr +where + Ty: EdgeType, + Ix: IndexType, +{ +} + +impl Index> for Csr +where + Ty: EdgeType, + Ix: IndexType, +{ + type Output = N; + + fn index(&self, ix: NodeIndex) -> &N { + &self.node_weights[ix.index()] + } +} + +impl IndexMut> for Csr +where + Ty: EdgeType, + Ix: IndexType, +{ + fn index_mut(&mut self, ix: NodeIndex) -> &mut N { + &mut self.node_weights[ix.index()] + } +} + +#[derive(Debug, Clone)] +pub struct NodeIdentifiers { + r: Range, + ty: PhantomData, +} + +impl Iterator for NodeIdentifiers +where + Ix: IndexType, +{ + type Item = NodeIndex; + + fn next(&mut self) -> Option { + self.r.next().map(Ix::new) + } + + fn size_hint(&self) -> (usize, Option) { + self.r.size_hint() + } +} + +impl IntoNodeIdentifiers for &Csr +where + Ty: EdgeType, + Ix: IndexType, +{ + type NodeIdentifiers = NodeIdentifiers; + fn node_identifiers(self) -> Self::NodeIdentifiers { + NodeIdentifiers { + r: 0..self.node_count(), + ty: PhantomData, + } + } +} + +impl NodeCount for Csr +where + Ty: EdgeType, + Ix: IndexType, +{ + fn node_count(&self) -> usize { + (*self).node_count() + } +} + +impl EdgeCount for Csr +where + Ty: EdgeType, + Ix: IndexType, +{ + #[inline] + fn edge_count(&self) -> usize { + self.edge_count() + } +} + +impl GraphProp for Csr +where + Ty: EdgeType, + Ix: IndexType, +{ + type EdgeType = Ty; +} + +impl<'a, N, E, Ty, Ix> IntoNodeReferences for &'a Csr +where + Ty: EdgeType, + Ix: IndexType, +{ + type NodeRef = (NodeIndex, &'a N); + type NodeReferences = NodeReferences<'a, N, Ix>; + fn node_references(self) -> Self::NodeReferences { + NodeReferences { + iter: self.node_weights.iter().enumerate(), + ty: PhantomData, + } + } +} + +/// Iterator over all nodes of a graph. +#[derive(Debug, Clone)] +pub struct NodeReferences<'a, N: 'a, Ix: IndexType = DefaultIx> { + iter: Enumerate>, + ty: PhantomData, +} + +impl<'a, N, Ix> Iterator for NodeReferences<'a, N, Ix> +where + Ix: IndexType, +{ + type Item = (NodeIndex, &'a N); + + fn next(&mut self) -> Option { + self.iter.next().map(|(i, weight)| (Ix::new(i), weight)) + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +impl DoubleEndedIterator for NodeReferences<'_, N, Ix> +where + Ix: IndexType, +{ + fn next_back(&mut self) -> Option { + self.iter + .next_back() + .map(|(i, weight)| (Ix::new(i), weight)) + } +} + +impl ExactSizeIterator for NodeReferences<'_, N, Ix> where Ix: IndexType {} + +/// The adjacency matrix for **Csr** is a bitmap that's computed by +/// `.adjacency_matrix()`. +impl GetAdjacencyMatrix for &Csr +where + Ix: IndexType, + Ty: EdgeType, +{ + type AdjMatrix = FixedBitSet; + + fn adjacency_matrix(&self) -> FixedBitSet { + let n = self.node_count(); + let mut matrix = FixedBitSet::with_capacity(n * n); + for edge in self.edge_references() { + let i = n * edge.source().index() + edge.target().index(); + matrix.put(i); + + if !self.is_directed() { + let j = edge.source().index() + n * edge.target().index(); + matrix.put(j); + } + } + matrix + } + + fn is_adjacent(&self, matrix: &FixedBitSet, a: NodeIndex, b: NodeIndex) -> bool { + let n = self.node_count(); + let index = n * a.index() + b.index(); + matrix.contains(index) + } +} + +/* + * +Example + +[ a 0 b + c d e + 0 0 f ] + +Values: [a, b, c, d, e, f] +Column: [0, 2, 0, 1, 2, 2] +Row : [0, 2, 5] <- value index of row start + + * */ + +#[cfg(test)] +mod tests { + use super::Csr; + use crate::algo::bellman_ford; + use crate::algo::find_negative_cycle; + use crate::algo::tarjan_scc; + use crate::visit::Dfs; + use crate::visit::VisitMap; + use crate::Undirected; + + #[test] + fn csr1() { + let mut m: Csr = Csr::with_nodes(3); + m.add_edge(0, 0, ()); + m.add_edge(1, 2, ()); + m.add_edge(2, 2, ()); + m.add_edge(0, 2, ()); + m.add_edge(1, 0, ()); + m.add_edge(1, 1, ()); + println!("{:?}", m); + assert_eq!(&m.column, &[0, 2, 0, 1, 2, 2]); + assert_eq!(&m.row, &[0, 2, 5, 6]); + + let added = m.add_edge(1, 2, ()); + assert!(!added); + assert_eq!(&m.column, &[0, 2, 0, 1, 2, 2]); + assert_eq!(&m.row, &[0, 2, 5, 6]); + + assert_eq!(m.neighbors_slice(1), &[0, 1, 2]); + assert_eq!(m.node_count(), 3); + assert_eq!(m.edge_count(), 6); + } + + #[test] + fn csr_undirected() { + /* + [ 1 . 1 + . . 1 + 1 1 1 ] + */ + + let mut m: Csr<(), (), Undirected> = Csr::with_nodes(3); + m.add_edge(0, 0, ()); + m.add_edge(0, 2, ()); + m.add_edge(1, 2, ()); + m.add_edge(2, 2, ()); + println!("{:?}", m); + assert_eq!(&m.column, &[0, 2, 2, 0, 1, 2]); + assert_eq!(&m.row, &[0, 2, 3, 6]); + assert_eq!(m.node_count(), 3); + assert_eq!(m.edge_count(), 4); + } + + #[should_panic] + #[test] + fn csr_from_error_1() { + // not sorted in source + let m: Csr = Csr::from_sorted_edges(&[(0, 1), (1, 0), (0, 2)]).unwrap(); + println!("{:?}", m); + } + + #[should_panic] + #[test] + fn csr_from_error_2() { + // not sorted in target + let m: Csr = Csr::from_sorted_edges(&[(0, 1), (1, 0), (1, 2), (1, 1)]).unwrap(); + println!("{:?}", m); + } + + #[test] + fn csr_from() { + let m: Csr = + Csr::from_sorted_edges(&[(0, 1), (0, 2), (1, 0), (1, 1), (2, 2), (2, 4)]).unwrap(); + println!("{:?}", m); + assert_eq!(m.neighbors_slice(0), &[1, 2]); + assert_eq!(m.neighbors_slice(1), &[0, 1]); + assert_eq!(m.neighbors_slice(2), &[2, 4]); + assert_eq!(m.node_count(), 5); + assert_eq!(m.edge_count(), 6); + } + + #[test] + fn csr_dfs() { + let mut m: Csr = Csr::from_sorted_edges(&[ + (0, 1), + (0, 2), + (1, 0), + (1, 1), + (1, 3), + (2, 2), + // disconnected subgraph + (4, 4), + (4, 5), + ]) + .unwrap(); + println!("{:?}", m); + let mut dfs = Dfs::new(&m, 0); + while dfs.next(&m).is_some() {} + for i in 0..m.node_count() - 2 { + assert!(dfs.discovered.is_visited(&i), "visited {}", i) + } + assert!(!dfs.discovered[4]); + assert!(!dfs.discovered[5]); + + m.add_edge(1, 4, ()); + println!("{:?}", m); + + dfs.reset(&m); + dfs.move_to(0); + while dfs.next(&m).is_some() {} + + for i in 0..m.node_count() { + assert!(dfs.discovered[i], "visited {}", i) + } + } + + #[test] + fn csr_tarjan() { + let m: Csr = Csr::from_sorted_edges(&[ + (0, 1), + (0, 2), + (1, 0), + (1, 1), + (1, 3), + (2, 2), + (2, 4), + (4, 4), + (4, 5), + (5, 2), + ]) + .unwrap(); + println!("{:?}", m); + println!("{:?}", tarjan_scc(&m)); + } + + #[test] + fn test_bellman_ford() { + let m: Csr<(), _> = Csr::from_sorted_edges(&[ + (0, 1, 0.5), + (0, 2, 2.), + (1, 0, 1.), + (1, 1, 1.), + (1, 2, 1.), + (1, 3, 1.), + (2, 3, 3.), + (4, 5, 1.), + (5, 7, 2.), + (6, 7, 1.), + (7, 8, 3.), + ]) + .unwrap(); + println!("{:?}", m); + let result = bellman_ford(&m, 0).unwrap(); + println!("{:?}", result); + let answer = [0., 0.5, 1.5, 1.5]; + assert_eq!(&answer, &result.distances[..4]); + assert!(result.distances[4..].iter().all(|&x| f64::is_infinite(x))); + } + + #[test] + fn test_bellman_ford_neg_cycle() { + let m: Csr<(), _> = Csr::from_sorted_edges(&[ + (0, 1, 0.5), + (0, 2, 2.), + (1, 0, 1.), + (1, 1, -1.), + (1, 2, 1.), + (1, 3, 1.), + (2, 3, 3.), + ]) + .unwrap(); + let result = bellman_ford(&m, 0); + assert!(result.is_err()); + } + + #[test] + fn test_find_neg_cycle1() { + let m: Csr<(), _> = Csr::from_sorted_edges(&[ + (0, 1, 0.5), + (0, 2, 2.), + (1, 0, 1.), + (1, 1, -1.), + (1, 2, 1.), + (1, 3, 1.), + (2, 3, 3.), + ]) + .unwrap(); + let result = find_negative_cycle(&m, 0); + assert_eq!(result, Some([1].to_vec())); + } + + #[test] + fn test_find_neg_cycle2() { + let m: Csr<(), _> = Csr::from_sorted_edges(&[ + (0, 1, 0.5), + (0, 2, 2.), + (1, 0, 1.), + (1, 2, 1.), + (1, 3, 1.), + (2, 3, 3.), + ]) + .unwrap(); + let result = find_negative_cycle(&m, 0); + assert_eq!(result, None); + } + + #[test] + fn test_find_neg_cycle3() { + let m: Csr<(), _> = Csr::from_sorted_edges(&[ + (0, 1, 1.), + (0, 2, 1.), + (0, 3, 1.), + (1, 3, 1.), + (2, 1, 1.), + (3, 2, -3.), + ]) + .unwrap(); + let result = find_negative_cycle(&m, 0); + assert_eq!(result, Some([1, 3, 2].to_vec())); + } + + #[test] + fn test_find_neg_cycle4() { + let m: Csr<(), _> = Csr::from_sorted_edges(&[(0, 0, -1.)]).unwrap(); + let result = find_negative_cycle(&m, 0); + assert_eq!(result, Some([0].to_vec())); + } + + #[test] + fn test_edge_references() { + use crate::visit::EdgeRef; + use crate::visit::IntoEdgeReferences; + let m: Csr<(), _> = Csr::from_sorted_edges(&[ + (0, 1, 0.5), + (0, 2, 2.), + (1, 0, 1.), + (1, 1, 1.), + (1, 2, 1.), + (1, 3, 1.), + (2, 3, 3.), + (4, 5, 1.), + (5, 7, 2.), + (6, 7, 1.), + (7, 8, 3.), + ]) + .unwrap(); + let mut copy = Vec::new(); + for e in m.edge_references() { + copy.push((e.source(), e.target(), *e.weight())); + println!("{:?}", e); + } + let m2: Csr<(), _> = Csr::from_sorted_edges(©).unwrap(); + assert_eq!(&m.row, &m2.row); + assert_eq!(&m.column, &m2.column); + assert_eq!(&m.edges, &m2.edges); + } + + #[test] + fn test_add_node() { + let mut g: Csr = Csr::new(); + let a = g.add_node(()); + let b = g.add_node(()); + let c = g.add_node(()); + + assert!(g.add_edge(a, b, ())); + assert!(g.add_edge(b, c, ())); + assert!(g.add_edge(c, a, ())); + + println!("{:?}", g); + + assert_eq!(g.node_count(), 3); + + assert_eq!(g.neighbors_slice(a), &[b]); + assert_eq!(g.neighbors_slice(b), &[c]); + assert_eq!(g.neighbors_slice(c), &[a]); + + assert_eq!(g.edge_count(), 3); + } + + #[test] + fn test_add_node_with_existing_edges() { + let mut g: Csr = Csr::new(); + let a = g.add_node(()); + let b = g.add_node(()); + + assert!(g.add_edge(a, b, ())); + + let c = g.add_node(()); + + println!("{:?}", g); + + assert_eq!(g.node_count(), 3); + + assert_eq!(g.neighbors_slice(a), &[b]); + assert_eq!(g.neighbors_slice(b), &[]); + assert_eq!(g.neighbors_slice(c), &[]); + + assert_eq!(g.edge_count(), 1); + } + + #[test] + fn test_node_references() { + use crate::visit::IntoNodeReferences; + let mut g: Csr = Csr::new(); + g.add_node(42); + g.add_node(3); + g.add_node(44); + + let mut refs = g.node_references(); + assert_eq!(refs.next(), Some((0, &42))); + assert_eq!(refs.next(), Some((1, &3))); + assert_eq!(refs.next(), Some((2, &44))); + assert_eq!(refs.next(), None); + } +} diff --git a/vendor/petgraph/src/data.rs b/vendor/petgraph/src/data.rs new file mode 100644 index 00000000..90d25ebc --- /dev/null +++ b/vendor/petgraph/src/data.rs @@ -0,0 +1,478 @@ +//! Graph traits for associated data and graph construction. + +use crate::graph::IndexType; +#[cfg(feature = "graphmap")] +use crate::graphmap::{GraphMap, NodeTrait}; +#[cfg(feature = "stable_graph")] +use crate::stable_graph::StableGraph; +use crate::visit::{Data, NodeCount, NodeIndexable, Reversed}; +use crate::EdgeType; +use crate::Graph; + +trait_template! { + /// Access node and edge weights (associated data). +#[allow(clippy::needless_arbitrary_self_type)] +pub trait DataMap : Data { + @section self + fn node_weight(self: &Self, id: Self::NodeId) -> Option<&Self::NodeWeight>; + fn edge_weight(self: &Self, id: Self::EdgeId) -> Option<&Self::EdgeWeight>; +} +} + +macro_rules! access0 { + ($e:expr) => { + $e.0 + }; +} + +DataMap! {delegate_impl []} +DataMap! {delegate_impl [['a, G], G, &'a mut G, deref_twice]} +DataMap! {delegate_impl [[G], G, Reversed, access0]} + +trait_template! { + /// Access node and edge weights mutably. +#[allow(clippy::needless_arbitrary_self_type)] +pub trait DataMapMut : DataMap { + @section self + fn node_weight_mut(self: &mut Self, id: Self::NodeId) -> Option<&mut Self::NodeWeight>; + fn edge_weight_mut(self: &mut Self, id: Self::EdgeId) -> Option<&mut Self::EdgeWeight>; +} +} + +DataMapMut! {delegate_impl [['a, G], G, &'a mut G, deref_twice]} +DataMapMut! {delegate_impl [[G], G, Reversed, access0]} + +/// A graph that can be extended with further nodes and edges +pub trait Build: Data + NodeCount { + fn add_node(&mut self, weight: Self::NodeWeight) -> Self::NodeId; + /// Add a new edge. If parallel edges (duplicate) are not allowed and + /// the edge already exists, return `None`. + fn add_edge( + &mut self, + a: Self::NodeId, + b: Self::NodeId, + weight: Self::EdgeWeight, + ) -> Option { + Some(self.update_edge(a, b, weight)) + } + /// Add or update the edge from `a` to `b`. Return the id of the affected + /// edge. + fn update_edge( + &mut self, + a: Self::NodeId, + b: Self::NodeId, + weight: Self::EdgeWeight, + ) -> Self::EdgeId; +} + +/// A graph that can be created +pub trait Create: Build + Default { + fn with_capacity(nodes: usize, edges: usize) -> Self; +} + +impl Data for Graph +where + Ix: IndexType, +{ + type NodeWeight = N; + type EdgeWeight = E; +} + +impl DataMap for Graph +where + Ty: EdgeType, + Ix: IndexType, +{ + fn node_weight(&self, id: Self::NodeId) -> Option<&Self::NodeWeight> { + self.node_weight(id) + } + fn edge_weight(&self, id: Self::EdgeId) -> Option<&Self::EdgeWeight> { + self.edge_weight(id) + } +} + +impl DataMapMut for Graph +where + Ty: EdgeType, + Ix: IndexType, +{ + fn node_weight_mut(&mut self, id: Self::NodeId) -> Option<&mut Self::NodeWeight> { + self.node_weight_mut(id) + } + fn edge_weight_mut(&mut self, id: Self::EdgeId) -> Option<&mut Self::EdgeWeight> { + self.edge_weight_mut(id) + } +} + +#[cfg(feature = "stable_graph")] +impl DataMap for StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + fn node_weight(&self, id: Self::NodeId) -> Option<&Self::NodeWeight> { + self.node_weight(id) + } + fn edge_weight(&self, id: Self::EdgeId) -> Option<&Self::EdgeWeight> { + self.edge_weight(id) + } +} + +#[cfg(feature = "stable_graph")] +impl DataMapMut for StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + fn node_weight_mut(&mut self, id: Self::NodeId) -> Option<&mut Self::NodeWeight> { + self.node_weight_mut(id) + } + fn edge_weight_mut(&mut self, id: Self::EdgeId) -> Option<&mut Self::EdgeWeight> { + self.edge_weight_mut(id) + } +} + +impl Build for Graph +where + Ty: EdgeType, + Ix: IndexType, +{ + fn add_node(&mut self, weight: Self::NodeWeight) -> Self::NodeId { + self.add_node(weight) + } + fn add_edge( + &mut self, + a: Self::NodeId, + b: Self::NodeId, + weight: Self::EdgeWeight, + ) -> Option { + Some(self.add_edge(a, b, weight)) + } + fn update_edge( + &mut self, + a: Self::NodeId, + b: Self::NodeId, + weight: Self::EdgeWeight, + ) -> Self::EdgeId { + self.update_edge(a, b, weight) + } +} + +#[cfg(feature = "stable_graph")] +impl Build for StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + fn add_node(&mut self, weight: Self::NodeWeight) -> Self::NodeId { + self.add_node(weight) + } + fn add_edge( + &mut self, + a: Self::NodeId, + b: Self::NodeId, + weight: Self::EdgeWeight, + ) -> Option { + Some(self.add_edge(a, b, weight)) + } + fn update_edge( + &mut self, + a: Self::NodeId, + b: Self::NodeId, + weight: Self::EdgeWeight, + ) -> Self::EdgeId { + self.update_edge(a, b, weight) + } +} + +#[cfg(feature = "graphmap")] +impl Build for GraphMap +where + Ty: EdgeType, + N: NodeTrait, +{ + fn add_node(&mut self, weight: Self::NodeWeight) -> Self::NodeId { + self.add_node(weight) + } + fn add_edge( + &mut self, + a: Self::NodeId, + b: Self::NodeId, + weight: Self::EdgeWeight, + ) -> Option { + if self.contains_edge(a, b) { + None + } else { + let r = self.add_edge(a, b, weight); + debug_assert!(r.is_none()); + Some((a, b)) + } + } + fn update_edge( + &mut self, + a: Self::NodeId, + b: Self::NodeId, + weight: Self::EdgeWeight, + ) -> Self::EdgeId { + self.add_edge(a, b, weight); + (a, b) + } +} + +impl Create for Graph +where + Ty: EdgeType, + Ix: IndexType, +{ + fn with_capacity(nodes: usize, edges: usize) -> Self { + Self::with_capacity(nodes, edges) + } +} + +#[cfg(feature = "stable_graph")] +impl Create for StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + fn with_capacity(nodes: usize, edges: usize) -> Self { + Self::with_capacity(nodes, edges) + } +} + +#[cfg(feature = "graphmap")] +impl Create for GraphMap +where + Ty: EdgeType, + N: NodeTrait, +{ + fn with_capacity(nodes: usize, edges: usize) -> Self { + Self::with_capacity(nodes, edges) + } +} + +/// A graph element. +/// +/// A sequence of Elements, for example an iterator, is laid out as follows: +/// Nodes are implicitly given the index of their appearance in the sequence. +/// The edges’ source and target fields refer to these indices. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Element { + /// A graph node. + Node { weight: N }, + /// A graph edge. + Edge { + source: usize, + target: usize, + weight: E, + }, +} + +/// Create a graph from an iterator of elements. +pub trait FromElements: Create { + fn from_elements(iterable: I) -> Self + where + Self: Sized, + I: IntoIterator>, + { + let mut gr = Self::with_capacity(0, 0); + // usize -> NodeId map + let mut map = Vec::new(); + for element in iterable { + match element { + Element::Node { weight } => { + map.push(gr.add_node(weight)); + } + Element::Edge { + source, + target, + weight, + } => { + gr.add_edge(map[source], map[target], weight); + } + } + } + gr + } +} + +fn from_elements_indexable(iterable: I) -> G +where + G: Create + NodeIndexable, + I: IntoIterator>, +{ + let mut gr = G::with_capacity(0, 0); + let map = |gr: &G, i| gr.from_index(i); + for element in iterable { + match element { + Element::Node { weight } => { + gr.add_node(weight); + } + Element::Edge { + source, + target, + weight, + } => { + let from = map(&gr, source); + let to = map(&gr, target); + gr.add_edge(from, to, weight); + } + } + } + gr +} + +impl FromElements for Graph +where + Ty: EdgeType, + Ix: IndexType, +{ + fn from_elements(iterable: I) -> Self + where + Self: Sized, + I: IntoIterator>, + { + from_elements_indexable(iterable) + } +} + +#[cfg(feature = "stable_graph")] +impl FromElements for StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + fn from_elements(iterable: I) -> Self + where + Self: Sized, + I: IntoIterator>, + { + from_elements_indexable(iterable) + } +} + +#[cfg(feature = "graphmap")] +impl FromElements for GraphMap +where + Ty: EdgeType, + N: NodeTrait, +{ + fn from_elements(iterable: I) -> Self + where + Self: Sized, + I: IntoIterator>, + { + from_elements_indexable(iterable) + } +} + +/// Iterator adaptors for iterators of `Element`. +pub trait ElementIterator: Iterator> { + /// Create an iterator adaptor that filters graph elements. + /// + /// The function `f` is called with each element and if its return value + /// is `true` the element is accepted and if `false` it is removed. + /// `f` is called with mutable references to the node and edge weights, + /// so that they can be mutated (but the edge endpoints can not). + /// + /// This filter adapts the edge source and target indices in the + /// stream so that they are correct after the removals. + fn filter_elements(self, f: F) -> FilterElements + where + Self: Sized, + F: FnMut(Element<&mut N, &mut E>) -> bool, + { + FilterElements { + iter: self, + node_index: 0, + map: Vec::new(), + f, + } + } +} + +impl ElementIterator for I where I: Iterator> {} + +/// An iterator that filters graph elements. +/// +/// See [`.filter_elements()`][1] for more information. +/// +/// [1]: trait.ElementIterator.html#method.filter_elements +#[derive(Debug, Clone)] +pub struct FilterElements { + iter: I, + node_index: usize, + map: Vec, + f: F, +} + +impl Iterator for FilterElements +where + I: Iterator>, + F: FnMut(Element<&mut N, &mut E>) -> bool, +{ + type Item = Element; + + fn next(&mut self) -> Option { + loop { + let mut elt = self.iter.next()?; + let keep = (self.f)(match elt { + Element::Node { ref mut weight } => Element::Node { weight }, + Element::Edge { + source, + target, + ref mut weight, + } => Element::Edge { + source, + target, + weight, + }, + }); + let is_node = if let Element::Node { .. } = elt { + true + } else { + false + }; + if !keep && is_node { + self.map.push(self.node_index); + } + if is_node { + self.node_index += 1; + } + if !keep { + continue; + } + + // map edge parts + match elt { + Element::Edge { + ref mut source, + ref mut target, + .. + } => { + // Find the node indices in the map of removed ones. + // If a node was removed, the edge is as well. + // Otherwise the counts are adjusted by the number of nodes + // removed. + // Example: map: [1, 3, 4, 6] + // binary search for 2, result is Err(1). One node has been + // removed before 2. + match self.map.binary_search(source) { + Ok(_) => continue, + Err(i) => *source -= i, + } + match self.map.binary_search(target) { + Ok(_) => continue, + Err(i) => *target -= i, + } + } + Element::Node { .. } => {} + } + return Some(elt); + } + } + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } +} diff --git a/vendor/petgraph/src/dot.rs b/vendor/petgraph/src/dot.rs new file mode 100644 index 00000000..82ed518d --- /dev/null +++ b/vendor/petgraph/src/dot.rs @@ -0,0 +1,371 @@ +//! Simple graphviz dot file format output. + +use std::fmt::{self, Display, Write}; + +use crate::visit::{ + EdgeRef, GraphProp, IntoEdgeReferences, IntoNodeReferences, NodeIndexable, NodeRef, +}; + +/// `Dot` implements output to graphviz .dot format for a graph. +/// +/// Formatting and options are rather simple, this is mostly intended +/// for debugging. Exact output may change. +/// +/// # Examples +/// +/// ``` +/// use petgraph::Graph; +/// use petgraph::dot::{Dot, Config}; +/// +/// let mut graph = Graph::<_, ()>::new(); +/// graph.add_node("A"); +/// graph.add_node("B"); +/// graph.add_node("C"); +/// graph.add_node("D"); +/// graph.extend_with_edges(&[ +/// (0, 1), (0, 2), (0, 3), +/// (1, 2), (1, 3), +/// (2, 3), +/// ]); +/// +/// println!("{:?}", Dot::with_config(&graph, &[Config::EdgeNoLabel])); +/// +/// // In this case the output looks like this: +/// // +/// // digraph { +/// // 0 [label="\"A\""] +/// // 1 [label="\"B\""] +/// // 2 [label="\"C\""] +/// // 3 [label="\"D\""] +/// // 0 -> 1 +/// // 0 -> 2 +/// // 0 -> 3 +/// // 1 -> 2 +/// // 1 -> 3 +/// // 2 -> 3 +/// // } +/// +/// // If you need multiple config options, just list them all in the slice. +/// ``` +pub struct Dot<'a, G> +where + G: IntoEdgeReferences + IntoNodeReferences, +{ + graph: G, + get_edge_attributes: &'a dyn Fn(G, G::EdgeRef) -> String, + get_node_attributes: &'a dyn Fn(G, G::NodeRef) -> String, + config: Configs, +} + +static TYPE: [&str; 2] = ["graph", "digraph"]; +static EDGE: [&str; 2] = ["--", "->"]; +static INDENT: &str = " "; + +impl<'a, G> Dot<'a, G> +where + G: IntoNodeReferences + IntoEdgeReferences, +{ + /// Create a `Dot` formatting wrapper with default configuration. + #[inline] + pub fn new(graph: G) -> Self { + Self::with_config(graph, &[]) + } + + /// Create a `Dot` formatting wrapper with custom configuration. + #[inline] + pub fn with_config(graph: G, config: &'a [Config]) -> Self { + Self::with_attr_getters(graph, config, &|_, _| String::new(), &|_, _| String::new()) + } + + #[inline] + pub fn with_attr_getters( + graph: G, + config: &'a [Config], + get_edge_attributes: &'a dyn Fn(G, G::EdgeRef) -> String, + get_node_attributes: &'a dyn Fn(G, G::NodeRef) -> String, + ) -> Self { + let config = Configs::extract(config); + Dot { + graph, + get_edge_attributes, + get_node_attributes, + config, + } + } +} + +/// `Dot` configuration. +/// +/// This enum does not have an exhaustive definition (will be expanded) +// TODO: #[non_exhaustive] once MSRV >= 1.40, +// and/or for a breaking change make this something like an EnumSet: https://docs.rs/enumset +#[derive(Debug, PartialEq, Eq)] +pub enum Config { + /// Use indices for node labels. + NodeIndexLabel, + /// Use indices for edge labels. + EdgeIndexLabel, + /// Use no edge labels. + EdgeNoLabel, + /// Use no node labels. + NodeNoLabel, + /// Do not print the graph/digraph string. + GraphContentOnly, + #[doc(hidden)] + _Incomplete(()), +} +macro_rules! make_config_struct { + ($($variant:ident,)*) => { + #[allow(non_snake_case)] + #[derive(Default)] + struct Configs { + $($variant: bool,)* + } + impl Configs { + #[inline] + fn extract(configs: &[Config]) -> Self { + let mut conf = Self::default(); + for c in configs { + match *c { + $(Config::$variant => conf.$variant = true,)* + Config::_Incomplete(()) => {} + } + } + conf + } + } + } +} +make_config_struct!( + NodeIndexLabel, + EdgeIndexLabel, + EdgeNoLabel, + NodeNoLabel, + GraphContentOnly, +); + +impl Dot<'_, G> +where + G: IntoNodeReferences + IntoEdgeReferences + NodeIndexable + GraphProp, +{ + fn graph_fmt(&self, f: &mut fmt::Formatter, node_fmt: NF, edge_fmt: EF) -> fmt::Result + where + NF: Fn(&G::NodeWeight, &mut fmt::Formatter) -> fmt::Result, + EF: Fn(&G::EdgeWeight, &mut fmt::Formatter) -> fmt::Result, + { + let g = self.graph; + if !self.config.GraphContentOnly { + writeln!(f, "{} {{", TYPE[g.is_directed() as usize])?; + } + + // output all labels + for node in g.node_references() { + write!(f, "{}{} [ ", INDENT, g.to_index(node.id()),)?; + if !self.config.NodeNoLabel { + write!(f, "label = \"")?; + if self.config.NodeIndexLabel { + write!(f, "{}", g.to_index(node.id()))?; + } else { + Escaped(FnFmt(node.weight(), &node_fmt)).fmt(f)?; + } + write!(f, "\" ")?; + } + writeln!(f, "{}]", (self.get_node_attributes)(g, node))?; + } + // output all edges + for (i, edge) in g.edge_references().enumerate() { + write!( + f, + "{}{} {} {} [ ", + INDENT, + g.to_index(edge.source()), + EDGE[g.is_directed() as usize], + g.to_index(edge.target()), + )?; + if !self.config.EdgeNoLabel { + write!(f, "label = \"")?; + if self.config.EdgeIndexLabel { + write!(f, "{}", i)?; + } else { + Escaped(FnFmt(edge.weight(), &edge_fmt)).fmt(f)?; + } + write!(f, "\" ")?; + } + writeln!(f, "{}]", (self.get_edge_attributes)(g, edge))?; + } + + if !self.config.GraphContentOnly { + writeln!(f, "}}")?; + } + Ok(()) + } +} + +impl fmt::Display for Dot<'_, G> +where + G: IntoEdgeReferences + IntoNodeReferences + NodeIndexable + GraphProp, + G::EdgeWeight: fmt::Display, + G::NodeWeight: fmt::Display, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.graph_fmt(f, fmt::Display::fmt, fmt::Display::fmt) + } +} + +impl fmt::LowerHex for Dot<'_, G> +where + G: IntoEdgeReferences + IntoNodeReferences + NodeIndexable + GraphProp, + G::EdgeWeight: fmt::LowerHex, + G::NodeWeight: fmt::LowerHex, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.graph_fmt(f, fmt::LowerHex::fmt, fmt::LowerHex::fmt) + } +} + +impl fmt::UpperHex for Dot<'_, G> +where + G: IntoEdgeReferences + IntoNodeReferences + NodeIndexable + GraphProp, + G::EdgeWeight: fmt::UpperHex, + G::NodeWeight: fmt::UpperHex, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.graph_fmt(f, fmt::UpperHex::fmt, fmt::UpperHex::fmt) + } +} + +impl fmt::Debug for Dot<'_, G> +where + G: IntoEdgeReferences + IntoNodeReferences + NodeIndexable + GraphProp, + G::EdgeWeight: fmt::Debug, + G::NodeWeight: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.graph_fmt(f, fmt::Debug::fmt, fmt::Debug::fmt) + } +} + +/// Escape for Graphviz +struct Escaper(W); + +impl fmt::Write for Escaper +where + W: fmt::Write, +{ + fn write_str(&mut self, s: &str) -> fmt::Result { + for c in s.chars() { + self.write_char(c)?; + } + Ok(()) + } + + fn write_char(&mut self, c: char) -> fmt::Result { + match c { + '"' | '\\' => self.0.write_char('\\')?, + // \l is for left justified linebreak + '\n' => return self.0.write_str("\\l"), + _ => {} + } + self.0.write_char(c) + } +} + +/// Pass Display formatting through a simple escaping filter +struct Escaped(T); + +impl fmt::Display for Escaped +where + T: fmt::Display, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if f.alternate() { + writeln!(&mut Escaper(f), "{:#}", &self.0) + } else { + write!(&mut Escaper(f), "{}", &self.0) + } + } +} + +/// Format data using a specific format function +struct FnFmt<'a, T, F>(&'a T, F); + +impl<'a, T, F> fmt::Display for FnFmt<'a, T, F> +where + F: Fn(&'a T, &mut fmt::Formatter<'_>) -> fmt::Result, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.1(self.0, f) + } +} + +#[cfg(test)] +mod test { + use super::{Config, Dot, Escaper}; + use crate::prelude::Graph; + use crate::visit::NodeRef; + use std::fmt::Write; + + #[test] + fn test_escape() { + let mut buff = String::new(); + { + let mut e = Escaper(&mut buff); + let _ = e.write_str("\" \\ \n"); + } + assert_eq!(buff, "\\\" \\\\ \\l"); + } + + fn simple_graph() -> Graph<&'static str, &'static str> { + let mut graph = Graph::<&str, &str>::new(); + let a = graph.add_node("A"); + let b = graph.add_node("B"); + graph.add_edge(a, b, "edge_label"); + graph + } + + #[test] + fn test_nodeindexlable_option() { + let graph = simple_graph(); + let dot = format!("{:?}", Dot::with_config(&graph, &[Config::NodeIndexLabel])); + assert_eq!(dot, "digraph {\n 0 [ label = \"0\" ]\n 1 [ label = \"1\" ]\n 0 -> 1 [ label = \"\\\"edge_label\\\"\" ]\n}\n"); + } + + #[test] + fn test_edgeindexlable_option() { + let graph = simple_graph(); + let dot = format!("{:?}", Dot::with_config(&graph, &[Config::EdgeIndexLabel])); + assert_eq!(dot, "digraph {\n 0 [ label = \"\\\"A\\\"\" ]\n 1 [ label = \"\\\"B\\\"\" ]\n 0 -> 1 [ label = \"0\" ]\n}\n"); + } + + #[test] + fn test_edgenolable_option() { + let graph = simple_graph(); + let dot = format!("{:?}", Dot::with_config(&graph, &[Config::EdgeNoLabel])); + assert_eq!(dot, "digraph {\n 0 [ label = \"\\\"A\\\"\" ]\n 1 [ label = \"\\\"B\\\"\" ]\n 0 -> 1 [ ]\n}\n"); + } + + #[test] + fn test_nodenolable_option() { + let graph = simple_graph(); + let dot = format!("{:?}", Dot::with_config(&graph, &[Config::NodeNoLabel])); + assert_eq!( + dot, + "digraph {\n 0 [ ]\n 1 [ ]\n 0 -> 1 [ label = \"\\\"edge_label\\\"\" ]\n}\n" + ); + } + + #[test] + fn test_with_attr_getters() { + let graph = simple_graph(); + let dot = format!( + "{:?}", + Dot::with_attr_getters( + &graph, + &[Config::NodeNoLabel, Config::EdgeNoLabel], + &|_, er| format!("label = \"{}\"", er.weight().to_uppercase()), + &|_, nr| format!("label = \"{}\"", nr.weight().to_lowercase()), + ), + ); + assert_eq!(dot, "digraph {\n 0 [ label = \"a\"]\n 1 [ label = \"b\"]\n 0 -> 1 [ label = \"EDGE_LABEL\"]\n}\n"); + } +} diff --git a/vendor/petgraph/src/generate.rs b/vendor/petgraph/src/generate.rs new file mode 100644 index 00000000..9dc7dbf4 --- /dev/null +++ b/vendor/petgraph/src/generate.rs @@ -0,0 +1,133 @@ +//! ***Unstable.*** Graph generation. +//! +//! ***Unstable: API may change at any time.*** Depends on `feature = "generate"`. +//! + +use crate::graph::NodeIndex; +use crate::{Directed, EdgeType, Graph}; + +// A DAG has the property that the adjacency matrix is lower triangular, +// diagonal zero. +// +// This means we only allow edges i → j where i < j. +// +// The set of all DAG of a particular size is simply the power set of all +// possible edges. +// +// For a graph of n=3 nodes we have (n - 1) * n / 2 = 3 possible edges. + +/// A graph generator of “all” graphs of a particular size. +/// +/// ***Unstable: API may change at any time.*** Depends on `feature = "generate"`. +pub struct Generator { + acyclic: bool, + selfloops: bool, + nodes: usize, + /// number of possible edges + nedges: usize, + /// current edge bitmap + bits: u64, + g: Graph<(), (), Ty>, +} + +impl Generator { + /// Generate all possible Directed acyclic graphs (DAGs) of a particular number of vertices. + /// + /// These are only generated with one per isomorphism, so they use + /// one canonical node labeling where node *i* can only have edges to node *j* if *i < j*. + /// + /// For a graph of *k* vertices there are *e = (k - 1) k / 2* possible edges and + /// *2e* DAGs. + pub fn directed_acyclic(nodes: usize) -> Self { + assert!(nodes != 0); + let nedges = (nodes - 1) * nodes / 2; + assert!(nedges < 64); + Generator { + acyclic: true, + selfloops: false, + nodes: nodes, + nedges: nedges, + bits: !0, + g: Graph::with_capacity(nodes, nedges), + } + } +} + +impl Generator { + /// Generate all possible graphs of a particular number of vertices. + /// + /// All permutations are generated, so the graphs are not unique down to isomorphism. + /// + /// For a graph of *k* vertices there are *e = k²* possible edges and + /// *2k2* graphs. + pub fn all(nodes: usize, allow_selfloops: bool) -> Self { + let scale = if Ty::is_directed() { 1 } else { 2 }; + let nedges = if allow_selfloops { + (nodes * nodes - nodes) / scale + nodes + } else { + (nodes * nodes) / scale - nodes + }; + assert!(nedges < 64); + Generator { + acyclic: false, + selfloops: allow_selfloops, + nodes: nodes, + nedges: nedges, + bits: !0, + g: Graph::with_capacity(nodes, nedges), + } + } + + fn state_to_graph(&mut self) -> &Graph<(), (), Ty> { + self.g.clear(); + for _ in 0..self.nodes { + self.g.add_node(()); + } + // For a DAG: + // interpret the bits in order, it's a lower triangular matrix: + // a b c d + // a x x x x + // b 0 x x x + // c 1 2 x x + // d 3 4 5 x + let mut bit = 0; + for i in 0..self.nodes { + let start = if self.acyclic || !self.g.is_directed() { + i + } else { + 0 + }; + for j in start..self.nodes { + if i == j && !self.selfloops { + continue; + } + if self.bits & (1u64 << bit) != 0 { + self.g.add_edge(NodeIndex::new(i), NodeIndex::new(j), ()); + } + + bit += 1; + } + } + &self.g + } + + pub fn next_ref(&mut self) -> Option<&Graph<(), (), Ty>> { + if self.bits == !0 { + self.bits = 0; + } else { + self.bits += 1; + if self.bits >= 1u64 << self.nedges { + return None; + } + } + Some(self.state_to_graph()) + } +} + +impl Iterator for Generator { + type Item = Graph<(), (), Ty>; + + fn next(&mut self) -> Option { + self.next_ref().cloned() + } +} diff --git a/vendor/petgraph/src/graph6/graph6_decoder.rs b/vendor/petgraph/src/graph6/graph6_decoder.rs new file mode 100644 index 00000000..c0d6ecfa --- /dev/null +++ b/vendor/petgraph/src/graph6/graph6_decoder.rs @@ -0,0 +1,200 @@ +//! [graph6 format](https://users.cecs.anu.edu.au/~bdm/data/formats.txt) decoder for undirected graphs. + +use crate::{csr::Csr, graph::IndexType, Graph, Undirected}; + +#[cfg(feature = "graphmap")] +use crate::graphmap::GraphMap; + +#[cfg(feature = "graphmap")] +use std::hash::BuildHasher; + +#[cfg(feature = "matrix_graph")] +use crate::matrix_graph::{MatrixGraph, Nullable}; + +#[cfg(feature = "stable_graph")] +use crate::stable_graph::{StableGraph, StableUnGraph}; + +const N: usize = 63; + +/// A graph that can be converted from graph6 format string. +pub trait FromGraph6 { + fn from_graph6_string(graph6_string: String) -> Self; +} + +/// Converts a graph6 format string into data can be used to construct an undirected graph. +/// Returns a tuple containing the graph order and its edges. +pub fn from_graph6_representation(graph6_representation: String) -> (usize, Vec<(Ix, Ix)>) +where + Ix: IndexType, +{ + let (order_bytes, adj_matrix_bytes) = + get_order_bytes_and_adj_matrix_bytes(graph6_representation); + + let order_bits = bytes_vector_to_bits_vector(order_bytes); + let adj_matrix_bits = bytes_vector_to_bits_vector(adj_matrix_bytes); + + let graph_order = get_bits_as_decimal(order_bits); + let edges = get_edges(graph_order, adj_matrix_bits); + + (graph_order, edges) +} + +// Converts a graph6 format string into a vector of bytes, converted from ASCII characters, +// split into two parts, the first representing the graph order, and the second its adjacency matrix. +fn get_order_bytes_and_adj_matrix_bytes(graph6_representation: String) -> (Vec, Vec) { + let bytes: Vec = graph6_representation + .chars() + .map(|c| (c as usize) - N) + .collect(); + + let mut order_bytes = vec![]; + let mut adj_matrix_bytes = vec![]; + + let first_byte = *bytes.first().unwrap(); + if first_byte == N { + order_bytes.extend_from_slice(&bytes[1..=3]); + adj_matrix_bytes.extend_from_slice(&bytes[4..]); + } else { + order_bytes.push(first_byte); + adj_matrix_bytes.extend_from_slice(&bytes[1..]); + }; + + (order_bytes, adj_matrix_bytes) +} + +// Converts a bytes vector into a bits vector. +fn bytes_vector_to_bits_vector(bytes: Vec) -> Vec { + bytes + .iter() + .flat_map(|&byte| get_number_as_bits(byte, 6)) + .collect() +} + +// Get binary representation of `n` as a vector of bits with `bits_length` length. +fn get_number_as_bits(n: usize, bits_length: usize) -> Vec { + let mut bits = Vec::new(); + for i in (0..bits_length).rev() { + bits.push(((n >> i) & 1) as u8); + } + bits +} + +// Convert a bits vector into its decimal representation. +fn get_bits_as_decimal(bits: Vec) -> usize { + let bits_str = bits + .iter() + .map(|bit| bit.to_string()) + .collect::>() + .join(""); + + usize::from_str_radix(&bits_str, 2).unwrap() +} + +// Get graph edges from its order and bits vector representation of its adjacency matrix. +fn get_edges(order: usize, adj_matrix_bits: Vec) -> Vec<(Ix, Ix)> +where + Ix: IndexType, +{ + let mut edges = vec![]; + + let mut i = 0; + for col in 1..order { + for lin in 0..col { + let is_adjacent = adj_matrix_bits[i] == 1; + + if is_adjacent { + edges.push((Ix::new(lin), Ix::new(col))); + }; + + i += 1; + } + } + + edges +} + +impl FromGraph6 for Graph<(), (), Undirected, Ix> { + fn from_graph6_string(graph6_string: String) -> Self { + let (order, edges): (usize, Vec<(Ix, Ix)>) = from_graph6_representation(graph6_string); + + let mut graph: Graph<(), (), Undirected, Ix> = Graph::with_capacity(order, edges.len()); + for _ in 0..order { + graph.add_node(()); + } + graph.extend_with_edges(edges); + + graph + } +} + +#[cfg(feature = "stable_graph")] +impl FromGraph6 for StableGraph<(), (), Undirected, Ix> { + fn from_graph6_string(graph6_string: String) -> Self { + let (order, edges): (usize, Vec<(Ix, Ix)>) = from_graph6_representation(graph6_string); + + let mut graph: StableGraph<(), (), Undirected, Ix> = + StableUnGraph::with_capacity(order, edges.len()); + for _ in 0..order { + graph.add_node(()); + } + graph.extend_with_edges(edges); + + graph + } +} + +#[cfg(feature = "graphmap")] +impl FromGraph6 for GraphMap { + fn from_graph6_string(graph6_string: String) -> Self { + let (order, edges): (usize, Vec<(Ix, Ix)>) = from_graph6_representation(graph6_string); + + let mut graph: GraphMap = + GraphMap::with_capacity(order, edges.len()); + for i in 0..order { + graph.add_node(Ix::new(i)); + } + for (a, b) in edges { + graph.add_edge(a, b, ()); + } + + graph + } +} + +#[cfg(feature = "matrix_graph")] +impl FromGraph6 for MatrixGraph<(), (), Undirected, Null, Ix> +where + Null: Nullable, + Ix: IndexType, +{ + fn from_graph6_string(graph6_string: String) -> Self { + let (order, edges): (usize, Vec<(Ix, Ix)>) = from_graph6_representation(graph6_string); + + let mut graph: MatrixGraph<(), (), Undirected, Null, Ix> = + MatrixGraph::with_capacity(order); + for _ in 0..order { + graph.add_node(()); + } + graph.extend_with_edges(edges.iter()); + + graph + } +} + +impl FromGraph6 for Csr<(), (), Undirected, Ix> { + fn from_graph6_string(graph6_string: String) -> Self { + let (order, edges): (usize, Vec<(Ix, Ix)>) = from_graph6_representation(graph6_string); + + let mut graph: Csr<(), (), Undirected, Ix> = Csr::new(); + let mut nodes = Vec::new(); + for _ in 0..order { + let i = graph.add_node(()); + nodes.push(i); + } + for (a, b) in edges { + graph.add_edge(a, b, ()); + } + + graph + } +} diff --git a/vendor/petgraph/src/graph6/graph6_encoder.rs b/vendor/petgraph/src/graph6/graph6_encoder.rs new file mode 100644 index 00000000..41ba530a --- /dev/null +++ b/vendor/petgraph/src/graph6/graph6_encoder.rs @@ -0,0 +1,154 @@ +//! [graph6 format](https://users.cecs.anu.edu.au/~bdm/data/formats.txt) encoder for undirected graphs. + +use crate::{ + csr::Csr, + graph::IndexType, + visit::{GetAdjacencyMatrix, IntoNodeIdentifiers}, + Graph, Undirected, +}; + +#[cfg(feature = "graphmap")] +use crate::graphmap::{GraphMap, NodeTrait}; + +#[cfg(feature = "graphmap")] +use std::hash::BuildHasher; + +#[cfg(feature = "matrix_graph")] +use crate::matrix_graph::{MatrixGraph, Nullable}; + +#[cfg(feature = "stable_graph")] +use crate::stable_graph::StableGraph; + +const N: usize = 63; + +/// A graph that can be converted to graph6 format string. +pub trait ToGraph6 { + fn graph6_string(&self) -> String; +} + +/// Converts a graph that implements GetAdjacencyMatrix and IntoNodeIdentifers +/// into a graph6 format string. +pub fn get_graph6_representation(graph: G) -> String +where + G: GetAdjacencyMatrix + IntoNodeIdentifiers, +{ + let (graph_order, mut upper_diagonal_as_bits) = get_adj_matrix_upper_diagonal_as_bits(graph); + let mut graph_order_as_bits = get_graph_order_as_bits(graph_order); + + let mut graph_as_bits = vec![]; + graph_as_bits.append(&mut graph_order_as_bits); + graph_as_bits.append(&mut upper_diagonal_as_bits); + + bits_to_ascii(graph_as_bits) +} + +// Traverse graph nodes and construct the upper diagonal of its adjacency matrix as a vector of bits. +// Returns a tuple containing: +// - `n`: graph order (number of nodes in graph) +// - `bits`: a vector of 0s and 1s encoding the upper diagonal of the graphs adjacency matrix. +fn get_adj_matrix_upper_diagonal_as_bits(graph: G) -> (usize, Vec) +where + G: GetAdjacencyMatrix + IntoNodeIdentifiers, +{ + let node_ids_iter = graph.node_identifiers(); + let mut node_ids_vec = vec![]; + + let adj_matrix = graph.adjacency_matrix(); + let mut bits = vec![]; + let mut n = 0; + for node_id in node_ids_iter { + node_ids_vec.push(node_id); + + for i in 1..=n { + let is_adjacent: bool = + graph.is_adjacent(&adj_matrix, node_ids_vec[i - 1], node_ids_vec[n]); + bits.push(if is_adjacent { 1 } else { 0 }); + } + + n += 1; + } + + (n, bits) +} + +// Converts graph order to a bits vector. +fn get_graph_order_as_bits(order: usize) -> Vec { + let to_convert_to_bits = if order < N { + vec![(order, 6)] + } else if order <= 258047 { + vec![(N, 6), (order, 18)] + } else { + panic!("Graph order not supported.") + }; + + to_convert_to_bits + .iter() + .flat_map(|&(n, n_of_bits)| get_number_as_bits(n, n_of_bits)) + .collect() +} + +// Get binary representation of `n` as a vector of bits with `bits_length` length. +fn get_number_as_bits(n: usize, bits_length: usize) -> Vec { + let mut bits = Vec::new(); + for i in (0..bits_length).rev() { + bits.push((n >> i) & 1); + } + bits +} + +// Convert a vector of bits to a String using ASCII encoding. +// Each 6 bits will be converted to a single ASCII character. +fn bits_to_ascii(mut bits: Vec) -> String { + while bits.len() % 6 != 0 { + bits.push(0); + } + + let bits_strs = bits.iter().map(|bit| bit.to_string()).collect::>(); + + let bytes = bits_strs + .chunks(6) + .map(|bits_chunk| bits_chunk.join("")) + .map(|bits_str| usize::from_str_radix(&bits_str, 2)); + + bytes + .map(|byte| char::from((N + byte.unwrap()) as u8)) + .collect() +} + +impl ToGraph6 for Graph { + fn graph6_string(&self) -> String { + get_graph6_representation(self) + } +} + +#[cfg(feature = "stable_graph")] +impl ToGraph6 for StableGraph { + fn graph6_string(&self) -> String { + get_graph6_representation(self) + } +} + +#[cfg(feature = "graphmap")] +impl ToGraph6 for GraphMap { + fn graph6_string(&self) -> String { + get_graph6_representation(self) + } +} + +#[cfg(feature = "matrix_graph")] +impl ToGraph6 for MatrixGraph +where + N: NodeTrait, + Null: Nullable, + Ix: IndexType, +{ + fn graph6_string(&self) -> String { + get_graph6_representation(self) + } +} + +impl ToGraph6 for Csr { + fn graph6_string(&self) -> String { + get_graph6_representation(self) + } +} diff --git a/vendor/petgraph/src/graph6/mod.rs b/vendor/petgraph/src/graph6/mod.rs new file mode 100644 index 00000000..0d16f0c7 --- /dev/null +++ b/vendor/petgraph/src/graph6/mod.rs @@ -0,0 +1,7 @@ +//! Traits related to [graph6 format](https://users.cecs.anu.edu.au/~bdm/data/formats.txt) for undirected graphs. + +pub use self::graph6_decoder::*; +pub use self::graph6_encoder::*; + +mod graph6_decoder; +mod graph6_encoder; diff --git a/vendor/petgraph/src/graph_impl/frozen.rs b/vendor/petgraph/src/graph_impl/frozen.rs new file mode 100644 index 00000000..52dfb4d9 --- /dev/null +++ b/vendor/petgraph/src/graph_impl/frozen.rs @@ -0,0 +1,108 @@ +use std::ops::{Deref, Index, IndexMut}; + +use super::Frozen; +use crate::data::{DataMap, DataMapMut}; +use crate::graph::Graph; +use crate::graph::{GraphIndex, IndexType}; +use crate::visit::{ + Data, EdgeCount, EdgeIndexable, GetAdjacencyMatrix, GraphBase, GraphProp, IntoEdges, + IntoEdgesDirected, IntoNeighborsDirected, IntoNodeIdentifiers, NodeCompactIndexable, NodeCount, + NodeIndexable, +}; +use crate::visit::{IntoEdgeReferences, IntoNeighbors, IntoNodeReferences, Visitable}; +use crate::{Direction, EdgeType}; + +impl<'a, G> Frozen<'a, G> { + /// Create a new `Frozen` from a mutable reference to a graph. + pub fn new(gr: &'a mut G) -> Self { + Frozen(gr) + } +} + +/// Deref allows transparent access to all shared reference (read-only) +/// functionality in the underlying graph. +impl Deref for Frozen<'_, G> { + type Target = G; + fn deref(&self) -> &G { + self.0 + } +} + +impl Index for Frozen<'_, G> +where + G: Index, +{ + type Output = G::Output; + fn index(&self, i: I) -> &G::Output { + self.0.index(i) + } +} + +impl IndexMut for Frozen<'_, G> +where + G: IndexMut, +{ + fn index_mut(&mut self, i: I) -> &mut G::Output { + self.0.index_mut(i) + } +} + +impl Frozen<'_, Graph> +where + Ty: EdgeType, + Ix: IndexType, +{ + #[allow(clippy::type_complexity)] + /// Index the `Graph` by two indices, any combination of + /// node or edge indices is fine. + /// + /// **Panics** if the indices are equal or if they are out of bounds. + pub fn index_twice_mut( + &mut self, + i: T, + j: U, + ) -> ( + &mut as Index>::Output, + &mut as Index>::Output, + ) + where + Graph: IndexMut + IndexMut, + T: GraphIndex, + U: GraphIndex, + { + self.0.index_twice_mut(i, j) + } +} + +macro_rules! access0 { + ($e:expr) => { + $e.0 + }; +} + +impl GraphBase for Frozen<'_, G> +where + G: GraphBase, +{ + type NodeId = G::NodeId; + type EdgeId = G::EdgeId; +} + +Data! {delegate_impl [['a, G], G, Frozen<'a, G>, deref_twice]} +DataMap! {delegate_impl [['a, G], G, Frozen<'a, G>, deref_twice]} +DataMapMut! {delegate_impl [['a, G], G, Frozen<'a, G>, access0]} +GetAdjacencyMatrix! {delegate_impl [['a, G], G, Frozen<'a, G>, deref_twice]} +IntoEdgeReferences! {delegate_impl [['a, 'b, G], G, &'b Frozen<'a, G>, deref_twice]} +IntoEdges! {delegate_impl [['a, 'b, G], G, &'b Frozen<'a, G>, deref_twice]} +IntoEdgesDirected! {delegate_impl [['a, 'b, G], G, &'b Frozen<'a, G>, deref_twice]} +IntoNeighbors! {delegate_impl [['a, 'b, G], G, &'b Frozen<'a, G>, deref_twice]} +IntoNeighborsDirected! {delegate_impl [['a, 'b, G], G, &'b Frozen<'a, G>, deref_twice]} +IntoNodeIdentifiers! {delegate_impl [['a, 'b, G], G, &'b Frozen<'a, G>, deref_twice]} +IntoNodeReferences! {delegate_impl [['a, 'b, G], G, &'b Frozen<'a, G>, deref_twice]} +NodeCompactIndexable! {delegate_impl [['a, G], G, Frozen<'a, G>, deref_twice]} +NodeCount! {delegate_impl [['a, G], G, Frozen<'a, G>, deref_twice]} +NodeIndexable! {delegate_impl [['a, G], G, Frozen<'a, G>, deref_twice]} +EdgeCount! {delegate_impl [['a, G], G, Frozen<'a, G>, deref_twice]} +EdgeIndexable! {delegate_impl [['a, G], G, Frozen<'a, G>, deref_twice]} +GraphProp! {delegate_impl [['a, G], G, Frozen<'a, G>, deref_twice]} +Visitable! {delegate_impl [['a, G], G, Frozen<'a, G>, deref_twice]} diff --git a/vendor/petgraph/src/graph_impl/mod.rs b/vendor/petgraph/src/graph_impl/mod.rs new file mode 100644 index 00000000..3a123f72 --- /dev/null +++ b/vendor/petgraph/src/graph_impl/mod.rs @@ -0,0 +1,2411 @@ +use std::cmp; +use std::fmt; +use std::hash::Hash; +use std::iter; +use std::marker::PhantomData; +use std::mem::size_of; +use std::ops::{Index, IndexMut, Range}; +use std::slice; + +use fixedbitset::FixedBitSet; + +use crate::{Directed, Direction, EdgeType, Incoming, IntoWeightedEdge, Outgoing, Undirected}; + +use crate::iter_format::{DebugMap, IterFormatExt, NoPretty}; + +use crate::util::enumerate; +use crate::visit; + +#[cfg(feature = "serde-1")] +mod serialization; + +/// The default integer type for graph indices. +/// `u32` is the default to reduce the size of the graph's data and improve +/// performance in the common case. +/// +/// Used for node and edge indices in `Graph` and `StableGraph`, used +/// for node indices in `Csr`. +pub type DefaultIx = u32; + +/// Trait for the unsigned integer type used for node and edge indices. +/// +/// # Safety +/// +/// Marked `unsafe` because: the trait must faithfully preserve +/// and convert index values. +pub unsafe trait IndexType: Copy + Default + Hash + Ord + fmt::Debug + 'static { + fn new(x: usize) -> Self; + fn index(&self) -> usize; + fn max() -> Self; +} + +unsafe impl IndexType for usize { + #[inline(always)] + fn new(x: usize) -> Self { + x + } + #[inline(always)] + fn index(&self) -> Self { + *self + } + #[inline(always)] + fn max() -> Self { + ::std::usize::MAX + } +} + +unsafe impl IndexType for u32 { + #[inline(always)] + fn new(x: usize) -> Self { + x as u32 + } + #[inline(always)] + fn index(&self) -> usize { + *self as usize + } + #[inline(always)] + fn max() -> Self { + ::std::u32::MAX + } +} + +unsafe impl IndexType for u16 { + #[inline(always)] + fn new(x: usize) -> Self { + x as u16 + } + #[inline(always)] + fn index(&self) -> usize { + *self as usize + } + #[inline(always)] + fn max() -> Self { + ::std::u16::MAX + } +} + +unsafe impl IndexType for u8 { + #[inline(always)] + fn new(x: usize) -> Self { + x as u8 + } + #[inline(always)] + fn index(&self) -> usize { + *self as usize + } + #[inline(always)] + fn max() -> Self { + ::std::u8::MAX + } +} + +/// Node identifier. +#[derive(Copy, Clone, Default, PartialEq, PartialOrd, Eq, Ord, Hash)] +pub struct NodeIndex(Ix); + +impl NodeIndex { + #[inline] + pub fn new(x: usize) -> Self { + NodeIndex(IndexType::new(x)) + } + + #[inline] + pub fn index(self) -> usize { + self.0.index() + } + + #[inline] + pub fn end() -> Self { + NodeIndex(IndexType::max()) + } + + fn _into_edge(self) -> EdgeIndex { + EdgeIndex(self.0) + } +} + +unsafe impl IndexType for NodeIndex { + fn index(&self) -> usize { + self.0.index() + } + fn new(x: usize) -> Self { + NodeIndex::new(x) + } + fn max() -> Self { + NodeIndex(::max()) + } +} + +impl From for NodeIndex { + fn from(ix: Ix) -> Self { + NodeIndex(ix) + } +} + +impl fmt::Debug for NodeIndex { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "NodeIndex({:?})", self.0) + } +} + +/// Short version of `NodeIndex::new` +pub fn node_index(index: usize) -> NodeIndex { + NodeIndex::new(index) +} + +/// Short version of `EdgeIndex::new` +pub fn edge_index(index: usize) -> EdgeIndex { + EdgeIndex::new(index) +} + +/// Edge identifier. +#[derive(Copy, Clone, Default, PartialEq, PartialOrd, Eq, Ord, Hash)] +pub struct EdgeIndex(Ix); + +impl EdgeIndex { + #[inline] + pub fn new(x: usize) -> Self { + EdgeIndex(IndexType::new(x)) + } + + #[inline] + pub fn index(self) -> usize { + self.0.index() + } + + /// An invalid `EdgeIndex` used to denote absence of an edge, for example + /// to end an adjacency list. + #[inline] + pub fn end() -> Self { + EdgeIndex(IndexType::max()) + } + + fn _into_node(self) -> NodeIndex { + NodeIndex(self.0) + } +} + +impl From for EdgeIndex { + fn from(ix: Ix) -> Self { + EdgeIndex(ix) + } +} + +impl fmt::Debug for EdgeIndex { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "EdgeIndex({:?})", self.0) + } +} +/* + * FIXME: Use this impl again, when we don't need to add so many bounds +impl fmt::Debug for EdgeIndex +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(write!(f, "EdgeIndex(")); + if *self == EdgeIndex::end() { + try!(write!(f, "End")); + } else { + try!(write!(f, "{}", self.index())); + } + write!(f, ")") + } +} +*/ + +const DIRECTIONS: [Direction; 2] = [Outgoing, Incoming]; + +/// The graph's node type. +#[derive(Debug)] +pub struct Node { + /// Associated node data. + pub weight: N, + /// Next edge in outgoing and incoming edge lists. + next: [EdgeIndex; 2], +} + +impl Clone for Node +where + E: Clone, + Ix: Copy, +{ + clone_fields!(Node, weight, next,); +} + +impl Node { + /// Accessor for data structure internals: the first edge in the given direction. + pub fn next_edge(&self, dir: Direction) -> EdgeIndex { + self.next[dir.index()] + } +} + +/// The graph's edge type. +#[derive(Debug)] +pub struct Edge { + /// Associated edge data. + pub weight: E, + /// Next edge in outgoing and incoming edge lists. + next: [EdgeIndex; 2], + /// Start and End node index + node: [NodeIndex; 2], +} + +impl Clone for Edge +where + E: Clone, + Ix: Copy, +{ + clone_fields!(Edge, weight, next, node,); +} + +impl Edge { + /// Accessor for data structure internals: the next edge for the given direction. + pub fn next_edge(&self, dir: Direction) -> EdgeIndex { + self.next[dir.index()] + } + + /// Return the source node index. + pub fn source(&self) -> NodeIndex { + self.node[0] + } + + /// Return the target node index. + pub fn target(&self) -> NodeIndex { + self.node[1] + } +} + +/// `Graph` is a graph datastructure using an adjacency list representation. +/// +/// `Graph` is parameterized over: +/// +/// - Associated data `N` for nodes and `E` for edges, called *weights*. +/// The associated data can be of arbitrary type. +/// - Edge type `Ty` that determines whether the graph edges are directed or undirected. +/// - Index type `Ix`, which determines the maximum size of the graph. +/// +/// The `Graph` is a regular Rust collection and is `Send` and `Sync` (as long +/// as associated data `N` and `E` are). +/// +/// The graph uses **O(|V| + |E|)** space, and allows fast node and edge insert, +/// efficient graph search and graph algorithms. +/// It implements **O(e')** edge lookup and edge and node removals, where **e'** +/// is some local measure of edge count. +/// Based on the graph datastructure used in rustc. +/// +/// Here's an example of building a graph with directed edges, and below +/// an illustration of how it could be rendered with graphviz (see +/// [`Dot`](../dot/struct.Dot.html)): +/// +/// ``` +/// use petgraph::Graph; +/// +/// let mut deps = Graph::<&str, &str>::new(); +/// let pg = deps.add_node("petgraph"); +/// let fb = deps.add_node("fixedbitset"); +/// let qc = deps.add_node("quickcheck"); +/// let rand = deps.add_node("rand"); +/// let libc = deps.add_node("libc"); +/// deps.extend_with_edges(&[ +/// (pg, fb), (pg, qc), +/// (qc, rand), (rand, libc), (qc, libc), +/// ]); +/// ``` +/// +/// ![graph-example](https://bluss.github.io/ndarray/images/graph-example.svg) +/// +/// ### Graph Indices +/// +/// The graph maintains indices for nodes and edges, and node and edge +/// weights may be accessed mutably. Indices range in a compact interval, for +/// example for *n* nodes indices are 0 to *n* - 1 inclusive. +/// +/// `NodeIndex` and `EdgeIndex` are types that act as references to nodes and edges, +/// but these are only stable across certain operations: +/// +/// * **Removing nodes or edges may shift other indices.** Removing a node will +/// force the last node to shift its index to take its place. Similarly, +/// removing an edge shifts the index of the last edge. +/// * Adding nodes or edges keeps indices stable. +/// +/// The `Ix` parameter is `u32` by default. The goal is that you can ignore this parameter +/// completely unless you need a very big graph -- then you can use `usize`. +/// +/// * The fact that the node and edge indices in the graph each are numbered in compact +/// intervals (from 0 to *n* - 1 for *n* nodes) simplifies some graph algorithms. +/// +/// * You can select graph index integer type after the size of the graph. A smaller +/// size may have better performance. +/// +/// * Using indices allows mutation while traversing the graph, see `Dfs`, +/// and `.neighbors(a).detach()`. +/// +/// * You can create several graphs using the equal node indices but with +/// differing weights or differing edges. +/// +/// * Indices don't allow as much compile time checking as references. +/// +pub struct Graph { + nodes: Vec>, + edges: Vec>, + ty: PhantomData, +} + +/// A `Graph` with directed edges. +/// +/// For example, an edge from *1* to *2* is distinct from an edge from *2* to +/// *1*. +pub type DiGraph = Graph; + +/// A `Graph` with undirected edges. +/// +/// For example, an edge between *1* and *2* is equivalent to an edge between +/// *2* and *1*. +pub type UnGraph = Graph; + +/// The resulting cloned graph has the same graph indices as `self`. +impl Clone for Graph +where + N: Clone, + E: Clone, +{ + fn clone(&self) -> Self { + Graph { + nodes: self.nodes.clone(), + edges: self.edges.clone(), + ty: self.ty, + } + } + + fn clone_from(&mut self, rhs: &Self) { + self.nodes.clone_from(&rhs.nodes); + self.edges.clone_from(&rhs.edges); + self.ty = rhs.ty; + } +} + +impl fmt::Debug for Graph +where + N: fmt::Debug, + E: fmt::Debug, + Ty: EdgeType, + Ix: IndexType, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let etype = if self.is_directed() { + "Directed" + } else { + "Undirected" + }; + let mut fmt_struct = f.debug_struct("Graph"); + fmt_struct.field("Ty", &etype); + fmt_struct.field("node_count", &self.node_count()); + fmt_struct.field("edge_count", &self.edge_count()); + if self.edge_count() > 0 { + fmt_struct.field( + "edges", + &self + .edges + .iter() + .map(|e| NoPretty((e.source().index(), e.target().index()))) + .format(", "), + ); + } + // skip weights if they are ZST! + if size_of::() != 0 { + fmt_struct.field( + "node weights", + &DebugMap(|| self.nodes.iter().map(|n| &n.weight).enumerate()), + ); + } + if size_of::() != 0 { + fmt_struct.field( + "edge weights", + &DebugMap(|| self.edges.iter().map(|n| &n.weight).enumerate()), + ); + } + fmt_struct.finish() + } +} + +enum Pair { + Both(T, T), + One(T), + None, +} + +use std::cmp::max; + +/// Get mutable references at index `a` and `b`. +fn index_twice(slc: &mut [T], a: usize, b: usize) -> Pair<&mut T> { + if max(a, b) >= slc.len() { + Pair::None + } else if a == b { + Pair::One(&mut slc[max(a, b)]) + } else { + // safe because a, b are in bounds and distinct + unsafe { + let ptr = slc.as_mut_ptr(); + let ar = &mut *ptr.add(a); + let br = &mut *ptr.add(b); + Pair::Both(ar, br) + } + } +} + +impl Graph { + /// Create a new `Graph` with directed edges. + /// + /// This is a convenience method. Use `Graph::with_capacity` or `Graph::default` for + /// a constructor that is generic in all the type parameters of `Graph`. + pub fn new() -> Self { + Graph { + nodes: Vec::new(), + edges: Vec::new(), + ty: PhantomData, + } + } +} + +impl Graph { + /// Create a new `Graph` with undirected edges. + /// + /// This is a convenience method. Use `Graph::with_capacity` or `Graph::default` for + /// a constructor that is generic in all the type parameters of `Graph`. + pub fn new_undirected() -> Self { + Graph { + nodes: Vec::new(), + edges: Vec::new(), + ty: PhantomData, + } + } +} + +impl Graph +where + Ty: EdgeType, + Ix: IndexType, +{ + /// Create a new `Graph` with estimated capacity. + pub fn with_capacity(nodes: usize, edges: usize) -> Self { + Graph { + nodes: Vec::with_capacity(nodes), + edges: Vec::with_capacity(edges), + ty: PhantomData, + } + } + + /// Return the number of nodes (vertices) in the graph. + /// + /// Computes in **O(1)** time. + pub fn node_count(&self) -> usize { + self.nodes.len() + } + + /// Return the number of edges in the graph. + /// + /// Computes in **O(1)** time. + pub fn edge_count(&self) -> usize { + self.edges.len() + } + + /// Whether the graph has directed edges or not. + #[inline] + pub fn is_directed(&self) -> bool { + Ty::is_directed() + } + + /// Add a node (also called vertex) with associated data `weight` to the graph. + /// + /// Computes in **O(1)** time. + /// + /// Return the index of the new node. + /// + /// **Panics** if the Graph is at the maximum number of nodes for its index + /// type (N/A if usize). + pub fn add_node(&mut self, weight: N) -> NodeIndex { + let node = Node { + weight, + next: [EdgeIndex::end(), EdgeIndex::end()], + }; + let node_idx = NodeIndex::new(self.nodes.len()); + // check for max capacity, except if we use usize + assert!(::max().index() == !0 || NodeIndex::end() != node_idx); + self.nodes.push(node); + node_idx + } + + /// Access the weight for node `a`. + /// + /// If node `a` doesn't exist in the graph, return `None`. + /// Also available with indexing syntax: `&graph[a]`. + pub fn node_weight(&self, a: NodeIndex) -> Option<&N> { + self.nodes.get(a.index()).map(|n| &n.weight) + } + + /// Access the weight for node `a`, mutably. + /// + /// If node `a` doesn't exist in the graph, return `None`. + /// Also available with indexing syntax: `&mut graph[a]`. + pub fn node_weight_mut(&mut self, a: NodeIndex) -> Option<&mut N> { + self.nodes.get_mut(a.index()).map(|n| &mut n.weight) + } + + /// Add an edge from `a` to `b` to the graph, with its associated + /// data `weight`. + /// + /// Return the index of the new edge. + /// + /// Computes in **O(1)** time. + /// + /// **Panics** if any of the nodes don't exist.
+ /// **Panics** if the Graph is at the maximum number of edges for its index + /// type (N/A if usize). + /// + /// **Note:** `Graph` allows adding parallel (“duplicate”) edges. If you want + /// to avoid this, use [`.update_edge(a, b, weight)`](#method.update_edge) instead. + pub fn add_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> EdgeIndex { + let edge_idx = EdgeIndex::new(self.edges.len()); + assert!(::max().index() == !0 || EdgeIndex::end() != edge_idx); + let mut edge = Edge { + weight, + node: [a, b], + next: [EdgeIndex::end(); 2], + }; + match index_twice(&mut self.nodes, a.index(), b.index()) { + Pair::None => panic!("Graph::add_edge: node indices out of bounds"), + Pair::One(an) => { + edge.next = an.next; + an.next[0] = edge_idx; + an.next[1] = edge_idx; + } + Pair::Both(an, bn) => { + // a and b are different indices + edge.next = [an.next[0], bn.next[1]]; + an.next[0] = edge_idx; + bn.next[1] = edge_idx; + } + } + self.edges.push(edge); + edge_idx + } + + /// Add or update an edge from `a` to `b`. + /// If the edge already exists, its weight is updated. + /// + /// Return the index of the affected edge. + /// + /// Computes in **O(e')** time, where **e'** is the number of edges + /// connected to `a` (and `b`, if the graph edges are undirected). + /// + /// **Panics** if any of the nodes doesn't exist. + pub fn update_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> EdgeIndex { + if let Some(ix) = self.find_edge(a, b) { + if let Some(ed) = self.edge_weight_mut(ix) { + *ed = weight; + return ix; + } + } + self.add_edge(a, b, weight) + } + + /// Access the weight for edge `e`. + /// + /// If edge `e` doesn't exist in the graph, return `None`. + /// Also available with indexing syntax: `&graph[e]`. + pub fn edge_weight(&self, e: EdgeIndex) -> Option<&E> { + self.edges.get(e.index()).map(|ed| &ed.weight) + } + + /// Access the weight for edge `e`, mutably. + /// + /// If edge `e` doesn't exist in the graph, return `None`. + /// Also available with indexing syntax: `&mut graph[e]`. + pub fn edge_weight_mut(&mut self, e: EdgeIndex) -> Option<&mut E> { + self.edges.get_mut(e.index()).map(|ed| &mut ed.weight) + } + + /// Access the source and target nodes for `e`. + /// + /// If edge `e` doesn't exist in the graph, return `None`. + pub fn edge_endpoints(&self, e: EdgeIndex) -> Option<(NodeIndex, NodeIndex)> { + self.edges + .get(e.index()) + .map(|ed| (ed.source(), ed.target())) + } + + /// Remove `a` from the graph if it exists, and return its weight. + /// If it doesn't exist in the graph, return `None`. + /// + /// Apart from `a`, this invalidates the last node index in the graph + /// (that node will adopt the removed node index). Edge indices are + /// invalidated as they would be following the removal of each edge + /// with an endpoint in `a`. + /// + /// Computes in **O(e')** time, where **e'** is the number of affected + /// edges, including *n* calls to `.remove_edge()` where *n* is the number + /// of edges with an endpoint in `a`, and including the edges with an + /// endpoint in the displaced node. + pub fn remove_node(&mut self, a: NodeIndex) -> Option { + self.nodes.get(a.index())?; + for d in &DIRECTIONS { + let k = d.index(); + + // Remove all edges from and to this node. + loop { + let next = self.nodes[a.index()].next[k]; + if next == EdgeIndex::end() { + break; + } + let ret = self.remove_edge(next); + debug_assert!(ret.is_some()); + let _ = ret; + } + } + + // Use swap_remove -- only the swapped-in node is going to change + // NodeIndex, so we only have to walk its edges and update them. + + let node = self.nodes.swap_remove(a.index()); + + // Find the edge lists of the node that had to relocate. + // It may be that no node had to relocate, then we are done already. + let swap_edges = match self.nodes.get(a.index()) { + None => return Some(node.weight), + Some(ed) => ed.next, + }; + + // The swapped element's old index + let old_index = NodeIndex::new(self.nodes.len()); + let new_index = a; + + // Adjust the starts of the out edges, and ends of the in edges. + for &d in &DIRECTIONS { + let k = d.index(); + let mut edges = edges_walker_mut(&mut self.edges, swap_edges[k], d); + while let Some(curedge) = edges.next_edge() { + debug_assert!(curedge.node[k] == old_index); + curedge.node[k] = new_index; + } + } + Some(node.weight) + } + + /// For edge `e` with endpoints `edge_node`, replace links to it, + /// with links to `edge_next`. + fn change_edge_links( + &mut self, + edge_node: [NodeIndex; 2], + e: EdgeIndex, + edge_next: [EdgeIndex; 2], + ) { + for &d in &DIRECTIONS { + let k = d.index(); + let node = match self.nodes.get_mut(edge_node[k].index()) { + Some(r) => r, + None => { + debug_assert!( + false, + "Edge's endpoint dir={:?} index={:?} not found", + d, edge_node[k] + ); + return; + } + }; + let fst = node.next[k]; + if fst == e { + //println!("Updating first edge 0 for node {}, set to {}", edge_node[0], edge_next[0]); + node.next[k] = edge_next[k]; + } else { + let mut edges = edges_walker_mut(&mut self.edges, fst, d); + while let Some(curedge) = edges.next_edge() { + if curedge.next[k] == e { + curedge.next[k] = edge_next[k]; + break; // the edge can only be present once in the list. + } + } + } + } + } + + /// Remove an edge and return its edge weight, or `None` if it didn't exist. + /// + /// Apart from `e`, this invalidates the last edge index in the graph + /// (that edge will adopt the removed edge index). + /// + /// Computes in **O(e')** time, where **e'** is the size of four particular edge lists, for + /// the vertices of `e` and the vertices of another affected edge. + pub fn remove_edge(&mut self, e: EdgeIndex) -> Option { + // every edge is part of two lists, + // outgoing and incoming edges. + // Remove it from both + let (edge_node, edge_next) = match self.edges.get(e.index()) { + None => return None, + Some(x) => (x.node, x.next), + }; + // Remove the edge from its in and out lists by replacing it with + // a link to the next in the list. + self.change_edge_links(edge_node, e, edge_next); + self.remove_edge_adjust_indices(e) + } + + fn remove_edge_adjust_indices(&mut self, e: EdgeIndex) -> Option { + // swap_remove the edge -- only the removed edge + // and the edge swapped into place are affected and need updating + // indices. + let edge = self.edges.swap_remove(e.index()); + let swap = match self.edges.get(e.index()) { + // no elment needed to be swapped. + None => return Some(edge.weight), + Some(ed) => ed.node, + }; + let swapped_e = EdgeIndex::new(self.edges.len()); + + // Update the edge lists by replacing links to the old index by references to the new + // edge index. + self.change_edge_links(swap, swapped_e, [e, e]); + Some(edge.weight) + } + + /// Return an iterator of all nodes with an edge starting from `a`. + /// + /// - `Directed`: Outgoing edges from `a`. + /// - `Undirected`: All edges from or to `a`. + /// + /// Produces an empty iterator if the node doesn't exist.
+ /// Iterator element type is `NodeIndex`. + /// + /// Use [`.neighbors(a).detach()`][1] to get a neighbor walker that does + /// not borrow from the graph. + /// + /// [1]: struct.Neighbors.html#method.detach + pub fn neighbors(&self, a: NodeIndex) -> Neighbors { + self.neighbors_directed(a, Outgoing) + } + + /// Return an iterator of all neighbors that have an edge between them and + /// `a`, in the specified direction. + /// If the graph's edges are undirected, this is equivalent to *.neighbors(a)*. + /// + /// - `Directed`, `Outgoing`: All edges from `a`. + /// - `Directed`, `Incoming`: All edges to `a`. + /// - `Undirected`: All edges from or to `a`. + /// + /// Produces an empty iterator if the node doesn't exist.
+ /// Iterator element type is `NodeIndex`. + /// + /// For a `Directed` graph, neighbors are listed in reverse order of their + /// addition to the graph, so the most recently added edge's neighbor is + /// listed first. The order in an `Undirected` graph is arbitrary. + /// + /// Use [`.neighbors_directed(a, dir).detach()`][1] to get a neighbor walker that does + /// not borrow from the graph. + /// + /// [1]: struct.Neighbors.html#method.detach + pub fn neighbors_directed(&self, a: NodeIndex, dir: Direction) -> Neighbors { + let mut iter = self.neighbors_undirected(a); + if self.is_directed() { + let k = dir.index(); + iter.next[1 - k] = EdgeIndex::end(); + iter.skip_start = NodeIndex::end(); + } + iter + } + + /// Return an iterator of all neighbors that have an edge between them and + /// `a`, in either direction. + /// If the graph's edges are undirected, this is equivalent to *.neighbors(a)*. + /// + /// - `Directed` and `Undirected`: All edges from or to `a`. + /// + /// Produces an empty iterator if the node doesn't exist.
+ /// Iterator element type is `NodeIndex`. + /// + /// Use [`.neighbors_undirected(a).detach()`][1] to get a neighbor walker that does + /// not borrow from the graph. + /// + /// [1]: struct.Neighbors.html#method.detach + /// + pub fn neighbors_undirected(&self, a: NodeIndex) -> Neighbors { + Neighbors { + skip_start: a, + edges: &self.edges, + next: match self.nodes.get(a.index()) { + None => [EdgeIndex::end(), EdgeIndex::end()], + Some(n) => n.next, + }, + } + } + + /// Return an iterator of all edges of `a`. + /// + /// - `Directed`: Outgoing edges from `a`. + /// - `Undirected`: All edges connected to `a`. + /// + /// Produces an empty iterator if the node doesn't exist.
+ /// Iterator element type is `EdgeReference`. + pub fn edges(&self, a: NodeIndex) -> Edges { + self.edges_directed(a, Outgoing) + } + + /// Return an iterator of all edges of `a`, in the specified direction. + /// + /// - `Directed`, `Outgoing`: All edges from `a`. + /// - `Directed`, `Incoming`: All edges to `a`. + /// - `Undirected`, `Outgoing`: All edges connected to `a`, with `a` being the source of each + /// edge. + /// - `Undirected`, `Incoming`: All edges connected to `a`, with `a` being the target of each + /// edge. + /// + /// Produces an empty iterator if the node `a` doesn't exist.
+ /// Iterator element type is `EdgeReference`. + pub fn edges_directed(&self, a: NodeIndex, dir: Direction) -> Edges { + Edges { + skip_start: a, + edges: &self.edges, + direction: dir, + next: match self.nodes.get(a.index()) { + None => [EdgeIndex::end(), EdgeIndex::end()], + Some(n) => n.next, + }, + ty: PhantomData, + } + } + + /// Return an iterator over all the edges connecting `a` and `b`. + /// + /// - `Directed`: Outgoing edges from `a`. + /// - `Undirected`: All edges connected to `a`. + /// + /// Iterator element type is `EdgeReference`. + pub fn edges_connecting( + &self, + a: NodeIndex, + b: NodeIndex, + ) -> EdgesConnecting { + EdgesConnecting { + target_node: b, + edges: self.edges_directed(a, Direction::Outgoing), + ty: PhantomData, + } + } + + /// Lookup if there is an edge from `a` to `b`. + /// + /// Computes in **O(e')** time, where **e'** is the number of edges + /// connected to `a` (and `b`, if the graph edges are undirected). + pub fn contains_edge(&self, a: NodeIndex, b: NodeIndex) -> bool { + self.find_edge(a, b).is_some() + } + + /// Lookup an edge from `a` to `b`. + /// + /// Computes in **O(e')** time, where **e'** is the number of edges + /// connected to `a` (and `b`, if the graph edges are undirected). + pub fn find_edge(&self, a: NodeIndex, b: NodeIndex) -> Option> { + if !self.is_directed() { + self.find_edge_undirected(a, b).map(|(ix, _)| ix) + } else { + match self.nodes.get(a.index()) { + None => None, + Some(node) => self.find_edge_directed_from_node(node, b), + } + } + } + + fn find_edge_directed_from_node( + &self, + node: &Node, + b: NodeIndex, + ) -> Option> { + let mut edix = node.next[0]; + while let Some(edge) = self.edges.get(edix.index()) { + if edge.node[1] == b { + return Some(edix); + } + edix = edge.next[0]; + } + None + } + + /// Lookup an edge between `a` and `b`, in either direction. + /// + /// If the graph is undirected, then this is equivalent to `.find_edge()`. + /// + /// Return the edge index and its directionality, with `Outgoing` meaning + /// from `a` to `b` and `Incoming` the reverse, + /// or `None` if the edge does not exist. + pub fn find_edge_undirected( + &self, + a: NodeIndex, + b: NodeIndex, + ) -> Option<(EdgeIndex, Direction)> { + match self.nodes.get(a.index()) { + None => None, + Some(node) => self.find_edge_undirected_from_node(node, b), + } + } + + fn find_edge_undirected_from_node( + &self, + node: &Node, + b: NodeIndex, + ) -> Option<(EdgeIndex, Direction)> { + for &d in &DIRECTIONS { + let k = d.index(); + let mut edix = node.next[k]; + while let Some(edge) = self.edges.get(edix.index()) { + if edge.node[1 - k] == b { + return Some((edix, d)); + } + edix = edge.next[k]; + } + } + None + } + + /// Return an iterator over either the nodes without edges to them + /// (`Incoming`) or from them (`Outgoing`). + /// + /// An *internal* node has both incoming and outgoing edges. + /// The nodes in `.externals(Incoming)` are the source nodes and + /// `.externals(Outgoing)` are the sinks of the graph. + /// + /// For a graph with undirected edges, both the sinks and the sources are + /// just the nodes without edges. + /// + /// The whole iteration computes in **O(|V|)** time. + pub fn externals(&self, dir: Direction) -> Externals { + Externals { + iter: self.nodes.iter().enumerate(), + dir, + ty: PhantomData, + } + } + + /// Return an iterator over the node indices of the graph. + /// + /// For example, in a rare case where a graph algorithm were not applicable, + /// the following code will iterate through all nodes to find a + /// specific index: + /// + /// ``` + /// # use petgraph::Graph; + /// # let mut g = Graph::<&str, i32>::new(); + /// # g.add_node("book"); + /// let index = g.node_indices().find(|i| g[*i] == "book").unwrap(); + /// ``` + pub fn node_indices(&self) -> NodeIndices { + NodeIndices { + r: 0..self.node_count(), + ty: PhantomData, + } + } + + /// Return an iterator yielding mutable access to all node weights. + /// + /// The order in which weights are yielded matches the order of their + /// node indices. + pub fn node_weights_mut(&mut self) -> NodeWeightsMut { + NodeWeightsMut { + nodes: self.nodes.iter_mut(), + } + } + + /// Return an iterator yielding immutable access to all node weights. + /// + /// The order in which weights are yielded matches the order of their + /// node indices. + pub fn node_weights(&self) -> NodeWeights { + NodeWeights { + nodes: self.nodes.iter(), + } + } + + /// Return an iterator over the edge indices of the graph + pub fn edge_indices(&self) -> EdgeIndices { + EdgeIndices { + r: 0..self.edge_count(), + ty: PhantomData, + } + } + + /// Create an iterator over all edges, in indexed order. + /// + /// Iterator element type is `EdgeReference`. + pub fn edge_references(&self) -> EdgeReferences { + EdgeReferences { + iter: self.edges.iter().enumerate(), + } + } + + /// Return an iterator yielding immutable access to all edge weights. + /// + /// The order in which weights are yielded matches the order of their + /// edge indices. + pub fn edge_weights(&self) -> EdgeWeights { + EdgeWeights { + edges: self.edges.iter(), + } + } + /// Return an iterator yielding mutable access to all edge weights. + /// + /// The order in which weights are yielded matches the order of their + /// edge indices. + pub fn edge_weights_mut(&mut self) -> EdgeWeightsMut { + EdgeWeightsMut { + edges: self.edges.iter_mut(), + } + } + + // Remaining methods are of the more internal flavour, read-only access to + // the data structure's internals. + + /// Access the internal node array. + pub fn raw_nodes(&self) -> &[Node] { + &self.nodes + } + + /// Access the internal edge array. + pub fn raw_edges(&self) -> &[Edge] { + &self.edges + } + + #[allow(clippy::type_complexity)] + /// Convert the graph into a vector of Nodes and a vector of Edges + pub fn into_nodes_edges(self) -> (Vec>, Vec>) { + (self.nodes, self.edges) + } + + /// Accessor for data structure internals: the first edge in the given direction. + pub fn first_edge(&self, a: NodeIndex, dir: Direction) -> Option> { + match self.nodes.get(a.index()) { + None => None, + Some(node) => { + let edix = node.next[dir.index()]; + if edix == EdgeIndex::end() { + None + } else { + Some(edix) + } + } + } + } + + /// Accessor for data structure internals: the next edge for the given direction. + pub fn next_edge(&self, e: EdgeIndex, dir: Direction) -> Option> { + match self.edges.get(e.index()) { + None => None, + Some(node) => { + let edix = node.next[dir.index()]; + if edix == EdgeIndex::end() { + None + } else { + Some(edix) + } + } + } + } + + /// Index the `Graph` by two indices, any combination of + /// node or edge indices is fine. + /// + /// **Panics** if the indices are equal or if they are out of bounds. + /// + /// ``` + /// use petgraph::{Graph, Incoming}; + /// use petgraph::visit::Dfs; + /// + /// let mut gr = Graph::new(); + /// let a = gr.add_node(0.); + /// let b = gr.add_node(0.); + /// let c = gr.add_node(0.); + /// gr.add_edge(a, b, 3.); + /// gr.add_edge(b, c, 2.); + /// gr.add_edge(c, b, 1.); + /// + /// // walk the graph and sum incoming edges into the node weight + /// let mut dfs = Dfs::new(&gr, a); + /// while let Some(node) = dfs.next(&gr) { + /// // use a walker -- a detached neighbors iterator + /// let mut edges = gr.neighbors_directed(node, Incoming).detach(); + /// while let Some(edge) = edges.next_edge(&gr) { + /// let (nw, ew) = gr.index_twice_mut(node, edge); + /// *nw += *ew; + /// } + /// } + /// + /// // check the result + /// assert_eq!(gr[a], 0.); + /// assert_eq!(gr[b], 4.); + /// assert_eq!(gr[c], 2.); + /// ``` + pub fn index_twice_mut( + &mut self, + i: T, + j: U, + ) -> ( + &mut >::Output, + &mut >::Output, + ) + where + Self: IndexMut + IndexMut, + T: GraphIndex, + U: GraphIndex, + { + assert!(T::is_node_index() != U::is_node_index() || i.index() != j.index()); + + // Allow two mutable indexes here -- they are nonoverlapping + unsafe { + let self_mut = self as *mut _; + ( + >::index_mut(&mut *self_mut, i), + >::index_mut(&mut *self_mut, j), + ) + } + } + + /// Reverse the direction of all edges + pub fn reverse(&mut self) { + // swap edge endpoints, + // edge incoming / outgoing lists, + // node incoming / outgoing lists + for edge in &mut self.edges { + edge.node.swap(0, 1); + edge.next.swap(0, 1); + } + for node in &mut self.nodes { + node.next.swap(0, 1); + } + } + + /// Remove all nodes and edges + pub fn clear(&mut self) { + self.nodes.clear(); + self.edges.clear(); + } + + /// Remove all edges + pub fn clear_edges(&mut self) { + self.edges.clear(); + for node in &mut self.nodes { + node.next = [EdgeIndex::end(), EdgeIndex::end()]; + } + } + + /// Return the current node and edge capacity of the graph. + pub fn capacity(&self) -> (usize, usize) { + (self.nodes.capacity(), self.edges.capacity()) + } + + /// Reserves capacity for at least `additional` more nodes to be inserted in + /// the graph. Graph may reserve more space to avoid frequent reallocations. + /// + /// **Panics** if the new capacity overflows `usize`. + pub fn reserve_nodes(&mut self, additional: usize) { + self.nodes.reserve(additional); + } + + /// Reserves capacity for at least `additional` more edges to be inserted in + /// the graph. Graph may reserve more space to avoid frequent reallocations. + /// + /// **Panics** if the new capacity overflows `usize`. + pub fn reserve_edges(&mut self, additional: usize) { + self.edges.reserve(additional); + } + + /// Reserves the minimum capacity for exactly `additional` more nodes to be + /// inserted in the graph. Does nothing if the capacity is already + /// sufficient. + /// + /// Prefer `reserve_nodes` if future insertions are expected. + /// + /// **Panics** if the new capacity overflows `usize`. + pub fn reserve_exact_nodes(&mut self, additional: usize) { + self.nodes.reserve_exact(additional); + } + + /// Reserves the minimum capacity for exactly `additional` more edges to be + /// inserted in the graph. + /// Does nothing if the capacity is already sufficient. + /// + /// Prefer `reserve_edges` if future insertions are expected. + /// + /// **Panics** if the new capacity overflows `usize`. + pub fn reserve_exact_edges(&mut self, additional: usize) { + self.edges.reserve_exact(additional); + } + + /// Shrinks the capacity of the underlying nodes collection as much as possible. + pub fn shrink_to_fit_nodes(&mut self) { + self.nodes.shrink_to_fit(); + } + + /// Shrinks the capacity of the underlying edges collection as much as possible. + pub fn shrink_to_fit_edges(&mut self) { + self.edges.shrink_to_fit(); + } + + /// Shrinks the capacity of the graph as much as possible. + pub fn shrink_to_fit(&mut self) { + self.nodes.shrink_to_fit(); + self.edges.shrink_to_fit(); + } + + /// Keep all nodes that return `true` from the `visit` closure, + /// remove the others. + /// + /// `visit` is provided a proxy reference to the graph, so that + /// the graph can be walked and associated data modified. + /// + /// The order nodes are visited is not specified. + pub fn retain_nodes(&mut self, mut visit: F) + where + F: FnMut(Frozen, NodeIndex) -> bool, + { + for index in self.node_indices().rev() { + if !visit(Frozen(self), index) { + let ret = self.remove_node(index); + debug_assert!(ret.is_some()); + let _ = ret; + } + } + } + + /// Keep all edges that return `true` from the `visit` closure, + /// remove the others. + /// + /// `visit` is provided a proxy reference to the graph, so that + /// the graph can be walked and associated data modified. + /// + /// The order edges are visited is not specified. + pub fn retain_edges(&mut self, mut visit: F) + where + F: FnMut(Frozen, EdgeIndex) -> bool, + { + for index in self.edge_indices().rev() { + if !visit(Frozen(self), index) { + let ret = self.remove_edge(index); + debug_assert!(ret.is_some()); + let _ = ret; + } + } + } + + /// Create a new `Graph` from an iterable of edges. + /// + /// Node weights `N` are set to default values. + /// Edge weights `E` may either be specified in the list, + /// or they are filled with default values. + /// + /// Nodes are inserted automatically to match the edges. + /// + /// ``` + /// use petgraph::Graph; + /// + /// let gr = Graph::<(), i32>::from_edges(&[ + /// (0, 1), (0, 2), (0, 3), + /// (1, 2), (1, 3), + /// (2, 3), + /// ]); + /// ``` + pub fn from_edges(iterable: I) -> Self + where + I: IntoIterator, + I::Item: IntoWeightedEdge, + >::NodeId: Into>, + N: Default, + { + let mut g = Self::with_capacity(0, 0); + g.extend_with_edges(iterable); + g + } + + /// Extend the graph from an iterable of edges. + /// + /// Node weights `N` are set to default values. + /// Edge weights `E` may either be specified in the list, + /// or they are filled with default values. + /// + /// Nodes are inserted automatically to match the edges. + pub fn extend_with_edges(&mut self, iterable: I) + where + I: IntoIterator, + I::Item: IntoWeightedEdge, + >::NodeId: Into>, + N: Default, + { + let iter = iterable.into_iter(); + let (low, _) = iter.size_hint(); + self.edges.reserve(low); + + for elt in iter { + let (source, target, weight) = elt.into_weighted_edge(); + let (source, target) = (source.into(), target.into()); + let nx = cmp::max(source, target); + while nx.index() >= self.node_count() { + self.add_node(N::default()); + } + self.add_edge(source, target, weight); + } + } + + /// Create a new `Graph` by mapping node and + /// edge weights to new values. + /// + /// The resulting graph has the same structure and the same + /// graph indices as `self`. + pub fn map<'a, F, G, N2, E2>( + &'a self, + mut node_map: F, + mut edge_map: G, + ) -> Graph + where + F: FnMut(NodeIndex, &'a N) -> N2, + G: FnMut(EdgeIndex, &'a E) -> E2, + { + let mut g = Graph::with_capacity(self.node_count(), self.edge_count()); + g.nodes.extend(enumerate(&self.nodes).map(|(i, node)| Node { + weight: node_map(NodeIndex::new(i), &node.weight), + next: node.next, + })); + g.edges.extend(enumerate(&self.edges).map(|(i, edge)| Edge { + weight: edge_map(EdgeIndex::new(i), &edge.weight), + next: edge.next, + node: edge.node, + })); + g + } + + /// Create a new `Graph` by mapping nodes and edges. + /// A node or edge may be mapped to `None` to exclude it from + /// the resulting graph. + /// + /// Nodes are mapped first with the `node_map` closure, then + /// `edge_map` is called for the edges that have not had any endpoint + /// removed. + /// + /// The resulting graph has the structure of a subgraph of the original graph. + /// If no nodes are removed, the resulting graph has compatible node + /// indices; if neither nodes nor edges are removed, the result has + /// the same graph indices as `self`. + pub fn filter_map<'a, F, G, N2, E2>( + &'a self, + mut node_map: F, + mut edge_map: G, + ) -> Graph + where + F: FnMut(NodeIndex, &'a N) -> Option, + G: FnMut(EdgeIndex, &'a E) -> Option, + { + let mut g = Graph::with_capacity(0, 0); + // mapping from old node index to new node index, end represents removed. + let mut node_index_map = vec![NodeIndex::end(); self.node_count()]; + for (i, node) in enumerate(&self.nodes) { + if let Some(nw) = node_map(NodeIndex::new(i), &node.weight) { + node_index_map[i] = g.add_node(nw); + } + } + for (i, edge) in enumerate(&self.edges) { + // skip edge if any endpoint was removed + let source = node_index_map[edge.source().index()]; + let target = node_index_map[edge.target().index()]; + if source != NodeIndex::end() && target != NodeIndex::end() { + if let Some(ew) = edge_map(EdgeIndex::new(i), &edge.weight) { + g.add_edge(source, target, ew); + } + } + } + g + } + + /// Convert the graph into either undirected or directed. No edge adjustments + /// are done, so you may want to go over the result to remove or add edges. + /// + /// Computes in **O(1)** time. + pub fn into_edge_type(self) -> Graph + where + NewTy: EdgeType, + { + Graph { + nodes: self.nodes, + edges: self.edges, + ty: PhantomData, + } + } + + // + // internal methods + // + #[cfg(feature = "serde-1")] + /// Fix up node and edge links after deserialization + fn link_edges(&mut self) -> Result<(), NodeIndex> { + for (edge_index, edge) in enumerate(&mut self.edges) { + let a = edge.source(); + let b = edge.target(); + let edge_idx = EdgeIndex::new(edge_index); + match index_twice(&mut self.nodes, a.index(), b.index()) { + Pair::None => return Err(if a > b { a } else { b }), + Pair::One(an) => { + edge.next = an.next; + an.next[0] = edge_idx; + an.next[1] = edge_idx; + } + Pair::Both(an, bn) => { + // a and b are different indices + edge.next = [an.next[0], bn.next[1]]; + an.next[0] = edge_idx; + bn.next[1] = edge_idx; + } + } + } + Ok(()) + } +} + +/// An iterator over either the nodes without edges to them or from them. +#[derive(Debug, Clone)] +pub struct Externals<'a, N: 'a, Ty, Ix: IndexType = DefaultIx> { + iter: iter::Enumerate>>, + dir: Direction, + ty: PhantomData, +} + +impl<'a, N: 'a, Ty, Ix> Iterator for Externals<'a, N, Ty, Ix> +where + Ty: EdgeType, + Ix: IndexType, +{ + type Item = NodeIndex; + fn next(&mut self) -> Option> { + let k = self.dir.index(); + loop { + match self.iter.next() { + None => return None, + Some((index, node)) => { + if node.next[k] == EdgeIndex::end() + && (Ty::is_directed() || node.next[1 - k] == EdgeIndex::end()) + { + return Some(NodeIndex::new(index)); + } else { + continue; + } + } + } + } + } + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } +} + +/// Iterator over the neighbors of a node. +/// +/// Iterator element type is `NodeIndex`. +/// +/// Created with [`.neighbors()`][1], [`.neighbors_directed()`][2] or +/// [`.neighbors_undirected()`][3]. +/// +/// [1]: struct.Graph.html#method.neighbors +/// [2]: struct.Graph.html#method.neighbors_directed +/// [3]: struct.Graph.html#method.neighbors_undirected +#[derive(Debug)] +pub struct Neighbors<'a, E: 'a, Ix: 'a = DefaultIx> { + /// starting node to skip over + skip_start: NodeIndex, + edges: &'a [Edge], + next: [EdgeIndex; 2], +} + +impl Iterator for Neighbors<'_, E, Ix> +where + Ix: IndexType, +{ + type Item = NodeIndex; + + fn next(&mut self) -> Option> { + // First any outgoing edges + match self.edges.get(self.next[0].index()) { + None => {} + Some(edge) => { + self.next[0] = edge.next[0]; + return Some(edge.node[1]); + } + } + // Then incoming edges + // For an "undirected" iterator (traverse both incoming + // and outgoing edge lists), make sure we don't double + // count selfloops by skipping them in the incoming list. + while let Some(edge) = self.edges.get(self.next[1].index()) { + self.next[1] = edge.next[1]; + if edge.node[0] != self.skip_start { + return Some(edge.node[0]); + } + } + None + } +} + +impl Clone for Neighbors<'_, E, Ix> +where + Ix: IndexType, +{ + clone_fields!(Neighbors, skip_start, edges, next,); +} + +impl Neighbors<'_, E, Ix> +where + Ix: IndexType, +{ + /// Return a “walker” object that can be used to step through the + /// neighbors and edges from the origin node. + /// + /// Note: The walker does not borrow from the graph, this is to allow mixing + /// edge walking with mutating the graph's weights. + pub fn detach(&self) -> WalkNeighbors { + WalkNeighbors { + skip_start: self.skip_start, + next: self.next, + } + } +} + +struct EdgesWalkerMut<'a, E: 'a, Ix: IndexType = DefaultIx> { + edges: &'a mut [Edge], + next: EdgeIndex, + dir: Direction, +} + +fn edges_walker_mut( + edges: &mut [Edge], + next: EdgeIndex, + dir: Direction, +) -> EdgesWalkerMut +where + Ix: IndexType, +{ + EdgesWalkerMut { edges, next, dir } +} + +impl EdgesWalkerMut<'_, E, Ix> +where + Ix: IndexType, +{ + fn next_edge(&mut self) -> Option<&mut Edge> { + self.next().map(|t| t.1) + } + + fn next(&mut self) -> Option<(EdgeIndex, &mut Edge)> { + let this_index = self.next; + let k = self.dir.index(); + match self.edges.get_mut(self.next.index()) { + None => None, + Some(edge) => { + self.next = edge.next[k]; + Some((this_index, edge)) + } + } + } +} + +impl<'a, N, E, Ty, Ix> visit::IntoEdges for &'a Graph +where + Ty: EdgeType, + Ix: IndexType, +{ + type Edges = Edges<'a, E, Ty, Ix>; + fn edges(self, a: Self::NodeId) -> Self::Edges { + self.edges(a) + } +} + +impl<'a, N, E, Ty, Ix> visit::IntoEdgesDirected for &'a Graph +where + Ty: EdgeType, + Ix: IndexType, +{ + type EdgesDirected = Edges<'a, E, Ty, Ix>; + fn edges_directed(self, a: Self::NodeId, dir: Direction) -> Self::EdgesDirected { + self.edges_directed(a, dir) + } +} + +/// Iterator over the edges of from or to a node +#[derive(Debug)] +pub struct Edges<'a, E: 'a, Ty, Ix: 'a = DefaultIx> +where + Ty: EdgeType, + Ix: IndexType, +{ + /// starting node to skip over + skip_start: NodeIndex, + edges: &'a [Edge], + + /// Next edge to visit. + next: [EdgeIndex; 2], + + /// For directed graphs: the direction to iterate in + /// For undirected graphs: the direction of edges + direction: Direction, + ty: PhantomData, +} + +impl<'a, E, Ty, Ix> Iterator for Edges<'a, E, Ty, Ix> +where + Ty: EdgeType, + Ix: IndexType, +{ + type Item = EdgeReference<'a, E, Ix>; + + fn next(&mut self) -> Option { + // type direction | iterate over reverse + // | + // Directed Outgoing | outgoing no + // Directed Incoming | incoming no + // Undirected Outgoing | both incoming + // Undirected Incoming | both outgoing + + // For iterate_over, "both" is represented as None. + // For reverse, "no" is represented as None. + let (iterate_over, reverse) = if Ty::is_directed() { + (Some(self.direction), None) + } else { + (None, Some(self.direction.opposite())) + }; + + if iterate_over.unwrap_or(Outgoing) == Outgoing { + let i = self.next[0].index(); + if let Some(Edge { node, weight, next }) = self.edges.get(i) { + self.next[0] = next[0]; + return Some(EdgeReference { + index: edge_index(i), + node: if reverse == Some(Outgoing) { + swap_pair(*node) + } else { + *node + }, + weight, + }); + } + } + + if iterate_over.unwrap_or(Incoming) == Incoming { + while let Some(Edge { node, weight, next }) = self.edges.get(self.next[1].index()) { + let edge_index = self.next[1]; + self.next[1] = next[1]; + // In any of the "both" situations, self-loops would be iterated over twice. + // Skip them here. + if iterate_over.is_none() && node[0] == self.skip_start { + continue; + } + + return Some(EdgeReference { + index: edge_index, + node: if reverse == Some(Incoming) { + swap_pair(*node) + } else { + *node + }, + weight, + }); + } + } + + None + } +} + +/// Iterator over the multiple directed edges connecting a source node to a target node +#[derive(Debug, Clone)] +pub struct EdgesConnecting<'a, E: 'a, Ty, Ix: 'a = DefaultIx> +where + Ty: EdgeType, + Ix: IndexType, +{ + target_node: NodeIndex, + edges: Edges<'a, E, Ty, Ix>, + ty: PhantomData, +} + +impl<'a, E, Ty, Ix> Iterator for EdgesConnecting<'a, E, Ty, Ix> +where + Ty: EdgeType, + Ix: IndexType, +{ + type Item = EdgeReference<'a, E, Ix>; + + fn next(&mut self) -> Option> { + let target_node = self.target_node; + self.edges + .by_ref() + .find(|&edge| edge.node[1] == target_node) + } + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.edges.size_hint(); + (0, upper) + } +} + +fn swap_pair(mut x: [T; 2]) -> [T; 2] { + x.swap(0, 1); + x +} + +impl Clone for Edges<'_, E, Ty, Ix> +where + Ix: IndexType, + Ty: EdgeType, +{ + fn clone(&self) -> Self { + Edges { + skip_start: self.skip_start, + edges: self.edges, + next: self.next, + direction: self.direction, + ty: self.ty, + } + } +} + +/// Iterator yielding immutable access to all node weights. +pub struct NodeWeights<'a, N: 'a, Ix: IndexType = DefaultIx> { + nodes: ::std::slice::Iter<'a, Node>, +} +impl<'a, N, Ix> Iterator for NodeWeights<'a, N, Ix> +where + Ix: IndexType, +{ + type Item = &'a N; + + fn next(&mut self) -> Option<&'a N> { + self.nodes.next().map(|node| &node.weight) + } + + fn size_hint(&self) -> (usize, Option) { + self.nodes.size_hint() + } +} +/// Iterator yielding mutable access to all node weights. +#[derive(Debug)] +pub struct NodeWeightsMut<'a, N: 'a, Ix: IndexType = DefaultIx> { + nodes: ::std::slice::IterMut<'a, Node>, // TODO: change type to something that implements Clone? +} + +impl<'a, N, Ix> Iterator for NodeWeightsMut<'a, N, Ix> +where + Ix: IndexType, +{ + type Item = &'a mut N; + + fn next(&mut self) -> Option<&'a mut N> { + self.nodes.next().map(|node| &mut node.weight) + } + + fn size_hint(&self) -> (usize, Option) { + self.nodes.size_hint() + } +} + +/// Iterator yielding immutable access to all edge weights. +pub struct EdgeWeights<'a, E: 'a, Ix: IndexType = DefaultIx> { + edges: ::std::slice::Iter<'a, Edge>, +} + +impl<'a, E, Ix> Iterator for EdgeWeights<'a, E, Ix> +where + Ix: IndexType, +{ + type Item = &'a E; + + fn next(&mut self) -> Option<&'a E> { + self.edges.next().map(|edge| &edge.weight) + } + + fn size_hint(&self) -> (usize, Option) { + self.edges.size_hint() + } +} + +/// Iterator yielding mutable access to all edge weights. +#[derive(Debug)] +pub struct EdgeWeightsMut<'a, E: 'a, Ix: IndexType = DefaultIx> { + edges: ::std::slice::IterMut<'a, Edge>, // TODO: change type to something that implements Clone? +} + +impl<'a, E, Ix> Iterator for EdgeWeightsMut<'a, E, Ix> +where + Ix: IndexType, +{ + type Item = &'a mut E; + + fn next(&mut self) -> Option<&'a mut E> { + self.edges.next().map(|edge| &mut edge.weight) + } + + fn size_hint(&self) -> (usize, Option) { + self.edges.size_hint() + } +} + +/// Index the `Graph` by `NodeIndex` to access node weights. +/// +/// **Panics** if the node doesn't exist. +impl Index> for Graph +where + Ty: EdgeType, + Ix: IndexType, +{ + type Output = N; + fn index(&self, index: NodeIndex) -> &N { + &self.nodes[index.index()].weight + } +} + +/// Index the `Graph` by `NodeIndex` to access node weights. +/// +/// **Panics** if the node doesn't exist. +impl IndexMut> for Graph +where + Ty: EdgeType, + Ix: IndexType, +{ + fn index_mut(&mut self, index: NodeIndex) -> &mut N { + &mut self.nodes[index.index()].weight + } +} + +/// Index the `Graph` by `EdgeIndex` to access edge weights. +/// +/// **Panics** if the edge doesn't exist. +impl Index> for Graph +where + Ty: EdgeType, + Ix: IndexType, +{ + type Output = E; + fn index(&self, index: EdgeIndex) -> &E { + &self.edges[index.index()].weight + } +} + +/// Index the `Graph` by `EdgeIndex` to access edge weights. +/// +/// **Panics** if the edge doesn't exist. +impl IndexMut> for Graph +where + Ty: EdgeType, + Ix: IndexType, +{ + fn index_mut(&mut self, index: EdgeIndex) -> &mut E { + &mut self.edges[index.index()].weight + } +} + +/// Create a new empty `Graph`. +impl Default for Graph +where + Ty: EdgeType, + Ix: IndexType, +{ + fn default() -> Self { + Self::with_capacity(0, 0) + } +} + +/// A `GraphIndex` is a node or edge index. +pub trait GraphIndex: Copy { + #[doc(hidden)] + fn index(&self) -> usize; + #[doc(hidden)] + fn is_node_index() -> bool; +} + +impl GraphIndex for NodeIndex { + #[inline] + #[doc(hidden)] + fn index(&self) -> usize { + NodeIndex::index(*self) + } + #[inline] + #[doc(hidden)] + fn is_node_index() -> bool { + true + } +} + +impl GraphIndex for EdgeIndex { + #[inline] + #[doc(hidden)] + fn index(&self) -> usize { + EdgeIndex::index(*self) + } + #[inline] + #[doc(hidden)] + fn is_node_index() -> bool { + false + } +} + +/// A “walker” object that can be used to step through the edge list of a node. +/// +/// Created with [`.detach()`](struct.Neighbors.html#method.detach). +/// +/// The walker does not borrow from the graph, so it lets you step through +/// neighbors or incident edges while also mutating graph weights, as +/// in the following example: +/// +/// ``` +/// use petgraph::{Graph, Incoming}; +/// use petgraph::visit::Dfs; +/// +/// let mut gr = Graph::new(); +/// let a = gr.add_node(0.); +/// let b = gr.add_node(0.); +/// let c = gr.add_node(0.); +/// gr.add_edge(a, b, 3.); +/// gr.add_edge(b, c, 2.); +/// gr.add_edge(c, b, 1.); +/// +/// // step through the graph and sum incoming edges into the node weight +/// let mut dfs = Dfs::new(&gr, a); +/// while let Some(node) = dfs.next(&gr) { +/// // use a detached neighbors walker +/// let mut edges = gr.neighbors_directed(node, Incoming).detach(); +/// while let Some(edge) = edges.next_edge(&gr) { +/// gr[node] += gr[edge]; +/// } +/// } +/// +/// // check the result +/// assert_eq!(gr[a], 0.); +/// assert_eq!(gr[b], 4.); +/// assert_eq!(gr[c], 2.); +/// ``` +pub struct WalkNeighbors { + skip_start: NodeIndex, + next: [EdgeIndex; 2], +} + +impl Clone for WalkNeighbors +where + Ix: IndexType, +{ + fn clone(&self) -> Self { + WalkNeighbors { + skip_start: self.skip_start, + next: self.next, + } + } +} + +impl WalkNeighbors { + /// Step to the next edge and its endpoint node in the walk for graph `g`. + /// + /// The next node indices are always the others than the starting point + /// where the `WalkNeighbors` value was created. + /// For an `Outgoing` walk, the target nodes, + /// for an `Incoming` walk, the source nodes of the edge. + pub fn next( + &mut self, + g: &Graph, + ) -> Option<(EdgeIndex, NodeIndex)> { + // First any outgoing edges + match g.edges.get(self.next[0].index()) { + None => {} + Some(edge) => { + let ed = self.next[0]; + self.next[0] = edge.next[0]; + return Some((ed, edge.node[1])); + } + } + // Then incoming edges + // For an "undirected" iterator (traverse both incoming + // and outgoing edge lists), make sure we don't double + // count selfloops by skipping them in the incoming list. + while let Some(edge) = g.edges.get(self.next[1].index()) { + let ed = self.next[1]; + self.next[1] = edge.next[1]; + if edge.node[0] != self.skip_start { + return Some((ed, edge.node[0])); + } + } + None + } + + pub fn next_node( + &mut self, + g: &Graph, + ) -> Option> { + self.next(g).map(|t| t.1) + } + + pub fn next_edge( + &mut self, + g: &Graph, + ) -> Option> { + self.next(g).map(|t| t.0) + } +} + +/// Iterator over the node indices of a graph. +#[derive(Clone, Debug)] +pub struct NodeIndices { + r: Range, + ty: PhantomData Ix>, +} + +impl Iterator for NodeIndices { + type Item = NodeIndex; + + fn next(&mut self) -> Option { + self.r.next().map(node_index) + } + + fn size_hint(&self) -> (usize, Option) { + self.r.size_hint() + } +} + +impl DoubleEndedIterator for NodeIndices { + fn next_back(&mut self) -> Option { + self.r.next_back().map(node_index) + } +} + +impl ExactSizeIterator for NodeIndices {} + +/// Iterator over the edge indices of a graph. +#[derive(Clone, Debug)] +pub struct EdgeIndices { + r: Range, + ty: PhantomData Ix>, +} + +impl Iterator for EdgeIndices { + type Item = EdgeIndex; + + fn next(&mut self) -> Option { + self.r.next().map(edge_index) + } + + fn size_hint(&self) -> (usize, Option) { + self.r.size_hint() + } +} + +impl DoubleEndedIterator for EdgeIndices { + fn next_back(&mut self) -> Option { + self.r.next_back().map(edge_index) + } +} + +impl ExactSizeIterator for EdgeIndices {} + +/// Reference to a `Graph` edge. +#[derive(Debug)] +pub struct EdgeReference<'a, E: 'a, Ix = DefaultIx> { + index: EdgeIndex, + node: [NodeIndex; 2], + weight: &'a E, +} + +impl Clone for EdgeReference<'_, E, Ix> { + fn clone(&self) -> Self { + *self + } +} + +impl Copy for EdgeReference<'_, E, Ix> {} + +impl PartialEq for EdgeReference<'_, E, Ix> +where + E: PartialEq, +{ + fn eq(&self, rhs: &Self) -> bool { + self.index == rhs.index && self.weight == rhs.weight + } +} + +impl visit::GraphBase for Graph +where + Ix: IndexType, +{ + type NodeId = NodeIndex; + type EdgeId = EdgeIndex; +} + +impl visit::Visitable for Graph +where + Ty: EdgeType, + Ix: IndexType, +{ + type Map = FixedBitSet; + fn visit_map(&self) -> FixedBitSet { + FixedBitSet::with_capacity(self.node_count()) + } + + fn reset_map(&self, map: &mut Self::Map) { + map.clear(); + map.grow(self.node_count()); + } +} + +impl visit::GraphProp for Graph +where + Ty: EdgeType, + Ix: IndexType, +{ + type EdgeType = Ty; +} + +impl<'a, N, E: 'a, Ty, Ix> visit::IntoNodeIdentifiers for &'a Graph +where + Ty: EdgeType, + Ix: IndexType, +{ + type NodeIdentifiers = NodeIndices; + fn node_identifiers(self) -> NodeIndices { + Graph::node_indices(self) + } +} + +impl visit::NodeCount for Graph +where + Ty: EdgeType, + Ix: IndexType, +{ + fn node_count(&self) -> usize { + self.node_count() + } +} + +impl visit::NodeIndexable for Graph +where + Ty: EdgeType, + Ix: IndexType, +{ + #[inline] + fn node_bound(&self) -> usize { + self.node_count() + } + #[inline] + fn to_index(&self, ix: NodeIndex) -> usize { + ix.index() + } + #[inline] + fn from_index(&self, ix: usize) -> Self::NodeId { + NodeIndex::new(ix) + } +} + +impl visit::NodeCompactIndexable for Graph +where + Ty: EdgeType, + Ix: IndexType, +{ +} + +impl<'a, N, E: 'a, Ty, Ix> visit::IntoNeighbors for &'a Graph +where + Ty: EdgeType, + Ix: IndexType, +{ + type Neighbors = Neighbors<'a, E, Ix>; + fn neighbors(self, n: NodeIndex) -> Neighbors<'a, E, Ix> { + Graph::neighbors(self, n) + } +} + +impl<'a, N, E: 'a, Ty, Ix> visit::IntoNeighborsDirected for &'a Graph +where + Ty: EdgeType, + Ix: IndexType, +{ + type NeighborsDirected = Neighbors<'a, E, Ix>; + fn neighbors_directed(self, n: NodeIndex, d: Direction) -> Neighbors<'a, E, Ix> { + Graph::neighbors_directed(self, n, d) + } +} + +impl<'a, N: 'a, E: 'a, Ty, Ix> visit::IntoEdgeReferences for &'a Graph +where + Ty: EdgeType, + Ix: IndexType, +{ + type EdgeRef = EdgeReference<'a, E, Ix>; + type EdgeReferences = EdgeReferences<'a, E, Ix>; + fn edge_references(self) -> Self::EdgeReferences { + (*self).edge_references() + } +} + +impl visit::EdgeCount for Graph +where + Ty: EdgeType, + Ix: IndexType, +{ + #[inline] + fn edge_count(&self) -> usize { + self.edge_count() + } +} + +impl<'a, N, E, Ty, Ix> visit::IntoNodeReferences for &'a Graph +where + Ty: EdgeType, + Ix: IndexType, +{ + type NodeRef = (NodeIndex, &'a N); + type NodeReferences = NodeReferences<'a, N, Ix>; + fn node_references(self) -> Self::NodeReferences { + NodeReferences { + iter: self.nodes.iter().enumerate(), + } + } +} + +/// Iterator over all nodes of a graph. +#[derive(Debug, Clone)] +pub struct NodeReferences<'a, N: 'a, Ix: IndexType = DefaultIx> { + iter: iter::Enumerate>>, +} + +impl<'a, N, Ix> Iterator for NodeReferences<'a, N, Ix> +where + Ix: IndexType, +{ + type Item = (NodeIndex, &'a N); + + fn next(&mut self) -> Option { + self.iter + .next() + .map(|(i, node)| (node_index(i), &node.weight)) + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +impl DoubleEndedIterator for NodeReferences<'_, N, Ix> +where + Ix: IndexType, +{ + fn next_back(&mut self) -> Option { + self.iter + .next_back() + .map(|(i, node)| (node_index(i), &node.weight)) + } +} + +impl ExactSizeIterator for NodeReferences<'_, N, Ix> where Ix: IndexType {} + +impl<'a, Ix, E> EdgeReference<'a, E, Ix> +where + Ix: IndexType, +{ + /// Access the edge’s weight. + /// + /// **NOTE** that this method offers a longer lifetime + /// than the trait (unfortunately they don't match yet). + pub fn weight(&self) -> &'a E { + self.weight + } +} + +impl visit::EdgeRef for EdgeReference<'_, E, Ix> +where + Ix: IndexType, +{ + type NodeId = NodeIndex; + type EdgeId = EdgeIndex; + type Weight = E; + + fn source(&self) -> Self::NodeId { + self.node[0] + } + fn target(&self) -> Self::NodeId { + self.node[1] + } + fn weight(&self) -> &E { + self.weight + } + fn id(&self) -> Self::EdgeId { + self.index + } +} + +/// Iterator over all edges of a graph. +#[derive(Debug, Clone)] +pub struct EdgeReferences<'a, E: 'a, Ix: IndexType = DefaultIx> { + iter: iter::Enumerate>>, +} + +impl<'a, E, Ix> Iterator for EdgeReferences<'a, E, Ix> +where + Ix: IndexType, +{ + type Item = EdgeReference<'a, E, Ix>; + + fn next(&mut self) -> Option { + self.iter.next().map(|(i, edge)| EdgeReference { + index: edge_index(i), + node: edge.node, + weight: &edge.weight, + }) + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +impl DoubleEndedIterator for EdgeReferences<'_, E, Ix> +where + Ix: IndexType, +{ + fn next_back(&mut self) -> Option { + self.iter.next_back().map(|(i, edge)| EdgeReference { + index: edge_index(i), + node: edge.node, + weight: &edge.weight, + }) + } +} + +impl ExactSizeIterator for EdgeReferences<'_, E, Ix> where Ix: IndexType {} + +impl visit::EdgeIndexable for Graph +where + Ty: EdgeType, + Ix: IndexType, +{ + fn edge_bound(&self) -> usize { + self.edge_count() + } + + fn to_index(&self, ix: EdgeIndex) -> usize { + ix.index() + } + + fn from_index(&self, ix: usize) -> Self::EdgeId { + EdgeIndex::new(ix) + } +} + +mod frozen; +#[cfg(feature = "stable_graph")] +pub mod stable_graph; + +/// `Frozen` is a graph wrapper. +/// +/// The `Frozen` only allows shared access (read-only) to the +/// underlying graph `G`, but it allows mutable access to its +/// node and edge weights. +/// +/// This is used to ensure immutability of the graph's structure +/// while permitting weights to be both read and written. +/// +/// See indexing implementations and the traits `Data` and `DataMap` +/// for read-write access to the graph's weights. +pub struct Frozen<'a, G: 'a>(&'a mut G); diff --git a/vendor/petgraph/src/graph_impl/serialization.rs b/vendor/petgraph/src/graph_impl/serialization.rs new file mode 100644 index 00000000..d53c9de4 --- /dev/null +++ b/vendor/petgraph/src/graph_impl/serialization.rs @@ -0,0 +1,355 @@ +use serde::de::Error; + +use std::marker::PhantomData; + +use crate::prelude::*; + +use crate::graph::Node; +use crate::graph::{Edge, IndexType}; +use crate::serde_utils::CollectSeqWithLength; +use crate::serde_utils::MappedSequenceVisitor; +use crate::serde_utils::{FromDeserialized, IntoSerializable}; +use crate::EdgeType; + +use super::{EdgeIndex, NodeIndex}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +/// Serialization representation for Graph +/// Keep in sync with deserialization and StableGraph +/// +/// The serialization format is as follows, in Pseudorust: +/// +/// Graph { +/// nodes: [N], +/// node_holes: [NodeIndex], +/// edge_property: EdgeProperty, +/// edges: [Option<(NodeIndex, NodeIndex, E)>] +/// } +/// +/// The same format is used by both Graph and StableGraph. +/// +/// For graph there are restrictions: +/// node_holes is always empty and edges are always Some +/// +/// A stable graph serialization that obeys these restrictions +/// (effectively, it has no interior vacancies) can de deserialized +/// as a graph. +/// +/// Node indices are serialized as integers and are fixed size for +/// binary formats, so the Ix parameter matters there. +#[derive(Serialize)] +#[serde(rename = "Graph")] +#[serde(bound(serialize = "N: Serialize, E: Serialize, Ix: IndexType + Serialize"))] +pub struct SerGraph<'a, N: 'a, E: 'a, Ix: 'a + IndexType> { + #[serde(serialize_with = "ser_graph_nodes")] + nodes: &'a [Node], + node_holes: &'a [NodeIndex], + edge_property: EdgeProperty, + #[serde(serialize_with = "ser_graph_edges")] + edges: &'a [Edge], +} + +// Deserialization representation for Graph +// Keep in sync with serialization and StableGraph +#[derive(Deserialize)] +#[serde(rename = "Graph")] +#[serde(bound( + deserialize = "N: Deserialize<'de>, E: Deserialize<'de>, Ix: IndexType + Deserialize<'de>" +))] +pub struct DeserGraph { + #[serde(deserialize_with = "deser_graph_nodes")] + nodes: Vec>, + #[serde(deserialize_with = "deser_graph_node_holes")] + #[allow(unused)] + #[serde(default = "Vec::new")] + node_holes: Vec>, + edge_property: EdgeProperty, + #[serde(deserialize_with = "deser_graph_edges")] + edges: Vec>, +} + +impl Serialize for NodeIndex +where + Ix: IndexType + Serialize, +{ + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.0.serialize(serializer) + } +} + +impl<'de, Ix> Deserialize<'de> for NodeIndex +where + Ix: IndexType + Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Ok(NodeIndex(Ix::deserialize(deserializer)?)) + } +} + +impl Serialize for EdgeIndex +where + Ix: IndexType + Serialize, +{ + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.0.serialize(serializer) + } +} + +impl<'de, Ix> Deserialize<'de> for EdgeIndex +where + Ix: IndexType + Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Ok(EdgeIndex(Ix::deserialize(deserializer)?)) + } +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "lowercase")] +#[derive(Debug)] +pub enum EdgeProperty { + Undirected, + Directed, +} + +impl EdgeProperty { + pub fn is_directed(&self) -> bool { + match *self { + EdgeProperty::Directed => true, + EdgeProperty::Undirected => false, + } + } +} + +impl From> for EdgeProperty +where + Ty: EdgeType, +{ + fn from(_: PhantomData) -> Self { + if Ty::is_directed() { + EdgeProperty::Directed + } else { + EdgeProperty::Undirected + } + } +} + +impl FromDeserialized for PhantomData +where + Ty: EdgeType, +{ + type Input = EdgeProperty; + fn from_deserialized(input: Self::Input) -> Result + where + E2: Error, + { + if input.is_directed() != Ty::is_directed() { + Err(E2::custom(format_args!( + "graph edge property mismatch, \ + expected {:?}, found {:?}", + EdgeProperty::from(PhantomData::), + input + ))) + } else { + Ok(PhantomData) + } + } +} + +fn ser_graph_nodes(nodes: &&[Node], serializer: S) -> Result +where + S: Serializer, + N: Serialize, + Ix: Serialize + IndexType, +{ + serializer.collect_seq_exact(nodes.iter().map(|node| &node.weight)) +} + +fn ser_graph_edges(edges: &&[Edge], serializer: S) -> Result +where + S: Serializer, + E: Serialize, + Ix: Serialize + IndexType, +{ + serializer.collect_seq_exact( + edges + .iter() + .map(|edge| Some((edge.source(), edge.target(), &edge.weight))), + ) +} + +fn deser_graph_nodes<'de, D, N, Ix>(deserializer: D) -> Result>, D::Error> +where + D: Deserializer<'de>, + N: Deserialize<'de>, + Ix: IndexType + Deserialize<'de>, +{ + deserializer.deserialize_seq(MappedSequenceVisitor::new(|n| { + Ok(Node { + weight: n, + next: [EdgeIndex::end(); 2], + }) + })) +} + +fn deser_graph_node_holes<'de, D, Ix>(deserializer: D) -> Result>, D::Error> +where + D: Deserializer<'de>, + Ix: IndexType + Deserialize<'de>, +{ + deserializer.deserialize_seq( + MappedSequenceVisitor::, NodeIndex, _>::new(|_| { + Err("Graph can not have holes in the node set, found non-empty node_holes") + }), + ) +} + +fn deser_graph_edges<'de, D, N, Ix>(deserializer: D) -> Result>, D::Error> +where + D: Deserializer<'de>, + N: Deserialize<'de>, + Ix: IndexType + Deserialize<'de>, +{ + deserializer.deserialize_seq(MappedSequenceVisitor::< + Option<(NodeIndex, NodeIndex, N)>, + _, + _, + >::new(|x| { + if let Some((i, j, w)) = x { + Ok(Edge { + weight: w, + node: [i, j], + next: [EdgeIndex::end(); 2], + }) + } else { + Err("Graph can not have holes in the edge set, found None, expected edge") + } + })) +} + +impl<'a, N, E, Ty, Ix> IntoSerializable for &'a Graph +where + Ix: IndexType, + Ty: EdgeType, +{ + type Output = SerGraph<'a, N, E, Ix>; + fn into_serializable(self) -> Self::Output { + SerGraph { + nodes: &self.nodes, + node_holes: &[], + edges: &self.edges, + edge_property: EdgeProperty::from(PhantomData::), + } + } +} + +/// Requires crate feature `"serde-1"` +impl Serialize for Graph +where + Ty: EdgeType, + Ix: IndexType + Serialize, + N: Serialize, + E: Serialize, +{ + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.into_serializable().serialize(serializer) + } +} + +pub fn invalid_node_err(node_index: usize, len: usize) -> E +where + E: Error, +{ + E::custom(format_args!( + "invalid value: node index `{}` does not exist in graph \ + with node bound {}", + node_index, len + )) +} + +pub fn invalid_hole_err(node_index: usize) -> E +where + E: Error, +{ + E::custom(format_args!( + "invalid value: node hole `{}` is not allowed.", + node_index + )) +} + +pub fn invalid_length_err(node_or_edge: &str, len: usize) -> E +where + E: Error, + Ix: IndexType, +{ + E::custom(format_args!( + "invalid size: graph {} count {} exceeds index type maximum {}", + node_or_edge, + len, + ::max().index() + )) +} + +impl<'a, N, E, Ty, Ix> FromDeserialized for Graph +where + Ix: IndexType, + Ty: EdgeType, +{ + type Input = DeserGraph; + fn from_deserialized(input: Self::Input) -> Result + where + E2: Error, + { + let ty = PhantomData::::from_deserialized(input.edge_property)?; + let nodes = input.nodes; + let edges = input.edges; + if nodes.len() >= ::max().index() { + Err(invalid_length_err::("node", nodes.len()))? + } + + if edges.len() >= ::max().index() { + Err(invalid_length_err::("edge", edges.len()))? + } + + let mut gr = Graph { + nodes: nodes, + edges: edges, + ty: ty, + }; + let nc = gr.node_count(); + gr.link_edges() + .map_err(|i| invalid_node_err(i.index(), nc))?; + Ok(gr) + } +} + +/// Requires crate feature `"serde-1"` +impl<'de, N, E, Ty, Ix> Deserialize<'de> for Graph +where + Ty: EdgeType, + Ix: IndexType + Deserialize<'de>, + N: Deserialize<'de>, + E: Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Self::from_deserialized(DeserGraph::deserialize(deserializer)?) + } +} diff --git a/vendor/petgraph/src/graph_impl/stable_graph/mod.rs b/vendor/petgraph/src/graph_impl/stable_graph/mod.rs new file mode 100644 index 00000000..bf03b62d --- /dev/null +++ b/vendor/petgraph/src/graph_impl/stable_graph/mod.rs @@ -0,0 +1,2103 @@ +//! `StableGraph` keeps indices stable across removals. +//! +//! Depends on `feature = "stable_graph"`. +//! + +use std::cmp; +use std::fmt; +use std::iter; +use std::marker::PhantomData; +use std::mem::replace; +use std::mem::size_of; +use std::ops::{Index, IndexMut}; +use std::slice; + +use fixedbitset::FixedBitSet; + +use crate::{Directed, Direction, EdgeType, Graph, Incoming, Outgoing, Undirected}; + +use crate::iter_format::{DebugMap, IterFormatExt, NoPretty}; +use crate::iter_utils::IterUtilsExt; + +use super::{index_twice, Edge, Frozen, Node, Pair, DIRECTIONS}; +use crate::visit; +use crate::visit::{EdgeIndexable, EdgeRef, IntoEdgeReferences, NodeIndexable}; +use crate::IntoWeightedEdge; + +// reexport those things that are shared with Graph +#[doc(no_inline)] +pub use crate::graph::{ + edge_index, node_index, DefaultIx, EdgeIndex, GraphIndex, IndexType, NodeIndex, +}; + +use crate::util::enumerate; + +#[cfg(feature = "serde-1")] +mod serialization; + +/// `StableGraph` is a graph datastructure using an adjacency +/// list representation. +/// +/// The graph **does not invalidate** any unrelated node or edge indices when +/// items are removed. +/// +/// `StableGraph` is parameterized over: +/// +/// - Associated data `N` for nodes and `E` for edges, also called *weights*. +/// The associated data can be of arbitrary type. +/// - Edge type `Ty` that determines whether the graph edges are directed or undirected. +/// - Index type `Ix`, which determines the maximum size of the graph. +/// +/// The graph uses **O(|V| + |E|)** space, and allows fast node and edge insert +/// and efficient graph search. +/// +/// It implements **O(e')** edge lookup and edge and node removals, where **e'** +/// is some local measure of edge count. +/// +/// - Nodes and edges are each numbered in an interval from *0* to some number +/// *m*, but *not all* indices in the range are valid, since gaps are formed +/// by deletions. +/// +/// - You can select graph index integer type after the size of the graph. A smaller +/// size may have better performance. +/// +/// - Using indices allows mutation while traversing the graph, see `Dfs`. +/// +/// - The `StableGraph` is a regular rust collection and is `Send` and `Sync` +/// (as long as associated data `N` and `E` are). +/// +/// - Indices don't allow as much compile time checking as references. +/// +/// Depends on crate feature `stable_graph` (default). *Stable Graph is still +/// missing a few methods compared to Graph. You can contribute to help it +/// achieve parity.* +pub struct StableGraph { + g: Graph, Option, Ty, Ix>, + node_count: usize, + edge_count: usize, + + // node and edge free lists (both work the same way) + // + // free_node, if not NodeIndex::end(), points to a node index + // that is vacant (after a deletion). + // The free nodes form a doubly linked list using the fields Node.next[0] + // for forward references and Node.next[1] for backwards ones. + // The nodes are stored as EdgeIndex, and the _into_edge()/_into_node() + // methods convert. + // free_edge, if not EdgeIndex::end(), points to a free edge. + // The edges only form a singly linked list using Edge.next[0] to store + // the forward reference. + free_node: NodeIndex, + free_edge: EdgeIndex, +} + +/// A `StableGraph` with directed edges. +/// +/// For example, an edge from *1* to *2* is distinct from an edge from *2* to +/// *1*. +pub type StableDiGraph = StableGraph; + +/// A `StableGraph` with undirected edges. +/// +/// For example, an edge between *1* and *2* is equivalent to an edge between +/// *2* and *1*. +pub type StableUnGraph = StableGraph; + +impl fmt::Debug for StableGraph +where + N: fmt::Debug, + E: fmt::Debug, + Ty: EdgeType, + Ix: IndexType, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let etype = if self.is_directed() { + "Directed" + } else { + "Undirected" + }; + let mut fmt_struct = f.debug_struct("StableGraph"); + fmt_struct.field("Ty", &etype); + fmt_struct.field("node_count", &self.node_count); + fmt_struct.field("edge_count", &self.edge_count); + if self.g.edges.iter().any(|e| e.weight.is_some()) { + fmt_struct.field( + "edges", + &self + .g + .edges + .iter() + .filter(|e| e.weight.is_some()) + .map(|e| NoPretty((e.source().index(), e.target().index()))) + .format(", "), + ); + } + // skip weights if they are ZST! + if size_of::() != 0 { + fmt_struct.field( + "node weights", + &DebugMap(|| { + self.g + .nodes + .iter() + .map(|n| n.weight.as_ref()) + .enumerate() + .filter_map(|(i, wo)| wo.map(move |w| (i, w))) + }), + ); + } + if size_of::() != 0 { + fmt_struct.field( + "edge weights", + &DebugMap(|| { + self.g + .edges + .iter() + .map(|n| n.weight.as_ref()) + .enumerate() + .filter_map(|(i, wo)| wo.map(move |w| (i, w))) + }), + ); + } + fmt_struct.field("free_node", &self.free_node); + fmt_struct.field("free_edge", &self.free_edge); + fmt_struct.finish() + } +} + +impl StableGraph { + /// Create a new `StableGraph` with directed edges. + /// + /// This is a convenience method. See `StableGraph::with_capacity` + /// or `StableGraph::default` for a constructor that is generic in all the + /// type parameters of `StableGraph`. + pub fn new() -> Self { + Self::with_capacity(0, 0) + } +} + +impl StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + /// Create a new `StableGraph` with estimated capacity. + pub fn with_capacity(nodes: usize, edges: usize) -> Self { + StableGraph { + g: Graph::with_capacity(nodes, edges), + node_count: 0, + edge_count: 0, + free_node: NodeIndex::end(), + free_edge: EdgeIndex::end(), + } + } + + /// Return the current node and edge capacity of the graph. + pub fn capacity(&self) -> (usize, usize) { + self.g.capacity() + } + + /// Reverse the direction of all edges + pub fn reverse(&mut self) { + // swap edge endpoints, + // edge incoming / outgoing lists, + // node incoming / outgoing lists + for edge in &mut self.g.edges { + edge.node.swap(0, 1); + edge.next.swap(0, 1); + } + for node in &mut self.g.nodes { + node.next.swap(0, 1); + } + } + + /// Remove all nodes and edges + pub fn clear(&mut self) { + self.node_count = 0; + self.edge_count = 0; + self.free_node = NodeIndex::end(); + self.free_edge = EdgeIndex::end(); + self.g.clear(); + } + + /// Remove all edges + pub fn clear_edges(&mut self) { + self.edge_count = 0; + self.free_edge = EdgeIndex::end(); + self.g.edges.clear(); + // clear edges without touching the free list + for node in &mut self.g.nodes { + if node.weight.is_some() { + node.next = [EdgeIndex::end(), EdgeIndex::end()]; + } + } + } + + /// Return the number of nodes (vertices) in the graph. + /// + /// Computes in **O(1)** time. + pub fn node_count(&self) -> usize { + self.node_count + } + + /// Return the number of edges in the graph. + /// + /// Computes in **O(1)** time. + pub fn edge_count(&self) -> usize { + self.edge_count + } + + /// Whether the graph has directed edges or not. + #[inline] + pub fn is_directed(&self) -> bool { + Ty::is_directed() + } + + /// Add a node (also called vertex) with associated data `weight` to the graph. + /// + /// Computes in **O(1)** time. + /// + /// Return the index of the new node. + /// + /// **Panics** if the `StableGraph` is at the maximum number of nodes for + /// its index type. + pub fn add_node(&mut self, weight: N) -> NodeIndex { + if self.free_node != NodeIndex::end() { + let node_idx = self.free_node; + self.occupy_vacant_node(node_idx, weight); + node_idx + } else { + self.node_count += 1; + self.g.add_node(Some(weight)) + } + } + + /// free_node: Which free list to update for the vacancy + fn add_vacant_node(&mut self, free_node: &mut NodeIndex) { + let node_idx = self.g.add_node(None); + // link the free list + let node_slot = &mut self.g.nodes[node_idx.index()]; + node_slot.next = [free_node._into_edge(), EdgeIndex::end()]; + if *free_node != NodeIndex::end() { + self.g.nodes[free_node.index()].next[1] = node_idx._into_edge(); + } + *free_node = node_idx; + } + + /// Remove `a` from the graph if it exists, and return its weight. + /// If it doesn't exist in the graph, return `None`. + /// + /// The node index `a` is invalidated, but none other. + /// Edge indices are invalidated as they would be following the removal of + /// each edge with an endpoint in `a`. + /// + /// Computes in **O(e')** time, where **e'** is the number of affected + /// edges, including *n* calls to `.remove_edge()` where *n* is the number + /// of edges with an endpoint in `a`. + pub fn remove_node(&mut self, a: NodeIndex) -> Option { + let node_weight = self.g.nodes.get_mut(a.index())?.weight.take()?; + for d in &DIRECTIONS { + let k = d.index(); + + // Remove all edges from and to this node. + loop { + let next = self.g.nodes[a.index()].next[k]; + if next == EdgeIndex::end() { + break; + } + let ret = self.remove_edge(next); + debug_assert!(ret.is_some()); + let _ = ret; + } + } + + let node_slot = &mut self.g.nodes[a.index()]; + //let node_weight = replace(&mut self.g.nodes[a.index()].weight, Entry::Empty(self.free_node)); + //self.g.nodes[a.index()].next = [EdgeIndex::end(), EdgeIndex::end()]; + node_slot.next = [self.free_node._into_edge(), EdgeIndex::end()]; + if self.free_node != NodeIndex::end() { + self.g.nodes[self.free_node.index()].next[1] = a._into_edge(); + } + self.free_node = a; + self.node_count -= 1; + + Some(node_weight) + } + + pub fn contains_node(&self, a: NodeIndex) -> bool { + self.get_node(a).is_some() + } + + // Return the Node if it is not vacant (non-None weight) + fn get_node(&self, a: NodeIndex) -> Option<&Node, Ix>> { + self.g + .nodes + .get(a.index()) + .and_then(|node| node.weight.as_ref().map(move |_| node)) + } + + /// Add an edge from `a` to `b` to the graph, with its associated + /// data `weight`. + /// + /// Return the index of the new edge. + /// + /// Computes in **O(1)** time. + /// + /// **Panics** if any of the nodes don't exist.
+ /// **Panics** if the `StableGraph` is at the maximum number of edges for + /// its index type. + /// + /// **Note:** `StableGraph` allows adding parallel (“duplicate”) edges. + pub fn add_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> EdgeIndex { + let edge_idx; + let mut new_edge = None::>; + { + let edge: &mut Edge<_, _>; + + if self.free_edge != EdgeIndex::end() { + edge_idx = self.free_edge; + edge = &mut self.g.edges[edge_idx.index()]; + let _old = replace(&mut edge.weight, Some(weight)); + debug_assert!(_old.is_none()); + self.free_edge = edge.next[0]; + edge.node = [a, b]; + } else { + edge_idx = EdgeIndex::new(self.g.edges.len()); + assert!(::max().index() == !0 || EdgeIndex::end() != edge_idx); + new_edge = Some(Edge { + weight: Some(weight), + node: [a, b], + next: [EdgeIndex::end(); 2], + }); + edge = new_edge.as_mut().unwrap(); + } + + let wrong_index = match index_twice(&mut self.g.nodes, a.index(), b.index()) { + Pair::None => Some(cmp::max(a.index(), b.index())), + Pair::One(an) => { + if an.weight.is_none() { + Some(a.index()) + } else { + edge.next = an.next; + an.next[0] = edge_idx; + an.next[1] = edge_idx; + None + } + } + Pair::Both(an, bn) => { + // a and b are different indices + if an.weight.is_none() { + Some(a.index()) + } else if bn.weight.is_none() { + Some(b.index()) + } else { + edge.next = [an.next[0], bn.next[1]]; + an.next[0] = edge_idx; + bn.next[1] = edge_idx; + None + } + } + }; + if let Some(i) = wrong_index { + panic!( + "StableGraph::add_edge: node index {} is not a node in the graph", + i + ); + } + self.edge_count += 1; + } + if let Some(edge) = new_edge { + self.g.edges.push(edge); + } + edge_idx + } + + /// free_edge: Which free list to update for the vacancy + fn add_vacant_edge(&mut self, free_edge: &mut EdgeIndex) { + let edge_idx = EdgeIndex::new(self.g.edges.len()); + debug_assert!(edge_idx != EdgeIndex::end()); + let mut edge = Edge { + weight: None, + node: [NodeIndex::end(); 2], + next: [EdgeIndex::end(); 2], + }; + edge.next[0] = *free_edge; + *free_edge = edge_idx; + self.g.edges.push(edge); + } + + /// Add or update an edge from `a` to `b`. + /// If the edge already exists, its weight is updated. + /// + /// Return the index of the affected edge. + /// + /// Computes in **O(e')** time, where **e'** is the number of edges + /// connected to `a` (and `b`, if the graph edges are undirected). + /// + /// **Panics** if any of the nodes don't exist. + pub fn update_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> EdgeIndex { + if let Some(ix) = self.find_edge(a, b) { + self[ix] = weight; + return ix; + } + self.add_edge(a, b, weight) + } + + /// Remove an edge and return its edge weight, or `None` if it didn't exist. + /// + /// Invalidates the edge index `e` but no other. + /// + /// Computes in **O(e')** time, where **e'** is the number of edges + /// connected to the same endpoints as `e`. + pub fn remove_edge(&mut self, e: EdgeIndex) -> Option { + // every edge is part of two lists, + // outgoing and incoming edges. + // Remove it from both + let (is_edge, edge_node, edge_next) = match self.g.edges.get(e.index()) { + None => return None, + Some(x) => (x.weight.is_some(), x.node, x.next), + }; + if !is_edge { + return None; + } + + // Remove the edge from its in and out lists by replacing it with + // a link to the next in the list. + self.g.change_edge_links(edge_node, e, edge_next); + + // Clear the edge and put it in the free list + let edge = &mut self.g.edges[e.index()]; + edge.next = [self.free_edge, EdgeIndex::end()]; + edge.node = [NodeIndex::end(), NodeIndex::end()]; + self.free_edge = e; + self.edge_count -= 1; + edge.weight.take() + } + + /// Access the weight for node `a`. + /// + /// Also available with indexing syntax: `&graph[a]`. + pub fn node_weight(&self, a: NodeIndex) -> Option<&N> { + match self.g.nodes.get(a.index()) { + Some(no) => no.weight.as_ref(), + None => None, + } + } + + /// Access the weight for node `a`, mutably. + /// + /// Also available with indexing syntax: `&mut graph[a]`. + pub fn node_weight_mut(&mut self, a: NodeIndex) -> Option<&mut N> { + match self.g.nodes.get_mut(a.index()) { + Some(no) => no.weight.as_mut(), + None => None, + } + } + + /// Return an iterator yielding immutable access to all node weights. + /// + /// The order in which weights are yielded matches the order of their node + /// indices. + pub fn node_weights(&self) -> impl Iterator { + self.g + .node_weights() + .filter_map(|maybe_node| maybe_node.as_ref()) + } + /// Return an iterator yielding mutable access to all node weights. + /// + /// The order in which weights are yielded matches the order of their node + /// indices. + pub fn node_weights_mut(&mut self) -> impl Iterator { + self.g + .node_weights_mut() + .filter_map(|maybe_node| maybe_node.as_mut()) + } + + /// Return an iterator over the node indices of the graph + pub fn node_indices(&self) -> NodeIndices { + NodeIndices { + iter: enumerate(self.raw_nodes()), + } + } + + /// Access the weight for edge `e`. + /// + /// Also available with indexing syntax: `&graph[e]`. + pub fn edge_weight(&self, e: EdgeIndex) -> Option<&E> { + match self.g.edges.get(e.index()) { + Some(ed) => ed.weight.as_ref(), + None => None, + } + } + + /// Access the weight for edge `e`, mutably + /// + /// Also available with indexing syntax: `&mut graph[e]`. + pub fn edge_weight_mut(&mut self, e: EdgeIndex) -> Option<&mut E> { + match self.g.edges.get_mut(e.index()) { + Some(ed) => ed.weight.as_mut(), + None => None, + } + } + + /// Return an iterator yielding immutable access to all edge weights. + /// + /// The order in which weights are yielded matches the order of their edge + /// indices. + pub fn edge_weights(&self) -> impl Iterator { + self.g + .edge_weights() + .filter_map(|maybe_edge| maybe_edge.as_ref()) + } + /// Return an iterator yielding mutable access to all edge weights. + /// + /// The order in which weights are yielded matches the order of their edge + /// indices. + pub fn edge_weights_mut(&mut self) -> impl Iterator { + self.g + .edge_weights_mut() + .filter_map(|maybe_edge| maybe_edge.as_mut()) + } + + /// Access the source and target nodes for `e`. + pub fn edge_endpoints(&self, e: EdgeIndex) -> Option<(NodeIndex, NodeIndex)> { + match self.g.edges.get(e.index()) { + Some(ed) if ed.weight.is_some() => Some((ed.source(), ed.target())), + _otherwise => None, + } + } + + /// Return an iterator over the edge indices of the graph + pub fn edge_indices(&self) -> EdgeIndices { + EdgeIndices { + iter: enumerate(self.raw_edges()), + } + } + + /// Return an iterator over all the edges connecting `a` and `b`. + /// + /// - `Directed`: Outgoing edges from `a`. + /// - `Undirected`: All edges connected to `a`. + /// + /// Iterator element type is `EdgeReference`. + pub fn edges_connecting( + &self, + a: NodeIndex, + b: NodeIndex, + ) -> EdgesConnecting { + EdgesConnecting { + target_node: b, + edges: self.edges_directed(a, Direction::Outgoing), + ty: PhantomData, + } + } + + /// Lookup if there is an edge from `a` to `b`. + /// + /// Computes in **O(e')** time, where **e'** is the number of edges + /// connected to `a` (and `b`, if the graph edges are undirected). + pub fn contains_edge(&self, a: NodeIndex, b: NodeIndex) -> bool { + self.find_edge(a, b).is_some() + } + + /// Lookup an edge from `a` to `b`. + /// + /// Computes in **O(e')** time, where **e'** is the number of edges + /// connected to `a` (and `b`, if the graph edges are undirected). + pub fn find_edge(&self, a: NodeIndex, b: NodeIndex) -> Option> { + if !self.is_directed() { + self.find_edge_undirected(a, b).map(|(ix, _)| ix) + } else { + match self.get_node(a) { + None => None, + Some(node) => self.g.find_edge_directed_from_node(node, b), + } + } + } + + /// Lookup an edge between `a` and `b`, in either direction. + /// + /// If the graph is undirected, then this is equivalent to `.find_edge()`. + /// + /// Return the edge index and its directionality, with `Outgoing` meaning + /// from `a` to `b` and `Incoming` the reverse, + /// or `None` if the edge does not exist. + pub fn find_edge_undirected( + &self, + a: NodeIndex, + b: NodeIndex, + ) -> Option<(EdgeIndex, Direction)> { + match self.get_node(a) { + None => None, + Some(node) => self.g.find_edge_undirected_from_node(node, b), + } + } + + /// Return an iterator of all nodes with an edge starting from `a`. + /// + /// - `Directed`: Outgoing edges from `a`. + /// - `Undirected`: All edges connected to `a`. + /// + /// Produces an empty iterator if the node doesn't exist.
+ /// Iterator element type is `NodeIndex`. + /// + /// Use [`.neighbors(a).detach()`][1] to get a neighbor walker that does + /// not borrow from the graph. + /// + /// [1]: struct.Neighbors.html#method.detach + pub fn neighbors(&self, a: NodeIndex) -> Neighbors { + self.neighbors_directed(a, Outgoing) + } + + /// Return an iterator of all neighbors that have an edge between them and `a`, + /// in the specified direction. + /// If the graph's edges are undirected, this is equivalent to *.neighbors(a)*. + /// + /// - `Directed`, `Outgoing`: All edges from `a`. + /// - `Directed`, `Incoming`: All edges to `a`. + /// - `Undirected`: All edges connected to `a`. + /// + /// Produces an empty iterator if the node doesn't exist.
+ /// Iterator element type is `NodeIndex`. + /// + /// Use [`.neighbors_directed(a, dir).detach()`][1] to get a neighbor walker that does + /// not borrow from the graph. + /// + /// [1]: struct.Neighbors.html#method.detach + pub fn neighbors_directed(&self, a: NodeIndex, dir: Direction) -> Neighbors { + let mut iter = self.neighbors_undirected(a); + if self.is_directed() { + let k = dir.index(); + iter.next[1 - k] = EdgeIndex::end(); + iter.skip_start = NodeIndex::end(); + } + iter + } + + /// Return an iterator of all neighbors that have an edge between them and `a`, + /// in either direction. + /// If the graph's edges are undirected, this is equivalent to *.neighbors(a)*. + /// + /// - `Directed` and `Undirected`: All edges connected to `a`. + /// + /// Produces an empty iterator if the node doesn't exist.
+ /// Iterator element type is `NodeIndex`. + /// + /// Use [`.neighbors_undirected(a).detach()`][1] to get a neighbor walker that does + /// not borrow from the graph. + /// + /// [1]: struct.Neighbors.html#method.detach + pub fn neighbors_undirected(&self, a: NodeIndex) -> Neighbors { + Neighbors { + skip_start: a, + edges: &self.g.edges, + next: match self.get_node(a) { + None => [EdgeIndex::end(), EdgeIndex::end()], + Some(n) => n.next, + }, + } + } + + /// Return an iterator of all edges of `a`. + /// + /// - `Directed`: Outgoing edges from `a`. + /// - `Undirected`: All edges connected to `a`. + /// + /// Produces an empty iterator if the node doesn't exist.
+ /// Iterator element type is `EdgeReference`. + pub fn edges(&self, a: NodeIndex) -> Edges { + self.edges_directed(a, Outgoing) + } + + /// Return an iterator of all edges of `a`, in the specified direction. + /// + /// - `Directed`, `Outgoing`: All edges from `a`. + /// - `Directed`, `Incoming`: All edges to `a`. + /// - `Undirected`, `Outgoing`: All edges connected to `a`, with `a` being the source of each + /// edge. + /// - `Undirected`, `Incoming`: All edges connected to `a`, with `a` being the target of each + /// edge. + /// + /// Produces an empty iterator if the node `a` doesn't exist.
+ /// Iterator element type is `EdgeReference`. + pub fn edges_directed(&self, a: NodeIndex, dir: Direction) -> Edges { + Edges { + skip_start: a, + edges: &self.g.edges, + direction: dir, + next: match self.get_node(a) { + None => [EdgeIndex::end(), EdgeIndex::end()], + Some(n) => n.next, + }, + ty: PhantomData, + } + } + + /// Return an iterator over either the nodes without edges to them + /// (`Incoming`) or from them (`Outgoing`). + /// + /// An *internal* node has both incoming and outgoing edges. + /// The nodes in `.externals(Incoming)` are the source nodes and + /// `.externals(Outgoing)` are the sinks of the graph. + /// + /// For a graph with undirected edges, both the sinks and the sources are + /// just the nodes without edges. + /// + /// The whole iteration computes in **O(|V|)** time. + pub fn externals(&self, dir: Direction) -> Externals { + Externals { + iter: self.raw_nodes().iter().enumerate(), + dir, + ty: PhantomData, + } + } + + /// Index the `StableGraph` by two indices, any combination of + /// node or edge indices is fine. + /// + /// **Panics** if the indices are equal or if they are out of bounds. + pub fn index_twice_mut( + &mut self, + i: T, + j: U, + ) -> ( + &mut >::Output, + &mut >::Output, + ) + where + Self: IndexMut + IndexMut, + T: GraphIndex, + U: GraphIndex, + { + assert!(T::is_node_index() != U::is_node_index() || i.index() != j.index()); + + // Allow two mutable indexes here -- they are nonoverlapping + unsafe { + let self_mut = self as *mut _; + ( + >::index_mut(&mut *self_mut, i), + >::index_mut(&mut *self_mut, j), + ) + } + } + + /// Keep all nodes that return `true` from the `visit` closure, + /// remove the others. + /// + /// `visit` is provided a proxy reference to the graph, so that + /// the graph can be walked and associated data modified. + /// + /// The order nodes are visited is not specified. + /// + /// The node indices of the removed nodes are invalidated, but none other. + /// Edge indices are invalidated as they would be following the removal of + /// each edge with an endpoint in a removed node. + /// + /// Computes in **O(n + e')** time, where **n** is the number of node indices and + /// **e'** is the number of affected edges, including *n* calls to `.remove_edge()` + /// where *n* is the number of edges with an endpoint in a removed node. + pub fn retain_nodes(&mut self, mut visit: F) + where + F: FnMut(Frozen, NodeIndex) -> bool, + { + for i in 0..self.node_bound() { + let ix = node_index(i); + if self.contains_node(ix) && !visit(Frozen(self), ix) { + self.remove_node(ix); + } + } + self.check_free_lists(); + } + + /// Keep all edges that return `true` from the `visit` closure, + /// remove the others. + /// + /// `visit` is provided a proxy reference to the graph, so that + /// the graph can be walked and associated data modified. + /// + /// The order edges are visited is not specified. + /// + /// The edge indices of the removed edes are invalidated, but none other. + /// + /// Computes in **O(e'')** time, **e'** is the number of affected edges, + /// including the calls to `.remove_edge()` for each removed edge. + pub fn retain_edges(&mut self, mut visit: F) + where + F: FnMut(Frozen, EdgeIndex) -> bool, + { + for i in 0..self.edge_bound() { + let ix = edge_index(i); + if self.edge_weight(ix).is_some() && !visit(Frozen(self), ix) { + self.remove_edge(ix); + } + } + self.check_free_lists(); + } + + /// Create a new `StableGraph` from an iterable of edges. + /// + /// Node weights `N` are set to default values. + /// Edge weights `E` may either be specified in the list, + /// or they are filled with default values. + /// + /// Nodes are inserted automatically to match the edges. + /// + /// ``` + /// use petgraph::stable_graph::StableGraph; + /// + /// let gr = StableGraph::<(), i32>::from_edges(&[ + /// (0, 1), (0, 2), (0, 3), + /// (1, 2), (1, 3), + /// (2, 3), + /// ]); + /// ``` + pub fn from_edges(iterable: I) -> Self + where + I: IntoIterator, + I::Item: IntoWeightedEdge, + >::NodeId: Into>, + N: Default, + { + let mut g = Self::with_capacity(0, 0); + g.extend_with_edges(iterable); + g + } + + /// Create a new `StableGraph` by mapping node and + /// edge weights to new values. + /// + /// The resulting graph has the same structure and the same + /// graph indices as `self`. + pub fn map<'a, F, G, N2, E2>( + &'a self, + mut node_map: F, + mut edge_map: G, + ) -> StableGraph + where + F: FnMut(NodeIndex, &'a N) -> N2, + G: FnMut(EdgeIndex, &'a E) -> E2, + { + let g = self.g.map( + move |i, w| w.as_ref().map(|w| node_map(i, w)), + move |i, w| w.as_ref().map(|w| edge_map(i, w)), + ); + StableGraph { + g, + node_count: self.node_count, + edge_count: self.edge_count, + free_node: self.free_node, + free_edge: self.free_edge, + } + } + + /// Create a new `StableGraph` by mapping nodes and edges. + /// A node or edge may be mapped to `None` to exclude it from + /// the resulting graph. + /// + /// Nodes are mapped first with the `node_map` closure, then + /// `edge_map` is called for the edges that have not had any endpoint + /// removed. + /// + /// The resulting graph has the structure of a subgraph of the original graph. + /// Nodes and edges that are not removed maintain their old node or edge + /// indices. + pub fn filter_map<'a, F, G, N2, E2>( + &'a self, + mut node_map: F, + mut edge_map: G, + ) -> StableGraph + where + F: FnMut(NodeIndex, &'a N) -> Option, + G: FnMut(EdgeIndex, &'a E) -> Option, + { + let node_bound = self.node_bound(); + let edge_bound = self.edge_bound(); + let mut result_g = StableGraph::with_capacity(node_bound, edge_bound); + // use separate free lists so that + // add_node / add_edge below do not reuse the tombstones + let mut free_node = NodeIndex::end(); + let mut free_edge = EdgeIndex::end(); + + // the stable graph keeps the node map itself + + for (i, node) in enumerate(self.raw_nodes()) { + if i >= node_bound { + break; + } + if let Some(node_weight) = node.weight.as_ref() { + if let Some(new_weight) = node_map(NodeIndex::new(i), node_weight) { + result_g.add_node(new_weight); + continue; + } + } + result_g.add_vacant_node(&mut free_node); + } + for (i, edge) in enumerate(self.raw_edges()) { + if i >= edge_bound { + break; + } + let source = edge.source(); + let target = edge.target(); + if let Some(edge_weight) = edge.weight.as_ref() { + if result_g.contains_node(source) && result_g.contains_node(target) { + if let Some(new_weight) = edge_map(EdgeIndex::new(i), edge_weight) { + result_g.add_edge(source, target, new_weight); + continue; + } + } + } + result_g.add_vacant_edge(&mut free_edge); + } + result_g.free_node = free_node; + result_g.free_edge = free_edge; + result_g.check_free_lists(); + result_g + } + + /// Extend the graph from an iterable of edges. + /// + /// Node weights `N` are set to default values. + /// Edge weights `E` may either be specified in the list, + /// or they are filled with default values. + /// + /// Nodes are inserted automatically to match the edges. + pub fn extend_with_edges(&mut self, iterable: I) + where + I: IntoIterator, + I::Item: IntoWeightedEdge, + >::NodeId: Into>, + N: Default, + { + let iter = iterable.into_iter(); + + for elt in iter { + let (source, target, weight) = elt.into_weighted_edge(); + let (source, target) = (source.into(), target.into()); + self.ensure_node_exists(source); + self.ensure_node_exists(target); + self.add_edge(source, target, weight); + } + } + + // + // internal methods + // + fn raw_nodes(&self) -> &[Node, Ix>] { + self.g.raw_nodes() + } + + fn raw_edges(&self) -> &[Edge, Ix>] { + self.g.raw_edges() + } + + /// Create a new node using a vacant position, + /// updating the free nodes doubly linked list. + fn occupy_vacant_node(&mut self, node_idx: NodeIndex, weight: N) { + let node_slot = &mut self.g.nodes[node_idx.index()]; + let _old = replace(&mut node_slot.weight, Some(weight)); + debug_assert!(_old.is_none()); + let previous_node = node_slot.next[1]; + let next_node = node_slot.next[0]; + node_slot.next = [EdgeIndex::end(), EdgeIndex::end()]; + if previous_node != EdgeIndex::end() { + self.g.nodes[previous_node.index()].next[0] = next_node; + } + if next_node != EdgeIndex::end() { + self.g.nodes[next_node.index()].next[1] = previous_node; + } + if self.free_node == node_idx { + self.free_node = next_node._into_node(); + } + self.node_count += 1; + } + + /// Create the node if it does not exist, + /// adding vacant nodes for padding if needed. + fn ensure_node_exists(&mut self, node_ix: NodeIndex) + where + N: Default, + { + if let Some(Some(_)) = self.g.node_weight(node_ix) { + return; + } + while node_ix.index() >= self.g.node_count() { + let mut free_node = self.free_node; + self.add_vacant_node(&mut free_node); + self.free_node = free_node; + } + self.occupy_vacant_node(node_ix, N::default()); + } + + #[cfg(feature = "serde-1")] + /// Fix up node and edge links after deserialization + fn link_edges(&mut self) -> Result<(), NodeIndex> { + // set up free node list + self.node_count = 0; + self.edge_count = 0; + let mut free_node = NodeIndex::end(); + for node_index in 0..self.g.node_count() { + let node = &mut self.g.nodes[node_index]; + if node.weight.is_some() { + self.node_count += 1; + } else { + // free node + node.next = [free_node._into_edge(), EdgeIndex::end()]; + if free_node != NodeIndex::end() { + self.g.nodes[free_node.index()].next[1] = EdgeIndex::new(node_index); + } + free_node = NodeIndex::new(node_index); + } + } + self.free_node = free_node; + + let mut free_edge = EdgeIndex::end(); + for (edge_index, edge) in enumerate(&mut self.g.edges) { + if edge.weight.is_none() { + // free edge + edge.next = [free_edge, EdgeIndex::end()]; + free_edge = EdgeIndex::new(edge_index); + continue; + } + let a = edge.source(); + let b = edge.target(); + let edge_idx = EdgeIndex::new(edge_index); + match index_twice(&mut self.g.nodes, a.index(), b.index()) { + Pair::None => return Err(if a > b { a } else { b }), + Pair::One(an) => { + edge.next = an.next; + an.next[0] = edge_idx; + an.next[1] = edge_idx; + } + Pair::Both(an, bn) => { + // a and b are different indices + edge.next = [an.next[0], bn.next[1]]; + an.next[0] = edge_idx; + bn.next[1] = edge_idx; + } + } + self.edge_count += 1; + } + self.free_edge = free_edge; + Ok(()) + } + + #[cfg(not(debug_assertions))] + fn check_free_lists(&self) {} + #[cfg(debug_assertions)] + // internal method to debug check the free lists (linked lists) + // For the nodes, also check the backpointers of the doubly linked list. + fn check_free_lists(&self) { + let mut free_node = self.free_node; + let mut prev_free_node = NodeIndex::end(); + let mut free_node_len = 0; + while free_node != NodeIndex::end() { + if let Some(n) = self.g.nodes.get(free_node.index()) { + if n.weight.is_none() { + debug_assert_eq!(n.next[1]._into_node(), prev_free_node); + prev_free_node = free_node; + free_node = n.next[0]._into_node(); + free_node_len += 1; + continue; + } + debug_assert!( + false, + "Corrupt free list: pointing to existing {:?}", + free_node.index() + ); + } + debug_assert!(false, "Corrupt free list: missing {:?}", free_node.index()); + } + debug_assert_eq!(self.node_count(), self.raw_nodes().len() - free_node_len); + + let mut free_edge_len = 0; + let mut free_edge = self.free_edge; + while free_edge != EdgeIndex::end() { + if let Some(n) = self.g.edges.get(free_edge.index()) { + if n.weight.is_none() { + free_edge = n.next[0]; + free_edge_len += 1; + continue; + } + debug_assert!( + false, + "Corrupt free list: pointing to existing {:?}", + free_node.index() + ); + } + debug_assert!(false, "Corrupt free list: missing {:?}", free_edge.index()); + } + debug_assert_eq!(self.edge_count(), self.raw_edges().len() - free_edge_len); + } +} + +/// The resulting cloned graph has the same graph indices as `self`. +impl Clone for StableGraph +where + N: Clone, + E: Clone, +{ + fn clone(&self) -> Self { + StableGraph { + g: self.g.clone(), + node_count: self.node_count, + edge_count: self.edge_count, + free_node: self.free_node, + free_edge: self.free_edge, + } + } + + fn clone_from(&mut self, rhs: &Self) { + self.g.clone_from(&rhs.g); + self.node_count = rhs.node_count; + self.edge_count = rhs.edge_count; + self.free_node = rhs.free_node; + self.free_edge = rhs.free_edge; + } +} + +/// Index the `StableGraph` by `NodeIndex` to access node weights. +/// +/// **Panics** if the node doesn't exist. +impl Index> for StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + type Output = N; + fn index(&self, index: NodeIndex) -> &N { + self.node_weight(index).unwrap() + } +} + +/// Index the `StableGraph` by `NodeIndex` to access node weights. +/// +/// **Panics** if the node doesn't exist. +impl IndexMut> for StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + fn index_mut(&mut self, index: NodeIndex) -> &mut N { + self.node_weight_mut(index).unwrap() + } +} + +/// Index the `StableGraph` by `EdgeIndex` to access edge weights. +/// +/// **Panics** if the edge doesn't exist. +impl Index> for StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + type Output = E; + fn index(&self, index: EdgeIndex) -> &E { + self.edge_weight(index).unwrap() + } +} + +/// Index the `StableGraph` by `EdgeIndex` to access edge weights. +/// +/// **Panics** if the edge doesn't exist. +impl IndexMut> for StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + fn index_mut(&mut self, index: EdgeIndex) -> &mut E { + self.edge_weight_mut(index).unwrap() + } +} + +/// Create a new empty `StableGraph`. +impl Default for StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + fn default() -> Self { + Self::with_capacity(0, 0) + } +} + +/// Convert a `Graph` into a `StableGraph` +/// +/// Computes in **O(|V| + |E|)** time. +/// +/// The resulting graph has the same node and edge indices as +/// the original graph. +impl From> for StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + fn from(g: Graph) -> Self { + let nodes = g.nodes.into_iter().map(|e| Node { + weight: Some(e.weight), + next: e.next, + }); + let edges = g.edges.into_iter().map(|e| Edge { + weight: Some(e.weight), + node: e.node, + next: e.next, + }); + StableGraph { + node_count: nodes.len(), + edge_count: edges.len(), + g: Graph { + edges: edges.collect(), + nodes: nodes.collect(), + ty: g.ty, + }, + free_node: NodeIndex::end(), + free_edge: EdgeIndex::end(), + } + } +} + +/// Convert a `StableGraph` into a `Graph` +/// +/// Computes in **O(|V| + |E|)** time. +/// +/// This translates the stable graph into a graph with node and edge indices in +/// a compact interval without holes (like `Graph`s always are). +/// +/// Only if the stable graph had no vacancies after deletions (if node bound was +/// equal to node count, and the same for edges), would the resulting graph have +/// the same node and edge indices as the input. +impl From> for Graph +where + Ty: EdgeType, + Ix: IndexType, +{ + fn from(graph: StableGraph) -> Self { + let mut result_g = Graph::with_capacity(graph.node_count(), graph.edge_count()); + // mapping from old node index to new node index + let mut node_index_map = vec![NodeIndex::end(); graph.node_bound()]; + + for (i, node) in enumerate(graph.g.nodes) { + if let Some(nw) = node.weight { + node_index_map[i] = result_g.add_node(nw); + } + } + for edge in graph.g.edges { + let source_index = edge.source().index(); + let target_index = edge.target().index(); + if let Some(ew) = edge.weight { + let source = node_index_map[source_index]; + let target = node_index_map[target_index]; + debug_assert!(source != NodeIndex::end()); + debug_assert!(target != NodeIndex::end()); + result_g.add_edge(source, target, ew); + } + } + result_g + } +} + +/// Iterator over all nodes of a graph. +#[derive(Debug, Clone)] +pub struct NodeReferences<'a, N: 'a, Ix: IndexType = DefaultIx> { + iter: iter::Enumerate, Ix>>>, +} + +impl<'a, N, Ix> Iterator for NodeReferences<'a, N, Ix> +where + Ix: IndexType, +{ + type Item = (NodeIndex, &'a N); + + fn next(&mut self) -> Option { + self.iter + .ex_find_map(|(i, node)| node.weight.as_ref().map(move |w| (node_index(i), w))) + } + + fn size_hint(&self) -> (usize, Option) { + let (_, hi) = self.iter.size_hint(); + (0, hi) + } +} + +impl DoubleEndedIterator for NodeReferences<'_, N, Ix> +where + Ix: IndexType, +{ + fn next_back(&mut self) -> Option { + self.iter + .ex_rfind_map(|(i, node)| node.weight.as_ref().map(move |w| (node_index(i), w))) + } +} + +/// Reference to a `StableGraph` edge. +#[derive(Debug)] +pub struct EdgeReference<'a, E: 'a, Ix = DefaultIx> { + index: EdgeIndex, + node: [NodeIndex; 2], + weight: &'a E, +} + +impl Clone for EdgeReference<'_, E, Ix> { + fn clone(&self) -> Self { + *self + } +} + +impl Copy for EdgeReference<'_, E, Ix> {} + +impl PartialEq for EdgeReference<'_, E, Ix> +where + E: PartialEq, +{ + fn eq(&self, rhs: &Self) -> bool { + self.index == rhs.index && self.weight == rhs.weight + } +} + +impl<'a, Ix, E> EdgeReference<'a, E, Ix> +where + Ix: IndexType, +{ + /// Access the edge’s weight. + /// + /// **NOTE** that this method offers a longer lifetime + /// than the trait (unfortunately they don't match yet). + pub fn weight(&self) -> &'a E { + self.weight + } +} + +/// Iterator over the edges of from or to a node +#[derive(Debug, Clone)] +pub struct Edges<'a, E: 'a, Ty, Ix: 'a = DefaultIx> +where + Ty: EdgeType, + Ix: IndexType, +{ + /// starting node to skip over + skip_start: NodeIndex, + edges: &'a [Edge, Ix>], + + /// Next edge to visit. + next: [EdgeIndex; 2], + + /// For directed graphs: the direction to iterate in + /// For undirected graphs: the direction of edges + direction: Direction, + ty: PhantomData, +} + +impl<'a, E, Ty, Ix> Iterator for Edges<'a, E, Ty, Ix> +where + Ty: EdgeType, + Ix: IndexType, +{ + type Item = EdgeReference<'a, E, Ix>; + + fn next(&mut self) -> Option { + // type direction | iterate over reverse + // | + // Directed Outgoing | outgoing no + // Directed Incoming | incoming no + // Undirected Outgoing | both incoming + // Undirected Incoming | both outgoing + + // For iterate_over, "both" is represented as None. + // For reverse, "no" is represented as None. + let (iterate_over, reverse) = if Ty::is_directed() { + (Some(self.direction), None) + } else { + (None, Some(self.direction.opposite())) + }; + + if iterate_over.unwrap_or(Outgoing) == Outgoing { + let i = self.next[0].index(); + if let Some(Edge { + node, + weight: Some(weight), + next, + }) = self.edges.get(i) + { + self.next[0] = next[0]; + return Some(EdgeReference { + index: edge_index(i), + node: if reverse == Some(Outgoing) { + swap_pair(*node) + } else { + *node + }, + weight, + }); + } + } + + if iterate_over.unwrap_or(Incoming) == Incoming { + while let Some(Edge { node, weight, next }) = self.edges.get(self.next[1].index()) { + debug_assert!(weight.is_some()); + let edge_index = self.next[1]; + self.next[1] = next[1]; + // In any of the "both" situations, self-loops would be iterated over twice. + // Skip them here. + if iterate_over.is_none() && node[0] == self.skip_start { + continue; + } + + return Some(EdgeReference { + index: edge_index, + node: if reverse == Some(Incoming) { + swap_pair(*node) + } else { + *node + }, + weight: weight.as_ref().unwrap(), + }); + } + } + + None + } +} + +/// Iterator over the multiple directed edges connecting a source node to a target node +#[derive(Debug, Clone)] +pub struct EdgesConnecting<'a, E: 'a, Ty, Ix: 'a = DefaultIx> +where + Ty: EdgeType, + Ix: IndexType, +{ + target_node: NodeIndex, + edges: Edges<'a, E, Ty, Ix>, + ty: PhantomData, +} + +impl<'a, E, Ty, Ix> Iterator for EdgesConnecting<'a, E, Ty, Ix> +where + Ty: EdgeType, + Ix: IndexType, +{ + type Item = EdgeReference<'a, E, Ix>; + + fn next(&mut self) -> Option> { + let target_node = self.target_node; + self.edges + .by_ref() + .find(|&edge| edge.node[1] == target_node) + } + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.edges.size_hint(); + (0, upper) + } +} + +fn swap_pair(mut x: [T; 2]) -> [T; 2] { + x.swap(0, 1); + x +} + +/// Iterator over all edges of a graph. +#[derive(Debug, Clone)] +pub struct EdgeReferences<'a, E: 'a, Ix: 'a = DefaultIx> { + iter: iter::Enumerate, Ix>>>, +} + +impl<'a, E, Ix> Iterator for EdgeReferences<'a, E, Ix> +where + Ix: IndexType, +{ + type Item = EdgeReference<'a, E, Ix>; + + fn next(&mut self) -> Option { + self.iter.ex_find_map(|(i, edge)| { + edge.weight.as_ref().map(move |weight| EdgeReference { + index: edge_index(i), + node: edge.node, + weight, + }) + }) + } +} + +impl DoubleEndedIterator for EdgeReferences<'_, E, Ix> +where + Ix: IndexType, +{ + fn next_back(&mut self) -> Option { + self.iter.ex_rfind_map(|(i, edge)| { + edge.weight.as_ref().map(move |weight| EdgeReference { + index: edge_index(i), + node: edge.node, + weight, + }) + }) + } +} + +/// An iterator over either the nodes without edges to them or from them. +#[derive(Debug, Clone)] +pub struct Externals<'a, N: 'a, Ty, Ix: IndexType = DefaultIx> { + iter: iter::Enumerate, Ix>>>, + dir: Direction, + ty: PhantomData, +} + +impl<'a, N: 'a, Ty, Ix> Iterator for Externals<'a, N, Ty, Ix> +where + Ty: EdgeType, + Ix: IndexType, +{ + type Item = NodeIndex; + fn next(&mut self) -> Option> { + let k = self.dir.index(); + loop { + match self.iter.next() { + None => return None, + Some((index, node)) => { + if node.weight.is_some() + && node.next[k] == EdgeIndex::end() + && (Ty::is_directed() || node.next[1 - k] == EdgeIndex::end()) + { + return Some(NodeIndex::new(index)); + } else { + continue; + } + } + } + } + } + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } +} + +/// Iterator over the neighbors of a node. +/// +/// Iterator element type is `NodeIndex`. +#[derive(Debug, Clone)] +pub struct Neighbors<'a, E: 'a, Ix: 'a = DefaultIx> { + /// starting node to skip over + skip_start: NodeIndex, + edges: &'a [Edge, Ix>], + next: [EdgeIndex; 2], +} + +impl Neighbors<'_, E, Ix> +where + Ix: IndexType, +{ + /// Return a “walker” object that can be used to step through the + /// neighbors and edges from the origin node. + /// + /// Note: The walker does not borrow from the graph, this is to allow mixing + /// edge walking with mutating the graph's weights. + pub fn detach(&self) -> WalkNeighbors { + WalkNeighbors { + inner: super::WalkNeighbors { + skip_start: self.skip_start, + next: self.next, + }, + } + } +} + +impl Iterator for Neighbors<'_, E, Ix> +where + Ix: IndexType, +{ + type Item = NodeIndex; + + fn next(&mut self) -> Option> { + // First any outgoing edges + match self.edges.get(self.next[0].index()) { + None => {} + Some(edge) => { + debug_assert!(edge.weight.is_some()); + self.next[0] = edge.next[0]; + return Some(edge.node[1]); + } + } + // Then incoming edges + // For an "undirected" iterator (traverse both incoming + // and outgoing edge lists), make sure we don't double + // count selfloops by skipping them in the incoming list. + while let Some(edge) = self.edges.get(self.next[1].index()) { + debug_assert!(edge.weight.is_some()); + self.next[1] = edge.next[1]; + if edge.node[0] != self.skip_start { + return Some(edge.node[0]); + } + } + None + } +} + +/// A “walker” object that can be used to step through the edge list of a node. +/// +/// See [*.detach()*](struct.Neighbors.html#method.detach) for more information. +/// +/// The walker does not borrow from the graph, so it lets you step through +/// neighbors or incident edges while also mutating graph weights, as +/// in the following example: +/// +/// ``` +/// use petgraph::visit::Dfs; +/// use petgraph::Incoming; +/// use petgraph::stable_graph::StableGraph; +/// +/// let mut gr = StableGraph::new(); +/// let a = gr.add_node(0.); +/// let b = gr.add_node(0.); +/// let c = gr.add_node(0.); +/// gr.add_edge(a, b, 3.); +/// gr.add_edge(b, c, 2.); +/// gr.add_edge(c, b, 1.); +/// +/// // step through the graph and sum incoming edges into the node weight +/// let mut dfs = Dfs::new(&gr, a); +/// while let Some(node) = dfs.next(&gr) { +/// // use a detached neighbors walker +/// let mut edges = gr.neighbors_directed(node, Incoming).detach(); +/// while let Some(edge) = edges.next_edge(&gr) { +/// gr[node] += gr[edge]; +/// } +/// } +/// +/// // check the result +/// assert_eq!(gr[a], 0.); +/// assert_eq!(gr[b], 4.); +/// assert_eq!(gr[c], 2.); +/// ``` +pub struct WalkNeighbors { + inner: super::WalkNeighbors, +} + +impl Clone for WalkNeighbors { + clone_fields!(WalkNeighbors, inner); +} + +impl WalkNeighbors { + /// Step to the next edge and its endpoint node in the walk for graph `g`. + /// + /// The next node indices are always the others than the starting point + /// where the `WalkNeighbors` value was created. + /// For an `Outgoing` walk, the target nodes, + /// for an `Incoming` walk, the source nodes of the edge. + pub fn next( + &mut self, + g: &StableGraph, + ) -> Option<(EdgeIndex, NodeIndex)> { + self.inner.next(&g.g) + } + + pub fn next_node( + &mut self, + g: &StableGraph, + ) -> Option> { + self.next(g).map(|t| t.1) + } + + pub fn next_edge( + &mut self, + g: &StableGraph, + ) -> Option> { + self.next(g).map(|t| t.0) + } +} + +/// Iterator over the node indices of a graph. +#[derive(Debug, Clone)] +pub struct NodeIndices<'a, N: 'a, Ix: 'a = DefaultIx> { + iter: iter::Enumerate, Ix>>>, +} + +impl Iterator for NodeIndices<'_, N, Ix> { + type Item = NodeIndex; + + fn next(&mut self) -> Option { + self.iter.ex_find_map(|(i, node)| { + if node.weight.is_some() { + Some(node_index(i)) + } else { + None + } + }) + } + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } +} + +impl DoubleEndedIterator for NodeIndices<'_, N, Ix> { + fn next_back(&mut self) -> Option { + self.iter.ex_rfind_map(|(i, node)| { + if node.weight.is_some() { + Some(node_index(i)) + } else { + None + } + }) + } +} + +/// Iterator over the edge indices of a graph. +#[derive(Debug, Clone)] +pub struct EdgeIndices<'a, E: 'a, Ix: 'a = DefaultIx> { + iter: iter::Enumerate, Ix>>>, +} + +impl Iterator for EdgeIndices<'_, E, Ix> { + type Item = EdgeIndex; + + fn next(&mut self) -> Option { + self.iter.ex_find_map(|(i, node)| { + if node.weight.is_some() { + Some(edge_index(i)) + } else { + None + } + }) + } + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } +} + +impl DoubleEndedIterator for EdgeIndices<'_, E, Ix> { + fn next_back(&mut self) -> Option { + self.iter.ex_rfind_map(|(i, node)| { + if node.weight.is_some() { + Some(edge_index(i)) + } else { + None + } + }) + } +} + +impl visit::GraphBase for StableGraph +where + Ix: IndexType, +{ + type NodeId = NodeIndex; + type EdgeId = EdgeIndex; +} + +impl visit::Visitable for StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + type Map = FixedBitSet; + fn visit_map(&self) -> FixedBitSet { + FixedBitSet::with_capacity(self.node_bound()) + } + fn reset_map(&self, map: &mut Self::Map) { + map.clear(); + map.grow(self.node_bound()); + } +} + +impl visit::Data for StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + type NodeWeight = N; + type EdgeWeight = E; +} + +impl visit::GraphProp for StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + type EdgeType = Ty; +} + +impl<'a, N, E: 'a, Ty, Ix> visit::IntoNodeIdentifiers for &'a StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + type NodeIdentifiers = NodeIndices<'a, N, Ix>; + fn node_identifiers(self) -> Self::NodeIdentifiers { + StableGraph::node_indices(self) + } +} + +impl visit::NodeCount for StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + fn node_count(&self) -> usize { + self.node_count() + } +} + +impl<'a, N, E, Ty, Ix> visit::IntoNodeReferences for &'a StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + type NodeRef = (NodeIndex, &'a N); + type NodeReferences = NodeReferences<'a, N, Ix>; + fn node_references(self) -> Self::NodeReferences { + NodeReferences { + iter: enumerate(self.raw_nodes()), + } + } +} + +impl visit::NodeIndexable for StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + /// Return an upper bound of the node indices in the graph + fn node_bound(&self) -> usize { + self.node_indices().next_back().map_or(0, |i| i.index() + 1) + } + fn to_index(&self, ix: NodeIndex) -> usize { + ix.index() + } + fn from_index(&self, ix: usize) -> Self::NodeId { + NodeIndex::new(ix) + } +} + +impl<'a, N, E: 'a, Ty, Ix> visit::IntoNeighbors for &'a StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + type Neighbors = Neighbors<'a, E, Ix>; + fn neighbors(self, n: Self::NodeId) -> Self::Neighbors { + (*self).neighbors(n) + } +} + +impl<'a, N, E: 'a, Ty, Ix> visit::IntoNeighborsDirected for &'a StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + type NeighborsDirected = Neighbors<'a, E, Ix>; + fn neighbors_directed(self, n: NodeIndex, d: Direction) -> Self::NeighborsDirected { + StableGraph::neighbors_directed(self, n, d) + } +} + +impl<'a, N, E, Ty, Ix> visit::IntoEdges for &'a StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + type Edges = Edges<'a, E, Ty, Ix>; + fn edges(self, a: Self::NodeId) -> Self::Edges { + self.edges(a) + } +} + +impl visit::EdgeRef for EdgeReference<'_, E, Ix> +where + Ix: IndexType, +{ + type NodeId = NodeIndex; + type EdgeId = EdgeIndex; + type Weight = E; + + fn source(&self) -> Self::NodeId { + self.node[0] + } + fn target(&self) -> Self::NodeId { + self.node[1] + } + fn weight(&self) -> &E { + self.weight + } + fn id(&self) -> Self::EdgeId { + self.index + } +} + +impl visit::EdgeIndexable for StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + fn edge_bound(&self) -> usize { + self.edge_references() + .next_back() + .map_or(0, |edge| edge.id().index() + 1) + } + + fn to_index(&self, ix: EdgeIndex) -> usize { + ix.index() + } + + fn from_index(&self, ix: usize) -> Self::EdgeId { + EdgeIndex::new(ix) + } +} + +impl<'a, N, E, Ty, Ix> visit::IntoEdgesDirected for &'a StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + type EdgesDirected = Edges<'a, E, Ty, Ix>; + fn edges_directed(self, a: Self::NodeId, dir: Direction) -> Self::EdgesDirected { + self.edges_directed(a, dir) + } +} + +impl<'a, N: 'a, E: 'a, Ty, Ix> visit::IntoEdgeReferences for &'a StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + type EdgeRef = EdgeReference<'a, E, Ix>; + type EdgeReferences = EdgeReferences<'a, E, Ix>; + + /// Create an iterator over all edges in the graph, in indexed order. + /// + /// Iterator element type is `EdgeReference`. + fn edge_references(self) -> Self::EdgeReferences { + EdgeReferences { + iter: self.g.edges.iter().enumerate(), + } + } +} + +impl visit::EdgeCount for StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + #[inline] + fn edge_count(&self) -> usize { + self.edge_count() + } +} + +#[test] +fn stable_graph() { + let mut gr = StableGraph::<_, _>::with_capacity(0, 0); + let a = gr.add_node(0); + let b = gr.add_node(1); + let c = gr.add_node(2); + let _ed = gr.add_edge(a, b, 1); + println!("{:?}", gr); + gr.remove_node(b); + println!("{:?}", gr); + let d = gr.add_node(3); + println!("{:?}", gr); + gr.check_free_lists(); + gr.remove_node(a); + gr.check_free_lists(); + gr.remove_node(c); + gr.check_free_lists(); + println!("{:?}", gr); + gr.add_edge(d, d, 2); + println!("{:?}", gr); + + let e = gr.add_node(4); + gr.add_edge(d, e, 3); + println!("{:?}", gr); + for neigh in gr.neighbors(d) { + println!("edge {:?} -> {:?}", d, neigh); + } + gr.check_free_lists(); +} + +#[test] +fn dfs() { + use crate::visit::Dfs; + + let mut gr = StableGraph::<_, _>::with_capacity(0, 0); + let a = gr.add_node("a"); + let b = gr.add_node("b"); + let c = gr.add_node("c"); + let d = gr.add_node("d"); + gr.add_edge(a, b, 1); + gr.add_edge(a, c, 2); + gr.add_edge(b, c, 3); + gr.add_edge(b, d, 4); + gr.add_edge(c, d, 5); + gr.add_edge(d, b, 6); + gr.add_edge(c, b, 7); + println!("{:?}", gr); + + let mut dfs = Dfs::new(&gr, a); + while let Some(next) = dfs.next(&gr) { + println!("dfs visit => {:?}, weight={:?}", next, &gr[next]); + } +} + +#[test] +fn test_retain_nodes() { + let mut gr = StableGraph::<_, _>::with_capacity(6, 6); + let a = gr.add_node("a"); + let f = gr.add_node("f"); + let b = gr.add_node("b"); + let c = gr.add_node("c"); + let d = gr.add_node("d"); + let e = gr.add_node("e"); + gr.add_edge(a, b, 1); + gr.add_edge(a, c, 2); + gr.add_edge(b, c, 3); + gr.add_edge(b, d, 4); + gr.add_edge(c, d, 5); + gr.add_edge(d, b, 6); + gr.add_edge(c, b, 7); + gr.add_edge(d, e, 8); + gr.remove_node(f); + + assert_eq!(gr.node_count(), 5); + assert_eq!(gr.edge_count(), 8); + gr.retain_nodes(|frozen_gr, ix| frozen_gr[ix] >= "c"); + assert_eq!(gr.node_count(), 3); + assert_eq!(gr.edge_count(), 2); + + gr.check_free_lists(); +} + +#[test] +fn extend_with_edges() { + let mut gr = StableGraph::<_, _>::default(); + let a = gr.add_node("a"); + let b = gr.add_node("b"); + let c = gr.add_node("c"); + let _d = gr.add_node("d"); + gr.remove_node(a); + gr.remove_node(b); + gr.remove_node(c); + + gr.extend_with_edges(vec![(0, 1, ())]); + assert_eq!(gr.node_count(), 3); + assert_eq!(gr.edge_count(), 1); + gr.check_free_lists(); + + gr.extend_with_edges(vec![(5, 1, ())]); + assert_eq!(gr.node_count(), 4); + assert_eq!(gr.edge_count(), 2); + gr.check_free_lists(); +} + +#[test] +fn test_reverse() { + let mut gr = StableGraph::<_, _>::default(); + let a = gr.add_node("a"); + let b = gr.add_node("b"); + + gr.add_edge(a, b, 0); + + let mut reversed_gr = gr.clone(); + reversed_gr.reverse(); + + for i in gr.node_indices() { + itertools::assert_equal(gr.edges_directed(i, Incoming), reversed_gr.edges(i)); + } +} diff --git a/vendor/petgraph/src/graph_impl/stable_graph/serialization.rs b/vendor/petgraph/src/graph_impl/stable_graph/serialization.rs new file mode 100644 index 00000000..8292422c --- /dev/null +++ b/vendor/petgraph/src/graph_impl/stable_graph/serialization.rs @@ -0,0 +1,298 @@ +use serde::de::Error; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +use std::marker::PhantomData; + +use crate::prelude::*; + +use crate::graph::Node; +use crate::graph::{Edge, IndexType}; +use crate::serde_utils::CollectSeqWithLength; +use crate::serde_utils::MappedSequenceVisitor; +use crate::serde_utils::{FromDeserialized, IntoSerializable}; +use crate::stable_graph::StableGraph; +use crate::visit::{EdgeIndexable, NodeIndexable}; +use crate::EdgeType; + +use super::super::serialization::{ + invalid_hole_err, invalid_length_err, invalid_node_err, EdgeProperty, +}; + +// Serialization representation for StableGraph +// Keep in sync with deserialization and Graph +#[derive(Serialize)] +#[serde(rename = "Graph")] +#[serde(bound(serialize = "N: Serialize, E: Serialize, Ix: IndexType + Serialize"))] +pub struct SerStableGraph<'a, N: 'a, E: 'a, Ix: 'a + IndexType> { + nodes: Somes<&'a [Node, Ix>]>, + node_holes: Holes<&'a [Node, Ix>]>, + edge_property: EdgeProperty, + #[serde(serialize_with = "ser_stable_graph_edges")] + edges: &'a [Edge, Ix>], +} + +// Deserialization representation for StableGraph +// Keep in sync with serialization and Graph +#[derive(Deserialize)] +#[serde(rename = "Graph")] +#[serde(bound( + deserialize = "N: Deserialize<'de>, E: Deserialize<'de>, Ix: IndexType + Deserialize<'de>" +))] +pub struct DeserStableGraph { + #[serde(deserialize_with = "deser_stable_graph_nodes")] + nodes: Vec, Ix>>, + #[serde(default = "Vec::new")] + node_holes: Vec>, + edge_property: EdgeProperty, + #[serde(deserialize_with = "deser_stable_graph_edges")] + edges: Vec, Ix>>, +} + +/// `Somes` are the present node weights N, with known length. +struct Somes(usize, T); + +impl<'a, N, Ix> Serialize for Somes<&'a [Node, Ix>]> +where + N: Serialize, +{ + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.collect_seq_with_length( + self.0, + self.1.iter().filter_map(|node| node.weight.as_ref()), + ) + } +} + +/// Holes are the node indices of vacancies, with known length +struct Holes(usize, T); + +impl<'a, N, Ix> Serialize for Holes<&'a [Node, Ix>]> +where + Ix: Serialize + IndexType, +{ + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.collect_seq_with_length( + self.0, + self.1.iter().enumerate().filter_map(|(i, node)| { + if node.weight.is_none() { + Some(NodeIndex::::new(i)) + } else { + None + } + }), + ) + } +} + +fn ser_stable_graph_edges( + edges: &&[Edge, Ix>], + serializer: S, +) -> Result +where + S: Serializer, + E: Serialize, + Ix: Serialize + IndexType, +{ + serializer.collect_seq_exact(edges.iter().map(|edge| { + edge.weight + .as_ref() + .map(|w| (edge.source(), edge.target(), w)) + })) +} + +fn deser_stable_graph_nodes<'de, D, N, Ix>( + deserializer: D, +) -> Result, Ix>>, D::Error> +where + D: Deserializer<'de>, + N: Deserialize<'de>, + Ix: IndexType + Deserialize<'de>, +{ + deserializer.deserialize_seq(MappedSequenceVisitor::new(|n| { + Ok(Node { + weight: Some(n), + next: [EdgeIndex::end(); 2], + }) + })) +} + +fn deser_stable_graph_edges<'de, D, N, Ix>( + deserializer: D, +) -> Result, Ix>>, D::Error> +where + D: Deserializer<'de>, + N: Deserialize<'de>, + Ix: IndexType + Deserialize<'de>, +{ + deserializer.deserialize_seq(MappedSequenceVisitor::< + Option<(NodeIndex, NodeIndex, N)>, + _, + _, + >::new(|x| { + if let Some((i, j, w)) = x { + Ok(Edge { + weight: Some(w), + node: [i, j], + next: [EdgeIndex::end(); 2], + }) + } else { + Ok(Edge { + weight: None, + node: [NodeIndex::end(); 2], + next: [EdgeIndex::end(); 2], + }) + } + })) +} + +impl<'a, N, E, Ty, Ix> IntoSerializable for &'a StableGraph +where + Ix: IndexType, + Ty: EdgeType, +{ + type Output = SerStableGraph<'a, N, E, Ix>; + fn into_serializable(self) -> Self::Output { + let nodes = &self.raw_nodes()[..self.node_bound()]; + let node_count = self.node_count(); + let hole_count = nodes.len() - node_count; + let edges = &self.raw_edges()[..self.edge_bound()]; + SerStableGraph { + nodes: Somes(node_count, nodes), + node_holes: Holes(hole_count, nodes), + edges: edges, + edge_property: EdgeProperty::from(PhantomData::), + } + } +} + +/// Requires crate feature `"serde-1"` +impl Serialize for StableGraph +where + Ty: EdgeType, + Ix: IndexType + Serialize, + N: Serialize, + E: Serialize, +{ + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.into_serializable().serialize(serializer) + } +} + +impl<'a, N, E, Ty, Ix> FromDeserialized for StableGraph +where + Ix: IndexType, + Ty: EdgeType, +{ + type Input = DeserStableGraph; + fn from_deserialized(input: Self::Input) -> Result + where + E2: Error, + { + let ty = PhantomData::::from_deserialized(input.edge_property)?; + let node_holes = input.node_holes; + let edges = input.edges; + if edges.len() >= ::max().index() { + Err(invalid_length_err::("edge", edges.len()))? + } + + let total_nodes = input.nodes.len() + node_holes.len(); + let mut nodes = Vec::with_capacity(total_nodes); + + let mut compact_nodes = input.nodes.into_iter(); + let mut node_pos = 0; + for hole_pos in node_holes.iter() { + let hole_pos = hole_pos.index(); + if !(node_pos..total_nodes).contains(&hole_pos) { + return Err(invalid_hole_err(hole_pos)); + } + nodes.extend(compact_nodes.by_ref().take(hole_pos - node_pos)); + nodes.push(Node { + weight: None, + next: [EdgeIndex::end(); 2], + }); + node_pos = hole_pos + 1; + debug_assert_eq!(nodes.len(), node_pos); + } + nodes.extend(compact_nodes); + + if nodes.len() >= ::max().index() { + Err(invalid_length_err::("node", nodes.len()))? + } + + let node_bound = nodes.len(); + let mut sgr = StableGraph { + g: Graph { + nodes: nodes, + edges: edges, + ty: ty, + }, + node_count: 0, + edge_count: 0, + free_edge: EdgeIndex::end(), + free_node: NodeIndex::end(), + }; + sgr.link_edges() + .map_err(|i| invalid_node_err(i.index(), node_bound))?; + Ok(sgr) + } +} + +/// Requires crate feature `"serde-1"` +impl<'de, N, E, Ty, Ix> Deserialize<'de> for StableGraph +where + Ty: EdgeType, + Ix: IndexType + Deserialize<'de>, + N: Deserialize<'de>, + E: Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Self::from_deserialized(DeserStableGraph::deserialize(deserializer)?) + } +} + +#[test] +fn test_from_deserialized_with_holes() { + use crate::graph::node_index; + use crate::stable_graph::StableUnGraph; + use itertools::assert_equal; + use serde::de::value::Error as SerdeError; + + let input = DeserStableGraph::<_, (), u32> { + nodes: vec![ + Node { + weight: Some(1), + next: [EdgeIndex::end(); 2], + }, + Node { + weight: Some(4), + next: [EdgeIndex::end(); 2], + }, + Node { + weight: Some(5), + next: [EdgeIndex::end(); 2], + }, + ], + node_holes: vec![node_index(0), node_index(2), node_index(3), node_index(6)], + edges: vec![], + edge_property: EdgeProperty::Undirected, + }; + let graph = StableUnGraph::from_deserialized::(input).unwrap(); + + assert_eq!(graph.node_count(), 3); + assert_equal( + graph.raw_nodes().iter().map(|n| n.weight.as_ref().cloned()), + vec![None, Some(1), None, None, Some(4), Some(5), None], + ); +} diff --git a/vendor/petgraph/src/graphmap.rs b/vendor/petgraph/src/graphmap.rs new file mode 100644 index 00000000..855656be --- /dev/null +++ b/vendor/petgraph/src/graphmap.rs @@ -0,0 +1,1504 @@ +//! `GraphMap` is a graph datastructure where node values are mapping +//! keys. + +use indexmap::map::Keys; +use indexmap::map::{Iter as IndexMapIter, IterMut as IndexMapIterMut}; +use indexmap::IndexMap; +use std::cmp::Ordering; +use std::collections::hash_map::RandomState; +use std::collections::HashSet; +use std::fmt; +use std::hash::{self, BuildHasher, Hash}; +use std::iter::Copied; +use std::iter::FromIterator; +use std::marker::PhantomData; +use std::mem; +use std::ops::{Deref, Index, IndexMut}; +use std::slice::Iter; + +use crate::{Directed, Direction, EdgeType, Incoming, Outgoing, Undirected}; + +use crate::graph::node_index; +use crate::graph::Graph; +use crate::visit; +use crate::IntoWeightedEdge; + +#[cfg(feature = "rayon")] +use indexmap::map::rayon::{ParIter, ParIterMut, ParKeys}; +#[cfg(feature = "rayon")] +use rayon::prelude::*; + +/// A `GraphMap` with undirected edges. +/// +/// For example, an edge between *1* and *2* is equivalent to an edge between +/// *2* and *1*. +pub type UnGraphMap = GraphMap; +/// A `GraphMap` with directed edges. +/// +/// For example, an edge from *1* to *2* is distinct from an edge from *2* to +/// *1*. +pub type DiGraphMap = GraphMap; + +/// `GraphMap` is a graph datastructure using an associative array +/// of its node weights `N`. +/// +/// It uses an combined adjacency list and sparse adjacency matrix +/// representation, using **O(|V| + |E|)** space, and allows testing for edge +/// existence in constant time. +/// +/// `GraphMap` is parameterized over: +/// +/// - Associated data `N` for nodes and `E` for edges, called *weights*. +/// - The node weight `N` must implement `Copy` and will be used as node +/// identifier, duplicated into several places in the data structure. +/// It must be suitable as a hash table key (implementing `Eq + Hash`). +/// The node type must also implement `Ord` so that the implementation can +/// order the pair (`a`, `b`) for an edge connecting any two nodes `a` and `b`. +/// - `E` can be of arbitrary type. +/// - Edge type `Ty` that determines whether the graph edges are directed or +/// undirected. +/// +/// You can use the type aliases `UnGraphMap` and `DiGraphMap` for convenience. +/// +/// `GraphMap` does not allow parallel edges, but self loops are allowed. +/// +/// Depends on crate feature `graphmap` (default). +#[derive(Clone)] +pub struct GraphMap +where + S: BuildHasher, +{ + nodes: IndexMap, S>, + edges: IndexMap<(N, N), E, S>, + ty: PhantomData, +} + +impl fmt::Debug + for GraphMap +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.nodes.fmt(f) + } +} + +/// A trait group for `GraphMap`'s node identifier. +pub trait NodeTrait: Copy + Ord + Hash {} +impl NodeTrait for N where N: Copy + Ord + Hash {} + +// non-repr(usize) version of Direction +#[derive(Copy, Clone, Debug, PartialEq)] +enum CompactDirection { + Outgoing, + Incoming, +} + +impl CompactDirection { + /// Return the opposite `CompactDirection`. + #[inline] + pub fn opposite(self) -> CompactDirection { + match self { + CompactDirection::Outgoing => CompactDirection::Incoming, + CompactDirection::Incoming => CompactDirection::Outgoing, + } + } +} + +impl From for CompactDirection { + fn from(d: Direction) -> Self { + match d { + Outgoing => CompactDirection::Outgoing, + Incoming => CompactDirection::Incoming, + } + } +} + +impl From for Direction { + fn from(d: CompactDirection) -> Self { + match d { + CompactDirection::Outgoing => Outgoing, + CompactDirection::Incoming => Incoming, + } + } +} + +impl PartialEq for CompactDirection { + fn eq(&self, rhs: &Direction) -> bool { + (*self as usize) == (*rhs as usize) + } +} + +#[cfg(feature = "serde-1")] +impl serde::Serialize for GraphMap +where + Ty: EdgeType, + N: NodeTrait + serde::Serialize, + E: serde::Serialize, + S: BuildHasher, + Self: Clone, +{ + /// Serializes the given `GraphMap` into the same format as the standard + /// `Graph`. Needs feature `serde-1`. + /// + /// Note: the graph has to be `Clone` for this to work. + fn serialize(&self, serializer: Ser) -> Result + where + Ser: serde::Serializer, + { + let cloned_graph: GraphMap = GraphMap::clone(self); + let equivalent_graph: Graph = cloned_graph.into_graph(); + equivalent_graph.serialize(serializer) + } +} + +#[cfg(feature = "serde-1")] +impl<'de, N, E, Ty, S> serde::Deserialize<'de> for GraphMap +where + Ty: EdgeType, + N: NodeTrait + serde::Deserialize<'de>, + E: Clone + serde::Deserialize<'de>, + S: BuildHasher + Default, +{ + /// Deserializes into a new `GraphMap` from the same format as the standard + /// `Graph`. Needs feature `serde-1`. + /// + /// **Warning**: When deseralizing a graph that was not originally a `GraphMap`, + /// the restrictions from [`from_graph`](#method.from_graph) apply. + /// + /// Note: The edge weights have to be `Clone` for this to work. + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let equivalent_graph: Graph = Graph::deserialize(deserializer)?; + Ok(GraphMap::from_graph(equivalent_graph)) + } +} + +impl GraphMap +where + N: NodeTrait, + Ty: EdgeType, + S: BuildHasher, +{ + /// Create a new `GraphMap` + pub fn new() -> Self + where + S: Default, + { + Self::default() + } + + /// Create a new `GraphMap` with estimated capacity. + pub fn with_capacity(nodes: usize, edges: usize) -> Self + where + S: Default, + { + Self { + nodes: IndexMap::with_capacity_and_hasher(nodes, S::default()), + edges: IndexMap::with_capacity_and_hasher(edges, S::default()), + ty: PhantomData, + } + } + + /// Create a new `GraphMap` with estimated capacity, and specified hasher. + pub fn with_capacity_and_hasher(nodes: usize, edges: usize, hasher: S) -> Self + where + S: Clone, + { + Self { + nodes: IndexMap::with_capacity_and_hasher(nodes, hasher.clone()), + edges: IndexMap::with_capacity_and_hasher(edges, hasher), + ty: PhantomData, + } + } + + /// Return the current node and edge capacity of the graph. + pub fn capacity(&self) -> (usize, usize) { + (self.nodes.capacity(), self.edges.capacity()) + } + + /// Use their natural order to map the node pair (a, b) to a canonical edge id. + #[inline] + fn edge_key(a: N, b: N) -> (N, N) { + if Ty::is_directed() || a <= b { + (a, b) + } else { + (b, a) + } + } + + /// Whether the graph has directed edges. + pub fn is_directed(&self) -> bool { + Ty::is_directed() + } + + /// Create a new `GraphMap` from an iterable of edges. + /// + /// Node values are taken directly from the list. + /// Edge weights `E` may either be specified in the list, + /// or they are filled with default values. + /// + /// Nodes are inserted automatically to match the edges. + /// + /// ``` + /// use petgraph::graphmap::UnGraphMap; + /// + /// // Create a new undirected GraphMap. + /// // Use a type hint to have `()` be the edge weight type. + /// let gr = UnGraphMap::<_, ()>::from_edges(&[ + /// (0, 1), (0, 2), (0, 3), + /// (1, 2), (1, 3), + /// (2, 3), + /// ]); + /// ``` + pub fn from_edges(iterable: I) -> Self + where + I: IntoIterator, + I::Item: IntoWeightedEdge, + S: Default, + { + Self::from_iter(iterable) + } + + /// Return the number of nodes in the graph. + pub fn node_count(&self) -> usize { + self.nodes.len() + } + + /// Return the number of edges in the graph. + pub fn edge_count(&self) -> usize { + self.edges.len() + } + + /// Remove all nodes and edges + pub fn clear(&mut self) { + self.nodes.clear(); + self.edges.clear(); + } + + /// Add node `n` to the graph. + pub fn add_node(&mut self, n: N) -> N { + self.nodes.entry(n).or_default(); + n + } + + /// Return `true` if node `n` was removed. + /// + /// Computes in **O(V)** time, due to the removal of edges with other nodes. + pub fn remove_node(&mut self, n: N) -> bool { + let links = match self.nodes.swap_remove(&n) { + None => return false, + Some(sus) => sus, + }; + for (succ, dir) in links { + let edge = if dir == CompactDirection::Outgoing { + Self::edge_key(n, succ) + } else { + Self::edge_key(succ, n) + }; + // remove all successor links + self.remove_single_edge(&succ, &n, dir.opposite()); + // Remove all edge values + self.edges.swap_remove(&edge); + } + true + } + + /// Return `true` if the node is contained in the graph. + pub fn contains_node(&self, n: N) -> bool { + self.nodes.contains_key(&n) + } + + /// Add an edge connecting `a` and `b` to the graph, with associated + /// data `weight`. For a directed graph, the edge is directed from `a` + /// to `b`. + /// + /// Inserts nodes `a` and/or `b` if they aren't already part of the graph. + /// + /// Return `None` if the edge did not previously exist, otherwise, + /// the associated data is updated and the old value is returned + /// as `Some(old_weight)`. + /// + /// ``` + /// // Create a GraphMap with directed edges, and add one edge to it + /// use petgraph::graphmap::DiGraphMap; + /// + /// let mut g = DiGraphMap::new(); + /// g.add_edge("x", "y", -1); + /// assert_eq!(g.node_count(), 2); + /// assert_eq!(g.edge_count(), 1); + /// assert!(g.contains_edge("x", "y")); + /// assert!(!g.contains_edge("y", "x")); + /// ``` + pub fn add_edge(&mut self, a: N, b: N, weight: E) -> Option { + if let old @ Some(_) = self.edges.insert(Self::edge_key(a, b), weight) { + old + } else { + // insert in the adjacency list if it's a new edge + self.nodes + .entry(a) + .or_insert_with(|| Vec::with_capacity(1)) + .push((b, CompactDirection::Outgoing)); + if a != b { + // self loops don't have the Incoming entry + self.nodes + .entry(b) + .or_insert_with(|| Vec::with_capacity(1)) + .push((a, CompactDirection::Incoming)); + } + None + } + } + + /// Remove edge relation from a to b + /// + /// Return `true` if it did exist. + fn remove_single_edge(&mut self, a: &N, b: &N, dir: CompactDirection) -> bool { + match self.nodes.get_mut(a) { + None => false, + Some(sus) => { + if Ty::is_directed() { + match sus.iter().position(|elt| elt == &(*b, dir)) { + Some(index) => { + sus.swap_remove(index); + true + } + None => false, + } + } else { + match sus.iter().position(|elt| &elt.0 == b) { + Some(index) => { + sus.swap_remove(index); + true + } + None => false, + } + } + } + } + } + + /// Remove edge from `a` to `b` from the graph and return the edge weight. + /// + /// Return `None` if the edge didn't exist. + /// + /// ``` + /// // Create a GraphMap with undirected edges, and add and remove an edge. + /// use petgraph::graphmap::UnGraphMap; + /// + /// let mut g = UnGraphMap::new(); + /// g.add_edge("x", "y", -1); + /// + /// let edge_data = g.remove_edge("y", "x"); + /// assert_eq!(edge_data, Some(-1)); + /// assert_eq!(g.edge_count(), 0); + /// ``` + pub fn remove_edge(&mut self, a: N, b: N) -> Option { + let exist1 = self.remove_single_edge(&a, &b, CompactDirection::Outgoing); + let exist2 = if a != b { + self.remove_single_edge(&b, &a, CompactDirection::Incoming) + } else { + exist1 + }; + let weight = self.edges.swap_remove(&Self::edge_key(a, b)); + debug_assert!(exist1 == exist2 && exist1 == weight.is_some()); + weight + } + + /// Return `true` if the edge connecting `a` with `b` is contained in the graph. + pub fn contains_edge(&self, a: N, b: N) -> bool { + self.edges.contains_key(&Self::edge_key(a, b)) + } + + /// Return an iterator over the nodes of the graph. + /// + /// Iterator element type is `N`. + pub fn nodes(&self) -> Nodes<'_, N> { + Nodes { + iter: self.nodes.keys().copied(), + } + } + + /// Return a parallel iterator over the nodes of the graph. + /// + /// Iterator element type is `N`. + #[cfg(feature = "rayon")] + pub fn par_nodes(&self) -> ParNodes<'_, N> + where + N: Send + Sync, + { + ParNodes { + iter: self.nodes.par_keys(), + } + } + + /// Return an iterator of all nodes with an edge starting from `a`. + /// + /// - `Directed`: Outgoing edges from `a`. + /// - `Undirected`: All edges from or to `a`. + /// + /// Produces an empty iterator if the node doesn't exist.
+ /// Iterator element type is `N`. + pub fn neighbors(&self, a: N) -> Neighbors { + Neighbors { + iter: match self.nodes.get(&a) { + Some(neigh) => neigh.iter(), + None => [].iter(), + }, + ty: self.ty, + } + } + + /// Return an iterator of all neighbors that have an edge between them and + /// `a`, in the specified direction. + /// If the graph's edges are undirected, this is equivalent to *.neighbors(a)*. + /// + /// - `Directed`, `Outgoing`: All edges from `a`. + /// - `Directed`, `Incoming`: All edges to `a`. + /// - `Undirected`: All edges from or to `a`. + /// + /// Produces an empty iterator if the node doesn't exist.
+ /// Iterator element type is `N`. + pub fn neighbors_directed(&self, a: N, dir: Direction) -> NeighborsDirected { + NeighborsDirected { + iter: match self.nodes.get(&a) { + Some(neigh) => neigh.iter(), + None => [].iter(), + }, + start_node: a, + dir, + ty: self.ty, + } + } + + /// Return an iterator of target nodes with an edge starting from `a`, + /// paired with their respective edge weights. + /// + /// - `Directed`: Outgoing edges from `a`. + /// - `Undirected`: All edges from or to `a`. + /// + /// Produces an empty iterator if the node doesn't exist.
+ /// Iterator element type is `(N, N, &E)`. + pub fn edges(&self, a: N) -> Edges { + Edges { + from: a, + iter: self.neighbors(a), + edges: &self.edges, + } + } + + /// Return an iterator of target nodes with an edge starting from `a`, + /// paired with their respective edge weights. + /// + /// - `Directed`, `Outgoing`: All edges from `a`. + /// - `Directed`, `Incoming`: All edges to `a`. + /// - `Undirected`, `Outgoing`: All edges connected to `a`, with `a` being the source of each + /// edge. + /// - `Undirected`, `Incoming`: All edges connected to `a`, with `a` being the target of each + /// edge. + /// + /// Produces an empty iterator if the node doesn't exist.
+ /// Iterator element type is `(N, N, &E)`. + pub fn edges_directed(&self, a: N, dir: Direction) -> EdgesDirected { + EdgesDirected { + from: a, + iter: self.neighbors_directed(a, dir), + dir, + edges: &self.edges, + } + } + + /// Return a reference to the edge weight connecting `a` with `b`, or + /// `None` if the edge does not exist in the graph. + pub fn edge_weight(&self, a: N, b: N) -> Option<&E> { + self.edges.get(&Self::edge_key(a, b)) + } + + /// Return a mutable reference to the edge weight connecting `a` with `b`, or + /// `None` if the edge does not exist in the graph. + pub fn edge_weight_mut(&mut self, a: N, b: N) -> Option<&mut E> { + self.edges.get_mut(&Self::edge_key(a, b)) + } + + /// Return an iterator over all edges of the graph with their weight in arbitrary order. + /// + /// Iterator element type is `(N, N, &E)` + pub fn all_edges(&self) -> AllEdges { + AllEdges { + inner: self.edges.iter(), + ty: self.ty, + } + } + + /// Return an iterator over all edges of the graph in arbitrary order, with a mutable reference + /// to their weight. + /// + /// Iterator element type is `(N, N, &mut E)` + pub fn all_edges_mut(&mut self) -> AllEdgesMut { + AllEdgesMut { + inner: self.edges.iter_mut(), + ty: self.ty, + } + } + + /// Return a parallel iterator over all edges of the graph with their weight in arbitrary + /// order. + /// + /// Iterator element type is `(N, N, &E)` + #[cfg(feature = "rayon")] + pub fn par_all_edges(&self) -> ParAllEdges + where + N: Send + Sync, + E: Sync, + { + ParAllEdges { + inner: self.edges.par_iter(), + ty: PhantomData, + } + } + + /// Return a parallel iterator over all edges of the graph in arbitrary order, with a mutable + /// reference to their weight. + /// + /// Iterator element type is `(N, N, &mut E)` + #[cfg(feature = "rayon")] + pub fn par_all_edges_mut(&mut self) -> ParAllEdgesMut + where + N: Send + Sync, + E: Send, + { + ParAllEdgesMut { + inner: self.edges.par_iter_mut(), + ty: PhantomData, + } + } + + /// Return a `Graph` that corresponds to this `GraphMap`. + /// + /// 1. Note that node and edge indices in the `Graph` have nothing in common + /// with the `GraphMap`s node weights `N`. The node weights `N` are used as + /// node weights in the resulting `Graph`, too. + /// 2. Note that the index type is user-chosen. + /// + /// Computes in **O(|V| + |E|)** time (average). + /// + /// **Panics** if the number of nodes or edges does not fit with + /// the resulting graph's index type. + pub fn into_graph(self) -> Graph + where + Ix: crate::graph::IndexType, + { + // assuming two successive iterations of the same hashmap produce the same order + let mut gr = Graph::with_capacity(self.node_count(), self.edge_count()); + for (&node, _) in &self.nodes { + gr.add_node(node); + } + for ((a, b), edge_weight) in self.edges { + let ai = self.nodes.get_index_of(&a).unwrap(); + let bi = self.nodes.get_index_of(&b).unwrap(); + gr.add_edge(node_index(ai), node_index(bi), edge_weight); + } + gr + } + + /// Creates a `GraphMap` that corresponds to the given `Graph`. + /// + /// **Warning**: Nodes with the same weight are merged and only the last parallel edge + /// is kept. Node and edge indices of the `Graph` are lost. Only use this function + /// if the node weights are distinct and there are no parallel edges. + /// + /// Computes in **O(|V| + |E|)** time (average). + pub fn from_graph(graph: Graph) -> Self + where + Ix: crate::graph::IndexType, + E: Clone, + S: Default, + { + let mut new_graph: GraphMap = + GraphMap::with_capacity(graph.node_count(), graph.edge_count()); + + for node in graph.raw_nodes() { + new_graph.add_node(node.weight); + } + + for edge in graph.edge_indices() { + let (a, b) = graph.edge_endpoints(edge).unwrap(); + new_graph.add_edge( + *graph.node_weight(a).unwrap(), + *graph.node_weight(b).unwrap(), + graph.edge_weight(edge).unwrap().clone(), + ); + } + + new_graph + } +} + +/// Create a new `GraphMap` from an iterable of edges. +impl FromIterator for GraphMap +where + Item: IntoWeightedEdge, + N: NodeTrait, + Ty: EdgeType, + S: BuildHasher + Default, +{ + fn from_iter(iterable: I) -> Self + where + I: IntoIterator, + { + let iter = iterable.into_iter(); + let (low, _) = iter.size_hint(); + let mut g = Self::with_capacity(0, low); + g.extend(iter); + g + } +} + +/// Extend the graph from an iterable of edges. +/// +/// Nodes are inserted automatically to match the edges. +impl Extend for GraphMap +where + Item: IntoWeightedEdge, + N: NodeTrait, + Ty: EdgeType, + S: BuildHasher, +{ + fn extend(&mut self, iterable: I) + where + I: IntoIterator, + { + let iter = iterable.into_iter(); + let (low, _) = iter.size_hint(); + self.edges.reserve(low); + + for elt in iter { + let (source, target, weight) = elt.into_weighted_edge(); + self.add_edge(source, target, weight); + } + } +} + +iterator_wrap! { + impl (Iterator DoubleEndedIterator ExactSizeIterator) for + #[derive(Debug, Clone)] + struct Nodes <'a, N> where { N: 'a + NodeTrait } + item: N, + iter: Copied>>, +} + +#[derive(Debug, Clone)] +pub struct Neighbors<'a, N, Ty = Undirected> +where + N: 'a, + Ty: EdgeType, +{ + iter: Iter<'a, (N, CompactDirection)>, + ty: PhantomData, +} + +impl Iterator for Neighbors<'_, N, Ty> +where + N: NodeTrait, + Ty: EdgeType, +{ + type Item = N; + fn next(&mut self) -> Option { + if Ty::is_directed() { + (&mut self.iter) + .filter_map(|&(n, dir)| if dir == Outgoing { Some(n) } else { None }) + .next() + } else { + self.iter.next().map(|&(n, _)| n) + } + } + fn size_hint(&self) -> (usize, Option) { + let (lower, upper) = self.iter.size_hint(); + if Ty::is_directed() { + (0, upper) + } else { + (lower, upper) + } + } +} + +#[derive(Debug, Clone)] +pub struct NeighborsDirected<'a, N, Ty> +where + N: 'a, + Ty: EdgeType, +{ + iter: Iter<'a, (N, CompactDirection)>, + start_node: N, + dir: Direction, + ty: PhantomData, +} + +impl Iterator for NeighborsDirected<'_, N, Ty> +where + N: NodeTrait, + Ty: EdgeType, +{ + type Item = N; + fn next(&mut self) -> Option { + if Ty::is_directed() { + let self_dir = self.dir; + let start_node = self.start_node; + (&mut self.iter) + .filter_map(move |&(n, dir)| { + if dir == self_dir || n == start_node { + Some(n) + } else { + None + } + }) + .next() + } else { + self.iter.next().map(|&(n, _)| n) + } + } + fn size_hint(&self) -> (usize, Option) { + let (lower, upper) = self.iter.size_hint(); + if Ty::is_directed() { + (0, upper) + } else { + (lower, upper) + } + } +} + +#[derive(Debug, Clone)] +pub struct Edges<'a, N, E: 'a, Ty, S = RandomState> +where + N: 'a + NodeTrait, + Ty: EdgeType, + S: BuildHasher, +{ + from: N, + edges: &'a IndexMap<(N, N), E, S>, + iter: Neighbors<'a, N, Ty>, +} + +impl<'a, N, E, Ty, S> Iterator for Edges<'a, N, E, Ty, S> +where + N: 'a + NodeTrait, + E: 'a, + Ty: EdgeType, + S: BuildHasher, +{ + type Item = (N, N, &'a E); + fn next(&mut self) -> Option { + self.iter.next().map(|b| { + let a = self.from; + match self.edges.get(&GraphMap::::edge_key(a, b)) { + None => unreachable!(), + Some(edge) => (a, b, edge), + } + }) + } + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +#[derive(Debug, Clone)] +pub struct EdgesDirected<'a, N, E: 'a, Ty, S = RandomState> +where + N: 'a + NodeTrait, + Ty: EdgeType, + S: BuildHasher, +{ + from: N, + dir: Direction, + edges: &'a IndexMap<(N, N), E, S>, + iter: NeighborsDirected<'a, N, Ty>, +} + +impl<'a, N, E, Ty, S> Iterator for EdgesDirected<'a, N, E, Ty, S> +where + N: 'a + NodeTrait, + E: 'a, + Ty: EdgeType, + S: BuildHasher, +{ + type Item = (N, N, &'a E); + fn next(&mut self) -> Option { + self.iter.next().map(|mut b| { + let mut a = self.from; + if self.dir == Direction::Incoming { + mem::swap(&mut a, &mut b); + } + match self.edges.get(&GraphMap::::edge_key(a, b)) { + None => unreachable!(), + Some(edge) => (a, b, edge), + } + }) + } + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +#[derive(Debug, Clone)] +pub struct AllEdges<'a, N, E: 'a, Ty> +where + N: 'a + NodeTrait, +{ + inner: IndexMapIter<'a, (N, N), E>, + ty: PhantomData, +} + +impl<'a, N, E, Ty> Iterator for AllEdges<'a, N, E, Ty> +where + N: 'a + NodeTrait, + E: 'a, + Ty: EdgeType, +{ + type Item = (N, N, &'a E); + fn next(&mut self) -> Option { + self.inner.next().map(|(&(a, b), v)| (a, b, v)) + } + + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + + fn count(self) -> usize { + self.inner.count() + } + + fn nth(&mut self, n: usize) -> Option { + self.inner + .nth(n) + .map(|(&(n1, n2), weight)| (n1, n2, weight)) + } + + fn last(self) -> Option { + self.inner + .last() + .map(|(&(n1, n2), weight)| (n1, n2, weight)) + } +} + +impl<'a, N, E, Ty> DoubleEndedIterator for AllEdges<'a, N, E, Ty> +where + N: 'a + NodeTrait, + E: 'a, + Ty: EdgeType, +{ + fn next_back(&mut self) -> Option { + self.inner + .next_back() + .map(|(&(n1, n2), weight)| (n1, n2, weight)) + } +} + +pub struct AllEdgesMut<'a, N, E: 'a, Ty> +where + N: 'a + NodeTrait, +{ + inner: IndexMapIterMut<'a, (N, N), E>, // TODO: change to something that implements Debug + Clone? + ty: PhantomData, +} + +impl<'a, N, E, Ty> Iterator for AllEdgesMut<'a, N, E, Ty> +where + N: 'a + NodeTrait, + E: 'a, + Ty: EdgeType, +{ + type Item = (N, N, &'a mut E); + fn next(&mut self) -> Option { + self.inner + .next() + .map(|(&(n1, n2), weight)| (n1, n2, weight)) + } + + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + + fn count(self) -> usize { + self.inner.count() + } + + fn nth(&mut self, n: usize) -> Option { + self.inner + .nth(n) + .map(|(&(n1, n2), weight)| (n1, n2, weight)) + } + + fn last(self) -> Option { + self.inner + .last() + .map(|(&(n1, n2), weight)| (n1, n2, weight)) + } +} + +impl<'a, N, E, Ty> DoubleEndedIterator for AllEdgesMut<'a, N, E, Ty> +where + N: 'a + NodeTrait, + E: 'a, + Ty: EdgeType, +{ + fn next_back(&mut self) -> Option { + self.inner + .next_back() + .map(|(&(n1, n2), weight)| (n1, n2, weight)) + } +} + +/// Index `GraphMap` by node pairs to access edge weights. +impl Index<(N, N)> for GraphMap +where + N: NodeTrait, + Ty: EdgeType, + S: BuildHasher, +{ + type Output = E; + fn index(&self, index: (N, N)) -> &E { + let index = Self::edge_key(index.0, index.1); + self.edge_weight(index.0, index.1) + .expect("GraphMap::index: no such edge") + } +} + +/// Index `GraphMap` by node pairs to access edge weights. +impl IndexMut<(N, N)> for GraphMap +where + N: NodeTrait, + Ty: EdgeType, + S: BuildHasher, +{ + fn index_mut(&mut self, index: (N, N)) -> &mut E { + let index = Self::edge_key(index.0, index.1); + self.edge_weight_mut(index.0, index.1) + .expect("GraphMap::index: no such edge") + } +} + +/// Create a new empty `GraphMap`. +impl Default for GraphMap +where + N: NodeTrait, + Ty: EdgeType, + S: BuildHasher + Default, +{ + fn default() -> Self { + GraphMap::with_capacity(0, 0) + } +} + +/// A reference that is hashed and compared by its pointer value. +/// +/// `Ptr` is used for certain configurations of `GraphMap`, +/// in particular in the combination where the node type for +/// `GraphMap` is something of type for example `Ptr(&Cell)`, +/// with the `Cell` being `TypedArena` allocated. +pub struct Ptr<'b, T: 'b>(pub &'b T); + +impl Copy for Ptr<'_, T> {} +impl Clone for Ptr<'_, T> { + fn clone(&self) -> Self { + *self + } +} + +fn ptr_eq(a: *const T, b: *const T) -> bool { + a == b +} + +impl<'b, T> PartialEq for Ptr<'b, T> { + /// Ptr compares by pointer equality, i.e if they point to the same value + fn eq(&self, other: &Ptr<'b, T>) -> bool { + ptr_eq(self.0, other.0) + } +} + +impl<'b, T> PartialOrd for Ptr<'b, T> { + fn partial_cmp(&self, other: &Ptr<'b, T>) -> Option { + Some(self.cmp(other)) + } +} + +impl<'b, T> Ord for Ptr<'b, T> { + /// Ptr is ordered by pointer value, i.e. an arbitrary but stable and total order. + fn cmp(&self, other: &Ptr<'b, T>) -> Ordering { + let a: *const T = self.0; + let b: *const T = other.0; + a.cmp(&b) + } +} + +impl Deref for Ptr<'_, T> { + type Target = T; + fn deref(&self) -> &T { + self.0 + } +} + +impl Eq for Ptr<'_, T> {} + +impl Hash for Ptr<'_, T> { + fn hash(&self, st: &mut H) { + let ptr = (self.0) as *const T; + ptr.hash(st) + } +} + +impl fmt::Debug for Ptr<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.0.fmt(f) + } +} + +#[derive(Debug, Clone)] +pub struct NodeIdentifiers<'a, N, E: 'a, Ty> +where + N: 'a + NodeTrait, +{ + iter: IndexMapIter<'a, N, Vec<(N, CompactDirection)>>, + ty: PhantomData, + edge_ty: PhantomData, +} + +impl<'a, N, E, Ty> Iterator for NodeIdentifiers<'a, N, E, Ty> +where + N: 'a + NodeTrait, + E: 'a, + Ty: EdgeType, +{ + type Item = N; + fn next(&mut self) -> Option { + self.iter.next().map(|(&n, _)| n) + } + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +#[derive(Debug, Clone)] +pub struct NodeReferences<'a, N, E: 'a, Ty> +where + N: 'a + NodeTrait, +{ + iter: IndexMapIter<'a, N, Vec<(N, CompactDirection)>>, + ty: PhantomData, + edge_ty: PhantomData, +} + +impl<'a, N, E, Ty> Iterator for NodeReferences<'a, N, E, Ty> +where + N: 'a + NodeTrait, + E: 'a, + Ty: EdgeType, +{ + type Item = (N, &'a N); + fn next(&mut self) -> Option { + self.iter.next().map(|(n, _)| (*n, n)) + } + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +impl visit::GraphBase for GraphMap +where + N: Copy + PartialEq, + S: BuildHasher, +{ + type NodeId = N; + type EdgeId = (N, N); +} + +impl visit::Data for GraphMap +where + N: Copy + PartialEq, + Ty: EdgeType, + S: BuildHasher, +{ + type NodeWeight = N; + type EdgeWeight = E; +} + +impl visit::Visitable for GraphMap +where + N: Copy + Ord + Hash, + Ty: EdgeType, + S: BuildHasher, +{ + type Map = HashSet; + fn visit_map(&self) -> HashSet { + HashSet::with_capacity(self.node_count()) + } + fn reset_map(&self, map: &mut Self::Map) { + map.clear(); + } +} + +impl visit::GraphProp for GraphMap +where + N: NodeTrait, + Ty: EdgeType, + S: BuildHasher, +{ + type EdgeType = Ty; +} + +impl<'a, N, E, Ty, S> visit::IntoNodeReferences for &'a GraphMap +where + N: NodeTrait, + Ty: EdgeType, + S: BuildHasher, +{ + type NodeRef = (N, &'a N); + type NodeReferences = NodeReferences<'a, N, E, Ty>; + fn node_references(self) -> Self::NodeReferences { + NodeReferences { + iter: self.nodes.iter(), + ty: self.ty, + edge_ty: PhantomData, + } + } +} + +impl<'a, N, E: 'a, Ty, S> visit::IntoNodeIdentifiers for &'a GraphMap +where + N: NodeTrait, + Ty: EdgeType, + S: BuildHasher, +{ + type NodeIdentifiers = NodeIdentifiers<'a, N, E, Ty>; + + fn node_identifiers(self) -> Self::NodeIdentifiers { + NodeIdentifiers { + iter: self.nodes.iter(), + ty: self.ty, + edge_ty: PhantomData, + } + } +} + +impl visit::NodeCount for GraphMap +where + N: NodeTrait, + Ty: EdgeType, + S: BuildHasher, +{ + fn node_count(&self) -> usize { + (*self).node_count() + } +} + +impl visit::NodeIndexable for GraphMap +where + N: NodeTrait, + Ty: EdgeType, + S: BuildHasher, +{ + fn node_bound(&self) -> usize { + self.node_count() + } + fn to_index(&self, ix: Self::NodeId) -> usize { + self.nodes.get_index_of(&ix).unwrap() + } + fn from_index(&self, ix: usize) -> Self::NodeId { + assert!( + ix < self.nodes.len(), + "The requested index {} is out-of-bounds.", + ix + ); + let (&key, _) = self.nodes.get_index(ix).unwrap(); + key + } +} + +impl visit::NodeCompactIndexable for GraphMap +where + N: NodeTrait, + Ty: EdgeType, + S: BuildHasher, +{ +} + +impl<'a, N: 'a, E, Ty, S> visit::IntoNeighbors for &'a GraphMap +where + N: Copy + Ord + Hash, + Ty: EdgeType, + S: BuildHasher, +{ + type Neighbors = Neighbors<'a, N, Ty>; + fn neighbors(self, n: Self::NodeId) -> Self::Neighbors { + self.neighbors(n) + } +} + +impl<'a, N: 'a, E, Ty, S> visit::IntoNeighborsDirected for &'a GraphMap +where + N: Copy + Ord + Hash, + Ty: EdgeType, + S: BuildHasher, +{ + type NeighborsDirected = NeighborsDirected<'a, N, Ty>; + fn neighbors_directed(self, n: N, dir: Direction) -> Self::NeighborsDirected { + self.neighbors_directed(n, dir) + } +} + +impl visit::EdgeIndexable for GraphMap +where + N: NodeTrait, + Ty: EdgeType, + S: BuildHasher, +{ + fn edge_bound(&self) -> usize { + self.edge_count() + } + + fn to_index(&self, ix: Self::EdgeId) -> usize { + self.edges.get_index_of(&ix).unwrap() + } + + fn from_index(&self, ix: usize) -> Self::EdgeId { + assert!( + ix < self.edges.len(), + "The requested index {} is out-of-bounds.", + ix + ); + let (&key, _) = self.edges.get_index(ix).unwrap(); + key + } +} + +impl<'a, N: 'a, E: 'a, Ty, S> visit::IntoEdges for &'a GraphMap +where + N: NodeTrait, + Ty: EdgeType, + S: BuildHasher, +{ + type Edges = Edges<'a, N, E, Ty, S>; + fn edges(self, a: Self::NodeId) -> Self::Edges { + self.edges(a) + } +} + +impl<'a, N: 'a, E: 'a, Ty, S> visit::IntoEdgesDirected for &'a GraphMap +where + N: NodeTrait, + Ty: EdgeType, + S: BuildHasher, +{ + type EdgesDirected = EdgesDirected<'a, N, E, Ty, S>; + fn edges_directed(self, a: Self::NodeId, dir: Direction) -> Self::EdgesDirected { + self.edges_directed(a, dir) + } +} + +impl<'a, N: 'a, E: 'a, Ty, S> visit::IntoEdgeReferences for &'a GraphMap +where + N: NodeTrait, + Ty: EdgeType, + S: BuildHasher, +{ + type EdgeRef = (N, N, &'a E); + type EdgeReferences = AllEdges<'a, N, E, Ty>; + fn edge_references(self) -> Self::EdgeReferences { + self.all_edges() + } +} + +impl visit::EdgeCount for GraphMap +where + N: NodeTrait, + Ty: EdgeType, + S: BuildHasher, +{ + #[inline] + fn edge_count(&self) -> usize { + self.edge_count() + } +} + +/// The `GraphMap` keeps an adjacency matrix internally. +impl visit::GetAdjacencyMatrix for GraphMap +where + N: Copy + Ord + Hash, + Ty: EdgeType, + S: BuildHasher, +{ + type AdjMatrix = (); + #[inline] + fn adjacency_matrix(&self) {} + #[inline] + fn is_adjacent(&self, _: &(), a: N, b: N) -> bool { + self.contains_edge(a, b) + } +} + +/// A [ParallelIterator] over this graph's nodes. +#[cfg(feature = "rayon")] +pub struct ParNodes<'a, N> +where + N: NodeTrait + Send + Sync, +{ + iter: ParKeys<'a, N, Vec<(N, CompactDirection)>>, +} + +#[cfg(feature = "rayon")] +impl<'a, N> ParallelIterator for ParNodes<'a, N> +where + N: NodeTrait + Send + Sync, +{ + type Item = N; + + fn drive_unindexed(self, consumer: C) -> C::Result + where + C: rayon::iter::plumbing::UnindexedConsumer, + { + self.iter.copied().drive_unindexed(consumer) + } + + fn opt_len(&self) -> Option { + self.iter.opt_len() + } +} + +#[cfg(feature = "rayon")] +impl<'a, N> IndexedParallelIterator for ParNodes<'a, N> +where + N: NodeTrait + Send + Sync, +{ + fn drive(self, consumer: C) -> C::Result + where + C: rayon::iter::plumbing::Consumer, + { + self.iter.copied().drive(consumer) + } + + fn len(&self) -> usize { + self.iter.len() + } + + fn with_producer(self, callback: CB) -> CB::Output + where + CB: rayon::iter::plumbing::ProducerCallback, + { + self.iter.copied().with_producer(callback) + } +} + +/// A [ParallelIterator] over this graph's edges. +#[cfg(feature = "rayon")] +pub struct ParAllEdges<'a, N, E, Ty> +where + N: NodeTrait + Send + Sync, + E: Sync, +{ + inner: ParIter<'a, (N, N), E>, + ty: PhantomData, +} + +#[cfg(feature = "rayon")] +impl<'a, N, E, Ty> ParallelIterator for ParAllEdges<'a, N, E, Ty> +where + N: NodeTrait + Send + Sync, + E: Sync, +{ + type Item = (N, N, &'a E); + + fn drive_unindexed(self, c: C) -> C::Result + where + C: rayon::iter::plumbing::UnindexedConsumer, + { + self.inner.map(|(&(a, b), v)| (a, b, v)).drive_unindexed(c) + } + + fn opt_len(&self) -> Option { + self.inner.opt_len() + } +} + +#[cfg(feature = "rayon")] +impl<'a, N, E, Ty> IndexedParallelIterator for ParAllEdges<'a, N, E, Ty> +where + N: NodeTrait + Send + Sync, + E: Sync, +{ + fn drive(self, consumer: C) -> C::Result + where + C: rayon::iter::plumbing::Consumer, + { + self.inner.map(|(&(a, b), v)| (a, b, v)).drive(consumer) + } + + fn len(&self) -> usize { + self.inner.len() + } + + fn with_producer(self, callback: CB) -> CB::Output + where + CB: rayon::iter::plumbing::ProducerCallback, + { + self.inner + .map(|(&(a, b), v)| (a, b, v)) + .with_producer(callback) + } +} + +/// A [ParallelIterator] over this graph's edges by mutable reference. +#[cfg(feature = "rayon")] +pub struct ParAllEdgesMut<'a, N, E: 'a, Ty> +where + N: NodeTrait + Send + Sync, + E: Send, +{ + inner: ParIterMut<'a, (N, N), E>, + ty: PhantomData, +} + +#[cfg(feature = "rayon")] +impl<'a, N, E, Ty> ParallelIterator for ParAllEdgesMut<'a, N, E, Ty> +where + N: NodeTrait + Send + Sync, + E: Send, +{ + type Item = (N, N, &'a mut E); + + fn drive_unindexed(self, c: C) -> C::Result + where + C: rayon::iter::plumbing::UnindexedConsumer, + { + self.inner.map(|(&(a, b), v)| (a, b, v)).drive_unindexed(c) + } + + fn opt_len(&self) -> Option { + self.inner.opt_len() + } +} + +#[cfg(feature = "rayon")] +impl<'a, N, E, Ty> IndexedParallelIterator for ParAllEdgesMut<'a, N, E, Ty> +where + N: NodeTrait + Send + Sync, + E: Send, +{ + fn drive(self, consumer: C) -> C::Result + where + C: rayon::iter::plumbing::Consumer, + { + self.inner.map(|(&(a, b), v)| (a, b, v)).drive(consumer) + } + + fn len(&self) -> usize { + self.inner.len() + } + + fn with_producer(self, callback: CB) -> CB::Output + where + CB: rayon::iter::plumbing::ProducerCallback, + { + self.inner + .map(|(&(a, b), v)| (a, b, v)) + .with_producer(callback) + } +} diff --git a/vendor/petgraph/src/iter_format.rs b/vendor/petgraph/src/iter_format.rs new file mode 100644 index 00000000..c882b1e7 --- /dev/null +++ b/vendor/petgraph/src/iter_format.rs @@ -0,0 +1,102 @@ +//! Formatting utils + +use std::cell::RefCell; +use std::fmt; + +/// Format the iterator like a map +pub struct DebugMap(pub F); + +impl fmt::Debug for DebugMap +where + F: Fn() -> I, + I: IntoIterator, + K: fmt::Debug, + V: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_map().entries((self.0)()).finish() + } +} + +/// Avoid "pretty" debug +pub struct NoPretty(pub T); + +impl fmt::Debug for NoPretty +where + T: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self.0) + } +} + +/// Format all iterator elements lazily, separated by `sep`. +/// +/// The format value can only be formatted once, after that the iterator is +/// exhausted. +/// +/// See [`.format()`](../trait.Itertools.html#method.format) +/// for more information. +#[derive(Clone)] +pub struct Format<'a, I> { + sep: &'a str, + /// Format uses interior mutability because Display::fmt takes &self. + inner: RefCell>, +} + +pub trait IterFormatExt: Iterator { + fn format(self, separator: &str) -> Format + where + Self: Sized, + { + Format { + sep: separator, + inner: RefCell::new(Some(self)), + } + } +} + +impl IterFormatExt for I where I: Iterator {} + +impl Format<'_, I> +where + I: Iterator, +{ + fn format(&self, f: &mut fmt::Formatter, mut cb: F) -> fmt::Result + where + F: FnMut(&I::Item, &mut fmt::Formatter) -> fmt::Result, + { + let mut iter = match self.inner.borrow_mut().take() { + Some(t) => t, + None => panic!("Format: was already formatted once"), + }; + + if let Some(fst) = iter.next() { + cb(&fst, f)?; + for elt in iter { + if !self.sep.is_empty() { + f.write_str(self.sep)?; + } + cb(&elt, f)?; + } + } + Ok(()) + } +} + +macro_rules! impl_format { + ($($fmt_trait:ident)*) => { + $( + impl<'a, I> fmt::$fmt_trait for Format<'a, I> + where I: Iterator, + I::Item: fmt::$fmt_trait, + { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format(f, fmt::$fmt_trait::fmt) + } + } + )* + } +} + +impl_format!(Debug); diff --git a/vendor/petgraph/src/iter_utils.rs b/vendor/petgraph/src/iter_utils.rs new file mode 100644 index 00000000..587af84c --- /dev/null +++ b/vendor/petgraph/src/iter_utils.rs @@ -0,0 +1,32 @@ +pub trait IterUtilsExt: Iterator { + /// Return the first element that maps to `Some(_)`, or None if the iterator + /// was exhausted. + fn ex_find_map(&mut self, mut f: F) -> Option + where + F: FnMut(Self::Item) -> Option, + { + for elt in self { + if let result @ Some(_) = f(elt) { + return result; + } + } + None + } + + /// Return the last element from the back that maps to `Some(_)`, or + /// None if the iterator was exhausted. + fn ex_rfind_map(&mut self, mut f: F) -> Option + where + F: FnMut(Self::Item) -> Option, + Self: DoubleEndedIterator, + { + while let Some(elt) = self.next_back() { + if let result @ Some(_) = f(elt) { + return result; + } + } + None + } +} + +impl IterUtilsExt for I where I: Iterator {} diff --git a/vendor/petgraph/src/lib.rs b/vendor/petgraph/src/lib.rs new file mode 100644 index 00000000..5b667376 --- /dev/null +++ b/vendor/petgraph/src/lib.rs @@ -0,0 +1,305 @@ +//! `petgraph` is a graph data structure library. +//! +//! Graphs are collections of nodes, and edges between nodes. `petgraph` +//! provides several [graph types](index.html#graph-types) (each differing in the +//! tradeoffs taken in their internal representation), +//! [algorithms](./algo/index.html#functions) on those graphs, and functionality to +//! [output graphs](./dot/struct.Dot.html) in +//! [`graphviz`](https://www.graphviz.org/) format. Both nodes and edges +//! can have arbitrary associated data, and edges may be either directed or undirected. +//! +//! # Example +//! +//! ```rust +//! use petgraph::graph::{NodeIndex, UnGraph}; +//! use petgraph::algo::{dijkstra, min_spanning_tree}; +//! use petgraph::data::FromElements; +//! use petgraph::dot::{Dot, Config}; +//! +//! // Create an undirected graph with `i32` nodes and edges with `()` associated data. +//! let g = UnGraph::::from_edges(&[ +//! (1, 2), (2, 3), (3, 4), +//! (1, 4)]); +//! +//! // Find the shortest path from `1` to `4` using `1` as the cost for every edge. +//! let node_map = dijkstra(&g, 1.into(), Some(4.into()), |_| 1); +//! assert_eq!(&1i32, node_map.get(&NodeIndex::new(4)).unwrap()); +//! +//! // Get the minimum spanning tree of the graph as a new graph, and check that +//! // one edge was trimmed. +//! let mst = UnGraph::<_, _>::from_elements(min_spanning_tree(&g)); +//! assert_eq!(g.raw_edges().len() - 1, mst.raw_edges().len()); +//! +//! // Output the tree to `graphviz` `DOT` format +//! println!("{:?}", Dot::with_config(&mst, &[Config::EdgeNoLabel])); +//! // graph { +//! // 0 [label="\"0\""] +//! // 1 [label="\"0\""] +//! // 2 [label="\"0\""] +//! // 3 [label="\"0\""] +//! // 1 -- 2 +//! // 3 -- 4 +//! // 2 -- 3 +//! // } +//! ``` +//! +//! # Graph types +//! +//! * [`Graph`](./graph/struct.Graph.html) - +//! An adjacency list graph with arbitrary associated data. +//! * [`StableGraph`](./stable_graph/struct.StableGraph.html) - +//! Similar to `Graph`, but it keeps indices stable across removals. +//! * [`GraphMap`](./graphmap/struct.GraphMap.html) - +//! An adjacency list graph backed by a hash table. The node identifiers are the keys +//! into the table. +//! * [`MatrixGraph`](./matrix_graph/struct.MatrixGraph.html) - +//! An adjacency matrix graph. +//! * [`CSR`](./csr/struct.Csr.html) - +//! A sparse adjacency matrix graph with arbitrary associated data. +//! +//! ### Generic parameters +//! +//! Each graph type is generic over a handful of parameters. All graphs share 3 common +//! parameters, `N`, `E`, and `Ty`. This is a broad overview of what those are. Each +//! type's documentation will have finer detail on these parameters. +//! +//! `N` & `E` are called *weights* in this implementation, and are associated with +//! nodes and edges respectively. They can generally be of arbitrary type, and don't have to +//! be what you might conventionally consider weight-like. For example, using `&str` for `N` +//! will work. Many algorithms that require costs let you provide a cost function that +//! translates your `N` and `E` weights into costs appropriate to the algorithm. Some graph +//! types and choices do impose bounds on `N` or `E`. +//! [`min_spanning_tree`](./algo/fn.min_spanning_tree.html) for example requires edge weights that +//! implement [`PartialOrd`](https://doc.rust-lang.org/stable/core/cmp/trait.PartialOrd.html). +//! [`GraphMap`](./graphmap/struct.GraphMap.html) requires node weights that can serve as hash +//! map keys, since that graph type does not create standalone node indices. +//! +//! `Ty` controls whether edges are [`Directed`](./enum.Directed.html) or +//! [`Undirected`](./enum.Undirected.html). +//! +//! `Ix` appears on graph types that use indices. It is exposed so you can control +//! the size of node and edge indices, and therefore the memory footprint of your graphs. +//! Allowed values are `u8`, `u16`, `u32`, and `usize`, with `u32` being the default. +//! +//! ### Shorthand types +//! +//! Each graph type vends a few shorthand type definitions that name some specific +//! generic choices. For example, [`DiGraph<_, _>`](./graph/type.DiGraph.html) is shorthand +//! for [`Graph<_, _, Directed>`](graph/struct.Graph.html). +//! [`UnMatrix<_, _>`](./matrix_graph/type.UnMatrix.html) is shorthand for +//! [`MatrixGraph<_, _, Undirected>`](./matrix_graph/struct.MatrixGraph.html). Each graph type's +//! module documentation lists the available shorthand types. +//! +//! # Crate features +//! +//! * **serde-1** - +//! Defaults off. Enables serialization for ``Graph, StableGraph, GraphMap`` using +//! [`serde 1.0`](https://crates.io/crates/serde). May require a more recent version +//! of Rust than petgraph alone. +//! * **graphmap** - +//! Defaults on. Enables [`GraphMap`](./graphmap/struct.GraphMap.html). +//! * **stable_graph** - +//! Defaults on. Enables [`StableGraph`](./stable_graph/struct.StableGraph.html). +//! * **matrix_graph** - +//! Defaults on. Enables [`MatrixGraph`](./matrix_graph/struct.MatrixGraph.html). +//! +#![doc(html_root_url = "https://docs.rs/petgraph/0.4/")] + +extern crate fixedbitset; +#[cfg(feature = "graphmap")] +extern crate indexmap; + +#[cfg(feature = "serde-1")] +extern crate serde; +#[cfg(feature = "serde-1")] +#[macro_use] +extern crate serde_derive; + +#[cfg(all(feature = "serde-1", test))] +extern crate itertools; + +#[doc(no_inline)] +pub use crate::graph::Graph; + +pub use crate::Direction::{Incoming, Outgoing}; + +#[macro_use] +mod macros; +mod scored; + +// these modules define trait-implementing macros +#[macro_use] +pub mod visit; +#[macro_use] +pub mod data; + +pub mod acyclic; +pub mod adj; +pub mod algo; +pub mod csr; +pub mod dot; +#[cfg(feature = "generate")] +pub mod generate; +pub mod graph6; +mod graph_impl; +#[cfg(feature = "graphmap")] +pub mod graphmap; +mod iter_format; +mod iter_utils; +#[cfg(feature = "matrix_graph")] +pub mod matrix_graph; +#[cfg(feature = "quickcheck")] +mod quickcheck; +#[cfg(feature = "serde-1")] +mod serde_utils; +mod traits_graph; +pub mod unionfind; +mod util; + +pub mod operator; +pub mod prelude; + +/// `Graph` is a graph datastructure using an adjacency list representation. +pub mod graph { + pub use crate::graph_impl::{ + edge_index, node_index, DefaultIx, DiGraph, Edge, EdgeIndex, EdgeIndices, EdgeReference, + EdgeReferences, EdgeWeightsMut, Edges, EdgesConnecting, Externals, Frozen, Graph, + GraphIndex, IndexType, Neighbors, Node, NodeIndex, NodeIndices, NodeReferences, + NodeWeightsMut, UnGraph, WalkNeighbors, + }; +} + +#[cfg(feature = "stable_graph")] +pub use crate::graph_impl::stable_graph; + +// Index into the NodeIndex and EdgeIndex arrays +/// Edge direction. +#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)] +#[repr(usize)] +#[cfg_attr( + feature = "serde-1", + derive(serde_derive::Serialize, serde_derive::Deserialize) +)] +pub enum Direction { + /// An `Outgoing` edge is an outward edge *from* the current node. + Outgoing = 0, + /// An `Incoming` edge is an inbound edge *to* the current node. + Incoming = 1, +} + +impl Direction { + /// Return the opposite `Direction`. + #[inline] + pub fn opposite(self) -> Direction { + match self { + Outgoing => Incoming, + Incoming => Outgoing, + } + } + + /// Return `0` for `Outgoing` and `1` for `Incoming`. + #[inline] + pub fn index(self) -> usize { + (self as usize) & 0x1 + } +} + +#[doc(hidden)] +pub use crate::Direction as EdgeDirection; + +/// Marker type for a directed graph. +#[derive(Clone, Copy, Debug)] +#[cfg_attr( + feature = "serde-1", + derive(serde_derive::Serialize, serde_derive::Deserialize) +)] +pub enum Directed {} + +/// Marker type for an undirected graph. +#[derive(Clone, Copy, Debug)] +#[cfg_attr( + feature = "serde-1", + derive(serde_derive::Serialize, serde_derive::Deserialize) +)] +pub enum Undirected {} + +/// A graph's edge type determines whether it has directed edges or not. +pub trait EdgeType { + fn is_directed() -> bool; +} + +impl EdgeType for Directed { + #[inline] + fn is_directed() -> bool { + true + } +} + +impl EdgeType for Undirected { + #[inline] + fn is_directed() -> bool { + false + } +} + +/// Convert an element like `(i, j)` or `(i, j, w)` into +/// a triple of source, target, edge weight. +/// +/// For `Graph::from_edges` and `GraphMap::from_edges`. +pub trait IntoWeightedEdge { + type NodeId; + fn into_weighted_edge(self) -> (Self::NodeId, Self::NodeId, E); +} + +impl IntoWeightedEdge for (Ix, Ix) +where + E: Default, +{ + type NodeId = Ix; + + fn into_weighted_edge(self) -> (Ix, Ix, E) { + let (s, t) = self; + (s, t, E::default()) + } +} + +impl IntoWeightedEdge for (Ix, Ix, E) { + type NodeId = Ix; + fn into_weighted_edge(self) -> (Ix, Ix, E) { + self + } +} + +impl IntoWeightedEdge for (Ix, Ix, &E) +where + E: Clone, +{ + type NodeId = Ix; + fn into_weighted_edge(self) -> (Ix, Ix, E) { + let (a, b, c) = self; + (a, b, c.clone()) + } +} + +impl IntoWeightedEdge for &(Ix, Ix) +where + Ix: Copy, + E: Default, +{ + type NodeId = Ix; + fn into_weighted_edge(self) -> (Ix, Ix, E) { + let (s, t) = *self; + (s, t, E::default()) + } +} + +impl IntoWeightedEdge for &(Ix, Ix, E) +where + Ix: Copy, + E: Clone, +{ + type NodeId = Ix; + fn into_weighted_edge(self) -> (Ix, Ix, E) { + self.clone() + } +} diff --git a/vendor/petgraph/src/macros.rs b/vendor/petgraph/src/macros.rs new file mode 100644 index 00000000..9ecb9002 --- /dev/null +++ b/vendor/petgraph/src/macros.rs @@ -0,0 +1,108 @@ +macro_rules! clone_fields { + ($name:ident, $($field:ident),+ $(,)*) => ( + fn clone(&self) -> Self { + $name { + $( + $field : self . $field .clone() + ),* + } + } + ); +} + +macro_rules! iterator_wrap { + (impl () for + struct $name: ident <$($typarm:tt),*> where { $($bounds: tt)* } + item: $item: ty, + iter: $iter: ty, + ) => (); + ( + impl (Iterator $($rest:tt)*) for + $(#[$derive:meta])* + struct $name: ident <$($typarm:tt),*> where { $($bounds: tt)* } + item: $item: ty, + iter: $iter: ty, + ) => ( + // having complex iterator types is kind of the point of this macro + #[allow(clippy::type_complexity)] + $(#[$derive])* + pub struct $name <$($typarm),*> where $($bounds)* { + iter: $iter, + } + impl<$($typarm),*> Iterator for $name <$($typarm),*> + where $($bounds)* + { + type Item = $item; + #[inline] + fn next(&mut self) -> Option { + self.iter.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + } + iterator_wrap!( + impl ($($rest)*) for + struct $name <$($typarm),*> where { $($bounds)* } + item: $item, + iter: $iter, + ); + ); + + ( +impl (ExactSizeIterator $($rest:tt)*) for + $(#[$derive:meta])* + struct $name: ident <$($typarm:tt),*> where { $($bounds: tt)* } + item: $item: ty, + iter: $iter: ty, + ) => ( + impl<$($typarm),*> ExactSizeIterator for $name <$($typarm),*> + where $($bounds)* + { + #[inline] + fn len(&self) -> usize { + self.iter.len() + } + } + iterator_wrap!( + impl ($($rest)*) for + $(#[$derive])* + struct $name <$($typarm),*> where { $($bounds)* } + item: $item, + iter: $iter, + ); + ); + + ( +impl (DoubleEndedIterator $($rest:tt)*) for + $(#[$derive:meta])* + struct $name: ident <$($typarm:tt),*> where { $($bounds: tt)* } + item: $item: ty, + iter: $iter: ty, + ) => ( + impl<$($typarm),*> DoubleEndedIterator for $name <$($typarm),*> + where $($bounds)* + { + fn next_back(&mut self) -> Option { + self.iter.next_back() + } + fn rfold(self, accum: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { self.iter.rfold(accum, f) } + fn rfind

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { self.iter.rfind(predicate) } + } + iterator_wrap!( + impl ($($rest)*) for + $(#[$derive])* + struct $name <$($typarm),*> where { $($bounds)* } + item: $item, + iter: $iter, + ); + ); +} diff --git a/vendor/petgraph/src/matrix_graph.rs b/vendor/petgraph/src/matrix_graph.rs new file mode 100644 index 00000000..2ae7c8d0 --- /dev/null +++ b/vendor/petgraph/src/matrix_graph.rs @@ -0,0 +1,1814 @@ +//! `MatrixGraph` is a graph datastructure backed by an adjacency matrix. + +use std::marker::PhantomData; +use std::ops::{Index, IndexMut}; + +use std::cmp; +use std::mem; + +use indexmap::IndexSet; + +use fixedbitset::FixedBitSet; + +use crate::{Directed, Direction, EdgeType, IntoWeightedEdge, Outgoing, Undirected}; + +use crate::graph::NodeIndex as GraphNodeIndex; + +use crate::visit::{ + Data, EdgeCount, GetAdjacencyMatrix, GraphBase, GraphProp, IntoEdgeReferences, IntoEdges, + IntoEdgesDirected, IntoNeighbors, IntoNeighborsDirected, IntoNodeIdentifiers, + IntoNodeReferences, NodeCount, NodeIndexable, Visitable, +}; + +use crate::data::Build; + +pub use crate::graph::IndexType; + +// The following types are used to control the max size of the adjacency matrix. Since the maximum +// size of the matrix vector's is the square of the maximum number of nodes, the number of nodes +// should be reasonably picked. +type DefaultIx = u16; + +/// Node identifier. +pub type NodeIndex = GraphNodeIndex; + +mod private { + pub trait Sealed {} + + impl Sealed for super::NotZero {} + impl Sealed for Option {} +} + +/// Wrapper trait for an `Option`, allowing user-defined structs to be input as containers when +/// defining a null element. +/// +/// Note: this trait is currently *sealed* and cannot be implemented for types outside this crate. +pub trait Nullable: Default + Into::Wrapped>> + private::Sealed { + #[doc(hidden)] + type Wrapped; + + #[doc(hidden)] + fn new(value: Self::Wrapped) -> Self; + + #[doc(hidden)] + fn as_ref(&self) -> Option<&Self::Wrapped>; + + #[doc(hidden)] + fn as_mut(&mut self) -> Option<&mut Self::Wrapped>; + + #[doc(hidden)] + fn is_null(&self) -> bool { + self.as_ref().is_none() + } +} + +impl Nullable for Option { + type Wrapped = T; + + fn new(value: T) -> Self { + Some(value) + } + + fn as_ref(&self) -> Option<&Self::Wrapped> { + self.as_ref() + } + + fn as_mut(&mut self) -> Option<&mut Self::Wrapped> { + self.as_mut() + } +} + +/// `NotZero` is used to optimize the memory usage of edge weights `E` in a +/// [`MatrixGraph`](struct.MatrixGraph.html), replacing the default `Option` sentinel. +/// +/// Pre-requisite: edge weight should implement [`Zero`](trait.Zero.html). +/// +/// Note that if you're already using the standard non-zero types (such as `NonZeroU32`), you don't +/// have to use this wrapper and can leave the default `Null` type argument. +pub struct NotZero(T); + +impl Default for NotZero { + fn default() -> Self { + NotZero(T::zero()) + } +} + +impl Nullable for NotZero { + #[doc(hidden)] + type Wrapped = T; + + #[doc(hidden)] + fn new(value: T) -> Self { + assert!(!value.is_zero()); + NotZero(value) + } + + // implemented here for optimization purposes + #[doc(hidden)] + fn is_null(&self) -> bool { + self.0.is_zero() + } + + #[doc(hidden)] + fn as_ref(&self) -> Option<&Self::Wrapped> { + if !self.is_null() { + Some(&self.0) + } else { + None + } + } + + #[doc(hidden)] + fn as_mut(&mut self) -> Option<&mut Self::Wrapped> { + if !self.is_null() { + Some(&mut self.0) + } else { + None + } + } +} + +impl From> for Option { + fn from(not_zero: NotZero) -> Self { + if !not_zero.is_null() { + Some(not_zero.0) + } else { + None + } + } +} + +/// Base trait for types that can be wrapped in a [`NotZero`](struct.NotZero.html). +/// +/// Implementors must provide a singleton object that will be used to mark empty edges in a +/// [`MatrixGraph`](struct.MatrixGraph.html). +/// +/// Note that this trait is already implemented for the base numeric types. +pub trait Zero { + /// Return the singleton object which can be used as a sentinel value. + fn zero() -> Self; + + /// Return true if `self` is equal to the sentinel value. + fn is_zero(&self) -> bool; +} + +macro_rules! not_zero_impl { + ($t:ty,$z:expr) => { + impl Zero for $t { + fn zero() -> Self { + $z as $t + } + + #[allow(clippy::float_cmp)] + fn is_zero(&self) -> bool { + self == &Self::zero() + } + } + }; +} + +macro_rules! not_zero_impls { + ($($t:ty),*) => { + $( + not_zero_impl!($t, 0); + )* + } +} + +not_zero_impls!(u8, u16, u32, u64, usize); +not_zero_impls!(i8, i16, i32, i64, isize); +not_zero_impls!(f32, f64); + +/// Short version of `NodeIndex::new` (with Ix = `DefaultIx`) +#[inline] +pub fn node_index(ax: usize) -> NodeIndex { + NodeIndex::new(ax) +} + +/// `MatrixGraph` is a graph datastructure using an adjacency matrix +/// representation. +/// +/// `MatrixGraph` is parameterized over: +/// +/// - Associated data `N` for nodes and `E` for edges, called *weights*. +/// The associated data can be of arbitrary type. +/// - Edge type `Ty` that determines whether the graph edges are directed or undirected. +/// - Nullable type `Null`, which denotes the edges' presence (defaults to `Option`). You may +/// specify [`NotZero`](struct.NotZero.html) if you want to use a sentinel value (such as 0) +/// to mark the absence of an edge. +/// - Index type `Ix` that sets the maximum size for the graph (defaults to `DefaultIx`). +/// +/// The graph uses **O(|V^2|)** space, with fast edge insertion & amortized node insertion, as well +/// as efficient graph search and graph algorithms on dense graphs. +/// +/// This graph is backed by a flattened 2D array. For undirected graphs, only the lower triangular +/// matrix is stored. Since the backing array stores edge weights, it is recommended to box large +/// edge weights. +#[derive(Clone)] +pub struct MatrixGraph = Option, Ix = DefaultIx> +{ + node_adjacencies: Vec, + node_capacity: usize, + nodes: IdStorage, + nb_edges: usize, + ty: PhantomData, + ix: PhantomData, +} + +/// A `MatrixGraph` with directed edges. +pub type DiMatrix, Ix = DefaultIx> = MatrixGraph; + +/// A `MatrixGraph` with undirected edges. +pub type UnMatrix, Ix = DefaultIx> = MatrixGraph; + +impl, Ix: IndexType> + MatrixGraph +{ + /// Create a new `MatrixGraph` with estimated capacity for nodes. + pub fn with_capacity(node_capacity: usize) -> Self { + let mut m = Self { + node_adjacencies: vec![], + node_capacity: 0, + nodes: IdStorage::with_capacity(node_capacity), + nb_edges: 0, + ty: PhantomData, + ix: PhantomData, + }; + + debug_assert!(node_capacity <= ::max().index()); + if node_capacity > 0 { + m.extend_capacity_for_node(NodeIndex::new(node_capacity - 1), true); + } + + m + } + + #[inline] + fn to_edge_position(&self, a: NodeIndex, b: NodeIndex) -> Option { + if cmp::max(a.index(), b.index()) >= self.node_capacity { + return None; + } + Some(self.to_edge_position_unchecked(a, b)) + } + + #[inline] + fn to_edge_position_unchecked(&self, a: NodeIndex, b: NodeIndex) -> usize { + to_linearized_matrix_position::(a.index(), b.index(), self.node_capacity) + } + + /// Remove all nodes and edges. + pub fn clear(&mut self) { + for edge in self.node_adjacencies.iter_mut() { + *edge = Default::default(); + } + self.nodes.clear(); + self.nb_edges = 0; + } + + /// Return the number of nodes (vertices) in the graph. + /// + /// Computes in **O(1)** time. + #[inline] + pub fn node_count(&self) -> usize { + self.nodes.len() + } + + /// Return the number of edges in the graph. + /// + /// Computes in **O(1)** time. + #[inline] + pub fn edge_count(&self) -> usize { + self.nb_edges + } + + /// Return whether the graph has directed edges or not. + #[inline] + pub fn is_directed(&self) -> bool { + Ty::is_directed() + } + + /// Add a node (also called vertex) with associated data `weight` to the graph. + /// + /// Computes in **O(1)** time. + /// + /// Return the index of the new node. + /// + /// **Panics** if the MatrixGraph is at the maximum number of nodes for its index type. + pub fn add_node(&mut self, weight: N) -> NodeIndex { + NodeIndex::new(self.nodes.add(weight)) + } + + /// Remove `a` from the graph. + /// + /// Computes in **O(V)** time, due to the removal of edges with other nodes. + /// + /// **Panics** if the node `a` does not exist. + pub fn remove_node(&mut self, a: NodeIndex) -> N { + for id in self.nodes.iter_ids() { + let position = self.to_edge_position(a, NodeIndex::new(id)); + if let Some(pos) = position { + self.node_adjacencies[pos] = Default::default(); + } + + if Ty::is_directed() { + let position = self.to_edge_position(NodeIndex::new(id), a); + if let Some(pos) = position { + self.node_adjacencies[pos] = Default::default(); + } + } + } + + self.nodes.remove(a.index()) + } + + #[inline] + fn extend_capacity_for_node(&mut self, min_node: NodeIndex, exact: bool) { + self.node_capacity = extend_linearized_matrix::( + &mut self.node_adjacencies, + self.node_capacity, + min_node.index() + 1, + exact, + ); + } + + #[inline] + fn extend_capacity_for_edge(&mut self, a: NodeIndex, b: NodeIndex) { + let min_node = cmp::max(a, b); + if min_node.index() >= self.node_capacity { + self.extend_capacity_for_node(min_node, false); + } + } + + /// Update the edge from `a` to `b` to the graph, with its associated data `weight`. + /// + /// Return the previous data, if any. + /// + /// Computes in **O(1)** time, best case. + /// Computes in **O(|V|^2)** time, worst case (matrix needs to be re-allocated). + /// + /// **Panics** if any of the nodes don't exist. + pub fn update_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> Option { + self.extend_capacity_for_edge(a, b); + let p = self.to_edge_position_unchecked(a, b); + let old_weight = mem::replace(&mut self.node_adjacencies[p], Null::new(weight)); + if old_weight.is_null() { + self.nb_edges += 1; + } + old_weight.into() + } + + /// Add an edge from `a` to `b` to the graph, with its associated + /// data `weight`. + /// + /// Computes in **O(1)** time, best case. + /// Computes in **O(|V|^2)** time, worst case (matrix needs to be re-allocated). + /// + /// **Panics** if any of the nodes don't exist. + /// **Panics** if an edge already exists from `a` to `b`. + /// + /// **Note:** `MatrixGraph` does not allow adding parallel (“duplicate”) edges. If you want to avoid + /// this, use [`.update_edge(a, b, weight)`](#method.update_edge) instead. + pub fn add_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) { + let old_edge_id = self.update_edge(a, b, weight); + assert!(old_edge_id.is_none()); + } + + /// Remove the edge from `a` to `b` to the graph. + /// + /// **Panics** if any of the nodes don't exist. + /// **Panics** if no edge exists between `a` and `b`. + pub fn remove_edge(&mut self, a: NodeIndex, b: NodeIndex) -> E { + let p = self + .to_edge_position(a, b) + .expect("No edge found between the nodes."); + let old_weight = mem::take(&mut self.node_adjacencies[p]).into().unwrap(); + let old_weight: Option<_> = old_weight.into(); + self.nb_edges -= 1; + old_weight.unwrap() + } + + /// Return true if there is an edge between `a` and `b`. + /// + /// **Panics** if any of the nodes don't exist. + pub fn has_edge(&self, a: NodeIndex, b: NodeIndex) -> bool { + if let Some(p) = self.to_edge_position(a, b) { + return !self.node_adjacencies[p].is_null(); + } + false + } + + /// Access the weight for node `a`. + /// + /// Also available with indexing syntax: `&graph[a]`. + /// + /// **Panics** if the node doesn't exist. + pub fn node_weight(&self, a: NodeIndex) -> &N { + &self.nodes[a.index()] + } + + /// Access the weight for node `a`, mutably. + /// + /// Also available with indexing syntax: `&mut graph[a]`. + /// + /// **Panics** if the node doesn't exist. + pub fn node_weight_mut(&mut self, a: NodeIndex) -> &mut N { + &mut self.nodes[a.index()] + } + + /// Access the weight for edge `e`. + /// + /// Also available with indexing syntax: `&graph[e]`. + /// + /// **Panics** if no edge exists between `a` and `b`. + pub fn edge_weight(&self, a: NodeIndex, b: NodeIndex) -> &E { + let p = self + .to_edge_position(a, b) + .expect("No edge found between the nodes."); + self.node_adjacencies[p] + .as_ref() + .expect("No edge found between the nodes.") + } + + /// Access the weight for edge `e`, mutably. + /// + /// Also available with indexing syntax: `&mut graph[e]`. + /// + /// **Panics** if no edge exists between `a` and `b`. + pub fn edge_weight_mut(&mut self, a: NodeIndex, b: NodeIndex) -> &mut E { + let p = self + .to_edge_position(a, b) + .expect("No edge found between the nodes."); + self.node_adjacencies[p] + .as_mut() + .expect("No edge found between the nodes.") + } + + /// Return an iterator of all nodes with an edge starting from `a`. + /// + /// - `Directed`: Outgoing edges from `a`. + /// - `Undirected`: All edges from or to `a`. + /// + /// Produces an empty iterator if the node doesn't exist.
+ /// Iterator element type is [`NodeIndex`](../graph/struct.NodeIndex.html). + pub fn neighbors(&self, a: NodeIndex) -> Neighbors { + Neighbors(Edges::on_columns( + a.index(), + &self.node_adjacencies, + self.node_capacity, + )) + } + + /// Return an iterator of all edges of `a`. + /// + /// - `Directed`: Outgoing edges from `a`. + /// - `Undirected`: All edges connected to `a`. + /// + /// Produces an empty iterator if the node doesn't exist.
+ /// Iterator element type is `(NodeIndex, NodeIndex, &E)`. + pub fn edges(&self, a: NodeIndex) -> Edges { + Edges::on_columns(a.index(), &self.node_adjacencies, self.node_capacity) + } + + /// Create a new `MatrixGraph` from an iterable of edges. + /// + /// Node weights `N` are set to default values. + /// Edge weights `E` may either be specified in the list, + /// or they are filled with default values. + /// + /// Nodes are inserted automatically to match the edges. + /// + /// ``` + /// use petgraph::matrix_graph::MatrixGraph; + /// + /// let gr = MatrixGraph::<(), i32>::from_edges(&[ + /// (0, 1), (0, 2), (0, 3), + /// (1, 2), (1, 3), + /// (2, 3), + /// ]); + /// ``` + pub fn from_edges(iterable: I) -> Self + where + I: IntoIterator, + I::Item: IntoWeightedEdge, + >::NodeId: Into>, + N: Default, + { + let mut g = Self::default(); + g.extend_with_edges(iterable); + g + } + + /// Extend the graph from an iterable of edges. + /// + /// Node weights `N` are set to default values. + /// Edge weights `E` may either be specified in the list, + /// or they are filled with default values. + /// + /// Nodes are inserted automatically to match the edges. + pub fn extend_with_edges(&mut self, iterable: I) + where + I: IntoIterator, + I::Item: IntoWeightedEdge, + >::NodeId: Into>, + N: Default, + { + for elt in iterable { + let (source, target, weight) = elt.into_weighted_edge(); + let (source, target) = (source.into(), target.into()); + let nx = cmp::max(source, target); + while nx.index() >= self.node_count() { + self.add_node(N::default()); + } + self.add_edge(source, target, weight); + } + } +} + +impl, Ix: IndexType> MatrixGraph { + /// Return an iterator of all neighbors that have an edge between them and + /// `a`, in the specified direction. + /// If the graph's edges are undirected, this is equivalent to *.neighbors(a)*. + /// + /// - `Outgoing`: All edges from `a`. + /// - `Incoming`: All edges to `a`. + /// + /// Produces an empty iterator if the node doesn't exist.
+ /// Iterator element type is [`NodeIndex`](../graph/struct.NodeIndex.html). + pub fn neighbors_directed( + &self, + a: NodeIndex, + d: Direction, + ) -> Neighbors { + if d == Outgoing { + self.neighbors(a) + } else { + Neighbors(Edges::on_rows( + a.index(), + &self.node_adjacencies, + self.node_capacity, + )) + } + } + + /// Return an iterator of all edges of `a`, in the specified direction. + /// + /// - `Outgoing`: All edges from `a`. + /// - `Incoming`: All edges to `a`. + /// + /// Produces an empty iterator if the node `a` doesn't exist.
+ /// Iterator element type is `(NodeIndex, NodeIndex, &E)`. + pub fn edges_directed(&self, a: NodeIndex, d: Direction) -> Edges { + if d == Outgoing { + self.edges(a) + } else { + Edges::on_rows(a.index(), &self.node_adjacencies, self.node_capacity) + } + } +} + +/// Iterator over the node identifiers of a graph. +/// +/// Created from a call to [`.node_identifiers()`][1] on a [`MatrixGraph`][2]. +/// +/// [1]: ../visit/trait.IntoNodeIdentifiers.html#tymethod.node_identifiers +/// [2]: struct.MatrixGraph.html +#[derive(Debug, Clone)] +pub struct NodeIdentifiers<'a, Ix> { + iter: IdIterator<'a>, + ix: PhantomData, +} + +impl<'a, Ix: IndexType> NodeIdentifiers<'a, Ix> { + fn new(iter: IdIterator<'a>) -> Self { + Self { + iter, + ix: PhantomData, + } + } +} + +impl Iterator for NodeIdentifiers<'_, Ix> { + type Item = NodeIndex; + + fn next(&mut self) -> Option { + self.iter.next().map(NodeIndex::new) + } + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +/// Iterator over all nodes of a graph. +/// +/// Created from a call to [`.node_references()`][1] on a [`MatrixGraph`][2]. +/// +/// [1]: ../visit/trait.IntoNodeReferences.html#tymethod.node_references +/// [2]: struct.MatrixGraph.html +#[derive(Debug, Clone)] +pub struct NodeReferences<'a, N: 'a, Ix> { + nodes: &'a IdStorage, + iter: IdIterator<'a>, + ix: PhantomData, +} + +impl<'a, N: 'a, Ix> NodeReferences<'a, N, Ix> { + fn new(nodes: &'a IdStorage) -> Self { + NodeReferences { + nodes, + iter: nodes.iter_ids(), + ix: PhantomData, + } + } +} + +impl<'a, N: 'a, Ix: IndexType> Iterator for NodeReferences<'a, N, Ix> { + type Item = (NodeIndex, &'a N); + + fn next(&mut self) -> Option { + self.iter + .next() + .map(|i| (NodeIndex::new(i), &self.nodes[i])) + } + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +/// Iterator over all edges of a graph. +/// +/// Created from a call to [`.edge_references()`][1] on a [`MatrixGraph`][2]. +/// +/// [1]: ../visit/trait.IntoEdgeReferences.html#tymethod.edge_references +/// [2]: struct.MatrixGraph.html +#[derive(Debug, Clone)] +pub struct EdgeReferences<'a, Ty: EdgeType, Null: 'a + Nullable, Ix> { + row: usize, + column: usize, + node_adjacencies: &'a [Null], + node_capacity: usize, + ty: PhantomData, + ix: PhantomData, +} + +impl<'a, Ty: EdgeType, Null: 'a + Nullable, Ix> EdgeReferences<'a, Ty, Null, Ix> { + fn new(node_adjacencies: &'a [Null], node_capacity: usize) -> Self { + EdgeReferences { + row: 0, + column: 0, + node_adjacencies, + node_capacity, + ty: PhantomData, + ix: PhantomData, + } + } +} + +impl<'a, Ty: EdgeType, Null: Nullable, Ix: IndexType> Iterator + for EdgeReferences<'a, Ty, Null, Ix> +{ + type Item = (NodeIndex, NodeIndex, &'a Null::Wrapped); + + fn next(&mut self) -> Option { + loop { + let (row, column) = (self.row, self.column); + if row >= self.node_capacity { + return None; + } + + // By default, advance the column. Reset and advance the row if the column overflows. + // + // Note that for undirected graphs, we don't want to yield the same edge twice, + // therefore the maximum column length should be the index new after the row index. + self.column += 1; + let max_column_len = if !Ty::is_directed() { + row + 1 + } else { + self.node_capacity + }; + if self.column >= max_column_len { + self.column = 0; + self.row += 1; + } + + let p = to_linearized_matrix_position::(row, column, self.node_capacity); + if let Some(e) = self.node_adjacencies[p].as_ref() { + return Some((NodeIndex::new(row), NodeIndex::new(column), e)); + } + } + } +} + +/// Iterator over the neighbors of a node. +/// +/// Iterator element type is `NodeIndex`. +/// +/// Created with [`.neighbors()`][1], [`.neighbors_directed()`][2]. +/// +/// [1]: struct.MatrixGraph.html#method.neighbors +/// [2]: struct.MatrixGraph.html#method.neighbors_directed +#[derive(Debug, Clone)] +pub struct Neighbors<'a, Ty: EdgeType, Null: 'a + Nullable, Ix>(Edges<'a, Ty, Null, Ix>); + +impl Iterator for Neighbors<'_, Ty, Null, Ix> { + type Item = NodeIndex; + + fn next(&mut self) -> Option { + self.0.next().map(|(_, b, _)| b) + } + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum NeighborIterDirection { + Rows, + Columns, +} + +/// Iterator over the edges of from or to a node +/// +/// Created with [`.edges()`][1], [`.edges_directed()`][2]. +/// +/// [1]: struct.MatrixGraph.html#method.edges +/// [2]: struct.MatrixGraph.html#method.edges_directed +#[derive(Debug, Clone)] +pub struct Edges<'a, Ty: EdgeType, Null: 'a + Nullable, Ix> { + iter_direction: NeighborIterDirection, + node_adjacencies: &'a [Null], + node_capacity: usize, + row: usize, + column: usize, + ty: PhantomData, + ix: PhantomData, +} + +impl<'a, Ty: EdgeType, Null: 'a + Nullable, Ix> Edges<'a, Ty, Null, Ix> { + fn on_columns(row: usize, node_adjacencies: &'a [Null], node_capacity: usize) -> Self { + Edges { + iter_direction: NeighborIterDirection::Columns, + node_adjacencies, + node_capacity, + row, + column: 0, + ty: PhantomData, + ix: PhantomData, + } + } + + fn on_rows(column: usize, node_adjacencies: &'a [Null], node_capacity: usize) -> Self { + Edges { + iter_direction: NeighborIterDirection::Rows, + node_adjacencies, + node_capacity, + row: 0, + column, + ty: PhantomData, + ix: PhantomData, + } + } +} + +impl<'a, Ty: EdgeType, Null: Nullable, Ix: IndexType> Iterator for Edges<'a, Ty, Null, Ix> { + type Item = (NodeIndex, NodeIndex, &'a Null::Wrapped); + + fn next(&mut self) -> Option { + use self::NeighborIterDirection::*; + + loop { + let (row, column) = (self.row, self.column); + if row >= self.node_capacity || column >= self.node_capacity { + return None; + } + + match self.iter_direction { + Rows => self.row += 1, + Columns => self.column += 1, + } + + let p = to_linearized_matrix_position::(row, column, self.node_capacity); + if let Some(e) = self.node_adjacencies[p].as_ref() { + let (a, b) = match self.iter_direction { + Rows => (column, row), + Columns => (row, column), + }; + + return Some((NodeIndex::new(a), NodeIndex::new(b), e)); + } + } + } +} + +#[inline] +fn to_linearized_matrix_position(row: usize, column: usize, width: usize) -> usize { + if Ty::is_directed() { + to_flat_square_matrix_position(row, column, width) + } else { + to_lower_triangular_matrix_position(row, column) + } +} + +#[inline] +fn extend_linearized_matrix( + node_adjacencies: &mut Vec, + old_node_capacity: usize, + new_capacity: usize, + exact: bool, +) -> usize { + if old_node_capacity >= new_capacity { + return old_node_capacity; + } + if Ty::is_directed() { + extend_flat_square_matrix(node_adjacencies, old_node_capacity, new_capacity, exact) + } else { + extend_lower_triangular_matrix(node_adjacencies, new_capacity) + } +} + +#[inline] +fn to_flat_square_matrix_position(row: usize, column: usize, width: usize) -> usize { + row * width + column +} + +#[inline] +fn extend_flat_square_matrix( + node_adjacencies: &mut Vec, + old_node_capacity: usize, + new_node_capacity: usize, + exact: bool, +) -> usize { + // Grow the capacity by exponential steps to avoid repeated allocations. + // Disabled for the with_capacity constructor. + let new_node_capacity = if exact { + new_node_capacity + } else { + const MIN_CAPACITY: usize = 4; + cmp::max(new_node_capacity.next_power_of_two(), MIN_CAPACITY) + }; + + // Optimization: when resizing the matrix this way we skip the first few grows to make + // small matrices a bit faster to work with. + + ensure_len(node_adjacencies, new_node_capacity.pow(2)); + for c in (1..old_node_capacity).rev() { + let pos = c * old_node_capacity; + let new_pos = c * new_node_capacity; + // Move the slices directly if they do not overlap with their new position + if pos + old_node_capacity <= new_pos { + debug_assert!(pos + old_node_capacity < node_adjacencies.len()); + debug_assert!(new_pos + old_node_capacity < node_adjacencies.len()); + let ptr = node_adjacencies.as_mut_ptr(); + // SAFETY: pos + old_node_capacity <= new_pos, so this won't overlap + unsafe { + let old = ptr.add(pos); + let new = ptr.add(new_pos); + core::ptr::swap_nonoverlapping(old, new, old_node_capacity); + } + } else { + for i in (0..old_node_capacity).rev() { + node_adjacencies.as_mut_slice().swap(pos + i, new_pos + i); + } + } + } + + new_node_capacity +} + +#[inline] +fn to_lower_triangular_matrix_position(row: usize, column: usize) -> usize { + let (row, column) = if row > column { + (row, column) + } else { + (column, row) + }; + (row * (row + 1)) / 2 + column +} + +#[inline] +fn extend_lower_triangular_matrix( + node_adjacencies: &mut Vec, + new_capacity: usize, +) -> usize { + let max_node = new_capacity - 1; + let max_pos = to_lower_triangular_matrix_position(max_node, max_node); + ensure_len(node_adjacencies, max_pos + 1); + new_capacity +} + +/// Grow a Vec by appending the type's default value until the `size` is reached. +fn ensure_len(v: &mut Vec, size: usize) { + v.resize_with(size, T::default); +} + +#[derive(Debug, Clone)] +struct IdStorage { + elements: Vec>, + upper_bound: usize, + removed_ids: IndexSet, +} + +impl IdStorage { + fn with_capacity(capacity: usize) -> Self { + IdStorage { + elements: Vec::with_capacity(capacity), + upper_bound: 0, + removed_ids: IndexSet::new(), + } + } + + fn add(&mut self, element: T) -> usize { + let id = if let Some(id) = self.removed_ids.pop() { + id + } else { + let id = self.upper_bound; + self.upper_bound += 1; + + ensure_len(&mut self.elements, id + 1); + + id + }; + + self.elements[id] = Some(element); + + id + } + + fn remove(&mut self, id: usize) -> T { + let data = self.elements[id].take().unwrap(); + if self.upper_bound - id == 1 { + self.upper_bound -= 1; + } else { + self.removed_ids.insert(id); + } + data + } + + fn clear(&mut self) { + self.upper_bound = 0; + self.elements.clear(); + self.removed_ids.clear(); + } + + #[inline] + fn len(&self) -> usize { + self.upper_bound - self.removed_ids.len() + } + + fn iter_ids(&self) -> IdIterator { + IdIterator { + upper_bound: self.upper_bound, + removed_ids: &self.removed_ids, + current: None, + } + } +} + +impl Index for IdStorage { + type Output = T; + fn index(&self, index: usize) -> &T { + self.elements[index].as_ref().unwrap() + } +} + +impl IndexMut for IdStorage { + fn index_mut(&mut self, index: usize) -> &mut T { + self.elements[index].as_mut().unwrap() + } +} + +#[derive(Debug, Clone)] +struct IdIterator<'a> { + upper_bound: usize, + removed_ids: &'a IndexSet, + current: Option, +} + +impl Iterator for IdIterator<'_> { + type Item = usize; + + fn next(&mut self) -> Option { + // initialize / advance + let current = { + if self.current.is_none() { + self.current = Some(0); + self.current.as_mut().unwrap() + } else { + let current = self.current.as_mut().unwrap(); + *current += 1; + current + } + }; + + // skip removed ids + while self.removed_ids.contains(current) && *current < self.upper_bound { + *current += 1; + } + + if *current < self.upper_bound { + Some(*current) + } else { + None + } + } +} + +/// Create a new empty `MatrixGraph`. +impl, Ix: IndexType> Default + for MatrixGraph +{ + fn default() -> Self { + Self::with_capacity(0) + } +} + +impl MatrixGraph { + /// Create a new `MatrixGraph` with directed edges. + /// + /// This is a convenience method. Use `MatrixGraph::with_capacity` or `MatrixGraph::default` for + /// a constructor that is generic in all the type parameters of `MatrixGraph`. + pub fn new() -> Self { + MatrixGraph::default() + } +} + +impl MatrixGraph { + /// Create a new `MatrixGraph` with undirected edges. + /// + /// This is a convenience method. Use `MatrixGraph::with_capacity` or `MatrixGraph::default` for + /// a constructor that is generic in all the type parameters of `MatrixGraph`. + pub fn new_undirected() -> Self { + MatrixGraph::default() + } +} + +/// Index the `MatrixGraph` by `NodeIndex` to access node weights. +/// +/// **Panics** if the node doesn't exist. +impl, Ix: IndexType> Index> + for MatrixGraph +{ + type Output = N; + + fn index(&self, ax: NodeIndex) -> &N { + self.node_weight(ax) + } +} + +/// Index the `MatrixGraph` by `NodeIndex` to access node weights. +/// +/// **Panics** if the node doesn't exist. +impl, Ix: IndexType> IndexMut> + for MatrixGraph +{ + fn index_mut(&mut self, ax: NodeIndex) -> &mut N { + self.node_weight_mut(ax) + } +} + +impl, Ix: IndexType> NodeCount + for MatrixGraph +{ + fn node_count(&self) -> usize { + MatrixGraph::node_count(self) + } +} + +impl, Ix: IndexType> EdgeCount + for MatrixGraph +{ + #[inline] + fn edge_count(&self) -> usize { + self.edge_count() + } +} + +/// Index the `MatrixGraph` by `NodeIndex` pair to access edge weights. +/// +/// Also available with indexing syntax: `&graph[e]`. +/// +/// **Panics** if no edge exists between `a` and `b`. +impl, Ix: IndexType> + Index<(NodeIndex, NodeIndex)> for MatrixGraph +{ + type Output = E; + + fn index(&self, (ax, bx): (NodeIndex, NodeIndex)) -> &E { + self.edge_weight(ax, bx) + } +} + +/// Index the `MatrixGraph` by `NodeIndex` pair to access edge weights. +/// +/// Also available with indexing syntax: `&mut graph[e]`. +/// +/// **Panics** if no edge exists between `a` and `b`. +impl, Ix: IndexType> + IndexMut<(NodeIndex, NodeIndex)> for MatrixGraph +{ + fn index_mut(&mut self, (ax, bx): (NodeIndex, NodeIndex)) -> &mut E { + self.edge_weight_mut(ax, bx) + } +} + +impl, Ix: IndexType> GetAdjacencyMatrix + for MatrixGraph +{ + type AdjMatrix = (); + + fn adjacency_matrix(&self) -> Self::AdjMatrix {} + + fn is_adjacent(&self, _: &Self::AdjMatrix, a: NodeIndex, b: NodeIndex) -> bool { + MatrixGraph::has_edge(self, a, b) + } +} + +impl, Ix: IndexType> Visitable + for MatrixGraph +{ + type Map = FixedBitSet; + + fn visit_map(&self) -> FixedBitSet { + FixedBitSet::with_capacity(self.node_bound()) + } + + fn reset_map(&self, map: &mut Self::Map) { + map.clear(); + map.grow(self.node_bound()); + } +} + +impl, Ix: IndexType> GraphBase + for MatrixGraph +{ + type NodeId = NodeIndex; + type EdgeId = (NodeIndex, NodeIndex); +} + +impl, Ix: IndexType> GraphProp + for MatrixGraph +{ + type EdgeType = Ty; +} + +impl, Ix: IndexType> Data + for MatrixGraph +{ + type NodeWeight = N; + type EdgeWeight = E; +} + +impl<'a, N, E: 'a, Ty: EdgeType, Null: Nullable, Ix: IndexType> IntoNodeIdentifiers + for &'a MatrixGraph +{ + type NodeIdentifiers = NodeIdentifiers<'a, Ix>; + + fn node_identifiers(self) -> Self::NodeIdentifiers { + NodeIdentifiers::new(self.nodes.iter_ids()) + } +} + +impl<'a, N, E: 'a, Ty: EdgeType, Null: Nullable, Ix: IndexType> IntoNeighbors + for &'a MatrixGraph +{ + type Neighbors = Neighbors<'a, Ty, Null, Ix>; + + fn neighbors(self, a: NodeIndex) -> Self::Neighbors { + MatrixGraph::neighbors(self, a) + } +} + +impl<'a, N, E: 'a, Null: Nullable, Ix: IndexType> IntoNeighborsDirected + for &'a MatrixGraph +{ + type NeighborsDirected = Neighbors<'a, Directed, Null, Ix>; + + fn neighbors_directed(self, a: NodeIndex, d: Direction) -> Self::NeighborsDirected { + MatrixGraph::neighbors_directed(self, a, d) + } +} + +impl<'a, N, E, Ty: EdgeType, Null: Nullable, Ix: IndexType> IntoNodeReferences + for &'a MatrixGraph +{ + type NodeRef = (NodeIndex, &'a N); + type NodeReferences = NodeReferences<'a, N, Ix>; + fn node_references(self) -> Self::NodeReferences { + NodeReferences::new(&self.nodes) + } +} + +impl<'a, N, E, Ty: EdgeType, Null: Nullable, Ix: IndexType> IntoEdgeReferences + for &'a MatrixGraph +{ + type EdgeRef = (NodeIndex, NodeIndex, &'a E); + type EdgeReferences = EdgeReferences<'a, Ty, Null, Ix>; + fn edge_references(self) -> Self::EdgeReferences { + EdgeReferences::new(&self.node_adjacencies, self.node_capacity) + } +} + +impl<'a, N, E, Ty: EdgeType, Null: Nullable, Ix: IndexType> IntoEdges + for &'a MatrixGraph +{ + type Edges = Edges<'a, Ty, Null, Ix>; + fn edges(self, a: Self::NodeId) -> Self::Edges { + MatrixGraph::edges(self, a) + } +} + +impl<'a, N, E, Null: Nullable, Ix: IndexType> IntoEdgesDirected + for &'a MatrixGraph +{ + type EdgesDirected = Edges<'a, Directed, Null, Ix>; + + fn edges_directed(self, a: Self::NodeId, dir: Direction) -> Self::EdgesDirected { + MatrixGraph::edges_directed(self, a, dir) + } +} + +impl, Ix: IndexType> NodeIndexable + for MatrixGraph +{ + fn node_bound(&self) -> usize { + self.nodes.upper_bound + } + + fn to_index(&self, ix: NodeIndex) -> usize { + ix.index() + } + + fn from_index(&self, ix: usize) -> Self::NodeId { + NodeIndex::new(ix) + } +} + +impl, Ix: IndexType> Build + for MatrixGraph +{ + fn add_node(&mut self, weight: Self::NodeWeight) -> Self::NodeId { + self.add_node(weight) + } + + fn add_edge( + &mut self, + a: Self::NodeId, + b: Self::NodeId, + weight: Self::EdgeWeight, + ) -> Option { + if !self.has_edge(a, b) { + MatrixGraph::update_edge(self, a, b, weight); + Some((a, b)) + } else { + None + } + } + + fn update_edge( + &mut self, + a: Self::NodeId, + b: Self::NodeId, + weight: Self::EdgeWeight, + ) -> Self::EdgeId { + MatrixGraph::update_edge(self, a, b, weight); + (a, b) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{Incoming, Outgoing}; + + #[test] + fn test_new() { + let g = MatrixGraph::::new(); + assert_eq!(g.node_count(), 0); + assert_eq!(g.edge_count(), 0); + } + + #[test] + fn test_default() { + let g = MatrixGraph::::default(); + assert_eq!(g.node_count(), 0); + assert_eq!(g.edge_count(), 0); + } + + #[test] + fn test_with_capacity() { + let g = MatrixGraph::::with_capacity(10); + assert_eq!(g.node_count(), 0); + assert_eq!(g.edge_count(), 0); + } + + #[test] + fn test_node_indexing() { + let mut g: MatrixGraph = MatrixGraph::new(); + let a = g.add_node('a'); + let b = g.add_node('b'); + assert_eq!(g.node_count(), 2); + assert_eq!(g.edge_count(), 0); + assert_eq!(g[a], 'a'); + assert_eq!(g[b], 'b'); + } + + #[test] + fn test_remove_node() { + let mut g: MatrixGraph = MatrixGraph::new(); + let a = g.add_node('a'); + + g.remove_node(a); + + assert_eq!(g.node_count(), 0); + assert_eq!(g.edge_count(), 0); + } + + #[test] + fn test_add_edge() { + let mut g = MatrixGraph::new(); + let a = g.add_node('a'); + let b = g.add_node('b'); + let c = g.add_node('c'); + g.add_edge(a, b, ()); + g.add_edge(b, c, ()); + assert_eq!(g.node_count(), 3); + assert_eq!(g.edge_count(), 2); + } + + #[test] + /// Adds an edge that triggers a second extension of the matrix. + /// From #425 + fn test_add_edge_with_extension() { + let mut g = DiMatrix::::new(); + let _n0 = g.add_node(0); + let n1 = g.add_node(1); + let n2 = g.add_node(2); + let n3 = g.add_node(3); + let n4 = g.add_node(4); + let _n5 = g.add_node(5); + g.add_edge(n2, n1, ()); + g.add_edge(n2, n3, ()); + g.add_edge(n2, n4, ()); + assert_eq!(g.node_count(), 6); + assert_eq!(g.edge_count(), 3); + assert!(g.has_edge(n2, n1)); + assert!(g.has_edge(n2, n3)); + assert!(g.has_edge(n2, n4)); + } + + #[test] + fn test_matrix_resize() { + let mut g = DiMatrix::::with_capacity(3); + let n0 = g.add_node(0); + let n1 = g.add_node(1); + let n2 = g.add_node(2); + let n3 = g.add_node(3); + g.add_edge(n1, n0, ()); + g.add_edge(n1, n1, ()); + // Triggers a resize from capacity 3 to 4 + g.add_edge(n2, n3, ()); + assert_eq!(g.node_count(), 4); + assert_eq!(g.edge_count(), 3); + assert!(g.has_edge(n1, n0)); + assert!(g.has_edge(n1, n1)); + assert!(g.has_edge(n2, n3)); + } + + #[test] + fn test_add_edge_with_weights() { + let mut g = MatrixGraph::new(); + let a = g.add_node('a'); + let b = g.add_node('b'); + let c = g.add_node('c'); + g.add_edge(a, b, true); + g.add_edge(b, c, false); + assert!(*g.edge_weight(a, b)); + assert!(!*g.edge_weight(b, c)); + } + + #[test] + fn test_add_edge_with_weights_undirected() { + let mut g = MatrixGraph::new_undirected(); + let a = g.add_node('a'); + let b = g.add_node('b'); + let c = g.add_node('c'); + let d = g.add_node('d'); + g.add_edge(a, b, "ab"); + g.add_edge(a, a, "aa"); + g.add_edge(b, c, "bc"); + g.add_edge(d, d, "dd"); + assert_eq!(*g.edge_weight(a, b), "ab"); + assert_eq!(*g.edge_weight(b, c), "bc"); + } + + /// Shorthand for `.collect::>()` + trait IntoVec { + fn into_vec(self) -> Vec; + } + + impl IntoVec for It + where + It: Iterator, + { + fn into_vec(self) -> Vec { + self.collect() + } + } + + #[test] + fn test_clear() { + let mut g = MatrixGraph::new(); + let a = g.add_node('a'); + let b = g.add_node('b'); + let c = g.add_node('c'); + assert_eq!(g.node_count(), 3); + + g.add_edge(a, b, ()); + g.add_edge(b, c, ()); + g.add_edge(c, a, ()); + assert_eq!(g.edge_count(), 3); + + g.clear(); + + assert_eq!(g.node_count(), 0); + assert_eq!(g.edge_count(), 0); + + let a = g.add_node('a'); + let b = g.add_node('b'); + let c = g.add_node('c'); + assert_eq!(g.node_count(), 3); + assert_eq!(g.edge_count(), 0); + + assert_eq!(g.neighbors_directed(a, Incoming).into_vec(), vec![]); + assert_eq!(g.neighbors_directed(b, Incoming).into_vec(), vec![]); + assert_eq!(g.neighbors_directed(c, Incoming).into_vec(), vec![]); + + assert_eq!(g.neighbors_directed(a, Outgoing).into_vec(), vec![]); + assert_eq!(g.neighbors_directed(b, Outgoing).into_vec(), vec![]); + assert_eq!(g.neighbors_directed(c, Outgoing).into_vec(), vec![]); + } + + #[test] + fn test_clear_undirected() { + let mut g = MatrixGraph::new_undirected(); + let a = g.add_node('a'); + let b = g.add_node('b'); + let c = g.add_node('c'); + assert_eq!(g.node_count(), 3); + + g.add_edge(a, b, ()); + g.add_edge(b, c, ()); + g.add_edge(c, a, ()); + assert_eq!(g.edge_count(), 3); + + g.clear(); + + assert_eq!(g.node_count(), 0); + assert_eq!(g.edge_count(), 0); + + let a = g.add_node('a'); + let b = g.add_node('b'); + let c = g.add_node('c'); + assert_eq!(g.node_count(), 3); + assert_eq!(g.edge_count(), 0); + + assert_eq!(g.neighbors(a).into_vec(), vec![]); + assert_eq!(g.neighbors(b).into_vec(), vec![]); + assert_eq!(g.neighbors(c).into_vec(), vec![]); + } + + /// Helper trait for always sorting before testing. + trait IntoSortedVec { + fn into_sorted_vec(self) -> Vec; + } + + impl IntoSortedVec for It + where + It: Iterator, + T: Ord, + { + fn into_sorted_vec(self) -> Vec { + let mut v: Vec = self.collect(); + v.sort(); + v + } + } + + /// Helper macro for always sorting before testing. + macro_rules! sorted_vec { + ($($x:expr),*) => { + { + let mut v = vec![$($x,)*]; + v.sort(); + v + } + } + } + + #[test] + fn test_neighbors() { + let mut g = MatrixGraph::new(); + let a = g.add_node('a'); + let b = g.add_node('b'); + let c = g.add_node('c'); + g.add_edge(a, b, ()); + g.add_edge(a, c, ()); + + let a_neighbors = g.neighbors(a).into_sorted_vec(); + assert_eq!(a_neighbors, sorted_vec![b, c]); + + let b_neighbors = g.neighbors(b).into_sorted_vec(); + assert_eq!(b_neighbors, vec![]); + + let c_neighbors = g.neighbors(c).into_sorted_vec(); + assert_eq!(c_neighbors, vec![]); + } + + #[test] + fn test_neighbors_undirected() { + let mut g = MatrixGraph::new_undirected(); + let a = g.add_node('a'); + let b = g.add_node('b'); + let c = g.add_node('c'); + g.add_edge(a, b, ()); + g.add_edge(a, c, ()); + + let a_neighbors = g.neighbors(a).into_sorted_vec(); + assert_eq!(a_neighbors, sorted_vec![b, c]); + + let b_neighbors = g.neighbors(b).into_sorted_vec(); + assert_eq!(b_neighbors, sorted_vec![a]); + + let c_neighbors = g.neighbors(c).into_sorted_vec(); + assert_eq!(c_neighbors, sorted_vec![a]); + } + + #[test] + fn test_remove_node_and_edges() { + let mut g = MatrixGraph::new(); + let a = g.add_node('a'); + let b = g.add_node('b'); + let c = g.add_node('c'); + g.add_edge(a, b, ()); + g.add_edge(b, c, ()); + g.add_edge(c, a, ()); + + // removing b should break the `a -> b` and `b -> c` edges + g.remove_node(b); + + assert_eq!(g.node_count(), 2); + + let a_neighbors = g.neighbors(a).into_sorted_vec(); + assert_eq!(a_neighbors, vec![]); + + let c_neighbors = g.neighbors(c).into_sorted_vec(); + assert_eq!(c_neighbors, vec![a]); + } + + #[test] + fn test_remove_node_and_edges_undirected() { + let mut g = UnMatrix::new_undirected(); + let a = g.add_node('a'); + let b = g.add_node('b'); + let c = g.add_node('c'); + g.add_edge(a, b, ()); + g.add_edge(b, c, ()); + g.add_edge(c, a, ()); + + // removing a should break the `a - b` and `a - c` edges + g.remove_node(a); + + assert_eq!(g.node_count(), 2); + + let b_neighbors = g.neighbors(b).into_sorted_vec(); + assert_eq!(b_neighbors, vec![c]); + + let c_neighbors = g.neighbors(c).into_sorted_vec(); + assert_eq!(c_neighbors, vec![b]); + } + + #[test] + fn test_node_identifiers() { + let mut g = MatrixGraph::new(); + let a = g.add_node('a'); + let b = g.add_node('b'); + let c = g.add_node('c'); + let d = g.add_node('c'); + g.add_edge(a, b, ()); + g.add_edge(a, c, ()); + + let node_ids = g.node_identifiers().into_sorted_vec(); + assert_eq!(node_ids, sorted_vec![a, b, c, d]); + } + + #[test] + fn test_edges_directed() { + let g: MatrixGraph = MatrixGraph::from_edges(&[ + (0, 5), + (0, 2), + (0, 3), + (0, 1), + (1, 3), + (2, 3), + (2, 4), + (4, 0), + (6, 6), + ]); + + assert_eq!(g.edges_directed(node_index(0), Outgoing).count(), 4); + assert_eq!(g.edges_directed(node_index(1), Outgoing).count(), 1); + assert_eq!(g.edges_directed(node_index(2), Outgoing).count(), 2); + assert_eq!(g.edges_directed(node_index(3), Outgoing).count(), 0); + assert_eq!(g.edges_directed(node_index(4), Outgoing).count(), 1); + assert_eq!(g.edges_directed(node_index(5), Outgoing).count(), 0); + assert_eq!(g.edges_directed(node_index(6), Outgoing).count(), 1); + + assert_eq!(g.edges_directed(node_index(0), Incoming).count(), 1); + assert_eq!(g.edges_directed(node_index(1), Incoming).count(), 1); + assert_eq!(g.edges_directed(node_index(2), Incoming).count(), 1); + assert_eq!(g.edges_directed(node_index(3), Incoming).count(), 3); + assert_eq!(g.edges_directed(node_index(4), Incoming).count(), 1); + assert_eq!(g.edges_directed(node_index(5), Incoming).count(), 1); + assert_eq!(g.edges_directed(node_index(6), Incoming).count(), 1); + } + + #[test] + fn test_edges_undirected() { + let g: UnMatrix = UnMatrix::from_edges(&[ + (0, 5), + (0, 2), + (0, 3), + (0, 1), + (1, 3), + (2, 3), + (2, 4), + (4, 0), + (6, 6), + ]); + + assert_eq!(g.edges(node_index(0)).count(), 5); + assert_eq!(g.edges(node_index(1)).count(), 2); + assert_eq!(g.edges(node_index(2)).count(), 3); + assert_eq!(g.edges(node_index(3)).count(), 3); + assert_eq!(g.edges(node_index(4)).count(), 2); + assert_eq!(g.edges(node_index(5)).count(), 1); + assert_eq!(g.edges(node_index(6)).count(), 1); + } + + #[test] + fn test_edges_of_absent_node_is_empty_iterator() { + let g: MatrixGraph = MatrixGraph::new(); + assert_eq!(g.edges(node_index(0)).count(), 0); + } + + #[test] + fn test_neighbors_of_absent_node_is_empty_iterator() { + let g: MatrixGraph = MatrixGraph::new(); + assert_eq!(g.neighbors(node_index(0)).count(), 0); + } + + #[test] + fn test_edge_references() { + let g: MatrixGraph = MatrixGraph::from_edges(&[ + (0, 5), + (0, 2), + (0, 3), + (0, 1), + (1, 3), + (2, 3), + (2, 4), + (4, 0), + (6, 6), + ]); + + assert_eq!(g.edge_references().count(), 9); + } + + #[test] + fn test_edge_references_undirected() { + let g: UnMatrix = UnMatrix::from_edges(&[ + (0, 5), + (0, 2), + (0, 3), + (0, 1), + (1, 3), + (2, 3), + (2, 4), + (4, 0), + (6, 6), + ]); + + assert_eq!(g.edge_references().count(), 9); + } + + #[test] + fn test_id_storage() { + use super::IdStorage; + + let mut storage: IdStorage = IdStorage::with_capacity(0); + let a = storage.add('a'); + let b = storage.add('b'); + let c = storage.add('c'); + + assert!(a < b && b < c); + + // list IDs + assert_eq!(storage.iter_ids().into_vec(), vec![a, b, c]); + + storage.remove(b); + + // re-use of IDs + let bb = storage.add('B'); + assert_eq!(b, bb); + + // list IDs + assert_eq!(storage.iter_ids().into_vec(), vec![a, b, c]); + } + + #[test] + fn test_not_zero() { + let mut g: MatrixGraph<(), i32, Directed, NotZero> = MatrixGraph::default(); + + let a = g.add_node(()); + let b = g.add_node(()); + + assert!(!g.has_edge(a, b)); + assert_eq!(g.edge_count(), 0); + + g.add_edge(a, b, 12); + + assert!(g.has_edge(a, b)); + assert_eq!(g.edge_count(), 1); + assert_eq!(g.edge_weight(a, b), &12); + + g.remove_edge(a, b); + + assert!(!g.has_edge(a, b)); + assert_eq!(g.edge_count(), 0); + } + + #[test] + #[should_panic] + fn test_not_zero_asserted() { + let mut g: MatrixGraph<(), i32, Directed, NotZero> = MatrixGraph::default(); + + let a = g.add_node(()); + let b = g.add_node(()); + + g.add_edge(a, b, 0); // this should trigger an assertion + } + + #[test] + fn test_not_zero_float() { + let mut g: MatrixGraph<(), f32, Directed, NotZero> = MatrixGraph::default(); + + let a = g.add_node(()); + let b = g.add_node(()); + + assert!(!g.has_edge(a, b)); + assert_eq!(g.edge_count(), 0); + + g.add_edge(a, b, 12.); + + assert!(g.has_edge(a, b)); + assert_eq!(g.edge_count(), 1); + assert_eq!(g.edge_weight(a, b), &12.); + + g.remove_edge(a, b); + + assert!(!g.has_edge(a, b)); + assert_eq!(g.edge_count(), 0); + } + #[test] + // From https://github.com/petgraph/petgraph/issues/523 + fn test_tarjan_scc_with_removed_node() { + let mut g: MatrixGraph<(), ()> = MatrixGraph::new(); + + g.add_node(()); + let b = g.add_node(()); + g.add_node(()); + + g.remove_node(b); + + assert_eq!( + crate::algo::tarjan_scc(&g), + [[node_index(0)], [node_index(2)]] + ); + } + + #[test] + // From https://github.com/petgraph/petgraph/issues/523 + fn test_kosaraju_scc_with_removed_node() { + let mut g: MatrixGraph<(), ()> = MatrixGraph::new(); + + g.add_node(()); + let b = g.add_node(()); + g.add_node(()); + + g.remove_node(b); + + assert_eq!( + crate::algo::kosaraju_scc(&g), + [[node_index(2)], [node_index(0)]] + ); + } +} diff --git a/vendor/petgraph/src/operator.rs b/vendor/petgraph/src/operator.rs new file mode 100644 index 00000000..baa4f12b --- /dev/null +++ b/vendor/petgraph/src/operator.rs @@ -0,0 +1,83 @@ +//! Operators for creating new graphs from existings ones. +use super::graph::{Graph, IndexType}; +use super::EdgeType; +use crate::visit::IntoNodeReferences; + +/// \[Generic\] complement of the graph +/// +/// Computes the graph complement of the input Graph and stores it +/// in the provided empty output Graph. +/// +/// The function does not create self-loops. +/// +/// Computes in **O(|V|^2*log(|V|))** time (average). +/// +/// Returns the complement. +/// +/// # Example +/// ```rust +/// use petgraph::Graph; +/// use petgraph::operator::complement; +/// use petgraph::prelude::*; +/// +/// let mut graph: Graph<(),(),Directed> = Graph::new(); +/// let a = graph.add_node(()); // node with no weight +/// let b = graph.add_node(()); +/// let c = graph.add_node(()); +/// let d = graph.add_node(()); +/// +/// graph.extend_with_edges(&[ +/// (a, b), +/// (b, c), +/// (c, d), +/// ]); +/// // a ----> b ----> c ----> d +/// +/// let mut output: Graph<(), (), Directed> = Graph::new(); +/// +/// complement(&graph, &mut output, ()); +/// +/// let mut expected_res: Graph<(), (), Directed> = Graph::new(); +/// let a = expected_res.add_node(()); +/// let b = expected_res.add_node(()); +/// let c = expected_res.add_node(()); +/// let d = expected_res.add_node(()); +/// expected_res.extend_with_edges(&[ +/// (a, c), +/// (a, d), +/// (b, a), +/// (b, d), +/// (c, a), +/// (c, b), +/// (d, a), +/// (d, b), +/// (d, c), +/// ]); +/// +/// for x in graph.node_indices() { +/// for y in graph.node_indices() { +/// assert_eq!(output.contains_edge(x, y), expected_res.contains_edge(x, y)); +/// } +/// } +/// ``` +pub fn complement( + input: &Graph, + output: &mut Graph, + weight: E, +) where + Ty: EdgeType, + Ix: IndexType, + E: Clone, + N: Clone, +{ + for (_node, weight) in input.node_references() { + output.add_node(weight.clone()); + } + for x in input.node_indices() { + for y in input.node_indices() { + if x != y && !input.contains_edge(x, y) { + output.add_edge(x, y, weight.clone()); + } + } + } +} diff --git a/vendor/petgraph/src/prelude.rs b/vendor/petgraph/src/prelude.rs new file mode 100644 index 00000000..f50b338b --- /dev/null +++ b/vendor/petgraph/src/prelude.rs @@ -0,0 +1,21 @@ +//! Commonly used items. +//! +//! ``` +//! use petgraph::prelude::*; +//! ``` + +#[doc(no_inline)] +pub use crate::graph::{DiGraph, EdgeIndex, Graph, NodeIndex, UnGraph}; +#[cfg(feature = "graphmap")] +#[doc(no_inline)] +pub use crate::graphmap::{DiGraphMap, GraphMap, UnGraphMap}; +#[doc(no_inline)] +#[cfg(feature = "stable_graph")] +pub use crate::stable_graph::{StableDiGraph, StableGraph, StableUnGraph}; +#[doc(no_inline)] +pub use crate::visit::{Bfs, Dfs, DfsPostOrder}; +#[doc(no_inline)] +pub use crate::{Directed, Direction, Incoming, Outgoing, Undirected}; + +#[doc(no_inline)] +pub use crate::visit::EdgeRef; diff --git a/vendor/petgraph/src/quickcheck.rs b/vendor/petgraph/src/quickcheck.rs new file mode 100644 index 00000000..17375b45 --- /dev/null +++ b/vendor/petgraph/src/quickcheck.rs @@ -0,0 +1,216 @@ +extern crate quickcheck; +use self::quickcheck::{Arbitrary, Gen}; + +use crate::graph::{node_index, IndexType}; +#[cfg(feature = "stable_graph")] +use crate::stable_graph::StableGraph; +use crate::{EdgeType, Graph}; + +#[cfg(feature = "graphmap")] +use crate::graphmap::{GraphMap, NodeTrait}; +use crate::visit::NodeIndexable; + +/// Return a random float in the range [0, 1.) +fn random_01(g: &mut G) -> f64 { + // from rand + let bits = 53; + let scale = 1. / ((1u64 << bits) as f64); + let x: u64 = Arbitrary::arbitrary(g); + (x >> (64 - bits)) as f64 * scale +} + +/// `Arbitrary` for `Graph` creates a graph by selecting a node count +/// and a probability for each possible edge to exist. +/// +/// The result will be simple graph or digraph, self loops +/// possible, no parallel edges. +/// +/// The exact properties of the produced graph is subject to change. +/// +/// Requires crate feature `"quickcheck"` +impl Arbitrary for Graph +where + N: Arbitrary, + E: Arbitrary, + Ty: EdgeType + Send + 'static, + Ix: IndexType + Send, +{ + fn arbitrary(g: &mut G) -> Self { + let nodes = usize::arbitrary(g); + if nodes == 0 { + return Graph::with_capacity(0, 0); + } + // use X² for edge probability (bias towards lower) + let edge_prob = random_01(g) * random_01(g); + let edges = ((nodes as f64).powi(2) * edge_prob) as usize; + let mut gr = Graph::with_capacity(nodes, edges); + for _ in 0..nodes { + gr.add_node(N::arbitrary(g)); + } + for i in gr.node_indices() { + for j in gr.node_indices() { + if !gr.is_directed() && i > j { + continue; + } + let p: f64 = random_01(g); + if p <= edge_prob { + gr.add_edge(i, j, E::arbitrary(g)); + } + } + } + gr + } + + // shrink the graph by splitting it in two by a very + // simple algorithm, just even and odd node indices + fn shrink(&self) -> Box> { + let self_ = self.clone(); + Box::new((0..2).filter_map(move |x| { + let gr = self_.filter_map( + |i, w| { + if i.index() % 2 == x { + Some(w.clone()) + } else { + None + } + }, + |_, w| Some(w.clone()), + ); + // make sure we shrink + if gr.node_count() < self_.node_count() { + Some(gr) + } else { + None + } + })) + } +} + +#[cfg(feature = "stable_graph")] +/// `Arbitrary` for `StableGraph` creates a graph by selecting a node count +/// and a probability for each possible edge to exist. +/// +/// The result will be simple graph or digraph, with possible +/// self loops, no parallel edges. +/// +/// The exact properties of the produced graph is subject to change. +/// +/// Requires crate features `"quickcheck"` and `"stable_graph"` +impl Arbitrary for StableGraph +where + N: Arbitrary, + E: Arbitrary, + Ty: EdgeType + Send + 'static, + Ix: IndexType + Send, +{ + fn arbitrary(g: &mut G) -> Self { + let nodes = usize::arbitrary(g); + if nodes == 0 { + return StableGraph::with_capacity(0, 0); + } + // use X² for edge probability (bias towards lower) + let edge_prob = random_01(g) * random_01(g); + let edges = ((nodes as f64).powi(2) * edge_prob) as usize; + let mut gr = StableGraph::with_capacity(nodes, edges); + for _ in 0..nodes { + gr.add_node(N::arbitrary(g)); + } + for i in 0..gr.node_count() { + for j in 0..gr.node_count() { + let i = node_index(i); + let j = node_index(j); + if !gr.is_directed() && i > j { + continue; + } + let p: f64 = random_01(g); + if p <= edge_prob { + gr.add_edge(i, j, E::arbitrary(g)); + } + } + } + if bool::arbitrary(g) { + // potentially remove nodes to make holes in nodes & edge sets + let n = u8::arbitrary(g) % (gr.node_count() as u8); + for _ in 0..n { + let ni = node_index(usize::arbitrary(g) % gr.node_bound()); + if gr.node_weight(ni).is_some() { + gr.remove_node(ni); + } + } + } + gr + } + + // shrink the graph by splitting it in two by a very + // simple algorithm, just even and odd node indices + fn shrink(&self) -> Box> { + let self_ = self.clone(); + Box::new((0..2).filter_map(move |x| { + let gr = self_.filter_map( + |i, w| { + if i.index() % 2 == x { + Some(w.clone()) + } else { + None + } + }, + |_, w| Some(w.clone()), + ); + // make sure we shrink + if gr.node_count() < self_.node_count() { + Some(gr) + } else { + None + } + })) + } +} + +/// `Arbitrary` for `GraphMap` creates a graph by selecting a node count +/// and a probability for each possible edge to exist. +/// +/// The result will be simple graph or digraph, self loops +/// possible, no parallel edges. +/// +/// The exact properties of the produced graph is subject to change. +/// +/// Requires crate features `"quickcheck"` and `"graphmap"` +#[cfg(feature = "graphmap")] +impl Arbitrary for GraphMap +where + N: NodeTrait + Arbitrary, + E: Arbitrary, + Ty: EdgeType + Clone + Send + 'static, +{ + fn arbitrary(g: &mut G) -> Self { + let nodes = usize::arbitrary(g); + if nodes == 0 { + return GraphMap::with_capacity(0, 0); + } + let mut nodes = (0..nodes).map(|_| N::arbitrary(g)).collect::>(); + nodes.sort(); + nodes.dedup(); + + // use X² for edge probability (bias towards lower) + let edge_prob = random_01(g) * random_01(g); + let edges = ((nodes.len() as f64).powi(2) * edge_prob) as usize; + let mut gr = GraphMap::with_capacity(nodes.len(), edges); + for &node in &nodes { + gr.add_node(node); + } + for (index, &i) in nodes.iter().enumerate() { + let js = if Ty::is_directed() { + &nodes[..] + } else { + &nodes[index..] + }; + for &j in js { + let p: f64 = random_01(g); + if p <= edge_prob { + gr.add_edge(i, j, E::arbitrary(g)); + } + } + } + gr + } +} diff --git a/vendor/petgraph/src/scored.rs b/vendor/petgraph/src/scored.rs new file mode 100644 index 00000000..a1c8af9b --- /dev/null +++ b/vendor/petgraph/src/scored.rs @@ -0,0 +1,93 @@ +use std::cmp::Ordering; + +/// `MinScored` holds a score `K` and a scored object `T` in +/// a pair for use with a `BinaryHeap`. +/// +/// `MinScored` compares in reverse order by the score, so that we can +/// use `BinaryHeap` as a min-heap to extract the score-value pair with the +/// least score. +/// +/// **Note:** `MinScored` implements a total order (`Ord`), so that it is +/// possible to use float types as scores. +#[derive(Copy, Clone, Debug)] +pub struct MinScored(pub K, pub T); + +impl PartialEq for MinScored { + #[inline] + fn eq(&self, other: &MinScored) -> bool { + self.cmp(other) == Ordering::Equal + } +} + +impl Eq for MinScored {} + +impl PartialOrd for MinScored { + #[inline] + fn partial_cmp(&self, other: &MinScored) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for MinScored { + #[inline] + fn cmp(&self, other: &MinScored) -> Ordering { + let a = &self.0; + let b = &other.0; + if a == b { + Ordering::Equal + } else if a < b { + Ordering::Greater + } else if a > b { + Ordering::Less + } else if a.ne(a) && b.ne(b) { + // these are the NaN cases + Ordering::Equal + } else if a.ne(a) { + // Order NaN less, so that it is last in the MinScore order + Ordering::Less + } else { + Ordering::Greater + } + } +} + +#[derive(Copy, Clone, Debug)] +pub struct MaxScored(pub K, pub T); + +impl PartialEq for MaxScored { + #[inline] + fn eq(&self, other: &MaxScored) -> bool { + self.cmp(other) == Ordering::Equal + } +} + +impl Eq for MaxScored {} + +impl PartialOrd for MaxScored { + #[inline] + fn partial_cmp(&self, other: &MaxScored) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for MaxScored { + #[inline] + fn cmp(&self, other: &MaxScored) -> Ordering { + let a = &self.0; + let b = &other.0; + if a == b { + Ordering::Equal + } else if a < b { + Ordering::Less + } else if a > b { + Ordering::Greater + } else if a.ne(a) && b.ne(b) { + // these are the NaN cases + Ordering::Equal + } else if a.ne(a) { + Ordering::Less + } else { + Ordering::Greater + } + } +} diff --git a/vendor/petgraph/src/serde_utils.rs b/vendor/petgraph/src/serde_utils.rs new file mode 100644 index 00000000..f127f33b --- /dev/null +++ b/vendor/petgraph/src/serde_utils.rs @@ -0,0 +1,95 @@ +use serde::de::{Deserialize, Error, SeqAccess, Visitor}; +use serde::ser::{Serialize, SerializeSeq, Serializer}; +use std::fmt; +use std::marker::PhantomData; + +/// Map to serializeable representation +pub trait IntoSerializable { + type Output; + fn into_serializable(self) -> Self::Output; +} + +/// Map from deserialized representation +pub trait FromDeserialized: Sized { + type Input; + fn from_deserialized(input: Self::Input) -> Result + where + E: Error; +} + +/// Serde combinator. A sequence visitor that maps deserialized elements +/// lazily; the visitor can also emit new errors if the elements have errors. +pub struct MappedSequenceVisitor +where + F: Fn(T) -> Result, +{ + f: F, + marker: PhantomData T>, +} + +impl<'de, F, T, R> MappedSequenceVisitor +where + T: Deserialize<'de>, + F: Fn(T) -> Result, +{ + pub fn new(f: F) -> Self { + MappedSequenceVisitor { + f: f, + marker: PhantomData, + } + } +} + +impl<'de, F, T, R> Visitor<'de> for MappedSequenceVisitor +where + T: Deserialize<'de>, + F: Fn(T) -> Result, +{ + type Value = Vec; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "a sequence") + } + fn visit_seq(self, mut seq: A) -> Result + where + A: SeqAccess<'de>, + { + let mut v = Vec::new(); + while let Some(elem) = seq.next_element()? { + match (self.f)(elem) { + Err(s) => Err(::custom(s))?, + Ok(x) => v.push(x), + } + } + Ok(v) + } +} + +pub trait CollectSeqWithLength: Serializer { + fn collect_seq_with_length(self, length: usize, iterable: I) -> Result + where + I: IntoIterator, + I::Item: Serialize, + { + let mut count = 0; + let mut seq = self.serialize_seq(Some(length))?; + for element in iterable { + seq.serialize_element(&element)?; + count += 1; + } + debug_assert_eq!(length, count, "collect_seq_with_length: length mismatch!"); + seq.end() + } + + fn collect_seq_exact(self, iterable: I) -> Result + where + I: IntoIterator, + I::Item: Serialize, + I::IntoIter: ExactSizeIterator, + { + let iter = iterable.into_iter(); + self.collect_seq_with_length(iter.len(), iter) + } +} + +impl CollectSeqWithLength for S where S: Serializer {} diff --git a/vendor/petgraph/src/traits_graph.rs b/vendor/petgraph/src/traits_graph.rs new file mode 100644 index 00000000..272e9e7f --- /dev/null +++ b/vendor/petgraph/src/traits_graph.rs @@ -0,0 +1,73 @@ +use fixedbitset::FixedBitSet; + +use super::EdgeType; + +use super::graph::{Graph, IndexType, NodeIndex}; +#[cfg(feature = "stable_graph")] +use crate::stable_graph::StableGraph; +use crate::visit::EdgeRef; +#[cfg(feature = "stable_graph")] +use crate::visit::{IntoEdgeReferences, NodeIndexable}; + +use super::visit::GetAdjacencyMatrix; + +/// The adjacency matrix for **Graph** is a bitmap that's computed by +/// `.adjacency_matrix()`. +impl GetAdjacencyMatrix for Graph +where + Ty: EdgeType, + Ix: IndexType, +{ + type AdjMatrix = FixedBitSet; + + fn adjacency_matrix(&self) -> FixedBitSet { + let n = self.node_count(); + let mut matrix = FixedBitSet::with_capacity(n * n); + for edge in self.edge_references() { + let i = edge.source().index() * n + edge.target().index(); + matrix.put(i); + if !self.is_directed() { + let j = edge.source().index() + n * edge.target().index(); + matrix.put(j); + } + } + matrix + } + + fn is_adjacent(&self, matrix: &FixedBitSet, a: NodeIndex, b: NodeIndex) -> bool { + let n = self.node_count(); + let index = n * a.index() + b.index(); + matrix.contains(index) + } +} + +#[cfg(feature = "stable_graph")] +/// The adjacency matrix for **Graph** is a bitmap that's computed by +/// `.adjacency_matrix()`. +impl GetAdjacencyMatrix for StableGraph +where + Ty: EdgeType, + Ix: IndexType, +{ + type AdjMatrix = FixedBitSet; + + fn adjacency_matrix(&self) -> FixedBitSet { + let n = self.node_bound(); + let mut matrix = FixedBitSet::with_capacity(n * n); + for edge in self.edge_references() { + let i = edge.source().index() * n + edge.target().index(); + matrix.put(i); + if !self.is_directed() { + let j = edge.source().index() + n * edge.target().index(); + matrix.put(j); + } + } + matrix + } + + fn is_adjacent(&self, matrix: &FixedBitSet, a: NodeIndex, b: NodeIndex) -> bool { + let n = self.node_count(); + let index = n * a.index() + b.index(); + matrix.contains(index) + } +} diff --git a/vendor/petgraph/src/unionfind.rs b/vendor/petgraph/src/unionfind.rs new file mode 100644 index 00000000..2f6b12c0 --- /dev/null +++ b/vendor/petgraph/src/unionfind.rs @@ -0,0 +1,146 @@ +//! `UnionFind` is a disjoint-set data structure. + +use super::graph::IndexType; +use std::cmp::Ordering; + +/// `UnionFind` is a disjoint-set data structure. It tracks set membership of *n* elements +/// indexed from *0* to *n - 1*. The scalar type is `K` which must be an unsigned integer type. +/// +/// +/// +/// Too awesome not to quote: +/// +/// “The amortized time per operation is **O(α(n))** where **α(n)** is the +/// inverse of **f(x) = A(x, x)** with **A** being the extremely fast-growing Ackermann function.” +#[derive(Debug, Clone)] +pub struct UnionFind { + // For element at index *i*, store the index of its parent; the representative itself + // stores its own index. This forms equivalence classes which are the disjoint sets, each + // with a unique representative. + parent: Vec, + // It is a balancing tree structure, + // so the ranks are logarithmic in the size of the container -- a byte is more than enough. + // + // Rank is separated out both to save space and to save cache in when searching in the parent + // vector. + rank: Vec, +} + +#[inline] +unsafe fn get_unchecked(xs: &[K], index: usize) -> &K { + debug_assert!(index < xs.len()); + xs.get_unchecked(index) +} + +#[inline] +unsafe fn get_unchecked_mut(xs: &mut [K], index: usize) -> &mut K { + debug_assert!(index < xs.len()); + xs.get_unchecked_mut(index) +} + +impl UnionFind +where + K: IndexType, +{ + /// Create a new `UnionFind` of `n` disjoint sets. + pub fn new(n: usize) -> Self { + let rank = vec![0; n]; + let parent = (0..n).map(K::new).collect::>(); + + UnionFind { parent, rank } + } + + /// Return the representative for `x`. + /// + /// **Panics** if `x` is out of bounds. + pub fn find(&self, x: K) -> K { + assert!(x.index() < self.parent.len()); + unsafe { + let mut x = x; + loop { + // Use unchecked indexing because we can trust the internal set ids. + let xparent = *get_unchecked(&self.parent, x.index()); + if xparent == x { + break; + } + x = xparent; + } + x + } + } + + /// Return the representative for `x`. + /// + /// Write back the found representative, flattening the internal + /// datastructure in the process and quicken future lookups. + /// + /// **Panics** if `x` is out of bounds. + pub fn find_mut(&mut self, x: K) -> K { + assert!(x.index() < self.parent.len()); + unsafe { self.find_mut_recursive(x) } + } + + unsafe fn find_mut_recursive(&mut self, mut x: K) -> K { + let mut parent = *get_unchecked(&self.parent, x.index()); + while parent != x { + let grandparent = *get_unchecked(&self.parent, parent.index()); + *get_unchecked_mut(&mut self.parent, x.index()) = grandparent; + x = parent; + parent = grandparent; + } + x + } + + /// Returns `true` if the given elements belong to the same set, and returns + /// `false` otherwise. + pub fn equiv(&self, x: K, y: K) -> bool { + self.find(x) == self.find(y) + } + + /// Unify the two sets containing `x` and `y`. + /// + /// Return `false` if the sets were already the same, `true` if they were unified. + /// + /// **Panics** if `x` or `y` is out of bounds. + pub fn union(&mut self, x: K, y: K) -> bool { + if x == y { + return false; + } + let xrep = self.find_mut(x); + let yrep = self.find_mut(y); + + if xrep == yrep { + return false; + } + + let xrepu = xrep.index(); + let yrepu = yrep.index(); + let xrank = self.rank[xrepu]; + let yrank = self.rank[yrepu]; + + // The rank corresponds roughly to the depth of the treeset, so put the + // smaller set below the larger + match xrank.cmp(&yrank) { + Ordering::Less => self.parent[xrepu] = yrep, + Ordering::Greater => self.parent[yrepu] = xrep, + Ordering::Equal => { + self.parent[yrepu] = xrep; + self.rank[xrepu] += 1; + } + } + true + } + + /// Return a vector mapping each element to its representative. + pub fn into_labeling(mut self) -> Vec { + // write in the labeling of each element + unsafe { + for ix in 0..self.parent.len() { + let k = *get_unchecked(&self.parent, ix); + let xrep = self.find_mut_recursive(k); + *self.parent.get_unchecked_mut(ix) = xrep; + } + } + self.parent + } +} diff --git a/vendor/petgraph/src/util.rs b/vendor/petgraph/src/util.rs new file mode 100644 index 00000000..980e6041 --- /dev/null +++ b/vendor/petgraph/src/util.rs @@ -0,0 +1,16 @@ +use std::iter; + +pub fn enumerate(iterable: I) -> iter::Enumerate +where + I: IntoIterator, +{ + iterable.into_iter().enumerate() +} + +pub fn zip(i: I, j: J) -> iter::Zip +where + I: IntoIterator, + J: IntoIterator, +{ + i.into_iter().zip(j) +} diff --git a/vendor/petgraph/src/visit/dfsvisit.rs b/vendor/petgraph/src/visit/dfsvisit.rs new file mode 100644 index 00000000..d2eb5d4a --- /dev/null +++ b/vendor/petgraph/src/visit/dfsvisit.rs @@ -0,0 +1,314 @@ +use crate::visit::IntoNeighbors; +use crate::visit::{VisitMap, Visitable}; + +/// Strictly monotonically increasing event time for a depth first search. +#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Default, Hash)] +pub struct Time(pub usize); + +/// A depth first search (DFS) visitor event. +#[derive(Copy, Clone, Debug)] +pub enum DfsEvent { + Discover(N, Time), + /// An edge of the tree formed by the traversal. + TreeEdge(N, N), + /// An edge to an already visited node. + BackEdge(N, N), + /// A cross or forward edge. + /// + /// For an edge *(u, v)*, if the discover time of *v* is greater than *u*, + /// then it is a forward edge, else a cross edge. + CrossForwardEdge(N, N), + /// All edges from a node have been reported. + Finish(N, Time), +} + +/// Return if the expression is a break value, execute the provided statement +/// if it is a prune value. +macro_rules! try_control { + ($e:expr, $p:stmt) => { + try_control!($e, $p, ()); + }; + ($e:expr, $p:stmt, $q:stmt) => { + match $e { + x => { + if x.should_break() { + return x; + } else if x.should_prune() { + $p + } else { + $q + } + } + } + }; +} + +/// Control flow for `depth_first_search` callbacks. +#[derive(Copy, Clone, Debug)] +pub enum Control { + /// Continue the DFS traversal as normal. + Continue, + /// Prune the current node from the DFS traversal. No more edges from this + /// node will be reported to the callback. A `DfsEvent::Finish` for this + /// node will still be reported. This can be returned in response to any + /// `DfsEvent`, except `Finish`, which will panic. + Prune, + /// Stop the DFS traversal and return the provided value. + Break(B), +} + +impl Control { + pub fn breaking() -> Control<()> { + Control::Break(()) + } + /// Get the value in `Control::Break(_)`, if present. + pub fn break_value(self) -> Option { + match self { + Control::Continue | Control::Prune => None, + Control::Break(b) => Some(b), + } + } +} + +/// Control flow for callbacks. +/// +/// The empty return value `()` is equivalent to continue. +pub trait ControlFlow { + fn continuing() -> Self; + fn should_break(&self) -> bool; + fn should_prune(&self) -> bool; +} + +impl ControlFlow for () { + fn continuing() {} + #[inline] + fn should_break(&self) -> bool { + false + } + #[inline] + fn should_prune(&self) -> bool { + false + } +} + +impl ControlFlow for Control { + fn continuing() -> Self { + Control::Continue + } + fn should_break(&self) -> bool { + if let Control::Break(_) = *self { + true + } else { + false + } + } + fn should_prune(&self) -> bool { + match *self { + Control::Prune => true, + Control::Continue | Control::Break(_) => false, + } + } +} + +impl ControlFlow for Result { + fn continuing() -> Self { + Ok(C::continuing()) + } + fn should_break(&self) -> bool { + if let Ok(ref c) = *self { + c.should_break() + } else { + true + } + } + fn should_prune(&self) -> bool { + if let Ok(ref c) = *self { + c.should_prune() + } else { + false + } + } +} + +/// The default is `Continue`. +impl Default for Control { + fn default() -> Self { + Control::Continue + } +} + +/// A recursive depth first search. +/// +/// Starting points are the nodes in the iterator `starts` (specify just one +/// start vertex *x* by using `Some(x)`). +/// +/// The traversal emits discovery and finish events for each reachable vertex, +/// and edge classification of each reachable edge. `visitor` is called for each +/// event, see [`DfsEvent`][de] for possible values. +/// +/// The return value should implement the trait `ControlFlow`, and can be used to change +/// the control flow of the search. +/// +/// `Control` Implements `ControlFlow` such that `Control::Continue` resumes the search. +/// `Control::Break` will stop the visit early, returning the contained value. +/// `Control::Prune` will stop traversing any additional edges from the current +/// node and proceed immediately to the `Finish` event. +/// +/// There are implementations of `ControlFlow` for `()`, and `Result` where +/// `C: ControlFlow`. The implementation for `()` will continue until finished. +/// For `Result`, upon encountering an `E` it will break, otherwise acting the same as `C`. +/// +/// ***Panics** if you attempt to prune a node from its `Finish` event. +/// +/// [de]: enum.DfsEvent.html +/// +/// # Example returning `Control`. +/// +/// Find a path from vertex 0 to 5, and exit the visit as soon as we reach +/// the goal vertex. +/// +/// ``` +/// use petgraph::prelude::*; +/// use petgraph::graph::node_index as n; +/// use petgraph::visit::depth_first_search; +/// use petgraph::visit::{DfsEvent, Control}; +/// +/// let gr: Graph<(), ()> = Graph::from_edges(&[ +/// (0, 1), (0, 2), (0, 3), +/// (1, 3), +/// (2, 3), (2, 4), +/// (4, 0), (4, 5), +/// ]); +/// +/// // record each predecessor, mapping node → node +/// let mut predecessor = vec![NodeIndex::end(); gr.node_count()]; +/// let start = n(0); +/// let goal = n(5); +/// depth_first_search(&gr, Some(start), |event| { +/// if let DfsEvent::TreeEdge(u, v) = event { +/// predecessor[v.index()] = u; +/// if v == goal { +/// return Control::Break(v); +/// } +/// } +/// Control::Continue +/// }); +/// +/// let mut next = goal; +/// let mut path = vec![next]; +/// while next != start { +/// let pred = predecessor[next.index()]; +/// path.push(pred); +/// next = pred; +/// } +/// path.reverse(); +/// assert_eq!(&path, &[n(0), n(2), n(4), n(5)]); +/// ``` +/// +/// # Example returning a `Result`. +/// ``` +/// use petgraph::graph::node_index as n; +/// use petgraph::prelude::*; +/// use petgraph::visit::depth_first_search; +/// use petgraph::visit::{DfsEvent, Time}; +/// +/// let gr: Graph<(), ()> = Graph::from_edges(&[(0, 1), (1, 2), (1, 1), (2, 1)]); +/// let start = n(0); +/// let mut back_edges = 0; +/// let mut discover_time = 0; +/// // Stop the search, the first time a BackEdge is encountered. +/// let result = depth_first_search(&gr, Some(start), |event| { +/// match event { +/// // In the cases where Ok(()) is returned, +/// // Result falls back to the implementation of Control on the value (). +/// // In the case of (), this is to always return Control::Continue. +/// // continuing the search. +/// DfsEvent::Discover(_, Time(t)) => { +/// discover_time = t; +/// Ok(()) +/// } +/// DfsEvent::BackEdge(_, _) => { +/// back_edges += 1; +/// // the implementation of ControlFlow for Result, +/// // treats this Err value as Continue::Break +/// Err(event) +/// } +/// _ => Ok(()), +/// } +/// }); +/// +/// // Even though the graph has more than one cycle, +/// // The number of back_edges visited by the search should always be 1. +/// assert_eq!(back_edges, 1); +/// println!("discover time:{:?}", discover_time); +/// println!("number of backedges encountered: {}", back_edges); +/// println!("back edge: {:?}", result); +/// ``` +pub fn depth_first_search(graph: G, starts: I, mut visitor: F) -> C +where + G: IntoNeighbors + Visitable, + I: IntoIterator, + F: FnMut(DfsEvent) -> C, + C: ControlFlow, +{ + let time = &mut Time(0); + let discovered = &mut graph.visit_map(); + let finished = &mut graph.visit_map(); + + for start in starts { + try_control!( + dfs_visitor(graph, start, &mut visitor, discovered, finished, time), + unreachable!() + ); + } + C::continuing() +} + +pub(crate) fn dfs_visitor( + graph: G, + u: G::NodeId, + visitor: &mut F, + discovered: &mut impl VisitMap, + finished: &mut impl VisitMap, + time: &mut Time, +) -> C +where + G: IntoNeighbors + Visitable, + F: FnMut(DfsEvent) -> C, + C: ControlFlow, +{ + if !discovered.visit(u) { + return C::continuing(); + } + + try_control!( + visitor(DfsEvent::Discover(u, time_post_inc(time))), + {}, + for v in graph.neighbors(u) { + if !discovered.is_visited(&v) { + try_control!(visitor(DfsEvent::TreeEdge(u, v)), continue); + try_control!( + dfs_visitor(graph, v, visitor, discovered, finished, time), + unreachable!() + ); + } else if !finished.is_visited(&v) { + try_control!(visitor(DfsEvent::BackEdge(u, v)), continue); + } else { + try_control!(visitor(DfsEvent::CrossForwardEdge(u, v)), continue); + } + } + ); + let first_finish = finished.visit(u); + debug_assert!(first_finish); + try_control!( + visitor(DfsEvent::Finish(u, time_post_inc(time))), + panic!("Pruning on the `DfsEvent::Finish` is not supported!") + ); + C::continuing() +} + +fn time_post_inc(x: &mut Time) -> Time { + let v = *x; + x.0 += 1; + v +} diff --git a/vendor/petgraph/src/visit/filter.rs b/vendor/petgraph/src/visit/filter.rs new file mode 100644 index 00000000..496f57f5 --- /dev/null +++ b/vendor/petgraph/src/visit/filter.rs @@ -0,0 +1,583 @@ +use crate::prelude::*; + +use fixedbitset::FixedBitSet; +use std::collections::HashSet; +use std::marker::PhantomData; + +use crate::data::DataMap; +use crate::visit::{Data, NodeCompactIndexable, NodeCount}; +use crate::visit::{ + EdgeIndexable, GraphBase, GraphProp, IntoEdgeReferences, IntoEdges, IntoEdgesDirected, + IntoNeighbors, IntoNeighborsDirected, IntoNodeIdentifiers, IntoNodeReferences, NodeIndexable, + NodeRef, VisitMap, Visitable, +}; + +/// A graph filter for nodes. +pub trait FilterNode { + /// Return true to have the node be part of the graph + fn include_node(&self, node: N) -> bool; +} + +impl FilterNode for F +where + F: Fn(N) -> bool, +{ + fn include_node(&self, n: N) -> bool { + (*self)(n) + } +} + +/// This filter includes the nodes that are contained in the set. +impl FilterNode for FixedBitSet +where + FixedBitSet: VisitMap, +{ + fn include_node(&self, n: N) -> bool { + self.is_visited(&n) + } +} + +/// This filter includes the nodes that are contained in the set. +impl FilterNode for HashSet +where + HashSet: VisitMap, +{ + fn include_node(&self, n: N) -> bool { + self.is_visited(&n) + } +} + +// Can't express these as a generic impl over all references since that would conflict with the +// impl for Fn. +impl FilterNode for &FixedBitSet +where + FixedBitSet: VisitMap, +{ + fn include_node(&self, n: N) -> bool { + self.is_visited(&n) + } +} + +impl FilterNode for &HashSet +where + HashSet: VisitMap, +{ + fn include_node(&self, n: N) -> bool { + self.is_visited(&n) + } +} + +/// A node-filtering graph adaptor. +#[derive(Copy, Clone, Debug)] +pub struct NodeFiltered(pub G, pub F); + +impl NodeFiltered +where + G: GraphBase, + F: Fn(G::NodeId) -> bool, +{ + /// Create an `NodeFiltered` adaptor from the closure `filter`. + pub fn from_fn(graph: G, filter: F) -> Self { + NodeFiltered(graph, filter) + } +} + +impl GraphBase for NodeFiltered +where + G: GraphBase, +{ + type NodeId = G::NodeId; + type EdgeId = G::EdgeId; +} + +impl<'a, G, F> IntoNeighbors for &'a NodeFiltered +where + G: IntoNeighbors, + F: FilterNode, +{ + type Neighbors = NodeFilteredNeighbors<'a, G::Neighbors, F>; + fn neighbors(self, n: G::NodeId) -> Self::Neighbors { + NodeFilteredNeighbors { + include_source: self.1.include_node(n), + iter: self.0.neighbors(n), + f: &self.1, + } + } +} + +/// A filtered neighbors iterator. +#[derive(Debug, Clone)] +pub struct NodeFilteredNeighbors<'a, I, F: 'a> { + include_source: bool, + iter: I, + f: &'a F, +} + +impl Iterator for NodeFilteredNeighbors<'_, I, F> +where + I: Iterator, + I::Item: Copy, + F: FilterNode, +{ + type Item = I::Item; + fn next(&mut self) -> Option { + let f = self.f; + if !self.include_source { + None + } else { + self.iter.find(move |&target| f.include_node(target)) + } + } + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } +} + +impl<'a, G, F> IntoNeighborsDirected for &'a NodeFiltered +where + G: IntoNeighborsDirected, + F: FilterNode, +{ + type NeighborsDirected = NodeFilteredNeighbors<'a, G::NeighborsDirected, F>; + fn neighbors_directed(self, n: G::NodeId, dir: Direction) -> Self::NeighborsDirected { + NodeFilteredNeighbors { + include_source: self.1.include_node(n), + iter: self.0.neighbors_directed(n, dir), + f: &self.1, + } + } +} + +impl<'a, G, F> IntoNodeIdentifiers for &'a NodeFiltered +where + G: IntoNodeIdentifiers, + F: FilterNode, +{ + type NodeIdentifiers = NodeFilteredNeighbors<'a, G::NodeIdentifiers, F>; + fn node_identifiers(self) -> Self::NodeIdentifiers { + NodeFilteredNeighbors { + include_source: true, + iter: self.0.node_identifiers(), + f: &self.1, + } + } +} + +impl<'a, G, F> IntoNodeReferences for &'a NodeFiltered +where + G: IntoNodeReferences, + F: FilterNode, +{ + type NodeRef = G::NodeRef; + type NodeReferences = NodeFilteredNodes<'a, G::NodeReferences, F>; + fn node_references(self) -> Self::NodeReferences { + NodeFilteredNodes { + include_source: true, + iter: self.0.node_references(), + f: &self.1, + } + } +} + +/// A filtered node references iterator. +#[derive(Debug, Clone)] +pub struct NodeFilteredNodes<'a, I, F: 'a> { + include_source: bool, + iter: I, + f: &'a F, +} + +impl Iterator for NodeFilteredNodes<'_, I, F> +where + I: Iterator, + I::Item: Copy + NodeRef, + F: FilterNode<::NodeId>, +{ + type Item = I::Item; + fn next(&mut self) -> Option { + let f = self.f; + if !self.include_source { + None + } else { + self.iter.find(move |&target| f.include_node(target.id())) + } + } + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } +} + +impl<'a, G, F> IntoEdgeReferences for &'a NodeFiltered +where + G: IntoEdgeReferences, + F: FilterNode, +{ + type EdgeRef = G::EdgeRef; + type EdgeReferences = NodeFilteredEdgeReferences<'a, G, G::EdgeReferences, F>; + fn edge_references(self) -> Self::EdgeReferences { + NodeFilteredEdgeReferences { + graph: PhantomData, + iter: self.0.edge_references(), + f: &self.1, + } + } +} + +/// A filtered edges iterator. +#[derive(Debug, Clone)] +pub struct NodeFilteredEdgeReferences<'a, G, I, F: 'a> { + graph: PhantomData, + iter: I, + f: &'a F, +} + +impl Iterator for NodeFilteredEdgeReferences<'_, G, I, F> +where + F: FilterNode, + G: IntoEdgeReferences, + I: Iterator, +{ + type Item = I::Item; + fn next(&mut self) -> Option { + let f = self.f; + self.iter + .find(move |&edge| f.include_node(edge.source()) && f.include_node(edge.target())) + } + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } +} + +impl<'a, G, F> IntoEdges for &'a NodeFiltered +where + G: IntoEdges, + F: FilterNode, +{ + type Edges = NodeFilteredEdges<'a, G, G::Edges, F>; + fn edges(self, a: G::NodeId) -> Self::Edges { + NodeFilteredEdges { + graph: PhantomData, + include_source: self.1.include_node(a), + iter: self.0.edges(a), + f: &self.1, + dir: Direction::Outgoing, + } + } +} + +impl<'a, G, F> IntoEdgesDirected for &'a NodeFiltered +where + G: IntoEdgesDirected, + F: FilterNode, +{ + type EdgesDirected = NodeFilteredEdges<'a, G, G::EdgesDirected, F>; + fn edges_directed(self, a: G::NodeId, dir: Direction) -> Self::EdgesDirected { + NodeFilteredEdges { + graph: PhantomData, + include_source: self.1.include_node(a), + iter: self.0.edges_directed(a, dir), + f: &self.1, + dir, + } + } +} + +/// A filtered edges iterator. +#[derive(Debug, Clone)] +pub struct NodeFilteredEdges<'a, G, I, F: 'a> { + graph: PhantomData, + include_source: bool, + iter: I, + f: &'a F, + dir: Direction, +} + +impl Iterator for NodeFilteredEdges<'_, G, I, F> +where + F: FilterNode, + G: IntoEdges, + I: Iterator, +{ + type Item = I::Item; + fn next(&mut self) -> Option { + if !self.include_source { + None + } else { + let dir = self.dir; + let f = self.f; + self.iter.find(move |&edge| { + f.include_node(match dir { + Direction::Outgoing => edge.target(), + Direction::Incoming => edge.source(), + }) + }) + } + } + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } +} + +impl DataMap for NodeFiltered +where + G: DataMap, + F: FilterNode, +{ + fn node_weight(&self, id: Self::NodeId) -> Option<&Self::NodeWeight> { + if self.1.include_node(id) { + self.0.node_weight(id) + } else { + None + } + } + + fn edge_weight(&self, id: Self::EdgeId) -> Option<&Self::EdgeWeight> { + self.0.edge_weight(id) + } +} + +macro_rules! access0 { + ($e:expr) => { + $e.0 + }; +} + +Data! {delegate_impl [[G, F], G, NodeFiltered, access0]} +NodeIndexable! {delegate_impl [[G, F], G, NodeFiltered, access0]} +EdgeIndexable! {delegate_impl [[G, F], G, NodeFiltered, access0]} +GraphProp! {delegate_impl [[G, F], G, NodeFiltered, access0]} +Visitable! {delegate_impl [[G, F], G, NodeFiltered, access0]} + +/// A graph filter for edges +pub trait FilterEdge { + /// Return true to have the edge be part of the graph + fn include_edge(&self, edge: Edge) -> bool; +} + +impl FilterEdge for F +where + F: Fn(N) -> bool, +{ + fn include_edge(&self, n: N) -> bool { + (*self)(n) + } +} + +/// An edge-filtering graph adaptor. +/// +/// The adaptor may filter out edges. The filter implements the trait +/// `FilterEdge`. Closures of type `Fn(G::EdgeRef) -> bool` already +/// implement this trait. +/// +/// The filter may use edge source, target, id, and weight to select whether to +/// include the edge or not. +#[derive(Copy, Clone, Debug)] +pub struct EdgeFiltered(pub G, pub F); + +impl EdgeFiltered +where + G: IntoEdgeReferences, + F: Fn(G::EdgeRef) -> bool, +{ + /// Create an `EdgeFiltered` adaptor from the closure `filter`. + pub fn from_fn(graph: G, filter: F) -> Self { + EdgeFiltered(graph, filter) + } +} + +impl GraphBase for EdgeFiltered +where + G: GraphBase, +{ + type NodeId = G::NodeId; + type EdgeId = G::EdgeId; +} + +impl<'a, G, F> IntoNeighbors for &'a EdgeFiltered +where + G: IntoEdges, + F: FilterEdge, +{ + type Neighbors = EdgeFilteredNeighbors<'a, G, F>; + fn neighbors(self, n: G::NodeId) -> Self::Neighbors { + EdgeFilteredNeighbors { + iter: self.0.edges(n), + f: &self.1, + } + } +} + +impl<'a, G, F> IntoNeighborsDirected for &'a EdgeFiltered +where + G: IntoEdgesDirected, + F: FilterEdge, +{ + type NeighborsDirected = EdgeFilteredNeighborsDirected<'a, G, F>; + fn neighbors_directed(self, n: G::NodeId, dir: Direction) -> Self::NeighborsDirected { + EdgeFilteredNeighborsDirected { + iter: self.0.edges_directed(n, dir), + f: &self.1, + from: n, + } + } +} + +/// A filtered neighbors iterator. +#[derive(Debug, Clone)] +pub struct EdgeFilteredNeighbors<'a, G, F: 'a> +where + G: IntoEdges, +{ + iter: G::Edges, + f: &'a F, +} + +impl Iterator for EdgeFilteredNeighbors<'_, G, F> +where + F: FilterEdge, + G: IntoEdges, +{ + type Item = G::NodeId; + fn next(&mut self) -> Option { + let f = self.f; + (&mut self.iter) + .filter_map(move |edge| { + if f.include_edge(edge) { + Some(edge.target()) + } else { + None + } + }) + .next() + } + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } +} + +impl<'a, G, F> IntoEdgeReferences for &'a EdgeFiltered +where + G: IntoEdgeReferences, + F: FilterEdge, +{ + type EdgeRef = G::EdgeRef; + type EdgeReferences = EdgeFilteredEdges<'a, G, G::EdgeReferences, F>; + fn edge_references(self) -> Self::EdgeReferences { + EdgeFilteredEdges { + graph: PhantomData, + iter: self.0.edge_references(), + f: &self.1, + } + } +} + +impl<'a, G, F> IntoEdges for &'a EdgeFiltered +where + G: IntoEdges, + F: FilterEdge, +{ + type Edges = EdgeFilteredEdges<'a, G, G::Edges, F>; + fn edges(self, n: G::NodeId) -> Self::Edges { + EdgeFilteredEdges { + graph: PhantomData, + iter: self.0.edges(n), + f: &self.1, + } + } +} + +impl<'a, G, F> IntoEdgesDirected for &'a EdgeFiltered +where + G: IntoEdgesDirected, + F: FilterEdge, +{ + type EdgesDirected = EdgeFilteredEdges<'a, G, G::EdgesDirected, F>; + + fn edges_directed(self, n: G::NodeId, dir: Direction) -> Self::EdgesDirected { + EdgeFilteredEdges { + graph: PhantomData, + iter: self.0.edges_directed(n, dir), + f: &self.1, + } + } +} + +/// A filtered edges iterator. +#[derive(Debug, Clone)] +pub struct EdgeFilteredEdges<'a, G, I, F: 'a> { + graph: PhantomData, + iter: I, + f: &'a F, +} + +impl Iterator for EdgeFilteredEdges<'_, G, I, F> +where + F: FilterEdge, + G: IntoEdgeReferences, + I: Iterator, +{ + type Item = I::Item; + fn next(&mut self) -> Option { + let f = self.f; + self.iter.find(move |&edge| f.include_edge(edge)) + } + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } +} + +/// A filtered neighbors-directed iterator. +#[derive(Debug, Clone)] +pub struct EdgeFilteredNeighborsDirected<'a, G, F: 'a> +where + G: IntoEdgesDirected, +{ + iter: G::EdgesDirected, + f: &'a F, + from: G::NodeId, +} + +impl Iterator for EdgeFilteredNeighborsDirected<'_, G, F> +where + F: FilterEdge, + G: IntoEdgesDirected, +{ + type Item = G::NodeId; + fn next(&mut self) -> Option { + let f = self.f; + let from = self.from; + (&mut self.iter) + .filter_map(move |edge| { + if f.include_edge(edge) { + if edge.source() != from { + Some(edge.source()) + } else { + Some(edge.target()) // includes case where from == source == target + } + } else { + None + } + }) + .next() + } + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } +} + +Data! {delegate_impl [[G, F], G, EdgeFiltered, access0]} +GraphProp! {delegate_impl [[G, F], G, EdgeFiltered, access0]} +IntoNodeIdentifiers! {delegate_impl [['a, G, F], G, &'a EdgeFiltered, access0]} +IntoNodeReferences! {delegate_impl [['a, G, F], G, &'a EdgeFiltered, access0]} +NodeCompactIndexable! {delegate_impl [[G, F], G, EdgeFiltered, access0]} +NodeCount! {delegate_impl [[G, F], G, EdgeFiltered, access0]} +NodeIndexable! {delegate_impl [[G, F], G, EdgeFiltered, access0]} +EdgeIndexable! {delegate_impl [[G, F], G, EdgeFiltered, access0]} +Visitable! {delegate_impl [[G, F], G, EdgeFiltered, access0]} diff --git a/vendor/petgraph/src/visit/macros.rs b/vendor/petgraph/src/visit/macros.rs new file mode 100644 index 00000000..1b36030d --- /dev/null +++ b/vendor/petgraph/src/visit/macros.rs @@ -0,0 +1,135 @@ +/// Define a trait as usual, and a macro that can be used to instantiate +/// implementations of it. +/// +/// There *must* be section markers in the trait definition: +/// @section type for associated types +/// @section self for methods +/// @section nodelegate for arbitrary tail that is not forwarded. +macro_rules! trait_template { + ($(#[$doc:meta])* pub trait $name:ident $($methods:tt)*) => { + macro_rules! $name { + ($m:ident $extra:tt) => { + $m! { + $extra + pub trait $name $($methods)* + } + } + } + + remove_sections! { [] + $(#[$doc])* + pub trait $name $($methods)* + + // This is where the trait definition is reproduced by the macro. + // It makes the source links point to this place! + // + // I'm sorry, you'll have to find the source by looking at the + // source of the module the trait is defined in. + // + // We use this nifty macro so that we can automatically generate + // delegation trait impls and implement the graph traits for more + // types and combinators. + } + } +} + +macro_rules! remove_sections_inner { + ([$($stack:tt)*]) => { + $($stack)* + }; + // escape the following tt + ([$($stack:tt)*] @escape $_x:tt $($t:tt)*) => { + remove_sections_inner!([$($stack)*] $($t)*); + }; + ([$($stack:tt)*] @section $x:ident $($t:tt)*) => { + remove_sections_inner!([$($stack)*] $($t)*); + }; + ([$($stack:tt)*] $t:tt $($tail:tt)*) => { + remove_sections_inner!([$($stack)* $t] $($tail)*); + }; +} + +// This is the outer layer, just find the { } of the actual trait definition +// recurse once into { }, but not more. +macro_rules! remove_sections { + ([$($stack:tt)*]) => { + $($stack)* + }; + ([$($stack:tt)*] { $($tail:tt)* }) => { + $($stack)* { + remove_sections_inner!([] $($tail)*); + } + }; + ([$($stack:tt)*] $t:tt $($tail:tt)*) => { + remove_sections!([$($stack)* $t] $($tail)*); + }; +} + +macro_rules! deref { + ($e:expr) => { + *$e + }; +} +macro_rules! deref_twice { + ($e:expr) => { + **$e + }; +} + +/// Implement a trait by delegation. By default as if we are delegating +/// from &G to G. +macro_rules! delegate_impl { + ([] $($rest:tt)*) => { + delegate_impl! { [['a, G], G, &'a G, deref] $($rest)* } + }; + ([[$($param:tt)*], $self_type:ident, $self_wrap:ty, $self_map:ident] + pub trait $name:ident $(: $sup:ident)* $(+ $more_sup:ident)* { + + // "Escaped" associated types. Stripped before making the `trait` + // itself, but forwarded when delegating impls. + $( + @escape [type $assoc_name_ext:ident] + // Associated types. Forwarded. + )* + $( + @section type + $( + $(#[$_assoc_attr:meta])* + type $assoc_name:ident $(: $assoc_bound:ty)*; + )+ + )* + // Methods. Forwarded. Using $self_map!(self) around the self argument. + // Methods must use receiver `self` or explicit type like `self: &Self` + // &self and &mut self are _not_ supported. + $( + @section self + $( + $(#[$_method_attr:meta])* + fn $method_name:ident(self $(: $self_selftype:ty)* $(,$marg:ident : $marg_ty:ty)*) $(-> $mret:ty)?; + )+ + )* + // Arbitrary tail that is ignored when forwarding. + $( + @section nodelegate + $($tail:tt)* + )* + }) => { + impl<$($param)*> $name for $self_wrap where $self_type: $name { + $( + $( + type $assoc_name = $self_type::$assoc_name; + )* + )* + $( + type $assoc_name_ext = $self_type::$assoc_name_ext; + )* + $( + $( + fn $method_name(self $(: $self_selftype)* $(,$marg: $marg_ty)*) $(-> $mret)? { + $self_map!(self).$method_name($($marg),*) + } + )* + )* + } + } +} diff --git a/vendor/petgraph/src/visit/mod.rs b/vendor/petgraph/src/visit/mod.rs new file mode 100644 index 00000000..bc152560 --- /dev/null +++ b/vendor/petgraph/src/visit/mod.rs @@ -0,0 +1,481 @@ +//! Graph traits and graph traversals. +//! +//! ### The `Into-` Traits +//! +//! Graph traits like [`IntoNeighbors`][in] create iterators and use the same +//! pattern that `IntoIterator` does: the trait takes a reference to a graph, +//! and produces an iterator. These traits are quite composable, but with the +//! limitation that they only use shared references to graphs. +//! +//! ### Graph Traversal +//! +//! [`Dfs`](struct.Dfs.html), [`Bfs`][bfs], [`DfsPostOrder`][dfspo] and +//! [`Topo`][topo] are basic visitors and they use “walker” methods: the +//! visitors don't hold the graph as borrowed during traversal, only for the +//! `.next()` call on the walker. They can be converted to iterators +//! through the [`Walker`][w] trait. +//! +//! There is also the callback based traversal [`depth_first_search`][dfs]. +//! +//! [bfs]: struct.Bfs.html +//! [dfspo]: struct.DfsPostOrder.html +//! [topo]: struct.Topo.html +//! [dfs]: fn.depth_first_search.html +//! [w]: trait.Walker.html +//! +//! ### Other Graph Traits +//! +//! The traits are rather loosely coupled at the moment (which is intentional, +//! but will develop a bit), and there are traits missing that could be added. +//! +//! Not much is needed to be able to use the visitors on a graph. A graph +//! needs to define [`GraphBase`][gb], [`IntoNeighbors`][in] and +//! [`Visitable`][vis] as a minimum. +//! +//! [gb]: trait.GraphBase.html +//! [in]: trait.IntoNeighbors.html +//! [vis]: trait.Visitable.html +//! +//! ### Graph Trait Implementations +//! +//! The following table lists the traits that are implemented for each graph type: +//! +//! | | Graph | StableGraph | GraphMap | MatrixGraph | Csr | List | +//! | --------------------- | :---: | :---------: | :------: | :---------: | :---: | :---: | +//! | GraphBase | x | x | x | x | x | x | +//! | GraphProp | x | x | x | x | x | x | +//! | NodeCount | x | x | x | x | x | x | +//! | NodeIndexable | x | x | x | x | x | x | +//! | NodeCompactIndexable | x | | x | | x | x | +//! | EdgeCount | x | x | x | x | x | x | +//! | EdgeIndexable | x | x | x | | | | +//! | Data | x | x | x | x | x | x | +//! | IntoNodeIdentifiers | x | x | x | x | x | x | +//! | IntoNodeReferences | x | x | x | x | x | x | +//! | IntoEdgeReferences | x | x | x | x | x | x | +//! | IntoNeighbors | x | x | x | x | x | x | +//! | IntoNeighborsDirected | x | x | x | x | | | +//! | IntoEdges | x | x | x | x | x | x | +//! | IntoEdgesDirected | x | x | x | x | | | +//! | Visitable | x | x | x | x | x | x | +//! | GetAdjacencyMatrix | x | x | x | x | x | x | + +// filter, reversed have their `mod` lines at the end, +// so that they can use the trait template macros +pub use self::filter::*; +pub use self::reversed::*; +pub use self::undirected_adaptor::*; + +#[macro_use] +mod macros; + +mod dfsvisit; +mod traversal; +pub use self::dfsvisit::*; +pub use self::traversal::*; + +use fixedbitset::FixedBitSet; +use std::collections::HashSet; +use std::hash::{BuildHasher, Hash}; + +use super::EdgeType; +use crate::prelude::Direction; + +use crate::graph::IndexType; + +trait_template! { +/// Base graph trait: defines the associated node identifier and +/// edge identifier types. +pub trait GraphBase { + // FIXME: We can drop this escape/nodelegate stuff in Rust 1.18 + @escape [type NodeId] + @escape [type EdgeId] + @section nodelegate + /// edge identifier + type EdgeId: Copy + PartialEq; + /// node identifier + type NodeId: Copy + PartialEq; +} +} + +GraphBase! {delegate_impl []} +GraphBase! {delegate_impl [['a, G], G, &'a mut G, deref]} + +/// A copyable reference to a graph. +pub trait GraphRef: Copy + GraphBase {} + +impl GraphRef for &G where G: GraphBase {} + +trait_template! { +/// Access to the neighbors of each node +/// +/// The neighbors are, depending on the graph’s edge type: +/// +/// - `Directed`: All targets of edges from `a`. +/// - `Undirected`: All other endpoints of edges connected to `a`. +pub trait IntoNeighbors : GraphRef { + @section type + type Neighbors: Iterator; + @section self + /// Return an iterator of the neighbors of node `a`. + fn neighbors(self, a: Self::NodeId) -> Self::Neighbors; +} +} + +IntoNeighbors! {delegate_impl []} + +trait_template! { +/// Access to the neighbors of each node, through incoming or outgoing edges. +/// +/// Depending on the graph’s edge type, the neighbors of a given directionality +/// are: +/// +/// - `Directed`, `Outgoing`: All targets of edges from `a`. +/// - `Directed`, `Incoming`: All sources of edges to `a`. +/// - `Undirected`: All other endpoints of edges connected to `a`. +pub trait IntoNeighborsDirected : IntoNeighbors { + @section type + type NeighborsDirected: Iterator; + @section self + fn neighbors_directed(self, n: Self::NodeId, d: Direction) + -> Self::NeighborsDirected; +} +} + +trait_template! { +/// Access to the edges of each node. +/// +/// The edges are, depending on the graph’s edge type: +/// +/// - `Directed`: All edges from `a`. +/// - `Undirected`: All edges connected to `a`, with `a` being the source of each edge. +/// +/// This is an extended version of the trait `IntoNeighbors`; the former +/// only iterates over the target node identifiers, while this trait +/// yields edge references (trait [`EdgeRef`][er]). +/// +/// [er]: trait.EdgeRef.html +pub trait IntoEdges : IntoEdgeReferences + IntoNeighbors { + @section type + type Edges: Iterator; + @section self + fn edges(self, a: Self::NodeId) -> Self::Edges; +} +} + +IntoEdges! {delegate_impl []} + +trait_template! { +/// Access to all edges of each node, in the specified direction. +/// +/// The edges are, depending on the direction and the graph’s edge type: +/// +/// +/// - `Directed`, `Outgoing`: All edges from `a`. +/// - `Directed`, `Incoming`: All edges to `a`. +/// - `Undirected`, `Outgoing`: All edges connected to `a`, with `a` being the source of each edge. +/// - `Undirected`, `Incoming`: All edges connected to `a`, with `a` being the target of each edge. +/// +/// This is an extended version of the trait `IntoNeighborsDirected`; the former +/// only iterates over the target node identifiers, while this trait +/// yields edge references (trait [`EdgeRef`][er]). +/// +/// [er]: trait.EdgeRef.html +pub trait IntoEdgesDirected : IntoEdges + IntoNeighborsDirected { + @section type + type EdgesDirected: Iterator; + @section self + fn edges_directed(self, a: Self::NodeId, dir: Direction) -> Self::EdgesDirected; +} +} + +IntoEdgesDirected! {delegate_impl []} + +trait_template! { +/// Access to the sequence of the graph’s `NodeId`s. +pub trait IntoNodeIdentifiers : GraphRef { + @section type + type NodeIdentifiers: Iterator; + @section self + fn node_identifiers(self) -> Self::NodeIdentifiers; +} +} + +IntoNodeIdentifiers! {delegate_impl []} +IntoNeighborsDirected! {delegate_impl []} + +trait_template! { +/// Define associated data for nodes and edges +pub trait Data : GraphBase { + @section type + type NodeWeight; + type EdgeWeight; +} +} + +Data! {delegate_impl []} +Data! {delegate_impl [['a, G], G, &'a mut G, deref]} + +/// An edge reference. +/// +/// Edge references are used by traits `IntoEdges` and `IntoEdgeReferences`. +pub trait EdgeRef: Copy { + type NodeId; + type EdgeId; + type Weight; + /// The source node of the edge. + fn source(&self) -> Self::NodeId; + /// The target node of the edge. + fn target(&self) -> Self::NodeId; + /// A reference to the weight of the edge. + fn weight(&self) -> &Self::Weight; + /// The edge’s identifier. + fn id(&self) -> Self::EdgeId; +} + +impl EdgeRef for (N, N, &E) +where + N: Copy, +{ + type NodeId = N; + type EdgeId = (N, N); + type Weight = E; + + fn source(&self) -> N { + self.0 + } + fn target(&self) -> N { + self.1 + } + fn weight(&self) -> &E { + self.2 + } + fn id(&self) -> (N, N) { + (self.0, self.1) + } +} + +/// A node reference. +pub trait NodeRef: Copy { + type NodeId; + type Weight; + fn id(&self) -> Self::NodeId; + fn weight(&self) -> &Self::Weight; +} + +trait_template! { +/// Access to the sequence of the graph’s nodes +pub trait IntoNodeReferences : Data + IntoNodeIdentifiers { + @section type + type NodeRef: NodeRef; + type NodeReferences: Iterator; + @section self + fn node_references(self) -> Self::NodeReferences; +} +} + +IntoNodeReferences! {delegate_impl []} + +impl NodeRef for (Id, ()) +where + Id: Copy, +{ + type NodeId = Id; + type Weight = (); + fn id(&self) -> Self::NodeId { + self.0 + } + fn weight(&self) -> &Self::Weight { + static DUMMY: () = (); + &DUMMY + } +} + +impl NodeRef for (Id, &W) +where + Id: Copy, +{ + type NodeId = Id; + type Weight = W; + fn id(&self) -> Self::NodeId { + self.0 + } + fn weight(&self) -> &Self::Weight { + self.1 + } +} + +trait_template! { +/// Access to the sequence of the graph’s edges +pub trait IntoEdgeReferences : Data + GraphRef { + @section type + type EdgeRef: EdgeRef; + type EdgeReferences: Iterator; + @section self + fn edge_references(self) -> Self::EdgeReferences; +} +} + +IntoEdgeReferences! {delegate_impl [] } + +trait_template! { + /// Edge kind property (directed or undirected edges) +pub trait GraphProp : GraphBase { + @section type + /// The kind of edges in the graph. + type EdgeType: EdgeType; + + @section nodelegate + fn is_directed(&self) -> bool { + ::is_directed() + } +} +} + +GraphProp! {delegate_impl []} + +trait_template! { + /// The graph’s `NodeId`s map to indices + #[allow(clippy::needless_arbitrary_self_type)] + pub trait NodeIndexable : GraphBase { + @section self + /// Return an upper bound of the node indices in the graph + /// (suitable for the size of a bitmap). + fn node_bound(self: &Self) -> usize; + /// Convert `a` to an integer index. + fn to_index(self: &Self, a: Self::NodeId) -> usize; + /// Convert `i` to a node index. `i` must be a valid value in the graph. + fn from_index(self: &Self, i: usize) -> Self::NodeId; + } +} + +NodeIndexable! {delegate_impl []} + +trait_template! { + /// The graph’s `NodeId`s map to indices + #[allow(clippy::needless_arbitrary_self_type)] + pub trait EdgeIndexable : GraphBase { + @section self + /// Return an upper bound of the edge indices in the graph + /// (suitable for the size of a bitmap). + fn edge_bound(self: &Self) -> usize; + /// Convert `a` to an integer index. + fn to_index(self: &Self, a: Self::EdgeId) -> usize; + /// Convert `i` to an edge index. `i` must be a valid value in the graph. + fn from_index(self: &Self, i: usize) -> Self::EdgeId; + } +} + +EdgeIndexable! {delegate_impl []} + +trait_template! { +/// A graph with a known node count. +#[allow(clippy::needless_arbitrary_self_type)] +pub trait NodeCount : GraphBase { + @section self + fn node_count(self: &Self) -> usize; +} +} + +NodeCount! {delegate_impl []} + +trait_template! { +/// The graph’s `NodeId`s map to indices, in a range without holes. +/// +/// The graph's node identifiers correspond to exactly the indices +/// `0..self.node_bound()`. +pub trait NodeCompactIndexable : NodeIndexable + NodeCount { } +} + +NodeCompactIndexable! {delegate_impl []} + +/// A mapping for storing the visited status for NodeId `N`. +pub trait VisitMap { + /// Mark `a` as visited. + /// + /// Return **true** if this is the first visit, false otherwise. + fn visit(&mut self, a: N) -> bool; + + /// Return whether `a` has been visited before. + fn is_visited(&self, a: &N) -> bool; +} + +impl VisitMap for FixedBitSet +where + Ix: IndexType, +{ + fn visit(&mut self, x: Ix) -> bool { + !self.put(x.index()) + } + fn is_visited(&self, x: &Ix) -> bool { + self.contains(x.index()) + } +} + +impl VisitMap for HashSet +where + N: Hash + Eq, + S: BuildHasher, +{ + fn visit(&mut self, x: N) -> bool { + self.insert(x) + } + fn is_visited(&self, x: &N) -> bool { + self.contains(x) + } +} + +trait_template! { +/// A graph that can create a map that tracks the visited status of its nodes. +#[allow(clippy::needless_arbitrary_self_type)] +pub trait Visitable : GraphBase { + @section type + /// The associated map type + type Map: VisitMap; + @section self + /// Create a new visitor map + fn visit_map(self: &Self) -> Self::Map; + /// Reset the visitor map (and resize to new size of graph if needed) + fn reset_map(self: &Self, map: &mut Self::Map); +} +} +Visitable! {delegate_impl []} + +trait_template! { +/// Create or access the adjacency matrix of a graph. +/// +/// The implementor can either create an adjacency matrix, or it can return +/// a placeholder if it has the needed representation internally. +#[allow(clippy::needless_arbitrary_self_type)] +pub trait GetAdjacencyMatrix : GraphBase { + @section type + /// The associated adjacency matrix type + type AdjMatrix; + @section self + /// Create the adjacency matrix + fn adjacency_matrix(self: &Self) -> Self::AdjMatrix; + /// Return true if there is an edge from `a` to `b`, false otherwise. + /// + /// Computes in O(1) time. + fn is_adjacent(self: &Self, matrix: &Self::AdjMatrix, a: Self::NodeId, b: Self::NodeId) -> bool; +} +} + +GetAdjacencyMatrix! {delegate_impl []} + +trait_template! { +/// A graph with a known edge count. +#[allow(clippy::needless_arbitrary_self_type)] +pub trait EdgeCount : GraphBase { + @section self + /// Return the number of edges in the graph. + fn edge_count(self: &Self) -> usize; +} +} + +EdgeCount! {delegate_impl []} + +mod filter; +mod reversed; +mod undirected_adaptor; diff --git a/vendor/petgraph/src/visit/reversed.rs b/vendor/petgraph/src/visit/reversed.rs new file mode 100644 index 00000000..4c0b89c8 --- /dev/null +++ b/vendor/petgraph/src/visit/reversed.rs @@ -0,0 +1,184 @@ +use crate::{Direction, Incoming}; + +use crate::visit::{ + Data, EdgeCount, EdgeIndexable, EdgeRef, GetAdjacencyMatrix, GraphBase, GraphProp, GraphRef, + IntoEdgeReferences, IntoEdges, IntoEdgesDirected, IntoNeighbors, IntoNeighborsDirected, + IntoNodeIdentifiers, IntoNodeReferences, NodeCompactIndexable, NodeCount, NodeIndexable, + Visitable, +}; + +/// An edge-reversing graph adaptor. +/// +/// All edges have the opposite direction with `Reversed`. +#[derive(Copy, Clone, Debug)] +pub struct Reversed(pub G); + +impl GraphBase for Reversed { + type NodeId = G::NodeId; + type EdgeId = G::EdgeId; +} + +impl GraphRef for Reversed {} + +Data! {delegate_impl [[G], G, Reversed, access0]} + +impl IntoNeighbors for Reversed +where + G: IntoNeighborsDirected, +{ + type Neighbors = G::NeighborsDirected; + fn neighbors(self, n: G::NodeId) -> G::NeighborsDirected { + self.0.neighbors_directed(n, Incoming) + } +} + +impl IntoNeighborsDirected for Reversed +where + G: IntoNeighborsDirected, +{ + type NeighborsDirected = G::NeighborsDirected; + fn neighbors_directed(self, n: G::NodeId, d: Direction) -> G::NeighborsDirected { + self.0.neighbors_directed(n, d.opposite()) + } +} + +impl IntoEdges for Reversed +where + G: IntoEdgesDirected, +{ + type Edges = ReversedEdges; + fn edges(self, a: Self::NodeId) -> Self::Edges { + ReversedEdges { + iter: self.0.edges_directed(a, Incoming), + } + } +} + +impl IntoEdgesDirected for Reversed +where + G: IntoEdgesDirected, +{ + type EdgesDirected = ReversedEdges; + fn edges_directed(self, a: Self::NodeId, dir: Direction) -> Self::Edges { + ReversedEdges { + iter: self.0.edges_directed(a, dir.opposite()), + } + } +} + +impl Visitable for Reversed { + type Map = G::Map; + fn visit_map(&self) -> G::Map { + self.0.visit_map() + } + fn reset_map(&self, map: &mut Self::Map) { + self.0.reset_map(map); + } +} + +/// A reversed edges iterator. +#[derive(Debug, Clone)] +pub struct ReversedEdges { + iter: I, +} + +impl Iterator for ReversedEdges +where + I: Iterator, + I::Item: EdgeRef, +{ + type Item = ReversedEdgeReference; + fn next(&mut self) -> Option { + self.iter.next().map(ReversedEdgeReference) + } + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +/// A reversed edge reference +#[derive(Copy, Clone, Debug)] +pub struct ReversedEdgeReference(R); + +impl ReversedEdgeReference { + /// Return the original, unreversed edge reference. + pub fn as_unreversed(&self) -> &R { + &self.0 + } + + /// Consume `self` and return the original, unreversed edge reference. + pub fn into_unreversed(self) -> R { + self.0 + } +} + +/// An edge reference +impl EdgeRef for ReversedEdgeReference +where + R: EdgeRef, +{ + type NodeId = R::NodeId; + type EdgeId = R::EdgeId; + type Weight = R::Weight; + fn source(&self) -> Self::NodeId { + self.0.target() + } + fn target(&self) -> Self::NodeId { + self.0.source() + } + fn weight(&self) -> &Self::Weight { + self.0.weight() + } + fn id(&self) -> Self::EdgeId { + self.0.id() + } +} + +impl IntoEdgeReferences for Reversed +where + G: IntoEdgeReferences, +{ + type EdgeRef = ReversedEdgeReference; + type EdgeReferences = ReversedEdgeReferences; + fn edge_references(self) -> Self::EdgeReferences { + ReversedEdgeReferences { + iter: self.0.edge_references(), + } + } +} + +/// A reversed edge references iterator. +#[derive(Debug, Clone)] +pub struct ReversedEdgeReferences { + iter: I, +} + +impl Iterator for ReversedEdgeReferences +where + I: Iterator, + I::Item: EdgeRef, +{ + type Item = ReversedEdgeReference; + fn next(&mut self) -> Option { + self.iter.next().map(ReversedEdgeReference) + } + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +macro_rules! access0 { + ($e:expr) => { + $e.0 + }; +} + +NodeIndexable! {delegate_impl [[G], G, Reversed, access0]} +NodeCompactIndexable! {delegate_impl [[G], G, Reversed, access0]} +IntoNodeIdentifiers! {delegate_impl [[G], G, Reversed, access0]} +IntoNodeReferences! {delegate_impl [[G], G, Reversed, access0]} +GraphProp! {delegate_impl [[G], G, Reversed, access0]} +NodeCount! {delegate_impl [[G], G, Reversed, access0]} +EdgeCount! {delegate_impl [[G], G, Reversed, access0]} +EdgeIndexable! {delegate_impl [[G], G, Reversed, access0]} +GetAdjacencyMatrix! {delegate_impl [[G], G, Reversed, access0]} diff --git a/vendor/petgraph/src/visit/traversal.rs b/vendor/petgraph/src/visit/traversal.rs new file mode 100644 index 00000000..f1f434a7 --- /dev/null +++ b/vendor/petgraph/src/visit/traversal.rs @@ -0,0 +1,536 @@ +use super::{GraphRef, IntoNodeIdentifiers, Reversed}; +use super::{IntoNeighbors, IntoNeighborsDirected, VisitMap, Visitable}; +use crate::Incoming; +use std::collections::VecDeque; + +/// Visit nodes of a graph in a depth-first-search (DFS) emitting nodes in +/// preorder (when they are first discovered). +/// +/// The traversal starts at a given node and only traverses nodes reachable +/// from it. +/// +/// `Dfs` is not recursive. +/// +/// `Dfs` does not itself borrow the graph, and because of this you can run +/// a traversal over a graph while still retaining mutable access to it, if you +/// use it like the following example: +/// +/// ``` +/// use petgraph::Graph; +/// use petgraph::visit::Dfs; +/// +/// let mut graph = Graph::<_,()>::new(); +/// let a = graph.add_node(0); +/// +/// let mut dfs = Dfs::new(&graph, a); +/// while let Some(nx) = dfs.next(&graph) { +/// // we can access `graph` mutably here still +/// graph[nx] += 1; +/// } +/// +/// assert_eq!(graph[a], 1); +/// ``` +/// +/// **Note:** The algorithm may not behave correctly if nodes are removed +/// during iteration. It may not necessarily visit added nodes or edges. +#[derive(Clone, Debug)] +pub struct Dfs { + /// The stack of nodes to visit + pub stack: Vec, + /// The map of discovered nodes + pub discovered: VM, +} + +impl Default for Dfs +where + VM: Default, +{ + fn default() -> Self { + Dfs { + stack: Vec::new(), + discovered: VM::default(), + } + } +} + +impl Dfs +where + N: Copy + PartialEq, + VM: VisitMap, +{ + /// Create a new **Dfs**, using the graph's visitor map, and put **start** + /// in the stack of nodes to visit. + pub fn new(graph: G, start: N) -> Self + where + G: GraphRef + Visitable, + { + let mut dfs = Dfs::empty(graph); + dfs.move_to(start); + dfs + } + + /// Create a `Dfs` from a vector and a visit map + pub fn from_parts(stack: Vec, discovered: VM) -> Self { + Dfs { stack, discovered } + } + + /// Clear the visit state + pub fn reset(&mut self, graph: G) + where + G: GraphRef + Visitable, + { + graph.reset_map(&mut self.discovered); + self.stack.clear(); + } + + /// Create a new **Dfs** using the graph's visitor map, and no stack. + pub fn empty(graph: G) -> Self + where + G: GraphRef + Visitable, + { + Dfs { + stack: Vec::new(), + discovered: graph.visit_map(), + } + } + + /// Keep the discovered map, but clear the visit stack and restart + /// the dfs from a particular node. + pub fn move_to(&mut self, start: N) { + self.stack.clear(); + self.stack.push(start); + } + + /// Return the next node in the dfs, or **None** if the traversal is done. + pub fn next(&mut self, graph: G) -> Option + where + G: IntoNeighbors, + { + while let Some(node) = self.stack.pop() { + if self.discovered.visit(node) { + for succ in graph.neighbors(node) { + if !self.discovered.is_visited(&succ) { + self.stack.push(succ); + } + } + return Some(node); + } + } + None + } +} + +/// Visit nodes in a depth-first-search (DFS) emitting nodes in postorder +/// (each node after all its descendants have been emitted). +/// +/// `DfsPostOrder` is not recursive. +/// +/// The traversal starts at a given node and only traverses nodes reachable +/// from it. +#[derive(Clone, Debug)] +pub struct DfsPostOrder { + /// The stack of nodes to visit + pub stack: Vec, + /// The map of discovered nodes + pub discovered: VM, + /// The map of finished nodes + pub finished: VM, +} + +impl Default for DfsPostOrder +where + VM: Default, +{ + fn default() -> Self { + DfsPostOrder { + stack: Vec::new(), + discovered: VM::default(), + finished: VM::default(), + } + } +} + +impl DfsPostOrder +where + N: Copy + PartialEq, + VM: VisitMap, +{ + /// Create a new `DfsPostOrder` using the graph's visitor map, and put + /// `start` in the stack of nodes to visit. + pub fn new(graph: G, start: N) -> Self + where + G: GraphRef + Visitable, + { + let mut dfs = Self::empty(graph); + dfs.move_to(start); + dfs + } + + /// Create a new `DfsPostOrder` using the graph's visitor map, and no stack. + pub fn empty(graph: G) -> Self + where + G: GraphRef + Visitable, + { + DfsPostOrder { + stack: Vec::new(), + discovered: graph.visit_map(), + finished: graph.visit_map(), + } + } + + /// Clear the visit state + pub fn reset(&mut self, graph: G) + where + G: GraphRef + Visitable, + { + graph.reset_map(&mut self.discovered); + graph.reset_map(&mut self.finished); + self.stack.clear(); + } + + /// Keep the discovered and finished map, but clear the visit stack and restart + /// the dfs from a particular node. + pub fn move_to(&mut self, start: N) { + self.stack.clear(); + self.stack.push(start); + } + + /// Return the next node in the traversal, or `None` if the traversal is done. + pub fn next(&mut self, graph: G) -> Option + where + G: IntoNeighbors, + { + while let Some(&nx) = self.stack.last() { + if self.discovered.visit(nx) { + // First time visiting `nx`: Push neighbors, don't pop `nx` + for succ in graph.neighbors(nx) { + if !self.discovered.is_visited(&succ) { + self.stack.push(succ); + } + } + } else { + self.stack.pop(); + if self.finished.visit(nx) { + // Second time: All reachable nodes must have been finished + return Some(nx); + } + } + } + None + } +} + +/// A breadth first search (BFS) of a graph. +/// +/// The traversal starts at a given node and only traverses nodes reachable +/// from it. +/// +/// `Bfs` is not recursive. +/// +/// `Bfs` does not itself borrow the graph, and because of this you can run +/// a traversal over a graph while still retaining mutable access to it, if you +/// use it like the following example: +/// +/// ``` +/// use petgraph::Graph; +/// use petgraph::visit::Bfs; +/// +/// let mut graph = Graph::<_,()>::new(); +/// let a = graph.add_node(0); +/// +/// let mut bfs = Bfs::new(&graph, a); +/// while let Some(nx) = bfs.next(&graph) { +/// // we can access `graph` mutably here still +/// graph[nx] += 1; +/// } +/// +/// assert_eq!(graph[a], 1); +/// ``` +/// +/// **Note:** The algorithm may not behave correctly if nodes are removed +/// during iteration. It may not necessarily visit added nodes or edges. +#[derive(Clone)] +pub struct Bfs { + /// The queue of nodes to visit + pub stack: VecDeque, + /// The map of discovered nodes + pub discovered: VM, +} + +impl Default for Bfs +where + VM: Default, +{ + fn default() -> Self { + Bfs { + stack: VecDeque::new(), + discovered: VM::default(), + } + } +} + +impl Bfs +where + N: Copy + PartialEq, + VM: VisitMap, +{ + /// Create a new **Bfs**, using the graph's visitor map, and put **start** + /// in the stack of nodes to visit. + pub fn new(graph: G, start: N) -> Self + where + G: GraphRef + Visitable, + { + let mut discovered = graph.visit_map(); + discovered.visit(start); + let mut stack = VecDeque::new(); + stack.push_front(start); + Bfs { stack, discovered } + } + + /// Return the next node in the bfs, or **None** if the traversal is done. + pub fn next(&mut self, graph: G) -> Option + where + G: IntoNeighbors, + { + if let Some(node) = self.stack.pop_front() { + for succ in graph.neighbors(node) { + if self.discovered.visit(succ) { + self.stack.push_back(succ); + } + } + + return Some(node); + } + None + } +} + +/// A topological order traversal for a graph. +/// +/// **Note** that `Topo` only visits nodes that are not part of cycles, +/// i.e. nodes in a true DAG. Use other visitors like `DfsPostOrder` or +/// algorithms like kosaraju_scc to handle graphs with possible cycles. +#[derive(Clone)] +pub struct Topo { + tovisit: Vec, + ordered: VM, +} + +impl Default for Topo +where + VM: Default, +{ + fn default() -> Self { + Topo { + tovisit: Vec::new(), + ordered: VM::default(), + } + } +} + +impl Topo +where + N: Copy + PartialEq, + VM: VisitMap, +{ + /// Create a new `Topo`, using the graph's visitor map, and put all + /// initial nodes in the to visit list. + pub fn new(graph: G) -> Self + where + G: IntoNodeIdentifiers + IntoNeighborsDirected + Visitable, + { + let mut topo = Self::empty(graph); + topo.extend_with_initials(graph); + topo + } + + /// Create a new `Topo` with initial nodes. + /// + /// Nodes with incoming edges are ignored. + pub fn with_initials(graph: G, initials: I) -> Self + where + G: IntoNeighborsDirected + Visitable, + I: IntoIterator, + { + Topo { + tovisit: initials + .into_iter() + .filter(|&n| graph.neighbors_directed(n, Incoming).next().is_none()) + .collect(), + ordered: graph.visit_map(), + } + } + + fn extend_with_initials(&mut self, g: G) + where + G: IntoNodeIdentifiers + IntoNeighborsDirected, + { + // find all initial nodes (nodes without incoming edges) + self.tovisit.extend( + g.node_identifiers() + .filter(move |&a| g.neighbors_directed(a, Incoming).next().is_none()), + ); + } + + /* Private until it has a use */ + /// Create a new `Topo`, using the graph's visitor map with *no* starting + /// index specified. + fn empty(graph: G) -> Self + where + G: GraphRef + Visitable, + { + Topo { + ordered: graph.visit_map(), + tovisit: Vec::new(), + } + } + + /// Clear visited state, and put all initial nodes in the to visit list. + pub fn reset(&mut self, graph: G) + where + G: IntoNodeIdentifiers + IntoNeighborsDirected + Visitable, + { + graph.reset_map(&mut self.ordered); + self.tovisit.clear(); + self.extend_with_initials(graph); + } + + /// Return the next node in the current topological order traversal, or + /// `None` if the traversal is at the end. + /// + /// *Note:* The graph may not have a complete topological order, and the only + /// way to know is to run the whole traversal and make sure it visits every node. + pub fn next(&mut self, g: G) -> Option + where + G: IntoNeighborsDirected + Visitable, + { + // Take an unvisited element and find which of its neighbors are next + while let Some(nix) = self.tovisit.pop() { + if self.ordered.is_visited(&nix) { + continue; + } + self.ordered.visit(nix); + for neigh in g.neighbors(nix) { + // Look at each neighbor, and those that only have incoming edges + // from the already ordered list, they are the next to visit. + if Reversed(g) + .neighbors(neigh) + .all(|b| self.ordered.is_visited(&b)) + { + self.tovisit.push(neigh); + } + } + return Some(nix); + } + None + } +} + +/// A walker is a traversal state, but where part of the traversal +/// information is supplied manually to each next call. +/// +/// This for example allows graph traversals that don't hold a borrow of the +/// graph they are traversing. +pub trait Walker { + type Item; + /// Advance to the next item + fn walk_next(&mut self, context: Context) -> Option; + + /// Create an iterator out of the walker and given `context`. + fn iter(self, context: Context) -> WalkerIter + where + Self: Sized, + Context: Clone, + { + WalkerIter { + walker: self, + context, + } + } +} + +/// A walker and its context wrapped into an iterator. +#[derive(Clone, Debug)] +pub struct WalkerIter { + walker: W, + context: C, +} + +impl WalkerIter +where + W: Walker, + C: Clone, +{ + pub fn context(&self) -> C { + self.context.clone() + } + + pub fn inner_ref(&self) -> &W { + &self.walker + } + + pub fn inner_mut(&mut self) -> &mut W { + &mut self.walker + } +} + +impl Iterator for WalkerIter +where + W: Walker, + C: Clone, +{ + type Item = W::Item; + fn next(&mut self) -> Option { + self.walker.walk_next(self.context.clone()) + } +} + +impl Walker for &mut W +where + W: Walker, +{ + type Item = W::Item; + fn walk_next(&mut self, context: C) -> Option { + (**self).walk_next(context) + } +} + +impl Walker for Dfs +where + G: IntoNeighbors + Visitable, +{ + type Item = G::NodeId; + fn walk_next(&mut self, context: G) -> Option { + self.next(context) + } +} + +impl Walker for DfsPostOrder +where + G: IntoNeighbors + Visitable, +{ + type Item = G::NodeId; + fn walk_next(&mut self, context: G) -> Option { + self.next(context) + } +} + +impl Walker for Bfs +where + G: IntoNeighbors + Visitable, +{ + type Item = G::NodeId; + fn walk_next(&mut self, context: G) -> Option { + self.next(context) + } +} + +impl Walker for Topo +where + G: IntoNeighborsDirected + Visitable, +{ + type Item = G::NodeId; + fn walk_next(&mut self, context: G) -> Option { + self.next(context) + } +} diff --git a/vendor/petgraph/src/visit/undirected_adaptor.rs b/vendor/petgraph/src/visit/undirected_adaptor.rs new file mode 100644 index 00000000..ee7e21e0 --- /dev/null +++ b/vendor/petgraph/src/visit/undirected_adaptor.rs @@ -0,0 +1,111 @@ +use crate::visit::{ + Data, GraphBase, GraphProp, GraphRef, IntoEdgeReferences, IntoEdges, IntoEdgesDirected, + IntoNeighbors, IntoNeighborsDirected, IntoNodeIdentifiers, IntoNodeReferences, + NodeCompactIndexable, NodeCount, NodeIndexable, Visitable, +}; +use crate::Direction; + +/// An edge direction removing graph adaptor. +#[derive(Copy, Clone, Debug)] +pub struct UndirectedAdaptor(pub G); + +impl GraphRef for UndirectedAdaptor {} + +impl IntoNeighbors for UndirectedAdaptor +where + G: IntoNeighborsDirected, +{ + type Neighbors = std::iter::Chain; + fn neighbors(self, n: G::NodeId) -> Self::Neighbors { + self.0 + .neighbors_directed(n, Direction::Incoming) + .chain(self.0.neighbors_directed(n, Direction::Outgoing)) + } +} + +impl IntoEdges for UndirectedAdaptor +where + G: IntoEdgesDirected, +{ + type Edges = std::iter::Chain; + fn edges(self, a: Self::NodeId) -> Self::Edges { + self.0 + .edges_directed(a, Direction::Incoming) + .chain(self.0.edges_directed(a, Direction::Outgoing)) + } +} + +impl GraphProp for UndirectedAdaptor +where + G: GraphBase, +{ + type EdgeType = crate::Undirected; + + fn is_directed(&self) -> bool { + false + } +} + +macro_rules! access0 { + ($e:expr) => { + $e.0 + }; +} + +GraphBase! {delegate_impl [[G], G, UndirectedAdaptor, access0]} +Data! {delegate_impl [[G], G, UndirectedAdaptor, access0]} +IntoEdgeReferences! {delegate_impl [[G], G, UndirectedAdaptor, access0]} +Visitable! {delegate_impl [[G], G, UndirectedAdaptor, access0]} +NodeIndexable! {delegate_impl [[G], G, UndirectedAdaptor, access0]} +NodeCompactIndexable! {delegate_impl [[G], G, UndirectedAdaptor, access0]} +IntoNodeIdentifiers! {delegate_impl [[G], G, UndirectedAdaptor, access0]} +IntoNodeReferences! {delegate_impl [[G], G, UndirectedAdaptor, access0]} +NodeCount! {delegate_impl [[G], G, UndirectedAdaptor, access0]} + +#[cfg(test)] +mod tests { + use super::*; + use crate::graph::{DiGraph, Graph}; + use crate::visit::Dfs; + + static LINEAR_EDGES: [(u32, u32); 5] = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]; + + #[test] + pub fn test_is_reachable() { + // create a linear digraph, choose a node in the centre and check all nodes are visited + // by a dfs + + let graph = DiGraph::<(), ()>::from_edges(&LINEAR_EDGES); + + let mut nodes = graph.node_identifiers().collect::>(); + nodes.sort(); + + let graph = UndirectedAdaptor(&graph); + + use crate::visit::Walker; + let mut visited_nodes: Vec<_> = Dfs::new(&graph, nodes[2]).iter(&graph).collect(); + visited_nodes.sort(); + assert_eq!(visited_nodes, nodes); + } + + #[test] + pub fn test_neighbors_count() { + { + let graph = Graph::<(), ()>::from_edges(&LINEAR_EDGES); + let graph = UndirectedAdaptor(&graph); + + let mut nodes = graph.node_identifiers().collect::>(); + nodes.sort(); + assert_eq!(graph.neighbors(nodes[1]).count(), 2); + } + + { + let graph = Graph::<(), ()>::from_edges(&LINEAR_EDGES); + let graph = UndirectedAdaptor(&graph); + + let mut nodes = graph.node_identifiers().collect::>(); + nodes.sort(); + assert_eq!(graph.neighbors(nodes[1]).count(), 2); + } + } +} -- cgit v1.2.3