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_metric_class_fn: Option<fn(&S, usize) -> usize>,
41 pub route_distance_fn: Option<fn(&S, usize, usize, usize) -> i64>,
42 pub route_feasible_fn: Option<fn(&S, usize, &[usize]) -> bool>,
43 pub element_owner_fn: Option<fn(&S, &V) -> Option<usize>>,
44 pub construction_element_order_key: Option<fn(&S, V) -> i64>,
45 pub precedence_duration_fn: Option<fn(&S, V) -> usize>,
46 pub precedence_successors_fn: Option<fn(&S, V, &mut Vec<V>)>,
47 _phantom: PhantomData<(fn() -> S, fn() -> V)>,
48}
49
50impl<S, V, DM: Clone, IDM: Clone> Clone for ListVariableSlot<S, V, DM, IDM> {
51 fn clone(&self) -> Self {
52 Self {
53 entity_type_name: self.entity_type_name,
54 element_count: self.element_count,
55 assigned_elements: self.assigned_elements,
56 list_len: self.list_len,
57 list_remove: self.list_remove,
58 construction_list_remove: self.construction_list_remove,
59 list_insert: self.list_insert,
60 list_get: self.list_get,
61 list_set: self.list_set,
62 list_reverse: self.list_reverse,
63 sublist_remove: self.sublist_remove,
64 sublist_insert: self.sublist_insert,
65 ruin_remove: self.ruin_remove,
66 ruin_insert: self.ruin_insert,
67 index_to_element: self.index_to_element,
68 entity_count: self.entity_count,
69 cross_distance_meter: self.cross_distance_meter.clone(),
70 intra_distance_meter: self.intra_distance_meter.clone(),
71 variable_name: self.variable_name,
72 descriptor_index: self.descriptor_index,
73 route_get_fn: self.route_get_fn,
74 route_set_fn: self.route_set_fn,
75 route_depot_fn: self.route_depot_fn,
76 route_metric_class_fn: self.route_metric_class_fn,
77 route_distance_fn: self.route_distance_fn,
78 route_feasible_fn: self.route_feasible_fn,
79 element_owner_fn: self.element_owner_fn,
80 construction_element_order_key: self.construction_element_order_key,
81 precedence_duration_fn: self.precedence_duration_fn,
82 precedence_successors_fn: self.precedence_successors_fn,
83 _phantom: PhantomData,
84 }
85 }
86}
87
88impl<S, V, DM, IDM> ListVariableSlot<S, V, DM, IDM> {
89 #[allow(clippy::too_many_arguments)]
90 pub fn new(
91 entity_type_name: &'static str,
92 element_count: fn(&S) -> usize,
93 assigned_elements: fn(&S) -> Vec<V>,
94 list_len: fn(&S, usize) -> usize,
95 list_remove: fn(&mut S, usize, usize) -> Option<V>,
96 construction_list_remove: fn(&mut S, usize, usize) -> V,
97 list_insert: fn(&mut S, usize, usize, V),
98 list_get: fn(&S, usize, usize) -> Option<V>,
99 list_set: fn(&mut S, usize, usize, V),
100 list_reverse: fn(&mut S, usize, usize, usize),
101 sublist_remove: fn(&mut S, usize, usize, usize) -> Vec<V>,
102 sublist_insert: fn(&mut S, usize, usize, Vec<V>),
103 ruin_remove: fn(&mut S, usize, usize) -> V,
104 ruin_insert: fn(&mut S, usize, usize, V),
105 index_to_element: fn(&S, usize) -> V,
106 entity_count: fn(&S) -> usize,
107 cross_distance_meter: DM,
108 intra_distance_meter: IDM,
109 variable_name: &'static str,
110 descriptor_index: usize,
111 route_get_fn: Option<fn(&S, usize) -> Vec<usize>>,
112 route_set_fn: Option<fn(&mut S, usize, Vec<usize>)>,
113 route_depot_fn: Option<fn(&S, usize) -> usize>,
114 route_metric_class_fn: Option<fn(&S, usize) -> usize>,
115 route_distance_fn: Option<fn(&S, usize, usize, usize) -> i64>,
116 route_feasible_fn: Option<fn(&S, usize, &[usize]) -> bool>,
117 ) -> Self {
118 Self {
119 entity_type_name,
120 element_count,
121 assigned_elements,
122 list_len,
123 list_remove,
124 construction_list_remove,
125 list_insert,
126 list_get,
127 list_set,
128 list_reverse,
129 sublist_remove,
130 sublist_insert,
131 ruin_remove,
132 ruin_insert,
133 index_to_element,
134 entity_count,
135 cross_distance_meter,
136 intra_distance_meter,
137 variable_name,
138 descriptor_index,
139 route_get_fn,
140 route_set_fn,
141 route_depot_fn,
142 route_metric_class_fn,
143 route_distance_fn,
144 route_feasible_fn,
145 element_owner_fn: None,
146 construction_element_order_key: None,
147 precedence_duration_fn: None,
148 precedence_successors_fn: None,
149 _phantom: PhantomData,
150 }
151 }
152
153 pub fn with_element_owner_fn(
154 mut self,
155 element_owner_fn: Option<fn(&S, &V) -> Option<usize>>,
156 ) -> Self {
157 self.element_owner_fn = element_owner_fn;
158 self
159 }
160
161 pub fn with_construction_element_order_key(
162 mut self,
163 construction_element_order_key: Option<fn(&S, V) -> i64>,
164 ) -> Self {
165 self.construction_element_order_key = construction_element_order_key;
166 self
167 }
168
169 pub fn with_precedence_hooks(
170 mut self,
171 duration_fn: Option<fn(&S, V) -> usize>,
172 successors_fn: Option<fn(&S, V, &mut Vec<V>)>,
173 ) -> Self {
174 self.precedence_duration_fn = duration_fn;
175 self.precedence_successors_fn = successors_fn;
176 self
177 }
178
179 pub fn matches_target(&self, entity_class: Option<&str>, variable_name: Option<&str>) -> bool {
180 entity_class.is_none_or(|name| name == self.entity_type_name)
181 && variable_name.is_none_or(|name| name == self.variable_name)
182 }
183
184 pub fn has_unassigned_elements(&self, solution: &S) -> bool {
185 (self.assigned_elements)(solution).len() < (self.element_count)(solution)
186 }
187
188 pub fn has_list_content(&self, solution: &S) -> bool {
189 (0..(self.entity_count)(solution))
190 .any(|entity_index| (self.list_len)(solution, entity_index) > 0)
191 }
192
193 pub fn supports_clarke_wright(&self) -> bool {
194 self.route_set_fn.is_some()
195 && self.route_depot_fn.is_some()
196 && self.route_distance_fn.is_some()
197 && self.route_feasible_fn.is_some()
198 }
199
200 pub fn supports_k_opt(&self) -> bool {
201 self.route_get_fn.is_some()
202 && self.route_set_fn.is_some()
203 && self.route_depot_fn.is_some()
204 && self.route_distance_fn.is_some()
205 }
206
207 pub fn supports_ruin(&self) -> bool {
208 true
209 }
210
211 pub fn supports_precedence_moves(&self) -> bool {
212 self.precedence_duration_fn.is_some() && self.precedence_successors_fn.is_some()
213 }
214}
215
216impl<S, V, DM: fmt::Debug, IDM: fmt::Debug> fmt::Debug for ListVariableSlot<S, V, DM, IDM> {
217 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
218 f.debug_struct("ListVariableSlot")
219 .field("entity_type_name", &self.entity_type_name)
220 .field("variable_name", &self.variable_name)
221 .field("descriptor_index", &self.descriptor_index)
222 .finish()
223 }
224}