19#include "absl/container/flat_hash_map.h"
28template <
typename IntList>
29void AddIndices(
const IntList& indices, std::vector<int>* output) {
30 output->insert(output->end(), indices.begin(), indices.end());
37 output_negated_expr->
Clear();
38 for (
int i = 0; i < input_expr.
vars_size(); ++i) {
47 switch (
ct.constraint_case()) {
48 case ConstraintProto::ConstraintCase::kBoolOr:
49 AddIndices(
ct.bool_or().literals(), &output.
literals);
51 case ConstraintProto::ConstraintCase::kBoolAnd:
52 AddIndices(
ct.bool_and().literals(), &output.
literals);
54 case ConstraintProto::ConstraintCase::kAtMostOne:
55 AddIndices(
ct.at_most_one().literals(), &output.
literals);
57 case ConstraintProto::ConstraintCase::kExactlyOne:
58 AddIndices(
ct.exactly_one().literals(), &output.
literals);
60 case ConstraintProto::ConstraintCase::kBoolXor:
61 AddIndices(
ct.bool_xor().literals(), &output.
literals);
63 case ConstraintProto::ConstraintCase::kIntDiv:
64 AddIndices(
ct.int_div().target().vars(), &output.
variables);
66 AddIndices(expr.vars(), &output.
variables);
69 case ConstraintProto::ConstraintCase::kIntMod:
70 AddIndices(
ct.int_mod().target().vars(), &output.
variables);
72 AddIndices(expr.vars(), &output.
variables);
75 case ConstraintProto::ConstraintCase::kLinMax: {
76 AddIndices(
ct.lin_max().target().vars(), &output.
variables);
78 AddIndices(expr.vars(), &output.
variables);
82 case ConstraintProto::ConstraintCase::kIntProd:
83 AddIndices(
ct.int_prod().target().vars(), &output.
variables);
85 AddIndices(expr.vars(), &output.
variables);
88 case ConstraintProto::ConstraintCase::kLinear:
91 case ConstraintProto::ConstraintCase::kAllDiff:
93 AddIndices(expr.vars(), &output.
variables);
96 case ConstraintProto::ConstraintCase::kDummyConstraint:
97 AddIndices(
ct.dummy_constraint().vars(), &output.
variables);
99 case ConstraintProto::ConstraintCase::kElement:
102 AddIndices(
ct.element().vars(), &output.
variables);
104 case ConstraintProto::ConstraintCase::kCircuit:
105 AddIndices(
ct.circuit().literals(), &output.
literals);
107 case ConstraintProto::ConstraintCase::kRoutes:
108 AddIndices(
ct.routes().literals(), &output.
literals);
110 case ConstraintProto::ConstraintCase::kInverse:
111 AddIndices(
ct.inverse().f_direct(), &output.
variables);
112 AddIndices(
ct.inverse().f_inverse(), &output.
variables);
114 case ConstraintProto::ConstraintCase::kReservoir:
118 AddIndices(
ct.reservoir().active_literals(), &output.
literals);
120 case ConstraintProto::ConstraintCase::kTable:
123 case ConstraintProto::ConstraintCase::kAutomaton:
124 AddIndices(
ct.automaton().vars(), &output.
variables);
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);
131 case ConstraintProto::ConstraintCase::kNoOverlap:
133 case ConstraintProto::ConstraintCase::kNoOverlap2D:
135 case ConstraintProto::ConstraintCase::kCumulative:
136 AddIndices(
ct.cumulative().capacity().vars(), &output.
variables);
141 case ConstraintProto::ConstraintCase::CONSTRAINT_NOT_SET:
147#define APPLY_TO_SINGULAR_FIELD(ct_name, field_name) \
149 int temp = ct->mutable_##ct_name()->field_name(); \
151 ct->mutable_##ct_name()->set_##field_name(temp); \
154#define APPLY_TO_REPEATED_FIELD(ct_name, field_name) \
156 for (int& r : *ct->mutable_##ct_name()->mutable_##field_name()) f(&r); \
161 for (
int& r : *
ct->mutable_enforcement_literal()) f(&r);
162 switch (
ct->constraint_case()) {
163 case ConstraintProto::ConstraintCase::kBoolOr:
166 case ConstraintProto::ConstraintCase::kBoolAnd:
169 case ConstraintProto::ConstraintCase::kAtMostOne:
172 case ConstraintProto::ConstraintCase::kExactlyOne:
175 case ConstraintProto::ConstraintCase::kBoolXor:
178 case ConstraintProto::ConstraintCase::kIntDiv:
180 case ConstraintProto::ConstraintCase::kIntMod:
182 case ConstraintProto::ConstraintCase::kLinMax:
184 case ConstraintProto::ConstraintCase::kIntProd:
186 case ConstraintProto::ConstraintCase::kLinear:
188 case ConstraintProto::ConstraintCase::kAllDiff:
190 case ConstraintProto::ConstraintCase::kDummyConstraint:
192 case ConstraintProto::ConstraintCase::kElement:
194 case ConstraintProto::ConstraintCase::kCircuit:
197 case ConstraintProto::ConstraintCase::kRoutes:
200 case ConstraintProto::ConstraintCase::kInverse:
202 case ConstraintProto::ConstraintCase::kReservoir:
205 case ConstraintProto::ConstraintCase::kTable:
207 case ConstraintProto::ConstraintCase::kAutomaton:
209 case ConstraintProto::ConstraintCase::kInterval:
211 case ConstraintProto::ConstraintCase::kNoOverlap:
213 case ConstraintProto::ConstraintCase::kNoOverlap2D:
215 case ConstraintProto::ConstraintCase::kCumulative:
217 case ConstraintProto::ConstraintCase::CONSTRAINT_NOT_SET:
224 switch (
ct->constraint_case()) {
225 case ConstraintProto::ConstraintCase::kBoolOr:
227 case ConstraintProto::ConstraintCase::kBoolAnd:
229 case ConstraintProto::ConstraintCase::kAtMostOne:
231 case ConstraintProto::ConstraintCase::kExactlyOne:
233 case ConstraintProto::ConstraintCase::kBoolXor:
235 case ConstraintProto::ConstraintCase::kIntDiv:
237 for (
int i = 0; i <
ct->int_div().exprs_size(); ++i) {
241 case ConstraintProto::ConstraintCase::kIntMod:
243 for (
int i = 0; i <
ct->int_mod().exprs_size(); ++i) {
247 case ConstraintProto::ConstraintCase::kLinMax:
249 for (
int i = 0; i <
ct->lin_max().exprs_size(); ++i) {
253 case ConstraintProto::ConstraintCase::kIntProd:
255 for (
int i = 0; i <
ct->int_prod().exprs_size(); ++i) {
259 case ConstraintProto::ConstraintCase::kLinear:
262 case ConstraintProto::ConstraintCase::kAllDiff:
263 for (
int i = 0; i <
ct->all_diff().exprs_size(); ++i) {
267 case ConstraintProto::ConstraintCase::kDummyConstraint:
270 case ConstraintProto::ConstraintCase::kElement:
275 case ConstraintProto::ConstraintCase::kCircuit:
277 case ConstraintProto::ConstraintCase::kRoutes:
279 case ConstraintProto::ConstraintCase::kInverse:
283 case ConstraintProto::ConstraintCase::kReservoir:
284 for (
int i = 0; i <
ct->reservoir().time_exprs_size(); ++i) {
288 case ConstraintProto::ConstraintCase::kTable:
291 case ConstraintProto::ConstraintCase::kAutomaton:
294 case ConstraintProto::ConstraintCase::kInterval:
299 case ConstraintProto::ConstraintCase::kNoOverlap:
301 case ConstraintProto::ConstraintCase::kNoOverlap2D:
303 case ConstraintProto::ConstraintCase::kCumulative:
305 for (
int i = 0; i <
ct->cumulative().demands_size(); ++i) {
307 *
ct->mutable_cumulative()->mutable_demands(i)->mutable_vars()) {
312 case ConstraintProto::ConstraintCase::CONSTRAINT_NOT_SET:
319 switch (
ct->constraint_case()) {
320 case ConstraintProto::ConstraintCase::kBoolOr:
322 case ConstraintProto::ConstraintCase::kBoolAnd:
324 case ConstraintProto::ConstraintCase::kAtMostOne:
326 case ConstraintProto::ConstraintCase::kExactlyOne:
328 case ConstraintProto::ConstraintCase::kBoolXor:
330 case ConstraintProto::ConstraintCase::kIntDiv:
332 case ConstraintProto::ConstraintCase::kIntMod:
334 case ConstraintProto::ConstraintCase::kLinMax:
336 case ConstraintProto::ConstraintCase::kIntProd:
338 case ConstraintProto::ConstraintCase::kLinear:
340 case ConstraintProto::ConstraintCase::kAllDiff:
342 case ConstraintProto::ConstraintCase::kDummyConstraint:
344 case ConstraintProto::ConstraintCase::kElement:
346 case ConstraintProto::ConstraintCase::kCircuit:
348 case ConstraintProto::ConstraintCase::kRoutes:
350 case ConstraintProto::ConstraintCase::kInverse:
352 case ConstraintProto::ConstraintCase::kReservoir:
354 case ConstraintProto::ConstraintCase::kTable:
356 case ConstraintProto::ConstraintCase::kAutomaton:
358 case ConstraintProto::ConstraintCase::kInterval:
360 case ConstraintProto::ConstraintCase::kNoOverlap:
363 case ConstraintProto::ConstraintCase::kNoOverlap2D:
367 case ConstraintProto::ConstraintCase::kCumulative:
370 case ConstraintProto::ConstraintCase::CONSTRAINT_NOT_SET:
375#undef APPLY_TO_SINGULAR_FIELD
376#undef APPLY_TO_REPEATED_FIELD
380 switch (constraint_case) {
381 case ConstraintProto::ConstraintCase::kBoolOr:
383 case ConstraintProto::ConstraintCase::kBoolAnd:
385 case ConstraintProto::ConstraintCase::kAtMostOne:
387 case ConstraintProto::ConstraintCase::kExactlyOne:
388 return "kExactlyOne";
389 case ConstraintProto::ConstraintCase::kBoolXor:
391 case ConstraintProto::ConstraintCase::kIntDiv:
393 case ConstraintProto::ConstraintCase::kIntMod:
395 case ConstraintProto::ConstraintCase::kLinMax:
397 case ConstraintProto::ConstraintCase::kIntProd:
399 case ConstraintProto::ConstraintCase::kLinear:
401 case ConstraintProto::ConstraintCase::kAllDiff:
403 case ConstraintProto::ConstraintCase::kDummyConstraint:
404 return "kDummyConstraint";
405 case ConstraintProto::ConstraintCase::kElement:
407 case ConstraintProto::ConstraintCase::kCircuit:
409 case ConstraintProto::ConstraintCase::kRoutes:
411 case ConstraintProto::ConstraintCase::kInverse:
413 case ConstraintProto::ConstraintCase::kReservoir:
415 case ConstraintProto::ConstraintCase::kTable:
417 case ConstraintProto::ConstraintCase::kAutomaton:
419 case ConstraintProto::ConstraintCase::kInterval:
421 case ConstraintProto::ConstraintCase::kNoOverlap:
423 case ConstraintProto::ConstraintCase::kNoOverlap2D:
424 return "kNoOverlap2D";
425 case ConstraintProto::ConstraintCase::kCumulative:
426 return "kCumulative";
427 case ConstraintProto::ConstraintCase::CONSTRAINT_NOT_SET:
437 for (
const int lit : references.
literals) {
440 for (
const int lit :
ct.enforcement_literal()) {
448 std::vector<int> used_intervals;
449 switch (
ct.constraint_case()) {
450 case ConstraintProto::ConstraintCase::kBoolOr:
452 case ConstraintProto::ConstraintCase::kBoolAnd:
454 case ConstraintProto::ConstraintCase::kAtMostOne:
456 case ConstraintProto::ConstraintCase::kExactlyOne:
458 case ConstraintProto::ConstraintCase::kBoolXor:
460 case ConstraintProto::ConstraintCase::kIntDiv:
462 case ConstraintProto::ConstraintCase::kIntMod:
464 case ConstraintProto::ConstraintCase::kLinMax:
466 case ConstraintProto::ConstraintCase::kIntProd:
468 case ConstraintProto::ConstraintCase::kLinear:
470 case ConstraintProto::ConstraintCase::kAllDiff:
472 case ConstraintProto::ConstraintCase::kDummyConstraint:
474 case ConstraintProto::ConstraintCase::kElement:
476 case ConstraintProto::ConstraintCase::kCircuit:
478 case ConstraintProto::ConstraintCase::kRoutes:
480 case ConstraintProto::ConstraintCase::kInverse:
482 case ConstraintProto::ConstraintCase::kReservoir:
484 case ConstraintProto::ConstraintCase::kTable:
486 case ConstraintProto::ConstraintCase::kAutomaton:
488 case ConstraintProto::ConstraintCase::kInterval:
490 case ConstraintProto::ConstraintCase::kNoOverlap:
491 AddIndices(
ct.no_overlap().intervals(), &used_intervals);
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);
497 case ConstraintProto::ConstraintCase::kCumulative:
498 AddIndices(
ct.cumulative().intervals(), &used_intervals);
500 case ConstraintProto::ConstraintCase::CONSTRAINT_NOT_SET:
504 return used_intervals;
509 int64_t objective_value = 0;
510 for (
int i = 0; i < objective.
vars_size(); ++i) {
512 const int ref = objective.
vars(i);
517 return objective_value;
522 std::abs(expr.
coeffs(0)) == 1;
539 for (
int i = 0; i < expr.
vars_size(); ++i) {
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;
563 for (
const auto [
var,
coeff] : coeffs) {
564 if (
coeff != 0)
return false;
#define DCHECK(condition)
int32_t vars(int index) const
int64_t coeffs(int index) const
::PROTOBUF_NAMESPACE_ID::RepeatedField< int64_t > * mutable_domain()
void add_coeffs(int64_t value)
void add_vars(int32_t value)
int64_t domain(int index) const
void set_offset(int64_t value)
void add_coeffs(int64_t value)
void add_vars(int32_t value)
int32_t vars(int index) const
int64_t coeffs(int index) const
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final
SharedResponseManager * response
#define APPLY_TO_SINGULAR_FIELD(ct_name, field_name)
#define APPLY_TO_REPEATED_FIELD(ct_name, field_name)
void STLSortAndRemoveDuplicates(T *v, const LessFunc &less_func)
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.
std::optional< int64_t > end
std::vector< int > variables
std::vector< int > literals