OR-Tools  9.0
cp_model_utils.cc
Go to the documentation of this file.
1 // Copyright 2010-2021 Google LLC
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
15 
16 #include <cstdint>
17 
18 #include "ortools/base/stl_util.h"
19 
20 namespace operations_research {
21 namespace sat {
22 
23 namespace {
24 
25 template <typename IntList>
26 void AddIndices(const IntList& indices, std::vector<int>* output) {
27  output->insert(output->end(), indices.begin(), indices.end());
28 }
29 
30 } // namespace
31 
32 void SetToNegatedLinearExpression(const LinearExpressionProto& input_expr,
33  LinearExpressionProto* output_negated_expr) {
34  output_negated_expr->Clear();
35  for (int i = 0; i < input_expr.vars_size(); ++i) {
36  output_negated_expr->add_vars(NegatedRef(input_expr.vars(i)));
37  output_negated_expr->add_coeffs(input_expr.coeffs(i));
38  }
39  output_negated_expr->set_offset(-input_expr.offset());
40 }
41 
43  IndexReferences output;
44  switch (ct.constraint_case()) {
45  case ConstraintProto::ConstraintCase::kBoolOr:
46  AddIndices(ct.bool_or().literals(), &output.literals);
47  break;
48  case ConstraintProto::ConstraintCase::kBoolAnd:
49  AddIndices(ct.bool_and().literals(), &output.literals);
50  break;
51  case ConstraintProto::ConstraintCase::kAtMostOne:
52  AddIndices(ct.at_most_one().literals(), &output.literals);
53  break;
54  case ConstraintProto::ConstraintCase::kExactlyOne:
55  AddIndices(ct.exactly_one().literals(), &output.literals);
56  break;
57  case ConstraintProto::ConstraintCase::kBoolXor:
58  AddIndices(ct.bool_xor().literals(), &output.literals);
59  break;
60  case ConstraintProto::ConstraintCase::kIntDiv:
61  output.variables.push_back(ct.int_div().target());
62  AddIndices(ct.int_div().vars(), &output.variables);
63  break;
64  case ConstraintProto::ConstraintCase::kIntMod:
65  output.variables.push_back(ct.int_mod().target());
66  AddIndices(ct.int_mod().vars(), &output.variables);
67  break;
68  case ConstraintProto::ConstraintCase::kIntMax:
69  output.variables.push_back(ct.int_max().target());
70  AddIndices(ct.int_max().vars(), &output.variables);
71  break;
72  case ConstraintProto::ConstraintCase::kLinMax: {
73  AddIndices(ct.lin_max().target().vars(), &output.variables);
74  for (int i = 0; i < ct.lin_max().exprs_size(); ++i) {
75  AddIndices(ct.lin_max().exprs(i).vars(), &output.variables);
76  }
77  break;
78  }
79  case ConstraintProto::ConstraintCase::kIntMin:
80  output.variables.push_back(ct.int_min().target());
81  AddIndices(ct.int_min().vars(), &output.variables);
82  break;
83  case ConstraintProto::ConstraintCase::kLinMin: {
84  AddIndices(ct.lin_min().target().vars(), &output.variables);
85  for (int i = 0; i < ct.lin_min().exprs_size(); ++i) {
86  AddIndices(ct.lin_min().exprs(i).vars(), &output.variables);
87  }
88  break;
89  }
90  case ConstraintProto::ConstraintCase::kIntProd:
91  output.variables.push_back(ct.int_prod().target());
92  AddIndices(ct.int_prod().vars(), &output.variables);
93  break;
94  case ConstraintProto::ConstraintCase::kLinear:
95  AddIndices(ct.linear().vars(), &output.variables);
96  break;
97  case ConstraintProto::ConstraintCase::kAllDiff:
98  AddIndices(ct.all_diff().vars(), &output.variables);
99  break;
100  case ConstraintProto::ConstraintCase::kElement:
101  output.variables.push_back(ct.element().index());
102  output.variables.push_back(ct.element().target());
103  AddIndices(ct.element().vars(), &output.variables);
104  break;
105  case ConstraintProto::ConstraintCase::kCircuit:
106  AddIndices(ct.circuit().literals(), &output.literals);
107  break;
108  case ConstraintProto::ConstraintCase::kRoutes:
109  AddIndices(ct.routes().literals(), &output.literals);
110  break;
111  case ConstraintProto::ConstraintCase::kInverse:
112  AddIndices(ct.inverse().f_direct(), &output.variables);
113  AddIndices(ct.inverse().f_inverse(), &output.variables);
114  break;
115  case ConstraintProto::ConstraintCase::kReservoir:
116  AddIndices(ct.reservoir().times(), &output.variables);
117  AddIndices(ct.reservoir().actives(), &output.literals);
118  break;
119  case ConstraintProto::ConstraintCase::kTable:
120  AddIndices(ct.table().vars(), &output.variables);
121  break;
122  case ConstraintProto::ConstraintCase::kAutomaton:
123  AddIndices(ct.automaton().vars(), &output.variables);
124  break;
125  case ConstraintProto::ConstraintCase::kInterval:
126  if (ct.interval().has_start_view()) {
127  AddIndices(ct.interval().start_view().vars(), &output.variables);
128  } else {
129  output.variables.push_back(ct.interval().start());
130  }
131  if (ct.interval().has_size_view()) {
132  AddIndices(ct.interval().size_view().vars(), &output.variables);
133  } else {
134  output.variables.push_back(ct.interval().size());
135  }
136  if (ct.interval().has_end_view()) {
137  AddIndices(ct.interval().end_view().vars(), &output.variables);
138  } else {
139  output.variables.push_back(ct.interval().end());
140  }
141  break;
142  case ConstraintProto::ConstraintCase::kNoOverlap:
143  break;
144  case ConstraintProto::ConstraintCase::kNoOverlap2D:
145  break;
146  case ConstraintProto::ConstraintCase::kCumulative:
147  output.variables.push_back(ct.cumulative().capacity());
148  AddIndices(ct.cumulative().demands(), &output.variables);
149  break;
150  case ConstraintProto::ConstraintCase::CONSTRAINT_NOT_SET:
151  break;
152  }
153  return output;
154 }
155 
156 #define APPLY_TO_SINGULAR_FIELD(ct_name, field_name) \
157  { \
158  int temp = ct->mutable_##ct_name()->field_name(); \
159  f(&temp); \
160  ct->mutable_##ct_name()->set_##field_name(temp); \
161  }
162 
163 #define APPLY_TO_REPEATED_FIELD(ct_name, field_name) \
164  { \
165  for (int& r : *ct->mutable_##ct_name()->mutable_##field_name()) f(&r); \
166  }
167 
168 void ApplyToAllLiteralIndices(const std::function<void(int*)>& f,
169  ConstraintProto* ct) {
170  for (int& r : *ct->mutable_enforcement_literal()) f(&r);
171  switch (ct->constraint_case()) {
172  case ConstraintProto::ConstraintCase::kBoolOr:
173  APPLY_TO_REPEATED_FIELD(bool_or, literals);
174  break;
175  case ConstraintProto::ConstraintCase::kBoolAnd:
176  APPLY_TO_REPEATED_FIELD(bool_and, literals);
177  break;
178  case ConstraintProto::ConstraintCase::kAtMostOne:
179  APPLY_TO_REPEATED_FIELD(at_most_one, literals);
180  break;
181  case ConstraintProto::ConstraintCase::kExactlyOne:
182  APPLY_TO_REPEATED_FIELD(exactly_one, literals);
183  break;
184  case ConstraintProto::ConstraintCase::kBoolXor:
185  APPLY_TO_REPEATED_FIELD(bool_xor, literals);
186  break;
187  case ConstraintProto::ConstraintCase::kIntDiv:
188  break;
189  case ConstraintProto::ConstraintCase::kIntMod:
190  break;
191  case ConstraintProto::ConstraintCase::kIntMax:
192  break;
193  case ConstraintProto::ConstraintCase::kLinMax:
194  break;
195  case ConstraintProto::ConstraintCase::kIntMin:
196  break;
197  case ConstraintProto::ConstraintCase::kLinMin:
198  break;
199  case ConstraintProto::ConstraintCase::kIntProd:
200  break;
201  case ConstraintProto::ConstraintCase::kLinear:
202  break;
203  case ConstraintProto::ConstraintCase::kAllDiff:
204  break;
205  case ConstraintProto::ConstraintCase::kElement:
206  break;
207  case ConstraintProto::ConstraintCase::kCircuit:
208  APPLY_TO_REPEATED_FIELD(circuit, literals);
209  break;
210  case ConstraintProto::ConstraintCase::kRoutes:
211  APPLY_TO_REPEATED_FIELD(routes, literals);
212  break;
213  case ConstraintProto::ConstraintCase::kInverse:
214  break;
215  case ConstraintProto::ConstraintCase::kReservoir:
216  APPLY_TO_REPEATED_FIELD(reservoir, actives);
217  break;
218  case ConstraintProto::ConstraintCase::kTable:
219  break;
220  case ConstraintProto::ConstraintCase::kAutomaton:
221  break;
222  case ConstraintProto::ConstraintCase::kInterval:
223  break;
224  case ConstraintProto::ConstraintCase::kNoOverlap:
225  break;
226  case ConstraintProto::ConstraintCase::kNoOverlap2D:
227  break;
228  case ConstraintProto::ConstraintCase::kCumulative:
229  break;
230  case ConstraintProto::ConstraintCase::CONSTRAINT_NOT_SET:
231  break;
232  }
233 }
234 
235 void ApplyToAllVariableIndices(const std::function<void(int*)>& f,
236  ConstraintProto* ct) {
237  switch (ct->constraint_case()) {
238  case ConstraintProto::ConstraintCase::kBoolOr:
239  break;
240  case ConstraintProto::ConstraintCase::kBoolAnd:
241  break;
242  case ConstraintProto::ConstraintCase::kAtMostOne:
243  break;
244  case ConstraintProto::ConstraintCase::kExactlyOne:
245  break;
246  case ConstraintProto::ConstraintCase::kBoolXor:
247  break;
248  case ConstraintProto::ConstraintCase::kIntDiv:
249  APPLY_TO_SINGULAR_FIELD(int_div, target);
250  APPLY_TO_REPEATED_FIELD(int_div, vars);
251  break;
252  case ConstraintProto::ConstraintCase::kIntMod:
253  APPLY_TO_SINGULAR_FIELD(int_mod, target);
254  APPLY_TO_REPEATED_FIELD(int_mod, vars);
255  break;
256  case ConstraintProto::ConstraintCase::kIntMax:
257  APPLY_TO_SINGULAR_FIELD(int_max, target);
258  APPLY_TO_REPEATED_FIELD(int_max, vars);
259  break;
260  case ConstraintProto::ConstraintCase::kLinMax:
261  APPLY_TO_REPEATED_FIELD(lin_max, target()->mutable_vars);
262  for (int i = 0; i < ct->lin_max().exprs_size(); ++i) {
263  APPLY_TO_REPEATED_FIELD(lin_max, exprs(i)->mutable_vars);
264  }
265  break;
266  case ConstraintProto::ConstraintCase::kIntMin:
267  APPLY_TO_SINGULAR_FIELD(int_min, target);
268  APPLY_TO_REPEATED_FIELD(int_min, vars);
269  break;
270  case ConstraintProto::ConstraintCase::kLinMin:
271  APPLY_TO_REPEATED_FIELD(lin_min, target()->mutable_vars);
272  for (int i = 0; i < ct->lin_min().exprs_size(); ++i) {
273  APPLY_TO_REPEATED_FIELD(lin_min, exprs(i)->mutable_vars);
274  }
275  break;
276  case ConstraintProto::ConstraintCase::kIntProd:
277  APPLY_TO_SINGULAR_FIELD(int_prod, target);
278  APPLY_TO_REPEATED_FIELD(int_prod, vars);
279  break;
280  case ConstraintProto::ConstraintCase::kLinear:
281  APPLY_TO_REPEATED_FIELD(linear, vars);
282  break;
283  case ConstraintProto::ConstraintCase::kAllDiff:
284  APPLY_TO_REPEATED_FIELD(all_diff, vars);
285  break;
286  case ConstraintProto::ConstraintCase::kElement:
287  APPLY_TO_SINGULAR_FIELD(element, index);
288  APPLY_TO_SINGULAR_FIELD(element, target);
289  APPLY_TO_REPEATED_FIELD(element, vars);
290  break;
291  case ConstraintProto::ConstraintCase::kCircuit:
292  break;
293  case ConstraintProto::ConstraintCase::kRoutes:
294  break;
295  case ConstraintProto::ConstraintCase::kInverse:
296  APPLY_TO_REPEATED_FIELD(inverse, f_direct);
297  APPLY_TO_REPEATED_FIELD(inverse, f_inverse);
298  break;
299  case ConstraintProto::ConstraintCase::kReservoir:
300  APPLY_TO_REPEATED_FIELD(reservoir, times);
301  break;
302  case ConstraintProto::ConstraintCase::kTable:
303  APPLY_TO_REPEATED_FIELD(table, vars);
304  break;
305  case ConstraintProto::ConstraintCase::kAutomaton:
306  APPLY_TO_REPEATED_FIELD(automaton, vars);
307  break;
308  case ConstraintProto::ConstraintCase::kInterval:
309  if (ct->interval().has_start_view()) {
310  APPLY_TO_REPEATED_FIELD(interval, start_view()->mutable_vars);
311  } else {
313  }
314  if (ct->interval().has_size_view()) {
315  APPLY_TO_REPEATED_FIELD(interval, size_view()->mutable_vars);
316  } else {
318  }
319  if (ct->interval().has_end_view()) {
320  APPLY_TO_REPEATED_FIELD(interval, end_view()->mutable_vars);
321  } else {
323  }
324  break;
325  case ConstraintProto::ConstraintCase::kNoOverlap:
326  break;
327  case ConstraintProto::ConstraintCase::kNoOverlap2D:
328  break;
329  case ConstraintProto::ConstraintCase::kCumulative:
330  APPLY_TO_SINGULAR_FIELD(cumulative, capacity);
331  APPLY_TO_REPEATED_FIELD(cumulative, demands);
332  break;
333  case ConstraintProto::ConstraintCase::CONSTRAINT_NOT_SET:
334  break;
335  }
336 }
337 
338 void ApplyToAllIntervalIndices(const std::function<void(int*)>& f,
339  ConstraintProto* ct) {
340  switch (ct->constraint_case()) {
341  case ConstraintProto::ConstraintCase::kBoolOr:
342  break;
343  case ConstraintProto::ConstraintCase::kBoolAnd:
344  break;
345  case ConstraintProto::ConstraintCase::kAtMostOne:
346  break;
347  case ConstraintProto::ConstraintCase::kExactlyOne:
348  break;
349  case ConstraintProto::ConstraintCase::kBoolXor:
350  break;
351  case ConstraintProto::ConstraintCase::kIntDiv:
352  break;
353  case ConstraintProto::ConstraintCase::kIntMod:
354  break;
355  case ConstraintProto::ConstraintCase::kIntMax:
356  break;
357  case ConstraintProto::ConstraintCase::kLinMax:
358  break;
359  case ConstraintProto::ConstraintCase::kIntMin:
360  break;
361  case ConstraintProto::ConstraintCase::kLinMin:
362  break;
363  case ConstraintProto::ConstraintCase::kIntProd:
364  break;
365  case ConstraintProto::ConstraintCase::kLinear:
366  break;
367  case ConstraintProto::ConstraintCase::kAllDiff:
368  break;
369  case ConstraintProto::ConstraintCase::kElement:
370  break;
371  case ConstraintProto::ConstraintCase::kCircuit:
372  break;
373  case ConstraintProto::ConstraintCase::kRoutes:
374  break;
375  case ConstraintProto::ConstraintCase::kInverse:
376  break;
377  case ConstraintProto::ConstraintCase::kReservoir:
378  break;
379  case ConstraintProto::ConstraintCase::kTable:
380  break;
381  case ConstraintProto::ConstraintCase::kAutomaton:
382  break;
383  case ConstraintProto::ConstraintCase::kInterval:
384  break;
385  case ConstraintProto::ConstraintCase::kNoOverlap:
386  APPLY_TO_REPEATED_FIELD(no_overlap, intervals);
387  break;
388  case ConstraintProto::ConstraintCase::kNoOverlap2D:
389  APPLY_TO_REPEATED_FIELD(no_overlap_2d, x_intervals);
390  APPLY_TO_REPEATED_FIELD(no_overlap_2d, y_intervals);
391  break;
392  case ConstraintProto::ConstraintCase::kCumulative:
393  APPLY_TO_REPEATED_FIELD(cumulative, intervals);
394  break;
395  case ConstraintProto::ConstraintCase::CONSTRAINT_NOT_SET:
396  break;
397  }
398 }
399 
400 #undef APPLY_TO_SINGULAR_FIELD
401 #undef APPLY_TO_REPEATED_FIELD
402 
403 std::string ConstraintCaseName(
404  ConstraintProto::ConstraintCase constraint_case) {
405  switch (constraint_case) {
406  case ConstraintProto::ConstraintCase::kBoolOr:
407  return "kBoolOr";
408  case ConstraintProto::ConstraintCase::kBoolAnd:
409  return "kBoolAnd";
410  case ConstraintProto::ConstraintCase::kAtMostOne:
411  return "kAtMostOne";
412  case ConstraintProto::ConstraintCase::kExactlyOne:
413  return "kExactlyOne";
414  case ConstraintProto::ConstraintCase::kBoolXor:
415  return "kBoolXor";
416  case ConstraintProto::ConstraintCase::kIntDiv:
417  return "kIntDiv";
418  case ConstraintProto::ConstraintCase::kIntMod:
419  return "kIntMod";
420  case ConstraintProto::ConstraintCase::kIntMax:
421  return "kIntMax";
422  case ConstraintProto::ConstraintCase::kLinMax:
423  return "kLinMax";
424  case ConstraintProto::ConstraintCase::kIntMin:
425  return "kIntMin";
426  case ConstraintProto::ConstraintCase::kLinMin:
427  return "kLinMin";
428  case ConstraintProto::ConstraintCase::kIntProd:
429  return "kIntProd";
430  case ConstraintProto::ConstraintCase::kLinear:
431  return "kLinear";
432  case ConstraintProto::ConstraintCase::kAllDiff:
433  return "kAllDiff";
434  case ConstraintProto::ConstraintCase::kElement:
435  return "kElement";
436  case ConstraintProto::ConstraintCase::kCircuit:
437  return "kCircuit";
438  case ConstraintProto::ConstraintCase::kRoutes:
439  return "kRoutes";
440  case ConstraintProto::ConstraintCase::kInverse:
441  return "kInverse";
442  case ConstraintProto::ConstraintCase::kReservoir:
443  return "kReservoir";
444  case ConstraintProto::ConstraintCase::kTable:
445  return "kTable";
446  case ConstraintProto::ConstraintCase::kAutomaton:
447  return "kAutomaton";
448  case ConstraintProto::ConstraintCase::kInterval:
449  return "kInterval";
450  case ConstraintProto::ConstraintCase::kNoOverlap:
451  return "kNoOverlap";
452  case ConstraintProto::ConstraintCase::kNoOverlap2D:
453  return "kNoOverlap2D";
454  case ConstraintProto::ConstraintCase::kCumulative:
455  return "kCumulative";
456  case ConstraintProto::ConstraintCase::CONSTRAINT_NOT_SET:
457  return "kEmpty";
458  }
459 }
460 
461 std::vector<int> UsedVariables(const ConstraintProto& ct) {
463  for (int& ref : references.variables) {
464  ref = PositiveRef(ref);
465  }
466  for (const int lit : references.literals) {
467  references.variables.push_back(PositiveRef(lit));
468  }
469  for (const int lit : ct.enforcement_literal()) {
470  references.variables.push_back(PositiveRef(lit));
471  }
473  return references.variables;
474 }
475 
476 std::vector<int> UsedIntervals(const ConstraintProto& ct) {
477  std::vector<int> used_intervals;
478  switch (ct.constraint_case()) {
479  case ConstraintProto::ConstraintCase::kBoolOr:
480  break;
481  case ConstraintProto::ConstraintCase::kBoolAnd:
482  break;
483  case ConstraintProto::ConstraintCase::kAtMostOne:
484  break;
485  case ConstraintProto::ConstraintCase::kExactlyOne:
486  break;
487  case ConstraintProto::ConstraintCase::kBoolXor:
488  break;
489  case ConstraintProto::ConstraintCase::kIntDiv:
490  break;
491  case ConstraintProto::ConstraintCase::kIntMod:
492  break;
493  case ConstraintProto::ConstraintCase::kIntMax:
494  break;
495  case ConstraintProto::ConstraintCase::kLinMax:
496  break;
497  case ConstraintProto::ConstraintCase::kIntMin:
498  break;
499  case ConstraintProto::ConstraintCase::kLinMin:
500  break;
501  case ConstraintProto::ConstraintCase::kIntProd:
502  break;
503  case ConstraintProto::ConstraintCase::kLinear:
504  break;
505  case ConstraintProto::ConstraintCase::kAllDiff:
506  break;
507  case ConstraintProto::ConstraintCase::kElement:
508  break;
509  case ConstraintProto::ConstraintCase::kCircuit:
510  break;
511  case ConstraintProto::ConstraintCase::kRoutes:
512  break;
513  case ConstraintProto::ConstraintCase::kInverse:
514  break;
515  case ConstraintProto::ConstraintCase::kReservoir:
516  break;
517  case ConstraintProto::ConstraintCase::kTable:
518  break;
519  case ConstraintProto::ConstraintCase::kAutomaton:
520  break;
521  case ConstraintProto::ConstraintCase::kInterval:
522  break;
523  case ConstraintProto::ConstraintCase::kNoOverlap:
524  AddIndices(ct.no_overlap().intervals(), &used_intervals);
525  break;
526  case ConstraintProto::ConstraintCase::kNoOverlap2D:
527  AddIndices(ct.no_overlap_2d().x_intervals(), &used_intervals);
528  AddIndices(ct.no_overlap_2d().y_intervals(), &used_intervals);
529  break;
530  case ConstraintProto::ConstraintCase::kCumulative:
531  AddIndices(ct.cumulative().intervals(), &used_intervals);
532  break;
533  case ConstraintProto::ConstraintCase::CONSTRAINT_NOT_SET:
534  break;
535  }
536  gtl::STLSortAndRemoveDuplicates(&used_intervals);
537  return used_intervals;
538 }
539 
540 int64_t ComputeInnerObjective(const CpObjectiveProto& objective,
541  const CpSolverResponse& response) {
542  int64_t objective_value = 0;
543  auto& repeated_field_values = response.solution().empty()
544  ? response.solution_lower_bounds()
545  : response.solution();
546  for (int i = 0; i < objective.vars_size(); ++i) {
547  int64_t coeff = objective.coeffs(i);
548  const int ref = objective.vars(i);
549  const int var = PositiveRef(ref);
550  if (!RefIsPositive(ref)) coeff = -coeff;
551  objective_value += coeff * repeated_field_values[var];
552  }
553  return objective_value;
554 }
555 
556 } // namespace sat
557 } // namespace operations_research
SharedResponseManager * response
#define APPLY_TO_SINGULAR_FIELD(ct_name, field_name)
#define APPLY_TO_REPEATED_FIELD(ct_name, field_name)
const Constraint * ct
IntVar * var
Definition: expr_array.cc:1874
void STLSortAndRemoveDuplicates(T *v, const LessFunc &less_func)
Definition: stl_util.h:58
int64_t ComputeInnerObjective(const CpObjectiveProto &objective, const CpSolverResponse &response)
std::vector< int > UsedVariables(const ConstraintProto &ct)
bool RefIsPositive(int ref)
std::vector< int > UsedIntervals(const ConstraintProto &ct)
void SetToNegatedLinearExpression(const LinearExpressionProto &input_expr, LinearExpressionProto *output_negated_expr)
void ApplyToAllLiteralIndices(const std::function< void(int *)> &f, ConstraintProto *ct)
void ApplyToAllIntervalIndices(const std::function< void(int *)> &f, ConstraintProto *ct)
void ApplyToAllVariableIndices(const std::function< void(int *)> &f, ConstraintProto *ct)
IndexReferences GetReferencesUsedByConstraint(const ConstraintProto &ct)
std::string ConstraintCaseName(ConstraintProto::ConstraintCase constraint_case)
Collection of objects used to extend the Constraint Solver library.
int index
Definition: pack.cc:509
IntervalVar * interval
Definition: resource.cc:100
int64_t capacity