mirror of
https://github.com/Z3Prover/z3
synced 2025-08-22 11:07:51 +00:00
move model and proof converters to self-contained module
This commit is contained in:
parent
7b12a5c5a8
commit
1dca6402fb
88 changed files with 170 additions and 134 deletions
8
src/ast/converters/CMakeLists.txt
Normal file
8
src/ast/converters/CMakeLists.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
z3_add_component(converters
|
||||
SOURCES
|
||||
model_converter.cpp
|
||||
proof_converter.cpp
|
||||
generic_model_converter.cpp
|
||||
COMPONENT_DEPENDENCIES
|
||||
model
|
||||
)
|
124
src/ast/converters/converter.h
Normal file
124
src/ast/converters/converter.h
Normal file
|
@ -0,0 +1,124 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
converter.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Abstract class and templates for proof and model converters.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-11-14
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#pragma once
|
||||
|
||||
#include "util/vector.h"
|
||||
#include "util/ref.h"
|
||||
#include "ast/ast_translation.h"
|
||||
|
||||
class converter {
|
||||
unsigned m_ref_count;
|
||||
public:
|
||||
converter():m_ref_count(0) {}
|
||||
virtual ~converter() = default;
|
||||
|
||||
void inc_ref() { ++m_ref_count; }
|
||||
|
||||
void dec_ref() {
|
||||
--m_ref_count;
|
||||
if (m_ref_count == 0) {
|
||||
dealloc(this);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void cancel() {}
|
||||
|
||||
virtual void display(std::ostream & out) = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class concat_converter : public T {
|
||||
protected:
|
||||
ref<T> m_c1;
|
||||
ref<T> m_c2;
|
||||
|
||||
template<typename T2>
|
||||
T * translate_core(ast_translation & translator) {
|
||||
T * t1 = m_c1->translate(translator);
|
||||
T * t2 = m_c2->translate(translator);
|
||||
return alloc(T2, t1, t2);
|
||||
}
|
||||
|
||||
public:
|
||||
concat_converter(T * c1, T * c2):m_c1(c1), m_c2(c2) {}
|
||||
|
||||
void cancel() override {
|
||||
m_c2->cancel();
|
||||
m_c1->cancel();
|
||||
}
|
||||
|
||||
virtual char const * get_name() const = 0;
|
||||
|
||||
void display(std::ostream & out) override {
|
||||
m_c1->display(out);
|
||||
m_c2->display(out);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class concat_star_converter : public T {
|
||||
protected:
|
||||
ref<T> m_c1;
|
||||
ptr_vector<T> m_c2s;
|
||||
unsigned_vector m_szs;
|
||||
|
||||
template<typename T2>
|
||||
T * translate_core(ast_translation & translator) {
|
||||
T * t1 = m_c1 ? m_c1->translate(translator) : nullptr;
|
||||
ptr_buffer<T> t2s;
|
||||
for (T* c : m_c2s)
|
||||
t2s.push_back(c ? c->translate(translator) : nullptr);
|
||||
return alloc(T2, t1, m_c2s.size(), t2s.data(), m_szs.data());
|
||||
}
|
||||
|
||||
public:
|
||||
concat_star_converter(T * c1, unsigned num, T * const * c2s, unsigned * szs):
|
||||
m_c1(c1) {
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
T * c2 = c2s[i];
|
||||
if (c2)
|
||||
c2->inc_ref();
|
||||
m_c2s.push_back(c2);
|
||||
m_szs.push_back(szs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
~concat_star_converter() override {
|
||||
for (T* c : m_c2s)
|
||||
if (c) c->dec_ref();
|
||||
}
|
||||
|
||||
void cancel() override {
|
||||
if (m_c1)
|
||||
m_c1->cancel();
|
||||
for (T* c : m_c2s)
|
||||
if (c) c->cancel();
|
||||
}
|
||||
|
||||
virtual char const * get_name() const = 0;
|
||||
|
||||
void display(std::ostream & out) override {
|
||||
if (m_c1)
|
||||
m_c1->display(out);
|
||||
for (T* c : m_c2s)
|
||||
if (c) c->display(out);
|
||||
}
|
||||
};
|
||||
|
||||
|
218
src/ast/converters/generic_model_converter.cpp
Normal file
218
src/ast/converters/generic_model_converter.cpp
Normal file
|
@ -0,0 +1,218 @@
|
|||
/*++
|
||||
Copyright (c) 2017 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
generic_model_converter.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Generic model converter that hides and adds entries.
|
||||
It subsumes filter_model_converter and extension_model_converter.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2017-10-29
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
#include "ast/for_each_expr.h"
|
||||
#include "ast/ast_util.h"
|
||||
#include "ast/occurs.h"
|
||||
#include "ast/rewriter/expr_safe_replace.h"
|
||||
#include "ast/rewriter/th_rewriter.h"
|
||||
#include "ast/converters/generic_model_converter.h"
|
||||
#include "model/model_v2_pp.h"
|
||||
#include "model/model_evaluator.h"
|
||||
|
||||
|
||||
generic_model_converter::~generic_model_converter() {
|
||||
}
|
||||
|
||||
|
||||
void generic_model_converter::add(func_decl * d, expr* e) {
|
||||
VERIFY(e);
|
||||
VERIFY(d->get_range() == e->get_sort());
|
||||
m_first_idx.insert_if_not_there(d, m_entries.size());
|
||||
m_entries.push_back(entry(d, e, m, ADD));
|
||||
}
|
||||
|
||||
void generic_model_converter::operator()(model_ref & md) {
|
||||
TRACE("model_converter", tout << "before generic_model_converter\n"; model_v2_pp(tout, *md); display(tout););
|
||||
|
||||
model_evaluator ev(*(md.get()));
|
||||
ev.set_model_completion(true);
|
||||
ev.set_expand_array_equalities(false);
|
||||
expr_ref val(m);
|
||||
unsigned arity;
|
||||
bool reset_ev = false;
|
||||
for (unsigned i = m_entries.size(); i-- > 0; ) {
|
||||
entry const& e = m_entries[i];
|
||||
switch (e.m_instruction) {
|
||||
case instruction::HIDE:
|
||||
md->unregister_decl(e.m_f);
|
||||
break;
|
||||
case instruction::ADD:
|
||||
ev(e.m_def, val);
|
||||
TRACE("model_converter", tout << e.m_f->get_name() << " ->\n" << e.m_def << "\n==>\n" << val << "\n";);
|
||||
arity = e.m_f->get_arity();
|
||||
reset_ev = false;
|
||||
if (arity == 0) {
|
||||
expr* old_val = md->get_const_interp(e.m_f);
|
||||
if (old_val && old_val == val) {
|
||||
// skip
|
||||
}
|
||||
else {
|
||||
reset_ev = old_val != nullptr;
|
||||
md->register_decl(e.m_f, val);
|
||||
}
|
||||
}
|
||||
else {
|
||||
func_interp * old_val = md->get_func_interp(e.m_f);
|
||||
if (old_val && old_val->get_else() == val) {
|
||||
// skip
|
||||
}
|
||||
else {
|
||||
reset_ev = old_val != nullptr;
|
||||
func_interp * new_fi = alloc(func_interp, m, arity);
|
||||
new_fi->set_else(val);
|
||||
md->register_decl(e.m_f, new_fi);
|
||||
}
|
||||
}
|
||||
if (reset_ev) {
|
||||
ev.reset();
|
||||
ev.set_model_completion(true);
|
||||
ev.set_expand_array_equalities(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
TRACE("model_converter", tout << "after generic_model_converter\n"; model_v2_pp(tout, *md););
|
||||
}
|
||||
|
||||
void generic_model_converter::display(std::ostream & out) {
|
||||
for (entry const& e : m_entries) {
|
||||
switch (e.m_instruction) {
|
||||
case instruction::HIDE:
|
||||
display_del(out, e.m_f);
|
||||
break;
|
||||
case instruction::ADD:
|
||||
display_add(out, m, e.m_f, e.m_def);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
generic_model_converter * generic_model_converter::copy(ast_translation & translator) {
|
||||
ast_manager& to = translator.to();
|
||||
generic_model_converter * res = alloc(generic_model_converter, to, m_orig.c_str());
|
||||
for (entry const& e : m_entries) {
|
||||
func_decl_ref d(translator(e.m_f.get()), to);
|
||||
switch (e.m_instruction) {
|
||||
case instruction::HIDE:
|
||||
res->hide(d);
|
||||
break;
|
||||
case instruction::ADD: {
|
||||
expr_ref def(translator(e.m_def.get()), to);
|
||||
res->add(d, def);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void generic_model_converter::set_env(ast_pp_util* visitor) {
|
||||
if (!visitor) {
|
||||
m_env = nullptr;
|
||||
}
|
||||
else {
|
||||
m_env = &visitor->env();
|
||||
for (entry const& e : m_entries) {
|
||||
visitor->coll.visit_func(e.m_f);
|
||||
if (e.m_def) visitor->coll.visit(e.m_def);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void generic_model_converter::get_units(obj_map<expr, bool>& units) {
|
||||
th_rewriter rw(m);
|
||||
expr_safe_replace rep(m);
|
||||
expr_ref tmp(m);
|
||||
for (auto const& kv : units) {
|
||||
rep.insert(kv.m_key, kv.m_value ? m.mk_true() : m.mk_false());
|
||||
}
|
||||
for (unsigned i = m_entries.size(); i-- > 0;) {
|
||||
entry const& e = m_entries[i];
|
||||
switch (e.m_instruction) {
|
||||
case HIDE:
|
||||
tmp = m.mk_const(e.m_f);
|
||||
if (units.contains(tmp)) {
|
||||
m.dec_ref(tmp);
|
||||
units.remove(tmp);
|
||||
}
|
||||
break;
|
||||
case ADD:
|
||||
if (e.m_f->get_arity() == 0 && m.is_bool(e.m_f->get_range())) {
|
||||
tmp = m.mk_const(e.m_f);
|
||||
if (units.contains(tmp)) {
|
||||
break;
|
||||
}
|
||||
tmp = e.m_def;
|
||||
rep(tmp);
|
||||
rw(tmp);
|
||||
if (m.is_true(tmp)) {
|
||||
tmp = m.mk_const(e.m_f);
|
||||
m.inc_ref(tmp);
|
||||
units.insert(tmp, true);
|
||||
rep.insert(tmp, m.mk_true());
|
||||
}
|
||||
else if (m.is_false(tmp)) {
|
||||
tmp = m.mk_const(e.m_f);
|
||||
m.inc_ref(tmp);
|
||||
units.insert(tmp, false);
|
||||
rep.insert(tmp, m.mk_false());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
\brief simplify definition expansion from model converter in the case they come from blocked clauses.
|
||||
In this case the definitions are of the form:
|
||||
|
||||
x <=> x or not (C)
|
||||
|
||||
or dually,
|
||||
|
||||
x <=> not (not x or not C)
|
||||
|
||||
in either case the definitions simplify to
|
||||
|
||||
x or C
|
||||
|
||||
*/
|
||||
expr_ref generic_model_converter::simplify_def(entry const& e) {
|
||||
expr_ref c(m.mk_const(e.m_f), m);
|
||||
if (m.is_bool(c) && occurs(c, e.m_def)) {
|
||||
expr_safe_replace rep(m);
|
||||
expr_ref result1 = e.m_def;
|
||||
expr_ref result2 = e.m_def;
|
||||
rep.apply_substitution(c, m.mk_true(), result1);
|
||||
rep.apply_substitution(c, m.mk_false(), result2);
|
||||
th_rewriter rw(m);
|
||||
expr_ref result(m.mk_and(m.mk_implies(result2, c), m.mk_implies(c, result1)), m);
|
||||
rw(result);
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
return expr_ref(m.mk_eq(c, e.m_def), m);
|
||||
}
|
||||
}
|
73
src/ast/converters/generic_model_converter.h
Normal file
73
src/ast/converters/generic_model_converter.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*++
|
||||
Copyright (c) 2017 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
generic_model_converter.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Generic model converter that hides and adds entries.
|
||||
It subsumes filter_model_converter and extension_model_converter.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2017-10-29
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#pragma once
|
||||
|
||||
#include "ast/converters/model_converter.h"
|
||||
|
||||
class generic_model_converter : public model_converter {
|
||||
enum instruction { HIDE, ADD };
|
||||
struct entry {
|
||||
func_decl_ref m_f;
|
||||
expr_ref m_def;
|
||||
instruction m_instruction;
|
||||
entry(func_decl* f, expr* d, ast_manager& m, instruction i):
|
||||
m_f(f, m), m_def(d, m), m_instruction(i) {}
|
||||
};
|
||||
ast_manager& m;
|
||||
std::string m_orig;
|
||||
vector<entry> m_entries;
|
||||
obj_map<func_decl, unsigned> m_first_idx;
|
||||
|
||||
expr_ref simplify_def(entry const& e);
|
||||
|
||||
public:
|
||||
generic_model_converter(ast_manager & m, char const* orig) : m(m), m_orig(orig) {}
|
||||
|
||||
~generic_model_converter() override;
|
||||
|
||||
void hide(expr* e) { SASSERT(is_app(e) && to_app(e)->get_num_args() == 0); hide(to_app(e)->get_decl()); }
|
||||
|
||||
void hide(func_decl * f) { m_entries.push_back(entry(f, nullptr, m, HIDE)); }
|
||||
|
||||
void add(func_decl * d, expr* e);
|
||||
|
||||
void add(expr * d, expr* e) { SASSERT(is_app(d) && to_app(d)->get_num_args() == 0); add(to_app(d)->get_decl(), e); }
|
||||
|
||||
void operator()(labels_vec & labels) override {}
|
||||
|
||||
void operator()(model_ref & md) override;
|
||||
|
||||
void operator()(expr_ref& fml) override { UNREACHABLE(); }
|
||||
|
||||
void cancel() override {}
|
||||
|
||||
void display(std::ostream & out) override;
|
||||
|
||||
model_converter * translate(ast_translation & translator) override { return copy(translator); }
|
||||
|
||||
generic_model_converter* copy(ast_translation & translator);
|
||||
|
||||
void set_env(ast_pp_util* visitor) override;
|
||||
|
||||
void get_units(obj_map<expr, bool>& units) override;
|
||||
};
|
||||
|
||||
typedef ref<generic_model_converter> generic_model_converter_ref;
|
||||
|
201
src/ast/converters/model_converter.cpp
Normal file
201
src/ast/converters/model_converter.cpp
Normal file
|
@ -0,0 +1,201 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
model_converter.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Abstract interface for converting models.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-04-21
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#include "ast/converters/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, smt2_pp_environment& env, ast_manager& m, func_decl* f, expr* e) {
|
||||
VERIFY(e);
|
||||
VERIFY(f->get_range() == e->get_sort());
|
||||
ast_smt2_pp(out, f, e, env, params_ref(), 0, "model-add") << "\n";
|
||||
}
|
||||
|
||||
void model_converter::display_add(std::ostream& out, ast_manager& m, func_decl* f, expr* e) const {
|
||||
smt2_pp_environment_dbg dbgenv(m);
|
||||
smt2_pp_environment& env = m_env ? *m_env : dbgenv;
|
||||
display_add(out, env, m, f, e);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 << "(model-del ", f->get_name(), f->is_skolem(), *m_env) << ")\n";
|
||||
}
|
||||
else {
|
||||
out << "(model-del " << f->get_name() << ")\n";
|
||||
}
|
||||
}
|
||||
|
||||
void model_converter::set_env(ast_pp_util* visitor) {
|
||||
if (visitor) {
|
||||
m_env = &visitor->env();
|
||||
}
|
||||
else {
|
||||
m_env = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
smt2_pp_environment_dbg dbgenv(m);
|
||||
smt2_pp_environment& env = m_env ? *m_env : dbgenv;
|
||||
display_add(out, env, *mdl);
|
||||
}
|
||||
|
||||
void model_converter::display_add(std::ostream& out, smt2_pp_environment& env, model& mdl) {
|
||||
|
||||
ast_manager& m = mdl.get_manager();
|
||||
for (unsigned i = 0, sz = mdl.get_num_constants(); i < sz; ++i) {
|
||||
func_decl* f = mdl.get_constant(i);
|
||||
display_add(out, env, 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, env, 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) {
|
||||
VERIFY(m_c1 && m_c2);
|
||||
}
|
||||
|
||||
void operator()(model_ref & m) override {
|
||||
this->m_c2->operator()(m);
|
||||
this->m_c1->operator()(m);
|
||||
}
|
||||
|
||||
void operator()(expr_ref & fml) override {
|
||||
this->m_c2->operator()(fml);
|
||||
this->m_c1->operator()(fml);
|
||||
}
|
||||
|
||||
void operator()(labels_vec & r) override {
|
||||
this->m_c2->operator()(r);
|
||||
this->m_c1->operator()(r);
|
||||
}
|
||||
|
||||
void get_units(obj_map<expr, bool>& fmls) override {
|
||||
m_c2->get_units(fmls);
|
||||
m_c1->get_units(fmls);
|
||||
}
|
||||
|
||||
char const * get_name() const override { return "concat-model-converter"; }
|
||||
|
||||
model_converter * translate(ast_translation & translator) override {
|
||||
return this->translate_core<concat_model_converter>(translator);
|
||||
}
|
||||
|
||||
void set_env(ast_pp_util* visitor) override {
|
||||
this->m_c1->set_env(visitor);
|
||||
this->m_c2->set_env(visitor);
|
||||
}
|
||||
};
|
||||
|
||||
model_converter * concat(model_converter * mc1, model_converter * mc2) {
|
||||
if (mc1 == nullptr)
|
||||
return mc2;
|
||||
if (mc2 == nullptr)
|
||||
return mc1;
|
||||
return alloc(concat_model_converter, mc1, mc2);
|
||||
}
|
||||
|
||||
|
||||
class model2mc : public model_converter {
|
||||
model_ref m_model;
|
||||
labels_vec m_labels;
|
||||
public:
|
||||
model2mc(model * m):m_model(m) {}
|
||||
|
||||
model2mc(model * m, labels_vec const & r):m_model(m), m_labels(r) {}
|
||||
|
||||
void operator()(model_ref & m) override {
|
||||
if (!m || !m_model) {
|
||||
m = m_model;
|
||||
return;
|
||||
}
|
||||
m->copy_const_interps(*m_model.get());
|
||||
m->copy_func_interps(*m_model.get());
|
||||
m->copy_usort_interps(*m_model.get());
|
||||
}
|
||||
|
||||
void operator()(labels_vec & r) override {
|
||||
r.append(m_labels.size(), m_labels.data());
|
||||
}
|
||||
|
||||
void operator()(expr_ref& fml) override {
|
||||
model::scoped_model_completion _scm(m_model, false);
|
||||
fml = (*m_model)(fml);
|
||||
}
|
||||
|
||||
void get_units(obj_map<expr, bool>& fmls) override {
|
||||
// no-op
|
||||
}
|
||||
|
||||
void cancel() override {
|
||||
}
|
||||
|
||||
void display(std::ostream & out) override {
|
||||
ast_manager& m = m_model->get_manager();
|
||||
smt2_pp_environment_dbg dbgenv(m);
|
||||
smt2_pp_environment& env = m_env ? *m_env : dbgenv;
|
||||
model_converter::display_add(out, env, *m_model);
|
||||
}
|
||||
|
||||
model_converter * translate(ast_translation & translator) override {
|
||||
model * m = m_model->translate(translator);
|
||||
return alloc(model2mc, m, m_labels);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
model_converter * model2model_converter(model * m) {
|
||||
if (!m) return nullptr;
|
||||
return alloc(model2mc, m);
|
||||
}
|
||||
|
||||
model_converter * model_and_labels2model_converter(model * m, labels_vec const & r) {
|
||||
if (!m) return nullptr;
|
||||
return alloc(model2mc, m, r);
|
||||
}
|
||||
|
||||
void model_converter2model(ast_manager & mng, model_converter * mc, model_ref & m) {
|
||||
if (mc) {
|
||||
m = alloc(model, mng);
|
||||
(*mc)(m);
|
||||
}
|
||||
}
|
||||
|
||||
void apply(model_converter_ref & mc, model_ref & m) {
|
||||
if (mc) {
|
||||
(*mc)(m);
|
||||
}
|
||||
}
|
||||
|
112
src/ast/converters/model_converter.h
Normal file
112
src/ast/converters/model_converter.h
Normal file
|
@ -0,0 +1,112 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
model_converter.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Abstract interface for converting models.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-04-21
|
||||
|
||||
Notes:
|
||||
|
||||
A model converter, mc, can be used to convert a model for one
|
||||
of a generated subgoal into a model for an initial goal or solver state.
|
||||
For a goal or solver state that is decided, a model converter can be
|
||||
a simple wrapper around a model.
|
||||
|
||||
Logically, given a formula F and subgoal formula F_s a model converter mc
|
||||
for F_s relative to F has the property:
|
||||
|
||||
m |= F_s iff mc(m) |= F for every model m
|
||||
|
||||
For the evaluator associated with models, m, we expect
|
||||
|
||||
eval(m)(F_s) <=> eval(mc(m))(F)
|
||||
|
||||
This property holds for both eval, that decides on a fixed value
|
||||
for constants that have no interpretation in m and for 'peval'
|
||||
(partial eval) that returns just the constants that are unfixed.
|
||||
(in the model evaluator one can control this behavior using a
|
||||
configuration flag)
|
||||
|
||||
and more generally over the eval method have:
|
||||
|
||||
G => F_s iff peval(mc(e))(G) => F for every formula G
|
||||
|
||||
|
||||
where e is the empty model (a model that does not evaluate any
|
||||
|
||||
When a model converter supports application to a formula it satisfies
|
||||
the following property:
|
||||
|
||||
mc(G) & F_s is SAT iff G & F is SAT
|
||||
|
||||
For a model converter that is a sequence of definitions and removals
|
||||
of functions we can obtain mc(G) by adding back or expanding definitions
|
||||
that are required to interpret G fully in the context of F_s.
|
||||
|
||||
--*/
|
||||
#pragma once
|
||||
|
||||
#include "util/ref.h"
|
||||
#include "ast/ast_pp_util.h"
|
||||
#include "model/model.h"
|
||||
#include "ast/converters/converter.h"
|
||||
|
||||
class labels_vec : public svector<symbol> {};
|
||||
class smt2_pp_environment;
|
||||
|
||||
class model_converter : public converter {
|
||||
protected:
|
||||
smt2_pp_environment* m_env;
|
||||
static void display_add(std::ostream& out, smt2_pp_environment& env, ast_manager& m, func_decl* f, expr* e);
|
||||
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(nullptr) {}
|
||||
|
||||
virtual void operator()(model_ref & m) = 0;
|
||||
|
||||
virtual void operator()(labels_vec & r) {}
|
||||
|
||||
virtual void operator()(expr_ref& fml) { UNREACHABLE(); }
|
||||
|
||||
virtual model_converter * translate(ast_translation & translator) = 0;
|
||||
|
||||
virtual void set_env(ast_pp_util* visitor);
|
||||
|
||||
/**
|
||||
\brief we are adding a formula to the context of the model converter.
|
||||
The operator has as side effect of adding definitions as assertions to the
|
||||
formula and removing these definitions from the model converter.
|
||||
*/
|
||||
|
||||
virtual void get_units(obj_map<expr, bool>& fmls) { UNREACHABLE(); }
|
||||
|
||||
static void display_add(std::ostream& out, smt2_pp_environment& env, model& mdl);
|
||||
|
||||
};
|
||||
|
||||
typedef ref<model_converter> model_converter_ref;
|
||||
typedef sref_vector<model_converter> model_converter_ref_vector;
|
||||
typedef sref_buffer<model_converter> model_converter_ref_buffer;
|
||||
|
||||
model_converter * concat(model_converter * mc1, model_converter * mc2);
|
||||
|
||||
model_converter * model2model_converter(model * m);
|
||||
|
||||
model_converter * model_and_labels2model_converter(model * m, labels_vec const &r);
|
||||
|
||||
void model_converter2model(ast_manager & mng, model_converter * mc, model_ref & m);
|
||||
|
||||
void apply(model_converter_ref & mc, model_ref & m);
|
||||
|
||||
|
100
src/ast/converters/proof_converter.cpp
Normal file
100
src/ast/converters/proof_converter.cpp
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
proof_converter.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Abstract interface for converting proofs, and basic combinators
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-11-14
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#include "ast/converters/proof_converter.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
|
||||
class concat_proof_converter : public concat_converter<proof_converter> {
|
||||
public:
|
||||
concat_proof_converter(proof_converter * pc1, proof_converter * pc2):concat_converter<proof_converter>(pc1, pc2) {}
|
||||
|
||||
char const * get_name() const override { return "concat-proof-converter"; }
|
||||
|
||||
proof_ref operator()(ast_manager & m, unsigned num_source, proof * const * source) override {
|
||||
proof_ref tmp(m);
|
||||
tmp = this->m_c2->operator()(m, num_source, source);
|
||||
proof * new_source = tmp.get();
|
||||
return this->m_c1->operator()(m, 1, &new_source);
|
||||
}
|
||||
|
||||
proof_converter * translate(ast_translation & translator) override {
|
||||
return this->translate_core<concat_proof_converter>(translator);
|
||||
}
|
||||
};
|
||||
|
||||
proof_converter * concat(proof_converter * pc1, proof_converter * pc2) {
|
||||
if (pc1 == nullptr)
|
||||
return pc2;
|
||||
if (pc2 == nullptr)
|
||||
return pc1;
|
||||
return alloc(concat_proof_converter, pc1, pc2);
|
||||
}
|
||||
|
||||
|
||||
class proof2pc : public proof_converter {
|
||||
proof_ref m_pr;
|
||||
public:
|
||||
proof2pc(ast_manager & m, proof * pr):m_pr(pr, m) {}
|
||||
|
||||
proof_ref operator()(ast_manager & m, unsigned num_source, proof * const * source) override {
|
||||
SASSERT(num_source == 0);
|
||||
return m_pr;
|
||||
}
|
||||
|
||||
proof_converter * translate(ast_translation & translator) override {
|
||||
return alloc(proof2pc, translator.to(), translator(m_pr.get()));
|
||||
}
|
||||
|
||||
void display(std::ostream & out) override {
|
||||
out << "(proof->proof-converter-wrapper\n" << mk_ismt2_pp(m_pr.get(), m_pr.get_manager()) << ")\n";
|
||||
}
|
||||
};
|
||||
|
||||
proof_converter * proof2proof_converter(ast_manager & m, proof * pr) {
|
||||
if (pr == nullptr)
|
||||
return nullptr;
|
||||
return alloc(proof2pc, m, pr);
|
||||
}
|
||||
|
||||
void apply(ast_manager & m, proof_converter * pc, proof_ref & pr) {
|
||||
if (pc) {
|
||||
proof * _pr = pr.get();
|
||||
pr = (*pc)(m, 1, &_pr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Let pc2s be a buffer of proof converters that are wrappers for proofs.
|
||||
That is, they are functors of the form: unit -> Proof
|
||||
Then, this function applies pc1 to the proofs produced by pc2s's and store
|
||||
the resultant proof in result.
|
||||
|
||||
pc1 and pc2s must be different from 0.
|
||||
*/
|
||||
proof_ref apply(ast_manager & m, proof_converter_ref & pc1, proof_converter_ref_buffer & pc2s) {
|
||||
SASSERT(pc1);
|
||||
proof_ref_buffer prs(m);
|
||||
unsigned sz = pc2s.size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
proof_ref pr(m);
|
||||
SASSERT(pc2s[i]); // proof production is enabled
|
||||
pr = pc2s[i]->operator()(m, 0, nullptr);
|
||||
prs.push_back(pr);
|
||||
}
|
||||
return (*pc1)(m, sz, prs.data());
|
||||
}
|
43
src/ast/converters/proof_converter.h
Normal file
43
src/ast/converters/proof_converter.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
proof_converter.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Abstract interface for converting proofs, and basic combinators.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-04-26
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#pragma once
|
||||
|
||||
#include "ast/ast.h"
|
||||
#include "util/ref.h"
|
||||
#include "ast/converters/converter.h"
|
||||
|
||||
class proof_converter : public converter {
|
||||
public:
|
||||
virtual proof_ref operator()(ast_manager & m, unsigned num_source, proof * const * source) = 0;
|
||||
virtual proof_converter * translate(ast_translation & translator) = 0;
|
||||
};
|
||||
|
||||
typedef ref<proof_converter> proof_converter_ref;
|
||||
typedef sref_vector<proof_converter> proof_converter_ref_vector;
|
||||
typedef sref_buffer<proof_converter> proof_converter_ref_buffer;
|
||||
|
||||
|
||||
proof_converter * concat(proof_converter * pc1, proof_converter * pc2);
|
||||
|
||||
proof_converter * proof2proof_converter(ast_manager & m, proof * pr);
|
||||
|
||||
void apply(ast_manager & m, proof_converter * pc, proof_ref & pr);
|
||||
|
||||
proof_ref apply(ast_manager & m, proof_converter_ref & pc1, proof_converter_ref_buffer & pc2s);
|
||||
|
|
@ -33,6 +33,7 @@ Author:
|
|||
#include "util/statistics.h"
|
||||
#include "util/params.h"
|
||||
#include "ast/simplifiers/dependent_expr.h"
|
||||
#include "ast/converters/model_converter.h"
|
||||
|
||||
/**
|
||||
abstract interface to state updated by simplifiers.
|
||||
|
@ -66,6 +67,7 @@ public:
|
|||
virtual void collect_statistics(statistics& st) const {}
|
||||
virtual void reset_statistics() {}
|
||||
virtual void updt_params(params_ref const& p) {}
|
||||
virtual model_converter_ref get_model_converter() { return model_converter_ref(); }
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -23,6 +23,7 @@ Author:
|
|||
#include "ast/recfun_decl_plugin.h"
|
||||
#include "ast/rewriter/expr_replacer.h"
|
||||
#include "ast/simplifiers/solve_eqs.h"
|
||||
#include "ast/converters/generic_model_converter.h"
|
||||
|
||||
|
||||
namespace euf {
|
||||
|
@ -183,14 +184,16 @@ namespace euf {
|
|||
m_unsafe_vars.mark(term);
|
||||
}
|
||||
|
||||
#if 0
|
||||
typedef generic_model_converter gmc;
|
||||
|
||||
model_converter_ref solve_eqs::get_model_converter() {
|
||||
model_converter_ref mc = alloc(gmc, m, "solve-eqs");
|
||||
for (unsigned id : m_subst_ids)
|
||||
static_cast<gmc*>(mc.get())->add(id2var(id), m_subst->find(v));
|
||||
for (unsigned id : m_subst_ids) {
|
||||
auto* v = m_id2var[id];
|
||||
static_cast<gmc*>(mc.get())->add(v, m_subst->find(v));
|
||||
}
|
||||
return mc;
|
||||
}
|
||||
#endif
|
||||
|
||||
solve_eqs::solve_eqs(ast_manager& m, dependent_expr_state& fmls) :
|
||||
dependent_expr_simplifier(m, fmls), m_rewriter(m) {
|
||||
|
|
|
@ -18,9 +18,9 @@ Author:
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "ast/rewriter/th_rewriter.h"
|
||||
#include "ast/expr_substitution.h"
|
||||
#include "util/scoped_ptr_vector.h"
|
||||
#include "ast/expr_substitution.h"
|
||||
#include "ast/rewriter/th_rewriter.h"
|
||||
#include "ast/simplifiers/extract_eqs.h"
|
||||
|
||||
namespace euf {
|
||||
|
@ -74,6 +74,6 @@ namespace euf {
|
|||
void updt_params(params_ref const& p) override;
|
||||
void collect_statistics(statistics& st) const override;
|
||||
|
||||
// model_converter_ref get_model_converter();
|
||||
model_converter_ref get_model_converter() override;
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue