3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-15 23:35:26 +00:00

implementing model updates

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2017-10-30 16:11:51 -05:00
parent 92b5301b7f
commit 3de8c193ea
63 changed files with 482 additions and 294 deletions

View file

@ -3,6 +3,7 @@ z3_add_component(tactic
equiv_proof_converter.cpp
extension_model_converter.cpp
filter_model_converter.cpp
generic_model_converter.cpp
goal.cpp
goal_num_occurs.cpp
goal_shared_occs.cpp

View file

@ -21,7 +21,7 @@ Revision History:
--*/
#include "tactic/tactical.h"
#include "tactic/filter_model_converter.h"
#include "tactic/extension_model_converter.h"
#include "tactic/generic_model_converter.h"
#include "util/cooperate.h"
#include "ast/arith_decl_plugin.h"
#include "tactic/core/simplify_tactic.h"
@ -127,9 +127,7 @@ class degree_shift_tactic : public tactic {
void visit_args(expr * t, expr_fast_mark1 & visited) {
if (is_app(t)) {
unsigned num_args = to_app(t)->get_num_args();
for (unsigned i = 0; i < num_args; i++) {
expr * arg = to_app(t)->get_arg(i);
for (expr * arg : *to_app(t)) {
save_degree(arg, m_one);
visit(arg, visited);
}
@ -166,11 +164,9 @@ class degree_shift_tactic : public tactic {
void display_candidates(std::ostream & out) {
out << "candidates:\n";
obj_map<app, rational>::iterator it = m_var2degree.begin();
obj_map<app, rational>::iterator end = m_var2degree.end();
for (; it != end; ++it) {
if (!it->m_value.is_one()) {
out << "POWER: " << it->m_value << "\n" << mk_ismt2_pp(it->m_key, m) << "\n";
for (auto const& kv : m_var2degree) {
if (!kv.m_value.is_one()) {
out << "POWER: " << kv.m_value << "\n" << mk_ismt2_pp(kv.m_key, m) << "\n";
}
}
}
@ -189,48 +185,42 @@ class degree_shift_tactic : public tactic {
void discard_non_candidates() {
m_pinned.reset();
ptr_vector<app> to_delete;
obj_map<app, rational>::iterator it = m_var2degree.begin();
obj_map<app, rational>::iterator end = m_var2degree.end();
for (; it != end; ++it) {
if (it->m_value.is_one())
to_delete.push_back(it->m_key);
for (auto const& kv : m_var2degree) {
if (kv.m_value.is_one())
to_delete.push_back(kv.m_key);
else
m_pinned.push_back(it->m_key); // make sure it is not deleted during simplifications
m_pinned.push_back(kv.m_key); // make sure it is not deleted during simplifications
}
ptr_vector<app>::iterator it2 = to_delete.begin();
ptr_vector<app>::iterator end2 = to_delete.end();
for (; it2 != end2; ++it2)
m_var2degree.erase(*it2);
for (app* a : to_delete)
m_var2degree.erase(a);
}
void prepare_substitution(model_converter_ref & mc) {
SASSERT(!m_var2degree.empty());
filter_model_converter * fmc = 0;
extension_model_converter * xmc = 0;
generic_model_converter * xmc = 0;
if (m_produce_models) {
fmc = alloc(filter_model_converter, m);
xmc = alloc(extension_model_converter, m);
xmc = alloc(generic_model_converter, m);
mc = concat(fmc, xmc);
}
obj_map<app, rational>::iterator it = m_var2degree.begin();
obj_map<app, rational>::iterator end = m_var2degree.end();
for (; it != end; ++it) {
SASSERT(it->m_value.is_int());
SASSERT(it->m_value >= rational(2));
app * fresh = m.mk_fresh_const(0, it->m_key->get_decl()->get_range());
for (auto const& kv : m_var2degree) {
SASSERT(kv.m_value.is_int());
SASSERT(kv.m_value >= rational(2));
app * fresh = m.mk_fresh_const(0, kv.m_key->get_decl()->get_range());
m_pinned.push_back(fresh);
m_var2var.insert(it->m_key, fresh);
m_var2var.insert(kv.m_key, fresh);
if (m_produce_models) {
fmc->insert(fresh->get_decl());
xmc->insert(it->m_key->get_decl(), mk_power(fresh, rational(1)/it->m_value));
xmc->add(kv.m_key->get_decl(), mk_power(fresh, rational(1)/kv.m_value));
}
if (m_produce_proofs) {
expr * s = mk_power(it->m_key, it->m_value);
expr * s = mk_power(kv.m_key, kv.m_value);
expr * eq = m.mk_eq(fresh, s);
proof * pr1 = m.mk_def_intro(eq);
proof * result_pr = m.mk_apply_def(fresh, s, pr1);
m_pinned.push_back(result_pr);
m_var2pr.insert(it->m_key, result_pr);
m_var2pr.insert(kv.m_key, result_pr);
}
}
}
@ -267,17 +257,15 @@ class degree_shift_tactic : public tactic {
}
// add >= 0 constraints for variables with even degree
obj_map<app, rational>::iterator it = m_var2degree.begin();
obj_map<app, rational>::iterator end = m_var2degree.end();
for (; it != end; ++it) {
SASSERT(it->m_value.is_int());
SASSERT(it->m_value >= rational(2));
if (it->m_value.is_even()) {
app * new_var = m_var2var.find(it->m_key);
for (auto const& kv : m_var2degree) {
SASSERT(kv.m_value.is_int());
SASSERT(kv.m_value >= rational(2));
if (kv.m_value.is_even()) {
app * new_var = m_var2var.find(kv.m_key);
app * new_c = m_autil.mk_ge(new_var, m_autil.mk_numeral(rational(0), false));
proof * new_pr = 0;
if (m_produce_proofs) {
proof * pr = m_var2pr.find(it->m_key);
proof * pr = m_var2pr.find(kv.m_key);
new_pr = m.mk_th_lemma(m_autil.get_family_id(), new_c, 1, &pr);
}
g->assert_expr(new_c, new_pr, 0);

View file

@ -113,6 +113,11 @@ public:
}
return mc;
}
virtual void display(std::ostream & out) {
out << "(elim01-model-converter)\n";
}
};

View file

@ -107,12 +107,18 @@ class eq2bv_tactic : public tactic {
virtual model_converter* translate(ast_translation & translator) {
bvmc* v = alloc(bvmc);
obj_map<func_decl, func_decl*>::iterator it = m_map.begin(), end = m_map.end();
for (; it != end; ++it) {
v->m_map.insert(translator(it->m_key), translator(it->m_value));
for (auto const& kv : m_map) {
v->m_map.insert(translator(kv.m_key), translator(kv.m_value));
}
return v;
}
virtual void display(std::ostream & out) {
for (auto const& kv : m_map) {
out << "(model-set " << kv.m_key->get_name() << " " << kv.m_value->get_name() << ")\n";
}
}
};
public:

View file

@ -131,10 +131,8 @@ public:
for (unsigned i = 0; i < size; ++i) {
quick_for_each_expr(proc, visited, g->form(i));
}
obj_hashtable<sort>::iterator it = m_non_fd_sorts.begin(), end = m_non_fd_sorts.end();
for (; it != end; ++it) {
m_fd_sorts.remove(*it);
}
for (sort* s : m_non_fd_sorts)
m_fd_sorts.remove(s);
if (!m_fd_sorts.empty()) {
ref<extension_model_converter> ext = alloc(extension_model_converter, m);
ref<filter_model_converter> filter = alloc(filter_model_converter, m);
@ -152,21 +150,12 @@ public:
}
expr_ref_vector bounds(m);
rw.flush_side_constraints(bounds);
for (unsigned i = 0; i < bounds.size(); ++i) {
g->assert_expr(bounds[i].get());
}
{
obj_map<func_decl, func_decl*>::iterator it = rw.enum2bv().begin(), end = rw.enum2bv().end();
for (; it != end; ++it) {
filter->insert(it->m_value);
}
}
{
obj_map<func_decl, expr*>::iterator it = rw.enum2def().begin(), end = rw.enum2def().end();
for (; it != end; ++it) {
ext->insert(it->m_key, it->m_value);
}
}
for (expr* b : bounds)
g->assert_expr(b);
for (auto const& kv : rw.enum2bv())
filter->insert(kv.m_value);
for (auto const& kv : rw.enum2def())
ext->insert(kv.m_key, kv.m_value);
mc = concat(filter.get(), ext.get());
report_tactic_progress(":fd-num-translated", rw.num_translated());

View file

@ -38,8 +38,7 @@ public:
virtual void cancel() {}
// for debugging purposes
virtual void display(std::ostream & out) {}
virtual void display(std::ostream & out) = 0;
};
template<typename T>
@ -68,10 +67,8 @@ public:
virtual char const * get_name() const = 0;
virtual void display(std::ostream & out) {
out << "(" << get_name() << "\n";
m_c1->display(out);
m_c2->display(out);
out << ")\n";
}
};
@ -86,10 +83,9 @@ protected:
T * translate_core(ast_translation & translator) {
T * t1 = m_c1 ? m_c1->translate(translator) : 0;
ptr_buffer<T> t2s;
unsigned num = m_c2s.size();
for (unsigned i = 0; i < num; i++)
t2s.push_back(m_c2s[i] ? m_c2s[i]->translate(translator) : 0);
return alloc(T2, t1, num, t2s.c_ptr(), m_szs.c_ptr());
for (T* c : m_c2s)
t2s.push_back(c ? c->translate(translator) : 0);
return alloc(T2, t1, m_c2s.size(), t2s.c_ptr(), m_szs.c_ptr());
}
public:
@ -105,36 +101,24 @@ public:
}
virtual ~concat_star_converter() {
unsigned sz = m_c2s.size();
for (unsigned i = 0; i < sz; i++) {
T * c2 = m_c2s[i];
if (c2)
c2->dec_ref();
}
for (T* c : m_c2s)
if (c) c->dec_ref();
}
virtual void cancel() {
if (m_c1)
m_c1->cancel();
unsigned num = m_c2s.size();
for (unsigned i = 0; i < num; i++) {
if (m_c2s[i])
m_c2s[i]->cancel();
}
for (T* c : m_c2s)
if (c) c->cancel();
}
virtual char const * get_name() const = 0;
virtual void display(std::ostream & out) {
out << "(" << get_name() << "\n";
if (m_c1)
m_c1->display(out);
out << "(\n";
unsigned num = m_c2s.size();
for (unsigned i = 0; i < num; i++)
if (m_c2s[i])
m_c2s[i]->display(out);
out << "))\n";
for (T* c : m_c2s)
if (c) c->display(out);
}
};

View file

@ -17,7 +17,7 @@ Notes:
--*/
#include "tactic/tactical.h"
#include "tactic/extension_model_converter.h"
#include "tactic/generic_model_converter.h"
#include "tactic/filter_model_converter.h"
#include "ast/rewriter/rewriter_def.h"
#include "ast/arith_decl_plugin.h"
@ -34,7 +34,7 @@ class elim_uncnstr_tactic : public tactic {
struct imp {
// unconstrained vars collector
typedef extension_model_converter mc;
typedef generic_model_converter mc;
struct rw_cfg : public default_rewriter_cfg {
bool m_produce_proofs;
@ -120,7 +120,7 @@ class elim_uncnstr_tactic : public tactic {
SASSERT(uncnstr(v));
SASSERT(to_app(v)->get_num_args() == 0);
if (m_mc)
m_mc->insert(to_app(v)->get_decl(), def);
m_mc->add(to_app(v)->get_decl(), def);
}
void add_defs(unsigned num, expr * const * args, expr * u, expr * identity) {

View file

@ -50,8 +50,8 @@ public:
virtual void operator()(model_ref & mdl, unsigned goal_idx) {
SASSERT(goal_idx == 0);
for (unsigned i = 0; i < m_const.size(); ++i) {
mdl->register_decl(m_const[i].first->get_decl(), m_const[i].second);
for (auto const& kv : m_const) {
mdl->register_decl(kv.first->get_decl(), kv.second);
}
}
@ -65,12 +65,18 @@ public:
virtual model_converter * translate(ast_translation & translator) {
pb_preproc_model_converter* mc = alloc(pb_preproc_model_converter, translator.to());
for (unsigned i = 0; i < m_const.size(); ++i) {
mc->set_value_p(translator(m_const[i].first), translator(m_const[i].second));
for (auto const& kv : m_const) {
mc->set_value_p(translator(kv.first), translator(kv.second));
}
return mc;
}
virtual void display(std::ostream & out) {
for (auto const& kv : m_const) {
out << "(model-set " << mk_pp(kv.first, m) << " " << mk_pp(kv.second, m) << ")\n";
}
}
private:
void set_value_p(app* e, expr* v) {
SASSERT(e->get_num_args() == 0);

View file

@ -79,6 +79,8 @@ class split_clause_tactic : public tactic {
virtual proof_converter * translate(ast_translation & translator) {
return alloc(split_pc, translator.to(), translator(m_clause), translator(m_clause_pr));
}
virtual void display(std::ostream & out) { out << "(split-clause-pc)\n"; }
};
public:

View file

@ -47,6 +47,7 @@ public:
ast_manager& get_manager() { return m; }
virtual void display(std::ostream & out) {}
};
#endif

View file

@ -7,7 +7,7 @@ Module Name:
Abstract:
Model converter that introduces eliminated variables in a model.
Model converter that introduces eliminated variables in a model.
Author:
@ -16,11 +16,11 @@ Author:
Notes:
--*/
#include "tactic/extension_model_converter.h"
#include "model/model_evaluator.h"
#include "ast/ast_smt2_pp.h"
#include "model/model_v2_pp.h"
#include "ast/ast_pp.h"
#include "ast/ast_smt2_pp.h"
#include "model/model_evaluator.h"
#include "model/model_v2_pp.h"
#include "tactic/extension_model_converter.h"
extension_model_converter::~extension_model_converter() {
}
@ -78,20 +78,17 @@ void extension_model_converter::insert(func_decl * v, expr * def) {
void extension_model_converter::display(std::ostream & out) {
out << "(extension-model-converter";
for (unsigned i = 0; i < m_vars.size(); i++) {
out << "\n (" << m_vars.get(i)->get_name() << " ";
unsigned indent = m_vars.get(i)->get_name().size() + 4;
out << mk_ismt2_pp(m_defs.get(i), m(), indent) << ")";
display_add(out, m(), m_vars.get(i), m_defs.get(i));
}
out << ")" << std::endl;
}
model_converter * extension_model_converter::translate(ast_translation & translator) {
extension_model_converter * res = alloc(extension_model_converter, translator.to());
for (unsigned i = 0; i < m_vars.size(); i++)
res->m_vars.push_back(translator(m_vars[i].get()));
for (unsigned i = 0; i < m_defs.size(); i++)
res->m_defs.push_back(translator(m_defs[i].get()));
for (func_decl* v : m_vars)
res->m_vars.push_back(translator(v));
for (expr* d : m_defs)
res->m_defs.push_back(translator(d));
return res;
}

View file

@ -23,12 +23,11 @@ Notes:
#include "ast/ast.h"
#include "tactic/model_converter.h"
class extension_model_converter : public model_converter {
func_decl_ref_vector m_vars;
expr_ref_vector m_defs;
public:
extension_model_converter(ast_manager & m):m_vars(m), m_defs(m) {
extension_model_converter(ast_manager & m): m_vars(m), m_defs(m) {
}
virtual ~extension_model_converter();
@ -44,6 +43,4 @@ public:
virtual model_converter * translate(ast_translation & translator);
};
#endif

View file

@ -55,11 +55,9 @@ void filter_model_converter::operator()(svector<symbol> & labels, unsigned goal_
}
void filter_model_converter::display(std::ostream & out) {
out << "(filter-model-converter";
for (unsigned i = 0; i < m_decls.size(); i++) {
out << " " << m_decls.get(i)->get_name();
for (func_decl* f : m_decls) {
display_del(out, f);
}
out << ")" << std::endl;
}
model_converter * filter_model_converter::translate(ast_translation & translator) {

View file

@ -24,7 +24,7 @@ Notes:
class filter_model_converter : public model_converter {
func_decl_ref_vector m_decls;
public:
filter_model_converter(ast_manager & m):m_decls(m) {}
filter_model_converter(ast_manager & m): m_decls(m) {}
virtual ~filter_model_converter();

View file

@ -78,6 +78,7 @@ public:
ast_manager& get_manager() { return m; }
virtual void display(std::ostream & out) {}
};
#endif

View file

@ -18,10 +18,53 @@ Notes:
--*/
#include "tactic/model_converter.h"
#include "model/model_v2_pp.h"
#include "ast/ast_smt2_pp.h"
/*
* Add or overwrite value in model.
*/
void model_converter::display_add(std::ostream& out, ast_manager& m, func_decl* f, expr* e) const {
// TBD: for arity > 0, requires signature of arguments.
if (m_env) {
ast_smt2_pp(out, f, e, *m_env, params_ref(), 0, "model-add");
}
else {
unsigned indent = f->get_name().size() + 4;
out << "(model-add " << f->get_name() << " " << mk_ismt2_pp(e, m, indent) << ")\n";
}
}
/*
* A value is removed from the model.
*/
void model_converter::display_del(std::ostream& out, func_decl* f) const {
if (m_env) {
ast_smt2_pp(out, f, *m_env, params_ref(), 0, "model-del");
}
else {
out << "(model-del " << f->get_name() << ")\n";
}
}
void model_converter::display_add(std::ostream& out, ast_manager& m) {
// default printer for converter that adds entries
model_ref mdl = alloc(model, m);
(*this)(mdl);
for (unsigned i = 0, sz = mdl->get_num_constants(); i < sz; ++i) {
func_decl* f = mdl->get_constant(i);
display_add(out, m, f, mdl->get_const_interp(f));
}
for (unsigned i = 0, sz = mdl->get_num_functions(); i < sz; ++i) {
func_decl* f = mdl->get_function(i);
func_interp* fi = mdl->get_func_interp(f);
display_add(out, m, f, fi->get_interp());
}
}
class concat_model_converter : public concat_converter<model_converter> {
public:
concat_model_converter(model_converter * mc1, model_converter * mc2):concat_converter<model_converter>(mc1, mc2) {}
concat_model_converter(model_converter * mc1, model_converter * mc2): concat_converter<model_converter>(mc1, mc2) {}
virtual void operator()(model_ref & m) {
this->m_c2->operator()(m);
@ -37,7 +80,6 @@ public:
this->m_c2->operator()(r, goal_idx);
this->m_c1->operator()(r, 0);
}
virtual char const * get_name() const { return "concat-model-converter"; }
@ -90,9 +132,9 @@ public:
// found the model converter that should be used
model_converter * c2 = this->m_c2s[i];
if (c2)
c2->operator()(r, goal_idx);
c2->operator()(r, goal_idx);
if (m_c1)
this->m_c1->operator()(r, i);
this->m_c1->operator()(r, i);
return;
}
// invalid goal
@ -143,10 +185,10 @@ public:
}
virtual void operator()(labels_vec & r, unsigned goal_idx) {
r.append(m_labels.size(), m_labels.c_ptr());
r.append(m_labels.size(), m_labels.c_ptr());
}
virtual void cancel() {
virtual void cancel() {
}
virtual void display(std::ostream & out) {

View file

@ -24,9 +24,19 @@ Notes:
#include "util/ref.h"
class labels_vec : public svector<symbol> {};
class smt2_pp_environment;
class model_converter : public converter {
protected:
smt2_pp_environment* m_env;
void display_add(std::ostream& out, ast_manager& m, func_decl* f, expr* e) const;
void display_del(std::ostream& out, func_decl* f) const;
void display_add(std::ostream& out, ast_manager& m);
public:
model_converter(): m_env(0) {}
virtual void operator()(model_ref & m) {} // TODO: delete
virtual void operator()(model_ref & m, unsigned goal_idx) {
@ -34,10 +44,12 @@ public:
SASSERT(goal_idx == 0);
operator()(m);
}
virtual void operator()(labels_vec & r, unsigned goal_idx) {}
virtual model_converter * translate(ast_translation & translator) = 0;
void set_pp_env(smt2_pp_environment* env) { m_env = env; }
};
typedef ref<model_converter> model_converter_ref;

View file

@ -150,7 +150,7 @@ public:
virtual void set_progress_callback(progress_callback * callback) { m_solver->set_progress_callback(callback); }
virtual void collect_statistics(statistics & st) const { m_solver->collect_statistics(st); }
virtual void get_unsat_core(ptr_vector<expr> & r) { m_solver->get_unsat_core(r); }
virtual void get_model(model_ref & mdl) {
virtual void get_model_core(model_ref & mdl) {
m_solver->get_model(mdl);
if (mdl) {
extend_model(mdl);

View file

@ -95,7 +95,7 @@ public:
virtual void set_progress_callback(progress_callback * callback) { m_solver->set_progress_callback(callback); }
virtual void collect_statistics(statistics & st) const { m_solver->collect_statistics(st); }
virtual void get_unsat_core(ptr_vector<expr> & r) { m_solver->get_unsat_core(r); }
virtual void get_model(model_ref & mdl) {
virtual void get_model_core(model_ref & mdl) {
m_solver->get_model(mdl);
if (mdl) {
extend_model(mdl);

View file

@ -87,7 +87,7 @@ public:
m_solver->collect_statistics(st);
}
virtual void get_unsat_core(ptr_vector<expr> & r) { m_solver->get_unsat_core(r); }
virtual void get_model(model_ref & mdl) {
virtual void get_model_core(model_ref & mdl) {
m_solver->get_model(mdl);
if (mdl) {
filter_model(mdl);

View file

@ -45,6 +45,8 @@ public:
// run the replacements the inverse direction.
void invert() { m_proofs.reverse(); }
virtual void display(std::ostream & out) {}
};
#endif

View file

@ -175,7 +175,7 @@ void exec(tactic & t, goal_ref const & in, goal_ref_buffer & result, model_conve
}
lbool check_sat(tactic & t, goal_ref & g, model_ref & md, labels_vec & labels, proof_ref & pr, expr_dependency_ref & core, std::string & reason_unknown) {
lbool check_sat(tactic & t, goal_ref & g, model_ref & md, model_converter_ref& mc, labels_vec & labels, proof_ref & pr, expr_dependency_ref & core, std::string & reason_unknown) {
bool models_enabled = g->models_enabled();
bool proofs_enabled = g->proofs_enabled();
bool cores_enabled = g->unsat_core_enabled();
@ -184,7 +184,6 @@ lbool check_sat(tactic & t, goal_ref & g, model_ref & md, labels_vec & labels, p
core = 0;
ast_manager & m = g->m();
goal_ref_buffer r;
model_converter_ref mc;
proof_converter_ref pc;
try {
exec(t, g, r, mc, pc, core);
@ -219,9 +218,9 @@ lbool check_sat(tactic & t, goal_ref & g, model_ref & md, labels_vec & labels, p
}
else {
if (models_enabled) {
model_converter2model(m, mc.get(), md);
if (mc)
(*mc)(labels, 0);
model_converter2model(m, mc.get(), md);
if (mc)
(*mc)(labels, 0);
}
reason_unknown = "incomplete";
return l_undef;

View file

@ -153,7 +153,7 @@ public:
#define MK_SIMPLE_TACTIC_FACTORY(NAME, ST) MK_TACTIC_FACTORY(NAME, return ST;)
void exec(tactic & t, goal_ref const & in, goal_ref_buffer & result, model_converter_ref & mc, proof_converter_ref & pc, expr_dependency_ref & core);
lbool check_sat(tactic & t, goal_ref & g, model_ref & md, labels_vec & labels, proof_ref & pr, expr_dependency_ref & core, std::string & reason_unknown);
lbool check_sat(tactic & t, goal_ref & g, model_ref & md, model_converter_ref& mc, labels_vec & labels, proof_ref & pr, expr_dependency_ref & core, std::string & reason_unknown);
// Throws an exception if goal \c in requires proof generation.
void fail_if_proof_generation(char const * tactic_name, goal_ref const & in);