17#ifndef OR_TOOLS_SAT_CLAUSE_H_
18#define OR_TOOLS_SAT_CLAUSE_H_
26#include "absl/base/attributes.h"
27#include "absl/container/flat_hash_map.h"
28#include "absl/container/flat_hash_set.h"
29#include "absl/container/inlined_vector.h"
30#include "absl/random/bit_gen_ref.h"
31#include "absl/types/span.h"
40#include "ortools/sat/sat_parameters.pb.h"
63 void operator delete(
void* p) {
68 int size()
const {
return size_; }
69 int empty()
const {
return size_ == 0; }
73 const Literal*
const end()
const {
return &(literals_[size_]); }
89 return absl::Span<const Literal>(&(literals_[1]), size_ - 1);
93 absl::Span<const Literal>
AsSpan()
const {
94 return absl::Span<const Literal>(&(literals_[0]), size_);
120 Literal* literals() {
return &(literals_[0]); }
125 void Clear() { size_ = 0; }
129 void Rewrite(absl::Span<const Literal> new_clause) {
131 for (
const Literal l : new_clause) literals_[size_++] = l;
138 Literal literals_[0];
169 void Resize(
int num_variables);
173 absl::Span<const Literal>
Reason(
const Trail& trail,
174 int trail_index)
const final;
183 bool AddClause(absl::Span<const Literal> literals);
223 return clauses_info_.contains(clause);
227 return &clauses_info_;
233 return num_inspected_clause_literals_;
243 drat_proof_handler_ = drat_proof_handler;
250 for (; to_minimize_index_ < clauses_.size(); ++to_minimize_index_) {
251 if (!clauses_[to_minimize_index_]->IsAttached())
continue;
253 return clauses_[to_minimize_index_++];
281 SatClause* clause, absl::Span<const Literal> new_clause);
316 return watchers_on_false_[false_literal.
Index()];
326 bool PropagateOnFalse(
Literal false_literal,
Trail* trail);
340 std::vector<SatClause*> reasons_;
345 bool is_clean_ =
true;
350 int64_t num_inspected_clauses_;
351 int64_t num_inspected_clause_literals_;
352 int64_t num_watched_clauses_;
356 bool all_clauses_are_attached_ =
true;
363 std::vector<SatClause*> clauses_;
365 int to_minimize_index_ = 0;
368 absl::flat_hash_map<SatClause*, ClauseInfo> clauses_info_;
394 if (p.first > p.second)
std::swap(p.first, p.second);
395 if (set_.find(p) == set_.end()) {
397 newly_added_.push_back(c);
404 const std::vector<BinaryClause>&
newly_added()
const {
return newly_added_; }
408 absl::flat_hash_set<std::pair<int, int>> set_;
409 std::vector<BinaryClause> newly_added_;
461 stats_(
"BinaryImplicationGraph"),
471 LOG(
INFO) <<
"num_redundant_implications " << num_redundant_implications_;
477 absl::Span<const Literal>
Reason(
const Trail& trail,
478 int trail_index)
const final;
481 void Resize(
int num_variables);
485 return num_implications_ == 0 && at_most_ones_.
empty();
507 ABSL_MUST_USE_RESULT
bool AddAtMostOne(absl::Span<const Literal> at_most_one);
520 std::vector<Literal>* c);
524 const Trail& trail, std::vector<Literal>* c,
546 bool IsDag()
const {
return is_dag_; }
552 return reverse_topological_order_;
558 return implications_[l.
Index()];
565 if (l.
Index() >= representative_of_.
size())
return l;
593 int64_t max_num_explored_nodes = 1e8);
605 const std::vector<Literal>& literals,
606 const std::vector<double>& lp_values);
626 CHECK_EQ(num_redundant_literals_ % 2, 0);
627 return num_redundant_literals_;
632 return num_redundant_implications_;
649 template <
typename Output>
654 absl::flat_hash_set<std::pair<LiteralIndex, LiteralIndex>>
656 for (LiteralIndex i(0); i < implications_.size(); ++i) {
658 for (
const Literal b : implications_[i]) {
664 duplicate_detection.insert({a.Index(), b.Index()}).second) {
665 out->AddBinaryClause(
a,
b);
672 drat_proof_handler_ = drat_proof_handler;
680 reasons_[trail_index] = new_reason.
Negated();
698 return estimated_sizes_[
literal.Index()];
711 BooleanVariable
var, std::deque<std::vector<Literal>>* postsolve_clauses);
720 int64_t
WorkDone()
const {
return work_done_in_mark_descendants_; }
723 template <
bool use_weight = true>
725 const absl::Span<const Literal> at_most_one,
732 bool FixLiteral(
Literal true_literal);
738 bool PropagateOnTrue(
Literal true_literal,
Trail* trail);
741 void RemoveRedundantLiterals(std::vector<Literal>* conflict);
745 void MarkDescendants(
Literal root);
751 std::vector<Literal> ExpandAtMostOne(
752 const absl::Span<const Literal> at_most_one,
753 int64_t max_num_explored_nodes);
759 bool CleanUpAndAddAtMostOnes(
const int base_index);
769 std::deque<Literal> reasons_;
783 int64_t num_implications_ = 0;
794 std::vector<Literal> at_most_one_buffer_;
797 std::vector<std::vector<Literal>> tmp_cuts_;
800 int64_t num_propagations_ = 0;
801 int64_t num_inspections_ = 0;
802 int64_t num_minimization_ = 0;
803 int64_t num_literals_removed_ = 0;
804 int64_t num_redundant_implications_ = 0;
805 int64_t num_redundant_literals_ = 0;
815 std::vector<Literal> dfs_stack_;
819 int64_t work_done_in_mark_descendants_ = 0;
822 bool is_dag_ =
false;
823 std::vector<LiteralIndex> reverse_topological_order_;
828 std::vector<Literal> direct_implications_;
829 std::vector<Literal> direct_implications_of_negated_literal_;
835 int num_processed_fixed_variables_ = 0;
#define CHECK_EQ(val1, val2)
std::string StatString() const
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
const std::vector< BinaryClause > & newly_added() const
int64_t NumImplicationOnVariableRemoval(BooleanVariable var)
bool Propagate(Trail *trail) final
void AddBinaryClause(Literal a, Literal b)
bool ComputeTransitiveReduction(bool log_info=false)
~BinaryImplicationGraph() override
void MinimizeConflictWithReachability(std::vector< Literal > *c)
const std::vector< LiteralIndex > & ReverseTopologicalOrder() const
void ChangeReason(int trail_index, Literal new_reason)
bool AddBinaryClauseDuringSearch(Literal a, Literal b)
const std::vector< std::vector< Literal > > & GenerateAtMostOnesWithLargeWeight(const std::vector< Literal > &literals, const std::vector< double > &lp_values)
void ExtractAllBinaryClauses(Output *out) const
absl::Span< const Literal > Reason(const Trail &trail, int trail_index) const final
const absl::InlinedVector< Literal, 6 > & Implications(Literal l) const
void RemoveBooleanVariable(BooleanVariable var, std::deque< std::vector< Literal > > *postsolve_clauses)
void MinimizeConflictFirstWithTransitiveReduction(const Trail &trail, std::vector< Literal > *c, SparseBitset< BooleanVariable > *marked, absl::BitGenRef random)
Literal RepresentativeOf(Literal l) const
void SetDratProofHandler(DratProofHandler *drat_proof_handler)
bool TransformIntoMaxCliques(std::vector< std::vector< Literal > > *at_most_ones, int64_t max_num_explored_nodes=1e8)
int64_t num_redundant_literals() const
const std::vector< Literal > & DirectImplications(Literal literal)
BinaryImplicationGraph(Model *model)
int64_t num_inspections() const
int64_t num_redundant_implications() const
bool IsRedundant(Literal l) const
void AddImplication(Literal a, Literal b)
void MinimizeConflictFirst(const Trail &trail, std::vector< Literal > *c, SparseBitset< BooleanVariable > *marked)
bool DetectEquivalences(bool log_info=false)
void CleanupAllRemovedVariables()
int64_t num_literals_removed() const
int64_t num_propagations() const
bool FindFailedLiteralAroundVar(BooleanVariable var, bool *is_unsat)
void RemoveFixedVariables()
int64_t num_minimization() const
bool IsEmpty() const final
bool IsRemoved(Literal l) const
std::vector< Literal > ExpandAtMostOneWithWeight(const absl::Span< const Literal > at_most_one, const absl::StrongVector< LiteralIndex, bool > &can_be_included, const absl::StrongVector< LiteralIndex, double > &expanded_lp_values)
int64_t num_implications() const
ABSL_MUST_USE_RESULT bool AddAtMostOne(absl::Span< const Literal > at_most_one)
int64_t literal_size() const
void MinimizeConflictExperimental(const Trail &trail, std::vector< Literal > *c)
void Resize(int num_variables)
int DirectImplicationsEstimatedSize(Literal literal) const
LiteralIndex Index() const
ABSL_MUST_USE_RESULT bool InprocessingFixLiteral(Literal true_literal)
LiteralWatchers(Model *model)
bool Propagate(Trail *trail) final
void InprocessingRemoveClause(SatClause *clause)
SatClause * NextClauseToMinimize()
absl::Span< const Literal > Reason(const Trail &trail, int trail_index) const final
absl::flat_hash_map< SatClause *, ClauseInfo > * mutable_clauses_info()
SatClause * AddRemovableClause(const std::vector< Literal > &literals, Trail *trail)
int64_t num_inspected_clauses() const
SatClause * InprocessingAddClause(absl::Span< const Literal > new_clause)
void SetDratProofHandler(DratProofHandler *drat_proof_handler)
int64_t num_clauses() const
void Attach(SatClause *clause, Trail *trail)
bool AddClause(absl::Span< const Literal > literals, Trail *trail)
SatClause * ReasonClause(int trail_index) const
bool IsRemovable(SatClause *const clause) const
ABSL_MUST_USE_RESULT bool InprocessingRewriteClause(SatClause *clause, absl::Span< const Literal > new_clause)
int64_t num_watched_clauses() const
void LazyDetach(SatClause *clause)
int64_t num_removable_clauses() const
const std::vector< SatClause * > & AllClausesInCreationOrder() const
~LiteralWatchers() override
const std::vector< Watcher > & WatcherListOnFalse(Literal false_literal) const
int64_t num_inspected_clause_literals() const
void ResetToMinimizeIndex()
void DeleteRemovedClauses()
int64_t literal_size() const
void Detach(SatClause *clause)
void Resize(int num_variables)
Class that owns everything related to a particular optimization model.
absl::Span< const Literal > AsSpan() const
const Literal *const begin() const
absl::Span< const Literal > PropagationReason() const
Literal SecondLiteral() const
Literal PropagatedLiteral() const
bool IsSatisfied(const VariablesAssignment &assignment) const
bool RemoveFixedLiteralsAndTestIfTrue(const VariablesAssignment &assignment)
std::string DebugString() const
const Literal *const end() const
Literal FirstLiteral() const
static SatClause * Create(absl::Span< const Literal > literals)
void RegisterPropagator(SatPropagator *propagator)
void ChangeReason(int trail_index, int propagator_id)
const VariablesAssignment & Assignment() const
bool LiteralIsTrue(Literal literal) const
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
void swap(IdMap< K, V > &a, IdMap< K, V > &b)
const LiteralIndex kNoLiteralIndex(-1)
Collection of objects used to extend the Constraint Solver library.
#define IF_STATS_ENABLED(instructions)
bool operator==(BinaryClause o) const
bool operator!=(BinaryClause o) const
BinaryClause(Literal _a, Literal _b)
bool protected_during_next_cleanup
Watcher(SatClause *c, Literal b, int i=2)