Skip to main content

solverforge_solver/manager/
solver_factory.rs

1/* SolverFactory with zero-erasure design.
2
3Low-level solver infrastructure for building and executing solve phases.
4For async job management, see [`SolverManager`](super::SolverManager).
5*/
6
7use std::marker::PhantomData;
8
9use solverforge_core::domain::PlanningSolution;
10use solverforge_scoring::Director;
11
12use crate::phase::Phase;
13use crate::scope::SolverScope;
14use crate::solver::NoTermination;
15use crate::termination::Termination;
16
17use super::builder::SolverFactoryBuilder;
18
19/// Zero-erasure solver factory.
20///
21/// Stores phases as a concrete tuple type `P`, score calculator as `C`,
22/// and termination as `T`. No dynamic dispatch anywhere.
23///
24/// # Type Parameters
25///
26/// * `S` - The solution type
27/// * `D` - The score director type
28/// * `C` - The score calculator type
29/// * `P` - The phases tuple type
30/// * `T` - The termination type
31pub struct SolverFactory<S, D, C, P, T> {
32    score_calculator: C,
33    phases: P,
34    termination: T,
35    _marker: PhantomData<fn(S, D, P, T)>,
36}
37
38impl<S, D, C, P, T> SolverFactory<S, D, C, P, T>
39where
40    S: PlanningSolution,
41    D: Director<S>,
42    C: Fn(&S) -> S::Score + Send + Sync,
43    P: Phase<S, D>,
44    T: Termination<S, D>,
45{
46    pub fn new(score_calculator: C, phases: P, termination: T) -> Self {
47        Self {
48            score_calculator,
49            phases,
50            termination,
51            _marker: PhantomData,
52        }
53    }
54
55    pub fn score_calculator(&self) -> &C {
56        &self.score_calculator
57    }
58
59    /// Calculates score for a solution.
60    pub fn calculate_score(&self, solution: &S) -> S::Score {
61        (self.score_calculator)(solution)
62    }
63
64    pub fn phases(&self) -> &P {
65        &self.phases
66    }
67
68    pub fn phases_mut(&mut self) -> &mut P {
69        &mut self.phases
70    }
71
72    pub fn termination(&self) -> &T {
73        &self.termination
74    }
75
76    /// Solves using the configured phases and termination.
77    pub fn solve(&mut self, solver_scope: &mut SolverScope<S, D>) {
78        solver_scope.start_solving();
79        self.phases.solve(solver_scope);
80    }
81
82    /// Creates a Solver from this factory's configuration.
83    ///
84    /// The returned Solver can be used with `solve_with_director()` for
85    /// macro-generated code or `solve()` for direct use.
86    pub fn create_solver(self) -> crate::solver::Solver<'static, P, Option<T>, S, ()> {
87        crate::solver::Solver::new(self.phases).with_termination(self.termination)
88    }
89}
90
91/// Creates a builder for SolverFactory.
92///
93/// Use `SolverFactoryBuilder::new()` directly for full type control.
94pub fn solver_factory_builder<S, D, C>(
95    score_calculator: C,
96) -> SolverFactoryBuilder<S, D, C, (), NoTermination>
97where
98    S: PlanningSolution,
99    C: Fn(&S) -> S::Score + Send + Sync,
100{
101    SolverFactoryBuilder::new(score_calculator)
102}
103
104impl<S: PlanningSolution> SolverFactory<S, (), (), (), ()> {
105    /// Creates a new builder for SolverFactory.
106    ///
107    /// This allows calling `SolverFactory::<MySolution>::builder(score_fn)`
108    /// to start building a solver factory.
109    ///
110    /// # Example
111    ///
112    /// ```
113    /// use solverforge_core::domain::PlanningSolution;
114    /// use solverforge_core::score::SoftScore;
115    /// use solverforge_solver::manager::solver_factory_builder;
116    ///
117    /// #[derive(Clone)]
118    /// struct MySolution {
119    ///     score: Option<SoftScore>,
120    /// }
121    ///
122    /// impl PlanningSolution for MySolution {
123    ///     type Score = SoftScore;
124    ///     fn score(&self) -> Option<Self::Score> { self.score }
125    ///     fn set_score(&mut self, score: Option<Self::Score>) { self.score = score; }
126    /// }
127    ///
128    /// let builder = solver_factory_builder::<MySolution, (), _>(|_s| SoftScore::of(0));
129    /// ```
130    pub fn builder<D, C>(score_calculator: C) -> SolverFactoryBuilder<S, D, C, (), NoTermination>
131    where
132        C: Fn(&S) -> S::Score + Send + Sync,
133    {
134        SolverFactoryBuilder::new(score_calculator)
135    }
136}