3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-24 09:35:32 +00:00

merge with master

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2018-07-02 15:31:26 -07:00
commit 03ed33ac02
30 changed files with 129 additions and 76 deletions

View file

@ -968,7 +968,7 @@ private:
void throw_tactic(expr* e) {
std::stringstream strm;
strm << "goal is in a fragment unsupported by pb2bv. Offending expression: " << mk_pp(e, m);
throw tactic_exception(strm.str().c_str());
throw tactic_exception(strm.str());
}
};

View file

@ -30,7 +30,9 @@ Notes:
#include "tactic/core/reduce_invertible_tactic.h"
#include "tactic/core/collect_occs.h"
#include "tactic/generic_model_converter.h"
#include <cstdint>
namespace {
class reduce_invertible_tactic : public tactic {
ast_manager& m;
bv_util m_bv;
@ -60,7 +62,8 @@ public:
generic_model_converter_ref mc;
occs(*g, vars);
expr_safe_replace sub(m);
expr_ref p(m), new_v(m);
expr_ref new_v(m);
expr * p;
for (expr* v : vars) {
if (is_invertible(v, p, new_v, &mc)) {
mark_inverted(p);
@ -75,8 +78,8 @@ public:
expr_ref f_new(m);
sub(f, f_new);
rw(f_new, f_new);
proof_ref new_pr(m);
if (f == f_new) continue;
proof_ref new_pr(m);
if (g->proofs_enabled()) {
proof * pr = g->pr(idx);
new_pr = m.mk_modus_ponens(pr, new_pr);
@ -120,11 +123,20 @@ private:
}
}
// store up to two parents of expression.
// store one parent of expression, or null if multiple
struct parents {
parents(): m_p1(nullptr), m_p2(nullptr) {}
expr* m_p1;
expr* m_p2;
parents(): m_p(0) {}
uintptr_t m_p;
void set(expr * e) {
SASSERT((uintptr_t)e != 1);
if (!m_p) m_p = (uintptr_t)e;
else m_p = 1;
}
expr * get() const {
return m_p == 1 ? nullptr : (expr*)m_p;
}
};
svector<parents> m_parents;
struct parent_collector {
@ -132,9 +144,8 @@ private:
parent_collector(reduce_invertible_tactic& c):c(c) {}
void operator()(app* n) {
for (expr* arg : *n) {
c.m_parents.reserve(arg->get_id() + 1, parents());
parents& p = c.m_parents[arg->get_id()];
if (!p.m_p1) p.m_p1 = n; else p.m_p2 = n;
c.m_parents.reserve(arg->get_id() + 1);
c.m_parents[arg->get_id()].set(n);
}
}
void operator()(expr*) {}
@ -156,11 +167,13 @@ private:
// TBD: could be made to be recursive, by walking multiple layers of parents.
bool is_invertible(expr* v, expr_ref& p, expr_ref& new_v, generic_model_converter_ref* mc) {
p = m_parents[v->get_id()].m_p1;
if (m_parents[v->get_id()].m_p2 || !p) return false;
bool is_invertible(expr* v, expr*& p, expr_ref& new_v, generic_model_converter_ref* mc) {
p = m_parents[v->get_id()].get();
SASSERT(p);
if (m_inverted.is_marked(p)) return false;
if (mc && !is_ground(p)) return false;
if (m_bv.is_bv_add(p)) {
if (mc) {
ensure_mc(mc);
@ -175,6 +188,24 @@ private:
new_v = v;
return true;
}
expr *a, *b;
// shift(a, b), where both a,b are single use. Set b = 0 and return a
// FIXME: needs to check that both variables are grounded by same quantifier
if (m_bv.is_bv_shl(p, a, b) ||
m_bv.is_bv_ashr(p, a, b) ||
m_bv.is_bv_lshr(p, a, b)) {
if (!m_parents[(v == a ? b : a)->get_id()].get())
return false;
if (mc) {
ensure_mc(mc);
(*mc)->add(b, m_bv.mk_numeral(rational::zero(), get_sort(b)));
}
new_v = a;
return true;
}
if (m_bv.is_bv_mul(p)) {
expr_ref rest(m);
for (expr* arg : *to_app(p)) {
@ -365,7 +396,8 @@ private:
expr_safe_replace sub(m);
t.m_parents.reset();
t.m_inverted.reset();
expr_ref p(m), new_v(m);
expr_ref new_v(m);
expr * p;
{
parent_collector proc(t);
@ -409,11 +441,9 @@ private:
rewriter_tpl<reduce_q_rw_cfg>(t.m, false, m_cfg),
m_cfg(t) {}
};
};
}
tactic * mk_reduce_invertible_tactic(ast_manager & m, params_ref const &) {
return alloc(reduce_invertible_tactic, m);
}

View file

@ -206,7 +206,7 @@ void fail_if_proof_generation(char const * tactic_name, goal_ref const & in) {
if (in->proofs_enabled()) {
std::string msg = tactic_name;
msg += " does not support proof production";
throw tactic_exception(msg.c_str());
throw tactic_exception(std::move(msg));
}
}
@ -214,7 +214,7 @@ void fail_if_unsat_core_generation(char const * tactic_name, goal_ref const & in
if (in->unsat_core_enabled()) {
std::string msg = tactic_name;
msg += " does not support unsat core production";
throw tactic_exception(msg.c_str());
throw tactic_exception(std::move(msg));
}
}
@ -222,6 +222,6 @@ void fail_if_model_generation(char const * tactic_name, goal_ref const & in) {
if (in->models_enabled()) {
std::string msg = tactic_name;
msg += " does not generate models";
throw tactic_exception(msg.c_str());
throw tactic_exception(std::move(msg));
}
}

View file

@ -26,7 +26,7 @@ class tactic_exception : public z3_exception {
protected:
std::string m_msg;
public:
tactic_exception(char const * msg):m_msg(msg) {}
tactic_exception(std::string && msg) : m_msg(std::move(msg)) {}
~tactic_exception() override {}
char const * msg() const override { return m_msg.c_str(); }
};

View file

@ -463,9 +463,9 @@ public:
if (finished_id == UINT_MAX) {
switch (ex_kind) {
case ERROR_EX: throw z3_error(error_code);
case TACTIC_EX: throw tactic_exception(ex_msg.c_str());
case TACTIC_EX: throw tactic_exception(std::move(ex_msg));
default:
throw default_exception(ex_msg.c_str());
throw default_exception(std::move(ex_msg));
}
}
}
@ -660,9 +660,9 @@ public:
if (failed) {
switch (ex_kind) {
case ERROR_EX: throw z3_error(error_code);
case TACTIC_EX: throw tactic_exception(ex_msg.c_str());
case TACTIC_EX: throw tactic_exception(std::move(ex_msg));
default:
throw default_exception(ex_msg.c_str());
throw default_exception(std::move(ex_msg));
}
}