pub mod solve;
use crate::config::{Csp, SolveStats};
use crate::constraint::{self, AllDifferent, Constraint, ConstraintEnum, NotEqual, VarId};
use crate::domain::Domain;
use crate::solver::adjacency::Adjacency;
use crate::variable::Variable;
impl<D: Domain> Csp<D> {
pub fn new() -> Self {
Self {
variables: Vec::new(),
constraints: Vec::new(),
adjacency: None,
stats: SolveStats::default(),
constraint_weights: Vec::new(),
var_constraint_ids: Vec::new(),
}
}
pub fn add_variable(&mut self, domain: D) -> VarId {
let id = self.variables.len() as VarId;
self.variables.push(Variable::new(domain));
id
}
pub fn add_variables(&mut self, domain: &D, count: usize) -> Vec<VarId> {
(0..count)
.map(|_| self.add_variable(domain.clone()))
.collect()
}
pub fn add_constraint(&mut self, c: impl Constraint<D> + 'static) {
self.constraints.push(ConstraintEnum::Custom(Box::new(c)));
}
pub fn add_constraint_enum(&mut self, c: ConstraintEnum<D>) {
self.constraints.push(c);
}
pub fn add_not_equal(&mut self, x: VarId, y: VarId) {
self.constraints
.push(ConstraintEnum::NotEqual(NotEqual::new(x, y)));
}
pub fn add_all_different(&mut self, vars: Vec<VarId>) {
self.constraints
.push(ConstraintEnum::AllDifferent(AllDifferent::new(vars)));
}
pub fn add_equals(&mut self, var: VarId, value: D::Value)
where
D: 'static,
D::Value: Send + Sync,
{
self.add_constraint(constraint::LambdaConstraint::new(
vec![var],
move |assignment| match &assignment[var as usize] {
Some(v) => *v == value,
None => true,
},
format!("equals({var})"),
));
}
pub fn add_less_than(&mut self, x: VarId, y: VarId)
where
D: 'static,
D::Value: PartialOrd + Send + Sync,
{
self.add_constraint(constraint::LambdaConstraint::new(
vec![x, y],
move |assignment| match (&assignment[x as usize], &assignment[y as usize]) {
(Some(a), Some(b)) => a < b,
_ => true,
},
format!("less_than({x},{y})"),
));
}
pub fn add_greater_than(&mut self, x: VarId, y: VarId)
where
D: 'static,
D::Value: PartialOrd + Send + Sync,
{
self.add_constraint(constraint::LambdaConstraint::new(
vec![x, y],
move |assignment| match (&assignment[x as usize], &assignment[y as usize]) {
(Some(a), Some(b)) => a > b,
_ => true,
},
format!("greater_than({x},{y})"),
));
}
pub fn finalize(&mut self)
where
D::Value: PartialEq + 'static,
{
let num_vars = self.variables.len();
self.adjacency = Some(Adjacency::build(num_vars, &self.constraints));
self.constraint_weights = vec![1.0; self.constraints.len()];
self.var_constraint_ids = vec![Vec::new(); num_vars];
for (ci, c) in self.constraints.iter().enumerate() {
for &v in c.scope() {
self.var_constraint_ids[v as usize].push(ci);
}
}
}
}