14#ifndef OR_TOOLS_SAT_INTEGER_H_
15#define OR_TOOLS_SAT_INTEGER_H_
28#include "absl/base/attributes.h"
29#include "absl/container/btree_map.h"
30#include "absl/container/flat_hash_map.h"
31#include "absl/container/inlined_vector.h"
32#include "absl/log/check.h"
33#include "absl/strings/str_cat.h"
34#include "absl/types/span.h"
40#include "ortools/sat/sat_parameters.pb.h"
53 absl::InlinedVector<std::pair<IntegerVariable, IntegerValue>, 2>;
67 return absl::StrCat(
"(lit(",
literal.Index().value(),
") * ",
103 : sat_solver_(model->GetOrCreate<
SatSolver>()),
104 trail_(model->GetOrCreate<
Trail>()),
107 num_created_variables_(0) {}
114 VLOG(1) <<
"#variables created = " << num_created_variables_;
154 IntegerVariable var)
const;
156 IntegerVariable var)
const;
200 IntegerValue value)
const;
214 if (lit.
Index() >= reverse_encoding_.size()) {
215 return empty_integer_literal_vector_;
217 return reverse_encoding_[lit];
223 if (lit.
Index() >= reverse_equality_encoding_.size()) {
224 return empty_integer_value_vector_;
226 return reverse_equality_encoding_[lit];
233 temp_associated_vars_.clear();
235 temp_associated_vars_.push_back(l.var);
238 temp_associated_vars_.push_back(var);
240 return temp_associated_vars_;
249 return literal_view_[lit];
255 Literal lit, IntegerVariable* view =
nullptr,
256 bool* view_is_direct =
nullptr)
const;
267 IntegerValue* bound)
const;
272 DCHECK_EQ(0, sat_solver_->CurrentDecisionLevel());
274 Literal(sat_solver_->NewBooleanVariable(),
true);
275 literal_index_true_ = literal_true.
Index();
279 (void)sat_solver_->AddUnitClause(literal_true);
281 return Literal(literal_index_true_);
289 IntegerVariable var)
const;
303 void AddImplications(
304 const absl::btree_map<IntegerValue, Literal>& map,
305 absl::btree_map<IntegerValue, Literal>::const_iterator it,
313 bool add_implications_ =
true;
314 int64_t num_created_variables_ = 0;
332 absl::btree_map<IntegerValue, Literal>>
341 reverse_equality_encoding_;
344 mutable std::vector<IntegerVariable> temp_associated_vars_;
356 absl::flat_hash_map<std::pair<PositiveOnlyIndex, IntegerValue>,
Literal>
357 equality_to_associated_literal_;
361 absl::InlinedVector<ValueLiteralPair, 2>>
372 std::vector<IntegerValue> tmp_values_;
373 std::vector<ValueLiteralPair> tmp_encoding_;
376 mutable std::vector<ValueLiteralPair> partial_encoding_;
394 virtual void Explain(
int id, IntegerValue propagation_slack,
395 IntegerVariable var_to_explain,
int trail_index,
396 std::vector<Literal>* literals_reason,
397 std::vector<int>* trail_indices_reason) = 0;
410 trail_(model->GetOrCreate<
Trail>()),
411 sat_solver_(model->GetOrCreate<
SatSolver>()),
412 time_limit_(model->GetOrCreate<
TimeLimit>()),
413 parameters_(*model->GetOrCreate<SatParameters>()) {
427 void Untrail(const
Trail& trail,
int literal_trail_index) final;
429 int64_t conflict_id) const final;
436 return IntegerVariable(var_lbs_.size());
452 IntegerValue upper_bound);
496 bool IsFixed(IntegerVariable
i)
const;
566 absl::Span<const IntegerValue> coeffs,
567 std::vector<IntegerLiteral>* reason)
const;
571 absl::Span<const IntegerValue> coeffs,
572 absl::Span<const IntegerVariable> vars,
573 std::vector<IntegerLiteral>* reason)
const;
577 absl::Span<const IntegerValue> coeffs,
578 std::vector<int>* trail_indices)
const;
602 return EnqueueInternal(i_lit,
false, {}, {}, integer_trail_.size());
606 absl::Span<const IntegerLiteral> integer_reason) {
607 return EnqueueInternal(i_lit,
false, literal_reason, integer_reason,
608 integer_trail_.size());
621 IntegerLiteral i_lit, absl::Span<const IntegerLiteral> integer_reason);
631 std::vector<IntegerLiteral>* integer_reason);
642 absl::Span<const IntegerLiteral> integer_reason,
643 int trail_index_with_same_reason) {
644 return EnqueueInternal(i_lit,
false, literal_reason, integer_reason,
645 trail_index_with_same_reason);
652 const int trail_index = integer_trail_.size();
653 lazy_reasons_.push_back(LazyReasonEntry{explainer, propagation_slack,
654 i_lit.
var, id, trail_index});
655 return EnqueueInternal(i_lit,
true, {}, {}, 0);
670 absl::Span<const IntegerLiteral> integer_reason);
681 std::vector<Literal>* output)
const;
690 int64_t
timestamp()
const {
return num_enqueues_ + num_untrails_; }
700 watchers_.push_back(p);
706 absl::Span<const IntegerLiteral> integer_reason) {
707 DCHECK(ReasonIsValid(literal_reason, integer_reason));
708 std::vector<Literal>* conflict = trail_->MutableConflict();
709 conflict->assign(literal_reason.begin(), literal_reason.end());
714 DCHECK(ReasonIsValid({}, integer_reason));
715 std::vector<Literal>* conflict = trail_->MutableConflict();
723 return var_trail_index_[var] < var_lbs_.size();
729 reversible_classes_.push_back(rev);
732 int Index()
const {
return integer_trail_.size(); }
743 std::vector<IntegerLiteral>* output)
const;
767 return !delayed_to_fix_->literal_to_fix.empty() ||
768 !delayed_to_fix_->integer_literal_to_fix.empty();
774 std::function<
bool(absl::Span<const Literal> clause,
775 absl::Span<const IntegerLiteral> integers)>
777 debug_checker_ = std::move(checker);
788 IntegerValue target_min,
789 std::vector<int>* indices)
const {
790 int64_t num_processed = 0;
792 if (expr.IsConstant()) {
793 DCHECK_GE(expr.constant, target_min);
800 if (++num_processed % 5 == 0 && time_limit_->LimitReached())
return;
807 const int index = tmp_var_to_trail_index_in_queue_[expr.var];
808 if (index == std::numeric_limits<int>::max())
continue;
810 expr.ValueAt(integer_trail_[index].bound) >= target_min) {
811 has_dependency_ =
true;
819 FindLowestTrailIndexThatExplainBound(expr.GreaterOrEqual(target_min));
821 indices->push_back(index);
829 bool ReasonIsValid(absl::Span<const Literal> literal_reason,
830 absl::Span<const IntegerLiteral> integer_reason);
833 bool ReasonIsValid(
Literal lit, absl::Span<const Literal> literal_reason,
834 absl::Span<const IntegerLiteral> integer_reason);
836 absl::Span<const Literal> literal_reason,
837 absl::Span<const IntegerLiteral> integer_reason);
846 std::vector<Literal>* InitializeConflict(
848 absl::Span<const Literal> literals_reason,
849 absl::Span<const IntegerLiteral> bounds_reason);
852 int AppendReasonToInternalBuffers(
853 absl::Span<const Literal> literal_reason,
854 absl::Span<const IntegerLiteral> integer_reason);
857 ABSL_MUST_USE_RESULT
bool EnqueueInternal(
859 absl::Span<const Literal> literal_reason,
860 absl::Span<const IntegerLiteral> integer_reason,
861 int trail_index_with_same_reason);
864 void EnqueueLiteralInternal(
Literal literal,
bool use_lazy_reason,
865 absl::Span<const Literal> literal_reason,
866 absl::Span<const IntegerLiteral> integer_reason);
871 ABSL_MUST_USE_RESULT
bool EnqueueAssociatedIntegerLiteral(
875 void MergeReasonIntoInternal(std::vector<Literal>* output,
876 int64_t conflict_id)
const;
881 int FindLowestTrailIndexThatExplainBound(
IntegerLiteral i_lit)
const;
886 void ComputeLazyReasonIfNeeded(
int reason_index)
const;
893 absl::Span<const int> Dependencies(
int reason_index)
const;
899 void AppendLiteralsReason(
int reason_index,
900 std::vector<Literal>* output)
const;
903 std::string DebugString();
906 int64_t NextConflictId();
919 mutable int var_trail_index_cache_threshold_ = 0;
921 var_trail_index_cache_;
925 absl::flat_hash_map<IntegerValue, IntegerVariable> constant_map_;
932 int32_t prev_trail_index;
936 int32_t reason_index;
938 std::vector<TrailEntry> integer_trail_;
940 struct LazyReasonEntry {
941 LazyReasonInterface* explainer;
942 IntegerValue propagation_slack;
943 IntegerVariable var_to_explain;
945 int trail_index_at_propagation_time;
947 void Explain(std::vector<Literal>* literals,
948 std::vector<int>* dependencies)
const {
949 explainer->Explain(
id, propagation_slack, var_to_explain,
950 trail_index_at_propagation_time, literals,
954 std::vector<int> lazy_reason_decision_levels_;
955 std::vector<LazyReasonEntry> lazy_reasons_;
959 std::vector<int> integer_search_levels_;
962 std::vector<int> reason_decision_levels_;
963 std::vector<int> literals_reason_starts_;
964 std::vector<Literal> literals_reason_buffer_;
969 std::vector<int> bounds_reason_starts_;
970 mutable std::vector<int> cached_sizes_;
971 std::vector<IntegerLiteral> bounds_reason_buffer_;
972 mutable std::vector<int> trail_index_reason_buffer_;
975 mutable std::vector<Literal> lazy_reason_literals_;
976 mutable std::vector<int> lazy_reason_trail_indices_;
979 mutable bool has_dependency_ =
false;
980 mutable std::vector<int> tmp_queue_;
981 mutable std::vector<IntegerVariable> tmp_to_clear_;
982 mutable util_intops::StrongVector<IntegerVariable, int>
983 tmp_var_to_trail_index_in_queue_;
984 mutable SparseBitset<BooleanVariable> added_variables_;
987 struct RelaxHeapEntry {
991 bool operator<(
const RelaxHeapEntry& o)
const {
return index < o.index; }
993 mutable std::vector<RelaxHeapEntry> relax_heap_;
994 mutable std::vector<int> tmp_indices_;
997 mutable SparseBitset<IntegerVariable> tmp_marked_;
1000 std::vector<IntegerLiteral> tmp_cleaned_reason_;
1003 std::vector<int> boolean_trail_index_to_reason_index_;
1007 int first_level_without_full_propagation_ = -1;
1012 mutable int64_t last_conflict_id_ = -1;
1013 mutable bool info_is_valid_on_subsequent_last_level_expansion_ =
false;
1014 mutable util_intops::StrongVector<IntegerVariable, int>
1015 var_to_trail_index_at_lower_level_;
1016 mutable std::vector<int> tmp_seen_;
1017 mutable std::vector<IntegerVariable> to_clear_for_lower_level_;
1019 int64_t num_enqueues_ = 0;
1020 int64_t num_untrails_ = 0;
1021 int64_t num_level_zero_enqueues_ = 0;
1022 mutable int64_t num_decisions_to_break_loop_ = 0;
1024 std::vector<SparseBitset<IntegerVariable>*> watchers_;
1025 std::vector<ReversibleInterface*> reversible_classes_;
1027 mutable Domain temp_domain_;
1028 DelayedRootLevelDeduction* delayed_to_fix_;
1029 IntegerDomains* domains_;
1030 IntegerEncoder* encoder_;
1032 SatSolver* sat_solver_;
1033 TimeLimit* time_limit_;
1034 const SatParameters& parameters_;
1039 absl::flat_hash_map<std::pair<LiteralIndex, IntegerVariable>, IntegerValue>
1042 std::function<bool(absl::Span<const Literal> clause,
1043 absl::Span<const IntegerLiteral> integers)>
1044 debug_checker_ =
nullptr;
1072 LOG(FATAL) <<
"Not implemented.";
1113 void Untrail(const
Trail& trail,
int literal_trail_index) final;
1142 void WatchLowerBound(IntegerVariable var,
int id,
int watch_index = -1);
1143 void WatchUpperBound(IntegerVariable var,
int id,
int watch_index = -1);
1200 bool_to_reset_on_backtrack_.push_back(is_in_dive);
1217 const std::function<
void(
const std::vector<IntegerVariable>&)> cb) {
1218 level_zero_modified_variable_callback_.push_back(cb);
1227 stop_propagation_callback_ = callback;
1241 void UpdateCallingNeeds(
Trail* trail);
1251 return id == o.id && watch_index == o.watch_index;
1255 literal_to_watcher_;
1258 std::vector<PropagatorInterface*> watchers_;
1259 SparseBitset<IntegerVariable> modified_vars_;
1262 SparseBitset<IntegerVariable> modified_vars_for_callback_;
1266 std::vector<std::deque<int>> queue_by_priority_;
1267 std::vector<bool> in_queue_;
1271 std::vector<bool> id_need_reversible_support_;
1272 std::vector<int> id_to_level_at_last_call_;
1273 RevVector<IdType, int> id_to_greatest_common_level_since_last_call_;
1274 std::vector<std::vector<ReversibleInterface*>> id_to_reversible_classes_;
1275 std::vector<std::vector<int*>> id_to_reversible_ints_;
1277 std::vector<std::vector<int>> id_to_watch_indices_;
1278 std::vector<int> id_to_priority_;
1279 std::vector<int> id_to_idempotence_;
1282 std::vector<int> propagator_ids_to_call_at_level_zero_;
1287 std::vector<std::function<void(
const std::vector<IntegerVariable>&)>>
1288 level_zero_modified_variable_callback_;
1290 std::function<bool()> stop_propagation_callback_;
1292 std::vector<bool*> bool_to_reset_on_backtrack_;
1317 Literal l, IntegerVariable
i)
const {
1318 const auto it = conditional_lbs_.find({l.
Index(),
i});
1319 if (it != conditional_lbs_.end()) {
1320 return std::max(var_lbs_[
i], it->second);
1326 Literal l, AffineExpression expr)
const {
1332 Literal l, IntegerVariable
i)
const {
1343 IntegerVariable
i)
const {
1348 IntegerVariable
i)
const {
1395 IntegerVariable var)
const {
1396 return integer_trail_[var.value()].bound;
1400 IntegerVariable var)
const {
1405 return integer_trail_[var.value()].bound ==
1428 if (l.
Index() >= literal_to_watcher_.size()) {
1429 literal_to_watcher_.resize(l.
Index().value() + 1);
1431 literal_to_watcher_[l].
push_back({id, watch_index});
1437 if (var.value() >= var_to_watcher_.size()) {
1438 var_to_watcher_.resize(var.value() + 1);
1445 const WatchData data = {id, watch_index};
1446 if (!var_to_watcher_[var].empty() && var_to_watcher_[var].back() == data) {
1474 return [=](
Model* model) {
1481 return [=](
Model* model) {
1483 ->GetOrCreateConstantIntegerVariable(IntegerValue(value));
1489 return [=](
Model* model) {
1492 IntegerValue(lb), IntegerValue(ub));
1498 return [=](
Model* model) {
1499 return model->
GetOrCreate<IntegerTrail>()->AddIntegerVariable(domain);
1507 auto* encoder = model->GetOrCreate<IntegerEncoder>();
1508 const IntegerVariable candidate = encoder->GetLiteralView(lit);
1511 IntegerVariable var;
1512 auto* integer_trail = model->GetOrCreate<
IntegerTrail>();
1514 if (assignment.LiteralIsTrue(lit)) {
1515 var = integer_trail->GetOrCreateConstantIntegerVariable(IntegerValue(1));
1516 }
else if (assignment.LiteralIsFalse(lit)) {
1517 var = integer_trail->GetOrCreateConstantIntegerVariable(IntegerValue(0));
1519 var = integer_trail->AddIntegerVariable(IntegerValue(0), IntegerValue(1));
1522 encoder->AssociateToIntegerEqualValue(lit, var, IntegerValue(1));
1530 return [=](
Model* model) {
1535inline std::function<int64_t(
const Model&)>
LowerBound(IntegerVariable v) {
1536 return [=](
const Model& model) {
1537 return model.Get<IntegerTrail>()->
LowerBound(v).value();
1541inline std::function<int64_t(
const Model&)>
UpperBound(IntegerVariable v) {
1542 return [=](
const Model& model) {
1543 return model.Get<IntegerTrail>()->
UpperBound(v).value();
1547inline std::function<bool(
const Model&)>
IsFixed(IntegerVariable v) {
1548 return [=](
const Model& model) {
1549 const IntegerTrail* trail = model.Get<IntegerTrail>();
1550 return trail->LowerBound(v) == trail->UpperBound(v);
1555inline std::function<int64_t(
const Model&)>
Value(IntegerVariable v) {
1556 return [=](
const Model& model) {
1557 const IntegerTrail* trail = model.Get<IntegerTrail>();
1558 CHECK_EQ(trail->LowerBound(v), trail->UpperBound(v)) << v;
1559 return trail->LowerBound(v).value();
1565 return [=](
Model* model) {
1566 if (!model->GetOrCreate<IntegerTrail>()->Enqueue(
1568 std::vector<Literal>(), std::vector<IntegerLiteral>())) {
1569 model->GetOrCreate<
SatSolver>()->NotifyThatModelIsUnsat();
1570 VLOG(1) <<
"Model trivially infeasible, variable " << v
1571 <<
" has upper bound " << model->Get(
UpperBound(v))
1572 <<
" and GreaterOrEqual() was called with a lower bound of "
1579 return [=](
Model* model) {
1582 std::vector<Literal>(), std::vector<IntegerLiteral>())) {
1583 model->GetOrCreate<
SatSolver>()->NotifyThatModelIsUnsat();
1584 VLOG(1) <<
"Model trivially infeasible, variable " << v
1585 <<
" has lower bound " << model->Get(
LowerBound(v))
1586 <<
" and LowerOrEqual() was called with an upper bound of " << ub;
1592inline std::function<void(
Model*)>
Equality(IntegerVariable v, int64_t value) {
1593 return [=](
Model* model) {
1606 absl::Span<const Literal> enforcement_literals, IntegerLiteral
i) {
1607 return [=](
Model* model) {
1608 auto* sat_solver = model->GetOrCreate<SatSolver>();
1610 if (
i.bound <= integer_trail->LowerBound(
i.var)) {
1612 }
else if (
i.bound > integer_trail->UpperBound(
i.var)) {
1614 std::vector<Literal> clause;
1615 for (
const Literal literal : enforcement_literals) {
1616 clause.push_back(literal.Negated());
1618 sat_solver->AddClauseDuringSearch(clause);
1623 std::vector<Literal> clause{encoder->GetOrCreateAssociatedLiteral(
i)};
1624 for (
const Literal literal : enforcement_literals) {
1625 clause.push_back(literal.Negated());
1627 sat_solver->AddClauseDuringSearch(clause);
1635 int64_t lb, int64_t ub) {
1636 return [=](
Model* model) {
1641 v, IntegerValue(lb))));
1656 IntegerVariable var) {
1657 return [=](
Model* model) {
1659 if (!encoder->VariableIsFullyEncoded(var)) {
1660 encoder->FullyEncodeVariable(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
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)
Fix v to a given 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)
Returns the vector of the negated variables.
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)
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)
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
std::function< void(Model *)> ImpliesInInterval(Literal in_interval, IntegerVariable v, int64_t lb, int64_t ub)
in_interval => v in [lb, ub].
IntegerVariable CreateNewIntegerVariableFromLiteral(Literal lit, Model *model)
In SWIG mode, we don't want anything besides these top-level includes.
#define DEFINE_STRONG_INDEX_TYPE(index_type_name)
IntegerValue ValueAt(IntegerValue var_value) const
Returns the value of this affine expression given its variable value.
std::vector< IntegerLiteral > integer_literal_to_fix
std::vector< Literal > literal_to_fix
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)
static IntegerLiteral TrueLiteral()
static IntegerLiteral LowerOrEqual(IntegerVariable i, IntegerValue bound)
bool operator==(const LiteralValueValue &rhs) const
Used for testing.
std::string DebugString() const