diff options
Diffstat (limited to 'vendor/petgraph-0.6.5/src/csr.rs')
| -rw-r--r-- | vendor/petgraph-0.6.5/src/csr.rs | 1148 |
1 files changed, 0 insertions, 1148 deletions
diff --git a/vendor/petgraph-0.6.5/src/csr.rs b/vendor/petgraph-0.6.5/src/csr.rs deleted file mode 100644 index f9f7446c..00000000 --- a/vendor/petgraph-0.6.5/src/csr.rs +++ /dev/null @@ -1,1148 +0,0 @@ -//! 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 { - 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<'a, E, Ty, Ix: Copy> Clone for EdgeReference<'a, E, Ty, Ix> { - fn clone(&self) -> Self { - *self - } -} - -impl<'a, E, Ty, Ix: Copy> Copy for EdgeReference<'a, 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<'a, E, Ty, Ix> EdgeRef for EdgeReference<'a, 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<'a, Ix> Iterator for Neighbors<'a, 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<'a, N, E, Ty, Ix> IntoNodeIdentifiers for &'a 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<'a, N, Ix> DoubleEndedIterator for NodeReferences<'a, 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<'a, N, Ix> ExactSizeIterator for NodeReferences<'a, N, Ix> where Ix: IndexType {} - -/// The adjacency matrix for **Csr** is a bitmap that's computed by -/// `.adjacency_matrix()`. -impl<'a, N, E, Ty, Ix> GetAdjacencyMatrix for &'a 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 = edge.source().index() * n + edge.target().index(); - matrix.put(i); - - 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.edge_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 let Some(_) = dfs.next(&m) {} - 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 let Some(_) = dfs.next(&m) {} - - for i in 0..m.node_count() { - assert!(dfs.discovered[i], "visited {}", i) - } - } - - #[test] - fn csr_tarjan() { - let m: Csr = Csr::from_sorted_edges(&[ - (0, 1), - (0, 2), - (1, 0), - (1, 1), - (1, 3), - (2, 2), - (2, 4), - (4, 4), - (4, 5), - (5, 2), - ]) - .unwrap(); - println!("{:?}", m); - println!("{:?}", tarjan_scc(&m)); - } - - #[test] - fn test_bellman_ford() { - let m: Csr<(), _> = Csr::from_sorted_edges(&[ - (0, 1, 0.5), - (0, 2, 2.), - (1, 0, 1.), - (1, 1, 1.), - (1, 2, 1.), - (1, 3, 1.), - (2, 3, 3.), - (4, 5, 1.), - (5, 7, 2.), - (6, 7, 1.), - (7, 8, 3.), - ]) - .unwrap(); - println!("{:?}", m); - let result = bellman_ford(&m, 0).unwrap(); - println!("{:?}", result); - let answer = [0., 0.5, 1.5, 1.5]; - assert_eq!(&answer, &result.distances[..4]); - assert!(result.distances[4..].iter().all(|&x| f64::is_infinite(x))); - } - - #[test] - fn test_bellman_ford_neg_cycle() { - let m: Csr<(), _> = Csr::from_sorted_edges(&[ - (0, 1, 0.5), - (0, 2, 2.), - (1, 0, 1.), - (1, 1, -1.), - (1, 2, 1.), - (1, 3, 1.), - (2, 3, 3.), - ]) - .unwrap(); - let result = bellman_ford(&m, 0); - assert!(result.is_err()); - } - - #[test] - fn test_find_neg_cycle1() { - let m: Csr<(), _> = Csr::from_sorted_edges(&[ - (0, 1, 0.5), - (0, 2, 2.), - (1, 0, 1.), - (1, 1, -1.), - (1, 2, 1.), - (1, 3, 1.), - (2, 3, 3.), - ]) - .unwrap(); - let result = find_negative_cycle(&m, 0); - assert_eq!(result, Some([1].to_vec())); - } - - #[test] - fn test_find_neg_cycle2() { - let m: Csr<(), _> = Csr::from_sorted_edges(&[ - (0, 1, 0.5), - (0, 2, 2.), - (1, 0, 1.), - (1, 2, 1.), - (1, 3, 1.), - (2, 3, 3.), - ]) - .unwrap(); - let result = find_negative_cycle(&m, 0); - assert_eq!(result, None); - } - - #[test] - fn test_find_neg_cycle3() { - let m: Csr<(), _> = Csr::from_sorted_edges(&[ - (0, 1, 1.), - (0, 2, 1.), - (0, 3, 1.), - (1, 3, 1.), - (2, 1, 1.), - (3, 2, -3.), - ]) - .unwrap(); - let result = find_negative_cycle(&m, 0); - assert_eq!(result, Some([1, 3, 2].to_vec())); - } - - #[test] - fn test_find_neg_cycle4() { - let m: Csr<(), _> = Csr::from_sorted_edges(&[(0, 0, -1.)]).unwrap(); - let result = find_negative_cycle(&m, 0); - assert_eq!(result, Some([0].to_vec())); - } - - #[test] - fn test_edge_references() { - use crate::visit::EdgeRef; - use crate::visit::IntoEdgeReferences; - let m: Csr<(), _> = Csr::from_sorted_edges(&[ - (0, 1, 0.5), - (0, 2, 2.), - (1, 0, 1.), - (1, 1, 1.), - (1, 2, 1.), - (1, 3, 1.), - (2, 3, 3.), - (4, 5, 1.), - (5, 7, 2.), - (6, 7, 1.), - (7, 8, 3.), - ]) - .unwrap(); - let mut copy = Vec::new(); - for e in m.edge_references() { - copy.push((e.source(), e.target(), *e.weight())); - println!("{:?}", e); - } - let m2: Csr<(), _> = Csr::from_sorted_edges(©).unwrap(); - assert_eq!(&m.row, &m2.row); - assert_eq!(&m.column, &m2.column); - assert_eq!(&m.edges, &m2.edges); - } - - #[test] - fn test_add_node() { - let mut g: Csr = Csr::new(); - let a = g.add_node(()); - let b = g.add_node(()); - let c = g.add_node(()); - - assert!(g.add_edge(a, b, ())); - assert!(g.add_edge(b, c, ())); - assert!(g.add_edge(c, a, ())); - - println!("{:?}", g); - - assert_eq!(g.node_count(), 3); - - assert_eq!(g.neighbors_slice(a), &[b]); - assert_eq!(g.neighbors_slice(b), &[c]); - assert_eq!(g.neighbors_slice(c), &[a]); - - assert_eq!(g.edge_count(), 3); - } - - #[test] - fn test_add_node_with_existing_edges() { - let mut g: Csr = Csr::new(); - let a = g.add_node(()); - let b = g.add_node(()); - - assert!(g.add_edge(a, b, ())); - - let c = g.add_node(()); - - println!("{:?}", g); - - assert_eq!(g.node_count(), 3); - - assert_eq!(g.neighbors_slice(a), &[b]); - assert_eq!(g.neighbors_slice(b), &[]); - assert_eq!(g.neighbors_slice(c), &[]); - - assert_eq!(g.edge_count(), 1); - } - - #[test] - fn test_node_references() { - use crate::visit::IntoNodeReferences; - let mut g: Csr<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); - } -} |
