solverforge_solver/heuristic/move/
list_reverse.rs1use std::fmt::Debug;
12use std::marker::PhantomData;
13
14use solverforge_core::domain::PlanningSolution;
15use solverforge_scoring::Director;
16
17use super::list_kernel::{
18 reverse_candidate_trace_identity, reverse_do_move, reverse_is_doable, reverse_tabu_signature,
19 ReverseCoordinates, StaticListReverseAccess,
20};
21use super::{Move, MoveTabuSignature};
22
23pub struct ListReverseMove<S, V> {
62 entity_index: usize,
64 start: usize,
66 end: usize,
68 list_len: fn(&S, usize) -> usize,
69 list_get: fn(&S, usize, usize) -> Option<V>,
70 list_reverse: fn(&mut S, usize, usize, usize),
72 variable_name: &'static str,
73 descriptor_index: usize,
74 _phantom: PhantomData<fn() -> V>,
75}
76
77impl<S, V> Clone for ListReverseMove<S, V> {
78 fn clone(&self) -> Self {
79 *self
80 }
81}
82
83impl<S, V> Copy for ListReverseMove<S, V> {}
84
85impl<S, V: Debug> Debug for ListReverseMove<S, V> {
86 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87 f.debug_struct("ListReverseMove")
88 .field("entity", &self.entity_index)
89 .field("range", &(self.start..self.end))
90 .field("variable_name", &self.variable_name)
91 .finish()
92 }
93}
94
95impl<S, V> ListReverseMove<S, V> {
96 #[allow(clippy::too_many_arguments)]
108 pub fn new(
109 entity_index: usize,
110 start: usize,
111 end: usize,
112 list_len: fn(&S, usize) -> usize,
113 list_get: fn(&S, usize, usize) -> Option<V>,
114 list_reverse: fn(&mut S, usize, usize, usize),
115 variable_name: &'static str,
116 descriptor_index: usize,
117 ) -> Self {
118 Self {
119 entity_index,
120 start,
121 end,
122 list_len,
123 list_get,
124 list_reverse,
125 variable_name,
126 descriptor_index,
127 _phantom: PhantomData,
128 }
129 }
130
131 pub fn entity_index(&self) -> usize {
132 self.entity_index
133 }
134
135 pub fn start(&self) -> usize {
136 self.start
137 }
138
139 pub fn end(&self) -> usize {
140 self.end
141 }
142
143 pub fn segment_len(&self) -> usize {
144 self.end.saturating_sub(self.start)
145 }
146
147 fn access(&self) -> StaticListReverseAccess<S, V> {
148 StaticListReverseAccess {
149 list_len: self.list_len,
150 list_get: self.list_get,
151 list_reverse: self.list_reverse,
152 variable_name: self.variable_name,
153 descriptor_index: self.descriptor_index,
154 }
155 }
156
157 fn coordinates(&self) -> ReverseCoordinates {
158 ReverseCoordinates {
159 entity: self.entity_index,
160 start: self.start,
161 end: self.end,
162 }
163 }
164}
165
166impl<S, V> Move<S> for ListReverseMove<S, V>
167where
168 S: PlanningSolution,
169 V: Clone + Send + Sync + Debug + 'static,
170{
171 type Undo = ();
172
173 fn is_doable<D: Director<S>>(&self, score_director: &D) -> bool {
174 reverse_is_doable(&self.access(), self.coordinates(), score_director)
175 }
176
177 fn do_move<D: Director<S>>(&self, score_director: &mut D) -> Self::Undo {
178 reverse_do_move(&self.access(), self.coordinates(), score_director);
179 }
180
181 fn undo_move<D: Director<S>>(&self, score_director: &mut D, (): Self::Undo) {
182 self.do_move(score_director);
183 }
184
185 fn descriptor_index(&self) -> usize {
186 self.descriptor_index
187 }
188
189 fn entity_indices(&self) -> &[usize] {
190 std::slice::from_ref(&self.entity_index)
191 }
192
193 fn variable_name(&self) -> &str {
194 self.variable_name
195 }
196
197 fn telemetry_label(&self) -> &'static str {
198 "list_reverse"
199 }
200
201 fn tabu_signature<D: Director<S>>(&self, score_director: &D) -> MoveTabuSignature {
202 reverse_tabu_signature(&self.access(), self.coordinates(), score_director)
203 }
204
205 fn candidate_trace_identity(&self) -> Option<crate::stats::CandidateTraceIdentity> {
206 Some(reverse_candidate_trace_identity(
207 &self.access(),
208 self.coordinates(),
209 ))
210 }
211}