33 return context->GetLiteralRepresentative(ref_);
37 return context->GetVariableRepresentative(ref_);
52 if (!constant_to_ref_.contains(cst)) {
59 return constant_to_ref_[cst].Get(
this);
65 ct->add_enforcement_literal(
a);
66 ct->mutable_bool_and()->add_literals(
b);
94 return domains[
var].Min() >= 0 && domains[
var].Max() <= 1;
100 return domains[lit].Min() == 1;
109 return domains[lit].Max() == 0;
135 int64_t result = expr.
offset();
136 for (
int i = 0; i < expr.
vars_size(); ++i) {
148 int64_t result = expr.
offset();
149 for (
int i = 0; i < expr.
vars_size(); ++i) {
161 for (
int i = 0; i < expr.
vars_size(); ++i) {
168 int64_t result = expr.
offset();
169 for (
int i = 0; i < expr.
vars_size(); ++i) {
170 if (expr.
coeffs(i) == 0)
continue;
179 for (
int i = 0; i < expr.
vars_size(); ++i) {
188 if (expr.
vars().size() != 1)
return false;
194 const int ref = expr.
vars(0);
206 const int ref = expr.
vars(0);
228 if (!
proto.enforcement_literal().empty())
return false;
237 return absl::StrCat(
"interval_", ct_ref,
"(",
StartMin(ct_ref),
"..",
243 return absl::StrCat(
"interval_", ct_ref,
"(lit=",
literal,
", ",
247 return absl::StrCat(
"interval_", ct_ref,
"(lit=",
literal,
", ",
252 return absl::StrCat(
"interval_", ct_ref,
"(",
StartMin(ct_ref),
" --(",
255 return absl::StrCat(
"interval_", ct_ref,
"(",
StartMin(ct_ref),
" --(",
299bool PresolveContext::VariableIsNotRepresentativeOfEquivalenceClass(
315 return VariableIsNotRepresentativeOfEquivalenceClass(
var) &&
332 return VariableIsNotRepresentativeOfEquivalenceClass(
var) &&
334 var_to_constraints_[
var].size() == 2;
352 return var_to_constraints_[
PositiveRef(ref)].empty();
364 if (
IsFixed(ref))
return false;
365 if (!removed_variables_.contains(
PositiveRef(ref)))
return false;
366 if (!var_to_constraints_[
PositiveRef(ref)].empty()) {
368 " was removed, yet it appears in some constraints!");
371 for (
const int c : var_to_constraints_[
PositiveRef(ref)]) {
373 logger_,
"constraint #", c,
" : ",
384 return var_to_num_linear1_[
var] == var_to_constraints_[
var].size() ||
386 var_to_num_linear1_[
var] + 1 == var_to_constraints_[
var].size());
392 result = domains[ref];
403 return domains[ref].Contains(
value);
407 int64_t
value)
const {
417 int ref,
const Domain& domain,
bool* domain_modified) {
422 if (domains[
var].IsIncludedIn(domain)) {
425 domains[
var] = domains[
var].IntersectionWith(domain);
428 if (domains[
var].IsIncludedIn(temp)) {
431 domains[
var] = domains[
var].IntersectionWith(temp);
434 if (domain_modified !=
nullptr) {
435 *domain_modified =
true;
438 if (domains[
var].IsEmpty()) {
455 bool* domain_modified) {
456 if (expr.
vars().empty()) {
464 if (expr.
vars().size() == 1) {
487 if (
ct.constraint_case() ==
488 ConstraintProto::ConstraintCase::CONSTRAINT_NOT_SET) {
491 for (
const int literal :
ct.enforcement_literal()) {
499 bool contains_one_free_literal =
false;
500 for (
const int literal :
ct.enforcement_literal()) {
504 return contains_one_free_literal;
511 stats_by_rule_name_[
name] += num_times;
517 const int old_var = constraint_to_linear1_var_[c];
519 var_to_num_linear1_[old_var]--;
521 if (
ct.constraint_case() == ConstraintProto::ConstraintCase::kLinear &&
522 ct.linear().vars().size() == 1) {
524 constraint_to_linear1_var_[c] =
var;
525 var_to_num_linear1_[
var]++;
529void PresolveContext::AddVariableUsage(
int c) {
533 for (
const int v : constraint_to_vars_[c]) {
535 var_to_constraints_[v].insert(c);
537 for (
const int i : constraint_to_intervals_[c]) interval_usage_[i]++;
538 UpdateLinear1Usage(
ct, c);
542 if (is_unsat_)
return;
547 for (
const int i : constraint_to_intervals_[c]) interval_usage_[i]--;
549 for (
const int i : constraint_to_intervals_[c]) interval_usage_[i]++;
554 const std::vector<int>& old_usage = constraint_to_vars_[c];
555 const int old_size = old_usage.size();
557 for (
const int var : tmp_new_usage_) {
559 while (i < old_size && old_usage[i] <
var) {
560 var_to_constraints_[old_usage[i]].erase(c);
563 if (i < old_size && old_usage[i] ==
var) {
566 var_to_constraints_[
var].insert(c);
569 for (; i < old_size; ++i) var_to_constraints_[old_usage[i]].erase(c);
570 constraint_to_vars_[c] = tmp_new_usage_;
572 UpdateLinear1Usage(
ct, c);
580 if (is_unsat_)
return;
581 const int old_size = constraint_to_vars_.size();
584 constraint_to_vars_.resize(new_size);
585 constraint_to_linear1_var_.resize(new_size, -1);
586 constraint_to_intervals_.resize(new_size);
587 interval_usage_.resize(new_size);
588 for (
int c = old_size; c < new_size; ++c) {
595 if (is_unsat_)
return true;
597 LOG(
INFO) <<
"Wrong constraint_to_vars size!";
600 for (
int c = 0; c < constraint_to_vars_.size(); ++c) {
601 if (constraint_to_vars_[c] !=
603 LOG(
INFO) <<
"Wrong variables usage for constraint: \n"
605 <<
"old_size: " << constraint_to_vars_[c].size();
609 int num_in_objective = 0;
610 for (
int v = 0; v < var_to_constraints_.size(); ++v) {
613 if (!objective_map_.contains(v)) {
615 <<
" is marked as part of the objective but isn't.";
620 if (num_in_objective != objective_map_.size()) {
621 LOG(
INFO) <<
"Not all variables are marked as part of the objective";
638bool PresolveContext::AddRelation(
int x,
int y, int64_t c, int64_t o,
642 if (std::abs(c) != 1)
return repo->
TryAdd(x, y, c, o);
659 bool allow_rep_x = m_x < m_y;
660 bool allow_rep_y = m_y < m_x;
667 if (allow_rep_x && allow_rep_y) {
677 return repo->
TryAdd(x, y, c, o, allow_rep_x, allow_rep_y);
691 if (constant_to_ref_.contains(
min)) {
692 const int rep = constant_to_ref_[
min].Get(
this);
695 AddRelation(
var, rep, 1, 0, &var_equiv_relations_);
732 for (
auto& ref_map : var_to_constraints_) {
758 if (affine_relations_.
ClassSize(rep) == 1 &&
759 var_equiv_relations_.
ClassSize(rep) == 1) {
783 std::vector<std::pair<int, double>> terms;
784 for (
int i = 0; i < objective.vars_size(); ++i) {
786 terms.push_back({objective.vars(i), objective.coeffs(i)});
788 const double offset = objective.offset();
789 const bool maximize = objective.maximize();
799 int64_t mod, int64_t rhs) {
803 const int64_t gcd = std::gcd(
coeff, mod);
805 if (rhs % gcd != 0) {
807 absl::StrCat(
"Infeasible ",
coeff,
" * X = ", rhs,
" % ", mod));
815 if (std::abs(mod) == 1)
return true;
833 "Empty domain in CanonicalizeAffineVariable()");
849 const int64_t min_value = new_domain.
Min();
860 bool debug_no_recursion) {
862 if (is_unsat_)
return false;
871 if (lhs % std::abs(
coeff) != 0) {
904 const int64_t unique_value = -
b /
a;
941 if (std::abs(
a) > 1 && std::abs(
b) > 1) {
957 if (std::abs(
a) == 1) {
978 y,
DomainOf(x).AdditionWith(
Domain(-o)).InverseMultiplicationBy(c))) {
983 DomainOf(y).ContinuousMultiplicationBy(c).AdditionWith(
Domain(o)))) {
996 CHECK(!debug_no_recursion);
1002 CHECK(AddRelation(x, y, c, o, &affine_relations_));
1003 if ((c == 1 || c == -1) && o == 0) {
1004 CHECK(AddRelation(x, y, c, o, &var_equiv_relations_));
1033 if (is_unsat_)
return false;
1042 if (ref_a == ref_b)
return true;
1056 const auto insert_status = abs_relations_.insert(
1058 if (!insert_status.second) {
1060 const int candidate = insert_status.first->second.Get(
this);
1061 if (removed_variables_.contains(candidate)) {
1071 auto it = abs_relations_.find(target_ref);
1072 if (it == abs_relations_.end())
return false;
1079 const int candidate = it->second.Get(
this);
1080 if (removed_variables_.contains(candidate)) {
1081 abs_relations_.erase(it);
1110 DCHECK_NE(positive_possible, negative_possible);
1153 for (
int i = domains.size(); i < working_model->variables_size(); ++i) {
1155 if (domains.back().IsEmpty()) {
1162 var_to_constraints_.resize(domains.size());
1163 var_to_num_linear1_.resize(domains.size());
1171 const int64_t var_min =
MinOf(
var);
1172 const int64_t var_max =
MaxOf(
var);
1174 if (is_unsat_)
return;
1176 absl::flat_hash_map<int64_t, SavedLiteral>& var_map = encoding_[
var];
1179 auto min_it = var_map.find(var_min);
1180 if (min_it != var_map.end()) {
1181 const int old_var =
PositiveRef(min_it->second.Get(
this));
1182 if (removed_variables_.contains(old_var)) {
1183 var_map.erase(min_it);
1184 min_it = var_map.end();
1189 auto max_it = var_map.find(var_max);
1190 if (max_it != var_map.end()) {
1191 const int old_var =
PositiveRef(max_it->second.Get(
this));
1192 if (removed_variables_.contains(old_var)) {
1193 var_map.erase(max_it);
1194 max_it = var_map.end();
1201 if (min_it != var_map.end() && max_it != var_map.end()) {
1202 min_literal = min_it->second.Get(
this);
1203 max_literal = max_it->second.Get(
this);
1204 if (min_literal !=
NegatedRef(max_literal)) {
1207 if (is_unsat_)
return;
1212 }
else if (min_it != var_map.end() && max_it == var_map.end()) {
1214 min_literal = min_it->second.Get(
this);
1217 }
else if (min_it == var_map.end() && max_it != var_map.end()) {
1219 max_literal = max_it->second.Get(
this);
1246 var_max - var_min, var_min);
1249 var_min - var_max, var_max);
1254void PresolveContext::InsertVarValueEncodingInternal(
int literal,
int var,
1256 bool add_constraints) {
1260 absl::flat_hash_map<int64_t, SavedLiteral>& var_map = encoding_[
var];
1266 const auto [it, inserted] =
1269 const int previous_literal = it->second.Get(
this);
1278 if (
literal != previous_literal) {
1280 "variables: merge equivalent var value encoding literals");
1293 <<
") == " <<
value;
1296 if (add_constraints) {
1304bool PresolveContext::InsertHalfVarValueEncoding(
int literal,
int var,
1305 int64_t
value,
bool imply_eq) {
1306 if (is_unsat_)
return false;
1313 if (!direct_set.insert(
literal).second)
return false;
1316 << (imply_eq ?
") == " :
") != ") <<
value;
1323 for (
const int other : other_set) {
1328 InsertVarValueEncodingInternal(imply_eq_literal,
var,
value,
1336bool PresolveContext::CanonicalizeEncoding(
int* ref, int64_t*
value) {
1338 if ((*
value - r.offset) % r.coeff != 0)
return false;
1339 *ref = r.representative;
1346 if (!CanonicalizeEncoding(&ref, &
value)) {
1350 InsertVarValueEncodingInternal(
literal, ref,
value,
true);
1356 if (!CanonicalizeEncoding(&
var, &
value))
return false;
1363 if (!CanonicalizeEncoding(&
var, &
value))
return false;
1371 if (!CanonicalizeEncoding(&ref, &
value))
return false;
1372 const absl::flat_hash_map<int64_t, SavedLiteral>& var_map = encoding_[ref];
1373 const auto it = var_map.find(
value);
1374 if (it != var_map.end()) {
1376 *
literal = it->second.Get(
this);
1385 const int64_t size = domains[
var].Size();
1386 if (size <= 2)
return true;
1387 const auto& it = encoding_.find(
var);
1388 return it == encoding_.end() ? false : size <= it->second.size();
1393 if (
IsFixed(expr))
return true;
1402 const int var = ref;
1405 if (!domains[
var].Contains(
value)) {
1410 absl::flat_hash_map<int64_t, SavedLiteral>& var_map = encoding_[
var];
1411 auto it = var_map.find(
value);
1412 if (it != var_map.end()) {
1413 const int lit = it->second.Get(
this);
1417 var_map.erase(
value);
1424 if (domains[
var].Size() == 1) {
1427 return true_literal;
1431 const int64_t var_min =
MinOf(
var);
1432 const int64_t var_max =
MaxOf(
var);
1433 if (domains[
var].Size() == 2) {
1435 const int64_t other_value =
value == var_min ? var_max : var_min;
1436 auto other_it = var_map.find(other_value);
1437 if (other_it != var_map.end()) {
1442 var_map.erase(other_value);
1451 if (var_min == 0 && var_max == 1) {
1491 objective_offset_ = obj.
offset();
1493 if (objective_scaling_factor_ == 0.0) {
1494 objective_scaling_factor_ = 1.0;
1499 if (objective_integer_scaling_factor_ == 0) {
1500 objective_integer_scaling_factor_ = 1;
1503 if (!obj.
domain().empty()) {
1506 objective_domain_is_constraining_ =
true;
1509 objective_domain_is_constraining_ =
false;
1516 objective_overflow_detection_ = 0;
1518 objective_map_.clear();
1519 for (
int i = 0; i < obj.
vars_size(); ++i) {
1520 const int ref = obj.
vars(i);
1521 const int64_t var_max_magnitude =
1526 if (var_max_magnitude == 0)
continue;
1529 objective_overflow_detection_ += var_max_magnitude * std::abs(
coeff);
1533 if (objective_map_[
var] == 0) {
1534 objective_map_.erase(
var);
1543 int64_t offset_change = 0;
1549 tmp_entries_.clear();
1550 for (
const auto& entry : objective_map_) {
1551 tmp_entries_.push_back(entry);
1557 for (
const auto& entry : tmp_entries_) {
1558 const int var = entry.first;
1559 const auto it = objective_map_.find(
var);
1560 if (it == objective_map_.end())
continue;
1561 const int64_t
coeff = it->second;
1568 var_to_constraints_[
var].size() == 1 &&
1585 objective_map_.erase(
var);
1592 objective_map_.erase(
var);
1601 if (new_coeff == 0) {
1614 Domain implied_domain(0);
1618 tmp_entries_.clear();
1619 for (
const auto& entry : objective_map_) {
1620 tmp_entries_.push_back(entry);
1622 std::sort(tmp_entries_.begin(), tmp_entries_.end());
1623 for (
const auto& entry : tmp_entries_) {
1624 const int var = entry.first;
1625 const int64_t
coeff = entry.second;
1638 if (simplify_domain) {
1644 objective_offset_ += offset_change;
1645 objective_integer_offset_ +=
1646 offset_change * objective_integer_scaling_factor_;
1650 for (
auto& entry : objective_map_) {
1651 entry.second /= gcd;
1654 objective_offset_ /=
static_cast<double>(gcd);
1655 objective_scaling_factor_ *=
static_cast<double>(gcd);
1656 objective_integer_scaling_factor_ *= gcd;
1659 if (objective_domain_.
IsEmpty())
return false;
1664 objective_domain_is_constraining_ =
1667 objective_domain_.
Max()))
1673 objective_map_.erase(
var);
1678 int64_t& map_ref = objective_map_[
var];
1681 objective_map_.erase(
var);
1690 objective_offset_ +=
static_cast<double>(
value);
1691 objective_integer_offset_ +=
value * objective_integer_scaling_factor_;
1696 int var_in_equality, int64_t coeff_in_equality,
1697 const ConstraintProto& equality, std::vector<int>* new_vars_in_objective) {
1701 if (new_vars_in_objective !=
nullptr) new_vars_in_objective->clear();
1705 const int64_t coeff_in_objective =
1708 CHECK_EQ(coeff_in_objective % coeff_in_equality, 0);
1710 const int64_t multiplier = coeff_in_objective / coeff_in_equality;
1714 for (
int i = 0; i < equality.
linear().vars().size(); ++i) {
1721 const int64_t new_value =
1723 objective_overflow_detection_ -
1724 std::abs(coeff_in_equality) *
1726 std::abs(
MaxOf(var_in_equality))));
1728 objective_overflow_detection_ = new_value;
1740 int64_t temp =
CapProd(offset.
Min(), objective_integer_scaling_factor_);
1743 temp =
CapAdd(temp, objective_integer_offset_);
1749 for (
int i = 0; i < equality.
linear().vars().size(); ++i) {
1756 if (
var == var_in_equality)
continue;
1758 int64_t& map_ref = objective_map_[
var];
1759 if (map_ref == 0 && new_vars_in_objective !=
nullptr) {
1760 new_vars_in_objective->push_back(
var);
1762 map_ref -=
coeff * multiplier;
1765 objective_map_.erase(
var);
1772 objective_map_.erase(var_in_equality);
1776 objective_offset_ +=
static_cast<double>(offset.
Min());
1777 objective_integer_offset_ += offset.
Min() * objective_integer_scaling_factor_;
1783 objective_domain_is_constraining_ =
true;
1785 if (objective_domain_.
IsEmpty()) {
1792 absl::Span<const int> exactly_one) {
1793 if (objective_map_.empty())
return false;
1796 for (
const int ref : exactly_one) {
1797 const auto it = objective_map_.find(
PositiveRef(ref));
1798 if (it == objective_map_.end())
return false;
1800 const int64_t
coeff = it->second;
1809 int64_t offset = min_coeff;
1810 for (
const int ref : exactly_one) {
1812 int64_t& map_ref = objective_map_.at(
var);
1814 map_ref -= min_coeff;
1816 objective_map_.erase(
var);
1824 map_ref += min_coeff;
1826 objective_map_.erase(
var);
1829 offset -= min_coeff;
1835 objective_offset_ += offset;
1836 objective_integer_offset_ += offset * objective_integer_scaling_factor_;
1845 std::vector<std::pair<int, int64_t>> entries;
1846 for (
const auto& entry : objective_map_) {
1847 entries.push_back(entry);
1849 std::sort(entries.begin(), entries.end());
1855 if (objective_integer_scaling_factor_ == 1) {
1863 for (
const auto& entry : entries) {
1864 mutable_obj->
add_vars(entry.first);
1877 int active_i,
int active_j) {
1883 const std::tuple<int, int64_t, int, int64_t, int64_t, int, int> key =
1885 const auto& it = reified_precedences_cache_.find(key);
1886 if (it != reified_precedences_cache_.end())
return it->second;
1889 reified_precedences_cache_[key] = result;
1903 const int64_t offset =
1942 const auto& rev_it = reified_precedences_cache_.find(
1944 if (rev_it != reified_precedences_cache_.end()) {
1947 bool_or->add_literals(rev_it->second);
1955std::tuple<int, int64_t, int, int64_t, int64_t, int, int>
1958 int active_i,
int active_j) {
1961 const int64_t coeff_i =
IsFixed(time_i) ? 0 : time_i.
coeffs(0);
1964 const int64_t coeff_j =
IsFixed(time_j) ? 0 : time_j.
coeffs(0);
1965 const int64_t offset =
1970 if (active_j < active_i)
std::swap(active_i, active_j);
1971 return std::make_tuple(var_i, coeff_i, var_j, coeff_j, offset, active_i,
1976 reified_precedences_cache_.clear();
1983 " affine relations were detected.");
1984 std::map<std::string, int> sorted_rules(stats_by_rule_name_.begin(),
1985 stats_by_rule_name_.end());
1986 for (
const auto& entry : sorted_rules) {
1987 if (entry.second == 1) {
1988 SOLVER_LOG(logger_,
" - rule '", entry.first,
"' was applied 1 time.");
1990 SOLVER_LOG(logger_,
" - rule '", entry.first,
"' was applied ",
1991 entry.second,
" times.");
1997 if (
context->ModelIsUnsat())
return false;
2000 context->WriteVariableDomainsToProto();
2019 *local_param =
context->params();
2020 local_param->set_use_implied_bounds(
false);
2026 encoder->DisableImplicationBetweenLiteral();
2037 if (mapping->ConstraintIsAlreadyLoaded(&
ct))
continue;
2039 if (sat_solver->IsModelUnsat()) {
2040 return context->NotifyThatModelIsUnsat(absl::StrCat(
2041 "after loading constraint during probing ",
ct.ShortDebugString()));
2044 encoder->AddAllImplicationsBetweenAssociatedLiterals();
2045 if (!sat_solver->Propagate()) {
2046 return context->NotifyThatModelIsUnsat(
2047 "during probing initial propagation");
#define DCHECK_LE(val1, val2)
#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.
bool Contains(int64_t value) const
Returns true iff value is in Domain.
Domain ContinuousMultiplicationBy(int64_t coeff) const
Returns a superset of MultiplicationBy() to avoid the explosion in the representation size.
int64_t FixedValue() const
Returns the value of a fixed 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}.
bool IsFixed() const
Returns true iff the domain is reduced to a single value.
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)
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
void add_literals(int32_t value)
const ::operations_research::sat::IntervalConstraintProto & interval() const
const ::operations_research::sat::LinearConstraintProto & linear() const
int32_t enforcement_literal(int index) const
::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t > * mutable_enforcement_literal()
::operations_research::sat::LinearConstraintProto * mutable_linear()
void add_enforcement_literal(int32_t value)
::operations_research::sat::BoolArgumentProto * mutable_bool_or()
const ::operations_research::sat::CpObjectiveProto & objective() const
const ::operations_research::sat::IntegerVariableProto & variables(int index) const
bool has_floating_point_objective() const
bool has_objective() const
void clear_floating_point_objective()
::operations_research::sat::IntegerVariableProto * mutable_variables(int index)
int variables_size() const
::operations_research::sat::ConstraintProto * add_constraints()
const ::operations_research::sat::FloatObjectiveProto & floating_point_objective() const
::operations_research::sat::IntegerVariableProto * add_variables()
::operations_research::sat::CpObjectiveProto * mutable_objective()
int constraints_size() const
const ::operations_research::sat::ConstraintProto & constraints(int index) const
void add_coeffs(int64_t value)
void add_vars(int32_t value)
int64_t domain(int index) const
int32_t vars(int index) const
int64_t coeffs(int index) const
double scaling_factor() const
void set_integer_scaling_factor(int64_t value)
int64_t integer_scaling_factor() const
void set_offset(double value)
void set_integer_offset(int64_t value)
int64_t integer_offset() const
void set_scaling_factor(double value)
void add_domain(int64_t value)
::PROTOBUF_NAMESPACE_ID::RepeatedField< int64_t > * mutable_coeffs()
void add_coeffs(int64_t value)
void add_vars(int32_t value)
int32_t vars(int index) const
int64_t coeffs(int index) const
::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t > * mutable_vars()
void add_domain(int64_t value)
int32_t vars(int index) const
int64_t coeffs(int index) const
Class that owns everything related to a particular optimization model.
void Register(T *non_owned_class)
Register a non-owned class that will be "singleton" in the model.
T * GetOrCreate()
Returns an object of type T that is unique to this model (like a "local" singleton).
bool VariableIsRemovable(int ref) const
int64_t MaxOf(int ref) const
bool CanonicalizeAffineVariable(int ref, int64_t coeff, int64_t mod, int64_t rhs)
SparseBitset< int64_t > modified_domains
void AddToObjectiveOffset(int64_t value)
bool ExpressionIsALiteral(const LinearExpressionProto &expr, int *literal=nullptr) const
bool IsFullyEncoded(int ref) const
bool StoreAbsRelation(int target_ref, int ref)
bool VariableWithCostIsUnique(int ref) const
bool ConstraintIsInactive(int ct_index) const
bool ConstraintVariableUsageIsConsistent()
void AddImplication(int a, int b)
void AddToObjective(int var, int64_t value)
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)
int GetOrCreateReifiedPrecedenceLiteral(const LinearExpressionProto &time_i, const LinearExpressionProto &time_j, int active_i, int active_j)
ABSL_MUST_USE_RESULT bool CanonicalizeObjective(bool simplify_domain=true)
bool StoreBooleanEqualityRelation(int ref_a, int ref_b)
int64_t StartMin(int ct_ref) const
bool VariableWithCostIsUniqueAndRemovable(int ref) const
void WriteObjectiveToProto() const
bool ExpressionIsSingleVariable(const LinearExpressionProto &expr) const
int GetLiteralRepresentative(int ref) const
ABSL_MUST_USE_RESULT bool SetLiteralToTrue(int lit)
int GetOrCreateAffineValueEncoding(const LinearExpressionProto &expr, int64_t value)
ABSL_MUST_USE_RESULT bool ScaleFloatingPointObjective()
std::vector< absl::flat_hash_set< int > > var_to_ub_only_constraints
ABSL_MUST_USE_RESULT 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)
int64_t EndMin(int ct_ref) const
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 InsertVarValueEncoding(int literal, int ref, int64_t value)
void WriteVariableDomainsToProto() const
bool DomainIsEmpty(int ref) const
void CanonicalizeVariable(int ref)
void CanonicalizeDomainOfSizeTwo(int var)
int64_t StartMax(int ct_ref) const
int64_t FixedValue(int ref) const
bool LiteralIsTrue(int lit) const
std::tuple< int, int64_t, int, int64_t, int64_t, int, int > GetReifiedPrecedenceKey(const LinearExpressionProto &time_i, const LinearExpressionProto &time_j, int active_i, int active_j)
CpModelProto * working_model
bool HasVarValueEncoding(int ref, int64_t value, int *literal=nullptr)
bool IntervalIsConstant(int ct_ref) const
bool DomainContains(int ref, int64_t value) const
bool LiteralIsFalse(int lit) const
void UpdateRuleStats(const std::string &name, int num_times=1)
void RemoveAllVariablesFromAffineRelationConstraint()
AffineRelation::Relation GetAffineRelation(int ref) const
void RemoveVariableFromObjective(int var)
bool VariableIsNotUsedAnymore(int ref) const
void UpdateConstraintVariableUsage(int c)
bool keep_all_feasible_solutions
bool IsFixed(int ref) const
int NumAffineRelations() const
bool StoreAffineRelation(int ref_x, int ref_y, int64_t coeff, int64_t offset, bool debug_no_recursion=false)
std::string IntervalDebugString(int ct_ref) const
ABSL_MUST_USE_RESULT bool SetLiteralToFalse(int lit)
int LiteralForExpressionMax(const LinearExpressionProto &expr) const
std::string RefDebugString(int ref) const
int64_t EndMax(int ct_ref) const
bool ConstraintIsOptional(int ct_ref) const
int GetOrCreateConstantVar(int64_t cst)
bool ExpressionIsAffineBoolean(const LinearExpressionProto &expr) const
int64_t SizeMax(int ct_ref) const
bool ExploitExactlyOneInObjective(absl::Span< const int > exactly_one)
void ClearPrecedenceCache()
Domain DomainSuperSetOf(const LinearExpressionProto &expr) const
void ReadObjectiveFromProto()
int64_t SizeMin(int ct_ref) const
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 VariableIsOnlyUsedInEncodingAndMaybeInObjective(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
CpModelProto const * model_proto
GurobiMPCallbackContext * context
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)
bool ScaleAndSetObjective(const SatParameters ¶ms, const std::vector< std::pair< int, double > > &objective, double objective_offset, bool maximize, CpModelProto *cp_model, SolverLogger *logger)
void LoadVariables(const CpModelProto &model_proto, bool view_all_booleans_as_integers, Model *m)
bool LoadConstraint(const ConstraintProto &ct, Model *m)
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)
bool ExpressionIsAffine(const LinearExpressionProto &expr)
Domain ReadDomainFromProto(const ProtoWithDomain &proto)
int64_t ProductWithModularInverse(int64_t coeff, int64_t mod, int64_t rhs)
bool LoadModelForProbing(PresolveContext *context, Model *local_model)
constexpr int kObjectiveConstraint
void ExtractEncoding(const CpModelProto &model_proto, Model *m)
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)