Skip to main content

trellis_runner/
procedure.rs

1use crate::CancellationGuard;
2
3use std::ops::Deref;
4
5/// Trait implemented by all problems solvable by `Trellis`
6///
7/// A procedure defines the core loop of the solver. Typically we would write a for loop,
8/// consisting of an initialisation step where the procedure is arranged, a procedure carried out
9/// on each loop iteration, and a finalisation step prior to return. This trait separates these
10/// methods so they can be called by the Engine
11pub trait Procedure<P> {
12    /// The type returned to the caller.
13    type Output;
14
15    /// The internal state used by the procedure
16    type State;
17
18    /// An identifier for the procedure.
19    ///
20    /// This identifier is printed in tracing logs
21    const NAME: &'static str;
22    /// Initialisation.
23    ///
24    /// This step prepares the state object for the main procedure loop.
25    fn initialise(&self, _problem: &mut P, _state: &mut Self::State) {}
26    /// One iteration of the core algorithm
27    fn step(&self, problem: &mut P, state: &mut Self::State, guard: CancellationGuard<'_>);
28
29    /// Converts the internal state to the user-facing return datatype
30    fn finalise(&self, problem: &mut P, state: &Self::State) -> Self::Output;
31}
32
33pub trait FallibleProcedure<P> {
34    type Error: std::error::Error + 'static + Send + Sync;
35
36    type Output;
37
38    type State;
39
40    /// An identifier for the procedure.
41    ///
42    /// This identifier is printed in tracing logs
43    const NAME: &'static str;
44
45    fn initialise_fallible(
46        &self,
47        _problem: &mut P,
48        _state: &mut Self::State,
49    ) -> Result<(), Self::Error>;
50
51    fn step_fallible(
52        &self,
53        problem: &mut P,
54        state: &mut Self::State,
55        guard: CancellationGuard<'_>,
56    ) -> Result<(), Self::Error>;
57
58    fn finalise_fallible(
59        &self,
60        problem: &mut P,
61        state: &Self::State,
62    ) -> Result<Self::Output, Self::Error>;
63}
64
65pub struct Infallible<Proc>(pub Proc);
66
67impl<Proc> Deref for Infallible<Proc> {
68    type Target = Proc;
69    fn deref(&self) -> &Self::Target {
70        &self.0
71    }
72}
73
74impl<Proc, P> FallibleProcedure<P> for Infallible<Proc>
75where
76    Proc: Procedure<P>,
77{
78    const NAME: &'static str = <Proc as Procedure<P>>::NAME;
79    type State = <Proc as Procedure<P>>::State;
80    type Output = <Proc as Procedure<P>>::Output;
81    type Error = std::convert::Infallible;
82
83    fn initialise_fallible(
84        &self,
85        problem: &mut P,
86        state: &mut Self::State,
87    ) -> Result<(), Self::Error> {
88        let _: () = self.initialise(problem, state);
89        Ok(())
90    }
91
92    fn step_fallible(
93        &self,
94        problem: &mut P,
95        state: &mut Self::State,
96        guard: CancellationGuard<'_>,
97    ) -> Result<(), Self::Error> {
98        let _: () = self.step(problem, state, guard);
99        Ok(())
100    }
101
102    fn finalise_fallible(
103        &self,
104        problem: &mut P,
105        state: &Self::State,
106    ) -> Result<Self::Output, Self::Error> {
107        Ok(self.finalise(problem, state))
108    }
109}