diff --git a/src/api/api_quant.cpp b/src/api/api_quant.cpp index 883e9e752..4170852a9 100644 --- a/src/api/api_quant.cpp +++ b/src/api/api_quant.cpp @@ -165,7 +165,10 @@ extern "C" { } for (unsigned i = 0; i < num_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()); names.push_back(of_symbol(s)); types.push_back(of_sort(mk_c(c)->m().get_sort(a))); diff --git a/src/ast/rewriter/ast_counter.cpp b/src/ast/rewriter/ast_counter.cpp index a807237c5..6f49a232f 100644 --- a/src/ast/rewriter/ast_counter.cpp +++ b/src/ast/rewriter/ast_counter.cpp @@ -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) { has_var = false; unsigned max_var = 0; + ptr_vector qs; while (!m_todo.empty()) { expr* e = m_todo.back(); m_todo.pop_back(); @@ -117,14 +118,7 @@ unsigned var_counter::get_max_var(bool& has_var) { m_visited.mark(e, true); switch(e->get_kind()) { case AST_QUANTIFIER: { - var_counter aux_counter; - 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; - } + qs.push_back(to_quantifier(e)); break; } case AST_VAR: { @@ -147,6 +141,20 @@ unsigned var_counter::get_max_var(bool& has_var) { } } 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; } diff --git a/src/muz_qe/dl_context.cpp b/src/muz_qe/dl_context.cpp index 9f250742c..7da9808e7 100644 --- a/src/muz_qe/dl_context.cpp +++ b/src/muz_qe/dl_context.cpp @@ -652,6 +652,7 @@ namespace datalog { if (check_pred(e)) { std::ostringstream out; out << "recursive predicate " << mk_ismt2_pp(e, get_manager()) << " occurs nested in body"; + r->display(*this, out << "\n"); throw default_exception(out.str()); } diff --git a/src/muz_qe/dl_rule.cpp b/src/muz_qe/dl_rule.cpp index 70da4ed4b..455f2c244 100644 --- a/src/muz_qe/dl_rule.cpp +++ b/src/muz_qe/dl_rule.cpp @@ -186,15 +186,20 @@ namespace datalog { } void rule_manager::mk_rule_core(expr* fml, proof* p, rule_set& rules, symbol const& name) { + DEBUG_CODE(ptr_vector sorts; + ::get_free_vars(fml, sorts); ); expr_ref_vector fmls(m); proof_ref_vector prs(m); m_hnf.reset(); m_hnf.set_name(name); + m_hnf(fml, p, fmls, prs); for (unsigned i = 0; i < m_hnf.get_fresh_predicates().size(); ++i) { m_ctx.register_predicate(m_hnf.get_fresh_predicates()[i], false); } for (unsigned i = 0; i < fmls.size(); ++i) { + DEBUG_CODE(ptr_vector sorts; + ::get_free_vars(fmls[i].get(), sorts); ); mk_horn_rule(fmls[i].get(), prs[i].get(), rules, name); } } @@ -265,7 +270,7 @@ namespace datalog { } else { head = ensure_app(fml); - } + } return index; } @@ -491,6 +496,12 @@ namespace datalog { app * * uninterp_tail = r->m_tail; //grows upwards app * * interp_tail = r->m_tail+n; //grows downwards + DEBUG_CODE(ptr_vector sorts; + ::get_free_vars(head, sorts); + for (unsigned i = 0; i < n; ++i) { + ::get_free_vars(tail[i], sorts); + }); + bool has_neg = false; for (unsigned i = 0; i < n; i++) { diff --git a/src/muz_qe/hnf.cpp b/src/muz_qe/hnf.cpp index 75a85061c..36316cfa6 100644 --- a/src/muz_qe/hnf.cpp +++ b/src/muz_qe/hnf.cpp @@ -128,7 +128,12 @@ public: } 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() { diff --git a/src/muz_qe/rel_context.cpp b/src/muz_qe/rel_context.cpp index ce1b30b88..d597500b2 100644 --- a/src/muz_qe/rel_context.cpp +++ b/src/muz_qe/rel_context.cpp @@ -105,14 +105,12 @@ namespace datalog { } } - lbool rel_context::saturate() { + lbool rel_context::saturate(scoped_query& sq) { m_context.ensure_closed(); bool time_limit = m_context.soft_timeout()!=0; unsigned remaining_time_limit = m_context.soft_timeout(); unsigned restart_time = m_context.initial_restart_timeout(); - - scoped_query scoped_query(m_context); - + instruction_block termination_code; lbool result; @@ -191,7 +189,7 @@ namespace datalog { else { restart_time = static_cast(new_restart_time); } - scoped_query.reset(); + sq.reset(); } m_context.record_transformed_rules(); TRACE("dl", display_profile(tout);); @@ -206,7 +204,7 @@ namespace datalog { } m_context.close(); reset_negated_tables(); - lbool res = saturate(); + lbool res = saturate(_scoped_query); switch(res) { case l_true: { @@ -215,7 +213,8 @@ namespace datalog { bool some_non_empty = num_rels == 0; bool is_approx = false; 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()) { some_non_empty = true; } @@ -272,13 +271,14 @@ namespace datalog { if (m_context.magic_sets_for_queries()) { 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); - lbool res = saturate(); - - if (res != l_undef) { + if (res != l_undef) { m_last_result_relation = get_relation(query_pred).clone(); if (m_last_result_relation->empty()) { res = l_false; diff --git a/src/muz_qe/rel_context.h b/src/muz_qe/rel_context.h index 057d1c15f..0b73caaa6 100644 --- a/src/muz_qe/rel_context.h +++ b/src/muz_qe/rel_context.h @@ -109,7 +109,7 @@ namespace datalog { void display_profile(std::ostream& out); - lbool saturate(); + lbool saturate(scoped_query& sq); }; };