Skip to content

Commit 8147434

Browse files
committed
[CP-SAT] more tweakings
1 parent c70d3aa commit 8147434

8 files changed

Lines changed: 54 additions & 25 deletions

File tree

ortools/sat/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3920,6 +3920,7 @@ cc_library(
39203920
"//ortools/base",
39213921
"//ortools/base:stl_util",
39223922
"//ortools/util:filelineiter",
3923+
"@abseil-cpp//absl/base:core_headers",
39233924
"@abseil-cpp//absl/container:flat_hash_map",
39243925
"@abseil-cpp//absl/container:flat_hash_set",
39253926
"@abseil-cpp//absl/log",

ortools/sat/cp_model_solver_test.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,7 @@ TEST(SolveCpModelTest, HintWithNegativeRef) {
956956
TEST(SolveCpModelTest, SolutionHintBasicTest) {
957957
SatParameters params;
958958
params.set_cp_model_presolve(false);
959+
params.set_num_workers(1);
959960
for (int loop = 0; loop < 50; ++loop) {
960961
CpModelProto model_proto;
961962

ortools/sat/integer_search.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ class ContinuousProber {
346346

347347
private:
348348
static const int kTestLimitPeriod = 20;
349-
static const int kLogPeriod = 1000;
349+
static const int kLogPeriod = 5000;
350350
static const int kSyncPeriod = 50;
351351

352352
SatSolver::Status ShaveLiteral(Literal literal);

ortools/sat/opb_reader.h

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <utility>
2222
#include <vector>
2323

24+
#include "absl/base/attributes.h"
2425
#include "absl/container/flat_hash_map.h"
2526
#include "absl/container/flat_hash_set.h"
2627
#include "absl/log/check.h"
@@ -56,7 +57,8 @@ class OpbReader {
5657

5758
// Loads the given opb filename into the given problem.
5859
// Returns true on success.
59-
bool LoadAndValidate(const std::string& filename, CpModelProto* model) {
60+
ABSL_MUST_USE_RESULT bool LoadAndValidate(const std::string& filename,
61+
CpModelProto* model) {
6062
model->Clear();
6163
model->set_name(ExtractProblemName(filename));
6264

@@ -72,17 +74,8 @@ class OpbReader {
7274
ProcessNewLine(line);
7375

7476
// Check if the model is supported. It is not supported if one constant
75-
// contains an integer that does not fit in int64_t.
76-
// In that case, we create a dummy model with a single variable that
77-
// overflows.
78-
if (!model_is_supported_) {
79-
model->Clear();
80-
IntegerVariableProto* var = model->add_variables();
81-
var->add_domain(std::numeric_limits<int64_t>::min());
82-
var->add_domain(std::numeric_limits<int64_t>::max());
83-
num_variables_ = 1;
84-
return true;
85-
}
77+
// contains an integer that does not fit in an int64_t.
78+
if (!model_is_supported_) return false;
8679
}
8780
if (num_lines == 0) {
8881
LOG(ERROR) << "File '" << filename << "' is empty or can't be read.";

ortools/sat/opb_reader_test.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ TEST(LoadAndValidateBooleanProblemTest, IntegerOverflow) {
107107
const std::string filename =
108108
file::JoinPath(::testing::TempDir(), "file2.opb");
109109
CHECK_OK(file::SetContents(filename, file, file::Defaults()));
110-
EXPECT_TRUE(reader.LoadAndValidate(filename, &problem));
110+
EXPECT_FALSE(reader.LoadAndValidate(filename, &problem));
111111
EXPECT_FALSE(reader.model_is_supported());
112112
}
113113

ortools/sat/primary_variables.cc

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,8 @@ VariableRelationships ComputeVariableRelationships(const CpModelProto& model) {
231231
}
232232
var_is_secondary.Set(v);
233233
result.secondary_variables.push_back(v);
234-
result.dependency_resolution_constraint_index.push_back(c);
234+
result.dependency_resolution_constraint.push_back(model.constraints(c));
235+
result.redundant_constraint_indices.push_back(c);
235236
break;
236237
}
237238

@@ -295,14 +296,17 @@ VariableRelationships ComputeVariableRelationships(const CpModelProto& model) {
295296
var_is_secondary.Set(single_deducible_var);
296297
update_constraints_after_var_is_decided(single_deducible_var);
297298
result.secondary_variables.push_back(single_deducible_var);
298-
result.dependency_resolution_constraint_index.push_back(c);
299+
result.dependency_resolution_constraint.push_back(model.constraints(c));
300+
result.redundant_constraint_indices.push_back(c);
299301
}
300302
}
301303

302304
for (int i = 0; i < result.secondary_variables.size(); ++i) {
303305
const int var = result.secondary_variables[i];
304-
const int c = result.dependency_resolution_constraint_index[i];
305-
const ConstraintData& data = constraint_data[c];
306+
ConstraintData data;
307+
const ConstraintProto& ct = result.dependency_resolution_constraint[i];
308+
GetRelationshipForConstraint(ct, &data.deducible_vars, &data.input_vars,
309+
&data.preferred_to_deduce);
306310
for (const int v : data.input_vars) {
307311
if (var_is_secondary.IsSet(v)) {
308312
result.variable_dependencies.push_back({var, v});
@@ -326,9 +330,8 @@ bool ComputeAllVariablesFromPrimaryVariables(
326330
}
327331
for (int i = 0; i < relationships.secondary_variables.size(); ++i) {
328332
const int var = relationships.secondary_variables[i];
329-
const int constraint_index =
330-
relationships.dependency_resolution_constraint_index[i];
331-
const ConstraintProto& ct = model.constraints(constraint_index);
333+
const ConstraintProto& ct =
334+
relationships.dependency_resolution_constraint[i];
332335
switch (ct.constraint_case()) {
333336
case ConstraintProto::kLinear: {
334337
const LinearConstraintProto& linear = ct.linear();

ortools/sat/primary_variables.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,20 @@ namespace sat {
4040
// of the secondary variables.
4141
struct VariableRelationships {
4242
std::vector<int> secondary_variables;
43-
std::vector<int> dependency_resolution_constraint_index;
43+
std::vector<ConstraintProto> dependency_resolution_constraint;
44+
4445
// A pair of(x, y) means that one needs to compute the value of y before
4546
// computing the value of x. This defines an implicit dependency DAG for
4647
// computing the secondary variables from the primary.
4748
std::vector<std::pair<int, int>> variable_dependencies;
49+
50+
// The list of model constraints that are redundant (ie., satisfied by
51+
// construction) when the secondary variables are computed from the primary
52+
// ones. In other words, a model has a solution for a set of primary
53+
// variables {x_i} if and only if all the variable bounds and non-redundant
54+
// constraints are satisfied after the secondary variables have been computed
55+
// from the primary ones.
56+
std::vector<int> redundant_constraint_indices;
4857
};
4958

5059
// Compute the variable relationships for a given model. Note that there are

ortools/sat/sat_runner.cc

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <cstdlib>
1616
#include <functional>
1717
#include <iostream>
18+
#include <limits>
1819
#include <string>
1920
#include <vector>
2021

@@ -177,10 +178,31 @@ bool LoadProblem(const std::string& filename, absl::string_view hint_file,
177178
absl::EndsWith(filename, ".wbo.bz2") ||
178179
absl::EndsWith(filename, ".wbo.gz")) {
179180
OpbReader reader;
180-
reader.LoadAndValidate(filename, cp_model);
181+
if (!reader.LoadAndValidate(filename, cp_model)) {
182+
if (!reader.model_is_supported()) { // Some constants are too large.
183+
if (absl::GetFlag(FLAGS_competition_mode)) {
184+
// We output the official UNSUPPORTED status.
185+
std::cout << "s UNSUPPORTED" << std::endl;
186+
return false; // Bypass the solve part.
187+
} else {
188+
// Create a dummy model with a single variable that overflows.
189+
// This way, the solver will return MODEL_INVALID instead of
190+
// crashing.
191+
IntegerVariableProto* var = cp_model->add_variables();
192+
var->add_domain(std::numeric_limits<int64_t>::min());
193+
var->add_domain(std::numeric_limits<int64_t>::max());
194+
return true; // Will still call solve() to get the status.
195+
}
196+
} else {
197+
return false; // Bypass the solve part.
198+
}
199+
}
200+
181201
if (absl::GetFlag(FLAGS_competition_mode)) {
182-
LogInPbCompetitionFormat(reader.num_variables(),
183-
cp_model->has_objective(), model, parameters);
202+
const int num_variables =
203+
reader.model_is_supported() ? reader.num_variables() : 1;
204+
LogInPbCompetitionFormat(num_variables, cp_model->has_objective(), model,
205+
parameters);
184206
}
185207
} else if (absl::EndsWith(filename, ".cnf") ||
186208
absl::EndsWith(filename, ".cnf.xz") ||

0 commit comments

Comments
 (0)