1use 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
20pub type NodeIndex<Ix = DefaultIx> = Ix;
22pub type EdgeIndex = usize;
24
25const BINARY_SEARCH_CUTOFF: usize = 32;
26
27#[derive(Debug)]
45pub struct Csr<N = (), E = (), Ty = Directed, Ix = DefaultIx> {
46 column: Vec<NodeIndex<Ix>>,
48 edges: Vec<E>,
50 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 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 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#[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 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 if node > n.index() {
190 return Err(EdgesNotSorted {
191 first_error: (n.index(), m.index()),
192 });
193 }
194 if n.index() != node {
202 break 'inner;
203 }
204 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 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 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 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 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 let pos = match self.find_edge_pos(a, b) {
304 Ok(_) => return false, Err(i) => i,
306 };
307 self.column.insert(pos, b);
308 self.edges.insert(pos, weight);
309 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 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 pub fn out_degree(&self, a: NodeIndex<Ix>) -> usize {
361 let r = self.neighbors_range(a);
362 r.end - r.start
363 }
364
365 pub fn neighbors_slice(&self, a: NodeIndex<Ix>) -> &[NodeIndex<Ix>] {
369 self.neighbors_of(a).1
370 }
371
372 pub fn edges_slice(&self, a: NodeIndex<Ix>) -> &[E] {
376 &self.edges[self.neighbors_range(a)]
377 }
378
379 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 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; }
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 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#[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 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 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 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 (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(©).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}