14#ifndef ORTOOLS_SAT_INTEGER_H_
15#define ORTOOLS_SAT_INTEGER_H_
29#include "absl/base/attributes.h"
30#include "absl/container/btree_map.h"
31#include "absl/container/flat_hash_map.h"
32#include "absl/container/inlined_vector.h"
33#include "absl/log/check.h"
34#include "absl/strings/str_cat.h"
35#include "absl/types/span.h"
56 absl::InlinedVector<std::pair<IntegerVariable, IntegerValue>, 2>;
70 return absl::StrCat(
"(lit(",
literal.Index().value(),
") * ",
109 : sat_solver_(model->GetOrCreate<
SatSolver>()),
110 trail_(model->GetOrCreate<
Trail>()),
115 num_created_variables_(0) {}
122 VLOG(1) <<
"#variables created = " << num_created_variables_;
162 IntegerVariable var)
const;
164 IntegerVariable var)
const;
216 IntegerValue value)
const;
230 if (lit.
Index() >= reverse_encoding_.size()) {
231 return empty_integer_literal_vector_;
233 return reverse_encoding_[lit];
239 if (lit.
Index() >= reverse_equality_encoding_.size()) {
240 return empty_integer_value_vector_;
242 return reverse_equality_encoding_[lit];
249 temp_associated_vars_.clear();
251 temp_associated_vars_.push_back(l.var);
254 temp_associated_vars_.push_back(var);
256 return temp_associated_vars_;
267 const IntegerVariable result = literal_view_[lit];
275 Literal lit, IntegerVariable* view =
nullptr,
276 bool* view_is_direct =
nullptr)
const;
287 IntegerValue* bound)
const;
289 IntegerValue* bound)
const;
294 DCHECK_EQ(0, sat_solver_->CurrentDecisionLevel());
296 Literal(sat_solver_->NewBooleanVariable(),
true);
297 literal_index_true_ = literal_true.
Index();
300 if (lrat_proof_handler_ !=
nullptr) {
301 clause_id = clause_id_generator_->GetNextId();
305 lrat_proof_handler_->AddInferredClause(clause_id, {literal_true}, {});
307 trail_->EnqueueWithUnitReason(clause_id, literal_true);
309 return Literal(literal_index_true_);
317 IntegerVariable var)
const;
335 void AddImplications(
336 const absl::btree_map<IntegerValue, Literal>& map,
337 absl::btree_map<IntegerValue, Literal>::const_iterator it,
347 bool add_implications_ =
true;
348 int64_t num_created_variables_ = 0;
366 absl::btree_map<IntegerValue, Literal>>
375 reverse_equality_encoding_;
378 mutable std::vector<IntegerVariable> temp_associated_vars_;
390 absl::flat_hash_map<std::pair<PositiveOnlyIndex, IntegerValue>,
Literal>
391 equality_to_associated_literal_;
395 absl::InlinedVector<ValueLiteralPair, 2>>
406 std::vector<IntegerValue> tmp_values_;
407 std::vector<ValueLiteralPair> tmp_encoding_;
410 mutable std::vector<ValueLiteralPair> partial_encoding_;
456 absl::Span<const IntegerVariable>
vars;
509 return *
this == o || *
this < o;
530 trail_(model->GetOrCreate<
Trail>()),
531 sat_solver_(model->GetOrCreate<
SatSolver>()),
532 time_limit_(model->GetOrCreate<
TimeLimit>()),
547 void Untrail(const
Trail& trail,
int literal_trail_index) final;
549 int64_t conflict_id) const final;
554 if (trail_->conflict_timestamp() != global_id_conflict_timestamp_) {
556 tmp_reason_.boolean_literals_at_false = trail_->FailingClause();
574 return IntegerVariable(var_lbs_.size());
590 IntegerValue upper_bound);
634 bool IsFixed(IntegerVariable
i)
const;
710 absl::Span<const IntegerValue> coeffs,
711 std::vector<IntegerLiteral>* reason)
const;
715 absl::Span<const IntegerValue> coeffs,
716 absl::Span<const IntegerVariable> vars,
717 std::vector<IntegerLiteral>* reason)
const;
721 absl::Span<const IntegerValue> coeffs,
722 std::vector<int>* trail_indices)
const;
746 return EnqueueInternal(i_lit,
false, {}, {});
750 absl::Span<const IntegerLiteral> integer_reason) {
751 return EnqueueInternal(i_lit,
false, literal_reason, integer_reason);
764 IntegerLiteral i_lit, absl::Span<const IntegerLiteral> integer_reason);
767 absl::Span<const IntegerLiteral> integer_reason);
777 std::vector<IntegerLiteral>* integer_reason);
788 absl::Span<const IntegerLiteral> integer_reason,
789 int trail_index_with_same_reason) {
790 return EnqueueInternal(i_lit,
false, literal_reason, integer_reason,
791 trail_index_with_same_reason);
798 const int trail_index = integer_trail_.size();
799 lazy_reasons_.push_back(
800 LazyReasonEntry{explainer, propagation_slack, i_lit, id, trail_index});
801 return EnqueueInternal(i_lit,
true, {}, {});
807 tmp_lazy_reason_boolean_literals_.clear();
808 return tmp_lazy_reason_boolean_literals_;
811 tmp_lazy_reason_integer_literals_.clear();
812 return tmp_lazy_reason_integer_literals_;
827 Literal literal, absl::Span<const Literal> literal_reason,
828 absl::Span<const IntegerLiteral> integer_reason);
831 Literal literal, absl::Span<const Literal> literal_reason,
832 absl::Span<const IntegerLiteral> integer_reason);
843 std::vector<Literal>* output)
const;
852 int64_t
timestamp()
const {
return num_enqueues_ + num_untrails_; }
862 watchers_.push_back(p);
866 return integer_trail_[integer_trail_index].var;
870 integer_trail_[integer_trail_index].var,
871 integer_trail_[integer_trail_index].bound);
874 int starting_integer_index) {
876 CHECK_LT(var, var_trail_index_.size());
877 int index = std::min(starting_integer_index, var_trail_index_[var]);
880 if (index <
static_cast<int>(var_lbs_.size()))
return -1;
881 CHECK_LT(index, integer_trail_.size());
882 CHECK_EQ(integer_trail_[index].var, var);
884 index = integer_trail_[index].prev_trail_index;
888 if (integer_trail_index < var_lbs_.size()) {
889 CHECK_EQ(integer_trail_[integer_trail_index].prev_trail_index, -1);
891 return integer_trail_[integer_trail_index].prev_trail_index;
894 CHECK_GE(integer_index, var_lbs_.size());
897 const auto& entry = extra_trail_info_[integer_index];
898 CHECK_NE(entry.assignment_level, 0);
906 absl::Span<const IntegerLiteral> integer_reason) {
909 std::vector<Literal>* conflict = trail_->MutableConflict();
910 if (new_conflict_resolution_) {
911 global_id_conflict_timestamp_ = trail_->conflict_timestamp();
915 tmp_literal_reason_.assign(literal_reason.begin(), literal_reason.end());
916 tmp_integer_reason_.assign(integer_reason.begin(), integer_reason.end());
917 tmp_reason_.boolean_literals_at_false = tmp_literal_reason_;
918 tmp_reason_.integer_literals = tmp_integer_reason_;
922 conflict->assign(literal_reason.begin(), literal_reason.end());
932 return var_trail_index_[var] < var_lbs_.size();
938 reversible_classes_.push_back(rev);
941 int Index()
const {
return integer_trail_.size(); }
952 std::vector<IntegerLiteral>* output)
const;
976 return !delayed_to_fix_->literal_to_fix.empty() ||
977 !delayed_to_fix_->integer_literal_to_fix.empty();
983 std::function<
bool(absl::Span<const Literal> clause,
984 absl::Span<const IntegerLiteral> integers)>
986 debug_checker_ = std::move(checker);
1008 absl::Span<const Literal> literal_reason,
1009 absl::Span<const IntegerLiteral> integer_reason);
1016 int bool_trail_index, ReasonIndex reason_index,
1017 int assignment_level);
1021 bool ReasonIsValid(absl::Span<const Literal> literal_reason,
1022 absl::Span<const IntegerLiteral> integer_reason);
1025 bool ReasonIsValid(
Literal lit, absl::Span<const Literal> literal_reason,
1026 absl::Span<const IntegerLiteral> integer_reason);
1028 absl::Span<const Literal> literal_reason,
1029 absl::Span<const IntegerLiteral> integer_reason);
1038 std::vector<Literal>* InitializeConflict(
1040 absl::Span<const Literal> literals_reason,
1041 absl::Span<const IntegerLiteral> bounds_reason);
1044 ABSL_MUST_USE_RESULT
bool EnqueueInternal(
1046 absl::Span<const Literal> literal_reason,
1047 absl::Span<const IntegerLiteral> integer_reason,
1048 int trail_index_with_same_reason = std::numeric_limits<int>::max());
1051 ABSL_MUST_USE_RESULT
bool EnqueueLiteralInternal(
1052 Literal literal,
bool use_lazy_reason,
1053 absl::Span<const Literal> literal_reason,
1054 absl::Span<const IntegerLiteral> integer_reason);
1059 ABSL_MUST_USE_RESULT
bool EnqueueAssociatedIntegerLiteral(
1063 void MergeReasonIntoInternal(std::vector<Literal>* output,
1064 int64_t conflict_id)
const;
1069 int FindLowestTrailIndexThatExplainBound(
IntegerLiteral i_lit)
const;
1074 void ComputeLazyReasonIfNeeded(ReasonIndex index)
const;
1081 absl::Span<const int> Dependencies(ReasonIndex index)
const;
1087 void AppendLiteralsReason(ReasonIndex index,
1088 std::vector<Literal>* output)
const;
1091 std::string DebugString();
1104 mutable int var_trail_index_cache_threshold_ = 0;
1106 var_trail_index_cache_;
1110 absl::flat_hash_map<IntegerValue, IntegerVariable> constant_map_;
1116 IntegerVariable var;
1117 int32_t prev_trail_index = -1;
1121 ReasonIndex reason_index = ReasonIndex(0);
1123 std::vector<TrailEntry> integer_trail_;
1128 struct ExtraTrailEntry {
1129 int32_t assignment_level;
1130 int32_t bool_trail_index;
1132 std::vector<ExtraTrailEntry> extra_trail_info_;
1134 struct LazyReasonEntry {
1135 LazyReasonInterface* explainer;
1136 IntegerValue propagation_slack;
1137 IntegerLiteral propagated_i_lit;
1139 int trail_index_at_propagation_time;
1145 void Explain(IntegerValue bound_to_explain, IntegerReason* reason)
const {
1146 DCHECK_LE(bound_to_explain, propagated_i_lit.bound);
1148 reason->slack = propagation_slack;
1149 reason->propagated_i_lit = propagated_i_lit;
1150 reason->index_at_propagation = trail_index_at_propagation_time;
1151 explainer->Explain(
id,
1157 void Explain(IntegerReason* reason)
const {
1158 Explain(propagated_i_lit.bound, reason);
1161 std::vector<int> lazy_reason_decision_levels_;
1162 util_intops::StrongVector<ReasonIndex, LazyReasonEntry> lazy_reasons_;
1166 std::vector<int> integer_search_levels_;
1169 std::vector<ReasonIndex> reason_decision_levels_;
1170 util_intops::StrongVector<ReasonIndex, int> literals_reason_starts_;
1171 std::vector<Literal> literals_reason_buffer_;
1176 util_intops::StrongVector<ReasonIndex, int> bounds_reason_starts_;
1177 mutable util_intops::StrongVector<ReasonIndex, int> cached_sizes_;
1178 std::vector<IntegerLiteral> bounds_reason_buffer_;
1179 mutable std::vector<int> trail_index_reason_buffer_;
1182 IntegerReason tmp_reason_;
1183 std::vector<Literal> tmp_lazy_reason_boolean_literals_;
1184 std::vector<IntegerLiteral> tmp_lazy_reason_integer_literals_;
1188 std::vector<Literal> tmp_boolean_literals_;
1189 std::vector<IntegerLiteral> tmp_integer_literals_;
1192 mutable IntegerReason tmp_lazy_reason_;
1193 mutable std::vector<Literal> lazy_reason_literals_;
1194 mutable std::vector<int> lazy_reason_trail_indices_;
1195 mutable std::vector<int> tmp_trail_indices_;
1196 mutable std::vector<IntegerValue> tmp_coeffs_;
1199 mutable bool has_dependency_ =
false;
1200 mutable std::vector<int> tmp_queue_;
1201 mutable std::vector<IntegerVariable> tmp_to_clear_;
1202 mutable util_intops::StrongVector<IntegerVariable, int>
1203 tmp_var_to_trail_index_in_queue_;
1204 mutable SparseBitset<BooleanVariable> added_variables_;
1207 struct RelaxHeapEntry {
1211 bool operator<(
const RelaxHeapEntry& o)
const {
return index < o.index; }
1213 mutable std::vector<RelaxHeapEntry> relax_heap_;
1214 mutable std::vector<int> tmp_indices_;
1217 mutable SparseBitset<IntegerVariable> tmp_marked_;
1220 std::vector<IntegerLiteral> tmp_cleaned_reason_;
1223 std::vector<ReasonIndex> boolean_trail_index_to_reason_index_;
1227 int first_level_without_full_propagation_ = -1;
1232 mutable int64_t last_conflict_id_ = -1;
1233 mutable bool info_is_valid_on_subsequent_last_level_expansion_ =
false;
1234 mutable util_intops::StrongVector<IntegerVariable, int>
1235 var_to_trail_index_at_lower_level_;
1236 mutable std::vector<int> tmp_seen_;
1237 mutable std::vector<IntegerVariable> to_clear_for_lower_level_;
1239 int64_t global_id_conflict_timestamp_ = 0;
1240 int64_t num_enqueues_ = 0;
1241 int64_t num_untrails_ = 0;
1242 int64_t num_level_zero_enqueues_ = 0;
1243 mutable int64_t num_decisions_to_break_loop_ = 0;
1245 std::vector<SparseBitset<IntegerVariable>*> watchers_;
1246 std::vector<ReversibleInterface*> reversible_classes_;
1248 mutable int64_t work_done_in_find_indices_ = 0;
1250 mutable Domain temp_domain_;
1251 DelayedRootLevelDeduction* delayed_to_fix_;
1252 IntegerDomains* domains_;
1253 IntegerEncoder* encoder_;
1255 SatSolver* sat_solver_;
1256 TimeLimit* time_limit_;
1257 const SatParameters& parameters_;
1259 bool new_conflict_resolution_ =
false;
1261 std::vector<Literal> tmp_literal_reason_;
1262 std::vector<IntegerLiteral> tmp_integer_reason_;
1267 absl::flat_hash_map<std::pair<LiteralIndex, IntegerVariable>, IntegerValue>
1270 std::function<bool(absl::Span<const Literal> clause,
1271 absl::Span<const IntegerLiteral> integers)>
1272 debug_checker_ =
nullptr;
1300 LOG(FATAL) <<
"Not implemented.";
1341 void Untrail(const
Trail& trail,
int literal_trail_index) final;
1370 void WatchLowerBound(IntegerVariable var,
int id,
int watch_index = -1);
1371 void WatchUpperBound(IntegerVariable var,
int id,
int watch_index = -1);
1428 bool_to_reset_on_backtrack_.push_back(is_in_dive);
1445 const std::function<
void(
const std::vector<IntegerVariable>&)> cb) {
1446 level_zero_modified_variable_callback_.push_back(cb);
1455 stop_propagation_callback_ = callback;
1476 void UpdateCallingNeeds(
Trail* trail);
1486 return id == o.id && watch_index == o.watch_index;
1490 literal_to_watcher_;
1493 std::vector<PropagatorInterface*> watchers_;
1494 SparseBitset<IntegerVariable> modified_vars_;
1497 SparseBitset<IntegerVariable> modified_vars_for_callback_;
1501 std::vector<std::deque<int>> queue_by_priority_;
1502 std::vector<bool> in_queue_;
1506 std::vector<bool> id_need_reversible_support_;
1507 std::vector<int> id_to_level_at_last_call_;
1508 RevVector<IdType, int> id_to_greatest_common_level_since_last_call_;
1509 std::vector<std::vector<ReversibleInterface*>> id_to_reversible_classes_;
1510 std::vector<std::vector<int*>> id_to_reversible_ints_;
1512 std::vector<std::vector<int>> id_to_watch_indices_;
1513 std::vector<int> id_to_priority_;
1514 std::vector<int> id_to_idempotence_;
1517 std::vector<int> propagator_ids_to_call_at_level_zero_;
1521 bool call_again_ =
false;
1523 std::vector<std::function<void(
const std::vector<IntegerVariable>&)>>
1524 level_zero_modified_variable_callback_;
1526 std::function<bool()> stop_propagation_callback_;
1528 std::vector<bool*> bool_to_reset_on_backtrack_;
1553 Literal l, IntegerVariable
i)
const {
1554 const auto it = conditional_lbs_.find({l.
Index(),
i});
1555 if (it != conditional_lbs_.end()) {
1556 return std::max(var_lbs_[
i], it->second);
1562 Literal l, AffineExpression expr)
const {
1568 Literal l, IntegerVariable
i)
const {
1579 IntegerVariable
i)
const {
1584 IntegerVariable
i)
const {
1599 IntegerValue result = 0;
1603 }
else if (expr.
coeffs[
i] > 0) {
1649 IntegerVariable var)
const {
1651 DCHECK_LT(var, integer_trail_.size());
1652 return integer_trail_[var.value()].bound;
1656 IntegerVariable var)
const {
1661 return integer_trail_[var.value()].bound ==
1680 IntegerValue result = 0;
1681 for (
int i = 0;
i < 2; ++
i) {
1690 LinearExpression2 expr)
const {
1691 expr.SimpleCanonicalization();
1692 IntegerValue result = 0;
1693 for (
int i = 0;
i < 2; ++
i) {
1694 if (expr.coeffs[
i] != 0) {
1708 if (l.
Index() >= literal_to_watcher_.size()) {
1709 literal_to_watcher_.resize(l.
Index().value() + 1);
1711 literal_to_watcher_[l].
push_back({id, watch_index});
1717 if (var.value() >= var_to_watcher_.size()) {
1718 var_to_watcher_.resize(var.value() + 1);
1725 const WatchData data = {id, watch_index};
1726 if (!var_to_watcher_[var].empty() && var_to_watcher_[var].back() == data) {
1754 return [=](
Model* model) {
1761 return [=](
Model* model) {
1763 ->GetOrCreateConstantIntegerVariable(IntegerValue(value));
1769 return [=](
Model* model) {
1772 IntegerValue(lb), IntegerValue(ub));
1778 return [=](
Model* model) {
1779 return model->
GetOrCreate<IntegerTrail>()->AddIntegerVariable(domain);
1787 auto* encoder = model->GetOrCreate<IntegerEncoder>();
1788 const IntegerVariable candidate = encoder->GetLiteralView(lit);
1791 IntegerVariable var;
1792 auto* integer_trail = model->GetOrCreate<
IntegerTrail>();
1794 if (assignment.LiteralIsTrue(lit)) {
1795 var = integer_trail->GetOrCreateConstantIntegerVariable(IntegerValue(1));
1796 }
else if (assignment.LiteralIsFalse(lit)) {
1797 var = integer_trail->GetOrCreateConstantIntegerVariable(IntegerValue(0));
1799 var = integer_trail->AddIntegerVariable(IntegerValue(0), IntegerValue(1));
1802 encoder->AssociateToIntegerEqualValue(lit, var, IntegerValue(1));
1810 return [=](
Model* model) {
1815inline std::function<int64_t(
const Model&)>
LowerBound(IntegerVariable v) {
1816 return [=](
const Model& model) {
1817 return model.Get<IntegerTrail>()->
LowerBound(v).value();
1821inline std::function<int64_t(
const Model&)>
UpperBound(IntegerVariable v) {
1822 return [=](
const Model& model) {
1823 return model.Get<IntegerTrail>()->
UpperBound(v).value();
1827inline std::function<bool(
const Model&)>
IsFixed(IntegerVariable v) {
1828 return [=](
const Model& model) {
1829 const IntegerTrail* trail = model.Get<IntegerTrail>();
1830 return trail->LowerBound(v) == trail->UpperBound(v);
1835inline std::function<int64_t(
const Model&)>
Value(IntegerVariable v) {
1836 return [=](
const Model& model) {
1837 const IntegerTrail* trail = model.Get<IntegerTrail>();
1838 CHECK_EQ(trail->LowerBound(v), trail->UpperBound(v)) << v;
1839 return trail->LowerBound(v).value();
1845 return [=](
Model* model) {
1846 if (!model->GetOrCreate<IntegerTrail>()->Enqueue(
1848 std::vector<Literal>(), std::vector<IntegerLiteral>())) {
1849 model->GetOrCreate<
SatSolver>()->NotifyThatModelIsUnsat();
1850 VLOG(1) <<
"Model trivially infeasible, variable " << v
1851 <<
" has upper bound " << model->Get(
UpperBound(v))
1852 <<
" and GreaterOrEqual() was called with a lower bound of "
1859 return [=](
Model* model) {
1862 std::vector<Literal>(), std::vector<IntegerLiteral>())) {
1863 model->GetOrCreate<
SatSolver>()->NotifyThatModelIsUnsat();
1864 VLOG(1) <<
"Model trivially infeasible, variable " << v
1865 <<
" has lower bound " << model->Get(
LowerBound(v))
1866 <<
" and LowerOrEqual() was called with an upper bound of " << ub;
1872inline std::function<void(
Model*)>
Equality(IntegerVariable v, int64_t value) {
1873 return [=](
Model* model) {
1886 absl::Span<const Literal> enforcement_literals, IntegerLiteral
i) {
1887 return [=](
Model* model) {
1888 auto* sat_solver = model->GetOrCreate<SatSolver>();
1890 if (
i.bound <= integer_trail->LowerBound(
i.var)) {
1892 }
else if (
i.bound > integer_trail->UpperBound(
i.var)) {
1894 std::vector<Literal> clause;
1895 for (
const Literal literal : enforcement_literals) {
1896 clause.push_back(literal.Negated());
1898 sat_solver->AddClauseDuringSearch(clause);
1903 std::vector<Literal> clause{encoder->GetOrCreateAssociatedLiteral(
i)};
1904 for (
const Literal literal : enforcement_literals) {
1905 clause.push_back(literal.Negated());
1907 sat_solver->AddClauseDuringSearch(clause);
1915 int64_t lb, int64_t ub) {
1916 return [=](
Model* model) {
1921 v, IntegerValue(lb))));
1936 IntegerVariable var) {
1937 return [=](
Model* model) {
1939 if (!encoder->VariableIsFullyEncoded(var)) {
1940 encoder->FullyEncodeVariable(var);
void ClearAndResize(IntegerType size)
int NumPropagators() const
void WatchUpperBound(AffineExpression e, int id)
bool Propagate(Trail *trail) final
void SetUntilNextBacktrack(bool *is_in_dive)
void RegisterReversibleInt(int id, int *rev)
void WatchAffineExpression(AffineExpression e, int id)
void NotifyThatPropagatorMayNotReachFixedPointInOnePass(int id)
void WatchLowerBound(IntegerValue, int)
void WatchLiteral(Literal l, int id, int watch_index=-1)
void WatchIntegerVariable(IntegerValue, int)
void WatchUpperBound(IntegerVariable var, int id, int watch_index=-1)
~GenericLiteralWatcher() final=default
void Untrail(const Trail &trail, int literal_trail_index) final
void WatchLowerBound(IntegerVariable var, int id, int watch_index=-1)
void RegisterLevelZeroModifiedVariablesCallback(const std::function< void(const std::vector< IntegerVariable > &)> cb)
void SetStopPropagationCallback(std::function< bool()> callback)
void WatchUpperBound(IntegerValue, int)
void SetPropagatorPriority(int id, int priority)
void WatchIntegerVariable(IntegerVariable i, int id, int watch_index=-1)
void RegisterReversibleClass(int id, ReversibleInterface *rev)
void ReserveSpaceForNumVariables(int num_vars)
int Register(PropagatorInterface *propagator)
GenericLiteralWatcher & operator=(const GenericLiteralWatcher &)=delete
void CallOnNextPropagate(int id)
GenericLiteralWatcher(const GenericLiteralWatcher &)=delete
void CallAgainDuringThisPropagation()
GenericLiteralWatcher(Model *model)
void AlwaysCallAtLevelZero(int id)
const std::vector< ValueLiteralPair > & FullDomainEncoding(IntegerVariable var) const
IntegerEncoder & operator=(const IntegerEncoder &)=delete
std::pair< IntegerLiteral, IntegerLiteral > Canonicalize(IntegerLiteral i_lit) const
void AssociateToIntegerLiteral(Literal literal, IntegerLiteral i_lit)
const InlinedIntegerValueVector & GetEqualityLiterals(Literal lit) const
IntegerVariable GetLiteralView(Literal lit) const
void AddAllImplicationsBetweenAssociatedLiterals()
Literal GetFalseLiteral()
void FullyEncodeVariable(IntegerVariable var)
IntegerEncoder(const IntegerEncoder &)=delete
IntegerEncoder(Model *model)
bool VariableIsFullyEncoded(IntegerVariable var) const
bool IsFixedOrHasAssociatedLiteral(IntegerLiteral i_lit) const
const std::vector< ValueLiteralPair > & PartialDomainEncoding(IntegerVariable var) const
LiteralIndex GetAssociatedEqualityLiteral(IntegerVariable var, IntegerValue value) const
const InlinedIntegerLiteralVector & GetIntegerLiterals(Literal lit) const
LiteralIndex SearchForLiteralAtOrBefore(IntegerLiteral i_lit, IntegerValue *bound) const
void ReserveSpaceForNumVariables(int num_vars)
Literal GetOrCreateAssociatedLiteral(IntegerLiteral i_lit)
LiteralIndex SearchForLiteralAtOrAfter(IntegerLiteral i_lit, IntegerValue *bound) const
void AssociateToIntegerEqualValue(Literal literal, IntegerVariable var, IntegerValue value)
ABSL_MUST_USE_RESULT bool LiteralOrNegationHasView(Literal lit, IntegerVariable *view=nullptr, bool *view_is_direct=nullptr) const
const std::vector< IntegerVariable > & GetAllAssociatedVariables(Literal lit) const
std::vector< ValueLiteralPair > PartialGreaterThanEncoding(IntegerVariable var) const
LiteralIndex GetAssociatedLiteral(IntegerLiteral i_lit) const
bool VariableDomainHasHoles(IntegerVariable var)
bool UpdateEncodingOnInitialDomainChange(IntegerVariable var, Domain domain)
void DisableImplicationBetweenLiteral()
Literal GetOrCreateLiteralAssociatedToEquality(IntegerVariable var, IntegerValue value)
void UseNewConflictResolution()
void NotifyThatPropagationWasAborted()
ABSL_MUST_USE_RESULT bool ConditionalEnqueue(Literal lit, IntegerLiteral i_lit, std::vector< Literal > *literal_reason, std::vector< IntegerLiteral > *integer_reason)
absl::Span< const Literal > Reason(const Trail &trail, int trail_index, int64_t conflict_id) const final
IntegerValue LowerBound(IntegerVariable i) const
absl::Span< const IntegerLiteral > IntegerReasonAsSpan(ReasonIndex index) const
void RemoveLevelZeroBounds(std::vector< IntegerLiteral > *reason) const
ABSL_MUST_USE_RESULT bool Enqueue(IntegerLiteral i_lit, absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
int FindTrailIndexOfVarBefore(IntegerVariable var, int threshold) const
bool VariableLowerBoundIsFromLevelZero(IntegerVariable var) const
IntegerTrail & operator=(const IntegerTrail &)=delete
absl::Span< const Literal > LiteralReasonAsSpan(ReasonIndex index) const
int NumConstantVariables() const
int64_t num_enqueues() const
IntegerVariable VarAtIndex(int integer_trail_index) const
std::vector< Literal > & ClearedMutableTmpLiterals()
void RegisterWatcher(SparseBitset< IntegerVariable > *p)
IntegerLiteral UpperBoundAsLiteral(IntegerVariable i) const
bool IsFixedAtLevelZero(IntegerVariable var) const
IntegerLiteral IntegerLiteralAtIndex(int integer_trail_index) const
ABSL_MUST_USE_RESULT bool SafeEnqueue(IntegerLiteral i_lit, absl::Span< const IntegerLiteral > integer_reason)
void RelaxLinearReason(IntegerValue slack, absl::Span< const IntegerValue > coeffs, std::vector< IntegerLiteral > *reason) const
bool IntegerLiteralIsTrue(IntegerLiteral l) const
int GetFirstIndexBefore(IntegerVariable var, GlobalTrailIndex source_index, int starting_integer_index)
IntegerValue UpperBound(IntegerVariable i) const
void AppendNewBoundsFrom(int base_index, std::vector< IntegerLiteral > *output) const
IntegerValue FixedValue(IntegerVariable i) const
std::vector< IntegerLiteral > & ClearedMutableTmpIntegerLiterals()
bool IntegerLiteralIsFalse(IntegerLiteral l) const
IntegerLiteral LowerBoundAsLiteral(IntegerVariable i) const
bool HasPendingRootLevelDeduction() const
IntegerVariable AddIntegerVariable()
void RegisterReversibleClass(ReversibleInterface *rev)
bool ReportConflict(absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
int64_t timestamp() const
IntegerTrail(Model *model)
int PreviousTrailIndex(int integer_trail_index) const
const IntegerReason & GetIntegerReason(GlobalTrailIndex index, std::optional< IntegerValue > needed_bound)
void AppendRelaxedLinearReason(IntegerValue slack, absl::Span< const IntegerValue > coeffs, absl::Span< const IntegerVariable > vars, std::vector< IntegerLiteral > *reason) const
IntegerTrail(const IntegerTrail &)=delete
bool ReportConflict(absl::Span< const IntegerLiteral > integer_reason)
ABSL_MUST_USE_RESULT bool EnqueueWithLazyReason(IntegerLiteral i_lit, int id, IntegerValue propagation_slack, LazyReasonInterface *explainer)
bool IsTrueAtLevelZero(IntegerLiteral l) const
const IntegerReason & IntegerConflict()
void AppendNewBounds(std::vector< IntegerLiteral > *output) const
bool InPropagationLoop() const
bool UpdateInitialDomain(IntegerVariable var, Domain domain)
bool IsFixed(IntegerVariable i) const
IntegerVariable NumIntegerVariables() const
ABSL_MUST_USE_RESULT bool Enqueue(IntegerLiteral i_lit, absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason, int trail_index_with_same_reason)
IntegerValue ConditionalLowerBound(Literal l, IntegerVariable i) const
IntegerVariable NextVariableToBranchOnInPropagationLoop() const
IntegerValue ConditionalUpperBound(Literal l, IntegerVariable i) const
const IntegerValue * LowerBoundsData() const
ABSL_MUST_USE_RESULT bool SafeEnqueueLiteral(Literal literal, absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
void RegisterDebugChecker(std::function< bool(absl::Span< const Literal > clause, absl::Span< const IntegerLiteral > integers)> checker)
GlobalTrailIndex GlobalIndexAt(int integer_index) const
int64_t num_level_zero_enqueues() const
ABSL_MUST_USE_RESULT bool RootLevelEnqueue(IntegerLiteral i_lit)
IntegerValue LevelZeroUpperBound(IntegerVariable var) const
void MergeReasonInto(absl::Span< const IntegerLiteral > literals, std::vector< Literal > *output) const
ABSL_MUST_USE_RESULT bool EnqueueLiteral(Literal literal, absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
const Domain & InitialVariableDomain(IntegerVariable var) const
IntegerValue LevelZeroLowerBound(IntegerVariable var) const
void Untrail(const Trail &trail, int literal_trail_index) final
ABSL_MUST_USE_RESULT bool Enqueue(IntegerLiteral i_lit)
IntegerVariable FirstUnassignedVariable() const
void ReserveSpaceForNumVariables(int num_vars)
bool Propagate(Trail *trail) final
IntegerVariable GetOrCreateConstantIntegerVariable(IntegerValue value)
std::vector< Literal > ReasonFor(IntegerLiteral literal) const
bool CurrentBranchHadAnIncompletePropagation()
ReasonIndex AppendReasonToInternalBuffers(absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
virtual ~LazyReasonInterface()=default
virtual void Explain(int id, IntegerLiteral to_explain, IntegerReason *reason)=0
LazyReasonInterface()=default
virtual std::string LazyReasonName() const =0
LiteralIndex Index() const
virtual ~PropagatorInterface()=default
virtual bool IncrementalPropagate(const std::vector< int > &)
virtual bool Propagate()=0
PropagatorInterface()=default
RevIntRepository(Model *model)
RevIntegerValueRepository(Model *model)
SatPropagator(const std::string &name)
void AddPropagator(SatPropagator *propagator)
void push_back(const value_type &val)
std::function< std::vector< ValueLiteralPair >(Model *)> FullyEncodeVariable(IntegerVariable var)
std::function< IntegerVariable(Model *)> NewIntegerVariableFromLiteral(Literal lit)
constexpr IntegerValue kMaxIntegerValue(std::numeric_limits< IntegerValue::ValueType >::max() - 1)
std::function< void(Model *)> Equality(IntegerVariable v, int64_t value)
bool operator==(const BoolArgumentProto &lhs, const BoolArgumentProto &rhs)
const LiteralIndex kNoLiteralIndex(-1)
std::function< int64_t(const Model &)> LowerBound(IntegerVariable v)
std::function< BooleanVariable(Model *)> NewBooleanVariable()
std::function< void(Model *)> LowerOrEqual(IntegerVariable v, int64_t ub)
std::vector< IntegerVariable > NegationOf(absl::Span< const IntegerVariable > vars)
std::function< bool(const Model &)> IsFixed(IntegerVariable v)
constexpr IntegerValue kMinIntegerValue(-kMaxIntegerValue.value())
const IntegerVariable kNoIntegerVariable(-1)
absl::InlinedVector< std::pair< IntegerVariable, IntegerValue >, 2 > InlinedIntegerValueVector
std::function< void(Model *)> Implication(absl::Span< const Literal > enforcement_literals, IntegerLiteral i)
std::function< IntegerVariable(Model *)> ConstantIntegerVariable(int64_t value)
constexpr ClauseId kNoClauseId(0)
std::function< int64_t(const Model &)> Value(IntegerVariable v)
std::function< int64_t(const Model &)> UpperBound(IntegerVariable v)
std::function< IntegerVariable(Model *)> NewIntegerVariable(int64_t lb, int64_t ub)
std::function< void(Model *)> GreaterOrEqual(IntegerVariable v, int64_t lb)
absl::InlinedVector< IntegerLiteral, 2 > InlinedIntegerLiteralVector
PositiveOnlyIndex GetPositiveOnlyIndex(IntegerVariable var)
std::function< void(Model *)> ImpliesInInterval(Literal in_interval, IntegerVariable v, int64_t lb, int64_t ub)
bool VariableIsPositive(IntegerVariable i)
IntegerVariable CreateNewIntegerVariableFromLiteral(Literal lit, Model *model)
#define DEFINE_STRONG_INDEX_TYPE(index_type_name)
IntegerValue ValueAt(IntegerValue var_value) const
std::vector< IntegerLiteral > integer_literal_to_fix
std::vector< Literal > literal_to_fix
bool operator>=(const GlobalTrailIndex &o) const
bool operator<=(const GlobalTrailIndex &o) const
bool operator<(const GlobalTrailIndex &o) const
static constexpr int kNoIntegerIndex
bool operator==(const GlobalTrailIndex &o) const
bool operator>(const GlobalTrailIndex &o) const
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)
static IntegerLiteral TrueLiteral()
static IntegerLiteral LowerOrEqual(IntegerVariable i, IntegerValue bound)
static IntegerLiteral FalseLiteral()
absl::Span< const Literal > boolean_literals_at_false
IntegerLiteral propagated_i_lit
absl::Span< const IntegerValue > coeffs
absl::Span< const Literal > boolean_literals_at_true
absl::Span< const IntegerVariable > vars
absl::Span< const IntegerLiteral > integer_literals
void SimpleCanonicalization()
bool operator==(const LiteralValueValue &rhs) const
std::string DebugString() const