1use std::fmt::Debug;
8use std::marker::PhantomData;
9
10use solverforge_core::domain::PlanningSolution;
11use solverforge_scoring::Director;
12
13use crate::heuristic::r#move::MoveArena;
14use crate::heuristic::r#move::{ChangeMove, EitherMove, ListMoveImpl, Move, SwapMove};
15
16use super::entity::{EntityReference, EntitySelector, FromSolutionEntitySelector};
17use super::value_selector::{StaticValueSelector, ValueSelector};
18
19pub trait MoveSelector<S: PlanningSolution, M: Move<S>>: Send + Debug {
28 fn iter_moves<'a, D: Director<S>>(
30 &'a self,
31 score_director: &'a D,
32 ) -> impl Iterator<Item = M> + 'a;
33
34 fn size<D: Director<S>>(&self, score_director: &D) -> usize;
35
36 fn append_moves<D: Director<S>>(&self, score_director: &D, arena: &mut MoveArena<M>) {
37 arena.extend(self.iter_moves(score_director));
38 }
39
40 fn is_never_ending(&self) -> bool {
42 false
43 }
44}
45
46pub struct ChangeMoveSelector<S, V, ES, VS> {
50 entity_selector: ES,
51 value_selector: VS,
52 getter: fn(&S, usize) -> Option<V>,
53 setter: fn(&mut S, usize, Option<V>),
54 descriptor_index: usize,
55 variable_name: &'static str,
56 _phantom: PhantomData<(fn() -> S, fn() -> V)>,
57}
58
59impl<S, V: Debug, ES: Debug, VS: Debug> Debug for ChangeMoveSelector<S, V, ES, VS> {
60 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61 f.debug_struct("ChangeMoveSelector")
62 .field("entity_selector", &self.entity_selector)
63 .field("value_selector", &self.value_selector)
64 .field("descriptor_index", &self.descriptor_index)
65 .field("variable_name", &self.variable_name)
66 .finish()
67 }
68}
69
70impl<S: PlanningSolution, V: Clone, ES, VS> ChangeMoveSelector<S, V, ES, VS> {
71 pub fn new(
81 entity_selector: ES,
82 value_selector: VS,
83 getter: fn(&S, usize) -> Option<V>,
84 setter: fn(&mut S, usize, Option<V>),
85 descriptor_index: usize,
86 variable_name: &'static str,
87 ) -> Self {
88 Self {
89 entity_selector,
90 value_selector,
91 getter,
92 setter,
93 descriptor_index,
94 variable_name,
95 _phantom: PhantomData,
96 }
97 }
98}
99
100impl<S: PlanningSolution, V: Clone + Send + Sync + Debug + 'static>
101 ChangeMoveSelector<S, V, FromSolutionEntitySelector, StaticValueSelector<S, V>>
102{
103 pub fn simple(
104 getter: fn(&S, usize) -> Option<V>,
105 setter: fn(&mut S, usize, Option<V>),
106 descriptor_index: usize,
107 variable_name: &'static str,
108 values: Vec<V>,
109 ) -> Self {
110 Self {
111 entity_selector: FromSolutionEntitySelector::new(descriptor_index),
112 value_selector: StaticValueSelector::new(values),
113 getter,
114 setter,
115 descriptor_index,
116 variable_name,
117 _phantom: PhantomData,
118 }
119 }
120}
121
122impl<S, V, ES, VS> MoveSelector<S, ChangeMove<S, V>> for ChangeMoveSelector<S, V, ES, VS>
123where
124 S: PlanningSolution,
125 V: Clone + PartialEq + Send + Sync + Debug + 'static,
126 ES: EntitySelector<S>,
127 VS: ValueSelector<S, V>,
128{
129 fn iter_moves<'a, D: Director<S>>(
130 &'a self,
131 score_director: &'a D,
132 ) -> impl Iterator<Item = ChangeMove<S, V>> + 'a {
133 let descriptor_index = self.descriptor_index;
134 let variable_name = self.variable_name;
135 let getter = self.getter;
136 let setter = self.setter;
137 let value_selector = &self.value_selector;
138
139 self.entity_selector
141 .iter(score_director)
142 .flat_map(move |entity_ref| {
143 value_selector
144 .iter_typed(
145 score_director,
146 entity_ref.descriptor_index,
147 entity_ref.entity_index,
148 )
149 .map(move |value| {
150 ChangeMove::new(
151 entity_ref.entity_index,
152 Some(value),
153 getter,
154 setter,
155 variable_name,
156 descriptor_index,
157 )
158 })
159 })
160 }
161
162 fn size<D: Director<S>>(&self, score_director: &D) -> usize {
163 self.entity_selector
164 .iter(score_director)
165 .map(|entity_ref| {
166 self.value_selector.size(
167 score_director,
168 entity_ref.descriptor_index,
169 entity_ref.entity_index,
170 )
171 })
172 .sum()
173 }
174}
175
176pub struct SwapMoveSelector<S, V, LES, RES> {
180 left_entity_selector: LES,
181 right_entity_selector: RES,
182 getter: fn(&S, usize) -> Option<V>,
184 setter: fn(&mut S, usize, Option<V>),
186 descriptor_index: usize,
187 variable_name: &'static str,
188 _phantom: PhantomData<(fn() -> S, fn() -> V)>,
189}
190
191impl<S, V, LES: Debug, RES: Debug> Debug for SwapMoveSelector<S, V, LES, RES> {
192 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
193 f.debug_struct("SwapMoveSelector")
194 .field("left_entity_selector", &self.left_entity_selector)
195 .field("right_entity_selector", &self.right_entity_selector)
196 .field("descriptor_index", &self.descriptor_index)
197 .field("variable_name", &self.variable_name)
198 .finish()
199 }
200}
201
202impl<S: PlanningSolution, V, LES, RES> SwapMoveSelector<S, V, LES, RES> {
203 pub fn new(
204 left_entity_selector: LES,
205 right_entity_selector: RES,
206 getter: fn(&S, usize) -> Option<V>,
207 setter: fn(&mut S, usize, Option<V>),
208 descriptor_index: usize,
209 variable_name: &'static str,
210 ) -> Self {
211 Self {
212 left_entity_selector,
213 right_entity_selector,
214 getter,
215 setter,
216 descriptor_index,
217 variable_name,
218 _phantom: PhantomData,
219 }
220 }
221}
222
223impl<S: PlanningSolution, V>
224 SwapMoveSelector<S, V, FromSolutionEntitySelector, FromSolutionEntitySelector>
225{
226 pub fn simple(
234 getter: fn(&S, usize) -> Option<V>,
235 setter: fn(&mut S, usize, Option<V>),
236 descriptor_index: usize,
237 variable_name: &'static str,
238 ) -> Self {
239 Self {
240 left_entity_selector: FromSolutionEntitySelector::new(descriptor_index),
241 right_entity_selector: FromSolutionEntitySelector::new(descriptor_index),
242 getter,
243 setter,
244 descriptor_index,
245 variable_name,
246 _phantom: PhantomData,
247 }
248 }
249}
250
251impl<S, V, LES, RES> MoveSelector<S, SwapMove<S, V>> for SwapMoveSelector<S, V, LES, RES>
252where
253 S: PlanningSolution,
254 V: Clone + PartialEq + Send + Sync + Debug + 'static,
255 LES: EntitySelector<S>,
256 RES: EntitySelector<S>,
257{
258 fn iter_moves<'a, D: Director<S>>(
259 &'a self,
260 score_director: &'a D,
261 ) -> impl Iterator<Item = SwapMove<S, V>> + 'a {
262 let descriptor_index = self.descriptor_index;
263 let variable_name = self.variable_name;
264 let getter = self.getter;
265 let setter = self.setter;
266
267 let left_entities: Vec<EntityReference> =
269 self.left_entity_selector.iter(score_director).collect();
270 let right_entities: Vec<EntityReference> =
271 self.right_entity_selector.iter(score_director).collect();
272
273 let mut moves =
275 Vec::with_capacity(left_entities.len() * left_entities.len().saturating_sub(1) / 2);
276 for (i, left) in left_entities.iter().enumerate() {
277 for right in &right_entities[i + 1..] {
278 if left.descriptor_index == right.descriptor_index
279 && left.descriptor_index == descriptor_index
280 {
281 moves.push(SwapMove::new(
282 left.entity_index,
283 right.entity_index,
284 getter,
285 setter,
286 variable_name,
287 descriptor_index,
288 ));
289 }
290 }
291 }
292
293 moves.into_iter()
294 }
295
296 fn size<D: Director<S>>(&self, score_director: &D) -> usize {
297 let left_count = self.left_entity_selector.size(score_director);
298 let right_count = self.right_entity_selector.size(score_director);
299
300 if left_count == right_count {
301 left_count * left_count.saturating_sub(1) / 2
302 } else {
303 left_count * right_count / 2
304 }
305 }
306}
307
308pub struct EitherChangeMoveSelector<S, V, ES, VS> {
315 inner: ChangeMoveSelector<S, V, ES, VS>,
316}
317
318impl<S, V: Debug, ES: Debug, VS: Debug> Debug for EitherChangeMoveSelector<S, V, ES, VS> {
319 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
320 f.debug_struct("EitherChangeMoveSelector")
321 .field("inner", &self.inner)
322 .finish()
323 }
324}
325
326impl<S: PlanningSolution, V: Clone + Send + Sync + Debug + 'static>
327 EitherChangeMoveSelector<S, V, FromSolutionEntitySelector, StaticValueSelector<S, V>>
328{
329 pub fn simple(
330 getter: fn(&S, usize) -> Option<V>,
331 setter: fn(&mut S, usize, Option<V>),
332 descriptor_index: usize,
333 variable_name: &'static str,
334 values: Vec<V>,
335 ) -> Self {
336 Self {
337 inner: ChangeMoveSelector::simple(
338 getter,
339 setter,
340 descriptor_index,
341 variable_name,
342 values,
343 ),
344 }
345 }
346}
347
348impl<S, V, ES, VS> MoveSelector<S, EitherMove<S, V>> for EitherChangeMoveSelector<S, V, ES, VS>
349where
350 S: PlanningSolution,
351 V: Clone + PartialEq + Send + Sync + Debug + 'static,
352 ES: EntitySelector<S>,
353 VS: ValueSelector<S, V>,
354{
355 fn iter_moves<'a, D: Director<S>>(
356 &'a self,
357 score_director: &'a D,
358 ) -> impl Iterator<Item = EitherMove<S, V>> + 'a {
359 self.inner
360 .iter_moves(score_director)
361 .map(EitherMove::Change)
362 }
363
364 fn size<D: Director<S>>(&self, score_director: &D) -> usize {
365 self.inner.size(score_director)
366 }
367}
368
369pub struct EitherSwapMoveSelector<S, V, LES, RES> {
371 inner: SwapMoveSelector<S, V, LES, RES>,
372}
373
374impl<S, V: Debug, LES: Debug, RES: Debug> Debug for EitherSwapMoveSelector<S, V, LES, RES> {
375 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
376 f.debug_struct("EitherSwapMoveSelector")
377 .field("inner", &self.inner)
378 .finish()
379 }
380}
381
382impl<S: PlanningSolution, V>
383 EitherSwapMoveSelector<S, V, FromSolutionEntitySelector, FromSolutionEntitySelector>
384{
385 pub fn simple(
386 getter: fn(&S, usize) -> Option<V>,
387 setter: fn(&mut S, usize, Option<V>),
388 descriptor_index: usize,
389 variable_name: &'static str,
390 ) -> Self {
391 Self {
392 inner: SwapMoveSelector::simple(getter, setter, descriptor_index, variable_name),
393 }
394 }
395}
396
397impl<S, V, LES, RES> MoveSelector<S, EitherMove<S, V>> for EitherSwapMoveSelector<S, V, LES, RES>
398where
399 S: PlanningSolution,
400 V: Clone + PartialEq + Send + Sync + Debug + 'static,
401 LES: EntitySelector<S>,
402 RES: EntitySelector<S>,
403{
404 fn iter_moves<'a, D: Director<S>>(
405 &'a self,
406 score_director: &'a D,
407 ) -> impl Iterator<Item = EitherMove<S, V>> + 'a {
408 self.inner.iter_moves(score_director).map(EitherMove::Swap)
409 }
410
411 fn size<D: Director<S>>(&self, score_director: &D) -> usize {
412 self.inner.size(score_director)
413 }
414}
415
416use super::k_opt::{KOptMoveSelector, ListPositionDistanceMeter, NearbyKOptMoveSelector};
422use super::list_change::ListChangeMoveSelector;
423use super::list_ruin::ListRuinMoveSelector;
424
425pub struct ListMoveListChangeSelector<S, V, ES> {
427 inner: ListChangeMoveSelector<S, V, ES>,
428}
429
430impl<S, V: Debug, ES: Debug> Debug for ListMoveListChangeSelector<S, V, ES> {
431 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
432 f.debug_struct("ListMoveListChangeSelector")
433 .field("inner", &self.inner)
434 .finish()
435 }
436}
437
438impl<S, V, ES> ListMoveListChangeSelector<S, V, ES> {
439 pub fn new(inner: ListChangeMoveSelector<S, V, ES>) -> Self {
441 Self { inner }
442 }
443}
444
445impl<S, V, ES> MoveSelector<S, ListMoveImpl<S, V>> for ListMoveListChangeSelector<S, V, ES>
446where
447 S: PlanningSolution,
448 V: Clone + PartialEq + Send + Sync + Debug + 'static,
449 ES: EntitySelector<S>,
450{
451 fn iter_moves<'a, D: Director<S>>(
452 &'a self,
453 score_director: &'a D,
454 ) -> impl Iterator<Item = ListMoveImpl<S, V>> + 'a {
455 self.inner
456 .iter_moves(score_director)
457 .map(ListMoveImpl::ListChange)
458 }
459
460 fn size<D: Director<S>>(&self, score_director: &D) -> usize {
461 self.inner.size(score_director)
462 }
463}
464
465pub struct ListMoveKOptSelector<S, V, ES> {
467 inner: KOptMoveSelector<S, V, ES>,
468}
469
470impl<S, V: Debug, ES: Debug> Debug for ListMoveKOptSelector<S, V, ES> {
471 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
472 f.debug_struct("ListMoveKOptSelector")
473 .field("inner", &self.inner)
474 .finish()
475 }
476}
477
478impl<S, V, ES> ListMoveKOptSelector<S, V, ES> {
479 pub fn new(inner: KOptMoveSelector<S, V, ES>) -> Self {
481 Self { inner }
482 }
483}
484
485impl<S, V, ES> MoveSelector<S, ListMoveImpl<S, V>> for ListMoveKOptSelector<S, V, ES>
486where
487 S: PlanningSolution,
488 V: Clone + PartialEq + Send + Sync + Debug + 'static,
489 ES: EntitySelector<S>,
490{
491 fn iter_moves<'a, D: Director<S>>(
492 &'a self,
493 score_director: &'a D,
494 ) -> impl Iterator<Item = ListMoveImpl<S, V>> + 'a {
495 self.inner
496 .iter_moves(score_director)
497 .map(ListMoveImpl::KOpt)
498 }
499
500 fn size<D: Director<S>>(&self, score_director: &D) -> usize {
501 self.inner.size(score_director)
502 }
503}
504
505pub struct ListMoveNearbyKOptSelector<S, V, D: ListPositionDistanceMeter<S>, ES> {
507 inner: NearbyKOptMoveSelector<S, V, D, ES>,
508}
509
510impl<S, V: Debug, D: ListPositionDistanceMeter<S>, ES: Debug> Debug
511 for ListMoveNearbyKOptSelector<S, V, D, ES>
512{
513 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
514 f.debug_struct("ListMoveNearbyKOptSelector")
515 .field("inner", &self.inner)
516 .finish()
517 }
518}
519
520impl<S, V, D: ListPositionDistanceMeter<S>, ES> ListMoveNearbyKOptSelector<S, V, D, ES> {
521 pub fn new(inner: NearbyKOptMoveSelector<S, V, D, ES>) -> Self {
523 Self { inner }
524 }
525}
526
527impl<S, V, D, ES> MoveSelector<S, ListMoveImpl<S, V>> for ListMoveNearbyKOptSelector<S, V, D, ES>
528where
529 S: PlanningSolution,
530 V: Clone + PartialEq + Send + Sync + Debug + 'static,
531 D: ListPositionDistanceMeter<S> + 'static,
532 ES: EntitySelector<S>,
533{
534 fn iter_moves<'a, Dir: Director<S>>(
535 &'a self,
536 score_director: &'a Dir,
537 ) -> impl Iterator<Item = ListMoveImpl<S, V>> + 'a {
538 self.inner
539 .iter_moves(score_director)
540 .map(ListMoveImpl::KOpt)
541 }
542
543 fn size<Dir: Director<S>>(&self, score_director: &Dir) -> usize {
544 self.inner.size(score_director)
545 }
546}
547
548pub struct ListMoveListRuinSelector<S, V> {
550 inner: ListRuinMoveSelector<S, V>,
551}
552
553impl<S, V: Debug> Debug for ListMoveListRuinSelector<S, V> {
554 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
555 f.debug_struct("ListMoveListRuinSelector")
556 .field("inner", &self.inner)
557 .finish()
558 }
559}
560
561impl<S, V> ListMoveListRuinSelector<S, V> {
562 pub fn new(inner: ListRuinMoveSelector<S, V>) -> Self {
564 Self { inner }
565 }
566}
567
568impl<S, V> MoveSelector<S, ListMoveImpl<S, V>> for ListMoveListRuinSelector<S, V>
569where
570 S: PlanningSolution,
571 V: Clone + PartialEq + Send + Sync + Debug + 'static,
572{
573 fn iter_moves<'a, D: Director<S>>(
574 &'a self,
575 score_director: &'a D,
576 ) -> impl Iterator<Item = ListMoveImpl<S, V>> + 'a {
577 self.inner
578 .iter_moves(score_director)
579 .map(ListMoveImpl::ListRuin)
580 }
581
582 fn size<D: Director<S>>(&self, score_director: &D) -> usize {
583 self.inner.size(score_director)
584 }
585}
586
587#[cfg(test)]
594#[path = "move_selector_tests.rs"]
595mod tests;