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/log/check.h"
33#include "absl/types/span.h"
43#include "ortools/sat/sat_parameters.pb.h"
94 CHECK_LT(2 * num_vars, std::numeric_limits<int32_t>::max());
96 return BooleanVariable(num_vars);
139 bool use_upper_bound, Coefficient upper_bound,
140 std::vector<LiteralWithCoeff>* cst);
158 owned_propagators_.push_back(std::move(propagator));
166 decision_policy_->SetAssignmentPreference(literal, weight);
169 return decision_policy_->AllPreferences();
172 return decision_policy_->ResetDecisionHeuristic();
217 const std::vector<Literal>& assumptions,
218 int64_t max_number_of_conflicts = -1);
282 Literal true_literal,
int* first_propagation_index =
nullptr);
350 template <
typename Output>
358 if (num_processed_fixed_variables_ < trail_->Index()) {
361 clauses_propagator_->DeleteRemovedClauses();
366 binary_implication_graph_->ExtractAllBinaryClauses(out);
367 for (
SatClause* clause : clauses_propagator_->AllClausesInCreationOrder()) {
368 if (!clauses_propagator_->IsRemovable(clause)) {
369 out->AddClause(clause->AsSpan());
390 const std::vector<Decision>&
Decisions()
const {
return decisions_; }
450 drat_proof_handler_ = drat_proof_handler;
451 clauses_propagator_->SetDratProofHandler(drat_proof_handler_);
452 binary_implication_graph_->SetDratProofHandler(drat_proof_handler_);
477 bool minimize_new_clauses_only =
false);
484 current - deterministic_time_at_last_advanced_time_limit_);
485 deterministic_time_at_last_advanced_time_limit_ = current;
492 if (!decisions_.empty())
return decisions_[0].trail_index;
494 return trail_->Index();
509 clauses_propagator_->EnsureNewClauseIndexInitialized();
523 bool ClauseIsValidUnderDebugAssignment(
524 absl::Span<const Literal> clause)
const;
525 bool PBConstraintIsValidUnderDebugAssignment(
526 absl::Span<const LiteralWithCoeff> cst, Coefficient rhs)
const;
534 Status SolveInternal(
int assumption_level);
551 Status ReapplyDecisionsUpTo(
int level,
552 int* first_propagation_index =
nullptr);
555 bool IsMemoryLimitReached()
const;
558 bool SetModelUnsat();
561 int DecisionLevel(BooleanVariable var)
const {
568 SatClause* ReasonClauseOrNull(BooleanVariable var)
const;
569 UpperBoundedLinearConstraint* ReasonPbConstraintOrNull(
570 BooleanVariable var)
const;
581 bool ResolvePBConflict(BooleanVariable var,
582 MutableUpperBoundedLinearConstraint* conflict,
591 bool ClauseIsUsedAsReason(SatClause* clause)
const {
592 const BooleanVariable var = clause->PropagatedLiteral().Variable();
595 ReasonClauseOrNull(var) == clause;
600 bool AddProblemClauseInternal(absl::Span<const Literal> literals);
605 bool AddLinearConstraintInternal(
const std::vector<LiteralWithCoeff>& cst,
606 Coefficient rhs, Coefficient max_value);
609 void CanonicalizeLinear(std::vector<LiteralWithCoeff>* cst,
610 Coefficient* bound_shift, Coefficient* max_value);
618 int AddLearnedClauseAndEnqueueUnitPropagation(
619 const std::vector<Literal>& literals,
bool is_redundant);
623 void EnqueueNewDecision(Literal literal);
629 bool PropagationIsDone()
const;
632 void InitializePropagators();
635 void ProcessNewlyFixedVariablesForDratProof();
639 int ComputeMaxTrailIndex(absl::Span<const Literal> clause)
const;
653 void ComputeFirstUIPConflict(
654 int max_trail_index, std::vector<Literal>* conflict,
655 std::vector<Literal>* reason_used_to_infer_the_conflict,
656 std::vector<SatClause*>* subsumed_clauses);
661 void ComputeUnionOfReasons(absl::Span<const Literal>
input,
662 std::vector<Literal>* literals);
668 void ComputePBConflict(
int max_trail_index, Coefficient initial_slack,
669 MutableUpperBoundedLinearConstraint* conflict,
670 int* backjump_level);
680 void MinimizeConflict(std::vector<Literal>* conflict);
681 void MinimizeConflictExperimental(std::vector<Literal>* conflict);
682 void MinimizeConflictSimple(std::vector<Literal>* conflict);
683 void MinimizeConflictRecursively(std::vector<Literal>* conflict);
686 bool CanBeInferedFromConflictVariables(BooleanVariable variable);
693 bool IsConflictValid(absl::Span<const Literal> literals);
697 int ComputeBacktrackLevel(absl::Span<const Literal> literals);
712 template <
typename LiteralList>
713 int ComputeLbd(
const LiteralList& literals);
717 void CleanClauseDatabaseIfNeeded();
721 void BumpReasonActivities(absl::Span<const Literal> literals);
722 void BumpClauseActivity(SatClause* clause);
723 void RescaleClauseActivities(
double scaling_factor);
724 void UpdateClauseActivityIncrement();
726 std::string DebugString(
const SatClause& clause)
const;
727 std::string StatusString(
Status status)
const;
728 std::string RunningStatisticsString()
const;
733 bool SubsumptionIsInteresting(BooleanVariable variable,
int max_size);
734 void KeepAllClausesUsedToInfer(BooleanVariable variable);
740 void TryToMinimizeClause(SatClause* clause);
744 std::unique_ptr<Model> owned_model_;
746 BooleanVariable num_variables_ = BooleanVariable(0);
750 BinaryImplicationGraph* binary_implication_graph_;
751 ClauseManager* clauses_propagator_;
752 PbConstraints* pb_constraints_;
755 std::vector<SatPropagator*> propagators_;
756 std::vector<SatPropagator*> non_empty_propagators_;
759 std::vector<SatPropagator*> external_propagators_;
760 SatPropagator* last_propagator_ =
nullptr;
763 std::vector<std::unique_ptr<SatPropagator>> owned_propagators_;
766 bool track_binary_clauses_;
767 BinaryClauseManager binary_clauses_;
771 TimeLimit* time_limit_;
772 SatParameters* parameters_;
773 RestartPolicy* restart_;
774 SatDecisionPolicy* decision_policy_;
775 SolverLogger* logger_;
778 VariablesAssignment debug_assignment_;
784 int current_decision_level_ = 0;
785 std::vector<Decision> decisions_;
789 int last_decision_or_backtrack_trail_index_ = 0;
792 int assumption_level_ = 0;
793 std::vector<Literal> assumptions_;
798 int num_processed_fixed_variables_ = 0;
799 double deterministic_time_of_last_fixed_variables_cleanup_ = 0.0;
802 int drat_num_processed_fixed_variables_ = 0;
811 bool model_is_unsat_ =
false;
814 double clause_activity_increment_;
818 int num_learned_clause_before_cleanup_ = 0;
820 int64_t minimization_by_propagation_threshold_ = 0;
823 SparseBitset<BooleanVariable> is_marked_;
824 SparseBitset<BooleanVariable> is_independent_;
825 SparseBitset<BooleanVariable> tmp_mark_;
826 std::vector<int> min_trail_index_per_level_;
829 std::vector<BooleanVariable> dfs_stack_;
830 std::vector<BooleanVariable> variable_to_process_;
833 std::vector<Literal> literals_scratchpad_;
837 SparseBitset<SatDecisionLevel> is_level_marked_;
840 std::vector<Literal> learned_conflict_;
841 std::vector<Literal> reason_used_to_infer_the_conflict_;
842 std::vector<Literal> extra_reason_literals_;
843 std::vector<SatClause*> subsumed_clauses_;
850 bool block_clause_deletion_ =
false;
854 VariableWithSameReasonIdentifier same_reason_identifier_;
857 bool is_relevant_for_core_computation_;
860 MutableUpperBoundedLinearConstraint pb_conflict_;
865 double deterministic_time_at_last_advanced_time_limit_ = 0;
867 DratProofHandler* drat_proof_handler_;
869 mutable StatsGroup stats_;
890 int64_t lower_bound, int64_t upper_bound,
891 std::vector<LiteralWithCoeff>* cst) {
892 return [=](
Model* model) {
894 true, Coefficient(lower_bound),
895 true, Coefficient(upper_bound), cst);
900 int64_t lower_bound, int64_t upper_bound,
901 absl::Span<const Literal> literals) {
902 return [=, literals = std::vector<Literal>(literals.begin(), literals.end())](
904 std::vector<LiteralWithCoeff> cst;
905 cst.reserve(literals.size());
906 for (
int i = 0;
i < literals.size(); ++
i) {
907 cst.emplace_back(literals[
i], 1);
910 true, Coefficient(lower_bound),
911 true, Coefficient(upper_bound), &cst);
916 absl::Span<const Literal> literals) {
917 return [=, literals = std::vector<Literal>(literals.begin(), literals.end())](
919 std::vector<LiteralWithCoeff> cst;
920 cst.reserve(literals.size());
921 for (
const Literal l : literals) {
922 cst.emplace_back(l, Coefficient(1));
925 true, Coefficient(1),
926 true, Coefficient(1), &cst);
931 absl::Span<const Literal> literals) {
932 return [=, literals = std::vector<Literal>(literals.begin(), literals.end())](
934 std::vector<LiteralWithCoeff> cst;
935 cst.reserve(literals.size());
936 for (
const Literal l : literals) {
937 cst.emplace_back(l, Coefficient(1));
940 false, Coefficient(0),
941 true, Coefficient(1), &cst);
946 absl::Span<const Literal> literals) {
954 return [=](
Model* model) {
960inline std::function<void(
Model*)>
Equality(Literal a, Literal
b) {
961 return [=](
Model* model) {
969 absl::Span<const Literal> literals, Literal r) {
970 return [=, literals = std::vector<Literal>(literals.begin(), literals.end())](
972 std::vector<Literal> clause;
973 for (
const Literal l : literals) {
979 clause.push_back(r.Negated());
986 absl::Span<const Literal> enforcement_literals,
987 absl::Span<const Literal> clause) {
988 return [=](
Model* model) {
989 std::vector<Literal> tmp;
990 for (
const Literal l : enforcement_literals) {
991 tmp.push_back(l.Negated());
993 for (
const Literal l : clause) {
1004 absl::Span<const Literal> literals, Literal r) {
1005 return [=, literals = std::vector<Literal>(literals.begin(), literals.end())](
1007 std::vector<Literal> clause;
1008 for (
const Literal l : literals) {
1010 clause.push_back(l.Negated());
1014 clause.push_back(r);
1030inline std::function<int64_t(
const Model&)>
Value(Literal l) {
1031 return [=](
const Model& model) {
1039inline std::function<int64_t(
const Model&)>
Value(BooleanVariable
b) {
1040 return [=](
const Model& model) {
1052 return [=](
Model* model) {
1058 std::vector<Literal> clause_to_exclude_solution;
1059 clause_to_exclude_solution.reserve(current_level);
1060 for (
int i = 0;
i < current_level; ++
i) {
1061 clause_to_exclude_solution.push_back(
1062 sat_solver->
Decisions()[
i].literal.Negated());
void AdvanceDeterministicTime(double deterministic_duration)
T Add(std::function< T(Model *)> f)
T Get(std::function< T(const Model &)> f) const
Similar to Add() but this is const.
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)
void LoadDebugSolution(absl::Span< const Literal > solution)
Status SolveWithTimeLimit(TimeLimit *time_limit)
void SetDratProofHandler(DratProofHandler *drat_proof_handler)
double deterministic_time() const
const std::vector< BinaryClause > & NewlyAddedBinaryClauses()
SatSolver(const SatSolver &)=delete
This type is neither copyable nor movable.
bool MinimizeByPropagation(double dtime, bool minimize_new_clauses_only=false)
void ProcessCurrentConflict()
Status UnsatStatus() const
SolverLogger * mutable_logger()
Hack to allow to temporarily disable logging if it is enabled.
bool AddBinaryClauses(absl::Span< const BinaryClause > clauses)
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 NotifyThatModelIsUnsat()
bool AddProblemClause(absl::Span< const Literal > literals)
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)
void EnsureNewClauseIndexInitialized()
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()
std::vector< Literal > GetDecisionsFixing(absl::Span< const Literal > literals)
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::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 *)> ReifiedBoolAnd(absl::Span< const Literal > literals, Literal r)
std::function< void(Model *)> Implication(absl::Span< const Literal > enforcement_literals, IntegerLiteral i)
std::ostream & operator<<(std::ostream &os, const BoolVar &var)
std::function< int64_t(const Model &)> Value(IntegerVariable v)
This checks that the variable is fixed.
std::function< void(Model *)> AtMostOneConstraint(absl::Span< const Literal > literals)
std::function< void(Model *)> CardinalityConstraint(int64_t lower_bound, int64_t upper_bound, absl::Span< const Literal > literals)
std::function< void(Model *)> ExactlyOneConstraint(absl::Span< const 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 *)> ReifiedBoolOr(absl::Span< const Literal > literals, Literal r)
r <=> (at least one literal is true). This is a reified clause.
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.
Select next search node to expand Select next item_i to add this new search node to the search Generate a new search node where item_i is not in the knapsack Check validity of this new partial solution(using propagators) - If valid
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)