1use alloc::{fmt, vec, vec::Vec};
4use core::{
5 cmp,
6 hash::BuildHasher,
7 marker::PhantomData,
8 mem,
9 ops::{Index, IndexMut},
10};
11
12use fixedbitset::FixedBitSet;
13use indexmap::IndexSet;
14
15use crate::{
16 data::Build,
17 graph::NodeIndex as GraphNodeIndex,
18 visit::{
19 Data, EdgeCount, GetAdjacencyMatrix, GraphBase, GraphProp, IntoEdgeReferences, IntoEdges,
20 IntoEdgesDirected, IntoNeighbors, IntoNeighborsDirected, IntoNodeIdentifiers,
21 IntoNodeReferences, NodeCount, NodeIndexable, Visitable,
22 },
23 Directed, Direction, EdgeType, IntoWeightedEdge, Outgoing, Undirected,
24};
25
26#[cfg(feature = "std")]
27use std::collections::hash_map::RandomState;
28
29pub use crate::graph::IndexType;
30
31type DefaultIx = u16;
35
36pub type NodeIndex<Ix = DefaultIx> = GraphNodeIndex<Ix>;
38
39mod private {
40 pub trait Sealed {}
41
42 impl<T> Sealed for super::NotZero<T> {}
43 impl<T> Sealed for Option<T> {}
44}
45
46pub trait Nullable: Default + Into<Option<<Self as Nullable>::Wrapped>> + private::Sealed {
51 #[doc(hidden)]
52 type Wrapped;
53
54 #[doc(hidden)]
55 fn new(value: Self::Wrapped) -> Self;
56
57 #[doc(hidden)]
58 fn as_ref(&self) -> Option<&Self::Wrapped>;
59
60 #[doc(hidden)]
61 fn as_mut(&mut self) -> Option<&mut Self::Wrapped>;
62
63 #[doc(hidden)]
64 fn is_null(&self) -> bool {
65 self.as_ref().is_none()
66 }
67}
68
69impl<T> Nullable for Option<T> {
70 type Wrapped = T;
71
72 fn new(value: T) -> Self {
73 Some(value)
74 }
75
76 fn as_ref(&self) -> Option<&Self::Wrapped> {
77 self.as_ref()
78 }
79
80 fn as_mut(&mut self) -> Option<&mut Self::Wrapped> {
81 self.as_mut()
82 }
83}
84
85pub struct NotZero<T>(T);
93
94impl<T: Zero> Default for NotZero<T> {
95 fn default() -> Self {
96 NotZero(T::zero())
97 }
98}
99
100impl<T: Zero> Nullable for NotZero<T> {
101 #[doc(hidden)]
102 type Wrapped = T;
103
104 #[doc(hidden)]
105 fn new(value: T) -> Self {
106 assert!(!value.is_zero());
107 NotZero(value)
108 }
109
110 #[doc(hidden)]
112 fn is_null(&self) -> bool {
113 self.0.is_zero()
114 }
115
116 #[doc(hidden)]
117 fn as_ref(&self) -> Option<&Self::Wrapped> {
118 if !self.is_null() {
119 Some(&self.0)
120 } else {
121 None
122 }
123 }
124
125 #[doc(hidden)]
126 fn as_mut(&mut self) -> Option<&mut Self::Wrapped> {
127 if !self.is_null() {
128 Some(&mut self.0)
129 } else {
130 None
131 }
132 }
133}
134
135impl<T: Zero> From<NotZero<T>> for Option<T> {
136 fn from(not_zero: NotZero<T>) -> Self {
137 if !not_zero.is_null() {
138 Some(not_zero.0)
139 } else {
140 None
141 }
142 }
143}
144
145pub trait Zero {
152 fn zero() -> Self;
154
155 fn is_zero(&self) -> bool;
157}
158
159macro_rules! not_zero_impl {
160 ($t:ty,$z:expr) => {
161 impl Zero for $t {
162 fn zero() -> Self {
163 $z as $t
164 }
165
166 #[allow(clippy::float_cmp)]
167 fn is_zero(&self) -> bool {
168 self == &Self::zero()
169 }
170 }
171 };
172}
173
174macro_rules! not_zero_impls {
175 ($($t:ty),*) => {
176 $(
177 not_zero_impl!($t, 0);
178 )*
179 }
180}
181
182not_zero_impls!(u8, u16, u32, u64, usize);
183not_zero_impls!(i8, i16, i32, i64, isize);
184not_zero_impls!(f32, f64);
185
186#[inline]
188pub fn node_index(ax: usize) -> NodeIndex {
189 NodeIndex::new(ax)
190}
191
192#[derive(Debug, Clone, Copy, PartialEq, Eq)]
194pub enum MatrixError {
195 NodeIxLimit,
197
198 NodeMissed(usize),
200}
201
202#[cfg(feature = "std")]
203impl std::error::Error for MatrixError {}
204
205#[cfg(not(feature = "std"))]
206impl core::error::Error for MatrixError {}
207
208impl fmt::Display for MatrixError {
209 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
210 match self {
211 MatrixError::NodeIxLimit => write!(
212 f,
213 "The MatrixGraph is at the maximum number of nodes for its index"
214 ),
215
216 MatrixError::NodeMissed(i) => {
217 write!(f, "The node with index {i} is missing from the graph.")
218 }
219 }
220 }
221}
222
223#[derive(Clone)]
243pub struct MatrixGraph<
244 N,
245 E,
246 #[cfg(feature = "std")] S = RandomState,
247 #[cfg(not(feature = "std"))] S,
248 Ty = Directed,
249 Null: Nullable<Wrapped = E> = Option<E>,
250 Ix = DefaultIx,
251> {
252 node_adjacencies: Vec<Null>,
253 node_capacity: usize,
254 nodes: IdStorage<N, S>,
255 nb_edges: usize,
256 ty: PhantomData<Ty>,
257 ix: PhantomData<Ix>,
258}
259
260pub type DiMatrix<
262 N,
263 E,
264 #[cfg(feature = "std")] S = RandomState,
265 #[cfg(not(feature = "std"))] S,
266 Null = Option<E>,
267 Ix = DefaultIx,
268> = MatrixGraph<N, E, S, Directed, Null, Ix>;
269
270pub type UnMatrix<
272 N,
273 E,
274 #[cfg(feature = "std")] S = RandomState,
275 #[cfg(not(feature = "std"))] S,
276 Null = Option<E>,
277 Ix = DefaultIx,
278> = MatrixGraph<N, E, S, Undirected, Null, Ix>;
279
280impl<N, E, S: BuildHasher, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType>
281 MatrixGraph<N, E, S, Ty, Null, Ix>
282{
283 pub fn with_capacity(node_capacity: usize) -> Self
285 where
286 S: Default,
287 {
288 Self::with_capacity_and_hasher(node_capacity, Default::default())
289 }
290
291 pub fn with_capacity_and_hasher(node_capacity: usize, hasher: S) -> Self {
293 let mut m = Self {
294 node_adjacencies: vec![],
295 node_capacity: 0,
296 nodes: IdStorage::with_capacity_and_hasher(node_capacity, hasher),
297 nb_edges: 0,
298 ty: PhantomData,
299 ix: PhantomData,
300 };
301
302 debug_assert!(node_capacity <= <Ix as IndexType>::max().index());
303 if node_capacity > 0 {
304 m.extend_capacity_for_node(NodeIndex::new(node_capacity - 1), true);
305 }
306
307 m
308 }
309
310 #[inline]
311 fn to_edge_position(&self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> Option<usize> {
312 if cmp::max(a.index(), b.index()) >= self.node_capacity {
313 return None;
314 }
315 Some(self.to_edge_position_unchecked(a, b))
316 }
317
318 #[inline]
319 fn to_edge_position_unchecked(&self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> usize {
320 to_linearized_matrix_position::<Ty>(a.index(), b.index(), self.node_capacity)
321 }
322
323 pub fn clear(&mut self) {
325 for edge in self.node_adjacencies.iter_mut() {
326 *edge = Default::default();
327 }
328 self.nodes.clear();
329 self.nb_edges = 0;
330 }
331
332 #[inline]
336 pub fn node_count(&self) -> usize {
337 self.nodes.len()
338 }
339
340 #[inline]
344 pub fn edge_count(&self) -> usize {
345 self.nb_edges
346 }
347
348 #[inline]
350 pub fn is_directed(&self) -> bool {
351 Ty::is_directed()
352 }
353
354 #[track_caller]
362 pub fn add_node(&mut self, weight: N) -> NodeIndex<Ix> {
363 NodeIndex::new(self.nodes.add(weight))
364 }
365
366 pub fn try_add_node(&mut self, weight: N) -> Result<NodeIndex<Ix>, MatrixError> {
375 let node_idx = NodeIndex::<Ix>::new(self.nodes.len());
376 if !(<Ix as IndexType>::max().index() == !0 || NodeIndex::end() != node_idx) {
377 return Err(MatrixError::NodeIxLimit);
378 }
379 Ok(NodeIndex::new(self.nodes.add(weight)))
380 }
381
382 #[track_caller]
388 pub fn remove_node(&mut self, a: NodeIndex<Ix>) -> N {
389 for id in self.nodes.iter_ids() {
390 let position = self.to_edge_position(a, NodeIndex::new(id));
391 if let Some(pos) = position {
392 self.node_adjacencies[pos] = Default::default();
393 }
394
395 if Ty::is_directed() {
396 let position = self.to_edge_position(NodeIndex::new(id), a);
397 if let Some(pos) = position {
398 self.node_adjacencies[pos] = Default::default();
399 }
400 }
401 }
402
403 self.nodes.remove(a.index())
404 }
405
406 #[inline]
407 fn extend_capacity_for_node(&mut self, min_node: NodeIndex<Ix>, exact: bool) {
408 self.node_capacity = extend_linearized_matrix::<Ty, _>(
409 &mut self.node_adjacencies,
410 self.node_capacity,
411 min_node.index() + 1,
412 exact,
413 );
414 }
415
416 #[inline]
417 fn extend_capacity_for_edge(&mut self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) {
418 let min_node = cmp::max(a, b);
419 if min_node.index() >= self.node_capacity {
420 self.extend_capacity_for_node(min_node, false);
421 }
422 }
423
424 #[track_caller]
433 pub fn update_edge(&mut self, a: NodeIndex<Ix>, b: NodeIndex<Ix>, weight: E) -> Option<E> {
434 self.extend_capacity_for_edge(a, b);
435 let p = self.to_edge_position_unchecked(a, b);
436 let old_weight = mem::replace(&mut self.node_adjacencies[p], Null::new(weight));
437 if old_weight.is_null() {
438 self.nb_edges += 1;
439 }
440 old_weight.into()
441 }
442
443 pub fn try_update_edge(
453 &mut self,
454 a: NodeIndex<Ix>,
455 b: NodeIndex<Ix>,
456 weight: E,
457 ) -> Result<Option<E>, MatrixError> {
458 self.assert_node_bounds(a, b)?;
459 Ok(self.update_edge(a, b, weight))
460 }
461
462 #[track_caller]
474 pub fn add_edge(&mut self, a: NodeIndex<Ix>, b: NodeIndex<Ix>, weight: E) {
475 let old_edge_id = self.update_edge(a, b, weight);
476 assert!(old_edge_id.is_none());
477 }
478
479 pub fn add_or_update_edge(
490 &mut self,
491 a: NodeIndex<Ix>,
492 b: NodeIndex<Ix>,
493 weight: E,
494 ) -> Result<Option<E>, MatrixError> {
495 self.extend_capacity_for_edge(a, b);
496 self.try_update_edge(a, b, weight)
497 }
498
499 #[track_caller]
504 pub fn remove_edge(&mut self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> E {
505 let p = self
506 .to_edge_position(a, b)
507 .expect("No edge found between the nodes.");
508 let old_weight = mem::take(&mut self.node_adjacencies[p]).into().unwrap();
509 let old_weight: Option<_> = old_weight.into();
510 self.nb_edges -= 1;
511 old_weight.unwrap()
512 }
513
514 pub fn try_remove_edge(&mut self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> Option<E> {
518 let p = self.to_edge_position(a, b)?;
519 if let Some(entry) = self.node_adjacencies.get_mut(p) {
520 let old_weight = mem::take(entry).into()?;
521 self.nb_edges -= 1;
522 return Some(old_weight);
523 }
524 None
525 }
526
527 #[track_caller]
532 pub fn has_edge(&self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> bool {
533 if let Some(p) = self.to_edge_position(a, b) {
534 return self
535 .node_adjacencies
536 .get(p)
537 .map(|e| !e.is_null())
538 .unwrap_or(false);
539 }
540 false
541 }
542
543 #[track_caller]
549 pub fn node_weight(&self, a: NodeIndex<Ix>) -> &N {
550 &self.nodes[a.index()]
551 }
552
553 pub fn get_node_weight(&self, a: NodeIndex<Ix>) -> Option<&N> {
557 self.nodes.elements.get(a.index())?.as_ref()
558 }
559
560 #[track_caller]
566 pub fn node_weight_mut(&mut self, a: NodeIndex<Ix>) -> &mut N {
567 &mut self.nodes[a.index()]
568 }
569
570 pub fn get_node_weight_mut(&mut self, a: NodeIndex<Ix>) -> Option<&mut N> {
574 self.nodes.elements.get_mut(a.index())?.as_mut()
575 }
576
577 #[track_caller]
583 pub fn edge_weight(&self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> &E {
584 let p = self
585 .to_edge_position(a, b)
586 .expect("No edge found between the nodes.");
587 self.node_adjacencies[p]
588 .as_ref()
589 .expect("No edge found between the nodes.")
590 }
591
592 pub fn get_edge_weight(&self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> Option<&E> {
596 let p = self.to_edge_position(a, b)?;
597 self.node_adjacencies.get(p)?.as_ref()
598 }
599
600 #[track_caller]
606 pub fn edge_weight_mut(&mut self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> &mut E {
607 let p = self
608 .to_edge_position(a, b)
609 .expect("No edge found between the nodes.");
610 self.node_adjacencies[p]
611 .as_mut()
612 .expect("No edge found between the nodes.")
613 }
614
615 pub fn get_edge_weight_mut(&mut self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> Option<&mut E> {
619 let p = self.to_edge_position(a, b)?;
620 self.node_adjacencies.get_mut(p)?.as_mut()
621 }
622
623 pub fn neighbors(&self, a: NodeIndex<Ix>) -> Neighbors<Ty, Null, Ix> {
631 Neighbors(Edges::on_columns(
632 a.index(),
633 &self.node_adjacencies,
634 self.node_capacity,
635 ))
636 }
637
638 pub fn edges(&self, a: NodeIndex<Ix>) -> Edges<Ty, Null, Ix> {
646 Edges::on_columns(a.index(), &self.node_adjacencies, self.node_capacity)
647 }
648
649 pub fn from_edges<I>(iterable: I) -> Self
667 where
668 I: IntoIterator,
669 I::Item: IntoWeightedEdge<E>,
670 <I::Item as IntoWeightedEdge<E>>::NodeId: Into<NodeIndex<Ix>>,
671 N: Default,
672 S: Default,
673 {
674 let mut g = Self::default();
675 g.extend_with_edges(iterable);
676 g
677 }
678
679 pub fn extend_with_edges<I>(&mut self, iterable: I)
687 where
688 I: IntoIterator,
689 I::Item: IntoWeightedEdge<E>,
690 <I::Item as IntoWeightedEdge<E>>::NodeId: Into<NodeIndex<Ix>>,
691 N: Default,
692 {
693 for elt in iterable {
694 let (source, target, weight) = elt.into_weighted_edge();
695 let (source, target) = (source.into(), target.into());
696 let nx = cmp::max(source, target);
697 while nx.index() >= self.node_count() {
698 self.add_node(N::default());
699 }
700 self.add_edge(source, target, weight);
701 }
702 }
703
704 fn assert_node_bounds(&self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> Result<(), MatrixError> {
705 if a.index() >= self.node_capacity {
706 Err(MatrixError::NodeMissed(a.index()))
707 } else if b.index() >= self.node_capacity {
708 Err(MatrixError::NodeMissed(b.index()))
709 } else {
710 Ok(())
711 }
712 }
713}
714
715impl<N, E, S: BuildHasher, Null: Nullable<Wrapped = E>, Ix: IndexType>
716 MatrixGraph<N, E, S, Directed, Null, Ix>
717{
718 pub fn neighbors_directed(
728 &self,
729 a: NodeIndex<Ix>,
730 d: Direction,
731 ) -> Neighbors<Directed, Null, Ix> {
732 if d == Outgoing {
733 self.neighbors(a)
734 } else {
735 Neighbors(Edges::on_rows(
736 a.index(),
737 &self.node_adjacencies,
738 self.node_capacity,
739 ))
740 }
741 }
742
743 pub fn edges_directed(&self, a: NodeIndex<Ix>, d: Direction) -> Edges<Directed, Null, Ix> {
751 if d == Outgoing {
752 self.edges(a)
753 } else {
754 Edges::on_rows(a.index(), &self.node_adjacencies, self.node_capacity)
755 }
756 }
757}
758
759#[derive(Debug, Clone)]
766pub struct NodeIdentifiers<
767 'a,
768 Ix,
769 #[cfg(feature = "std")] S = RandomState,
770 #[cfg(not(feature = "std"))] S,
771> {
772 iter: IdIterator<'a, S>,
773 ix: PhantomData<Ix>,
774}
775
776impl<'a, Ix: IndexType, S> NodeIdentifiers<'a, Ix, S> {
777 fn new(iter: IdIterator<'a, S>) -> Self {
778 Self {
779 iter,
780 ix: PhantomData,
781 }
782 }
783}
784
785impl<Ix: IndexType, S: BuildHasher> Iterator for NodeIdentifiers<'_, Ix, S> {
786 type Item = NodeIndex<Ix>;
787
788 fn next(&mut self) -> Option<Self::Item> {
789 self.iter.next().map(NodeIndex::new)
790 }
791 fn size_hint(&self) -> (usize, Option<usize>) {
792 self.iter.size_hint()
793 }
794}
795
796#[derive(Debug, Clone)]
803pub struct NodeReferences<
804 'a,
805 N: 'a,
806 Ix,
807 #[cfg(feature = "std")] S = RandomState,
808 #[cfg(not(feature = "std"))] S,
809> {
810 nodes: &'a IdStorage<N, S>,
811 iter: IdIterator<'a, S>,
812 ix: PhantomData<Ix>,
813}
814
815impl<'a, N: 'a, Ix, S: BuildHasher> NodeReferences<'a, N, Ix, S> {
816 fn new(nodes: &'a IdStorage<N, S>) -> Self {
817 NodeReferences {
818 nodes,
819 iter: nodes.iter_ids(),
820 ix: PhantomData,
821 }
822 }
823}
824
825impl<'a, N: 'a, Ix: IndexType, S: BuildHasher> Iterator for NodeReferences<'a, N, Ix, S> {
826 type Item = (NodeIndex<Ix>, &'a N);
827
828 fn next(&mut self) -> Option<Self::Item> {
829 self.iter
830 .next()
831 .map(|i| (NodeIndex::new(i), &self.nodes[i]))
832 }
833 fn size_hint(&self) -> (usize, Option<usize>) {
834 self.iter.size_hint()
835 }
836}
837
838#[derive(Debug, Clone)]
845pub struct EdgeReferences<'a, Ty: EdgeType, Null: 'a + Nullable, Ix> {
846 row: usize,
847 column: usize,
848 node_adjacencies: &'a [Null],
849 node_capacity: usize,
850 ty: PhantomData<Ty>,
851 ix: PhantomData<Ix>,
852}
853
854impl<'a, Ty: EdgeType, Null: 'a + Nullable, Ix> EdgeReferences<'a, Ty, Null, Ix> {
855 fn new(node_adjacencies: &'a [Null], node_capacity: usize) -> Self {
856 EdgeReferences {
857 row: 0,
858 column: 0,
859 node_adjacencies,
860 node_capacity,
861 ty: PhantomData,
862 ix: PhantomData,
863 }
864 }
865}
866
867impl<'a, Ty: EdgeType, Null: Nullable, Ix: IndexType> Iterator
868 for EdgeReferences<'a, Ty, Null, Ix>
869{
870 type Item = (NodeIndex<Ix>, NodeIndex<Ix>, &'a Null::Wrapped);
871
872 fn next(&mut self) -> Option<Self::Item> {
873 loop {
874 let (row, column) = (self.row, self.column);
875 if row >= self.node_capacity {
876 return None;
877 }
878
879 self.column += 1;
884 let max_column_len = if !Ty::is_directed() {
885 row + 1
886 } else {
887 self.node_capacity
888 };
889 if self.column >= max_column_len {
890 self.column = 0;
891 self.row += 1;
892 }
893
894 let p = to_linearized_matrix_position::<Ty>(row, column, self.node_capacity);
895 if let Some(e) = self.node_adjacencies[p].as_ref() {
896 return Some((NodeIndex::new(row), NodeIndex::new(column), e));
897 }
898 }
899 }
900}
901
902#[derive(Debug, Clone)]
911pub struct Neighbors<'a, Ty: EdgeType, Null: 'a + Nullable, Ix>(Edges<'a, Ty, Null, Ix>);
912
913impl<Ty: EdgeType, Null: Nullable, Ix: IndexType> Iterator for Neighbors<'_, Ty, Null, Ix> {
914 type Item = NodeIndex<Ix>;
915
916 fn next(&mut self) -> Option<Self::Item> {
917 self.0.next().map(|(_, b, _)| b)
918 }
919 fn size_hint(&self) -> (usize, Option<usize>) {
920 self.0.size_hint()
921 }
922}
923
924#[derive(Debug, Clone, Copy, PartialEq, Eq)]
925enum NeighborIterDirection {
926 Rows,
927 Columns,
928}
929
930#[derive(Debug, Clone)]
937pub struct Edges<'a, Ty: EdgeType, Null: 'a + Nullable, Ix> {
938 iter_direction: NeighborIterDirection,
939 node_adjacencies: &'a [Null],
940 node_capacity: usize,
941 row: usize,
942 column: usize,
943 ty: PhantomData<Ty>,
944 ix: PhantomData<Ix>,
945}
946
947impl<'a, Ty: EdgeType, Null: 'a + Nullable, Ix> Edges<'a, Ty, Null, Ix> {
948 fn on_columns(row: usize, node_adjacencies: &'a [Null], node_capacity: usize) -> Self {
949 Edges {
950 iter_direction: NeighborIterDirection::Columns,
951 node_adjacencies,
952 node_capacity,
953 row,
954 column: 0,
955 ty: PhantomData,
956 ix: PhantomData,
957 }
958 }
959
960 fn on_rows(column: usize, node_adjacencies: &'a [Null], node_capacity: usize) -> Self {
961 Edges {
962 iter_direction: NeighborIterDirection::Rows,
963 node_adjacencies,
964 node_capacity,
965 row: 0,
966 column,
967 ty: PhantomData,
968 ix: PhantomData,
969 }
970 }
971}
972
973impl<'a, Ty: EdgeType, Null: Nullable, Ix: IndexType> Iterator for Edges<'a, Ty, Null, Ix> {
974 type Item = (NodeIndex<Ix>, NodeIndex<Ix>, &'a Null::Wrapped);
975
976 fn next(&mut self) -> Option<Self::Item> {
977 use self::NeighborIterDirection::*;
978
979 loop {
980 let (row, column) = (self.row, self.column);
981 if row >= self.node_capacity || column >= self.node_capacity {
982 return None;
983 }
984
985 match self.iter_direction {
986 Rows => self.row += 1,
987 Columns => self.column += 1,
988 }
989
990 let p = to_linearized_matrix_position::<Ty>(row, column, self.node_capacity);
991 if let Some(e) = self.node_adjacencies[p].as_ref() {
992 let (a, b) = match self.iter_direction {
993 Rows => (column, row),
994 Columns => (row, column),
995 };
996
997 return Some((NodeIndex::new(a), NodeIndex::new(b), e));
998 }
999 }
1000 }
1001}
1002
1003#[inline]
1004fn to_linearized_matrix_position<Ty: EdgeType>(row: usize, column: usize, width: usize) -> usize {
1005 if Ty::is_directed() {
1006 to_flat_square_matrix_position(row, column, width)
1007 } else {
1008 to_lower_triangular_matrix_position(row, column)
1009 }
1010}
1011
1012#[inline]
1013fn extend_linearized_matrix<Ty: EdgeType, T: Default>(
1014 node_adjacencies: &mut Vec<T>,
1015 old_node_capacity: usize,
1016 new_capacity: usize,
1017 exact: bool,
1018) -> usize {
1019 if old_node_capacity >= new_capacity {
1020 return old_node_capacity;
1021 }
1022 if Ty::is_directed() {
1023 extend_flat_square_matrix(node_adjacencies, old_node_capacity, new_capacity, exact)
1024 } else {
1025 extend_lower_triangular_matrix(node_adjacencies, new_capacity)
1026 }
1027}
1028
1029#[inline]
1030fn to_flat_square_matrix_position(row: usize, column: usize, width: usize) -> usize {
1031 row * width + column
1032}
1033
1034#[inline]
1035fn extend_flat_square_matrix<T: Default>(
1036 node_adjacencies: &mut Vec<T>,
1037 old_node_capacity: usize,
1038 new_node_capacity: usize,
1039 exact: bool,
1040) -> usize {
1041 let new_node_capacity = if exact {
1044 new_node_capacity
1045 } else {
1046 const MIN_CAPACITY: usize = 4;
1047 cmp::max(new_node_capacity.next_power_of_two(), MIN_CAPACITY)
1048 };
1049
1050 ensure_len(node_adjacencies, new_node_capacity.pow(2));
1054 for c in (1..old_node_capacity).rev() {
1055 let pos = c * old_node_capacity;
1056 let new_pos = c * new_node_capacity;
1057 if pos + old_node_capacity <= new_pos {
1059 debug_assert!(pos + old_node_capacity < node_adjacencies.len());
1060 debug_assert!(new_pos + old_node_capacity < node_adjacencies.len());
1061 let ptr = node_adjacencies.as_mut_ptr();
1062 unsafe {
1064 let old = ptr.add(pos);
1065 let new = ptr.add(new_pos);
1066 core::ptr::swap_nonoverlapping(old, new, old_node_capacity);
1067 }
1068 } else {
1069 for i in (0..old_node_capacity).rev() {
1070 node_adjacencies.as_mut_slice().swap(pos + i, new_pos + i);
1071 }
1072 }
1073 }
1074
1075 new_node_capacity
1076}
1077
1078#[inline]
1079fn to_lower_triangular_matrix_position(row: usize, column: usize) -> usize {
1080 let (row, column) = if row > column {
1081 (row, column)
1082 } else {
1083 (column, row)
1084 };
1085 (row * (row + 1)) / 2 + column
1086}
1087
1088#[inline]
1089fn extend_lower_triangular_matrix<T: Default>(
1090 node_adjacencies: &mut Vec<T>,
1091 new_capacity: usize,
1092) -> usize {
1093 let max_node = new_capacity - 1;
1094 let max_pos = to_lower_triangular_matrix_position(max_node, max_node);
1095 ensure_len(node_adjacencies, max_pos + 1);
1096 new_capacity
1097}
1098
1099fn ensure_len<T: Default>(v: &mut Vec<T>, size: usize) {
1101 v.resize_with(size, T::default);
1102}
1103
1104#[derive(Debug, Clone)]
1105struct IdStorage<T, #[cfg(feature = "std")] S = RandomState, #[cfg(not(feature = "std"))] S> {
1106 elements: Vec<Option<T>>,
1107 upper_bound: usize,
1108 removed_ids: IndexSet<usize, S>,
1109}
1110
1111impl<T, S: BuildHasher> IdStorage<T, S> {
1112 fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self {
1113 IdStorage {
1114 elements: Vec::with_capacity(capacity),
1115 upper_bound: 0,
1116 removed_ids: IndexSet::with_hasher(hasher),
1117 }
1118 }
1119
1120 fn add(&mut self, element: T) -> usize {
1121 let id = if let Some(id) = self.removed_ids.pop() {
1122 id
1123 } else {
1124 let id = self.upper_bound;
1125 self.upper_bound += 1;
1126
1127 ensure_len(&mut self.elements, id + 1);
1128
1129 id
1130 };
1131
1132 self.elements[id] = Some(element);
1133
1134 id
1135 }
1136
1137 fn remove(&mut self, id: usize) -> T {
1138 let data = self.elements[id].take().unwrap();
1139 if self.upper_bound - id == 1 {
1140 self.upper_bound -= 1;
1141 } else {
1142 self.removed_ids.insert(id);
1143 }
1144 data
1145 }
1146
1147 fn clear(&mut self) {
1148 self.upper_bound = 0;
1149 self.elements.clear();
1150 self.removed_ids.clear();
1151 }
1152
1153 #[inline]
1154 fn len(&self) -> usize {
1155 self.upper_bound - self.removed_ids.len()
1156 }
1157
1158 fn iter_ids(&self) -> IdIterator<S> {
1159 IdIterator {
1160 upper_bound: self.upper_bound,
1161 removed_ids: &self.removed_ids,
1162 current: None,
1163 }
1164 }
1165}
1166
1167impl<T, S> Index<usize> for IdStorage<T, S> {
1168 type Output = T;
1169 fn index(&self, index: usize) -> &T {
1170 self.elements[index].as_ref().unwrap()
1171 }
1172}
1173
1174impl<T, S> IndexMut<usize> for IdStorage<T, S> {
1175 fn index_mut(&mut self, index: usize) -> &mut T {
1176 self.elements[index].as_mut().unwrap()
1177 }
1178}
1179
1180#[derive(Debug, Clone)]
1181struct IdIterator<'a, S> {
1182 upper_bound: usize,
1183 removed_ids: &'a IndexSet<usize, S>,
1184 current: Option<usize>,
1185}
1186
1187impl<S: BuildHasher> Iterator for IdIterator<'_, S> {
1188 type Item = usize;
1189
1190 fn next(&mut self) -> Option<Self::Item> {
1191 let current = {
1193 if self.current.is_none() {
1194 self.current = Some(0);
1195 self.current.as_mut().unwrap()
1196 } else {
1197 let current = self.current.as_mut().unwrap();
1198 *current += 1;
1199 current
1200 }
1201 };
1202
1203 while self.removed_ids.contains(current) && *current < self.upper_bound {
1205 *current += 1;
1206 }
1207
1208 if *current < self.upper_bound {
1209 Some(*current)
1210 } else {
1211 None
1212 }
1213 }
1214}
1215
1216impl<N, E, S: BuildHasher + Default, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType>
1218 Default for MatrixGraph<N, E, S, Ty, Null, Ix>
1219{
1220 fn default() -> Self {
1221 Self::with_capacity(0)
1222 }
1223}
1224
1225impl<N, E, S: BuildHasher + Default> MatrixGraph<N, E, S, Directed> {
1226 pub fn new() -> Self {
1231 MatrixGraph::default()
1232 }
1233}
1234
1235impl<N, E, S: BuildHasher + Default> MatrixGraph<N, E, S, Undirected> {
1236 pub fn new_undirected() -> Self {
1241 MatrixGraph::default()
1242 }
1243}
1244
1245impl<N, E, S: BuildHasher, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType>
1249 Index<NodeIndex<Ix>> for MatrixGraph<N, E, S, Ty, Null, Ix>
1250{
1251 type Output = N;
1252
1253 fn index(&self, ax: NodeIndex<Ix>) -> &N {
1254 self.node_weight(ax)
1255 }
1256}
1257
1258impl<N, E, S: BuildHasher, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType>
1262 IndexMut<NodeIndex<Ix>> for MatrixGraph<N, E, S, Ty, Null, Ix>
1263{
1264 fn index_mut(&mut self, ax: NodeIndex<Ix>) -> &mut N {
1265 self.node_weight_mut(ax)
1266 }
1267}
1268
1269impl<N, E, S: BuildHasher, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> NodeCount
1270 for MatrixGraph<N, E, S, Ty, Null, Ix>
1271{
1272 fn node_count(&self) -> usize {
1273 MatrixGraph::node_count(self)
1274 }
1275}
1276
1277impl<N, E, S: BuildHasher, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> EdgeCount
1278 for MatrixGraph<N, E, S, Ty, Null, Ix>
1279{
1280 #[inline]
1281 fn edge_count(&self) -> usize {
1282 self.edge_count()
1283 }
1284}
1285
1286impl<N, E, S: BuildHasher, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType>
1292 Index<(NodeIndex<Ix>, NodeIndex<Ix>)> for MatrixGraph<N, E, S, Ty, Null, Ix>
1293{
1294 type Output = E;
1295
1296 fn index(&self, (ax, bx): (NodeIndex<Ix>, NodeIndex<Ix>)) -> &E {
1297 self.edge_weight(ax, bx)
1298 }
1299}
1300
1301impl<N, E, S: BuildHasher, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType>
1307 IndexMut<(NodeIndex<Ix>, NodeIndex<Ix>)> for MatrixGraph<N, E, S, Ty, Null, Ix>
1308{
1309 fn index_mut(&mut self, (ax, bx): (NodeIndex<Ix>, NodeIndex<Ix>)) -> &mut E {
1310 self.edge_weight_mut(ax, bx)
1311 }
1312}
1313
1314impl<N, E, S: BuildHasher, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType>
1315 GetAdjacencyMatrix for MatrixGraph<N, E, S, Ty, Null, Ix>
1316{
1317 type AdjMatrix = ();
1318
1319 fn adjacency_matrix(&self) -> Self::AdjMatrix {}
1320
1321 fn is_adjacent(&self, _: &Self::AdjMatrix, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> bool {
1322 MatrixGraph::has_edge(self, a, b)
1323 }
1324}
1325
1326impl<N, E, S, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> Visitable
1327 for MatrixGraph<N, E, S, Ty, Null, Ix>
1328{
1329 type Map = FixedBitSet;
1330
1331 fn visit_map(&self) -> FixedBitSet {
1332 FixedBitSet::with_capacity(self.node_bound())
1333 }
1334
1335 fn reset_map(&self, map: &mut Self::Map) {
1336 map.clear();
1337 map.grow(self.node_bound());
1338 }
1339}
1340
1341impl<N, E, S, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> GraphBase
1342 for MatrixGraph<N, E, S, Ty, Null, Ix>
1343{
1344 type NodeId = NodeIndex<Ix>;
1345 type EdgeId = (NodeIndex<Ix>, NodeIndex<Ix>);
1346}
1347
1348impl<N, E, S, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> GraphProp
1349 for MatrixGraph<N, E, S, Ty, Null, Ix>
1350{
1351 type EdgeType = Ty;
1352}
1353
1354impl<N, E, S, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> Data
1355 for MatrixGraph<N, E, S, Ty, Null, Ix>
1356{
1357 type NodeWeight = N;
1358 type EdgeWeight = E;
1359}
1360
1361impl<'a, N, E: 'a, S: BuildHasher, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType>
1362 IntoNodeIdentifiers for &'a MatrixGraph<N, E, S, Ty, Null, Ix>
1363{
1364 type NodeIdentifiers = NodeIdentifiers<'a, Ix, S>;
1365
1366 fn node_identifiers(self) -> Self::NodeIdentifiers {
1367 NodeIdentifiers::new(self.nodes.iter_ids())
1368 }
1369}
1370
1371impl<'a, N, E: 'a, S: BuildHasher, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType>
1372 IntoNeighbors for &'a MatrixGraph<N, E, S, Ty, Null, Ix>
1373{
1374 type Neighbors = Neighbors<'a, Ty, Null, Ix>;
1375
1376 fn neighbors(self, a: NodeIndex<Ix>) -> Self::Neighbors {
1377 MatrixGraph::neighbors(self, a)
1378 }
1379}
1380
1381impl<'a, N, E: 'a, S: BuildHasher, Null: Nullable<Wrapped = E>, Ix: IndexType> IntoNeighborsDirected
1382 for &'a MatrixGraph<N, E, S, Directed, Null, Ix>
1383{
1384 type NeighborsDirected = Neighbors<'a, Directed, Null, Ix>;
1385
1386 fn neighbors_directed(self, a: NodeIndex<Ix>, d: Direction) -> Self::NeighborsDirected {
1387 MatrixGraph::neighbors_directed(self, a, d)
1388 }
1389}
1390
1391impl<'a, N, E, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType, S: BuildHasher + 'a>
1392 IntoNodeReferences for &'a MatrixGraph<N, E, S, Ty, Null, Ix>
1393{
1394 type NodeRef = (NodeIndex<Ix>, &'a N);
1395 type NodeReferences = NodeReferences<'a, N, Ix, S>;
1396 fn node_references(self) -> Self::NodeReferences {
1397 NodeReferences::new(&self.nodes)
1398 }
1399}
1400
1401impl<'a, N, E, S, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> IntoEdgeReferences
1402 for &'a MatrixGraph<N, E, S, Ty, Null, Ix>
1403{
1404 type EdgeRef = (NodeIndex<Ix>, NodeIndex<Ix>, &'a E);
1405 type EdgeReferences = EdgeReferences<'a, Ty, Null, Ix>;
1406 fn edge_references(self) -> Self::EdgeReferences {
1407 EdgeReferences::new(&self.node_adjacencies, self.node_capacity)
1408 }
1409}
1410
1411impl<'a, N, E, S: BuildHasher, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> IntoEdges
1412 for &'a MatrixGraph<N, E, S, Ty, Null, Ix>
1413{
1414 type Edges = Edges<'a, Ty, Null, Ix>;
1415 fn edges(self, a: Self::NodeId) -> Self::Edges {
1416 MatrixGraph::edges(self, a)
1417 }
1418}
1419
1420impl<'a, N, E, S: BuildHasher, Null: Nullable<Wrapped = E>, Ix: IndexType> IntoEdgesDirected
1421 for &'a MatrixGraph<N, E, S, Directed, Null, Ix>
1422{
1423 type EdgesDirected = Edges<'a, Directed, Null, Ix>;
1424
1425 fn edges_directed(self, a: Self::NodeId, dir: Direction) -> Self::EdgesDirected {
1426 MatrixGraph::edges_directed(self, a, dir)
1427 }
1428}
1429
1430impl<N, E, S, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> NodeIndexable
1431 for MatrixGraph<N, E, S, Ty, Null, Ix>
1432{
1433 fn node_bound(&self) -> usize {
1434 self.nodes.upper_bound
1435 }
1436
1437 fn to_index(&self, ix: NodeIndex<Ix>) -> usize {
1438 ix.index()
1439 }
1440
1441 fn from_index(&self, ix: usize) -> Self::NodeId {
1442 NodeIndex::new(ix)
1443 }
1444}
1445
1446impl<N, E, S: BuildHasher, Ty: EdgeType, Null: Nullable<Wrapped = E>, Ix: IndexType> Build
1447 for MatrixGraph<N, E, S, Ty, Null, Ix>
1448{
1449 fn add_node(&mut self, weight: Self::NodeWeight) -> Self::NodeId {
1450 self.add_node(weight)
1451 }
1452
1453 fn add_edge(
1454 &mut self,
1455 a: Self::NodeId,
1456 b: Self::NodeId,
1457 weight: Self::EdgeWeight,
1458 ) -> Option<Self::EdgeId> {
1459 if !self.has_edge(a, b) {
1460 MatrixGraph::update_edge(self, a, b, weight);
1461 Some((a, b))
1462 } else {
1463 None
1464 }
1465 }
1466
1467 fn update_edge(
1468 &mut self,
1469 a: Self::NodeId,
1470 b: Self::NodeId,
1471 weight: Self::EdgeWeight,
1472 ) -> Self::EdgeId {
1473 MatrixGraph::update_edge(self, a, b, weight);
1474 (a, b)
1475 }
1476}
1477
1478#[cfg(test)]
1479mod tests {
1480 use super::*;
1481 use crate::{Incoming, Outgoing};
1482 use std::collections::hash_map::RandomState;
1483
1484 #[test]
1485 fn test_new() {
1486 let g = MatrixGraph::<i32, i32>::new();
1487 assert_eq!(g.node_count(), 0);
1488 assert_eq!(g.edge_count(), 0);
1489 }
1490
1491 #[test]
1492 fn test_default() {
1493 let g = MatrixGraph::<i32, i32>::default();
1494 assert_eq!(g.node_count(), 0);
1495 assert_eq!(g.edge_count(), 0);
1496 }
1497
1498 #[test]
1499 fn test_with_capacity() {
1500 let g = MatrixGraph::<i32, i32>::with_capacity(10);
1501 assert_eq!(g.node_count(), 0);
1502 assert_eq!(g.edge_count(), 0);
1503 }
1504
1505 #[test]
1506 fn test_node_indexing() {
1507 let mut g: MatrixGraph<char, ()> = MatrixGraph::new();
1508 let a = g.add_node('a');
1509 let b = g.add_node('b');
1510 assert_eq!(g.node_count(), 2);
1511 assert_eq!(g.edge_count(), 0);
1512 assert_eq!(g[a], 'a');
1513 assert_eq!(g[b], 'b');
1514 }
1515
1516 #[test]
1517 fn test_remove_node() {
1518 let mut g: MatrixGraph<char, ()> = MatrixGraph::new();
1519 let a = g.add_node('a');
1520
1521 g.remove_node(a);
1522
1523 assert_eq!(g.node_count(), 0);
1524 assert_eq!(g.edge_count(), 0);
1525 }
1526
1527 #[test]
1528 fn test_add_edge() {
1529 let mut g = MatrixGraph::<_, _, RandomState>::new();
1530 let a = g.add_node('a');
1531 let b = g.add_node('b');
1532 let c = g.add_node('c');
1533 g.add_edge(a, b, ());
1534 g.add_edge(b, c, ());
1535 assert_eq!(g.node_count(), 3);
1536 assert_eq!(g.edge_count(), 2);
1537 }
1538
1539 #[test]
1540 fn test_add_edge_with_extension() {
1543 let mut g = DiMatrix::<u8, ()>::new();
1544 let _n0 = g.add_node(0);
1545 let n1 = g.add_node(1);
1546 let n2 = g.add_node(2);
1547 let n3 = g.add_node(3);
1548 let n4 = g.add_node(4);
1549 let _n5 = g.add_node(5);
1550 g.add_edge(n2, n1, ());
1551 g.add_edge(n2, n3, ());
1552 g.add_edge(n2, n4, ());
1553 assert_eq!(g.node_count(), 6);
1554 assert_eq!(g.edge_count(), 3);
1555 assert!(g.has_edge(n2, n1));
1556 assert!(g.has_edge(n2, n3));
1557 assert!(g.has_edge(n2, n4));
1558 }
1559
1560 #[test]
1561 fn test_has_edge() {
1562 let mut g = MatrixGraph::<_, _, RandomState>::new();
1563 let a = g.add_node('a');
1564 let b = g.add_node('b');
1565 let c = g.add_node('c');
1566 g.add_edge(a, b, ());
1567 g.add_edge(b, c, ());
1568 assert!(g.has_edge(a, b));
1569 assert!(g.has_edge(b, c));
1570 assert!(!g.has_edge(a, c));
1571 assert!(!g.has_edge(10.into(), 100.into())); }
1573
1574 #[test]
1575 fn test_matrix_resize() {
1576 let mut g = DiMatrix::<u8, ()>::with_capacity(3);
1577 let n0 = g.add_node(0);
1578 let n1 = g.add_node(1);
1579 let n2 = g.add_node(2);
1580 let n3 = g.add_node(3);
1581 g.add_edge(n1, n0, ());
1582 g.add_edge(n1, n1, ());
1583 g.add_edge(n2, n3, ());
1585 assert_eq!(g.node_count(), 4);
1586 assert_eq!(g.edge_count(), 3);
1587 assert!(g.has_edge(n1, n0));
1588 assert!(g.has_edge(n1, n1));
1589 assert!(g.has_edge(n2, n3));
1590 }
1591
1592 #[test]
1593 fn test_add_edge_with_weights() {
1594 let mut g = MatrixGraph::<_, _, RandomState>::new();
1595 let a = g.add_node('a');
1596 let b = g.add_node('b');
1597 let c = g.add_node('c');
1598 g.add_edge(a, b, true);
1599 g.add_edge(b, c, false);
1600 assert!(*g.edge_weight(a, b));
1601 assert!(!*g.edge_weight(b, c));
1602 }
1603
1604 #[test]
1605 fn test_add_edge_with_weights_undirected() {
1606 let mut g = MatrixGraph::<_, _, RandomState, Undirected>::new_undirected();
1607 let a = g.add_node('a');
1608 let b = g.add_node('b');
1609 let c = g.add_node('c');
1610 let d = g.add_node('d');
1611 g.add_edge(a, b, "ab");
1612 g.add_edge(a, a, "aa");
1613 g.add_edge(b, c, "bc");
1614 g.add_edge(d, d, "dd");
1615 assert_eq!(*g.edge_weight(a, b), "ab");
1616 assert_eq!(*g.edge_weight(b, c), "bc");
1617 }
1618
1619 trait IntoVec<T> {
1621 fn into_vec(self) -> Vec<T>;
1622 }
1623
1624 impl<It, T> IntoVec<T> for It
1625 where
1626 It: Iterator<Item = T>,
1627 {
1628 fn into_vec(self) -> Vec<T> {
1629 self.collect()
1630 }
1631 }
1632
1633 #[test]
1634 fn test_clear() {
1635 let mut g = MatrixGraph::<_, _, RandomState>::new();
1636 let a = g.add_node('a');
1637 let b = g.add_node('b');
1638 let c = g.add_node('c');
1639 assert_eq!(g.node_count(), 3);
1640
1641 g.add_edge(a, b, ());
1642 g.add_edge(b, c, ());
1643 g.add_edge(c, a, ());
1644 assert_eq!(g.edge_count(), 3);
1645
1646 g.clear();
1647
1648 assert_eq!(g.node_count(), 0);
1649 assert_eq!(g.edge_count(), 0);
1650
1651 let a = g.add_node('a');
1652 let b = g.add_node('b');
1653 let c = g.add_node('c');
1654 assert_eq!(g.node_count(), 3);
1655 assert_eq!(g.edge_count(), 0);
1656
1657 assert_eq!(g.neighbors_directed(a, Incoming).into_vec(), vec![]);
1658 assert_eq!(g.neighbors_directed(b, Incoming).into_vec(), vec![]);
1659 assert_eq!(g.neighbors_directed(c, Incoming).into_vec(), vec![]);
1660
1661 assert_eq!(g.neighbors_directed(a, Outgoing).into_vec(), vec![]);
1662 assert_eq!(g.neighbors_directed(b, Outgoing).into_vec(), vec![]);
1663 assert_eq!(g.neighbors_directed(c, Outgoing).into_vec(), vec![]);
1664 }
1665
1666 #[test]
1667 fn test_clear_undirected() {
1668 let mut g = MatrixGraph::<_, _, RandomState, Undirected>::new_undirected();
1669 let a = g.add_node('a');
1670 let b = g.add_node('b');
1671 let c = g.add_node('c');
1672 assert_eq!(g.node_count(), 3);
1673
1674 g.add_edge(a, b, ());
1675 g.add_edge(b, c, ());
1676 g.add_edge(c, a, ());
1677 assert_eq!(g.edge_count(), 3);
1678
1679 g.clear();
1680
1681 assert_eq!(g.node_count(), 0);
1682 assert_eq!(g.edge_count(), 0);
1683
1684 let a = g.add_node('a');
1685 let b = g.add_node('b');
1686 let c = g.add_node('c');
1687 assert_eq!(g.node_count(), 3);
1688 assert_eq!(g.edge_count(), 0);
1689
1690 assert_eq!(g.neighbors(a).into_vec(), vec![]);
1691 assert_eq!(g.neighbors(b).into_vec(), vec![]);
1692 assert_eq!(g.neighbors(c).into_vec(), vec![]);
1693 }
1694
1695 trait IntoSortedVec<T> {
1697 fn into_sorted_vec(self) -> Vec<T>;
1698 }
1699
1700 impl<It, T> IntoSortedVec<T> for It
1701 where
1702 It: Iterator<Item = T>,
1703 T: Ord,
1704 {
1705 fn into_sorted_vec(self) -> Vec<T> {
1706 let mut v: Vec<T> = self.collect();
1707 v.sort();
1708 v
1709 }
1710 }
1711
1712 macro_rules! sorted_vec {
1714 ($($x:expr),*) => {
1715 {
1716 let mut v = vec![$($x,)*];
1717 v.sort();
1718 v
1719 }
1720 }
1721 }
1722
1723 #[test]
1724 fn test_neighbors() {
1725 let mut g = MatrixGraph::<_, _, RandomState>::new();
1726 let a = g.add_node('a');
1727 let b = g.add_node('b');
1728 let c = g.add_node('c');
1729 g.add_edge(a, b, ());
1730 g.add_edge(a, c, ());
1731
1732 let a_neighbors = g.neighbors(a).into_sorted_vec();
1733 assert_eq!(a_neighbors, sorted_vec![b, c]);
1734
1735 let b_neighbors = g.neighbors(b).into_sorted_vec();
1736 assert_eq!(b_neighbors, vec![]);
1737
1738 let c_neighbors = g.neighbors(c).into_sorted_vec();
1739 assert_eq!(c_neighbors, vec![]);
1740 }
1741
1742 #[test]
1743 fn test_neighbors_undirected() {
1744 let mut g = MatrixGraph::<_, _, RandomState, Undirected>::new_undirected();
1745 let a = g.add_node('a');
1746 let b = g.add_node('b');
1747 let c = g.add_node('c');
1748 g.add_edge(a, b, ());
1749 g.add_edge(a, c, ());
1750
1751 let a_neighbors = g.neighbors(a).into_sorted_vec();
1752 assert_eq!(a_neighbors, sorted_vec![b, c]);
1753
1754 let b_neighbors = g.neighbors(b).into_sorted_vec();
1755 assert_eq!(b_neighbors, sorted_vec![a]);
1756
1757 let c_neighbors = g.neighbors(c).into_sorted_vec();
1758 assert_eq!(c_neighbors, sorted_vec![a]);
1759 }
1760
1761 #[test]
1762 fn test_remove_node_and_edges() {
1763 let mut g = MatrixGraph::<_, _>::new();
1764 let a = g.add_node('a');
1765 let b = g.add_node('b');
1766 let c = g.add_node('c');
1767 g.add_edge(a, b, ());
1768 g.add_edge(b, c, ());
1769 g.add_edge(c, a, ());
1770
1771 g.remove_node(b);
1773
1774 assert_eq!(g.node_count(), 2);
1775
1776 let a_neighbors = g.neighbors(a).into_sorted_vec();
1777 assert_eq!(a_neighbors, vec![]);
1778
1779 let c_neighbors = g.neighbors(c).into_sorted_vec();
1780 assert_eq!(c_neighbors, vec![a]);
1781 }
1782
1783 #[test]
1784 fn test_remove_node_and_edges_undirected() {
1785 let mut g = UnMatrix::<_, _>::new_undirected();
1786 let a = g.add_node('a');
1787 let b = g.add_node('b');
1788 let c = g.add_node('c');
1789 g.add_edge(a, b, ());
1790 g.add_edge(b, c, ());
1791 g.add_edge(c, a, ());
1792
1793 g.remove_node(a);
1795
1796 assert_eq!(g.node_count(), 2);
1797
1798 let b_neighbors = g.neighbors(b).into_sorted_vec();
1799 assert_eq!(b_neighbors, vec![c]);
1800
1801 let c_neighbors = g.neighbors(c).into_sorted_vec();
1802 assert_eq!(c_neighbors, vec![b]);
1803 }
1804
1805 #[test]
1806 fn test_node_identifiers() {
1807 let mut g = MatrixGraph::<_, _>::new();
1808 let a = g.add_node('a');
1809 let b = g.add_node('b');
1810 let c = g.add_node('c');
1811 let d = g.add_node('c');
1812 g.add_edge(a, b, ());
1813 g.add_edge(a, c, ());
1814
1815 let node_ids = g.node_identifiers().into_sorted_vec();
1816 assert_eq!(node_ids, sorted_vec![a, b, c, d]);
1817 }
1818
1819 #[test]
1820 fn test_edges_directed() {
1821 let g: MatrixGraph<char, bool> = MatrixGraph::from_edges([
1822 (0, 5),
1823 (0, 2),
1824 (0, 3),
1825 (0, 1),
1826 (1, 3),
1827 (2, 3),
1828 (2, 4),
1829 (4, 0),
1830 (6, 6),
1831 ]);
1832
1833 assert_eq!(g.edges_directed(node_index(0), Outgoing).count(), 4);
1834 assert_eq!(g.edges_directed(node_index(1), Outgoing).count(), 1);
1835 assert_eq!(g.edges_directed(node_index(2), Outgoing).count(), 2);
1836 assert_eq!(g.edges_directed(node_index(3), Outgoing).count(), 0);
1837 assert_eq!(g.edges_directed(node_index(4), Outgoing).count(), 1);
1838 assert_eq!(g.edges_directed(node_index(5), Outgoing).count(), 0);
1839 assert_eq!(g.edges_directed(node_index(6), Outgoing).count(), 1);
1840
1841 assert_eq!(g.edges_directed(node_index(0), Incoming).count(), 1);
1842 assert_eq!(g.edges_directed(node_index(1), Incoming).count(), 1);
1843 assert_eq!(g.edges_directed(node_index(2), Incoming).count(), 1);
1844 assert_eq!(g.edges_directed(node_index(3), Incoming).count(), 3);
1845 assert_eq!(g.edges_directed(node_index(4), Incoming).count(), 1);
1846 assert_eq!(g.edges_directed(node_index(5), Incoming).count(), 1);
1847 assert_eq!(g.edges_directed(node_index(6), Incoming).count(), 1);
1848 }
1849
1850 #[test]
1851 fn test_edges_undirected() {
1852 let g: UnMatrix<char, bool> = UnMatrix::from_edges([
1853 (0, 5),
1854 (0, 2),
1855 (0, 3),
1856 (0, 1),
1857 (1, 3),
1858 (2, 3),
1859 (2, 4),
1860 (4, 0),
1861 (6, 6),
1862 ]);
1863
1864 assert_eq!(g.edges(node_index(0)).count(), 5);
1865 assert_eq!(g.edges(node_index(1)).count(), 2);
1866 assert_eq!(g.edges(node_index(2)).count(), 3);
1867 assert_eq!(g.edges(node_index(3)).count(), 3);
1868 assert_eq!(g.edges(node_index(4)).count(), 2);
1869 assert_eq!(g.edges(node_index(5)).count(), 1);
1870 assert_eq!(g.edges(node_index(6)).count(), 1);
1871 }
1872
1873 #[test]
1874 fn test_edges_of_absent_node_is_empty_iterator() {
1875 let g: MatrixGraph<char, bool> = MatrixGraph::new();
1876 assert_eq!(g.edges(node_index(0)).count(), 0);
1877 }
1878
1879 #[test]
1880 fn test_neighbors_of_absent_node_is_empty_iterator() {
1881 let g: MatrixGraph<char, bool> = MatrixGraph::new();
1882 assert_eq!(g.neighbors(node_index(0)).count(), 0);
1883 }
1884
1885 #[test]
1886 fn test_edge_references() {
1887 let g: MatrixGraph<char, bool> = MatrixGraph::from_edges([
1888 (0, 5),
1889 (0, 2),
1890 (0, 3),
1891 (0, 1),
1892 (1, 3),
1893 (2, 3),
1894 (2, 4),
1895 (4, 0),
1896 (6, 6),
1897 ]);
1898
1899 assert_eq!(g.edge_references().count(), 9);
1900 }
1901
1902 #[test]
1903 fn test_edge_references_undirected() {
1904 let g: UnMatrix<char, bool> = UnMatrix::from_edges([
1905 (0, 5),
1906 (0, 2),
1907 (0, 3),
1908 (0, 1),
1909 (1, 3),
1910 (2, 3),
1911 (2, 4),
1912 (4, 0),
1913 (6, 6),
1914 ]);
1915
1916 assert_eq!(g.edge_references().count(), 9);
1917 }
1918
1919 #[test]
1920 fn test_id_storage() {
1921 use super::IdStorage;
1922
1923 let mut storage: IdStorage<char> =
1924 IdStorage::with_capacity_and_hasher(0, Default::default());
1925 let a = storage.add('a');
1926 let b = storage.add('b');
1927 let c = storage.add('c');
1928
1929 assert!(a < b && b < c);
1930
1931 assert_eq!(storage.iter_ids().into_vec(), vec![a, b, c]);
1933
1934 storage.remove(b);
1935
1936 let bb = storage.add('B');
1938 assert_eq!(b, bb);
1939
1940 assert_eq!(storage.iter_ids().into_vec(), vec![a, b, c]);
1942 }
1943
1944 #[test]
1945 fn test_not_zero() {
1946 let mut g: MatrixGraph<(), i32, RandomState, Directed, NotZero<i32>> =
1947 MatrixGraph::default();
1948
1949 let a = g.add_node(());
1950 let b = g.add_node(());
1951
1952 assert!(!g.has_edge(a, b));
1953 assert_eq!(g.edge_count(), 0);
1954
1955 g.add_edge(a, b, 12);
1956
1957 assert!(g.has_edge(a, b));
1958 assert_eq!(g.edge_count(), 1);
1959 assert_eq!(g.edge_weight(a, b), &12);
1960
1961 g.remove_edge(a, b);
1962
1963 assert!(!g.has_edge(a, b));
1964 assert_eq!(g.edge_count(), 0);
1965 }
1966
1967 #[test]
1968 #[should_panic]
1969 fn test_not_zero_asserted() {
1970 let mut g: MatrixGraph<(), i32, RandomState, Directed, NotZero<i32>> =
1971 MatrixGraph::default();
1972
1973 let a = g.add_node(());
1974 let b = g.add_node(());
1975
1976 g.add_edge(a, b, 0); }
1978
1979 #[test]
1980 fn test_not_zero_float() {
1981 let mut g: MatrixGraph<(), f32, RandomState, Directed, NotZero<f32>> =
1982 MatrixGraph::default();
1983
1984 let a = g.add_node(());
1985 let b = g.add_node(());
1986
1987 assert!(!g.has_edge(a, b));
1988 assert_eq!(g.edge_count(), 0);
1989
1990 g.add_edge(a, b, 12.);
1991
1992 assert!(g.has_edge(a, b));
1993 assert_eq!(g.edge_count(), 1);
1994 assert_eq!(g.edge_weight(a, b), &12.);
1995
1996 g.remove_edge(a, b);
1997
1998 assert!(!g.has_edge(a, b));
1999 assert_eq!(g.edge_count(), 0);
2000 }
2001 #[test]
2002 fn test_tarjan_scc_with_removed_node() {
2004 let mut g: MatrixGraph<(), ()> = MatrixGraph::new();
2005
2006 g.add_node(());
2007 let b = g.add_node(());
2008 g.add_node(());
2009
2010 g.remove_node(b);
2011
2012 assert_eq!(
2013 crate::algo::tarjan_scc(&g),
2014 [[node_index(0)], [node_index(2)]]
2015 );
2016 }
2017
2018 #[test]
2019 fn test_kosaraju_scc_with_removed_node() {
2021 let mut g: MatrixGraph<(), ()> = MatrixGraph::new();
2022
2023 g.add_node(());
2024 let b = g.add_node(());
2025 g.add_node(());
2026
2027 g.remove_node(b);
2028
2029 assert_eq!(
2030 crate::algo::kosaraju_scc(&g),
2031 [[node_index(2)], [node_index(0)]]
2032 );
2033 }
2034
2035 #[test]
2036 fn test_try_update_edge() {
2037 let mut g = MatrixGraph::<char, u32>::new();
2038 let a = g.add_node('a');
2039 let b = g.add_node('b');
2040 let c = g.add_node('c');
2041 g.add_edge(a, b, 1);
2042 g.add_edge(b, c, 2);
2043 assert_eq!(g.try_update_edge(a, b, 10), Ok(Some(1)));
2044 assert_eq!(g.try_update_edge(a, b, 100), Ok(Some(10)));
2045 assert_eq!(g.try_update_edge(a, c, 33), Ok(None));
2046 assert_eq!(g.try_update_edge(a, c, 66), Ok(Some(33)));
2047 assert_eq!(
2048 g.try_update_edge(10.into(), 20.into(), 5),
2049 Err(MatrixError::NodeMissed(10))
2050 );
2051 }
2052
2053 #[test]
2054 fn test_add_or_update_edge() {
2055 let mut g = MatrixGraph::<char, u32>::new();
2056 let a = g.add_node('a');
2057 let b = g.add_node('b');
2058 let c = g.add_node('c');
2059 assert_eq!(g.add_or_update_edge(a, b, 1), Ok(None));
2060 assert_eq!(g.add_or_update_edge(b, c, 2), Ok(None));
2061 assert_eq!(g.add_or_update_edge(a, b, 10), Ok(Some(1)));
2062 assert_eq!(g.add_or_update_edge(a, c, 33), Ok(None));
2063 assert_eq!(g.add_or_update_edge(10.into(), 20.into(), 5), Ok(None));
2064 assert!(g.has_edge(10.into(), 20.into()));
2065 assert!(g.node_capacity >= 20);
2066 }
2067
2068 #[test]
2069 fn test_remove_edge() {
2070 let mut g = MatrixGraph::<char, u32>::new();
2071 let a = g.add_node('a');
2072 let b = g.add_node('b');
2073 let c = g.add_node('c');
2074 g.add_edge(a, b, 1);
2075 g.add_edge(b, c, 2);
2076 assert_eq!(g.try_remove_edge(a, b), Some(1));
2077 assert_eq!(g.try_remove_edge(a, b), None);
2078 assert_eq!(g.try_remove_edge(a, c), None);
2079 }
2080
2081 #[test]
2082 fn test_try_add_node() {
2083 let mut graph =
2084 MatrixGraph::<(), u32, RandomState, Directed, Option<u32>, u8>::with_capacity(255);
2085 for i in 0..255 {
2086 assert_eq!(graph.try_add_node(()), Ok(i.into()));
2087 }
2088 assert_eq!(graph.try_add_node(()), Err(MatrixError::NodeIxLimit));
2089 }
2090}