Skip to main content

solverforge_solver/heuristic/move/
list_either.rs

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