3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-10 13:10:50 +00:00

(spacer) add instances even when a q-lemma already exists

It is possible that a new instance of a quantified lemma is discovered
even though a quantified lemma it already known. In this case, the
instance should be added to a corresponding context, even though the
lemma is not new.
This commit is contained in:
Arie Gurfinkel 2017-08-03 19:49:50 -04:00
parent e94b97376c
commit 5da0753269
2 changed files with 27 additions and 16 deletions

View file

@ -314,7 +314,8 @@ bool pred_transformer::propagate_to_next_level (unsigned src_level)
/// \brief adds a lema to the solver and to child solvers /// \brief adds a lema to the solver and to child solvers
void pred_transformer::add_lemma_core(lemma* lemma) void pred_transformer::add_lemma_core(lemma* lemma,
bool ground_only)
{ {
unsigned lvl = lemma->level(); unsigned lvl = lemma->level();
expr* l = lemma->get_expr(); expr* l = lemma->get_expr();
@ -346,7 +347,8 @@ void pred_transformer::add_lemma_core(lemma* lemma)
} }
for (unsigned i = 0, sz = m_use.size (); i < sz; ++i) for (unsigned i = 0, sz = m_use.size (); i < sz; ++i)
{ m_use [i]->add_lemma_from_child(*this, lemma, next_level(lvl)); } { m_use [i]->add_lemma_from_child(*this, lemma,
next_level(lvl), ground_only); }
} }
bool pred_transformer::add_lemma (expr *e, unsigned lvl) { bool pred_transformer::add_lemma (expr *e, unsigned lvl) {
@ -355,7 +357,8 @@ bool pred_transformer::add_lemma (expr *e, unsigned lvl) {
} }
void pred_transformer::add_lemma_from_child (pred_transformer& child, void pred_transformer::add_lemma_from_child (pred_transformer& child,
lemma* lemma, unsigned lvl) lemma* lemma, unsigned lvl,
bool ground_only)
{ {
ensure_level(lvl); ensure_level(lvl);
expr_ref_vector fmls(m); expr_ref_vector fmls(m);
@ -365,21 +368,25 @@ void pred_transformer::add_lemma_from_child (pred_transformer& child,
expr_ref_vector inst(m); expr_ref_vector inst(m);
expr* a = to_app(fmls.get(i))->get_arg(0); expr* a = to_app(fmls.get(i))->get_arg(0);
expr* l = to_app(fmls.get(i))->get_arg(1); expr* l = to_app(fmls.get(i))->get_arg(1);
if (get_context().use_instantiate()) if (get_context().use_instantiate()) {
{ lemma->mk_insts(inst, l); } lemma->mk_insts(inst, l);
}
for (unsigned j=0; j < inst.size(); j++) { for (unsigned j=0; j < inst.size(); j++) {
inst.set(j, m.mk_implies(a, inst.get(j))); inst.set(j, m.mk_implies(a, inst.get(j)));
} }
if (lemma->is_ground() || get_context().use_qlemmas()) if (lemma->is_ground() || (get_context().use_qlemmas() && !ground_only)) {
{ inst.push_back(fmls.get(i)); } inst.push_back(fmls.get(i));
}
SASSERT (!inst.empty ()); SASSERT (!inst.empty ());
for (unsigned j = 0; j < inst.size(); ++j) { for (unsigned j = 0; j < inst.size(); ++j) {
TRACE("spacer_detail", tout << "child property: " TRACE("spacer_detail", tout << "child property: "
<< mk_pp(inst.get (j), m) << "\n";); << mk_pp(inst.get (j), m) << "\n";);
if (is_infty_level(lvl)) if (is_infty_level(lvl)) {
{ m_solver.assert_expr(inst.get(j)); } m_solver.assert_expr(inst.get(j));
else }
{ m_solver.assert_expr(inst.get(j), lvl); } else {
m_solver.assert_expr(inst.get(j), lvl);
}
} }
} }
@ -1263,18 +1270,21 @@ bool pred_transformer::frames::add_lemma(lemma *lem)
if (!lem->get_bindings().empty()) { if (!lem->get_bindings().empty()) {
m_lemmas [i]->add_binding(lem->get_bindings()); m_lemmas [i]->add_binding(lem->get_bindings());
} }
// if the lemma is at a higher level, skip it // if the lemma is at a higher level, skip it,
// XXX if there are new bindings, we need to assert new instances // but still assert any new instances
if (m_lemmas [i]->level() >= lem->level()) { if (m_lemmas [i]->level() >= lem->level()) {
TRACE("spacer", tout << "Already at a higher level: " TRACE("spacer", tout << "Already at a higher level: "
<< pp_level(m_lemmas [i]->level()) << "\n";); << pp_level(m_lemmas [i]->level()) << "\n";);
if (!lem->get_bindings().empty()) {
m_pt.add_lemma_core(m_lemmas[i], true);
}
return false; return false;
} }
// update level of the existing lemma // update level of the existing lemma
m_lemmas [i]->set_level(lem->level()); m_lemmas [i]->set_level(lem->level());
// assert lemma in the solver // assert lemma in the solver
m_pt.add_lemma_core(m_lemmas[i]); m_pt.add_lemma_core(m_lemmas[i], false);
// move the lemma to its new place to maintain sortedness // move the lemma to its new place to maintain sortedness
for (unsigned j = i; (j + 1) < sz && m_lt(m_lemmas [j + 1], m_lemmas[j]); ++j) { for (unsigned j = i; (j + 1) < sz && m_lt(m_lemmas [j + 1], m_lemmas[j]); ++j) {
m_lemmas.swap (j, j+1); m_lemmas.swap (j, j+1);

View file

@ -294,8 +294,9 @@ class pred_transformer {
void init_sig(); void init_sig();
void ensure_level(unsigned level); void ensure_level(unsigned level);
void add_lemma_core (lemma *lemma); void add_lemma_core (lemma *lemma, bool ground_only = false);
void add_lemma_from_child (pred_transformer &child, lemma *lemma, unsigned lvl); void add_lemma_from_child (pred_transformer &child, lemma *lemma,
unsigned lvl, bool ground_only = false);
void mk_assumptions(func_decl* head, expr* fml, expr_ref_vector& result); void mk_assumptions(func_decl* head, expr* fml, expr_ref_vector& result);