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, _solution: &S) -> 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
109
110impl<S, V, LES: Debug, RES: Debug> Debug for SwapMoveSelector<S, V, LES, RES> {
111 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112 f.debug_struct("SwapMoveSelector")
113 .field("left_entity_selector", &self.left_entity_selector)
114 .field("right_entity_selector", &self.right_entity_selector)
115 .field("descriptor_index", &self.descriptor_index)
116 .field("variable_index", &self.variable_index)
117 .field("variable_name", &self.variable_name)
118 .finish()
119 }
120}
121
122impl<S: PlanningSolution, V, LES, RES> SwapMoveSelector<S, V, LES, RES> {
123 pub fn new(
124 left_entity_selector: LES,
125 right_entity_selector: RES,
126 getter: fn(&S, usize, usize) -> Option<V>,
127 setter: fn(&mut S, usize, usize, Option<V>),
128 descriptor_index: usize,
129 variable_index: usize,
130 variable_name: &'static str,
131 ) -> Self {
132 Self {
133 left_entity_selector,
134 right_entity_selector,
135 getter,
136 setter,
137 descriptor_index,
138 variable_index,
139 variable_name,
140 _phantom: PhantomData,
141 }
142 }
143}
144
145impl<S: PlanningSolution, V>
146 SwapMoveSelector<S, V, FromSolutionEntitySelector, FromSolutionEntitySelector>
147{
148 pub fn simple(
149 getter: fn(&S, usize, usize) -> Option<V>,
150 setter: fn(&mut S, usize, usize, Option<V>),
151 descriptor_index: usize,
152 variable_index: usize,
153 variable_name: &'static str,
154 ) -> Self {
155 Self {
156 left_entity_selector: FromSolutionEntitySelector::new(descriptor_index),
157 right_entity_selector: FromSolutionEntitySelector::new(descriptor_index),
158 getter,
159 setter,
160 descriptor_index,
161 variable_index,
162 variable_name,
163 _phantom: PhantomData,
164 }
165 }
166}
167
168impl<S, V, LES, RES> MoveSelector<S, SwapMove<S, V>> for SwapMoveSelector<S, V, LES, RES>
169where
170 S: PlanningSolution,
171 V: Clone + PartialEq + Send + Sync + Debug + 'static,
172 LES: EntitySelector<S>,
173 RES: EntitySelector<S>,
174{
175 type Cursor<'a>
176 = SwapMoveCursor<S, V>
177 where
178 Self: 'a;
179
180 fn open_cursor<'a, D: Director<S>>(&'a self, score_director: &D) -> Self::Cursor<'a> {
181 self.open_cursor_with_context(score_director, MoveStreamContext::default())
182 }
183
184 fn open_cursor_with_context<'a, D: Director<S>>(
185 &'a self,
186 score_director: &D,
187 context: MoveStreamContext,
188 ) -> Self::Cursor<'a> {
189 let canonical_right: Vec<_> = self.right_entity_selector.iter(score_director).collect();
190 let canonical_left: Vec<_> = self.left_entity_selector.iter(score_director).collect();
191 let salt = ((self.descriptor_index as u64) << 32) ^ self.variable_index as u64;
192 let left_entities = (0..canonical_left.len())
193 .map(|offset| {
194 canonical_left[context.selection_index(
195 offset,
196 canonical_left.len(),
197 0x5A09_0000_0000_0001 ^ salt,
198 )]
199 })
200 .collect();
201 let right_entities = (0..canonical_right.len())
202 .map(|offset| {
203 canonical_right[context.selection_index(
204 offset,
205 canonical_right.len(),
206 0x5A09_0000_0000_0002 ^ salt,
207 )]
208 })
209 .collect();
210 SwapMoveCursor::new(
211 left_entities,
212 right_entities,
213 self.getter,
214 self.setter,
215 self.descriptor_index,
216 self.variable_index,
217 self.variable_name,
218 )
219 }
220
221 fn size<D: Director<S>>(&self, score_director: &D) -> usize {
222 let left_count = self.left_entity_selector.iter(score_director).count();
223 let right_count = self.right_entity_selector.iter(score_director).count();
224 left_count.saturating_mul(right_count.saturating_sub(1)) / 2
225 }
226}