use crate::graph::graph::Graph;
use std::collections::HashSet;
use std::fmt::Debug;
use std::hash::Hash;
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum DominatingSetError {
InvalidNeighborNode(usize),
}
impl std::fmt::Display for DominatingSetError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
DominatingSetError::InvalidNeighborNode(id) => {
write!(f, "Invalid neighbor node: node ID {} not found", id)
}
}
}
}
impl std::error::Error for DominatingSetError {}
pub trait DominatingSetFinder {
fn find_dominating_set(&self) -> Result<HashSet<usize>, DominatingSetError>;
}
impl<W, N, E> DominatingSetFinder for Graph<W, N, E>
where
W: Copy + Default + PartialEq,
N: Clone + Eq + Hash + Debug,
E: Clone + Default + Debug,
{
fn find_dominating_set(&self) -> Result<HashSet<usize>, DominatingSetError> {
let mut dominating_set = HashSet::new();
let mut covered = HashSet::new();
for node in self.all_nodes().map(|(id, _)| id) {
for (neighbor, _) in self.get_neighbors(node) {
if !self.nodes.contains(neighbor) {
return Err(DominatingSetError::InvalidNeighborNode(neighbor));
}
}
}
let mut nodes: Vec<_> = self.all_nodes().map(|(id, _)| id).collect();
nodes.sort_by_cached_key(|&node| usize::MAX - self.get_neighbors(node).len());
for node in nodes {
if !covered.contains(&node) {
dominating_set.insert(node);
covered.insert(node);
for (neighbor, _) in self.get_neighbors(node) {
covered.insert(neighbor); }
}
}
Ok(dominating_set)
}
}
#[cfg(test)]
mod tests {
use super::*;
fn create_test_graph(matrix: Vec<Vec<u32>>) -> Graph<u32, (), ()> {
Graph::from_adjacency_matrix(&matrix, false, (), ()).expect("Failed to create test graph")
}
#[test]
fn test_simple_dominating_set() {
let matrix = vec![
vec![0, 1, 1, 0],
vec![1, 0, 1, 1],
vec![1, 1, 0, 0],
vec![0, 1, 0, 0],
];
let graph = create_test_graph(matrix);
let ds = graph.find_dominating_set().unwrap();
assert!(!ds.is_empty(), "Dominating set should not be empty");
assert!(ds.len() <= 2, "Dominating set size should be at most 2");
}
#[test]
fn test_complex_dominating_set() {
let matrix = vec![
vec![0, 1, 0, 1, 0],
vec![1, 0, 1, 0, 0],
vec![0, 1, 0, 1, 1],
vec![1, 0, 1, 0, 0],
vec![0, 0, 1, 0, 0],
];
let graph = create_test_graph(matrix);
let ds = graph.find_dominating_set().unwrap();
assert!(!ds.is_empty(), "Dominating set should not be empty");
assert!(ds.len() <= 3, "Dominating set size should be at most 3");
}
}