solverforge_solver/manager/phase_factory/
local_search.rs1use std::marker::PhantomData;
4
5use solverforge_core::domain::PlanningSolution;
6use solverforge_scoring::ScoreDirector;
7
8use crate::heuristic::{Move, MoveSelector};
9use crate::phase::localsearch::{
10 AcceptedCountForager, Acceptor, HillClimbingAcceptor, LateAcceptanceAcceptor,
11 LocalSearchForager, LocalSearchPhase, SimulatedAnnealingAcceptor, TabuSearchAcceptor,
12};
13
14use super::super::PhaseFactory;
15
16pub struct LocalSearchPhaseFactory<S, M, MS, A, Fo>
29where
30 S: PlanningSolution,
31 M: Move<S>,
32 MS: MoveSelector<S, M>,
33 A: Acceptor<S>,
34 Fo: LocalSearchForager<S, M>,
35{
36 move_selector: MS,
37 acceptor: A,
38 forager: Fo,
39 step_limit: Option<u64>,
40 _marker: PhantomData<fn() -> (S, M)>,
41}
42
43impl<S, M, MS, A, Fo> LocalSearchPhaseFactory<S, M, MS, A, Fo>
44where
45 S: PlanningSolution,
46 M: Move<S>,
47 MS: MoveSelector<S, M>,
48 A: Acceptor<S>,
49 Fo: LocalSearchForager<S, M>,
50{
51 pub fn new(move_selector: MS, acceptor: A, forager: Fo) -> Self {
53 Self {
54 move_selector,
55 acceptor,
56 forager,
57 step_limit: None,
58 _marker: PhantomData,
59 }
60 }
61
62 pub fn with_step_limit(mut self, limit: u64) -> Self {
64 self.step_limit = Some(limit);
65 self
66 }
67}
68
69impl<S, M, MS> LocalSearchPhaseFactory<S, M, MS, HillClimbingAcceptor, AcceptedCountForager<S>>
72where
73 S: PlanningSolution,
74 M: Move<S>,
75 MS: MoveSelector<S, M>,
76{
77 pub fn hill_climbing(move_selector: MS) -> Self {
79 Self::new(
80 move_selector,
81 HillClimbingAcceptor::new(),
82 AcceptedCountForager::new(1),
83 )
84 }
85}
86
87impl<S, M, MS> LocalSearchPhaseFactory<S, M, MS, TabuSearchAcceptor<S>, AcceptedCountForager<S>>
88where
89 S: PlanningSolution,
90 M: Move<S>,
91 MS: MoveSelector<S, M>,
92{
93 pub fn tabu_search(move_selector: MS, tabu_size: usize) -> Self {
95 Self::new(
96 move_selector,
97 TabuSearchAcceptor::new(tabu_size),
98 AcceptedCountForager::new(1),
99 )
100 }
101}
102
103impl<S, M, MS>
104 LocalSearchPhaseFactory<S, M, MS, SimulatedAnnealingAcceptor, AcceptedCountForager<S>>
105where
106 S: PlanningSolution,
107 M: Move<S>,
108 MS: MoveSelector<S, M>,
109{
110 pub fn simulated_annealing(move_selector: MS, starting_temp: f64, decay_rate: f64) -> Self {
112 Self::new(
113 move_selector,
114 SimulatedAnnealingAcceptor::new(starting_temp, decay_rate),
115 AcceptedCountForager::new(1),
116 )
117 }
118}
119
120impl<S, M, MS> LocalSearchPhaseFactory<S, M, MS, LateAcceptanceAcceptor<S>, AcceptedCountForager<S>>
121where
122 S: PlanningSolution,
123 M: Move<S>,
124 MS: MoveSelector<S, M>,
125{
126 pub fn late_acceptance(move_selector: MS, size: usize) -> Self {
128 Self::new(
129 move_selector,
130 LateAcceptanceAcceptor::new(size),
131 AcceptedCountForager::new(1),
132 )
133 }
134}
135
136impl<S, D, M, MS, A, Fo> PhaseFactory<S, D> for LocalSearchPhaseFactory<S, M, MS, A, Fo>
137where
138 S: PlanningSolution,
139 D: ScoreDirector<S>,
140 M: Move<S> + Send + Sync + 'static,
141 MS: MoveSelector<S, M> + Clone + Send + Sync + 'static,
142 A: Acceptor<S> + Clone + Send + Sync + 'static,
143 Fo: LocalSearchForager<S, M> + Clone + Send + Sync + 'static,
144{
145 type Phase = LocalSearchPhase<S, M, MS, A, Fo>;
146
147 fn create(&self) -> Self::Phase {
148 LocalSearchPhase::new(
149 self.move_selector.clone(),
150 self.acceptor.clone(),
151 self.forager.clone(),
152 self.step_limit,
153 )
154 }
155}