1 extern crate itertools; 2 extern crate petgraph; 3 #[macro_use] 4 extern crate defmac; 5 6 use petgraph::adj::DefaultIx; 7 use petgraph::adj::IndexType; 8 use petgraph::adj::{List, UnweightedList}; 9 use petgraph::algo::tarjan_scc; 10 use petgraph::data::{DataMap, DataMapMut}; 11 use petgraph::dot::Dot; 12 use petgraph::prelude::*; 13 use petgraph::visit::{ 14 IntoEdgeReferences, IntoEdges, IntoNeighbors, IntoNodeReferences, NodeCount, NodeIndexable, 15 }; 16 17 use itertools::assert_equal; 18 n(x: u32) -> DefaultIx19 fn n(x: u32) -> DefaultIx { 20 DefaultIx::new(x as _) 21 } 22 23 #[test] node_indices()24 fn node_indices() { 25 let mut g = List::<()>::new(); 26 let a = g.add_node(); 27 let b = g.add_node(); 28 let c = g.add_node(); 29 let mut iter = g.node_indices(); 30 assert_eq!(iter.next(), Some(a)); 31 assert_eq!(iter.next(), Some(b)); 32 assert_eq!(iter.next(), Some(c)); 33 assert_eq!(iter.next(), None); 34 } 35 test_node_count<E>(g: &List<E>, n: usize)36 fn test_node_count<E>(g: &List<E>, n: usize) { 37 assert_eq!(n, g.node_count()); 38 assert_eq!(g.node_bound(), n); 39 assert_eq!(g.node_indices().count(), n); 40 assert_eq!(g.node_indices().len(), n); 41 assert_eq!(g.node_references().count(), n); 42 assert_eq!(g.node_references().len(), n); 43 } 44 45 #[test] node_bound()46 fn node_bound() { 47 let mut g = List::<()>::new(); 48 test_node_count(&g, 0); 49 for i in 0..10 { 50 g.add_node(); 51 test_node_count(&g, i + 1); 52 } 53 g.clear(); 54 test_node_count(&g, 0); 55 } 56 assert_sccs_eq<Ix: IndexType>(mut res: Vec<Vec<Ix>>, normalized: Vec<Vec<Ix>>)57 fn assert_sccs_eq<Ix: IndexType>(mut res: Vec<Vec<Ix>>, normalized: Vec<Vec<Ix>>) { 58 // normalize the result and compare with the answer. 59 for scc in &mut res { 60 scc.sort(); 61 } 62 // sort by minimum element 63 res.sort_by(|v, w| v[0].cmp(&w[0])); 64 assert_eq!(res, normalized); 65 } 66 scc_graph() -> UnweightedList<DefaultIx>67 fn scc_graph() -> UnweightedList<DefaultIx> { 68 let mut gr = List::new(); 69 for _ in 0..9 { 70 gr.add_node(); 71 } 72 for (a, b) in &[ 73 (6, 0), 74 (0, 3), 75 (3, 6), 76 (8, 6), 77 (8, 2), 78 (2, 5), 79 (5, 8), 80 (7, 5), 81 (1, 7), 82 ] { 83 gr.add_edge(n(*a), n(*b), ()); 84 } 85 // make an identical replacement of n(4) and leave a hole 86 let x = gr.add_node(); 87 gr.add_edge(n(7), x, ()); 88 gr.add_edge(x, n(1), ()); 89 gr 90 } 91 92 #[test] test_tarjan_scc()93 fn test_tarjan_scc() { 94 let gr = scc_graph(); 95 96 let x = n(gr.node_bound() as u32 - 1); 97 assert_sccs_eq( 98 tarjan_scc(&gr), 99 vec![ 100 vec![n(0), n(3), n(6)], 101 vec![n(1), n(7), x], 102 vec![n(2), n(5), n(8)], 103 vec![n(4)], 104 ], 105 ); 106 } 107 make_graph() -> List<i32>108 fn make_graph() -> List<i32> { 109 let mut gr = List::new(); 110 let mut c = 0..; 111 let mut e = || -> i32 { c.next().unwrap() }; 112 for _ in 0..=9 { 113 gr.add_node(); 114 } 115 for &(from, to) in &[ 116 (6, 0), 117 (0, 3), 118 (3, 6), 119 (8, 6), 120 (8, 2), 121 (2, 5), 122 (5, 8), 123 (7, 5), 124 (1, 7), 125 (7, 9), 126 (8, 6), // parallel edge 127 (9, 1), 128 (9, 9), 129 (9, 9), 130 ] { 131 gr.add_edge(n(from), n(to), e()); 132 } 133 gr 134 } 135 136 defmac!(edges ref gr, x => gr.edges(x).map(|r| (r.target(), *r.weight()))); 137 138 #[test] test_edges_directed()139 fn test_edges_directed() { 140 let gr = make_graph(); 141 dbg!(&gr); 142 let x = n(9); 143 assert_equal(edges!(&gr, x), vec![(1, 11), (x, 12), (x, 13)]); 144 assert_equal(edges!(&gr, n(0)), vec![(n(3), 1)]); 145 //assert_equal(edges!(&gr, n(4)), vec![]); 146 } 147 148 #[test] test_edge_references()149 fn test_edge_references() { 150 let mut gr = make_graph(); 151 assert_eq!(gr.edge_count(), gr.edge_references().count()); 152 for i in gr.edge_references() { 153 assert_eq!(gr.edge_endpoints(i.id()), Some((i.source(), i.target()))); 154 assert_eq!(gr.edge_weight(i.id()), Some(i.weight())); 155 } 156 for n in gr.node_indices() { 157 for e in gr.edge_indices_from(n) { 158 match gr.edge_weight_mut(e) { 159 None => {} 160 Some(r) => { 161 *r = 1; 162 } 163 } 164 } 165 } 166 for i in gr.edge_references() { 167 assert_eq!(*i.weight(), 1); 168 } 169 } 170 171 #[test] test_edge_iterators()172 fn test_edge_iterators() { 173 let gr = make_graph(); 174 for i in gr.node_indices() { 175 itertools::assert_equal( 176 gr.neighbors(n(i)), 177 gr.edges(n(i)).map(|r| { 178 assert_eq!(r.source(), n(i)); 179 r.target() 180 }), 181 ); 182 } 183 } 184 185 #[test] 186 #[should_panic(expected = "is not a valid node")] add_edge_vacant()187 fn add_edge_vacant() { 188 let mut g = List::new(); 189 let a: DefaultIx = g.add_node(); 190 let b = g.add_node(); 191 let _ = g.add_node(); 192 g.clear(); 193 g.add_edge(a, b, 1); 194 } 195 196 #[test] 197 #[should_panic(expected = "is not a valid node")] add_edge_oob()198 fn add_edge_oob() { 199 let mut g = List::new(); 200 let a = g.add_node(); 201 let _ = g.add_node(); 202 let _ = g.add_node(); 203 g.add_edge(a, n(4), 1); 204 } 205 206 #[test] 207 #[should_panic(expected = "index out of bounds")] add_edge_oob_2()208 fn add_edge_oob_2() { 209 let mut g = List::new(); 210 let a = g.add_node(); 211 let _ = g.add_node(); 212 let _ = g.add_node(); 213 g.add_edge(n(4), a, 1); 214 } 215 216 #[test] test_node_references()217 fn test_node_references() { 218 let gr = scc_graph(); 219 220 itertools::assert_equal(gr.node_references(), gr.node_indices()); 221 } 222 223 #[test] iterators_undir()224 fn iterators_undir() { 225 let mut g = List::with_capacity(2); 226 let a = g.add_node(); 227 let b = g.add_node(); 228 let c = g.add_node(); 229 let d = g.add_node(); 230 for &(from, to, w) in &[(a, b, 1), (a, c, 2), (b, c, 3), (c, c, 4), (a, d, 5)] { 231 g.add_edge(n(from), n(to), w); 232 } 233 234 itertools::assert_equal(g.neighbors(a), vec![b, c, d]); 235 itertools::assert_equal(g.neighbors(c), vec![c]); 236 itertools::assert_equal(g.neighbors(d), vec![]); 237 238 itertools::assert_equal(g.neighbors(b), vec![c]); 239 } 240 241 #[test] dot()242 fn dot() { 243 let mut gr = List::new(); 244 let a: DefaultIx = gr.add_node(); 245 let b = gr.add_node(); 246 gr.add_edge(a, a, 10u8); 247 gr.add_edge(a, b, 20); 248 let dot_output = format!("{:?}", Dot::new(&gr)); 249 assert_eq!( 250 dot_output, 251 r#"digraph { 252 0 [ label = "()" ] 253 1 [ label = "()" ] 254 0 -> 0 [ label = "10" ] 255 0 -> 1 [ label = "20" ] 256 } 257 "# 258 ); 259 } 260