1#[cfg(feature = "std")]
4use std::{
5 cmp,
6 marker::PhantomData,
7 mem,
8 ops::{Index, IndexMut},
9};
10
11#[cfg(not(feature = "std"))]
12use core::{
13 cmp,
14 marker::PhantomData,
15 mem,
16 ops::{Index, IndexMut},
17};
18
19#[cfg(not(feature = "std"))]
20use alloc::vec::Vec;
21
22use indexmap::IndexSet;
23
24use fixedbitset::FixedBitSet;
25
26use crate::{Directed, Direction, EdgeType, IntoWeightedEdge, Outgoing, Undirected};
27
28use crate::graph::NodeIndex as GraphNodeIndex;
29
30use crate::visit::{
31 Data, GetAdjacencyMatrix, GraphBase, GraphProp, IntoEdgeReferences, IntoEdges, IntoNeighbors,
32 IntoNeighborsDirected, IntoNodeIdentifiers, IntoNodeReferences, NodeCompactIndexable,
33 NodeCount, NodeIndexable, Visitable,
34};
35
36use crate::data::Build;
37
38pub use crate::graph::IndexType;
39
40type DefaultIx = u16;
44
45pub type NodeIndex<Ix = DefaultIx> = GraphNodeIndex<Ix>;
47
48mod private {
49 pub trait Sealed {}
50
51 impl<T> Sealed for super::NotZero<T> {}
52 impl<T> Sealed for Option<T> {}
53}
54
55pub trait Nullable: Default + Into<Option<<Self as Nullable>::Wrapped>> + private::Sealed {
60 #[doc(hidden)]
61 type Wrapped;
62
63 #[doc(hidden)]
64 fn new(value: Self::Wrapped) -> Self;
65
66 #[doc(hidden)]
67 fn as_ref(&self) -> Option<&Self::Wrapped>;
68
69 #[doc(hidden)]
70 fn as_mut(&mut self) -> Option<&mut Self::Wrapped>;
71
72 #[doc(hidden)]
73 fn is_null(&self) -> bool {
74 self.as_ref().is_none()
75 }
76}
77
78impl<T> Nullable for Option<T> {
79 type Wrapped = T;
80
81 fn new(value: T) -> Self {
82 Some(value)
83 }
84
85 fn as_ref(&self) -> Option<&Self::Wrapped> {
86 self.as_ref()
87 }
88
89 fn as_mut(&mut self) -> Option<&mut Self::Wrapped> {
90 self.as_mut()
91 }
92}
93
94pub struct NotZero<T>(T);
102
103impl<T: Zero> Default for NotZero<T> {
104 fn default() -> Self {
105 NotZero(T::zero())
106 }
107}
108
109impl<T: Zero> Nullable for NotZero<T> {
110 type Wrapped = T;
111
112 fn new(value: T) -> Self {
113 assert!(!value.is_zero());
114 NotZero(value)
115 }
116
117 fn is_null(&self) -> bool {
119 self.0.is_zero()
120 }
121
122 fn as_ref(&self) -> Option<&Self::Wrapped> {
123 if !self.is_null() {
124 Some(&self.0)
125 } else {
126 None
127 }
128 }
129
130 fn as_mut(&mut self) -> Option<&mut Self::Wrapped> {
131 if !self.is_null() {
132 Some(&mut self.0)
133 } else {
134 None
135 }
136 }
137}
138
139impl<T: Zero> Into<Option<T>> for NotZero<T> {
140 fn into(self) -> Option<T> {
141 if !self.is_null() {
142 Some(self.0)
143 } else {
144 None
145 }
146 }
147}
148
149pub trait Zero {
156 fn zero() -> Self;
158
159 fn is_zero(&self) -> bool;
161}
162
163macro_rules! not_zero_impl {
164 ($t:ty,$z:expr) => {
165 impl Zero for $t {
166 fn zero() -> Self {
167 $z as $t
168 }
169
170 fn is_zero(&self) -> bool {
171 self == &Self::zero()
172 }
173 }
174 };
175}
176
177macro_rules! not_zero_impls {
178 ($($t:ty),*) => {
179 $(
180 not_zero_impl!($t, 0);
181 )*
182 }
183}
184
185not_zero_impls!(u8, u16, u32, u64, usize);
186not_zero_impls!(i8, i16, i32, i64, isize);
187not_zero_impls!(f32, f64);
188
189#[inline]
191pub fn node_index(ax: usize) -> NodeIndex {
192 NodeIndex::new(ax)
193}
194
195#[derive(Clone)]
215pub struct MatrixGraph<N, E, Ty = Directed, Null: Nullable<Wrapped = E> = Option<E>, Ix = DefaultIx>
216{
217 node_adjacencies: Vec<Null>,
218 node_capacity: usize,
219 nodes: IdStorage<N>,
220 nb_edges: usize,
221 ty: PhantomData<Ty>,
222 ix: PhantomData<Ix>,
223}
224
225pub type DiMatrix<N, E, Null = Option<E>, Ix = DefaultIx> = MatrixGraph<N, E, Directed, Null, Ix>;
227
228pub type UnMatrix<N, E, Null = Option<E>, Ix = DefaultIx> = MatrixGraph<N, E, Undirected, Null, Ix>;
230
231impl<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType>
232 MatrixGraph<N, E, Ty, Null, Ix>
233{
234 pub fn with_capacity(node_capacity: usize) -> Self {
236 let mut m = Self {
237 node_adjacencies: vec![],
238 node_capacity: 0,
239 nodes: IdStorage::with_capacity(node_capacity),
240 nb_edges: 0,
241 ty: PhantomData,
242 ix: PhantomData,
243 };
244
245 debug_assert!(node_capacity <= <Ix as IndexType>::max().index());
246 m.extend_capacity_for_node(NodeIndex::new(node_capacity));
247
248 m
249 }
250
251 #[inline]
252 fn to_edge_position(&self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> usize {
253 to_linearized_matrix_position::<Ty>(a.index(), b.index(), self.node_capacity)
254 }
255
256 pub fn clear(&mut self) {
258 for edge in self.node_adjacencies.iter_mut() {
259 *edge = Default::default();
260 }
261 self.nodes.clear();
262 self.nb_edges = 0;
263 }
264
265 #[inline]
269 pub fn node_count(&self) -> usize {
270 self.nodes.len()
271 }
272
273 #[inline]
277 pub fn edge_count(&self) -> usize {
278 self.nb_edges
279 }
280
281 #[inline]
283 pub fn is_directed(&self) -> bool {
284 Ty::is_directed()
285 }
286
287 pub fn add_node(&mut self, weight: N) -> NodeIndex<Ix> {
295 NodeIndex::new(self.nodes.add(weight))
296 }
297
298 pub fn remove_node(&mut self, a: NodeIndex<Ix>) -> N {
304 for id in self.nodes.iter_ids() {
305 let position = self.to_edge_position(a, NodeIndex::new(id));
306 self.node_adjacencies[position] = Default::default();
307
308 if Ty::is_directed() {
309 let position = self.to_edge_position(NodeIndex::new(id), a);
310 self.node_adjacencies[position] = Default::default();
311 }
312 }
313
314 self.nodes.remove(a.index())
315 }
316
317 #[inline]
318 fn extend_capacity_for_node(&mut self, min_node: NodeIndex<Ix>) {
319 self.node_capacity = extend_linearized_matrix::<Ty, _>(
320 &mut self.node_adjacencies,
321 self.node_capacity,
322 min_node.index(),
323 );
324 }
325
326 #[inline]
327 fn extend_capacity_for_edge(&mut self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) {
328 let min_node = cmp::max(a, b);
329 if min_node.index() >= self.node_capacity {
330 self.extend_capacity_for_node(min_node);
331 }
332 }
333
334 pub fn update_edge(&mut self, a: NodeIndex<Ix>, b: NodeIndex<Ix>, weight: E) -> Option<E> {
343 self.extend_capacity_for_edge(a, b);
344
345 let p = self.to_edge_position(a, b);
346 let old_weight = mem::replace(&mut self.node_adjacencies[p], Null::new(weight));
347 if old_weight.is_null() {
348 self.nb_edges += 1;
349 }
350 old_weight.into()
351 }
352
353 pub fn add_edge(&mut self, a: NodeIndex<Ix>, b: NodeIndex<Ix>, weight: E) {
367 let old_edge_id = self.update_edge(a, b, weight);
368 assert!(old_edge_id.is_none());
369 }
370
371 pub fn remove_edge(&mut self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> E {
376 let p = self.to_edge_position(a, b);
377 let old_weight = mem::replace(&mut self.node_adjacencies[p], Default::default())
378 .into()
379 .unwrap();
380 let old_weight: Option<_> = old_weight.into();
381 self.nb_edges -= 1;
382 old_weight.unwrap()
383 }
384
385 pub fn has_edge(&self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> bool {
389 let p = self.to_edge_position(a, b);
390 !self.node_adjacencies[p].is_null()
391 }
392
393 pub fn node_weight(&self, a: NodeIndex<Ix>) -> &N {
399 &self.nodes[a.index()]
400 }
401
402 pub fn node_weight_mut(&mut self, a: NodeIndex<Ix>) -> &mut N {
408 &mut self.nodes[a.index()]
409 }
410
411 pub fn edge_weight(&self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> &E {
417 let p = self.to_edge_position(a, b);
418 self.node_adjacencies[p].as_ref().unwrap()
419 }
420
421 pub fn edge_weight_mut(&mut self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> &mut E {
427 let p = self.to_edge_position(a, b);
428 self.node_adjacencies[p].as_mut().unwrap()
429 }
430
431 pub fn neighbors(&self, a: NodeIndex<Ix>) -> Neighbors<Ty, Null, Ix> {
439 Neighbors(Edges::on_columns(
440 a.index(),
441 &self.node_adjacencies,
442 self.node_capacity,
443 ))
444 }
445
446 pub fn edges(&self, a: NodeIndex<Ix>) -> Edges<Ty, Null, Ix> {
454 Edges::on_columns(a.index(), &self.node_adjacencies, self.node_capacity)
455 }
456
457 pub fn from_edges<I>(iterable: I) -> Self
475 where
476 I: IntoIterator,
477 I::Item: IntoWeightedEdge<E>,
478 <I::Item as IntoWeightedEdge<E>>::NodeId: Into<NodeIndex<Ix>>,
479 N: Default,
480 {
481 let mut g = Self::default();
482 g.extend_with_edges(iterable);
483 g
484 }
485
486 pub fn extend_with_edges<I>(&mut self, iterable: I)
494 where
495 I: IntoIterator,
496 I::Item: IntoWeightedEdge<E>,
497 <I::Item as IntoWeightedEdge<E>>::NodeId: Into<NodeIndex<Ix>>,
498 N: Default,
499 {
500 for elt in iterable {
501 let (source, target, weight) = elt.into_weighted_edge();
502 let (source, target) = (source.into(), target.into());
503 let nx = cmp::max(source, target);
504 while nx.index() >= self.node_count() {
505 self.add_node(N::default());
506 }
507 self.add_edge(source, target, weight);
508 }
509 }
510}
511
512impl<N, E, Null: Nullable<Wrapped = E>, Ix: IndexType> MatrixGraph<N, E, Directed, Null, Ix> {
513 pub fn neighbors_directed(
523 &self,
524 a: NodeIndex<Ix>,
525 d: Direction,
526 ) -> Neighbors<Directed, Null, Ix> {
527 if d == Outgoing {
528 self.neighbors(a)
529 } else {
530 Neighbors(Edges::on_rows(
531 a.index(),
532 &self.node_adjacencies,
533 self.node_capacity,
534 ))
535 }
536 }
537
538 pub fn edges_directed(&self, a: NodeIndex<Ix>, d: Direction) -> Edges<Directed, Null, Ix> {
546 if d == Outgoing {
547 self.edges(a)
548 } else {
549 Edges::on_rows(a.index(), &self.node_adjacencies, self.node_capacity)
550 }
551 }
552}
553
554pub struct NodeIdentifiers<'a, Ix> {
561 iter: IdIterator<'a>,
562 ix: PhantomData<Ix>,
563}
564
565impl<'a, Ix: IndexType> NodeIdentifiers<'a, Ix> {
566 fn new(iter: IdIterator<'a>) -> Self {
567 Self {
568 iter,
569 ix: PhantomData,
570 }
571 }
572}
573
574impl<'a, Ix: IndexType> Iterator for NodeIdentifiers<'a, Ix> {
575 type Item = NodeIndex<Ix>;
576
577 fn next(&mut self) -> Option<Self::Item> {
578 self.iter.next().map(NodeIndex::new)
579 }
580}
581
582pub struct NodeReferences<'a, N: 'a, Ix> {
589 nodes: &'a IdStorage<N>,
590 iter: IdIterator<'a>,
591 ix: PhantomData<Ix>,
592}
593
594impl<'a, N: 'a, Ix> NodeReferences<'a, N, Ix> {
595 fn new(nodes: &'a IdStorage<N>) -> Self {
596 NodeReferences {
597 nodes,
598 iter: nodes.iter_ids(),
599 ix: PhantomData,
600 }
601 }
602}
603
604impl<'a, N: 'a, Ix: IndexType> Iterator for NodeReferences<'a, N, Ix> {
605 type Item = (NodeIndex<Ix>, &'a N);
606
607 fn next(&mut self) -> Option<Self::Item> {
608 self.iter
609 .next()
610 .map(|i| (NodeIndex::new(i), &self.nodes[i]))
611 }
612}
613
614pub struct EdgeReferences<'a, Ty: EdgeType, Null: 'a + Nullable, Ix> {
621 row: usize,
622 column: usize,
623 node_adjacencies: &'a [Null],
624 node_capacity: usize,
625 ty: PhantomData<Ty>,
626 ix: PhantomData<Ix>,
627}
628
629impl<'a, Ty: EdgeType, Null: 'a + Nullable, Ix> EdgeReferences<'a, Ty, Null, Ix> {
630 fn new(node_adjacencies: &'a [Null], node_capacity: usize) -> Self {
631 EdgeReferences {
632 row: 0,
633 column: 0,
634 node_adjacencies,
635 node_capacity,
636 ty: PhantomData,
637 ix: PhantomData,
638 }
639 }
640}
641
642impl<'a, Ty: EdgeType, Null: Nullable, Ix: IndexType> Iterator
643 for EdgeReferences<'a, Ty, Null, Ix>
644{
645 type Item = (NodeIndex<Ix>, NodeIndex<Ix>, &'a Null::Wrapped);
646
647 fn next(&mut self) -> Option<Self::Item> {
648 loop {
649 let (row, column) = (self.row, self.column);
650 if row >= self.node_capacity {
651 return None;
652 }
653
654 self.column += 1;
659 let max_column_len = if !Ty::is_directed() {
660 row + 1
661 } else {
662 self.node_capacity
663 };
664 if self.column >= max_column_len {
665 self.column = 0;
666 self.row += 1;
667 }
668
669 let p = to_linearized_matrix_position::<Ty>(row, column, self.node_capacity);
670 if let Some(e) = self.node_adjacencies[p].as_ref() {
671 return Some((NodeIndex::new(row), NodeIndex::new(column), e));
672 }
673 }
674 }
675}
676
677pub struct Neighbors<'a, Ty: EdgeType, Null: 'a + Nullable, Ix>(Edges<'a, Ty, Null, Ix>);
686
687impl<'a, Ty: EdgeType, Null: Nullable, Ix: IndexType> Iterator for Neighbors<'a, Ty, Null, Ix> {
688 type Item = NodeIndex<Ix>;
689
690 fn next(&mut self) -> Option<Self::Item> {
691 self.0.next().map(|(_, b, _)| b)
692 }
693}
694
695enum NeighborIterDirection {
696 Rows,
697 Columns,
698}
699
700pub struct Edges<'a, Ty: EdgeType, Null: 'a + Nullable, Ix> {
707 iter_direction: NeighborIterDirection,
708 node_adjacencies: &'a [Null],
709 node_capacity: usize,
710 row: usize,
711 column: usize,
712 ty: PhantomData<Ty>,
713 ix: PhantomData<Ix>,
714}
715
716impl<'a, Ty: EdgeType, Null: 'a + Nullable, Ix> Edges<'a, Ty, Null, Ix> {
717 fn on_columns(row: usize, node_adjacencies: &'a [Null], node_capacity: usize) -> Self {
718 Edges {
719 iter_direction: NeighborIterDirection::Columns,
720 node_adjacencies,
721 node_capacity,
722 row,
723 column: 0,
724 ty: PhantomData,
725 ix: PhantomData,
726 }
727 }
728
729 fn on_rows(column: usize, node_adjacencies: &'a [Null], node_capacity: usize) -> Self {
730 Edges {
731 iter_direction: NeighborIterDirection::Rows,
732 node_adjacencies,
733 node_capacity,
734 row: 0,
735 column,
736 ty: PhantomData,
737 ix: PhantomData,
738 }
739 }
740}
741
742impl<'a, Ty: EdgeType, Null: Nullable, Ix: IndexType> Iterator for Edges<'a, Ty, Null, Ix> {
743 type Item = (NodeIndex<Ix>, NodeIndex<Ix>, &'a Null::Wrapped);
744
745 fn next(&mut self) -> Option<Self::Item> {
746 use self::NeighborIterDirection::*;
747
748 loop {
749 let (row, column) = (self.row, self.column);
750 if row >= self.node_capacity || column >= self.node_capacity {
751 return None;
752 }
753
754 match self.iter_direction {
755 Rows => self.row += 1,
756 Columns => self.column += 1,
757 }
758
759 let p = to_linearized_matrix_position::<Ty>(row, column, self.node_capacity);
760 if let Some(e) = self.node_adjacencies[p].as_ref() {
761 let (a, b) = match self.iter_direction {
762 Rows => (column, row),
763 Columns => (row, column),
764 };
765
766 return Some((NodeIndex::new(a), NodeIndex::new(b), e));
767 }
768 }
769 }
770}
771
772#[inline]
773fn to_linearized_matrix_position<Ty: EdgeType>(row: usize, column: usize, width: usize) -> usize {
774 if Ty::is_directed() {
775 to_flat_square_matrix_position(row, column, width)
776 } else {
777 to_lower_triangular_matrix_position(row, column)
778 }
779}
780
781#[inline]
782fn extend_linearized_matrix<Ty: EdgeType, T: Default>(
783 node_adjacencies: &mut Vec<T>,
784 old_node_capacity: usize,
785 min_node_capacity: usize,
786) -> usize {
787 if Ty::is_directed() {
788 extend_flat_square_matrix(node_adjacencies, old_node_capacity, min_node_capacity)
789 } else {
790 extend_lower_triangular_matrix(node_adjacencies, min_node_capacity)
791 }
792}
793
794#[inline]
795fn to_flat_square_matrix_position(row: usize, column: usize, width: usize) -> usize {
796 row * width + column
797}
798
799#[inline]
800fn extend_flat_square_matrix<T: Default>(
801 node_adjacencies: &mut Vec<T>,
802 old_node_capacity: usize,
803 min_node_capacity: usize,
804) -> usize {
805 let min_node_capacity = (min_node_capacity + 1).next_power_of_two();
806
807 const MIN_CAPACITY: usize = 4;
810 let new_node_capacity = cmp::max(min_node_capacity, MIN_CAPACITY);
811
812 let mut new_node_adjacencies = vec![];
813 ensure_len(&mut new_node_adjacencies, new_node_capacity.pow(2));
814
815 for c in 0..old_node_capacity {
816 let pos = c * old_node_capacity;
817 let new_pos = c * new_node_capacity;
818
819 let mut old = &mut node_adjacencies[pos..pos + old_node_capacity];
820 let mut new = &mut new_node_adjacencies[new_pos..new_pos + old_node_capacity];
821
822 mem::swap(&mut old, &mut new);
823 }
824
825 mem::swap(node_adjacencies, &mut new_node_adjacencies);
826
827 new_node_capacity
828}
829
830#[inline]
831fn to_lower_triangular_matrix_position(row: usize, column: usize) -> usize {
832 let (row, column) = if row > column {
833 (row, column)
834 } else {
835 (column, row)
836 };
837 (row * (row + 1)) / 2 + column
838}
839
840#[inline]
841fn extend_lower_triangular_matrix<T: Default>(
842 node_adjacencies: &mut Vec<T>,
843 new_node_capacity: usize,
844) -> usize {
845 let max_pos = to_lower_triangular_matrix_position(new_node_capacity, new_node_capacity);
846 ensure_len(node_adjacencies, max_pos + 1);
847 new_node_capacity + 1
848}
849
850fn ensure_len<T: Default>(v: &mut Vec<T>, size: usize) {
852 if let Some(n) = size.checked_sub(v.len()) {
853 v.reserve(n);
854 for _ in 0..n {
855 v.push(T::default());
856 }
857 }
858}
859
860#[derive(Clone)]
861struct IdStorage<T> {
862 elements: Vec<Option<T>>,
863 upper_bound: usize,
864 removed_ids: IndexSet<usize>,
865}
866
867impl<T> IdStorage<T> {
868 fn with_capacity(capacity: usize) -> Self {
869 IdStorage {
870 elements: Vec::with_capacity(capacity),
871 upper_bound: 0,
872 removed_ids: IndexSet::new(),
873 }
874 }
875
876 fn add(&mut self, element: T) -> usize {
877 let id = if let Some(id) = self.removed_ids.pop() {
878 id
879 } else {
880 let id = self.upper_bound;
881 self.upper_bound += 1;
882
883 ensure_len(&mut self.elements, id + 1);
884
885 id
886 };
887
888 self.elements[id] = Some(element);
889
890 id
891 }
892
893 fn remove(&mut self, id: usize) -> T {
894 let data = self.elements[id].take().unwrap();
895 if self.upper_bound - id == 1 {
896 self.upper_bound -= 1;
897 } else {
898 self.removed_ids.insert(id);
899 }
900 data
901 }
902
903 fn clear(&mut self) {
904 self.upper_bound = 0;
905 self.elements.clear();
906 self.removed_ids.clear();
907 }
908
909 #[inline]
910 fn len(&self) -> usize {
911 self.upper_bound - self.removed_ids.len()
912 }
913
914 fn iter_ids(&self) -> IdIterator {
915 IdIterator {
916 upper_bound: self.upper_bound,
917 removed_ids: &self.removed_ids,
918 current: None,
919 }
920 }
921}
922
923impl<T> Index<usize> for IdStorage<T> {
924 type Output = T;
925 fn index(&self, index: usize) -> &T {
926 self.elements[index].as_ref().unwrap()
927 }
928}
929
930impl<T> IndexMut<usize> for IdStorage<T> {
931 fn index_mut(&mut self, index: usize) -> &mut T {
932 self.elements[index].as_mut().unwrap()
933 }
934}
935
936struct IdIterator<'a> {
937 upper_bound: usize,
938 removed_ids: &'a IndexSet<usize>,
939 current: Option<usize>,
940}
941
942impl<'a> Iterator for IdIterator<'a> {
943 type Item = usize;
944
945 fn next(&mut self) -> Option<Self::Item> {
946 let current = {
948 if self.current.is_none() {
949 self.current = Some(0);
950 self.current.as_mut().unwrap()
951 } else {
952 let current = self.current.as_mut().unwrap();
953 *current += 1;
954 current
955 }
956 };
957
958 while self.removed_ids.contains(current) && *current < self.upper_bound {
960 *current += 1;
961 }
962
963 if *current < self.upper_bound {
964 Some(*current)
965 } else {
966 None
967 }
968 }
969}
970
971impl<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> Default
973 for MatrixGraph<N, E, Ty, Null, Ix>
974{
975 fn default() -> Self {
976 Self::with_capacity(0)
977 }
978}
979
980impl<N, E> MatrixGraph<N, E, Directed> {
981 pub fn new() -> Self {
986 MatrixGraph::default()
987 }
988}
989
990impl<N, E> MatrixGraph<N, E, Undirected> {
991 pub fn new_undirected() -> Self {
996 MatrixGraph::default()
997 }
998}
999
1000impl<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> Index<NodeIndex<Ix>>
1004 for MatrixGraph<N, E, Ty, Null, Ix>
1005{
1006 type Output = N;
1007
1008 fn index(&self, ax: NodeIndex<Ix>) -> &N {
1009 self.node_weight(ax)
1010 }
1011}
1012
1013impl<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> IndexMut<NodeIndex<Ix>>
1017 for MatrixGraph<N, E, Ty, Null, Ix>
1018{
1019 fn index_mut(&mut self, ax: NodeIndex<Ix>) -> &mut N {
1020 self.node_weight_mut(ax)
1021 }
1022}
1023
1024impl<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> NodeCount
1025 for MatrixGraph<N, E, Ty, Null, Ix>
1026{
1027 fn node_count(&self) -> usize {
1028 MatrixGraph::node_count(self)
1029 }
1030}
1031
1032impl<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType>
1038 Index<(NodeIndex<Ix>, NodeIndex<Ix>)> for MatrixGraph<N, E, Ty, Null, Ix>
1039{
1040 type Output = E;
1041
1042 fn index(&self, (ax, bx): (NodeIndex<Ix>, NodeIndex<Ix>)) -> &E {
1043 self.edge_weight(ax, bx)
1044 }
1045}
1046
1047impl<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType>
1053 IndexMut<(NodeIndex<Ix>, NodeIndex<Ix>)> for MatrixGraph<N, E, Ty, Null, Ix>
1054{
1055 fn index_mut(&mut self, (ax, bx): (NodeIndex<Ix>, NodeIndex<Ix>)) -> &mut E {
1056 self.edge_weight_mut(ax, bx)
1057 }
1058}
1059
1060impl<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> GetAdjacencyMatrix
1061 for MatrixGraph<N, E, Ty, Null, Ix>
1062{
1063 type AdjMatrix = ();
1064
1065 fn adjacency_matrix(&self) -> Self::AdjMatrix {}
1066
1067 fn is_adjacent(&self, _: &Self::AdjMatrix, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> bool {
1068 MatrixGraph::has_edge(self, a, b)
1069 }
1070}
1071
1072impl<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> Visitable
1073 for MatrixGraph<N, E, Ty, Null, Ix>
1074{
1075 type Map = FixedBitSet;
1076
1077 fn visit_map(&self) -> FixedBitSet {
1078 FixedBitSet::with_capacity(self.node_count())
1079 }
1080
1081 fn reset_map(&self, map: &mut Self::Map) {
1082 map.clear();
1083 map.grow(self.node_count());
1084 }
1085}
1086
1087impl<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> GraphBase
1088 for MatrixGraph<N, E, Ty, Null, Ix>
1089{
1090 type NodeId = NodeIndex<Ix>;
1091 type EdgeId = (NodeIndex<Ix>, NodeIndex<Ix>);
1092}
1093
1094impl<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> GraphProp
1095 for MatrixGraph<N, E, Ty, Null, Ix>
1096{
1097 type EdgeType = Ty;
1098}
1099
1100impl<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> Data
1101 for MatrixGraph<N, E, Ty, Null, Ix>
1102{
1103 type NodeWeight = N;
1104 type EdgeWeight = E;
1105}
1106
1107impl<'a, N, E: 'a, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> IntoNodeIdentifiers
1108 for &'a MatrixGraph<N, E, Ty, Null, Ix>
1109{
1110 type NodeIdentifiers = NodeIdentifiers<'a, Ix>;
1111
1112 fn node_identifiers(self) -> Self::NodeIdentifiers {
1113 NodeIdentifiers::new(self.nodes.iter_ids())
1114 }
1115}
1116
1117impl<'a, N, E: 'a, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> IntoNeighbors
1118 for &'a MatrixGraph<N, E, Ty, Null, Ix>
1119{
1120 type Neighbors = Neighbors<'a, Ty, Null, Ix>;
1121
1122 fn neighbors(self, a: NodeIndex<Ix>) -> Self::Neighbors {
1123 MatrixGraph::neighbors(self, a)
1124 }
1125}
1126
1127impl<'a, N, E: 'a, Null: Nullable<Wrapped = E>, Ix: IndexType> IntoNeighborsDirected
1128 for &'a MatrixGraph<N, E, Directed, Null, Ix>
1129{
1130 type NeighborsDirected = Neighbors<'a, Directed, Null, Ix>;
1131
1132 fn neighbors_directed(self, a: NodeIndex<Ix>, d: Direction) -> Self::NeighborsDirected {
1133 MatrixGraph::neighbors_directed(self, a, d)
1134 }
1135}
1136
1137impl<'a, N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> IntoNodeReferences
1138 for &'a MatrixGraph<N, E, Ty, Null, Ix>
1139{
1140 type NodeRef = (NodeIndex<Ix>, &'a N);
1141 type NodeReferences = NodeReferences<'a, N, Ix>;
1142 fn node_references(self) -> Self::NodeReferences {
1143 NodeReferences::new(&self.nodes)
1144 }
1145}
1146
1147impl<'a, N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> IntoEdgeReferences
1148 for &'a MatrixGraph<N, E, Ty, Null, Ix>
1149{
1150 type EdgeRef = (NodeIndex<Ix>, NodeIndex<Ix>, &'a E);
1151 type EdgeReferences = EdgeReferences<'a, Ty, Null, Ix>;
1152 fn edge_references(self) -> Self::EdgeReferences {
1153 EdgeReferences::new(&self.node_adjacencies, self.node_capacity)
1154 }
1155}
1156
1157impl<'a, N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> IntoEdges
1158 for &'a MatrixGraph<N, E, Ty, Null, Ix>
1159{
1160 type Edges = Edges<'a, Ty, Null, Ix>;
1161 fn edges(self, a: Self::NodeId) -> Self::Edges {
1162 MatrixGraph::edges(self, a)
1163 }
1164}
1165
1166impl<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> NodeIndexable
1167 for MatrixGraph<N, E, Ty, Null, Ix>
1168{
1169 fn node_bound(&self) -> usize {
1170 self.node_count()
1171 }
1172
1173 fn to_index(&self, ix: NodeIndex<Ix>) -> usize {
1174 ix.index()
1175 }
1176
1177 fn from_index(&self, ix: usize) -> Self::NodeId {
1178 NodeIndex::new(ix)
1179 }
1180}
1181
1182impl<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> NodeCompactIndexable
1183 for MatrixGraph<N, E, Ty, Null, Ix>
1184{
1185}
1186
1187impl<N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> Build
1188 for MatrixGraph<N, E, Ty, Null, Ix>
1189{
1190 fn add_node(&mut self, weight: Self::NodeWeight) -> Self::NodeId {
1191 self.add_node(weight)
1192 }
1193
1194 fn add_edge(
1195 &mut self,
1196 a: Self::NodeId,
1197 b: Self::NodeId,
1198 weight: Self::EdgeWeight,
1199 ) -> Option<Self::EdgeId> {
1200 if !self.has_edge(a, b) {
1201 MatrixGraph::update_edge(self, a, b, weight);
1202 Some((a, b))
1203 } else {
1204 None
1205 }
1206 }
1207
1208 fn update_edge(
1209 &mut self,
1210 a: Self::NodeId,
1211 b: Self::NodeId,
1212 weight: Self::EdgeWeight,
1213 ) -> Self::EdgeId {
1214 MatrixGraph::update_edge(self, a, b, weight);
1215 (a, b)
1216 }
1217}
1218
1219#[cfg(test)]
1220mod tests {
1221 use super::*;
1222 use crate::{Incoming, Outgoing};
1223
1224 #[test]
1225 fn test_new() {
1226 let g = MatrixGraph::<i32, i32>::new();
1227 assert_eq!(g.node_count(), 0);
1228 assert_eq!(g.edge_count(), 0);
1229 }
1230
1231 #[test]
1232 fn test_default() {
1233 let g = MatrixGraph::<i32, i32>::default();
1234 assert_eq!(g.node_count(), 0);
1235 assert_eq!(g.edge_count(), 0);
1236 }
1237
1238 #[test]
1239 fn test_with_capacity() {
1240 let g = MatrixGraph::<i32, i32>::with_capacity(10);
1241 assert_eq!(g.node_count(), 0);
1242 assert_eq!(g.edge_count(), 0);
1243 }
1244
1245 #[test]
1246 fn test_node_indexing() {
1247 let mut g: MatrixGraph<char, ()> = MatrixGraph::new();
1248 let a = g.add_node('a');
1249 let b = g.add_node('b');
1250 assert_eq!(g.node_count(), 2);
1251 assert_eq!(g.edge_count(), 0);
1252 assert_eq!(g[a], 'a');
1253 assert_eq!(g[b], 'b');
1254 }
1255
1256 #[test]
1257 fn test_remove_node() {
1258 let mut g: MatrixGraph<char, ()> = MatrixGraph::new();
1259 let a = g.add_node('a');
1260
1261 g.remove_node(a);
1262
1263 assert_eq!(g.node_count(), 0);
1264 assert_eq!(g.edge_count(), 0);
1265 }
1266
1267 #[test]
1268 fn test_add_edge() {
1269 let mut g = MatrixGraph::new();
1270 let a = g.add_node('a');
1271 let b = g.add_node('b');
1272 let c = g.add_node('c');
1273 g.add_edge(a, b, ());
1274 g.add_edge(b, c, ());
1275 assert_eq!(g.node_count(), 3);
1276 assert_eq!(g.edge_count(), 2);
1277 }
1278
1279 #[test]
1280 fn test_add_edge_with_weights() {
1281 let mut g = MatrixGraph::new();
1282 let a = g.add_node('a');
1283 let b = g.add_node('b');
1284 let c = g.add_node('c');
1285 g.add_edge(a, b, true);
1286 g.add_edge(b, c, false);
1287 assert_eq!(*g.edge_weight(a, b), true);
1288 assert_eq!(*g.edge_weight(b, c), false);
1289 }
1290
1291 #[test]
1292 fn test_add_edge_with_weights_undirected() {
1293 let mut g = MatrixGraph::new_undirected();
1294 let a = g.add_node('a');
1295 let b = g.add_node('b');
1296 let c = g.add_node('c');
1297 let d = g.add_node('d');
1298 g.add_edge(a, b, "ab");
1299 g.add_edge(a, a, "aa");
1300 g.add_edge(b, c, "bc");
1301 g.add_edge(d, d, "dd");
1302 assert_eq!(*g.edge_weight(a, b), "ab");
1303 assert_eq!(*g.edge_weight(b, c), "bc");
1304 }
1305
1306 trait IntoVec<T> {
1308 fn into_vec(self) -> Vec<T>;
1309 }
1310
1311 impl<It, T> IntoVec<T> for It
1312 where
1313 It: Iterator<Item = T>,
1314 {
1315 fn into_vec(self) -> Vec<T> {
1316 self.collect()
1317 }
1318 }
1319
1320 #[test]
1321 fn test_clear() {
1322 let mut g = MatrixGraph::new();
1323 let a = g.add_node('a');
1324 let b = g.add_node('b');
1325 let c = g.add_node('c');
1326 assert_eq!(g.node_count(), 3);
1327
1328 g.add_edge(a, b, ());
1329 g.add_edge(b, c, ());
1330 g.add_edge(c, a, ());
1331 assert_eq!(g.edge_count(), 3);
1332
1333 g.clear();
1334
1335 assert_eq!(g.node_count(), 0);
1336 assert_eq!(g.edge_count(), 0);
1337
1338 let a = g.add_node('a');
1339 let b = g.add_node('b');
1340 let c = g.add_node('c');
1341 assert_eq!(g.node_count(), 3);
1342 assert_eq!(g.edge_count(), 0);
1343
1344 assert_eq!(g.neighbors_directed(a, Incoming).into_vec(), vec![]);
1345 assert_eq!(g.neighbors_directed(b, Incoming).into_vec(), vec![]);
1346 assert_eq!(g.neighbors_directed(c, Incoming).into_vec(), vec![]);
1347
1348 assert_eq!(g.neighbors_directed(a, Outgoing).into_vec(), vec![]);
1349 assert_eq!(g.neighbors_directed(b, Outgoing).into_vec(), vec![]);
1350 assert_eq!(g.neighbors_directed(c, Outgoing).into_vec(), vec![]);
1351 }
1352
1353 #[test]
1354 fn test_clear_undirected() {
1355 let mut g = MatrixGraph::new_undirected();
1356 let a = g.add_node('a');
1357 let b = g.add_node('b');
1358 let c = g.add_node('c');
1359 assert_eq!(g.node_count(), 3);
1360
1361 g.add_edge(a, b, ());
1362 g.add_edge(b, c, ());
1363 g.add_edge(c, a, ());
1364 assert_eq!(g.edge_count(), 3);
1365
1366 g.clear();
1367
1368 assert_eq!(g.node_count(), 0);
1369 assert_eq!(g.edge_count(), 0);
1370
1371 let a = g.add_node('a');
1372 let b = g.add_node('b');
1373 let c = g.add_node('c');
1374 assert_eq!(g.node_count(), 3);
1375 assert_eq!(g.edge_count(), 0);
1376
1377 assert_eq!(g.neighbors(a).into_vec(), vec![]);
1378 assert_eq!(g.neighbors(b).into_vec(), vec![]);
1379 assert_eq!(g.neighbors(c).into_vec(), vec![]);
1380 }
1381
1382 trait IntoSortedVec<T> {
1384 fn into_sorted_vec(self) -> Vec<T>;
1385 }
1386
1387 impl<It, T> IntoSortedVec<T> for It
1388 where
1389 It: Iterator<Item = T>,
1390 T: Ord,
1391 {
1392 fn into_sorted_vec(self) -> Vec<T> {
1393 let mut v: Vec<T> = self.collect();
1394 v.sort();
1395 v
1396 }
1397 }
1398
1399 macro_rules! sorted_vec {
1401 ($($x:expr),*) => {
1402 {
1403 let mut v = vec![$($x,)*];
1404 v.sort();
1405 v
1406 }
1407 }
1408 }
1409
1410 #[test]
1411 fn test_neighbors() {
1412 let mut g = MatrixGraph::new();
1413 let a = g.add_node('a');
1414 let b = g.add_node('b');
1415 let c = g.add_node('c');
1416 g.add_edge(a, b, ());
1417 g.add_edge(a, c, ());
1418
1419 let a_neighbors = g.neighbors(a).into_sorted_vec();
1420 assert_eq!(a_neighbors, sorted_vec![b, c]);
1421
1422 let b_neighbors = g.neighbors(b).into_sorted_vec();
1423 assert_eq!(b_neighbors, vec![]);
1424
1425 let c_neighbors = g.neighbors(c).into_sorted_vec();
1426 assert_eq!(c_neighbors, vec![]);
1427 }
1428
1429 #[test]
1430 fn test_neighbors_undirected() {
1431 let mut g = MatrixGraph::new_undirected();
1432 let a = g.add_node('a');
1433 let b = g.add_node('b');
1434 let c = g.add_node('c');
1435 g.add_edge(a, b, ());
1436 g.add_edge(a, c, ());
1437
1438 let a_neighbors = g.neighbors(a).into_sorted_vec();
1439 assert_eq!(a_neighbors, sorted_vec![b, c]);
1440
1441 let b_neighbors = g.neighbors(b).into_sorted_vec();
1442 assert_eq!(b_neighbors, sorted_vec![a]);
1443
1444 let c_neighbors = g.neighbors(c).into_sorted_vec();
1445 assert_eq!(c_neighbors, sorted_vec![a]);
1446 }
1447
1448 #[test]
1449 fn test_remove_node_and_edges() {
1450 let mut g = MatrixGraph::new();
1451 let a = g.add_node('a');
1452 let b = g.add_node('b');
1453 let c = g.add_node('c');
1454 g.add_edge(a, b, ());
1455 g.add_edge(b, c, ());
1456 g.add_edge(c, a, ());
1457
1458 g.remove_node(b);
1460
1461 assert_eq!(g.node_count(), 2);
1462
1463 let a_neighbors = g.neighbors(a).into_sorted_vec();
1464 assert_eq!(a_neighbors, vec![]);
1465
1466 let c_neighbors = g.neighbors(c).into_sorted_vec();
1467 assert_eq!(c_neighbors, vec![a]);
1468 }
1469
1470 #[test]
1471 fn test_remove_node_and_edges_undirected() {
1472 let mut g = UnMatrix::new_undirected();
1473 let a = g.add_node('a');
1474 let b = g.add_node('b');
1475 let c = g.add_node('c');
1476 g.add_edge(a, b, ());
1477 g.add_edge(b, c, ());
1478 g.add_edge(c, a, ());
1479
1480 g.remove_node(a);
1482
1483 assert_eq!(g.node_count(), 2);
1484
1485 let b_neighbors = g.neighbors(b).into_sorted_vec();
1486 assert_eq!(b_neighbors, vec![c]);
1487
1488 let c_neighbors = g.neighbors(c).into_sorted_vec();
1489 assert_eq!(c_neighbors, vec![b]);
1490 }
1491
1492 #[test]
1493 fn test_node_identifiers() {
1494 let mut g = MatrixGraph::new();
1495 let a = g.add_node('a');
1496 let b = g.add_node('b');
1497 let c = g.add_node('c');
1498 let d = g.add_node('c');
1499 g.add_edge(a, b, ());
1500 g.add_edge(a, c, ());
1501
1502 let node_ids = g.node_identifiers().into_sorted_vec();
1503 assert_eq!(node_ids, sorted_vec![a, b, c, d]);
1504 }
1505
1506 #[test]
1507 fn test_edges_directed() {
1508 let g: MatrixGraph<char, bool> = MatrixGraph::from_edges(&[
1509 (0, 5),
1510 (0, 2),
1511 (0, 3),
1512 (0, 1),
1513 (1, 3),
1514 (2, 3),
1515 (2, 4),
1516 (4, 0),
1517 (6, 6),
1518 ]);
1519
1520 assert_eq!(g.edges_directed(node_index(0), Outgoing).count(), 4);
1521 assert_eq!(g.edges_directed(node_index(1), Outgoing).count(), 1);
1522 assert_eq!(g.edges_directed(node_index(2), Outgoing).count(), 2);
1523 assert_eq!(g.edges_directed(node_index(3), Outgoing).count(), 0);
1524 assert_eq!(g.edges_directed(node_index(4), Outgoing).count(), 1);
1525 assert_eq!(g.edges_directed(node_index(5), Outgoing).count(), 0);
1526 assert_eq!(g.edges_directed(node_index(6), Outgoing).count(), 1);
1527
1528 assert_eq!(g.edges_directed(node_index(0), Incoming).count(), 1);
1529 assert_eq!(g.edges_directed(node_index(1), Incoming).count(), 1);
1530 assert_eq!(g.edges_directed(node_index(2), Incoming).count(), 1);
1531 assert_eq!(g.edges_directed(node_index(3), Incoming).count(), 3);
1532 assert_eq!(g.edges_directed(node_index(4), Incoming).count(), 1);
1533 assert_eq!(g.edges_directed(node_index(5), Incoming).count(), 1);
1534 assert_eq!(g.edges_directed(node_index(6), Incoming).count(), 1);
1535 }
1536
1537 #[test]
1538 fn test_edges_undirected() {
1539 let g: UnMatrix<char, bool> = UnMatrix::from_edges(&[
1540 (0, 5),
1541 (0, 2),
1542 (0, 3),
1543 (0, 1),
1544 (1, 3),
1545 (2, 3),
1546 (2, 4),
1547 (4, 0),
1548 (6, 6),
1549 ]);
1550
1551 assert_eq!(g.edges(node_index(0)).count(), 5);
1552 assert_eq!(g.edges(node_index(1)).count(), 2);
1553 assert_eq!(g.edges(node_index(2)).count(), 3);
1554 assert_eq!(g.edges(node_index(3)).count(), 3);
1555 assert_eq!(g.edges(node_index(4)).count(), 2);
1556 assert_eq!(g.edges(node_index(5)).count(), 1);
1557 assert_eq!(g.edges(node_index(6)).count(), 1);
1558 }
1559
1560 #[test]
1561 fn test_edges_of_absent_node_is_empty_iterator() {
1562 let g: MatrixGraph<char, bool> = MatrixGraph::new();
1563 assert_eq!(g.edges(node_index(0)).count(), 0);
1564 }
1565
1566 #[test]
1567 fn test_neighbors_of_absent_node_is_empty_iterator() {
1568 let g: MatrixGraph<char, bool> = MatrixGraph::new();
1569 assert_eq!(g.neighbors(node_index(0)).count(), 0);
1570 }
1571
1572 #[test]
1573 fn test_edge_references() {
1574 let g: MatrixGraph<char, bool> = MatrixGraph::from_edges(&[
1575 (0, 5),
1576 (0, 2),
1577 (0, 3),
1578 (0, 1),
1579 (1, 3),
1580 (2, 3),
1581 (2, 4),
1582 (4, 0),
1583 (6, 6),
1584 ]);
1585
1586 assert_eq!(g.edge_references().count(), 9);
1587 }
1588
1589 #[test]
1590 fn test_edge_references_undirected() {
1591 let g: UnMatrix<char, bool> = UnMatrix::from_edges(&[
1592 (0, 5),
1593 (0, 2),
1594 (0, 3),
1595 (0, 1),
1596 (1, 3),
1597 (2, 3),
1598 (2, 4),
1599 (4, 0),
1600 (6, 6),
1601 ]);
1602
1603 assert_eq!(g.edge_references().count(), 9);
1604 }
1605
1606 #[test]
1607 fn test_id_storage() {
1608 use super::IdStorage;
1609
1610 let mut storage: IdStorage<char> = IdStorage::with_capacity(0);
1611 let a = storage.add('a');
1612 let b = storage.add('b');
1613 let c = storage.add('c');
1614
1615 assert!(a < b && b < c);
1616
1617 assert_eq!(storage.iter_ids().into_vec(), vec![a, b, c]);
1619
1620 storage.remove(b);
1621
1622 let bb = storage.add('B');
1624 assert_eq!(b, bb);
1625
1626 assert_eq!(storage.iter_ids().into_vec(), vec![a, b, c]);
1628 }
1629
1630 #[test]
1631 fn test_not_zero() {
1632 let mut g: MatrixGraph<(), i32, Directed, NotZero<i32>> = MatrixGraph::default();
1633
1634 let a = g.add_node(());
1635 let b = g.add_node(());
1636
1637 assert!(!g.has_edge(a, b));
1638 assert_eq!(g.edge_count(), 0);
1639
1640 g.add_edge(a, b, 12);
1641
1642 assert!(g.has_edge(a, b));
1643 assert_eq!(g.edge_count(), 1);
1644 assert_eq!(g.edge_weight(a, b), &12);
1645
1646 g.remove_edge(a, b);
1647
1648 assert!(!g.has_edge(a, b));
1649 assert_eq!(g.edge_count(), 0);
1650 }
1651
1652 #[test]
1653 #[should_panic]
1654 fn test_not_zero_asserted() {
1655 let mut g: MatrixGraph<(), i32, Directed, NotZero<i32>> = MatrixGraph::default();
1656
1657 let a = g.add_node(());
1658 let b = g.add_node(());
1659
1660 g.add_edge(a, b, 0); }
1662
1663 #[test]
1664 fn test_not_zero_float() {
1665 let mut g: MatrixGraph<(), f32, Directed, NotZero<f32>> = MatrixGraph::default();
1666
1667 let a = g.add_node(());
1668 let b = g.add_node(());
1669
1670 assert!(!g.has_edge(a, b));
1671 assert_eq!(g.edge_count(), 0);
1672
1673 g.add_edge(a, b, 12.);
1674
1675 assert!(g.has_edge(a, b));
1676 assert_eq!(g.edge_count(), 1);
1677 assert_eq!(g.edge_weight(a, b), &12.);
1678
1679 g.remove_edge(a, b);
1680
1681 assert!(!g.has_edge(a, b));
1682 assert_eq!(g.edge_count(), 0);
1683 }
1684}