solverforge_solver/termination/
move_count.rs

1//! Move count termination.
2
3use std::fmt::Debug;
4use std::marker::PhantomData;
5
6use solverforge_core::domain::PlanningSolution;
7use solverforge_scoring::ScoreDirector;
8
9use super::Termination;
10use crate::scope::SolverScope;
11
12/// Terminates when a maximum number of moves have been evaluated.
13///
14/// # Example
15///
16/// ```
17/// use solverforge_solver::termination::MoveCountTermination;
18/// use solverforge_core::score::SimpleScore;
19/// use solverforge_core::domain::PlanningSolution;
20///
21/// #[derive(Clone)]
22/// struct MySolution;
23/// impl PlanningSolution for MySolution {
24///     type Score = SimpleScore;
25///     fn score(&self) -> Option<Self::Score> { None }
26///     fn set_score(&mut self, _: Option<Self::Score>) {}
27/// }
28///
29/// // Terminate after evaluating 100,000 moves
30/// let termination = MoveCountTermination::<MySolution>::new(100_000);
31/// ```
32#[derive(Clone)]
33pub struct MoveCountTermination<S: PlanningSolution> {
34    limit: u64,
35    _phantom: PhantomData<fn() -> S>,
36}
37
38impl<S: PlanningSolution> Debug for MoveCountTermination<S> {
39    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40        f.debug_struct("MoveCountTermination")
41            .field("limit", &self.limit)
42            .finish()
43    }
44}
45
46impl<S: PlanningSolution> MoveCountTermination<S> {
47    /// Creates a new move count termination.
48    ///
49    /// # Arguments
50    /// * `limit` - Maximum moves to evaluate before terminating
51    pub fn new(limit: u64) -> Self {
52        Self {
53            limit,
54            _phantom: PhantomData,
55        }
56    }
57}
58
59impl<S: PlanningSolution, D: ScoreDirector<S>> Termination<S, D> for MoveCountTermination<S> {
60    fn is_terminated(&self, solver_scope: &SolverScope<'_, S, D>) -> bool {
61        solver_scope.stats().moves_evaluated >= self.limit
62    }
63}