dlinear  0.0.1
Delta-complete SMT solver for linear programming
Loading...
Searching...
No Matches
SatSolver.cpp
1
6#include "SatSolver.h"
7
8#include <cstdlib>
9#include <unordered_map>
10#include <utility>
11
12#include "dlinear/util/exception.h"
13#include "dlinear/util/logging.h"
14
15namespace dlinear {
16
17SatSolver::SatSolver(PredicateAbstractor &predicate_abstractor, const std::string &class_name)
18 : config_{predicate_abstractor.config()},
19 cur_clause_start_{0},
20 cnfizer_{predicate_abstractor.config()},
21 predicate_abstractor_{predicate_abstractor},
22 stats_{config_.with_timings(), class_name, "Total time spent in CheckSat", "Total # of CheckSat"} {}
23
25
26std::vector<std::vector<Literal>> SatSolver::clauses() const {
27 std::vector<std::vector<Literal>> clauses{std::vector<Literal>{}};
28 for (int sat_lit : main_clauses_copy_) {
29 if (sat_lit == 0) {
30 if (!clauses.back().empty()) clauses.emplace_back();
31 continue;
32 }
33 const Variable &var = sat_to_var_[std::abs(sat_lit)];
34 // The variable was introduced with some cnf conversion. It is not part of the model
35 if (cnf_variables_.count(var.get_id()) > 0) continue;
36 clauses.back().emplace_back(var, sat_lit > 0);
37 }
38 clauses.pop_back();
39 return clauses;
40}
41
43 DLINEAR_DEBUG_FMT("SatSolver::AddFormula({})", f);
44 auto [clauses, aux] = cnfizer_(f);
45
46 // Collect CNF variables and store them in `cnf_variables_`.
47 for (const Variable &p : aux) cnf_variables_.insert(p.get_id());
48 // Convert a first-order clauses into a Boolean formula by predicate abstraction
49 // The original can be retrieved by `predicate_abstractor_[abstracted_formula]`.
50 for (Formula &clause : clauses) clause = predicate_abstractor_.Process(clause);
51
52 AddClauses(clauses);
53}
54
55void SatSolver::AddFormulas(const std::vector<Formula> &formulas) {
56 for (const Formula &f : formulas) AddFormula(f);
57}
58
59void SatSolver::AddClauses(const std::vector<Formula> &formulas) {
60 for (const Formula &f : formulas) AddClause(f);
61}
62
64 DLINEAR_DEBUG_FMT("ContextImpl::AddClause({})", f);
65 // Set up Variable ⇔ Literal (in SAT) map.
66 for (const Variable &var : f.GetFreeVariables()) MakeSatVar(var);
67 // Add clauses to SAT solver.
69}
70
72 DLINEAR_ASSERT_FMT(is_variable(f) || (is_negation(f) && is_variable(get_operand(f))),
73 "f must be a variable or negation of a variable. Found {}", f);
74 if (is_variable(f)) {
75 AddLiteral({get_variable(f), true}, false);
76 } else {
77 AddLiteral({get_variable(get_operand(f)), false}, false);
78 }
79}
80
81void SatSolver::MarkAsCnfVariable(const Variable &var) { cnf_variables_.insert(var.get_id()); }
82
84 LiteralSet fixed_literals;
85 FixedTheoryLiterals(fixed_literals);
86 return fixed_literals;
87}
88void SatSolver::Assume(const LiteralSet &literals) {
89 for (const Literal &lit : literals) Assume(lit);
90}
91
93 main_clauses_copy_.push_back(lit);
95}
96
97void SatSolver::GetMainActiveLiterals(std::set<int> &lits) const {
98 for (auto it = lits.begin(); it != lits.end();) {
99 const int i = *it;
100 bool required = false;
101 // Determine whether literal `i' is required
102 const auto c_it = main_clause_lookup_.find(i);
103 if (c_it != main_clause_lookup_.end()) {
104 for (size_t c : c_it->second) {
105 int count = 0;
106 size_t j;
107 for (j = c; j < main_clauses_copy_.size() && main_clauses_copy_[j]; ++j) {
108 int k = main_clauses_copy_[j];
109 if (lits.find(k) != lits.end()) ++count;
110 }
111 DLINEAR_ASSERT(j < main_clauses_copy_.size(), "buffer overrun");
112 DLINEAR_ASSERT(count > 0, "should contain at least 'i'");
113 if (count == 1) {
114 // `i' is the only active literal in clause `c'; hence, required.
115 required = true;
116 break;
117 }
118 }
119 }
120 // There is more than one literal in every main (non-learned) clause
121 // containing literal `i'. Hence, it is not required.
122 if (!required) {
123 it = lits.erase(it);
124 } else {
125 ++it;
126 }
127 }
128}
129
131 Model model;
132
133 for (int i : GetMainActiveLiterals()) {
134 const auto it_var = sat_to_var_.find(abs(i));
135 if (it_var == sat_to_var_.end()) {
136 // There is no symbolic::Variable corresponding to this
137 // picosat variable (int). This could be because of picosat_push/pop.
138 continue;
139 }
140 const Variable &var{it_var->second};
141 const auto &var_to_formula_map = predicate_abstractor_.var_to_formula_map();
142 if (var_to_formula_map.contains(var)) { // The variable is a theory literal
143 DLINEAR_TRACE_FMT("SatSolver::CheckSat: Add theory literal {}{} to Model", i > 0 ? "" : "¬", var);
144 model.second.emplace_back(var, i > 0);
145 } else if (cnf_variables_.count(var.get_id()) == 0) { // The variable wasn't introduced by CNF transformations
146 DLINEAR_TRACE_FMT("SatSolver::CheckSat: Add Boolean literal {}{} to Model ", i > 0 ? "" : "¬", var);
147 model.first.emplace_back(var, i > 0);
148 } else { // The variable was introduced by CNF transformations
149 DLINEAR_TRACE_FMT("SatSolver::CheckSat: Skip {}{} which is a temporary variable.", i > 0 ? "" : "¬", var);
150 }
151 }
152 DLINEAR_DEBUG("SatSolver::CheckSat() Found a model.");
153 // DLINEAR_TRACE_FMT("SatSolver::CheckSat(): Model: {}", model);
154 return model;
155}
156
157} // namespace dlinear
const IterationStats & stats() const
Get read-only access to the statistics of the FormulaVisitor.
Dataclass collecting statistics about some operation or process.
Definition Stats.h:71
Predicate abstraction is a method to convert a first-order logic formula into a Boolean formula.
Formula Process(const Formula &f)
Convert a first-order logic formula f into a Boolean formula by predicate abstraction.
const std::unordered_map< Variable, Formula > & var_to_formula_map() const
Get read-only access to the map of previously converted formulae to variable of the PredicateAbstract...
SatSolver(PredicateAbstractor &predicate_abstractor, const std::string &class_name="SatSolver")
Construct a new SatSolver object.
Definition SatSolver.cpp:17
void AddClauses(const std::vector< Formula > &formulas)
Add a vector of formulas formulas to the solver.
Definition SatSolver.cpp:59
void AddFormula(const Formula &f)
Add a formula f to the solver.
Definition SatSolver.cpp:42
ScopedUnorderedSet< Variable::Id > cnf_variables_
Set of temporary Boolean variables introduced by CNF transformations.
Definition SatSolver.h:236
std::size_t cur_clause_start_
Index of the first clause added by the SAT solver.
Definition SatSolver.h:231
ScopedUnorderedMap< int, Variable > sat_to_var_
Map int (Variable type in PicoSat) → symbolic::Variable.
Definition SatSolver.h:234
std::vector< int > main_clauses_copy_
Store the main clauses to restore them after the SAT solver call.
Definition SatSolver.h:229
void AddLiteral(const Formula &f)
Add a formula f to the solver.
Definition SatSolver.cpp:71
virtual void AddClauseToSat(const Formula &f)=0
Add a clause f to the internal SAT solver.
Model OnSatResult()
If the SAT solver returns SAT, this function can be used to obtain a model for the formula.
void AddClause(const Formula &f)
Add a formula f to the solver.
Definition SatSolver.cpp:63
PlaistedGreenbaumCnfizer cnfizer_
Converts the formula to CNF.
Definition SatSolver.h:238
PredicateAbstractor & predicate_abstractor_
Converts the theory literals to boolean variables.
Definition SatSolver.h:239
void AddFormulas(const std::vector< Formula > &formulas)
Add the formulas to the solver.
Definition SatSolver.cpp:55
LiteralSet FixedTheoryLiterals()
Get the theory literals that are fixed in the current configuration.
Definition SatSolver.cpp:83
virtual void MakeSatVar(const Variable &var)=0
Add a variable to the internal SAT solver.
void UpdateLookup(int lit)
Update data structures used to minimize the number of assigned literals the theory solver has to veri...
Definition SatSolver.cpp:92
virtual std::set< int > GetMainActiveLiterals()=0
Get a set of the currently active literals in the clauses, ignoring those required by learned clauses...
void MarkAsCnfVariable(const Variable &var)
Mark var as a CNF variable.
Definition SatSolver.cpp:81
void Assume(const LiteralSet &literals)
Assumption a set of literals to be fixed for the next iteration.
Definition SatSolver.cpp:88
const IterationStats & cnfizer_stats() const
Get read-only access to the statistics of the cnfizer of the SAT solver.
Definition SatSolver.cpp:24
std::map< int, std::set< std::size_t > > main_clause_lookup_
Lookup table for literals in the main clauses.
Definition SatSolver.h:230
Represents a symbolic form of a first-order logic formula.
const Variables & GetFreeVariables() const
Gets free variables (unquantified variables).
Represents a symbolic variable.
Global namespace for the dlinear library.
std::set< Literal > LiteralSet
A set of literals.
Definition literal.h:28
std::pair< std::vector< Literal >, std::vector< Literal > > Model
A model is a pair of two vectors of literals.
Definition literal.h:29
A literal is a variable with an associated truth value, indicating whether it is true or false.
Definition literal.h:24