use crate::VariableId;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SetDomainSnapshot {
pub glb: Vec<i32>,
pub lub: Vec<i32>,
pub card_min: usize,
pub card_max: usize,
}
impl SetDomainSnapshot {
#[must_use]
pub fn is_empty(&self) -> bool {
self.card_min > self.card_max
|| self.glb.len() > self.card_max
|| self.lub.len() < self.card_min
|| !self.glb.iter().all(|value| self.lub.contains(value))
}
#[must_use]
pub fn undecided(&self) -> Vec<i32> {
self.lub
.iter()
.copied()
.filter(|value| !self.glb.contains(value))
.collect()
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct FloatDomainSnapshot {
pub min: f64,
pub max: f64,
pub holes: Vec<f64>,
}
impl FloatDomainSnapshot {
#[must_use]
pub fn is_empty(&self) -> bool {
self.min > self.max
|| ((self.max - self.min).abs() <= f64::EPSILON
&& self
.holes
.iter()
.any(|hole| (*hole - self.min).abs() <= f64::EPSILON))
}
#[must_use]
pub fn is_fixed(&self) -> bool {
!self.is_empty()
&& (self.max - self.min).abs() < f64::EPSILON
&& !self
.holes
.iter()
.any(|hole| (*hole - self.min).abs() <= f64::EPSILON)
}
#[must_use]
pub fn contains(&self, value: f64) -> bool {
!self.is_empty()
&& value >= self.min
&& value <= self.max
&& !self
.holes
.iter()
.any(|hole| (*hole - value).abs() <= f64::EPSILON)
}
}
pub trait ExtendedPropagationContext {
fn set_domain(&self, var: VariableId) -> Option<SetDomainSnapshot>;
fn float_domain(&self, var: VariableId) -> Option<FloatDomainSnapshot>;
fn force_set_in(&mut self, var: VariableId, value: i32) -> bool;
fn force_set_out(&mut self, var: VariableId, value: i32) -> bool;
fn tighten_set_cardinality(
&mut self,
var: VariableId,
card_min: usize,
card_max: usize,
) -> bool;
fn tighten_float_below(&mut self, var: VariableId, bound: f64) -> bool;
fn tighten_float_above(&mut self, var: VariableId, bound: f64) -> bool;
fn exclude_float_point(&mut self, var: VariableId, value: f64) -> bool;
}