mirror of
https://github.com/Z3Prover/z3
synced 2025-04-24 01:25:31 +00:00
model refactor (#4723)
* refactor model fixing Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * missing cond macro Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * file Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * file Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * add macros dependency Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * deps and debug Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * add dependency to normal forms Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * build issues Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * compile Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fix leal regression * complete model fixer Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fold back private functionality to model_finder Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * avoid duplicate fixed callbacks Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
6cc52e04c3
commit
fa58a36b9f
42 changed files with 2060 additions and 1494 deletions
|
@ -107,6 +107,11 @@ namespace euf {
|
|||
enode* n = enode::mk(m_region, f, num_args, args);
|
||||
m_nodes.push_back(n);
|
||||
m_exprs.push_back(f);
|
||||
if (is_app(f) && num_args > 0) {
|
||||
unsigned id = to_app(f)->get_decl()->get_decl_id();
|
||||
m_decl2enodes.reserve(id+1);
|
||||
m_decl2enodes[id].push_back(n);
|
||||
}
|
||||
m_expr2enode.setx(f->get_id(), n, nullptr);
|
||||
push_node(n);
|
||||
for (unsigned i = 0; i < num_args; ++i)
|
||||
|
@ -114,9 +119,15 @@ namespace euf {
|
|||
return n;
|
||||
}
|
||||
|
||||
enode_vector const& egraph::enodes_of(func_decl* f) {
|
||||
unsigned id = f->get_decl_id();
|
||||
if (id < m_decl2enodes.size())
|
||||
return m_decl2enodes[id];
|
||||
return m_empty_enodes;
|
||||
}
|
||||
|
||||
enode_bool_pair egraph::insert_table(enode* p) {
|
||||
auto rc = m_table.insert(p);
|
||||
enode* p_other = rc.first;
|
||||
p->m_cg = rc.first;
|
||||
return rc;
|
||||
}
|
||||
|
@ -338,6 +349,8 @@ namespace euf {
|
|||
|
||||
m_expr2enode[e->get_id()] = nullptr;
|
||||
n->~enode();
|
||||
if (is_app(e) && n->num_args() > 0)
|
||||
m_decl2enodes[to_app(e)->get_decl()->get_decl_id()].pop_back();
|
||||
m_nodes.pop_back();
|
||||
m_exprs.pop_back();
|
||||
};
|
||||
|
|
|
@ -141,7 +141,7 @@ namespace euf {
|
|||
tag(tag_t::is_value_assignment), r1(n), n1(nullptr), qhead(0) {}
|
||||
};
|
||||
ast_manager& m;
|
||||
svector<to_merge> m_to_merge;
|
||||
svector<to_merge> m_to_merge;
|
||||
etable m_table;
|
||||
region m_region;
|
||||
svector<update_record> m_updates;
|
||||
|
@ -150,6 +150,8 @@ namespace euf {
|
|||
enode* m_tmp_eq { nullptr };
|
||||
enode_vector m_nodes;
|
||||
expr_ref_vector m_exprs;
|
||||
vector<enode_vector> m_decl2enodes;
|
||||
enode_vector m_empty_enodes;
|
||||
unsigned m_num_scopes { 0 };
|
||||
bool m_inconsistent { false };
|
||||
enode *m_n1 { nullptr };
|
||||
|
@ -214,6 +216,7 @@ namespace euf {
|
|||
~egraph();
|
||||
enode* find(expr* f) { return m_expr2enode.get(f->get_id(), nullptr); }
|
||||
enode* mk(expr* f, unsigned n, enode *const* args);
|
||||
enode_vector const& enodes_of(func_decl* f);
|
||||
void push() { ++m_num_scopes; }
|
||||
void pop(unsigned num_scopes);
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace euf {
|
|||
|
||||
// one table per func_decl implementation
|
||||
unsigned etable::cg_hash::operator()(enode * n) const {
|
||||
SASSERT(decl(n)->is_flat_associative() || n->num_args() >= 3);
|
||||
SASSERT(n->get_decl()->is_flat_associative() || n->num_args() >= 3);
|
||||
unsigned a, b, c;
|
||||
a = b = 0x9e3779b9;
|
||||
c = 11;
|
||||
|
@ -50,7 +50,7 @@ namespace euf {
|
|||
}
|
||||
|
||||
bool etable::cg_eq::operator()(enode * n1, enode * n2) const {
|
||||
SASSERT(decl(n1) == decl(n2));
|
||||
SASSERT(n1->get_decl() == n2->get_decl());
|
||||
unsigned num = n1->num_args();
|
||||
if (num != n2->num_args()) {
|
||||
return false;
|
||||
|
@ -96,7 +96,7 @@ namespace euf {
|
|||
}
|
||||
|
||||
unsigned etable::set_table_id(enode * n) {
|
||||
func_decl * f = decl(n);
|
||||
func_decl * f = n->get_decl();
|
||||
unsigned tid;
|
||||
decl_info d(f, n->num_args());
|
||||
if (!m_func_decl2id.find(d, tid)) {
|
||||
|
|
|
@ -24,8 +24,6 @@ namespace euf {
|
|||
|
||||
// one table per function symbol
|
||||
|
||||
static func_decl* decl(enode* n) { return n->get_decl(); }
|
||||
|
||||
|
||||
/**
|
||||
\brief Congruence table.
|
||||
|
@ -45,7 +43,7 @@ namespace euf {
|
|||
bool operator()(enode * n1, enode * n2) const {
|
||||
SASSERT(n1->num_args() == 1);
|
||||
SASSERT(n2->num_args() == 1);
|
||||
SASSERT(decl(n1) == decl(n2));
|
||||
SASSERT(n1->get_decl() == n2->get_decl());
|
||||
return get_root(n1, 0) == get_root(n2, 0);
|
||||
}
|
||||
};
|
||||
|
@ -63,7 +61,7 @@ namespace euf {
|
|||
bool operator()(enode * n1, enode * n2) const {
|
||||
SASSERT(n1->num_args() == 2);
|
||||
SASSERT(n2->num_args() == 2);
|
||||
SASSERT(decl(n1) == decl(n2));
|
||||
SASSERT(n1->get_decl() == n2->get_decl());
|
||||
return
|
||||
get_root(n1, 0) == get_root(n2, 0) &&
|
||||
get_root(n1, 1) == get_root(n2, 1);
|
||||
|
@ -90,7 +88,7 @@ namespace euf {
|
|||
SASSERT(n1->num_args() == 2);
|
||||
SASSERT(n2->num_args() == 2);
|
||||
|
||||
SASSERT(decl(n1) == decl(n2));
|
||||
SASSERT(n1->get_decl() == n2->get_decl());
|
||||
enode* c1_1 = get_root(n1, 0);
|
||||
enode* c1_2 = get_root(n1, 1);
|
||||
enode* c2_1 = get_root(n2, 0);
|
||||
|
|
|
@ -70,21 +70,4 @@ public:
|
|||
array_model convert_array_func_interp(model_core * mc, func_decl * f, func_decl * bv_f);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class fpa2bv_conversion_trail_elem : public trail<T> {
|
||||
ast_manager& m;
|
||||
obj_map<expr, expr*>& m_map;
|
||||
expr_ref key;
|
||||
public:
|
||||
fpa2bv_conversion_trail_elem(ast_manager& m, obj_map<expr, expr*>& map, expr* e) :
|
||||
m(m), m_map(map), key(e, m) { }
|
||||
~fpa2bv_conversion_trail_elem() override { }
|
||||
void undo(T& s) override {
|
||||
expr* val = m_map.find(key);
|
||||
m_map.remove(key);
|
||||
m.dec_ref(key);
|
||||
m.dec_ref(val);
|
||||
key = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -32,11 +32,11 @@ Notes:
|
|||
fpa2bv_converter::fpa2bv_converter(ast_manager & m) :
|
||||
m(m),
|
||||
m_simp(m),
|
||||
m_util(m),
|
||||
m_bv_util(m),
|
||||
m_arith_util(m),
|
||||
m_dt_util(m),
|
||||
m_seq_util(m),
|
||||
m_util(m),
|
||||
m_mpf_manager(m_util.fm()),
|
||||
m_mpz_manager(m_mpf_manager.mpz_manager()),
|
||||
m_hi_fp_unspecified(true),
|
||||
|
|
|
@ -2,6 +2,7 @@ z3_add_component(macros
|
|||
SOURCES
|
||||
macro_finder.cpp
|
||||
macro_manager.cpp
|
||||
quantifier_macro_info.cpp
|
||||
macro_util.cpp
|
||||
quasi_macros.cpp
|
||||
COMPONENT_DEPENDENCIES
|
||||
|
|
72
src/ast/macros/cond_macro.h
Normal file
72
src/ast/macros/cond_macro.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
cond_macro.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Class for maintaining conditional macros
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2010-12-17.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#pragma once
|
||||
#include "ast/ast_ll_pp.h"
|
||||
|
||||
class cond_macro {
|
||||
protected:
|
||||
func_decl * m_f;
|
||||
expr_ref m_def;
|
||||
expr_ref m_cond;
|
||||
bool m_ineq;
|
||||
bool m_satisfy_atom;
|
||||
bool m_hint;
|
||||
unsigned m_weight;
|
||||
public:
|
||||
cond_macro(ast_manager & m, func_decl * f, expr * def, expr * cond, bool ineq, bool satisfy_atom, bool hint, unsigned weight):
|
||||
m_f(f),
|
||||
m_def(def,m),
|
||||
m_cond(cond, m),
|
||||
m_ineq(ineq),
|
||||
m_satisfy_atom(satisfy_atom),
|
||||
m_hint(hint),
|
||||
m_weight(weight) {
|
||||
SASSERT(!m_hint || !m_cond);
|
||||
}
|
||||
|
||||
~cond_macro() {
|
||||
}
|
||||
|
||||
func_decl * get_f() const { return m_f; }
|
||||
|
||||
expr * get_def() const { return m_def; }
|
||||
|
||||
expr * get_cond() const { return m_cond; }
|
||||
|
||||
bool is_unconditional() const { return !m_cond || m_cond.m().is_true(m_cond); }
|
||||
|
||||
bool satisfy_atom() const { return m_satisfy_atom; }
|
||||
|
||||
bool is_hint() const { return m_hint; }
|
||||
|
||||
bool is_equal(cond_macro const * other) const {
|
||||
return m_f == other->m_f && m_def == other->m_def && m_cond == other->m_cond;
|
||||
}
|
||||
|
||||
std::ostream& display(std::ostream & out) const {
|
||||
out << "[" << m_f->get_name() << " -> " << mk_bounded_pp(m_def, m_def.m(), 6);
|
||||
if (m_hint)
|
||||
out << " *hint*";
|
||||
else
|
||||
out << " when " << mk_bounded_pp(m_cond, m_cond.m(), 6);
|
||||
return out << "] weight: " << m_weight;
|
||||
}
|
||||
|
||||
unsigned get_weight() const { return m_weight; }
|
||||
};
|
66
src/ast/macros/quantifier_macro_info.cpp
Normal file
66
src/ast/macros/quantifier_macro_info.cpp
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
quantifier_macro_info.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Macro solving utilities
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2010-12-17.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/macros/quantifier_macro_info.h"
|
||||
|
||||
quantifier_macro_info::quantifier_macro_info(ast_manager& m, quantifier* q) :
|
||||
m(m),
|
||||
m_flat_q(q, m),
|
||||
m_is_auf(true),
|
||||
m_has_x_eq_y(false),
|
||||
m_the_one(m) {
|
||||
SASSERT(is_forall(q));
|
||||
collect_macro_candidates(q);
|
||||
}
|
||||
|
||||
void quantifier_macro_info::collect_macro_candidates(quantifier* q) {
|
||||
macro_util mutil(m);
|
||||
macro_util::macro_candidates candidates(m);
|
||||
mutil.collect_macro_candidates(q, candidates);
|
||||
unsigned num_candidates = candidates.size();
|
||||
for (unsigned i = 0; i < num_candidates; i++) {
|
||||
cond_macro* mc = alloc(cond_macro, m, candidates.get_f(i), candidates.get_def(i), candidates.get_cond(i),
|
||||
candidates.ineq(i), candidates.satisfy_atom(i), candidates.hint(i), q->get_weight());
|
||||
insert_macro(mc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool quantifier_macro_info::unary_function_fragment() const {
|
||||
unsigned sz = m_ng_decls.size();
|
||||
if (sz > 1)
|
||||
return false;
|
||||
if (sz == 0)
|
||||
return true;
|
||||
func_decl* f = *(m_ng_decls.begin());
|
||||
return f->get_arity() == 1;
|
||||
}
|
||||
|
||||
std::ostream& quantifier_macro_info::display(std::ostream& out) const {
|
||||
out << "info for quantifier:\n" << mk_pp(m_flat_q, m) << "\n";
|
||||
out << "IS_AUF: " << m_is_auf << ", has x=y: " << m_has_x_eq_y << "\n";
|
||||
out << "unary function fragment: " << unary_function_fragment() << "\n";
|
||||
out << "ng decls: ";
|
||||
for (func_decl* f : m_ng_decls)
|
||||
out << f->get_name() << " ";
|
||||
out << "\nmacros:\n";
|
||||
for (cond_macro* cm : m_cond_macros)
|
||||
cm->display(out << " ") << "\n";
|
||||
return out;
|
||||
}
|
55
src/ast/macros/quantifier_macro_info.h
Normal file
55
src/ast/macros/quantifier_macro_info.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
quantifier_macro_info.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Macro solving utilities
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2010-12-17.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#pragma once
|
||||
#include "util/scoped_ptr_vector.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
#include "ast/macros/cond_macro.h"
|
||||
#include "ast/macros/macro_util.h"
|
||||
#include "ast/func_decl_dependencies.h"
|
||||
|
||||
/**
|
||||
\brief Store relevant information regarding a particular universal quantifier.
|
||||
The information is used to (try to) build a model that satisfy the universal quantifier.
|
||||
*/
|
||||
class quantifier_macro_info {
|
||||
protected:
|
||||
ast_manager& m;
|
||||
quantifier_ref m_flat_q; // (flattened) quantifier
|
||||
bool m_is_auf;
|
||||
bool m_has_x_eq_y;
|
||||
func_decl_set m_ng_decls; // declarations used in non-ground applications (basic_family operators are ignored here).
|
||||
scoped_ptr_vector<cond_macro> m_cond_macros;
|
||||
func_decl_ref m_the_one; // the macro head used to satisfy the quantifier. this is useful for model checking
|
||||
void collect_macro_candidates(quantifier* q);
|
||||
public:
|
||||
quantifier_macro_info(ast_manager& m, quantifier* q);
|
||||
virtual ~quantifier_macro_info() {}
|
||||
bool is_auf() const { return m_is_auf; }
|
||||
quantifier* get_flat_q() const { return m_flat_q; }
|
||||
bool has_cond_macros() const { return !m_cond_macros.empty(); }
|
||||
scoped_ptr_vector<cond_macro> const& macros() const { return m_cond_macros; }
|
||||
void set_the_one(func_decl* f) { m_the_one = f; }
|
||||
func_decl* get_the_one() const { return m_the_one; }
|
||||
bool contains_ng_decl(func_decl* f) const { return m_ng_decls.contains(f); }
|
||||
func_decl_set const& get_ng_decls() const { return m_ng_decls; }
|
||||
virtual void reset_the_one() { m_the_one = nullptr; }
|
||||
void insert_macro(cond_macro* m) { m_cond_macros.push_back(m); }
|
||||
bool unary_function_fragment() const;
|
||||
virtual std::ostream& display(std::ostream& out) const;
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue