solverforge_solver/heuristic/selector/
list_swap.rs1use std::fmt::Debug;
58use std::marker::PhantomData;
59
60use solverforge_core::domain::PlanningSolution;
61use solverforge_scoring::Director;
62
63use crate::heuristic::r#move::{ListMoveImpl, ListSwapMove};
64
65use super::entity::EntitySelector;
66use super::typed_move_selector::MoveSelector;
67
68pub struct ListSwapMoveSelector<S, V, ES> {
79 entity_selector: ES,
80 list_len: fn(&S, usize) -> usize,
81 list_get: fn(&S, usize, usize) -> Option<V>,
82 list_set: fn(&mut S, usize, usize, V),
83 variable_name: &'static str,
84 descriptor_index: usize,
85 _phantom: PhantomData<(fn() -> S, fn() -> V)>,
86}
87
88impl<S, V: Debug, ES: Debug> Debug for ListSwapMoveSelector<S, V, ES> {
89 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90 f.debug_struct("ListSwapMoveSelector")
91 .field("entity_selector", &self.entity_selector)
92 .field("variable_name", &self.variable_name)
93 .field("descriptor_index", &self.descriptor_index)
94 .finish()
95 }
96}
97
98impl<S, V, ES> ListSwapMoveSelector<S, V, ES> {
99 pub fn new(
109 entity_selector: ES,
110 list_len: fn(&S, usize) -> usize,
111 list_get: fn(&S, usize, usize) -> Option<V>,
112 list_set: fn(&mut S, usize, usize, V),
113 variable_name: &'static str,
114 descriptor_index: usize,
115 ) -> Self {
116 Self {
117 entity_selector,
118 list_len,
119 list_get,
120 list_set,
121 variable_name,
122 descriptor_index,
123 _phantom: PhantomData,
124 }
125 }
126}
127
128impl<S, V, ES> MoveSelector<S, ListSwapMove<S, V>> for ListSwapMoveSelector<S, V, ES>
129where
130 S: PlanningSolution,
131 V: Clone + PartialEq + Send + Sync + Debug + 'static,
132 ES: EntitySelector<S>,
133{
134 fn iter_moves<'a, D: Director<S>>(
135 &'a self,
136 score_director: &'a D,
137 ) -> impl Iterator<Item = ListSwapMove<S, V>> + 'a {
138 let solution = score_director.working_solution();
139 let list_len = self.list_len;
140 let list_get = self.list_get;
141 let list_set = self.list_set;
142 let variable_name = self.variable_name;
143 let descriptor_index = self.descriptor_index;
144
145 let entities: Vec<usize> = self
146 .entity_selector
147 .iter(score_director)
148 .map(|r| r.entity_index)
149 .collect();
150
151 let route_lens: Vec<usize> = entities.iter().map(|&e| list_len(solution, e)).collect();
152
153 let mut moves = Vec::new();
154
155 for (i, &entity_a) in entities.iter().enumerate() {
156 let len_a = route_lens[i];
157 if len_a == 0 {
158 continue;
159 }
160
161 for pos_a in 0..len_a {
163 for pos_b in pos_a + 1..len_a {
164 moves.push(ListSwapMove::new(
165 entity_a,
166 pos_a,
167 entity_a,
168 pos_b,
169 list_len,
170 list_get,
171 list_set,
172 variable_name,
173 descriptor_index,
174 ));
175 }
176 }
177
178 for (j, &entity_b) in entities.iter().enumerate() {
180 if j <= i {
181 continue;
182 }
183 let len_b = route_lens[j];
184 if len_b == 0 {
185 continue;
186 }
187
188 for pos_a in 0..len_a {
189 for pos_b in 0..len_b {
190 moves.push(ListSwapMove::new(
191 entity_a,
192 pos_a,
193 entity_b,
194 pos_b,
195 list_len,
196 list_get,
197 list_set,
198 variable_name,
199 descriptor_index,
200 ));
201 }
202 }
203 }
204 }
205
206 moves.into_iter()
207 }
208
209 fn size<D: Director<S>>(&self, score_director: &D) -> usize {
210 let solution = score_director.working_solution();
211 let list_len = self.list_len;
212
213 let entities: Vec<usize> = self
214 .entity_selector
215 .iter(score_director)
216 .map(|r| r.entity_index)
217 .collect();
218
219 let route_lens: Vec<usize> = entities.iter().map(|&e| list_len(solution, e)).collect();
220 let n = entities.len();
221 if n == 0 {
222 return 0;
223 }
224
225 let intra: usize = route_lens
228 .iter()
229 .map(|&m| m * m.saturating_sub(1) / 2)
230 .sum();
231 let inter: usize = (0..n)
232 .flat_map(|i| (i + 1..n).map(move |j| (i, j)))
233 .map(|(i, j)| route_lens[i] * route_lens[j])
234 .sum();
235 intra + inter
236 }
237}
238
239pub struct ListMoveListSwapSelector<S, V, ES> {
241 inner: ListSwapMoveSelector<S, V, ES>,
242}
243
244impl<S, V: Debug, ES: Debug> Debug for ListMoveListSwapSelector<S, V, ES> {
245 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
246 f.debug_struct("ListMoveListSwapSelector")
247 .field("inner", &self.inner)
248 .finish()
249 }
250}
251
252impl<S, V, ES> ListMoveListSwapSelector<S, V, ES> {
253 pub fn new(inner: ListSwapMoveSelector<S, V, ES>) -> Self {
255 Self { inner }
256 }
257}
258
259impl<S, V, ES> MoveSelector<S, ListMoveImpl<S, V>> for ListMoveListSwapSelector<S, V, ES>
260where
261 S: PlanningSolution,
262 V: Clone + PartialEq + Send + Sync + Debug + 'static,
263 ES: EntitySelector<S>,
264{
265 fn iter_moves<'a, D: Director<S>>(
266 &'a self,
267 score_director: &'a D,
268 ) -> impl Iterator<Item = ListMoveImpl<S, V>> + 'a {
269 self.inner
270 .iter_moves(score_director)
271 .map(ListMoveImpl::ListSwap)
272 }
273
274 fn size<D: Director<S>>(&self, score_director: &D) -> usize {
275 self.inner.size(score_director)
276 }
277}