3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-05-01 04:45:52 +00:00

revamp configuration parameter names for fixedpoint

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2014-08-18 01:03:11 -07:00
parent f748a03ac7
commit ddbff6f77b
12 changed files with 358 additions and 246 deletions

View file

@ -81,7 +81,7 @@ namespace pdr {
ctx(ctx), m_head(head, m),
m_sig(m), m_solver(pm, ctx.get_params(), head->get_name()),
m_invariants(m), m_transition(m), m_initial_state(m),
m_reachable(pm, (datalog::PDR_CACHE_MODE)ctx.get_params().cache_mode()) {}
m_reachable(pm, (datalog::PDR_CACHE_MODE)ctx.get_params().pdr_cache_mode()) {}
pred_transformer::~pred_transformer() {
rule2inst::iterator it2 = m_rule2inst.begin(), end2 = m_rule2inst.end();
@ -738,6 +738,11 @@ namespace pdr {
m_closed = true;
}
void model_node::reopen() {
SASSERT(m_closed);
m_closed = false;
}
static bool is_ini(datalog::rule const& r) {
return r.get_uninterpreted_tail_size() == 0;
}
@ -747,6 +752,7 @@ namespace pdr {
return const_cast<datalog::rule*>(m_rule);
}
// only initial states are not set by the PDR search.
SASSERT(m_model.get());
datalog::rule const& rl1 = pt().find_rule(*m_model);
if (is_ini(rl1)) {
set_rule(&rl1);
@ -866,9 +872,10 @@ namespace pdr {
}
void model_search::add_leaf(model_node& n) {
unsigned& count = cache(n).insert_if_not_there2(n.state(), 0)->get_data().m_value;
++count;
if (count == 1 || is_repeated(n)) {
model_nodes ns;
model_nodes& nodes = cache(n).insert_if_not_there2(n.state(), ns)->get_data().m_value;
nodes.push_back(&n);
if (nodes.size() == 1 || is_repeated(n)) {
set_leaf(n);
}
else {
@ -877,7 +884,7 @@ namespace pdr {
}
void model_search::set_leaf(model_node& n) {
erase_children(n);
erase_children(n, true);
SASSERT(n.is_open());
enqueue_leaf(n);
}
@ -899,7 +906,7 @@ namespace pdr {
set_leaf(*root);
}
obj_map<expr, unsigned>& model_search::cache(model_node const& n) {
obj_map<expr, ptr_vector<model_node> >& model_search::cache(model_node const& n) {
unsigned l = n.orig_level();
if (l >= m_cache.size()) {
m_cache.resize(l + 1);
@ -907,7 +914,7 @@ namespace pdr {
return m_cache[l];
}
void model_search::erase_children(model_node& n) {
void model_search::erase_children(model_node& n, bool backtrack) {
ptr_vector<model_node> todo, nodes;
todo.append(n.children());
erase_leaf(n);
@ -918,13 +925,20 @@ namespace pdr {
nodes.push_back(m);
todo.append(m->children());
erase_leaf(*m);
remove_node(*m);
remove_node(*m, backtrack);
}
std::for_each(nodes.begin(), nodes.end(), delete_proc<model_node>());
}
void model_search::remove_node(model_node& n) {
if (0 == --cache(n).find(n.state())) {
void model_search::remove_node(model_node& n, bool backtrack) {
model_nodes& nodes = cache(n).find(n.state());
nodes.erase(&n);
if (nodes.size() > 0 && n.is_open() && backtrack) {
for (unsigned i = 0; i < nodes.size(); ++i) {
nodes[i]->reopen();
}
}
if (nodes.empty()) {
cache(n).remove(n.state());
}
}
@ -971,6 +985,9 @@ namespace pdr {
if (n->get_model_ptr()) {
models.insert(n->state(), n->get_model_ptr());
rules.insert(n->state(), n->get_rule());
pred_transformer& pt = n->pt();
context& ctx = pt.get_context();
datalog::context& dctx = ctx.get_context();
}
todo.pop_back();
todo.append(n->children().size(), n->children().c_ptr());
@ -981,12 +998,18 @@ namespace pdr {
model_node* n = todo.back();
model* md = 0;
ast_manager& m = n->pt().get_manager();
if (!n->get_model_ptr() && models.find(n->state(), md)) {
TRACE("pdr", tout << mk_pp(n->state(), m) << "\n";);
model_ref mr(md);
n->set_model(mr);
datalog::rule const* rule = rules.find(n->state());
n->set_rule(rule);
if (!n->get_model_ptr()) {
if (models.find(n->state(), md)) {
TRACE("pdr", tout << mk_pp(n->state(), m) << "\n";);
model_ref mr(md);
n->set_model(mr);
datalog::rule const* rule = rules.find(n->state());
n->set_rule(rule);
}
else {
IF_VERBOSE(1, n->display(verbose_stream() << "no model:\n", 0);
verbose_stream() << mk_pp(n->state(), m) << "\n";);
}
}
todo.pop_back();
todo.append(n->children().size(), n->children().c_ptr());
@ -1205,8 +1228,8 @@ namespace pdr {
void model_search::reset() {
if (m_root) {
erase_children(*m_root);
remove_node(*m_root);
erase_children(*m_root, false);
remove_node(*m_root, false);
dealloc(m_root);
m_root = 0;
}
@ -1239,10 +1262,10 @@ namespace pdr {
m_params(params),
m(m),
m_context(0),
m_pm(m_fparams, params.max_num_contexts(), m),
m_pm(m_fparams, params.pdr_max_num_contexts(), m),
m_query_pred(m),
m_query(0),
m_search(m_params.bfs_model_search()),
m_search(m_params.pdr_bfs_model_search(), m),
m_last_result(l_undef),
m_inductive_lvl(0),
m_expanded_lvl(0),
@ -1470,93 +1493,108 @@ namespace pdr {
}
}
};
void context::validate() {
if (!m_params.validate_result()) {
return;
}
void context::validate_proof() {
std::stringstream msg;
switch(m_last_result) {
case l_true: {
proof_ref pr = get_proof();
proof_checker checker(m);
expr_ref_vector side_conditions(m);
bool ok = checker.check(pr, side_conditions);
if (!ok) {
msg << "proof validation failed";
proof_ref pr = get_proof();
proof_checker checker(m);
expr_ref_vector side_conditions(m);
bool ok = checker.check(pr, side_conditions);
if (!ok) {
msg << "proof validation failed";
IF_VERBOSE(0, verbose_stream() << msg.str() << "\n";);
throw default_exception(msg.str());
}
for (unsigned i = 0; i < side_conditions.size(); ++i) {
expr* cond = side_conditions[i].get();
expr_ref tmp(m);
tmp = m.mk_not(cond);
IF_VERBOSE(2, verbose_stream() << "checking side-condition:\n" << mk_pp(cond, m) << "\n";);
smt::kernel solver(m, get_fparams());
solver.assert_expr(tmp);
lbool res = solver.check();
if (res != l_false) {
msg << "rule validation failed when checking: " << mk_pp(cond, m);
IF_VERBOSE(0, verbose_stream() << msg.str() << "\n";);
throw default_exception(msg.str());
}
for (unsigned i = 0; i < side_conditions.size(); ++i) {
expr* cond = side_conditions[i].get();
expr_ref tmp(m);
tmp = m.mk_not(cond);
IF_VERBOSE(2, verbose_stream() << "checking side-condition:\n" << mk_pp(cond, m) << "\n";);
}
}
}
void context::validate_search() {
expr_ref tr = m_search.get_trace(*this);
// TBD: tr << "\n";
}
void context::validate_model() {
std::stringstream msg;
expr_ref_vector refs(m);
expr_ref tmp(m);
model_ref model;
vector<relation_info> rs;
model_converter_ref mc;
get_level_property(m_inductive_lvl, refs, rs);
inductive_property ex(m, mc, rs);
ex.to_model(model);
decl2rel::iterator it = m_rels.begin(), end = m_rels.end();
var_subst vs(m, false);
for (; it != end; ++it) {
ptr_vector<datalog::rule> const& rules = it->m_value->rules();
for (unsigned i = 0; i < rules.size(); ++i) {
datalog::rule& r = *rules[i];
model->eval(r.get_head(), tmp);
expr_ref_vector fmls(m);
fmls.push_back(m.mk_not(tmp));
unsigned utsz = r.get_uninterpreted_tail_size();
unsigned tsz = r.get_tail_size();
for (unsigned j = 0; j < utsz; ++j) {
model->eval(r.get_tail(j), tmp);
fmls.push_back(tmp);
}
for (unsigned j = utsz; j < tsz; ++j) {
fmls.push_back(r.get_tail(j));
}
tmp = m.mk_and(fmls.size(), fmls.c_ptr());
ptr_vector<sort> sorts;
svector<symbol> names;
get_free_vars(tmp, sorts);
for (unsigned i = 0; i < sorts.size(); ++i) {
if (!sorts[i]) {
sorts[i] = m.mk_bool_sort();
}
names.push_back(symbol(i));
}
sorts.reverse();
if (!sorts.empty()) {
tmp = m.mk_exists(sorts.size(), sorts.c_ptr(), names.c_ptr(), tmp);
}
smt::kernel solver(m, get_fparams());
solver.assert_expr(tmp);
lbool res = solver.check();
if (res != l_false) {
msg << "rule validation failed when checking: " << mk_pp(cond, m);
msg << "rule validation failed when checking: " << mk_pp(tmp, m);
IF_VERBOSE(0, verbose_stream() << msg.str() << "\n";);
throw default_exception(msg.str());
}
}
break;
}
case l_false: {
expr_ref_vector refs(m);
expr_ref tmp(m);
model_ref model;
vector<relation_info> rs;
model_converter_ref mc;
get_level_property(m_inductive_lvl, refs, rs);
inductive_property ex(m, mc, rs);
ex.to_model(model);
decl2rel::iterator it = m_rels.begin(), end = m_rels.end();
var_subst vs(m, false);
for (; it != end; ++it) {
ptr_vector<datalog::rule> const& rules = it->m_value->rules();
for (unsigned i = 0; i < rules.size(); ++i) {
datalog::rule& r = *rules[i];
model->eval(r.get_head(), tmp);
expr_ref_vector fmls(m);
fmls.push_back(m.mk_not(tmp));
unsigned utsz = r.get_uninterpreted_tail_size();
unsigned tsz = r.get_tail_size();
for (unsigned j = 0; j < utsz; ++j) {
model->eval(r.get_tail(j), tmp);
fmls.push_back(tmp);
}
for (unsigned j = utsz; j < tsz; ++j) {
fmls.push_back(r.get_tail(j));
}
tmp = m.mk_and(fmls.size(), fmls.c_ptr());
ptr_vector<sort> sorts;
svector<symbol> names;
get_free_vars(tmp, sorts);
for (unsigned i = 0; i < sorts.size(); ++i) {
if (!sorts[i]) {
sorts[i] = m.mk_bool_sort();
}
names.push_back(symbol(i));
}
sorts.reverse();
if (!sorts.empty()) {
tmp = m.mk_exists(sorts.size(), sorts.c_ptr(), names.c_ptr(), tmp);
}
smt::kernel solver(m, get_fparams());
solver.assert_expr(tmp);
lbool res = solver.check();
if (res != l_false) {
msg << "rule validation failed when checking: " << mk_pp(tmp, m);
IF_VERBOSE(0, verbose_stream() << msg.str() << "\n";);
throw default_exception(msg.str());
}
}
}
break;
}
}
void context::validate() {
if (!m_params.pdr_validate_result()) {
return;
}
switch(m_last_result) {
case l_true:
if (m_params.generate_proof_trace()) {
validate_proof();
}
validate_search();
break;
case l_false:
validate_model();
break;
default:
break;
}
@ -1570,7 +1608,7 @@ namespace pdr {
void context::init_core_generalizers(datalog::rule_set& rules) {
reset_core_generalizers();
classifier_proc classify(m, rules);
bool use_mc = m_params.use_multicore_generalizer();
bool use_mc = m_params.pdr_use_multicore_generalizer();
if (use_mc) {
m_core_generalizers.push_back(alloc(core_multi_generalizer, *this, 0));
}
@ -1580,9 +1618,9 @@ namespace pdr {
m_fparams.m_arith_auto_config_simplex = true;
m_fparams.m_arith_propagate_eqs = false;
m_fparams.m_arith_eager_eq_axioms = false;
if (m_params.use_utvpi() &&
!m_params.use_convex_closure_generalizer() &&
!m_params.use_convex_interior_generalizer()) {
if (m_params.pdr_utvpi() &&
!m_params.pdr_use_convex_closure_generalizer() &&
!m_params.pdr_use_convex_interior_generalizer()) {
if (classify.is_dl()) {
m_fparams.m_arith_mode = AS_DIFF_LOGIC;
m_fparams.m_arith_expand_eqs = true;
@ -1594,19 +1632,19 @@ namespace pdr {
}
}
}
if (m_params.use_convex_closure_generalizer()) {
if (m_params.pdr_use_convex_closure_generalizer()) {
m_core_generalizers.push_back(alloc(core_convex_hull_generalizer, *this, true));
}
if (m_params.use_convex_interior_generalizer()) {
if (m_params.pdr_use_convex_interior_generalizer()) {
m_core_generalizers.push_back(alloc(core_convex_hull_generalizer, *this, false));
}
if (!use_mc && m_params.use_inductive_generalizer()) {
if (!use_mc && m_params.pdr_use_inductive_generalizer()) {
m_core_generalizers.push_back(alloc(core_bool_inductive_generalizer, *this, 0));
}
if (m_params.inductive_reachability_check()) {
if (m_params.pdr_inductive_reachability_check()) {
m_core_generalizers.push_back(alloc(core_induction_generalizer, *this));
}
if (m_params.use_arith_inductive_generalizer()) {
if (m_params.pdr_use_arith_inductive_generalizer()) {
m_core_generalizers.push_back(alloc(core_arith_inductive_generalizer, *this));
}
@ -1824,7 +1862,7 @@ namespace pdr {
m_expanded_lvl = n.level();
}
pred_transformer::scoped_farkas sf (n.pt(), m_params.use_farkas());
pred_transformer::scoped_farkas sf (n.pt(), m_params.pdr_farkas());
if (n.pt().is_reachable(n.state())) {
TRACE("pdr", tout << "reachable\n";);
close_node(n);
@ -1865,7 +1903,7 @@ namespace pdr {
n.pt().add_property(ncore, uses_level?n.level():infty_level);
}
CASSERT("pdr",n.level() == 0 || check_invariant(n.level()-1));
m_search.backtrack_level(!found_invariant && m_params.flexible_trace(), n);
m_search.backtrack_level(!found_invariant && m_params.pdr_flexible_trace(), n);
break;
}
case l_undef: {
@ -1892,7 +1930,7 @@ namespace pdr {
}
void context::propagate(unsigned max_prop_lvl) {
if (m_params.simplify_formulas_pre()) {
if (m_params.pdr_simplify_formulas_pre()) {
simplify_formulas();
}
for (unsigned lvl = m_expanded_lvl; lvl <= max_prop_lvl; lvl++) {
@ -1911,7 +1949,7 @@ namespace pdr {
throw inductive_exception();
}
}
if (m_params.simplify_formulas_post()) {
if (m_params.pdr_simplify_formulas_post()) {
simplify_formulas();
}
}
@ -1959,16 +1997,18 @@ namespace pdr {
*/
void context::create_children(model_node& n) {
SASSERT(n.level() > 0);
bool use_model_generalizer = m_params.use_model_generalizer();
bool use_model_generalizer = m_params.pdr_use_model_generalizer();
scoped_no_proof _sc(m);
pred_transformer& pt = n.pt();
model_ref M = n.get_model_ptr();
SASSERT(M.get());
datalog::rule const& r = pt.find_rule(*M);
expr* T = pt.get_transition(r);
expr* phi = n.state();
n.set_rule(&r);
TRACE("pdr",
tout << "Model:\n";

View file

@ -124,6 +124,7 @@ namespace pdr {
unsigned get_num_levels() { return m_levels.size(); }
expr_ref get_cover_delta(func_decl* p_orig, int level);
void add_cover(unsigned level, expr* property);
context& get_context() { return ctx; }
std::ostream& display(std::ostream& strm) const;
@ -231,6 +232,7 @@ namespace pdr {
}
void set_closed();
void reopen();
void set_pre_closed() { m_closed = true; }
void reset() { m_children.reset(); }
@ -243,19 +245,21 @@ namespace pdr {
};
class model_search {
typedef ptr_vector<model_node> model_nodes;
ast_manager& m;
bool m_bfs;
model_node* m_root;
std::deque<model_node*> m_leaves;
vector<obj_map<expr, unsigned> > m_cache;
obj_map<expr, unsigned>& cache(model_node const& n);
void erase_children(model_node& n);
vector<obj_map<expr, model_nodes > > m_cache;
obj_map<expr, model_nodes>& cache(model_node const& n);
void erase_children(model_node& n, bool backtrack);
void erase_leaf(model_node& n);
void remove_node(model_node& n);
void remove_node(model_node& n, bool backtrack);
void enqueue_leaf(model_node& n); // add leaf to priority queue.
void update_models();
public:
model_search(bool bfs): m_bfs(bfs), m_root(0) {}
model_search(bool bfs, ast_manager& m): m(m), m_bfs(bfs), m_root(0) {}
~model_search();
void reset();
@ -267,7 +271,7 @@ namespace pdr {
void set_root(model_node* n);
model_node& get_root() const { return *m_root; }
std::ostream& display(std::ostream& out) const;
expr_ref get_trace(context const& ctx);
expr_ref get_trace(context const& ctx);
proof_ref get_proof_trace(context const& ctx);
void backtrack_level(bool uses_level, model_node& n);
};
@ -355,6 +359,9 @@ namespace pdr {
void reset_core_generalizers();
void validate();
void validate_proof();
void validate_search();
void validate_model();
public:

View file

@ -105,7 +105,7 @@ lbool dl_interface::query(expr * query) {
apply_default_transformation(m_ctx);
if (m_ctx.get_params().slice()) {
if (m_ctx.get_params().xform_slice()) {
datalog::rule_transformer transformer(m_ctx);
datalog::mk_slice* slice = alloc(datalog::mk_slice, m_ctx);
transformer.register_plugin(slice);
@ -122,12 +122,12 @@ lbool dl_interface::query(expr * query) {
}
}
if (m_ctx.get_params().unfold_rules() > 0) {
unsigned num_unfolds = m_ctx.get_params().unfold_rules();
if (m_ctx.get_params().xform_unfold_rules() > 0) {
unsigned num_unfolds = m_ctx.get_params().xform_unfold_rules();
datalog::rule_transformer transf1(m_ctx), transf2(m_ctx);
transf1.register_plugin(alloc(datalog::mk_coalesce, m_ctx));
transf2.register_plugin(alloc(datalog::mk_unfold, m_ctx));
if (m_ctx.get_params().coalesce_rules()) {
if (m_ctx.get_params().xform_coalesce_rules()) {
m_ctx.transform_rules(transf1);
}
while (num_unfolds > 0) {
@ -176,7 +176,7 @@ expr_ref dl_interface::get_cover_delta(int level, func_decl* pred_orig) {
}
void dl_interface::add_cover(int level, func_decl* pred, expr* property) {
if (m_ctx.get_params().slice()) {
if (m_ctx.get_params().xform_slice()) {
throw default_exception("Covers are incompatible with slicing. Disable slicing before using covers");
}
m_context->add_cover(level, pred, property);

View file

@ -231,7 +231,7 @@ namespace pdr {
m(pm.get_manager()),
m_pm(pm),
m_name(name),
m_try_minimize_core(p.try_minimize_core()),
m_try_minimize_core(p.pdr_try_minimize_core()),
m_ctx(pm.mk_fresh()),
m_pos_level_atoms(m),
m_neg_level_atoms(m),