1pub struct ChangeMoveSelector<S, V, ES, VS> {
3 entity_selector: ES,
4 value_selector: VS,
5 getter: fn(&S, usize, usize) -> Option<V>,
6 setter: fn(&mut S, usize, usize, Option<V>),
7 descriptor_index: usize,
8 variable_index: usize,
9 variable_name: &'static str,
10 allows_unassigned: bool,
11 _phantom: PhantomData<(fn() -> S, fn() -> V)>,
12}
13
14struct ChangeEntityValues<V> {
15 entity_ref: super::entity::EntityReference,
16 values: Vec<V>,
17 current_assigned: bool,
18}
19
20pub struct ChangeMoveCursor<S, V>
21where
22 S: PlanningSolution,
23 V: Clone + PartialEq + Send + Sync + Debug + 'static,
24{
25 store: CandidateStore<S, ChangeMove<S, V>>,
26 entity_values: Vec<ChangeEntityValues<V>>,
27 entity_offset: usize,
28 value_offset: usize,
29 getter: fn(&S, usize, usize) -> Option<V>,
30 setter: fn(&mut S, usize, usize, Option<V>),
31 descriptor_index: usize,
32 variable_index: usize,
33 variable_name: &'static str,
34 allows_unassigned: bool,
35}
36
37impl<S, V> ChangeMoveCursor<S, V>
38where
39 S: PlanningSolution,
40 V: Clone + PartialEq + Send + Sync + Debug + 'static,
41{
42 fn new(
43 entity_values: Vec<ChangeEntityValues<V>>,
44 getter: fn(&S, usize, usize) -> Option<V>,
45 setter: fn(&mut S, usize, usize, Option<V>),
46 descriptor_index: usize,
47 variable_index: usize,
48 variable_name: &'static str,
49 allows_unassigned: bool,
50 ) -> Self {
51 Self {
52 store: CandidateStore::new(),
53 entity_values,
54 entity_offset: 0,
55 value_offset: 0,
56 getter,
57 setter,
58 descriptor_index,
59 variable_index,
60 variable_name,
61 allows_unassigned,
62 }
63 }
64
65 #[inline(always)]
66 fn next_move(&mut self) -> Option<ChangeMove<S, V>> {
67 while self.entity_offset < self.entity_values.len() {
68 let entity_values = &self.entity_values[self.entity_offset];
69 if self.value_offset < entity_values.values.len() {
70 let value = entity_values.values[self.value_offset].clone();
71 self.value_offset += 1;
72 return Some(ChangeMove::new(
73 entity_values.entity_ref.entity_index,
74 Some(value),
75 self.getter,
76 self.setter,
77 self.variable_index,
78 self.variable_name,
79 self.descriptor_index,
80 ));
81 }
82
83 let to_none_offset = entity_values.values.len();
84 if self.allows_unassigned
85 && entity_values.current_assigned
86 && self.value_offset == to_none_offset
87 {
88 self.value_offset += 1;
89 return Some(ChangeMove::new(
90 entity_values.entity_ref.entity_index,
91 None,
92 self.getter,
93 self.setter,
94 self.variable_index,
95 self.variable_name,
96 self.descriptor_index,
97 ));
98 }
99
100 self.entity_offset += 1;
101 self.value_offset = 0;
102 }
103 None
104 }
105}
106
107impl<S, V> MoveCursor<S, ChangeMove<S, V>> for ChangeMoveCursor<S, V>
108where
109 S: PlanningSolution,
110 V: Clone + PartialEq + Send + Sync + Debug + 'static,
111{
112 fn next_candidate(&mut self) -> Option<CandidateId> {
113 let mov = self.next_move()?;
114 Some(self.store.push(mov))
115 }
116
117 fn candidate(
118 &self,
119 id: CandidateId,
120 ) -> Option<MoveCandidateRef<'_, S, ChangeMove<S, V>>> {
121 self.store.candidate(id)
122 }
123
124 fn take_candidate(&mut self, id: CandidateId) -> ChangeMove<S, V> {
125 self.store.take_candidate(id)
126 }
127
128 #[inline(always)]
129 fn next_owned_candidate(&mut self) -> Option<ChangeMove<S, V>> {
130 self.next_move()
131 }
132
133 #[inline(always)]
134 fn next_owned_candidate_inspected<T, F>(&mut self, mut inspect: F) -> Option<(ChangeMove<S, V>, T)>
135 where
136 F: for<'a> FnMut(MoveCandidateRef<'a, S, ChangeMove<S, V>>) -> Option<T>,
137 {
138 loop {
139 let mov = self.next_move()?;
140 if let Some(metadata) = inspect(MoveCandidateRef::Borrowed(&mov)) {
141 return Some((mov, metadata));
142 }
143 }
144 }
145
146 fn release_candidate(&mut self, id: CandidateId) -> bool {
147 self.store.release_candidate(id)
148 }
149}
150
151impl<S, V> Iterator for ChangeMoveCursor<S, V>
152where
153 S: PlanningSolution,
154 V: Clone + PartialEq + Send + Sync + Debug + 'static,
155{
156 type Item = ChangeMove<S, V>;
157
158 fn next(&mut self) -> Option<Self::Item> {
159 self.next_move()
160 }
161}
162
163impl<S, V: Debug, ES: Debug, VS: Debug> Debug for ChangeMoveSelector<S, V, ES, VS> {
164 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
165 f.debug_struct("ChangeMoveSelector")
166 .field("entity_selector", &self.entity_selector)
167 .field("value_selector", &self.value_selector)
168 .field("descriptor_index", &self.descriptor_index)
169 .field("variable_index", &self.variable_index)
170 .field("variable_name", &self.variable_name)
171 .field("allows_unassigned", &self.allows_unassigned)
172 .finish()
173 }
174}
175
176impl<S: PlanningSolution, V: Clone, ES, VS> ChangeMoveSelector<S, V, ES, VS> {
177 pub fn new(
178 entity_selector: ES,
179 value_selector: VS,
180 getter: fn(&S, usize, usize) -> Option<V>,
181 setter: fn(&mut S, usize, usize, Option<V>),
182 descriptor_index: usize,
183 variable_index: usize,
184 variable_name: &'static str,
185 ) -> Self {
186 Self {
187 entity_selector,
188 value_selector,
189 getter,
190 setter,
191 descriptor_index,
192 variable_index,
193 variable_name,
194 allows_unassigned: false,
195 _phantom: PhantomData,
196 }
197 }
198
199 pub fn with_allows_unassigned(mut self, allows_unassigned: bool) -> Self {
200 self.allows_unassigned = allows_unassigned;
201 self
202 }
203}
204
205impl<S: PlanningSolution, V: Clone + Send + Sync + Debug + 'static>
206 ChangeMoveSelector<S, V, FromSolutionEntitySelector, StaticValueSelector<S, V>>
207{
208 pub fn simple(
209 getter: fn(&S, usize, usize) -> Option<V>,
210 setter: fn(&mut S, usize, usize, Option<V>),
211 descriptor_index: usize,
212 variable_index: usize,
213 variable_name: &'static str,
214 values: Vec<V>,
215 ) -> Self {
216 Self {
217 entity_selector: FromSolutionEntitySelector::new(descriptor_index),
218 value_selector: StaticValueSelector::new(values),
219 getter,
220 setter,
221 descriptor_index,
222 variable_index,
223 variable_name,
224 allows_unassigned: false,
225 _phantom: PhantomData,
226 }
227 }
228}
229
230impl<S, V, ES, VS> MoveSelector<S, ChangeMove<S, V>> for ChangeMoveSelector<S, V, ES, VS>
231where
232 S: PlanningSolution,
233 V: Clone + PartialEq + Send + Sync + Debug + 'static,
234 ES: EntitySelector<S>,
235 VS: ValueSelector<S, V>,
236{
237 type Cursor<'a>
238 = ChangeMoveCursor<S, V>
239 where
240 Self: 'a;
241
242 fn open_cursor<'a, D: Director<S>>(&'a self, score_director: &D) -> Self::Cursor<'a> {
243 self.open_cursor_with_context(score_director, MoveStreamContext::default())
244 }
245
246 fn open_cursor_with_context<'a, D: Director<S>>(
247 &'a self,
248 score_director: &D,
249 context: MoveStreamContext,
250 ) -> Self::Cursor<'a> {
251 let solution = score_director.working_solution();
252 let canonical_entities = self.entity_selector.iter(score_director).collect::<Vec<_>>();
253 let entity_count = canonical_entities.len();
254 let entity_salt = 0xC4A4_6E00_0000_0001
255 ^ ((self.descriptor_index as u64) << 32)
256 ^ self.variable_index as u64;
257 let entity_values = (0..entity_count)
258 .map(|entity_offset| {
259 let entity_ref = canonical_entities
260 [context.selection_index(entity_offset, entity_count, entity_salt)];
261 let current_assigned = (self.getter)(
262 solution,
263 entity_ref.entity_index,
264 self.variable_index,
265 )
266 .is_some();
267 let canonical_values = self
268 .value_selector
269 .iter(
270 score_director,
271 entity_ref.descriptor_index,
272 entity_ref.entity_index,
273 )
274 .collect::<Vec<_>>();
275 let value_count = canonical_values.len();
276 let value_salt = 0xC4A4_6E00_0000_0000
277 ^ entity_ref.entity_index as u64
278 ^ ((self.descriptor_index as u64) << 32)
279 ^ self.variable_index as u64;
280 let values = if context.is_canonical() {
281 canonical_values
282 } else {
283 (0..value_count)
284 .map(|value_offset| {
285 canonical_values
286 [context.selection_index(value_offset, value_count, value_salt)]
287 .clone()
288 })
289 .collect()
290 };
291 ChangeEntityValues {
292 entity_ref,
293 values,
294 current_assigned,
295 }
296 })
297 .collect();
298 ChangeMoveCursor::new(
299 entity_values,
300 self.getter,
301 self.setter,
302 self.descriptor_index,
303 self.variable_index,
304 self.variable_name,
305 self.allows_unassigned,
306 )
307 }
308
309 fn size<D: Director<S>>(&self, score_director: &D) -> usize {
310 self.entity_selector
311 .iter(score_director)
312 .map(|entity_ref| {
313 self.value_selector.size(
314 score_director,
315 entity_ref.descriptor_index,
316 entity_ref.entity_index,
317 ) + usize::from(
318 self.allows_unassigned
319 && (self.getter)(
320 score_director.working_solution(),
321 entity_ref.entity_index,
322 self.variable_index,
323 )
324 .is_some(),
325 )
326 })
327 .sum()
328 }
329}