solverforge_solver/phase/
sequence.rs1use std::fmt::{self, Debug};
2
3use solverforge_core::domain::PlanningSolution;
4use solverforge_scoring::Director;
5
6use crate::phase::Phase;
7use crate::scope::{ProgressCallback, SolverScope};
8use crate::stats::CandidateTracePhasePlan;
9
10pub struct PhaseSequence<P> {
11 phases: Vec<P>,
12}
13
14impl<P> PhaseSequence<P> {
15 pub fn new(phases: Vec<P>) -> Self {
16 Self { phases }
17 }
18
19 pub fn phases(&self) -> &[P] {
20 &self.phases
21 }
22
23 pub fn into_phases(self) -> Vec<P> {
24 self.phases
25 }
26}
27
28impl<P: Debug> Debug for PhaseSequence<P> {
29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 f.debug_struct("PhaseSequence")
31 .field("phases", &self.phases)
32 .finish()
33 }
34}
35
36impl<S, D, ProgressCb, P> Phase<S, D, ProgressCb> for PhaseSequence<P>
37where
38 S: PlanningSolution,
39 D: Director<S>,
40 ProgressCb: ProgressCallback<S>,
41 P: Phase<S, D, ProgressCb>,
42{
43 fn solve(&mut self, solver_scope: &mut SolverScope<'_, S, D, ProgressCb>) {
44 for phase in &mut self.phases {
45 phase.solve(solver_scope);
46 }
47 }
48
49 fn phase_type_name(&self) -> &'static str {
50 "PhaseSequence"
51 }
52
53 fn on_solver_terminal(&mut self, solver_scope: &mut SolverScope<'_, S, D, ProgressCb>) {
54 for phase in &mut self.phases {
55 phase.on_solver_terminal(solver_scope);
56 }
57 }
58
59 fn candidate_trace_plan(&self) -> CandidateTracePhasePlan {
60 CandidateTracePhasePlan::known(
61 "solverforge.phase.sequence",
62 [("phase_count", self.phases.len().to_string())],
63 self.phases
64 .iter()
65 .map(|phase| phase.candidate_trace_plan())
66 .collect(),
67 )
68 }
69}