use crate::constraint::{Constraint, PropagationResult, compare_assigned, prune, require_bounds};
use crate::model::domain::TrailedDomains;
use crate::model::variable::VariableId;
use std::collections::HashMap;
#[derive(Debug, Clone)]
pub struct LessThanOrEqual {
v1: VariableId,
v2: VariableId,
offset: i64,
scope: [VariableId; 2],
}
impl LessThanOrEqual {
pub fn new(v1: VariableId, v2: VariableId, offset: i64) -> Self {
Self {
v1,
v2,
offset,
scope: [v1, v2],
}
}
}
impl Constraint for LessThanOrEqual {
fn name(&self) -> &str {
"LessThanOrEqual"
}
fn scope(&self) -> &[VariableId] {
&self.scope
}
fn is_satisfied(&self, assignment: &HashMap<VariableId, i64>) -> bool {
compare_assigned(assignment, self.v1, self.v2, |val1, val2| {
val1 <= val2.saturating_add(self.offset)
})
}
fn propagate(&self, domains: &mut TrailedDomains) -> PropagationResult {
let mut changed = false;
let (_, max2) = match require_bounds(domains, self.v2) {
Ok(bounds) => bounds,
Err(result) => return result,
};
if let Some(result) = prune(domains, &mut changed, self.v1, |d| {
d.remove_above(max2.saturating_add(self.offset))
}) {
return result;
}
let (min1, _) = match require_bounds(domains, self.v1) {
Ok(bounds) => bounds,
Err(result) => return result,
};
if let Some(result) = prune(domains, &mut changed, self.v2, |d| {
d.remove_below(min1.saturating_sub(self.offset))
}) {
return result;
}
PropagationResult::Success { changed }
}
}