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