use serde::{Deserialize, Serialize};
use crate::cover::OpenCover;
use crate::section::SectionFamily;
use crate::cochain::compute_cohomology;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ObstructionClass {
pub h1_dimension: usize,
pub conflicting_agents: Vec<(usize, usize)>,
}
impl ObstructionClass {
pub fn detect(cover: &OpenCover, sections: &SectionFamily, tol: f64) -> Self {
let (_h0, h1) = compute_cohomology(cover, tol);
let diffs = sections.pairwise_differences(cover);
let conflicting: Vec<(usize, usize)> = diffs
.iter()
.filter(|(_, _, d)| d.iter().any(|x| x.abs() > tol))
.map(|(i, j, _)| (*i, *j))
.collect();
Self {
h1_dimension: h1.dimension,
conflicting_agents: conflicting,
}
}
pub fn is_consistent(&self) -> bool {
self.h1_dimension == 0 && self.conflicting_agents.is_empty()
}
pub fn classify(&self) -> ObstructionType {
if self.h1_dimension == 0 {
ObstructionType::None
} else if self.conflicting_agents.len() == 1 {
ObstructionType::Pairwise(self.conflicting_agents[0])
} else if self.conflicting_agents.len() > 1 {
ObstructionType::MultiAgent(self.conflicting_agents.clone())
} else {
ObstructionType::Hidden(self.h1_dimension)
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum ObstructionType {
None,
Pairwise((usize, usize)),
MultiAgent(Vec<(usize, usize)>),
Hidden(usize),
}