28 return context->GetLiteralRepresentative(ref_);
32 return context->GetVariableRepresentative(ref_);
49 IntegerVariableProto*
const var_proto =
working_model->add_variables();
50 var_proto->add_domain(cst);
51 var_proto->add_domain(cst);
54 return constant_to_ref_[cst].Get(
this);
60 ct->add_enforcement_literal(
a);
61 ct->mutable_bool_and()->add_literals(
b);
66 ConstraintProto*
const imply =
working_model->add_constraints();
70 imply->mutable_enforcement_literal()->Resize(1,
b);
71 LinearConstraintProto* mutable_linear = imply->mutable_linear();
72 mutable_linear->mutable_vars()->Resize(1, x);
73 mutable_linear->mutable_coeffs()->Resize(1, 1);
89 return domains[
var].Min() >= 0 && domains[
var].Max() <= 1;
95 return domains[lit].Min() == 1;
104 return domains[lit].Max() == 0;
123 int64_t result = expr.offset();
124 for (
int i = 0; i < expr.vars_size(); ++i) {
125 const int64_t coeff = expr.coeffs(i);
127 result += coeff *
MinOf(expr.vars(i));
129 result += coeff *
MaxOf(expr.vars(i));
136 int64_t result = expr.offset();
137 for (
int i = 0; i < expr.vars_size(); ++i) {
138 const int64_t coeff = expr.coeffs(i);
140 result += coeff *
MaxOf(expr.vars(i));
142 result += coeff *
MinOf(expr.vars(i));
150 bool PresolveContext::VariableIsNotRepresentativeOfEquivalenceClass(
171 return var_to_constraints_[
var].size() == 1 &&
172 VariableIsNotRepresentativeOfEquivalenceClass(
var) &&
182 var_to_constraints_[
var].size() == 2 &&
183 VariableIsNotRepresentativeOfEquivalenceClass(
var);
190 return var_to_constraints_[
PositiveRef(ref)].empty();
202 if (
IsFixed(ref))
return false;
203 if (!removed_variables_.contains(
PositiveRef(ref)))
return false;
204 if (!var_to_constraints_[
PositiveRef(ref)].empty()) {
206 " was removed, yet it appears in some constraints!");
209 for (
const int c : var_to_constraints_[
PositiveRef(ref)]) {
211 logger_,
"constraint #", c,
" : ",
212 c >= 0 ?
working_model->constraints(c).ShortDebugString() :
"");
221 return var_to_num_linear1_[
var] == var_to_constraints_[
var].size();
227 result = domains[ref];
238 return domains[ref].Contains(
value);
242 int ref,
const Domain& domain,
bool* domain_modified) {
247 if (domains[
var].IsIncludedIn(domain)) {
250 domains[
var] = domains[
var].IntersectionWith(domain);
253 if (domains[
var].IsIncludedIn(temp)) {
256 domains[
var] = domains[
var].IntersectionWith(temp);
259 if (domain_modified !=
nullptr) {
260 *domain_modified =
true;
263 if (domains[
var].IsEmpty()) {
297 void PresolveContext::UpdateLinear1Usage(
const ConstraintProto&
ct,
int c) {
298 const int old_var = constraint_to_linear1_var_[c];
300 var_to_num_linear1_[old_var]--;
302 if (
ct.constraint_case() == ConstraintProto::ConstraintCase::kLinear &&
303 ct.linear().vars().size() == 1) {
305 constraint_to_linear1_var_[c] =
var;
306 var_to_num_linear1_[
var]++;
310 void PresolveContext::AddVariableUsage(
int c) {
314 for (
const int v : constraint_to_vars_[c]) {
316 var_to_constraints_[v].insert(c);
318 for (
const int i : constraint_to_intervals_[c]) interval_usage_[i]++;
319 UpdateLinear1Usage(
ct, c);
323 if (is_unsat)
return;
328 for (
const int i : constraint_to_intervals_[c]) interval_usage_[i]--;
330 for (
const int i : constraint_to_intervals_[c]) interval_usage_[i]++;
335 const std::vector<int>& old_usage = constraint_to_vars_[c];
336 const int old_size = old_usage.size();
338 for (
const int var : tmp_new_usage_) {
340 while (i < old_size && old_usage[i] <
var) {
341 var_to_constraints_[old_usage[i]].erase(c);
344 if (i < old_size && old_usage[i] ==
var) {
347 var_to_constraints_[
var].insert(c);
350 for (; i < old_size; ++i) var_to_constraints_[old_usage[i]].erase(c);
351 constraint_to_vars_[c] = tmp_new_usage_;
353 UpdateLinear1Usage(
ct, c);
357 return constraint_to_vars_.size() ==
working_model->constraints_size();
361 if (is_unsat)
return;
362 const int old_size = constraint_to_vars_.size();
365 constraint_to_vars_.resize(new_size);
366 constraint_to_linear1_var_.resize(new_size, -1);
367 constraint_to_intervals_.resize(new_size);
368 interval_usage_.resize(new_size);
369 for (
int c = old_size; c < new_size; ++c) {
376 if (is_unsat)
return true;
377 if (constraint_to_vars_.size() !=
working_model->constraints_size()) {
378 LOG(
INFO) <<
"Wrong constraint_to_vars size!";
381 for (
int c = 0; c < constraint_to_vars_.size(); ++c) {
382 if (constraint_to_vars_[c] !=
384 LOG(
INFO) <<
"Wrong variables usage for constraint: \n"
386 <<
"old_size: " << constraint_to_vars_[c].size();
390 int num_in_objective = 0;
391 for (
int v = 0; v < var_to_constraints_.size(); ++v) {
394 if (!objective_map_.contains(v)) {
396 <<
" is marked as part of the objective but isn't.";
401 if (num_in_objective != objective_map_.size()) {
402 LOG(
INFO) <<
"Not all variables are marked as part of the objective";
419 bool PresolveContext::AddRelation(
int x,
int y, int64_t c, int64_t o,
423 if (std::abs(c) != 1)
return repo->
TryAdd(x, y, c, o);
440 bool allow_rep_x = m_x < m_y;
441 bool allow_rep_y = m_y < m_x;
448 return repo->
TryAdd(x, y, c, o, allow_rep_x, allow_rep_y);
456 const int rep = constant_to_ref_[
min].Get(
this);
459 AddRelation(
var, rep, 1, 0, &affine_relations_);
460 AddRelation(
var, rep, 1, 0, &var_equiv_relations_);
498 for (
auto& ref_map : var_to_constraints_) {
524 if (affine_relations_.
ClassSize(rep) == 1 &&
525 var_equiv_relations_.
ClassSize(rep) == 1) {
537 if (is_unsat)
return false;
545 const int64_t lhs =
DomainOf(ref_x).
Min() - offset;
546 if (lhs % std::abs(coeff) != 0) {
556 const int64_t value_x =
DomainOf(ref_y).
Min() * coeff + offset;
575 if (
b != 0) is_unsat =
true;
583 const int64_t unique_value = -
b /
a;
605 bool added = AddRelation(x, y, c, o, &affine_relations_);
606 if ((c == 1 || c == -1) && o == 0) {
607 added |= AddRelation(x, y, c, o, &var_equiv_relations_);
620 if (x != rep) encoding_remap_queue_.push_back(x);
621 if (y != rep) encoding_remap_queue_.push_back(y);
637 LOG(
INFO) <<
"Cannot add relation " <<
DomainOf(ref_x) <<
" = " << coeff
638 <<
" * " <<
DomainOf(ref_y) <<
" + " << offset
639 <<
" because of incompatibilities with existing relation: ";
640 for (
const int ref : {ref_x, ref_y}) {
643 <<
DomainOf(r.representative) <<
" + " << r.offset;
651 if (is_unsat)
return;
660 if (ref_a == ref_b)
return;
677 const auto insert_status = abs_relations_.insert(
679 if (!insert_status.second) {
681 const int candidate = insert_status.first->second.Get(
this);
682 if (removed_variables_.contains(candidate)) {
692 auto it = abs_relations_.find(target_ref);
693 if (it == abs_relations_.end())
return false;
700 const int candidate = it->second.Get(
this);
701 if (removed_variables_.contains(candidate)) {
702 abs_relations_.erase(it);
730 DCHECK_NE(positive_possible, negative_possible);
773 for (
int i = domains.size(); i < working_model->variables_size(); ++i) {
775 if (domains.back().IsEmpty()) {
782 var_to_constraints_.resize(domains.size());
783 var_to_num_linear1_.resize(domains.size());
788 bool PresolveContext::RemapEncodingMaps() {
797 encoding_remap_queue_.clear();
803 for (
const int var : encoding_remap_queue_) {
807 int num_remapping = 0;
811 const absl::flat_hash_map<int64_t, SavedLiteral>& var_map =
813 for (
const auto& entry : var_map) {
814 const int lit = entry.second.Get(
this);
815 if (removed_variables_.contains(
PositiveRef(lit)))
continue;
816 if ((entry.first - r.
offset) % r.
coeff != 0)
continue;
817 const int64_t rep_value = (entry.first - r.
offset) / r.
coeff;
821 if (is_unsat)
return false;
823 encoding_.erase(
var);
828 const absl::flat_hash_map<int64_t, absl::flat_hash_set<int>>& var_map =
829 eq_half_encoding_[
var];
830 for (
const auto& entry : var_map) {
831 if ((entry.first - r.
offset) % r.
coeff != 0)
continue;
832 const int64_t rep_value = (entry.first - r.
offset) / r.
coeff;
833 for (
int literal : entry.second) {
838 if (is_unsat)
return false;
841 eq_half_encoding_.erase(
var);
846 const absl::flat_hash_map<int64_t, absl::flat_hash_set<int>>& var_map =
847 neq_half_encoding_[
var];
848 for (
const auto& entry : var_map) {
849 if ((entry.first - r.
offset) % r.
coeff != 0)
continue;
850 const int64_t rep_value = (entry.first - r.
offset) / r.
coeff;
851 for (
int literal : entry.second) {
856 if (is_unsat)
return false;
859 neq_half_encoding_.erase(
var);
862 if (num_remapping > 0) {
863 VLOG(1) <<
"Remapped " << num_remapping <<
" encodings due to " <<
var
867 encoding_remap_queue_.clear();
877 if (is_unsat)
return;
879 absl::flat_hash_map<int64_t, SavedLiteral>& var_map = encoding_[
var];
882 auto min_it = var_map.find(var_min);
883 if (min_it != var_map.end()) {
884 const int old_var =
PositiveRef(min_it->second.Get(
this));
885 if (removed_variables_.contains(old_var)) {
886 var_map.erase(min_it);
887 min_it = var_map.end();
892 auto max_it = var_map.find(var_max);
893 if (max_it != var_map.end()) {
894 const int old_var =
PositiveRef(max_it->second.Get(
this));
895 if (removed_variables_.contains(old_var)) {
896 var_map.erase(max_it);
897 max_it = var_map.end();
904 if (min_it != var_map.end() && max_it != var_map.end()) {
905 min_literal = min_it->second.Get(
this);
906 max_literal = max_it->second.Get(
this);
910 if (is_unsat)
return;
915 }
else if (min_it != var_map.end() && max_it == var_map.end()) {
917 min_literal = min_it->second.Get(
this);
920 }
else if (min_it == var_map.end() && max_it != var_map.end()) {
922 max_literal = max_it->second.Get(
this);
949 var_max - var_min, var_min));
952 var_min - var_max, var_max));
957 void PresolveContext::InsertVarValueEncodingInternal(
int literal,
int var,
959 bool add_constraints) {
962 absl::flat_hash_map<int64_t, SavedLiteral>& var_map = encoding_[
var];
968 const auto it = var_map.find(
value);
969 if (it != var_map.end()) {
970 const int old_var =
PositiveRef(it->second.Get(
this));
971 if (removed_variables_.contains(old_var)) {
977 var_map.insert(std::make_pair(
value, SavedLiteral(
literal)));
980 if (!insert.second) {
981 const int previous_literal = insert.first->second.Get(
this);
983 if (
literal != previous_literal) {
985 "variables: merge equivalent var value encoding literals");
998 if (add_constraints) {
1006 bool PresolveContext::InsertHalfVarValueEncoding(
int literal,
int var,
1007 int64_t
value,
bool imply_eq) {
1008 if (is_unsat)
return false;
1015 if (!direct_set.insert(
literal).second)
return false;
1018 << (imply_eq ?
") == " :
") != ") <<
value;
1025 for (
const int other : other_set) {
1030 InsertVarValueEncodingInternal(imply_eq_literal,
var,
value,
1038 bool PresolveContext::CanonicalizeEncoding(
int* ref, int64_t*
value) {
1040 if ((*
value - r.offset) % r.coeff != 0)
return false;
1041 *ref = r.representative;
1048 if (!RemapEncodingMaps())
return;
1049 if (!CanonicalizeEncoding(&ref, &
value))
return;
1051 InsertVarValueEncodingInternal(
literal, ref,
value,
true);
1056 if (!RemapEncodingMaps())
return false;
1057 if (!CanonicalizeEncoding(&
var, &
value))
return false;
1064 if (!RemapEncodingMaps())
return false;
1065 if (!CanonicalizeEncoding(&
var, &
value))
return false;
1072 if (!RemapEncodingMaps())
return false;
1073 if (!CanonicalizeEncoding(&ref, &
value))
return false;
1074 const absl::flat_hash_map<int64_t, SavedLiteral>& var_map = encoding_[ref];
1075 const auto it = var_map.find(
value);
1076 if (it != var_map.end()) {
1078 *
literal = it->second.Get(
this);
1090 const int var = ref;
1093 if (!domains[
var].Contains(
value)) {
1098 absl::flat_hash_map<int64_t, SavedLiteral>& var_map = encoding_[
var];
1099 auto it = var_map.find(
value);
1100 if (it != var_map.end()) {
1101 return it->second.Get(
this);
1105 if (domains[
var].Size() == 1) {
1108 return true_literal;
1112 const int64_t var_min =
MinOf(
var);
1113 const int64_t var_max =
MaxOf(
var);
1114 if (domains[
var].Size() == 2) {
1116 const int64_t other_value =
value == var_min ? var_max : var_min;
1117 auto other_it = var_map.find(other_value);
1118 if (other_it != var_map.end()) {
1126 if (var_min == 0 && var_max == 1) {
1147 objective_offset_ = obj.offset();
1148 objective_scaling_factor_ = obj.scaling_factor();
1149 if (objective_scaling_factor_ == 0.0) {
1150 objective_scaling_factor_ = 1.0;
1152 if (!obj.domain().empty()) {
1155 objective_domain_is_constraining_ =
true;
1158 objective_domain_is_constraining_ =
false;
1165 objective_overflow_detection_ = 0;
1167 objective_map_.clear();
1168 for (
int i = 0; i < obj.vars_size(); ++i) {
1169 const int ref = obj.vars(i);
1170 int64_t coeff = obj.coeffs(i);
1174 objective_overflow_detection_ +=
1177 objective_map_[
var] += coeff;
1178 if (objective_map_[
var] == 0) {
1179 objective_map_.erase(
var);
1188 int64_t offset_change = 0;
1194 tmp_entries_.clear();
1195 for (
const auto& entry : objective_map_) {
1196 tmp_entries_.push_back(entry);
1202 for (
const auto& entry : tmp_entries_) {
1203 const int var = entry.first;
1204 const auto it = objective_map_.find(
var);
1205 if (it == objective_map_.end())
continue;
1206 const int64_t coeff = it->second;
1213 var_to_constraints_[
var].size() == 1 &&
1228 offset_change += coeff *
MinOf(
var);
1230 objective_map_.erase(
var);
1237 objective_map_.erase(
var);
1241 offset_change += coeff * r.
offset;
1246 if (new_coeff == 0) {
1259 Domain implied_domain(0);
1263 tmp_entries_.clear();
1264 for (
const auto& entry : objective_map_) {
1265 tmp_entries_.push_back(entry);
1267 std::sort(tmp_entries_.begin(), tmp_entries_.end());
1268 for (
const auto& entry : tmp_entries_) {
1269 const int var = entry.first;
1270 const int64_t coeff = entry.second;
1285 objective_offset_ += offset_change;
1289 for (
auto& entry : objective_map_) {
1290 entry.second /= gcd;
1293 objective_offset_ /=
static_cast<double>(gcd);
1294 objective_scaling_factor_ *=
static_cast<double>(gcd);
1297 if (objective_domain_.
IsEmpty())
return false;
1302 objective_domain_is_constraining_ =
1305 objective_domain_.
Max()))
1311 int var_in_equality, int64_t coeff_in_equality,
1312 const ConstraintProto& equality, std::vector<int>* new_vars_in_objective) {
1313 CHECK(equality.enforcement_literal().empty());
1316 if (new_vars_in_objective !=
nullptr) new_vars_in_objective->clear();
1320 const int64_t coeff_in_objective =
1323 CHECK_EQ(coeff_in_objective % coeff_in_equality, 0);
1324 const int64_t multiplier = coeff_in_objective / coeff_in_equality;
1328 for (
int i = 0; i < equality.linear().vars().size(); ++i) {
1329 int var = equality.linear().vars(i);
1331 int64_t coeff = equality.linear().coeffs(i);
1335 const int64_t new_value =
1337 objective_overflow_detection_ -
1338 std::abs(coeff_in_equality) *
1340 std::abs(
MaxOf(var_in_equality))));
1342 objective_overflow_detection_ = new_value;
1344 for (
int i = 0; i < equality.linear().vars().size(); ++i) {
1345 int var = equality.linear().vars(i);
1346 int64_t coeff = equality.linear().coeffs(i);
1351 if (
var == var_in_equality)
continue;
1353 int64_t& map_ref = objective_map_[
var];
1354 if (map_ref == 0 && new_vars_in_objective !=
nullptr) {
1355 new_vars_in_objective->push_back(
var);
1357 map_ref -= coeff * multiplier;
1360 objective_map_.erase(
var);
1367 objective_map_.erase(var_in_equality);
1379 objective_offset_ +=
static_cast<double>(offset.
Min());
1385 objective_domain_is_constraining_ =
true;
1387 if (objective_domain_.
IsEmpty()) {
1395 std::vector<std::pair<int, int64_t>> entries;
1396 for (
const auto& entry : objective_map_) {
1397 entries.push_back(entry);
1399 std::sort(entries.begin(), entries.end());
1401 CpObjectiveProto* mutable_obj =
working_model->mutable_objective();
1402 mutable_obj->set_offset(objective_offset_);
1403 mutable_obj->set_scaling_factor(objective_scaling_factor_);
1405 mutable_obj->clear_vars();
1406 mutable_obj->clear_coeffs();
1407 for (
const auto& entry : entries) {
1408 mutable_obj->add_vars(entry.first);
1409 mutable_obj->add_coeffs(entry.second);
1417 if (active_j < active_i)
std::swap(active_i, active_j);
1419 const std::tuple<int, int, int, int> key =
1420 std::make_tuple(time_i, time_j, active_i, active_j);
1421 const auto& it = reified_precedences_cache_.find(key);
1422 if (it != reified_precedences_cache_.end())
return it->second;
1425 reified_precedences_cache_[key] = result;
1428 ConstraintProto*
const lesseq =
working_model->add_constraints();
1429 lesseq->add_enforcement_literal(result);
1430 lesseq->mutable_linear()->add_vars(time_i);
1431 lesseq->mutable_linear()->add_vars(time_j);
1432 lesseq->mutable_linear()->add_coeffs(-1);
1433 lesseq->mutable_linear()->add_coeffs(1);
1434 lesseq->mutable_linear()->add_domain(0);
1444 ConstraintProto*
const greater =
working_model->add_constraints();
1445 greater->mutable_linear()->add_vars(time_i);
1446 greater->mutable_linear()->add_vars(time_j);
1447 greater->mutable_linear()->add_coeffs(-1);
1448 greater->mutable_linear()->add_coeffs(1);
1450 greater->mutable_linear()->add_domain(-1);
1453 greater->add_enforcement_literal(
NegatedRef(result));
1454 greater->add_enforcement_literal(active_i);
1455 greater->add_enforcement_literal(active_j);
1462 const auto& rev_it = reified_precedences_cache_.find(
1463 std::make_tuple(time_j, time_i, active_i, active_j));
1464 if (rev_it != reified_precedences_cache_.end()) {
1465 auto*
const bool_or =
working_model->add_constraints()->mutable_bool_or();
1466 bool_or->add_literals(result);
1467 bool_or->add_literals(rev_it->second);
1476 reified_precedences_cache_.clear();
#define DCHECK_NE(val1, val2)
#define CHECK_EQ(val1, val2)
#define CHECK_NE(val1, val2)
#define DCHECK_LT(val1, val2)
#define DCHECK(condition)
#define CHECK_LE(val1, val2)
#define DCHECK_EQ(val1, val2)
#define VLOG(verboselevel)
void IgnoreFromClassSize(int x)
bool TryAdd(int x, int y, int64_t coeff, int64_t offset)
int ClassSize(int x) const
Relation Get(int x) const
We call domain any subset of Int64 = [kint64min, kint64max].
static Domain AllValues()
Returns the full domain Int64.
Domain InverseMultiplicationBy(const int64_t coeff) const
Returns {x ∈ Int64, ∃ e ∈ D, x * coeff = e}.
Domain Negation() const
Returns {x ∈ Int64, ∃ e ∈ D, x = -e}.
bool IsIncludedIn(const Domain &domain) const
Returns true iff D is included in the given domain.
Domain AdditionWith(const Domain &domain) const
Returns {x ∈ Int64, ∃ a ∈ D, ∃ b ∈ domain, x = a + b}.
Domain MultiplicationBy(int64_t coeff, bool *exact=nullptr) const
Returns {x ∈ Int64, ∃ e ∈ D, x = e * coeff}.
Domain IntersectionWith(const Domain &domain) const
Returns the intersection of D and domain.
int64_t Min() const
Returns the min value of the domain.
bool IsEmpty() const
Returns true if this is the empty set.
int64_t Max() const
Returns the max value of the domain.
Domain RelaxIfTooComplex() const
If NumIntervals() is too large, this return a superset of the domain.
Domain SimplifyUsingImpliedDomain(const Domain &implied_domain) const
Advanced usage.
static int64_t GCD64(int64_t x, int64_t y)
bool LoggingIsEnabled() const
void Set(IntegerType index)
void Resize(IntegerType size)
int64_t MaxOf(int ref) const
SparseBitset< int64_t > modified_domains
bool StoreAbsRelation(int target_ref, int ref)
bool ConstraintVariableUsageIsConsistent()
void AddImplication(int a, int b)
void InsertVarValueEncoding(int literal, int ref, int64_t value)
bool VariableIsOnlyUsedInEncoding(int ref) const
ABSL_MUST_USE_RESULT bool IntersectDomainWith(int ref, const Domain &domain, bool *domain_modified=nullptr)
std::vector< absl::flat_hash_set< int > > var_to_lb_only_constraints
bool ConstraintVariableGraphIsUpToDate() const
bool StoreLiteralImpliesVarNEqValue(int literal, int var, int64_t value)
bool VariableWithCostIsUniqueAndRemovable(int ref) const
void WriteObjectiveToProto() const
int GetLiteralRepresentative(int ref) const
ABSL_MUST_USE_RESULT bool SetLiteralToTrue(int lit)
bool StoreAffineRelation(int ref_x, int ref_y, int64_t coeff, int64_t offset)
std::vector< absl::flat_hash_set< int > > var_to_ub_only_constraints
bool SubstituteVariableInObjective(int var_in_equality, int64_t coeff_in_equality, const ConstraintProto &equality, std::vector< int > *new_vars_in_objective=nullptr)
int GetOrCreateVarValueEncoding(int ref, int64_t value)
void UpdateNewConstraintsVariableUsage()
bool VariableIsUniqueAndRemovable(int ref) const
void RemoveVariableFromAffineRelation(int var)
ABSL_MUST_USE_RESULT bool NotifyThatModelIsUnsat(const std::string &message="")
bool PropagateAffineRelation(int ref)
Domain DomainOf(int ref) const
int64_t num_presolve_operations
void InitializeNewDomains()
int GetVariableRepresentative(int ref) const
std::string AffineRelationDebugString(int ref) const
int NewIntVar(const Domain &domain)
void MarkVariableAsRemoved(int ref)
bool DomainIsEmpty(int ref) const
void CanonicalizeDomainOfSizeTwo(int var)
bool LiteralIsTrue(int lit) const
absl::flat_hash_map< std::string, int > stats_by_rule_name
void StoreBooleanEqualityRelation(int ref_a, int ref_b)
CpModelProto * working_model
bool HasVarValueEncoding(int ref, int64_t value, int *literal=nullptr)
bool DomainContains(int ref, int64_t value) const
bool LiteralIsFalse(int lit) const
void UpdateRuleStats(const std::string &name, int num_times=1)
ABSL_MUST_USE_RESULT bool CanonicalizeObjective()
void RemoveAllVariablesFromAffineRelationConstraint()
AffineRelation::Relation GetAffineRelation(int ref) const
bool VariableIsNotUsedAnymore(int ref) const
void UpdateConstraintVariableUsage(int c)
bool keep_all_feasible_solutions
bool IsFixed(int ref) const
ABSL_MUST_USE_RESULT bool SetLiteralToFalse(int lit)
std::string RefDebugString(int ref) const
int GetOrCreateConstantVar(int64_t cst)
int GetOrCreateReifiedPrecedenceLiteral(int time_i, int time_j, int active_i, int active_j)
void ClearPrecedenceCache()
void ReadObjectiveFromProto()
void AddImplyInDomain(int b, int x, const Domain &domain)
bool CanBeUsedAsLiteral(int ref) const
bool VariableWasRemoved(int ref) const
void ExploitFixedDomain(int var)
int64_t MinOf(int ref) const
bool GetAbsRelation(int target_ref, int *ref)
bool StoreLiteralImpliesVarEqValue(int literal, int var, int64_t value)
int Get(PresolveContext *context) const
int Get(PresolveContext *context) const
GurobiMPCallbackContext * context
bool ContainsKey(const Collection &collection, const Key &key)
const Collection::value_type::second_type & FindOrDie(const Collection &collection, const typename Collection::value_type::first_type &key)
void swap(IdMap< K, V > &a, IdMap< K, V > &b)
std::vector< int > UsedVariables(const ConstraintProto &ct)
bool RefIsPositive(int ref)
std::vector< int > UsedIntervals(const ConstraintProto &ct)
constexpr int kAffineRelationConstraint
void FillDomainInProto(const Domain &domain, ProtoWithDomain *proto)
Domain ReadDomainFromProto(const ProtoWithDomain &proto)
constexpr int kObjectiveConstraint
Collection of objects used to extend the Constraint Solver library.
int64_t CapAdd(int64_t x, int64_t y)
const absl::string_view ToString(MPSolver::OptimizationProblemType optimization_problem_type)
int64_t CapProd(int64_t x, int64_t y)
std::string ProtobufDebugString(const P &message)
#define SOLVER_LOG(logger,...)
#define VLOG_IS_ON(verboselevel)