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

Merge branch 'master' of https://github.com/Z3Prover/z3 into lackr

This commit is contained in:
Christoph M. Wintersteiger 2016-02-04 18:27:19 +00:00
commit 808eb664cb
21 changed files with 1832 additions and 1669 deletions

View file

@ -60,11 +60,11 @@ namespace datalog {
expr_ref fml(m.mk_app(q, T), m);
b.assert_expr(fml);
res = b.m_solver.check();
if (res == l_true) {
res = get_model();
}
b.m_solver.pop(1);
b.m_solver.pop(1);
++m_bit_width;
}
return res;
@ -74,11 +74,11 @@ namespace datalog {
sort_ref mk_index_sort() {
return sort_ref(m_bv.mk_sort(m_bit_width), m);
}
var_ref mk_index_var() {
return var_ref(m.mk_var(0, mk_index_sort()), m);
}
void compile() {
sort_ref index_sort = mk_index_sort();
var_ref var = mk_index_var();
@ -92,17 +92,17 @@ namespace datalog {
// Assert: forall level . p(T) => body of rule i + equalities for head of rule i
func_decl_ref pr = mk_q_func_decl(p);
expr_ref pred = expr_ref(m.mk_app(pr, var.get()), m);
expr_ref_vector rules(m), sub(m), conjs(m);
expr_ref_vector rules(m), sub(m), conjs(m);
expr_ref trm(m), rule_body(m), rule_i(m);
for (unsigned i = 0; i < rls.size(); ++i) {
sub.reset();
for (unsigned i = 0; i < rls.size(); ++i) {
sub.reset();
conjs.reset();
rule& r = *rls[i];
rule& r = *rls[i];
rule_i = m.mk_app(mk_q_rule(p, i), var.get());
rules.push_back(rule_i);
mk_qrule_vars(r, i, sub);
// apply substitution to body.
var_subst vs(m, false);
for (unsigned k = 0; k < p->get_arity(); ++k) {
@ -137,21 +137,21 @@ namespace datalog {
b.assert_expr(trm);
}
}
void setup() {
b.m_fparams.m_relevancy_lvl = 2;
b.m_fparams.m_model = true;
b.m_fparams.m_model_compact = true;
b.m_fparams.m_mbqi = true;
}
void mk_qrule_vars(datalog::rule const& r, unsigned rule_id, expr_ref_vector& sub) {
ptr_vector<sort> sorts;
r.get_vars(m, sorts);
// populate substitution of bound variables.
sub.reset();
sub.resize(sorts.size());
for (unsigned k = 0; k < r.get_decl()->get_arity(); ++k) {
expr* arg = r.get_head()->get_arg(k);
if (is_var(arg)) {
@ -177,52 +177,52 @@ namespace datalog {
if (sorts[j] && !sub[j].get()) {
sub[j] = mk_q_var(r.get_decl(), sorts[j], rule_id, idx++);
}
}
}
}
expr_ref mk_q_var(func_decl* pred, sort* s, unsigned rule_id, unsigned idx) {
std::stringstream _name;
_name << pred->get_name() << "#" << rule_id << "_" << idx;
symbol nm(_name.str().c_str());
symbol nm(_name.str().c_str());
var_ref var = mk_index_var();
return expr_ref(m.mk_app(m.mk_func_decl(nm, mk_index_sort(), s), var), m);
}
}
expr_ref mk_q_arg(func_decl* pred, unsigned idx, bool is_current) {
SASSERT(idx < pred->get_arity());
std::stringstream _name;
_name << pred->get_name() << "#" << idx;
symbol nm(_name.str().c_str());
symbol nm(_name.str().c_str());
expr_ref var(mk_index_var(), m);
if (!is_current) {
var = m_bv.mk_bv_sub(var, mk_q_one());
}
return expr_ref(m.mk_app(m.mk_func_decl(nm, mk_index_sort(), pred->get_domain(idx)), var), m);
}
expr_ref mk_q_one() {
return mk_q_num(1);
}
expr_ref mk_q_num(unsigned i) {
return expr_ref(m_bv.mk_numeral(i, m_bit_width), m);
}
func_decl_ref mk_q_func_decl(func_decl* f) {
std::stringstream _name;
_name << f->get_name() << "#";
symbol nm(_name.str().c_str());
symbol nm(_name.str().c_str());
return func_decl_ref(m.mk_func_decl(nm, mk_index_sort(), f->get_range()), m);
}
func_decl_ref mk_q_rule(func_decl* f, unsigned rule_id) {
std::stringstream _name;
_name << f->get_name() << "#" << rule_id;
symbol nm(_name.str().c_str());
symbol nm(_name.str().c_str());
return func_decl_ref(m.mk_func_decl(nm, mk_index_sort(), m.mk_bool_sort()), m);
}
expr_ref eval_q(model_ref& model, func_decl* f, unsigned i) {
func_decl_ref fn = mk_q_func_decl(f);
expr_ref t(m), result(m);
@ -230,7 +230,7 @@ namespace datalog {
model->eval(t, result);
return result;
}
expr_ref eval_q(model_ref& model, expr* t, unsigned i) {
expr_ref tmp(m), result(m), num(m);
var_subst vs(m, false);
@ -239,8 +239,8 @@ namespace datalog {
vs(t, 1, nums, tmp);
model->eval(tmp, result);
return result;
}
}
lbool get_model() {
rule_manager& rm = b.m_ctx.get_rule_manager();
func_decl_ref q = mk_q_func_decl(b.m_query_pred);
@ -250,7 +250,7 @@ namespace datalog {
rule_unifier unifier(b.m_ctx);
rational num;
unsigned level, bv_size;
b.m_solver.get_model(md);
func_decl* pred = b.m_query_pred;
dl_decl_util util(m);
@ -261,7 +261,7 @@ namespace datalog {
level = num.get_unsigned();
SASSERT(m.is_true(eval_q(md, b.m_query_pred, level)));
TRACE("bmc", model_smt2_pp(tout, m, *md, 0););
rule_ref r0(rm), r1(rm), r2(rm);
while (true) {
TRACE("bmc", tout << "Predicate: " << pred->get_name() << "\n";);
@ -269,8 +269,8 @@ namespace datalog {
rule_vector const& rls = b.m_rules.get_predicate_rules(pred);
rule* r = 0;
unsigned i = 0;
for (; i < rls.size(); ++i) {
rule_i = m.mk_app(mk_q_rule(pred, i), mk_q_num(level).get());
for (; i < rls.size(); ++i) {
rule_i = m.mk_app(mk_q_rule(pred, i), mk_q_num(level).get());
TRACE("bmc", rls[i]->display(b.m_ctx, tout << "Checking rule " << mk_pp(rule_i, m) << " "););
if (m.is_true(eval_q(md, rule_i, level))) {
r = rls[i];
@ -280,13 +280,13 @@ namespace datalog {
SASSERT(r);
mk_qrule_vars(*r, i, sub);
// we have rule, we have variable names of rule.
// extract values for the variables in the rule.
for (unsigned j = 0; j < sub.size(); ++j) {
expr_ref vl = eval_q(md, sub[j].get(), i);
if (vl) {
// vl can be 0 if the interpretation does not assign a value to it.
sub[j] = vl;
sub[j] = vl;
}
else {
sub[j] = m.mk_var(j, m.get_sort(sub[j].get()));
@ -295,7 +295,7 @@ namespace datalog {
svector<std::pair<unsigned, unsigned> > positions;
vector<expr_ref_vector> substs;
expr_ref fml(m), concl(m);
rm.to_formula(*r, fml);
r2 = r;
rm.substitute(r2, sub.size(), sub.c_ptr());
@ -308,15 +308,15 @@ namespace datalog {
unifier.apply(*r0.get(), 0, *r2.get(), r1);
rm.to_formula(*r1.get(), concl);
scoped_proof _sp(m);
p = r->get_proof();
if (!p) {
p = m.mk_asserted(fml);
}
proof* premises[2] = { pr, p };
positions.push_back(std::make_pair(0, 1));
substs.push_back(sub1);
substs.push_back(sub);
pr = m.mk_hyper_resolve(2, premises, concl, positions, substs);
@ -339,7 +339,7 @@ namespace datalog {
}
r0 = r2;
}
if (level == 0) {
SASSERT(r->get_uninterpreted_tail_size() == 0);
break;
@ -370,7 +370,7 @@ namespace datalog {
lbool check() {
setup();
for (unsigned i = 0; ; ++i) {
IF_VERBOSE(1, verbose_stream() << "level: " << i << "\n";);
IF_VERBOSE(1, verbose_stream() << "level: " << i << "\n";);
b.checkpoint();
expr_ref_vector fmls(m);
compile(b.m_rules, fmls, i);
@ -392,12 +392,12 @@ namespace datalog {
for (unsigned i = 0; i < level_p->get_arity(); ++i) {
std::stringstream _name;
_name << query_pred->get_name() << "#" << level << "_" << i;
symbol nm(_name.str().c_str());
symbol nm(_name.str().c_str());
vars.push_back(m.mk_const(nm, level_p->get_domain(i)));
}
return expr_ref(m.mk_app(level_p, vars.size(), vars.c_ptr()), m);
}
void compile(rule_set const& rules, expr_ref_vector& result, unsigned level) {
bool_rewriter br(m);
rule_set::decl2rules::iterator it = rules.begin_grouped_rules();
@ -405,16 +405,16 @@ namespace datalog {
for (; it != end; ++it) {
func_decl* p = it->m_key;
rule_vector const& rls = *it->m_value;
// Assert: p_level(vars) => r1_level(vars) \/ r2_level(vars) \/ r3_level(vars) \/ ...
// Assert: r_i_level(vars) => exists aux_vars . body of rule i for level
// Assert: r_i_level(vars) => exists aux_vars . body of rule i for level
func_decl_ref level_pred = mk_level_predicate(p, level);
expr_ref_vector rules(m);
expr_ref body(m), head(m);
for (unsigned i = 0; i < rls.size(); ++i) {
rule& r = *rls[i];
func_decl_ref rule_i = mk_level_rule(p, i, level);
for (unsigned i = 0; i < rls.size(); ++i) {
rule& r = *rls[i];
func_decl_ref rule_i = mk_level_rule(p, i, level);
rules.push_back(apply_vars(rule_i));
ptr_vector<sort> rule_vars;
@ -440,10 +440,10 @@ namespace datalog {
head = m.mk_app(rule_i, args.size(), args.c_ptr());
for (unsigned i = 0; i < r.get_tail_size(); ++i) {
conjs.push_back(r.get_tail(i));
}
}
br.mk_and(conjs.size(), conjs.c_ptr(), body);
replace_by_level_predicates(level, body);
replace_by_level_predicates(level, body);
body = skolemize_vars(r, args, rule_vars, body);
body = m.mk_implies(head, body);
body = bind_vars(body, head);
@ -496,7 +496,7 @@ namespace datalog {
// find the rule that was triggered by evaluating the arguments to prop.
rule_vector const& rls = b.m_rules.get_predicate_rules(pred);
rule* r = 0;
for (unsigned i = 0; i < rls.size(); ++i) {
for (unsigned i = 0; i < rls.size(); ++i) {
func_decl_ref rule_i = mk_level_rule(pred, i, level);
TRACE("bmc", rls[i]->display(b.m_ctx, tout << "Checking rule " << mk_pp(rule_i, m) << " "););
prop_r = m.mk_app(rule_i, prop->get_num_args(), prop->get_args());
@ -537,7 +537,7 @@ namespace datalog {
prs.push_back(get_proof(md, head_j, to_app(prop_body), level-1));
positions.push_back(std::make_pair(j+1,0));
substs.push_back(expr_ref_vector(m));
}
}
pr = m.mk_hyper_resolve(sz+1, prs.c_ptr(), prop, positions, substs);
return pr;
}
@ -557,16 +557,16 @@ namespace datalog {
func_decl_ref mk_level_predicate(func_decl* p, unsigned level) {
std::stringstream _name;
_name << p->get_name() << "#" << level;
symbol nm(_name.str().c_str());
symbol nm(_name.str().c_str());
return func_decl_ref(m.mk_func_decl(nm, p->get_arity(), p->get_domain(), m.mk_bool_sort()), m);
}
func_decl_ref mk_level_rule(func_decl* p, unsigned rule_idx, unsigned level) {
std::stringstream _name;
_name << "rule:" << p->get_name() << "#" << level << "_" << rule_idx;
symbol nm(_name.str().c_str());
symbol nm(_name.str().c_str());
return func_decl_ref(m.mk_func_decl(nm, p->get_arity(), p->get_domain(), m.mk_bool_sort()), m);
}
}
expr_ref apply_vars(func_decl* p) {
expr_ref_vector vars(m);
@ -617,7 +617,7 @@ namespace datalog {
func_decl_ref mk_body_func(rule& r, ptr_vector<sort> const& args, unsigned index, sort* s) {
std::stringstream _name;
_name << r.get_decl()->get_name() << "@" << index;
symbol name(_name.str().c_str());
symbol name(_name.str().c_str());
func_decl* f = m.mk_func_decl(name, args.size(), args.c_ptr(), s);
return func_decl_ref(f, m);
}
@ -689,16 +689,16 @@ namespace datalog {
struct level_replacer_cfg : public default_rewriter_cfg {
level_replacer m_r;
level_replacer_cfg(nonlinear& nl, unsigned level):
level_replacer_cfg(nonlinear& nl, unsigned level):
m_r(nl, level) {}
bool rewrite_patterns() const { return false; }
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
return m_r.mk_app_core(f, num, args, result);
}
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) {
@ -725,9 +725,9 @@ namespace datalog {
fml = tmp;
}
};
// --------------------------------------------------------------------------
// Basic non-linear BMC based on compiling into data-types (it is inefficient)
@ -747,7 +747,7 @@ namespace datalog {
setup();
declare_datatypes();
compile();
return check_query();
return check_query();
}
private:
@ -765,7 +765,7 @@ namespace datalog {
func_decl_ref mk_predicate(func_decl* pred) {
std::stringstream _name;
_name << pred->get_name() << "#";
symbol nm(_name.str().c_str());
symbol nm(_name.str().c_str());
sort* pred_trace_sort = m_pred2sort.find(pred);
return func_decl_ref(m.mk_func_decl(nm, pred_trace_sort, m_path_sort, m.mk_bool_sort()), m);
}
@ -773,30 +773,30 @@ namespace datalog {
func_decl_ref mk_rule(func_decl* p, unsigned rule_idx) {
std::stringstream _name;
_name << "rule:" << p->get_name() << "#" << rule_idx;
symbol nm(_name.str().c_str());
symbol nm(_name.str().c_str());
sort* pred_trace_sort = m_pred2sort.find(p);
return func_decl_ref(m.mk_func_decl(nm, pred_trace_sort, m_path_sort, m.mk_bool_sort()), m);
return func_decl_ref(m.mk_func_decl(nm, pred_trace_sort, m_path_sort, m.mk_bool_sort()), m);
}
expr_ref mk_var(func_decl* pred, sort*s, unsigned idx, expr* path_arg, expr* trace_arg) {
std::stringstream _name;
_name << pred->get_name() << "#V_" << idx;
symbol nm(_name.str().c_str());
symbol nm(_name.str().c_str());
func_decl_ref fn(m);
fn = m.mk_func_decl(nm, m_pred2sort.find(pred), m_path_sort, s);
return expr_ref(m.mk_app(fn, trace_arg, path_arg), m);
}
expr_ref mk_arg(func_decl* pred, unsigned idx, expr* path_arg, expr* trace_arg) {
SASSERT(idx < pred->get_arity());
std::stringstream _name;
_name << pred->get_name() << "#X_" << idx;
symbol nm(_name.str().c_str());
symbol nm(_name.str().c_str());
func_decl_ref fn(m);
fn = m.mk_func_decl(nm, m_pred2sort.find(pred), m_path_sort, pred->get_domain(idx));
return expr_ref(m.mk_app(fn, trace_arg, path_arg), m);
}
void mk_subst(datalog::rule& r, expr* path, app* trace, expr_ref_vector& sub) {
datatype_util dtu(m);
ptr_vector<sort> sorts;
@ -840,52 +840,52 @@ namespace datalog {
}
}
}
/**
\brief compile Horn rule into co-Horn implication.
forall args . R(path_var, rule_i(trace_vars)) => Body[X(path_var, rule_i(trace_vars)), Y(S_j(path_var), trace_vars_j)]
*/
*/
void compile() {
datatype_util dtu(m);
rule_set::decl2rules::iterator it = b.m_rules.begin_grouped_rules();
rule_set::decl2rules::iterator end = b.m_rules.end_grouped_rules();
for (; it != end; ++it) {
func_decl* p = it->m_key;
rule_vector const& rls = *it->m_value;
// Assert: p_level => r1_level \/ r2_level \/ r3_level \/ ...
// where: r_i_level = body of rule i for level + equalities for head of rule i
expr_ref rule_body(m), tmp(m), pred(m), trace_arg(m), fml(m);
var_ref path_var(m), trace_var(m);
expr_ref_vector rules(m), sub(m), conjs(m), vars(m), patterns(m);
sort* pred_sort = m_pred2sort.find(p);
path_var = m.mk_var(0, m_path_sort);
trace_var = m.mk_var(1, pred_sort);
trace_var = m.mk_var(1, pred_sort);
// sort* sorts[2] = { pred_sort, m_path_sort };
ptr_vector<func_decl> const& cnstrs = *dtu.get_datatype_constructors(pred_sort);
ptr_vector<func_decl> const& succs = *dtu.get_datatype_constructors(m_path_sort);
SASSERT(cnstrs.size() == rls.size());
pred = m.mk_app(mk_predicate(p), trace_var.get(), path_var.get());
for (unsigned i = 0; i < rls.size(); ++i) {
sub.reset();
for (unsigned i = 0; i < rls.size(); ++i) {
sub.reset();
conjs.reset();
vars.reset();
rule& r = *rls[i];
rule& r = *rls[i];
func_decl_ref rule_pred_i = mk_rule(p, i);
// Create cnstr_rule_i(Vars)
func_decl* cnstr = cnstrs[i];
rules.push_back(m.mk_app(rule_pred_i, trace_var.get(), path_var.get()));
unsigned arity = cnstr->get_arity();
for (unsigned j = 0; j < arity; ++j) {
vars.push_back(m.mk_var(arity-j,cnstr->get_domain(j)));
vars.push_back(m.mk_var(arity-j,cnstr->get_domain(j)));
}
trace_arg = m.mk_app(cnstr, vars.size(), vars.c_ptr());
mk_subst(r, path_var, to_app(trace_arg), sub);
// apply substitution to body.
var_subst vs(m, false);
for (unsigned k = 0; k < p->get_arity(); ++k) {
@ -926,28 +926,28 @@ namespace datalog {
names.push_back(symbol("path"));
SASSERT(names.size() == q_sorts.size());
SASSERT(vars.size() == names.size());
symbol qid = r.name(), skid;
symbol qid = r.name(), skid;
tmp = m.mk_app(mk_predicate(p), trace_arg.get(), path_var.get());
patterns.reset();
patterns.push_back(m.mk_pattern(to_app(tmp)));
fml = m.mk_implies(tmp, rule_body);
fml = m.mk_forall(vars.size(), q_sorts.c_ptr(), names.c_ptr(), fml, 1, qid, skid, 1, patterns.c_ptr());
b.assert_expr(fml);
b.assert_expr(fml);
}
}
}
}
void declare_datatypes() {
rule_set::decl2rules::iterator it = b.m_rules.begin_grouped_rules();
rule_set::decl2rules::iterator end = b.m_rules.end_grouped_rules();
datatype_util dtu(m);
ptr_vector<datatype_decl> dts;
obj_map<func_decl, unsigned> pred_idx;
for (unsigned i = 0; it != end; ++it, ++i) {
pred_idx.insert(it->m_key, i);
}
it = b.m_rules.begin_grouped_rules();
for (; it != end; ++it) {
rule_vector const& rls = *it->m_value;
@ -971,27 +971,27 @@ namespace datalog {
_name << "?";
symbol is_name(_name.str().c_str());
cnstrs.push_back(mk_constructor_decl(name, is_name, accs.size(), accs.c_ptr()));
}
}
dts.push_back(mk_datatype_decl(pred->get_name(), cnstrs.size(), cnstrs.c_ptr()));
}
sort_ref_vector new_sorts(m);
family_id dfid = m.mk_family_id("datatype");
datatype_decl_plugin* dtp = static_cast<datatype_decl_plugin*>(m.get_plugin(dfid));
VERIFY (dtp->mk_datatypes(dts.size(), dts.c_ptr(), new_sorts));
it = b.m_rules.begin_grouped_rules();
for (unsigned i = 0; it != end; ++it, ++i) {
for (unsigned i = 0; it != end; ++it, ++i) {
m_pred2sort.insert(it->m_key, new_sorts[i].get());
m_sort2pred.insert(new_sorts[i].get(), it->m_key);
m_pinned.push_back(new_sorts[i].get());
m_pinned.push_back(new_sorts[i].get());
}
if (new_sorts.size() > 0) {
TRACE("bmc", dtu.display_datatype(new_sorts[0].get(), tout););
}
del_datatype_decls(dts.size(), dts.c_ptr());
// declare path data-type.
{
new_sorts.reset();
@ -1004,9 +1004,9 @@ namespace datalog {
rule* r = *it;
unsigned sz = r->get_uninterpreted_tail_size();
max_arity = std::max(sz, max_arity);
}
}
cnstrs.push_back(mk_constructor_decl(symbol("Z#"), symbol("Z#?"), 0, 0));
for (unsigned i = 0; i + 1 < max_arity; ++i) {
std::stringstream _name;
_name << "succ#" << i;
@ -1019,13 +1019,13 @@ namespace datalog {
type_ref tr(0);
accs.push_back(mk_accessor_decl(name, tr));
cnstrs.push_back(mk_constructor_decl(name, is_name, accs.size(), accs.c_ptr()));
}
}
dts.push_back(mk_datatype_decl(symbol("Path"), cnstrs.size(), cnstrs.c_ptr()));
VERIFY (dtp->mk_datatypes(dts.size(), dts.c_ptr(), new_sorts));
m_path_sort = new_sorts[0].get();
}
}
proof_ref get_proof(model_ref& md, app* trace, app* path) {
datatype_util dtu(m);
rule_manager& rm = b.m_ctx.get_rule_manager();
@ -1044,7 +1044,7 @@ namespace datalog {
proof_ref pr(m);
expr_ref fml(m), head(m), tmp(m);
app_ref path1(m);
var_subst vs(m, false);
mk_subst(*rules[i], path, trace, sub);
rm.to_formula(*rules[i], fml);
@ -1061,30 +1061,30 @@ namespace datalog {
rule_ref rl(b.m_ctx.get_rule_manager());
rl = rules[i];
b.m_ctx.get_rule_manager().substitute(rl, sub.size(), sub.c_ptr());
substs.push_back(sub);
for (unsigned j = 0; j < sz; ++j) {
if (j == 0) {
path1 = path;
path1 = path;
}
else {
path1 = m.mk_app(succs[j], path);
}
prs.push_back(get_proof(md, to_app(trace->get_arg(j)), path1));
positions.push_back(std::make_pair(j+1,0));
substs.push_back(expr_ref_vector(m));
substs.push_back(expr_ref_vector(m));
}
head = rl->get_head();
pr = m.mk_hyper_resolve(sz+1, prs.c_ptr(), head, positions, substs);
pr = m.mk_hyper_resolve(sz+1, prs.c_ptr(), head, positions, substs);
return pr;
}
}
UNREACHABLE();
return proof_ref(0, m);
}
// instantiation of algebraic data-types takes care of the rest.
lbool check_query() {
sort* trace_sort = m_pred2sort.find(b.m_query_pred);
@ -1102,10 +1102,10 @@ namespace datalog {
}
b.m_solver.get_model(md);
mk_answer(md, trace, path);
return l_true;
return l_true;
}
}
bool check_model(model_ref& md, expr* trace) {
expr_ref trace_val(m), eq(m);
md->eval(trace, trace_val);
@ -1122,10 +1122,10 @@ namespace datalog {
eq = m.mk_not(eq);
b.assert_expr(eq);
}
return is_sat != l_false;
return is_sat != l_false;
}
void mk_answer(model_ref& md, expr_ref& trace, expr_ref& path) {
void mk_answer(model_ref& md, expr_ref& trace, expr_ref& path) {
IF_VERBOSE(2, model_smt2_pp(verbose_stream(), m, *md, 0););
md->eval(trace, trace);
md->eval(path, path);
@ -1139,7 +1139,7 @@ namespace datalog {
apply(m, b.m_ctx.get_proof_converter().get(), pr);
b.m_answer = pr;
}
};
// --------------------------------------------------------------------------
@ -1155,7 +1155,7 @@ namespace datalog {
lbool check() {
setup();
for (unsigned i = 0; ; ++i) {
IF_VERBOSE(1, verbose_stream() << "level: " << i << "\n";);
IF_VERBOSE(1, verbose_stream() << "level: " << i << "\n";);
b.checkpoint();
compile(i);
lbool res = check(i);
@ -1183,9 +1183,9 @@ namespace datalog {
b.m_solver.get_model(md);
func_decl* pred = b.m_query_pred;
SASSERT(m.is_true(md->get_const_interp(to_app(level_query)->get_decl())));
TRACE("bmc", model_smt2_pp(tout, m, *md, 0););
rule_ref r0(rm), r1(rm), r2(rm);
while (true) {
TRACE("bmc", tout << "Predicate: " << pred->get_name() << "\n";);
@ -1193,7 +1193,7 @@ namespace datalog {
rule_vector const& rls = b.m_rules.get_predicate_rules(pred);
rule* r = 0;
unsigned i = 0;
for (; i < rls.size(); ++i) {
for (; i < rls.size(); ++i) {
expr_ref rule_i = mk_level_rule(pred, i, level);
TRACE("bmc", rls[i]->display(b.m_ctx, tout << "Checking rule " << mk_pp(rule_i, m) << " "););
if (m.is_true(md->get_const_interp(to_app(rule_i)->get_decl()))) {
@ -1204,13 +1204,13 @@ namespace datalog {
SASSERT(r);
mk_rule_vars(*r, level, i, sub);
// we have rule, we have variable names of rule.
// extract values for the variables in the rule.
for (unsigned j = 0; j < sub.size(); ++j) {
expr* vl = md->get_const_interp(to_app(sub[j].get())->get_decl());
if (vl) {
// vl can be 0 if the interpretation does not assign a value to it.
sub[j] = vl;
sub[j] = vl;
}
else {
sub[j] = m.mk_var(j, m.get_sort(sub[j].get()));
@ -1219,7 +1219,7 @@ namespace datalog {
svector<std::pair<unsigned, unsigned> > positions;
vector<expr_ref_vector> substs;
expr_ref fml(m), concl(m);
rm.to_formula(*r, fml);
r2 = r;
rm.substitute(r2, sub.size(), sub.c_ptr());
@ -1239,12 +1239,12 @@ namespace datalog {
apply_subst(sub, sub2);
unifier.apply(*r0.get(), 0, *r2.get(), r1);
rm.to_formula(*r1.get(), concl);
scoped_proof _sp(m);
proof* premises[2] = { pr, p };
positions.push_back(std::make_pair(0, 1));
substs.push_back(sub1);
substs.push_back(sub);
pr = m.mk_hyper_resolve(2, premises, concl, positions, substs);
@ -1263,7 +1263,7 @@ namespace datalog {
}
r0 = r2;
}
if (level == 0) {
SASSERT(r->get_uninterpreted_tail_size() == 0);
break;
@ -1276,8 +1276,8 @@ namespace datalog {
apply(m, b.m_ctx.get_proof_converter().get(), pr);
b.m_answer = pr;
}
void setup() {
b.m_fparams.m_relevancy_lvl = 0;
b.m_fparams.m_model = true;
@ -1285,54 +1285,54 @@ namespace datalog {
b.m_fparams.m_mbqi = false;
// m_fparams.m_auto_config = false;
}
lbool check(unsigned level) {
expr_ref level_query = mk_level_predicate(b.m_query_pred, level);
expr* q = level_query.get();
return b.m_solver.check(1, &q);
}
expr_ref mk_level_predicate(func_decl* p, unsigned level) {
return mk_level_predicate(p->get_name(), level);
}
expr_ref mk_level_predicate(symbol const& name, unsigned level) {
std::stringstream _name;
_name << name << "#" << level;
symbol nm(_name.str().c_str());
symbol nm(_name.str().c_str());
return expr_ref(m.mk_const(nm, m.mk_bool_sort()), m);
}
expr_ref mk_level_arg(func_decl* pred, unsigned idx, unsigned level) {
SASSERT(idx < pred->get_arity());
std::stringstream _name;
_name << pred->get_name() << "#" << level << "_" << idx;
symbol nm(_name.str().c_str());
symbol nm(_name.str().c_str());
return expr_ref(m.mk_const(nm, pred->get_domain(idx)), m);
}
expr_ref mk_level_var(func_decl* pred, sort* s, unsigned rule_id, unsigned idx, unsigned level) {
std::stringstream _name;
_name << pred->get_name() << "#" << level << "_" << rule_id << "_" << idx;
symbol nm(_name.str().c_str());
symbol nm(_name.str().c_str());
return expr_ref(m.mk_const(nm, s), m);
}
expr_ref mk_level_rule(func_decl* p, unsigned rule_idx, unsigned level) {
std::stringstream _name;
_name << "rule:" << p->get_name() << "#" << level << "_" << rule_idx;
symbol nm(_name.str().c_str());
symbol nm(_name.str().c_str());
return expr_ref(m.mk_const(nm, m.mk_bool_sort()), m);
}
void mk_rule_vars(rule& r, unsigned level, unsigned rule_id, expr_ref_vector& sub) {
ptr_vector<sort> sorts;
r.get_vars(m, sorts);
// populate substitution of bound variables.
sub.reset();
sub.resize(sorts.size());
for (unsigned k = 0; k < r.get_decl()->get_arity(); ++k) {
expr* arg = r.get_head()->get_arg(k);
if (is_var(arg)) {
@ -1361,34 +1361,34 @@ namespace datalog {
}
}
}
void compile(unsigned level) {
rule_set::decl2rules::iterator it = b.m_rules.begin_grouped_rules();
rule_set::decl2rules::iterator end = b.m_rules.end_grouped_rules();
for (; it != end; ++it) {
func_decl* p = it->m_key;
rule_vector const& rls = *it->m_value;
// Assert: p_level => r1_level \/ r2_level \/ r3_level \/ ...
// Assert: r_i_level => body of rule i for level + equalities for head of rule i
expr_ref level_pred = mk_level_predicate(p, level);
expr_ref_vector rules(m), sub(m), conjs(m);
expr_ref rule_body(m), tmp(m);
for (unsigned i = 0; i < rls.size(); ++i) {
sub.reset();
for (unsigned i = 0; i < rls.size(); ++i) {
sub.reset();
conjs.reset();
rule& r = *rls[i];
expr_ref rule_i = mk_level_rule(p, i, level);
rule& r = *rls[i];
expr_ref rule_i = mk_level_rule(p, i, level);
rules.push_back(rule_i);
if (level == 0 && r.get_uninterpreted_tail_size() > 0) {
tmp = m.mk_not(rule_i);
b.assert_expr(tmp);
continue;
}
mk_rule_vars(r, level, i, sub);
// apply substitution to body.
var_subst vs(m, false);
for (unsigned k = 0; k < p->get_arity(); ++k) {
@ -1418,11 +1418,11 @@ namespace datalog {
}
}
};
bmc::bmc(context& ctx):
bmc::bmc(context& ctx):
engine_base(ctx.get_manager(), "bmc"),
m_ctx(ctx),
m(ctx.get_manager()),
m_ctx(ctx),
m(ctx.get_manager()),
m_solver(m, m_fparams),
m_rules(ctx),
m_query_pred(m),
@ -1440,9 +1440,9 @@ namespace datalog {
rule_set& rules0 = m_ctx.get_rules();
datalog::rule_set old_rules(rules0);
rule_manager.mk_query(query, rules0);
expr_ref bg_assertion = m_ctx.get_background_assertion();
expr_ref bg_assertion = m_ctx.get_background_assertion();
apply_default_transformation(m_ctx);
if (m_ctx.xform_slice()) {
datalog::rule_transformer transformer(m_ctx);
datalog::mk_slice* slice = alloc(datalog::mk_slice, m_ctx);
@ -1490,7 +1490,7 @@ namespace datalog {
}
}
void bmc::assert_expr(expr* e) {
void bmc::assert_expr(expr* e) {
TRACE("bmc", tout << mk_pp(e, m) << "\n";);
m_solver.assert_expr(e);
}
@ -1510,7 +1510,7 @@ namespace datalog {
void bmc::checkpoint() {
if (m.canceled()) {
throw default_exception("bmc canceled");
throw default_exception(Z3_CANCELED_MSG);
}
}
@ -1526,7 +1526,7 @@ namespace datalog {
m_solver.reset_statistics();
}
expr_ref bmc::get_answer() {
expr_ref bmc::get_answer() {
return m_answer;
}

View file

@ -62,7 +62,7 @@ namespace Duality {
context ctx;
RPFP::LogicSolver *ls;
RPFP *rpfp;
DualityStatus status;
std::vector<expr> clauses;
std::vector<std::vector<RPFP::label_struct> > clause_labels;
@ -104,14 +104,14 @@ namespace Duality {
//
// Check if the new rules are weaker so that we can
// Check if the new rules are weaker so that we can
// re-use existing context.
//
//
#if 0
void dl_interface::check_reset() {
// TODO
datalog::rule_ref_vector const& new_rules = m_ctx.get_rules().get_rules();
datalog::rule_ref_vector const& old_rules = m_old_rules.get_rules();
datalog::rule_ref_vector const& old_rules = m_old_rules.get_rules();
bool is_subsumed = !old_rules.empty();
for (unsigned i = 0; is_subsumed && i < new_rules.size(); ++i) {
is_subsumed = false;
@ -155,7 +155,7 @@ namespace Duality {
expr_ref_vector rules(m_ctx.get_manager());
svector< ::symbol> names;
svector< ::symbol> names;
unsigned_vector bounds;
// m_ctx.get_rules_as_formulas(rules, names);
@ -189,7 +189,7 @@ namespace Duality {
rules.push_back(f);
}
}
else
else
m_ctx.get_raw_rule_formulas(rules, names, bounds);
// get all the rules as clauses
@ -199,7 +199,7 @@ namespace Duality {
expr e(_d->ctx,rules[i].get());
clauses.push_back(e);
}
std::vector<sort> b_sorts;
std::vector<symbol> b_names;
used_vars uv;
@ -216,7 +216,7 @@ namespace Duality {
#if 0
// turn the query into a clause
expr q(_d->ctx,m_ctx.bind_variables(query,false));
std::vector<sort> b_sorts;
std::vector<symbol> b_names;
if (q.is_quantifier() && !q.is_quantifier_forall()) {
@ -235,14 +235,14 @@ namespace Duality {
qc = _d->ctx.make_quant(Forall,b_sorts,b_names,qc);
clauses.push_back(qc);
bounds.push_back(UINT_MAX);
// get the background axioms
unsigned num_asserts = m_ctx.get_num_assertions();
for (unsigned i = 0; i < num_asserts; ++i) {
expr e(_d->ctx,m_ctx.get_assertion(i));
_d->rpfp->AssertAxiom(e);
}
// make sure each predicate is the head of at least one clause
func_decl_set heads;
for(unsigned i = 0; i < clauses.size(); i++){
@ -297,14 +297,14 @@ namespace Duality {
// populate the edge-to-clause map
for(unsigned i = 0; i < _d->rpfp->edges.size(); ++i)
_d->map[_d->rpfp->edges[i]] = i;
// create a solver object
Solver *rs = Solver::Create("duality", _d->rpfp);
if(old_rs)
rs->LearnFrom(old_rs); // new solver gets hints from old solver
// set its options
IF_VERBOSE(1, rs->SetOption("report","1"););
rs->SetOption("full_expand",m_ctx.get_params().duality_full_expand() ? "1" : "0");
@ -328,12 +328,12 @@ namespace Duality {
ans = rs->Solve();
}
catch (Duality::solver::cancel_exception &exn){
throw default_exception("duality canceled");
throw default_exception(Z3_CANCELED_MSG);
}
catch (Duality::Solver::Incompleteness &exn){
throw default_exception("incompleteness");
}
// profile!
if(m_ctx.get_params().duality_profile())
@ -343,7 +343,7 @@ namespace Duality {
_d->status = ans ? StatusModel : StatusRefutation;
_d->cex.swap(rs->GetCounterexample()); // take ownership of cex
_d->old_rs = rs; // save this for later hints
if(old_data){
dealloc(old_data); // this deallocates the old solver if there is one
}
@ -392,7 +392,7 @@ namespace Duality {
context &ctx = d->dd()->ctx;
RPFP::Node &node = *root;
RPFP::Edge &edge = *node.Outgoing;
// first, prove the children (that are actually used)
for(unsigned i = 0; i < edge.Children.size(); i++){
@ -434,19 +434,19 @@ namespace Duality {
}
}
out << " )\n";
out << " (labels";
std::vector<symbol> labels;
tree->GetLabels(&edge,labels);
for(unsigned j = 0; j < labels.size(); j++){
out << " " << labels[j];
}
out << " )\n";
// reference the proofs of all the children, in syntactic order
// "true" means the child is not needed
out << " (ref ";
for(unsigned i = 0; i < edge.Children.size(); i++){
if(!tree->Empty(edge.Children[i]))
@ -468,7 +468,7 @@ namespace Duality {
ast_manager &m = m_ctx.get_manager();
model_ref md = get_model();
out << "(fixedpoint \n";
model_smt2_pp(out, m, *md.get(), 0);
model_smt2_pp(out, m, *md.get(), 0);
out << ")\n";
}
else if(_d->status == StatusRefutation){
@ -550,22 +550,22 @@ namespace Duality {
}
return md;
}
static proof_ref extract_proof(dl_interface *d, RPFP *tree, RPFP::Node *root) {
context &ctx = d->dd()->ctx;
ast_manager &mgr = ctx.m();
RPFP::Node &node = *root;
RPFP::Edge &edge = *node.Outgoing;
RPFP::Edge *orig_edge = edge.map;
// first, prove the children (that are actually used)
proof_ref_vector prems(mgr);
::vector<expr_ref_vector> substs;
int orig_clause = d->dd()->map[orig_edge];
expr &t = d->dd()->clauses[orig_clause];
prems.push_back(mgr.mk_asserted(ctx.uncook(t)));
substs.push_back(expr_ref_vector(mgr));
if (t.is_quantifier() && t.is_quantifier_forall()) {
int bound = t.get_quantifier_num_bound();
@ -599,12 +599,12 @@ namespace Duality {
for(unsigned i = 0; i < edge.F.IndParams.size(); i++)
args.push_back(tree->Eval(&edge,edge.F.IndParams[i]));
expr conc = f(args);
::vector< ::proof *> pprems;
for(unsigned i = 0; i < prems.size(); i++)
pprems.push_back(prems[i].get());
proof_ref res(mgr.mk_hyper_resolve(pprems.size(),&pprems[0], ctx.uncook(conc), pos, substs),mgr);
return res;

File diff suppressed because it is too large Load diff