Skip to content

Commit 9ae9d2e

Browse files
committed
constraint_solver: update from google3
1 parent 17632b7 commit 9ae9d2e

File tree

11 files changed

+833
-714
lines changed

11 files changed

+833
-714
lines changed

ortools/constraint_solver/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,8 @@ cc_library(
177177
"interval.h",
178178
"local_search.h",
179179
"model_cache.h",
180+
"pack.h",
181+
"range_cst.h",
180182
"sched_expr.h",
181183
"search.h",
182184
"sequence_var.h",

ortools/constraint_solver/constraint_solver.cc

Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757
#include "ortools/constraint_solver/interval.h"
5858
#include "ortools/constraint_solver/local_search.h"
5959
#include "ortools/constraint_solver/model_cache.h"
60+
#include "ortools/constraint_solver/pack.h"
61+
#include "ortools/constraint_solver/range_cst.h"
6062
#include "ortools/constraint_solver/sequence_var.h"
6163
#include "ortools/constraint_solver/table.h"
6264
#include "ortools/constraint_solver/timetabling.h"
@@ -3875,6 +3877,10 @@ Constraint* Solver::MakeNonOverlappingNonStrictBoxesConstraint(
38753877
return RevAlloc(new Diffn(this, x_vars, y_vars, dx, dy, false));
38763878
}
38773879

3880+
Pack* Solver::MakePack(const std::vector<IntVar*>& vars, int number_of_bins) {
3881+
return RevAlloc(new Pack(this, vars, number_of_bins));
3882+
}
3883+
38783884
namespace {
38793885
std::string StringifyEvaluatorBare(const Solver::Int64ToIntVar& evaluator,
38803886
int64_t range_start, int64_t range_end) {
@@ -6906,4 +6912,290 @@ Assignment* Solver::MakeAssignment(const Assignment* const a) {
69066912
return RevAlloc(new Assignment(a));
69076913
}
69086914

6915+
Constraint* Solver::MakeEquality(IntExpr* l, IntExpr* r) {
6916+
CHECK(l != nullptr) << "left expression nullptr, maybe a bad cast";
6917+
CHECK(r != nullptr) << "left expression nullptr, maybe a bad cast";
6918+
CHECK_EQ(this, l->solver());
6919+
CHECK_EQ(this, r->solver());
6920+
if (l->Bound()) {
6921+
return MakeEquality(r, l->Min());
6922+
} else if (r->Bound()) {
6923+
return MakeEquality(l, r->Min());
6924+
} else {
6925+
return RevAlloc(new RangeEquality(this, l, r));
6926+
}
6927+
}
6928+
6929+
Constraint* Solver::MakeLessOrEqual(IntExpr* l, IntExpr* r) {
6930+
CHECK(l != nullptr) << "left expression nullptr, maybe a bad cast";
6931+
CHECK(r != nullptr) << "left expression nullptr, maybe a bad cast";
6932+
CHECK_EQ(this, l->solver());
6933+
CHECK_EQ(this, r->solver());
6934+
if (l == r) {
6935+
return MakeTrueConstraint();
6936+
} else if (l->Bound()) {
6937+
return MakeGreaterOrEqual(r, l->Min());
6938+
} else if (r->Bound()) {
6939+
return MakeLessOrEqual(l, r->Min());
6940+
} else {
6941+
return RevAlloc(new RangeLessOrEqual(this, l, r));
6942+
}
6943+
}
6944+
6945+
Constraint* Solver::MakeGreaterOrEqual(IntExpr* l, IntExpr* r) {
6946+
return MakeLessOrEqual(r, l);
6947+
}
6948+
6949+
Constraint* Solver::MakeLess(IntExpr* l, IntExpr* r) {
6950+
CHECK(l != nullptr) << "left expression nullptr, maybe a bad cast";
6951+
CHECK(r != nullptr) << "left expression nullptr, maybe a bad cast";
6952+
CHECK_EQ(this, l->solver());
6953+
CHECK_EQ(this, r->solver());
6954+
if (l->Bound()) {
6955+
return MakeGreater(r, l->Min());
6956+
} else if (r->Bound()) {
6957+
return MakeLess(l, r->Min());
6958+
} else {
6959+
return RevAlloc(new RangeLess(this, l, r));
6960+
}
6961+
}
6962+
6963+
Constraint* Solver::MakeGreater(IntExpr* l, IntExpr* r) {
6964+
return MakeLess(r, l);
6965+
}
6966+
6967+
Constraint* Solver::MakeNonEquality(IntExpr* l, IntExpr* r) {
6968+
CHECK(l != nullptr) << "left expression nullptr, maybe a bad cast";
6969+
CHECK(r != nullptr) << "left expression nullptr, maybe a bad cast";
6970+
CHECK_EQ(this, l->solver());
6971+
CHECK_EQ(this, r->solver());
6972+
if (l->Bound()) {
6973+
return MakeNonEquality(r, l->Min());
6974+
} else if (r->Bound()) {
6975+
return MakeNonEquality(l, r->Min());
6976+
}
6977+
return RevAlloc(new DiffVar(this, l->Var(), r->Var()));
6978+
}
6979+
6980+
IntVar* Solver::MakeIsEqualVar(IntExpr* v1, IntExpr* v2) {
6981+
CHECK_EQ(this, v1->solver());
6982+
CHECK_EQ(this, v2->solver());
6983+
if (v1->Bound()) {
6984+
return MakeIsEqualCstVar(v2, v1->Min());
6985+
} else if (v2->Bound()) {
6986+
return MakeIsEqualCstVar(v1, v2->Min());
6987+
}
6988+
IntExpr* cache = model_cache_->FindExprExprExpression(
6989+
v1, v2, ModelCache::EXPR_EXPR_IS_EQUAL);
6990+
if (cache == nullptr) {
6991+
cache = model_cache_->FindExprExprExpression(
6992+
v2, v1, ModelCache::EXPR_EXPR_IS_EQUAL);
6993+
}
6994+
if (cache != nullptr) {
6995+
return cache->Var();
6996+
} else {
6997+
IntVar* boolvar = nullptr;
6998+
IntExpr* reverse_cache = model_cache_->FindExprExprExpression(
6999+
v1, v2, ModelCache::EXPR_EXPR_IS_NOT_EQUAL);
7000+
if (reverse_cache == nullptr) {
7001+
reverse_cache = model_cache_->FindExprExprExpression(
7002+
v2, v1, ModelCache::EXPR_EXPR_IS_NOT_EQUAL);
7003+
}
7004+
if (reverse_cache != nullptr) {
7005+
boolvar = MakeDifference(1, reverse_cache)->Var();
7006+
} else {
7007+
std::string name1 = v1->name();
7008+
if (name1.empty()) {
7009+
name1 = v1->DebugString();
7010+
}
7011+
std::string name2 = v2->name();
7012+
if (name2.empty()) {
7013+
name2 = v2->DebugString();
7014+
}
7015+
boolvar =
7016+
MakeBoolVar(absl::StrFormat("IsEqualVar(%s, %s)", name1, name2));
7017+
AddConstraint(MakeIsEqualCt(v1, v2, boolvar));
7018+
model_cache_->InsertExprExprExpression(boolvar, v1, v2,
7019+
ModelCache::EXPR_EXPR_IS_EQUAL);
7020+
}
7021+
return boolvar;
7022+
}
7023+
}
7024+
7025+
Constraint* Solver::MakeIsEqualCt(IntExpr* v1, IntExpr* v2, IntVar* b) {
7026+
CHECK_EQ(this, v1->solver());
7027+
CHECK_EQ(this, v2->solver());
7028+
if (v1->Bound()) {
7029+
return MakeIsEqualCstCt(v2, v1->Min(), b);
7030+
} else if (v2->Bound()) {
7031+
return MakeIsEqualCstCt(v1, v2->Min(), b);
7032+
}
7033+
if (b->Bound()) {
7034+
if (b->Min() == 0) {
7035+
return MakeNonEquality(v1, v2);
7036+
} else {
7037+
return MakeEquality(v1, v2);
7038+
}
7039+
}
7040+
return RevAlloc(new IsEqualCt(this, v1, v2, b));
7041+
}
7042+
7043+
IntVar* Solver::MakeIsDifferentVar(IntExpr* v1, IntExpr* v2) {
7044+
CHECK_EQ(this, v1->solver());
7045+
CHECK_EQ(this, v2->solver());
7046+
if (v1->Bound()) {
7047+
return MakeIsDifferentCstVar(v2, v1->Min());
7048+
} else if (v2->Bound()) {
7049+
return MakeIsDifferentCstVar(v1, v2->Min());
7050+
}
7051+
IntExpr* cache = model_cache_->FindExprExprExpression(
7052+
v1, v2, ModelCache::EXPR_EXPR_IS_NOT_EQUAL);
7053+
if (cache == nullptr) {
7054+
cache = model_cache_->FindExprExprExpression(
7055+
v2, v1, ModelCache::EXPR_EXPR_IS_NOT_EQUAL);
7056+
}
7057+
if (cache != nullptr) {
7058+
return cache->Var();
7059+
} else {
7060+
IntVar* boolvar = nullptr;
7061+
IntExpr* reverse_cache = model_cache_->FindExprExprExpression(
7062+
v1, v2, ModelCache::EXPR_EXPR_IS_EQUAL);
7063+
if (reverse_cache == nullptr) {
7064+
reverse_cache = model_cache_->FindExprExprExpression(
7065+
v2, v1, ModelCache::EXPR_EXPR_IS_EQUAL);
7066+
}
7067+
if (reverse_cache != nullptr) {
7068+
boolvar = MakeDifference(1, reverse_cache)->Var();
7069+
} else {
7070+
std::string name1 = v1->name();
7071+
if (name1.empty()) {
7072+
name1 = v1->DebugString();
7073+
}
7074+
std::string name2 = v2->name();
7075+
if (name2.empty()) {
7076+
name2 = v2->DebugString();
7077+
}
7078+
boolvar =
7079+
MakeBoolVar(absl::StrFormat("IsDifferentVar(%s, %s)", name1, name2));
7080+
AddConstraint(MakeIsDifferentCt(v1, v2, boolvar));
7081+
}
7082+
model_cache_->InsertExprExprExpression(boolvar, v1, v2,
7083+
ModelCache::EXPR_EXPR_IS_NOT_EQUAL);
7084+
return boolvar;
7085+
}
7086+
}
7087+
7088+
Constraint* Solver::MakeIsDifferentCt(IntExpr* v1, IntExpr* v2, IntVar* b) {
7089+
CHECK_EQ(this, v1->solver());
7090+
CHECK_EQ(this, v2->solver());
7091+
if (v1->Bound()) {
7092+
return MakeIsDifferentCstCt(v2, v1->Min(), b);
7093+
} else if (v2->Bound()) {
7094+
return MakeIsDifferentCstCt(v1, v2->Min(), b);
7095+
}
7096+
return RevAlloc(new IsDifferentCt(this, v1, v2, b));
7097+
}
7098+
7099+
IntVar* Solver::MakeIsLessOrEqualVar(IntExpr* left, IntExpr* right) {
7100+
CHECK_EQ(this, left->solver());
7101+
CHECK_EQ(this, right->solver());
7102+
if (left->Bound()) {
7103+
return MakeIsGreaterOrEqualCstVar(right, left->Min());
7104+
} else if (right->Bound()) {
7105+
return MakeIsLessOrEqualCstVar(left, right->Min());
7106+
}
7107+
IntExpr* const cache = model_cache_->FindExprExprExpression(
7108+
left, right, ModelCache::EXPR_EXPR_IS_LESS_OR_EQUAL);
7109+
if (cache != nullptr) {
7110+
return cache->Var();
7111+
} else {
7112+
std::string name1 = left->name();
7113+
if (name1.empty()) {
7114+
name1 = left->DebugString();
7115+
}
7116+
std::string name2 = right->name();
7117+
if (name2.empty()) {
7118+
name2 = right->DebugString();
7119+
}
7120+
IntVar* const boolvar =
7121+
MakeBoolVar(absl::StrFormat("IsLessOrEqual(%s, %s)", name1, name2));
7122+
7123+
AddConstraint(RevAlloc(new IsLessOrEqualCt(this, left, right, boolvar)));
7124+
model_cache_->InsertExprExprExpression(
7125+
boolvar, left, right, ModelCache::EXPR_EXPR_IS_LESS_OR_EQUAL);
7126+
return boolvar;
7127+
}
7128+
}
7129+
7130+
Constraint* Solver::MakeIsLessOrEqualCt(IntExpr* left, IntExpr* right,
7131+
IntVar* b) {
7132+
CHECK_EQ(this, left->solver());
7133+
CHECK_EQ(this, right->solver());
7134+
if (left->Bound()) {
7135+
return MakeIsGreaterOrEqualCstCt(right, left->Min(), b);
7136+
} else if (right->Bound()) {
7137+
return MakeIsLessOrEqualCstCt(left, right->Min(), b);
7138+
}
7139+
return RevAlloc(new IsLessOrEqualCt(this, left, right, b));
7140+
}
7141+
7142+
IntVar* Solver::MakeIsLessVar(IntExpr* left, IntExpr* right) {
7143+
CHECK_EQ(this, left->solver());
7144+
CHECK_EQ(this, right->solver());
7145+
if (left->Bound()) {
7146+
return MakeIsGreaterCstVar(right, left->Min());
7147+
} else if (right->Bound()) {
7148+
return MakeIsLessCstVar(left, right->Min());
7149+
}
7150+
IntExpr* const cache = model_cache_->FindExprExprExpression(
7151+
left, right, ModelCache::EXPR_EXPR_IS_LESS);
7152+
if (cache != nullptr) {
7153+
return cache->Var();
7154+
} else {
7155+
std::string name1 = left->name();
7156+
if (name1.empty()) {
7157+
name1 = left->DebugString();
7158+
}
7159+
std::string name2 = right->name();
7160+
if (name2.empty()) {
7161+
name2 = right->DebugString();
7162+
}
7163+
IntVar* const boolvar =
7164+
MakeBoolVar(absl::StrFormat("IsLessOrEqual(%s, %s)", name1, name2));
7165+
7166+
AddConstraint(RevAlloc(new IsLessCt(this, left, right, boolvar)));
7167+
model_cache_->InsertExprExprExpression(boolvar, left, right,
7168+
ModelCache::EXPR_EXPR_IS_LESS);
7169+
return boolvar;
7170+
}
7171+
}
7172+
7173+
Constraint* Solver::MakeIsLessCt(IntExpr* left, IntExpr* right, IntVar* b) {
7174+
CHECK_EQ(this, left->solver());
7175+
CHECK_EQ(this, right->solver());
7176+
if (left->Bound()) {
7177+
return MakeIsGreaterCstCt(right, left->Min(), b);
7178+
} else if (right->Bound()) {
7179+
return MakeIsLessCstCt(left, right->Min(), b);
7180+
}
7181+
return RevAlloc(new IsLessCt(this, left, right, b));
7182+
}
7183+
7184+
IntVar* Solver::MakeIsGreaterOrEqualVar(IntExpr* left, IntExpr* right) {
7185+
return MakeIsLessOrEqualVar(right, left);
7186+
}
7187+
7188+
Constraint* Solver::MakeIsGreaterOrEqualCt(IntExpr* left, IntExpr* right,
7189+
IntVar* b) {
7190+
return MakeIsLessOrEqualCt(right, left, b);
7191+
}
7192+
7193+
IntVar* Solver::MakeIsGreaterVar(IntExpr* left, IntExpr* right) {
7194+
return MakeIsLessVar(right, left);
7195+
}
7196+
7197+
Constraint* Solver::MakeIsGreaterCt(IntExpr* left, IntExpr* right, IntVar* b) {
7198+
return MakeIsLessCt(right, left, b);
7199+
}
7200+
69097201
} // namespace operations_research

0 commit comments

Comments
 (0)