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 CompleteMandatoryConstruction,
15}
16
17impl StepControlPolicy {
18 pub(crate) fn for_required_construction(required_only: bool) -> Self {
19 if required_only {
20 Self::CompleteMandatoryConstruction
21 } else {
22 Self::ObserveConfigLimits
23 }
24 }
25
26 pub(crate) fn should_terminate_construction<S, D, ProgressCb>(
27 self,
28 solver_scope: &mut SolverScope<'_, S, D, ProgressCb>,
29 ) -> bool
30 where
31 S: PlanningSolution,
32 D: Director<S>,
33 ProgressCb: ProgressCallback<S>,
34 {
35 match self {
36 Self::ObserveConfigLimits => solver_scope.should_terminate_construction(),
37 Self::CompleteMandatoryConstruction => {
38 solver_scope.should_interrupt_mandatory_construction()
39 }
40 }
41 }
42}
43
44pub struct StepScope<'t, 'a, 'b, S: PlanningSolution, D: Director<S>, BestCb = ()> {
54 phase_scope: &'a mut PhaseScope<'t, 'b, S, D, BestCb>,
56 step_index: u64,
58 step_score: Option<S::Score>,
60 control_policy: StepControlPolicy,
61 control_polling_required: bool,
62 progress_polling_required: bool,
63}
64
65impl<'t, 'a, 'b, S: PlanningSolution, D: Director<S>, BestCb: ProgressCallback<S>>
66 StepScope<'t, 'a, 'b, S, D, BestCb>
67{
68 pub fn new(phase_scope: &'a mut PhaseScope<'t, 'b, S, D, BestCb>) -> Self {
69 Self::new_with_control_policy(phase_scope, StepControlPolicy::ObserveConfigLimits)
70 }
71
72 pub(crate) fn new_with_control_policy(
73 phase_scope: &'a mut PhaseScope<'t, 'b, S, D, BestCb>,
74 control_policy: StepControlPolicy,
75 ) -> Self {
76 let step_index = phase_scope.step_count();
77 let control_polling_required = match control_policy {
78 StepControlPolicy::ObserveConfigLimits => {
79 phase_scope.solver_scope().config_control_polling_required()
80 }
81 StepControlPolicy::CompleteMandatoryConstruction => phase_scope
82 .solver_scope()
83 .mandatory_control_polling_required(),
84 };
85 Self {
86 phase_scope,
87 step_index,
88 step_score: None,
89 control_policy,
90 control_polling_required,
91 progress_polling_required: BestCb::PUBLISHES_PROGRESS
92 || tracing::enabled!(tracing::Level::DEBUG),
93 }
94 }
95
96 pub fn step_index(&self) -> u64 {
97 self.step_index
98 }
99
100 pub fn step_score(&self) -> Option<&S::Score> {
101 self.step_score.as_ref()
102 }
103
104 pub(crate) fn control_policy(&self) -> StepControlPolicy {
105 self.control_policy
106 }
107
108 pub(crate) fn pending_control(&self) -> PendingControl {
109 if !self.control_polling_required {
110 return PendingControl::Continue;
111 }
112 match self.control_policy {
113 StepControlPolicy::ObserveConfigLimits => {
114 self.phase_scope.solver_scope().pending_control()
115 }
116 StepControlPolicy::CompleteMandatoryConstruction => self
117 .phase_scope
118 .solver_scope()
119 .mandatory_construction_pending_control(),
120 }
121 }
122
123 pub(crate) fn progress_polling_required(&self) -> bool {
124 self.progress_polling_required
125 }
126
127 pub fn set_step_score(&mut self, score: S::Score)
128 where
129 S::Score: Copy,
130 {
131 self.phase_scope.solver_scope_mut().set_current_score(score);
132 self.phase_scope
133 .solver_scope_mut()
134 .observe_phase_step_score(score);
135 self.step_score = Some(score);
136 }
137
138 pub fn complete(&mut self) {
140 self.phase_scope.increment_step_count();
141 self.phase_scope.solver_scope_mut().pause_if_requested();
142 self.phase_scope.report_progress_if_due();
143 }
144
145 pub fn phase_scope(&self) -> &PhaseScope<'t, 'b, S, D, BestCb> {
146 self.phase_scope
147 }
148
149 pub fn phase_scope_mut(&mut self) -> &mut PhaseScope<'t, 'b, S, D, BestCb> {
150 self.phase_scope
151 }
152
153 pub fn score_director(&self) -> &D {
154 self.phase_scope.score_director()
155 }
156
157 pub(crate) fn score_director_mut(&mut self) -> &mut D {
158 self.phase_scope.score_director_mut()
159 }
160
161 pub fn mutate<T, F>(&mut self, mutate: F) -> T
162 where
163 F: FnOnce(&mut D) -> T,
164 {
165 self.phase_scope.mutate(mutate)
166 }
167
168 pub(crate) fn apply_committed_move<M>(&mut self, mov: &M)
169 where
170 M: Move<S>,
171 {
172 self.phase_scope
173 .solver_scope_mut()
174 .apply_committed_move(mov);
175 }
176
177 pub(crate) fn apply_committed_change<F>(&mut self, change: F)
178 where
179 F: FnOnce(&mut D),
180 {
181 self.phase_scope
182 .solver_scope_mut()
183 .apply_committed_change(change);
184 }
185
186 pub fn calculate_score(&mut self) -> S::Score {
188 self.phase_scope.calculate_score()
189 }
190}