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}