OR-Tools  9.2
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#include <functional>
18
19#include "absl/container/flat_hash_map.h"
22
23namespace operations_research {
24namespace sat {
25
26namespace {
27
28template <typename IntList>
29void AddIndices(const IntList& indices, std::vector<int>* output) {
30 output->insert(output->end(), indices.begin(), indices.end());
31}
32
33} // namespace
34
36 LinearExpressionProto* output_negated_expr) {
37 output_negated_expr->Clear();
38 for (int i = 0; i < input_expr.vars_size(); ++i) {
39 output_negated_expr->add_vars(NegatedRef(input_expr.vars(i)));
40 output_negated_expr->add_coeffs(input_expr.coeffs(i));
41 }
42 output_negated_expr->set_offset(-input_expr.offset());
43}
44
46 IndexReferences output;
47 switch (ct.constraint_case()) {
48 case ConstraintProto::ConstraintCase::kBoolOr:
49 AddIndices(ct.bool_or().literals(), &output.literals);
50 break;
51 case ConstraintProto::ConstraintCase::kBoolAnd:
52 AddIndices(ct.bool_and().literals(), &output.literals);
53 break;
54 case ConstraintProto::ConstraintCase::kAtMostOne:
55 AddIndices(ct.at_most_one().literals(), &output.literals);
56 break;
57 case ConstraintProto::ConstraintCase::kExactlyOne:
58 AddIndices(ct.exactly_one().literals(), &output.literals);
59 break;
60 case ConstraintProto::ConstraintCase::kBoolXor:
61 AddIndices(ct.bool_xor().literals(), &output.literals);
62 break;
63 case ConstraintProto::ConstraintCase::kIntDiv:
64 AddIndices(ct.int_div().target().vars(), &output.variables);
65 for (const LinearExpressionProto& expr : ct.int_div().exprs()) {
66 AddIndices(expr.vars(), &output.variables);
67 }
68 break;
69 case ConstraintProto::ConstraintCase::kIntMod:
70 AddIndices(ct.int_mod().target().vars(), &output.variables);
71 for (const LinearExpressionProto& expr : ct.int_mod().exprs()) {
72 AddIndices(expr.vars(), &output.variables);
73 }
74 break;
75 case ConstraintProto::ConstraintCase::kLinMax: {
76 AddIndices(ct.lin_max().target().vars(), &output.variables);
77 for (const LinearExpressionProto& expr : ct.lin_max().exprs()) {
78 AddIndices(expr.vars(), &output.variables);
79 }
80 break;
81 }
82 case ConstraintProto::ConstraintCase::kIntProd:
83 AddIndices(ct.int_prod().target().vars(), &output.variables);
84 for (const LinearExpressionProto& expr : ct.int_prod().exprs()) {
85 AddIndices(expr.vars(), &output.variables);
86 }
87 break;
88 case ConstraintProto::ConstraintCase::kLinear:
89 AddIndices(ct.linear().vars(), &output.variables);
90 break;
91 case ConstraintProto::ConstraintCase::kAllDiff:
92 for (const LinearExpressionProto& expr : ct.all_diff().exprs()) {
93 AddIndices(expr.vars(), &output.variables);
94 }
95 break;
96 case ConstraintProto::ConstraintCase::kDummyConstraint:
97 AddIndices(ct.dummy_constraint().vars(), &output.variables);
98 break;
99 case ConstraintProto::ConstraintCase::kElement:
100 output.variables.push_back(ct.element().index());
101 output.variables.push_back(ct.element().target());
102 AddIndices(ct.element().vars(), &output.variables);
103 break;
104 case ConstraintProto::ConstraintCase::kCircuit:
105 AddIndices(ct.circuit().literals(), &output.literals);
106 break;
107 case ConstraintProto::ConstraintCase::kRoutes:
108 AddIndices(ct.routes().literals(), &output.literals);
109 break;
110 case ConstraintProto::ConstraintCase::kInverse:
111 AddIndices(ct.inverse().f_direct(), &output.variables);
112 AddIndices(ct.inverse().f_inverse(), &output.variables);
113 break;
114 case ConstraintProto::ConstraintCase::kReservoir:
115 for (const LinearExpressionProto& time : ct.reservoir().time_exprs()) {
116 AddIndices(time.vars(), &output.variables);
117 }
118 AddIndices(ct.reservoir().active_literals(), &output.literals);
119 break;
120 case ConstraintProto::ConstraintCase::kTable:
121 AddIndices(ct.table().vars(), &output.variables);
122 break;
123 case ConstraintProto::ConstraintCase::kAutomaton:
124 AddIndices(ct.automaton().vars(), &output.variables);
125 break;
126 case ConstraintProto::ConstraintCase::kInterval:
127 AddIndices(ct.interval().start().vars(), &output.variables);
128 AddIndices(ct.interval().size().vars(), &output.variables);
129 AddIndices(ct.interval().end().vars(), &output.variables);
130 break;
131 case ConstraintProto::ConstraintCase::kNoOverlap:
132 break;
133 case ConstraintProto::ConstraintCase::kNoOverlap2D:
134 break;
135 case ConstraintProto::ConstraintCase::kCumulative:
136 AddIndices(ct.cumulative().capacity().vars(), &output.variables);
137 for (const LinearExpressionProto& demand : ct.cumulative().demands()) {
138 AddIndices(demand.vars(), &output.variables);
139 }
140 break;
141 case ConstraintProto::ConstraintCase::CONSTRAINT_NOT_SET:
142 break;
143 }
144 return output;
145}
146
147#define APPLY_TO_SINGULAR_FIELD(ct_name, field_name) \
148 { \
149 int temp = ct->mutable_##ct_name()->field_name(); \
150 f(&temp); \
151 ct->mutable_##ct_name()->set_##field_name(temp); \
152 }
153
154#define APPLY_TO_REPEATED_FIELD(ct_name, field_name) \
155 { \
156 for (int& r : *ct->mutable_##ct_name()->mutable_##field_name()) f(&r); \
157 }
158
159void ApplyToAllLiteralIndices(const std::function<void(int*)>& f,
161 for (int& r : *ct->mutable_enforcement_literal()) f(&r);
162 switch (ct->constraint_case()) {
163 case ConstraintProto::ConstraintCase::kBoolOr:
164 APPLY_TO_REPEATED_FIELD(bool_or, literals);
165 break;
166 case ConstraintProto::ConstraintCase::kBoolAnd:
167 APPLY_TO_REPEATED_FIELD(bool_and, literals);
168 break;
169 case ConstraintProto::ConstraintCase::kAtMostOne:
170 APPLY_TO_REPEATED_FIELD(at_most_one, literals);
171 break;
172 case ConstraintProto::ConstraintCase::kExactlyOne:
173 APPLY_TO_REPEATED_FIELD(exactly_one, literals);
174 break;
175 case ConstraintProto::ConstraintCase::kBoolXor:
176 APPLY_TO_REPEATED_FIELD(bool_xor, literals);
177 break;
178 case ConstraintProto::ConstraintCase::kIntDiv:
179 break;
180 case ConstraintProto::ConstraintCase::kIntMod:
181 break;
182 case ConstraintProto::ConstraintCase::kLinMax:
183 break;
184 case ConstraintProto::ConstraintCase::kIntProd:
185 break;
186 case ConstraintProto::ConstraintCase::kLinear:
187 break;
188 case ConstraintProto::ConstraintCase::kAllDiff:
189 break;
190 case ConstraintProto::ConstraintCase::kDummyConstraint:
191 break;
192 case ConstraintProto::ConstraintCase::kElement:
193 break;
194 case ConstraintProto::ConstraintCase::kCircuit:
195 APPLY_TO_REPEATED_FIELD(circuit, literals);
196 break;
197 case ConstraintProto::ConstraintCase::kRoutes:
198 APPLY_TO_REPEATED_FIELD(routes, literals);
199 break;
200 case ConstraintProto::ConstraintCase::kInverse:
201 break;
202 case ConstraintProto::ConstraintCase::kReservoir:
203 APPLY_TO_REPEATED_FIELD(reservoir, active_literals);
204 break;
205 case ConstraintProto::ConstraintCase::kTable:
206 break;
207 case ConstraintProto::ConstraintCase::kAutomaton:
208 break;
209 case ConstraintProto::ConstraintCase::kInterval:
210 break;
211 case ConstraintProto::ConstraintCase::kNoOverlap:
212 break;
213 case ConstraintProto::ConstraintCase::kNoOverlap2D:
214 break;
215 case ConstraintProto::ConstraintCase::kCumulative:
216 break;
217 case ConstraintProto::ConstraintCase::CONSTRAINT_NOT_SET:
218 break;
219 }
220}
221
222void ApplyToAllVariableIndices(const std::function<void(int*)>& f,
224 switch (ct->constraint_case()) {
225 case ConstraintProto::ConstraintCase::kBoolOr:
226 break;
227 case ConstraintProto::ConstraintCase::kBoolAnd:
228 break;
229 case ConstraintProto::ConstraintCase::kAtMostOne:
230 break;
231 case ConstraintProto::ConstraintCase::kExactlyOne:
232 break;
233 case ConstraintProto::ConstraintCase::kBoolXor:
234 break;
235 case ConstraintProto::ConstraintCase::kIntDiv:
236 APPLY_TO_REPEATED_FIELD(int_div, target()->mutable_vars);
237 for (int i = 0; i < ct->int_div().exprs_size(); ++i) {
238 APPLY_TO_REPEATED_FIELD(int_div, exprs(i)->mutable_vars);
239 }
240 break;
241 case ConstraintProto::ConstraintCase::kIntMod:
242 APPLY_TO_REPEATED_FIELD(int_mod, target()->mutable_vars);
243 for (int i = 0; i < ct->int_mod().exprs_size(); ++i) {
244 APPLY_TO_REPEATED_FIELD(int_mod, exprs(i)->mutable_vars);
245 }
246 break;
247 case ConstraintProto::ConstraintCase::kLinMax:
248 APPLY_TO_REPEATED_FIELD(lin_max, target()->mutable_vars);
249 for (int i = 0; i < ct->lin_max().exprs_size(); ++i) {
250 APPLY_TO_REPEATED_FIELD(lin_max, exprs(i)->mutable_vars);
251 }
252 break;
253 case ConstraintProto::ConstraintCase::kIntProd:
254 APPLY_TO_REPEATED_FIELD(int_prod, target()->mutable_vars);
255 for (int i = 0; i < ct->int_prod().exprs_size(); ++i) {
256 APPLY_TO_REPEATED_FIELD(int_prod, exprs(i)->mutable_vars);
257 }
258 break;
259 case ConstraintProto::ConstraintCase::kLinear:
260 APPLY_TO_REPEATED_FIELD(linear, vars);
261 break;
262 case ConstraintProto::ConstraintCase::kAllDiff:
263 for (int i = 0; i < ct->all_diff().exprs_size(); ++i) {
264 APPLY_TO_REPEATED_FIELD(all_diff, exprs(i)->mutable_vars);
265 }
266 break;
267 case ConstraintProto::ConstraintCase::kDummyConstraint:
268 APPLY_TO_REPEATED_FIELD(dummy_constraint, vars);
269 break;
270 case ConstraintProto::ConstraintCase::kElement:
272 APPLY_TO_SINGULAR_FIELD(element, target);
273 APPLY_TO_REPEATED_FIELD(element, vars);
274 break;
275 case ConstraintProto::ConstraintCase::kCircuit:
276 break;
277 case ConstraintProto::ConstraintCase::kRoutes:
278 break;
279 case ConstraintProto::ConstraintCase::kInverse:
280 APPLY_TO_REPEATED_FIELD(inverse, f_direct);
281 APPLY_TO_REPEATED_FIELD(inverse, f_inverse);
282 break;
283 case ConstraintProto::ConstraintCase::kReservoir:
284 for (int i = 0; i < ct->reservoir().time_exprs_size(); ++i) {
285 APPLY_TO_REPEATED_FIELD(reservoir, time_exprs(i)->mutable_vars);
286 }
287 break;
288 case ConstraintProto::ConstraintCase::kTable:
289 APPLY_TO_REPEATED_FIELD(table, vars);
290 break;
291 case ConstraintProto::ConstraintCase::kAutomaton:
292 APPLY_TO_REPEATED_FIELD(automaton, vars);
293 break;
294 case ConstraintProto::ConstraintCase::kInterval:
295 APPLY_TO_REPEATED_FIELD(interval, start()->mutable_vars);
296 APPLY_TO_REPEATED_FIELD(interval, size()->mutable_vars);
297 APPLY_TO_REPEATED_FIELD(interval, end()->mutable_vars);
298 break;
299 case ConstraintProto::ConstraintCase::kNoOverlap:
300 break;
301 case ConstraintProto::ConstraintCase::kNoOverlap2D:
302 break;
303 case ConstraintProto::ConstraintCase::kCumulative:
304 APPLY_TO_REPEATED_FIELD(cumulative, capacity()->mutable_vars);
305 for (int i = 0; i < ct->cumulative().demands_size(); ++i) {
306 for (int& r :
307 *ct->mutable_cumulative()->mutable_demands(i)->mutable_vars()) {
308 f(&r);
309 }
310 }
311 break;
312 case ConstraintProto::ConstraintCase::CONSTRAINT_NOT_SET:
313 break;
314 }
315}
316
317void ApplyToAllIntervalIndices(const std::function<void(int*)>& f,
319 switch (ct->constraint_case()) {
320 case ConstraintProto::ConstraintCase::kBoolOr:
321 break;
322 case ConstraintProto::ConstraintCase::kBoolAnd:
323 break;
324 case ConstraintProto::ConstraintCase::kAtMostOne:
325 break;
326 case ConstraintProto::ConstraintCase::kExactlyOne:
327 break;
328 case ConstraintProto::ConstraintCase::kBoolXor:
329 break;
330 case ConstraintProto::ConstraintCase::kIntDiv:
331 break;
332 case ConstraintProto::ConstraintCase::kIntMod:
333 break;
334 case ConstraintProto::ConstraintCase::kLinMax:
335 break;
336 case ConstraintProto::ConstraintCase::kIntProd:
337 break;
338 case ConstraintProto::ConstraintCase::kLinear:
339 break;
340 case ConstraintProto::ConstraintCase::kAllDiff:
341 break;
342 case ConstraintProto::ConstraintCase::kDummyConstraint:
343 break;
344 case ConstraintProto::ConstraintCase::kElement:
345 break;
346 case ConstraintProto::ConstraintCase::kCircuit:
347 break;
348 case ConstraintProto::ConstraintCase::kRoutes:
349 break;
350 case ConstraintProto::ConstraintCase::kInverse:
351 break;
352 case ConstraintProto::ConstraintCase::kReservoir:
353 break;
354 case ConstraintProto::ConstraintCase::kTable:
355 break;
356 case ConstraintProto::ConstraintCase::kAutomaton:
357 break;
358 case ConstraintProto::ConstraintCase::kInterval:
359 break;
360 case ConstraintProto::ConstraintCase::kNoOverlap:
361 APPLY_TO_REPEATED_FIELD(no_overlap, intervals);
362 break;
363 case ConstraintProto::ConstraintCase::kNoOverlap2D:
364 APPLY_TO_REPEATED_FIELD(no_overlap_2d, x_intervals);
365 APPLY_TO_REPEATED_FIELD(no_overlap_2d, y_intervals);
366 break;
367 case ConstraintProto::ConstraintCase::kCumulative:
368 APPLY_TO_REPEATED_FIELD(cumulative, intervals);
369 break;
370 case ConstraintProto::ConstraintCase::CONSTRAINT_NOT_SET:
371 break;
372 }
373}
374
375#undef APPLY_TO_SINGULAR_FIELD
376#undef APPLY_TO_REPEATED_FIELD
377
379 ConstraintProto::ConstraintCase constraint_case) {
380 switch (constraint_case) {
381 case ConstraintProto::ConstraintCase::kBoolOr:
382 return "kBoolOr";
383 case ConstraintProto::ConstraintCase::kBoolAnd:
384 return "kBoolAnd";
385 case ConstraintProto::ConstraintCase::kAtMostOne:
386 return "kAtMostOne";
387 case ConstraintProto::ConstraintCase::kExactlyOne:
388 return "kExactlyOne";
389 case ConstraintProto::ConstraintCase::kBoolXor:
390 return "kBoolXor";
391 case ConstraintProto::ConstraintCase::kIntDiv:
392 return "kIntDiv";
393 case ConstraintProto::ConstraintCase::kIntMod:
394 return "kIntMod";
395 case ConstraintProto::ConstraintCase::kLinMax:
396 return "kLinMax";
397 case ConstraintProto::ConstraintCase::kIntProd:
398 return "kIntProd";
399 case ConstraintProto::ConstraintCase::kLinear:
400 return "kLinear";
401 case ConstraintProto::ConstraintCase::kAllDiff:
402 return "kAllDiff";
403 case ConstraintProto::ConstraintCase::kDummyConstraint:
404 return "kDummyConstraint";
405 case ConstraintProto::ConstraintCase::kElement:
406 return "kElement";
407 case ConstraintProto::ConstraintCase::kCircuit:
408 return "kCircuit";
409 case ConstraintProto::ConstraintCase::kRoutes:
410 return "kRoutes";
411 case ConstraintProto::ConstraintCase::kInverse:
412 return "kInverse";
413 case ConstraintProto::ConstraintCase::kReservoir:
414 return "kReservoir";
415 case ConstraintProto::ConstraintCase::kTable:
416 return "kTable";
417 case ConstraintProto::ConstraintCase::kAutomaton:
418 return "kAutomaton";
419 case ConstraintProto::ConstraintCase::kInterval:
420 return "kInterval";
421 case ConstraintProto::ConstraintCase::kNoOverlap:
422 return "kNoOverlap";
423 case ConstraintProto::ConstraintCase::kNoOverlap2D:
424 return "kNoOverlap2D";
425 case ConstraintProto::ConstraintCase::kCumulative:
426 return "kCumulative";
427 case ConstraintProto::ConstraintCase::CONSTRAINT_NOT_SET:
428 return "kEmpty";
429 }
430}
431
432std::vector<int> UsedVariables(const ConstraintProto& ct) {
434 for (int& ref : references.variables) {
435 ref = PositiveRef(ref);
436 }
437 for (const int lit : references.literals) {
438 references.variables.push_back(PositiveRef(lit));
439 }
440 for (const int lit : ct.enforcement_literal()) {
441 references.variables.push_back(PositiveRef(lit));
442 }
444 return references.variables;
445}
446
447std::vector<int> UsedIntervals(const ConstraintProto& ct) {
448 std::vector<int> used_intervals;
449 switch (ct.constraint_case()) {
450 case ConstraintProto::ConstraintCase::kBoolOr:
451 break;
452 case ConstraintProto::ConstraintCase::kBoolAnd:
453 break;
454 case ConstraintProto::ConstraintCase::kAtMostOne:
455 break;
456 case ConstraintProto::ConstraintCase::kExactlyOne:
457 break;
458 case ConstraintProto::ConstraintCase::kBoolXor:
459 break;
460 case ConstraintProto::ConstraintCase::kIntDiv:
461 break;
462 case ConstraintProto::ConstraintCase::kIntMod:
463 break;
464 case ConstraintProto::ConstraintCase::kLinMax:
465 break;
466 case ConstraintProto::ConstraintCase::kIntProd:
467 break;
468 case ConstraintProto::ConstraintCase::kLinear:
469 break;
470 case ConstraintProto::ConstraintCase::kAllDiff:
471 break;
472 case ConstraintProto::ConstraintCase::kDummyConstraint:
473 break;
474 case ConstraintProto::ConstraintCase::kElement:
475 break;
476 case ConstraintProto::ConstraintCase::kCircuit:
477 break;
478 case ConstraintProto::ConstraintCase::kRoutes:
479 break;
480 case ConstraintProto::ConstraintCase::kInverse:
481 break;
482 case ConstraintProto::ConstraintCase::kReservoir:
483 break;
484 case ConstraintProto::ConstraintCase::kTable:
485 break;
486 case ConstraintProto::ConstraintCase::kAutomaton:
487 break;
488 case ConstraintProto::ConstraintCase::kInterval:
489 break;
490 case ConstraintProto::ConstraintCase::kNoOverlap:
491 AddIndices(ct.no_overlap().intervals(), &used_intervals);
492 break;
493 case ConstraintProto::ConstraintCase::kNoOverlap2D:
494 AddIndices(ct.no_overlap_2d().x_intervals(), &used_intervals);
495 AddIndices(ct.no_overlap_2d().y_intervals(), &used_intervals);
496 break;
497 case ConstraintProto::ConstraintCase::kCumulative:
498 AddIndices(ct.cumulative().intervals(), &used_intervals);
499 break;
500 case ConstraintProto::ConstraintCase::CONSTRAINT_NOT_SET:
501 break;
502 }
503 gtl::STLSortAndRemoveDuplicates(&used_intervals);
504 return used_intervals;
505}
506
508 const CpSolverResponse& response) {
509 int64_t objective_value = 0;
510 for (int i = 0; i < objective.vars_size(); ++i) {
511 int64_t coeff = objective.coeffs(i);
512 const int ref = objective.vars(i);
513 const int var = PositiveRef(ref);
514 if (!RefIsPositive(ref)) coeff = -coeff;
515 objective_value += coeff * response.solution()[var];
516 }
517 return objective_value;
518}
519
521 return expr.offset() == 0 && expr.vars_size() == 1 &&
522 std::abs(expr.coeffs(0)) == 1;
523}
524
526 return expr.vars_size() <= 1;
527}
528
529// Returns the reference the expression can be reduced to. It will DCHECK that
530// ExpressionContainsSingleRef(expr) is true.
533 return expr.coeffs(0) == 1 ? expr.vars(0) : NegatedRef(expr.vars(0));
534}
535
537 int64_t coefficient,
538 LinearConstraintProto* linear) {
539 for (int i = 0; i < expr.vars_size(); ++i) {
540 linear->add_vars(expr.vars(i));
541 linear->add_coeffs(expr.coeffs(i) * coefficient);
542 }
543 DCHECK(!linear->domain().empty());
544 const int64_t shift = coefficient * expr.offset();
545 if (shift != 0) {
546 for (int64_t& d : *linear->mutable_domain()) {
547 d -= shift;
548 }
549 }
550}
551
554 int64_t b_scaling) {
555 if (a.vars_size() != b.vars_size()) return false;
556 if (a.offset() != b.offset() * b_scaling) return false;
557 absl::flat_hash_map<int, int64_t> coeffs;
558 for (int i = 0; i < a.vars_size(); ++i) {
559 coeffs[a.vars(i)] += a.coeffs(i);
560 coeffs[b.vars(i)] += -b.coeffs(i) * b_scaling;
561 }
562
563 for (const auto [var, coeff] : coeffs) {
564 if (coeff != 0) return false;
565 }
566 return true;
567}
568
569} // namespace sat
570} // namespace operations_research
#define DCHECK(condition)
Definition: base/logging.h:889
::PROTOBUF_NAMESPACE_ID::RepeatedField< int64_t > * mutable_domain()
Definition: cp_model.pb.h:7623
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final
int64_t b
int64_t a
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)
bool LinearExpressionProtosAreEqual(const LinearExpressionProto &a, const LinearExpressionProto &b, int64_t b_scaling)
void ApplyToAllIntervalIndices(const std::function< void(int *)> &f, ConstraintProto *ct)
bool ExpressionIsAffine(const LinearExpressionProto &expr)
void ApplyToAllVariableIndices(const std::function< void(int *)> &f, ConstraintProto *ct)
IndexReferences GetReferencesUsedByConstraint(const ConstraintProto &ct)
void AddLinearExpressionToLinearConstraint(const LinearExpressionProto &expr, int64_t coefficient, LinearConstraintProto *linear)
std::string ConstraintCaseName(ConstraintProto::ConstraintCase constraint_case)
int GetSingleRefFromExpression(const LinearExpressionProto &expr)
bool ExpressionContainsSingleRef(const LinearExpressionProto &expr)
Collection of objects used to extend the Constraint Solver library.
int index
Definition: pack.cc:509
int64_t demand
Definition: resource.cc:125
int64_t time
Definition: resource.cc:1691
IntervalVar * interval
Definition: resource.cc:100
int64_t coefficient
int64_t capacity
std::optional< int64_t > end
int64_t start
const double coeff