use std::marker::PhantomData;
use solverforge_core::domain::PlanningSolution;
use solverforge_scoring::Director;
use crate::phase::Phase;
use crate::scope::SolverScope;
use crate::solver::NoTermination;
use crate::termination::Termination;
use super::builder::SolverFactoryBuilder;
pub struct SolverFactory<S, D, C, P, T> {
score_calculator: C,
phases: P,
termination: T,
_marker: PhantomData<fn(S, D, P, T)>,
}
impl<S, D, C, P, T> SolverFactory<S, D, C, P, T>
where
S: PlanningSolution,
D: Director<S>,
C: Fn(&S) -> S::Score + Send + Sync,
P: Phase<S, D>,
T: Termination<S, D>,
{
pub fn new(score_calculator: C, phases: P, termination: T) -> Self {
Self {
score_calculator,
phases,
termination,
_marker: PhantomData,
}
}
pub fn score_calculator(&self) -> &C {
&self.score_calculator
}
pub fn calculate_score(&self, solution: &S) -> S::Score {
(self.score_calculator)(solution)
}
pub fn phases(&self) -> &P {
&self.phases
}
pub fn phases_mut(&mut self) -> &mut P {
&mut self.phases
}
pub fn termination(&self) -> &T {
&self.termination
}
pub fn solve(&mut self, solver_scope: &mut SolverScope<S, D>) {
solver_scope.start_solving();
self.phases.solve(solver_scope);
}
pub fn create_solver(self) -> crate::solver::Solver<'static, P, Option<T>, S, ()> {
crate::solver::Solver::new(self.phases).with_termination(self.termination)
}
}
pub fn solver_factory_builder<S, D, C>(
score_calculator: C,
) -> SolverFactoryBuilder<S, D, C, (), NoTermination>
where
S: PlanningSolution,
C: Fn(&S) -> S::Score + Send + Sync,
{
SolverFactoryBuilder::new(score_calculator)
}
impl<S: PlanningSolution> SolverFactory<S, (), (), (), ()> {
pub fn builder<D, C>(score_calculator: C) -> SolverFactoryBuilder<S, D, C, (), NoTermination>
where
C: Fn(&S) -> S::Score + Send + Sync,
{
SolverFactoryBuilder::new(score_calculator)
}
}