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
Subtract(IntegerValue
a, IntegerValue
b) {
89 return IntegerValue(result);
92 inline IntegerValue
CeilRatio(IntegerValue dividend,
93 IntegerValue positive_divisor) {
94 DCHECK_GT(positive_divisor, 0);
95 const IntegerValue result = dividend / positive_divisor;
96 const IntegerValue adjust =
97 static_cast<IntegerValue
>(result * positive_divisor < dividend);
98 return result + adjust;
102 IntegerValue positive_divisor) {
103 DCHECK_GT(positive_divisor, 0);
104 const IntegerValue result = dividend / positive_divisor;
105 const IntegerValue adjust =
106 static_cast<IntegerValue
>(result * positive_divisor > dividend);
107 return result - adjust;
114 IntegerValue positive_divisor) {
115 DCHECK_GT(positive_divisor, 0);
116 const IntegerValue m = dividend % positive_divisor;
117 return m < 0 ? m + positive_divisor : m;
126 *result = IntegerValue(add);
138 return IntegerVariable(i.value() ^ 1);
142 return (i.value() & 1) == 0;
146 return IntegerVariable(i.value() & (~1));
152 return PositiveOnlyIndex(
var.value() / 2);
157 const std::vector<IntegerVariable>& vars);
193 ? absl::StrCat(
"I",
var.value() / 2,
">=",
bound.value())
194 : absl::StrCat(
"I",
var.value() / 2,
"<=", -
bound.value());
199 IntegerValue
bound = IntegerValue(0);
237 IntegerValue
coeff = IntegerValue(0);
258 :
public std::vector<std::function<LiteralIndex()>> {};
283 num_created_variables_(0) {}
286 VLOG(1) <<
"#variables created = " << num_created_variables_;
335 IntegerVariable
var)
const;
379 IntegerValue
value)
const;
393 if (lit.
Index() >= reverse_encoding_.
size()) {
394 return empty_integer_literal_vector_;
396 return reverse_encoding_[lit.
Index()];
403 if (lit.
Index() >= full_reverse_encoding_.
size()) {
404 return empty_integer_literal_vector_;
406 return full_reverse_encoding_[lit.
Index()];
412 return newly_fixed_integer_literals_;
415 newly_fixed_integer_literals_.clear();
424 return literal_view_[lit.
Index()];
436 IntegerValue*
bound)
const;
444 literal_index_true_ = literal_true.
Index();
447 return Literal(literal_index_true_);
455 IntegerVariable
var)
const {
456 if (
var >= encoding_by_var_.size()) {
457 return std::map<IntegerValue, Literal>();
459 return encoding_by_var_[
var];
475 void AddImplications(
const std::map<IntegerValue, Literal>& map,
476 std::map<IntegerValue, Literal>::const_iterator it,
482 bool add_implications_ =
true;
483 int64 num_created_variables_ = 0;
498 full_reverse_encoding_;
499 std::vector<IntegerLiteral> newly_fixed_integer_literals_;
511 absl::flat_hash_map<std::pair<PositiveOnlyIndex, IntegerValue>,
Literal>
512 equality_to_associated_literal_;
526 std::vector<IntegerValue> tmp_values_;
550 void Untrail(
const Trail& trail,
int literal_trail_index)
final;
551 absl::Span<const Literal>
Reason(
const Trail& trail,
552 int trail_index)
const final;
559 return IntegerVariable(vars_.
size());
569 IntegerValue upper_bound);
613 const LiteralIndex is_ignored_literal = is_ignored_literals_[i];
619 return Literal(is_ignored_literals_[i]);
628 is_ignored_literals_[i] == is_considered.
NegatedIndex());
634 IntegerValue
LowerBound(IntegerVariable i)
const;
635 IntegerValue
UpperBound(IntegerVariable i)
const;
638 bool IsFixed(IntegerVariable i)
const;
679 absl::Span<const IntegerValue> coeffs,
680 std::vector<IntegerLiteral>* reason)
const;
684 absl::Span<const IntegerValue> coeffs,
685 absl::Span<const IntegerVariable> vars,
686 std::vector<IntegerLiteral>* reason)
const;
690 absl::Span<const IntegerValue> coeffs,
691 std::vector<int>* trail_indices)
const;
714 ABSL_MUST_USE_RESULT
bool Enqueue(
716 absl::Span<const IntegerLiteral> integer_reason);
725 ABSL_MUST_USE_RESULT
bool Enqueue(
727 absl::Span<const IntegerLiteral> integer_reason,
728 int trail_index_with_same_reason);
743 std::vector<Literal>* literals, std::vector<int>* dependencies)>;
750 absl::Span<const IntegerLiteral> integer_reason);
760 std::vector<Literal>* output)
const;
779 watchers_.push_back(p);
785 absl::Span<const IntegerLiteral> integer_reason) {
786 DCHECK(ReasonIsValid(literal_reason, integer_reason));
788 conflict->assign(literal_reason.begin(), literal_reason.end());
793 DCHECK(ReasonIsValid({}, integer_reason));
802 return vars_[
var].current_trail_index < vars_.
size();
808 reversible_classes_.push_back(rev);
811 int Index()
const {
return integer_trail_.size(); }
829 bool ReasonIsValid(absl::Span<const Literal> literal_reason,
830 absl::Span<const IntegerLiteral> integer_reason);
835 std::vector<Literal>* InitializeConflict(
837 absl::Span<const Literal> literals_reason,
838 absl::Span<const IntegerLiteral> bounds_reason);
841 ABSL_MUST_USE_RESULT
bool EnqueueInternal(
843 absl::Span<const Literal> literal_reason,
844 absl::Span<const IntegerLiteral> integer_reason,
845 int trail_index_with_same_reason);
849 absl::Span<const Literal> literal_reason,
850 absl::Span<const IntegerLiteral> integer_reason);
855 ABSL_MUST_USE_RESULT
bool EnqueueAssociatedIntegerLiteral(
859 void MergeReasonIntoInternal(std::vector<Literal>* output)
const;
864 int FindLowestTrailIndexThatExplainBound(
IntegerLiteral i_lit)
const;
869 void ComputeLazyReasonIfNeeded(
int trail_index)
const;
876 absl::Span<const int> Dependencies(
int trail_index)
const;
882 void AppendLiteralsReason(
int trail_index,
883 std::vector<Literal>* output)
const;
886 std::string DebugString();
891 IntegerValue current_bound;
894 int current_trail_index;
904 mutable int var_trail_index_cache_threshold_ = 0;
909 absl::flat_hash_map<IntegerValue, IntegerVariable> constant_map_;
916 int32 prev_trail_index;
923 std::vector<TrailEntry> integer_trail_;
924 std::vector<LazyReasonFunction> lazy_reasons_;
928 std::vector<int> integer_search_levels_;
935 std::vector<int> reason_decision_levels_;
936 std::vector<int> literals_reason_starts_;
937 std::vector<int> bounds_reason_starts_;
938 std::vector<Literal> literals_reason_buffer_;
943 std::vector<IntegerLiteral> bounds_reason_buffer_;
944 mutable std::vector<int> trail_index_reason_buffer_;
947 mutable std::vector<Literal> lazy_reason_literals_;
948 mutable std::vector<int> lazy_reason_trail_indices_;
959 RevMap<absl::flat_hash_map<IntegerVariable, int>>
960 var_to_current_lb_interval_index_;
963 mutable bool has_dependency_ =
false;
964 mutable std::vector<int> tmp_queue_;
965 mutable std::vector<IntegerVariable> tmp_to_clear_;
967 mutable SparseBitset<BooleanVariable> added_variables_;
970 struct RelaxHeapEntry {
974 bool operator<(
const RelaxHeapEntry& o)
const {
return index < o.index; }
976 mutable std::vector<RelaxHeapEntry> relax_heap_;
977 mutable std::vector<int> tmp_indices_;
980 mutable SparseBitset<IntegerVariable> tmp_marked_;
986 std::vector<int> boolean_trail_index_to_integer_one_;
988 int64 num_enqueues_ = 0;
989 int64 num_untrails_ = 0;
990 int64 num_level_zero_enqueues_ = 0;
992 std::vector<SparseBitset<IntegerVariable>*> watchers_;
993 std::vector<ReversibleInterface*> reversible_classes_;
995 IntegerDomains* domains_;
996 IntegerEncoder* encoder_;
1032 LOG(FATAL) <<
"Not implemented.";
1065 void Untrail(
const Trail& trail,
int literal_trail_index)
final;
1139 const std::function<
void(
const std::vector<IntegerVariable>&)> cb) {
1140 level_zero_modified_variable_callback_.push_back(cb);
1151 void UpdateCallingNeeds(
Trail* trail);
1163 std::vector<PropagatorInterface*> watchers_;
1168 std::vector<std::deque<int>> queue_by_priority_;
1169 std::vector<bool> in_queue_;
1172 DEFINE_INT_TYPE(IdType,
int32);
1173 std::vector<int> id_to_level_at_last_call_;
1175 std::vector<std::vector<ReversibleInterface*>> id_to_reversible_classes_;
1176 std::vector<std::vector<int*>> id_to_reversible_ints_;
1177 std::vector<std::vector<int>> id_to_watch_indices_;
1178 std::vector<int> id_to_priority_;
1179 std::vector<int> id_to_idempotence_;
1182 std::vector<int> propagator_ids_to_call_at_level_zero_;
1187 std::vector<std::function<void(
const std::vector<IntegerVariable>&)>>
1188 level_zero_modified_variable_callback_;
1198 IntegerValue
bound) {
1204 IntegerValue
bound) {
1218 return vars_[i].current_bound;
1226 return vars_[i].current_bound == -vars_[
NegationOf(i)].current_bound;
1248 IntegerVariable i)
const {
1253 IntegerVariable i)
const {
1268 IntegerVariable
var)
const {
1269 return integer_trail_[
var.value()].bound;
1273 IntegerVariable
var)
const {
1279 if (l.
Index() >= literal_to_watcher_.
size()) {
1280 literal_to_watcher_.
resize(l.
Index().value() + 1);
1288 if (
var.value() >= var_to_watcher_.
size()) {
1289 var_to_watcher_.
resize(
var.value() + 1);
1331 ->GetOrCreateConstantIntegerVariable(IntegerValue(
value));
1340 IntegerValue(lb), IntegerValue(ub));
1360 IntegerVariable
var;
1361 const auto& assignment =
model->GetOrCreate<
SatSolver>()->Assignment();
1362 if (assignment.LiteralIsTrue(lit)) {
1364 }
else if (assignment.LiteralIsFalse(lit)) {
1370 encoder->AssociateToIntegerEqualValue(lit,
var, IntegerValue(1));
1408 std::vector<Literal>(), std::vector<IntegerLiteral>())) {
1410 VLOG(1) <<
"Model trivially infeasible, variable " << v
1412 <<
" and GreaterOrEqual() was called with a lower bound of "
1422 std::vector<Literal>(), std::vector<IntegerLiteral>())) {
1424 LOG(WARNING) <<
"Model trivially infeasible, variable " << v
1426 <<
" and LowerOrEqual() was called with an upper bound of "
1447 const std::vector<Literal>& enforcement_literals,
IntegerLiteral i) {
1454 std::vector<Literal> clause;
1481 v, IntegerValue(lb))));
1495 inline std::function<std::vector<IntegerEncoder::ValueLiteralPair>(Model*)>
1511 std::function<void(Model*)>
1517 #endif // OR_TOOLS_SAT_INTEGER_H_