19#ifndef OR_TOOLS_SAT_SAT_SOLVER_H_
20#define OR_TOOLS_SAT_SAT_SOLVER_H_
31#include "absl/base/attributes.h"
32#include "absl/container/flat_hash_map.h"
33#include "absl/log/check.h"
34#include "absl/strings/string_view.h"
35#include "absl/types/span.h"
47#include "ortools/sat/sat_parameters.pb.h"
98 CHECK_LT(2 * num_vars, std::numeric_limits<int32_t>::max());
100 return BooleanVariable(num_vars);
122 bool is_safe =
true);
139 std::vector<LiteralWithCoeff>* cst);
157 owned_propagators_.push_back(std::move(propagator));
216 const std::vector<Literal>& assumptions,
217 int64_t max_number_of_conflicts = -1);
277 Literal true_literal,
int* first_propagation_index =
nullptr);
345 template <
typename Output>
353 if (num_processed_fixed_variables_ < trail_->Index()) {
364 out->AddClause(clause->AsSpan());
385 const std::vector<Decision>&
Decisions()
const {
return decisions_; }
445 drat_proof_handler_ = drat_proof_handler;
478 current - deterministic_time_at_last_advanced_time_limit_);
479 deterministic_time_at_last_advanced_time_limit_ = current;
486 if (!decisions_.empty())
return decisions_[0].trail_index;
488 return trail_->
Index();
513 bool ClauseIsValidUnderDebugAssignment(
514 absl::Span<const Literal> clause)
const;
515 bool PBConstraintIsValidUnderDebugAssignment(
516 const std::vector<LiteralWithCoeff>& cst, Coefficient rhs)
const;
524 Status SolveInternal(
int assumption_level);
541 Status ReapplyDecisionsUpTo(
int level,
542 int* first_propagation_index =
nullptr);
545 bool IsMemoryLimitReached()
const;
548 bool SetModelUnsat();
551 int DecisionLevel(BooleanVariable
var)
const {
558 SatClause* ReasonClauseOrNull(BooleanVariable
var)
const;
559 UpperBoundedLinearConstraint* ReasonPbConstraintOrNull(
560 BooleanVariable
var)
const;
571 bool ResolvePBConflict(BooleanVariable
var,
572 MutableUpperBoundedLinearConstraint* conflict,
581 bool ClauseIsUsedAsReason(SatClause* clause)
const {
582 const BooleanVariable
var = clause->PropagatedLiteral().Variable();
585 ReasonClauseOrNull(
var) == clause;
590 bool AddProblemClauseInternal(absl::Span<const Literal> literals);
595 bool AddLinearConstraintInternal(
const std::vector<LiteralWithCoeff>& cst,
596 Coefficient rhs, Coefficient max_value);
599 void CanonicalizeLinear(std::vector<LiteralWithCoeff>* cst,
600 Coefficient* bound_shift, Coefficient* max_value);
608 int AddLearnedClauseAndEnqueueUnitPropagation(
609 const std::vector<Literal>& literals,
bool is_redundant);
613 void EnqueueNewDecision(Literal
literal);
619 bool PropagationIsDone()
const;
622 void InitializePropagators();
625 void ProcessNewlyFixedVariablesForDratProof();
629 int ComputeMaxTrailIndex(absl::Span<const Literal> clause)
const;
643 void ComputeFirstUIPConflict(
644 int max_trail_index, std::vector<Literal>* conflict,
645 std::vector<Literal>* reason_used_to_infer_the_conflict,
646 std::vector<SatClause*>* subsumed_clauses);
651 void ComputeUnionOfReasons(
const std::vector<Literal>&
input,
652 std::vector<Literal>* literals);
658 void ComputePBConflict(
int max_trail_index, Coefficient initial_slack,
659 MutableUpperBoundedLinearConstraint* conflict,
660 int* backjump_level);
670 void MinimizeConflict(std::vector<Literal>* conflict);
671 void MinimizeConflictExperimental(std::vector<Literal>* conflict);
672 void MinimizeConflictSimple(std::vector<Literal>* conflict);
673 void MinimizeConflictRecursively(std::vector<Literal>* conflict);
676 bool CanBeInferedFromConflictVariables(BooleanVariable variable);
683 bool IsConflictValid(
const std::vector<Literal>& literals);
687 int ComputeBacktrackLevel(
const std::vector<Literal>& literals);
702 template <
typename LiteralList>
703 int ComputeLbd(
const LiteralList& literals);
707 void CleanClauseDatabaseIfNeeded();
711 void BumpReasonActivities(
const std::vector<Literal>& literals);
712 void BumpClauseActivity(SatClause* clause);
713 void RescaleClauseActivities(
double scaling_factor);
714 void UpdateClauseActivityIncrement();
716 std::string DebugString(
const SatClause& clause)
const;
718 std::string RunningStatisticsString()
const;
722 void KeepAllClauseUsedToInfer(BooleanVariable variable);
723 bool SubsumptionIsInteresting(BooleanVariable variable);
729 void TryToMinimizeClause(SatClause* clause);
733 std::unique_ptr<Model> owned_model_;
735 BooleanVariable num_variables_ = BooleanVariable(0);
739 BinaryImplicationGraph* binary_implication_graph_;
740 ClauseManager* clauses_propagator_;
741 PbConstraints* pb_constraints_;
744 std::vector<SatPropagator*> propagators_;
745 std::vector<SatPropagator*> non_empty_propagators_;
748 std::vector<SatPropagator*> external_propagators_;
749 SatPropagator* last_propagator_ =
nullptr;
752 std::vector<std::unique_ptr<SatPropagator>> owned_propagators_;
755 bool track_binary_clauses_;
756 BinaryClauseManager binary_clauses_;
760 TimeLimit* time_limit_;
761 SatParameters* parameters_;
762 RestartPolicy* restart_;
763 SatDecisionPolicy* decision_policy_;
764 SolverLogger* logger_;
767 VariablesAssignment debug_assignment_;
773 int current_decision_level_ = 0;
774 std::vector<Decision> decisions_;
778 int last_decision_or_backtrack_trail_index_ = 0;
781 int assumption_level_ = 0;
782 std::vector<Literal> assumptions_;
787 int num_processed_fixed_variables_ = 0;
788 double deterministic_time_of_last_fixed_variables_cleanup_ = 0.0;
791 int drat_num_processed_fixed_variables_ = 0;
800 bool model_is_unsat_ =
false;
803 double clause_activity_increment_;
807 int num_learned_clause_before_cleanup_ = 0;
809 int64_t minimization_by_propagation_threshold_ = 0;
812 SparseBitset<BooleanVariable> is_marked_;
813 SparseBitset<BooleanVariable> is_independent_;
814 SparseBitset<BooleanVariable> tmp_mark_;
815 std::vector<int> min_trail_index_per_level_;
818 std::vector<BooleanVariable> dfs_stack_;
819 std::vector<BooleanVariable> variable_to_process_;
822 std::vector<Literal> literals_scratchpad_;
826 SparseBitset<SatDecisionLevel> is_level_marked_;
829 std::vector<Literal> learned_conflict_;
830 std::vector<Literal> reason_used_to_infer_the_conflict_;
831 std::vector<Literal> extra_reason_literals_;
832 std::vector<SatClause*> subsumed_clauses_;
839 bool block_clause_deletion_ =
false;
843 VariableWithSameReasonIdentifier same_reason_identifier_;
846 bool is_relevant_for_core_computation_;
849 MutableUpperBoundedLinearConstraint pb_conflict_;
854 double deterministic_time_at_last_advanced_time_limit_ = 0;
856 DratProofHandler* drat_proof_handler_;
858 mutable StatsGroup stats_;
870void MinimizeCore(SatSolver* solver, std::vector<Literal>* core);
880 std::vector<LiteralWithCoeff>* cst) {
890 const std::vector<Literal>& literals) {
892 std::vector<LiteralWithCoeff> cst;
893 cst.reserve(literals.size());
894 for (
int i = 0;
i < literals.size(); ++
i) {
895 cst.emplace_back(literals[
i], 1);
904 const std::vector<Literal>& literals) {
906 std::vector<LiteralWithCoeff> cst;
907 cst.reserve(literals.size());
908 for (
const Literal l : literals) {
909 cst.emplace_back(l, Coefficient(1));
912 true, Coefficient(1),
913 true, Coefficient(1), &cst);
918 const std::vector<Literal>& literals) {
920 std::vector<LiteralWithCoeff> cst;
921 cst.reserve(literals.size());
922 for (
const Literal l : literals) {
923 cst.emplace_back(l, Coefficient(1));
926 false, Coefficient(0),
927 true, Coefficient(1), &cst);
932 absl::Span<const Literal> literals) {
940inline std::function<void(Model*)>
Implication(Literal
a, Literal
b) {
941 return [=](Model*
model) {
947inline std::function<void(Model*)>
Equality(Literal
a, Literal
b) {
948 return [=](Model*
model) {
956 const std::vector<Literal>& literals, Literal r) {
958 std::vector<Literal> clause;
959 for (
const Literal l : literals) {
965 clause.push_back(r.Negated());
972 absl::Span<const Literal> enforcement_literals,
973 absl::Span<const Literal> clause) {
975 std::vector<Literal> tmp;
976 for (
const Literal l : enforcement_literals) {
977 tmp.push_back(l.Negated());
979 for (
const Literal l : clause) {
990 const std::vector<Literal>& literals, Literal r) {
992 std::vector<Literal> clause;
993 for (
const Literal l : literals) {
995 clause.push_back(l.Negated());
1015inline std::function<int64_t(
const Model&)>
Value(Literal l) {
1016 return [=](
const Model&
model) {
1024inline std::function<int64_t(
const Model&)>
Value(BooleanVariable
b) {
1025 return [=](
const Model&
model) {
1037 return [=](Model*
model) {
1043 std::vector<Literal> clause_to_exclude_solution;
1044 clause_to_exclude_solution.reserve(current_level);
1045 for (
int i = 0;
i < current_level; ++
i) {
1046 clause_to_exclude_solution.push_back(
1047 sat_solver->
Decisions()[
i].literal.Negated());
void AdvanceDeterministicTime(double deterministic_duration)
void ExtractAllBinaryClauses(Output *out) const
void SetDratProofHandler(DratProofHandler *drat_proof_handler)
bool IsRemovable(SatClause *const clause) const
void DeleteRemovedClauses()
void SetDratProofHandler(DratProofHandler *drat_proof_handler)
const std::vector< SatClause * > & AllClausesInCreationOrder() const
std::vector< std::pair< Literal, float > > AllPreferences() const
Returns the vector of the current assignment preferences.
void SetAssignmentPreference(Literal literal, float weight)
void ResetDecisionHeuristic()
Base class for all the SAT constraints.
void ExtractClauses(Output *out)
Status EnqueueDecisionAndBacktrackOnConflict(Literal true_literal, int *first_propagation_index=nullptr)
bool AddLinearConstraint(bool use_lower_bound, Coefficient lower_bound, bool use_upper_bound, Coefficient upper_bound, std::vector< LiteralWithCoeff > *cst)
Status SolveWithTimeLimit(TimeLimit *time_limit)
void SetDratProofHandler(DratProofHandler *drat_proof_handler)
double deterministic_time() const
bool AddBinaryClauses(const std::vector< BinaryClause > &clauses)
bool AddProblemClause(absl::Span< const Literal > literals, bool is_safe=true)
bool MinimizeByPropagation(double dtime)
const std::vector< BinaryClause > & NewlyAddedBinaryClauses()
SatSolver(const SatSolver &)=delete
This type is neither copyable nor movable.
void ProcessCurrentConflict()
Status UnsatStatus() const
SolverLogger * mutable_logger()
Hack to allow to temporarily disable logging if it is enabled.
void SetAssignmentPreference(Literal literal, float weight)
BooleanVariable NewBooleanVariable()
void ProcessNewlyFixedVariables()
Simplifies the problem when new variables are assigned at level 0.
bool ResetWithGivenAssumptions(const std::vector< Literal > &assumptions)
int64_t num_branches() const
Some statistics since the creation of the solver.
void LoadDebugSolution(const std::vector< Literal > &solution)
void NotifyThatModelIsUnsat()
std::vector< Literal > GetLastIncompatibleDecisions()
bool RestoreSolverToAssumptionLevel()
bool AddBinaryClause(Literal a, Literal b)
Same as AddProblemClause() below, but for small clauses.
void TrackBinaryClauses(bool value)
int EnqueueDecisionAndBackjumpOnConflict(Literal true_literal)
int64_t num_failures() const
void ResetDecisionHeuristic()
bool ModelIsUnsat() const
void Backtrack(int target_level)
bool ReapplyAssumptionsIfNeeded()
void ClearNewlyAddedBinaryClauses()
int64_t num_propagations() const
bool IsModelUnsat() const
int64_t num_backtracks() const
const SatParameters & parameters() const
bool EnqueueDecisionIfNotConflicting(Literal true_literal)
bool AddClauseDuringSearch(absl::Span< const Literal > literals)
ABSL_MUST_USE_RESULT bool Propagate()
void SetAssumptionLevel(int assumption_level)
std::vector< std::pair< Literal, float > > AllPreferences() const
int64_t num_restarts() const
ABSL_MUST_USE_RESULT bool AddUnitClause(Literal true_literal)
bool AddTernaryClause(Literal a, Literal b, Literal c)
void TakePropagatorOwnership(std::unique_ptr< SatPropagator > propagator)
SatSolver & operator=(const SatSolver &)=delete
void AdvanceDeterministicTime(TimeLimit *limit)
Status ResetAndSolveWithGivenAssumptions(const std::vector< Literal > &assumptions, int64_t max_number_of_conflicts=-1)
const VariablesAssignment & Assignment() const
int CurrentDecisionLevel() const
int AssumptionLevel() const
ABSL_MUST_USE_RESULT bool ResetToLevelZero()
void SaveDebugAssignment()
void AddLastPropagator(SatPropagator *propagator)
const std::vector< Decision > & Decisions() const
ABSL_MUST_USE_RESULT bool FinishPropagation()
const Trail & LiteralTrail() const
void SetNumVariables(int num_variables)
Counters counters() const
int64_t NumFixedVariables() const
void AddPropagator(SatPropagator *propagator)
void SetParameters(const SatParameters ¶meters)
const AssignmentInfo & Info(BooleanVariable var) const
const VariablesAssignment & Assignment() const
bool VariableIsAssigned(BooleanVariable var) const
Returns true iff the given variable is assigned.
bool LiteralIsTrue(Literal literal) const
std::function< void(Model *)> Equality(IntegerVariable v, int64_t value)
Fix v to a given value.
std::function< void(Model *)> ReifiedBoolOr(const std::vector< Literal > &literals, Literal r)
r <=> (at least one literal is true). This is a reified clause.
std::string SatStatusString(SatSolver::Status status)
Returns a string representation of a SatSolver::Status.
std::function< void(Model *)> ClauseConstraint(absl::Span< const Literal > literals)
std::function< void(Model *)> EnforcedClause(absl::Span< const Literal > enforcement_literals, absl::Span< const Literal > clause)
enforcement_literals => clause.
std::function< void(Model *)> ReifiedBoolLe(Literal a, Literal b, Literal r)
r <=> (a <= b).
std::function< void(Model *)> Implication(absl::Span< const Literal > enforcement_literals, IntegerLiteral i)
std::ostream & operator<<(std::ostream &os, const BoolVar &var)
std::function< void(Model *)> AtMostOneConstraint(const std::vector< Literal > &literals)
std::function< int64_t(const Model &)> Value(IntegerVariable v)
This checks that the variable is fixed.
std::function< void(Model *)> ReifiedBoolAnd(const std::vector< Literal > &literals, Literal r)
std::function< void(Model *)> CardinalityConstraint(int64_t lower_bound, int64_t upper_bound, const std::vector< Literal > &literals)
std::function< void(Model *)> BooleanLinearConstraint(int64_t lower_bound, int64_t upper_bound, std::vector< LiteralWithCoeff > *cst)
const int kUnsatTrailIndex
A constant used by the EnqueueDecision*() API.
std::function< void(Model *)> ExactlyOneConstraint(const std::vector< Literal > &literals)
std::function< void(Model *)> ExcludeCurrentSolutionAndBacktrack()
void MinimizeCore(SatSolver *solver, std::vector< Literal > *core)
In SWIG mode, we don't want anything besides these top-level includes.
static int input(yyscan_t yyscanner)
#define DEFINE_STRONG_INDEX_TYPE(index_type_name)
int32_t trail_index
The index of this assignment in the trail.
int64_t minimization_num_true
int64_t num_subsumed_clauses
int64_t num_literals_forgotten
int64_t minimization_num_decisions
int64_t minimization_num_clauses
TryToMinimizeClause() stats.
int64_t num_minimizations
Minimization stats.
int64_t minimization_num_removed_literals
int64_t minimization_num_subsumed
int64_t num_literals_removed
int64_t minimization_num_reused
int64_t num_literals_learned
Clause learning /deletion stats.
int64_t num_learned_pb_literals
PB constraints.
Decision(int i, Literal l)