Skip to content

Commit

Permalink
[CP-SAT] more bug fixes; more moving of hint management to solution_c…
Browse files Browse the repository at this point in the history
…rush
  • Loading branch information
lperron committed Jan 22, 2025
1 parent 52a9170 commit eee2f10
Show file tree
Hide file tree
Showing 10 changed files with 399 additions and 401 deletions.
3 changes: 3 additions & 0 deletions ortools/sat/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -835,9 +835,12 @@ cc_library(
":cp_model_cc_proto",
":cp_model_utils",
":sat_parameters_cc_proto",
":symmetry_util",
"//ortools/algorithms:sparse_permutation",
"//ortools/util:sorted_interval_list",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/container:inlined_vector",
"@com_google_absl//absl/log",
"@com_google_absl//absl/log:check",
"@com_google_absl//absl/types:span",
],
Expand Down
5 changes: 3 additions & 2 deletions ortools/sat/cp_model.proto
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,9 @@ message NoOverlap2DConstraintProto {
// this constraint. Moreover, intervals of size zero are ignored.
//
// All demands must not contain any negative value in their domains. This is
// checked at validation. The capacity can currently contains negative values,
// but it will be propagated to >= 0 right away.
// checked at validation. Even if there are no intervals, this constraint
// implicit enforces capacity >= 0. In other words, a negative capacity is
// considered valid but always infeasible.
message CumulativeConstraintProto {
LinearExpressionProto capacity = 1;
repeated int32 intervals = 2;
Expand Down
33 changes: 17 additions & 16 deletions ortools/sat/cp_model_checker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,20 @@ std::string ValidateIntDivConstraint(const CpModelProto& model,
return "";
}

void AppendToOverflowValidator(const LinearExpressionProto& input,
LinearExpressionProto* output,
int64_t prod = 1) {
output->mutable_vars()->Add(input.vars().begin(), input.vars().end());
for (const int64_t coeff : input.coeffs()) {
output->add_coeffs(coeff * prod);
}

// We add the absolute value to be sure that future computation will not
// overflow depending on the order they are performed in.
output->set_offset(
CapAdd(std::abs(output->offset()), std::abs(input.offset())));
}

std::string ValidateElementConstraint(const CpModelProto& model,
const ConstraintProto& ct) {
const ElementConstraintProto& element = ct.element();
Expand Down Expand Up @@ -484,10 +498,7 @@ std::string ValidateElementConstraint(const CpModelProto& model,
for (const LinearExpressionProto& expr : element.exprs()) {
RETURN_IF_NOT_EMPTY(ValidateAffineExpression(model, expr));
LinearExpressionProto overflow_detection = ct.element().linear_target();
for (int i = 0; i < expr.vars_size(); ++i) {
overflow_detection.add_vars(expr.vars(i));
overflow_detection.add_coeffs(-expr.coeffs(i));
}
AppendToOverflowValidator(expr, &overflow_detection, -1);
overflow_detection.set_offset(overflow_detection.offset() -
expr.offset());
if (PossibleIntegerOverflow(model, overflow_detection.vars(),
Expand Down Expand Up @@ -647,17 +658,6 @@ std::string ValidateRoutesConstraint(const ConstraintProto& ct) {
return ValidateGraphInput(/*is_route=*/true, ct.routes());
}

void AppendToOverflowValidator(const LinearExpressionProto& input,
LinearExpressionProto* output) {
output->mutable_vars()->Add(input.vars().begin(), input.vars().end());
output->mutable_coeffs()->Add(input.coeffs().begin(), input.coeffs().end());

// We add the absolute value to be sure that future computation will not
// overflow depending on the order they are performed in.
output->set_offset(
CapAdd(std::abs(output->offset()), std::abs(input.offset())));
}

std::string ValidateIntervalConstraint(const CpModelProto& model,
const ConstraintProto& ct) {
if (ct.enforcement_literal().size() > 1) {
Expand Down Expand Up @@ -705,7 +705,7 @@ std::string ValidateIntervalConstraint(const CpModelProto& model,
"variable are currently not supported.";
}
RETURN_IF_NOT_EMPTY(ValidateLinearExpression(model, arg.end()));
AppendToOverflowValidator(arg.end(), &for_overflow_validation);
AppendToOverflowValidator(arg.end(), &for_overflow_validation, -1);

if (PossibleIntegerOverflow(model, for_overflow_validation.vars(),
for_overflow_validation.coeffs(),
Expand Down Expand Up @@ -1484,6 +1484,7 @@ class ConstraintChecker {
bool CumulativeConstraintIsFeasible(const CpModelProto& model,
const ConstraintProto& ct) {
const int64_t capacity = LinearExpressionValue(ct.cumulative().capacity());
if (capacity < 0) return false;
const int num_intervals = ct.cumulative().intervals_size();
std::vector<std::pair<int64_t, int64_t>> events;
for (int i = 0; i < num_intervals; ++i) {
Expand Down
Loading

0 comments on commit eee2f10

Please sign in to comment.