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) {
83 DCHECK_GT(positive_divisor, 0);
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) {
92 DCHECK_GT(positive_divisor, 0);
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) {
104 DCHECK_GT(positive_divisor, 0);
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);
182 ? absl::StrCat(
"I",
var.value() / 2,
">=",
bound.value())
183 : absl::StrCat(
"I",
var.value() / 2,
"<=", -
bound.value());
188 IntegerValue
bound = IntegerValue(0);
226 IntegerValue
coeff = IntegerValue(0);
247 :
public std::vector<std::function<LiteralIndex()>> {};
272 num_created_variables_(0) {}
275 VLOG(1) <<
"#variables created = " << num_created_variables_;
324 IntegerVariable
var)
const;
368 IntegerValue
value)
const;
382 if (lit.
Index() >= reverse_encoding_.
size()) {
383 return empty_integer_literal_vector_;
385 return reverse_encoding_[lit.
Index()];
392 if (lit.
Index() >= full_reverse_encoding_.
size()) {
393 return empty_integer_literal_vector_;
395 return full_reverse_encoding_[lit.
Index()];
401 return newly_fixed_integer_literals_;
404 newly_fixed_integer_literals_.clear();
413 return literal_view_[lit.
Index()];
425 IntegerValue*
bound)
const;
433 literal_index_true_ = literal_true.
Index();
436 return Literal(literal_index_true_);
444 IntegerVariable
var)
const {
445 if (
var >= encoding_by_var_.size()) {
446 return std::map<IntegerValue, Literal>();
448 return encoding_by_var_[
var];
464 void AddImplications(
const std::map<IntegerValue, Literal>& map,
465 std::map<IntegerValue, Literal>::const_iterator it,
471 bool add_implications_ =
true;
472 int64 num_created_variables_ = 0;
487 full_reverse_encoding_;
488 std::vector<IntegerLiteral> newly_fixed_integer_literals_;
500 absl::flat_hash_map<std::pair<PositiveOnlyIndex, IntegerValue>,
Literal>
501 equality_to_associated_literal_;
515 std::vector<IntegerValue> tmp_values_;
530 parameters_(*
model->GetOrCreate<SatParameters>()) {
540 void Untrail(const
Trail& trail,
int literal_trail_index) final;
542 int trail_index) const final;
549 return IntegerVariable(vars_.
size());
565 IntegerValue upper_bound);
609 const LiteralIndex is_ignored_literal = is_ignored_literals_[i];
615 return Literal(is_ignored_literals_[i]);
624 is_ignored_literals_[i] == is_considered.
NegatedIndex());
630 IntegerValue
LowerBound(IntegerVariable i)
const;
631 IntegerValue
UpperBound(IntegerVariable i)
const;
634 bool IsFixed(IntegerVariable i)
const;
678 absl::Span<const IntegerValue> coeffs,
679 std::vector<IntegerLiteral>* reason)
const;
683 absl::Span<const IntegerValue> coeffs,
684 absl::Span<const IntegerVariable> vars,
685 std::vector<IntegerLiteral>* reason)
const;
689 absl::Span<const IntegerValue> coeffs,
690 std::vector<int>* trail_indices)
const;
713 ABSL_MUST_USE_RESULT
bool Enqueue(
715 absl::Span<const IntegerLiteral> integer_reason);
724 ABSL_MUST_USE_RESULT
bool Enqueue(
726 absl::Span<const IntegerLiteral> integer_reason,
727 int trail_index_with_same_reason);
742 std::vector<Literal>* literals, std::vector<int>* dependencies)>;
749 absl::Span<const IntegerLiteral> integer_reason);
759 std::vector<Literal>* output)
const;
778 watchers_.push_back(p);
784 absl::Span<const IntegerLiteral> integer_reason) {
785 DCHECK(ReasonIsValid(literal_reason, integer_reason));
787 conflict->assign(literal_reason.begin(), literal_reason.end());
792 DCHECK(ReasonIsValid({}, integer_reason));
801 return vars_[
var].current_trail_index < vars_.
size();
807 reversible_classes_.push_back(rev);
810 int Index()
const {
return integer_trail_.size(); }
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_;
980 struct RelaxHeapEntry {
984 bool operator<(
const RelaxHeapEntry& o)
const {
return index < o.index; }
986 mutable std::vector<RelaxHeapEntry> relax_heap_;
987 mutable std::vector<int> tmp_indices_;
990 mutable SparseBitset<IntegerVariable> tmp_marked_;
996 std::vector<int> boolean_trail_index_to_integer_one_;
1000 int first_level_without_full_propagation_ = -1;
1002 int64 num_enqueues_ = 0;
1003 int64 num_untrails_ = 0;
1004 int64 num_level_zero_enqueues_ = 0;
1005 mutable int64 num_decisions_to_break_loop_ = 0;
1007 std::vector<SparseBitset<IntegerVariable>*> watchers_;
1008 std::vector<ReversibleInterface*> reversible_classes_;
1010 IntegerDomains* domains_;
1011 IntegerEncoder* encoder_;
1013 const SatParameters& parameters_;
1043 LOG(FATAL) <<
"Not implemented.";
1076 void Untrail(
const Trail& trail,
int literal_trail_index)
final;
1150 const std::function<
void(
const std::vector<IntegerVariable>&)> cb) {
1151 level_zero_modified_variable_callback_.push_back(cb);
1162 void UpdateCallingNeeds(
Trail* trail);
1174 std::vector<PropagatorInterface*> watchers_;
1179 std::vector<std::deque<int>> queue_by_priority_;
1180 std::vector<bool> in_queue_;
1183 DEFINE_INT_TYPE(IdType,
int32);
1184 std::vector<int> id_to_level_at_last_call_;
1186 std::vector<std::vector<ReversibleInterface*>> id_to_reversible_classes_;
1187 std::vector<std::vector<int*>> id_to_reversible_ints_;
1188 std::vector<std::vector<int>> id_to_watch_indices_;
1189 std::vector<int> id_to_priority_;
1190 std::vector<int> id_to_idempotence_;
1193 std::vector<int> propagator_ids_to_call_at_level_zero_;
1198 std::vector<std::function<void(
const std::vector<IntegerVariable>&)>>
1199 level_zero_modified_variable_callback_;
1209 IntegerValue
bound) {
1215 IntegerValue
bound) {
1229 return vars_[i].current_bound;
1237 return vars_[i].current_bound == -vars_[
NegationOf(i)].current_bound;
1259 IntegerVariable i)
const {
1264 IntegerVariable i)
const {
1279 IntegerVariable
var)
const {
1280 return integer_trail_[
var.value()].bound;
1284 IntegerVariable
var)
const {
1289 return integer_trail_[
var.value()].bound ==
1295 if (l.
Index() >= literal_to_watcher_.
size()) {
1296 literal_to_watcher_.
resize(l.
Index().value() + 1);
1304 if (
var.value() >= var_to_watcher_.
size()) {
1305 var_to_watcher_.
resize(
var.value() + 1);
1341 ->GetOrCreateConstantIntegerVariable(IntegerValue(
value));
1350 IntegerValue(lb), IntegerValue(ub));
1370 IntegerVariable
var;
1371 const auto& assignment =
model->GetOrCreate<
SatSolver>()->Assignment();
1372 if (assignment.LiteralIsTrue(lit)) {
1374 }
else if (assignment.LiteralIsFalse(lit)) {
1380 encoder->AssociateToIntegerEqualValue(lit,
var, IntegerValue(1));
1418 std::vector<Literal>(), std::vector<IntegerLiteral>())) {
1420 VLOG(1) <<
"Model trivially infeasible, variable " << v
1422 <<
" and GreaterOrEqual() was called with a lower bound of "
1432 std::vector<Literal>(), std::vector<IntegerLiteral>())) {
1434 LOG(WARNING) <<
"Model trivially infeasible, variable " << v
1436 <<
" and LowerOrEqual() was called with an upper bound of "
1457 const std::vector<Literal>& enforcement_literals,
IntegerLiteral i) {
1464 std::vector<Literal> clause;
1491 v, IntegerValue(lb))));
1505 inline std::function<std::vector<IntegerEncoder::ValueLiteralPair>(Model*)>
1521 std::function<void(Model*)>
1527 #endif // OR_TOOLS_SAT_INTEGER_H_