solverforge_solver/heuristic/selector/
value_selector.rs1use std::fmt::Debug;
8use std::marker::PhantomData;
9
10use solverforge_core::domain::PlanningSolution;
11use solverforge_scoring::Director;
12
13pub trait ValueSelector<S: PlanningSolution, V>: Send + Debug {
22 fn iter_typed<'a, D: Director<S>>(
24 &'a self,
25 score_director: &D,
26 descriptor_index: usize,
27 entity_index: usize,
28 ) -> impl Iterator<Item = V> + 'a;
29
30 fn size<D: Director<S>>(
31 &self,
32 score_director: &D,
33 descriptor_index: usize,
34 entity_index: usize,
35 ) -> usize;
36
37 fn is_never_ending(&self) -> bool {
39 false
40 }
41}
42
43pub struct StaticValueSelector<S, V> {
45 values: Vec<V>,
46 _phantom: PhantomData<fn() -> S>,
47}
48
49impl<S, V: Clone> Clone for StaticValueSelector<S, V> {
50 fn clone(&self) -> Self {
51 Self {
52 values: self.values.clone(),
53 _phantom: PhantomData,
54 }
55 }
56}
57
58impl<S, V: Debug> Debug for StaticValueSelector<S, V> {
59 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
60 f.debug_struct("StaticValueSelector")
61 .field("values", &self.values)
62 .finish()
63 }
64}
65
66impl<S, V: Clone> StaticValueSelector<S, V> {
67 pub fn new(values: Vec<V>) -> Self {
68 Self {
69 values,
70 _phantom: PhantomData,
71 }
72 }
73
74 pub fn values(&self) -> &[V] {
75 &self.values
76 }
77}
78
79impl<S, V> ValueSelector<S, V> for StaticValueSelector<S, V>
80where
81 S: PlanningSolution,
82 V: Clone + Send + Debug + 'static,
83{
84 fn iter_typed<'a, D: Director<S>>(
85 &'a self,
86 _score_director: &D,
87 _descriptor_index: usize,
88 _entity_index: usize,
89 ) -> impl Iterator<Item = V> + 'a {
90 self.values.iter().cloned()
91 }
92
93 fn size<D: Director<S>>(
94 &self,
95 _score_director: &D,
96 _descriptor_index: usize,
97 _entity_index: usize,
98 ) -> usize {
99 self.values.len()
100 }
101}
102
103pub struct FromSolutionValueSelector<S, V> {
105 extractor: fn(&S) -> Vec<V>,
106 _phantom: PhantomData<(fn() -> S, fn() -> V)>,
107}
108
109impl<S, V> Debug for FromSolutionValueSelector<S, V> {
110 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
111 f.debug_struct("FromSolutionValueSelector").finish()
112 }
113}
114
115impl<S, V> FromSolutionValueSelector<S, V> {
116 pub fn new(extractor: fn(&S) -> Vec<V>) -> Self {
117 Self {
118 extractor,
119 _phantom: PhantomData,
120 }
121 }
122}
123
124pub struct PerEntityValueSelector<S, V> {
125 extractor: fn(&S, usize) -> Vec<V>,
126 _phantom: PhantomData<(fn() -> S, fn() -> V)>,
127}
128
129impl<S, V> Debug for PerEntityValueSelector<S, V> {
130 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
131 f.debug_struct("PerEntityValueSelector").finish()
132 }
133}
134
135impl<S, V> PerEntityValueSelector<S, V> {
136 pub fn new(extractor: fn(&S, usize) -> Vec<V>) -> Self {
137 Self {
138 extractor,
139 _phantom: PhantomData,
140 }
141 }
142}
143
144impl<S, V> ValueSelector<S, V> for PerEntityValueSelector<S, V>
145where
146 S: PlanningSolution,
147 V: Clone + Send + Debug + 'static,
148{
149 fn iter_typed<'a, D: Director<S>>(
150 &'a self,
151 score_director: &D,
152 _descriptor_index: usize,
153 entity_index: usize,
154 ) -> impl Iterator<Item = V> + 'a {
155 (self.extractor)(score_director.working_solution(), entity_index).into_iter()
156 }
157
158 fn size<D: Director<S>>(
159 &self,
160 score_director: &D,
161 _descriptor_index: usize,
162 entity_index: usize,
163 ) -> usize {
164 (self.extractor)(score_director.working_solution(), entity_index).len()
165 }
166}
167
168pub struct PerEntitySliceValueSelector<S, V> {
169 extractor: for<'a> fn(&'a S, usize) -> &'a [V],
170 _phantom: PhantomData<(fn() -> S, fn() -> V)>,
171}
172
173impl<S, V> Debug for PerEntitySliceValueSelector<S, V> {
174 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
175 f.debug_struct("PerEntitySliceValueSelector").finish()
176 }
177}
178
179impl<S, V> PerEntitySliceValueSelector<S, V> {
180 pub fn new(extractor: for<'a> fn(&'a S, usize) -> &'a [V]) -> Self {
181 Self {
182 extractor,
183 _phantom: PhantomData,
184 }
185 }
186}
187
188impl<S, V> ValueSelector<S, V> for PerEntitySliceValueSelector<S, V>
189where
190 S: PlanningSolution,
191 V: Copy + Send + Debug + 'static,
192{
193 fn iter_typed<'a, D: Director<S>>(
194 &'a self,
195 score_director: &D,
196 _descriptor_index: usize,
197 entity_index: usize,
198 ) -> impl Iterator<Item = V> + 'a {
199 (self.extractor)(score_director.working_solution(), entity_index)
200 .to_vec()
201 .into_iter()
202 }
203
204 fn size<D: Director<S>>(
205 &self,
206 score_director: &D,
207 _descriptor_index: usize,
208 entity_index: usize,
209 ) -> usize {
210 (self.extractor)(score_director.working_solution(), entity_index).len()
211 }
212}
213
214impl<S, V> ValueSelector<S, V> for FromSolutionValueSelector<S, V>
215where
216 S: PlanningSolution,
217 V: Clone + Send + Debug + 'static,
218{
219 fn iter_typed<'a, D: Director<S>>(
220 &'a self,
221 score_director: &D,
222 _descriptor_index: usize,
223 _entity_index: usize,
224 ) -> impl Iterator<Item = V> + 'a {
225 let values = (self.extractor)(score_director.working_solution());
226 values.into_iter()
227 }
228
229 fn size<D: Director<S>>(
230 &self,
231 score_director: &D,
232 _descriptor_index: usize,
233 _entity_index: usize,
234 ) -> usize {
235 (self.extractor)(score_director.working_solution()).len()
236 }
237}
238
239pub struct RangeValueSelector<S> {
243 count_fn: fn(&S) -> usize,
244 _phantom: PhantomData<fn() -> S>,
245}
246
247impl<S> Debug for RangeValueSelector<S> {
248 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
249 f.debug_struct("RangeValueSelector").finish()
250 }
251}
252
253impl<S> RangeValueSelector<S> {
254 pub fn new(count_fn: fn(&S) -> usize) -> Self {
255 Self {
256 count_fn,
257 _phantom: PhantomData,
258 }
259 }
260}
261
262impl<S> ValueSelector<S, usize> for RangeValueSelector<S>
263where
264 S: PlanningSolution,
265{
266 fn iter_typed<'a, D: Director<S>>(
267 &'a self,
268 score_director: &D,
269 _descriptor_index: usize,
270 _entity_index: usize,
271 ) -> impl Iterator<Item = usize> + 'a {
272 let count = (self.count_fn)(score_director.working_solution());
273 0..count
274 }
275
276 fn size<D: Director<S>>(
277 &self,
278 score_director: &D,
279 _descriptor_index: usize,
280 _entity_index: usize,
281 ) -> usize {
282 (self.count_fn)(score_director.working_solution())
283 }
284}
285
286#[cfg(test)]
287#[path = "value_selector_tests.rs"]
288mod tests;