use serde::{Deserialize, Serialize};
use crate::cover::{OpenCover, RestrictionMap};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct LocalSection {
pub agent_id: usize,
pub data: Vec<f64>,
}
impl LocalSection {
pub fn new(agent_id: usize, data: Vec<f64>) -> Self {
Self { agent_id, data }
}
pub fn restrict(&self, cover: &OpenCover, intersection: &[usize]) -> Vec<f64> {
let rmap = RestrictionMap::from_cover(cover, self.agent_id, intersection);
rmap.apply(&self.data)
}
pub fn agrees_with(&self, other: &LocalSection, cover: &OpenCover, tol: f64) -> bool {
let inter = cover.intersection(self.agent_id, other.agent_id);
if inter.is_empty() {
return true; }
let a = self.restrict(cover, &inter);
let b = other.restrict(cover, &inter);
a.iter().zip(b.iter()).all(|(x, y)| (x - y).abs() < tol)
}
pub fn dim(&self) -> usize {
self.data.len()
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct SectionFamily {
pub sections: Vec<LocalSection>,
}
impl SectionFamily {
pub fn new(sections: Vec<LocalSection>) -> Self {
Self { sections }
}
pub fn get(&self, agent_id: usize) -> Option<&LocalSection> {
self.sections.iter().find(|s| s.agent_id == agent_id)
}
pub fn is_consistent(&self, cover: &OpenCover, tol: f64) -> bool {
for i in 0..self.sections.len() {
for j in (i + 1)..self.sections.len() {
if !self.sections[i].agrees_with(&self.sections[j], cover, tol) {
return false;
}
}
}
true
}
pub fn pairwise_differences(&self, cover: &OpenCover) -> Vec<(usize, usize, Vec<f64>)> {
let intersections = cover.nonempty_intersections();
let mut diffs = Vec::new();
for (i, j, inter) in &intersections {
let si = self.get(*i);
let sj = self.get(*j);
if let (Some(si), Some(sj)) = (si, sj) {
let ri = si.restrict(cover, inter);
let rj = sj.restrict(cover, inter);
let diff: Vec<f64> = ri.iter().zip(rj.iter()).map(|(a, b)| a - b).collect();
diffs.push((*i, *j, diff));
}
}
diffs
}
pub fn len(&self) -> usize {
self.sections.len()
}
pub fn is_empty(&self) -> bool {
self.sections.is_empty()
}
}