mirror of
https://github.com/Z3Prover/z3
synced 2025-04-24 09:35:32 +00:00
re-organization of muz
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
9e61820125
commit
e4338f085b
37 changed files with 6 additions and 875 deletions
35
src/tactic/equiv_proof_converter.cpp
Normal file
35
src/tactic/equiv_proof_converter.cpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
equiv_proof_converter.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Proof converter that applies equivalence rule to leaves.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2012-11-23
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "equiv_proof_converter.h"
|
||||
#include "ast_pp.h"
|
||||
#include "scoped_proof.h"
|
||||
|
||||
void equiv_proof_converter::insert(expr* fml1, expr* fml2) {
|
||||
if (fml1 != fml2) {
|
||||
scoped_proof _sp(m);
|
||||
proof_ref p1(m), p2(m), p3(m);
|
||||
p1 = m.mk_asserted(fml1);
|
||||
p2 = m.mk_rewrite(fml1, fml2);
|
||||
p3 = m.mk_modus_ponens(p1, p2);
|
||||
TRACE("proof_converter", tout << mk_pp(p3.get(), m) << "\n";);
|
||||
SASSERT(m.has_fact(p3));
|
||||
m_replace.insert(p3);
|
||||
}
|
||||
}
|
52
src/tactic/equiv_proof_converter.h
Normal file
52
src/tactic/equiv_proof_converter.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
equiv_proof_converter.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Proof converter that applies equivalence rule to leaves.
|
||||
|
||||
Given a proof P with occurrences of [asserted fml]
|
||||
replace [asserted fml] by a proof of the form
|
||||
[mp [asserted fml'] [~ fml fml']]
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2012-11-23
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _EQUIV_PROOF_CONVERTER_H_
|
||||
#define _EQUIV_PROOF_CONVERTER_H_
|
||||
|
||||
#include "replace_proof_converter.h"
|
||||
|
||||
class equiv_proof_converter : public proof_converter {
|
||||
ast_manager& m;
|
||||
replace_proof_converter m_replace;
|
||||
public:
|
||||
|
||||
equiv_proof_converter(ast_manager& m): m(m), m_replace(m) {}
|
||||
|
||||
virtual ~equiv_proof_converter() {}
|
||||
|
||||
virtual void operator()(ast_manager & m, unsigned num_source, proof * const * source, proof_ref & result) {
|
||||
m_replace(m, num_source, source, result);
|
||||
}
|
||||
|
||||
virtual proof_converter * translate(ast_translation & translator) {
|
||||
return m_replace.translate(translator);
|
||||
}
|
||||
|
||||
void insert(expr* fml1, expr* fml2);
|
||||
|
||||
ast_manager& get_manager() { return m; }
|
||||
|
||||
};
|
||||
|
||||
#endif
|
233
src/tactic/horn_subsume_model_converter.cpp
Normal file
233
src/tactic/horn_subsume_model_converter.cpp
Normal file
|
@ -0,0 +1,233 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
horn_subsume_model_converter.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Model converter for redundant Horn clauses.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2012-9-16
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
#include "horn_subsume_model_converter.h"
|
||||
#include "var_subst.h"
|
||||
#include "ast_pp.h"
|
||||
#include "model_smt2_pp.h"
|
||||
#include "bool_rewriter.h"
|
||||
#include "th_rewriter.h"
|
||||
#include "for_each_expr.h"
|
||||
#include "well_sorted.h"
|
||||
|
||||
void horn_subsume_model_converter::insert(app* head, expr* body) {
|
||||
m_delay_head.push_back(head);
|
||||
m_delay_body.push_back(body);
|
||||
}
|
||||
|
||||
void horn_subsume_model_converter::insert(app* head, unsigned sz, expr* const* body) {
|
||||
expr_ref b(m);
|
||||
bool_rewriter(m).mk_and(sz, body, b);
|
||||
insert(head, b.get());
|
||||
}
|
||||
|
||||
|
||||
bool horn_subsume_model_converter::mk_horn(
|
||||
app* head, expr* body, func_decl_ref& pred, expr_ref& body_res) {
|
||||
|
||||
expr_ref_vector conjs(m), subst(m);
|
||||
ptr_vector<sort> sorts, sorts2;
|
||||
var_subst vs(m, false);
|
||||
|
||||
if (!is_uninterp(head)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pred = head->get_decl();
|
||||
unsigned arity = head->get_num_args();
|
||||
|
||||
get_free_vars(head, sorts);
|
||||
get_free_vars(body, sorts);
|
||||
|
||||
if (arity == 0 && sorts.empty()) {
|
||||
body_res = body;
|
||||
return true;
|
||||
}
|
||||
|
||||
svector<symbol> names;
|
||||
for (unsigned i = 0; i < sorts.size(); ++i) {
|
||||
if (!sorts[i]) {
|
||||
sorts[i] = m.mk_bool_sort();
|
||||
}
|
||||
names.push_back(symbol(i));
|
||||
}
|
||||
names.reverse();
|
||||
sorts.reverse();
|
||||
conjs.push_back(body);
|
||||
for (unsigned i = 0; i < arity; ++i) {
|
||||
expr* arg = head->get_arg(i);
|
||||
var_ref v(m);
|
||||
v = m.mk_var(sorts.size()+i, m.get_sort(arg));
|
||||
|
||||
if (is_var(arg)) {
|
||||
unsigned w = to_var(arg)->get_idx();
|
||||
if (w >= subst.size()) {
|
||||
subst.resize(w+1);
|
||||
}
|
||||
if (subst[w].get()) {
|
||||
conjs.push_back(m.mk_eq(v, subst[w].get()));
|
||||
}
|
||||
else {
|
||||
subst[w] = v;
|
||||
}
|
||||
}
|
||||
else {
|
||||
conjs.push_back(m.mk_eq(v, arg));
|
||||
}
|
||||
}
|
||||
expr_ref body_expr(m);
|
||||
body_expr = m.mk_and(conjs.size(), conjs.c_ptr());
|
||||
|
||||
// substitute variables directly.
|
||||
if (!subst.empty()) {
|
||||
expr_ref tmp(body_expr);
|
||||
vs(tmp, subst.size(), subst.c_ptr(), body_expr);
|
||||
}
|
||||
|
||||
if (sorts.empty()) {
|
||||
SASSERT(subst.empty());
|
||||
body_res = body_expr;
|
||||
}
|
||||
else {
|
||||
body_res = m.mk_exists(sorts.size(), sorts.c_ptr(), names.c_ptr(), body_expr.get());
|
||||
m_rewrite(body_res);
|
||||
|
||||
}
|
||||
TRACE("mc",
|
||||
tout << mk_pp(head, m) << " :- " << mk_pp(body, m) << "\n";
|
||||
tout << pred->get_name() << " :- " << mk_pp(body_res.get(), m) << "\n";);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool horn_subsume_model_converter::mk_horn(
|
||||
expr* clause, func_decl_ref& pred, expr_ref& body) {
|
||||
ptr_vector<sort> sorts;
|
||||
|
||||
// formula is closed.
|
||||
DEBUG_CODE(get_free_vars(clause, sorts); SASSERT(sorts.empty()););
|
||||
|
||||
while (is_quantifier(clause) && to_quantifier(clause)->is_forall()) {
|
||||
quantifier* q = to_quantifier(clause);
|
||||
clause = q->get_expr();
|
||||
}
|
||||
expr* e1, *e2;
|
||||
if (m.is_implies(clause, e1, e2)) {
|
||||
if (!is_uninterp(e2)) {
|
||||
return false;
|
||||
}
|
||||
return mk_horn(to_app(e2), e1, pred, body);
|
||||
}
|
||||
else if (m.is_or(clause)) {
|
||||
// todo?
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void horn_subsume_model_converter::add_default_proc::operator()(app* n) {
|
||||
|
||||
//
|
||||
// predicates that have not been assigned values
|
||||
// in the Horn model are assumed false.
|
||||
//
|
||||
if (m.is_bool(n) &&
|
||||
!m_md->has_interpretation(n->get_decl()) &&
|
||||
(n->get_family_id() == null_family_id)) {
|
||||
TRACE("mc", tout << "adding: " << n->get_decl()->get_name() << "\n";);
|
||||
if (n->get_decl()->get_arity() == 0) {
|
||||
m_md->register_decl(n->get_decl(), m.mk_false());
|
||||
}
|
||||
else {
|
||||
func_interp* fi = alloc(func_interp, m, n->get_decl()->get_arity());
|
||||
fi->set_else(m.mk_false());
|
||||
m_md->register_decl(n->get_decl(), fi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void horn_subsume_model_converter::add_default_false_interpretation(expr* e, model_ref& md) {
|
||||
add_default_proc proc(m, md);
|
||||
for_each_expr(proc, e);
|
||||
}
|
||||
|
||||
|
||||
void horn_subsume_model_converter::operator()(model_ref& mr) {
|
||||
|
||||
func_decl_ref pred(m);
|
||||
expr_ref body_res(m);
|
||||
for (unsigned i = 0; i < m_delay_head.size(); ++i) {
|
||||
VERIFY(mk_horn(m_delay_head[i].get(), m_delay_body[i].get(), pred, body_res));
|
||||
insert(pred.get(), body_res.get());
|
||||
}
|
||||
m_delay_head.reset();
|
||||
m_delay_body.reset();
|
||||
|
||||
TRACE("mc", tout << m_funcs.size() << "\n"; model_smt2_pp(tout, m, *mr, 0););
|
||||
for (unsigned i = m_funcs.size(); i > 0; ) {
|
||||
--i;
|
||||
func_decl* h = m_funcs[i].get();
|
||||
expr_ref body(m_bodies[i].get(), m);
|
||||
unsigned arity = h->get_arity();
|
||||
add_default_false_interpretation(body, mr);
|
||||
SASSERT(m.is_bool(body));
|
||||
|
||||
TRACE("mc", tout << "eval: " << h->get_name() << "\n" << mk_pp(body, m) << "\n";);
|
||||
expr_ref tmp(body);
|
||||
mr->eval(tmp, body);
|
||||
|
||||
TRACE("mc", tout << "to:\n" << mk_pp(body, m) << "\n";);
|
||||
|
||||
if (arity == 0) {
|
||||
expr* e = mr->get_const_interp(h);
|
||||
if (e) {
|
||||
body = m.mk_or(e, body);
|
||||
}
|
||||
m_rewrite(body);
|
||||
mr->register_decl(h, body);
|
||||
}
|
||||
else {
|
||||
func_interp* f = mr->get_func_interp(h);
|
||||
if (f) {
|
||||
expr* e = f->get_else();
|
||||
body = m.mk_or(e, body);
|
||||
}
|
||||
else {
|
||||
f = alloc(func_interp, m, arity);
|
||||
mr->register_decl(h, f);
|
||||
}
|
||||
m_rewrite(body);
|
||||
f->set_else(body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
model_converter* horn_subsume_model_converter::translate(ast_translation & translator) {
|
||||
horn_subsume_model_converter* mc = alloc(horn_subsume_model_converter, translator.to());
|
||||
for (unsigned i = 0; i < m_funcs.size(); ++i) {
|
||||
mc->insert(translator(m_funcs[i].get()), translator(m_bodies[i].get()));
|
||||
}
|
||||
return mc;
|
||||
}
|
||||
|
83
src/tactic/horn_subsume_model_converter.h
Normal file
83
src/tactic/horn_subsume_model_converter.h
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
horn_subsume_model_converter.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Model converter for redundant Horn clauses.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2012-9-16
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
Notes:
|
||||
|
||||
|
||||
Subsumption transformation (remove Horn clause):
|
||||
|
||||
P(x) :- Body(x,y) Rules
|
||||
----------------------------
|
||||
Rules
|
||||
|
||||
|
||||
Model converter:
|
||||
|
||||
P(x) := P(x) or (exists y. Body(x,y))
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _HORN_SUBSUME_MODEL_CONVERTER_H_
|
||||
#define _HORN_SUBSUME_MODEL_CONVERTER_H_
|
||||
|
||||
#include "model_converter.h"
|
||||
#include "th_rewriter.h"
|
||||
|
||||
class horn_subsume_model_converter : public model_converter {
|
||||
ast_manager& m;
|
||||
func_decl_ref_vector m_funcs;
|
||||
expr_ref_vector m_bodies;
|
||||
th_rewriter m_rewrite;
|
||||
app_ref_vector m_delay_head;
|
||||
expr_ref_vector m_delay_body;
|
||||
|
||||
void add_default_false_interpretation(expr* e, model_ref& md);
|
||||
|
||||
struct add_default_proc {
|
||||
ast_manager& m;
|
||||
model_ref& m_md;
|
||||
add_default_proc(ast_manager& m, model_ref& md): m(m), m_md(md) {}
|
||||
void operator()(app* n);
|
||||
void operator()(expr* n) {}
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
horn_subsume_model_converter(ast_manager& m):
|
||||
m(m), m_funcs(m), m_bodies(m), m_rewrite(m),
|
||||
m_delay_head(m), m_delay_body(m) {}
|
||||
|
||||
bool mk_horn(expr* clause, func_decl_ref& pred, expr_ref& body);
|
||||
|
||||
bool mk_horn(app* head, expr* body, func_decl_ref& pred, expr_ref& body_res);
|
||||
|
||||
void insert(app* head, expr* body);
|
||||
|
||||
void insert(app* head, unsigned sz, expr* const* body);
|
||||
|
||||
void insert(func_decl* p, expr* body) { m_funcs.push_back(p); m_bodies.push_back(body); }
|
||||
|
||||
virtual void operator()(model_ref& m);
|
||||
|
||||
virtual model_converter * translate(ast_translation & translator);
|
||||
|
||||
ast_manager& get_manager() { return m; }
|
||||
|
||||
};
|
||||
|
||||
#endif
|
86
src/tactic/replace_proof_converter.cpp
Normal file
86
src/tactic/replace_proof_converter.cpp
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
replace_proof_converter.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Proof converter that replaces asserted by sub-proof.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2012-9-16
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "replace_proof_converter.h"
|
||||
#include "expr_functors.h"
|
||||
#include "ast_pp.h"
|
||||
#include "for_each_expr.h"
|
||||
|
||||
/**
|
||||
\brief Replace expressions by other expressions.
|
||||
|
||||
replace_map is caching, so inserting src |-> dst has no effect if
|
||||
src is a sub-expression of something that has already been visited.
|
||||
The assumption is that proof replacements are inserted into
|
||||
the replace_proof_converter in the order that they are introduced, so
|
||||
there are no such clashes.
|
||||
|
||||
map_proc is used as expr_replacer behaves differently
|
||||
when proof mode is turned on.
|
||||
*/
|
||||
class replace_map : public map_proc {
|
||||
public:
|
||||
replace_map(ast_manager& m): map_proc(m) {}
|
||||
|
||||
void insert(expr* src, expr* dst) {
|
||||
m_map.insert(src, dst, 0);
|
||||
}
|
||||
|
||||
void operator()(var* v) { visit(v); }
|
||||
void operator()(app* a) { if (!get_expr(a)) { reconstruct(a); } }
|
||||
void operator()(quantifier* q) { visit(q); }
|
||||
|
||||
void apply(expr_ref& e) {
|
||||
for_each_expr(*this, e);
|
||||
e = get_expr(e);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void replace_proof_converter::operator()(ast_manager & m, unsigned num_source,
|
||||
proof * const * source, proof_ref & result) {
|
||||
SASSERT(num_source == 1);
|
||||
replace_map replace(m);
|
||||
proof_ref p(m);
|
||||
expr_ref tmp(source[0], m), e(m), f(m);
|
||||
|
||||
// apply the substitution to the prefix before inserting it.
|
||||
for (unsigned i = 0; i < m_proofs.size(); ++i) {
|
||||
p = m_proofs[i].get();
|
||||
e = p;
|
||||
replace.apply(e);
|
||||
f = m.mk_asserted(m.get_fact(p));
|
||||
replace.insert(f, e);
|
||||
TRACE("proof_converter", tout << f->get_id() << " " << mk_pp(f, m) <<
|
||||
"\n|-> " << mk_pp(e, m) << "\n";);
|
||||
}
|
||||
replace.apply(tmp);
|
||||
TRACE("proof_converter", tout << mk_pp(source[0], m) << "\n";
|
||||
tout << mk_pp(tmp.get(), m) << "\n";);
|
||||
result = to_app(tmp);
|
||||
}
|
||||
|
||||
proof_converter * replace_proof_converter::translate(ast_translation & translator) {
|
||||
replace_proof_converter* rp = alloc(replace_proof_converter, m);
|
||||
for (unsigned i = 0; i < m_proofs.size(); ++i) {
|
||||
rp->insert(translator(m_proofs[i].get()));
|
||||
}
|
||||
return rp;
|
||||
}
|
||||
|
50
src/tactic/replace_proof_converter.h
Normal file
50
src/tactic/replace_proof_converter.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
replace_proof_converter.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Proof converter to replace asserted leaves by proofs.
|
||||
|
||||
Given a proof P with occurrences of [asserted fml]
|
||||
Replace [asserted fml] by proofs whose conclusions are fml.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2012-9-16
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _REPLACE_PROOF_CONVERTER_H_
|
||||
#define _REPLACE_PROOF_CONVERTER_H_
|
||||
|
||||
#include "proof_converter.h"
|
||||
|
||||
class replace_proof_converter : public proof_converter {
|
||||
ast_manager& m;
|
||||
proof_ref_vector m_proofs;
|
||||
public:
|
||||
|
||||
replace_proof_converter(ast_manager& m): m(m), m_proofs(m) {}
|
||||
|
||||
virtual ~replace_proof_converter() {}
|
||||
|
||||
virtual void operator()(ast_manager & m, unsigned num_source, proof * const * source, proof_ref & result);
|
||||
|
||||
virtual proof_converter * translate(ast_translation & translator);
|
||||
|
||||
void insert(proof* p) { m_proofs.push_back(p); }
|
||||
|
||||
ast_manager& get_manager() { return m; }
|
||||
|
||||
// run the replacements the inverse direction.
|
||||
void invert() { m_proofs.reverse(); }
|
||||
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue