use std::fmt::Debug;
use solverforge_core::domain::PlanningSolution;
use solverforge_core::score::Score;
use solverforge_scoring::Director;
use super::Termination;
use crate::scope::ProgressCallback;
use crate::scope::SolverScope;
#[derive(Debug, Clone)]
pub struct BestScoreTermination<Sc: Score> {
target_score: Sc,
}
impl<Sc: Score> BestScoreTermination<Sc> {
pub fn new(target_score: Sc) -> Self {
Self { target_score }
}
}
impl<S, D, BestCb, Sc> Termination<S, D, BestCb> for BestScoreTermination<Sc>
where
S: PlanningSolution<Score = Sc>,
D: Director<S>,
BestCb: ProgressCallback<S>,
Sc: Score,
{
fn is_terminated(&self, solver_scope: &SolverScope<S, D, BestCb>) -> bool {
solver_scope
.best_score()
.map(|score| *score >= self.target_score)
.unwrap_or(false)
}
}
pub struct BestScoreFeasibleTermination<S, F>
where
S: PlanningSolution,
F: Fn(&S::Score) -> bool + Send + Sync,
{
feasibility_check: F,
_phantom: std::marker::PhantomData<fn() -> S>,
}
impl<S, F> Debug for BestScoreFeasibleTermination<S, F>
where
S: PlanningSolution,
F: Fn(&S::Score) -> bool + Send + Sync,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("BestScoreFeasibleTermination").finish()
}
}
impl<S, F> BestScoreFeasibleTermination<S, F>
where
S: PlanningSolution,
F: Fn(&S::Score) -> bool + Send + Sync,
{
pub fn new(feasibility_check: F) -> Self {
Self {
feasibility_check,
_phantom: std::marker::PhantomData,
}
}
}
impl<S: PlanningSolution> BestScoreFeasibleTermination<S, fn(&S::Score) -> bool> {
pub fn score_at_least_zero() -> Self {
Self::new(|score| *score >= S::Score::zero())
}
}
impl<S, D, BestCb, F> Termination<S, D, BestCb> for BestScoreFeasibleTermination<S, F>
where
S: PlanningSolution,
D: Director<S>,
BestCb: ProgressCallback<S>,
F: Fn(&S::Score) -> bool + Send + Sync,
{
fn is_terminated(&self, solver_scope: &SolverScope<S, D, BestCb>) -> bool {
solver_scope
.best_score()
.map(|score| (self.feasibility_check)(score))
.unwrap_or(false)
}
}