30 return context->GetLiteralRepresentative(ref_);
34 return context->GetVariableRepresentative(ref_);
53 var_proto->add_domain(cst);
56 return constant_to_ref_[cst].Get(
this);
62 ct->add_enforcement_literal(
a);
63 ct->mutable_bool_and()->add_literals(
b);
91 return domains[
var].Min() >= 0 && domains[
var].Max() <= 1;
97 return domains[lit].Min() == 1;
106 return domains[lit].Max() == 0;
125 int64_t result = expr.
offset();
126 for (
int i = 0; i < expr.
vars_size(); ++i) {
127 const int64_t coeff = expr.
coeffs(i);
138 int64_t result = expr.
offset();
139 for (
int i = 0; i < expr.
vars_size(); ++i) {
140 const int64_t coeff = expr.
coeffs(i);
153 for (
int i = 0; i < expr.
vars_size(); ++i) {
162 if (expr.
vars().size() != 1)
return false;
168 const int ref = expr.
vars(0);
175 if (!
proto.enforcement_literal().empty())
return false;
176 if (!
proto.interval().has_start_view())
return false;
177 for (
const int var :
proto.interval().start_view().vars()) {
180 for (
const int var :
proto.interval().size_view().vars()) {
183 for (
const int var :
proto.interval().end_view().vars()) {
191 return absl::StrCat(
"interval_", ct_ref,
"(",
StartMin(ct_ref),
"..",
197 return absl::StrCat(
"interval_", ct_ref,
"(lit=",
literal,
", ",
201 return absl::StrCat(
"interval_", ct_ref,
"(lit=",
literal,
", ",
206 return absl::StrCat(
"interval_", ct_ref,
"(",
StartMin(ct_ref),
" --(",
209 return absl::StrCat(
"interval_", ct_ref,
"(",
StartMin(ct_ref),
" --(",
259 bool PresolveContext::VariableIsNotRepresentativeOfEquivalenceClass(
275 return VariableIsNotRepresentativeOfEquivalenceClass(
var) &&
295 var_to_constraints_[
var].size() == 2;
302 return var_to_constraints_[
PositiveRef(ref)].empty();
314 if (
IsFixed(ref))
return false;
315 if (!removed_variables_.contains(
PositiveRef(ref)))
return false;
316 if (!var_to_constraints_[
PositiveRef(ref)].empty()) {
318 " was removed, yet it appears in some constraints!");
321 for (
const int c : var_to_constraints_[
PositiveRef(ref)]) {
323 logger_,
"constraint #", c,
" : ",
334 return var_to_num_linear1_[
var] == var_to_constraints_[
var].size() ||
336 var_to_num_linear1_[
var] + 1 == var_to_constraints_[
var].size());
342 result = domains[ref];
353 return domains[ref].Contains(
value);
357 int ref,
const Domain& domain,
bool* domain_modified) {
362 if (domains[
var].IsIncludedIn(domain)) {
365 domains[
var] = domains[
var].IntersectionWith(domain);
368 if (domains[
var].IsIncludedIn(temp)) {
371 domains[
var] = domains[
var].IntersectionWith(temp);
374 if (domain_modified !=
nullptr) {
375 *domain_modified =
true;
378 if (domains[
var].IsEmpty()) {
395 bool* domain_modified) {
396 if (expr.
vars().empty()) {
399 if (expr.
vars().size() == 1) {
422 if (
ct.constraint_case() ==
423 ConstraintProto::ConstraintCase::CONSTRAINT_NOT_SET) {
426 for (
const int literal :
ct.enforcement_literal()) {
434 bool contains_one_free_literal =
false;
435 for (
const int literal :
ct.enforcement_literal()) {
439 return contains_one_free_literal;
446 stats_by_rule_name_[
name] += num_times;
452 const int old_var = constraint_to_linear1_var_[c];
454 var_to_num_linear1_[old_var]--;
456 if (
ct.constraint_case() == ConstraintProto::ConstraintCase::kLinear &&
457 ct.linear().vars().size() == 1) {
459 constraint_to_linear1_var_[c] =
var;
460 var_to_num_linear1_[
var]++;
464 void PresolveContext::AddVariableUsage(
int c) {
468 for (
const int v : constraint_to_vars_[c]) {
470 var_to_constraints_[v].insert(c);
472 for (
const int i : constraint_to_intervals_[c]) interval_usage_[i]++;
473 UpdateLinear1Usage(
ct, c);
477 if (is_unsat_)
return;
482 for (
const int i : constraint_to_intervals_[c]) interval_usage_[i]--;
484 for (
const int i : constraint_to_intervals_[c]) interval_usage_[i]++;
489 const std::vector<int>& old_usage = constraint_to_vars_[c];
490 const int old_size = old_usage.size();
492 for (
const int var : tmp_new_usage_) {
494 while (i < old_size && old_usage[i] <
var) {
495 var_to_constraints_[old_usage[i]].erase(c);
498 if (i < old_size && old_usage[i] ==
var) {
501 var_to_constraints_[
var].insert(c);
504 for (; i < old_size; ++i) var_to_constraints_[old_usage[i]].erase(c);
505 constraint_to_vars_[c] = tmp_new_usage_;
507 UpdateLinear1Usage(
ct, c);
515 if (is_unsat_)
return;
516 const int old_size = constraint_to_vars_.size();
519 constraint_to_vars_.resize(new_size);
520 constraint_to_linear1_var_.resize(new_size, -1);
521 constraint_to_intervals_.resize(new_size);
522 interval_usage_.resize(new_size);
523 for (
int c = old_size; c < new_size; ++c) {
530 if (is_unsat_)
return true;
532 LOG(
INFO) <<
"Wrong constraint_to_vars size!";
535 for (
int c = 0; c < constraint_to_vars_.size(); ++c) {
536 if (constraint_to_vars_[c] !=
538 LOG(
INFO) <<
"Wrong variables usage for constraint: \n" 540 <<
"old_size: " << constraint_to_vars_[c].size();
544 int num_in_objective = 0;
545 for (
int v = 0; v < var_to_constraints_.size(); ++v) {
548 if (!objective_map_.contains(v)) {
550 <<
" is marked as part of the objective but isn't.";
555 if (num_in_objective != objective_map_.size()) {
556 LOG(
INFO) <<
"Not all variables are marked as part of the objective";
573 bool PresolveContext::AddRelation(
int x,
int y, int64_t c, int64_t o,
577 if (std::abs(c) != 1)
return repo->
TryAdd(x, y, c, o);
594 bool allow_rep_x = m_x < m_y;
595 bool allow_rep_y = m_y < m_x;
602 if (allow_rep_x && allow_rep_y) {
612 return repo->
TryAdd(x, y, c, o, allow_rep_x, allow_rep_y);
627 const int rep = constant_to_ref_[
min].Get(
this);
630 AddRelation(
var, rep, 1, 0, &var_equiv_relations_);
667 for (
auto& ref_map : var_to_constraints_) {
693 if (affine_relations_.
ClassSize(rep) == 1 &&
694 var_equiv_relations_.
ClassSize(rep) == 1) {
706 if (is_unsat_)
return false;
714 const int64_t lhs =
DomainOf(ref_x).
Min() - offset;
715 if (lhs % std::abs(coeff) != 0) {
725 const int64_t value_x =
DomainOf(ref_y).
Min() * coeff + offset;
744 if (
b != 0) is_unsat_ =
true;
752 const int64_t unique_value = -
b /
a;
774 bool added = AddRelation(x, y, c, o, &affine_relations_);
775 if ((c == 1 || c == -1) && o == 0) {
776 added |= AddRelation(x, y, c, o, &var_equiv_relations_);
789 if (x != rep) encoding_remap_queue_.push_back(x);
790 if (y != rep) encoding_remap_queue_.push_back(y);
806 LOG(
INFO) <<
"Cannot add relation " <<
DomainOf(ref_x) <<
" = " << coeff
807 <<
" * " <<
DomainOf(ref_y) <<
" + " << offset
808 <<
" because of incompatibilities with existing relation: ";
809 for (
const int ref : {ref_x, ref_y}) {
812 <<
DomainOf(r.representative) <<
" + " << r.offset;
820 if (is_unsat_)
return;
829 if (ref_a == ref_b)
return;
846 const auto insert_status = abs_relations_.insert(
848 if (!insert_status.second) {
850 const int candidate = insert_status.first->second.Get(
this);
851 if (removed_variables_.contains(candidate)) {
861 auto it = abs_relations_.find(target_ref);
862 if (it == abs_relations_.end())
return false;
869 const int candidate = it->second.Get(
this);
870 if (removed_variables_.contains(candidate)) {
871 abs_relations_.erase(it);
900 DCHECK_NE(positive_possible, negative_possible);
945 if (domains.back().IsEmpty()) {
952 var_to_constraints_.resize(domains.size());
953 var_to_num_linear1_.resize(domains.size());
958 bool PresolveContext::RemapEncodingMaps() {
967 encoding_remap_queue_.clear();
973 for (
const int var : encoding_remap_queue_) {
977 int num_remapping = 0;
981 const absl::flat_hash_map<int64_t, SavedLiteral>& var_map =
983 for (
const auto& entry : var_map) {
984 const int lit = entry.second.Get(
this);
985 if (removed_variables_.contains(
PositiveRef(lit)))
continue;
986 if ((entry.first - r.
offset) % r.
coeff != 0)
continue;
987 const int64_t rep_value = (entry.first - r.
offset) / r.
coeff;
991 if (is_unsat_)
return false;
993 encoding_.erase(
var);
998 const absl::flat_hash_map<int64_t, absl::flat_hash_set<int>>& var_map =
999 eq_half_encoding_[
var];
1000 for (
const auto& entry : var_map) {
1001 if ((entry.first - r.
offset) % r.
coeff != 0)
continue;
1002 const int64_t rep_value = (entry.first - r.
offset) / r.
coeff;
1003 for (
int literal : entry.second) {
1008 if (is_unsat_)
return false;
1011 eq_half_encoding_.erase(
var);
1016 const absl::flat_hash_map<int64_t, absl::flat_hash_set<int>>& var_map =
1017 neq_half_encoding_[
var];
1018 for (
const auto& entry : var_map) {
1019 if ((entry.first - r.
offset) % r.
coeff != 0)
continue;
1020 const int64_t rep_value = (entry.first - r.
offset) / r.
coeff;
1021 for (
int literal : entry.second) {
1026 if (is_unsat_)
return false;
1029 neq_half_encoding_.erase(
var);
1032 if (num_remapping > 0) {
1033 VLOG(1) <<
"Remapped " << num_remapping <<
" encodings due to " <<
var 1037 encoding_remap_queue_.clear();
1044 const int64_t var_min =
MinOf(
var);
1045 const int64_t var_max =
MaxOf(
var);
1047 if (is_unsat_)
return;
1049 absl::flat_hash_map<int64_t, SavedLiteral>& var_map = encoding_[
var];
1052 auto min_it = var_map.find(var_min);
1053 if (min_it != var_map.end()) {
1054 const int old_var =
PositiveRef(min_it->second.Get(
this));
1055 if (removed_variables_.contains(old_var)) {
1056 var_map.erase(min_it);
1057 min_it = var_map.end();
1062 auto max_it = var_map.find(var_max);
1063 if (max_it != var_map.end()) {
1064 const int old_var =
PositiveRef(max_it->second.Get(
this));
1065 if (removed_variables_.contains(old_var)) {
1066 var_map.erase(max_it);
1067 max_it = var_map.end();
1074 if (min_it != var_map.end() && max_it != var_map.end()) {
1075 min_literal = min_it->second.Get(
this);
1076 max_literal = max_it->second.Get(
this);
1077 if (min_literal !=
NegatedRef(max_literal)) {
1080 if (is_unsat_)
return;
1085 }
else if (min_it != var_map.end() && max_it == var_map.end()) {
1087 min_literal = min_it->second.Get(
this);
1090 }
else if (min_it == var_map.end() && max_it != var_map.end()) {
1092 max_literal = max_it->second.Get(
this);
1119 var_max - var_min, var_min));
1122 var_min - var_max, var_max));
1127 void PresolveContext::InsertVarValueEncodingInternal(
int literal,
int var,
1129 bool add_constraints) {
1132 absl::flat_hash_map<int64_t, SavedLiteral>& var_map = encoding_[
var];
1138 const auto it = var_map.find(
value);
1139 if (it != var_map.end()) {
1140 const int old_var =
PositiveRef(it->second.Get(
this));
1141 if (removed_variables_.contains(old_var)) {
1147 var_map.insert(std::make_pair(
value, SavedLiteral(
literal)));
1150 if (!insert.second) {
1151 const int previous_literal = insert.first->second.Get(
this);
1153 if (
literal != previous_literal) {
1155 "variables: merge equivalent var value encoding literals");
1165 <<
") == " <<
value;
1168 if (add_constraints) {
1176 bool PresolveContext::InsertHalfVarValueEncoding(
int literal,
int var,
1177 int64_t
value,
bool imply_eq) {
1178 if (is_unsat_)
return false;
1185 if (!direct_set.insert(
literal).second)
return false;
1188 << (imply_eq ?
") == " :
") != ") <<
value;
1195 for (
const int other : other_set) {
1200 InsertVarValueEncodingInternal(imply_eq_literal,
var,
value,
1208 bool PresolveContext::CanonicalizeEncoding(
int* ref, int64_t*
value) {
1210 if ((*
value - r.offset) % r.coeff != 0)
return false;
1211 *ref = r.representative;
1218 if (!RemapEncodingMaps())
return;
1219 if (!CanonicalizeEncoding(&ref, &
value))
return;
1221 InsertVarValueEncodingInternal(
literal, ref,
value,
true);
1226 if (!RemapEncodingMaps())
return false;
1227 if (!CanonicalizeEncoding(&
var, &
value))
return false;
1234 if (!RemapEncodingMaps())
return false;
1235 if (!CanonicalizeEncoding(&
var, &
value))
return false;
1243 if (!RemapEncodingMaps())
return false;
1244 if (!CanonicalizeEncoding(&ref, &
value))
return false;
1245 const absl::flat_hash_map<int64_t, SavedLiteral>& var_map = encoding_[ref];
1246 const auto it = var_map.find(
value);
1247 if (it != var_map.end()) {
1249 *
literal = it->second.Get(
this);
1267 const int var = ref;
1270 if (!domains[
var].Contains(
value)) {
1275 absl::flat_hash_map<int64_t, SavedLiteral>& var_map = encoding_[
var];
1276 auto it = var_map.find(
value);
1277 if (it != var_map.end()) {
1278 return it->second.Get(
this);
1282 if (domains[
var].Size() == 1) {
1285 return true_literal;
1289 const int64_t var_min =
MinOf(
var);
1290 const int64_t var_max =
MaxOf(
var);
1291 if (domains[
var].Size() == 2) {
1293 const int64_t other_value =
value == var_min ? var_max : var_min;
1294 auto other_it = var_map.find(other_value);
1295 if (other_it != var_map.end()) {
1303 if (var_min == 0 && var_max == 1) {
1324 objective_offset_ = obj.
offset();
1326 if (objective_scaling_factor_ == 0.0) {
1327 objective_scaling_factor_ = 1.0;
1329 if (!obj.
domain().empty()) {
1332 objective_domain_is_constraining_ =
true;
1335 objective_domain_is_constraining_ =
false;
1342 objective_overflow_detection_ = 0;
1344 objective_map_.clear();
1345 for (
int i = 0; i < obj.
vars_size(); ++i) {
1346 const int ref = obj.
vars(i);
1347 int64_t coeff = obj.
coeffs(i);
1351 objective_overflow_detection_ +=
1354 objective_map_[
var] += coeff;
1355 if (objective_map_[
var] == 0) {
1356 objective_map_.erase(
var);
1365 int64_t offset_change = 0;
1371 tmp_entries_.clear();
1372 for (
const auto& entry : objective_map_) {
1373 tmp_entries_.push_back(entry);
1379 for (
const auto& entry : tmp_entries_) {
1380 const int var = entry.first;
1381 const auto it = objective_map_.find(
var);
1382 if (it == objective_map_.end())
continue;
1383 const int64_t coeff = it->second;
1390 var_to_constraints_[
var].size() == 1 &&
1405 offset_change += coeff *
MinOf(
var);
1407 objective_map_.erase(
var);
1414 objective_map_.erase(
var);
1418 offset_change += coeff * r.
offset;
1423 if (new_coeff == 0) {
1436 Domain implied_domain(0);
1440 tmp_entries_.clear();
1441 for (
const auto& entry : objective_map_) {
1442 tmp_entries_.push_back(entry);
1444 std::sort(tmp_entries_.begin(), tmp_entries_.end());
1445 for (
const auto& entry : tmp_entries_) {
1446 const int var = entry.first;
1447 const int64_t coeff = entry.second;
1462 objective_offset_ += offset_change;
1466 for (
auto& entry : objective_map_) {
1467 entry.second /= gcd;
1470 objective_offset_ /= static_cast<double>(gcd);
1471 objective_scaling_factor_ *= static_cast<double>(gcd);
1474 if (objective_domain_.
IsEmpty())
return false;
1479 objective_domain_is_constraining_ =
1482 objective_domain_.
Max()))
1488 objective_map_.erase(
var);
1493 int64_t& map_ref = objective_map_[
var];
1496 objective_map_.erase(
var);
1505 objective_offset_ += static_cast<double>(
value);
1510 int var_in_equality, int64_t coeff_in_equality,
1511 const ConstraintProto& equality, std::vector<int>* new_vars_in_objective) {
1515 if (new_vars_in_objective !=
nullptr) new_vars_in_objective->clear();
1519 const int64_t coeff_in_objective =
1522 CHECK_EQ(coeff_in_objective % coeff_in_equality, 0);
1523 const int64_t multiplier = coeff_in_objective / coeff_in_equality;
1527 for (
int i = 0; i < equality.
linear().
vars().size(); ++i) {
1534 const int64_t new_value =
1536 objective_overflow_detection_ -
1537 std::abs(coeff_in_equality) *
1539 std::abs(
MaxOf(var_in_equality))));
1541 objective_overflow_detection_ = new_value;
1543 for (
int i = 0; i < equality.
linear().
vars().size(); ++i) {
1550 if (
var == var_in_equality)
continue;
1552 int64_t& map_ref = objective_map_[
var];
1553 if (map_ref == 0 && new_vars_in_objective !=
nullptr) {
1554 new_vars_in_objective->push_back(
var);
1556 map_ref -= coeff * multiplier;
1559 objective_map_.erase(
var);
1566 objective_map_.erase(var_in_equality);
1578 objective_offset_ += static_cast<double>(offset.
Min());
1584 objective_domain_is_constraining_ =
true;
1586 if (objective_domain_.IsEmpty()) {
1593 absl::Span<const int> exactly_one) {
1595 for (
const int ref : exactly_one) {
1596 const auto it = objective_map_.find(
PositiveRef(ref));
1597 if (it == objective_map_.end())
return false;
1599 const int64_t coeff = it->second;
1601 min_coeff =
std::min(min_coeff, coeff);
1604 min_coeff =
std::min(min_coeff, -coeff);
1608 int64_t offset = min_coeff;
1609 for (
const int ref : exactly_one) {
1611 int64_t& map_ref = objective_map_.at(
var);
1613 map_ref -= min_coeff;
1615 objective_map_.erase(
var);
1623 map_ref += min_coeff;
1625 objective_map_.erase(
var);
1628 offset -= min_coeff;
1634 objective_offset_ += offset;
1643 std::vector<std::pair<int, int64_t>> entries;
1644 for (
const auto& entry : objective_map_) {
1645 entries.push_back(entry);
1647 std::sort(entries.begin(), entries.end());
1651 mutable_obj->set_scaling_factor(objective_scaling_factor_);
1653 mutable_obj->clear_vars();
1654 mutable_obj->clear_coeffs();
1655 for (
const auto& entry : entries) {
1656 mutable_obj->add_vars(entry.first);
1657 mutable_obj->add_coeffs(entry.second);
1668 if (active_j < active_i)
std::swap(active_i, active_j);
1670 const std::tuple<int, int, int, int> key =
1671 std::make_tuple(time_i, time_j, active_i, active_j);
1672 const auto& it = reified_precedences_cache_.find(key);
1673 if (it != reified_precedences_cache_.end())
return it->second;
1676 reified_precedences_cache_[key] = result;
1717 const auto& rev_it = reified_precedences_cache_.find(
1718 std::make_tuple(time_j, time_i, active_i, active_j));
1719 if (rev_it != reified_precedences_cache_.end()) {
1722 bool_or->add_literals(rev_it->second);
1731 reified_precedences_cache_.clear();
1738 " affine relations were detected.");
1740 " variable equivalence relations were detected.");
1741 std::map<std::string, int> sorted_rules(stats_by_rule_name_.begin(),
1742 stats_by_rule_name_.end());
1743 for (
const auto& entry : sorted_rules) {
1744 if (entry.second == 1) {
1745 SOLVER_LOG(logger_,
" - rule '", entry.first,
"' was applied 1 time.");
1747 SOLVER_LOG(logger_,
" - rule '", entry.first,
"' was applied ",
1748 entry.second,
" times.");
::PROTOBUF_NAMESPACE_ID::int64 offset() const
std::vector< int > UsedVariables(const ConstraintProto &ct)
int Get(PresolveContext *context) const
int64_t MinOf(int ref) const
Relation Get(int x) const
void set_offset(double value)
::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 > * mutable_vars()
void InitializeNewDomains()
bool VariableIsUniqueAndRemovable(int ref) const
void Set(IntegerType index)
void ReadObjectiveFromProto()
::PROTOBUF_NAMESPACE_ID::int64 domain(int index) const
#define SOLVER_LOG(logger,...)
void add_enforcement_literal(::PROTOBUF_NAMESPACE_ID::int32 value)
Domain InverseMultiplicationBy(const int64_t coeff) const
Returns {x ∈ Int64, ∃ e ∈ D, x * coeff = e}.
void RemoveVariableFromAffineRelation(int var)
bool ConstraintVariableGraphIsUpToDate() const
bool ConstraintVariableUsageIsConsistent()
SparseBitset< int64_t > modified_domains
void UpdateRuleStats(const std::string &name, int num_times=1)
void StoreBooleanEqualityRelation(int ref_a, int ref_b)
void AddToObjective(int var, int64_t value)
bool StoreLiteralImpliesVarNEqValue(int literal, int var, int64_t value)
bool ConstraintIsOptional(int ct_ref) const
int GetOrCreateConstantVar(int64_t cst)
void CanonicalizeDomainOfSizeTwo(int var)
int64_t StartMin(int ct_ref) const
#define VLOG(verboselevel)
bool ConstraintIsInactive(int ct_index) const
bool GetAbsRelation(int target_ref, int *ref)
bool StoreAffineRelation(int ref_x, int ref_y, int64_t coeff, int64_t offset)
void swap(IdMap< K, V > &a, IdMap< K, V > &b)
std::string RefDebugString(int ref) const
constexpr int kAffineRelationConstraint
void Resize(IntegerType size)
void add_coeffs(::PROTOBUF_NAMESPACE_ID::int64 value)
const absl::string_view ToString(MPSolver::OptimizationProblemType optimization_problem_type)
bool VariableIsNotUsedAnymore(int ref) const
::PROTOBUF_NAMESPACE_ID::int64 coeffs(int index) const
bool keep_all_feasible_solutions
std::string AffineRelationDebugString(int ref) const
bool StoreAbsRelation(int target_ref, int ref)
int LiteralForExpressionMax(const LinearExpressionProto &expr) const
void add_literals(::PROTOBUF_NAMESPACE_ID::int32 value)
int64_t CapProd(int64_t x, int64_t y)
int64_t EndMin(int ct_ref) const
bool ExpressionIsAffineBoolean(const LinearExpressionProto &expr) const
Domain SimplifyUsingImpliedDomain(const Domain &implied_domain) const
Advanced usage.
int variables_size() const
::operations_research::sat::IntegerVariableProto * add_variables()
bool VariableIsOnlyUsedInEncodingAndMaybeInObjective(int ref) const
int64_t Max() const
Returns the max value of the domain.
void add_vars(::PROTOBUF_NAMESPACE_ID::int32 value)
static Domain AllValues()
Returns the full domain Int64.
void add_domain(::PROTOBUF_NAMESPACE_ID::int64 value)
int64_t num_presolve_operations
void UpdateConstraintVariableUsage(int c)
CpModelProto * working_model
void ExploitFixedDomain(int var)
bool CanBeUsedAsLiteral(int ref) const
std::string ProtobufDebugString(const P &message)
ABSL_MUST_USE_RESULT bool SetLiteralToFalse(int lit)
Domain DomainOf(int ref) const
::PROTOBUF_NAMESPACE_ID::int32 vars(int index) const
int NewIntVar(const Domain &domain)
::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 > * mutable_enforcement_literal()
::PROTOBUF_NAMESPACE_ID::int32 enforcement_literal(int index) const
::operations_research::sat::BoolArgumentProto * mutable_bool_or()
const ::operations_research::sat::LinearConstraintProto & linear() const
::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int64 > * mutable_coeffs()
void IgnoreFromClassSize(int x)
bool HasVarValueEncoding(int ref, int64_t value, int *literal=nullptr)
bool VariableIsRemovable(int ref) const
const ::operations_research::sat::IntegerVariableProto & variables(int index) const
int64_t EndMax(int ct_ref) const
int64_t Min() const
Returns the min value of the domain.
int64_t CapAdd(int64_t x, int64_t y)
Domain Negation() const
Returns {x ∈ Int64, ∃ e ∈ D, x = -e}.
::PROTOBUF_NAMESPACE_ID::int64 coeffs(int index) const
#define DCHECK_NE(val1, val2)
int64_t SizeMax(int ct_ref) const
bool VariableWasRemoved(int ref) const
void ClearPrecedenceCache()
int64_t MaxOf(int ref) const
void WriteObjectiveToProto() const
bool PropagateAffineRelation(int ref)
#define CHECK_LE(val1, val2)
::operations_research::sat::LinearConstraintProto * mutable_linear()
void AddToObjectiveOffset(int64_t value)
const ::operations_research::sat::ConstraintProto & constraints(int index) const
static int64_t GCD64(int64_t x, int64_t y)
::operations_research::sat::ConstraintProto * add_constraints()
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)
const ::operations_research::sat::CpObjectiveProto & objective() const
void add_domain(::PROTOBUF_NAMESPACE_ID::int64 value)
::PROTOBUF_NAMESPACE_ID::int64 coeffs(int index) const
void MarkVariableAsRemoved(int ref)
std::vector< absl::flat_hash_set< int > > var_to_ub_only_constraints
bool DomainIsEmpty(int ref) const
Domain RelaxIfTooComplex() const
If NumIntervals() is too large, this return a superset of the domain.
ABSL_MUST_USE_RESULT bool IntersectDomainWith(int ref, const Domain &domain, bool *domain_modified=nullptr)
Domain IntersectionWith(const Domain &domain) const
Returns the intersection of D and domain.
Domain MultiplicationBy(int64_t coeff, bool *exact=nullptr) const
Returns {x ∈ Int64, ∃ e ∈ D, x = e * coeff}.
int constraints_size() const
bool VariableWithCostIsUniqueAndRemovable(int ref) const
ABSL_MUST_USE_RESULT bool NotifyThatModelIsUnsat(const std::string &message="")
int ClassSize(int x) const
#define CHECK_EQ(val1, val2)
std::vector< int > UsedIntervals(const ConstraintProto &ct)
bool SubstituteVariableInObjective(int var_in_equality, int64_t coeff_in_equality, const ConstraintProto &equality, std::vector< int > *new_vars_in_objective=nullptr)
Domain AdditionWith(const Domain &domain) const
Returns {x ∈ Int64, ∃ a ∈ D, ∃ b ∈ domain, x = a + b}.
bool IsIncludedIn(const Domain &domain) const
Returns true iff D is included in the given domain.
bool ModelIsExpanded() const
bool DomainContains(int ref, int64_t value) const
#define DCHECK(condition)
bool LiteralIsTrue(int lit) const
We call domain any subset of Int64 = [kint64min, kint64max].
int Get(PresolveContext *context) const
void AddImplication(int a, int b)
void FillDomainInProto(const Domain &domain, ProtoWithDomain *proto)
void UpdateNewConstraintsVariableUsage()
int64_t StartMax(int ct_ref) const
bool Contains(int64_t value) const
Returns true iff value is in Domain.
bool LoggingIsEnabled() const
#define DCHECK_EQ(val1, val2)
Domain DomainSuperSetOf(const LinearExpressionProto &expr) const
std::vector< absl::flat_hash_set< int > > var_to_lb_only_constraints
void AddImplyInDomain(int b, int x, const Domain &domain)
int GetOrCreateReifiedPrecedenceLiteral(int time_i, int time_j, int active_i, int active_j)
int GetVariableRepresentative(int ref) const
bool StoreLiteralImpliesVarEqValue(int literal, int var, int64_t value)
Collection of objects used to extend the Constraint Solver library.
bool IsFixed(int ref) const
::operations_research::sat::CpObjectiveProto * mutable_objective()
int64_t SizeMin(int ct_ref) const
bool ExploitExactlyOneInObjective(absl::Span< const int > exactly_one)
bool IntervalIsConstant(int ct_ref) const
const ::operations_research::sat::IntervalConstraintProto & interval() const
void RemoveAllVariablesFromAffineRelationConstraint()
std::string IntervalDebugString(int ct_ref) const
::PROTOBUF_NAMESPACE_ID::int32 vars(int index) const
bool RefIsPositive(int ref)
constexpr int kObjectiveConstraint
bool LiteralIsFalse(int lit) const
bool TryAdd(int x, int y, int64_t coeff, int64_t offset)
ABSL_MUST_USE_RESULT bool SetLiteralToTrue(int lit)
#define VLOG_IS_ON(verboselevel)
int GetOrCreateVarValueEncoding(int ref, int64_t value)
void RemoveVariableFromObjective(int var)
::PROTOBUF_NAMESPACE_ID::int32 vars(int index) const
int NumEquivRelations() const
GurobiMPCallbackContext * context
int NumAffineRelations() const
void InsertVarValueEncoding(int literal, int ref, int64_t value)
double scaling_factor() const
Domain ReadDomainFromProto(const ProtoWithDomain &proto)
bool IsEmpty() const
Returns true if this is the empty set.
AffineRelation::Relation GetAffineRelation(int ref) const
#define CHECK_NE(val1, val2)
int GetLiteralRepresentative(int ref) const
#define DCHECK_LT(val1, val2)
ABSL_MUST_USE_RESULT bool CanonicalizeObjective()