diff options
Diffstat (limited to 'vendor/petgraph/tests/stable_graph.rs')
-rw-r--r-- | vendor/petgraph/tests/stable_graph.rs | 409 |
1 files changed, 409 insertions, 0 deletions
diff --git a/vendor/petgraph/tests/stable_graph.rs b/vendor/petgraph/tests/stable_graph.rs new file mode 100644 index 000000000..82cbcc7c4 --- /dev/null +++ b/vendor/petgraph/tests/stable_graph.rs @@ -0,0 +1,409 @@ +#![cfg(feature = "stable_graph")] + +extern crate itertools; +extern crate petgraph; +#[macro_use] +extern crate defmac; + +use itertools::assert_equal; +use petgraph::algo::{kosaraju_scc, min_spanning_tree, tarjan_scc}; +use petgraph::dot::Dot; +use petgraph::prelude::*; +use petgraph::stable_graph::node_index as n; +use petgraph::visit::{IntoEdgeReferences, IntoNodeReferences, NodeIndexable}; +use petgraph::EdgeType; + +#[test] +fn node_indices() { + let mut g = StableGraph::<_, ()>::new(); + let a = g.add_node(0); + let b = g.add_node(1); + let c = g.add_node(2); + g.remove_node(b); + let mut iter = g.node_indices(); + assert_eq!(iter.next(), Some(a)); + assert_eq!(iter.next(), Some(c)); + assert_eq!(iter.next(), None); +} + +#[test] +fn node_bound() { + let mut g = StableGraph::<_, ()>::new(); + assert_eq!(g.node_bound(), g.node_count()); + for i in 0..10 { + g.add_node(i); + assert_eq!(g.node_bound(), g.node_count()); + } + let full_count = g.node_count(); + g.remove_node(n(0)); + g.remove_node(n(2)); + assert_eq!(g.node_bound(), full_count); + g.clear(); + assert_eq!(g.node_bound(), 0); +} + +#[test] +fn clear_edges() { + let mut gr = scc_graph(); + gr.remove_node(n(1)); + gr.clear_edges(); + // check that we use the free list for the vacancies + assert_eq!(gr.add_node(()), n(1)); + assert_eq!(gr.add_node(()), n(4)); + assert!(gr.edge_references().next().is_none()); + assert!(gr.node_indices().all(|i| gr.neighbors(i).next().is_none())); +} + +fn assert_sccs_eq(mut res: Vec<Vec<NodeIndex>>, normalized: Vec<Vec<NodeIndex>>) { + // normalize the result and compare with the answer. + for scc in &mut res { + scc.sort(); + } + // sort by minimum element + res.sort_by(|v, w| v[0].cmp(&w[0])); + assert_eq!(res, normalized); +} + +fn scc_graph() -> StableGraph<(), ()> { + let mut gr: StableGraph<(), ()> = StableGraph::from_edges(&[ + (6, 0), + (0, 3), + (3, 6), + (8, 6), + (8, 2), + (2, 5), + (5, 8), + (7, 5), + (1, 7), + (7, 4), + (4, 1), + ]); + // make an identical replacement of n(4) and leave a hole + let x = gr.add_node(()); + gr.add_edge(n(7), x, ()); + gr.add_edge(x, n(1), ()); + gr.remove_node(n(4)); + gr +} + +#[test] +fn test_scc() { + let gr = scc_graph(); + println!("{:?}", gr); + + let x = n(gr.node_bound() - 1); + assert_sccs_eq( + kosaraju_scc(&gr), + vec![ + vec![n(0), n(3), n(6)], + vec![n(1), n(7), x], + vec![n(2), n(5), n(8)], + ], + ); +} + +#[test] +fn test_tarjan_scc() { + let gr = scc_graph(); + + let x = n(gr.node_bound() - 1); + assert_sccs_eq( + tarjan_scc(&gr), + vec![ + vec![n(0), n(3), n(6)], + vec![n(1), n(7), x], + vec![n(2), n(5), n(8)], + ], + ); +} + +fn make_graph<Ty>() -> StableGraph<(), i32, Ty> +where + Ty: EdgeType, +{ + let mut gr = StableGraph::default(); + let mut c = 0..; + let mut e = || -> i32 { c.next().unwrap() }; + gr.extend_with_edges(&[ + (6, 0, e()), + (0, 3, e()), + (3, 6, e()), + (8, 6, e()), + (8, 2, e()), + (2, 5, e()), + (5, 8, e()), + (7, 5, e()), + (1, 7, e()), + (7, 4, e()), + (8, 6, e()), // parallel edge + (4, 1, e()), + ]); + // make an identical replacement of n(4) and leave a hole + let x = gr.add_node(()); + gr.add_edge(n(7), x, e()); + gr.add_edge(x, n(1), e()); + gr.add_edge(x, x, e()); // make two self loops + let rm_self_loop = gr.add_edge(x, x, e()); + gr.add_edge(x, x, e()); + gr.remove_node(n(4)); + gr.remove_node(n(6)); + gr.remove_edge(rm_self_loop); + gr +} + +defmac!(edges ref gr, x => gr.edges(x).map(|r| (r.target(), *r.weight()))); + +#[test] +fn test_edges_directed() { + let gr = make_graph::<Directed>(); + let x = n(9); + assert_equal(edges!(gr, x), vec![(x, 16), (x, 14), (n(1), 13)]); + assert_equal(edges!(gr, n(0)), vec![(n(3), 1)]); + assert_equal(edges!(gr, n(4)), vec![]); +} + +#[test] +fn test_edge_references() { + let gr = make_graph::<Directed>(); + assert_eq!(gr.edge_count(), gr.edge_references().count()); +} + +#[test] +fn test_edges_undirected() { + let gr = make_graph::<Undirected>(); + let x = n(9); + assert_equal( + edges!(gr, x), + vec![(x, 16), (x, 14), (n(1), 13), (n(7), 12)], + ); + assert_equal(edges!(gr, n(0)), vec![(n(3), 1)]); + assert_equal(edges!(gr, n(4)), vec![]); +} + +#[test] +fn test_edge_iterators_directed() { + let gr = make_graph::<Directed>(); + for i in gr.node_indices() { + itertools::assert_equal(gr.edges_directed(i, Outgoing), gr.edges(i)); + for edge in gr.edges_directed(i, Outgoing) { + assert_eq!( + edge.source(), + i, + "outgoing edges should have a fixed source" + ); + } + } + let mut incoming = vec![Vec::new(); gr.node_bound()]; + + for i in gr.node_indices() { + for j in gr.neighbors(i) { + incoming[j.index()].push(i); + } + } + + println!("{:#?}", gr); + for i in gr.node_indices() { + itertools::assert_equal( + gr.edges_directed(i, Incoming).map(|e| e.source()), + incoming[i.index()].iter().rev().cloned(), + ); + for edge in gr.edges_directed(i, Incoming) { + assert_eq!( + edge.target(), + i, + "incoming edges should have a fixed target" + ); + } + } +} + +#[test] +fn test_edge_iterators_undir() { + let gr = make_graph::<Undirected>(); + for i in gr.node_indices() { + itertools::assert_equal(gr.edges_directed(i, Outgoing), gr.edges(i)); + for edge in gr.edges_directed(i, Outgoing) { + assert_eq!( + edge.source(), + i, + "outgoing edges should have a fixed source" + ); + } + } + for i in gr.node_indices() { + itertools::assert_equal(gr.edges_directed(i, Incoming), gr.edges(i)); + for edge in gr.edges_directed(i, Incoming) { + assert_eq!( + edge.target(), + i, + "incoming edges should have a fixed target" + ); + } + } +} + +#[test] +#[should_panic(expected = "is not a node")] +fn add_edge_vacant() { + let mut g = StableGraph::<_, _>::new(); + let a = g.add_node(0); + let b = g.add_node(1); + let _ = g.add_node(2); + let _ = g.remove_node(b); + g.add_edge(a, b, 1); +} + +#[test] +#[should_panic(expected = "is not a node")] +fn add_edge_oob() { + let mut g = StableGraph::<_, _>::new(); + let a = g.add_node(0); + let _ = g.add_node(1); + let _ = g.add_node(2); + g.add_edge(a, n(4), 1); +} + +#[test] +fn test_node_references() { + let gr = scc_graph(); + + itertools::assert_equal(gr.node_references().map(|(i, _)| i), gr.node_indices()); +} + +#[test] +fn iterators_undir() { + let mut g = StableUnGraph::<_, _>::default(); + let a = g.add_node(0); + let b = g.add_node(1); + let c = g.add_node(2); + let d = g.add_node(3); + g.extend_with_edges(&[(a, b, 1), (a, c, 2), (b, c, 3), (c, c, 4), (a, d, 5)]); + g.remove_node(b); + + itertools::assert_equal(g.neighbors(a), vec![d, c]); + itertools::assert_equal(g.neighbors(c), vec![c, a]); + itertools::assert_equal(g.neighbors(d), vec![a]); + + // the node that was removed + itertools::assert_equal(g.neighbors(b), vec![]); + + // remove one more + g.remove_node(c); + itertools::assert_equal(g.neighbors(c), vec![]); +} + +#[test] +fn dot() { + let mut gr = StableGraph::new(); + let a = gr.add_node("x"); + let b = gr.add_node("y"); + gr.add_edge(a, a, "10"); + gr.add_edge(a, b, "20"); + let dot_output = format!("{}", Dot::new(&gr)); + assert_eq!( + dot_output, + r#"digraph { + 0 [ label = "x" ] + 1 [ label = "y" ] + 0 -> 0 [ label = "10" ] + 0 -> 1 [ label = "20" ] +} +"# + ); +} + +defmac!(iter_eq a, b => a.eq(b)); +defmac!(nodes_eq ref a, ref b => a.node_references().eq(b.node_references())); +defmac!(edgew_eq ref a, ref b => a.edge_references().eq(b.edge_references())); +defmac!(edges_eq ref a, ref b => + iter_eq!( + a.edge_references().map(|e| (e.source(), e.target())), + b.edge_references().map(|e| (e.source(), e.target())))); + +#[test] +fn from() { + let mut gr1 = StableGraph::new(); + let a = gr1.add_node(1); + let b = gr1.add_node(2); + let c = gr1.add_node(3); + gr1.add_edge(a, a, 10); + gr1.add_edge(a, b, 20); + gr1.add_edge(b, c, 30); + gr1.add_edge(a, c, 40); + + let gr2 = Graph::from(gr1.clone()); + let gr3 = StableGraph::from(gr2); + assert!(nodes_eq!(gr1, gr3)); + assert!(edgew_eq!(gr1, gr3)); + assert!(edges_eq!(gr1, gr3)); + + gr1.remove_node(b); + + let gr4 = Graph::from(gr1); + let gr5 = StableGraph::from(gr4.clone()); + + let mut ans = StableGraph::new(); + let a = ans.add_node(1); + let c = ans.add_node(3); + ans.add_edge(a, a, 10); + ans.add_edge(a, c, 40); + + assert!(nodes_eq!(gr4, ans)); + assert!(edges_eq!(gr4, ans)); + + assert!(nodes_eq!(gr5, ans)); + assert!(edgew_eq!(gr5, ans)); + assert!(edges_eq!(gr5, ans)); +} + +use petgraph::data::FromElements; +use petgraph::stable_graph::StableGraph; + +#[test] +fn from_min_spanning_tree() { + let mut g = StableGraph::new(); + let mut nodes = Vec::new(); + for _ in 0..6 { + nodes.push(g.add_node(())); + } + let es = [(4, 5), (3, 4), (3, 5)]; + for &(a, b) in es.iter() { + g.add_edge(NodeIndex::new(a), NodeIndex::new(b), ()); + } + for i in 0..3 { + let _ = g.remove_node(nodes[i]); + } + let _ = StableGraph::<(), (), Undirected, usize>::from_elements(min_spanning_tree(&g)); +} + +#[test] +fn weights_mut_iterator() { + let mut gr = StableGraph::new(); + let a = gr.add_node(1); + let b = gr.add_node(2); + let c = gr.add_node(3); + let e1 = gr.add_edge(a, a, 10); + let e2 = gr.add_edge(a, b, 20); + let e3 = gr.add_edge(b, c, 30); + let e4 = gr.add_edge(a, c, 40); + + for n in gr.node_weights_mut() { + *n += 1; + } + assert_eq!(gr[a], 2); + assert_eq!(gr[b], 3); + assert_eq!(gr[c], 4); + + for e in gr.edge_weights_mut() { + *e -= 1; + } + assert_eq!(gr[e1], 9); + assert_eq!(gr[e2], 19); + assert_eq!(gr[e3], 29); + assert_eq!(gr[e4], 39); + + // test on deletion + gr.remove_node(b); + assert_eq!(gr.node_weights_mut().count(), gr.node_count()); + assert_eq!(gr.edge_weights_mut().count(), gr.edge_count()); +} |