solverforge_solver/termination/
composite.rs1use std::fmt::Debug;
7use std::marker::PhantomData;
8
9use solverforge_core::domain::PlanningSolution;
10use solverforge_scoring::Director;
11
12use super::Termination;
13use crate::scope::BestSolutionCallback;
14use crate::scope::SolverScope;
15
16#[derive(Clone)]
47pub struct OrTermination<T, S, D>(pub T, PhantomData<fn(S, D)>);
48
49impl<T: Debug, S, D> Debug for OrTermination<T, S, D> {
50 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51 f.debug_tuple("OrTermination").field(&self.0).finish()
52 }
53}
54
55impl<T, S, D> OrTermination<T, S, D> {
56 pub fn new(terminations: T) -> Self {
57 Self(terminations, PhantomData)
58 }
59}
60
61#[derive(Clone)]
92pub struct AndTermination<T, S, D>(pub T, PhantomData<fn(S, D)>);
93
94impl<T: Debug, S, D> Debug for AndTermination<T, S, D> {
95 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
96 f.debug_tuple("AndTermination").field(&self.0).finish()
97 }
98}
99
100impl<T, S, D> AndTermination<T, S, D> {
101 pub fn new(terminations: T) -> Self {
102 Self(terminations, PhantomData)
103 }
104}
105
106macro_rules! impl_composite_termination {
107 ($($idx:tt: $T:ident),+) => {
108 impl<S, D, BestCb, $($T),+> Termination<S, D, BestCb> for OrTermination<($($T,)+), S, D>
109 where
110 S: PlanningSolution,
111 D: Director<S>,
112 BestCb: BestSolutionCallback<S>,
113 $($T: Termination<S, D, BestCb>,)+
114 {
115 fn is_terminated(&self, solver_scope: &SolverScope<S, D, BestCb>) -> bool {
116 $(
117 if self.0.$idx.is_terminated(solver_scope) {
118 return true;
119 }
120 )+
121 false
122 }
123
124 fn install_inphase_limits(&self, solver_scope: &mut SolverScope<S, D, BestCb>) {
125 $(
128 self.0.$idx.install_inphase_limits(solver_scope);
129 )+
130 }
131 }
132
133 impl<S, D, BestCb, $($T),+> Termination<S, D, BestCb> for AndTermination<($($T,)+), S, D>
134 where
135 S: PlanningSolution,
136 D: Director<S>,
137 BestCb: BestSolutionCallback<S>,
138 $($T: Termination<S, D, BestCb>,)+
139 {
140 fn is_terminated(&self, solver_scope: &SolverScope<S, D, BestCb>) -> bool {
141 $(
142 if !self.0.$idx.is_terminated(solver_scope) {
143 return false;
144 }
145 )+
146 true
147 }
148
149 fn install_inphase_limits(&self, solver_scope: &mut SolverScope<S, D, BestCb>) {
150 $(
151 self.0.$idx.install_inphase_limits(solver_scope);
152 )+
153 }
154 }
155 };
156}
157
158impl_composite_termination!(0: T0);
159impl_composite_termination!(0: T0, 1: T1);
160impl_composite_termination!(0: T0, 1: T1, 2: T2);
161impl_composite_termination!(0: T0, 1: T1, 2: T2, 3: T3);
162impl_composite_termination!(0: T0, 1: T1, 2: T2, 3: T3, 4: T4);
163impl_composite_termination!(0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5);
164impl_composite_termination!(0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6);
165impl_composite_termination!(0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7);