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