solverforge_solver/builder/
basic_selector.rs1use std::fmt::Debug;
4
5use solverforge_config::MoveSelectorConfig;
6use solverforge_core::domain::PlanningSolution;
7use solverforge_scoring::Director;
8
9use crate::heuristic::r#move::EitherMove;
10use crate::heuristic::selector::decorator::VecUnionSelector;
11use crate::heuristic::selector::typed_move_selector::MoveSelector;
12use crate::heuristic::selector::{
13 EitherChangeMoveSelector, EitherSwapMoveSelector, FromSolutionEntitySelector,
14};
15
16use super::context::BasicContext;
17
18pub enum BasicLeafSelector<S: PlanningSolution> {
24 Change(
26 EitherChangeMoveSelector<
27 S,
28 usize,
29 FromSolutionEntitySelector,
30 crate::heuristic::selector::typed_value::StaticTypedValueSelector<S, usize>,
31 >,
32 ),
33 Swap(EitherSwapMoveSelector<S, usize, FromSolutionEntitySelector, FromSolutionEntitySelector>),
35}
36
37impl<S: PlanningSolution> Debug for BasicLeafSelector<S> {
38 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39 match self {
40 Self::Change(s) => write!(f, "BasicLeafSelector::Change({s:?})"),
41 Self::Swap(s) => write!(f, "BasicLeafSelector::Swap({s:?})"),
42 }
43 }
44}
45
46impl<S> MoveSelector<S, EitherMove<S, usize>> for BasicLeafSelector<S>
47where
48 S: PlanningSolution,
49{
50 fn iter_moves<'a, D: Director<S>>(
51 &'a self,
52 score_director: &'a D,
53 ) -> impl Iterator<Item = EitherMove<S, usize>> + 'a {
54 match self {
55 Self::Change(s) => {
56 let moves: Vec<_> = s.iter_moves(score_director).collect();
57 moves.into_iter()
58 }
59 Self::Swap(s) => {
60 let moves: Vec<_> = s.iter_moves(score_director).collect();
61 moves.into_iter()
62 }
63 }
64 }
65
66 fn size<D: Director<S>>(&self, score_director: &D) -> usize {
67 match self {
68 Self::Change(s) => s.size(score_director),
69 Self::Swap(s) => s.size(score_director),
70 }
71 }
72}
73
74pub struct BasicMoveSelectorBuilder;
76
77impl BasicMoveSelectorBuilder {
78 pub fn build<S>(
85 config: Option<&MoveSelectorConfig>,
86 ctx: &BasicContext<S>,
87 ) -> VecUnionSelector<S, EitherMove<S, usize>, BasicLeafSelector<S>>
88 where
89 S: PlanningSolution,
90 {
91 let mut leaves: Vec<BasicLeafSelector<S>> = Vec::new();
92 match config {
93 None => {
94 Self::push_change(&mut leaves, ctx);
95 Self::push_swap(&mut leaves, ctx);
96 }
97 Some(cfg) => Self::collect_leaves(cfg, ctx, &mut leaves),
98 }
99 VecUnionSelector::new(leaves)
100 }
101
102 fn collect_leaves<S>(
103 config: &MoveSelectorConfig,
104 ctx: &BasicContext<S>,
105 out: &mut Vec<BasicLeafSelector<S>>,
106 ) where
107 S: PlanningSolution,
108 {
109 match config {
110 MoveSelectorConfig::ChangeMoveSelector(_) => Self::push_change(out, ctx),
111 MoveSelectorConfig::SwapMoveSelector(_) => Self::push_swap(out, ctx),
112 MoveSelectorConfig::UnionMoveSelector(u) => {
113 for child in &u.selectors {
114 Self::collect_leaves(child, ctx, out);
115 }
116 }
117 _ => {
119 Self::push_change(out, ctx);
121 Self::push_swap(out, ctx);
122 }
123 }
124 }
125
126 fn push_change<S>(out: &mut Vec<BasicLeafSelector<S>>, ctx: &BasicContext<S>)
127 where
128 S: PlanningSolution,
129 {
130 out.push(BasicLeafSelector::Change(EitherChangeMoveSelector::simple(
131 ctx.get_variable,
132 ctx.set_variable,
133 ctx.descriptor_index,
134 ctx.variable_field,
135 ctx.values.clone(),
136 )));
137 }
138
139 fn push_swap<S>(out: &mut Vec<BasicLeafSelector<S>>, ctx: &BasicContext<S>)
140 where
141 S: PlanningSolution,
142 {
143 out.push(BasicLeafSelector::Swap(EitherSwapMoveSelector::simple(
144 ctx.get_variable,
145 ctx.set_variable,
146 ctx.descriptor_index,
147 ctx.variable_field,
148 )));
149 }
150}