use super::Constraint;
pub struct CartesianProduct<'a> {
idx: Vec<usize>,
constraints: Vec<&'a Constraint>,
}
impl<'a> CartesianProduct<'a> {
pub fn new() -> Self {
CartesianProduct {
idx: Vec::new(),
constraints: Vec::new(),
}
}
pub fn dimension(&self) -> usize {
*self.idx.last().unwrap_or(&0)
}
pub fn add_constraint(&mut self, ni: usize, constraint: &'a Constraint) {
assert!(
self.dimension() < ni,
"provided index is smaller than or equal to previous index, or zero"
);
self.idx.push(ni);
self.constraints.push(constraint);
}
}
impl<'a> Constraint for CartesianProduct<'a> {
fn project(&self, x: &mut [f64]) {
assert!(x.len() == self.dimension(), "x has wrong size");
let mut j = 0;
self.idx
.iter()
.zip(self.constraints.iter())
.for_each(|(&i, c)| {
c.project(&mut x[j..i]);
j = i;
});
}
}