3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-23 09:05:31 +00:00

refactor sat/sls interface. Remove wpm2 and bvsls dependencies

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2014-08-15 10:40:44 -07:00
parent a02cab2194
commit ee1a1b1135
43 changed files with 609 additions and 891 deletions

View file

@ -105,6 +105,7 @@ namespace sat {
}
m_minimize_lemmas = p.minimize_lemmas();
m_minimize_core = p.minimize_core();
m_optimize_model = p.optimize_model();
m_dyn_sub_res = p.dyn_sub_res();
}

View file

@ -69,6 +69,7 @@ namespace sat {
bool m_minimize_lemmas;
bool m_dyn_sub_res;
bool m_minimize_core;
bool m_optimize_model;
symbol m_always_true;

View file

@ -41,6 +41,7 @@ namespace sat {
lbool mus::operator()() {
flet<bool> _disable_min(s.m_config.m_minimize_core, false);
flet<bool> _disable_opt(s.m_config.m_optimize_model, false);
TRACE("sat", tout << "old core: " << s.get_core() << "\n";);
IF_VERBOSE(2, verbose_stream() << "(sat.mus " << s.get_core() << ")\n";);
reset();

View file

@ -19,4 +19,5 @@ def_module_params('sat',
('minimize_lemmas', BOOL, True, 'minimize learned clauses'),
('dyn_sub_res', BOOL, True, 'dynamic subsumption resolution for minimizing learned clauses'),
('minimize_core', BOOL, False, 'minimize computed core'),
('optimize_model', BOOL, False, 'enable optimization of soft constraints'),
('dimacs.core', BOOL, False, 'extract core from DIMACS benchmarks')))

View file

@ -50,8 +50,8 @@ namespace sat {
return m_elems[rnd(num_elems())];
}
sls::sls(solver& s): s(s) {
m_max_tries = 10000;
sls::sls(solver& s): s(s), m_cancel(false) {
m_max_tries = 1000000;
m_prob_choose_min_var = 43;
m_clause_generation = 0;
}
@ -180,6 +180,7 @@ namespace sat {
m_use_list[c[j].index()].push_back(i);
}
}
DEBUG_CODE(check_use_list(););
}
unsigned_vector const& sls::get_use(literal lit) {
@ -242,7 +243,7 @@ namespace sat {
}
void sls::flip(literal lit) {
// IF_VERBOSE(0, verbose_stream() << lit << " ";);
//IF_VERBOSE(0, verbose_stream() << lit << " ";);
SASSERT(value_at(lit, m_model) == l_false);
SASSERT(!m_tabu[lit.var()]);
m_model[lit.var()] = lit.sign()?l_false:l_true;
@ -266,9 +267,70 @@ namespace sat {
}
void sls::check_invariant() {
for (unsigned i = 0; i < m_clauses.size(); ++i) {
clause const& c = *m_clauses[i];
bool is_sat = c.satisfied_by(m_model);
SASSERT(is_sat != m_false.contains(i));
SASSERT(is_sat == m_num_true[i] > 0);
}
}
void sls::check_use_list() {
for (unsigned i = 0; i < m_clauses.size(); ++i) {
clause const& c = *m_clauses[i];
for (unsigned j = 0; j < c.size(); ++j) {
unsigned idx = c[j].index();
SASSERT(m_use_list[idx].contains(i));
}
}
for (unsigned i = 0; i < m_use_list.size(); ++i) {
literal lit = to_literal(i);
for (unsigned j = 0; j < m_use_list[i].size(); ++j) {
clause const& c = *m_clauses[m_use_list[i][j]];
bool found = false;
for (unsigned k = 0; !found && k < c.size(); ++k) {
found = c[k] == lit;
}
SASSERT(found);
}
}
}
void sls::display(std::ostream& out) const {
out << "Model\n";
for (bool_var v = 0; v < m_model.size(); ++v) {
out << v << ": " << m_model[v] << "\n";
}
out << "Clauses\n";
unsigned sz = m_false.num_elems();
for (unsigned i = 0; i < sz; ++i) {
out << *m_clauses[m_false[i]] << "\n";
}
for (unsigned i = 0; i < m_clauses.size(); ++i) {
if (m_false.contains(i)) continue;
clause const& c = *m_clauses[i];
out << c << " " << m_num_true[i] << "\n";
}
bool has_tabu = false;
for (unsigned i = 0; !has_tabu && i < m_tabu.size(); ++i) {
has_tabu = m_tabu[i];
}
if (has_tabu) {
out << "Tabu: ";
for (unsigned i = 0; i < m_tabu.size(); ++i) {
if (m_tabu[i]) {
literal lit(i, false);
if (value_at(lit, m_model) == l_false) lit.neg();
out << lit << " ";
}
}
out << "\n";
}
}
wsls::wsls(solver& s):
sls(s)
{
@ -277,7 +339,7 @@ namespace sat {
wsls::~wsls() {}
void wsls::set_soft(unsigned sz, double const* weights, literal const* lits) {
void wsls::set_soft(unsigned sz, literal const* lits, double const* weights) {
m_soft.reset();
m_weights.reset();
m_soft.append(sz, lits);
@ -291,14 +353,17 @@ namespace sat {
// Initialize m_clause_weights, m_hscore, m_sscore.
//
m_best_value = m_false.empty()?evaluate_model():-1.0;
m_best_model.reset();
m_clause_weights.reset();
m_hscore.reset();
m_sscore.reset();
m_H.reset();
m_S.reset();
m_best_model.append(s.get_model());
m_clause_weights.resize(m_clauses.size(), 1);
m_sscore.resize(s.num_vars(), 0.0);
m_hscore.resize(s.num_vars(), 0);
unsigned num_violated = 0;
for (unsigned i = 0; i < m_soft.size(); ++i) {
literal lit = m_soft[i];
m_sscore[lit.var()] = m_weights[i];
@ -310,16 +375,19 @@ namespace sat {
m_hscore[i] = compute_hscore(i);
refresh_scores(i);
}
DEBUG_CODE(check_invariant(););
unsigned i = 0;
for (; !m_cancel && i < m_max_tries; ++i) {
for (; !m_cancel && m_best_value > 0 && i < m_max_tries; ++i) {
wflip();
}
IF_VERBOSE(2, verbose_stream() << "tries " << i << "\n";);
TRACE("sat", display(tout););
IF_VERBOSE(0, verbose_stream() << "tries " << i << "\n";);
}
void wsls::wflip() {
literal lit;
if (pick_wflip(lit)) {
// IF_VERBOSE(0, verbose_stream() << lit << " ";);
wflip(lit);
}
}
@ -328,8 +396,10 @@ namespace sat {
if (m_false.empty()) {
double val = evaluate_model();
if (val < m_best_value || m_best_value < 0.0) {
m_best_value = val;
m_best_model.reset();
m_best_model.append(m_model);
IF_VERBOSE(0, verbose_stream() << "new value:" << val << "\n";);
}
}
unsigned idx;
@ -337,6 +407,8 @@ namespace sat {
idx = m_H.choose(m_rand);
lit = literal(idx, false);
if (value_at(lit, m_model) == l_true) lit.neg();
SASSERT(value_at(lit, m_model) == l_false);
TRACE("sat", tout << "flip H(" << m_H.num_elems() << ") " << lit << "\n";);
}
else if (!m_S.empty()) {
double score = 0.0;
@ -353,16 +425,38 @@ namespace sat {
m_min_vars.push_back(literal(v, false));
}
}
idx = m_min_vars[m_rand(m_min_vars.size())].var(); // pick with largest sscore.
lit = m_min_vars[m_rand(m_min_vars.size())]; // pick with largest sscore.
SASSERT(value_at(lit, m_model) == l_false);
TRACE("sat", tout << "flip S(" << m_min_vars.size() << "," << score << ") " << lit << "\n";);
}
else {
update_hard_weights();
if (!m_false.empty()) {
unsigned cls_idx = m_false.choose(m_rand);
clause const& c = *m_clauses[cls_idx];
lit = c[m_rand(c.size())];
TRACE("sat", tout << "flip hard(" << m_false.num_elems() << "," << c.size() << ") " << lit << "\n";);
}
else {
lit = m_soft[m_rand(m_soft.size())];
m_min_vars.reset();
for (unsigned i = 0; i < m_soft.size(); ++i) {
lit = m_soft[i];
if (value_at(lit, m_model) == l_false) {
m_min_vars.push_back(lit);
}
}
if (m_min_vars.empty()) {
SASSERT(m_best_value == 0.0);
UNREACHABLE(); // we should have exited the main loop before.
return false;
}
else {
lit = m_min_vars[m_rand(m_min_vars.size())];
}
TRACE("sat", tout << "flip soft(" << m_min_vars.size() << ") " << lit << "\n";);
}
SASSERT(value_at(lit, m_model) == l_false);
}
return !m_tabu[lit.var()];
}
@ -408,7 +502,6 @@ namespace sat {
}
}
}
DEBUG_CODE(check_invariant(););
}
@ -488,9 +581,29 @@ namespace sat {
// The score(v) is the reward on soft clauses for flipping v.
for (unsigned j = 0; j < m_soft.size(); ++j) {
unsigned v = m_soft[j].var();
double ss = value_at(m_soft[j], m_model)?(-m_weights[j]):m_weights[j];
double ss = (l_true == value_at(m_soft[j], m_model))?(-m_weights[j]):m_weights[j];
SASSERT(m_sscore[v] == ss);
}
// m_H are values such that m_hscore >= 0.
for (bool_var v = 0; v < m_hscore.size(); ++v) {
SASSERT(m_hscore[v] > 0 == m_H.contains(v));
}
// m_S are values such that hscore = 0, sscore > 0
for (bool_var v = 0; v < m_sscore.size(); ++v) {
SASSERT((m_hscore[v] == 0 && m_sscore[v] > 0) == m_S.contains(v));
}
}
void wsls::display(std::ostream& out) const {
sls::display(out);
out << "Best model\n";
for (bool_var v = 0; v < m_best_model.size(); ++v) {
out << v << ": " << m_best_model[v] << " h: " << m_hscore[v];
if (m_sscore[v] != 0.0) out << " s: " << m_sscore[v];
out << "\n";
}
}
};

View file

@ -60,6 +60,8 @@ namespace sat {
virtual ~sls();
lbool operator()(unsigned sz, literal const* tabu, bool reuse_model);
void set_cancel(bool f) { m_cancel = f; }
void set_max_tries(unsigned mx) { m_max_tries = mx; }
virtual void display(std::ostream& out) const;
protected:
void init(unsigned sz, literal const* tabu, bool reuse_model);
void init_tabu(unsigned sz, literal const* tabu);
@ -69,6 +71,7 @@ namespace sat {
unsigned_vector const& get_use(literal lit);
void flip(literal lit);
virtual void check_invariant();
void check_use_list();
private:
bool pick_flip(literal& lit);
void flip();
@ -91,9 +94,11 @@ namespace sat {
public:
wsls(solver& s);
virtual ~wsls();
void set_soft(unsigned sz, double const* weights, literal const* lits);
void set_soft(unsigned sz, literal const* lits, double const* weights);
bool has_soft() const { return !m_soft.empty(); }
void opt(unsigned sz, literal const* tabu, bool reuse_model);
model const& get_model() { return m_best_model; }
virtual void display(std::ostream& out) const;
private:
void wflip();
void wflip(literal lit);

View file

@ -40,6 +40,7 @@ namespace sat {
m_asymm_branch(*this, p),
m_probing(*this, p),
m_mus(*this),
m_wsls(*this),
m_inconsistent(false),
m_num_frozen(0),
m_activity_inc(128),
@ -528,6 +529,10 @@ namespace sat {
return found_undef ? l_undef : l_false;
}
void solver::initialize_soft(unsigned sz, literal const* lits, double const* weights) {
m_wsls.set_soft(sz, lits, weights);
}
// -----------------------
//
// Propagation
@ -1003,6 +1008,11 @@ namespace sat {
m_model[v] = value(v);
}
TRACE("sat_mc_bug", m_mc.display(tout););
if (m_config.m_optimize_model) {
m_wsls.opt(0, 0, false);
m_model.reset();
m_model.append(m_wsls.get_model());
}
m_mc(m_model);
TRACE("sat", for (bool_var v = 0; v < num; v++) tout << v << ": " << m_model[v] << "\n";);
@ -2305,6 +2315,7 @@ namespace sat {
void solver::set_cancel(bool f) {
m_cancel = f;
m_wsls.set_cancel(f);
}
void solver::collect_statistics(statistics & st) const {

View file

@ -33,6 +33,7 @@ Revision History:
#include"sat_iff3_finder.h"
#include"sat_probing.h"
#include"sat_mus.h"
#include"sat_sls.h"
#include"params.h"
#include"statistics.h"
#include"stopwatch.h"
@ -82,6 +83,7 @@ namespace sat {
asymm_branch m_asymm_branch;
probing m_probing;
mus m_mus;
wsls m_wsls;
bool m_inconsistent;
// A conflict is usually a single justification. That is, a justification
// for false. If m_not_l is not null_literal, then m_conflict is a
@ -224,13 +226,14 @@ namespace sat {
void assign_core(literal l, justification jst);
void set_conflict(justification c, literal not_l);
void set_conflict(justification c) { set_conflict(c, null_literal); }
lbool status(clause const & c) const;
lbool status(clause const & c) const;
clause_offset get_offset(clause const & c) const { return m_cls_allocator.get_offset(&c); }
void checkpoint() {
if (m_cancel) throw solver_exception(Z3_CANCELED_MSG);
if (memory::get_allocation_size() > m_config.m_max_memory) throw solver_exception(Z3_MAX_MEMORY_MSG);
}
typedef std::pair<literal, literal> bin_clause;
void initialize_soft(unsigned sz, literal const* lits, double const* weights);
protected:
watch_list & get_wlist(literal l) { return m_watches[l.index()]; }
watch_list const & get_wlist(literal l) const { return m_watches[l.index()]; }

View file

@ -36,6 +36,7 @@ Notes:
#include"model_v2_pp.h"
#include"tactic.h"
#include"ast_pp.h"
#include<strstream>
struct goal2sat::imp {
struct frame {
@ -78,8 +79,9 @@ struct goal2sat::imp {
m_max_memory = megabytes_to_bytes(p.get_uint("max_memory", UINT_MAX));
}
void throw_op_not_handled() {
throw tactic_exception("operator not supported, apply simplifier before invoking translator");
void throw_op_not_handled(std::string const& s) {
std::string s0 = "operator " + s + " not supported, apply simplifier before invoking translator";
throw tactic_exception(s0.c_str());
}
void mk_clause(sat::literal l) {
@ -183,9 +185,12 @@ struct goal2sat::imp {
case OP_AND:
case OP_XOR:
case OP_IMPLIES:
case OP_DISTINCT:
case OP_DISTINCT: {
TRACE("goal2sat_not_handled", tout << mk_ismt2_pp(t, m) << "\n";);
throw_op_not_handled();
std::ostringstream strm;
strm << mk_ismt2_pp(t, m);
throw_op_not_handled(strm.str());
}
default:
convert_atom(t, root, sign);
return true;