3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-23 17:15:31 +00:00

reducing dependencies on simplifier

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2017-08-22 15:09:34 -07:00
parent a206362cef
commit e2b46257d6
18 changed files with 289 additions and 215 deletions

View file

@ -389,16 +389,16 @@ public:
app * mk_lt(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_LT, arg1, arg2); }
app * mk_gt(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_GT, arg1, arg2); }
app * mk_add(unsigned num_args, expr * const * args) { return m_manager.mk_app(m_afid, OP_ADD, num_args, args); }
app * mk_add(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_ADD, arg1, arg2); }
app * mk_add(expr * arg1, expr * arg2, expr* arg3) { return m_manager.mk_app(m_afid, OP_ADD, arg1, arg2, arg3); }
app * mk_add(unsigned num_args, expr * const * args) const { return m_manager.mk_app(m_afid, OP_ADD, num_args, args); }
app * mk_add(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_ADD, arg1, arg2); }
app * mk_add(expr * arg1, expr * arg2, expr* arg3) const { return m_manager.mk_app(m_afid, OP_ADD, arg1, arg2, arg3); }
app * mk_sub(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_SUB, arg1, arg2); }
app * mk_sub(unsigned num_args, expr * const * args) { return m_manager.mk_app(m_afid, OP_SUB, num_args, args); }
app * mk_mul(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_MUL, arg1, arg2); }
app * mk_mul(expr * arg1, expr * arg2, expr* arg3) { return m_manager.mk_app(m_afid, OP_MUL, arg1, arg2, arg3); }
app * mk_mul(unsigned num_args, expr * const * args) { return m_manager.mk_app(m_afid, OP_MUL, num_args, args); }
app * mk_uminus(expr * arg) { return m_manager.mk_app(m_afid, OP_UMINUS, arg); }
app * mk_sub(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_SUB, arg1, arg2); }
app * mk_sub(unsigned num_args, expr * const * args) const { return m_manager.mk_app(m_afid, OP_SUB, num_args, args); }
app * mk_mul(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_MUL, arg1, arg2); }
app * mk_mul(expr * arg1, expr * arg2, expr* arg3) const { return m_manager.mk_app(m_afid, OP_MUL, arg1, arg2, arg3); }
app * mk_mul(unsigned num_args, expr * const * args) const { return m_manager.mk_app(m_afid, OP_MUL, num_args, args); }
app * mk_uminus(expr * arg) const { return m_manager.mk_app(m_afid, OP_UMINUS, arg); }
app * mk_div(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_DIV, arg1, arg2); }
app * mk_idiv(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_IDIV, arg1, arg2); }
app * mk_rem(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_REM, arg1, arg2); }

View file

