1pub struct SwapMoveSelector<S, V, LES, RES> {
3 left_entity_selector: LES,
4 right_entity_selector: RES,
5 getter: fn(&S, usize, usize) -> Option<V>,
6 setter: fn(&mut S, usize, usize, Option<V>),
7 descriptor_index: usize,
8 variable_index: usize,
9 variable_name: &'static str,
10 _phantom: PhantomData<(fn() -> S, fn() -> V)>,
11}
12
13pub struct SwapMoveCursor<S, V>
14where
15 S: PlanningSolution,
16 V: Clone + PartialEq + Send + Sync + Debug + 'static,
17{
18 store: CandidateStore<S, SwapMove<S, V>>,
19 left_entities: Vec<super::entity::EntityReference>,
20 right_entities: Vec<super::entity::EntityReference>,
21 left_offset: usize,
22 right_offset: usize,
23 getter: fn(&S, usize, usize) -> Option<V>,
24 setter: fn(&mut S, usize, usize, Option<V>),
25 descriptor_index: usize,
26 variable_index: usize,
27 variable_name: &'static str,
28}
29
30impl<S, V> SwapMoveCursor<S, V>
31where
32 S: PlanningSolution,
33 V: Clone + PartialEq + Send + Sync + Debug + 'static,
34{
35 fn new(
36 left_entities: Vec<super::entity::EntityReference>,
37 right_entities: Vec<super::entity::EntityReference>,
38 getter: fn(&S, usize, usize) -> Option<V>,
39 setter: fn(&mut S, usize, usize, Option<V>),
40 descriptor_index: usize,
41 variable_index: usize,
42 variable_name: &'static str,
43 ) -> Self {
44 Self {
45 store: CandidateStore::new(),
46 left_entities,
47 right_entities,
48 left_offset: 0,
49 right_offset: 0,
50 getter,
51 setter,
52 descriptor_index,
53 variable_index,
54 variable_name,
55 }
56 }
57}
58
59impl<S, V> MoveCursor<S, SwapMove<S, V>> for SwapMoveCursor<S, V>
60where
61 S: PlanningSolution,
62 V: Clone + PartialEq + Send + Sync + Debug + 'static,
63{
64 fn next_candidate(&mut self) -> Option<CandidateId> {
65 while self.left_offset < self.left_entities.len() {
66 while self.right_offset < self.right_entities.len() {
67 let left_entity_ref = self.left_entities[self.left_offset];
68 let right_entity_ref = self.right_entities[self.right_offset];
69 self.right_offset += 1;
70
71 if left_entity_ref.entity_index >= right_entity_ref.entity_index {
72 continue;
73 }
74
75 return Some(self.store.push(SwapMove::new(
76 left_entity_ref.entity_index,
77 right_entity_ref.entity_index,
78 self.getter,
79 self.setter,
80 self.variable_index,
81 self.variable_name,
82 self.descriptor_index,
83 )));
84 }
85
86 self.left_offset += 1;
87 self.right_offset = 0;
88 }
89
90 None
91 }
92
93 fn candidate(
94 &self,
95 id: CandidateId,
96 ) -> Option<MoveCandidateRef<'_, S, SwapMove<S, V>>> {
97 self.store.candidate(id)
98 }
99
100 fn take_candidate(&mut self, id: CandidateId) -> SwapMove<S, V> {
101 self.store.take_candidate(id)
102 }
103
104 fn release_candidate(&mut self, id: CandidateId) -> bool {
105 self.store.release_candidate(id)
106 }
107}
108
109impl<S, V> Iterator for SwapMoveCursor<S, V>
110where
111 S: PlanningSolution,
112 V: Clone + PartialEq + Send + Sync + Debug + 'static,
113{
114 type Item = SwapMove<S, V>;
115
116 fn next(&mut self) -> Option<Self::Item> {
117 let id = self.next_candidate()?;
118 Some(self.take_candidate(id))
119 }
120}
121
122impl<S, V, LES: Debug, RES: Debug> Debug for SwapMoveSelector<S, V, LES, RES> {
123 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
124 f.debug_struct("SwapMoveSelector")
125 .field("left_entity_selector", &self.left_entity_selector)
126 .field("right_entity_selector", &self.right_entity_selector)
127 .field("descriptor_index", &self.descriptor_index)
128 .field("variable_index", &self.variable_index)
129 .field("variable_name", &self.variable_name)
130 .finish()
131 }
132}
133
134impl<S: PlanningSolution, V, LES, RES> SwapMoveSelector<S, V, LES, RES> {
135 pub fn new(
136 left_entity_selector: LES,
137 right_entity_selector: RES,
138 getter: fn(&S, usize, usize) -> Option<V>,
139 setter: fn(&mut S, usize, usize, Option<V>),
140 descriptor_index: usize,
141 variable_index: usize,
142 variable_name: &'static str,
143 ) -> Self {
144 Self {
145 left_entity_selector,
146 right_entity_selector,
147 getter,
148 setter,
149 descriptor_index,
150 variable_index,
151 variable_name,
152 _phantom: PhantomData,
153 }
154 }
155}
156
157impl<S: PlanningSolution, V>
158 SwapMoveSelector<S, V, FromSolutionEntitySelector, FromSolutionEntitySelector>
159{
160 pub fn simple(
161 getter: fn(&S, usize, usize) -> Option<V>,
162 setter: fn(&mut S, usize, usize, Option<V>),
163 descriptor_index: usize,
164 variable_index: usize,
165 variable_name: &'static str,
166 ) -> Self {
167 Self {
168 left_entity_selector: FromSolutionEntitySelector::new(descriptor_index),
169 right_entity_selector: FromSolutionEntitySelector::new(descriptor_index),
170 getter,
171 setter,
172 descriptor_index,
173 variable_index,
174 variable_name,
175 _phantom: PhantomData,
176 }
177 }
178}
179
180impl<S, V, LES, RES> MoveSelector<S, SwapMove<S, V>> for SwapMoveSelector<S, V, LES, RES>
181where
182 S: PlanningSolution,
183 V: Clone + PartialEq + Send + Sync + Debug + 'static,
184 LES: EntitySelector<S>,
185 RES: EntitySelector<S>,
186{
187 type Cursor<'a>
188 = SwapMoveCursor<S, V>
189 where
190 Self: 'a;
191
192 fn open_cursor<'a, D: Director<S>>(&'a self, score_director: &D) -> Self::Cursor<'a> {
193 self.open_cursor_with_context(score_director, MoveStreamContext::default())
194 }
195
196 fn open_cursor_with_context<'a, D: Director<S>>(
197 &'a self,
198 score_director: &D,
199 context: MoveStreamContext,
200 ) -> Self::Cursor<'a> {
201 let canonical_right: Vec<_> = self.right_entity_selector.iter(score_director).collect();
202 let canonical_left: Vec<_> = self.left_entity_selector.iter(score_director).collect();
203 let salt = ((self.descriptor_index as u64) << 32) ^ self.variable_index as u64;
204 let left_entities = (0..canonical_left.len())
205 .map(|offset| {
206 canonical_left[context.selection_index(
207 offset,
208 canonical_left.len(),
209 0x5A09_0000_0000_0001 ^ salt,
210 )]
211 })
212 .collect();
213 let right_entities = (0..canonical_right.len())
214 .map(|offset| {
215 canonical_right[context.selection_index(
216 offset,
217 canonical_right.len(),
218 0x5A09_0000_0000_0002 ^ salt,
219 )]
220 })
221 .collect();
222 SwapMoveCursor::new(
223 left_entities,
224 right_entities,
225 self.getter,
226 self.setter,
227 self.descriptor_index,
228 self.variable_index,
229 self.variable_name,
230 )
231 }
232
233 fn size<D: Director<S>>(&self, score_director: &D) -> usize {
234 let left_count = self.left_entity_selector.iter(score_director).count();
235 let right_count = self.right_entity_selector.iter(score_director).count();
236 left_count.saturating_mul(right_count.saturating_sub(1)) / 2
237 }
238}