Skip to main content

solverforge_solver/heuristic/move/
list_either.rs

1/* ListMoveImpl - 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, SubListChangeMove,
14    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`, and `ListRuinMoveSelector`
23/// without type erasure.
24///
25/// # Example
26///
27/// ```
28/// use solverforge_solver::heuristic::r#move::ListMoveImpl;
29/// ```
30pub enum ListMoveImpl<S, V> {
31    ListChange(ListChangeMove<S, V>),
32    ListSwap(ListSwapMove<S, V>),
33    SubListChange(SubListChangeMove<S, V>),
34    SubListSwap(SubListSwapMove<S, V>),
35    ListReverse(ListReverseMove<S, V>),
36    KOpt(KOptMove<S, V>),
37    ListRuin(ListRuinMove<S, V>),
38}
39
40impl<S, V: Clone> Clone for ListMoveImpl<S, V> {
41    fn clone(&self) -> Self {
42        match self {
43            Self::ListChange(m) => Self::ListChange(*m),
44            Self::ListSwap(m) => Self::ListSwap(*m),
45            Self::SubListChange(m) => Self::SubListChange(*m),
46            Self::SubListSwap(m) => Self::SubListSwap(*m),
47            Self::ListReverse(m) => Self::ListReverse(*m),
48            Self::KOpt(m) => Self::KOpt(m.clone()),
49            Self::ListRuin(m) => Self::ListRuin(m.clone()),
50        }
51    }
52}
53
54impl<S, V: Debug> Debug for ListMoveImpl<S, V> {
55    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56        match self {
57            Self::ListChange(m) => m.fmt(f),
58            Self::ListSwap(m) => m.fmt(f),
59            Self::SubListChange(m) => m.fmt(f),
60            Self::SubListSwap(m) => m.fmt(f),
61            Self::ListReverse(m) => m.fmt(f),
62            Self::KOpt(m) => m.fmt(f),
63            Self::ListRuin(m) => m.fmt(f),
64        }
65    }
66}
67
68impl<S, V> Move<S> for ListMoveImpl<S, V>
69where
70    S: PlanningSolution,
71    V: Clone + PartialEq + Send + Sync + Debug + 'static,
72{
73    fn is_doable<D: Director<S>>(&self, score_director: &D) -> bool {
74        match self {
75            Self::ListChange(m) => m.is_doable(score_director),
76            Self::ListSwap(m) => m.is_doable(score_director),
77            Self::SubListChange(m) => m.is_doable(score_director),
78            Self::SubListSwap(m) => m.is_doable(score_director),
79            Self::ListReverse(m) => m.is_doable(score_director),
80            Self::KOpt(m) => m.is_doable(score_director),
81            Self::ListRuin(m) => m.is_doable(score_director),
82        }
83    }
84
85    fn do_move<D: Director<S>>(&self, score_director: &mut D) {
86        match self {
87            Self::ListChange(m) => m.do_move(score_director),
88            Self::ListSwap(m) => m.do_move(score_director),
89            Self::SubListChange(m) => m.do_move(score_director),
90            Self::SubListSwap(m) => m.do_move(score_director),
91            Self::ListReverse(m) => m.do_move(score_director),
92            Self::KOpt(m) => m.do_move(score_director),
93            Self::ListRuin(m) => m.do_move(score_director),
94        }
95    }
96
97    fn descriptor_index(&self) -> usize {
98        match self {
99            Self::ListChange(m) => m.descriptor_index(),
100            Self::ListSwap(m) => m.descriptor_index(),
101            Self::SubListChange(m) => m.descriptor_index(),
102            Self::SubListSwap(m) => m.descriptor_index(),
103            Self::ListReverse(m) => m.descriptor_index(),
104            Self::KOpt(m) => m.descriptor_index(),
105            Self::ListRuin(m) => m.descriptor_index(),
106        }
107    }
108
109    fn entity_indices(&self) -> &[usize] {
110        match self {
111            Self::ListChange(m) => m.entity_indices(),
112            Self::ListSwap(m) => m.entity_indices(),
113            Self::SubListChange(m) => m.entity_indices(),
114            Self::SubListSwap(m) => m.entity_indices(),
115            Self::ListReverse(m) => m.entity_indices(),
116            Self::KOpt(m) => m.entity_indices(),
117            Self::ListRuin(m) => m.entity_indices(),
118        }
119    }
120
121    fn variable_name(&self) -> &str {
122        match self {
123            Self::ListChange(m) => m.variable_name(),
124            Self::ListSwap(m) => m.variable_name(),
125            Self::SubListChange(m) => m.variable_name(),
126            Self::SubListSwap(m) => m.variable_name(),
127            Self::ListReverse(m) => m.variable_name(),
128            Self::KOpt(m) => m.variable_name(),
129            Self::ListRuin(m) => m.variable_name(),
130        }
131    }
132}