mirror of
https://github.com/Z3Prover/z3
synced 2025-06-03 04:41:21 +00:00
fix build
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
fc3a642876
commit
d1dab327cd
3 changed files with 119 additions and 82 deletions
|
@ -75,32 +75,32 @@ namespace q {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
void mbqi::restrict_to_universe(expr* sk, ptr_vector<expr> const& universe) {
|
void mbqi::restrict_to_universe(expr* sk, ptr_vector<expr> const& universe) {
|
||||||
SASSERT(!universe.empty());
|
SASSERT(!universe.empty());
|
||||||
expr_ref_vector eqs(m);
|
expr_ref_vector eqs(m);
|
||||||
|
euf::enode* n = nullptr;
|
||||||
unsigned generation_min = UINT_MAX;
|
unsigned generation_min = UINT_MAX;
|
||||||
for (expr* e : universe) {
|
for (expr* e : universe) {
|
||||||
euf::enode* n = nullptr;
|
|
||||||
if (ctx.values2root().find(e, n)) {
|
if (ctx.values2root().find(e, n)) {
|
||||||
unsigned g = n->class_generation();
|
unsigned g = n->class_generation();
|
||||||
|
generation_min = std::min(generation_min, g);
|
||||||
|
m_generation_max = std::max(m_generation_max, g);
|
||||||
if (g > m_generation_bound) {
|
if (g > m_generation_bound) {
|
||||||
std::cout << "SKIP\n";
|
std::cout << "SKIP\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#if 1
|
|
||||||
if (g < generation_min) {
|
|
||||||
std::cout << "RESET\n";
|
|
||||||
eqs.reset();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
m_generation_max = std::max(m_generation_max, g);
|
|
||||||
generation_min = std::min(generation_min, g);
|
|
||||||
|
|
||||||
eqs.push_back(m.mk_eq(sk, e));
|
|
||||||
std::cout << mk_pp(e, m) << ": " << ctx.bpp(n) << " gen: " << n->generation() << " " << n->class_generation() << " class-size: " << n->get_root()->class_size() << "\n";
|
std::cout << mk_pp(e, m) << ": " << ctx.bpp(n) << " gen: " << n->generation() << " " << n->class_generation() << " class-size: " << n->get_root()->class_size() << "\n";
|
||||||
}
|
}
|
||||||
else
|
eqs.push_back(m.mk_eq(sk, e));
|
||||||
eqs.push_back(m.mk_eq(sk, e));
|
}
|
||||||
|
if (eqs.empty()) {
|
||||||
|
for (expr* e : universe)
|
||||||
|
if (ctx.values2root().find(e, n) && n->class_generation() <= generation_min)
|
||||||
|
eqs.push_back(m.mk_eq(sk, e));
|
||||||
}
|
}
|
||||||
m_solver->assert_expr(mk_or(eqs));
|
m_solver->assert_expr(mk_or(eqs));
|
||||||
}
|
}
|
||||||
|
@ -134,12 +134,16 @@ namespace q {
|
||||||
if (count > m_max_choose_candidates)
|
if (count > m_max_choose_candidates)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
std::cout << "choose " << r->class_size() << " " << expr_ref(r->get_expr(), m) << "\n";
|
||||||
return expr_ref(r->get_expr(), m);
|
return expr_ref(r->get_expr(), m);
|
||||||
}
|
}
|
||||||
|
|
||||||
lbool mbqi::check_forall(quantifier* q) {
|
lbool mbqi::check_forall(quantifier* q) {
|
||||||
quantifier* q_flat = m_qs.flatten(q);
|
quantifier* q_flat = m_qs.flatten(q);
|
||||||
init_solver();
|
init_solver();
|
||||||
|
|
||||||
|
m_generation_bound = 1;
|
||||||
|
m_generation_max = 0;
|
||||||
::solver::scoped_push _sp(*m_solver);
|
::solver::scoped_push _sp(*m_solver);
|
||||||
std::cout << mk_pp(q, m, 4) << "\n";
|
std::cout << mk_pp(q, m, 4) << "\n";
|
||||||
auto* qb = specialize(q_flat);
|
auto* qb = specialize(q_flat);
|
||||||
|
@ -147,6 +151,12 @@ namespace q {
|
||||||
return l_undef;
|
return l_undef;
|
||||||
if (m.is_false(qb->mbody))
|
if (m.is_false(qb->mbody))
|
||||||
return l_true;
|
return l_true;
|
||||||
|
|
||||||
|
if (!qb->free_vars.empty())
|
||||||
|
quick_check(q, *qb);
|
||||||
|
|
||||||
|
add_universe_restriction(q, *qb);
|
||||||
|
std::cout << "gen-max: " << m_generation_max << "\n";
|
||||||
#if 0
|
#if 0
|
||||||
if (quick_check(q, *qb)) {
|
if (quick_check(q, *qb)) {
|
||||||
|
|
||||||
|
@ -159,38 +169,48 @@ namespace q {
|
||||||
return r;
|
return r;
|
||||||
if (r == l_false)
|
if (r == l_false)
|
||||||
return l_true;
|
return l_true;
|
||||||
model_ref mdl0, mdl1;
|
model_ref mdl;
|
||||||
expr_ref proj(m);
|
expr_ref proj(m);
|
||||||
m_solver->get_model(mdl0);
|
m_solver->get_model(mdl);
|
||||||
unsigned i = 0;
|
if (check_forall_subst(q, *qb, *mdl))
|
||||||
|
return l_false;
|
||||||
|
else
|
||||||
|
return check_forall_default(q, *qb, *mdl);
|
||||||
|
}
|
||||||
|
|
||||||
|
lbool mbqi::check_forall_default(quantifier* q, q_body& qb, model& mdl) {
|
||||||
expr_ref_vector eqs(m);
|
expr_ref_vector eqs(m);
|
||||||
if (!qb->var_args.empty()) {
|
add_domain_bounds(mdl, qb);
|
||||||
::solver::scoped_push _sp(*m_solver);
|
auto proj = solver_project(mdl, qb, eqs, false);
|
||||||
add_domain_eqs(*mdl0, *qb);
|
if (!proj)
|
||||||
for (; i < m_max_cex && l_true == m_solver->check_sat(0, nullptr); ++i) {
|
return l_undef;
|
||||||
m_solver->get_model(mdl1);
|
std::cout << "project-base\n" << proj << "\n";
|
||||||
proj = solver_project(*mdl1, *qb, eqs, true);
|
add_instantiation(q, proj);
|
||||||
if (!proj)
|
|
||||||
break;
|
|
||||||
std::cout << "project\n" << proj << "\n";
|
|
||||||
std::cout << "eqs: " << eqs << "\n";
|
|
||||||
add_instantiation(q, proj);
|
|
||||||
m_solver->assert_expr(m.mk_not(mk_and(eqs)));
|
|
||||||
std::cout << "solve again " << i << "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i == 0) {
|
|
||||||
add_domain_bounds(*mdl0, *qb);
|
|
||||||
proj = solver_project(*mdl0, *qb, eqs, false);
|
|
||||||
if (!proj)
|
|
||||||
return l_undef;
|
|
||||||
std::cout << "project-base\n" << proj << "\n";
|
|
||||||
add_instantiation(q, proj);
|
|
||||||
}
|
|
||||||
// TODO: add as top-level clause for relevancy
|
|
||||||
return l_false;
|
return l_false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool mbqi::check_forall_subst(quantifier* q, q_body& qb, model& mdl0) {
|
||||||
|
if (qb.var_args.empty())
|
||||||
|
return false;
|
||||||
|
model_ref mdl1;
|
||||||
|
expr_ref_vector eqs(m);
|
||||||
|
unsigned i = 0;
|
||||||
|
::solver::scoped_push _sp(*m_solver);
|
||||||
|
add_domain_eqs(mdl0, qb);
|
||||||
|
for (; i < m_max_cex && l_true == m_solver->check_sat(0, nullptr); ++i) {
|
||||||
|
m_solver->get_model(mdl1);
|
||||||
|
auto proj = solver_project(*mdl1, qb, eqs, true);
|
||||||
|
if (!proj)
|
||||||
|
break;
|
||||||
|
std::cout << "project\n" << proj << "\n";
|
||||||
|
std::cout << "eqs: " << eqs << "\n";
|
||||||
|
add_instantiation(q, proj);
|
||||||
|
m_solver->assert_expr(m.mk_not(mk_and(eqs)));
|
||||||
|
std::cout << "solve again " << i << "\n";
|
||||||
|
}
|
||||||
|
return i > 0;
|
||||||
|
}
|
||||||
|
|
||||||
void mbqi::add_instantiation(quantifier* q, expr_ref& proj) {
|
void mbqi::add_instantiation(quantifier* q, expr_ref& proj) {
|
||||||
sat::literal qlit = ctx.expr2literal(q);
|
sat::literal qlit = ctx.expr2literal(q);
|
||||||
if (is_exists(q))
|
if (is_exists(q))
|
||||||
|
@ -201,6 +221,15 @@ namespace q {
|
||||||
m_instantiations.push_back(instantiation_t(qlit, proj, generation));
|
m_instantiations.push_back(instantiation_t(qlit, proj, generation));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mbqi::add_universe_restriction(quantifier* q, q_body& qb) {
|
||||||
|
unsigned sz = q->get_num_decls();
|
||||||
|
for (unsigned i = 0; i < sz; ++i) {
|
||||||
|
sort* s = q->get_decl_sort(i);
|
||||||
|
if (m_model->has_uninterpreted_sort(s))
|
||||||
|
restrict_to_universe(qb.vars.get(i), m_model->get_universe(s));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mbqi::q_body* mbqi::specialize(quantifier* q) {
|
mbqi::q_body* mbqi::specialize(quantifier* q) {
|
||||||
var_subst subst(m);
|
var_subst subst(m);
|
||||||
q_body* result = q2body(q);
|
q_body* result = q2body(q);
|
||||||
|
@ -208,12 +237,6 @@ namespace q {
|
||||||
if (!m_model->eval_expr(q->get_expr(), mbody, true))
|
if (!m_model->eval_expr(q->get_expr(), mbody, true))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
unsigned sz = q->get_num_decls();
|
|
||||||
for (unsigned i = 0; i < sz; ++i) {
|
|
||||||
sort* s = q->get_decl_sort(i);
|
|
||||||
if (m_model->has_uninterpreted_sort(s))
|
|
||||||
restrict_to_universe(result->vars.get(i), m_model->get_universe(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
mbody = subst(mbody, result->vars);
|
mbody = subst(mbody, result->vars);
|
||||||
if (is_forall(q))
|
if (is_forall(q))
|
||||||
|
@ -452,7 +475,8 @@ namespace q {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mbqi::quick_check(quantifier* q, q_body& qb) {
|
bool mbqi::quick_check(quantifier* q, q_body& qb) {
|
||||||
unsigned max_rounds = 10;
|
std::cout << "QUICK-CHECK\n";
|
||||||
|
unsigned max_rounds = 100;
|
||||||
unsigned_vector offsets;
|
unsigned_vector offsets;
|
||||||
if (!first_offset(offsets, qb.vars))
|
if (!first_offset(offsets, qb.vars))
|
||||||
return false;
|
return false;
|
||||||
|
@ -460,70 +484,78 @@ namespace q {
|
||||||
unsigned bindings = 0;
|
unsigned bindings = 0;
|
||||||
expr_ref_vector binding(m);
|
expr_ref_vector binding(m);
|
||||||
for (unsigned i = 0; i < max_rounds && bindings < m_max_cex; ++i) {
|
for (unsigned i = 0; i < max_rounds && bindings < m_max_cex; ++i) {
|
||||||
if (!next_binding(offsets, qb.vars, binding))
|
set_binding(offsets, qb.vars, binding);
|
||||||
break;
|
std::cout << "binding " << binding << "\n";
|
||||||
if (m_model->is_true(qb.vbody)) {
|
if (m_model->is_true(qb.vbody)) {
|
||||||
expr_ref body(q->get_expr(), m);
|
expr_ref body(q->get_expr(), m);
|
||||||
body = subst(q->get_expr(), binding);
|
body = subst(q->get_expr(), binding);
|
||||||
if (is_forall(q))
|
if (is_forall(q))
|
||||||
body = ::mk_not(m, body);
|
body = ::mk_not(m, body);
|
||||||
sat::literal qlit = ctx.expr2literal(q);
|
|
||||||
std::cout << "instantiate " << mk_pp(q, m) << "\n";
|
std::cout << "instantiate " << mk_pp(q, m) << "\n";
|
||||||
std::cout << "binding:\n" << binding << "\n";
|
std::cout << "binding:\n" << binding << "\n";
|
||||||
std::cout << "body:\n" << body << "\n";
|
std::cout << "body:\n" << body << "\n";
|
||||||
add_instantiation(q, body);
|
add_instantiation(q, body);
|
||||||
++bindings;
|
++bindings;
|
||||||
}
|
}
|
||||||
|
if (!next_offset(offsets, qb.vars))
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return bindings > 0;
|
return bindings > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mbqi::first_offset(unsigned_vector& offsets, app_ref_vector const& vars) {
|
bool mbqi::next_offset(unsigned_vector& offsets, app_ref_vector const& vars, unsigned index, unsigned start) {
|
||||||
offsets.reset();
|
auto* v = vars[index];
|
||||||
unsigned index = 0;
|
sort* srt = m.get_sort(v);
|
||||||
auto const& nodes = ctx.get_egraph().nodes();
|
auto const& nodes = ctx.get_egraph().nodes();
|
||||||
unsigned sz = nodes.size();
|
unsigned sz = nodes.size();
|
||||||
|
for (unsigned i = start; i < sz; ++i) {
|
||||||
|
expr* e = nodes[i]->get_expr();
|
||||||
|
if (m.get_sort(e) == srt && !m.is_value(e)) {
|
||||||
|
offsets[index] = i;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mbqi::first_offset(unsigned_vector& offsets, app_ref_vector const& vars) {
|
||||||
|
offsets.reset();
|
||||||
for (app* v : vars)
|
for (app* v : vars)
|
||||||
offsets.push_back(0);
|
offsets.push_back(0);
|
||||||
for (auto* v : vars) {
|
for (unsigned i = 0; i < vars.size(); ++i)
|
||||||
sort* srt = m.get_sort(v);
|
if (!next_offset(offsets, vars, i, 0))
|
||||||
bool found = false;
|
|
||||||
unsigned i = offsets[index];
|
|
||||||
for (; i < sz; ++i) {
|
|
||||||
expr* e = nodes[i]->get_expr();
|
|
||||||
if (m.get_sort(e) == srt && !m.is_value(e)) {
|
|
||||||
offsets[index] = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
++index;
|
|
||||||
if (i == sz)
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mbqi::next_binding(unsigned_vector& offsets, app_ref_vector const& vars, expr_ref_vector& binding) {
|
void mbqi::set_binding(unsigned_vector const& offsets, app_ref_vector const& vars, expr_ref_vector& binding) {
|
||||||
auto const& nodes = ctx.get_egraph().nodes();
|
|
||||||
unsigned index = m_qs.random() % offsets.size();
|
|
||||||
unsigned i = offsets[index] + 1;
|
|
||||||
sort* srt = m.get_sort(vars[index]);
|
|
||||||
unsigned sz = nodes.size();
|
|
||||||
while (i < sz && m.get_sort(nodes[i]->get_expr()) != srt)
|
|
||||||
++i;
|
|
||||||
if (i == sz)
|
|
||||||
return false;
|
|
||||||
if (nodes[i]->generation() > 0)
|
|
||||||
return false;
|
|
||||||
binding.reset();
|
binding.reset();
|
||||||
|
auto const& nodes = ctx.get_egraph().nodes();
|
||||||
m_model->reset_eval_cache();
|
m_model->reset_eval_cache();
|
||||||
for (unsigned j = 0; j < offsets.size(); ++j) {
|
for (unsigned j = 0; j < offsets.size(); ++j) {
|
||||||
unsigned offset = offsets[j];
|
unsigned offset = offsets[j];
|
||||||
binding.push_back(nodes[offset]->get_expr());
|
binding.push_back(nodes[offset]->get_expr());
|
||||||
m_model->register_decl(vars[j]->get_decl(), (*m_model)(binding.get(j)));
|
m_model->register_decl(vars[j]->get_decl(), (*m_model)(binding.get(j)));
|
||||||
}
|
}
|
||||||
offsets[index] = i;
|
}
|
||||||
|
|
||||||
|
bool mbqi::next_offset(unsigned_vector& offsets, app_ref_vector const& vars) {
|
||||||
|
for (unsigned i = 0; i < vars.size(); ++i) {
|
||||||
|
if (next_offset(offsets, vars, i, offsets[i] + 1))
|
||||||
|
return true;
|
||||||
|
if (!next_offset(offsets, vars, i, 0))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
#if 0
|
||||||
|
auto const& nodes = ctx.get_egraph().nodes();
|
||||||
|
unsigned index = m_qs.random() % offsets.size();
|
||||||
|
if (!next_offset(offsets, vars, index, offsets[index] + 1))
|
||||||
|
return false;
|
||||||
|
if (nodes[offsets[index]]->generation() > 1)
|
||||||
|
return false;
|
||||||
return true;
|
return true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void mbqi::init_model() {
|
void mbqi::init_model() {
|
||||||
|
|
|
@ -78,6 +78,7 @@ namespace q {
|
||||||
q_body* specialize(quantifier* q);
|
q_body* specialize(quantifier* q);
|
||||||
q_body* q2body(quantifier* q);
|
q_body* q2body(quantifier* q);
|
||||||
expr_ref solver_project(model& mdl, q_body& qb, expr_ref_vector& eqs, bool use_inst);
|
expr_ref solver_project(model& mdl, q_body& qb, expr_ref_vector& eqs, bool use_inst);
|
||||||
|
void add_universe_restriction(quantifier* q, q_body& qb);
|
||||||
void add_domain_eqs(model& mdl, q_body& qb);
|
void add_domain_eqs(model& mdl, q_body& qb);
|
||||||
void add_domain_bounds(model& mdl, q_body& qb);
|
void add_domain_bounds(model& mdl, q_body& qb);
|
||||||
void eliminate_nested_vars(expr_ref_vector& fmls, q_body& qb);
|
void eliminate_nested_vars(expr_ref_vector& fmls, q_body& qb);
|
||||||
|
@ -89,9 +90,14 @@ namespace q {
|
||||||
void add_plugin(mbp::project_plugin* p);
|
void add_plugin(mbp::project_plugin* p);
|
||||||
void add_instantiation(quantifier* q, expr_ref& proj);
|
void add_instantiation(quantifier* q, expr_ref& proj);
|
||||||
|
|
||||||
|
lbool check_forall_default(quantifier* q, q_body& qb, model& mdl);
|
||||||
|
bool check_forall_subst(quantifier* q, q_body& qb, model& mdl);
|
||||||
|
|
||||||
bool quick_check(quantifier* q, q_body& qb);
|
bool quick_check(quantifier* q, q_body& qb);
|
||||||
bool next_binding(unsigned_vector& offsets, app_ref_vector const& vars, expr_ref_vector& binding);
|
bool next_offset(unsigned_vector& offsets, app_ref_vector const& vars);
|
||||||
bool first_offset(unsigned_vector& offsets, app_ref_vector const& vars);
|
bool first_offset(unsigned_vector& offsets, app_ref_vector const& vars);
|
||||||
|
bool next_offset(unsigned_vector& offsets, app_ref_vector const& vars, unsigned i, unsigned start);
|
||||||
|
void set_binding(unsigned_vector const& offsets, app_ref_vector const& vars, expr_ref_vector& binding);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -3487,7 +3487,6 @@ public:
|
||||||
return inf_eps(rational::zero(), val);
|
return inf_eps(rational::zero(), val);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
std::cout << st << "\n";
|
|
||||||
SASSERT(st == lp::lp_status::UNBOUNDED);
|
SASSERT(st == lp::lp_status::UNBOUNDED);
|
||||||
TRACE("arith", display(tout << st << " v" << v << " vi: " << vi << "\n"););
|
TRACE("arith", display(tout << st << " v" << v << " vi: " << vi << "\n"););
|
||||||
has_shared = false;
|
has_shared = false;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue