minor optims

This commit is contained in:
Laurent Perron
2025-04-10 11:40:38 +02:00
parent f2e2e497ed
commit edb9051c03
18 changed files with 3809 additions and 79 deletions

View File

@@ -194,6 +194,7 @@ int main(int argc, char** argv) {
std::string currentLine;
while (std::getline(std::cin, currentLine)) {
input.append(currentLine);
input.append("\n");
}
} else {
if (residual_flags.empty()) {

View File

@@ -134,8 +134,11 @@ std::vector<typename Graph::ArcIndex> BuildPrimMinimumSpanningTree(
int GetHeapIndex() const { return heap_index; }
bool operator<(const Entry& other) const { return value > other.value; }
NodeIndex node;
// In the typical case, `NodeIndex` is 4 bytes, so having fields in this
// order is optimal in terms of memory usage and cache locality across all
// values of `sizeof(ArcValueType)`.
ArcValueType value;
NodeIndex node;
int heap_index;
};
@@ -143,7 +146,9 @@ std::vector<typename Graph::ArcIndex> BuildPrimMinimumSpanningTree(
std::vector<Entry> entries;
std::vector<bool> touched_entry(graph.num_nodes(), false);
for (NodeIndex node : graph.AllNodes()) {
entries.push_back({node, std::numeric_limits<ArcValueType>::max(), -1});
entries.push_back({.value = std::numeric_limits<ArcValueType>::max(),
.node = node,
.heap_index = -1});
}
entries[0].value = 0;
pq.Add(&entries[0]);

View File

@@ -3509,11 +3509,13 @@ cc_library(
":synchronization",
":timetable",
":util",
"//ortools/base:stl_util",
"//ortools/util:bitset",
"//ortools/util:saturated_arithmetic",
"//ortools/util:strong_integers",
"//ortools/util:time_limit",
"@abseil-cpp//absl/container:flat_hash_set",
"@abseil-cpp//absl/container:inlined_vector",
"@abseil-cpp//absl/log",
"@abseil-cpp//absl/log:check",
"@abseil-cpp//absl/log:vlog_is_on",

View File

@@ -610,6 +610,9 @@ LinearExpr IntervalVar::EndExpr() const {
BoolVar IntervalVar::PresenceBoolVar() const {
DCHECK(builder_ != nullptr);
if (builder_ == nullptr) return BoolVar();
if (builder_->Proto().constraints(index_).enforcement_literal_size() == 0) {
return builder_->TrueVar();
}
return BoolVar(builder_->Proto().constraints(index_).enforcement_literal(0),
builder_);
}
@@ -712,12 +715,25 @@ BoolVar CpModelBuilder::FalseVar() {
IntervalVar CpModelBuilder::NewIntervalVar(const LinearExpr& start,
const LinearExpr& size,
const LinearExpr& end) {
return NewOptionalIntervalVar(start, size, end, TrueVar());
const int index = cp_model_.constraints_size();
ConstraintProto* const ct = cp_model_.add_constraints();
IntervalConstraintProto* const interval = ct->mutable_interval();
*interval->mutable_start() = LinearExprToProto(start);
*interval->mutable_size() = LinearExprToProto(size);
*interval->mutable_end() = LinearExprToProto(end);
return IntervalVar(index, this);
}
IntervalVar CpModelBuilder::NewFixedSizeIntervalVar(const LinearExpr& start,
int64_t size) {
return NewOptionalFixedSizeIntervalVar(start, size, TrueVar());
const int index = cp_model_.constraints_size();
ConstraintProto* const ct = cp_model_.add_constraints();
IntervalConstraintProto* const interval = ct->mutable_interval();
*interval->mutable_start() = LinearExprToProto(start);
interval->mutable_size()->set_offset(size);
*interval->mutable_end() = LinearExprToProto(start);
interval->mutable_end()->set_offset(interval->end().offset() + size);
return IntervalVar(index, this);
}
IntervalVar CpModelBuilder::NewOptionalIntervalVar(const LinearExpr& start,

View File

@@ -2407,7 +2407,8 @@ CpSolverResponse SolveCpModel(const CpModelProto& model_proto, Model* model) {
// Always add the timing information to a response. Note that it is important
// to add this after the log/dump postprocessor since we execute them in
// reverse order.
auto* shared_time_limit = model->GetOrCreate<ModelSharedTimeLimit>();
ModelSharedTimeLimit* shared_time_limit =
model->GetOrCreate<ModelSharedTimeLimit>();
shared_response_manager->AddResponsePostprocessor(
[&wall_timer, &user_timer,
&shared_time_limit](CpSolverResponse* response) {
@@ -2446,7 +2447,7 @@ CpSolverResponse SolveCpModel(const CpModelProto& model_proto, Model* model) {
// Register SIGINT handler if requested by the parameters.
if (params.catch_sigint_signal()) {
model->GetOrCreate<SigintHandler>()->Register(
[&shared_time_limit]() { shared_time_limit->Stop(); });
[shared_time_limit]() { shared_time_limit->Stop(); });
}
#endif // __PORTABLE_PLATFORM__

View File

@@ -1196,13 +1196,11 @@ TEST(CpModelTest, TestNoOverlap) {
const CpModelProto expected_model = ParseTestProto(R"pb(
variables { domain: 0 domain: 20 }
variables { domain: 0 domain: 20 }
variables { domain: 1 domain: 1 }
variables { domain: 0 domain: 20 }
variables { domain: 0 domain: 20 }
variables { domain: 0 domain: 20 }
variables { domain: 0 domain: 20 }
constraints {
enforcement_literal: 2
interval {
start { vars: 0 coeffs: 1 }
end { vars: 1 coeffs: 1 }
@@ -1210,23 +1208,20 @@ TEST(CpModelTest, TestNoOverlap) {
}
}
constraints {
enforcement_literal: 2
interval {
start { vars: 3 coeffs: 1 }
end { vars: 4 coeffs: 1 }
start { vars: 2 coeffs: 1 }
end { vars: 3 coeffs: 1 }
size { offset: 5 }
}
}
constraints {
enforcement_literal: 2
interval {
start { vars: 5 coeffs: 1 }
end { vars: 6 coeffs: 1 }
start { vars: 4 coeffs: 1 }
end { vars: 5 coeffs: 1 }
size { offset: 5 }
}
}
constraints { no_overlap { intervals: 0 intervals: 1 intervals: 2 } }
)pb");
constraints { no_overlap { intervals: 0 intervals: 1 intervals: 2 } })pb");
EXPECT_THAT(cp_model.Proto(), EqualsProto(expected_model));
}
@@ -1257,7 +1252,6 @@ TEST(CpModelTest, TestNoOverlap2D) {
variables { domain: 0 domain: 20 }
variables { domain: 0 domain: 20 }
variables { domain: 5 domain: 5 }
variables { domain: 1 domain: 1 }
variables { domain: 0 domain: 20 }
variables { domain: 0 domain: 20 }
variables { domain: 0 domain: 20 }
@@ -1265,7 +1259,6 @@ TEST(CpModelTest, TestNoOverlap2D) {
variables { domain: 0 domain: 20 }
variables { domain: 0 domain: 20 }
constraints {
enforcement_literal: 3
interval {
start { vars: 0 coeffs: 1 }
end { vars: 1 coeffs: 1 }
@@ -1273,26 +1266,23 @@ TEST(CpModelTest, TestNoOverlap2D) {
}
}
constraints {
enforcement_literal: 3
interval {
start { vars: 4 coeffs: 1 }
end { vars: 5 coeffs: 1 }
start { vars: 3 coeffs: 1 }
end { vars: 4 coeffs: 1 }
size { vars: 2 coeffs: 1 }
}
}
constraints {
enforcement_literal: 3
interval {
start { vars: 6 coeffs: 1 }
end { vars: 7 coeffs: 1 }
start { vars: 5 coeffs: 1 }
end { vars: 6 coeffs: 1 }
size { vars: 2 coeffs: 1 }
}
}
constraints {
enforcement_literal: 3
interval {
start { vars: 8 coeffs: 1 }
end { vars: 9 coeffs: 1 }
start { vars: 7 coeffs: 1 }
end { vars: 8 coeffs: 1 }
size { vars: 2 coeffs: 1 }
}
}
@@ -1325,13 +1315,11 @@ TEST(CpModelTest, TestCumulative) {
const CpModelProto expected_model = ParseTestProto(R"pb(
variables { domain: 0 domain: 20 }
variables { domain: 0 domain: 20 }
variables { domain: 1 domain: 1 }
variables { domain: 0 domain: 20 }
variables { domain: 0 domain: 20 }
variables { domain: 5 domain: 10 }
variables { domain: 5 domain: 10 }
constraints {
enforcement_literal: 2
interval {
start { vars: 0 coeffs: 1 }
end { vars: 1 coeffs: 1 }
@@ -1339,23 +1327,21 @@ TEST(CpModelTest, TestCumulative) {
}
}
constraints {
enforcement_literal: 2
interval {
start { vars: 3 coeffs: 1 }
end { vars: 4 coeffs: 1 }
start { vars: 2 coeffs: 1 }
end { vars: 3 coeffs: 1 }
size { offset: 5 }
}
}
constraints {
cumulative {
capacity: { vars: 5 coeffs: 1 }
capacity { vars: 4 coeffs: 1 }
intervals: 0
intervals: 1
demands { vars: 6 coeffs: 1 }
demands { vars: 5 coeffs: 1 }
demands { offset: 8 }
}
}
)pb");
})pb");
EXPECT_THAT(cp_model.Proto(), EqualsProto(expected_model));
}

View File

@@ -2063,9 +2063,10 @@ ImpliedBoundsProcessor::ComputeBestImpliedBound(
// and slack in [0, ub - lb].
const IntegerValue diff = entry.lower_bound - lb;
CHECK_GE(diff, 0);
const double bool_lp_value = entry.is_positive
? lp_values[entry.literal_view]
: 1.0 - lp_values[entry.literal_view];
const double bool_lp_value =
VariableIsPositive(entry.literal_view)
? lp_values[entry.literal_view]
: 1.0 - lp_values[PositiveVariable(entry.literal_view)];
const double slack_lp_value =
lp_values[var] - ToDouble(lb) - bool_lp_value * ToDouble(diff);
@@ -2075,14 +2076,14 @@ ImpliedBoundsProcessor::ComputeBestImpliedBound(
LinearConstraint ib_cut;
ib_cut.lb = kMinIntegerValue;
std::vector<std::pair<IntegerVariable, IntegerValue>> terms;
if (entry.is_positive) {
if (VariableIsPositive(entry.literal_view)) {
// X >= Indicator * (bound - lb) + lb
terms.push_back({entry.literal_view, diff});
terms.push_back({var, IntegerValue(-1)});
ib_cut.ub = -lb;
} else {
// X >= -Indicator * (bound - lb) + bound
terms.push_back({entry.literal_view, -diff});
terms.push_back({PositiveVariable(entry.literal_view), -diff});
terms.push_back({var, IntegerValue(-1)});
ib_cut.ub = -entry.lower_bound;
}
@@ -2100,7 +2101,6 @@ ImpliedBoundsProcessor::ComputeBestImpliedBound(
result.var_lp_value = lp_values[var];
result.bool_lp_value = bool_lp_value;
result.implied_bound = entry.lower_bound;
result.is_positive = entry.is_positive;
result.bool_var = entry.literal_view;
}
}
@@ -2153,11 +2153,11 @@ bool ImpliedBoundsProcessor::DecomposeWithImpliedLowerBound(
// We have X/-X = info.diff * Boolean + slack.
bool_term.coeff = term.coeff * bound_diff;
bool_term.expr_vars[0] = info.bool_var;
bool_term.expr_vars[0] = PositiveVariable(info.bool_var);
bool_term.expr_coeffs[1] = 0;
bool_term.bound_diff = IntegerValue(1);
bool_term.lp_value = info.bool_lp_value;
if (info.is_positive) {
if (VariableIsPositive(info.bool_var)) {
bool_term.expr_coeffs[0] = IntegerValue(1);
bool_term.expr_offset = IntegerValue(0);
} else {

View File

@@ -263,8 +263,10 @@ class ImpliedBoundsProcessor {
struct BestImpliedBoundInfo {
double var_lp_value = 0.0;
double bool_lp_value = 0.0;
bool is_positive;
IntegerValue implied_bound;
// When VariableIsPositive(bool_var) then it is when this is one that the
// bound is implied. Otherwise it is when this is zero.
IntegerVariable bool_var = kNoIntegerVariable;
double SlackLpValue(IntegerValue lb) const {

View File

@@ -26,11 +26,13 @@
#include <vector>
#include "absl/container/flat_hash_set.h"
#include "absl/container/inlined_vector.h"
#include "absl/log/check.h"
#include "absl/log/log.h"
#include "absl/log/vlog_is_on.h"
#include "absl/numeric/bits.h"
#include "absl/types/span.h"
#include "ortools/base/stl_util.h"
#include "ortools/sat/2d_mandatory_overlap_propagator.h"
#include "ortools/sat/2d_orthogonal_packing.h"
#include "ortools/sat/2d_try_edge_propagator.h"
@@ -287,11 +289,11 @@ void AddNonOverlappingRectangles(const std::vector<IntervalVariable>& x,
};
for (int i = 0; i < num_boxes; ++i) {
if (repository->IsOptional(x[i])) continue;
if (repository->IsOptional(y[i])) continue;
if (repository->IsAbsent(x[i])) continue;
if (repository->IsAbsent(y[i])) continue;
for (int j = i + 1; j < num_boxes; ++j) {
if (repository->IsOptional(x[j])) continue;
if (repository->IsOptional(y[j])) continue;
if (repository->IsAbsent(x[j])) continue;
if (repository->IsAbsent(y[j])) continue;
// At most one of these two x options is true.
const Literal x_ij = f(repository->End(x[i]), repository->Start(x[j]));
@@ -314,7 +316,21 @@ void AddNonOverlappingRectangles(const std::vector<IntervalVariable>& x,
}
// At least one of the 4 options is true.
if (!sat_solver->AddProblemClause({x_ij, x_ji, y_ij, y_ji})) {
std::vector<Literal> clause = {x_ij, x_ji, y_ij, y_ji};
if (repository->IsOptional(x[i])) {
clause.push_back(repository->PresenceLiteral(x[i]).Negated());
}
if (repository->IsOptional(y[i])) {
clause.push_back(repository->PresenceLiteral(y[i]).Negated());
}
if (repository->IsOptional(x[j])) {
clause.push_back(repository->PresenceLiteral(x[j]).Negated());
}
if (repository->IsOptional(y[j])) {
clause.push_back(repository->PresenceLiteral(y[j]).Negated());
}
gtl::STLSortAndRemoveDuplicates(&clause);
if (!sat_solver->AddProblemClause(clause)) {
return;
}
}

View File

@@ -20,8 +20,20 @@ variables {
constraints {
all_diff {
exprs {
vars: [0, 1, 2, 3]
coeffs: [1, 1, 1, 1]
vars: [0]
coeffs: [1]
}
exprs {
vars: [1]
coeffs: [1]
}
exprs {
vars: [2]
coeffs: [1]
}
exprs {
vars: [3]
coeffs: [1]
}
}
}

View File

@@ -0,0 +1,954 @@
# proto-file: ortools/sat/cp_model.proto
# proto-message: operations_research.sat.CpModelProto
variables { domain: [0, 41] }
variables { domain: [0, 53] }
variables { domain: [40, 40] }
variables { domain: [41, 41] }
variables { domain: [17, 17] }
variables { domain: [42, 42] }
variables { domain: [14, 14] }
variables { domain: [28, 28] }
variables { domain: [0, 47] }
variables { domain: [0, 51] }
variables { domain: [0, 51] }
variables { domain: [0, 55] }
variables { domain: [0, 51] }
variables { domain: [0, 55] }
variables { domain: [0, 41] }
variables { domain: [0, 53] }
variables { domain: [0, 51] }
variables { domain: [0, 47] }
variables { domain: [2, 2] }
variables { domain: [34, 34] }
variables { domain: [0, 43] }
variables { domain: [0, 55] }
variables { domain: [0, 0] }
variables { domain: [55, 55] }
variables { domain: [0, 0] }
variables { domain: [12, 12] }
variables { domain: [12, 12] }
variables { domain: [35, 35] }
variables { domain: [10, 10] }
variables { domain: [17, 17] }
variables { domain: [4, 4] }
variables { domain: [35, 35] }
variables { domain: [24, 24] }
variables { domain: [41, 41] }
variables { domain: [0, 0] }
variables { domain: [20, 20] }
variables { domain: [0, 43] }
variables { domain: [0, 49] }
variables { domain: [0, 57] }
variables { domain: [0, 55] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [6, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [3, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [1, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
variables { domain: [0, 23] }
constraints {
interval {
start { vars: [0] coeffs: [1] }
end { vars: [0] coeffs: [1] offset: 20 }
size { offset: 20 }
}
}
constraints {
interval {
start { vars: [1] coeffs: [1] }
end { vars: [1] coeffs: [1] offset: 4 }
size { offset: 4 }
}
}
constraints {
interval {
start { offset: 40 }
end { offset: 60 }
size { offset: 20 }
}
}
constraints {
interval {
start { offset: 41 }
end { offset: 55 }
size { offset: 14 }
}
}
constraints {
interval {
start { offset: 17 }
end { offset: 21 }
size { offset: 4 }
}
}
constraints {
interval {
start { offset: 42 }
end { offset: 52 }
size { offset: 10 }
}
}
constraints {
interval {
start { offset: 14 }
end { offset: 20 }
size { offset: 6 }
}
}
constraints {
interval {
start { offset: 28 }
end { offset: 32 }
size { offset: 4 }
}
}
constraints {
interval {
start { vars: [8] coeffs: [1] }
end { vars: [8] coeffs: [1] offset: 14 }
size { offset: 14 }
}
}
constraints {
interval {
start { vars: [9] coeffs: [1] }
end { vars: [9] coeffs: [1] offset: 6 }
size { offset: 6 }
}
}
constraints {
interval {
start { vars: [10] coeffs: [1] }
end { vars: [10] coeffs: [1] offset: 10 }
size { offset: 10 }
}
}
constraints {
interval {
start { vars: [11] coeffs: [1] }
end { vars: [11] coeffs: [1] offset: 2 }
size { offset: 2 }
}
}
constraints {
interval {
start { vars: [12] coeffs: [1] }
end { vars: [12] coeffs: [1] offset: 10 }
size { offset: 10 }
}
}
constraints {
interval {
start { vars: [13] coeffs: [1] }
end { vars: [13] coeffs: [1] offset: 2 }
size { offset: 2 }
}
}
constraints {
interval {
start { vars: [14] coeffs: [1] }
end { vars: [14] coeffs: [1] offset: 20 }
size { offset: 20 }
}
}
constraints {
interval {
start { vars: [15] coeffs: [1] }
end { vars: [15] coeffs: [1] offset: 4 }
size { offset: 4 }
}
}
constraints {
interval {
start { vars: [16] coeffs: [1] }
end { vars: [16] coeffs: [1] offset: 10 }
size { offset: 10 }
}
}
constraints {
interval {
start { vars: [17] coeffs: [1] }
end { vars: [17] coeffs: [1] offset: 10 }
size { offset: 10 }
}
}
constraints {
interval {
start { offset: 2 }
end { offset: 4 }
size { offset: 2 }
}
}
constraints {
interval {
start { offset: 34 }
end { offset: 40 }
size { offset: 6 }
}
}
constraints {
interval {
start { vars: [20] coeffs: [1] }
end { vars: [20] coeffs: [1] offset: 18 }
size { offset: 18 }
}
}
constraints {
interval {
start { vars: [21] coeffs: [1] }
end { vars: [21] coeffs: [1] offset: 2 }
size { offset: 2 }
}
}
constraints {
interval {
start { }
end { offset: 10 }
size { offset: 10 }
}
}
constraints {
interval {
start { offset: 55 }
end { offset: 75 }
size { offset: 20 }
}
}
constraints {
interval {
start { }
end { offset: 8 }
size { offset: 8 }
}
}
constraints {
interval {
start { offset: 12 }
end { offset: 14 }
size { offset: 2 }
}
}
constraints {
interval {
start { offset: 12 }
end { offset: 14 }
size { offset: 2 }
}
}
constraints {
interval {
start { offset: 35 }
end { offset: 51 }
size { offset: 16 }
}
}
constraints {
interval {
start { offset: 10 }
end { offset: 14 }
size { offset: 4 }
}
}
constraints {
interval {
start { offset: 17 }
end { offset: 35 }
size { offset: 18 }
}
}
constraints {
interval {
start { offset: 4 }
end { offset: 12 }
size { offset: 8 }
}
}
constraints {
interval {
start { offset: 35 }
end { offset: 55 }
size { offset: 20 }
}
}
constraints {
interval {
start { offset: 24 }
end { offset: 40 }
size { offset: 16 }
}
}
constraints {
interval {
start { offset: 41 }
end { offset: 61 }
size { offset: 20 }
}
}
constraints {
interval {
start { }
end { offset: 10 }
size { offset: 10 }
}
}
constraints {
interval {
start { offset: 20 }
end { offset: 34 }
size { offset: 14 }
}
}
constraints {
interval {
start { vars: [36] coeffs: [1] }
end { vars: [36] coeffs: [1] offset: 18 }
size { offset: 18 }
}
}
constraints {
interval {
start { vars: [37] coeffs: [1] }
end { vars: [37] coeffs: [1] offset: 8 }
size { offset: 8 }
}
}
constraints {
interval {
start { vars: [38] coeffs: [1] }
end { vars: [38] coeffs: [1] offset: 4 }
size { offset: 4 }
}
}
constraints {
interval {
start { vars: [39] coeffs: [1] }
end { vars: [39] coeffs: [1] offset: 2 }
size { offset: 2 }
}
}
constraints {
linear {
vars: [8, 10, 40]
coeffs: [1, -1, -1]
domain: [-74, 12]
}
}
constraints {
linear {
vars: [8, 10, 40]
coeffs: [1, -1, 1]
domain: [-12, 70]
}
}
constraints {
linear {
vars: [12, 42]
coeffs: [1, -1]
domain: [-23, 13]
}
}
constraints {
linear {
vars: [0, 43]
coeffs: [1, -1]
domain: [-23, 22]
}
}
constraints {
linear {
vars: [10, 20, 45]
coeffs: [1, -1, -1]
domain: [-66, 14]
}
}
constraints {
linear {
vars: [10, 20, 45]
coeffs: [1, -1, 1]
domain: [-14, 74]
}
}
constraints {
linear {
vars: [10, 12, 46]
coeffs: [1, -1, -1]
domain: [-74, 10]
}
}
constraints {
linear {
vars: [10, 12, 46]
coeffs: [1, -1, 1]
domain: [-10, 74]
}
}
constraints {
linear {
vars: [36, 48]
coeffs: [-1, -1]
domain: [-66, -21]
}
}
constraints {
linear {
vars: [8, 16, 49]
coeffs: [1, -1, -1]
domain: [-74, 12]
}
}
constraints {
linear {
vars: [8, 16, 49]
coeffs: [1, -1, 1]
domain: [-12, 70]
}
}
constraints {
linear {
vars: [38, 50]
coeffs: [-1, -1]
domain: [-80, -9]
}
}
constraints {
linear {
vars: [38, 50]
coeffs: [-1, 1]
domain: [-19, 23]
}
}
constraints {
linear {
vars: [16, 52]
coeffs: [1, -1]
domain: [-23, 37]
}
}
constraints {
linear {
vars: [16, 52]
coeffs: [1, 1]
domain: [11, 74]
}
}
constraints {
linear {
vars: [36, 53]
coeffs: [-1, -1]
domain: [-66, -2]
}
}
constraints {
linear {
vars: [36, 53]
coeffs: [-1, 1]
domain: [-26, 23]
}
}
constraints {
linear {
vars: [8, 14, 56]
coeffs: [1, -1, -1]
domain: [-64, 17]
}
}
constraints {
linear {
vars: [8, 14, 56]
coeffs: [1, -1, 1]
domain: [-17, 70]
}
}
constraints {
linear {
vars: [8, 57]
coeffs: [-1, -1]
domain: [-70, -4]
}
}
constraints {
linear {
vars: [8, 57]
coeffs: [-1, 1]
domain: [-24, 23]
}
}
constraints {
linear {
vars: [12, 58]
coeffs: [1, -1]
domain: [-23, 17]
}
}
constraints {
linear {
vars: [12, 58]
coeffs: [1, 1]
domain: [3, 74]
}
}
constraints {
linear {
vars: [36, 59]
coeffs: [-1, -1]
domain: [-66, -6]
}
}
constraints {
linear {
vars: [36, 59]
coeffs: [-1, 1]
domain: [-28, 23]
}
}
constraints {
linear {
vars: [12, 14, 61]
coeffs: [1, -1, -1]
domain: [-64, 15]
}
}
constraints {
linear {
vars: [12, 14, 61]
coeffs: [1, -1, 1]
domain: [-15, 74]
}
}
constraints {
linear {
vars: [12, 62]
coeffs: [1, -1]
domain: [-23, 10]
}
}
constraints {
linear {
vars: [14, 63]
coeffs: [1, -1]
domain: [-23, 23]
}
}
constraints {
linear {
vars: [14, 63]
coeffs: [1, 1]
domain: [1, 64]
}
}
constraints {
linear {
vars: [0, 65]
coeffs: [1, -1]
domain: [-23, 15]
}
}
constraints {
linear {
vars: [14, 38, 66]
coeffs: [1, -1, -1]
domain: [-80, 12]
}
}
constraints {
linear {
vars: [14, 38, 66]
coeffs: [1, -1, 1]
domain: [-12, 64]
}
}
constraints {
linear {
vars: [38, 67]
coeffs: [-1, -1]
domain: [-80, -14]
}
}
constraints {
linear {
vars: [38, 67]
coeffs: [-1, 1]
domain: [-34, 23]
}
}
constraints {
linear {
vars: [10, 16, 68]
coeffs: [1, -1, -1]
domain: [-74, 10]
}
}
constraints {
linear {
vars: [10, 16, 68]
coeffs: [1, -1, 1]
domain: [-10, 74]
}
}
constraints {
linear {
vars: [36, 69]
coeffs: [-1, -1]
domain: [-66, -2]
}
}
constraints {
linear {
vars: [36, 69]
coeffs: [-1, 1]
domain: [-22, 23]
}
}
constraints {
linear {
vars: [9, 11, 70]
coeffs: [1, -1, -1]
domain: [-78, 4]
}
}
constraints {
linear {
vars: [9, 11, 70]
coeffs: [1, -1, 1]
domain: [-4, 74]
}
}
constraints {
linear {
vars: [13, 72]
coeffs: [1, -1]
domain: [-23, 46]
}
}
constraints {
linear {
vars: [13, 72]
coeffs: [1, 1]
domain: [24, 78]
}
}
constraints {
linear {
vars: [1, 73]
coeffs: [1, -1]
domain: [-23, 28]
}
}
constraints {
linear {
vars: [1, 73]
coeffs: [1, 1]
domain: [6, 76]
}
}
constraints {
linear {
vars: [11, 21, 75]
coeffs: [1, -1, -1]
domain: [-78, 2]
}
}
constraints {
linear {
vars: [11, 21, 75]
coeffs: [1, -1, 1]
domain: [-2, 78]
}
}
constraints {
linear {
vars: [11, 13, 76]
coeffs: [1, -1, -1]
domain: [-78, 2]
}
}
constraints {
linear {
vars: [11, 13, 76]
coeffs: [1, -1, 1]
domain: [-2, 78]
}
}
constraints {
linear {
vars: [37, 78]
coeffs: [-1, -1]
domain: [-72, -30]
}
}
constraints {
linear {
vars: [9, 17, 79]
coeffs: [1, -1, -1]
domain: [-70, 8]
}
}
constraints {
linear {
vars: [9, 17, 79]
coeffs: [1, -1, 1]
domain: [-8, 74]
}
}
constraints {
linear {
vars: [39, 80]
coeffs: [-1, -1]
domain: [-78, -25]
}
}
constraints {
linear {
vars: [39, 80]
coeffs: [-1, 1]
domain: [-31, 23]
}
}
constraints {
linear {
vars: [17, 82]
coeffs: [1, 1]
domain: [26, 70]
}
}
constraints {
linear {
vars: [37, 83]
coeffs: [-1, -1]
domain: [-72, -22]
}
}
constraints {
linear {
vars: [37, 83]
coeffs: [-1, 1]
domain: [-34, 23]
}
}
constraints {
linear {
vars: [9, 15, 86]
coeffs: [1, -1, -1]
domain: [-76, 5]
}
}
constraints {
linear {
vars: [9, 15, 86]
coeffs: [1, -1, 1]
domain: [-5, 74]
}
}
constraints {
linear {
vars: [9, 87]
coeffs: [-1, -1]
domain: [-74, -23]
}
}
constraints {
linear {
vars: [9, 87]
coeffs: [-1, 1]
domain: [-33, 23]
}
}
constraints {
linear {
vars: [13, 88]
coeffs: [1, -1]
domain: [-23, 27]
}
}
constraints {
linear {
vars: [13, 88]
coeffs: [1, 1]
domain: [7, 78]
}
}
constraints {
linear {
vars: [37, 89]
coeffs: [-1, -1]
domain: [-72, -33]
}
}
constraints {
linear {
vars: [13, 15, 91]
coeffs: [1, -1, -1]
domain: [-76, 3]
}
}
constraints {
linear {
vars: [13, 15, 91]
coeffs: [1, -1, 1]
domain: [-3, 78]
}
}
constraints {
linear {
vars: [13, 92]
coeffs: [1, -1]
domain: [-23, 28]
}
}
constraints {
linear {
vars: [13, 92]
coeffs: [1, 1]
domain: [12, 78]
}
}
constraints {
linear {
vars: [15, 93]
coeffs: [1, -1]
domain: [-23, 45]
}
}
constraints {
linear {
vars: [15, 93]
coeffs: [1, 1]
domain: [25, 76]
}
}
constraints {
linear {
vars: [1, 95]
coeffs: [1, -1]
domain: [-23, 29]
}
}
constraints {
linear {
vars: [1, 95]
coeffs: [1, 1]
domain: [11, 76]
}
}
constraints {
linear {
vars: [15, 39, 96]
coeffs: [1, -1, -1]
domain: [-78, 3]
}
}
constraints {
linear {
vars: [15, 39, 96]
coeffs: [1, -1, 1]
domain: [-3, 76]
}
}
constraints {
linear {
vars: [39, 97]
coeffs: [-1, -1]
domain: [-78, -30]
}
}
constraints {
linear {
vars: [39, 97]
coeffs: [-1, 1]
domain: [-52, 23]
}
}
constraints {
linear {
vars: [11, 17, 98]
coeffs: [1, -1, -1]
domain: [-70, 6]
}
}
constraints {
linear {
vars: [11, 17, 98]
coeffs: [1, -1, 1]
domain: [-6, 78]
}
}
constraints {
linear {
vars: [37, 99]
coeffs: [-1, -1]
domain: [-72, -23]
}
}
constraints {
linear {
vars: [37, 99]
coeffs: [-1, 1]
domain: [-47, 23]
}
}
constraints {
no_overlap_2d {
x_intervals: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38]
y_intervals: [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39]
}
}
objective {
vars: [40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
coeffs: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
domain: [0, 24]
}

File diff suppressed because it is too large Load Diff

View File

@@ -158,8 +158,8 @@ bool ImpliedBounds::Add(Literal literal, IntegerLiteral integer_literal) {
}
++num_enqueued_in_var_to_bounds_;
has_implied_bounds_.Set(var);
var_to_bounds_[var].push_back({integer_encoder_->GetLiteralView(literal),
integer_literal.bound, true});
var_to_bounds_[var].emplace_back(integer_encoder_->GetLiteralView(literal),
integer_literal.bound);
} else if (integer_encoder_->GetLiteralView(literal.Negated()) !=
kNoIntegerVariable) {
if (var_to_bounds_.size() <= var) {
@@ -168,9 +168,9 @@ bool ImpliedBounds::Add(Literal literal, IntegerLiteral integer_literal) {
}
++num_enqueued_in_var_to_bounds_;
has_implied_bounds_.Set(var);
var_to_bounds_[var].push_back(
{integer_encoder_->GetLiteralView(literal.Negated()),
integer_literal.bound, false});
var_to_bounds_[var].emplace_back(
NegationOf(integer_encoder_->GetLiteralView(literal.Negated())),
integer_literal.bound);
}
return true;
}

View File

@@ -49,22 +49,21 @@ namespace sat {
// have BoolVar => X >= bound, we can always lower bound the variable X by
// (bound - X_lb) * BoolVar + X_lb, and that can lead to stronger cuts.
struct ImpliedBoundEntry {
// An integer variable in [0, 1]. When at 1, then the IntegerVariable
// PositiveVariable(literal_view) is an integer variable in [0, 1].
// If VariableIsPositive(literal_view), when at 1, then the IntegerVariable
// corresponding to this entry must be greater or equal to the given lower
// bound.
//
// If !VariableIsPositive(literal_view) then it is when
// PositiveVariable(literal_view) is zero that the lower bound is valid.
IntegerVariable literal_view = kNoIntegerVariable;
IntegerValue lower_bound = IntegerValue(0);
// If false, it is when the literal_view is zero that the lower bound is
// valid.
bool is_positive = true;
// These constructors are needed for OR-Tools.
ImpliedBoundEntry(IntegerVariable lit, IntegerValue lb, bool positive)
: literal_view(lit), lower_bound(lb), is_positive(positive) {}
ImpliedBoundEntry(IntegerVariable lit, IntegerValue lb)
: literal_view(lit), lower_bound(lb) {}
ImpliedBoundEntry()
: literal_view(kNoIntegerVariable), lower_bound(0), is_positive(true) {}
ImpliedBoundEntry() : literal_view(kNoIntegerVariable), lower_bound(0) {}
};
// Maintains all the implications of the form Literal => IntegerLiteral. We

View File

@@ -145,7 +145,6 @@ TEST(ImpliedBoundsTest, ReadBoundsFromTrail) {
EXPECT_EQ(result.size(), 1);
EXPECT_EQ(result[0].literal_view, view);
EXPECT_EQ(result[0].lower_bound, IntegerValue(9));
EXPECT_TRUE(result[0].is_positive);
}
TEST(ImpliedBoundsTest, DetectEqualityFromMin) {

View File

@@ -454,14 +454,6 @@ void IntegerEncoder::AssociateToIntegerEqualValue(Literal literal,
literal_view_[literal] = var;
}
}
if (value == -1 && domain.Min() >= -1 && domain.Max() <= 0) {
if (literal.Index() >= literal_view_.size()) {
literal_view_.resize(literal.Index().value() + 1, kNoIntegerVariable);
literal_view_[literal] = NegationOf(var);
} else if (literal_view_[literal] == kNoIntegerVariable) {
literal_view_[literal] = NegationOf(var);
}
}
// We use the "do not insert if present" behavior of .insert() to do just one
// lookup.

View File

@@ -240,13 +240,17 @@ class IntegerEncoder {
return temp_associated_vars_;
}
// If it exists, returns a [0,1] integer variable which is equal to 1 iff the
// If it exists, returns a [0, 1] integer variable which is equal to 1 iff the
// given literal is true. Returns kNoIntegerVariable if such variable does not
// exist. Note that one can create one by creating a new IntegerVariable and
// calling AssociateToIntegerEqualValue().
//
// Note that this will only return "positive" IntegerVariable.
IntegerVariable GetLiteralView(Literal lit) const {
if (lit.Index() >= literal_view_.size()) return kNoIntegerVariable;
return literal_view_[lit];
const IntegerVariable result = literal_view_[lit];
DCHECK(result == kNoIntegerVariable || VariableIsPositive(result));
return result;
}
// If this is true, then a literal can be linearized with an affine expression
@@ -343,8 +347,8 @@ class IntegerEncoder {
// Used by GetAllAssociatedVariables().
mutable std::vector<IntegerVariable> temp_associated_vars_;
// Store for a given LiteralIndex its IntegerVariable view or kNoLiteralIndex
// if there is none.
// Store for a given LiteralIndex its IntegerVariable view or kNoVariableIndex
// if there is none. Note that only positive IntegerVariable will appear here.
util_intops::StrongVector<LiteralIndex, IntegerVariable> literal_view_;
// Mapping (variable == value) -> associated literal. Note that even if

View File

@@ -14,6 +14,7 @@
#include "ortools/util/sigint.h"
#include <csignal>
#include <cstdlib>
#include <functional>
#include "ortools/base/logging.h"