Skip to main content

solverforge_solver/termination/
score_calculation_count.rs

1// Score calculation count termination.
2
3use std::fmt::Debug;
4use std::marker::PhantomData;
5
6use solverforge_core::domain::PlanningSolution;
7use solverforge_scoring::Director;
8
9use super::Termination;
10use crate::scope::BestSolutionCallback;
11use crate::scope::SolverScope;
12
13/* Terminates when a maximum number of score calculations is reached.
14
15# Example
16
17```
18use solverforge_solver::termination::ScoreCalculationCountTermination;
19use solverforge_core::score::SoftScore;
20use solverforge_core::domain::PlanningSolution;
21
22#[derive(Clone)]
23struct MySolution;
24impl PlanningSolution for MySolution {
25type Score = SoftScore;
26fn score(&self) -> Option<Self::Score> { None }
27fn set_score(&mut self, _: Option<Self::Score>) {}
28}
29
30// Terminate after 10,000 score calculations
31let termination = ScoreCalculationCountTermination::<MySolution>::new(10_000);
32```
33*/
34#[derive(Clone)]
35pub struct ScoreCalculationCountTermination<S: PlanningSolution> {
36    limit: u64,
37    _phantom: PhantomData<fn() -> S>,
38}
39
40impl<S: PlanningSolution> Debug for ScoreCalculationCountTermination<S> {
41    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42        f.debug_struct("ScoreCalculationCountTermination")
43            .field("limit", &self.limit)
44            .finish()
45    }
46}
47
48impl<S: PlanningSolution> ScoreCalculationCountTermination<S> {
49    /// Creates a new score calculation count termination.
50    ///
51    /// # Arguments
52    /// * `limit` - Maximum score calculations before terminating
53    pub fn new(limit: u64) -> Self {
54        Self {
55            limit,
56            _phantom: PhantomData,
57        }
58    }
59}
60
61impl<S: PlanningSolution, D: Director<S>, BestCb: BestSolutionCallback<S>> Termination<S, D, BestCb>
62    for ScoreCalculationCountTermination<S>
63{
64    fn is_terminated(&self, solver_scope: &SolverScope<'_, S, D, BestCb>) -> bool {
65        solver_scope.stats().score_calculations >= self.limit
66    }
67
68    fn install_inphase_limits(&self, solver_scope: &mut SolverScope<S, D, BestCb>) {
69        let limit = match solver_scope.inphase_score_calc_count_limit {
70            Some(existing) => existing.min(self.limit),
71            None => self.limit,
72        };
73        solver_scope.inphase_score_calc_count_limit = Some(limit);
74    }
75}