solverforge_solver/phase/
mod.rs

1//! Solver phases for different solving strategies
2//!
3//! Phases are the main building blocks of solving:
4//! - ConstructionHeuristicPhase: Builds an initial solution
5//! - LocalSearchPhase: Improves an existing solution
6//! - ExhaustiveSearchPhase: Explores entire solution space
7//! - PartitionedSearchPhase: Parallel solving via partitioning
8//! - VndPhase: Variable Neighborhood Descent
9//! - BasicConstructionPhase/BasicLocalSearchPhase: For basic variable problems
10
11pub mod basic;
12pub mod construction;
13pub mod exhaustive;
14pub mod localsearch;
15pub mod partitioned;
16pub mod vnd;
17
18use std::fmt::Debug;
19
20use solverforge_core::domain::PlanningSolution;
21use solverforge_scoring::ScoreDirector;
22
23use crate::scope::SolverScope;
24
25/// A phase of the solving process.
26///
27/// Phases are executed in sequence by the solver. Each phase has its own
28/// strategy for exploring or constructing solutions.
29///
30/// # Type Parameters
31/// * `S` - The planning solution type
32/// * `D` - The score director type
33pub trait Phase<S: PlanningSolution, D: ScoreDirector<S>>: Send + Debug {
34    /// Executes this phase.
35    ///
36    /// The phase should modify the working solution in the solver scope
37    /// and update the best solution when improvements are found.
38    fn solve(&mut self, solver_scope: &mut SolverScope<'_, S, D>);
39
40    /// Returns the name of this phase type.
41    fn phase_type_name(&self) -> &'static str;
42}
43
44/// Unit type implements Phase as a no-op (empty phase list).
45impl<S: PlanningSolution, D: ScoreDirector<S>> Phase<S, D> for () {
46    fn solve(&mut self, _solver_scope: &mut SolverScope<'_, S, D>) {
47        // No-op: empty phase list does nothing
48    }
49
50    fn phase_type_name(&self) -> &'static str {
51        "NoOp"
52    }
53}
54
55// ((), P1)
56impl<S, D, P1> Phase<S, D> for ((), P1)
57where
58    S: PlanningSolution,
59    D: ScoreDirector<S>,
60    P1: Phase<S, D>,
61{
62    fn solve(&mut self, solver_scope: &mut SolverScope<'_, S, D>) {
63        self.1.solve(solver_scope);
64    }
65
66    fn phase_type_name(&self) -> &'static str {
67        self.1.phase_type_name()
68    }
69}
70
71// (((), P1), P2)
72impl<S, D, P1, P2> Phase<S, D> for (((), P1), P2)
73where
74    S: PlanningSolution,
75    D: ScoreDirector<S>,
76    P1: Phase<S, D>,
77    P2: Phase<S, D>,
78{
79    fn solve(&mut self, solver_scope: &mut SolverScope<'_, S, D>) {
80        (self.0).1.solve(solver_scope);
81        self.1.solve(solver_scope);
82    }
83
84    fn phase_type_name(&self) -> &'static str {
85        "PhaseTuple"
86    }
87}
88
89// ((((), P1), P2), P3)
90impl<S, D, P1, P2, P3> Phase<S, D> for ((((), P1), P2), P3)
91where
92    S: PlanningSolution,
93    D: ScoreDirector<S>,
94    P1: Phase<S, D>,
95    P2: Phase<S, D>,
96    P3: Phase<S, D>,
97{
98    fn solve(&mut self, solver_scope: &mut SolverScope<'_, S, D>) {
99        ((self.0).0).1.solve(solver_scope);
100        (self.0).1.solve(solver_scope);
101        self.1.solve(solver_scope);
102    }
103
104    fn phase_type_name(&self) -> &'static str {
105        "PhaseTuple"
106    }
107}
108
109// (((((), P1), P2), P3), P4)
110impl<S, D, P1, P2, P3, P4> Phase<S, D> for (((((), P1), P2), P3), P4)
111where
112    S: PlanningSolution,
113    D: ScoreDirector<S>,
114    P1: Phase<S, D>,
115    P2: Phase<S, D>,
116    P3: Phase<S, D>,
117    P4: Phase<S, D>,
118{
119    fn solve(&mut self, solver_scope: &mut SolverScope<'_, S, D>) {
120        (((self.0).0).0).1.solve(solver_scope);
121        ((self.0).0).1.solve(solver_scope);
122        (self.0).1.solve(solver_scope);
123        self.1.solve(solver_scope);
124    }
125
126    fn phase_type_name(&self) -> &'static str {
127        "PhaseTuple"
128    }
129}