solverforge_solver/scope/
phase.rs1use std::time::Duration;
4use std::time::Instant;
5
6use solverforge_core::domain::PlanningSolution;
7use solverforge_scoring::Director;
8
9use super::solver::ProgressCallback;
10use super::SolverScope;
11use crate::stats::PhaseStats;
12
13pub struct PhaseScope<'t, 'a, S: PlanningSolution, D: Director<S>, BestCb = ()> {
22 solver_scope: &'a mut SolverScope<'t, S, D, BestCb>,
24 phase_index: usize,
26 starting_score: Option<S::Score>,
28 step_count: u64,
30 start_time: Instant,
32 stats: PhaseStats,
34}
35
36impl<'t, 'a, S: PlanningSolution, D: Director<S>, BestCb: ProgressCallback<S>>
37 PhaseScope<'t, 'a, S, D, BestCb>
38{
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 pub fn with_phase_type(
52 solver_scope: &'a mut SolverScope<'t, S, D, BestCb>,
53 phase_index: usize,
54 phase_type: &'static str,
55 ) -> Self {
56 let starting_score = solver_scope.best_score().cloned();
57 Self {
58 solver_scope,
59 phase_index,
60 starting_score,
61 step_count: 0,
62 start_time: Instant::now(),
63 stats: PhaseStats::new(phase_index, phase_type),
64 }
65 }
66
67 pub fn phase_index(&self) -> usize {
68 self.phase_index
69 }
70
71 pub fn starting_score(&self) -> Option<&S::Score> {
72 self.starting_score.as_ref()
73 }
74
75 pub fn elapsed(&self) -> std::time::Duration {
76 self.start_time.elapsed()
77 }
78
79 pub fn step_count(&self) -> u64 {
80 self.step_count
81 }
82
83 pub fn increment_step_count(&mut self) -> u64 {
85 self.step_count += 1;
86 self.stats.record_step();
87 self.solver_scope.increment_step_count();
88 self.step_count
89 }
90
91 pub fn solver_scope(&self) -> &SolverScope<'t, S, D, BestCb> {
92 self.solver_scope
93 }
94
95 pub fn solver_scope_mut(&mut self) -> &mut SolverScope<'t, S, D, BestCb> {
96 self.solver_scope
97 }
98
99 pub fn score_director(&self) -> &D {
100 self.solver_scope.score_director()
101 }
102
103 pub fn score_director_mut(&mut self) -> &mut D {
104 self.solver_scope.score_director_mut()
105 }
106
107 pub fn calculate_score(&mut self) -> S::Score {
109 self.stats.record_score_calculation();
110 self.solver_scope.calculate_score()
111 }
112
113 pub fn update_best_solution(&mut self) {
115 self.solver_scope.update_best_solution()
116 }
117
118 pub fn stats(&self) -> &PhaseStats {
119 &self.stats
120 }
121
122 pub fn stats_mut(&mut self) -> &mut PhaseStats {
123 &mut self.stats
124 }
125
126 pub fn record_generated_batch(&mut self, count: u64, duration: Duration) {
127 self.stats.record_generated_batch(count, duration);
128 self.solver_scope
129 .stats_mut()
130 .record_generated_batch(count, duration);
131 }
132
133 pub fn record_generated_move(&mut self, duration: Duration) {
134 self.record_generated_batch(1, duration);
135 }
136
137 pub fn record_generation_time(&mut self, duration: Duration) {
138 self.stats.record_generation_time(duration);
139 self.solver_scope
140 .stats_mut()
141 .record_generation_time(duration);
142 }
143
144 pub fn record_evaluated_move(&mut self, duration: Duration) {
145 self.stats.record_evaluated_move(duration);
146 self.solver_scope
147 .stats_mut()
148 .record_evaluated_move(duration);
149 }
150
151 pub fn record_move_accepted(&mut self) {
152 self.stats.record_move_accepted();
153 self.solver_scope.stats_mut().record_move_accepted();
154 }
155
156 pub fn record_score_calculation(&mut self) {
157 self.stats.record_score_calculation();
158 self.solver_scope.stats_mut().record_score_calculation();
159 }
160}