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: &'a 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: &'a 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: &'a 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
168impl<S, V> ValueSelector<S, V> for FromSolutionValueSelector<S, V>
169where
170 S: PlanningSolution,
171 V: Clone + Send + Debug + 'static,
172{
173 fn iter_typed<'a, D: Director<S>>(
174 &'a self,
175 score_director: &'a D,
176 _descriptor_index: usize,
177 _entity_index: usize,
178 ) -> impl Iterator<Item = V> + 'a {
179 let values = (self.extractor)(score_director.working_solution());
180 values.into_iter()
181 }
182
183 fn size<D: Director<S>>(
184 &self,
185 score_director: &D,
186 _descriptor_index: usize,
187 _entity_index: usize,
188 ) -> usize {
189 (self.extractor)(score_director.working_solution()).len()
190 }
191}
192
193pub struct RangeValueSelector<S> {
197 count_fn: fn(&S) -> usize,
198 _phantom: PhantomData<fn() -> S>,
199}
200
201impl<S> Debug for RangeValueSelector<S> {
202 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
203 f.debug_struct("RangeValueSelector").finish()
204 }
205}
206
207impl<S> RangeValueSelector<S> {
208 pub fn new(count_fn: fn(&S) -> usize) -> Self {
209 Self {
210 count_fn,
211 _phantom: PhantomData,
212 }
213 }
214}
215
216impl<S> ValueSelector<S, usize> for RangeValueSelector<S>
217where
218 S: PlanningSolution,
219{
220 fn iter_typed<'a, D: Director<S>>(
221 &'a self,
222 score_director: &'a D,
223 _descriptor_index: usize,
224 _entity_index: usize,
225 ) -> impl Iterator<Item = usize> + 'a {
226 let count = (self.count_fn)(score_director.working_solution());
227 0..count
228 }
229
230 fn size<D: Director<S>>(
231 &self,
232 score_director: &D,
233 _descriptor_index: usize,
234 _entity_index: usize,
235 ) -> usize {
236 (self.count_fn)(score_director.working_solution())
237 }
238}
239
240#[cfg(test)]
241#[path = "value_selector_tests.rs"]
242mod tests;