Skip to main content

solverforge_solver/scope/
phase.rs

1//! Phase-level scope.
2
3use std::time::Instant;
4
5use solverforge_core::domain::PlanningSolution;
6use solverforge_scoring::Director;
7
8use super::solver::BestSolutionCallback;
9use super::SolverScope;
10use crate::stats::PhaseStats;
11
12/// Scope for a single phase of solving.
13///
14/// # Type Parameters
15/// * `'t` - Lifetime of the termination flag
16/// * `'a` - Lifetime of the solver scope reference
17/// * `S` - The planning solution type
18/// * `D` - The score director type
19/// * `BestCb` - The best-solution callback type
20pub struct PhaseScope<'t, 'a, S: PlanningSolution, D: Director<S>, BestCb = ()> {
21    /// Reference to the parent solver scope.
22    solver_scope: &'a mut SolverScope<'t, S, D, BestCb>,
23    /// Index of this phase (0-based).
24    phase_index: usize,
25    /// Score at the start of this phase.
26    starting_score: Option<S::Score>,
27    /// Number of steps in this phase.
28    step_count: u64,
29    /// When this phase started.
30    start_time: Instant,
31    /// Phase statistics.
32    stats: PhaseStats,
33}
34
35impl<'t, 'a, S: PlanningSolution, D: Director<S>, BestCb: BestSolutionCallback<S>>
36    PhaseScope<'t, 'a, S, D, BestCb>
37{
38    /// Creates a new phase scope.
39    pub fn new(solver_scope: &'a mut SolverScope<'t, S, D, BestCb>, phase_index: usize) -> Self {
40        let starting_score = solver_scope.best_score().cloned();
41        Self {
42            solver_scope,
43            phase_index,
44            starting_score,
45            step_count: 0,
46            start_time: Instant::now(),
47            stats: PhaseStats::new(phase_index, "Unknown"),
48        }
49    }
50
51    /// Creates a new phase scope with a specific phase type name.
52    pub fn with_phase_type(
53        solver_scope: &'a mut SolverScope<'t, S, D, BestCb>,
54        phase_index: usize,
55        phase_type: &'static str,
56    ) -> Self {
57        let starting_score = solver_scope.best_score().cloned();
58        Self {
59            solver_scope,
60            phase_index,
61            starting_score,
62            step_count: 0,
63            start_time: Instant::now(),
64            stats: PhaseStats::new(phase_index, phase_type),
65        }
66    }
67
68    /// Returns the phase index.
69    pub fn phase_index(&self) -> usize {
70        self.phase_index
71    }
72
73    /// Returns the starting score for this phase.
74    pub fn starting_score(&self) -> Option<&S::Score> {
75        self.starting_score.as_ref()
76    }
77
78    /// Returns the elapsed time for this phase.
79    pub fn elapsed(&self) -> std::time::Duration {
80        self.start_time.elapsed()
81    }
82
83    /// Returns the step count for this phase.
84    pub fn step_count(&self) -> u64 {
85        self.step_count
86    }
87
88    /// Increments the phase step count.
89    pub fn increment_step_count(&mut self) -> u64 {
90        self.step_count += 1;
91        self.solver_scope.increment_step_count();
92        self.step_count
93    }
94
95    /// Returns a reference to the solver scope.
96    pub fn solver_scope(&self) -> &SolverScope<'t, S, D, BestCb> {
97        self.solver_scope
98    }
99
100    /// Returns a mutable reference to the solver scope.
101    pub fn solver_scope_mut(&mut self) -> &mut SolverScope<'t, S, D, BestCb> {
102        self.solver_scope
103    }
104
105    /// Returns a reference to the score director.
106    pub fn score_director(&self) -> &D {
107        self.solver_scope.score_director()
108    }
109
110    /// Returns a mutable reference to the score director.
111    pub fn score_director_mut(&mut self) -> &mut D {
112        self.solver_scope.score_director_mut()
113    }
114
115    /// Calculates the current score.
116    pub fn calculate_score(&mut self) -> S::Score {
117        self.solver_scope.calculate_score()
118    }
119
120    /// Updates best solution.
121    pub fn update_best_solution(&mut self) {
122        self.solver_scope.update_best_solution()
123    }
124
125    /// Returns a reference to the phase statistics.
126    pub fn stats(&self) -> &PhaseStats {
127        &self.stats
128    }
129
130    /// Returns a mutable reference to the phase statistics.
131    pub fn stats_mut(&mut self) -> &mut PhaseStats {
132        &mut self.stats
133    }
134}