pumpkin_constraints/constraints/
cumulative.rs1use std::fmt::Debug;
2
3use pumpkin_core::Solver;
4use pumpkin_core::asserts::pumpkin_assert_simple;
5use pumpkin_core::constraints::Constraint;
6use pumpkin_core::proof::ConstraintTag;
7use pumpkin_core::variables::IntegerVariable;
8use pumpkin_core::variables::Literal;
9use pumpkin_propagators::cumulative::ArgTask;
10use pumpkin_propagators::cumulative::options::CumulativeOptions;
11use pumpkin_propagators::cumulative::options::CumulativePropagationMethod;
12use pumpkin_propagators::cumulative::time_table::TimeTableOverIntervalIncrementalPropagator;
13use pumpkin_propagators::cumulative::time_table::TimeTableOverIntervalPropagator;
14use pumpkin_propagators::cumulative::time_table::TimeTablePerPointIncrementalPropagator;
15use pumpkin_propagators::cumulative::time_table::TimeTablePerPointPropagator;
16
17pub fn cumulative<StartTimes, Durations, ResourceRequirements>(
80 start_times: StartTimes,
81 durations: Durations,
82 resource_requirements: ResourceRequirements,
83 resource_capacity: i32,
84 constraint_tag: ConstraintTag,
85) -> impl Constraint
86where
87 StartTimes: IntoIterator,
88 StartTimes::Item: IntegerVariable + Debug + 'static,
89 StartTimes::IntoIter: ExactSizeIterator,
90 Durations: IntoIterator<Item = i32>,
91 Durations::IntoIter: ExactSizeIterator,
92 ResourceRequirements: IntoIterator<Item = i32>,
93 ResourceRequirements::IntoIter: ExactSizeIterator,
94{
95 cumulative_with_options(
96 start_times,
97 durations,
98 resource_requirements,
99 resource_capacity,
100 CumulativeOptions::default(),
101 constraint_tag,
102 )
103}
104
105pub fn cumulative_with_options<StartTimes, Durations, ResourceRequirements>(
110 start_times: StartTimes,
111 durations: Durations,
112 resource_requirements: ResourceRequirements,
113 resource_capacity: i32,
114 options: CumulativeOptions,
115 constraint_tag: ConstraintTag,
116) -> impl Constraint
117where
118 StartTimes: IntoIterator,
119 StartTimes::Item: IntegerVariable + Debug + 'static,
120 StartTimes::IntoIter: ExactSizeIterator,
121 Durations: IntoIterator<Item = i32>,
122 Durations::IntoIter: ExactSizeIterator,
123 ResourceRequirements: IntoIterator<Item = i32>,
124 ResourceRequirements::IntoIter: ExactSizeIterator,
125{
126 let start_times = start_times.into_iter();
127 let durations = durations.into_iter();
128 let resource_requirements = resource_requirements.into_iter();
129
130 pumpkin_assert_simple!(
131 start_times.len() == durations.len() && durations.len() == resource_requirements.len(),
132 "The number of start variables, durations and resource requirements should be the same!"
133 );
134
135 CumulativeConstraint::new(
136 &start_times
137 .zip(durations)
138 .zip(resource_requirements)
139 .map(|((start_time, duration), resource_requirement)| ArgTask {
140 start_time,
141 processing_time: duration,
142 resource_usage: resource_requirement,
143 })
144 .collect::<Vec<_>>(),
145 resource_capacity,
146 options,
147 constraint_tag,
148 )
149}
150
151struct CumulativeConstraint<Var> {
152 tasks: Vec<ArgTask<Var>>,
153 resource_capacity: i32,
154 options: CumulativeOptions,
155 constraint_tag: ConstraintTag,
156}
157
158impl<Var: IntegerVariable + 'static> CumulativeConstraint<Var> {
159 fn new(
160 tasks: &[ArgTask<Var>],
161 resource_capacity: i32,
162 options: CumulativeOptions,
163 constraint_tag: ConstraintTag,
164 ) -> Self {
165 Self {
166 tasks: tasks.into(),
167 resource_capacity,
168
169 options,
170 constraint_tag,
171 }
172 }
173}
174
175impl<Var: IntegerVariable + 'static + Debug> Constraint for CumulativeConstraint<Var> {
176 fn post(self, solver: &mut Solver) {
177 match self.options.propagation_method {
178 CumulativePropagationMethod::TimeTablePerPoint => TimeTablePerPointPropagator::new(
179 &self.tasks,
180 self.resource_capacity,
181 self.options.propagator_options,
182 self.constraint_tag,
183 )
184 .post(solver),
185
186 CumulativePropagationMethod::TimeTablePerPointIncremental => {
187 TimeTablePerPointIncrementalPropagator::<Var, false>::new(
188 &self.tasks,
189 self.resource_capacity,
190 self.options.propagator_options,
191 self.constraint_tag,
192 )
193 .post(solver)
194 }
195 CumulativePropagationMethod::TimeTablePerPointIncrementalSynchronised => {
196 TimeTablePerPointIncrementalPropagator::<Var, true>::new(
197 &self.tasks,
198 self.resource_capacity,
199 self.options.propagator_options,
200 self.constraint_tag,
201 )
202 .post(solver)
203 }
204 CumulativePropagationMethod::TimeTableOverInterval => {
205 TimeTableOverIntervalPropagator::new(
206 &self.tasks,
207 self.resource_capacity,
208 self.options.propagator_options,
209 self.constraint_tag,
210 )
211 .post(solver)
212 }
213 CumulativePropagationMethod::TimeTableOverIntervalIncremental => {
214 TimeTableOverIntervalIncrementalPropagator::<Var, false>::new(
215 &self.tasks,
216 self.resource_capacity,
217 self.options.propagator_options,
218 self.constraint_tag,
219 )
220 .post(solver)
221 }
222 CumulativePropagationMethod::TimeTableOverIntervalIncrementalSynchronised => {
223 TimeTableOverIntervalIncrementalPropagator::<Var, true>::new(
224 &self.tasks,
225 self.resource_capacity,
226 self.options.propagator_options,
227 self.constraint_tag,
228 )
229 .post(solver)
230 }
231 }
232 }
233
234 fn implied_by(self, solver: &mut Solver, reification_literal: Literal) {
235 match self.options.propagation_method {
236 CumulativePropagationMethod::TimeTablePerPoint => TimeTablePerPointPropagator::new(
237 &self.tasks,
238 self.resource_capacity,
239 self.options.propagator_options,
240 self.constraint_tag,
241 )
242 .implied_by(solver, reification_literal),
243 CumulativePropagationMethod::TimeTablePerPointIncremental => {
244 TimeTablePerPointIncrementalPropagator::<Var, false>::new(
245 &self.tasks,
246 self.resource_capacity,
247 self.options.propagator_options,
248 self.constraint_tag,
249 )
250 .implied_by(solver, reification_literal)
251 }
252 CumulativePropagationMethod::TimeTablePerPointIncrementalSynchronised => {
253 TimeTablePerPointIncrementalPropagator::<Var, true>::new(
254 &self.tasks,
255 self.resource_capacity,
256 self.options.propagator_options,
257 self.constraint_tag,
258 )
259 .implied_by(solver, reification_literal)
260 }
261 CumulativePropagationMethod::TimeTableOverInterval => {
262 TimeTableOverIntervalPropagator::new(
263 &self.tasks,
264 self.resource_capacity,
265 self.options.propagator_options,
266 self.constraint_tag,
267 )
268 .implied_by(solver, reification_literal)
269 }
270 CumulativePropagationMethod::TimeTableOverIntervalIncremental => {
271 TimeTableOverIntervalIncrementalPropagator::<Var, false>::new(
272 &self.tasks,
273 self.resource_capacity,
274 self.options.propagator_options,
275 self.constraint_tag,
276 )
277 .implied_by(solver, reification_literal)
278 }
279 CumulativePropagationMethod::TimeTableOverIntervalIncrementalSynchronised => {
280 TimeTableOverIntervalIncrementalPropagator::<Var, true>::new(
281 &self.tasks,
282 self.resource_capacity,
283 self.options.propagator_options,
284 self.constraint_tag,
285 )
286 .implied_by(solver, reification_literal)
287 }
288 }
289 }
290}