1pub struct ChangeMoveSelector<S, V, ES, VS> {
3 entity_selector: ES,
4 value_selector: VS,
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 allows_unassigned: bool,
11 _phantom: PhantomData<(fn() -> S, fn() -> V)>,
12}
13
14struct ChangeEntityValues<V> {
15 entity_ref: super::entity::EntityReference,
16 values: Vec<V>,
17 current_assigned: bool,
18}
19
20pub struct ChangeMoveCursor<S, V>
21where
22 S: PlanningSolution,
23 V: Clone + PartialEq + Send + Sync + Debug + 'static,
24{
25 store: CandidateStore<S, ChangeMove<S, V>>,
26 entity_values: Vec<ChangeEntityValues<V>>,
27 entity_offset: usize,
28 value_offset: usize,
29 getter: fn(&S, usize, usize) -> Option<V>,
30 setter: fn(&mut S, usize, usize, Option<V>),
31 descriptor_index: usize,
32 variable_index: usize,
33 variable_name: &'static str,
34 allows_unassigned: bool,
35}
36
37impl<S, V> ChangeMoveCursor<S, V>
38where
39 S: PlanningSolution,
40 V: Clone + PartialEq + Send + Sync + Debug + 'static,
41{
42 fn new(
43 entity_values: Vec<ChangeEntityValues<V>>,
44 getter: fn(&S, usize, usize) -> Option<V>,
45 setter: fn(&mut S, usize, usize, Option<V>),
46 descriptor_index: usize,
47 variable_index: usize,
48 variable_name: &'static str,
49 allows_unassigned: bool,
50 ) -> Self {
51 Self {
52 store: CandidateStore::new(),
53 entity_values,
54 entity_offset: 0,
55 value_offset: 0,
56 getter,
57 setter,
58 descriptor_index,
59 variable_index,
60 variable_name,
61 allows_unassigned,
62 }
63 }
64}
65
66impl<S, V> MoveCursor<S, ChangeMove<S, V>> for ChangeMoveCursor<S, V>
67where
68 S: PlanningSolution,
69 V: Clone + PartialEq + Send + Sync + Debug + 'static,
70{
71 fn next_candidate(&mut self) -> Option<CandidateId> {
72 while self.entity_offset < self.entity_values.len() {
73 let entity_values = &self.entity_values[self.entity_offset];
74 if self.value_offset < entity_values.values.len() {
75 let value = entity_values.values[self.value_offset].clone();
76 self.value_offset += 1;
77 return Some(self.store.push(ChangeMove::new(
78 entity_values.entity_ref.entity_index,
79 Some(value),
80 self.getter,
81 self.setter,
82 self.variable_index,
83 self.variable_name,
84 self.descriptor_index,
85 )));
86 }
87
88 let to_none_offset = entity_values.values.len();
89 if self.allows_unassigned
90 && entity_values.current_assigned
91 && self.value_offset == to_none_offset
92 {
93 self.value_offset += 1;
94 return Some(self.store.push(ChangeMove::new(
95 entity_values.entity_ref.entity_index,
96 None,
97 self.getter,
98 self.setter,
99 self.variable_index,
100 self.variable_name,
101 self.descriptor_index,
102 )));
103 }
104
105 self.entity_offset += 1;
106 self.value_offset = 0;
107 }
108
109 None
110 }
111
112 fn candidate(
113 &self,
114 id: CandidateId,
115 ) -> Option<MoveCandidateRef<'_, S, ChangeMove<S, V>>> {
116 self.store.candidate(id)
117 }
118
119 fn take_candidate(&mut self, id: CandidateId) -> ChangeMove<S, V> {
120 self.store.take_candidate(id)
121 }
122}
123
124impl<S, V> Iterator for ChangeMoveCursor<S, V>
125where
126 S: PlanningSolution,
127 V: Clone + PartialEq + Send + Sync + Debug + 'static,
128{
129 type Item = ChangeMove<S, V>;
130
131 fn next(&mut self) -> Option<Self::Item> {
132 let id = self.next_candidate()?;
133 Some(self.take_candidate(id))
134 }
135}
136
137impl<S, V: Debug, ES: Debug, VS: Debug> Debug for ChangeMoveSelector<S, V, ES, VS> {
138 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
139 f.debug_struct("ChangeMoveSelector")
140 .field("entity_selector", &self.entity_selector)
141 .field("value_selector", &self.value_selector)
142 .field("descriptor_index", &self.descriptor_index)
143 .field("variable_index", &self.variable_index)
144 .field("variable_name", &self.variable_name)
145 .field("allows_unassigned", &self.allows_unassigned)
146 .finish()
147 }
148}
149
150impl<S: PlanningSolution, V: Clone, ES, VS> ChangeMoveSelector<S, V, ES, VS> {
151 pub fn new(
152 entity_selector: ES,
153 value_selector: VS,
154 getter: fn(&S, usize, usize) -> Option<V>,
155 setter: fn(&mut S, usize, usize, Option<V>),
156 descriptor_index: usize,
157 variable_index: usize,
158 variable_name: &'static str,
159 ) -> Self {
160 Self {
161 entity_selector,
162 value_selector,
163 getter,
164 setter,
165 descriptor_index,
166 variable_index,
167 variable_name,
168 allows_unassigned: false,
169 _phantom: PhantomData,
170 }
171 }
172
173 pub fn with_allows_unassigned(mut self, allows_unassigned: bool) -> Self {
174 self.allows_unassigned = allows_unassigned;
175 self
176 }
177}
178
179impl<S: PlanningSolution, V: Clone + Send + Sync + Debug + 'static>
180 ChangeMoveSelector<S, V, FromSolutionEntitySelector, StaticValueSelector<S, V>>
181{
182 pub fn simple(
183 getter: fn(&S, usize, usize) -> Option<V>,
184 setter: fn(&mut S, usize, usize, Option<V>),
185 descriptor_index: usize,
186 variable_index: usize,
187 variable_name: &'static str,
188 values: Vec<V>,
189 ) -> Self {
190 Self {
191 entity_selector: FromSolutionEntitySelector::new(descriptor_index),
192 value_selector: StaticValueSelector::new(values),
193 getter,
194 setter,
195 descriptor_index,
196 variable_index,
197 variable_name,
198 allows_unassigned: false,
199 _phantom: PhantomData,
200 }
201 }
202}
203
204impl<S, V, ES, VS> MoveSelector<S, ChangeMove<S, V>> for ChangeMoveSelector<S, V, ES, VS>
205where
206 S: PlanningSolution,
207 V: Clone + PartialEq + Send + Sync + Debug + 'static,
208 ES: EntitySelector<S>,
209 VS: ValueSelector<S, V>,
210{
211 type Cursor<'a>
212 = ChangeMoveCursor<S, V>
213 where
214 Self: 'a;
215
216 fn open_cursor<'a, D: Director<S>>(&'a self, score_director: &D) -> Self::Cursor<'a> {
217 self.open_cursor_with_context(score_director, MoveStreamContext::default())
218 }
219
220 fn open_cursor_with_context<'a, D: Director<S>>(
221 &'a self,
222 score_director: &D,
223 context: MoveStreamContext,
224 ) -> Self::Cursor<'a> {
225 let solution = score_director.working_solution();
226 let mut entity_values: Vec<_> = self
227 .entity_selector
228 .iter(score_director)
229 .map(|entity_ref| {
230 let current_assigned = (self.getter)(
231 solution,
232 entity_ref.entity_index,
233 self.variable_index,
234 )
235 .is_some();
236 let values = self.value_selector.iter(
237 score_director,
238 entity_ref.descriptor_index,
239 entity_ref.entity_index,
240 ).collect();
241 ChangeEntityValues {
242 entity_ref,
243 values,
244 current_assigned,
245 }
246 })
247 .collect();
248 for entity_values in &mut entity_values {
249 let start = context.start_offset(
250 entity_values.values.len(),
251 0xC4A4_6E00_0000_0000
252 ^ entity_values.entity_ref.entity_index as u64
253 ^ ((self.descriptor_index as u64) << 32)
254 ^ self.variable_index as u64,
255 );
256 entity_values.values.rotate_left(start);
257 }
258 let entity_start = context.start_offset(
259 entity_values.len(),
260 0xC4A4_6E00_0000_0001
261 ^ ((self.descriptor_index as u64) << 32)
262 ^ self.variable_index as u64,
263 );
264 entity_values.rotate_left(entity_start);
265 ChangeMoveCursor::new(
266 entity_values,
267 self.getter,
268 self.setter,
269 self.descriptor_index,
270 self.variable_index,
271 self.variable_name,
272 self.allows_unassigned,
273 )
274 }
275
276 fn size<D: Director<S>>(&self, score_director: &D) -> usize {
277 self.entity_selector
278 .iter(score_director)
279 .map(|entity_ref| {
280 self.value_selector.size(
281 score_director,
282 entity_ref.descriptor_index,
283 entity_ref.entity_index,
284 ) + usize::from(
285 self.allows_unassigned
286 && (self.getter)(
287 score_director.working_solution(),
288 entity_ref.entity_index,
289 self.variable_index,
290 )
291 .is_some(),
292 )
293 })
294 .sum()
295 }
296}