solverforge_solver/scope/
phase.rs

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