Skip to content

Commit 98129bd

Browse files
committed
[CP-SAT] more bug fixes; more moving of hint management to solution_crush
1 parent 81e18b7 commit 98129bd

File tree

10 files changed

+399
-401
lines changed

10 files changed

+399
-401
lines changed

ortools/sat/BUILD.bazel

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,9 +835,12 @@ cc_library(
835835
":cp_model_cc_proto",
836836
":cp_model_utils",
837837
":sat_parameters_cc_proto",
838+
":symmetry_util",
838839
"//ortools/algorithms:sparse_permutation",
839840
"//ortools/util:sorted_interval_list",
840841
"@com_google_absl//absl/container:flat_hash_map",
842+
"@com_google_absl//absl/container:inlined_vector",
843+
"@com_google_absl//absl/log",
841844
"@com_google_absl//absl/log:check",
842845
"@com_google_absl//absl/types:span",
843846
],

ortools/sat/cp_model.proto

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,9 @@ message NoOverlap2DConstraintProto {
160160
// this constraint. Moreover, intervals of size zero are ignored.
161161
//
162162
// All demands must not contain any negative value in their domains. This is
163-
// checked at validation. The capacity can currently contains negative values,
164-
// but it will be propagated to >= 0 right away.
163+
// checked at validation. Even if there are no intervals, this constraint
164+
// implicit enforces capacity >= 0. In other words, a negative capacity is
165+
// considered valid but always infeasible.
165166
message CumulativeConstraintProto {
166167
LinearExpressionProto capacity = 1;
167168
repeated int32 intervals = 2;

ortools/sat/cp_model_checker.cc

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,20 @@ std::string ValidateIntDivConstraint(const CpModelProto& model,
423423
return "";
424424
}
425425

426+
void AppendToOverflowValidator(const LinearExpressionProto& input,
427+
LinearExpressionProto* output,
428+
int64_t prod = 1) {
429+
output->mutable_vars()->Add(input.vars().begin(), input.vars().end());
430+
for (const int64_t coeff : input.coeffs()) {
431+
output->add_coeffs(coeff * prod);
432+
}
433+
434+
// We add the absolute value to be sure that future computation will not
435+
// overflow depending on the order they are performed in.
436+
output->set_offset(
437+
CapAdd(std::abs(output->offset()), std::abs(input.offset())));
438+
}
439+
426440
std::string ValidateElementConstraint(const CpModelProto& model,
427441
const ConstraintProto& ct) {
428442
const ElementConstraintProto& element = ct.element();
@@ -484,10 +498,7 @@ std::string ValidateElementConstraint(const CpModelProto& model,
484498
for (const LinearExpressionProto& expr : element.exprs()) {
485499
RETURN_IF_NOT_EMPTY(ValidateAffineExpression(model, expr));
486500
LinearExpressionProto overflow_detection = ct.element().linear_target();
487-
for (int i = 0; i < expr.vars_size(); ++i) {
488-
overflow_detection.add_vars(expr.vars(i));
489-
overflow_detection.add_coeffs(-expr.coeffs(i));
490-
}
501+
AppendToOverflowValidator(expr, &overflow_detection, -1);
491502
overflow_detection.set_offset(overflow_detection.offset() -
492503
expr.offset());
493504
if (PossibleIntegerOverflow(model, overflow_detection.vars(),
@@ -647,17 +658,6 @@ std::string ValidateRoutesConstraint(const ConstraintProto& ct) {
647658
return ValidateGraphInput(/*is_route=*/true, ct.routes());
648659
}
649660

650-
void AppendToOverflowValidator(const LinearExpressionProto& input,
651-
LinearExpressionProto* output) {
652-
output->mutable_vars()->Add(input.vars().begin(), input.vars().end());
653-
output->mutable_coeffs()->Add(input.coeffs().begin(), input.coeffs().end());
654-
655-
// We add the absolute value to be sure that future computation will not
656-
// overflow depending on the order they are performed in.
657-
output->set_offset(
658-
CapAdd(std::abs(output->offset()), std::abs(input.offset())));
659-
}
660-
661661
std::string ValidateIntervalConstraint(const CpModelProto& model,
662662
const ConstraintProto& ct) {
663663
if (ct.enforcement_literal().size() > 1) {
@@ -705,7 +705,7 @@ std::string ValidateIntervalConstraint(const CpModelProto& model,
705705
"variable are currently not supported.";
706706
}
707707
RETURN_IF_NOT_EMPTY(ValidateLinearExpression(model, arg.end()));
708-
AppendToOverflowValidator(arg.end(), &for_overflow_validation);
708+
AppendToOverflowValidator(arg.end(), &for_overflow_validation, -1);
709709

710710
if (PossibleIntegerOverflow(model, for_overflow_validation.vars(),
711711
for_overflow_validation.coeffs(),
@@ -1484,6 +1484,7 @@ class ConstraintChecker {
14841484
bool CumulativeConstraintIsFeasible(const CpModelProto& model,
14851485
const ConstraintProto& ct) {
14861486
const int64_t capacity = LinearExpressionValue(ct.cumulative().capacity());
1487+
if (capacity < 0) return false;
14871488
const int num_intervals = ct.cumulative().intervals_size();
14881489
std::vector<std::pair<int64_t, int64_t>> events;
14891490
for (int i = 0; i < num_intervals; ++i) {

0 commit comments

Comments
 (0)