solverforge_solver/termination/
best_score.rs1use std::fmt::Debug;
4
5use solverforge_core::domain::PlanningSolution;
6use solverforge_core::score::Score;
7use solverforge_scoring::Director;
8
9use super::Termination;
10use crate::scope::ProgressCallback;
11use crate::scope::SolverScope;
12
13#[derive(Debug, Clone)]
29pub struct BestScoreTermination<Sc: Score> {
30 target_score: Sc,
31}
32
33impl<Sc: Score> BestScoreTermination<Sc> {
34 pub fn new(target_score: Sc) -> Self {
35 Self { target_score }
36 }
37}
38
39impl<S, D, BestCb, Sc> Termination<S, D, BestCb> for BestScoreTermination<Sc>
40where
41 S: PlanningSolution<Score = Sc>,
42 D: Director<S>,
43 BestCb: ProgressCallback<S>,
44 Sc: Score,
45{
46 fn is_terminated(&self, solver_scope: &SolverScope<S, D, BestCb>) -> bool {
47 solver_scope
48 .best_score()
49 .map(|score| *score >= self.target_score)
50 .unwrap_or(false)
51 }
52
53 fn install_inphase_limits(&self, solver_scope: &mut SolverScope<S, D, BestCb>) {
54 solver_scope.install_inphase_best_score_limit(self.target_score);
55 }
56}
57
58pub struct BestScoreFeasibleTermination<S, F>
69where
70 S: PlanningSolution,
71 F: Fn(&S::Score) -> bool + Send + Sync,
72{
73 feasibility_check: F,
74 _phantom: std::marker::PhantomData<fn() -> S>,
75}
76
77impl<S, F> Debug for BestScoreFeasibleTermination<S, F>
78where
79 S: PlanningSolution,
80 F: Fn(&S::Score) -> bool + Send + Sync,
81{
82 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83 f.debug_struct("BestScoreFeasibleTermination").finish()
84 }
85}
86
87impl<S, F> BestScoreFeasibleTermination<S, F>
88where
89 S: PlanningSolution,
90 F: Fn(&S::Score) -> bool + Send + Sync,
91{
92 pub fn new(feasibility_check: F) -> Self {
93 Self {
94 feasibility_check,
95 _phantom: std::marker::PhantomData,
96 }
97 }
98}
99
100impl<S: PlanningSolution> BestScoreFeasibleTermination<S, fn(&S::Score) -> bool> {
101 pub fn score_at_least_zero() -> Self {
105 Self::new(|score| *score >= S::Score::zero())
106 }
107}
108
109impl<S, D, BestCb, F> Termination<S, D, BestCb> for BestScoreFeasibleTermination<S, F>
110where
111 S: PlanningSolution,
112 D: Director<S>,
113 BestCb: ProgressCallback<S>,
114 F: Fn(&S::Score) -> bool + Send + Sync,
115{
116 fn is_terminated(&self, solver_scope: &SolverScope<S, D, BestCb>) -> bool {
117 solver_scope
118 .best_score()
119 .map(|score| (self.feasibility_check)(score))
120 .unwrap_or(false)
121 }
122}