|
| 1 | +use petgraph::graph::{DiGraph, UnGraph}; |
| 2 | +use petgraph::visit::EdgeRef; |
| 3 | +use quickcheck::{quickcheck, TestResult}; |
| 4 | +use rustworkx_core::generators::complete_graph; |
| 5 | +use std::collections::HashSet; |
| 6 | + |
| 7 | +#[test] |
| 8 | +fn prop_complete_graph_structure_directed() { |
| 9 | + fn prop(n: usize) -> TestResult { |
| 10 | + let n = n % 100; // limit for runtime issues |
| 11 | + if n == 0 { |
| 12 | + return TestResult::discard(); |
| 13 | + } |
| 14 | + |
| 15 | + let g = match complete_graph::<DiGraph<(), ()>, (), _, _, ()>(Some(n), None, || (), || ()) { |
| 16 | + Ok(g) => g, |
| 17 | + Err(_) => return TestResult::error("Unexpected error in directed complete graph"), |
| 18 | + }; |
| 19 | + |
| 20 | + if g.node_count() != n || g.edge_count() != n * (n - 1) { |
| 21 | + return TestResult::failed(); |
| 22 | + } |
| 23 | + |
| 24 | + // Ensure that for every pair (i, j) with i != j, an edge exists exists |
| 25 | + let expected_edges: HashSet<_> = (0..n) |
| 26 | + .flat_map(|i| (0..n).filter(move |&j| j != i).map(move |j| (i, j))) |
| 27 | + .collect(); |
| 28 | + |
| 29 | + let actual_edges: HashSet<_> = g |
| 30 | + .edge_references() |
| 31 | + .map(|e| (e.source().index(), e.target().index())) |
| 32 | + .collect(); |
| 33 | + |
| 34 | + TestResult::from_bool(expected_edges == actual_edges) |
| 35 | + } |
| 36 | + |
| 37 | + quickcheck(prop as fn(usize) -> TestResult); |
| 38 | +} |
| 39 | + |
| 40 | +#[test] |
| 41 | +fn prop_complete_graph_structure_undirected() { |
| 42 | + fn prop(n: usize) -> TestResult { |
| 43 | + let n = n % 100; |
| 44 | + if n == 0 { |
| 45 | + return TestResult::discard(); |
| 46 | + } |
| 47 | + |
| 48 | + let g = match complete_graph::<UnGraph<(), ()>, (), _, _, ()>(Some(n), None, || (), || ()) { |
| 49 | + Ok(g) => g, |
| 50 | + Err(_) => return TestResult::error("Unexpected error in undirected complete graph"), |
| 51 | + }; |
| 52 | + |
| 53 | + if g.node_count() != n || g.edge_count() != n * (n - 1) / 2 { |
| 54 | + return TestResult::failed(); |
| 55 | + } |
| 56 | + |
| 57 | + // in undirected graphs, (i, j) and (j, i) are the same edge, so we only include one of them. |
| 58 | + let expected_edges: HashSet<_> = (0..n) |
| 59 | + .flat_map(|i| (i + 1..n).map(move |j| (i, j))) |
| 60 | + .collect(); |
| 61 | + |
| 62 | + let actual_edges: HashSet<_> = g |
| 63 | + .edge_references() |
| 64 | + .map(|e| { |
| 65 | + let u = e.source().index(); |
| 66 | + let v = e.target().index(); |
| 67 | + (u.min(v), u.max(v)) |
| 68 | + }) |
| 69 | + .collect(); |
| 70 | + |
| 71 | + TestResult::from_bool(expected_edges == actual_edges) |
| 72 | + } |
| 73 | + |
| 74 | + quickcheck(prop as fn(usize) -> TestResult); |
| 75 | +} |
0 commit comments