Skip to main content

solverforge_solver/builder/list_selector/
leaf.rs

1use std::fmt::Debug;
2
3use solverforge_core::domain::PlanningSolution;
4use solverforge_scoring::Director;
5
6use crate::heuristic::r#move::{ListMoveImpl, MoveArena};
7use crate::heuristic::selector::move_selector::{
8    ListMoveKOptSelector, ListMoveListChangeSelector, ListMoveListRuinSelector,
9    ListMoveNearbyKOptSelector, MoveSelector,
10};
11use crate::heuristic::selector::nearby_list_change::CrossEntityDistanceMeter;
12use crate::heuristic::selector::{
13    FromSolutionEntitySelector, ListMoveListReverseSelector, ListMoveListSwapSelector,
14    ListMoveNearbyListChangeSelector, ListMoveNearbyListSwapSelector,
15    ListMoveSubListChangeSelector, ListMoveSubListSwapSelector,
16};
17
18use super::super::context::IntraDistanceAdapter;
19
20/// A monomorphized leaf selector for list planning variables.
21///
22/// Each variant wraps one of the available list move selector wrapper types.
23/// Allows `VecUnionSelector<S, ListMoveImpl<S, V>, ListLeafSelector<S, V, DM, IDM>>` to have
24/// a single concrete type regardless of configuration.
25pub enum ListLeafSelector<S, V, DM, IDM>
26where
27    S: PlanningSolution,
28    V: Clone + PartialEq + Send + Sync + Debug + 'static,
29    DM: CrossEntityDistanceMeter<S>,
30    IDM: CrossEntityDistanceMeter<S>,
31{
32    NearbyListChange(ListMoveNearbyListChangeSelector<S, V, DM, FromSolutionEntitySelector>),
33    NearbyListSwap(ListMoveNearbyListSwapSelector<S, V, DM, FromSolutionEntitySelector>),
34    ListReverse(ListMoveListReverseSelector<S, V, FromSolutionEntitySelector>),
35    SubListChange(ListMoveSubListChangeSelector<S, V, FromSolutionEntitySelector>),
36    KOpt(ListMoveKOptSelector<S, V, FromSolutionEntitySelector>),
37    NearbyKOpt(
38        ListMoveNearbyKOptSelector<S, V, IntraDistanceAdapter<IDM>, FromSolutionEntitySelector>,
39    ),
40    ListRuin(ListMoveListRuinSelector<S, V>),
41    ListChange(ListMoveListChangeSelector<S, V, FromSolutionEntitySelector>),
42    ListSwap(ListMoveListSwapSelector<S, V, FromSolutionEntitySelector>),
43    SubListSwap(ListMoveSubListSwapSelector<S, V, FromSolutionEntitySelector>),
44}
45
46impl<S, V, DM, IDM> Debug for ListLeafSelector<S, V, DM, IDM>
47where
48    S: PlanningSolution,
49    V: Clone + PartialEq + Send + Sync + Debug + 'static,
50    DM: CrossEntityDistanceMeter<S>,
51    IDM: CrossEntityDistanceMeter<S>,
52{
53    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54        match self {
55            Self::NearbyListChange(s) => write!(f, "ListLeafSelector::NearbyListChange({s:?})"),
56            Self::NearbyListSwap(s) => write!(f, "ListLeafSelector::NearbyListSwap({s:?})"),
57            Self::ListReverse(s) => write!(f, "ListLeafSelector::ListReverse({s:?})"),
58            Self::SubListChange(s) => write!(f, "ListLeafSelector::SubListChange({s:?})"),
59            Self::KOpt(s) => write!(f, "ListLeafSelector::KOpt({s:?})"),
60            Self::NearbyKOpt(s) => write!(f, "ListLeafSelector::NearbyKOpt({s:?})"),
61            Self::ListRuin(s) => write!(f, "ListLeafSelector::ListRuin({s:?})"),
62            Self::ListChange(s) => write!(f, "ListLeafSelector::ListChange({s:?})"),
63            Self::ListSwap(s) => write!(f, "ListLeafSelector::ListSwap({s:?})"),
64            Self::SubListSwap(s) => write!(f, "ListLeafSelector::SubListSwap({s:?})"),
65        }
66    }
67}
68
69impl<S, V, DM, IDM> MoveSelector<S, ListMoveImpl<S, V>> for ListLeafSelector<S, V, DM, IDM>
70where
71    S: PlanningSolution,
72    V: Clone + PartialEq + Send + Sync + Debug + 'static,
73    DM: CrossEntityDistanceMeter<S>,
74    IDM: CrossEntityDistanceMeter<S> + 'static,
75{
76    fn iter_moves<'a, D: Director<S>>(
77        &'a self,
78        score_director: &'a D,
79    ) -> impl Iterator<Item = ListMoveImpl<S, V>> + 'a {
80        enum ListLeafIter<A, B, C, DIter, E, F, G, H, I, J> {
81            NearbyListChange(A),
82            NearbyListSwap(B),
83            ListReverse(C),
84            SubListChange(DIter),
85            KOpt(E),
86            NearbyKOpt(F),
87            ListRuin(G),
88            ListChange(H),
89            ListSwap(I),
90            SubListSwap(J),
91        }
92
93        impl<T, A, B, C, DIter, E, F, G, H, I, J> Iterator
94            for ListLeafIter<A, B, C, DIter, E, F, G, H, I, J>
95        where
96            A: Iterator<Item = T>,
97            B: Iterator<Item = T>,
98            C: Iterator<Item = T>,
99            DIter: Iterator<Item = T>,
100            E: Iterator<Item = T>,
101            F: Iterator<Item = T>,
102            G: Iterator<Item = T>,
103            H: Iterator<Item = T>,
104            I: Iterator<Item = T>,
105            J: Iterator<Item = T>,
106        {
107            type Item = T;
108
109            fn next(&mut self) -> Option<Self::Item> {
110                match self {
111                    Self::NearbyListChange(iter) => iter.next(),
112                    Self::NearbyListSwap(iter) => iter.next(),
113                    Self::ListReverse(iter) => iter.next(),
114                    Self::SubListChange(iter) => iter.next(),
115                    Self::KOpt(iter) => iter.next(),
116                    Self::NearbyKOpt(iter) => iter.next(),
117                    Self::ListRuin(iter) => iter.next(),
118                    Self::ListChange(iter) => iter.next(),
119                    Self::ListSwap(iter) => iter.next(),
120                    Self::SubListSwap(iter) => iter.next(),
121                }
122            }
123        }
124
125        match self {
126            Self::NearbyListChange(s) => {
127                ListLeafIter::NearbyListChange(s.iter_moves(score_director))
128            }
129            Self::NearbyListSwap(s) => ListLeafIter::NearbyListSwap(s.iter_moves(score_director)),
130            Self::ListReverse(s) => ListLeafIter::ListReverse(s.iter_moves(score_director)),
131            Self::SubListChange(s) => ListLeafIter::SubListChange(s.iter_moves(score_director)),
132            Self::KOpt(s) => ListLeafIter::KOpt(s.iter_moves(score_director)),
133            Self::NearbyKOpt(s) => ListLeafIter::NearbyKOpt(s.iter_moves(score_director)),
134            Self::ListRuin(s) => ListLeafIter::ListRuin(s.iter_moves(score_director)),
135            Self::ListChange(s) => ListLeafIter::ListChange(s.iter_moves(score_director)),
136            Self::ListSwap(s) => ListLeafIter::ListSwap(s.iter_moves(score_director)),
137            Self::SubListSwap(s) => ListLeafIter::SubListSwap(s.iter_moves(score_director)),
138        }
139    }
140
141    fn size<D: Director<S>>(&self, score_director: &D) -> usize {
142        match self {
143            Self::NearbyListChange(s) => s.size(score_director),
144            Self::NearbyListSwap(s) => s.size(score_director),
145            Self::ListReverse(s) => s.size(score_director),
146            Self::SubListChange(s) => s.size(score_director),
147            Self::KOpt(s) => s.size(score_director),
148            Self::NearbyKOpt(s) => s.size(score_director),
149            Self::ListRuin(s) => s.size(score_director),
150            Self::ListChange(s) => s.size(score_director),
151            Self::ListSwap(s) => s.size(score_director),
152            Self::SubListSwap(s) => s.size(score_director),
153        }
154    }
155
156    fn append_moves<D: Director<S>>(
157        &self,
158        score_director: &D,
159        arena: &mut MoveArena<ListMoveImpl<S, V>>,
160    ) {
161        match self {
162            Self::NearbyListChange(s) => arena.extend(s.iter_moves(score_director)),
163            Self::NearbyListSwap(s) => arena.extend(s.iter_moves(score_director)),
164            Self::ListReverse(s) => arena.extend(s.iter_moves(score_director)),
165            Self::SubListChange(s) => arena.extend(s.iter_moves(score_director)),
166            Self::KOpt(s) => arena.extend(s.iter_moves(score_director)),
167            Self::NearbyKOpt(s) => arena.extend(s.iter_moves(score_director)),
168            Self::ListRuin(s) => arena.extend(s.iter_moves(score_director)),
169            Self::ListChange(s) => arena.extend(s.iter_moves(score_director)),
170            Self::ListSwap(s) => arena.extend(s.iter_moves(score_director)),
171            Self::SubListSwap(s) => arena.extend(s.iter_moves(score_director)),
172        }
173    }
174}