Skip to main content

solverforge_solver/heuristic/move/
list_union.rs

1/* ListMoveUnion - a monomorphized union of all list-variable move types.
2
3This allows local search to combine all list move types in a single arena
4without trait-object dispatch.
5*/
6
7use std::fmt::Debug;
8
9use solverforge_core::domain::PlanningSolution;
10use solverforge_scoring::Director;
11
12use super::{
13    KOptMove, ListChangeMove, ListReverseMove, ListRuinMove, ListSwapMove, Move, MoveTabuSignature,
14    SequentialCompositeMove, SublistChangeMove, SublistSwapMove,
15};
16
17/// A monomorphized union of all list-variable move types.
18///
19/// Implements `Move<S>` by delegating to the inner variant.
20/// Enables combining `ListChangeMoveSelector`, `ListSwapMoveSelector`,
21/// `SublistChangeMoveSelector`, `SublistSwapMoveSelector`,
22/// `ListReverseMoveSelector`, `KOptMoveSelector`, `ListRuinMoveSelector`, and
23/// cartesian composites without type erasure.
24///
25/// # Example
26///
27/// ```
28/// use solverforge_solver::heuristic::r#move::ListMoveUnion;
29/// ```
30#[allow(clippy::large_enum_variant)]
31pub enum ListMoveUnion<S, V> {
32    ListChange(ListChangeMove<S, V>),
33    ListSwap(ListSwapMove<S, V>),
34    SublistChange(SublistChangeMove<S, V>),
35    SublistSwap(SublistSwapMove<S, V>),
36    ListReverse(ListReverseMove<S, V>),
37    KOpt(KOptMove<S, V>),
38    ListRuin(ListRuinMove<S, V>),
39    Composite(SequentialCompositeMove<S, ListMoveUnion<S, V>>),
40}
41
42impl<S, V> Clone for ListMoveUnion<S, V>
43where
44    S: PlanningSolution,
45    V: Clone + PartialEq + Send + Sync + Debug + 'static,
46{
47    fn clone(&self) -> Self {
48        match self {
49            Self::ListChange(m) => Self::ListChange(*m),
50            Self::ListSwap(m) => Self::ListSwap(*m),
51            Self::SublistChange(m) => Self::SublistChange(*m),
52            Self::SublistSwap(m) => Self::SublistSwap(*m),
53            Self::ListReverse(m) => Self::ListReverse(*m),
54            Self::KOpt(m) => Self::KOpt(m.clone()),
55            Self::ListRuin(m) => Self::ListRuin(m.clone()),
56            Self::Composite(m) => Self::Composite(m.clone()),
57        }
58    }
59}
60
61impl<S, V> Debug for ListMoveUnion<S, V>
62where
63    S: PlanningSolution,
64    V: Clone + PartialEq + Send + Sync + Debug + 'static,
65{
66    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67        match self {
68            Self::ListChange(m) => m.fmt(f),
69            Self::ListSwap(m) => m.fmt(f),
70            Self::SublistChange(m) => m.fmt(f),
71            Self::SublistSwap(m) => m.fmt(f),
72            Self::ListReverse(m) => m.fmt(f),
73            Self::KOpt(m) => m.fmt(f),
74            Self::ListRuin(m) => m.fmt(f),
75            Self::Composite(m) => m.fmt(f),
76        }
77    }
78}
79
80impl<S, V> Move<S> for ListMoveUnion<S, V>
81where
82    S: PlanningSolution,
83    V: Clone + PartialEq + Send + Sync + Debug + 'static,
84{
85    fn is_doable<D: Director<S>>(&self, score_director: &D) -> bool {
86        match self {
87            Self::ListChange(m) => m.is_doable(score_director),
88            Self::ListSwap(m) => m.is_doable(score_director),
89            Self::SublistChange(m) => m.is_doable(score_director),
90            Self::SublistSwap(m) => m.is_doable(score_director),
91            Self::ListReverse(m) => m.is_doable(score_director),
92            Self::KOpt(m) => m.is_doable(score_director),
93            Self::ListRuin(m) => m.is_doable(score_director),
94            Self::Composite(m) => m.is_doable(score_director),
95        }
96    }
97
98    fn do_move<D: Director<S>>(&self, score_director: &mut D) {
99        match self {
100            Self::ListChange(m) => m.do_move(score_director),
101            Self::ListSwap(m) => m.do_move(score_director),
102            Self::SublistChange(m) => m.do_move(score_director),
103            Self::SublistSwap(m) => m.do_move(score_director),
104            Self::ListReverse(m) => m.do_move(score_director),
105            Self::KOpt(m) => m.do_move(score_director),
106            Self::ListRuin(m) => m.do_move(score_director),
107            Self::Composite(m) => m.do_move(score_director),
108        }
109    }
110
111    fn descriptor_index(&self) -> usize {
112        match self {
113            Self::ListChange(m) => m.descriptor_index(),
114            Self::ListSwap(m) => m.descriptor_index(),
115            Self::SublistChange(m) => m.descriptor_index(),
116            Self::SublistSwap(m) => m.descriptor_index(),
117            Self::ListReverse(m) => m.descriptor_index(),
118            Self::KOpt(m) => m.descriptor_index(),
119            Self::ListRuin(m) => m.descriptor_index(),
120            Self::Composite(m) => m.descriptor_index(),
121        }
122    }
123
124    fn entity_indices(&self) -> &[usize] {
125        match self {
126            Self::ListChange(m) => m.entity_indices(),
127            Self::ListSwap(m) => m.entity_indices(),
128            Self::SublistChange(m) => m.entity_indices(),
129            Self::SublistSwap(m) => m.entity_indices(),
130            Self::ListReverse(m) => m.entity_indices(),
131            Self::KOpt(m) => m.entity_indices(),
132            Self::ListRuin(m) => m.entity_indices(),
133            Self::Composite(m) => m.entity_indices(),
134        }
135    }
136
137    fn variable_name(&self) -> &str {
138        match self {
139            Self::ListChange(m) => m.variable_name(),
140            Self::ListSwap(m) => m.variable_name(),
141            Self::SublistChange(m) => m.variable_name(),
142            Self::SublistSwap(m) => m.variable_name(),
143            Self::ListReverse(m) => m.variable_name(),
144            Self::KOpt(m) => m.variable_name(),
145            Self::ListRuin(m) => m.variable_name(),
146            Self::Composite(m) => m.variable_name(),
147        }
148    }
149
150    fn tabu_signature<D: Director<S>>(&self, score_director: &D) -> MoveTabuSignature {
151        match self {
152            Self::ListChange(m) => m.tabu_signature(score_director),
153            Self::ListSwap(m) => m.tabu_signature(score_director),
154            Self::SublistChange(m) => m.tabu_signature(score_director),
155            Self::SublistSwap(m) => m.tabu_signature(score_director),
156            Self::ListReverse(m) => m.tabu_signature(score_director),
157            Self::KOpt(m) => m.tabu_signature(score_director),
158            Self::ListRuin(m) => m.tabu_signature(score_director),
159            Self::Composite(m) => m.tabu_signature(score_director),
160        }
161    }
162}