14#ifndef OR_TOOLS_SAT_INTEGER_H_
15#define OR_TOOLS_SAT_INTEGER_H_
30#include "absl/base/attributes.h"
31#include "absl/container/btree_map.h"
32#include "absl/container/flat_hash_map.h"
33#include "absl/container/inlined_vector.h"
34#include "absl/log/check.h"
35#include "absl/strings/str_cat.h"
36#include "absl/types/span.h"
41#include "ortools/sat/sat_parameters.pb.h"
70 std::numeric_limits<IntegerValue::ValueType>::max() - 1);
74 const double kInfinity = std::numeric_limits<double>::infinity();
77 return static_cast<double>(
value.value());
80template <
class IntType>
82 return IntType(std::abs(t.value()));
86 IntegerValue positive_divisor) {
87 DCHECK_GT(positive_divisor, 0);
88 const IntegerValue result = dividend / positive_divisor;
89 const IntegerValue adjust =
90 static_cast<IntegerValue
>(result * positive_divisor < dividend);
91 return result + adjust;
95 IntegerValue positive_divisor) {
96 DCHECK_GT(positive_divisor, 0);
97 const IntegerValue result = dividend / positive_divisor;
98 const IntegerValue adjust =
99 static_cast<IntegerValue
>(result * positive_divisor > dividend);
100 return result - adjust;
105inline IntegerValue
CapProdI(IntegerValue
a, IntegerValue
b) {
106 return IntegerValue(
CapProd(
a.value(),
b.value()));
109inline IntegerValue
CapSubI(IntegerValue
a, IntegerValue
b) {
110 return IntegerValue(
CapSub(
a.value(),
b.value()));
113inline IntegerValue
CapAddI(IntegerValue
a, IntegerValue
b) {
114 return IntegerValue(
CapAdd(
a.value(),
b.value()));
136 : inverse_((1ull << 48) / divisor + 1) {}
139 return static_cast<uint16_t
>((inverse_ *
static_cast<uint64_t
>(dividend)) >>
154 IntegerValue positive_divisor) {
155 DCHECK_GT(positive_divisor, 0);
156 const IntegerValue m = dividend % positive_divisor;
157 return m < 0 ? m + positive_divisor : m;
160inline bool AddTo(IntegerValue
a, IntegerValue* result) {
162 const IntegerValue add =
CapAddI(
a, *result);
172 const IntegerValue add =
CapAddI(prod, *result);
186 return IntegerVariable(
i.value() ^ 1);
190 return (
i.value() & 1) == 0;
194 return IntegerVariable(
i.value() & (~1));
200 return PositiveOnlyIndex(
var.value() / 2);
204 IntegerValue coeff) {
206 return absl::StrCat(coeff.value(),
"*X",
var.value() / 2);
211 const std::vector<IntegerVariable>& vars);
256 ? absl::StrCat(
"I",
var.value() / 2,
">=",
bound.value())
257 : absl::StrCat(
"I",
var.value() / 2,
"<=", -
bound.value());
262 IntegerValue
bound = IntegerValue(0);
271 absl::Span<const IntegerLiteral> literals) {
288 absl::InlinedVector<std::pair<IntegerVariable, IntegerValue>, 2>;
330 IntegerValue
ValueAt(IntegerValue var_value)
const {
346 return absl::StrCat(
"(",
coeff.value(),
" * X",
var.value(),
")");
348 return absl::StrCat(
"(",
coeff.value(),
" * X",
var.value(),
" + ",
358 IntegerValue
coeff = IntegerValue(0);
365 h = H::combine(std::move(h), e.
var);
366 h = H::combine(std::move(h), e.
coeff);
368 h = H::combine(std::move(h), e.
constant);
403 return a.literal <
b.literal;
409 return (
a.value <
b.value) ||
410 (
a.value ==
b.value &&
a.literal <
b.literal);
420 IntegerValue
value = IntegerValue(0);
438 return absl::StrCat(
"(lit(",
literal.
Index().value(),
") * ",
478 num_created_variables_(0) {}
485 VLOG(1) <<
"#variables created = " << num_created_variables_;
525 IntegerVariable
var)
const;
527 IntegerVariable
var)
const;
571 IntegerValue
value)
const;
585 if (
lit.Index() >= reverse_encoding_.size()) {
586 return empty_integer_literal_vector_;
588 return reverse_encoding_[
lit];
594 if (
lit.Index() >= reverse_equality_encoding_.size()) {
595 return empty_integer_value_vector_;
597 return reverse_equality_encoding_[
lit];
604 temp_associated_vars_.clear();
606 temp_associated_vars_.push_back(l.var);
609 temp_associated_vars_.push_back(
var);
611 return temp_associated_vars_;
620 return literal_view_[
lit];
627 bool* view_is_direct =
nullptr)
const;
638 IntegerValue*
bound)
const;
646 literal_index_true_ = literal_true.
Index();
652 return Literal(literal_index_true_);
660 IntegerVariable
var)
const;
674 void AddImplications(
675 const absl::btree_map<IntegerValue, Literal>& map,
676 absl::btree_map<IntegerValue, Literal>::const_iterator it,
684 bool add_implications_ =
true;
685 int64_t num_created_variables_ = 0;
703 absl::btree_map<IntegerValue, Literal>>
712 reverse_equality_encoding_;
715 mutable std::vector<IntegerVariable> temp_associated_vars_;
727 absl::flat_hash_map<std::pair<PositiveOnlyIndex, IntegerValue>,
Literal>
728 equality_to_associated_literal_;
732 absl::InlinedVector<ValueLiteralPair, 2>>
743 std::vector<IntegerValue> tmp_values_;
744 std::vector<ValueLiteralPair> tmp_encoding_;
747 mutable std::vector<ValueLiteralPair> partial_encoding_;
765 virtual void Explain(
int id, IntegerValue propagation_slack,
766 IntegerVariable var_to_explain,
int trail_index,
767 std::vector<Literal>* literals_reason,
768 std::vector<int>* trail_indices_reason) = 0;
784 parameters_(*
model->GetOrCreate<SatParameters>()) {
798 void Untrail(const
Trail& trail,
int literal_trail_index) final;
800 int64_t conflict_id) const final;
807 return IntegerVariable(var_lbs_.size());
867 bool IsFixed(IntegerVariable
i)
const;
937 absl::Span<const IntegerValue> coeffs,
938 std::vector<IntegerLiteral>* reason)
const;
942 absl::Span<const IntegerValue> coeffs,
943 absl::Span<const IntegerVariable> vars,
944 std::vector<IntegerLiteral>* reason)
const;
948 absl::Span<const IntegerValue> coeffs,
949 std::vector<int>* trail_indices)
const;
973 return EnqueueInternal(i_lit,
false, {}, {}, integer_trail_.size());
977 absl::Span<const IntegerLiteral> integer_reason) {
978 return EnqueueInternal(i_lit,
false, literal_reason, integer_reason,
979 integer_trail_.size());
992 IntegerLiteral i_lit, absl::Span<const IntegerLiteral> integer_reason);
1002 std::vector<IntegerLiteral>* integer_reason);
1013 absl::Span<const IntegerLiteral> integer_reason,
1014 int trail_index_with_same_reason) {
1015 return EnqueueInternal(i_lit,
false, literal_reason, integer_reason,
1016 trail_index_with_same_reason);
1023 const int trail_index = integer_trail_.size();
1024 lazy_reasons_.push_back(LazyReasonEntry{explainer, propagation_slack,
1025 i_lit.
var, id, trail_index});
1026 return EnqueueInternal(i_lit,
true, {}, {}, 0);
1041 absl::Span<const IntegerLiteral> integer_reason);
1052 std::vector<Literal>* output)
const;
1061 int64_t
timestamp()
const {
return num_enqueues_ + num_untrails_; }
1071 watchers_.push_back(p);
1077 absl::Span<const IntegerLiteral> integer_reason) {
1078 DCHECK(ReasonIsValid(literal_reason, integer_reason));
1080 conflict->assign(literal_reason.begin(), literal_reason.end());
1085 DCHECK(ReasonIsValid({}, integer_reason));
1094 return var_trail_index_[
var] < var_lbs_.size();
1100 reversible_classes_.push_back(rev);
1103 int Index()
const {
return integer_trail_.size(); }
1114 std::vector<IntegerLiteral>* output)
const;
1145 std::function<
bool(absl::Span<const Literal> clause,
1146 absl::Span<const IntegerLiteral> integers)>
1148 debug_checker_ = std::move(checker);
1159 IntegerValue target_min,
1160 std::vector<int>* indices)
const {
1162 if (expr.IsConstant()) {
1163 DCHECK_GE(expr.constant, target_min);
1173 const int index = tmp_var_to_trail_index_in_queue_[expr.var];
1174 if (
index == std::numeric_limits<int>::max())
continue;
1176 expr.ValueAt(integer_trail_[
index].bound) >= target_min) {
1177 has_dependency_ =
true;
1185 FindLowestTrailIndexThatExplainBound(expr.GreaterOrEqual(target_min));
1187 indices->push_back(
index);
1195 bool ReasonIsValid(absl::Span<const Literal> literal_reason,
1196 absl::Span<const IntegerLiteral> integer_reason);
1199 bool ReasonIsValid(
Literal lit, absl::Span<const Literal> literal_reason,
1200 absl::Span<const IntegerLiteral> integer_reason);
1202 absl::Span<const Literal> literal_reason,
1203 absl::Span<const IntegerLiteral> integer_reason);
1212 std::vector<Literal>* InitializeConflict(
1214 absl::Span<const Literal> literals_reason,
1215 absl::Span<const IntegerLiteral> bounds_reason);
1218 int AppendReasonToInternalBuffers(
1219 absl::Span<const Literal> literal_reason,
1220 absl::Span<const IntegerLiteral> integer_reason);
1223 ABSL_MUST_USE_RESULT
bool EnqueueInternal(
1225 absl::Span<const Literal> literal_reason,
1226 absl::Span<const IntegerLiteral> integer_reason,
1227 int trail_index_with_same_reason);
1230 void EnqueueLiteralInternal(
Literal literal,
bool use_lazy_reason,
1231 absl::Span<const Literal> literal_reason,
1232 absl::Span<const IntegerLiteral> integer_reason);
1237 ABSL_MUST_USE_RESULT
bool EnqueueAssociatedIntegerLiteral(
1241 void MergeReasonIntoInternal(std::vector<Literal>* output,
1242 int64_t conflict_id)
const;
1247 int FindLowestTrailIndexThatExplainBound(
IntegerLiteral i_lit)
const;
1252 void ComputeLazyReasonIfNeeded(
int reason_index)
const;
1259 absl::Span<const int> Dependencies(
int reason_index)
const;
1265 void AppendLiteralsReason(
int reason_index,
1266 std::vector<Literal>* output)
const;
1269 std::string DebugString();
1272 int64_t NextConflictId();
1285 mutable int var_trail_index_cache_threshold_ = 0;
1287 var_trail_index_cache_;
1291 absl::flat_hash_map<IntegerValue, IntegerVariable> constant_map_;
1297 IntegerVariable var;
1298 int32_t prev_trail_index;
1302 int32_t reason_index;
1304 std::vector<TrailEntry> integer_trail_;
1306 struct LazyReasonEntry {
1307 LazyReasonInterface* explainer;
1308 IntegerValue propagation_slack;
1309 IntegerVariable var_to_explain;
1311 int trail_index_at_propagation_time;
1313 void Explain(std::vector<Literal>* literals,
1314 std::vector<int>* dependencies)
const {
1315 explainer->Explain(
id, propagation_slack, var_to_explain,
1316 trail_index_at_propagation_time, literals,
1320 std::vector<int> lazy_reason_decision_levels_;
1321 std::vector<LazyReasonEntry> lazy_reasons_;
1325 std::vector<int> integer_search_levels_;
1328 std::vector<int> reason_decision_levels_;
1329 std::vector<int> literals_reason_starts_;
1330 std::vector<Literal> literals_reason_buffer_;
1335 std::vector<int> bounds_reason_starts_;
1336 mutable std::vector<int> cached_sizes_;
1337 std::vector<IntegerLiteral> bounds_reason_buffer_;
1338 mutable std::vector<int> trail_index_reason_buffer_;
1341 mutable std::vector<Literal> lazy_reason_literals_;
1342 mutable std::vector<int> lazy_reason_trail_indices_;
1345 mutable bool has_dependency_ =
false;
1346 mutable std::vector<int> tmp_queue_;
1347 mutable std::vector<IntegerVariable> tmp_to_clear_;
1349 tmp_var_to_trail_index_in_queue_;
1350 mutable SparseBitset<BooleanVariable> added_variables_;
1353 struct RelaxHeapEntry {
1357 bool operator<(
const RelaxHeapEntry& o)
const {
return index < o.index; }
1359 mutable std::vector<RelaxHeapEntry> relax_heap_;
1360 mutable std::vector<int> tmp_indices_;
1363 mutable SparseBitset<IntegerVariable> tmp_marked_;
1366 std::vector<IntegerLiteral> tmp_cleaned_reason_;
1369 std::vector<int> boolean_trail_index_to_reason_index_;
1373 int first_level_without_full_propagation_ = -1;
1378 mutable int64_t last_conflict_id_ = -1;
1379 mutable bool info_is_valid_on_subsequent_last_level_expansion_ =
false;
1381 var_to_trail_index_at_lower_level_;
1382 mutable std::vector<int> tmp_seen_;
1383 mutable std::vector<IntegerVariable> to_clear_for_lower_level_;
1385 int64_t num_enqueues_ = 0;
1386 int64_t num_untrails_ = 0;
1387 int64_t num_level_zero_enqueues_ = 0;
1388 mutable int64_t num_decisions_to_break_loop_ = 0;
1390 std::vector<SparseBitset<IntegerVariable>*> watchers_;
1391 std::vector<ReversibleInterface*> reversible_classes_;
1393 mutable Domain temp_domain_;
1394 DelayedRootLevelDeduction* delayed_to_fix_;
1395 IntegerDomains* domains_;
1396 IntegerEncoder* encoder_;
1398 SatSolver* sat_solver_;
1399 TimeLimit* time_limit_;
1400 const SatParameters& parameters_;
1405 absl::flat_hash_map<std::pair<LiteralIndex, IntegerVariable>, IntegerValue>
1408 std::function<bool(absl::Span<const Literal> clause,
1409 absl::Span<const IntegerLiteral> integers)>
1410 debug_checker_ =
nullptr;
1438 LOG(FATAL) <<
"Not implemented.";
1479 void Untrail(const
Trail& trail,
int literal_trail_index) final;
1566 bool_to_reset_on_backtrack_.push_back(is_in_dive);
1583 const std::function<
void(
const std::vector<IntegerVariable>&)> cb) {
1584 level_zero_modified_variable_callback_.push_back(cb);
1593 stop_propagation_callback_ =
callback;
1607 void UpdateCallingNeeds(
Trail* trail);
1616 bool operator==(
const WatchData& o)
const {
1617 return id == o.id && watch_index == o.watch_index;
1621 literal_to_watcher_;
1624 std::vector<PropagatorInterface*> watchers_;
1625 SparseBitset<IntegerVariable> modified_vars_;
1628 SparseBitset<IntegerVariable> modified_vars_for_callback_;
1632 std::vector<std::deque<int>> queue_by_priority_;
1633 std::vector<bool> in_queue_;
1637 std::vector<bool> id_need_reversible_support_;
1638 std::vector<int> id_to_level_at_last_call_;
1639 RevVector<IdType, int> id_to_greatest_common_level_since_last_call_;
1640 std::vector<std::vector<ReversibleInterface*>> id_to_reversible_classes_;
1641 std::vector<std::vector<int*>> id_to_reversible_ints_;
1643 std::vector<std::vector<int>> id_to_watch_indices_;
1644 std::vector<int> id_to_priority_;
1645 std::vector<int> id_to_idempotence_;
1648 std::vector<int> propagator_ids_to_call_at_level_zero_;
1653 std::vector<std::function<void(
const std::vector<IntegerVariable>&)>>
1654 level_zero_modified_variable_callback_;
1656 std::function<bool()> stop_propagation_callback_;
1658 std::vector<bool*> bool_to_reset_on_backtrack_;
1666 IntegerValue
bound) {
1672 IntegerValue
bound) {
1695 IntegerValue
bound)
const {
1700 DCHECK_GT(
coeff, 0);
1711 DCHECK_GT(
coeff, 0);
1733 Literal l, IntegerVariable
i)
const {
1734 const auto it = conditional_lbs_.find({l.
Index(),
i});
1735 if (it != conditional_lbs_.end()) {
1736 return std::max(var_lbs_[
i], it->second);
1742 Literal l, AffineExpression expr)
const {
1748 Literal l, IntegerVariable
i)
const {
1759 IntegerVariable
i)
const {
1764 IntegerVariable
i)
const {
1811 IntegerVariable
var)
const {
1812 return integer_trail_[
var.value()].bound;
1816 IntegerVariable
var)
const {
1821 return integer_trail_[
var.value()].bound ==
1844 if (l.
Index() >= literal_to_watcher_.size()) {
1845 literal_to_watcher_.
resize(l.
Index().value() + 1);
1847 literal_to_watcher_[l].
push_back({id, watch_index});
1853 if (
var.value() >= var_to_watcher_.size()) {
1854 var_to_watcher_.
resize(
var.value() + 1);
1861 const WatchData data = {id, watch_index};
1862 if (!var_to_watcher_[
var].empty() && var_to_watcher_[
var].back() == data) {
1897 return [=](Model*
model) {
1898 return model->GetOrCreate<IntegerTrail>()
1899 ->GetOrCreateConstantIntegerVariable(IntegerValue(
value));
1905 return [=](Model*
model) {
1908 IntegerValue(lb), IntegerValue(ub));
1913 const Domain& domain) {
1914 return [=](Model*
model) {
1915 return model->GetOrCreate<IntegerTrail>()->AddIntegerVariable(domain);
1923 auto* encoder =
model->GetOrCreate<IntegerEncoder>();
1924 const IntegerVariable candidate = encoder->GetLiteralView(
lit);
1927 IntegerVariable
var;
1930 if (assignment.LiteralIsTrue(
lit)) {
1931 var = integer_trail->GetOrCreateConstantIntegerVariable(IntegerValue(1));
1932 }
else if (assignment.LiteralIsFalse(
lit)) {
1933 var = integer_trail->GetOrCreateConstantIntegerVariable(IntegerValue(0));
1935 var = integer_trail->AddIntegerVariable(IntegerValue(0), IntegerValue(1));
1938 encoder->AssociateToIntegerEqualValue(
lit,
var, IntegerValue(1));
1946 return [=](Model*
model) {
1951inline std::function<int64_t(
const Model&)>
LowerBound(IntegerVariable v) {
1952 return [=](
const Model&
model) {
1957inline std::function<int64_t(
const Model&)>
UpperBound(IntegerVariable v) {
1958 return [=](
const Model&
model) {
1963inline std::function<bool(
const Model&)>
IsFixed(IntegerVariable v) {
1964 return [=](
const Model&
model) {
1965 const IntegerTrail* trail =
model.Get<IntegerTrail>();
1966 return trail->LowerBound(v) == trail->UpperBound(v);
1971inline std::function<int64_t(
const Model&)>
Value(IntegerVariable v) {
1972 return [=](
const Model&
model) {
1973 const IntegerTrail* trail =
model.Get<IntegerTrail>();
1974 CHECK_EQ(trail->LowerBound(v), trail->UpperBound(v)) << v;
1975 return trail->LowerBound(v).value();
1979inline std::function<void(Model*)>
GreaterOrEqual(IntegerVariable v,
1981 return [=](Model*
model) {
1982 if (!
model->GetOrCreate<IntegerTrail>()->Enqueue(
1984 std::vector<Literal>(), std::vector<IntegerLiteral>())) {
1986 VLOG(1) <<
"Model trivially infeasible, variable " << v
1988 <<
" and GreaterOrEqual() was called with a lower bound of "
1994inline std::function<void(Model*)>
LowerOrEqual(IntegerVariable v, int64_t ub) {
1995 return [=](Model*
model) {
1996 if (!
model->GetOrCreate<IntegerTrail>()->Enqueue(
1998 std::vector<Literal>(), std::vector<IntegerLiteral>())) {
2000 VLOG(1) <<
"Model trivially infeasible, variable " << v
2002 <<
" and LowerOrEqual() was called with an upper bound of " << ub;
2008inline std::function<void(Model*)>
Equality(IntegerVariable v, int64_t
value) {
2009 return [=](Model*
model) {
2022 absl::Span<const Literal> enforcement_literals, IntegerLiteral
i) {
2023 return [=](Model*
model) {
2024 IntegerTrail* integer_trail =
model->GetOrCreate<IntegerTrail>();
2025 if (
i.bound <= integer_trail->LowerBound(
i.var)) {
2027 }
else if (
i.bound > integer_trail->UpperBound(
i.var)) {
2029 std::vector<Literal> clause;
2030 for (
const Literal
literal : enforcement_literals) {
2031 clause.push_back(
literal.Negated());
2037 IntegerEncoder* encoder =
model->GetOrCreate<IntegerEncoder>();
2038 std::vector<Literal> clause{encoder->GetOrCreateAssociatedLiteral(
i)};
2039 for (
const Literal
literal : enforcement_literals) {
2040 clause.push_back(
literal.Negated());
2050 int64_t lb, int64_t ub) {
2051 return [=](Model*
model) {
2056 v, IntegerValue(lb))));
2071 IntegerVariable
var) {
2072 return [=](Model*
model) {
2073 IntegerEncoder* encoder =
model->GetOrCreate<IntegerEncoder>();
2074 if (!encoder->VariableIsFullyEncoded(
var)) {
2075 encoder->FullyEncodeVariable(
var);
2077 return encoder->FullDomainEncoding(
var);
void ClearAndResize(IntegerType size)
int NumPropagators() const
Returns the number of registered propagators.
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)
Memory optimization: you can call this before registering watchers.
int Register(PropagatorInterface *propagator)
Registers a propagator and returns its unique ids.
GenericLiteralWatcher & operator=(const GenericLiteralWatcher &)=delete
void CallOnNextPropagate(int id)
Add the given propagator to its queue.
GenericLiteralWatcher(const GenericLiteralWatcher &)=delete
This type is neither copyable nor movable.
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
This type is neither copyable nor movable.
IntegerEncoder(Model *model)
Literal GetTrueLiteral()
Gets the literal always set to true, make it if it does not exist.
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
Returns the IntegerLiterals that were associated with the given Literal.
LiteralIndex SearchForLiteralAtOrBefore(IntegerLiteral i_lit, IntegerValue *bound) const
void ReserveSpaceForNumVariables(int num_vars)
Memory optimization: you can call this before encoding variables.
Literal GetOrCreateAssociatedLiteral(IntegerLiteral i_lit)
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 UpdateEncodingOnInitialDomainChange(IntegerVariable var, Domain domain)
void DisableImplicationBetweenLiteral()
Literal GetOrCreateLiteralAssociatedToEquality(IntegerVariable var, IntegerValue value)
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
Returns the current lower/upper bound of the given integer variable.
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
Returns true if the variable lower bound is still the one from level zero.
IntegerTrail & operator=(const IntegerTrail &)=delete
int NumConstantVariables() const
int64_t num_enqueues() const
void RegisterWatcher(SparseBitset< IntegerVariable > *p)
IntegerLiteral UpperBoundAsLiteral(IntegerVariable i) const
bool IsFixedAtLevelZero(IntegerVariable var) const
Returns true if the variable is fixed at level 0.
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
Returns the current value (if known) of an IntegerLiteral.
IntegerValue UpperBound(IntegerVariable i) const
void AppendNewBoundsFrom(int base_index, std::vector< IntegerLiteral > *output) const
IntegerValue FixedValue(IntegerVariable i) const
Checks that the variable is fixed and returns its value.
bool IntegerLiteralIsFalse(IntegerLiteral l) const
IntegerLiteral LowerBoundAsLiteral(IntegerVariable i) const
bool HasPendingRootLevelDeduction() const
Return true if we can fix new fact at level zero.
IntegerVariable AddIntegerVariable()
void AddAllGreaterThanConstantReason(absl::Span< AffineExpression > exprs, IntegerValue target_min, std::vector< int > *indices) const
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)
void AppendRelaxedLinearReason(IntegerValue slack, absl::Span< const IntegerValue > coeffs, absl::Span< const IntegerVariable > vars, std::vector< IntegerLiteral > *reason) const
Same as above but take in IntegerVariables instead of IntegerLiterals.
IntegerTrail(const IntegerTrail &)=delete
This type is neither copyable nor movable.
bool ReportConflict(absl::Span< const IntegerLiteral > integer_reason)
ABSL_MUST_USE_RESULT bool EnqueueWithLazyReason(IntegerLiteral i_lit, int id, IntegerValue propagation_slack, LazyReasonInterface *explainer)
Lazy reason API.
void AppendNewBounds(std::vector< IntegerLiteral > *output) const
bool InPropagationLoop() const
bool UpdateInitialDomain(IntegerVariable var, Domain domain)
bool IsFixed(IntegerVariable i) const
Checks if the variable is fixed.
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
Returns the current upper bound assuming the literal is true.
const IntegerValue * LowerBoundsData() const
void RegisterDebugChecker(std::function< bool(absl::Span< const Literal > clause, absl::Span< const IntegerLiteral > integers)> checker)
int64_t num_level_zero_enqueues() const
Same as num_enqueues but only count the level zero changes.
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
void 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
Returns globally valid lower/upper bound on the given integer variable.
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()
virtual ~LazyReasonInterface()=default
LazyReasonInterface()=default
virtual void Explain(int id, IntegerValue propagation_slack, IntegerVariable var_to_explain, int trail_index, std::vector< Literal > *literals_reason, std::vector< int > *trail_indices_reason)=0
LiteralIndex Index() const
Base class for CP like propagators.
virtual ~PropagatorInterface()=default
virtual bool IncrementalPropagate(const std::vector< int > &)
virtual bool Propagate()=0
PropagatorInterface()=default
QuickSmallDivision(uint16_t divisor)
uint16_t DivideByDivisor(uint16_t dividend) const
RevIntRepository(Model *model)
RevIntegerValueRepository(Model *model)
Base class for all the SAT constraints.
BooleanVariable NewBooleanVariable()
ABSL_MUST_USE_RESULT bool AddUnitClause(Literal true_literal)
int CurrentDecisionLevel() const
void AddPropagator(SatPropagator *propagator)
std::vector< Literal > * MutableConflict()
value_type * data()
– Pass-through methods to STL vector ----------------------------------—
void push_back(const value_type &val)
void resize(size_type new_size)
std::function< std::vector< ValueLiteralPair >(Model *)> FullyEncodeVariable(IntegerVariable var)
std::function< IntegerVariable(Model *)> NewIntegerVariableFromLiteral(Literal lit)
IntegerValue FloorRatio(IntegerValue dividend, IntegerValue positive_divisor)
bool AddProductTo(IntegerValue a, IntegerValue b, IntegerValue *result)
Computes result += a * b, and return false iff there is an overflow.
constexpr IntegerValue kMaxIntegerValue(std::numeric_limits< IntegerValue::ValueType >::max() - 1)
std::function< void(Model *)> Equality(IntegerVariable v, int64_t value)
Fix v to a given value.
bool AddTo(IntegerValue a, IntegerValue *result)
IntType IntTypeAbs(IntType t)
IntegerValue CeilRatio(IntegerValue dividend, IntegerValue positive_divisor)
bool ProdOverflow(IntegerValue t, IntegerValue value)
const LiteralIndex kNoLiteralIndex(-1)
std::function< void(Model *)> ClauseConstraint(absl::Span< const Literal > literals)
std::function< int64_t(const Model &)> LowerBound(IntegerVariable v)
std::function< BooleanVariable(Model *)> NewBooleanVariable()
std::vector< IntegerVariable > NegationOf(const std::vector< IntegerVariable > &vars)
Returns the vector of the negated variables.
std::function< void(Model *)> LowerOrEqual(IntegerVariable v, int64_t ub)
std::string IntegerTermDebugString(IntegerVariable var, IntegerValue coeff)
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)
IntegerVariable PositiveVariable(IntegerVariable i)
std::ostream & operator<<(std::ostream &os, const BoolVar &var)
IntegerValue PositiveRemainder(IntegerValue dividend, IntegerValue positive_divisor)
IntegerValue CapAddI(IntegerValue a, IntegerValue b)
std::function< int64_t(const Model &)> Value(IntegerVariable v)
This checks that the variable is fixed.
std::function< int64_t(const Model &)> UpperBound(IntegerVariable v)
H AbslHashValue(H h, const IntVar &i)
– ABSL HASHING SUPPORT --------------------------------------------------—
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)
in_interval => v in [lb, ub].
bool VariableIsPositive(IntegerVariable i)
IntegerValue CapSubI(IntegerValue a, IntegerValue b)
bool AtMinOrMaxInt64I(IntegerValue t)
IntegerValue CapProdI(IntegerValue a, IntegerValue b)
Overflows and saturated arithmetic.
double ToDouble(IntegerValue value)
IntegerVariable CreateNewIntegerVariableFromLiteral(Literal lit, Model *model)
In SWIG mode, we don't want anything besides these top-level includes.
bool AtMinOrMaxInt64(int64_t x)
Checks if x is equal to the min or the max value of an int64_t.
int64_t CapAdd(int64_t x, int64_t y)
static constexpr double kInfinity
int64_t CapSub(int64_t x, int64_t y)
int64_t CapProd(int64_t x, int64_t y)
#define DEFINE_STRONG_INT64_TYPE(integer_type_name)
#define DEFINE_STRONG_INDEX_TYPE(index_type_name)
IntegerLiteral GreaterOrEqual(IntegerValue bound) const
var * coeff + constant >= bound.
bool operator==(AffineExpression o) const
AffineExpression MultipliedBy(IntegerValue multiplier) const
AffineExpression Negated() const
AffineExpression(IntegerVariable v, IntegerValue c, IntegerValue cst)
AffineExpression()=default
Helper to construct an AffineExpression.
IntegerValue ValueAt(IntegerValue var_value) const
Returns the value of this affine expression given its variable value.
AffineExpression(IntegerVariable v, IntegerValue c)
double LpValue(const util_intops::StrongVector< IntegerVariable, double > &lp_values) const
Returns the affine expression value under a given LP solution.
AffineExpression(IntegerValue cst)
AffineExpression(IntegerVariable v)
std::string DebugString() const
IntegerLiteral LowerOrEqual(IntegerValue bound) const
var * coeff + constant <= bound.
std::vector< int64_t > proto_values
util_intops::StrongVector< IntegerVariable, bool > ivar_has_value
util_intops::StrongVector< IntegerVariable, IntegerValue > ivar_values
std::vector< IntegerLiteral > integer_literal_to_fix
std::vector< Literal > literal_to_fix
bool operator==(IntegerLiteral o) const
bool IsAlwaysFalse() const
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)
static IntegerLiteral TrueLiteral()
IntegerLiteral Negated() const
The negation of x >= bound is x <= bound - 1.
std::string DebugString() const
static IntegerLiteral LowerOrEqual(IntegerVariable i, IntegerValue bound)
bool IsAlwaysTrue() const
static IntegerLiteral FalseLiteral()
IntegerLiteral(IntegerVariable v, IntegerValue b)
bool operator!=(IntegerLiteral o) const
IntegerLiteral()
Clients should prefer the static construction methods above.
bool operator==(const LiteralValueValue &rhs) const
Used for testing.
std::string DebugString() const
bool operator()(const ValueLiteralPair &a, const ValueLiteralPair &b) const
bool operator()(const ValueLiteralPair &a, const ValueLiteralPair &b) const
std::string DebugString() const
bool operator==(const ValueLiteralPair &o) const