use rust_igraph::{Graph, full_graph};
use std::collections::BTreeSet;
fn print_summary(label: &str, g: &Graph) {
println!("--- {label} ---");
println!(" vcount = {}", g.vcount());
println!(" ecount = {}", g.ecount());
println!(" directed = {}", g.is_directed());
}
fn dump_edges(g: &Graph) -> Vec<(u32, u32)> {
let ec = u32::try_from(g.ecount()).expect("ecount fits u32 in example");
let mut out = Vec::with_capacity(g.ecount());
for e in 0..ec {
let (u, v) = g.edge(e).expect("edge in range");
out.push((u, v));
}
out
}
fn assert_self_loop_count(g: &Graph, expected: u32) {
let mut loops = 0u32;
for (u, v) in dump_edges(g) {
if u == v {
loops += 1;
}
}
assert_eq!(
loops, expected,
"self-loop count mismatch (got {loops}, want {expected})"
);
}
fn main() {
let k0 = full_graph(0, false, false).expect("K_0");
print_summary("K_0 = full_graph(0, false, false)", &k0);
assert_eq!(k0.vcount(), 0);
assert_eq!(k0.ecount(), 0);
assert!(!k0.is_directed());
let k1_noloops = full_graph(1, false, false).expect("K_1 no loops");
print_summary("K_1 = full_graph(1, false, false)", &k1_noloops);
assert_eq!(k1_noloops.vcount(), 1);
assert_eq!(k1_noloops.ecount(), 0);
let k1_loops = full_graph(1, false, true).expect("K_1 with loops");
print_summary("K_1 (loops) = full_graph(1, false, true)", &k1_loops);
assert_eq!(k1_loops.vcount(), 1);
assert_eq!(k1_loops.ecount(), 1);
assert_eq!(dump_edges(&k1_loops), vec![(0, 0)]);
let k4_ud_noloops = full_graph(4, false, false).expect("K_4");
print_summary("K_4 = full_graph(4, false, false)", &k4_ud_noloops);
assert_eq!(k4_ud_noloops.vcount(), 4);
assert_eq!(k4_ud_noloops.ecount(), 6);
assert!(!k4_ud_noloops.is_directed());
assert_self_loop_count(&k4_ud_noloops, 0);
let k4_ud_loops = full_graph(4, false, true).expect("K_4 + loops");
print_summary("K_4 (loops) = full_graph(4, false, true)", &k4_ud_loops);
assert_eq!(k4_ud_loops.vcount(), 4);
assert_eq!(k4_ud_loops.ecount(), 10);
assert_self_loop_count(&k4_ud_loops, 4);
let k4_dir_noloops = full_graph(4, true, false).expect("directed K_4");
print_summary("directed K_4 = full_graph(4, true, false)", &k4_dir_noloops);
assert_eq!(k4_dir_noloops.vcount(), 4);
assert_eq!(k4_dir_noloops.ecount(), 12);
assert!(k4_dir_noloops.is_directed());
assert_self_loop_count(&k4_dir_noloops, 0);
let k4_dir_loops = full_graph(4, true, true).expect("directed K_4 + loops");
print_summary(
"directed K_4 + loops = full_graph(4, true, true)",
&k4_dir_loops,
);
assert_eq!(k4_dir_loops.vcount(), 4);
assert_eq!(k4_dir_loops.ecount(), 16);
assert!(k4_dir_loops.is_directed());
assert_self_loop_count(&k4_dir_loops, 4);
let got: BTreeSet<(u32, u32)> = dump_edges(&k4_ud_noloops).into_iter().collect();
let mut expected: BTreeSet<(u32, u32)> = BTreeSet::new();
for i in 0u32..4 {
for j in (i + 1)..4 {
expected.insert((i, j));
}
}
assert_eq!(
got, expected,
"K_4 (undirected, no loops) must equal the unordered pair set"
);
println!("\nall structural invariants OK ✓");
}