Skip to main content

solverforge_solver/heuristic/selector/move_selector/
swap.rs

1/// A swap move selector that generates `SwapMove` instances.
2pub 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
13impl<S, V, LES: Debug, RES: Debug> Debug for SwapMoveSelector<S, V, LES, RES> {
14    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
15        f.debug_struct("SwapMoveSelector")
16            .field("left_entity_selector", &self.left_entity_selector)
17            .field("right_entity_selector", &self.right_entity_selector)
18            .field("descriptor_index", &self.descriptor_index)
19            .field("variable_index", &self.variable_index)
20            .field("variable_name", &self.variable_name)
21            .finish()
22    }
23}
24
25impl<S: PlanningSolution, V, LES, RES> SwapMoveSelector<S, V, LES, RES> {
26    pub fn new(
27        left_entity_selector: LES,
28        right_entity_selector: RES,
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    ) -> Self {
35        Self {
36            left_entity_selector,
37            right_entity_selector,
38            getter,
39            setter,
40            descriptor_index,
41            variable_index,
42            variable_name,
43            _phantom: PhantomData,
44        }
45    }
46}
47
48impl<S: PlanningSolution, V>
49    SwapMoveSelector<S, V, FromSolutionEntitySelector, FromSolutionEntitySelector>
50{
51    pub fn simple(
52        getter: fn(&S, usize, usize) -> Option<V>,
53        setter: fn(&mut S, usize, usize, Option<V>),
54        descriptor_index: usize,
55        variable_index: usize,
56        variable_name: &'static str,
57    ) -> Self {
58        Self {
59            left_entity_selector: FromSolutionEntitySelector::new(descriptor_index),
60            right_entity_selector: FromSolutionEntitySelector::new(descriptor_index),
61            getter,
62            setter,
63            descriptor_index,
64            variable_index,
65            variable_name,
66            _phantom: PhantomData,
67        }
68    }
69}
70
71impl<S, V, LES, RES> MoveSelector<S, SwapMove<S, V>> for SwapMoveSelector<S, V, LES, RES>
72where
73    S: PlanningSolution,
74    V: Clone + PartialEq + Send + Sync + Debug + 'static,
75    LES: EntitySelector<S>,
76    RES: EntitySelector<S>,
77{
78    type Cursor<'a>
79        = ArenaMoveCursor<S, SwapMove<S, V>>
80    where
81        Self: 'a;
82
83    fn open_cursor<'a, D: Director<S>>(&'a self, score_director: &D) -> Self::Cursor<'a> {
84        let getter = self.getter;
85        let setter = self.setter;
86        let variable_index = self.variable_index;
87        let variable_name = self.variable_name;
88        let descriptor_index = self.descriptor_index;
89        let right_entities: Vec<_> = self.right_entity_selector.iter(score_director).collect();
90        let mut moves = Vec::new();
91        for left_entity_ref in self.left_entity_selector.iter(score_director) {
92            for right_entity_ref in &right_entities {
93                if left_entity_ref.entity_index < right_entity_ref.entity_index {
94                    moves.push(SwapMove::new(
95                        left_entity_ref.entity_index,
96                        right_entity_ref.entity_index,
97                        getter,
98                        setter,
99                        variable_index,
100                        variable_name,
101                        descriptor_index,
102                    ));
103                }
104            }
105        }
106        ArenaMoveCursor::from_moves(moves)
107    }
108
109    fn size<D: Director<S>>(&self, score_director: &D) -> usize {
110        let left_count = self.left_entity_selector.iter(score_director).count();
111        let right_count = self.right_entity_selector.iter(score_director).count();
112        left_count.saturating_mul(right_count.saturating_sub(1)) / 2
113    }
114}