mirror of
https://github.com/Z3Prover/z3
synced 2025-06-05 21:53:23 +00:00
Merge pull request #505 from MikolasJanota/tmp
Improvement in lazy ackermannization.
This commit is contained in:
commit
62a54cf154
4 changed files with 44 additions and 18 deletions
|
@ -38,6 +38,7 @@ public:
|
||||||
tactic_report report("ackermannize", *g);
|
tactic_report report("ackermannize", *g);
|
||||||
fail_if_unsat_core_generation("ackermannize", g);
|
fail_if_unsat_core_generation("ackermannize", g);
|
||||||
fail_if_proof_generation("ackermannize", g);
|
fail_if_proof_generation("ackermannize", g);
|
||||||
|
TRACE("ackermannize", g->display(tout << "in\n"););
|
||||||
|
|
||||||
expr_ref_vector flas(m);
|
expr_ref_vector flas(m);
|
||||||
const unsigned sz = g->size();
|
const unsigned sz = g->size();
|
||||||
|
@ -48,6 +49,7 @@ public:
|
||||||
goal_ref resg(alloc(goal, *g, true));
|
goal_ref resg(alloc(goal, *g, true));
|
||||||
const bool success = lackr.mk_ackermann(resg, m_lemma_limit);
|
const bool success = lackr.mk_ackermann(resg, m_lemma_limit);
|
||||||
if (!success) { // Just pass on the input unchanged
|
if (!success) { // Just pass on the input unchanged
|
||||||
|
TRACE("ackermannize", tout << "ackermannize not run due to limit" << std::endl;);
|
||||||
result.reset();
|
result.reset();
|
||||||
result.push_back(g.get());
|
result.push_back(g.get());
|
||||||
mc = 0;
|
mc = 0;
|
||||||
|
@ -62,7 +64,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
resg->inc_depth();
|
resg->inc_depth();
|
||||||
TRACE("ackermannize", resg->display(tout););
|
TRACE("ackermannize", resg->display(tout << "out\n"););
|
||||||
SASSERT(resg->is_well_sorted());
|
SASSERT(resg->is_well_sorted());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,11 +34,13 @@ struct lackr_model_constructor::imp {
|
||||||
, m_conflicts(conflicts)
|
, m_conflicts(conflicts)
|
||||||
, m_b_rw(m)
|
, m_b_rw(m)
|
||||||
, m_bv_rw(m)
|
, m_bv_rw(m)
|
||||||
|
, m_evaluator(NULL)
|
||||||
, m_empty_model(m)
|
, m_empty_model(m)
|
||||||
, m_ackr_helper(m)
|
, m_ackr_helper(m)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
~imp() {
|
~imp() {
|
||||||
|
if (m_evaluator) dealloc(m_evaluator);
|
||||||
{
|
{
|
||||||
values2val_t::iterator i = m_values2val.begin();
|
values2val_t::iterator i = m_values2val.begin();
|
||||||
const values2val_t::iterator e = m_values2val.end();
|
const values2val_t::iterator e = m_values2val.end();
|
||||||
|
@ -60,15 +62,17 @@ struct lackr_model_constructor::imp {
|
||||||
|
|
||||||
//
|
//
|
||||||
// Returns true iff model was successfully constructed.
|
// Returns true iff model was successfully constructed.
|
||||||
|
// Conflicts are saved as a side effect.
|
||||||
//
|
//
|
||||||
bool check() {
|
bool check() {
|
||||||
|
bool retv = true;
|
||||||
for (unsigned i = 0; i < m_abstr_model->get_num_constants(); i++) {
|
for (unsigned i = 0; i < m_abstr_model->get_num_constants(); i++) {
|
||||||
func_decl * const c = m_abstr_model->get_constant(i);
|
func_decl * const c = m_abstr_model->get_constant(i);
|
||||||
app * const term = m_info->find_term(c);
|
app * const _term = m_info->find_term(c);
|
||||||
if (term) m_stack.push_back(term);
|
expr * const term = _term ? _term : m_m.mk_const(c);
|
||||||
else m_stack.push_back(m_m.mk_const(c));
|
if (!check_term(term)) retv = false;
|
||||||
}
|
}
|
||||||
return run();
|
return retv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -134,7 +138,7 @@ struct lackr_model_constructor::imp {
|
||||||
conflict_list& m_conflicts;
|
conflict_list& m_conflicts;
|
||||||
bool_rewriter m_b_rw;
|
bool_rewriter m_b_rw;
|
||||||
bv_rewriter m_bv_rw;
|
bv_rewriter m_bv_rw;
|
||||||
scoped_ptr<model_evaluator> m_evaluator;
|
model_evaluator * m_evaluator;
|
||||||
model m_empty_model;
|
model m_empty_model;
|
||||||
private:
|
private:
|
||||||
struct val_info { expr * value; app * source_term; };
|
struct val_info { expr * value; app * source_term; };
|
||||||
|
@ -144,6 +148,7 @@ struct lackr_model_constructor::imp {
|
||||||
app2val_t m_app2val;
|
app2val_t m_app2val;
|
||||||
ptr_vector<expr> m_stack;
|
ptr_vector<expr> m_stack;
|
||||||
ackr_helper m_ackr_helper;
|
ackr_helper m_ackr_helper;
|
||||||
|
expr_mark m_visited;
|
||||||
|
|
||||||
static inline val_info mk_val_info(expr* value, app* source_term) {
|
static inline val_info mk_val_info(expr* value, app* source_term) {
|
||||||
val_info rv;
|
val_info rv;
|
||||||
|
@ -152,17 +157,23 @@ struct lackr_model_constructor::imp {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Performs congruence check on a given term.
|
||||||
|
bool check_term(expr * term) {
|
||||||
|
m_stack.push_back(term);
|
||||||
|
const bool rv = _check_stack();
|
||||||
|
m_stack.reset();
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
// Performs congruence check on terms on the stack.
|
// Performs congruence check on terms on the stack.
|
||||||
// (Currently stops upon the first failure).
|
// Stops upon the first failure.
|
||||||
// Returns true if and only if congruence check succeeded.
|
// Returns true if and only if all congruence checks succeeded.
|
||||||
bool run() {
|
bool _check_stack() {
|
||||||
m_evaluator = alloc(model_evaluator, m_empty_model);
|
if (m_evaluator == NULL) m_evaluator = alloc(model_evaluator, m_empty_model);
|
||||||
expr_mark visited;
|
|
||||||
expr * curr;
|
expr * curr;
|
||||||
while (!m_stack.empty()) {
|
while (!m_stack.empty()) {
|
||||||
curr = m_stack.back();
|
curr = m_stack.back();
|
||||||
if (visited.is_marked(curr)) {
|
if (m_visited.is_marked(curr)) {
|
||||||
m_stack.pop_back();
|
m_stack.pop_back();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -173,8 +184,8 @@ struct lackr_model_constructor::imp {
|
||||||
return false;
|
return false;
|
||||||
case AST_APP: {
|
case AST_APP: {
|
||||||
app * a = to_app(curr);
|
app * a = to_app(curr);
|
||||||
if (for_each_expr_args(m_stack, visited, a->get_num_args(), a->get_args())) {
|
if (for_each_expr_args(m_stack, m_visited, a->get_num_args(), a->get_args())) {
|
||||||
visited.mark(a, true);
|
m_visited.mark(a, true);
|
||||||
m_stack.pop_back();
|
m_stack.pop_back();
|
||||||
if (!mk_value(a)) return false;
|
if (!mk_value(a)) return false;
|
||||||
}
|
}
|
||||||
|
@ -212,7 +223,11 @@ struct lackr_model_constructor::imp {
|
||||||
for (unsigned i = 0; i < num; ++i) {
|
for (unsigned i = 0; i < num; ++i) {
|
||||||
expr * val;
|
expr * val;
|
||||||
const bool b = eval_cached(to_app(args[i]), val); // TODO: OK conversion to_app?
|
const bool b = eval_cached(to_app(args[i]), val); // TODO: OK conversion to_app?
|
||||||
CTRACE("model_constructor", !b, tout << "fail arg val(\n" << mk_ismt2_pp(args[i], m_m, 2); );
|
CTRACE("model_constructor", m_conflicts.empty() && !b, tout << "fail arg val(\n" << mk_ismt2_pp(args[i], m_m, 2) << '\n'; );
|
||||||
|
if (!b) {
|
||||||
|
// bailing out because args eval failed previously
|
||||||
|
return false;
|
||||||
|
}
|
||||||
TRACE("model_constructor", tout <<
|
TRACE("model_constructor", tout <<
|
||||||
"arg val " << i << "(\n" << mk_ismt2_pp(args[i], m_m, 2)
|
"arg val " << i << "(\n" << mk_ismt2_pp(args[i], m_m, 2)
|
||||||
<< " : " << mk_ismt2_pp(val, m_m, 2) << '\n'; );
|
<< " : " << mk_ismt2_pp(val, m_m, 2) << '\n'; );
|
||||||
|
|
|
@ -47,6 +47,7 @@ public:
|
||||||
: m_m(m)
|
: m_m(m)
|
||||||
, m_p(p)
|
, m_p(p)
|
||||||
, m_use_sat(false)
|
, m_use_sat(false)
|
||||||
|
, m_inc_use_sat(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual ~qfufbv_ackr_tactic() { }
|
virtual ~qfufbv_ackr_tactic() { }
|
||||||
|
@ -85,6 +86,7 @@ public:
|
||||||
void updt_params(params_ref const & _p) {
|
void updt_params(params_ref const & _p) {
|
||||||
qfufbv_tactic_params p(_p);
|
qfufbv_tactic_params p(_p);
|
||||||
m_use_sat = p.sat_backend();
|
m_use_sat = p.sat_backend();
|
||||||
|
m_inc_use_sat = p.inc_sat_backend();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void collect_statistics(statistics & st) const {
|
virtual void collect_statistics(statistics & st) const {
|
||||||
|
@ -105,13 +107,19 @@ private:
|
||||||
params_ref m_p;
|
params_ref m_p;
|
||||||
lackr_stats m_st;
|
lackr_stats m_st;
|
||||||
bool m_use_sat;
|
bool m_use_sat;
|
||||||
|
bool m_inc_use_sat;
|
||||||
|
|
||||||
solver* setup_sat() {
|
solver* setup_sat() {
|
||||||
solver * sat(NULL);
|
solver * sat(NULL);
|
||||||
if (m_use_sat) {
|
if (m_use_sat) {
|
||||||
|
if (m_inc_use_sat) {
|
||||||
|
sat = mk_inc_sat_solver(m_m, m_p);
|
||||||
|
}
|
||||||
|
else {
|
||||||
tactic_ref t = mk_qfbv_tactic(m_m, m_p);
|
tactic_ref t = mk_qfbv_tactic(m_m, m_p);
|
||||||
sat = mk_tactic2solver(m_m, t.get(), m_p);
|
sat = mk_tactic2solver(m_m, t.get(), m_p);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
tactic_ref t = mk_qfaufbv_tactic(m_m, m_p);
|
tactic_ref t = mk_qfaufbv_tactic(m_m, m_p);
|
||||||
sat = mk_tactic2solver(m_m, t.get(), m_p);
|
sat = mk_tactic2solver(m_m, t.get(), m_p);
|
||||||
|
|
|
@ -4,5 +4,6 @@ def_module_params('ackermannization',
|
||||||
export=True,
|
export=True,
|
||||||
params=(
|
params=(
|
||||||
('sat_backend', BOOL, False, 'use SAT rather than SMT in qfufbv_ackr_tactic'),
|
('sat_backend', BOOL, False, 'use SAT rather than SMT in qfufbv_ackr_tactic'),
|
||||||
|
('inc_sat_backend', BOOL, False, 'use incremental SAT'),
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue