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};
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 {
52 Self {
53 move_selector,
54 acceptor,
55 forager,
56 step_limit: None,
57 _marker: PhantomData,
58 }
59 }
60
61 pub fn with_step_limit(mut self, limit: u64) -> Self {
62 self.step_limit = Some(limit);
63 self
64 }
65}
66
67impl<S, M, MS> LocalSearchPhaseFactory<S, M, MS, HillClimbingAcceptor, AcceptedCountForager<S>>
70where
71 S: PlanningSolution,
72 M: Move<S>,
73 MS: MoveSelector<S, M>,
74{
75 pub fn hill_climbing(move_selector: MS) -> Self {
76 Self::new(
77 move_selector,
78 HillClimbingAcceptor::new(),
79 AcceptedCountForager::new(1),
80 )
81 }
82}
83
84impl<S, M, MS> LocalSearchPhaseFactory<S, M, MS, TabuSearchAcceptor<S>, AcceptedCountForager<S>>
85where
86 S: PlanningSolution,
87 M: Move<S>,
88 MS: MoveSelector<S, M>,
89{
90 pub fn tabu_search(move_selector: MS, tabu_size: usize) -> Self {
91 Self::new(
92 move_selector,
93 TabuSearchAcceptor::new(tabu_size),
94 AcceptedCountForager::new(1),
95 )
96 }
97}
98
99impl<S, M, MS>
100 LocalSearchPhaseFactory<S, M, MS, SimulatedAnnealingAcceptor, AcceptedCountForager<S>>
101where
102 S: PlanningSolution,
103 M: Move<S>,
104 MS: MoveSelector<S, M>,
105{
106 pub fn simulated_annealing(move_selector: MS, starting_temp: f64, decay_rate: f64) -> Self {
107 Self::new(
108 move_selector,
109 SimulatedAnnealingAcceptor::new(starting_temp, decay_rate),
110 AcceptedCountForager::new(1),
111 )
112 }
113}
114
115impl<S, M, MS> LocalSearchPhaseFactory<S, M, MS, LateAcceptanceAcceptor<S>, AcceptedCountForager<S>>
116where
117 S: PlanningSolution,
118 M: Move<S>,
119 MS: MoveSelector<S, M>,
120{
121 pub fn late_acceptance(move_selector: MS, size: usize) -> Self {
122 Self::new(
123 move_selector,
124 LateAcceptanceAcceptor::new(size),
125 AcceptedCountForager::new(1),
126 )
127 }
128}
129
130impl<S, D, M, MS, A, Fo> PhaseFactory<S, D> for LocalSearchPhaseFactory<S, M, MS, A, Fo>
131where
132 S: PlanningSolution,
133 D: Director<S>,
134 M: Move<S> + Send + Sync + 'static,
135 MS: MoveSelector<S, M> + Clone + Send + Sync + 'static,
136 A: Acceptor<S> + Clone + Send + Sync + 'static,
137 Fo: LocalSearchForager<S, M> + Clone + Send + Sync + 'static,
138{
139 type Phase = LocalSearchPhase<S, M, MS, A, Fo>;
140
141 fn create(&self) -> Self::Phase {
142 LocalSearchPhase::new(
143 self.move_selector.clone(),
144 self.acceptor.clone(),
145 self.forager.clone(),
146 self.step_limit,
147 )
148 }
149}