Skip to main content

solverforge_solver/heuristic/selector/move_selector/
change.rs

1/// A change move selector that generates `ChangeMove` instances.
2pub 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}