14 #ifndef OR_TOOLS_SAT_INTEGER_H_
15 #define OR_TOOLS_SAT_INTEGER_H_
26 #include "absl/container/flat_hash_map.h"
27 #include "absl/container/inlined_vector.h"
28 #include "absl/strings/str_cat.h"
29 #include "absl/types/span.h"
70 const double kInfinity = std::numeric_limits<double>::infinity();
73 return static_cast<double>(
value.value());
76 template <
class IntType>
78 return IntType(std::abs(t.value()));
81 inline IntegerValue
CeilRatio(IntegerValue dividend,
82 IntegerValue positive_divisor) {
84 const IntegerValue result = dividend / positive_divisor;
85 const IntegerValue adjust =
86 static_cast<IntegerValue
>(result * positive_divisor < dividend);
87 return result + adjust;
91 IntegerValue positive_divisor) {
93 const IntegerValue result = dividend / positive_divisor;
94 const IntegerValue adjust =
95 static_cast<IntegerValue
>(result * positive_divisor > dividend);
96 return result - adjust;
103 IntegerValue positive_divisor) {
105 const IntegerValue m = dividend % positive_divisor;
106 return m < 0 ? m + positive_divisor : m;
115 *result = IntegerValue(add);
127 return IntegerVariable(i.value() ^ 1);
131 return (i.value() & 1) == 0;
135 return IntegerVariable(i.value() & (~1));
141 return PositiveOnlyIndex(
var.value() / 2);
146 const std::vector<IntegerVariable>& vars);
184 ? absl::StrCat(
"I",
var.value() / 2,
">=",
bound.value())
185 : absl::StrCat(
"I",
var.value() / 2,
"<=", -
bound.value());
190 IntegerValue
bound = IntegerValue(0);
228 IntegerValue
coeff = IntegerValue(0);
267 num_created_variables_(0) {}
270 VLOG(1) <<
"#variables created = " << num_created_variables_;
319 IntegerVariable
var)
const;
363 IntegerValue
value)
const;
377 if (lit.
Index() >= reverse_encoding_.
size()) {
378 return empty_integer_literal_vector_;
380 return reverse_encoding_[lit.
Index()];
387 if (lit.
Index() >= full_reverse_encoding_.
size()) {
388 return empty_integer_literal_vector_;
390 return full_reverse_encoding_[lit.
Index()];
396 return newly_fixed_integer_literals_;
399 newly_fixed_integer_literals_.clear();
408 return literal_view_[lit.
Index()];
420 IntegerValue*
bound)
const;
428 literal_index_true_ = literal_true.
Index();
431 return Literal(literal_index_true_);
439 IntegerVariable
var)
const {
440 if (
var >= encoding_by_var_.size()) {
441 return std::map<IntegerValue, Literal>();
443 return encoding_by_var_[
var];
459 void AddImplications(
const std::map<IntegerValue, Literal>& map,
460 std::map<IntegerValue, Literal>::const_iterator it,
466 bool add_implications_ =
true;
467 int64 num_created_variables_ = 0;
482 full_reverse_encoding_;
483 std::vector<IntegerLiteral> newly_fixed_integer_literals_;
495 absl::flat_hash_map<std::pair<PositiveOnlyIndex, IntegerValue>,
Literal>
496 equality_to_associated_literal_;
510 std::vector<IntegerValue> tmp_values_;
525 parameters_(*
model->GetOrCreate<SatParameters>()) {
535 void Untrail(const
Trail& trail,
int literal_trail_index) final;
537 int trail_index) const final;
544 return IntegerVariable(vars_.
size());
560 IntegerValue upper_bound);
604 const LiteralIndex is_ignored_literal = is_ignored_literals_[i];
610 return Literal(is_ignored_literals_[i]);
619 is_ignored_literals_[i] == is_considered.
NegatedIndex());
625 IntegerValue
LowerBound(IntegerVariable i)
const;
626 IntegerValue
UpperBound(IntegerVariable i)
const;
629 bool IsFixed(IntegerVariable i)
const;
673 absl::Span<const IntegerValue> coeffs,
674 std::vector<IntegerLiteral>* reason)
const;
678 absl::Span<const IntegerValue> coeffs,
679 absl::Span<const IntegerVariable> vars,
680 std::vector<IntegerLiteral>* reason)
const;
684 absl::Span<const IntegerValue> coeffs,
685 std::vector<int>* trail_indices)
const;
708 ABSL_MUST_USE_RESULT
bool Enqueue(
710 absl::Span<const IntegerLiteral> integer_reason);
719 ABSL_MUST_USE_RESULT
bool Enqueue(
721 absl::Span<const IntegerLiteral> integer_reason,
722 int trail_index_with_same_reason);
737 std::vector<Literal>* literals, std::vector<int>* dependencies)>;
744 absl::Span<const IntegerLiteral> integer_reason);
754 std::vector<Literal>* output)
const;
773 watchers_.push_back(p);
779 absl::Span<const IntegerLiteral> integer_reason) {
780 DCHECK(ReasonIsValid(literal_reason, integer_reason));
782 conflict->assign(literal_reason.begin(), literal_reason.end());
787 DCHECK(ReasonIsValid({}, integer_reason));
796 return vars_[
var].current_trail_index < vars_.
size();
802 reversible_classes_.push_back(rev);
805 int Index()
const {
return integer_trail_.size(); }
833 return !literal_to_fix_.empty() || !integer_literal_to_fix_.empty();
839 bool ReasonIsValid(absl::Span<const Literal> literal_reason,
840 absl::Span<const IntegerLiteral> integer_reason);
845 std::vector<Literal>* InitializeConflict(
847 absl::Span<const Literal> literals_reason,
848 absl::Span<const IntegerLiteral> bounds_reason);
851 ABSL_MUST_USE_RESULT
bool EnqueueInternal(
853 absl::Span<const Literal> literal_reason,
854 absl::Span<const IntegerLiteral> integer_reason,
855 int trail_index_with_same_reason);
859 absl::Span<const Literal> literal_reason,
860 absl::Span<const IntegerLiteral> integer_reason);
865 ABSL_MUST_USE_RESULT
bool EnqueueAssociatedIntegerLiteral(
869 void MergeReasonIntoInternal(std::vector<Literal>* output)
const;
874 int FindLowestTrailIndexThatExplainBound(
IntegerLiteral i_lit)
const;
879 void ComputeLazyReasonIfNeeded(
int trail_index)
const;
886 absl::Span<const int> Dependencies(
int trail_index)
const;
892 void AppendLiteralsReason(
int trail_index,
893 std::vector<Literal>* output)
const;
896 std::string DebugString();
901 IntegerValue current_bound;
904 int current_trail_index;
914 mutable int var_trail_index_cache_threshold_ = 0;
919 absl::flat_hash_map<IntegerValue, IntegerVariable> constant_map_;
926 int32 prev_trail_index;
933 std::vector<TrailEntry> integer_trail_;
934 std::vector<LazyReasonFunction> lazy_reasons_;
938 std::vector<int> integer_search_levels_;
945 std::vector<int> reason_decision_levels_;
946 std::vector<int> literals_reason_starts_;
947 std::vector<int> bounds_reason_starts_;
948 std::vector<Literal> literals_reason_buffer_;
953 std::vector<IntegerLiteral> bounds_reason_buffer_;
954 mutable std::vector<int> trail_index_reason_buffer_;
957 mutable std::vector<Literal> lazy_reason_literals_;
958 mutable std::vector<int> lazy_reason_trail_indices_;
969 RevMap<absl::flat_hash_map<IntegerVariable, int>>
970 var_to_current_lb_interval_index_;
973 mutable bool has_dependency_ =
false;
974 mutable std::vector<int> tmp_queue_;
975 mutable std::vector<IntegerVariable> tmp_to_clear_;
977 mutable SparseBitset<BooleanVariable> added_variables_;
984 std::vector<Literal> literal_to_fix_;
985 std::vector<IntegerLiteral> integer_literal_to_fix_;
988 struct RelaxHeapEntry {
992 bool operator<(
const RelaxHeapEntry& o)
const {
return index < o.index; }
994 mutable std::vector<RelaxHeapEntry> relax_heap_;
995 mutable std::vector<int> tmp_indices_;
998 mutable SparseBitset<IntegerVariable> tmp_marked_;
1004 std::vector<int> boolean_trail_index_to_integer_one_;
1008 int first_level_without_full_propagation_ = -1;
1010 int64 num_enqueues_ = 0;
1011 int64 num_untrails_ = 0;
1012 int64 num_level_zero_enqueues_ = 0;
1013 mutable int64 num_decisions_to_break_loop_ = 0;
1015 std::vector<SparseBitset<IntegerVariable>*> watchers_;
1016 std::vector<ReversibleInterface*> reversible_classes_;
1018 IntegerDomains* domains_;
1019 IntegerEncoder* encoder_;
1021 const SatParameters& parameters_;
1084 void Untrail(
const Trail& trail,
int literal_trail_index)
final;
1158 const std::function<
void(
const std::vector<IntegerVariable>&)> cb) {
1159 level_zero_modified_variable_callback_.push_back(cb);
1170 void UpdateCallingNeeds(
Trail* trail);
1182 std::vector<PropagatorInterface*> watchers_;
1187 std::vector<std::deque<int>> queue_by_priority_;
1188 std::vector<bool> in_queue_;
1191 DEFINE_INT_TYPE(IdType,
int32);
1192 std::vector<int> id_to_level_at_last_call_;
1194 std::vector<std::vector<ReversibleInterface*>> id_to_reversible_classes_;
1195 std::vector<std::vector<int*>> id_to_reversible_ints_;
1196 std::vector<std::vector<int>> id_to_watch_indices_;
1197 std::vector<int> id_to_priority_;
1198 std::vector<int> id_to_idempotence_;
1201 std::vector<int> propagator_ids_to_call_at_level_zero_;
1206 std::vector<std::function<void(
const std::vector<IntegerVariable>&)>>
1207 level_zero_modified_variable_callback_;
1217 IntegerValue
bound) {
1223 IntegerValue
bound) {
1237 return vars_[i].current_bound;
1245 return vars_[i].current_bound == -vars_[
NegationOf(i)].current_bound;
1267 IntegerVariable i)
const {
1272 IntegerVariable i)
const {
1287 IntegerVariable
var)
const {
1288 return integer_trail_[
var.value()].bound;
1292 IntegerVariable
var)
const {
1297 return integer_trail_[
var.value()].bound ==
1303 if (l.
Index() >= literal_to_watcher_.
size()) {
1304 literal_to_watcher_.
resize(l.
Index().value() + 1);
1312 if (
var.value() >= var_to_watcher_.
size()) {
1313 var_to_watcher_.
resize(
var.value() + 1);
1349 ->GetOrCreateConstantIntegerVariable(IntegerValue(
value));
1358 IntegerValue(lb), IntegerValue(ub));
1378 IntegerVariable
var;
1380 if (assignment.LiteralIsTrue(lit)) {
1382 }
else if (assignment.LiteralIsFalse(lit)) {
1388 encoder->AssociateToIntegerEqualValue(lit,
var, IntegerValue(1));
1426 std::vector<Literal>(), std::vector<IntegerLiteral>())) {
1428 VLOG(1) <<
"Model trivially infeasible, variable " << v
1430 <<
" and GreaterOrEqual() was called with a lower bound of "
1440 std::vector<Literal>(), std::vector<IntegerLiteral>())) {
1442 LOG(
WARNING) <<
"Model trivially infeasible, variable " << v
1444 <<
" and LowerOrEqual() was called with an upper bound of "
1465 const std::vector<Literal>& enforcement_literals,
IntegerLiteral i) {
1472 std::vector<Literal> clause;
1499 v, IntegerValue(lb))));
1513 inline std::function<std::vector<IntegerEncoder::ValueLiteralPair>(Model*)>
1529 std::function<void(Model*)>
1535 #endif // OR_TOOLS_SAT_INTEGER_H_