solverforge_solver/manager/
solver_factory.rs

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