1#[cfg(feature = "std")]
4use std::{
5 cmp::{max, Ordering},
6 iter::{Enumerate, Zip},
7 marker::PhantomData,
8 ops::{Index, IndexMut, Range},
9 slice::Iter as SliceIter,
10 slice::Windows,
11};
12
13#[cfg(not(feature = "std"))]
14use core::{
15 cmp::{max, Ordering},
16 iter::{Enumerate, Zip},
17 marker::PhantomData,
18 ops::{Index, IndexMut, Range},
19 slice::Iter as SliceIter,
20 slice::Windows,
21};
22
23#[cfg(not(feature = "std"))]
24use alloc::vec::Vec;
25
26use crate::visit::{Data, GraphProp, IntoEdgeReferences, NodeCount};
27use crate::visit::{EdgeRef, GraphBase, IntoEdges, IntoNeighbors, NodeIndexable};
28use crate::visit::{IntoNodeIdentifiers, NodeCompactIndexable, Visitable};
29
30use crate::util::zip;
31
32#[doc(no_inline)]
33pub use crate::graph::{DefaultIx, IndexType};
34
35use crate::{Directed, EdgeType, IntoWeightedEdge};
36
37pub type NodeIndex<Ix = DefaultIx> = Ix;
39pub type EdgeIndex = usize;
41
42const BINARY_SEARCH_CUTOFF: usize = 32;
43
44#[derive(Debug)]
62pub struct Csr<N = (), E = (), Ty = Directed, Ix = DefaultIx> {
63 column: Vec<NodeIndex<Ix>>,
65 edges: Vec<E>,
67 row: Vec<usize>,
70 node_weights: Vec<N>,
71 edge_count: usize,
72 ty: PhantomData<Ty>,
73}
74
75impl<N, E, Ty, Ix> Default for Csr<N, E, Ty, Ix>
76where
77 Ty: EdgeType,
78 Ix: IndexType,
79{
80 fn default() -> Self {
81 Self::new()
82 }
83}
84
85impl<N: Clone, E: Clone, Ty, Ix: Clone> Clone for Csr<N, E, Ty, Ix> {
86 fn clone(&self) -> Self {
87 Csr {
88 column: self.column.clone(),
89 edges: self.edges.clone(),
90 row: self.row.clone(),
91 node_weights: self.node_weights.clone(),
92 edge_count: self.edge_count,
93 ty: self.ty,
94 }
95 }
96}
97
98impl<N, E, Ty, Ix> Csr<N, E, Ty, Ix>
99where
100 Ty: EdgeType,
101 Ix: IndexType,
102{
103 pub fn new() -> Self {
105 Csr {
106 column: vec![],
107 edges: vec![],
108 row: vec![0; 1],
109 node_weights: vec![],
110 edge_count: 0,
111 ty: PhantomData,
112 }
113 }
114
115 pub fn with_nodes(n: usize) -> Self
133 where
134 N: Default,
135 {
136 Csr {
137 column: Vec::new(),
138 edges: Vec::new(),
139 row: vec![0; n + 1],
140 node_weights: (0..n).map(|_| N::default()).collect(),
141 edge_count: 0,
142 ty: PhantomData,
143 }
144 }
145}
146
147#[derive(Clone, Debug)]
149pub struct EdgesNotSorted {
150 first_error: (usize, usize),
151}
152
153impl<N, E, Ix> Csr<N, E, Directed, Ix>
154where
155 Ix: IndexType,
156{
157 pub fn from_sorted_edges<Edge>(edges: &[Edge]) -> Result<Self, EdgesNotSorted>
176 where
177 Edge: Clone + IntoWeightedEdge<E, NodeId = NodeIndex<Ix>>,
178 N: Default,
179 {
180 let max_node_id = match edges
181 .iter()
182 .map(|edge| {
183 let (x, y, _) = edge.clone().into_weighted_edge();
184 max(x.index(), y.index())
185 })
186 .max()
187 {
188 None => return Ok(Self::with_nodes(0)),
189 Some(x) => x,
190 };
191 let mut self_ = Self::with_nodes(max_node_id + 1);
192 let mut iter = edges.iter().cloned().peekable();
193 {
194 let mut rows = self_.row.iter_mut();
195
196 let mut node = 0;
197 let mut rstart = 0;
198 let mut last_target;
199 'outer: for r in &mut rows {
200 *r = rstart;
201 last_target = None;
202 'inner: loop {
203 if let Some(edge) = iter.peek() {
204 let (n, m, weight) = edge.clone().into_weighted_edge();
205 if node > n.index() {
207 return Err(EdgesNotSorted {
208 first_error: (n.index(), m.index()),
209 });
210 }
211 if n.index() != node {
219 break 'inner;
220 }
221 if !last_target.map_or(true, |x| m > x) {
228 return Err(EdgesNotSorted {
229 first_error: (n.index(), m.index()),
230 });
231 }
232 last_target = Some(m);
233 self_.column.push(m);
234 self_.edges.push(weight);
235 rstart += 1;
236 } else {
237 break 'outer;
238 }
239 iter.next();
240 }
241 node += 1;
242 }
243 for r in rows {
244 *r = rstart;
245 }
246 }
247
248 Ok(self_)
249 }
250}
251
252impl<N, E, Ty, Ix> Csr<N, E, Ty, Ix>
253where
254 Ty: EdgeType,
255 Ix: IndexType,
256{
257 pub fn node_count(&self) -> usize {
258 self.row.len() - 1
259 }
260
261 pub fn edge_count(&self) -> usize {
262 if self.is_directed() {
263 self.column.len()
264 } else {
265 self.edge_count
266 }
267 }
268
269 pub fn is_directed(&self) -> bool {
270 Ty::is_directed()
271 }
272
273 pub fn clear_edges(&mut self) {
275 self.column.clear();
276 self.edges.clear();
277 for r in &mut self.row {
278 *r = 0;
279 }
280 if !self.is_directed() {
281 self.edge_count = 0;
282 }
283 }
284
285 pub fn add_node(&mut self, weight: N) -> NodeIndex<Ix> {
287 let i = self.row.len() - 1;
288 self.row.insert(i, self.column.len());
289 self.node_weights.insert(i, weight);
290 Ix::new(i)
291 }
292
293 pub fn add_edge(&mut self, a: NodeIndex<Ix>, b: NodeIndex<Ix>, weight: E) -> bool
300 where
301 E: Clone,
302 {
303 let ret = self.add_edge_(a, b, weight.clone());
304 if ret && !self.is_directed() {
305 self.edge_count += 1;
306 }
307 if ret && !self.is_directed() && a != b {
308 let _ret2 = self.add_edge_(b, a, weight);
309 debug_assert_eq!(ret, _ret2);
310 }
311 ret
312 }
313
314 fn add_edge_(&mut self, a: NodeIndex<Ix>, b: NodeIndex<Ix>, weight: E) -> bool {
316 assert!(a.index() < self.node_count() && b.index() < self.node_count());
317 let pos = match self.find_edge_pos(a, b) {
321 Ok(_) => return false, Err(i) => i,
323 };
324 self.column.insert(pos, b);
325 self.edges.insert(pos, weight);
326 for r in &mut self.row[a.index() + 1..] {
328 *r += 1;
329 }
330 true
331 }
332
333 fn find_edge_pos(&self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> Result<usize, usize> {
334 let (index, neighbors) = self.neighbors_of(a);
335 if neighbors.len() < BINARY_SEARCH_CUTOFF {
336 for (i, elt) in neighbors.iter().enumerate() {
337 match elt.cmp(&b) {
338 Ordering::Equal => return Ok(i + index),
339 Ordering::Greater => return Err(i + index),
340 Ordering::Less => {}
341 }
342 }
343 Err(neighbors.len() + index)
344 } else {
345 match neighbors.binary_search(&b) {
346 Ok(i) => Ok(i + index),
347 Err(i) => Err(i + index),
348 }
349 }
350 }
351
352 pub fn contains_edge(&self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> bool {
356 self.find_edge_pos(a, b).is_ok()
357 }
358
359 fn neighbors_range(&self, a: NodeIndex<Ix>) -> Range<usize> {
360 let index = self.row[a.index()];
361 let end = self
362 .row
363 .get(a.index() + 1)
364 .cloned()
365 .unwrap_or_else(|| self.column.len());
366 index..end
367 }
368
369 fn neighbors_of(&self, a: NodeIndex<Ix>) -> (usize, &[Ix]) {
370 let r = self.neighbors_range(a);
371 (r.start, &self.column[r])
372 }
373
374 pub fn out_degree(&self, a: NodeIndex<Ix>) -> usize {
378 let r = self.neighbors_range(a);
379 r.end - r.start
380 }
381
382 pub fn neighbors_slice(&self, a: NodeIndex<Ix>) -> &[NodeIndex<Ix>] {
386 self.neighbors_of(a).1
387 }
388
389 pub fn edges_slice(&self, a: NodeIndex<Ix>) -> &[E] {
393 &self.edges[self.neighbors_range(a)]
394 }
395
396 pub fn edges(&self, a: NodeIndex<Ix>) -> Edges<E, Ty, Ix> {
404 let r = self.neighbors_range(a);
405 Edges {
406 index: r.start,
407 source: a,
408 iter: zip(&self.column[r.clone()], &self.edges[r]),
409 ty: self.ty,
410 }
411 }
412}
413
414#[derive(Clone, Debug)]
415pub struct Edges<'a, E: 'a, Ty = Directed, Ix: 'a = DefaultIx> {
416 index: usize,
417 source: NodeIndex<Ix>,
418 iter: Zip<SliceIter<'a, NodeIndex<Ix>>, SliceIter<'a, E>>,
419 ty: PhantomData<Ty>,
420}
421
422#[derive(Debug)]
423pub struct EdgeReference<'a, E: 'a, Ty, Ix: 'a = DefaultIx> {
424 index: EdgeIndex,
425 source: NodeIndex<Ix>,
426 target: NodeIndex<Ix>,
427 weight: &'a E,
428 ty: PhantomData<Ty>,
429}
430
431impl<'a, E, Ty, Ix: Copy> Clone for EdgeReference<'a, E, Ty, Ix> {
432 fn clone(&self) -> Self {
433 *self
434 }
435}
436
437impl<'a, E, Ty, Ix: Copy> Copy for EdgeReference<'a, E, Ty, Ix> {}
438
439impl<'a, Ty, E, Ix> EdgeReference<'a, E, Ty, Ix>
440where
441 Ty: EdgeType,
442{
443 pub fn weight(&self) -> &'a E {
448 self.weight
449 }
450}
451
452impl<'a, E, Ty, Ix> EdgeRef for EdgeReference<'a, E, Ty, Ix>
453where
454 Ty: EdgeType,
455 Ix: IndexType,
456{
457 type NodeId = NodeIndex<Ix>;
458 type EdgeId = EdgeIndex;
459 type Weight = E;
460
461 fn source(&self) -> Self::NodeId {
462 self.source
463 }
464 fn target(&self) -> Self::NodeId {
465 self.target
466 }
467 fn weight(&self) -> &E {
468 self.weight
469 }
470 fn id(&self) -> Self::EdgeId {
471 self.index
472 }
473}
474
475impl<'a, E, Ty, Ix> Iterator for Edges<'a, E, Ty, Ix>
476where
477 Ty: EdgeType,
478 Ix: IndexType,
479{
480 type Item = EdgeReference<'a, E, Ty, Ix>;
481 fn next(&mut self) -> Option<Self::Item> {
482 self.iter.next().map(move |(&j, w)| {
483 let index = self.index;
484 self.index += 1;
485 EdgeReference {
486 index,
487 source: self.source,
488 target: j,
489 weight: w,
490 ty: PhantomData,
491 }
492 })
493 }
494}
495
496impl<N, E, Ty, Ix> Data for Csr<N, E, Ty, Ix>
497where
498 Ty: EdgeType,
499 Ix: IndexType,
500{
501 type NodeWeight = N;
502 type EdgeWeight = E;
503}
504
505impl<'a, N, E, Ty, Ix> IntoEdgeReferences for &'a Csr<N, E, Ty, Ix>
506where
507 Ty: EdgeType,
508 Ix: IndexType,
509{
510 type EdgeRef = EdgeReference<'a, E, Ty, Ix>;
511 type EdgeReferences = EdgeReferences<'a, E, Ty, Ix>;
512 fn edge_references(self) -> Self::EdgeReferences {
513 EdgeReferences {
514 index: 0,
515 source_index: Ix::new(0),
516 edge_ranges: self.row.windows(2).enumerate(),
517 column: &self.column,
518 edges: &self.edges,
519 iter: zip(&[], &[]),
520 ty: self.ty,
521 }
522 }
523}
524
525pub struct EdgeReferences<'a, E: 'a, Ty, Ix: 'a> {
526 source_index: NodeIndex<Ix>,
527 index: usize,
528 edge_ranges: Enumerate<Windows<'a, usize>>,
529 column: &'a [NodeIndex<Ix>],
530 edges: &'a [E],
531 iter: Zip<SliceIter<'a, NodeIndex<Ix>>, SliceIter<'a, E>>,
532 ty: PhantomData<Ty>,
533}
534
535impl<'a, E, Ty, Ix> Iterator for EdgeReferences<'a, E, Ty, Ix>
536where
537 Ty: EdgeType,
538 Ix: IndexType,
539{
540 type Item = EdgeReference<'a, E, Ty, Ix>;
541 fn next(&mut self) -> Option<Self::Item> {
542 loop {
543 if let Some((&j, w)) = self.iter.next() {
544 let index = self.index;
545 self.index += 1;
546 return Some(EdgeReference {
547 index,
548 source: self.source_index,
549 target: j,
550 weight: w,
551 ty: PhantomData,
552 });
553 }
554 if let Some((i, w)) = self.edge_ranges.next() {
555 let a = w[0];
556 let b = w[1];
557 self.iter = zip(&self.column[a..b], &self.edges[a..b]);
558 self.source_index = Ix::new(i);
559 } else {
560 return None;
561 }
562 }
563 }
564}
565
566impl<'a, N, E, Ty, Ix> IntoEdges for &'a Csr<N, E, Ty, Ix>
567where
568 Ty: EdgeType,
569 Ix: IndexType,
570{
571 type Edges = Edges<'a, E, Ty, Ix>;
572 fn edges(self, a: Self::NodeId) -> Self::Edges {
573 self.edges(a)
574 }
575}
576
577impl<N, E, Ty, Ix> GraphBase for Csr<N, E, Ty, Ix>
578where
579 Ty: EdgeType,
580 Ix: IndexType,
581{
582 type NodeId = NodeIndex<Ix>;
583 type EdgeId = EdgeIndex; }
585
586use fixedbitset::FixedBitSet;
587
588impl<N, E, Ty, Ix> Visitable for Csr<N, E, Ty, Ix>
589where
590 Ty: EdgeType,
591 Ix: IndexType,
592{
593 type Map = FixedBitSet;
594 fn visit_map(&self) -> FixedBitSet {
595 FixedBitSet::with_capacity(self.node_count())
596 }
597 fn reset_map(&self, map: &mut Self::Map) {
598 map.clear();
599 map.grow(self.node_count());
600 }
601}
602
603#[derive(Clone, Debug)]
604pub struct Neighbors<'a, Ix: 'a = DefaultIx> {
605 iter: SliceIter<'a, NodeIndex<Ix>>,
606}
607
608impl<'a, Ix> Iterator for Neighbors<'a, Ix>
609where
610 Ix: IndexType,
611{
612 type Item = NodeIndex<Ix>;
613
614 fn next(&mut self) -> Option<Self::Item> {
615 self.iter.next().cloned()
616 }
617
618 fn size_hint(&self) -> (usize, Option<usize>) {
619 self.iter.size_hint()
620 }
621}
622
623impl<'a, N, E, Ty, Ix> IntoNeighbors for &'a Csr<N, E, Ty, Ix>
624where
625 Ty: EdgeType,
626 Ix: IndexType,
627{
628 type Neighbors = Neighbors<'a, Ix>;
629
630 fn neighbors(self, a: Self::NodeId) -> Self::Neighbors {
638 Neighbors {
639 iter: self.neighbors_slice(a).iter(),
640 }
641 }
642}
643
644impl<N, E, Ty, Ix> NodeIndexable for Csr<N, E, Ty, Ix>
645where
646 Ty: EdgeType,
647 Ix: IndexType,
648{
649 fn node_bound(&self) -> usize {
650 self.node_count()
651 }
652 fn to_index(&self, a: Self::NodeId) -> usize {
653 a.index()
654 }
655 fn from_index(&self, ix: usize) -> Self::NodeId {
656 Ix::new(ix)
657 }
658}
659
660impl<N, E, Ty, Ix> NodeCompactIndexable for Csr<N, E, Ty, Ix>
661where
662 Ty: EdgeType,
663 Ix: IndexType,
664{
665}
666
667impl<N, E, Ty, Ix> Index<NodeIndex<Ix>> for Csr<N, E, Ty, Ix>
668where
669 Ty: EdgeType,
670 Ix: IndexType,
671{
672 type Output = N;
673
674 fn index(&self, ix: NodeIndex<Ix>) -> &N {
675 &self.node_weights[ix.index()]
676 }
677}
678
679impl<N, E, Ty, Ix> IndexMut<NodeIndex<Ix>> for Csr<N, E, Ty, Ix>
680where
681 Ty: EdgeType,
682 Ix: IndexType,
683{
684 fn index_mut(&mut self, ix: NodeIndex<Ix>) -> &mut N {
685 &mut self.node_weights[ix.index()]
686 }
687}
688
689pub struct NodeIdentifiers<Ix = DefaultIx> {
690 r: Range<usize>,
691 ty: PhantomData<Ix>,
692}
693
694impl<Ix> Iterator for NodeIdentifiers<Ix>
695where
696 Ix: IndexType,
697{
698 type Item = NodeIndex<Ix>;
699
700 fn next(&mut self) -> Option<Self::Item> {
701 self.r.next().map(Ix::new)
702 }
703
704 fn size_hint(&self) -> (usize, Option<usize>) {
705 self.r.size_hint()
706 }
707}
708
709impl<'a, N, E, Ty, Ix> IntoNodeIdentifiers for &'a Csr<N, E, Ty, Ix>
710where
711 Ty: EdgeType,
712 Ix: IndexType,
713{
714 type NodeIdentifiers = NodeIdentifiers<Ix>;
715 fn node_identifiers(self) -> Self::NodeIdentifiers {
716 NodeIdentifiers {
717 r: 0..self.node_count(),
718 ty: PhantomData,
719 }
720 }
721}
722
723impl<N, E, Ty, Ix> NodeCount for Csr<N, E, Ty, Ix>
724where
725 Ty: EdgeType,
726 Ix: IndexType,
727{
728 fn node_count(&self) -> usize {
729 (*self).node_count()
730 }
731}
732
733impl<N, E, Ty, Ix> GraphProp for Csr<N, E, Ty, Ix>
734where
735 Ty: EdgeType,
736 Ix: IndexType,
737{
738 type EdgeType = Ty;
739}
740
741#[allow(unused_variables)]
755#[cfg(test)]
756mod tests {
757 use super::Csr;
758 use crate::algo::bellman_ford;
759 use crate::algo::tarjan_scc;
760 #[cfg(not(feature = "std"))]
761 use alloc::vec::Vec;
762 use crate::visit::Dfs;
763 use crate::visit::VisitMap;
764 use crate::Undirected;
765
766 #[test]
767 fn csr1() {
768 let mut m: Csr = Csr::with_nodes(3);
769 m.add_edge(0, 0, ());
770 m.add_edge(1, 2, ());
771 m.add_edge(2, 2, ());
772 m.add_edge(0, 2, ());
773 m.add_edge(1, 0, ());
774 m.add_edge(1, 1, ());
775 #[cfg(feature = "std")]
776 println!("{:?}", m);
777 assert_eq!(&m.column, &[0, 2, 0, 1, 2, 2]);
778 assert_eq!(&m.row, &[0, 2, 5, 6]);
779
780 let added = m.add_edge(1, 2, ());
781 assert!(!added);
782 assert_eq!(&m.column, &[0, 2, 0, 1, 2, 2]);
783 assert_eq!(&m.row, &[0, 2, 5, 6]);
784
785 assert_eq!(m.neighbors_slice(1), &[0, 1, 2]);
786 assert_eq!(m.node_count(), 3);
787 assert_eq!(m.edge_count(), 6);
788 }
789
790 #[test]
791 fn csr_undirected() {
792 let mut m: Csr<(), (), Undirected> = Csr::with_nodes(3);
799 m.add_edge(0, 0, ());
800 m.add_edge(0, 2, ());
801 m.add_edge(1, 2, ());
802 m.add_edge(2, 2, ());
803 #[cfg(feature = "std")]
804 println!("{:?}", m);
805 assert_eq!(&m.column, &[0, 2, 2, 0, 1, 2]);
806 assert_eq!(&m.row, &[0, 2, 3, 6]);
807 assert_eq!(m.node_count(), 3);
808 assert_eq!(m.edge_count(), 4);
809 }
810
811 #[should_panic]
812 #[test]
813 fn csr_from_error_1() {
814 let m: Csr = Csr::from_sorted_edges(&[(0, 1), (1, 0), (0, 2)]).unwrap();
816 #[cfg(feature = "std")]
817 println!("{:?}", m);
818 }
819
820 #[should_panic]
821 #[test]
822 fn csr_from_error_2() {
823 let m: Csr = Csr::from_sorted_edges(&[(0, 1), (1, 0), (1, 2), (1, 1)]).unwrap();
825 #[cfg(feature = "std")]
826 println!("{:?}", m);
827 }
828
829 #[test]
830 fn csr_from() {
831 let m: Csr =
832 Csr::from_sorted_edges(&[(0, 1), (0, 2), (1, 0), (1, 1), (2, 2), (2, 4)]).unwrap();
833 #[cfg(feature = "std")]
834 println!("{:?}", m);
835 assert_eq!(m.neighbors_slice(0), &[1, 2]);
836 assert_eq!(m.neighbors_slice(1), &[0, 1]);
837 assert_eq!(m.neighbors_slice(2), &[2, 4]);
838 assert_eq!(m.node_count(), 5);
839 assert_eq!(m.edge_count(), 6);
840 }
841
842 #[test]
843 fn csr_dfs() {
844 let mut m: Csr = Csr::from_sorted_edges(&[
845 (0, 1),
846 (0, 2),
847 (1, 0),
848 (1, 1),
849 (1, 3),
850 (2, 2),
851 (4, 4),
853 (4, 5),
854 ])
855 .unwrap();
856 #[cfg(feature = "std")]
857 println!("{:?}", m);
858 let mut dfs = Dfs::new(&m, 0);
859 while let Some(_) = dfs.next(&m) {}
860 for i in 0..m.node_count() - 2 {
861 assert!(dfs.discovered.is_visited(&i), "visited {}", i)
862 }
863 assert!(!dfs.discovered[4]);
864 assert!(!dfs.discovered[5]);
865
866 m.add_edge(1, 4, ());
867 #[cfg(feature = "std")]
868 println!("{:?}", m);
869
870 dfs.reset(&m);
871 dfs.move_to(0);
872 while let Some(_) = dfs.next(&m) {}
873
874 for i in 0..m.node_count() {
875 assert!(dfs.discovered[i], "visited {}", i)
876 }
877 }
878
879 #[test]
880 fn csr_tarjan() {
881 let m: Csr = Csr::from_sorted_edges(&[
882 (0, 1),
883 (0, 2),
884 (1, 0),
885 (1, 1),
886 (1, 3),
887 (2, 2),
888 (2, 4),
889 (4, 4),
890 (4, 5),
891 (5, 2),
892 ])
893 .unwrap();
894 #[cfg(feature = "std")]
895 println!("{:?}", m);
896 let tarjan = tarjan_scc(&m);
897 #[cfg(feature = "std")]
898 println!("{:?}", tarjan);
899 }
900
901 #[test]
902 fn test_bellman_ford() {
903 let m: Csr<(), _> = Csr::from_sorted_edges(&[
904 (0, 1, 0.5),
905 (0, 2, 2.),
906 (1, 0, 1.),
907 (1, 1, 1.),
908 (1, 2, 1.),
909 (1, 3, 1.),
910 (2, 3, 3.),
911 (4, 5, 1.),
912 (5, 7, 2.),
913 (6, 7, 1.),
914 (7, 8, 3.),
915 ])
916 .unwrap();
917 #[cfg(feature = "std")]
918 println!("{:?}", m);
919 let result = bellman_ford(&m, 0).unwrap();
920 #[cfg(feature = "std")]
921 println!("{:?}", result);
922 let answer = [0., 0.5, 1.5, 1.5];
923 assert_eq!(&answer, &result.0[..4]);
924 assert!(answer[4..].iter().all(|&x| f64::is_infinite(x)));
925 }
926
927 #[test]
928 fn test_bellman_ford_neg_cycle() {
929 let m: Csr<(), _> = Csr::from_sorted_edges(&[
930 (0, 1, 0.5),
931 (0, 2, 2.),
932 (1, 0, 1.),
933 (1, 1, -1.),
934 (1, 2, 1.),
935 (1, 3, 1.),
936 (2, 3, 3.),
937 ])
938 .unwrap();
939 let result = bellman_ford(&m, 0);
940 assert!(result.is_err());
941 }
942
943 #[test]
944 fn test_edge_references() {
945 use crate::visit::EdgeRef;
946 use crate::visit::IntoEdgeReferences;
947 let m: Csr<(), _> = Csr::from_sorted_edges(&[
948 (0, 1, 0.5),
949 (0, 2, 2.),
950 (1, 0, 1.),
951 (1, 1, 1.),
952 (1, 2, 1.),
953 (1, 3, 1.),
954 (2, 3, 3.),
955 (4, 5, 1.),
956 (5, 7, 2.),
957 (6, 7, 1.),
958 (7, 8, 3.),
959 ])
960 .unwrap();
961 let mut copy = Vec::new();
962 for e in m.edge_references() {
963 copy.push((e.source(), e.target(), *e.weight()));
964 #[cfg(feature = "std")]
965 println!("{:?}", e);
966 }
967 let m2: Csr<(), _> = Csr::from_sorted_edges(©).unwrap();
968 assert_eq!(&m.row, &m2.row);
969 assert_eq!(&m.column, &m2.column);
970 assert_eq!(&m.edges, &m2.edges);
971 }
972
973 #[test]
974 fn test_add_node() {
975 let mut g: Csr = Csr::new();
976 let a = g.add_node(());
977 let b = g.add_node(());
978 let c = g.add_node(());
979
980 assert!(g.add_edge(a, b, ()));
981 assert!(g.add_edge(b, c, ()));
982 assert!(g.add_edge(c, a, ()));
983
984 #[cfg(feature = "std")]
985 println!("{:?}", g);
986
987 assert_eq!(g.node_count(), 3);
988
989 assert_eq!(g.neighbors_slice(a), &[b]);
990 assert_eq!(g.neighbors_slice(b), &[c]);
991 assert_eq!(g.neighbors_slice(c), &[a]);
992
993 assert_eq!(g.edge_count(), 3);
994 }
995
996 #[test]
997 fn test_add_node_with_existing_edges() {
998 let mut g: Csr = Csr::new();
999 let a = g.add_node(());
1000 let b = g.add_node(());
1001
1002 assert!(g.add_edge(a, b, ()));
1003
1004 let c = g.add_node(());
1005
1006 #[cfg(feature = "std")]
1007 println!("{:?}", g);
1008
1009 assert_eq!(g.node_count(), 3);
1010
1011 assert_eq!(g.neighbors_slice(a), &[b]);
1012 assert_eq!(g.neighbors_slice(b), &[]);
1013 assert_eq!(g.neighbors_slice(c), &[]);
1014
1015 assert_eq!(g.edge_count(), 1);
1016 }
1017}