solverforge_solver/scope/
step.rs1use solverforge_core::domain::PlanningSolution;
4use solverforge_scoring::Director;
5
6use crate::heuristic::r#move::Move;
7
8use super::solver::{PendingControl, ProgressCallback};
9use super::{PhaseScope, SolverScope};
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub(crate) enum StepControlPolicy {
13 ObserveConfigLimits,
14}
15
16impl StepControlPolicy {
17 pub(crate) fn for_required_construction(_required_only: bool) -> Self {
18 Self::ObserveConfigLimits
19 }
20
21 pub(crate) fn should_terminate_construction<S, D, ProgressCb>(
22 self,
23 solver_scope: &mut SolverScope<'_, S, D, ProgressCb>,
24 ) -> bool
25 where
26 S: PlanningSolution,
27 D: Director<S>,
28 ProgressCb: ProgressCallback<S>,
29 {
30 solver_scope.should_terminate_construction()
31 }
32}
33
34pub struct StepScope<'t, 'a, 'b, S: PlanningSolution, D: Director<S>, BestCb = ()> {
44 phase_scope: &'a mut PhaseScope<'t, 'b, S, D, BestCb>,
46 step_index: u64,
48 step_score: Option<S::Score>,
50 control_policy: StepControlPolicy,
51 control_polling_required: bool,
52 progress_polling_required: bool,
53}
54
55impl<'t, 'a, 'b, S: PlanningSolution, D: Director<S>, BestCb: ProgressCallback<S>>
56 StepScope<'t, 'a, 'b, S, D, BestCb>
57{
58 pub fn new(phase_scope: &'a mut PhaseScope<'t, 'b, S, D, BestCb>) -> Self {
59 Self::new_with_control_policy(phase_scope, StepControlPolicy::ObserveConfigLimits)
60 }
61
62 pub(crate) fn new_with_control_policy(
63 phase_scope: &'a mut PhaseScope<'t, 'b, S, D, BestCb>,
64 control_policy: StepControlPolicy,
65 ) -> Self {
66 let step_index = phase_scope.step_count();
67 let control_polling_required = phase_scope.solver_scope().config_control_polling_required();
68 Self {
69 phase_scope,
70 step_index,
71 step_score: None,
72 control_policy,
73 control_polling_required,
74 progress_polling_required: BestCb::PUBLISHES_PROGRESS
75 || tracing::enabled!(tracing::Level::DEBUG),
76 }
77 }
78
79 pub fn step_index(&self) -> u64 {
80 self.step_index
81 }
82
83 pub fn step_score(&self) -> Option<&S::Score> {
84 self.step_score.as_ref()
85 }
86
87 pub(crate) fn control_policy(&self) -> StepControlPolicy {
88 self.control_policy
89 }
90
91 pub(crate) fn pending_control(&self) -> PendingControl {
92 if !self.control_polling_required {
93 return PendingControl::Continue;
94 }
95 self.phase_scope.solver_scope().pending_control()
96 }
97
98 pub(crate) fn progress_polling_required(&self) -> bool {
99 self.progress_polling_required
100 }
101
102 pub fn set_step_score(&mut self, score: S::Score)
103 where
104 S::Score: Copy,
105 {
106 self.phase_scope.solver_scope_mut().set_current_score(score);
107 self.phase_scope
108 .solver_scope_mut()
109 .observe_phase_step_score(score);
110 self.step_score = Some(score);
111 }
112
113 pub fn complete(&mut self) {
115 self.phase_scope.increment_step_count();
116 self.phase_scope.solver_scope_mut().pause_if_requested();
117 self.phase_scope.report_progress_if_due();
118 }
119
120 pub fn phase_scope(&self) -> &PhaseScope<'t, 'b, S, D, BestCb> {
121 self.phase_scope
122 }
123
124 pub fn phase_scope_mut(&mut self) -> &mut PhaseScope<'t, 'b, S, D, BestCb> {
125 self.phase_scope
126 }
127
128 pub fn score_director(&self) -> &D {
129 self.phase_scope.score_director()
130 }
131
132 pub(crate) fn score_director_mut(&mut self) -> &mut D {
133 self.phase_scope.score_director_mut()
134 }
135
136 pub fn mutate<T, F>(&mut self, mutate: F) -> T
137 where
138 F: FnOnce(&mut D) -> T,
139 {
140 self.phase_scope.mutate(mutate)
141 }
142
143 pub(crate) fn apply_committed_move<M>(&mut self, mov: &M)
144 where
145 M: Move<S>,
146 {
147 self.phase_scope
148 .solver_scope_mut()
149 .apply_committed_move(mov);
150 }
151
152 pub(crate) fn apply_committed_change<F>(&mut self, change: F)
153 where
154 F: FnOnce(&mut D),
155 {
156 self.phase_scope
157 .solver_scope_mut()
158 .apply_committed_change(change);
159 }
160
161 pub fn calculate_score(&mut self) -> S::Score {
163 self.phase_scope.calculate_score()
164 }
165}