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

Merge branch 'unstable' of https://git01.codeplex.com/z3 into unstable

This commit is contained in:
Nikolaj Bjorner 2012-10-29 08:07:40 -07:00
commit 99e94e3263
131 changed files with 1027 additions and 6914 deletions

View file

@ -23,7 +23,6 @@ Revision History:
#include"cmd_context.h"
#include"smt2parser.h"
#include"smtparser.h"
#include"z3_solver.h"
extern "C" {
@ -248,40 +247,6 @@ extern "C" {
return mk_c(c)->m_smtlib_error_buffer.c_str();
Z3_CATCH_RETURN("");
}
Z3_ast parse_z3_stream(Z3_context c, std::istream& is) {
z3_solver parser(c, is, verbose_stream(), mk_c(c)->fparams(), false);
if (!parser.parse()) {
SET_ERROR_CODE(Z3_PARSER_ERROR);
return of_ast(mk_c(c)->m().mk_true());
}
expr_ref_vector assumptions(mk_c(c)->m());
parser.get_assumptions(assumptions);
return of_ast(mk_c(c)->mk_and(assumptions.size(), assumptions.c_ptr()));
}
Z3_ast Z3_API Z3_parse_z3_string(Z3_context c, Z3_string str) {
Z3_TRY;
LOG_Z3_parse_z3_string(c, str);
std::string s(str);
std::istringstream is(s);
Z3_ast r = parse_z3_stream(c, is);
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_parse_z3_file(Z3_context c, Z3_string file_name) {
Z3_TRY;
LOG_Z3_parse_z3_file(c, file_name);
std::ifstream is(file_name);
if (!is) {
SET_ERROR_CODE(Z3_PARSER_ERROR);
return 0;
}
Z3_ast r = parse_z3_stream(c, is);
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
// ---------------
// Support for SMTLIB2

View file

@ -4977,23 +4977,6 @@ BEGIN_MLAPI_EXCLUDE
Z3_string Z3_API Z3_get_smtlib_error(__in Z3_context c);
END_MLAPI_EXCLUDE
/**
\brief \mlh parse_z3_string c str \endmlh
Parse the given string using the Z3 native parser.
Return the conjunction of asserts made in the input.
def_API('Z3_parse_z3_string', AST, (_in(CONTEXT), _in(STRING)))
*/
Z3_ast Z3_API Z3_parse_z3_string(__in Z3_context c, __in Z3_string str);
/**
\brief Similar to #Z3_parse_z3_string, but reads the benchmark from a file.
def_API('Z3_parse_z3_file', AST, (_in(CONTEXT), _in(STRING)))
*/
Z3_ast Z3_API Z3_parse_z3_file(__in Z3_context c, __in Z3_string file_name);
/*@}*/
#ifdef CorML4

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1410,6 +1410,51 @@ br_status bv_rewriter::mk_bv_xor(unsigned num, expr * const * args, expr_ref & r
}
}
}
// XOR is a mask
// All arguments but one is a numeral.
//
// Apply a transformation of the form:
//
// (bvxor a 0011) --> (concat ((_ extract 3 2) a) ((_ extract 1 0) (bvnot a)))
//
if (!v1.is_zero() && num_coeffs == num - 1) {
// find argument that is not a numeral
expr * t = 0;
for (unsigned i = 0; i < num; i++) {
t = args[i];
if (!is_numeral(t))
break;
}
SASSERT(t != 0);
numeral two(2);
expr_ref_buffer exs(m());
expr_ref not_t(m());
not_t = m_util.mk_bv_not(t);
unsigned low = 0;
unsigned i = 0;
while (i < sz) {
while (i < sz && mod(v1, two).is_one()) {
i++;
div(v1, two, v1);
}
if (i != low) {
exs.push_back(m_mk_extract(i-1, low, not_t));
low = i;
}
while (i < sz && mod(v1, two).is_zero()) {
i++;
div(v1, two, v1);
}
if (i != low) {
exs.push_back(m_mk_extract(i-1, low, t));
low = i;
}
}
std::reverse(exs.c_ptr(), exs.c_ptr() + exs.size());
result = m_util.mk_concat(exs.size(), exs.c_ptr());
return BR_REWRITE3;
}
if (!merged && !flattened && (num_coeffs == 0 || (num_coeffs == 1 && !v1.is_zero() && v1 != (m_util.power_of_two(sz) - numeral(1)))))
return BR_FAILED;

1343
src/bindings/c++/z3++.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -2853,30 +2853,6 @@ namespace Microsoft.Z3
}
#endregion
#region Native Parser
/// <summary>
/// Parse the given string using the Z3 native parser.
/// </summary>
/// <returns>A conjunction of asserts made in <paramref name="str"/>.</returns>
public Expr ParseZ3String(string str)
{
Contract.Ensures(Contract.Result<Expr>() != null);
return Expr.Create(this, Native.Z3_parse_z3_string(nCtx, str));
}
/// <summary>
/// Parse the given file using the Z3 native parser.
/// </summary>
/// <returns>A conjunction of asserts made in the file.</returns>
public Expr ParseZ3File(string fileName)
{
Contract.Ensures(Contract.Result<Expr>() != null);
return Expr.Create(this, Native.Z3_parse_z3_file(nCtx, fileName));
}
#endregion
#region Goals
/// <summary>
/// Creates a new Goal.

View file

@ -1,8 +0,0 @@
from z3 import *
x = Real('x')
y = Real('y')
s = Solver()
s.add(x + y > 5, x > 1, y > 1)
print s.check()
print s.model()

View file

@ -24,7 +24,7 @@ Small example:
>>> s.check()
sat
>>> s.model()
[x = 1, y = 2]
[y = 2, x = 1]
Z3 exceptions:
@ -1698,9 +1698,9 @@ def Exists(vs, body, weight=1, qid="", skid="", patterns=[], no_patterns=[]):
>>> q
Exists([x, y], f(x, y) >= x)
>>> Tactic('nnf')(q)
[[f(x!foo!2, y!foo!1) >= x!foo!2]]
[[f(x!foo!1, y!foo!0) >= x!foo!1]]
>>> Tactic('nnf')(q).as_expr()
f(x!foo!4, y!foo!3) >= x!foo!4
f(x!foo!3, y!foo!2) >= x!foo!3
"""
return _mk_quantifier(False, vs, body, weight, qid, skid, patterns, no_patterns)
@ -6908,7 +6908,7 @@ def solve(*args, **keywords):
>>> a, b = Ints('a b')
>>> solve(a + b == 3, Or(a == 0, a == 1), a != 0)
[a = 1, b = 2]
[b = 2, a = 1]
"""
s = Solver()
s.set(**keywords)

View file

