16#ifndef OR_TOOLS_SAT_SAT_BASE_H_
17#define OR_TOOLS_SAT_SAT_BASE_H_
28#include "absl/base/attributes.h"
29#include "absl/log/check.h"
30#include "absl/strings/str_format.h"
31#include "absl/types/span.h"
69 : index_(signed_value > 0 ? ((signed_value - 1) << 1)
70 : ((-signed_value - 1) << 1) ^ 1) {
71 CHECK_NE(signed_value, 0);
76 Literal(BooleanVariable variable,
bool is_positive)
77 : index_(is_positive ? (variable.
value() << 1)
78 : (variable.
value() << 1) ^ 1) {}
85 operator LiteralIndex()
const {
return Index(); }
87 BooleanVariable
Variable()
const {
return BooleanVariable(index_ >> 1); }
91 LiteralIndex
Index()
const {
return LiteralIndex(index_); }
92 LiteralIndex
NegatedIndex()
const {
return LiteralIndex(index_ ^ 1); }
95 return (index_ & 1) ? -((index_ >> 1) + 1) : ((index_ >> 1) + 1);
108 template <
typename H>
110 return H::combine(std::move(h),
literal.index_);
122template <
typename Sink,
typename... T>
128 absl::Span<const Literal> literals) {
147 std::vector<Literal> result(
input.size());
148 for (
int i = 0;
i < result.size(); ++
i) {
165 assignment_.
Resize(LiteralIndex(num_variables << 1));
225 : view_(assignment.assignment_.const_view()) {}
228 return view_[
literal.NegatedIndex()];
266 return absl::StrFormat(
"level:%d type:%d trail_index:%d",
level,
type,
270static_assert(
sizeof(AssignmentInfo) == 8,
271 "ERROR_AssignmentInfo_is_not_well_compacted");
292 current_info_.
level = 0;
299 void Resize(
int num_variables);
308 current_info_.
type = propagator_id;
313 info_[true_literal.
Variable()] = current_info_;
336 BooleanVariable reference_var) {
337 reference_var_with_same_reason_as_[true_literal.
Variable()] = reference_var;
356 const BooleanVariable
var = true_literal.
Variable();
357 reasons_[
var] = reasons_repository_[info_[
var].trail_index];
358 old_type_[
var] = info_[
var].type;
377 absl::Span<const Literal>
Reason(BooleanVariable
var,
378 int64_t conflict_id = -1)
const;
394 if (trail_index >= reasons_repository_.size()) {
395 reasons_repository_.resize(trail_index + 1);
397 reasons_repository_[trail_index].clear();
398 return &reasons_repository_[trail_index];
409 const BooleanVariable
var = trail_[trail_index].Variable();
410 info_[
var].type = propagator_id;
411 old_type_[
var] = propagator_id;
418 num_untrailed_enqueues_ +=
index - target_trail_index;
419 for (
int i = target_trail_index;
i <
index; ++
i) {
434 failing_sat_clause_ =
nullptr;
440 if (
DEBUG_MODE && debug_checker_ !=
nullptr) {
441 CHECK(debug_checker_(conflict_));
459 return trail_.begin() +
index;
465 DCHECK_LT(
var, info_.size());
473 if (!result.empty()) result +=
" ";
474 result += trail_[
i].DebugString();
480 std::function<
bool(absl::Span<const Literal> clause)> checker) {
481 debug_checker_ = std::move(checker);
485 int64_t num_untrailed_enqueues_ = 0;
488 std::vector<Literal> trail_;
489 std::vector<Literal> conflict_;
495 reference_var_with_same_reason_as_;
520 mutable std::deque<std::vector<Literal>> reasons_repository_;
526 std::vector<SatPropagator*> propagators_;
528 std::function<bool(absl::Span<const Literal> clause)> debug_checker_ =
588 LOG(FATAL) <<
"Not implemented.";
605 virtual bool IsEmpty()
const {
return false; }
618 const Trail& trail)
const {
620 LOG(INFO) <<
"Issue in '" <<
name_ <<
":"
622 <<
" trail_.Index()=" << trail.
Index();
628 LOG(INFO) <<
"Issue in '" <<
name_ <<
"':" <<
" propagation_trail_index_="
630 <<
" level_at_propagation_index="
639 assignment_.
Resize(num_variables);
640 info_.resize(num_variables);
641 trail_.resize(num_variables);
642 reasons_.resize(num_variables);
646 old_type_.
resize(num_variables);
647 reference_var_with_same_reason_as_.
resize(num_variables);
651 if (propagators_.empty()) {
654 CHECK_LT(propagators_.size(), 16);
656 propagators_.push_back(propagator);
660 BooleanVariable
var)
const {
664 var = reference_var_with_same_reason_as_[
var];
673 var = reference_var_with_same_reason_as_[
var];
676 const int type = info_[
var].type;
681 int64_t conflict_id)
const {
687 if (
DEBUG_MODE && debug_checker_ !=
nullptr) {
688 std::vector<Literal> clause;
689 clause.assign(reasons_[
var].begin(), reasons_[
var].
end());
691 CHECK(debug_checker_(clause));
693 return reasons_[
var];
701 DCHECK_LT(info.
type, propagators_.size());
702 DCHECK(propagators_[info.
type] !=
nullptr) << info.
type;
708 if (
DEBUG_MODE && debug_checker_ !=
nullptr) {
709 std::vector<Literal> clause;
710 clause.assign(reasons_[
var].begin(), reasons_[
var].
end());
712 CHECK(debug_checker_(clause));
714 return reasons_[
var];
When speed matter, caching the base pointer helps.
bool IsSet(IndexType i) const
Returns true if the bit at position i is set.
IndexType size() const
Returns how many bits this Bitset64 can hold.
void ClearTwoBits(IndexType i)
Clears the bits at position i and i ^ 1.
void Resize(IndexType size)
bool AreOneOfTwoBitsSet(IndexType i) const
Returns true if the bit at position i or the one at position i ^ 1 is set.
void Set(IndexType i)
Sets the bit at position i to 1.
AssignmentView(const VariablesAssignment &assignment)
bool LiteralIsFalse(Literal literal) const
bool LiteralIsTrue(Literal literal) const
bool operator<(const Literal &other) const
std::string DebugString() const
LiteralIndex NegatedIndex() const
bool operator!=(Literal other) const
friend H AbslHashValue(H h, Literal literal)
Literal(LiteralIndex index)
LiteralIndex Index() const
BooleanVariable Variable() const
Literal(BooleanVariable variable, bool is_positive)
Literal(int signed_value)
bool operator==(Literal other) const
Base class for all the SAT constraints.
virtual absl::Span< const Literal > Reason(const Trail &, int, int64_t) const
bool PropagatePreconditionsAreSatisfied(const Trail &trail) const
######################## Implementations below ########################
SatPropagator(const std::string &name)
int propagation_trail_index_
void SetPropagatorId(int id)
Sets/Gets this propagator unique id.
virtual void Untrail(const Trail &, int trail_index)
virtual bool Propagate(Trail *trail)=0
virtual bool IsEmpty() const
bool PropagationIsDone(const Trail &trail) const
Returns true iff all the trail was inspected by this propagator.
SatPropagator(const SatPropagator &)=delete
This type is neither copyable nor movable.
SatPropagator & operator=(const SatPropagator &)=delete
virtual ~SatPropagator()=default
BooleanVariable ReferenceVarWithSameReason(BooleanVariable var) const
std::vector< Literal >::const_iterator IteratorAt(int index) const
int NumVariables() const
Getters.
std::vector< Literal > * MutableConflict()
int64_t NumberOfEnqueues() const
const Literal & operator[](int index) const
void SetDecisionLevel(int level)
Changes the decision level used by the next Enqueue().
int AssignmentType(BooleanVariable var) const
Trail(const Trail &)=delete
This type is neither copyable nor movable.
void EnqueueSearchDecision(Literal true_literal)
Specific Enqueue() version for the search decision.
std::string DebugString() const
Print the current literals on the trail.
void Enqueue(Literal true_literal, int propagator_id)
void Untrail(int target_trail_index)
void EnqueueWithSameReasonAs(Literal true_literal, BooleanVariable reference_var)
absl::Span< const Literal > Reason(BooleanVariable var, int64_t conflict_id=-1) const
std::vector< Literal > * GetEmptyVectorToStoreReason() const
Shortcut for GetEmptyVectorToStoreReason(Index()).
void RegisterDebugChecker(std::function< bool(absl::Span< const Literal > clause)> checker)
void EnqueueWithUnitReason(Literal true_literal)
Specific Enqueue() version for a fixed variable.
int CurrentDecisionLevel() const
void ChangeReason(int trail_index, int propagator_id)
void SetFailingSatClause(SatClause *clause)
Trail & operator=(const Trail &)=delete
const AssignmentInfo & Info(BooleanVariable var) const
std::vector< Literal > * GetEmptyVectorToStoreReason(int trail_index) const
void RegisterPropagator(SatPropagator *propagator)
void SetCurrentPropagatorId(int propagator_id)
void FastEnqueue(Literal true_literal)
ABSL_MUST_USE_RESULT bool EnqueueWithStoredReason(Literal true_literal)
SatClause * FailingSatClause() const
absl::Span< const Literal > FailingClause() const
Returns the last conflict.
void Resize(int num_variables)
const VariablesAssignment & Assignment() const
bool VariableIsAssigned(BooleanVariable var) const
Returns true iff the given variable is assigned.
bool LiteralIsAssigned(Literal literal) const
VariablesAssignment & operator=(const VariablesAssignment &)=delete
Literal GetTrueLiteralForAssignedVariable(BooleanVariable var) const
bool LiteralIsFalse(Literal literal) const
int NumberOfVariables() const
void AssignFromTrueLiteral(Literal literal)
void UnassignLiteral(Literal literal)
VariablesAssignment(const VariablesAssignment &)=delete
This type is neither copyable nor movable.
VariablesAssignment()=default
void Resize(int num_variables)
VariablesAssignment(int num_variables)
bool LiteralIsTrue(Literal literal) const
void resize(size_type new_size)
const std::string name
A name for logging purposes.
void AbslStringify(Sink &sink, Literal arg)
const LiteralIndex kNoLiteralIndex(-1)
const LiteralIndex kTrueLiteralIndex(-2)
std::ostream & operator<<(std::ostream &os, const BoolVar &var)
const LiteralIndex kFalseLiteralIndex(-3)
std::vector< Literal > Literals(absl::Span< const int > input)
const BooleanVariable kNoBooleanVariable(-1)
In SWIG mode, we don't want anything besides these top-level includes.
static int input(yyscan_t yyscanner)
std::optional< int64_t > end
#define DEFINE_STRONG_INDEX_TYPE(index_type_name)
Information about a variable assignment.
std::string DebugString() const
int32_t trail_index
The index of this assignment in the trail.
static constexpr int kSearchDecision
static constexpr int kSameReasonAs
static constexpr int kFirstFreePropagationId
Propagator ids starts from there and are created dynamically.
static constexpr int kUnitReason
static constexpr int kCachedReason