diff --git a/src/ast/CMakeLists.txt b/src/ast/CMakeLists.txt index b0c9f7724..f14a28373 100644 --- a/src/ast/CMakeLists.txt +++ b/src/ast/CMakeLists.txt @@ -14,6 +14,7 @@ z3_add_component(ast ast_translation.cpp ast_util.cpp bv_decl_plugin.cpp + cached_var_subst.cpp char_decl_plugin.cpp datatype_decl_plugin.cpp decl_collector.cpp @@ -37,6 +38,7 @@ z3_add_component(ast occurs.cpp pb_decl_plugin.cpp pp.cpp + quantifier_stat.cpp recfun_decl_plugin.cpp reg_decl_plugins.cpp seq_decl_plugin.cpp diff --git a/src/ast/cached_var_subst.cpp b/src/ast/cached_var_subst.cpp new file mode 100644 index 000000000..93b7467bd --- /dev/null +++ b/src/ast/cached_var_subst.cpp @@ -0,0 +1,99 @@ +/*++ +Copyright (c) 2006 Microsoft Corporation + +Module Name: + + cached_var_subst.cpp + +Abstract: + + + +Author: + + Leonardo de Moura (leonardo) 2009-01-23. + +Revision History: + +--*/ +#include "ast/cached_var_subst.h" +#include "ast/rewriter/rewriter_def.h" + +bool cached_var_subst::key_eq_proc::operator()(cached_var_subst::key * k1, cached_var_subst::key * k2) const { + if (k1->m_qa != k2->m_qa) + return false; + if (k1->m_num_bindings != k2->m_num_bindings) + return false; + for (unsigned i = 0; i < k1->m_num_bindings; i++) + if (k1->m_bindings[i] != k2->m_bindings[i]) + return false; + return true; +} + +cached_var_subst::cached_var_subst(ast_manager & _m): + m(_m), + m_proc(m), + m_refs(m) { +} + +void cached_var_subst::reset() { + m_refs.reset(); + m_instances.reset(); + m_region.reset(); + m_new_keys.reset(); + m_key = nullptr; +} + +expr** cached_var_subst::operator()(quantifier* qa, unsigned num_bindings) { + m_new_keys.reserve(num_bindings+1, 0); + m_key = m_new_keys[num_bindings]; + if (m_key == nullptr) + m_key = static_cast(m_region.allocate(sizeof(key) + sizeof(expr*)*num_bindings)); + m_key->m_qa = qa; + m_key->m_num_bindings = num_bindings; + return m_key->m_bindings; +} + + +expr_ref cached_var_subst::operator()() { + expr_ref result(m); + + auto* entry = m_instances.insert_if_not_there3(m_key, nullptr); + unsigned num_bindings = m_key->m_num_bindings; + if (entry->get_data().m_key != m_key) { + SASSERT(entry->get_data().m_value != 0); + // entry was already there + m_new_keys[num_bindings] = m_key; // recycle key + result = entry->get_data().m_value; + SCTRACE("bindings", is_trace_enabled("coming_from_quant"), tout << "(cache)\n"; + for (unsigned i = 0; i < num_bindings; i++) + if (m_key->m_bindings[i]) + tout << i << ": " << mk_ismt2_pp(m_key->m_bindings[i], result.m()) << ";\n"; + tout.flush();); + return result; + } + + SASSERT(entry->get_data().m_value == 0); + try { + result = m_proc(m_key->m_qa->get_expr(), m_key->m_num_bindings, m_key->m_bindings); + } + catch (...) { + // CMW: The var_subst reducer was interrupted and m_instances is + // in an inconsistent state; we need to remove (m_key, 0). + m_instances.remove(m_key); + throw; + } + + // cache result + entry->get_data().m_value = result; + + // remove key from cache + m_new_keys[num_bindings] = nullptr; + + // increment reference counters + m_refs.push_back(m_key->m_qa); + for (unsigned i = 0; i < m_key->m_num_bindings; i++) + m_refs.push_back(m_key->m_bindings[i]); + m_refs.push_back(result); + return result; +} diff --git a/src/smt/cached_var_subst.h b/src/ast/cached_var_subst.h similarity index 87% rename from src/smt/cached_var_subst.h rename to src/ast/cached_var_subst.h index 54d462bf2..2675f46ce 100644 --- a/src/smt/cached_var_subst.h +++ b/src/ast/cached_var_subst.h @@ -20,7 +20,6 @@ Revision History: #include "ast/rewriter/var_subst.h" #include "util/map.h" -#include "smt/smt_enode.h" class cached_var_subst { struct key { @@ -37,14 +36,17 @@ class cached_var_subst { bool operator()(key * k1, key * k2) const; }; typedef map instances; + ast_manager& m; var_subst m_proc; expr_ref_vector m_refs; instances m_instances; region m_region; ptr_vector m_new_keys; // mapping from num_bindings -> next key + key* m_key { nullptr }; public: cached_var_subst(ast_manager & m); - void operator()(quantifier * qa, unsigned num_bindings, smt::enode * const * bindings, expr_ref & result); + expr** operator()(quantifier * qa, unsigned num_bindings); + expr_ref operator()(); void reset(); }; diff --git a/src/smt/smt_quantifier_stat.cpp b/src/ast/quantifier_stat.cpp similarity index 98% rename from src/smt/smt_quantifier_stat.cpp rename to src/ast/quantifier_stat.cpp index 78c0124c3..17efb11e9 100644 --- a/src/smt/smt_quantifier_stat.cpp +++ b/src/ast/quantifier_stat.cpp @@ -16,9 +16,9 @@ Author: Revision History: --*/ -#include "smt/smt_quantifier_stat.h" +#include "ast/quantifier_stat.h" -namespace smt { +namespace q { quantifier_stat::quantifier_stat(unsigned generation): m_size(0), diff --git a/src/smt/smt_quantifier_stat.h b/src/ast/quantifier_stat.h similarity index 98% rename from src/smt/smt_quantifier_stat.h rename to src/ast/quantifier_stat.h index ffa20cb43..45fd58530 100644 --- a/src/smt/smt_quantifier_stat.h +++ b/src/ast/quantifier_stat.h @@ -3,7 +3,7 @@ Copyright (c) 2006 Microsoft Corporation Module Name: - smt_quantifier_stat.h + quantifier_stat.h Abstract: @@ -23,7 +23,7 @@ Revision History: #include "util/approx_nat.h" #include "util/region.h" -namespace smt { +namespace q { /** \brief Store statistics for quantifiers. This information is diff --git a/src/smt/CMakeLists.txt b/src/smt/CMakeLists.txt index 6f414dd78..c9b6988cf 100644 --- a/src/smt/CMakeLists.txt +++ b/src/smt/CMakeLists.txt @@ -3,7 +3,6 @@ z3_add_component(smt arith_eq_adapter.cpp arith_eq_solver.cpp asserted_formulas.cpp - cached_var_subst.cpp cost_evaluator.cpp dyn_ack.cpp expr_context_simplifier.cpp @@ -45,7 +44,6 @@ z3_add_component(smt smt_model_generator.cpp smt_parallel.cpp smt_quantifier.cpp - smt_quantifier_stat.cpp smt_quick_checker.cpp smt_relevancy.cpp smt_setup.cpp diff --git a/src/smt/cached_var_subst.cpp b/src/smt/cached_var_subst.cpp deleted file mode 100644 index b2e3cccd1..000000000 --- a/src/smt/cached_var_subst.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - cached_var_subst.cpp - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2009-01-23. - -Revision History: - ---*/ -#include "smt/cached_var_subst.h" -#include "ast/rewriter/rewriter_def.h" - -bool cached_var_subst::key_eq_proc::operator()(cached_var_subst::key * k1, cached_var_subst::key * k2) const { - if (k1->m_qa != k2->m_qa) - return false; - if (k1->m_num_bindings != k2->m_num_bindings) - return false; - for (unsigned i = 0; i < k1->m_num_bindings; i++) - if (k1->m_bindings[i] != k2->m_bindings[i]) - return false; - return true; -} - -cached_var_subst::cached_var_subst(ast_manager & m): - m_proc(m), - m_refs(m) { -} - -void cached_var_subst::reset() { - m_refs.reset(); - m_instances.reset(); - m_region.reset(); - m_new_keys.reset(); -} - -void cached_var_subst::operator()(quantifier * qa, unsigned num_bindings, smt::enode * const * bindings, expr_ref & result) { - m_new_keys.reserve(num_bindings+1, 0); - key * new_key = m_new_keys[num_bindings]; - if (new_key == nullptr) - new_key = static_cast(m_region.allocate(sizeof(key) + sizeof(expr*)*num_bindings)); - - new_key->m_qa = qa; - new_key->m_num_bindings = num_bindings; - for (unsigned i = 0; i < num_bindings; i++) - new_key->m_bindings[i] = bindings[i]->get_owner(); - - auto* entry = m_instances.insert_if_not_there3(new_key, nullptr); - if (entry->get_data().m_key != new_key) { - SASSERT(entry->get_data().m_value != 0); - // entry was already there - m_new_keys[num_bindings] = new_key; // recycle key - result = entry->get_data().m_value; - SCTRACE("bindings", is_trace_enabled("coming_from_quant"),tout << "(cache)\n"; - for (unsigned i = 0; i < num_bindings; i++) { - if (new_key->m_bindings[i]) { - tout << i << ": " << mk_ismt2_pp(new_key->m_bindings[i], result.m()) << ";\n"; - } - } - tout.flush();); - return; - } - - SASSERT(entry->get_data().m_value == 0); - try { - result = m_proc(qa->get_expr(), new_key->m_num_bindings, new_key->m_bindings); - } - catch (...) { - // CMW: The var_subst reducer was interrupted and m_instances is - // in an inconsistent state; we need to remove (new_key, 0). - m_instances.remove(new_key); - throw; // Throw on to smt::qi_queue/smt::solver. - } - - // cache result - entry->get_data().m_value = result; - - // remove key from cache - m_new_keys[num_bindings] = 0; - - // increment reference counters - m_refs.push_back(qa); - for (unsigned i = 0; i < new_key->m_num_bindings; i++) - m_refs.push_back(new_key->m_bindings[i]); - m_refs.push_back(result); -} diff --git a/src/smt/qi_queue.cpp b/src/smt/qi_queue.cpp index 8cc9429a8..a7b03dc3e 100644 --- a/src/smt/qi_queue.cpp +++ b/src/smt/qi_queue.cpp @@ -98,8 +98,8 @@ namespace smt { m_parser.add_var("cs_factor"); } - quantifier_stat * qi_queue::set_values(quantifier * q, app * pat, unsigned generation, unsigned min_top_generation, unsigned max_top_generation, float cost) { - quantifier_stat * stat = m_qm.get_stat(q); + q::quantifier_stat * qi_queue::set_values(quantifier * q, app * pat, unsigned generation, unsigned min_top_generation, unsigned max_top_generation, float cost) { + q::quantifier_stat * stat = m_qm.get_stat(q); m_vals[COST] = cost; m_vals[MIN_TOP_GENERATION] = static_cast(min_top_generation); m_vals[MAX_TOP_GENERATION] = static_cast(max_top_generation); @@ -120,7 +120,7 @@ namespace smt { } float qi_queue::get_cost(quantifier * q, app * pat, unsigned generation, unsigned min_top_generation, unsigned max_top_generation) { - quantifier_stat * stat = set_values(q, pat, generation, min_top_generation, max_top_generation, 0); + q::quantifier_stat * stat = set_values(q, pat, generation, min_top_generation, max_top_generation, 0); float r = m_evaluator(m_cost_function, m_vals.size(), m_vals.c_ptr()); stat->update_max_cost(r); return r; @@ -206,7 +206,7 @@ namespace smt { TRACE("qi_queue_profile", tout << q->get_qid() << ", gen: " << generation << " " << *f << " cost: " << ent.m_cost << "\n";); - quantifier_stat * stat = m_qm.get_stat(q); + q::quantifier_stat * stat = m_qm.get_stat(q); if (m_checker.is_sat(q->get_expr(), num_bindings, bindings)) { TRACE("checker", tout << "instance already satisfied\n";); @@ -221,8 +221,10 @@ namespace smt { STRACE("instance", tout << "### " << static_cast(f) <<", " << q->get_qid() << "\n";); - expr_ref instance(m); - m_subst(q, num_bindings, bindings, instance); + auto* ebindings = m_subst(q, num_bindings); + for (unsigned i = 0; i < num_bindings; ++i) + ebindings[i] = bindings[i]->get_owner(); + expr_ref instance = m_subst(); TRACE("qi_queue", tout << "new instance:\n" << mk_pp(instance, m) << "\n";); TRACE("qi_queue_instance", tout << "new instance:\n" << mk_pp(instance, m) << "\n";); diff --git a/src/smt/qi_queue.h b/src/smt/qi_queue.h index 50ba2e1b9..7ea524b9e 100644 --- a/src/smt/qi_queue.h +++ b/src/smt/qi_queue.h @@ -19,14 +19,14 @@ Revision History: #pragma once #include "ast/ast.h" -#include "smt/smt_quantifier_stat.h" +#include "ast/cached_var_subst.h" +#include "ast/quantifier_stat.h" #include "smt/smt_checker.h" #include "smt/smt_quantifier.h" #include "smt/fingerprints.h" #include "smt/params/qi_params.h" #include "parsers/util/cost_parser.h" #include "smt/cost_evaluator.h" -#include "smt/cached_var_subst.h" #include "util/statistics.h" namespace smt { @@ -71,7 +71,7 @@ namespace smt { svector m_scopes; void init_parser_vars(); - quantifier_stat * set_values(quantifier * q, app * pat, unsigned generation, unsigned min_top_generation, unsigned max_top_generation, float cost); + q::quantifier_stat * set_values(quantifier * q, app * pat, unsigned generation, unsigned min_top_generation, unsigned max_top_generation, float cost); float get_cost(quantifier * q, app * pat, unsigned generation, unsigned min_top_generation, unsigned max_top_generation); unsigned get_new_gen(quantifier * q, unsigned generation, float cost); void instantiate(entry & ent); diff --git a/src/smt/smt_context.h b/src/smt/smt_context.h index 8f08d1607..2a13b29f3 100644 --- a/src/smt/smt_context.h +++ b/src/smt/smt_context.h @@ -18,6 +18,7 @@ Revision History: --*/ #pragma once +#include "ast/quantifier_stat.h" #include "smt/smt_clause.h" #include "smt/smt_setup.h" #include "smt/smt_enode.h" @@ -29,7 +30,6 @@ Revision History: #include "smt/smt_clause_proof.h" #include "smt/smt_theory.h" #include "smt/smt_quantifier.h" -#include "smt/smt_quantifier_stat.h" #include "smt/smt_statistics.h" #include "smt/smt_conflict_resolution.h" #include "smt/smt_relevancy.h" diff --git a/src/smt/smt_quantifier.cpp b/src/smt/smt_quantifier.cpp index 8de933c44..774906d05 100644 --- a/src/smt/smt_quantifier.cpp +++ b/src/smt/smt_quantifier.cpp @@ -18,9 +18,9 @@ Revision History: --*/ #include "ast/ast_pp.h" #include "ast/ast_ll_pp.h" +#include "ast/quantifier_stat.h" #include "smt/smt_quantifier.h" #include "smt/smt_context.h" -#include "smt/smt_quantifier_stat.h" #include "smt/smt_model_finder.h" #include "smt/smt_model_checker.h" #include "smt/smt_quick_checker.h" @@ -129,8 +129,8 @@ namespace smt { context & m_context; smt_params & m_params; qi_queue m_qi_queue; - obj_map m_quantifier_stat; - quantifier_stat_gen m_qstat_gen; + obj_map m_quantifier_stat; + q::quantifier_stat_gen m_qstat_gen; ptr_vector m_quantifiers; scoped_ptr m_plugin; unsigned m_num_instances; @@ -150,7 +150,7 @@ namespace smt { bool has_trace_stream() const { return m().has_trace_stream(); } std::ostream & trace_stream() { return m().trace_stream(); } - quantifier_stat * get_stat(quantifier * q) const { + q::quantifier_stat * get_stat(quantifier * q) const { return m_quantifier_stat.find(q); } @@ -159,7 +159,7 @@ namespace smt { } void add(quantifier * q, unsigned generation) { - quantifier_stat * stat = m_qstat_gen(q, generation); + q::quantifier_stat * stat = m_qstat_gen(q, generation); m_quantifier_stat.insert(q, stat); m_quantifiers.push_back(q); m_plugin->add(q); @@ -168,7 +168,7 @@ namespace smt { bool has_quantifiers() const { return !m_quantifiers.empty(); } void display_stats(std::ostream & out, quantifier * q) { - quantifier_stat * s = get_stat(q); + q::quantifier_stat * s = get_stat(q); unsigned num_instances = s->get_num_instances(); unsigned num_instances_simplify_true = s->get_num_instances_simplify_true(); unsigned num_instances_checker_sat = s->get_num_instances_checker_sat(); @@ -460,7 +460,7 @@ namespace smt { return m_imp->is_shared(n); } - quantifier_stat * quantifier_manager::get_stat(quantifier * q) const { + q::quantifier_stat * quantifier_manager::get_stat(quantifier * q) const { return m_imp->get_stat(q); } diff --git a/src/smt/smt_quantifier.h b/src/smt/smt_quantifier.h index abe84916b..4978797a6 100644 --- a/src/smt/smt_quantifier.h +++ b/src/smt/smt_quantifier.h @@ -19,6 +19,7 @@ Revision History: #pragma once #include "ast/ast.h" +#include "ast/quantifier_stat.h" #include "util/statistics.h" #include "util/params.h" #include "smt/smt_types.h" @@ -50,7 +51,7 @@ namespace smt { bool is_shared(enode * n) const; - quantifier_stat * get_stat(quantifier * q) const; + q::quantifier_stat * get_stat(quantifier * q) const; unsigned get_generation(quantifier * q) const; static void log_justification_to_root(std::ostream & log, enode *en, obj_hashtable &already_visited, context &ctx, ast_manager &m);