mirror of
https://github.com/Z3Prover/z3
synced 2025-08-23 03:27:52 +00:00
model refactor (#4723)
* refactor model fixing Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * missing cond macro Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * file Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * file Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * add macros dependency Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * deps and debug Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * add dependency to normal forms Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * build issues Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * compile Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fix leal regression * complete model fixer Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fold back private functionality to model_finder Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * avoid duplicate fixed callbacks Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
6cc52e04c3
commit
fa58a36b9f
42 changed files with 2060 additions and 1494 deletions
|
@ -57,14 +57,16 @@ namespace sat {
|
|||
protected:
|
||||
bool m_drating { false };
|
||||
int m_id { 0 };
|
||||
symbol m_name;
|
||||
solver* m_solver { nullptr };
|
||||
public:
|
||||
extension(int id): m_id(id) {}
|
||||
extension(symbol const& name, int id): m_id(id), m_name(name) {}
|
||||
virtual ~extension() {}
|
||||
int get_id() const { return m_id; }
|
||||
void set_solver(solver* s) { m_solver = s; }
|
||||
solver& s() { return *m_solver; }
|
||||
solver const& s() const { return *m_solver; }
|
||||
symbol const& name() const { return m_name; }
|
||||
|
||||
virtual void set_lookahead(lookahead* s) {};
|
||||
class scoped_drating {
|
||||
|
|
|
@ -26,6 +26,7 @@ z3_add_component(sat_smt
|
|||
fpa_solver.cpp
|
||||
q_mbi.cpp
|
||||
q_model_finder.cpp
|
||||
q_model_fixer.cpp
|
||||
q_solver.cpp
|
||||
sat_dual_solver.cpp
|
||||
sat_th.cpp
|
||||
|
|
|
@ -75,7 +75,7 @@ For example
|
|||
namespace array {
|
||||
|
||||
solver::solver(euf::solver& ctx, theory_id id) :
|
||||
th_euf_solver(ctx, id),
|
||||
th_euf_solver(ctx, symbol("array"), id),
|
||||
a(m),
|
||||
m_sort2epsilon(m),
|
||||
m_sort2diag(m),
|
||||
|
|
|
@ -1363,7 +1363,7 @@ namespace sat {
|
|||
ba_solver(ctx.get_manager(), ctx.get_si(), id) {}
|
||||
|
||||
ba_solver::ba_solver(ast_manager& m, sat::sat_internalizer& si, euf::theory_id id)
|
||||
: euf::th_solver(m, id),
|
||||
: euf::th_solver(m, symbol("ba"), id),
|
||||
si(si), m_pb(m),
|
||||
m_lookahead(nullptr),
|
||||
m_constraint_id(0), m_ba(*this), m_sort(m_ba) {
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace bv {
|
|||
};
|
||||
|
||||
solver::solver(euf::solver& ctx, theory_id id) :
|
||||
euf::th_euf_solver(ctx, id),
|
||||
euf::th_euf_solver(ctx, symbol("bv"), id),
|
||||
bv(m),
|
||||
m_autil(m),
|
||||
m_ackerman(*this),
|
||||
|
|
|
@ -29,7 +29,7 @@ Author:
|
|||
namespace euf {
|
||||
|
||||
solver::solver(ast_manager& m, sat::sat_internalizer& si, params_ref const& p) :
|
||||
extension(m.mk_family_id("euf")),
|
||||
extension(symbol("euf"), m.mk_family_id("euf")),
|
||||
m(m),
|
||||
si(si),
|
||||
m_egraph(m),
|
||||
|
@ -76,7 +76,7 @@ namespace euf {
|
|||
}
|
||||
|
||||
th_solver* solver::quantifier2solver() {
|
||||
family_id fid = m.mk_family_id(q::solver::name());
|
||||
family_id fid = m.mk_family_id(symbol("quant"));
|
||||
auto* ext = m_id2solver.get(fid, nullptr);
|
||||
if (ext)
|
||||
return ext;
|
||||
|
@ -99,27 +99,18 @@ namespace euf {
|
|||
bv_util bvu(m);
|
||||
array_util au(m);
|
||||
fpa_util fpa(m);
|
||||
if (pb.get_family_id() == fid) {
|
||||
if (pb.get_family_id() == fid)
|
||||
ext = alloc(sat::ba_solver, *this, fid);
|
||||
if (use_drat())
|
||||
s().get_drat().add_theory(fid, symbol("ba"));
|
||||
}
|
||||
else if (bvu.get_family_id() == fid) {
|
||||
else if (bvu.get_family_id() == fid)
|
||||
ext = alloc(bv::solver, *this, fid);
|
||||
if (use_drat())
|
||||
s().get_drat().add_theory(fid, symbol("bv"));
|
||||
}
|
||||
else if (au.get_family_id() == fid) {
|
||||
else if (au.get_family_id() == fid)
|
||||
ext = alloc(array::solver, *this, fid);
|
||||
if (use_drat())
|
||||
s().get_drat().add_theory(fid, symbol("array"));
|
||||
}
|
||||
else if (fpa.get_family_id() == fid) {
|
||||
else if (fpa.get_family_id() == fid)
|
||||
ext = alloc(fpa::solver, *this);
|
||||
if (use_drat())
|
||||
s().get_drat().add_theory(fid, symbol("fpa"));
|
||||
}
|
||||
|
||||
if (ext) {
|
||||
if (use_drat())
|
||||
s().get_drat().add_theory(fid, ext->name());
|
||||
ext->set_solver(m_solver);
|
||||
ext->push_scopes(s().num_scopes());
|
||||
add_solver(fid, ext);
|
||||
|
|
|
@ -23,7 +23,7 @@ Revision History:
|
|||
namespace fpa {
|
||||
|
||||
solver::solver(euf::solver& ctx) :
|
||||
euf::th_euf_solver(ctx, ctx.get_manager().mk_family_id("fpa")),
|
||||
euf::th_euf_solver(ctx, symbol("fpa"), ctx.get_manager().mk_family_id("fpa")),
|
||||
m_th_rw(ctx.get_manager()),
|
||||
m_converter(ctx.get_manager(), m_th_rw),
|
||||
m_rw(ctx.get_manager(), m_converter, params_ref()),
|
||||
|
@ -65,7 +65,7 @@ namespace fpa {
|
|||
m.inc_ref(e);
|
||||
m.inc_ref(res);
|
||||
|
||||
ctx.push(fpa2bv_conversion_trail_elem<euf::solver>(m, m_conversions, e));
|
||||
ctx.push(insert_ref2_map<euf::solver, ast_manager, expr, expr>(m, m_conversions, e, res.get()));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -26,8 +26,13 @@ Author:
|
|||
namespace q {
|
||||
|
||||
mbqi::mbqi(euf::solver& ctx, solver& s):
|
||||
ctx(ctx), qs(s), m(s.get_manager()), m_model_finder(ctx), m_fresh_trail(m) {}
|
||||
|
||||
ctx(ctx),
|
||||
qs(s),
|
||||
m(s.get_manager()),
|
||||
m_model_fixer(ctx, qs),
|
||||
m_model_finder(ctx),
|
||||
m_fresh_trail(m)
|
||||
{}
|
||||
|
||||
void mbqi::restrict_to_universe(expr * sk, ptr_vector<expr> const & universe) {
|
||||
SASSERT(!universe.empty());
|
||||
|
@ -97,7 +102,7 @@ namespace q {
|
|||
if (r == l_false)
|
||||
return l_true;
|
||||
model_ref mdl0, mdl1;
|
||||
m_solver->get_model(mdl0);
|
||||
m_solver->get_model(mdl0);
|
||||
expr_ref proj(m);
|
||||
auto add_projection = [&](model& mdl, bool inv) {
|
||||
proj = project(mdl, q, vars, inv);
|
||||
|
@ -222,4 +227,8 @@ namespace q {
|
|||
m_max_cex = ctx.get_config().m_mbqi_max_cexs;
|
||||
}
|
||||
|
||||
void mbqi::finalize_model(model& mdl) {
|
||||
m_model_fixer(mdl);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ Author:
|
|||
#include "solver/solver.h"
|
||||
#include "sat/smt/sat_th.h"
|
||||
#include "sat/smt/q_model_finder.h"
|
||||
|
||||
#include "sat/smt/q_model_fixer.h"
|
||||
|
||||
namespace euf {
|
||||
class solver;
|
||||
|
@ -33,13 +33,14 @@ namespace q {
|
|||
euf::solver& ctx;
|
||||
solver& qs;
|
||||
ast_manager& m;
|
||||
model_fixer m_model_fixer;
|
||||
model_finder m_model_finder;
|
||||
model_ref m_model;
|
||||
ref<::solver> m_solver;
|
||||
obj_map<sort, obj_hashtable<expr>*> m_fresh;
|
||||
scoped_ptr_vector<obj_hashtable<expr>> m_values;
|
||||
expr_ref_vector m_fresh_trail;
|
||||
unsigned m_max_cex{ 10 };
|
||||
unsigned m_max_cex{ 1 };
|
||||
|
||||
void restrict_to_universe(expr * sk, ptr_vector<expr> const & universe);
|
||||
void register_value(expr* e);
|
||||
|
@ -58,6 +59,8 @@ namespace q {
|
|||
lbool operator()();
|
||||
|
||||
void init_search();
|
||||
|
||||
void finalize_model(model& mdl);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -36,4 +36,8 @@ namespace q {
|
|||
|
||||
}
|
||||
|
||||
void model_finder::adjust_model(model& mdl) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -37,9 +37,23 @@ namespace q {
|
|||
|
||||
model_finder(euf::solver& ctx);
|
||||
|
||||
/**
|
||||
* Compute an instantiation terms for the i'th bound variable in quantifier q.
|
||||
*/
|
||||
expr_ref inv_term(model& mdl, quantifier* q, unsigned idx, expr* value, unsigned& generation);
|
||||
|
||||
/**
|
||||
* Pre-restrict instantiations of vars, by adding constraints to solver s
|
||||
*/
|
||||
void restrict_instantiations(::solver& s, model& mdl, quantifier* q, expr_ref_vector const& vars);
|
||||
|
||||
/**
|
||||
* Update model in order to best satisfy quantifiers.
|
||||
* For the array property fragment, update the model
|
||||
* such that the range of functions behaves monotonically
|
||||
* based on regions over the inputs.
|
||||
*/
|
||||
void adjust_model(model& mdl);
|
||||
|
||||
};
|
||||
|
||||
|
|
198
src/sat/smt/q_model_fixer.cpp
Normal file
198
src/sat/smt/q_model_fixer.cpp
Normal file
|
@ -0,0 +1,198 @@
|
|||
/*++
|
||||
Copyright (c) 2020 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
q_model_fixer.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Model-based quantifier instantiation model-finder plugin
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2020-10-02
|
||||
|
||||
Notes:
|
||||
|
||||
Derives from smt/smt_model_finder.cpp
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
#include "ast/for_each_expr.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
#include "ast/bv_decl_plugin.h"
|
||||
#include "model/model_macro_solver.h"
|
||||
#include "sat/smt/q_model_fixer.h"
|
||||
#include "sat/smt/q_solver.h"
|
||||
#include "sat/smt/euf_solver.h"
|
||||
|
||||
|
||||
namespace q {
|
||||
|
||||
template<typename U>
|
||||
static bool lt(U const& u, expr* x, expr* y) {
|
||||
rational v1, v2;
|
||||
if (u.is_numeral(x, v1) && u.is_numeral(y, v2))
|
||||
return v1 < v2;
|
||||
else
|
||||
return x->get_id() < y->get_id();
|
||||
}
|
||||
|
||||
class arith_projection : public projection_function {
|
||||
ast_manager& m;
|
||||
arith_util a;
|
||||
public:
|
||||
bool operator()(expr* e1, expr* e2) const { return lt(a, e1, e2); }
|
||||
arith_projection(ast_manager& m): m(m), a(m) {}
|
||||
~arith_projection() override {}
|
||||
void sort(ptr_buffer<expr>& values) override { std::sort(values.begin(), values.end(), *this); }
|
||||
expr* mk_lt(expr* x, expr* y) override { return a.mk_lt(x, y); }
|
||||
};
|
||||
|
||||
class ubv_projection : public projection_function {
|
||||
ast_manager& m;
|
||||
bv_util bvu;
|
||||
public:
|
||||
bool operator()(expr* e1, expr* e2) const { return lt(bvu, e1, e2); }
|
||||
ubv_projection(ast_manager& m): m(m), bvu(m) {}
|
||||
~ubv_projection() override {}
|
||||
void sort(ptr_buffer<expr>& values) override { std::sort(values.begin(), values.end(), *this); }
|
||||
expr* mk_lt(expr* x, expr* y) override { return m.mk_not(bvu.mk_ule(y, x)); }
|
||||
};
|
||||
|
||||
model_fixer::model_fixer(euf::solver& ctx, q::solver& qs) :
|
||||
ctx(ctx), m_qs(qs), m(ctx.get_manager()), m_dependencies(m) {}
|
||||
|
||||
void model_fixer::operator()(model& mdl) {
|
||||
ptr_vector<quantifier> univ;
|
||||
for (sat::literal lit : m_qs.universal()) {
|
||||
quantifier* q = to_quantifier(ctx.bool_var2expr(lit.var()));
|
||||
if (ctx.is_relevant(q))
|
||||
univ.push_back(q);
|
||||
}
|
||||
if (univ.empty())
|
||||
return;
|
||||
|
||||
m_dependencies.reset();
|
||||
ptr_vector<quantifier> residue;
|
||||
|
||||
simple_macro_solver sms(m, *this);
|
||||
sms(mdl, univ, residue);
|
||||
|
||||
hint_macro_solver hms(m, *this);
|
||||
hms(mdl, univ, residue);
|
||||
|
||||
non_auf_macro_solver nas(m, *this, m_dependencies);
|
||||
nas.set_mbqi_force_template(ctx.get_config().m_mbqi_force_template);
|
||||
nas(mdl, univ, residue);
|
||||
|
||||
univ.append(residue);
|
||||
add_projection_functions(mdl, univ);
|
||||
}
|
||||
|
||||
quantifier_macro_info* model_fixer::operator()(quantifier* q) {
|
||||
quantifier_macro_info* info = nullptr;
|
||||
if (!m_q2info.find(q, info)) {
|
||||
info = alloc(quantifier_macro_info, m, m_qs.flatten(q));
|
||||
m_q2info.insert(q, info);
|
||||
ctx.push(new_obj_trail<euf::solver, quantifier_macro_info>(info));
|
||||
ctx.push(insert_obj_map<euf::solver, quantifier, quantifier_macro_info*>(m_q2info, q));
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
void model_fixer::add_projection_functions(model& mdl, ptr_vector<quantifier> const& qs) {
|
||||
func_decl_set fns;
|
||||
collect_partial_functions(qs, fns);
|
||||
for (func_decl* f : fns)
|
||||
add_projection_functions(mdl, f);
|
||||
}
|
||||
|
||||
void model_fixer::add_projection_functions(model& mdl, func_decl* f) {
|
||||
// update interpretation of f so that the graph of f is fully determined by the
|
||||
// ground values of its arguments.
|
||||
func_interp* fi = mdl.get_func_interp(f);
|
||||
if (!fi)
|
||||
return;
|
||||
if (fi->is_constant())
|
||||
return;
|
||||
expr_ref_vector args(m);
|
||||
for (unsigned i = 0; i < f->get_arity(); ++i)
|
||||
args.push_back(add_projection_function(mdl, f, i));
|
||||
if (!fi->get_else() && fi->num_entries() > 0)
|
||||
fi->set_else(fi->get_entry(ctx.s().rand()(fi->num_entries()))->get_result());
|
||||
bool has_projection = false;
|
||||
for (expr* arg : args)
|
||||
has_projection |= !is_var(arg);
|
||||
if (!has_projection)
|
||||
return;
|
||||
func_interp* new_fi = alloc(func_interp, m, f->get_arity());
|
||||
func_decl* f_new = m.mk_fresh_func_decl(f->get_name(), symbol("aux"), f->get_arity(), f->get_domain(), f->get_range());
|
||||
new_fi->set_else(m.mk_app(f_new, args));
|
||||
mdl.update_func_interp(f, new_fi);
|
||||
mdl.register_decl(f_new, fi);
|
||||
}
|
||||
|
||||
expr_ref model_fixer::add_projection_function(model& mdl, func_decl* f, unsigned idx) {
|
||||
sort* srt = f->get_domain(idx);
|
||||
projection_function* proj = get_projection(srt);
|
||||
if (!proj)
|
||||
return expr_ref(m.mk_var(idx, srt), m);
|
||||
ptr_buffer<expr> values;
|
||||
for (euf::enode* n : ctx.get_egraph().enodes_of(f))
|
||||
values.push_back(mdl(n->get_arg(idx)->get_expr()));
|
||||
if (values.empty())
|
||||
return expr_ref(m.mk_var(idx, srt), m);
|
||||
proj->sort(values);
|
||||
unsigned j = 0;
|
||||
for (unsigned i = 0; i < values.size(); ++i)
|
||||
if (i == 0 || values[i-1] != values[i])
|
||||
values[j++] = values[i];
|
||||
values.shrink(j);
|
||||
|
||||
unsigned sz = values.size();
|
||||
expr_ref var(m.mk_var(0, srt), m);
|
||||
expr_ref pi(values.get(sz-1), m);
|
||||
for (unsigned i = sz - 1; i >= 1; i--) {
|
||||
expr* c = proj->mk_lt(var, values[i]);
|
||||
pi = m.mk_ite(c, values[i - 1], pi);
|
||||
}
|
||||
func_interp* rpi = alloc(func_interp, m, 1);
|
||||
rpi->set_else(pi);
|
||||
func_decl * p = m.mk_fresh_func_decl(1, &srt, srt);
|
||||
mdl.register_decl(p, rpi);
|
||||
return expr_ref(m.mk_app(p, m.mk_var(idx, srt)), m);
|
||||
}
|
||||
|
||||
projection_function* model_fixer::get_projection(sort* srt) {
|
||||
projection_function* proj = nullptr;
|
||||
if (m_projections.find(srt, proj))
|
||||
return proj;
|
||||
arith_util autil(m);
|
||||
bv_util butil(m);
|
||||
if (autil.is_real(srt) || autil.is_int(srt))
|
||||
proj = alloc(arith_projection, m);
|
||||
else if (butil.is_bv_sort(srt))
|
||||
proj = alloc(ubv_projection, m);
|
||||
// TBD: sbv_projection? FP, ADT projection?
|
||||
if (!proj)
|
||||
return nullptr;
|
||||
m_projections.insert(srt, proj);
|
||||
ctx.push(new_obj_trail<euf::solver, projection_function>(proj));
|
||||
ctx.push(insert_obj_map<euf::solver, sort, projection_function*>(m_projections, srt));
|
||||
return proj;
|
||||
}
|
||||
|
||||
void model_fixer::collect_partial_functions(ptr_vector<quantifier> const& qs, func_decl_set& fns) {
|
||||
for (quantifier* q : qs) {
|
||||
auto* info = (*this)(q);
|
||||
quantifier* flat_q = info->get_flat_q();
|
||||
expr_ref body(flat_q->get_expr(), m);
|
||||
for (expr* t : subterms(body))
|
||||
if (is_uninterp(t) && !to_app(t)->is_ground())
|
||||
fns.insert(to_app(t)->get_decl());
|
||||
}
|
||||
}
|
||||
}
|
78
src/sat/smt/q_model_fixer.h
Normal file
78
src/sat/smt/q_model_fixer.h
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*++
|
||||
Copyright (c) 2020 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
q_model_fixer.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Model-based quantifier instantiation model-finder plugin
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2020-10-02
|
||||
|
||||
Notes:
|
||||
|
||||
Derives from smt/smt_model_finder.cpp
|
||||
|
||||
Contains exclusively functionality that adjusts a model to make it
|
||||
easier to satisfy relevant universally quantified literals.
|
||||
|
||||
--*/
|
||||
#pragma once
|
||||
|
||||
#include "sat/smt/sat_th.h"
|
||||
#include "solver/solver.h"
|
||||
#include "model/model_macro_solver.h"
|
||||
|
||||
namespace euf {
|
||||
class solver;
|
||||
}
|
||||
|
||||
namespace q {
|
||||
|
||||
class solver;
|
||||
|
||||
typedef obj_hashtable<func_decl> func_decl_set;
|
||||
|
||||
class projection_function {
|
||||
public:
|
||||
virtual ~projection_function() {}
|
||||
virtual void sort(ptr_buffer<expr>& values) = 0;
|
||||
virtual expr* mk_lt(expr* a, expr* b) = 0;
|
||||
};
|
||||
|
||||
class model_fixer : public quantifier2macro_infos {
|
||||
euf::solver& ctx;
|
||||
solver& m_qs;
|
||||
ast_manager& m;
|
||||
obj_map<quantifier, quantifier_macro_info*> m_q2info;
|
||||
func_decl_dependencies m_dependencies;
|
||||
obj_map<sort, projection_function*> m_projections;
|
||||
|
||||
void add_projection_functions(model& mdl, ptr_vector<quantifier> const& qs);
|
||||
void add_projection_functions(model& mdl, func_decl* f);
|
||||
expr_ref add_projection_function(model& mdl, func_decl* f, unsigned idx);
|
||||
void collect_partial_functions(ptr_vector<quantifier> const& qs, func_decl_set& fns);
|
||||
projection_function* get_projection(sort* srt);
|
||||
|
||||
public:
|
||||
|
||||
model_fixer(euf::solver& ctx, solver& qs);
|
||||
~model_fixer() override {}
|
||||
|
||||
/**
|
||||
* Update model in order to best satisfy quantifiers.
|
||||
* For the array property fragment, update the model
|
||||
* such that the range of functions behaves monotonically
|
||||
* based on regions over the inputs.
|
||||
*/
|
||||
void operator()(model& mdl);
|
||||
|
||||
quantifier_macro_info* operator()(quantifier* q);
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -19,13 +19,14 @@ Author:
|
|||
#include "sat/smt/q_solver.h"
|
||||
#include "sat/smt/euf_solver.h"
|
||||
#include "sat/smt/sat_th.h"
|
||||
|
||||
#include "ast/normal_forms/pull_quant.h"
|
||||
#include "ast/well_sorted.h"
|
||||
|
||||
namespace q {
|
||||
|
||||
solver::solver(euf::solver& ctx):
|
||||
th_euf_solver(ctx, ctx.get_manager().get_family_id(name())),
|
||||
m_mbqi(ctx, *this)
|
||||
th_euf_solver(ctx, symbol("quant"), ctx.get_manager().get_family_id(symbol("quant"))),
|
||||
m_mbqi(ctx, *this)
|
||||
{}
|
||||
|
||||
void solver::asserted(sat::literal l) {
|
||||
|
@ -43,10 +44,12 @@ namespace q {
|
|||
}
|
||||
|
||||
sat::check_result solver::check() {
|
||||
switch (m_mbqi()) {
|
||||
case l_true: return sat::check_result::CR_DONE;
|
||||
case l_false: return sat::check_result::CR_CONTINUE;
|
||||
case l_undef: return sat::check_result::CR_GIVEUP;
|
||||
if (ctx.get_config().m_mbqi) {
|
||||
switch (m_mbqi()) {
|
||||
case l_true: return sat::check_result::CR_DONE;
|
||||
case l_false: return sat::check_result::CR_CONTINUE;
|
||||
case l_undef: return sat::check_result::CR_GIVEUP;
|
||||
}
|
||||
}
|
||||
return sat::check_result::CR_GIVEUP;
|
||||
}
|
||||
|
@ -117,4 +120,27 @@ namespace q {
|
|||
mk_var(ctx.get_egraph().find(e));
|
||||
return lit;
|
||||
}
|
||||
|
||||
void solver::finalize_model(model& mdl) {
|
||||
m_mbqi.finalize_model(mdl);
|
||||
}
|
||||
|
||||
quantifier* solver::flatten(quantifier* q) {
|
||||
quantifier* q_flat = nullptr;
|
||||
if (!has_quantifiers(q->get_expr()))
|
||||
return q;
|
||||
if (m_flat.find(q, q_flat))
|
||||
return q_flat;
|
||||
proof_ref pr(m);
|
||||
expr_ref new_q(m);
|
||||
pull_quant pull(m);
|
||||
pull(q, new_q, pr);
|
||||
SASSERT(is_well_sorted(m, new_q));
|
||||
q_flat = to_quantifier(new_q);
|
||||
m.inc_ref(q_flat);
|
||||
m.inc_ref(q);
|
||||
m_flat.insert(q, q_flat);
|
||||
ctx.push(insert_ref2_map<euf::solver, ast_manager, quantifier, quantifier>(m, m_flat, q, q_flat));
|
||||
return q_flat;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ namespace q {
|
|||
class solver : public euf::th_euf_solver {
|
||||
|
||||
typedef obj_map<quantifier, sat::literal> skolem_table;
|
||||
typedef obj_map<quantifier, quantifier*> flat_table;
|
||||
friend class mbqi;
|
||||
|
||||
struct stats {
|
||||
|
@ -42,6 +43,7 @@ namespace q {
|
|||
mbqi m_mbqi;
|
||||
|
||||
skolem_table m_skolems;
|
||||
flat_table m_flat;
|
||||
sat::literal_vector m_universal;
|
||||
|
||||
sat::literal skolemize(quantifier* q);
|
||||
|
@ -51,7 +53,6 @@ namespace q {
|
|||
|
||||
solver(euf::solver& ctx);
|
||||
~solver() override {}
|
||||
static char const* name() { return "quant"; }
|
||||
bool is_external(sat::bool_var v) override { return false; }
|
||||
void get_antecedents(sat::literal l, sat::ext_justification_idx idx, sat::literal_vector& r, bool probing) override {}
|
||||
void asserted(sat::literal l) override;
|
||||
|
@ -67,7 +68,10 @@ namespace q {
|
|||
void internalize(expr* e, bool redundant) override { UNREACHABLE(); }
|
||||
euf::theory_var mk_var(euf::enode* n) override;
|
||||
void init_search() override;
|
||||
void finalize_model(model& mdl) override;
|
||||
|
||||
ast_manager& get_manager() { return m; }
|
||||
sat::literal_vector const& universal() const { return m_universal; }
|
||||
quantifier* flatten(quantifier* q);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -52,8 +52,8 @@ namespace euf {
|
|||
return true;
|
||||
}
|
||||
|
||||
th_euf_solver::th_euf_solver(euf::solver& ctx, euf::theory_id id):
|
||||
th_solver(ctx.get_manager(), id),
|
||||
th_euf_solver::th_euf_solver(euf::solver& ctx, symbol const& name, euf::theory_id id):
|
||||
th_solver(ctx.get_manager(), name, id),
|
||||
ctx(ctx)
|
||||
{}
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ namespace euf {
|
|||
protected:
|
||||
ast_manager & m;
|
||||
public:
|
||||
th_solver(ast_manager& m, euf::theory_id id): extension(id), m(m) {}
|
||||
th_solver(ast_manager& m, symbol const& name, euf::theory_id id): extension(name, id), m(m) {}
|
||||
|
||||
virtual th_solver* clone(sat::solver* s, euf::solver& ctx) = 0;
|
||||
|
||||
|
@ -158,7 +158,7 @@ namespace euf {
|
|||
}
|
||||
|
||||
public:
|
||||
th_euf_solver(euf::solver& ctx, euf::theory_id id);
|
||||
th_euf_solver(euf::solver& ctx, symbol const& name, euf::theory_id id);
|
||||
virtual ~th_euf_solver() {}
|
||||
virtual theory_var mk_var(enode * n);
|
||||
unsigned get_num_vars() const { return m_var2enode.size();}
|
||||
|
|
|
@ -21,7 +21,7 @@ Author:
|
|||
namespace user {
|
||||
|
||||
solver::solver(euf::solver& ctx) :
|
||||
th_euf_solver(ctx, ctx.get_manager().mk_family_id("user"))
|
||||
th_euf_solver(ctx, symbol("user"), ctx.get_manager().mk_family_id("user"))
|
||||
{}
|
||||
|
||||
solver::~solver() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue