summaryrefslogtreecommitdiff
path: root/vendor/petgraph/src
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-02 18:36:06 -0600
committermo khan <mo@mokhan.ca>2025-07-02 18:36:06 -0600
commit8cdfa445d6629ffef4cb84967ff7017654045bc2 (patch)
tree22f0b0907c024c78d26a731e2e1f5219407d8102 /vendor/petgraph/src
parent4351c74c7c5f97156bc94d3a8549b9940ac80e3f (diff)
chore: add vendor directory
Diffstat (limited to 'vendor/petgraph/src')
-rw-r--r--vendor/petgraph/src/acyclic.rs867
-rw-r--r--vendor/petgraph/src/acyclic/order_map.rs193
-rw-r--r--vendor/petgraph/src/adj.rs653
-rw-r--r--vendor/petgraph/src/algo/astar.rs178
-rw-r--r--vendor/petgraph/src/algo/bellman_ford.rs244
-rw-r--r--vendor/petgraph/src/algo/coloring.rs96
-rw-r--r--vendor/petgraph/src/algo/dijkstra.rs122
-rw-r--r--vendor/petgraph/src/algo/dominators.rs333
-rw-r--r--vendor/petgraph/src/algo/feedback_arc_set.rs449
-rw-r--r--vendor/petgraph/src/algo/floyd_warshall.rs143
-rw-r--r--vendor/petgraph/src/algo/ford_fulkerson.rs196
-rw-r--r--vendor/petgraph/src/algo/isomorphism.rs994
-rw-r--r--vendor/petgraph/src/algo/k_shortest_path.rs115
-rw-r--r--vendor/petgraph/src/algo/matching.rs606
-rw-r--r--vendor/petgraph/src/algo/min_spanning_tree.rs117
-rw-r--r--vendor/petgraph/src/algo/mod.rs867
-rw-r--r--vendor/petgraph/src/algo/page_rank.rs185
-rw-r--r--vendor/petgraph/src/algo/simple_paths.rs199
-rw-r--r--vendor/petgraph/src/algo/tred.rs162
-rw-r--r--vendor/petgraph/src/csr.rs1151
-rw-r--r--vendor/petgraph/src/data.rs478
-rw-r--r--vendor/petgraph/src/dot.rs371
-rw-r--r--vendor/petgraph/src/generate.rs133
-rw-r--r--vendor/petgraph/src/graph6/graph6_decoder.rs200
-rw-r--r--vendor/petgraph/src/graph6/graph6_encoder.rs154
-rw-r--r--vendor/petgraph/src/graph6/mod.rs7
-rw-r--r--vendor/petgraph/src/graph_impl/frozen.rs108
-rw-r--r--vendor/petgraph/src/graph_impl/mod.rs2411
-rw-r--r--vendor/petgraph/src/graph_impl/serialization.rs355
-rw-r--r--vendor/petgraph/src/graph_impl/stable_graph/mod.rs2103
-rw-r--r--vendor/petgraph/src/graph_impl/stable_graph/serialization.rs298
-rw-r--r--vendor/petgraph/src/graphmap.rs1504
-rw-r--r--vendor/petgraph/src/iter_format.rs102
-rw-r--r--vendor/petgraph/src/iter_utils.rs32
-rw-r--r--vendor/petgraph/src/lib.rs305
-rw-r--r--vendor/petgraph/src/macros.rs108
-rw-r--r--vendor/petgraph/src/matrix_graph.rs1814
-rw-r--r--vendor/petgraph/src/operator.rs83
-rw-r--r--vendor/petgraph/src/prelude.rs21
-rw-r--r--vendor/petgraph/src/quickcheck.rs216
-rw-r--r--vendor/petgraph/src/scored.rs93
-rw-r--r--vendor/petgraph/src/serde_utils.rs95
-rw-r--r--vendor/petgraph/src/traits_graph.rs73
-rw-r--r--vendor/petgraph/src/unionfind.rs146
-rw-r--r--vendor/petgraph/src/util.rs16
-rw-r--r--vendor/petgraph/src/visit/dfsvisit.rs314
-rw-r--r--vendor/petgraph/src/visit/filter.rs583
-rw-r--r--vendor/petgraph/src/visit/macros.rs135
-rw-r--r--vendor/petgraph/src/visit/mod.rs481
-rw-r--r--vendor/petgraph/src/visit/reversed.rs184
-rw-r--r--vendor/petgraph/src/visit/traversal.rs536
-rw-r--r--vendor/petgraph/src/visit/undirected_adaptor.rs111
52 files changed, 21440 insertions, 0 deletions
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<G: Visitable> {
+ /// The underlying graph, accessible through the `inner` method.
+ graph: G,
+ /// The current topological order of the nodes.
+ order_map: OrderMap<G::NodeId>,
+
+ // 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<FixedBitSet>,
+ /// Helper map for DFS tracking finished nodes.
+ finished: RefCell<FixedBitSet>,
+}
+
+/// An error that can occur during edge addition for acyclic graphs.
+#[derive(Clone, Debug, PartialEq)]
+pub enum AcyclicEdgeError<N> {
+ /// The edge would create a cycle.
+ Cycle(Cycle<N>),
+ /// The edge would create a self-loop.
+ SelfLoop,
+ /// Could not successfully add the edge to the underlying graph.
+ InvalidEdge,
+}
+
+impl<N> From<Cycle<N>> for AcyclicEdgeError<N> {
+ fn from(cycle: Cycle<N>) -> Self {
+ AcyclicEdgeError::Cycle(cycle)
+ }
+}
+
+impl<G: Visitable> Acyclic<G> {
+ /// 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<Item = G::NodeId> + '_ {
+ 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<TopologicalPosition> + 'r,
+ ) -> impl Iterator<Item = G::NodeId> + '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<G: Visitable + NodeIndexable> Acyclic<G>
+where
+ for<'a> &'a G: IntoNeighborsDirected + IntoNodeIdentifiers + GraphBase<NodeId = G::NodeId>,
+{
+ /// 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<Self, Cycle<G::NodeId>> {
+ 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<G::EdgeId, AcyclicEdgeError<G::NodeId>>
+ 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<G::EdgeId, AcyclicEdgeError<G::NodeId>>
+ 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<G::NodeId>>
+ 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<TopologicalPosition, G::NodeId>,
+ BTreeMap<TopologicalPosition, G::NodeId>,
+ ),
+ Cycle<G::NodeId>,
+ >
+ 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<TopologicalPosition, G::NodeId>,
+ ) -> Result<(), Cycle<G::NodeId>>
+ 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<TopologicalPosition, G::NodeId>,
+ ) -> Result<(), Cycle<G::NodeId>>
+ 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<G: Visitable> GraphBase for Acyclic<G> {
+ type NodeId = G::NodeId;
+ type EdgeId = G::EdgeId;
+}
+
+impl<G: Default + Visitable> Default for Acyclic<G> {
+ 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<G: Build + Visitable + NodeIndexable> Build for Acyclic<G>
+where
+ for<'a> &'a G: IntoNeighborsDirected
+ + IntoNodeIdentifiers
+ + Visitable<Map = G::Map>
+ + GraphBase<NodeId = G::NodeId>,
+ 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::EdgeId> {
+ 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<G: Create + Visitable + NodeIndexable> Create for Acyclic<G>
+where
+ for<'a> &'a G: IntoNeighborsDirected
+ + IntoNodeIdentifiers
+ + Visitable<Map = G::Map>
+ + GraphBase<NodeId = G::NodeId>,
+ 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<G: Visitable> Deref for Acyclic<G> {
+ 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<G: NodeIndexable + IntoNeighborsDirected + IntoNodeIdentifiers + Visitable>(
+ graph: G,
+ start: G::NodeId,
+ order_map: &OrderMap<G::NodeId>,
+ // 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<bool, Cycle<G::NodeId>>,
+ res: &mut BTreeMap<TopologicalPosition, G::NodeId>,
+ discovered: &mut FixedBitSet,
+ finished: &mut FixedBitSet,
+) -> Result<(), Cycle<G::NodeId>>
+where
+ G::NodeId: IndexType,
+{
+ dfs_visitor(
+ graph,
+ start,
+ &mut |ev| -> Result<Control<()>, Cycle<G::NodeId>> {
+ 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<G: Visitable + Data> Data for Acyclic<G> {
+ type NodeWeight = G::NodeWeight;
+ type EdgeWeight = G::EdgeWeight;
+}
+
+impl<G: Visitable + DataMap> DataMap for Acyclic<G> {
+ 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<G: Visitable + DataMapMut> DataMapMut for Acyclic<G> {
+ 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<G: Visitable + EdgeCount> EdgeCount for Acyclic<G> {
+ fn edge_count(&self) -> usize {
+ self.inner().edge_count()
+ }
+}
+
+impl<G: Visitable + EdgeIndexable> EdgeIndexable for Acyclic<G> {
+ 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<G: Visitable + GetAdjacencyMatrix> GetAdjacencyMatrix for Acyclic<G> {
+ 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<G: Visitable + GraphProp> GraphProp for Acyclic<G> {
+ type EdgeType = G::EdgeType;
+}
+
+impl<G: Visitable + NodeCompactIndexable> NodeCompactIndexable for Acyclic<G> {}
+
+impl<G: Visitable + NodeCount> NodeCount for Acyclic<G> {
+ fn node_count(&self) -> usize {
+ self.inner().node_count()
+ }
+}
+
+impl<G: Visitable + NodeIndexable> NodeIndexable for Acyclic<G> {
+ 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<G: Visitable> Visitable for Acyclic<G> {
+ 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<N, E, Ix: IndexType> Acyclic<$graph_type<N, E, Ix>> {
+ /// 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<N, E, Ix> as GraphBase>::EdgeId,
+ ) -> Option<E> {
+ 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<N, E, Ix> as GraphBase>::NodeId,
+ ) -> Option<N> {
+ self.order_map.remove_node(n, &self.graph);
+ self.graph.remove_node(n)
+ }
+ }
+
+ impl<N, E, Ix: IndexType> TryFrom<$graph_type<N, E, Ix>>
+ for Acyclic<$graph_type<N, E, Ix>>
+ {
+ type Error = Cycle<NodeIndex<Ix>>;
+
+ fn try_from(graph: $graph_type<N, E, Ix>) -> Result<Self, Self::Error> {
+ 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<N, E, Ix>> {
+ type EdgeRef = <&'a $graph_type<N, E, Ix> as IntoEdgeReferences>::EdgeRef;
+ type EdgeReferences = <&'a $graph_type<N, E, Ix> 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<N, E, Ix>> {
+ type Edges = <&'a $graph_type<N, E, Ix> 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<N, E, Ix>> {
+ type EdgesDirected = <&'a $graph_type<N, E, Ix> 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<N, E, Ix>> {
+ type Neighbors = <&'a $graph_type<N, E, Ix> 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<N, E, Ix>> {
+ type NeighborsDirected =
+ <&'a $graph_type<N, E, Ix> 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<N, E, Ix>> {
+ type NodeIdentifiers =
+ <&'a $graph_type<N, E, Ix> 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<N, E, Ix>> {
+ type NodeRef = <&'a $graph_type<N, E, Ix> as IntoNodeReferences>::NodeRef;
+ type NodeReferences = <&'a $graph_type<N, E, Ix> 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::<StableDiGraph<(), ()>>::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<G>)
+ where
+ G: Visitable + NodeCount + NodeIndexable,
+ &'a G: NodeIndexable
+ + IntoNodeReferences
+ + IntoNeighborsDirected
+ + GraphBase<NodeId = G::NodeId>,
+ 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<N> {
+ /// Map topological position to node index.
+ pos_to_node: BTreeMap<TopologicalPosition, N>,
+ /// 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<TopologicalPosition>,
+}
+
+impl<N> Default for OrderMap<N> {
+ fn default() -> Self {
+ Self {
+ pos_to_node: Default::default(),
+ node_to_pos: Default::default(),
+ }
+ }
+}
+
+impl<N: fmt::Debug> fmt::Debug for OrderMap<N> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("OrderMap")
+ .field("order", &self.pos_to_node)
+ .finish()
+ }
+}
+
+impl<N: Copy> OrderMap<N> {
+ pub(super) fn try_from_graph<G>(graph: G) -> Result<Self, Cycle<G::NodeId>>
+ where
+ G: NodeIndexable<NodeId = N> + 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<NodeId = N>,
+ ) -> 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<N> {
+ 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<Item = N> + '_ {
+ 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<TopologicalPosition>,
+ ) -> impl Iterator<Item = N> + '_ {
+ 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<NodeId = N>,
+ ) -> 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<NodeId = N>) {
+ 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<NodeId = N>,
+ ) {
+ 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<G: Visitable> super::Acyclic<G> {
+ /// 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<NodeId = G::NodeId>,
+ {
+ 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<G::NodeId> {
+ 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 = DefaultIx> = Ix;
+
+/// Adjacency list edge index type, a pair of integers.
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
+pub struct EdgeIndex<Ix = DefaultIx>
+where
+ Ix: IndexType,
+{
+ /// Source of the edge.
+ from: NodeIndex<Ix>,
+ /// 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 <Ix> where { Ix: IndexType }
+item: EdgeIndex<Ix>,
+iter: std::iter::Map<std::iter::Zip<Range<usize>, std::iter::Repeat<NodeIndex<Ix>>>, fn((usize, NodeIndex<Ix>)) -> EdgeIndex<Ix>>,
+}
+
+/// Weighted sucessor
+#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
+struct WSuc<E, Ix: IndexType> {
+ /// Index of the sucessor.
+ suc: Ix,
+ /// Weight of the edge to `suc`.
+ weight: E,
+}
+
+/// One row of the adjacency list.
+type Row<E, Ix> = Vec<WSuc<E, Ix>>;
+type RowIter<'a, E, Ix> = std::slice::Iter<'a, WSuc<E, Ix>>;
+
+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<Ix>,
+iter: std::iter::Map<RowIter<'a, E, Ix>, fn(&WSuc<E, Ix>) -> NodeIndex<Ix>>,
+}
+
+/// 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<Ix>,
+ /// a reference to the corresponding item in the adjacency list
+ edge: &'a WSuc<E, Ix>,
+}
+
+impl<E, Ix: IndexType> Copy for EdgeReference<'_, E, Ix> {}
+impl<E, Ix: IndexType> Clone for EdgeReference<'_, E, Ix> {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+impl<E, Ix: IndexType> visit::EdgeRef for EdgeReference<'_, E, Ix> {
+ type NodeId = NodeIndex<Ix>;
+ type EdgeId = EdgeIndex<Ix>;
+ 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<std::slice::Iter<'a, Row<E, Ix>>>,
+ row_index: usize,
+ row_len: usize,
+ cur: usize,
+}
+
+impl<E, Ix: IndexType> Iterator for EdgeIndices<'_, E, Ix> {
+ type Item = EdgeIndex<Ix>;
+ fn next(&mut self) -> Option<EdgeIndex<Ix>> {
+ 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 <Ix> where {}
+ item: Ix,
+ iter: std::iter::Map<Range<usize>, 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<E, Ix = DefaultIx>
+where
+ Ix: IndexType,
+{
+ suc: Vec<Row<E, Ix>>,
+}
+
+impl<E, Ix: IndexType> List<E, Ix> {
+ /// Creates a new, empty adjacency list.
+ pub fn new() -> List<E, Ix> {
+ List { suc: Vec::new() }
+ }
+
+ /// Creates a new, empty adjacency list tailored for `nodes` nodes.
+ pub fn with_capacity(nodes: usize) -> List<E, Ix> {
+ 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<Ix> {
+ 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<Ix> {
+ 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<I: Iterator<Item = (NodeIndex<Ix>, E)>>(
+ &mut self,
+ edges: I,
+ ) -> NodeIndex<Ix> {
+ 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.<br>
+ ///
+ /// **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<Ix>, b: NodeIndex<Ix>, weight: E) -> EdgeIndex<Ix> {
+ 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<Ix>) -> Option<&WSuc<E, Ix>> {
+ self.suc
+ .get(e.from.index())
+ .and_then(|row| row.get(e.successor_index))
+ }
+
+ fn get_edge_mut(&mut self, e: EdgeIndex<Ix>) -> Option<&mut WSuc<E, Ix>> {
+ 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<Ix>) -> Option<(NodeIndex<Ix>, NodeIndex<Ix>)> {
+ self.get_edge(e).map(|x| (e.from, x.suc))
+ }
+
+ pub fn edge_indices_from(&self, a: NodeIndex<Ix>) -> OutgoingEdgeIndices<Ix> {
+ let proj: fn((usize, NodeIndex<Ix>)) -> EdgeIndex<Ix> =
+ |(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<Ix>, b: NodeIndex<Ix>) -> 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<Ix>, b: NodeIndex<Ix>) -> Option<EdgeIndex<Ix>> {
+ 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<Ix> {
+ 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<E, Ix> {
+ 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<Ix> = List<(), Ix>;
+
+impl<E, Ix: IndexType> Build for List<E, Ix> {
+ /// 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<Ix> {
+ 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.<br>
+ ///
+ /// **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<Ix>, b: NodeIndex<Ix>, weight: E) -> Option<EdgeIndex<Ix>> {
+ 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.<br>
+ fn update_edge(&mut self, a: NodeIndex<Ix>, b: NodeIndex<Ix>, weight: E) -> EdgeIndex<Ix> {
+ 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<E, Ix> 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::<E>() != 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<E, Ix> fmt::Debug for List<E, Ix>
+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<E, Ix> visit::GraphBase for List<E, Ix>
+where
+ Ix: IndexType,
+{
+ type NodeId = NodeIndex<Ix>;
+ type EdgeId = EdgeIndex<Ix>;
+}
+
+impl<E, Ix> visit::Visitable for List<E, Ix>
+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<E, Ix: IndexType> visit::IntoNodeIdentifiers for &List<E, Ix> {
+ type NodeIdentifiers = NodeIndices<Ix>;
+ fn node_identifiers(self) -> NodeIndices<Ix> {
+ self.node_indices()
+ }
+}
+
+impl<Ix: IndexType> visit::NodeRef for NodeIndex<Ix> {
+ type NodeId = NodeIndex<Ix>;
+ type Weight = ();
+ fn id(&self) -> Self::NodeId {
+ *self
+ }
+ fn weight(&self) -> &Self::Weight {
+ &()
+ }
+}
+
+impl<Ix: IndexType, E> visit::IntoNodeReferences for &List<E, Ix> {
+ type NodeRef = NodeIndex<Ix>;
+ type NodeReferences = NodeIndices<Ix>;
+ fn node_references(self) -> Self::NodeReferences {
+ self.node_indices()
+ }
+}
+
+impl<E, Ix: IndexType> visit::Data for List<E, Ix> {
+ type NodeWeight = ();
+ type EdgeWeight = E;
+}
+
+impl<'a, E, Ix: IndexType> IntoNeighbors for &'a List<E, Ix> {
+ 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<Ix>) -> Self::Neighbors {
+ let proj: fn(&WSuc<E, Ix>) -> NodeIndex<Ix> = |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::Enumerate<RowIter<'a, E, Ix>>, std::iter::Repeat<Ix>>,
+ fn(((usize, &'a WSuc<E, Ix>), 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<E, Ix>>
+ >,
+ SomeIter<'a, E, Ix>,
+ fn(
+ (usize, &'a Vec<WSuc<E, Ix>>)
+ ) -> SomeIter<'a, E, Ix>,
+>,
+}
+
+impl<E, Ix: IndexType> Clone for EdgeReferences<'_, E, Ix> {
+ fn clone(&self) -> Self {
+ EdgeReferences {
+ iter: self.iter.clone(),
+ }
+ }
+}
+
+fn proj1<E, Ix: IndexType>(
+ ((successor_index, edge), from): ((usize, &WSuc<E, Ix>), Ix),
+) -> EdgeReference<E, Ix> {
+ let id = EdgeIndex {
+ from,
+ successor_index,
+ };
+ EdgeReference { id, edge }
+}
+fn proj2<E, Ix: IndexType>((row_index, row): (usize, &Vec<WSuc<E, Ix>>)) -> SomeIter<E, Ix> {
+ row.iter()
+ .enumerate()
+ .zip(std::iter::repeat(Ix::new(row_index)))
+ .map(proj1 as _)
+}
+
+impl<'a, Ix: IndexType, E> visit::IntoEdgeReferences for &'a List<E, Ix> {
+ 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<E, Ix> {
+ 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<E, Ix: IndexType> visit::GraphProp for List<E, Ix> {
+ type EdgeType = crate::Directed;
+ fn is_directed(&self) -> bool {
+ true
+ }
+}
+
+impl<E, Ix: IndexType> NodeCount for List<E, Ix> {
+ /// Returns the number of nodes in the list
+ ///
+ /// Computes in **O(1)** time.
+ fn node_count(&self) -> usize {
+ self.suc.len()
+ }
+}
+
+impl<E, Ix: IndexType> EdgeCount for List<E, Ix> {
+ /// Returns the number of edges in the list
+ ///
+ /// Computes in **O(|V|)** time.
+ fn edge_count(&self) -> usize {
+ List::edge_count(self)
+ }
+}
+
+impl<E, Ix: IndexType> visit::NodeIndexable for List<E, Ix> {
+ 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<E, Ix: IndexType> visit::NodeCompactIndexable for List<E, Ix> {}
+
+impl<E, Ix: IndexType> DataMap for List<E, Ix> {
+ 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<Ix>) -> Option<&E> {
+ self.get_edge(e).map(|x| &x.weight)
+ }
+}
+
+impl<E, Ix: IndexType> DataMapMut for List<E, Ix> {
+ 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<Ix>) -> 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<E, Ix> GetAdjacencyMatrix for List<E, Ix>
+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<Ix>, b: NodeIndex<Ix>) -> 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<G, F, H, K, IsGoal>(
+ graph: G,
+ start: G::NodeId,
+ mut is_goal: IsGoal,
+ mut edge_cost: F,
+ mut estimate_cost: H,
+) -> Option<(K, Vec<G::NodeId>)>
+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::<G>::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<G>
+where
+ G: GraphBase,
+ G::NodeId: Eq + Hash,
+{
+ came_from: HashMap<G::NodeId, G::NodeId>,
+}
+
+impl<G> PathTracker<G>
+where
+ G: GraphBase,
+ G::NodeId: Eq + Hash,
+{
+ fn new() -> PathTracker<G> {
+ 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<G::NodeId> {
+ let mut path = vec![last];
+
+ let mut current = last;
+ while let Some(&previous) = self.came_from.get(&current) {
+ 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<NodeId, EdgeWeight> {
+ pub distances: Vec<EdgeWeight>,
+ pub predecessors: Vec<Option<NodeId>>,
+}
+
+/// \[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: G,
+ source: G::NodeId,
+) -> Result<Paths<G::NodeId, G::EdgeWeight>, 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: G, source: G::NodeId) -> Option<Vec<G::NodeId>>
+where
+ G: NodeCount + IntoNodeIdentifiers + IntoEdges + NodeIndexable + Visitable,
+ G::EdgeWeight: FloatMeasure,
+{
+ let ix = |i| g.to_index(i);
+ let mut path = Vec::<G::NodeId>::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: G,
+ source: G::NodeId,
+) -> (Vec<G::EdgeWeight>, Vec<Option<G::NodeId>>)
+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<G>(graph: G) -> (HashMap<G::NodeId, usize>, 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<NodeIndex, usize> = [
+/// (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<G, F, K>(
+ graph: G,
+ start: G::NodeId,
+ goal: Option<G::NodeId>,
+ mut edge_cost: F,
+) -> HashMap<G::NodeId, K>
+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<N>
+where
+ N: Copy + Eq + Hash,
+{
+ root: N,
+ dominators: HashMap<N, N>,
+}
+
+impl<N> Dominators<N>
+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<N> {
+ 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<DominatorsIter<N>> {
+ 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<DominatorsIter<N>> {
+ 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<N> {
+ 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<N>,
+ node: Option<N>,
+}
+
+impl<'a, N> Iterator for DominatorsIter<'a, N>
+where
+ N: 'a + Copy + Eq + Hash,
+{
+ type Item = N;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ 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<Self::Item> {
+ 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<usize>) {
+ 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<G>(graph: G, root: G::NodeId) -> Dominators<G::NodeId>
+where
+ G: IntoNeighbors + Visitable,
+ <G as GraphBase>::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<N>(
+ post_order: &[N],
+ node_to_post_order_idx: &HashMap<N, usize>,
+ mut predecessor_sets: HashMap<N, HashSet<N>>,
+) -> Vec<Vec<usize>>
+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<NodeId> = HashMap<NodeId, HashSet<NodeId>>;
+
+fn simple_fast_post_order<G>(
+ graph: G,
+ root: G::NodeId,
+) -> (Vec<G::NodeId>, PredecessorSets<G::NodeId>)
+where
+ G: IntoNeighbors + Visitable,
+ <G as GraphBase>::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<u32> = 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<EdgeIndex> = 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: G) -> impl Iterator<Item = G::EdgeRef>
+where
+ G: IntoEdgeReferences + GraphProp<EdgeType = Directed>,
+ 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<Item = (NodeIndex<usize>, NodeIndex<usize>)>,
+) -> HashMap<usize, usize> {
+ 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<usize>| -> 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<FasNode, FasNodeContainer, FasNodeIndex>;
+
+#[derive(Debug)]
+struct FasNodeContainer {
+ nodes: Vec<LinkedListEntry<FasNode, FasNodeIndex>>,
+}
+
+impl Index<FasNodeIndex> for FasNodeContainer {
+ type Output = LinkedListEntry<FasNode, FasNodeIndex>;
+
+ fn index(&self, index: FasNodeIndex) -> &Self::Output {
+ &self.nodes[index.0]
+ }
+}
+
+impl IndexMut<FasNodeIndex> 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<NodeLinkedList>,
+ /// Bidirectional nodes with negative delta degree (index 0 is -1 dd, 1 is -2 etc)
+ bidirectional_nve_dd: Vec<NodeLinkedList>,
+}
+
+#[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<usize>,
+
+ /// All outward edges from this node (not removed during processing)
+ out_edges: Vec<FasNodeIndex>,
+
+ /// All inward edges from this node (not removed during processing)
+ in_edges: Vec<FasNodeIndex>,
+
+ /// 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<NodeLinkedList>) {
+ 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<Data, Container, Ix> {
+ pub start: Option<Ix>,
+ marker: PhantomData<(Data, Container)>,
+ }
+
+ #[derive(Debug)]
+ pub struct LinkedListEntry<Data, Ix> {
+ pos: Option<LinkedListPosition<Ix>>,
+ data: Data,
+ }
+
+ #[derive(Debug)]
+ struct LinkedListPosition<Ix> {
+ prev: Option<Ix>,
+ next: Option<Ix>,
+ }
+
+ impl<Data, Ix> LinkedListEntry<Data, Ix> {
+ 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<Ix> {
+ self.pos
+ .as_mut()
+ .expect("expected linked list entry to have populated position")
+ }
+ }
+
+ impl<Data, Container, Ix> LinkedList<Data, Container, Ix>
+ where
+ Container: IndexMut<Ix, Output = LinkedListEntry<Data, Ix>>,
+ 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<Ix> {
+ 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<Ix> {
+ 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<G, F, K>(
+ graph: G,
+ mut edge_cost: F,
+) -> Result<HashMap<(G::NodeId, G::NodeId), K>, 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<N>(
+ network: N,
+ edge: N::EdgeRef,
+ vertex: N::NodeId,
+ flow: N::EdgeWeight,
+) -> N::EdgeWeight
+where
+ N: NodeIndexable + IntoEdges,
+ N::EdgeWeight: Sub<Output = N::EdgeWeight> + 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<N>(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<N>(
+ network: N,
+ source: N::NodeId,
+ destination: N::NodeId,
+ edge_to: &mut [Option<N::EdgeRef>],
+ flows: &[N::EdgeWeight],
+) -> bool
+where
+ N: NodeCount + IntoEdgesDirected + NodeIndexable + EdgeIndexable + Visitable,
+ N::EdgeWeight: Sub<Output = N::EdgeWeight> + 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<N>(
+ network: N,
+ edge: N::EdgeRef,
+ vertex: N::NodeId,
+ flow: N::EdgeWeight,
+ delta: N::EdgeWeight,
+) -> N::EdgeWeight
+where
+ N: NodeIndexable + IntoEdges,
+ N::EdgeWeight: Sub<Output = N::EdgeWeight> + 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::<u8, u8>::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<N>(
+ network: N,
+ source: N::NodeId,
+ destination: N::NodeId,
+) -> (N::EdgeWeight, Vec<N::EdgeWeight>)
+where
+ N: NodeCount
+ + EdgeCount
+ + IntoEdgesDirected
+ + EdgeIndexable
+ + NodeIndexable
+ + DataMap
+ + Visitable,
+ N::EdgeWeight: Sub<Output = N::EdgeWeight> + 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<usize>,
+ /// 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<usize>,
+ /// 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<usize>,
+ 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<usize> {
+ 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<usize> {
+ 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<usize> {
+ 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<G0: GraphBase, G1: GraphBase> {
+ fn enabled() -> bool;
+ fn eq(&mut self, _g0: &G0, _g1: &G1, _n0: G0::NodeId, _n1: G1::NodeId) -> bool;
+ }
+
+ impl<G0: GraphBase, G1: GraphBase> NodeMatcher<G0, G1> 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<G0, G1, F> NodeMatcher<G0, G1> 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<G0: GraphBase, G1: GraphBase> {
+ fn enabled() -> bool;
+ fn eq(
+ &mut self,
+ _g0: &G0,
+ _g1: &G1,
+ e0: (G0::NodeId, G0::NodeId),
+ e1: (G1::NodeId, G1::NodeId),
+ ) -> bool;
+ }
+
+ impl<G0: GraphBase, G1: GraphBase> EdgeMatcher<G0, G1> 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<G0, G1, F> EdgeMatcher<G0, G1> 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<G0, G1>
+ 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<G0, G1, NM, EM>(
+ 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<G0, G1>,
+ EM: EdgeMatcher<G0, G1>,
+ {
+ 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<G0, G1>(
+ 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<G0, G1>(
+ st: &mut (Vf2State<'_, G0>, Vf2State<'_, G1>),
+ nx: G1::NodeId,
+ open_list: OpenList,
+ ) -> Option<G1::NodeId>
+ 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<G0, G1>(
+ 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<G0, G1>(
+ 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<G0, G1, NM, EM>(
+ st: &mut (Vf2State<'_, G0>, Vf2State<'_, G1>),
+ node_match: &mut NM,
+ edge_match: &mut EM,
+ match_subgraph: bool,
+ ) -> Option<bool>
+ where
+ G0: NodeCompactIndexable
+ + EdgeCount
+ + GetAdjacencyMatrix
+ + GraphProp
+ + IntoNeighborsDirected,
+ G1: NodeCompactIndexable
+ + EdgeCount
+ + GetAdjacencyMatrix
+ + GraphProp
+ + IntoNeighborsDirected,
+ NM: NodeMatcher<G0, G1>,
+ EM: EdgeMatcher<G0, G1>,
+ {
+ 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<G0, G1, NM, EM>(
+ st: &mut (Vf2State<'_, G0>, Vf2State<'_, G1>),
+ node_match: &mut NM,
+ edge_match: &mut EM,
+ match_subgraph: bool,
+ stack: &mut Vec<Frame<G0, G1>>,
+ ) -> Option<Vec<usize>>
+ where
+ G0: NodeCompactIndexable
+ + EdgeCount
+ + GetAdjacencyMatrix
+ + GraphProp
+ + IntoNeighborsDirected,
+ G1: NodeCompactIndexable
+ + EdgeCount
+ + GetAdjacencyMatrix
+ + GraphProp
+ + IntoNeighborsDirected,
+ NM: NodeMatcher<G0, G1>,
+ EM: EdgeMatcher<G0, G1>,
+ {
+ 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<G0, G1>,
+ EM: EdgeMatcher<G0, G1>,
+ {
+ st: (Vf2State<'a, G0>, Vf2State<'b, G1>),
+ node_match: &'c mut NM,
+ edge_match: &'c mut EM,
+ match_subgraph: bool,
+ stack: Vec<Frame<G0, G1>>,
+ }
+
+ 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<G0, G1>,
+ EM: EdgeMatcher<G0, G1>,
+ {
+ 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<G0, G1, NM, EM> Iterator for GraphMatcher<'_, '_, '_, G0, G1, NM, EM>
+ where
+ G0: NodeCompactIndexable
+ + EdgeCount
+ + GetAdjacencyMatrix
+ + GraphProp
+ + IntoNeighborsDirected,
+ G1: NodeCompactIndexable
+ + EdgeCount
+ + GetAdjacencyMatrix
+ + GraphProp
+ + IntoNeighborsDirected,
+ NM: NodeMatcher<G0, G1>,
+ EM: EdgeMatcher<G0, G1>,
+ {
+ type Item = Vec<usize>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ isomorphisms(
+ &mut self.st,
+ self.node_match,
+ self.edge_match,
+ self.match_subgraph,
+ &mut self.stack,
+ )
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ // 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<Option<usize>> = [
+ 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, G1>(g0: G0, g1: G1) -> bool
+where
+ G0: NodeCompactIndexable + EdgeCount + GetAdjacencyMatrix + GraphProp + IntoNeighborsDirected,
+ G1: NodeCompactIndexable
+ + EdgeCount
+ + GetAdjacencyMatrix
+ + GraphProp<EdgeType = G0::EdgeType>
+ + 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, G1, NM, EM>(
+ 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<EdgeType = G0::EdgeType>
+ + 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, G1>(g0: G0, g1: G1) -> bool
+where
+ G0: NodeCompactIndexable + EdgeCount + GetAdjacencyMatrix + GraphProp + IntoNeighborsDirected,
+ G1: NodeCompactIndexable
+ + EdgeCount
+ + GetAdjacencyMatrix
+ + GraphProp<EdgeType = G0::EdgeType>
+ + 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, G1, NM, EM>(
+ 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<EdgeType = G0::EdgeType>
+ + 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<impl Iterator<Item = Vec<usize>> + 'a>
+where
+ G0: 'a
+ + NodeCompactIndexable
+ + EdgeCount
+ + DataMap
+ + GetAdjacencyMatrix
+ + GraphProp
+ + IntoEdgesDirected,
+ G1: 'a
+ + NodeCompactIndexable
+ + EdgeCount
+ + DataMap
+ + GetAdjacencyMatrix
+ + GraphProp<EdgeType = G0::EdgeType>
+ + 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<NodeIndex, usize> = [
+/// (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<G, F, K>(
+ graph: G,
+ start: G::NodeId,
+ goal: Option<G::NodeId>,
+ k: usize,
+ mut edge_cost: F,
+) -> HashMap<G::NodeId, K>
+where
+ G: IntoEdges + Visitable + NodeCount + NodeIndexable,
+ G::NodeId: Eq + Hash,
+ F: FnMut(G::EdgeRef) -> K,
+ K: Measure + Copy,
+{
+ let mut counter: Vec<usize> = 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<G: GraphBase> {
+ graph: G,
+ mate: Vec<Option<G::NodeId>>,
+ n_edges: usize,
+}
+
+impl<G> Matching<G>
+where
+ G: GraphBase,
+{
+ fn new(graph: G, mate: Vec<Option<G::NodeId>>, n_edges: usize) -> Self {
+ Self {
+ graph,
+ mate,
+ n_edges,
+ }
+ }
+}
+
+impl<G> Matching<G>
+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<G::NodeId> {
+ 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<G> Matching<G>
+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<Self::NodeId>;
+}
+
+impl<G: NodeIndexable> 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<Self::NodeId> {
+ if i != self.dummy_idx() {
+ Some(self.from_index(i))
+ } else {
+ None
+ }
+ }
+}
+
+pub struct MatchedNodes<'a, G: GraphBase> {
+ graph: &'a G,
+ mate: &'a [Option<G::NodeId>],
+ current: usize,
+}
+
+impl<G> Iterator for MatchedNodes<'_, G>
+where
+ G: NodeIndexable,
+{
+ type Item = G::NodeId;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ 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<G::NodeId>],
+ current: usize,
+}
+
+impl<G> Iterator for MatchedEdges<'_, G>
+where
+ G: NodeIndexable,
+{
+ type Item = (G::NodeId, G::NodeId);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ 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<G>(graph: G) -> Matching<G>
+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<G>(graph: &G) -> (Vec<Option<G::NodeId>>, 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<G, F>(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<G: GraphBase> {
+ 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<G: GraphBase> Label<G> {
+ 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<G::NodeId> {
+ 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<G: GraphBase> Default for Label<G> {
+ fn default() -> Self {
+ Label::None
+ }
+}
+
+impl<G: GraphBase> PartialEq for Label<G> {
+ 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<G>(graph: G) -> Matching<G>
+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<Label<G>> = 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<G, F>(
+ graph: &G,
+ edge: G::EdgeRef,
+ mate: &[Option<G::NodeId>],
+ label: &mut [Label<G>],
+ 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<G>(
+ graph: &G,
+ outer: G::NodeId,
+ other: G::NodeId,
+ mate: &mut [Option<G::NodeId>],
+ label: &[Label<G>],
+) 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: G) -> MinSpanningTree<G>
+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<G>
+where
+ G: Data + IntoNodeReferences,
+{
+ graph: G,
+ node_ids: Option<G::NodeReferences>,
+ subgraphs: UnionFind<usize>,
+ #[allow(clippy::type_complexity)]
+ sort_edges: BinaryHeap<MinScored<G::EdgeWeight, (G::NodeId, G::NodeId)>>,
+ node_map: HashMap<usize, usize>,
+ node_count: usize,
+}
+
+impl<G> Iterator for MinSpanningTree<G>
+where
+ G: IntoNodeReferences + NodeIndexable,
+ G::NodeWeight: Clone,
+ G::EdgeWeight: PartialOrd,
+{
+ type Item = Element<G::NodeWeight, G::EdgeWeight>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ 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: 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: 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: G,
+ space: Option<&mut DfsSpace<G::NodeId, G::Map>>,
+) -> Result<Vec<G::NodeId>, Cycle<G::NodeId>>
+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: 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<G> = DfsSpace<<G as GraphBase>::NodeId, <G as Visitable>::Map>;
+
+/// Workspace for a graph traversal.
+#[derive(Clone, Debug)]
+pub struct DfsSpace<N, VM> {
+ dfs: Dfs<N, VM>,
+}
+
+impl<N, VM> DfsSpace<N, VM>
+where
+ N: Copy + PartialEq,
+ VM: VisitMap<N>,
+{
+ pub fn new<G>(g: G) -> Self
+ where
+ G: GraphRef + Visitable<NodeId = N, Map = VM>,
+ {
+ DfsSpace { dfs: Dfs::empty(g) }
+ }
+}
+
+impl<N, VM> Default for DfsSpace<N, VM>
+where
+ VM: VisitMap<N> + Default,
+{
+ fn default() -> Self {
+ DfsSpace {
+ dfs: Dfs {
+ stack: <_>::default(),
+ discovered: <_>::default(),
+ },
+ }
+ }
+}
+
+/// Create a Dfs if it's needed
+fn with_dfs<G, F, R>(g: G, space: Option<&mut DfsSpaceType<G>>, f: F) -> R
+where
+ G: GraphRef + Visitable,
+ F: FnOnce(&mut Dfs<G::NodeId, G::Map>) -> 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: G,
+ from: G::NodeId,
+ to: G::NodeId,
+ space: Option<&mut DfsSpace<G::NodeId, G::Map>>,
+) -> 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: G) -> Vec<Vec<G::NodeId>>
+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: G) -> Vec<Vec<G::NodeId>>
+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<NonZeroUsize>,
+}
+
+/// 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<N> {
+ index: usize,
+ componentcount: usize,
+ nodes: Vec<NodeData>,
+ stack: Vec<N>,
+}
+
+impl<N> Default for TarjanScc<N> {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl<N> TarjanScc<N> {
+ /// 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<G, F>(&mut self, g: G, mut f: F)
+ where
+ G: IntoNodeIdentifiers<NodeId = N> + IntoNeighbors<NodeId = N> + NodeIndexable<NodeId = N>,
+ 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<G, F>(&mut self, v: G::NodeId, g: G, f: &mut F)
+ where
+ G: IntoNeighbors<NodeId = N> + NodeIndexable<NodeId = N>,
+ 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<G>(&self, g: G, v: N) -> usize
+ where
+ G: IntoNeighbors<NodeId = N> + NodeIndexable<NodeId = N>,
+ 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: G) -> Vec<Vec<G::NodeId>>
+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<_>>(), vec![A, A, A, A]);
+/// assert_eq!(condensed_graph.neighbors(B).collect::<Vec<_>>(), 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<_>>(), vec![A]);
+/// ```
+pub fn condensation<N, E, Ty, Ix>(
+ g: Graph<N, E, Ty, Ix>,
+ make_acyclic: bool,
+) -> Graph<Vec<N>, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ let sccs = kosaraju_scc(&g);
+ let mut condensed: Graph<Vec<N>, 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<N>(pub(crate) N);
+
+impl<N> Cycle<N> {
+ /// 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, N, VM>(g: G, start: N) -> bool
+where
+ G: GraphRef + Visitable<NodeId = N, Map = VM> + IntoNeighbors<NodeId = N>,
+ N: Copy + PartialEq + std::fmt::Debug,
+ VM: VisitMap<N>,
+{
+ 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<Self, Output = Self> + Default + Clone {}
+
+impl<M> Measure for M where M: Debug + PartialOrd + Add<M, Output = M> + 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<Self, Output = Self> {
+ 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<Self, Output = Self>
+ + std::ops::Mul<Self, Output = Self>
+ + std::ops::Div<Self, Output = Self>
+ + 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<G, D>(graph: G, damping_factor: D, nb_iter: usize) -> Vec<D>
+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<D> = (0..node_count)
+ .map(|i| graph.edges(nodeix(i)).map(|_| D::one()).sum::<D>())
+ .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::<D>()
+ })
+ .collect::<Vec<D>>();
+ let sum = pi.iter().copied().sum::<D>();
+ ranks = pi.iter().map(|r| *r / sum).collect::<Vec<D>>();
+ }
+ ranks
+}
+
+#[allow(dead_code)]
+fn out_edges_info<G, D>(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<G, D>(
+ graph: G,
+ damping_factor: D,
+ nb_iter: usize,
+ tol: Option<D>,
+) -> Vec<D>
+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<D> = (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::<D>()
+ })
+ .collect::<Vec<D>>();
+ let sum = pi.par_iter().map(|score| *score).sum::<D>();
+ let new_ranks = pi.par_iter().map(|r| *r / sum).collect::<Vec<D>>();
+ let squared_norm_2 = new_ranks
+ .par_iter()
+ .zip(&ranks)
+ .map(|(new, old)| (*new - *old) * (*new - *old))
+ .sum::<D>();
+ 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 <https://networkx.github.io/documentation/stable/reference/algorithms/generated/networkx.algorithms.simple_paths.all_simple_paths.html>.
+///
+/// # 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::<Vec<_>, _>(&graph, a, d, 0, None)
+/// .collect::<Vec<_>>();
+///
+/// assert_eq!(paths.len(), 4);
+///
+///
+/// // Take only 2 paths.
+/// let paths = algo::all_simple_paths::<Vec<_>, _>(&graph, a, d, 0, None)
+/// .take(2)
+/// .collect::<Vec<_>>();
+///
+/// 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<TargetColl, G>(
+ graph: G,
+ from: G::NodeId,
+ to: G::NodeId,
+ min_intermediate_nodes: usize,
+ max_intermediate_nodes: Option<usize>,
+) -> impl Iterator<Item = TargetColl>
+where
+ G: NodeCount,
+ G: IntoNeighborsDirected,
+ G::NodeId: Eq + Hash,
+ TargetColl: FromIterator<G::NodeId>,
+{
+ // 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<G::NodeId> = 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::<TargetColl>();
+ 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::<TargetColl>();
+ 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::<i32, i32, _>::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<Vec<_>> =
+ 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::<i32, i32, _>::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<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::<i32, i32, _>::from_edges(&[(0, 1), (2, 1)]);
+
+ println!("{}", Dot::new(&graph));
+ let actual_simple_paths_0_to_2: Vec<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<NodeIndex> = 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, Ix: IndexType>(
+ g: G,
+ toposort: &[G::NodeId],
+) -> (UnweightedList<Ix>, Vec<Ix>)
+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<E, Ix: IndexType>(
+ g: &List<E, Ix>,
+) -> (UnweightedList<Ix>, UnweightedList<Ix>) {
+ 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 = DefaultIx> = 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<N = (), E = (), Ty = Directed, Ix = DefaultIx> {
+ /// Column of next edge
+ column: Vec<NodeIndex<Ix>>,
+ /// weight of each edge; lock step with column
+ edges: Vec<E>,
+ /// Index of start of row Always node_count + 1 long.
+ /// Last element is always equal to column.len()
+ row: Vec<usize>,
+ node_weights: Vec<N>,
+ edge_count: usize,
+ ty: PhantomData<Ty>,
+}
+
+impl<N, E, Ty, Ix> Default for Csr<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl<N: Clone, E: Clone, Ty, Ix: Clone> Clone for Csr<N, E, Ty, Ix> {
+ 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<N, E, Ty, Ix> Csr<N, E, Ty, Ix>
+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::<u8,()>::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<N, E, Ix> Csr<N, E, Directed, Ix>
+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<Edge>(edges: &[Edge]) -> Result<Self, EdgesNotSorted>
+ where
+ Edge: Clone + IntoWeightedEdge<E, NodeId = NodeIndex<Ix>>,
+ 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<N, E, Ty, Ix> Csr<N, E, Ty, Ix>
+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<Ix> {
+ 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<Ix>, b: NodeIndex<Ix>, 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<Ix>, b: NodeIndex<Ix>, 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<Ix>, b: NodeIndex<Ix>) -> Result<usize, usize> {
+ 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<Ix>, b: NodeIndex<Ix>) -> bool {
+ self.find_edge_pos(a, b).is_ok()
+ }
+
+ fn neighbors_range(&self, a: NodeIndex<Ix>) -> Range<usize> {
+ 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<Ix>) -> (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<Ix>) -> 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<Ix>) -> &[NodeIndex<Ix>] {
+ 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<Ix>) -> &[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.<br>
+ /// Iterator element type is `EdgeReference<E, Ty, Ix>`.
+ pub fn edges(&self, a: NodeIndex<Ix>) -> Edges<E, Ty, Ix> {
+ 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<Ix>,
+ iter: Zip<SliceIter<'a, NodeIndex<Ix>>, SliceIter<'a, E>>,
+ ty: PhantomData<Ty>,
+}
+
+#[derive(Debug)]
+pub struct EdgeReference<'a, E: 'a, Ty, Ix: 'a = DefaultIx> {
+ index: EdgeIndex,
+ source: NodeIndex<Ix>,
+ target: NodeIndex<Ix>,
+ weight: &'a E,
+ ty: PhantomData<Ty>,
+}
+
+impl<E, Ty, Ix: Copy> Clone for EdgeReference<'_, E, Ty, Ix> {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+impl<E, Ty, Ix: Copy> 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<E, Ty, Ix> EdgeRef for EdgeReference<'_, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ type NodeId = NodeIndex<Ix>;
+ 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::Item> {
+ 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<usize>) {
+ self.iter.size_hint()
+ }
+}
+
+impl<N, E, Ty, Ix> Data for Csr<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ type NodeWeight = N;
+ type EdgeWeight = E;
+}
+
+impl<'a, N, E, Ty, Ix> IntoEdgeReferences for &'a Csr<N, E, Ty, Ix>
+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<Ix>,
+ index: usize,
+ edge_ranges: Enumerate<Windows<'a, usize>>,
+ column: &'a [NodeIndex<Ix>],
+ edges: &'a [E],
+ iter: Zip<SliceIter<'a, NodeIndex<Ix>>, SliceIter<'a, E>>,
+ ty: PhantomData<Ty>,
+}
+
+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<Self::Item> {
+ 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<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ type Edges = Edges<'a, E, Ty, Ix>;
+ fn edges(self, a: Self::NodeId) -> Self::Edges {
+ self.edges(a)
+ }
+}
+
+impl<N, E, Ty, Ix> GraphBase for Csr<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ type NodeId = NodeIndex<Ix>;
+ type EdgeId = EdgeIndex; // index into edges vector
+}
+
+use fixedbitset::FixedBitSet;
+
+impl<N, E, Ty, Ix> Visitable for Csr<N, E, Ty, Ix>
+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<Ix>>,
+}
+
+impl<Ix> Iterator for Neighbors<'_, Ix>
+where
+ Ix: IndexType,
+{
+ type Item = NodeIndex<Ix>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.next().cloned()
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+}
+
+impl<'a, N, E, Ty, Ix> IntoNeighbors for &'a Csr<N, E, Ty, Ix>
+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.<br>
+ /// Iterator element type is `NodeIndex<Ix>`.
+ fn neighbors(self, a: Self::NodeId) -> Self::Neighbors {
+ Neighbors {
+ iter: self.neighbors_slice(a).iter(),
+ }
+ }
+}
+
+impl<N, E, Ty, Ix> NodeIndexable for Csr<N, E, Ty, Ix>
+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<N, E, Ty, Ix> NodeCompactIndexable for Csr<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+}
+
+impl<N, E, Ty, Ix> Index<NodeIndex<Ix>> for Csr<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ type Output = N;
+
+ fn index(&self, ix: NodeIndex<Ix>) -> &N {
+ &self.node_weights[ix.index()]
+ }
+}
+
+impl<N, E, Ty, Ix> IndexMut<NodeIndex<Ix>> for Csr<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ fn index_mut(&mut self, ix: NodeIndex<Ix>) -> &mut N {
+ &mut self.node_weights[ix.index()]
+ }
+}
+
+#[derive(Debug, Clone)]
+pub struct NodeIdentifiers<Ix = DefaultIx> {
+ r: Range<usize>,
+ ty: PhantomData<Ix>,
+}
+
+impl<Ix> Iterator for NodeIdentifiers<Ix>
+where
+ Ix: IndexType,
+{
+ type Item = NodeIndex<Ix>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.r.next().map(Ix::new)
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.r.size_hint()
+ }
+}
+
+impl<N, E, Ty, Ix> IntoNodeIdentifiers for &Csr<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ type NodeIdentifiers = NodeIdentifiers<Ix>;
+ fn node_identifiers(self) -> Self::NodeIdentifiers {
+ NodeIdentifiers {
+ r: 0..self.node_count(),
+ ty: PhantomData,
+ }
+ }
+}
+
+impl<N, E, Ty, Ix> NodeCount for Csr<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ fn node_count(&self) -> usize {
+ (*self).node_count()
+ }
+}
+
+impl<N, E, Ty, Ix> EdgeCount for Csr<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ #[inline]
+ fn edge_count(&self) -> usize {
+ self.edge_count()
+ }
+}
+
+impl<N, E, Ty, Ix> GraphProp for Csr<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ type EdgeType = Ty;
+}
+
+impl<'a, N, E, Ty, Ix> IntoNodeReferences for &'a Csr<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ type NodeRef = (NodeIndex<Ix>, &'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<SliceIter<'a, N>>,
+ ty: PhantomData<Ix>,
+}
+
+impl<'a, N, Ix> Iterator for NodeReferences<'a, N, Ix>
+where
+ Ix: IndexType,
+{
+ type Item = (NodeIndex<Ix>, &'a N);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.next().map(|(i, weight)| (Ix::new(i), weight))
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+}
+
+impl<N, Ix> DoubleEndedIterator for NodeReferences<'_, N, Ix>
+where
+ Ix: IndexType,
+{
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.iter
+ .next_back()
+ .map(|(i, weight)| (Ix::new(i), weight))
+ }
+}
+
+impl<N, Ix> ExactSizeIterator for NodeReferences<'_, N, Ix> where Ix: IndexType {}
+
+/// The adjacency matrix for **Csr** is a bitmap that's computed by
+/// `.adjacency_matrix()`.
+impl<N, E, Ty, Ix> GetAdjacencyMatrix for &Csr<N, E, Ty, Ix>
+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<Ix>, b: NodeIndex<Ix>) -> 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(&copy).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<u32> = 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<G>, 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<G>, 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<Self::EdgeId> {
+ 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<N, E, Ty, Ix> Data for Graph<N, E, Ty, Ix>
+where
+ Ix: IndexType,
+{
+ type NodeWeight = N;
+ type EdgeWeight = E;
+}
+
+impl<N, E, Ty, Ix> DataMap for Graph<N, E, Ty, Ix>
+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<N, E, Ty, Ix> DataMapMut for Graph<N, E, Ty, Ix>
+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<N, E, Ty, Ix> DataMap for StableGraph<N, E, Ty, Ix>
+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<N, E, Ty, Ix> DataMapMut for StableGraph<N, E, Ty, Ix>
+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<N, E, Ty, Ix> Build for Graph<N, E, Ty, Ix>
+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<Self::EdgeId> {
+ 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<N, E, Ty, Ix> Build for StableGraph<N, E, Ty, Ix>
+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<Self::EdgeId> {
+ 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<N, E, Ty> Build for GraphMap<N, E, Ty>
+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<Self::EdgeId> {
+ 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<N, E, Ty, Ix> Create for Graph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ fn with_capacity(nodes: usize, edges: usize) -> Self {
+ Self::with_capacity(nodes, edges)
+ }
+}
+
+#[cfg(feature = "stable_graph")]
+impl<N, E, Ty, Ix> Create for StableGraph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ fn with_capacity(nodes: usize, edges: usize) -> Self {
+ Self::with_capacity(nodes, edges)
+ }
+}
+
+#[cfg(feature = "graphmap")]
+impl<N, E, Ty> Create for GraphMap<N, E, Ty>
+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<N, E> {
+ /// 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<I>(iterable: I) -> Self
+ where
+ Self: Sized,
+ I: IntoIterator<Item = Element<Self::NodeWeight, Self::EdgeWeight>>,
+ {
+ 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<G, I>(iterable: I) -> G
+where
+ G: Create + NodeIndexable,
+ I: IntoIterator<Item = Element<G::NodeWeight, G::EdgeWeight>>,
+{
+ 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<N, E, Ty, Ix> FromElements for Graph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ fn from_elements<I>(iterable: I) -> Self
+ where
+ Self: Sized,
+ I: IntoIterator<Item = Element<Self::NodeWeight, Self::EdgeWeight>>,
+ {
+ from_elements_indexable(iterable)
+ }
+}
+
+#[cfg(feature = "stable_graph")]
+impl<N, E, Ty, Ix> FromElements for StableGraph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ fn from_elements<I>(iterable: I) -> Self
+ where
+ Self: Sized,
+ I: IntoIterator<Item = Element<Self::NodeWeight, Self::EdgeWeight>>,
+ {
+ from_elements_indexable(iterable)
+ }
+}
+
+#[cfg(feature = "graphmap")]
+impl<N, E, Ty> FromElements for GraphMap<N, E, Ty>
+where
+ Ty: EdgeType,
+ N: NodeTrait,
+{
+ fn from_elements<I>(iterable: I) -> Self
+ where
+ Self: Sized,
+ I: IntoIterator<Item = Element<Self::NodeWeight, Self::EdgeWeight>>,
+ {
+ from_elements_indexable(iterable)
+ }
+}
+
+/// Iterator adaptors for iterators of `Element`.
+pub trait ElementIterator<N, E>: Iterator<Item = Element<N, E>> {
+ /// 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<F>(self, f: F) -> FilterElements<Self, F>
+ where
+ Self: Sized,
+ F: FnMut(Element<&mut N, &mut E>) -> bool,
+ {
+ FilterElements {
+ iter: self,
+ node_index: 0,
+ map: Vec::new(),
+ f,
+ }
+ }
+}
+
+impl<N, E, I: ?Sized> ElementIterator<N, E> for I where I: Iterator<Item = Element<N, E>> {}
+
+/// 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<I, F> {
+ iter: I,
+ node_index: usize,
+ map: Vec<usize>,
+ f: F,
+}
+
+impl<I, F, N, E> Iterator for FilterElements<I, F>
+where
+ I: Iterator<Item = Element<N, E>>,
+ F: FnMut(Element<&mut N, &mut E>) -> bool,
+{
+ type Item = Element<N, E>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ 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<usize>) {
+ 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<G> Dot<'_, G>
+where
+ G: IntoNodeReferences + IntoEdgeReferences + NodeIndexable + GraphProp,
+{
+ fn graph_fmt<NF, EF>(&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<G> 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<G> 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<G> 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<G> 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>(W);
+
+impl<W> fmt::Write for Escaper<W>
+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>(T);
+
+impl<T> fmt::Display for Escaped<T>
+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<Ty> {
+ acyclic: bool,
+ selfloops: bool,
+ nodes: usize,
+ /// number of possible edges
+ nedges: usize,
+ /// current edge bitmap
+ bits: u64,
+ g: Graph<(), (), Ty>,
+}
+
+impl Generator<Directed> {
+ /// 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
+ /// *2<sup>e</sup>* 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<Ty: EdgeType> Generator<Ty> {
+ /// 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
+ /// *2<sup>k<sup>2</sup></sup>* 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<Ty: EdgeType> Iterator for Generator<Ty> {
+ type Item = Graph<(), (), Ty>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ 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<Ix>(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<usize>, Vec<usize>) {
+ let bytes: Vec<usize> = 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<usize>) -> Vec<u8> {
+ 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<u8> {
+ 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<u8>) -> usize {
+ let bits_str = bits
+ .iter()
+ .map(|bit| bit.to_string())
+ .collect::<Vec<String>>()
+ .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<Ix>(order: usize, adj_matrix_bits: Vec<u8>) -> 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<Ix: IndexType> 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<Ix: IndexType> 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<Ix: IndexType, S: BuildHasher + Default> FromGraph6 for GraphMap<Ix, (), Undirected, S> {
+ fn from_graph6_string(graph6_string: String) -> Self {
+ let (order, edges): (usize, Vec<(Ix, Ix)>) = from_graph6_representation(graph6_string);
+
+ let mut graph: GraphMap<Ix, (), Undirected, S> =
+ 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<Null, Ix> FromGraph6 for MatrixGraph<(), (), Undirected, Null, Ix>
+where
+ Null: Nullable<Wrapped = ()>,
+ 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<Ix: IndexType> 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<G>(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<G>(graph: G) -> (usize, Vec<usize>)
+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<usize> {
+ 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<usize> {
+ 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<usize>) -> String {
+ while bits.len() % 6 != 0 {
+ bits.push(0);
+ }
+
+ let bits_strs = bits.iter().map(|bit| bit.to_string()).collect::<Vec<_>>();
+
+ 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<N, E, Ix: IndexType> ToGraph6 for Graph<N, E, Undirected, Ix> {
+ fn graph6_string(&self) -> String {
+ get_graph6_representation(self)
+ }
+}
+
+#[cfg(feature = "stable_graph")]
+impl<N, E, Ix: IndexType> ToGraph6 for StableGraph<N, E, Undirected, Ix> {
+ fn graph6_string(&self) -> String {
+ get_graph6_representation(self)
+ }
+}
+
+#[cfg(feature = "graphmap")]
+impl<N: NodeTrait, E, S: BuildHasher> ToGraph6 for GraphMap<N, E, Undirected, S> {
+ fn graph6_string(&self) -> String {
+ get_graph6_representation(self)
+ }
+}
+
+#[cfg(feature = "matrix_graph")]
+impl<N, E, Null, Ix> ToGraph6 for MatrixGraph<N, E, Undirected, Null, Ix>
+where
+ N: NodeTrait,
+ Null: Nullable<Wrapped = E>,
+ Ix: IndexType,
+{
+ fn graph6_string(&self) -> String {
+ get_graph6_representation(self)
+ }
+}
+
+impl<N, E, Ix: IndexType> ToGraph6 for Csr<N, E, Undirected, Ix> {
+ 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<G> Deref for Frozen<'_, G> {
+ type Target = G;
+ fn deref(&self) -> &G {
+ self.0
+ }
+}
+
+impl<G, I> Index<I> for Frozen<'_, G>
+where
+ G: Index<I>,
+{
+ type Output = G::Output;
+ fn index(&self, i: I) -> &G::Output {
+ self.0.index(i)
+ }
+}
+
+impl<G, I> IndexMut<I> for Frozen<'_, G>
+where
+ G: IndexMut<I>,
+{
+ fn index_mut(&mut self, i: I) -> &mut G::Output {
+ self.0.index_mut(i)
+ }
+}
+
+impl<N, E, Ty, Ix> Frozen<'_, Graph<N, E, Ty, Ix>>
+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<T, U>(
+ &mut self,
+ i: T,
+ j: U,
+ ) -> (
+ &mut <Graph<N, E, Ty, Ix> as Index<T>>::Output,
+ &mut <Graph<N, E, Ty, Ix> as Index<U>>::Output,
+ )
+ where
+ Graph<N, E, Ty, Ix>: IndexMut<T> + IndexMut<U>,
+ T: GraphIndex,
+ U: GraphIndex,
+ {
+ self.0.index_twice_mut(i, j)
+ }
+}
+
+macro_rules! access0 {
+ ($e:expr) => {
+ $e.0
+ };
+}
+
+impl<G> 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 = DefaultIx>(Ix);
+
+impl<Ix: IndexType> NodeIndex<Ix> {
+ #[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<Ix> {
+ EdgeIndex(self.0)
+ }
+}
+
+unsafe impl<Ix: IndexType> IndexType for NodeIndex<Ix> {
+ fn index(&self) -> usize {
+ self.0.index()
+ }
+ fn new(x: usize) -> Self {
+ NodeIndex::new(x)
+ }
+ fn max() -> Self {
+ NodeIndex(<Ix as IndexType>::max())
+ }
+}
+
+impl<Ix: IndexType> From<Ix> for NodeIndex<Ix> {
+ fn from(ix: Ix) -> Self {
+ NodeIndex(ix)
+ }
+}
+
+impl<Ix: fmt::Debug> fmt::Debug for NodeIndex<Ix> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "NodeIndex({:?})", self.0)
+ }
+}
+
+/// Short version of `NodeIndex::new`
+pub fn node_index<Ix: IndexType>(index: usize) -> NodeIndex<Ix> {
+ NodeIndex::new(index)
+}
+
+/// Short version of `EdgeIndex::new`
+pub fn edge_index<Ix: IndexType>(index: usize) -> EdgeIndex<Ix> {
+ EdgeIndex::new(index)
+}
+
+/// Edge identifier.
+#[derive(Copy, Clone, Default, PartialEq, PartialOrd, Eq, Ord, Hash)]
+pub struct EdgeIndex<Ix = DefaultIx>(Ix);
+
+impl<Ix: IndexType> EdgeIndex<Ix> {
+ #[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<Ix> {
+ NodeIndex(self.0)
+ }
+}
+
+impl<Ix: IndexType> From<Ix> for EdgeIndex<Ix> {
+ fn from(ix: Ix) -> Self {
+ EdgeIndex(ix)
+ }
+}
+
+impl<Ix: fmt::Debug> fmt::Debug for EdgeIndex<Ix> {
+ 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<Ix: IndexType> fmt::Debug for EdgeIndex<Ix>
+{
+ 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<N, Ix = DefaultIx> {
+ /// Associated node data.
+ pub weight: N,
+ /// Next edge in outgoing and incoming edge lists.
+ next: [EdgeIndex<Ix>; 2],
+}
+
+impl<E, Ix> Clone for Node<E, Ix>
+where
+ E: Clone,
+ Ix: Copy,
+{
+ clone_fields!(Node, weight, next,);
+}
+
+impl<N, Ix: IndexType> Node<N, Ix> {
+ /// Accessor for data structure internals: the first edge in the given direction.
+ pub fn next_edge(&self, dir: Direction) -> EdgeIndex<Ix> {
+ self.next[dir.index()]
+ }
+}
+
+/// The graph's edge type.
+#[derive(Debug)]
+pub struct Edge<E, Ix = DefaultIx> {
+ /// Associated edge data.
+ pub weight: E,
+ /// Next edge in outgoing and incoming edge lists.
+ next: [EdgeIndex<Ix>; 2],
+ /// Start and End node index
+ node: [NodeIndex<Ix>; 2],
+}
+
+impl<E, Ix> Clone for Edge<E, Ix>
+where
+ E: Clone,
+ Ix: Copy,
+{
+ clone_fields!(Edge, weight, next, node,);
+}
+
+impl<E, Ix: IndexType> Edge<E, Ix> {
+ /// Accessor for data structure internals: the next edge for the given direction.
+ pub fn next_edge(&self, dir: Direction) -> EdgeIndex<Ix> {
+ self.next[dir.index()]
+ }
+
+ /// Return the source node index.
+ pub fn source(&self) -> NodeIndex<Ix> {
+ self.node[0]
+ }
+
+ /// Return the target node index.
+ pub fn target(&self) -> NodeIndex<Ix> {
+ self.node[1]
+ }
+}
+
+/// `Graph<N, E, Ty, Ix>` 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<N, E, Ty = Directed, Ix = DefaultIx> {
+ nodes: Vec<Node<N, Ix>>,
+ edges: Vec<Edge<E, Ix>>,
+ ty: PhantomData<Ty>,
+}
+
+/// 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<N, E, Ix = DefaultIx> = Graph<N, E, Directed, Ix>;
+
+/// 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<N, E, Ix = DefaultIx> = Graph<N, E, Undirected, Ix>;
+
+/// The resulting cloned graph has the same graph indices as `self`.
+impl<N, E, Ty, Ix: IndexType> Clone for Graph<N, E, Ty, Ix>
+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<N, E, Ty, Ix> fmt::Debug for Graph<N, E, Ty, Ix>
+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::<N>() != 0 {
+ fmt_struct.field(
+ "node weights",
+ &DebugMap(|| self.nodes.iter().map(|n| &n.weight).enumerate()),
+ );
+ }
+ if size_of::<E>() != 0 {
+ fmt_struct.field(
+ "edge weights",
+ &DebugMap(|| self.edges.iter().map(|n| &n.weight).enumerate()),
+ );
+ }
+ fmt_struct.finish()
+ }
+}
+
+enum Pair<T> {
+ Both(T, T),
+ One(T),
+ None,
+}
+
+use std::cmp::max;
+
+/// Get mutable references at index `a` and `b`.
+fn index_twice<T>(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<N, E> Graph<N, E, Directed> {
+ /// 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<N, E> Graph<N, E, Undirected> {
+ /// 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<N, E, Ty, Ix> Graph<N, E, Ty, Ix>
+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<Ix> {
+ 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!(<Ix as IndexType>::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<Ix>) -> 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<Ix>) -> 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.<br>
+ /// **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<Ix>, b: NodeIndex<Ix>, weight: E) -> EdgeIndex<Ix> {
+ let edge_idx = EdgeIndex::new(self.edges.len());
+ assert!(<Ix as IndexType>::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<Ix>, b: NodeIndex<Ix>, weight: E) -> EdgeIndex<Ix> {
+ 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<Ix>) -> 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<Ix>) -> 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<Ix>) -> Option<(NodeIndex<Ix>, NodeIndex<Ix>)> {
+ 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<Ix>) -> Option<N> {
+ 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<Ix>, 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<Ix>; 2],
+ e: EdgeIndex<Ix>,
+ edge_next: [EdgeIndex<Ix>; 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<Ix>) -> Option<E> {
+ // 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<Ix>) -> Option<E> {
+ // 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.<br>
+ /// Iterator element type is `NodeIndex<Ix>`.
+ ///
+ /// 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<Ix>) -> Neighbors<E, Ix> {
+ 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.<br>
+ /// Iterator element type is `NodeIndex<Ix>`.
+ ///
+ /// 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<Ix>, dir: Direction) -> Neighbors<E, Ix> {
+ 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.<br>
+ /// Iterator element type is `NodeIndex<Ix>`.
+ ///
+ /// 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<Ix>) -> Neighbors<E, Ix> {
+ 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.<br>
+ /// Iterator element type is `EdgeReference<E, Ix>`.
+ pub fn edges(&self, a: NodeIndex<Ix>) -> Edges<E, Ty, Ix> {
+ 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.<br>
+ /// Iterator element type is `EdgeReference<E, Ix>`.
+ pub fn edges_directed(&self, a: NodeIndex<Ix>, dir: Direction) -> Edges<E, Ty, Ix> {
+ 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<E, Ix>`.
+ pub fn edges_connecting(
+ &self,
+ a: NodeIndex<Ix>,
+ b: NodeIndex<Ix>,
+ ) -> EdgesConnecting<E, Ty, Ix> {
+ 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<Ix>, b: NodeIndex<Ix>) -> 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<Ix>, b: NodeIndex<Ix>) -> Option<EdgeIndex<Ix>> {
+ 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<N, Ix>,
+ b: NodeIndex<Ix>,
+ ) -> Option<EdgeIndex<Ix>> {
+ 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<Ix>,
+ b: NodeIndex<Ix>,
+ ) -> Option<(EdgeIndex<Ix>, 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<N, Ix>,
+ b: NodeIndex<Ix>,
+ ) -> Option<(EdgeIndex<Ix>, 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<N, Ty, Ix> {
+ 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<Ix> {
+ 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<N, Ix> {
+ 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<N, Ix> {
+ NodeWeights {
+ nodes: self.nodes.iter(),
+ }
+ }
+
+ /// Return an iterator over the edge indices of the graph
+ pub fn edge_indices(&self) -> EdgeIndices<Ix> {
+ EdgeIndices {
+ r: 0..self.edge_count(),
+ ty: PhantomData,
+ }
+ }
+
+ /// Create an iterator over all edges, in indexed order.
+ ///
+ /// Iterator element type is `EdgeReference<E, Ix>`.
+ pub fn edge_references(&self) -> EdgeReferences<E, Ix> {
+ 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<E, Ix> {
+ 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<E, Ix> {
+ 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<N, Ix>] {
+ &self.nodes
+ }
+
+ /// Access the internal edge array.
+ pub fn raw_edges(&self) -> &[Edge<E, Ix>] {
+ &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<Node<N, Ix>>, Vec<Edge<E, Ix>>) {
+ (self.nodes, self.edges)
+ }
+
+ /// Accessor for data structure internals: the first edge in the given direction.
+ pub fn first_edge(&self, a: NodeIndex<Ix>, dir: Direction) -> Option<EdgeIndex<Ix>> {
+ 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<Ix>, dir: Direction) -> Option<EdgeIndex<Ix>> {
+ 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<T, U>(
+ &mut self,
+ i: T,
+ j: U,
+ ) -> (
+ &mut <Self as Index<T>>::Output,
+ &mut <Self as Index<U>>::Output,
+ )
+ where
+ Self: IndexMut<T> + IndexMut<U>,
+ 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 _;
+ (
+ <Self as IndexMut<T>>::index_mut(&mut *self_mut, i),
+ <Self as IndexMut<U>>::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<F>(&mut self, mut visit: F)
+ where
+ F: FnMut(Frozen<Self>, NodeIndex<Ix>) -> 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<F>(&mut self, mut visit: F)
+ where
+ F: FnMut(Frozen<Self>, EdgeIndex<Ix>) -> 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<I>(iterable: I) -> Self
+ where
+ I: IntoIterator,
+ I::Item: IntoWeightedEdge<E>,
+ <I::Item as IntoWeightedEdge<E>>::NodeId: Into<NodeIndex<Ix>>,
+ 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<I>(&mut self, iterable: I)
+ where
+ I: IntoIterator,
+ I::Item: IntoWeightedEdge<E>,
+ <I::Item as IntoWeightedEdge<E>>::NodeId: Into<NodeIndex<Ix>>,
+ 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<N2, E2, Ty, Ix>
+ where
+ F: FnMut(NodeIndex<Ix>, &'a N) -> N2,
+ G: FnMut(EdgeIndex<Ix>, &'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<N2, E2, Ty, Ix>
+ where
+ F: FnMut(NodeIndex<Ix>, &'a N) -> Option<N2>,
+ G: FnMut(EdgeIndex<Ix>, &'a E) -> Option<E2>,
+ {
+ 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<NewTy>(self) -> Graph<N, E, NewTy, Ix>
+ 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<Ix>> {
+ 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<slice::Iter<'a, Node<N, Ix>>>,
+ dir: Direction,
+ ty: PhantomData<Ty>,
+}
+
+impl<'a, N: 'a, Ty, Ix> Iterator for Externals<'a, N, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ type Item = NodeIndex<Ix>;
+ fn next(&mut self) -> Option<NodeIndex<Ix>> {
+ 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<usize>) {
+ let (_, upper) = self.iter.size_hint();
+ (0, upper)
+ }
+}
+
+/// Iterator over the neighbors of a node.
+///
+/// Iterator element type is `NodeIndex<Ix>`.
+///
+/// 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<Ix>,
+ edges: &'a [Edge<E, Ix>],
+ next: [EdgeIndex<Ix>; 2],
+}
+
+impl<E, Ix> Iterator for Neighbors<'_, E, Ix>
+where
+ Ix: IndexType,
+{
+ type Item = NodeIndex<Ix>;
+
+ fn next(&mut self) -> Option<NodeIndex<Ix>> {
+ // 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<E, Ix> Clone for Neighbors<'_, E, Ix>
+where
+ Ix: IndexType,
+{
+ clone_fields!(Neighbors, skip_start, edges, next,);
+}
+
+impl<E, Ix> 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<Ix> {
+ WalkNeighbors {
+ skip_start: self.skip_start,
+ next: self.next,
+ }
+ }
+}
+
+struct EdgesWalkerMut<'a, E: 'a, Ix: IndexType = DefaultIx> {
+ edges: &'a mut [Edge<E, Ix>],
+ next: EdgeIndex<Ix>,
+ dir: Direction,
+}
+
+fn edges_walker_mut<E, Ix>(
+ edges: &mut [Edge<E, Ix>],
+ next: EdgeIndex<Ix>,
+ dir: Direction,
+) -> EdgesWalkerMut<E, Ix>
+where
+ Ix: IndexType,
+{
+ EdgesWalkerMut { edges, next, dir }
+}
+
+impl<E, Ix> EdgesWalkerMut<'_, E, Ix>
+where
+ Ix: IndexType,
+{
+ fn next_edge(&mut self) -> Option<&mut Edge<E, Ix>> {
+ self.next().map(|t| t.1)
+ }
+
+ fn next(&mut self) -> Option<(EdgeIndex<Ix>, &mut Edge<E, Ix>)> {
+ 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<N, E, Ty, Ix>
+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<N, E, Ty, Ix>
+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<Ix>,
+ edges: &'a [Edge<E, Ix>],
+
+ /// Next edge to visit.
+ next: [EdgeIndex<Ix>; 2],
+
+ /// For directed graphs: the direction to iterate in
+ /// For undirected graphs: the direction of edges
+ direction: Direction,
+ ty: PhantomData<Ty>,
+}
+
+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<Self::Item> {
+ // 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<Ix>,
+ edges: Edges<'a, E, Ty, Ix>,
+ ty: PhantomData<Ty>,
+}
+
+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<EdgeReference<'a, E, Ix>> {
+ let target_node = self.target_node;
+ self.edges
+ .by_ref()
+ .find(|&edge| edge.node[1] == target_node)
+ }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let (_, upper) = self.edges.size_hint();
+ (0, upper)
+ }
+}
+
+fn swap_pair<T>(mut x: [T; 2]) -> [T; 2] {
+ x.swap(0, 1);
+ x
+}
+
+impl<E, Ty, Ix> 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<N, Ix>>,
+}
+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<usize>) {
+ 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<N, Ix>>, // 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<usize>) {
+ 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<E, Ix>>,
+}
+
+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<usize>) {
+ 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<E, Ix>>, // 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<usize>) {
+ self.edges.size_hint()
+ }
+}
+
+/// Index the `Graph` by `NodeIndex` to access node weights.
+///
+/// **Panics** if the node doesn't exist.
+impl<N, E, Ty, Ix> Index<NodeIndex<Ix>> for Graph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ type Output = N;
+ fn index(&self, index: NodeIndex<Ix>) -> &N {
+ &self.nodes[index.index()].weight
+ }
+}
+
+/// Index the `Graph` by `NodeIndex` to access node weights.
+///
+/// **Panics** if the node doesn't exist.
+impl<N, E, Ty, Ix> IndexMut<NodeIndex<Ix>> for Graph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ fn index_mut(&mut self, index: NodeIndex<Ix>) -> &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<N, E, Ty, Ix> Index<EdgeIndex<Ix>> for Graph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ type Output = E;
+ fn index(&self, index: EdgeIndex<Ix>) -> &E {
+ &self.edges[index.index()].weight
+ }
+}
+
+/// Index the `Graph` by `EdgeIndex` to access edge weights.
+///
+/// **Panics** if the edge doesn't exist.
+impl<N, E, Ty, Ix> IndexMut<EdgeIndex<Ix>> for Graph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ fn index_mut(&mut self, index: EdgeIndex<Ix>) -> &mut E {
+ &mut self.edges[index.index()].weight
+ }
+}
+
+/// Create a new empty `Graph`.
+impl<N, E, Ty, Ix> Default for Graph<N, E, Ty, Ix>
+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<Ix: IndexType> GraphIndex for NodeIndex<Ix> {
+ #[inline]
+ #[doc(hidden)]
+ fn index(&self) -> usize {
+ NodeIndex::index(*self)
+ }
+ #[inline]
+ #[doc(hidden)]
+ fn is_node_index() -> bool {
+ true
+ }
+}
+
+impl<Ix: IndexType> GraphIndex for EdgeIndex<Ix> {
+ #[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<Ix> {
+ skip_start: NodeIndex<Ix>,
+ next: [EdgeIndex<Ix>; 2],
+}
+
+impl<Ix> Clone for WalkNeighbors<Ix>
+where
+ Ix: IndexType,
+{
+ fn clone(&self) -> Self {
+ WalkNeighbors {
+ skip_start: self.skip_start,
+ next: self.next,
+ }
+ }
+}
+
+impl<Ix: IndexType> WalkNeighbors<Ix> {
+ /// 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<N, E, Ty: EdgeType>(
+ &mut self,
+ g: &Graph<N, E, Ty, Ix>,
+ ) -> Option<(EdgeIndex<Ix>, NodeIndex<Ix>)> {
+ // 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<N, E, Ty: EdgeType>(
+ &mut self,
+ g: &Graph<N, E, Ty, Ix>,
+ ) -> Option<NodeIndex<Ix>> {
+ self.next(g).map(|t| t.1)
+ }
+
+ pub fn next_edge<N, E, Ty: EdgeType>(
+ &mut self,
+ g: &Graph<N, E, Ty, Ix>,
+ ) -> Option<EdgeIndex<Ix>> {
+ self.next(g).map(|t| t.0)
+ }
+}
+
+/// Iterator over the node indices of a graph.
+#[derive(Clone, Debug)]
+pub struct NodeIndices<Ix = DefaultIx> {
+ r: Range<usize>,
+ ty: PhantomData<fn() -> Ix>,
+}
+
+impl<Ix: IndexType> Iterator for NodeIndices<Ix> {
+ type Item = NodeIndex<Ix>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.r.next().map(node_index)
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.r.size_hint()
+ }
+}
+
+impl<Ix: IndexType> DoubleEndedIterator for NodeIndices<Ix> {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.r.next_back().map(node_index)
+ }
+}
+
+impl<Ix: IndexType> ExactSizeIterator for NodeIndices<Ix> {}
+
+/// Iterator over the edge indices of a graph.
+#[derive(Clone, Debug)]
+pub struct EdgeIndices<Ix = DefaultIx> {
+ r: Range<usize>,
+ ty: PhantomData<fn() -> Ix>,
+}
+
+impl<Ix: IndexType> Iterator for EdgeIndices<Ix> {
+ type Item = EdgeIndex<Ix>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.r.next().map(edge_index)
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.r.size_hint()
+ }
+}
+
+impl<Ix: IndexType> DoubleEndedIterator for EdgeIndices<Ix> {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.r.next_back().map(edge_index)
+ }
+}
+
+impl<Ix: IndexType> ExactSizeIterator for EdgeIndices<Ix> {}
+
+/// Reference to a `Graph` edge.
+#[derive(Debug)]
+pub struct EdgeReference<'a, E: 'a, Ix = DefaultIx> {
+ index: EdgeIndex<Ix>,
+ node: [NodeIndex<Ix>; 2],
+ weight: &'a E,
+}
+
+impl<E, Ix: IndexType> Clone for EdgeReference<'_, E, Ix> {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+impl<E, Ix: IndexType> Copy for EdgeReference<'_, E, Ix> {}
+
+impl<E, Ix: IndexType> PartialEq for EdgeReference<'_, E, Ix>
+where
+ E: PartialEq,
+{
+ fn eq(&self, rhs: &Self) -> bool {
+ self.index == rhs.index && self.weight == rhs.weight
+ }
+}
+
+impl<N, E, Ty, Ix> visit::GraphBase for Graph<N, E, Ty, Ix>
+where
+ Ix: IndexType,
+{
+ type NodeId = NodeIndex<Ix>;
+ type EdgeId = EdgeIndex<Ix>;
+}
+
+impl<N, E, Ty, Ix> visit::Visitable for Graph<N, E, Ty, Ix>
+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<N, E, Ty, Ix> visit::GraphProp for Graph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ type EdgeType = Ty;
+}
+
+impl<'a, N, E: 'a, Ty, Ix> visit::IntoNodeIdentifiers for &'a Graph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ type NodeIdentifiers = NodeIndices<Ix>;
+ fn node_identifiers(self) -> NodeIndices<Ix> {
+ Graph::node_indices(self)
+ }
+}
+
+impl<N, E, Ty, Ix> visit::NodeCount for Graph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ fn node_count(&self) -> usize {
+ self.node_count()
+ }
+}
+
+impl<N, E, Ty, Ix> visit::NodeIndexable for Graph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ #[inline]
+ fn node_bound(&self) -> usize {
+ self.node_count()
+ }
+ #[inline]
+ fn to_index(&self, ix: NodeIndex<Ix>) -> usize {
+ ix.index()
+ }
+ #[inline]
+ fn from_index(&self, ix: usize) -> Self::NodeId {
+ NodeIndex::new(ix)
+ }
+}
+
+impl<N, E, Ty, Ix> visit::NodeCompactIndexable for Graph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+}
+
+impl<'a, N, E: 'a, Ty, Ix> visit::IntoNeighbors for &'a Graph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ type Neighbors = Neighbors<'a, E, Ix>;
+ fn neighbors(self, n: NodeIndex<Ix>) -> Neighbors<'a, E, Ix> {
+ Graph::neighbors(self, n)
+ }
+}
+
+impl<'a, N, E: 'a, Ty, Ix> visit::IntoNeighborsDirected for &'a Graph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ type NeighborsDirected = Neighbors<'a, E, Ix>;
+ fn neighbors_directed(self, n: NodeIndex<Ix>, 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<N, E, Ty, Ix>
+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<N, E, Ty, Ix> visit::EdgeCount for Graph<N, E, Ty, Ix>
+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<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ type NodeRef = (NodeIndex<Ix>, &'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<slice::Iter<'a, Node<N, Ix>>>,
+}
+
+impl<'a, N, Ix> Iterator for NodeReferences<'a, N, Ix>
+where
+ Ix: IndexType,
+{
+ type Item = (NodeIndex<Ix>, &'a N);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter
+ .next()
+ .map(|(i, node)| (node_index(i), &node.weight))
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+}
+
+impl<N, Ix> DoubleEndedIterator for NodeReferences<'_, N, Ix>
+where
+ Ix: IndexType,
+{
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.iter
+ .next_back()
+ .map(|(i, node)| (node_index(i), &node.weight))
+ }
+}
+
+impl<N, Ix> 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<Ix, E> visit::EdgeRef for EdgeReference<'_, E, Ix>
+where
+ Ix: IndexType,
+{
+ type NodeId = NodeIndex<Ix>;
+ type EdgeId = EdgeIndex<Ix>;
+ 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<slice::Iter<'a, Edge<E, 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::Item> {
+ self.iter.next().map(|(i, edge)| EdgeReference {
+ index: edge_index(i),
+ node: edge.node,
+ weight: &edge.weight,
+ })
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+}
+
+impl<E, Ix> DoubleEndedIterator for EdgeReferences<'_, E, Ix>
+where
+ Ix: IndexType,
+{
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.iter.next_back().map(|(i, edge)| EdgeReference {
+ index: edge_index(i),
+ node: edge.node,
+ weight: &edge.weight,
+ })
+ }
+}
+
+impl<E, Ix> ExactSizeIterator for EdgeReferences<'_, E, Ix> where Ix: IndexType {}
+
+impl<N, E, Ty, Ix> visit::EdgeIndexable for Graph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ fn edge_bound(&self) -> usize {
+ self.edge_count()
+ }
+
+ fn to_index(&self, ix: EdgeIndex<Ix>) -> 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<Ix>],
+/// edge_property: EdgeProperty,
+/// edges: [Option<(NodeIndex<Ix>, NodeIndex<Ix>, 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<N, Ix>],
+ node_holes: &'a [NodeIndex<Ix>],
+ edge_property: EdgeProperty,
+ #[serde(serialize_with = "ser_graph_edges")]
+ edges: &'a [Edge<E, Ix>],
+}
+
+// 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<N, E, Ix> {
+ #[serde(deserialize_with = "deser_graph_nodes")]
+ nodes: Vec<Node<N, Ix>>,
+ #[serde(deserialize_with = "deser_graph_node_holes")]
+ #[allow(unused)]
+ #[serde(default = "Vec::new")]
+ node_holes: Vec<NodeIndex<Ix>>,
+ edge_property: EdgeProperty,
+ #[serde(deserialize_with = "deser_graph_edges")]
+ edges: Vec<Edge<E, Ix>>,
+}
+
+impl<Ix> Serialize for NodeIndex<Ix>
+where
+ Ix: IndexType + Serialize,
+{
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ self.0.serialize(serializer)
+ }
+}
+
+impl<'de, Ix> Deserialize<'de> for NodeIndex<Ix>
+where
+ Ix: IndexType + Deserialize<'de>,
+{
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ Ok(NodeIndex(Ix::deserialize(deserializer)?))
+ }
+}
+
+impl<Ix> Serialize for EdgeIndex<Ix>
+where
+ Ix: IndexType + Serialize,
+{
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ self.0.serialize(serializer)
+ }
+}
+
+impl<'de, Ix> Deserialize<'de> for EdgeIndex<Ix>
+where
+ Ix: IndexType + Deserialize<'de>,
+{
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ 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<Ty> From<PhantomData<Ty>> for EdgeProperty
+where
+ Ty: EdgeType,
+{
+ fn from(_: PhantomData<Ty>) -> Self {
+ if Ty::is_directed() {
+ EdgeProperty::Directed
+ } else {
+ EdgeProperty::Undirected
+ }
+ }
+}
+
+impl<Ty> FromDeserialized for PhantomData<Ty>
+where
+ Ty: EdgeType,
+{
+ type Input = EdgeProperty;
+ fn from_deserialized<E2>(input: Self::Input) -> Result<Self, E2>
+ where
+ E2: Error,
+ {
+ if input.is_directed() != Ty::is_directed() {
+ Err(E2::custom(format_args!(
+ "graph edge property mismatch, \
+ expected {:?}, found {:?}",
+ EdgeProperty::from(PhantomData::<Ty>),
+ input
+ )))
+ } else {
+ Ok(PhantomData)
+ }
+ }
+}
+
+fn ser_graph_nodes<S, N, Ix>(nodes: &&[Node<N, Ix>], serializer: S) -> Result<S::Ok, S::Error>
+where
+ S: Serializer,
+ N: Serialize,
+ Ix: Serialize + IndexType,
+{
+ serializer.collect_seq_exact(nodes.iter().map(|node| &node.weight))
+}
+
+fn ser_graph_edges<S, E, Ix>(edges: &&[Edge<E, Ix>], serializer: S) -> Result<S::Ok, S::Error>
+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<Vec<Node<N, Ix>>, 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<Vec<NodeIndex<Ix>>, D::Error>
+where
+ D: Deserializer<'de>,
+ Ix: IndexType + Deserialize<'de>,
+{
+ deserializer.deserialize_seq(
+ MappedSequenceVisitor::<NodeIndex<Ix>, NodeIndex<Ix>, _>::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<Vec<Edge<N, Ix>>, D::Error>
+where
+ D: Deserializer<'de>,
+ N: Deserialize<'de>,
+ Ix: IndexType + Deserialize<'de>,
+{
+ deserializer.deserialize_seq(MappedSequenceVisitor::<
+ Option<(NodeIndex<Ix>, NodeIndex<Ix>, 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<N, E, Ty, Ix>
+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::<Ty>),
+ }
+ }
+}
+
+/// Requires crate feature `"serde-1"`
+impl<N, E, Ty, Ix> Serialize for Graph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType + Serialize,
+ N: Serialize,
+ E: Serialize,
+{
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ self.into_serializable().serialize(serializer)
+ }
+}
+
+pub fn invalid_node_err<E>(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<E>(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<Ix, E>(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,
+ <Ix as IndexType>::max().index()
+ ))
+}
+
+impl<'a, N, E, Ty, Ix> FromDeserialized for Graph<N, E, Ty, Ix>
+where
+ Ix: IndexType,
+ Ty: EdgeType,
+{
+ type Input = DeserGraph<N, E, Ix>;
+ fn from_deserialized<E2>(input: Self::Input) -> Result<Self, E2>
+ where
+ E2: Error,
+ {
+ let ty = PhantomData::<Ty>::from_deserialized(input.edge_property)?;
+ let nodes = input.nodes;
+ let edges = input.edges;
+ if nodes.len() >= <Ix as IndexType>::max().index() {
+ Err(invalid_length_err::<Ix, _>("node", nodes.len()))?
+ }
+
+ if edges.len() >= <Ix as IndexType>::max().index() {
+ Err(invalid_length_err::<Ix, _>("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<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType + Deserialize<'de>,
+ N: Deserialize<'de>,
+ E: Deserialize<'de>,
+{
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ 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<N, E, Ty, Ix>` 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<N, E, Ty = Directed, Ix = DefaultIx> {
+ g: Graph<Option<N>, Option<E>, 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<Ix>,
+ free_edge: EdgeIndex<Ix>,
+}
+
+/// 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<N, E, Ix = DefaultIx> = StableGraph<N, E, Directed, Ix>;
+
+/// 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<N, E, Ix = DefaultIx> = StableGraph<N, E, Undirected, Ix>;
+
+impl<N, E, Ty, Ix> fmt::Debug for StableGraph<N, E, Ty, Ix>
+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::<N>() != 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::<E>() != 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<N, E> StableGraph<N, E, Directed> {
+ /// 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<N, E, Ty, Ix> StableGraph<N, E, Ty, Ix>
+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<Ix> {
+ 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<Ix>) {
+ 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<Ix>) -> Option<N> {
+ 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<Ix>) -> bool {
+ self.get_node(a).is_some()
+ }
+
+ // Return the Node if it is not vacant (non-None weight)
+ fn get_node(&self, a: NodeIndex<Ix>) -> Option<&Node<Option<N>, 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.<br>
+ /// **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<Ix>, b: NodeIndex<Ix>, weight: E) -> EdgeIndex<Ix> {
+ let edge_idx;
+ let mut new_edge = None::<Edge<_, _>>;
+ {
+ 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!(<Ix as IndexType>::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<Ix>) {
+ 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<Ix>, b: NodeIndex<Ix>, weight: E) -> EdgeIndex<Ix> {
+ 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<Ix>) -> Option<E> {
+ // 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<Ix>) -> 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<Ix>) -> 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<Item = &N> {
+ 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<Item = &mut N> {
+ 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<N, Ix> {
+ 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<Ix>) -> 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<Ix>) -> 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<Item = &E> {
+ 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<Item = &mut E> {
+ 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<Ix>) -> Option<(NodeIndex<Ix>, NodeIndex<Ix>)> {
+ 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<E, Ix> {
+ 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<E, Ix>`.
+ pub fn edges_connecting(
+ &self,
+ a: NodeIndex<Ix>,
+ b: NodeIndex<Ix>,
+ ) -> EdgesConnecting<E, Ty, Ix> {
+ 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<Ix>, b: NodeIndex<Ix>) -> 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<Ix>, b: NodeIndex<Ix>) -> Option<EdgeIndex<Ix>> {
+ 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<Ix>,
+ b: NodeIndex<Ix>,
+ ) -> Option<(EdgeIndex<Ix>, 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.<br>
+ /// Iterator element type is `NodeIndex<Ix>`.
+ ///
+ /// 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<Ix>) -> Neighbors<E, Ix> {
+ 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.<br>
+ /// Iterator element type is `NodeIndex<Ix>`.
+ ///
+ /// 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<Ix>, dir: Direction) -> Neighbors<E, Ix> {
+ 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.<br>
+ /// Iterator element type is `NodeIndex<Ix>`.
+ ///
+ /// 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<Ix>) -> Neighbors<E, Ix> {
+ 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.<br>
+ /// Iterator element type is `EdgeReference<E, Ix>`.
+ pub fn edges(&self, a: NodeIndex<Ix>) -> Edges<E, Ty, Ix> {
+ 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.<br>
+ /// Iterator element type is `EdgeReference<E, Ix>`.
+ pub fn edges_directed(&self, a: NodeIndex<Ix>, dir: Direction) -> Edges<E, Ty, Ix> {
+ 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<N, Ty, Ix> {
+ 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<T, U>(
+ &mut self,
+ i: T,
+ j: U,
+ ) -> (
+ &mut <Self as Index<T>>::Output,
+ &mut <Self as Index<U>>::Output,
+ )
+ where
+ Self: IndexMut<T> + IndexMut<U>,
+ 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 _;
+ (
+ <Self as IndexMut<T>>::index_mut(&mut *self_mut, i),
+ <Self as IndexMut<U>>::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<F>(&mut self, mut visit: F)
+ where
+ F: FnMut(Frozen<Self>, NodeIndex<Ix>) -> 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<F>(&mut self, mut visit: F)
+ where
+ F: FnMut(Frozen<Self>, EdgeIndex<Ix>) -> 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<I>(iterable: I) -> Self
+ where
+ I: IntoIterator,
+ I::Item: IntoWeightedEdge<E>,
+ <I::Item as IntoWeightedEdge<E>>::NodeId: Into<NodeIndex<Ix>>,
+ 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<N2, E2, Ty, Ix>
+ where
+ F: FnMut(NodeIndex<Ix>, &'a N) -> N2,
+ G: FnMut(EdgeIndex<Ix>, &'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<N2, E2, Ty, Ix>
+ where
+ F: FnMut(NodeIndex<Ix>, &'a N) -> Option<N2>,
+ G: FnMut(EdgeIndex<Ix>, &'a E) -> Option<E2>,
+ {
+ 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<I>(&mut self, iterable: I)
+ where
+ I: IntoIterator,
+ I::Item: IntoWeightedEdge<E>,
+ <I::Item as IntoWeightedEdge<E>>::NodeId: Into<NodeIndex<Ix>>,
+ 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<Option<N>, Ix>] {
+ self.g.raw_nodes()
+ }
+
+ fn raw_edges(&self) -> &[Edge<Option<E>, 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<Ix>, 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<Ix>)
+ 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<Ix>> {
+ // 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<N, E, Ty, Ix: IndexType> Clone for StableGraph<N, E, Ty, Ix>
+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<N, E, Ty, Ix> Index<NodeIndex<Ix>> for StableGraph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ type Output = N;
+ fn index(&self, index: NodeIndex<Ix>) -> &N {
+ self.node_weight(index).unwrap()
+ }
+}
+
+/// Index the `StableGraph` by `NodeIndex` to access node weights.
+///
+/// **Panics** if the node doesn't exist.
+impl<N, E, Ty, Ix> IndexMut<NodeIndex<Ix>> for StableGraph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ fn index_mut(&mut self, index: NodeIndex<Ix>) -> &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<N, E, Ty, Ix> Index<EdgeIndex<Ix>> for StableGraph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ type Output = E;
+ fn index(&self, index: EdgeIndex<Ix>) -> &E {
+ self.edge_weight(index).unwrap()
+ }
+}
+
+/// Index the `StableGraph` by `EdgeIndex` to access edge weights.
+///
+/// **Panics** if the edge doesn't exist.
+impl<N, E, Ty, Ix> IndexMut<EdgeIndex<Ix>> for StableGraph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ fn index_mut(&mut self, index: EdgeIndex<Ix>) -> &mut E {
+ self.edge_weight_mut(index).unwrap()
+ }
+}
+
+/// Create a new empty `StableGraph`.
+impl<N, E, Ty, Ix> Default for StableGraph<N, E, Ty, Ix>
+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<N, E, Ty, Ix> From<Graph<N, E, Ty, Ix>> for StableGraph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ fn from(g: Graph<N, E, Ty, Ix>) -> 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<N, E, Ty, Ix> From<StableGraph<N, E, Ty, Ix>> for Graph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ fn from(graph: StableGraph<N, E, Ty, Ix>) -> 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<slice::Iter<'a, Node<Option<N>, Ix>>>,
+}
+
+impl<'a, N, Ix> Iterator for NodeReferences<'a, N, Ix>
+where
+ Ix: IndexType,
+{
+ type Item = (NodeIndex<Ix>, &'a N);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter
+ .ex_find_map(|(i, node)| node.weight.as_ref().map(move |w| (node_index(i), w)))
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let (_, hi) = self.iter.size_hint();
+ (0, hi)
+ }
+}
+
+impl<N, Ix> DoubleEndedIterator for NodeReferences<'_, N, Ix>
+where
+ Ix: IndexType,
+{
+ fn next_back(&mut self) -> Option<Self::Item> {
+ 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<Ix>,
+ node: [NodeIndex<Ix>; 2],
+ weight: &'a E,
+}
+
+impl<E, Ix: IndexType> Clone for EdgeReference<'_, E, Ix> {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+impl<E, Ix: IndexType> Copy for EdgeReference<'_, E, Ix> {}
+
+impl<E, Ix: IndexType> 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<Ix>,
+ edges: &'a [Edge<Option<E>, Ix>],
+
+ /// Next edge to visit.
+ next: [EdgeIndex<Ix>; 2],
+
+ /// For directed graphs: the direction to iterate in
+ /// For undirected graphs: the direction of edges
+ direction: Direction,
+ ty: PhantomData<Ty>,
+}
+
+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<Self::Item> {
+ // 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<Ix>,
+ edges: Edges<'a, E, Ty, Ix>,
+ ty: PhantomData<Ty>,
+}
+
+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<EdgeReference<'a, E, Ix>> {
+ let target_node = self.target_node;
+ self.edges
+ .by_ref()
+ .find(|&edge| edge.node[1] == target_node)
+ }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let (_, upper) = self.edges.size_hint();
+ (0, upper)
+ }
+}
+
+fn swap_pair<T>(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<slice::Iter<'a, Edge<Option<E>, 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::Item> {
+ self.iter.ex_find_map(|(i, edge)| {
+ edge.weight.as_ref().map(move |weight| EdgeReference {
+ index: edge_index(i),
+ node: edge.node,
+ weight,
+ })
+ })
+ }
+}
+
+impl<E, Ix> DoubleEndedIterator for EdgeReferences<'_, E, Ix>
+where
+ Ix: IndexType,
+{
+ fn next_back(&mut self) -> Option<Self::Item> {
+ 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<slice::Iter<'a, Node<Option<N>, Ix>>>,
+ dir: Direction,
+ ty: PhantomData<Ty>,
+}
+
+impl<'a, N: 'a, Ty, Ix> Iterator for Externals<'a, N, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ type Item = NodeIndex<Ix>;
+ fn next(&mut self) -> Option<NodeIndex<Ix>> {
+ 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<usize>) {
+ 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<Ix>,
+ edges: &'a [Edge<Option<E>, Ix>],
+ next: [EdgeIndex<Ix>; 2],
+}
+
+impl<E, Ix> 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<Ix> {
+ WalkNeighbors {
+ inner: super::WalkNeighbors {
+ skip_start: self.skip_start,
+ next: self.next,
+ },
+ }
+ }
+}
+
+impl<E, Ix> Iterator for Neighbors<'_, E, Ix>
+where
+ Ix: IndexType,
+{
+ type Item = NodeIndex<Ix>;
+
+ fn next(&mut self) -> Option<NodeIndex<Ix>> {
+ // 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<Ix> {
+ inner: super::WalkNeighbors<Ix>,
+}
+
+impl<Ix: IndexType> Clone for WalkNeighbors<Ix> {
+ clone_fields!(WalkNeighbors, inner);
+}
+
+impl<Ix: IndexType> WalkNeighbors<Ix> {
+ /// 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<N, E, Ty: EdgeType>(
+ &mut self,
+ g: &StableGraph<N, E, Ty, Ix>,
+ ) -> Option<(EdgeIndex<Ix>, NodeIndex<Ix>)> {
+ self.inner.next(&g.g)
+ }
+
+ pub fn next_node<N, E, Ty: EdgeType>(
+ &mut self,
+ g: &StableGraph<N, E, Ty, Ix>,
+ ) -> Option<NodeIndex<Ix>> {
+ self.next(g).map(|t| t.1)
+ }
+
+ pub fn next_edge<N, E, Ty: EdgeType>(
+ &mut self,
+ g: &StableGraph<N, E, Ty, Ix>,
+ ) -> Option<EdgeIndex<Ix>> {
+ 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<slice::Iter<'a, Node<Option<N>, Ix>>>,
+}
+
+impl<N, Ix: IndexType> Iterator for NodeIndices<'_, N, Ix> {
+ type Item = NodeIndex<Ix>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.ex_find_map(|(i, node)| {
+ if node.weight.is_some() {
+ Some(node_index(i))
+ } else {
+ None
+ }
+ })
+ }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let (_, upper) = self.iter.size_hint();
+ (0, upper)
+ }
+}
+
+impl<N, Ix: IndexType> DoubleEndedIterator for NodeIndices<'_, N, Ix> {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ 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<slice::Iter<'a, Edge<Option<E>, Ix>>>,
+}
+
+impl<E, Ix: IndexType> Iterator for EdgeIndices<'_, E, Ix> {
+ type Item = EdgeIndex<Ix>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.ex_find_map(|(i, node)| {
+ if node.weight.is_some() {
+ Some(edge_index(i))
+ } else {
+ None
+ }
+ })
+ }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let (_, upper) = self.iter.size_hint();
+ (0, upper)
+ }
+}
+
+impl<E, Ix: IndexType> DoubleEndedIterator for EdgeIndices<'_, E, Ix> {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.iter.ex_rfind_map(|(i, node)| {
+ if node.weight.is_some() {
+ Some(edge_index(i))
+ } else {
+ None
+ }
+ })
+ }
+}
+
+impl<N, E, Ty, Ix> visit::GraphBase for StableGraph<N, E, Ty, Ix>
+where
+ Ix: IndexType,
+{
+ type NodeId = NodeIndex<Ix>;
+ type EdgeId = EdgeIndex<Ix>;
+}
+
+impl<N, E, Ty, Ix> visit::Visitable for StableGraph<N, E, Ty, Ix>
+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<N, E, Ty, Ix> visit::Data for StableGraph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ type NodeWeight = N;
+ type EdgeWeight = E;
+}
+
+impl<N, E, Ty, Ix> visit::GraphProp for StableGraph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ type EdgeType = Ty;
+}
+
+impl<'a, N, E: 'a, Ty, Ix> visit::IntoNodeIdentifiers for &'a StableGraph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ type NodeIdentifiers = NodeIndices<'a, N, Ix>;
+ fn node_identifiers(self) -> Self::NodeIdentifiers {
+ StableGraph::node_indices(self)
+ }
+}
+
+impl<N, E, Ty, Ix> visit::NodeCount for StableGraph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ fn node_count(&self) -> usize {
+ self.node_count()
+ }
+}
+
+impl<'a, N, E, Ty, Ix> visit::IntoNodeReferences for &'a StableGraph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ type NodeRef = (NodeIndex<Ix>, &'a N);
+ type NodeReferences = NodeReferences<'a, N, Ix>;
+ fn node_references(self) -> Self::NodeReferences {
+ NodeReferences {
+ iter: enumerate(self.raw_nodes()),
+ }
+ }
+}
+
+impl<N, E, Ty, Ix> visit::NodeIndexable for StableGraph<N, E, Ty, Ix>
+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<Ix>) -> 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<N, E, Ty, Ix>
+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<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ type NeighborsDirected = Neighbors<'a, E, Ix>;
+ fn neighbors_directed(self, n: NodeIndex<Ix>, d: Direction) -> Self::NeighborsDirected {
+ StableGraph::neighbors_directed(self, n, d)
+ }
+}
+
+impl<'a, N, E, Ty, Ix> visit::IntoEdges for &'a StableGraph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType,
+{
+ type Edges = Edges<'a, E, Ty, Ix>;
+ fn edges(self, a: Self::NodeId) -> Self::Edges {
+ self.edges(a)
+ }
+}
+
+impl<Ix, E> visit::EdgeRef for EdgeReference<'_, E, Ix>
+where
+ Ix: IndexType,
+{
+ type NodeId = NodeIndex<Ix>;
+ type EdgeId = EdgeIndex<Ix>;
+ 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<N, E, Ty, Ix> visit::EdgeIndexable for StableGraph<N, E, Ty, Ix>
+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<Ix>) -> 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<N, E, Ty, Ix>
+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<N, E, Ty, Ix>
+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<E, Ix>`.
+ fn edge_references(self) -> Self::EdgeReferences {
+ EdgeReferences {
+ iter: self.g.edges.iter().enumerate(),
+ }
+ }
+}
+
+impl<N, E, Ty, Ix> visit::EdgeCount for StableGraph<N, E, Ty, Ix>
+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<Option<N>, Ix>]>,
+ node_holes: Holes<&'a [Node<Option<N>, Ix>]>,
+ edge_property: EdgeProperty,
+ #[serde(serialize_with = "ser_stable_graph_edges")]
+ edges: &'a [Edge<Option<E>, 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<N, E, Ix> {
+ #[serde(deserialize_with = "deser_stable_graph_nodes")]
+ nodes: Vec<Node<Option<N>, Ix>>,
+ #[serde(default = "Vec::new")]
+ node_holes: Vec<NodeIndex<Ix>>,
+ edge_property: EdgeProperty,
+ #[serde(deserialize_with = "deser_stable_graph_edges")]
+ edges: Vec<Edge<Option<E>, Ix>>,
+}
+
+/// `Somes` are the present node weights N, with known length.
+struct Somes<T>(usize, T);
+
+impl<'a, N, Ix> Serialize for Somes<&'a [Node<Option<N>, Ix>]>
+where
+ N: Serialize,
+{
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ 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<T>(usize, T);
+
+impl<'a, N, Ix> Serialize for Holes<&'a [Node<Option<N>, Ix>]>
+where
+ Ix: Serialize + IndexType,
+{
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ 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::<Ix>::new(i))
+ } else {
+ None
+ }
+ }),
+ )
+ }
+}
+
+fn ser_stable_graph_edges<S, E, Ix>(
+ edges: &&[Edge<Option<E>, Ix>],
+ serializer: S,
+) -> Result<S::Ok, S::Error>
+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<Vec<Node<Option<N>, 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<Vec<Edge<Option<N>, Ix>>, D::Error>
+where
+ D: Deserializer<'de>,
+ N: Deserialize<'de>,
+ Ix: IndexType + Deserialize<'de>,
+{
+ deserializer.deserialize_seq(MappedSequenceVisitor::<
+ Option<(NodeIndex<Ix>, NodeIndex<Ix>, 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<N, E, Ty, Ix>
+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::<Ty>),
+ }
+ }
+}
+
+/// Requires crate feature `"serde-1"`
+impl<N, E, Ty, Ix> Serialize for StableGraph<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType + Serialize,
+ N: Serialize,
+ E: Serialize,
+{
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ self.into_serializable().serialize(serializer)
+ }
+}
+
+impl<'a, N, E, Ty, Ix> FromDeserialized for StableGraph<N, E, Ty, Ix>
+where
+ Ix: IndexType,
+ Ty: EdgeType,
+{
+ type Input = DeserStableGraph<N, E, Ix>;
+ fn from_deserialized<E2>(input: Self::Input) -> Result<Self, E2>
+ where
+ E2: Error,
+ {
+ let ty = PhantomData::<Ty>::from_deserialized(input.edge_property)?;
+ let node_holes = input.node_holes;
+ let edges = input.edges;
+ if edges.len() >= <Ix as IndexType>::max().index() {
+ Err(invalid_length_err::<Ix, _>("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() >= <Ix as IndexType>::max().index() {
+ Err(invalid_length_err::<Ix, _>("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<N, E, Ty, Ix>
+where
+ Ty: EdgeType,
+ Ix: IndexType + Deserialize<'de>,
+ N: Deserialize<'de>,
+ E: Deserialize<'de>,
+{
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ 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::<SerdeError>(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<N, E, Ty>` 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<N, E> = GraphMap<N, E, Undirected>;
+/// 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<N, E> = GraphMap<N, E, Directed>;
+
+/// `GraphMap<N, E, Ty>` 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<N, E, Ty, S = RandomState>
+where
+ S: BuildHasher,
+{
+ nodes: IndexMap<N, Vec<(N, CompactDirection)>, S>,
+ edges: IndexMap<(N, N), E, S>,
+ ty: PhantomData<Ty>,
+}
+
+impl<N: Eq + Hash + fmt::Debug, E: fmt::Debug, Ty: EdgeType, S: BuildHasher> fmt::Debug
+ for GraphMap<N, E, Ty, S>
+{
+ 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<N> 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<Direction> for CompactDirection {
+ fn from(d: Direction) -> Self {
+ match d {
+ Outgoing => CompactDirection::Outgoing,
+ Incoming => CompactDirection::Incoming,
+ }
+ }
+}
+
+impl From<CompactDirection> for Direction {
+ fn from(d: CompactDirection) -> Self {
+ match d {
+ CompactDirection::Outgoing => Outgoing,
+ CompactDirection::Incoming => Incoming,
+ }
+ }
+}
+
+impl PartialEq<Direction> for CompactDirection {
+ fn eq(&self, rhs: &Direction) -> bool {
+ (*self as usize) == (*rhs as usize)
+ }
+}
+
+#[cfg(feature = "serde-1")]
+impl<N, E, Ty, S> serde::Serialize for GraphMap<N, E, Ty, S>
+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<Ser>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error>
+ where
+ Ser: serde::Serializer,
+ {
+ let cloned_graph: GraphMap<N, E, Ty, S> = GraphMap::clone(self);
+ let equivalent_graph: Graph<N, E, Ty, u32> = cloned_graph.into_graph();
+ equivalent_graph.serialize(serializer)
+ }
+}
+
+#[cfg(feature = "serde-1")]
+impl<'de, N, E, Ty, S> serde::Deserialize<'de> for GraphMap<N, E, Ty, S>
+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<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ let equivalent_graph: Graph<N, E, Ty, u32> = Graph::deserialize(deserializer)?;
+ Ok(GraphMap::from_graph(equivalent_graph))
+ }
+}
+
+impl<N, E, Ty, S> GraphMap<N, E, Ty, S>
+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<I>(iterable: I) -> Self
+ where
+ I: IntoIterator,
+ I::Item: IntoWeightedEdge<E, NodeId = N>,
+ 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<E> {
+ 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<E> {
+ 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.<br>
+ /// Iterator element type is `N`.
+ pub fn neighbors(&self, a: N) -> Neighbors<N, Ty> {
+ 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.<br>
+ /// Iterator element type is `N`.
+ pub fn neighbors_directed(&self, a: N, dir: Direction) -> NeighborsDirected<N, Ty> {
+ 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.<br>
+ /// Iterator element type is `(N, N, &E)`.
+ pub fn edges(&self, a: N) -> Edges<N, E, Ty, S> {
+ 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.<br>
+ /// Iterator element type is `(N, N, &E)`.
+ pub fn edges_directed(&self, a: N, dir: Direction) -> EdgesDirected<N, E, Ty, S> {
+ 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<N, E, Ty> {
+ 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<N, E, Ty> {
+ 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<N, E, Ty>
+ 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<N, E, Ty>
+ 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<Ix>(self) -> Graph<N, E, Ty, Ix>
+ 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<Ix>(graph: Graph<N, E, Ty, Ix>) -> Self
+ where
+ Ix: crate::graph::IndexType,
+ E: Clone,
+ S: Default,
+ {
+ let mut new_graph: GraphMap<N, E, Ty, S> =
+ 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<N, E, Ty, Item, S> FromIterator<Item> for GraphMap<N, E, Ty, S>
+where
+ Item: IntoWeightedEdge<E, NodeId = N>,
+ N: NodeTrait,
+ Ty: EdgeType,
+ S: BuildHasher + Default,
+{
+ fn from_iter<I>(iterable: I) -> Self
+ where
+ I: IntoIterator<Item = Item>,
+ {
+ 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<N, E, Ty, Item, S> Extend<Item> for GraphMap<N, E, Ty, S>
+where
+ Item: IntoWeightedEdge<E, NodeId = N>,
+ N: NodeTrait,
+ Ty: EdgeType,
+ S: BuildHasher,
+{
+ fn extend<I>(&mut self, iterable: I)
+ where
+ I: IntoIterator<Item = Item>,
+ {
+ 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<Keys<'a, N, Vec<(N, CompactDirection)>>>,
+}
+
+#[derive(Debug, Clone)]
+pub struct Neighbors<'a, N, Ty = Undirected>
+where
+ N: 'a,
+ Ty: EdgeType,
+{
+ iter: Iter<'a, (N, CompactDirection)>,
+ ty: PhantomData<Ty>,
+}
+
+impl<N, Ty> Iterator for Neighbors<'_, N, Ty>
+where
+ N: NodeTrait,
+ Ty: EdgeType,
+{
+ type Item = N;
+ fn next(&mut self) -> Option<N> {
+ 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<usize>) {
+ 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<Ty>,
+}
+
+impl<N, Ty> Iterator for NeighborsDirected<'_, N, Ty>
+where
+ N: NodeTrait,
+ Ty: EdgeType,
+{
+ type Item = N;
+ fn next(&mut self) -> Option<N> {
+ 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<usize>) {
+ 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::Item> {
+ self.iter.next().map(|b| {
+ let a = self.from;
+ match self.edges.get(&GraphMap::<N, E, Ty>::edge_key(a, b)) {
+ None => unreachable!(),
+ Some(edge) => (a, b, edge),
+ }
+ })
+ }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ 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::Item> {
+ 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::<N, E, Ty>::edge_key(a, b)) {
+ None => unreachable!(),
+ Some(edge) => (a, b, edge),
+ }
+ })
+ }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ 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<Ty>,
+}
+
+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::Item> {
+ self.inner.next().map(|(&(a, b), v)| (a, b, v))
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.inner.size_hint()
+ }
+
+ fn count(self) -> usize {
+ self.inner.count()
+ }
+
+ fn nth(&mut self, n: usize) -> Option<Self::Item> {
+ self.inner
+ .nth(n)
+ .map(|(&(n1, n2), weight)| (n1, n2, weight))
+ }
+
+ fn last(self) -> Option<Self::Item> {
+ 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::Item> {
+ 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<Ty>,
+}
+
+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::Item> {
+ self.inner
+ .next()
+ .map(|(&(n1, n2), weight)| (n1, n2, weight))
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.inner.size_hint()
+ }
+
+ fn count(self) -> usize {
+ self.inner.count()
+ }
+
+ fn nth(&mut self, n: usize) -> Option<Self::Item> {
+ self.inner
+ .nth(n)
+ .map(|(&(n1, n2), weight)| (n1, n2, weight))
+ }
+
+ fn last(self) -> Option<Self::Item> {
+ 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::Item> {
+ self.inner
+ .next_back()
+ .map(|(&(n1, n2), weight)| (n1, n2, weight))
+ }
+}
+
+/// Index `GraphMap` by node pairs to access edge weights.
+impl<N, E, Ty, S> Index<(N, N)> for GraphMap<N, E, Ty, S>
+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<N, E, Ty, S> IndexMut<(N, N)> for GraphMap<N, E, Ty, S>
+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<N, E, Ty, S> Default for GraphMap<N, E, Ty, S>
+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<T>)`,
+/// with the `Cell<T>` being `TypedArena` allocated.
+pub struct Ptr<'b, T: 'b>(pub &'b T);
+
+impl<T> Copy for Ptr<'_, T> {}
+impl<T> Clone for Ptr<'_, T> {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+fn ptr_eq<T>(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<Ordering> {
+ 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<T> Deref for Ptr<'_, T> {
+ type Target = T;
+ fn deref(&self) -> &T {
+ self.0
+ }
+}
+
+impl<T> Eq for Ptr<'_, T> {}
+
+impl<T> Hash for Ptr<'_, T> {
+ fn hash<H: hash::Hasher>(&self, st: &mut H) {
+ let ptr = (self.0) as *const T;
+ ptr.hash(st)
+ }
+}
+
+impl<T: fmt::Debug> 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<Ty>,
+ edge_ty: PhantomData<E>,
+}
+
+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::Item> {
+ self.iter.next().map(|(&n, _)| n)
+ }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ 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<Ty>,
+ edge_ty: PhantomData<E>,
+}
+
+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::Item> {
+ self.iter.next().map(|(n, _)| (*n, n))
+ }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+}
+
+impl<N, E, Ty, S> visit::GraphBase for GraphMap<N, E, Ty, S>
+where
+ N: Copy + PartialEq,
+ S: BuildHasher,
+{
+ type NodeId = N;
+ type EdgeId = (N, N);
+}
+
+impl<N, E, Ty, S> visit::Data for GraphMap<N, E, Ty, S>
+where
+ N: Copy + PartialEq,
+ Ty: EdgeType,
+ S: BuildHasher,
+{
+ type NodeWeight = N;
+ type EdgeWeight = E;
+}
+
+impl<N, E, Ty, S> visit::Visitable for GraphMap<N, E, Ty, S>
+where
+ N: Copy + Ord + Hash,
+ Ty: EdgeType,
+ S: BuildHasher,
+{
+ type Map = HashSet<N>;
+ fn visit_map(&self) -> HashSet<N> {
+ HashSet::with_capacity(self.node_count())
+ }
+ fn reset_map(&self, map: &mut Self::Map) {
+ map.clear();
+ }
+}
+
+impl<N, E, Ty, S> visit::GraphProp for GraphMap<N, E, Ty, S>
+where
+ N: NodeTrait,
+ Ty: EdgeType,
+ S: BuildHasher,
+{
+ type EdgeType = Ty;
+}
+
+impl<'a, N, E, Ty, S> visit::IntoNodeReferences for &'a GraphMap<N, E, Ty, S>
+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<N, E, Ty, S>
+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<N, E, Ty, S> visit::NodeCount for GraphMap<N, E, Ty, S>
+where
+ N: NodeTrait,
+ Ty: EdgeType,
+ S: BuildHasher,
+{
+ fn node_count(&self) -> usize {
+ (*self).node_count()
+ }
+}
+
+impl<N, E, Ty, S> visit::NodeIndexable for GraphMap<N, E, Ty, S>
+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<N, E, Ty, S> visit::NodeCompactIndexable for GraphMap<N, E, Ty, S>
+where
+ N: NodeTrait,
+ Ty: EdgeType,
+ S: BuildHasher,
+{
+}
+
+impl<'a, N: 'a, E, Ty, S> visit::IntoNeighbors for &'a GraphMap<N, E, Ty, S>
+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<N, E, Ty, S>
+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<N, E, Ty, S> visit::EdgeIndexable for GraphMap<N, E, Ty, S>
+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<N, E, Ty, S>
+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<N, E, Ty, S>
+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<N, E, Ty, S>
+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<N, E, Ty, S> visit::EdgeCount for GraphMap<N, E, Ty, S>
+where
+ N: NodeTrait,
+ Ty: EdgeType,
+ S: BuildHasher,
+{
+ #[inline]
+ fn edge_count(&self) -> usize {
+ self.edge_count()
+ }
+}
+
+/// The `GraphMap` keeps an adjacency matrix internally.
+impl<N, E, Ty, S> visit::GetAdjacencyMatrix for GraphMap<N, E, Ty, S>
+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<C>(self, consumer: C) -> C::Result
+ where
+ C: rayon::iter::plumbing::UnindexedConsumer<Self::Item>,
+ {
+ self.iter.copied().drive_unindexed(consumer)
+ }
+
+ fn opt_len(&self) -> Option<usize> {
+ self.iter.opt_len()
+ }
+}
+
+#[cfg(feature = "rayon")]
+impl<'a, N> IndexedParallelIterator for ParNodes<'a, N>
+where
+ N: NodeTrait + Send + Sync,
+{
+ fn drive<C>(self, consumer: C) -> C::Result
+ where
+ C: rayon::iter::plumbing::Consumer<Self::Item>,
+ {
+ self.iter.copied().drive(consumer)
+ }
+
+ fn len(&self) -> usize {
+ self.iter.len()
+ }
+
+ fn with_producer<CB>(self, callback: CB) -> CB::Output
+ where
+ CB: rayon::iter::plumbing::ProducerCallback<Self::Item>,
+ {
+ 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<fn(Ty)>,
+}
+
+#[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<C>(self, c: C) -> C::Result
+ where
+ C: rayon::iter::plumbing::UnindexedConsumer<Self::Item>,
+ {
+ self.inner.map(|(&(a, b), v)| (a, b, v)).drive_unindexed(c)
+ }
+
+ fn opt_len(&self) -> Option<usize> {
+ 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<C>(self, consumer: C) -> C::Result
+ where
+ C: rayon::iter::plumbing::Consumer<Self::Item>,
+ {
+ self.inner.map(|(&(a, b), v)| (a, b, v)).drive(consumer)
+ }
+
+ fn len(&self) -> usize {
+ self.inner.len()
+ }
+
+ fn with_producer<CB>(self, callback: CB) -> CB::Output
+ where
+ CB: rayon::iter::plumbing::ProducerCallback<Self::Item>,
+ {
+ 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<fn(Ty)>,
+}
+
+#[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<C>(self, c: C) -> C::Result
+ where
+ C: rayon::iter::plumbing::UnindexedConsumer<Self::Item>,
+ {
+ self.inner.map(|(&(a, b), v)| (a, b, v)).drive_unindexed(c)
+ }
+
+ fn opt_len(&self) -> Option<usize> {
+ 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<C>(self, consumer: C) -> C::Result
+ where
+ C: rayon::iter::plumbing::Consumer<Self::Item>,
+ {
+ self.inner.map(|(&(a, b), v)| (a, b, v)).drive(consumer)
+ }
+
+ fn len(&self) -> usize {
+ self.inner.len()
+ }
+
+ fn with_producer<CB>(self, callback: CB) -> CB::Output
+ where
+ CB: rayon::iter::plumbing::ProducerCallback<Self::Item>,
+ {
+ 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<F>(pub F);
+
+impl<F, I, K, V> fmt::Debug for DebugMap<F>
+where
+ F: Fn() -> I,
+ I: IntoIterator<Item = (K, V)>,
+ 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<T>(pub T);
+
+impl<T> fmt::Debug for NoPretty<T>
+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<Option<I>>,
+}
+
+pub trait IterFormatExt: Iterator {
+ fn format(self, separator: &str) -> Format<Self>
+ where
+ Self: Sized,
+ {
+ Format {
+ sep: separator,
+ inner: RefCell::new(Some(self)),
+ }
+ }
+}
+
+impl<I> IterFormatExt for I where I: Iterator {}
+
+impl<I> Format<'_, I>
+where
+ I: Iterator,
+{
+ fn format<F>(&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<F, R>(&mut self, mut f: F) -> Option<R>
+ where
+ F: FnMut(Self::Item) -> Option<R>,
+ {
+ 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<F, R>(&mut self, mut f: F) -> Option<R>
+ where
+ F: FnMut(Self::Item) -> Option<R>,
+ Self: DoubleEndedIterator,
+ {
+ while let Some(elt) = self.next_back() {
+ if let result @ Some(_) = f(elt) {
+ return result;
+ }
+ }
+ None
+ }
+}
+
+impl<I> 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::<i32, ()>::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<N, E, Ty, Ix>` 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<E> {
+ type NodeId;
+ fn into_weighted_edge(self) -> (Self::NodeId, Self::NodeId, E);
+}
+
+impl<Ix, E> IntoWeightedEdge<E> 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<Ix, E> IntoWeightedEdge<E> for (Ix, Ix, E) {
+ type NodeId = Ix;
+ fn into_weighted_edge(self) -> (Ix, Ix, E) {
+ self
+ }
+}
+
+impl<Ix, E> IntoWeightedEdge<E> 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<Ix, E> IntoWeightedEdge<E> 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<Ix, E> IntoWeightedEdge<E> 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::Item> {
+ self.iter.next()
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ 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::Item> {
+ self.iter.next_back()
+ }
+ fn rfold<B, F>(self, accum: B, f: F) -> B
+ where
+ F: FnMut(B, Self::Item) -> B,
+ { self.iter.rfold(accum, f) }
+ fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
+ 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<N, E, Ty, NullN, NullE, Ix>` 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<Ix = DefaultIx> = GraphNodeIndex<Ix>;
+
+mod private {
+ pub trait Sealed {}
+
+ impl<T> Sealed for super::NotZero<T> {}
+ impl<T> Sealed for Option<T> {}
+}
+
+/// 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<Option<<Self as Nullable>::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<T> Nullable for Option<T> {
+ 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<E>` 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>(T);
+
+impl<T: Zero> Default for NotZero<T> {
+ fn default() -> Self {
+ NotZero(T::zero())
+ }
+}
+
+impl<T: Zero> Nullable for NotZero<T> {
+ #[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<T: Zero> From<NotZero<T>> for Option<T> {
+ fn from(not_zero: NotZero<T>) -> 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<N, E, Ty, Null>` 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<E>`). You may
+/// specify [`NotZero<E>`](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<N, E, Ty = Directed, Null: Nullable<Wrapped = E> = Option<E>, Ix = DefaultIx>
+{
+ node_adjacencies: Vec<Null>,
+ node_capacity: usize,
+ nodes: IdStorage<N>,
+ nb_edges: usize,
+ ty: PhantomData<Ty>,
+ ix: PhantomData<Ix>,
+}
+
+/// A `MatrixGraph` with directed edges.
+pub type DiMatrix<N, E, Null = Option<E>, Ix = DefaultIx> = MatrixGraph<N, E, Directed, Null, Ix>;
+
+/// A `MatrixGraph` with undirected edges.
+pub type UnMatrix<N, E, Null = Option<E>, Ix = DefaultIx> = MatrixGraph<N, E, Undirected, Null, Ix>;
+
+impl<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType>
+ MatrixGraph<N, E, Ty, Null, Ix>
+{
+ /// 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 <= <Ix as IndexType>::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<Ix>, b: NodeIndex<Ix>) -> Option<usize> {
+ 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<Ix>, b: NodeIndex<Ix>) -> usize {
+ to_linearized_matrix_position::<Ty>(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<Ix> {
+ 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<Ix>) -> 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<Ix>, exact: bool) {
+ self.node_capacity = extend_linearized_matrix::<Ty, _>(
+ &mut self.node_adjacencies,
+ self.node_capacity,
+ min_node.index() + 1,
+ exact,
+ );
+ }
+
+ #[inline]
+ fn extend_capacity_for_edge(&mut self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) {
+ 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<Ix>, b: NodeIndex<Ix>, weight: E) -> Option<E> {
+ 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<Ix>, b: NodeIndex<Ix>, 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<Ix>, b: NodeIndex<Ix>) -> 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<Ix>, b: NodeIndex<Ix>) -> 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<Ix>) -> &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<Ix>) -> &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<Ix>, b: NodeIndex<Ix>) -> &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<Ix>, b: NodeIndex<Ix>) -> &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.<br>
+ /// Iterator element type is [`NodeIndex<Ix>`](../graph/struct.NodeIndex.html).
+ pub fn neighbors(&self, a: NodeIndex<Ix>) -> Neighbors<Ty, Null, Ix> {
+ 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.<br>
+ /// Iterator element type is `(NodeIndex<Ix>, NodeIndex<Ix>, &E)`.
+ pub fn edges(&self, a: NodeIndex<Ix>) -> Edges<Ty, Null, Ix> {
+ 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<I>(iterable: I) -> Self
+ where
+ I: IntoIterator,
+ I::Item: IntoWeightedEdge<E>,
+ <I::Item as IntoWeightedEdge<E>>::NodeId: Into<NodeIndex<Ix>>,
+ 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<I>(&mut self, iterable: I)
+ where
+ I: IntoIterator,
+ I::Item: IntoWeightedEdge<E>,
+ <I::Item as IntoWeightedEdge<E>>::NodeId: Into<NodeIndex<Ix>>,
+ 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<N, E, Null: Nullable<Wrapped = E>, Ix: IndexType> MatrixGraph<N, E, Directed, Null, Ix> {
+ /// 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.<br>
+ /// Iterator element type is [`NodeIndex<Ix>`](../graph/struct.NodeIndex.html).
+ pub fn neighbors_directed(
+ &self,
+ a: NodeIndex<Ix>,
+ d: Direction,
+ ) -> Neighbors<Directed, Null, Ix> {
+ 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.<br>
+ /// Iterator element type is `(NodeIndex<Ix>, NodeIndex<Ix>, &E)`.
+ pub fn edges_directed(&self, a: NodeIndex<Ix>, d: Direction) -> Edges<Directed, Null, Ix> {
+ 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<Ix>,
+}
+
+impl<'a, Ix: IndexType> NodeIdentifiers<'a, Ix> {
+ fn new(iter: IdIterator<'a>) -> Self {
+ Self {
+ iter,
+ ix: PhantomData,
+ }
+ }
+}
+
+impl<Ix: IndexType> Iterator for NodeIdentifiers<'_, Ix> {
+ type Item = NodeIndex<Ix>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.next().map(NodeIndex::new)
+ }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ 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<N>,
+ iter: IdIterator<'a>,
+ ix: PhantomData<Ix>,
+}
+
+impl<'a, N: 'a, Ix> NodeReferences<'a, N, Ix> {
+ fn new(nodes: &'a IdStorage<N>) -> Self {
+ NodeReferences {
+ nodes,
+ iter: nodes.iter_ids(),
+ ix: PhantomData,
+ }
+ }
+}
+
+impl<'a, N: 'a, Ix: IndexType> Iterator for NodeReferences<'a, N, Ix> {
+ type Item = (NodeIndex<Ix>, &'a N);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter
+ .next()
+ .map(|i| (NodeIndex::new(i), &self.nodes[i]))
+ }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ 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<Ty>,
+ ix: PhantomData<Ix>,
+}
+
+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<Ix>, NodeIndex<Ix>, &'a Null::Wrapped);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ 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::<Ty>(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<Ix>`.
+///
+/// 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<Ty: EdgeType, Null: Nullable, Ix: IndexType> Iterator for Neighbors<'_, Ty, Null, Ix> {
+ type Item = NodeIndex<Ix>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.0.next().map(|(_, b, _)| b)
+ }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ 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<Ty>,
+ ix: PhantomData<Ix>,
+}
+
+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<Ix>, NodeIndex<Ix>, &'a Null::Wrapped);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ 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::<Ty>(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<Ty: EdgeType>(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<Ty: EdgeType, T: Default>(
+ node_adjacencies: &mut Vec<T>,
+ 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<T: Default>(
+ node_adjacencies: &mut Vec<T>,
+ 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<T: Default>(
+ node_adjacencies: &mut Vec<T>,
+ 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<T: Default>(v: &mut Vec<T>, size: usize) {
+ v.resize_with(size, T::default);
+}
+
+#[derive(Debug, Clone)]
+struct IdStorage<T> {
+ elements: Vec<Option<T>>,
+ upper_bound: usize,
+ removed_ids: IndexSet<usize>,
+}
+
+impl<T> IdStorage<T> {
+ 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<T> Index<usize> for IdStorage<T> {
+ type Output = T;
+ fn index(&self, index: usize) -> &T {
+ self.elements[index].as_ref().unwrap()
+ }
+}
+
+impl<T> IndexMut<usize> for IdStorage<T> {
+ 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<usize>,
+ current: Option<usize>,
+}
+
+impl Iterator for IdIterator<'_> {
+ type Item = usize;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ // 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<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> Default
+ for MatrixGraph<N, E, Ty, Null, Ix>
+{
+ fn default() -> Self {
+ Self::with_capacity(0)
+ }
+}
+
+impl<N, E> MatrixGraph<N, E, Directed> {
+ /// 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<N, E> MatrixGraph<N, E, Undirected> {
+ /// 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<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> Index<NodeIndex<Ix>>
+ for MatrixGraph<N, E, Ty, Null, Ix>
+{
+ type Output = N;
+
+ fn index(&self, ax: NodeIndex<Ix>) -> &N {
+ self.node_weight(ax)
+ }
+}
+
+/// Index the `MatrixGraph` by `NodeIndex` to access node weights.
+///
+/// **Panics** if the node doesn't exist.
+impl<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> IndexMut<NodeIndex<Ix>>
+ for MatrixGraph<N, E, Ty, Null, Ix>
+{
+ fn index_mut(&mut self, ax: NodeIndex<Ix>) -> &mut N {
+ self.node_weight_mut(ax)
+ }
+}
+
+impl<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> NodeCount
+ for MatrixGraph<N, E, Ty, Null, Ix>
+{
+ fn node_count(&self) -> usize {
+ MatrixGraph::node_count(self)
+ }
+}
+
+impl<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> EdgeCount
+ for MatrixGraph<N, E, Ty, Null, Ix>
+{
+ #[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<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType>
+ Index<(NodeIndex<Ix>, NodeIndex<Ix>)> for MatrixGraph<N, E, Ty, Null, Ix>
+{
+ type Output = E;
+
+ fn index(&self, (ax, bx): (NodeIndex<Ix>, NodeIndex<Ix>)) -> &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<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType>
+ IndexMut<(NodeIndex<Ix>, NodeIndex<Ix>)> for MatrixGraph<N, E, Ty, Null, Ix>
+{
+ fn index_mut(&mut self, (ax, bx): (NodeIndex<Ix>, NodeIndex<Ix>)) -> &mut E {
+ self.edge_weight_mut(ax, bx)
+ }
+}
+
+impl<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> GetAdjacencyMatrix
+ for MatrixGraph<N, E, Ty, Null, Ix>
+{
+ type AdjMatrix = ();
+
+ fn adjacency_matrix(&self) -> Self::AdjMatrix {}
+
+ fn is_adjacent(&self, _: &Self::AdjMatrix, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> bool {
+ MatrixGraph::has_edge(self, a, b)
+ }
+}
+
+impl<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> Visitable
+ for MatrixGraph<N, E, Ty, Null, Ix>
+{
+ 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<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> GraphBase
+ for MatrixGraph<N, E, Ty, Null, Ix>
+{
+ type NodeId = NodeIndex<Ix>;
+ type EdgeId = (NodeIndex<Ix>, NodeIndex<Ix>);
+}
+
+impl<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> GraphProp
+ for MatrixGraph<N, E, Ty, Null, Ix>
+{
+ type EdgeType = Ty;
+}
+
+impl<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> Data
+ for MatrixGraph<N, E, Ty, Null, Ix>
+{
+ type NodeWeight = N;
+ type EdgeWeight = E;
+}
+
+impl<'a, N, E: 'a, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> IntoNodeIdentifiers
+ for &'a MatrixGraph<N, E, Ty, Null, Ix>
+{
+ 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<Wrapped = E>, Ix: IndexType> IntoNeighbors
+ for &'a MatrixGraph<N, E, Ty, Null, Ix>
+{
+ type Neighbors = Neighbors<'a, Ty, Null, Ix>;
+
+ fn neighbors(self, a: NodeIndex<Ix>) -> Self::Neighbors {
+ MatrixGraph::neighbors(self, a)
+ }
+}
+
+impl<'a, N, E: 'a, Null: Nullable<Wrapped = E>, Ix: IndexType> IntoNeighborsDirected
+ for &'a MatrixGraph<N, E, Directed, Null, Ix>
+{
+ type NeighborsDirected = Neighbors<'a, Directed, Null, Ix>;
+
+ fn neighbors_directed(self, a: NodeIndex<Ix>, d: Direction) -> Self::NeighborsDirected {
+ MatrixGraph::neighbors_directed(self, a, d)
+ }
+}
+
+impl<'a, N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> IntoNodeReferences
+ for &'a MatrixGraph<N, E, Ty, Null, Ix>
+{
+ type NodeRef = (NodeIndex<Ix>, &'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<Wrapped = E>, Ix: IndexType> IntoEdgeReferences
+ for &'a MatrixGraph<N, E, Ty, Null, Ix>
+{
+ type EdgeRef = (NodeIndex<Ix>, NodeIndex<Ix>, &'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<Wrapped = E>, Ix: IndexType> IntoEdges
+ for &'a MatrixGraph<N, E, Ty, Null, Ix>
+{
+ 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<Wrapped = E>, Ix: IndexType> IntoEdgesDirected
+ for &'a MatrixGraph<N, E, Directed, Null, Ix>
+{
+ 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<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> NodeIndexable
+ for MatrixGraph<N, E, Ty, Null, Ix>
+{
+ fn node_bound(&self) -> usize {
+ self.nodes.upper_bound
+ }
+
+ fn to_index(&self, ix: NodeIndex<Ix>) -> usize {
+ ix.index()
+ }
+
+ fn from_index(&self, ix: usize) -> Self::NodeId {
+ NodeIndex::new(ix)
+ }
+}
+
+impl<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> Build
+ for MatrixGraph<N, E, Ty, Null, Ix>
+{
+ 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<Self::EdgeId> {
+ 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::<i32, i32>::new();
+ assert_eq!(g.node_count(), 0);
+ assert_eq!(g.edge_count(), 0);
+ }
+
+ #[test]
+ fn test_default() {
+ let g = MatrixGraph::<i32, i32>::default();
+ assert_eq!(g.node_count(), 0);
+ assert_eq!(g.edge_count(), 0);
+ }
+
+ #[test]
+ fn test_with_capacity() {
+ let g = MatrixGraph::<i32, i32>::with_capacity(10);
+ assert_eq!(g.node_count(), 0);
+ assert_eq!(g.edge_count(), 0);
+ }
+
+ #[test]
+ fn test_node_indexing() {
+ let mut g: MatrixGraph<char, ()> = 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<char, ()> = 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::<u8, ()>::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::<u8, ()>::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::<Vec<_>>()`
+ trait IntoVec<T> {
+ fn into_vec(self) -> Vec<T>;
+ }
+
+ impl<It, T> IntoVec<T> for It
+ where
+ It: Iterator<Item = T>,
+ {
+ fn into_vec(self) -> Vec<T> {
+ 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<T> {
+ fn into_sorted_vec(self) -> Vec<T>;
+ }
+
+ impl<It, T> IntoSortedVec<T> for It
+ where
+ It: Iterator<Item = T>,
+ T: Ord,
+ {
+ fn into_sorted_vec(self) -> Vec<T> {
+ let mut v: Vec<T> = 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<char, bool> = 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<char, bool> = 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<char, bool> = MatrixGraph::new();
+ assert_eq!(g.edges(node_index(0)).count(), 0);
+ }
+
+ #[test]
+ fn test_neighbors_of_absent_node_is_empty_iterator() {
+ let g: MatrixGraph<char, bool> = MatrixGraph::new();
+ assert_eq!(g.neighbors(node_index(0)).count(), 0);
+ }
+
+ #[test]
+ fn test_edge_references() {
+ let g: MatrixGraph<char, bool> = 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<char, bool> = 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<char> = 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<i32>> = 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<i32>> = 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<f32>> = 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<N, E, Ty, Ix>(
+ input: &Graph<N, E, Ty, Ix>,
+ output: &mut Graph<N, E, Ty, Ix>,
+ 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: Gen>(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<N, E, Ty, Ix> Arbitrary for Graph<N, E, Ty, Ix>
+where
+ N: Arbitrary,
+ E: Arbitrary,
+ Ty: EdgeType + Send + 'static,
+ Ix: IndexType + Send,
+{
+ fn arbitrary<G: Gen>(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<dyn Iterator<Item = Self>> {
+ 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<N, E, Ty, Ix> Arbitrary for StableGraph<N, E, Ty, Ix>
+where
+ N: Arbitrary,
+ E: Arbitrary,
+ Ty: EdgeType + Send + 'static,
+ Ix: IndexType + Send,
+{
+ fn arbitrary<G: Gen>(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<dyn Iterator<Item = Self>> {
+ 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<N, E, Ty> Arbitrary for GraphMap<N, E, Ty>
+where
+ N: NodeTrait + Arbitrary,
+ E: Arbitrary,
+ Ty: EdgeType + Clone + Send + 'static,
+{
+ fn arbitrary<G: Gen>(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::<Vec<_>>();
+ 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<K, T>` 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<K, T>(pub K, pub T);
+
+impl<K: PartialOrd, T> PartialEq for MinScored<K, T> {
+ #[inline]
+ fn eq(&self, other: &MinScored<K, T>) -> bool {
+ self.cmp(other) == Ordering::Equal
+ }
+}
+
+impl<K: PartialOrd, T> Eq for MinScored<K, T> {}
+
+impl<K: PartialOrd, T> PartialOrd for MinScored<K, T> {
+ #[inline]
+ fn partial_cmp(&self, other: &MinScored<K, T>) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl<K: PartialOrd, T> Ord for MinScored<K, T> {
+ #[inline]
+ fn cmp(&self, other: &MinScored<K, T>) -> 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<K, T>(pub K, pub T);
+
+impl<K: PartialOrd, T> PartialEq for MaxScored<K, T> {
+ #[inline]
+ fn eq(&self, other: &MaxScored<K, T>) -> bool {
+ self.cmp(other) == Ordering::Equal
+ }
+}
+
+impl<K: PartialOrd, T> Eq for MaxScored<K, T> {}
+
+impl<K: PartialOrd, T> PartialOrd for MaxScored<K, T> {
+ #[inline]
+ fn partial_cmp(&self, other: &MaxScored<K, T>) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl<K: PartialOrd, T> Ord for MaxScored<K, T> {
+ #[inline]
+ fn cmp(&self, other: &MaxScored<K, T>) -> 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<E>(input: Self::Input) -> Result<Self, E>
+ 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<T, R, F>
+where
+ F: Fn(T) -> Result<R, &'static str>,
+{
+ f: F,
+ marker: PhantomData<fn() -> T>,
+}
+
+impl<'de, F, T, R> MappedSequenceVisitor<T, R, F>
+where
+ T: Deserialize<'de>,
+ F: Fn(T) -> Result<R, &'static str>,
+{
+ pub fn new(f: F) -> Self {
+ MappedSequenceVisitor {
+ f: f,
+ marker: PhantomData,
+ }
+ }
+}
+
+impl<'de, F, T, R> Visitor<'de> for MappedSequenceVisitor<T, R, F>
+where
+ T: Deserialize<'de>,
+ F: Fn(T) -> Result<R, &'static str>,
+{
+ type Value = Vec<R>;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ write!(formatter, "a sequence")
+ }
+ fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
+ where
+ A: SeqAccess<'de>,
+ {
+ let mut v = Vec::new();
+ while let Some(elem) = seq.next_element()? {
+ match (self.f)(elem) {
+ Err(s) => Err(<A::Error>::custom(s))?,
+ Ok(x) => v.push(x),
+ }
+ }
+ Ok(v)
+ }
+}
+
+pub trait CollectSeqWithLength: Serializer {
+ fn collect_seq_with_length<I>(self, length: usize, iterable: I) -> Result<Self::Ok, Self::Error>
+ 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<I>(self, iterable: I) -> Result<Self::Ok, Self::Error>
+ where
+ I: IntoIterator,
+ I::Item: Serialize,
+ I::IntoIter: ExactSizeIterator,
+ {
+ let iter = iterable.into_iter();
+ self.collect_seq_with_length(iter.len(), iter)
+ }
+}
+
+impl<S> 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<N, E, Ty, Ix> GetAdjacencyMatrix for Graph<N, E, Ty, Ix>
+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<Ix>, b: NodeIndex<Ix>) -> 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<N, E, Ty, Ix> GetAdjacencyMatrix for StableGraph<N, E, Ty, Ix>
+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<Ix>, b: NodeIndex<Ix>) -> 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<K>` is a disjoint-set data structure.
+
+use super::graph::IndexType;
+use std::cmp::Ordering;
+
+/// `UnionFind<K>` 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.
+///
+/// <http://en.wikipedia.org/wiki/Disjoint-set_data_structure>
+///
+/// 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<K> {
+ // 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<K>,
+ // 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<u8>,
+}
+
+#[inline]
+unsafe fn get_unchecked<K>(xs: &[K], index: usize) -> &K {
+ debug_assert!(index < xs.len());
+ xs.get_unchecked(index)
+}
+
+#[inline]
+unsafe fn get_unchecked_mut<K>(xs: &mut [K], index: usize) -> &mut K {
+ debug_assert!(index < xs.len());
+ xs.get_unchecked_mut(index)
+}
+
+impl<K> UnionFind<K>
+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::<Vec<K>>();
+
+ 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<K> {
+ // 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<I>(iterable: I) -> iter::Enumerate<I::IntoIter>
+where
+ I: IntoIterator,
+{
+ iterable.into_iter().enumerate()
+}
+
+pub fn zip<I, J>(i: I, j: J) -> iter::Zip<I::IntoIter, J::IntoIter>
+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<N> {
+ 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<B> {
+ /// 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<B> Control<B> {
+ pub fn breaking() -> Control<()> {
+ Control::Break(())
+ }
+ /// Get the value in `Control::Break(_)`, if present.
+ pub fn break_value(self) -> Option<B> {
+ 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<B> ControlFlow for Control<B> {
+ 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<C: ControlFlow, E> ControlFlow for Result<C, E> {
+ 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<B> Default for Control<B> {
+ 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<C, E>` 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<G, I, F, C>(graph: G, starts: I, mut visitor: F) -> C
+where
+ G: IntoNeighbors + Visitable,
+ I: IntoIterator<Item = G::NodeId>,
+ F: FnMut(DfsEvent<G::NodeId>) -> 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<G, F, C>(
+ graph: G,
+ u: G::NodeId,
+ visitor: &mut F,
+ discovered: &mut impl VisitMap<G::NodeId>,
+ finished: &mut impl VisitMap<G::NodeId>,
+ time: &mut Time,
+) -> C
+where
+ G: IntoNeighbors + Visitable,
+ F: FnMut(DfsEvent<G::NodeId>) -> 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<N> {
+ /// Return true to have the node be part of the graph
+ fn include_node(&self, node: N) -> bool;
+}
+
+impl<F, N> FilterNode<N> 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<N> FilterNode<N> for FixedBitSet
+where
+ FixedBitSet: VisitMap<N>,
+{
+ fn include_node(&self, n: N) -> bool {
+ self.is_visited(&n)
+ }
+}
+
+/// This filter includes the nodes that are contained in the set.
+impl<N, S> FilterNode<N> for HashSet<N, S>
+where
+ HashSet<N, S>: VisitMap<N>,
+{
+ 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<N> FilterNode<N> for &FixedBitSet
+where
+ FixedBitSet: VisitMap<N>,
+{
+ fn include_node(&self, n: N) -> bool {
+ self.is_visited(&n)
+ }
+}
+
+impl<N, S> FilterNode<N> for &HashSet<N, S>
+where
+ HashSet<N, S>: VisitMap<N>,
+{
+ fn include_node(&self, n: N) -> bool {
+ self.is_visited(&n)
+ }
+}
+
+/// A node-filtering graph adaptor.
+#[derive(Copy, Clone, Debug)]
+pub struct NodeFiltered<G, F>(pub G, pub F);
+
+impl<F, G> NodeFiltered<G, F>
+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<G, F> GraphBase for NodeFiltered<G, F>
+where
+ G: GraphBase,
+{
+ type NodeId = G::NodeId;
+ type EdgeId = G::EdgeId;
+}
+
+impl<'a, G, F> IntoNeighbors for &'a NodeFiltered<G, F>
+where
+ G: IntoNeighbors,
+ F: FilterNode<G::NodeId>,
+{
+ 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<I, F> Iterator for NodeFilteredNeighbors<'_, I, F>
+where
+ I: Iterator,
+ I::Item: Copy,
+ F: FilterNode<I::Item>,
+{
+ type Item = I::Item;
+ fn next(&mut self) -> Option<Self::Item> {
+ 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<usize>) {
+ let (_, upper) = self.iter.size_hint();
+ (0, upper)
+ }
+}
+
+impl<'a, G, F> IntoNeighborsDirected for &'a NodeFiltered<G, F>
+where
+ G: IntoNeighborsDirected,
+ F: FilterNode<G::NodeId>,
+{
+ 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<G, F>
+where
+ G: IntoNodeIdentifiers,
+ F: FilterNode<G::NodeId>,
+{
+ 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<G, F>
+where
+ G: IntoNodeReferences,
+ F: FilterNode<G::NodeId>,
+{
+ 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<I, F> Iterator for NodeFilteredNodes<'_, I, F>
+where
+ I: Iterator,
+ I::Item: Copy + NodeRef,
+ F: FilterNode<<I::Item as NodeRef>::NodeId>,
+{
+ type Item = I::Item;
+ fn next(&mut self) -> Option<Self::Item> {
+ 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<usize>) {
+ let (_, upper) = self.iter.size_hint();
+ (0, upper)
+ }
+}
+
+impl<'a, G, F> IntoEdgeReferences for &'a NodeFiltered<G, F>
+where
+ G: IntoEdgeReferences,
+ F: FilterNode<G::NodeId>,
+{
+ 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<G>,
+ iter: I,
+ f: &'a F,
+}
+
+impl<G, I, F> Iterator for NodeFilteredEdgeReferences<'_, G, I, F>
+where
+ F: FilterNode<G::NodeId>,
+ G: IntoEdgeReferences,
+ I: Iterator<Item = G::EdgeRef>,
+{
+ type Item = I::Item;
+ fn next(&mut self) -> Option<Self::Item> {
+ 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<usize>) {
+ let (_, upper) = self.iter.size_hint();
+ (0, upper)
+ }
+}
+
+impl<'a, G, F> IntoEdges for &'a NodeFiltered<G, F>
+where
+ G: IntoEdges,
+ F: FilterNode<G::NodeId>,
+{
+ 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<G, F>
+where
+ G: IntoEdgesDirected,
+ F: FilterNode<G::NodeId>,
+{
+ 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<G>,
+ include_source: bool,
+ iter: I,
+ f: &'a F,
+ dir: Direction,
+}
+
+impl<G, I, F> Iterator for NodeFilteredEdges<'_, G, I, F>
+where
+ F: FilterNode<G::NodeId>,
+ G: IntoEdges,
+ I: Iterator<Item = G::EdgeRef>,
+{
+ type Item = I::Item;
+ fn next(&mut self) -> Option<Self::Item> {
+ 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<usize>) {
+ let (_, upper) = self.iter.size_hint();
+ (0, upper)
+ }
+}
+
+impl<G, F> DataMap for NodeFiltered<G, F>
+where
+ G: DataMap,
+ F: FilterNode<G::NodeId>,
+{
+ 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<G, F>, access0]}
+NodeIndexable! {delegate_impl [[G, F], G, NodeFiltered<G, F>, access0]}
+EdgeIndexable! {delegate_impl [[G, F], G, NodeFiltered<G, F>, access0]}
+GraphProp! {delegate_impl [[G, F], G, NodeFiltered<G, F>, access0]}
+Visitable! {delegate_impl [[G, F], G, NodeFiltered<G, F>, access0]}
+
+/// A graph filter for edges
+pub trait FilterEdge<Edge> {
+ /// Return true to have the edge be part of the graph
+ fn include_edge(&self, edge: Edge) -> bool;
+}
+
+impl<F, N> FilterEdge<N> 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<G, F>(pub G, pub F);
+
+impl<F, G> EdgeFiltered<G, F>
+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<G, F> GraphBase for EdgeFiltered<G, F>
+where
+ G: GraphBase,
+{
+ type NodeId = G::NodeId;
+ type EdgeId = G::EdgeId;
+}
+
+impl<'a, G, F> IntoNeighbors for &'a EdgeFiltered<G, F>
+where
+ G: IntoEdges,
+ F: FilterEdge<G::EdgeRef>,
+{
+ 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<G, F>
+where
+ G: IntoEdgesDirected,
+ F: FilterEdge<G::EdgeRef>,
+{
+ 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<G, F> Iterator for EdgeFilteredNeighbors<'_, G, F>
+where
+ F: FilterEdge<G::EdgeRef>,
+ G: IntoEdges,
+{
+ type Item = G::NodeId;
+ fn next(&mut self) -> Option<Self::Item> {
+ 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<usize>) {
+ let (_, upper) = self.iter.size_hint();
+ (0, upper)
+ }
+}
+
+impl<'a, G, F> IntoEdgeReferences for &'a EdgeFiltered<G, F>
+where
+ G: IntoEdgeReferences,
+ F: FilterEdge<G::EdgeRef>,
+{
+ 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<G, F>
+where
+ G: IntoEdges,
+ F: FilterEdge<G::EdgeRef>,
+{
+ 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<G, F>
+where
+ G: IntoEdgesDirected,
+ F: FilterEdge<G::EdgeRef>,
+{
+ 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<G>,
+ iter: I,
+ f: &'a F,
+}
+
+impl<G, I, F> Iterator for EdgeFilteredEdges<'_, G, I, F>
+where
+ F: FilterEdge<G::EdgeRef>,
+ G: IntoEdgeReferences,
+ I: Iterator<Item = G::EdgeRef>,
+{
+ type Item = I::Item;
+ fn next(&mut self) -> Option<Self::Item> {
+ let f = self.f;
+ self.iter.find(move |&edge| f.include_edge(edge))
+ }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ 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<G, F> Iterator for EdgeFilteredNeighborsDirected<'_, G, F>
+where
+ F: FilterEdge<G::EdgeRef>,
+ G: IntoEdgesDirected,
+{
+ type Item = G::NodeId;
+ fn next(&mut self) -> Option<Self::Item> {
+ 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<usize>) {
+ let (_, upper) = self.iter.size_hint();
+ (0, upper)
+ }
+}
+
+Data! {delegate_impl [[G, F], G, EdgeFiltered<G, F>, access0]}
+GraphProp! {delegate_impl [[G, F], G, EdgeFiltered<G, F>, access0]}
+IntoNodeIdentifiers! {delegate_impl [['a, G, F], G, &'a EdgeFiltered<G, F>, access0]}
+IntoNodeReferences! {delegate_impl [['a, G, F], G, &'a EdgeFiltered<G, F>, access0]}
+NodeCompactIndexable! {delegate_impl [[G, F], G, EdgeFiltered<G, F>, access0]}
+NodeCount! {delegate_impl [[G, F], G, EdgeFiltered<G, F>, access0]}
+NodeIndexable! {delegate_impl [[G, F], G, EdgeFiltered<G, F>, access0]}
+EdgeIndexable! {delegate_impl [[G, F], G, EdgeFiltered<G, F>, access0]}
+Visitable! {delegate_impl [[G, F], G, EdgeFiltered<G, F>, 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<G> 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<Item=Self::NodeId>;
+ @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<Item=Self::NodeId>;
+ @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<Item=Self::EdgeRef>;
+ @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<Item=Self::EdgeRef>;
+ @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<Item=Self::NodeId>;
+ @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<N, E> 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<NodeId=Self::NodeId, Weight=Self::NodeWeight>;
+ type NodeReferences: Iterator<Item=Self::NodeRef>;
+ @section self
+ fn node_references(self) -> Self::NodeReferences;
+}
+}
+
+IntoNodeReferences! {delegate_impl []}
+
+impl<Id> 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<Id, W> 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<NodeId=Self::NodeId, EdgeId=Self::EdgeId,
+ Weight=Self::EdgeWeight>;
+ type EdgeReferences: Iterator<Item=Self::EdgeRef>;
+ @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 {
+ <Self::EdgeType>::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<N> {
+ /// 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<Ix> VisitMap<Ix> 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<N, S> VisitMap<N> for HashSet<N, S>
+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<Self::NodeId>;
+ @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<G>(pub G);
+
+impl<G: GraphBase> GraphBase for Reversed<G> {
+ type NodeId = G::NodeId;
+ type EdgeId = G::EdgeId;
+}
+
+impl<G: GraphRef> GraphRef for Reversed<G> {}
+
+Data! {delegate_impl [[G], G, Reversed<G>, access0]}
+
+impl<G> IntoNeighbors for Reversed<G>
+where
+ G: IntoNeighborsDirected,
+{
+ type Neighbors = G::NeighborsDirected;
+ fn neighbors(self, n: G::NodeId) -> G::NeighborsDirected {
+ self.0.neighbors_directed(n, Incoming)
+ }
+}
+
+impl<G> IntoNeighborsDirected for Reversed<G>
+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<G> IntoEdges for Reversed<G>
+where
+ G: IntoEdgesDirected,
+{
+ type Edges = ReversedEdges<G::EdgesDirected>;
+ fn edges(self, a: Self::NodeId) -> Self::Edges {
+ ReversedEdges {
+ iter: self.0.edges_directed(a, Incoming),
+ }
+ }
+}
+
+impl<G> IntoEdgesDirected for Reversed<G>
+where
+ G: IntoEdgesDirected,
+{
+ type EdgesDirected = ReversedEdges<G::EdgesDirected>;
+ fn edges_directed(self, a: Self::NodeId, dir: Direction) -> Self::Edges {
+ ReversedEdges {
+ iter: self.0.edges_directed(a, dir.opposite()),
+ }
+ }
+}
+
+impl<G: Visitable> Visitable for Reversed<G> {
+ 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<I> {
+ iter: I,
+}
+
+impl<I> Iterator for ReversedEdges<I>
+where
+ I: Iterator,
+ I::Item: EdgeRef,
+{
+ type Item = ReversedEdgeReference<I::Item>;
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.next().map(ReversedEdgeReference)
+ }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+}
+
+/// A reversed edge reference
+#[derive(Copy, Clone, Debug)]
+pub struct ReversedEdgeReference<R>(R);
+
+impl<R> ReversedEdgeReference<R> {
+ /// 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<R> EdgeRef for ReversedEdgeReference<R>
+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<G> IntoEdgeReferences for Reversed<G>
+where
+ G: IntoEdgeReferences,
+{
+ type EdgeRef = ReversedEdgeReference<G::EdgeRef>;
+ type EdgeReferences = ReversedEdgeReferences<G::EdgeReferences>;
+ fn edge_references(self) -> Self::EdgeReferences {
+ ReversedEdgeReferences {
+ iter: self.0.edge_references(),
+ }
+ }
+}
+
+/// A reversed edge references iterator.
+#[derive(Debug, Clone)]
+pub struct ReversedEdgeReferences<I> {
+ iter: I,
+}
+
+impl<I> Iterator for ReversedEdgeReferences<I>
+where
+ I: Iterator,
+ I::Item: EdgeRef,
+{
+ type Item = ReversedEdgeReference<I::Item>;
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.next().map(ReversedEdgeReference)
+ }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+}
+
+macro_rules! access0 {
+ ($e:expr) => {
+ $e.0
+ };
+}
+
+NodeIndexable! {delegate_impl [[G], G, Reversed<G>, access0]}
+NodeCompactIndexable! {delegate_impl [[G], G, Reversed<G>, access0]}
+IntoNodeIdentifiers! {delegate_impl [[G], G, Reversed<G>, access0]}
+IntoNodeReferences! {delegate_impl [[G], G, Reversed<G>, access0]}
+GraphProp! {delegate_impl [[G], G, Reversed<G>, access0]}
+NodeCount! {delegate_impl [[G], G, Reversed<G>, access0]}
+EdgeCount! {delegate_impl [[G], G, Reversed<G>, access0]}
+EdgeIndexable! {delegate_impl [[G], G, Reversed<G>, access0]}
+GetAdjacencyMatrix! {delegate_impl [[G], G, Reversed<G>, 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<N, VM> {
+ /// The stack of nodes to visit
+ pub stack: Vec<N>,
+ /// The map of discovered nodes
+ pub discovered: VM,
+}
+
+impl<N, VM> Default for Dfs<N, VM>
+where
+ VM: Default,
+{
+ fn default() -> Self {
+ Dfs {
+ stack: Vec::new(),
+ discovered: VM::default(),
+ }
+ }
+}
+
+impl<N, VM> Dfs<N, VM>
+where
+ N: Copy + PartialEq,
+ VM: VisitMap<N>,
+{
+ /// Create a new **Dfs**, using the graph's visitor map, and put **start**
+ /// in the stack of nodes to visit.
+ pub fn new<G>(graph: G, start: N) -> Self
+ where
+ G: GraphRef + Visitable<NodeId = N, Map = VM>,
+ {
+ 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<N>, discovered: VM) -> Self {
+ Dfs { stack, discovered }
+ }
+
+ /// Clear the visit state
+ pub fn reset<G>(&mut self, graph: G)
+ where
+ G: GraphRef + Visitable<NodeId = N, Map = VM>,
+ {
+ 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<G>(graph: G) -> Self
+ where
+ G: GraphRef + Visitable<NodeId = N, Map = VM>,
+ {
+ 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<G>(&mut self, graph: G) -> Option<N>
+ where
+ G: IntoNeighbors<NodeId = N>,
+ {
+ 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<N, VM> {
+ /// The stack of nodes to visit
+ pub stack: Vec<N>,
+ /// The map of discovered nodes
+ pub discovered: VM,
+ /// The map of finished nodes
+ pub finished: VM,
+}
+
+impl<N, VM> Default for DfsPostOrder<N, VM>
+where
+ VM: Default,
+{
+ fn default() -> Self {
+ DfsPostOrder {
+ stack: Vec::new(),
+ discovered: VM::default(),
+ finished: VM::default(),
+ }
+ }
+}
+
+impl<N, VM> DfsPostOrder<N, VM>
+where
+ N: Copy + PartialEq,
+ VM: VisitMap<N>,
+{
+ /// Create a new `DfsPostOrder` using the graph's visitor map, and put
+ /// `start` in the stack of nodes to visit.
+ pub fn new<G>(graph: G, start: N) -> Self
+ where
+ G: GraphRef + Visitable<NodeId = N, Map = VM>,
+ {
+ 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<G>(graph: G) -> Self
+ where
+ G: GraphRef + Visitable<NodeId = N, Map = VM>,
+ {
+ DfsPostOrder {
+ stack: Vec::new(),
+ discovered: graph.visit_map(),
+ finished: graph.visit_map(),
+ }
+ }
+
+ /// Clear the visit state
+ pub fn reset<G>(&mut self, graph: G)
+ where
+ G: GraphRef + Visitable<NodeId = N, Map = VM>,
+ {
+ 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<G>(&mut self, graph: G) -> Option<N>
+ where
+ G: IntoNeighbors<NodeId = N>,
+ {
+ 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<N, VM> {
+ /// The queue of nodes to visit
+ pub stack: VecDeque<N>,
+ /// The map of discovered nodes
+ pub discovered: VM,
+}
+
+impl<N, VM> Default for Bfs<N, VM>
+where
+ VM: Default,
+{
+ fn default() -> Self {
+ Bfs {
+ stack: VecDeque::new(),
+ discovered: VM::default(),
+ }
+ }
+}
+
+impl<N, VM> Bfs<N, VM>
+where
+ N: Copy + PartialEq,
+ VM: VisitMap<N>,
+{
+ /// Create a new **Bfs**, using the graph's visitor map, and put **start**
+ /// in the stack of nodes to visit.
+ pub fn new<G>(graph: G, start: N) -> Self
+ where
+ G: GraphRef + Visitable<NodeId = N, Map = VM>,
+ {
+ 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<G>(&mut self, graph: G) -> Option<N>
+ where
+ G: IntoNeighbors<NodeId = N>,
+ {
+ 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<N, VM> {
+ tovisit: Vec<N>,
+ ordered: VM,
+}
+
+impl<N, VM> Default for Topo<N, VM>
+where
+ VM: Default,
+{
+ fn default() -> Self {
+ Topo {
+ tovisit: Vec::new(),
+ ordered: VM::default(),
+ }
+ }
+}
+
+impl<N, VM> Topo<N, VM>
+where
+ N: Copy + PartialEq,
+ VM: VisitMap<N>,
+{
+ /// Create a new `Topo`, using the graph's visitor map, and put all
+ /// initial nodes in the to visit list.
+ pub fn new<G>(graph: G) -> Self
+ where
+ G: IntoNodeIdentifiers + IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>,
+ {
+ 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<G, I>(graph: G, initials: I) -> Self
+ where
+ G: IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>,
+ I: IntoIterator<Item = N>,
+ {
+ Topo {
+ tovisit: initials
+ .into_iter()
+ .filter(|&n| graph.neighbors_directed(n, Incoming).next().is_none())
+ .collect(),
+ ordered: graph.visit_map(),
+ }
+ }
+
+ fn extend_with_initials<G>(&mut self, g: G)
+ where
+ G: IntoNodeIdentifiers + IntoNeighborsDirected<NodeId = N>,
+ {
+ // 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<G>(graph: G) -> Self
+ where
+ G: GraphRef + Visitable<NodeId = N, Map = VM>,
+ {
+ Topo {
+ ordered: graph.visit_map(),
+ tovisit: Vec::new(),
+ }
+ }
+
+ /// Clear visited state, and put all initial nodes in the to visit list.
+ pub fn reset<G>(&mut self, graph: G)
+ where
+ G: IntoNodeIdentifiers + IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>,
+ {
+ 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<G>(&mut self, g: G) -> Option<N>
+ where
+ G: IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>,
+ {
+ // 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<Context> {
+ type Item;
+ /// Advance to the next item
+ fn walk_next(&mut self, context: Context) -> Option<Self::Item>;
+
+ /// Create an iterator out of the walker and given `context`.
+ fn iter(self, context: Context) -> WalkerIter<Self, Context>
+ where
+ Self: Sized,
+ Context: Clone,
+ {
+ WalkerIter {
+ walker: self,
+ context,
+ }
+ }
+}
+
+/// A walker and its context wrapped into an iterator.
+#[derive(Clone, Debug)]
+pub struct WalkerIter<W, C> {
+ walker: W,
+ context: C,
+}
+
+impl<W, C> WalkerIter<W, C>
+where
+ W: Walker<C>,
+ 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<W, C> Iterator for WalkerIter<W, C>
+where
+ W: Walker<C>,
+ C: Clone,
+{
+ type Item = W::Item;
+ fn next(&mut self) -> Option<Self::Item> {
+ self.walker.walk_next(self.context.clone())
+ }
+}
+
+impl<C, W: ?Sized> Walker<C> for &mut W
+where
+ W: Walker<C>,
+{
+ type Item = W::Item;
+ fn walk_next(&mut self, context: C) -> Option<Self::Item> {
+ (**self).walk_next(context)
+ }
+}
+
+impl<G> Walker<G> for Dfs<G::NodeId, G::Map>
+where
+ G: IntoNeighbors + Visitable,
+{
+ type Item = G::NodeId;
+ fn walk_next(&mut self, context: G) -> Option<Self::Item> {
+ self.next(context)
+ }
+}
+
+impl<G> Walker<G> for DfsPostOrder<G::NodeId, G::Map>
+where
+ G: IntoNeighbors + Visitable,
+{
+ type Item = G::NodeId;
+ fn walk_next(&mut self, context: G) -> Option<Self::Item> {
+ self.next(context)
+ }
+}
+
+impl<G> Walker<G> for Bfs<G::NodeId, G::Map>
+where
+ G: IntoNeighbors + Visitable,
+{
+ type Item = G::NodeId;
+ fn walk_next(&mut self, context: G) -> Option<Self::Item> {
+ self.next(context)
+ }
+}
+
+impl<G> Walker<G> for Topo<G::NodeId, G::Map>
+where
+ G: IntoNeighborsDirected + Visitable,
+{
+ type Item = G::NodeId;
+ fn walk_next(&mut self, context: G) -> Option<Self::Item> {
+ 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<G>(pub G);
+
+impl<G: GraphRef> GraphRef for UndirectedAdaptor<G> {}
+
+impl<G> IntoNeighbors for UndirectedAdaptor<G>
+where
+ G: IntoNeighborsDirected,
+{
+ type Neighbors = std::iter::Chain<G::NeighborsDirected, G::NeighborsDirected>;
+ fn neighbors(self, n: G::NodeId) -> Self::Neighbors {
+ self.0
+ .neighbors_directed(n, Direction::Incoming)
+ .chain(self.0.neighbors_directed(n, Direction::Outgoing))
+ }
+}
+
+impl<G> IntoEdges for UndirectedAdaptor<G>
+where
+ G: IntoEdgesDirected,
+{
+ type Edges = std::iter::Chain<G::EdgesDirected, G::EdgesDirected>;
+ fn edges(self, a: Self::NodeId) -> Self::Edges {
+ self.0
+ .edges_directed(a, Direction::Incoming)
+ .chain(self.0.edges_directed(a, Direction::Outgoing))
+ }
+}
+
+impl<G> GraphProp for UndirectedAdaptor<G>
+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<G>, access0]}
+Data! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
+IntoEdgeReferences! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
+Visitable! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
+NodeIndexable! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
+NodeCompactIndexable! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
+IntoNodeIdentifiers! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
+IntoNodeReferences! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
+NodeCount! {delegate_impl [[G], G, UndirectedAdaptor<G>, 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::<Vec<_>>();
+ 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::<Vec<_>>();
+ 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::<Vec<_>>();
+ nodes.sort();
+ assert_eq!(graph.neighbors(nodes[1]).count(), 2);
+ }
+ }
+}