Skip to main content

petgraph/
csr.rs

1//! Compressed Sparse Row (CSR) is a sparse adjacency matrix graph.
2
3use std::cmp::{max, Ordering};
4use std::iter::{Enumerate, Zip};
5use std::marker::PhantomData;
6use std::ops::{Index, IndexMut, Range};
7use std::slice::Windows;
8
9use crate::visit::{Data, GraphProp, IntoEdgeReferences, NodeCount};
10use crate::visit::{EdgeRef, GraphBase, IntoEdges, IntoNeighbors, NodeIndexable};
11use crate::visit::{IntoNodeIdentifiers, NodeCompactIndexable, Visitable};
12
13use crate::util::zip;
14
15#[doc(no_inline)]
16pub use crate::graph::{DefaultIx, IndexType};
17
18use crate::{Directed, EdgeType, IntoWeightedEdge};
19
20/// Csr node index type, a plain integer.
21pub type NodeIndex<Ix = DefaultIx> = Ix;
22/// Csr edge index type, a plain integer.
23pub type EdgeIndex = usize;
24
25const BINARY_SEARCH_CUTOFF: usize = 32;
26
27/// Compressed Sparse Row ([`CSR`]) is a sparse adjacency matrix graph.
28///
29/// `CSR` is parameterized over:
30///
31/// - Associated data `N` for nodes and `E` for edges, called *weights*.
32///   The associated data can be of arbitrary type.
33/// - Edge type `Ty` that determines whether the graph edges are directed or undirected.
34/// - Index type `Ix`, which determines the maximum size of the graph.
35///
36///
37/// Using **O(|E| + |V|)** space.
38///
39/// Self loops are allowed, no parallel edges.
40///
41/// Fast iteration of the outgoing edges of a vertex.
42///
43/// [`CSR`]: https://en.wikipedia.org/wiki/Sparse_matrix#Compressed_sparse_row_(CSR,_CRS_or_Yale_format)
44#[derive(Debug)]
45pub struct Csr<N = (), E = (), Ty = Directed, Ix = DefaultIx> {
46    /// Column of next edge
47    column: Vec<NodeIndex<Ix>>,
48    /// weight of each edge; lock step with column
49    edges: Vec<E>,
50    /// Index of start of row Always node_count + 1 long.
51    /// Last element is always equal to column.len()
52    row: Vec<usize>,
53    node_weights: Vec<N>,
54    edge_count: usize,
55    ty: PhantomData<Ty>,
56}
57
58impl<N, E, Ty, Ix> Default for Csr<N, E, Ty, Ix>
59where
60    Ty: EdgeType,
61    Ix: IndexType,
62{
63    fn default() -> Self {
64        Self::new()
65    }
66}
67
68impl<N: Clone, E: Clone, Ty, Ix: Clone> Clone for Csr<N, E, Ty, Ix> {
69    fn clone(&self) -> Self {
70        Csr {
71            column: self.column.clone(),
72            edges: self.edges.clone(),
73            row: self.row.clone(),
74            node_weights: self.node_weights.clone(),
75            edge_count: self.edge_count,
76            ty: self.ty,
77        }
78    }
79}
80
81impl<N, E, Ty, Ix> Csr<N, E, Ty, Ix>
82where
83    Ty: EdgeType,
84    Ix: IndexType,
85{
86    /// Create an empty `Csr`.
87    pub fn new() -> Self {
88        Csr {
89            column: vec![],
90            edges: vec![],
91            row: vec![0; 1],
92            node_weights: vec![],
93            edge_count: 0,
94            ty: PhantomData,
95        }
96    }
97
98    /// Create a new [`Csr`] with `n` nodes. `N` must implement [`Default`] for the weight of each node.
99    ///
100    /// [`Default`]: https://doc.rust-lang.org/nightly/core/default/trait.Default.html
101    /// [`Csr`]: #struct.Csr.html
102    ///
103    /// # Example
104    /// ```rust
105    /// use petgraph::csr::Csr;
106    /// use petgraph::prelude::*;
107    ///
108    /// let graph = Csr::<u8,()>::with_nodes(5);
109    /// assert_eq!(graph.node_count(),5);
110    /// assert_eq!(graph.edge_count(),0);
111    ///
112    /// assert_eq!(graph[0],0);
113    /// assert_eq!(graph[4],0);
114    /// ```
115    pub fn with_nodes(n: usize) -> Self
116    where
117        N: Default,
118    {
119        Csr {
120            column: Vec::new(),
121            edges: Vec::new(),
122            row: vec![0; n + 1],
123            node_weights: (0..n).map(|_| N::default()).collect(),
124            edge_count: 0,
125            ty: PhantomData,
126        }
127    }
128}
129
130/// Csr creation error: edges were not in sorted order.
131#[derive(Clone, Debug)]
132pub struct EdgesNotSorted {
133    first_error: (usize, usize),
134}
135
136impl<N, E, Ix> Csr<N, E, Directed, Ix>
137where
138    Ix: IndexType,
139{
140    /// Create a new `Csr` from a sorted sequence of edges
141    ///
142    /// Edges **must** be sorted and unique, where the sort order is the default
143    /// order for the pair *(u, v)* in Rust (*u* has priority).
144    ///
145    /// Computes in **O(|E| + |V|)** time.
146    /// # Example
147    /// ```rust
148    /// use petgraph::csr::Csr;
149    /// use petgraph::prelude::*;
150    ///
151    /// let graph = Csr::<(),()>::from_sorted_edges(&[
152    ///                     (0, 1), (0, 2),
153    ///                     (1, 0), (1, 2), (1, 3),
154    ///                     (2, 0),
155    ///                     (3, 1),
156    /// ]);
157    /// ```
158    pub fn from_sorted_edges<Edge>(edges: &[Edge]) -> Result<Self, EdgesNotSorted>
159    where
160        Edge: Clone + IntoWeightedEdge<E, NodeId = NodeIndex<Ix>>,
161        N: Default,
162    {
163        let max_node_id = match edges
164            .iter()
165            .map(|edge| {
166                let (x, y, _) = edge.clone().into_weighted_edge();
167                max(x.index(), y.index())
168            })
169            .max()
170        {
171            None => return Ok(Self::with_nodes(0)),
172            Some(x) => x,
173        };
174        let mut self_ = Self::with_nodes(max_node_id + 1);
175        let mut iter = edges.iter().cloned().peekable();
176        {
177            let mut rows = self_.row.iter_mut();
178
179            let mut node = 0;
180            let mut rstart = 0;
181            let mut last_target;
182            'outer: for r in &mut rows {
183                *r = rstart;
184                last_target = None;
185                'inner: loop {
186                    if let Some(edge) = iter.peek() {
187                        let (n, m, weight) = edge.clone().into_weighted_edge();
188                        // check that the edges are in increasing sequence
189                        if node > n.index() {
190                            return Err(EdgesNotSorted {
191                                first_error: (n.index(), m.index()),
192                            });
193                        }
194                        /*
195                        debug_assert!(node <= n.index(),
196                                      concat!("edges are not sorted, ",
197                                              "failed assertion source {:?} <= {:?} ",
198                                              "for edge {:?}"),
199                                      node, n, (n, m));
200                                      */
201                        if n.index() != node {
202                            break 'inner;
203                        }
204                        // check that the edges are in increasing sequence
205                        /*
206                        debug_assert!(last_target.map_or(true, |x| m > x),
207                                      "edges are not sorted, failed assertion {:?} < {:?}",
208                                      last_target, m);
209                                      */
210                        if !last_target.map_or(true, |x| m > x) {
211                            return Err(EdgesNotSorted {
212                                first_error: (n.index(), m.index()),
213                            });
214                        }
215                        last_target = Some(m);
216                        self_.column.push(m);
217                        self_.edges.push(weight);
218                        rstart += 1;
219                    } else {
220                        break 'outer;
221                    }
222                    iter.next();
223                }
224                node += 1;
225            }
226            for r in rows {
227                *r = rstart;
228            }
229        }
230
231        Ok(self_)
232    }
233}
234
235impl<N, E, Ty, Ix> Csr<N, E, Ty, Ix>
236where
237    Ty: EdgeType,
238    Ix: IndexType,
239{
240    pub fn node_count(&self) -> usize {
241        self.row.len() - 1
242    }
243
244    pub fn edge_count(&self) -> usize {
245        if self.is_directed() {
246            self.column.len()
247        } else {
248            self.edge_count
249        }
250    }
251
252    pub fn is_directed(&self) -> bool {
253        Ty::is_directed()
254    }
255
256    /// Remove all edges
257    pub fn clear_edges(&mut self) {
258        self.column.clear();
259        self.edges.clear();
260        for r in &mut self.row {
261            *r = 0;
262        }
263        if !self.is_directed() {
264            self.edge_count = 0;
265        }
266    }
267
268    /// Adds a new node with the given weight, returning the corresponding node index.
269    pub fn add_node(&mut self, weight: N) -> NodeIndex<Ix> {
270        let i = self.row.len() - 1;
271        self.row.insert(i, self.column.len());
272        self.node_weights.insert(i, weight);
273        Ix::new(i)
274    }
275
276    /// Return `true` if the edge was added
277    ///
278    /// If you add all edges in row-major order, the time complexity
279    /// is **O(|V|·|E|)** for the whole operation.
280    ///
281    /// **Panics** if `a` or `b` are out of bounds.
282    pub fn add_edge(&mut self, a: NodeIndex<Ix>, b: NodeIndex<Ix>, weight: E) -> bool
283    where
284        E: Clone,
285    {
286        let ret = self.add_edge_(a, b, weight.clone());
287        if ret && !self.is_directed() {
288            self.edge_count += 1;
289        }
290        if ret && !self.is_directed() && a != b {
291            let _ret2 = self.add_edge_(b, a, weight);
292            debug_assert_eq!(ret, _ret2);
293        }
294        ret
295    }
296
297    // Return false if the edge already exists
298    fn add_edge_(&mut self, a: NodeIndex<Ix>, b: NodeIndex<Ix>, weight: E) -> bool {
299        assert!(a.index() < self.node_count() && b.index() < self.node_count());
300        // a x b is at (a, b) in the matrix
301
302        // find current range of edges from a
303        let pos = match self.find_edge_pos(a, b) {
304            Ok(_) => return false, /* already exists */
305            Err(i) => i,
306        };
307        self.column.insert(pos, b);
308        self.edges.insert(pos, weight);
309        // update row vector
310        for r in &mut self.row[a.index() + 1..] {
311            *r += 1;
312        }
313        true
314    }
315
316    fn find_edge_pos(&self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> Result<usize, usize> {
317        let (index, neighbors) = self.neighbors_of(a);
318        if neighbors.len() < BINARY_SEARCH_CUTOFF {
319            for (i, elt) in neighbors.iter().enumerate() {
320                match elt.cmp(&b) {
321                    Ordering::Equal => return Ok(i + index),
322                    Ordering::Greater => return Err(i + index),
323                    Ordering::Less => {}
324                }
325            }
326            Err(neighbors.len() + index)
327        } else {
328            match neighbors.binary_search(&b) {
329                Ok(i) => Ok(i + index),
330                Err(i) => Err(i + index),
331            }
332        }
333    }
334
335    /// Computes in **O(log |V|)** time.
336    ///
337    /// **Panics** if the node `a` does not exist.
338    pub fn contains_edge(&self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> bool {
339        self.find_edge_pos(a, b).is_ok()
340    }
341
342    fn neighbors_range(&self, a: NodeIndex<Ix>) -> Range<usize> {
343        let index = self.row[a.index()];
344        let end = self
345            .row
346            .get(a.index() + 1)
347            .cloned()
348            .unwrap_or_else(|| self.column.len());
349        index..end
350    }
351
352    fn neighbors_of(&self, a: NodeIndex<Ix>) -> (usize, &[Ix]) {
353        let r = self.neighbors_range(a);
354        (r.start, &self.column[r])
355    }
356
357    /// Computes in **O(1)** time.
358    ///
359    /// **Panics** if the node `a` does not exist.
360    pub fn out_degree(&self, a: NodeIndex<Ix>) -> usize {
361        let r = self.neighbors_range(a);
362        r.end - r.start
363    }
364
365    /// Computes in **O(1)** time.
366    ///
367    /// **Panics** if the node `a` does not exist.
368    pub fn neighbors_slice(&self, a: NodeIndex<Ix>) -> &[NodeIndex<Ix>] {
369        self.neighbors_of(a).1
370    }
371
372    /// Computes in **O(1)** time.
373    ///
374    /// **Panics** if the node `a` does not exist.
375    pub fn edges_slice(&self, a: NodeIndex<Ix>) -> &[E] {
376        &self.edges[self.neighbors_range(a)]
377    }
378
379    /// Return an iterator of all edges of `a`.
380    ///
381    /// - `Directed`: Outgoing edges from `a`.
382    /// - `Undirected`: All edges connected to `a`.
383    ///
384    /// **Panics** if the node `a` does not exist.<br>
385    /// Iterator element type is `EdgeReference<E, Ty, Ix>`.
386    pub fn edges(&self, a: NodeIndex<Ix>) -> Edges<E, Ty, Ix> {
387        let r = self.neighbors_range(a);
388        Edges {
389            index: r.start,
390            source: a,
391            iter: zip(&self.column[r.clone()], &self.edges[r]),
392            ty: self.ty,
393        }
394    }
395}
396
397#[derive(Clone, Debug)]
398pub struct Edges<'a, E: 'a, Ty = Directed, Ix: 'a = DefaultIx> {
399    index: usize,
400    source: NodeIndex<Ix>,
401    iter: Zip<SliceIter<'a, NodeIndex<Ix>>, SliceIter<'a, E>>,
402    ty: PhantomData<Ty>,
403}
404
405#[derive(Debug)]
406pub struct EdgeReference<'a, E: 'a, Ty, Ix: 'a = DefaultIx> {
407    index: EdgeIndex,
408    source: NodeIndex<Ix>,
409    target: NodeIndex<Ix>,
410    weight: &'a E,
411    ty: PhantomData<Ty>,
412}
413
414impl<'a, E, Ty, Ix: Copy> Clone for EdgeReference<'a, E, Ty, Ix> {
415    fn clone(&self) -> Self {
416        *self
417    }
418}
419
420impl<'a, E, Ty, Ix: Copy> Copy for EdgeReference<'a, E, Ty, Ix> {}
421
422impl<'a, Ty, E, Ix> EdgeReference<'a, E, Ty, Ix>
423where
424    Ty: EdgeType,
425{
426    /// Access the edge’s weight.
427    ///
428    /// **NOTE** that this method offers a longer lifetime
429    /// than the trait (unfortunately they don't match yet).
430    pub fn weight(&self) -> &'a E {
431        self.weight
432    }
433}
434
435impl<'a, E, Ty, Ix> EdgeRef for EdgeReference<'a, E, Ty, Ix>
436where
437    Ty: EdgeType,
438    Ix: IndexType,
439{
440    type NodeId = NodeIndex<Ix>;
441    type EdgeId = EdgeIndex;
442    type Weight = E;
443
444    fn source(&self) -> Self::NodeId {
445        self.source
446    }
447    fn target(&self) -> Self::NodeId {
448        self.target
449    }
450    fn weight(&self) -> &E {
451        self.weight
452    }
453    fn id(&self) -> Self::EdgeId {
454        self.index
455    }
456}
457
458impl<'a, E, Ty, Ix> Iterator for Edges<'a, E, Ty, Ix>
459where
460    Ty: EdgeType,
461    Ix: IndexType,
462{
463    type Item = EdgeReference<'a, E, Ty, Ix>;
464    fn next(&mut self) -> Option<Self::Item> {
465        self.iter.next().map(move |(&j, w)| {
466            let index = self.index;
467            self.index += 1;
468            EdgeReference {
469                index,
470                source: self.source,
471                target: j,
472                weight: w,
473                ty: PhantomData,
474            }
475        })
476    }
477}
478
479impl<N, E, Ty, Ix> Data for Csr<N, E, Ty, Ix>
480where
481    Ty: EdgeType,
482    Ix: IndexType,
483{
484    type NodeWeight = N;
485    type EdgeWeight = E;
486}
487
488impl<'a, N, E, Ty, Ix> IntoEdgeReferences for &'a Csr<N, E, Ty, Ix>
489where
490    Ty: EdgeType,
491    Ix: IndexType,
492{
493    type EdgeRef = EdgeReference<'a, E, Ty, Ix>;
494    type EdgeReferences = EdgeReferences<'a, E, Ty, Ix>;
495    fn edge_references(self) -> Self::EdgeReferences {
496        EdgeReferences {
497            index: 0,
498            source_index: Ix::new(0),
499            edge_ranges: self.row.windows(2).enumerate(),
500            column: &self.column,
501            edges: &self.edges,
502            iter: zip(&[], &[]),
503            ty: self.ty,
504        }
505    }
506}
507
508pub struct EdgeReferences<'a, E: 'a, Ty, Ix: 'a> {
509    source_index: NodeIndex<Ix>,
510    index: usize,
511    edge_ranges: Enumerate<Windows<'a, usize>>,
512    column: &'a [NodeIndex<Ix>],
513    edges: &'a [E],
514    iter: Zip<SliceIter<'a, NodeIndex<Ix>>, SliceIter<'a, E>>,
515    ty: PhantomData<Ty>,
516}
517
518impl<'a, E, Ty, Ix> Iterator for EdgeReferences<'a, E, Ty, Ix>
519where
520    Ty: EdgeType,
521    Ix: IndexType,
522{
523    type Item = EdgeReference<'a, E, Ty, Ix>;
524    fn next(&mut self) -> Option<Self::Item> {
525        loop {
526            if let Some((&j, w)) = self.iter.next() {
527                let index = self.index;
528                self.index += 1;
529                return Some(EdgeReference {
530                    index,
531                    source: self.source_index,
532                    target: j,
533                    weight: w,
534                    ty: PhantomData,
535                });
536            }
537            if let Some((i, w)) = self.edge_ranges.next() {
538                let a = w[0];
539                let b = w[1];
540                self.iter = zip(&self.column[a..b], &self.edges[a..b]);
541                self.source_index = Ix::new(i);
542            } else {
543                return None;
544            }
545        }
546    }
547}
548
549impl<'a, N, E, Ty, Ix> IntoEdges for &'a Csr<N, E, Ty, Ix>
550where
551    Ty: EdgeType,
552    Ix: IndexType,
553{
554    type Edges = Edges<'a, E, Ty, Ix>;
555    fn edges(self, a: Self::NodeId) -> Self::Edges {
556        self.edges(a)
557    }
558}
559
560impl<N, E, Ty, Ix> GraphBase for Csr<N, E, Ty, Ix>
561where
562    Ty: EdgeType,
563    Ix: IndexType,
564{
565    type NodeId = NodeIndex<Ix>;
566    type EdgeId = EdgeIndex; // index into edges vector
567}
568
569use fixedbitset::FixedBitSet;
570
571impl<N, E, Ty, Ix> Visitable for Csr<N, E, Ty, Ix>
572where
573    Ty: EdgeType,
574    Ix: IndexType,
575{
576    type Map = FixedBitSet;
577    fn visit_map(&self) -> FixedBitSet {
578        FixedBitSet::with_capacity(self.node_count())
579    }
580    fn reset_map(&self, map: &mut Self::Map) {
581        map.clear();
582        map.grow(self.node_count());
583    }
584}
585
586use std::slice::Iter as SliceIter;
587
588#[derive(Clone, Debug)]
589pub struct Neighbors<'a, Ix: 'a = DefaultIx> {
590    iter: SliceIter<'a, NodeIndex<Ix>>,
591}
592
593impl<'a, Ix> Iterator for Neighbors<'a, Ix>
594where
595    Ix: IndexType,
596{
597    type Item = NodeIndex<Ix>;
598
599    fn next(&mut self) -> Option<Self::Item> {
600        self.iter.next().cloned()
601    }
602
603    fn size_hint(&self) -> (usize, Option<usize>) {
604        self.iter.size_hint()
605    }
606}
607
608impl<'a, N, E, Ty, Ix> IntoNeighbors for &'a Csr<N, E, Ty, Ix>
609where
610    Ty: EdgeType,
611    Ix: IndexType,
612{
613    type Neighbors = Neighbors<'a, Ix>;
614
615    /// Return an iterator of all neighbors of `a`.
616    ///
617    /// - `Directed`: Targets of outgoing edges from `a`.
618    /// - `Undirected`: Opposing endpoints of all edges connected to `a`.
619    ///
620    /// **Panics** if the node `a` does not exist.<br>
621    /// Iterator element type is `NodeIndex<Ix>`.
622    fn neighbors(self, a: Self::NodeId) -> Self::Neighbors {
623        Neighbors {
624            iter: self.neighbors_slice(a).iter(),
625        }
626    }
627}
628
629impl<N, E, Ty, Ix> NodeIndexable for Csr<N, E, Ty, Ix>
630where
631    Ty: EdgeType,
632    Ix: IndexType,
633{
634    fn node_bound(&self) -> usize {
635        self.node_count()
636    }
637    fn to_index(&self, a: Self::NodeId) -> usize {
638        a.index()
639    }
640    fn from_index(&self, ix: usize) -> Self::NodeId {
641        Ix::new(ix)
642    }
643}
644
645impl<N, E, Ty, Ix> NodeCompactIndexable for Csr<N, E, Ty, Ix>
646where
647    Ty: EdgeType,
648    Ix: IndexType,
649{
650}
651
652impl<N, E, Ty, Ix> Index<NodeIndex<Ix>> for Csr<N, E, Ty, Ix>
653where
654    Ty: EdgeType,
655    Ix: IndexType,
656{
657    type Output = N;
658
659    fn index(&self, ix: NodeIndex<Ix>) -> &N {
660        &self.node_weights[ix.index()]
661    }
662}
663
664impl<N, E, Ty, Ix> IndexMut<NodeIndex<Ix>> for Csr<N, E, Ty, Ix>
665where
666    Ty: EdgeType,
667    Ix: IndexType,
668{
669    fn index_mut(&mut self, ix: NodeIndex<Ix>) -> &mut N {
670        &mut self.node_weights[ix.index()]
671    }
672}
673
674pub struct NodeIdentifiers<Ix = DefaultIx> {
675    r: Range<usize>,
676    ty: PhantomData<Ix>,
677}
678
679impl<Ix> Iterator for NodeIdentifiers<Ix>
680where
681    Ix: IndexType,
682{
683    type Item = NodeIndex<Ix>;
684
685    fn next(&mut self) -> Option<Self::Item> {
686        self.r.next().map(Ix::new)
687    }
688
689    fn size_hint(&self) -> (usize, Option<usize>) {
690        self.r.size_hint()
691    }
692}
693
694impl<'a, N, E, Ty, Ix> IntoNodeIdentifiers for &'a Csr<N, E, Ty, Ix>
695where
696    Ty: EdgeType,
697    Ix: IndexType,
698{
699    type NodeIdentifiers = NodeIdentifiers<Ix>;
700    fn node_identifiers(self) -> Self::NodeIdentifiers {
701        NodeIdentifiers {
702            r: 0..self.node_count(),
703            ty: PhantomData,
704        }
705    }
706}
707
708impl<N, E, Ty, Ix> NodeCount for Csr<N, E, Ty, Ix>
709where
710    Ty: EdgeType,
711    Ix: IndexType,
712{
713    fn node_count(&self) -> usize {
714        (*self).node_count()
715    }
716}
717
718impl<N, E, Ty, Ix> GraphProp for Csr<N, E, Ty, Ix>
719where
720    Ty: EdgeType,
721    Ix: IndexType,
722{
723    type EdgeType = Ty;
724}
725
726/*
727 *
728Example
729
730[ a 0 b
731  c d e
732  0 0 f ]
733
734Values: [a, b, c, d, e, f]
735Column: [0, 2, 0, 1, 2, 2]
736Row   : [0, 2, 5]   <- value index of row start
737
738 * */
739
740#[cfg(test)]
741mod tests {
742    use super::Csr;
743    use crate::algo::bellman_ford;
744    use crate::algo::tarjan_scc;
745    use crate::visit::Dfs;
746    use crate::visit::VisitMap;
747    use crate::Undirected;
748
749    #[test]
750    fn csr1() {
751        let mut m: Csr = Csr::with_nodes(3);
752        m.add_edge(0, 0, ());
753        m.add_edge(1, 2, ());
754        m.add_edge(2, 2, ());
755        m.add_edge(0, 2, ());
756        m.add_edge(1, 0, ());
757        m.add_edge(1, 1, ());
758        println!("{:?}", m);
759        assert_eq!(&m.column, &[0, 2, 0, 1, 2, 2]);
760        assert_eq!(&m.row, &[0, 2, 5, 6]);
761
762        let added = m.add_edge(1, 2, ());
763        assert!(!added);
764        assert_eq!(&m.column, &[0, 2, 0, 1, 2, 2]);
765        assert_eq!(&m.row, &[0, 2, 5, 6]);
766
767        assert_eq!(m.neighbors_slice(1), &[0, 1, 2]);
768        assert_eq!(m.node_count(), 3);
769        assert_eq!(m.edge_count(), 6);
770    }
771
772    #[test]
773    fn csr_undirected() {
774        /*
775           [ 1 . 1
776             . . 1
777             1 1 1 ]
778        */
779
780        let mut m: Csr<(), (), Undirected> = Csr::with_nodes(3);
781        m.add_edge(0, 0, ());
782        m.add_edge(0, 2, ());
783        m.add_edge(1, 2, ());
784        m.add_edge(2, 2, ());
785        println!("{:?}", m);
786        assert_eq!(&m.column, &[0, 2, 2, 0, 1, 2]);
787        assert_eq!(&m.row, &[0, 2, 3, 6]);
788        assert_eq!(m.node_count(), 3);
789        assert_eq!(m.edge_count(), 4);
790    }
791
792    #[should_panic]
793    #[test]
794    fn csr_from_error_1() {
795        // not sorted in source
796        let m: Csr = Csr::from_sorted_edges(&[(0, 1), (1, 0), (0, 2)]).unwrap();
797        println!("{:?}", m);
798    }
799
800    #[should_panic]
801    #[test]
802    fn csr_from_error_2() {
803        // not sorted in target
804        let m: Csr = Csr::from_sorted_edges(&[(0, 1), (1, 0), (1, 2), (1, 1)]).unwrap();
805        println!("{:?}", m);
806    }
807
808    #[test]
809    fn csr_from() {
810        let m: Csr =
811            Csr::from_sorted_edges(&[(0, 1), (0, 2), (1, 0), (1, 1), (2, 2), (2, 4)]).unwrap();
812        println!("{:?}", m);
813        assert_eq!(m.neighbors_slice(0), &[1, 2]);
814        assert_eq!(m.neighbors_slice(1), &[0, 1]);
815        assert_eq!(m.neighbors_slice(2), &[2, 4]);
816        assert_eq!(m.node_count(), 5);
817        assert_eq!(m.edge_count(), 6);
818    }
819
820    #[test]
821    fn csr_dfs() {
822        let mut m: Csr = Csr::from_sorted_edges(&[
823            (0, 1),
824            (0, 2),
825            (1, 0),
826            (1, 1),
827            (1, 3),
828            (2, 2),
829            // disconnected subgraph
830            (4, 4),
831            (4, 5),
832        ])
833        .unwrap();
834        println!("{:?}", m);
835        let mut dfs = Dfs::new(&m, 0);
836        while let Some(_) = dfs.next(&m) {}
837        for i in 0..m.node_count() - 2 {
838            assert!(dfs.discovered.is_visited(&i), "visited {}", i)
839        }
840        assert!(!dfs.discovered[4]);
841        assert!(!dfs.discovered[5]);
842
843        m.add_edge(1, 4, ());
844        println!("{:?}", m);
845
846        dfs.reset(&m);
847        dfs.move_to(0);
848        while let Some(_) = dfs.next(&m) {}
849
850        for i in 0..m.node_count() {
851            assert!(dfs.discovered[i], "visited {}", i)
852        }
853    }
854
855    #[test]
856    fn csr_tarjan() {
857        let m: Csr = Csr::from_sorted_edges(&[
858            (0, 1),
859            (0, 2),
860            (1, 0),
861            (1, 1),
862            (1, 3),
863            (2, 2),
864            (2, 4),
865            (4, 4),
866            (4, 5),
867            (5, 2),
868        ])
869        .unwrap();
870        println!("{:?}", m);
871        println!("{:?}", tarjan_scc(&m));
872    }
873
874    #[test]
875    fn test_bellman_ford() {
876        let m: Csr<(), _> = Csr::from_sorted_edges(&[
877            (0, 1, 0.5),
878            (0, 2, 2.),
879            (1, 0, 1.),
880            (1, 1, 1.),
881            (1, 2, 1.),
882            (1, 3, 1.),
883            (2, 3, 3.),
884            (4, 5, 1.),
885            (5, 7, 2.),
886            (6, 7, 1.),
887            (7, 8, 3.),
888        ])
889        .unwrap();
890        println!("{:?}", m);
891        let result = bellman_ford(&m, 0).unwrap();
892        println!("{:?}", result);
893        let answer = [0., 0.5, 1.5, 1.5];
894        assert_eq!(&answer, &result.0[..4]);
895        assert!(answer[4..].iter().all(|&x| f64::is_infinite(x)));
896    }
897
898    #[test]
899    fn test_bellman_ford_neg_cycle() {
900        let m: Csr<(), _> = Csr::from_sorted_edges(&[
901            (0, 1, 0.5),
902            (0, 2, 2.),
903            (1, 0, 1.),
904            (1, 1, -1.),
905            (1, 2, 1.),
906            (1, 3, 1.),
907            (2, 3, 3.),
908        ])
909        .unwrap();
910        let result = bellman_ford(&m, 0);
911        assert!(result.is_err());
912    }
913
914    #[test]
915    fn test_edge_references() {
916        use crate::visit::EdgeRef;
917        use crate::visit::IntoEdgeReferences;
918        let m: Csr<(), _> = Csr::from_sorted_edges(&[
919            (0, 1, 0.5),
920            (0, 2, 2.),
921            (1, 0, 1.),
922            (1, 1, 1.),
923            (1, 2, 1.),
924            (1, 3, 1.),
925            (2, 3, 3.),
926            (4, 5, 1.),
927            (5, 7, 2.),
928            (6, 7, 1.),
929            (7, 8, 3.),
930        ])
931        .unwrap();
932        let mut copy = Vec::new();
933        for e in m.edge_references() {
934            copy.push((e.source(), e.target(), *e.weight()));
935            println!("{:?}", e);
936        }
937        let m2: Csr<(), _> = Csr::from_sorted_edges(&copy).unwrap();
938        assert_eq!(&m.row, &m2.row);
939        assert_eq!(&m.column, &m2.column);
940        assert_eq!(&m.edges, &m2.edges);
941    }
942
943    #[test]
944    fn test_add_node() {
945        let mut g: Csr = Csr::new();
946        let a = g.add_node(());
947        let b = g.add_node(());
948        let c = g.add_node(());
949
950        assert!(g.add_edge(a, b, ()));
951        assert!(g.add_edge(b, c, ()));
952        assert!(g.add_edge(c, a, ()));
953
954        println!("{:?}", g);
955
956        assert_eq!(g.node_count(), 3);
957
958        assert_eq!(g.neighbors_slice(a), &[b]);
959        assert_eq!(g.neighbors_slice(b), &[c]);
960        assert_eq!(g.neighbors_slice(c), &[a]);
961
962        assert_eq!(g.edge_count(), 3);
963    }
964
965    #[test]
966    fn test_add_node_with_existing_edges() {
967        let mut g: Csr = Csr::new();
968        let a = g.add_node(());
969        let b = g.add_node(());
970
971        assert!(g.add_edge(a, b, ()));
972
973        let c = g.add_node(());
974
975        println!("{:?}", g);
976
977        assert_eq!(g.node_count(), 3);
978
979        assert_eq!(g.neighbors_slice(a), &[b]);
980        assert_eq!(g.neighbors_slice(b), &[]);
981        assert_eq!(g.neighbors_slice(c), &[]);
982
983        assert_eq!(g.edge_count(), 1);
984    }
985}