solverforge_solver/heuristic/move/
list_union.rs1use std::fmt::Debug;
8
9use solverforge_core::domain::PlanningSolution;
10use solverforge_scoring::Director;
11
12use super::{
13 KOptMove, ListChangeMove, ListReverseMove, ListRuinMove, ListSwapMove, Move, MoveTabuSignature,
14 SublistChangeMove, SublistSwapMove,
15};
16
17#[allow(clippy::large_enum_variant)]
31pub enum ListMoveUnion<S, V> {
32 ListChange(ListChangeMove<S, V>),
33 ListSwap(ListSwapMove<S, V>),
34 SublistChange(SublistChangeMove<S, V>),
35 SublistSwap(SublistSwapMove<S, V>),
36 ListReverse(ListReverseMove<S, V>),
37 KOpt(KOptMove<S, V>),
38 ListRuin(ListRuinMove<S, V>),
39}
40
41pub enum ListMoveUnionUndo<S, V>
42where
43 S: PlanningSolution,
44 V: Clone + PartialEq + Send + Sync + Debug + 'static,
45{
46 ListChange(<ListChangeMove<S, V> as Move<S>>::Undo),
47 ListSwap(<ListSwapMove<S, V> as Move<S>>::Undo),
48 SublistChange(<SublistChangeMove<S, V> as Move<S>>::Undo),
49 SublistSwap(<SublistSwapMove<S, V> as Move<S>>::Undo),
50 ListReverse(<ListReverseMove<S, V> as Move<S>>::Undo),
51 KOpt(<KOptMove<S, V> as Move<S>>::Undo),
52 ListRuin(<ListRuinMove<S, V> as Move<S>>::Undo),
53}
54
55impl<S, V> Clone for ListMoveUnion<S, V>
56where
57 S: PlanningSolution,
58 V: Clone + PartialEq + Send + Sync + Debug + 'static,
59{
60 fn clone(&self) -> Self {
61 match self {
62 Self::ListChange(m) => Self::ListChange(*m),
63 Self::ListSwap(m) => Self::ListSwap(*m),
64 Self::SublistChange(m) => Self::SublistChange(*m),
65 Self::SublistSwap(m) => Self::SublistSwap(*m),
66 Self::ListReverse(m) => Self::ListReverse(*m),
67 Self::KOpt(m) => Self::KOpt(m.clone()),
68 Self::ListRuin(m) => Self::ListRuin(m.clone()),
69 }
70 }
71}
72
73impl<S, V> Debug for ListMoveUnion<S, V>
74where
75 S: PlanningSolution,
76 V: Clone + PartialEq + Send + Sync + Debug + 'static,
77{
78 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79 match self {
80 Self::ListChange(m) => m.fmt(f),
81 Self::ListSwap(m) => m.fmt(f),
82 Self::SublistChange(m) => m.fmt(f),
83 Self::SublistSwap(m) => m.fmt(f),
84 Self::ListReverse(m) => m.fmt(f),
85 Self::KOpt(m) => m.fmt(f),
86 Self::ListRuin(m) => m.fmt(f),
87 }
88 }
89}
90
91impl<S, V> Move<S> for ListMoveUnion<S, V>
92where
93 S: PlanningSolution,
94 V: Clone + PartialEq + Send + Sync + Debug + 'static,
95{
96 type Undo = ListMoveUnionUndo<S, V>;
97
98 fn is_doable<D: Director<S>>(&self, score_director: &D) -> bool {
99 match self {
100 Self::ListChange(m) => m.is_doable(score_director),
101 Self::ListSwap(m) => m.is_doable(score_director),
102 Self::SublistChange(m) => m.is_doable(score_director),
103 Self::SublistSwap(m) => m.is_doable(score_director),
104 Self::ListReverse(m) => m.is_doable(score_director),
105 Self::KOpt(m) => m.is_doable(score_director),
106 Self::ListRuin(m) => m.is_doable(score_director),
107 }
108 }
109
110 fn do_move<D: Director<S>>(&self, score_director: &mut D) -> Self::Undo {
111 match self {
112 Self::ListChange(m) => {
113 m.do_move(score_director);
114 ListMoveUnionUndo::ListChange(())
115 }
116 Self::ListSwap(m) => {
117 m.do_move(score_director);
118 ListMoveUnionUndo::ListSwap(())
119 }
120 Self::SublistChange(m) => {
121 m.do_move(score_director);
122 ListMoveUnionUndo::SublistChange(())
123 }
124 Self::SublistSwap(m) => {
125 m.do_move(score_director);
126 ListMoveUnionUndo::SublistSwap(())
127 }
128 Self::ListReverse(m) => {
129 m.do_move(score_director);
130 ListMoveUnionUndo::ListReverse(())
131 }
132 Self::KOpt(m) => ListMoveUnionUndo::KOpt(m.do_move(score_director)),
133 Self::ListRuin(m) => ListMoveUnionUndo::ListRuin(m.do_move(score_director)),
134 }
135 }
136
137 fn undo_move<D: Director<S>>(&self, score_director: &mut D, undo: Self::Undo) {
138 match (self, undo) {
139 (Self::ListChange(m), ListMoveUnionUndo::ListChange(undo)) => {
140 m.undo_move(score_director, undo)
141 }
142 (Self::ListSwap(m), ListMoveUnionUndo::ListSwap(undo)) => {
143 m.undo_move(score_director, undo)
144 }
145 (Self::SublistChange(m), ListMoveUnionUndo::SublistChange(undo)) => {
146 m.undo_move(score_director, undo)
147 }
148 (Self::SublistSwap(m), ListMoveUnionUndo::SublistSwap(undo)) => {
149 m.undo_move(score_director, undo)
150 }
151 (Self::ListReverse(m), ListMoveUnionUndo::ListReverse(undo)) => {
152 m.undo_move(score_director, undo)
153 }
154 (Self::KOpt(m), ListMoveUnionUndo::KOpt(undo)) => m.undo_move(score_director, undo),
155 (Self::ListRuin(m), ListMoveUnionUndo::ListRuin(undo)) => {
156 m.undo_move(score_director, undo)
157 }
158 _ => panic!("list move undo shape must match move shape"),
159 }
160 }
161
162 fn descriptor_index(&self) -> usize {
163 match self {
164 Self::ListChange(m) => m.descriptor_index(),
165 Self::ListSwap(m) => m.descriptor_index(),
166 Self::SublistChange(m) => m.descriptor_index(),
167 Self::SublistSwap(m) => m.descriptor_index(),
168 Self::ListReverse(m) => m.descriptor_index(),
169 Self::KOpt(m) => m.descriptor_index(),
170 Self::ListRuin(m) => m.descriptor_index(),
171 }
172 }
173
174 fn entity_indices(&self) -> &[usize] {
175 match self {
176 Self::ListChange(m) => m.entity_indices(),
177 Self::ListSwap(m) => m.entity_indices(),
178 Self::SublistChange(m) => m.entity_indices(),
179 Self::SublistSwap(m) => m.entity_indices(),
180 Self::ListReverse(m) => m.entity_indices(),
181 Self::KOpt(m) => m.entity_indices(),
182 Self::ListRuin(m) => m.entity_indices(),
183 }
184 }
185
186 fn variable_name(&self) -> &str {
187 match self {
188 Self::ListChange(m) => m.variable_name(),
189 Self::ListSwap(m) => m.variable_name(),
190 Self::SublistChange(m) => m.variable_name(),
191 Self::SublistSwap(m) => m.variable_name(),
192 Self::ListReverse(m) => m.variable_name(),
193 Self::KOpt(m) => m.variable_name(),
194 Self::ListRuin(m) => m.variable_name(),
195 }
196 }
197
198 fn tabu_signature<D: Director<S>>(&self, score_director: &D) -> MoveTabuSignature {
199 match self {
200 Self::ListChange(m) => m.tabu_signature(score_director),
201 Self::ListSwap(m) => m.tabu_signature(score_director),
202 Self::SublistChange(m) => m.tabu_signature(score_director),
203 Self::SublistSwap(m) => m.tabu_signature(score_director),
204 Self::ListReverse(m) => m.tabu_signature(score_director),
205 Self::KOpt(m) => m.tabu_signature(score_director),
206 Self::ListRuin(m) => m.tabu_signature(score_director),
207 }
208 }
209}