1pub mod solve;
9
10use crate::config::{Csp, SolveStats};
11use crate::constraint::{self, AllDifferent, Constraint, ConstraintEnum, NotEqual, VarId};
12use crate::domain::Domain;
13use crate::solver::adjacency::Adjacency;
14use crate::variable::Variable;
15
16impl<D: Domain> Csp<D> {
17 pub fn new() -> Self {
19 Self {
20 variables: Vec::new(),
21 constraints: Vec::new(),
22 adjacency: None,
23 stats: SolveStats::default(),
24 constraint_weights: Vec::new(),
25 var_constraint_ids: Vec::new(),
26 }
27 }
28
29 pub fn add_variable(&mut self, domain: D) -> VarId {
31 let id = self.variables.len() as VarId;
32 self.variables.push(Variable::new(domain));
33 id
34 }
35
36 pub fn add_variables(&mut self, domain: &D, count: usize) -> Vec<VarId> {
38 (0..count)
39 .map(|_| self.add_variable(domain.clone()))
40 .collect()
41 }
42
43 pub fn add_constraint(&mut self, c: impl Constraint<D> + 'static) {
45 self.constraints.push(ConstraintEnum::Custom(Box::new(c)));
46 }
47
48 pub fn add_constraint_enum(&mut self, c: ConstraintEnum<D>) {
50 self.constraints.push(c);
51 }
52
53 pub fn add_not_equal(&mut self, x: VarId, y: VarId) {
55 self.constraints
56 .push(ConstraintEnum::NotEqual(NotEqual::new(x, y)));
57 }
58
59 pub fn add_all_different(&mut self, vars: Vec<VarId>) {
61 self.constraints
62 .push(ConstraintEnum::AllDifferent(AllDifferent::new(vars)));
63 }
64
65 pub fn add_equals(&mut self, var: VarId, value: D::Value)
67 where
68 D: 'static,
69 D::Value: Send + Sync,
70 {
71 self.add_constraint(constraint::LambdaConstraint::new(
72 vec![var],
73 move |assignment| match &assignment[var as usize] {
74 Some(v) => *v == value,
75 None => true,
76 },
77 format!("equals({var})"),
78 ));
79 }
80
81 pub fn add_less_than(&mut self, x: VarId, y: VarId)
83 where
84 D: 'static,
85 D::Value: PartialOrd + Send + Sync,
86 {
87 self.add_constraint(constraint::LambdaConstraint::new(
88 vec![x, y],
89 move |assignment| match (&assignment[x as usize], &assignment[y as usize]) {
90 (Some(a), Some(b)) => a < b,
91 _ => true,
92 },
93 format!("less_than({x},{y})"),
94 ));
95 }
96
97 pub fn add_greater_than(&mut self, x: VarId, y: VarId)
99 where
100 D: 'static,
101 D::Value: PartialOrd + Send + Sync,
102 {
103 self.add_constraint(constraint::LambdaConstraint::new(
104 vec![x, y],
105 move |assignment| match (&assignment[x as usize], &assignment[y as usize]) {
106 (Some(a), Some(b)) => a > b,
107 _ => true,
108 },
109 format!("greater_than({x},{y})"),
110 ));
111 }
112
113 pub fn finalize(&mut self)
116 where
117 D::Value: PartialEq + 'static,
118 {
119 let num_vars = self.variables.len();
120 self.adjacency = Some(Adjacency::build(num_vars, &self.constraints));
121
122 self.constraint_weights = vec![1.0; self.constraints.len()];
123 self.var_constraint_ids = vec![Vec::new(); num_vars];
124 for (ci, c) in self.constraints.iter().enumerate() {
125 for &v in c.scope() {
126 self.var_constraint_ids[v as usize].push(ci);
127 }
128 }
129 }
130}