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