@ -45,6 +45,7 @@ Revision History:
#include "cooperate.h"
#include "tactical.h"
#include "model_v2_pp.h"
#include "obj_hashtable.h"
namespace qe {
@ -723,6 +724,85 @@ namespace qe {
}
};
// ----------------------------
// def_vector
void def_vector::normalize() {
// apply nested definitions into place.
ast_manager& m = m_vars.get_manager();
expr_substitution sub(m);
scoped_ptr<expr_replacer> rep = mk_expr_simp_replacer(m);
if (size() <= 1) {
return;
}
for (unsigned i = size(); i > 0; ) {
--i;
expr_ref e(m);
e = def(i);
rep->set_substitution(&sub);
(*rep)(e);
sub.insert(m.mk_const(var(i)), e);
def_ref(i) = e;
}
}
void def_vector::project(unsigned num_vars, app* const* vars) {
obj_hashtable<func_decl> fns;
for (unsigned i = 0; i < num_vars; ++i) {
fns.insert(vars[i]->get_decl());
}
for (unsigned i = 0; i < size(); ++i) {
if (fns.contains(m_vars[i].get())) {
//
// retain only first occurrence of eliminated variable.
// later occurrences are just recycling the name.
//
fns.remove(m_vars[i].get());
}
else {
for (unsigned j = i+1; j < size(); ++j) {
m_vars.set(j-1, m_vars.get(j));
m_defs.set(j-1, m_defs.get(j));
}
m_vars.pop_back();
m_defs.pop_back();
--i;
}
}
}
// ----------------------------
// guarded_defs
std::ostream& guarded_defs::display(std::ostream& out) const {
ast_manager& m = m_guards.get_manager();
for (unsigned i = 0; i < size(); ++i) {
for (unsigned j = 0; j < defs(i).size(); ++j) {
out << defs(i).var(j)->get_name() << " := " << mk_pp(defs(i).def(j), m) << "\n";
}
out << "if " << mk_pp(guard(i), m) << "\n";
}
return out;
}
bool guarded_defs::inv() {
return m_defs.size() == m_guards.size();
}
void guarded_defs::add(expr* guard, def_vector const& defs) {
SASSERT(inv());
m_defs.push_back(defs);
m_guards.push_back(guard);
m_defs.back().normalize();
SASSERT(inv());
}
void guarded_defs::project(unsigned num_vars, app* const* vars) {
for (unsigned i = 0; i < size(); ++i) {
m_defs[i].project(num_vars, vars);
}
}
// ----------------------------
// Obtain atoms in NNF formula.
@ -810,7 +890,7 @@ namespace qe {
virtual lbool eliminate_exists(
unsigned num_vars, app* const* vars,
expr_ref& fml, app_ref_vector& free_vars, bool get_first, def_vector* defs) = 0;
expr_ref& fml, app_ref_vector& free_vars, bool get_first, guarded_defs* defs) = 0;
virtual void set_assumption(expr* fml) = 0;
@ -918,40 +998,25 @@ namespace qe {
}
}
bool get_leaf_rec(expr_ref& fml, def_vector& defs) {
void get_leaves_rec(def_vector& defs, guarded_defs& gdefs) {
expr* f = this->fml();
unsigned sz = defs.size();
defs.append(def());
if (m_children.empty() && f && !m.is_false(f) &&
m_vars.empty() && !has_var()) {
fml = f;
return true;
gdefs.add(f, defs);
}
unsigned sz = defs.size();
for (unsigned i = 0; i < m_children.size(); ++i) {
search_tree* st = m_children[i];
defs.append(st->def());
if (st->get_leaf_rec(fml, defs)) {
return true;
else {
for (unsigned i = 0; i < m_children.size(); ++i) {
m_children[i]->get_leaves_rec(defs, gdefs);
}
defs.shrink(sz);
}
return false;
defs.shrink(sz);
}
void get_leaf(expr_ref& fml, def_vector& defs) {
get_leaf_rec(fml, defs);
// apply nested definitions into place.
expr_substitution sub(m);
scoped_ptr<expr_replacer> rep = mk_expr_simp_replacer(m);
for (unsigned i = defs.size(); i > 0; ) {
--i;
expr_ref e(m);
e = defs.def(i);
rep->set_substitution(&sub);
(*rep)(e);
sub.insert(m.mk_const(defs.var(i)), e);
defs.def_ref(i) = e;
}
void get_leaves(guarded_defs& gdefs) {
def_vector defs(m);
get_leaves_rec(defs, gdefs);
}
void reset() {
@ -1248,7 +1313,7 @@ namespace qe {
app_ref_vector m_new_vars; // variables added by solvers
bool m_get_first; // get first satisfying branch.
def_vector* m_defs;
guarded_defs* m_defs;
nnf_normalizer m_nnf; // nnf conversion
@ -1311,7 +1376,7 @@ namespace qe {
void check(unsigned num_vars, app* const* vars,
expr* assumption, expr_ref& fml, bool get_first,
app_ref_vector& free_vars, def_vector* defs) {
app_ref_vector& free_vars, guarded_defs* defs) {
reset();
m_solver.push();
@ -1366,9 +1431,11 @@ namespace qe {
expr_ref_vector result(m);
m_root.get_leaves(result);
m_bool_rewriter.mk_or(result.size(), result.c_ptr(), fml);
}
else if (defs) {
m_root.get_leaf(fml, *defs);
}
if (defs) {
m_root.get_leaves(*defs);
defs->project(num_vars, vars);
}
TRACE("qe",
@ -1401,7 +1468,7 @@ namespace qe {
private:
void final_check(model_evaluator& model_eval) {
TRACE("qe", tout << (m_fml?"fml":"null") << "\n";);
TRACE("qe", tout << "\n";);
while (can_propagate_assignment(model_eval)) {
propagate_assignment(model_eval);
}
@ -1480,7 +1547,7 @@ namespace qe {
m_qe.eliminate_exists(1, &var, fml, m_free_vars, false, 0);
}
lbool eliminate_exists(unsigned num_vars, app* const* vars, expr_ref& fml, bool get_first, def_vector* defs) {
lbool eliminate_exists(unsigned num_vars, app* const* vars, expr_ref& fml, bool get_first, guarded_defs* defs) {
return m_qe.eliminate_exists(num_vars, vars, fml, m_free_vars, get_first, defs);
}
@ -1700,7 +1767,7 @@ namespace qe {
void propagate_assignment(model_evaluator& model_eval) {
if (m_fml) {
update_current(model_eval, true);
update_status st = update_current(model_eval, true);
}
}
@ -1982,7 +2049,7 @@ namespace qe {
virtual lbool eliminate_exists(
unsigned num_vars, app* const* vars, expr_ref& fml,
app_ref_vector& free_vars, bool get_first, def_vector* defs) {
app_ref_vector& free_vars, bool get_first, guarded_defs* defs) {
if (get_first) {
return eliminate_block(num_vars, vars, fml, free_vars, get_first, defs);
}
@ -2008,7 +2075,7 @@ namespace qe {
lbool eliminate_block(
unsigned num_vars, app* const* vars, expr_ref& fml,
app_ref_vector& free_vars, bool get_first, def_vector* defs) {
app_ref_vector& free_vars, bool get_first, guarded_defs* defs) {
checkpoint();
@ -2094,54 +2161,6 @@ namespace qe {
};
#if 0
//
// Instantiation based quantifier elimination procedure.
// try a few loops of checking satisfiability.
// substitute in model values for bound variables.
//
class quant_elim_inst : public quant_elim {
ast_manager&
public:
quant_elim_inst(ast_manager& m): m(m) {}
virtual lbool eliminate_exists(
unsigned num_vars, app* const* vars,
expr_ref& fml, app_ref_vector& free_vars, bool get_first, def_vector* defs) {
}
virtual void set_assumption(expr* fml) {}
virtual void collect_statistics(statistics & st) const {
m_solver.collect_statistics(st);
}
virtual void eliminate(bool is_forall, unsigned num_vars, app* const* vars, expr_ref& fml) {
if (is_forall) {
fml = m.mk_not(fml);
r = eliminate_exists(num_vars, vars, fml, free_vars, false, defs);
fml = m.mk_not(fml);
}
else {
r = eliminate_exists(num_vars, vars, fml, free_vars, false, defs);
}
}
virtual void set_cancel(bool f) {
m_solver.set_cancel(f);
}
virtual void updt_params(params_ref const& p) {
m_solver.updt_params(p);
}
};
#endif
// ------------------------------------------------
// expr_quant_elim
@ -2310,40 +2329,28 @@ namespace qe {
lbool expr_quant_elim::first_elim(unsigned num_vars, app* const* vars, expr_ref& fml, def_vector& defs) {
app_ref_vector fvs(m);
init_qe();
return m_qe->eliminate_exists(num_vars, vars, fml, fvs, true, &defs);
}
bool expr_quant_elim::solve_for_var(app* var, expr* _fml, expr_ref_vector& terms, expr_ref_vector& fmls) {
expr_ref assms(m.mk_true(), m);
func_decl* v = var->get_decl();
init_qe();
while (true) {
def_vector defs(m);
app_ref_vector fvs(m);
m_qe->set_assumption(assms);
expr_ref fml(_fml, m);
lbool is_sat = m_qe->eliminate_exists(1, &var, fml, fvs, true, &defs);
switch (is_sat) {
case l_false: return true;
case l_undef: return false;
default: break;
}
bool found = false;
for (unsigned i = 0; !found && i < defs.size(); ++i) {
if (defs.var(i) == v) {
terms.push_back(defs.def(i));
fmls.push_back(fml);
found = true;
}
}
if (!found) {
NOT_IMPLEMENTED_YET();
}
assms = m.mk_and(assms, m.mk_not(fml));
guarded_defs gdefs(m);
lbool res = m_qe->eliminate_exists(num_vars, vars, fml, fvs, true, &gdefs);
if (gdefs.size() > 0) {
defs.reset();
defs.append(gdefs.defs(0));
fml = gdefs.guard(0);
}
return true;
return res;
}
bool expr_quant_elim::solve_for_var(app* var, expr* fml, guarded_defs& defs) {
return solve_for_vars(1,&var, fml, defs);
}
bool expr_quant_elim::solve_for_vars(unsigned num_vars, app* const* vars, expr* _fml, guarded_defs& defs) {
app_ref_vector fvs(m);
expr_ref fml(_fml, m);
TRACE("qe", tout << mk_pp(fml, m) << "\n";);
init_qe();
lbool is_sat = m_qe->eliminate_exists(num_vars, vars, fml, fvs, false, &defs);
return is_sat != l_undef;
}
void expr_quant_elim::set_cancel(bool f) {
if (m_qe) {

View file

@ -226,8 +226,10 @@ namespace qe {
class def_vector {
func_decl_ref_vector m_vars;
expr_ref_vector m_defs;
def_vector& operator=(def_vector const& other);
public:
def_vector(ast_manager& m): m_vars(m), m_defs(m) {}
def_vector(def_vector const& other): m_vars(other.m_vars), m_defs(other.m_defs) {}
void push_back(func_decl* v, expr* e) {
m_vars.push_back(v);
m_defs.push_back(e);
@ -240,6 +242,33 @@ namespace qe {
func_decl* var(unsigned i) const { return m_vars[i]; }
expr* def(unsigned i) const { return m_defs[i]; }
expr_ref_vector::element_ref def_ref(unsigned i) { return m_defs[i]; }
void normalize();
void project(unsigned num_vars, app* const* vars);
};
/**
\brief Guarded definitions.
A realizer to a an existential quantified formula is a disjunction
together with a substitution from the existentially quantified variables
to terms such that:
1. The original formula (exists (vars) fml) is equivalent to the disjunction of guards.
2. Each guard is equivalent to fml where 'vars' are replaced by the substitution associated
with the guard.
*/
class guarded_defs {
expr_ref_vector m_guards;
vector<def_vector> m_defs;
bool inv();
public:
guarded_defs(ast_manager& m): m_guards(m) { SASSERT(inv()); }
void add(expr* guard, def_vector const& defs);
unsigned size() const { return m_guards.size(); }
def_vector const& defs(unsigned i) const { return m_defs[i]; }
expr* guard(unsigned i) const { return m_guards[i]; }
std::ostream& display(std::ostream& out) const;
void project(unsigned num_vars, app* const* vars);
};
class quant_elim;
@ -277,10 +306,12 @@ namespace qe {
\brief solve for (exists (var) fml).
Return false if operation failed.
Return true and list of pairs (t_i, fml_i) in <terms, fmls>
such that fml[t_1] \/ ... \/ fml[t_n] == (exists (var) fml)
and fml_i == fml[t_1]
such that fml_1 \/ ... \/ fml_n == (exists (var) fml)
and fml_i => fml[t_i]
*/
bool solve_for_var(app* var, expr* fml, expr_ref_vector& terms, expr_ref_vector& fmls);
bool solve_for_var(app* var, expr* fml, guarded_defs& defs);
bool solve_for_vars(unsigned num_vars, app* const* vars, expr* fml, guarded_defs& defs);
void set_cancel(bool f);

View file

@ -367,16 +367,6 @@ namespace qe {
simplify(result);
}
expr_ref mk_idiv(expr* a, numeral const & k) {
if (k.is_one()) {
return expr_ref(a, m);
}
expr_ref result(m);
result = m_arith.mk_idiv(a, m_arith.mk_numeral(k, true));
simplify(result);
return result;
}
expr* mk_numeral(numeral const& k, bool is_int = true) { return m_arith.mk_numeral(k, is_int); }
expr* mk_numeral(int k, bool is_int) { return mk_numeral(numeral(k),is_int); }
@ -1699,6 +1689,40 @@ public:
private:
/**
\brief Compute least upper/greatest lower bounds for x.
Assume:
(not (= k 0))
(<= 0 (mod m k))
(< (mod m k) (abs k))
(= m (+ (* k (div m k)) (mod m k)))
i.e.
k * (e div k) + (e mod k) = e
When k is positive, least upper bound
for x such that: k*x <= e is e div k
When k is negative, greatest lower bound
for x such that k*x <= e is e div k
k * (e div k) + (e mod k) = e
*/
expr_ref mk_idiv(expr* e, numeral k) {
SASSERT(!k.is_zero());
arith_util& a = m_util.m_arith;
if (k.is_one()) {
return expr_ref(e, m);
}
if (k.is_minus_one()) {
return expr_ref(a.mk_uminus(e), m);
}
SASSERT(a.is_int(e));
return expr_ref(a.mk_idiv(e, a.mk_numeral(k, true)), m);
}
void get_def(contains_app& contains_x, unsigned v, expr* fml, expr_ref& def) {
app* x = contains_x.x();
x_subst x_t(m_util);
@ -1730,35 +1754,30 @@ public:
// a*x + term <= 0
expr_ref term(bounds.exprs(is_strict, !is_lower)[i], m);
rational a = bounds.coeffs(is_strict, !is_lower)[i];
if (x_t.get_term()) {
// a*(c*x' + s) + term <= 0
// term <- a*s + term
// a <- a*c
term = m_util.mk_add(m_util.mk_mul(a,x_t.get_term()), term);
a = a * x_t.get_coeff();
// x := coeff * x' + s
// solve instead for
// a*coeff*x' + term + a*s <= 0
TRACE("qe", tout << x_t.get_coeff() << "* " << mk_pp(x,m) << " + "
<< mk_pp(x_t.get_term(), m) << "\n";);
SASSERT(x_t.get_coeff().is_pos());
term = m_util.mk_add(term, m_util.mk_mul(a, x_t.get_term()));
a = a * x_t.get_coeff();
}
TRACE("qe", tout << a << "* " << mk_pp(x,m) << " + " << mk_pp(term, m) << " <= 0\n";);
SASSERT(a.is_int());
if (is_lower) {
// a*x + t <= 0
// <=
// x <= -t div a
SASSERT(a.is_pos());
term = m_util.mk_idiv(m_util.mk_uminus(term), a);
}
else {
// -a*x + t <= 0
// <=>
// t <= a*x
// <=
// ((div t a) + 1) <= x
term = m_util.mk_idiv(term, abs(a));
if (!(abs(a).is_one())) {
term = m_util.mk_add(term, m_util.mk_one(x));
}
}
terms.push_back(term);
SASSERT(is_lower == a.is_pos());
TRACE("qe", tout << is_lower << " " << a << " " << mk_pp(term, m) << "\n";);
// a*x + t <= 0
// <=
// x <= -t div a + 1
term = m_util.mk_uminus(term);
term = mk_idiv(term, a);
terms.push_back(term);
TRACE("qe", tout << "a: " << a << " term: " << mk_pp(term, m) << "\n";);
}
is_strict = true;
sz = bounds.size(is_strict, !is_lower);
@ -1788,14 +1807,11 @@ public:
}
if (x_t.get_term()) {
//
// x = x_t.get_coeff()*x' + x_t.get_term()
// =>
// x' = (x - x_t.get_term()) div x_t.get_coeff()
//
def = m_util.mk_idiv(m_util.mk_sub(def, x_t.get_term()), x_t.get_coeff());
// x := coeff * x + s
TRACE("qe", tout << x_t.get_coeff() << "* " << mk_pp(x,m) << " + "
<< mk_pp(x_t.get_term(), m) << "\n";);
def = m_util.mk_add(m_util.mk_mul(x_t.get_coeff(), def), x_t.get_term());
}
m_util.simplify(def);
return;
}
@ -1822,25 +1838,39 @@ public:
// assert v => (x <= t_i)
//
SASSERT(v < bounds.size(is_strict, is_lower));
expr_ref t(bounds.exprs(is_strict, is_lower)[v], m);
def = bounds.exprs(is_strict, is_lower)[v];
rational a = bounds.coeffs(is_strict, is_lower)[v];
t = x_t.mk_term(a, t);
a = x_t.mk_coeff(a);
def = t;
if (a.is_pos()) {
def = m_util.mk_uminus(def);
}
if (x_t.get_term()) {
def = m_util.mk_idiv(m_util.mk_sub(def, x_t.get_term()), x_t.get_coeff());
// x := coeff * x' + s
// solve instead for
// a*coeff*x' + term + a*s <= 0
TRACE("qe", tout << x_t.get_coeff() << "* " << mk_pp(x,m) << " + "
<< mk_pp(x_t.get_term(), m) << "\n";);
SASSERT(x_t.get_coeff().is_pos());
def = m_util.mk_add(def, m_util.mk_mul(a, x_t.get_term()));
a = a * x_t.get_coeff();
}
if (!a.is_one()) {
def = m_util.mk_idiv(def, a);
SASSERT(a.is_int());
SASSERT(is_lower != a.is_pos());
// a*x + t <= 0
// <=
// x <= -t div a
def = m_util.mk_uminus(def);
def = mk_idiv(def, a);
if (x_t.get_term()) {
// x := coeff * x + s
def = m_util.mk_add(m_util.mk_mul(x_t.get_coeff(), def), x_t.get_term());
}
m_util.simplify(def);
TRACE("qe", tout << "TBD: " << a << " " << mk_pp(t, m) << "\n";);
TRACE("qe", tout << "TBD: " << a << " " << mk_pp(def, m) << "\n";);
}
expr_ref mk_not(expr* e) {

View file

@ -467,10 +467,10 @@ namespace qe {
SASSERT(m_datatype_util.is_datatype(s));
TRACE("quant_elim", tout << mk_pp(x.x(), m) << " " << vl << "\n";);
if (m_datatype_util.is_recursive(s)) {
subst_rec(x, vl, fml);
subst_rec(x, vl, fml, def);
}
else {
subst_nonrec(x, vl, fml);
subst_nonrec(x, vl, fml, def);
}
if (def) {
*def = 0; // TBD
@ -501,14 +501,21 @@ namespace qe {
private:
void add_def(expr* term, expr_ref* def) {
if (def) {
*def = term;
}
}
//
// replace x by C(y1,..,yn) where y1,..,yn are fresh variables.
//
void subst_constructor(contains_app& x, func_decl* c, expr_ref& fml) {
void subst_constructor(contains_app& x, func_decl* c, expr_ref& fml, expr_ref* def) {
subst_clos* sub = 0;
if (m_subst_cache.find(x.x(), c, sub)) {
m_replace->apply_substitution(x.x(), sub->first, 0, fml);
add_def(sub->first, def);
for (unsigned i = 0; i < sub->second.size(); ++i) {
m_ctx.add_var(sub->second[i]);
}
@ -529,6 +536,7 @@ namespace qe {
m_trail.push_back(c);
m_trail.push_back(t);
add_def(t, def);
m_replace->apply_substitution(x.x(), t, 0, fml);
sub->first = t;
m_subst_cache.insert(x.x(), c, sub);
@ -643,7 +651,7 @@ namespace qe {
}
}
void subst_rec(contains_app& contains_x, rational const& vl, expr_ref& fml) {
void subst_rec(contains_app& contains_x, rational const& vl, expr_ref& fml, expr_ref* def) {
app* x = contains_x.x();
sort* s = x->get_decl()->get_range();
SASSERT(m_datatype_util.is_datatype(s));
@ -661,6 +669,7 @@ namespace qe {
app_ref fresh_x(m.mk_fresh_const("x", s), m);
m_ctx.add_var(fresh_x);
m_replace->apply_substitution(x, fresh_x, 0, fml);
add_def(fresh_x, def);
TRACE("quant_elim", tout << "Add recognizer " << mk_pp(is_c, m) << "\n";);
return;
}
@ -668,7 +677,7 @@ namespace qe {
if (has_selector(contains_x, fml, c)) {
TRACE("quant_elim", tout << "Eliminate selector " << mk_ll_pp(c, m) << "\n";);
subst_constructor(contains_x, c, fml);
subst_constructor(contains_x, c, fml, def);
return;
}
@ -697,6 +706,7 @@ namespace qe {
if (idx < eqs.num_eqs()) {
expr* t = eqs.eq(idx);
expr* c = eqs.eq_cond(idx);
add_def(t, def);
m_replace->apply_substitution(x, t, fml);
if (!m.is_true(c)) {
fml = m.mk_and(c, fml);
@ -710,6 +720,10 @@ namespace qe {
for (unsigned i = 0; i < eqs.num_neqs(); ++i) {
m_replace->apply_substitution(eqs.neq_atom(i), m.mk_true(), fml);
}
if (def) {
NOT_IMPLEMENTED_YET();
// you need to create a diagonal term
}
}
TRACE("quant_elim", tout << "reduced " << mk_pp(fml.get(), m) << "\n";);
}
@ -753,7 +767,7 @@ namespace qe {
m_ctx.add_constraint(true, is_c);
}
virtual void subst_nonrec(contains_app& x, rational const& vl, expr_ref& fml) {
virtual void subst_nonrec(contains_app& x, rational const& vl, expr_ref& fml, expr_ref* def) {
sort* s = x.x()->get_decl()->get_range();
SASSERT(m_datatype_util.is_datatype(s));
SASSERT(!m_datatype_util.is_recursive(s));
@ -767,7 +781,7 @@ namespace qe {
SASSERT(vl.get_unsigned() < sz);
c = (*m_datatype_util.get_datatype_constructors(s))[vl.get_unsigned()];
}
subst_constructor(x, c, fml);
subst_constructor(x, c, fml, def);
}

File diff suppressed because it is too large Load diff

View file

@ -19,11 +19,10 @@ Revision History:
#ifndef _SMT_PARSER_H_
#define _SMT_PARSER_H_
#include "ast.h"
#include "vector.h"
#include "smtlib.h"
#include "z3.h"
#include <iostream>
#include<iostream>
#include"ast.h"
#include"vector.h"
#include"smtlib.h"
namespace smtlib {
class parser {
@ -42,8 +41,6 @@ namespace smtlib {
virtual bool parse_file(char const * path) = 0;
virtual bool parse_string(char const * string) = 0;
virtual bool parse_commands(Z3_context ctx, std::istream& is, std::ostream& os) = 0;
virtual benchmark * get_benchmark() = 0;
};
};

View file

@ -27,7 +27,7 @@ class tactic;
tactic * mk_propagate_values_tactic(ast_manager & m, params_ref const & p = params_ref());
/*
ADD_TACTIC_CMD("propagate-values", "propagate constants.", "mk_propagate_values_tactic(m, p)")
ADD_TACTIC("propagate-values", "propagate constants.", "mk_propagate_values_tactic(m, p)")
*/
#endif

View file

@ -1,59 +0,0 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
tst_ast_pp.cpp
Abstract:
Test AST Pretty printing module
Author:
Nikolaj Bjorner (nbjorner) 2006-10-5
Revision History:
--*/
#include "ast.h"
#include "ast_pp.h"
#include "ast_dag_pp.h"
#include "smtparser.h"
#include <iostream>
void tst_ast_pp()
{
ast_manager m;
smtlib::parser* parser = smtlib::parser::create(m);
parser->initialize_smtlib();
if (!parser->parse_string(
"(benchmark test :extrasorts (A B) :extrafuns ((f A A) (g A A A) (x A) (p A bool)) \n"
":formula (p (f x))\n"
":extrafuns ((x1 Int) (y1 Int))\n"
":formula (<= 1 (+ x1 y1))\n"
":formula (let (x (g x x)) (let (x (g x x)) (let (x (g x x)) (let (x (g x x)) (p (g x x))))))\n"
":formula (p x)\n"
")")) {
SASSERT(false);
dealloc(parser);
return;
}
smtlib::benchmark* b = parser->get_benchmark();
for (unsigned j = 0; j < b->get_num_assumptions(); ++j) {
expr* e = b->get_assumptions()[j];
std::cout << mk_pp(e, m) << "\n";
ast_dag_pp(std::cout, m, e);
}
for (unsigned j = 0; j < b->get_num_formulas(); ++j) {
expr* e = b->begin_formulas()[j];
std::cout << mk_pp(e, m) << "\n";
ast_dag_pp(std::cout, m, e);
}
dealloc(parser);
}

View file

@ -1,90 +0,0 @@
/*++
Copyright (c) 2008 Microsoft Corporation
Module Name:
tst_ast_smt_pp.cpp
Abstract:
Test AST Pretty printing module
Author:
Nikolaj Bjorner (nbjorner) 2008-09-04
Revision History:
--*/
#include "ast.h"
#include "ast_smt_pp.h"
#include "smtparser.h"
#include <iostream>
#include <sstream>
void tst_ast_smt_pp()
{
ast_manager m;
smtlib::parser* parser = smtlib::parser::create(m);
parser->initialize_smtlib();
if (!parser->parse_string(
"(benchmark test :extrasorts (A B) :extrafuns ((f A A) (g A A A) (x A) (p A bool)) \n"
":extrafuns ((arg0 BitVec[8]) (arg1 BitVec[8]) (arg2 BitVec[8]))\n"
":formula (p (f x))\n"
":extrafuns ((x1 Int) (y1 Int))\n"
":formula (<= 1 (+ x1 y1))\n"
":formula (let (x (g x x)) (let (x (g x x)) (let (x (g x x)) (let (x (g x x)) (p (g x x))))))\n"
":formula (p x)\n"
":formula (bvsge (bvadd arg0 arg2) (extract[7:0] bv3[32]))\n"
":formula (forall (x Int) (y Int) (z Int) (and (<= 1 x) (<= x y))) \n"
":formula (forall (x Int) (y Int) (z Int) (and (<= 2 (ite (<= z 1) x (* 2 x))) (<= x y)))\n"
":formula (forall (x Int) (y Int) (and (<= 2 (ite (forall (z Int) (<= z 1)) x (* 2 x))) (<= x y)))\n"
":formula (forall (x Int) (y Int) (and (<= 2 (ite (forall (z Int) (or (> x y) (<= z 1))) x (* 2 x))) (<= x y)))\n"
":extrafuns ((a1 Array))\n"
":formula (= x1 (select (store a1 y1 y1) x1))\n"
":extrafuns ((a2 Array[32:8]))\n"
":formula (= arg0 (select a2 bv0[32]))\n"
":datatypes ((list (cons (car Int) (cdr list)) nil))\n"
":extrafuns ((a list) (b list) (c list))\n"
":formula (is_nil nil)\n"
":datatypes ((list1 (cons1 (car1 Int) (cdr1 list2)) nil1) (list2 (cons1 (car2 list) (cdr2 list1)) nil2) )\n"
":formula (is_nil2 nil2)\n"
")")) {
SASSERT(false);
dealloc(parser);
return;
}
smtlib::benchmark* b = parser->get_benchmark();
for (unsigned j = 0; j < b->get_num_formulas(); ++j) {
expr* e = b->begin_formulas()[j];
ast_smt_pp pp(m);
pp.display(std::cout, e);
}
for (unsigned j = 0; j < b->get_num_formulas(); ++j) {
expr* e = b->begin_formulas()[j];
// print and parse formula again.
std::ostringstream buffer;
ast_smt_pp pp(m);
pp.display(buffer, e);
ast_manager m2;
smtlib::parser* parser2 = smtlib::parser::create(m2);
parser2->initialize_smtlib();
if (!parser2->parse_string(buffer.str().c_str())) {
SASSERT(false);
dealloc(parser2);
return;
}
dealloc(parser2);
}
dealloc(parser);
}

View file

@ -1,118 +0,0 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
dl_rule_set.cpp
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2010-05-18.
Revision History:
--*/
#include"dl_context.h"
#include"dl_rule_set.h"
#include"dl_mk_filter_rules.h"
#include"dl_mk_simple_joins.h"
#include"smtparser.h"
#include"ast_pp.h"
#include<iostream>
#include<sstream>
void tst_dl_rule_set() {
enable_trace("mk_filter_rules");
front_end_params params;
ast_manager m;
smtlib::parser * parser = smtlib::parser::create(m);
parser->initialize_smtlib();
datalog::context ctx(m, params);
datalog::rule_set rs(ctx);
datalog::rule_manager& rm = ctx.get_rule_manager();
datalog::rule_ref_vector rv(rm);
if (!parser->parse_string(
"(benchmark test\n"
":extrapreds ((T Int Int) (Q Int Int) (R Int Int Int) (S Int Int Int) (DynActual Int Int Int) (GlobalSym Int Int) (HeapPointsTo Int Int Int) (Calls Int Int)) \n"
":extrapreds ((Actual Int Int Int) (PointsTo Int Int) (PointsTo0 Int Int) (FuncDecl0 Int Int) (Assign Int Int) (Load Int Int Int))\n"
":formula (forall (x Int) (=> (Q x 1) (T x x)))\n"
":formula (forall (v Int) (h Int) (=> (PointsTo0 v h) (PointsTo v h)))\n"
":formula (forall (v Int) (h Int) (=> (FuncDecl0 v h) (PointsTo v h)))\n"
":formula (forall (v Int) (h Int) (=> (FuncDecl0 v h) (PointsTo v h)))\n"
":formula (forall (v1 Int) (v2 Int) (h Int) (=> (and (PointsTo v2 h) (Assign v1 v2)) (PointsTo v1 h)))\n"
":formula (forall (x Int) (y Int) (z Int) (=> (and (Q x y) (T y z)) (T x y)))\n"
":formula (forall (i1 Int) (v Int) (fun Int) (c Int) (v1 Int) (h Int) (h1 Int) (=> (and (GlobalSym 0 fun) (HeapPointsTo fun 1 c) (Calls i1 c) (Actual i1 3 v1) (PointsTo v1 h) (HeapPointsTo h 0 h1) (PointsTo v h1)) (DynActual i1 2 v)))\n"
":formula (forall (i1 Int) (v Int) (fun Int) (c Int) (v1 Int) (h Int) (h1 Int) (=> (and (GlobalSym 0 fun) (HeapPointsTo fun 1 c) (Calls i1 c) (Actual i1 3 v1) (PointsTo v1 h) (HeapPointsTo h 1 h1) (PointsTo v h1)) (DynActual i1 3 v)))\n"
":formula (forall (i1 Int) (v Int) (fun Int) (c Int) (v1 Int) (h Int) (h1 Int) (=> (and (GlobalSym 0 fun) (HeapPointsTo fun 1 c) (Calls i1 c) (Actual i1 3 v1) (PointsTo v1 h) (HeapPointsTo h 2 h1) (PointsTo v h1)) (DynActual i1 4 v)))\n"
":formula (forall (v1 Int) (v2 Int) (h1 Int) (h2 Int) (f Int) (=> (and (Load v2 v1 f) (PointsTo v1 h1) (HeapPointsTo h1 f h2)) (PointsTo v2 h1)))\n"
":formula (forall (v1 Int) (v2 Int) (h1 Int) (h2 Int) (f Int) (=> (and (Load v2 v1 0) (HeapPointsTo h1 f h2)) (PointsTo v2 h1)))\n"
":formula (forall (v1 Int) (v2 Int) (h1 Int) (h2 Int) (f Int) (=> (and (not (Load v2 v1 0)) (HeapPointsTo h1 f h2)) (PointsTo v2 h1)))\n"
")")) {
SASSERT(false);
dealloc(parser);
return;
}
smtlib::benchmark * b = parser->get_benchmark();
for (unsigned j = 0; j < b->get_num_formulas(); ++j) {
expr * e = b->begin_formulas()[j];
ptr_vector<expr> todo;
todo.push_back(e);
while (!todo.empty()) {
e = todo.back();
todo.pop_back();
if (is_quantifier(e)) {
e = to_quantifier(e)->get_expr();
todo.push_back(e);
}
else if (is_app(e)) {
app* a = to_app(e);
if (is_uninterp(e) && !ctx.is_predicate(a->get_decl())) {
std::cout << "registering " << a->get_decl()->get_name() << "\n";
ctx.register_predicate(a->get_decl());
}
else {
todo.append(a->get_num_args(), a->get_args());
}
}
}
}
for (unsigned j = 0; j < b->get_num_formulas(); ++j) {
expr * e = b->begin_formulas()[j];
if (is_quantifier(e)) {
try {
rm.mk_rule(e, rv);
}
catch(...) {
std::cerr << "ERROR: it is not a valid Datalog rule:\n" << mk_pp(e, m) << "\n";
}
}
}
rs.add_rules(rv.size(), rv.c_ptr());
rs.display(std::cout);
datalog::mk_filter_rules p(ctx);
model_converter_ref mc;
proof_converter_ref pc;
datalog::rule_set * new_rs = p(rs, mc, pc);
std::cout << "\nAfter mk_filter:\n";
new_rs->display(std::cout);
datalog::mk_simple_joins p2(ctx);
datalog::rule_set * new_rs2 = p2(*new_rs, mc, pc);
std::cout << "\nAfter mk_simple_joins:\n";
new_rs2->display(std::cout);
dealloc(new_rs);
dealloc(new_rs2);
dealloc(parser);
}

View file

@ -1,127 +0,0 @@
#include "expr_delta.h"
#include "smtparser.h"
#include "ast_pp.h"
#include "ast_smt_pp.h"
static void iterate_delta(ast_manager& m, expr_delta& delta) {
unsigned n = 0;
expr_ref_vector result(m);
std::cout << "Delta\n";
while (true) {
result.reset();
if (!delta.delta_dfs(n, result)) {
return;
}
std::cout << n << ": ";
for (unsigned i = 0; i < result.size(); ++i) {
std::cout << mk_pp(result[i].get(), m) << " ";
}
std::cout << "\n";
n++;
}
}
void tst_expr_delta1() {
ast_manager m;
smtlib::parser* parser = smtlib::parser::create(m);
parser->initialize_smtlib();
parser->parse_string(
"(benchmark samples :logic QF_LIA \n"
" :extrafuns ((a Int) (b Int) (c Int)) \n"
" :assumption (> a 0) \n"
" :assumption (> b 0) \n"
" :formula (forall (x Int) (y Int) (z Int) (and (<= 1 x) (<= x y))) \n"
" :formula (forall (x Int) (y Int) (z Int) (and (<= 2 (ite (<= z 1) x (* 2 x))) (<= x y)))\n"
" :formula (forall (x Int) (y Int) (and (<= 2 (ite (forall (z Int) (<= z 1)) x (* 2 x))) (<= x y)))\n"
" :formula (forall (x Int) (y Int) (and (<= 2 (ite (forall (z Int) (or (> x y) (<= z 1))) x (* 2 x))) (<= x y)))\n"
")"
);
smtlib::benchmark* b = parser->get_benchmark();
for (unsigned j = 0; j < b->get_num_formulas(); ++j) {
expr_delta delta(m);
for (unsigned i = 0; i < b->get_num_assumptions(); ++i) {
delta.assert_cnstr(b->get_assumptions()[i]);
}
delta.assert_cnstr(b->begin_formulas()[j]);
iterate_delta(m, delta);
}
dealloc(parser);
}
static void get_expr_delta(unsigned position, char const* in, char const* out) {
ast_manager m;
smtlib::parser* parser = smtlib::parser::create(m);
parser->initialize_smtlib();
if (!parser->parse_file(in)) {
std::cout << "error parsing file\n";
dealloc(parser);
return;
}
smtlib::benchmark* b = parser->get_benchmark();
SASSERT(b->get_num_formulas() == 1);
expr_delta delta(m);
for (unsigned i = 0; i < b->get_num_assumptions(); ++i) {
delta.assert_cnstr(b->get_assumptions()[i]);
}
delta.assert_cnstr(b->begin_formulas()[0]);
expr_ref_vector result(m);
if (!delta.delta_dfs(position, result)) {
std::cout << "done\n";
}
else {
ast_smt_pp pp(m);
std::ofstream outf(out);
if (outf.bad() || outf.fail()) {
std::cout << "Could not open output\n";
}
else {
switch(b->get_status()) {
case smtlib::benchmark::UNKNOWN:
pp.set_status("unknown");
break;
case smtlib::benchmark::SAT:
pp.set_status("sat");
break;
case smtlib::benchmark::UNSAT:
pp.set_status("unsat");
break;
}
pp.set_logic(b->get_logic().str().c_str());
for (unsigned i = 0; i + 1 < result.size(); ++i) {
pp.add_assumption(result[i].get());
}
pp.display(outf, result[result.size()-1].get());
std::cout << "ok\n";
}
}
dealloc(parser);
}
void tst_expr_delta(char** argv, int argc, int& i) {
if (i + 3 >= argc) {
std::cout << "Usage: <position:number> <input:file-name> <output:file-name>\n";
return;
}
++i;
unsigned position = atol(argv[i]);
++i;
char const* in_file = argv[i];
++i;
char const* out_file = argv[i];
get_expr_delta(position, in_file, out_file);
}

View file

@ -1,51 +0,0 @@
#include "expr_pattern_match.h"
#include "smtparser.h"
#include "ast_pp.h"
#include "arith_decl_plugin.h"
#include "bv_decl_plugin.h"
#include "array_decl_plugin.h"
#include "reg_decl_plugins.h"
void tst_expr_pattern_match() {
ast_manager manager;
reg_decl_plugins(manager);
expr_pattern_match apm(manager);
apm.display(std::cout);
const char* test_string = "(benchmark patterns :status unknown :logic ALL \n"
":extrasorts (S) \n"
":extrafuns ((R S S bool)) \n"
":formula (forall (x S) (y S) (z S) \n"
" (or (not (R x y)) (not (R y z)) (R x z)) \n"
" ; :pats { (R x y) (R y z) } \n"
" :weight { 2 } \n"
" )\n"
")";
smtlib::parser* parser = smtlib::parser::create(manager);
parser->initialize_smtlib();
std::cout << "parsing test string\n";
if (!parser->parse_string(test_string)) {
UNREACHABLE();
}
std::cout << "test string parsed\n";
smtlib::benchmark* bench = parser->get_benchmark();
for (unsigned i = 0; i < bench->get_num_formulas(); ++i) {
expr* fml = bench->begin_formulas()[i];
SASSERT(fml->get_kind() == AST_QUANTIFIER);
quantifier* qf = to_quantifier(fml);
app_ref_vector patterns(manager);
unsigned weight = 0;
if (apm.match_quantifier(qf, patterns, weight)) {
std::cout << "Found pattern match\n";
for (unsigned i = 0; i < patterns.size(); ++i) {
ast_pp(std::cout, patterns[i].get(), manager) << "\n";
}
std::cout << "weight: " << weight << "\n";
}
}
dealloc(parser);
}

View file

@ -1,94 +0,0 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
grobner.cpp
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-12-05.
Revision History:
--*/
#include"smtparser.h"
#include"ast_pp.h"
#include"arith_decl_plugin.h"
#include"simplifier.h"
#include"basic_simplifier_plugin.h"
#include"arith_simplifier_plugin.h"
#include"front_end_params.h"
#include"grobner.h"
#include"reg_decl_plugins.h"
void display_eqs(grobner & gb, v_dependency_manager & dep_m) {
std::cerr << "RESULT:\n";
ptr_vector<grobner::equation> eqs;
gb.get_equations(eqs);
ptr_vector<grobner::equation>::iterator it = eqs.begin();
ptr_vector<grobner::equation>::iterator end = eqs.end();
for (; it != end; ++it) {
grobner::equation * eq = *it;
ptr_vector<void> exs;
v_dependency * d = eq->get_dependency();
dep_m.linearize(d, exs);
std::cerr << "{";
ptr_vector<void>::iterator it2 = exs.begin();
ptr_vector<void>::iterator end2 = exs.end();
for (bool first = true; it2 != end2; ++it2) {
if (first) first = false; else std::cerr << " ";
std::cerr << *it2;
}
std::cerr << "}, lc: " << eq->is_linear_combination() << ", ";
gb.display_equation(std::cerr, *eq);
}
}
void tst_grobner(char ** argv, int argc, int & i) {
front_end_params params;
if (i + 1 < argc) {
char const* file_path = argv[i+1];
ast_manager m;
smtlib::parser* parser = smtlib::parser::create(m);
reg_decl_plugins(m);
parser->initialize_smtlib();
if (!parser->parse_file(file_path)) {
std::cout << "Could not parse file : " << file_path << std::endl;
dealloc(parser);
return;
}
smtlib::benchmark* b = parser->get_benchmark();
simplifier simp(m);
basic_simplifier_plugin * bp = alloc(basic_simplifier_plugin, m);
simp.register_plugin(bp);
simp.register_plugin(alloc(arith_simplifier_plugin, m, *bp, params));
arith_util util(m);
v_dependency_manager dep_m;
grobner gb(m, dep_m);
ptr_vector<expr>::const_iterator it = b->begin_axioms();
ptr_vector<expr>::const_iterator end = b->end_axioms();
for (unsigned idx = 1; it != end; ++it, ++idx) {
expr * ax = *it;
expr_ref s_ax(m);
proof_ref pr(m);
simp(ax, s_ax, pr);
std::cerr << mk_pp(s_ax, m) << "\n";
if (m.is_eq(s_ax))
gb.assert_eq(s_ax, dep_m.mk_leaf(reinterpret_cast<void*>(idx)));
}
gb.display(std::cerr);
gb.compute_basis(1024);
display_eqs(gb, dep_m);
dealloc(parser);
}
}

View file

@ -18,6 +18,8 @@ Revision History:
--*/
#include"imdd.h"
#ifndef _AMD64_
static void tst0() {
std::cout << "--------------------------------\n";
imdd_manager m;
@ -607,3 +609,9 @@ void tst_imdd() {
}
#else
void tst_imdd() {
}
#endif

View file

@ -123,7 +123,6 @@ int main(int argc, char ** argv) {
memory::initialize(0);
bool do_display_usage = false;
parse_cmd_line_args(argc, argv, do_display_usage);
TST_ARGV(grobner);
TST(random);
TST(vector);
TST(symbol_table);
@ -131,23 +130,17 @@ int main(int argc, char ** argv) {
TST(symbol);
TST(heap);
TST(hashtable);
TST_ARGV(smtparser);
TST(rational);
TST(inf_rational);
TST(ast);
TST(optional);
TST(bit_vector);
TST(ast_pp);
TST(ast_smt_pp);
TST_ARGV(expr_delta);
TST(string_buffer);
TST(map);
TST(diff_logic);
TST(uint_set);
TST_ARGV(expr_rand);
TST(expr_context_simplifier);
TST(ini_file);
TST(expr_pattern_match);
TST(list);
TST(small_object_allocator);
TST(timeout);
@ -157,9 +150,6 @@ int main(int argc, char ** argv) {
TST(bit_blaster);
TST(var_subst);
TST(simple_parser);
TST(symmetry);
TST_ARGV(symmetry_parse);
TST_ARGV(symmetry_prove);
TST(api);
TST(old_interval);
TST(interval_skip_list);
@ -167,10 +157,8 @@ int main(int argc, char ** argv) {
TST(memory);
TST(get_implied_equalities);
TST(arith_simplifier_plugin);
TST(quant_elim);
TST(matcher);
TST(datalog_parser);
TST(dl_rule_set);
TST_ARGV(datalog_parser_file);
TST(object_allocator);
TST(mpz);
@ -208,7 +196,6 @@ int main(int argc, char ** argv) {
TST(prime_generator);
TST(permutation);
TST(nlsat);
TST(qe_defs);
TST(ext_numeral);
TST(interval);
TST(quant_solve);

View file

@ -20,8 +20,6 @@ Revision History:
#include"util.h"
#include"vector.h"
using namespace std;
void apply_permutation_copy(unsigned sz, unsigned const * src, unsigned const * p, unsigned * target) {
for (unsigned i = 0; i < sz; i++) {
target[i] = src[p[i]];
@ -29,6 +27,7 @@ void apply_permutation_copy(unsigned sz, unsigned const * src, unsigned const *
}
static void tst1(unsigned sz, unsigned num_tries, unsigned max = UINT_MAX) {
#if 0
unsigned_vector data;
unsigned_vector p;
unsigned_vector new_data;
@ -51,6 +50,7 @@ static void tst1(unsigned sz, unsigned num_tries, unsigned max = UINT_MAX) {
for (unsigned i = 0; i < 0; i++)
SASSERT(data[i] == new_data[i]);
}
#endif
}
void tst_permutation() {

View file

@ -1,87 +0,0 @@
#include "arith_decl_plugin.h"
#include "qe.h"
#include "ast_pp.h"
#include "smtparser.h"
#include "reg_decl_plugins.h"
static void test_defs(ast_manager& m, expr* _fml) {
arith_util a(m);
app_ref x(m);
qe::def_vector defs(m);
expr_ref fml(_fml, m);
x = m.mk_const(symbol("x"), a.mk_int());
app* vars[1] = { x.get() };
front_end_params fparams;
qe::expr_quant_elim qelim(m, fparams);
lbool result = qelim.first_elim(1, vars, fml, defs);
std::cout << mk_pp(_fml, m) << "\n--->\n";
std::cout << mk_pp(fml, m) << "\n";
for (unsigned i = 0; i < defs.size(); ++i) {
std::cout << defs.var(i)->get_name() << " "
<< mk_pp(defs.def(i), m) << "\n";
}
std::cout << "\n";
}
static void test_defs_all(ast_manager& m, expr* _fml) {
arith_util a(m);
app_ref x(m);
expr_ref fml(_fml, m), fml0(_fml, m);
x = m.mk_const(symbol("x"), a.mk_int());
app* vars[1] = { x.get() };
front_end_params fparams;
qe::expr_quant_elim qelim(m, fparams);
lbool result = l_true;
while (result == l_true) {
fml = fml0;
qe::def_vector defs(m);
result = qelim.first_elim(1, vars, fml, defs);
std::cout << result << "\n";
std::cout << mk_pp(fml, m) << "\n";
for (unsigned i = 0; i < defs.size(); ++i) {
std::cout << defs.var(i)->get_name() << " "
<< mk_pp(defs.def(i), m) << "\n";
}
fml0 = m.mk_and(fml0, m.mk_not(fml));
}
}
static void test_defs(char const* str) {
ast_manager m;
reg_decl_plugins(m);
scoped_ptr<smtlib::parser> parser = smtlib::parser::create(m);
parser->initialize_smtlib();
std::ostringstream buffer;
buffer << "(benchmark presburger :status unknown :logic AUFLIA "
<< ":extrafuns ((x Int) (y Int) (z Int))\n"
<< ":formula " << str << ")";
parser->parse_string(buffer.str().c_str());
smtlib::benchmark* b = parser->get_benchmark();
smtlib::theory::expr_iterator it = b->begin_formulas();
smtlib::theory::expr_iterator end = b->end_formulas();
for (; it != end; ++it) {
test_defs(m, *it);
}
}
void tst_qe_defs() {
enable_trace("qe");
test_defs("(and (<= (* 2 x) y) (>= (* 3 x) z) (<= (* 4 x) (* 2 z)) (= (mod x 2) 0))");
return;
test_defs("(and (<= (* 2 x) y) (>= (* 3 x) z) (= (mod x 2) 0))");
test_defs("(and (<= (* 2 x) y) (= (mod x 2) 0))");
test_defs("(= (* 2 x) y)");
test_defs("(or (< x 0) (> x 1))");
test_defs("(or (< x y) (> x y))");
test_defs("(= x y)");
test_defs("(<= x y)");
test_defs("(>= x y)");
test_defs("(and (<= (+ x y) 0) (<= (+ x z) 0))");
test_defs("(and (<= (+ x y) 0) (<= (+ (* 2 x) z) 0))");
test_defs("(and (<= (+ (* 3 x) y) 0) (<= (+ (* 2 x) z) 0))");
test_defs("(and (>= x y) (>= x z))");
test_defs("(< x y)");
test_defs("(> x y)");
}

View file

@ -8,39 +8,85 @@
#include "expr_replacer.h"
#include "smt_solver.h"
#include "reg_decl_plugins.h"
#include "expr_abstract.h"
#include "model_smt2_pp.h"
#include "smt2parser.h"
#include "var_subst.h"
static void validate_quant_solution(ast_manager& m, app* x, expr* fml, expr* t, expr* new_fml) {
static void validate_quant_solution(ast_manager& m, expr* fml, expr* guard, qe::def_vector const& defs) {
// verify:
// new_fml <=> fml[t/x]
// new_fml => fml[t/x]
scoped_ptr<expr_replacer> rep = mk_expr_simp_replacer(m);
app_ref_vector xs(m);
expr_substitution sub(m);
sub.insert(x, t);
for (unsigned i = 0; i < defs.size(); ++i) {
xs.push_back(m.mk_const(defs.var(i)));
sub.insert(xs.back(), defs.def(i));
}
rep->set_substitution(&sub);
expr_ref fml1(fml, m);
(*rep)(fml1);
expr_ref tmp(m);
tmp = m.mk_not(m.mk_iff(new_fml, fml1));
tmp = m.mk_not(m.mk_implies(guard, fml1));
front_end_params fp;
smt::solver solver(m, fp);
solver.assert_expr(tmp);
lbool res = solver.check();
std::cout << res << "\n";
//SASSERT(res == l_false);
if (res != l_false) {
std::cout << "Validation failed: " << res << "\n";
std::cout << mk_pp(tmp, m) << "\n";
model_ref model;
solver.get_model(model);
model_smt2_pp(std::cout, m, *model, 0);
fatal_error(0);
}
}
static void validate_quant_solutions(app* x, expr* fml, expr_ref_vector& guards) {
return;
// quant_elim option got removed...
// verify:
// fml <=> guard_1 \/ guard_2 \/ ...
ast_manager& m = guards.get_manager();
expr_ref tmp(m), fml2(m);
tmp = m.mk_or(guards.size(), guards.c_ptr());
expr* _x = x;
std::cout << mk_pp(fml, m) << "\n";
expr_abstract(m, 0, 1, &_x, fml, fml2);
std::cout << mk_pp(fml2, m) << "\n";
symbol name(x->get_decl()->get_name());
sort* s = m.get_sort(x);
fml2 = m.mk_exists(1, &s, &name, fml2);
std::cout << mk_pp(fml2, m) << "\n";
tmp = m.mk_not(m.mk_iff(fml2, tmp));
std::cout << mk_pp(tmp, m) << "\n";
front_end_params fp;
smt::solver solver(m, fp);
solver.assert_expr(tmp);
lbool res = solver.check();
std::cout << "checked\n";
SASSERT(res == l_false);
if (res != l_false) {
std::cout << res << "\n";
fatal_error(0);
}
}
static void test_quant_solver(ast_manager& m, app* x, expr* fml) {
static void test_quant_solver(ast_manager& m, unsigned sz, app*const* xs, expr* fml) {
front_end_params params;
params.m_quant_elim = true;
qe::expr_quant_elim qe(m, params);
expr_ref_vector terms(m);
expr_ref_vector fmls(m);
bool success = qe.solve_for_var(x, fml, terms, fmls);
qe::guarded_defs defs(m);
bool success = qe.solve_for_vars(sz, xs, fml, defs);
std::cout << "------------------------\n";
std::cout << mk_pp(fml, m) << "\n";
if (success) {
for (unsigned i = 0; i < terms.size(); ++i) {
std::cout << mk_pp(x, m) << " = " << mk_pp(terms[i].get(), m) << "\n" << mk_pp(fmls[i].get(), m) << "\n";
validate_quant_solution(m, x, fml, terms[i].get(), fmls[i].get());
if (success) {
defs.display(std::cout);
for (unsigned i = 0; i < defs.size(); ++i) {
validate_quant_solution(m, fml, defs.guard(i), defs.defs(i));
}
}
else {
@ -48,99 +94,136 @@ static void test_quant_solver(ast_manager& m, app* x, expr* fml) {
}
}
static void test_quant_solver_rec(ast_manager& m, unsigned num_vars, app* const* xs, expr* fml) {
if (num_vars == 0) {
return;
}
front_end_params params;
params.m_quant_elim = true;
qe::expr_quant_elim qe(m, params);
expr_ref_vector fmls(m), ors(m), terms(m);
app* x = xs[0];
bool success = qe.solve_for_var(x, fml, terms, fmls);
std::cout << "------------------------\n";
std::cout << mk_pp(fml, m) << "\n";
if (success) {
for (unsigned i = 0; i < terms.size(); ++i) {
std::cout << mk_pp(x, m) << " = " << mk_pp(terms[i].get(), m) << "\n" << mk_pp(fmls[i].get(), m) << "\n";
validate_quant_solution(m, x, fml, terms[i].get(), fmls[i].get());
ors.reset();
if (m.is_or(fmls[i].get())) {
ors.append(to_app(fmls[i].get())->get_num_args(), to_app(fmls[i].get())->get_args());
}
else {
ors.push_back(fmls[i].get());
}
for (unsigned j = 0; j < ors.size(); ++j) {
test_quant_solver_rec(m, num_vars-1, xs+1, ors[j].get());
}
static expr_ref parse_fml(ast_manager& m, char const* str) {
expr_ref result(m);
front_end_params fp;
cmd_context ctx(fp, false, &m);
ctx.set_ignore_check(true);
std::ostringstream buffer;
buffer << "(declare-const x Int)\n"
<< "(declare-const y Int)\n"
<< "(declare-const z Int)\n"
<< "(declare-const a Int)\n"
<< "(declare-const b Int)\n"
<< "(declare-datatypes () ((IList (nil) (cons (car Int) (cdr IList)))))\n"
<< "(declare-const l1 IList)\n"
<< "(declare-const l2 IList)\n"
<< "(declare-datatypes () ((Cell (null) (cell (car Cell) (cdr Cell)))))\n"
<< "(declare-const c1 Cell)\n"
<< "(declare-const c2 Cell)\n"
<< "(declare-const c3 Cell)\n"
<< "(declare-datatypes () ((Tuple (tuple (first Int) (second Bool) (third Real)))))\n"
<< "(declare-const t1 Tuple)\n"
<< "(declare-const t2 Tuple)\n"
<< "(declare-const t3 Tuple)\n"
<< "(assert " << str << ")\n";
std::istringstream is(buffer.str());
VERIFY(parse_smt2_commands(ctx, is));
SASSERT(ctx.begin_assertions() != ctx.end_assertions());
result = *ctx.begin_assertions();
return result;
}
static void parse_fml(char const* str, app_ref_vector& vars, expr_ref& fml) {
ast_manager& m = fml.get_manager();
fml = parse_fml(m, str);
if (is_exists(fml)) {
quantifier* q = to_quantifier(fml);
for (unsigned i = 0; i < q->get_num_decls(); ++i) {
vars.push_back(m.mk_const(q->get_decl_name(i), q->get_decl_sort(i)));
}
}
else {
std::cout << "failed\n";
fml = q->get_expr();
var_subst vs(m, true);
vs(fml, vars.size(), (expr*const*)vars.c_ptr(), fml);
}
}
static void test_quant_solver(ast_manager& m, app* x, char const* str) {
expr_ref fml = parse_fml(m, str);
test_quant_solver(m, 1, &x, fml);
}
static void test_quant_solver(ast_manager& m, unsigned sz, app*const* xs, char const* str) {
expr_ref fml = parse_fml(m, str);
test_quant_solver(m, sz, xs, fml);
}
static void test_quant_solver(ast_manager& m, char const* str) {
expr_ref fml(m);
app_ref_vector vars(m);
parse_fml(str, vars, fml);
test_quant_solver(m, vars.size(), vars.c_ptr(), fml);
}
static void test_quant_solve1() {
ast_manager m;
arith_util ar(m);
reg_decl_plugins(m);
sort* i = ar.mk_int();
app_ref x(m.mk_const(symbol("x"),i), m);
app_ref y(m.mk_const(symbol("y"),i), m);
app_ref a(m.mk_const(symbol("a"),i), m);
app_ref b(m.mk_const(symbol("b"),i), m);
expr_ref n2(ar.mk_numeral(rational(2), true), m);
expr_ref n3(ar.mk_numeral(rational(3), true), m);
expr_ref n4(ar.mk_numeral(rational(4), true), m);
expr_ref n10(ar.mk_numeral(rational(10), true), m);
expr_ref n20(ar.mk_numeral(rational(20), true), m);
expr_ref x2(ar.mk_mul(n2, x), m);
expr_ref x3(ar.mk_mul(n3, x), m);
expr_ref fml1(m), fml2(m), fml3(m), fml4(m);
expr_ref fml(m), t1(m), t2(m);
fml1 = m.mk_eq(x, a);
fml2 = ar.mk_lt(x, a);
fml3 = ar.mk_gt(x, a);
fml4 = m.mk_and(ar.mk_lt(x, a), ar.mk_lt(x, b));
expr_ref fml5(m.mk_and(ar.mk_gt(x, a), ar.mk_lt(x, b)), m);
expr_ref fml6(ar.mk_le(x, a), m);
expr_ref fml7(ar.mk_ge(x, a), m);
expr_ref fml8(ar.mk_lt(ar.mk_mul(n2, x), a), m);
expr_ref fml9(m.mk_eq(ar.mk_mul(n2, x), a), m);
test_quant_solver(m, x.get(), fml1.get());
test_quant_solver(m, x.get(), fml2.get());
test_quant_solver(m, x.get(), fml3.get());
test_quant_solver(m, x.get(), fml4.get());
test_quant_solver(m, x.get(), fml5.get());
test_quant_solver(m, x.get(), fml6.get());
test_quant_solver(m, x.get(), fml7.get());
test_quant_solver(m, x.get(), fml8.get());
test_quant_solver(m, x.get(), fml9.get());
fml = ar.mk_lt(x2, a); test_quant_solver(m, x.get(), fml.get());
fml = ar.mk_gt(x2, a); test_quant_solver(m, x.get(), fml.get());
fml = ar.mk_le(x2, a); test_quant_solver(m, x.get(), fml.get());
fml = ar.mk_ge(x2, a); test_quant_solver(m, x.get(), fml.get());
app_ref xr(m.mk_const(symbol("x"),i), m);
app_ref yr(m.mk_const(symbol("y"),i), m);
app* x = xr.get();
app* y = yr.get();
app* xy[2] = { x, y };
fml = m.mk_and(ar.mk_lt(a, ar.mk_mul(n3,x)), ar.mk_lt(ar.mk_mul(n3,x), b));
test_quant_solver(m, x.get(), fml.get());
test_quant_solver(m, x, "(and (<= x y) (= (mod x 2) 0))");
test_quant_solver(m, x, "(and (<= (* 2 x) y) (= (mod x 2) 0))");
test_quant_solver(m, x, "(and (>= x y) (= (mod x 2) 0))");
test_quant_solver(m, x, "(and (>= (* 2 x) y) (= (mod x 2) 0))");
test_quant_solver(m, x, "(and (<= (* 2 x) y) (>= x z) (= (mod x 2) 0))");
test_quant_solver(m, x, "(and (<= (* 2 x) y) (>= (* 3 x) z) (= (mod x 2) 0))");
test_quant_solver(m, x, "(>= (* 2 x) a)");
test_quant_solver(m, x, "(<= (* 2 x) a)");
test_quant_solver(m, x, "(< (* 2 x) a)");
test_quant_solver(m, x, "(= (* 2 x) a)");
test_quant_solver(m, x, "(< (* 2 x) a)");
test_quant_solver(m, x, "(> (* 2 x) a)");
test_quant_solver(m, x, "(and (<= a x) (<= (* 2 x) b))");
test_quant_solver(m, x, "(and (<= a x) (<= x b))");
test_quant_solver(m, x, "(and (<= (* 2 a) x) (<= x b))");
test_quant_solver(m, x, "(and (<= (* 2 a) x) (<= (* 2 x) b))");
test_quant_solver(m, x, "(and (<= a x) (<= (* 3 x) b))");
test_quant_solver(m, x, "(and (<= (* 3 a) x) (<= x b))");
test_quant_solver(m, x, "(and (<= (* 3 a) x) (<= (* 3 x) b))");
test_quant_solver(m, x, "(and (< a (* 3 x)) (< (* 3 x) b))");
test_quant_solver(m, x, "(< (* 3 x) a)");
test_quant_solver(m, x, "(= (* 3 x) a)");
test_quant_solver(m, x, "(< (* 3 x) a)");
test_quant_solver(m, x, "(> (* 3 x) a)");
test_quant_solver(m, x, "(<= (* 3 x) a)");
test_quant_solver(m, x, "(>= (* 3 x) a)");
test_quant_solver(m, x, "(<= (* 2 x) a)");
test_quant_solver(m, x, "(or (= (* 2 x) y) (= (+ (* 2 x) 1) y))");
test_quant_solver(m, x, "(= x a)");
test_quant_solver(m, x, "(< x a)");
test_quant_solver(m, x, "(> x a)");
test_quant_solver(m, x, "(and (> x a) (< x b))");
test_quant_solver(m, x, "(and (> x a) (< x b))");
test_quant_solver(m, x, "(<= x a)");
test_quant_solver(m, x, "(>= x a)");
test_quant_solver(m, x, "(and (<= (* 2 x) y) (= (mod x 2) 0))");
test_quant_solver(m, x, "(= (* 2 x) y)");
test_quant_solver(m, x, "(or (< x 0) (> x 1))");
test_quant_solver(m, x, "(or (< x y) (> x y))");
test_quant_solver(m, x, "(= x y)");
test_quant_solver(m, x, "(<= x y)");
test_quant_solver(m, x, "(>= x y)");
test_quant_solver(m, x, "(and (<= (+ x y) 0) (<= (+ x z) 0))");
test_quant_solver(m, x, "(and (<= (+ x y) 0) (<= (+ (* 2 x) z) 0))");
test_quant_solver(m, x, "(and (<= (+ (* 3 x) y) 0) (<= (+ (* 2 x) z) 0))");
test_quant_solver(m, x, "(and (>= x y) (>= x z))");
test_quant_solver(m, x, "(< x y)");
test_quant_solver(m, x, "(> x y)");
test_quant_solver(m, 2, xy, "(and (<= (- (* 2 y) b) (+ (* 3 x) a)) (<= (- (* 2 x) a) (+ (* 4 y) b)))");
t1 = ar.mk_sub(ar.mk_mul(n2,y),b);
t2 = ar.mk_add(ar.mk_mul(n3,x),a);
fml1 = ar.mk_le(t1, t2);
t1 = ar.mk_sub(ar.mk_mul(n2,x),a);
t2 = ar.mk_add(ar.mk_mul(n4,y),b);
fml2 = ar.mk_le(t1,t2);
fml = m.mk_and(fml1, fml2);
app* xy[2] = { x.get(), y.get() };
test_quant_solver_rec(m, 2, xy, fml.get());
test_quant_solver(m, "(exists ((c Cell)) (= c null))");
test_quant_solver(m, "(exists ((c Cell)) (= c (cell null c1)))");
//TBD:
//test_quant_solver(m, "(exists ((c Cell)) (= (cell c c) c1))");
//test_quant_solver(m, "(exists ((c Cell)) (not (= c null)))");
}

View file

@ -1,52 +0,0 @@
#ifdef _WINDOWS
#include <iostream>
#include <strstream>
#include <fstream>
#include <sstream>
#include "smtparser.h"
#include "for_each_file.h"
#include "array_decl_plugin.h"
#include "bv_decl_plugin.h"
#include "reg_decl_plugins.h"
class for_each_file_smt : public for_each_file_proc {
public:
for_each_file_smt() {}
bool operator()(char const * file_path) {
bool result = true;
std::cout << "Parsing: " << file_path << std::endl;
ast_manager ast_manager;
smtlib::parser* parser = smtlib::parser::create(ast_manager);
reg_decl_plugins(ast_manager);
parser->initialize_smtlib();
if (!parser->parse_file(file_path)) {
std::cout << "Could not parse file : " << file_path << std::endl;
result = false;
}
dealloc(parser);
return result;
}
};
static bool test_directory(char const * base) {
for_each_file_smt foreach;
return for_each_file(foreach, base, "*.smt");
}
void tst_smtparser(char** argv, int argc, int & i) {
bool result = true;
if (i + 1 < argc) {
result = test_directory(argv[i+1]);
i += 1;
}
SASSERT(result);
}
#else
void tst_smtparser(char** argv, int argc, int & i) {
}
#endif

View file

@ -17,7 +17,6 @@ Revision History:
--*/
#include"var_subst.h"
#include"smtparser.h"
#include"ast_pp.h"
#include"arith_decl_plugin.h"
#include"bv_decl_plugin.h"
@ -104,22 +103,4 @@ void tst_var_subst() {
ast_manager m;
reg_decl_plugins(m);
tst_subst(m);
scoped_ptr<smtlib::parser> parser = smtlib::parser::create(m);
parser->initialize_smtlib();
parser->parse_string(
"(benchmark samples :logic AUFLIA\n"
" :extrafuns ((f Int Int) (g Int Int Int) (a Int) (b Int))\n"
" :formula (forall (x Int) (or (= (f x) x) (forall (y Int) (z Int) (= (g x y) (f z)))))\n"
" :formula (forall (x Int) (w Int) (or (= (f x) x) (forall (y Int) (z Int) (or (= (g x y) (g w z)) (forall (x1 Int) (= (f x1) (g x y)))))))\n"
")"
);
smtlib::benchmark* b = parser->get_benchmark();
smtlib::theory::expr_iterator it = b->begin_formulas();
smtlib::theory::expr_iterator end = b->end_formulas();
for (; it != end; ++it)
tst_instantiate(m, *it);
}

View file

@ -156,7 +156,7 @@ protected:
\brief Return true if the given key \c k is in the entry \c e. That is,
k \in [e.begin_key(), e.end_key()].
*/
bool contains(entry const & e, key const & k) const { return leq(e.begin_key(), k) && leq(k, e.end_key()); }
bool contains(entry const & e, key const & k) const { return this->leq(e.begin_key(), k) && this->leq(k, e.end_key()); }
/**
\brief Return true if the given key \c k is in the entry \c e. That is,
@ -193,7 +193,7 @@ protected:
for (;;) {
int mid = low + ((high - low) / 2);
entry const & mid_entry = bt->get(mid);
if (gt(k, mid_entry.end_key())) {
if (this->gt(k, mid_entry.end_key())) {
low = mid + 1;
if (low > high) {
idx = static_cast<unsigned>(mid) + 1;
@ -277,7 +277,7 @@ protected:
// the search_key must be in the current bucket, or in the first entry of the next bucket (if the next bucket is not 0).
SASSERT(curr->empty() || lt(first_key(curr), k));
SASSERT(next == 0 || geq(first_key(next), k));
SASSERT(next == 0 || this->geq(first_key(next), k));
DEBUG_CODE({
if (UpdatePredVect && next != 0)
for (unsigned i = 0; i < next->level(); i++)
@ -318,7 +318,7 @@ protected:
\brief Return true if the two entries (that satisfy lt(e1, e2)) can be merged.
*/
bool can_be_merged(entry const & e1, entry const & e2) const {
return val_eq(e1.val(), e2.val()) && eq(succ(e1.end_key()), e2.begin_key());
return this->val_eq(e1.val(), e2.val()) && this->eq(this->succ(e1.end_key()), e2.begin_key());
}
/**
@ -327,16 +327,16 @@ protected:
\remark pred_vect contains the predecessors of the successor of bt.
*/
void merge_first_of_succ_if_possible(manager & m, bucket * bt, bucket * pred_vect[]) {
SASSERT(check_pred_vect(bt->get_next(0), pred_vect));
SASSERT(this->check_pred_vect(bt->get_next(0), pred_vect));
bucket * next_bucket = bt->get_next(0);
if (next_bucket != 0) {
entry & curr_entry = bt->last_entry();
entry & next_entry = next_bucket->get(0);
if (can_be_merged(curr_entry, next_entry)) {
curr_entry.set_end_key(next_entry.end_key());
del_entry(m, next_bucket, 0); // del_entry invokes dec_ref_eh
this->del_entry(m, next_bucket, 0); // del_entry invokes dec_ref_eh
if (next_bucket->empty())
del_bucket(m, next_bucket, pred_vect);
this->del_bucket(m, next_bucket, pred_vect);
}
}
}
@ -355,7 +355,7 @@ protected:
entry & next_entry = bt->get(idx+1);
if (can_be_merged(curr_entry, next_entry)) {
curr_entry.set_end_key(next_entry.end_key());
del_entry(m, bt, idx+1); // del_entry invokes dec_ref_eh
this->del_entry(m, bt, idx+1); // del_entry invokes dec_ref_eh
}
}
}
@ -371,7 +371,7 @@ protected:
entry & prev_entry = bt->get(idx-1);
if (can_be_merged(prev_entry, curr_entry)) {
prev_entry.set_end_key(curr_entry.end_key());
del_entry(m, bt, idx); // del_entry invokes dec_ref_eh
this->del_entry(m, bt, idx); // del_entry invokes dec_ref_eh
}
}
@ -439,7 +439,7 @@ protected:
int mid = low + ((high - low) / 2);
SASSERT(mid < static_cast<int>(bt->size()));
entry & mid_entry = bt->get(mid);
if (gt(k, mid_entry.end_key())) {
if (this->gt(k, mid_entry.end_key())) {
low = mid + 1;
if (low > high) {
// mid entry must be deleted since k > mid_entry.end_key().
@ -461,7 +461,7 @@ protected:
SASSERT(contains(mid_entry, k));
if (lt(k, mid_entry.end_key())) {
TRACE("del_entries_upto_bug", tout << "exit 3) mid: " << mid << "\n"; this->display(tout, mid_entry); tout << "\n";);
mid_entry.set_begin_key(succ(k));
mid_entry.set_begin_key(this->succ(k));
SASSERT(mid < static_cast<int>(bt->size())); // Reason: loop invariant
return del_entries<RECYCLE_ENTRY>(m, bt, s_idx, mid);
}
@ -479,21 +479,21 @@ protected:
\brief Keep deleting keys <= k in bt and its successors.
*/
void del_entries_upto_loop(manager & m, bucket * bt, key const & k, bucket * pred_vect []) {
SASSERT(check_pred_vect(bt, pred_vect));
SASSERT(this->check_pred_vect(bt, pred_vect));
while (bt != 0) {
key const & bt_last_key = last_key(bt);
if (lt(k, bt_last_key)) {
del_last_entries_upto<false>(m, bt, 0, k);
return;
}
else if (eq(k, bt_last_key)) {
del_bucket(m, bt, pred_vect);
else if (this->eq(k, bt_last_key)) {
this->del_bucket(m, bt, pred_vect);
return;
}
else {
SASSERT(gt(k, bt_last_key));
SASSERT(this->gt(k, bt_last_key));
bucket * next = bt->get_next(0);
del_bucket(m, bt, pred_vect);
this->del_bucket(m, bt, pred_vect);
bt = next;
// continue deleting...
}
@ -516,7 +516,7 @@ protected:
*/
template<bool INSERT>
bool del_entries_upto(manager & m, bucket * bt, key const & k, bucket * pred_vect[], bucket * next_pred_vect[]) {
SASSERT(check_pred_vect(bt, pred_vect)); // pred_vect contains the predecessors of bt.
SASSERT(this->check_pred_vect(bt, pred_vect)); // pred_vect contains the predecessors of bt.
if (lt(k, first_key(bt))) {
// nothing to be done...
return false; // didn't manage to recycle entry.
@ -524,7 +524,7 @@ protected:
key const & bt_last_key = last_key(bt);
TRACE("del_entries_upto_bug", tout << "bt_last_key: " << bt_last_key << "\n";);
if (lt(k, bt_last_key)) {
if (this->lt(k, bt_last_key)) {
return del_last_entries_upto<INSERT>(m, bt, 0, k);
}
else {
@ -533,10 +533,10 @@ protected:
this->dec_ref(m, bt);
// REMARK: the slot 0 will be reused, but the element there is gone.
bt->set_size(1);
if (gt(k, bt_last_key)) {
if (this->gt(k, bt_last_key)) {
bucket * next = bt->get_next(0);
if (next != 0) {
update_predecessor_vector(pred_vect, bt, next_pred_vect);
this->update_predecessor_vector(pred_vect, bt, next_pred_vect);
del_entries_upto_loop(m, next, k, next_pred_vect);
}
}
@ -544,7 +544,7 @@ protected:
}
else {
bucket * next = bt->get_next(0);
del_bucket(m, bt, pred_vect); // it will invoke dec_ref_eh for all values in bt.
this->del_bucket(m, bt, pred_vect); // it will invoke dec_ref_eh for all values in bt.
// pred_vect does not need to be updated since it contains the predecessors of
// bt, since bt was deleted they are now the predecessors of its successor.
if (next != 0) {
@ -566,7 +566,7 @@ protected:
*/
template<bool INSERT>
bool del_entries_upto(manager & m, bucket * bt, unsigned s_idx, key const & k, bucket * pred_vect[]) {
SASSERT(check_pred_vect(bt->get_next(0), pred_vect)); // pred_vect contains the predecessors of the successor of bt.
SASSERT(this->check_pred_vect(bt->get_next(0), pred_vect)); // pred_vect contains the predecessors of the successor of bt.
SASSERT(s_idx > 0);
TRACE("del_entries_upto_bug",
tout << "INSERT: " << INSERT << "\n";
@ -592,7 +592,7 @@ protected:
return del_last_entries_upto<INSERT>(m, bt, s_idx, k);
}
else {
if (gt(k, bt_last_key)) {
if (this->gt(k, bt_last_key)) {
del_entries_upto_loop(m, bt->get_next(0), k, pred_vect);
}
if (Traits::ref_count) {
@ -619,10 +619,10 @@ protected:
*/
void insert_begin(manager & m, bucket * bt, key const & b, key const & e, value const & v, bucket * pred_vect[]) {
TRACE("interval_skip_list_bug", tout << "insert_begin: [" << b << ", " << e << "] -> " << v << "\n"; this->display(tout, bt););
SASSERT(check_pred_vect(bt, pred_vect));
SASSERT(this->check_pred_vect(bt, pred_vect));
SASSERT(!bt->empty());
SASSERT(bt->size() <= bt->capacity());
SASSERT(leq(b, first_key(bt)));
SASSERT(this->leq(b, first_key(bt)));
bucket * next_pred_vect[Traits::max_level];
next_pred_vect[0] = 0;
@ -639,14 +639,14 @@ protected:
merge_next_if_possible(m, bt, 0, next_pred_vect);
}
else {
update_predecessor_vector(pred_vect, bt);
this->update_predecessor_vector(pred_vect, bt);
merge_next_if_possible(m, bt, 0, pred_vect);
}
return;
}
// check if can merge with first entry in the bucket.
entry & fe = bt->first_entry();
if (val_eq(fe.val(), v) && eq(fe.begin_key(), succ(e))) {
if (this->val_eq(fe.val(), v) && this->eq(fe.begin_key(), this->succ(e))) {
// can merge
fe.set_begin_key(b);
// A new reference to v was not created. So, we must invoke dec_ref_eh since we increased the counter above.
@ -657,15 +657,15 @@ protected:
if (bt->size() == bt->capacity()) {
if (bt->capacity() < Traits::max_capacity) {
SASSERT(this->first_bucket() == bt && this->first_bucket()->get_next(0) == 0);
expand_first_bucket(m);
this->expand_first_bucket(m);
bt = this->first_bucket();
}
else {
// there is no space
splice(m, bt, pred_vect);
this->splice(m, bt, pred_vect);
}
}
open_space(bt, 0);
this->open_space(bt, 0);
set_entry(bt, 0, b, e, v); // Reference to v was stored, and inc_ref_eh was invoked above.
SASSERT(!can_be_merged(bt->get(0), bt->get(1)));
}
@ -675,7 +675,7 @@ protected:
*/
void insert_at(manager & m, bucket * bt, unsigned idx, key const & b, key const & e, value const & v, bucket * pred_vect[]) {
SASSERT(idx > 0);
SASSERT(check_pred_vect(bt->get_next(0), pred_vect));
SASSERT(this->check_pred_vect(bt->get_next(0), pred_vect));
this->inc_ref(m, v);
TRACE("insert_at_bug", tout << "before del_entries_upto:\n"; this->display_physical(tout););
@ -697,17 +697,17 @@ protected:
// there is no space
if (bt->capacity() < Traits::max_capacity) {
SASSERT(this->first_bucket() == bt && this->first_bucket()->get_next(0) == 0);
expand_first_bucket(m);
this->expand_first_bucket(m);
bt = this->first_bucket();
// there is no need to update pred_vect, since the list contains only one bucket.
}
else {
splice(m, bt, pred_vect);
this->splice(m, bt, pred_vect);
bucket * new_next = bt->get_next(0);
SASSERT(bt->size() == bt->capacity()/2);
if (idx == bt->capacity()/2) {
entry & bt_last_entry = bt->last_entry();
if (val_eq(bt_last_entry.val(), v) && eq(bt_last_entry.end_key(), pred(b))) {
if (this->val_eq(bt_last_entry.val(), v) && this->eq(bt_last_entry.end_key(), this->pred(b))) {
// merged with the last key of bt
bt_last_entry.set_end_key(e);
// A new reference to v was not created. So, we must invoke dec_ref_eh since we increased the counter above.
@ -715,7 +715,7 @@ protected:
return;
}
entry & new_next_first_entry = new_next->first_entry();
if (val_eq(new_next_first_entry.val(), v) && eq(new_next_first_entry.begin_key(), succ(e))) {
if (this->val_eq(new_next_first_entry.val(), v) && this->eq(new_next_first_entry.begin_key(), this->succ(e))) {
// merged with the first key of new_next
new_next_first_entry.set_begin_key(b);
// A new reference to v was not created. So, we must invoke dec_ref_eh since we increased the counter above.
@ -731,12 +731,12 @@ protected:
idx -= bt->capacity()/2;
SASSERT(idx > 0);
bt = new_next;
update_predecessor_vector(pred_vect, bt);
this->update_predecessor_vector(pred_vect, bt);
}
}
}
SASSERT(idx > 0);
open_space(bt, idx);
this->open_space(bt, idx);
set_entry(bt, idx, b, e, v); // Reference to v was stored, and inc_ref_eh was invoked above.
merge_next_if_possible(m, bt, idx, pred_vect);
merge_prev_if_possible(m, bt, idx);
@ -750,7 +750,7 @@ protected:
*/
void insert_inside(manager & m, bucket * bt, key const & b, key const & e, value const & v, bucket * pred_vect[]) {
TRACE("interval_skip_list_bug", tout << "insert_inside: [" << b << ", " << e << "] -> " << v << "\n";);
SASSERT(check_pred_vect(bt->get_next(0), pred_vect));
SASSERT(this->check_pred_vect(bt->get_next(0), pred_vect));
SASSERT(!bt->empty());
SASSERT(bt->size() <= bt->capacity());
// perform binary search to find position to insert [b, e]->v
@ -759,7 +759,7 @@ protected:
for (;;) {
int mid = low + ((high - low) / 2);
entry & mid_entry = bt->get(mid);
if (gt(b, mid_entry.end_key())) {
if (this->gt(b, mid_entry.end_key())) {
low = mid + 1;
if (low > high) {
// insert after mid_entry since b > mid_entry.end_key().
@ -779,8 +779,8 @@ protected:
else {
SASSERT(contains(mid_entry, b));
TRACE("insert_inside_bug", tout << "insert_inside:\n"; this->display(tout, bt););
if (val_eq(mid_entry.val(), v)) {
if (gt(e, mid_entry.end_key())) {
if (this->val_eq(mid_entry.val(), v)) {
if (this->gt(e, mid_entry.end_key())) {
// No need to create space.
// We did not create a new reference to v.
mid_entry.set_end_key(e);
@ -790,8 +790,8 @@ protected:
}
}
else {
if (gt(b, mid_entry.begin_key())) {
if (lt(e, mid_entry.end_key())) {
if (this->gt(b, mid_entry.begin_key())) {
if (this->lt(e, mid_entry.end_key())) {
// New interval is the middle of existing interval
// We must INVOKE add_ref_eh for mid_entry.val() and v.
@ -802,11 +802,11 @@ protected:
if (bt->size() >= bt->capacity() - 1) {
if (bt->capacity() < Traits::max_capacity) {
SASSERT(this->first_bucket() == bt && this->first_bucket()->get_next(0) == 0);
expand_first_bucket(m);
this->expand_first_bucket(m);
bt = this->first_bucket();
}
else {
splice(m, bt, pred_vect);
this->splice(m, bt, pred_vect);
int new_sz = bt->size();
bucket * new_next = bt->get_next(0);
if (mid >= new_sz) {
@ -816,24 +816,24 @@ protected:
}
}
}
open_2spaces(bt, mid);
this->open_2spaces(bt, mid);
entry & mid1_entry = bt->get(mid);
entry & new_entry = bt->get(mid+1);
entry & mid2_entry = bt->get(mid+2);
mid2_entry = mid1_entry;
mid1_entry.set_end_key(pred(b));
mid1_entry.set_end_key(this->pred(b));
new_entry.set_begin_key(b);
new_entry.set_end_key(e);
new_entry.set_val(v);
mid2_entry.set_begin_key(succ(e));
mid2_entry.set_begin_key(this->succ(e));
}
else {
mid_entry.set_end_key(pred(b));
mid_entry.set_end_key(this->pred(b));
insert_at(m, bt, mid+1, b, e, v, pred_vect);
}
}
else {
SASSERT(eq(b, mid_entry.begin_key()));
SASSERT(this->eq(b, mid_entry.begin_key()));
SASSERT(mid > 0); // Reason: insert_begin would have been called instead.
insert_at(m, bt, mid, b, e, v, pred_vect);
}
@ -864,7 +864,7 @@ protected:
for (;;) {
int mid = low + ((high - low) / 2);
entry & mid_entry = bt->get(mid);
if (gt(b, mid_entry.end_key())) {
if (this->gt(b, mid_entry.end_key())) {
low = mid + 1;
if (low > high) {
// insert after mid_entry since b > mid_entry.end_key().
@ -872,7 +872,7 @@ protected:
return;
}
}
else if (lt(b, mid_entry.begin_key())) {
else if (this->lt(b, mid_entry.begin_key())) {
high = mid - 1;
if (low > high) {
// insert before mid_entry since b < mid_entry.begin_key().
@ -883,8 +883,8 @@ protected:
}
else {
SASSERT(contains(mid_entry, b));
if (gt(b, mid_entry.begin_key())) {
if (lt(e, mid_entry.end_key())) {
if (this->gt(b, mid_entry.begin_key())) {
if (this->lt(e, mid_entry.end_key())) {
// The removed interval is inside of an existing interval.
// mid_entry will be split in two. So, we must invoke add_ref_eh for mid_entry.val()
@ -894,12 +894,12 @@ protected:
if (bt->size() == bt->capacity()) {
if (bt->capacity() < Traits::max_capacity) {
SASSERT(this->first_bucket() == bt && this->first_bucket()->get_next(0) == 0);
expand_first_bucket(m);
this->expand_first_bucket(m);
bt = this->first_bucket();
SASSERT(bt->size() < bt->capacity());
}
else {
splice(m, bt, pred_vect);
this->splice(m, bt, pred_vect);
if (mid >= static_cast<int>(bt->size())) {
// mid_entry moved to new (successor) bucket
mid -= bt->size();
@ -907,19 +907,19 @@ protected:
}
}
}
open_space(bt, mid);
this->open_space(bt, mid);
entry & mid1_entry = bt->get(mid);
entry & mid2_entry = bt->get(mid+1);
mid1_entry.set_end_key(pred(b));
mid2_entry.set_begin_key(succ(e));
mid1_entry.set_end_key(this->pred(b));
mid2_entry.set_begin_key(this->succ(e));
}
else {
mid_entry.set_end_key(pred(b));
mid_entry.set_end_key(this->pred(b));
del_entries_upto<false>(m, bt, mid+1, e, pred_vect);
}
}
else {
SASSERT(eq(b, mid_entry.begin_key()));
SASSERT(this->eq(b, mid_entry.begin_key()));
SASSERT(mid > 0); // Reason: remove_begin would have been called instead.
del_entries_upto<false>(m, bt, mid, e, pred_vect);
}
@ -1022,7 +1022,7 @@ private:
SASSERT(pred_vect[i]->get_next(i) == next);
});
SASSERT(curr == this->m_header || lt(first_key(curr), k));
SASSERT(next == 0 || leq(k, first_key(next)));
SASSERT(next == 0 || this->leq(k, first_key(next)));
}
public:
@ -1031,7 +1031,7 @@ public:
\brief Insert the entries [i -> v] for every i \in [b, e].
*/
void insert(manager & m, key const & b, key const & e, value const & v) {
SASSERT(leq(b, e));
SASSERT(this->leq(b, e));
if (this->empty()) {
insert_first_entry(m, b, e, v);
return;
@ -1052,20 +1052,20 @@ public:
SASSERT(this->first_bucket() == next);
insert_begin(m, next, b, e, v, pred_vect);
}
else if (next == 0 || gt(first_key(next), b)) {
else if (next == 0 || this->gt(first_key(next), b)) {
insert_inside(m, curr, b, e, v, pred_vect);
}
else {
SASSERT(!curr->empty());
SASSERT(!next->empty());
SASSERT(next != 0);
SASSERT(eq(first_key(next), b));
SASSERT(this->eq(first_key(next), b));
// Bucket curr is the predecessor of next.
SASSERT(curr->get_next(0) == next);
// check if we can merge with last entry of curr
entry & curr_last_entry = curr->last_entry();
if (val_eq(curr_last_entry.val(), v) && eq(curr_last_entry.end_key(), pred(b))) {
if (this->val_eq(curr_last_entry.val(), v) && this->eq(curr_last_entry.end_key(), this->pred(b))) {
// No new reference to v was create, we don't need to invok inc_ref_eh
curr_last_entry.set_end_key(e);
del_entries_upto<false>(m, next, e, pred_vect, 0);
@ -1190,7 +1190,7 @@ public:
\brief For each i \in [b, e] remove any entry [i->v] if it is in the list.
*/
void remove(manager & m, key const & b, key const & e) {
SASSERT(leq(b, e));
SASSERT(this->leq(b, e));
if (this->empty())
return;
bucket * pred_vect[Traits::max_level];
@ -1202,12 +1202,12 @@ public:
SASSERT(next != 0);
remove_begin(m, next, b, e, pred_vect);
}
else if (next == 0 || gt(first_key(next), b)) {
else if (next == 0 || this->gt(first_key(next), b)) {
remove_inside(m, curr, b, e, pred_vect);
}
else {
SASSERT(next != 0);
SASSERT(eq(first_key(next), b));
SASSERT(this->eq(first_key(next), b));
remove_begin(m, next, b, e, pred_vect);
}
}
@ -1273,9 +1273,9 @@ public:
--i;
for (;;) {
next = curr->get_next(i);
if (next != 0 && leq(first_key(next), k)) {
TRACE("interval_skip_list", tout << "next_bucket(" << k << "), i: " << i << " skipping #" << get_bucket_idx(curr);
tout << ", moving to: #" << get_bucket_idx(next) << "\n"; this->display(tout, next););
if (next != 0 && this->leq(first_key(next), k)) {
TRACE("interval_skip_list", tout << "next_bucket(" << k << "), i: " << i << " skipping #" << this->get_bucket_idx(curr);
tout << ", moving to: #" << this->get_bucket_idx(next) << "\n"; this->display(tout, next););
curr = next;
if (curr->level() > max) {
max = curr->level();
@ -1427,11 +1427,11 @@ public:
for (; it1 != end1 && it2 != end2; it1++, it2++) {
entry const & e1 = *it1;
entry const & e2 = *it2;
if (!eq(e1.begin_key(), e2.begin_key()))
if (!this->eq(e1.begin_key(), e2.begin_key()))
return false;
if (!eq(e1.end_key(), e2.end_key()))
if (!this->eq(e1.end_key(), e2.end_key()))
return false;
if (!val_eq(e1.val(), e2.val()))
if (!this->val_eq(e1.val(), e2.val()))
return false;
}
return true;
@ -1459,8 +1459,8 @@ public:
entry & curr = const_cast<entry&>(*it);
value const & old_val = curr.val();
value new_val = f(old_val);
inc_ref(m, new_val);
dec_ref(m, old_val);
this->inc_ref(m, new_val);
this->dec_ref(m, old_val);
curr.set_val(new_val);
}
SASSERT(check_invariant());
@ -1599,7 +1599,7 @@ private:
*/
void move_js(join_state & js, key const & k) const {
SASSERT(!js.done());
if (leq(k, js.tail())) {
if (this->leq(k, js.tail())) {
// We can't skip the current entry, because k in inside it.
// So, we just update the head.
js.m_head = k;
@ -1666,7 +1666,7 @@ public:
#ifdef Z3DEBUG
private:
bool check_invariant(entry const & e) const {
SASSERT(leq(e.begin_key(), e.end_key()));
SASSERT(this->leq(e.begin_key(), e.end_key()));
return true;
}
@ -1705,7 +1705,7 @@ public:
bucket const * next = curr->get_next(i);
if (next != 0) {
SASSERT(next->level() >= i);
SASSERT(i == 0 || is_reachable_at_i(curr, next, i-1));
SASSERT(i == 0 || this->is_reachable_at_i(curr, next, i-1));
SASSERT(!next->empty());
entry const & last_of_curr = curr->last_entry();
entry const & first_of_next = next->first_entry();