3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-12-04 19:16:46 +00:00

remove auxiliary assumptions

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2022-01-07 11:25:04 -08:00
parent 0b234bb6e3
commit 7b9fcbc96a
5 changed files with 86 additions and 42 deletions

View file

@ -196,6 +196,7 @@ namespace {
m_context.pop(n);
}
lbool check_sat_core2(unsigned num_assumptions, expr * const * assumptions) override {
TRACE("solver_na2as", tout << "smt_solver::check_sat_core: " << num_assumptions << "\n";);
return m_context.check(num_assumptions, assumptions);
@ -275,6 +276,7 @@ namespace {
if (use_smtmus) {
smtmus mus(*this);
mus.add_soft(r.size(), r.data());
mus.set_assumptions(m_last_assumptions);
expr_ref_vector r2(m);
if (l_true == mus.get_mus(r2)) {
r.reset();

View file

@ -125,6 +125,7 @@ struct smtmus::imp {
obj_map<func_decl, unsigned_vector> m_soft_occurs; // map from variables to soft clause occurrences
obj_map<func_decl, unsigned_vector> m_hard_occurs; // map from variables to hard clause occurrences
obj_map<expr, ineq*> m_lit2ineq; // map from literals to inequality abstraction
expr_ref_vector m_assumptions; // set of assumptions used.
unsigned m_rotated = 0;
unsigned p_max_cores = 30;
@ -134,7 +135,7 @@ struct smtmus::imp {
bool p_use_reset = false;
imp(solver& s) :
m_solver(s), m_main_solver(&s), m(s.get_manager()), a(m), m_soft(m), m_hard(m)
m_solver(s), m_main_solver(&s), m(s.get_manager()), a(m), m_soft(m), m_hard(m), m_assumptions(m)
{}
~imp() {
@ -145,23 +146,16 @@ struct smtmus::imp {
m_soft.push_back(lit);
}
void init_soft_clauses() {
void set_assumptions(expr_ref_vector const& assumptions) {
m_assumptions.reset();
m_assumptions.append(assumptions);
}
void init_softs(expr_ref_vector const& soft, obj_map<expr, unsigned>& softs) {
obj_hashtable<expr> dups;
obj_map<expr, unsigned> soft2hard;
obj_map<expr, unsigned> softs;
u_map<expr*> hard2soft;
unsigned idx = 0;
// initialize hard clauses
m_hard.reset();
m_hard.append(m_solver.get_assertions());
// initialize soft clauses.
m_soft_clauses.reset();
for (expr* s : m_soft)
m_soft_clauses.push_back(expr_ref_vector(m, 1, &s));
// collect indicator variable candidates
for (expr* s : m_soft) {
unsigned idx = 0;
for (expr* s : soft) {
if (is_uninterp_const(s)) {
if (softs.contains(s))
dups.insert(s);
@ -172,11 +166,11 @@ struct smtmus::imp {
}
for (auto* s : dups)
softs.remove(s);
if (softs.empty())
return;
}
void init_soft2hard(obj_map<expr, unsigned>& soft2hard, u_map<expr*>& hard2soft, obj_map<expr, unsigned>const & softs) {
// find all clauses where soft indicators are used.
idx = 0;
unsigned idx = 0;
for (expr* f : m_hard) {
expr_ref_vector ors(m);
flatten_or(f, ors);
@ -190,7 +184,6 @@ struct smtmus::imp {
}
++idx;
}
// remove hard2soft associations if soft clauses don't occur uniquely.
idx = 0;
unsigned_vector to_remove;
@ -206,6 +199,32 @@ struct smtmus::imp {
}
for (auto i : to_remove)
hard2soft.remove(i);
}
void simplify_hard(u_map<expr*> const& hard2soft) {
for (auto const& [i, s] : hard2soft)
m_hard[i] = m.mk_true();
}
void init_soft_clauses() {
obj_map<expr, unsigned> soft2hard;
obj_map<expr, unsigned> softs;
u_map<expr*> hard2soft;
unsigned idx = 0;
// initialize hard clauses
m_hard.reset();
m_hard.append(m_solver.get_assertions());
// initialize soft clauses.
m_soft_clauses.reset();
for (expr* s : m_soft)
m_soft_clauses.push_back(expr_ref_vector(m, 1, &s));
init_softs(m_soft, softs);
if (softs.empty())
return;
init_soft2hard(soft2hard, hard2soft, softs);
//
// update soft clauses using hard clauses.
@ -231,16 +250,27 @@ struct smtmus::imp {
++idx;
}
SASSERT(idx <= ors.size());
m_hard[i] = m.mk_true();
}
simplify_hard(hard2soft);
softs.reset();
hard2soft.reset();
init_softs(m_assumptions, softs);
if (!softs.empty()) {
init_soft2hard(soft2hard, hard2soft, softs);
simplify_hard(hard2soft);
}
TRACE("satmus",
for (expr* s : m_soft)
tout << "soft " << mk_pp(s, m) << "\n";
for (auto const& clause : m_soft_clauses)
tout << "clause " << clause << "\n";
for (expr* h : m_hard)
tout << "hard " << mk_pp(h, m) << "\n";);
for (expr* s : m_soft)
tout << "soft " << mk_pp(s, m) << "\n";
for (auto const& clause : m_soft_clauses)
tout << "clause " << clause << "\n";
for (expr* h : m_hard)
tout << "hard " << mk_pp(h, m) << "\n";
for (expr* a : m_assumptions)
tout << "assumption " << mk_pp(a, m) << "\n";
);
}
void init_occurs(unsigned idx, func_decl* v, obj_map<func_decl, unsigned_vector>& occurs) {
@ -287,12 +317,16 @@ struct smtmus::imp {
return init_lit2ineq(lit);
}
ineq* init_lit2ineq(expr* lit) {
ineq* init_lit2ineq(expr* _lit) {
expr* lit = _lit;
bool is_not = m.is_not(lit, lit);
expr* x, * y;
auto mul = [&](rational const& coeff, expr* t) -> expr* {
rational coeff2;
if (coeff == 1)
return t;
else if (a.is_numeral(t, coeff2))
return a.mk_numeral(coeff*coeff2, t->get_sort());
return a.mk_mul(a.mk_numeral(coeff, a.is_int(t)), t);
};
if (a.is_le(lit, x, y) || a.is_lt(lit, x, y) || a.is_ge(lit, y, x) || a.is_gt(lit, y, x)) {
@ -342,12 +376,12 @@ struct smtmus::imp {
e->m_base = a.mk_numeral(rational::zero(), a.is_int(x));
else
e->m_base = a.mk_add(basis);
m_lit2ineq.insert(lit, e);
m_lit2ineq.insert(_lit, e);
return e;
}
else {
// literals that don't correspond to inequalities are associated with null.
m_lit2ineq.insert(lit, nullptr);
m_lit2ineq.insert(_lit, nullptr);
return nullptr;
}
}
@ -735,3 +769,6 @@ lbool smtmus::get_mus(expr_ref_vector& mus) {
return m_imp->get_mus(mus);
}
void smtmus::set_assumptions(expr_ref_vector const& assumptions) {
m_imp->set_assumptions(assumptions);
}

View file

@ -35,6 +35,8 @@ class smtmus {
add_soft(clss[i]);
}
void set_assumptions(expr_ref_vector const& assumptions);
/**
Retrieve mus over soft constraints
*/

View file

@ -25,7 +25,8 @@ Notes:
solver_na2as::solver_na2as(ast_manager & m):
m(m),
m_assumptions(m) {
m_assumptions(m),
m_last_assumptions(m) {
}
solver_na2as::~solver_na2as() {}
@ -45,36 +46,37 @@ void solver_na2as::assert_expr_core2(expr * t, expr * a) {
}
}
struct append_assumptions {
expr_ref_vector & m_assumptions;
struct solver_na2as::append_assumptions {
solver_na2as& s;
unsigned m_old_sz;
append_assumptions(expr_ref_vector & _m_assumptions,
append_assumptions(solver_na2as& s,
unsigned num_assumptions,
expr * const * assumptions):
m_assumptions(_m_assumptions) {
m_old_sz = m_assumptions.size();
m_assumptions.append(num_assumptions, assumptions);
s(s), m_old_sz(s.m_assumptions.size()) {
s.m_assumptions.append(num_assumptions, assumptions);
s.m_last_assumptions.reset();
s.m_last_assumptions.append(s.m_assumptions);
}
~append_assumptions() {
m_assumptions.shrink(m_old_sz);
s.m_assumptions.shrink(m_old_sz);
}
};
lbool solver_na2as::check_sat_core(unsigned num_assumptions, expr * const * assumptions) {
append_assumptions app(m_assumptions, num_assumptions, assumptions);
append_assumptions app(*this, num_assumptions, assumptions);
TRACE("solver_na2as", display(tout););
return check_sat_core2(m_assumptions.size(), m_assumptions.data());
}
lbool solver_na2as::check_sat_cc(const expr_ref_vector &assumptions, vector<expr_ref_vector> const &clauses) {
if (clauses.empty()) return check_sat(assumptions.size(), assumptions.data());
append_assumptions app(m_assumptions, assumptions.size(), assumptions.data());
append_assumptions app(*this, assumptions.size(), assumptions.data());
return check_sat_cc_core(m_assumptions, clauses);
}
lbool solver_na2as::get_consequences(expr_ref_vector const& asms, expr_ref_vector const& vars, expr_ref_vector& consequences) {
append_assumptions app(m_assumptions, asms.size(), asms.data());
append_assumptions app(*this, asms.size(), asms.data());
return get_consequences_core(m_assumptions, vars, consequences);
}

View file

@ -26,9 +26,10 @@ Notes:
class solver_na2as : public solver {
protected:
ast_manager & m;
expr_ref_vector m_assumptions;
expr_ref_vector m_assumptions, m_last_assumptions;
unsigned_vector m_scopes;
void restore_assumptions(unsigned old_sz);
struct append_assumptions;
public:
solver_na2as(ast_manager & m);
~solver_na2as() override;