use std::hash::Hash;
use petgraph::data::{Build, Create};
use petgraph::visit::{Data, NodeIndexable};
use super::InvalidInputError;
pub fn petersen_graph<G, T, F, H, M>(
n: usize,
k: usize,
mut default_node_weight: F,
mut default_edge_weight: H,
) -> Result<G, InvalidInputError>
where
G: Build + Create + Data<NodeWeight = T, EdgeWeight = M> + NodeIndexable,
F: FnMut() -> T,
H: FnMut() -> M,
G::NodeId: Eq + Hash,
{
if n < 3 {
return Err(InvalidInputError {});
}
if k == 0 || 2 * k >= n {
return Err(InvalidInputError {});
}
let mut graph = G::with_capacity(2 * n, 3 * n);
let star_nodes: Vec<G::NodeId> = (0..n)
.map(|_| graph.add_node(default_node_weight()))
.collect();
let polygon_nodes: Vec<G::NodeId> = (0..n)
.map(|_| graph.add_node(default_node_weight()))
.collect();
for i in 0..n {
graph.add_edge(
star_nodes[i],
star_nodes[(i + k) % n],
default_edge_weight(),
);
}
for i in 0..n {
graph.add_edge(
polygon_nodes[i],
polygon_nodes[(i + 1) % n],
default_edge_weight(),
);
}
for i in 0..n {
graph.add_edge(polygon_nodes[i], star_nodes[i], default_edge_weight());
}
Ok(graph)
}
#[cfg(test)]
mod tests {
use crate::generators::petersen_graph;
use crate::generators::InvalidInputError;
use crate::petgraph;
use crate::petgraph::visit::EdgeRef;
#[test]
fn test_petersen_graph() {
let expected_edge_list = vec![
(0, 2),
(1, 3),
(2, 4),
(3, 0),
(4, 1),
(5, 6),
(6, 7),
(7, 8),
(8, 9),
(9, 5),
(5, 0),
(6, 1),
(7, 2),
(8, 3),
(9, 4),
];
let g: petgraph::graph::UnGraph<(), ()> = petersen_graph(5, 2, || (), || ()).unwrap();
assert_eq!(
expected_edge_list,
g.edge_references()
.map(|edge| (edge.source().index(), edge.target().index()))
.collect::<Vec<(usize, usize)>>(),
);
}
#[test]
fn test_petersen_error() {
match petersen_graph::<petgraph::graph::DiGraph<(), ()>, (), _, _, ()>(2, 3, || (), || ()) {
Ok(_) => panic!("Returned a non-error"),
Err(e) => assert_eq!(e, InvalidInputError),
};
}
}