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

merged with unstable

This commit is contained in:
Ken McMillan 2013-10-18 17:26:41 -07:00
commit 3a0947b3ba
413 changed files with 31618 additions and 17204 deletions

View file

@ -869,11 +869,7 @@ struct aig_manager::imp {
void mk_ite(aig * n) {
aig_lit c, t, e;
#ifdef Z3DEBUG
bool ok =
#endif
m.is_ite(n, c, t, e);
SASSERT(ok);
VERIFY(m.is_ite(n, c, t, e));
if (c.is_inverted()) {
c.invert();
std::swap(t, e);

View file

@ -70,7 +70,6 @@ public:
void max_sharing(aig_ref & r);
void to_formula(aig_ref const & r, expr_ref & result);
void to_formula(aig_ref const & r, goal & result);
void to_cnf(aig_ref const & r, goal & result);
void display(std::ostream & out, aig_ref const & r) const;
void display_smt2(std::ostream & out, aig_ref const & r) const;
unsigned get_num_aigs() const;

View file

@ -0,0 +1,160 @@
#include"arith_bounds_tactic.h"
#include"arith_decl_plugin.h"
struct arith_bounds_tactic : public tactic {
ast_manager& m;
arith_util a;
volatile bool m_cancel;
arith_bounds_tactic(ast_manager& m):
m(m),
a(m),
m_cancel(false)
{
}
ast_manager& get_manager() { return m; }
void set_cancel(bool f) {
m_cancel = f;
}
virtual void cleanup() {
m_cancel = false;
}
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) {
bounds_arith_subsumption(in, result);
}
virtual tactic* translate(ast_manager& m) {
return alloc(arith_bounds_tactic, m);
}
void checkpoint() {
if (m_cancel) {
throw tactic_exception(TACTIC_CANCELED_MSG);
}
}
struct info { rational r; unsigned idx; bool is_strict;};
/**
\brief Basic arithmetic subsumption simplification based on bounds.
*/
void mk_proof(proof_ref& pr, goal_ref const& s, unsigned i, unsigned j) {
if (s->proofs_enabled()) {
proof* th_lemma = m.mk_th_lemma(a.get_family_id(), m.mk_implies(s->form(i), s->form(j)), 0, 0);
pr = m.mk_modus_ponens(s->pr(i), th_lemma);
}
}
bool is_le_or_lt(expr* e, expr*& e1, expr*& e2, bool& is_strict) {
bool is_negated = m.is_not(e, e);
if ((!is_negated && (a.is_le(e, e1, e2) || a.is_ge(e, e2, e1))) ||
(is_negated && (a.is_lt(e, e2, e1) || a.is_gt(e, e1, e2)))) {
is_strict = false;
return true;
}
if ((!is_negated && (a.is_lt(e, e1, e2) || a.is_gt(e, e2, e1))) ||
(is_negated && (a.is_le(e, e2, e1) || a.is_ge(e, e1, e2)))) {
is_strict = true;
return true;
}
return false;
}
void bounds_arith_subsumption(goal_ref const& g, goal_ref_buffer& result) {
info inf;
rational r;
goal_ref s(g); // initialize result.
obj_map<expr, info> lower, upper;
expr* e1, *e2;
TRACE("arith_subsumption", s->display(tout); );
for (unsigned i = 0; i < s->size(); ++i) {
checkpoint();
expr* lemma = s->form(i);
bool is_strict = false;
bool is_lower = false;
if (!is_le_or_lt(lemma, e1, e2, is_strict)) {
continue;
}
// e1 <= e2 or e1 < e2
if (a.is_numeral(e2, r)) {
is_lower = true;
}
else if (a.is_numeral(e1, r)) {
is_lower = false;
}
else {
continue;
}
proof_ref new_pr(m);
if (is_lower && upper.find(e1, inf)) {
if (inf.r > r || (inf.r == r && is_strict && !inf.is_strict)) {
mk_proof(new_pr, s, i, inf.idx);
s->update(inf.idx, m.mk_true(), new_pr);
inf.r = r;
inf.is_strict = is_strict;
inf.idx = i;
upper.insert(e1, inf);
}
else {
mk_proof(new_pr, s, inf.idx, i);
s->update(i, m.mk_true(), new_pr);
}
}
else if (is_lower) {
inf.r = r;
inf.is_strict = is_strict;
inf.idx = i;
upper.insert(e1, inf);
}
else if (!is_lower && lower.find(e2, inf)) {
if (inf.r < r || (inf.r == r && is_strict && !inf.is_strict)) {
mk_proof(new_pr, s, i, inf.idx);
s->update(inf.idx, m.mk_true(), new_pr);
inf.r = r;
inf.is_strict = is_strict;
inf.idx = i;
lower.insert(e2, inf);
}
else {
mk_proof(new_pr, s, inf.idx, i);
s->update(i, m.mk_true());
}
}
else if (!is_lower) {
inf.r = r;
inf.is_strict = is_strict;
inf.idx = i;
lower.insert(e2, inf);
}
}
s->elim_true();
result.push_back(s.get());
TRACE("arith_subsumption", s->display(tout); );
}
};
tactic * mk_arith_bounds_tactic(ast_manager & m, params_ref const & p) {
return alloc(arith_bounds_tactic, m);
}

View file

@ -0,0 +1,37 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
arith_bounds_tactic.h
Abstract:
Fast/rudimentary arithmetic subsumption tactic.
Author:
Nikolaj Bjorner (nbjorner) 2012-9-6
Notes:
Background: The Farkas learner in PDR generates tons
of inequalities that contain redundancies.
It therefore needs a fast way to reduce these redundancies before
passing the results to routines that are more expensive.
The arith subsumption_strategy encapsulates a rudimentary
routine for simplifying inequalities. Additional simplification
routines can be added here or composed with this strategy.
Note: The bound_manager subsumes some of the collection methods used
for assembling bounds, but it does not have a way to check for
subsumption of atoms.
--*/
#ifndef _ARITH_BOUNDS_TACTIC_H_
#define _ARITH_BOUNDS_TACTIC_H_
#include "tactic.h"
tactic * mk_arith_bounds_tactic(ast_manager & m, params_ref const & p = params_ref());
#endif

View file

@ -29,6 +29,7 @@ Revision History:
#include"th_rewriter.h"
#include"filter_model_converter.h"
#include"ast_smt2_pp.h"
#include"expr_replacer.h"
/*
----
@ -131,18 +132,16 @@ struct purify_arith_proc {
proof_ref_vector m_new_cnstr_prs;
expr_ref m_subst;
proof_ref m_subst_pr;
bool m_in_q;
unsigned m_var_idx;
expr_ref_vector m_new_vars;
rw_cfg(purify_arith_proc & o, bool in_q):
rw_cfg(purify_arith_proc & o):
m_owner(o),
m_pinned(o.m()),
m_new_cnstrs(o.m()),
m_new_cnstr_prs(o.m()),
m_subst(o.m()),
m_subst_pr(o.m()),
m_in_q(in_q),
m_var_idx(0) {
m_new_vars(o.m()) {
}
ast_manager & m() { return m_owner.m(); }
@ -155,14 +154,9 @@ struct purify_arith_proc {
bool elim_inverses() const { return m_owner.m_elim_inverses; }
expr * mk_fresh_var(bool is_int) {
if (m_in_q) {
unsigned idx = m_var_idx;
m_var_idx++;
return m().mk_var(idx, is_int ? u().mk_int() : u().mk_real());
}
else {
return m().mk_fresh_const(0, is_int ? u().mk_int() : u().mk_real());
}
expr * r = m().mk_fresh_const(0, is_int ? u().mk_int() : u().mk_real());
m_new_vars.push_back(r);
return r;
}
expr * mk_fresh_real_var() { return mk_fresh_var(false); }
@ -596,105 +590,51 @@ struct purify_arith_proc {
struct rw : public rewriter_tpl<rw_cfg> {
rw_cfg m_cfg;
rw(purify_arith_proc & o, bool in_q):
rw(purify_arith_proc & o):
rewriter_tpl<rw_cfg>(o.m(), o.m_produce_proofs, m_cfg),
m_cfg(o, in_q) {
}
};
/**
\brief Return the number of (auxiliary) variables needed for converting an expression.
*/
struct num_vars_proc {
arith_util & m_util;
expr_fast_mark1 m_visited;
ptr_vector<expr> m_todo;
unsigned m_num_vars;
bool m_elim_root_objs;
num_vars_proc(arith_util & u, bool elim_root_objs):
m_util(u),
m_elim_root_objs(elim_root_objs) {
}
void visit(expr * t) {
if (m_visited.is_marked(t))
return;
m_visited.mark(t);
m_todo.push_back(t);
}
void process(app * t) {
if (t->get_family_id() == m_util.get_family_id()) {
if (m_util.is_power(t)) {
rational k;
if (m_util.is_numeral(t->get_arg(1), k) && (k.is_zero() || !k.is_int())) {
m_num_vars++;
}
}
else if (m_util.is_div(t) ||
m_util.is_idiv(t) ||
m_util.is_mod(t) ||
m_util.is_to_int(t) ||
(m_util.is_irrational_algebraic_numeral(t) && m_elim_root_objs)) {
m_num_vars++;
}
}
unsigned num_args = t->get_num_args();
for (unsigned i = 0; i < num_args; i++)
visit(t->get_arg(i));
}
unsigned operator()(expr * t) {
m_num_vars = 0;
visit(t);
while (!m_todo.empty()) {
expr * t = m_todo.back();
m_todo.pop_back();
if (is_app(t))
process(to_app(t));
}
m_visited.reset();
return m_num_vars;
m_cfg(o) {
}
};
void process_quantifier(quantifier * q, expr_ref & result, proof_ref & result_pr) {
result_pr = 0;
num_vars_proc p(u(), m_elim_root_objs);
expr_ref body(m());
unsigned num_vars = p(q->get_expr());
if (num_vars > 0) {
// open space for aux vars
var_shifter shifter(m());
shifter(q->get_expr(), num_vars, body);
}
else {
body = q->get_expr();
}
rw r(*this, true);
rw r(*this);
expr_ref new_body(m());
proof_ref new_body_pr(m());
r(body, new_body, new_body_pr);
r(q->get_expr(), new_body, new_body_pr);
unsigned num_vars = r.cfg().m_new_vars.size();
TRACE("purify_arith",
tout << "num_vars: " << num_vars << "\n";
tout << "body: " << mk_ismt2_pp(body, m()) << "\nnew_body: " << mk_ismt2_pp(new_body, m()) << "\n";);
tout << "body: " << mk_ismt2_pp(q->get_expr(), m()) << "\nnew_body: " << mk_ismt2_pp(new_body, m()) << "\n";);
if (num_vars == 0) {
SASSERT(r.cfg().m_new_cnstrs.empty());
result = m().update_quantifier(q, new_body);
if (m_produce_proofs)
result_pr = m().mk_quant_intro(q, to_quantifier(result.get()), result_pr);
}
else {
// Add new constraints
expr_ref_vector & cnstrs = r.cfg().m_new_cnstrs;
cnstrs.push_back(new_body);
new_body = m().mk_and(cnstrs.size(), cnstrs.c_ptr());
// Open space for new variables
var_shifter shifter(m());
shifter(new_body, num_vars, new_body);
// Rename fresh constants in r.cfg().m_new_vars to variables
ptr_buffer<sort> sorts;
buffer<symbol> names;
expr_substitution subst(m(), false, false);
for (unsigned i = 0; i < num_vars; i++) {
sorts.push_back(u().mk_real());
expr * c = r.cfg().m_new_vars.get(i);
sort * s = get_sort(c);
sorts.push_back(s);
names.push_back(m().mk_fresh_var_name("x"));
unsigned idx = num_vars - i - 1;
subst.insert(c, m().mk_var(idx, s));
}
scoped_ptr<expr_replacer> replacer = mk_default_expr_replacer(m());
replacer->set_substitution(&subst);
(*replacer)(new_body, new_body);
new_body = m().mk_exists(num_vars, sorts.c_ptr(), names.c_ptr(), new_body);
result = m().update_quantifier(q, new_body);
if (m_produce_proofs) {
@ -708,7 +648,7 @@ struct purify_arith_proc {
}
void operator()(goal & g, model_converter_ref & mc, bool produce_models) {
rw r(*this, false);
rw r(*this);
// purify
expr_ref new_curr(m());
proof_ref new_pr(m());

View file

@ -269,7 +269,7 @@ class max_bv_sharing_tactic : public tactic {
m_rw.cfg().cleanup();
g->inc_depth();
result.push_back(g.get());
TRACE("qe", g->display(tout););
TRACE("max_bv_sharing", g->display(tout););
SASSERT(g->is_well_sorted());
}
};

View file

@ -21,7 +21,7 @@ Notes:
#include"goal_num_occurs.h"
#include"cooperate.h"
#include"ast_ll_pp.h"
#include"ast_smt2_pp.h"
#include"ast_pp.h"
struct ctx_simplify_tactic::imp {
struct cached_result {
@ -105,6 +105,7 @@ struct ctx_simplify_tactic::imp {
}
bool shared(expr * t) const {
TRACE("ctx_simplify_tactic_bug", tout << mk_pp(t, m) << "\n";);
return t->get_ref_count() > 1 && m_occs.get_num_occs(t) > 1;
}
@ -242,12 +243,13 @@ struct ctx_simplify_tactic::imp {
}
void assert_expr(expr * t, bool sign) {
expr * p = t;
if (m.is_not(t)) {
t = to_app(t)->get_arg(0);
sign = !sign;
}
bool mk_scope = true;
if (shared(t)) {
if (shared(t) || shared(p)) {
push();
mk_scope = false;
assert_eq_core(t, sign ? m.mk_false() : m.mk_true());
@ -371,6 +373,12 @@ struct ctx_simplify_tactic::imp {
if (!modified) {
r = t;
}
else if (new_new_args.empty()) {
r = OR?m.mk_false():m.mk_true();
}
else if (new_new_args.size() == 1) {
r = new_new_args[0];
}
else {
std::reverse(new_new_args.c_ptr(), new_new_args.c_ptr() + new_new_args.size());
m_mk_app(t->get_decl(), new_new_args.size(), new_new_args.c_ptr(), r);
@ -451,7 +459,7 @@ struct ctx_simplify_tactic::imp {
if (visit.is_marked(s)) {
continue;
}
visit.mark(s, true);
visit.mark(s, true);
++sz;
for (unsigned i = 0; is_app(s) && i < to_app(s)->get_num_args(); ++i) {
todo.push_back(to_app(s)->get_arg(i));

View file

@ -165,7 +165,7 @@ class propagate_values_tactic : public tactic {
m_occs(*m_goal);
while (true) {
TRACE("propagate_values", m_goal->display(tout););
TRACE("propagate_values", tout << "while(true) loop\n"; m_goal->display(tout););
if (forward) {
for (; m_idx < size; m_idx++) {
process_current();
@ -201,14 +201,14 @@ class propagate_values_tactic : public tactic {
if (round >= m_max_rounds)
break;
IF_VERBOSE(100, verbose_stream() << "starting new round, goal size: " << m_goal->num_exprs() << std::endl;);
TRACE("propgate_values", tout << "round finished\n"; m_goal->display(tout); tout << "\n";);
TRACE("propagate_values", tout << "round finished\n"; m_goal->display(tout); tout << "\n";);
}
end:
m_goal->elim_redundancies();
m_goal->inc_depth();
result.push_back(m_goal);
SASSERT(m_goal->is_well_sorted());
TRACE("propagate_values", m_goal->display(tout););
TRACE("propagate_values", tout << "end\n"; m_goal->display(tout););
TRACE("propagate_values_core", m_goal->display_with_dependencies(tout););
m_goal = 0;
}

View file

@ -0,0 +1,35 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
equiv_proof_converter.cpp
Abstract:
Proof converter that applies equivalence rule to leaves.
Author:
Nikolaj Bjorner (nbjorner) 2012-11-23
Revision History:
--*/
#include "equiv_proof_converter.h"
#include "ast_pp.h"
#include "scoped_proof.h"
void equiv_proof_converter::insert(expr* fml1, expr* fml2) {
if (fml1 != fml2) {
scoped_proof _sp(m);
proof_ref p1(m), p2(m), p3(m);
p1 = m.mk_asserted(fml1);
p2 = m.mk_rewrite(fml1, fml2);
p3 = m.mk_modus_ponens(p1, p2);
TRACE("proof_converter", tout << mk_pp(p3.get(), m) << "\n";);
SASSERT(m.has_fact(p3));
m_replace.insert(p3);
}
}

View file

@ -0,0 +1,52 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
equiv_proof_converter.h
Abstract:
Proof converter that applies equivalence rule to leaves.
Given a proof P with occurrences of [asserted fml]
replace [asserted fml] by a proof of the form
[mp [asserted fml'] [~ fml fml']]
Author:
Nikolaj Bjorner (nbjorner) 2012-11-23
Revision History:
--*/
#ifndef _EQUIV_PROOF_CONVERTER_H_
#define _EQUIV_PROOF_CONVERTER_H_
#include "replace_proof_converter.h"
class equiv_proof_converter : public proof_converter {
ast_manager& m;
replace_proof_converter m_replace;
public:
equiv_proof_converter(ast_manager& m): m(m), m_replace(m) {}
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);
}
virtual proof_converter * translate(ast_translation & translator) {
return m_replace.translate(translator);
}
void insert(expr* fml1, expr* fml2);
ast_manager& get_manager() { return m; }
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -31,23 +31,39 @@ typedef enum { BV_RM_TIES_TO_AWAY=0, BV_RM_TIES_TO_EVEN=1, BV_RM_TO_NEGATIVE=2,
class fpa2bv_model_converter;
struct func_decl_triple {
func_decl_triple () { f_sgn = 0; f_sig = 0; f_exp = 0; }
func_decl_triple (func_decl * sgn, func_decl * sig, func_decl * exp)
{
f_sgn = sgn;
f_sig = sig;
f_exp = exp;
}
func_decl * f_sgn;
func_decl * f_sig;
func_decl * f_exp;
};
class fpa2bv_converter {
ast_manager & m;
basic_simplifier_plugin m_simp;
float_util m_util;
mpf_manager & m_mpf_manager;
mpf_manager & m_mpf_manager;
unsynch_mpz_manager & m_mpz_manager;
bv_util m_bv_util;
float_decl_plugin * m_plugin;
obj_map<func_decl, expr*> m_const2bv;
obj_map<func_decl, expr*> m_rm_const2bv;
obj_map<func_decl, func_decl*> m_uf2bvuf;
obj_map<func_decl, func_decl_triple> m_uf23bvuf;
public:
fpa2bv_converter(ast_manager & m);
~fpa2bv_converter();
float_util & fu() { return m_util; }
bv_util & bu() { return m_bv_util; }
bool is_float(sort * s) { return m_util.is_float(s); }
bool is_float(expr * e) { return is_app(e) && m_util.is_float(to_app(e)->get_decl()->get_range()); }
@ -66,8 +82,10 @@ public:
void mk_rounding_mode(func_decl * f, expr_ref & result);
void mk_value(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_const(func_decl * f, expr_ref & result);
void mk_const(func_decl * f, expr_ref & result);
void mk_rm_const(func_decl * f, expr_ref & result);
void mk_uninterpreted_function(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_var(unsigned base_inx, sort * srt, expr_ref & result);
void mk_plus_inf(func_decl * f, expr_ref & result);
void mk_minus_inf(func_decl * f, expr_ref & result);
@ -98,12 +116,18 @@ public:
void mk_is_nzero(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_is_pzero(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_is_sign_minus(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_is_nan(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_is_inf(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_is_normal(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_is_subnormal(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_to_float(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_to_ieee_bv(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
void mk_to_ieee_bv(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
obj_map<func_decl, expr*> const & const2bv() const { return m_const2bv; }
obj_map<func_decl, expr*> const & rm_const2bv() const { return m_rm_const2bv; }
obj_map<func_decl, func_decl*> const & uf2bvuf() const { return m_uf2bvuf; }
obj_map<func_decl, func_decl_triple> const & uf23bvuf() const { return m_uf23bvuf; }
void dbg_decouple(const char * prefix, expr_ref & e);
expr_ref_vector extra_assertions;
@ -135,7 +159,7 @@ protected:
void mk_bias(expr * e, expr_ref & result);
void mk_unbias(expr * e, expr_ref & result);
void unpack(expr * e, expr_ref & sgn, expr_ref & sig, expr_ref & exp, bool normalize);
void unpack(expr * e, expr_ref & sgn, expr_ref & sig, expr_ref & exp, expr_ref & lz, bool normalize);
void round(sort * s, expr_ref & rm, expr_ref & sgn, expr_ref & sig, expr_ref & exp, expr_ref & result);
void add_core(unsigned sbits, unsigned ebits, expr_ref & rm,
@ -148,10 +172,14 @@ class fpa2bv_model_converter : public model_converter {
ast_manager & m;
obj_map<func_decl, expr*> m_const2bv;
obj_map<func_decl, expr*> m_rm_const2bv;
obj_map<func_decl, func_decl*> m_uf2bvuf;
obj_map<func_decl, func_decl_triple> m_uf23bvuf;
public:
fpa2bv_model_converter(ast_manager & m, obj_map<func_decl, expr*> const & const2bv,
obj_map<func_decl, expr*> const & rm_const2bv) :
obj_map<func_decl, expr*> const & rm_const2bv,
obj_map<func_decl, func_decl*> const & uf2bvuf,
obj_map<func_decl, func_decl_triple> const & uf23bvuf) :
m(m) {
// Just create a copy?
for (obj_map<func_decl, expr*>::iterator it = const2bv.begin();
@ -170,6 +198,21 @@ public:
m.inc_ref(it->m_key);
m.inc_ref(it->m_value);
}
for (obj_map<func_decl, func_decl*>::iterator it = uf2bvuf.begin();
it != uf2bvuf.end();
it++)
{
m_uf2bvuf.insert(it->m_key, it->m_value);
m.inc_ref(it->m_key);
m.inc_ref(it->m_value);
}
for (obj_map<func_decl, func_decl_triple>::iterator it = uf23bvuf.begin();
it != uf23bvuf.end();
it++)
{
m_uf23bvuf.insert(it->m_key, it->m_value);
m.inc_ref(it->m_key);
}
}
virtual ~fpa2bv_model_converter() {
@ -202,6 +245,8 @@ protected:
model_converter * mk_fpa2bv_model_converter(ast_manager & m,
obj_map<func_decl, expr*> const & const2bv,
obj_map<func_decl, expr*> const & rm_const2bv);
obj_map<func_decl, expr*> const & rm_const2bv,
obj_map<func_decl, func_decl*> const & uf2bvuf,
obj_map<func_decl, func_decl_triple> const & uf23bvuf);
#endif

View file

@ -29,6 +29,7 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg {
ast_manager & m_manager;
expr_ref_vector m_out;
fpa2bv_converter & m_conv;
sort_ref_vector m_bindings;
unsigned long long m_max_memory;
unsigned m_max_steps;
@ -38,7 +39,8 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg {
fpa2bv_rewriter_cfg(ast_manager & m, fpa2bv_converter & c, params_ref const & p):
m_manager(m),
m_out(m),
m_conv(c) {
m_conv(c),
m_bindings(m) {
updt_params(p);
// We need to make sure that the mananger has the BV plugin loaded.
symbol s_bv("bv");
@ -53,6 +55,9 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg {
m_out.finalize();
}
void reset() {
}
void updt_params(params_ref const & p) {
m_max_memory = megabytes_to_bytes(p.get_uint("max_memory", UINT_MAX));
m_max_steps = p.get_uint("max_steps", UINT_MAX);
@ -127,6 +132,10 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg {
case OP_FLOAT_IS_ZERO: m_conv.mk_is_zero(f, num, args, result); return BR_DONE;
case OP_FLOAT_IS_NZERO: m_conv.mk_is_nzero(f, num, args, result); return BR_DONE;
case OP_FLOAT_IS_PZERO: m_conv.mk_is_pzero(f, num, args, result); return BR_DONE;
case OP_FLOAT_IS_NAN: m_conv.mk_is_nan(f, num, args, result); return BR_DONE;
case OP_FLOAT_IS_INF: m_conv.mk_is_inf(f, num, args, result); return BR_DONE;
case OP_FLOAT_IS_NORMAL: m_conv.mk_is_normal(f, num, args, result); return BR_DONE;
case OP_FLOAT_IS_SUBNORMAL: m_conv.mk_is_subnormal(f, num, args, result); return BR_DONE;
case OP_FLOAT_IS_SIGN_MINUS: m_conv.mk_is_sign_minus(f, num, args, result); return BR_DONE;
case OP_TO_FLOAT: m_conv.mk_to_float(f, num, args, result); return BR_DONE;
case OP_TO_IEEE_BV: m_conv.mk_to_ieee_bv(f, num, args, result); return BR_DONE;
@ -136,21 +145,109 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg {
throw tactic_exception("NYI");
}
}
if (f->get_family_id() == null_family_id)
{
bool is_float_uf = m_conv.is_float(f->get_range());
unsigned i = 0;
while (!is_float_uf && i < num)
{
is_float_uf = m_conv.is_float(f->get_domain()[i]);
i++;
}
if (is_float_uf)
{
m_conv.mk_uninterpreted_function(f, num, args, result);
return BR_DONE;
}
}
return BR_FAILED;
}
bool pre_visit(expr * t)
{
TRACE("fpa2bv", tout << "pre_visit: " << mk_ismt2_pp(t, m()) << std::endl;);
if (is_quantifier(t)) {
quantifier * q = to_quantifier(t);
TRACE("fpa2bv", tout << "pre_visit quantifier [" << q->get_id() << "]: " << mk_ismt2_pp(q->get_expr(), m()) << std::endl;);
sort_ref_vector new_bindings(m_manager);
for (unsigned i = 0 ; i < q->get_num_decls(); i++)
new_bindings.push_back(q->get_decl_sort(i));
SASSERT(new_bindings.size() == q->get_num_decls());
m_bindings.append(new_bindings);
}
return true;
}
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) {
return false;
unsigned curr_sz = m_bindings.size();
SASSERT(old_q->get_num_decls() <= curr_sz);
unsigned num_decls = old_q->get_num_decls();
unsigned old_sz = curr_sz - num_decls;
string_buffer<> name_buffer;
ptr_buffer<sort> new_decl_sorts;
sbuffer<symbol> new_decl_names;
for (unsigned i = 0; i < num_decls; i++) {
symbol const & n = old_q->get_decl_name(i);
sort * s = old_q->get_decl_sort(i);
if (m_conv.is_float(s)) {
unsigned ebits = m_conv.fu().get_ebits(s);
unsigned sbits = m_conv.fu().get_sbits(s);
name_buffer.reset();
name_buffer << n << ".bv";
new_decl_names.push_back(symbol(name_buffer.c_str()));
new_decl_sorts.push_back(m_conv.bu().mk_sort(sbits+ebits));
}
else {
new_decl_sorts.push_back(s);
new_decl_names.push_back(n);
}
}
result = m().mk_quantifier(old_q->is_forall(), new_decl_sorts.size(), new_decl_sorts.c_ptr(), new_decl_names.c_ptr(),
new_body, old_q->get_weight(), old_q->get_qid(), old_q->get_skid(),
old_q->get_num_patterns(), new_patterns, old_q->get_num_no_patterns(), new_no_patterns);
result_pr = 0;
m_bindings.shrink(old_sz);
TRACE("fpa2bv", tout << "reduce_quantifier[" << old_q->get_depth() << "]: " <<
mk_ismt2_pp(old_q->get_expr(), m()) << std::endl <<
" new body: " << mk_ismt2_pp(new_body, m()) << std::endl;
tout << "result = " << mk_ismt2_pp(result, m()) << std::endl;);
return true;
}
bool reduce_var(var * t, expr_ref & result, proof_ref & result_pr) {
return false;
if (t->get_idx() >= m_bindings.size())
return false;
// unsigned inx = m_bindings.size() - t->get_idx() - 1;
expr_ref new_exp(m());
sort * s = t->get_sort();
if (m_conv.is_float(s))
{
expr_ref new_var(m());
unsigned ebits = m_conv.fu().get_ebits(s);
unsigned sbits = m_conv.fu().get_sbits(s);
new_var = m().mk_var(t->get_idx(), m_conv.bu().mk_sort(sbits+ebits));
m_conv.mk_triple(m_conv.bu().mk_extract(sbits+ebits-1, sbits+ebits-1, new_var),
m_conv.bu().mk_extract(sbits+ebits-2, ebits, new_var),
m_conv.bu().mk_extract(ebits-1, 0, new_var),
new_exp);
}
else
new_exp = m().mk_var(t->get_idx(), s);
result = new_exp;
result_pr = 0;
TRACE("fpa2bv", tout << "reduce_var: " << mk_ismt2_pp(t, m()) << " -> " << mk_ismt2_pp(result, m()) << std::endl;);
return true;
}
};

View file

@ -90,7 +90,7 @@ class fpa2bv_tactic : public tactic {
}
if (g->models_enabled())
mc = mk_fpa2bv_model_converter(m, m_conv.const2bv(), m_conv.rm_const2bv());
mc = mk_fpa2bv_model_converter(m, m_conv.const2bv(), m_conv.rm_const2bv(), m_conv.uf2bvuf(), m_conv.uf23bvuf());
g->inc_depth();
result.push_back(g.get());

View file

@ -0,0 +1,233 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
horn_subsume_model_converter.cpp
Abstract:
Model converter for redundant Horn clauses.
Author:
Nikolaj Bjorner (nbjorner) 2012-9-16
Revision History:
--*/
#include "horn_subsume_model_converter.h"
#include "var_subst.h"
#include "ast_pp.h"
#include "model_smt2_pp.h"
#include "bool_rewriter.h"
#include "th_rewriter.h"
#include "for_each_expr.h"
#include "well_sorted.h"
void horn_subsume_model_converter::insert(app* head, expr* body) {
m_delay_head.push_back(head);
m_delay_body.push_back(body);
}
void horn_subsume_model_converter::insert(app* head, unsigned sz, expr* const* body) {
expr_ref b(m);
bool_rewriter(m).mk_and(sz, body, b);
insert(head, b.get());
}
bool horn_subsume_model_converter::mk_horn(
app* head, expr* body, func_decl_ref& pred, expr_ref& body_res) {
expr_ref_vector conjs(m), subst(m);
ptr_vector<sort> sorts, sorts2;
var_subst vs(m, false);
if (!is_uninterp(head)) {
return false;
}
pred = head->get_decl();
unsigned arity = head->get_num_args();
get_free_vars(head, sorts);
get_free_vars(body, sorts);
if (arity == 0 && sorts.empty()) {
body_res = body;
return true;
}
svector<symbol> names;
for (unsigned i = 0; i < sorts.size(); ++i) {
if (!sorts[i]) {
sorts[i] = m.mk_bool_sort();
}
names.push_back(symbol(i));
}
names.reverse();
sorts.reverse();
conjs.push_back(body);
for (unsigned i = 0; i < arity; ++i) {
expr* arg = head->get_arg(i);
var_ref v(m);
v = m.mk_var(sorts.size()+i, m.get_sort(arg));
if (is_var(arg)) {
unsigned w = to_var(arg)->get_idx();
if (w >= subst.size()) {
subst.resize(w+1);
}
if (subst[w].get()) {
conjs.push_back(m.mk_eq(v, subst[w].get()));
}
else {
subst[w] = v;
}
}
else {
conjs.push_back(m.mk_eq(v, arg));
}
}
expr_ref body_expr(m);
body_expr = m.mk_and(conjs.size(), conjs.c_ptr());
// substitute variables directly.
if (!subst.empty()) {
expr_ref tmp(body_expr);
vs(tmp, subst.size(), subst.c_ptr(), body_expr);
}
if (sorts.empty()) {
SASSERT(subst.empty());
body_res = body_expr;
}
else {
body_res = m.mk_exists(sorts.size(), sorts.c_ptr(), names.c_ptr(), body_expr.get());
m_rewrite(body_res);
}
TRACE("mc",
tout << mk_pp(head, m) << " :- " << mk_pp(body, m) << "\n";
tout << pred->get_name() << " :- " << mk_pp(body_res.get(), m) << "\n";);
return true;
}
bool horn_subsume_model_converter::mk_horn(
expr* clause, func_decl_ref& pred, expr_ref& body) {
ptr_vector<sort> sorts;
// formula is closed.
DEBUG_CODE(get_free_vars(clause, sorts); SASSERT(sorts.empty()););
while (is_quantifier(clause) && to_quantifier(clause)->is_forall()) {
quantifier* q = to_quantifier(clause);
clause = q->get_expr();
}
expr* e1, *e2;
if (m.is_implies(clause, e1, e2)) {
if (!is_uninterp(e2)) {
return false;
}
return mk_horn(to_app(e2), e1, pred, body);
}
else if (m.is_or(clause)) {
// todo?
return false;
}
else {
return false;
}
}
void horn_subsume_model_converter::add_default_proc::operator()(app* n) {
//
// predicates that have not been assigned values
// in the Horn model are assumed false.
//
if (m.is_bool(n) &&
!m_md->has_interpretation(n->get_decl()) &&
(n->get_family_id() == null_family_id)) {
TRACE("mc", tout << "adding: " << n->get_decl()->get_name() << "\n";);
if (n->get_decl()->get_arity() == 0) {
m_md->register_decl(n->get_decl(), m.mk_false());
}
else {
func_interp* fi = alloc(func_interp, m, n->get_decl()->get_arity());
fi->set_else(m.mk_false());
m_md->register_decl(n->get_decl(), fi);
}
}
}
void horn_subsume_model_converter::add_default_false_interpretation(expr* e, model_ref& md) {
add_default_proc proc(m, md);
for_each_expr(proc, e);
}
void horn_subsume_model_converter::operator()(model_ref& mr) {
func_decl_ref pred(m);
expr_ref body_res(m);
for (unsigned i = 0; i < m_delay_head.size(); ++i) {
VERIFY(mk_horn(m_delay_head[i].get(), m_delay_body[i].get(), pred, body_res));
insert(pred.get(), body_res.get());
}
m_delay_head.reset();
m_delay_body.reset();
TRACE("mc", tout << m_funcs.size() << "\n"; model_smt2_pp(tout, m, *mr, 0););
for (unsigned i = m_funcs.size(); i > 0; ) {
--i;
func_decl* h = m_funcs[i].get();
expr_ref body(m_bodies[i].get(), m);
unsigned arity = h->get_arity();
add_default_false_interpretation(body, mr);
SASSERT(m.is_bool(body));
TRACE("mc", tout << "eval: " << h->get_name() << "\n" << mk_pp(body, m) << "\n";);
expr_ref tmp(body);
mr->eval(tmp, body);
TRACE("mc", tout << "to:\n" << mk_pp(body, m) << "\n";);
if (arity == 0) {
expr* e = mr->get_const_interp(h);
if (e) {
body = m.mk_or(e, body);
}
m_rewrite(body);
mr->register_decl(h, body);
}
else {
func_interp* f = mr->get_func_interp(h);
if (f) {
expr* e = f->get_else();
body = m.mk_or(e, body);
}
else {
f = alloc(func_interp, m, arity);
mr->register_decl(h, f);
}
m_rewrite(body);
f->set_else(body);
}
}
}
model_converter* horn_subsume_model_converter::translate(ast_translation & translator) {
horn_subsume_model_converter* mc = alloc(horn_subsume_model_converter, translator.to());
for (unsigned i = 0; i < m_funcs.size(); ++i) {
mc->insert(translator(m_funcs[i].get()), translator(m_bodies[i].get()));
}
return mc;
}

View file

@ -0,0 +1,83 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
horn_subsume_model_converter.h
Abstract:
Model converter for redundant Horn clauses.
Author:
Nikolaj Bjorner (nbjorner) 2012-9-16
Revision History:
Notes:
Subsumption transformation (remove Horn clause):
P(x) :- Body(x,y) Rules
----------------------------
Rules
Model converter:
P(x) := P(x) or (exists y. Body(x,y))
--*/
#ifndef _HORN_SUBSUME_MODEL_CONVERTER_H_
#define _HORN_SUBSUME_MODEL_CONVERTER_H_
#include "model_converter.h"
#include "th_rewriter.h"
class horn_subsume_model_converter : public model_converter {
ast_manager& m;
func_decl_ref_vector m_funcs;
expr_ref_vector m_bodies;
th_rewriter m_rewrite;
app_ref_vector m_delay_head;
expr_ref_vector m_delay_body;
void add_default_false_interpretation(expr* e, model_ref& md);
struct add_default_proc {
ast_manager& m;
model_ref& m_md;
add_default_proc(ast_manager& m, model_ref& md): m(m), m_md(md) {}
void operator()(app* n);
void operator()(expr* n) {}
};
public:
horn_subsume_model_converter(ast_manager& m):
m(m), m_funcs(m), m_bodies(m), m_rewrite(m),
m_delay_head(m), m_delay_body(m) {}
bool mk_horn(expr* clause, func_decl_ref& pred, expr_ref& body);
bool mk_horn(app* head, expr* body, func_decl_ref& pred, expr_ref& body_res);
void insert(app* head, expr* body);
void insert(app* head, unsigned sz, expr* const* body);
void insert(func_decl* p, expr* body) { m_funcs.push_back(p); m_bodies.push_back(body); }
virtual void operator()(model_ref& m);
virtual model_converter * translate(ast_translation & translator);
ast_manager& get_manager() { return m; }
};
#endif

View file

@ -94,7 +94,6 @@ public:
smt_strategic_solver_factory(symbol const & logic):m_logic(logic) {}
virtual ~smt_strategic_solver_factory() {}
virtual solver * operator()(ast_manager & m, params_ref const & p, bool proofs_enabled, bool models_enabled, bool unsat_core_enabled, symbol const & logic) {
symbol l;
if (m_logic != symbol::null)

View file

@ -0,0 +1,86 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
replace_proof_converter.cpp
Abstract:
Proof converter that replaces asserted by sub-proof.
Author:
Nikolaj Bjorner (nbjorner) 2012-9-16
Revision History:
--*/
#include "replace_proof_converter.h"
#include "expr_functors.h"
#include "ast_pp.h"
#include "for_each_expr.h"
/**
\brief Replace expressions by other expressions.
replace_map is caching, so inserting src |-> dst has no effect if
src is a sub-expression of something that has already been visited.
The assumption is that proof replacements are inserted into
the replace_proof_converter in the order that they are introduced, so
there are no such clashes.
map_proc is used as expr_replacer behaves differently
when proof mode is turned on.
*/
class replace_map : public map_proc {
public:
replace_map(ast_manager& m): map_proc(m) {}
void insert(expr* src, expr* dst) {
m_map.insert(src, dst, 0);
}
void operator()(var* v) { visit(v); }
void operator()(app* a) { if (!get_expr(a)) { reconstruct(a); } }
void operator()(quantifier* q) { visit(q); }
void apply(expr_ref& e) {
for_each_expr(*this, e);
e = get_expr(e);
}
};
void replace_proof_converter::operator()(ast_manager & m, unsigned num_source,
proof * const * source, proof_ref & result) {
SASSERT(num_source == 1);
replace_map replace(m);
proof_ref p(m);
expr_ref tmp(source[0], m), e(m), f(m);
// apply the substitution to the prefix before inserting it.
for (unsigned i = 0; i < m_proofs.size(); ++i) {
p = m_proofs[i].get();
e = p;
replace.apply(e);
f = m.mk_asserted(m.get_fact(p));
replace.insert(f, e);
TRACE("proof_converter", tout << f->get_id() << " " << mk_pp(f, m) <<
"\n|-> " << mk_pp(e, m) << "\n";);
}
replace.apply(tmp);
TRACE("proof_converter", tout << mk_pp(source[0], m) << "\n";
tout << mk_pp(tmp.get(), m) << "\n";);
result = to_app(tmp);
}
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()));
}
return rp;
}

View file

@ -0,0 +1,50 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
replace_proof_converter.h
Abstract:
Proof converter to replace asserted leaves by proofs.
Given a proof P with occurrences of [asserted fml]
Replace [asserted fml] by proofs whose conclusions are fml.
Author:
Nikolaj Bjorner (nbjorner) 2012-9-16
Revision History:
--*/
#ifndef _REPLACE_PROOF_CONVERTER_H_
#define _REPLACE_PROOF_CONVERTER_H_
#include "proof_converter.h"
class replace_proof_converter : public proof_converter {
ast_manager& m;
proof_ref_vector m_proofs;
public:
replace_proof_converter(ast_manager& m): m(m), m_proofs(m) {}
virtual ~replace_proof_converter() {}
virtual void operator()(ast_manager & m, unsigned num_source, proof * const * source, proof_ref & result);
virtual proof_converter * translate(ast_translation & translator);
void insert(proof* p) { m_proofs.push_back(p); }
ast_manager& get_manager() { return m; }
// run the replacements the inverse direction.
void invert() { m_proofs.reverse(); }
};
#endif

View file

@ -1370,7 +1370,7 @@ class sls_tactic : public tactic {
void updt_params(params_ref const & p) {
m_produce_models = p.get_bool("produce_models", false);
m_max_restarts = p.get_uint("sls_restarts", -1);
m_max_restarts = p.get_uint("sls_restarts", (unsigned)-1);
m_tracker.set_random_seed(p.get_uint("random_seed", 0));
m_plateau_limit = p.get_uint("plateau_limit", 100);
}
@ -1612,7 +1612,7 @@ class sls_tactic : public tactic {
lbool search(goal_ref const & g) {
lbool res = l_undef;
double score = 0.0, old_score = 0.0;
unsigned new_const = -1, new_bit = 0;
unsigned new_const = (unsigned)-1, new_bit = 0;
mpz new_value;
move_type move;
@ -1631,7 +1631,7 @@ class sls_tactic : public tactic {
checkpoint();
old_score = score;
new_const = -1;
new_const = (unsigned)-1;
ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g);

View file

@ -22,6 +22,7 @@ Revision History:
#include"solve_eqs_tactic.h"
#include"elim_uncnstr_tactic.h"
#include"qe_tactic.h"
#include"qe_sat_tactic.h"
#include"ctx_simplify_tactic.h"
#include"smt_tactic.h"
@ -98,8 +99,11 @@ tactic * mk_aufnira_tactic(ast_manager & m, params_ref const & p) {
tactic * mk_lra_tactic(ast_manager & m, params_ref const & p) {
tactic * st = and_then(mk_quant_preprocessor(m),
mk_qe_tactic(m),
mk_smt_tactic());
or_else(try_for(mk_smt_tactic(), 100),
try_for(qe::mk_sat_tactic(m), 1000),
try_for(mk_smt_tactic(), 1000),
and_then(mk_qe_tactic(m), mk_smt_tactic())));
st->updt_params(p);
return st;
}

View file

@ -67,7 +67,7 @@ class quasi_macros_tactic : public tactic {
simp.register_plugin(bvsimp);
macro_manager mm(m_manager, simp);
quasi_macros qm(m_manager, mm, *bsimp, simp);
quasi_macros qm(m_manager, mm, simp);
bool more = true;
expr_ref_vector forms(m_manager), new_forms(m_manager);

View file

@ -442,11 +442,10 @@ expr * ufbv_rewriter::rewrite(expr * n) {
}
class ufbv_rewriter::add_back_idx_proc {
ast_manager & m_manager;
back_idx_map & m_back_idx;
expr * m_expr;
public:
add_back_idx_proc(ast_manager & m, back_idx_map & bi, expr * e):m_manager(m),m_back_idx(bi),m_expr(e) {}
add_back_idx_proc(back_idx_map & bi, expr * e):m_back_idx(bi),m_expr(e) {}
void operator()(var * n) {}
void operator()(quantifier * n) {}
void operator()(app * n) {
@ -469,11 +468,10 @@ public:
};
class ufbv_rewriter::remove_back_idx_proc {
ast_manager & m_manager;
back_idx_map & m_back_idx;
expr * m_expr;
public:
remove_back_idx_proc(ast_manager & m, back_idx_map & bi, expr * e):m_manager(m),m_back_idx(bi),m_expr(e) {}
remove_back_idx_proc(back_idx_map & bi, expr * e):m_back_idx(bi),m_expr(e) {}
void operator()(var * n) {}
void operator()(quantifier * n) {}
void operator()(app * n) {
@ -511,7 +509,7 @@ void ufbv_rewriter::reschedule_processed(func_decl * f) {
expr * p = *sit;
// remove p from m_processed and m_back_idx
m_processed.remove(p);
remove_back_idx_proc proc(m_manager, m_back_idx, p); // this could change it->m_value, thus we need the `temp' set.
remove_back_idx_proc proc(m_back_idx, p); // this could change it->m_value, thus we need the `temp' set.
for_each_expr(proc, p);
// insert p into m_todo
m_todo.push_back(p);
@ -619,7 +617,7 @@ void ufbv_rewriter::reschedule_demodulators(func_decl * f, expr * lhs) {
// remove d from m_back_idx
// just remember it here, because otherwise it and/or esit might become invalid?
// to_remove.insert(d);
remove_back_idx_proc proc(m_manager, m_back_idx, d);
remove_back_idx_proc proc(m_back_idx, d);
for_each_expr(proc, d);
// insert d into m_todo
m_todo.push_back(d);
@ -674,7 +672,7 @@ void ufbv_rewriter::operator()(unsigned n, expr * const * exprs, proof * const *
// insert n' into m_processed
m_processed.insert(np);
// update m_back_idx (traverse n' and for each uninterpreted function declaration f in n' add the entry f->n' to m_back_idx)
add_back_idx_proc proc(m_manager, m_back_idx, np);
add_back_idx_proc proc(m_back_idx, np);
for_each_expr(proc, np);
} else {
// np is a demodulator that allows us to replace 'large' with 'small'.
@ -702,7 +700,7 @@ void ufbv_rewriter::operator()(unsigned n, expr * const * exprs, proof * const *
insert_fwd_idx(large, small, to_quantifier(np));
// update m_back_idx
add_back_idx_proc proc(m_manager, m_back_idx, np);
add_back_idx_proc proc(m_back_idx, np);
for_each_expr(proc, np);
}
}