@ -784,6 +784,12 @@ bool bv_recognizers::is_numeral(expr const * n, rational & val, unsigned & bv_si
return true;
}
bool bv_recognizers::is_numeral(expr const * n, rational & val) const {
unsigned bv_size = 0;
return is_numeral(n, val, bv_size);
}
bool bv_recognizers::is_allone(expr const * e) const {
rational r;
unsigned bv_size;
@ -847,7 +853,7 @@ bv_util::bv_util(ast_manager & m):
m_plugin = static_cast<bv_decl_plugin*>(m.get_plugin(m.mk_family_id("bv")));
}
app * bv_util::mk_numeral(rational const & val, sort* s) {
app * bv_util::mk_numeral(rational const & val, sort* s) const {
if (!is_bv_sort(s)) {
return 0;
}
@ -855,7 +861,7 @@ app * bv_util::mk_numeral(rational const & val, sort* s) {
return mk_numeral(val, bv_size);
}
app * bv_util::mk_numeral(rational const & val, unsigned bv_size) {
app * bv_util::mk_numeral(rational const & val, unsigned bv_size) const {
parameter p1(val);
parameter p[2] = { p1, parameter(static_cast<int>(bv_size)) };
return m_manager.mk_app(get_fid(), OP_BV_NUM, 2, p, 0, 0);

View file

@ -293,6 +293,7 @@ public:
family_id get_fid() const { return m_afid; }
family_id get_family_id() const { return get_fid(); }
bool is_numeral(expr const * n, rational & val) const;
bool is_numeral(expr const * n, rational & val, unsigned & bv_size) const;
bool is_numeral(expr const * n) const { return is_app_of(n, get_fid(), OP_BV_NUM); }
bool is_allone(expr const * e) const;
@ -381,9 +382,9 @@ public:
ast_manager & get_manager() const { return m_manager; }
app * mk_numeral(rational const & val, sort* s);
app * mk_numeral(rational const & val, unsigned bv_size);
app * mk_numeral(uint64 u, unsigned bv_size) { return mk_numeral(rational(u, rational::ui64()), bv_size); }
app * mk_numeral(rational const & val, sort* s) const;
app * mk_numeral(rational const & val, unsigned bv_size) const;
app * mk_numeral(uint64 u, unsigned bv_size) const { return mk_numeral(rational(u, rational::ui64()), bv_size); }
sort * mk_sort(unsigned bv_size);
unsigned get_bv_size(sort const * s) const {

View file

@ -48,14 +48,12 @@ bool macro_finder::is_macro(expr * n, app_ref & head, expr_ref & def) {
bool macro_finder::is_arith_macro(expr * n, proof * pr, expr_ref_vector & new_exprs, proof_ref_vector & new_prs) {
if (!is_quantifier(n) || !to_quantifier(n)->is_forall())
return false;
arith_simplifier_plugin * as = get_arith_simp();
arith_util & autil = as->get_arith_util();
expr * body = to_quantifier(n)->get_expr();
unsigned num_decls = to_quantifier(n)->get_num_decls();
if (!autil.is_le(body) && !autil.is_ge(body) && !m_manager.is_eq(body))
if (!m_autil.is_le(body) && !m_autil.is_ge(body) && !m_manager.is_eq(body))
return false;
if (!as->is_add(to_app(body)->get_arg(0)))
if (!m_autil.is_add(to_app(body)->get_arg(0)))
return false;
app_ref head(m_manager);
expr_ref def(m_manager);
@ -66,10 +64,10 @@ bool macro_finder::is_arith_macro(expr * n, proof * pr, expr_ref_vector & new_ex
if (!inv || m_manager.is_eq(body))
new_body = m_manager.mk_app(to_app(body)->get_decl(), head, def);
else if (as->is_le(body))
new_body = autil.mk_ge(head, def);
else if (m_autil.is_le(body))
new_body = m_autil.mk_ge(head, def);
else
new_body = autil.mk_le(head, def);
new_body = m_autil.mk_le(head, def);
quantifier_ref new_q(m_manager);
new_q = m_manager.update_quantifier(to_quantifier(n), new_body);
@ -88,10 +86,9 @@ bool macro_finder::is_arith_macro(expr * n, proof * pr, expr_ref_vector & new_ex
func_decl * k = m_manager.mk_fresh_func_decl(f->get_name(), symbol::null, f->get_arity(), f->get_domain(), f->get_range());
app * k_app = m_manager.mk_app(k, head->get_num_args(), head->get_args());
expr_ref_buffer new_rhs_args(m_manager);
expr_ref new_rhs2(m_manager);
as->mk_add(def, k_app, new_rhs2);
expr_ref new_rhs2(m_autil.mk_add(def, k_app), m_manager);
expr * body1 = m_manager.mk_eq(head, new_rhs2);
expr * body2 = m_manager.mk_app(new_body->get_decl(), k_app, as->mk_numeral(rational(0)));
expr * body2 = m_manager.mk_app(new_body->get_decl(), k_app, m_autil.mk_int(0));
quantifier * q1 = m_manager.update_quantifier(new_q, body1);
expr * patterns[1] = { m_manager.mk_pattern(k_app) };
quantifier * q2 = m_manager.update_quantifier(new_q, 1, patterns, body2);
@ -158,7 +155,8 @@ static void pseudo_predicate_macro2macro(ast_manager & m, app * head, app * t, e
macro_finder::macro_finder(ast_manager & m, macro_manager & mm):
m_manager(m),
m_macro_manager(mm),
m_util(mm.get_util()) {
m_util(mm.get_util()),
m_autil(m) {
}
macro_finder::~macro_finder() {

View file

@ -20,7 +20,6 @@ Revision History:
#define MACRO_FINDER_H_
#include "ast/macros/macro_manager.h"
#include "ast/simplifier/arith_simplifier_plugin.h"
bool is_macro_head(expr * n, unsigned num_decls);
@ -37,7 +36,7 @@ class macro_finder {
ast_manager & m_manager;
macro_manager & m_macro_manager;
macro_util & m_util;
arith_simplifier_plugin * get_arith_simp() { return m_util.get_arith_simp(); }
arith_util m_autil;
bool expand_macros(unsigned num, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs);
bool is_arith_macro(expr * n, proof * pr, expr_ref_vector & new_exprs, proof_ref_vector & new_prs);

View file

@ -28,7 +28,7 @@ Revision History:
macro_manager::macro_manager(ast_manager & m, simplifier & s):
m_manager(m),
m_simplifier(s),
m_util(m, s),
m_util(m),
m_decls(m),
m_macros(m),
m_macro_prs(m),

View file

@ -29,16 +29,17 @@ Revision History:
#include "ast/well_sorted.h"
#include "ast/rewriter/bool_rewriter.h"
macro_util::macro_util(ast_manager & m, simplifier & s):
macro_util::macro_util(ast_manager & m):
m_manager(m),
m_bv(m),
m_simplifier(s),
m_arith_simp(0),
m_bv_simp(0),
m_arith(m),
m_arith_rw(m),
m_bv_rw(m),
m_forbidden_set(0),
m_curr_clause(0) {
}
#if 0
arith_simplifier_plugin * macro_util::get_arith_simp() const {
if (m_arith_simp == 0) {
const_cast<macro_util*>(this)->m_arith_simp = static_cast<arith_simplifier_plugin*>(m_simplifier.get_plugin(m_manager.mk_family_id("arith")));
@ -54,7 +55,7 @@ bv_simplifier_plugin * macro_util::get_bv_simp() const {
SASSERT(m_bv_simp != 0);
return m_bv_simp;
}
#endif
bool macro_util::is_bv(expr * n) const {
return m_bv.is_bv(n);
@ -65,32 +66,41 @@ bool macro_util::is_bv_sort(sort * s) const {
}
bool macro_util::is_add(expr * n) const {
return get_arith_simp()->is_add(n) || m_bv.is_bv_add(n);
return m_arith.is_add(n) || m_bv.is_bv_add(n);
}
bool macro_util::is_times_minus_one(expr * n, expr * & arg) const {
return get_arith_simp()->is_times_minus_one(n, arg) || get_bv_simp()->is_times_minus_one(n, arg);
return m_arith_rw.is_times_minus_one(n, arg) || m_bv_rw.is_times_minus_one(n, arg);
}
bool macro_util::is_le(expr * n) const {
return get_arith_simp()->is_le(n) || m_bv.is_bv_ule(n) || m_bv.is_bv_sle(n);
return m_arith.is_le(n) || m_bv.is_bv_ule(n) || m_bv.is_bv_sle(n);
}
bool macro_util::is_le_ge(expr * n) const {
return get_arith_simp()->is_le_ge(n) || m_bv.is_bv_ule(n) || m_bv.is_bv_sle(n);
return m_arith.is_ge(n) || m_arith.is_le(n) || m_bv.is_bv_ule(n) || m_bv.is_bv_sle(n);
}
poly_simplifier_plugin * macro_util::get_poly_simp_for(sort * s) const {
if (is_bv_sort(s))
return get_bv_simp();
else
return get_arith_simp();
bool macro_util::is_var_plus_ground(expr * n, bool & inv, var * & v, expr_ref & t) {
return m_arith_rw.is_var_plus_ground(n, inv, v, t) || m_bv_rw.is_var_plus_ground(n, inv, v, t);
}
bool macro_util::is_zero_safe(expr * n) const {
if (m_bv_rw.is_bv(n)) {
return m_bv.is_zero(n);
}
else {
return m_arith_rw.is_zero(n);
}
}
app * macro_util::mk_zero(sort * s) const {
poly_simplifier_plugin * ps = get_poly_simp_for(s);
ps->set_curr_sort(s);
return ps->mk_zero();
if (m_bv.is_bv_sort(s)) {
return m_bv.mk_numeral(rational(0), s);
}
else {
return m_arith.mk_numeral(rational(0), s);
}
}
void macro_util::mk_sub(expr * t1, expr * t2, expr_ref & r) const {
@ -98,7 +108,7 @@ void macro_util::mk_sub(expr * t1, expr * t2, expr_ref & r) const {
r = m_bv.mk_bv_sub(t1, t2);
}
else {
get_arith_simp()->mk_sub(t1, t2, r);
r = m_arith.mk_sub(t1, t2);
}
}
@ -107,18 +117,32 @@ void macro_util::mk_add(expr * t1, expr * t2, expr_ref & r) const {
r = m_bv.mk_bv_add(t1, t2);
}
else {
get_arith_simp()->mk_add(t1, t2, r);
r = m_arith.mk_add(t1, t2);
}
}
void macro_util::mk_add(unsigned num_args, expr * const * args, sort * s, expr_ref & r) const {
if (num_args == 0) {
switch (num_args) {
case 0:
r = mk_zero(s);
return;
break;
case 1:
r = args[0];
break;
default:
if (m_bv.is_bv_sort(s)) {
r = args[0];
while (num_args >= 2) {
--num_args;
++args;
r = m_bv.mk_bv_add(r, args[0]);
}
}
else {
r = m_arith.mk_add(num_args, args);
}
break;
}
poly_simplifier_plugin * ps = get_poly_simp_for(s);
ps->set_curr_sort(s);
ps->mk_add(num_args, args, r);
}
/**
@ -241,13 +265,12 @@ bool macro_util::poly_contains_head(expr * n, func_decl * f, expr * exception) c
bool macro_util::is_arith_macro(expr * n, unsigned num_decls, app_ref & head, expr_ref & def, bool & inv) const {
// TODO: obsolete... we should move to collect_arith_macro_candidates
arith_simplifier_plugin * as = get_arith_simp();
if (!m_manager.is_eq(n) && !as->is_le(n) && !as->is_ge(n))
if (!m_manager.is_eq(n) && !m_arith.is_le(n) && !m_arith.is_ge(n))
return false;
expr * lhs = to_app(n)->get_arg(0);
expr * rhs = to_app(n)->get_arg(1);
if (!as->is_numeral(rhs))
if (!m_arith.is_numeral(rhs))
return false;
inv = false;
@ -272,7 +295,7 @@ bool macro_util::is_arith_macro(expr * n, unsigned num_decls, app_ref & head, ex
!poly_contains_head(lhs, to_app(arg)->get_decl(), arg)) {
h = arg;
}
else if (h == 0 && as->is_times_minus_one(arg, neg_arg) &&
else if (h == 0 && m_arith_rw.is_times_minus_one(arg, neg_arg) &&
is_macro_head(neg_arg, num_decls) &&
!is_forbidden(to_app(neg_arg)->get_decl()) &&
!poly_contains_head(lhs, to_app(neg_arg)->get_decl(), arg)) {
@ -287,11 +310,11 @@ bool macro_util::is_arith_macro(expr * n, unsigned num_decls, app_ref & head, ex
return false;
head = to_app(h);
expr_ref tmp(m_manager);
as->mk_add(args.size(), args.c_ptr(), tmp);
tmp = m_arith.mk_add(args.size(), args.c_ptr());
if (inv)
as->mk_sub(tmp, rhs, def);
def = m_arith.mk_sub(tmp, rhs);
else
as->mk_sub(rhs, tmp, def);
def = m_arith.mk_sub(rhs, tmp);
return true;
}

View file

@ -22,12 +22,8 @@ Revision History:
#include "ast/ast.h"
#include "util/obj_hashtable.h"
#include "ast/simplifier/simplifier.h"
class poly_simplifier_plugin;
class arith_simplifier_plugin;
class bv_simplifier_plugin;
class basic_simplifier_plugin;
#include "ast/rewriter/arith_rewriter.h"
#include "ast/rewriter/bv_rewriter.h"
class macro_util {
public:
@ -63,9 +59,9 @@ public:
private:
ast_manager & m_manager;
bv_util m_bv;
simplifier & m_simplifier;
arith_simplifier_plugin * m_arith_simp;
bv_simplifier_plugin * m_bv_simp;
arith_util m_arith;
arith_rewriter m_arith_rw;
bv_rewriter m_bv_rw;
obj_hashtable<func_decl> * m_forbidden_set;
bool is_forbidden(func_decl * f) const { return m_forbidden_set != 0 && m_forbidden_set->contains(f); }
@ -94,11 +90,9 @@ private:
public:
macro_util(ast_manager & m, simplifier & s);
macro_util(ast_manager & m);
void set_forbidden_set(obj_hashtable<func_decl> * s) { m_forbidden_set = s; }
arith_simplifier_plugin * get_arith_simp() const;
bv_simplifier_plugin * get_bv_simp() const;
bool is_macro_head(expr * n, unsigned num_decls) const;
bool is_left_simple_macro(expr * n, unsigned num_decls, app_ref & head, expr_ref & def) const;
@ -113,6 +107,8 @@ public:
return is_arith_macro(n, num_decls, head, def, inv);
}
bool is_zero_safe(expr * n) const;
bool is_var_plus_ground(expr * n, bool & inv, var * & v, expr_ref & t);
bool is_pseudo_head(expr * n, unsigned num_decls, app_ref & head, app_ref & t);
bool is_pseudo_predicate_macro(expr * n, app_ref & head, app_ref & t, expr_ref & def);
@ -137,7 +133,6 @@ public:
void mk_sub(expr * t1, expr * t2, expr_ref & r) const;
void mk_add(expr * t1, expr * t2, expr_ref & r) const;
void mk_add(unsigned num_args, expr * const * args, sort * s, expr_ref & r) const;
poly_simplifier_plugin * get_poly_simp_for(sort * s) const;
};
#endif

View file

@ -22,10 +22,10 @@ Revision History:
#include "util/uint_set.h"
#include "ast/rewriter/var_subst.h"
quasi_macros::quasi_macros(ast_manager & m, macro_manager & mm, simplifier & s) :
m_manager(m),
quasi_macros::quasi_macros(ast_manager & m, macro_manager & mm) :
m_manager(m),
m_macro_manager(mm),
m_simplifier(s),
m_rewriter(m),
m_new_vars(m),
m_new_eqs(m),
m_new_qsorts(m) {
@ -299,8 +299,8 @@ void quasi_macros::apply_macros(unsigned n, expr * const * exprs, proof * const
proof_ref pr(m_manager), ps(m_manager);
proof * p = m_manager.proofs_enabled() ? prs[i] : 0;
m_macro_manager.expand_macros(exprs[i], p, r, pr);
m_simplifier(r, rs, ps);
new_exprs.push_back(rs);
m_rewriter(r);
new_exprs.push_back(r);
new_prs.push_back(ps);
}
}

View file

@ -21,8 +21,7 @@ Revision History:
#include<sstream>
#include "ast/macros/macro_manager.h"
#include "ast/simplifier/basic_simplifier_plugin.h"
#include "ast/simplifier/simplifier.h"
#include "ast/rewriter/th_rewriter.h"
/**
\brief Finds quasi macros and applies them.
@ -32,7 +31,7 @@ class quasi_macros {
ast_manager & m_manager;
macro_manager & m_macro_manager;
simplifier & m_simplifier;
th_rewriter m_rewriter;
occurrences_map m_occurrences;
ptr_vector<expr> m_todo;
@ -57,7 +56,7 @@ class quasi_macros {
void apply_macros(unsigned n, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs);
public:
quasi_macros(ast_manager & m, macro_manager & mm, simplifier & s);
quasi_macros(ast_manager & m, macro_manager & mm);
~quasi_macros();
/**

View file

@ -35,7 +35,6 @@ protected:
bool is_numeral(expr * n) const { return m_util.is_numeral(n); }
bool is_numeral(expr * n, numeral & r) const { return m_util.is_numeral(n, r); }
bool is_zero(expr * n) const { return m_util.is_zero(n); }
bool is_minus_one(expr * n) const { return m_util.is_minus_one(n); }
void normalize(numeral & c, sort * s) {}
app * mk_numeral(numeral const & r, sort * s) { return m_util.mk_numeral(r, s); }
@ -45,6 +44,7 @@ protected:
decl_kind power_decl_kind() const { return OP_POWER; }
public:
arith_rewriter_core(ast_manager & m):m_util(m) {}
bool is_zero(expr * n) const { return m_util.is_zero(n); }
};
class arith_rewriter : public poly_rewriter<arith_rewriter_core> {

View file

@ -39,7 +39,6 @@ protected:
bool is_numeral(expr * n) const { return Config::is_numeral(n); }
bool is_numeral(expr * n, numeral & r) const { return Config::is_numeral(n, r); }
bool is_zero(expr * n) const { return Config::is_zero(n); }
bool is_minus_one(expr * n) const { return Config::is_minus_one(n); }
void normalize(numeral & c) { Config::normalize(c, m_curr_sort); }
app * mk_numeral(numeral const & r) { return Config::mk_numeral(r, m_curr_sort); }
@ -111,6 +110,9 @@ public:
bool is_mul(expr * n) const { return is_app_of(n, get_fid(), mul_decl_kind()); }
bool is_add(func_decl * f) const { return is_decl_of(f, get_fid(), add_decl_kind()); }
bool is_mul(func_decl * f) const { return is_decl_of(f, get_fid(), mul_decl_kind()); }
bool is_times_minus_one(expr * n, expr*& r) const;
bool is_var_plus_ground(expr * n, bool & inv, var * & v, expr_ref & t);
br_status mk_mul_core(unsigned num_args, expr * const * args, expr_ref & result) {
SASSERT(num_args > 0);

View file

@ -931,3 +931,63 @@ expr* poly_rewriter<Config>::merge_muls(expr* x, expr* y) {
m1[k] = mk_add_app(2, args);
return mk_mul_app(k+1, m1.c_ptr());
}
template<typename Config>
bool poly_rewriter<Config>::is_times_minus_one(expr * n, expr* & r) const {
if (is_mul(n) && to_app(n)->get_num_args() == 2 && is_minus_one(to_app(n)->get_arg(0))) {
r = to_app(n)->get_arg(1);
return true;
}
return false;
}
/**
\brief Return true if n is can be put into the form (+ v t) or (+ (- v) t)
\c inv = true will contain true if (- v) is found, and false otherwise.
*/
template<typename Config>
bool poly_rewriter<Config>::is_var_plus_ground(expr * n, bool & inv, var * & v, expr_ref & t) {
if (!is_add(n) || is_ground(n))
return false;
ptr_buffer<expr> args;
v = 0;
expr * curr = to_app(n);
bool stop = false;
inv = false;
while (!stop) {
expr * arg;
expr * neg_arg;
if (is_add(curr)) {
arg = to_app(curr)->get_arg(0);
curr = to_app(curr)->get_arg(1);
}
else {
arg = curr;
stop = true;
}
if (is_ground(arg)) {
TRACE("model_checker_bug", tout << "pushing:\n" << mk_pp(arg, m()) << "\n";);
args.push_back(arg);
}
else if (is_var(arg)) {
if (v != 0)
return false; // already found variable
v = to_var(arg);
}
else if (is_times_minus_one(arg, neg_arg) && is_var(neg_arg)) {
if (v != 0)
return false; // already found variable
v = to_var(neg_arg);
inv = true;
}
else {
return false; // non ground term.
}
}
if (v == 0)
return false; // did not find variable
SASSERT(!args.empty());
mk_add(args.size(), args.c_ptr(), t);
return true;
}