solverforge_solver/heuristic/selector/
mimic.rs1use std::fmt::Debug;
15use std::sync::{Arc, Mutex};
16
17use solverforge_core::domain::PlanningSolution;
18use solverforge_scoring::Director;
19
20use super::entity::{EntityReference, EntitySelector};
21
22#[derive(Debug, Default, Clone, Copy)]
30struct MimicState {
31 has_next_recorded: bool,
33 has_next: bool,
35 next_recorded: bool,
37 recorded_entity: Option<EntityReference>,
39}
40
41#[derive(Clone)]
43pub struct MimicRecorder {
44 shared: Arc<Mutex<MimicState>>,
45 id: String,
47}
48
49impl MimicRecorder {
50 pub fn new(id: impl Into<String>) -> Self {
51 Self {
52 shared: Arc::new(Mutex::new(MimicState::default())),
53 id: id.into(),
54 }
55 }
56
57 fn record_has_next(&self, has_next: bool) {
59 *self.shared.lock().unwrap() = MimicState {
60 has_next_recorded: true,
61 has_next,
62 next_recorded: false,
63 recorded_entity: None,
64 };
65 }
66
67 fn record_next(&self, entity: EntityReference) {
69 *self.shared.lock().unwrap() = MimicState {
70 has_next_recorded: true,
71 has_next: true,
72 next_recorded: true,
73 recorded_entity: Some(entity),
74 };
75 }
76
77 pub fn get_has_next(&self) -> Option<bool> {
78 let state = self.shared.lock().unwrap();
79 if state.has_next_recorded {
80 Some(state.has_next)
81 } else {
82 None
83 }
84 }
85
86 pub fn get_recorded_entity(&self) -> Option<EntityReference> {
87 let state = self.shared.lock().unwrap();
88 if state.next_recorded {
89 state.recorded_entity
90 } else {
91 None
92 }
93 }
94
95 pub fn id(&self) -> &str {
96 &self.id
97 }
98
99 pub fn reset(&self) {
101 *self.shared.lock().unwrap() = MimicState::default();
102 }
103}
104
105impl Debug for MimicRecorder {
106 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107 f.debug_struct("MimicRecorder")
108 .field("id", &self.id)
109 .field("state", &*self.shared.lock().unwrap())
110 .finish()
111 }
112}
113
114pub struct MimicRecordingEntitySelector<S, ES> {
125 child: ES,
127 recorder: MimicRecorder,
129 _phantom: std::marker::PhantomData<fn() -> S>,
131}
132
133impl<S, ES> MimicRecordingEntitySelector<S, ES> {
134 pub fn new(child: ES, recorder: MimicRecorder) -> Self {
135 Self {
136 child,
137 recorder,
138 _phantom: std::marker::PhantomData,
139 }
140 }
141
142 pub fn recorder(&self) -> MimicRecorder {
143 self.recorder.clone()
144 }
145}
146
147impl<S: PlanningSolution, ES: Debug> Debug for MimicRecordingEntitySelector<S, ES> {
148 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
149 f.debug_struct("MimicRecordingEntitySelector")
150 .field("child", &self.child)
151 .field("recorder_id", &self.recorder.id)
152 .finish()
153 }
154}
155
156impl<S, ES> EntitySelector<S> for MimicRecordingEntitySelector<S, ES>
157where
158 S: PlanningSolution,
159 ES: EntitySelector<S>,
160{
161 fn iter<'a, D: Director<S>>(
162 &'a self,
163 score_director: &D,
164 ) -> impl Iterator<Item = EntityReference> + 'a {
165 self.recorder.reset();
167
168 let child_iter = self.child.iter(score_director);
169 RecordingIterator {
170 inner: child_iter,
171 recorder: &self.recorder,
172 }
173 }
174
175 fn size<D: Director<S>>(&self, score_director: &D) -> usize {
176 self.child.size(score_director)
177 }
178
179 fn is_never_ending(&self) -> bool {
180 self.child.is_never_ending()
181 }
182}
183
184struct RecordingIterator<'a, I> {
186 inner: I,
187 recorder: &'a MimicRecorder,
188}
189
190impl<'a, I: Iterator<Item = EntityReference>> Iterator for RecordingIterator<'a, I> {
191 type Item = EntityReference;
192
193 fn next(&mut self) -> Option<Self::Item> {
194 let next = self.inner.next();
195 match next {
196 Some(entity) => {
197 self.recorder.record_next(entity);
198 Some(entity)
199 }
200 None => {
201 self.recorder.record_has_next(false);
202 None
203 }
204 }
205 }
206}
207
208pub struct MimicReplayingEntitySelector {
213 recorder: MimicRecorder,
215}
216
217impl MimicReplayingEntitySelector {
218 pub fn new(recorder: MimicRecorder) -> Self {
219 Self { recorder }
220 }
221}
222
223impl Debug for MimicReplayingEntitySelector {
224 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
225 f.debug_struct("MimicReplayingEntitySelector")
226 .field("recorder_id", &self.recorder.id)
227 .finish()
228 }
229}
230
231impl<S: PlanningSolution> EntitySelector<S> for MimicReplayingEntitySelector {
232 fn iter<'a, D: Director<S>>(
233 &'a self,
234 _score_director: &D,
235 ) -> impl Iterator<Item = EntityReference> + 'a {
236 ReplayingIterator {
237 recorder: &self.recorder,
238 returned: false,
239 }
240 }
241
242 fn size<D: Director<S>>(&self, _score_director: &D) -> usize {
243 if self.recorder.get_recorded_entity().is_some() {
245 1
246 } else {
247 0
248 }
249 }
250
251 fn is_never_ending(&self) -> bool {
252 false
253 }
254}
255
256struct ReplayingIterator<'a> {
258 recorder: &'a MimicRecorder,
259 returned: bool,
260}
261
262impl<'a> Iterator for ReplayingIterator<'a> {
263 type Item = EntityReference;
264
265 fn next(&mut self) -> Option<Self::Item> {
266 if self.returned {
267 return None;
268 }
269
270 match self.recorder.get_recorded_entity() {
272 Some(entity) => {
273 self.returned = true;
274 Some(entity)
275 }
276 None => {
277 match self.recorder.get_has_next() {
279 Some(false) => None, Some(true) => panic!(
281 "MimicReplayingEntitySelector: Recording selector's hasNext() was true \
282 but next() was never called. Ensure the recording selector's iterator \
283 is advanced before using the replaying selector."
284 ),
285 None => panic!(
286 "MimicReplayingEntitySelector: No recording found. \
287 The recording selector must be iterated before the replaying selector."
288 ),
289 }
290 }
291 }
292 }
293}