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