solverforge_solver/heuristic/selector/
mimic.rs1use std::cell::Cell;
14use std::fmt::Debug;
15use std::ptr::NonNull;
16
17use solverforge_core::domain::PlanningSolution;
18use solverforge_scoring::ScoreDirector;
19
20use super::entity::{EntityReference, EntitySelector};
21
22#[derive(Debug, Default, Clone, Copy)]
27struct MimicState {
28 has_next_recorded: bool,
30 has_next: bool,
32 next_recorded: bool,
34 recorded_entity: Option<EntityReference>,
36}
37
38struct SharedMimicState {
45 state: Cell<MimicState>,
46 refcount: Cell<usize>,
47}
48
49pub struct MimicRecorder {
54 ptr: NonNull<SharedMimicState>,
55 id: String,
57}
58
59impl MimicRecorder {
60 pub fn new(id: impl Into<String>) -> Self {
62 let shared = Box::new(SharedMimicState {
63 state: Cell::new(MimicState::default()),
64 refcount: Cell::new(1),
65 });
66 Self {
67 ptr: NonNull::from(Box::leak(shared)),
68 id: id.into(),
69 }
70 }
71
72 #[inline]
73 fn shared(&self) -> &SharedMimicState {
74 unsafe { self.ptr.as_ref() }
77 }
78
79 fn record_has_next(&self, has_next: bool) {
81 self.shared().state.set(MimicState {
82 has_next_recorded: true,
83 has_next,
84 next_recorded: false,
85 recorded_entity: None,
86 });
87 }
88
89 fn record_next(&self, entity: EntityReference) {
91 self.shared().state.set(MimicState {
92 has_next_recorded: true,
93 has_next: true,
94 next_recorded: true,
95 recorded_entity: Some(entity),
96 });
97 }
98
99 pub fn get_has_next(&self) -> Option<bool> {
101 let state = self.shared().state.get();
102 if state.has_next_recorded {
103 Some(state.has_next)
104 } else {
105 None
106 }
107 }
108
109 pub fn get_recorded_entity(&self) -> Option<EntityReference> {
111 let state = self.shared().state.get();
112 if state.next_recorded {
113 state.recorded_entity
114 } else {
115 None
116 }
117 }
118
119 pub fn id(&self) -> &str {
121 &self.id
122 }
123
124 pub fn reset(&self) {
126 self.shared().state.set(MimicState::default());
127 }
128}
129
130impl Clone for MimicRecorder {
131 fn clone(&self) -> Self {
132 let shared = self.shared();
133 shared.refcount.set(shared.refcount.get() + 1);
134 Self {
135 ptr: self.ptr,
136 id: self.id.clone(),
137 }
138 }
139}
140
141impl Drop for MimicRecorder {
142 fn drop(&mut self) {
143 let shared = self.shared();
144 let rc = shared.refcount.get() - 1;
145 if rc == 0 {
146 unsafe {
149 drop(Box::from_raw(self.ptr.as_ptr()));
150 }
151 } else {
152 shared.refcount.set(rc);
153 }
154 }
155}
156
157impl Debug for MimicRecorder {
158 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
159 f.debug_struct("MimicRecorder")
160 .field("id", &self.id)
161 .field("state", &self.shared().state.get())
162 .finish()
163 }
164}
165
166unsafe impl Send for MimicRecorder {}
170unsafe impl Sync for MimicRecorder {}
171
172pub struct MimicRecordingEntitySelector<S, ES> {
183 child: ES,
185 recorder: MimicRecorder,
187 _phantom: std::marker::PhantomData<fn() -> S>,
189}
190
191impl<S, ES> MimicRecordingEntitySelector<S, ES> {
192 pub fn new(child: ES, recorder: MimicRecorder) -> Self {
194 Self {
195 child,
196 recorder,
197 _phantom: std::marker::PhantomData,
198 }
199 }
200
201 pub fn recorder(&self) -> MimicRecorder {
203 self.recorder.clone()
204 }
205}
206
207impl<S: PlanningSolution, ES: Debug> Debug for MimicRecordingEntitySelector<S, ES> {
208 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
209 f.debug_struct("MimicRecordingEntitySelector")
210 .field("child", &self.child)
211 .field("recorder_id", &self.recorder.id)
212 .finish()
213 }
214}
215
216impl<S, ES> EntitySelector<S> for MimicRecordingEntitySelector<S, ES>
217where
218 S: PlanningSolution,
219 ES: EntitySelector<S>,
220{
221 fn iter<'a, D: ScoreDirector<S>>(
222 &'a self,
223 score_director: &'a D,
224 ) -> impl Iterator<Item = EntityReference> + 'a {
225 self.recorder.reset();
227
228 let child_iter = self.child.iter(score_director);
229 RecordingIterator {
230 inner: child_iter,
231 recorder: &self.recorder,
232 }
233 }
234
235 fn size<D: ScoreDirector<S>>(&self, score_director: &D) -> usize {
236 self.child.size(score_director)
237 }
238
239 fn is_never_ending(&self) -> bool {
240 self.child.is_never_ending()
241 }
242}
243
244struct RecordingIterator<'a, I> {
246 inner: I,
247 recorder: &'a MimicRecorder,
248}
249
250impl<'a, I: Iterator<Item = EntityReference>> Iterator for RecordingIterator<'a, I> {
251 type Item = EntityReference;
252
253 fn next(&mut self) -> Option<Self::Item> {
254 let next = self.inner.next();
255 match next {
256 Some(entity) => {
257 self.recorder.record_next(entity);
258 Some(entity)
259 }
260 None => {
261 self.recorder.record_has_next(false);
262 None
263 }
264 }
265 }
266}
267
268pub struct MimicReplayingEntitySelector {
273 recorder: MimicRecorder,
275}
276
277impl MimicReplayingEntitySelector {
278 pub fn new(recorder: MimicRecorder) -> Self {
280 Self { recorder }
281 }
282}
283
284impl Debug for MimicReplayingEntitySelector {
285 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
286 f.debug_struct("MimicReplayingEntitySelector")
287 .field("recorder_id", &self.recorder.id)
288 .finish()
289 }
290}
291
292impl<S: PlanningSolution> EntitySelector<S> for MimicReplayingEntitySelector {
293 fn iter<'a, D: ScoreDirector<S>>(
294 &'a self,
295 _score_director: &'a D,
296 ) -> impl Iterator<Item = EntityReference> + 'a {
297 ReplayingIterator {
298 recorder: &self.recorder,
299 returned: false,
300 }
301 }
302
303 fn size<D: ScoreDirector<S>>(&self, _score_director: &D) -> usize {
304 if self.recorder.get_recorded_entity().is_some() {
306 1
307 } else {
308 0
309 }
310 }
311
312 fn is_never_ending(&self) -> bool {
313 false
314 }
315}
316
317struct ReplayingIterator<'a> {
319 recorder: &'a MimicRecorder,
320 returned: bool,
321}
322
323impl<'a> Iterator for ReplayingIterator<'a> {
324 type Item = EntityReference;
325
326 fn next(&mut self) -> Option<Self::Item> {
327 if self.returned {
328 return None;
329 }
330
331 match self.recorder.get_recorded_entity() {
333 Some(entity) => {
334 self.returned = true;
335 Some(entity)
336 }
337 None => {
338 match self.recorder.get_has_next() {
340 Some(false) => None, Some(true) => panic!(
342 "MimicReplayingEntitySelector: Recording selector's hasNext() was true \
343 but next() was never called. Ensure the recording selector's iterator \
344 is advanced before using the replaying selector."
345 ),
346 None => panic!(
347 "MimicReplayingEntitySelector: No recording found. \
348 The recording selector must be iterated before the replaying selector."
349 ),
350 }
351 }
352 }
353 }
354}
355
356#[cfg(test)]
357mod tests {
358 use super::*;
359 use crate::heuristic::selector::entity::FromSolutionEntitySelector;
360 use crate::test_utils::create_simple_nqueens_director;
361
362 #[test]
363 fn test_mimic_recording_selector() {
364 let director = create_simple_nqueens_director(3);
365
366 let solution = director.working_solution();
368 for (i, queen) in solution.queens.iter().enumerate() {
369 assert_eq!(queen.column, i as i64);
370 }
371
372 let recorder = MimicRecorder::new("test");
373 let child = FromSolutionEntitySelector::new(0);
374 let recording = MimicRecordingEntitySelector::new(child, recorder);
375
376 let entities: Vec<_> = recording.iter(&director).collect();
377 assert_eq!(entities.len(), 3);
378 assert_eq!(entities[0], EntityReference::new(0, 0));
379 assert_eq!(entities[1], EntityReference::new(0, 1));
380 assert_eq!(entities[2], EntityReference::new(0, 2));
381 }
382
383 #[test]
384 fn test_mimic_replaying_selector() {
385 let director = create_simple_nqueens_director(3);
386
387 let recorder = MimicRecorder::new("test");
388 let child = FromSolutionEntitySelector::new(0);
389 let recording = MimicRecordingEntitySelector::new(child, recorder.clone());
390 let replaying = MimicReplayingEntitySelector::new(recorder);
391
392 let mut recording_iter = recording.iter(&director);
394
395 let first = recording_iter.next().unwrap();
397 assert_eq!(first, EntityReference::new(0, 0));
398
399 let replayed: Vec<_> = replaying.iter(&director).collect();
401 assert_eq!(replayed.len(), 1);
402 assert_eq!(replayed[0], EntityReference::new(0, 0));
403
404 let second = recording_iter.next().unwrap();
406 assert_eq!(second, EntityReference::new(0, 1));
407
408 let replayed: Vec<_> = replaying.iter(&director).collect();
410 assert_eq!(replayed.len(), 1);
411 assert_eq!(replayed[0], EntityReference::new(0, 1));
412 }
413
414 #[test]
415 fn test_mimic_synchronized_iteration() {
416 let director = create_simple_nqueens_director(3);
417
418 let recorder = MimicRecorder::new("test");
419 let child = FromSolutionEntitySelector::new(0);
420 let recording = MimicRecordingEntitySelector::new(child, recorder.clone());
421 let replaying = MimicReplayingEntitySelector::new(recorder);
422
423 for recorded in recording.iter(&director) {
426 let replayed: Vec<_> = replaying.iter(&director).collect();
427 assert_eq!(replayed.len(), 1);
428 assert_eq!(replayed[0], recorded);
429 }
430 }
431
432 #[test]
433 fn test_mimic_empty_selector() {
434 let director = create_simple_nqueens_director(0);
435
436 let recorder = MimicRecorder::new("test");
437 let child = FromSolutionEntitySelector::new(0);
438 let recording = MimicRecordingEntitySelector::new(child, recorder.clone());
439 let replaying = MimicReplayingEntitySelector::new(recorder);
440
441 let entities: Vec<_> = recording.iter(&director).collect();
443 assert_eq!(entities.len(), 0);
444
445 let replayed: Vec<_> = replaying.iter(&director).collect();
447 assert_eq!(replayed.len(), 0);
448 }
449}