1use std::fmt;
2use std::marker::PhantomData;
3
4use crate::heuristic::selector::k_opt::ListPositionDistanceMeter;
5use crate::heuristic::selector::nearby_list_change::CrossEntityDistanceMeter;
6
7pub struct IntraDistanceAdapter<T>(pub T);
8
9impl<S, T: CrossEntityDistanceMeter<S>> ListPositionDistanceMeter<S> for IntraDistanceAdapter<T> {
10 fn distance(&self, solution: &S, entity_idx: usize, pos_a: usize, pos_b: usize) -> f64 {
11 self.0
12 .distance(solution, entity_idx, pos_a, entity_idx, pos_b)
13 }
14}
15
16pub struct ListVariableSlot<S, V, DM, IDM> {
17 pub entity_type_name: &'static str,
18 pub element_count: fn(&S) -> usize,
19 pub assigned_elements: fn(&S) -> Vec<V>,
20 pub list_len: fn(&S, usize) -> usize,
21 pub list_remove: fn(&mut S, usize, usize) -> Option<V>,
22 pub construction_list_remove: fn(&mut S, usize, usize) -> V,
23 pub list_insert: fn(&mut S, usize, usize, V),
24 pub list_get: fn(&S, usize, usize) -> Option<V>,
25 pub list_set: fn(&mut S, usize, usize, V),
26 pub list_reverse: fn(&mut S, usize, usize, usize),
27 pub sublist_remove: fn(&mut S, usize, usize, usize) -> Vec<V>,
28 pub sublist_insert: fn(&mut S, usize, usize, Vec<V>),
29 pub ruin_remove: fn(&mut S, usize, usize) -> V,
30 pub ruin_insert: fn(&mut S, usize, usize, V),
31 pub index_to_element: fn(&S, usize) -> V,
32 pub entity_count: fn(&S) -> usize,
33 pub cross_distance_meter: DM,
34 pub intra_distance_meter: IDM,
35 pub variable_name: &'static str,
36 pub descriptor_index: usize,
37 pub route_get_fn: Option<fn(&S, usize) -> Vec<usize>>,
38 pub route_set_fn: Option<fn(&mut S, usize, Vec<usize>)>,
39 pub route_depot_fn: Option<fn(&S, usize) -> usize>,
40 pub route_distance_fn: Option<fn(&S, usize, usize, usize) -> i64>,
41 pub route_feasible_fn: Option<fn(&S, usize, &[usize]) -> bool>,
42 pub savings_depot_fn: Option<fn(&S, usize) -> usize>,
43 pub savings_metric_class_fn: Option<fn(&S, usize) -> usize>,
44 pub savings_distance_fn: Option<fn(&S, usize, usize, usize) -> i64>,
45 pub savings_feasible_fn: Option<fn(&S, usize, &[usize]) -> bool>,
46 pub element_owner_fn: Option<fn(&S, &V) -> Option<usize>>,
47 pub construction_element_order_key: Option<fn(&S, V) -> i64>,
48 pub precedence_duration_fn: Option<fn(&S, V) -> usize>,
49 pub precedence_successors_fn: Option<fn(&S, V, &mut Vec<V>)>,
50 _phantom: PhantomData<(fn() -> S, fn() -> V)>,
51}
52
53impl<S, V, DM: Clone, IDM: Clone> Clone for ListVariableSlot<S, V, DM, IDM> {
54 fn clone(&self) -> Self {
55 Self {
56 entity_type_name: self.entity_type_name,
57 element_count: self.element_count,
58 assigned_elements: self.assigned_elements,
59 list_len: self.list_len,
60 list_remove: self.list_remove,
61 construction_list_remove: self.construction_list_remove,
62 list_insert: self.list_insert,
63 list_get: self.list_get,
64 list_set: self.list_set,
65 list_reverse: self.list_reverse,
66 sublist_remove: self.sublist_remove,
67 sublist_insert: self.sublist_insert,
68 ruin_remove: self.ruin_remove,
69 ruin_insert: self.ruin_insert,
70 index_to_element: self.index_to_element,
71 entity_count: self.entity_count,
72 cross_distance_meter: self.cross_distance_meter.clone(),
73 intra_distance_meter: self.intra_distance_meter.clone(),
74 variable_name: self.variable_name,
75 descriptor_index: self.descriptor_index,
76 route_get_fn: self.route_get_fn,
77 route_set_fn: self.route_set_fn,
78 route_depot_fn: self.route_depot_fn,
79 route_distance_fn: self.route_distance_fn,
80 route_feasible_fn: self.route_feasible_fn,
81 savings_depot_fn: self.savings_depot_fn,
82 savings_metric_class_fn: self.savings_metric_class_fn,
83 savings_distance_fn: self.savings_distance_fn,
84 savings_feasible_fn: self.savings_feasible_fn,
85 element_owner_fn: self.element_owner_fn,
86 construction_element_order_key: self.construction_element_order_key,
87 precedence_duration_fn: self.precedence_duration_fn,
88 precedence_successors_fn: self.precedence_successors_fn,
89 _phantom: PhantomData,
90 }
91 }
92}
93
94impl<S, V, DM, IDM> ListVariableSlot<S, V, DM, IDM> {
95 #[allow(clippy::too_many_arguments)]
96 pub fn new(
97 entity_type_name: &'static str,
98 element_count: fn(&S) -> usize,
99 assigned_elements: fn(&S) -> Vec<V>,
100 list_len: fn(&S, usize) -> usize,
101 list_remove: fn(&mut S, usize, usize) -> Option<V>,
102 construction_list_remove: fn(&mut S, usize, usize) -> V,
103 list_insert: fn(&mut S, usize, usize, V),
104 list_get: fn(&S, usize, usize) -> Option<V>,
105 list_set: fn(&mut S, usize, usize, V),
106 list_reverse: fn(&mut S, usize, usize, usize),
107 sublist_remove: fn(&mut S, usize, usize, usize) -> Vec<V>,
108 sublist_insert: fn(&mut S, usize, usize, Vec<V>),
109 ruin_remove: fn(&mut S, usize, usize) -> V,
110 ruin_insert: fn(&mut S, usize, usize, V),
111 index_to_element: fn(&S, usize) -> V,
112 entity_count: fn(&S) -> usize,
113 cross_distance_meter: DM,
114 intra_distance_meter: IDM,
115 variable_name: &'static str,
116 descriptor_index: usize,
117 route_get_fn: Option<fn(&S, usize) -> Vec<usize>>,
118 route_set_fn: Option<fn(&mut S, usize, Vec<usize>)>,
119 route_depot_fn: Option<fn(&S, usize) -> usize>,
120 route_distance_fn: Option<fn(&S, usize, usize, usize) -> i64>,
121 route_feasible_fn: Option<fn(&S, usize, &[usize]) -> bool>,
122 savings_depot_fn: Option<fn(&S, usize) -> usize>,
123 savings_metric_class_fn: Option<fn(&S, usize) -> usize>,
124 savings_distance_fn: Option<fn(&S, usize, usize, usize) -> i64>,
125 savings_feasible_fn: Option<fn(&S, usize, &[usize]) -> bool>,
126 ) -> Self {
127 Self {
128 entity_type_name,
129 element_count,
130 assigned_elements,
131 list_len,
132 list_remove,
133 construction_list_remove,
134 list_insert,
135 list_get,
136 list_set,
137 list_reverse,
138 sublist_remove,
139 sublist_insert,
140 ruin_remove,
141 ruin_insert,
142 index_to_element,
143 entity_count,
144 cross_distance_meter,
145 intra_distance_meter,
146 variable_name,
147 descriptor_index,
148 route_get_fn,
149 route_set_fn,
150 route_depot_fn,
151 route_distance_fn,
152 route_feasible_fn,
153 savings_depot_fn,
154 savings_metric_class_fn,
155 savings_distance_fn,
156 savings_feasible_fn,
157 element_owner_fn: None,
158 construction_element_order_key: None,
159 precedence_duration_fn: None,
160 precedence_successors_fn: None,
161 _phantom: PhantomData,
162 }
163 }
164
165 pub fn with_element_owner_fn(
166 mut self,
167 element_owner_fn: Option<fn(&S, &V) -> Option<usize>>,
168 ) -> Self {
169 self.element_owner_fn = element_owner_fn;
170 self
171 }
172
173 pub fn with_construction_element_order_key(
174 mut self,
175 construction_element_order_key: Option<fn(&S, V) -> i64>,
176 ) -> Self {
177 self.construction_element_order_key = construction_element_order_key;
178 self
179 }
180
181 pub fn with_precedence_hooks(
182 mut self,
183 duration_fn: Option<fn(&S, V) -> usize>,
184 successors_fn: Option<fn(&S, V, &mut Vec<V>)>,
185 ) -> Self {
186 self.precedence_duration_fn = duration_fn;
187 self.precedence_successors_fn = successors_fn;
188 self
189 }
190
191 pub fn matches_target(&self, entity_class: Option<&str>, variable_name: Option<&str>) -> bool {
192 entity_class.is_none_or(|name| name == self.entity_type_name)
193 && variable_name.is_none_or(|name| name == self.variable_name)
194 }
195
196 pub fn has_unassigned_elements(&self, solution: &S) -> bool {
197 (self.assigned_elements)(solution).len() < (self.element_count)(solution)
198 }
199
200 pub fn has_list_content(&self, solution: &S) -> bool {
201 (0..(self.entity_count)(solution))
202 .any(|entity_index| (self.list_len)(solution, entity_index) > 0)
203 }
204
205 pub fn supports_clarke_wright(&self) -> bool {
206 self.route_set_fn.is_some()
207 && self.savings_depot_fn.is_some()
208 && self.savings_distance_fn.is_some()
209 && self.savings_feasible_fn.is_some()
210 }
211
212 pub fn supports_k_opt(&self) -> bool {
213 self.route_get_fn.is_some()
214 && self.route_set_fn.is_some()
215 && self.route_depot_fn.is_some()
216 && self.route_distance_fn.is_some()
217 }
218
219 pub fn supports_ruin(&self) -> bool {
220 true
221 }
222
223 pub fn supports_precedence_moves(&self) -> bool {
224 self.precedence_duration_fn.is_some() && self.precedence_successors_fn.is_some()
225 }
226}
227
228impl<S, V, DM: fmt::Debug, IDM: fmt::Debug> fmt::Debug for ListVariableSlot<S, V, DM, IDM> {
229 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
230 f.debug_struct("ListVariableSlot")
231 .field("entity_type_name", &self.entity_type_name)
232 .field("variable_name", &self.variable_name)
233 .field("descriptor_index", &self.descriptor_index)
234 .finish()
235 }
236}