mirror of
https://github.com/Z3Prover/z3
synced 2025-04-06 01:24:08 +00:00
remove unused features related to weighted check-sat
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
9f49905582
commit
bc6b3007de
|
@ -2,7 +2,6 @@ z3_add_component(sat
|
|||
SOURCES
|
||||
dimacs.cpp
|
||||
sat_asymm_branch.cpp
|
||||
sat_bceq.cpp
|
||||
sat_clause.cpp
|
||||
sat_clause_set.cpp
|
||||
sat_clause_use_list.cpp
|
||||
|
@ -16,7 +15,6 @@ z3_add_component(sat
|
|||
sat_probing.cpp
|
||||
sat_scc.cpp
|
||||
sat_simplifier.cpp
|
||||
sat_sls.cpp
|
||||
sat_solver.cpp
|
||||
sat_watched.cpp
|
||||
COMPONENT_DEPENDENCIES
|
||||
|
|
|
@ -302,17 +302,7 @@ public:
|
|||
}
|
||||
|
||||
lbool check_sat(unsigned sz, expr* const* asms) {
|
||||
if (m_st == s_primal_dual && m_c.sat_enabled()) {
|
||||
rational max_weight = m_upper;
|
||||
vector<rational> weights;
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
weights.push_back(get_weight(asms[i]));
|
||||
}
|
||||
return inc_sat_check_sat(s(), sz, asms, weights.c_ptr(), max_weight);
|
||||
}
|
||||
else {
|
||||
return s().check_sat(sz, asms);
|
||||
}
|
||||
return s().check_sat(sz, asms);
|
||||
}
|
||||
|
||||
void found_optimum() {
|
||||
|
|
|
@ -20,9 +20,49 @@ Notes:
|
|||
#include "smt_literal.h"
|
||||
#include "ast_pp.h"
|
||||
#include "th_rewriter.h"
|
||||
#include "sat_sls.h"
|
||||
#include "sat_types.h"
|
||||
|
||||
namespace smt {
|
||||
|
||||
class index_set {
|
||||
|
||||
unsigned_vector m_elems;
|
||||
unsigned_vector m_index;
|
||||
public:
|
||||
unsigned num_elems() const { return m_elems.size(); }
|
||||
unsigned operator[](unsigned idx) const { return m_elems[idx]; }
|
||||
void reset() { m_elems.reset(); m_index.reset(); }
|
||||
bool empty() const { return m_elems.empty(); }
|
||||
|
||||
bool contains(unsigned idx) const {
|
||||
return
|
||||
(idx < m_index.size()) &&
|
||||
(m_index[idx] < m_elems.size()) &&
|
||||
(m_elems[m_index[idx]] == idx);
|
||||
}
|
||||
|
||||
void insert(unsigned idx) {
|
||||
m_index.reserve(idx+1);
|
||||
if (!contains(idx)) {
|
||||
m_index[idx] = m_elems.size();
|
||||
m_elems.push_back(idx);
|
||||
}
|
||||
}
|
||||
|
||||
void remove(unsigned idx) {
|
||||
if (!contains(idx)) return;
|
||||
unsigned pos = m_index[idx];
|
||||
m_elems[pos] = m_elems.back();
|
||||
m_index[m_elems[pos]] = pos;
|
||||
m_elems.pop_back();
|
||||
}
|
||||
|
||||
unsigned choose(random_gen& rnd) const {
|
||||
SASSERT(!empty());
|
||||
return m_elems[rnd(num_elems())];
|
||||
}
|
||||
};
|
||||
|
||||
struct pb_sls::imp {
|
||||
|
||||
struct clause {
|
||||
|
@ -73,8 +113,8 @@ namespace smt {
|
|||
expr_ref_vector m_trail;
|
||||
obj_map<expr, unsigned> m_decl2var; // map declarations to Boolean variables.
|
||||
ptr_vector<expr> m_var2decl; // reverse map
|
||||
sat::index_set m_hard_false; // list of hard clauses that are false.
|
||||
sat::index_set m_soft_false; // list of soft clauses that are false.
|
||||
index_set m_hard_false; // list of hard clauses that are false.
|
||||
index_set m_soft_false; // list of soft clauses that are false.
|
||||
unsigned m_max_flips; // maximal number of flips
|
||||
unsigned m_non_greedy_percent; // percent of moves to do non-greedy style
|
||||
random_gen m_rng;
|
||||
|
|
|
@ -1,530 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2014 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
sat_bceq.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Find equivalent literals based on blocked clause decomposition.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2014-09-27.
|
||||
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"sat_bceq.h"
|
||||
#include"sat_solver.h"
|
||||
#include"trace.h"
|
||||
#include"bit_vector.h"
|
||||
#include"map.h"
|
||||
#include"sat_elim_eqs.h"
|
||||
|
||||
namespace sat {
|
||||
|
||||
void bceq::use_list::init(unsigned num_vars) {
|
||||
m_clauses.reset();
|
||||
m_clauses.resize(2*num_vars);
|
||||
}
|
||||
|
||||
void bceq::use_list::insert(clause& c) {
|
||||
unsigned sz = c.size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
m_clauses[c[i].index()].push_back(&c);
|
||||
}
|
||||
}
|
||||
|
||||
void bceq::use_list::erase(clause& c) {
|
||||
unsigned sz = c.size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
m_clauses[c[i].index()].erase(&c);
|
||||
}
|
||||
}
|
||||
|
||||
ptr_vector<clause>& bceq::use_list::get(literal lit) {
|
||||
return m_clauses[lit.index()];
|
||||
}
|
||||
|
||||
bceq::bceq(solver & s):
|
||||
m_solver(s) {
|
||||
}
|
||||
|
||||
void bceq::register_clause(clause* cls) {
|
||||
m_clauses.setx(cls->id(), cls, 0);
|
||||
}
|
||||
|
||||
void bceq::unregister_clause(clause* cls) {
|
||||
m_clauses.setx(cls->id(), 0, 0);
|
||||
}
|
||||
|
||||
void bceq::init() {
|
||||
m_clauses.reset();
|
||||
m_bin_clauses.reset();
|
||||
m_L.reset();
|
||||
m_R.reset();
|
||||
m_L_blits.reset();
|
||||
m_R_blits.reset();
|
||||
m_bce_use_list.reset();
|
||||
clause * const* it = m_solver.begin_clauses();
|
||||
clause * const* end = m_solver.end_clauses();
|
||||
for (; it != end; ++it) {
|
||||
clause* cls = *it;
|
||||
if (!cls->was_removed()) {
|
||||
m_use_list->insert(*cls);
|
||||
register_clause(cls);
|
||||
}
|
||||
}
|
||||
bin_clauses bc;
|
||||
m_solver.collect_bin_clauses(bc, false); // exclude roots.
|
||||
literal lits[2];
|
||||
for (unsigned i = 0; i < bc.size(); ++i) {
|
||||
lits[0] = bc[i].first;
|
||||
lits[1] = bc[i].second;
|
||||
clause* cls = m_solver.m_cls_allocator.mk_clause(2, lits, false);
|
||||
m_use_list->insert(*cls);
|
||||
m_bin_clauses.push_back(cls);
|
||||
register_clause(cls);
|
||||
}
|
||||
TRACE("sat",
|
||||
for (unsigned i = 0; i < m_clauses.size(); ++i) {
|
||||
clause const* cls = m_clauses[i];
|
||||
if (cls) tout << *cls << "\n";
|
||||
});
|
||||
}
|
||||
|
||||
void bceq::pure_decompose() {
|
||||
// while F != empty
|
||||
// pick a clause and variable x in clause.
|
||||
// get use list U1 of x and U2 of ~x
|
||||
// assume |U1| >= |U2|
|
||||
// add U1 to clause set.
|
||||
for (unsigned i = 0; i < m_clauses.size(); ++i) {
|
||||
clause* cls = m_clauses[i];
|
||||
if (cls) {
|
||||
SASSERT(i == cls->id());
|
||||
pure_decompose((*cls)[0]);
|
||||
SASSERT(!m_clauses[i]);
|
||||
}
|
||||
}
|
||||
m_L.reverse();
|
||||
m_L_blits.reverse();
|
||||
}
|
||||
|
||||
void bceq::pure_decompose(literal lit) {
|
||||
clause_use_list& pos = m_use_list->get(lit);
|
||||
clause_use_list& neg = m_use_list->get(~lit);
|
||||
unsigned sz1 = m_L.size();
|
||||
unsigned sz2 = m_R.size();
|
||||
pure_decompose(pos, m_L);
|
||||
pure_decompose(neg, m_R);
|
||||
unsigned delta1 = m_L.size() - sz1;
|
||||
unsigned delta2 = m_R.size() - sz2;
|
||||
if (delta1 < delta2) {
|
||||
m_L_blits.resize(sz1+delta2, ~lit);
|
||||
m_R_blits.resize(sz2+delta1, lit);
|
||||
for (unsigned i = 0; i < delta1; ++i) {
|
||||
std::swap(m_L[sz1 + i], m_R[sz2 + i]);
|
||||
}
|
||||
for (unsigned i = delta1; i < delta2; ++i) {
|
||||
m_L.push_back(m_R[sz2 + i]);
|
||||
}
|
||||
m_R.resize(sz2 + delta1);
|
||||
std::swap(delta1, delta2);
|
||||
}
|
||||
else {
|
||||
m_L_blits.resize(sz1+delta1, lit);
|
||||
m_R_blits.resize(sz2+delta2, ~lit);
|
||||
}
|
||||
TRACE("bceq", tout << lit << " " << "pos: " << delta1 << " " << "neg: " << delta2 << "\n";);
|
||||
}
|
||||
|
||||
void bceq::pure_decompose(clause_use_list& uses, svector<clause*>& clauses) {
|
||||
unsigned sz = uses.size();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
clause& cls = *uses[i];
|
||||
if (!cls.was_removed() && m_clauses[cls.id()]) {
|
||||
clauses.push_back(&cls);
|
||||
m_clauses[cls.id()] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bceq::post_decompose() {
|
||||
m_marked.reset();
|
||||
m_marked.resize(2*m_solver.num_vars(), false);
|
||||
use_list ul;
|
||||
use_list* save = m_use_list;
|
||||
m_use_list = &ul;
|
||||
ul.init(m_solver.num_vars());
|
||||
for (unsigned i = 0; i < m_L.size(); ++i) {
|
||||
ul.insert(*m_L[i]);
|
||||
}
|
||||
|
||||
// cheap pass: add clauses from R in order
|
||||
// such that they are blocked with respect to
|
||||
// predecessors.
|
||||
m_removed.reset();
|
||||
for (unsigned i = 0; i < m_R.size(); ++i) {
|
||||
literal lit = find_blocked(*m_R[i]);
|
||||
if (lit != null_literal) {
|
||||
m_L.push_back(m_R[i]);
|
||||
m_L_blits.push_back(lit);
|
||||
ul.insert(*m_R[i]);
|
||||
m_R[i] = m_R.back();
|
||||
m_R_blits[i] = m_R_blits.back();
|
||||
m_R.pop_back();
|
||||
m_R_blits.pop_back();
|
||||
--i;
|
||||
}
|
||||
}
|
||||
// expensive pass: add clauses from R as long
|
||||
// as BCE produces the empty set of clauses.
|
||||
m_bce_use_list.init(m_solver.num_vars());
|
||||
for (unsigned i = 0; i < m_L.size(); ++i) {
|
||||
m_bce_use_list.insert(*m_L[i]);
|
||||
}
|
||||
for (unsigned i = 0; i < m_R.size(); ++i) {
|
||||
if (bce(*m_R[i])) {
|
||||
m_R[i] = m_R.back();
|
||||
m_R_blits[i] = m_R_blits.back();
|
||||
m_R.pop_back();
|
||||
m_R_blits.pop_back();
|
||||
--i;
|
||||
}
|
||||
}
|
||||
m_use_list = save;
|
||||
}
|
||||
|
||||
|
||||
// Note: replay blocked clause elimination:
|
||||
// Suppose C u { c1 } is blocked.
|
||||
// annotate each clause by blocking literal.
|
||||
// for new clause c2, check if C u { c2 } is blocked.
|
||||
// For each c in C record which literal it is blocked.
|
||||
// (Order the clauses in C by block ordering)
|
||||
// l | c is blocked,
|
||||
// -> c2 contains ~l => check if c c2 is blocked
|
||||
//
|
||||
bool bceq::bce(clause& cls0) {
|
||||
IF_VERBOSE(1, verbose_stream() << "bce " << m_L.size() << " " << m_R.size() << " " << cls0 << "\n";);
|
||||
unsigned_vector& live_clauses = m_live_clauses;
|
||||
live_clauses.reset();
|
||||
m_use_list = &m_bce_use_list;
|
||||
m_bce_use_list.insert(cls0);
|
||||
svector<clause*>& clauses = m_L;
|
||||
literal_vector& blits = m_L_blits;
|
||||
clauses.push_back(&cls0);
|
||||
blits.push_back(null_literal);
|
||||
bool removed = false;
|
||||
m_removed.reset();
|
||||
for (unsigned i = 0; i < clauses.size(); ++i) {
|
||||
clause& cls1 = *clauses[i];
|
||||
literal lit = find_blocked(cls1);
|
||||
if (lit == null_literal) {
|
||||
live_clauses.push_back(i);
|
||||
}
|
||||
else {
|
||||
m_removed.setx(cls1.id(), true, false);
|
||||
removed = true;
|
||||
}
|
||||
}
|
||||
while (removed) {
|
||||
removed = false;
|
||||
//std::cout << live_clauses.size() << " ";
|
||||
for (unsigned i = 0; i < live_clauses.size(); ++i) {
|
||||
clause& cls1 = *clauses[live_clauses[i]];
|
||||
literal lit = find_blocked(cls1);
|
||||
if (lit != null_literal) {
|
||||
m_removed.setx(cls1.id(), true, false);
|
||||
removed = true;
|
||||
live_clauses[i] = live_clauses.back();
|
||||
live_clauses.pop_back();
|
||||
--i;
|
||||
}
|
||||
}
|
||||
}
|
||||
//std::cout << "\n";
|
||||
m_bce_use_list.erase(cls0);
|
||||
clauses.pop_back();
|
||||
blits.pop_back();
|
||||
return live_clauses.empty();
|
||||
}
|
||||
|
||||
literal bceq::find_blocked(clause const& cls) {
|
||||
TRACE("bceq", tout << cls << "\n";);
|
||||
|
||||
unsigned sz = cls.size();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
m_marked[(~cls[i]).index()] = true;
|
||||
}
|
||||
literal result = null_literal;
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
literal lit = cls[i];
|
||||
if (is_blocked(lit)) {
|
||||
TRACE("bceq", tout << "is blocked " << lit << " : " << cls << "\n";);
|
||||
result = lit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
m_marked[(~cls[i]).index()] = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool bceq::is_blocked(literal lit) const {
|
||||
clause_use_list& uses = m_use_list->get(~lit);
|
||||
unsigned sz = uses.size();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
clause const& cls = *uses[i];
|
||||
unsigned sz = cls.size();
|
||||
bool is_axiom = m_removed.get(cls.id(), false);
|
||||
for (unsigned i = 0; !is_axiom && i < sz; ++i) {
|
||||
is_axiom = m_marked[cls[i].index()] && cls[i] != ~lit;
|
||||
}
|
||||
|
||||
TRACE("bceq", tout << "resolvent " << lit << " : " << cls << " " << (is_axiom?"axiom":"non-axiom") << "\n";);
|
||||
if (!is_axiom) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void bceq::init_rbits() {
|
||||
m_rbits.reset();
|
||||
for (unsigned i = 0; i < m_solver.num_vars(); ++i) {
|
||||
uint64 lo = m_rand() + (m_rand() << 16);
|
||||
uint64 hi = m_rand() + (m_rand() << 16);
|
||||
m_rbits.push_back(lo + (hi << 32ULL));
|
||||
}
|
||||
}
|
||||
|
||||
void bceq::init_reconstruction_stack() {
|
||||
m_rstack.reset();
|
||||
m_bstack.reset();
|
||||
// decomposition already creates a blocked stack in the proper order.
|
||||
m_rstack.append(m_L);
|
||||
m_bstack.append(m_L_blits);
|
||||
}
|
||||
|
||||
uint64 bceq::eval_clause(clause const& cls) const {
|
||||
uint64 b = 0;
|
||||
unsigned sz = cls.size();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
literal lit = cls[i];
|
||||
uint64 val = m_rbits[lit.var()];
|
||||
if (lit.sign()) {
|
||||
val = ~val;
|
||||
}
|
||||
b |= val;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
void bceq::sat_sweep() {
|
||||
init_rbits();
|
||||
init_reconstruction_stack();
|
||||
for (unsigned i = 0; i < m_rstack.size(); ++i) {
|
||||
clause const& cls = *m_rstack[i];
|
||||
literal block_lit = m_bstack[i];
|
||||
uint64 b = eval_clause(cls);
|
||||
// v = 0, b = 0 -> v := 1
|
||||
// v = 0, b = 1 -> v := 0
|
||||
// v = 1, b = 0 -> v := 0
|
||||
// v = 1, b = 1 -> v := 1
|
||||
m_rbits[block_lit.var()] ^= ~b;
|
||||
|
||||
}
|
||||
DEBUG_CODE(verify_sweep(););
|
||||
}
|
||||
|
||||
void bceq::verify_sweep() {
|
||||
DEBUG_CODE(
|
||||
for (unsigned i = 0; i < m_L.size(); ++i) {
|
||||
uint64 b = eval_clause(*m_L[i]);
|
||||
SASSERT((~b) == 0);
|
||||
});
|
||||
}
|
||||
|
||||
struct u64_hash { unsigned operator()(uint64 u) const { return (unsigned)u; } };
|
||||
|
||||
struct u64_eq { bool operator()(uint64 u1, uint64 u2) const { return u1 == u2; } };
|
||||
|
||||
void bceq::extract_partition() {
|
||||
unsigned num_vars = m_solver.num_vars();
|
||||
map<uint64, unsigned, u64_hash, u64_eq> table;
|
||||
union_find<> union_find(m_union_find_ctx);
|
||||
for (unsigned i = 0; i < num_vars; ++i) {
|
||||
m_s->mk_var(true, true);
|
||||
union_find.mk_var();
|
||||
}
|
||||
for (unsigned i = 0; i < m_L.size(); ++i) {
|
||||
m_s->mk_clause(m_L[i]->size(), m_L[i]->begin());
|
||||
}
|
||||
for (unsigned i = 0; i < num_vars; ++i) {
|
||||
uint64 val = m_rbits[i];
|
||||
unsigned index;
|
||||
if (table.find(val, index)) {
|
||||
union_find.merge(i, index);
|
||||
}
|
||||
else if (table.find(~val, index)) {
|
||||
union_find.merge(i, index);
|
||||
}
|
||||
else {
|
||||
table.insert(val, i);
|
||||
}
|
||||
}
|
||||
TRACE("sat", union_find.display(tout););
|
||||
|
||||
//
|
||||
// Preliminary version:
|
||||
// A more appropriate is to walk each pair,
|
||||
// and refine partition based on SAT results.
|
||||
//
|
||||
for (unsigned i = 0; i < num_vars; ++i) {
|
||||
if (!union_find.is_root(i)) continue;
|
||||
unsigned v = union_find.next(i);
|
||||
unsigned last_v = UINT_MAX;
|
||||
if (!m_solver.was_eliminated(i)) {
|
||||
last_v = i;
|
||||
}
|
||||
while (v != i) {
|
||||
if (!m_solver.was_eliminated(v)) {
|
||||
if (last_v != UINT_MAX) {
|
||||
if (check_equality(v, last_v)) {
|
||||
// last_v was eliminated.
|
||||
|
||||
}
|
||||
else {
|
||||
// TBD: refine partition.
|
||||
}
|
||||
}
|
||||
last_v = v;
|
||||
}
|
||||
v = union_find.next(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool bceq::check_equality(unsigned v1, unsigned v2) {
|
||||
TRACE("sat", tout << "check: " << v1 << " = " << v2 << "\n";);
|
||||
uint64 val1 = m_rbits[v1];
|
||||
uint64 val2 = m_rbits[v2];
|
||||
literal l1 = literal(v1, false);
|
||||
literal l2 = literal(v2, false);
|
||||
if (val1 != val2) {
|
||||
SASSERT(val1 == ~val2);
|
||||
l2.neg();
|
||||
}
|
||||
if (is_already_equiv(l1, l2)) {
|
||||
TRACE("sat", tout << "Already equivalent: " << l1 << " " << l2 << "\n";);
|
||||
return false;
|
||||
}
|
||||
|
||||
literal lits[2];
|
||||
lits[0] = l1;
|
||||
lits[1] = ~l2;
|
||||
lbool is_sat = m_s->check(2, lits);
|
||||
if (is_sat == l_false) {
|
||||
lits[0] = ~l1;
|
||||
lits[1] = l2;
|
||||
is_sat = m_s->check(2, lits);
|
||||
}
|
||||
if (is_sat == l_false) {
|
||||
TRACE("sat", tout << "Found equivalent: " << l1 << " " << l2 << "\n";);
|
||||
assert_equality(l1, l2);
|
||||
}
|
||||
else {
|
||||
TRACE("sat", tout << "Not equivalent: " << l1 << " " << l2 << "\n";);
|
||||
// TBD: if is_sat == l_true, then refine partition.
|
||||
}
|
||||
return is_sat == l_false;
|
||||
}
|
||||
|
||||
bool bceq::is_already_equiv(literal l1, literal l2) {
|
||||
watch_list const& w1 = m_solver.get_wlist(l1);
|
||||
bool found = false;
|
||||
for (unsigned i = 0; !found && i < w1.size(); ++i) {
|
||||
watched const& w = w1[i];
|
||||
found = w.is_binary_clause() && w.get_literal() == ~l2;
|
||||
}
|
||||
if (!found) return false;
|
||||
found = false;
|
||||
watch_list const& w2 = m_solver.get_wlist(~l1);
|
||||
for (unsigned i = 0; !found && i < w2.size(); ++i) {
|
||||
watched const& w = w2[i];
|
||||
found = w.is_binary_clause() && w.get_literal() == l2;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
void bceq::assert_equality(literal l1, literal l2) {
|
||||
if (l2.sign()) {
|
||||
l1.neg();
|
||||
l2.neg();
|
||||
}
|
||||
literal_vector roots;
|
||||
bool_var_vector vars;
|
||||
for (unsigned i = 0; i < m_solver.num_vars(); ++i) {
|
||||
roots.push_back(literal(i, false));
|
||||
}
|
||||
roots[l2.var()] = l1;
|
||||
vars.push_back(l2.var());
|
||||
elim_eqs elim(m_solver);
|
||||
IF_VERBOSE(1,
|
||||
for (unsigned i = 0; i < vars.size(); ++i) {
|
||||
verbose_stream() << "var: " << vars[i] << " root: " << roots[vars[i]] << "\n";
|
||||
});
|
||||
elim(roots, vars);
|
||||
}
|
||||
|
||||
void bceq::cleanup() {
|
||||
m_solver.del_clauses(m_bin_clauses.begin(), m_bin_clauses.end());
|
||||
m_bin_clauses.reset();
|
||||
}
|
||||
|
||||
|
||||
void bceq::operator()() {
|
||||
if (!m_solver.m_config.m_bcd) return;
|
||||
flet<bool> _disable_bcd(m_solver.m_config.m_bcd, false);
|
||||
flet<bool> _disable_min(m_solver.m_config.m_core_minimize, false);
|
||||
flet<bool> _disable_opt(m_solver.m_config.m_optimize_model, false);
|
||||
flet<unsigned> _bound_maxc(m_solver.m_config.m_max_conflicts, 1500);
|
||||
|
||||
use_list ul;
|
||||
solver s(m_solver.m_params, m_solver.rlimit(), 0);
|
||||
s.m_config.m_bcd = false;
|
||||
s.m_config.m_core_minimize = false;
|
||||
s.m_config.m_optimize_model = false;
|
||||
s.m_config.m_max_conflicts = 1500;
|
||||
m_use_list = &ul;
|
||||
m_s = &s;
|
||||
ul.init(m_solver.num_vars());
|
||||
init();
|
||||
pure_decompose();
|
||||
post_decompose();
|
||||
IF_VERBOSE(1, verbose_stream() << "Decomposed set " << m_L.size() << " rest: " << m_R.size() << "\n";);
|
||||
|
||||
TRACE("sat",
|
||||
tout << "Decomposed set " << m_L.size() << "\n";
|
||||
for (unsigned i = 0; i < m_L.size(); ++i) {
|
||||
clause const* cls = m_L[i];
|
||||
if (cls) tout << *cls << "\n";
|
||||
}
|
||||
tout << "remainder " << m_R.size() << "\n";
|
||||
for (unsigned i = 0; i < m_R.size(); ++i) {
|
||||
clause const* cls = m_R[i];
|
||||
if (cls) tout << *cls << "\n";
|
||||
}
|
||||
);
|
||||
sat_sweep();
|
||||
extract_partition();
|
||||
cleanup();
|
||||
}
|
||||
};
|
|
@ -1,89 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2014 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
sat_bceq.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Find equivalent literals based on blocked clause decomposition.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2014-09-27.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef SAT_BCEQ_H_
|
||||
#define SAT_BCEQ_H_
|
||||
|
||||
#include"sat_types.h"
|
||||
#include"union_find.h"
|
||||
|
||||
|
||||
namespace sat {
|
||||
class solver;
|
||||
|
||||
class bceq {
|
||||
typedef ptr_vector<clause> clause_use_list;
|
||||
class use_list {
|
||||
vector<ptr_vector<clause> > m_clauses;
|
||||
public:
|
||||
use_list() {}
|
||||
void init(unsigned num_vars);
|
||||
void reset() { m_clauses.reset(); }
|
||||
void erase(clause& c);
|
||||
void insert(clause& c);
|
||||
ptr_vector<clause>& get(literal lit);
|
||||
};
|
||||
typedef std::pair<literal, literal> bin_clause;
|
||||
typedef svector<bin_clause> bin_clauses;
|
||||
solver & m_solver;
|
||||
use_list* m_use_list;
|
||||
use_list m_bce_use_list;
|
||||
solver* m_s;
|
||||
random_gen m_rand;
|
||||
svector<clause*> m_clauses;
|
||||
svector<clause*> m_L;
|
||||
svector<clause*> m_R;
|
||||
literal_vector m_L_blits;
|
||||
literal_vector m_R_blits;
|
||||
svector<clause*> m_bin_clauses;
|
||||
svector<uint64> m_rbits;
|
||||
svector<clause*> m_rstack; // stack of blocked clauses
|
||||
literal_vector m_bstack; // stack of blocking literals
|
||||
svector<bool> m_marked;
|
||||
svector<bool> m_removed; // set of clauses removed (not considered in clause set during BCE)
|
||||
union_find_default_ctx m_union_find_ctx;
|
||||
unsigned_vector m_live_clauses;
|
||||
|
||||
void init();
|
||||
void register_clause(clause* cls);
|
||||
void unregister_clause(clause* cls);
|
||||
void pure_decompose();
|
||||
void pure_decompose(literal lit);
|
||||
void pure_decompose(ptr_vector<clause>& uses, svector<clause*>& clauses);
|
||||
void post_decompose();
|
||||
literal find_blocked(clause const& cls);
|
||||
bool bce(clause& cls);
|
||||
bool is_blocked(literal lit) const;
|
||||
void init_rbits();
|
||||
void init_reconstruction_stack();
|
||||
void sat_sweep();
|
||||
void cleanup();
|
||||
uint64 eval_clause(clause const& cls) const;
|
||||
void verify_sweep();
|
||||
void extract_partition();
|
||||
bool check_equality(unsigned v1, unsigned v2);
|
||||
bool is_already_equiv(literal l1, literal l2);
|
||||
void assert_equality(literal l1, literal l2);
|
||||
public:
|
||||
bceq(solver & s);
|
||||
void operator()();
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -111,8 +111,6 @@ namespace sat {
|
|||
m_minimize_lemmas = p.minimize_lemmas();
|
||||
m_core_minimize = p.core_minimize();
|
||||
m_core_minimize_partial = p.core_minimize_partial();
|
||||
m_optimize_model = p.optimize_model();
|
||||
m_bcd = p.bcd();
|
||||
m_dyn_sub_res = p.dyn_sub_res();
|
||||
}
|
||||
|
||||
|
|
|
@ -72,8 +72,6 @@ namespace sat {
|
|||
bool m_dyn_sub_res;
|
||||
bool m_core_minimize;
|
||||
bool m_core_minimize_partial;
|
||||
bool m_optimize_model;
|
||||
bool m_bcd;
|
||||
|
||||
|
||||
symbol m_always_true;
|
||||
|
|
|
@ -20,11 +20,10 @@ Notes:
|
|||
|
||||
#include "sat_solver.h"
|
||||
#include "sat_mus.h"
|
||||
#include "sat_sls.h"
|
||||
|
||||
namespace sat {
|
||||
|
||||
mus::mus(solver& s):s(s), m_is_active(false), m_best_value(0), m_restart(0), m_max_restarts(0) {}
|
||||
mus::mus(solver& s):s(s), m_is_active(false),m_restart(0), m_max_restarts(0) {}
|
||||
|
||||
mus::~mus() {}
|
||||
|
||||
|
@ -32,7 +31,6 @@ namespace sat {
|
|||
m_core.reset();
|
||||
m_mus.reset();
|
||||
m_model.reset();
|
||||
m_best_value = 0;
|
||||
m_max_restarts = (s.m_stats.m_restart - m_restart) + 10;
|
||||
m_restart = s.m_stats.m_restart;
|
||||
}
|
||||
|
@ -45,21 +43,13 @@ namespace sat {
|
|||
}
|
||||
|
||||
void mus::update_model() {
|
||||
double new_value = s.m_wsls.evaluate_model(s.m_model);
|
||||
if (m_model.empty()) {
|
||||
m_model.append(s.m_model);
|
||||
m_best_value = new_value;
|
||||
}
|
||||
else if (m_best_value > new_value) {
|
||||
m_model.reset();
|
||||
m_model.append(s.m_model);
|
||||
m_best_value = new_value;
|
||||
}
|
||||
}
|
||||
|
||||
lbool mus::operator()() {
|
||||
flet<bool> _disable_min(s.m_config.m_core_minimize, false);
|
||||
flet<bool> _disable_opt(s.m_config.m_optimize_model, false);
|
||||
flet<bool> _is_active(m_is_active, true);
|
||||
IF_VERBOSE(3, verbose_stream() << "(sat.mus " << s.get_core() << ")\n";);
|
||||
reset();
|
||||
|
@ -120,9 +110,6 @@ namespace sat {
|
|||
SASSERT(value_at(lit, s.get_model()) == l_false);
|
||||
mus.push_back(lit);
|
||||
update_model();
|
||||
if (!core.empty()) {
|
||||
// mr(); // TBD: measure
|
||||
}
|
||||
break;
|
||||
}
|
||||
case l_false:
|
||||
|
@ -262,27 +249,5 @@ namespace sat {
|
|||
IF_VERBOSE(3, verbose_stream() << "core verification: " << is_sat << " " << core << "\n";);
|
||||
}
|
||||
|
||||
void mus::mr() {
|
||||
sls sls(s);
|
||||
literal_vector tabu;
|
||||
tabu.append(m_mus);
|
||||
tabu.append(m_core);
|
||||
bool reuse_model = false;
|
||||
for (unsigned i = m_mus.size(); i < tabu.size(); ++i) {
|
||||
tabu[i] = ~tabu[i];
|
||||
lbool is_sat = sls(tabu.size(), tabu.c_ptr(), reuse_model);
|
||||
tabu[i] = ~tabu[i];
|
||||
if (is_sat == l_true) {
|
||||
m_mus.push_back(tabu[i]);
|
||||
m_core.erase(tabu[i]);
|
||||
IF_VERBOSE(3, verbose_stream() << "in core " << tabu[i] << "\n";);
|
||||
reuse_model = true;
|
||||
}
|
||||
else {
|
||||
IF_VERBOSE(3, verbose_stream() << "NOT in core " << tabu[i] << "\n";);
|
||||
reuse_model = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ namespace sat {
|
|||
literal_vector m_mus;
|
||||
bool m_is_active;
|
||||
model m_model; // model obtained during minimal unsat core
|
||||
double m_best_value;
|
||||
unsigned m_restart;
|
||||
unsigned m_max_restarts;
|
||||
|
||||
|
@ -41,7 +40,6 @@ namespace sat {
|
|||
lbool mus1();
|
||||
lbool mus2();
|
||||
lbool qx(literal_set& assignment, literal_set& support, bool has_support);
|
||||
void mr();
|
||||
void reset();
|
||||
void set_core();
|
||||
void update_model();
|
||||
|
|
|
@ -22,6 +22,4 @@ def_module_params('sat',
|
|||
('dyn_sub_res', BOOL, True, 'dynamic subsumption resolution for minimizing learned clauses'),
|
||||
('core.minimize', BOOL, False, 'minimize computed core'),
|
||||
('core.minimize_partial', BOOL, False, 'apply partial (cheap) core minimization'),
|
||||
('optimize_model', BOOL, False, 'enable optimization of soft constraints'),
|
||||
('bcd', BOOL, False, 'enable blocked clause decomposition for equality extraction'),
|
||||
('dimacs.core', BOOL, False, 'extract core from DIMACS benchmarks')))
|
||||
|
|
|
@ -1,686 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2014 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
sat_sls.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
SLS for clauses in SAT solver
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2014-12-8
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
|
||||
#include "sat_sls.h"
|
||||
#include "sat_solver.h"
|
||||
|
||||
namespace sat {
|
||||
|
||||
bool index_set::contains(unsigned idx) const {
|
||||
return
|
||||
(idx < m_index.size()) &&
|
||||
(m_index[idx] < m_elems.size()) &&
|
||||
(m_elems[m_index[idx]] == idx);
|
||||
}
|
||||
|
||||
void index_set::insert(unsigned idx) {
|
||||
m_index.reserve(idx+1);
|
||||
if (!contains(idx)) {
|
||||
m_index[idx] = m_elems.size();
|
||||
m_elems.push_back(idx);
|
||||
}
|
||||
}
|
||||
|
||||
void index_set::remove(unsigned idx) {
|
||||
if (!contains(idx)) return;
|
||||
unsigned pos = m_index[idx];
|
||||
m_elems[pos] = m_elems.back();
|
||||
m_index[m_elems[pos]] = pos;
|
||||
m_elems.pop_back();
|
||||
}
|
||||
|
||||
unsigned index_set::choose(random_gen& rnd) const {
|
||||
SASSERT(!empty());
|
||||
return m_elems[rnd(num_elems())];
|
||||
}
|
||||
|
||||
sls::sls(solver& s): s(s) {
|
||||
m_prob_choose_min_var = 43;
|
||||
m_clause_generation = 0;
|
||||
}
|
||||
|
||||
sls::~sls() {
|
||||
for (unsigned i = 0; i < m_bin_clauses.size(); ++i) {
|
||||
m_alloc.del_clause(m_bin_clauses[i]);
|
||||
}
|
||||
}
|
||||
|
||||
lbool sls::operator()(unsigned sz, literal const* tabu, bool reuse_model) {
|
||||
init(sz, tabu, reuse_model);
|
||||
unsigned i;
|
||||
for (i = 0; !m_false.empty() && !s.canceled() && i < m_max_tries; ++i) {
|
||||
flip();
|
||||
}
|
||||
IF_VERBOSE(2, verbose_stream() << "tries " << i << "\n";);
|
||||
if (m_false.empty()) {
|
||||
SASSERT(s.check_model(m_model));
|
||||
return l_true;
|
||||
}
|
||||
return l_undef;
|
||||
}
|
||||
|
||||
void sls::init(unsigned sz, literal const* tabu, bool reuse_model) {
|
||||
bool same_generation = (m_clause_generation == s.m_stats.m_non_learned_generation);
|
||||
if (!same_generation) {
|
||||
init_clauses();
|
||||
init_use();
|
||||
IF_VERBOSE(0, verbose_stream() << s.m_stats.m_non_learned_generation << " " << m_clause_generation << "\n";);
|
||||
}
|
||||
if (!reuse_model) {
|
||||
init_model();
|
||||
}
|
||||
init_tabu(sz, tabu);
|
||||
m_clause_generation = s.m_stats.m_non_learned_generation;
|
||||
|
||||
m_max_tries = 10*(s.num_vars() + m_clauses.size());
|
||||
|
||||
}
|
||||
|
||||
void sls::init_clauses() {
|
||||
for (unsigned i = 0; i < m_bin_clauses.size(); ++i) {
|
||||
m_alloc.del_clause(m_bin_clauses[i]);
|
||||
}
|
||||
m_bin_clauses.reset();
|
||||
m_clauses.reset();
|
||||
clause * const * it = s.begin_clauses();
|
||||
clause * const * end = s.end_clauses();
|
||||
for (; it != end; ++it) {
|
||||
m_clauses.push_back(*it);
|
||||
}
|
||||
svector<solver::bin_clause> bincs;
|
||||
s.collect_bin_clauses(bincs, false);
|
||||
literal lits[2];
|
||||
for (unsigned i = 0; i < bincs.size(); ++i) {
|
||||
lits[0] = bincs[i].first;
|
||||
lits[1] = bincs[i].second;
|
||||
clause* cl = m_alloc.mk_clause(2, lits, false);
|
||||
m_clauses.push_back(cl);
|
||||
m_bin_clauses.push_back(cl);
|
||||
}
|
||||
}
|
||||
|
||||
void sls::init_model() {
|
||||
m_num_true.reset();
|
||||
m_model.reset();
|
||||
m_model.append(s.get_model());
|
||||
unsigned sz = m_clauses.size();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
clause const& c = *m_clauses[i];
|
||||
unsigned n = 0;
|
||||
unsigned csz = c.size();
|
||||
for (unsigned j = 0; j < csz; ++j) {
|
||||
lbool val = value_at(c[j], m_model);
|
||||
switch (val) {
|
||||
case l_true:
|
||||
++n;
|
||||
break;
|
||||
case l_undef:
|
||||
++n;
|
||||
m_model[c[j].var()] = c[j].sign()?l_false:l_true;
|
||||
SASSERT(value_at(c[j], m_model) == l_true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_num_true.push_back(n);
|
||||
if (n == 0) {
|
||||
m_false.insert(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sls::init_tabu(unsigned sz, literal const* tabu) {
|
||||
// our main use is where m_model satisfies all the hard constraints.
|
||||
// SASSERT(s.check_model(m_model));
|
||||
// SASSERT(m_false.empty());
|
||||
// ASSERT: m_num_true is correct count.
|
||||
m_tabu.reset();
|
||||
m_tabu.resize(s.num_vars(), false);
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
literal lit = tabu[i];
|
||||
if (s.m_level[lit.var()] == 0) continue;
|
||||
if (value_at(lit, m_model) == l_false) {
|
||||
flip(lit);
|
||||
}
|
||||
m_tabu[lit.var()] = true;
|
||||
}
|
||||
for (unsigned i = 0; i < s.m_trail.size(); ++i) {
|
||||
literal lit = s.m_trail[i];
|
||||
if (s.m_level[lit.var()] > 0) break;
|
||||
if (value_at(lit, m_model) != l_true) {
|
||||
flip(lit);
|
||||
}
|
||||
m_tabu[lit.var()] = true;
|
||||
}
|
||||
}
|
||||
|
||||
void sls::init_use() {
|
||||
m_use_list.reset();
|
||||
m_use_list.resize(s.num_vars()*2);
|
||||
unsigned sz = m_clauses.size();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
clause const& c = *m_clauses[i];
|
||||
unsigned csz = c.size();
|
||||
for (unsigned j = 0; j < csz; ++j) {
|
||||
m_use_list[c[j].index()].push_back(i);
|
||||
}
|
||||
}
|
||||
DEBUG_CODE(check_use_list(););
|
||||
}
|
||||
|
||||
unsigned_vector const& sls::get_use(literal lit) {
|
||||
SASSERT(lit.index() < m_use_list.size());
|
||||
return m_use_list[lit.index()];
|
||||
}
|
||||
|
||||
unsigned sls::get_break_count(literal lit, unsigned min_break) {
|
||||
SASSERT(value_at(lit, m_model) == l_false);
|
||||
unsigned result = 0;
|
||||
unsigned_vector const& uses = get_use(~lit);
|
||||
unsigned sz = uses.size();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
if (m_num_true[uses[i]] == 1) {
|
||||
++result;
|
||||
if (result > min_break) return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool sls::pick_flip(literal& lit) {
|
||||
unsigned clause_idx = m_false.choose(m_rand);
|
||||
clause const& c = *m_clauses[clause_idx];
|
||||
SASSERT(!c.satisfied_by(m_model));
|
||||
unsigned min_break = UINT_MAX;
|
||||
unsigned sz = c.size();
|
||||
m_min_vars.reset();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
lit = c[i];
|
||||
if (m_tabu[lit.var()]) continue;
|
||||
unsigned break_count = get_break_count(lit, min_break);
|
||||
if (break_count < min_break) {
|
||||
min_break = break_count;
|
||||
m_min_vars.reset();
|
||||
m_min_vars.push_back(lit);
|
||||
}
|
||||
else if (break_count == min_break) {
|
||||
m_min_vars.push_back(lit);
|
||||
}
|
||||
}
|
||||
if (min_break == 0 || (!m_min_vars.empty() && m_rand(100) >= m_prob_choose_min_var)) {
|
||||
lit = m_min_vars[m_rand(m_min_vars.size())];
|
||||
return true;
|
||||
}
|
||||
else if (min_break == UINT_MAX) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
lit = c[m_rand(c.size())];
|
||||
return !m_tabu[lit.var()];
|
||||
}
|
||||
}
|
||||
|
||||
void sls::flip() {
|
||||
literal lit;
|
||||
if (pick_flip(lit)) {
|
||||
flip(lit);
|
||||
}
|
||||
}
|
||||
|
||||
void sls::flip(literal 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;
|
||||
SASSERT(value_at(lit, m_model) == l_true);
|
||||
unsigned_vector const& use1 = get_use(lit);
|
||||
unsigned sz = use1.size();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
unsigned cl = use1[i];
|
||||
m_num_true[cl]++;
|
||||
SASSERT(m_num_true[cl] <= m_clauses[cl]->size());
|
||||
if (m_num_true[cl] == 1) m_false.remove(cl);
|
||||
}
|
||||
unsigned_vector const& use2 = get_use(~lit);
|
||||
sz = use2.size();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
unsigned cl = use2[i];
|
||||
SASSERT(m_num_true[cl] > 0);
|
||||
m_num_true[cl]--;
|
||||
if (m_num_true[cl] == 0) m_false.insert(cl);
|
||||
}
|
||||
}
|
||||
|
||||
void sls::check_invariant() {
|
||||
DEBUG_CODE(
|
||||
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() {
|
||||
DEBUG_CODE(
|
||||
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)
|
||||
{
|
||||
m_smoothing_probability = 1; // 1/1000
|
||||
}
|
||||
|
||||
wsls::~wsls() {}
|
||||
|
||||
void wsls::set_soft(unsigned sz, literal const* lits, double const* weights) {
|
||||
m_soft.reset();
|
||||
m_weights.reset();
|
||||
m_soft.append(sz, lits);
|
||||
m_weights.append(sz, weights);
|
||||
}
|
||||
|
||||
void wsls::opt(unsigned sz, literal const* tabu, bool reuse_model) {
|
||||
init(sz, tabu, reuse_model);
|
||||
|
||||
//
|
||||
// Initialize m_clause_weights, m_hscore, m_sscore.
|
||||
//
|
||||
m_best_value = m_false.empty()?evaluate_model(m_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);
|
||||
for (unsigned i = 0; i < m_soft.size(); ++i) {
|
||||
literal lit = m_soft[i];
|
||||
m_sscore[lit.var()] = m_weights[i];
|
||||
if (value_at(lit, m_model) == l_true) {
|
||||
m_sscore[lit.var()] = -m_sscore[lit.var()];
|
||||
}
|
||||
}
|
||||
for (bool_var i = 0; i < s.num_vars(); ++i) {
|
||||
m_hscore[i] = compute_hscore(i);
|
||||
refresh_scores(i);
|
||||
}
|
||||
DEBUG_CODE(check_invariant(););
|
||||
unsigned i = 0;
|
||||
for (; !s.canceled() && m_best_value > 0 && i < m_max_tries; ++i) {
|
||||
wflip();
|
||||
if (m_false.empty()) {
|
||||
double val = evaluate_model(m_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);
|
||||
s.set_model(m_best_model);
|
||||
IF_VERBOSE(1, verbose_stream() << "new value: " << val << " @ " << i << "\n";);
|
||||
if (i*2 > m_max_tries) {
|
||||
m_max_tries *= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
bool wsls::pick_wflip(literal & lit) {
|
||||
unsigned idx;
|
||||
if (!m_H.empty()) {
|
||||
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;
|
||||
m_min_vars.reset();
|
||||
for (unsigned i = 0; i < m_S.num_elems(); ++i) {
|
||||
unsigned v = m_S[i];
|
||||
SASSERT(m_sscore[v] > 0.0);
|
||||
if (m_sscore[v] > score) {
|
||||
m_min_vars.reset();
|
||||
m_min_vars.push_back(literal(v, false));
|
||||
score = m_sscore[v];
|
||||
}
|
||||
else if (m_sscore[v] == score) {
|
||||
m_min_vars.push_back(literal(v, false));
|
||||
}
|
||||
}
|
||||
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 {
|
||||
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() << ", " << m_sscore[lit.var()] << ") " << lit << "\n";);
|
||||
|
||||
}
|
||||
SASSERT(value_at(lit, m_model) == l_false);
|
||||
}
|
||||
return !m_tabu[lit.var()];
|
||||
}
|
||||
|
||||
void wsls::wflip(literal lit) {
|
||||
flip(lit);
|
||||
unsigned v = lit.var();
|
||||
m_sscore[v] = -m_sscore[v];
|
||||
m_hscore[v] = compute_hscore(v);
|
||||
refresh_scores(v);
|
||||
recompute_hscores(lit);
|
||||
}
|
||||
|
||||
void wsls::update_hard_weights() {
|
||||
unsigned csz = m_clauses.size();
|
||||
if (m_smoothing_probability >= m_rand(1000)) {
|
||||
for (unsigned i = 0; i < csz; ++i) {
|
||||
if (m_clause_weights[i] > 1 && !m_false.contains(i)) {
|
||||
--m_clause_weights[i];
|
||||
if (m_num_true[i] == 1) {
|
||||
clause const& c = *m_clauses[i];
|
||||
unsigned sz = c.size();
|
||||
for (unsigned j = 0; j < sz; ++j) {
|
||||
if (value_at(c[j], m_model) == l_true) {
|
||||
++m_hscore[c[j].var()];
|
||||
refresh_scores(c[j].var());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (unsigned i = 0; i < csz; ++i) {
|
||||
if (m_false.contains(i)) {
|
||||
++m_clause_weights[i];
|
||||
clause const& c = *m_clauses[i];
|
||||
unsigned sz = c.size();
|
||||
for (unsigned j = 0; j < sz; ++j) {
|
||||
++m_hscore[c[j].var()];
|
||||
refresh_scores(c[j].var());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DEBUG_CODE(check_invariant(););
|
||||
}
|
||||
|
||||
double wsls::evaluate_model(model& mdl) {
|
||||
SASSERT(m_false.empty());
|
||||
double result = 0.0;
|
||||
for (unsigned i = 0; i < m_soft.size(); ++i) {
|
||||
literal lit = m_soft[i];
|
||||
if (value_at(lit, mdl) != l_true) {
|
||||
result += m_weights[i];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int wsls::compute_hscore(bool_var v) {
|
||||
literal lit(v, false);
|
||||
if (value_at(lit, m_model) == l_false) {
|
||||
lit.neg();
|
||||
}
|
||||
SASSERT(value_at(lit, m_model) == l_true);
|
||||
int hs = 0;
|
||||
unsigned_vector const& use1 = get_use(~lit);
|
||||
unsigned sz = use1.size();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
unsigned cl = use1[i];
|
||||
if (m_num_true[cl] == 0) {
|
||||
SASSERT(m_false.contains(cl));
|
||||
hs += m_clause_weights[cl];
|
||||
}
|
||||
else {
|
||||
SASSERT(!m_false.contains(cl));
|
||||
}
|
||||
}
|
||||
unsigned_vector const& use2 = get_use(lit);
|
||||
sz = use2.size();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
unsigned cl = use2[i];
|
||||
if (m_num_true[cl] == 1) {
|
||||
SASSERT(!m_false.contains(cl));
|
||||
hs -= m_clause_weights[cl];
|
||||
}
|
||||
}
|
||||
return hs;
|
||||
}
|
||||
|
||||
void wsls::recompute_hscores(literal lit) {
|
||||
SASSERT(value_at(lit, m_model) == l_true);
|
||||
TRACE("sat", tout << lit.var() << " := " << m_hscore[lit.var()] << "\n";);
|
||||
unsigned_vector const& use1 = get_use(lit);
|
||||
unsigned sz = use1.size();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
unsigned cl = use1[i];
|
||||
TRACE("sat", tout << *m_clauses[cl] << " " << m_num_true[cl] << "\n";);
|
||||
SASSERT(m_num_true[cl] > 0);
|
||||
if (m_num_true[cl] == 1) {
|
||||
// num_true 0 -> 1
|
||||
// other literals don't have upside any more.
|
||||
// subtract one from all other literals
|
||||
adjust_all_values(lit, cl, -static_cast<int>(m_clause_weights[cl]));
|
||||
}
|
||||
else if (m_num_true[cl] == 2) {
|
||||
// num_true 1 -> 2, previous critical literal is no longer critical
|
||||
adjust_pivot_value(lit, cl, +m_clause_weights[cl]);
|
||||
}
|
||||
}
|
||||
unsigned_vector const& use2 = get_use(~lit);
|
||||
sz = use2.size();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
unsigned cl = use2[i];
|
||||
TRACE("sat", tout << *m_clauses[cl] << " " << m_num_true[cl] << "\n";);
|
||||
if (m_num_true[cl] == 0) {
|
||||
// num_true 1 -> 0
|
||||
// all variables became critical.
|
||||
adjust_all_values(~lit, cl, +m_clause_weights[cl]);
|
||||
}
|
||||
else if (m_num_true[cl] == 1) {
|
||||
adjust_pivot_value(~lit, cl, -static_cast<int>(m_clause_weights[cl]));
|
||||
}
|
||||
// else n+1 -> n >= 2
|
||||
}
|
||||
}
|
||||
|
||||
void wsls::adjust_all_values(literal lit, unsigned cl, int delta) {
|
||||
clause const& c = *m_clauses[cl];
|
||||
unsigned sz = c.size();
|
||||
TRACE("sat", tout << lit << " " << c << " delta: " << delta << " nt: " << m_num_true[cl] << "\n";);
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
literal lit2 = c[i];
|
||||
if (lit2 != lit) {
|
||||
TRACE("sat", tout << lit2.var() << " := " << m_hscore[lit2.var()] << "\n";);
|
||||
m_hscore[lit2.var()] += delta;
|
||||
TRACE("sat", tout << lit2.var() << " := " << m_hscore[lit2.var()] << "\n";);
|
||||
refresh_scores(lit2.var());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wsls::adjust_pivot_value(literal lit, unsigned cl, int delta) {
|
||||
clause const& c = *m_clauses[cl];
|
||||
unsigned csz = c.size();
|
||||
for (unsigned j = 0; j < csz; ++j) {
|
||||
literal lit2 = c[j];
|
||||
if (lit2 != lit && value_at(lit2, m_model) == l_true) {
|
||||
TRACE("sat", tout << lit2.var() << " := " << m_hscore[lit2.var()] << "\n";);
|
||||
m_hscore[lit2.var()] += delta;
|
||||
TRACE("sat", tout << lit2.var() << " := " << m_hscore[lit2.var()] << "\n";);
|
||||
refresh_scores(lit2.var());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wsls::refresh_scores(bool_var v) {
|
||||
if (m_hscore[v] > 0 && !m_tabu[v] && m_sscore[v] == 0) {
|
||||
m_H.insert(v);
|
||||
}
|
||||
else {
|
||||
m_H.remove(v);
|
||||
}
|
||||
if (m_sscore[v] > 0) {
|
||||
if (m_hscore[v] == 0 && !m_tabu[v]) {
|
||||
m_S.insert(v);
|
||||
}
|
||||
else {
|
||||
m_S.remove(v);
|
||||
}
|
||||
}
|
||||
else if (m_sscore[v] < 0) {
|
||||
m_S.remove(v);
|
||||
}
|
||||
}
|
||||
|
||||
void wsls::check_invariant() {
|
||||
sls::check_invariant();
|
||||
// The hscore is the reward for flipping the truth value of variable v.
|
||||
// hscore(v) = Sum weight(c) for num_true(c) = 0 and v in c
|
||||
// - Sum weight(c) for num_true(c) = 1 and (v in c, M(v) or !v in c and !M(v))
|
||||
DEBUG_CODE(
|
||||
for (unsigned v = 0; v < s.num_vars(); ++v) {
|
||||
int hs = compute_hscore(v);
|
||||
CTRACE("sat", hs != m_hscore[v], display(tout << v << " - computed: " << hs << " - assigned: " << m_hscore[v] << "\n"););
|
||||
SASSERT(m_hscore[v] == hs);
|
||||
}
|
||||
|
||||
// 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 = (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 and sscore = 0.
|
||||
for (bool_var v = 0; v < m_hscore.size(); ++v) {
|
||||
SASSERT((m_hscore[v] > 0 && !m_tabu[v] && m_sscore[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_tabu[v]) == 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";
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2014 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
sat_sls.h
|
||||
|
||||
Abstract:
|
||||
|
||||
SLS for clauses in SAT solver
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2014-12-8
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#ifndef SAT_SLS_H_
|
||||
#define SAT_SLS_H_
|
||||
|
||||
#include "util.h"
|
||||
#include "sat_simplifier.h"
|
||||
|
||||
namespace sat {
|
||||
|
||||
class index_set {
|
||||
unsigned_vector m_elems;
|
||||
unsigned_vector m_index;
|
||||
public:
|
||||
unsigned num_elems() const { return m_elems.size(); }
|
||||
unsigned operator[](unsigned idx) const { return m_elems[idx]; }
|
||||
void reset() { m_elems.reset(); m_index.reset(); }
|
||||
bool empty() const { return m_elems.empty(); }
|
||||
bool contains(unsigned idx) const;
|
||||
void insert(unsigned idx);
|
||||
void remove(unsigned idx);
|
||||
unsigned choose(random_gen& rnd) const;
|
||||
};
|
||||
|
||||
class sls {
|
||||
protected:
|
||||
solver& s;
|
||||
random_gen m_rand;
|
||||
unsigned m_max_tries;
|
||||
unsigned m_prob_choose_min_var; // number between 0 and 99.
|
||||
unsigned m_clause_generation;
|
||||
ptr_vector<clause const> m_clauses; // vector of all clauses.
|
||||
index_set m_false; // clauses currently false
|
||||
vector<unsigned_vector> m_use_list; // use lists for literals
|
||||
unsigned_vector m_num_true; // per clause, count of # true literals
|
||||
svector<literal> m_min_vars; // literals with smallest break count
|
||||
model m_model; // current model
|
||||
clause_allocator m_alloc; // clause allocator
|
||||
clause_vector m_bin_clauses; // binary clauses
|
||||
svector<bool> m_tabu; // variables that cannot be swapped
|
||||
public:
|
||||
sls(solver& s);
|
||||
virtual ~sls();
|
||||
lbool operator()(unsigned sz, literal const* tabu, bool reuse_model);
|
||||
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);
|
||||
void init_model();
|
||||
void init_use();
|
||||
void init_clauses();
|
||||
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();
|
||||
unsigned get_break_count(literal lit, unsigned min_break);
|
||||
};
|
||||
|
||||
/**
|
||||
\brief sls with weighted soft clauses.
|
||||
*/
|
||||
class wsls : public sls {
|
||||
unsigned_vector m_clause_weights;
|
||||
svector<int> m_hscore;
|
||||
svector<double> m_sscore;
|
||||
literal_vector m_soft;
|
||||
svector<double> m_weights;
|
||||
double m_best_value;
|
||||
model m_best_model;
|
||||
index_set m_H, m_S;
|
||||
unsigned m_smoothing_probability;
|
||||
public:
|
||||
wsls(solver& s);
|
||||
virtual ~wsls();
|
||||
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);
|
||||
virtual void display(std::ostream& out) const;
|
||||
double evaluate_model(model& mdl);
|
||||
private:
|
||||
void wflip();
|
||||
void wflip(literal lit);
|
||||
void update_hard_weights();
|
||||
bool pick_wflip(literal & lit);
|
||||
virtual void check_invariant();
|
||||
void refresh_scores(bool_var v);
|
||||
int compute_hscore(bool_var v);
|
||||
void recompute_hscores(literal lit);
|
||||
void adjust_all_values(literal lit, unsigned cl, int delta);
|
||||
void adjust_pivot_value(literal lit, unsigned cl, int delta);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -20,7 +20,6 @@ Revision History:
|
|||
#include"sat_integrity_checker.h"
|
||||
#include"luby.h"
|
||||
#include"trace.h"
|
||||
#include"sat_bceq.h"
|
||||
#include"max_cliques.h"
|
||||
|
||||
// define to update glue during propagation
|
||||
|
@ -42,7 +41,6 @@ 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),
|
||||
|
@ -55,7 +53,6 @@ namespace sat {
|
|||
m_conflicts = 0;
|
||||
m_next_simplify = 0;
|
||||
m_num_checkpoints = 0;
|
||||
m_initializing_preferred = false;
|
||||
}
|
||||
|
||||
solver::~solver() {
|
||||
|
@ -713,7 +710,7 @@ namespace sat {
|
|||
// Search
|
||||
//
|
||||
// -----------------------
|
||||
lbool solver::check(unsigned num_lits, literal const* lits, double const* weights, double max_weight) {
|
||||
lbool solver::check(unsigned num_lits, literal const* lits) {
|
||||
pop_to_base_level();
|
||||
IF_VERBOSE(2, verbose_stream() << "(sat.sat-solver)\n";);
|
||||
SASSERT(scope_lvl() == 0);
|
||||
|
@ -728,7 +725,7 @@ namespace sat {
|
|||
init_search();
|
||||
propagate(false);
|
||||
if (inconsistent()) return l_false;
|
||||
init_assumptions(num_lits, lits, weights, max_weight);
|
||||
init_assumptions(num_lits, lits);
|
||||
propagate(false);
|
||||
if (check_inconsistent()) return l_false;
|
||||
cleanup();
|
||||
|
@ -914,12 +911,11 @@ namespace sat {
|
|||
}
|
||||
}
|
||||
|
||||
void solver::init_assumptions(unsigned num_lits, literal const* lits, double const* weights, double max_weight) {
|
||||
void solver::init_assumptions(unsigned num_lits, literal const* lits) {
|
||||
if (num_lits == 0 && m_user_scope_literals.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
retry_init_assumptions:
|
||||
reset_assumptions();
|
||||
push();
|
||||
|
||||
|
@ -943,16 +939,6 @@ namespace sat {
|
|||
assign(nlit, justification());
|
||||
}
|
||||
|
||||
if (weights && !inconsistent()) {
|
||||
if (m_config.m_optimize_model) {
|
||||
m_wsls.set_soft(num_lits, lits, weights);
|
||||
}
|
||||
if (!init_weighted_assumptions(num_lits, lits, weights, max_weight)) {
|
||||
goto retry_init_assumptions;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; !inconsistent() && i < num_lits; ++i) {
|
||||
literal lit = lits[i];
|
||||
SASSERT(is_external(lit.var()));
|
||||
|
@ -962,109 +948,6 @@ namespace sat {
|
|||
}
|
||||
|
||||
|
||||
bool solver::init_weighted_assumptions(unsigned num_lits, literal const* lits, double const* weights, double max_weight) {
|
||||
flet<bool> _min1(m_config.m_core_minimize, false);
|
||||
m_weight = 0;
|
||||
m_blocker.reset();
|
||||
svector<lbool> values;
|
||||
unsigned num_cores = 0;
|
||||
for (unsigned i = 0; !inconsistent() && i < num_lits; ++i) {
|
||||
literal lit = lits[i];
|
||||
SASSERT(is_external(lit.var()));
|
||||
TRACE("sat", tout << "propagate: " << lit << " " << value(lit) << "\n";);
|
||||
SASSERT(m_scope_lvl == 1);
|
||||
add_assumption(lit);
|
||||
switch(value(lit)) {
|
||||
case l_undef:
|
||||
values.push_back(l_true);
|
||||
assign(lit, justification());
|
||||
if (num_cores*2 >= num_lits) {
|
||||
break;
|
||||
}
|
||||
propagate(false);
|
||||
if (inconsistent()) {
|
||||
flet<bool> _init(m_initializing_preferred, true);
|
||||
while (inconsistent()) {
|
||||
if (!resolve_conflict()) {
|
||||
return true;
|
||||
}
|
||||
propagate(true);
|
||||
}
|
||||
if (m_scope_lvl == 0) {
|
||||
return false;
|
||||
}
|
||||
// backjump to last consistent assumption:
|
||||
unsigned j;
|
||||
m_weight = 0;
|
||||
m_blocker.reset();
|
||||
for (j = 0; j < i && value(lits[j]) == values[j]; ++j) {
|
||||
if (values[j] == l_false) {
|
||||
m_weight += weights[j];
|
||||
m_blocker.push_back(lits[j]);
|
||||
}
|
||||
}
|
||||
SASSERT(value(lits[j]) != values[j]);
|
||||
SASSERT(j <= i);
|
||||
SASSERT(j == 0 || value(lits[j-1]) == values[j-1]);
|
||||
for (unsigned k = i; k >= j; --k) {
|
||||
if (is_assumption(lits[k])) {
|
||||
pop_assumption();
|
||||
}
|
||||
}
|
||||
values.resize(j);
|
||||
TRACE("sat", tout << "backjump " << (i - j + 1) << " steps " << num_cores << "\n";);
|
||||
i = j - 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case l_false:
|
||||
++num_cores;
|
||||
values.push_back(l_false);
|
||||
SASSERT(!inconsistent());
|
||||
set_conflict(justification(), ~lit);
|
||||
m_conflict_lvl = scope_lvl();
|
||||
resolve_conflict_for_unsat_core();
|
||||
IF_VERBOSE(3, verbose_stream() << "(sat.core: " << m_core << ")\n";);
|
||||
update_min_core();
|
||||
SASSERT(m_min_core_valid);
|
||||
m_weight += weights[i];
|
||||
if (m_weight <= max_weight) {
|
||||
m_blocker.push_back(lit);
|
||||
}
|
||||
TRACE("sat", tout << "core: " << m_core << "\nassumptions: " << m_assumptions << "\n";);
|
||||
SASSERT(m_core.size() <= m_assumptions.size());
|
||||
SASSERT(m_assumptions.size() <= i+1);
|
||||
if (m_core.size() <= 3) {
|
||||
m_inconsistent = true;
|
||||
TRACE("opt", tout << "found small core: " << m_core << "\n";);
|
||||
IF_VERBOSE(11, verbose_stream() << "(sat.core: " << m_core << ")\n";);
|
||||
return true;
|
||||
}
|
||||
pop_assumption();
|
||||
m_inconsistent = false;
|
||||
break;
|
||||
case l_true:
|
||||
values.push_back(l_true);
|
||||
SASSERT(m_justification[lit.var()].get_kind() != justification::NONE || lvl(lit) == 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
TRACE("sat", tout << "initialized\n";);
|
||||
IF_VERBOSE(11, verbose_stream() << "(sat.blocker: " << m_blocker << "\nCore: " << m_min_core << ")\n";);
|
||||
if (m_weight >= max_weight) {
|
||||
// block the current correction set candidate.
|
||||
++m_stats.m_blocked_corr_sets;
|
||||
TRACE("opt", tout << "blocking soft correction set: " << m_blocker << "\n";);
|
||||
IF_VERBOSE(11, verbose_stream() << "blocking " << m_blocker << "\n";);
|
||||
pop_to_base_level();
|
||||
mk_clause_core(m_blocker);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void solver::update_min_core() {
|
||||
if (!m_min_core_valid || m_core.size() < m_min_core.size()) {
|
||||
m_min_core.reset();
|
||||
|
@ -1148,11 +1031,6 @@ namespace sat {
|
|||
m_min_core_valid = false;
|
||||
m_min_core.reset();
|
||||
TRACE("sat", display(tout););
|
||||
|
||||
if (m_config.m_bcd) {
|
||||
bceq bc(*this);
|
||||
bc();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1244,9 +1122,6 @@ 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_mc(m_model);
|
||||
TRACE("sat", for (bool_var v = 0; v < num; v++) tout << v << ": " << m_model[v] << "\n";);
|
||||
|
||||
|
@ -1673,10 +1548,6 @@ namespace sat {
|
|||
if (m_not_l == literal()) tout << "null literal\n";
|
||||
else tout << m_not_l << "\n";);
|
||||
|
||||
if (m_initializing_preferred) {
|
||||
SASSERT(m_conflict_lvl <= 1);
|
||||
return resolve_conflict_for_init();
|
||||
}
|
||||
if (m_conflict_lvl <= 1 && tracking_assumptions()) {
|
||||
resolve_conflict_for_unsat_core();
|
||||
return false;
|
||||
|
@ -3184,10 +3055,10 @@ namespace sat {
|
|||
if (asms.empty()) {
|
||||
bool_var v = mk_var(true, false);
|
||||
literal lit(v, false);
|
||||
init_assumptions(1, &lit, 0, 0);
|
||||
init_assumptions(1, &lit);
|
||||
}
|
||||
else {
|
||||
init_assumptions(asms.size(), asms.c_ptr(), 0, 0);
|
||||
init_assumptions(asms.size(), asms.c_ptr());
|
||||
}
|
||||
propagate(false);
|
||||
if (check_inconsistent()) return l_false;
|
||||
|
@ -3249,10 +3120,10 @@ namespace sat {
|
|||
if (asms.empty()) {
|
||||
bool_var v = mk_var(true, false);
|
||||
literal lit(v, false);
|
||||
init_assumptions(1, &lit, 0, 0);
|
||||
init_assumptions(1, &lit);
|
||||
}
|
||||
else {
|
||||
init_assumptions(asms.size(), asms.c_ptr(), 0, 0);
|
||||
init_assumptions(asms.size(), asms.c_ptr());
|
||||
}
|
||||
propagate(false);
|
||||
if (check_inconsistent()) return l_false;
|
||||
|
|
|
@ -33,7 +33,6 @@ 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"
|
||||
|
@ -86,7 +85,6 @@ namespace sat {
|
|||
asymm_branch m_asymm_branch;
|
||||
probing m_probing;
|
||||
mus m_mus; // MUS for minimal core extraction
|
||||
wsls m_wsls; // SLS facility for MaxSAT use
|
||||
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
|
||||
|
@ -141,9 +139,6 @@ namespace sat {
|
|||
friend class probing;
|
||||
friend class iff3_finder;
|
||||
friend class mus;
|
||||
friend class sls;
|
||||
friend class wsls;
|
||||
friend class bceq;
|
||||
friend struct mk_stat;
|
||||
public:
|
||||
solver(params_ref const & p, reslimit& l, extension * ext);
|
||||
|
@ -280,10 +275,7 @@ namespace sat {
|
|||
//
|
||||
// -----------------------
|
||||
public:
|
||||
lbool check(unsigned num_lits = 0, literal const* lits = 0) {
|
||||
return check(num_lits, lits, 0, 0);
|
||||
}
|
||||
lbool check(unsigned num_lits, literal const* lits, double const* weights, double max_weight);
|
||||
lbool check(unsigned num_lits = 0, literal const* lits = 0);
|
||||
|
||||
model const & get_model() const { return m_model; }
|
||||
bool model_is_current() const { return m_model_is_current; }
|
||||
|
@ -311,11 +303,7 @@ namespace sat {
|
|||
|
||||
literal_vector m_min_core;
|
||||
bool m_min_core_valid;
|
||||
literal_vector m_blocker;
|
||||
double m_weight;
|
||||
bool m_initializing_preferred;
|
||||
void init_assumptions(unsigned num_lits, literal const* lits, double const* weights, double max_weight);
|
||||
bool init_weighted_assumptions(unsigned num_lits, literal const* lits, double const* weights, double max_weight);
|
||||
void init_assumptions(unsigned num_lits, literal const* lits);
|
||||
void reassert_min_core();
|
||||
void update_min_core();
|
||||
void resolve_weighted();
|
||||
|
|
|
@ -105,13 +105,8 @@ public:
|
|||
|
||||
virtual void set_progress_callback(progress_callback * callback) {}
|
||||
|
||||
virtual lbool check_sat(unsigned num_assumptions, expr * const * assumptions) {
|
||||
return check_sat(num_assumptions, assumptions, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
void display_weighted(std::ostream& out, unsigned sz, expr * const * assumptions, unsigned const* weights) {
|
||||
m_weights.reset();
|
||||
if (weights != 0) {
|
||||
for (unsigned i = 0; i < sz; ++i) m_weights.push_back(weights[i]);
|
||||
}
|
||||
|
@ -131,15 +126,11 @@ public:
|
|||
for (unsigned i = 0; i < m_asms.size(); ++i) {
|
||||
nweights.push_back((unsigned) m_weights[i]);
|
||||
}
|
||||
m_weights.reset();
|
||||
m_solver.display_wcnf(out, m_asms.size(), m_asms.c_ptr(), nweights.c_ptr());
|
||||
}
|
||||
|
||||
lbool check_sat(unsigned sz, expr * const * assumptions, double const* weights, double max_weight) {
|
||||
m_weights.reset();
|
||||
if (weights != 0) {
|
||||
m_weights.append(sz, weights);
|
||||
}
|
||||
SASSERT(m_weights.empty() == (m_weights.c_ptr() == 0));
|
||||
virtual lbool check_sat(unsigned sz, expr * const * assumptions) {
|
||||
m_solver.pop_to_base_level();
|
||||
dep2asm_t dep2asm;
|
||||
m_model = 0;
|
||||
|
@ -148,10 +139,10 @@ public:
|
|||
r = internalize_assumptions(sz, assumptions, dep2asm);
|
||||
if (r != l_true) return r;
|
||||
|
||||
r = m_solver.check(m_asms.size(), m_asms.c_ptr(), m_weights.c_ptr(), max_weight);
|
||||
r = m_solver.check(m_asms.size(), m_asms.c_ptr());
|
||||
switch (r) {
|
||||
case l_true:
|
||||
if (sz > 0 && !weights) {
|
||||
if (sz > 0) {
|
||||
check_assumptions(dep2asm);
|
||||
}
|
||||
break;
|
||||
|
@ -675,18 +666,6 @@ solver* mk_inc_sat_solver(ast_manager& m, params_ref const& p) {
|
|||
}
|
||||
|
||||
|
||||
lbool inc_sat_check_sat(solver& _s, unsigned sz, expr*const* soft, rational const* _weights, rational const& max_weight) {
|
||||
inc_sat_solver& s = dynamic_cast<inc_sat_solver&>(_s);
|
||||
vector<double> weights;
|
||||
for (unsigned i = 0; _weights && i < sz; ++i) {
|
||||
weights.push_back(_weights[i].get_double());
|
||||
}
|
||||
params_ref p;
|
||||
p.set_bool("minimize_core", false);
|
||||
s.updt_params(p);
|
||||
return s.check_sat(sz, soft, weights.c_ptr(), max_weight.get_double());
|
||||
}
|
||||
|
||||
void inc_sat_display(std::ostream& out, solver& _s, unsigned sz, expr*const* soft, rational const* _weights) {
|
||||
inc_sat_solver& s = dynamic_cast<inc_sat_solver&>(_s);
|
||||
vector<unsigned> weights;
|
||||
|
|
|
@ -24,7 +24,6 @@ Notes:
|
|||
|
||||
solver* mk_inc_sat_solver(ast_manager& m, params_ref const& p);
|
||||
|
||||
lbool inc_sat_check_sat(solver& s, unsigned sz, expr*const* soft, rational const* weights, rational const& max_weight);
|
||||
|
||||
void inc_sat_display(std::ostream& out, solver& s, unsigned sz, expr*const* soft, rational const* _weights);
|
||||
|
||||
|
|
Loading…
Reference in a new issue