Skip to main content

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