3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-17 19:36:17 +00:00

fix parameter checking on quantifiers (thanks to Esteban Pavese), fix query tracking in rel_context (thanks to Nuno Lopes), fix counter for free variables under quantfiers (thanks to Tomer Weiss)

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2013-08-22 15:00:52 -07:00
parent 0b56440cba
commit 5c145dcd4b
7 changed files with 50 additions and 22 deletions

View file

@ -165,7 +165,10 @@ extern "C" {
} }
for (unsigned i = 0; i < num_bound; ++i) { for (unsigned i = 0; i < num_bound; ++i) {
app* a = to_app(bound[i]); app* a = to_app(bound[i]);
SASSERT(a->get_kind() == AST_APP); if (a->get_kind() != AST_APP) {
SET_ERROR_CODE(Z3_INVALID_ARG);
RETURN_Z3(0);
}
symbol s(to_app(a)->get_decl()->get_name()); symbol s(to_app(a)->get_decl()->get_name());
names.push_back(of_symbol(s)); names.push_back(of_symbol(s));
types.push_back(of_sort(mk_c(c)->m().get_sort(a))); types.push_back(of_sort(mk_c(c)->m().get_sort(a)));

View file

@ -108,6 +108,7 @@ void var_counter::count_vars(ast_manager & m, const app * pred, int coef) {
unsigned var_counter::get_max_var(bool& has_var) { unsigned var_counter::get_max_var(bool& has_var) {
has_var = false; has_var = false;
unsigned max_var = 0; unsigned max_var = 0;
ptr_vector<quantifier> qs;
while (!m_todo.empty()) { while (!m_todo.empty()) {
expr* e = m_todo.back(); expr* e = m_todo.back();
m_todo.pop_back(); m_todo.pop_back();
@ -117,14 +118,7 @@ unsigned var_counter::get_max_var(bool& has_var) {
m_visited.mark(e, true); m_visited.mark(e, true);
switch(e->get_kind()) { switch(e->get_kind()) {
case AST_QUANTIFIER: { case AST_QUANTIFIER: {
var_counter aux_counter; qs.push_back(to_quantifier(e));
quantifier* q = to_quantifier(e);
bool has_var1 = false;
unsigned max_v = aux_counter.get_max_var(has_var1);
if (max_v > max_var + q->get_num_decls()) {
max_var = max_v - q->get_num_decls();
has_var = true;
}
break; break;
} }
case AST_VAR: { case AST_VAR: {
@ -147,6 +141,20 @@ unsigned var_counter::get_max_var(bool& has_var) {
} }
} }
m_visited.reset(); m_visited.reset();
while (!qs.empty()) {
var_counter aux_counter;
quantifier* q = qs.back();
qs.pop_back();
aux_counter.m_todo.push_back(q->get_expr());
bool has_var1 = false;
unsigned max_v = aux_counter.get_max_var(has_var1);
if (max_v >= max_var + q->get_num_decls()) {
max_var = max_v - q->get_num_decls();
has_var = has_var || has_var1;
}
}
return max_var; return max_var;
} }

View file

@ -652,6 +652,7 @@ namespace datalog {
if (check_pred(e)) { if (check_pred(e)) {
std::ostringstream out; std::ostringstream out;
out << "recursive predicate " << mk_ismt2_pp(e, get_manager()) << " occurs nested in body"; out << "recursive predicate " << mk_ismt2_pp(e, get_manager()) << " occurs nested in body";
r->display(*this, out << "\n");
throw default_exception(out.str()); throw default_exception(out.str());
} }

View file

@ -186,15 +186,20 @@ namespace datalog {
} }
void rule_manager::mk_rule_core(expr* fml, proof* p, rule_set& rules, symbol const& name) { void rule_manager::mk_rule_core(expr* fml, proof* p, rule_set& rules, symbol const& name) {
DEBUG_CODE(ptr_vector<sort> sorts;
::get_free_vars(fml, sorts); );
expr_ref_vector fmls(m); expr_ref_vector fmls(m);
proof_ref_vector prs(m); proof_ref_vector prs(m);
m_hnf.reset(); m_hnf.reset();
m_hnf.set_name(name); m_hnf.set_name(name);
m_hnf(fml, p, fmls, prs); m_hnf(fml, p, fmls, prs);
for (unsigned i = 0; i < m_hnf.get_fresh_predicates().size(); ++i) { for (unsigned i = 0; i < m_hnf.get_fresh_predicates().size(); ++i) {
m_ctx.register_predicate(m_hnf.get_fresh_predicates()[i], false); m_ctx.register_predicate(m_hnf.get_fresh_predicates()[i], false);
} }
for (unsigned i = 0; i < fmls.size(); ++i) { for (unsigned i = 0; i < fmls.size(); ++i) {
DEBUG_CODE(ptr_vector<sort> sorts;
::get_free_vars(fmls[i].get(), sorts); );
mk_horn_rule(fmls[i].get(), prs[i].get(), rules, name); mk_horn_rule(fmls[i].get(), prs[i].get(), rules, name);
} }
} }
@ -265,7 +270,7 @@ namespace datalog {
} }
else { else {
head = ensure_app(fml); head = ensure_app(fml);
} }
return index; return index;
} }
@ -491,6 +496,12 @@ namespace datalog {
app * * uninterp_tail = r->m_tail; //grows upwards app * * uninterp_tail = r->m_tail; //grows upwards
app * * interp_tail = r->m_tail+n; //grows downwards app * * interp_tail = r->m_tail+n; //grows downwards
DEBUG_CODE(ptr_vector<sort> sorts;
::get_free_vars(head, sorts);
for (unsigned i = 0; i < n; ++i) {
::get_free_vars(tail[i], sorts);
});
bool has_neg = false; bool has_neg = false;
for (unsigned i = 0; i < n; i++) { for (unsigned i = 0; i < n; i++) {

View file

@ -128,7 +128,12 @@ public:
} }
void set_name(symbol const& n) { void set_name(symbol const& n) {
m_name = n; if (n == symbol::null) {
m_name = symbol("P");
}
else {
m_name = n;
}
} }
func_decl_ref_vector const& get_fresh_predicates() { func_decl_ref_vector const& get_fresh_predicates() {

View file

@ -105,14 +105,12 @@ namespace datalog {
} }
} }
lbool rel_context::saturate() { lbool rel_context::saturate(scoped_query& sq) {
m_context.ensure_closed(); m_context.ensure_closed();
bool time_limit = m_context.soft_timeout()!=0; bool time_limit = m_context.soft_timeout()!=0;
unsigned remaining_time_limit = m_context.soft_timeout(); unsigned remaining_time_limit = m_context.soft_timeout();
unsigned restart_time = m_context.initial_restart_timeout(); unsigned restart_time = m_context.initial_restart_timeout();
scoped_query scoped_query(m_context);
instruction_block termination_code; instruction_block termination_code;
lbool result; lbool result;
@ -191,7 +189,7 @@ namespace datalog {
else { else {
restart_time = static_cast<unsigned>(new_restart_time); restart_time = static_cast<unsigned>(new_restart_time);
} }
scoped_query.reset(); sq.reset();
} }
m_context.record_transformed_rules(); m_context.record_transformed_rules();
TRACE("dl", display_profile(tout);); TRACE("dl", display_profile(tout););
@ -206,7 +204,7 @@ namespace datalog {
} }
m_context.close(); m_context.close();
reset_negated_tables(); reset_negated_tables();
lbool res = saturate(); lbool res = saturate(_scoped_query);
switch(res) { switch(res) {
case l_true: { case l_true: {
@ -215,7 +213,8 @@ namespace datalog {
bool some_non_empty = num_rels == 0; bool some_non_empty = num_rels == 0;
bool is_approx = false; bool is_approx = false;
for (unsigned i = 0; i < num_rels; ++i) { for (unsigned i = 0; i < num_rels; ++i) {
relation_base& rel = get_relation(rels[i]); func_decl* q = m_context.get_rules().get_pred(rels[i]);
relation_base& rel = get_relation(q);
if (!rel.empty()) { if (!rel.empty()) {
some_non_empty = true; some_non_empty = true;
} }
@ -272,13 +271,14 @@ namespace datalog {
if (m_context.magic_sets_for_queries()) { if (m_context.magic_sets_for_queries()) {
m_context.transform_rules(alloc(mk_magic_sets, m_context, query_pred)); m_context.transform_rules(alloc(mk_magic_sets, m_context, query_pred));
query_pred = m_context.get_rules().get_pred(query_pred);
} }
lbool res = saturate(_scoped_query);
query_pred = m_context.get_rules().get_pred(query_pred); query_pred = m_context.get_rules().get_pred(query_pred);
lbool res = saturate(); if (res != l_undef) {
if (res != l_undef) {
m_last_result_relation = get_relation(query_pred).clone(); m_last_result_relation = get_relation(query_pred).clone();
if (m_last_result_relation->empty()) { if (m_last_result_relation->empty()) {
res = l_false; res = l_false;

View file

@ -109,7 +109,7 @@ namespace datalog {
void display_profile(std::ostream& out); void display_profile(std::ostream& out);
lbool saturate(); lbool saturate(scoped_query& sq);
}; };
}; };