mirror of
https://github.com/Z3Prover/z3
synced 2025-04-28 03:15:50 +00:00
initial integration of opt
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
commit
8205b45839
114 changed files with 3680 additions and 1370 deletions
|
@ -128,7 +128,7 @@ extern "C" {
|
|||
lbool r = l_undef;
|
||||
cancel_eh<reslimit> eh(mk_c(c)->m().limit());
|
||||
unsigned timeout = to_optimize_ptr(o)->get_params().get_uint("timeout", mk_c(c)->get_timeout());
|
||||
unsigned rlimit = mk_c(c)->get_rlimit();
|
||||
unsigned rlimit = to_optimize_ptr(o)->get_params().get_uint("rlimit", mk_c(c)->get_rlimit());
|
||||
api::context::set_interruptable si(*(mk_c(c)), eh);
|
||||
{
|
||||
scoped_timer timer(timeout, &eh);
|
||||
|
|
|
@ -52,7 +52,7 @@ extern "C" {
|
|||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_pble(Z3_context c, unsigned num_args,
|
||||
Z3_ast const args[], int _coeffs[],
|
||||
Z3_ast const args[], int const _coeffs[],
|
||||
int k) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_pble(c, num_args, args, _coeffs, k);
|
||||
|
@ -70,7 +70,7 @@ extern "C" {
|
|||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_pbge(Z3_context c, unsigned num_args,
|
||||
Z3_ast const args[], int _coeffs[],
|
||||
Z3_ast const args[], int const _coeffs[],
|
||||
int k) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_pble(c, num_args, args, _coeffs, k);
|
||||
|
@ -88,7 +88,7 @@ extern "C" {
|
|||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_pbeq(Z3_context c, unsigned num_args,
|
||||
Z3_ast const args[], int _coeffs[],
|
||||
Z3_ast const args[], int const _coeffs[],
|
||||
int k) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_pble(c, num_args, args, _coeffs, k);
|
||||
|
|
|
@ -69,14 +69,17 @@ extern "C" {
|
|||
}
|
||||
expr * const* ps = reinterpret_cast<expr * const*>(patterns);
|
||||
expr * const* no_ps = reinterpret_cast<expr * const*>(no_patterns);
|
||||
pattern_validator v(mk_c(c)->m());
|
||||
for (unsigned i = 0; i < num_patterns; i++) {
|
||||
if (!v(num_decls, ps[i], 0, 0)) {
|
||||
SET_ERROR_CODE(Z3_INVALID_PATTERN);
|
||||
return 0;
|
||||
symbol qid = to_symbol(quantifier_id);
|
||||
bool is_rec = mk_c(c)->m().rec_fun_qid() == qid;
|
||||
if (!is_rec) {
|
||||
pattern_validator v(mk_c(c)->m());
|
||||
for (unsigned i = 0; i < num_patterns; i++) {
|
||||
if (!v(num_decls, ps[i], 0, 0)) {
|
||||
SET_ERROR_CODE(Z3_INVALID_PATTERN);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sort* const* ts = reinterpret_cast<sort * const*>(sorts);
|
||||
svector<symbol> names;
|
||||
for (unsigned i = 0; i < num_decls; ++i) {
|
||||
|
@ -88,7 +91,7 @@ extern "C" {
|
|||
(0 != is_forall),
|
||||
names.size(), ts, names.c_ptr(), to_expr(body),
|
||||
weight,
|
||||
to_symbol(quantifier_id),
|
||||
qid,
|
||||
to_symbol(skolem_id),
|
||||
num_patterns, ps,
|
||||
num_no_patterns, no_ps
|
||||
|
|
|
@ -86,7 +86,13 @@ namespace z3 {
|
|||
};
|
||||
inline std::ostream & operator<<(std::ostream & out, exception const & e) { out << e.msg(); return out; }
|
||||
|
||||
|
||||
#if !defined(Z3_THROW)
|
||||
#if __cpp_exceptions || _CPPUNWIND
|
||||
#define Z3_THROW(x) throw x
|
||||
#else
|
||||
#define Z3_THROW(x) {}
|
||||
#endif
|
||||
#endif // !defined(Z3_THROW)
|
||||
|
||||
/**
|
||||
\brief Z3 global configuration object.
|
||||
|
@ -165,7 +171,7 @@ namespace z3 {
|
|||
Z3_error_code check_error() const {
|
||||
Z3_error_code e = Z3_get_error_code(m_ctx);
|
||||
if (e != Z3_OK && enable_exceptions())
|
||||
throw exception(Z3_get_error_msg(m_ctx, e));
|
||||
Z3_THROW(exception(Z3_get_error_msg(m_ctx, e)));
|
||||
return e;
|
||||
}
|
||||
|
||||
|
@ -701,7 +707,7 @@ namespace z3 {
|
|||
if (!is_numeral_i(result)) {
|
||||
assert(ctx().enable_exceptions());
|
||||
if (!ctx().enable_exceptions()) return 0;
|
||||
throw exception("numeral does not fit in machine int");
|
||||
Z3_THROW(exception("numeral does not fit in machine int"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -721,7 +727,7 @@ namespace z3 {
|
|||
if (!is_numeral_u(result)) {
|
||||
assert(ctx().enable_exceptions());
|
||||
if (!ctx().enable_exceptions()) return 0;
|
||||
throw exception("numeral does not fit in machine uint");
|
||||
Z3_THROW(exception("numeral does not fit in machine uint"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -738,7 +744,7 @@ namespace z3 {
|
|||
if (!is_numeral_i64(result)) {
|
||||
assert(ctx().enable_exceptions());
|
||||
if (!ctx().enable_exceptions()) return 0;
|
||||
throw exception("numeral does not fit in machine __int64");
|
||||
Z3_THROW(exception("numeral does not fit in machine __int64"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -755,7 +761,7 @@ namespace z3 {
|
|||
if (!is_numeral_u64(result)) {
|
||||
assert(ctx().enable_exceptions());
|
||||
if (!ctx().enable_exceptions()) return 0;
|
||||
throw exception("numeral does not fit in machine __uint64");
|
||||
Z3_THROW(exception("numeral does not fit in machine __uint64"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -890,6 +896,7 @@ namespace z3 {
|
|||
friend expr operator+(expr const & a, expr const & b);
|
||||
friend expr operator+(expr const & a, int b);
|
||||
friend expr operator+(int a, expr const & b);
|
||||
friend expr sum(expr_vector const& args);
|
||||
|
||||
friend expr operator*(expr const & a, expr const & b);
|
||||
friend expr operator*(expr const & a, int b);
|
||||
|
@ -928,7 +935,6 @@ namespace z3 {
|
|||
|
||||
|
||||
friend expr operator>=(expr const & a, expr const & b);
|
||||
friend expr wasoperator(expr const & a, expr const & b);
|
||||
friend expr operator>=(expr const & a, int b);
|
||||
friend expr operator>=(int a, expr const & b);
|
||||
|
||||
|
@ -940,6 +946,12 @@ namespace z3 {
|
|||
friend expr operator>(expr const & a, int b);
|
||||
friend expr operator>(int a, expr const & b);
|
||||
|
||||
friend expr pble(expr_vector const& es, int const * coeffs, int bound);
|
||||
friend expr pbge(expr_vector const& es, int const * coeffs, int bound);
|
||||
friend expr pbeq(expr_vector const& es, int const * coeffs, int bound);
|
||||
friend expr atmost(expr_vector const& es, unsigned bound);
|
||||
friend expr atleast(expr_vector const& es, unsigned bound);
|
||||
|
||||
friend expr operator&(expr const & a, expr const & b);
|
||||
friend expr operator&(expr const & a, int b);
|
||||
friend expr operator&(int a, expr const & b);
|
||||
|
@ -1559,7 +1571,54 @@ namespace z3 {
|
|||
array<Z3_app> vars(xs);
|
||||
Z3_ast r = Z3_mk_exists_const(b.ctx(), 0, vars.size(), vars.ptr(), 0, 0, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
|
||||
inline expr pble(expr_vector const& es, int const* coeffs, int bound) {
|
||||
assert(es.size() > 0);
|
||||
context& ctx = es[0].ctx();
|
||||
array<Z3_ast> _es(es);
|
||||
Z3_ast r = Z3_mk_pble(ctx, _es.size(), _es.ptr(), coeffs, bound);
|
||||
ctx.check_error();
|
||||
return expr(ctx, r);
|
||||
}
|
||||
inline expr pbge(expr_vector const& es, int const* coeffs, int bound) {
|
||||
assert(es.size() > 0);
|
||||
context& ctx = es[0].ctx();
|
||||
array<Z3_ast> _es(es);
|
||||
Z3_ast r = Z3_mk_pbge(ctx, _es.size(), _es.ptr(), coeffs, bound);
|
||||
ctx.check_error();
|
||||
return expr(ctx, r);
|
||||
}
|
||||
inline expr pbeq(expr_vector const& es, int const* coeffs, int bound) {
|
||||
assert(es.size() > 0);
|
||||
context& ctx = es[0].ctx();
|
||||
array<Z3_ast> _es(es);
|
||||
Z3_ast r = Z3_mk_pbeq(ctx, _es.size(), _es.ptr(), coeffs, bound);
|
||||
ctx.check_error();
|
||||
return expr(ctx, r);
|
||||
}
|
||||
inline expr atmost(expr_vector const& es, unsigned bound) {
|
||||
assert(es.size() > 0);
|
||||
context& ctx = es[0].ctx();
|
||||
array<Z3_ast> _es(es);
|
||||
Z3_ast r = Z3_mk_atmost(ctx, _es.size(), _es.ptr(), bound);
|
||||
ctx.check_error();
|
||||
return expr(ctx, r);
|
||||
}
|
||||
inline expr atleast(expr_vector const& es, unsigned bound) {
|
||||
assert(es.size() > 0);
|
||||
context& ctx = es[0].ctx();
|
||||
array<Z3_ast> _es(es);
|
||||
Z3_ast r = Z3_mk_atleast(ctx, _es.size(), _es.ptr(), bound);
|
||||
ctx.check_error();
|
||||
return expr(ctx, r);
|
||||
}
|
||||
inline expr sum(expr_vector const& args) {
|
||||
assert(args.size() > 0);
|
||||
context& ctx = args[0].ctx();
|
||||
array<Z3_ast> _args(args);
|
||||
Z3_ast r = Z3_mk_add(ctx, _args.size(), _args.ptr());
|
||||
ctx.check_error();
|
||||
return expr(ctx, r);
|
||||
}
|
||||
|
||||
inline expr distinct(expr_vector const& args) {
|
||||
assert(args.size() > 0);
|
||||
|
@ -1699,7 +1758,7 @@ namespace z3 {
|
|||
Z3_bool status = Z3_model_eval(ctx(), m_model, n, model_completion, &r);
|
||||
check_error();
|
||||
if (status == Z3_FALSE && ctx().enable_exceptions())
|
||||
throw exception("failed to evaluate expression");
|
||||
Z3_THROW(exception("failed to evaluate expression"));
|
||||
return expr(ctx(), r);
|
||||
}
|
||||
|
||||
|
@ -2023,7 +2082,7 @@ namespace z3 {
|
|||
}
|
||||
inline tactic par_or(unsigned n, tactic const* tactics) {
|
||||
if (n == 0) {
|
||||
throw exception("a non-zero number of tactics need to be passed to par_or");
|
||||
Z3_THROW(exception("a non-zero number of tactics need to be passed to par_or"));
|
||||
}
|
||||
array<Z3_tactic> buffer(n);
|
||||
for (unsigned i = 0; i < n; ++i) buffer[i] = tactics[i];
|
||||
|
@ -2178,14 +2237,14 @@ namespace z3 {
|
|||
class fixedpoint : public object {
|
||||
Z3_fixedpoint m_fp;
|
||||
public:
|
||||
fixedpoint(context& c):object(c) { mfp = Z3_mk_fixedpoint(c); Z3_fixedpoint_inc_ref(c, m_fp); }
|
||||
fixedpoint(context& c):object(c) { m_fp = Z3_mk_fixedpoint(c); Z3_fixedpoint_inc_ref(c, m_fp); }
|
||||
~fixedpoint() { Z3_fixedpoint_dec_ref(ctx(), m_fp); }
|
||||
operator Z3_fixedpoint() const { return m_fp; }
|
||||
void from_string(char const* s) { Z3_fixedpoint_from_string(ctx(), m_fp, s); check_error(); }
|
||||
void from_file(char const* s) { Z3_fixedpoint_from_file(ctx(), m_fp, s); check_error(); }
|
||||
void add_rule(expr& rule, symbol const& name) { Z3_fixedpoint_add_rule(ctx(), m_fp, rule, name); check_error(); }
|
||||
void add_fact(func_decl& f, unsigned const* args) { Z3_fixedpoint_add_fact(ctx(), m_fp, f, f.num_args(), args); check_error(); }
|
||||
check_result query(expr& q) { Z3_lbool r = Z3_fixedpoint_query(ctx(), m_fp, q); check_error(); to_check_result(r); }
|
||||
void add_fact(func_decl& f, unsigned * args) { Z3_fixedpoint_add_fact(ctx(), m_fp, f, f.arity(), args); check_error(); }
|
||||
check_result query(expr& q) { Z3_lbool r = Z3_fixedpoint_query(ctx(), m_fp, q); check_error(); return to_check_result(r); }
|
||||
check_result query(func_decl_vector& relations) {
|
||||
array<Z3_func_decl> rs(relations);
|
||||
Z3_lbool r = Z3_fixedpoint_query_relations(ctx(), m_fp, rs.size(), rs.ptr());
|
||||
|
@ -2194,9 +2253,13 @@ namespace z3 {
|
|||
}
|
||||
expr get_answer() { Z3_ast r = Z3_fixedpoint_get_answer(ctx(), m_fp); check_error(); return expr(ctx(), r); }
|
||||
std::string reason_unknown() { return Z3_fixedpoint_get_reason_unknown(ctx(), m_fp); }
|
||||
void update_rule(expr& rule, synbol const& name) { Z3_fixedpoint_update_rule(ctx(), m_fp, rule, name); check_error(); }
|
||||
void update_rule(expr& rule, symbol const& name) { Z3_fixedpoint_update_rule(ctx(), m_fp, rule, name); check_error(); }
|
||||
unsigned get_num_levels(func_decl& p) { unsigned r = Z3_fixedpoint_get_num_levels(ctx(), m_fp, p); check_error(); return r; }
|
||||
expr get_cover_delta(int level, func_decl& p) { return Z3_fixedpoint_get_cover_delta(ctx(), m_fp, level, p); check_error(); }
|
||||
expr get_cover_delta(int level, func_decl& p) {
|
||||
Z3_ast r = Z3_fixedpoint_get_cover_delta(ctx(), m_fp, level, p);
|
||||
check_error();
|
||||
return expr(ctx(), r);
|
||||
}
|
||||
void add_cover(int level, func_decl& p, expr& property) { Z3_fixedpoint_add_cover(ctx(), m_fp, level, p, property); check_error(); }
|
||||
stats statistics() const { Z3_stats r = Z3_fixedpoint_get_statistics(ctx(), m_fp); check_error(); return stats(ctx(), r); }
|
||||
void register_relation(func_decl& p) { Z3_fixedpoint_register_relation(ctx(), m_fp, p); }
|
||||
|
@ -2205,11 +2268,15 @@ namespace z3 {
|
|||
void set(params const & p) { Z3_fixedpoint_set_params(ctx(), m_fp, p); check_error(); }
|
||||
std::string help() const { return Z3_fixedpoint_get_help(ctx(), m_fp); }
|
||||
param_descrs get_param_descrs() { return param_descrs(ctx(), Z3_fixedpoint_get_param_descrs(ctx(), m_fp)); }
|
||||
std::string to_string() { return Z3_fixedpoint_to_string(ctx(), m_fp); }
|
||||
std::string to_string() { return Z3_fixedpoint_to_string(ctx(), m_fp, 0, 0); }
|
||||
std::string to_string(expr_vector const& queries) {
|
||||
array<Z3_ast> qs(queries);
|
||||
return Z3_fixedpoint_to_string(ctx(), m_fp, qs.size(), qs.ptr());
|
||||
}
|
||||
void push() { Z3_fixedpoint_push(ctx(), m_fp); check_error(); }
|
||||
void pop() { Z3_fixedpoint_pop(ctx(), m_fp); check_error(); }
|
||||
};
|
||||
inline std::ostream & operator<<(std::ostream & out, fixedpoint const & f) { return out << Z3_fixedpoint_to_string(f.ctx(), f); }
|
||||
inline std::ostream & operator<<(std::ostream & out, fixedpoint const & f) { return out << Z3_fixedpoint_to_string(f.ctx(), f, 0, 0); }
|
||||
|
||||
inline tactic fail_if(probe const & p) {
|
||||
Z3_tactic r = Z3_tactic_fail_if(p.ctx(), p);
|
||||
|
|
|
@ -1890,43 +1890,43 @@ public class Context implements AutoCloseable {
|
|||
/**
|
||||
* Create the empty sequence.
|
||||
*/
|
||||
public SeqExpr MkEmptySeq(Sort s)
|
||||
public SeqExpr mkEmptySeq(Sort s)
|
||||
{
|
||||
checkContextMatch(s);
|
||||
return new SeqExpr(this, Native.mkSeqEmpty(nCtx(), s.getNativeObject()));
|
||||
return (SeqExpr) Expr.create(this, Native.mkSeqEmpty(nCtx(), s.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the singleton sequence.
|
||||
*/
|
||||
public SeqExpr MkUnit(Expr elem)
|
||||
public SeqExpr mkUnit(Expr elem)
|
||||
{
|
||||
checkContextMatch(elem);
|
||||
return new SeqExpr(this, Native.mkSeqUnit(nCtx(), elem.getNativeObject()));
|
||||
return (SeqExpr) Expr.create(this, Native.mkSeqUnit(nCtx(), elem.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a string constant.
|
||||
*/
|
||||
public SeqExpr MkString(String s)
|
||||
public SeqExpr mkString(String s)
|
||||
{
|
||||
return new SeqExpr(this, Native.mkString(nCtx(), s));
|
||||
return (SeqExpr) Expr.create(this, Native.mkString(nCtx(), s));
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatentate sequences.
|
||||
*/
|
||||
public SeqExpr MkConcat(SeqExpr... t)
|
||||
public SeqExpr mkConcat(SeqExpr... t)
|
||||
{
|
||||
checkContextMatch(t);
|
||||
return new SeqExpr(this, Native.mkSeqConcat(nCtx(), t.length, AST.arrayToNative(t)));
|
||||
return (SeqExpr) Expr.create(this, Native.mkSeqConcat(nCtx(), t.length, AST.arrayToNative(t)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the length of a given sequence.
|
||||
*/
|
||||
public IntExpr MkLength(SeqExpr s)
|
||||
public IntExpr mkLength(SeqExpr s)
|
||||
{
|
||||
checkContextMatch(s);
|
||||
return (IntExpr) Expr.create(this, Native.mkSeqLength(nCtx(), s.getNativeObject()));
|
||||
|
@ -1935,130 +1935,221 @@ public class Context implements AutoCloseable {
|
|||
/**
|
||||
* Check for sequence prefix.
|
||||
*/
|
||||
public BoolExpr MkPrefixOf(SeqExpr s1, SeqExpr s2)
|
||||
public BoolExpr mkPrefixOf(SeqExpr s1, SeqExpr s2)
|
||||
{
|
||||
checkContextMatch(s1, s2);
|
||||
return new BoolExpr(this, Native.mkSeqPrefix(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
|
||||
return (BoolExpr) Expr.create(this, Native.mkSeqPrefix(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for sequence suffix.
|
||||
*/
|
||||
public BoolExpr MkSuffixOf(SeqExpr s1, SeqExpr s2)
|
||||
public BoolExpr mkSuffixOf(SeqExpr s1, SeqExpr s2)
|
||||
{
|
||||
checkContextMatch(s1, s2);
|
||||
return new BoolExpr(this, Native.mkSeqSuffix(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
|
||||
return (BoolExpr)Expr.create(this, Native.mkSeqSuffix(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for sequence containment of s2 in s1.
|
||||
*/
|
||||
public BoolExpr MkContains(SeqExpr s1, SeqExpr s2)
|
||||
public BoolExpr mkContains(SeqExpr s1, SeqExpr s2)
|
||||
{
|
||||
checkContextMatch(s1, s2);
|
||||
return new BoolExpr(this, Native.mkSeqContains(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
|
||||
return (BoolExpr) Expr.create(this, Native.mkSeqContains(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve sequence of length one at index.
|
||||
*/
|
||||
public SeqExpr MkAt(SeqExpr s, IntExpr index)
|
||||
public SeqExpr mkAt(SeqExpr s, IntExpr index)
|
||||
{
|
||||
checkContextMatch(s, index);
|
||||
return new SeqExpr(this, Native.mkSeqAt(nCtx(), s.getNativeObject(), index.getNativeObject()));
|
||||
return (SeqExpr) Expr.create(this, Native.mkSeqAt(nCtx(), s.getNativeObject(), index.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract subsequence.
|
||||
*/
|
||||
public SeqExpr MkExtract(SeqExpr s, IntExpr offset, IntExpr length)
|
||||
public SeqExpr mkExtract(SeqExpr s, IntExpr offset, IntExpr length)
|
||||
{
|
||||
checkContextMatch(s, offset, length);
|
||||
return new SeqExpr(this, Native.mkSeqExtract(nCtx(), s.getNativeObject(), offset.getNativeObject(), length.getNativeObject()));
|
||||
return (SeqExpr) Expr.create(this, Native.mkSeqExtract(nCtx(), s.getNativeObject(), offset.getNativeObject(), length.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract index of sub-string starting at offset.
|
||||
*/
|
||||
public IntExpr MkIndexOf(SeqExpr s, SeqExpr substr, ArithExpr offset)
|
||||
public IntExpr mkIndexOf(SeqExpr s, SeqExpr substr, ArithExpr offset)
|
||||
{
|
||||
checkContextMatch(s, substr, offset);
|
||||
return new IntExpr(this, Native.mkSeqIndex(nCtx(), s.getNativeObject(), substr.getNativeObject(), offset.getNativeObject()));
|
||||
return (IntExpr)Expr.create(this, Native.mkSeqIndex(nCtx(), s.getNativeObject(), substr.getNativeObject(), offset.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the first occurrence of src by dst in s.
|
||||
*/
|
||||
public SeqExpr MkReplace(SeqExpr s, SeqExpr src, SeqExpr dst)
|
||||
public SeqExpr mkReplace(SeqExpr s, SeqExpr src, SeqExpr dst)
|
||||
{
|
||||
checkContextMatch(s, src, dst);
|
||||
return new SeqExpr(this, Native.mkSeqReplace(nCtx(), s.getNativeObject(), src.getNativeObject(), dst.getNativeObject()));
|
||||
return (SeqExpr) Expr.create(this, Native.mkSeqReplace(nCtx(), s.getNativeObject(), src.getNativeObject(), dst.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a regular expression that accepts sequence s.
|
||||
*/
|
||||
public ReExpr MkToRe(SeqExpr s)
|
||||
public ReExpr mkToRe(SeqExpr s)
|
||||
{
|
||||
checkContextMatch(s);
|
||||
return new ReExpr(this, Native.mkSeqToRe(nCtx(), s.getNativeObject()));
|
||||
return (ReExpr) Expr.create(this, Native.mkSeqToRe(nCtx(), s.getNativeObject()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check for regular expression membership.
|
||||
*/
|
||||
public BoolExpr MkInRe(SeqExpr s, ReExpr re)
|
||||
public BoolExpr mkInRe(SeqExpr s, ReExpr re)
|
||||
{
|
||||
checkContextMatch(s, re);
|
||||
return new BoolExpr(this, Native.mkSeqInRe(nCtx(), s.getNativeObject(), re.getNativeObject()));
|
||||
return (BoolExpr) Expr.create(this, Native.mkSeqInRe(nCtx(), s.getNativeObject(), re.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the Kleene star of a regular expression.
|
||||
*/
|
||||
public ReExpr MkStar(ReExpr re)
|
||||
public ReExpr mkStar(ReExpr re)
|
||||
{
|
||||
checkContextMatch(re);
|
||||
return new ReExpr(this, Native.mkReStar(nCtx(), re.getNativeObject()));
|
||||
return (ReExpr) Expr.create(this, Native.mkReStar(nCtx(), re.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the lower and upper-bounded Kleene star of a regular expression.
|
||||
*/
|
||||
public ReExpr mkLoop(ReExpr re, int lo, int hi)
|
||||
{
|
||||
return (ReExpr) Expr.create(this, Native.mkReLoop(nCtx(), re.getNativeObject(), lo, hi));
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the lower-bounded Kleene star of a regular expression.
|
||||
*/
|
||||
public ReExpr mkLoop(ReExpr re, int lo)
|
||||
{
|
||||
return (ReExpr) Expr.create(this, Native.mkReLoop(nCtx(), re.getNativeObject(), lo, 0));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Take the Kleene plus of a regular expression.
|
||||
*/
|
||||
public ReExpr MPlus(ReExpr re)
|
||||
public ReExpr mkPlus(ReExpr re)
|
||||
{
|
||||
checkContextMatch(re);
|
||||
return new ReExpr(this, Native.mkRePlus(nCtx(), re.getNativeObject()));
|
||||
return (ReExpr) Expr.create(this, Native.mkRePlus(nCtx(), re.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the optional regular expression.
|
||||
*/
|
||||
public ReExpr MOption(ReExpr re)
|
||||
public ReExpr mkOption(ReExpr re)
|
||||
{
|
||||
checkContextMatch(re);
|
||||
return new ReExpr(this, Native.mkReOption(nCtx(), re.getNativeObject()));
|
||||
return (ReExpr) Expr.create(this, Native.mkReOption(nCtx(), re.getNativeObject()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create the complement regular expression.
|
||||
*/
|
||||
public ReExpr mkComplement(ReExpr re)
|
||||
{
|
||||
checkContextMatch(re);
|
||||
return (ReExpr) Expr.create(this, Native.mkReComplement(nCtx(), re.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the concatenation of regular languages.
|
||||
*/
|
||||
public ReExpr MkConcat(ReExpr... t)
|
||||
public ReExpr mkConcat(ReExpr... t)
|
||||
{
|
||||
checkContextMatch(t);
|
||||
return new ReExpr(this, Native.mkReConcat(nCtx(), t.length, AST.arrayToNative(t)));
|
||||
return (ReExpr) Expr.create(this, Native.mkReConcat(nCtx(), t.length, AST.arrayToNative(t)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the union of regular languages.
|
||||
*/
|
||||
public ReExpr MkUnion(ReExpr... t)
|
||||
public ReExpr mkUnion(ReExpr... t)
|
||||
{
|
||||
checkContextMatch(t);
|
||||
return new ReExpr(this, Native.mkReUnion(nCtx(), t.length, AST.arrayToNative(t)));
|
||||
return (ReExpr) Expr.create(this, Native.mkReUnion(nCtx(), t.length, AST.arrayToNative(t)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the intersection of regular languages.
|
||||
*/
|
||||
public ReExpr mkIntersect(ReExpr... t)
|
||||
{
|
||||
checkContextMatch(t);
|
||||
return (ReExpr) Expr.create(this, Native.mkReIntersect(nCtx(), t.length, AST.arrayToNative(t)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a range expression.
|
||||
*/
|
||||
public ReExpr MkRange(SeqExpr lo, SeqExpr hi)
|
||||
{
|
||||
checkContextMatch(lo, hi);
|
||||
return (ReExpr) Expr.create(this, Native.mkReRange(nCtx(), lo.getNativeObject(), hi.getNativeObject()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create an at-most-k constraint.
|
||||
*/
|
||||
public BoolExpr mkAtMost(BoolExpr[] args, int k)
|
||||
{
|
||||
checkContextMatch(args);
|
||||
return (BoolExpr) Expr.create(this, Native.mkAtmost(nCtx(), args.length, AST.arrayToNative(args), k));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an at-least-k constraint.
|
||||
*/
|
||||
public BoolExpr mkAtLeast(BoolExpr[] args, int k)
|
||||
{
|
||||
checkContextMatch(args);
|
||||
return (BoolExpr) Expr.create(this, Native.mkAtleast(nCtx(), args.length, AST.arrayToNative(args), k));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a pseudo-Boolean less-or-equal constraint.
|
||||
*/
|
||||
public BoolExpr mkPBLe(int[] coeffs, BoolExpr[] args, int k)
|
||||
{
|
||||
checkContextMatch(args);
|
||||
return (BoolExpr) Expr.create(this, Native.mkPble(nCtx(), args.length, AST.arrayToNative(args), coeffs, k));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a pseudo-Boolean greater-or-equal constraint.
|
||||
*/
|
||||
public BoolExpr mkPBGe(int[] coeffs, BoolExpr[] args, int k)
|
||||
{
|
||||
checkContextMatch(args);
|
||||
return (BoolExpr) Expr.create(this, Native.mkPbge(nCtx(), args.length, AST.arrayToNative(args), coeffs, k));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a pseudo-Boolean equal constraint.
|
||||
*/
|
||||
public BoolExpr mkPBEq(int[] coeffs, BoolExpr[] args, int k)
|
||||
{
|
||||
checkContextMatch(args);
|
||||
return (BoolExpr) Expr.create(this, Native.mkPbeq(nCtx(), args.length, AST.arrayToNative(args), coeffs, k));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a Term of a given sort.
|
||||
|
|
|
@ -3701,12 +3701,8 @@ def Extract(high, low, a):
|
|||
high = StringVal(high)
|
||||
if is_seq(high):
|
||||
s = high
|
||||
offset = _py2expr(low, high.ctx)
|
||||
length = _py2expr(a, high.ctx)
|
||||
|
||||
if __debug__:
|
||||
_z3_assert(is_int(offset) and is_int(length), "Second and third arguments must be integers")
|
||||
return SeqRef(Z3_mk_seq_extract(s.ctx_ref(), s.as_ast(), offset.as_ast(), length.as_ast()), s.ctx)
|
||||
offset, length = _coerce_exprs(low, a, s.ctx)
|
||||
return SeqRef(Z3_mk_seq_extract(s.ctx_ref(), s.as_ast(), offset.as_ast(), length.as_ast()), s.ctx)
|
||||
if __debug__:
|
||||
_z3_assert(low <= high, "First argument must be greater than or equal to second argument")
|
||||
_z3_assert(_is_int(high) and high >= 0 and _is_int(low) and low >= 0, "First and second arguments must be non negative integers")
|
||||
|
@ -6198,7 +6194,7 @@ class Solver(Z3PPObject):
|
|||
>>> s.consequences([a],[b,c,d])
|
||||
(sat, [Implies(a, b), Implies(a, c)])
|
||||
>>> s.consequences([Not(c),d],[a,b,c,d])
|
||||
(sat, [Implies(Not(c), Not(c)), Implies(d, d), Implies(Not(c), Not(b)), Implies(Not(c), Not(a))])
|
||||
(sat, [Implies(d, d), Implies(Not(c), Not(c)), Implies(Not(c), Not(b)), Implies(Not(c), Not(a))])
|
||||
"""
|
||||
if isinstance(assumptions, list):
|
||||
_asms = AstVector(None, self.ctx)
|
||||
|
@ -7204,7 +7200,7 @@ def With(t, *args, **keys):
|
|||
>>> t((x + 1)*(y + 2) == 0)
|
||||
[[2*x + y + x*y == -2]]
|
||||
"""
|
||||
ctx = keys.get('ctx', None)
|
||||
ctx = keys.pop('ctx', None)
|
||||
t = _to_tactic(t, ctx)
|
||||
p = args2params(args, keys, t.ctx)
|
||||
return Tactic(Z3_tactic_using_params(t.ctx.ref(), t.tactic, p.params), t.ctx)
|
||||
|
|
|
@ -1500,7 +1500,7 @@ extern "C" {
|
|||
All main interaction with Z3 happens in the context of a \c Z3_context.
|
||||
|
||||
In contrast to #Z3_mk_context_rc, the life time of Z3_ast objects
|
||||
are determined by the scope level of #Z3_push and #Z3_pop.
|
||||
are determined by the scope level of #Z3_solver_push and #Z3_solver_pop.
|
||||
In other words, a Z3_ast object remains valid until there is a
|
||||
call to Z3_pop that takes the current scope below the level where
|
||||
the object was created.
|
||||
|
@ -3091,8 +3091,8 @@ extern "C" {
|
|||
\brief Create a numeral of a given sort.
|
||||
|
||||
\param c logical context.
|
||||
\param numeral A string representing the numeral value in decimal notation. The string may be of the form \code{[num]*[.[num]*][E[+|-][num]+]}.
|
||||
If the given sort is a real, then the numeral can be a rational, that is, a string of the form \ccode{[num]* / [num]*}.
|
||||
\param numeral A string representing the numeral value in decimal notation. The string may be of the form `[num]*[.[num]*][E[+|-][num]+]`.
|
||||
If the given sort is a real, then the numeral can be a rational, that is, a string of the form `[num]* / [num]*` .
|
||||
\param ty The sort of the numeral. In the current implementation, the given sort can be an int, real, finite-domain, or bit-vectors of arbitrary size.
|
||||
|
||||
\sa Z3_mk_int
|
||||
|
@ -3306,7 +3306,7 @@ extern "C" {
|
|||
Z3_ast Z3_API Z3_mk_seq_replace(Z3_context c, Z3_ast s, Z3_ast src, Z3_ast dst);
|
||||
|
||||
/**
|
||||
\brief Retrieve from \s the unit sequence positioned at position \c index.
|
||||
\brief Retrieve from \c s the unit sequence positioned at position \c index.
|
||||
|
||||
def_API('Z3_mk_seq_at' ,AST ,(_in(CONTEXT), _in(AST), _in(AST)))
|
||||
*/
|
||||
|
@ -4006,7 +4006,7 @@ extern "C" {
|
|||
def_API('Z3_mk_pble', AST, (_in(CONTEXT), _in(UINT), _in_array(1,AST), _in_array(1,INT), _in(INT)))
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_pble(Z3_context c, unsigned num_args,
|
||||
Z3_ast const args[], int coeffs[],
|
||||
Z3_ast const args[], int const coeffs[],
|
||||
int k);
|
||||
|
||||
/**
|
||||
|
@ -4017,7 +4017,7 @@ extern "C" {
|
|||
def_API('Z3_mk_pbge', AST, (_in(CONTEXT), _in(UINT), _in_array(1,AST), _in_array(1,INT), _in(INT)))
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_pbge(Z3_context c, unsigned num_args,
|
||||
Z3_ast const args[], int coeffs[],
|
||||
Z3_ast const args[], int const coeffs[],
|
||||
int k);
|
||||
|
||||
/**
|
||||
|
@ -4028,7 +4028,7 @@ extern "C" {
|
|||
def_API('Z3_mk_pbeq', AST, (_in(CONTEXT), _in(UINT), _in_array(1,AST), _in_array(1,INT), _in(INT)))
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_pbeq(Z3_context c, unsigned num_args,
|
||||
Z3_ast const args[], int coeffs[],
|
||||
Z3_ast const args[], int const coeffs[],
|
||||
int k);
|
||||
|
||||
/**
|
||||
|
|
|
@ -35,7 +35,7 @@ struct arith_decl_plugin::algebraic_numbers_wrapper {
|
|||
|
||||
~algebraic_numbers_wrapper() {
|
||||
}
|
||||
|
||||
|
||||
unsigned mk_id(algebraic_numbers::anum const & val) {
|
||||
SASSERT(!m_amanager.is_rational(val));
|
||||
unsigned new_id = m_id_gen.mk();
|
||||
|
@ -121,7 +121,7 @@ void arith_decl_plugin::set_manager(ast_manager * m, family_id id) {
|
|||
m_int_decl = m->mk_sort(symbol("Int"), sort_info(id, INT_SORT));
|
||||
m->inc_ref(m_int_decl);
|
||||
sort * i = m_int_decl;
|
||||
|
||||
|
||||
sort * b = m->mk_bool_sort();
|
||||
|
||||
#define MK_PRED(FIELD, NAME, KIND, SORT) { \
|
||||
|
@ -140,7 +140,7 @@ void arith_decl_plugin::set_manager(ast_manager * m, family_id id) {
|
|||
MK_PRED(m_i_ge_decl, ">=", OP_GE, i);
|
||||
MK_PRED(m_i_lt_decl, "<", OP_LT, i);
|
||||
MK_PRED(m_i_gt_decl, ">", OP_GT, i);
|
||||
|
||||
|
||||
#define MK_AC_OP(FIELD, NAME, KIND, SORT) { \
|
||||
func_decl_info info(id, KIND); \
|
||||
info.set_associative(); \
|
||||
|
@ -205,7 +205,7 @@ void arith_decl_plugin::set_manager(ast_manager * m, family_id id) {
|
|||
MK_UNARY(m_asinh_decl, "asinh", OP_ASINH, r);
|
||||
MK_UNARY(m_acosh_decl, "acosh", OP_ACOSH, r);
|
||||
MK_UNARY(m_atanh_decl, "atanh", OP_ATANH, r);
|
||||
|
||||
|
||||
func_decl * pi_decl = m->mk_const_decl(symbol("pi"), r, func_decl_info(id, OP_PI));
|
||||
m_pi = m->mk_const(pi_decl);
|
||||
m->inc_ref(m_pi);
|
||||
|
@ -213,7 +213,7 @@ void arith_decl_plugin::set_manager(ast_manager * m, family_id id) {
|
|||
func_decl * e_decl = m->mk_const_decl(symbol("euler"), r, func_decl_info(id, OP_E));
|
||||
m_e = m->mk_const(e_decl);
|
||||
m->inc_ref(m_e);
|
||||
|
||||
|
||||
func_decl * z_pw_z_int = m->mk_const_decl(symbol("0^0-int"), i, func_decl_info(id, OP_0_PW_0_INT));
|
||||
m_0_pw_0_int = m->mk_const(z_pw_z_int);
|
||||
m->inc_ref(m_0_pw_0_int);
|
||||
|
@ -221,7 +221,7 @@ void arith_decl_plugin::set_manager(ast_manager * m, family_id id) {
|
|||
func_decl * z_pw_z_real = m->mk_const_decl(symbol("0^0-real"), r, func_decl_info(id, OP_0_PW_0_REAL));
|
||||
m_0_pw_0_real = m->mk_const(z_pw_z_real);
|
||||
m->inc_ref(m_0_pw_0_real);
|
||||
|
||||
|
||||
MK_OP(m_neg_root_decl, "neg-root", OP_NEG_ROOT, r);
|
||||
MK_UNARY(m_div_0_decl, "/0", OP_DIV_0, r);
|
||||
MK_UNARY(m_idiv_0_decl, "div0", OP_IDIV_0, i);
|
||||
|
@ -285,7 +285,8 @@ arith_decl_plugin::arith_decl_plugin():
|
|||
m_idiv_0_decl(0),
|
||||
m_mod_0_decl(0),
|
||||
m_u_asin_decl(0),
|
||||
m_u_acos_decl(0) {
|
||||
m_u_acos_decl(0),
|
||||
m_convert_int_numerals_to_real(false) {
|
||||
}
|
||||
|
||||
arith_decl_plugin::~arith_decl_plugin() {
|
||||
|
@ -418,7 +419,7 @@ app * arith_decl_plugin::mk_numeral(rational const & val, bool is_int) {
|
|||
if (val.is_unsigned()) {
|
||||
unsigned u_val = val.get_unsigned();
|
||||
if (u_val < MAX_SMALL_NUM_TO_CACHE) {
|
||||
if (is_int) {
|
||||
if (is_int && !m_convert_int_numerals_to_real) {
|
||||
app * r = m_small_ints.get(u_val, 0);
|
||||
if (r == 0) {
|
||||
parameter p[2] = { parameter(val), parameter(1) };
|
||||
|
@ -442,7 +443,7 @@ app * arith_decl_plugin::mk_numeral(rational const & val, bool is_int) {
|
|||
}
|
||||
parameter p[2] = { parameter(val), parameter(static_cast<int>(is_int)) };
|
||||
func_decl * decl;
|
||||
if (is_int)
|
||||
if (is_int && !m_convert_int_numerals_to_real)
|
||||
decl = m_manager->mk_const_decl(m_intv_sym, m_int_decl, func_decl_info(m_family_id, OP_NUM, 2, p));
|
||||
else
|
||||
decl = m_manager->mk_const_decl(m_realv_sym, m_real_decl, func_decl_info(m_family_id, OP_NUM, 2, p));
|
||||
|
@ -479,14 +480,14 @@ static bool has_real_arg(ast_manager * m, unsigned num_args, expr * const * args
|
|||
}
|
||||
|
||||
static bool is_const_op(decl_kind k) {
|
||||
return
|
||||
k == OP_PI ||
|
||||
return
|
||||
k == OP_PI ||
|
||||
k == OP_E ||
|
||||
k == OP_0_PW_0_INT ||
|
||||
k == OP_0_PW_0_REAL;
|
||||
}
|
||||
|
||||
func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
|
||||
func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
if (k == OP_NUM)
|
||||
return mk_num_decl(num_parameters, parameters, arity);
|
||||
|
@ -503,7 +504,7 @@ func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters
|
|||
}
|
||||
}
|
||||
|
||||
func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned num_args, expr * const * args, sort * range) {
|
||||
if (k == OP_NUM)
|
||||
return mk_num_decl(num_parameters, parameters, num_args);
|
||||
|
@ -521,9 +522,17 @@ func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters
|
|||
}
|
||||
|
||||
void arith_decl_plugin::get_sort_names(svector<builtin_name>& sort_names, symbol const & logic) {
|
||||
// TODO: only define Int and Real in the right logics
|
||||
sort_names.push_back(builtin_name("Int", INT_SORT));
|
||||
sort_names.push_back(builtin_name("Real", REAL_SORT));
|
||||
if (logic == "NRA" ||
|
||||
logic == "QF_NRA" ||
|
||||
logic == "QF_UFNRA") {
|
||||
m_convert_int_numerals_to_real = true;
|
||||
sort_names.push_back(builtin_name("Real", REAL_SORT));
|
||||
}
|
||||
else {
|
||||
// TODO: only define Int and Real in the right logics
|
||||
sort_names.push_back(builtin_name("Int", INT_SORT));
|
||||
sort_names.push_back(builtin_name("Real", REAL_SORT));
|
||||
}
|
||||
}
|
||||
|
||||
void arith_decl_plugin::get_op_names(svector<builtin_name>& op_names, symbol const & logic) {
|
||||
|
@ -563,16 +572,16 @@ void arith_decl_plugin::get_op_names(svector<builtin_name>& op_names, symbol con
|
|||
}
|
||||
|
||||
bool arith_decl_plugin::is_value(app * e) const {
|
||||
return
|
||||
is_app_of(e, m_family_id, OP_NUM) ||
|
||||
return
|
||||
is_app_of(e, m_family_id, OP_NUM) ||
|
||||
is_app_of(e, m_family_id, OP_IRRATIONAL_ALGEBRAIC_NUM) ||
|
||||
is_app_of(e, m_family_id, OP_PI) ||
|
||||
is_app_of(e, m_family_id, OP_E);
|
||||
}
|
||||
|
||||
bool arith_decl_plugin::is_unique_value(app * e) const {
|
||||
return
|
||||
is_app_of(e, m_family_id, OP_NUM) ||
|
||||
return
|
||||
is_app_of(e, m_family_id, OP_NUM) ||
|
||||
is_app_of(e, m_family_id, OP_PI) ||
|
||||
is_app_of(e, m_family_id, OP_E);
|
||||
}
|
||||
|
@ -671,7 +680,7 @@ expr_ref arith_util::mk_mul_simplify(expr_ref_vector const& args) {
|
|||
}
|
||||
expr_ref arith_util::mk_mul_simplify(unsigned sz, expr* const* args) {
|
||||
expr_ref result(m_manager);
|
||||
|
||||
|
||||
switch (sz) {
|
||||
case 0:
|
||||
result = mk_numeral(rational(1), true);
|
||||
|
@ -681,7 +690,7 @@ expr_ref arith_util::mk_mul_simplify(unsigned sz, expr* const* args) {
|
|||
break;
|
||||
default:
|
||||
result = mk_mul(sz, args);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -692,7 +701,7 @@ expr_ref arith_util::mk_add_simplify(expr_ref_vector const& args) {
|
|||
}
|
||||
expr_ref arith_util::mk_add_simplify(unsigned sz, expr* const* args) {
|
||||
expr_ref result(m_manager);
|
||||
|
||||
|
||||
switch (sz) {
|
||||
case 0:
|
||||
result = mk_numeral(rational(0), true);
|
||||
|
@ -702,7 +711,7 @@ expr_ref arith_util::mk_add_simplify(unsigned sz, expr* const* args) {
|
|||
break;
|
||||
default:
|
||||
result = mk_add(sz, args);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -152,6 +152,8 @@ protected:
|
|||
ptr_vector<app> m_small_ints;
|
||||
ptr_vector<app> m_small_reals;
|
||||
|
||||
bool m_convert_int_numerals_to_real;
|
||||
|
||||
func_decl * mk_func_decl(decl_kind k, bool is_real);
|
||||
virtual void set_manager(ast_manager * m, family_id id);
|
||||
decl_kind fix_kind(decl_kind k, unsigned arity);
|
||||
|
|
|
@ -1002,14 +1002,6 @@ class smt2_printer {
|
|||
reset_stacks();
|
||||
SASSERT(&(r.get_manager()) == &(fm()));
|
||||
m_soccs(n);
|
||||
TRACE("smt2_pp_shared",
|
||||
tout << "shared terms for:\n" << mk_pp(n, m()) << "\n";
|
||||
tout << "------>\n";
|
||||
shared_occs::iterator it = m_soccs.begin_shared();
|
||||
shared_occs::iterator end = m_soccs.end_shared();
|
||||
for (; it != end; ++it) {
|
||||
tout << mk_pp(*it, m()) << "\n";
|
||||
});
|
||||
m_root = n;
|
||||
push_frame(n, true);
|
||||
while (!m_frame_stack.empty()) {
|
||||
|
|
|
@ -406,11 +406,11 @@ public:
|
|||
app * mk_bv_not(expr * arg) { return m_manager.mk_app(get_fid(), OP_BNOT, arg); }
|
||||
app * mk_bv_xor(unsigned num, expr * const * args) { return m_manager.mk_app(get_fid(), OP_BXOR, num, args); }
|
||||
app * mk_bv_neg(expr * arg) { return m_manager.mk_app(get_fid(), OP_BNEG, arg); }
|
||||
app * mk_bv_urem(expr * arg1, expr * arg2) { return m_manager.mk_app(get_fid(), OP_BUREM, arg1, arg2); }
|
||||
app * mk_bv_srem(expr * arg1, expr * arg2) { return m_manager.mk_app(get_fid(), OP_BSREM, arg1, arg2); }
|
||||
app * mk_bv_add(expr * arg1, expr * arg2) { return m_manager.mk_app(get_fid(), OP_BADD, arg1, arg2); }
|
||||
app * mk_bv_sub(expr * arg1, expr * arg2) { return m_manager.mk_app(get_fid(), OP_BSUB, arg1, arg2); }
|
||||
app * mk_bv_mul(expr * arg1, expr * arg2) { return m_manager.mk_app(get_fid(), OP_BMUL, arg1, arg2); }
|
||||
app * mk_bv_urem(expr * arg1, expr * arg2) const { return m_manager.mk_app(get_fid(), OP_BUREM, arg1, arg2); }
|
||||
app * mk_bv_srem(expr * arg1, expr * arg2) const { return m_manager.mk_app(get_fid(), OP_BSREM, arg1, arg2); }
|
||||
app * mk_bv_add(expr * arg1, expr * arg2) const { return m_manager.mk_app(get_fid(), OP_BADD, arg1, arg2); }
|
||||
app * mk_bv_sub(expr * arg1, expr * arg2) const { return m_manager.mk_app(get_fid(), OP_BSUB, arg1, arg2); }
|
||||
app * mk_bv_mul(expr * arg1, expr * arg2) const { return m_manager.mk_app(get_fid(), OP_BMUL, arg1, arg2); }
|
||||
app * mk_zero_extend(unsigned n, expr* e) {
|
||||
parameter p(n);
|
||||
return m_manager.mk_app(get_fid(), OP_ZERO_EXT, 1, &p, 1, &e);
|
||||
|
|
|
@ -23,8 +23,21 @@ void decl_collector::visit_sort(sort * n) {
|
|||
family_id fid = n->get_family_id();
|
||||
if (m().is_uninterp(n))
|
||||
m_sorts.push_back(n);
|
||||
if (fid == m_dt_fid)
|
||||
if (fid == m_dt_fid) {
|
||||
m_sorts.push_back(n);
|
||||
|
||||
unsigned num_cnstr = m_dt_util.get_datatype_num_constructors(n);
|
||||
for (unsigned i = 0; i < num_cnstr; i++) {
|
||||
func_decl * cnstr = m_dt_util.get_datatype_constructors(n)->get(i);
|
||||
m_decls.push_back(cnstr);
|
||||
ptr_vector<func_decl> const & cnstr_acc = *m_dt_util.get_constructor_accessors(cnstr);
|
||||
unsigned num_cas = cnstr_acc.size();
|
||||
for (unsigned j = 0; j < num_cas; j++) {
|
||||
func_decl * accsr = cnstr_acc.get(j);
|
||||
m_decls.push_back(accsr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool decl_collector::is_bool(sort * s) {
|
||||
|
@ -38,14 +51,15 @@ void decl_collector::visit_func(func_decl * n) {
|
|||
m_preds.push_back(n);
|
||||
else
|
||||
m_decls.push_back(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
decl_collector::decl_collector(ast_manager & m, bool preds):
|
||||
m_manager(m),
|
||||
m_sep_preds(preds) {
|
||||
m_sep_preds(preds),
|
||||
m_dt_util(m) {
|
||||
m_basic_fid = m_manager.get_basic_family_id();
|
||||
m_dt_fid = m_manager.mk_family_id("datatype");
|
||||
m_dt_fid = m_dt_util.get_family_id();
|
||||
}
|
||||
|
||||
void decl_collector::visit(ast* n) {
|
||||
|
@ -55,7 +69,7 @@ void decl_collector::visit(ast* n) {
|
|||
n = todo.back();
|
||||
todo.pop_back();
|
||||
if (!m_visited.is_marked(n)) {
|
||||
m_visited.mark(n, true);
|
||||
m_visited.mark(n, true);
|
||||
switch(n->get_kind()) {
|
||||
case AST_APP: {
|
||||
app * a = to_app(n);
|
||||
|
@ -64,7 +78,7 @@ void decl_collector::visit(ast* n) {
|
|||
}
|
||||
todo.push_back(a->get_decl());
|
||||
break;
|
||||
}
|
||||
}
|
||||
case AST_QUANTIFIER: {
|
||||
quantifier * q = to_quantifier(n);
|
||||
unsigned num_decls = q->get_num_decls();
|
||||
|
@ -77,7 +91,7 @@ void decl_collector::visit(ast* n) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case AST_SORT:
|
||||
case AST_SORT:
|
||||
visit_sort(to_sort(n));
|
||||
break;
|
||||
case AST_FUNC_DECL: {
|
||||
|
|
|
@ -21,6 +21,7 @@ Revision History:
|
|||
#define SMT_DECL_COLLECTOR_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"datatype_decl_plugin.h"
|
||||
|
||||
class decl_collector {
|
||||
ast_manager & m_manager;
|
||||
|
@ -28,9 +29,10 @@ class decl_collector {
|
|||
ptr_vector<sort> m_sorts;
|
||||
ptr_vector<func_decl> m_decls;
|
||||
ptr_vector<func_decl> m_preds;
|
||||
ast_mark m_visited;
|
||||
family_id m_basic_fid;
|
||||
family_id m_dt_fid;
|
||||
ast_mark m_visited;
|
||||
family_id m_basic_fid;
|
||||
family_id m_dt_fid;
|
||||
datatype_util m_dt_util;
|
||||
|
||||
void visit_sort(sort* n);
|
||||
bool is_bool(sort* s);
|
||||
|
|
|
@ -19,22 +19,22 @@ Revision History:
|
|||
--*/
|
||||
#include"macro_util.h"
|
||||
#include"occurs.h"
|
||||
#include"ast_util.h"
|
||||
#include"arith_simplifier_plugin.h"
|
||||
#include"basic_simplifier_plugin.h"
|
||||
#include"bv_simplifier_plugin.h"
|
||||
#include"var_subst.h"
|
||||
#include"ast_pp.h"
|
||||
#include"ast_ll_pp.h"
|
||||
#include"ast_util.h"
|
||||
#include"for_each_expr.h"
|
||||
#include"well_sorted.h"
|
||||
#include"bool_rewriter.h"
|
||||
|
||||
macro_util::macro_util(ast_manager & m, simplifier & s):
|
||||
m_manager(m),
|
||||
m_bv(m),
|
||||
m_simplifier(s),
|
||||
m_arith_simp(0),
|
||||
m_bv_simp(0),
|
||||
m_basic_simp(0),
|
||||
m_forbidden_set(0),
|
||||
m_curr_clause(0) {
|
||||
}
|
||||
|
@ -55,24 +55,17 @@ bv_simplifier_plugin * macro_util::get_bv_simp() const {
|
|||
return m_bv_simp;
|
||||
}
|
||||
|
||||
basic_simplifier_plugin * macro_util::get_basic_simp() const {
|
||||
if (m_basic_simp == 0) {
|
||||
const_cast<macro_util*>(this)->m_basic_simp = static_cast<basic_simplifier_plugin*>(m_simplifier.get_plugin(m_manager.get_basic_family_id()));
|
||||
}
|
||||
SASSERT(m_basic_simp != 0);
|
||||
return m_basic_simp;
|
||||
}
|
||||
|
||||
bool macro_util::is_bv(expr * n) const {
|
||||
return get_bv_simp()->is_bv(n);
|
||||
return m_bv.is_bv(n);
|
||||
}
|
||||
|
||||
bool macro_util::is_bv_sort(sort * s) const {
|
||||
return get_bv_simp()->is_bv_sort(s);
|
||||
return m_bv.is_bv_sort(s);
|
||||
}
|
||||
|
||||
bool macro_util::is_add(expr * n) const {
|
||||
return get_arith_simp()->is_add(n) || get_bv_simp()->is_add(n);
|
||||
return get_arith_simp()->is_add(n) || m_bv.is_bv_add(n);
|
||||
}
|
||||
|
||||
bool macro_util::is_times_minus_one(expr * n, expr * & arg) const {
|
||||
|
@ -80,11 +73,11 @@ bool macro_util::is_times_minus_one(expr * n, expr * & arg) const {
|
|||
}
|
||||
|
||||
bool macro_util::is_le(expr * n) const {
|
||||
return get_arith_simp()->is_le(n) || get_bv_simp()->is_le(n);
|
||||
return get_arith_simp()->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) || get_bv_simp()->is_le_ge(n);
|
||||
return get_arith_simp()->is_le_ge(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 {
|
||||
|
@ -102,7 +95,7 @@ app * macro_util::mk_zero(sort * s) const {
|
|||
|
||||
void macro_util::mk_sub(expr * t1, expr * t2, expr_ref & r) const {
|
||||
if (is_bv(t1)) {
|
||||
get_bv_simp()->mk_sub(t1, t2, r);
|
||||
r = m_bv.mk_bv_sub(t1, t2);
|
||||
}
|
||||
else {
|
||||
get_arith_simp()->mk_sub(t1, t2, r);
|
||||
|
@ -111,7 +104,7 @@ void macro_util::mk_sub(expr * t1, expr * t2, expr_ref & r) const {
|
|||
|
||||
void macro_util::mk_add(expr * t1, expr * t2, expr_ref & r) const {
|
||||
if (is_bv(t1)) {
|
||||
get_bv_simp()->mk_add(t1, t2, r);
|
||||
r = m_bv.mk_bv_add(t1, t2);
|
||||
}
|
||||
else {
|
||||
get_arith_simp()->mk_add(t1, t2, r);
|
||||
|
@ -429,7 +422,7 @@ void macro_util::quasi_macro_head_to_macro_head(app * qhead, unsigned & num_decl
|
|||
new_args.push_back(new_var);
|
||||
new_conds.push_back(new_cond);
|
||||
}
|
||||
get_basic_simp()->mk_and(new_conds.size(), new_conds.c_ptr(), cond);
|
||||
bool_rewriter(m_manager).mk_and(new_conds.size(), new_conds.c_ptr(), cond);
|
||||
head = m_manager.mk_app(qhead->get_decl(), new_args.size(), new_args.c_ptr());
|
||||
num_decls = next_var_idx;
|
||||
}
|
||||
|
@ -687,7 +680,7 @@ void macro_util::insert_quasi_macro(app * head, unsigned num_decls, expr * def,
|
|||
if (cond == 0)
|
||||
new_cond = extra_cond;
|
||||
else
|
||||
get_basic_simp()->mk_and(cond, extra_cond, new_cond);
|
||||
bool_rewriter(m_manager).mk_and(cond, extra_cond, new_cond);
|
||||
}
|
||||
else {
|
||||
hint_to_macro_head(m_manager, head, num_decls, new_head);
|
||||
|
@ -719,20 +712,19 @@ void macro_util::get_rest_clause_as_cond(expr * except_lit, expr_ref & extra_con
|
|||
if (m_curr_clause == 0)
|
||||
return;
|
||||
SASSERT(is_clause(m_manager, m_curr_clause));
|
||||
basic_simplifier_plugin * bs = get_basic_simp();
|
||||
expr_ref_buffer neg_other_lits(m_manager);
|
||||
unsigned num_lits = get_clause_num_literals(m_manager, m_curr_clause);
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
expr * l = get_clause_literal(m_manager, m_curr_clause, i);
|
||||
if (l != except_lit) {
|
||||
expr_ref neg_l(m_manager);
|
||||
bs->mk_not(l, neg_l);
|
||||
bool_rewriter(m_manager).mk_not(l, neg_l);
|
||||
neg_other_lits.push_back(neg_l);
|
||||
}
|
||||
}
|
||||
if (neg_other_lits.empty())
|
||||
return;
|
||||
get_basic_simp()->mk_and(neg_other_lits.size(), neg_other_lits.c_ptr(), extra_cond);
|
||||
bool_rewriter(m_manager).mk_and(neg_other_lits.size(), neg_other_lits.c_ptr(), extra_cond);
|
||||
}
|
||||
|
||||
void macro_util::collect_poly_args(expr * n, expr * exception, ptr_buffer<expr> & args) {
|
||||
|
|
|
@ -62,10 +62,10 @@ 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;
|
||||
basic_simplifier_plugin * m_basic_simp;
|
||||
obj_hashtable<func_decl> * m_forbidden_set;
|
||||
|
||||
bool is_forbidden(func_decl * f) const { return m_forbidden_set != 0 && m_forbidden_set->contains(f); }
|
||||
|
@ -99,7 +99,6 @@ public:
|
|||
|
||||
arith_simplifier_plugin * get_arith_simp() const;
|
||||
bv_simplifier_plugin * get_bv_simp() const;
|
||||
basic_simplifier_plugin * get_basic_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;
|
||||
|
|
|
@ -28,7 +28,7 @@ struct defined_names::impl {
|
|||
typedef obj_map<expr, proof *> expr2proof;
|
||||
ast_manager & m_manager;
|
||||
symbol m_z3name;
|
||||
|
||||
|
||||
/**
|
||||
\brief Mapping from expressions to their names. A name is an application.
|
||||
If the expression does not have free variables, then the name is just a constant.
|
||||
|
@ -38,25 +38,25 @@ struct defined_names::impl {
|
|||
\brief Mapping from expressions to the apply-def proof.
|
||||
That is, for each expression e, m_expr2proof[e] is the
|
||||
proof e and m_expr2name[2] are observ. equivalent.
|
||||
|
||||
|
||||
This mapping is not used if proof production is disabled.
|
||||
*/
|
||||
expr2proof m_expr2proof;
|
||||
|
||||
|
||||
/**
|
||||
\brief Domain of m_expr2name. It is used to keep the expressions
|
||||
alive and for backtracking
|
||||
*/
|
||||
expr_ref_vector m_exprs;
|
||||
expr_ref_vector m_exprs;
|
||||
expr_ref_vector m_names; //!< Range of m_expr2name. It is used to keep the names alive.
|
||||
proof_ref_vector m_apply_proofs; //!< Range of m_expr2proof. It is used to keep the def-intro proofs alive.
|
||||
|
||||
|
||||
|
||||
|
||||
unsigned_vector m_lims; //!< Backtracking support.
|
||||
|
||||
|
||||
impl(ast_manager & m, char const * prefix);
|
||||
virtual ~impl();
|
||||
|
||||
|
||||
app * gen_name(expr * e, sort_ref_buffer & var_sorts, buffer<symbol> & var_names);
|
||||
void cache_new_name(expr * e, app * name);
|
||||
void cache_new_name_intro_proof(expr * e, proof * pr);
|
||||
|
@ -106,7 +106,7 @@ app * defined_names::impl::gen_name(expr * e, sort_ref_buffer & var_sorts, buffe
|
|||
for (unsigned i = 0; i < num_vars; i++) {
|
||||
sort * s = uv.get(i);
|
||||
if (s) {
|
||||
domain.push_back(s);
|
||||
domain.push_back(s);
|
||||
new_args.push_back(m_manager.mk_var(i, s));
|
||||
var_sorts.push_back(s);
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ void defined_names::impl::bound_vars(sort_ref_buffer const & sorts, buffer<symbo
|
|||
1, symbol::null, symbol::null,
|
||||
1, patterns);
|
||||
TRACE("mk_definition_bug", tout << "before elim_unused_vars:\n" << mk_ismt2_pp(q, m_manager) << "\n";);
|
||||
elim_unused_vars(m_manager, q, result);
|
||||
elim_unused_vars(m_manager, q, params_ref(), result);
|
||||
TRACE("mk_definition_bug", tout << "after elim_unused_vars:\n" << mk_ismt2_pp(result, m_manager) << "\n";);
|
||||
}
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ bool defined_names::impl::mk_name(expr * e, expr_ref & new_def, proof_ref & new_
|
|||
|
||||
app * n_ptr;
|
||||
if (m_expr2name.find(e, n_ptr)) {
|
||||
TRACE("mk_definition_bug", tout << "name for expression is already cached..., returning false...\n";);
|
||||
TRACE("mk_definition_bug", tout << "name for expression is already cached..., returning false...\n";);
|
||||
n = n_ptr;
|
||||
if (m_manager.proofs_enabled()) {
|
||||
proof * pr_ptr = 0;
|
||||
|
@ -220,19 +220,19 @@ bool defined_names::impl::mk_name(expr * e, expr_ref & new_def, proof_ref & new_
|
|||
else {
|
||||
sort_ref_buffer var_sorts(m_manager);
|
||||
buffer<symbol> var_names;
|
||||
|
||||
|
||||
n = gen_name(e, var_sorts, var_names);
|
||||
cache_new_name(e, n);
|
||||
|
||||
|
||||
TRACE("mk_definition_bug", tout << "name: " << mk_ismt2_pp(n, m_manager) << "\n";);
|
||||
// variables are in reverse order in quantifiers
|
||||
std::reverse(var_sorts.c_ptr(), var_sorts.c_ptr() + var_sorts.size());
|
||||
std::reverse(var_names.c_ptr(), var_names.c_ptr() + var_names.size());
|
||||
|
||||
|
||||
mk_definition(e, n, var_sorts, var_names, new_def);
|
||||
|
||||
|
||||
TRACE("mk_definition_bug", tout << "new_def:\n" << mk_ismt2_pp(new_def, m_manager) << "\n";);
|
||||
|
||||
|
||||
if (m_manager.proofs_enabled()) {
|
||||
new_def_pr = m_manager.mk_def_intro(new_def);
|
||||
pr = m_manager.mk_apply_def(e, n, new_def_pr);
|
||||
|
@ -311,11 +311,11 @@ void defined_names::reset() {
|
|||
m_pos_impl->reset();
|
||||
}
|
||||
|
||||
unsigned defined_names::get_num_names() const {
|
||||
unsigned defined_names::get_num_names() const {
|
||||
return m_impl->get_num_names() + m_pos_impl->get_num_names();
|
||||
}
|
||||
|
||||
func_decl * defined_names::get_name_decl(unsigned i) const {
|
||||
func_decl * defined_names::get_name_decl(unsigned i) const {
|
||||
SASSERT(i < get_num_names());
|
||||
unsigned n1 = m_impl->get_num_names();
|
||||
return i < n1 ? m_impl->get_name_decl(i) : m_pos_impl->get_name_decl(i - n1);
|
||||
|
|
|
@ -194,7 +194,7 @@ bool arith_rewriter::is_bound(expr * arg1, expr * arg2, op_kind kind, expr_ref &
|
|||
}
|
||||
}
|
||||
expr* t1, *t2;
|
||||
bool is_int;
|
||||
bool is_int = false;
|
||||
if (m_util.is_mod(arg2)) {
|
||||
std::swap(arg1, arg2);
|
||||
switch (kind) {
|
||||
|
|
|
@ -36,7 +36,7 @@ static bool is_neg_var(ast_manager & m, expr * e, unsigned num_decls) {
|
|||
|
||||
/**
|
||||
\brief Return true if \c e is of the form (not (= VAR t)) or (not (iff VAR t)) or (iff VAR t) or (iff (not VAR) t) or (VAR IDX) or (not (VAR IDX)).
|
||||
The last case can be viewed
|
||||
The last case can be viewed
|
||||
*/
|
||||
bool der::is_var_diseq(expr * e, unsigned num_decls, var * & v, expr_ref & t) {
|
||||
// (not (= VAR t)) and (not (iff VAR t)) cases
|
||||
|
@ -49,7 +49,7 @@ bool der::is_var_diseq(expr * e, unsigned num_decls, var * & v, expr_ref & t) {
|
|||
return false;
|
||||
if (!is_var(lhs, num_decls))
|
||||
std::swap(lhs, rhs);
|
||||
SASSERT(is_var(lhs, num_decls));
|
||||
SASSERT(is_var(lhs, num_decls));
|
||||
// Remark: Occurs check is not necessary here... the top-sort procedure will check for cycles...
|
||||
// if (occurs(lhs, rhs)) {
|
||||
// return false;
|
||||
|
@ -67,7 +67,7 @@ bool der::is_var_diseq(expr * e, unsigned num_decls, var * & v, expr_ref & t) {
|
|||
if (is_var(lhs, num_decls) || is_var(rhs, num_decls)) {
|
||||
if (!is_var(lhs, num_decls))
|
||||
std::swap(lhs, rhs);
|
||||
SASSERT(is_var(lhs, num_decls));
|
||||
SASSERT(is_var(lhs, num_decls));
|
||||
// Remark: Occurs check is not necessary here... the top-sort procedure will check for cycles...
|
||||
// if (occurs(lhs, rhs)) {
|
||||
// return false;
|
||||
|
@ -83,11 +83,11 @@ bool der::is_var_diseq(expr * e, unsigned num_decls, var * & v, expr_ref & t) {
|
|||
if (!is_neg_var(m_manager, lhs, num_decls))
|
||||
std::swap(lhs, rhs);
|
||||
SASSERT(is_neg_var(m_manager, lhs, num_decls));
|
||||
expr * lhs_var = to_app(lhs)->get_arg(0);
|
||||
expr * lhs_var = to_app(lhs)->get_arg(0);
|
||||
// Remark: Occurs check is not necessary here... the top-sort procedure will check for cycles...
|
||||
// if (occurs(lhs_var, rhs)) {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
v = to_var(lhs_var);
|
||||
t = rhs;
|
||||
TRACE("der", tout << mk_pp(e, m_manager) << "\n";);
|
||||
|
@ -134,11 +134,11 @@ void der::operator()(quantifier * q, expr_ref & r, proof_ref & pr) {
|
|||
pr = m_manager.mk_transitivity(pr, curr_pr);
|
||||
}
|
||||
} while (q != r && is_quantifier(r));
|
||||
|
||||
|
||||
// Eliminate variables that have become unused
|
||||
if (reduced && is_forall(r)) {
|
||||
quantifier * q = to_quantifier(r);
|
||||
elim_unused_vars(m_manager, q, r);
|
||||
elim_unused_vars(m_manager, q, params_ref(), r);
|
||||
if (m_manager.proofs_enabled()) {
|
||||
proof * p1 = m_manager.mk_elim_unused_vars(q, r);
|
||||
pr = m_manager.mk_transitivity(pr, p1);
|
||||
|
@ -153,24 +153,24 @@ void der::reduce1(quantifier * q, expr_ref & r, proof_ref & pr) {
|
|||
r = q;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
expr * e = q->get_expr();
|
||||
unsigned num_decls = q->get_num_decls();
|
||||
var * v = 0;
|
||||
expr_ref t(m_manager);
|
||||
expr_ref t(m_manager);
|
||||
|
||||
if (m_manager.is_or(e)) {
|
||||
unsigned num_args = to_app(e)->get_num_args();
|
||||
unsigned i = 0;
|
||||
unsigned diseq_count = 0;
|
||||
unsigned largest_vinx = 0;
|
||||
|
||||
|
||||
m_map.reset();
|
||||
m_pos2var.reset();
|
||||
m_inx2var.reset();
|
||||
|
||||
|
||||
m_pos2var.reserve(num_args, -1);
|
||||
|
||||
|
||||
// Find all disequalities
|
||||
for (; i < num_args; i++) {
|
||||
if (is_var_diseq(to_app(e)->get_arg(i), num_decls, v, t)) {
|
||||
|
@ -192,7 +192,7 @@ void der::reduce1(quantifier * q, expr_ref & r, proof_ref & pr) {
|
|||
get_elimination_order();
|
||||
SASSERT(m_order.size() <= diseq_count); // some might be missing because of cycles
|
||||
|
||||
if (!m_order.empty()) {
|
||||
if (!m_order.empty()) {
|
||||
create_substitution(largest_vinx + 1);
|
||||
apply_substitution(q, r);
|
||||
}
|
||||
|
@ -202,22 +202,22 @@ void der::reduce1(quantifier * q, expr_ref & r, proof_ref & pr) {
|
|||
r = q;
|
||||
}
|
||||
}
|
||||
// Remark: get_elimination_order/top-sort checks for cycles, but it is not invoked for unit clauses.
|
||||
// Remark: get_elimination_order/top-sort checks for cycles, but it is not invoked for unit clauses.
|
||||
// So, we must perform a occurs check here.
|
||||
else if (is_var_diseq(e, num_decls, v, t) && !occurs(v, t)) {
|
||||
r = m_manager.mk_false();
|
||||
}
|
||||
else
|
||||
else
|
||||
r = q;
|
||||
|
||||
|
||||
if (m_manager.proofs_enabled()) {
|
||||
pr = r == q ? 0 : m_manager.mk_der(q, r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void der_sort_vars(ptr_vector<var> & vars, ptr_vector<expr> & definitions, unsigned_vector & order) {
|
||||
order.reset();
|
||||
|
||||
|
||||
// eliminate self loops, and definitions containing quantifiers.
|
||||
bool found = false;
|
||||
for (unsigned i = 0; i < definitions.size(); i++) {
|
||||
|
@ -228,7 +228,7 @@ void der_sort_vars(ptr_vector<var> & vars, ptr_vector<expr> & definitions, unsig
|
|||
else
|
||||
found = true; // found at least one candidate
|
||||
}
|
||||
|
||||
|
||||
if (!found)
|
||||
return;
|
||||
|
||||
|
@ -329,14 +329,14 @@ void der::get_elimination_order() {
|
|||
// der::top_sort ts(m_manager);
|
||||
der_sort_vars(m_inx2var, m_map, m_order);
|
||||
|
||||
TRACE("der",
|
||||
TRACE("der",
|
||||
tout << "Elimination m_order:" << std::endl;
|
||||
for(unsigned i=0; i<m_order.size(); i++)
|
||||
{
|
||||
if (i != 0) tout << ",";
|
||||
tout << m_order[i];
|
||||
}
|
||||
tout << std::endl;
|
||||
tout << std::endl;
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -359,24 +359,24 @@ void der::create_substitution(unsigned sz) {
|
|||
|
||||
void der::apply_substitution(quantifier * q, expr_ref & r) {
|
||||
expr * e = q->get_expr();
|
||||
unsigned num_args=to_app(e)->get_num_args();
|
||||
|
||||
unsigned num_args=to_app(e)->get_num_args();
|
||||
|
||||
// get a new expression
|
||||
m_new_args.reset();
|
||||
for(unsigned i = 0; i < num_args; i++) {
|
||||
int x = m_pos2var[i];
|
||||
if (x != -1 && m_map[x] != 0)
|
||||
if (x != -1 && m_map[x] != 0)
|
||||
continue; // this is a disequality with definition (vanishes)
|
||||
|
||||
|
||||
m_new_args.push_back(to_app(e)->get_arg(i));
|
||||
}
|
||||
|
||||
unsigned sz = m_new_args.size();
|
||||
expr_ref t(m_manager);
|
||||
t = (sz == 1) ? m_new_args[0] : m_manager.mk_or(sz, m_new_args.c_ptr());
|
||||
expr_ref new_e(m_manager);
|
||||
expr_ref new_e(m_manager);
|
||||
m_subst(t, m_subst_map.size(), m_subst_map.c_ptr(), new_e);
|
||||
|
||||
|
||||
// don't forget to update the quantifier patterns
|
||||
expr_ref_buffer new_patterns(m_manager);
|
||||
expr_ref_buffer new_no_patterns(m_manager);
|
||||
|
@ -392,7 +392,7 @@ void der::apply_substitution(quantifier * q, expr_ref & r) {
|
|||
new_no_patterns.push_back(new_nopat);
|
||||
}
|
||||
|
||||
r = m_manager.update_quantifier(q, new_patterns.size(), new_patterns.c_ptr(),
|
||||
r = m_manager.update_quantifier(q, new_patterns.size(), new_patterns.c_ptr(),
|
||||
new_no_patterns.size(), new_no_patterns.c_ptr(), new_e);
|
||||
}
|
||||
|
||||
|
@ -404,9 +404,9 @@ struct der_rewriter_cfg : public default_rewriter_cfg {
|
|||
|
||||
ast_manager & m() const { return m_der.m(); }
|
||||
|
||||
bool reduce_quantifier(quantifier * old_q,
|
||||
expr * new_body,
|
||||
expr * const * new_patterns,
|
||||
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) {
|
||||
|
|
|
@ -315,6 +315,8 @@ protected:
|
|||
template<bool ProofGen>
|
||||
void process_app(app * t, frame & fr);
|
||||
|
||||
bool constant_fold(app* t, frame& fr);
|
||||
|
||||
template<bool ProofGen>
|
||||
void process_quantifier(quantifier * q, frame & fr);
|
||||
|
||||
|
|
|
@ -174,6 +174,37 @@ bool rewriter_tpl<Config>::visit(expr * t, unsigned max_depth) {
|
|||
}
|
||||
}
|
||||
|
||||
template<typename Config>
|
||||
bool rewriter_tpl<Config>::constant_fold(app * t, frame & fr) {
|
||||
if (fr.m_i == 1 && m().is_ite(t)) {
|
||||
expr * cond = result_stack()[fr.m_spos].get();
|
||||
expr* arg = 0;
|
||||
if (m().is_true(cond)) {
|
||||
arg = t->get_arg(1);
|
||||
}
|
||||
else if (m().is_false(cond)) {
|
||||
arg = t->get_arg(2);
|
||||
}
|
||||
if (arg) {
|
||||
result_stack().shrink(fr.m_spos);
|
||||
result_stack().push_back(arg);
|
||||
fr.m_state = REWRITE_BUILTIN;
|
||||
if (visit<false>(arg, fr.m_max_depth)) {
|
||||
m_r = result_stack().back();
|
||||
result_stack().pop_back();
|
||||
result_stack().pop_back();
|
||||
result_stack().push_back(m_r);
|
||||
cache_result<false>(t, m_r, m_pr, fr.m_cache_result);
|
||||
frame_stack().pop_back();
|
||||
set_new_child_flag(t);
|
||||
}
|
||||
m_r = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename Config>
|
||||
template<bool ProofGen>
|
||||
void rewriter_tpl<Config>::process_app(app * t, frame & fr) {
|
||||
|
@ -183,16 +214,10 @@ void rewriter_tpl<Config>::process_app(app * t, frame & fr) {
|
|||
case PROCESS_CHILDREN: {
|
||||
unsigned num_args = t->get_num_args();
|
||||
while (fr.m_i < num_args) {
|
||||
expr * arg = t->get_arg(fr.m_i);
|
||||
if (fr.m_i >= 1 && m().is_ite(t) && !ProofGen) {
|
||||
expr * cond = result_stack()[fr.m_spos].get();
|
||||
if (m().is_true(cond)) {
|
||||
arg = t->get_arg(1);
|
||||
}
|
||||
else if (m().is_false(cond)) {
|
||||
arg = t->get_arg(2);
|
||||
}
|
||||
if (!ProofGen && constant_fold(t, fr)) {
|
||||
return;
|
||||
}
|
||||
expr * arg = t->get_arg(fr.m_i);
|
||||
fr.m_i++;
|
||||
if (!visit<ProofGen>(arg, fr.m_max_depth))
|
||||
return;
|
||||
|
|
|
@ -8,5 +8,6 @@ def_module_params('rewriter',
|
|||
("push_ite_bv", BOOL, False, "push if-then-else over bit-vector terms."),
|
||||
("pull_cheap_ite", BOOL, False, "pull if-then-else terms when cheap."),
|
||||
("bv_ineq_consistency_test_max", UINT, 0, "max size of conjunctions on which to perform consistency test based on inequalities on bitvectors."),
|
||||
("cache_all", BOOL, False, "cache all intermediate results.")))
|
||||
("cache_all", BOOL, False, "cache all intermediate results."),
|
||||
("ignore_patterns_on_ground_qbody", BOOL, True, "ignores patterns on quantifiers that don't mention their bound variables.")))
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ Abstract:
|
|||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2015-12-5
|
||||
Murphy Berzish 2017-02-21
|
||||
|
||||
Notes:
|
||||
|
||||
|
@ -59,7 +60,12 @@ expr_ref sym_expr::accept(expr* e) {
|
|||
}
|
||||
|
||||
std::ostream& sym_expr::display(std::ostream& out) const {
|
||||
return out << m_t;
|
||||
switch (m_ty) {
|
||||
case t_char: return out << m_t;
|
||||
case t_range: return out << m_t << ":" << m_s;
|
||||
case t_pred: return out << m_t;
|
||||
}
|
||||
return out << "expression type not recognized";
|
||||
}
|
||||
|
||||
struct display_expr1 {
|
||||
|
@ -236,6 +242,7 @@ eautomaton* re2automaton::re2aut(expr* e) {
|
|||
unsigned nb = s1.num_bits();
|
||||
expr_ref _start(bv.mk_numeral(start, nb), m);
|
||||
expr_ref _stop(bv.mk_numeral(stop, nb), m);
|
||||
TRACE("seq", tout << "Range: " << start << " " << stop << "\n";);
|
||||
a = alloc(eautomaton, sm, sym_expr::mk_range(_start, _stop));
|
||||
return a.detach();
|
||||
}
|
||||
|
@ -509,15 +516,66 @@ br_status seq_rewriter::mk_seq_length(expr* a, expr_ref& result) {
|
|||
br_status seq_rewriter::mk_seq_extract(expr* a, expr* b, expr* c, expr_ref& result) {
|
||||
zstring s;
|
||||
rational pos, len;
|
||||
if (m_util.str.is_string(a, s) && m_autil.is_numeral(b, pos) && m_autil.is_numeral(c, len) &&
|
||||
pos.is_unsigned() && len.is_unsigned() && pos.get_unsigned() + len.get_unsigned() <= s.length()) {
|
||||
unsigned _pos = pos.get_unsigned();
|
||||
unsigned _len = len.get_unsigned();
|
||||
result = m_util.str.mk_string(s.extract(_pos, _len));
|
||||
|
||||
bool constantBase = m_util.str.is_string(a, s);
|
||||
bool constantPos = m_autil.is_numeral(b, pos);
|
||||
bool constantLen = m_autil.is_numeral(c, len);
|
||||
|
||||
// case 1: pos<0 or len<=0
|
||||
// rewrite to ""
|
||||
if ( (constantPos && pos.is_neg()) || (constantLen && !len.is_pos()) ) {
|
||||
result = m_util.str.mk_empty(m().get_sort(a));
|
||||
return BR_DONE;
|
||||
}
|
||||
// case 1.1: pos >= length(base)
|
||||
// rewrite to ""
|
||||
if (constantBase && constantPos && pos >= rational(s.length())) {
|
||||
result = m_util.str.mk_empty(m().get_sort(a));
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
constantPos &= pos.is_unsigned();
|
||||
constantLen &= len.is_unsigned();
|
||||
|
||||
if (constantBase && constantPos && constantLen) {
|
||||
if (pos.get_unsigned() + len.get_unsigned() >= s.length()) {
|
||||
// case 2: pos+len goes past the end of the string
|
||||
unsigned _len = s.length() - pos.get_unsigned() + 1;
|
||||
result = m_util.str.mk_string(s.extract(pos.get_unsigned(), _len));
|
||||
} else {
|
||||
// case 3: pos+len still within string
|
||||
result = m_util.str.mk_string(s.extract(pos.get_unsigned(), len.get_unsigned()));
|
||||
}
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
if (constantPos && constantLen) {
|
||||
unsigned _pos = pos.get_unsigned();
|
||||
unsigned _len = len.get_unsigned();
|
||||
SASSERT(_len > 0);
|
||||
expr_ref_vector as(m()), bs(m());
|
||||
m_util.str.get_concat(a, as);
|
||||
for (unsigned i = 0; i < as.size() && _len > 0; ++i) {
|
||||
if (m_util.str.is_unit(as[i].get())) {
|
||||
if (_pos == 0) {
|
||||
bs.push_back(as[i].get());
|
||||
--_len;
|
||||
}
|
||||
else {
|
||||
--_pos;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return BR_FAILED;
|
||||
}
|
||||
}
|
||||
result = m_util.str.mk_concat(bs);
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status seq_rewriter::mk_seq_contains(expr* a, expr* b, expr_ref& result) {
|
||||
zstring c, d;
|
||||
if (m_util.str.is_string(a, c) && m_util.str.is_string(b, d)) {
|
||||
|
@ -594,19 +652,77 @@ br_status seq_rewriter::mk_seq_contains(expr* a, expr* b, expr_ref& result) {
|
|||
result = m().mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
bool all_units = true;
|
||||
for (unsigned i = 0; i < bs.size(); ++i) {
|
||||
all_units = m_util.str.is_unit(bs[i].get());
|
||||
}
|
||||
for (unsigned i = 0; i < as.size(); ++i) {
|
||||
all_units = m_util.str.is_unit(as[i].get());
|
||||
}
|
||||
if (all_units) {
|
||||
if (as.size() < bs.size()) {
|
||||
result = m().mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
expr_ref_vector ors(m());
|
||||
for (unsigned i = 0; i < as.size() - bs.size() + 1; ++i) {
|
||||
expr_ref_vector ands(m());
|
||||
for (unsigned j = 0; j < bs.size(); ++j) {
|
||||
ands.push_back(m().mk_eq(as[i + j].get(), bs[j].get()));
|
||||
}
|
||||
ors.push_back(::mk_and(ands));
|
||||
}
|
||||
result = ::mk_or(ors);
|
||||
return BR_REWRITE_FULL;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
/*
|
||||
* (str.at s i), constants s/i, i < 0 or i >= |s| ==> (str.at s i) = ""
|
||||
*/
|
||||
br_status seq_rewriter::mk_seq_at(expr* a, expr* b, expr_ref& result) {
|
||||
zstring c;
|
||||
rational r;
|
||||
if (m_util.str.is_string(a, c) && m_autil.is_numeral(b, r) && r.is_unsigned()) {
|
||||
unsigned j = r.get_unsigned();
|
||||
if (j < c.length()) {
|
||||
result = m_util.str.mk_string(c.extract(j, 1));
|
||||
if (m_autil.is_numeral(b, r)) {
|
||||
if (r.is_neg()) {
|
||||
result = m_util.str.mk_empty(m().get_sort(a));
|
||||
return BR_DONE;
|
||||
}
|
||||
unsigned len = 0;
|
||||
bool bounded = min_length(1, &a, len);
|
||||
if (bounded && r >= rational(len)) {
|
||||
result = m_util.str.mk_empty(m().get_sort(a));
|
||||
return BR_DONE;
|
||||
}
|
||||
if (m_util.str.is_string(a, c)) {
|
||||
if (r.is_unsigned() && r < rational(c.length())) {
|
||||
result = m_util.str.mk_string(c.extract(r.get_unsigned(), 1));
|
||||
}
|
||||
else {
|
||||
result = m_util.str.mk_empty(m().get_sort(a));
|
||||
}
|
||||
return BR_DONE;
|
||||
}
|
||||
if (r.is_unsigned()) {
|
||||
len = r.get_unsigned();
|
||||
expr_ref_vector as(m());
|
||||
m_util.str.get_concat(a, as);
|
||||
for (unsigned i = 0; i < as.size(); ++i) {
|
||||
if (m_util.str.is_unit(as[i].get())) {
|
||||
if (len == 0) {
|
||||
result = as[i].get();
|
||||
return BR_DONE;
|
||||
}
|
||||
--len;
|
||||
}
|
||||
else {
|
||||
return BR_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
@ -664,6 +780,7 @@ br_status seq_rewriter::mk_seq_prefix(expr* a, expr* b, expr_ref& result) {
|
|||
bool isc2 = m_util.str.is_string(b, s2);
|
||||
if (isc1 && isc2) {
|
||||
result = m().mk_bool_val(s1.prefixof(s2));
|
||||
TRACE("seq", tout << result << "\n";);
|
||||
return BR_DONE;
|
||||
}
|
||||
if (m_util.str.is_empty(a)) {
|
||||
|
@ -677,6 +794,7 @@ br_status seq_rewriter::mk_seq_prefix(expr* a, expr* b, expr_ref& result) {
|
|||
expr_ref_vector as(m()), bs(m());
|
||||
|
||||
if (a1 != b1 && isc1 && isc2) {
|
||||
TRACE("seq", tout << s1 << " " << s2 << "\n";);
|
||||
if (s1.length() <= s2.length()) {
|
||||
if (s1.prefixof(s2)) {
|
||||
if (a == a1) {
|
||||
|
@ -721,26 +839,27 @@ br_status seq_rewriter::mk_seq_prefix(expr* a, expr* b, expr_ref& result) {
|
|||
m_util.str.get_concat(a, as);
|
||||
m_util.str.get_concat(b, bs);
|
||||
unsigned i = 0;
|
||||
bool all_values = true;
|
||||
expr_ref_vector eqs(m());
|
||||
for (; i < as.size() && i < bs.size(); ++i) {
|
||||
expr* a = as[i].get(), *b = bs[i].get();
|
||||
if (a == b) {
|
||||
continue;
|
||||
}
|
||||
all_values &= m().is_value(a) && m().is_value(b);
|
||||
if (all_values) {
|
||||
result = m().mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
if (m_util.str.is_unit(a) && m_util.str.is_unit(b)) {
|
||||
eqs.push_back(m().mk_eq(a, b));
|
||||
continue;
|
||||
}
|
||||
if (m().is_value(a) && m().is_value(b) && m_util.str.is_string(a) && m_util.str.is_string(b)) {
|
||||
TRACE("seq", tout << mk_pp(a, m()) << " != " << mk_pp(b, m()) << "\n";);
|
||||
result = m().mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
if (i == as.size()) {
|
||||
result = mk_and(eqs);
|
||||
TRACE("seq", tout << result << "\n";);
|
||||
if (m().is_true(result)) {
|
||||
return BR_DONE;
|
||||
}
|
||||
|
@ -752,6 +871,7 @@ br_status seq_rewriter::mk_seq_prefix(expr* a, expr* b, expr_ref& result) {
|
|||
eqs.push_back(m().mk_eq(m_util.str.mk_empty(m().get_sort(a)), as[j].get()));
|
||||
}
|
||||
result = mk_and(eqs);
|
||||
TRACE("seq", tout << result << "\n";);
|
||||
return BR_REWRITE3;
|
||||
}
|
||||
if (i > 0) {
|
||||
|
@ -759,6 +879,7 @@ br_status seq_rewriter::mk_seq_prefix(expr* a, expr* b, expr_ref& result) {
|
|||
a = m_util.str.mk_concat(as.size() - i, as.c_ptr() + i);
|
||||
b = m_util.str.mk_concat(bs.size() - i, bs.c_ptr() + i);
|
||||
result = m_util.str.mk_prefix(a, b);
|
||||
TRACE("seq", tout << result << "\n";);
|
||||
return BR_DONE;
|
||||
}
|
||||
else {
|
||||
|
@ -1343,6 +1464,7 @@ bool seq_rewriter::reduce_eq(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_
|
|||
zstring s;
|
||||
bool lchange = false;
|
||||
SASSERT(lhs.empty());
|
||||
TRACE("seq", tout << ls << "\n"; tout << rs << "\n";);
|
||||
// solve from back
|
||||
while (true) {
|
||||
while (!rs.empty() && m_util.str.is_empty(rs.back())) {
|
||||
|
@ -1460,9 +1582,11 @@ bool seq_rewriter::reduce_eq(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_
|
|||
head2 < rs.size() &&
|
||||
m_util.str.is_string(ls[head1].get(), s1) &&
|
||||
m_util.str.is_string(rs[head2].get(), s2)) {
|
||||
TRACE("seq", tout << s1 << " - " << s2 << " " << s1.length() << " " << s2.length() << "\n";);
|
||||
unsigned l = std::min(s1.length(), s2.length());
|
||||
for (unsigned i = 0; i < l; ++i) {
|
||||
if (s1[i] != s2[i]) {
|
||||
TRACE("seq", tout << "different at position " << i << " " << s1[i] << " " << s2[i] << "\n";);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
bool m_cache_all;
|
||||
bool m_push_ite_arith;
|
||||
bool m_push_ite_bv;
|
||||
bool m_ignore_patterns_on_ground_qbody;
|
||||
|
||||
// substitution support
|
||||
expr_dependency_ref m_used_dependencies; // set of dependencies of used substitutions
|
||||
|
@ -70,8 +71,9 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
m_cache_all = p.cache_all();
|
||||
m_push_ite_arith = p.push_ite_arith();
|
||||
m_push_ite_bv = p.push_ite_bv();
|
||||
m_ignore_patterns_on_ground_qbody = p.ignore_patterns_on_ground_qbody();
|
||||
}
|
||||
|
||||
|
||||
void updt_params(params_ref const & p) {
|
||||
m_b_rw.updt_params(p);
|
||||
m_a_rw.updt_params(p);
|
||||
|
@ -82,7 +84,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
updt_local_params(p);
|
||||
}
|
||||
|
||||
bool flat_assoc(func_decl * f) const {
|
||||
bool flat_assoc(func_decl * f) const {
|
||||
if (!m_flat) return false;
|
||||
family_id fid = f->get_family_id();
|
||||
if (fid == null_family_id)
|
||||
|
@ -98,10 +100,10 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
}
|
||||
|
||||
bool rewrite_patterns() const { return false; }
|
||||
|
||||
|
||||
bool cache_all_results() const { return m_cache_all; }
|
||||
|
||||
bool max_steps_exceeded(unsigned num_steps) const {
|
||||
bool max_steps_exceeded(unsigned num_steps) const {
|
||||
cooperate("simplifier");
|
||||
if (memory::get_allocation_size() > m_max_memory)
|
||||
throw rewriter_exception(Z3_MAX_MEMORY_MSG);
|
||||
|
@ -179,13 +181,13 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
st = m_ar_rw.mk_eq_core(args[0], args[1], result);
|
||||
else if (s_fid == m_seq_rw.get_fid())
|
||||
st = m_seq_rw.mk_eq_core(args[0], args[1], result);
|
||||
|
||||
|
||||
if (st != BR_FAILED)
|
||||
return st;
|
||||
}
|
||||
if (k == OP_EQ || k == OP_IFF) {
|
||||
SASSERT(num == 2);
|
||||
st = apply_tamagotchi(args[0], args[1], result);
|
||||
st = apply_tamagotchi(args[0], args[1], result);
|
||||
if (st != BR_FAILED)
|
||||
return st;
|
||||
}
|
||||
|
@ -239,13 +241,13 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
}
|
||||
else {
|
||||
if (SWAP) {
|
||||
result = m().mk_ite(ite->get_arg(0),
|
||||
result = m().mk_ite(ite->get_arg(0),
|
||||
m().mk_app(p, value, ite->get_arg(1)),
|
||||
m().mk_app(p, value, ite->get_arg(2)));
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
else {
|
||||
result = m().mk_ite(ite->get_arg(0),
|
||||
result = m().mk_ite(ite->get_arg(0),
|
||||
m().mk_app(p, ite->get_arg(1), value),
|
||||
m().mk_app(p, ite->get_arg(2), value));
|
||||
return BR_REWRITE2;
|
||||
|
@ -257,7 +259,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
// ite-value-tree := (ite c <subtree> <subtree>)
|
||||
// subtree := value
|
||||
// | (ite c <subtree> <subtree>)
|
||||
//
|
||||
//
|
||||
bool is_ite_value_tree(expr * t) {
|
||||
if (!m().is_ite(t))
|
||||
return false;
|
||||
|
@ -281,7 +283,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
br_status pull_ite(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
if (num == 2 && m().is_bool(f->get_range()) && !m().is_bool(args[0])) {
|
||||
if (m().is_ite(args[0])) {
|
||||
|
@ -325,7 +327,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
if (!is_app(t))
|
||||
return false;
|
||||
family_id fid = to_app(t)->get_family_id();
|
||||
return ((fid == m_a_rw.get_fid() && m_push_ite_arith) ||
|
||||
return ((fid == m_a_rw.get_fid() && m_push_ite_arith) ||
|
||||
(fid == m_bv_rw.get_fid() && m_push_ite_bv));
|
||||
}
|
||||
|
||||
|
@ -349,7 +351,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Try to "unify" t1 and t2
|
||||
Examples
|
||||
|
@ -463,7 +465,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
}
|
||||
// terms matched...
|
||||
bool is_int = m_a_util.is_int(t1);
|
||||
if (!new_t1)
|
||||
if (!new_t1)
|
||||
new_t1 = m_a_util.mk_numeral(rational(0), is_int);
|
||||
if (!new_t2)
|
||||
new_t2 = m_a_util.mk_numeral(rational(0), is_int);
|
||||
|
@ -476,7 +478,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
args.push_back(arg);
|
||||
}
|
||||
SASSERT(!args.empty());
|
||||
if (args.size() == 1)
|
||||
if (args.size() == 1)
|
||||
c = args[0];
|
||||
else
|
||||
c = m_a_util.mk_add(args.size(), args.c_ptr());
|
||||
|
@ -518,7 +520,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
|
||||
// Apply transformations of the form
|
||||
//
|
||||
// (ite c (+ k1 a) (+ k2 a)) --> (+ (ite c k1 k2) a)
|
||||
// (ite c (+ k1 a) (+ k2 a)) --> (+ (ite c k1 k2) a)
|
||||
// (ite c (* k1 a) (* k2 a)) --> (* (ite c k1 k2) a)
|
||||
//
|
||||
// These transformations are useful for bit-vector problems, since
|
||||
|
@ -536,7 +538,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
if (unify(t, e, f_prime, new_t, new_e, common, first)) {
|
||||
if (first)
|
||||
result = m().mk_app(f_prime, common, m().mk_ite(c, new_t, new_e));
|
||||
else
|
||||
else
|
||||
result = m().mk_app(f_prime, m().mk_ite(c, new_t, new_e), common);
|
||||
return BR_DONE;
|
||||
}
|
||||
|
@ -558,7 +560,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
result_pr = 0;
|
||||
br_status st = reduce_app_core(f, num, args, result);
|
||||
if (st != BR_DONE && st != BR_FAILED) {
|
||||
CTRACE("th_rewriter_step", st != BR_FAILED,
|
||||
CTRACE("th_rewriter_step", st != BR_FAILED,
|
||||
tout << f->get_name() << "\n";
|
||||
for (unsigned i = 0; i < num; i++) tout << mk_ismt2_pp(args[i], m()) << "\n";
|
||||
tout << "---------->\n" << mk_ismt2_pp(result, m()) << "\n";);
|
||||
|
@ -576,7 +578,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
else
|
||||
st = pull_ite(result);
|
||||
}
|
||||
CTRACE("th_rewriter_step", st != BR_FAILED,
|
||||
CTRACE("th_rewriter_step", st != BR_FAILED,
|
||||
tout << f->get_name() << "\n";
|
||||
for (unsigned i = 0; i < num; i++) tout << mk_ismt2_pp(args[i], m()) << "\n";
|
||||
tout << "---------->\n" << mk_ismt2_pp(result, m()) << "\n";);
|
||||
|
@ -593,28 +595,28 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
}
|
||||
|
||||
|
||||
bool reduce_quantifier(quantifier * old_q,
|
||||
expr * new_body,
|
||||
expr * const * new_patterns,
|
||||
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) {
|
||||
quantifier_ref q1(m());
|
||||
proof * p1 = 0;
|
||||
if (is_quantifier(new_body) &&
|
||||
if (is_quantifier(new_body) &&
|
||||
to_quantifier(new_body)->is_forall() == old_q->is_forall() &&
|
||||
!old_q->has_patterns() &&
|
||||
!to_quantifier(new_body)->has_patterns()) {
|
||||
|
||||
|
||||
quantifier * nested_q = to_quantifier(new_body);
|
||||
|
||||
|
||||
ptr_buffer<sort> sorts;
|
||||
buffer<symbol> names;
|
||||
buffer<symbol> names;
|
||||
sorts.append(old_q->get_num_decls(), old_q->get_decl_sorts());
|
||||
names.append(old_q->get_num_decls(), old_q->get_decl_names());
|
||||
sorts.append(nested_q->get_num_decls(), nested_q->get_decl_sorts());
|
||||
names.append(nested_q->get_num_decls(), nested_q->get_decl_names());
|
||||
|
||||
|
||||
q1 = m().mk_quantifier(old_q->is_forall(),
|
||||
sorts.size(),
|
||||
sorts.c_ptr(),
|
||||
|
@ -624,9 +626,9 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
old_q->get_qid(),
|
||||
old_q->get_skid(),
|
||||
0, 0, 0, 0);
|
||||
|
||||
|
||||
SASSERT(is_well_sorted(m(), q1));
|
||||
|
||||
|
||||
if (m().proofs_enabled()) {
|
||||
SASSERT(old_q->get_expr() == new_body);
|
||||
p1 = m().mk_pull_quant(old_q, q1);
|
||||
|
@ -635,24 +637,24 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
else {
|
||||
ptr_buffer<expr> new_patterns_buf;
|
||||
ptr_buffer<expr> new_no_patterns_buf;
|
||||
|
||||
|
||||
new_patterns_buf.append(old_q->get_num_patterns(), new_patterns);
|
||||
new_no_patterns_buf.append(old_q->get_num_no_patterns(), new_no_patterns);
|
||||
|
||||
remove_duplicates(new_patterns_buf);
|
||||
remove_duplicates(new_no_patterns_buf);
|
||||
|
||||
q1 = m().update_quantifier(old_q,
|
||||
|
||||
q1 = m().update_quantifier(old_q,
|
||||
new_patterns_buf.size(), new_patterns_buf.c_ptr(), new_no_patterns_buf.size(), new_no_patterns_buf.c_ptr(),
|
||||
new_body);
|
||||
TRACE("reduce_quantifier", tout << mk_ismt2_pp(old_q, m()) << "\n----->\n" << mk_ismt2_pp(q1, m()) << "\n";);
|
||||
SASSERT(is_well_sorted(m(), q1));
|
||||
}
|
||||
|
||||
elim_unused_vars(m(), q1, result);
|
||||
|
||||
elim_unused_vars(m(), q1, params_ref(), result);
|
||||
|
||||
TRACE("reduce_quantifier", tout << "after elim_unused_vars:\n" << mk_ismt2_pp(result, m()) << "\n";);
|
||||
|
||||
|
||||
result_pr = 0;
|
||||
if (m().proofs_enabled()) {
|
||||
proof * p2 = 0;
|
||||
|
@ -758,7 +760,7 @@ unsigned th_rewriter::get_num_steps() const {
|
|||
void th_rewriter::cleanup() {
|
||||
ast_manager & m = m_imp->m();
|
||||
dealloc(m_imp);
|
||||
m_imp = alloc(imp, m, m_params);
|
||||
m_imp = alloc(imp, m, m_params);
|
||||
}
|
||||
|
||||
void th_rewriter::reset() {
|
||||
|
|
|
@ -39,10 +39,16 @@ void var_subst::operator()(expr * n, unsigned num_args, expr * const * args, exp
|
|||
tout << mk_ismt2_pp(result, m_reducer.m()) << "\n";);
|
||||
}
|
||||
|
||||
unused_vars_eliminator::unused_vars_eliminator(ast_manager & m, params_ref const & params) :
|
||||
m(m), m_subst(m), m_params(params)
|
||||
{
|
||||
m_ignore_patterns_on_ground_qbody = m_params.get_bool("ignore_patterns_on_ground_qbody", true);
|
||||
}
|
||||
|
||||
void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
|
||||
SASSERT(is_well_sorted(m, q));
|
||||
if (is_ground(q->get_expr())) {
|
||||
// ignore patterns if the body is a ground formula.
|
||||
if (m_ignore_patterns_on_ground_qbody && is_ground(q->get_expr())) {
|
||||
// Ignore patterns if the body is a ground formula.
|
||||
result = q->get_expr();
|
||||
return;
|
||||
}
|
||||
|
@ -146,8 +152,8 @@ void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
|
|||
SASSERT(is_well_sorted(m, result));
|
||||
}
|
||||
|
||||
void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
|
||||
unused_vars_eliminator el(m);
|
||||
void elim_unused_vars(ast_manager & m, quantifier * q, params_ref const & params, expr_ref & result) {
|
||||
unused_vars_eliminator el(m, params);
|
||||
el(q, result);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ Notes:
|
|||
|
||||
#include"rewriter.h"
|
||||
#include"used_vars.h"
|
||||
#include"params.h"
|
||||
|
||||
/**
|
||||
\brief Alias for var_shifter class.
|
||||
|
@ -31,7 +32,7 @@ typedef var_shifter shift_vars;
|
|||
\brief Variable substitution functor. It substitutes variables by expressions.
|
||||
The expressions may contain variables.
|
||||
*/
|
||||
class var_subst {
|
||||
class var_subst {
|
||||
beta_reducer m_reducer;
|
||||
bool m_std_order;
|
||||
public:
|
||||
|
@ -39,7 +40,7 @@ public:
|
|||
bool std_order() const { return m_std_order; }
|
||||
|
||||
/**
|
||||
When std_order() == true,
|
||||
When std_order() == true,
|
||||
I'm using the same standard used in quantifier instantiation.
|
||||
(VAR 0) is stored in the last position of the array.
|
||||
...
|
||||
|
@ -55,15 +56,17 @@ public:
|
|||
\brief Eliminate the unused variables from \c q. Store the result in \c r.
|
||||
*/
|
||||
class unused_vars_eliminator {
|
||||
ast_manager& m;
|
||||
var_subst m_subst;
|
||||
used_vars m_used;
|
||||
ast_manager & m;
|
||||
var_subst m_subst;
|
||||
used_vars m_used;
|
||||
params_ref m_params;
|
||||
bool m_ignore_patterns_on_ground_qbody;
|
||||
public:
|
||||
unused_vars_eliminator(ast_manager& m): m(m), m_subst(m) {}
|
||||
unused_vars_eliminator(ast_manager & m, params_ref const & params);
|
||||
void operator()(quantifier* q, expr_ref& r);
|
||||
};
|
||||
|
||||
void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & r);
|
||||
void elim_unused_vars(ast_manager & m, quantifier * q, params_ref const & params, expr_ref & r);
|
||||
|
||||
/**
|
||||
\brief Instantiate quantifier q using the given exprs.
|
||||
|
@ -86,7 +89,7 @@ class expr_free_vars {
|
|||
expr_sparse_mark m_mark;
|
||||
ptr_vector<sort> m_sorts;
|
||||
ptr_vector<expr> m_todo;
|
||||
public:
|
||||
public:
|
||||
void reset();
|
||||
void operator()(expr* e);
|
||||
void accumulate(expr* e);
|
||||
|
@ -96,7 +99,7 @@ public:
|
|||
bool contains(unsigned idx) const { return idx < m_sorts.size() && m_sorts[idx] != 0; }
|
||||
void set_default_sort(sort* s);
|
||||
void reverse() { m_sorts.reverse(); }
|
||||
sort*const* c_ptr() const { return m_sorts.c_ptr(); }
|
||||
sort*const* c_ptr() const { return m_sorts.c_ptr(); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -126,13 +126,14 @@ static bool is_escape_char(char const *& s, unsigned& result) {
|
|||
zstring::zstring(encoding enc): m_encoding(enc) {}
|
||||
|
||||
zstring::zstring(char const* s, encoding enc): m_encoding(enc) {
|
||||
unsigned mask = 0xFF; // TBD for UTF
|
||||
while (*s) {
|
||||
unsigned ch;
|
||||
if (is_escape_char(s, ch)) {
|
||||
m_buffer.push_back(ch);
|
||||
m_buffer.push_back(ch & mask);
|
||||
}
|
||||
else {
|
||||
m_buffer.push_back(*s);
|
||||
m_buffer.push_back(*s & mask);
|
||||
++s;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -304,6 +304,7 @@ public:
|
|||
|
||||
app* mk_to_re(expr* s) { return m.mk_app(m_fid, OP_SEQ_TO_RE, 1, &s); }
|
||||
app* mk_in_re(expr* s, expr* r) { return m.mk_app(m_fid, OP_SEQ_IN_RE, s, r); }
|
||||
app* mk_range(expr* s1, expr* s2) { return m.mk_app(m_fid, OP_RE_RANGE, s1, s2); }
|
||||
app* mk_concat(expr* r1, expr* r2) { return m.mk_app(m_fid, OP_RE_CONCAT, r1, r2); }
|
||||
app* mk_union(expr* r1, expr* r2) { return m.mk_app(m_fid, OP_RE_UNION, r1, r2); }
|
||||
app* mk_inter(expr* r1, expr* r2) { return m.mk_app(m_fid, OP_RE_INTERSECT, r1, r2); }
|
||||
|
|
|
@ -1517,13 +1517,24 @@ void bv_simplifier_plugin::mk_bv2int(expr * arg, sort* range, expr_ref & result)
|
|||
result = m_arith.mk_add(tmp1, tmp2);
|
||||
}
|
||||
// commented out to reproduce bug in reduction of int2bv/bv2int
|
||||
else if (m_util.is_concat(arg)) {
|
||||
expr_ref tmp1(m_manager), tmp2(m_manager);
|
||||
unsigned sz2 = get_bv_size(to_app(arg)->get_arg(1));
|
||||
mk_bv2int(to_app(arg)->get_arg(0), range, tmp1);
|
||||
mk_bv2int(to_app(arg)->get_arg(1), range, tmp2);
|
||||
tmp1 = m_arith.mk_mul(m_arith.mk_numeral(power(numeral(2), sz2), true), tmp1);
|
||||
result = m_arith.mk_add(tmp1, tmp2);
|
||||
else if (m_util.is_concat(arg) && to_app(arg)->get_num_args() > 0) {
|
||||
expr_ref_vector args(m_manager);
|
||||
unsigned num_args = to_app(arg)->get_num_args();
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
expr_ref tmp(m_manager);
|
||||
mk_bv2int(to_app(arg)->get_arg(i), range, tmp);
|
||||
args.push_back(tmp);
|
||||
}
|
||||
unsigned sz = get_bv_size(to_app(arg)->get_arg(num_args-1));
|
||||
for (unsigned i = num_args - 1; i > 0; ) {
|
||||
expr_ref tmp(m_manager);
|
||||
--i;
|
||||
tmp = args[i].get();
|
||||
tmp = m_arith.mk_mul(m_arith.mk_numeral(power(numeral(2), sz), true), tmp);
|
||||
args[i] = tmp;
|
||||
sz += get_bv_size(to_app(arg)->get_arg(i));
|
||||
}
|
||||
result = m_arith.mk_add(args.size(), args.c_ptr());
|
||||
}
|
||||
else {
|
||||
parameter parameter(range);
|
||||
|
|
|
@ -14,7 +14,7 @@ Author:
|
|||
Leonardo de Moura (leonardo) 2010-04-02.
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
Christoph Wintersteiger 2010-04-06: Added implementation.
|
||||
|
||||
--*/
|
||||
|
@ -40,7 +40,7 @@ bool distribute_forall::visit_children(expr * n) {
|
|||
bool visited = true;
|
||||
unsigned j;
|
||||
switch(n->get_kind()) {
|
||||
case AST_VAR:
|
||||
case AST_VAR:
|
||||
break;
|
||||
case AST_APP:
|
||||
j = to_app(n)->get_num_args();
|
||||
|
@ -86,15 +86,15 @@ void distribute_forall::reduce1_app(app * a) {
|
|||
SASSERT(is_cached(a->get_arg(j)));
|
||||
expr * c = get_cached(a->get_arg(j));
|
||||
SASSERT(c!=0);
|
||||
if (c != a->get_arg(j))
|
||||
if (c != a->get_arg(j))
|
||||
reduced = true;
|
||||
m_new_args[j] = c;
|
||||
}
|
||||
}
|
||||
|
||||
if (reduced) {
|
||||
na = m_manager.mk_app(a->get_decl(), num_args, m_new_args.c_ptr());
|
||||
}
|
||||
|
||||
|
||||
cache_result(a, na);
|
||||
}
|
||||
|
||||
|
@ -126,11 +126,11 @@ void distribute_forall::reduce1_quantifier(quantifier * q) {
|
|||
quantifier_ref tmp_q(m_manager);
|
||||
tmp_q = m_manager.update_quantifier(q, not_arg);
|
||||
expr_ref new_q(m_manager);
|
||||
elim_unused_vars(m_manager, tmp_q, new_q);
|
||||
elim_unused_vars(m_manager, tmp_q, params_ref(), new_q);
|
||||
new_args.push_back(new_q);
|
||||
}
|
||||
expr_ref result(m_manager);
|
||||
// m_bsimp.mk_and actually constructs a (not (or ...)) formula,
|
||||
// m_bsimp.mk_and actually constructs a (not (or ...)) formula,
|
||||
// it will also apply basic simplifications.
|
||||
m_bsimp.mk_and(new_args.size(), new_args.c_ptr(), result);
|
||||
cache_result(q, result);
|
||||
|
@ -148,15 +148,15 @@ void distribute_forall::operator()(expr * f, expr_ref & result) {
|
|||
|
||||
while (!m_todo.empty()) {
|
||||
expr * e = m_todo.back();
|
||||
if (visit_children(e)) {
|
||||
if (visit_children(e)) {
|
||||
m_todo.pop_back();
|
||||
reduce1(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = get_cached(f);
|
||||
SASSERT(result!=0);
|
||||
TRACE("distribute_forall", tout << mk_ll_pp(f, m_manager) << "======>\n"
|
||||
TRACE("distribute_forall", tout << mk_ll_pp(f, m_manager) << "======>\n"
|
||||
<< mk_ll_pp(result, m_manager););
|
||||
}
|
||||
|
||||
|
@ -166,5 +166,5 @@ expr * distribute_forall::get_cached(expr * n) const {
|
|||
|
||||
void distribute_forall::cache_result(expr * n, expr * r) {
|
||||
SASSERT(r != 0);
|
||||
m_cache.insert(n, r);
|
||||
m_cache.insert(n, r);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ elim_bounds::elim_bounds(ast_manager & m):
|
|||
|
||||
(<= x k)
|
||||
(<= (+ x (* -1 y)) k)
|
||||
(<= (+ x (* -1 t)) k)
|
||||
(<= (+ x (* -1 t)) k)
|
||||
(<= (+ t (* -1 x)) k)
|
||||
|
||||
x and y are a bound variables, t is a ground term and k is a numeral
|
||||
|
@ -65,14 +65,14 @@ bool elim_bounds::is_bound(expr * n, var * & lower, var * & upper) {
|
|||
|
||||
if (neg)
|
||||
le = !le;
|
||||
|
||||
|
||||
if (is_var(n)) {
|
||||
upper = to_var(n);
|
||||
}
|
||||
else if (m_util.is_add(n) && to_app(n)->get_num_args() == 2) {
|
||||
expr * arg1 = to_app(n)->get_arg(0);
|
||||
expr * arg2 = to_app(n)->get_arg(1);
|
||||
if (is_var(arg1))
|
||||
if (is_var(arg1))
|
||||
upper = to_var(arg1);
|
||||
else if (!is_ground(arg1))
|
||||
return false;
|
||||
|
@ -95,7 +95,7 @@ bool elim_bounds::is_bound(expr * n, var * & lower, var * & upper) {
|
|||
|
||||
if (!le)
|
||||
std::swap(upper, lower);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -188,7 +188,7 @@ void elim_bounds::operator()(quantifier * q, expr_ref & r) {
|
|||
}
|
||||
quantifier_ref new_q(m_manager);
|
||||
new_q = m_manager.update_quantifier(q, new_body);
|
||||
elim_unused_vars(m_manager, new_q, r);
|
||||
elim_unused_vars(m_manager, new_q, params_ref(), r);
|
||||
TRACE("elim_bounds", tout << mk_pp(q, m_manager) << "\n" << mk_pp(r, m_manager) << "\n";);
|
||||
}
|
||||
|
||||
|
@ -199,10 +199,10 @@ bool elim_bounds_star::visit_quantifier(quantifier * q) {
|
|||
visit(q->get_expr(), visited);
|
||||
return visited;
|
||||
}
|
||||
|
||||
|
||||
void elim_bounds_star::reduce1_quantifier(quantifier * q) {
|
||||
if (!q->is_forall() || q->get_num_patterns() != 0) {
|
||||
cache_result(q, q, 0);
|
||||
cache_result(q, q, 0);
|
||||
return;
|
||||
}
|
||||
quantifier_ref new_q(m);
|
||||
|
|
|
@ -33,8 +33,8 @@ simplifier::simplifier(ast_manager & m):
|
|||
m_ac_support(true) {
|
||||
}
|
||||
|
||||
void simplifier::register_plugin(plugin * p) {
|
||||
m_plugins.register_plugin(p);
|
||||
void simplifier::register_plugin(plugin * p) {
|
||||
m_plugins.register_plugin(p);
|
||||
}
|
||||
|
||||
simplifier::~simplifier() {
|
||||
|
@ -46,13 +46,13 @@ void simplifier::enable_ac_support(bool flag) {
|
|||
ptr_vector<plugin>::const_iterator it = m_plugins.begin();
|
||||
ptr_vector<plugin>::const_iterator end = m_plugins.end();
|
||||
for (; it != end; ++it) {
|
||||
if (*it != 0)
|
||||
if (*it != 0)
|
||||
(*it)->enable_ac_support(flag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief External interface for the simplifier.
|
||||
\brief External interface for the simplifier.
|
||||
A client will invoke operator()(s, r, p) to simplify s.
|
||||
The result is stored in r.
|
||||
When proof generation is enabled, a proof for the equivalence (or equisatisfiability)
|
||||
|
@ -69,14 +69,14 @@ void simplifier::operator()(expr * s, expr_ref & r, proof_ref & p) {
|
|||
proof * result_proof;
|
||||
switch (m.proof_mode()) {
|
||||
case PGM_DISABLED: // proof generation is disabled.
|
||||
reduce_core(s);
|
||||
reduce_core(s);
|
||||
// after executing reduce_core, the result of the simplification is in the cache
|
||||
get_cached(s, result, result_proof);
|
||||
r = result;
|
||||
p = m.mk_undef_proof();
|
||||
break;
|
||||
case PGM_COARSE: // coarse proofs... in this case, we do not produce a step by step (fine grain) proof to show the equivalence (or equisatisfiability) of s an r.
|
||||
m_subst_proofs.reset(); // m_subst_proofs is an auxiliary vector that is used to justify substitutions. See comment on method get_subst.
|
||||
m_subst_proofs.reset(); // m_subst_proofs is an auxiliary vector that is used to justify substitutions. See comment on method get_subst.
|
||||
reduce_core(s);
|
||||
get_cached(s, result, result_proof);
|
||||
r = result;
|
||||
|
@ -163,7 +163,7 @@ bool simplifier::visit_children(expr * n) {
|
|||
// The method ast_manager::mk_app is used to create the flat version of an AC operator.
|
||||
// In Z3 1.x, we used multi-ary operators. This creates problems for the superposition engine.
|
||||
// So, starting at Z3 2.x, only boolean operators can be multi-ary.
|
||||
// Example:
|
||||
// Example:
|
||||
// (and (and a b) (and c d)) --> (and a b c d)
|
||||
// (+ (+ a b) (+ c d)) --> (+ a (+ b (+ c d)))
|
||||
// Remark: The flattening is only applied if m_ac_support is true.
|
||||
|
@ -178,7 +178,7 @@ bool simplifier::visit_children(expr * n) {
|
|||
}
|
||||
return visited;
|
||||
}
|
||||
case AST_QUANTIFIER:
|
||||
case AST_QUANTIFIER:
|
||||
return visit_quantifier(to_quantifier(n));
|
||||
default:
|
||||
UNREACHABLE();
|
||||
|
@ -188,7 +188,7 @@ bool simplifier::visit_children(expr * n) {
|
|||
|
||||
/**
|
||||
\brief Visit the children of n assuming it is an AC (associative-commutative) operator.
|
||||
|
||||
|
||||
For example, if n is of the form (+ (+ a b) (+ c d)), this method
|
||||
will return true if the nodes a, b, c and d have been already simplified.
|
||||
The nodes (+ a b) and (+ c d) are not really checked.
|
||||
|
@ -216,7 +216,7 @@ bool simplifier::visit_ac(app * n) {
|
|||
expr * arg = n->get_arg(i);
|
||||
if (is_app_of(arg, decl))
|
||||
todo.push_back(to_app(arg));
|
||||
else
|
||||
else
|
||||
visit(arg, visited);
|
||||
}
|
||||
}
|
||||
|
@ -319,7 +319,7 @@ void simplifier::reduce1_app_core(app * n) {
|
|||
proof * p;
|
||||
if (n == r)
|
||||
p = 0;
|
||||
else if (r != s)
|
||||
else if (r != s)
|
||||
// we use a "theory rewrite generic proof" to justify the step
|
||||
// s = (decl arg_0' ... arg_{n-1}') --> r
|
||||
p = m.mk_transitivity(p1, m.mk_rewrite(s, r));
|
||||
|
@ -368,7 +368,7 @@ void simplifier::reduce1_ac_app_core(app * n) {
|
|||
proof_ref p1(m);
|
||||
mk_ac_congruent_term(n, n_c, p1);
|
||||
TRACE("ac", tout << "expr:\n" << mk_pp(n, m) << "\ncongruent term:\n" << mk_pp(n_c, m) << "\n";);
|
||||
expr_ref r(m);
|
||||
expr_ref r(m);
|
||||
func_decl * decl = n->get_decl();
|
||||
family_id fid = decl->get_family_id();
|
||||
plugin * p = get_plugin(fid);
|
||||
|
@ -415,7 +415,7 @@ void simplifier::reduce1_ac_app_core(app * n) {
|
|||
proof * p;
|
||||
if (n == r.get())
|
||||
p = 0;
|
||||
else if (r.get() != n_c.get())
|
||||
else if (r.get() != n_c.get())
|
||||
p = m.mk_transitivity(p1, m.mk_rewrite(n_c, r));
|
||||
else
|
||||
p = p1;
|
||||
|
@ -434,7 +434,7 @@ void simplifier::dump_rewrite_lemma(func_decl * decl, unsigned num_args, expr *
|
|||
sprintf_s(buffer, ARRAYSIZE(buffer), "lemma_%d.smt", g_rewrite_lemma_id);
|
||||
#else
|
||||
sprintf(buffer, "rewrite_lemma_%d.smt", g_rewrite_lemma_id);
|
||||
#endif
|
||||
#endif
|
||||
ast_smt_pp pp(m);
|
||||
pp.set_benchmark_name("rewrite_lemma");
|
||||
pp.set_status("unsat");
|
||||
|
@ -450,7 +450,7 @@ void simplifier::dump_rewrite_lemma(func_decl * decl, unsigned num_args, expr *
|
|||
/**
|
||||
\brief Return in \c result an expression \c e equivalent to <tt>(f args[0] ... args[num_args - 1])</tt>, and
|
||||
store in \c pr a proof for <tt>(= (f args[0] ... args[num_args - 1]) e)</tt>
|
||||
|
||||
|
||||
If e is identical to (f args[0] ... args[num_args - 1]), then pr is set to 0.
|
||||
*/
|
||||
void simplifier::mk_app(func_decl * decl, unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
|
@ -474,7 +474,7 @@ void simplifier::mk_app(func_decl * decl, unsigned num_args, expr * const * args
|
|||
//dump_rewrite_lemma(decl, num_args, args, result.get());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
result = m.mk_app(decl, num_args, args);
|
||||
}
|
||||
|
||||
|
@ -494,17 +494,17 @@ void simplifier::mk_congruent_term(app * n, app_ref & r, proof_ref & p) {
|
|||
proof * arg_proof;
|
||||
get_cached(arg, new_arg, arg_proof);
|
||||
|
||||
CTRACE("simplifier_bug", (arg != new_arg) != (arg_proof != 0),
|
||||
CTRACE("simplifier_bug", (arg != new_arg) != (arg_proof != 0),
|
||||
tout << mk_ll_pp(arg, m) << "\n---->\n" << mk_ll_pp(new_arg, m) << "\n";
|
||||
tout << "#" << arg->get_id() << " #" << new_arg->get_id() << "\n";
|
||||
tout << arg << " " << new_arg << "\n";);
|
||||
|
||||
|
||||
|
||||
|
||||
if (arg != new_arg) {
|
||||
has_new_args = true;
|
||||
proofs.push_back(arg_proof);
|
||||
SASSERT(arg_proof);
|
||||
}
|
||||
}
|
||||
else {
|
||||
SASSERT(arg_proof == 0);
|
||||
}
|
||||
|
@ -526,10 +526,10 @@ void simplifier::mk_congruent_term(app * n, app_ref & r, proof_ref & p) {
|
|||
/**
|
||||
\brief Store the new arguments of \c n in result. Store in p a proof for
|
||||
(= n (f result[0] ... result[num_args - 1])), where f is the function symbol of n.
|
||||
|
||||
|
||||
If there are no new arguments or fine grain proofs are disabled, then p is set to 0.
|
||||
|
||||
Return true there are new arguments.
|
||||
Return true there are new arguments.
|
||||
*/
|
||||
bool simplifier::get_args(app * n, ptr_vector<expr> & result, proof_ref & p) {
|
||||
bool has_new_args = false;
|
||||
|
@ -565,10 +565,10 @@ bool simplifier::get_args(app * n, ptr_vector<expr> & result, proof_ref & p) {
|
|||
void simplifier::mk_ac_congruent_term(app * n, app_ref & r, proof_ref & p) {
|
||||
SASSERT(m_ac_support);
|
||||
func_decl * f = n->get_decl();
|
||||
|
||||
|
||||
m_ac_cache.reset();
|
||||
m_ac_pr_cache.reset();
|
||||
|
||||
|
||||
ptr_buffer<app> todo;
|
||||
ptr_buffer<expr> new_args;
|
||||
ptr_buffer<proof> new_arg_prs;
|
||||
|
@ -621,7 +621,7 @@ void simplifier::mk_ac_congruent_term(app * n, app_ref & r, proof_ref & p) {
|
|||
todo.pop_back();
|
||||
if (!has_new_arg) {
|
||||
m_ac_cache.insert(curr, curr);
|
||||
if (m.fine_grain_proofs())
|
||||
if (m.fine_grain_proofs())
|
||||
m_ac_pr_cache.insert(curr, 0);
|
||||
}
|
||||
else {
|
||||
|
@ -634,7 +634,7 @@ void simplifier::mk_ac_congruent_term(app * n, app_ref & r, proof_ref & p) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SASSERT(m_ac_cache.contains(n));
|
||||
app * new_n = 0;
|
||||
m_ac_cache.find(n, new_n);
|
||||
|
@ -646,7 +646,7 @@ void simplifier::mk_ac_congruent_term(app * n, app_ref & r, proof_ref & p) {
|
|||
}
|
||||
}
|
||||
|
||||
#define White 0
|
||||
#define White 0
|
||||
#define Grey 1
|
||||
#define Black 2
|
||||
|
||||
|
@ -688,7 +688,7 @@ void simplifier::ac_top_sort(app * n, ptr_buffer<expr> & result) {
|
|||
while (!todo.empty()) {
|
||||
expr * curr = todo.back();
|
||||
int color;
|
||||
obj_map<expr, int>::obj_map_entry * entry = colors.insert_if_not_there2(curr, White);
|
||||
obj_map<expr, int>::obj_map_entry * entry = colors.insert_if_not_there2(curr, White);
|
||||
SASSERT(entry);
|
||||
color = entry->get_data().m_value;
|
||||
switch (color) {
|
||||
|
@ -731,7 +731,7 @@ void simplifier::get_ac_args(app * n, ptr_vector<expr> & args, vector<rational>
|
|||
ac_top_sort(n, sorted_exprs);
|
||||
SASSERT(!sorted_exprs.empty());
|
||||
SASSERT(sorted_exprs[sorted_exprs.size()-1] == n);
|
||||
|
||||
|
||||
TRACE("ac", tout << mk_ll_pp(n, m, true, false) << "#" << n->get_id() << "\nsorted expressions...\n";
|
||||
for (unsigned i = 0; i < sorted_exprs.size(); i++) {
|
||||
tout << "#" << sorted_exprs[i]->get_id() << " ";
|
||||
|
@ -747,7 +747,7 @@ void simplifier::get_ac_args(app * n, ptr_vector<expr> & args, vector<rational>
|
|||
expr * curr = sorted_exprs[j];
|
||||
rational mult;
|
||||
m_ac_mults.find(curr, mult);
|
||||
SASSERT(!mult.is_zero());
|
||||
SASSERT(!mult.is_zero());
|
||||
if (is_app_of(curr, decl)) {
|
||||
unsigned num_args = to_app(curr)->get_num_args();
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
|
@ -772,16 +772,16 @@ void simplifier::reduce1_quantifier(quantifier * q) {
|
|||
|
||||
quantifier_ref q1(m);
|
||||
proof * p1 = 0;
|
||||
|
||||
if (is_quantifier(new_body) &&
|
||||
|
||||
if (is_quantifier(new_body) &&
|
||||
to_quantifier(new_body)->is_forall() == q->is_forall() &&
|
||||
!to_quantifier(q)->has_patterns() &&
|
||||
!to_quantifier(new_body)->has_patterns()) {
|
||||
|
||||
|
||||
quantifier * nested_q = to_quantifier(new_body);
|
||||
|
||||
ptr_buffer<sort> sorts;
|
||||
buffer<symbol> names;
|
||||
buffer<symbol> names;
|
||||
sorts.append(q->get_num_decls(), q->get_decl_sorts());
|
||||
names.append(q->get_num_decls(), q->get_decl_names());
|
||||
sorts.append(nested_q->get_num_decls(), nested_q->get_decl_sorts());
|
||||
|
@ -797,7 +797,7 @@ void simplifier::reduce1_quantifier(quantifier * q) {
|
|||
q->get_skid(),
|
||||
0, 0, 0, 0);
|
||||
SASSERT(is_well_sorted(m, q1));
|
||||
|
||||
|
||||
if (m.fine_grain_proofs()) {
|
||||
quantifier * q0 = m.update_quantifier(q, new_body);
|
||||
proof * p0 = q == q0 ? 0 : m.mk_quant_intro(q, q0, new_body_pr);
|
||||
|
@ -817,13 +817,13 @@ void simplifier::reduce1_quantifier(quantifier * q) {
|
|||
get_cached(q->get_pattern(i), new_pattern, new_pattern_pr);
|
||||
if (m.is_pattern(new_pattern)) {
|
||||
new_patterns.push_back(new_pattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
num = q->get_num_no_patterns();
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
get_cached(q->get_no_pattern(i), new_pattern, new_pattern_pr);
|
||||
new_no_patterns.push_back(new_pattern);
|
||||
}
|
||||
}
|
||||
|
||||
remove_duplicates(new_patterns);
|
||||
remove_duplicates(new_no_patterns);
|
||||
|
@ -833,7 +833,7 @@ void simplifier::reduce1_quantifier(quantifier * q) {
|
|||
q->get_decl_sorts(),
|
||||
q->get_decl_names(),
|
||||
new_body,
|
||||
q->get_weight(),
|
||||
q->get_weight(),
|
||||
q->get_qid(),
|
||||
q->get_skid(),
|
||||
new_patterns.size(),
|
||||
|
@ -850,10 +850,10 @@ void simplifier::reduce1_quantifier(quantifier * q) {
|
|||
p1 = q == q1 ? 0 : m.mk_quant_intro(q, q1, new_body_pr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
expr_ref r(m);
|
||||
elim_unused_vars(m, q1, r);
|
||||
|
||||
elim_unused_vars(m, q1, params_ref(), r);
|
||||
|
||||
proof * pr = 0;
|
||||
if (m.fine_grain_proofs()) {
|
||||
proof * p2 = 0;
|
||||
|
@ -871,7 +871,7 @@ void simplifier::reduce1_quantifier(quantifier * q) {
|
|||
void simplifier::borrow_plugins(simplifier const & s) {
|
||||
ptr_vector<plugin>::const_iterator it = s.begin_plugins();
|
||||
ptr_vector<plugin>::const_iterator end = s.end_plugins();
|
||||
for (; it != end; ++it)
|
||||
for (; it != end; ++it)
|
||||
register_plugin(*it);
|
||||
}
|
||||
|
||||
|
@ -882,7 +882,7 @@ void simplifier::enable_presimp() {
|
|||
enable_ac_support(false);
|
||||
ptr_vector<plugin>::const_iterator it = begin_plugins();
|
||||
ptr_vector<plugin>::const_iterator end = end_plugins();
|
||||
for (; it != end; ++it)
|
||||
for (; it != end; ++it)
|
||||
(*it)->enable_presimp(true);
|
||||
}
|
||||
|
||||
|
@ -905,7 +905,7 @@ bool subst_simplifier::get_subst(expr * n, expr_ref & r, proof_ref & p) {
|
|||
m_subst_map->get(n, _r, _p);
|
||||
r = _r;
|
||||
p = _p;
|
||||
if (m.coarse_grain_proofs())
|
||||
if (m.coarse_grain_proofs())
|
||||
m_subst_proofs.push_back(p);
|
||||
return true;
|
||||
}
|
||||
|
@ -917,7 +917,7 @@ static void push_core(ast_manager & m, expr * e, proof * pr, expr_ref_vector & r
|
|||
TRACE("preprocessor",
|
||||
tout << mk_pp(e, m) << "\n";
|
||||
if (pr) tout << mk_ll_pp(pr, m) << "\n\n";);
|
||||
if (m.is_true(e))
|
||||
if (m.is_true(e))
|
||||
return;
|
||||
result.push_back(e);
|
||||
if (m.proofs_enabled())
|
||||
|
@ -952,9 +952,9 @@ void push_assertion(ast_manager & m, expr * e, proof * pr, expr_ref_vector & res
|
|||
CTRACE("push_assertion", !(pr == 0 || m.is_undef_proof(pr) || m.get_fact(pr) == e),
|
||||
tout << mk_pp(e, m) << "\n" << mk_pp(m.get_fact(pr), m) << "\n";);
|
||||
SASSERT(pr == 0 || m.is_undef_proof(pr) || m.get_fact(pr) == e);
|
||||
if (m.is_and(e))
|
||||
if (m.is_and(e))
|
||||
push_and(m, to_app(e), pr, result, result_prs);
|
||||
else if (m.is_not(e) && m.is_or(to_app(e)->get_arg(0)))
|
||||
else if (m.is_not(e) && m.is_or(to_app(e)->get_arg(0)))
|
||||
push_not_or(m, to_app(to_app(e)->get_arg(0)), pr, result, result_prs);
|
||||
else
|
||||
push_core(m, e, pr, result, result_prs);
|
||||
|
|
|
@ -100,13 +100,34 @@ public:
|
|||
|
||||
ATOMIC_CMD(exit_cmd, "exit", "exit.", ctx.print_success(); throw stop_parser_exception(););
|
||||
|
||||
ATOMIC_CMD(get_model_cmd, "get-model", "retrieve model for the last check-sat command", {
|
||||
if (!ctx.is_model_available() || ctx.get_check_sat_result() == 0)
|
||||
throw cmd_exception("model is not available");
|
||||
model_ref m;
|
||||
ctx.get_check_sat_result()->get_model(m);
|
||||
ctx.display_model(m);
|
||||
});
|
||||
class get_model_cmd : public cmd {
|
||||
unsigned m_index;
|
||||
public:
|
||||
get_model_cmd(): cmd("get-model"), m_index(0) {}
|
||||
virtual char const * get_usage() const { return "[<index of box objective>]"; }
|
||||
virtual char const * get_descr(cmd_context & ctx) const {
|
||||
return "retrieve model for the last check-sat command.\nSupply optional index if retrieving a model corresponding to a box optimization objective";
|
||||
}
|
||||
virtual unsigned get_arity() const { return VAR_ARITY; }
|
||||
virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { return CPK_UINT; }
|
||||
virtual void set_next_arg(cmd_context & ctx, unsigned index) { m_index = index; }
|
||||
virtual void execute(cmd_context & ctx) {
|
||||
if (!ctx.is_model_available() || ctx.get_check_sat_result() == 0)
|
||||
throw cmd_exception("model is not available");
|
||||
model_ref m;
|
||||
if (m_index > 0 && ctx.get_opt()) {
|
||||
ctx.get_opt()->get_box_model(m, m_index);
|
||||
}
|
||||
else {
|
||||
ctx.get_check_sat_result()->get_model(m);
|
||||
}
|
||||
ctx.display_model(m);
|
||||
}
|
||||
virtual void reset(cmd_context& ctx) {
|
||||
m_index = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
ATOMIC_CMD(get_assignment_cmd, "get-assignment", "retrieve assignment", {
|
||||
if (!ctx.is_model_available() || ctx.get_check_sat_result() == 0)
|
||||
|
|
|
@ -739,8 +739,11 @@ void cmd_context::insert_rec_fun(func_decl* f, expr_ref_vector const& binding, s
|
|||
lhs = m().mk_app(f, binding.size(), binding.c_ptr());
|
||||
eq = m().mk_eq(lhs, e);
|
||||
if (!ids.empty()) {
|
||||
expr* pat = m().mk_pattern(lhs);
|
||||
eq = m().mk_forall(ids.size(), f->get_domain(), ids.c_ptr(), eq, 0, m().rec_fun_qid(), symbol::null, 1, &pat);
|
||||
if (!is_app(e)) {
|
||||
throw cmd_exception("Z3 only supports recursive definitions that are proper terms (not binders or variables)");
|
||||
}
|
||||
expr* pats[2] = { m().mk_pattern(lhs), m().mk_pattern(to_app(e)) };
|
||||
eq = m().mk_forall(ids.size(), f->get_domain(), ids.c_ptr(), eq, 0, m().rec_fun_qid(), symbol::null, 2, pats);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -1551,6 +1554,7 @@ void cmd_context::validate_model() {
|
|||
p.set_uint("sort_store", true);
|
||||
p.set_bool("completion", true);
|
||||
model_evaluator evaluator(*(md.get()), p);
|
||||
evaluator.set_expand_array_equalities(false);
|
||||
contains_array_op_proc contains_array(m());
|
||||
{
|
||||
scoped_rlimit _rlimit(m().limit(), 0);
|
||||
|
|
|
@ -124,6 +124,7 @@ public:
|
|||
virtual bool is_pareto() = 0;
|
||||
virtual void set_logic(symbol const& s) = 0;
|
||||
virtual bool print_model() const = 0;
|
||||
virtual void get_box_model(model_ref& mdl, unsigned index) = 0;
|
||||
virtual void updt_params(params_ref const& p) = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ public:
|
|||
virtual void init_pdescrs(cmd_context & ctx, param_descrs & p) {
|
||||
model_evaluator::get_param_descrs(p);
|
||||
insert_timeout(p);
|
||||
p.insert("model_index", CPK_UINT, "(default: 0) index of model from box optimization objective");
|
||||
}
|
||||
|
||||
virtual void prepare(cmd_context & ctx) {
|
||||
|
@ -58,9 +59,15 @@ public:
|
|||
if (!ctx.is_model_available())
|
||||
throw cmd_exception("model is not available");
|
||||
model_ref md;
|
||||
unsigned index = m_params.get_uint("model_index", 0);
|
||||
check_sat_result * last_result = ctx.get_check_sat_result();
|
||||
SASSERT(last_result);
|
||||
last_result->get_model(md);
|
||||
if (index == 0 || !ctx.get_opt()) {
|
||||
last_result->get_model(md);
|
||||
}
|
||||
else {
|
||||
ctx.get_opt()->get_box_model(md, index);
|
||||
}
|
||||
expr_ref r(ctx.m());
|
||||
unsigned timeout = m_params.get_uint("timeout", UINT_MAX);
|
||||
unsigned rlimit = m_params.get_uint("rlimit", 0);
|
||||
|
|
|
@ -29,11 +29,12 @@ Notes:
|
|||
#include"bound_manager.h"
|
||||
#include"used_vars.h"
|
||||
#include"var_subst.h"
|
||||
#include"gparams.h"
|
||||
|
||||
#ifndef _EXTERNAL_RELEASE
|
||||
|
||||
BINARY_SYM_CMD(get_quantifier_body_cmd,
|
||||
"dbg-get-qbody",
|
||||
BINARY_SYM_CMD(get_quantifier_body_cmd,
|
||||
"dbg-get-qbody",
|
||||
"<symbol> <quantifier>",
|
||||
"store the body of the quantifier in the global variable <symbol>",
|
||||
CPK_EXPR,
|
||||
|
@ -43,8 +44,8 @@ BINARY_SYM_CMD(get_quantifier_body_cmd,
|
|||
store_expr_ref(ctx, m_sym, to_quantifier(arg)->get_expr());
|
||||
});
|
||||
|
||||
BINARY_SYM_CMD(set_cmd,
|
||||
"dbg-set",
|
||||
BINARY_SYM_CMD(set_cmd,
|
||||
"dbg-set",
|
||||
"<symbol> <term>",
|
||||
"store <term> in the global variable <symbol>",
|
||||
CPK_EXPR,
|
||||
|
@ -57,7 +58,7 @@ UNARY_CMD(pp_var_cmd, "dbg-pp-var", "<symbol>", "pretty print a global variable
|
|||
expr * t = get_expr_ref(ctx, arg);
|
||||
SASSERT(t != 0);
|
||||
ctx.display(ctx.regular_stream(), t);
|
||||
ctx.regular_stream() << std::endl;
|
||||
ctx.regular_stream() << std::endl;
|
||||
});
|
||||
|
||||
BINARY_SYM_CMD(shift_vars_cmd,
|
||||
|
@ -71,7 +72,7 @@ BINARY_SYM_CMD(shift_vars_cmd,
|
|||
var_shifter s(ctx.m());
|
||||
s(t, arg, r);
|
||||
store_expr_ref(ctx, m_sym, r.get());
|
||||
});
|
||||
});
|
||||
|
||||
UNARY_CMD(pp_shared_cmd, "dbg-pp-shared", "<term>", "display shared subterms of the given term", CPK_EXPR, expr *, {
|
||||
shared_occs s(ctx.m());
|
||||
|
@ -81,7 +82,7 @@ UNARY_CMD(pp_shared_cmd, "dbg-pp-shared", "<term>", "display shared subterms of
|
|||
shared_occs::iterator end = s.end_shared();
|
||||
for (; it != end; ++it) {
|
||||
expr * curr = *it;
|
||||
ctx.regular_stream() << std::endl << " ";
|
||||
ctx.regular_stream() << std::endl << " ";
|
||||
ctx.display(ctx.regular_stream(), curr, 2);
|
||||
}
|
||||
ctx.regular_stream() << ")" << std::endl;
|
||||
|
@ -112,7 +113,7 @@ public:
|
|||
if (m_idx == 1) return CPK_SYMBOL_LIST;
|
||||
return CPK_SYMBOL;
|
||||
}
|
||||
virtual void set_next_arg(cmd_context & ctx, symbol const & s) {
|
||||
virtual void set_next_arg(cmd_context & ctx, symbol const & s) {
|
||||
if (m_idx == 0) {
|
||||
m_source = get_expr_ref(ctx, s);
|
||||
}
|
||||
|
@ -146,24 +147,24 @@ UNARY_CMD(bool_rewriter_cmd, "dbg-bool-rewriter", "<term>", "apply the Boolean r
|
|||
bool_rewriter_star r(ctx.m(), p);
|
||||
r(arg, t);
|
||||
ctx.display(ctx.regular_stream(), t);
|
||||
ctx.regular_stream() << std::endl;
|
||||
ctx.regular_stream() << std::endl;
|
||||
});
|
||||
|
||||
UNARY_CMD(bool_frewriter_cmd, "dbg-bool-flat-rewriter", "<term>", "apply the Boolean (flattening) rewriter to the given term", CPK_EXPR, expr *, {
|
||||
expr_ref t(ctx.m());
|
||||
{
|
||||
{
|
||||
params_ref p;
|
||||
p.set_bool("flat", true);
|
||||
bool_rewriter_star r(ctx.m(), p);
|
||||
r(arg, t);
|
||||
}
|
||||
ctx.display(ctx.regular_stream(), t);
|
||||
ctx.regular_stream() << std::endl;
|
||||
ctx.regular_stream() << std::endl;
|
||||
});
|
||||
|
||||
UNARY_CMD(elim_and_cmd, "dbg-elim-and", "<term>", "apply the Boolean rewriter (eliminating AND operator and flattening) to the given term", CPK_EXPR, expr *, {
|
||||
expr_ref t(ctx.m());
|
||||
{
|
||||
{
|
||||
params_ref p;
|
||||
p.set_bool("flat", true);
|
||||
p.set_bool("elim_and", true);
|
||||
|
@ -171,7 +172,7 @@ UNARY_CMD(elim_and_cmd, "dbg-elim-and", "<term>", "apply the Boolean rewriter (e
|
|||
r(arg, t);
|
||||
}
|
||||
ctx.display(ctx.regular_stream(), t);
|
||||
ctx.regular_stream() << std::endl;
|
||||
ctx.regular_stream() << std::endl;
|
||||
});
|
||||
|
||||
class lt_cmd : public cmd {
|
||||
|
@ -192,7 +193,7 @@ public:
|
|||
}
|
||||
virtual void execute(cmd_context & ctx) {
|
||||
bool r = lt(m_t1, m_t2);
|
||||
ctx.regular_stream() << (r ? "true" : "false") << std::endl;
|
||||
ctx.regular_stream() << (r ? "true" : "false") << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -249,7 +250,7 @@ UNARY_CMD(set_next_id, "dbg-set-next-id", "<unsigned>", "set the next expression
|
|||
|
||||
UNARY_CMD(used_vars_cmd, "dbg-used-vars", "<expr>", "test used_vars functor", CPK_EXPR, expr *, {
|
||||
used_vars proc;
|
||||
if (is_quantifier(arg))
|
||||
if (is_quantifier(arg))
|
||||
arg = to_quantifier(arg)->get_expr();
|
||||
proc(arg);
|
||||
ctx.regular_stream() << "(vars";
|
||||
|
@ -258,7 +259,7 @@ UNARY_CMD(used_vars_cmd, "dbg-used-vars", "<expr>", "test used_vars functor", CP
|
|||
ctx.regular_stream() << "\n (" << std::left << std::setw(6) << i << " ";
|
||||
if (s != 0)
|
||||
ctx.display(ctx.regular_stream(), s, 10);
|
||||
else
|
||||
else
|
||||
ctx.regular_stream() << "<not-used>";
|
||||
ctx.regular_stream() << ")";
|
||||
}
|
||||
|
@ -271,7 +272,7 @@ UNARY_CMD(elim_unused_vars_cmd, "dbg-elim-unused-vars", "<expr>", "eliminate unu
|
|||
return;
|
||||
}
|
||||
expr_ref r(ctx.m());
|
||||
elim_unused_vars(ctx.m(), to_quantifier(arg), r);
|
||||
elim_unused_vars(ctx.m(), to_quantifier(arg), gparams::get(), r);
|
||||
SASSERT(!is_quantifier(r) || !to_quantifier(r)->may_have_unused_vars());
|
||||
ctx.display(ctx.regular_stream(), r);
|
||||
ctx.regular_stream() << std::endl;
|
||||
|
@ -287,18 +288,18 @@ public:
|
|||
virtual char const * get_descr() const { return "instantiate the quantifier using the given expressions."; }
|
||||
virtual unsigned get_arity() const { return 2; }
|
||||
virtual void prepare(cmd_context & ctx) { m_q = 0; m_args.reset(); }
|
||||
|
||||
|
||||
virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const {
|
||||
if (m_q == 0) return CPK_EXPR;
|
||||
else return CPK_EXPR_LIST;
|
||||
}
|
||||
|
||||
|
||||
virtual void set_next_arg(cmd_context & ctx, expr * s) {
|
||||
if (!is_quantifier(s))
|
||||
throw cmd_exception("invalid command, quantifier expected.");
|
||||
m_q = to_quantifier(s);
|
||||
}
|
||||
|
||||
|
||||
virtual void set_next_arg(cmd_context & ctx, unsigned num, expr * const * ts) {
|
||||
if (num != m_q->get_num_decls())
|
||||
throw cmd_exception("invalid command, mismatch between the number of quantified variables and the number of arguments.");
|
||||
|
@ -331,7 +332,7 @@ public:
|
|||
class instantiate_nested_cmd : public instantiate_cmd_core {
|
||||
public:
|
||||
instantiate_nested_cmd():instantiate_cmd_core("dbg-instantiate-nested") {}
|
||||
|
||||
|
||||
virtual char const * get_descr() const { return "instantiate the quantifier nested in the outermost quantifier, this command is used to test the instantiation procedure with quantifiers that contain free variables."; }
|
||||
|
||||
virtual void set_next_arg(cmd_context & ctx, expr * s) {
|
||||
|
|
|
@ -41,8 +41,8 @@ namespace Duality {
|
|||
params_ref p;
|
||||
p.set_bool("proof", true); // this is currently useless
|
||||
if(models)
|
||||
p.set_bool("model", true);
|
||||
p.set_bool("unsat_core", true);
|
||||
p.set_bool("model", true);
|
||||
p.set_bool("unsat_core", true);
|
||||
bool mbqi = c.get_config().get().get_bool("mbqi",true);
|
||||
p.set_bool("mbqi",mbqi); // just to test
|
||||
p.set_str("mbqi.id","itp"); // use mbqi for quantifiers in interpolants
|
||||
|
@ -57,7 +57,7 @@ namespace Duality {
|
|||
m_mode = m().proof_mode();
|
||||
}
|
||||
|
||||
expr context::constant(const std::string &name, const sort &ty){
|
||||
expr context::constant(const std::string &name, const sort &ty){
|
||||
symbol s = str_symbol(name.c_str());
|
||||
return cook(m().mk_const(m().mk_const_decl(s, ty)));
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ namespace Duality {
|
|||
}
|
||||
|
||||
expr context::mki(family_id fid, ::decl_kind dk, int n, ::expr **args){
|
||||
return cook(m().mk_app(fid, dk, 0, 0, n, (::expr **)args));
|
||||
return cook(m().mk_app(fid, dk, 0, 0, n, (::expr **)args));
|
||||
}
|
||||
|
||||
expr context::make(decl_kind op, const std::vector<expr> &args){
|
||||
|
@ -168,9 +168,9 @@ namespace Duality {
|
|||
expr_abstract(m(), 0, num_bound, VEC2PTR(bound_asts), to_expr(body.raw()), abs_body);
|
||||
expr_ref result(m());
|
||||
result = m().mk_quantifier(
|
||||
op == Forall,
|
||||
names.size(), VEC2PTR(types), VEC2PTR(names), abs_body.get(),
|
||||
0,
|
||||
op == Forall,
|
||||
names.size(), VEC2PTR(types), VEC2PTR(names), abs_body.get(),
|
||||
0,
|
||||
::symbol(),
|
||||
::symbol(),
|
||||
0, 0,
|
||||
|
@ -194,9 +194,9 @@ namespace Duality {
|
|||
}
|
||||
expr_ref result(m());
|
||||
result = m().mk_quantifier(
|
||||
op == Forall,
|
||||
names.size(), VEC2PTR(types), VEC2PTR(names), to_expr(body.raw()),
|
||||
0,
|
||||
op == Forall,
|
||||
names.size(), VEC2PTR(types), VEC2PTR(names), to_expr(body.raw()),
|
||||
0,
|
||||
::symbol(),
|
||||
::symbol(),
|
||||
0, 0,
|
||||
|
@ -273,7 +273,7 @@ namespace Duality {
|
|||
return OtherArray;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return Other;
|
||||
}
|
||||
|
||||
|
@ -340,7 +340,7 @@ namespace Duality {
|
|||
params p;
|
||||
return simplify(p);
|
||||
}
|
||||
|
||||
|
||||
expr context::make_var(int idx, const sort &s){
|
||||
::sort * a = to_sort(s.raw());
|
||||
return cook(m().mk_var(idx,a));
|
||||
|
@ -348,7 +348,7 @@ namespace Duality {
|
|||
|
||||
|
||||
expr expr::qe_lite() const {
|
||||
::qe_lite qe(m());
|
||||
::qe_lite qe(m(), params_ref());
|
||||
expr_ref result(to_expr(raw()),m());
|
||||
proof_ref pf(m());
|
||||
qe(result,pf);
|
||||
|
@ -356,7 +356,7 @@ namespace Duality {
|
|||
}
|
||||
|
||||
expr expr::qe_lite(const std::set<int> &idxs, bool index_of_bound) const {
|
||||
::qe_lite qe(m());
|
||||
::qe_lite qe(m(), params_ref());
|
||||
expr_ref result(to_expr(raw()),m());
|
||||
proof_ref pf(m());
|
||||
uint_set uis;
|
||||
|
@ -412,16 +412,16 @@ namespace Duality {
|
|||
std::vector < ::sort * > _domain(domain.size());
|
||||
for(unsigned i = 0; i < domain.size(); i++)
|
||||
_domain[i] = to_sort(domain[i].raw());
|
||||
::func_decl* d = m().mk_fresh_func_decl(prefix,
|
||||
_domain.size(),
|
||||
::func_decl* d = m().mk_fresh_func_decl(prefix,
|
||||
_domain.size(),
|
||||
VEC2PTR(_domain),
|
||||
to_sort(range.raw()));
|
||||
return func_decl(*this,d);
|
||||
}
|
||||
|
||||
func_decl context::fresh_func_decl(char const * prefix, sort const & range){
|
||||
::func_decl* d = m().mk_fresh_func_decl(prefix,
|
||||
0,
|
||||
::func_decl* d = m().mk_fresh_func_decl(prefix,
|
||||
0,
|
||||
0,
|
||||
to_sort(range.raw()));
|
||||
return func_decl(*this,d);
|
||||
|
@ -462,30 +462,30 @@ namespace Duality {
|
|||
incremental,
|
||||
_theory.size(),
|
||||
VEC2PTR(_theory));
|
||||
|
||||
|
||||
if(lb == Z3_L_FALSE){
|
||||
interpolants.resize(_interpolants.size());
|
||||
for (unsigned i = 0; i < _interpolants.size(); ++i) {
|
||||
interpolants[i] = expr(ctx(),_interpolants[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (_model) {
|
||||
model = iz3wrapper::model(ctx(), _model);
|
||||
}
|
||||
|
||||
|
||||
if(_labels){
|
||||
labels = _labels;
|
||||
}
|
||||
|
||||
|
||||
return lb;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static int linearize_assumptions(int num,
|
||||
TermTree *assumptions,
|
||||
std::vector<std::vector <expr> > &linear_assumptions,
|
||||
std::vector<std::vector <expr> > &linear_assumptions,
|
||||
std::vector<int> &parents){
|
||||
for(unsigned i = 0; i < assumptions->getChildren().size(); i++)
|
||||
num = linearize_assumptions(num, assumptions->getChildren()[i], linear_assumptions, parents);
|
||||
|
@ -501,7 +501,7 @@ namespace Duality {
|
|||
}
|
||||
|
||||
static int unlinearize_interpolants(int num,
|
||||
TermTree* assumptions,
|
||||
TermTree* assumptions,
|
||||
const std::vector<expr> &interpolant,
|
||||
TermTree * &tree_interpolant)
|
||||
{
|
||||
|
@ -522,7 +522,7 @@ namespace Duality {
|
|||
literals &labels,
|
||||
bool incremental
|
||||
)
|
||||
|
||||
|
||||
{
|
||||
int size = assumptions->number(0);
|
||||
std::vector<std::vector<expr> > linear_assumptions(size);
|
||||
|
@ -540,36 +540,36 @@ namespace Duality {
|
|||
ptr_vector< ::ast> _theory(theory.size());
|
||||
for(unsigned i = 0; i < theory.size(); i++)
|
||||
_theory[i] = theory[i];
|
||||
|
||||
|
||||
|
||||
|
||||
if(!incremental){
|
||||
push();
|
||||
for(unsigned i = 0; i < linear_assumptions.size(); i++)
|
||||
for(unsigned j = 0; j < linear_assumptions[i].size(); j++)
|
||||
add(linear_assumptions[i][j]);
|
||||
}
|
||||
|
||||
|
||||
check_result res = unsat;
|
||||
|
||||
if(!m_solver->get_proof())
|
||||
res = check();
|
||||
|
||||
|
||||
if(res == unsat){
|
||||
|
||||
interpolation_options_struct opts;
|
||||
if(weak_mode)
|
||||
opts.set("weak","1");
|
||||
|
||||
opts.set("weak","1");
|
||||
|
||||
::ast *proof = m_solver->get_proof();
|
||||
try {
|
||||
iz3interpolate(m(),proof,_assumptions,_parents,_interpolants,_theory,&opts);
|
||||
}
|
||||
// If there's an interpolation bug, throw a char *
|
||||
// exception so duality can catch it and restart.
|
||||
// exception so duality can catch it and restart.
|
||||
catch (const interpolation_failure &f) {
|
||||
throw f.msg();
|
||||
}
|
||||
|
||||
|
||||
std::vector<expr> linearized_interpolants(_interpolants.size());
|
||||
for(unsigned i = 0; i < _interpolants.size(); i++)
|
||||
linearized_interpolants[i] = expr(ctx(),_interpolants[i]);
|
||||
|
@ -585,13 +585,13 @@ namespace Duality {
|
|||
model_ref _m;
|
||||
m_solver->get_model(_m);
|
||||
model = Duality::model(ctx(),_m.get());
|
||||
|
||||
|
||||
#if 0
|
||||
if(_labels){
|
||||
labels = _labels;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if(!incremental)
|
||||
pop();
|
||||
|
||||
|
@ -603,7 +603,7 @@ namespace Duality {
|
|||
void interpolating_solver::SetWeakInterpolants(bool weak){
|
||||
weak_mode = weak;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void interpolating_solver::SetPrintToFile(const std::string &filename){
|
||||
print_filename = filename;
|
||||
|
@ -618,14 +618,14 @@ namespace Duality {
|
|||
void interpolating_solver::RemoveInterpolationAxiom(const expr & t){
|
||||
// theory.remove(t);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *interpolating_solver::profile(){
|
||||
// return Z3_interpolation_profile(ctx());
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void get_assumptions_rec(stl_ext::hash_set<ast> &memo, const proof &pf, std::vector<expr> &assumps){
|
||||
if(memo.find(pf) != memo.end())return;
|
||||
memo.insert(pf);
|
||||
|
@ -657,7 +657,7 @@ namespace Duality {
|
|||
model_smt2_pp(std::cout, m(), *m_model, 0);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void model::show_hash() const {
|
||||
std::ostringstream ss;
|
||||
model_smt2_pp(ss, m(), *m_model, 0);
|
||||
|
|
|
@ -541,6 +541,7 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
|||
placeholder_arg |= is_placeholder(args[i]);
|
||||
}
|
||||
try {
|
||||
TRACE("duality", print_expr(tout, e); tout << "\n";);
|
||||
opr f = op(e);
|
||||
if(f == Equal && args[0] == args[1]) res = mk_true();
|
||||
else if(f == And) res = my_and(args);
|
||||
|
@ -853,6 +854,7 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
|||
|
||||
ast simplify_rotate_eq2leq(const ast &pl, const ast &neg_equality, const ast &pf){
|
||||
if(pl == arg(pf,1)){
|
||||
TRACE("duality", print_expr(tout, pl); print_expr(tout << "\n", neg_equality); print_expr(tout << "\n", pf); tout << "\n";);
|
||||
ast cond = mk_true();
|
||||
ast equa = sep_cond(arg(pf,0),cond);
|
||||
if(is_equivrel_chain(equa)){
|
||||
|
@ -1870,10 +1872,13 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
|||
|
||||
ast chain_ineqs(opr comp_op, LitType t, const ast &chain, const ast &lhs, const ast &rhs){
|
||||
if(is_true(chain)){
|
||||
if(lhs != rhs)
|
||||
if (lhs != rhs) {
|
||||
TRACE("duality", print_expr(tout, lhs); tout << " "; print_expr(tout, rhs); tout << "\n";);
|
||||
throw bad_ineq_inference();
|
||||
}
|
||||
return make(Leq,make_int(rational(0)),make_int(rational(0)));
|
||||
}
|
||||
TRACE("duality", print_expr(tout, chain); print_expr(tout << "\n", lhs); tout << " "; print_expr(tout, rhs); tout << "\n";);
|
||||
ast last = chain_last(chain);
|
||||
ast rest = chain_rest(chain);
|
||||
ast mid = subst_in_pos(rhs,rewrite_pos(last),rewrite_lhs(last));
|
||||
|
|
|
@ -47,14 +47,14 @@ Revision History:
|
|||
|
||||
namespace datalog {
|
||||
|
||||
rule_manager::rule_manager(context& ctx)
|
||||
rule_manager::rule_manager(context& ctx)
|
||||
: m(ctx.get_manager()),
|
||||
m_ctx(ctx),
|
||||
m_body(m),
|
||||
m_head(m),
|
||||
m_args(m),
|
||||
m_hnf(m),
|
||||
m_qe(m),
|
||||
m_qe(m, params_ref()),
|
||||
m_rwr(m),
|
||||
m_ufproc(m) {}
|
||||
|
||||
|
@ -98,7 +98,7 @@ namespace datalog {
|
|||
var_idx_set& rule_manager::finalize_collect_vars() {
|
||||
unsigned sz = m_free_vars.size();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
if (m_free_vars[i]) m_var_idx.insert(i);
|
||||
if (m_free_vars[i]) m_var_idx.insert(i);
|
||||
}
|
||||
return m_var_idx;
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ namespace datalog {
|
|||
}
|
||||
|
||||
|
||||
void rule_manager::mk_rule(expr* fml, proof* p, rule_set& rules, symbol const& name) {
|
||||
void rule_manager::mk_rule(expr* fml, proof* p, rule_set& rules, symbol const& name) {
|
||||
scoped_proof_mode _sc(m, m_ctx.generate_proof_trace()?PGM_FINE:PGM_DISABLED);
|
||||
proof_ref pr(p, m);
|
||||
expr_ref fml1(m);
|
||||
|
@ -147,7 +147,7 @@ namespace datalog {
|
|||
if (fml1 != fml && pr) {
|
||||
pr = m.mk_asserted(fml1);
|
||||
}
|
||||
remove_labels(fml1, pr);
|
||||
remove_labels(fml1, pr);
|
||||
mk_rule_core(fml1, pr, rules, name);
|
||||
}
|
||||
|
||||
|
@ -162,7 +162,7 @@ namespace datalog {
|
|||
else {
|
||||
is_negated.push_back(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rule_manager::mk_rule_core(expr* fml, proof* p, rule_set& rules, symbol const& name) {
|
||||
|
@ -170,7 +170,7 @@ namespace datalog {
|
|||
proof_ref_vector prs(m);
|
||||
m_hnf.reset();
|
||||
m_hnf.set_name(name);
|
||||
|
||||
|
||||
m_hnf(fml, p, fmls, prs);
|
||||
for (unsigned i = 0; i < m_hnf.get_fresh_predicates().size(); ++i) {
|
||||
m_ctx.register_predicate(m_hnf.get_fresh_predicates()[i], false);
|
||||
|
@ -181,7 +181,7 @@ namespace datalog {
|
|||
}
|
||||
|
||||
void rule_manager::mk_horn_rule(expr* fml, proof* p, rule_set& rules, symbol const& name) {
|
||||
|
||||
|
||||
m_body.reset();
|
||||
m_neg.reset();
|
||||
unsigned index = extract_horn(fml, m_body, m_head);
|
||||
|
@ -208,13 +208,13 @@ namespace datalog {
|
|||
}
|
||||
else if (is_quantifier(fml1)) {
|
||||
p = m.mk_modus_ponens(p, m.mk_symmetry(m.mk_der(to_quantifier(fml1), fml)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
p = m.mk_modus_ponens(p, m.mk_rewrite(fml, fml1));
|
||||
}
|
||||
}
|
||||
|
||||
if (m_ctx.fix_unbound_vars()) {
|
||||
if (m_ctx.fix_unbound_vars()) {
|
||||
fix_unbound_vars(r, true);
|
||||
}
|
||||
|
||||
|
@ -242,10 +242,10 @@ namespace datalog {
|
|||
for (unsigned i = 0; i < m_args.size(); ++i) {
|
||||
body.push_back(ensure_app(m_args[i].get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
head = ensure_app(fml);
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
|
@ -262,12 +262,12 @@ namespace datalog {
|
|||
|
||||
func_decl* rule_manager::mk_query(expr* query, rule_set& rules) {
|
||||
TRACE("dl", tout << mk_pp(query, m) << "\n";);
|
||||
|
||||
|
||||
ptr_vector<sort> vars;
|
||||
svector<symbol> names;
|
||||
app_ref_vector body(m);
|
||||
expr_ref q(m);
|
||||
|
||||
|
||||
// Add implicit variables.
|
||||
// Remove existential prefix.
|
||||
bind_variables(query, false, q);
|
||||
|
@ -278,7 +278,7 @@ namespace datalog {
|
|||
m_free_vars(q);
|
||||
vars.append(m_free_vars.size(), m_free_vars.c_ptr());
|
||||
if (vars.contains(static_cast<sort*>(0))) {
|
||||
var_subst sub(m, false);
|
||||
var_subst sub(m, false);
|
||||
expr_ref_vector args(m);
|
||||
// [s0, 0, s2, ..]
|
||||
// [0 -> 0, 1 -> x, 2 -> 1, ..]
|
||||
|
@ -313,7 +313,7 @@ namespace datalog {
|
|||
}
|
||||
}
|
||||
|
||||
// we want outermost declared variable first to
|
||||
// we want outermost declared variable first to
|
||||
// follow order of quantified variables so we reverse vars.
|
||||
while (vars.size() > names.size()) {
|
||||
names.push_back(symbol(names.size()));
|
||||
|
@ -321,9 +321,9 @@ namespace datalog {
|
|||
vars.reverse();
|
||||
names.reverse();
|
||||
func_decl* qpred = m_ctx.mk_fresh_head_predicate(symbol("query"), symbol(), vars.size(), vars.c_ptr(), body_pred);
|
||||
m_ctx.register_predicate(qpred, false);
|
||||
m_ctx.register_predicate(qpred, false);
|
||||
rules.set_output_predicate(qpred);
|
||||
|
||||
|
||||
if (m_ctx.get_model_converter()) {
|
||||
filter_model_converter* mc = alloc(filter_model_converter, m);
|
||||
mc->insert(qpred);
|
||||
|
@ -366,7 +366,7 @@ namespace datalog {
|
|||
for (unsigned i = 0; i < r.size(); ++i) {
|
||||
body.push_back(ensure_app(r[i].get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rule_manager::hoist_compound(unsigned& num_bound, app_ref& fml, app_ref_vector& body) {
|
||||
|
||||
|
@ -440,7 +440,7 @@ namespace datalog {
|
|||
if (is_quantifier(e)) {
|
||||
q = to_quantifier(e);
|
||||
return q->is_forall();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -454,7 +454,7 @@ namespace datalog {
|
|||
return app_ref(m.mk_eq(e, m.mk_true()), m);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void rule_manager::check_app(expr* e) {
|
||||
if (!is_app(e)) {
|
||||
std::ostringstream out;
|
||||
|
@ -481,7 +481,7 @@ namespace datalog {
|
|||
bool has_neg = false;
|
||||
|
||||
for (unsigned i = 0; i < n; i++) {
|
||||
bool is_neg = (is_negated != 0 && is_negated[i]);
|
||||
bool is_neg = (is_negated != 0 && is_negated[i]);
|
||||
app * curr = tail[i];
|
||||
|
||||
if (is_neg && !m_ctx.is_predicate(curr)) {
|
||||
|
@ -571,7 +571,7 @@ namespace datalog {
|
|||
case 1: fml = m.mk_implies(body[0].get(), fml); break;
|
||||
default: fml = m.mk_implies(m.mk_and(body.size(), body.c_ptr()), fml); break;
|
||||
}
|
||||
|
||||
|
||||
m_free_vars(fml);
|
||||
if (m_free_vars.empty()) {
|
||||
return;
|
||||
|
@ -579,7 +579,7 @@ namespace datalog {
|
|||
svector<symbol> names;
|
||||
used_symbols<> us;
|
||||
m_free_vars.set_default_sort(m.mk_bool_sort());
|
||||
|
||||
|
||||
us(fml);
|
||||
m_free_vars.reverse();
|
||||
for (unsigned j = 0, i = 0; i < m_free_vars.size(); ++j) {
|
||||
|
@ -594,8 +594,8 @@ namespace datalog {
|
|||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
fml = m.mk_forall(m_free_vars.size(), m_free_vars.c_ptr(), names.c_ptr(), fml);
|
||||
}
|
||||
fml = m.mk_forall(m_free_vars.size(), m_free_vars.c_ptr(), names.c_ptr(), fml);
|
||||
}
|
||||
|
||||
std::ostream& rule_manager::display_smt2(rule const& r, std::ostream & out) {
|
||||
|
@ -749,7 +749,7 @@ namespace datalog {
|
|||
quant_tail = m.mk_exists(q_var_cnt, qsorts.c_ptr(), qnames.c_ptr(), unbound_tail_pre_quant);
|
||||
|
||||
if (try_quantifier_elimination) {
|
||||
TRACE("dl_rule_unbound_fix_pre_qe",
|
||||
TRACE("dl_rule_unbound_fix_pre_qe",
|
||||
tout<<"rule: ";
|
||||
r->display(m_ctx, tout);
|
||||
tout<<"tail with unbound vars: "<<mk_pp(unbound_tail, m)<<"\n";
|
||||
|
@ -764,7 +764,7 @@ namespace datalog {
|
|||
fixed_tail = quant_tail;
|
||||
}
|
||||
|
||||
TRACE("dl_rule_unbound_fix",
|
||||
TRACE("dl_rule_unbound_fix",
|
||||
tout<<"rule: ";
|
||||
r->display(m_ctx, tout);
|
||||
tout<<"tail with unbound vars: "<<mk_pp(unbound_tail, m)<<"\n";
|
||||
|
@ -796,7 +796,7 @@ namespace datalog {
|
|||
to_formula(new_rule, fml);
|
||||
scoped_proof _sc(m);
|
||||
proof* p = m.mk_rewrite(m.get_fact(old_rule.get_proof()), fml);
|
||||
new_rule.set_proof(m, m.mk_modus_ponens(old_rule.get_proof(), p));
|
||||
new_rule.set_proof(m, m.mk_modus_ponens(old_rule.get_proof(), p));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -824,7 +824,7 @@ namespace datalog {
|
|||
}
|
||||
r = mk(new_head.get(), new_tail.size(), new_tail.c_ptr(), tail_neg.c_ptr(), r->name(), false);
|
||||
|
||||
// keep old variable indices around so we can compose with substitutions.
|
||||
// keep old variable indices around so we can compose with substitutions.
|
||||
// r->norm_vars(*this);
|
||||
}
|
||||
|
||||
|
@ -835,7 +835,7 @@ namespace datalog {
|
|||
|
||||
void rule_manager::check_valid_head(expr * head) const {
|
||||
SASSERT(head);
|
||||
|
||||
|
||||
if (!m_ctx.is_predicate(head)) {
|
||||
std::ostringstream out;
|
||||
out << "Illegal head. The head predicate needs to be uninterpreted and registered (as recursive) " << mk_pp(head, m);
|
||||
|
@ -874,14 +874,14 @@ namespace datalog {
|
|||
m.get_allocator().deallocate(get_obj_size(n), this);
|
||||
}
|
||||
|
||||
void rule::set_proof(ast_manager& m, proof* p) {
|
||||
void rule::set_proof(ast_manager& m, proof* p) {
|
||||
if (p) {
|
||||
m.inc_ref(p);
|
||||
m.inc_ref(p);
|
||||
}
|
||||
if (m_proof) {
|
||||
m.dec_ref(m_proof);
|
||||
m.dec_ref(m_proof);
|
||||
}
|
||||
m_proof = p;
|
||||
m_proof = p;
|
||||
}
|
||||
|
||||
bool rule::is_in_tail(const func_decl * p, bool only_positive) const {
|
||||
|
@ -896,7 +896,7 @@ namespace datalog {
|
|||
|
||||
|
||||
//
|
||||
// non-predicates may appear only in the interpreted tail, it is therefore
|
||||
// non-predicates may appear only in the interpreted tail, it is therefore
|
||||
// sufficient only to check the tail.
|
||||
//
|
||||
bool rule_manager::has_uninterpreted_non_predicates(rule const& r, func_decl*& f) const {
|
||||
|
@ -911,7 +911,7 @@ namespace datalog {
|
|||
|
||||
|
||||
//
|
||||
// Quantifiers may appear only in the interpreted tail, it is therefore
|
||||
// Quantifiers may appear only in the interpreted tail, it is therefore
|
||||
// sufficient only to check the interpreted tail.
|
||||
//
|
||||
void rule_manager::has_quantifiers(rule const& r, bool& existential, bool& universal) const {
|
||||
|
@ -945,7 +945,7 @@ namespace datalog {
|
|||
unsigned sz = get_tail_size();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
used.process(get_tail(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rule::get_vars(ast_manager& m, ptr_vector<sort>& sorts) const {
|
||||
|
@ -994,13 +994,13 @@ namespace datalog {
|
|||
app * old_tail = get_tail(i);
|
||||
expr_ref new_tail_e(m);
|
||||
vs(old_tail, subst_vals.size(), subst_vals.c_ptr(), new_tail_e);
|
||||
bool sign = is_neg_tail(i);
|
||||
bool sign = is_neg_tail(i);
|
||||
m.inc_ref(new_tail_e);
|
||||
m.dec_ref(old_tail);
|
||||
m_tail[i] = TAG(app *, to_app(new_tail_e), sign);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void rule::display(context & ctx, std::ostream & out) const {
|
||||
ast_manager & m = ctx.get_manager();
|
||||
//out << mk_pp(m_head, m);
|
||||
|
@ -1068,7 +1068,7 @@ namespace datalog {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1007,7 +1007,7 @@ namespace pdr {
|
|||
return m_cache[l];
|
||||
}
|
||||
|
||||
void model_search::erase_children(model_node& n, bool backtrack) {
|
||||
void model_search::erase_children(model_node& n, bool backtrack) {
|
||||
ptr_vector<model_node> todo, nodes;
|
||||
todo.append(n.children());
|
||||
remove_goal(n);
|
||||
|
@ -2241,7 +2241,7 @@ namespace pdr {
|
|||
vars.append(aux_vars.size(), aux_vars.c_ptr());
|
||||
|
||||
scoped_ptr<expr_replacer> rep;
|
||||
qe_lite qe(m);
|
||||
qe_lite qe(m, m_params.p);
|
||||
expr_ref phi1 = m_pm.mk_and(Phi);
|
||||
qe(vars, phi1);
|
||||
TRACE("pdr", tout << "Eliminated\n" << mk_pp(phi1, m) << "\n";);
|
||||
|
|
|
@ -53,10 +53,10 @@ namespace tb {
|
|||
app* t = to_app(_t);
|
||||
|
||||
if (m.is_value(s) && m.is_value(t)) {
|
||||
IF_VERBOSE(2, verbose_stream() << "different:" << mk_pp(s, m) << " " << mk_pp(t, m) << "\n";);
|
||||
IF_VERBOSE(2, verbose_stream() << "different:" << mk_pp(s, m) << " " << mk_pp(t, m) << "\n";);
|
||||
return l_false;
|
||||
}
|
||||
|
||||
|
||||
if (m_dt.is_constructor(s) && m_dt.is_constructor(t)) {
|
||||
if (s->get_decl() == t->get_decl()) {
|
||||
lbool state = l_true;
|
||||
|
@ -75,7 +75,7 @@ namespace tb {
|
|||
return state;
|
||||
}
|
||||
else {
|
||||
IF_VERBOSE(2, verbose_stream() << "different constructors:" << mk_pp(s, m) << " " << mk_pp(t, m) << "\n";);
|
||||
IF_VERBOSE(2, verbose_stream() << "different constructors:" << mk_pp(s, m) << " " << mk_pp(t, m) << "\n";);
|
||||
return l_false;
|
||||
}
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ namespace tb {
|
|||
case l_false:
|
||||
return false;
|
||||
default:
|
||||
conds.push_back(m.mk_eq(p, t));
|
||||
conds.push_back(m.mk_eq(p, t));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ namespace tb {
|
|||
|
||||
public:
|
||||
matcher(ast_manager& m): m(m), m_dt(m) {}
|
||||
|
||||
|
||||
bool operator()(app* pat, app* term, substitution& s, expr_ref_vector& conds) {
|
||||
// top-most term to match is a predicate. The predicates should be the same.
|
||||
if (pat->get_decl() != term->get_decl() ||
|
||||
|
@ -149,7 +149,7 @@ namespace tb {
|
|||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class clause {
|
||||
|
@ -165,22 +165,22 @@ namespace tb {
|
|||
unsigned m_next_rule; // next rule to expand goal on
|
||||
unsigned m_ref; // reference count
|
||||
|
||||
public:
|
||||
|
||||
public:
|
||||
|
||||
clause(ast_manager& m):
|
||||
m_head(m),
|
||||
m_predicates(m),
|
||||
m_constraint(m),
|
||||
m_seqno(0),
|
||||
m_index(0),
|
||||
m_index(0),
|
||||
m_num_vars(0),
|
||||
m_predicate_index(0),
|
||||
m_predicate_index(0),
|
||||
m_parent_rule(0),
|
||||
m_parent_index(0),
|
||||
m_next_rule(static_cast<unsigned>(-1)),
|
||||
m_ref(0) {
|
||||
}
|
||||
|
||||
|
||||
void set_seqno(unsigned seqno) { m_seqno = seqno; }
|
||||
unsigned get_seqno() const { return m_seqno; }
|
||||
unsigned get_next_rule() const { return m_next_rule; }
|
||||
|
@ -198,10 +198,10 @@ namespace tb {
|
|||
void set_head(app* h) { m_head = h; }
|
||||
unsigned get_parent_index() const { return m_parent_index; }
|
||||
unsigned get_parent_rule() const { return m_parent_rule; }
|
||||
void set_parent(ref<tb::clause>& parent) {
|
||||
void set_parent(ref<tb::clause>& parent) {
|
||||
m_parent_index = parent->get_index();
|
||||
m_parent_rule = parent->get_next_rule();
|
||||
}
|
||||
}
|
||||
|
||||
expr_ref get_body() const {
|
||||
ast_manager& m = get_manager();
|
||||
|
@ -247,7 +247,7 @@ namespace tb {
|
|||
}
|
||||
if (!vars.empty()) {
|
||||
body = m.mk_forall(vars.size(), vars.c_ptr(), names.c_ptr(), body);
|
||||
}
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
|
@ -273,18 +273,18 @@ namespace tb {
|
|||
reduce_equalities();
|
||||
// IF_VERBOSE(1, display(verbose_stream()););
|
||||
}
|
||||
|
||||
|
||||
void inc_ref() {
|
||||
m_ref++;
|
||||
}
|
||||
|
||||
|
||||
void dec_ref() {
|
||||
--m_ref;
|
||||
if (m_ref == 0) {
|
||||
dealloc(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void display(std::ostream& out) const {
|
||||
ast_manager& m = m_head.get_manager();
|
||||
expr_ref_vector fmls(m);
|
||||
|
@ -304,7 +304,7 @@ namespace tb {
|
|||
}
|
||||
out << mk_pp(fml, m) << "\n";
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
ast_manager& get_manager() const { return m_head.get_manager(); }
|
||||
|
@ -314,7 +314,7 @@ namespace tb {
|
|||
// - m_head - head predicate
|
||||
// - m_predicates - auxiliary predicates in body.
|
||||
// - m_constraint - side constraint
|
||||
//
|
||||
//
|
||||
void init_from_rule(datalog::rule_ref const& r) {
|
||||
ast_manager& m = get_manager();
|
||||
expr_ref_vector fmls(m);
|
||||
|
@ -328,7 +328,7 @@ namespace tb {
|
|||
m_predicates.reset();
|
||||
for (unsigned i = 0; i < utsz; ++i) {
|
||||
m_predicates.push_back(r->get_tail(i));
|
||||
}
|
||||
}
|
||||
bool_rewriter(m).mk_and(fmls.size(), fmls.c_ptr(), m_constraint);
|
||||
}
|
||||
|
||||
|
@ -348,13 +348,13 @@ namespace tb {
|
|||
if (get_subst(rw, subst, i, fmls)) {
|
||||
fmls[i] = m.mk_true();
|
||||
}
|
||||
}
|
||||
}
|
||||
subst.apply(1, delta, expr_offset(m_head, 0), tmp);
|
||||
m_head = to_app(tmp);
|
||||
for (unsigned i = 0; i < m_predicates.size(); ++i) {
|
||||
subst.apply(1, delta, expr_offset(m_predicates[i].get(), 0), tmp);
|
||||
m_predicates[i] = to_app(tmp);
|
||||
}
|
||||
}
|
||||
bool_rewriter(m).mk_and(fmls.size(), fmls.c_ptr(), m_constraint);
|
||||
subst.apply(1, delta, expr_offset(m_constraint, 0), m_constraint);
|
||||
rw(m_constraint);
|
||||
|
@ -404,7 +404,7 @@ namespace tb {
|
|||
throw non_constructor();
|
||||
}
|
||||
}
|
||||
void operator()(var* v) { }
|
||||
void operator()(var* v) { }
|
||||
void operator()(quantifier* ) {
|
||||
throw non_constructor();
|
||||
}
|
||||
|
@ -421,7 +421,7 @@ namespace tb {
|
|||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
// rules
|
||||
class rules {
|
||||
|
@ -456,7 +456,7 @@ namespace tb {
|
|||
func_decl* f = g->get_decl();
|
||||
map::obj_map_entry* e = m_index.insert_if_not_there2(f, unsigned_vector());
|
||||
SASSERT(e);
|
||||
e->get_data().m_value.push_back(idx);
|
||||
e->get_data().m_value.push_back(idx);
|
||||
}
|
||||
|
||||
unsigned get_num_rules(func_decl* p) const {
|
||||
|
@ -475,14 +475,14 @@ namespace tb {
|
|||
for (; it != end; ++it) {
|
||||
decls.push_back(it->m_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ref<clause> get_rule(func_decl* p, unsigned idx) const {
|
||||
map::obj_map_entry* e = m_index.find_core(p);
|
||||
SASSERT(p);
|
||||
unsigned rule_id = e->get_data().get_value()[idx];
|
||||
return m_rules[rule_id];
|
||||
}
|
||||
}
|
||||
private:
|
||||
void reset() {
|
||||
m_rules.reset();
|
||||
|
@ -509,7 +509,7 @@ namespace tb {
|
|||
bool_rewriter m_rw;
|
||||
smt_params m_fparams;
|
||||
smt::kernel m_solver;
|
||||
|
||||
|
||||
public:
|
||||
index(ast_manager& m):
|
||||
m(m),
|
||||
|
@ -520,7 +520,7 @@ namespace tb {
|
|||
m_matcher(m),
|
||||
m_refs(m),
|
||||
m_subst(m),
|
||||
m_qe(m),
|
||||
m_qe(m, params_ref()),
|
||||
m_rw(m),
|
||||
m_solver(m, m_fparams) {}
|
||||
|
||||
|
@ -544,7 +544,7 @@ namespace tb {
|
|||
}
|
||||
|
||||
private:
|
||||
|
||||
|
||||
void setup(clause const& g) {
|
||||
m_preds.reset();
|
||||
m_refs.reset();
|
||||
|
@ -569,8 +569,8 @@ namespace tb {
|
|||
}
|
||||
vs(g.get_constraint(), vars.size(), vars.c_ptr(), fml);
|
||||
fmls.push_back(fml);
|
||||
m_precond = m.mk_and(fmls.size(), fmls.c_ptr());
|
||||
IF_VERBOSE(2,
|
||||
m_precond = m.mk_and(fmls.size(), fmls.c_ptr());
|
||||
IF_VERBOSE(2,
|
||||
verbose_stream() << "setup-match: ";
|
||||
for (unsigned i = 0; i < m_preds.size(); ++i) {
|
||||
verbose_stream() << mk_pp(m_preds[i].get(), m) << " ";
|
||||
|
@ -587,18 +587,18 @@ namespace tb {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
//
|
||||
// check that each predicate in r is matched by some predicate in premise.
|
||||
// for now: skip multiple matches within the same rule (incomplete).
|
||||
//
|
||||
bool match_rule(unsigned rule_index) {
|
||||
clause const& g = *m_index[rule_index];
|
||||
clause const& g = *m_index[rule_index];
|
||||
m_sideconds.reset();
|
||||
m_subst.reset();
|
||||
m_subst.reserve(2, g.get_num_vars());
|
||||
|
||||
|
||||
IF_VERBOSE(2, g.display(verbose_stream() << "try-match\n"););
|
||||
|
||||
return match_head(g);
|
||||
|
@ -628,9 +628,9 @@ namespace tb {
|
|||
}
|
||||
verbose_stream() << mk_pp(q, m) << " = " << mk_pp(p, m) << "\n";
|
||||
);
|
||||
|
||||
|
||||
if (q->get_decl() == p->get_decl() &&
|
||||
|
||||
if (q->get_decl() == p->get_decl() &&
|
||||
m_matcher(q, p, m_subst, m_sideconds) &&
|
||||
match_predicates(predicate_index + 1, g)) {
|
||||
return true;
|
||||
|
@ -646,7 +646,7 @@ namespace tb {
|
|||
expr_ref q(m), postcond(m);
|
||||
expr_ref_vector fmls(m_sideconds);
|
||||
m_subst.reset_cache();
|
||||
|
||||
|
||||
for (unsigned i = 0; !m.canceled() && i < fmls.size(); ++i) {
|
||||
m_subst.apply(2, deltas, expr_offset(fmls[i].get(), 0), q);
|
||||
fmls[i] = q;
|
||||
|
@ -680,7 +680,7 @@ namespace tb {
|
|||
verbose_stream() << "check: " << mk_pp(postcond, m, 7 + g.get_num_predicates()) << "\n";);
|
||||
|
||||
if (!is_ground(postcond)) {
|
||||
IF_VERBOSE(1, verbose_stream() << "TBD: non-ground\n"
|
||||
IF_VERBOSE(1, verbose_stream() << "TBD: non-ground\n"
|
||||
<< mk_pp(postcond, m) << "\n";
|
||||
m_clause->display(verbose_stream());
|
||||
verbose_stream() << "\n=>\n";
|
||||
|
@ -743,7 +743,7 @@ namespace tb {
|
|||
double m_weight_multiply;
|
||||
unsigned m_update_frequency;
|
||||
unsigned m_next_update;
|
||||
|
||||
|
||||
|
||||
public:
|
||||
selection(datalog::context& ctx):
|
||||
|
@ -766,7 +766,7 @@ namespace tb {
|
|||
scores.reset();
|
||||
basic_score_predicate(p, scores);
|
||||
insert_score(p->get_decl(), scores);
|
||||
}
|
||||
}
|
||||
normalize_scores(rs);
|
||||
}
|
||||
|
||||
|
@ -783,7 +783,7 @@ namespace tb {
|
|||
default:
|
||||
return weight_select(g);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void reset() {
|
||||
|
@ -867,8 +867,8 @@ namespace tb {
|
|||
}
|
||||
}
|
||||
IF_VERBOSE(1, verbose_stream() << "select:" << result << "\n";);
|
||||
|
||||
return result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned basic_weight_select(clause const& g) {
|
||||
|
@ -957,7 +957,7 @@ namespace tb {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
double score_predicate(app* p) {
|
||||
double score = 1;
|
||||
if (find_score(p, score)) {
|
||||
|
@ -1031,7 +1031,7 @@ namespace tb {
|
|||
}
|
||||
else {
|
||||
m_score_map.insert(f, scores);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1044,15 +1044,15 @@ namespace tb {
|
|||
expr_ref_vector m_sub1;
|
||||
expr_ref_vector m_sub2;
|
||||
public:
|
||||
unifier(ast_manager& m):
|
||||
m(m),
|
||||
unifier(ast_manager& m):
|
||||
m(m),
|
||||
m_unifier(m),
|
||||
m_S1(m),
|
||||
m_S2(m, false),
|
||||
m_rename(m),
|
||||
m_sub1(m),
|
||||
m_sub1(m),
|
||||
m_sub2(m) {}
|
||||
|
||||
|
||||
bool operator()(ref<clause>& tgt, unsigned idx, ref<clause>& src, bool compute_subst, ref<clause>& result) {
|
||||
return unify(*tgt, idx, *src, compute_subst, result);
|
||||
}
|
||||
|
@ -1066,12 +1066,12 @@ namespace tb {
|
|||
}
|
||||
}
|
||||
|
||||
bool unify(clause const& tgt, unsigned idx, clause const& src, bool compute_subst, ref<clause>& result) {
|
||||
qe_lite qe(m);
|
||||
bool unify(clause const& tgt, unsigned idx, clause const& src, bool compute_subst, ref<clause>& result) {
|
||||
qe_lite qe(m, params_ref());
|
||||
reset();
|
||||
SASSERT(tgt.get_predicate(idx)->get_decl() == src.get_decl());
|
||||
unsigned var_cnt = std::max(tgt.get_num_vars(), src.get_num_vars());
|
||||
m_S1.reserve(2, var_cnt);
|
||||
m_S1.reserve(2, var_cnt);
|
||||
if (!m_unifier(tgt.get_predicate(idx), src.get_head(), m_S1)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1080,7 +1080,7 @@ namespace tb {
|
|||
app_ref head(m);
|
||||
result = alloc(clause, m);
|
||||
unsigned delta[2] = { 0, var_cnt };
|
||||
m_S1.apply(2, delta, expr_offset(tgt.get_head(), 0), tmp);
|
||||
m_S1.apply(2, delta, expr_offset(tgt.get_head(), 0), tmp);
|
||||
head = to_app(tmp);
|
||||
for (unsigned i = 0; i < tgt.get_num_predicates(); ++i) {
|
||||
if (i != idx) {
|
||||
|
@ -1096,7 +1096,7 @@ namespace tb {
|
|||
}
|
||||
m_S1.apply(2, delta, expr_offset(tgt.get_constraint(), 0), tmp);
|
||||
m_S1.apply(2, delta, expr_offset(src.get_constraint(), 1), tmp2);
|
||||
constraint = m.mk_and(tmp, tmp2);
|
||||
constraint = m.mk_and(tmp, tmp2);
|
||||
|
||||
// perform trival quantifier-elimination:
|
||||
uint_set index_set;
|
||||
|
@ -1114,7 +1114,7 @@ namespace tb {
|
|||
if (m.is_false(constraint)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// initialize rule.
|
||||
result->init(head, predicates, constraint);
|
||||
ptr_vector<sort> vars;
|
||||
|
@ -1147,10 +1147,10 @@ namespace tb {
|
|||
extract_subst(delta, src, 1);
|
||||
}
|
||||
// init result using head, predicates, constraint
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
void reset() {
|
||||
m_S1.reset();
|
||||
|
@ -1175,9 +1175,9 @@ namespace tb {
|
|||
else {
|
||||
insert_subst(offset, m.mk_true());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void insert_subst(unsigned offset, expr* e) {
|
||||
if (offset == 0) {
|
||||
m_sub1.push_back(e);
|
||||
|
@ -1201,7 +1201,7 @@ namespace tb {
|
|||
|
||||
|
||||
//
|
||||
// Given a clause
|
||||
// Given a clause
|
||||
// P(s) :- P(t), Phi(x).
|
||||
// Compute the clauses:
|
||||
// acc: P(s) :- Delta(z,t), P(z), Phi(x).
|
||||
|
@ -1237,7 +1237,7 @@ namespace tb {
|
|||
head = m.mk_app(delta, zszs.size(), zszs.c_ptr());
|
||||
for (unsigned i = 0; i < zs.size(); ++i) {
|
||||
zszs[i+zs.size()] = q->get_arg(i);
|
||||
}
|
||||
}
|
||||
pred = m.mk_app(delta, zszs.size(), zszs.c_ptr());
|
||||
preds.push_back(pred);
|
||||
for (unsigned i = 1; i < g.get_num_predicates(); ++i) {
|
||||
|
@ -1247,28 +1247,28 @@ namespace tb {
|
|||
preds.push_back(m.mk_app(q->get_decl(), zs.size(), zs.c_ptr()));
|
||||
acc->init(p, preds, g.get_constraint());
|
||||
|
||||
IF_VERBOSE(1,
|
||||
IF_VERBOSE(1,
|
||||
delta1->display(verbose_stream() << "delta1:\n");
|
||||
delta2->display(verbose_stream() << "delta2:\n");
|
||||
acc->display(verbose_stream() << "acc:\n"););
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// Given a sequence of clauses and inference rules
|
||||
// compute a super-predicate and auxiliary clauses.
|
||||
//
|
||||
//
|
||||
// P1(x) :- P2(y), R(z)
|
||||
// P2(y) :- P3(z), T(u)
|
||||
// P3(z) :- P1(x), U(v)
|
||||
// =>
|
||||
// P1(x) :- P1(x), R(z), T(u), U(v)
|
||||
//
|
||||
//
|
||||
|
||||
ref<clause> resolve_rules(unsigned num_clauses, clause*const* clauses, unsigned const* positions) {
|
||||
ref<clause> result = clauses[0];
|
||||
ref<clause> tmp;
|
||||
unsigned offset = 0;
|
||||
for (unsigned i = 0; i + 1 < num_clauses; ++i) {
|
||||
for (unsigned i = 0; i + 1 < num_clauses; ++i) {
|
||||
clause const& cl = *clauses[i+1];
|
||||
offset += positions[i];
|
||||
VERIFY (m_unifier.unify(*result, offset, cl, false, tmp));
|
||||
|
@ -1276,7 +1276,7 @@ namespace tb {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
@ -1286,7 +1286,7 @@ namespace tb {
|
|||
unsigned num_vars = g.get_num_vars();
|
||||
for (unsigned i = 0; i < p->get_num_args(); ++i) {
|
||||
result.push_back(m.mk_var(num_vars+i, m.get_sort(p->get_arg(i))));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
@ -1341,7 +1341,7 @@ namespace datalog {
|
|||
uint_set m_displayed_rules;
|
||||
public:
|
||||
imp(context& ctx):
|
||||
m_ctx(ctx),
|
||||
m_ctx(ctx),
|
||||
m(ctx.get_manager()),
|
||||
rm(ctx.get_rule_manager()),
|
||||
m_index(m),
|
||||
|
@ -1358,7 +1358,7 @@ namespace datalog {
|
|||
m_fparams.m_timeout = 1000;
|
||||
}
|
||||
|
||||
~imp() {}
|
||||
~imp() {}
|
||||
|
||||
lbool query(expr* query) {
|
||||
m_ctx.ensure_opened();
|
||||
|
@ -1378,7 +1378,7 @@ namespace datalog {
|
|||
IF_VERBOSE(1, display_clause(*get_clause(), verbose_stream() << "g" << get_clause()->get_seqno() << " "););
|
||||
return run();
|
||||
}
|
||||
|
||||
|
||||
void cleanup() {
|
||||
m_clauses.reset();
|
||||
}
|
||||
|
@ -1400,7 +1400,7 @@ namespace datalog {
|
|||
|
||||
expr_ref get_answer() const {
|
||||
switch(m_status) {
|
||||
case l_undef:
|
||||
case l_undef:
|
||||
UNREACHABLE();
|
||||
return expr_ref(m.mk_false(), m);
|
||||
case l_true: {
|
||||
|
@ -1415,7 +1415,7 @@ namespace datalog {
|
|||
return expr_ref(m.mk_true(), m);
|
||||
}
|
||||
private:
|
||||
|
||||
|
||||
void select_predicate() {
|
||||
tb::clause & g = *get_clause();
|
||||
unsigned num_predicates = g.get_num_predicates();
|
||||
|
@ -1430,17 +1430,17 @@ namespace datalog {
|
|||
IF_VERBOSE(2, verbose_stream() << mk_pp(g.get_predicate(pi), m) << "\n";);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void apply_rule(ref<tb::clause>& r) {
|
||||
ref<tb::clause> clause = get_clause();
|
||||
ref<tb::clause> next_clause;
|
||||
ref<tb::clause> next_clause;
|
||||
if (m_unifier(clause, clause->get_predicate_index(), r, false, next_clause) &&
|
||||
!query_is_tautology(*next_clause)) {
|
||||
init_clause(next_clause);
|
||||
unsigned subsumer = 0;
|
||||
IF_VERBOSE(1,
|
||||
IF_VERBOSE(1,
|
||||
display_rule(*clause, verbose_stream());
|
||||
display_premise(*clause,
|
||||
display_premise(*clause,
|
||||
verbose_stream() << "g" << next_clause->get_seqno() << " ");
|
||||
display_clause(*next_clause, verbose_stream());
|
||||
);
|
||||
|
@ -1462,8 +1462,8 @@ namespace datalog {
|
|||
m_instruction = tb::SELECT_RULE;
|
||||
}
|
||||
}
|
||||
|
||||
void select_rule() {
|
||||
|
||||
void select_rule() {
|
||||
tb::clause& g = *get_clause();
|
||||
g.inc_next_rule();
|
||||
unsigned pi = g.get_predicate_index();
|
||||
|
@ -1481,7 +1481,7 @@ namespace datalog {
|
|||
|
||||
void backtrack() {
|
||||
SASSERT(!m_clauses.empty());
|
||||
m_clauses.pop_back();
|
||||
m_clauses.pop_back();
|
||||
if (m_clauses.empty()) {
|
||||
m_instruction = tb::SATISFIABLE;
|
||||
}
|
||||
|
@ -1500,16 +1500,16 @@ namespace datalog {
|
|||
return l_undef;
|
||||
}
|
||||
switch(m_instruction) {
|
||||
case tb::SELECT_PREDICATE:
|
||||
select_predicate();
|
||||
case tb::SELECT_PREDICATE:
|
||||
select_predicate();
|
||||
break;
|
||||
case tb::SELECT_RULE:
|
||||
select_rule();
|
||||
case tb::SELECT_RULE:
|
||||
select_rule();
|
||||
break;
|
||||
case tb::BACKTRACK:
|
||||
backtrack();
|
||||
break;
|
||||
case tb::SATISFIABLE:
|
||||
case tb::SATISFIABLE:
|
||||
m_status = l_false;
|
||||
return l_false;
|
||||
case tb::UNSATISFIABLE:
|
||||
|
@ -1522,18 +1522,18 @@ namespace datalog {
|
|||
return l_undef;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool query_is_tautology(tb::clause const& g) {
|
||||
expr_ref fml = g.to_formula();
|
||||
fml = m.mk_not(fml);
|
||||
m_solver.push();
|
||||
m_solver.assert_expr(fml);
|
||||
lbool is_sat = m_solver.check();
|
||||
lbool is_sat = m_solver.check();
|
||||
m_solver.pop(1);
|
||||
|
||||
TRACE("dl", tout << is_sat << ":\n" << mk_pp(fml, m) << "\n";);
|
||||
|
||||
|
||||
return l_false == is_sat;
|
||||
|
||||
}
|
||||
|
@ -1560,7 +1560,7 @@ namespace datalog {
|
|||
|
||||
void display_premise(tb::clause& p, std::ostream& out) {
|
||||
func_decl* f = p.get_predicate(p.get_predicate_index())->get_decl();
|
||||
out << "{g" << p.get_seqno() << " " << f->get_name() << " pos: "
|
||||
out << "{g" << p.get_seqno() << " " << f->get_name() << " pos: "
|
||||
<< p.get_predicate_index() << " rule: " << p.get_next_rule() << "}\n";
|
||||
}
|
||||
|
||||
|
@ -1576,21 +1576,21 @@ namespace datalog {
|
|||
ref<tb::clause> replayed_clause;
|
||||
replace_proof_converter pc(m);
|
||||
|
||||
// clause is a empty clause.
|
||||
// clause is a empty clause.
|
||||
// Pretend it is asserted.
|
||||
// It gets replaced by premises.
|
||||
SASSERT(clause->get_num_predicates() == 0);
|
||||
SASSERT(clause->get_num_predicates() == 0);
|
||||
expr_ref root = clause->to_formula();
|
||||
|
||||
vector<expr_ref_vector> substs;
|
||||
while (0 != clause->get_index()) {
|
||||
SASSERT(clause->get_parent_index() < clause->get_index());
|
||||
while (0 != clause->get_index()) {
|
||||
SASSERT(clause->get_parent_index() < clause->get_index());
|
||||
unsigned p_index = clause->get_parent_index();
|
||||
unsigned p_rule = clause->get_parent_rule();
|
||||
ref<tb::clause> parent = m_clauses[p_index];
|
||||
unsigned pi = parent->get_predicate_index();
|
||||
func_decl* pred = parent->get_predicate(pi)->get_decl();
|
||||
ref<tb::clause> rl = m_rules.get_rule(pred, p_rule);
|
||||
ref<tb::clause> rl = m_rules.get_rule(pred, p_rule);
|
||||
VERIFY(m_unifier(parent, parent->get_predicate_index(), rl, true, replayed_clause));
|
||||
expr_ref_vector s1(m_unifier.get_rule_subst(true));
|
||||
expr_ref_vector s2(m_unifier.get_rule_subst(false));
|
||||
|
@ -1614,36 +1614,36 @@ namespace datalog {
|
|||
}
|
||||
expr_ref body = clause.get_body();
|
||||
var_subst vs(m, false);
|
||||
vs(body, subst.size(), subst.c_ptr(), body);
|
||||
vs(body, subst.size(), subst.c_ptr(), body);
|
||||
out << mk_pp(body, m) << "\n";
|
||||
}
|
||||
|
||||
void resolve_rule(replace_proof_converter& pc, tb::clause const& r1, tb::clause const& r2,
|
||||
void resolve_rule(replace_proof_converter& pc, tb::clause const& r1, tb::clause const& r2,
|
||||
expr_ref_vector const& s1, expr_ref_vector const& s2, tb::clause const& res) const {
|
||||
unsigned idx = r1.get_predicate_index();
|
||||
expr_ref fml = res.to_formula();
|
||||
vector<expr_ref_vector> substs;
|
||||
svector<std::pair<unsigned, unsigned> > positions;
|
||||
substs.push_back(s1);
|
||||
substs.push_back(s2);
|
||||
substs.push_back(s2);
|
||||
scoped_proof _sc(m);
|
||||
proof_ref pr(m);
|
||||
proof_ref_vector premises(m);
|
||||
premises.push_back(m.mk_asserted(r1.to_formula()));
|
||||
premises.push_back(m.mk_asserted(r2.to_formula()));
|
||||
positions.push_back(std::make_pair(idx+1, 0));
|
||||
positions.push_back(std::make_pair(idx+1, 0));
|
||||
pr = m.mk_hyper_resolve(2, premises.c_ptr(), fml, positions, substs);
|
||||
pc.insert(pr);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
tab::tab(context& ctx):
|
||||
datalog::engine_base(ctx.get_manager(),"tabulation"),
|
||||
m_imp(alloc(imp, ctx)) {
|
||||
m_imp(alloc(imp, ctx)) {
|
||||
}
|
||||
tab::~tab() {
|
||||
dealloc(m_imp);
|
||||
}
|
||||
}
|
||||
lbool tab::query(expr* query) {
|
||||
return m_imp->query(query);
|
||||
}
|
||||
|
|
|
@ -126,6 +126,12 @@ namespace datalog {
|
|||
app* s;
|
||||
var* v;
|
||||
|
||||
// disable Ackerman reduction if head contains a non-variable or non-constant argument.
|
||||
for (unsigned i = 0; i < to_app(head)->get_num_args(); ++i) {
|
||||
expr* arg = to_app(head)->get_arg(i);
|
||||
if (!is_var(arg) && !m.is_value(arg)) return false;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < conjs.size(); ++i) {
|
||||
expr* e = conjs[i].get();
|
||||
if (is_select_eq_var(e, s, v)) {
|
||||
|
@ -281,6 +287,7 @@ namespace datalog {
|
|||
m_rewriter(body);
|
||||
sub(head);
|
||||
m_rewriter(head);
|
||||
TRACE("dl", tout << body << " => " << head << "\n";);
|
||||
change = ackermanize(r, body, head);
|
||||
if (!change) {
|
||||
rules.add_rule(&r);
|
||||
|
|
|
@ -394,10 +394,6 @@ namespace datalog {
|
|||
m_simp(a, simp1_res);
|
||||
(*m_rw)(simp1_res.get(), res);
|
||||
|
||||
/*if (simp1_res.get()!=res.get()) {
|
||||
std::cout<<"pre norm:\n"<<mk_pp(simp1_res.get(),m)<<"post norm:\n"<<mk_pp(res.get(),m)<<"\n";
|
||||
}*/
|
||||
|
||||
m_simp(res.get(), res);
|
||||
}
|
||||
|
||||
|
|
|
@ -272,7 +272,8 @@ namespace opt {
|
|||
s.assert_expr(m_hard_constraints);
|
||||
IF_VERBOSE(1, verbose_stream() << "(optimize:check-sat)\n";);
|
||||
lbool is_sat = s.check_sat(0,0);
|
||||
TRACE("opt", tout << "initial search result: " << is_sat << "\n";);
|
||||
TRACE("opt", tout << "initial search result: " << is_sat << "\n";
|
||||
s.display(tout););
|
||||
if (is_sat != l_false) {
|
||||
s.get_model(m_model);
|
||||
s.get_labels(m_labels);
|
||||
|
@ -340,6 +341,14 @@ namespace opt {
|
|||
fix_model(mdl);
|
||||
}
|
||||
|
||||
void context::get_box_model(model_ref& mdl, unsigned index) {
|
||||
if (index >= m_box_models.size()) {
|
||||
throw default_exception("index into models is out of bounds");
|
||||
}
|
||||
mdl = m_box_models[index];
|
||||
fix_model(mdl);
|
||||
}
|
||||
|
||||
lbool context::execute_min_max(unsigned index, bool committed, bool scoped, bool is_max) {
|
||||
if (scoped) get_solver().push();
|
||||
lbool result = m_optsmt.lex(index, is_max);
|
||||
|
@ -1036,6 +1045,10 @@ namespace opt {
|
|||
TRACE("opt", tout << "Purifying " << term << "\n";);
|
||||
term = purify(fm, term);
|
||||
}
|
||||
else if (m.is_ite(term)) {
|
||||
TRACE("opt", tout << "Purifying " << term << "\n";);
|
||||
term = purify(fm, term);
|
||||
}
|
||||
if (fm) {
|
||||
m_model_converter = concat(m_model_converter.get(), fm.get());
|
||||
}
|
||||
|
@ -1226,7 +1239,7 @@ namespace opt {
|
|||
out << " (";
|
||||
display_objective(out, obj);
|
||||
if (get_lower_as_num(i) != get_upper_as_num(i)) {
|
||||
out << " (" << get_lower(i) << " " << get_upper(i) << ")";
|
||||
out << " (interval " << get_lower(i) << " " << get_upper(i) << ")";
|
||||
}
|
||||
else {
|
||||
out << " " << get_lower(i);
|
||||
|
|
|
@ -186,6 +186,7 @@ namespace opt {
|
|||
virtual bool print_model() const;
|
||||
virtual void set_model(model_ref& _m) { m_model = _m; }
|
||||
virtual void get_model(model_ref& _m);
|
||||
virtual void get_box_model(model_ref& _m, unsigned index);
|
||||
virtual void fix_model(model_ref& _m);
|
||||
virtual void collect_statistics(statistics& stats) const;
|
||||
virtual proof* get_proof() { return 0; }
|
||||
|
|
|
@ -5,6 +5,8 @@ def_module_params('opt',
|
|||
('maxsat_engine', SYMBOL, 'maxres', "select engine for maxsat: 'core_maxsat', 'wmax', 'maxres', 'pd-maxres'"),
|
||||
('priority', SYMBOL, 'lex', "select how to priortize objectives: 'lex' (lexicographic), 'pareto', or 'box'"),
|
||||
('dump_benchmarks', BOOL, False, 'dump benchmarks for profiling'),
|
||||
('timeout', UINT, UINT_MAX, 'timeout (in milliseconds) (UINT_MAX and 0 mean no timeout)'),
|
||||
('rlimit', UINT, 0, 'resource limit (0 means no limit)'),
|
||||
('print_model', BOOL, False, 'display model for satisfiable constraints'),
|
||||
('enable_sls', BOOL, False, 'enable SLS tuning during weighted maxsast'),
|
||||
('enable_sat', BOOL, True, 'enable the new SAT core for propositional constraints'),
|
||||
|
|
|
@ -50,6 +50,7 @@ namespace opt {
|
|||
if (m_params.m_case_split_strategy == CS_ACTIVITY_DELAY_NEW) {
|
||||
m_params.m_relevancy_lvl = 0;
|
||||
}
|
||||
// m_params.m_auto_config = false;
|
||||
}
|
||||
|
||||
unsigned opt_solver::m_dump_count = 0;
|
||||
|
@ -357,6 +358,7 @@ namespace opt {
|
|||
}
|
||||
smt::theory_opt& opt = get_optimizer();
|
||||
smt::theory_var v = m_objective_vars[var];
|
||||
TRACE("opt", tout << "v" << var << " " << val << "\n";);
|
||||
|
||||
if (typeid(smt::theory_inf_arith) == typeid(opt)) {
|
||||
smt::theory_inf_arith& th = dynamic_cast<smt::theory_inf_arith&>(opt);
|
||||
|
@ -386,8 +388,32 @@ namespace opt {
|
|||
smt::theory_rdl& th = dynamic_cast<smt::theory_rdl&>(opt);
|
||||
return th.mk_ge(m_fm, v, val);
|
||||
}
|
||||
|
||||
if (typeid(smt::theory_dense_i) == typeid(opt) &&
|
||||
val.get_infinitesimal().is_zero()) {
|
||||
smt::theory_dense_i& th = dynamic_cast<smt::theory_dense_i&>(opt);
|
||||
return th.mk_ge(m_fm, v, val);
|
||||
}
|
||||
|
||||
// difference logic?
|
||||
if (typeid(smt::theory_dense_mi) == typeid(opt) &&
|
||||
val.get_infinitesimal().is_zero()) {
|
||||
smt::theory_dense_mi& th = dynamic_cast<smt::theory_dense_mi&>(opt);
|
||||
return th.mk_ge(m_fm, v, val);
|
||||
}
|
||||
|
||||
if (typeid(smt::theory_dense_si) == typeid(opt) &&
|
||||
val.get_infinitesimal().is_zero()) {
|
||||
smt::theory_dense_si& th = dynamic_cast<smt::theory_dense_si&>(opt);
|
||||
return th.mk_ge(m_fm, v, val);
|
||||
}
|
||||
|
||||
if (typeid(smt::theory_dense_smi) == typeid(opt) &&
|
||||
val.get_infinitesimal().is_zero()) {
|
||||
smt::theory_dense_smi& th = dynamic_cast<smt::theory_dense_smi&>(opt);
|
||||
return th.mk_ge(m_fm, v, val);
|
||||
}
|
||||
|
||||
IF_VERBOSE(0, verbose_stream() << "WARNING: unhandled theory " << typeid(opt).name() << "\n";);
|
||||
return expr_ref(m.mk_true(), m);
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -7,7 +7,7 @@ Module Name:
|
|||
|
||||
Abstract:
|
||||
|
||||
Light weight partial quantifier-elimination procedures
|
||||
Light weight partial quantifier-elimination procedures
|
||||
|
||||
Author:
|
||||
|
||||
|
@ -31,14 +31,14 @@ class qe_lite {
|
|||
class impl;
|
||||
impl * m_impl;
|
||||
public:
|
||||
qe_lite(ast_manager& m);
|
||||
qe_lite(ast_manager & m, params_ref const & p);
|
||||
|
||||
~qe_lite();
|
||||
|
||||
/**
|
||||
\brief
|
||||
Apply light-weight quantifier elimination
|
||||
on constants provided as vector of variables.
|
||||
Apply light-weight quantifier elimination
|
||||
on constants provided as vector of variables.
|
||||
Return the updated formula and updated set of variables that were not eliminated.
|
||||
|
||||
*/
|
||||
|
@ -66,4 +66,4 @@ tactic * mk_qe_lite_tactic(ast_manager & m, params_ref const & p = params_ref())
|
|||
ADD_TACTIC("qe-light", "apply light-weight quantifier elimination.", "mk_qe_lite_tactic(m, p)")
|
||||
*/
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -96,7 +96,6 @@ namespace sat {
|
|||
if (!process(c))
|
||||
continue; // clause was removed
|
||||
*it2 = *it;
|
||||
// throw exception to test bug fix: if (it2 != it) throw solver_exception("trigger bug");
|
||||
++it2;
|
||||
}
|
||||
s.m_clauses.set_end(it2);
|
||||
|
@ -129,14 +128,14 @@ namespace sat {
|
|||
// check if the clause is already satisfied
|
||||
for (i = 0; i < sz; i++) {
|
||||
if (s.value(c[i]) == l_true) {
|
||||
s.dettach_clause(c);
|
||||
s.detach_clause(c);
|
||||
s.del_clause(c);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// try asymmetric branching
|
||||
// clause must not be used for propagation
|
||||
s.dettach_clause(c);
|
||||
solver::scoped_detach scoped_d(s, c);
|
||||
s.push();
|
||||
for (i = 0; i < sz - 1; i++) {
|
||||
literal l = c[i];
|
||||
|
@ -154,7 +153,6 @@ namespace sat {
|
|||
SASSERT(s.m_qhead == s.m_trail.size());
|
||||
if (i == sz - 1) {
|
||||
// clause size can't be reduced.
|
||||
s.attach_clause(c);
|
||||
return true;
|
||||
}
|
||||
// clause can be reduced
|
||||
|
@ -190,14 +188,14 @@ namespace sat {
|
|||
case 1:
|
||||
TRACE("asymm_branch", tout << "produced unit clause: " << c[0] << "\n";);
|
||||
s.assign(c[0], justification());
|
||||
s.del_clause(c);
|
||||
s.propagate_core(false);
|
||||
scoped_d.del_clause();
|
||||
SASSERT(s.inconsistent() || s.m_qhead == s.m_trail.size());
|
||||
return false; // check_missed_propagation() may fail, since m_clauses is not in a consistent state.
|
||||
case 2:
|
||||
SASSERT(s.value(c[0]) == l_undef && s.value(c[1]) == l_undef);
|
||||
s.mk_bin_clause(c[0], c[1], false);
|
||||
s.del_clause(c);
|
||||
scoped_d.del_clause();
|
||||
SASSERT(s.m_qhead == s.m_trail.size());
|
||||
return false;
|
||||
default:
|
||||
|
|
|
@ -94,7 +94,7 @@ namespace sat {
|
|||
continue;
|
||||
}
|
||||
if (!c.frozen())
|
||||
m_solver.dettach_clause(c);
|
||||
m_solver.detach_clause(c);
|
||||
// apply substitution
|
||||
for (i = 0; i < sz; i++) {
|
||||
SASSERT(!m_solver.was_eliminated(c[i].var()));
|
||||
|
|
|
@ -159,6 +159,8 @@ namespace sat {
|
|||
if (!m_subsumption && !m_elim_blocked_clauses && !m_resolution)
|
||||
return;
|
||||
|
||||
// solver::scoped_disable_checkpoint _scoped_disable_checkpoint(s);
|
||||
|
||||
initialize();
|
||||
|
||||
CASSERT("sat_solver", s.check_invariant());
|
||||
|
@ -172,15 +174,13 @@ namespace sat {
|
|||
CASSERT("sat_solver", s.check_invariant());
|
||||
m_need_cleanup = false;
|
||||
m_use_list.init(s.num_vars());
|
||||
init_visited();
|
||||
bool learned_in_use_lists = false;
|
||||
m_learned_in_use_lists = false;
|
||||
if (learned) {
|
||||
register_clauses(s.m_learned);
|
||||
learned_in_use_lists = true;
|
||||
m_learned_in_use_lists = true;
|
||||
}
|
||||
register_clauses(s.m_clauses);
|
||||
|
||||
|
||||
if (!learned && (m_elim_blocked_clauses || m_elim_blocked_clauses_at == m_num_calls))
|
||||
elim_blocked_clauses();
|
||||
|
||||
|
@ -189,7 +189,9 @@ namespace sat {
|
|||
|
||||
m_sub_counter = m_subsumption_limit;
|
||||
m_elim_counter = m_res_limit;
|
||||
unsigned old_num_elim_vars = m_num_elim_vars;
|
||||
m_old_num_elim_vars = m_num_elim_vars;
|
||||
|
||||
scoped_finalize _scoped_finalize(*this);
|
||||
|
||||
do {
|
||||
if (m_subsumption)
|
||||
|
@ -210,19 +212,19 @@ namespace sat {
|
|||
lookahead(s).simplify();
|
||||
}
|
||||
|
||||
bool vars_eliminated = m_num_elim_vars > old_num_elim_vars;
|
||||
bool vars_eliminated = m_num_elim_vars > m_old_num_elim_vars;
|
||||
|
||||
if (m_need_cleanup) {
|
||||
TRACE("after_simplifier", tout << "cleanning watches...\n";);
|
||||
cleanup_watches();
|
||||
cleanup_clauses(s.m_learned, true, vars_eliminated, learned_in_use_lists);
|
||||
cleanup_clauses(s.m_learned, true, vars_eliminated, m_learned_in_use_lists);
|
||||
cleanup_clauses(s.m_clauses, false, vars_eliminated, true);
|
||||
}
|
||||
else {
|
||||
TRACE("after_simplifier", tout << "skipping cleanup...\n";);
|
||||
if (vars_eliminated) {
|
||||
// must remove learned clauses with eliminated variables
|
||||
cleanup_clauses(s.m_learned, true, true, learned_in_use_lists);
|
||||
cleanup_clauses(s.m_learned, true, true, m_learned_in_use_lists);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -291,7 +293,7 @@ namespace sat {
|
|||
unsigned sz = c.size();
|
||||
if (sz == 0) {
|
||||
s.set_conflict(justification());
|
||||
for (; it != end; ++it) {
|
||||
for (; it != end; ++it, ++it2) {
|
||||
*it2 = *it;
|
||||
++it2;
|
||||
}
|
||||
|
|
|
@ -91,6 +91,9 @@ namespace sat {
|
|||
unsigned m_num_sub_res;
|
||||
unsigned m_num_elim_lits;
|
||||
|
||||
bool m_learned_in_use_lists;
|
||||
unsigned m_old_num_elim_vars;
|
||||
|
||||
struct size_lt {
|
||||
bool operator()(clause const * c1, clause const * c2) const { return c1->size() > c2->size(); }
|
||||
};
|
||||
|
@ -168,6 +171,14 @@ namespace sat {
|
|||
struct subsumption_report;
|
||||
struct elim_var_report;
|
||||
|
||||
class scoped_finalize {
|
||||
simplifier& s;
|
||||
public:
|
||||
scoped_finalize(simplifier& s) : s(s) {}
|
||||
~scoped_finalize() { s.scoped_finalize_fn(); }
|
||||
};
|
||||
void scoped_finalize_fn();
|
||||
|
||||
public:
|
||||
simplifier(solver & s, params_ref const & p);
|
||||
~simplifier();
|
||||
|
|
|
@ -36,6 +36,7 @@ namespace sat {
|
|||
|
||||
solver::solver(params_ref const & p, reslimit& l):
|
||||
m_rlimit(l),
|
||||
m_checkpoint_enabled(true),
|
||||
m_config(p),
|
||||
m_par(0),
|
||||
m_par_syncing_clauses(false),
|
||||
|
@ -121,7 +122,7 @@ namespace sat {
|
|||
if (!it->is_binary_non_learned_clause())
|
||||
continue;
|
||||
literal l2 = it->get_literal();
|
||||
if (l.index() > l2.index())
|
||||
if (l.index() > l2.index())
|
||||
continue;
|
||||
mk_clause_core(l, l2);
|
||||
}
|
||||
|
@ -301,7 +302,7 @@ namespace sat {
|
|||
void solver::push_reinit_stack(clause & c) {
|
||||
TRACE("sat_reinit", tout << "adding to reinit stack: " << c << "\n";);
|
||||
m_clauses_to_reinit.push_back(clause_wrapper(c));
|
||||
c.set_reinit_stack(true);
|
||||
c.set_reinit_stack(true);
|
||||
}
|
||||
|
||||
|
||||
|
@ -520,26 +521,26 @@ namespace sat {
|
|||
return simplify_clause_core<false>(num_lits, lits);
|
||||
}
|
||||
|
||||
void solver::dettach_bin_clause(literal l1, literal l2, bool learned) {
|
||||
void solver::detach_bin_clause(literal l1, literal l2, bool learned) {
|
||||
get_wlist(~l1).erase(watched(l2, learned));
|
||||
get_wlist(~l2).erase(watched(l1, learned));
|
||||
if (m_config.m_drat) m_drat.del(l1, l2);
|
||||
}
|
||||
|
||||
void solver::dettach_clause(clause & c) {
|
||||
void solver::detach_clause(clause & c) {
|
||||
if (c.size() == 3)
|
||||
dettach_ter_clause(c);
|
||||
detach_ter_clause(c);
|
||||
else
|
||||
dettach_nary_clause(c);
|
||||
detach_nary_clause(c);
|
||||
}
|
||||
|
||||
void solver::dettach_nary_clause(clause & c) {
|
||||
void solver::detach_nary_clause(clause & c) {
|
||||
clause_offset cls_off = get_offset(c);
|
||||
erase_clause_watch(get_wlist(~c[0]), cls_off);
|
||||
erase_clause_watch(get_wlist(~c[1]), cls_off);
|
||||
}
|
||||
|
||||
void solver::dettach_ter_clause(clause & c) {
|
||||
void solver::detach_ter_clause(clause & c) {
|
||||
erase_ternary_watch(get_wlist(~c[0]), c[1], c[2]);
|
||||
erase_ternary_watch(get_wlist(~c[1]), c[0], c[2]);
|
||||
erase_ternary_watch(get_wlist(~c[2]), c[0], c[1]);
|
||||
|
@ -925,13 +926,13 @@ namespace sat {
|
|||
}
|
||||
int finished_id = -1;
|
||||
std::string ex_msg;
|
||||
par_exception_kind ex_kind;
|
||||
par_exception_kind ex_kind = DEFAULT_EX;
|
||||
unsigned error_code = 0;
|
||||
lbool result = l_undef;
|
||||
bool canceled = false;
|
||||
#pragma omp parallel for
|
||||
for (int i = 0; i < num_threads; ++i) {
|
||||
try {
|
||||
try {
|
||||
lbool r = l_undef;
|
||||
if (IS_AUX_SOLVER(i)) {
|
||||
r = par.get_solver(i).check(num_lits, lits);
|
||||
|
@ -966,7 +967,7 @@ namespace sat {
|
|||
rlimit().cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (z3_error & err) {
|
||||
error_code = err.error_code();
|
||||
|
@ -1271,7 +1272,7 @@ namespace sat {
|
|||
for (unsigned i = 0; !inconsistent() && i < m_assumptions.size(); ++i) {
|
||||
assign(m_assumptions[i], justification());
|
||||
}
|
||||
TRACE("sat",
|
||||
TRACE("sat",
|
||||
for (unsigned i = 0; i < m_assumptions.size(); ++i) {
|
||||
index_set s;
|
||||
if (m_antecedents.find(m_assumptions[i].var(), s)) {
|
||||
|
@ -1625,7 +1626,7 @@ namespace sat {
|
|||
for (unsigned i = new_sz; i < sz; i++) {
|
||||
clause & c = *(m_learned[i]);
|
||||
if (can_delete(c)) {
|
||||
dettach_clause(c);
|
||||
detach_clause(c);
|
||||
del_clause(c);
|
||||
}
|
||||
else {
|
||||
|
@ -1683,7 +1684,7 @@ namespace sat {
|
|||
else {
|
||||
c.inc_inact_rounds();
|
||||
if (c.inact_rounds() > m_config.m_gc_k) {
|
||||
dettach_clause(c);
|
||||
detach_clause(c);
|
||||
del_clause(c);
|
||||
m_stats.m_gc_clause++;
|
||||
deleted++;
|
||||
|
@ -1694,7 +1695,7 @@ namespace sat {
|
|||
if (psm(c) > static_cast<unsigned>(c.size() * m_min_d_tk)) {
|
||||
// move to frozen;
|
||||
TRACE("sat_frozen", tout << "freezing size: " << c.size() << " psm: " << psm(c) << " " << c << "\n";);
|
||||
dettach_clause(c);
|
||||
detach_clause(c);
|
||||
c.reset_inact_rounds();
|
||||
c.freeze();
|
||||
m_num_frozen++;
|
||||
|
@ -2632,7 +2633,7 @@ namespace sat {
|
|||
}
|
||||
else {
|
||||
clause & c = *(cw.get_clause());
|
||||
dettach_clause(c);
|
||||
detach_clause(c);
|
||||
attach_clause(c, reinit);
|
||||
if (!at_base_lvl() && reinit) {
|
||||
// clause propagated literal, must keep it in the reinit stack.
|
||||
|
@ -2665,7 +2666,7 @@ namespace sat {
|
|||
for (unsigned i = 0; i < clauses.size(); ++i) {
|
||||
clause & c = *(clauses[i]);
|
||||
if (c.contains(lit)) {
|
||||
dettach_clause(c);
|
||||
detach_clause(c);
|
||||
del_clause(c);
|
||||
}
|
||||
else {
|
||||
|
@ -2683,7 +2684,7 @@ namespace sat {
|
|||
literal l1 = m_user_bin_clauses[i].first;
|
||||
literal l2 = m_user_bin_clauses[i].second;
|
||||
if (nlit == l1 || nlit == l2) {
|
||||
dettach_bin_clause(l1, l2, learned);
|
||||
detach_bin_clause(l1, l2, learned);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3172,7 +3173,7 @@ namespace sat {
|
|||
literal_pair p(l1, l2);
|
||||
if (!seen_bc.contains(p)) {
|
||||
seen_bc.insert(p);
|
||||
mc.add_edge(l1.index(), l2.index());
|
||||
mc.add_edge(l1.index(), l2.index());
|
||||
}
|
||||
}
|
||||
vector<unsigned_vector> _mutexes;
|
||||
|
@ -3229,7 +3230,7 @@ namespace sat {
|
|||
}
|
||||
|
||||
void solver::fixup_consequence_core() {
|
||||
index_set s;
|
||||
index_set s;
|
||||
TRACE("sat", tout << m_core << "\n";);
|
||||
for (unsigned i = 0; i < m_core.size(); ++i) {
|
||||
TRACE("sat", tout << m_core[i] << ": "; display_index_set(tout, m_antecedents.find(m_core[i].var())) << "\n";);
|
||||
|
@ -3279,20 +3280,20 @@ namespace sat {
|
|||
while (true) {
|
||||
++num_iterations;
|
||||
SASSERT(!inconsistent());
|
||||
|
||||
|
||||
lbool r = bounded_search();
|
||||
if (r != l_undef) {
|
||||
fixup_consequence_core();
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
extract_fixed_consequences(num_units, asms, unfixed_vars, conseq);
|
||||
|
||||
if (m_conflicts > m_config.m_max_conflicts) {
|
||||
IF_VERBOSE(SAT_VB_LVL, verbose_stream() << "(sat \"abort: max-conflicts = " << m_conflicts << "\")\n";);
|
||||
return l_undef;
|
||||
}
|
||||
|
||||
|
||||
restart();
|
||||
simplify_problem();
|
||||
if (check_inconsistent()) {
|
||||
|
@ -3300,11 +3301,11 @@ namespace sat {
|
|||
return l_false;
|
||||
}
|
||||
gc();
|
||||
|
||||
|
||||
if (m_config.m_restart_max <= num_iterations) {
|
||||
IF_VERBOSE(SAT_VB_LVL, verbose_stream() << "(sat \"abort: max-restarts\")\n";);
|
||||
return l_undef;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3345,13 +3346,17 @@ namespace sat {
|
|||
checkpoint();
|
||||
literal_set::iterator it = unfixed_lits.begin(), end = unfixed_lits.end();
|
||||
unsigned num_resolves = 0;
|
||||
unsigned num_fixed = 0;
|
||||
unsigned num_assigned = 0;
|
||||
lbool is_sat = l_true;
|
||||
for (; it != end; ++it) {
|
||||
literal lit = *it;
|
||||
literal lit = *it;
|
||||
if (value(lit) != l_undef) {
|
||||
++num_fixed;
|
||||
continue;
|
||||
}
|
||||
push();
|
||||
++num_assigned;
|
||||
assign(~lit, justification());
|
||||
propagate(false);
|
||||
while (inconsistent()) {
|
||||
|
@ -3368,8 +3373,18 @@ namespace sat {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (scope_lvl() == 1) {
|
||||
it = unfixed_lits.begin();
|
||||
for (; it != end; ++it) {
|
||||
literal lit = *it;
|
||||
if (value(lit) == l_true) {
|
||||
VERIFY(extract_fixed_consequences(lit, assumptions, unfixed_vars, conseq));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_sat == l_true) {
|
||||
if (scope_lvl() == search_lvl() && num_resolves > 0) {
|
||||
IF_VERBOSE(1, verbose_stream() << "(sat.get-consequences backjump)\n";);
|
||||
is_sat = l_undef;
|
||||
}
|
||||
else {
|
||||
|
@ -3386,12 +3401,14 @@ namespace sat {
|
|||
if (is_sat == l_true) {
|
||||
delete_unfixed(unfixed_lits, unfixed_vars);
|
||||
}
|
||||
extract_fixed_consequences(num_units, assumptions, unfixed_vars, conseq);
|
||||
extract_fixed_consequences(num_units, assumptions, unfixed_vars, conseq);
|
||||
update_unfixed_literals(unfixed_lits, unfixed_vars);
|
||||
IF_VERBOSE(1, verbose_stream() << "(sat.get-consequences"
|
||||
<< " iterations: " << num_iterations
|
||||
<< " variables: " << unfixed_lits.size()
|
||||
<< " fixed: " << conseq.size()
|
||||
<< " status: " << is_sat
|
||||
<< " pre-assigned: " << num_fixed
|
||||
<< " unfixed: " << lits.size() - conseq.size() - unfixed_lits.size()
|
||||
<< ")\n";);
|
||||
|
||||
|
|
|
@ -74,6 +74,7 @@ namespace sat {
|
|||
struct abort_solver {};
|
||||
protected:
|
||||
reslimit& m_rlimit;
|
||||
bool m_checkpoint_enabled;
|
||||
config m_config;
|
||||
stats m_stats;
|
||||
scoped_ptr<extension> m_ext;
|
||||
|
@ -210,15 +211,44 @@ namespace sat {
|
|||
bool attach_nary_clause(clause & c);
|
||||
void attach_clause(clause & c, bool & reinit);
|
||||
void attach_clause(clause & c) { bool reinit; attach_clause(c, reinit); }
|
||||
class scoped_detach {
|
||||
solver& s;
|
||||
clause& c;
|
||||
bool m_deleted;
|
||||
public:
|
||||
scoped_detach(solver& s, clause& c): s(s), c(c), m_deleted(false) {
|
||||
s.detach_clause(c);
|
||||
}
|
||||
~scoped_detach() {
|
||||
if (!m_deleted) s.attach_clause(c);
|
||||
}
|
||||
|
||||
void del_clause() {
|
||||
if (!m_deleted) {
|
||||
s.del_clause(c);
|
||||
m_deleted = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
class scoped_disable_checkpoint {
|
||||
solver& s;
|
||||
public:
|
||||
scoped_disable_checkpoint(solver& s): s(s) {
|
||||
s.m_checkpoint_enabled = false;
|
||||
}
|
||||
~scoped_disable_checkpoint() {
|
||||
s.m_checkpoint_enabled = true;
|
||||
}
|
||||
};
|
||||
unsigned select_watch_lit(clause const & cls, unsigned starting_at) const;
|
||||
unsigned select_learned_watch_lit(clause const & cls) const;
|
||||
bool simplify_clause(unsigned & num_lits, literal * lits) const;
|
||||
template<bool lvl0>
|
||||
bool simplify_clause_core(unsigned & num_lits, literal * lits) const;
|
||||
void dettach_bin_clause(literal l1, literal l2, bool learned);
|
||||
void dettach_clause(clause & c);
|
||||
void dettach_nary_clause(clause & c);
|
||||
void dettach_ter_clause(clause & c);
|
||||
void detach_bin_clause(literal l1, literal l2, bool learned);
|
||||
void detach_clause(clause & c);
|
||||
void detach_nary_clause(clause & c);
|
||||
void detach_ter_clause(clause & c);
|
||||
void push_reinit_stack(clause & c);
|
||||
|
||||
// -----------------------
|
||||
|
@ -257,6 +287,7 @@ namespace sat {
|
|||
lbool status(clause const & c) const;
|
||||
clause_offset get_offset(clause const & c) const { return m_cls_allocator.get_offset(&c); }
|
||||
void checkpoint() {
|
||||
if (!m_checkpoint_enabled) return;
|
||||
if (!m_rlimit.inc()) {
|
||||
m_mc.reset();
|
||||
m_model_is_current = false;
|
||||
|
|
|
@ -3942,7 +3942,7 @@ namespace smt {
|
|||
#endif
|
||||
|
||||
virtual void on_match(quantifier * qa, app * pat, unsigned num_bindings, enode * const * bindings, unsigned max_generation, ptr_vector<enode> & used_enodes) {
|
||||
TRACE("trigger_bug", tout << "found match\n";);
|
||||
TRACE("trigger_bug", tout << "found match " << mk_pp(qa, m_ast_manager) << "\n";);
|
||||
#ifdef Z3DEBUG
|
||||
if (m_check_missing_instances) {
|
||||
if (!m_context.slow_contains_instance(qa, num_bindings, bindings)) {
|
||||
|
|
|
@ -81,7 +81,7 @@ ext_numeral & ext_numeral::operator*=(ext_numeral const & other) {
|
|||
m_value.reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
if (is_infinite() || other.is_infinite()) {
|
||||
if (sign() == other.sign())
|
||||
m_kind = PLUS_INFINITY;
|
||||
|
@ -203,7 +203,7 @@ interval::interval(v_dependency_manager & m, rational const & val, v_dependency
|
|||
m_lower_dep(l_dep),
|
||||
m_upper_dep(u_dep) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Create intervals (-oo, val], (-oo, val), [val, oo), (val, oo)
|
||||
*/
|
||||
|
@ -271,8 +271,8 @@ interval & interval::operator-=(interval const & other) {
|
|||
return operator+=(tmp);
|
||||
}
|
||||
|
||||
v_dependency * interval::join(v_dependency * d1, v_dependency * d2, v_dependency * d3, v_dependency * d4) {
|
||||
return m_manager.mk_join(m_manager.mk_join(d1, d2), m_manager.mk_join(d3,d4));
|
||||
v_dependency * interval::join(v_dependency * d1, v_dependency * d2, v_dependency * d3, v_dependency * d4) {
|
||||
return m_manager.mk_join(m_manager.mk_join(d1, d2), m_manager.mk_join(d3,d4));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -318,7 +318,7 @@ interval & interval::operator*=(interval const & other) {
|
|||
v_dependency * d_d = other.m_upper_dep;
|
||||
|
||||
TRACE("interval_bug", tout << "operator*= " << *this << " " << other << "\n";);
|
||||
|
||||
|
||||
if (is_N()) {
|
||||
if (other.is_N()) {
|
||||
// x <= b <= 0, y <= d <= 0 --> b*d <= x*y
|
||||
|
@ -452,7 +452,7 @@ interval & interval::operator*=(interval const & other) {
|
|||
m_upper_dep = m_upper.is_infinite() ? 0 : join(b_d, d_d, a_d);
|
||||
}
|
||||
else {
|
||||
// 0 <= a <= x, 0 <= c <= y --> a*c <= x*y
|
||||
// 0 <= a <= x, 0 <= c <= y --> a*c <= x*y
|
||||
// x <= b, y <= d --> x*y <= b*d (uses the fact that x is pos (a is not negative) or y is pos (c is not negative))
|
||||
TRACE("interval_bug", tout << "(P, P)\n";);
|
||||
SASSERT(other.is_P());
|
||||
|
@ -467,7 +467,7 @@ interval & interval::operator*=(interval const & other) {
|
|||
}
|
||||
}
|
||||
TRACE("interval_bug", tout << "operator*= result: " << *this << "\n";);
|
||||
CTRACE("interval", !(!(contains_zero1 || contains_zero2) || contains_zero()),
|
||||
CTRACE("interval", !(!(contains_zero1 || contains_zero2) || contains_zero()),
|
||||
tout << "contains_zero1: " << contains_zero1 << ", contains_zero2: " << contains_zero2 << ", contains_zero(): " << contains_zero() << "\n";);
|
||||
SASSERT(!(contains_zero1 || contains_zero2) || contains_zero());
|
||||
return *this;
|
||||
|
@ -482,7 +482,7 @@ bool interval::contains_zero() const {
|
|||
tout << "m_upper.is_zero: " << m_upper.is_zero() << "\n";
|
||||
tout << "m_upper_open: " << m_upper_open << "\n";
|
||||
tout << "result: " << ((m_lower.is_neg() || (m_lower.is_zero() && !m_lower_open)) && (m_upper.is_pos() || (m_upper.is_zero() && !m_upper_open))) << "\n";);
|
||||
return
|
||||
return
|
||||
(m_lower.is_neg() || (m_lower.is_zero() && !m_lower_open)) &&
|
||||
(m_upper.is_pos() || (m_upper.is_zero() && !m_upper_open));
|
||||
}
|
||||
|
@ -510,7 +510,7 @@ interval & interval::inv() {
|
|||
ext_numeral new_upper;
|
||||
if (m_lower.is_zero()) {
|
||||
SASSERT(m_lower_open);
|
||||
ext_numeral plus_infinity(true);
|
||||
ext_numeral plus_infinity(true);
|
||||
new_upper = plus_infinity;
|
||||
}
|
||||
else {
|
||||
|
@ -595,7 +595,7 @@ void interval::expt(unsigned n) {
|
|||
else if (m_upper.is_neg()) {
|
||||
// [l, u]^n = [u^n, l^n] if u < 0
|
||||
// a <= x <= b < 0 --> x^n <= a^n (use lower and upper bound -- need the fact that x is negative)
|
||||
// x <= b < 0 --> b^n <= x^n
|
||||
// x <= b < 0 --> b^n <= x^n
|
||||
std::swap(m_lower, m_upper);
|
||||
std::swap(m_lower_open, m_upper_open);
|
||||
std::swap(m_lower_dep, m_upper_dep);
|
||||
|
@ -614,7 +614,7 @@ void interval::expt(unsigned n) {
|
|||
m_upper = m_lower;
|
||||
m_upper_open = m_lower_open;
|
||||
}
|
||||
m_upper_dep = m_upper.is_infinite() ? 0 : m_manager.mk_join(m_lower_dep, m_upper_dep);
|
||||
m_upper_dep = m_upper.is_infinite() ? 0 : m_manager.mk_join(m_lower_dep, m_upper_dep);
|
||||
m_lower = ext_numeral(0);
|
||||
m_lower_open = false;
|
||||
m_lower_dep = 0;
|
||||
|
|
|
@ -64,5 +64,6 @@ def_module_params(module_name='smt',
|
|||
('core.validate', BOOL, False, 'validate unsat core produced by SMT context'),
|
||||
('core.minimize', BOOL, False, 'minimize unsat core produced by SMT context'),
|
||||
('core.extend_patterns', BOOL, False, 'extend unsat core with literals that trigger (potential) quantifier instances'),
|
||||
('core.extend_patterns.max_distance', UINT, UINT_MAX, 'limits the distance of a pattern-extended unsat core')
|
||||
('core.extend_patterns.max_distance', UINT, UINT_MAX, 'limits the distance of a pattern-extended unsat core'),
|
||||
('core.extend_nonlocal_patterns', BOOL, False, 'extend unsat cores with literals that have quantifiers with patterns that contain symbols which are not in the quantifier\'s body')
|
||||
))
|
||||
|
|
|
@ -59,9 +59,9 @@ namespace smt {
|
|||
SASSERT(n->trans_reaches(n->get_root()));
|
||||
while (n) {
|
||||
if (Set)
|
||||
n->set_mark();
|
||||
n->set_mark2();
|
||||
else
|
||||
n->unset_mark();
|
||||
n->unset_mark2();
|
||||
n = n->m_trans.m_target;
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ namespace smt {
|
|||
mark_enodes_in_trans<true>(n1);
|
||||
while (true) {
|
||||
SASSERT(n2);
|
||||
if (n2->is_marked()) {
|
||||
if (n2->is_marked2()) {
|
||||
mark_enodes_in_trans<false>(n1);
|
||||
return n2;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ namespace smt {
|
|||
index_set::iterator it = vars.begin(), end = vars.end();
|
||||
for (; it != end; ++it) {
|
||||
expr* e = bool_var2expr(*it);
|
||||
e = m_assumption2orig.find(e);
|
||||
premises.push_back(get_assignment(*it) != l_false ? e : m_manager.mk_not(e));
|
||||
}
|
||||
return mk_and(premises);
|
||||
|
@ -44,13 +45,14 @@ namespace smt {
|
|||
// - e is an equality between a variable and value that is to be fixed.
|
||||
// - e is a data-type recognizer of a variable that is to be fixed.
|
||||
//
|
||||
void context::extract_fixed_consequences(literal lit, obj_map<expr, expr*>& vars, index_set const& assumptions, expr_ref_vector& conseq) {
|
||||
void context::extract_fixed_consequences(literal lit, index_set const& assumptions, expr_ref_vector& conseq) {
|
||||
ast_manager& m = m_manager;
|
||||
datatype_util dt(m);
|
||||
expr* e1, *e2;
|
||||
expr_ref fml(m);
|
||||
if (lit == true_literal) return;
|
||||
expr* e = bool_var2expr(lit.var());
|
||||
TRACE("context", display(tout << mk_pp(e, m) << "\n"););
|
||||
index_set s;
|
||||
if (assumptions.contains(lit.var())) {
|
||||
s.insert(lit.var());
|
||||
|
@ -65,26 +67,32 @@ namespace smt {
|
|||
}
|
||||
tout << "\n";);
|
||||
bool found = false;
|
||||
if (vars.contains(e)) {
|
||||
if (m_var2val.contains(e)) {
|
||||
found = true;
|
||||
m_var2val.erase(e);
|
||||
e = m_var2orig.find(e);
|
||||
fml = lit.sign() ? m.mk_not(e) : e;
|
||||
vars.erase(e);
|
||||
}
|
||||
else if (!lit.sign() && m.is_eq(e, e1, e2)) {
|
||||
if (vars.contains(e2)) {
|
||||
std::swap(e1, e2);
|
||||
}
|
||||
if (vars.contains(e1) && m.is_value(e2)) {
|
||||
if (m_var2val.contains(e2) && m.is_value(e1)) {
|
||||
found = true;
|
||||
fml = e;
|
||||
vars.erase(e1);
|
||||
m_var2val.erase(e2);
|
||||
e2 = m_var2orig.find(e2);
|
||||
std::swap(e1, e2);
|
||||
fml = m.mk_eq(e1, e2);
|
||||
}
|
||||
else if (m_var2val.contains(e1) && m.is_value(e2)) {
|
||||
found = true;
|
||||
m_var2val.erase(e1);
|
||||
e1 = m_var2orig.find(e1);
|
||||
fml = m.mk_eq(e1, e2);
|
||||
}
|
||||
}
|
||||
else if (!lit.sign() && is_app(e) && dt.is_recognizer(to_app(e)->get_decl())) {
|
||||
if (vars.contains(to_app(e)->get_arg(0))) {
|
||||
if (m_var2val.contains(to_app(e)->get_arg(0))) {
|
||||
found = true;
|
||||
fml = m.mk_eq(to_app(e)->get_arg(0), m.mk_const(dt.get_recognizer_constructor(to_app(e)->get_decl())));
|
||||
vars.erase(to_app(e)->get_arg(0));
|
||||
m_var2val.erase(to_app(e)->get_arg(0));
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
|
@ -94,6 +102,7 @@ namespace smt {
|
|||
}
|
||||
|
||||
void context::justify(literal lit, index_set& s) {
|
||||
ast_manager& m = m_manager;
|
||||
b_justification js = get_justification(lit.var());
|
||||
switch (js.get_kind()) {
|
||||
case b_justification::CLAUSE: {
|
||||
|
@ -119,6 +128,9 @@ namespace smt {
|
|||
literal_vector literals;
|
||||
m_conflict_resolution->justification2literals(js.get_justification(), literals);
|
||||
for (unsigned j = 0; j < literals.size(); ++j) {
|
||||
if (!m_antecedents.contains(literals[j].var())) {
|
||||
TRACE("context", tout << literals[j] << " " << mk_pp(bool_var2expr(literals[j].var()), m) << "\n";);
|
||||
}
|
||||
s |= m_antecedents.find(literals[j].var());
|
||||
}
|
||||
break;
|
||||
|
@ -126,13 +138,13 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
|
||||
void context::extract_fixed_consequences(unsigned& start, obj_map<expr, expr*>& vars, index_set const& assumptions, expr_ref_vector& conseq) {
|
||||
void context::extract_fixed_consequences(unsigned& start, index_set const& assumptions, expr_ref_vector& conseq) {
|
||||
pop_to_search_lvl();
|
||||
SASSERT(!inconsistent());
|
||||
literal_vector const& lits = assigned_literals();
|
||||
unsigned sz = lits.size();
|
||||
for (unsigned i = start; i < sz; ++i) {
|
||||
extract_fixed_consequences(lits[i], vars, assumptions, conseq);
|
||||
extract_fixed_consequences(lits[i], assumptions, conseq);
|
||||
}
|
||||
start = sz;
|
||||
SASSERT(!inconsistent());
|
||||
|
@ -150,10 +162,10 @@ namespace smt {
|
|||
// rules out as many non-fixed variables as possible.
|
||||
//
|
||||
|
||||
unsigned context::delete_unfixed(obj_map<expr, expr*>& var2val, expr_ref_vector& unfixed) {
|
||||
unsigned context::delete_unfixed(expr_ref_vector& unfixed) {
|
||||
ast_manager& m = m_manager;
|
||||
ptr_vector<expr> to_delete;
|
||||
obj_map<expr,expr*>::iterator it = var2val.begin(), end = var2val.end();
|
||||
obj_map<expr,expr*>::iterator it = m_var2val.begin(), end = m_var2val.end();
|
||||
for (; it != end; ++it) {
|
||||
expr* k = it->m_key;
|
||||
expr* v = it->m_value;
|
||||
|
@ -189,7 +201,7 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
for (unsigned i = 0; i < to_delete.size(); ++i) {
|
||||
var2val.remove(to_delete[i]);
|
||||
m_var2val.remove(to_delete[i]);
|
||||
unfixed.push_back(to_delete[i]);
|
||||
}
|
||||
return to_delete.size();
|
||||
|
@ -202,12 +214,12 @@ namespace smt {
|
|||
// Add a clause to short-circuit the congruence justifications for
|
||||
// next rounds.
|
||||
//
|
||||
unsigned context::extract_fixed_eqs(obj_map<expr, expr*>& var2val, expr_ref_vector& conseq) {
|
||||
unsigned context::extract_fixed_eqs(expr_ref_vector& conseq) {
|
||||
TRACE("context", tout << "extract fixed consequences\n";);
|
||||
ast_manager& m = m_manager;
|
||||
ptr_vector<expr> to_delete;
|
||||
expr_ref fml(m), eq(m);
|
||||
obj_map<expr,expr*>::iterator it = var2val.begin(), end = var2val.end();
|
||||
obj_map<expr,expr*>::iterator it = m_var2val.begin(), end = m_var2val.end();
|
||||
for (; it != end; ++it) {
|
||||
expr* k = it->m_key;
|
||||
expr* v = it->m_value;
|
||||
|
@ -220,7 +232,7 @@ namespace smt {
|
|||
s |= m_antecedents.find(literals[i].var());
|
||||
}
|
||||
|
||||
fml = m.mk_eq(k, v);
|
||||
fml = m.mk_eq(m_var2orig.find(k), v);
|
||||
fml = m.mk_implies(antecedent2fml(s), fml);
|
||||
conseq.push_back(fml);
|
||||
to_delete.push_back(k);
|
||||
|
@ -235,16 +247,20 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
for (unsigned i = 0; i < to_delete.size(); ++i) {
|
||||
var2val.remove(to_delete[i]);
|
||||
m_var2val.remove(to_delete[i]);
|
||||
}
|
||||
return to_delete.size();
|
||||
}
|
||||
|
||||
literal context::mk_diseq(expr* e, expr* val) {
|
||||
ast_manager& m = m_manager;
|
||||
if (m.is_bool(e)) {
|
||||
if (m.is_bool(e) && b_internalized(e)) {
|
||||
return literal(get_bool_var(e), m.is_true(val));
|
||||
}
|
||||
else if (m.is_bool(e)) {
|
||||
internalize_formula(e, false);
|
||||
return literal(get_bool_var(e), !m.is_true(val));
|
||||
}
|
||||
else {
|
||||
expr_ref eq(mk_eq_atom(e, val), m);
|
||||
internalize_formula(eq, false);
|
||||
|
@ -252,43 +268,85 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
|
||||
lbool context::get_consequences(expr_ref_vector const& assumptions,
|
||||
expr_ref_vector const& vars,
|
||||
lbool context::get_consequences(expr_ref_vector const& assumptions0,
|
||||
expr_ref_vector const& vars0,
|
||||
expr_ref_vector& conseq,
|
||||
expr_ref_vector& unfixed) {
|
||||
|
||||
m_antecedents.reset();
|
||||
m_antecedents.insert(true_literal.var(), index_set());
|
||||
pop_to_base_lvl();
|
||||
ast_manager& m = m_manager;
|
||||
expr_ref_vector vars(m), assumptions(m);
|
||||
m_var2val.reset();
|
||||
m_var2orig.reset();
|
||||
m_assumption2orig.reset();
|
||||
bool pushed = false;
|
||||
for (unsigned i = 0; i < vars0.size(); ++i) {
|
||||
expr* v = vars0[i];
|
||||
if (is_uninterp_const(v)) {
|
||||
vars.push_back(v);
|
||||
m_var2orig.insert(v, v);
|
||||
}
|
||||
else {
|
||||
if (!pushed) {
|
||||
pushed = true;
|
||||
push();
|
||||
}
|
||||
expr_ref c(m.mk_fresh_const("v", m.get_sort(v)), m);
|
||||
expr_ref eq(m.mk_eq(c, v), m);
|
||||
assert_expr(eq);
|
||||
vars.push_back(c);
|
||||
m_var2orig.insert(c, v);
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i < assumptions0.size(); ++i) {
|
||||
expr* a = assumptions0[i];
|
||||
if (is_uninterp_const(a)) {
|
||||
assumptions.push_back(a);
|
||||
m_assumption2orig.insert(a, a);
|
||||
}
|
||||
else {
|
||||
if (!pushed) {
|
||||
pushed = true;
|
||||
push();
|
||||
}
|
||||
expr_ref c(m.mk_fresh_const("a", m.get_sort(a)), m);
|
||||
expr_ref eq(m.mk_eq(c, a), m);
|
||||
assert_expr(eq);
|
||||
assumptions.push_back(c);
|
||||
m_assumption2orig.insert(c, a);
|
||||
}
|
||||
}
|
||||
lbool is_sat = check(assumptions.size(), assumptions.c_ptr());
|
||||
if (is_sat != l_true) {
|
||||
TRACE("context", tout << is_sat << "\n";);
|
||||
if (pushed) pop(1);
|
||||
return is_sat;
|
||||
}
|
||||
|
||||
obj_map<expr, expr*> var2val;
|
||||
index_set _assumptions;
|
||||
for (unsigned i = 0; i < assumptions.size(); ++i) {
|
||||
_assumptions.insert(get_literal(assumptions[i]).var());
|
||||
_assumptions.insert(get_literal(assumptions[i].get()).var());
|
||||
}
|
||||
model_ref mdl;
|
||||
get_model(mdl);
|
||||
ast_manager& m = m_manager;
|
||||
expr_ref_vector trail(m);
|
||||
model_evaluator eval(*mdl.get());
|
||||
expr_ref val(m);
|
||||
TRACE("context", model_pp(tout, *mdl););
|
||||
for (unsigned i = 0; i < vars.size(); ++i) {
|
||||
eval(vars[i], val);
|
||||
eval(vars[i].get(), val);
|
||||
if (m.is_value(val)) {
|
||||
trail.push_back(val);
|
||||
var2val.insert(vars[i], val);
|
||||
m_var2val.insert(vars[i].get(), val);
|
||||
}
|
||||
else {
|
||||
unfixed.push_back(vars[i]);
|
||||
unfixed.push_back(vars[i].get());
|
||||
}
|
||||
}
|
||||
unsigned num_units = 0;
|
||||
extract_fixed_consequences(num_units, var2val, _assumptions, conseq);
|
||||
extract_fixed_consequences(num_units, _assumptions, conseq);
|
||||
app_ref eq(m);
|
||||
TRACE("context",
|
||||
tout << "vars: " << vars.size() << "\n";
|
||||
|
@ -298,11 +356,12 @@ namespace smt {
|
|||
unsigned num_fixed_eqs = 0;
|
||||
unsigned chunk_size = 100;
|
||||
|
||||
while (!var2val.empty()) {
|
||||
obj_map<expr,expr*>::iterator it = var2val.begin(), end = var2val.end();
|
||||
while (!m_var2val.empty()) {
|
||||
obj_map<expr,expr*>::iterator it = m_var2val.begin(), end = m_var2val.end();
|
||||
unsigned num_vars = 0;
|
||||
for (; it != end && num_vars < chunk_size; ++it) {
|
||||
if (get_cancel_flag()) {
|
||||
if (pushed) pop(1);
|
||||
return l_undef;
|
||||
}
|
||||
expr* e = it->m_key;
|
||||
|
@ -332,6 +391,7 @@ namespace smt {
|
|||
while (true) {
|
||||
is_sat = bounded_search();
|
||||
if (is_sat != l_true && m_last_search_failure != OK) {
|
||||
if (pushed) pop(1);
|
||||
return is_sat;
|
||||
}
|
||||
if (is_sat == l_undef) {
|
||||
|
@ -347,18 +407,21 @@ namespace smt {
|
|||
m_not_l = null_literal;
|
||||
}
|
||||
if (is_sat == l_true) {
|
||||
delete_unfixed(var2val, unfixed);
|
||||
delete_unfixed(unfixed);
|
||||
}
|
||||
extract_fixed_consequences(num_units, var2val, _assumptions, conseq);
|
||||
num_fixed_eqs += extract_fixed_eqs(var2val, conseq);
|
||||
IF_VERBOSE(1, display_consequence_progress(verbose_stream(), num_iterations, var2val.size(), conseq.size(),
|
||||
extract_fixed_consequences(num_units, _assumptions, conseq);
|
||||
num_fixed_eqs += extract_fixed_eqs(conseq);
|
||||
IF_VERBOSE(1, display_consequence_progress(verbose_stream(), num_iterations, m_var2val.size(), conseq.size(),
|
||||
unfixed.size(), num_fixed_eqs););
|
||||
TRACE("context", display_consequence_progress(tout, num_iterations, var2val.size(), conseq.size(),
|
||||
TRACE("context", display_consequence_progress(tout, num_iterations, m_var2val.size(), conseq.size(),
|
||||
unfixed.size(), num_fixed_eqs););
|
||||
}
|
||||
|
||||
end_search();
|
||||
DEBUG_CODE(validate_consequences(assumptions, vars, conseq, unfixed););
|
||||
if (pushed) {
|
||||
pop(1);
|
||||
}
|
||||
return l_true;
|
||||
}
|
||||
|
||||
|
|
|
@ -304,7 +304,6 @@ namespace smt {
|
|||
TRACE("assign_core", tout << (decision?"decision: ":"propagating: ") << l << " ";
|
||||
display_literal_verbose(tout, l); tout << " level: " << m_scope_lvl << "\n";
|
||||
display(tout, j););
|
||||
SASSERT(l.var() < static_cast<int>(m_b_internalized_stack.size()));
|
||||
m_assigned_literals.push_back(l);
|
||||
m_assignment[l.index()] = l_true;
|
||||
m_assignment[(~l).index()] = l_false;
|
||||
|
@ -319,14 +318,23 @@ namespace smt {
|
|||
d.m_phase_available = true;
|
||||
d.m_phase = !l.sign();
|
||||
TRACE("phase_selection", tout << "saving phase, is_pos: " << d.m_phase << " l: " << l << "\n";);
|
||||
|
||||
TRACE("relevancy",
|
||||
tout << "is_atom: " << d.is_atom() << " is relevant: " << is_relevant_core(bool_var2expr(l.var())) << "\n";);
|
||||
if (d.is_atom() && (m_fparams.m_relevancy_lvl == 0 || (m_fparams.m_relevancy_lvl == 1 && !d.is_quantifier()) || is_relevant_core(bool_var2expr(l.var()))))
|
||||
tout << "is_atom: " << d.is_atom() << " is relevant: " << is_relevant_core(l) << "\n";);
|
||||
if (d.is_atom() && (m_fparams.m_relevancy_lvl == 0 || (m_fparams.m_relevancy_lvl == 1 && !d.is_quantifier()) || is_relevant_core(l)))
|
||||
m_atom_propagation_queue.push_back(l);
|
||||
|
||||
if (m_manager.has_trace_stream())
|
||||
trace_assign(l, j, decision);
|
||||
m_case_split_queue->assign_lit_eh(l);
|
||||
|
||||
// a unit is asserted at search level. Mark it as relevant.
|
||||
// this addresses bug... where a literal becomes fixed to true (false)
|
||||
// as a conflict gets assigned misses relevancy (and quantifier instantiation).
|
||||
//
|
||||
if (false && !decision && relevancy() && at_search_level() && !is_relevant_core(l)) {
|
||||
mark_as_relevant(l);
|
||||
}
|
||||
}
|
||||
|
||||
bool context::bcp() {
|
||||
|
@ -1634,7 +1642,7 @@ namespace smt {
|
|||
m_atom_propagation_queue.push_back(literal(v, val == l_false));
|
||||
}
|
||||
}
|
||||
TRACE("propagate_relevancy", tout << "marking as relevant:\n" << mk_bounded_pp(n, m_manager) << "\n";);
|
||||
TRACE("propagate_relevancy", tout << "marking as relevant:\n" << mk_bounded_pp(n, m_manager) << " " << m_scope_lvl << "\n";);
|
||||
#ifndef SMTCOMP
|
||||
m_case_split_queue->relevant_eh(n);
|
||||
#endif
|
||||
|
@ -3073,11 +3081,11 @@ namespace smt {
|
|||
m_assumptions.reset();
|
||||
}
|
||||
|
||||
void context::mk_unsat_core() {
|
||||
lbool context::mk_unsat_core() {
|
||||
SASSERT(inconsistent());
|
||||
if (!tracking_assumptions()) {
|
||||
SASSERT(m_assumptions.empty());
|
||||
return;
|
||||
return l_false;
|
||||
}
|
||||
uint_set already_found_assumptions;
|
||||
literal_vector::const_iterator it = m_conflict_resolution->begin_unsat_core();
|
||||
|
@ -3102,7 +3110,17 @@ namespace smt {
|
|||
for (unsigned i = 0; i < sz; i++) {
|
||||
tout << mk_pp(m_unsat_core.get(i), m_manager) << "\n";
|
||||
});
|
||||
validate_unsat_core();
|
||||
validate_unsat_core();
|
||||
// theory validation of unsat core
|
||||
ptr_vector<theory>::iterator th_it = m_theory_set.begin();
|
||||
ptr_vector<theory>::iterator th_end = m_theory_set.end();
|
||||
for (; th_it != th_end; ++th_it) {
|
||||
lbool theory_result = (*th_it)->validate_unsat_core(m_unsat_core);
|
||||
if (theory_result == l_undef) {
|
||||
return l_undef;
|
||||
}
|
||||
}
|
||||
return l_false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3145,6 +3163,14 @@ namespace smt {
|
|||
SASSERT(m_scope_lvl == 0);
|
||||
SASSERT(!m_setup.already_configured());
|
||||
setup_context(m_fparams.m_auto_config);
|
||||
|
||||
expr_ref_vector theory_assumptions(m_manager);
|
||||
add_theory_assumptions(theory_assumptions);
|
||||
if (!theory_assumptions.empty()) {
|
||||
TRACE("search", tout << "Adding theory assumptions to context" << std::endl;);
|
||||
return check(theory_assumptions.size(), theory_assumptions.c_ptr(), reset_cancel, true);
|
||||
}
|
||||
|
||||
internalize_assertions();
|
||||
lbool r = l_undef;
|
||||
if (m_asserted_formulas.inconsistent()) {
|
||||
|
@ -3206,7 +3232,15 @@ namespace smt {
|
|||
(*it)->setup();
|
||||
}
|
||||
|
||||
lbool context::check(unsigned num_assumptions, expr * const * assumptions, bool reset_cancel) {
|
||||
void context::add_theory_assumptions(expr_ref_vector & theory_assumptions) {
|
||||
ptr_vector<theory>::iterator it = m_theory_set.begin();
|
||||
ptr_vector<theory>::iterator end = m_theory_set.end();
|
||||
for (; it != end; ++it) {
|
||||
(*it)->add_theory_assumptions(theory_assumptions);
|
||||
}
|
||||
}
|
||||
|
||||
lbool context::check(unsigned ext_num_assumptions, expr * const * ext_assumptions, bool reset_cancel, bool already_did_theory_assumptions) {
|
||||
m_stats.m_num_checks++;
|
||||
TRACE("check_bug", tout << "STARTING check(num_assumptions, assumptions)\n";
|
||||
tout << "inconsistent: " << inconsistent() << ", m_unsat_core.empty(): " << m_unsat_core.empty() << "\n";
|
||||
|
@ -3217,6 +3251,15 @@ namespace smt {
|
|||
m_unsat_core.reset();
|
||||
if (!check_preamble(reset_cancel))
|
||||
return l_undef;
|
||||
|
||||
expr_ref_vector all_assumptions(m_manager, ext_num_assumptions, ext_assumptions);
|
||||
if (!already_did_theory_assumptions) {
|
||||
add_theory_assumptions(all_assumptions);
|
||||
}
|
||||
|
||||
unsigned num_assumptions = all_assumptions.size();
|
||||
expr * const * assumptions = all_assumptions.c_ptr();
|
||||
|
||||
if (!validate_assumptions(num_assumptions, assumptions))
|
||||
return l_undef;
|
||||
TRACE("check_bug", tout << "inconsistent: " << inconsistent() << ", m_unsat_core.empty(): " << m_unsat_core.empty() << "\n";);
|
||||
|
@ -3240,13 +3283,21 @@ namespace smt {
|
|||
TRACE("after_internalization", display(tout););
|
||||
if (inconsistent()) {
|
||||
VERIFY(!resolve_conflict()); // build the proof
|
||||
mk_unsat_core();
|
||||
r = l_false;
|
||||
lbool result = mk_unsat_core();
|
||||
if (result == l_undef) {
|
||||
r = l_undef;
|
||||
} else {
|
||||
r = l_false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
r = search();
|
||||
if (r == l_false)
|
||||
mk_unsat_core();
|
||||
if (r == l_false) {
|
||||
lbool result = mk_unsat_core();
|
||||
if (result == l_undef) {
|
||||
r = l_undef;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3750,6 +3801,7 @@ namespace smt {
|
|||
// I invoke pop_scope_core instead of pop_scope because I don't want
|
||||
// to reset cached generations... I need them to rebuild the literals
|
||||
// of the new conflict clause.
|
||||
if (relevancy()) record_relevancy(num_lits, lits);
|
||||
unsigned num_bool_vars = pop_scope_core(m_scope_lvl - new_lvl);
|
||||
SASSERT(m_scope_lvl == new_lvl);
|
||||
// the logical context may still be in conflict after
|
||||
|
@ -3781,6 +3833,7 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (relevancy()) restore_relevancy(num_lits, lits);
|
||||
// Resetting the cache manually because I did not invoke pop_scope, but pop_scope_core
|
||||
reset_cache_generation();
|
||||
TRACE("resolve_conflict_bug",
|
||||
|
@ -3863,6 +3916,28 @@ namespace smt {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
\brief we record and restore relevancy information for literals in conflict clauses.
|
||||
A literal may have been marked relevant within the scope that gets popped during
|
||||
conflict resolution. In this case, the literal is no longer marked as relevant after
|
||||
the pop. This can cause quantifier instantiation to miss relevant triggers and thereby
|
||||
cause incmpleteness.
|
||||
*/
|
||||
void context::record_relevancy(unsigned n, literal const* lits) {
|
||||
m_relevant_conflict_literals.reset();
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
m_relevant_conflict_literals.push_back(is_relevant(lits[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void context::restore_relevancy(unsigned n, literal const* lits) {
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
if (m_relevant_conflict_literals[i] && !is_relevant(lits[i])) {
|
||||
mark_as_relevant(lits[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void context::get_relevant_labels(expr* cnstr, buffer<symbol> & result) {
|
||||
if (m_fparams.m_check_at_labels) {
|
||||
|
@ -4195,42 +4270,21 @@ namespace smt {
|
|||
for (unsigned i = 0; i < m_asserted_formulas.get_num_formulas(); ++i) {
|
||||
expr* e = m_asserted_formulas.get_formula(i);
|
||||
if (is_quantifier(e)) {
|
||||
TRACE("context", tout << mk_pp(e, m) << "\n";);
|
||||
quantifier* q = to_quantifier(e);
|
||||
if (!m.is_rec_fun_def(q)) continue;
|
||||
SASSERT(q->get_num_patterns() == 1);
|
||||
SASSERT(q->get_num_patterns() == 2);
|
||||
expr* fn = to_app(q->get_pattern(0))->get_arg(0);
|
||||
expr* body = to_app(q->get_pattern(1))->get_arg(0);
|
||||
SASSERT(is_app(fn));
|
||||
func_decl* f = to_app(fn)->get_decl();
|
||||
expr* eq = q->get_expr();
|
||||
expr_ref body(m);
|
||||
if (is_fun_def(fn, q->get_expr(), body)) {
|
||||
func_interp* fi = alloc(func_interp, m, f->get_arity());
|
||||
fi->set_else(body);
|
||||
m_model->register_decl(f, fi);
|
||||
}
|
||||
func_interp* fi = alloc(func_interp, m, f->get_arity());
|
||||
fi->set_else(body);
|
||||
m_model->register_decl(f, fi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool context::is_fun_def(expr* f, expr* body, expr_ref& result) {
|
||||
expr* t1, *t2, *t3;
|
||||
if (m_manager.is_eq(body, t1, t2) || m_manager.is_iff(body, t1, t2)) {
|
||||
if (t1 == f) return result = t2, true;
|
||||
if (t2 == f) return result = t1, true;
|
||||
return false;
|
||||
}
|
||||
if (m_manager.is_ite(body, t1, t2, t3)) {
|
||||
expr_ref body1(m_manager), body2(m_manager);
|
||||
if (is_fun_def(f, t2, body1) && is_fun_def(f, t3, body2)) {
|
||||
// f is not free in t1
|
||||
result = m_manager.mk_ite(t1, body1, body2);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1066,7 +1066,9 @@ namespace smt {
|
|||
|
||||
void reset_assumptions();
|
||||
|
||||
void mk_unsat_core();
|
||||
void add_theory_assumptions(expr_ref_vector & theory_assumptions);
|
||||
|
||||
lbool mk_unsat_core();
|
||||
|
||||
void validate_unsat_core();
|
||||
|
||||
|
@ -1110,6 +1112,10 @@ namespace smt {
|
|||
|
||||
bool is_relevant_core(expr * n) const { return m_relevancy_propagator->is_relevant(n); }
|
||||
|
||||
svector<bool> m_relevant_conflict_literals;
|
||||
void record_relevancy(unsigned n, literal const* lits);
|
||||
void restore_relevancy(unsigned n, literal const* lits);
|
||||
|
||||
public:
|
||||
// event handler for relevancy_propagator class
|
||||
void relevant_eh(expr * n);
|
||||
|
@ -1131,6 +1137,10 @@ namespace smt {
|
|||
return is_relevant(l.var());
|
||||
}
|
||||
|
||||
bool is_relevant_core(literal l) const {
|
||||
return is_relevant_core(bool_var2expr(l.var()));
|
||||
}
|
||||
|
||||
void mark_as_relevant(expr * n) { m_relevancy_propagator->mark_as_relevant(n); m_relevancy_propagator->propagate(); }
|
||||
|
||||
void mark_as_relevant(enode * n) { mark_as_relevant(n->get_owner()); }
|
||||
|
@ -1166,8 +1176,6 @@ namespace smt {
|
|||
|
||||
void add_rec_funs_to_model();
|
||||
|
||||
bool is_fun_def(expr* f, expr* q, expr_ref& body);
|
||||
|
||||
public:
|
||||
bool can_propagate() const;
|
||||
|
||||
|
@ -1378,14 +1386,17 @@ namespace smt {
|
|||
typedef hashtable<unsigned, u_hash, u_eq> index_set;
|
||||
//typedef uint_set index_set;
|
||||
u_map<index_set> m_antecedents;
|
||||
void extract_fixed_consequences(literal lit, obj_map<expr, expr*>& var2val, index_set const& assumptions, expr_ref_vector& conseq);
|
||||
void extract_fixed_consequences(unsigned& idx, obj_map<expr, expr*>& var2val, index_set const& assumptions, expr_ref_vector& conseq);
|
||||
obj_map<expr, expr*> m_var2orig;
|
||||
obj_map<expr, expr*> m_assumption2orig;
|
||||
obj_map<expr, expr*> m_var2val;
|
||||
void extract_fixed_consequences(literal lit, index_set const& assumptions, expr_ref_vector& conseq);
|
||||
void extract_fixed_consequences(unsigned& idx, index_set const& assumptions, expr_ref_vector& conseq);
|
||||
|
||||
void display_consequence_progress(std::ostream& out, unsigned it, unsigned nv, unsigned fixed, unsigned unfixed, unsigned eq);
|
||||
|
||||
unsigned delete_unfixed(obj_map<expr, expr*>& var2val, expr_ref_vector& unfixed);
|
||||
unsigned delete_unfixed(expr_ref_vector& unfixed);
|
||||
|
||||
unsigned extract_fixed_eqs(obj_map<expr, expr*>& var2val, expr_ref_vector& conseq);
|
||||
unsigned extract_fixed_eqs(expr_ref_vector& conseq);
|
||||
|
||||
expr_ref antecedent2fml(index_set const& ante);
|
||||
|
||||
|
@ -1442,7 +1453,7 @@ namespace smt {
|
|||
|
||||
void pop(unsigned num_scopes);
|
||||
|
||||
lbool check(unsigned num_assumptions = 0, expr * const * assumptions = 0, bool reset_cancel = true);
|
||||
lbool check(unsigned num_assumptions = 0, expr * const * assumptions = 0, bool reset_cancel = true, bool already_did_theory_assumptions = false);
|
||||
|
||||
lbool get_consequences(expr_ref_vector const& assumptions, expr_ref_vector const& vars, expr_ref_vector& conseq, expr_ref_vector& unfixed);
|
||||
|
||||
|
|
|
@ -433,6 +433,9 @@ namespace smt {
|
|||
if (!is_ground(n)) {
|
||||
continue;
|
||||
}
|
||||
if (is_quantifier(n) && m.is_rec_fun_def(to_quantifier(n))) {
|
||||
continue;
|
||||
}
|
||||
switch (get_assignment(*it)) {
|
||||
case l_undef:
|
||||
break;
|
||||
|
|
|
@ -246,13 +246,15 @@ namespace smt {
|
|||
|
||||
simple_justification::simple_justification(region & r, unsigned num_lits, literal const * lits):
|
||||
m_num_literals(num_lits) {
|
||||
m_literals = new (r) literal[num_lits];
|
||||
memcpy(m_literals, lits, sizeof(literal) * num_lits);
|
||||
if (num_lits != 0) {
|
||||
m_literals = new (r) literal[num_lits];
|
||||
memcpy(m_literals, lits, sizeof(literal) * num_lits);
|
||||
#ifdef Z3DEBUG
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
SASSERT(lits[i] != null_literal);
|
||||
}
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
SASSERT(lits[i] != null_literal);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void simple_justification::get_antecedents(conflict_resolution & cr) {
|
||||
|
|
|
@ -316,9 +316,9 @@ namespace smt {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool model_checker::check_rec_fun(quantifier* q) {
|
||||
bool model_checker::check_rec_fun(quantifier* q, bool strict_rec_fun) {
|
||||
TRACE("model_checker", tout << mk_pp(q, m) << "\n";);
|
||||
SASSERT(q->get_num_patterns() == 1);
|
||||
SASSERT(q->get_num_patterns() == 2); // first pattern is the function, second is the body.
|
||||
expr* fn = to_app(q->get_pattern(0))->get_arg(0);
|
||||
SASSERT(is_app(fn));
|
||||
func_decl* f = to_app(fn)->get_decl();
|
||||
|
@ -340,7 +340,7 @@ namespace smt {
|
|||
}
|
||||
sub(q->get_expr(), num_decls, args.c_ptr(), tmp);
|
||||
m_curr_model->eval(tmp, result, true);
|
||||
if (m.is_false(result)) {
|
||||
if (strict_rec_fun ? !m.is_true(result) : m.is_false(result)) {
|
||||
add_instance(q, args, 0);
|
||||
return false;
|
||||
}
|
||||
|
@ -365,10 +365,10 @@ namespace smt {
|
|||
|
||||
bool model_checker::check(proto_model * md, obj_map<enode, app *> const & root2value) {
|
||||
SASSERT(md != 0);
|
||||
|
||||
m_root2value = &root2value;
|
||||
ptr_vector<quantifier>::const_iterator it = m_qm->begin_quantifiers();
|
||||
ptr_vector<quantifier>::const_iterator end = m_qm->end_quantifiers();
|
||||
if (it == end)
|
||||
|
||||
if (m_qm->num_quantifiers() == 0)
|
||||
return true;
|
||||
|
||||
if (m_iteration_idx >= m_params.m_mbqi_max_iterations) {
|
||||
|
@ -393,6 +393,36 @@ namespace smt {
|
|||
bool found_relevant = false;
|
||||
unsigned num_failures = 0;
|
||||
|
||||
check_quantifiers(false, found_relevant, num_failures);
|
||||
|
||||
|
||||
if (found_relevant)
|
||||
m_iteration_idx++;
|
||||
|
||||
TRACE("model_checker", tout << "model after check:\n"; model_pp(tout, *md););
|
||||
TRACE("model_checker", tout << "model checker result: " << (num_failures == 0) << "\n";);
|
||||
m_max_cexs += m_params.m_mbqi_max_cexs;
|
||||
|
||||
if (num_failures == 0 && !m_context->validate_model()) {
|
||||
num_failures = 1;
|
||||
// this time force expanding recursive function definitions
|
||||
// that are not forced true in the current model.
|
||||
check_quantifiers(true, found_relevant, num_failures);
|
||||
}
|
||||
if (num_failures == 0)
|
||||
m_curr_model->cleanup();
|
||||
if (m_params.m_mbqi_trace) {
|
||||
if (num_failures == 0)
|
||||
verbose_stream() << "(smt.mbqi :succeeded true)\n";
|
||||
else
|
||||
verbose_stream() << "(smt.mbqi :num-failures " << num_failures << ")\n";
|
||||
}
|
||||
return num_failures == 0;
|
||||
}
|
||||
|
||||
void model_checker::check_quantifiers(bool strict_rec_fun, bool& found_relevant, unsigned& num_failures) {
|
||||
ptr_vector<quantifier>::const_iterator it = m_qm->begin_quantifiers();
|
||||
ptr_vector<quantifier>::const_iterator end = m_qm->end_quantifiers();
|
||||
for (; it != end; ++it) {
|
||||
quantifier * q = *it;
|
||||
if(!m_qm->mbqi_enabled(q)) continue;
|
||||
|
@ -406,7 +436,7 @@ namespace smt {
|
|||
}
|
||||
found_relevant = true;
|
||||
if (m.is_rec_fun_def(q)) {
|
||||
if (!check_rec_fun(q)) {
|
||||
if (!check_rec_fun(q, strict_rec_fun)) {
|
||||
TRACE("model_checker", tout << "checking recursive function failed\n";);
|
||||
num_failures++;
|
||||
}
|
||||
|
@ -420,26 +450,6 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found_relevant)
|
||||
m_iteration_idx++;
|
||||
|
||||
TRACE("model_checker", tout << "model after check:\n"; model_pp(tout, *md););
|
||||
TRACE("model_checker", tout << "model checker result: " << (num_failures == 0) << "\n";);
|
||||
m_max_cexs += m_params.m_mbqi_max_cexs;
|
||||
|
||||
if (num_failures == 0 && !m_context->validate_model()) {
|
||||
num_failures = 1;
|
||||
}
|
||||
if (num_failures == 0)
|
||||
m_curr_model->cleanup();
|
||||
if (m_params.m_mbqi_trace) {
|
||||
if (num_failures == 0)
|
||||
verbose_stream() << "(smt.mbqi :succeeded true)\n";
|
||||
else
|
||||
verbose_stream() << "(smt.mbqi :num-failures " << num_failures << ")\n";
|
||||
}
|
||||
return num_failures == 0;
|
||||
}
|
||||
|
||||
void model_checker::init_search_eh() {
|
||||
|
|
|
@ -59,7 +59,8 @@ namespace smt {
|
|||
void assert_neg_q_m(quantifier * q, expr_ref_vector & sks);
|
||||
bool add_blocking_clause(model * cex, expr_ref_vector & sks);
|
||||
bool check(quantifier * q);
|
||||
bool check_rec_fun(quantifier* q);
|
||||
bool check_rec_fun(quantifier* q, bool strict_rec_fun);
|
||||
void check_quantifiers(bool strict_rec_fun, bool& found_relevant, unsigned& num_failures);
|
||||
|
||||
struct instance {
|
||||
quantifier * m_q;
|
||||
|
|
|
@ -52,8 +52,9 @@ namespace smt {
|
|||
m_qi_queue.setup();
|
||||
}
|
||||
|
||||
bool has_trace_stream() const { return m_context.get_manager().has_trace_stream(); }
|
||||
std::ostream & trace_stream() { return m_context.get_manager().trace_stream(); }
|
||||
ast_manager& m() const { return m_context.get_manager(); }
|
||||
bool has_trace_stream() const { return m().has_trace_stream(); }
|
||||
std::ostream & trace_stream() { return m().trace_stream(); }
|
||||
|
||||
quantifier_stat * get_stat(quantifier * q) const {
|
||||
return m_quantifier_stat.find(q);
|
||||
|
@ -110,8 +111,9 @@ namespace smt {
|
|||
unsigned max_top_generation,
|
||||
ptr_vector<enode> & used_enodes) {
|
||||
max_generation = std::max(max_generation, get_generation(q));
|
||||
if (m_num_instances > m_params.m_qi_max_instances)
|
||||
if (m_num_instances > m_params.m_qi_max_instances) {
|
||||
return false;
|
||||
}
|
||||
get_stat(q)->update_max_generation(max_generation);
|
||||
fingerprint * f = m_context.add_fingerprint(q, q->get_id(), num_bindings, bindings);
|
||||
if (f) {
|
||||
|
@ -132,9 +134,17 @@ namespace smt {
|
|||
}
|
||||
m_qi_queue.insert(f, pat, max_generation, min_top_generation, max_top_generation); // TODO
|
||||
m_num_instances++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
TRACE("quantifier",
|
||||
tout << mk_pp(q, m()) << " ";
|
||||
for (unsigned i = 0; i < num_bindings; ++i) {
|
||||
tout << mk_pp(bindings[i]->get_owner(), m()) << " ";
|
||||
}
|
||||
tout << "\n";
|
||||
tout << "inserted: " << (f != 0) << "\n";
|
||||
);
|
||||
|
||||
return f != 0;
|
||||
}
|
||||
|
||||
void init_search_eh() {
|
||||
|
@ -186,7 +196,7 @@ namespace smt {
|
|||
}
|
||||
|
||||
bool check_quantifier(quantifier* q) {
|
||||
return m_context.is_relevant(q) && m_context.get_assignment(q) == l_true; // && !m_context.get_manager().is_rec_fun_def(q);
|
||||
return m_context.is_relevant(q) && m_context.get_assignment(q) == l_true; // && !m().is_rec_fun_def(q);
|
||||
}
|
||||
|
||||
bool quick_check_quantifiers() {
|
||||
|
@ -387,6 +397,10 @@ namespace smt {
|
|||
return m_imp->m_quantifiers.end();
|
||||
}
|
||||
|
||||
unsigned quantifier_manager::num_quantifiers() const {
|
||||
return m_imp->m_quantifiers.size();
|
||||
}
|
||||
|
||||
// The default plugin uses E-matching, MBQI and quick-checker
|
||||
class default_qm_plugin : public quantifier_manager_plugin {
|
||||
quantifier_manager * m_qm;
|
||||
|
@ -501,13 +515,13 @@ namespace smt {
|
|||
SASSERT(m_context->get_manager().is_pattern(mp));
|
||||
bool unary = (mp->get_num_args() == 1);
|
||||
if (!unary && j >= num_eager_multi_patterns) {
|
||||
TRACE("assign_quantifier", tout << "delaying (too many multipatterns):\n" << mk_ismt2_pp(mp, m_context->get_manager()) << "\n"
|
||||
TRACE("quantifier", tout << "delaying (too many multipatterns):\n" << mk_ismt2_pp(mp, m_context->get_manager()) << "\n"
|
||||
<< "j: " << j << " unary: " << unary << " m_params.m_qi_max_eager_multipatterns: " << m_fparams->m_qi_max_eager_multipatterns
|
||||
<< " num_eager_multi_patterns: " << num_eager_multi_patterns << "\n";);
|
||||
m_lazy_mam->add_pattern(q, mp);
|
||||
}
|
||||
else {
|
||||
TRACE("assign_quantifier", tout << "adding:\n" << mk_ismt2_pp(mp, m_context->get_manager()) << "\n";);
|
||||
TRACE("quantifier", tout << "adding:\n" << mk_ismt2_pp(mp, m_context->get_manager()) << "\n";);
|
||||
m_mam->add_pattern(q, mp);
|
||||
}
|
||||
if (!unary)
|
||||
|
|
|
@ -91,6 +91,8 @@ namespace smt {
|
|||
|
||||
ptr_vector<quantifier>::const_iterator begin_quantifiers() const;
|
||||
ptr_vector<quantifier>::const_iterator end_quantifiers() const;
|
||||
unsigned num_quantifiers() const;
|
||||
|
||||
};
|
||||
|
||||
class quantifier_manager_plugin {
|
||||
|
|
|
@ -38,6 +38,7 @@ namespace smt {
|
|||
bool m_minimizing_core;
|
||||
bool m_core_extend_patterns;
|
||||
unsigned m_core_extend_patterns_max_distance;
|
||||
bool m_core_extend_nonlocal_patterns;
|
||||
obj_map<expr, expr*> m_name2assertion;
|
||||
|
||||
public:
|
||||
|
@ -48,13 +49,15 @@ namespace smt {
|
|||
m_context(m, m_smt_params),
|
||||
m_minimizing_core(false),
|
||||
m_core_extend_patterns(false),
|
||||
m_core_extend_patterns_max_distance(UINT_MAX) {
|
||||
m_core_extend_patterns_max_distance(UINT_MAX),
|
||||
m_core_extend_nonlocal_patterns(false) {
|
||||
m_logic = l;
|
||||
if (m_logic != symbol::null)
|
||||
m_context.set_logic(m_logic);
|
||||
smt_params_helper smth(p);
|
||||
m_core_extend_patterns = smth.core_extend_patterns();
|
||||
m_core_extend_patterns_max_distance = smth.core_extend_patterns_max_distance();
|
||||
m_core_extend_nonlocal_patterns = smth.core_extend_nonlocal_patterns();
|
||||
}
|
||||
|
||||
virtual solver * translate(ast_manager & m, params_ref const & p) {
|
||||
|
@ -81,6 +84,8 @@ namespace smt {
|
|||
m_context.updt_params(p);
|
||||
smt_params_helper smth(p);
|
||||
m_core_extend_patterns = smth.core_extend_patterns();
|
||||
m_core_extend_patterns_max_distance = smth.core_extend_patterns_max_distance();
|
||||
m_core_extend_nonlocal_patterns = smth.core_extend_nonlocal_patterns();
|
||||
}
|
||||
|
||||
virtual void collect_param_descrs(param_descrs & r) {
|
||||
|
@ -172,6 +177,8 @@ namespace smt {
|
|||
|
||||
if (m_core_extend_patterns)
|
||||
add_pattern_literals_to_core(r);
|
||||
if (m_core_extend_nonlocal_patterns)
|
||||
add_nonlocal_pattern_literals_to_core(r);
|
||||
}
|
||||
|
||||
virtual void get_model(model_ref & m) {
|
||||
|
@ -250,7 +257,7 @@ namespace smt {
|
|||
}
|
||||
};
|
||||
|
||||
void collect_pattern_func_decls(expr_ref & e, func_decl_set & fds) {
|
||||
void collect_pattern_fds(expr_ref & e, func_decl_set & fds) {
|
||||
collect_pattern_fds_proc p(get_manager(), fds);
|
||||
expr_mark visited;
|
||||
for_each_expr(p, visited, e);
|
||||
|
@ -295,7 +302,7 @@ namespace smt {
|
|||
expr_ref name(core[i], m);
|
||||
SASSERT(m_name2assertion.contains(name));
|
||||
expr_ref assrtn(m_name2assertion.find(name), m);
|
||||
collect_pattern_func_decls(assrtn, pattern_fds);
|
||||
collect_pattern_fds(assrtn, pattern_fds);
|
||||
}
|
||||
|
||||
if (!pattern_fds.empty()) {
|
||||
|
@ -317,6 +324,55 @@ namespace smt {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct collect_body_fds_proc {
|
||||
ast_manager & m;
|
||||
func_decl_set & m_fds;
|
||||
collect_body_fds_proc(ast_manager & m, func_decl_set & fds) :
|
||||
m(m), m_fds(fds) {
|
||||
}
|
||||
void operator()(var * n) {}
|
||||
void operator()(app * n) {}
|
||||
void operator()(quantifier * n) {
|
||||
collect_fds_proc p(m, m_fds);
|
||||
expr_fast_mark1 visited;
|
||||
quick_for_each_expr(p, visited, n->get_expr());
|
||||
}
|
||||
};
|
||||
|
||||
void collect_body_func_decls(expr_ref & e, func_decl_set & fds) {
|
||||
ast_manager & m = get_manager();
|
||||
collect_body_fds_proc p(m, fds);
|
||||
expr_mark visited;
|
||||
for_each_expr(p, visited, e);
|
||||
}
|
||||
|
||||
void add_nonlocal_pattern_literals_to_core(ptr_vector<expr> & core) {
|
||||
ast_manager & m = get_manager();
|
||||
|
||||
obj_map<expr, expr*>::iterator it = m_name2assertion.begin();
|
||||
obj_map<expr, expr*>::iterator end = m_name2assertion.end();
|
||||
for (unsigned i = 0; it != end; it++, i++) {
|
||||
expr_ref name(it->m_key, m);
|
||||
expr_ref assrtn(it->m_value, m);
|
||||
|
||||
if (!core.contains(name)) {
|
||||
func_decl_set pattern_fds, body_fds;
|
||||
collect_pattern_fds(assrtn, pattern_fds);
|
||||
collect_body_func_decls(assrtn, body_fds);
|
||||
|
||||
func_decl_set::iterator pit = pattern_fds.begin();
|
||||
func_decl_set::iterator pend= pattern_fds.end();
|
||||
for (; pit != pend; pit++) {
|
||||
func_decl * fd = *pit;
|
||||
if (!body_fds.contains(fd)) {
|
||||
core.insert(name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -177,6 +177,22 @@ namespace smt {
|
|||
virtual void restart_eh() {
|
||||
}
|
||||
|
||||
/**
|
||||
\brief This method is called by smt_context before the search starts
|
||||
to get any extra assumptions the theory wants to use.
|
||||
(See theory_str for an example)
|
||||
*/
|
||||
virtual void add_theory_assumptions(expr_ref_vector & assumptions) {
|
||||
}
|
||||
|
||||
/**
|
||||
\brief This method is called from smt_context when an unsat core is generated.
|
||||
The theory may change the answer to UNKNOWN by returning l_undef from this method.
|
||||
*/
|
||||
virtual lbool validate_unsat_core(expr_ref_vector & unsat_core) {
|
||||
return l_false;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief This method is invoked before the search starts.
|
||||
*/
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace smt {
|
|||
template<typename Ext>
|
||||
void theory_arith<Ext>::found_underspecified_op(app * n) {
|
||||
if (!m_found_underspecified_op) {
|
||||
TRACE("arith", tout << "found non underspecificed expression:\n" << mk_pp(n, get_manager()) << "\n";);
|
||||
TRACE("arith", tout << "found underspecificed expression:\n" << mk_pp(n, get_manager()) << "\n";);
|
||||
get_context().push_trail(value_trail<context, bool>(m_found_underspecified_op));
|
||||
m_found_underspecified_op = true;
|
||||
}
|
||||
|
@ -395,6 +395,7 @@ namespace smt {
|
|||
|
||||
template<typename Ext>
|
||||
theory_var theory_arith<Ext>::internalize_div(app * n) {
|
||||
if (!m_util.is_numeral(n->get_arg(1))) found_underspecified_op(n);
|
||||
found_underspecified_op(n);
|
||||
theory_var s = mk_binary_op(n);
|
||||
context & ctx = get_context();
|
||||
|
@ -418,7 +419,7 @@ namespace smt {
|
|||
template<typename Ext>
|
||||
theory_var theory_arith<Ext>::internalize_mod(app * n) {
|
||||
TRACE("arith_mod", tout << "internalizing...\n" << mk_pp(n, get_manager()) << "\n";);
|
||||
found_underspecified_op(n);
|
||||
if (!m_util.is_numeral(n->get_arg(1))) found_underspecified_op(n);
|
||||
theory_var s = mk_binary_op(n);
|
||||
context & ctx = get_context();
|
||||
if (!ctx.relevancy())
|
||||
|
@ -428,7 +429,7 @@ namespace smt {
|
|||
|
||||
template<typename Ext>
|
||||
theory_var theory_arith<Ext>::internalize_rem(app * n) {
|
||||
found_underspecified_op(n);
|
||||
if (!m_util.is_numeral(n->get_arg(1))) found_underspecified_op(n);
|
||||
theory_var s = mk_binary_op(n);
|
||||
context & ctx = get_context();
|
||||
if (!ctx.relevancy()) {
|
||||
|
|
|
@ -206,7 +206,8 @@ namespace smt {
|
|||
numeral k = ceil(get_value(v));
|
||||
rational _k = k.to_rational();
|
||||
expr_ref bound(get_manager());
|
||||
bound = m_util.mk_ge(get_enode(v)->get_owner(), m_util.mk_numeral(_k, true));
|
||||
expr* e = get_enode(v)->get_owner();
|
||||
bound = m_util.mk_ge(e, m_util.mk_numeral(_k, m_util.is_int(e)));
|
||||
TRACE("arith_int", tout << mk_bounded_pp(bound, get_manager()) << "\n";);
|
||||
context & ctx = get_context();
|
||||
ctx.internalize(bound, true);
|
||||
|
@ -371,7 +372,7 @@ namespace smt {
|
|||
|
||||
ctx.mk_th_axiom(get_id(), l1, l2);
|
||||
|
||||
TRACE("theory_arith_int",
|
||||
TRACE("arith_int",
|
||||
tout << "cut: (or " << mk_pp(p1, get_manager()) << " " << mk_pp(p2, get_manager()) << ")\n";
|
||||
);
|
||||
|
||||
|
@ -1407,6 +1408,7 @@ namespace smt {
|
|||
if (m_params.m_arith_int_eq_branching && branch_infeasible_int_equality()) {
|
||||
return FC_CONTINUE;
|
||||
}
|
||||
|
||||
theory_var int_var = find_infeasible_int_base_var();
|
||||
if (int_var != null_theory_var) {
|
||||
TRACE("arith_int", tout << "v" << int_var << " does not have an integer assignment: " << get_value(int_var) << "\n";);
|
||||
|
|
|
@ -339,8 +339,13 @@ namespace smt {
|
|||
tout << mk_pp(var, get_manager()) << "\n";
|
||||
tout << "power " << power << ": " << expt(i, power) << "\n";
|
||||
display_interval(tout << "target before: ", target); tout << "\n";);
|
||||
|
||||
i.expt(power);
|
||||
target *= i;
|
||||
|
||||
get_manager().limit().inc((target.is_lower_open() || target.minus_infinity()) ? 1 : target.get_lower_value().bitsize());
|
||||
get_manager().limit().inc((target.is_upper_open() || target.plus_infinity()) ? 1 : target.get_upper_value().bitsize());
|
||||
|
||||
TRACE("non_linear", display_interval(tout << "target after: ", target); tout << "\n";);
|
||||
}
|
||||
|
||||
|
|
|
@ -607,12 +607,13 @@ namespace smt {
|
|||
}
|
||||
expr_ref sum(m);
|
||||
arith_simp().mk_add(sz, args.c_ptr(), sum);
|
||||
literal l(mk_eq(n, sum, false));
|
||||
TRACE("bv",
|
||||
tout << mk_pp(n, m) << "\n";
|
||||
tout << mk_pp(sum, m) << "\n";
|
||||
ctx.display_literal_verbose(tout, l);
|
||||
tout << "\n";
|
||||
);
|
||||
|
||||
literal l(mk_eq(n, sum, false));
|
||||
|
||||
ctx.mark_as_relevant(l);
|
||||
ctx.mk_th_axiom(get_id(), 1, &l);
|
||||
|
|
|
@ -868,7 +868,8 @@ namespace smt {
|
|||
e = ctx.get_enode(to_app(n));
|
||||
}
|
||||
else {
|
||||
e = ctx.mk_enode(to_app(n), false, false, true);
|
||||
ctx.internalize(n, false);
|
||||
e = ctx.get_enode(n);
|
||||
}
|
||||
v = e->get_th_var(get_id());
|
||||
if (v == null_theory_var) {
|
||||
|
@ -901,7 +902,7 @@ namespace smt {
|
|||
objective_term const& objective = m_objectives[v];
|
||||
has_shared = false;
|
||||
|
||||
IF_VERBOSE(1,
|
||||
IF_VERBOSE(4,
|
||||
for (unsigned i = 0; i < objective.size(); ++i) {
|
||||
verbose_stream() << objective[i].second
|
||||
<< " * v" << objective[i].first << " ";
|
||||
|
@ -991,9 +992,12 @@ namespace smt {
|
|||
if (num_nodes <= v && v < num_nodes + num_edges) {
|
||||
unsigned edge_id = v - num_nodes;
|
||||
literal lit = m_edges[edge_id].m_justification;
|
||||
get_context().literal2expr(lit, tmp);
|
||||
core.push_back(tmp);
|
||||
if (lit != null_literal) {
|
||||
get_context().literal2expr(lit, tmp);
|
||||
core.push_back(tmp);
|
||||
}
|
||||
}
|
||||
TRACE("opt", tout << core << "\n";);
|
||||
}
|
||||
for (unsigned i = 0; i < num_nodes; ++i) {
|
||||
mpq_inf const& val = S.get_value(i);
|
||||
|
@ -1005,7 +1009,8 @@ namespace smt {
|
|||
inf_eps result(rational(0), r);
|
||||
blocker = mk_gt(v, result);
|
||||
IF_VERBOSE(10, verbose_stream() << blocker << "\n";);
|
||||
return result;
|
||||
r += m_objective_consts[v];
|
||||
return inf_eps(rational(0), r);
|
||||
}
|
||||
default:
|
||||
TRACE("opt", tout << "unbounded\n"; );
|
||||
|
@ -1016,6 +1021,7 @@ namespace smt {
|
|||
|
||||
template<typename Ext>
|
||||
theory_var theory_dense_diff_logic<Ext>::add_objective(app* term) {
|
||||
TRACE("opt", tout << mk_pp(term, get_manager()) << "\n";);
|
||||
objective_term objective;
|
||||
theory_var result = m_objectives.size();
|
||||
rational q(1), r(0);
|
||||
|
@ -1050,6 +1056,7 @@ namespace smt {
|
|||
ast_manager& m = get_manager();
|
||||
objective_term const& t = m_objectives[v];
|
||||
expr_ref e(m), f(m), f2(m);
|
||||
TRACE("opt", tout << "mk_ineq " << v << " " << val << "\n";);
|
||||
if (t.size() == 1 && t[0].second.is_one()) {
|
||||
f = get_enode(t[0].first)->get_owner();
|
||||
}
|
||||
|
|
|
@ -255,6 +255,11 @@ final_check_status theory_seq::final_check_eh() {
|
|||
TRACE("seq", tout << ">>solve_eqs\n";);
|
||||
return FC_CONTINUE;
|
||||
}
|
||||
if (check_contains()) {
|
||||
++m_stats.m_propagate_contains;
|
||||
TRACE("seq", tout << ">>propagate_contains\n";);
|
||||
return FC_CONTINUE;
|
||||
}
|
||||
if (solve_nqs(0)) {
|
||||
++m_stats.m_solve_nqs;
|
||||
TRACE("seq", tout << ">>solve_nqs\n";);
|
||||
|
@ -290,11 +295,6 @@ final_check_status theory_seq::final_check_eh() {
|
|||
TRACE("seq", tout << ">>propagate_automata\n";);
|
||||
return FC_CONTINUE;
|
||||
}
|
||||
if (check_contains()) {
|
||||
++m_stats.m_propagate_contains;
|
||||
TRACE("seq", tout << ">>propagate_contains\n";);
|
||||
return FC_CONTINUE;
|
||||
}
|
||||
if (is_solved()) {
|
||||
TRACE("seq", tout << ">>is_solved\n";);
|
||||
return FC_DONE;
|
||||
|
@ -1159,7 +1159,7 @@ bool theory_seq::check_extensionality() {
|
|||
}
|
||||
|
||||
/*
|
||||
\brief check negated contains constriants.
|
||||
\brief check negated contains constraints.
|
||||
*/
|
||||
bool theory_seq::check_contains() {
|
||||
context & ctx = get_context();
|
||||
|
@ -1199,6 +1199,11 @@ bool theory_seq::is_solved() {
|
|||
IF_VERBOSE(10, display_disequation(verbose_stream() << "(seq.giveup ", m_nqs[0]); verbose_stream() << " is unsolved)\n";);
|
||||
return false;
|
||||
}
|
||||
if (!m_ncs.empty()) {
|
||||
TRACE("seq", display_nc(tout << "(seq.giveup ", m_ncs[0]); tout << " is unsolved)\n";);
|
||||
IF_VERBOSE(10, display_nc(verbose_stream() << "(seq.giveup ", m_ncs[0]); verbose_stream() << " is unsolved)\n";);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1981,6 +1986,23 @@ bool theory_seq::solve_nc(unsigned idx) {
|
|||
}
|
||||
if (c != n.contains()) {
|
||||
m_ncs.push_back(nc(c, deps));
|
||||
m_new_propagation = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
expr* e1, *e2;
|
||||
if (m.is_eq(c, e1, e2)) {
|
||||
literal eq = mk_eq(e1, e2, false);
|
||||
propagate_lit(deps, 0, 0, ~eq);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m.is_or(c)) {
|
||||
for (unsigned i = 0; i < to_app(c)->get_num_args(); ++i) {
|
||||
expr_ref ci(to_app(c)->get_arg(i), m);
|
||||
m_ncs.push_back(nc(ci, deps));
|
||||
}
|
||||
m_new_propagation = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -2344,6 +2366,17 @@ bool theory_seq::add_itos_axiom(expr* e) {
|
|||
return false;
|
||||
}
|
||||
add_axiom(mk_eq(e2, n, false));
|
||||
|
||||
#if 1
|
||||
expr_ref num_re(m), opt_re(m);
|
||||
num_re = m_util.re.mk_range(m_util.str.mk_string(symbol("0")), m_util.str.mk_string(symbol("9")));
|
||||
num_re = m_util.re.mk_plus(num_re);
|
||||
opt_re = m_util.re.mk_opt(m_util.re.mk_to_re(m_util.str.mk_string(symbol("-"))));
|
||||
num_re = m_util.re.mk_concat(opt_re, num_re);
|
||||
app_ref in_re(m_util.re.mk_in_re(e, num_re), m);
|
||||
internalize_term(in_re);
|
||||
propagate_in_re(in_re, true);
|
||||
#endif
|
||||
m_trail_stack.push(push_replay(alloc(replay_axiom, m, e)));
|
||||
return true;
|
||||
}
|
||||
|
@ -2403,6 +2436,18 @@ void theory_seq::display(std::ostream & out) const {
|
|||
}
|
||||
}
|
||||
|
||||
if (!m_ncs.empty()) {
|
||||
out << "Non contains:\n";
|
||||
for (unsigned i = 0; i < m_ncs.size(); ++i) {
|
||||
display_nc(out, m_ncs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void theory_seq::display_nc(std::ostream& out, nc const& nc) const {
|
||||
out << "not " << mk_pp(nc.contains(), m) << "\n";
|
||||
display_deps(out << " <- ", nc.deps()); out << "\n";
|
||||
}
|
||||
|
||||
void theory_seq::display_equations(std::ostream& out) const {
|
||||
|
@ -2719,7 +2764,9 @@ bool theory_seq::can_propagate() {
|
|||
|
||||
expr_ref theory_seq::canonize(expr* e, dependency*& eqs) {
|
||||
expr_ref result = expand(e, eqs);
|
||||
TRACE("seq", tout << mk_pp(e, m) << " expands to " << result << "\n";);
|
||||
m_rewrite(result);
|
||||
TRACE("seq", tout << mk_pp(e, m) << " rewrites to " << result << "\n";);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -3494,6 +3541,7 @@ void theory_seq::add_extract_suffix_axiom(expr* e, expr* s, expr* i) {
|
|||
let e = at(s, i)
|
||||
|
||||
0 <= i < len(s) -> s = xey & len(x) = i & len(e) = 1
|
||||
i < 0 \/ i >= len(s) -> e = empty
|
||||
|
||||
*/
|
||||
void theory_seq::add_at_axiom(expr* e) {
|
||||
|
@ -3507,13 +3555,18 @@ void theory_seq::add_at_axiom(expr* e) {
|
|||
expr_ref y = mk_skolem(m_post, s, mk_sub(mk_sub(len_s, i), one));
|
||||
expr_ref xey = mk_concat(x, e, y);
|
||||
expr_ref len_x(m_util.str.mk_length(x), m);
|
||||
expr_ref emp(m_util.str.mk_empty(m.get_sort(e)), m);
|
||||
|
||||
literal i_ge_0 = mk_literal(m_autil.mk_ge(i, zero));
|
||||
literal i_ge_len_s = mk_literal(m_autil.mk_ge(mk_sub(i, m_util.str.mk_length(s)), zero));
|
||||
|
||||
|
||||
add_axiom(~i_ge_0, i_ge_len_s, mk_seq_eq(s, xey));
|
||||
add_axiom(~i_ge_0, i_ge_len_s, mk_eq(one, len_e, false));
|
||||
add_axiom(~i_ge_0, i_ge_len_s, mk_eq(i, len_x, false));
|
||||
|
||||
add_axiom(i_ge_0, mk_eq(s, emp, false));
|
||||
add_axiom(~i_ge_len_s, mk_eq(s, emp, false));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4469,10 +4522,11 @@ bool theory_seq::canonizes(bool sign, expr* e) {
|
|||
context& ctx = get_context();
|
||||
dependency* deps = 0;
|
||||
expr_ref cont = canonize(e, deps);
|
||||
TRACE("seq", tout << mk_pp(e, m) << " -> " << cont << "\n";);
|
||||
TRACE("seq", tout << mk_pp(e, m) << " -> " << cont << "\n";
|
||||
if (deps) display_deps(tout, deps););
|
||||
if ((m.is_true(cont) && !sign) ||
|
||||
(m.is_false(cont) && sign)) {
|
||||
TRACE("seq", display(tout););
|
||||
TRACE("seq", display(tout); tout << ctx.get_assignment(ctx.get_literal(e)) << "\n";);
|
||||
propagate_lit(deps, 0, 0, ctx.get_literal(e));
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -570,6 +570,7 @@ namespace smt {
|
|||
void display_disequation(std::ostream& out, ne const& e) const;
|
||||
void display_deps(std::ostream& out, dependency* deps) const;
|
||||
void display_deps(std::ostream& out, literal_vector const& lits, enode_pair_vector const& eqs) const;
|
||||
void display_nc(std::ostream& out, nc const& nc) const;
|
||||
public:
|
||||
theory_seq(ast_manager& m);
|
||||
virtual ~theory_seq();
|
||||
|
|
|
@ -34,6 +34,7 @@ class elim_small_bv_tactic : public tactic {
|
|||
|
||||
struct rw_cfg : public default_rewriter_cfg {
|
||||
ast_manager & m;
|
||||
params_ref m_params;
|
||||
bv_util m_util;
|
||||
simplifier m_simp;
|
||||
ref<filter_model_converter> m_mc;
|
||||
|
@ -47,6 +48,7 @@ class elim_small_bv_tactic : public tactic {
|
|||
|
||||
rw_cfg(ast_manager & _m, params_ref const & p) :
|
||||
m(_m),
|
||||
m_params(p),
|
||||
m_util(_m),
|
||||
m_simp(_m),
|
||||
m_bindings(_m),
|
||||
|
@ -119,7 +121,7 @@ class elim_small_bv_tactic : public tactic {
|
|||
return res;
|
||||
}
|
||||
|
||||
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
|
||||
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
|
||||
TRACE("elim_small_bv_app", expr_ref tmp(m.mk_app(f, num, args), m); tout << "reduce " << tmp << std::endl; );
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
@ -178,7 +180,7 @@ class elim_small_bv_tactic : public tactic {
|
|||
|
||||
quantifier_ref new_q(m);
|
||||
new_q = m.update_quantifier(q, body);
|
||||
unused_vars_eliminator el(m);
|
||||
unused_vars_eliminator el(m, m_params);
|
||||
el(new_q, result);
|
||||
|
||||
TRACE("elim_small_bv", tout << "elimination result: " << mk_ismt2_pp(result, m) << std::endl; );
|
||||
|
@ -203,6 +205,7 @@ class elim_small_bv_tactic : public tactic {
|
|||
}
|
||||
|
||||
void updt_params(params_ref const & p) {
|
||||
m_params = p;
|
||||
m_max_memory = megabytes_to_bytes(p.get_uint("max_memory", UINT_MAX));
|
||||
m_max_steps = p.get_uint("max_steps", UINT_MAX);
|
||||
m_max_bits = p.get_uint("max_bits", 4);
|
||||
|
@ -305,7 +308,7 @@ public:
|
|||
virtual void cleanup() {
|
||||
ast_manager & m = m_imp->m;
|
||||
imp * d = alloc(imp, m, m_params);
|
||||
std::swap(d, m_imp);
|
||||
std::swap(d, m_imp);
|
||||
dealloc(d);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,9 +24,9 @@ class distribute_forall_tactic : public tactic {
|
|||
ast_manager & m;
|
||||
|
||||
rw_cfg(ast_manager & _m):m(_m) {}
|
||||
bool reduce_quantifier(quantifier * old_q,
|
||||
expr * new_body,
|
||||
expr * const * new_patterns,
|
||||
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) {
|
||||
|
@ -34,7 +34,7 @@ class distribute_forall_tactic : public tactic {
|
|||
if (!old_q->is_forall()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (m.is_not(new_body) && m.is_or(to_app(new_body)->get_arg(0))) {
|
||||
// (forall X (not (or F1 ... Fn)))
|
||||
// -->
|
||||
|
@ -50,13 +50,13 @@ class distribute_forall_tactic : public tactic {
|
|||
quantifier_ref tmp_q(m);
|
||||
tmp_q = m.update_quantifier(old_q, not_arg);
|
||||
expr_ref new_q(m);
|
||||
elim_unused_vars(m, tmp_q, new_q);
|
||||
elim_unused_vars(m, tmp_q, params_ref(), new_q);
|
||||
new_args.push_back(new_q);
|
||||
}
|
||||
result = m.mk_and(new_args.size(), new_args.c_ptr());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (m.is_and(new_body)) {
|
||||
// (forall X (and F1 ... Fn))
|
||||
// -->
|
||||
|
@ -70,20 +70,20 @@ class distribute_forall_tactic : public tactic {
|
|||
quantifier_ref tmp_q(m);
|
||||
tmp_q = m.update_quantifier(old_q, arg);
|
||||
expr_ref new_q(m);
|
||||
elim_unused_vars(m, tmp_q, new_q);
|
||||
elim_unused_vars(m, tmp_q, params_ref(), new_q);
|
||||
new_args.push_back(new_q);
|
||||
}
|
||||
result = m.mk_and(new_args.size(), new_args.c_ptr());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
struct rw : public rewriter_tpl<rw_cfg> {
|
||||
rw_cfg m_cfg;
|
||||
|
||||
|
||||
rw(ast_manager & m, bool proofs_enabled):
|
||||
rewriter_tpl<rw_cfg>(m, proofs_enabled, m_cfg),
|
||||
m_cfg(m) {
|
||||
|
@ -99,19 +99,19 @@ public:
|
|||
return alloc(distribute_forall_tactic);
|
||||
}
|
||||
|
||||
virtual void operator()(goal_ref const & g,
|
||||
goal_ref_buffer & result,
|
||||
model_converter_ref & mc,
|
||||
virtual void operator()(goal_ref const & g,
|
||||
goal_ref_buffer & result,
|
||||
model_converter_ref & mc,
|
||||
proof_converter_ref & pc,
|
||||
expr_dependency_ref & core) {
|
||||
SASSERT(g->is_well_sorted());
|
||||
ast_manager & m = g->m();
|
||||
bool produce_proofs = g->proofs_enabled();
|
||||
rw r(m, produce_proofs);
|
||||
m_rw = &r;
|
||||
m_rw = &r;
|
||||
mc = 0; pc = 0; core = 0; result.reset();
|
||||
tactic_report report("distribute-forall", *g);
|
||||
|
||||
|
||||
expr_ref new_curr(m);
|
||||
proof_ref new_pr(m);
|
||||
unsigned size = g->size();
|
||||
|
@ -126,12 +126,12 @@ public:
|
|||
}
|
||||
g->update(idx, new_curr, new_pr, g->dep(idx));
|
||||
}
|
||||
|
||||
|
||||
g->inc_depth();
|
||||
result.push_back(g.get());
|
||||
TRACE("distribute-forall", g->display(tout););
|
||||
SASSERT(g->is_well_sorted());
|
||||
m_rw = 0;
|
||||
m_rw = 0;
|
||||
}
|
||||
|
||||
virtual void cleanup() {}
|
||||
|
|
|
@ -34,19 +34,19 @@ Notes:
|
|||
class bounded_int2bv_solver : public solver_na2as {
|
||||
ast_manager& m;
|
||||
params_ref m_params;
|
||||
bv_util m_bv;
|
||||
arith_util m_arith;
|
||||
expr_ref_vector m_assertions;
|
||||
mutable bv_util m_bv;
|
||||
mutable arith_util m_arith;
|
||||
mutable expr_ref_vector m_assertions;
|
||||
ref<solver> m_solver;
|
||||
ptr_vector<bound_manager> m_bounds;
|
||||
func_decl_ref_vector m_bv_fns;
|
||||
func_decl_ref_vector m_int_fns;
|
||||
mutable ptr_vector<bound_manager> m_bounds;
|
||||
mutable func_decl_ref_vector m_bv_fns;
|
||||
mutable func_decl_ref_vector m_int_fns;
|
||||
unsigned_vector m_bv_fns_lim;
|
||||
obj_map<func_decl, func_decl*> m_int2bv;
|
||||
obj_map<func_decl, func_decl*> m_bv2int;
|
||||
obj_map<func_decl, rational> m_bv2offset;
|
||||
bv2int_rewriter_ctx m_rewriter_ctx;
|
||||
bv2int_rewriter_star m_rewriter;
|
||||
mutable obj_map<func_decl, func_decl*> m_int2bv;
|
||||
mutable obj_map<func_decl, func_decl*> m_bv2int;
|
||||
mutable obj_map<func_decl, rational> m_bv2offset;
|
||||
mutable bv2int_rewriter_ctx m_rewriter_ctx;
|
||||
mutable bv2int_rewriter_star m_rewriter;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -78,7 +78,19 @@ public:
|
|||
}
|
||||
|
||||
virtual void assert_expr(expr * t) {
|
||||
unsigned i = m_assertions.size();
|
||||
m_assertions.push_back(t);
|
||||
while (i < m_assertions.size()) {
|
||||
t = m_assertions[i].get();
|
||||
if (m.is_and(t)) {
|
||||
m_assertions.append(to_app(t)->get_num_args(), to_app(t)->get_args());
|
||||
m_assertions[i] = m_assertions.back();
|
||||
m_assertions.pop_back();
|
||||
}
|
||||
else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void push_core() {
|
||||
|
@ -184,7 +196,7 @@ private:
|
|||
}
|
||||
filter_model_converter filter(m);
|
||||
for (unsigned i = 0; i < m_bv_fns.size(); ++i) {
|
||||
filter.insert(m_bv_fns[i]);
|
||||
filter.insert(m_bv_fns[i].get());
|
||||
}
|
||||
filter(mdl, 0);
|
||||
}
|
||||
|
@ -205,13 +217,13 @@ private:
|
|||
ext(mdl, 0);
|
||||
}
|
||||
|
||||
void accumulate_sub(expr_safe_replace& sub) {
|
||||
void accumulate_sub(expr_safe_replace& sub) const {
|
||||
for (unsigned i = 0; i < m_bounds.size(); ++i) {
|
||||
accumulate_sub(sub, *m_bounds[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void accumulate_sub(expr_safe_replace& sub, bound_manager& bm) {
|
||||
void accumulate_sub(expr_safe_replace& sub, bound_manager& bm) const {
|
||||
bound_manager::iterator it = bm.begin(), end = bm.end();
|
||||
for (; it != end; ++it) {
|
||||
expr* e = *it;
|
||||
|
@ -252,19 +264,20 @@ private:
|
|||
sub.insert(e, t);
|
||||
}
|
||||
else {
|
||||
IF_VERBOSE(1,
|
||||
verbose_stream() << "unprocessed entry: " << mk_pp(e, m) << "\n";
|
||||
if (bm.has_lower(e, lo, s1)) {
|
||||
verbose_stream() << "lower: " << lo << " " << s1 << "\n";
|
||||
}
|
||||
if (bm.has_upper(e, hi, s2)) {
|
||||
verbose_stream() << "upper: " << hi << " " << s2 << "\n";
|
||||
});
|
||||
TRACE("pb",
|
||||
tout << "unprocessed entry: " << mk_pp(e, m) << "\n";
|
||||
if (bm.has_lower(e, lo, s1)) {
|
||||
tout << "lower: " << lo << " " << s1 << "\n";
|
||||
}
|
||||
if (bm.has_upper(e, hi, s2)) {
|
||||
tout << "upper: " << hi << " " << s2 << "\n";
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned get_num_bits(rational const& k) {
|
||||
|
||||
unsigned get_num_bits(rational const& k) const {
|
||||
SASSERT(!k.is_neg());
|
||||
SASSERT(k.is_int());
|
||||
rational two(2);
|
||||
|
@ -277,11 +290,13 @@ private:
|
|||
return num_bits;
|
||||
}
|
||||
|
||||
void flush_assertions() {
|
||||
void flush_assertions() const {
|
||||
if (m_assertions.empty()) return;
|
||||
bound_manager& bm = *m_bounds.back();
|
||||
for (unsigned i = 0; i < m_assertions.size(); ++i) {
|
||||
bm(m_assertions[i].get());
|
||||
}
|
||||
TRACE("int2bv", bm.display(tout););
|
||||
expr_safe_replace sub(m);
|
||||
accumulate_sub(sub);
|
||||
proof_ref proof(m);
|
||||
|
@ -304,6 +319,17 @@ private:
|
|||
m_assertions.reset();
|
||||
m_rewriter.reset();
|
||||
}
|
||||
|
||||
virtual unsigned get_num_assertions() const {
|
||||
flush_assertions();
|
||||
return m_solver->get_num_assertions();
|
||||
}
|
||||
|
||||
virtual expr * get_assertion(unsigned idx) const {
|
||||
flush_assertions();
|
||||
return m_solver->get_assertion(idx);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
solver * mk_bounded_int2bv_solver(ast_manager & m, params_ref const & p, solver* s) {
|
||||
|
|
|
@ -163,6 +163,14 @@ public:
|
|||
ext(mdl, 0);
|
||||
}
|
||||
|
||||
virtual unsigned get_num_assertions() const {
|
||||
return m_solver->get_num_assertions();
|
||||
}
|
||||
|
||||
virtual expr * get_assertion(unsigned idx) const {
|
||||
return m_solver->get_assertion(idx);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
solver * mk_enum2bv_solver(ast_manager & m, params_ref const & p, solver* s) {
|
||||
|
|
|
@ -27,9 +27,9 @@ Notes:
|
|||
class pb2bv_solver : public solver_na2as {
|
||||
ast_manager& m;
|
||||
params_ref m_params;
|
||||
expr_ref_vector m_assertions;
|
||||
ref<solver> m_solver;
|
||||
pb2bv_rewriter m_rewriter;
|
||||
mutable expr_ref_vector m_assertions;
|
||||
mutable ref<solver> m_solver;
|
||||
mutable pb2bv_rewriter m_rewriter;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -107,8 +107,19 @@ public:
|
|||
filter(mdl, 0);
|
||||
}
|
||||
|
||||
virtual unsigned get_num_assertions() const {
|
||||
flush_assertions();
|
||||
return m_solver->get_num_assertions();
|
||||
}
|
||||
|
||||
virtual expr * get_assertion(unsigned idx) const {
|
||||
flush_assertions();
|
||||
return m_solver->get_assertion(idx);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
void flush_assertions() {
|
||||
void flush_assertions() const {
|
||||
proof_ref proof(m);
|
||||
expr_ref fml(m);
|
||||
expr_ref_vector fmls(m);
|
||||
|
|
|
@ -49,7 +49,7 @@ ufbv_rewriter::~ufbv_rewriter() {
|
|||
bool ufbv_rewriter::is_demodulator(expr * e, expr_ref & large, expr_ref & small) const {
|
||||
if (e->get_kind() == AST_QUANTIFIER) {
|
||||
quantifier * q = to_quantifier(e);
|
||||
if (q->is_forall()) {
|
||||
if (q->is_forall()) {
|
||||
expr * qe = q->get_expr();
|
||||
if ((m_manager.is_eq(qe) || m_manager.is_iff(qe))) {
|
||||
app * eq = to_app(q->get_expr());
|
||||
|
@ -61,7 +61,7 @@ bool ufbv_rewriter::is_demodulator(expr * e, expr_ref & large, expr_ref & small)
|
|||
<< mk_pp(lhs, m_manager) << "\n"
|
||||
<< mk_pp(rhs, m_manager) << "\n"
|
||||
<< "subset: " << subset << ", smaller: " << smaller << "\n";);
|
||||
// We only track uninterpreted functions, everything else is likely too expensive.
|
||||
// We only track uninterpreted functions, everything else is likely too expensive.
|
||||
if ((subset == +1 || subset == +2) && smaller == +1) {
|
||||
if (is_uninterp(rhs)) {
|
||||
large = rhs;
|
||||
|
@ -78,7 +78,7 @@ bool ufbv_rewriter::is_demodulator(expr * e, expr_ref & large, expr_ref & small)
|
|||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
if ((subset == -1 || subset == +2) && smaller == -1) {
|
||||
if (is_uninterp(lhs)) {
|
||||
large = lhs;
|
||||
|
@ -113,13 +113,13 @@ bool ufbv_rewriter::is_demodulator(expr * e, expr_ref & large, expr_ref & small)
|
|||
return false;
|
||||
}
|
||||
|
||||
class var_set_proc {
|
||||
class var_set_proc {
|
||||
uint_set & m_set;
|
||||
public:
|
||||
var_set_proc(uint_set &s):m_set(s) {}
|
||||
void operator()(var * n) { m_set.insert(n->get_idx()); }
|
||||
void operator()(quantifier * n) {}
|
||||
void operator()(app * n) {}
|
||||
void operator()(app * n) {}
|
||||
};
|
||||
|
||||
int ufbv_rewriter::is_subset(expr * e1, expr * e2) const {
|
||||
|
@ -132,10 +132,10 @@ int ufbv_rewriter::is_subset(expr * e1, expr * e2) const {
|
|||
for_each_expr(proc1, e1);
|
||||
var_set_proc proc2(ev2);
|
||||
for_each_expr(proc2, e2);
|
||||
|
||||
return (ev1==ev2 ) ? +2 : // We return +2 if the sets are equal.
|
||||
(ev1.subset_of(ev2)) ? +1 :
|
||||
(ev2.subset_of(ev1)) ? -1 :
|
||||
|
||||
return (ev1==ev2 ) ? +2 : // We return +2 if the sets are equal.
|
||||
(ev1.subset_of(ev2)) ? +1 :
|
||||
(ev2.subset_of(ev1)) ? -1 :
|
||||
0 ;
|
||||
}
|
||||
|
||||
|
@ -154,8 +154,8 @@ int ufbv_rewriter::is_smaller(expr * e1, expr * e2) const {
|
|||
else if (is_uninterp(e1) && !is_uninterp(e2))
|
||||
return -1;
|
||||
|
||||
// two uninterpreted functions are ordered first by the number of
|
||||
// arguments, then by their id.
|
||||
// two uninterpreted functions are ordered first by the number of
|
||||
// arguments, then by their id.
|
||||
if (is_uninterp(e1) && is_uninterp(e2)) {
|
||||
if (to_app(e1)->get_num_args() < to_app(e2)->get_num_args())
|
||||
return +1;
|
||||
|
@ -163,10 +163,10 @@ int ufbv_rewriter::is_smaller(expr * e1, expr * e2) const {
|
|||
return -1;
|
||||
else {
|
||||
unsigned a = to_app(e1)->get_decl()->get_id();
|
||||
unsigned b = to_app(e2)->get_decl()->get_id();
|
||||
if (a < b)
|
||||
unsigned b = to_app(e2)->get_decl()->get_id();
|
||||
if (a < b)
|
||||
return +1;
|
||||
else if (a > b)
|
||||
else if (a > b)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -185,8 +185,8 @@ int ufbv_rewriter::is_smaller(expr * e1, expr * e2) const {
|
|||
default: UNREACHABLE();
|
||||
}
|
||||
|
||||
return (sz1 == sz2) ? 0 :
|
||||
(sz1 < sz2) ? +1 :
|
||||
return (sz1 == sz2) ? 0 :
|
||||
(sz1 < sz2) ? +1 :
|
||||
-1 ;
|
||||
}
|
||||
|
||||
|
@ -194,9 +194,9 @@ class max_var_id_proc {
|
|||
unsigned m_max_var_id;
|
||||
public:
|
||||
max_var_id_proc(void):m_max_var_id(0) {}
|
||||
void operator()(var * n) {
|
||||
if(n->get_idx() > m_max_var_id)
|
||||
m_max_var_id = n->get_idx();
|
||||
void operator()(var * n) {
|
||||
if(n->get_idx() > m_max_var_id)
|
||||
m_max_var_id = n->get_idx();
|
||||
}
|
||||
void operator()(quantifier * n) {}
|
||||
void operator()(app * n) {}
|
||||
|
@ -206,7 +206,7 @@ public:
|
|||
unsigned ufbv_rewriter::max_var_id(expr * e)
|
||||
{
|
||||
max_var_id_proc proc;
|
||||
for_each_expr(proc, e);
|
||||
for_each_expr(proc, e);
|
||||
return proc.get_max();
|
||||
}
|
||||
|
||||
|
@ -219,14 +219,14 @@ void ufbv_rewriter::insert_fwd_idx(expr * large, expr * small, quantifier * demo
|
|||
func_decl * fd = to_app(large)->get_decl();
|
||||
|
||||
fwd_idx_map::iterator it = m_fwd_idx.find_iterator(fd);
|
||||
if (it == m_fwd_idx.end()) {
|
||||
quantifier_set * qs = alloc(quantifier_set, 1);
|
||||
if (it == m_fwd_idx.end()) {
|
||||
quantifier_set * qs = alloc(quantifier_set, 1);
|
||||
m_fwd_idx.insert(fd, qs);
|
||||
it = m_fwd_idx.find_iterator(fd);
|
||||
}
|
||||
|
||||
SASSERT(it->m_value);
|
||||
it->m_value->insert(demodulator);
|
||||
it->m_value->insert(demodulator);
|
||||
|
||||
m_manager.inc_ref(demodulator);
|
||||
m_manager.inc_ref(large);
|
||||
|
@ -238,13 +238,13 @@ void ufbv_rewriter::remove_fwd_idx(func_decl * f, quantifier * demodulator) {
|
|||
TRACE("demodulator_fwd", tout << "REMOVE: " << std::hex << (size_t)demodulator << std::endl; );
|
||||
|
||||
fwd_idx_map::iterator it = m_fwd_idx.find_iterator(f);
|
||||
if (it != m_fwd_idx.end()) {
|
||||
if (it != m_fwd_idx.end()) {
|
||||
demodulator2lhs_rhs::iterator fit = m_demodulator2lhs_rhs.find_iterator(demodulator);
|
||||
m_manager.dec_ref(fit->m_value.first);
|
||||
m_manager.dec_ref(fit->m_value.second);
|
||||
m_manager.dec_ref(demodulator);
|
||||
m_demodulator2lhs_rhs.erase(demodulator);
|
||||
it->m_value->erase(demodulator);
|
||||
it->m_value->erase(demodulator);
|
||||
} else {
|
||||
SASSERT(m_demodulator2lhs_rhs.contains(demodulator));
|
||||
}
|
||||
|
@ -281,13 +281,13 @@ void ufbv_rewriter::show_fwd_idx(std::ostream & out) {
|
|||
}
|
||||
}
|
||||
|
||||
bool ufbv_rewriter::rewrite1(func_decl * f, ptr_vector<expr> & m_new_args, expr_ref & np) {
|
||||
bool ufbv_rewriter::rewrite1(func_decl * f, ptr_vector<expr> & m_new_args, expr_ref & np) {
|
||||
fwd_idx_map::iterator it = m_fwd_idx.find_iterator(f);
|
||||
if (it != m_fwd_idx.end()) {
|
||||
TRACE("demodulator_bug", tout << "trying to rewrite: " << f->get_name() << " args:\n";
|
||||
for (unsigned i = 0; i < m_new_args.size(); i++) { tout << mk_pp(m_new_args[i], m_manager) << "\n"; });
|
||||
quantifier_set::iterator dit = it->m_value->begin();
|
||||
quantifier_set::iterator dend = it->m_value->end();
|
||||
quantifier_set::iterator dend = it->m_value->end();
|
||||
for ( ; dit != dend ; dit++ ) {
|
||||
quantifier * d = *dit;
|
||||
|
||||
|
@ -302,7 +302,7 @@ bool ufbv_rewriter::rewrite1(func_decl * f, ptr_vector<expr> & m_new_args, expr_
|
|||
TRACE("demodulator_bug", tout << "Matching with demodulator: " << mk_pp(d, m_manager) << std::endl; );
|
||||
|
||||
SASSERT(large->get_decl() == f);
|
||||
|
||||
|
||||
if (m_match_subst(large, l_s.second, m_new_args.c_ptr(), np)) {
|
||||
TRACE("demodulator_bug", tout << "succeeded...\n" << mk_pp(l_s.second, m_manager) << "\n===>\n" << mk_pp(np, m_manager) << "\n";);
|
||||
return true;
|
||||
|
@ -331,22 +331,22 @@ void ufbv_rewriter::rewrite_cache(expr * e, expr * new_e, bool done) {
|
|||
}
|
||||
|
||||
expr * ufbv_rewriter::rewrite(expr * n) {
|
||||
if (m_fwd_idx.empty())
|
||||
if (m_fwd_idx.empty())
|
||||
return n;
|
||||
|
||||
TRACE("demodulator", tout << "rewrite: " << mk_pp(n, m_manager) << std::endl; );
|
||||
app * a;
|
||||
|
||||
|
||||
SASSERT(m_rewrite_todo.empty());
|
||||
m_rewrite_cache.reset();
|
||||
|
||||
|
||||
m_rewrite_todo.push_back(n);
|
||||
while (!m_rewrite_todo.empty()) {
|
||||
TRACE("demodulator_stack", tout << "STACK: " << std::endl;
|
||||
for ( unsigned i = 0; i<m_rewrite_todo.size(); i++)
|
||||
for ( unsigned i = 0; i<m_rewrite_todo.size(); i++)
|
||||
tout << std::dec << i << ": " << std::hex << (size_t)m_rewrite_todo[i] << std::endl;
|
||||
);
|
||||
|
||||
);
|
||||
|
||||
expr * e = m_rewrite_todo.back();
|
||||
expr * actual = e;
|
||||
|
||||
|
@ -355,7 +355,7 @@ expr * ufbv_rewriter::rewrite(expr * n) {
|
|||
if (ebp.second) {
|
||||
m_rewrite_todo.pop_back();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
actual = ebp.first;
|
||||
}
|
||||
|
@ -366,8 +366,8 @@ expr * ufbv_rewriter::rewrite(expr * n) {
|
|||
rewrite_cache(e, actual, true);
|
||||
m_rewrite_todo.pop_back();
|
||||
break;
|
||||
case AST_APP:
|
||||
a = to_app(actual);
|
||||
case AST_APP:
|
||||
a = to_app(actual);
|
||||
if (rewrite_visit_children(a)) {
|
||||
func_decl * f = a->get_decl();
|
||||
m_new_args.reset();
|
||||
|
@ -389,12 +389,12 @@ expr * ufbv_rewriter::rewrite(expr * n) {
|
|||
// No pop.
|
||||
} else {
|
||||
if(all_untouched) {
|
||||
rewrite_cache(e, actual, true);
|
||||
}
|
||||
rewrite_cache(e, actual, true);
|
||||
}
|
||||
else {
|
||||
expr_ref na(m_manager);
|
||||
if (f->get_family_id() != m_manager.get_basic_family_id())
|
||||
na = m_manager.mk_app(f, m_new_args.size(), m_new_args.c_ptr());
|
||||
na = m_manager.mk_app(f, m_new_args.size(), m_new_args.c_ptr());
|
||||
else
|
||||
m_bsimp.reduce(f, m_new_args.size(), m_new_args.c_ptr(), na);
|
||||
TRACE("demodulator_bug", tout << "e:\n" << mk_pp(e, m_manager) << "\nnew_args: \n";
|
||||
|
@ -405,9 +405,9 @@ expr * ufbv_rewriter::rewrite(expr * n) {
|
|||
}
|
||||
m_rewrite_todo.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AST_QUANTIFIER: {
|
||||
case AST_QUANTIFIER: {
|
||||
expr * body = to_quantifier(actual)->get_expr();
|
||||
if (m_rewrite_cache.contains(body)) {
|
||||
const expr_bool_pair ebp = m_rewrite_cache.get(body);
|
||||
|
@ -417,13 +417,13 @@ expr * ufbv_rewriter::rewrite(expr * n) {
|
|||
q = m_manager.update_quantifier(to_quantifier(actual), new_body);
|
||||
m_new_exprs.push_back(q);
|
||||
expr_ref new_q(m_manager);
|
||||
elim_unused_vars(m_manager, q, new_q);
|
||||
elim_unused_vars(m_manager, q, params_ref(), new_q);
|
||||
m_new_exprs.push_back(new_q);
|
||||
rewrite_cache(e, new_q, true);
|
||||
rewrite_cache(e, new_q, true);
|
||||
m_rewrite_todo.pop_back();
|
||||
} else {
|
||||
m_rewrite_todo.push_back(body);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -437,7 +437,7 @@ expr * ufbv_rewriter::rewrite(expr * n) {
|
|||
expr * r = ebp.first;
|
||||
|
||||
TRACE("demodulator", tout << "rewrite result: " << mk_pp(r, m_manager) << std::endl; );
|
||||
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -448,7 +448,7 @@ public:
|
|||
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) {
|
||||
void operator()(app * n) {
|
||||
// We track only uninterpreted and constant functions.
|
||||
if (n->get_num_args()==0) return;
|
||||
SASSERT(m_expr && m_expr != (expr*) 0x00000003);
|
||||
|
@ -464,7 +464,7 @@ public:
|
|||
m_back_idx.insert(d, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class ufbv_rewriter::remove_back_idx_proc {
|
||||
|
@ -473,15 +473,15 @@ class ufbv_rewriter::remove_back_idx_proc {
|
|||
public:
|
||||
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) {
|
||||
void operator()(quantifier * n) {}
|
||||
void operator()(app * n) {
|
||||
// We track only uninterpreted and constant functions.
|
||||
if (n->get_num_args()==0) return;
|
||||
func_decl * d=n->get_decl();
|
||||
if (d->get_family_id() == null_family_id) {
|
||||
if (d->get_family_id() == null_family_id) {
|
||||
back_idx_map::iterator it = m_back_idx.find_iterator(d);
|
||||
if (it != m_back_idx.end()) {
|
||||
SASSERT(it->m_value);
|
||||
SASSERT(it->m_value);
|
||||
it->m_value->remove(m_expr);
|
||||
}
|
||||
}
|
||||
|
@ -489,12 +489,12 @@ public:
|
|||
};
|
||||
|
||||
void ufbv_rewriter::reschedule_processed(func_decl * f) {
|
||||
//use m_back_idx to find all formulas p in m_processed that contains f {
|
||||
//use m_back_idx to find all formulas p in m_processed that contains f {
|
||||
back_idx_map::iterator it = m_back_idx.find_iterator(f);
|
||||
if (it != m_back_idx.end()) {
|
||||
SASSERT(it->m_value);
|
||||
expr_set temp;
|
||||
|
||||
|
||||
expr_set::iterator sit = it->m_value->begin();
|
||||
expr_set::iterator send = it->m_value->end();
|
||||
for ( ; sit != send ; sit++ ) {
|
||||
|
@ -502,7 +502,7 @@ void ufbv_rewriter::reschedule_processed(func_decl * f) {
|
|||
if (m_processed.contains(p))
|
||||
temp.insert(p);
|
||||
}
|
||||
|
||||
|
||||
sit = temp.begin();
|
||||
send = temp.end();
|
||||
for ( ; sit != send; sit++) {
|
||||
|
@ -511,7 +511,7 @@ void ufbv_rewriter::reschedule_processed(func_decl * f) {
|
|||
m_processed.remove(p);
|
||||
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
|
||||
// insert p into m_todo
|
||||
m_todo.push_back(p);
|
||||
}
|
||||
}
|
||||
|
@ -529,40 +529,40 @@ bool ufbv_rewriter::can_rewrite(expr * n, expr * lhs) {
|
|||
|
||||
while (!stack.empty()) {
|
||||
curr = stack.back();
|
||||
|
||||
|
||||
if (visited.is_marked(curr)) {
|
||||
stack.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(curr->get_kind()) {
|
||||
case AST_VAR:
|
||||
case AST_VAR:
|
||||
visited.mark(curr, true);
|
||||
stack.pop_back();
|
||||
break;
|
||||
|
||||
case AST_APP:
|
||||
if (for_each_expr_args(stack, visited, to_app(curr)->get_num_args(), to_app(curr)->get_args())) {
|
||||
if (for_each_expr_args(stack, visited, to_app(curr)->get_num_args(), to_app(curr)->get_args())) {
|
||||
if (m_match_subst(lhs, curr))
|
||||
return true;
|
||||
visited.mark(curr, true);
|
||||
stack.pop_back();
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case AST_QUANTIFIER:
|
||||
if (!for_each_expr_args(stack, visited, to_quantifier(curr)->get_num_patterns(),
|
||||
if (!for_each_expr_args(stack, visited, to_quantifier(curr)->get_num_patterns(),
|
||||
to_quantifier(curr)->get_patterns())) {
|
||||
break;
|
||||
}
|
||||
if (!for_each_expr_args(stack, visited, to_quantifier(curr)->get_num_no_patterns(),
|
||||
if (!for_each_expr_args(stack, visited, to_quantifier(curr)->get_num_no_patterns(),
|
||||
to_quantifier(curr)->get_no_patterns())) {
|
||||
break;
|
||||
}
|
||||
if (!visited.is_marked(to_quantifier(curr)->get_expr())) {
|
||||
stack.push_back(to_quantifier(curr)->get_expr());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
stack.pop_back();
|
||||
break;
|
||||
|
@ -597,7 +597,7 @@ void ufbv_rewriter::reschedule_demodulators(func_decl * f, expr * lhs) {
|
|||
expr * occ = *esit;
|
||||
|
||||
if (!is_quantifier(occ))
|
||||
continue;
|
||||
continue;
|
||||
|
||||
// Use the fwd idx to find out whether this is a demodulator.
|
||||
demodulator2lhs_rhs::iterator d2lr_it = m_demodulator2lhs_rhs.find_iterator(to_quantifier(occ));
|
||||
|
@ -605,22 +605,22 @@ void ufbv_rewriter::reschedule_demodulators(func_decl * f, expr * lhs) {
|
|||
l = d2lr_it->m_value.first;
|
||||
quantifier_ref d(m_manager);
|
||||
func_decl_ref df(m_manager);
|
||||
d = to_quantifier(occ);
|
||||
d = to_quantifier(occ);
|
||||
df = to_app(l)->get_decl();
|
||||
|
||||
// Now we know there is an occurrence of f in d
|
||||
// if n' can rewrite d {
|
||||
// if n' can rewrite d {
|
||||
if (can_rewrite(d, lhs)) {
|
||||
TRACE("demodulator", tout << "Rescheduling: " << std::endl << mk_pp(d, m_manager) << std::endl; );
|
||||
// remove d from m_fwd_idx
|
||||
remove_fwd_idx(df, d);
|
||||
// remove d from m_back_idx
|
||||
// remove d from m_back_idx
|
||||
// just remember it here, because otherwise it and/or esit might become invalid?
|
||||
// to_remove.insert(d);
|
||||
// to_remove.insert(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);
|
||||
m_todo.push_back(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -629,10 +629,10 @@ void ufbv_rewriter::reschedule_demodulators(func_decl * f, expr * lhs) {
|
|||
//for (ptr_vector<expr>::iterator it = to_remove.begin(); it != to_remove.end(); it++) {
|
||||
// expr * d = *it;
|
||||
// remove_back_idx_proc proc(m_manager, m_back_idx, d);
|
||||
// for_each_expr(proc, d);
|
||||
// for_each_expr(proc, d);
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
void ufbv_rewriter::operator()(unsigned n, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs) {
|
||||
if (m_manager.proofs_enabled()) {
|
||||
// Let us not waste time with proof production
|
||||
|
@ -655,7 +655,7 @@ void ufbv_rewriter::operator()(unsigned n, expr * const * exprs, proof * const *
|
|||
|
||||
m_match_subst.reserve(max_vid);
|
||||
|
||||
while (!m_todo.empty()) {
|
||||
while (!m_todo.empty()) {
|
||||
// let n be the next formula in m_todo.
|
||||
expr_ref cur(m_manager);
|
||||
cur = m_todo.back();
|
||||
|
@ -670,21 +670,21 @@ void ufbv_rewriter::operator()(unsigned n, expr * const * exprs, proof * const *
|
|||
expr_ref large(m_manager), small(m_manager);
|
||||
if (!is_demodulator(np, large, small)) {
|
||||
// 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)
|
||||
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_back_idx, np);
|
||||
for_each_expr(proc, np);
|
||||
} else {
|
||||
} else {
|
||||
// np is a demodulator that allows us to replace 'large' with 'small'.
|
||||
TRACE("demodulator", tout << "Found demodulator: " << std::endl;
|
||||
tout << mk_pp(large.get(), m_manager) << std::endl << " ---> " <<
|
||||
tout << mk_pp(large.get(), m_manager) << std::endl << " ---> " <<
|
||||
std::endl << mk_pp(small.get(), m_manager) << std::endl; );
|
||||
|
||||
TRACE("demodulator_s", tout << "Found demodulator: " << std::endl;
|
||||
tout << to_app(large)->get_decl()->get_name() <<
|
||||
tout << to_app(large)->get_decl()->get_name() <<
|
||||
"[" << to_app(large)->get_depth() << "]" << " ---> ";
|
||||
if (is_app(small))
|
||||
tout << to_app(small)->get_decl()->get_name() <<
|
||||
tout << to_app(small)->get_decl()->get_name() <<
|
||||
"[" << to_app(small)->get_depth() << "]" << std::endl;
|
||||
else
|
||||
tout << mk_pp(small.get(), m_manager) << std::endl; );
|
||||
|
@ -695,14 +695,14 @@ void ufbv_rewriter::operator()(unsigned n, expr * const * exprs, proof * const *
|
|||
|
||||
reschedule_processed(f);
|
||||
reschedule_demodulators(f, large);
|
||||
|
||||
|
||||
// insert n' into m_fwd_idx
|
||||
insert_fwd_idx(large, small, to_quantifier(np));
|
||||
|
||||
// update m_back_idx
|
||||
add_back_idx_proc proc(m_back_idx, np);
|
||||
for_each_expr(proc, np);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the result is the contents of m_processed + all demodulators in m_fwd_idx.
|
||||
|
@ -743,10 +743,10 @@ ufbv_rewriter::match_subst::match_subst(ast_manager & m):
|
|||
*/
|
||||
struct match_args_aux_proc {
|
||||
substitution & m_subst;
|
||||
struct no_match {};
|
||||
|
||||
struct no_match {};
|
||||
|
||||
match_args_aux_proc(substitution & s):m_subst(s) {}
|
||||
|
||||
|
||||
void operator()(var * n) {
|
||||
expr_offset r;
|
||||
if (m_subst.find(n, 0, r)) {
|
||||
|
@ -766,7 +766,7 @@ struct match_args_aux_proc {
|
|||
bool ufbv_rewriter::match_subst::match_args(app * lhs, expr * const * args) {
|
||||
m_cache.reset();
|
||||
m_todo.reset();
|
||||
|
||||
|
||||
// fill todo-list, and perform quick success/failure tests
|
||||
m_all_args_eq = true;
|
||||
unsigned num_args = lhs->get_num_args();
|
||||
|
@ -777,21 +777,21 @@ bool ufbv_rewriter::match_subst::match_args(app * lhs, expr * const * args) {
|
|||
m_all_args_eq = false;
|
||||
if (is_app(t_arg) && is_app(i_arg) && to_app(t_arg)->get_decl() != to_app(i_arg)->get_decl()) {
|
||||
// quick failure...
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
m_todo.push_back(expr_pair(t_arg, i_arg));
|
||||
}
|
||||
|
||||
if (m_all_args_eq) {
|
||||
|
||||
if (m_all_args_eq) {
|
||||
// quick success worked...
|
||||
return true;
|
||||
}
|
||||
|
||||
m_subst.reset();
|
||||
|
||||
|
||||
while (!m_todo.empty()) {
|
||||
expr_pair const & p = m_todo.back();
|
||||
|
||||
|
||||
if (is_var(p.first)) {
|
||||
expr_offset r;
|
||||
if (m_subst.find(to_var(p.first), 0, r)) {
|
||||
|
@ -814,7 +814,7 @@ bool ufbv_rewriter::match_subst::match_args(app * lhs, expr * const * args) {
|
|||
|
||||
SASSERT(is_app(p.first) && is_app(p.second));
|
||||
|
||||
if (to_app(p.first)->is_ground() && !to_app(p.second)->is_ground())
|
||||
if (to_app(p.first)->is_ground() && !to_app(p.second)->is_ground())
|
||||
return false;
|
||||
|
||||
if (p.first == p.second && to_app(p.first)->is_ground()) {
|
||||
|
@ -827,7 +827,7 @@ bool ufbv_rewriter::match_subst::match_args(app * lhs, expr * const * args) {
|
|||
m_todo.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (p.first == p.second) {
|
||||
// p.first and p.second is not ground...
|
||||
|
||||
|
@ -855,10 +855,10 @@ bool ufbv_rewriter::match_subst::match_args(app * lhs, expr * const * args) {
|
|||
|
||||
app * n1 = to_app(p.first);
|
||||
app * n2 = to_app(p.second);
|
||||
|
||||
|
||||
if (n1->get_decl() != n2->get_decl())
|
||||
return false;
|
||||
|
||||
|
||||
unsigned num_args1 = n1->get_num_args();
|
||||
if (num_args1 != n2->get_num_args())
|
||||
return false;
|
||||
|
@ -867,7 +867,7 @@ bool ufbv_rewriter::match_subst::match_args(app * lhs, expr * const * args) {
|
|||
|
||||
if (num_args1 == 0)
|
||||
continue;
|
||||
|
||||
|
||||
m_cache.insert(p);
|
||||
unsigned j = num_args1;
|
||||
while (j > 0) {
|
||||
|
@ -886,7 +886,7 @@ bool ufbv_rewriter::match_subst::operator()(app * lhs, expr * rhs, expr * const
|
|||
new_rhs = rhs;
|
||||
return true;
|
||||
}
|
||||
unsigned deltas[2] = { 0, 0 };
|
||||
unsigned deltas[2] = { 0, 0 };
|
||||
m_subst.apply(2, deltas, expr_offset(rhs, 0), new_rhs);
|
||||
return true;
|
||||
}
|
||||
|
|
218
src/test/cnf_backbones.cpp
Normal file
218
src/test/cnf_backbones.cpp
Normal file
|
@ -0,0 +1,218 @@
|
|||
/*++
|
||||
Copyright (c) 2017 Microsoft Corporation
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include<time.h>
|
||||
#include<signal.h>
|
||||
#include"timeout.h"
|
||||
#include"rlimit.h"
|
||||
#include"dimacs.h"
|
||||
#include"sat_solver.h"
|
||||
#include"gparams.h"
|
||||
|
||||
static sat::solver * g_solver = 0;
|
||||
static clock_t g_start_time;
|
||||
|
||||
static void display_statistics() {
|
||||
clock_t end_time = clock();
|
||||
if (g_solver) {
|
||||
std::cout.flush();
|
||||
std::cerr.flush();
|
||||
|
||||
statistics st;
|
||||
g_solver->collect_statistics(st);
|
||||
st.update("total time", ((static_cast<double>(end_time) - static_cast<double>(g_start_time)) / CLOCKS_PER_SEC));
|
||||
st.display_smt2(std::cout);
|
||||
}
|
||||
}
|
||||
|
||||
static void on_timeout() {
|
||||
display_statistics();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void STD_CALL on_ctrl_c(int) {
|
||||
signal (SIGINT, SIG_DFL);
|
||||
display_statistics();
|
||||
raise(SIGINT);
|
||||
}
|
||||
|
||||
static void display_model(sat::solver const & s) {
|
||||
sat::model const & m = s.get_model();
|
||||
for (unsigned i = 1; i < m.size(); i++) {
|
||||
switch (m[i]) {
|
||||
case l_false: std::cout << "-" << i << " "; break;
|
||||
case l_undef: break;
|
||||
case l_true: std::cout << i << " "; break;
|
||||
}
|
||||
}
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
static void display_status(lbool r) {
|
||||
switch (r) {
|
||||
case l_true:
|
||||
std::cout << "sat\n";
|
||||
break;
|
||||
case l_undef:
|
||||
std::cout << "unknown\n";
|
||||
break;
|
||||
case l_false:
|
||||
std::cout << "unsat\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void prune_unfixed(sat::literal_vector& lambda, sat::model const& m) {
|
||||
for (unsigned i = 0; i < lambda.size(); ++i) {
|
||||
if ((m[lambda[i].var()] == l_false) != lambda[i].sign()) {
|
||||
lambda[i] = lambda.back();
|
||||
lambda.pop_back();
|
||||
--i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Algorithm 7: Corebased Algorithm with Chunking
|
||||
|
||||
static void back_remove(sat::literal_vector& lits, sat::literal l) {
|
||||
for (unsigned i = lits.size(); i > 0; ) {
|
||||
--i;
|
||||
if (lits[i] == l) {
|
||||
lits[i] = lits.back();
|
||||
lits.pop_back();
|
||||
return;
|
||||
}
|
||||
}
|
||||
std::cout << "UNREACHABLE\n";
|
||||
}
|
||||
|
||||
static void brute_force_consequences(sat::solver& s, sat::literal_vector const& gamma, sat::literal_vector& backbones) {
|
||||
for (unsigned i = 0; i < gamma.size(); ++i) {
|
||||
sat::literal nlit = ~gamma[i];
|
||||
lbool r = s.check(1, &nlit);
|
||||
if (r == l_false) {
|
||||
backbones.push_back(gamma[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static lbool core_chunking(sat::solver& s, sat::bool_var_vector& vars, vector<sat::literal_vector>& conseq, unsigned K) {
|
||||
lbool r = s.check();
|
||||
display_status(r);
|
||||
if (r != l_true) {
|
||||
return r;
|
||||
}
|
||||
sat::model const & m = s.get_model();
|
||||
sat::literal_vector lambda, backbones;
|
||||
for (unsigned i = 1; i < m.size(); i++) {
|
||||
lambda.push_back(sat::literal(i, m[i] == l_false));
|
||||
}
|
||||
while (!lambda.empty()) {
|
||||
IF_VERBOSE(1, verbose_stream() << "(sat-backbone-core " << lambda.size() << " " << backbones.size() << ")\n";);
|
||||
unsigned k = std::min(K, lambda.size());
|
||||
sat::literal_vector gamma, omegaN;
|
||||
for (unsigned i = 0; i < k; ++i) {
|
||||
sat::literal l = lambda[lambda.size() - i - 1];
|
||||
gamma.push_back(l);
|
||||
omegaN.push_back(~l);
|
||||
}
|
||||
while (true) {
|
||||
r = s.check(omegaN.size(), omegaN.c_ptr());
|
||||
if (r == l_true) {
|
||||
IF_VERBOSE(1, verbose_stream() << "(sat) " << omegaN << "\n";);
|
||||
prune_unfixed(lambda, s.get_model());
|
||||
break;
|
||||
}
|
||||
sat::literal_vector const& core = s.get_core();
|
||||
sat::literal_vector occurs;
|
||||
IF_VERBOSE(1, verbose_stream() << "(core " << core.size() << ")\n";);
|
||||
for (unsigned i = 0; i < omegaN.size(); ++i) {
|
||||
if (core.contains(omegaN[i])) {
|
||||
occurs.push_back(omegaN[i]);
|
||||
}
|
||||
}
|
||||
if (occurs.size() == 1) {
|
||||
sat::literal lit = occurs.back();
|
||||
sat::literal nlit = ~lit;
|
||||
backbones.push_back(~lit);
|
||||
back_remove(lambda, ~lit);
|
||||
back_remove(gamma, ~lit);
|
||||
s.mk_clause(1, &nlit);
|
||||
}
|
||||
for (unsigned i = 0; i < omegaN.size(); ++i) {
|
||||
if (occurs.contains(omegaN[i])) {
|
||||
omegaN[i] = omegaN.back();
|
||||
omegaN.pop_back();
|
||||
--i;
|
||||
}
|
||||
}
|
||||
if (omegaN.empty() && occurs.size() > 1) {
|
||||
brute_force_consequences(s, gamma, backbones);
|
||||
for (unsigned i = 0; i < gamma.size(); ++i) {
|
||||
back_remove(lambda, gamma[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i < backbones.size(); ++i) {
|
||||
sat::literal_vector cons;
|
||||
cons.push_back(backbones[i]);
|
||||
conseq.push_back(cons);
|
||||
}
|
||||
return l_true;
|
||||
}
|
||||
|
||||
|
||||
static void cnf_backbones(bool use_chunk, char const* file_name) {
|
||||
g_start_time = clock();
|
||||
register_on_timeout_proc(on_timeout);
|
||||
signal(SIGINT, on_ctrl_c);
|
||||
params_ref p = gparams::get_module("sat");
|
||||
p.set_bool("produce_models", true);
|
||||
reslimit limit;
|
||||
sat::solver solver(p, limit, 0);
|
||||
g_solver = &solver;
|
||||
|
||||
if (file_name) {
|
||||
std::ifstream in(file_name);
|
||||
if (in.bad() || in.fail()) {
|
||||
std::cerr << "(error \"failed to open file '" << file_name << "'\")" << std::endl;
|
||||
exit(ERR_OPEN_FILE);
|
||||
}
|
||||
parse_dimacs(in, solver);
|
||||
}
|
||||
else {
|
||||
parse_dimacs(std::cin, solver);
|
||||
}
|
||||
IF_VERBOSE(20, solver.display_status(verbose_stream()););
|
||||
|
||||
vector<sat::literal_vector> conseq;
|
||||
sat::bool_var_vector vars;
|
||||
sat::literal_vector assumptions;
|
||||
for (unsigned i = 1; i < solver.num_vars(); ++i) {
|
||||
vars.push_back(i);
|
||||
solver.set_external(i);
|
||||
}
|
||||
lbool r;
|
||||
if (use_chunk) {
|
||||
r = core_chunking(solver, vars, conseq, 100);
|
||||
}
|
||||
else {
|
||||
r = solver.get_consequences(assumptions, vars, conseq);
|
||||
}
|
||||
std::cout << vars.size() << " " << conseq.size() << "\n";
|
||||
display_status(r);
|
||||
display_statistics();
|
||||
}
|
||||
|
||||
void tst_cnf_backbones(char ** argv, int argc, int& i) {
|
||||
if (i + 1 < argc) {
|
||||
bool use_chunk = (i + 2 < argc && argv[i + 2] == std::string("chunk"));
|
||||
cnf_backbones(use_chunk, argv[i + 1]);
|
||||
++i;
|
||||
if (use_chunk) ++i;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/*++
|
||||
Copyright (c) 2015 Microsoft Corporation
|
||||
|
||||
|
|
|
@ -243,8 +243,12 @@ int main(int argc, char ** argv) {
|
|||
TST(model_evaluator);
|
||||
TST(get_consequences);
|
||||
TST(pb2bv);
|
||||
<<<<<<< HEAD
|
||||
TST_ARGV(sat_lookahead);
|
||||
TST_ARGV(sat_local_search);
|
||||
=======
|
||||
TST_ARGV(cnf_backbones);
|
||||
>>>>>>> 69aa5ca877f5de0a2c00515d0fe86a797b95701a
|
||||
//TST_ARGV(hs);
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,9 @@ Revision History:
|
|||
|
||||
#ifdef USE_INTRINSICS
|
||||
#include <emmintrin.h>
|
||||
#if defined(_MSC_VER) || defined(__SSE4_1__)
|
||||
#include <smmintrin.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
hwf_manager::hwf_manager() :
|
||||
|
@ -303,7 +306,9 @@ void hwf_manager::round_to_integral(mpf_rounding_mode rm, hwf const & x, hwf & o
|
|||
// According to the Intel Architecture manual, the x87-instrunction FRNDINT is the
|
||||
// same in 32-bit and 64-bit mode. The _mm_round_* intrinsics are SSE4 extensions.
|
||||
#ifdef _WINDOWS
|
||||
#ifdef USE_INTRINSICS
|
||||
#if defined(USE_INTRINSICS) && \
|
||||
(defined(_WINDOWS) && (defined(__AVX__) || defined(_M_X64))) || \
|
||||
(!defined(_WINDOWS) && defined(__SSE4_1__))
|
||||
switch (rm) {
|
||||
case 0: _mm_store_sd(&o.value, _mm_round_pd(_mm_set_sd(x.value), _MM_FROUND_TO_NEAREST_INT)); break;
|
||||
case 2: _mm_store_sd(&o.value, _mm_round_pd(_mm_set_sd(x.value), _MM_FROUND_TO_POS_INF)); break;
|
||||
|
|
|
@ -88,9 +88,6 @@ public:
|
|||
bool is_pzero(hwf const & x);
|
||||
|
||||
bool is_one(hwf const & x);
|
||||
|
||||
// structural eq
|
||||
bool eq_core(hwf const & x, hwf const & y);
|
||||
|
||||
bool eq(hwf const & x, hwf const & y);
|
||||
bool lt(hwf const & x, hwf const & y);
|
||||
|
|
|
@ -70,6 +70,7 @@ void small_object_allocator::reset() {
|
|||
|
||||
void small_object_allocator::deallocate(size_t size, void * p) {
|
||||
if (size == 0) return;
|
||||
|
||||
#if defined(Z3DEBUG) && !defined(_WINDOWS)
|
||||
// Valgrind friendly
|
||||
memory::deallocate(p);
|
||||
|
@ -93,6 +94,7 @@ void small_object_allocator::deallocate(size_t size, void * p) {
|
|||
|
||||
void * small_object_allocator::allocate(size_t size) {
|
||||
if (size == 0) return 0;
|
||||
|
||||
#if defined(Z3DEBUG) && !defined(_WINDOWS)
|
||||
// Valgrind friendly
|
||||
return memory::allocate(size);
|
||||
|
|
8
src/util/version.h.cmake.in
Normal file
8
src/util/version.h.cmake.in
Normal file
|
@ -0,0 +1,8 @@
|
|||
// automatically generated file.
|
||||
#define Z3_MAJOR_VERSION @Z3_VERSION_MAJOR@
|
||||
#define Z3_MINOR_VERSION @Z3_VERSION_MINOR@
|
||||
#define Z3_BUILD_NUMBER @Z3_VERSION_PATCH@
|
||||
#define Z3_REVISION_NUMBER @Z3_VERSION_TWEAK@
|
||||
|
||||
#define Z3_FULL_VERSION @Z3_FULL_VERSION@
|
||||
#cmakedefine Z3GITHASH @Z3GITHASH@
|
Loading…
Add table
Add a link
Reference in a new issue