solverforge_solver/termination/
best_score.rs1use std::fmt::Debug;
4
5use solverforge_core::domain::PlanningSolution;
6use solverforge_core::score::Score;
7
8use super::Termination;
9use crate::scope::SolverScope;
10
11#[derive(Debug, Clone)]
26pub struct BestScoreTermination<Sc: Score> {
27 target_score: Sc,
28}
29
30impl<Sc: Score> BestScoreTermination<Sc> {
31 pub fn new(target_score: Sc) -> Self {
33 Self { target_score }
34 }
35}
36
37impl<S, Sc> Termination<S> for BestScoreTermination<Sc>
38where
39 S: PlanningSolution<Score = Sc>,
40 Sc: Score,
41{
42 fn is_terminated(&self, solver_scope: &SolverScope<S>) -> bool {
43 solver_scope
44 .best_score()
45 .map(|score| *score >= self.target_score)
46 .unwrap_or(false)
47 }
48}
49
50pub struct BestScoreFeasibleTermination<S, F>
61where
62 S: PlanningSolution,
63 F: Fn(&S::Score) -> bool + Send + Sync,
64{
65 feasibility_check: F,
66 _phantom: std::marker::PhantomData<S>,
67}
68
69impl<S, F> Debug for BestScoreFeasibleTermination<S, F>
70where
71 S: PlanningSolution,
72 F: Fn(&S::Score) -> bool + Send + Sync,
73{
74 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75 f.debug_struct("BestScoreFeasibleTermination").finish()
76 }
77}
78
79impl<S, F> BestScoreFeasibleTermination<S, F>
80where
81 S: PlanningSolution,
82 F: Fn(&S::Score) -> bool + Send + Sync,
83{
84 pub fn new(feasibility_check: F) -> Self {
86 Self {
87 feasibility_check,
88 _phantom: std::marker::PhantomData,
89 }
90 }
91}
92
93impl<S: PlanningSolution> BestScoreFeasibleTermination<S, fn(&S::Score) -> bool> {
94 pub fn score_at_least_zero() -> Self {
98 Self::new(|score| *score >= S::Score::zero())
99 }
100}
101
102impl<S, F> Termination<S> for BestScoreFeasibleTermination<S, F>
103where
104 S: PlanningSolution,
105 F: Fn(&S::Score) -> bool + Send + Sync,
106{
107 fn is_terminated(&self, solver_scope: &SolverScope<S>) -> bool {
108 solver_scope
109 .best_score()
110 .map(|score| (self.feasibility_check)(score))
111 .unwrap_or(false)
112 }
113}