|
57 | 57 | #include "ortools/constraint_solver/interval.h" |
58 | 58 | #include "ortools/constraint_solver/local_search.h" |
59 | 59 | #include "ortools/constraint_solver/model_cache.h" |
| 60 | +#include "ortools/constraint_solver/pack.h" |
| 61 | +#include "ortools/constraint_solver/range_cst.h" |
60 | 62 | #include "ortools/constraint_solver/sequence_var.h" |
61 | 63 | #include "ortools/constraint_solver/table.h" |
62 | 64 | #include "ortools/constraint_solver/timetabling.h" |
@@ -3875,6 +3877,10 @@ Constraint* Solver::MakeNonOverlappingNonStrictBoxesConstraint( |
3875 | 3877 | return RevAlloc(new Diffn(this, x_vars, y_vars, dx, dy, false)); |
3876 | 3878 | } |
3877 | 3879 |
|
| 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 | + |
3878 | 3884 | namespace { |
3879 | 3885 | std::string StringifyEvaluatorBare(const Solver::Int64ToIntVar& evaluator, |
3880 | 3886 | int64_t range_start, int64_t range_end) { |
@@ -6906,4 +6912,290 @@ Assignment* Solver::MakeAssignment(const Assignment* const a) { |
6906 | 6912 | return RevAlloc(new Assignment(a)); |
6907 | 6913 | } |
6908 | 6914 |
|
| 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 | + |
6909 | 7201 | } // namespace operations_research |
0 commit comments