solverforge_solver/heuristic/move/
composite.rs1use std::fmt::Debug;
12use std::marker::PhantomData;
13
14use solverforge_core::domain::PlanningSolution;
15use solverforge_scoring::Director;
16
17use super::{Move, MoveArena};
18
19pub struct CompositeMove<S, M1, M2>
29where
30 S: PlanningSolution,
31 M1: Move<S>,
32 M2: Move<S>,
33{
34 index_1: usize,
35 index_2: usize,
36 _phantom: PhantomData<(fn() -> S, fn() -> M1, fn() -> M2)>,
37}
38
39impl<S, M1, M2> CompositeMove<S, M1, M2>
40where
41 S: PlanningSolution,
42 M1: Move<S>,
43 M2: Move<S>,
44{
45 pub fn new(index_1: usize, index_2: usize) -> Self {
46 Self {
47 index_1,
48 index_2,
49 _phantom: PhantomData,
50 }
51 }
52
53 pub fn index_1(&self) -> usize {
54 self.index_1
55 }
56
57 pub fn index_2(&self) -> usize {
58 self.index_2
59 }
60
61 pub fn is_doable_with_arenas<D: Director<S>>(
62 &self,
63 arena_1: &MoveArena<M1>,
64 arena_2: &MoveArena<M2>,
65 score_director: &D,
66 ) -> bool {
67 let m1 = arena_1.get(self.index_1);
68 let m2 = arena_2.get(self.index_2);
69
70 match (m1, m2) {
71 (Some(m1), Some(m2)) => m1.is_doable(score_director) || m2.is_doable(score_director),
72 _ => false,
73 }
74 }
75
76 pub fn do_move_with_arenas<D: Director<S>>(
78 &self,
79 arena_1: &MoveArena<M1>,
80 arena_2: &MoveArena<M2>,
81 score_director: &mut D,
82 ) {
83 if let Some(m1) = arena_1.get(self.index_1) {
84 m1.do_move(score_director);
85 }
86 if let Some(m2) = arena_2.get(self.index_2) {
87 m2.do_move(score_director);
88 }
89 }
90}
91
92impl<S, M1, M2> Clone for CompositeMove<S, M1, M2>
93where
94 S: PlanningSolution,
95 M1: Move<S>,
96 M2: Move<S>,
97{
98 fn clone(&self) -> Self {
99 *self
100 }
101}
102
103impl<S, M1, M2> Copy for CompositeMove<S, M1, M2>
104where
105 S: PlanningSolution,
106 M1: Move<S>,
107 M2: Move<S>,
108{
109}
110
111impl<S, M1, M2> Debug for CompositeMove<S, M1, M2>
112where
113 S: PlanningSolution,
114 M1: Move<S>,
115 M2: Move<S>,
116{
117 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
118 f.debug_struct("CompositeMove")
119 .field("index_1", &self.index_1)
120 .field("index_2", &self.index_2)
121 .finish()
122 }
123}