7#include "PicosatSatSolver.h"
9#include <unordered_map>
12#include "dlinear/util/Config.h"
13#include "dlinear/util/ScopedUnorderedMap.hpp"
14#include "dlinear/util/Stats.h"
15#include "dlinear/util/Timer.h"
16#include "dlinear/util/exception.h"
17#include "dlinear/util/logging.h"
21PicosatSatSolver::PicosatSatSolver(PredicateAbstractor &predicate_abstractor,
const std::string &class_name)
22 : SatSolver{predicate_abstractor, class_name}, sat_(picosat_init()), has_picosat_pop_used_{false} {
23 picosat_save_original_clauses(sat_);
24 if (config_.random_seed() != 0) {
25 picosat_set_seed(sat_, config_.random_seed());
26 DLINEAR_DEBUG_FMT(
"PicosatSatSolver::Set Random Seed {}", config_.random_seed());
28 picosat_set_global_default_phase(sat_,
static_cast<int>(config_.sat_default_phase()));
29 DLINEAR_DEBUG_FMT(
"PicosatSatSolver::Set Default Phase {}", config_.sat_default_phase());
31PicosatSatSolver::~PicosatSatSolver() { picosat_reset(sat_); }
33void PicosatSatSolver::MakeSatVar(
const Variable &var) {
34 auto it = var_to_sat_.find(var.get_id());
36 if (it != var_to_sat_.end())
return;
39 const int sat_var{picosat_inc_max_var(sat_)};
40 var_to_sat_.insert(var.get_id(), sat_var);
41 sat_to_var_.insert(sat_var, var);
42 DLINEAR_DEBUG_FMT(
"PicosatSatSolver::MakeSatVar({} ↦ {})", var, sat_var);
45void PicosatSatSolver::AddLearnedClause(
const LiteralSet &literals) {
46 for (
const Literal &lit : literals) AddLiteral(!lit,
true);
49void PicosatSatSolver::AddLearnedClause(
const Literal &lit) {
50 AddLiteral(!lit,
true);
54void PicosatSatSolver::AddLiteral(
const Literal &l,
bool learned) {
55 const auto &[var, truth] = l;
56 DLINEAR_ASSERT(var.get_type() == Variable::Type::BOOLEAN,
"var must be Boolean");
58 const int lit = truth ? var_to_sat_[var.get_id()] : -var_to_sat_[var.get_id()];
59 picosat_add(sat_, lit);
61 if (!learned) UpdateLookup(lit);
64std::set<int> PicosatSatSolver::GetMainActiveLiterals() {
66 for (
int i = 1; i <= picosat_variables(sat_); ++i) {
67 const int lit = i * (has_picosat_pop_used_ ? picosat_deref(sat_, i) : picosat_deref_partial(sat_, i));
68 if (lit == 0)
continue;
72 SatSolver::GetMainActiveLiterals(lits);
76std::optional<Model> PicosatSatSolver::CheckSat() {
77 TimerGuard timer_guard(&stats_.m_timer(), stats_.enabled());
80 DLINEAR_DEBUG_FMT(
"PicosatSatSolver::CheckSat(#vars = {}, #clauses = {})", picosat_variables(sat_),
81 picosat_added_original_clauses(sat_));
84 const int ret{picosat_sat(sat_, -1)};
86 if (ret == PICOSAT_SATISFIABLE) {
88 }
else if (ret == PICOSAT_UNSATISFIABLE) {
89 DLINEAR_DEBUG(
"PicosatSatSolver::CheckSat() No solution.");
92 DLINEAR_ASSERT(ret == PICOSAT_UNKNOWN,
"ret must be PICOSAT_UNKNOWN");
93 DLINEAR_RUNTIME_ERROR(
"PICOSAT returns PICOSAT_UNKNOWN.");
97void PicosatSatSolver::AddClauseToSat(
const Formula &f) {
98 cur_clause_start_ = main_clauses_copy_.size();
99 if (is_disjunction(f)) {
101 for (
const Formula &l : get_operands(f)) SatSolver::AddLiteral(l);
104 SatSolver::AddLiteral(f);
106 picosat_add(sat_, 0);
107 main_clauses_copy_.push_back(0);
110void PicosatSatSolver::FixedTheoryLiterals(
LiteralSet &fixed_literals) {
111 std::vector<int> clause;
112 clause.reserve(main_clauses_copy_.size());
113 for (
const int sat_lit : main_clauses_copy_) {
115 if (clause.size() == 1) {
116 DLINEAR_ASSERT(clause[0] != 0,
"Clause must be either true or false");
117 const Variable &var = sat_to_var_[abs(clause[0])];
118 if (predicate_abstractor_.var_to_formula_map().contains(var)) fixed_literals.emplace(var, clause[0] > 0);
123 clause.push_back(sat_lit);
125 DLINEAR_TRACE_FMT(
"PicosatSatSolver::FixedTheoryLiterals() fixed_literals = {}", fixed_literals);
128void PicosatSatSolver::Assume(
const Literal &lit) {
129 DLINEAR_TRACE_FMT(
"PicosatSatSolver::Assume({})", lit);
130 picosat_assume(sat_, lit.
truth ? var_to_sat_[lit.
var.get_id()] : -var_to_sat_[lit.
var.get_id()]);
133void PicosatSatSolver::Push() {
134 DLINEAR_DEBUG(
"PicosatSatSolver::Push()");
138 cnf_variables_.push();
139 DLINEAR_RUNTIME_ERROR(
"picosat_push is bugged.");
141void PicosatSatSolver::Pop() {
142 DLINEAR_DEBUG(
"PicosatSatSolver::Pop()");
143 cnf_variables_.pop();
147 has_picosat_pop_used_ =
true;
148 DLINEAR_RUNTIME_ERROR(
"picosat_pop is bugged.");
The TimeGuard wraps a timer object and pauses it when the guard object is destructed.
Represents a symbolic variable.
Global namespace for the dlinear library.
std::set< Literal > LiteralSet
A set of literals.
A literal is a variable with an associated truth value, indicating whether it is true or false.