3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-21 02:30:23 +00:00
Signed-off-by: Miguel Angelo Da Terra Neves <t-mineve@microsoft.com>
This commit is contained in:
Miguel Angelo Da Terra Neves 2017-11-20 11:55:18 -08:00
commit 37c39f4073
138 changed files with 1404 additions and 2783 deletions

View file

@ -1,5 +1,6 @@
z3_add_component(tactic
SOURCES
dependency_converter.cpp
equiv_proof_converter.cpp
generic_model_converter.cpp
goal.cpp

View file

@ -90,13 +90,8 @@ public:
SASSERT(g->is_well_sorted());
}
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
virtual void operator()(goal_ref const & g, goal_ref_buffer & result) {
fail_if_proof_generation("aig", g);
mc = 0; pc = 0; core = 0;
operator()(g);
g->inc_depth();
result.push_back(g.get());

View file

@ -111,11 +111,7 @@ class add_bounds_tactic : public tactic {
};
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
mc = 0; pc = 0; core = 0;
goal_ref_buffer & result) {
tactic_report report("add-bounds", *g);
bound_manager bm(m);
expr_fast_mark1 visited;
@ -161,11 +157,8 @@ public:
}
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(g, result, mc, pc, core);
goal_ref_buffer & result) {
(*m_imp)(g, result);
}
virtual void cleanup() {

View file

@ -24,10 +24,7 @@ struct arith_bounds_tactic : public tactic {
virtual void operator()(/* in */ goal_ref const & in,
/* out */ goal_ref_buffer & result,
/* out */ model_converter_ref & mc,
/* out */ proof_converter_ref & pc,
/* out */ expr_dependency_ref & core) {
/* out */ goal_ref_buffer & result) {
bounds_arith_subsumption(in, result);
}

View file

@ -53,13 +53,10 @@ public:
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
TRACE("card2bv-before", g->display(tout););
SASSERT(g->is_well_sorted());
mc = 0; pc = 0; core = 0; result.reset();
result.reset();
tactic_report report("card2bv", *g);
th_rewriter rw1(m, m_params);
pb2bv_rewriter rw2(m, m_params);
@ -90,10 +87,8 @@ public:
func_decl_ref_vector const& fns = rw2.fresh_constants();
if (!fns.empty()) {
generic_model_converter* filter = alloc(generic_model_converter, m);
for (unsigned i = 0; i < fns.size(); ++i) {
filter->hide(fns[i]);
}
mc = filter;
for (func_decl* f : fns) filter->hide(f);
g->add(filter);
}
g->inc_depth();

View file

@ -223,16 +223,13 @@ class degree_shift_tactic : public tactic {
}
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
mc = 0; pc = 0; core = 0;
m_produce_proofs = g->proofs_enabled();
m_produce_models = g->models_enabled();
tactic_report report("degree_shift", *g);
collect(*g);
model_converter_ref mc;
discard_non_candidates();
if (!m_var2degree.empty()) {
prepare_substitution(mc);
@ -270,6 +267,7 @@ class degree_shift_tactic : public tactic {
}
}
g->inc_depth();
g->add(mc.get());
result.push_back(g.get());
TRACE("degree_shift", g->display(tout); if (mc) mc->display(tout););
SASSERT(g->is_well_sorted());
@ -291,11 +289,8 @@ public:
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(in, result, mc, pc, core);
goal_ref_buffer & result) {
(*m_imp)(in, result);
}
virtual void cleanup() {

View file

@ -313,13 +313,10 @@ class diff_neq_tactic : public tactic {
}
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
m_produce_models = g->models_enabled();
mc = 0; pc = 0; core = 0; result.reset();
result.reset();
tactic_report report("diff-neq", *g);
fail_if_proof_generation("diff-neq", g);
fail_if_unsat_core_generation("diff-neq", g);
@ -332,8 +329,9 @@ class diff_neq_tactic : public tactic {
bool r = search();
report_tactic_progress(":conflicts", m_num_conflicts);
if (r) {
if (m_produce_models)
mc = model2model_converter(mk_model());
if (m_produce_models) {
g->add(model2model_converter(mk_model()));
}
g->reset();
}
else {
@ -384,11 +382,8 @@ public:
If s is not really in the difference logic fragment, then this is a NOOP.
*/
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(in, result, mc, pc, core);
goal_ref_buffer & result) {
(*m_imp)(in, result);
}
virtual void cleanup() {

View file

@ -41,8 +41,7 @@ public:
m_refs(m)
{}
virtual void operator()(model_ref & old_model, unsigned goal_idx) {
SASSERT(goal_idx == 0);
virtual void operator()(model_ref & old_model) {
model * new_model = alloc(model, m);
unsigned num = old_model->get_num_constants();
for (unsigned i = 0; i < m_nums_as_int.size(); ++i) {
@ -153,18 +152,13 @@ public:
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
mc = 0; pc = 0; core = 0;
tactic_report report("elim01", *g);
expr_safe_replace sub(m);
bool2int_model_converter* b2i = alloc(bool2int_model_converter, m);
mc = b2i;
ref<bool2int_model_converter> b2i = alloc(bool2int_model_converter, m);
bound_manager bounds(m);
expr_ref_vector axioms(m);
bounds(*g);
@ -179,7 +173,7 @@ public:
if (a.is_int(x) &&
bounds.has_lower(x, lo, s1) && !s1 && zero <= lo &&
bounds.has_upper(x, hi, s2) && !s2 && hi <= m_max_hi && lo <= hi) {
add_variable(b2i, sub, x, lo.get_unsigned(), hi.get_unsigned(), axioms);
add_variable(b2i.get(), sub, x, lo.get_unsigned(), hi.get_unsigned(), axioms);
}
else if (a.is_int(x)) {
TRACE("pb", tout << "Not adding variable " << mk_pp(x, m) << " has lower: "
@ -205,9 +199,9 @@ public:
}
g->update(i, new_curr, new_pr, g->dep(i));
}
for (unsigned i = 0; i < axioms.size(); ++i) {
g->assert_expr(axioms[i].get());
}
for (expr* a : axioms)
g->assert_expr(a);
g->add(b2i.get());
g->inc_depth();
result.push_back(g.get());
TRACE("pb", g->display(tout););

View file

@ -149,14 +149,8 @@ public:
void updt_params(params_ref const & p) {
}
virtual void operator()(
goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
virtual void operator()(goal_ref const & g, goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
mc = 0; pc = 0; core = 0;
m_trail.reset();
m_fd.reset();
m_max.reset();
@ -212,7 +206,7 @@ public:
}
}
g->inc_depth();
mc = mc1.get();
g->add(mc1.get());
result.push_back(g.get());
TRACE("pb", g->display(tout););
SASSERT(g->is_well_sorted());

View file

@ -257,12 +257,8 @@ class factor_tactic : public tactic {
}
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
mc = 0; pc = 0; core = 0;
tactic_report report("factor", *g);
bool produce_proofs = g->proofs_enabled();
@ -313,12 +309,9 @@ public:
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
try {
(*m_imp)(in, result, mc, pc, core);
(*m_imp)(in, result);
}
catch (z3_error & ex) {
throw ex;

View file

@ -249,12 +249,8 @@ class fix_dl_var_tactic : public tactic {
}
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
mc = 0; pc = 0; core = 0;
tactic_report report("fix-dl-var", *g);
bool produce_proofs = g->proofs_enabled();
m_produce_models = g->models_enabled();
@ -270,9 +266,9 @@ class fix_dl_var_tactic : public tactic {
m_rw.set_substitution(&subst);
if (m_produce_models) {
generic_model_converter * _mc = alloc(generic_model_converter, m);
_mc->add(var, zero);
mc = _mc;
generic_model_converter * mc = alloc(generic_model_converter, m);
mc->add(var, zero);
g->add(mc);
}
expr_ref new_curr(m);
@ -321,12 +317,9 @@ public:
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
try {
(*m_imp)(in, result, mc, pc, core);
(*m_imp)(in, result);
}
catch (rewriter_exception & ex) {
throw tactic_exception(ex.msg());

View file

@ -180,7 +180,7 @@ class fm_tactic : public tactic {
m_clauses.back().swap(c);
}
virtual void operator()(model_ref & md, unsigned goal_idx) {
virtual void operator()(model_ref & md) {
TRACE("fm_mc", model_v2_pp(tout, *md); display(tout););
model_evaluator ev(*(md.get()));
ev.set_model_completion(true);
@ -1550,12 +1550,8 @@ class fm_tactic : public tactic {
}
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
mc = 0; pc = 0; core = 0;
tactic_report report("fm", *g);
fail_if_proof_generation("fm", g);
m_produce_models = g->models_enabled();
@ -1603,7 +1599,7 @@ class fm_tactic : public tactic {
report_tactic_progress(":fm-cost", m_counter);
if (!m_inconsistent) {
copy_remaining();
mc = m_mc.get();
m_new_goal->add(concat(g->mc(), m_mc.get()));
}
}
reset_constraints();
@ -1675,11 +1671,8 @@ public:
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(in, result, mc, pc, core);
goal_ref_buffer & result) {
(*m_imp)(in, result);
}
};

View file

@ -159,12 +159,8 @@ public:
}
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
mc = 0; pc = 0; core = 0;
m_01s->reset();
tactic_report report("cardinality-intro", *g);
@ -173,9 +169,7 @@ public:
bounds(*g);
bound_manager::iterator bit = bounds.begin(), bend = bounds.end();
for (; bit != bend; ++bit) {
expr* x = *bit;
for (expr* x : bounds) {
bool s1 = false, s2 = false;
rational lo, hi;
if (a.is_int(x) &&
@ -197,9 +191,7 @@ public:
g->update(i, new_curr, new_pr, g->dep(i));
mark_rec(subfmls, new_curr);
}
expr_set::iterator it = m_01s->begin(), end = m_01s->end();
for (; it != end; ++it) {
expr* v = *it;
for (expr* v : *m_01s) {
if (subfmls.is_marked(v)) {
g->assert_expr(a.mk_le(v, a.mk_numeral(rational(1), true)));
g->assert_expr(a.mk_le(a.mk_numeral(rational(0), true), v));

View file

@ -188,15 +188,12 @@ class lia2pb_tactic : public tactic {
}
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
fail_if_proof_generation("lia2pb", g);
m_produce_models = g->models_enabled();
m_produce_unsat_cores = g->unsat_core_enabled();
mc = 0; pc = 0; core = 0; result.reset();
result.reset();
tactic_report report("lia2pb", *g);
m_bm.reset(); m_rw.reset(); m_new_deps.reset();
@ -223,10 +220,9 @@ class lia2pb_tactic : public tactic {
if (!check_num_bits())
throw tactic_exception("lia2pb failed, number of necessary bits exceeds specified threshold (use option :lia2pb-total-bits to increase threshold)");
generic_model_converter * gmc = 0;
ref<generic_model_converter> gmc;
if (m_produce_models) {
gmc = alloc(generic_model_converter, m);
mc = gmc;
}
expr_ref zero(m);
@ -296,6 +292,7 @@ class lia2pb_tactic : public tactic {
g->update(idx, new_curr, new_pr, dep);
}
g->inc_depth();
g->add(gmc.get());
result.push_back(g.get());
TRACE("lia2pb", g->display(tout););
SASSERT(g->is_well_sorted());
@ -330,12 +327,9 @@ public:
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
try {
(*m_imp)(in, result, mc, pc, core);
(*m_imp)(in, result);
}
catch (rewriter_exception & ex) {
throw tactic_exception(ex.msg());

View file

@ -440,19 +440,17 @@ public:
\return false if transformation is not possible.
*/
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
fail_if_proof_generation("nla2bv", g);
fail_if_unsat_core_generation("nla2bv", g);
mc = 0; pc = 0; core = 0; result.reset();
result.reset();
imp proc(g->m(), m_params);
scoped_set_imp setter(*this, proc);
model_converter_ref mc;
proc(*(g.get()), mc);
g->add(mc.get());
result.push_back(g.get());
SASSERT(g->is_well_sorted());
}

View file

@ -79,12 +79,7 @@ class normalize_bounds_tactic : public tactic {
return false;
}
void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
mc = 0; pc = 0; core = 0;
void operator()(goal_ref const & in, goal_ref_buffer & result) {
bool produce_models = in->models_enabled();
bool produce_proofs = in->proofs_enabled();
tactic_report report("normalize-bounds", *in);
@ -100,16 +95,13 @@ class normalize_bounds_tactic : public tactic {
generic_model_converter * gmc = 0;
if (produce_models) {
gmc = alloc(generic_model_converter, m);
mc = gmc;
in->add(gmc);
}
unsigned num_norm_bounds = 0;
expr_substitution subst(m);
rational val;
bound_manager::iterator it = m_bm.begin();
bound_manager::iterator end = m_bm.end();
for (; it != end; ++it) {
expr * x = *it;
for (expr * x : m_bm) {
if (is_target(x, val)) {
num_norm_bounds++;
sort * s = m.get_sort(x);
@ -171,12 +163,9 @@ public:
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
try {
(*m_imp)(in, result, mc, pc, core);
(*m_imp)(in, result);
}
catch (rewriter_exception & ex) {
throw tactic_exception(ex.msg());

View file

@ -27,17 +27,12 @@ pb2bv_model_converter::pb2bv_model_converter(ast_manager & _m) : m(_m) {
pb2bv_model_converter::pb2bv_model_converter(ast_manager & _m, obj_map<func_decl, expr*> const & c2bit, bound_manager const & bm):
m(_m) {
obj_map<func_decl, expr*>::iterator it = c2bit.begin();
obj_map<func_decl, expr*>::iterator end = c2bit.end();
for ( ; it != end; it++) {
m_c2bit.push_back(func_decl_pair(it->m_key, to_app(it->m_value)->get_decl()));
m.inc_ref(it->m_key);
m.inc_ref(to_app(it->m_value)->get_decl());
for (auto const& kv : c2bit) {
m_c2bit.push_back(func_decl_pair(kv.m_key, to_app(kv.m_value)->get_decl()));
m.inc_ref(kv.m_key);
m.inc_ref(to_app(kv.m_value)->get_decl());
}
bound_manager::iterator it2 = bm.begin();
bound_manager::iterator end2 = bm.end();
for (; it2 != end2; ++it2) {
expr * c = *it2;
for (expr* c : bm) {
SASSERT(is_uninterp_const(c));
func_decl * d = to_app(c)->get_decl();
if (!c2bit.contains(d)) {
@ -49,53 +44,43 @@ pb2bv_model_converter::pb2bv_model_converter(ast_manager & _m, obj_map<func_decl
}
pb2bv_model_converter::~pb2bv_model_converter() {
svector<func_decl_pair>::const_iterator it = m_c2bit.begin();
svector<func_decl_pair>::const_iterator end = m_c2bit.end();
for (; it != end; ++it) {
m.dec_ref(it->first);
m.dec_ref(it->second);
for (auto const& kv : m_c2bit) {
m.dec_ref(kv.first);
m.dec_ref(kv.second);
}
}
void pb2bv_model_converter::operator()(model_ref & md) {
(*this)(md, 0);
}
void pb2bv_model_converter::operator()(model_ref & md, unsigned goal_idx) {
SASSERT(goal_idx == 0);
void pb2bv_model_converter::operator()(model_ref & md) {
TRACE("pb2bv", tout << "converting model:\n"; model_v2_pp(tout, *md); display(tout););
arith_util a_util(m);
svector<func_decl_pair>::const_iterator it = m_c2bit.begin();
svector<func_decl_pair>::const_iterator end = m_c2bit.end();
for (; it != end; ++it) {
if (it->second) {
expr * val = md->get_const_interp(it->second);
for (auto const& kv : m_c2bit) {
if (kv.second) {
expr * val = md->get_const_interp(kv.second);
if (val == 0 || m.is_false(val)) {
/* false's and don't cares get the integer 0 solution*/
md->register_decl(it->first, a_util.mk_numeral(rational(0), true));
md->register_decl(kv.first, a_util.mk_numeral(rational(0), true));
}
else {
md->register_decl(it->first, a_util.mk_numeral(rational(1), true));
md->register_decl(kv.first, a_util.mk_numeral(rational(1), true));
}
}
else {
// it->first is a don't care.
md->register_decl(it->first, a_util.mk_numeral(rational(0), true));
// kv.first is a don't care.
md->register_decl(kv.first, a_util.mk_numeral(rational(0), true));
}
}
}
void pb2bv_model_converter::display(std::ostream & out) {
out << "(pb2bv-model-converter";
svector<func_decl_pair>::const_iterator it = m_c2bit.begin();
svector<func_decl_pair>::const_iterator end = m_c2bit.end();
for (; it != end; ++it) {
out << "\n (" << it->first->get_name() << " ";
if (it->second == 0)
for (auto const& kv : m_c2bit) {
out << "\n (" << kv.first->get_name() << " ";
if (kv.second == 0)
out << "0";
else
out << it->second->get_name();
out << kv.second->get_name();
out << ")";
}
out << ")\n";
@ -104,11 +89,9 @@ void pb2bv_model_converter::display(std::ostream & out) {
model_converter * pb2bv_model_converter::translate(ast_translation & translator) {
ast_manager & to = translator.to();
pb2bv_model_converter * res = alloc(pb2bv_model_converter, to);
svector<func_decl_pair>::iterator it = m_c2bit.begin();
svector<func_decl_pair>::iterator end = m_c2bit.end();
for (; it != end; it++) {
func_decl * f1 = translator(it->first);
func_decl * f2 = translator(it->second);
for (auto const& kv : m_c2bit) {
func_decl * f1 = translator(kv.first);
func_decl * f2 = translator(kv.second);
res->m_c2bit.push_back(func_decl_pair(f1, f2));
to.inc_ref(f1);
to.inc_ref(f2);

View file

@ -31,10 +31,9 @@ public:
pb2bv_model_converter(ast_manager & _m);
pb2bv_model_converter(ast_manager & _m, obj_map<func_decl, expr*> const & c2bit, bound_manager const & bm);
virtual ~pb2bv_model_converter();
virtual void operator()(model_ref & md);
virtual void operator()(model_ref & md, unsigned goal_idx);
virtual void display(std::ostream & out);
virtual model_converter * translate(ast_translation & translator);
void operator()(model_ref & md) override;
void display(std::ostream & out) override;
model_converter * translate(ast_translation & translator) override;
};
#endif

View file

@ -886,16 +886,13 @@ private:
}
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
TRACE("pb2bv", g->display(tout););
SASSERT(g->is_well_sorted());
fail_if_proof_generation("pb2bv", g);
m_produce_models = g->models_enabled();
m_produce_unsat_cores = g->unsat_core_enabled();
mc = 0; pc = 0; core = 0; result.reset();
result.reset();
tactic_report report("pb2bv", *g);
m_bm.reset(); m_rw.reset(); m_new_deps.reset();
@ -949,6 +946,7 @@ private:
g->update(idx, new_exprs[idx].get(), 0, (m_produce_unsat_cores) ? new_deps[idx].get() : g->dep(idx));
if (m_produce_models) {
model_converter_ref mc;
generic_model_converter * mc1 = alloc(generic_model_converter, m);
for (auto const& kv : m_const2bit)
mc1->hide(kv.m_value);
@ -957,7 +955,8 @@ private:
for (unsigned i = 0; i < num_temps; i++)
mc1->hide(m_temporary_ints.get(i));
pb2bv_model_converter * mc2 = alloc(pb2bv_model_converter, m, m_const2bit, m_bm);
mc = concat(mc1, mc2);
mc = concat(mc1, mc2);
g->add(mc.get());
}
g->inc_depth();
@ -999,11 +998,8 @@ public:
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(in, result, mc, pc, core);
goal_ref_buffer & result) {
(*m_imp)(in, result);
}
virtual void cleanup() {

View file

@ -52,7 +52,7 @@ public:
virtual void updt_params(params_ref const & p);
virtual void collect_param_descrs(param_descrs & r) {}
virtual void operator()(goal_ref const & g, goal_ref_buffer & result, model_converter_ref & mc, proof_converter_ref & pc, expr_dependency_ref & core);
virtual void operator()(goal_ref const & g, goal_ref_buffer & result);
virtual void cleanup();
};
@ -527,14 +527,11 @@ void propagate_ineqs_tactic::updt_params(params_ref const & p) {
}
void propagate_ineqs_tactic::operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
fail_if_proof_generation("propagate-ineqs", g);
fail_if_unsat_core_generation("propagate-ineqs", g);
mc = 0; pc = 0; core = 0; result.reset();
result.reset();
goal_ref r;
(*m_imp)(g.get(), r);
result.push_back(r.get());

View file

@ -821,13 +821,9 @@ public:
}
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
try {
SASSERT(g->is_well_sorted());
mc = 0; pc = 0; core = 0;
tactic_report report("purify-arith", *g);
TRACE("purify_arith", g->display(tout););
bool produce_proofs = g->proofs_enabled();
@ -835,10 +831,10 @@ public:
bool elim_root_objs = m_params.get_bool("elim_root_objects", true);
bool elim_inverses = m_params.get_bool("elim_inverses", true);
bool complete = m_params.get_bool("complete", true);
purify_arith_proc proc(*(g.get()), m_util, produce_proofs, elim_root_objs, elim_inverses, complete);
purify_arith_proc proc(*(g.get()), m_util, produce_proofs, elim_root_objs, elim_inverses, complete);
model_converter_ref mc;
proc(mc, produce_models);
g->add(mc.get());
g->inc_depth();
result.push_back(g.get());
TRACE("purify_arith", g->display(tout););

View file

@ -292,15 +292,12 @@ class recover_01_tactic : public tactic {
}
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
fail_if_proof_generation("recover-01", g);
fail_if_unsat_core_generation("recover-01", g);
m_produce_models = g->models_enabled();
mc = 0; pc = 0; core = 0; result.reset();
result.reset();
tactic_report report("recover-01", *g);
bool saved = false;
@ -308,7 +305,9 @@ class recover_01_tactic : public tactic {
SASSERT(new_goal->depth() == g->depth());
SASSERT(new_goal->prec() == g->prec());
new_goal->inc_depth();
new_goal->add(g->mc());
new_goal->add(g->pc());
unsigned sz = g->size();
for (unsigned i = 0; i < sz; i++) {
expr * f = g->form(i);
@ -327,7 +326,7 @@ class recover_01_tactic : public tactic {
if (m_produce_models) {
gmc = alloc(generic_model_converter, m);
mc = gmc;
new_goal->add(gmc);
}
dec_ref_key_values(m, bool2int);
@ -336,25 +335,20 @@ class recover_01_tactic : public tactic {
bool recovered = false;
expr_substitution _subst(m);
subst = &_subst;
var2clauses::iterator it = m_var2clauses.begin();
var2clauses::iterator end = m_var2clauses.end();
for (; it != end; ++it) {
if (process(it->m_key, it->m_value)) {
for (auto& kv : m_var2clauses) {
if (process(kv.m_key, kv.m_value)) {
recovered = true;
counter++;
}
else {
ptr_vector<app>::iterator it2 = it->m_value.begin();
ptr_vector<app>::iterator end2 = it->m_value.end();
for (; it2 != end2; ++it2) {
new_goal->assert_expr(*it2);
for (app* a : kv.m_value) {
new_goal->assert_expr(a);
}
}
}
if (!recovered) {
result.push_back(g.get());
mc = 0;
return;
}
@ -406,12 +400,9 @@ public:
}
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
try {
(*m_imp)(g, result, mc, pc, core);
(*m_imp)(g, result);
}
catch (rewriter_exception & ex) {
throw tactic_exception(ex.msg());

View file

@ -172,8 +172,7 @@ struct bit_blaster_model_converter : public model_converter {
return result;
}
void operator()(model_ref & md, unsigned goal_idx) override {
SASSERT(goal_idx == 0);
void operator()(model_ref & md) override {
model * new_model = alloc(model, m());
obj_hashtable<func_decl> bits;
collect_bits(bits);
@ -182,10 +181,6 @@ struct bit_blaster_model_converter : public model_converter {
md = new_model;
}
void operator()(model_ref & md) override {
operator()(md, 0);
}
/**
\brief simplisic expansion operator for formulas.
It just adds back bit-vector definitions to the formula whether they are used or not.

View file

@ -51,11 +51,7 @@ class bit_blaster_tactic : public tactic {
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
mc = 0; pc = 0; core = 0;
goal_ref_buffer & result) {
bool proofs_enabled = g->proofs_enabled();
if (proofs_enabled && m_blast_quant)
@ -88,12 +84,10 @@ class bit_blaster_tactic : public tactic {
}
if (change && g->models_enabled())
mc = mk_bit_blaster_model_converter(m(), m_rewriter->const2bits());
else
mc = 0;
g->add(mk_bit_blaster_model_converter(m(), m_rewriter->const2bits()));
g->inc_depth();
result.push_back(g.get());
TRACE("after_bit_blaster", g->display(tout); if (mc) mc->display(tout); tout << "\n";);
TRACE("after_bit_blaster", g->display(tout); if (g->mc()) g->mc()->display(tout); tout << "\n";);
m_rewriter->cleanup();
}
@ -135,12 +129,9 @@ public:
}
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
try {
(*m_imp)(g, result, mc, pc, core);
(*m_imp)(g, result);
}
catch (rewriter_exception & ex) {
throw tactic_exception(ex.msg());

View file

@ -379,11 +379,7 @@ class bv1_blaster_tactic : public tactic {
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
mc = 0; pc = 0; core = 0;
goal_ref_buffer & result) {
if (!is_target(*g))
throw tactic_exception("bv1 blaster cannot be applied to goal");
@ -409,7 +405,7 @@ class bv1_blaster_tactic : public tactic {
}
if (g->models_enabled())
mc = mk_bv1_blaster_model_converter(m(), m_rw.cfg().m_const2bits);
g->add(mk_bv1_blaster_model_converter(m(), m_rw.cfg().m_const2bits));
g->inc_depth();
result.push_back(g.get());
m_rw.cfg().cleanup();
@ -455,11 +451,8 @@ public:
Return a model_converter that converts any model for the updated set into a model for the old set.
*/
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(g, result, mc, pc, core);
goal_ref_buffer & result) {
(*m_imp)(g, result);
}
virtual void cleanup() {

View file

@ -136,11 +136,7 @@ class bv_bound_chk_tactic : public tactic {
public:
bv_bound_chk_tactic(ast_manager & m, params_ref const & p);
virtual ~bv_bound_chk_tactic();
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core);
void operator()(goal_ref const & g, goal_ref_buffer & result) override;
virtual tactic * translate(ast_manager & m);
virtual void updt_params(params_ref const & p);
void cleanup();
@ -197,16 +193,12 @@ bv_bound_chk_tactic::~bv_bound_chk_tactic() {
dealloc(m_imp);
}
void bv_bound_chk_tactic::operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void bv_bound_chk_tactic::operator()(goal_ref const & g, goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
fail_if_proof_generation("bv-bound-chk", g);
fail_if_unsat_core_generation("bv-bound-chk", g);
TRACE("bv-bound-chk", g->display(tout << "before:"); tout << std::endl;);
mc = 0; pc = 0; core = 0; result.reset();
result.reset();
m_imp->operator()(g);
g->inc_depth();
result.push_back(g.get());

View file

@ -39,7 +39,7 @@ public:
virtual ~bv_size_reduction_tactic();
virtual void operator()(goal_ref const & g, goal_ref_buffer & result, model_converter_ref & mc, proof_converter_ref & pc, expr_dependency_ref & core);
virtual void operator()(goal_ref const & g, goal_ref_buffer & result);
virtual void cleanup();
};
@ -382,16 +382,15 @@ bv_size_reduction_tactic::~bv_size_reduction_tactic() {
}
void bv_size_reduction_tactic::operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
fail_if_proof_generation("bv-size-reduction", g);
fail_if_unsat_core_generation("bv-size-reduction", g);
mc = 0; pc = 0; core = 0; result.reset();
result.reset();
model_converter_ref mc;
m_imp->operator()(*(g.get()), mc);
g->inc_depth();
g->add(mc.get());
result.push_back(g.get());
SASSERT(g->is_well_sorted());
}

View file

@ -53,18 +53,16 @@ class bvarray2uf_tactic : public tactic {
}
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core)
goal_ref_buffer & result)
{
SASSERT(g->is_well_sorted());
tactic_report report("bvarray2uf", *g);
mc = 0; pc = 0; core = 0; result.reset();
result.reset();
fail_if_unsat_core_generation("bvarray2uf", g);
TRACE("bvarray2uf", tout << "Before: " << std::endl; g->display(tout); );
m_produce_models = g->models_enabled();
model_converter_ref mc;
if (m_produce_models) {
generic_model_converter * fmc = alloc(generic_model_converter, m_manager);
@ -93,6 +91,7 @@ class bvarray2uf_tactic : public tactic {
g->assert_expr(m_rw.m_cfg.extra_assertions[i].get());
g->inc_depth();
g->add(mc.get());
result.push_back(g.get());
TRACE("bvarray2uf", tout << "After: " << std::endl; g->display(tout););
SASSERT(g->is_well_sorted());
@ -129,11 +128,8 @@ public:
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(in, result, mc, pc, core);
goal_ref_buffer & result) {
(*m_imp)(in, result);
}
virtual void cleanup() {

View file

@ -116,12 +116,7 @@ public:
virtual void collect_param_descrs(param_descrs & r) {
}
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
mc = 0; pc = 0; core = 0;
virtual void operator()(goal_ref const & g, goal_ref_buffer & result) {
bool produce_proofs = g->proofs_enabled();
tactic_report report("dt2bv", *g);
unsigned size = g->size();
@ -155,7 +150,7 @@ public:
for (auto const& kv : rw.enum2def())
filter->add(kv.m_key, kv.m_value);
mc = filter.get();
g->add(filter.get());
report_tactic_progress(":fd-num-translated", rw.num_translated());
}
g->inc_depth();

View file

@ -224,13 +224,8 @@ class elim_small_bv_tactic : public tactic {
m_rw.cfg().updt_params(p);
}
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void operator()(goal_ref const & g, goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
mc = 0; pc = 0; core = 0;
tactic_report report("elim-small-bv", *g);
bool produce_proofs = g->proofs_enabled();
fail_if_proof_generation("elim-small-bv", g);
@ -250,7 +245,7 @@ class elim_small_bv_tactic : public tactic {
}
g->update(idx, new_curr, new_pr, g->dep(idx));
}
mc = m_rw.m_cfg.m_mc.get();
g->add(m_rw.m_cfg.m_mc.get());
report_tactic_progress(":elim-small-bv-num-eliminated", m_rw.m_cfg.m_num_eliminated);
g->inc_depth();
@ -288,11 +283,8 @@ public:
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(in, result, mc, pc, core);
goal_ref_buffer & result) {
(*m_imp)(in, result);
}
virtual void cleanup() {

View file

@ -237,12 +237,8 @@ class max_bv_sharing_tactic : public tactic {
ast_manager & m() const { return m_rw.m(); }
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
mc = 0; pc = 0; core = 0;
tactic_report report("max-bv-sharing", *g);
bool produce_proofs = g->proofs_enabled();
@ -299,11 +295,8 @@ public:
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(in, result, mc, pc, core);
goal_ref_buffer & result) {
(*m_imp)(in, result);
}
virtual void cleanup() {

View file

@ -113,13 +113,8 @@ class blast_term_ite_tactic : public tactic {
m_rw.cfg().updt_params(p);
}
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void operator()(goal_ref const & g, goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
mc = 0; pc = 0; core = 0;
tactic_report report("blast-term-ite", *g);
bool produce_proofs = g->proofs_enabled();
@ -172,11 +167,8 @@ public:
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(in, result, mc, pc, core);
goal_ref_buffer & result) {
(*m_imp)(in, result);
}
virtual void cleanup() {

View file

@ -54,16 +54,11 @@ public:
virtual void updt_params(params_ref const & p) { m_params = p; m_elim_ite.updt_params(p); }
virtual void collect_param_descrs(param_descrs & r) { m_elim_ite.collect_param_descrs(r); }
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void operator()(goal_ref const & g, goal_ref_buffer& result) override {
SASSERT(g->is_well_sorted());
fail_if_proof_generation("cofactor-term-ite", g);
fail_if_unsat_core_generation("cofactor-term-ite", g);
tactic_report report("cofactor-term-ite", *g);
mc = 0; pc = 0; core = 0;
process(*(g.get()));
g->inc_depth();
result.push_back(g.get());

View file

@ -63,10 +63,7 @@ public:
virtual void collect_param_descrs(param_descrs & r) {}
virtual void operator()(goal_ref const & g, goal_ref_buffer & result,
model_converter_ref & mc, proof_converter_ref & pc,
expr_dependency_ref & core) {
mc = 0;
virtual void operator()(goal_ref const & g, goal_ref_buffer & result) {
tactic_report report("collect-statistics", *g);
collect_proc cp(m, m_stats);
@ -76,10 +73,8 @@ public:
for_each_expr(cp, visited, g->form(i));
std::cout << "(" << std::endl;
stats_type::iterator it = m_stats.begin();
stats_type::iterator end = m_stats.end();
for (; it != end; it++)
std::cout << " :" << it->first << " " << it->second << std::endl;
for (auto const& kv : m_stats)
std::cout << " :" << kv.first << " " << kv.second << std::endl;
std::cout << ")" << std::endl;
g->inc_depth();

View file

@ -621,11 +621,7 @@ void ctx_simplify_tactic::get_param_descrs(param_descrs & r) {
}
void ctx_simplify_tactic::operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
mc = 0; pc = 0; core = 0;
goal_ref_buffer & result) {
(*m_imp)(*(in.get()));
in->inc_depth();
result.push_back(in.get());

View file

@ -55,10 +55,7 @@ public:
virtual void collect_param_descrs(param_descrs & r) { get_param_descrs(r); }
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core);
goal_ref_buffer & result);
virtual void cleanup();
};

View file

@ -74,11 +74,7 @@ public:
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
mc = 0; pc = 0; core = 0;
goal_ref_buffer & result) {
(*m_imp)(*(in.get()));
in->inc_depth();
result.push_back(in.get());

View file

@ -100,16 +100,13 @@ public:
}
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
ast_manager & m = g->m();
bool produce_proofs = g->proofs_enabled();
rw r(m, produce_proofs);
m_rw = &r;
mc = 0; pc = 0; core = 0; result.reset();
result.reset();
tactic_report report("distribute-forall", *g);
expr_ref new_curr(m);

View file

@ -183,19 +183,11 @@ tactic * dom_simplify_tactic::translate(ast_manager & m) {
return alloc(dom_simplify_tactic, m, m_simplifier->translate(m), m_params);
}
void dom_simplify_tactic::operator()(
goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
mc = 0; pc = 0; core = 0;
void dom_simplify_tactic::operator()(goal_ref const & in, goal_ref_buffer & result) {
tactic_report report("dom-simplify", *in.get());
simplify_goal(*(in.get()));
in->inc_depth();
result.push_back(in.get());
}
void dom_simplify_tactic::cleanup() {

View file

@ -137,11 +137,7 @@ public:
static void get_param_descrs(param_descrs & r) {}
virtual void collect_param_descrs(param_descrs & r) { get_param_descrs(r); }
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core);
void operator()(goal_ref const & in, goal_ref_buffer & result) override;
virtual void cleanup();
};

View file

@ -100,12 +100,8 @@ class elim_term_ite_tactic : public tactic {
}
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
mc = 0; pc = 0; core = 0;
tactic_report report("elim-term-ite", *g);
bool produce_proofs = g->proofs_enabled();
m_rw.cfg().m_produce_models = g->models_enabled();
@ -124,7 +120,7 @@ class elim_term_ite_tactic : public tactic {
}
g->update(idx, new_curr, new_pr, g->dep(idx));
}
mc = m_rw.m_cfg.m_mc.get();
g->add(m_rw.m_cfg.m_mc.get());
report_tactic_progress(":elim-term-ite-consts", m_rw.m_cfg.m_num_fresh);
g->inc_depth();
result.push_back(g.get());
@ -162,11 +158,8 @@ public:
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(in, result, mc, pc, core);
goal_ref_buffer & result) {
(*m_imp)(in, result);
}
virtual void cleanup() {

View file

@ -816,11 +816,7 @@ class elim_uncnstr_tactic : public tactic {
}
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
mc = 0; pc = 0; core = 0;
goal_ref_buffer & result) {
bool produce_models = g->models_enabled();
bool produce_proofs = g->proofs_enabled();
@ -865,8 +861,7 @@ class elim_uncnstr_tactic : public tactic {
g->update(idx, new_f, new_pr, g->dep(idx));
}
if (!modified) {
if (round == 0) {
mc = 0;
if (round == 0) {
}
else {
app_ref_vector & fresh_vars = m_rw->cfg().m_fresh_vars;
@ -875,15 +870,14 @@ class elim_uncnstr_tactic : public tactic {
generic_model_converter * fmc = alloc(generic_model_converter, m());
for (app * f : fresh_vars)
fmc->hide(f);
mc = concat(fmc, m_mc.get());
g->add(concat(fmc, m_mc.get()));
}
else {
mc = 0;
g->set((model_converter*)nullptr);
}
}
m_mc = 0;
m_rw = 0;
TRACE("elim_uncnstr", if (mc) mc->display(tout););
result.push_back(g.get());
g->inc_depth();
return;
@ -933,11 +927,8 @@ public:
}
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(g, result, mc, pc, core);
goal_ref_buffer & result) {
(*m_imp)(g, result);
report_tactic_progress(":num-elim-apps", get_num_elim_apps());
}

View file

@ -144,12 +144,8 @@ class injectivity_tactic : public tactic {
}
void operator()(goal_ref const & goal,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
SASSERT(goal->is_well_sorted());
mc = 0; pc = 0; core = 0;
tactic_report report("injectivity", *goal);
fail_if_unsat_core_generation("injectivity", goal); // TODO: Support UNSAT cores
fail_if_proof_generation("injectivity", goal);
@ -271,11 +267,8 @@ public:
}
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_finder)(g, result, mc, pc, core);
goal_ref_buffer & result) {
(*m_finder)(g, result);
for (unsigned i = 0; i < g->size(); ++i) {
expr* curr = g->form(i);

View file

@ -54,13 +54,9 @@ public:
virtual void collect_param_descrs(param_descrs & r) { nnf::get_param_descrs(r); }
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
TRACE("nnf", tout << "params: " << m_params << "\n"; g->display(tout););
SASSERT(g->is_well_sorted());
mc = 0; pc = 0; core = 0;
tactic_report report("nnf", *g);
bool produce_proofs = g->proofs_enabled();
@ -98,7 +94,7 @@ public:
unsigned num_extra_names = dnames.get_num_names();
if (num_extra_names > 0) {
generic_model_converter * fmc = alloc(generic_model_converter, m);
mc = fmc;
g->add(fmc);
for (unsigned i = 0; i < num_extra_names; i++)
fmc->hide(dnames.get_name_decl(i));
}

View file

@ -128,13 +128,9 @@ class occf_tactic : public tactic {
}
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
mc = 0; pc = 0; core = 0;
fail_if_proof_generation("occf", g);
bool produce_models = g->models_enabled();
@ -158,7 +154,7 @@ class occf_tactic : public tactic {
continue;
if (produce_models && !m_mc) {
m_mc = alloc(generic_model_converter, m);
mc = m_mc;
g->add(m_mc);
}
expr * keep = 0;
new_lits.reset();
@ -211,11 +207,8 @@ public:
virtual void collect_param_descrs(param_descrs & r) {}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(in, result, mc, pc, core);
goal_ref_buffer & result) {
(*m_imp)(in, result);
}
virtual void cleanup() {

View file

@ -48,8 +48,7 @@ class pb_preproc_model_converter : public model_converter {
public:
pb_preproc_model_converter(ast_manager& m):m(m), pb(m), m_refs(m) {}
virtual void operator()(model_ref & mdl, unsigned goal_idx) {
SASSERT(goal_idx == 0);
virtual void operator()(model_ref & mdl) {
for (auto const& kv : m_const) {
mdl->register_decl(kv.first->get_decl(), kv.second);
}
@ -148,21 +147,17 @@ public:
return alloc(pb_preprocess_tactic, m);
}
virtual void operator()(
void operator()(
goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) override {
SASSERT(g->is_well_sorted());
pc = 0; core = 0;
if (g->proofs_enabled()) {
throw tactic_exception("pb-preprocess does not support proofs");
}
pb_preproc_model_converter* pp = alloc(pb_preproc_model_converter, m);
mc = pp;
g->add(pp);
g->inc_depth();
result.push_back(g.get());

View file

@ -136,12 +136,8 @@ class propagate_values_tactic : public tactic {
}
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
mc = 0; pc = 0; core = 0;
tactic_report report("propagate-values", *g);
m_goal = g.get();
@ -240,13 +236,9 @@ public:
r.insert("max_rounds", CPK_UINT, "(default: 2) maximum number of rounds.");
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void operator()(goal_ref const & in, goal_ref_buffer & result) override {
try {
(*m_imp)(in, result, mc, pc, core);
(*m_imp)(in, result);
}
catch (rewriter_exception & ex) {
throw tactic_exception(ex.msg());

View file

@ -73,8 +73,8 @@ public:
virtual ~reduce_args_tactic();
virtual void operator()(goal_ref const & g, goal_ref_buffer & result, model_converter_ref & mc, proof_converter_ref & pc, expr_dependency_ref & core);
virtual void cleanup();
void operator()(goal_ref const & g, goal_ref_buffer & result) override;
void cleanup() override;
};
tactic * mk_reduce_args_tactic(ast_manager & m, params_ref const & p) {
@ -439,7 +439,7 @@ struct reduce_args_tactic::imp {
return f_mc;
}
void operator()(goal & g, model_converter_ref & mc) {
void operator()(goal & g) {
if (g.inconsistent())
return;
TRACE("reduce_args", g.display(tout););
@ -468,9 +468,9 @@ struct reduce_args_tactic::imp {
report_tactic_progress(":reduced-funcs", decl2args.size());
if (g.models_enabled())
mc = mk_mc(decl2args, ctx.m_decl2arg2funcs);
g.add(mk_mc(decl2args, ctx.m_decl2arg2funcs));
TRACE("reduce_args", g.display(tout); if (mc) mc->display(tout););
TRACE("reduce_args", g.display(tout); if (g.mc()) g.mc()->display(tout););
}
};
@ -483,15 +483,12 @@ reduce_args_tactic::~reduce_args_tactic() {
}
void reduce_args_tactic::operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
fail_if_proof_generation("reduce-args", g);
fail_if_unsat_core_generation("reduce-args", g);
mc = 0; pc = 0; core = 0; result.reset();
m_imp->operator()(*(g.get()), mc);
result.reset();
m_imp->operator()(*(g.get()));
g->inc_depth();
result.push_back(g.get());
SASSERT(g->is_well_sorted());

View file

@ -93,15 +93,11 @@ void simplify_tactic::get_param_descrs(param_descrs & r) {
}
void simplify_tactic::operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
try {
(*m_imp)(*(in.get()));
in->inc_depth();
result.push_back(in.get());
mc = 0; pc = 0; core = 0;
}
catch (rewriter_exception & ex) {
throw tactic_exception(ex.msg());

View file

@ -30,21 +30,19 @@ public:
simplify_tactic(ast_manager & m, params_ref const & ref = params_ref());
virtual ~simplify_tactic();
virtual void updt_params(params_ref const & p);
void updt_params(params_ref const & p) override;
static void get_param_descrs(param_descrs & r);
virtual void collect_param_descrs(param_descrs & r) { get_param_descrs(r); }
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core);
void collect_param_descrs(param_descrs & r) override { get_param_descrs(r); }
virtual void cleanup();
void operator()(goal_ref const & in, goal_ref_buffer & result) override;
void cleanup() override;
unsigned get_num_steps() const;
virtual tactic * translate(ast_manager & m) { return alloc(simplify_tactic, m, m_params); }
tactic * translate(ast_manager & m) override { return alloc(simplify_tactic, m, m_params); }
};

View file

@ -666,13 +666,9 @@ class solve_eqs_tactic : public tactic {
return m_num_eliminated_vars;
}
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void operator()(goal_ref const & g, goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
mc = 0; pc = 0; core = 0;
model_converter_ref mc;
tactic_report report("solve_eqs", *g);
m_produce_models = g->models_enabled();
m_produce_proofs = g->proofs_enabled();
@ -692,7 +688,6 @@ class solve_eqs_tactic : public tactic {
normalize();
substitute(*(g.get()));
if (g->inconsistent()) {
mc = 0;
break;
}
save_elim_vars(mc);
@ -700,6 +695,7 @@ class solve_eqs_tactic : public tactic {
}
}
g->inc_depth();
g->add(mc.get());
result.push_back(g.get());
TRACE("solve_eqs", g->display(tout););
SASSERT(g->is_well_sorted());
@ -733,12 +729,9 @@ public:
r.insert("ite_solver", CPK_BOOL, "(default: true) use if-then-else solver.");
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(in, result, mc, pc, core);
void operator()(goal_ref const & in,
goal_ref_buffer & result) override {
(*m_imp)(in, result);
report_tactic_progress(":num-elim-vars", m_imp->get_num_eliminated_vars());
}

View file

@ -46,21 +46,16 @@ class split_clause_tactic : public tactic {
}
class split_pc : public proof_converter {
ast_manager & m_manager;
app * m_clause;
proof * m_clause_pr;
ast_manager & m;
app_ref m_clause;
proof_ref m_clause_pr;
public:
split_pc(ast_manager & m, app * cls, proof * pr):m_manager(m), m_clause(cls), m_clause_pr(pr) {
m.inc_ref(cls);
m.inc_ref(pr);
split_pc(ast_manager & m, app * cls, proof * pr):m(m), m_clause(cls, m), m_clause_pr(pr, m) {
}
~split_pc() {
m_manager.dec_ref(m_clause);
m_manager.dec_ref(m_clause_pr);
}
virtual ~split_pc() { }
virtual void operator()(ast_manager & m, unsigned num_source, proof * const * source, proof_ref & result) {
proof_ref operator()(ast_manager & m, unsigned num_source, proof * const * source) override {
// Let m_clause be of the form (l_0 or ... or l_{num_source - 1})
// Each source[i] proof is a proof for "false" using l_i as a hypothesis
// So, I use lemma for producing a proof for (not l_i) that does not contain the hypothesis,
@ -73,14 +68,14 @@ class split_clause_tactic : public tactic {
expr * not_li = m.mk_not(m_clause->get_arg(i));
prs.push_back(m.mk_lemma(pr_i, not_li));
}
result = m.mk_unit_resolution(prs.size(), prs.c_ptr());
return proof_ref(m.mk_unit_resolution(prs.size(), prs.c_ptr()), m);
}
virtual proof_converter * translate(ast_translation & translator) {
return alloc(split_pc, translator.to(), translator(m_clause), translator(m_clause_pr));
proof_converter * translate(ast_translation & translator) override {
return alloc(split_pc, translator.to(), translator(m_clause.get()), translator(m_clause_pr.get()));
}
virtual void display(std::ostream & out) { out << "(split-clause-pc)\n"; }
void display(std::ostream & out) override { out << "(split-clause-pc)\n"; }
};
public:
@ -97,23 +92,19 @@ public:
virtual ~split_clause_tactic() {
}
virtual void updt_params(params_ref const & p) {
void updt_params(params_ref const & p) override {
m_largest_clause = p.get_bool("split_largest_clause", false);
}
virtual void collect_param_descrs(param_descrs & r) {
void collect_param_descrs(param_descrs & r) override {
r.insert("split_largest_clause", CPK_BOOL, "(default: false) split the largest clause in the goal.");
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void operator()(goal_ref const & in,
goal_ref_buffer & result) override {
SASSERT(in->is_well_sorted());
tactic_report report("split-clause", *in);
TRACE("before_split_clause", in->display(tout););
pc = 0; mc = 0; core = 0;
ast_manager & m = in->m();
unsigned cls_pos = select_clause(m, in);
if (cls_pos == UINT_MAX) {
@ -123,16 +114,11 @@ public:
app * cls = to_app(in->form(cls_pos));
expr_dependency * cls_dep = in->dep(cls_pos);
if (produce_proofs)
pc = alloc(split_pc, m, cls, in->pr(cls_pos));
unsigned cls_sz = cls->get_num_args();
report_tactic_progress(":num-new-branches", cls_sz);
for (unsigned i = 0; i < cls_sz; i++) {
goal * subgoal_i;
if (i == cls_sz - 1)
subgoal_i = in.get();
else
subgoal_i = alloc(goal, *in);
expr * lit_i = cls->get_arg(i);
in->set(alloc(split_pc, m, cls, in->pr(cls_pos)));
report_tactic_progress(":num-new-branches", cls->get_num_args());
for (expr* lit_i : *cls) {
goal * subgoal_i = alloc(goal, *in);
subgoal_i->set(in->mc());
proof * pr_i = 0;
if (produce_proofs)
pr_i = m.mk_hypothesis(lit_i);
@ -140,6 +126,8 @@ public:
subgoal_i->inc_depth();
result.push_back(subgoal_i);
}
in->set(concat(in->pc(), result.size(), result.c_ptr()));
in->add(dependency_converter::concat(result.size(), result.c_ptr()));
}
virtual void cleanup() {

View file

@ -39,10 +39,7 @@ public:
virtual ~symmetry_reduce_tactic();
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core);
goal_ref_buffer & result);
virtual void cleanup();
};
@ -635,13 +632,10 @@ symmetry_reduce_tactic::~symmetry_reduce_tactic() {
}
void symmetry_reduce_tactic::operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
fail_if_proof_generation("symmetry_reduce", g);
fail_if_unsat_core_generation("symmetry_reduce", g);
mc = 0; pc = 0; core = 0; result.reset();
result.reset();
(*m_imp)(*(g.get()));
g->inc_depth();
result.push_back(g.get());

View file

@ -799,12 +799,8 @@ class tseitin_cnf_tactic : public tactic {
}
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
mc = 0; pc = 0; core = 0;
tactic_report report("tseitin-cnf", *g);
fail_if_proof_generation("tseitin-cnf", g);
m_produce_models = g->models_enabled();
@ -843,9 +839,7 @@ class tseitin_cnf_tactic : public tactic {
g->assert_expr(cls);
}
if (m_produce_models && !m_fresh_vars.empty())
mc = m_mc.get();
else
mc = 0;
g->add(m_mc.get());
g->inc_depth();
result.push_back(g.get());
TRACE("tseitin_cnf", g->display(tout););
@ -884,11 +878,8 @@ public:
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(in, result, mc, pc, core);
goal_ref_buffer & result) {
(*m_imp)(in, result);
report_tactic_progress(":cnf-aux-vars", m_imp->m_num_aux_vars);
}

View file

@ -0,0 +1,107 @@
/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
dependency_converter.cpp
Abstract:
Utility for converting dependencies across subgoals.
Author:
Nikolaj Bjorner (nbjorner) 2017-11-19
Notes:
--*/
#include "tactic/dependency_converter.h"
#include "tactic/goal.h"
class unit_dependency_converter : public dependency_converter {
expr_dependency_ref m_dep;
public:
unit_dependency_converter(expr_dependency_ref& d) : m_dep(d) {}
virtual expr_dependency_ref operator()() { return m_dep; }
virtual dependency_converter * translate(ast_translation & translator) {
expr_dependency_translation tr(translator);
expr_dependency_ref d(tr(m_dep), translator.to());
return alloc(unit_dependency_converter, d);
}
virtual void display(std::ostream& out) {
out << m_dep << "\n";
}
};
class concat_dependency_converter : public dependency_converter {
dependency_converter_ref m_dc1;
dependency_converter_ref m_dc2;
public:
concat_dependency_converter(dependency_converter* c1, dependency_converter* c2) : m_dc1(c1), m_dc2(c2) {}
virtual expr_dependency_ref operator()() {
expr_dependency_ref d1 = (*m_dc1)();
expr_dependency_ref d2 = (*m_dc2)();
ast_manager& m = d1.get_manager();
return expr_dependency_ref(m.mk_join(d1, d2), m);
}
virtual dependency_converter * translate(ast_translation & translator) {
return alloc(concat_dependency_converter, m_dc1->translate(translator), m_dc2->translate(translator));
}
virtual void display(std::ostream& out) {
m_dc1->display(out);
m_dc2->display(out);
}
};
class goal_dependency_converter : public dependency_converter {
ast_manager& m;
goal_ref_buffer m_goals;
public:
goal_dependency_converter(unsigned n, goal * const* goals) :
m(goals[0]->m()) {
for (unsigned i = 0; i < n; ++i) m_goals.push_back(goals[i]);
}
virtual expr_dependency_ref operator()() {
expr_dependency_ref result(m.mk_empty_dependencies(), m);
for (goal_ref g : m_goals) {
dependency_converter_ref dc = g->dc();
if (dc) result = m.mk_join(result, (*dc)());
}
return result;
}
virtual dependency_converter * translate(ast_translation & translator) {
goal_ref_buffer goals;
for (goal_ref g : m_goals) goals.push_back(g->translate(translator));
return alloc(goal_dependency_converter, goals.size(), goals.c_ptr());
}
virtual void display(std::ostream& out) { out << "goal-dep\n"; }
};
dependency_converter * dependency_converter::concat(dependency_converter * mc1, dependency_converter * mc2) {
if (!mc1) return mc2;
if (!mc2) return mc1;
return alloc(concat_dependency_converter, mc1, mc2);
}
dependency_converter* dependency_converter::unit(expr_dependency_ref& d) {
return alloc(unit_dependency_converter, d);
}
dependency_converter * dependency_converter::concat(unsigned n, goal * const* goals) {
if (n == 0) return nullptr;
return alloc(goal_dependency_converter, n, goals);
}

View file

@ -0,0 +1,47 @@
/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
dependency_converter.h
Abstract:
Utility for converting dependencies across subgoals.
Author:
Nikolaj Bjorner (nbjorner) 2017-11-19
Notes:
--*/
#ifndef DEPENDENCY_CONVERTER_H_
#define DEPENDENCY_CONVERTER_H_
#include "util/ref.h"
#include "ast/ast_pp_util.h"
#include "model/model.h"
#include "tactic/converter.h"
class goal;
class dependency_converter : public converter {
public:
static dependency_converter* unit(expr_dependency_ref& d);
static dependency_converter* concat(dependency_converter * dc1, dependency_converter * dc2);
static dependency_converter* concat(unsigned n, goal * const* goals);
virtual expr_dependency_ref operator()() = 0;
virtual dependency_converter * translate(ast_translation & translator) = 0;
};
typedef ref<dependency_converter> dependency_converter_ref;
typedef sref_vector<dependency_converter> dependency_converter_ref_vector;
typedef sref_buffer<dependency_converter> dependency_converter_ref_buffer;
#endif

View file

@ -35,11 +35,11 @@ public:
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);
proof_ref operator()(ast_manager & m, unsigned num_source, proof * const * source) override {
return m_replace(m, num_source, source);
}
virtual proof_converter * translate(ast_translation & translator) {
proof_converter * translate(ast_translation & translator) override {
return m_replace.translate(translator);
}
@ -47,7 +47,7 @@ public:
ast_manager& get_manager() { return m; }
virtual void display(std::ostream & out) {}
void display(std::ostream & out) override {}
};
#endif

View file

@ -37,20 +37,16 @@ public:
dealloc(m_bv2fp);
}
virtual void operator()(model_ref & md, unsigned goal_idx) {
SASSERT(goal_idx == 0);
void operator()(model_ref & md) override {
model * new_model = alloc(model, m);
convert(md.get(), new_model);
md = new_model;
}
virtual void operator()(model_ref & md) {
operator()(md, 0);
}
void display(std::ostream & out);
void display(std::ostream & out) override;
virtual model_converter * translate(ast_translation & translator);
model_converter * translate(ast_translation & translator) override;
protected:
fpa2bv_model_converter(ast_manager & m) :

View file

@ -47,16 +47,13 @@ class fpa2bv_tactic : public tactic {
}
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
m_proofs_enabled = g->proofs_enabled();
m_produce_models = g->models_enabled();
m_produce_unsat_cores = g->unsat_core_enabled();
mc = 0; pc = 0; core = 0; result.reset();
result.reset();
tactic_report report("fpa2bv", *g);
m_rw.reset();
@ -100,7 +97,7 @@ class fpa2bv_tactic : public tactic {
}
if (g->models_enabled())
mc = mk_fpa2bv_model_converter(m, m_conv);
g->add(mk_fpa2bv_model_converter(m, m_conv));
g->inc_depth();
result.push_back(g.get());
@ -110,7 +107,7 @@ class fpa2bv_tactic : public tactic {
SASSERT(g->is_well_sorted());
TRACE("fpa2bv", tout << "AFTER: " << std::endl; g->display(tout);
if (mc) mc->display(tout); tout << std::endl; );
if (g->mc()) g->mc()->display(tout); tout << std::endl; );
}
};
@ -140,12 +137,9 @@ public:
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
try {
(*m_imp)(in, result, mc, pc, core);
(*m_imp)(in, result);
}
catch (rewriter_exception & ex) {
throw tactic_exception(ex.msg());

View file

@ -24,8 +24,7 @@ Notes:
#include "model/model_evaluator.h"
void generic_model_converter::operator()(model_ref & md, unsigned goal_idx) {
std::cout << "model converter\n";
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);
@ -34,13 +33,11 @@ void generic_model_converter::operator()(model_ref & md, unsigned goal_idx) {
unsigned arity;
for (unsigned i = m_hide_entries.size(); i-- > 0; ) {
entry const& e = m_hide_entries[i];
std::cout << "hide " << e.m_f << "\n";
md->unregister_decl(e.m_f);
}
for (unsigned i = m_add_entries.size(); i-- > 0; ) {
entry const& e = m_add_entries[i];
ev(e.m_def, val);
std::cout << e.m_f << " " << e.m_def << " " << val << "\n";
TRACE("model_converter", tout << e.m_f->get_name() << " ->\n" << e.m_def << "\n==>\n" << val << "\n";);
arity = e.m_f->get_arity();
if (arity == 0) {

View file

@ -52,19 +52,17 @@ public:
void add(expr * d, expr* e) { SASSERT(is_app(d) && to_app(d)->get_num_args() == 0); add(to_app(d)->get_decl(), e); }
virtual void operator()(model_ref & md, unsigned goal_idx);
virtual void operator()(svector<symbol> & labels, unsigned goal_idx) {}
void operator()(labels_vec & labels) override {}
virtual void operator()(model_ref & md) { operator()(md, 0); }
void operator()(model_ref & md) override;
virtual void cancel() {}
void cancel() override {}
virtual void display(std::ostream & out);
void display(std::ostream & out) override;
virtual model_converter * translate(ast_translation & translator);
model_converter * translate(ast_translation & translator) override;
virtual void collect(ast_pp_util& visitor);
void collect(ast_pp_util& visitor) override;
void operator()(expr_ref& fml) override;
};

View file

@ -16,11 +16,11 @@ Author:
Revision History:
--*/
#include "tactic/goal.h"
#include "ast/ast_ll_pp.h"
#include "ast/ast_smt2_pp.h"
#include "ast/for_each_expr.h"
#include "ast/well_sorted.h"
#include "tactic/goal.h"
goal::precision goal::mk_union(precision p1, precision p2) {
if (p1 == PRECISE) return p2;
@ -105,6 +105,9 @@ void goal::copy_to(goal & target) const {
SASSERT(target.m_core_enabled == m_core_enabled);
target.m_inconsistent = m_inconsistent;
target.m_precision = mk_union(prec(), target.prec());
target.m_mc = m_mc.get();
target.m_pc = m_pc.get();
target.m_dc = m_dc.get();
}
void goal::push_back(expr * f, proof * pr, expr_dependency * d) {
@ -344,10 +347,7 @@ void goal::display_with_dependencies(ast_printer & prn, std::ostream & out) cons
out << "\n |-";
deps.reset();
m().linearize(dep(i), deps);
ptr_vector<expr>::iterator it = deps.begin();
ptr_vector<expr>::iterator end = deps.end();
for (; it != end; ++it) {
expr * d = *it;
for (expr * d : deps) {
if (is_uninterp_const(d)) {
out << " " << mk_ismt2_pp(d, m());
}
@ -361,10 +361,7 @@ void goal::display_with_dependencies(ast_printer & prn, std::ostream & out) cons
}
if (!to_pp.empty()) {
out << "\n :dependencies-definitions (";
obj_hashtable<expr>::iterator it = to_pp.begin();
obj_hashtable<expr>::iterator end = to_pp.end();
for (; it != end; ++it) {
expr * d = *it;
for (expr* d : to_pp) {
out << "\n (#" << d->get_id() << "\n ";
prn.display(out, d, 2);
out << ")";
@ -382,10 +379,7 @@ void goal::display_with_dependencies(std::ostream & out) const {
out << "\n |-";
deps.reset();
m().linearize(dep(i), deps);
ptr_vector<expr>::iterator it = deps.begin();
ptr_vector<expr>::iterator end = deps.end();
for (; it != end; ++it) {
expr * d = *it;
for (expr * d : deps) {
if (is_uninterp_const(d)) {
out << " " << mk_ismt2_pp(d, m());
}
@ -510,14 +504,12 @@ void goal::shrink(unsigned j) {
unsigned sz = size();
for (unsigned i = j; i < sz; i++)
m().pop_back(m_forms);
if (proofs_enabled()) {
if (proofs_enabled())
for (unsigned i = j; i < sz; i++)
m().pop_back(m_proofs);
}
if (unsat_core_enabled()) {
if (unsat_core_enabled())
for (unsigned i = j; i < sz; i++)
m().pop_back(m_dependencies);
}
}
/**
@ -662,6 +654,9 @@ goal * goal::translate(ast_translation & translator) const {
res->m_inconsistent = m_inconsistent;
res->m_depth = m_depth;
res->m_precision = m_precision;
res->m_pc = m_pc ? m_pc->translate(translator) : nullptr;
res->m_mc = m_mc ? m_mc->translate(translator) : nullptr;
res->m_dc = m_dc ? m_dc->translate(translator) : nullptr;
return res;
}

View file

@ -35,6 +35,9 @@ Revision History:
#include "util/ref.h"
#include "util/ref_vector.h"
#include "util/ref_buffer.h"
#include "tactic/model_converter.h"
#include "tactic/proof_converter.h"
#include "tactic/dependency_converter.h"
class goal {
public:
@ -49,6 +52,9 @@ public:
protected:
ast_manager & m_manager;
model_converter_ref m_mc;
proof_converter_ref m_pc;
dependency_converter_ref m_dc;
unsigned m_ref_count;
expr_array m_forms;
expr_array m_proofs;
@ -71,6 +77,7 @@ protected:
unsigned get_not_idx(expr * f) const;
void shrink(unsigned j);
void reset_core();
public:
goal(ast_manager & m, bool models_enabled = true, bool core_enabled = false);
@ -103,7 +110,7 @@ public:
void copy_to(goal & target) const;
void copy_from(goal const & src) { src.copy_to(*this); }
void assert_expr(expr * f, proof * pr, expr_dependency * d);
void assert_expr(expr * f, expr_dependency * d);
void assert_expr(expr * f, expr * d) { assert_expr(f, m().mk_leaf(d)); }
@ -142,6 +149,16 @@ public:
bool is_decided() const;
bool is_well_sorted() const;
dependency_converter* dc() { return m_dc.get(); }
model_converter* mc() { return m_mc.get(); }
proof_converter* pc() { return inconsistent() ? proof2proof_converter(m(), pr(0)) : m_pc.get(); }
void add(dependency_converter* d) { m_dc = dependency_converter::concat(m_dc.get(), d); }
void add(model_converter* m) { m_mc = concat(m_mc.get(), m); }
void add(proof_converter* p) { m_pc = concat(m_pc.get(), p); }
void set(dependency_converter* d) { m_dc = d; }
void set(model_converter* m) { m_mc = m; }
void set(proof_converter* p) { m_pc = p; }
goal * translate(ast_translation & translator) const;
};

View file

@ -68,14 +68,9 @@ public:
this->m_c2->operator()(fml);
}
void operator()(model_ref & m, unsigned goal_idx) override {
this->m_c2->operator()(m, goal_idx);
this->m_c1->operator()(m, 0);
}
void operator()(labels_vec & r, unsigned goal_idx) override {
this->m_c2->operator()(r, goal_idx);
this->m_c1->operator()(r, 0);
void operator()(labels_vec & r) override {
this->m_c2->operator()(r);
this->m_c1->operator()(r);
}
char const * get_name() const override { return "concat-model-converter"; }
@ -98,75 +93,6 @@ model_converter * concat(model_converter * mc1, model_converter * mc2) {
return alloc(concat_model_converter, mc1, mc2);
}
class concat_star_model_converter : public concat_star_converter<model_converter> {
public:
concat_star_model_converter(model_converter * mc1, unsigned num, model_converter * const * mc2s, unsigned * szs):
concat_star_converter<model_converter>(mc1, num, mc2s, szs) {
}
void operator()(model_ref & m) override {
// TODO: delete method after conversion is complete
UNREACHABLE();
}
void operator()(model_ref & m, unsigned goal_idx) override {
unsigned num = this->m_c2s.size();
for (unsigned i = 0; i < num; i++) {
if (goal_idx < this->m_szs[i]) {
// found the model converter that should be used
model_converter * c2 = this->m_c2s[i];
if (c2)
c2->operator()(m, goal_idx);
if (m_c1)
this->m_c1->operator()(m, i);
return;
}
// invalid goal
goal_idx -= this->m_szs[i];
}
UNREACHABLE();
}
void operator()(labels_vec & r, unsigned goal_idx) override {
unsigned num = this->m_c2s.size();
for (unsigned i = 0; i < num; i++) {
if (goal_idx < this->m_szs[i]) {
// found the model converter that should be used
model_converter * c2 = this->m_c2s[i];
if (c2)
c2->operator()(r, goal_idx);
if (m_c1)
this->m_c1->operator()(r, i);
return;
}
// invalid goal
goal_idx -= this->m_szs[i];
}
UNREACHABLE();
}
char const * get_name() const override { return "concat-star-model-converter"; }
model_converter * translate(ast_translation & translator) override {
return this->translate_core<concat_star_model_converter>(translator);
}
};
model_converter * concat(model_converter * mc1, unsigned num, model_converter * const * mc2s, unsigned * szs) {
SASSERT(num > 0);
if (num == 1)
return concat(mc1, mc2s[0]);
unsigned i;
for (i = 0; i < num; i++) {
if (mc2s[i] != 0)
break;
}
if (i == num) {
// all mc2s are 0
return mc1;
}
return alloc(concat_star_model_converter, mc1, num, mc2s, szs);
}
class model2mc : public model_converter {
model_ref m_model;
@ -182,11 +108,7 @@ public:
m = m_model;
}
void operator()(model_ref & m, unsigned goal_idx) override {
m = m_model;
}
void operator()(labels_vec & r, unsigned goal_idx) {
void operator()(labels_vec & r) {
r.append(m_labels.size(), m_labels.c_ptr());
}
@ -227,13 +149,13 @@ model_converter * model_and_labels2model_converter(model * m, buffer<symbol> & r
void model_converter2model(ast_manager & mng, model_converter * mc, model_ref & m) {
if (mc) {
m = alloc(model, mng);
(*mc)(m, 0);
(*mc)(m);
}
}
void apply(model_converter_ref & mc, model_ref & m, unsigned gidx) {
void apply(model_converter_ref & mc, model_ref & m) {
if (mc) {
(*mc)(m, gidx);
(*mc)(m);
}
}

View file

@ -15,14 +15,50 @@ Author:
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 retuns 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 definitinos
that are required to interpret G fully in the context of F_s.
--*/
#ifndef MODEL_CONVERTER_H_
#define MODEL_CONVERTER_H_
#include "util/ref.h"
#include "ast/ast_pp_util.h"
#include "model/model.h"
#include "tactic/converter.h"
#include "util/ref.h"
class labels_vec : public svector<symbol> {};
class smt2_pp_environment;
@ -36,17 +72,11 @@ protected:
public:
model_converter(): m_env(0) {}
model_converter(): m_env(nullptr) {}
virtual void operator()(model_ref & m) {} // TODO: delete
virtual void operator()(model_ref & m) = 0;
virtual void operator()(model_ref & m, unsigned goal_idx) {
// TODO: make it virtual after the transition to goal/tactic/tactical is complete
SASSERT(goal_idx == 0);
operator()(m);
}
virtual void operator()(labels_vec & r, unsigned goal_idx) {}
virtual void operator()(labels_vec & r) {}
virtual model_converter * translate(ast_translation & translator) = 0;
@ -61,25 +91,18 @@ public:
};
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);
/**
\brief \c mc1 is the model converter for a sequence of subgoals of size \c num.
Given an i in [0, num), mc2s[i] is the model converter for subgoal i,
and num_subgoals[i] is the number of subgoals of subgoals[i].
*/
model_converter * concat(model_converter * mc1, unsigned num, model_converter * const * mc2s, unsigned * num_subgoals);
model_converter * model2model_converter(model * m);
model_converter * model_and_labels2model_converter(model * m, buffer<symbol> &r);
void model_converter2model(ast_manager & mng, model_converter * mc, model_ref & m);
void apply(model_converter_ref & mc, model_ref & m, unsigned gidx);
void apply(model_converter_ref & mc, model_ref & m);
typedef sref_vector<model_converter> model_converter_ref_vector;
typedef sref_buffer<model_converter> model_converter_ref_buffer;
#endif

View file

@ -1,9 +0,0 @@
z3_add_component(nlsat_smt_tactic
SOURCES
nl_purify_tactic.cpp
COMPONENT_DEPENDENCIES
nlsat_tactic
smt_tactic
TACTIC_HEADERS
nl_purify_tactic.h
)

View file

@ -1,799 +0,0 @@
/*++
Copyright (c) 2015 Microsoft Corporation
Module Name:
nl_purify_tactic.cpp
Abstract:
Tactic for purifying quantifier-free formulas that mix QF_NRA and other theories.
It is designed to allow cooprating between the nlsat solver and other theories
in a decoupled way.
Let goal be formula F.
Let NL goal be formula G.
Assume F is in NNF.
Assume F does not contain mix of real/integers.
Assume F is quantifier-free (please, otherwise we need to reprocess from instantiated satisfiable formula)
For each atomic nl formula f,
- introduce a propositional variable p
- replace f by p
- add clauses p => f to G
For each interface term t,
- introduce interface variable v (or use t if it is already a variable)
- replace t by v
Check satisfiability of G.
If satisfiable, then check assignment to p and interface equalities on F
If unsat:
Retrieve core and add core to G.
else:
For interface equalities from model of F that are not equal in G, add
For interface variables that are equal under one model, but not the other model,
create interface predicate p_vw => v = w, add to both F, G.
Add interface equations to assumptions, recheck F.
If unsat retrieve core add to G.
Author:
Nikolaj Bjorner (nbjorner) 2015-5-5.
Revision History:
--*/
#include "tactic/tactical.h"
#include "tactic/nlsat_smt/nl_purify_tactic.h"
#include "smt/tactic/smt_tactic.h"
#include "ast/rewriter/rewriter.h"
#include "nlsat/tactic/nlsat_tactic.h"
#include "tactic/generic_model_converter.h"
#include "util/obj_pair_hashtable.h"
#include "ast/rewriter/rewriter_def.h"
#include "ast/ast_pp.h"
#include "util/trace.h"
#include "smt/smt_solver.h"
#include "solver/solver.h"
#include "model/model_smt2_pp.h"
#include "ast/rewriter/expr_safe_replace.h"
#include "ast/ast_util.h"
#include "solver/solver2tactic.h"
class nl_purify_tactic : public tactic {
enum polarity_t {
pol_pos,
pol_neg,
pol_dual
};
ast_manager & m;
arith_util m_util;
params_ref m_params;
bool m_produce_proofs;
ref<generic_model_converter> m_fmc;
tactic_ref m_nl_tac; // nlsat tactic
goal_ref m_nl_g; // nlsat goal
ref<solver> m_solver; // SMT solver
expr_ref_vector m_eq_preds; // predicates for equality between pairs of interface variables
svector<lbool> m_eq_values; // truth value of the equality predicates in nlsat
app_ref_vector m_new_reals; // interface real variables
app_ref_vector m_new_preds; // abstraction predicates for smt_solver (hide real constraints)
expr_ref_vector m_asms; // assumptions to pass to SMT solver
ptr_vector<expr> m_ctx_asms; // assumptions passed by context
obj_hashtable<expr> m_ctx_asms_set; // assumptions passed by context
obj_hashtable<expr> m_used_asms;
obj_map<expr, expr*> m_bool2dep;
obj_pair_map<expr,expr,expr*> m_eq_pairs; // map pairs of interface variables to auxiliary predicates
obj_map<expr,expr*> m_interface_cache; // map of compound real expression to interface variable.
obj_map<expr, polarity_t> m_polarities; // polarities of sub-expressions
public:
struct rw_cfg : public default_rewriter_cfg {
enum mode_t {
mode_interface_var,
mode_bool_preds
};
ast_manager& m;
nl_purify_tactic & m_owner;
app_ref_vector& m_new_reals;
app_ref_vector& m_new_preds;
obj_map<expr, polarity_t>& m_polarities;
obj_map<expr,expr*>& m_interface_cache;
expr_ref_vector m_args;
proof_ref_vector m_proofs;
mode_t m_mode;
rw_cfg(nl_purify_tactic & o):
m(o.m),
m_owner(o),
m_new_reals(o.m_new_reals),
m_new_preds(o.m_new_preds),
m_polarities(o.m_polarities),
m_interface_cache(o.m_interface_cache),
m_args(m),
m_proofs(m),
m_mode(mode_interface_var) {
}
virtual ~rw_cfg() {}
arith_util & u() { return m_owner.m_util; }
expr * mk_interface_var(expr* arg, proof_ref& arg_pr) {
expr* r;
if (m_interface_cache.find(arg, r)) {
return r;
}
if (is_uninterp_const(arg)) {
m_interface_cache.insert(arg, arg);
return arg;
}
r = m.mk_fresh_const(0, u().mk_real());
m_new_reals.push_back(to_app(r));
m_owner.m_fmc->hide(r);
m_interface_cache.insert(arg, r);
expr_ref eq(m);
eq = m.mk_eq(r, arg);
if (is_real_expression(arg)) {
m_owner.m_nl_g->assert_expr(eq); // m.mk_oeq(r, arg)
}
else {
m_owner.m_solver->assert_expr(eq);
}
if (m_owner.m_produce_proofs) {
arg_pr = m.mk_oeq(arg, r);
}
return r;
}
bool is_real_expression(expr* e) {
return is_app(e) && (to_app(e)->get_family_id() == u().get_family_id());
}
void mk_interface_bool(func_decl * f, unsigned num, expr* const* args, expr_ref& result, proof_ref& pr) {
expr_ref old_pred(m.mk_app(f, num, args), m);
polarity_t pol = m_polarities.find(old_pred);
result = m.mk_fresh_const(0, m.mk_bool_sort());
m_polarities.insert(result, pol);
m_new_preds.push_back(to_app(result));
m_owner.m_fmc->hide(result);
if (pol != pol_neg) {
m_owner.m_nl_g->assert_expr(m.mk_or(m.mk_not(result), old_pred));
}
if (pol != pol_pos) {
m_owner.m_nl_g->assert_expr(m.mk_or(result, m.mk_not(old_pred)));
}
if (m_owner.m_produce_proofs) {
pr = m.mk_oeq(old_pred, result);
}
TRACE("nlsat_smt", tout << old_pred << " : " << result << "\n";);
}
bool reduce_quantifier(quantifier * old_q,
expr * new_body,
expr * const * new_patterns,
expr * const * new_no_patterns,
expr_ref & result,
proof_ref & result_pr) {
throw tactic_exception("quantifiers are not supported in mixed-mode nlsat engine");
}
br_status reduce_app(func_decl * f, unsigned num, expr* const* args, expr_ref& result, proof_ref & pr) {
if (m_mode == mode_bool_preds) {
return reduce_app_bool(f, num, args, result, pr);
}
else {
return reduce_app_real(f, num, args, result, pr);
}
}
br_status reduce_app_bool(func_decl * f, unsigned num, expr* const* args, expr_ref& result, proof_ref & pr) {
if (f->get_family_id() == m.get_basic_family_id()) {
if (f->get_decl_kind() == OP_EQ && u().is_real(args[0])) {
mk_interface_bool(f, num, args, result, pr);
return BR_DONE;
}
else {
return BR_FAILED;
}
}
if (f->get_family_id() == u().get_family_id()) {
switch (f->get_decl_kind()) {
case OP_LE: case OP_GE: case OP_LT: case OP_GT:
// these are the only real cases of non-linear atomic formulas besides equality.
mk_interface_bool(f, num, args, result, pr);
return BR_DONE;
default:
return BR_FAILED;
}
}
return BR_FAILED;
}
// (+ (f x) y)
// (f (+ x y))
//
bool is_arith_op(expr* e) {
return is_app(e) && to_app(e)->get_family_id() == u().get_family_id();
}
br_status reduce_app_real(func_decl * f, unsigned num, expr* const* args, expr_ref& result, proof_ref & pr) {
bool has_interface = false;
bool is_arith = false;
if (f->get_family_id() == u().get_family_id()) {
switch (f->get_decl_kind()) {
case OP_NUM:
case OP_IRRATIONAL_ALGEBRAIC_NUM:
return BR_FAILED;
default:
is_arith = true;
break;
}
}
m_args.reset();
m_proofs.reset();
for (unsigned i = 0; i < num; ++i) {
expr* arg = args[i];
proof_ref arg_pr(m);
if (is_arith && !is_arith_op(arg)) {
has_interface = true;
m_args.push_back(mk_interface_var(arg, arg_pr));
}
else if (!is_arith && u().is_real(arg)) {
has_interface = true;
m_args.push_back(mk_interface_var(arg, arg_pr));
}
else {
m_args.push_back(arg);
}
if (arg_pr) {
m_proofs.push_back(arg_pr);
}
}
if (has_interface) {
result = m.mk_app(f, num, m_args.c_ptr());
if (m_owner.m_produce_proofs) {
pr = m.mk_oeq_congruence(m.mk_app(f, num, args), to_app(result), m_proofs.size(), m_proofs.c_ptr());
}
TRACE("nlsat_smt", tout << result << "\n";);
return BR_DONE;
}
else {
return BR_FAILED;
}
}
};
private:
class rw : public rewriter_tpl<rw_cfg> {
rw_cfg m_cfg;
public:
rw(nl_purify_tactic & o):
rewriter_tpl<rw_cfg>(o.m, o.m_produce_proofs, m_cfg),
m_cfg(o) {
}
void set_bool_mode() {
m_cfg.m_mode = rw_cfg::mode_bool_preds;
}
void set_interface_var_mode() {
m_cfg.m_mode = rw_cfg::mode_interface_var;
}
};
arith_util & u() { return m_util; }
void check_point() {
if (m.canceled()) {
throw tactic_exception(Z3_CANCELED_MSG);
}
}
void display_result(std::ostream& out, goal_ref_buffer const& result) {
for (unsigned i = 0; i < result.size(); ++i) {
result[i]->display_with_dependencies(out << "goal\n");
}
}
void update_eq_values(model_ref& mdl) {
expr_ref tmp(m);
for (unsigned i = 0; i < m_eq_preds.size(); ++i) {
expr* pred = m_eq_preds[i].get();
m_eq_values[i] = l_undef;
if (mdl->eval(pred, tmp)) {
if (m.is_true(tmp)) {
m_eq_values[i] = l_true;
}
else if (m.is_false(tmp)) {
m_eq_values[i] = l_false;
}
}
}
}
void solve(
goal_ref const& g,
goal_ref_buffer& result,
expr_dependency_ref& core,
model_converter_ref& mc) {
while (true) {
check_point();
TRACE("nlsat_smt", m_solver->display(tout << "SMT:\n"); m_nl_g->display(tout << "\nNL:\n"); );
goal_ref tmp_nl = alloc(goal, m, true, false);
model_converter_ref nl_mc;
proof_converter_ref nl_pc;
expr_dependency_ref nl_core(m);
result.reset();
tmp_nl->copy_from(*m_nl_g.get());
(*m_nl_tac)(tmp_nl, result, nl_mc, nl_pc, nl_core);
if (is_decided_unsat(result)) {
core2result(core, g, result);
TRACE("nlsat_smt", tout << "unsat\n";);
break;
}
if (!is_decided_sat(result)) {
TRACE("nlsat_smt", tout << "not a unit\n";);
break;
}
// extract evaluation on interface variables.
// assert booleans that evaluate to true.
// assert equalities between equal interface real variables.
model_ref mdl_nl, mdl_smt;
if (nl_mc.get()) {
model_converter2model(m, nl_mc.get(), mdl_nl);
update_eq_values(mdl_nl);
enforce_equalities(mdl_nl, m_nl_g);
setup_assumptions(mdl_nl);
TRACE("nlsat_smt",
model_smt2_pp(tout << "nl model\n", m, *mdl_nl.get(), 0);
m_solver->display(tout << "smt goal:\n"); tout << "\n";);
}
result.reset();
lbool r = m_solver->check_sat(m_asms.size(), m_asms.c_ptr());
if (r == l_false) {
// extract the core from the result
ptr_vector<expr> ecore, asms;
expr_ref_vector clause(m);
expr_ref fml(m);
get_unsat_core(ecore, asms);
//
// assumptions should also be used for the nlsat tactic,
// but since it does not support assumptions at this time
// we overapproximate the necessary core and accumulate
// all assumptions that are ever used.
//
for (unsigned i = 0; i < asms.size(); ++i) {
m_used_asms.insert(asms[i]);
}
if (ecore.empty()) {
core2result(core, g, result);
break;
}
for (unsigned i = 0; i < ecore.size(); ++i) {
clause.push_back(mk_not(m, ecore[i]));
}
fml = mk_or(m, clause.size(), clause.c_ptr());
m_nl_g->assert_expr(fml);
continue;
}
else if (r == l_true) {
m_solver->get_model(mdl_smt);
if (enforce_equalities(mdl_smt, m_nl_g)) {
// SMT enforced a new equality that wasn't true for nlsat.
continue;
}
TRACE("nlsat_smt",
m_fmc->display(tout << "joint state is sat\n");
nl_mc->display(tout << "nl\n"););
if (mdl_nl.get()) {
merge_models(*mdl_nl.get(), mdl_smt);
}
mc = m_fmc.get();
apply(mc, mdl_smt, 0);
mc = model2model_converter(mdl_smt.get());
result.push_back(alloc(goal, m));
}
else {
TRACE("nlsat_smt", tout << "unknown\n";);
}
break;
}
TRACE("nlsat_smt", display_result(tout, result););
}
void get_unsat_core(ptr_vector<expr>& core, ptr_vector<expr>& asms) {
m_solver->get_unsat_core(core);
for (unsigned i = 0; i < core.size(); ++i) {
if (m_ctx_asms_set.contains(core[i])) {
asms.push_back(core[i]);
core[i] = core.back();
core.pop_back();
--i;
}
}
}
void core2result(expr_dependency_ref & lcore, goal_ref const& g, goal_ref_buffer& result) {
result.reset();
proof * pr = 0;
lcore = 0;
g->reset();
obj_hashtable<expr>::iterator it = m_used_asms.begin(), end = m_used_asms.end();
for (; it != end; ++it) {
lcore = m.mk_join(lcore, m.mk_leaf(m_bool2dep.find(*it)));
}
g->assert_expr(m.mk_false(), pr, lcore);
TRACE("nlsat_smt", g->display_with_dependencies(tout););
result.push_back(g.get());
}
void setup_assumptions(model_ref& mdl) {
m_asms.reset();
m_asms.append(m_ctx_asms.size(), m_ctx_asms.c_ptr());
app_ref_vector const& fresh_preds = m_new_preds;
expr_ref tmp(m);
for (unsigned i = 0; i < fresh_preds.size(); ++i) {
expr* pred = fresh_preds[i];
if (mdl->eval(pred, tmp)) {
polarity_t pol = m_polarities.find(pred);
// if assumptinon literals are used to satisfy NL state,
// we have to assume them when satisfying SMT state
if (pol != pol_neg && m.is_false(tmp)) {
m_asms.push_back(m.mk_not(pred));
}
else if (pol != pol_pos && m.is_true(tmp)) {
m_asms.push_back(pred);
}
}
}
for (unsigned i = 0; i < m_eq_preds.size(); ++i) {
expr* pred = m_eq_preds[i].get();
switch (m_eq_values[i]) {
case l_true:
m_asms.push_back(pred);
break;
case l_false:
m_asms.push_back(m.mk_not(pred));
break;
default:
break;
}
}
TRACE("nlsat_smt",
tout << "assumptions:\n" << m_asms << "\n";);
}
bool enforce_equalities(model_ref& mdl, goal_ref const& nl_g) {
TRACE("nlsat_smt", tout << "Enforce equalities " << m_interface_cache.size() << "\n";);
bool new_equality = false;
expr_ref_vector nums(m);
obj_map<expr, expr*> num2var;
obj_map<expr, expr*>::iterator it = m_interface_cache.begin(), end = m_interface_cache.end();
for (; it != end; ++it) {
expr_ref r(m);
expr* v, *w, *pred;
w = it->m_value;
VERIFY(mdl->eval(w, r));
TRACE("nlsat_smt", tout << mk_pp(w, m) << " |-> " << r << "\n";);
nums.push_back(r);
if (num2var.find(r, v)) {
if (!m_eq_pairs.find(v, w, pred)) {
pred = m.mk_fresh_const(0, m.mk_bool_sort());
m_eq_preds.push_back(pred);
m_eq_values.push_back(l_true);
m_fmc->hide(pred);
nl_g->assert_expr(m.mk_or(m.mk_not(pred), m.mk_eq(w, v)));
nl_g->assert_expr(m.mk_or(pred, m.mk_not(m.mk_eq(w, v))));
m_solver->assert_expr(m.mk_iff(pred, m.mk_eq(w, v)));
new_equality = true;
m_eq_pairs.insert(v, w, pred);
}
else {
// interface equality is already enforced.
}
}
else {
num2var.insert(r, w);
}
}
return new_equality;
}
void merge_models(model const& mdl_nl, model_ref& mdl_smt) {
expr_safe_replace num2num(m);
expr_ref result(m), val2(m);
expr_ref_vector args(m);
unsigned sz = mdl_nl.get_num_constants();
for (unsigned i = 0; i < sz; ++i) {
func_decl* v = mdl_nl.get_constant(i);
if (u().is_real(v->get_range())) {
expr* val = mdl_nl.get_const_interp(v);
if (mdl_smt->eval(v, val2)) {
if (val != val2) {
num2num.insert(val2, val);
}
}
}
}
sz = mdl_smt->get_num_functions();
for (unsigned i = 0; i < sz; ++i) {
func_decl* f = mdl_smt->get_function(i);
if (has_real(f)) {
unsigned arity = f->get_arity();
func_interp* f1 = mdl_smt->get_func_interp(f);
func_interp* f2 = alloc(func_interp, m, f->get_arity());
for (unsigned j = 0; j < f1->num_entries(); ++j) {
args.reset();
func_entry const* entry = f1->get_entry(j);
for (unsigned k = 0; k < arity; ++k) {
translate(num2num, entry->get_arg(k), result);
args.push_back(result);
}
translate(num2num, entry->get_result(), result);
f2->insert_entry(args.c_ptr(), result);
}
translate(num2num, f1->get_else(), result);
f2->set_else(result);
mdl_smt->register_decl(f, f2);
}
}
mdl_smt->copy_const_interps(mdl_nl);
}
bool has_real(func_decl* f) {
for (unsigned i = 0; i < f->get_arity(); ++i) {
if (u().is_real(f->get_domain(i))) return true;
}
return u().is_real(f->get_range());
}
void translate(expr_safe_replace& num2num, expr* e, expr_ref& result) {
result = 0;
if (e) {
num2num(e, result);
}
}
void get_polarities(goal const& g) {
ptr_vector<expr> forms;
svector<polarity_t> pols;
unsigned sz = g.size();
for (unsigned i = 0; i < sz; ++i) {
forms.push_back(g.form(i));
pols.push_back(pol_pos);
}
polarity_t p, q;
while (!forms.empty()) {
expr* e = forms.back();
p = pols.back();
forms.pop_back();
pols.pop_back();
if (m_polarities.find(e, q)) {
if (p == q || q == pol_dual) continue;
p = pol_dual;
}
TRACE("nlsat_smt_verbose", tout << mk_pp(e, m) << "\n";);
m_polarities.insert(e, p);
if (is_quantifier(e) || is_var(e)) {
throw tactic_exception("nl-purify tactic does not support quantifiers");
}
SASSERT(is_app(e));
app* a = to_app(e);
func_decl* f = a->get_decl();
if (f->get_family_id() == m.get_basic_family_id() && p != pol_dual) {
switch(f->get_decl_kind()) {
case OP_NOT:
p = neg(p);
break;
case OP_AND:
case OP_OR:
break;
default:
p = pol_dual;
break;
}
}
else {
p = pol_dual;
}
for (unsigned i = 0; i < a->get_num_args(); ++i) {
forms.push_back(a->get_arg(i));
pols.push_back(p);
}
}
}
polarity_t neg(polarity_t p) {
switch (p) {
case pol_pos: return pol_neg;
case pol_neg: return pol_pos;
case pol_dual: return pol_dual;
}
return pol_dual;
}
polarity_t join(polarity_t p, polarity_t q) {
if (p == q) return p;
return pol_dual;
}
void rewrite_goal(rw& r, goal_ref const& g) {
r.reset();
expr_ref new_curr(m);
proof_ref new_pr(m);
unsigned sz = g->size();
for (unsigned i = 0; i < sz; i++) {
expr * curr = g->form(i);
r(curr, new_curr, new_pr);
if (m_produce_proofs) {
proof * pr = g->pr(i);
new_pr = m.mk_modus_ponens(pr, new_pr);
}
g->update(i, new_curr, new_pr, g->dep(i));
}
}
void remove_pure_arith(goal_ref const& g) {
obj_map<expr, bool> is_pure;
unsigned sz = g->size();
for (unsigned i = 0; i < sz; i++) {
expr * curr = g->form(i);
if (is_pure_arithmetic(is_pure, curr)) {
m_nl_g->assert_expr(curr, g->pr(i), g->dep(i));
g->update(i, m.mk_true(), g->pr(i), g->dep(i));
}
}
}
bool is_pure_arithmetic(obj_map<expr, bool>& is_pure, expr* e0) {
ptr_vector<expr> todo;
todo.push_back(e0);
while (!todo.empty()) {
expr* e = todo.back();
if (is_pure.contains(e)) {
todo.pop_back();
continue;
}
if (!is_app(e)) {
todo.pop_back();
is_pure.insert(e, false);
continue;
}
app* a = to_app(e);
bool pure = false, all_found = true, p;
pure |= (a->get_family_id() == u().get_family_id()) && u().is_real(a);
pure |= (m.is_eq(e) && u().is_real(a->get_arg(0)));
pure |= (a->get_family_id() == u().get_family_id()) && m.is_bool(a) && u().is_real(a->get_arg(0));
pure |= (a->get_family_id() == m.get_basic_family_id());
pure |= is_uninterp_const(a) && u().is_real(a);
for (unsigned i = 0; i < a->get_num_args(); ++i) {
if (!is_pure.find(a->get_arg(i), p)) {
todo.push_back(a->get_arg(i));
all_found = false;
}
else {
pure &= p;
}
}
if (all_found) {
is_pure.insert(e, pure);
todo.pop_back();
}
}
return is_pure.find(e0);
}
public:
nl_purify_tactic(ast_manager & m, params_ref const& p):
m(m),
m_util(m),
m_params(p),
m_fmc(0),
m_nl_tac(mk_nlsat_tactic(m, p)),
m_nl_g(0),
m_solver(mk_smt_solver(m, p, symbol::null)),
m_eq_preds(m),
m_new_reals(m),
m_new_preds(m),
m_asms(m)
{}
virtual ~nl_purify_tactic() {}
virtual void updt_params(params_ref const & p) {
m_params = p;
}
virtual tactic * translate(ast_manager& m) {
return alloc(nl_purify_tactic, m, m_params);
}
virtual void collect_statistics(statistics & st) const {
m_nl_tac->collect_statistics(st);
m_solver->collect_statistics(st);
}
virtual void reset_statistics() {
m_nl_tac->reset_statistics();
}
virtual void cleanup() {
m_solver = mk_smt_solver(m, m_params, symbol::null);
m_nl_tac->cleanup();
m_eq_preds.reset();
m_eq_values.reset();
m_new_reals.reset();
m_new_preds.reset();
m_eq_pairs.reset();
m_polarities.reset();
m_ctx_asms.reset();
m_ctx_asms_set.reset();
m_used_asms.reset();
m_bool2dep.reset();
}
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
tactic_report report("qfufnl-purify", *g);
TRACE("nlsat_smt", g->display(tout););
m_produce_proofs = g->proofs_enabled();
mc = 0; pc = 0; core = 0;
fail_if_proof_generation("qfufnra-purify", g);
// fail_if_unsat_core_generation("qfufnra-purify", g);
rw r(*this);
expr_ref_vector clauses(m);
m_nl_g = alloc(goal, m, true, false);
m_fmc = alloc(generic_model_converter, m);
// first hoist interface variables,
// then annotate subformulas by polarities,
// finally extract polynomial inequalities by
// creating a place-holder predicate inside the
// original goal and extracing pure nlsat clauses.
r.set_interface_var_mode();
rewrite_goal(r, g);
if (!g->unsat_core_enabled()) {
remove_pure_arith(g);
}
get_polarities(*g.get());
r.set_bool_mode();
rewrite_goal(r, g);
extract_clauses_and_dependencies(g, clauses, m_ctx_asms, m_bool2dep, m_fmc);
TRACE("nlsat_smt", tout << clauses << "\n";);
for (unsigned i = 0; i < m_ctx_asms.size(); ++i) {
m_ctx_asms_set.insert(m_ctx_asms[i]);
}
for (unsigned i = 0; i < clauses.size(); ++i) {
m_solver->assert_expr(clauses[i].get());
}
g->inc_depth();
solve(g, result, core, mc);
}
};
tactic * mk_nl_purify_tactic(ast_manager& m, params_ref const& p) {
return alloc(nl_purify_tactic, m, p);
}

View file

@ -1,35 +0,0 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
nl_purify_tactic.h
Abstract:
Tactic for purifying quantifier-free formulas that mix QF_NRA and other theories.
It is designed to allow cooprating between the nlsat solver and other theories
in a decoubled way.
Author:
Nikolaj Bjorner (nbjorner) 2015-5-5.
Revision History:
--*/
#ifndef NL_PURIFY_TACTIC_H_
#define NL_PURIFY_TACTIC_H_
#include "util/params.h"
class ast_manager;
class tactic;
tactic * mk_nl_purify_tactic(ast_manager & m, params_ref const & p = params_ref());
/*
ADD_TACTIC("nl-purify", "Decompose goal into pure NL-sat formula and formula over other theories.", "mk_nl_purify_tactic(m, p)")
*/
#endif

View file

@ -210,7 +210,7 @@ private:
}
generic_model_converter filter(m);
for (func_decl* f : m_bv_fns) filter.hide(f);
filter(mdl, 0);
filter(mdl);
}
void extend_model(model_ref& mdl) {
@ -225,7 +225,7 @@ private:
TRACE("int2bv", tout << mk_pp(kv.m_key, m) << " " << value << "\n";);
ext.add(kv.m_key, value);
}
ext(mdl, 0);
ext(mdl);
}
void accumulate_sub(expr_safe_replace& sub) const {

View file

@ -167,14 +167,14 @@ public:
for (auto const& kv : m_rewriter.enum2bv()) {
filter.hide(kv.m_value);
}
filter(mdl, 0);
filter(mdl);
}
void extend_model(model_ref& mdl) {
generic_model_converter ext(m);
for (auto const& kv : m_rewriter.enum2def())
ext.add(kv.m_key, kv.m_value);
ext(mdl, 0);
ext(mdl);
}
virtual unsigned get_num_assertions() const {

View file

@ -541,7 +541,7 @@ public:
init();
}
void operator ()(const goal_ref & g,goal_ref_buffer & result,model_converter_ref & mc,proof_converter_ref & pc,expr_dependency_ref & dep) {
void operator ()(const goal_ref & g,goal_ref_buffer & result) {
ast_manager& m = g->m();
solver* s = mk_fd_solver(m, m_params);
solver_state* st = alloc(solver_state, 0, s, m_params, cube_task);
@ -560,8 +560,7 @@ public:
switch (is_sat) {
case l_true:
if (g->models_enabled()) {
mc = model2model_converter(mdl.get());
mc = concat(fmc.get(), mc.get());
g->add(concat(fmc.get(), model2model_converter(mdl.get())));
}
g->reset();
break;

View file

@ -118,7 +118,7 @@ public:
for (func_decl* f : fns) {
filter.hide(f);
}
filter(mdl, 0);
filter(mdl);
}
virtual unsigned get_num_assertions() const {

View file

@ -17,6 +17,7 @@ Notes:
--*/
#include "tactic/proof_converter.h"
#include "tactic/goal.h"
#include "ast/ast_smt2_pp.h"
class concat_proof_converter : public concat_converter<proof_converter> {
@ -25,14 +26,14 @@ public:
virtual char const * get_name() const { return "concat-proof-converter"; }
virtual void operator()(ast_manager & m, unsigned num_source, proof * const * source, proof_ref & result) {
proof_ref operator()(ast_manager & m, unsigned num_source, proof * const * source) override {
proof_ref tmp(m);
this->m_c2->operator()(m, num_source, source, tmp);
tmp = this->m_c2->operator()(m, num_source, source);
proof * new_source = tmp.get();
this->m_c1->operator()(m, 1, &new_source, result);
return this->m_c1->operator()(m, 1, &new_source);
}
virtual proof_converter * translate(ast_translation & translator) {
proof_converter * translate(ast_translation & translator) override {
return this->translate_core<concat_proof_converter>(translator);
}
};
@ -45,66 +46,39 @@ proof_converter * concat(proof_converter * pc1, proof_converter * pc2) {
return alloc(concat_proof_converter, pc1, pc2);
}
class concat_star_proof_converter : public concat_star_converter<proof_converter> {
class subgoal_proof_converter : public proof_converter {
proof_converter_ref m_pc;
goal_ref_buffer m_goals;
public:
concat_star_proof_converter(proof_converter * pc1, unsigned num, proof_converter * const * pc2s, unsigned * szs):
concat_star_converter<proof_converter>(pc1, num, pc2s, szs) {
subgoal_proof_converter(proof_converter* pc, unsigned n, goal * const* goals):
m_pc(pc)
{
for (unsigned i = 0; i < n; ++i) m_goals.push_back(goals[i]);
}
virtual char const * get_name() const { return "concat-star-proof-converter"; }
virtual void operator()(ast_manager & m, unsigned num_source, proof * const * source, proof_ref & result) {
unsigned num = this->m_szs.size();
#ifdef Z3DEBUG
unsigned sum = 0;
for (unsigned i = 0; i < num; i++) {
sum += this->m_szs[i];
}
SASSERT(sum == num_source);
#endif
proof_ref_buffer tmp_prs(m);
for (unsigned i = 0; i < num; i++) {
unsigned sz = m_szs[i];
proof_converter * c2 = m_c2s[i];
proof_ref pr(m);
if (c2) {
(*c2)(m, sz, source, pr);
}
else {
SASSERT(sz == 1);
pr = *source;
}
source += sz;
tmp_prs.push_back(pr.get());
}
if (m_c1) {
(*m_c1)(m, tmp_prs.size(), tmp_prs.c_ptr(), result);
}
else {
SASSERT(tmp_prs.size() == 1);
result = tmp_prs[0];
proof_ref operator()(ast_manager & m, unsigned num_source, proof * const * source) override {
// ignore the proofs from the arguments, instead obtain the proofs fromt he subgoals.
SASSERT(num_source == 0);
proof_converter_ref_buffer pc_buffer;
for (goal_ref g : m_goals) {
pc_buffer.push_back(g->pc());
}
return apply(m, m_pc, pc_buffer);
}
virtual proof_converter * translate(ast_translation & translator) {
return this->translate_core<concat_star_proof_converter>(translator);
proof_converter* translate(ast_translation& tr) override {
proof_converter_ref pc1 = m_pc->translate(tr);
goal_ref_buffer goals;
for (goal_ref g : m_goals) goals.push_back(g->translate(tr));
return alloc(subgoal_proof_converter, pc1.get(), goals.size(), goals.c_ptr());
}
void display(std::ostream& out) override {}
};
proof_converter * concat(proof_converter * pc1, unsigned num, proof_converter * const * pc2s, unsigned * szs) {
SASSERT(num > 0);
if (num == 1)
return concat(pc1, pc2s[0]);
unsigned i;
for (i = 0; i < num; i++) {
if (pc2s[i] != 0)
break;
}
if (i == num) {
// all pc2s are 0
return pc1;
}
return alloc(concat_star_proof_converter, pc1, num, pc2s, szs);
proof_converter * concat(proof_converter *pc, unsigned n, goal* const* goals) {
return alloc(subgoal_proof_converter, pc, n, goals);
}
class proof2pc : public proof_converter {
@ -113,16 +87,16 @@ public:
proof2pc(ast_manager & m, proof * pr):m_pr(pr, m) {}
virtual ~proof2pc() {}
virtual void operator()(ast_manager & m, unsigned num_source, proof * const * source, proof_ref & result) {
proof_ref operator()(ast_manager & m, unsigned num_source, proof * const * source) override {
SASSERT(num_source == 0);
result = m_pr;
return m_pr;
}
virtual proof_converter * translate(ast_translation & translator) {
proof_converter * translate(ast_translation & translator) override {
return alloc(proof2pc, translator.to(), translator(m_pr.get()));
}
virtual void display(std::ostream & out) {
void display(std::ostream & out) override {
out << "(proof->proof-converter-wrapper\n" << mk_ismt2_pp(m_pr.get(), m_pr.get_manager()) << ")\n";
}
};
@ -136,7 +110,7 @@ proof_converter * proof2proof_converter(ast_manager & m, proof * pr) {
void apply(ast_manager & m, proof_converter * pc, proof_ref & pr) {
if (pc) {
proof * _pr = pr.get();
(*pc)(m, 1, &_pr, pr);
pr = (*pc)(m, 1, &_pr);
}
}
@ -148,15 +122,15 @@ void apply(ast_manager & m, proof_converter * pc, proof_ref & pr) {
pc1 and pc2s must be different from 0.
*/
void apply(ast_manager & m, proof_converter_ref & pc1, proof_converter_ref_buffer & pc2s, proof_ref & result) {
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
pc2s[i]->operator()(m, 0, 0, pr);
pr = pc2s[i]->operator()(m, 0, 0);
prs.push_back(pr);
}
(*pc1)(m, sz, prs.c_ptr(), result);
return (*pc1)(m, sz, prs.c_ptr());
}

View file

@ -20,33 +20,34 @@ Notes:
#define PROOF_CONVERTER_H_
#include "ast/ast.h"
#include "tactic/converter.h"
#include "util/ref.h"
#include "tactic/converter.h"
class goal;
class proof_converter : public converter {
public:
virtual ~proof_converter() { }
virtual void operator()(ast_manager & m, unsigned num_source, proof * const * source, proof_ref & result) = 0;
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);
/**
\brief \c pc1 is the proof converter for a sequence of subgoals of size \c num.
Given an i in [0, num), pc2s[i] is the proof converter for subgoal i,
and num_subgoals[i] is the number of subgoals of subgoals[i].
*/
proof_converter * concat(proof_converter * pc1, unsigned num, proof_converter * const * pc2s, unsigned * num_subgoals);
\brief create a proof converter that takes a set of subgoals and converts their proofs to a proof of
the goal they were derived from.
*/
proof_converter * concat(proof_converter *pc1, unsigned n, goal* const* goals);
proof_converter * proof2proof_converter(ast_manager & m, proof * pr);
typedef sref_vector<proof_converter> proof_converter_ref_vector;
typedef sref_buffer<proof_converter> proof_converter_ref_buffer;
void apply(ast_manager & m, proof_converter_ref & pc1, proof_converter_ref_buffer & pc2s, proof_ref & result);
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);
#endif

View file

@ -53,8 +53,7 @@ public:
};
void replace_proof_converter::operator()(ast_manager & m, unsigned num_source,
proof * const * source, proof_ref & result) {
proof_ref replace_proof_converter::operator()(ast_manager & m, unsigned num_source, proof * const * source) {
SASSERT(num_source == 1);
replace_map replace(m);
proof_ref p(m);
@ -73,14 +72,12 @@ void replace_proof_converter::operator()(ast_manager & m, unsigned num_source,
replace.apply(tmp);
TRACE("proof_converter", tout << mk_pp(source[0], m) << "\n";
tout << mk_pp(tmp.get(), m) << "\n";);
result = to_app(tmp);
return proof_ref(to_app(tmp), m);
}
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()));
}
for (proof* p : m_proofs) rp->insert(translator(p));
return rp;
}

View file

@ -34,9 +34,9 @@ public:
virtual ~replace_proof_converter() {}
virtual void operator()(ast_manager & _m, unsigned num_source, proof * const * source, proof_ref & result);
proof_ref operator()(ast_manager & _m, unsigned num_source, proof * const * source) override;
virtual proof_converter * translate(ast_translation & translator);
proof_converter * translate(ast_translation & translator) override;
void insert(proof* p) { m_proofs.push_back(p); }
@ -45,7 +45,7 @@ public:
// run the replacements the inverse direction.
void invert() { m_proofs.reverse(); }
virtual void display(std::ostream & out) {}
void display(std::ostream & out) override {}
};

View file

@ -46,13 +46,7 @@ public:
virtual void collect_param_descrs(param_descrs & r) {
}
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
mc = 0; pc = 0; core = 0;
void operator()(goal_ref const & g, goal_ref_buffer& result) override {
TRACE("sine", g->display(tout););
TRACE("sine", tout << g->size(););
ptr_vector<expr> new_forms;
@ -67,8 +61,6 @@ public:
result.push_back(g.get());
TRACE("sine", result[0]->display(tout););
SASSERT(g->is_well_sorted());
generic_model_converter * fmc = alloc(generic_model_converter, m);
mc = fmc;
}
virtual void cleanup() {

View file

@ -60,18 +60,16 @@ public:
}
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
mc = 0; pc = 0; core = 0; result.reset();
result.reset();
TRACE("sls", g->display(tout););
tactic_report report("sls", *g);
model_converter_ref mc;
m_engine->operator()(g, mc);
g->add(mc.get());
g->inc_depth();
result.push_back(g.get());
TRACE("sls", g->display(tout););

View file

@ -11,7 +11,6 @@ z3_add_component(smtlogic_tactics
qfnra_tactic.cpp
qfufbv_ackr_model_converter.cpp
qfufbv_tactic.cpp
qfufnra_tactic.cpp
qfuf_tactic.cpp
quant_tactics.cpp
COMPONENT_DEPENDENCIES
@ -22,7 +21,6 @@ z3_add_component(smtlogic_tactics
fp
muz
nlsat_tactic
nlsat_smt_tactic
qe
sat_solver
smt_tactic
@ -40,6 +38,5 @@ z3_add_component(smtlogic_tactics
qfnra_tactic.h
qfuf_tactic.h
qfufbv_tactic.h
qfufnra_tactic.h
quant_tactics.h
)

View file

@ -54,11 +54,7 @@ public:
virtual ~qfufbv_ackr_tactic() { }
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
mc = 0;
goal_ref_buffer & result) {
ast_manager& m(g->m());
tactic_report report("qfufbv_ackr", *g);
fail_if_unsat_core_generation("qfufbv_ackr", g);
@ -80,7 +76,7 @@ public:
// report model
if (g->models_enabled() && (o == l_true)) {
model_ref abstr_model = imp->get_model();
mc = mk_qfufbv_ackr_model_converter(m, imp->get_info(), abstr_model);
g->add(mk_qfufbv_ackr_model_converter(m, imp->get_info(), abstr_model));
}
}

View file

@ -67,16 +67,8 @@ void report_tactic_progress(char const * id, unsigned val) {
}
}
void skip_tactic::operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
result.reset();
void skip_tactic::operator()(goal_ref const & in, goal_ref_buffer& result) {
result.push_back(in.get());
mc = 0;
pc = 0;
core = 0;
}
tactic * mk_skip_tactic() {
@ -85,17 +77,13 @@ tactic * mk_skip_tactic() {
class fail_tactic : public tactic {
public:
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void operator()(goal_ref const & in, goal_ref_buffer & result) override {
throw tactic_exception("fail tactic");
}
virtual void cleanup() {}
void cleanup() override {}
virtual tactic * translate(ast_manager & m) { return this; }
tactic * translate(ast_manager & m) override { return this; }
};
tactic * mk_fail_tactic() {
@ -108,13 +96,9 @@ class report_verbose_tactic : public skip_tactic {
public:
report_verbose_tactic(char const * msg, unsigned lvl) : m_msg(msg), m_lvl(lvl) {}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void operator()(goal_ref const & in, goal_ref_buffer& result) override {
IF_VERBOSE(m_lvl, verbose_stream() << m_msg << "\n";);
skip_tactic::operator()(in, result, mc, pc, core);
skip_tactic::operator()(in, result);
}
};
@ -127,14 +111,10 @@ class trace_tactic : public skip_tactic {
public:
trace_tactic(char const * tag): m_tag(tag) {}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void operator()(goal_ref const & in, goal_ref_buffer& result) override {
TRACE(m_tag, in->display(tout););
(void)m_tag;
skip_tactic::operator()(in, result, mc, pc, core);
skip_tactic::operator()(in, result);
}
};
@ -146,14 +126,10 @@ class fail_if_undecided_tactic : public skip_tactic {
public:
fail_if_undecided_tactic() {}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void operator()(goal_ref const & in, goal_ref_buffer& result) override {
if (!in->is_decided())
throw tactic_exception("undecided");
skip_tactic::operator()(in, result, mc, pc, core);
skip_tactic::operator()(in, result);
}
};
@ -161,10 +137,10 @@ tactic * mk_fail_if_undecided_tactic() {
return alloc(fail_if_undecided_tactic);
}
void exec(tactic & t, goal_ref const & in, goal_ref_buffer & result, model_converter_ref & mc, proof_converter_ref & pc, expr_dependency_ref & core) {
void exec(tactic & t, goal_ref const & in, goal_ref_buffer & result) {
t.reset_statistics();
try {
t(in, result, mc, pc, core);
t(in, result);
t.cleanup();
}
catch (tactic_exception & ex) {
@ -175,7 +151,7 @@ void exec(tactic & t, goal_ref const & in, goal_ref_buffer & result, model_conve
}
lbool check_sat(tactic & t, goal_ref & g, model_ref & md, model_converter_ref& mc, labels_vec & labels, proof_ref & pr, expr_dependency_ref & core, std::string & reason_unknown) {
lbool check_sat(tactic & t, goal_ref & g, model_ref & md, labels_vec & labels, proof_ref & pr, expr_dependency_ref & core, std::string & reason_unknown) {
bool models_enabled = g->models_enabled();
bool proofs_enabled = g->proofs_enabled();
bool cores_enabled = g->unsat_core_enabled();
@ -184,23 +160,21 @@ lbool check_sat(tactic & t, goal_ref & g, model_ref & md, model_converter_ref& m
core = 0;
ast_manager & m = g->m();
goal_ref_buffer r;
proof_converter_ref pc;
try {
exec(t, g, r, mc, pc, core);
exec(t, g, r);
}
catch (tactic_exception & ex) {
reason_unknown = ex.msg();
return l_undef;
}
TRACE("tactic_mc", mc->display(tout););
TRACE("tactic_check_sat",
tout << "r.size(): " << r.size() << "\n";
for (unsigned i = 0; i < r.size(); i++) r[i]->display(tout););
if (is_decided_sat(r)) {
if (models_enabled) {
if (mc)
(*mc)(labels, 0);
model_converter_ref mc = r[0]->mc();
if (mc.get()) {
(*mc)(labels);
model_converter2model(m, mc.get(), md);
if (!md) {
// create empty model.
@ -217,10 +191,11 @@ lbool check_sat(tactic & t, goal_ref & g, model_ref & md, model_converter_ref& m
return l_false;
}
else {
if (models_enabled) {
if (models_enabled && r.size() >= 1) {
model_converter_ref mc = r[0]->mc();
model_converter2model(m, mc.get(), md);
if (mc)
(*mc)(labels, 0);
(*mc)(labels);
}
reason_unknown = "incomplete";
return l_undef;

View file

@ -24,8 +24,6 @@ Notes:
#include "tactic/goal.h"
#include "util/params.h"
#include "util/statistics.h"
#include "tactic/model_converter.h"
#include "tactic/proof_converter.h"
#include "tactic/tactic_exception.h"
#include "util/lbool.h"
@ -50,19 +48,7 @@ public:
The list of resultant subgoals is stored in \c result.
The content of \c in may be destroyed during the operation.
The resultant model converter \c mc can be used to convert a model for one of the returned subgoals
into a model for \in. If mc == 0, then model construction is disabled or any model for a subgoal
of \c in is also a model for \c in.
If \c result is decided_sat (i.e., it contains a single empty subgoal), then
the model converter is just wrapping the model.
The resultant proof converter \c pc can be used to convert proofs for each subgoal in \c result
into a proof for \c in. If pc == 0, then one of the following conditions should hold:
1- proof construction is disabled,
2- result contains a single subgoal, and any proof of unsatisfiability for this subgoal is a proof for \c in.
3- result is an decided_unsat (i.e., it contains a single unsat subgoal). The actual proof can be extracted from this goal.
The output parameter \c core is used to accumulate the unsat core of closed subgoals.
It must be 0 if dependency tracking is disabled, or the result is decided unsat, or
no tagged assertions were used to close any subgoal.
@ -75,11 +61,7 @@ public:
Therefore, in most cases, pc == 0 and core == 0 for non-branching tactics.
*/
virtual void operator()(/* in */ goal_ref const & in,
/* out */ goal_ref_buffer & result,
/* out */ model_converter_ref & mc,
/* out */ proof_converter_ref & pc,
/* out */ expr_dependency_ref & core) = 0;
virtual void operator()(goal_ref const & in, goal_ref_buffer& result) = 0;
virtual void collect_statistics(statistics & st) const {}
virtual void reset_statistics() {}
@ -119,9 +101,9 @@ void report_tactic_progress(char const * id, unsigned val);
class skip_tactic : public tactic {
public:
virtual void operator()(goal_ref const & in, goal_ref_buffer & result, model_converter_ref & mc, proof_converter_ref & pc, expr_dependency_ref & core);
virtual void cleanup() {}
virtual tactic * translate(ast_manager & m) { return this; }
void operator()(goal_ref const & in, goal_ref_buffer& result) override;
void cleanup() override {}
tactic * translate(ast_manager & m) override { return this; }
};
tactic * mk_skip_tactic();
@ -152,8 +134,8 @@ public:
#define MK_SIMPLE_TACTIC_FACTORY(NAME, ST) MK_TACTIC_FACTORY(NAME, return ST;)
void exec(tactic & t, goal_ref const & in, goal_ref_buffer & result, model_converter_ref & mc, proof_converter_ref & pc, expr_dependency_ref & core);
lbool check_sat(tactic & t, goal_ref & g, model_ref & md, model_converter_ref& mc, labels_vec & labels, proof_ref & pr, expr_dependency_ref & core, std::string & reason_unknown);
void exec(tactic & t, goal_ref const & in, goal_ref_buffer & result);
lbool check_sat(tactic & t, goal_ref & g, model_ref & md, labels_vec & labels, proof_ref & pr, expr_dependency_ref & core, std::string & reason_unknown);
// Throws an exception if goal \c in requires proof generation.
void fail_if_proof_generation(char const * tactic_name, goal_ref const & in);

View file

@ -16,33 +16,28 @@ Author:
Notes:
--*/
#include "tactic/tactical.h"
#include "util/scoped_timer.h"
#include "util/cancel_eh.h"
#include "util/cooperate.h"
#include "util/scoped_ptr_vector.h"
#include "util/z3_omp.h"
#include "tactic/tactical.h"
class binary_tactical : public tactic {
protected:
tactic * m_t1;
tactic * m_t2;
tactic_ref m_t1;
tactic_ref m_t2;
public:
binary_tactical(tactic * t1, tactic * t2):
m_t1(t1),
m_t2(t2) {
SASSERT(m_t1);
SASSERT(m_t2);
m_t1->inc_ref();
m_t2->inc_ref();
}
virtual ~binary_tactical() {
m_t1->dec_ref();
m_t2->dec_ref();
}
virtual ~binary_tactical() {}
virtual void updt_params(params_ref const & p) {
m_t1->updt_params(p);
@ -106,108 +101,63 @@ public:
and_then_tactical(tactic * t1, tactic * t2):binary_tactical(t1, t2) {}
virtual ~and_then_tactical() {}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void operator()(goal_ref const & in, goal_ref_buffer& result) override {
bool models_enabled = in->models_enabled();
bool proofs_enabled = in->proofs_enabled();
bool cores_enabled = in->unsat_core_enabled();
ast_manager & m = in->m();
goal_ref_buffer r1;
model_converter_ref mc1;
proof_converter_ref pc1;
expr_dependency_ref core1(m);
result.reset();
mc = 0;
pc = 0;
core = 0;
m_t1->operator()(in, r1, mc1, pc1, core1);
SASSERT(!is_decided(r1) || (!pc1 && !core1)); // the pc and core of decided goals is 0
ast_manager & m = in->m();
goal_ref_buffer r1;
m_t1->operator()(in, r1);
unsigned r1_size = r1.size();
SASSERT(r1_size > 0);
SASSERT(r1_size > 0);
if (r1_size == 1) {
if (r1[0]->is_decided()) {
result.push_back(r1[0]);
if (models_enabled) mc = mc1;
return;
result.push_back(r1[0]);
return;
}
goal_ref r1_0 = r1[0];
m_t2->operator()(r1_0, result, mc, pc, core);
if (models_enabled) mc = concat(mc1.get(), mc.get());
if (proofs_enabled) pc = concat(pc1.get(), pc.get());
if (cores_enabled) core = m.mk_join(core1.get(), core);
m_t2->operator()(r1_0, result);
}
else {
if (cores_enabled) core = core1;
proof_converter_ref_buffer pc_buffer;
model_converter_ref_buffer mc_buffer;
sbuffer<unsigned> sz_buffer;
goal_ref_buffer r2;
goal_ref_buffer r2;
for (unsigned i = 0; i < r1_size; i++) {
goal_ref g = r1[i];
r2.reset();
model_converter_ref mc2;
proof_converter_ref pc2;
expr_dependency_ref core2(m);
m_t2->operator()(g, r2, mc2, pc2, core2);
goal_ref g = r1[i];
r2.reset();
m_t2->operator()(g, r2);
if (is_decided(r2)) {
SASSERT(r2.size() == 1);
if (is_decided_sat(r2)) {
// found solution...
// found solution...
result.reset();
result.push_back(r2[0]);
if (models_enabled) {
// mc2 contains the actual model
model_ref md;
md = alloc(model, m);
apply(mc2, md, 0);
apply(mc1, md, i);
mc = model2model_converter(md.get());
}
SASSERT(!pc); SASSERT(!core);
return;
return;
}
else {
SASSERT(is_decided_unsat(r2));
// the proof and unsat core of a decided_unsat goal are stored in the node itself.
// pc2 and core2 must be 0.
SASSERT(!pc2);
SASSERT(!core2);
if (models_enabled) mc_buffer.push_back(0);
if (proofs_enabled) pc_buffer.push_back(proof2proof_converter(m, r2[0]->pr(0)));
if (models_enabled || proofs_enabled) sz_buffer.push_back(0);
if (cores_enabled) core = m.mk_join(core.get(), r2[0]->dep(0));
}
}
else {
result.append(r2.size(), r2.c_ptr());
if (models_enabled) mc_buffer.push_back(mc2.get());
if (proofs_enabled) pc_buffer.push_back(pc2.get());
if (models_enabled || proofs_enabled) sz_buffer.push_back(r2.size());
if (cores_enabled) core = m.mk_join(core.get(), core2.get());
}
}
if (result.empty()) {
// all subgoals were shown to be unsat.
// create an decided_unsat goal with the proof
in->reset_all();
proof_ref pr(m);
if (proofs_enabled)
apply(m, pc1, pc_buffer, pr);
SASSERT(cores_enabled || core == 0);
expr_dependency_ref core(m);
if (proofs_enabled) {
apply(m, in->pc(), pr);
}
dependency_converter* dc = in->dc();
if (cores_enabled && dc) {
core = (*dc)();
}
in->assert_expr(m.mk_false(), pr, core);
core = 0;
result.push_back(in.get());
SASSERT(!mc); SASSERT(!pc); SASSERT(!core);
}
else {
if (models_enabled) mc = concat(mc1.get(), mc_buffer.size(), mc_buffer.c_ptr(), sz_buffer.c_ptr());
if (proofs_enabled) pc = concat(pc1.get(), pc_buffer.size(), pc_buffer.c_ptr(), sz_buffer.c_ptr());
SASSERT(cores_enabled || core == 0);
}
}
}
@ -271,92 +221,58 @@ tactic * and_then(unsigned num, tactic * const * ts) {
class nary_tactical : public tactic {
protected:
ptr_vector<tactic> m_ts;
sref_vector<tactic> m_ts;
public:
nary_tactical(unsigned num, tactic * const * ts) {
for (unsigned i = 0; i < num; i++) {
SASSERT(ts[i]);
m_ts.push_back(ts[i]);
ts[i]->inc_ref();
}
}
virtual ~nary_tactical() {
unsigned sz = m_ts.size();
for (unsigned i = 0; i < sz; i++) {
m_ts[i]->dec_ref();
}
}
virtual ~nary_tactical() {}
virtual void updt_params(params_ref const & p) {
void updt_params(params_ref const & p) override {
TRACE("nary_tactical_updt_params", tout << "updt_params: " << p << "\n";);
ptr_vector<tactic>::iterator it = m_ts.begin();
ptr_vector<tactic>::iterator end = m_ts.end();
for (; it != end; ++it)
(*it)->updt_params(p);
for (tactic* t : m_ts) t->updt_params(p);
}
virtual void collect_param_descrs(param_descrs & r) {
ptr_vector<tactic>::iterator it = m_ts.begin();
ptr_vector<tactic>::iterator end = m_ts.end();
for (; it != end; ++it)
(*it)->collect_param_descrs(r);
void collect_param_descrs(param_descrs & r) override {
for (tactic* t : m_ts) t->collect_param_descrs(r);
}
virtual void collect_statistics(statistics & st) const {
ptr_vector<tactic>::const_iterator it = m_ts.begin();
ptr_vector<tactic>::const_iterator end = m_ts.end();
for (; it != end; ++it)
(*it)->collect_statistics(st);
void collect_statistics(statistics & st) const override {
for (tactic const* t : m_ts) t->collect_statistics(st);
}
virtual void reset_statistics() {
ptr_vector<tactic>::const_iterator it = m_ts.begin();
ptr_vector<tactic>::const_iterator end = m_ts.end();
for (; it != end; ++it)
(*it)->reset_statistics();
void reset_statistics() override {
for (tactic* t : m_ts) t->reset_statistics();
}
virtual void cleanup() {
ptr_vector<tactic>::iterator it = m_ts.begin();
ptr_vector<tactic>::iterator end = m_ts.end();
for (; it != end; ++it)
(*it)->cleanup();
void cleanup() override {
for (tactic* t : m_ts) t->cleanup();
}
virtual void reset() {
ptr_vector<tactic>::iterator it = m_ts.begin();
ptr_vector<tactic>::iterator end = m_ts.end();
for (; it != end; ++it)
(*it)->reset();
void reset() override {
for (tactic* t : m_ts) t->reset();
}
virtual void set_logic(symbol const & l) {
ptr_vector<tactic>::iterator it = m_ts.begin();
ptr_vector<tactic>::iterator end = m_ts.end();
for (; it != end; ++it)
(*it)->set_logic(l);
void set_logic(symbol const & l) override {
for (tactic* t : m_ts) t->set_logic(l);
}
virtual void set_progress_callback(progress_callback * callback) {
ptr_vector<tactic>::iterator it = m_ts.begin();
ptr_vector<tactic>::iterator end = m_ts.end();
for (; it != end; ++it)
(*it)->set_progress_callback(callback);
void set_progress_callback(progress_callback * callback) override {
for (tactic* t : m_ts) t->set_progress_callback(callback);
}
protected:
template<typename T>
tactic * translate_core(ast_manager & m) {
ptr_buffer<tactic> new_ts;
ptr_vector<tactic>::iterator it = m_ts.begin();
ptr_vector<tactic>::iterator end = m_ts.end();
for (; it != end; ++it) {
tactic * curr = *it;
tactic * new_curr = curr->translate(m);
new_ts.push_back(new_curr);
sref_vector<tactic> new_ts;
for (tactic* curr : m_ts) {
new_ts.push_back(curr->translate(m));
}
return alloc(T, new_ts.size(), new_ts.c_ptr());
}
@ -369,31 +285,24 @@ public:
virtual ~or_else_tactical() {}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
virtual void operator()(goal_ref const & in, goal_ref_buffer& result) {
goal orig(*(in.get()));
unsigned sz = m_ts.size();
unsigned i;
for (i = 0; i < sz; i++) {
tactic * t = m_ts[i];
result.reset();
mc = 0;
pc = 0;
core = 0;
SASSERT(sz > 0);
if (i < sz - 1) {
try {
t->operator()(in, result, mc, pc, core);
t->operator()(in, result);
return;
}
catch (tactic_exception &) {
result.reset();
}
}
else {
t->operator()(in, result, mc, pc, core);
t->operator()(in, result);
return;
}
in->reset_all();
@ -468,11 +377,7 @@ public:
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void operator()(goal_ref const & in, goal_ref_buffer& result) override {
bool use_seq;
#ifdef _NO_OMP_
use_seq = true;
@ -481,7 +386,7 @@ public:
#endif
if (use_seq) {
// execute tasks sequentially
or_else_tactical::operator()(in, result, mc, pc, core);
or_else_tactical::operator()(in, result);
return;
}
@ -509,15 +414,12 @@ public:
#pragma omp parallel for
for (int i = 0; i < static_cast<int>(sz); i++) {
goal_ref_buffer _result;
model_converter_ref _mc;
proof_converter_ref _pc;
expr_dependency_ref _core(*(managers[i]));
goal_ref in_copy = in_copies[i];
tactic & t = *(ts.get(i));
try {
t(in_copy, _result, _mc, _pc, _core);
t(in_copy, _result);
bool first = false;
#pragma omp critical (par_tactical)
{
@ -533,13 +435,11 @@ public:
}
}
ast_translation translator(*(managers[i]), m, false);
for (unsigned k = 0; k < _result.size(); k++) {
result.push_back(_result[k]->translate(translator));
for (goal* g : _result) {
result.push_back(g->translate(translator));
}
mc = _mc ? _mc->translate(translator) : 0;
pc = _pc ? _pc->translate(translator) : 0;
expr_dependency_translation td(translator);
core = td(_core);
goal_ref in2(in_copy->translate(translator));
in->copy_from(*(in2.get()));
}
}
catch (tactic_exception & ex) {
@ -562,7 +462,6 @@ public:
}
}
if (finished_id == UINT_MAX) {
mc = 0;
switch (ex_kind) {
case ERROR_EX: throw z3_error(error_code);
case TACTIC_EX: throw tactic_exception(ex_msg.c_str());
@ -599,11 +498,7 @@ public:
par_and_then_tactical(tactic * t1, tactic * t2):and_then_tactical(t1, t2) {}
virtual ~par_and_then_tactical() {}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void operator()(goal_ref const & in, goal_ref_buffer& result) override {
bool use_seq;
#ifdef _NO_OMP_
use_seq = true;
@ -612,43 +507,31 @@ public:
#endif
if (use_seq) {
// execute tasks sequentially
and_then_tactical::operator()(in, result, mc, pc, core);
and_then_tactical::operator()(in, result);
return;
}
// enabling proofs is possible, but requires translating subgoals back.
fail_if_proof_generation("par_and_then", in);
bool models_enabled = in->models_enabled();
bool proofs_enabled = in->proofs_enabled();
bool cores_enabled = in->unsat_core_enabled();
ast_manager & m = in->m();
goal_ref_buffer r1;
model_converter_ref mc1;
proof_converter_ref pc1;
expr_dependency_ref core1(m);
result.reset();
mc = 0;
pc = 0;
core = 0;
m_t1->operator()(in, r1, mc1, pc1, core1);
SASSERT(!is_decided(r1) || (!pc1 && !core1)); // the pc and core of decided goals is 0
unsigned r1_size = r1.size();
goal_ref_buffer r1;
m_t1->operator()(in, r1);
unsigned r1_size = r1.size();
SASSERT(r1_size > 0);
if (r1_size == 1) {
// Only one subgoal created... no need for parallelism
if (r1[0]->is_decided()) {
result.push_back(r1[0]);
if (models_enabled) mc = mc1;
SASSERT(!pc); SASSERT(!core);
return;
result.push_back(r1[0]);
return;
}
goal_ref r1_0 = r1[0];
m_t2->operator()(r1_0, result, mc, pc, core);
if (models_enabled) mc = concat(mc1.get(), mc.get());
if (proofs_enabled) pc = concat(pc1.get(), pc.get());
if (cores_enabled) core = m.mk_join(core1.get(), core);
m_t2->operator()(r1_0, result);
}
else {
if (cores_enabled) core = core1;
scoped_ptr_vector<ast_manager> managers;
tactic_ref_vector ts2;
@ -662,13 +545,9 @@ public:
ts2.push_back(m_t2->translate(*new_m));
}
proof_converter_ref_buffer pc_buffer;
model_converter_ref_buffer mc_buffer;
scoped_ptr_vector<expr_dependency_ref> core_buffer;
scoped_ptr_vector<goal_ref_buffer> goals_vect;
pc_buffer.resize(r1_size);
mc_buffer.resize(r1_size);
core_buffer.resize(r1_size);
goals_vect.resize(r1_size);
@ -684,14 +563,11 @@ public:
goal_ref new_g = g_copies[i];
goal_ref_buffer r2;
model_converter_ref mc2;
proof_converter_ref pc2;
expr_dependency_ref core2(new_m);
bool curr_failed = false;
try {
ts2[i]->operator()(new_g, r2, mc2, pc2, core2);
ts2[i]->operator()(new_g, r2);
}
catch (tactic_exception & ex) {
#pragma omp critical (par_and_then_tactical)
@ -756,31 +632,12 @@ public:
}
ast_translation translator(new_m, m, false);
SASSERT(r2.size() == 1);
result.push_back(r2[0]->translate(translator));
if (models_enabled) {
// mc2 contains the actual model
mc2 = mc2 ? mc2->translate(translator) : 0;
model_ref md;
md = alloc(model, m);
apply(mc2, md, 0);
apply(mc1, md, i);
mc = model2model_converter(md.get());
}
SASSERT(!pc); SASSERT(!core);
result.push_back(r2[0]->translate(translator));
}
}
else {
SASSERT(is_decided_unsat(r2));
// the proof and unsat core of a decided_unsat goal are stored in the node itself.
// pc2 and core2 must be 0.
SASSERT(!pc2);
SASSERT(!core2);
if (models_enabled) mc_buffer.set(i, 0);
if (proofs_enabled) {
proof * pr = r2[0]->pr(0);
pc_buffer.push_back(proof2proof_converter(m, pr));
}
if (cores_enabled && r2[0]->dep(0) != 0) {
expr_dependency_ref * new_dep = alloc(expr_dependency_ref, new_m);
*new_dep = r2[0]->dep(0);
@ -792,11 +649,10 @@ public:
goal_ref_buffer * new_r2 = alloc(goal_ref_buffer);
goals_vect.set(i, new_r2);
new_r2->append(r2.size(), r2.c_ptr());
mc_buffer.set(i, mc2.get());
pc_buffer.set(i, pc2.get());
if (cores_enabled && core2 != 0) {
dependency_converter* dc = r1[i]->dc();
if (cores_enabled && dc) {
expr_dependency_ref * new_dep = alloc(expr_dependency_ref, new_m);
*new_dep = core2;
*new_dep = (*dc)();
core_buffer.set(i, new_dep);
}
}
@ -814,25 +670,22 @@ public:
if (found_solution)
return;
core = 0;
sbuffer<unsigned> sz_buffer;
expr_dependency_ref core(m);
for (unsigned i = 0; i < r1_size; i++) {
ast_translation translator(*(managers[i]), m, false);
goal_ref_buffer * r = goals_vect[i];
unsigned j = result.size();
if (r != 0) {
for (unsigned k = 0; k < r->size(); k++) {
result.push_back((*r)[k]->translate(translator));
}
sz_buffer.push_back(r->size());
}
else {
sz_buffer.push_back(0);
if (proofs_enabled) {
// update proof converter of r1[i]
r1[i]->set(concat(r1[i]->pc(), result.size() - j, result.c_ptr() + j));
}
if (mc_buffer[i] != 0)
mc_buffer.set(i, mc_buffer[i]->translate(translator));
if (pc_buffer[i] != 0)
pc_buffer.set(i, pc_buffer[i]->translate(translator));
expr_dependency_translation td(translator);
if (core_buffer[i] != 0) {
expr_dependency_ref curr_core(m);
@ -840,24 +693,24 @@ public:
core = m.mk_join(curr_core, core);
}
}
if (core) {
in->add(dependency_converter::unit(core));
}
if (result.empty()) {
// all subgoals were shown to be unsat.
// create an decided_unsat goal with the proof
in->reset_all();
proof_ref pr(m);
if (proofs_enabled)
apply(m, pc1, pc_buffer, pr);
SASSERT(cores_enabled || core == 0);
if (proofs_enabled) {
apply(m, in->pc(), pr);
}
dependency_converter* dc = in->dc();
if (cores_enabled && dc) {
core = (*dc)();
}
in->assert_expr(m.mk_false(), pr, core);
core = 0;
result.push_back(in.get());
SASSERT(!mc); SASSERT(!pc); SASSERT(!core);
}
else {
if (models_enabled) mc = concat(mc1.get(), mc_buffer.size(), mc_buffer.c_ptr(), sz_buffer.c_ptr());
if (proofs_enabled) pc = concat(pc1.get(), pc_buffer.size(), pc_buffer.c_ptr(), sz_buffer.c_ptr());
SASSERT(cores_enabled || core == 0);
}
}
}
@ -885,26 +738,19 @@ tactic * par_and_then(unsigned num, tactic * const * ts) {
class unary_tactical : public tactic {
protected:
tactic * m_t;
tactic_ref m_t;
public:
unary_tactical(tactic * t):
m_t(t) {
SASSERT(t);
t->inc_ref();
SASSERT(t);
}
virtual ~unary_tactical() {
m_t->dec_ref();
}
virtual ~unary_tactical() { }
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
m_t->operator()(in, result, mc, pc, core);
void operator()(goal_ref const & in, goal_ref_buffer& result) override {
m_t->operator()(in, result);
}
virtual void cleanup(void) { m_t->cleanup(); }
@ -929,16 +775,10 @@ class repeat_tactical : public unary_tactical {
void operator()(unsigned depth,
goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer& result) {
// TODO: implement a non-recursive version.
if (depth > m_max_depth) {
result.push_back(in.get());
mc = 0;
pc = 0;
core = 0;
return;
}
@ -947,23 +787,14 @@ class repeat_tactical : public unary_tactical {
bool cores_enabled = in->unsat_core_enabled();
ast_manager & m = in->m();
goal_ref_buffer r1;
model_converter_ref mc1;
proof_converter_ref pc1;
expr_dependency_ref core1(m);
result.reset();
mc = 0;
pc = 0;
core = 0;
goal_ref_buffer r1;
result.reset();
{
goal orig_in(in->m(), proofs_enabled, models_enabled, cores_enabled);
orig_in.copy_from(*(in.get()));
m_t->operator()(in, r1, mc1, pc1, core1);
if (is_equal(orig_in, *(in.get()))) {
result.push_back(r1[0]);
if (models_enabled) mc = mc1;
if (proofs_enabled) pc = pc1;
if (cores_enabled) core = core1;
m_t->operator()(in, r1);
if (r1.size() == 1 && is_equal(orig_in, *(r1[0]))) {
result.push_back(r1[0]);
return;
}
}
@ -971,61 +802,31 @@ class repeat_tactical : public unary_tactical {
SASSERT(r1_size > 0);
if (r1_size == 1) {
if (r1[0]->is_decided()) {
result.push_back(r1[0]);
if (models_enabled) mc = mc1;
SASSERT(!pc); SASSERT(!core);
result.push_back(r1[0]);
return;
}
goal_ref r1_0 = r1[0];
operator()(depth+1, r1_0, result, mc, pc, core);
if (models_enabled) mc = concat(mc.get(), mc1.get());
if (proofs_enabled) pc = concat(pc.get(), pc1.get());
if (cores_enabled) core = m.mk_join(core1.get(), core);
operator()(depth+1, r1_0, result);
}
else {
if (cores_enabled) core = core1;
proof_converter_ref_buffer pc_buffer;
model_converter_ref_buffer mc_buffer;
sbuffer<unsigned> sz_buffer;
goal_ref_buffer r2;
for (unsigned i = 0; i < r1_size; i++) {
goal_ref g = r1[i];
r2.reset();
model_converter_ref mc2;
proof_converter_ref pc2;
expr_dependency_ref core2(m);
operator()(depth+1, g, r2, mc2, pc2, core2);
r2.reset();
operator()(depth+1, g, r2);
if (is_decided(r2)) {
SASSERT(r2.size() == 1);
if (is_decided_sat(r2)) {
// found solution...
result.push_back(r2[0]);
if (models_enabled) {
// mc2 contains the actual model
model_ref md;
if (mc2) (*mc2)(md, 0);
if (mc1) (*mc1)(md, i);
mc = model2model_converter(md.get());
}
SASSERT(!pc); SASSERT(!core);
return;
}
else {
SASSERT(is_decided_unsat(r2));
SASSERT(!pc2);
SASSERT(!core2);
if (models_enabled) mc_buffer.push_back(0);
if (proofs_enabled) pc_buffer.push_back(proof2proof_converter(m, r2[0]->pr(0)));
if (models_enabled || proofs_enabled) sz_buffer.push_back(0);
if (cores_enabled) core = m.mk_join(core.get(), r2[0]->dep(0));
}
}
else {
result.append(r2.size(), r2.c_ptr());
if (models_enabled) mc_buffer.push_back(mc2.get());
if (proofs_enabled) pc_buffer.push_back(pc2.get());
if (models_enabled || proofs_enabled) sz_buffer.push_back(r2.size());
if (cores_enabled) core = m.mk_join(core.get(), core2.get());
result.append(r2.size(), r2.c_ptr());
}
}
@ -1034,18 +835,15 @@ class repeat_tactical : public unary_tactical {
// create an decided_unsat goal with the proof
in->reset_all();
proof_ref pr(m);
if (proofs_enabled)
apply(m, pc1, pc_buffer, pr);
SASSERT(cores_enabled || core == 0);
expr_dependency_ref core(m);
if (proofs_enabled) {
apply(m, in->pc(), pr);
}
if (cores_enabled && in->dc()) {
core = (*in->dc())();
}
in->assert_expr(m.mk_false(), pr, core);
core = 0;
result.push_back(in.get());
SASSERT(!mc); SASSERT(!pc); SASSERT(!core);
}
else {
if (models_enabled) mc = concat(mc1.get(), mc_buffer.size(), mc_buffer.c_ptr(), sz_buffer.c_ptr());
if (proofs_enabled) pc = concat(pc1.get(), pc_buffer.size(), pc_buffer.c_ptr(), sz_buffer.c_ptr());
SASSERT(cores_enabled || core == 0);
}
}
}
@ -1056,12 +854,8 @@ public:
m_max_depth(max_depth) {
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
operator()(0, in, result, mc, pc, core);
void operator()(goal_ref const & in, goal_ref_buffer& result) override {
operator()(0, in, result);
}
virtual tactic * translate(ast_manager & m) {
@ -1079,17 +873,10 @@ class fail_if_branching_tactical : public unary_tactical {
public:
fail_if_branching_tactical(tactic * t, unsigned threshold):unary_tactical(t), m_threshold(threshold) {}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
m_t->operator()(in, result, mc, pc, core);
void operator()(goal_ref const & in, goal_ref_buffer& result) override {
m_t->operator()(in, result);
if (result.size() > m_threshold) {
result.reset();
mc = 0;
pc = 0;
core = 0;
result.reset(); // assumes in is not strenthened to one of the branches
throw tactic_exception("failed-if-branching tactical");
}
};
@ -1108,12 +895,8 @@ class cleanup_tactical : public unary_tactical {
public:
cleanup_tactical(tactic * t):unary_tactical(t) {}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
m_t->operator()(in, result, mc, pc, core);
void operator()(goal_ref const & in, goal_ref_buffer& result) override {
m_t->operator()(in, result);
m_t->cleanup();
}
@ -1132,16 +915,12 @@ class try_for_tactical : public unary_tactical {
public:
try_for_tactical(tactic * t, unsigned ts):unary_tactical(t), m_timeout(ts) {}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void operator()(goal_ref const & in, goal_ref_buffer& result) override {
cancel_eh<reslimit> eh(in->m().limit());
{
// Warning: scoped_timer is not thread safe in Linux.
scoped_timer timer(m_timeout, &eh);
m_t->operator()(in, result, mc, pc, core);
m_t->operator()(in, result);
}
}
@ -1202,13 +981,9 @@ public:
annotate_tactical(char const* name, tactic* t):
unary_tactical(t), m_name(name) {}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void operator()(goal_ref const & in, goal_ref_buffer& result) override {
scope _scope(m_name);
m_t->operator()(in, result, mc, pc, core);
m_t->operator()(in, result);
}
virtual tactic * translate(ast_manager & m) {
@ -1223,34 +998,27 @@ tactic * annotate_tactic(char const* name, tactic * t) {
}
class cond_tactical : public binary_tactical {
probe * m_p;
probe_ref m_p;
public:
cond_tactical(probe * p, tactic * t1, tactic * t2):
binary_tactical(t1, t2),
m_p(p) {
SASSERT(m_p);
m_p->inc_ref();
}
~cond_tactical() {
m_p->dec_ref();
}
virtual ~cond_tactical() {}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void operator()(goal_ref const & in, goal_ref_buffer & result) override {
if (m_p->operator()(*(in.get())).is_true())
m_t1->operator()(in, result, mc, pc, core);
m_t1->operator()(in, result);
else
m_t2->operator()(in, result, mc, pc, core);
m_t2->operator()(in, result);
}
virtual tactic * translate(ast_manager & m) {
tactic * new_t1 = m_t1->translate(m);
tactic * new_t2 = m_t2->translate(m);
return alloc(cond_tactical, m_p, new_t1, new_t2);
return alloc(cond_tactical, m_p.get(), new_t1, new_t2);
}
};
@ -1263,28 +1031,18 @@ tactic * when(probe * p, tactic * t) {
}
class fail_if_tactic : public tactic {
probe * m_p;
probe_ref m_p;
public:
fail_if_tactic(probe * p):
m_p(p) {
SASSERT(m_p);
m_p->inc_ref();
}
~fail_if_tactic() {
m_p->dec_ref();
}
virtual ~fail_if_tactic() {}
void cleanup() {}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
mc = 0;
pc = 0;
core = 0;
void operator()(goal_ref const & in, goal_ref_buffer& result) override {
if (m_p->operator()(*(in.get())).is_true()) {
throw tactic_exception("fail-if tactic");
}
@ -1308,18 +1066,12 @@ class if_no_proofs_tactical : public unary_tactical {
public:
if_no_proofs_tactical(tactic * t):unary_tactical(t) {}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void operator()(goal_ref const & in, goal_ref_buffer & result) override {
if (in->proofs_enabled()) {
mc = 0; pc = 0; core = 0;
result.reset();
result.push_back(in.get());
}
else {
m_t->operator()(in, result, mc, pc, core);
m_t->operator()(in, result);
}
}
@ -1330,18 +1082,12 @@ class if_no_unsat_cores_tactical : public unary_tactical {
public:
if_no_unsat_cores_tactical(tactic * t):unary_tactical(t) {}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void operator()(goal_ref const & in, goal_ref_buffer& result) override {
if (in->unsat_core_enabled()) {
mc = 0; pc = 0; core = 0;
result.reset();
result.push_back(in.get());
}
else {
m_t->operator()(in, result, mc, pc, core);
m_t->operator()(in, result);
}
}
@ -1352,18 +1098,12 @@ class if_no_models_tactical : public unary_tactical {
public:
if_no_models_tactical(tactic * t):unary_tactical(t) {}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void operator()(goal_ref const & in, goal_ref_buffer& result) override {
if (in->models_enabled()) {
mc = 0; pc = 0; core = 0;
result.reset();
result.push_back(in.get());
}
else {
m_t->operator()(in, result, mc, pc, core);
m_t->operator()(in, result);
}
}

View file

@ -38,12 +38,8 @@ class macro_finder_tactic : public tactic {
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
mc = 0; pc = 0; core = 0;
tactic_report report("macro-finder", *g);
bool produce_proofs = g->proofs_enabled();
@ -76,8 +72,7 @@ class macro_finder_tactic : public tactic {
func_decl * f = mm.get_macro_interpretation(i, f_interp);
evmc->add(f, f_interp);
}
mc = evmc;
g->add(evmc);
g->inc_depth();
result.push_back(g.get());
TRACE("macro-finder", g->display(tout););
@ -118,11 +113,8 @@ public:
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(in, result, mc, pc, core);
goal_ref_buffer & result) {
(*m_imp)(in, result);
}
virtual void cleanup() {

View file

@ -36,12 +36,8 @@ class quasi_macros_tactic : public tactic {
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
mc = 0; pc = 0; core = 0;
tactic_report report("quasi-macros", *g);
bool produce_proofs = g->proofs_enabled();
@ -88,8 +84,7 @@ class quasi_macros_tactic : public tactic {
func_decl * f = mm.get_macro_interpretation(i, f_interp);
evmc->add(f, f_interp);
}
mc = evmc;
g->add(evmc);
g->inc_depth();
result.push_back(g.get());
TRACE("quasi-macros", g->display(tout););
@ -129,11 +124,8 @@ public:
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(in, result, mc, pc, core);
goal_ref_buffer & result) {
(*m_imp)(in, result);
}
virtual void cleanup() {

View file

@ -32,12 +32,8 @@ class ufbv_rewriter_tactic : public tactic {
ast_manager & m() const { return m_manager; }
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
goal_ref_buffer & result) {
SASSERT(g->is_well_sorted());
mc = 0; pc = 0; core = 0;
tactic_report report("ufbv-rewriter", *g);
fail_if_unsat_core_generation("ufbv-rewriter", g);
@ -60,7 +56,8 @@ class ufbv_rewriter_tactic : public tactic {
for (unsigned i = 0; i < new_forms.size(); i++)
g->assert_expr(new_forms.get(i), produce_proofs ? new_proofs.get(i) : 0, 0);
mc = 0; // CMW: Remark: The demodulator could potentially remove all references to a variable.
// CMW: Remark: The demodulator could potentially
// remove all references to a variable.
g->inc_depth();
result.push_back(g.get());
@ -101,11 +98,8 @@ public:
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(in, result, mc, pc, core);
goal_ref_buffer & result) {
(*m_imp)(in, result);
}
virtual void cleanup() {