use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct OpenCover {
pub sets: Vec<Vec<usize>>,
}
impl OpenCover {
pub fn new(sets: Vec<Vec<usize>>) -> Self {
let mut sets: Vec<Vec<usize>> = sets
.into_iter()
.map(|mut s| {
s.sort_unstable();
s.dedup();
s
})
.collect();
if sets.is_empty() {
sets.push(vec![]);
}
Self { sets }
}
pub fn trivial(n: usize) -> Self {
Self {
sets: vec![(0..n).collect()],
}
}
pub fn num_sets(&self) -> usize {
self.sets.len()
}
pub fn universe_size(&self) -> usize {
let mut all: Vec<usize> = self.sets.iter().flatten().copied().collect();
all.sort_unstable();
all.dedup();
all.len()
}
pub fn universe(&self) -> Vec<usize> {
let mut all: Vec<usize> = self.sets.iter().flatten().copied().collect();
all.sort_unstable();
all.dedup();
all
}
pub fn intersection(&self, i: usize, j: usize) -> Vec<usize> {
let a = &self.sets[i];
let b = &self.sets[j];
let mut result = Vec::new();
let (mut ai, mut bi) = (0, 0);
while ai < a.len() && bi < b.len() {
if a[ai] == b[bi] {
result.push(a[ai]);
ai += 1;
bi += 1;
} else if a[ai] < b[bi] {
ai += 1;
} else {
bi += 1;
}
}
result
}
pub fn pairwise_intersections(&self) -> Vec<(usize, usize, Vec<usize>)> {
let n = self.num_sets();
let mut out = Vec::new();
for i in 0..n {
for j in (i + 1)..n {
let inter = self.intersection(i, j);
out.push((i, j, inter));
}
}
out
}
pub fn nonempty_intersections(&self) -> Vec<(usize, usize, Vec<usize>)> {
self.pairwise_intersections()
.into_iter()
.filter(|(_, _, v)| !v.is_empty())
.collect()
}
pub fn triple_intersection(&self, i: usize, j: usize, k: usize) -> Vec<usize> {
let ab = self.intersection(i, j);
let a = &ab;
let b = &self.sets[k];
let mut result = Vec::new();
let (mut ai, mut bi) = (0, 0);
while ai < a.len() && bi < b.len() {
if a[ai] == b[bi] {
result.push(a[ai]);
ai += 1;
bi += 1;
} else if a[ai] < b[bi] {
ai += 1;
} else {
bi += 1;
}
}
result
}
pub fn triple_intersections(&self) -> Vec<(usize, usize, usize, Vec<usize>)> {
let n = self.num_sets();
let mut out = Vec::new();
for i in 0..n {
for j in (i + 1)..n {
for k in (j + 1)..n {
let inter = self.triple_intersection(i, j, k);
if !inter.is_empty() {
out.push((i, j, k, inter));
}
}
}
}
out
}
pub fn is_valid_cover(&self) -> bool {
let universe = self.universe();
if universe.is_empty() && self.sets.iter().all(|s| s.is_empty()) {
return true;
}
if universe.is_empty() {
return true;
}
let max = *universe.last().unwrap();
universe.len() == max + 1
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct RestrictionMap {
pub from_set: usize,
pub to_intersection: Vec<usize>,
pub mapping: Vec<usize>,
}
impl RestrictionMap {
pub fn from_cover(cover: &OpenCover, from_idx: usize, intersection: &[usize]) -> Self {
let source = &cover.sets[from_idx];
let mapping: Vec<usize> = intersection
.iter()
.map(|&idx| {
source
.iter()
.position(|&x| x == idx)
.expect("intersection element must be in source set")
})
.collect();
Self {
from_set: from_idx,
to_intersection: intersection.to_vec(),
mapping,
}
}
pub fn apply(&self, data: &[f64]) -> Vec<f64> {
self.mapping.iter().map(|&i| data[i]).collect()
}
}