solverforge_solver/phase/exhaustive/
decider.rs1use std::fmt::Debug;
7
8use solverforge_core::domain::PlanningSolution;
9use solverforge_scoring::ScoreDirector;
10
11use super::bounder::ScoreBounder;
12use super::node::ExhaustiveSearchNode;
13
14pub trait ExhaustiveSearchDecider<S: PlanningSolution>: Send + Debug {
21 fn expand(
25 &self,
26 parent_index: usize,
27 parent: &ExhaustiveSearchNode<S>,
28 score_director: &mut dyn ScoreDirector<S>,
29 ) -> Vec<ExhaustiveSearchNode<S>>;
30
31 fn total_entities(&self, score_director: &dyn ScoreDirector<S>) -> usize;
33}
34
35pub struct SimpleDecider<S: PlanningSolution, V: Clone + Send + Sync + 'static> {
39 descriptor_index: usize,
41 variable_name: String,
43 values: Vec<V>,
45 bounder: Option<Box<dyn ScoreBounder<S>>>,
47 setter: fn(&mut S, usize, Option<V>),
49}
50
51impl<S: PlanningSolution, V: Clone + Send + Sync + 'static> SimpleDecider<S, V> {
52 pub fn new(
60 descriptor_index: usize,
61 variable_name: impl Into<String>,
62 values: Vec<V>,
63 setter: fn(&mut S, usize, Option<V>),
64 ) -> Self {
65 Self {
66 descriptor_index,
67 variable_name: variable_name.into(),
68 values,
69 bounder: None,
70 setter,
71 }
72 }
73
74 pub fn with_bounder(mut self, bounder: Box<dyn ScoreBounder<S>>) -> Self {
76 self.bounder = Some(bounder);
77 self
78 }
79}
80
81impl<S: PlanningSolution, V: Clone + Send + Sync + Debug + 'static> Debug for SimpleDecider<S, V> {
82 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83 f.debug_struct("SimpleDecider")
84 .field("descriptor_index", &self.descriptor_index)
85 .field("variable_name", &self.variable_name)
86 .field("value_count", &self.values.len())
87 .finish()
88 }
89}
90
91impl<S: PlanningSolution, V: Clone + Send + Sync + Debug + 'static> ExhaustiveSearchDecider<S>
92 for SimpleDecider<S, V>
93{
94 fn expand(
95 &self,
96 parent_index: usize,
97 parent: &ExhaustiveSearchNode<S>,
98 score_director: &mut dyn ScoreDirector<S>,
99 ) -> Vec<ExhaustiveSearchNode<S>> {
100 let entity_index = parent.depth();
101 let new_depth = parent.depth() + 1;
102
103 let total = self.total_entities(score_director);
105 if entity_index >= total {
106 return Vec::new();
107 }
108
109 let mut children = Vec::with_capacity(self.values.len());
110
111 for (value_index, value) in self.values.iter().enumerate() {
112 score_director.before_variable_changed(
114 self.descriptor_index,
115 entity_index,
116 &self.variable_name,
117 );
118
119 (self.setter)(
120 score_director.working_solution_mut(),
121 entity_index,
122 Some(value.clone()),
123 );
124
125 score_director.after_variable_changed(
126 self.descriptor_index,
127 entity_index,
128 &self.variable_name,
129 );
130
131 let score = score_director.calculate_score();
133
134 let mut child = ExhaustiveSearchNode::child(
136 parent_index,
137 new_depth,
138 score.clone(),
139 entity_index,
140 value_index,
141 );
142
143 if let Some(ref bounder) = self.bounder {
145 if let Some(bound) = bounder.calculate_optimistic_bound(score_director) {
146 child.set_optimistic_bound(bound);
147 }
148 }
149
150 children.push(child);
151
152 score_director.before_variable_changed(
154 self.descriptor_index,
155 entity_index,
156 &self.variable_name,
157 );
158
159 (self.setter)(score_director.working_solution_mut(), entity_index, None);
160
161 score_director.after_variable_changed(
162 self.descriptor_index,
163 entity_index,
164 &self.variable_name,
165 );
166 }
167
168 children
169 }
170
171 fn total_entities(&self, score_director: &dyn ScoreDirector<S>) -> usize {
172 score_director
173 .entity_count(self.descriptor_index)
174 .unwrap_or(0)
175 }
176}
177
178#[cfg(test)]
179mod tests {
180 use super::*;
181 use solverforge_core::score::SimpleScore;
182
183 #[derive(Clone, Debug)]
184 struct TestSolution {
185 score: Option<SimpleScore>,
186 }
187
188 impl PlanningSolution for TestSolution {
189 type Score = SimpleScore;
190
191 fn score(&self) -> Option<Self::Score> {
192 self.score
193 }
194
195 fn set_score(&mut self, score: Option<Self::Score>) {
196 self.score = score;
197 }
198 }
199
200 fn set_row(_s: &mut TestSolution, _idx: usize, _v: Option<i32>) {
202 }
204
205 #[test]
206 fn test_simple_decider_creation() {
207 let decider: SimpleDecider<TestSolution, i32> =
208 SimpleDecider::new(0, "row", vec![0, 1, 2, 3], set_row);
209
210 let debug = format!("{:?}", decider);
211 assert!(debug.contains("SimpleDecider"));
212 assert!(debug.contains("value_count: 4"));
213 }
214}