From 0d56499e2d96db8963f513e3a871c202b29ed70d Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 28 Aug 2013 21:20:24 -0700 Subject: [PATCH] re-organize muz_qe into separate units Signed-off-by: Nikolaj Bjorner --- scripts/mk_project.py | 13 +- src/api/api_datalog.cpp | 8 +- src/muz/{ => bmc}/dl_bmc_engine.cpp | 5 +- src/muz/{ => bmc}/dl_bmc_engine.h | 0 src/muz/{ => clp}/clp_context.cpp | 4 +- src/muz/{ => clp}/clp_context.h | 2 +- src/muz/dl_base.cpp | 459 ---- src/muz/dl_base.h | 1261 --------- src/muz/dl_bound_relation.cpp | 707 ----- src/muz/dl_bound_relation.h | 176 -- src/muz/dl_check_table.cpp | 439 --- src/muz/dl_check_table.h | 135 - src/muz/dl_cmds.h | 37 - src/muz/dl_context.cpp | 128 +- src/muz/dl_context.h | 100 +- src/muz/dl_engine_base.h | 82 + src/muz/dl_external_relation.cpp | 456 ---- src/muz/dl_external_relation.h | 154 -- src/muz/dl_finite_product_relation.cpp | 2377 ----------------- src/muz/dl_finite_product_relation.h | 366 --- src/muz/dl_interval_relation.cpp | 652 ----- src/muz/dl_interval_relation.h | 140 - src/muz/dl_mk_explanations.cpp | 880 ------ src/muz/dl_mk_explanations.h | 86 - src/muz/dl_mk_karr_invariants.cpp | 1114 -------- src/muz/dl_mk_karr_invariants.h | 138 - src/muz/dl_mk_partial_equiv.cpp | 154 -- src/muz/dl_mk_partial_equiv.h | 50 - src/muz/dl_mk_similarity_compressor.cpp | 545 ---- src/muz/dl_mk_similarity_compressor.h | 78 - src/muz/dl_mk_simple_joins.cpp | 741 ----- src/muz/dl_mk_simple_joins.h | 63 - src/muz/dl_product_relation.cpp | 1117 -------- src/muz/dl_product_relation.h | 190 -- src/muz/dl_relation_manager.cpp | 1702 ------------ src/muz/dl_relation_manager.h | 688 ----- src/muz/dl_sieve_relation.cpp | 666 ----- src/muz/dl_sieve_relation.h | 197 -- src/muz/dl_sparse_table.cpp | 1246 --------- src/muz/dl_sparse_table.h | 480 ---- src/muz/dl_table.cpp | 772 ------ src/muz/dl_table.h | 265 -- src/muz/dl_table_plugin.h | 193 -- src/muz/dl_table_relation.cpp | 490 ---- src/muz/dl_table_relation.h | 133 - src/muz/dl_util.cpp | 27 - src/muz/dl_util.h | 59 - src/muz/dl_vector_relation.h | 407 --- src/muz/{ => fp}/dl_cmds.cpp | 4 +- src/muz/fp/dl_register_engine.cpp | 51 + src/muz/fp/dl_register_engine.h | 36 + src/muz/{ => fp}/horn_tactic.cpp | 7 +- src/muz/{ => fp}/horn_tactic.h | 0 src/muz/{ => pdr}/pdr_context.cpp | 0 src/muz/{ => pdr}/pdr_context.h | 1 - src/muz/{ => pdr}/pdr_dl_interface.cpp | 4 +- src/muz/{ => pdr}/pdr_dl_interface.h | 1 + src/muz/{ => pdr}/pdr_farkas_learner.cpp | 0 src/muz/{ => pdr}/pdr_farkas_learner.h | 0 src/muz/{ => pdr}/pdr_generalizers.cpp | 2 +- src/muz/{ => pdr}/pdr_generalizers.h | 0 src/muz/{ => pdr}/pdr_manager.cpp | 0 src/muz/{ => pdr}/pdr_manager.h | 0 src/muz/{ => pdr}/pdr_prop_solver.cpp | 0 src/muz/{ => pdr}/pdr_prop_solver.h | 0 src/muz/{ => pdr}/pdr_reachable_cache.cpp | 0 src/muz/{ => pdr}/pdr_reachable_cache.h | 0 src/muz/{ => pdr}/pdr_smt_context_manager.cpp | 0 src/muz/{ => pdr}/pdr_smt_context_manager.h | 0 src/muz/{ => pdr}/pdr_sym_mux.cpp | 0 src/muz/{ => pdr}/pdr_sym_mux.h | 0 src/muz/{ => pdr}/pdr_util.cpp | 0 src/muz/{ => pdr}/pdr_util.h | 0 src/muz/{ => rel}/aig_exporter.cpp | 0 src/muz/{ => rel}/aig_exporter.h | 2 +- src/muz/{ => rel}/dl_compiler.cpp | 1 + src/muz/{ => rel}/dl_compiler.h | 0 src/muz/{ => rel}/dl_instruction.cpp | 11 +- src/muz/{ => rel}/dl_instruction.h | 9 +- src/muz/{ => rel}/rel_context.cpp | 64 +- src/muz/{ => rel}/rel_context.h | 53 +- src/muz/{ => tab}/tab_context.cpp | 0 src/muz/{ => tab}/tab_context.h | 2 +- .../{ => transforms}/dl_mk_array_blast.cpp | 0 src/muz/{ => transforms}/dl_mk_array_blast.h | 0 src/muz/{ => transforms}/dl_mk_backwards.cpp | 0 src/muz/{ => transforms}/dl_mk_backwards.h | 0 src/muz/{ => transforms}/dl_mk_bit_blast.cpp | 0 src/muz/{ => transforms}/dl_mk_bit_blast.h | 0 src/muz/{ => transforms}/dl_mk_coalesce.cpp | 0 src/muz/{ => transforms}/dl_mk_coalesce.h | 0 src/muz/{ => transforms}/dl_mk_coi_filter.cpp | 18 +- src/muz/{ => transforms}/dl_mk_coi_filter.h | 0 src/muz/{ => transforms}/dl_mk_different.h | 0 .../{ => transforms}/dl_mk_filter_rules.cpp | 0 src/muz/{ => transforms}/dl_mk_filter_rules.h | 0 .../dl_mk_interp_tail_simplifier.cpp | 0 .../dl_mk_interp_tail_simplifier.h | 0 src/muz/transforms/dl_mk_karr_invariants.cpp | 325 +++ src/muz/transforms/dl_mk_karr_invariants.h | 81 + .../{ => transforms}/dl_mk_loop_counter.cpp | 0 src/muz/{ => transforms}/dl_mk_loop_counter.h | 0 src/muz/{ => transforms}/dl_mk_magic_sets.cpp | 2 +- src/muz/{ => transforms}/dl_mk_magic_sets.h | 0 .../{ => transforms}/dl_mk_magic_symbolic.cpp | 0 .../{ => transforms}/dl_mk_magic_symbolic.h | 0 .../dl_mk_quantifier_abstraction.cpp | 0 .../dl_mk_quantifier_abstraction.h | 0 .../dl_mk_quantifier_instantiation.cpp | 0 .../dl_mk_quantifier_instantiation.h | 0 .../{ => transforms}/dl_mk_rule_inliner.cpp | 7 +- src/muz/{ => transforms}/dl_mk_rule_inliner.h | 6 +- src/muz/{ => transforms}/dl_mk_scale.cpp | 0 src/muz/{ => transforms}/dl_mk_scale.h | 0 src/muz/{ => transforms}/dl_mk_slice.cpp | 0 src/muz/{ => transforms}/dl_mk_slice.h | 0 .../dl_mk_subsumption_checker.cpp | 18 +- .../dl_mk_subsumption_checker.h | 0 .../dl_mk_unbound_compressor.cpp | 4 +- .../dl_mk_unbound_compressor.h | 2 +- src/muz/{ => transforms}/dl_mk_unfold.cpp | 0 src/muz/{ => transforms}/dl_mk_unfold.h | 0 src/muz/transforms/dl_transforms.cpp | 81 + src/muz/transforms/dl_transforms.h | 30 + src/shell/datalog_frontend.cpp | 9 +- src/test/datalog_parser.cpp | 8 +- src/test/dl_context.cpp | 8 +- src/test/dl_product_relation.cpp | 10 +- src/test/dl_query.cpp | 11 +- src/test/dl_relation.cpp | 8 +- src/test/dl_table.cpp | 5 +- 131 files changed, 994 insertions(+), 20069 deletions(-) rename src/muz/{ => bmc}/dl_bmc_engine.cpp (99%) rename src/muz/{ => bmc}/dl_bmc_engine.h (100%) rename src/muz/{ => clp}/clp_context.cpp (98%) rename src/muz/{ => clp}/clp_context.h (96%) delete mode 100644 src/muz/dl_base.cpp delete mode 100644 src/muz/dl_base.h delete mode 100644 src/muz/dl_bound_relation.cpp delete mode 100644 src/muz/dl_bound_relation.h delete mode 100644 src/muz/dl_check_table.cpp delete mode 100644 src/muz/dl_check_table.h delete mode 100644 src/muz/dl_cmds.h create mode 100644 src/muz/dl_engine_base.h delete mode 100644 src/muz/dl_external_relation.cpp delete mode 100644 src/muz/dl_external_relation.h delete mode 100644 src/muz/dl_finite_product_relation.cpp delete mode 100644 src/muz/dl_finite_product_relation.h delete mode 100644 src/muz/dl_interval_relation.cpp delete mode 100644 src/muz/dl_interval_relation.h delete mode 100644 src/muz/dl_mk_explanations.cpp delete mode 100644 src/muz/dl_mk_explanations.h delete mode 100644 src/muz/dl_mk_karr_invariants.cpp delete mode 100644 src/muz/dl_mk_karr_invariants.h delete mode 100644 src/muz/dl_mk_partial_equiv.cpp delete mode 100644 src/muz/dl_mk_partial_equiv.h delete mode 100644 src/muz/dl_mk_similarity_compressor.cpp delete mode 100644 src/muz/dl_mk_similarity_compressor.h delete mode 100644 src/muz/dl_mk_simple_joins.cpp delete mode 100644 src/muz/dl_mk_simple_joins.h delete mode 100644 src/muz/dl_product_relation.cpp delete mode 100644 src/muz/dl_product_relation.h delete mode 100644 src/muz/dl_relation_manager.cpp delete mode 100644 src/muz/dl_relation_manager.h delete mode 100644 src/muz/dl_sieve_relation.cpp delete mode 100644 src/muz/dl_sieve_relation.h delete mode 100644 src/muz/dl_sparse_table.cpp delete mode 100644 src/muz/dl_sparse_table.h delete mode 100644 src/muz/dl_table.cpp delete mode 100644 src/muz/dl_table.h delete mode 100644 src/muz/dl_table_plugin.h delete mode 100644 src/muz/dl_table_relation.cpp delete mode 100644 src/muz/dl_table_relation.h delete mode 100644 src/muz/dl_vector_relation.h rename src/muz/{ => fp}/dl_cmds.cpp (98%) create mode 100644 src/muz/fp/dl_register_engine.cpp create mode 100644 src/muz/fp/dl_register_engine.h rename src/muz/{ => fp}/horn_tactic.cpp (98%) rename src/muz/{ => fp}/horn_tactic.h (100%) rename src/muz/{ => pdr}/pdr_context.cpp (100%) rename src/muz/{ => pdr}/pdr_context.h (99%) rename src/muz/{ => pdr}/pdr_dl_interface.cpp (98%) rename src/muz/{ => pdr}/pdr_dl_interface.h (98%) rename src/muz/{ => pdr}/pdr_farkas_learner.cpp (100%) rename src/muz/{ => pdr}/pdr_farkas_learner.h (100%) rename src/muz/{ => pdr}/pdr_generalizers.cpp (99%) rename src/muz/{ => pdr}/pdr_generalizers.h (100%) rename src/muz/{ => pdr}/pdr_manager.cpp (100%) rename src/muz/{ => pdr}/pdr_manager.h (100%) rename src/muz/{ => pdr}/pdr_prop_solver.cpp (100%) rename src/muz/{ => pdr}/pdr_prop_solver.h (100%) rename src/muz/{ => pdr}/pdr_reachable_cache.cpp (100%) rename src/muz/{ => pdr}/pdr_reachable_cache.h (100%) rename src/muz/{ => pdr}/pdr_smt_context_manager.cpp (100%) rename src/muz/{ => pdr}/pdr_smt_context_manager.h (100%) rename src/muz/{ => pdr}/pdr_sym_mux.cpp (100%) rename src/muz/{ => pdr}/pdr_sym_mux.h (100%) rename src/muz/{ => pdr}/pdr_util.cpp (100%) rename src/muz/{ => pdr}/pdr_util.h (100%) rename src/muz/{ => rel}/aig_exporter.cpp (100%) rename src/muz/{ => rel}/aig_exporter.h (100%) rename src/muz/{ => rel}/dl_compiler.cpp (99%) rename src/muz/{ => rel}/dl_compiler.h (100%) rename src/muz/{ => rel}/dl_instruction.cpp (98%) rename src/muz/{ => rel}/dl_instruction.h (96%) rename src/muz/{ => rel}/rel_context.cpp (89%) rename src/muz/{ => rel}/rel_context.h (55%) rename src/muz/{ => tab}/tab_context.cpp (100%) rename src/muz/{ => tab}/tab_context.h (96%) rename src/muz/{ => transforms}/dl_mk_array_blast.cpp (100%) rename src/muz/{ => transforms}/dl_mk_array_blast.h (100%) rename src/muz/{ => transforms}/dl_mk_backwards.cpp (100%) rename src/muz/{ => transforms}/dl_mk_backwards.h (100%) rename src/muz/{ => transforms}/dl_mk_bit_blast.cpp (100%) rename src/muz/{ => transforms}/dl_mk_bit_blast.h (100%) rename src/muz/{ => transforms}/dl_mk_coalesce.cpp (100%) rename src/muz/{ => transforms}/dl_mk_coalesce.h (100%) rename src/muz/{ => transforms}/dl_mk_coi_filter.cpp (92%) rename src/muz/{ => transforms}/dl_mk_coi_filter.h (100%) rename src/muz/{ => transforms}/dl_mk_different.h (100%) rename src/muz/{ => transforms}/dl_mk_filter_rules.cpp (100%) rename src/muz/{ => transforms}/dl_mk_filter_rules.h (100%) rename src/muz/{ => transforms}/dl_mk_interp_tail_simplifier.cpp (100%) rename src/muz/{ => transforms}/dl_mk_interp_tail_simplifier.h (100%) create mode 100644 src/muz/transforms/dl_mk_karr_invariants.cpp create mode 100644 src/muz/transforms/dl_mk_karr_invariants.h rename src/muz/{ => transforms}/dl_mk_loop_counter.cpp (100%) rename src/muz/{ => transforms}/dl_mk_loop_counter.h (100%) rename src/muz/{ => transforms}/dl_mk_magic_sets.cpp (99%) rename src/muz/{ => transforms}/dl_mk_magic_sets.h (100%) rename src/muz/{ => transforms}/dl_mk_magic_symbolic.cpp (100%) rename src/muz/{ => transforms}/dl_mk_magic_symbolic.h (100%) rename src/muz/{ => transforms}/dl_mk_quantifier_abstraction.cpp (100%) rename src/muz/{ => transforms}/dl_mk_quantifier_abstraction.h (100%) rename src/muz/{ => transforms}/dl_mk_quantifier_instantiation.cpp (100%) rename src/muz/{ => transforms}/dl_mk_quantifier_instantiation.h (100%) rename src/muz/{ => transforms}/dl_mk_rule_inliner.cpp (99%) rename src/muz/{ => transforms}/dl_mk_rule_inliner.h (98%) rename src/muz/{ => transforms}/dl_mk_scale.cpp (100%) rename src/muz/{ => transforms}/dl_mk_scale.h (100%) rename src/muz/{ => transforms}/dl_mk_slice.cpp (100%) rename src/muz/{ => transforms}/dl_mk_slice.h (100%) rename src/muz/{ => transforms}/dl_mk_subsumption_checker.cpp (96%) rename src/muz/{ => transforms}/dl_mk_subsumption_checker.h (100%) rename src/muz/{ => transforms}/dl_mk_unbound_compressor.cpp (99%) rename src/muz/{ => transforms}/dl_mk_unbound_compressor.h (98%) rename src/muz/{ => transforms}/dl_mk_unfold.cpp (100%) rename src/muz/{ => transforms}/dl_mk_unfold.h (100%) create mode 100644 src/muz/transforms/dl_transforms.cpp create mode 100644 src/muz/transforms/dl_transforms.h diff --git a/scripts/mk_project.py b/scripts/mk_project.py index 44ad9ccbc..a2b4ef9b2 100644 --- a/scripts/mk_project.py +++ b/scripts/mk_project.py @@ -54,10 +54,17 @@ def init_project_def(): add_lib('smt_tactic', ['smt'], 'smt/tactic') add_lib('sls_tactic', ['tactic', 'normal_forms', 'core_tactics', 'bv_tactics'], 'tactic/sls') add_lib('qe', ['smt','sat'], 'qe') - add_lib('muz', ['smt', 'sat', 'smt2parser', 'aig_tactic','qe']) - add_lib('smtlogic_tactics', ['arith_tactics', 'bv_tactics', 'nlsat_tactic', 'smt_tactic', 'aig_tactic', 'muz','qe'], 'tactic/smtlogics') + add_lib('muz', ['smt', 'sat', 'smt2parser', 'aig_tactic', 'qe']) + add_lib('transforms', ['muz'], 'muz/transforms') + add_lib('rel', ['muz', 'transforms'], 'muz/rel') + add_lib('pdr', ['muz', 'transforms'], 'muz/pdr') + add_lib('clp', ['muz', 'transforms'], 'muz/clp') + add_lib('tab', ['muz', 'transforms'], 'muz/tab') + add_lib('bmc', ['muz', 'transforms'], 'muz/bmc') + add_lib('fp', ['muz', 'pdr', 'clp', 'tab', 'rel', 'bmc'], 'muz/fp') + add_lib('smtlogic_tactics', ['arith_tactics', 'bv_tactics', 'nlsat_tactic', 'smt_tactic', 'aig_tactic', 'fp', 'muz','qe'], 'tactic/smtlogics') add_lib('ufbv_tactic', ['normal_forms', 'core_tactics', 'macros', 'smt_tactic', 'rewriter'], 'tactic/ufbv') - add_lib('portfolio', ['smtlogic_tactics', 'ufbv_tactic', 'fpa', 'aig_tactic', 'muz', 'qe','sls_tactic', 'subpaving_tactic'], 'tactic/portfolio') + add_lib('portfolio', ['smtlogic_tactics', 'ufbv_tactic', 'fpa', 'aig_tactic', 'fp', 'muz', 'qe','sls_tactic', 'subpaving_tactic'], 'tactic/portfolio') add_lib('smtparser', ['portfolio'], 'parsers/smt') API_files = ['z3_api.h', 'z3_algebraic.h', 'z3_polynomial.h', 'z3_rcf.h'] add_lib('api', ['portfolio', 'user_plugin', 'smtparser', 'realclosure'], diff --git a/src/api/api_datalog.cpp b/src/api/api_datalog.cpp index 64b8b064e..ad6b5ad69 100644 --- a/src/api/api_datalog.cpp +++ b/src/api/api_datalog.cpp @@ -18,7 +18,6 @@ Revision History: #include"api_datalog.h" #include"api_context.h" #include"api_util.h" -#include"dl_context.h" #include"ast_pp.h" #include"api_ast_vector.h" #include"api_log_macros.h" @@ -30,8 +29,10 @@ Revision History: #include"cmd_context.h" #include"smt2parser.h" #include"dl_context.h" +#include"dl_register_engine.h" #include"dl_external_relation.h" #include"dl_decl_plugin.h" +#include"rel_context.h" namespace api { @@ -39,6 +40,7 @@ namespace api { void * m_state; reduce_app_callback_fptr m_reduce_app; reduce_assign_callback_fptr m_reduce_assign; + datalog::register_engine m_register_engine; datalog::context m_context; ast_ref_vector m_trail; public: @@ -46,7 +48,7 @@ namespace api { m_state(0), m_reduce_app(0), m_reduce_assign(0), - m_context(m, p), + m_context(m, m_register_engine, p), m_trail(m) {} virtual ~fixedpoint_context() {} @@ -59,7 +61,7 @@ namespace api { if (!m.has_plugin(name)) { m.register_plugin(name, alloc(datalog::dl_decl_plugin)); } - datalog::rel_context* rel = m_context.get_rel_context(); + datalog::rel_context_base* rel = m_context.get_rel_context(); if (rel) { datalog::relation_manager& r = rel->get_rmanager(); r.register_plugin(alloc(datalog::external_relation_plugin, *this, r)); diff --git a/src/muz/dl_bmc_engine.cpp b/src/muz/bmc/dl_bmc_engine.cpp similarity index 99% rename from src/muz/dl_bmc_engine.cpp rename to src/muz/bmc/dl_bmc_engine.cpp index 65a60cdeb..72e40590e 100644 --- a/src/muz/dl_bmc_engine.cpp +++ b/src/muz/bmc/dl_bmc_engine.cpp @@ -23,13 +23,14 @@ Revision History: #include "dl_mk_slice.h" #include "smt_kernel.h" #include "datatype_decl_plugin.h" -#include "dl_mk_rule_inliner.h" #include "dl_decl_plugin.h" #include "bool_rewriter.h" #include "model_smt2_pp.h" #include "ast_smt_pp.h" #include "well_sorted.h" #include "rewriter_def.h" +#include "dl_transforms.h" +#include "dl_mk_rule_inliner.h" namespace datalog { @@ -1437,7 +1438,7 @@ namespace datalog { datalog::rule_set old_rules(m_ctx.get_rules()); rule_manager.mk_query(query, m_ctx.get_rules()); expr_ref bg_assertion = m_ctx.get_background_assertion(); - m_ctx.apply_default_transformation(); + apply_default_transformation(m_ctx); if (m_ctx.get_params().slice()) { datalog::rule_transformer transformer(m_ctx); diff --git a/src/muz/dl_bmc_engine.h b/src/muz/bmc/dl_bmc_engine.h similarity index 100% rename from src/muz/dl_bmc_engine.h rename to src/muz/bmc/dl_bmc_engine.h diff --git a/src/muz/clp_context.cpp b/src/muz/clp/clp_context.cpp similarity index 98% rename from src/muz/clp_context.cpp rename to src/muz/clp/clp_context.cpp index 01299a2b7..5f3a09e2d 100644 --- a/src/muz/clp_context.cpp +++ b/src/muz/clp/clp_context.cpp @@ -22,6 +22,8 @@ Revision History: #include "unifier.h" #include "var_subst.h" #include "substitution.h" +#include "smt_kernel.h" +#include "dl_transforms.h" namespace datalog { @@ -67,7 +69,7 @@ namespace datalog { m_solver.reset(); m_goals.reset(); rm.mk_query(query, m_ctx.get_rules()); - m_ctx.apply_default_transformation(); + apply_default_transformation(m_ctx); func_decl* head_decl = m_ctx.get_rules().get_output_predicate(); rule_set& rules = m_ctx.get_rules(); rule_vector const& rv = rules.get_predicate_rules(head_decl); diff --git a/src/muz/clp_context.h b/src/muz/clp/clp_context.h similarity index 96% rename from src/muz/clp_context.h rename to src/muz/clp/clp_context.h index 5184b474d..6464ae634 100644 --- a/src/muz/clp_context.h +++ b/src/muz/clp/clp_context.h @@ -22,7 +22,7 @@ Revision History: #include "ast.h" #include "lbool.h" #include "statistics.h" -#include "dl_util.h" +#include "dl_engine_base.h" namespace datalog { class context; diff --git a/src/muz/dl_base.cpp b/src/muz/dl_base.cpp deleted file mode 100644 index 0f250d76c..000000000 --- a/src/muz/dl_base.cpp +++ /dev/null @@ -1,459 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - dl_base.cpp - -Abstract: - - - -Author: - - Krystof Hoder (t-khoder) 2010-09-14. - -Revision History: - ---*/ - - -#include"ast_pp.h" -#include"union_find.h" -#include"vector.h" -#include"dl_context.h" -#include"dl_base.h" -#include"bool_rewriter.h" -#include - - -namespace datalog { - - context & get_context_from_rel_manager(const relation_manager & rm) { - return rm.get_context(); - } - - ast_manager & get_ast_manager_from_rel_manager(const relation_manager & rm) { - return rm.get_context().get_manager(); - } - -#if DL_LEAK_HUNTING - void leak_guard_check(const symbol & s) { - } -#endif - - void relation_signature::output(ast_manager & m, std::ostream & out) const { - unsigned sz=size(); - out<<"("; - for(unsigned i=0; i reset_fn = - get_manager().mk_filter_interpreted_fn(static_cast(*this), bottom_ref); - if(!reset_fn) { - NOT_IMPLEMENTED_YET(); - } - (*reset_fn)(*this); - } - - - - void table_signature::from_join(const table_signature & s1, const table_signature & s2, unsigned col_cnt, - const unsigned * cols1, const unsigned * cols2, table_signature & result) { - result.reset(); - - unsigned s1sz=s1.size(); - unsigned s2sz=s2.size(); - unsigned s1first_func=s1sz-s1.functional_columns(); - unsigned s2first_func=s2sz-s2.functional_columns(); - for(unsigned i=0; i=col_cnt); - result.set_functional_columns(func_cnt-col_cnt); - } - } - - void table_signature::from_project_with_reduce(const table_signature & src, unsigned col_cnt, - const unsigned * removed_cols, table_signature & result) { - signature_base::from_project(src, col_cnt, removed_cols, result); - - unsigned remaining_fun = src.functional_columns(); - unsigned first_src_fun = src.first_functional(); - for(int i=col_cnt-1; i>=0; i--) { - if(removed_cols[i] remaining_in_equivalence_class; - remaining_in_equivalence_class.resize(join_sig_sz, 0); - bool merging_rows_can_happen = false; - - union_find_default_ctx uf_ctx; - union_find<> uf(uf_ctx); //the numbers in uf correspond to column indexes after the join - for(unsigned i=0; icols1[i]) ? cols1[i] : (first_func_ofs+cols1[i]-s1_first_func); - unsigned idx2 = (s2_first_func>cols2[i]) ? (second_ofs+cols2[i]) : (second_func_ofs+cols2[i]-s2_first_func); - uf.merge(idx1, idx2); - } - for(unsigned i=0; i=first_func_ofs) { - //removing functional columns won't make us merge rows - continue; - } - unsigned eq_class_idx = uf.find(rc); - if(remaining_in_equivalence_class[eq_class_idx]>1) { - remaining_in_equivalence_class[eq_class_idx]--; - } - else { - merging_rows_can_happen = true; - break; - } - } - - if(merging_rows_can_happen) { - //this one marks all columns as non-functional - from_project(aux, removed_col_cnt, removed_cols, result); - SASSERT(result.functional_columns()==0); - } - else { - //this one preserves columns to be functional - from_project_with_reduce(aux, removed_col_cnt, removed_cols, result); - } - } - - - - - // ----------------------------------- - // - // table_base - // - // ----------------------------------- - - //here we give generic implementation of table operations using iterators - - bool table_base::empty() const { - return begin()==end(); - } - - void table_base::remove_facts(unsigned fact_cnt, const table_fact * facts) { - for(unsigned i=0; i to_remove; - table_base::iterator it = begin(); - table_base::iterator iend = end(); - table_fact row; - for(; it!=iend; ++it) { - it->get_fact(row); - to_remove.push_back(row); - } - remove_facts(to_remove.size(), to_remove.c_ptr()); - } - - bool table_base::contains_fact(const table_fact & f) const { - iterator it = begin(); - iterator iend = end(); - - table_fact row; - - for(; it!=iend; ++it) { - it->get_fact(row); - if(vectors_equal(row, f)) { - return true; - } - } - return false; - } - - bool table_base::fetch_fact(table_fact & f) const { - if(get_signature().functional_columns()==0) { - return contains_fact(f); - } - else { - unsigned sig_sz = get_signature().size(); - unsigned non_func_cnt = sig_sz-get_signature().functional_columns(); - table_base::iterator it = begin(); - table_base::iterator iend = end(); - table_fact row; - for(; it!=iend; ++it) { - it->get_fact(row); - bool differs = false; - for(unsigned i=0; iget_fact(row); - res->add_new_fact(row); - } - return res; - } - - /** - \brief Default method for complementation. - - It assumes that the compiler creates only tables with - at most one column (0 or 1 columns). - Complementation of tables with more than one columns - is transformed into a cross product of complements and/or - difference. - - */ - table_base * table_base::complement(func_decl* p, const table_element * func_columns) const { - const table_signature & sig = get_signature(); - SASSERT(sig.functional_columns()==0 || func_columns!=0); - SASSERT(sig.first_functional() <= 1); - - table_base * res = get_plugin().mk_empty(sig); - - table_fact fact; - fact.resize(sig.first_functional()); - fact.append(sig.functional_columns(), func_columns); - - if (sig.first_functional() == 0) { - if (empty()) { - res->add_fact(fact); - } - return res; - } - - VERIFY(sig.first_functional() == 1); - - uint64 upper_bound = get_signature()[0]; - bool empty_table = empty(); - - if (upper_bound > (1 << 18)) { - std::ostringstream buffer; - buffer << "creating large table of size " << upper_bound; - if (p) buffer << " for relation " << p->get_name(); - warning_msg(buffer.str().c_str()); - } - - for(table_element i = 0; i < upper_bound; i++) { - fact[0] = i; - if(empty_table || !contains_fact(fact)) { - res->add_fact(fact); - } - } - return res; - } - - void table_base::display(std::ostream & out) const { - out << "table with signature "; - print_container(get_signature(), out); - out << ":\n"; - - iterator it = begin(); - iterator iend = end(); - for(; it!=iend; ++it) { - const row_interface & r = *it; - r.display(out); - } - - out << "\n"; - } - - - class table_base::row_interface::fact_row_iterator : public table_base::row_iterator_core { - const row_interface & m_parent; - unsigned m_index; - protected: - virtual bool is_finished() const { return m_index==m_parent.size(); } - public: - fact_row_iterator(const row_interface & row, bool finished) - : m_parent(row), m_index(finished ? row.size() : 0) {} - - virtual table_element operator*() { - SASSERT(!is_finished()); - return m_parent[m_index]; - } - - virtual void operator++() { - m_index++; - SASSERT(m_index<=m_parent.size()); - } - }; - - table_base::row_iterator table_base::row_interface::begin() const { - return row_iterator(alloc(fact_row_iterator, *this, false)); - } - table_base::row_iterator table_base::row_interface::end() const { - return row_iterator(alloc(fact_row_iterator, *this, true)); - } - - void table_base::row_interface::get_fact(table_fact & result) const { - result.reset(); - unsigned n=size(); - for(unsigned i=0; i - -Author: - - Krystof Hoder (t-khoder) 2010-09-23. - -Revision History: - ---*/ -#ifndef _DL_BASE_H_ -#define _DL_BASE_H_ - -#define DL_LEAK_HUNTING 0 - -#include - -#include"ast.h" -#include"map.h" -#include"vector.h" -#include"ref.h" -#include"dl_util.h" - -namespace datalog { - - class context; - class relation_manager; - - ast_manager & get_ast_manager_from_rel_manager(const relation_manager & rm); - context & get_context_from_rel_manager(const relation_manager & rm); - - typedef func_decl_set decl_set; - -#if DL_LEAK_HUNTING - void leak_guard_check(const symbol & s); -#endif - - - /** - Termplate class containing common infrastructure for relations and tables - */ - template - struct tr_infrastructure { - - typedef typename Traits::plugin plugin; - typedef typename Traits::base_object base_object; - typedef typename Traits::element element; - typedef typename Traits::fact fact; - typedef typename Traits::sort sort; - typedef typename Traits::signature_base_base signature_base_base; //this must be a vector-like type - typedef typename Traits::signature signature; //this must be a vector-like type - - /** - The client submits an initial class to be used as a base for signature. Then we excend it by - the common signature methods into a signature_base class which then the client inherits from - to obtain the actual signature class. - */ - class signature_base : public signature_base_base { - public: - bool operator==(const signature & o) const { - unsigned n=signature_base_base::size(); - if(n!=o.size()) { - return false; - } - return memcmp(this->c_ptr(), o.c_ptr(), n*sizeof(sort))==0; - /*for(unsigned i=0; i=2); - result=src; - - permutate_by_cycle(result, cycle_len, permutation_cycle); - } - - /** - \brief Into \c result assign signature \c src with reordered columns. - */ - static void from_permutation_rename(const signature & src, - const unsigned * permutation, signature & result) { - result.reset(); - unsigned n = src.size(); - for(unsigned i=0; i(0)); - } - }; - - /** - \brief Mutator for relations that propagate constraints as a consequence of - combination. - - - supports_attachment - is used to query the mutator if it allows communicating - constraints to relations of the kind of the relation. - - - attach - is used to associate downstream clients. - It assumes that the relation kind is supported (supports_kind returns true) - */ - class mutator_fn : public base_fn { - public: - virtual void operator()(base_object & t) = 0; - - virtual bool supports_attachment(base_object& other) { return false; } - - virtual void attach(base_object& other) { UNREACHABLE(); } - }; - - class intersection_filter_fn : public base_fn { - public: - virtual void operator()(base_object & t, const base_object & intersected_obj) = 0; - }; - - class default_join_project_fn; - - /** - \brief Plugin class providing factory functions for a table and operations on it. - - The functor factory functions (mk_*_fn) may return 0. It means that the plugin - is unable to perform the operation on relations/tables of the particular kind. - */ - class plugin_object { - friend class relation_manager; - friend class check_table_plugin; - - family_id m_kind; - symbol m_name; - relation_manager & m_manager; - protected: - plugin_object(symbol const& name, relation_manager & manager) - : m_kind(null_family_id), m_name(name), m_manager(manager) {} - - /** - \brief Check \c r is of the same kind as the plugin. - */ - bool check_kind(base_object const& r) const { return &r.get_plugin()==this; } - public: - virtual ~plugin_object() {} - - virtual void initialize(family_id fid) { m_kind = fid; } - - family_id get_kind() const { return m_kind; } - - symbol const& get_name() const { return m_name; } - - virtual void set_cancel(bool f) {} - - relation_manager & get_manager() const { return m_manager; } - ast_manager& get_ast_manager() const { return datalog::get_ast_manager_from_rel_manager(m_manager); } - context& get_context() const { return datalog::get_context_from_rel_manager(m_manager); } - - virtual bool can_handle_signature(const signature & s) = 0; - - virtual bool can_handle_signature(const signature & s, family_id kind) { - return can_handle_signature(s); - } - - /** - \brief Create empty table/relation with given signature and return pointer to it. - - Precondition: can_handle_signature(s)==true - */ - virtual base_object * mk_empty(const signature & s) = 0; - - /** - \brief Create empty table/relation with signature \c s and kind \c kind. - - Precondition: &orig.get_plugin()==this - */ - virtual base_object * mk_empty(const signature & s, family_id kind) { - SASSERT(kind==get_kind()); //if plugin uses multiple kinds, this function needs to be overriden - return mk_empty(s); - } - - /** - \brief Create empty table/relation of the same specification as \c orig and return pointer to it. - - Precondition: &orig.get_plugin()==this - */ - virtual base_object * mk_empty(const base_object & orig) { - return mk_empty(orig.get_signature(), orig.get_kind()); - } - - /** - \brief Create full table/relation with given signature and return pointer to it. - - Precondition: can_handle_signature(s)==true - */ - virtual base_object * mk_full(func_decl* p, const signature & s) { - base_object * aux = mk_empty(s); - base_object * res = aux->complement(p); - aux->deallocate(); - return res; - } - - virtual base_object * mk_full(func_decl* p, const signature & s, family_id kind) { - if (kind == get_kind() || kind == null_family_id) { - return mk_full(p, s); - } - base_object * aux = mk_empty(s, kind); - base_object * res = aux->complement(p); - aux->deallocate(); - return res; - } - - protected: - //see \c relation_manager for documentation of the operations - - virtual join_fn * mk_join_fn(const base_object & t1, const base_object & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) { return 0; } - - virtual transformer_fn * mk_project_fn(const base_object & t, unsigned col_cnt, - const unsigned * removed_cols) { return 0; } - - virtual join_fn * mk_join_project_fn(const base_object & t1, const base_object & t2, - unsigned joined_col_cnt, const unsigned * cols1, const unsigned * cols2, - unsigned removed_col_cnt, const unsigned * removed_cols) { return 0; } - - virtual transformer_fn * mk_rename_fn(const base_object & t, unsigned permutation_cycle_len, - const unsigned * permutation_cycle) { return 0; } - - virtual transformer_fn * mk_permutation_rename_fn(const base_object & t, - const unsigned * permutation) { return 0; } - - public: - virtual union_fn * mk_union_fn(const base_object & tgt, const base_object & src, - const base_object * delta) { return 0; } - protected: - - virtual union_fn * mk_widen_fn(const base_object & tgt, const base_object & src, - const base_object * delta) { return 0; } - - virtual mutator_fn * mk_filter_identical_fn(const base_object & t, unsigned col_cnt, - const unsigned * identical_cols) { return 0; } - - virtual mutator_fn * mk_filter_equal_fn(const base_object & t, const element & value, - unsigned col) { return 0; } - - virtual mutator_fn * mk_filter_interpreted_fn(const base_object & t, app * condition) - { return 0; } - - virtual transformer_fn * mk_filter_interpreted_and_project_fn(const base_object & t, - app * condition, unsigned removed_col_cnt, const unsigned * removed_cols) - { return 0; } - - virtual transformer_fn * mk_select_equal_and_project_fn(const base_object & t, - const element & value, unsigned col) { return 0; } - - virtual intersection_filter_fn * mk_filter_by_intersection_fn(const base_object & t, - const base_object & src, unsigned joined_col_cnt, - const unsigned * t_cols, const unsigned * src_cols) - { return 0; } - - virtual intersection_filter_fn * mk_filter_by_negation_fn(const base_object & t, - const base_object & negated_obj, unsigned joined_col_cnt, - const unsigned * t_cols, const unsigned * negated_cols) - { return 0; } - }; - - class base_ancestor { - plugin & m_plugin; - signature m_signature; - family_id m_kind; -#if DL_LEAK_HUNTING - sort_ref m_leak_guard; -#endif - protected: - base_ancestor(plugin & p, const signature & s) - : m_plugin(p), m_signature(s), m_kind(p.get_kind()) -#if DL_LEAK_HUNTING - , m_leak_guard(p.get_ast_manager().mk_fresh_sort(p.get_name().bare_str()), p.get_ast_manager()) -#endif - { -#if DL_LEAK_HUNTING - leak_guard_check(m_leak_guard->get_name()); -#endif - } - -#if DL_LEAK_HUNTING - base_ancestor(const base_ancestor & o) - : m_plugin(o.m_plugin), - m_signature(o.m_signature), - m_kind(o.m_kind), - m_leak_guard(m_plugin.get_ast_manager().mk_fresh_sort(m_plugin.get_name().bare_str()), - m_plugin.get_ast_manager()) { - leak_guard_check(m_leak_guard->get_name()); - } -#endif - - virtual ~base_ancestor() {} - - void set_kind(family_id kind) { SASSERT(kind>=0); m_kind = kind; } - - /** - Since the destructor is protected, we cannot use the \c dealloc macro. - */ - void destroy() { - SASSERT(this); - this->~base_ancestor(); -#if _DEBUG - memory::deallocate(__FILE__, __LINE__, this); -#else - memory::deallocate(this); -#endif - } - public: - /** - Deallocate the current object. - - Pointers and references to the current object become invalid after a call to this function. - */ - virtual void deallocate() { - destroy(); - } - /** - It must hold that operations created for particular table/relation are able to operate on - tables/relations of the same signature and kind. In most cases it is sufficient to use the kind - of the plugin object. - - However, it there is some parameter that is not reflected in the signature, the plugin may need to - allocate different kind numbers to the tables is creates. - */ - family_id get_kind() const { return m_kind; } - const signature & get_signature() const { return m_signature; } - plugin & get_plugin() const { return m_plugin; } - relation_manager & get_manager() const { return get_plugin().get_manager(); } - - virtual bool empty() const = 0; - virtual void add_fact(const fact & f) = 0; - /** - \brief Like \c add_fact, only here the caller guarantees that the fact is not present in - the table yet. - */ - virtual void add_new_fact(const fact & f) { - add_fact(f); - } - virtual bool contains_fact(const fact & f) const = 0; - - virtual void reset() = 0; - - /** - \brief Return table/relation that contains the same data as the current one. - */ - virtual base_object * clone() const = 0; - - virtual bool can_swap(const base_object & o) const { return false; } - - virtual void swap(base_object & o) { - std::swap(m_kind, o.m_kind); -#if DL_LEAK_HUNTING - m_leak_guard = get_plugin().get_ast_manager().mk_fresh_sort(get_plugin().get_name().bare_str()); - o.m_leak_guard = get_plugin().get_ast_manager().mk_fresh_sort(get_plugin().get_name().bare_str()); - leak_guard_check(m_leak_guard->get_name()); - leak_guard_check(o.m_leak_guard->get_name()); -#endif - } - - virtual unsigned get_size_estimate_rows() const { return UINT_MAX; } - virtual unsigned get_size_estimate_bytes() const { return UINT_MAX; } - virtual bool knows_exact_size() const { return false; } - - virtual void display(std::ostream & out) const = 0; - }; - - - class convenient_join_fn : public join_fn { - signature m_result_sig; - protected: - unsigned_vector m_cols1; - unsigned_vector m_cols2; - - convenient_join_fn(const signature & o1_sig, const signature & o2_sig, unsigned col_cnt, - const unsigned * cols1, const unsigned * cols2) - : m_cols1(col_cnt, cols1), - m_cols2(col_cnt, cols2) { - signature::from_join(o1_sig, o2_sig, col_cnt, cols1, cols2, m_result_sig); - } - - const signature & get_result_signature() const { return m_result_sig; } - }; - - class convenient_join_project_fn : public join_fn { - signature m_result_sig; - protected: - unsigned_vector m_cols1; - unsigned_vector m_cols2; - //it is non-const because it needs to be modified in sparse_table version of the join_project operator - unsigned_vector m_removed_cols; - - convenient_join_project_fn(const signature & o1_sig, const signature & o2_sig, - unsigned joined_col_cnt, const unsigned * cols1, const unsigned * cols2, - unsigned removed_col_cnt, const unsigned * removed_cols) - : m_cols1(joined_col_cnt, cols1), - m_cols2(joined_col_cnt, cols2), - m_removed_cols(removed_col_cnt, removed_cols) { - - signature::from_join_project(o1_sig, o2_sig, joined_col_cnt, cols1, cols2, - removed_col_cnt, removed_cols, m_result_sig); - } - - const signature & get_result_signature() const { return m_result_sig; } - }; - - class convenient_transformer_fn : public transformer_fn { - signature m_result_sig; - protected: - signature & get_result_signature() { return m_result_sig; } - const signature & get_result_signature() const { return m_result_sig; } - }; - - class convenient_project_fn : public convenient_transformer_fn { - protected: - unsigned_vector m_removed_cols; - - convenient_project_fn(const signature & orig_sig, unsigned col_cnt, const unsigned * removed_cols) - : m_removed_cols(col_cnt, removed_cols) { - signature::from_project(orig_sig, col_cnt, removed_cols, - convenient_transformer_fn::get_result_signature()); - } - }; - - class convenient_rename_fn : public convenient_transformer_fn { - protected: - const unsigned_vector m_cycle; - - convenient_rename_fn(const signature & orig_sig, unsigned cycle_len, - const unsigned * permutation_cycle) - : m_cycle(cycle_len, permutation_cycle) { - signature::from_rename(orig_sig, cycle_len, permutation_cycle, - convenient_transformer_fn::get_result_signature()); - } - }; - - class convenient_negation_filter_fn : public intersection_filter_fn { - protected: - unsigned m_joined_col_cnt; - const unsigned_vector m_cols1; - const unsigned_vector m_cols2; - bool m_all_neg_bound; //all columns are bound at least once - bool m_overlap; //one column in negated table is bound multiple times - svector m_bound; - - convenient_negation_filter_fn(const base_object & tgt, const base_object & neg_t, - unsigned joined_col_cnt, const unsigned * t_cols, const unsigned * negated_cols) - : m_joined_col_cnt(joined_col_cnt), m_cols1(joined_col_cnt, t_cols), - m_cols2(joined_col_cnt, negated_cols) { - unsigned neg_sig_size = neg_t.get_signature().size(); - m_overlap = false; - m_bound.resize(neg_sig_size, false); - for(unsigned i=0; i - void make_neg_bindings(T & tgt_neg, const U & src) const { - SASSERT(m_all_neg_bound); - SASSERT(!m_overlap); - for(unsigned i=0; i - bool bindings_match(const T & tgt_neg, const U & src) const { - for(unsigned i=0; i renamer_vector; - - unsigned_vector m_permutation; //this is valid only before m_renamers_initialized becomes true - bool m_renamers_initialized; - renamer_vector m_renamers; - public: - default_permutation_rename_fn(const base_object & o, const unsigned * permutation) - : m_permutation(o.get_signature().size(), permutation), - m_renamers_initialized(false) {} - - ~default_permutation_rename_fn() { - dealloc_ptr_vector_content(m_renamers); - } - - base_object * operator()(const base_object & o) { - const base_object * res = &o; - scoped_rel res_scoped; - if(m_renamers_initialized) { - typename renamer_vector::iterator rit = m_renamers.begin(); - typename renamer_vector::iterator rend = m_renamers.end(); - for(; rit!=rend; ++rit) { - res_scoped = (**rit)(*res); - res = res_scoped.get(); - } - } - else { - SASSERT(m_renamers.empty()); - unsigned_vector cycle; - while(try_remove_cycle_from_permutation(m_permutation, cycle)) { - transformer_fn * renamer = o.get_manager().mk_rename_fn(*res, cycle); - SASSERT(renamer); - m_renamers.push_back(renamer); - cycle.reset(); - - res_scoped = (*renamer)(*res); - res = res_scoped.get(); - } - m_renamers_initialized = true; - } - if(res_scoped) { - SASSERT(res==res_scoped.get()); - //we don't want to delete the last one since we'll be returning it - return res_scoped.release(); - } - else { - SASSERT(res==&o); - return res->clone(); - } - } - - }; - - - }; - - - // ----------------------------------- - // - // relation_base - // - // ----------------------------------- - - class relation_signature; - class relation_plugin; - class relation_base; - - typedef sort * relation_sort; - typedef ptr_vector relation_signature_base0; - typedef ptr_hash relation_sort_hash; - - typedef app * relation_element; - typedef app_ref relation_element_ref; - - class relation_fact : public app_ref_vector { - public: - class el_proxy { - friend class relation_fact; - - relation_fact & m_parent; - unsigned m_idx; - - el_proxy(relation_fact & parent, unsigned idx) : m_parent(parent), m_idx(idx) {} - public: - operator relation_element() const { - return m_parent.get(m_idx); - } - relation_element operator->() const { - return m_parent.get(m_idx); - } - relation_element operator=(const relation_element & val) const { - m_parent.set(m_idx, val); - return m_parent.get(m_idx); - } - relation_element operator=(const el_proxy & val) { - m_parent.set(m_idx, val); - return m_parent.get(m_idx); - } - }; - - typedef const relation_element * iterator; - - relation_fact(ast_manager & m) : app_ref_vector(m) {} - relation_fact(ast_manager & m, unsigned sz) : app_ref_vector(m) { resize(sz); } - relation_fact(context & ctx); - - iterator begin() const { return c_ptr(); } - iterator end() const { return c_ptr()+size(); } - - relation_element operator[](unsigned i) const { return get(i); } - el_proxy operator[](unsigned i) { return el_proxy(*this, i); } - }; - - struct relation_traits { - typedef relation_plugin plugin; - typedef relation_base base_object; - typedef relation_element element; - typedef relation_fact fact; - typedef relation_sort sort; - typedef relation_signature_base0 signature_base_base; - typedef relation_signature signature; - }; - - typedef tr_infrastructure relation_infrastructure; - - typedef relation_infrastructure::base_fn base_relation_fn; - typedef relation_infrastructure::join_fn relation_join_fn; - typedef relation_infrastructure::transformer_fn relation_transformer_fn; - typedef relation_infrastructure::union_fn relation_union_fn; - typedef relation_infrastructure::mutator_fn relation_mutator_fn; - typedef relation_infrastructure::intersection_filter_fn relation_intersection_filter_fn; - - typedef relation_infrastructure::convenient_join_fn convenient_relation_join_fn; - typedef relation_infrastructure::convenient_join_project_fn convenient_relation_join_project_fn; - typedef relation_infrastructure::convenient_transformer_fn convenient_relation_transformer_fn; - typedef relation_infrastructure::convenient_project_fn convenient_relation_project_fn; - typedef relation_infrastructure::convenient_rename_fn convenient_relation_rename_fn; - typedef relation_infrastructure::convenient_negation_filter_fn convenient_relation_negation_filter_fn; - typedef relation_infrastructure::identity_transformer_fn identity_relation_transformer_fn; - typedef relation_infrastructure::identity_mutator_fn identity_relation_mutator_fn; - typedef relation_infrastructure::identity_intersection_filter_fn identity_relation_intersection_filter_fn; - typedef relation_infrastructure::default_permutation_rename_fn default_relation_permutation_rename_fn; - - class relation_signature : public relation_infrastructure::signature_base { - public: - bool operator!=(const relation_signature & o) const { - return !(*this==o); - } - - void output(ast_manager & m, std::ostream & out) const; - - struct hash { - unsigned operator()(relation_signature const& s) const { - return obj_vector_hash(s); - } - }; - - struct eq { - bool operator()(relation_signature const& s1, relation_signature const& s2) const { - return s1 == s2; - } - }; - }; - - class relation_plugin : public relation_infrastructure::plugin_object { - protected: - enum special_relation_type { - ST_ORDINARY, - ST_TABLE_RELATION, - ST_FINITE_PRODUCT_RELATION, - ST_PRODUCT_RELATION, - ST_SIEVE_RELATION - }; - private: - special_relation_type m_special_type; - protected: - relation_plugin(symbol const& name, relation_manager & manager, - special_relation_type special_type = ST_ORDINARY) - : plugin_object(name, manager), - m_special_type(special_type) {} - public: - bool from_table() const { return m_special_type==ST_TABLE_RELATION; } - bool is_finite_product_relation() const { return m_special_type==ST_FINITE_PRODUCT_RELATION; } - bool is_product_relation() const { return m_special_type==ST_PRODUCT_RELATION; } - bool is_sieve_relation() const { return m_special_type==ST_SIEVE_RELATION; } - - /** - \brief If true, the relation can contain only one or zero elements. - - Having this zero allows the finite_product_relation to perform some operations in a simpler way. - (KH: I started implementing finite_product_relation::inner_singleton_union_fn that takes advantage of - it, but it's not finished.) - */ - virtual bool is_singleton_relation() const { return false; } - }; - - class relation_base : public relation_infrastructure::base_ancestor { - protected: - relation_base(relation_plugin & plugin, const relation_signature & s) - : base_ancestor(plugin, s) {} - virtual ~relation_base() {} - public: - virtual relation_base * complement(func_decl* p) const = 0; - - virtual void reset(); - - virtual void display_tuples(func_decl & pred, std::ostream & out) const { - out << "Tuples in " << pred.get_name() << ": \n"; - display(out); - } - - virtual void to_formula(expr_ref& fml) const = 0; - - bool from_table() const { return get_plugin().from_table(); } - virtual bool is_precise() const { return true; } - }; - - typedef ptr_vector relation_vector; - - // ----------------------------------- - // - // table_base - // - // ----------------------------------- - - class table_signature; - class table_plugin; - class table_base; - - typedef uint64 table_sort; - typedef svector table_signature_base0; - typedef uint64_hash table_sort_hash; - - typedef uint64 table_element; - typedef svector table_fact; - typedef uint64_hash table_element_hash; - - struct table_traits { - typedef table_plugin plugin; - typedef table_base base_object; - typedef table_element element; - typedef table_fact fact; - typedef table_sort sort; - typedef table_signature_base0 signature_base_base; - typedef table_signature signature; - }; - - typedef tr_infrastructure table_infrastructure; - - typedef table_infrastructure::base_fn base_table_fn; - typedef table_infrastructure::join_fn table_join_fn; - typedef table_infrastructure::transformer_fn table_transformer_fn; - typedef table_infrastructure::union_fn table_union_fn; - typedef table_infrastructure::mutator_fn table_mutator_fn; - typedef table_infrastructure::intersection_filter_fn table_intersection_filter_fn; - - typedef table_infrastructure::convenient_join_fn convenient_table_join_fn; - typedef table_infrastructure::convenient_join_project_fn convenient_table_join_project_fn; - typedef table_infrastructure::convenient_transformer_fn convenient_table_transformer_fn; - typedef table_infrastructure::convenient_project_fn convenient_table_project_fn; - typedef table_infrastructure::convenient_rename_fn convenient_table_rename_fn; - typedef table_infrastructure::convenient_negation_filter_fn convenient_table_negation_filter_fn; - typedef table_infrastructure::identity_transformer_fn identity_table_transformer_fn; - typedef table_infrastructure::identity_mutator_fn identity_table_mutator_fn; - typedef table_infrastructure::identity_intersection_filter_fn identity_table_intersection_filter_fn; - typedef table_infrastructure::default_permutation_rename_fn default_table_permutation_rename_fn; - - class table_row_mutator_fn { - public: - /** - \brief The function is called for a particular table row. The \c func_columns contains - a pointer to an array of functional column values that can be modified. If the function - returns true, the modification will appear in the table; otherwise the row will be deleted. - - It is possible that one call to the function stands for multiple table rows that share - the same functional column values. - */ - virtual bool operator()(table_element * func_columns) = 0; - }; - - class table_row_pair_reduce_fn { - public: - /** - \brief The function is called for pair of table rows that became duplicit due to projection. - The values that are in the first array after return from the function will be used for the - resulting row. - - It is assumed that the function is idempotent: when the two functional sub-tuples are equal, - the result is assumed to be equal to them as well, so the function may not be evaluated for them. - */ - virtual void operator()(table_element * func_columns, const table_element * merged_func_columns) = 0; - }; - - - class table_signature : public table_infrastructure::signature_base { - public: - struct hash { - unsigned operator()(table_signature const& s) const { - return svector_hash()(s); - } - }; - - struct eq { - bool operator()(table_signature const& s1, table_signature const& s2) const { - return s1 == s2; - } - }; - private: - unsigned m_functional_columns; - public: - table_signature() : m_functional_columns(0) {} - - void swap(table_signature & s) { - signature_base::swap(s); - std::swap(m_functional_columns, s.m_functional_columns); - } - - /** - \brief The returned value is the number of last columns that are functional. - - The uniqueness is enforced on non-functional columns. When projection causes two - facts to have equal non-functional parts, it is not defined which one of them is retained. - */ - unsigned functional_columns() const { return m_functional_columns; } - void set_functional_columns(unsigned val) { SASSERT(size()>=val); m_functional_columns = val; } - - /** - \brief Return index of the first functional column, or the size of the signature if there - are no functional columns. - */ - unsigned first_functional() const { return size()-m_functional_columns; } - - bool operator==(const table_signature & o) const { - return signature_base::operator==(o) && m_functional_columns==o.m_functional_columns; - } - bool operator!=(const table_signature & o) const { - return !(*this==o); - } - - /** - \brief return true iof the two signatures are equal when we ignore which columns are functional. - */ - bool equal_up_to_fn_mark(const table_signature & o) const { - return signature_base::operator==(o); - } - - - /** - \brief Into \c result assign signature of result of join of relations with signatures \c s1 - and \c s2. The result is - - (non-functional of s1)(non-functional of s2)(functional of s1)(functional of s2) - */ - static void from_join(const table_signature & s1, const table_signature & s2, unsigned col_cnt, - const unsigned * cols1, const unsigned * cols2, table_signature & result); - - static void from_join_project(const table_signature & s1, const table_signature & s2, - unsigned joined_col_cnt, const unsigned * cols1, const unsigned * cols2, unsigned removed_col_cnt, - const unsigned * removed_cols, table_signature & result); - - - /** - \brief Into \c result assign signature projected from \c src. - - The array of removed columns must be sorted in ascending order. - - If we remove at least one non-functional column, all the columns in the result are non-functional. - */ - static void from_project(const table_signature & src, unsigned col_cnt, - const unsigned * removed_cols, table_signature & result); - - static void from_project_with_reduce(const table_signature & src, unsigned col_cnt, - const unsigned * removed_cols, table_signature & result); - - /** - \brief Into \c result assign signature \c src with reordered columns. - - Permutations between functional and nonfunctional columns are not allowed. - */ - static void from_rename(const table_signature & src, unsigned cycle_len, - const unsigned * permutation_cycle, table_signature & result) { - signature_base::from_rename(src, cycle_len, permutation_cycle, result); - result.set_functional_columns(src.functional_columns()); -#if Z3DEBUG - unsigned first_src_fun = src.size()-src.functional_columns(); - bool in_func = permutation_cycle[0]>=first_src_fun; - for(unsigned i=1;i=first_src_fun)); - } -#endif - } - - /** - \brief Into \c result assign signature \c src with reordered columns. - - Permutations mixing functional and nonfunctional columns are not allowed. - */ - static void from_permutation_rename(const table_signature & src, - const unsigned * permutation, table_signature & result) { - signature_base::from_permutation_rename(src, permutation, result); - result.set_functional_columns(src.functional_columns()); -#if Z3DEBUG - unsigned sz = src.size(); - unsigned first_src_fun = sz-src.functional_columns(); - for(unsigned i=first_src_fun;i=first_src_fun); - } -#endif - } - - }; - - class table_plugin : public table_infrastructure::plugin_object { - friend class relation_manager; - protected: - table_plugin(symbol const& n, relation_manager & manager) : plugin_object(n, manager) {} - public: - - virtual bool can_handle_signature(const table_signature & s) { return s.functional_columns()==0; } - - protected: - /** - If the returned value is non-zero, the returned object must take ownership of \c mapper. - Otherwise \c mapper must remain unmodified. - */ - virtual table_mutator_fn * mk_map_fn(const table_base & t, table_row_mutator_fn * mapper) { return 0; } - - /** - If the returned value is non-zero, the returned object must take ownership of \c reducer. - Otherwise \c reducer must remain unmodified. - */ - virtual table_transformer_fn * mk_project_with_reduce_fn(const table_base & t, unsigned col_cnt, - const unsigned * removed_cols, table_row_pair_reduce_fn * reducer) { return 0; } - - }; - - class table_base : public table_infrastructure::base_ancestor { - protected: - table_base(table_plugin & plugin, const table_signature & s) - : base_ancestor(plugin, s) {} - virtual ~table_base() {} - public: - virtual table_base * clone() const; - virtual table_base * complement(func_decl* p, const table_element * func_columns = 0) const; - virtual bool empty() const; - - /** - \brief Return true if table contains fact that corresponds to \c f in all non-functional - columns. - */ - virtual bool contains_fact(const table_fact & f) const; - - /** - \brief If \c f (i.e. its non-functional part) is not present in the table, - add it and return true. Otherwise update \c f, so that the values of functional - columns correspond to the ones present in the table. - */ - virtual bool suggest_fact(table_fact & f); - - /** - \brief If \c f (i.e. its non-functional part) is not present in the table, - return false. Otherwise update \c f, so that the values of functional - columns correspond to the ones present in the table and return true. - */ - virtual bool fetch_fact(table_fact & f) const; - - /** - \brief Ensure fact \c f is present in the table (including the values of its functional columns). - */ - virtual void ensure_fact(const table_fact & f); - - virtual void remove_fact(const table_fact & fact) { - SASSERT(fact.size() == get_signature().size()); - remove_fact(fact.c_ptr()); } - - virtual void remove_fact(table_element const* fact) = 0; - virtual void remove_facts(unsigned fact_cnt, const table_fact * facts); - virtual void remove_facts(unsigned fact_cnt, const table_element * facts); - virtual void reset(); - - class row_interface; - - virtual void display(std::ostream & out) const; - - /** - \brief Convert table to a formula that encodes the table. - The columns correspond to bound variables indexed as - 0, .., sig.size()-1 - */ - virtual void to_formula(relation_signature const& sig, expr_ref& fml) const; - - protected: - - - class iterator_core { - unsigned m_ref_cnt; - public: - iterator_core() : m_ref_cnt(0) {} - virtual ~iterator_core() {} - - void inc_ref() { m_ref_cnt++; } - void dec_ref() { - SASSERT(m_ref_cnt>0); - m_ref_cnt--; - if(m_ref_cnt==0) { - dealloc(this); - } - } - - virtual bool is_finished() const = 0; - - virtual row_interface & operator*() = 0; - virtual void operator++() = 0; - virtual bool operator==(const iterator_core & it) { - //we worry about the equality operator only because of checking - //the equality with the end() iterator - if(is_finished() && it.is_finished()) { - return true; - } - return false; - } - private: - //private and undefined copy constructor and assignment operator - iterator_core(const iterator_core &); - iterator_core & operator=(const iterator_core &); - }; - - struct row_iterator_core { - unsigned m_ref_cnt; - public: - row_iterator_core() : m_ref_cnt(0) {} - virtual ~row_iterator_core() {} - - void inc_ref() { m_ref_cnt++; } - void dec_ref() { - SASSERT(m_ref_cnt>0); - m_ref_cnt--; - if(m_ref_cnt==0) { - dealloc(this); - } - } - - virtual bool is_finished() const = 0; - - virtual table_element operator*() = 0; - virtual void operator++() = 0; - virtual bool operator==(const row_iterator_core & it) { - //we worry about the equality operator only because of checking - //the equality with the end() iterator - if(is_finished() && it.is_finished()) { - return true; - } - return false; - } - private: - //private and undefined copy constructor and assignment operator - row_iterator_core(const row_iterator_core &); - row_iterator_core & operator=(const row_iterator_core &); - }; - - public: - class iterator { - friend class table_base; - - ref m_core; - - iterator(iterator_core * core) : m_core(core) {} - public: - /** - \brief Return reference to a row_interface object for the current row. - - The reference is valid only until the \c operator++() is called or - until the iterator is invalidated. - */ - row_interface & operator*() - { return *(*m_core); } - row_interface * operator->() - { return &(*(*m_core)); } - iterator & operator++() - { ++(*m_core); return *this; } - bool operator==(const iterator & it) - { return (*m_core)==(*it.m_core); } - bool operator!=(const iterator & it) - { return !operator==(it); } - }; - - class row_iterator { - friend class table_base; - friend class row_interface; - - ref m_core; - - row_iterator(row_iterator_core * core) : m_core(core) {} - public: - table_element operator*() - { return *(*m_core); } - row_iterator & operator++() - { ++(*m_core); return *this; } - bool operator==(const row_iterator & it) - { return (*m_core)==(*it.m_core); } - bool operator!=(const row_iterator & it) - { return !operator==(it); } - }; - - virtual iterator begin() const = 0; - virtual iterator end() const = 0; - - class row_interface { - class fact_row_iterator; - - const table_base & m_parent_table; - public: - typedef row_iterator iterator; - typedef row_iterator const_iterator; - - row_interface(const table_base & parent_table) : m_parent_table(parent_table) {} - virtual ~row_interface() {} - - virtual table_element operator[](unsigned col) const = 0; - - unsigned size() const { return m_parent_table.get_signature().size(); } - virtual void get_fact(table_fact & result) const; - virtual row_iterator begin() const; - virtual row_iterator end() const; - virtual void display(std::ostream & out) const; - }; - - protected: - - class caching_row_interface : public row_interface { - mutable table_fact m_current; - - bool populated() const { return !m_current.empty(); } - void ensure_populated() const { - if(!populated()) { - get_fact(m_current); - } - } - public: - caching_row_interface(const table_base & parent) : row_interface(parent) {} - - virtual void get_fact(table_fact & result) const = 0; - - virtual table_element operator[](unsigned col) const { - ensure_populated(); - return m_current[col]; - } - /** - \brief Resets the cache of the row object. - - Must be called when the row object begins to represent a different row in the table. - */ - void reset() { m_current.reset(); } - }; - - //This function is here to create iterator instances in classes that derive from table_base. - //We do not want to make the constructor of the iterator class public, and being private, the - //inheritor classes cannot see it directly. - static iterator mk_iterator(iterator_core * core) { - return iterator(core); - } - }; - - -}; - -#endif /* _DL_BASE_H_ */ - diff --git a/src/muz/dl_bound_relation.cpp b/src/muz/dl_bound_relation.cpp deleted file mode 100644 index 182046c1e..000000000 --- a/src/muz/dl_bound_relation.cpp +++ /dev/null @@ -1,707 +0,0 @@ -/*++ -Copyright (c) 2010 Microsoft Corporation - -Module Name: - - dl_bound_relation.cpp - -Abstract: - - Basic (strict upper) bound relation. - -Author: - - Nikolaj Bjorner (nbjorner) 2010-2-11 - -Revision History: - ---*/ - -#include "dl_bound_relation.h" -#include "debug.h" -#include "ast_pp.h" - -namespace datalog { - - bound_relation_plugin::bound_relation_plugin(relation_manager& m): - relation_plugin(bound_relation_plugin::get_name(), m), - m_arith(get_ast_manager()), - m_bsimp(get_ast_manager()) { - } - - bool bound_relation_plugin::can_handle_signature(const relation_signature & sig) { - for (unsigned i = 0; i < sig.size(); ++i) { - if (!m_arith.is_int(sig[i]) && !m_arith.is_real(sig[i])) { - return false; - } - } - return true; - } - - bound_relation& bound_relation_plugin::get(relation_base& r) { - return dynamic_cast(r); - } - - bound_relation const & bound_relation_plugin::get(relation_base const& r) { - return dynamic_cast(r); - } - - bound_relation* bound_relation_plugin::get(relation_base* r) { - return dynamic_cast(r); - } - - bool bound_relation_plugin::is_interval_relation(relation_base const& r) { - return symbol("interval_relation") == r.get_plugin().get_name(); - } - - interval_relation& bound_relation_plugin::get_interval_relation(relation_base& r) { - SASSERT(is_interval_relation(r)); - return dynamic_cast(r); - } - - interval_relation const& bound_relation_plugin::get_interval_relation(relation_base const& r) { - SASSERT(is_interval_relation(r)); - return dynamic_cast(r); - } - - relation_base * bound_relation_plugin::mk_empty(const relation_signature & s) { - return alloc(bound_relation, *this, s, true); - } - - relation_base * bound_relation_plugin::mk_full(func_decl* p, const relation_signature & s) { - return alloc(bound_relation, *this, s, false); - } - - class bound_relation_plugin::join_fn : public convenient_relation_join_fn { - public: - join_fn(const relation_signature & o1_sig, const relation_signature & o2_sig, unsigned col_cnt, - const unsigned * cols1, const unsigned * cols2) - : convenient_relation_join_fn(o1_sig, o2_sig, col_cnt, cols1, cols2) { - } - - virtual relation_base * operator()(const relation_base & _r1, const relation_base & _r2) { - bound_relation const& r1 = get(_r1); - bound_relation const& r2 = get(_r2); - bound_relation_plugin& p = r1.get_plugin(); - bound_relation* result = dynamic_cast(p.mk_full(0, get_result_signature())); - result->mk_join(r1, r2, m_cols1.size(), m_cols1.c_ptr(), m_cols2.c_ptr()); - return result; - } - }; - - relation_join_fn * bound_relation_plugin::mk_join_fn(const relation_base & r1, const relation_base & r2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) { - if (!check_kind(r1) || !check_kind(r2)) { - return 0; - } - return alloc(join_fn, r1.get_signature(), r2.get_signature(), col_cnt, cols1, cols2); - } - - - class bound_relation_plugin::project_fn : public convenient_relation_project_fn { - public: - project_fn(const relation_signature & orig_sig, unsigned removed_col_cnt, const unsigned * removed_cols) - : convenient_relation_project_fn(orig_sig, removed_col_cnt, removed_cols) { - } - - virtual relation_base * operator()(const relation_base & _r) { - bound_relation const& r = get(_r); - bound_relation_plugin& p = r.get_plugin(); - bound_relation* result = get(p.mk_full(0, get_result_signature())); - result->mk_project(r, m_removed_cols.size(), m_removed_cols.c_ptr()); - return result; - } - }; - - relation_transformer_fn * bound_relation_plugin::mk_project_fn(const relation_base & r, - unsigned col_cnt, const unsigned * removed_cols) { - return alloc(project_fn, r.get_signature(), col_cnt, removed_cols); - } - - class bound_relation_plugin::rename_fn : public convenient_relation_rename_fn { - public: - rename_fn(const relation_signature & orig_sig, unsigned cycle_len, const unsigned * cycle) - : convenient_relation_rename_fn(orig_sig, cycle_len, cycle) { - } - - virtual relation_base * operator()(const relation_base & _r) { - bound_relation const& r = get(_r); - bound_relation_plugin& p = r.get_plugin(); - bound_relation* result = get(p.mk_full(0, get_result_signature())); - result->mk_rename(r, m_cycle.size(), m_cycle.c_ptr()); - return result; - } - }; - - relation_transformer_fn * bound_relation_plugin::mk_rename_fn(const relation_base & r, - unsigned cycle_len, const unsigned * permutation_cycle) { - if(check_kind(r)) { - return alloc(rename_fn, r.get_signature(), cycle_len, permutation_cycle); - } - return 0; - } - - - class bound_relation_plugin::union_fn : public relation_union_fn { - bool m_is_widen; - public: - union_fn(bool is_widen) : - m_is_widen(is_widen) { - } - virtual void operator()(relation_base & _r, const relation_base & _src, relation_base * _delta) { - TRACE("bound_relation", _r.display(tout << "dst:\n"); _src.display(tout << "src:\n");); - get(_r).mk_union(get(_src), get(_delta), m_is_widen); - } - }; - - class bound_relation_plugin::union_fn_i : public relation_union_fn { - bool m_is_widen; - public: - union_fn_i(bool is_widen) : - m_is_widen(is_widen) { - } - virtual void operator()(relation_base & _r, const relation_base & _src, relation_base * _delta) { - TRACE("bound_relation", _r.display(tout << "dst:\n"); _src.display(tout << "src:\n");); - get(_r).mk_union_i(get_interval_relation(_src), get(_delta), m_is_widen); - TRACE("bound_relation", _r.display(tout << "dst':\n");); - } - }; - - - relation_union_fn * bound_relation_plugin::mk_union_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta) { - if (check_kind(tgt) && is_interval_relation(src) && (!delta || check_kind(*delta))) { - return alloc(union_fn_i, false); - } - if (check_kind(tgt) && check_kind(src) && (!delta || check_kind(*delta))) { - return alloc(union_fn, false); - } - return 0; - } - - relation_union_fn * bound_relation_plugin::mk_widen_fn( - const relation_base & tgt, const relation_base & src, - const relation_base * delta) { - if (check_kind(tgt) && is_interval_relation(src) && (!delta || check_kind(*delta))) { - return alloc(union_fn_i, true); - } - if (check_kind(tgt) && check_kind(src) && (!delta || check_kind(*delta))) { - return alloc(union_fn, true); - } - return 0; - } - - class bound_relation_plugin::filter_identical_fn : public relation_mutator_fn { - unsigned_vector m_cols; - public: - filter_identical_fn(unsigned col_cnt, const unsigned * identical_cols) - : m_cols(col_cnt, identical_cols) {} - - virtual void operator()(relation_base & r) { - for (unsigned i = 1; i < m_cols.size(); ++i) { - get(r).equate(m_cols[0], m_cols[i]); - } - } - }; - - relation_mutator_fn * bound_relation_plugin::mk_filter_identical_fn( - const relation_base & t, unsigned col_cnt, const unsigned * identical_cols) { - if(check_kind(t)) { - return alloc(filter_identical_fn, col_cnt, identical_cols); - } - return 0; - } - - class bound_relation_plugin::filter_equal_fn : public relation_mutator_fn { - public: - filter_equal_fn(relation_element const& value, unsigned col) {} - - virtual void operator()(relation_base & r) { } - }; - - relation_mutator_fn * bound_relation_plugin::mk_filter_equal_fn(const relation_base & r, - const relation_element & value, unsigned col) { - if (check_kind(r)) { - return alloc(filter_equal_fn, value, col); - } - return 0; - } - - class bound_relation_plugin::filter_interpreted_fn : public relation_mutator_fn { - enum kind_t { NOT_APPLICABLE, EQ_VAR, EQ_SUB, LT_VAR, LE_VAR, K_FALSE }; - app_ref m_cond; - app_ref m_lt; - arith_util m_arith; - interval_relation* m_interval; - unsigned_vector m_vars; - kind_t m_kind; - - unsigned get_var(expr* a) { - SASSERT(is_var(a)); - return to_var(a)->get_idx(); - } - - // x = z - y - void mk_sub_eq(expr* x, expr* z, expr* y) { - SASSERT(is_var(x)); - SASSERT(is_var(z)); - SASSERT(is_var(y)); - m_vars.push_back(get_var(x)); - m_vars.push_back(get_var(z)); - m_vars.push_back(get_var(y)); - m_kind = EQ_SUB; - } - - void mk_lt(expr* l, expr* r) { - SASSERT(is_var(l)); - SASSERT(is_var(r)); - m_vars.push_back(get_var(l)); - m_vars.push_back(get_var(r)); - m_lt = m_arith.mk_lt(l, r); - m_kind = LT_VAR; - } - - - void mk_le(expr* l, expr* r) { - SASSERT(is_var(l)); - SASSERT(is_var(r)); - m_vars.push_back(get_var(l)); - m_vars.push_back(get_var(r)); - m_kind = LE_VAR; - } - - void mk_eq(expr* l, expr* r) { - m_vars.push_back(get_var(l)); - m_vars.push_back(get_var(r)); - m_kind = EQ_VAR; - } - - public: - - filter_interpreted_fn(ast_manager& m, app* cond) : - m_cond(cond, m), - m_lt(m), m_arith(m), m_interval(0), m_kind(NOT_APPLICABLE) { - expr* l, *r, *r1, *r2, *c2; - rational n1; - if ((m_arith.is_lt(cond, l, r) || m_arith.is_gt(cond, r, l)) && - is_var(l) && is_var(r)) { - mk_lt(l, r); - } - else if (m.is_not(cond, c2) && - (m_arith.is_ge(c2, l, r) || m_arith.is_le(c2, r, l)) && - is_var(l) && is_var(r)) { - mk_lt(l, r); - } - else if ((m_arith.is_le(cond, l, r) || m_arith.is_ge(cond, r, l)) && - is_var(l) && is_var(r)) { - mk_le(l, r); - } - else if (m.is_not(cond, c2) && - (m_arith.is_gt(c2, l, r) || m_arith.is_lt(c2, r, l)) && - is_var(l) && is_var(r)) { - mk_le(l, r); - } - else if (m.is_false(cond)) { - m_kind = K_FALSE; - } - else if (m.is_eq(cond, l, r) && is_var(l) && is_var(r)) { - mk_eq(l, r); - } - else if (m.is_eq(cond, l, r) && - m_arith.is_sub(r, r1, r2) && - is_var(l) && is_var(r1) && is_var(r2)) { - mk_sub_eq(l, r1, r2); - } - else if (m.is_eq(cond, l, r) && - m_arith.is_sub(l, r1, r2) && - is_var(r) && is_var(r1) && is_var(r2)) { - mk_sub_eq(r, r1, r2); - } - else if (m.is_eq(cond, l, r) && - m_arith.is_add(r, r1, r2) && - m_arith.is_numeral(r1, n1) && - n1.is_pos() && is_var(l) && is_var(r2)) { - mk_lt(r2, l); - } - else if (m.is_eq(cond, l, r) && - m_arith.is_add(r, r1, r2) && - m_arith.is_numeral(r2, n1) && - n1.is_pos() && is_var(l) && is_var(r1)) { - mk_lt(r1, l); - } - else { - - } - } - - // - // x = z - y - // x = y - // x < y - // x <= y - // x < y + z - // - - void operator()(relation_base& t) { - TRACE("dl", tout << mk_pp(m_cond, m_cond.get_manager()) << "\n"; t.display(tout);); - bound_relation& r = get(t); - switch(m_kind) { - case K_FALSE: - r.set_empty(); - break; - case NOT_APPLICABLE: - break; - case EQ_VAR: - r.equate(m_vars[0], m_vars[1]); - break; - case EQ_SUB: - // TBD - break; - case LT_VAR: - r.mk_lt(m_vars[0], m_vars[1]); - break; - case LE_VAR: - r.mk_le(m_vars[0], m_vars[1]); - break; - default: - UNREACHABLE(); - break; - } - TRACE("dl", t.display(tout << "result\n");); - } - - bool supports_attachment(relation_base& t) { - return is_interval_relation(t); - } - - void attach(relation_base& t) { - SASSERT(is_interval_relation(t)); - interval_relation& r = get_interval_relation(t); - m_interval = &r; - } - }; - - relation_mutator_fn * bound_relation_plugin::mk_filter_interpreted_fn(const relation_base & t, app * condition) { - return alloc(filter_interpreted_fn, t.get_plugin().get_ast_manager(), condition); - } - - // ----------------------------- - // bound_relation - - void bound_relation_helper::mk_project_t(uint_set2& t, unsigned_vector const& renaming) { - if (t.lt.empty() && t.le.empty()) { - return; - } - uint_set::iterator it = t.lt.begin(), end = t.lt.end(); - unsigned_vector ltv, lev; - for (; it != end; ++it) { - ltv.push_back(renaming[*it]); - } - it = t.le.begin(), end = t.le.end(); - for (; it != end; ++it) { - lev.push_back(renaming[*it]); - } - TRACE("dl", - tout << "project: "; - for (unsigned i = 0; i < renaming.size(); ++i) - if (renaming[i] == UINT_MAX) tout << i << " "; - tout << ": "; - it = t.lt.begin(); end = t.lt.end(); - for (; it != end; ++it) tout << *it << " "; - tout << " le "; - it = t.le.begin(); end = t.le.end(); - for (; it != end; ++it) tout << *it << " "; - tout << " => "; - for (unsigned i = 0; i < ltv.size(); ++i) tout << ltv[i] << " "; - tout << " le "; - for (unsigned i = 0; i < lev.size(); ++i) tout << lev[i] << " "; - tout << "\n";); - t.lt.reset(); - for (unsigned i = 0; i < ltv.size(); ++i) { - t.lt.insert(ltv[i]); - } - t.le.reset(); - for (unsigned i = 0; i < lev.size(); ++i) { - t.le.insert(lev[i]); - } - } - - bound_relation::bound_relation(bound_relation_plugin& p, relation_signature const& s, bool is_empty): - vector_relation(p, s, is_empty, uint_set2()) - { - } - - - uint_set2 bound_relation::mk_intersect(uint_set2 const& t1, uint_set2 const& t2, bool& is_empty) const { - is_empty = false; - uint_set2 r(t1); - r.lt |= t2.lt; - r.le |= t2.le; - return r; - } - - uint_set2 bound_relation::mk_widen(uint_set2 const& t1, uint_set2 const& t2) const { - return mk_unite(t1, t2); - } - - uint_set2 bound_relation::mk_unite(uint_set2 const& t1, uint_set2 const& t2) const { - uint_set2 s1(t1); - s1.lt &= t2.lt; - s1.le &= t2.le; - return s1; - } - - uint_set2 bound_relation::mk_eq(union_find<> const& old_eqs, union_find<> const& new_eqs, uint_set2 const& t) const { - unsigned sz = old_eqs.get_num_vars(); - SASSERT(sz == new_eqs.get_num_vars()); - uint_set2 result; - for (unsigned i = 0; i < sz; ++i) { - if (t.lt.contains(i)) { - unsigned j = i; - do { - result.lt.insert(new_eqs.find(j)); - j = old_eqs.next(j); - } - while (j != i); - } - if (t.le.contains(i)) { - unsigned j = i; - do { - result.le.insert(new_eqs.find(j)); - j = old_eqs.next(j); - } - while (j != i); - } - } - return result; - } - - bool bound_relation::is_subset_of(uint_set2 const& t1, uint_set2 const& t2) const { - uint_set2 s1, s2; - normalize(t1, s1); - normalize(t2, s2); - return s1.lt.subset_of(s2.lt) && s1.le.subset_of(s2.le); - } - - void bound_relation::mk_rename_elem(uint_set2& t, unsigned col_cnt, unsigned const* cycle) { - // [ 0 -> 2 -> 3 -> 0] - if (col_cnt == 0) return; - unsigned col1, col2; - col1 = find(cycle[0]); - col2 = find(cycle[col_cnt-1]); - bool has_col2_lt = t.lt.contains(col2); - t.lt.remove(col2); - bool has_col2_le = t.le.contains(col2); - t.le.remove(col2); - for (unsigned i = 0; i + 1 < col_cnt; ++i) { - col1 = find(cycle[i]); - col2 = find(cycle[i+1]); - if (t.lt.contains(col1)) { - t.lt.remove(col1); - t.lt.insert(col2); - } - if (t.le.contains(col1)) { - t.le.remove(col1); - t.le.insert(col2); - } - } - if (has_col2_lt) { - col1 = find(cycle[0]); - t.lt.insert(col1); - } - if (has_col2_le) { - col1 = find(cycle[0]); - t.le.insert(col1); - } - } - - - bool bound_relation::is_full(uint_set2 const& t) const { - return t.lt.empty() && t.le.empty(); - } - - bool bound_relation::is_empty(unsigned index, uint_set2 const& t) const { - return t.lt.contains(find(index)) || t.le.contains(find(index)); - } - - void bound_relation::normalize(uint_set const& src, uint_set& dst) const { - uint_set::iterator it = src.begin(), end = src.end(); - for (; it != end; ++it) { - dst.insert(find(*it)); - } - } - void bound_relation::normalize(uint_set2 const& src, uint_set2& dst) const { - normalize(src.lt, dst.lt); - normalize(src.le, dst.le); - } - - - void bound_relation::mk_lt(unsigned i) { - uint_set2& dst = (*this)[i]; - while (!m_todo.empty()) { - unsigned j = m_todo.back().first; - bool strict = m_todo.back().second; - if (i == j && strict) { - m_todo.reset(); - m_empty = true; - return; - } - m_todo.pop_back(); - if (i == j) { - continue; - } - uint_set2& src = (*m_elems)[j]; - uint_set::iterator it = src.lt.begin(), end = src.lt.end(); - for(; it != end; ++it) { - m_todo.push_back(std::make_pair(*it, true)); - } - it = src.le.begin(), end = src.le.end(); - for(; it != end; ++it) { - m_todo.push_back(std::make_pair(*it, strict)); - } - if (strict) { - dst.lt.insert(j); - } - else { - dst.le.insert(j); - } - } - } - - void bound_relation::mk_lt(unsigned i, unsigned j) { - m_todo.reset(); - i = find(i); - m_todo.push_back(std::make_pair(find(j), true)); - mk_lt(i); - } - - void bound_relation::mk_le(unsigned i, unsigned j) { - m_todo.reset(); - i = find(i); - m_todo.push_back(std::make_pair(find(j), false)); - mk_lt(i); - } - - bool bound_relation::is_lt(unsigned i, unsigned j) const { - return (*this)[i].lt.contains(find(j)); - } - - void bound_relation::add_fact(const relation_fact & f) { - bound_relation r(get_plugin(), get_signature(), false); - for (unsigned i = 0; i < f.size(); ++i) { - scoped_ptr fe = get_plugin().mk_filter_equal_fn(r, f[i], i); - (*fe)(r); - } - mk_union(r, 0, false); - } - - bool bound_relation::contains_fact(const relation_fact & f) const { - if (empty()) { - return false; - } - // this is a very rough approximation. - return true; - } - - bound_relation * bound_relation::clone() const { - bound_relation* result = 0; - if (empty()) { - result = bound_relation_plugin::get(get_plugin().mk_empty(get_signature())); - } - else { - result = bound_relation_plugin::get(get_plugin().mk_full(0, get_signature())); - result->copy(*this); - } - return result; - } - - void bound_relation::mk_union_i(interval_relation const& src, bound_relation* delta, bool is_widen) { - unsigned size = get_signature().size(); - for (unsigned i = 0; i < size; ++i) { - if (find(i) != i) { - continue; - } - uint_set2& s = (*this)[i]; - ext_numeral const& lo = src[i].sup(); - if (lo.is_infinite()) { - s.lt.reset(); - s.le.reset(); - continue; - } - uint_set::iterator it = s.lt.begin(), end = s.lt.end(); - for(; it != end; ++it) { - ext_numeral const& hi = src[*it].inf(); - if (hi.is_infinite() || lo.to_rational() >= hi.to_rational()) { - s.lt.remove(*it); - } - } - it = s.le.begin(), end = s.le.end(); - for(; it != end; ++it) { - ext_numeral const& hi = src[*it].inf(); - if (hi.is_infinite() || lo.to_rational() > hi.to_rational()) { - s.le.remove(*it); - } - } - } - } - - bound_relation * bound_relation::complement(func_decl* p) const { - UNREACHABLE(); - return 0; - } - - void bound_relation::to_formula(expr_ref& fml) const { - ast_manager& m = get_plugin().get_ast_manager(); - arith_util& arith = get_plugin().m_arith; - basic_simplifier_plugin& bsimp = get_plugin().m_bsimp; - expr_ref_vector conjs(m); - relation_signature const& sig = get_signature(); - for (unsigned i = 0; i < sig.size(); ++i) { - if (i != find(i)) { - conjs.push_back(m.mk_eq(m.mk_var(i, sig[i]), m.mk_var(find(i), sig[find(i)]))); - continue; - } - uint_set2 const& upper = (*this)[i]; - uint_set::iterator it = upper.lt.begin(), end = upper.lt.end(); - for (; it != end; ++it) { - conjs.push_back(arith.mk_lt(m.mk_var(i, sig[i]), m.mk_var(*it, sig[*it]))); - } - it = upper.le.begin(), end = upper.le.end(); - for (; it != end; ++it) { - conjs.push_back(arith.mk_le(m.mk_var(i, sig[i]), m.mk_var(*it, sig[*it]))); - } - } - bsimp.mk_and(conjs.size(), conjs.c_ptr(), fml); - } - - - void bound_relation::display_index(unsigned i, uint_set2 const& src, std::ostream & out) const { - uint_set::iterator it = src.lt.begin(), end = src.lt.end(); - out << "#" << i; - if (!src.lt.empty()) { - out << " < "; - for(; it != end; ++it) { - out << *it << " "; - } - } - if (!src.le.empty()) { - it = src.le.begin(), end = src.le.end(); - out << " <= "; - for(; it != end; ++it) { - out << *it << " "; - } - } - if (src.lt.empty() && src.le.empty()) { - out << " < oo"; - } - out << "\n"; - } - - bound_relation_plugin& bound_relation::get_plugin() const { - return dynamic_cast(relation_base::get_plugin()); - } - - -}; - - diff --git a/src/muz/dl_bound_relation.h b/src/muz/dl_bound_relation.h deleted file mode 100644 index 04479b3b6..000000000 --- a/src/muz/dl_bound_relation.h +++ /dev/null @@ -1,176 +0,0 @@ -/*++ -Copyright (c) 2010 Microsoft Corporation - -Module Name: - - dl_bound_relation.h - -Abstract: - - Basic (strict upper) bound relation. - -Author: - - Nikolaj Bjorner (nbjorner) 2010-2-11 - -Revision History: - ---*/ -#ifndef _DL_BOUND_RELATION_H_ -#define _DL_BOUND_RELATION_H_ - -#include "dl_context.h" -#include "uint_set.h" -#include "dl_vector_relation.h" -#include "dl_interval_relation.h" -#include "arith_decl_plugin.h" -#include "basic_simplifier_plugin.h" - -namespace datalog { - - class bound_relation; - - class bound_relation_plugin : public relation_plugin { - friend class bound_relation; - class join_fn; - class project_fn; - class rename_fn; - class union_fn; - class union_fn_i; - class filter_equal_fn; - class filter_identical_fn; - class filter_interpreted_fn; - class filter_intersection_fn; - arith_util m_arith; - basic_simplifier_plugin m_bsimp; - public: - bound_relation_plugin(relation_manager& m); - virtual bool can_handle_signature(const relation_signature & s); - static symbol get_name() { return symbol("bound_relation"); } - virtual relation_base * mk_empty(const relation_signature & s); - virtual relation_base * mk_full(func_decl* p, const relation_signature & s); - virtual relation_join_fn * mk_join_fn(const relation_base & t1, const relation_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2); - virtual relation_transformer_fn * mk_project_fn(const relation_base & t, unsigned col_cnt, - const unsigned * removed_cols); - virtual relation_transformer_fn * mk_rename_fn(const relation_base & t, unsigned permutation_cycle_len, - const unsigned * permutation_cycle); - virtual relation_union_fn * mk_union_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta); - virtual relation_union_fn * mk_widen_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta); - virtual relation_mutator_fn * mk_filter_identical_fn(const relation_base & t, unsigned col_cnt, - const unsigned * identical_cols); - virtual relation_mutator_fn * mk_filter_equal_fn(const relation_base & t, const relation_element & value, - unsigned col); - virtual relation_mutator_fn * mk_filter_interpreted_fn(const relation_base & t, app * condition); - - virtual relation_join_fn * mk_join_project_fn(const relation_base & t1, const relation_base & t2, - unsigned joined_col_cnt, const unsigned * cols1, const unsigned * cols2, - unsigned removed_col_cnt, const unsigned * removed_cols) { return 0; } - - -#if 0 - virtual intersection_filter_fn * mk_filter_by_intersection_fn( - const relation_base & t, - const relation_base & src, unsigned joined_col_cnt, - const unsigned * t_cols, const unsigned * src_cols) { - return 0; - } -#endif - - static bound_relation* get(relation_base* r); - private: - static bound_relation& get(relation_base& r); - static bound_relation const & get(relation_base const& r); - - - static bool is_interval_relation(relation_base const& r); - static interval_relation& get_interval_relation(relation_base& r); - static interval_relation const& get_interval_relation(relation_base const& r); - }; - - struct uint_set2 { - uint_set lt; - uint_set le; - uint_set2(uint_set2 const& other):lt(other.lt), le(other.le) {} - uint_set2() {} - bool operator==(const uint_set2& other) const { - return other.lt == lt && other.le == le; - } - bool operator!=(const uint_set2& other) const { - return other.lt != lt || other.le != le; - } - }; - - inline std::ostream & operator<<(std::ostream & target, const uint_set2 & s) { - return target << s.lt << " " << s.le; - } - - - class bound_relation_helper { - public: - static void mk_project_t(uint_set2& t, unsigned_vector const& renaming); - }; - - class bound_relation : public vector_relation { - friend class bound_relation_plugin; - svector > m_todo; - - public: - bound_relation(bound_relation_plugin& p, relation_signature const& s, bool is_empty); - bound_relation& operator=(bound_relation const& other); - - virtual bool empty() const { return m_empty; } - virtual void add_fact(const relation_fact & f); - virtual bool contains_fact(const relation_fact & f) const; - virtual bound_relation * clone() const; - virtual bound_relation * complement(func_decl* p) const; - virtual void to_formula(expr_ref& fml) const; - bound_relation_plugin& get_plugin() const; - - void mk_union_i(interval_relation const& src, bound_relation* delta, bool is_widen); - - void mk_lt(unsigned i, unsigned j); - - void mk_lt(unsigned i); - - void mk_le(unsigned i, unsigned j); - - bool is_lt(unsigned i, unsigned j) const; - - virtual bool is_precise() const { return false; } - - private: - typedef uint_set2 T; - virtual T mk_intersect(T const& t1, T const& t2, bool& is_empty) const; - - virtual T mk_widen(T const& t1, T const& t2) const; - - virtual T mk_unite(T const& t1, T const& t2) const; - - virtual T mk_eq(union_find<> const& old_eqs, union_find<> const& new_eqs, T const& t) const; - - virtual void mk_rename_elem(T& i, unsigned col_cnt, unsigned const* cycle); - - - virtual bool is_subset_of(T const& t1, T const& t2) const; - - virtual bool is_full(T const& t) const; - - virtual bool is_empty(unsigned idx, T const& t) const; - - virtual void display_index(unsigned idx, T const& t, std::ostream& out) const; - - void normalize(T const& src, T& dst) const; - - void normalize(uint_set const& src, uint_set& dst) const; - - - - }; - -}; - -#endif - diff --git a/src/muz/dl_check_table.cpp b/src/muz/dl_check_table.cpp deleted file mode 100644 index ea4003e5f..000000000 --- a/src/muz/dl_check_table.cpp +++ /dev/null @@ -1,439 +0,0 @@ -/*++ -Copyright (c) 2010 Microsoft Corporation - -Module Name: - - dl_check_table.cpp - -Abstract: - - - -Author: - - Nikolaj Bjorner (nbjorner) 2010-11-15 - - -Revision History: - ---*/ - - -#include "dl_check_table.h" -#include "dl_table.h" - - -namespace datalog { - - bool check_table_plugin::can_handle_signature(table_signature const& s) { - return m_tocheck.can_handle_signature(s) && m_checker.can_handle_signature(s); - } - - - check_table & check_table_plugin::get(table_base& r) { - return static_cast(r); - } - - check_table const & check_table_plugin::get(table_base const& r) { - return static_cast(r); - } - - table_base& check_table_plugin::checker(table_base& r) { return *get(r).m_checker; } - table_base const& check_table_plugin::checker(table_base const& r) { return *get(r).m_checker; } - table_base* check_table_plugin::checker(table_base* r) { return r?(get(*r).m_checker):0; } - table_base const* check_table_plugin::checker(table_base const* r) { return r?(get(*r).m_checker):0; } - table_base& check_table_plugin::tocheck(table_base& r) { return *get(r).m_tocheck; } - table_base const& check_table_plugin::tocheck(table_base const& r) { return *get(r).m_tocheck; } - table_base* check_table_plugin::tocheck(table_base* r) { return r?(get(*r).m_tocheck):0; } - table_base const* check_table_plugin::tocheck(table_base const* r) { return r?(get(*r).m_tocheck):0; } - - table_base * check_table_plugin::mk_empty(const table_signature & s) { - IF_VERBOSE(1, verbose_stream() << __FUNCTION__ << "\n";); - table_base* checker = m_checker.mk_empty(s); - table_base* tocheck = m_tocheck.mk_empty(s); - return alloc(check_table, *this, s, tocheck, checker); - } - - class check_table_plugin::join_fn : public table_join_fn { - scoped_ptr m_tocheck; - scoped_ptr m_checker; - public: - join_fn(check_table_plugin& p, - const table_base & t1, const table_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) { - m_tocheck = p.get_manager().mk_join_fn(tocheck(t1), tocheck(t2), col_cnt, cols1, cols2); - m_checker = p.get_manager().mk_join_fn(checker(t1), checker(t2), col_cnt, cols1, cols2); - } - - virtual table_base* operator()(const table_base & t1, const table_base & t2) { - IF_VERBOSE(1, verbose_stream() << __FUNCTION__ << "\n";); - table_base* ttocheck = (*m_tocheck)(tocheck(t1), tocheck(t2)); - table_base* tchecker = (*m_checker)(checker(t1), checker(t2)); - check_table* result = alloc(check_table, get(t1).get_plugin(), ttocheck->get_signature(), ttocheck, tchecker); - return result; - } - }; - - table_join_fn * check_table_plugin::mk_join_fn(const table_base & t1, const table_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) { - if (!check_kind(t1) || !check_kind(t2)) { - return 0; - } - return alloc(join_fn, *this, t1, t2, col_cnt, cols1, cols2); - } - - class check_table_plugin::join_project_fn : public table_join_fn { - scoped_ptr m_tocheck; - scoped_ptr m_checker; - public: - join_project_fn(check_table_plugin& p, const table_base & t1, const table_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2, - unsigned removed_col_cnt, const unsigned * removed_cols) { - m_tocheck = p.get_manager().mk_join_project_fn(tocheck(t1), tocheck(t2), col_cnt, cols1, cols2, removed_col_cnt, removed_cols); - m_checker = p.get_manager().mk_join_project_fn(checker(t1), checker(t2), col_cnt, cols1, cols2, removed_col_cnt, removed_cols); - } - - virtual table_base* operator()(const table_base & t1, const table_base & t2) { - table_base* ttocheck = (*m_tocheck)(tocheck(t1), tocheck(t2)); - table_base* tchecker = (*m_checker)(checker(t1), checker(t2)); - check_table* result = alloc(check_table, get(t1).get_plugin(), ttocheck->get_signature(), ttocheck, tchecker); - return result; - } - }; - - table_join_fn * check_table_plugin::mk_join_project_fn(const table_base & t1, const table_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2, unsigned removed_col_cnt, - const unsigned * removed_cols) { - if (!check_kind(t1) || !check_kind(t2)) { - return 0; - } - return alloc(join_project_fn, *this, t1, t2, col_cnt, cols1, cols2, removed_col_cnt, removed_cols); - } - - class check_table_plugin::union_fn : public table_union_fn { - scoped_ptr m_tocheck; - scoped_ptr m_checker; - public: - union_fn(check_table_plugin& p, table_base const& tgt, const table_base& src, table_base const* delta) { - m_tocheck = p.get_manager().mk_union_fn(tocheck(tgt), tocheck(src), tocheck(delta)); - m_checker = p.get_manager().mk_union_fn(checker(tgt), checker(src), checker(delta)); - } - - virtual void operator()(table_base& tgt, const table_base& src, table_base* delta) { - IF_VERBOSE(1, verbose_stream() << __FUNCTION__ << "\n";); - (*m_tocheck)(tocheck(tgt), tocheck(src), tocheck(delta)); - (*m_checker)(checker(tgt), checker(src), checker(delta)); - get(tgt).well_formed(); - if (delta) { - get(*delta).well_formed(); - } - } - }; - - table_union_fn * check_table_plugin::mk_union_fn(const table_base & tgt, const table_base & src, const table_base * delta) { - if (!check_kind(tgt) || !check_kind(src) || (delta && !check_kind(*delta))) { - return 0; - } - return alloc(union_fn, *this, tgt, src, delta); - - } - - class check_table_plugin::project_fn : public table_transformer_fn { - scoped_ptr m_checker; - scoped_ptr m_tocheck; - public: - project_fn(check_table_plugin& p, const table_base & t, unsigned col_cnt, const unsigned * removed_cols) { - m_checker = p.get_manager().mk_project_fn(checker(t), col_cnt, removed_cols); - m_tocheck = p.get_manager().mk_project_fn(tocheck(t), col_cnt, removed_cols); - } - - table_base* operator()(table_base const& src) { - table_base* tchecker = (*m_checker)(checker(src)); - table_base* ttocheck = (*m_tocheck)(tocheck(src)); - check_table* result = alloc(check_table, get(src).get_plugin(), tchecker->get_signature(), ttocheck, tchecker); - return result; - } - }; - - table_transformer_fn * check_table_plugin::mk_project_fn(const table_base & t, unsigned col_cnt, const unsigned * removed_cols) { - if (!check_kind(t)) { - return 0; - } - return alloc(project_fn, *this, t, col_cnt, removed_cols); - } - - class check_table_plugin::select_equal_and_project_fn : public table_transformer_fn { - scoped_ptr m_checker; - scoped_ptr m_tocheck; - public: - select_equal_and_project_fn(check_table_plugin& p, const table_base & t, const table_element & value, unsigned col) { - m_checker = p.get_manager().mk_select_equal_and_project_fn(checker(t), value, col); - m_tocheck = p.get_manager().mk_select_equal_and_project_fn(tocheck(t), value, col); - } - - table_base* operator()(table_base const& src) { - table_base* tchecker = (*m_checker)(checker(src)); - table_base* ttocheck = (*m_tocheck)(tocheck(src)); - check_table* result = alloc(check_table, get(src).get_plugin(), tchecker->get_signature(), ttocheck, tchecker); - return result; - } - }; - - table_transformer_fn * check_table_plugin::mk_select_equal_and_project_fn(const table_base & t, - const table_element & value, unsigned col) { - if (!check_kind(t)) { - return 0; - } - return alloc(select_equal_and_project_fn, *this, t, value, col); - } - - class check_table_plugin::rename_fn : public table_transformer_fn { - scoped_ptr m_checker; - scoped_ptr m_tocheck; - public: - rename_fn(check_table_plugin& p, const table_base & t, unsigned cycle_len, unsigned const* cycle) { - m_checker = p.get_manager().mk_rename_fn(checker(t), cycle_len, cycle); - m_tocheck = p.get_manager().mk_rename_fn(tocheck(t), cycle_len, cycle); - } - - table_base* operator()(table_base const& src) { - IF_VERBOSE(1, verbose_stream() << __FUNCTION__ << "\n";); - table_base* tchecker = (*m_checker)(checker(src)); - table_base* ttocheck = (*m_tocheck)(tocheck(src)); - check_table* result = alloc(check_table, get(src).get_plugin(), ttocheck->get_signature(), ttocheck, tchecker); - return result; - } - }; - - table_transformer_fn * check_table_plugin::mk_rename_fn(const table_base & t, unsigned len, const unsigned * cycle) { - if (!check_kind(t)) { - return 0; - } - return alloc(rename_fn, *this, t, len, cycle); - } - - class check_table_plugin::filter_identical_fn : public table_mutator_fn { - scoped_ptr m_checker; - scoped_ptr m_tocheck; - public: - filter_identical_fn(check_table_plugin& p, const table_base & t,unsigned cnt, unsigned const* cols) - { - m_checker = p.get_manager().mk_filter_identical_fn(checker(t), cnt, cols); - m_tocheck = p.get_manager().mk_filter_identical_fn(tocheck(t), cnt, cols); - } - - void operator()(table_base & t) { - (*m_checker)(checker(t)); - (*m_tocheck)(tocheck(t)); - get(t).well_formed(); - } - }; - - table_mutator_fn * check_table_plugin::mk_filter_identical_fn(const table_base & t, unsigned col_cnt, - const unsigned * identical_cols) { - if (check_kind(t)) { - return alloc(filter_identical_fn, *this, t, col_cnt, identical_cols); - } - return 0; - } - - class check_table_plugin::filter_equal_fn : public table_mutator_fn { - scoped_ptr m_checker; - scoped_ptr m_tocheck; - public: - filter_equal_fn(check_table_plugin& p, const table_base & t, const table_element & v, unsigned col) - { - m_checker = p.get_manager().mk_filter_equal_fn(checker(t), v, col); - m_tocheck = p.get_manager().mk_filter_equal_fn(tocheck(t), v, col); - } - - virtual void operator()(table_base& src) { - (*m_checker)(checker(src)); - (*m_tocheck)(tocheck(src)); - get(src).well_formed(); - } - }; - - table_mutator_fn * check_table_plugin::mk_filter_equal_fn(const table_base & t, const table_element & value, unsigned col) { - if (check_kind(t)) { - return alloc(filter_equal_fn, *this, t, value, col); - } - return 0; - } - - class check_table_plugin::filter_interpreted_fn : public table_mutator_fn { - scoped_ptr m_checker; - scoped_ptr m_tocheck; - public: - filter_interpreted_fn(check_table_plugin& p, const table_base & t, app * condition) - { - m_checker = p.get_manager().mk_filter_interpreted_fn(checker(t), condition); - m_tocheck = p.get_manager().mk_filter_interpreted_fn(tocheck(t), condition); - } - - virtual void operator()(table_base& src) { - (*m_checker)(checker(src)); - (*m_tocheck)(tocheck(src)); - get(src).well_formed(); - } - }; - - table_mutator_fn * check_table_plugin::mk_filter_interpreted_fn(const table_base & t, app * condition) { - if (check_kind(t)) { - return alloc(filter_interpreted_fn, *this, t, condition); - } - return 0; - } - - class check_table_plugin::filter_interpreted_and_project_fn : public table_transformer_fn { - scoped_ptr m_checker; - scoped_ptr m_tocheck; - public: - filter_interpreted_and_project_fn(check_table_plugin& p, const table_base & t, app * condition, - unsigned removed_col_cnt, const unsigned * removed_cols) - { - m_checker = p.get_manager().mk_filter_interpreted_and_project_fn(checker(t), condition, removed_col_cnt, removed_cols); - m_tocheck = p.get_manager().mk_filter_interpreted_and_project_fn(tocheck(t), condition, removed_col_cnt, removed_cols); - } - - table_base* operator()(table_base const& src) { - table_base* tchecker = (*m_checker)(checker(src)); - table_base* ttocheck = (*m_tocheck)(tocheck(src)); - check_table* result = alloc(check_table, get(src).get_plugin(), ttocheck->get_signature(), ttocheck, tchecker); - return result; - } - }; - - table_transformer_fn * check_table_plugin::mk_filter_interpreted_and_project_fn(const table_base & t, - app * condition, unsigned removed_col_cnt, const unsigned * removed_cols) { - if (check_kind(t)) { - return alloc(filter_interpreted_and_project_fn, *this, t, condition, removed_col_cnt, removed_cols); - } - return 0; - } - - class check_table_plugin::filter_by_negation_fn : public table_intersection_filter_fn { - scoped_ptr m_checker; - scoped_ptr m_tocheck; - public: - filter_by_negation_fn( - check_table_plugin& p, - const table_base & t, - const table_base & negated_obj, unsigned joined_col_cnt, - const unsigned * t_cols, const unsigned * negated_cols) { - m_checker = p.get_manager().mk_filter_by_negation_fn(checker(t), checker(negated_obj), joined_col_cnt, t_cols, negated_cols); - m_tocheck = p.get_manager().mk_filter_by_negation_fn(tocheck(t), tocheck(negated_obj), joined_col_cnt, t_cols, negated_cols); - } - - virtual void operator()(table_base& src, table_base const& negated_obj) { - IF_VERBOSE(1, verbose_stream() << __FUNCTION__ << "\n";); - (*m_checker)(checker(src), checker(negated_obj)); - (*m_tocheck)(tocheck(src), tocheck(negated_obj)); - get(src).well_formed(); - } - - }; - - table_intersection_filter_fn * check_table_plugin::mk_filter_by_negation_fn(const table_base & t, - const table_base & negated_obj, unsigned joined_col_cnt, - const unsigned * t_cols, const unsigned * negated_cols) { - if (check_kind(t) && check_kind(negated_obj)) { - return alloc(filter_by_negation_fn, *this, t, negated_obj, joined_col_cnt, t_cols, negated_cols); - } - return 0; - } - - // ------------------ - // check_table - - - check_table::check_table(check_table_plugin & p, const table_signature & sig): - table_base(p, sig) { - (well_formed()); - } - - check_table::check_table(check_table_plugin & p, const table_signature & sig, table_base* tocheck, table_base* checker): - table_base(p, sig), - m_checker(checker), - m_tocheck(tocheck) { - well_formed(); - } - - check_table::~check_table() { - m_tocheck->deallocate(); - m_checker->deallocate(); - } - - bool check_table::well_formed() const { - get_plugin().m_count++; - iterator it = m_tocheck->begin(), end = m_tocheck->end(); - for (; it != end; ++it) { - table_fact fact; - it->get_fact(fact); - if (!m_checker->contains_fact(fact)) { - m_tocheck->display(verbose_stream()); - m_checker->display(verbose_stream()); - verbose_stream() << get_plugin().m_count << "\n"; - UNREACHABLE(); - fatal_error(0); - return false; - } - } - iterator it2 = m_checker->begin(), end2 = m_checker->end(); - for (; it2 != end2; ++it2) { - table_fact fact; - it2->get_fact(fact); - if (!m_tocheck->contains_fact(fact)) { - m_tocheck->display(verbose_stream()); - m_checker->display(verbose_stream()); - verbose_stream() << get_plugin().m_count << "\n"; - UNREACHABLE(); - fatal_error(0); - return false; - } - } - return true; - } - - bool check_table::empty() const { - if (m_tocheck->empty() != m_checker->empty()) { - m_tocheck->display(verbose_stream()); - m_checker->display(verbose_stream()); - verbose_stream() << get_plugin().m_count << "\n"; - fatal_error(0); - } - return m_tocheck->empty(); - } - - - void check_table::add_fact(const table_fact & f) { - IF_VERBOSE(1, verbose_stream() << __FUNCTION__ << "\n";); - m_tocheck->add_fact(f); - m_checker->add_fact(f); - well_formed(); - } - - void check_table::remove_fact(const table_element* f) { - IF_VERBOSE(1, verbose_stream() << __FUNCTION__ << "\n";); - m_tocheck->remove_fact(f); - m_checker->remove_fact(f); - well_formed(); - } - - bool check_table::contains_fact(const table_fact & f) const { - return m_checker->contains_fact(f); - } - - table_base * check_table::clone() const { - IF_VERBOSE(1, verbose_stream() << __FUNCTION__ << "\n";); - check_table* result = alloc(check_table, get_plugin(), get_signature(), m_tocheck->clone(), m_checker->clone()); - return result; - } - - table_base * check_table::complement(func_decl* p, const table_element * func_columns) const { - check_table* result = alloc(check_table, get_plugin(), get_signature(), m_tocheck->complement(p, func_columns), m_checker->complement(p, func_columns)); - return result; - } - -}; - diff --git a/src/muz/dl_check_table.h b/src/muz/dl_check_table.h deleted file mode 100644 index e4f439590..000000000 --- a/src/muz/dl_check_table.h +++ /dev/null @@ -1,135 +0,0 @@ -/*++ -Copyright (c) 2010 Microsoft Corporation - -Module Name: - - dl_check_table.h - -Abstract: - - - -Author: - - Nikolaj Bjorner (nbjorner) 2010-11-15 - - -Revision History: - ---*/ - -#ifndef _DL_CHECK_TABLE_H_ -#define _DL_CHECK_TABLE_H_ - -#include "dl_base.h" -#include "dl_decl_plugin.h" -#include "dl_relation_manager.h" - -namespace datalog { - class check_table; - - class check_table_plugin : public table_plugin { - friend class check_table; - table_plugin& m_checker; - table_plugin& m_tocheck; - unsigned m_count; - protected: - class join_fn; - class join_project_fn; - class union_fn; - class transformer_fn; - class rename_fn; - class project_fn; - class select_equal_and_project_fn; - class filter_equal_fn; - class filter_identical_fn; - class filter_interpreted_fn; - class filter_interpreted_and_project_fn; - class filter_by_negation_fn; - - public: - check_table_plugin(relation_manager & manager, symbol const& checker, symbol const& tocheck) - : table_plugin(symbol("check"), manager), - m_checker(*manager.get_table_plugin(checker)), - m_tocheck(*manager.get_table_plugin(tocheck)), m_count(0) {} - - virtual table_base * mk_empty(const table_signature & s); - - virtual table_join_fn * mk_join_fn(const table_base & t1, const table_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2); - virtual table_join_fn * mk_join_project_fn(const table_base & t1, const table_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2, unsigned removed_col_cnt, - const unsigned * removed_cols); - virtual table_union_fn * mk_union_fn(const table_base & tgt, const table_base & src, - const table_base * delta); - virtual table_transformer_fn * mk_project_fn(const table_base & t, unsigned col_cnt, - const unsigned * removed_cols); - virtual table_transformer_fn * mk_select_equal_and_project_fn(const table_base & t, - const table_element & value, unsigned col); - virtual table_transformer_fn * mk_rename_fn(const table_base & t, unsigned permutation_cycle_len, - const unsigned * permutation_cycle); - virtual table_mutator_fn * mk_filter_identical_fn(const table_base & t, unsigned col_cnt, - const unsigned * identical_cols); - virtual table_mutator_fn * mk_filter_equal_fn(const table_base & t, const table_element & value, - unsigned col); - virtual table_mutator_fn * mk_filter_interpreted_fn(const table_base & t, app * condition); - virtual table_transformer_fn * mk_filter_interpreted_and_project_fn(const table_base & t, - app * condition, unsigned removed_col_cnt, const unsigned * removed_cols); - virtual table_intersection_filter_fn * mk_filter_by_negation_fn( - const table_base & t, - const table_base & negated_obj, unsigned joined_col_cnt, - const unsigned * t_cols, const unsigned * negated_cols); - - virtual bool can_handle_signature(table_signature const& s); - - private: - static check_table& get(table_base& r); - - static check_table const & get(table_base const& r); - - static table_base& checker(table_base& r); - static table_base const& checker(table_base const& r); - static table_base* checker(table_base* r); - static table_base const* checker(table_base const* r); - static table_base& tocheck(table_base& r); - static table_base const& tocheck(table_base const& r); - static table_base* tocheck(table_base* r); - static table_base const* tocheck(table_base const* r); - }; - - class check_table : public table_base { - friend class check_table_plugin; - - table_base* m_checker; - table_base* m_tocheck; - - check_table(check_table_plugin & p, const table_signature & sig); - check_table(check_table_plugin & p, const table_signature & sig, table_base* tocheck, table_base* checker); - - virtual ~check_table(); - - bool well_formed() const; - - public: - - check_table_plugin & get_plugin() const { - return static_cast(table_base::get_plugin()); - } - - virtual bool empty() const; - virtual void add_fact(const table_fact & f); - virtual void remove_fact(const table_element* fact); - virtual bool contains_fact(const table_fact & f) const; - virtual table_base * complement(func_decl* p, const table_element * func_columns = 0) const; - virtual table_base * clone() const; - - virtual iterator begin() const { SASSERT(well_formed()); return m_tocheck->begin(); } - virtual iterator end() const { return m_tocheck->end(); } - - virtual unsigned get_size_estimate_rows() const { return m_tocheck->get_size_estimate_rows(); } - virtual unsigned get_size_estimate_bytes() const { return m_tocheck->get_size_estimate_bytes(); } - }; - - }; - - #endif /* _DL_CHECK_TABLE_H_ */ diff --git a/src/muz/dl_cmds.h b/src/muz/dl_cmds.h deleted file mode 100644 index d71b319c4..000000000 --- a/src/muz/dl_cmds.h +++ /dev/null @@ -1,37 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - dl_cmds.h - -Abstract: - Datalog commands for SMT2 front-end. - -Author: - - Nikolaj Bjorner (nbjorner) 2012-11-17 - -Notes: - ---*/ -#ifndef _DL_CMDS_H_ -#define _DL_CMDS_H_ - -#include "ast.h" - -class cmd_context; - -struct dl_collected_cmds { - expr_ref_vector m_rules; - svector m_names; - expr_ref_vector m_queries; - func_decl_ref_vector m_rels; - dl_collected_cmds(ast_manager& m) : m_rules(m), m_queries(m), m_rels(m) {} -}; - -void install_dl_cmds(cmd_context & ctx); -void install_dl_collect_cmds(dl_collected_cmds& collected_cmds, cmd_context& ctx); - - -#endif diff --git a/src/muz/dl_context.cpp b/src/muz/dl_context.cpp index f5bfb6b5e..5e707e315 100644 --- a/src/muz/dl_context.cpp +++ b/src/muz/dl_context.cpp @@ -23,28 +23,6 @@ Revision History: #include"basic_simplifier_plugin.h" #include"arith_decl_plugin.h" #include"bv_decl_plugin.h" -#include"dl_table.h" -#include"dl_table_relation.h" -#include"dl_rule_transformer.h" -#include"dl_mk_coi_filter.h" -#include"dl_mk_explanations.h" -#include"dl_mk_filter_rules.h" -#include"dl_mk_interp_tail_simplifier.h" -#include"dl_mk_rule_inliner.h" -#include"dl_mk_simple_joins.h" -#include"dl_mk_similarity_compressor.h" -#include"dl_mk_unbound_compressor.h" -#include"dl_mk_subsumption_checker.h" -#include"dl_mk_partial_equiv.h" -#include"dl_mk_bit_blast.h" -#include"dl_mk_array_blast.h" -#include"dl_mk_karr_invariants.h" -#include"dl_mk_magic_symbolic.h" -#include"dl_mk_quantifier_abstraction.h" -#include"dl_mk_quantifier_instantiation.h" -#include"dl_mk_scale.h" -#include"dl_compiler.h" -#include"dl_instruction.h" #include"dl_context.h" #include"for_each_expr.h" #include"ast_smt_pp.h" @@ -217,8 +195,9 @@ namespace datalog { // // ----------------------------------- - context::context(ast_manager & m, smt_params& fp, params_ref const& pa): + context::context(ast_manager & m, register_engine_base& re, smt_params& fp, params_ref const& pa): m(m), + m_register_engine(re), m_fparams(fp), m_params_ref(pa), m_params(m_params_ref), @@ -248,6 +227,7 @@ namespace datalog { m_last_answer(m), m_engine_type(LAST_ENGINE), m_cancel(false) { + re.set_context(this); } context::~context() { @@ -780,29 +760,6 @@ namespace datalog { m_closed = false; } - void context::transform_rules() { - m_transf.reset(); - m_transf.register_plugin(alloc(mk_coi_filter, *this)); - m_transf.register_plugin(alloc(mk_filter_rules, *this)); - m_transf.register_plugin(alloc(mk_simple_joins, *this)); - if (unbound_compressor()) { - m_transf.register_plugin(alloc(mk_unbound_compressor, *this)); - } - if (similarity_compressor()) { - m_transf.register_plugin(alloc(mk_similarity_compressor, *this)); - } - m_transf.register_plugin(alloc(mk_partial_equivalence_transformer, *this)); - m_transf.register_plugin(alloc(mk_rule_inliner, *this)); - m_transf.register_plugin(alloc(mk_interp_tail_simplifier, *this)); - - if (get_params().bit_blast()) { - m_transf.register_plugin(alloc(mk_bit_blast, *this, 22000)); - m_transf.register_plugin(alloc(mk_interp_tail_simplifier, *this, 21000)); - } - - transform_rules(m_transf); - } - void context::transform_rules(rule_transformer::plugin* plugin) { rule_transformer transformer(*this); transformer.register_plugin(plugin); @@ -834,45 +791,6 @@ namespace datalog { } void context::apply_default_transformation() { - ensure_closed(); - m_transf.reset(); - m_transf.register_plugin(alloc(datalog::mk_coi_filter, *this)); - m_transf.register_plugin(alloc(datalog::mk_interp_tail_simplifier, *this)); - - m_transf.register_plugin(alloc(datalog::mk_subsumption_checker, *this, 35005)); - m_transf.register_plugin(alloc(datalog::mk_rule_inliner, *this, 35000)); - m_transf.register_plugin(alloc(datalog::mk_coi_filter, *this, 34990)); - m_transf.register_plugin(alloc(datalog::mk_interp_tail_simplifier, *this, 34980)); - - //and another round of inlining - m_transf.register_plugin(alloc(datalog::mk_subsumption_checker, *this, 34975)); - m_transf.register_plugin(alloc(datalog::mk_rule_inliner, *this, 34970)); - m_transf.register_plugin(alloc(datalog::mk_coi_filter, *this, 34960)); - m_transf.register_plugin(alloc(datalog::mk_interp_tail_simplifier, *this, 34950)); - - m_transf.register_plugin(alloc(datalog::mk_subsumption_checker, *this, 34940)); - m_transf.register_plugin(alloc(datalog::mk_rule_inliner, *this, 34930)); - m_transf.register_plugin(alloc(datalog::mk_subsumption_checker, *this, 34920)); - m_transf.register_plugin(alloc(datalog::mk_rule_inliner, *this, 34910)); - m_transf.register_plugin(alloc(datalog::mk_subsumption_checker, *this, 34900)); - m_transf.register_plugin(alloc(datalog::mk_rule_inliner, *this, 34890)); - m_transf.register_plugin(alloc(datalog::mk_subsumption_checker, *this, 34880)); - - - if (get_params().quantify_arrays()) { - m_transf.register_plugin(alloc(datalog::mk_quantifier_abstraction, *this, 33000)); - m_transf.register_plugin(alloc(datalog::mk_array_blast, *this, 32500)); - } - m_transf.register_plugin(alloc(datalog::mk_quantifier_instantiation, *this, 32000)); - - m_transf.register_plugin(alloc(datalog::mk_bit_blast, *this, 35000)); - m_transf.register_plugin(alloc(datalog::mk_array_blast, *this, 36000)); - m_transf.register_plugin(alloc(datalog::mk_karr_invariants, *this, 36010)); - if (get_params().magic()) { - m_transf.register_plugin(alloc(datalog::mk_magic_symbolic, *this, 36020)); - } - m_transf.register_plugin(alloc(datalog::mk_scale, *this, 36030)); - transform_rules(m_transf); } void context::collect_params(param_descrs& p) { @@ -1024,39 +942,18 @@ namespace datalog { void context::ensure_engine() { if (!m_engine.get()) { - switch (get_engine()) { - case PDR_ENGINE: - case QPDR_ENGINE: - m_engine = alloc(pdr::dl_interface, *this); - break; - case DATALOG_ENGINE: - m_rel = alloc(rel_context, *this); - m_engine = m_rel; - break; - case BMC_ENGINE: - case QBMC_ENGINE: - m_engine = alloc(bmc, *this); - break; - case TAB_ENGINE: - m_engine = alloc(tab, *this); - break; - case CLP_ENGINE: - m_engine = alloc(clp, *this); - break; - case LAST_ENGINE: - UNREACHABLE(); + m_engine = m_register_engine.mk_engine(get_engine()); + + // break abstraction. + if (get_engine() == DATALOG_ENGINE) { + m_rel = dynamic_cast(m_engine.get()); } - } + } } lbool context::rel_query(unsigned num_rels, func_decl * const* rels) { ensure_engine(); - if (m_rel) { - return m_rel->query(num_rels, rels); - } - else { - return l_undef; - } + return m_engine->query(num_rels, rels); } expr* context::get_answer_as_formula() { @@ -1073,6 +970,11 @@ namespace datalog { m_engine->display_certificate(out); } + void context::display(std::ostream & out) const { + display_rules(out); + if (m_rel) m_rel->display_facts(out); + } + void context::display_profile(std::ostream& out) const { out << "\n---------------\n"; out << "Original rules\n"; diff --git a/src/muz/dl_context.h b/src/muz/dl_context.h index a3c7e583c..97a371f5a 100644 --- a/src/muz/dl_context.h +++ b/src/muz/dl_context.h @@ -28,15 +28,9 @@ Revision History: #include"th_rewriter.h" #include"str_hashtable.h" #include"var_subst.h" -#include"dl_base.h" #include"dl_costs.h" #include"dl_decl_plugin.h" -#include"dl_relation_manager.h" #include"dl_rule_set.h" -#include"pdr_dl_interface.h" -#include"dl_bmc_engine.h" -#include"tab_context.h" -#include"rel_context.h" #include"lbool.h" #include"statistics.h" #include"params.h" @@ -47,7 +41,7 @@ Revision History: #include"dl_rule_transformer.h" #include"expr_abstract.h" #include"expr_functors.h" -#include"clp_context.h" +#include"dl_engine_base.h" namespace datalog { @@ -60,6 +54,84 @@ namespace datalog { CANCELED }; + class relation_manager; + + typedef sort * relation_sort; + typedef uint64 table_element; + typedef svector table_fact; + + typedef app * relation_element; + typedef app_ref relation_element_ref; + + class relation_fact : public app_ref_vector { + public: + class el_proxy { + friend class relation_fact; + + relation_fact & m_parent; + unsigned m_idx; + + el_proxy(relation_fact & parent, unsigned idx) : m_parent(parent), m_idx(idx) {} + public: + operator relation_element() const { + return m_parent.get(m_idx); + } + relation_element operator->() const { + return m_parent.get(m_idx); + } + relation_element operator=(const relation_element & val) const { + m_parent.set(m_idx, val); + return m_parent.get(m_idx); + } + relation_element operator=(const el_proxy & val) { + m_parent.set(m_idx, val); + return m_parent.get(m_idx); + } + }; + + typedef const relation_element * iterator; + + relation_fact(ast_manager & m) : app_ref_vector(m) {} + relation_fact(ast_manager & m, unsigned sz) : app_ref_vector(m) { resize(sz); } + relation_fact(context & ctx); + + iterator begin() const { return c_ptr(); } + iterator end() const { return c_ptr()+size(); } + + relation_element operator[](unsigned i) const { return get(i); } + el_proxy operator[](unsigned i) { return el_proxy(*this, i); } + }; + + // attempt to modularize context code. + class rel_context_base : public engine_base { + public: + rel_context_base(ast_manager& m, char const* name): engine_base(m, name) {} + virtual ~rel_context_base() {} + virtual relation_manager & get_rmanager() = 0; + virtual const relation_manager & get_rmanager() const = 0; + virtual relation_base & get_relation(func_decl * pred) = 0; + virtual relation_base * try_get_relation(func_decl * pred) const = 0; + virtual bool is_empty_relation(func_decl* pred) const = 0; + virtual expr_ref try_get_formula(func_decl * pred) const = 0; + virtual void display_output_facts(rule_set const& rules, std::ostream & out) const = 0; + virtual void display_facts(std::ostream & out) const = 0; + virtual void display_profile(std::ostream& out) = 0; + virtual void restrict_predicates(func_decl_set const& predicates) = 0; + virtual bool result_contains_fact(relation_fact const& f) = 0; + virtual void add_fact(func_decl* pred, relation_fact const& fact) = 0; + virtual void add_fact(func_decl* pred, table_fact const& fact) = 0; + virtual bool has_facts(func_decl * pred) const = 0; + virtual void store_relation(func_decl * pred, relation_base * rel) = 0; + virtual void inherit_predicate_kind(func_decl* new_pred, func_decl* orig_pred) = 0; + virtual void set_predicate_representation(func_decl * pred, unsigned relation_name_cnt, + symbol const * relation_names) = 0; + virtual bool output_profile() const = 0; + virtual void collect_non_empty_predicates(func_decl_set& preds) = 0; + virtual void transform_rules() = 0; + virtual bool try_get_size(func_decl* pred, unsigned& rel_sz) const = 0; + virtual lbool saturate() = 0; + }; + class context { public: typedef unsigned finite_element; @@ -93,6 +165,7 @@ namespace datalog { ast_manager & m; + register_engine_base& m_register_engine; smt_params & m_fparams; params_ref m_params_ref; fixedpoint_params m_params; @@ -122,7 +195,7 @@ namespace datalog { model_converter_ref m_mc; proof_converter_ref m_pc; - rel_context* m_rel; + rel_context_base* m_rel; scoped_ptr m_engine; bool m_closed; @@ -143,7 +216,7 @@ namespace datalog { public: - context(ast_manager & m, smt_params& fp, params_ref const& p = params_ref()); + context(ast_manager & m, register_engine_base& re, smt_params& fp, params_ref const& p = params_ref()); ~context(); void reset(); @@ -160,6 +233,7 @@ namespace datalog { smt_params & get_fparams() const { return m_fparams; } fixedpoint_params const& get_params() const { return m_params; } DL_ENGINE get_engine() { configure_engine(); return m_engine_type; } + register_engine_base& get_register_engine() { return m_register_engine; } th_rewriter& get_rewriter() { return m_rewriter; } var_subst & get_var_subst() { return m_var_subst; } dl_decl_util & get_decl_util() { return m_decl_util; } @@ -355,7 +429,6 @@ namespace datalog { proof_converter_ref& get_proof_converter() { return m_pc; } void add_proof_converter(proof_converter* pc) { m_pc = concat(m_pc.get(), pc); } - void transform_rules(); void transform_rules(rule_transformer& transf); void transform_rules(rule_transformer::plugin* plugin); void replace_rules(rule_set const& rs); @@ -371,10 +444,7 @@ namespace datalog { m_rule_set.display(out); } - void display(std::ostream & out) const { - display_rules(out); - if (m_rel) m_rel->display_facts(out); - } + void display(std::ostream & out) const; void display_smt2(unsigned num_queries, expr* const* queries, std::ostream& out); @@ -459,7 +529,7 @@ namespace datalog { */ bool result_contains_fact(relation_fact const& f); - rel_context* get_rel_context() { ensure_engine(); return m_rel; } + rel_context_base* get_rel_context() { ensure_engine(); return m_rel; } private: diff --git a/src/muz/dl_engine_base.h b/src/muz/dl_engine_base.h new file mode 100644 index 000000000..52dc9acd4 --- /dev/null +++ b/src/muz/dl_engine_base.h @@ -0,0 +1,82 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + dl_engine_base.h + +Abstract: + + Base class for Datalog engines. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-08-28 + +Revision History: + +--*/ +#ifndef _DL_ENGINE_BASE_H_ +#define _DL_ENGINE_BASE_H_ + +#include "model.h" + +namespace datalog { + enum DL_ENGINE { + DATALOG_ENGINE, + PDR_ENGINE, + QPDR_ENGINE, + BMC_ENGINE, + QBMC_ENGINE, + TAB_ENGINE, + CLP_ENGINE, + LAST_ENGINE + }; + + class engine_base { + ast_manager& m; + std::string m_name; + public: + engine_base(ast_manager& m, char const* name): m(m), m_name(name) {} + virtual ~engine_base() {} + + virtual expr_ref get_answer() = 0; + virtual lbool query(expr* q) = 0; + virtual lbool query(unsigned num_rels, func_decl*const* rels) { return l_undef; } + + virtual void reset_statistics() {} + virtual void display_profile(std::ostream& out) const {} + virtual void collect_statistics(statistics& st) const {} + virtual unsigned get_num_levels(func_decl* pred) { + throw default_exception(std::string("get_num_levels is not supported for ") + m_name); + } + virtual expr_ref get_cover_delta(int level, func_decl* pred) { + throw default_exception(std::string("operation is not supported for ") + m_name); + } + virtual void add_cover(int level, func_decl* pred, expr* property) { + throw default_exception(std::string("operation is not supported for ") + m_name); + } + virtual void display_certificate(std::ostream& out) const { + throw default_exception(std::string("certificates are not supported for ") + m_name); + } + virtual model_ref get_model() { + return model_ref(alloc(model, m)); + } + virtual proof_ref get_proof() { + return proof_ref(m.mk_asserted(m.mk_true()), m); + } + virtual void updt_params() {} + virtual void cancel() {} + virtual void cleanup() {} + }; + + class context; + + class register_engine_base { + public: + virtual engine_base* mk_engine(DL_ENGINE engine_type) = 0; + virtual void set_context(context* ctx) = 0; + }; +} + +#endif diff --git a/src/muz/dl_external_relation.cpp b/src/muz/dl_external_relation.cpp deleted file mode 100644 index f32509473..000000000 --- a/src/muz/dl_external_relation.cpp +++ /dev/null @@ -1,456 +0,0 @@ -/*++ -Copyright (c) 2010 Microsoft Corporation - -Module Name: - - dl_external_relation.cpp - -Abstract: - - - -Author: - - Nikolaj Bjorner (nbjorner) 2010-05-10 - -Revision History: - ---*/ - -#include "debug.h" -#include "ast_pp.h" -#include "dl_context.h" -#include "dl_external_relation.h" -#include "dl_decl_plugin.h" - -namespace datalog { - - external_relation::external_relation(external_relation_plugin & p, const relation_signature & s, expr* r) - : relation_base(p, s), - m_rel(r, p.get_ast_manager()), - m_select_fn(p.get_ast_manager()), - m_store_fn(p.get_ast_manager()), - m_is_empty_fn(p.get_ast_manager()) - { - } - - external_relation::~external_relation() { - } - - void external_relation::mk_accessor(decl_kind k, func_decl_ref& fn, const relation_fact& f, bool destructive, expr_ref& res) const { - ast_manager& m = m_rel.get_manager(); - family_id fid = get_plugin().get_family_id(); - ptr_vector args; - args.push_back(m_rel); - for (unsigned i = 0; i < f.size(); ++i) { - args.push_back(f[i]); - } - if (!fn.get()) { - fn = m.mk_func_decl(fid, k, 0, 0, args.size(), args.c_ptr()); - } - if (destructive) { - get_plugin().reduce_assign(fn, args.size(), args.c_ptr(), 1, args.c_ptr()); - res = m_rel; - } - else { - get_plugin().reduce(fn, args.size(), args.c_ptr(), res); - } - } - - bool external_relation::empty() const { - ast_manager& m = m_rel.get_manager(); - expr* r = m_rel.get(); - expr_ref res(m); - if (!m_is_empty_fn.get()) { - family_id fid = get_plugin().get_family_id(); - const_cast(m_is_empty_fn) = m.mk_func_decl(fid, OP_RA_IS_EMPTY, 0, 0, 1, &r); - } - get_plugin().reduce(m_is_empty_fn, 1, &r, res); - return m.is_true(res); - } - - void external_relation::add_fact(const relation_fact & f) { - mk_accessor(OP_RA_STORE, m_store_fn, f, true, m_rel); - } - - bool external_relation::contains_fact(const relation_fact & f) const { - ast_manager& m = get_plugin().get_ast_manager(); - expr_ref res(m); - mk_accessor(OP_RA_SELECT, const_cast(m_select_fn), f, false, res); - return !m.is_false(res); - } - - external_relation * external_relation::clone() const { - ast_manager& m = m_rel.get_manager(); - family_id fid = get_plugin().get_family_id(); - expr* rel = m_rel.get(); - expr_ref res(m.mk_fresh_const("T", m.get_sort(rel)), m); - expr* rel_out = res.get(); - func_decl_ref fn(m.mk_func_decl(fid, OP_RA_CLONE,0,0, 1, &rel), m); - get_plugin().reduce_assign(fn, 1, &rel, 1, &rel_out); - return alloc(external_relation, get_plugin(), get_signature(), res); - } - - external_relation * external_relation::complement(func_decl* p) const { - ast_manager& m = m_rel.get_manager(); - family_id fid = get_plugin().get_family_id(); - expr_ref res(m); - expr* rel = m_rel; - func_decl_ref fn(m.mk_func_decl(fid, OP_RA_COMPLEMENT,0,0, 1, &rel), m); - get_plugin().reduce(fn, 1, &rel, res); - return alloc(external_relation, get_plugin(), get_signature(), res); - } - - void external_relation::display(std::ostream & out) const { - out << mk_pp(m_rel, m_rel.get_manager()) << "\n"; - } - - void external_relation::display_tuples(func_decl & pred, std::ostream & out) const { - display(out); - } - - - external_relation_plugin & external_relation::get_plugin() const { - return static_cast(relation_base::get_plugin()); - } - - - // ----------------------------------- - // - // external_relation_plugin - // - // ----------------------------------- - - - external_relation_plugin::external_relation_plugin(external_relation_context& ctx, relation_manager & m) - : relation_plugin(external_relation_plugin::get_name(), m), m_ext(ctx) {} - - external_relation const & external_relation_plugin::get(relation_base const& r) { - return dynamic_cast(r); - } - - external_relation & external_relation_plugin::get(relation_base & r) { - return dynamic_cast(r); - } - - relation_base * external_relation_plugin::mk_empty(const relation_signature & s) { - ast_manager& m = get_ast_manager(); - sort* r_sort = get_relation_sort(s); - parameter param(r_sort); - family_id fid = get_family_id(); - expr_ref e(m.mk_fresh_const("T", r_sort), m); - expr* args[1] = { e.get() }; - func_decl_ref empty_decl(m.mk_func_decl(fid, OP_RA_EMPTY, 1, ¶m, 0, (sort*const*)0), m); - reduce_assign(empty_decl, 0, 0, 1, args); - return alloc(external_relation, *this, s, e); - } - - sort* external_relation_plugin::get_relation_sort(relation_signature const& sig) { - vector sorts; - ast_manager& m = get_ast_manager(); - family_id fid = get_family_id(); - for (unsigned i = 0; i < sig.size(); ++i) { - sorts.push_back(parameter(sig[i])); - } - return m.mk_sort(fid, DL_RELATION_SORT, sorts.size(), sorts.c_ptr()); - } - - sort* external_relation_plugin::get_column_sort(unsigned col, sort* s) { - SASSERT(s->get_num_parameters() > col); - SASSERT(s->get_parameter(col).is_ast()); - SASSERT(is_sort(s->get_parameter(col).get_ast())); - return to_sort(s->get_parameter(col).get_ast()); - } - - family_id external_relation_plugin::get_family_id() { - return m_ext.get_family_id(); - } - - - void external_relation_plugin::mk_filter_fn(sort* s, app* condition, func_decl_ref& f) { - ast_manager& m = get_ast_manager(); - family_id fid = get_family_id(); - parameter param(condition); - f = m.mk_func_decl(fid, OP_RA_FILTER, 1, ¶m, 1, &s); - } - - class external_relation_plugin::join_fn : public convenient_relation_join_fn { - external_relation_plugin& m_plugin; - func_decl_ref m_join_fn; - expr* m_args[2]; - public: - join_fn(external_relation_plugin& p, const relation_signature & o1_sig, const relation_signature & o2_sig, unsigned col_cnt, - const unsigned * cols1, const unsigned * cols2) - : convenient_relation_join_fn(o1_sig, o2_sig, col_cnt, cols1, cols2), - m_plugin(p), - m_join_fn(p.get_ast_manager()) { - ast_manager& m = p.get_ast_manager(); - family_id fid = p.get_family_id(); - vector params; - for (unsigned i = 0; i < col_cnt; ++i) { - params.push_back(parameter(cols1[i])); - params.push_back(parameter(cols2[i])); - } - sort* domain[2] = { p.get_relation_sort(o1_sig), p.get_relation_sort(o2_sig) }; - m_join_fn = m.mk_func_decl(fid, OP_RA_JOIN, params.size(), params.c_ptr(), 2, domain); - } - - virtual relation_base * operator()(const relation_base & r1, const relation_base & r2) { - expr_ref res(m_plugin.get_ast_manager()); - m_args[0] = get(r1).get_relation(); - m_args[1] = get(r2).get_relation(); - m_plugin.reduce(m_join_fn, 2, m_args, res); - return alloc(external_relation, m_plugin, get_result_signature(), res); - } - }; - - relation_join_fn * external_relation_plugin::mk_join_fn(const relation_base & r1, const relation_base & r2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) { - if (!check_kind(r1) || !check_kind(r2)) { - return 0; - } - return alloc(join_fn, *this, r1.get_signature(), r2.get_signature() , col_cnt, cols1, cols2); - } - - - class external_relation_plugin::project_fn : public convenient_relation_project_fn { - external_relation_plugin& m_plugin; - func_decl_ref m_project_fn; - public: - project_fn(external_relation_plugin& p, sort* relation_sort, - const relation_signature & orig_sig, unsigned removed_col_cnt, const unsigned * removed_cols) - : convenient_relation_project_fn(orig_sig, removed_col_cnt, removed_cols), - m_plugin(p), - m_project_fn(p.get_ast_manager()) { - vector params; - ast_manager& m = p.get_ast_manager(); - family_id fid = p.get_family_id(); - for (unsigned i = 0; i < removed_col_cnt; ++i) { - params.push_back(parameter(removed_cols[i])); - } - m_project_fn = m.mk_func_decl(fid, OP_RA_PROJECT, params.size(), params.c_ptr(), 1, &relation_sort); - } - - virtual relation_base * operator()(const relation_base & r) { - expr_ref res(m_plugin.get_ast_manager()); - expr* rel = get(r).get_relation(); - m_plugin.reduce(m_project_fn, 1, &rel, res); - return alloc(external_relation, m_plugin, get_result_signature(), to_app(res)); - } - }; - - relation_transformer_fn * external_relation_plugin::mk_project_fn(const relation_base & r, - unsigned col_cnt, const unsigned * removed_cols) { - return alloc(project_fn, *this, get(r).get_sort(), r.get_signature(), col_cnt, removed_cols); - } - - - class external_relation_plugin::rename_fn : public convenient_relation_rename_fn { - external_relation_plugin& m_plugin; - func_decl_ref m_rename_fn; - expr* m_args[2]; - public: - rename_fn(external_relation_plugin& p, sort* relation_sort, const relation_signature & orig_sig, unsigned cycle_len, const unsigned * cycle) - : convenient_relation_rename_fn(orig_sig, cycle_len, cycle), - m_plugin(p), - m_rename_fn(p.get_ast_manager()) { - - ast_manager& m = p.get_ast_manager(); - family_id fid = p.get_family_id(); - vector params; - for (unsigned i = 0; i < cycle_len; ++i) { - SASSERT(cycle[i] < orig_sig.size()); - params.push_back(parameter(cycle[i])); - } - m_rename_fn = m.mk_func_decl(fid, OP_RA_RENAME, params.size(), params.c_ptr(), 1, &relation_sort); - } - - virtual relation_base * operator()(const relation_base & r) { - expr* rel = get(r).get_relation(); - expr_ref res(m_plugin.get_ast_manager()); - m_args[0] = rel; - m_plugin.reduce(m_rename_fn, 1, &rel, res); - return alloc(external_relation, m_plugin, get_result_signature(), res); - } - }; - - relation_transformer_fn * external_relation_plugin::mk_rename_fn(const relation_base & r, - unsigned cycle_len, const unsigned * permutation_cycle) { - if(!check_kind(r)) { - return 0; - } - return alloc(rename_fn, *this, get(r).get_sort(), r.get_signature(), cycle_len, permutation_cycle); - } - - - class external_relation_plugin::union_fn : public relation_union_fn { - external_relation_plugin& m_plugin; - func_decl_ref m_union_fn; - expr* m_args[2]; - expr* m_outs[2]; - - public: - union_fn(external_relation_plugin& p, decl_kind k, sort* relation_sort): - m_plugin(p), - m_union_fn(p.get_ast_manager()) { - ast_manager& m = p.get_ast_manager(); - sort* domain[2] = { relation_sort, relation_sort }; - m_union_fn = m.mk_func_decl(p.get_family_id(), k, 0, 0, 2, domain); - } - - virtual void operator()(relation_base & r, const relation_base & src, relation_base * delta) { - ast_manager& m = m_plugin.get_ast_manager(); - expr_ref_vector res(m); - m_args[0] = get(r).get_relation(); - m_args[1] = get(src).get_relation(); - m_outs[0] = m_args[0]; - unsigned num_out = 1; - if (delta) { - m_outs[1] = get(*delta).get_relation(); - ++num_out; - } - m_plugin.reduce_assign(m_union_fn, 2, m_args, num_out, m_outs); - } - }; - - relation_union_fn * external_relation_plugin::mk_union_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta) { - if (!check_kind(tgt) || !check_kind(src) || (delta && !check_kind(*delta))) { - return 0; - } - return alloc(union_fn, *this, OP_RA_UNION, get(src).get_sort()); - } - - relation_union_fn * external_relation_plugin::mk_widen_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta) { - if (!check_kind(tgt) || !check_kind(src) || (delta && !check_kind(*delta))) { - return 0; - } - return alloc(union_fn, *this, OP_RA_WIDEN, get(src).get_sort()); - } - - class external_relation_plugin::filter_interpreted_fn : public relation_mutator_fn { - external_relation_plugin& m_plugin; - app_ref m_condition; - func_decl_ref m_filter_fn; - public: - filter_interpreted_fn(external_relation_plugin& p, sort* relation_sort, app * condition) - : m_plugin(p), - m_condition(condition, p.get_ast_manager()), - m_filter_fn(p.get_ast_manager()) { - ast_manager& m = p.get_ast_manager(); - p.mk_filter_fn(relation_sort, condition, m_filter_fn); - SASSERT(m.is_bool(condition)); - } - - virtual void operator()(relation_base & r) { - SASSERT(m_plugin.check_kind(r)); - expr* arg = get(r).get_relation(); - m_plugin.reduce_assign(m_filter_fn, 1, &arg, 1, &arg); - } - }; - - relation_mutator_fn * external_relation_plugin::mk_filter_interpreted_fn(const relation_base & r, app * condition) { - if(!check_kind(r)) { - return 0; - } - return alloc(filter_interpreted_fn, *this, get(r).get_sort(), condition); - } - - relation_mutator_fn * external_relation_plugin::mk_filter_equal_fn(const relation_base & r, - const relation_element & value, unsigned col) { - if(!check_kind(r)) { - return 0; - } - ast_manager& m = get_ast_manager(); - app_ref condition(m); - expr_ref var(m); - sort* relation_sort = get(r).get_sort(); - sort* column_sort = get_column_sort(col, relation_sort); - var = m.mk_var(col, column_sort); - condition = m.mk_eq(var, value); - return mk_filter_interpreted_fn(r, condition); - } - - class external_relation_plugin::filter_identical_fn : public relation_mutator_fn { - external_relation_plugin& m_plugin; - func_decl_ref_vector m_filter_fn; - public: - filter_identical_fn(external_relation_plugin& p, sort* relation_sort, - unsigned col_cnt, const unsigned * identical_cols) - : m_plugin(p), m_filter_fn(p.get_ast_manager()) { - ast_manager& m = p.get_ast_manager(); - func_decl_ref fn(m); - app_ref eq(m); - if (col_cnt <= 1) { - return; - } - unsigned col = identical_cols[0]; - sort* s = p.get_column_sort(col, relation_sort); - var* v0 = m.mk_var(col, s); - for (unsigned i = 1; i < col_cnt; ++i) { - col = identical_cols[i]; - s = p.get_column_sort(col, relation_sort); - eq = m.mk_eq(v0, m.mk_var(col, s)); - p.mk_filter_fn(relation_sort, eq.get(), fn); - m_filter_fn.push_back(fn); - } - } - - virtual void operator()(relation_base & r) { - expr* r0 = get(r).get_relation(); - for (unsigned i = 0; i < m_filter_fn.size(); ++i) { - m_plugin.reduce_assign(m_filter_fn[i].get(), 1, &r0, 1, &r0); - } - } - }; - - relation_mutator_fn * external_relation_plugin::mk_filter_identical_fn(const relation_base & r, - unsigned col_cnt, const unsigned * identical_cols) { - if (!check_kind(r)) { - return 0; - } - return alloc(filter_identical_fn, *this, get(r).get_sort(), col_cnt, identical_cols); - } - - - class external_relation_plugin::negation_filter_fn : public convenient_relation_negation_filter_fn { - external_relation_plugin& m_plugin; - func_decl_ref m_negated_filter_fn; - expr* m_args[2]; - public: - negation_filter_fn(external_relation_plugin& p, - const relation_base & tgt, const relation_base & neg_t, - unsigned joined_col_cnt, const unsigned * t_cols, const unsigned * negated_cols) : - convenient_negation_filter_fn(tgt, neg_t, joined_col_cnt, t_cols, negated_cols), - m_plugin(p), - m_negated_filter_fn(p.get_ast_manager()) - { - ast_manager& m = p.get_ast_manager(); - family_id fid = p.get_family_id(); - vector params; - for (unsigned i = 0; i < joined_col_cnt; ++i) { - params.push_back(parameter(t_cols[i])); - params.push_back(parameter(negated_cols[i])); - } - sort* domain[2] = { get(tgt).get_sort(), get(neg_t).get_sort() }; - m_negated_filter_fn = m.mk_func_decl(fid, OP_RA_NEGATION_FILTER, params.size(), params.c_ptr(), 2, domain); - } - - void operator()(relation_base & t, const relation_base & negated_obj) { - m_args[0] = get(t).get_relation(); - m_args[1] = get(negated_obj).get_relation(); - m_plugin.reduce_assign(m_negated_filter_fn.get(), 2, m_args, 1, m_args); - } - }; - - relation_intersection_filter_fn * external_relation_plugin::mk_filter_by_negation_fn(const relation_base & t, - const relation_base & negated_obj, unsigned joined_col_cnt, - const unsigned * t_cols, const unsigned * negated_cols) { - if (!check_kind(t) || !check_kind(negated_obj)) { - return 0; - } - return alloc(negation_filter_fn, *this, t, negated_obj, joined_col_cnt, t_cols, negated_cols); - } - -}; diff --git a/src/muz/dl_external_relation.h b/src/muz/dl_external_relation.h deleted file mode 100644 index 03838ecc4..000000000 --- a/src/muz/dl_external_relation.h +++ /dev/null @@ -1,154 +0,0 @@ -/*++ -Copyright (c) 2010 Microsoft Corporation - -Module Name: - - dl_external_relation.h - -Abstract: - - - -Author: - - Nikolaj Bjorner (nbjorner) 2010-05-10 - -Revision History: - ---*/ -#ifndef _DL_EXTERNAL_RELATION_H_ -#define _DL_EXTERNAL_RELATION_H_ - -#include "dl_base.h" - -namespace datalog { - - class external_relation; - - class external_relation_context { - public: - virtual ~external_relation_context() {} - - virtual family_id get_family_id() const = 0; - - // reduce arguments. - virtual void reduce(func_decl* f, unsigned num_args, expr * const* args, expr_ref& result) = 0; - - // overwrite terms passed in outs vector with values computed by function. - virtual void reduce_assign(func_decl* f, unsigned num_args, expr * const* args, unsigned num_out, expr* const* outs) = 0; - }; - - class external_relation_plugin : public relation_plugin { - - friend class external_relation; - class join_fn; - class project_fn; - class rename_fn; - class union_fn; - class filter_identical_fn; - class filter_interpreted_fn; - class negation_filter_fn; - - external_relation_context& m_ext; - - public: - external_relation_plugin(external_relation_context& ctx, relation_manager & m); - - virtual bool can_handle_signature(const relation_signature & s) { return true; } - - static symbol get_name() { return symbol("external_relation"); } - - virtual relation_base * mk_empty(const relation_signature & s); - - virtual relation_join_fn * mk_join_fn(const relation_base & t1, const relation_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2); - virtual relation_transformer_fn * mk_project_fn(const relation_base & t, unsigned col_cnt, - const unsigned * removed_cols); - virtual relation_transformer_fn * mk_rename_fn(const relation_base & t, unsigned permutation_cycle_len, - const unsigned * permutation_cycle); - virtual relation_union_fn * mk_union_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta); - virtual relation_union_fn * mk_widen_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta); - virtual relation_mutator_fn * mk_filter_identical_fn(const relation_base & t, unsigned col_cnt, - const unsigned * identical_cols); - virtual relation_mutator_fn * mk_filter_equal_fn(const relation_base & t, const relation_element & value, - unsigned col); - virtual relation_mutator_fn * mk_filter_interpreted_fn(const relation_base & t, app * condition); - virtual relation_intersection_filter_fn * mk_filter_by_negation_fn(const relation_base & t, - const relation_base & negated_obj, unsigned joined_col_cnt, - const unsigned * t_cols, const unsigned * negated_cols); - - private: - - static external_relation& get(relation_base& r); - static external_relation const & get(relation_base const& r); - - void reduce(func_decl* f, unsigned num_args, expr * const* args, expr_ref& result) { - m_ext.reduce(f, num_args, args, result); - } - - void reduce_assign(func_decl* f, unsigned num_args, expr * const* args, unsigned num_out, expr* const* outs) { - m_ext.reduce_assign(f, num_args, args, num_out, outs); - } - - sort* get_relation_sort(relation_signature const& sig); - - sort* get_column_sort(unsigned col, sort* relation_sort); - - void mk_filter_fn(sort* s, app* condition, func_decl_ref& f); - - family_id get_family_id(); - }; - - class external_relation : public relation_base { - friend class external_relation_plugin; - friend class external_relation_plugin::join_fn; - friend class external_relation_plugin::project_fn; - friend class external_relation_plugin::rename_fn; - friend class external_relation_plugin::union_fn; - friend class external_relation_plugin::filter_identical_fn; - friend class external_relation_plugin::filter_interpreted_fn; - friend class external_relation_plugin::negation_filter_fn; - - expr_ref m_rel; - func_decl_ref m_select_fn; - func_decl_ref m_store_fn; - func_decl_ref m_is_empty_fn; - - unsigned size() const { return get_signature().size(); } - - sort* get_sort() const { return m_rel.get_manager().get_sort(m_rel); } - - void mk_accessor(decl_kind k, func_decl_ref& fn, const relation_fact& f, bool destructive, expr_ref& res) const; - - external_relation(external_relation_plugin & p, const relation_signature & s, expr* r); - virtual ~external_relation(); - - public: - external_relation_plugin & get_plugin() const; - - virtual bool empty() const; - - virtual void add_fact(const relation_fact & f); - - virtual bool contains_fact(const relation_fact & f) const; - - virtual external_relation * clone() const; - - virtual external_relation * complement(func_decl*) const; - - virtual void display(std::ostream & out) const; - - virtual void display_tuples(func_decl & pred, std::ostream & out) const; - - expr* get_relation() const { return m_rel.get(); } - - virtual void to_formula(expr_ref& fml) const { fml = get_relation(); } - - }; - - -}; - -#endif diff --git a/src/muz/dl_finite_product_relation.cpp b/src/muz/dl_finite_product_relation.cpp deleted file mode 100644 index 86fef433b..000000000 --- a/src/muz/dl_finite_product_relation.cpp +++ /dev/null @@ -1,2377 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - dl_finite_product_relation.cpp - -Abstract: - - - -Author: - - Krystof Hoder (t-khoder) 2010-09-14. - -Revision History: - ---*/ - - -#include -#include"dl_context.h" -#include"dl_relation_manager.h" -#include"dl_table_relation.h" -#include"dl_finite_product_relation.h" -#include"bool_rewriter.h" - -namespace datalog { - - //static variables - - const table_sort finite_product_relation::s_rel_idx_sort = INT_MAX; - - void universal_delete(finite_product_relation* ptr) { - ptr->deallocate(); - } - - - // ----------------------------------- - // - // finite_product_relation_plugin - // - // ----------------------------------- - - finite_product_relation & finite_product_relation_plugin::get(relation_base & r) { - SASSERT(r.get_plugin().is_finite_product_relation()); - return static_cast(r); - } - - const finite_product_relation & finite_product_relation_plugin::get(const relation_base & r) { - SASSERT(r.get_plugin().is_finite_product_relation()); - return static_cast(r); - } - - finite_product_relation * finite_product_relation_plugin::get(relation_base * r) { - SASSERT(!r || r->get_plugin().is_finite_product_relation()); - return static_cast(r); - } - - const finite_product_relation * finite_product_relation_plugin::get(const relation_base * r) { - SASSERT(!r || r->get_plugin().is_finite_product_relation()); - return static_cast(r); - } - - symbol finite_product_relation_plugin::get_name(relation_plugin & inner_plugin) { - std::string str = std::string("fpr_")+inner_plugin.get_name().bare_str(); - return symbol(str.c_str()); - } - - finite_product_relation_plugin & finite_product_relation_plugin::get_plugin(relation_manager & rmgr, - relation_plugin & inner) { - finite_product_relation_plugin * res; - if(!rmgr.try_get_finite_product_relation_plugin(inner, res)) { - res = alloc(finite_product_relation_plugin, inner, rmgr); - rmgr.register_plugin(res); - } - return *res; - } - - finite_product_relation_plugin::finite_product_relation_plugin(relation_plugin & inner_plugin, - relation_manager & manager) - : relation_plugin(get_name(inner_plugin), manager, ST_FINITE_PRODUCT_RELATION), - m_inner_plugin(inner_plugin), m_spec_store(*this) { - } - - void finite_product_relation_plugin::initialize(family_id fid) { - relation_plugin::initialize(fid); - m_spec_store.add_available_kind(get_kind()); - } - - family_id finite_product_relation_plugin::get_relation_kind(finite_product_relation & r, - const bool * table_columns) { - const relation_signature & sig = r.get_signature(); - svector table_cols_vect(sig.size(), table_columns); - return m_spec_store.get_relation_kind(sig, rel_spec(table_cols_vect)); - } - - void finite_product_relation_plugin::get_all_possible_table_columns(relation_manager & rmgr, - const relation_signature & s, svector & table_columns) { - SASSERT(table_columns.empty()); - unsigned s_sz = s.size(); - for(unsigned i=0; i table_columns; - get_all_possible_table_columns(s, table_columns); -#ifndef _EXTERNAL_RELEASE - unsigned s_sz = s.size(); - unsigned rel_col_cnt = 0; - for(unsigned i=0; icomplement_self(p); - return res; - } - - bool finite_product_relation_plugin::can_convert_to_table_relation(const finite_product_relation & r) { - return r.m_other_sig.empty(); - } - - table_relation * finite_product_relation_plugin::to_table_relation(const finite_product_relation & r) { - SASSERT(can_convert_to_table_relation(r)); - r.garbage_collect(true); - //now all rows in the table will correspond to rows in the resulting table_relation - - const table_base & t = r.get_table(); - - unsigned removed_col = t.get_signature().size()-1; - scoped_ptr project_fun = - get_manager().mk_project_fn(r.get_table(), 1, &removed_col); - - table_base * res_table = (*project_fun)(t); - SASSERT(res_table->get_signature().functional_columns()==0); - return static_cast(get_manager().mk_table_relation(r.get_signature(), res_table)); - } - - - bool finite_product_relation_plugin::can_be_converted(const relation_base & r) { - if(&r.get_plugin()==&get_inner_plugin()) { - //can be converted by mk_from_inner_relation - return true; - } - if(r.from_table()) { - //We can convert directly from table plugin only if the inner plugin can handle empty signatures. - - //TODO: If the inner plugin cannot handle empty signatures, we may try to move some of the - //table columns into the inner relation signature. - return get_inner_plugin().can_handle_signature(relation_signature()); - } - return false; - } - - finite_product_relation * finite_product_relation_plugin::mk_from_table_relation(const table_relation & r) { - func_decl* pred = 0; - const relation_signature & sig = r.get_signature(); - const table_base & t = r.get_table(); - table_plugin & tplugin = r.get_table().get_plugin(); - - relation_signature inner_sig; //empty signature for the inner relation - if(!get_inner_plugin().can_handle_signature(inner_sig)) { - return 0; - } - - table_signature idx_singleton_sig; - idx_singleton_sig.push_back(finite_product_relation::s_rel_idx_sort); - idx_singleton_sig.set_functional_columns(1); - - scoped_rel idx_singleton; - if(tplugin.can_handle_signature(idx_singleton_sig)) { - idx_singleton = tplugin.mk_empty(idx_singleton_sig); - } - else { - idx_singleton = get_manager().mk_empty_table(idx_singleton_sig); - } - table_fact idx_singleton_fact; - idx_singleton_fact.push_back(0); - idx_singleton->add_fact(idx_singleton_fact); - - scoped_ptr join_fun = get_manager().mk_join_fn(t, *idx_singleton, 0, 0, 0); - SASSERT(join_fun); - scoped_rel res_table = (*join_fun)(t, *idx_singleton); - - svector table_cols(sig.size(), true); - finite_product_relation * res = mk_empty(sig, table_cols.c_ptr()); - - //this one does not need to be deleted -- it will be taken over by \c res in the \c init function - relation_base * inner_rel = get_inner_plugin().mk_full(pred, inner_sig, get_inner_plugin().get_kind()); - - relation_vector rels; - rels.push_back(inner_rel); - - res->init(*res_table, rels, true); - return res; - } - - finite_product_relation * finite_product_relation_plugin::mk_from_inner_relation(const relation_base & r) { - SASSERT(&r.get_plugin()==&get_inner_plugin()); - const relation_signature & sig = r.get_signature(); - - table_signature idx_singleton_sig; - idx_singleton_sig.push_back(finite_product_relation::s_rel_idx_sort); - idx_singleton_sig.set_functional_columns(1); - - scoped_rel idx_singleton = get_manager().mk_empty_table(idx_singleton_sig); - table_fact idx_singleton_fact; - idx_singleton_fact.push_back(0); - idx_singleton->add_fact(idx_singleton_fact); - - svector table_cols(sig.size(), false); - finite_product_relation * res = mk_empty(sig, table_cols.c_ptr()); - - relation_vector rels; - rels.push_back(r.clone()); - - res->init(*idx_singleton, rels, true); - return res; - } - - class finite_product_relation_plugin::converting_join_fn : public convenient_relation_join_fn { - finite_product_relation_plugin & m_plugin; - scoped_ptr m_native_join; - - finite_product_relation * convert(const relation_base & r) { - SASSERT(&r.get_plugin()!=&m_plugin); - if(&r.get_plugin()==&m_plugin.get_inner_plugin()) { - return m_plugin.mk_from_inner_relation(r); - } - SASSERT(r.from_table()); - const table_relation & tr = static_cast(r); - finite_product_relation * res = m_plugin.mk_from_table_relation(tr); - SASSERT(res); - return res; - } - - public: - converting_join_fn(finite_product_relation_plugin & plugin, const relation_signature & sig1, - const relation_signature & sig2, unsigned col_cnt, const unsigned * cols1, - const unsigned * cols2) - : convenient_relation_join_fn(sig1, sig2, col_cnt, cols1, cols2), - m_plugin(plugin) {} - - virtual relation_base * operator()(const relation_base & r1, const relation_base & r2) { - scoped_rel r1_conv; - if(&r1.get_plugin()!=&m_plugin) { - r1_conv = convert(r1); - } - scoped_rel r2_conv; - if(&r2.get_plugin()!=&m_plugin) { - r2_conv = convert(r2); - } - - const finite_product_relation & fpr1 = r1_conv ? *r1_conv : get(r1); - const finite_product_relation & fpr2 = r2_conv ? *r2_conv : get(r2); - - SASSERT(&fpr1.get_plugin()==&m_plugin); - SASSERT(&fpr2.get_plugin()==&m_plugin); - - if(!m_native_join) { - m_native_join = m_plugin.get_manager().mk_join_fn(fpr1, fpr2, m_cols1, m_cols2, false); - } - return (*m_native_join)(fpr1, fpr2); - } - }; - - - class finite_product_relation_plugin::join_fn : public convenient_relation_join_fn { - scoped_ptr m_tjoin_fn; - scoped_ptr m_rjoin_fn; - - unsigned_vector m_t_joined_cols1; - unsigned_vector m_t_joined_cols2; - unsigned_vector m_r_joined_cols1; - unsigned_vector m_r_joined_cols2; - - //Column equalities betweet table and inner relations. - //The columns numbers correspont to the columns of the table/inner relation - //in the result of the join operation - unsigned_vector m_tr_table_joined_cols; - unsigned_vector m_tr_rel_joined_cols; - - scoped_ptr m_filter_tr_identities; - - scoped_ptr m_tjoined_second_rel_remover; - - //determines which columns of the result are table columns and which are in the inner relation - svector m_res_table_columns; - - public: - class join_maker : public table_row_mutator_fn { - join_fn & m_parent; - const finite_product_relation & m_r1; - const finite_product_relation & m_r2; - relation_vector & m_rjoins; - public: - join_maker(join_fn & parent, const finite_product_relation & r1, const finite_product_relation & r2, - relation_vector & rjoins) - : m_parent(parent), m_r1(r1), m_r2(r2), m_rjoins(rjoins) {} - - virtual bool operator()(table_element * func_columns) { - const relation_base & or1 = m_r1.get_inner_rel(func_columns[0]); - const relation_base & or2 = m_r2.get_inner_rel(func_columns[1]); - SASSERT(&or1); - SASSERT(&or2); - unsigned new_rel_num = m_rjoins.size(); - m_rjoins.push_back(m_parent.do_rjoin(or1, or2)); - func_columns[0]=new_rel_num; - return true; - } - }; - - join_fn(const finite_product_relation & r1, const finite_product_relation & r2, unsigned col_cnt, - const unsigned * cols1, const unsigned * cols2) - : convenient_relation_join_fn(r1.get_signature(), r2.get_signature(), col_cnt, cols1, cols2) { - unsigned second_table_after_join_ofs = r1.m_table2sig.size(); - unsigned second_inner_rel_after_join_ofs = r1.m_other2sig.size(); - for(unsigned i=0;i tjoined = (*m_tjoin_fn)(r1.get_table(), r2.get_table()); - - relation_vector joined_orelations; - - { - join_maker * mutator = alloc(join_maker, *this, r1, r2, joined_orelations); //dealocated in inner_join_mapper - scoped_ptr inner_join_mapper = rmgr.mk_map_fn(*tjoined, mutator); - (*inner_join_mapper)(*tjoined); - } - - - if(!m_tjoined_second_rel_remover) { - unsigned removed_col = tjoined->get_signature().size()-1; - m_tjoined_second_rel_remover = rmgr.mk_project_fn(*tjoined, 1, &removed_col); - } - //remove the second functional column from tjoined to get a table that corresponds - //to the table signature of the resulting relation - scoped_rel res_table = (*m_tjoined_second_rel_remover)(*tjoined); - - relation_plugin & res_oplugin = - joined_orelations.empty() ? r1.m_other_plugin : joined_orelations.back()->get_plugin(); - - //TODO: Maybe we might want to specify a particular relation kind, instead of just null_family_id. - //It would however need to be somehow inferred for the new signature. - - finite_product_relation * res = alloc(finite_product_relation, r1.get_plugin(), get_result_signature(), - m_res_table_columns.c_ptr(), res_table->get_plugin(), res_oplugin, null_family_id); - - res->init(*res_table, joined_orelations, true); - - if(m_tr_table_joined_cols.size()) { - //There were some shared variables between the table and the relation part. - //We enforce those equalities here. - if(!m_filter_tr_identities) { - m_filter_tr_identities = plugin.mk_filter_identical_pairs(*res, m_tr_table_joined_cols.size(), - m_tr_table_joined_cols.c_ptr(), m_tr_rel_joined_cols.c_ptr()); - SASSERT(m_filter_tr_identities); - } - (*m_filter_tr_identities)(*res); - } - return res; - } - }; - - - - - relation_join_fn * finite_product_relation_plugin::mk_join_fn(const relation_base & rb1, const relation_base & rb2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) { - if(!check_kind(rb1) || !check_kind(rb2)) { - bool r1foreign = &rb1.get_plugin()!=this; - bool r2foreign = &rb2.get_plugin()!=this; - if( (!r1foreign || can_be_converted(rb1)) && (!r2foreign || can_be_converted(rb2))) { - return alloc(converting_join_fn, *this, rb1.get_signature(), rb2.get_signature(), col_cnt, cols1, - cols2); - } - return 0; - } - const finite_product_relation & r1 = get(rb1); - const finite_product_relation & r2 = get(rb2); - - return alloc(join_fn, r1, r2, col_cnt, cols1, cols2); - } - - - class finite_product_relation_plugin::project_fn : public convenient_relation_project_fn { - unsigned_vector m_removed_table_cols; - unsigned_vector m_removed_rel_cols; - - scoped_ptr m_rel_projector; - scoped_ptr m_inner_rel_union; - - //determines which columns of the result are table columns and which are in the inner relation - svector m_res_table_columns; - public: - project_fn(const finite_product_relation & r, unsigned col_cnt, const unsigned * removed_cols) - : convenient_relation_project_fn(r.get_signature(), col_cnt, removed_cols) { - SASSERT(col_cnt>0); - for(unsigned i=0; ii); - m_res_table_columns.push_back(r.is_table_column(i)); - } - } - - class project_reducer : public table_row_pair_reduce_fn { - project_fn & m_parent; - relation_vector & m_relations; - public: - - project_reducer(project_fn & parent, relation_vector & relations) - : m_parent(parent), m_relations(relations) {} - - virtual void operator()(table_element * func_columns, const table_element * merged_func_columns) { - relation_base * tgt = m_relations[static_cast(func_columns[0])]->clone(); - relation_base & src = *m_relations[static_cast(merged_func_columns[0])]; - if(!m_parent.m_inner_rel_union) { - m_parent.m_inner_rel_union = tgt->get_manager().mk_union_fn(*tgt, src); - } - (*m_parent.m_inner_rel_union)(*tgt, src); - - unsigned new_idx = m_relations.size(); - m_relations.push_back(tgt); - func_columns[0] = new_idx; - } - }; - - virtual relation_base * operator()(const relation_base & rb) { - const finite_product_relation & r = get(rb); - finite_product_relation_plugin & plugin = r.get_plugin(); - const table_base & rtable = r.get_table(); - relation_manager & rmgr = plugin.get_manager(); - - r.garbage_collect(false); - relation_vector res_relations; - unsigned orig_rel_cnt = r.m_others.size(); - for(unsigned i=0; iclone() : 0); - } - SASSERT(res_relations.size()==orig_rel_cnt); - - bool shared_res_table = false; - const table_base * res_table; - - if(m_removed_table_cols.empty()) { - shared_res_table = true; - res_table = &rtable; - } - else { - project_reducer * preducer = alloc(project_reducer, *this, res_relations); - scoped_ptr tproject = - rmgr.mk_project_with_reduce_fn(rtable, m_removed_table_cols.size(), m_removed_table_cols.c_ptr(), preducer); - res_table = (*tproject)(rtable); - } - - relation_plugin * res_oplugin = 0; - - if(!m_removed_rel_cols.empty()) { - unsigned res_rel_cnt = res_relations.size(); - for(unsigned i=0; ideallocate(); - if(!res_oplugin) { - res_oplugin = &res_relations[i]->get_plugin(); - } - } - } - - if(!res_oplugin) { - res_oplugin = &r.m_other_plugin; - } - - //TODO: Maybe we might want to specify a particular relation kind, instead of just null_family_id. - //It would however need to be somehow inferred for the new signature. - - finite_product_relation * res = alloc(finite_product_relation, r.get_plugin(), get_result_signature(), - m_res_table_columns.c_ptr(), res_table->get_plugin(), *res_oplugin, null_family_id); - - res->init(*res_table, res_relations, false); - - if(!shared_res_table) { - const_cast(res_table)->deallocate(); - } - - return res; - } - }; - - relation_transformer_fn * finite_product_relation_plugin::mk_project_fn(const relation_base & rb, unsigned col_cnt, - const unsigned * removed_cols) { - if(&rb.get_plugin()!=this) { - return 0; - } - return alloc(project_fn, get(rb), col_cnt, removed_cols); - } - - - - class finite_product_relation_plugin::rename_fn : public convenient_relation_rename_fn { - scoped_ptr m_table_renamer; - scoped_ptr m_rel_renamer; - bool m_rel_identity; - - unsigned_vector m_rel_permutation; - - //determines which columns of the result are table columns and which are in the inner relation - svector m_res_table_columns; - public: - rename_fn(const finite_product_relation & r, unsigned cycle_len, const unsigned * permutation_cycle) - : convenient_relation_rename_fn(r.get_signature(), cycle_len, permutation_cycle) { - SASSERT(cycle_len>1); - - unsigned sig_sz = r.get_signature().size(); - unsigned_vector permutation; - add_sequence(0, sig_sz, permutation); - permutate_by_cycle(permutation, cycle_len, permutation_cycle); - - unsigned_vector table_permutation; - - bool table_identity = true; - m_rel_identity = true; - for(unsigned new_i=0; new_iclone() : 0); - } - - if(!m_rel_identity) { - unsigned res_rel_cnt = res_relations.size(); - for(unsigned i=0; i inner_rel = res_relations[i]; - if(!m_rel_renamer) { - m_rel_renamer = r.get_manager().mk_permutation_rename_fn(*inner_rel, m_rel_permutation); - } - - res_relations[i] = (*m_rel_renamer)(*inner_rel); - } - } - scoped_rel res_table_scoped; - const table_base * res_table = &rtable; - - if(m_table_renamer) { - res_table_scoped = (*m_table_renamer)(*res_table); - res_table = res_table_scoped.get(); - } - - //TODO: Maybe we might want to specify a particular relation kind, instead of just null_family_id. - //It would however need to be somehow inferred for the new signature. - - finite_product_relation * res = alloc(finite_product_relation, r.get_plugin(), get_result_signature(), - m_res_table_columns.c_ptr(), res_table->get_plugin(), r.m_other_plugin, null_family_id); - - res->init(*res_table, res_relations, false); - - return res; - } - }; - - relation_transformer_fn * finite_product_relation_plugin::mk_rename_fn(const relation_base & rb, - unsigned permutation_cycle_len, const unsigned * permutation_cycle) { - - if(&rb.get_plugin()!=this) { - return 0; - } - const finite_product_relation & r = get(rb); - return alloc(rename_fn, r, permutation_cycle_len, permutation_cycle); - } - - - class finite_product_relation_plugin::union_fn : public relation_union_fn { - bool m_use_delta; - unsigned_vector m_data_cols;//non-functional columns in the product-relation table (useful for creating operations) - scoped_ptr m_common_join; //result of the join contains (data columns), tgt_rel_idx, src_rel_idx - scoped_ptr m_rel_union; - scoped_ptr m_table_union; - scoped_ptr m_remove_overlaps; - scoped_ptr m_remove_src_column_from_overlap; - - //this one is populated only if we're doing union with delta - scoped_ptr m_delta_merging_union; - - scoped_ptr m_overlap_delta_table_builder; - public: - union_fn(const finite_product_relation & tgt, bool use_delta) : m_use_delta(use_delta) {} - - relation_union_fn & get_inner_rel_union_op(relation_base & r) { - if(!m_rel_union) { - m_rel_union = r.get_manager().mk_union_fn(r, r, m_use_delta ? &r : 0); - } - return *m_rel_union; - } - - class union_mapper : public table_row_mutator_fn { - union_fn & m_parent; - finite_product_relation & m_tgt; - const finite_product_relation & m_src; - table_base * m_delta_indexes; //table with signature (updated tgt rel index, delta_index in m_delta_rels) - relation_vector * m_delta_rels; - table_fact m_di_fact; //auxiliary fact for inserting into \c m_delta_indexes - public: - /** - If \c delta_indexes is 0, it means we are not collecting indexes. - */ - union_mapper(union_fn & parent, finite_product_relation & tgt, const finite_product_relation & src, - table_base * delta_indexes, relation_vector * delta_rels) - : m_parent(parent), - m_tgt(tgt), - m_src(src), - m_delta_indexes(delta_indexes), - m_delta_rels(delta_rels) {} - - virtual ~union_mapper() {} - - virtual bool operator()(table_element * func_columns) { - relation_base & otgt_orig = m_tgt.get_inner_rel(func_columns[0]); - const relation_base & osrc = m_src.get_inner_rel(func_columns[1]); - - relation_base * otgt = otgt_orig.clone(); - unsigned new_tgt_idx = m_tgt.get_next_rel_idx(); - m_tgt.set_inner_rel(new_tgt_idx, otgt); - if(m_delta_indexes) { - relation_base * odelta = otgt->get_plugin().mk_empty(otgt->get_signature()); - m_parent.get_inner_rel_union_op(*otgt)(*otgt, osrc, odelta); - - unsigned delta_idx = m_delta_rels->size(); - m_delta_rels->push_back(odelta); - m_di_fact.reset(); - m_di_fact.push_back(new_tgt_idx); - m_di_fact.push_back(delta_idx); - m_delta_indexes->add_fact(m_di_fact); - } - else { - m_parent.get_inner_rel_union_op(*otgt)(*otgt, osrc); - } - - func_columns[0]=new_tgt_idx; - return true; - } - }; - - /** - Makes a table whose last column has indexes to relations in \c src into a table - with indexes to relation \c tgt. - */ - class src_copying_mapper : public table_row_mutator_fn { - finite_product_relation & m_tgt; - const finite_product_relation & m_src; - public: - /** - If \c delta_indexes is 0, it means we are not collecting indexes. - */ - src_copying_mapper(finite_product_relation & tgt, const finite_product_relation & src) - : m_tgt(tgt), m_src(src) {} - - virtual bool operator()(table_element * func_columns) { - const relation_base & osrc = m_src.get_inner_rel(func_columns[0]); - unsigned new_tgt_idx = m_tgt.get_next_rel_idx(); - m_tgt.set_inner_rel(new_tgt_idx, osrc.clone()); - func_columns[0]=new_tgt_idx; - return true; - } - }; - - virtual void operator()(relation_base & tgtb, const relation_base & srcb, relation_base * deltab) { - finite_product_relation & tgt = get(tgtb); - const finite_product_relation & src0 = get(srcb); - finite_product_relation * delta = get(deltab); - - relation_manager & rmgr = tgt.get_manager(); - - scoped_rel src_aux_copy; //copy of src in case its specification needs to be modified - - if(!vectors_equal(tgt.m_table2sig, src0.m_table2sig) - || (delta && !vectors_equal(tgt.m_table2sig, delta->m_table2sig)) ) { - src_aux_copy = src0.clone(); - ptr_vector orig_rels; - orig_rels.push_back(src_aux_copy.get()); - orig_rels.push_back(&tgt); - if(delta) { - orig_rels.push_back(delta); - } - if(!finite_product_relation::try_unify_specifications(orig_rels)) { - throw default_exception("finite_product_relation union: cannot convert relations to common specification"); - } - } - - const finite_product_relation & src = src_aux_copy ? *src_aux_copy : src0; - - table_plugin & tplugin = tgt.get_table_plugin(); - - if(!m_common_join) { - unsigned data_cols_cnt = tgt.m_table_sig.size()-1; - for(unsigned i=0; i table_overlap = (*m_common_join)(tgt.get_table(), src.get_table()); - - scoped_rel delta_indexes; - relation_vector delta_rels; - if(m_use_delta) { - table_signature di_sig; - di_sig.push_back(finite_product_relation::s_rel_idx_sort); - di_sig.push_back(finite_product_relation::s_rel_idx_sort); - di_sig.set_functional_columns(1); - delta_indexes = tplugin.mk_empty(di_sig); - } - - { - union_mapper * umapper = alloc(union_mapper, *this, tgt, src, delta_indexes.get(), &delta_rels); - scoped_ptr mapping_fn = rmgr.mk_map_fn(*table_overlap, umapper); - (*mapping_fn)(*table_overlap); - } - - if(!m_remove_src_column_from_overlap) { - unsigned removed_cols[] = { table_overlap->get_signature().size()-1 }; - m_remove_src_column_from_overlap = rmgr.mk_project_fn(*table_overlap, 1, removed_cols); - } - //transform table_overlap into the signature of tgt.get_table(), so that the functional - //column contains indexes of the united relations - scoped_rel regular_overlap = (*m_remove_src_column_from_overlap)(*table_overlap); - - - if(!m_remove_overlaps) { - m_remove_overlaps = rmgr.mk_filter_by_negation_fn(tgt.get_table(), *regular_overlap, m_data_cols, - m_data_cols); - } - - //in tgt keep only the rows that are in tgt only - (*m_remove_overlaps)(tgt.get_table(), *regular_overlap); - - //add rows in which tgt and src overlapped - if(!m_table_union) { - m_table_union = rmgr.mk_union_fn(tgt.get_table(), tgt.get_table()); - } - (*m_table_union)(tgt.get_table(), *regular_overlap); - - scoped_rel src_only = src.get_table().clone(); - (*m_remove_overlaps)(*src_only, *regular_overlap); - - scoped_rel src_only2; //a copy of src_only for use in building the delta - if(m_use_delta) { - src_only2 = src_only->clone(); - } - - { - src_copying_mapper * cpmapper = alloc(src_copying_mapper, tgt, src); - scoped_ptr mapping_fn = rmgr.mk_map_fn(*src_only, cpmapper); - (*mapping_fn)(*src_only); - } - - //add rows that were only in src - (*m_table_union)(tgt.get_table(), *src_only); - - if(m_use_delta) { - bool extending_delta = !delta->empty(); - //current delta, we will add it to the deltab argument later if it was not given to us empty - finite_product_relation * cdelta; - if(extending_delta) { - cdelta = delta->get_plugin().mk_empty(*delta); - } - else { - cdelta = delta; - } - - if(!m_overlap_delta_table_builder) { - unsigned table_fn_col = regular_overlap->get_signature().size()-1; - unsigned first_col = 0; - unsigned removed_cols[] = { table_fn_col, table_fn_col+1 }; - m_overlap_delta_table_builder = rmgr.mk_join_project_fn(*regular_overlap, *delta_indexes, 1, - &table_fn_col, &first_col, 2, removed_cols); - } - - scoped_rel overlap_delta_table = - (*m_overlap_delta_table_builder)(*regular_overlap, *delta_indexes); - - cdelta->init(*overlap_delta_table, delta_rels, true); - - { - src_copying_mapper * cpmapper = alloc(src_copying_mapper, *cdelta, src); - scoped_ptr mapping_fn = rmgr.mk_map_fn(*src_only2, cpmapper); - (*mapping_fn)(*src_only2); - } - - //add rows that were only in src - (*m_table_union)(cdelta->get_table(), *src_only2); - - if(extending_delta) { - if(!m_delta_merging_union) { - m_delta_merging_union = rmgr.mk_union_fn(*delta, *cdelta); - } - (*m_delta_merging_union)(*delta, *cdelta); - cdelta->deallocate(); - } - } - } - }; - -#if 0 - /** - Union operation taking advantage of the fact that the inner relation of all the arguments - is a singleton relation. - */ - class finite_product_relation_plugin::inner_singleton_union_fn : public relation_union_fn { - - class offset_row_mapper : public table_row_mutator_fn { - public: - unsigned m_ofs; - virtual bool operator()(table_element * func_columns) { - func_columns[0] += m_ofs; - return true; - } - }; - - // [Leo]: gcc complained about the following class. - // It does not have a constructor and uses a reference - - class inner_relation_copier : public table_row_mutator_fn { - finite_product_relation & m_tgt; - const finite_product_relation & m_src; - finite_product_relation * m_delta; - unsigned m_tgt_ofs; - unsigned m_delta_ofs; - public: - virtual bool operator()(table_element * func_columns) { - unsigned src_idx = static_cast(func_columns[0]); - unsigned tgt_idx = src_idx + m_tgt_ofs; - unsigned delta_idx = m_delta ? (src_idx + m_delta_ofs) : 0; - SASSERT(!m_delta || m_tgt.m_others[tgt_idx]==m_delta->m_others[delta_idx]); - SASSERT(m_tgt.m_others[tgt_idx]==0 || m_tgt.m_others[tgt_idx]==m_src.m_others[src_idx]); - if(m_tgt.m_others[tgt_idx]==0) { - m_tgt.m_others[tgt_idx] = m_src.m_others[src_idx]->clone(); - if(m_delta) { - m_delta->m_others[delta_idx] = m_src.m_others[src_idx]->clone(); - } - } - return true; - } - }; - - scoped_ptr m_t_union_fun; - offset_row_mapper * m_offset_mapper_obj; //initialized together with m_offset_mapper_fun, and deallocated by it - scoped_ptr m_offset_mapper_fun; - - - - public: - virtual void operator()(relation_base & tgtb, const relation_base & srcb, relation_base * deltab) { - finite_product_relation & tgt = get(tgtb); - const finite_product_relation & src = get(srcb); - finite_product_relation * delta = get(deltab); - - finite_product_relation_plugin & plugin = tgt.get_plugin(); - relation_manager & rmgr = plugin.get_manager(); - - //we want only non-empty inner relations to remain - tgt.garbage_collect(true); - src.garbage_collect(true); - - table_base & tgt_table = tgt.get_table(); - const table_base & src_table = src.get_table(); - - scoped_rel offsetted_src = src_table.clone(); - - if(!m_offset_mapper_fun) { - m_offset_mapper_obj = alloc(offset_row_mapper); - m_offset_mapper_fun = rmgr.mk_map_fn(*offsetted_src, m_offset_mapper_obj); - } - unsigned src_rel_offset = tgt.m_others.size(); - m_offset_mapper_obj->m_ofs = src_rel_offset; - - (*m_offset_mapper_fun)(*offsetted_src); - - //if we need to generate a delta, we get collect it into an empty relation and then union - //it with the delta passed in as argument. - scoped_rel loc_delta = delta ? get(plugin.mk_empty(*delta)) : 0; - //even if we don't need to generate the delta for the caller, we still want to have a delta - //table to know which relations to copy. - scoped_rel loc_delta_table_scoped; - if(!loc_delta) { - loc_delta_table_scoped = tgt_table.get_plugin().mk_empty(tgt_table); - } - table_base * loc_delta_table = loc_delta ? &loc_delta->get_table() : loc_delta_table_scoped.get(); - - if(!m_t_union_fun) { - m_t_union_fun = rmgr.mk_union_fn(tgt_table, *offsetted_src, loc_delta_table); - } - (*m_t_union_fun)(tgt_table, *offsetted_src, loc_delta_table); - - - //TODO: copy the relations into tgt and (possibly) delta using inner_relation_copier - //TODO: unite the local delta with the delta passed in as an argument - NOT_IMPLEMENTED_YET(); - } - }; -#endif - - class finite_product_relation_plugin::converting_union_fn : public relation_union_fn { - scoped_ptr m_tr_union_fun; - public: - virtual void operator()(relation_base & tgtb, const relation_base & srcb, relation_base * deltab) { - SASSERT(srcb.get_plugin().is_finite_product_relation()); - const finite_product_relation & src = get(srcb); - finite_product_relation_plugin & plugin = src.get_plugin(); - scoped_rel tr_src = plugin.to_table_relation(src); - if(!m_tr_union_fun) { - m_tr_union_fun = plugin.get_manager().mk_union_fn(tgtb, *tr_src, deltab); - SASSERT(m_tr_union_fun); - } - (*m_tr_union_fun)(tgtb, *tr_src, deltab); - } - }; - - relation_union_fn * finite_product_relation_plugin::mk_union_fn(const relation_base & tgtb, const relation_base & srcb, - const relation_base * deltab) { - if(&srcb.get_plugin()!=this) { - return 0; - } - const finite_product_relation & src = get(srcb); - if(&tgtb.get_plugin()!=this || (deltab && &deltab->get_plugin()!=this) ) { - if(can_convert_to_table_relation(src)) { - return alloc(converting_union_fn); - } - return 0; - } - - const finite_product_relation * delta = get(deltab); - - return alloc(union_fn, get(tgtb), delta!=0); - } - - - class finite_product_relation_plugin::filter_identical_fn : public relation_mutator_fn { - //the table and relation columns that should be identical - //the column numbering is local to the table or inner relation - unsigned_vector m_table_cols; - unsigned_vector m_rel_cols; - - scoped_ptr m_table_filter; - scoped_ptr m_rel_filter; - scoped_ptr m_tr_filter; - public: - filter_identical_fn(const finite_product_relation & r, unsigned col_cnt, const unsigned * identical_cols) - : m_table_filter(0), m_rel_filter(0), m_tr_filter(0) { - finite_product_relation_plugin & plugin = r.get_plugin(); - for(unsigned i=0; i1) { - m_table_filter = r.get_manager().mk_filter_identical_fn(r.get_table(), m_table_cols.size(), - m_table_cols.c_ptr()); - SASSERT(m_table_filter); - } - if(!m_table_cols.empty() && !m_rel_cols.empty()) { - unsigned tr_filter_table_cols[] = { m_table_cols[0] }; - unsigned tr_filter_rel_cols[] = { m_rel_cols[0] }; - m_tr_filter = plugin.mk_filter_identical_pairs(r, 1, tr_filter_table_cols, tr_filter_rel_cols); - SASSERT(m_tr_filter); - } - } - - void ensure_rel_filter(const relation_base & orel) { - SASSERT(m_rel_cols.size()>1); - if(m_rel_filter) { - return; - } - m_rel_filter = orel.get_manager().mk_filter_identical_fn(orel, m_rel_cols.size(), m_rel_cols.c_ptr()); - SASSERT(m_rel_filter); - } - - virtual void operator()(relation_base & rb) { - finite_product_relation & r = get(rb); - - if(m_table_cols.size()>1) { - (*m_table_filter)(r.get_table()); - } - - if(m_rel_cols.size()>1) { - r.garbage_collect(true); - unsigned rel_cnt = r.m_others.size(); - for(unsigned rel_idx=0; rel_idx m_table_filter; - scoped_ptr m_rel_filter; - unsigned m_col; - app_ref m_value; - public: - filter_equal_fn(const finite_product_relation & r, const relation_element & value, unsigned col) - : m_col(col), m_value(value, r.get_context().get_manager()) { - if(r.is_table_column(col)) { - table_element tval; - r.get_manager().relation_to_table(r.get_signature()[col], value, tval); - m_table_filter = r.get_manager().mk_filter_equal_fn(r.get_table(), tval, r.m_sig2table[col]); - } - } - - virtual void operator()(relation_base & rb) { - finite_product_relation & r = get(rb); - - if(m_table_filter) { - (*m_table_filter)(r.get_table()); - return; - } - r.garbage_collect(false); - relation_vector & inner_rels = r.m_others; - unsigned rel_cnt = inner_rels.size(); - for(unsigned i=0; i m_table_filter; - scoped_ptr m_rel_filter; - app_ref m_cond; - - idx_set m_table_cond_columns; - idx_set m_rel_cond_columns; - - //like m_table_cond_columns and m_rel_cond_columns, only the indexes are local to the - //table/relation, not to the signature of the whole relation - idx_set m_table_local_cond_columns; - idx_set m_rel_local_cond_columns; - - /** - If equal to 0, it means the interpreted condition uses all table columns. Then the original - table is used instead of the result of the projection. - */ - scoped_ptr m_table_cond_columns_project; - /** - \brief Column indexes of the global relations to which correspond the data columns in the table - that is result of applying the \c m_table_cond_columns_project functor. - */ - unsigned_vector m_global_origins_of_projected_columns; - - scoped_ptr m_assembling_join_project; - - - /** - \brief Renaming that transforms the variable numbers pointing to the global relation into - variables that point to the inner relation variables. - - The elements that do not correspond to columns of the inner relation (but rather to the table - columns) is modified in \c operator() when evaluating the condition for all the relevant - combinations of table values. - */ - expr_ref_vector m_renaming_for_inner_rel; - public: - filter_interpreted_fn(const finite_product_relation & r, app * condition) - : m_manager(r.get_context().get_manager()), - m_subst(r.get_context().get_var_subst()), - m_cond(condition, m_manager), - m_renaming_for_inner_rel(m_manager) { - relation_manager & rmgr = r.get_manager(); - - rule_manager& rm = r.get_context().get_rule_manager(); - idx_set& cond_columns = rm.collect_vars(m_cond); - - unsigned sig_sz = r.get_signature().size(); - for(unsigned i=0; i tproj_scope; - const table_base * tproj; - if(m_table_cond_columns_project) { - tproj_scope = (*m_table_cond_columns_project)(rtable); - tproj = tproj_scope.get(); - } - else { - tproj = &rtable; - } - unsigned projected_data_cols = tproj->get_signature().size()-1; - SASSERT(m_table_cond_columns.num_elems()==projected_data_cols); - - table_signature filtered_sig = tproj->get_signature(); - filtered_sig.push_back(finite_product_relation::s_rel_idx_sort); - filtered_sig.set_functional_columns(1); - - relation_vector new_rels; - - scoped_rel filtered_table = tplugin.mk_empty(filtered_sig); - table_fact f; - unsigned renaming_ofs = m_renaming_for_inner_rel.size()-1; - table_base::iterator pit = tproj->begin(); - table_base::iterator pend = tproj->end(); - for(; pit!=pend; ++pit) { - pit->get_fact(f); - unsigned old_rel_idx = static_cast(f.back()); - const relation_base & old_rel = r.get_inner_rel(old_rel_idx); - - //put the table values into the substitution - for(unsigned i=0; i filter = rmgr.mk_filter_interpreted_fn(*new_rel, to_app(inner_cond)); - (*filter)(*new_rel); - - if(new_rel->empty()) { - new_rel->deallocate(); - continue; - } - - unsigned new_rel_idx = new_rels.size(); - new_rels.push_back(new_rel); - f.push_back(new_rel_idx); - filtered_table->add_fact(f); - } - - if(!m_assembling_join_project) { - unsigned_vector table_cond_columns_vect; - for(unsigned i=0; i new_table = (*m_assembling_join_project)(rtable, *filtered_table); - r.reset(); - r.init(*new_table, new_rels, true); - } - }; - - relation_mutator_fn * finite_product_relation_plugin::mk_filter_interpreted_fn(const relation_base & rb, - app * condition) { - if(&rb.get_plugin()!=this) { - return 0; - } - return alloc(filter_interpreted_fn, get(rb), condition); - } - - class finite_product_relation_plugin::negation_filter_fn : public relation_intersection_filter_fn { - - unsigned_vector m_r_cols; - unsigned_vector m_neg_cols; - - scoped_ptr m_table_neg_filter; - scoped_ptr m_table_neg_complement_selector; - scoped_ptr m_neg_intersection_join; - scoped_ptr m_table_intersection_join; - scoped_ptr m_table_overlap_union; - scoped_ptr m_table_subtract; - scoped_ptr m_inner_subtract; - scoped_ptr m_overlap_table_last_column_remover; - scoped_ptr m_r_table_union; - - bool m_table_overlaps_only; - - unsigned_vector m_r_shared_table_cols; - unsigned_vector m_neg_shared_table_cols; - - unsigned_vector m_r_shared_rel_cols; - unsigned_vector m_neg_shared_rel_cols; - public: - negation_filter_fn(const finite_product_relation & r, const finite_product_relation & neg, - unsigned joined_col_cnt, const unsigned * r_cols, const unsigned * neg_cols) - : m_r_cols(joined_col_cnt, r_cols), - m_neg_cols(joined_col_cnt, neg_cols), - m_table_overlaps_only(true) { - const table_signature & tsig = r.m_table_sig; - const table_base & rtable = r.get_table(); - relation_manager & rmgr = r.get_manager(); - - for(unsigned i=0; iget_signature().size() , all_rel_cols); - m_parent.m_inner_subtract = m_r.get_manager().mk_filter_by_negation_fn(*r_inner, - inters_inner, all_rel_cols, all_rel_cols); - } - (*m_parent.m_inner_subtract)(*r_inner, inters_inner); - - unsigned new_rel_num = m_r.get_next_rel_idx(); - m_r.set_inner_rel(new_rel_num, r_inner); - func_columns[0]=new_rel_num; - return true; - } - }; - - - virtual void operator()(relation_base & rb, const relation_base & negb) { - finite_product_relation & r = get(rb); - const finite_product_relation & neg = get(negb); - - if(m_table_overlaps_only) { - handle_only_tables_overlap_case(r, neg); - return; - } - - finite_product_relation_plugin & plugin = r.get_plugin(); - if(!m_neg_intersection_join) { - } - scoped_rel intersection = get((*m_neg_intersection_join)(r, neg)); - SASSERT(&intersection->get_plugin()==&plugin); //the result of join is also finite product - SASSERT(r.get_signature()==intersection->get_signature()); - - table_base & r_table = r.get_table(); - table_plugin & tplugin = r_table.get_plugin(); - relation_manager & rmgr = r.get_manager(); - - //we need to do this before we perform the \c m_table_subtract - //the sigrature of the \c table_overlap0 relation is - //(data_columns)(original rel idx)(subtracted rel idx) - scoped_rel table_overlap0 = (*m_table_intersection_join)(r_table, - intersection->get_table()); - - //the rows that don't appear in the table of the intersection are safe to stay - (*m_table_subtract)(r_table, intersection->get_table()); - - //now we will examine the rows that do appear in the intersection - - //There are no functional columns in the \c table_overlap0 relation (because of - //the project we did). We need to make both rel idx columns functional. - //We do not lose any rows, since the data columns by themselves are unique. - - table_signature table_overlap_sig(table_overlap0->get_signature()); - table_overlap_sig.set_functional_columns(2); - scoped_rel table_overlap = tplugin.mk_empty(table_overlap_sig); - - if(!m_table_overlap_union) { - m_table_overlap_union = rmgr.mk_union_fn(*table_overlap, *table_overlap0); - SASSERT(m_table_overlap_union); - } - (*m_table_overlap_union)(*table_overlap, *table_overlap0); - - { - rel_subtractor * mutator = alloc(rel_subtractor, *this, r, *intersection); - scoped_ptr mapper = rmgr.mk_map_fn(*table_overlap, mutator); - (*mapper)(*table_overlap); - } - - if(!m_overlap_table_last_column_remover) { - unsigned removed_col = table_overlap->get_signature().size()-1; - m_overlap_table_last_column_remover = rmgr.mk_project_fn(*table_overlap, 1, &removed_col); - } - scoped_rel final_overlapping_rows_table = - (*m_overlap_table_last_column_remover)(*table_overlap); - - if(!m_r_table_union) { - m_r_table_union = rmgr.mk_union_fn(r_table, *final_overlapping_rows_table); - } - - (*m_r_table_union)(r_table, *final_overlapping_rows_table); - } - }; - - relation_intersection_filter_fn * finite_product_relation_plugin::mk_filter_by_negation_fn(const relation_base & rb, - const relation_base & negb, unsigned joined_col_cnt, - const unsigned * r_cols, const unsigned * negated_cols) { - if(&rb.get_plugin()!=this || &negb.get_plugin()!=this) { - return 0; - } - - return alloc(negation_filter_fn, get(rb), get(negb), joined_col_cnt, r_cols, negated_cols); - } - - - class finite_product_relation_plugin::filter_identical_pairs_fn : public relation_mutator_fn { - scoped_ptr m_tproject_fn; //if zero, no columns need to be projected away - unsigned m_col_cnt; - unsigned_vector m_table_cols; - unsigned_vector m_rel_cols; - - scoped_ptr m_assembling_join_project; - scoped_ptr m_updating_union; - public: - filter_identical_pairs_fn(const finite_product_relation & r, unsigned col_cnt, const unsigned * table_cols, - const unsigned * rel_cols) : - m_col_cnt(col_cnt), - m_table_cols(col_cnt, table_cols), - m_rel_cols(col_cnt, rel_cols) { - SASSERT(col_cnt>0); - const table_signature & tsig = r.m_table_sig; - unsigned t_sz = tsig.size(); - - sort_two_arrays(col_cnt, m_table_cols.begin(), m_rel_cols.begin()); - SASSERT(m_table_cols.back() tproj; - if(m_tproject_fn) { - tproj = (*m_tproject_fn)(r.get_table()); - } - else { - tproj = r.get_table().clone(); - } - SASSERT(m_col_cnt+1==tproj->get_signature().size()); - - table_signature filtered_sig = tproj->get_signature(); - filtered_sig.push_back(finite_product_relation::s_rel_idx_sort); - filtered_sig.set_functional_columns(1); - - relation_vector new_rels; - scoped_rel filtered_table = tplugin.mk_empty(filtered_sig); - table_fact f; - table_base::iterator pit = tproj->begin(); - table_base::iterator pend = tproj->end(); - for(; pit!=pend; ++pit) { - pit->get_fact(f); - unsigned old_rel_idx = static_cast(f.back()); - const relation_base & old_rel = r.get_inner_rel(old_rel_idx); - relation_base * new_rel = old_rel.clone(); - for(unsigned i=0; i filter = rmgr.mk_filter_equal_fn(*new_rel, r_el, m_rel_cols[i]); - (*filter)(*new_rel); - } - - if(new_rel->empty()) { - new_rel->deallocate(); - continue; - } - - unsigned new_rel_idx = new_rels.size(); - new_rels.push_back(new_rel); - f.push_back(new_rel_idx); - filtered_table->add_fact(f); - } - - if(!m_assembling_join_project) { - m_assembling_join_project = mk_assembler_of_filter_result(rtable, *filtered_table, m_table_cols); - } - - scoped_rel new_table = (*m_assembling_join_project)(r.get_table(), *filtered_table); - - r.reset(); - r.init(*new_table, new_rels, true); - } - }; - - relation_mutator_fn * finite_product_relation_plugin::mk_filter_identical_pairs(const finite_product_relation & r, - unsigned col_cnt, const unsigned * table_cols, const unsigned * rel_cols) { - return alloc(filter_identical_pairs_fn, r, col_cnt, table_cols, rel_cols); - } - - table_join_fn * finite_product_relation_plugin::mk_assembler_of_filter_result(const table_base & relation_table, - const table_base & filtered_table, const unsigned_vector & selected_columns) { - - table_plugin & tplugin = relation_table.get_plugin(); - const table_signature & rtable_sig = relation_table.get_signature(); - unsigned rtable_sig_sz = rtable_sig.size(); - unsigned selected_col_cnt = selected_columns.size(); - SASSERT(selected_col_cnt+2==filtered_table.get_signature().size()); - SASSERT(rtable_sig.functional_columns()==1); - SASSERT(filtered_table.get_signature().functional_columns()==1); - - unsigned_vector rtable_joined_cols; - rtable_joined_cols.append(selected_col_cnt, selected_columns.c_ptr()); //filtered table cols - rtable_joined_cols.push_back(rtable_sig_sz-1); //unfiltered relation indexes - - unsigned_vector filtered_joined_cols; - add_sequence(0, selected_col_cnt, filtered_joined_cols); //filtered table cols - filtered_joined_cols.push_back(selected_col_cnt); //unfiltered relation indexes - SASSERT(rtable_joined_cols.size()==filtered_joined_cols.size()); - - //the signature after join: - //(all relation table columns)(all filtered relation table columns)(unfiltered rel idx non-func from 'filtered') - // (unfiltered rel idx func from 'rtable')(filtered rel idx) - unsigned_vector removed_cols; - unsigned filtered_nonfunc_ofs = rtable_sig_sz-1; - add_sequence(filtered_nonfunc_ofs, selected_col_cnt, removed_cols); //data columns from 'filtered' - unsigned idx_ofs = filtered_nonfunc_ofs+selected_col_cnt; - removed_cols.push_back(idx_ofs); //unfiltered relation indexes from 'filtered' - removed_cols.push_back(idx_ofs+1); //unfiltered relation indexes from rtable - - table_join_fn * res = tplugin.get_manager().mk_join_project_fn(relation_table, filtered_table, - rtable_joined_cols, filtered_joined_cols, removed_cols); - SASSERT(res); - return res; - } - - // ----------------------------------- - // - // finite_product_relation - // - // ----------------------------------- - - finite_product_relation::finite_product_relation(finite_product_relation_plugin & p, - const relation_signature & s, const bool * table_columns, table_plugin & tplugin, - relation_plugin & oplugin, family_id other_kind) - : relation_base(p, s), - m_other_plugin(oplugin), - m_other_kind(other_kind), - m_full_rel_idx(UINT_MAX) { - const relation_signature & rel_sig = get_signature(); - unsigned sz = rel_sig.size(); - m_sig2table.resize(sz, UINT_MAX); - m_sig2other.resize(sz, UINT_MAX); - for(unsigned i=0; iclone()), - m_others(r.m_others), - m_available_rel_indexes(r.m_available_rel_indexes), - m_full_rel_idx(r.m_full_rel_idx), - m_live_rel_collection_project(), - m_empty_rel_removal_filter() { - //m_others is now just a shallow copy, we need use clone of the relations that in it now - unsigned other_sz = m_others.size(); - for(unsigned i=0; ideallocate(); - relation_vector::iterator it = m_others.begin(); - relation_vector::iterator end = m_others.end(); - for(; it!=end; ++it) { - relation_base * rel= *it; - if(rel) { - rel->deallocate(); - } - } - } - - context & finite_product_relation::get_context() const { - return get_manager().get_context(); - } - - unsigned finite_product_relation::get_next_rel_idx() const { - unsigned res; - if(!m_available_rel_indexes.empty()) { - res = m_available_rel_indexes.back(); - m_available_rel_indexes.pop_back(); - } - else { - res = m_others.size(); - m_others.push_back(0); - } - SASSERT(m_others[res]==0); - return res; - } - - void finite_product_relation::recycle_rel_idx(unsigned idx) const { - SASSERT(m_others[idx]==0); - m_available_rel_indexes.push_back(idx); - } - - unsigned finite_product_relation::get_full_rel_idx() { - if(m_full_rel_idx==UINT_MAX) { - m_full_rel_idx = get_next_rel_idx(); - relation_base * full_other = mk_full_inner(0); - m_others[m_full_rel_idx] = full_other; - } - return m_full_rel_idx; - } - - void finite_product_relation::init(const table_base & table_vals, const relation_vector & others, bool contiguous) { - SASSERT(m_table_sig.equal_up_to_fn_mark(table_vals.get_signature())); - SASSERT(empty()); - if(!m_others.empty()) { - garbage_collect(false); - } - SASSERT(m_others.empty()); - - m_others = others; - scoped_ptr table_union = get_manager().mk_union_fn(get_table(), table_vals); - (*table_union)(get_table(), table_vals); - - if(!contiguous) { - unsigned rel_cnt = m_others.size(); - for(unsigned i=0; isuggest_fact(t_f)) { - SASSERT(t_f.back()==new_rel_idx); - new_rel = mk_empty_inner(); - } else { - new_rel = get_inner_rel(t_f.back()).clone(); - - t_f[t_f.size()-1]=new_rel_idx; - m_table->ensure_fact(t_f); - } - new_rel->add_fact(o_f); - set_inner_rel(new_rel_idx, new_rel); - } - - bool finite_product_relation::contains_fact(const relation_fact & f) const { - table_fact t_f; - extract_table_fact(f, t_f); - - if(!m_table->fetch_fact(t_f)) { - return false; - } - - relation_fact o_f(get_context()); - extract_other_fact(f, o_f); - - const relation_base & other = get_inner_rel(t_f.back()); - - return other.contains_fact(o_f); - } - - bool finite_product_relation::empty() const { - garbage_collect(true); - return m_table->empty(); - } - - finite_product_relation * finite_product_relation::clone() const { - return alloc(finite_product_relation, *this); - } - - void finite_product_relation::complement_self(func_decl* p) { - unsigned other_sz = m_others.size(); - for(unsigned i=0; icomplement(p); - std::swap(m_others[i],r); - r->deallocate(); - } - table_element full_rel_idx = get_full_rel_idx(); - scoped_rel complement_table = m_table->complement(p, &full_rel_idx); - - scoped_ptr u_fn = get_manager().mk_union_fn(*m_table, *complement_table, 0); - SASSERT(u_fn); - (*u_fn)(*m_table, *complement_table, 0); - } - - finite_product_relation * finite_product_relation::complement(func_decl* p) const { - finite_product_relation * res = clone(); - res->complement_self(p); - return res; - } - - class finite_product_relation::live_rel_collection_reducer : public table_row_pair_reduce_fn { - idx_set & m_accumulator; - public: - live_rel_collection_reducer(idx_set & accumulator) : m_accumulator(accumulator) {} - - virtual void operator()(table_element * func_columns, const table_element * merged_func_columns) { - m_accumulator.insert(static_cast(merged_func_columns[0])); - } - }; - - void finite_product_relation::collect_live_relation_indexes(idx_set & res) const { - SASSERT(res.empty()); - unsigned table_data_col_cnt = m_table_sig.size()-1; - - if(table_data_col_cnt==0) { - if(!get_table().empty()) { - table_base::iterator iit = get_table().begin(); - table_base::iterator iend = get_table().end(); - - SASSERT(iit!=iend); - res.insert(static_cast((*iit)[0])); - SASSERT((++iit)==iend); - } - return; - } - - if(!m_live_rel_collection_project) { - buffer removed_cols; - removed_cols.resize(table_data_col_cnt); - for(unsigned i=0; i live_indexes_table = (*m_live_rel_collection_project)(get_table()); - res.swap(m_live_rel_collection_acc); - - SASSERT(live_indexes_table->get_signature().size()==1); - SASSERT(live_indexes_table->get_signature().functional_columns()==1); - if(!live_indexes_table->empty()) { - table_base::iterator iit = live_indexes_table->begin(); - table_base::iterator iend = live_indexes_table->end(); - - SASSERT(iit!=iend); - res.insert(static_cast((*iit)[0])); - SASSERT((++iit)==iend); - } - } - - void finite_product_relation::garbage_collect(bool remove_empty) const { - idx_set live_indexes; - collect_live_relation_indexes(live_indexes); - - scoped_rel empty_rel_indexes; //populated only if \c remove_empty==true - table_fact empty_rel_fact; - - unsigned rel_cnt = m_others.size(); -#if Z3DEBUG - unsigned encountered_live_indexes = 0; -#endif - for(unsigned rel_idx=0; rel_idxempty()) { - continue; - } - if(empty_rel_indexes==0) { - table_signature empty_rel_indexes_sig; - empty_rel_indexes_sig.push_back(s_rel_idx_sort); - empty_rel_indexes = get_table_plugin().mk_empty(empty_rel_indexes_sig); - } - empty_rel_fact.reset(); - empty_rel_fact.push_back(rel_idx); - empty_rel_indexes->add_fact(empty_rel_fact); - } - m_others[rel_idx]->deallocate(); - m_others[rel_idx] = 0; - if(rel_idx==m_full_rel_idx) { - m_full_rel_idx = UINT_MAX; - } - recycle_rel_idx(rel_idx); - } - SASSERT(encountered_live_indexes==live_indexes.num_elems()); - - if(m_available_rel_indexes.size()==m_others.size()) { - m_available_rel_indexes.reset(); - m_others.reset(); - } - - if(empty_rel_indexes) { - SASSERT(remove_empty); - - if(!m_empty_rel_removal_filter) { - unsigned t_joined_cols[] = { m_table_sig.size()-1 }; - unsigned ei_joined_cols[] = { 0 }; - m_empty_rel_removal_filter = get_manager().mk_filter_by_negation_fn(get_table(), *empty_rel_indexes, - 1, t_joined_cols, ei_joined_cols); - } - - (*m_empty_rel_removal_filter)(*m_table, *empty_rel_indexes); - } - } - - bool finite_product_relation::try_unify_specifications(ptr_vector & rels) { - if(rels.empty()) { - return true; - } - unsigned sig_sz = rels.back()->get_signature().size(); - svector table_cols(sig_sz, true); - - ptr_vector::iterator it = rels.begin(); - ptr_vector::iterator end = rels.end(); - for(; it!=end; ++it) { - finite_product_relation & rel = **it; - for(unsigned i=0; i pr_fun = get_manager().mk_project_fn(get_table(), to_project_away); - table_base * moved_cols_table = (*pr_fun)(get_table()); //gets destroyed inside moved_cols_trel - scoped_rel moved_cols_trel = - rmgr.get_table_relation_plugin(moved_cols_table->get_plugin()).mk_from_table(moved_cols_sig, moved_cols_table); - - svector moved_cols_table_flags(moved_cols_sig.size(), false); - - scoped_rel moved_cols_rel = get_plugin().mk_empty(moved_cols_sig, - moved_cols_table_flags.c_ptr()); - - scoped_ptr union_fun = - get_manager().mk_union_fn(*moved_cols_rel, *moved_cols_trel); - SASSERT(union_fun); //the table_relation should be able to be 'unioned into' any relation - - (*union_fun)(*moved_cols_rel, *moved_cols_trel); - - unsigned_vector all_moved_cols_indexes; - add_sequence(0, moved_cols_sig.size(), all_moved_cols_indexes); - - scoped_ptr join_fun = get_manager().mk_join_project_fn(*this, *moved_cols_rel, new_rel_columns, - all_moved_cols_indexes, new_rel_columns, false); - - scoped_rel unordered_rel = (*join_fun)(*this, *moved_cols_rel); - SASSERT(unordered_rel->get_signature().size()==sig_sz); //the signature size should be the same as original - - //now we need to reorder the columns in the \c new_rel to match the original table - unsigned_vector permutation; - unsigned moved_cols_cnt = new_rel_columns.size(); - unsigned next_replaced_idx = 0; - unsigned next_orig_idx = 0; - for(unsigned i=0; i perm_fun = get_manager().mk_rename_fn(*unordered_rel, cycle); - //the scoped_rel wrapper does the destruction of the old object - unordered_rel = (*perm_fun)(*unordered_rel); - cycle.reset(); - } - - finite_product_relation & new_rel = finite_product_relation_plugin::get(*unordered_rel); - - //Swap the content of the current object and new_rel. On exitting the function new_rel will be destroyed - //since it points to the content of scoped_rel unordered_rel. - swap(new_rel); - - return true; - } - - void finite_product_relation::display(std::ostream & out) const { - - garbage_collect(true); - - out << "finite_product_relation:\n"; - - out << " table:\n"; - get_table().display(out); - - unsigned other_sz = m_others.size(); - for(unsigned i=0; iget_fact(tfact); - - const table_relation & orel = static_cast(get_inner_rel(tfact[rel_idx_col])); - const table_base & otable = orel.get_table(); - table_base::iterator oit = otable.begin(); - table_base::iterator oend = otable.end(); - for(; oit!=oend; ++oit) { - oit->get_fact(ofact); - - out << "\t("; - for(unsigned i=0; iget_fact(fact); - conjs.reset(); - SASSERT(fact.size() == fact_sz); - unsigned rel_idx = static_cast(fact[fact_sz-1]); - m_others[rel_idx]->to_formula(tmp); - for (unsigned i = 0; i + 1 < fact_sz; ++i) { - conjs.push_back(m.mk_eq(m.mk_var(i, sig[i]), util.mk_numeral(fact[i], sig[i]))); - } - sh(tmp, fact_sz-1, tmp); - conjs.push_back(tmp); - disjs.push_back(m.mk_and(conjs.size(), conjs.c_ptr())); - } - bool_rewriter(m).mk_or(disjs.size(), disjs.c_ptr(), fml); - } - -}; - diff --git a/src/muz/dl_finite_product_relation.h b/src/muz/dl_finite_product_relation.h deleted file mode 100644 index d5181d122..000000000 --- a/src/muz/dl_finite_product_relation.h +++ /dev/null @@ -1,366 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - dl_finite_product_relation.h - -Abstract: - - - -Author: - - Krystof Hoder (t-khoder) 2010-09-24. - -Revision History: - ---*/ -#ifndef _DL_FINITE_PRODUCT_RELATION_H_ -#define _DL_FINITE_PRODUCT_RELATION_H_ - - -#include "dl_base.h" -#include "dl_relation_manager.h" -#include "dl_table_relation.h" - -namespace datalog { - - class finite_product_relation; - - void universal_delete(finite_product_relation* ptr); - - - class finite_product_relation_plugin : public relation_plugin { - friend class finite_product_relation; - public: - struct rel_spec { - family_id m_inner_kind; //null_family_id means we don't care about the kind - svector m_table_cols; - - rel_spec() : m_inner_kind(null_family_id) {} - rel_spec(const svector& table_cols) - : m_inner_kind(null_family_id), m_table_cols(table_cols) {} - - bool operator==(const rel_spec & o) const { - return m_inner_kind==o.m_inner_kind && vectors_equal(m_table_cols, o.m_table_cols); - } - struct hash { - unsigned operator()(const rel_spec & o) const { - return o.m_inner_kind^svector_hash()(o.m_table_cols); - } - }; - }; - private: - - class join_fn; - class converting_join_fn; - class project_fn; - class rename_fn; - class union_fn; - class inner_singleton_union_fn; - class converting_union_fn; - class filter_identical_fn; - class filter_equal_fn; - class filter_interpreted_fn; - class negation_filter_fn; - class filter_identical_pairs_fn; - - relation_plugin & m_inner_plugin; - - rel_spec_store > m_spec_store; - - static symbol get_name(relation_plugin & inner_plugin); - family_id get_relation_kind(finite_product_relation & r, const bool * table_columns); - - static void get_all_possible_table_columns(relation_manager & rmgr, const relation_signature & s, - svector & table_columns); - void get_all_possible_table_columns(const relation_signature & s, svector & table_columns) { - get_all_possible_table_columns(get_manager(), s, table_columns); - } - - void split_signatures(const relation_signature & s, table_signature & table_sig, - relation_signature & remaining_sig); - void split_signatures(const relation_signature & s, const bool * table_columns, - table_signature & table_sig, relation_signature & remaining_sig); - public: - static finite_product_relation & get(relation_base & r); - static const finite_product_relation & get(const relation_base & r); - static finite_product_relation * get(relation_base * r); - static const finite_product_relation * get(const relation_base * r); - - static finite_product_relation_plugin & get_plugin(relation_manager & rmgr, relation_plugin & inner); - - finite_product_relation_plugin(relation_plugin & inner_plugin, relation_manager & manager); - - virtual void initialize(family_id fid); - - relation_plugin & get_inner_plugin() const { return m_inner_plugin; } - - virtual bool can_handle_signature(const relation_signature & s); - - virtual relation_base * mk_empty(const relation_signature & s); - /** - \c inner_kind==null_family_id means we don't care about the kind of the inner relation - */ - finite_product_relation * mk_empty(const relation_signature & s, const bool * table_columns, - family_id inner_kind=null_family_id); - finite_product_relation * mk_empty(const finite_product_relation & original); - virtual relation_base * mk_empty(const relation_base & original); - virtual relation_base * mk_empty(const relation_signature & s, family_id kind); - - virtual relation_base * mk_full(func_decl* p, const relation_signature & s); - - /** - \brief Return true if \c r can be converted to \c finite_product_relation_plugin either - by \c mk_from_table_relation or by \c mk_from_inner_relation. - */ - bool can_be_converted(const relation_base & r); - - /** - If the conversion cannot be performed, 0 is returned. - */ - finite_product_relation * mk_from_table_relation(const table_relation & r); - finite_product_relation * mk_from_inner_relation(const relation_base & r); - - bool can_convert_to_table_relation(const finite_product_relation & r); - table_relation * to_table_relation(const finite_product_relation & r); - - protected: - virtual relation_join_fn * mk_join_fn(const relation_base & t1, const relation_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2); - virtual relation_transformer_fn * mk_project_fn(const relation_base & t, unsigned col_cnt, - const unsigned * removed_cols); - virtual relation_transformer_fn * mk_rename_fn(const relation_base & t, unsigned permutation_cycle_len, - const unsigned * permutation_cycle); - virtual relation_union_fn * mk_union_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta); - virtual relation_mutator_fn * mk_filter_identical_fn(const relation_base & t, unsigned col_cnt, - const unsigned * identical_cols); - virtual relation_mutator_fn * mk_filter_equal_fn(const relation_base & t, const relation_element & value, - unsigned col); - virtual relation_mutator_fn * mk_filter_interpreted_fn(const relation_base & t, app * condition); - virtual relation_intersection_filter_fn * mk_filter_by_negation_fn(const relation_base & t, - const relation_base & negated_obj, unsigned joined_col_cnt, - const unsigned * t_cols, const unsigned * negated_cols); - - private: - /** - \brief Create a filter that enforces equality between pairs of table and relation columns - - The column numbers in arrays \c table_cols and \c rel_cols must be local to the table/inner relation. - */ - relation_mutator_fn * mk_filter_identical_pairs(const finite_product_relation & r, unsigned col_cnt, - const unsigned * table_cols, const unsigned * rel_cols); - - /** - \brief Create a join-project operation that creates a table according to \c relation_table - but with references to relations updated and removed according to the content of \c filtered_table. - \c selected_columns contains sorted indexes of data columns in \c relation_table that are also in - the \c filtered_table (so that the first column in \c filtered_table corresponds to - \c selected_columns[0] -th column in \c relation_table etc...) - - Signature of \c relation_table: - (data columns)(functional column with indexes of relation objects) - - Signature of \c filtered_table: - (selected data columns)(non-functional column with original relation object indexes) - (functional column with indexes of filtered relation objects) - - */ - static table_join_fn * mk_assembler_of_filter_result(const table_base & relation_table, - const table_base & filtered_table, const unsigned_vector & selected_columns); - - }; - - class finite_product_relation : public relation_base { - friend class finite_product_relation_plugin; - friend class finite_product_relation_plugin::join_fn; - friend class finite_product_relation_plugin::project_fn; - friend class finite_product_relation_plugin::union_fn; - friend class finite_product_relation_plugin::rename_fn; - friend class finite_product_relation_plugin::inner_singleton_union_fn; - friend class finite_product_relation_plugin::filter_equal_fn; - friend class finite_product_relation_plugin::filter_identical_pairs_fn; - - class live_rel_collection_reducer; - - - public: - /** - Size of this sort determines how many different relation objects can we refer to. - */ - static const table_sort s_rel_idx_sort; - - - /** - \brief The last column in the signature is a functional column with index of the - associated inner relation. The other columns correspond to the relation signature - according to \c m_table2sig. - - It holds that \c m_table_sig.size()-1==m_table2sig.size() - */ - - table_signature m_table_sig; - unsigned_vector m_table2sig; // (ordered list) - unsigned_vector m_sig2table; //index of corresponding table column or UINT_MAX - private: - relation_signature m_other_sig; - unsigned_vector m_other2sig; // (ordered list) - public: - unsigned_vector m_sig2other; //index of corresponding other relation column or UINT_MAX - private: - relation_plugin & m_other_plugin; - family_id m_other_kind; - - mutable table_base * m_table; - public: - mutable relation_vector m_others; - private: - mutable unsigned_vector m_available_rel_indexes; - - /** - \c UINT_MAX means uninitialized. - If we can get away with it, we want to have a single full relation to refer to. - */ - mutable unsigned m_full_rel_idx; - - mutable idx_set m_live_rel_collection_acc; - mutable scoped_ptr m_live_rel_collection_project; - - mutable scoped_ptr m_empty_rel_removal_filter; - - void recycle_rel_idx(unsigned idx) const; - - // creates a full relation if it does not exist. - unsigned get_full_rel_idx(); - - - - public: - relation_base & get_inner_rel(table_element idx) - { SASSERT(idx(idx)); } - relation_base & get_inner_rel(unsigned idx) { SASSERT(m_others[idx]); return *m_others[idx]; } - const relation_base & get_inner_rel(unsigned idx) const - { return const_cast(*this).get_inner_rel(idx); } - - unsigned get_next_rel_idx() const; - - /** - The relation takes ownership of the \c inner object. - */ - void set_inner_rel(table_element idx, relation_base * inner) - { SASSERT(idx(idx), inner); } - /** - The relation takes ownership of the \c inner object. - */ - void set_inner_rel(unsigned idx, relation_base * inner) { - SASSERT(!m_others[idx]); - SASSERT(inner); - m_others[idx] = inner; - } - table_base & get_table() { return *m_table; } - - table_plugin & get_table_plugin() const { return get_table().get_plugin(); } - - void garbage_collect(bool remove_empty) const; - - /** - \brief Initialize an empty relation with table \c table_vals and relations in \c others. - - The relation object takes ownership of relations inside the \c others vector. - - If \c contiguous is true, it can be assumed that there are no zero elements in the \c others array. - */ - void init(const table_base & table_vals, const relation_vector & others, bool contiguous); - - private: - - - /** - \brief Extract the values of table non-functional columns from the relation fact. - The value of the functional column which determines index of the inner relation is undefined. - */ - void extract_table_fact(const relation_fact rf, table_fact & tf) const; - /** - \brief Extract the values of the inner relation columns from the relation fact. - */ - void extract_other_fact(const relation_fact rf, relation_fact & of) const; - - relation_base * mk_empty_inner(); - relation_base * mk_full_inner(func_decl* pred); - - - void complement_self(func_decl* pred); - - void collect_live_relation_indexes(idx_set & res) const; - - - /** - \brief Try to modify relations in \c rels so that they have the same columns corresponding to the table - and the inner relation (so that the union can be perofrmed on theim in a straightforward way). - - Relations in \c rels must all have equal signature. - - Even if the function fails and false is returned, some relations may already be modified. They are - in a valid state, but with different specification. - */ - static bool try_unify_specifications(ptr_vector & rels); - - bool try_modify_specification(const bool * table_cols); - - virtual bool can_swap(const relation_base & r) const - { return &get_plugin()==&r.get_plugin(); } - - /** - \brief Swap content of the current relation with the content of \c r. - - Both relations must come from the same plugin and be of the same signature. - */ - virtual void swap(relation_base & r); - - /** - \brief Create a \c finite_product_relation object. - */ - finite_product_relation(finite_product_relation_plugin & p, const relation_signature & s, - const bool * table_columns, table_plugin & tplugin, relation_plugin & oplugin, family_id other_kind); - finite_product_relation(const finite_product_relation & r); - virtual ~finite_product_relation(); - public: - context & get_context() const; - finite_product_relation_plugin & get_plugin() const { - return static_cast(relation_base::get_plugin()); - } - - bool is_table_column(unsigned col_idx) const { return m_sig2table[col_idx]!=UINT_MAX; } - - const table_base & get_table() const { return *m_table; } - - const relation_base & get_inner_rel(table_element idx) const - { SASSERT(idx(idx)); } - - /** - The function calls garbage_collect, so the internal state may change when it is called. - */ - virtual bool empty() const; - void reset() { m_table->reset(); garbage_collect(false); } - - virtual void add_fact(const relation_fact & f); - virtual bool contains_fact(const relation_fact & f) const; - - virtual finite_product_relation * clone() const; - virtual finite_product_relation * complement(func_decl* p) const; - - virtual void display(std::ostream & out) const; - virtual void display_tuples(func_decl & pred, std::ostream & out) const; - - virtual unsigned get_size_estimate_rows() const { return m_table->get_size_estimate_rows(); } - virtual unsigned get_size_estimate_bytes() const { return m_table->get_size_estimate_bytes(); } - - virtual void to_formula(expr_ref& fml) const; - }; - -}; - -#endif /* _DL_FINITE_PRODUCT_RELATION_H_ */ - diff --git a/src/muz/dl_interval_relation.cpp b/src/muz/dl_interval_relation.cpp deleted file mode 100644 index adc8cb760..000000000 --- a/src/muz/dl_interval_relation.cpp +++ /dev/null @@ -1,652 +0,0 @@ -/*++ -Copyright (c) 2010 Microsoft Corporation - -Module Name: - - dl_interval_relation.cpp - -Abstract: - - Basic interval reatlion. - -Author: - - Nikolaj Bjorner (nbjorner) 2010-2-11 - -Revision History: - ---*/ - -#include "debug.h" -#include "optional.h" -#include "ast_pp.h" -#include "dl_interval_relation.h" -#include "bool_rewriter.h" - - -namespace datalog { - // ------------------------- - // interval_relation_plugin - - interval_relation_plugin::interval_relation_plugin(relation_manager& m): - relation_plugin(interval_relation_plugin::get_name(), m), - m_empty(m_dep), - m_arith(get_ast_manager()) { - } - - bool interval_relation_plugin::can_handle_signature(const relation_signature & sig) { - for (unsigned i = 0; i < sig.size(); ++i) { - if (!m_arith.is_int(sig[i]) && !m_arith.is_real(sig[i])) { - return false; - } - } - return true; - } - - - relation_base * interval_relation_plugin::mk_empty(const relation_signature & s) { - return alloc(interval_relation, *this, s, true); - } - - relation_base * interval_relation_plugin::mk_full(func_decl* p, const relation_signature & s) { - return alloc(interval_relation, *this, s, false); - } - - class interval_relation_plugin::join_fn : public convenient_relation_join_fn { - public: - join_fn(const relation_signature & o1_sig, const relation_signature & o2_sig, unsigned col_cnt, - const unsigned * cols1, const unsigned * cols2) - : convenient_relation_join_fn(o1_sig, o2_sig, col_cnt, cols1, cols2){ - } - - virtual relation_base * operator()(const relation_base & _r1, const relation_base & _r2) { - interval_relation const& r1 = get(_r1); - interval_relation const& r2 = get(_r2); - interval_relation_plugin& p = r1.get_plugin(); - interval_relation* result = dynamic_cast(p.mk_full(0, get_result_signature())); - result->mk_join(r1, r2, m_cols1.size(), m_cols1.c_ptr(), m_cols2.c_ptr()); - return result; - } - }; - - relation_join_fn * interval_relation_plugin::mk_join_fn(const relation_base & r1, const relation_base & r2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) { - if (!check_kind(r1) || !check_kind(r2)) { - return 0; - } - return alloc(join_fn, r1.get_signature(), r2.get_signature(), col_cnt, cols1, cols2); - } - - - class interval_relation_plugin::project_fn : public convenient_relation_project_fn { - public: - project_fn(const relation_signature & orig_sig, unsigned removed_col_cnt, const unsigned * removed_cols) - : convenient_relation_project_fn(orig_sig, removed_col_cnt, removed_cols) { - } - - virtual relation_base * operator()(const relation_base & _r) { - interval_relation const& r = get(_r); - interval_relation_plugin& p = r.get_plugin(); - interval_relation* result = dynamic_cast(p.mk_full(0, get_result_signature())); - result->mk_project(r, m_removed_cols.size(), m_removed_cols.c_ptr()); - return result; - } - }; - - relation_transformer_fn * interval_relation_plugin::mk_project_fn(const relation_base & r, - unsigned col_cnt, const unsigned * removed_cols) { - return alloc(project_fn, r.get_signature(), col_cnt, removed_cols); - } - - class interval_relation_plugin::rename_fn : public convenient_relation_rename_fn { - public: - rename_fn(const relation_signature & orig_sig, unsigned cycle_len, const unsigned * cycle) - : convenient_relation_rename_fn(orig_sig, cycle_len, cycle) { - } - - virtual relation_base * operator()(const relation_base & _r) { - interval_relation const& r = get(_r); - interval_relation_plugin& p = r.get_plugin(); - interval_relation* result = dynamic_cast(p.mk_full(0, get_result_signature())); - result->mk_rename(r, m_cycle.size(), m_cycle.c_ptr()); - return result; - } - }; - - relation_transformer_fn * interval_relation_plugin::mk_rename_fn(const relation_base & r, - unsigned cycle_len, const unsigned * permutation_cycle) { - if(!check_kind(r)) { - return 0; - } - return alloc(rename_fn, r.get_signature(), cycle_len, permutation_cycle); - } - - interval interval_relation_plugin::unite(interval const& src1, interval const& src2) { - bool l_open = src1.is_lower_open(); - bool r_open = src1.is_upper_open(); - ext_numeral low = src1.inf(); - ext_numeral high = src1.sup(); - if (src2.inf() < low || (src2.inf() == low && l_open)) { - low = src2.inf(); - l_open = src2.is_lower_open(); - } - if (src2.sup() > high || (src2.sup() == high && r_open)) { - high = src2.sup(); - r_open = src2.is_upper_open(); - } - return interval(dep(), low, l_open, 0, high, r_open, 0); - } - - interval interval_relation_plugin::widen(interval const& src1, interval const& src2) { - bool l_open = src1.is_lower_open(); - bool r_open = src1.is_upper_open(); - ext_numeral low = src1.inf(); - ext_numeral high = src1.sup(); - - if (src2.inf() < low || (low == src2.inf() && l_open && !src2.is_lower_open())) { - low = ext_numeral(false); - l_open = true; - } - if (high < src2.sup() || (src2.sup() == high && !r_open && src2.is_upper_open())) { - high = ext_numeral(true); - r_open = true; - } - return interval(dep(), low, l_open, 0, high, r_open, 0); - } - - interval interval_relation_plugin::meet(interval const& src1, interval const& src2, bool& isempty) { - isempty = false; - if (is_empty(0, src1) || is_infinite(src2)) { - return src1; - } - if (is_empty(0, src2) || is_infinite(src1)) { - return src2; - } - bool l_open = src1.is_lower_open(); - bool r_open = src1.is_upper_open(); - ext_numeral low = src1.inf(); - ext_numeral high = src1.sup(); - if (src2.inf() > low || (src2.inf() == low && !l_open)) { - low = src2.inf(); - l_open = src2.is_lower_open(); - } - if (src2.sup() < high || (src2.sup() == high && !r_open)) { - high = src2.sup(); - r_open = src2.is_upper_open(); - } - if (low > high || (low == high && (l_open || r_open))) { - isempty = true; - return interval(dep()); - } - else { - return interval(dep(), low, l_open, 0, high, r_open, 0); - } - } - - bool interval_relation_plugin::is_infinite(interval const& i) { - return i.plus_infinity() && i.minus_infinity(); - } - - bool interval_relation_plugin::is_empty(unsigned, interval const& i) { - return i.sup() < i.inf(); - } - - class interval_relation_plugin::union_fn : public relation_union_fn { - bool m_is_widen; - public: - union_fn(bool is_widen) : - m_is_widen(is_widen) { - } - - virtual void operator()(relation_base & _r, const relation_base & _src, relation_base * _delta) { - - TRACE("interval_relation", _r.display(tout << "dst:\n"); _src.display(tout << "src:\n");); - - interval_relation& r = get(_r); - interval_relation const& src = get(_src); - if (_delta) { - interval_relation& d = get(*_delta); - r.mk_union(src, &d, m_is_widen); - } - else { - r.mk_union(src, 0, m_is_widen); - } - } - }; - - relation_union_fn * interval_relation_plugin::mk_union_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta) { - if (!check_kind(tgt) || !check_kind(src) || (delta && !check_kind(*delta))) { - return 0; - } - return alloc(union_fn, false); - } - - relation_union_fn * interval_relation_plugin::mk_widen_fn( - const relation_base & tgt, const relation_base & src, - const relation_base * delta) { - if (!check_kind(tgt) || !check_kind(src) || (delta && !check_kind(*delta))) { - return 0; - } - return alloc(union_fn, true); - } - - class interval_relation_plugin::filter_identical_fn : public relation_mutator_fn { - unsigned_vector m_identical_cols; - public: - filter_identical_fn(unsigned col_cnt, const unsigned * identical_cols) - : m_identical_cols(col_cnt, identical_cols) {} - - virtual void operator()(relation_base & r) { - interval_relation & pr = get(r); - for (unsigned i = 1; i < m_identical_cols.size(); ++i) { - unsigned c1 = m_identical_cols[0]; - unsigned c2 = m_identical_cols[i]; - pr.equate(c1, c2); - } - } - }; - - relation_mutator_fn * interval_relation_plugin::mk_filter_identical_fn( - const relation_base & t, unsigned col_cnt, const unsigned * identical_cols) { - if(!check_kind(t)) { - return 0; - } - return alloc(filter_identical_fn, col_cnt, identical_cols); - } - - - class interval_relation_plugin::filter_equal_fn : public relation_mutator_fn { - unsigned m_col; - rational m_value; - public: - filter_equal_fn(relation_manager & m, const relation_element & value, unsigned col) - : m_col(col) { - arith_util arith(m.get_context().get_manager()); - VERIFY(arith.is_numeral(value, m_value)); - } - - virtual void operator()(relation_base & _r) { - interval_relation & r = get(_r); - interval_relation_plugin & p = r.get_plugin(); - r.mk_intersect(m_col, interval(p.dep(), m_value)); - TRACE("interval_relation", tout << m_value << "\n"; r.display(tout);); - } - }; - - relation_mutator_fn * interval_relation_plugin::mk_filter_equal_fn(const relation_base & r, - const relation_element & value, unsigned col) { - if(check_kind(r)) { - return alloc(filter_equal_fn, get_manager(), value, col); - } - return 0; - } - - - class interval_relation_plugin::filter_interpreted_fn : public relation_mutator_fn { - app_ref m_cond; - public: - filter_interpreted_fn(interval_relation const& t, app* cond): - m_cond(cond, t.get_plugin().get_ast_manager()) { - } - - void operator()(relation_base& t) { - get(t).filter_interpreted(m_cond); - TRACE("interval_relation", tout << mk_pp(m_cond, m_cond.get_manager()) << "\n"; t.display(tout);); - } - }; - - relation_mutator_fn * interval_relation_plugin::mk_filter_interpreted_fn(const relation_base & t, app * condition) { - if (check_kind(t)) { - return alloc(filter_interpreted_fn, get(t), condition); - } - return 0; - } - - interval_relation& interval_relation_plugin::get(relation_base& r) { - return dynamic_cast(r); - } - - interval_relation const & interval_relation_plugin::get(relation_base const& r) { - return dynamic_cast(r); - } - - // ----------------------- - // interval_relation - - interval_relation::interval_relation(interval_relation_plugin& p, relation_signature const& s, bool is_empty): - vector_relation(p, s, is_empty, interval(p.dep())) - { - TRACE("interval_relation", tout << s.size() << "\n";); - } - - void interval_relation::add_fact(const relation_fact & f) { - interval_relation r(get_plugin(), get_signature(), false); - ast_manager& m = get_plugin().get_ast_manager(); - for (unsigned i = 0; i < f.size(); ++i) { - app_ref eq(m); - expr* e = f[i]; - eq = m.mk_eq(m.mk_var(i, m.get_sort(e)), e); - r.filter_interpreted(eq.get()); - } - mk_union(r, 0, false); - } - - bool interval_relation::contains_fact(const relation_fact & f) const { - SASSERT(f.size() == get_signature().size()); - interval_relation_plugin& p = get_plugin(); - - for (unsigned i = 0; i < f.size(); ++i) { - if (f[i] != f[find(i)]) { - return false; - } - interval const& iv = (*this)[i]; - if (p.is_infinite(iv)) { - continue; - } - rational v; - if (p.m_arith.is_numeral(f[i], v)) { - if (!iv.contains(v)) { - return false; - } - } - else { - // TBD: may or must? - } - } - return true; - } - - interval_relation * interval_relation::clone() const { - interval_relation* result = alloc(interval_relation, get_plugin(), get_signature(), empty()); - result->copy(*this); - return result; - } - - interval_relation * interval_relation::complement(func_decl*) const { - UNREACHABLE(); - return 0; - } - - void interval_relation::to_formula(expr_ref& fml) const { - ast_manager& m = get_plugin().get_ast_manager(); - arith_util& arith = get_plugin().m_arith; - expr_ref_vector conjs(m); - relation_signature const& sig = get_signature(); - for (unsigned i = 0; i < sig.size(); ++i) { - if (i != find(i)) { - conjs.push_back(m.mk_eq(m.mk_var(i, sig[i]), - m.mk_var(find(i), sig[find(i)]))); - continue; - } - interval const& iv = (*this)[i]; - sort* ty = sig[i]; - expr_ref var(m.mk_var(i, ty), m); - if (!iv.minus_infinity()) { - expr* lo = arith.mk_numeral(iv.get_lower_value(), ty); - if (iv.is_lower_open()) { - conjs.push_back(arith.mk_lt(lo, var)); - } - else { - conjs.push_back(arith.mk_le(lo, var)); - } - } - if (!iv.plus_infinity()) { - expr* hi = arith.mk_numeral(iv.get_upper_value(), ty); - if (iv.is_upper_open()) { - conjs.push_back(arith.mk_lt(var, hi)); - } - else { - conjs.push_back(arith.mk_le(var, hi)); - } - } - } - bool_rewriter br(m); - br.mk_and(conjs.size(), conjs.c_ptr(), fml); - } - - - void interval_relation::display_index(unsigned i, interval const& j, std::ostream & out) const { - out << i << " in " << j << "\n"; - } - - interval_relation_plugin& interval_relation::get_plugin() const { - return static_cast(relation_base::get_plugin()); - } - - void interval_relation::mk_intersect(unsigned idx, interval const& i) { - bool isempty; - (*this)[idx] = mk_intersect((*this)[idx], i, isempty); - if (isempty || is_empty(idx, (*this)[idx])) { - set_empty(); - } - } - - void interval_relation::mk_rename_elem(interval& i, unsigned, unsigned const* ) { - - } - - void interval_relation::filter_interpreted(app* cond) { - interval_relation_plugin& p = get_plugin(); - rational k; - unsigned x, y; - if (p.is_lt(cond, x, k, y)) { - // 0 < x - y + k - if (x == UINT_MAX) { - // y < k - mk_intersect(y, interval(p.dep(), k, true, false, 0)); - return; - } - if (y == UINT_MAX) { - // -k < x - mk_intersect(x, interval(p.dep(), -k, true, true, 0)); - return; - } - // y < x + k - ext_numeral x_hi = (*this)[x].sup(); - ext_numeral y_lo = (*this)[y].inf(); - if (!x_hi.is_infinite()) { - mk_intersect(y, interval(p.dep(), k + x_hi.to_rational(), true, false, 0)); - } - if (!y_lo.is_infinite()) { - mk_intersect(x, interval(p.dep(), y_lo.to_rational() - k, true, true, 0)); - } - return; - } - bool is_int = false; - if (p.is_le(cond, x, k, y, is_int)) { - // 0 <= x - y + k - if (x == UINT_MAX) { - // y <= k - mk_intersect(y, interval(p.dep(), k, false, false, 0)); - return; - } - if (y == UINT_MAX) { - // -k <= x - mk_intersect(x, interval(p.dep(), -k, false, true, 0)); - return; - } - ext_numeral x_hi = (*this)[x].sup(); - ext_numeral y_lo = (*this)[y].inf(); - if (!x_hi.is_infinite()) { - mk_intersect(y, interval(p.dep(), k + x_hi.to_rational(), false, false, 0)); - } - if (!y_lo.is_infinite()) { - mk_intersect(x, interval(p.dep(), y_lo.to_rational() - k, false, true, 0)); - } - return; - } - if (p.is_eq(cond, x, k, y)) { - // y = x + k - if (x == UINT_MAX) { - SASSERT(y != UINT_MAX); - mk_intersect(y, interval(p.dep(), k)); - return; - } - if (y == UINT_MAX) { - // x = - k - SASSERT(x != UINT_MAX); - mk_intersect(x, interval(p.dep(), -k)); - return; - } - interval x_i = (*this)[x]; - interval y_i = (*this)[y]; - x_i += interval(p.dep(), k); - y_i -= interval(p.dep(), k); - mk_intersect(x, y_i); - mk_intersect(y, x_i); - } - if (get_plugin().get_ast_manager().is_false(cond)) { - set_empty(); - } - } - - bool interval_relation_plugin::is_linear(expr* e, unsigned& neg, unsigned& pos, rational& k, bool is_pos) const { -#define SET_VAR(_idx_) \ - if (is_pos &&pos == UINT_MAX) { \ - pos = _idx_; \ - return true; \ - } \ - if (!is_pos && neg == UINT_MAX) { \ - neg = _idx_; \ - return true; \ - } \ - else { \ - return false; \ - } - - if (is_var(e)) { - SET_VAR(to_var(e)->get_idx()); - } - if (!is_app(e)) { - return false; - } - app* a = to_app(e); - - if (m_arith.is_add(e)) { - for (unsigned i = 0; i < a->get_num_args(); ++i) { - if (!is_linear(a->get_arg(i), neg, pos, k, is_pos)) return false; - } - return true; - } - if (m_arith.is_sub(e)) { - SASSERT(a->get_num_args() == 2); - return - is_linear(a->get_arg(0), neg, pos, k, is_pos) && - is_linear(a->get_arg(1), neg, pos, k, !is_pos); - } - rational k1; - SASSERT(!m_arith.is_mul(e) || a->get_num_args() == 2); - if (m_arith.is_mul(e) && - m_arith.is_numeral(a->get_arg(0), k1) && - k1.is_minus_one() && - is_var(a->get_arg(1))) { - SET_VAR(to_var(a->get_arg(1))->get_idx()); - } - - if (m_arith.is_numeral(e, k1)) { - if (is_pos) { - k += k1; - } - else { - k -= k1; - } - return true; - } - return false; - } - - // 0 <= x - y + k - bool interval_relation_plugin::is_le(app* cond, unsigned& x, rational& k, unsigned& y, bool& is_int) const { - ast_manager& m = get_ast_manager(); - k.reset(); - x = UINT_MAX; - y = UINT_MAX; - - if (m_arith.is_le(cond)) { - is_int = m_arith.is_int(cond->get_arg(0)); - if (!is_linear(cond->get_arg(0), y, x, k, false)) return false; - if (!is_linear(cond->get_arg(1), y, x, k, true)) return false; - return (x != UINT_MAX || y != UINT_MAX); - } - if (m_arith.is_ge(cond)) { - is_int = m_arith.is_int(cond->get_arg(0)); - if (!is_linear(cond->get_arg(0), y, x, k, true)) return false; - if (!is_linear(cond->get_arg(1), y, x, k, false)) return false; - return (x != UINT_MAX || y != UINT_MAX); - } - if (m_arith.is_lt(cond) && m_arith.is_int(cond->get_arg(0))) { - is_int = true; - if (!is_linear(cond->get_arg(0), y, x, k, false)) return false; - if (!is_linear(cond->get_arg(1), y, x, k, true)) return false; - k -= rational::one(); - return (x != UINT_MAX || y != UINT_MAX); - } - if (m_arith.is_gt(cond) && m_arith.is_int(cond->get_arg(0))) { - is_int = true; - if (!is_linear(cond->get_arg(0), y, x, k, true)) return false; - if (!is_linear(cond->get_arg(1), y, x, k, false)) return false; - k += rational::one(); - return (x != UINT_MAX || y != UINT_MAX); - } - if (m.is_not(cond) && is_app(cond->get_arg(0))) { - // not (0 <= x - y + k) - // <=> - // 0 > x - y + k - // <=> - // 0 <= y - x - k - 1 - if (is_le(to_app(cond->get_arg(0)), x, k, y, is_int) && is_int) { - k.neg(); - k -= rational::one(); - std::swap(x, y); - return true; - } - // not (0 < x - y + k) - // <=> - // 0 >= x - y + k - // <=> - // 0 <= y - x - k - if (is_lt(to_app(cond->get_arg(0)), x, k, y)) { - is_int = false; - k.neg(); - std::swap(x, y); - return true; - } - } - return false; - } - - // 0 < x - y + k - bool interval_relation_plugin::is_lt(app* cond, unsigned& x, rational& k, unsigned& y) const { - k.reset(); - x = UINT_MAX; - y = UINT_MAX; - if (m_arith.is_lt(cond) && m_arith.is_real(cond->get_arg(0))) { - if (!is_linear(cond->get_arg(0), y, x, k, false)) return false; - if (!is_linear(cond->get_arg(1), y, x, k, true)) return false; - return (x != UINT_MAX || y != UINT_MAX); - } - if (m_arith.is_gt(cond) && m_arith.is_real(cond->get_arg(0))) { - if (!is_linear(cond->get_arg(0), y, x, k, true)) return false; - if (!is_linear(cond->get_arg(1), y, x, k, false)) return false; - return (x != UINT_MAX || y != UINT_MAX); - } - return false; - } - - // 0 = x - y + k - bool interval_relation_plugin::is_eq(app* cond, unsigned& x, rational& k, unsigned& y) const { - ast_manager& m = get_ast_manager(); - k.reset(); - x = UINT_MAX; - y = UINT_MAX; - if (m.is_eq(cond)) { - if (!is_linear(cond->get_arg(0), y, x, k, false)) return false; - if (!is_linear(cond->get_arg(1), y, x, k, true)) return false; - return (x != UINT_MAX || y != UINT_MAX); - } - return false; - } - -}; - diff --git a/src/muz/dl_interval_relation.h b/src/muz/dl_interval_relation.h deleted file mode 100644 index 685ef5c86..000000000 --- a/src/muz/dl_interval_relation.h +++ /dev/null @@ -1,140 +0,0 @@ -/*++ -Copyright (c) 2010 Microsoft Corporation - -Module Name: - - dl_interval_relation.h - -Abstract: - - Basic interval reatlion. - -Author: - - Nikolaj Bjorner (nbjorner) 2010-2-11 - -Revision History: - ---*/ -#ifndef _DL_INTERVAL_RELATION_H_ -#define _DL_INTERVAL_RELATION_H_ - - -#include "dl_context.h" -#include "old_interval.h" -#include "dl_vector_relation.h" -#include "arith_decl_plugin.h" -#include "basic_simplifier_plugin.h" - -namespace datalog { - - class interval_relation; - - class interval_relation_plugin : public relation_plugin { - v_dependency_manager m_dep; - interval m_empty; - arith_util m_arith; - - class join_fn; - class project_fn; - class rename_fn; - class union_fn; - class filter_equal_fn; - class filter_identical_fn; - class filter_interpreted_fn; - friend class interval_relation; - - interval unite(interval const& src1, interval const& src2); - interval widen(interval const& src1, interval const& src2); - interval meet(interval const& src1, interval const& src2, bool& is_empty); - - v_dependency_manager & dep() const { return const_cast(m_dep); } - - public: - interval_relation_plugin(relation_manager& m); - virtual bool can_handle_signature(const relation_signature & s); - static symbol get_name() { return symbol("interval_relation"); } - virtual relation_base * mk_empty(const relation_signature & s); - virtual relation_base * mk_full(func_decl* p, const relation_signature & s); - virtual relation_join_fn * mk_join_fn(const relation_base & t1, const relation_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2); - virtual relation_transformer_fn * mk_project_fn(const relation_base & t, unsigned col_cnt, - const unsigned * removed_cols); - virtual relation_transformer_fn * mk_rename_fn(const relation_base & t, unsigned permutation_cycle_len, - const unsigned * permutation_cycle); - virtual relation_union_fn * mk_union_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta); - virtual relation_union_fn * mk_widen_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta); - virtual relation_mutator_fn * mk_filter_identical_fn(const relation_base & t, unsigned col_cnt, - const unsigned * identical_cols); - virtual relation_mutator_fn * mk_filter_equal_fn(const relation_base & t, const relation_element & value, - unsigned col); - virtual relation_mutator_fn * mk_filter_interpreted_fn(const relation_base & t, app * condition); - - static bool is_empty(unsigned idx, interval const& i); - static bool is_infinite(interval const& i); - - private: - static interval_relation& get(relation_base& r); - static interval_relation const & get(relation_base const& r); - - bool is_linear(expr* e, unsigned& pos, unsigned& neg, rational& k, bool is_pos) const; - - // x + k <= y - bool is_le(app* cond, unsigned& x, rational& k, unsigned& y, bool& is_int) const; - // x + k < y - bool is_lt(app* cond, unsigned& x, rational& k, unsigned& y) const; - // x + k = y - bool is_eq(app* cond, unsigned& x, rational& k, unsigned& y) const; - }; - - - class interval_relation : public vector_relation { - friend class interval_relation_plugin; - friend class interval_relation_plugin::filter_equal_fn; - public: - interval_relation(interval_relation_plugin& p, relation_signature const& s, bool is_empty); - - virtual void add_fact(const relation_fact & f); - virtual bool contains_fact(const relation_fact & f) const; - virtual interval_relation * clone() const; - virtual interval_relation * complement(func_decl*) const; - virtual void to_formula(expr_ref& fml) const; - interval_relation_plugin& get_plugin() const; - - void filter_interpreted(app* cond); - virtual bool is_precise() const { return false; } - - private: - - virtual interval mk_intersect(interval const& t1, interval const& t2, bool& is_empty) const { - return get_plugin().meet(t1, t2, is_empty); - } - - virtual interval mk_unite(interval const& t1, interval const& t2) const { return get_plugin().unite(t1,t2); } - - virtual interval mk_widen(interval const& t1, interval const& t2) const { return get_plugin().widen(t1,t2); } - - virtual bool is_subset_of(interval const& t1, interval const& t2) const { NOT_IMPLEMENTED_YET(); return false; } - - virtual bool is_full(interval const& t) const { - return interval_relation_plugin::is_infinite(t); - } - - virtual bool is_empty(unsigned idx, interval const& t) const { - return interval_relation_plugin::is_empty(idx, t); - } - - virtual void mk_rename_elem(interval& i, unsigned col_cnt, unsigned const* cycle); - - virtual void display_index(unsigned idx, interval const & i, std::ostream& out) const; - - void mk_intersect(unsigned idx, interval const& i); - - }; - -}; - -#endif - diff --git a/src/muz/dl_mk_explanations.cpp b/src/muz/dl_mk_explanations.cpp deleted file mode 100644 index 253bbbec7..000000000 --- a/src/muz/dl_mk_explanations.cpp +++ /dev/null @@ -1,880 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - dl_mk_explanations.cpp - -Abstract: - - - -Author: - - Krystof Hoder (t-khoder) 2010-11-08. - -Revision History: - ---*/ - - -#include -#include"ast_pp.h" -#include "ast_smt_pp.h" -#include"dl_finite_product_relation.h" -#include"dl_product_relation.h" -#include"dl_sieve_relation.h" - -#include"dl_mk_explanations.h" - -namespace datalog { - - // ----------------------------------- - // - // explanation_relation_plugin declaration - // - // ----------------------------------- - - class explanation_relation; - - class explanation_relation_plugin : public relation_plugin { - friend class explanation_relation; - - class join_fn; - class project_fn; - class rename_fn; - class union_fn; - class foreign_union_fn; - class assignment_filter_fn; - class negation_filter_fn; - class intersection_filter_fn; - - bool m_relation_level_explanations; - - func_decl_ref m_union_decl; - - vector > m_pool; - - - app * mk_union(app * a1, app * a2) { - return get_ast_manager().mk_app(m_union_decl, a1, a2); - } - - public: - static symbol get_name(bool relation_level) { - return symbol(relation_level ? "relation_explanation" : "fact_explanation"); - } - - explanation_relation_plugin(bool relation_level, relation_manager & manager) - : relation_plugin(get_name(relation_level), manager), - m_relation_level_explanations(relation_level), - m_union_decl(mk_explanations::get_union_decl(get_context()), get_ast_manager()) {} - - ~explanation_relation_plugin() { - for (unsigned i = 0; i < m_pool.size(); ++i) { - for (unsigned j = 0; j < m_pool[i].size(); ++j) { - dealloc(m_pool[i][j]); - } - } - } - - virtual bool can_handle_signature(const relation_signature & s) { - unsigned n=s.size(); - for (unsigned i=0; i(relation_base::get_plugin()); - } - - virtual void to_formula(expr_ref& fml) const { - ast_manager& m = fml.get_manager(); - fml = m.mk_eq(m.mk_var(0, m.get_sort(m_data[0])), m_data[0]); - } - - bool is_undefined(unsigned col_idx) const { - return m_data[col_idx]==0; - } - bool no_undefined() const { - if (empty()) { - return true; - } - unsigned n = get_signature().size(); - for (unsigned i=0; i(get_plugin().mk_empty(get_signature())); - res->m_empty = m_empty; - SASSERT(res->m_data.empty()); - res->m_data.append(m_data); - return res; - } - - virtual relation_base * complement(func_decl* pred) const { - explanation_relation * res = static_cast(get_plugin().mk_empty(get_signature())); - if (empty()) { - res->set_undefined(); - } - return res; - } - - void display_explanation(app * expl, std::ostream & out) const { - if (expl) { - //TODO: some nice explanation output - ast_smt_pp pp(get_plugin().get_ast_manager()); - pp.display_expr_smt2(out, expl); - } - else { - out << ""; - } - } - - virtual void display(std::ostream & out) const { - if (empty()) { - out << "\n"; - return; - } - unsigned sz = get_signature().size(); - for (unsigned i=0; i s.size() && !m_pool[s.size()].empty()) { - explanation_relation* r = m_pool[s.size()].back(); - m_pool[s.size()].pop_back(); - r->m_empty = true; - r->m_data.reset(); - return r; - } - return alloc(explanation_relation, *this, s); - } - - void explanation_relation_plugin::recycle(explanation_relation* r) { - relation_signature const& sig = r->get_signature(); - if (m_pool.size() <= sig.size()) { - m_pool.resize(sig.size()+1); - } - m_pool[sig.size()].push_back(r); - } - - - class explanation_relation_plugin::join_fn : public convenient_relation_join_fn { - public: - join_fn(const relation_signature & sig1, const relation_signature & sig2) - : convenient_relation_join_fn(sig1, sig2, 0, 0, 0) {} - - virtual relation_base * operator()(const relation_base & r1_0, const relation_base & r2_0) { - const explanation_relation & r1 = static_cast(r1_0); - const explanation_relation & r2 = static_cast(r2_0); - explanation_relation_plugin & plugin = r1.get_plugin(); - - explanation_relation * res = static_cast(plugin.mk_empty(get_result_signature())); - if (!r1.empty() && !r2.empty()) { - res->m_empty = false; - SASSERT(res->m_data.empty()); - res->m_data.append(r1.m_data); - res->m_data.append(r2.m_data); - } - return res; - } - }; - - relation_join_fn * explanation_relation_plugin::mk_join_fn(const relation_base & r1, const relation_base & r2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) { - if (&r1.get_plugin()!=this || &r2.get_plugin()!=this) { - return 0; - } - if (col_cnt!=0) { - return 0; - } - return alloc(join_fn, r1.get_signature(), r2.get_signature()); - } - - - class explanation_relation_plugin::project_fn : public convenient_relation_project_fn { - public: - project_fn(const relation_signature & sig, unsigned col_cnt, const unsigned * removed_cols) - : convenient_relation_project_fn(sig, col_cnt, removed_cols) {} - - virtual relation_base * operator()(const relation_base & r0) { - const explanation_relation & r = static_cast(r0); - explanation_relation_plugin & plugin = r.get_plugin(); - - explanation_relation * res = static_cast(plugin.mk_empty(get_result_signature())); - if (!r.empty()) { - relation_fact proj_data = r.m_data; - project_out_vector_columns(proj_data, m_removed_cols); - res->assign_data(proj_data); - } - return res; - } - }; - - relation_transformer_fn * explanation_relation_plugin::mk_project_fn(const relation_base & r, unsigned col_cnt, - const unsigned * removed_cols) { - if (&r.get_plugin()!=this) { - return 0; - } - return alloc(project_fn, r.get_signature(), col_cnt, removed_cols); - } - - - class explanation_relation_plugin::rename_fn : public convenient_relation_rename_fn { - public: - rename_fn(const relation_signature & sig, unsigned permutation_cycle_len, const unsigned * permutation_cycle) - : convenient_relation_rename_fn(sig, permutation_cycle_len, permutation_cycle) {} - - virtual relation_base * operator()(const relation_base & r0) { - const explanation_relation & r = static_cast(r0); - explanation_relation_plugin & plugin = r.get_plugin(); - - explanation_relation * res = static_cast(plugin.mk_empty(get_result_signature())); - if (!r.empty()) { - relation_fact permutated_data = r.m_data; - permutate_by_cycle(permutated_data, m_cycle); - res->assign_data(permutated_data); - } - return res; - } - }; - - relation_transformer_fn * explanation_relation_plugin::mk_rename_fn(const relation_base & r, - unsigned permutation_cycle_len, const unsigned * permutation_cycle) { - return alloc(rename_fn, r.get_signature(), permutation_cycle_len, permutation_cycle); - } - - - class explanation_relation_plugin::union_fn : public relation_union_fn { - scoped_ptr m_delta_union_fun; - public: - virtual void operator()(relation_base & tgt0, const relation_base & src0, relation_base * delta0) { - explanation_relation & tgt = static_cast(tgt0); - const explanation_relation & src = static_cast(src0); - explanation_relation * delta = delta0 ? static_cast(delta0) : 0; - explanation_relation_plugin & plugin = tgt.get_plugin(); - - if (!src.no_undefined() || !tgt.no_undefined() || (delta && !delta->no_undefined())) { - UNREACHABLE(); - } - if (src.empty()) { - return; - } - if (plugin.m_relation_level_explanations) { - tgt.unite_with_data(src.m_data); - if (delta) { - if (!m_delta_union_fun) { - m_delta_union_fun = plugin.get_manager().mk_union_fn(*delta, src); - SASSERT(m_delta_union_fun); - } - (*m_delta_union_fun)(*delta, src); - } - } - else { - if (tgt.empty()) { - tgt.assign_data(src.m_data); - if (delta && delta->empty()) { - delta->assign_data(src.m_data); - } - } - } - } - }; - - class explanation_relation_plugin::foreign_union_fn : public relation_union_fn { - scoped_ptr m_delta_union_fun; - public: - virtual void operator()(relation_base & tgt0, const relation_base & src, relation_base * delta0) { - explanation_relation & tgt = static_cast(tgt0); - explanation_relation * delta = delta0 ? static_cast(delta0) : 0; - - if (src.empty()) { - return; - } - tgt.set_undefined(); - if (delta) { - delta->set_undefined(); - } - } - }; - - relation_union_fn * explanation_relation_plugin::mk_union_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta) { - if (!check_kind(tgt) || (delta && !check_kind(*delta))) { - return 0; - } - if (!check_kind(src)) { - //this is to handle the product relation - return alloc(foreign_union_fn); - } - return alloc(union_fn); - } - - class explanation_relation_plugin::assignment_filter_fn : public relation_mutator_fn { - ast_manager & m_manager; - var_subst & m_subst; - unsigned m_col_idx; - app_ref m_new_rule; - public: - assignment_filter_fn(context & ctx, unsigned col_idx, app_ref new_rule) - : m_manager(ctx.get_manager()), - m_subst(ctx.get_var_subst()), - m_col_idx(col_idx), - m_new_rule(new_rule) {} - - virtual void operator()(relation_base & r0) { - explanation_relation & r = static_cast(r0); - - if (!r.is_undefined(m_col_idx)) { - UNREACHABLE(); - } - - unsigned sz = r.get_signature().size(); - ptr_vector subst_arg; - subst_arg.resize(sz, 0); - unsigned ofs = sz-1; - for (unsigned i=0; iget_arg(0); - expr * arg2 = cond->get_arg(1); - - if (is_var(arg2)) { - std::swap(arg1, arg2); - } - - if (!is_var(arg1) || !is_app(arg2)) { - return 0; - } - var * col_var = to_var(arg1); - app * new_rule = to_app(arg2); - if (!get_context().get_decl_util().is_rule_sort(col_var->get_sort())) { - return 0; - } - unsigned col_idx = col_var->get_idx(); - - return alloc(assignment_filter_fn, get_context(), col_idx, app_ref(new_rule, get_ast_manager())); - } - - - class explanation_relation_plugin::negation_filter_fn : public relation_intersection_filter_fn { - public: - virtual void operator()(relation_base & r, const relation_base & neg) { - if (!neg.empty()) { - r.reset(); - } - } - }; - - relation_intersection_filter_fn * explanation_relation_plugin::mk_filter_by_negation_fn(const relation_base & r, - const relation_base & neg, unsigned joined_col_cnt, const unsigned * t_cols, - const unsigned * negated_cols) { - if (&r.get_plugin()!=this || &neg.get_plugin()!=this) { - return 0; - } - return alloc(negation_filter_fn); - } - - class explanation_relation_plugin::intersection_filter_fn : public relation_intersection_filter_fn { - func_decl_ref m_union_decl; - public: - intersection_filter_fn(explanation_relation_plugin & plugin) - : m_union_decl(plugin.m_union_decl) {} - - virtual void operator()(relation_base & tgt0, const relation_base & src0) { - explanation_relation & tgt = static_cast(tgt0); - const explanation_relation & src = static_cast(src0); - - if (src.empty()) { - tgt.reset(); - return; - } - if (tgt.empty()) { - return; - } - unsigned sz = tgt.get_signature().size(); - for (unsigned i=0; iget_decl()==m_union_decl.get()) { - if (curr_tgt->get_arg(0)==curr_src || curr_tgt->get_arg(1)==curr_src) { - tgt.m_data.set(i, curr_src); - continue; - } - } - //the intersection is imprecise because we do nothing here, but it is good enough for - //the purpose of explanations - } - } - }; - - relation_intersection_filter_fn * explanation_relation_plugin::mk_filter_by_intersection_fn( - const relation_base & tgt, const relation_base & src, unsigned joined_col_cnt, - const unsigned * tgt_cols, const unsigned * src_cols) { - if (&tgt.get_plugin()!=this || &src.get_plugin()!=this) { - return 0; - } - //this checks the join is one to one on all columns - if (tgt.get_signature()!=src.get_signature() - || joined_col_cnt!=tgt.get_signature().size() - || !containers_equal(tgt_cols, tgt_cols+joined_col_cnt, src_cols, src_cols+joined_col_cnt)) { - return 0; - } - counter ctr; - ctr.count(joined_col_cnt, tgt_cols); - if (ctr.get_max_counter_value()>1 || (joined_col_cnt && ctr.get_max_positive()!=joined_col_cnt-1)) { - return 0; - } - return alloc(intersection_filter_fn, *this); - } - - - // ----------------------------------- - // - // mk_explanations - // - // ----------------------------------- - - - mk_explanations::mk_explanations(context & ctx) - : plugin(50000), - m_manager(ctx.get_manager()), - m_context(ctx), - m_decl_util(ctx.get_decl_util()), - m_relation_level(ctx.explanations_on_relation_level()), - m_pinned(m_manager) { - m_e_sort = m_decl_util.mk_rule_sort(); - m_pinned.push_back(m_e_sort); - - relation_manager & rmgr = ctx.get_rel_context()->get_rmanager(); - symbol er_symbol = explanation_relation_plugin::get_name(m_relation_level); - m_er_plugin = static_cast(rmgr.get_relation_plugin(er_symbol)); - if (!m_er_plugin) { - m_er_plugin = alloc(explanation_relation_plugin, m_relation_level, rmgr); - rmgr.register_plugin(m_er_plugin); - if (!m_relation_level) { - DEBUG_CODE( - finite_product_relation_plugin * dummy; - SASSERT(!rmgr.try_get_finite_product_relation_plugin(*m_er_plugin, dummy)); - ); - rmgr.register_plugin(alloc(finite_product_relation_plugin, *m_er_plugin, rmgr)); - } - } - DEBUG_CODE( - if (!m_relation_level) { - finite_product_relation_plugin * dummy; - SASSERT(rmgr.try_get_finite_product_relation_plugin(*m_er_plugin, dummy)); - } - ); - } - - func_decl * mk_explanations::get_union_decl(context & ctx) { - ast_manager & m = ctx.get_manager(); - sort_ref s(ctx.get_decl_util().mk_rule_sort(), m); - //can it happen that the function name would collide with some other symbol? - //if functions can be overloaded by their ranges, it should be fine. - return m.mk_func_decl(symbol("e_union"), s, s, s); - } - - void mk_explanations::assign_rel_level_kind(func_decl * e_decl, func_decl * orig) { - SASSERT(m_relation_level); - - relation_manager & rmgr = m_context.get_rel_context()->get_rmanager(); - unsigned sz = e_decl->get_arity(); - relation_signature sig; - rmgr.from_predicate(e_decl, sig); - - svector inner_sieve(sz-1, true); - inner_sieve.push_back(false); - - svector expl_sieve(sz-1, false); - expl_sieve.push_back(true); - - sieve_relation_plugin & sieve_plugin = sieve_relation_plugin::get_plugin(rmgr); - - family_id inner_kind = rmgr.get_requested_predicate_kind(orig); //may be null_family_id - family_id inner_sieve_kind = sieve_plugin.get_relation_kind(sig, inner_sieve, inner_kind); - family_id expl_kind = m_er_plugin->get_kind(); - family_id expl_sieve_kind = sieve_plugin.get_relation_kind(sig, expl_sieve, expl_kind); - - product_relation_plugin::rel_spec product_spec; - product_spec.push_back(inner_sieve_kind); - product_spec.push_back(expl_sieve_kind); - - family_id pred_kind = - product_relation_plugin::get_plugin(rmgr).get_relation_kind(sig, product_spec); - - rmgr.set_predicate_kind(e_decl, pred_kind); - } - - func_decl * mk_explanations::get_e_decl(func_decl * orig_decl) { - decl_map::obj_map_entry * e = m_e_decl_map.insert_if_not_there2(orig_decl, 0); - if (e->get_data().m_value==0) { - relation_signature e_domain; - e_domain.append(orig_decl->get_arity(), orig_decl->get_domain()); - e_domain.push_back(m_e_sort); - func_decl * new_decl = m_context.mk_fresh_head_predicate(orig_decl->get_name(), symbol("expl"), - e_domain.size(), e_domain.c_ptr(), orig_decl); - m_pinned.push_back(new_decl); - e->get_data().m_value = new_decl; - - if (m_relation_level) { - assign_rel_level_kind(new_decl, orig_decl); - } - } - return e->get_data().m_value; - } - - app * mk_explanations::get_e_lit(app * lit, unsigned e_var_idx) { - expr_ref_vector args(m_manager); - func_decl * e_decl = get_e_decl(lit->get_decl()); - args.append(lit->get_num_args(), lit->get_args()); - args.push_back(m_manager.mk_var(e_var_idx, m_e_sort)); - return m_manager.mk_app(e_decl, args.c_ptr()); - } - - symbol mk_explanations::get_rule_symbol(rule * r) { - if (r->name() == symbol::null) { - std::stringstream sstm; - r->display(m_context, sstm); - std::string res = sstm.str(); - res = res.substr(0, res.find_last_not_of('\n')+1); - return symbol(res.c_str()); - } - else { - return r->name(); - } - } - - rule * mk_explanations::get_e_rule(rule * r) { - rule_counter ctr; - ctr.count_rule_vars(m_manager, r); - unsigned max_var; - unsigned next_var = ctr.get_max_positive(max_var) ? (max_var+1) : 0; - unsigned head_var = next_var++; - app_ref e_head(get_e_lit(r->get_head(), head_var), m_manager); - - app_ref_vector e_tail(m_manager); - svector neg_flags; - unsigned pos_tail_sz = r->get_positive_tail_size(); - for (unsigned i=0; iget_tail(i), e_var)); - neg_flags.push_back(false); - } - unsigned tail_sz = r->get_tail_size(); - for (unsigned i=pos_tail_sz; iget_tail(i)); - neg_flags.push_back(r->is_neg_tail(i)); - } - - symbol rule_repr = get_rule_symbol(r); - - expr_ref_vector rule_expr_args(m_manager); - for (unsigned tail_idx=0; tail_idxget_arg(tail->get_num_args()-1)); - } - else { - //this adds argument values and the explanation term - //(values will be substituted for variables at runtime by the finite_product_relation) - rule_expr_args.append(tail->get_num_args(), tail->get_args()); - } - } - //rule_expr contains rule function with string representation of the rule as symbol and - //for each positive uninterpreted tail it contains its argument values and its explanation term - expr * rule_expr = m_decl_util.mk_rule(rule_repr, rule_expr_args.size(), rule_expr_args.c_ptr()); - - app_ref e_record(m_manager.mk_eq(m_manager.mk_var(head_var, m_e_sort), rule_expr), m_manager); - e_tail.push_back(e_record); - neg_flags.push_back(false); - SASSERT(e_tail.size()==neg_flags.size()); - - return m_context.get_rule_manager().mk(e_head, e_tail.size(), e_tail.c_ptr(), neg_flags.c_ptr()); - } - - void mk_explanations::transform_rules(const rule_set & src, rule_set & dst) { - rule_set::iterator rit = src.begin(); - rule_set::iterator rend = src.end(); - for (; rit!=rend; ++rit) { - rule * e_rule = get_e_rule(*rit); - dst.add_rule(e_rule); - } - - //add rules that will (for output predicates) copy facts from explained relations back to - //the original ones - expr_ref_vector lit_args(m_manager); - decl_set::iterator pit = src.get_output_predicates().begin(); - decl_set::iterator pend = src.get_output_predicates().end(); - for (; pit != pend; ++pit) { - func_decl * orig_decl = *pit; - - lit_args.reset(); - unsigned arity = orig_decl->get_arity(); - for (unsigned i=0; iget_domain(i))); - } - app_ref orig_lit(m_manager.mk_app(orig_decl, lit_args.c_ptr()), m_manager); - app_ref e_lit(get_e_lit(orig_lit, arity), m_manager); - app * tail[] = { e_lit.get() }; - dst.add_rule(m_context.get_rule_manager().mk(orig_lit, 1, tail, 0)); - } - } - - void mk_explanations::translate_rel_level_relation(relation_manager & rmgr, relation_base & orig, - relation_base & e_rel) { - SASSERT(m_e_fact_relation); - SASSERT(e_rel.get_plugin().is_product_relation()); - - product_relation & prod_rel = static_cast(e_rel); - SASSERT(prod_rel.size()==2); - SASSERT(prod_rel[0].get_plugin().is_sieve_relation()); - SASSERT(prod_rel[1].get_plugin().is_sieve_relation()); - sieve_relation * srels[] = { - static_cast(&prod_rel[0]), - static_cast(&prod_rel[1]) }; - if (&srels[0]->get_inner().get_plugin()==m_er_plugin) { - std::swap(srels[0], srels[1]); - } - SASSERT(&srels[0]->get_inner().get_plugin()==&orig.get_plugin()); - SASSERT(&srels[1]->get_inner().get_plugin()==m_er_plugin); - - relation_base & new_orig = srels[0]->get_inner(); - explanation_relation & expl_rel = static_cast(srels[1]->get_inner()); - - { - scoped_ptr orig_union_fun = rmgr.mk_union_fn(new_orig, orig); - SASSERT(orig_union_fun); - (*orig_union_fun)(new_orig, orig); - } - - { - scoped_ptr expl_union_fun = rmgr.mk_union_fn(expl_rel, *m_e_fact_relation); - SASSERT(expl_union_fun); - (*expl_union_fun)(expl_rel, *m_e_fact_relation); - } - } - - void mk_explanations::transform_facts(relation_manager & rmgr, rule_set const& src, rule_set& dst) { - - if (!m_e_fact_relation) { - relation_signature expl_singleton_sig; - expl_singleton_sig.push_back(m_e_sort); - - relation_base * expl_singleton = rmgr.mk_empty_relation(expl_singleton_sig, m_er_plugin->get_kind()); - relation_fact es_fact(m_manager); - es_fact.push_back(m_decl_util.mk_fact(symbol("fact"))); - expl_singleton->add_fact(es_fact); - - SASSERT(&expl_singleton->get_plugin()==m_er_plugin); - m_e_fact_relation = static_cast(expl_singleton); - } - func_decl_set const& predicates = m_context.get_predicates(); - decl_set::iterator it = predicates.begin(); - decl_set::iterator end = predicates.end(); - for (; it!=end; ++it) { - func_decl * orig_decl = *it; - func_decl * e_decl = get_e_decl(orig_decl); - - if (!rmgr.try_get_relation(orig_decl) && - !src.contains(orig_decl)) { - // there are no facts or rules for this predicate - continue; - } - - dst.inherit_predicate(src, orig_decl, e_decl); - - relation_base & orig_rel = rmgr.get_relation(orig_decl); - relation_base & e_rel = rmgr.get_relation(e_decl); - SASSERT(e_rel.empty()); //the e_rel should be a new relation - - if (m_relation_level) { - translate_rel_level_relation(rmgr, orig_rel, e_rel); - } - else { - scoped_ptr product_fun = rmgr.mk_join_fn(orig_rel, *m_e_fact_relation, 0, 0, 0); - SASSERT(product_fun); - scoped_rel aux_extended_rel = (*product_fun)(orig_rel, *m_e_fact_relation); - scoped_ptr union_fun = rmgr.mk_union_fn(e_rel, *aux_extended_rel); - SASSERT(union_fun); - (*union_fun)(e_rel, *aux_extended_rel); - } - } - } - - rule_set * mk_explanations::operator()(rule_set const & source) { - - if (source.empty()) { - return 0; - } - if (!m_context.generate_explanations()) { - return 0; - } - rule_set * res = alloc(rule_set, m_context); - transform_facts(m_context.get_rel_context()->get_rmanager(), source, *res); - transform_rules(source, *res); - return res; - } - -}; - diff --git a/src/muz/dl_mk_explanations.h b/src/muz/dl_mk_explanations.h deleted file mode 100644 index 9e4d705c3..000000000 --- a/src/muz/dl_mk_explanations.h +++ /dev/null @@ -1,86 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - dl_mk_explanations.h - -Abstract: - - - -Author: - - Krystof Hoder (t-khoder) 2010-11-08. - -Revision History: - ---*/ - -#ifndef _DL_MK_EXPLANATIONS_H_ -#define _DL_MK_EXPLANATIONS_H_ - -#include "dl_context.h" -#include "dl_rule_transformer.h" - -namespace datalog { - - class explanation_relation; - class explanation_relation_plugin; - - class mk_explanations : public rule_transformer::plugin { - - typedef obj_map decl_map; - - ast_manager & m_manager; - context & m_context; - dl_decl_util & m_decl_util; - bool m_relation_level; - ast_ref_vector m_pinned; - explanation_relation_plugin * m_er_plugin; - sort * m_e_sort; - scoped_rel m_e_fact_relation; - - decl_map m_e_decl_map; - - symbol get_rule_symbol(rule * r); - - app * get_e_lit(app * lit, unsigned e_var_idx); - rule * get_e_rule(rule * r); - - /** - If \c m_relation_level is true, ensure \c e_decl predicate will be represented by - the right relation object. \c orig is the predicate corresponding to \c e_decl without - the explanation column. - */ - void assign_rel_level_kind(func_decl * e_decl, func_decl * orig); - void translate_rel_level_relation(relation_manager & rmgr, relation_base & orig, relation_base & e_rel); - - void transform_rules(const rule_set & src, rule_set & dst); - - void transform_facts(relation_manager & rmgr, rule_set const& src, rule_set& dst); - public: - /** - If relation_level is true, the explanation will not be stored for each fact, - but we will rather store history of the whole relation. - */ - mk_explanations(context & ctx); - - /** - \brief Return explanation predicate that corresponds to \c orig_decl. - */ - func_decl * get_e_decl(func_decl * orig_decl); - - static func_decl * get_union_decl(context & ctx); - func_decl * get_union_decl() const { - return get_union_decl(m_context); - } - - rule_set * operator()(rule_set const & source); - - static expr* get_explanation(relation_base const& r); - }; -}; - -#endif /* _DL_MK_EXPLANATIONS_H_ */ - diff --git a/src/muz/dl_mk_karr_invariants.cpp b/src/muz/dl_mk_karr_invariants.cpp deleted file mode 100644 index 11bc850bb..000000000 --- a/src/muz/dl_mk_karr_invariants.cpp +++ /dev/null @@ -1,1114 +0,0 @@ -/*++ -Copyright (c) 2013 Microsoft Corporation - -Module Name: - - dl_mk_karr_invariants.cpp - -Abstract: - - Extract integer linear invariants. - - The linear invariants are extracted according to Karr's method. - A short description is in - Nikolaj Bjorner, Anca Browne and Zohar Manna. Automatic Generation - of Invariants and Intermediate Assertions, in CP 95. - - The algorithm is here adapted to Horn clauses. - The idea is to maintain two data-structures for each recursive relation. - We call them R and RD - - R - set of linear congruences that are true of R. - - RD - the dual basis of of solutions for R. - - RD is updated by accumulating basis vectors for solutions - to R (the homogeneous dual of R) - R is updated from the inhomogeneous dual of RD. - -Author: - - Nikolaj Bjorner (nbjorner) 2013-03-09 - -Revision History: - ---*/ - -#include"dl_mk_karr_invariants.h" -#include"expr_safe_replace.h" -#include"bool_rewriter.h" -#include"dl_mk_backwards.h" -#include"dl_mk_loop_counter.h" -#include "for_each_expr.h" - -namespace datalog { - - - mk_karr_invariants::mk_karr_invariants(context & ctx, unsigned priority): - rule_transformer::plugin(priority, false), - m_ctx(ctx), - m(ctx.get_manager()), - rm(ctx.get_rule_manager()), - m_inner_ctx(m, ctx.get_fparams()), - a(m), - m_pinned(m), - m_cancel(false) { - params_ref params; - params.set_sym("default_relation", symbol("karr_relation")); - params.set_sym("engine", symbol("datalog")); - params.set_bool("karr", false); - m_inner_ctx.updt_params(params); - } - - mk_karr_invariants::~mk_karr_invariants() { } - - matrix& matrix::operator=(matrix const& other) { - reset(); - append(other); - return *this; - } - - void matrix::display_row( - std::ostream& out, vector const& row, rational const& b, bool is_eq) { - for (unsigned j = 0; j < row.size(); ++j) { - out << row[j] << " "; - } - out << (is_eq?" = ":" >= ") << -b << "\n"; - } - - void matrix::display_ineq( - std::ostream& out, vector const& row, rational const& b, bool is_eq) { - bool first = true; - for (unsigned j = 0; j < row.size(); ++j) { - if (!row[j].is_zero()) { - if (!first && row[j].is_pos()) { - out << "+ "; - } - if (row[j].is_minus_one()) { - out << "- "; - } - if (row[j] > rational(1) || row[j] < rational(-1)) { - out << row[j] << "*"; - } - out << "x" << j << " "; - first = false; - } - } - out << (is_eq?"= ":">= ") << -b << "\n"; - } - - void matrix::display(std::ostream& out) const { - for (unsigned i = 0; i < A.size(); ++i) { - display_row(out, A[i], b[i], eq[i]); - } - } - - - class mk_karr_invariants::add_invariant_model_converter : public model_converter { - ast_manager& m; - arith_util a; - func_decl_ref_vector m_funcs; - expr_ref_vector m_invs; - public: - - add_invariant_model_converter(ast_manager& m): m(m), a(m), m_funcs(m), m_invs(m) {} - - virtual ~add_invariant_model_converter() { } - - void add(func_decl* p, expr* inv) { - if (!m.is_true(inv)) { - m_funcs.push_back(p); - m_invs.push_back(inv); - } - } - - virtual void operator()(model_ref & mr) { - for (unsigned i = 0; i < m_funcs.size(); ++i) { - func_decl* p = m_funcs[i].get(); - func_interp* f = mr->get_func_interp(p); - expr_ref body(m); - unsigned arity = p->get_arity(); - SASSERT(0 < arity); - if (f) { - SASSERT(f->num_entries() == 0); - if (!f->is_partial()) { - bool_rewriter(m).mk_and(f->get_else(), m_invs[i].get(), body); - } - } - else { - f = alloc(func_interp, m, arity); - mr->register_decl(p, f); - body = m.mk_false(); // fragile: assume that relation was pruned by being infeasible. - } - f->set_else(body); - } - } - - virtual model_converter * translate(ast_translation & translator) { - add_invariant_model_converter* mc = alloc(add_invariant_model_converter, m); - for (unsigned i = 0; i < m_funcs.size(); ++i) { - mc->add(translator(m_funcs[i].get()), m_invs[i].get()); - } - return mc; - } - - private: - void mk_body(matrix const& M, expr_ref& body) { - expr_ref_vector conj(m); - for (unsigned i = 0; i < M.size(); ++i) { - mk_body(M.A[i], M.b[i], M.eq[i], conj); - } - bool_rewriter(m).mk_and(conj.size(), conj.c_ptr(), body); - } - - void mk_body(vector const& row, rational const& b, bool is_eq, expr_ref_vector& conj) { - expr_ref_vector sum(m); - expr_ref zero(m), lhs(m); - zero = a.mk_numeral(rational(0), true); - - for (unsigned i = 0; i < row.size(); ++i) { - if (row[i].is_zero()) { - continue; - } - var* var = m.mk_var(i, a.mk_int()); - if (row[i].is_one()) { - sum.push_back(var); - } - else { - sum.push_back(a.mk_mul(a.mk_numeral(row[i], true), var)); - } - } - if (!b.is_zero()) { - sum.push_back(a.mk_numeral(b, true)); - } - lhs = a.mk_add(sum.size(), sum.c_ptr()); - if (is_eq) { - conj.push_back(m.mk_eq(lhs, zero)); - } - else { - conj.push_back(a.mk_ge(lhs, zero)); - } - } - }; - - void mk_karr_invariants::cancel() { - m_cancel = true; - m_inner_ctx.cancel(); - } - - rule_set * mk_karr_invariants::operator()(rule_set const & source) { - if (!m_ctx.get_params().karr()) { - return 0; - } - rule_set::iterator it = source.begin(), end = source.end(); - for (; it != end; ++it) { - rule const& r = **it; - if (r.has_negation()) { - return 0; - } - } - mk_loop_counter lc(m_ctx); - mk_backwards bwd(m_ctx); - - scoped_ptr src_loop = lc(source); - TRACE("dl", src_loop->display(tout << "source loop\n");); - - get_invariants(*src_loop); - - if (m_cancel) { - return 0; - } - - // figure out whether to update same rules as used for saturation. - scoped_ptr rev_source = bwd(*src_loop); - get_invariants(*rev_source); - scoped_ptr src_annot = update_rules(*src_loop); - rule_set* rules = lc.revert(*src_annot); - rules->inherit_predicates(source); - TRACE("dl", rules->display(tout);); - m_pinned.reset(); - m_fun2inv.reset(); - return rules; - } - - void mk_karr_invariants::get_invariants(rule_set const& src) { - m_inner_ctx.reset(); - rel_context& rctx = *m_inner_ctx.get_rel_context(); - ptr_vector heads; - func_decl_set const& predicates = m_ctx.get_predicates(); - for (func_decl_set::iterator fit = predicates.begin(); fit != predicates.end(); ++fit) { - m_inner_ctx.register_predicate(*fit, false); - } - m_inner_ctx.ensure_opened(); - m_inner_ctx.replace_rules(src); - m_inner_ctx.close(); - rule_set::decl2rules::iterator dit = src.begin_grouped_rules(); - rule_set::decl2rules::iterator dend = src.end_grouped_rules(); - for (; dit != dend; ++dit) { - heads.push_back(dit->m_key); - } - m_inner_ctx.rel_query(heads.size(), heads.c_ptr()); - - // retrieve invariants. - dit = src.begin_grouped_rules(); - for (; dit != dend; ++dit) { - func_decl* p = dit->m_key; - relation_base* rb = rctx.try_get_relation(p); - if (rb) { - expr_ref fml(m); - rb->to_formula(fml); - if (m.is_true(fml)) { - continue; - } - expr* inv = 0; - if (m_fun2inv.find(p, inv)) { - fml = m.mk_and(inv, fml); - } - m_pinned.push_back(fml); - m_fun2inv.insert(p, fml); - } - } - } - - rule_set* mk_karr_invariants::update_rules(rule_set const& src) { - scoped_ptr dst = alloc(rule_set, m_ctx); - rule_set::iterator it = src.begin(), end = src.end(); - for (; it != end; ++it) { - update_body(*dst, **it); - } - if (m_ctx.get_model_converter()) { - add_invariant_model_converter* kmc = alloc(add_invariant_model_converter, m); - rule_set::decl2rules::iterator git = src.begin_grouped_rules(); - rule_set::decl2rules::iterator gend = src.end_grouped_rules(); - for (; git != gend; ++git) { - func_decl* p = git->m_key; - expr* fml = 0; - if (m_fun2inv.find(p, fml)) { - kmc->add(p, fml); - } - } - m_ctx.add_model_converter(kmc); - } - - dst->inherit_predicates(src); - return dst.detach(); - } - - void mk_karr_invariants::update_body(rule_set& rules, rule& r) { - unsigned utsz = r.get_uninterpreted_tail_size(); - unsigned tsz = r.get_tail_size(); - app_ref_vector tail(m); - expr_ref fml(m); - for (unsigned i = 0; i < tsz; ++i) { - tail.push_back(r.get_tail(i)); - } - for (unsigned i = 0; i < utsz; ++i) { - func_decl* q = r.get_decl(i); - expr* fml = 0; - if (m_fun2inv.find(q, fml)) { - expr_safe_replace rep(m); - for (unsigned j = 0; j < q->get_arity(); ++j) { - rep.insert(m.mk_var(j, q->get_domain(j)), - r.get_tail(i)->get_arg(j)); - } - expr_ref tmp(fml, m); - rep(tmp); - tail.push_back(to_app(tmp)); - } - } - rule* new_rule = &r; - if (tail.size() != tsz) { - new_rule = rm.mk(r.get_head(), tail.size(), tail.c_ptr(), 0, r.name()); - } - rules.add_rule(new_rule); - rm.mk_rule_rewrite_proof(r, *new_rule); // should be weakening rule. - } - - - - class karr_relation : public relation_base { - friend class karr_relation_plugin; - friend class karr_relation_plugin::filter_equal_fn; - - karr_relation_plugin& m_plugin; - ast_manager& m; - mutable arith_util a; - func_decl_ref m_fn; - mutable bool m_empty; - mutable matrix m_ineqs; - mutable bool m_ineqs_valid; - mutable matrix m_basis; - mutable bool m_basis_valid; - - public: - karr_relation(karr_relation_plugin& p, func_decl* f, relation_signature const& s, bool is_empty): - relation_base(p, s), - m_plugin(p), - m(p.get_ast_manager()), - a(m), - m_fn(f, m), - m_empty(is_empty), - m_ineqs_valid(!is_empty), - m_basis_valid(false) - { - } - - virtual bool empty() const { - return m_empty; - } - - virtual bool is_precise() const { return false; } - - virtual void add_fact(const relation_fact & f) { - SASSERT(m_empty); - SASSERT(!m_basis_valid); - m_empty = false; - m_ineqs_valid = true; - for (unsigned i = 0; i < f.size(); ++i) { - rational n; - if (a.is_numeral(f[i], n) && n.is_int()) { - vector row; - row.resize(f.size()); - row[i] = rational(1); - m_ineqs.A.push_back(row); - m_ineqs.b.push_back(-n); - m_ineqs.eq.push_back(true); - } - } - } - - virtual bool contains_fact(const relation_fact & f) const { - UNREACHABLE(); - return false; - } - - virtual void display(std::ostream & out) const { - if (m_fn) { - out << m_fn->get_name() << "\n"; - } - if (empty()) { - out << "empty\n"; - } - else { - if (m_ineqs_valid) { - m_ineqs.display(out << "ineqs:\n"); - } - if (m_basis_valid) { - m_basis.display(out << "basis:\n"); - } - } - } - - virtual karr_relation * clone() const { - karr_relation* result = alloc(karr_relation, m_plugin, m_fn, get_signature(), m_empty); - result->copy(*this); - return result; - } - - virtual karr_relation * complement(func_decl*) const { - UNREACHABLE(); - return 0; - } - - virtual void to_formula(expr_ref& fml) const { - if (empty()) { - fml = m.mk_false(); - } - else { - matrix const& M = get_ineqs(); - expr_ref_vector conj(m); - for (unsigned i = 0; i < M.size(); ++i) { - to_formula(M.A[i], M.b[i], M.eq[i], conj); - } - bool_rewriter(m).mk_and(conj.size(), conj.c_ptr(), fml); - } - } - - karr_relation_plugin& get_plugin() const { return m_plugin; } - - void filter_interpreted(app* cond) { - rational one(1), mone(-1); - expr* e1, *e2, *en; - var* v, *w; - rational n1, n2; - expr_ref_vector conjs(m); - qe::flatten_and(cond, conjs); - matrix& M = get_ineqs(); - unsigned num_columns = get_signature().size(); - - for (unsigned i = 0; i < conjs.size(); ++i) { - expr* e = conjs[i].get(); - rational b(0); - vector row; - row.resize(num_columns, rational(0)); - bool processed = true; - if (m.is_eq(e, e1, e2) && is_linear(e1, row, b, one) && is_linear(e2, row, b, mone)) { - M.A.push_back(row); - M.b.push_back(b); - M.eq.push_back(true); - } - else if ((a.is_le(e, e1, e2) || a.is_ge(e, e2, e1)) && - is_linear(e1, row, b, mone) && is_linear(e2, row, b, one)) { - M.A.push_back(row); - M.b.push_back(b); - M.eq.push_back(false); - } - else if ((a.is_lt(e, e1, e2) || a.is_gt(e, e2, e1)) && - is_linear(e1, row, b, mone) && is_linear(e2, row, b, one)) { - M.A.push_back(row); - M.b.push_back(b - rational(1)); - M.eq.push_back(false); - } - else if (m.is_not(e, en) && (a.is_lt(en, e2, e1) || a.is_gt(en, e1, e2)) && - is_linear(e1, row, b, mone) && is_linear(e2, row, b, one)) { - M.A.push_back(row); - M.b.push_back(b); - M.eq.push_back(false); - } - else if (m.is_not(e, en) && (a.is_le(en, e2, e1) || a.is_ge(en, e1, e2)) && - is_linear(e1, row, b, mone) && is_linear(e2, row, b, one)) { - M.A.push_back(row); - M.b.push_back(b - rational(1)); - M.eq.push_back(false); - } - else if (m.is_or(e, e1, e2) && is_eq(e1, v, n1) && is_eq(e2, w, n2) && v == w) { - if (n1 > n2) { - std::swap(n1, n2); - } - SASSERT(n1 <= n2); - row[v->get_idx()] = rational(1); - // v - n1 >= 0 - M.A.push_back(row); - M.b.push_back(-n1); - M.eq.push_back(false); - // -v + n2 >= 0 - row[v->get_idx()] = rational(-1); - M.A.push_back(row); - M.b.push_back(n2); - M.eq.push_back(false); - } - else { - processed = false; - } - TRACE("dl", tout << (processed?"+ ":"- ") << mk_pp(e, m) << "\n"; - if (processed) matrix::display_ineq(tout, row, M.b.back(), M.eq.back()); - ); - } - TRACE("dl", display(tout);); - } - - void mk_join(karr_relation const& r1, karr_relation const& r2, - unsigned col_cnt, unsigned const* cols1, unsigned const* cols2) { - if (r1.empty() || r2.empty()) { - m_empty = true; - return; - } - matrix const& M1 = r1.get_ineqs(); - matrix const& M2 = r2.get_ineqs(); - unsigned sig1_size = r1.get_signature().size(); - unsigned sig_size = get_signature().size(); - m_ineqs.reset(); - for (unsigned i = 0; i < M1.size(); ++i) { - vector row; - row.append(M1.A[i]); - row.resize(sig_size); - m_ineqs.A.push_back(row); - m_ineqs.b.push_back(M1.b[i]); - m_ineqs.eq.push_back(M1.eq[i]); - } - for (unsigned i = 0; i < M2.size(); ++i) { - vector row; - row.resize(sig_size); - for (unsigned j = 0; j < M2.A[i].size(); ++j) { - row[sig1_size + j] = M2.A[i][j]; - } - m_ineqs.A.push_back(row); - m_ineqs.b.push_back(M2.b[i]); - m_ineqs.eq.push_back(M2.eq[i]); - } - for (unsigned i = 0; i < col_cnt; ++i) { - vector row; - row.resize(sig_size); - row[cols1[i]] = rational(1); - row[sig1_size + cols2[i]] = rational(-1); - m_ineqs.A.push_back(row); - m_ineqs.b.push_back(rational(0)); - m_ineqs.eq.push_back(true); - } - m_ineqs_valid = true; - m_basis_valid = false; - m_empty = false; - if (r1.m_fn) { - m_fn = r1.m_fn; - } - if (r2.m_fn) { - m_fn = r2.m_fn; - } - } - - void mk_project(karr_relation const& r, unsigned cnt, unsigned const* cols) { - if (r.m_empty) { - m_empty = true; - return; - } - matrix const& M = r.get_basis(); - m_basis.reset(); - for (unsigned i = 0; i < M.size(); ++i) { - vector row; - unsigned k = 0; - for (unsigned j = 0; j < M.A[i].size(); ++j) { - if (k < cnt && j == cols[k]) { - ++k; - } - else { - row.push_back(M.A[i][j]); - } - } - SASSERT(row.size() + cnt == M.A[i].size()); - SASSERT(M.eq[i]); - m_basis.A.push_back(row); - m_basis.b.push_back(M.b[i]); - m_basis.eq.push_back(true); - } - m_basis_valid = true; - m_ineqs_valid = false; - m_empty = false; - m_fn = r.m_fn; - - TRACE("dl", - for (unsigned i = 0; i < cnt; ++i) { - tout << cols[i] << " "; - } - tout << "\n"; - r.display(tout); - display(tout);); - } - - void mk_rename(const karr_relation & r, unsigned col_cnt, const unsigned * cols) { - if (r.empty()) { - m_empty = true; - return; - } - m_ineqs.reset(); - m_basis.reset(); - m_ineqs_valid = r.m_ineqs_valid; - m_basis_valid = r.m_basis_valid; - if (m_ineqs_valid) { - m_ineqs.append(r.m_ineqs); - mk_rename(m_ineqs, col_cnt, cols); - } - if (m_basis_valid) { - m_basis.append(r.m_basis); - mk_rename(m_basis, col_cnt, cols); - } - m_fn = r.m_fn; - TRACE("dl", r.display(tout); display(tout);); - } - - void mk_union(karr_relation const& src, karr_relation* delta) { - if (src.empty()) { - if (delta) { - delta->m_empty = true; - } - return; - } - matrix const& M = src.get_basis(); - if (empty()) { - m_basis = M; - m_basis_valid = true; - m_empty = false; - m_ineqs_valid = false; - if (delta) { - delta->copy(*this); - } - return; - } - matrix& N = get_basis(); - unsigned N_size = N.size(); - for (unsigned i = 0; i < M.size(); ++i) { - bool found = false; - for (unsigned j = 0; !found && j < N_size; ++j) { - found = - same_row(M.A[i], N.A[j]) && - M.b[i] == N.b[j] && - M.eq[i] == N.eq[j]; - } - if (!found) { - N.A.push_back(M.A[i]); - N.b.push_back(M.b[i]); - N.eq.push_back(M.eq[i]); - } - } - m_ineqs_valid = false; - if (N_size != N.size()) { - if (delta) { - delta->copy(*this); - } - } - } - - matrix const& get_basis() const { - init_basis(); - return m_basis; - } - - matrix& get_basis() { - init_basis(); - return m_basis; - } - - matrix const& get_ineqs() const { - init_ineqs(); - return m_ineqs; - } - - matrix & get_ineqs() { - init_ineqs(); - return m_ineqs; - } - - private: - - void copy(karr_relation const& other) { - m_ineqs = other.m_ineqs; - m_basis = other.m_basis; - m_basis_valid = other.m_basis_valid; - m_ineqs_valid = other.m_ineqs_valid; - m_empty = other.m_empty; - } - - bool same_row(vector const& r1, vector const& r2) const { - SASSERT(r1.size() == r2.size()); - for (unsigned i = 0; i < r1.size(); ++i) { - if (r1[i] != r2[i]) { - return false; - } - } - return true; - } - - void mk_rename(matrix& M, unsigned col_cnt, unsigned const* cols) { - for (unsigned j = 0; j < M.size(); ++j) { - vector & row = M.A[j]; - rational tmp = row[cols[0]]; - for (unsigned i = 0; i + 1 < col_cnt; ++i) { - row[cols[i]] = row[cols[i+1]]; - } - row[cols[col_cnt-1]] = tmp; - } - } - - bool is_eq(expr* e, var*& v, rational& n) { - expr* e1, *e2; - if (!m.is_eq(e, e1, e2)) { - return false; - } - if (!is_var(e1)) { - std::swap(e1, e2); - } - if (!is_var(e1)) { - return false; - } - v = to_var(e1); - if (!a.is_numeral(e2, n)) { - return false; - } - return true; - } - - bool is_linear(expr* e, vector& row, rational& b, rational const& mul) { - if (!a.is_int(e)) { - return false; - } - if (is_var(e)) { - row[to_var(e)->get_idx()] += mul; - return true; - } - if (!is_app(e)) { - return false; - } - rational n; - if (a.is_numeral(e, n)) { - b += mul*n; - return true; - } - if (a.is_add(e)) { - for (unsigned i = 0; i < to_app(e)->get_num_args(); ++i) { - if (!is_linear(to_app(e)->get_arg(i), row, b, mul)) { - return false; - } - } - return true; - } - expr* e1, *e2; - if (a.is_sub(e, e1, e2)) { - return is_linear(e1, row, b, mul) && is_linear(e2, row, b, -mul); - } - if (a.is_mul(e, e1, e2) && a.is_numeral(e1, n)) { - return is_linear(e2, row, b, mul*n); - } - if (a.is_mul(e, e1, e2) && a.is_numeral(e2, n)) { - return is_linear(e1, row, b, mul*n); - } - if (a.is_uminus(e, e1)) { - return is_linear(e1, row, b, -mul); - } - return false; - } - - void init_ineqs() const { - if (!m_ineqs_valid) { - SASSERT(m_basis_valid); - m_plugin.dualizeH(m_ineqs, m_basis); - m_ineqs_valid = true; - } - } - - void init_basis() const { - if (!m_basis_valid) { - SASSERT(m_ineqs_valid); - if (m_plugin.dualizeI(m_basis, m_ineqs)) { - m_basis_valid = true; - } - else { - m_empty = true; - } - } - } - - void to_formula(vector const& row, rational const& b, bool is_eq, expr_ref_vector& conj) const { - expr_ref_vector sum(m); - expr_ref zero(m), lhs(m); - zero = a.mk_numeral(rational(0), true); - - for (unsigned i = 0; i < row.size(); ++i) { - if (row[i].is_zero()) { - continue; - } - var* var = m.mk_var(i, a.mk_int()); - if (row[i].is_one()) { - sum.push_back(var); - } - else { - sum.push_back(a.mk_mul(a.mk_numeral(row[i], true), var)); - } - } - if (!b.is_zero()) { - sum.push_back(a.mk_numeral(b, true)); - } - lhs = a.mk_add(sum.size(), sum.c_ptr()); - if (is_eq) { - conj.push_back(m.mk_eq(lhs, zero)); - } - else { - conj.push_back(a.mk_ge(lhs, zero)); - } - } - }; - - - karr_relation& karr_relation_plugin::get(relation_base& r) { - return dynamic_cast(r); - } - - karr_relation const & karr_relation_plugin::get(relation_base const& r) { - return dynamic_cast(r); - } - - void karr_relation_plugin::set_cancel(bool f) { - m_hb.set_cancel(f); - } - - relation_base * karr_relation_plugin::mk_empty(const relation_signature & s) { - return alloc(karr_relation, *this, 0, s, true); - } - - relation_base * karr_relation_plugin::mk_full(func_decl* p, const relation_signature & s) { - return alloc(karr_relation, *this, p, s, false); - } - - class karr_relation_plugin::join_fn : public convenient_relation_join_fn { - public: - join_fn(const relation_signature & o1_sig, const relation_signature & o2_sig, unsigned col_cnt, - const unsigned * cols1, const unsigned * cols2) - : convenient_relation_join_fn(o1_sig, o2_sig, col_cnt, cols1, cols2){ - } - - virtual relation_base * operator()(const relation_base & _r1, const relation_base & _r2) { - karr_relation const& r1 = get(_r1); - karr_relation const& r2 = get(_r2); - karr_relation_plugin& p = r1.get_plugin(); - karr_relation* result = dynamic_cast(p.mk_full(0, get_result_signature())); - result->mk_join(r1, r2, m_cols1.size(), m_cols1.c_ptr(), m_cols2.c_ptr()); - return result; - } - }; - - relation_join_fn * karr_relation_plugin::mk_join_fn( - const relation_base & t1, const relation_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) { - if (!check_kind(t1) || !check_kind(t2)) { - return 0; - } - return alloc(join_fn, t1.get_signature(), t2.get_signature(), col_cnt, cols1, cols2); - } - - - class karr_relation_plugin::project_fn : public convenient_relation_project_fn { - public: - project_fn(const relation_signature & orig_sig, unsigned removed_col_cnt, const unsigned * removed_cols) - : convenient_relation_project_fn(orig_sig, removed_col_cnt, removed_cols) { - } - - virtual relation_base * operator()(const relation_base & _r) { - karr_relation const& r = get(_r); - karr_relation_plugin& p = r.get_plugin(); - karr_relation* result = dynamic_cast(p.mk_full(0, get_result_signature())); - result->mk_project(r, m_removed_cols.size(), m_removed_cols.c_ptr()); - return result; - } - }; - - relation_transformer_fn * karr_relation_plugin::mk_project_fn(const relation_base & r, - unsigned col_cnt, const unsigned * removed_cols) { - return alloc(project_fn, r.get_signature(), col_cnt, removed_cols); - } - - class karr_relation_plugin::rename_fn : public convenient_relation_rename_fn { - public: - rename_fn(karr_relation_plugin& p, const relation_signature & orig_sig, unsigned cycle_len, const unsigned * cycle) - : convenient_relation_rename_fn(orig_sig, cycle_len, cycle) {} - - virtual relation_base * operator()(const relation_base & _r) { - karr_relation const& r = get(_r); - karr_relation_plugin& p = r.get_plugin(); - karr_relation* result = dynamic_cast(p.mk_full(0, get_result_signature())); - result->mk_rename(r, m_cycle.size(), m_cycle.c_ptr()); - return result; - } - }; - - relation_transformer_fn * karr_relation_plugin::mk_rename_fn(const relation_base & r, - unsigned cycle_len, const unsigned * permutation_cycle) { - if (!check_kind(r)) { - return 0; - } - return alloc(rename_fn, *this, r.get_signature(), cycle_len, permutation_cycle); - } - - bool karr_relation_plugin::dualizeI(matrix& dst, matrix const& src) { - dst.reset(); - m_hb.reset(); - for (unsigned i = 0; i < src.size(); ++i) { - if (src.eq[i]) { - m_hb.add_eq(src.A[i], -src.b[i]); - } - else { - m_hb.add_ge(src.A[i], -src.b[i]); - } - } - for (unsigned i = 0; !src.A.empty() && i < src.A[0].size(); ++i) { - m_hb.set_is_int(i); - } - lbool is_sat = l_undef; - - try { - is_sat = m_hb.saturate(); - } - catch (...) { - is_sat = l_undef; - } - TRACE("dl_verbose", m_hb.display(tout);); - if (is_sat == l_false) { - return false; - } - if (is_sat == l_undef) { - return true; - } - unsigned basis_size = m_hb.get_basis_size(); - bool first_initial = true; - for (unsigned i = 0; i < basis_size; ++i) { - bool is_initial; - vector soln; - m_hb.get_basis_solution(i, soln, is_initial); - if (is_initial && first_initial) { - dst.A.push_back(soln); - dst.b.push_back(rational(1)); - dst.eq.push_back(true); - first_initial = false; - } - else if (!is_initial) { - dst.A.push_back(soln); - dst.b.push_back(rational(0)); - dst.eq.push_back(true); - } - } - return true; - } - - void karr_relation_plugin::dualizeH(matrix& dst, matrix const& src) { - dst.reset(); - if (src.size() == 0) { - return; - } - m_hb.reset(); - for (unsigned i = 0; i < src.size(); ++i) { - vector v(src.A[i]); - v.push_back(src.b[i]); - if (src.eq[i]) { - m_hb.add_eq(v, rational(0)); - } - else { - m_hb.add_ge(v, rational(0)); - } - } - for (unsigned i = 0; i < 1 + src.A[0].size(); ++i) { - m_hb.set_is_int(i); - } - lbool is_sat = l_undef; - try { - is_sat = m_hb.saturate(); - } - catch (...) { - is_sat = l_undef; - } - if (is_sat != l_true) { - return; - } - TRACE("dl_verbose", m_hb.display(tout);); - SASSERT(is_sat == l_true); - unsigned basis_size = m_hb.get_basis_size(); - for (unsigned i = 0; i < basis_size; ++i) { - bool is_initial; - vector soln; - m_hb.get_basis_solution(i, soln, is_initial); - if (!is_initial) { - dst.b.push_back(soln.back()); - dst.eq.push_back(true); - soln.pop_back(); - dst.A.push_back(soln); - } - } - } - - - class karr_relation_plugin::union_fn : public relation_union_fn { - public: - union_fn() {} - - virtual void operator()(relation_base & _r, const relation_base & _src, relation_base * _delta) { - - karr_relation& r = get(_r); - karr_relation const& src = get(_src); - TRACE("dl", r.display(tout << "dst:\n"); src.display(tout << "src:\n");); - - if (_delta) { - karr_relation& d = get(*_delta); - r.mk_union(src, &d); - } - else { - r.mk_union(src, 0); - } - TRACE("dl", r.display(tout << "result:\n");); - } - }; - - relation_union_fn * karr_relation_plugin::mk_union_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta) { - if (!check_kind(tgt) || !check_kind(src) || (delta && !check_kind(*delta))) { - return 0; - } - return alloc(union_fn); - } - - class karr_relation_plugin::filter_identical_fn : public relation_mutator_fn { - unsigned_vector m_identical_cols; - public: - filter_identical_fn(unsigned col_cnt, const unsigned * identical_cols) - : m_identical_cols(col_cnt, identical_cols) {} - - virtual void operator()(relation_base & _r) { - karr_relation & r = get(_r); - TRACE("dl", r.display(tout << "src:\n");); - r.get_ineqs(); - for (unsigned i = 1; i < m_identical_cols.size(); ++i) { - unsigned c1 = m_identical_cols[0]; - unsigned c2 = m_identical_cols[i]; - vector row; - row.resize(r.get_signature().size()); - row[c1] = rational(1); - row[c2] = rational(-1); - r.m_ineqs.A.push_back(row); - r.m_ineqs.b.push_back(rational(0)); - r.m_ineqs.eq.push_back(true); - r.m_basis_valid = false; - } - TRACE("dl", r.display(tout << "result:\n");); - } - }; - - relation_mutator_fn * karr_relation_plugin::mk_filter_identical_fn( - const relation_base & t, unsigned col_cnt, const unsigned * identical_cols) { - if(!check_kind(t)) { - return 0; - } - return alloc(filter_identical_fn, col_cnt, identical_cols); - } - - - class karr_relation_plugin::filter_equal_fn : public relation_mutator_fn { - unsigned m_col; - rational m_value; - bool m_valid; - public: - filter_equal_fn(relation_manager & m, const relation_element & value, unsigned col) - : m_col(col) { - arith_util arith(m.get_context().get_manager()); - m_valid = arith.is_numeral(value, m_value) && m_value.is_int(); - } - - virtual void operator()(relation_base & _r) { - karr_relation & r = get(_r); - if (m_valid) { - r.get_ineqs(); - vector row; - row.resize(r.get_signature().size()); - row[m_col] = rational(1); - r.m_ineqs.A.push_back(row); - r.m_ineqs.b.push_back(rational(-1)); - r.m_ineqs.eq.push_back(true); - r.m_basis_valid = false; - } - TRACE("dl", tout << m_value << "\n"; r.display(tout);); - } - }; - - relation_mutator_fn * karr_relation_plugin::mk_filter_equal_fn(const relation_base & r, - const relation_element & value, unsigned col) { - if (check_kind(r)) { - return alloc(filter_equal_fn, get_manager(), value, col); - } - return 0; - } - - - class karr_relation_plugin::filter_interpreted_fn : public relation_mutator_fn { - app_ref m_cond; - public: - filter_interpreted_fn(karr_relation const& t, app* cond): - m_cond(cond, t.get_plugin().get_ast_manager()) { - } - - void operator()(relation_base& t) { - get(t).filter_interpreted(m_cond); - TRACE("dl", tout << mk_pp(m_cond, m_cond.get_manager()) << "\n"; t.display(tout);); - } - }; - - relation_mutator_fn * karr_relation_plugin::mk_filter_interpreted_fn(const relation_base & t, app * condition) { - if (check_kind(t)) { - return alloc(filter_interpreted_fn, get(t), condition); - } - return 0; - } - -}; - diff --git a/src/muz/dl_mk_karr_invariants.h b/src/muz/dl_mk_karr_invariants.h deleted file mode 100644 index a86f726ef..000000000 --- a/src/muz/dl_mk_karr_invariants.h +++ /dev/null @@ -1,138 +0,0 @@ -/*++ -Copyright (c) 2013 Microsoft Corporation - -Module Name: - - dl_mk_karr_invariants.h - -Abstract: - - Extract integer linear invariants. - -Author: - - Nikolaj Bjorner (nbjorner) 2013-03-08 - -Revision History: - ---*/ -#ifndef _DL_MK_KARR_INVARIANTS_H_ -#define _DL_MK_KARR_INVARIANTS_H_ - -#include"dl_context.h" -#include"dl_rule_set.h" -#include"dl_rule_transformer.h" -#include"arith_decl_plugin.h" -#include"hilbert_basis.h" - -namespace datalog { - - /** - \brief Rule transformer that strengthens bodies with invariants. - */ - - struct matrix { - vector > A; - vector b; - svector eq; - unsigned size() const { return A.size(); } - void reset() { A.reset(); b.reset(); eq.reset(); } - matrix& operator=(matrix const& other); - void append(matrix const& other) { A.append(other.A); b.append(other.b); eq.append(other.eq); } - void display(std::ostream& out) const; - static void display_row( - std::ostream& out, vector const& row, rational const& b, bool is_eq); - static void display_ineq( - std::ostream& out, vector const& row, rational const& b, bool is_eq); - }; - - class mk_karr_invariants : public rule_transformer::plugin { - - class add_invariant_model_converter; - - context& m_ctx; - ast_manager& m; - rule_manager& rm; - context m_inner_ctx; - arith_util a; - obj_map m_fun2inv; - ast_ref_vector m_pinned; - volatile bool m_cancel; - - void get_invariants(rule_set const& src); - - void update_body(rule_set& result, rule& r); - rule_set* update_rules(rule_set const& src); - public: - mk_karr_invariants(context & ctx, unsigned priority); - - virtual ~mk_karr_invariants(); - - virtual void cancel(); - - rule_set * operator()(rule_set const & source); - - }; - - class karr_relation; - - class karr_relation_plugin : public relation_plugin { - arith_util a; - hilbert_basis m_hb; - - class join_fn; - class project_fn; - class rename_fn; - class union_fn; - class filter_equal_fn; - class filter_identical_fn; - class filter_interpreted_fn; - friend class karr_relation; - public: - karr_relation_plugin(relation_manager& rm): - relation_plugin(karr_relation_plugin::get_name(), rm), - a(get_ast_manager()) - {} - - virtual bool can_handle_signature(const relation_signature & sig) { - return true; - } - - static symbol get_name() { return symbol("karr_relation"); } - - virtual void set_cancel(bool f); - - virtual relation_base * mk_empty(const relation_signature & s); - - virtual relation_base * mk_full(func_decl* p, const relation_signature & s); - - static karr_relation& get(relation_base& r); - static karr_relation const & get(relation_base const& r); - - virtual relation_join_fn * mk_join_fn( - const relation_base & t1, const relation_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2); - virtual relation_transformer_fn * mk_project_fn(const relation_base & t, unsigned col_cnt, - const unsigned * removed_cols); - virtual relation_transformer_fn * mk_rename_fn(const relation_base & t, unsigned permutation_cycle_len, - const unsigned * permutation_cycle); - virtual relation_union_fn * mk_union_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta); - virtual relation_mutator_fn * mk_filter_identical_fn(const relation_base & t, unsigned col_cnt, - const unsigned * identical_cols); - virtual relation_mutator_fn * mk_filter_equal_fn(const relation_base & t, const relation_element & value, - unsigned col); - virtual relation_mutator_fn * mk_filter_interpreted_fn(const relation_base & t, app * condition); - - private: - bool dualizeI(matrix& dst, matrix const& src); - void dualizeH(matrix& dst, matrix const& src); - - - }; - - -}; - -#endif /* _DL_MK_KARR_INVARIANTS_H_ */ - diff --git a/src/muz/dl_mk_partial_equiv.cpp b/src/muz/dl_mk_partial_equiv.cpp deleted file mode 100644 index 4d1a1e860..000000000 --- a/src/muz/dl_mk_partial_equiv.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/*++ -Copyright (c) 2012 Microsoft Corporation - -Module Name: - - dl_mk_partial_equiv.cpp - -Abstract: - - Rule transformer which identifies predicates that are partial equivalence relations. - -Author: - - Nikolaj Bjorner (nbjorner) 2012-05-14 - -Revision History: - ---*/ - -#include "dl_mk_partial_equiv.h" -#include "ast_pp.h" - -namespace datalog { - - bool mk_partial_equivalence_transformer::is_symmetry(rule const* r) { - func_decl* p = r->get_decl(); - return - p->get_arity() == 2 && - p->get_domain(0) == p->get_domain(1) && - r->get_tail_size() == 1 && - r->get_tail(0)->get_decl() == p && - r->get_head()->get_arg(0) == r->get_tail(0)->get_arg(1) && - r->get_head()->get_arg(1) == r->get_tail(0)->get_arg(0) && - is_var(r->get_head()->get_arg(0)) && - is_var(r->get_head()->get_arg(1)) && - r->get_head()->get_arg(0) != r->get_head()->get_arg(1); - } - - - bool mk_partial_equivalence_transformer::is_transitivity(rule const* r) { - func_decl* p = r->get_decl(); - if (p->get_arity() != 2 || - p->get_domain(0) != p->get_domain(1) || - r->get_tail_size() != 2 || - r->get_tail(0)->get_decl() != p || - r->get_tail(1)->get_decl() != p) { - return false; - } - app* h = r->get_head(); - app* a = r->get_tail(0); - app* b = r->get_tail(1); - expr* x1 = h->get_arg(0); - expr* x2 = h->get_arg(1); - expr* a1 = a->get_arg(0); - expr* a2 = a->get_arg(1); - expr* b1 = b->get_arg(0); - expr* b2 = b->get_arg(1); - - if (!(is_var(x1) && is_var(x2) && is_var(a1) && is_var(a2) && is_var(b1) && is_var(b2))) { - return false; - } - if (x1 == x2 || a1 == a2 || b1 == b2) { - return false; - } - if (a2 == b1) { - if (x1 == b2 && x2 == a1) { - return true; - } - if (x1 == a1 && x2 == b2) { - return true; - } - return false; - } - if (a1 == b2) { - if (x1 == b1 && x2 == a2) { - return true; - } - if (x1 == a2 && x2 == b1) { - return true; - } - return false; - } - - return false; -; - } - - - rule_set * mk_partial_equivalence_transformer::operator()(rule_set const & source) { - // TODO mc - - if (source.get_num_rules() == 0) { - return 0; - } - - if (m_context.get_engine() != DATALOG_ENGINE) { - return 0; - } - - relation_manager & rm = m_context.get_rel_context()->get_rmanager(); - rule_set::decl2rules::iterator it = source.begin_grouped_rules(); - rule_set::decl2rules::iterator end = source.end_grouped_rules(); - - rule_set* res = alloc(rule_set, m_context); - - for (; it != end; ++it) { - func_decl* p = it->m_key; - rule_vector const& rv = *(it->m_value); - bool has_symmetry = false; - bool has_transitivity = false; - unsigned i_symmetry, i_transitivity; - family_id kind = rm.get_requested_predicate_kind(p); - for (unsigned i = 0; i < rv.size(); ++i) { - - if (kind != null_family_id) { - res->add_rule(rv[i]); - } - else if (is_symmetry(rv[i])) { - i_symmetry = i; - has_symmetry = true; - } - else if (is_transitivity(rv[i])) { - i_transitivity = i; - has_transitivity = true; - } - else { - res->add_rule(rv[i]); - } - } - if (has_symmetry && !has_transitivity) { - res->add_rule(rv[i_symmetry]); - } - else if (!has_symmetry && has_transitivity) { - res->add_rule(rv[i_transitivity]); - } - else if (has_symmetry && has_transitivity) { - TRACE("dl", tout << "updating predicate " << mk_pp(p, m) << " to partial equivalence\n";); - SASSERT(kind == null_family_id); - rm.set_predicate_kind(p, rm.get_table_plugin(symbol("equivalence"))->get_kind()); - } - } - - if (res->get_num_rules() == source.get_num_rules()) { - dealloc(res); - return 0; - } - res->inherit_predicates(source); - - return res; - } - -}; - - diff --git a/src/muz/dl_mk_partial_equiv.h b/src/muz/dl_mk_partial_equiv.h deleted file mode 100644 index 54a70b3c0..000000000 --- a/src/muz/dl_mk_partial_equiv.h +++ /dev/null @@ -1,50 +0,0 @@ -/*++ -Copyright (c) 2012 Microsoft Corporation - -Module Name: - - dl_mk_partial_equiv.h - -Abstract: - - Rule transformer which identifies predicates that are partial equivalence relations. - -Author: - - Nikolaj Bjorner (nbjorner) 2012-05-14 - -Revision History: - ---*/ - - -#ifndef _DL_MK_PARTIAL_EQUIVALENCE_TRANSFORMER_H_ -#define _DL_MK_PARTIAL_EQUIVALENCE_TRANSFORMER_H_ - -#include "dl_context.h" -#include "dl_rule_transformer.h" - -namespace datalog { - - class mk_partial_equivalence_transformer : public rule_transformer::plugin { - ast_manager & m; - context & m_context; - public: - mk_partial_equivalence_transformer(context & ctx, unsigned priority=45000) - : plugin(priority), - m(ctx.get_manager()), - m_context(ctx) {} - - rule_set * operator()(rule_set const & source); - - private: - - bool is_symmetry(rule const* r); - bool is_transitivity(rule const* r); - }; - -}; - -#endif /* _DL_MK_PARTIAL_EQUIV_TRANSFORMER_H_ */ - - diff --git a/src/muz/dl_mk_similarity_compressor.cpp b/src/muz/dl_mk_similarity_compressor.cpp deleted file mode 100644 index d4f410130..000000000 --- a/src/muz/dl_mk_similarity_compressor.cpp +++ /dev/null @@ -1,545 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - dl_mk_similarity_compressor.cpp - -Abstract: - - - -Author: - - Krystof Hoder (t-khoder) 2010-10-22. - -Revision History: - ---*/ - -#include -#include -#include"dl_mk_similarity_compressor.h" - -namespace datalog { - - mk_similarity_compressor::mk_similarity_compressor(context & ctx) : - plugin(5000), - m_context(ctx), - m_manager(ctx.get_manager()), - m_threshold_count(ctx.similarity_compressor_threshold()), - m_result_rules(ctx.get_rule_manager()), - m_modified(false), - m_pinned(m_manager) { - SASSERT(m_threshold_count>1); - } - - void mk_similarity_compressor::reset() { - m_rules.reset(); - m_result_rules.reset(); - m_pinned.reset(); - } - - /** - Allows to traverse head and positive tails in a single for loop starting from -1 - */ - static app * get_by_tail_index(rule * r, int idx) { - if (idx < 0) { - return r->get_head(); - } - SASSERT(idx < static_cast(r->get_positive_tail_size())); - return r->get_tail(idx); - } - - template - static int aux_compare(T a, T b) { - return (a>b) ? 1 : ( (a==b) ? 0 : -1); - } - - template - static int aux_compare(T* a, T* b); - - static int compare_var_args(app* t1, app* t2) { - SASSERT(t1->get_num_args()==t2->get_num_args()); - int res; - unsigned n = t1->get_num_args(); - for (unsigned i = 0; i < n; i++) { - expr * a1 = t1->get_arg(i); - expr * a2 = t2->get_arg(i); - res = aux_compare(is_var(a1), is_var(a2)); - if (res != 0) { - return res; - } - if (is_var(a1)) { - res = aux_compare(to_var(a1)->get_idx(), to_var(a2)->get_idx()); - if (res != 0) { - return res; - } - } - } - return 0; - } - - static int compare_args(app* t1, app* t2, int & skip_countdown) { - SASSERT(t1->get_num_args()==t2->get_num_args()); - int res; - unsigned n = t1->get_num_args(); - for (unsigned i=0; iget_arg(i))) { - SASSERT(t1->get_arg(i) == t2->get_arg(i)); - continue; - } - if ((skip_countdown--) == 0) { - continue; - } - res = aux_compare(t1->get_arg(i)->get_id(), t2->get_arg(i)->get_id()); - if (res!=0) { return res; } - } - return 0; - } - - /** - \brief Return 0 if r1 and r2 could be similar. If the rough similarity - equaivelance class of r1 is greater than the one of r2, return 1; otherwise return -1. - - Two rules are in the same rough similarity class if they differ only in constant arguments - of positive uninterpreted predicates. - */ - static int rough_compare(rule * r1, rule * r2) { - int res = aux_compare(r1->get_tail_size(), r2->get_tail_size()); - if (res!=0) { return res; } - res = aux_compare(r1->get_uninterpreted_tail_size(), r2->get_uninterpreted_tail_size()); - if (res!=0) { return res; } - res = aux_compare(r1->get_positive_tail_size(), r2->get_positive_tail_size()); - if (res!=0) { return res; } - - int pos_tail_sz = r1->get_positive_tail_size(); - for (int i=-1; iget_decl()->get_id(), t2->get_decl()->get_id()); - if (res!=0) { return res; } - res = compare_var_args(t1, t2); - if (res!=0) { return res; } - } - - unsigned tail_sz = r1->get_tail_size(); - for (unsigned i=pos_tail_sz; iget_tail(i)->get_id(), r2->get_tail(i)->get_id()); - if (res!=0) { return res; } - } - - return 0; - } - - /** - \c r1 and \c r2 must be equal according to the \c rough_compare function for this function - to be called. - */ - static int total_compare(rule * r1, rule * r2, int skipped_arg_index = INT_MAX) { - SASSERT(rough_compare(r1, r2)==0); - int pos_tail_sz = r1->get_positive_tail_size(); - for (int i=-1; i info_vector; - - static void collect_const_indexes(app * t, int tail_index, info_vector & res) { - unsigned n = t->get_num_args(); - for (unsigned i=0; iget_arg(i))) { - continue; - } - res.push_back(const_info(tail_index, i)); - } - } - - static void collect_const_indexes(rule * r, info_vector & res) { - collect_const_indexes(r->get_head(), -1, res); - unsigned pos_tail_sz = r->get_positive_tail_size(); - for (unsigned i=0; iget_tail(i), i, res); - } - } - - template - static void collect_orphan_consts(rule * r, const info_vector & const_infos, T & tgt) { - unsigned const_cnt = const_infos.size(); - tgt.reset(); - for (unsigned i=0; iget_arg(inf.arg_index()))); - SASSERT(tgt.back()->get_num_args()==0); - } - } - template - static void collect_orphan_sorts(rule * r, const info_vector & const_infos, T & tgt) { - unsigned const_cnt = const_infos.size(); - tgt.reset(); - for (unsigned i=0; iget_decl()->get_domain(inf.arg_index())); - } - } - - /** - \brief From the \c tail_indexes and \c arg_indexes remove elements corresponding to constants - that are the same in rules \c *first ... \c *(after_last-1). - */ - static void remove_stable_constants(rule_vector::iterator first, rule_vector::iterator after_last, - info_vector & const_infos) { - SASSERT(after_last-first>1); - unsigned const_cnt = const_infos.size(); - ptr_vector vals; - rule * r = *(first++); - collect_orphan_consts(r, const_infos, vals); - SASSERT(vals.size()==const_cnt); - rule_vector::iterator it = first; - for (; it!=after_last; ++it) { - for (unsigned i=0; iget_arg(const_infos[i].arg_index())); - if (vals[i]!=val) { - vals[i] = 0; - } - } - } - unsigned removed_cnt = 0; - for (unsigned i=0; i vals; - ptr_vector sorts; - rule * r = *(first++); - collect_orphan_consts(r, const_infos, vals); - collect_orphan_sorts(r, const_infos, sorts); - SASSERT(vals.size()==const_cnt); - vector possible_parents(const_cnt); - for (unsigned i=1; iget_head()->get_num_args() - count_variable_arguments(r->get_head()); - unsigned pos_tail_sz = r->get_positive_tail_size(); - for (unsigned i=0; iget_tail(i)->get_num_args() - count_variable_arguments(r->get_tail(i)); - } - return res; - } - - static bool initial_comparator(rule * r1, rule * r2) { - int res = rough_compare(r1, r2); - if (res!=0) { return res>0; } - return total_compare(r1, r2)>0; - } - - class arg_ignoring_comparator { - unsigned m_ignored_index; - public: - arg_ignoring_comparator(unsigned ignored_index) : m_ignored_index(ignored_index) {} - bool operator()(rule * r1, rule * r2) const { - return total_compare(r1, r2, m_ignored_index)>0; - } - bool eq(rule * r1, rule * r2) const { - return total_compare(r1, r2, m_ignored_index)==0; - } - }; - - void mk_similarity_compressor::merge_class(rule_vector::iterator first, - rule_vector::iterator after_last) { - SASSERT(after_last-first>1); - info_vector const_infos; - rule * r = *first; //an arbitrary representative of the class - collect_const_indexes(r, const_infos); - remove_stable_constants(first, after_last, const_infos); - - unsigned const_cnt = const_infos.size(); - SASSERT(const_cnt>0); - - detect_equal_constants(first, after_last, const_infos); - - - //The aux relation contains column for each constant which does not have an earlier constant - //that it is equal to (i.e. only has no parent) - ptr_vector aux_domain; - collect_orphan_sorts(r, const_infos, aux_domain); - - func_decl* head_pred = r->get_decl(); - symbol const& name_prefix = head_pred->get_name(); - std::string name_suffix = "sc_" + to_string(const_cnt); - func_decl * aux_pred = m_context.mk_fresh_head_predicate(name_prefix, symbol(name_suffix.c_str()), - aux_domain.size(), aux_domain.c_ptr(), head_pred); - m_pinned.push_back(aux_pred); - - relation_fact val_fact(m_manager, const_cnt); - rule_vector::iterator it = first; - for (; it!=after_last; ++it) { - collect_orphan_consts(*it, const_infos, val_fact); - m_context.add_fact(aux_pred, val_fact); - } - m_context.get_rel_context()->get_rmanager().mark_saturated(aux_pred); - - app * new_head = r->get_head(); - ptr_vector new_tail; - svector new_negs; - unsigned tail_sz = r->get_tail_size(); - for (unsigned i=0; iget_tail(i)); - new_negs.push_back(r->is_neg_tail(i)); - } - - rule_counter ctr; - ctr.count_rule_vars(m_manager, r); - unsigned max_var_idx, new_var_idx_base; - if (ctr.get_max_positive(max_var_idx)) { - new_var_idx_base = max_var_idx+1; - } - else { - new_var_idx_base = 0; - } - - ptr_vector const_vars; //variables at indexes of their corresponding constants - expr_ref_vector aux_vars(m_manager); //variables as arguments for the auxiliary predicate - - unsigned aux_column_index = 0; - - for (unsigned i=0; i mod_args(mod_tail->get_num_args(), mod_tail->get_args()); - - for (; iget_decl(), mod_args.c_ptr()); - m_pinned.push_back(upd_tail); - mod_tail = upd_tail; - } - - app_ref aux_tail(m_manager.mk_app(aux_pred, aux_vars.c_ptr()), m_manager); - new_tail.push_back(aux_tail); - new_negs.push_back(false); - - rule * new_rule = m_context.get_rule_manager().mk(new_head, new_tail.size(), new_tail.c_ptr(), - new_negs.c_ptr()); - m_result_rules.push_back(new_rule); - - //TODO: allow for a rule to have multiple parent objects - new_rule->set_accounting_parent_object(m_context, r); - m_modified = true; - } - - void mk_similarity_compressor::process_class(rule_set const& source, rule_vector::iterator first, - rule_vector::iterator after_last) { - SASSERT(first!=after_last); - //remove duplicates - { - rule_vector::iterator it = first; - rule_vector::iterator prev = it; - ++it; - while(it!=after_last) { - if (it!=after_last && total_compare(*prev, *it)==0) { - --after_last; - std::swap(*it, *after_last); - m_modified = true; - } - else { - prev = it; - ++it; - } - } - } - SASSERT(first!=after_last); - - unsigned const_cnt = get_constant_count(*first); -#if 0 - for (unsigned ignored_index=0; ignored_indexm_threshold_count) { - merge_class(grp_begin, it); - //group was processed, so we remove it from the class - if (it==after_last) { - after_last=grp_begin; - it=after_last; - } - else { - while(it!=grp_begin) { - std::swap(*--it, *--after_last); - } - } - } - grp_begin = it; - grp_size = 0; - } - } - } -#endif - //TODO: compress also rules with pairs (or tuples) of equal constants - -#if 1 - if (const_cnt>0 && !source.is_output_predicate((*first)->get_decl())) { - unsigned rule_cnt = static_cast(after_last-first); - if (rule_cnt>m_threshold_count) { - merge_class(first, after_last); - return; - } - } -#endif - - //put rules which weren't merged into result - rule_vector::iterator it = first; - for (; it!=after_last; ++it) { - m_result_rules.push_back(*it); - } - } - - rule_set * mk_similarity_compressor::operator()(rule_set const & source) { - // TODO mc - m_modified = false; - unsigned init_rule_cnt = source.get_num_rules(); - SASSERT(m_rules.empty()); - for (unsigned i=0; i(0); - if (m_modified) { - result = alloc(rule_set, m_context); - unsigned fin_rule_cnt = m_result_rules.size(); - for (unsigned i=0; iadd_rule(m_result_rules.get(i)); - } - result->inherit_predicates(source); - } - reset(); - return result; - } -}; diff --git a/src/muz/dl_mk_similarity_compressor.h b/src/muz/dl_mk_similarity_compressor.h deleted file mode 100644 index 34b76e7e1..000000000 --- a/src/muz/dl_mk_similarity_compressor.h +++ /dev/null @@ -1,78 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - dl_mk_similarity_compressor.h - -Abstract: - - - -Author: - - Krystof Hoder (t-khoder) 2010-10-22. - -Revision History: - ---*/ -#ifndef _DL_MK_SIMILARITY_COMPRESSOR_H_ -#define _DL_MK_SIMILARITY_COMPRESSOR_H_ - -#include - -#include"map.h" -#include"obj_pair_hashtable.h" - -#include"dl_context.h" -#include"dl_rule_set.h" -#include"dl_rule_transformer.h" - -namespace datalog { - - /** - \brief Functor for merging groups of similar rules. - - A rule sequence - - P("1",x):-Q(x). - ... - P("N",x):-Q(x). - - will be replaced by - - P(y,x):-Q(x), Aux(y). - - and a set of facts - - Aux("1"). - ... - Aux("N"). - - Similar transformation is performed when the varying constant appears in the positive tail. - */ - class mk_similarity_compressor : public rule_transformer::plugin { - - context & m_context; - ast_manager & m_manager; - /** number of similar rules necessary for a group to be introduced */ - unsigned m_threshold_count; - rule_vector m_rules; - rule_ref_vector m_result_rules; - bool m_modified; - ast_ref_vector m_pinned; - - void merge_class(rule_vector::iterator first, rule_vector::iterator after_last); - void process_class(rule_set const& source, rule_vector::iterator first, rule_vector::iterator after_last); - - void reset(); - public: - mk_similarity_compressor(context & ctx); - - rule_set * operator()(rule_set const & source); - }; - -}; - -#endif /* _DL_MK_SIMILARITY_COMPRESSOR_H_ */ - diff --git a/src/muz/dl_mk_simple_joins.cpp b/src/muz/dl_mk_simple_joins.cpp deleted file mode 100644 index 300ed0879..000000000 --- a/src/muz/dl_mk_simple_joins.cpp +++ /dev/null @@ -1,741 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - dl_mk_simple_joins.cpp - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2010-05-20. - -Revision History: - ---*/ - -#include -#include -#include -#include"dl_mk_simple_joins.h" -#include"ast_pp.h" -#include"trace.h" - - -namespace datalog { - - mk_simple_joins::mk_simple_joins(context & ctx): - plugin(1000), - m_context(ctx), - rm(ctx.get_rule_manager()) { - } - - class join_planner { - typedef float cost; - - class pair_info { - cost m_total_cost; - /** - \brief Number of rules longer than two that contain this pair. - - This number is being updated by \c add_rule and \remove rule. Even though between - adding a rule and removing it, the length of a rule can decrease without this pair - being notified about it, it will surely see the decrease from length 3 to 2 which - the threshold for rule being counted in this counter. - */ - unsigned m_consumers; - bool m_stratified; - unsigned m_src_stratum; - public: - var_idx_set m_all_nonlocal_vars; - rule_vector m_rules; - - pair_info() : m_consumers(0), m_stratified(true), m_src_stratum(0) {} - - bool can_be_joined() const { - return m_consumers>0; - } - - cost get_cost() const { - /*if(m_instantiated) { - return std::numeric_limits::min(); - }*/ - SASSERT(m_consumers>0); - cost amortized = m_total_cost/m_consumers; - if(m_stratified) { - return amortized * ( (amortized>0) ? (1/16.0f) : 16.0f); - } - else { - return amortized; - } - } - - /** - \brief Add rule \c r among rules interested in current predicate pair. - - The \c pl.m_rule_content entry of the rule has to be properly filled in - by the time of a call to this function - */ - void add_rule(join_planner & pl, app * t1, app * t2, rule * r, - const var_idx_set & non_local_vars_normalized) { - if(m_rules.empty()) { - m_total_cost = pl.compute_cost(t1, t2); - m_src_stratum = std::max(pl.get_stratum(t1->get_decl()), pl.get_stratum(t2->get_decl())); - } - m_rules.push_back(r); - if(pl.m_rules_content.find_core(r)->get_data().m_value.size()>2) { - m_consumers++; - } - if(m_stratified) { - unsigned head_stratum = pl.get_stratum(r->get_decl()); - SASSERT(head_stratum>=m_src_stratum); - if(head_stratum==m_src_stratum) { - m_stratified = false; - } - } - idx_set_union(m_all_nonlocal_vars, non_local_vars_normalized); - } - /** - \brief Remove rule from the pair record. Return true if no rules remain - in the pair, and so it should be removed. - */ - bool remove_rule(rule * r, unsigned original_length) { - TRUSTME( remove_from_vector(m_rules, r) ); - if(original_length>2) { - SASSERT(m_consumers>0); - m_consumers--; - } - SASSERT(!m_rules.empty() || m_consumers==0); - return m_rules.empty(); - } - private: - pair_info & operator=(const pair_info &); //to avoid the implicit one - }; - typedef std::pair app_pair; - typedef map, obj_ptr_hash >, default_eq > cost_map; - typedef map, ptr_hash, ptr_eq > rule_pred_map; - - context & m_context; - ast_manager & m; - rule_manager & rm; - var_subst & m_var_subst; - rule_set & m_rs_aux_copy; //reference to a rule_set that will allow to ask for stratum levels - - cost_map m_costs; - ptr_vector m_interpreted; - rule_pred_map m_rules_content; - rule_ref_vector m_introduced_rules; - ptr_hashtable, ptr_eq > m_modified_rules; - - ast_ref_vector m_pinned; - mutable ptr_vector m_vars; - - public: - join_planner(context & ctx, rule_set & rs_aux_copy) - : m_context(ctx), m(ctx.get_manager()), - rm(ctx.get_rule_manager()), - m_var_subst(ctx.get_var_subst()), - m_rs_aux_copy(rs_aux_copy), - m_introduced_rules(ctx.get_rule_manager()), - m_pinned(ctx.get_manager()) - { - } - - ~join_planner() - { - cost_map::iterator it = m_costs.begin(); - cost_map::iterator end = m_costs.end(); - for (; it != end; ++it) { - dealloc(it->m_value); - } - m_costs.reset(); - } - private: - - void get_normalizer(app * t, unsigned & next_var, expr_ref_vector & result) const { - SASSERT(result.size()>0); - unsigned res_ofs = result.size()-1; - unsigned n=t->get_num_args(); - for(unsigned i=0; iget_arg(i))); - var * v = to_var(t->get_arg(i)); - unsigned var_idx = v->get_idx(); - if(result[res_ofs-var_idx]==0) { - result[res_ofs-var_idx]=m.mk_var(next_var, v->get_sort()); - next_var++; - } - } - } - - void get_normalizer(app * t1, app * t2, expr_ref_vector & result) const { - SASSERT(result.empty()); - if(t1->get_num_args()==0 && t2->get_num_args()==0) { - return; //nothing to normalize - } - SASSERT(!t1->is_ground() || !t2->is_ground()); - - unsigned max_var_idx = 0; - { - var_idx_set& orig_var_set = rm.collect_vars(t1, t2); - var_idx_set::iterator ovit = orig_var_set.begin(); - var_idx_set::iterator ovend = orig_var_set.end(); - for(; ovit!=ovend; ++ovit) { - unsigned var_idx = *ovit; - if(var_idx>max_var_idx) { - max_var_idx = var_idx; - } - } - } - - if(t1->get_decl()!=t2->get_decl()) { - if(t1->get_decl()->get_id()get_decl()->get_id()) { - std::swap(t1, t2); - } - } - else { - int_vector norm1(max_var_idx+1, -1); - int_vector norm2(max_var_idx+1, -1); - unsigned n=t1->get_num_args(); - SASSERT(n==t2->get_num_args()); - for(unsigned i=0; iget_arg(i)); - var * v2 = to_var(t2->get_arg(i)); - if(v1->get_sort()!=v2->get_sort()) { - //different sorts mean we can distinguish the two terms - if(v1->get_sort()->get_id()get_sort()->get_id()) { - std::swap(t1, t2); - } - break; - } - unsigned v1_idx = v1->get_idx(); - unsigned v2_idx = v2->get_idx(); - //since the rules already went through the mk_filter_rules transformer, - //variables must be linear - SASSERT(norm1[v1_idx]==-1); - SASSERT(norm2[v2_idx]==-1); - - if(norm2[v1_idx]!=norm1[v2_idx]) { - //now we can distinguish the two terms - if(norm2[v1_idx](0)); - unsigned next_var = 0; - get_normalizer(t1, next_var, result); - get_normalizer(t2, next_var, result); - } - - app_pair get_key(app * t1, app * t2) { - expr_ref_vector norm_subst(m); - get_normalizer(t1, t2, norm_subst); - expr_ref t1n_ref(m); - expr_ref t2n_ref(m); - m_var_subst(t1, norm_subst.size(), norm_subst.c_ptr(), t1n_ref); - m_var_subst(t2, norm_subst.size(), norm_subst.c_ptr(), t2n_ref); - app * t1n = to_app(t1n_ref); - app * t2n = to_app(t2n_ref); - if(t1n>t2n) { - std::swap(t1n, t2n); - } - m_pinned.push_back(t1n); - m_pinned.push_back(t2n); - - /* - IF_VERBOSE(0, - print_renaming(norm_subst, verbose_stream()); - display_predicate(m_context, t1, verbose_stream()); - display_predicate(m_context, t2, verbose_stream()); - display_predicate(m_context, t1n, verbose_stream()); - display_predicate(m_context, t2n, verbose_stream());); - */ - return app_pair(t1n, t2n); - } - - /** - \brief Add rule \c r among rules interested in predicate pair \c t1, \c t2. - - The \c m_rule_content entry of the rule \c r has to be properly filled in - by the time of a call to this function - */ - void register_pair(app * t1, app * t2, rule * r, const var_idx_set & non_local_vars) { - TRACE("dl", tout << mk_pp(t1, m) << " " << mk_pp(t2, m) << "\n"; - r->display(m_context, tout); tout << "\n";); - SASSERT(t1!=t2); - cost_map::entry * e = m_costs.insert_if_not_there2(get_key(t1, t2), 0); - pair_info * & ptr_inf = e->get_data().m_value; - if(ptr_inf==0) { - ptr_inf = alloc(pair_info); - } - pair_info & inf = *ptr_inf; - - expr_ref_vector normalizer(m); - get_normalizer(t1, t2, normalizer); - unsigned norm_ofs = normalizer.size()-1; - var_idx_set normalized_vars; - var_idx_set::iterator vit = non_local_vars.begin(); - var_idx_set::iterator vend = non_local_vars.end(); - for(; vit!=vend; ++vit) { - unsigned norm_var = to_var(normalizer.get(norm_ofs-*vit))->get_idx(); - normalized_vars.insert(norm_var); - } - - inf.add_rule(*this, t1, t2, r, normalized_vars); - } - - pair_info & get_pair(app_pair key) const { - cost_map::entry * e = m_costs.find_core(key); - SASSERT(e); - return *e->get_data().m_value; - } - - void remove_rule_from_pair(app_pair key, rule * r, unsigned original_len) { - pair_info * ptr = &get_pair(key); - if(ptr->remove_rule(r, original_len)) { - SASSERT(ptr->m_rules.empty()); - m_costs.remove(key); - dealloc(ptr); - } - } - - void register_rule(rule * r) { - rule_counter counter; - counter.count_rule_vars(m, r, 1); - - ptr_vector & rule_content = - m_rules_content.insert_if_not_there2(r, ptr_vector())->get_data().m_value; - SASSERT(rule_content.empty()); - - unsigned pos_tail_size=r->get_positive_tail_size(); - for(unsigned i=0; iget_tail(i)); - } - for(unsigned i=0; iget_tail(i); - var_idx_set t1_vars = rm.collect_vars(t1); - counter.count_vars(m, t1, -1); //temporarily remove t1 variables from counter - for(unsigned j=i+1; jget_tail(j); - counter.count_vars(m, t2, -1); //temporarily remove t2 variables from counter - var_idx_set scope_vars = rm.collect_vars(t2); - scope_vars |= t1_vars; - var_idx_set non_local_vars; - counter.collect_positive(non_local_vars); - counter.count_vars(m, t2, 1); //restore t2 variables in counter - set_intersection(non_local_vars, scope_vars); - register_pair(t1, t2, r, non_local_vars); - } - counter.count_vars(m, t1, 1); //restore t1 variables in counter - } - } - - bool extract_argument_info(unsigned var_idx, app * t, expr_ref_vector & args, - ptr_vector & domain) { - unsigned n=t->get_num_args(); - for(unsigned i=0; iget_arg(i)); - if(v->get_idx()==var_idx) { - args.push_back(v); - domain.push_back(m.get_sort(v)); - return true; - } - } - return false; - } - - void join_pair(app_pair pair_key) { - app * t1 = pair_key.first; - app * t2 = pair_key.second; - pair_info & inf = get_pair(pair_key); - SASSERT(!inf.m_rules.empty()); - var_idx_set & output_vars = inf.m_all_nonlocal_vars; - expr_ref_vector args(m); - ptr_vector domain; - - unsigned arity = output_vars.num_elems(); - idx_set::iterator ovit=output_vars.begin(); - idx_set::iterator ovend=output_vars.end(); - //TODO: improve quadratic complexity - for(;ovit!=ovend;++ovit) { - unsigned var_idx=*ovit; - - bool found=extract_argument_info(var_idx, t1, args, domain); - if(!found) { - found=extract_argument_info(var_idx, t2, args, domain); - } - SASSERT(found); - } - - SASSERT(args.size()==arity); - SASSERT(domain.size()==arity); - - rule * one_parent = inf.m_rules.back(); - - func_decl* parent_head = one_parent->get_decl(); - const char * one_parent_name = parent_head->get_name().bare_str(); - std::string parent_name; - if(inf.m_rules.size()>1) { - parent_name = one_parent_name + std::string("_and_") + to_string(inf.m_rules.size()-1); - } - else { - parent_name = one_parent_name; - } - - func_decl * decl = m_context.mk_fresh_head_predicate( - symbol(parent_name.c_str()), symbol("split"), - arity, domain.c_ptr(), parent_head); - - app_ref head(m.mk_app(decl, arity, args.c_ptr()), m); - - app * tail[] = {t1, t2}; - - rule * new_rule = m_context.get_rule_manager().mk(head, 2, tail, 0); - - //TODO: update accounting so that it can handle multiple parents - new_rule->set_accounting_parent_object(m_context, one_parent); - - m_introduced_rules.push_back(new_rule); - - //here we copy the inf.m_rules vector because inf.m_rules will get changed - //in the iteration. Also we use hashtable instead of vector because we do - //not want to process one rule twice. - typedef ptr_hashtable, default_eq > rule_hashtable; - rule_hashtable relevant_rules; - insert_into_set(relevant_rules, inf.m_rules); - rule_hashtable::iterator rit = relevant_rules.begin(); - rule_hashtable::iterator rend = relevant_rules.end(); - for(; rit!=rend; ++rit) { - apply_binary_rule(*rit, pair_key, head); - } - - // SASSERT(!m_costs.contains(pair_key)); - } - - void replace_edges(rule * r, const ptr_vector & removed_tails, - const ptr_vector & added_tails0, const ptr_vector & rule_content) { - SASSERT(removed_tails.size()>=added_tails0.size()); - unsigned len = rule_content.size(); - unsigned original_len = len+removed_tails.size()-added_tails0.size(); - ptr_vector added_tails(added_tails0); //we need a copy since we'll be modifying it - - unsigned rt_sz = removed_tails.size(); - //remove edges between removed tails - for(unsigned i=0; iget_head(); - - var_counter counter; - counter.count_vars(m, head, 1); - - unsigned tail_size=r->get_tail_size(); - unsigned pos_tail_size=r->get_positive_tail_size(); - - for(unsigned i=pos_tail_size; iget_tail(i), 1); - } - for(unsigned i=0; i & rule_content = m_rules_content.find_core(r)->get_data().m_value; - unsigned len = rule_content.size(); - if(len==1) { - return; - } - - func_decl * t1_pred = t1->get_decl(); - func_decl * t2_pred = t2->get_decl(); - ptr_vector removed_tails; - ptr_vector added_tails; - for(unsigned i1=0; i1get_decl()!=t1_pred) { - continue; - } - unsigned i2start = (t1_pred==t2_pred) ? (i1+1) : 0; - for(unsigned i2=i2start; i2get_decl()!=t2_pred) { - continue; - } - if(get_key(rt1, rt2)!=pair_key) { - continue; - } - expr_ref_vector normalizer(m); - get_normalizer(rt1, rt2, normalizer); - expr_ref_vector denormalizer(m); - reverse_renaming(m, normalizer, denormalizer); - expr_ref new_transf(m); - m_var_subst(t_new, denormalizer.size(), denormalizer.c_ptr(), new_transf); - app * new_lit = to_app(new_transf); - - m_pinned.push_back(new_lit); - rule_content[i1]=new_lit; - rule_content[i2]=rule_content.back(); - rule_content.pop_back(); - len--; //here the bound of both loops changes!!! - removed_tails.push_back(rt1); - removed_tails.push_back(rt2); - added_tails.push_back(new_lit); - //this exits the inner loop, the outer one continues in case there will - //be other matches - break; - } - } - SASSERT(!removed_tails.empty()); - SASSERT(!added_tails.empty()); - m_modified_rules.insert(r); - replace_edges(r, removed_tails, added_tails, rule_content); - } - - cost get_domain_size(func_decl * pred, unsigned arg_index) const { - relation_sort sort = pred->get_domain(arg_index); - return static_cast(m_context.get_sort_size_estimate(sort)); - //unsigned sz; - //if(!m_context.get_sort_size(sort, sz)) { - // sz=UINT_MAX; - //} - //return static_cast(sz); - } - - unsigned get_stratum(func_decl * pred) const { - return m_rs_aux_copy.get_predicate_strat(pred); - } - - cost estimate_size(app * t) const { - func_decl * pred = t->get_decl(); - unsigned n=pred->get_arity(); - rel_context* rel = m_context.get_rel_context(); - if (!rel) { - return cost(1); - } - relation_manager& rm = rel->get_rmanager(); - if( (m_context.saturation_was_run() && rm.try_get_relation(pred)) - || rm.is_saturated(pred)) { - SASSERT(rm.try_get_relation(pred)); //if it is saturated, it should exist - unsigned rel_size_int = rel->get_relation(pred).get_size_estimate_rows(); - if(rel_size_int!=0) { - cost rel_size = static_cast(rel_size_int); - cost curr_size = rel_size; - for(unsigned i=0; iget_arg(i))) { - curr_size /= get_domain_size(pred, i); - } - } - return curr_size; - } - } - cost res = 1; - for(unsigned i=0; iget_arg(i))) { - res *= get_domain_size(pred, i); - } - } - return res; - } - - cost compute_cost(app * t1, app * t2) const { - func_decl * t1_pred = t1->get_decl(); - func_decl * t2_pred = t2->get_decl(); - cost inters_size = 1; - variable_intersection vi(m_context.get_manager()); - vi.populate(t1, t2); - unsigned n = vi.size(); - for(unsigned i=0; i0) { - res /= 2; - } - else { - res *= 2; - } - } - }*/ - - TRACE("report_costs", - display_predicate(m_context, t1, tout); - display_predicate(m_context, t2, tout); - tout << res << "\n";); - return res; - } - - - bool pick_best_pair(app_pair & p) { - app_pair best; - bool found = false; - cost best_cost; - - cost_map::iterator it = m_costs.begin(); - cost_map::iterator end = m_costs.end(); - for(; it!=end; ++it) { - app_pair key = it->m_key; - pair_info & inf = *it->m_value; - if(!inf.can_be_joined()) { - continue; - } - cost c = inf.get_cost(); - if(!found || cm_key; - ptr_vector content = rcit->m_value; - SASSERT(content.size()<=2); - if(content.size()==orig_r->get_positive_tail_size()) { - //rule did not change - result->add_rule(orig_r); - continue; - } - - ptr_vector tail(content); - svector negs(tail.size(), false); - unsigned or_len = orig_r->get_tail_size(); - for(unsigned i=orig_r->get_positive_tail_size(); iget_tail(i)); - negs.push_back(orig_r->is_neg_tail(i)); - } - - rule * new_rule = m_context.get_rule_manager().mk(orig_r->get_head(), tail.size(), tail.c_ptr(), - negs.c_ptr()); - - new_rule->set_accounting_parent_object(m_context, orig_r); - m_context.get_rule_manager().mk_rule_rewrite_proof(*orig_r, *new_rule); - result->add_rule(new_rule); - } - while (!m_introduced_rules.empty()) { - result->add_rule(m_introduced_rules.back()); - m_context.get_rule_manager().mk_rule_asserted_proof(*m_introduced_rules.back()); - m_introduced_rules.pop_back(); - } - result->inherit_predicates(source); - return result; - } - }; - - rule_set * mk_simple_joins::operator()(rule_set const & source) { - rule_set rs_aux_copy(m_context); - rs_aux_copy.replace_rules(source); - if(!rs_aux_copy.is_closed()) { - rs_aux_copy.close(); - } - - join_planner planner(m_context, rs_aux_copy); - - return planner.run(source); - } - - -}; - diff --git a/src/muz/dl_mk_simple_joins.h b/src/muz/dl_mk_simple_joins.h deleted file mode 100644 index 36eb08dd5..000000000 --- a/src/muz/dl_mk_simple_joins.h +++ /dev/null @@ -1,63 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - dl_mk_simple_joins.h - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2010-05-20. - -Revision History: - ---*/ -#ifndef _DL_MK_SIMPLE_JOINS_H_ -#define _DL_MK_SIMPLE_JOINS_H_ - -#include"map.h" -#include"obj_pair_hashtable.h" - -#include"dl_context.h" -#include"dl_rule_set.h" -#include"dl_rule_transformer.h" - -namespace datalog { - - /** - \brief Functor for creating rules that contain simple joins. - A simple join is the join of two tables. - - After applying this transformation, every rule has at most one join. - So, the rules will have the form - - HEAD :- TAIL. - HEAD :- TAIL_1, TAIL_2. - - We also assume a rule may contain interpreted expressions that work as filtering conditions. - So, we may also have: - - HEAD :- TAIL, C_1, ..., C_n. - HEAD :- TAIL_1, TAIL_2, C_1, ..., C_n. - - Where the C_i's are interpreted expressions. - - We say that a rule containing C_i's is a rule with a "big tail". - */ - class mk_simple_joins : public rule_transformer::plugin { - context & m_context; - rule_manager & rm; - public: - mk_simple_joins(context & ctx); - - rule_set * operator()(rule_set const & source); - }; - -}; - -#endif /* _DL_MK_SIMPLE_JOINS_H_ */ - diff --git a/src/muz/dl_product_relation.cpp b/src/muz/dl_product_relation.cpp deleted file mode 100644 index 48cd666e6..000000000 --- a/src/muz/dl_product_relation.cpp +++ /dev/null @@ -1,1117 +0,0 @@ -/*++ -Copyright (c) 2010 Microsoft Corporation - -Module Name: - - dl_product_relation.cpp - -Abstract: - - A Relation combinator. - -Author: - - Nikolaj Bjorner (nbjorner) 2010-4-11 - -Revision History: - -Notes: - - join = - more refined version lets augment the product - relation as a consequence of join. - join Q = - join = - - - u = - more refined version: - < (R u R') n (R u S') n (R' u S), (S u S') n (S u R') n (S' u R)> - - - proj = < proj R, proj S> - - & phi = - attach S to [R & phi] whenever R & phi can propagate to S - - - [rename] = - - - ---*/ - - -#include "dl_sieve_relation.h" -#include "dl_table_relation.h" -#include "dl_product_relation.h" -#include "bool_rewriter.h" -#include "ast_pp.h" - -namespace datalog { - - // ----------------------------------- - // - // product_relation_plugin - // - // ----------------------------------- - - product_relation_plugin & product_relation_plugin::get_plugin(relation_manager & rmgr) { - product_relation_plugin * res = - static_cast(rmgr.get_relation_plugin(get_name())); - if(!res) { - res = alloc(product_relation_plugin, rmgr); - rmgr.register_plugin(res); - } - return *res; - } - - product_relation_plugin::product_relation_plugin(relation_manager& m): - relation_plugin(product_relation_plugin::get_name(), m, ST_PRODUCT_RELATION), - m_spec_store(*this) { - } - - void product_relation_plugin::initialize(family_id fid) { - relation_plugin::initialize(fid); - m_spec_store.add_available_kind(get_kind()); - } - - family_id product_relation_plugin::get_relation_kind(const relation_signature & sig, const rel_spec & spec) { - return m_spec_store.get_relation_kind(sig, spec); - } - - family_id product_relation_plugin::get_relation_kind(const product_relation & r) { - return get_relation_kind(r.get_signature(), r.m_spec); - } - - bool product_relation_plugin::can_handle_signature(const relation_signature & s) { - return m_spec_store.contains_signature(s); - } - - bool product_relation_plugin::can_handle_signature(const relation_signature & s, family_id k) { - return true; - } - - product_relation& product_relation_plugin::get(relation_base& r) { - return dynamic_cast(r); - } - - product_relation const & product_relation_plugin::get(relation_base const& r) { - return dynamic_cast(r); - } - - product_relation* product_relation_plugin::get(relation_base* r) { - return dynamic_cast(r); - } - - product_relation const* product_relation_plugin::get(relation_base const* r) { - return dynamic_cast(r); - } - - bool product_relation_plugin::is_product_relation(relation_base const& r) { - return r.get_plugin().get_name() == product_relation_plugin::get_name(); - } - - bool product_relation_plugin::are_aligned(const product_relation& r1, const product_relation& r2) { - unsigned sz = r1.size(); - if(sz!=r2.size()) { - return false; - } - for(unsigned i=0; i & rels, - rel_spec & res) { - vector specs; - ptr_vector::const_iterator rit = rels.begin(); - ptr_vector::const_iterator rend = rels.end(); - for(; rit!=rend; ++rit) { - specs.push_back((*rit)->m_spec); - } - - vector::iterator sit = specs.begin(); - vector::iterator send = specs.end(); - for(; sit!=send; ++sit) { - rel_spec & s = *sit; - std::sort(s.begin(), s.end()); - } - - res.reset(); - for(;;) { - family_id next = -1; - - sit = specs.begin(); - for(; sit!=send; ++sit) { - rel_spec & s = *sit; - if(!s.empty() && s.back()>next) { - next = s.back(); - } - } - if(next==-1) { - //we're done - break; - } - res.push_back(next); - sit = specs.begin(); - for(; sit!=send; ++sit) { - rel_spec & s = *sit; - if(!s.empty() && s.back()==next) { - s.pop_back(); - } - } - } - } - - - relation_base * product_relation_plugin::mk_empty(const relation_signature & s) { - return alloc(product_relation,*this, s); - } - - relation_base * product_relation_plugin::mk_empty(const relation_signature & s, family_id kind) { - rel_spec spec; - m_spec_store.get_relation_spec(s, kind, spec); - relation_vector inner_rels; - unsigned rel_cnt = spec.size(); - for(unsigned i=0; i m_joins; - ptr_vector m_full; - unsigned_vector m_offset1; - svector m_kind1; - unsigned_vector m_offset2; - svector m_kind2; - - const relation_base & get_nonsieve_relation(const relation_base & r) { - relation_plugin & rp = r.get_plugin(); - if(rp.is_sieve_relation()) { - return static_cast(r).get_inner(); - } - else { - return r; - } - } - - relation_plugin & get_nonsieve_plugin(const relation_base & r) { - return get_nonsieve_relation(r).get_plugin(); - } - - family_id get_nonsieve_kind(const relation_base & r) { - return get_nonsieve_relation(r).get_kind(); - } - - /** - A tableish relatio is either a table_relation or a sieve_relation with a table_relation inside. - */ - bool is_tableish_relation(const relation_base & r) { - return get_nonsieve_plugin(r).from_table(); - } - - relation_base * get_full_tableish_relation(const relation_signature & sig, func_decl* p, family_id kind) { - relation_manager& rmgr = m_plugin.get_manager(); - table_signature tsig; - if(rmgr.relation_signature_to_table(sig, tsig)) { - return rmgr.mk_table_relation(sig, rmgr.get_appropriate_plugin(tsig).mk_full(p, tsig, kind)); - } - unsigned sz = sig.size(); - tsig.reset(); - for(unsigned i=0; i relations; - unsigned sz = m_joins.size(); - relation_base* result = 0; - for (unsigned i = 0; i < sz; ++i) { - relation_base const& r1 = (m_kind1[i] == T_FULL)?(*m_full[m_offset1[i]]):access(m_offset1[i], _r1); - relation_base const& r2 = (m_kind2[i] == T_FULL)?(*m_full[m_offset2[i]]):access(m_offset2[i], _r2); - relations.push_back((*m_joins[i])(r1, r2)); - } - result = alloc(product_relation, m_plugin, get_result_signature(), sz, relations.c_ptr()); - TRACE("dl",result->display(tout);); - return result; - } - }; - - relation_join_fn * product_relation_plugin::mk_join_fn(const relation_base & r1, const relation_base & r2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) { - if (is_product_relation(r1) && is_product_relation(r2)) { - return alloc(join_fn, *this, get(r1), get(r2), col_cnt, cols1, cols2); - } - if (is_product_relation(r1)) { - return alloc(join_fn, *this, get(r1), r2, col_cnt, cols1, cols2); - } - if (is_product_relation(r2)) { - return alloc(join_fn, *this, r1, get(r2), col_cnt, cols1, cols2); - } - if (r1.get_kind() != r2.get_kind()) { - return alloc(join_fn, *this, r1, r2, col_cnt, cols1, cols2); - } - return 0; - } - - - class product_relation_plugin::transform_fn : public relation_transformer_fn { - relation_signature m_sig; - ptr_vector m_transforms; - public: - transform_fn(relation_signature s, unsigned num_trans, relation_transformer_fn** trans): - m_sig(s), - m_transforms(num_trans, trans) {} - - ~transform_fn() { dealloc_ptr_vector_content(m_transforms); } - - virtual relation_base * operator()(const relation_base & _r) { - product_relation const& r = get(_r); - product_relation_plugin& p = r.get_plugin(); - SASSERT(m_transforms.size() == r.size()); - ptr_vector relations; - for (unsigned i = 0; i < r.size(); ++i) { - relations.push_back((*m_transforms[i])(r[i])); - } - relation_base* result = alloc(product_relation, p, m_sig, relations.size(), relations.c_ptr()); - TRACE("dl", _r.display(tout); result->display(tout);); - return result; - } - }; - - relation_transformer_fn * product_relation_plugin::mk_project_fn(const relation_base & _r, - unsigned col_cnt, const unsigned * removed_cols) { - if (is_product_relation(_r)) { - product_relation const& r = get(_r); - ptr_vector projs; - for (unsigned i = 0; i < r.size(); ++i) { - projs.push_back(get_manager().mk_project_fn(r[i], col_cnt, removed_cols)); - } - relation_signature s; - relation_signature::from_project(r.get_signature(), col_cnt, removed_cols, s); - return alloc(transform_fn, s, projs.size(), projs.c_ptr()); - } - return 0; - } - - relation_transformer_fn * product_relation_plugin::mk_rename_fn(const relation_base & _r, - unsigned cycle_len, const unsigned * permutation_cycle) { - if(is_product_relation(_r)) { - ptr_vector trans; - product_relation const& r = get(_r); - for (unsigned i = 0; i < r.size(); ++i) { - trans.push_back(get_manager().mk_rename_fn(r[i], cycle_len, permutation_cycle)); - } - relation_signature s; - relation_signature::from_rename(r.get_signature(), cycle_len, permutation_cycle, s); - return alloc(transform_fn, s, trans.size(), trans.c_ptr()); - } - return 0; - } - - class product_relation_plugin::aligned_union_fn : public relation_union_fn { - relation_manager & m_rmgr; - bool m_is_widen; - - //m_union[i][j] is union between i-th and j-th relation. - //It can be zero which means that particular union should be skipped. - vector > m_unions; - - void mk_union_fn(unsigned i, unsigned j, relation_base const& r1, relation_base const& r2, - const relation_base* delta) { - relation_manager& rmgr = r1.get_manager(); - relation_union_fn* u = 0; - if (m_is_widen) { - u = rmgr.mk_widen_fn(r1, r2, delta); - } - else { - u = rmgr.mk_union_fn(r1, r2, delta); - } - m_unions.back().push_back(u); - } - - void init(const relation_vector & tgts, const relation_vector & srcs, const relation_vector * deltas) { - SASSERT(tgts.size()==srcs.size()); - unsigned num = tgts.size(); - for (unsigned i = 0; i < num; ++i) { - relation_base& r1 = *tgts[i]; - relation_base* delta = deltas ? (*deltas)[i] : 0; - m_unions.push_back(ptr_vector()); - for (unsigned j = 0; j < num; ++j) { - relation_base& r2 = *srcs[j]; - mk_union_fn(i, j, r1, r2, delta); - } - } - } - - bool can_do_inner_union(unsigned tgt_idx, unsigned src_idx) { - return m_unions[tgt_idx][src_idx]!=0; - } - - void do_inner_union(unsigned tgt_idx, unsigned src_idx, relation_base& tgt, - relation_base& src, relation_base * delta) { - SASSERT(m_unions[tgt_idx][src_idx]); - (*m_unions[tgt_idx][src_idx])(tgt, src, delta); - } - - /** - If tgt is zero, it is assumed to be a full relation. - */ - void do_destructive_intersection(scoped_rel& tgt, scoped_rel& src) { - if(!src) { - return; - } - if(!tgt) { - tgt=src.release(); - return; - } - do_intersection(*tgt, *src); - src = 0; - } - - void do_intersection(relation_base& tgt, relation_base& src) { - scoped_ptr intersect_fun = - m_rmgr.mk_filter_by_intersection_fn(tgt, src); - if(!intersect_fun) { - warning_msg("intersection does not exist"); - return; - } - (*intersect_fun)(tgt, src); - } - void do_delta_union(unsigned rel_idx, relation_base& tgt, relation_base& src) { - scoped_ptr union_fun = m_rmgr.mk_union_fn(tgt, src); - SASSERT(union_fun); - (*union_fun)(tgt, src); - } - public: - aligned_union_fn(product_relation const& tgt, product_relation const& src, product_relation const* delta, - bool is_widen) : - m_rmgr(tgt.get_manager()), - m_is_widen(is_widen) { - SASSERT(vectors_equal(tgt.m_spec, src.m_spec)); - SASSERT(!delta || vectors_equal(tgt.m_spec, delta->m_spec)); - init(tgt.m_relations, src.m_relations, delta ? &delta->m_relations : 0); - } - - ~aligned_union_fn() { - unsigned sz = m_unions.size(); - for(unsigned i=0; i side_results; - ptr_vector side_deltas; - - for (unsigned i = 0; i < num; ++i) { - relation_base& itgt = tgt[i]; - relation_base* idelta = delta ? &(*delta)[i] : 0; - - scoped_rel fresh_delta = idelta ? idelta->get_plugin().mk_empty(*idelta) : 0; - scoped_rel side_result; - scoped_rel side_delta; - - //compute the side unions with which we will intersect the result of the basic one - for (unsigned j = 0; j < num; ++j) { - if (i == j) { - continue; //this is the basic union which we will perform later - } - if (can_do_inner_union(i, j)) { - TRACE("dl", itgt.display(tout << "tgt:\n"); src[j].display(tout << "src:\n");); - // union[i][j] - scoped_rel one_side_union = itgt.clone(); - scoped_rel one_side_delta = fresh_delta ? fresh_delta->clone() : 0; - TRACE("dl", one_side_union->display(tout << "union 1:\n"); src[j].display(tout);); - do_inner_union(i, j, *one_side_union, src[j], one_side_delta.get()); - TRACE("dl", one_side_union->display(tout << "union:\n");); - do_destructive_intersection(side_result, one_side_union); - TRACE("dl", - side_result->display(tout << "inner-union: " << i << " " << j << "\n"); - itgt.display(tout << "tgt:\n");); - if (one_side_delta) { - do_destructive_intersection(side_delta, one_side_delta); - } - - // union[j][i] - one_side_union = src[i].clone(); - one_side_delta = fresh_delta ? fresh_delta->clone() : 0; - TRACE("dl", one_side_union->display(tout << "union 2:\n"); tgt[j].display(tout);); - do_inner_union(i, j, *one_side_union, tgt[j], one_side_delta.get()); - TRACE("dl", one_side_union->display(tout << "union:\n");); - do_destructive_intersection(side_result, one_side_union); - TRACE("dl", - side_result->display(tout << "inner-union: " << i << " " << j << "\n"); - itgt.display(tout << "tgt:\n");); - if (one_side_delta) { - do_destructive_intersection(side_delta, one_side_delta); - } - } - } - side_results.push_back(side_result.release()); - side_deltas.push_back(side_delta.release()); - } - for (unsigned i = 0; i < num; ++i) { - relation_base& itgt = tgt[i]; - relation_base* idelta = delta ? &(*delta)[i] : 0; - scoped_rel fresh_delta = idelta ? idelta->get_plugin().mk_empty(*idelta) : 0; - scoped_rel side_result(side_results[i]); - scoped_rel side_delta(side_deltas[i]); - - // perform the basic union - // assume a relation can always perform union with the relation of the same type - VERIFY(can_do_inner_union(i,i)); - do_inner_union(i, i, itgt, src[i], fresh_delta.get()); - - if (side_result) { - do_intersection(itgt, *side_result); - TRACE("dl", side_result->display(tout << "inner-union-end: " << i << "\n");); - } - if (fresh_delta) { - do_destructive_intersection(fresh_delta,side_delta); - SASSERT(idelta); - do_delta_union(i, *idelta, *fresh_delta); - } - } - if (num == 0) { - //we need to handle product relation of no relations separately - if (!src.m_default_empty && tgt.m_default_empty) { - tgt.m_default_empty = false; - if (delta) { - delta->m_default_empty = false; - } - } - } - TRACE("dl", _tgt.display(tout << "dst':\n"); - if (_delta) _delta->display(tout << "delta:\n"); ;); - } - }; - - class product_relation_plugin::unaligned_union_fn : public relation_union_fn { - bool m_is_widen; - rel_spec m_common_spec; - scoped_ptr m_aligned_union_fun; - public: - unaligned_union_fn(product_relation const& tgt, product_relation const& src, - product_relation const* delta, bool is_widen) : m_is_widen(is_widen) { - ptr_vector rels; - rels.push_back(&tgt); - rels.push_back(&src); - if(delta) { - rels.push_back(delta); - } - get_common_spec(rels, m_common_spec); - } - - - virtual void operator()(relation_base& _tgt, const relation_base& _src, relation_base* _delta) { - TRACE("dl", _tgt.display(tout << "dst:\n"); _src.display(tout << "src:\n");); - product_relation& tgt = get(_tgt); - product_relation const& src0 = get(_src); - product_relation* delta = _delta ? get(_delta) : 0; - - tgt.convert_spec(m_common_spec); - if(delta) { - delta->convert_spec(m_common_spec); - } - scoped_rel src_scoped; - if(src0.get_kind()!=tgt.get_kind()) { - src_scoped = src0.clone(); - src_scoped->convert_spec(m_common_spec); - } - product_relation const& src = src_scoped ? *src_scoped : src0; - - if(!m_aligned_union_fun) { - m_aligned_union_fun = alloc(aligned_union_fn, tgt, src, delta, m_is_widen); - SASSERT(m_aligned_union_fun); - } - (*m_aligned_union_fun)(tgt, src, delta); - TRACE("dl", _tgt.display(tout << "dst':\n"); - if (_delta) _delta->display(tout << "delta:\n");); - } - }; - - class product_relation_plugin::single_non_transparent_src_union_fn : public relation_union_fn { - unsigned m_single_rel_idx; - scoped_ptr m_inner_union_fun; - public: - single_non_transparent_src_union_fn(unsigned single_rel_idx, relation_union_fn* inner_union_fun) - : m_single_rel_idx(single_rel_idx), - m_inner_union_fun(inner_union_fun) {} - - virtual void operator()(relation_base& tgt, const relation_base& _src, relation_base* delta) { - product_relation const& src = get(_src); - (*m_inner_union_fun)(tgt, src[m_single_rel_idx], delta); - } - }; - - relation_union_fn * product_relation_plugin::mk_union_w_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta, bool is_widen) { - if (check_kind(tgt) && check_kind(src) && (!delta || check_kind(*delta))) { - if(are_aligned(get(tgt), get(src)) && (!delta || are_aligned(get(tgt), *get(delta)))) { - return alloc(aligned_union_fn, get(tgt), get(src), get(delta), is_widen); - } - return alloc(unaligned_union_fn, get(tgt), get(src), get(delta), is_widen); - } - if(check_kind(src)) { - const product_relation & p_src = get(src); - unsigned single_idx; - if(p_src.try_get_single_non_transparent(single_idx)) { - relation_union_fn * inner; - if(is_widen) { - inner = get_manager().mk_widen_fn(tgt, p_src[single_idx], delta); - } - else { - inner = get_manager().mk_union_fn(tgt, p_src[single_idx], delta); - } - if(inner) { - return alloc(single_non_transparent_src_union_fn, single_idx, inner); - } - } - } - return 0; - } - - relation_union_fn * product_relation_plugin::mk_union_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta) { - return mk_union_w_fn(tgt, src, delta, false); - } - - relation_union_fn * product_relation_plugin::mk_widen_fn( - const relation_base & tgt, const relation_base & src, const relation_base * delta) { - return mk_union_w_fn(tgt, src, delta, true); - } - - class product_relation_plugin::mutator_fn : public relation_mutator_fn { - ptr_vector m_mutators; - public: - mutator_fn(unsigned sz, relation_mutator_fn** muts): - m_mutators(sz, muts) {} - - ~mutator_fn() { dealloc_ptr_vector_content(m_mutators); } - - virtual void operator()(relation_base & _r) { - TRACE("dl", _r.display(tout);); - product_relation& r = get(_r); - SASSERT(m_mutators.size() == r.size()); - for (unsigned i = 0; i < r.size(); ++i) { - relation_mutator_fn* m = m_mutators[i]; - if (m) { - (*m)(r[i]); - } - } - TRACE("dl", _r.display(tout);); - } - }; - - - relation_mutator_fn * product_relation_plugin::mk_filter_identical_fn( - const relation_base & _t, unsigned col_cnt, const unsigned * identical_cols) { - - if(is_product_relation(_t)) { - bool found = false; - product_relation const& r = get(_t); - ptr_vector mutators; - for (unsigned i = 0; i < r.size(); ++i) { - relation_mutator_fn* m = get_manager().mk_filter_identical_fn(r[i], col_cnt, identical_cols); - mutators.push_back(m); - if (m) found = true; - } - if (found) { - return alloc(mutator_fn, mutators.size(), mutators.c_ptr()); - } - } - return 0; - } - - relation_mutator_fn * product_relation_plugin::mk_filter_equal_fn(const relation_base & _t, - const relation_element & value, unsigned col) { - if(is_product_relation(_t)) { - product_relation const& r = get(_t); - ptr_vector mutators; - bool found = false; - for (unsigned i = 0; i < r.size(); ++i) { - relation_mutator_fn* m = get_manager().mk_filter_equal_fn(r[i], value, col); - mutators.push_back(m); - if (m) found = true; - } - if (found) { - return alloc(mutator_fn, mutators.size(), mutators.c_ptr()); - } - } - return 0; - } - - class product_relation_plugin::filter_interpreted_fn : public relation_mutator_fn { - ptr_vector m_mutators; - svector > m_attach; - public: - - filter_interpreted_fn(product_relation const& r, app* cond) { - for (unsigned i = 0; i < r.size(); ++i) { - m_mutators.push_back(r.get_manager().mk_filter_interpreted_fn(r[i], cond)); - } - for (unsigned i = 0; i < r.size(); ++i) { - relation_mutator_fn& m1 = *(m_mutators[i]); - for (unsigned j = i + 1; j < r.size(); ++j) { - relation_mutator_fn& m2 = *(m_mutators[j]); - if (m1.supports_attachment(r[j])) { - m_attach.push_back(std::make_pair(i,j)); - } - if (m2.supports_attachment(r[i])) { - m_attach.push_back(std::make_pair(j,i)); - } - } - } - } - - ~filter_interpreted_fn() { dealloc_ptr_vector_content(m_mutators); } - - void operator()(relation_base& _r) { - TRACE("dl", _r.display(tout);); - product_relation const& r = get(_r); - for (unsigned i = 0; i < m_attach.size(); ++i) { - m_mutators[m_attach[i].first]->attach(r[m_attach[i].second]); - } - for (unsigned i = 0; i < m_mutators.size(); ++i) { - (*m_mutators[i])(r[i]); - } - TRACE("dl", _r.display(tout);); - } - }; - - relation_mutator_fn * product_relation_plugin::mk_filter_interpreted_fn(const relation_base & t, app * condition) { - return alloc(filter_interpreted_fn, get(t), condition); - } - - - // ----------------------------------- - // - // product_relation - // - // ----------------------------------- - - product_relation::product_relation(product_relation_plugin& p, relation_signature const& s): - relation_base(p, s), - m_default_empty(true) { - ensure_correct_kind(); - } - - product_relation::product_relation(product_relation_plugin& p, relation_signature const& s, unsigned num_relations, relation_base** relations) : - relation_base(p, s), - m_default_empty(true) { - for (unsigned i = 0; i < num_relations; ++i) { - SASSERT(relations[i]->get_signature()==s); - m_relations.push_back(relations[i]); - } - ensure_correct_kind(); - } - - product_relation::~product_relation() { - unsigned num_relations = m_relations.size(); - for (unsigned i = 0; i < num_relations; ++i) { - m_relations[i]->deallocate(); - } - } - - product_relation_plugin& product_relation::get_plugin() const { - return dynamic_cast(relation_base::get_plugin()); - } - - void product_relation::ensure_correct_kind() { - unsigned rel_cnt = m_relations.size(); - //the rel_cnt==0 part makes us to update the kind also when the relation is newly created - bool spec_changed = rel_cnt!=m_spec.size() || rel_cnt==0; - if(spec_changed) { - m_spec.resize(rel_cnt); - } - for(unsigned i=0;iget_kind(); - if(spec_changed || m_spec[i]!=rkind) { - spec_changed = true; - m_spec[i]=rkind; - } - } - if(spec_changed) { - family_id new_kind = get_plugin().get_relation_kind(*this); - set_kind(new_kind); - } - } - - void product_relation::convert_spec(const rel_spec & spec) { - - func_decl* p = 0; - const relation_signature & sig = get_signature(); - family_id new_kind = get_plugin().get_relation_kind(sig, spec); - if(new_kind==get_kind()) { - return; - } - - unsigned old_sz = size(); - unsigned new_sz = spec.size(); - unsigned old_remain = old_sz; - relation_vector new_rels; - - //the loop is quadratic with the number of relations, maybe we want to fix it - for(unsigned i=0; iget_kind()==ikind) { - irel = m_relations[j]; - m_relations[j] = 0; - old_remain--; - break; - } - } - if(!irel) { - if(old_sz==0 && m_default_empty) { - //The relation didn't contain any inner relations but it was empty, - //so we make the newly added relations empty as well. - irel = get_manager().mk_empty_relation(sig, new_kind); - } - else { - irel = get_manager().mk_full_relation(sig, p, new_kind); - } - } - new_rels.push_back(irel); - } - SASSERT(old_remain==0); //the new specification must be a superset of the old one - m_relations = new_rels; - - set_kind(new_kind); - DEBUG_CODE( - ensure_correct_kind(); - SASSERT(get_kind()==new_kind); - ); - } - - bool product_relation::try_get_single_non_transparent(unsigned & idx) const { - unsigned sz = size(); - bool found = false; - unsigned candidate; - for(unsigned i=0; i relations; - for (unsigned i = 0; i < size(); ++i) { - relations.push_back((*this)[i].clone()); - } - product_relation_plugin& p = get_plugin(); - return alloc(product_relation, p, get_signature(), relations.size(), relations.c_ptr()); - } - - product_relation * product_relation::complement(func_decl*) const { - if(m_relations.empty()) { - product_relation * res = clone(); - res->m_default_empty = !m_default_empty; - return res; - } - UNREACHABLE(); - return 0; - } - - bool product_relation::empty() const { - if(m_relations.empty()) { - return m_default_empty; - } - for (unsigned i = 0; i < m_relations.size(); ++i) { - if (m_relations[i]->empty()) { - return true; - } - } - return false; - } - - void product_relation::to_formula(expr_ref& fml) const { - ast_manager& m = fml.get_manager(); - expr_ref_vector conjs(m); - expr_ref tmp(m); - for (unsigned i = 0; i < m_relations.size(); ++i) { - m_relations[i]->to_formula(tmp); - conjs.push_back(tmp); - } - bool_rewriter(m).mk_and(conjs.size(), conjs.c_ptr(), fml); - } - - void product_relation::display(std::ostream & out) const { - out<<"Product of the following relations:\n"; - for (unsigned i = 0; i < m_relations.size(); ++i) { - m_relations[i]->display(out); - } - } - -}; - - - diff --git a/src/muz/dl_product_relation.h b/src/muz/dl_product_relation.h deleted file mode 100644 index bf37a59d0..000000000 --- a/src/muz/dl_product_relation.h +++ /dev/null @@ -1,190 +0,0 @@ -/*++ -Copyright (c) 2010 Microsoft Corporation - -Module Name: - - dl_product_relation.h - -Abstract: - - A Relation relation combinator. - -Author: - - Nikolaj Bjorner (nbjorner) 2010-4-11 - -Revision History: - ---*/ -#ifndef _DL_PRODUCT_RELATION_H_ -#define _DL_PRODUCT_RELATION_H_ - - -#include "dl_context.h" - -namespace datalog { - - class product_relation; - - class product_relation_plugin : public relation_plugin { - friend class product_relation; - public: - typedef svector rel_spec; - private: - class join_fn; - class transform_fn; - class mutator_fn; - class aligned_union_fn; - class unaligned_union_fn; - class single_non_transparent_src_union_fn; - class filter_equal_fn; - class filter_identical_fn; - class filter_interpreted_fn; - struct fid_hash { - typedef family_id data; - unsigned operator()(data x) const { return static_cast(x); } - }; - - rel_spec_store > m_spec_store; - - family_id get_relation_kind(const product_relation & r); - - bool is_product_relation(relation_base * r) { return r->get_plugin().is_product_relation(); } - - public: - static product_relation_plugin& get_plugin(relation_manager & rmgr); - - product_relation_plugin(relation_manager& m); - - virtual void initialize(family_id fid); - - virtual bool can_handle_signature(const relation_signature & s); - virtual bool can_handle_signature(const relation_signature & s, family_id kind); - - static symbol get_name() { return symbol("product_relation"); } - - family_id get_relation_kind(const relation_signature & sig, const rel_spec & spec); - - virtual relation_base * mk_empty(const relation_signature & s); - virtual relation_base * mk_empty(const relation_signature & s, family_id kind); - - virtual relation_base * mk_full(func_decl* p, const relation_signature & s); - virtual relation_base * mk_full(func_decl* p, const relation_signature & s, family_id kind); - - protected: - virtual relation_join_fn * mk_join_fn(const relation_base & t1, const relation_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2); - virtual relation_transformer_fn * mk_project_fn(const relation_base & t, unsigned col_cnt, - const unsigned * removed_cols); - virtual relation_transformer_fn * mk_rename_fn(const relation_base & t, unsigned permutation_cycle_len, - const unsigned * permutation_cycle); - virtual relation_union_fn * mk_union_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta); - virtual relation_union_fn * mk_widen_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta); - virtual relation_mutator_fn * mk_filter_identical_fn(const relation_base & t, unsigned col_cnt, - const unsigned * identical_cols); - virtual relation_mutator_fn * mk_filter_equal_fn(const relation_base & t, const relation_element & value, - unsigned col); - virtual relation_mutator_fn * mk_filter_interpreted_fn(const relation_base & t, app * condition); - - static bool is_product_relation(relation_base const& r); - - private: - static product_relation& get(relation_base& r); - static product_relation const & get(relation_base const& r); - static product_relation* get(relation_base* r); - static product_relation const* get(relation_base const* r); - - relation_union_fn * mk_union_w_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta, bool is_widen); - - bool are_aligned(const product_relation& r1, const product_relation& r2); - static void get_common_spec(const ptr_vector & rels, rel_spec & res); - }; - - - class product_relation : public relation_base { - friend class product_relation_plugin; - - friend class product_relation_plugin::join_fn; - friend class product_relation_plugin::transform_fn; - friend class product_relation_plugin::mutator_fn; - friend class product_relation_plugin::aligned_union_fn; - friend class product_relation_plugin::unaligned_union_fn; - friend class product_relation_plugin::single_non_transparent_src_union_fn; - friend class product_relation_plugin::filter_equal_fn; - friend class product_relation_plugin::filter_identical_fn; - friend class product_relation_plugin::filter_interpreted_fn; - - - - typedef product_relation_plugin::rel_spec rel_spec; - - /** - If m_relations is empty, value of this determines whether the relation is empty or full. - */ - bool m_default_empty; - - /** - There must not be two relations of the same kind - */ - ptr_vector m_relations; - - /** - Array of kinds of inner relations. - - If two product relations have equal signature and specification, their - m_relations arrays contain corresponding relations at the same indexes. - - The value returned by get_kind() depends uniquely on the specification. - */ - rel_spec m_spec; - - /** - \brief Ensure the kind assigned to this relation reflects the types of inner relations. - */ - void ensure_correct_kind(); - /** - The current specification must be a subset of the new one. - */ - void convert_spec(const rel_spec & spec); - public: - product_relation(product_relation_plugin& p, relation_signature const& s); - product_relation(product_relation_plugin& p, relation_signature const& s, unsigned num_relations, relation_base** relations); - - ~product_relation(); - - virtual bool empty() const; - virtual void add_fact(const relation_fact & f); - virtual bool contains_fact(const relation_fact & f) const; - virtual product_relation * clone() const; - virtual product_relation * complement(func_decl* p) const; - virtual void display(std::ostream & out) const; - virtual void to_formula(expr_ref& fml) const; - product_relation_plugin& get_plugin() const; - - unsigned size() const { return m_relations.size(); } - relation_base& operator[](unsigned i) const { return *m_relations[i]; } - - /** - If all relations except one are sieve_relations with no inner columns, - return true and into \c idx assign index of that relation. Otherwise return - false. - */ - bool try_get_single_non_transparent(unsigned & idx) const; - - virtual bool is_precise() const { - for (unsigned i = 0; i < m_relations.size(); ++i) { - if (!m_relations[i]->is_precise()) { - return false; - } - } - return true; - } - }; - -}; - -#endif - diff --git a/src/muz/dl_relation_manager.cpp b/src/muz/dl_relation_manager.cpp deleted file mode 100644 index 457ef28c0..000000000 --- a/src/muz/dl_relation_manager.cpp +++ /dev/null @@ -1,1702 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - dl_relation_manager.cpp - -Abstract: - - - -Author: - - Krystof Hoder (t-khoder) 2010-09-14. - -Revision History: - ---*/ - - -#include -#include"ast_pp.h" -#include"dl_check_table.h" -#include"dl_context.h" -#include"dl_finite_product_relation.h" -#include"dl_product_relation.h" -#include"dl_sieve_relation.h" -#include"dl_table_relation.h" -#include"dl_relation_manager.h" - -namespace datalog { - - relation_manager::~relation_manager() { - reset(); - } - - - void relation_manager::reset_relations() { - relation_map::iterator it=m_relations.begin(); - relation_map::iterator end=m_relations.end(); - for(;it!=end;++it) { - func_decl * pred = it->m_key; - get_context().get_manager().dec_ref(pred); //inc_ref in get_relation - relation_base * r=(*it).m_value; - r->deallocate(); - } - m_relations.reset(); - } - - void relation_manager::reset() { - reset_relations(); - - m_favourite_table_plugin = static_cast(0); - m_favourite_relation_plugin = static_cast(0); - dealloc_ptr_vector_content(m_table_plugins); - m_table_plugins.reset(); - dealloc_ptr_vector_content(m_relation_plugins); - m_relation_plugins.reset(); - m_next_table_fid = 0; - m_next_relation_fid = 0; - } - - dl_decl_util & relation_manager::get_decl_util() const { - return get_context().get_decl_util(); - } - - family_id relation_manager::get_next_relation_fid(relation_plugin & claimer) { - unsigned res = m_next_relation_fid++; - m_kind2plugin.insert(res, &claimer); - return res; - } - - void relation_manager::set_predicate_kind(func_decl * pred, family_id kind) { - SASSERT(!m_relations.contains(pred)); - m_pred_kinds.insert(pred, kind); - } - - family_id relation_manager::get_requested_predicate_kind(func_decl * pred) { - family_id res; - if(m_pred_kinds.find(pred, res)) { - return res; - } - else { - return null_family_id; - } - } - - relation_base & relation_manager::get_relation(func_decl * pred) { - relation_base * res = try_get_relation(pred); - if(!res) { - relation_signature sig; - from_predicate(pred, sig); - family_id rel_kind = get_requested_predicate_kind(pred); - res = mk_empty_relation(sig, rel_kind); - store_relation(pred, res); - } - return *res; - } - - relation_base * relation_manager::try_get_relation(func_decl * pred) const { - relation_base * res = 0; - if(!m_relations.find(pred, res)) { - return 0; - } - SASSERT(res); - return res; - } - - void relation_manager::store_relation(func_decl * pred, relation_base * rel) { - SASSERT(rel); - relation_map::entry * e = m_relations.insert_if_not_there2(pred, 0); - if (e->get_data().m_value) { - e->get_data().m_value->deallocate(); - } - else { - get_context().get_manager().inc_ref(pred); //dec_ref in reset - } - e->get_data().m_value = rel; - } - - void relation_manager::collect_non_empty_predicates(decl_set & res) const { - relation_map::iterator it = m_relations.begin(); - relation_map::iterator end = m_relations.end(); - for(; it!=end; ++it) { - if(!it->m_value->empty()) { - res.insert(it->m_key); - } - } - } - - void relation_manager::restrict_predicates(const decl_set & preds) { - typedef ptr_vector fd_vector; - fd_vector to_remove; - - relation_map::iterator rit = m_relations.begin(); - relation_map::iterator rend = m_relations.end(); - for(; rit!=rend; ++rit) { - func_decl * pred = rit->m_key; - if (!preds.contains(pred)) { - to_remove.insert(pred); - } - } - - fd_vector::iterator pit = to_remove.begin(); - fd_vector::iterator pend = to_remove.end(); - for(; pit!=pend; ++pit) { - func_decl * pred = *pit; - relation_base * rel; - VERIFY( m_relations.find(pred, rel) ); - rel->deallocate(); - m_relations.remove(pred); - get_context().get_manager().dec_ref(pred); - } - - set_intersection(m_saturated_rels, preds); - } - - void relation_manager::register_plugin(table_plugin * plugin) { - plugin->initialize(get_next_table_fid()); - m_table_plugins.push_back(plugin); - - if(plugin->get_name()==get_context().default_table()) { - m_favourite_table_plugin = plugin; - } - - table_relation_plugin * tr_plugin = alloc(table_relation_plugin, *plugin, *this); - register_relation_plugin_impl(tr_plugin); - m_table_relation_plugins.insert(plugin, tr_plugin); - - symbol checker_name = get_context().default_table_checker(); - if(get_context().default_table_checked() && get_table_plugin(checker_name)) { - if( m_favourite_table_plugin && - (plugin==m_favourite_table_plugin || plugin->get_name()==checker_name) ) { - symbol checked_name = get_context().default_table(); - //the plugins we need to create the checking plugin were just added - SASSERT(m_favourite_table_plugin->get_name()==get_context().default_table()); - table_plugin * checking_plugin = alloc(check_table_plugin, *this, checker_name, checked_name); - register_plugin(checking_plugin); - m_favourite_table_plugin = checking_plugin; - } - if(m_favourite_relation_plugin && m_favourite_relation_plugin->from_table()) { - table_relation_plugin * fav_rel_plugin = - static_cast(m_favourite_relation_plugin); - if(&fav_rel_plugin->get_table_plugin()==plugin || plugin->get_name()==checker_name) { - //the plugins we need to create the checking table_relation_plugin were just added - SASSERT(m_favourite_relation_plugin->get_name() == - get_context().default_relation()); - symbol checked_name = fav_rel_plugin->get_table_plugin().get_name(); - table_plugin * checking_plugin = alloc(check_table_plugin, *this, checker_name, checked_name); - register_plugin(checking_plugin); - - table_relation_plugin * checking_tr_plugin = - alloc(table_relation_plugin, *checking_plugin, *this); - register_relation_plugin_impl(checking_tr_plugin); - m_table_relation_plugins.insert(checking_plugin, checking_tr_plugin); - m_favourite_relation_plugin = checking_tr_plugin; - } - } - } - - } - - void relation_manager::register_relation_plugin_impl(relation_plugin * plugin) { - m_relation_plugins.push_back(plugin); - plugin->initialize(get_next_relation_fid(*plugin)); - if (plugin->get_name() == get_context().default_relation()) { - m_favourite_relation_plugin = plugin; - } - if(plugin->is_finite_product_relation()) { - finite_product_relation_plugin * fprp = static_cast(plugin); - relation_plugin * inner = &fprp->get_inner_plugin(); - m_finite_product_relation_plugins.insert(inner, fprp); - } - } - - relation_plugin * relation_manager::try_get_appropriate_plugin(const relation_signature & s) { - if(m_favourite_relation_plugin && m_favourite_relation_plugin->can_handle_signature(s)) { - return m_favourite_relation_plugin; - } - relation_plugin_vector::iterator rpit = m_relation_plugins.begin(); - relation_plugin_vector::iterator rpend = m_relation_plugins.end(); - for(; rpit!=rpend; ++rpit) { - if((*rpit)->can_handle_signature(s)) { - return *rpit; - } - } - return 0; - } - - relation_plugin & relation_manager::get_appropriate_plugin(const relation_signature & s) { - relation_plugin * res = try_get_appropriate_plugin(s); - if (!res) { - throw default_exception("no suitable plugin found for given relation signature"); - } - return *res; - } - - table_plugin * relation_manager::try_get_appropriate_plugin(const table_signature & t) { - if (m_favourite_table_plugin && m_favourite_table_plugin->can_handle_signature(t)) { - return m_favourite_table_plugin; - } - table_plugin_vector::iterator tpit = m_table_plugins.begin(); - table_plugin_vector::iterator tpend = m_table_plugins.end(); - for(; tpit!=tpend; ++tpit) { - if((*tpit)->can_handle_signature(t)) { - return *tpit; - } - } - return 0; - } - - table_plugin & relation_manager::get_appropriate_plugin(const table_signature & t) { - table_plugin * res = try_get_appropriate_plugin(t); - if(!res) { - throw default_exception("no suitable plugin found for given table signature"); - } - return *res; - } - - relation_plugin * relation_manager::get_relation_plugin(symbol const& s) { - relation_plugin_vector::iterator rpit = m_relation_plugins.begin(); - relation_plugin_vector::iterator rpend = m_relation_plugins.end(); - for(; rpit!=rpend; ++rpit) { - if((*rpit)->get_name()==s) { - return *rpit; - } - } - return 0; - } - - relation_plugin & relation_manager::get_relation_plugin(family_id kind) { - SASSERT(kind>=0); - SASSERT(kindget_name()==k) { - return *tpit; - } - } - return 0; - } - - table_relation_plugin & relation_manager::get_table_relation_plugin(table_plugin & tp) { - table_relation_plugin * res; - VERIFY( m_table_relation_plugins.find(&tp, res) ); - return *res; - } - - bool relation_manager::try_get_finite_product_relation_plugin(const relation_plugin & inner, - finite_product_relation_plugin * & res) { - return m_finite_product_relation_plugins.find(&inner, res); - } - - table_base * relation_manager::mk_empty_table(const table_signature & s) { - return get_appropriate_plugin(s).mk_empty(s); - } - - - bool relation_manager::is_non_explanation(relation_signature const& s) const { - dl_decl_util & decl_util = get_context().get_decl_util(); - unsigned n = s.size(); - for(unsigned i = 0; i < n; i++) { - if(decl_util.is_rule_sort(s[i])) { - return false; - } - } - return true; - } - - relation_base * relation_manager::mk_empty_relation(const relation_signature & s, func_decl* pred) { - return mk_empty_relation(s, get_requested_predicate_kind(pred)); - } - - relation_base * relation_manager::mk_empty_relation(const relation_signature & s, family_id kind) { - if (kind != null_family_id) { - relation_plugin & plugin = get_relation_plugin(kind); - if (plugin.can_handle_signature(s, kind)) - return plugin.mk_empty(s, kind); - } - relation_base * res; - relation_plugin* p = m_favourite_relation_plugin; - - if (p && p->can_handle_signature(s)) { - return p->mk_empty(s); - } - - if (mk_empty_table_relation(s, res)) { - return res; - } - - for (unsigned i = 0; i < m_relation_plugins.size(); ++i) { - p = m_relation_plugins[i]; - if (p->can_handle_signature(s)) { - return p->mk_empty(s); - } - } - - //If there is no plugin to handle the signature, we just create an empty product relation and - //stuff will be added to it by later operations. - return product_relation_plugin::get_plugin(*this).mk_empty(s); - } - - - relation_base * relation_manager::mk_table_relation(const relation_signature & s, table_base * table) { - SASSERT(s.size()==table->get_signature().size()); - return get_table_relation_plugin(table->get_plugin()).mk_from_table(s, table); - } - - bool relation_manager::mk_empty_table_relation(const relation_signature & s, relation_base * & result) { - table_signature tsig; - if(!relation_signature_to_table(s, tsig)) { - return false; - } - table_base * table = mk_empty_table(tsig); - result = mk_table_relation(s, table); - return true; - } - - - relation_base * relation_manager::mk_full_relation(const relation_signature & s, func_decl* p, family_id kind) { - if (kind != null_family_id) { - relation_plugin & plugin = get_relation_plugin(kind); - if (plugin.can_handle_signature(s, kind)) { - return plugin.mk_full(p, s, kind); - } - } - return get_appropriate_plugin(s).mk_full(p, s, null_family_id); - } - - relation_base * relation_manager::mk_full_relation(const relation_signature & s, func_decl* pred) { - family_id kind = get_requested_predicate_kind(pred); - return mk_full_relation(s, pred, kind); - } - - void relation_manager::relation_to_table(const relation_sort & sort, const relation_element & from, - table_element & to) { - SASSERT(from->get_num_args()==0); - VERIFY(get_context().get_decl_util().is_numeral_ext(from, to)); - } - - void relation_manager::table_to_relation(const relation_sort & sort, const table_element & from, - relation_element & to) { - to = get_decl_util().mk_numeral(from, sort); - } - - void relation_manager::table_to_relation(const relation_sort & sort, const table_element & from, - relation_element_ref & to) { - relation_element rel_el; - table_to_relation(sort, from, rel_el); - to = rel_el; - } - - void relation_manager::table_to_relation(const relation_sort & sort, const table_element & from, - const relation_fact::el_proxy & to) { - relation_element rel_el; - table_to_relation(sort, from, rel_el); - to = rel_el; - } - - bool relation_manager::relation_sort_to_table(const relation_sort & from, table_sort & to) { - return get_context().get_decl_util().try_get_size(from, to); - } - - void relation_manager::from_predicate(func_decl * pred, unsigned arg_index, relation_sort & result) { - result = pred->get_domain(arg_index); - } - - void relation_manager::from_predicate(func_decl * pred, relation_signature & result) { - result.reset(); - unsigned arg_num=pred->get_arity(); - for(unsigned i=0;iset_cancel(f); - } - } - - std::string relation_manager::to_nice_string(const relation_element & el) const { - uint64 val; - std::stringstream stm; - if(get_context().get_decl_util().is_numeral_ext(el, val)) { - stm << val; - } - else { - stm << mk_pp(el, get_context().get_manager()); - } - return stm.str(); - } - - std::string relation_manager::to_nice_string(const relation_sort & s, const relation_element & el) const { - std::stringstream stm; - uint64 val; - if(get_context().get_decl_util().is_numeral_ext(el, val)) { - get_context().print_constant_name(s, val, stm); - } - else { - stm << mk_pp(el, get_context().get_manager()); - } - return stm.str(); - } - - std::string relation_manager::to_nice_string(const relation_sort & s) const { - return std::string(s->get_name().bare_str()); - } - - std::string relation_manager::to_nice_string(const relation_signature & s) const { - std::string res("["); - bool first = true; - relation_signature::const_iterator it = s.begin(); - relation_signature::const_iterator end = s.end(); - for(; it!=end; ++it) { - if(first) { - first = false; - } - else { - res+=','; - } - res+=to_nice_string(*it); - } - res+=']'; - - return res; - } - - void relation_manager::display(std::ostream & out) const { - relation_map::iterator it=m_relations.begin(); - relation_map::iterator end=m_relations.end(); - for(;it!=end;++it) { - out << "Table " << it->m_key->get_name() << "\n"; - it->m_value->display(out); - } - } - - void relation_manager::display_relation_sizes(std::ostream & out) const { - relation_map::iterator it=m_relations.begin(); - relation_map::iterator end=m_relations.end(); - for(;it!=end;++it) { - out << "Relation " << it->m_key->get_name() << " has size " - << it->m_value->get_size_estimate_rows() << "\n"; - } - } - - void relation_manager::display_output_tables(rule_set const& rules, std::ostream & out) const { - const decl_set & output_preds = rules.get_output_predicates(); - decl_set::iterator it=output_preds.begin(); - decl_set::iterator end=output_preds.end(); - for(; it!=end; ++it) { - func_decl * pred = *it; - relation_base * rel = try_get_relation(pred); - if(!rel) { - out << "Tuples in " << pred->get_name() << ": \n"; - continue; - } - rel->display_tuples(*pred, out); - } - } - - - // ----------------------------------- - // - // relation operations - // - // ----------------------------------- - - class relation_manager::empty_signature_relation_join_fn : public relation_join_fn { - public: - virtual relation_base * operator()(const relation_base & r1, const relation_base & r2) { - TRACE("dl", tout << r1.get_plugin().get_name() << " " << r2.get_plugin().get_name() << "\n";); - if(r1.get_signature().empty()) { - if(r1.empty()) { - return r2.get_manager().mk_empty_relation(r2.get_signature(), r2.get_kind()); - } - else { - return r2.clone(); - } - } - else { - SASSERT(r2.get_signature().empty()); - if(r2.empty()) { - return r1.get_manager().mk_empty_relation(r1.get_signature(), r1.get_kind()); - } - else { - return r1.clone(); - } - } - } - }; - - relation_join_fn * relation_manager::mk_join_fn(const relation_base & t1, const relation_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2, bool allow_product_relation) { - relation_plugin * p1 = &t1.get_plugin(); - relation_plugin * p2 = &t2.get_plugin(); - - relation_join_fn * res = p1->mk_join_fn(t1, t2, col_cnt, cols1, cols2); - if(!res && p1!=p2) { - res = p2->mk_join_fn(t1, t2, col_cnt, cols1, cols2); - } - - if(!res && (t1.get_signature().empty() || t2.get_signature().empty())) { - res = alloc(empty_signature_relation_join_fn); - } - - finite_product_relation_plugin * fprp; - if(!res && p1->from_table() && try_get_finite_product_relation_plugin(*p2, fprp)) { - //we downcast here to relation_plugin so that we don't have to declare - //relation_manager as a friend class of finite_product_relation_plugin - res = static_cast(fprp)->mk_join_fn(t1, t2, col_cnt, cols1, cols2); - } - if(!res && p2->from_table() && try_get_finite_product_relation_plugin(*p1, fprp)) { - res = static_cast(fprp)->mk_join_fn(t1, t2, col_cnt, cols1, cols2); - } - - if(!res && allow_product_relation) { - relation_plugin & product_plugin = product_relation_plugin::get_plugin(*this); - res = product_plugin.mk_join_fn(t1, t2, col_cnt, cols1, cols2); - } - - return res; - } - - relation_transformer_fn * relation_manager::mk_project_fn(const relation_base & t, unsigned col_cnt, - const unsigned * removed_cols) { - return t.get_plugin().mk_project_fn(t, col_cnt, removed_cols); - } - - class relation_manager::default_relation_filter_interpreted_and_project_fn : public relation_transformer_fn { - scoped_ptr m_filter; - scoped_ptr m_project; - unsigned_vector m_removed_cols; - public: - /** - This constructor should be used only if we know that the projection operation - exists for the result of the join. - */ - default_relation_filter_interpreted_and_project_fn( - relation_mutator_fn* filter, - unsigned removed_col_cnt, - const unsigned * removed_cols) - : m_filter(filter), - m_project(0), - m_removed_cols(removed_col_cnt, removed_cols) {} - - virtual relation_base * operator()(const relation_base & t) { - scoped_rel t1 = t.clone(); - (*m_filter)(*t1); - if( !m_project) { - relation_manager & rmgr = t1->get_plugin().get_manager(); - m_project = rmgr.mk_project_fn(*t1, m_removed_cols.size(), m_removed_cols.c_ptr()); - if (!m_project) { - throw default_exception("projection does not exist"); - } - } - return (*m_project)(*t1); - } - }; - - relation_transformer_fn * relation_manager::mk_filter_interpreted_and_project_fn( - const relation_base & t, app * condition, - unsigned removed_col_cnt, const unsigned * removed_cols) { - - relation_transformer_fn* res = - t.get_plugin().mk_filter_interpreted_and_project_fn( - t, - condition, - removed_col_cnt, - removed_cols); - - if (!res) { - relation_mutator_fn* filter_fn = mk_filter_interpreted_fn(t, condition); - if (filter_fn) { - res = alloc(default_relation_filter_interpreted_and_project_fn, - filter_fn, - removed_col_cnt, - removed_cols); - } - } - return res; - } - - - class relation_manager::default_relation_join_project_fn : public relation_join_fn { - scoped_ptr m_join; - scoped_ptr m_project; - - unsigned_vector m_removed_cols; - public: - /** - This constructor should be used only if we know that the projection operation - exists for the result of the join. - */ - default_relation_join_project_fn(join_fn * join, unsigned removed_col_cnt, - const unsigned * removed_cols) - : m_join(join), m_project(0), m_removed_cols(removed_col_cnt, removed_cols) {} - - virtual relation_base * operator()(const relation_base & t1, const relation_base & t2) { - scoped_rel aux = (*m_join)(t1, t2); - if(!m_project) { - relation_manager & rmgr = aux->get_plugin().get_manager(); - m_project = rmgr.mk_project_fn(*aux, m_removed_cols.size(), m_removed_cols.c_ptr()); - if(!m_project) { - throw default_exception("projection does not exist"); - } - } - relation_base * res = (*m_project)(*aux); - return res; - } - }; - - - relation_join_fn * relation_manager::mk_join_project_fn(const relation_base & t1, const relation_base & t2, - unsigned joined_col_cnt, const unsigned * cols1, const unsigned * cols2, - unsigned removed_col_cnt, const unsigned * removed_cols, bool allow_product_relation_join) { - relation_join_fn * res = t1.get_plugin().mk_join_project_fn(t1, t2, joined_col_cnt, cols1, cols2, - removed_col_cnt, removed_cols); - if(!res && &t1.get_plugin()!=&t2.get_plugin()) { - res = t2.get_plugin().mk_join_project_fn(t1, t2, joined_col_cnt, cols1, cols2, removed_col_cnt, - removed_cols); - } - if(!res) { - relation_join_fn * join = mk_join_fn(t1, t2, joined_col_cnt, cols1, cols2, allow_product_relation_join); - if(join) { - res = alloc(default_relation_join_project_fn, join, removed_col_cnt, removed_cols); - } - } - return res; - - } - - relation_transformer_fn * relation_manager::mk_rename_fn(const relation_base & t, unsigned permutation_cycle_len, - const unsigned * permutation_cycle) { - return t.get_plugin().mk_rename_fn(t, permutation_cycle_len, permutation_cycle); - } - - relation_transformer_fn * relation_manager::mk_permutation_rename_fn(const relation_base & t, - const unsigned * permutation) { - relation_transformer_fn * res = t.get_plugin().mk_permutation_rename_fn(t, permutation); - if(!res) { - res = alloc(default_relation_permutation_rename_fn, t, permutation); - } - return res; - } - - - relation_union_fn * relation_manager::mk_union_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta) { - relation_union_fn * res = tgt.get_plugin().mk_union_fn(tgt, src, delta); - if(!res && &tgt.get_plugin()!=&src.get_plugin()) { - res = src.get_plugin().mk_union_fn(tgt, src, delta); - } - if(!res && delta && &tgt.get_plugin()!=&delta->get_plugin() && &src.get_plugin()!=&delta->get_plugin()) { - res = delta->get_plugin().mk_union_fn(tgt, src, delta); - } - return res; - } - - relation_union_fn * relation_manager::mk_widen_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta) { - relation_union_fn * res = tgt.get_plugin().mk_widen_fn(tgt, src, delta); - if(!res && &tgt.get_plugin()!=&src.get_plugin()) { - res = src.get_plugin().mk_widen_fn(tgt, src, delta); - } - if(!res && delta && &tgt.get_plugin()!=&delta->get_plugin() && &src.get_plugin()!=&delta->get_plugin()) { - res = delta->get_plugin().mk_widen_fn(tgt, src, delta); - } - if(!res) { - res = mk_union_fn(tgt, src, delta); - } - return res; - } - - relation_mutator_fn * relation_manager::mk_filter_identical_fn(const relation_base & t, unsigned col_cnt, - const unsigned * identical_cols) { - return t.get_plugin().mk_filter_identical_fn(t, col_cnt, identical_cols); - } - - relation_mutator_fn * relation_manager::mk_filter_equal_fn(const relation_base & t, - const relation_element & value, unsigned col) { - - return t.get_plugin().mk_filter_equal_fn(t, value, col); - } - - relation_mutator_fn * relation_manager::mk_filter_interpreted_fn(const relation_base & t, app * condition) { - return t.get_plugin().mk_filter_interpreted_fn(t, condition); - } - - class relation_manager::default_relation_select_equal_and_project_fn : public relation_transformer_fn { - scoped_ptr m_filter; - scoped_ptr m_project; - public: - default_relation_select_equal_and_project_fn(relation_mutator_fn * filter, relation_transformer_fn * project) - : m_filter(filter), m_project(project) {} - - virtual relation_base * operator()(const relation_base & t1) { - TRACE("dl", tout << t1.get_plugin().get_name() << "\n";); - scoped_rel aux = t1.clone(); - (*m_filter)(*aux); - relation_base * res = (*m_project)(*aux); - return res; - } - }; - - relation_transformer_fn * relation_manager::mk_select_equal_and_project_fn(const relation_base & t, - const relation_element & value, unsigned col) { - relation_transformer_fn * res = t.get_plugin().mk_select_equal_and_project_fn(t, value, col); - if(!res) { - relation_mutator_fn * selector = mk_filter_equal_fn(t, value, col); - if(selector) { - relation_transformer_fn * projector = mk_project_fn(t, 1, &col); - if(projector) { - res = alloc(default_relation_select_equal_and_project_fn, selector, projector); - } - else { - dealloc(selector); - } - } - } - return res; - } - - - class relation_manager::default_relation_intersection_filter_fn : public relation_intersection_filter_fn { - scoped_ptr m_join_fun; - scoped_ptr m_union_fun; - public: - - default_relation_intersection_filter_fn(relation_join_fn * join_fun, relation_union_fn * union_fun) - : m_join_fun(join_fun), m_union_fun(union_fun) {} - - virtual void operator()(relation_base & tgt, const relation_base & intersected_obj) { - scoped_rel filtered_rel = (*m_join_fun)(tgt, intersected_obj); - TRACE("dl", - tgt.display(tout << "tgt:\n"); - intersected_obj.display(tout << "intersected:\n"); - filtered_rel->display(tout << "filtered:\n"); - ); - if(!m_union_fun) { - SASSERT(tgt.can_swap(*filtered_rel)); - tgt.swap(*filtered_rel); - } - tgt.reset(); - TRACE("dl", tgt.display(tout << "target reset:\n"); ); - (*m_union_fun)(tgt, *filtered_rel); - TRACE("dl", tgt.display(tout << "intersected target:\n"); ); - } - - }; - - relation_intersection_filter_fn * relation_manager::try_mk_default_filter_by_intersection_fn( - const relation_base & tgt, const relation_base & src, unsigned joined_col_cnt, - const unsigned * tgt_cols, const unsigned * src_cols) { - TRACE("dl_verbose", tout << tgt.get_plugin().get_name() << "\n";); - unsigned_vector join_removed_cols; - add_sequence(tgt.get_signature().size(), src.get_signature().size(), join_removed_cols); - scoped_rel join_fun = mk_join_project_fn(tgt, src, joined_col_cnt, tgt_cols, src_cols, - join_removed_cols.size(), join_removed_cols.c_ptr(), false); - if(!join_fun) { - return 0; - } - //we perform the join operation here to see what the result is - scoped_rel join_res = (*join_fun)(tgt, src); - if(tgt.can_swap(*join_res)) { - return alloc(default_relation_intersection_filter_fn, join_fun.release(), 0); - } - if(join_res->get_plugin().is_product_relation()) { - //we cannot have the product relation here, since it uses the intersection operation - //for unions and therefore we would get into an infinite recursion - return 0; - } - scoped_rel union_fun = mk_union_fn(tgt, *join_res); - if(!union_fun) { - return 0; - } - return alloc(default_relation_intersection_filter_fn, join_fun.release(), union_fun.release()); - } - - - relation_intersection_filter_fn * relation_manager::mk_filter_by_intersection_fn(const relation_base & t, - const relation_base & src, unsigned joined_col_cnt, const unsigned * t_cols, const unsigned * src_cols) { - TRACE("dl_verbose", tout << t.get_plugin().get_name() << "\n";); - relation_intersection_filter_fn * res = t.get_plugin().mk_filter_by_intersection_fn(t, src, joined_col_cnt, - t_cols, src_cols); - if(!res && &t.get_plugin()!=&src.get_plugin()) { - res = src.get_plugin().mk_filter_by_intersection_fn(t, src, joined_col_cnt, t_cols, src_cols); - } - if(!res) { - res = try_mk_default_filter_by_intersection_fn(t, src, joined_col_cnt, t_cols, src_cols); - } - return res; - } - - relation_intersection_filter_fn * relation_manager::mk_filter_by_intersection_fn(const relation_base & tgt, - const relation_base & src) { - TRACE("dl_verbose", tout << tgt.get_plugin().get_name() << "\n";); - SASSERT(tgt.get_signature()==src.get_signature()); - unsigned sz = tgt.get_signature().size(); - unsigned_vector cols; - add_sequence(0, sz, cols); - return mk_filter_by_intersection_fn(tgt, src, cols, cols); - } - - - relation_intersection_filter_fn * relation_manager::mk_filter_by_negation_fn(const relation_base & t, - const relation_base & negated_obj, unsigned joined_col_cnt, - const unsigned * t_cols, const unsigned * negated_cols) { - TRACE("dl", tout << t.get_plugin().get_name() << "\n";); - relation_intersection_filter_fn * res = t.get_plugin().mk_filter_by_negation_fn(t, negated_obj, joined_col_cnt, - t_cols, negated_cols); - if(!res && &t.get_plugin()!=&negated_obj.get_plugin()) { - res = negated_obj.get_plugin().mk_filter_by_negation_fn(t, negated_obj, joined_col_cnt, t_cols, - negated_cols); - } - return res; - } - - - - - - // ----------------------------------- - // - // table operations - // - // ----------------------------------- - - class relation_manager::default_table_join_fn : public convenient_table_join_fn { - unsigned m_col_cnt; - public: - default_table_join_fn(const table_signature & t1_sig, const table_signature & t2_sig, unsigned col_cnt, - const unsigned * cols1, const unsigned * cols2) - : convenient_table_join_fn(t1_sig, t2_sig, col_cnt, cols1, cols2), m_col_cnt(col_cnt) {} - - virtual table_base * operator()(const table_base & t1, const table_base & t2) { - table_plugin * plugin = &t1.get_plugin(); - - const table_signature & res_sign = get_result_signature(); - if (!plugin->can_handle_signature(res_sign)) { - plugin = &t2.get_plugin(); - if (!plugin->can_handle_signature(res_sign)) { - plugin = &t1.get_manager().get_appropriate_plugin(res_sign); - } - } - SASSERT(plugin->can_handle_signature(res_sign)); - table_base * res = plugin->mk_empty(res_sign); - - unsigned t1cols = t1.get_signature().size(); - unsigned t2cols = t2.get_signature().size(); - unsigned t1first_func = t1.get_signature().first_functional(); - unsigned t2first_func = t2.get_signature().first_functional(); - - table_base::iterator els1it = t1.begin(); - table_base::iterator els1end = t1.end(); - table_base::iterator els2end = t2.end(); - - table_fact acc; - - for(; els1it!=els1end; ++els1it) { - const table_base::row_interface & row1 = *els1it; - - table_base::iterator els2it = t2.begin(); - for(; els2it!=els2end; ++els2it) { - const table_base::row_interface & row2 = *els2it; - - bool match=true; - for(unsigned i=0; iadd_fact(acc); - } - } - return res; - } - }; - - table_join_fn * relation_manager::mk_join_fn(const table_base & t1, const table_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) { - table_join_fn * res = t1.get_plugin().mk_join_fn(t1, t2, col_cnt, cols1, cols2); - if(!res && &t1.get_plugin()!=&t2.get_plugin()) { - res = t2.get_plugin().mk_join_fn(t1, t2, col_cnt, cols1, cols2); - } - if(!res) { - table_signature sig; - table_signature::from_join(t1.get_signature(), t2.get_signature(), - col_cnt, cols1, cols2, sig); - res = alloc(default_table_join_fn, t1.get_signature(), t2.get_signature(), col_cnt, cols1, cols2); - } - return res; - } - - - class relation_manager::auxiliary_table_transformer_fn { - table_fact m_row; - public: - virtual ~auxiliary_table_transformer_fn() {} - virtual const table_signature & get_result_signature() const = 0; - virtual void modify_fact(table_fact & f) const = 0; - - table_base * operator()(const table_base & t) { - table_plugin & plugin = t.get_plugin(); - const table_signature & res_sign = get_result_signature(); - SASSERT(plugin.can_handle_signature(res_sign)); - table_base * res = plugin.mk_empty(res_sign); - - table_base::iterator it = t.begin(); - table_base::iterator end = t.end(); - - for(; it!=end; ++it) { - it->get_fact(m_row); - modify_fact(m_row); - res->add_fact(m_row); - } - return res; - } - }; - - class relation_manager::default_table_project_fn - : public convenient_table_project_fn, auxiliary_table_transformer_fn { - public: - default_table_project_fn(const table_signature & orig_sig, unsigned removed_col_cnt, - const unsigned * removed_cols) - : convenient_table_project_fn(orig_sig, removed_col_cnt, removed_cols) { - SASSERT(removed_col_cnt>0); - } - - virtual const table_signature & get_result_signature() const { - return convenient_table_project_fn::get_result_signature(); - } - - virtual void modify_fact(table_fact & f) const { - project_out_vector_columns(f, m_removed_cols); - } - - virtual table_base * operator()(const table_base & t) { - return auxiliary_table_transformer_fn::operator()(t); - } - }; - - class relation_manager::null_signature_table_project_fn : public table_transformer_fn { - const table_signature m_empty_sig; - public: - null_signature_table_project_fn() : m_empty_sig() {} - virtual table_base * operator()(const table_base & t) { - relation_manager & m = t.get_plugin().get_manager(); - table_base * res = m.mk_empty_table(m_empty_sig); - if(!t.empty()) { - table_fact el; - res->add_fact(el); - } - return res; - } - }; - - - - table_transformer_fn * relation_manager::mk_project_fn(const table_base & t, unsigned col_cnt, - const unsigned * removed_cols) { - table_transformer_fn * res = t.get_plugin().mk_project_fn(t, col_cnt, removed_cols); - if(!res && col_cnt==t.get_signature().size()) { - //all columns are projected out - res = alloc(null_signature_table_project_fn); - } - if(!res) { - res = alloc(default_table_project_fn, t.get_signature(), col_cnt, removed_cols); - } - return res; - } - - - class relation_manager::default_table_join_project_fn : public convenient_table_join_project_fn { - scoped_ptr m_join; - scoped_ptr m_project; - - unsigned_vector m_removed_cols; - public: - default_table_join_project_fn(join_fn * join, const table_base & t1, const table_base & t2, - unsigned joined_col_cnt, const unsigned * cols1, const unsigned * cols2, unsigned removed_col_cnt, - const unsigned * removed_cols) - : convenient_table_join_project_fn(t1.get_signature(), t2.get_signature(), joined_col_cnt, cols1, - cols2, removed_col_cnt, removed_cols), - m_join(join), - m_removed_cols(removed_col_cnt, removed_cols) {} - - class unreachable_reducer : public table_row_pair_reduce_fn { - virtual void operator()(table_element * func_columns, const table_element * merged_func_columns) { - //we do project_with_reduce only if we are sure there will be no reductions - //(see code of the table_signature::from_join_project function) - UNREACHABLE(); - } - }; - - virtual table_base * operator()(const table_base & t1, const table_base & t2) { - table_base * aux = (*m_join)(t1, t2); - if(m_project==0) { - relation_manager & rmgr = aux->get_plugin().get_manager(); - if(get_result_signature().functional_columns()!=0) { - //to preserve functional columns we need to do the project_with_reduction - unreachable_reducer * reducer = alloc(unreachable_reducer); - m_project = rmgr.mk_project_with_reduce_fn(*aux, m_removed_cols.size(), m_removed_cols.c_ptr(), reducer); - } - else { - m_project = rmgr.mk_project_fn(*aux, m_removed_cols); - } - if(!m_project) { - throw default_exception("projection for table does not exist"); - } - } - table_base * res = (*m_project)(*aux); - aux->deallocate(); - return res; - } - }; - - table_join_fn * relation_manager::mk_join_project_fn(const table_base & t1, const table_base & t2, - unsigned joined_col_cnt, const unsigned * cols1, const unsigned * cols2, - unsigned removed_col_cnt, const unsigned * removed_cols) { - table_join_fn * res = t1.get_plugin().mk_join_project_fn(t1, t2, joined_col_cnt, cols1, cols2, - removed_col_cnt, removed_cols); - if(!res && &t1.get_plugin()!=&t2.get_plugin()) { - res = t2.get_plugin().mk_join_project_fn(t1, t2, joined_col_cnt, cols1, cols2, removed_col_cnt, - removed_cols); - } - if(!res) { - table_join_fn * join = mk_join_fn(t1, t2, joined_col_cnt, cols1, cols2); - if(join) { - res = alloc(default_table_join_project_fn, join, t1, t2, joined_col_cnt, cols1, cols2, - removed_col_cnt, removed_cols); - } - } - return res; - - } - - class relation_manager::default_table_rename_fn - : public convenient_table_rename_fn, auxiliary_table_transformer_fn { - public: - default_table_rename_fn(const table_signature & orig_sig, unsigned permutation_cycle_len, - const unsigned * permutation_cycle) - : convenient_table_rename_fn(orig_sig, permutation_cycle_len, permutation_cycle) { - SASSERT(permutation_cycle_len>=2); - } - - virtual const table_signature & get_result_signature() const { - return convenient_table_rename_fn::get_result_signature(); - } - - virtual void modify_fact(table_fact & f) const { - permutate_by_cycle(f, m_cycle); - } - - virtual table_base * operator()(const table_base & t) { - return auxiliary_table_transformer_fn::operator()(t); - } - - }; - - table_transformer_fn * relation_manager::mk_rename_fn(const table_base & t, unsigned permutation_cycle_len, - const unsigned * permutation_cycle) { - table_transformer_fn * res = t.get_plugin().mk_rename_fn(t, permutation_cycle_len, permutation_cycle); - if(!res) { - res = alloc(default_table_rename_fn, t.get_signature(), permutation_cycle_len, permutation_cycle); - } - return res; - } - - table_transformer_fn * relation_manager::mk_permutation_rename_fn(const table_base & t, - const unsigned * permutation) { - table_transformer_fn * res = t.get_plugin().mk_permutation_rename_fn(t, permutation); - if(!res) { - res = alloc(default_table_permutation_rename_fn, t, permutation); - } - return res; - } - - - class relation_manager::default_table_union_fn : public table_union_fn { - table_fact m_row; - public: - virtual void operator()(table_base & tgt, const table_base & src, table_base * delta) { - table_base::iterator it = src.begin(); - table_base::iterator iend = src.end(); - - for(; it!=iend; ++it) { - it->get_fact(m_row); - - if(delta) { - if(!tgt.contains_fact(m_row)) { - tgt.add_new_fact(m_row); - delta->add_fact(m_row); - } - } - else { - //if there's no delta, we don't need to know whether we are actually adding a new fact - tgt.add_fact(m_row); - } - } - } - }; - - table_union_fn * relation_manager::mk_union_fn(const table_base & tgt, const table_base & src, - const table_base * delta) { - table_union_fn * res = tgt.get_plugin().mk_union_fn(tgt, src, delta); - if(!res && &tgt.get_plugin()!=&src.get_plugin()) { - res = src.get_plugin().mk_union_fn(tgt, src, delta); - } - if(!res && delta && &tgt.get_plugin()!=&delta->get_plugin() && &src.get_plugin()!=&delta->get_plugin()) { - res = delta->get_plugin().mk_union_fn(tgt, src, delta); - } - if(!res) { - res = alloc(default_table_union_fn); - } - return res; - } - - table_union_fn * relation_manager::mk_widen_fn(const table_base & tgt, const table_base & src, - const table_base * delta) { - table_union_fn * res = tgt.get_plugin().mk_widen_fn(tgt, src, delta); - if(!res && &tgt.get_plugin()!=&src.get_plugin()) { - res = src.get_plugin().mk_widen_fn(tgt, src, delta); - } - if(!res && delta && &tgt.get_plugin()!=&delta->get_plugin() && &src.get_plugin()!=&delta->get_plugin()) { - res = delta->get_plugin().mk_widen_fn(tgt, src, delta); - } - if(!res) { - res = mk_union_fn(tgt, src, delta); - } - return res; - } - - - /** - An auixiliary class for functors that perform filtering. It performs the table traversal - and only asks for each individual row whether it should be removed. - - When using this class in multiple inheritance, this class should not be inherited publicly - and should be mentioned as last. This should ensure that deteletion of the object will - go well when initiated from a pointer to the first ancestor. - */ - class relation_manager::auxiliary_table_filter_fn { - table_fact m_row; - svector m_to_remove; - public: - virtual ~auxiliary_table_filter_fn() {} - virtual bool should_remove(const table_fact & f) const = 0; - - void operator()(table_base & r) { - m_to_remove.reset(); - unsigned sz = 0; - table_base::iterator it = r.begin(); - table_base::iterator iend = r.end(); - for(; it!=iend; ++it) { - it->get_fact(m_row); - if(should_remove(m_row)) { - m_to_remove.append(m_row.size(), m_row.c_ptr()); - ++sz; - } - } - r.remove_facts(sz, m_to_remove.c_ptr()); - } - }; - - class relation_manager::default_table_filter_identical_fn : public table_mutator_fn, auxiliary_table_filter_fn { - const unsigned m_col_cnt; - const unsigned_vector m_identical_cols; - public: - default_table_filter_identical_fn(unsigned col_cnt, const unsigned * identical_cols) - : m_col_cnt(col_cnt), - m_identical_cols(col_cnt, identical_cols) { - SASSERT(col_cnt>=2); - } - - virtual bool should_remove(const table_fact & f) const { - table_element val=f[m_identical_cols[0]]; - for(unsigned i=1; iget_arg(0); - if (!m.is_eq(condition)) { - return 0; - } - expr* x = to_app(condition)->get_arg(0); - expr* y = to_app(condition)->get_arg(1); - if (!is_var(x)) { - std::swap(x, y); - } - if (!is_var(x)) { - return 0; - } - dl_decl_util decl_util(m); - uint64 value = 0; - if (!decl_util.is_numeral_ext(y, value)) { - return 0; - } - return alloc(default_table_filter_not_equal_fn, ctx, to_var(x)->get_idx(), value); - } - }; - - - - class relation_manager::default_table_filter_interpreted_fn - : public table_mutator_fn, auxiliary_table_filter_fn { - ast_manager & m_ast_manager; - var_subst & m_vs; - dl_decl_util & m_decl_util; - th_rewriter & m_simp; - app_ref m_condition; - ptr_vector m_var_sorts; - expr_ref_vector m_args; - public: - default_table_filter_interpreted_fn(context & ctx, unsigned col_cnt, app* condition) - : m_ast_manager(ctx.get_manager()), - m_vs(ctx.get_var_subst()), - m_decl_util(ctx.get_decl_util()), - m_simp(ctx.get_rewriter()), - m_condition(condition, ctx.get_manager()), - m_args(ctx.get_manager()) { - m_var_sorts.resize(col_cnt); - get_free_vars(m_condition, m_var_sorts); - } - - virtual bool should_remove(const table_fact & f) const { - expr_ref_vector& args = const_cast(m_args); - - args.reset(); - //arguments need to be in reverse order for the substitution - unsigned col_cnt = f.size(); - for(int i=col_cnt-1;i>=0;i--) { - sort * var_sort = m_var_sorts[i]; - if(!var_sort) { - args.push_back(0); - continue; //this variable does not occur in the condition; - } - - table_element el = f[i]; - args.push_back(m_decl_util.mk_numeral(el, var_sort)); - } - - expr_ref ground(m_ast_manager); - m_vs(m_condition.get(), args.size(), args.c_ptr(), ground); - m_simp(ground); - - return m_ast_manager.is_false(ground); - } - - virtual void operator()(table_base & t) { - auxiliary_table_filter_fn::operator()(t); - } - }; - - table_mutator_fn * relation_manager::mk_filter_interpreted_fn(const table_base & t, app * condition) { - context & ctx = get_context(); - table_mutator_fn * res = t.get_plugin().mk_filter_interpreted_fn(t, condition); - if (!res) { - res = default_table_filter_not_equal_fn::mk(ctx, condition); - } - if(!res) { - res = alloc(default_table_filter_interpreted_fn, ctx, t.get_signature().size(), condition); - } - return res; - } - - - class relation_manager::default_table_filter_interpreted_and_project_fn - : public table_transformer_fn { - scoped_ptr m_filter; - scoped_ptr m_project; - app_ref m_condition; - unsigned_vector m_removed_cols; - public: - default_table_filter_interpreted_and_project_fn(context & ctx, table_mutator_fn * filter, - app * condition, unsigned removed_col_cnt, const unsigned * removed_cols) - : m_filter(filter), m_condition(condition, ctx.get_manager()), - m_removed_cols(removed_col_cnt, removed_cols) {} - - virtual table_base* operator()(const table_base & tb) { - table_base *t2 = tb.clone(); - (*m_filter)(*t2); - if (!m_project) { - relation_manager & rmgr = t2->get_plugin().get_manager(); - m_project = rmgr.mk_project_fn(*t2, m_removed_cols.size(), m_removed_cols.c_ptr()); - if (!m_project) { - throw default_exception("projection does not exist"); - } - } - return (*m_project)(*t2); - } - }; - - table_transformer_fn * relation_manager::mk_filter_interpreted_and_project_fn(const table_base & t, - app * condition, unsigned removed_col_cnt, const unsigned * removed_cols) { - table_transformer_fn * res = t.get_plugin().mk_filter_interpreted_and_project_fn(t, condition, removed_col_cnt, removed_cols); - if (res) - return res; - - table_mutator_fn * filter = mk_filter_interpreted_fn(t, condition); - SASSERT(filter); - res = alloc(default_table_filter_interpreted_and_project_fn, get_context(), filter, condition, removed_col_cnt, removed_cols); - return res; - } - - - table_intersection_filter_fn * relation_manager::mk_filter_by_intersection_fn(const table_base & t, - const table_base & src, unsigned joined_col_cnt, const unsigned * t_cols, const unsigned * src_cols) { - table_intersection_filter_fn * res = t.get_plugin().mk_filter_by_negation_fn(t, src, joined_col_cnt, - t_cols, src_cols); - if(!res && &t.get_plugin()!=&src.get_plugin()) { - res = src.get_plugin().mk_filter_by_negation_fn(t, src, joined_col_cnt, t_cols, src_cols); - } - return res; - } - - - - class relation_manager::default_table_negation_filter_fn : public convenient_table_negation_filter_fn, - auxiliary_table_filter_fn { - const table_base * m_negated_table; - mutable table_fact m_aux_fact; - public: - default_table_negation_filter_fn(const table_base & tgt, const table_base & neg_t, - unsigned joined_col_cnt, const unsigned * t_cols, const unsigned * negated_cols) - : convenient_table_negation_filter_fn(tgt, neg_t, joined_col_cnt, t_cols, negated_cols), - m_negated_table(0) { - m_aux_fact.resize(neg_t.get_signature().size()); - } - - virtual bool should_remove(const table_fact & f) const { - if(!m_all_neg_bound || m_overlap) { - table_base::iterator nit = m_negated_table->begin(); - table_base::iterator nend = m_negated_table->end(); - for(; nit!=nend; ++nit) { - const table_base::row_interface & nrow = *nit; - if(bindings_match(nrow, f)) { - return true; - } - } - return false; - } - else { - make_neg_bindings(m_aux_fact, f); - return m_negated_table->contains_fact(m_aux_fact); - } - } - - virtual void operator()(table_base & tgt, const table_base & negated_table) { - SASSERT(m_negated_table==0); - flet flet_neg_table(m_negated_table, &negated_table); - auxiliary_table_filter_fn::operator()(tgt); - } - - }; - - table_intersection_filter_fn * relation_manager::mk_filter_by_negation_fn(const table_base & t, - const table_base & negated_obj, unsigned joined_col_cnt, - const unsigned * t_cols, const unsigned * negated_cols) { - table_intersection_filter_fn * res = t.get_plugin().mk_filter_by_negation_fn(t, negated_obj, joined_col_cnt, - t_cols, negated_cols); - if(!res && &t.get_plugin()!=&negated_obj.get_plugin()) { - res = negated_obj.get_plugin().mk_filter_by_negation_fn(t, negated_obj, joined_col_cnt, t_cols, - negated_cols); - } - if(!res) { - res = alloc(default_table_negation_filter_fn, t, negated_obj, joined_col_cnt, t_cols, negated_cols); - } - return res; - } - - - class relation_manager::default_table_select_equal_and_project_fn : public table_transformer_fn { - scoped_ptr m_filter; - scoped_ptr m_project; - public: - default_table_select_equal_and_project_fn(table_mutator_fn * filter, table_transformer_fn * project) - : m_filter(filter), m_project(project) {} - - virtual table_base * operator()(const table_base & t1) { - TRACE("dl", tout << t1.get_plugin().get_name() << "\n";); - scoped_rel aux = t1.clone(); - (*m_filter)(*aux); - table_base * res = (*m_project)(*aux); - return res; - } - }; - - table_transformer_fn * relation_manager::mk_select_equal_and_project_fn(const table_base & t, - const table_element & value, unsigned col) { - table_transformer_fn * res = t.get_plugin().mk_select_equal_and_project_fn(t, value, col); - if(!res) { - table_mutator_fn * selector = mk_filter_equal_fn(t, value, col); - SASSERT(selector); - table_transformer_fn * projector = mk_project_fn(t, 1, &col); - SASSERT(projector); - res = alloc(default_table_select_equal_and_project_fn, selector, projector); - } - return res; - } - - - class relation_manager::default_table_map_fn : public table_mutator_fn { - scoped_ptr m_mapper; - unsigned m_first_functional; - scoped_rel m_aux_table; - scoped_ptr m_union_fn; - table_fact m_curr_fact; - public: - default_table_map_fn(const table_base & t, table_row_mutator_fn * mapper) - : m_mapper(mapper), m_first_functional(t.get_signature().first_functional()) { - SASSERT(t.get_signature().functional_columns()>0); - table_plugin & plugin = t.get_plugin(); - m_aux_table = plugin.mk_empty(t.get_signature()); - m_union_fn = plugin.mk_union_fn(t, *m_aux_table, static_cast(0)); - } - - virtual void operator()(table_base & t) { - SASSERT(t.get_signature()==m_aux_table->get_signature()); - if(!m_aux_table->empty()) { - m_aux_table->reset(); - } - - - table_base::iterator it = t.begin(); - table_base::iterator iend = t.end(); - for(; it!=iend; ++it) { - it->get_fact(m_curr_fact); - if((*m_mapper)(m_curr_fact.c_ptr()+m_first_functional)) { - m_aux_table->add_fact(m_curr_fact); - } - } - - t.reset(); - (*m_union_fn)(t, *m_aux_table, static_cast(0)); - } - }; - - table_mutator_fn * relation_manager::mk_map_fn(const table_base & t, table_row_mutator_fn * mapper) { - SASSERT(t.get_signature().functional_columns()>0); - table_mutator_fn * res = t.get_plugin().mk_map_fn(t, mapper); - if(!res) { - res = alloc(default_table_map_fn, t, mapper); - } - return res; - } - - - class relation_manager::default_table_project_with_reduce_fn : public convenient_table_transformer_fn { - unsigned_vector m_removed_cols; - const unsigned m_inp_col_cnt; - const unsigned m_removed_col_cnt; - const unsigned m_result_col_cnt; - scoped_ptr m_reducer; - unsigned m_res_first_functional; - table_fact m_row; - table_fact m_former_row; - public: - default_table_project_with_reduce_fn(const table_signature & orig_sig, unsigned removed_col_cnt, - const unsigned * removed_cols, table_row_pair_reduce_fn * reducer) - : m_removed_cols(removed_col_cnt, removed_cols), - m_inp_col_cnt(orig_sig.size()), - m_removed_col_cnt(removed_col_cnt), - m_result_col_cnt(orig_sig.size()-removed_col_cnt), - m_reducer(reducer) { - SASSERT(removed_col_cnt>0); - table_signature::from_project_with_reduce(orig_sig, removed_col_cnt, removed_cols, - get_result_signature()); - m_res_first_functional = get_result_signature().first_functional(); - m_row.resize(get_result_signature().size()); - m_former_row.resize(get_result_signature().size()); - } - - virtual void modify_fact(table_fact & f) const { - unsigned ofs=1; - unsigned r_i=1; - for(unsigned i=m_removed_cols[0]+1; isuggest_fact(m_former_row)) { - (*m_reducer)(m_former_row.c_ptr()+m_res_first_functional, m_row.c_ptr()+m_res_first_functional); - res->ensure_fact(m_former_row); - } - } - return res; - } - }; - - table_transformer_fn * relation_manager::mk_project_with_reduce_fn(const table_base & t, unsigned col_cnt, - const unsigned * removed_cols, table_row_pair_reduce_fn * reducer) { - SASSERT(t.get_signature().functional_columns()>0); - table_transformer_fn * res = t.get_plugin().mk_project_with_reduce_fn(t, col_cnt, removed_cols, reducer); - if(!res) { - res = alloc(default_table_project_with_reduce_fn, t.get_signature(), col_cnt, removed_cols, reducer); - } - return res; - } - -}; - diff --git a/src/muz/dl_relation_manager.h b/src/muz/dl_relation_manager.h deleted file mode 100644 index 9f12b4bb6..000000000 --- a/src/muz/dl_relation_manager.h +++ /dev/null @@ -1,688 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - dl_relation_manager.h - -Abstract: - - - -Author: - - Krystof Hoder (t-khoder) 2010-09-24. - -Revision History: - ---*/ -#ifndef _DL_RELATION_MANAGER_H_ -#define _DL_RELATION_MANAGER_H_ - - -#include"map.h" -#include"vector.h" -#include"dl_base.h" - -namespace datalog { - - class context; - class dl_decl_util; - class table_relation; - class table_relation_plugin; - class finite_product_relation; - class finite_product_relation_plugin; - class sieve_relation; - class sieve_relation_plugin; - class rule_set; - - - class relation_manager { - class empty_signature_relation_join_fn; - class default_relation_join_project_fn; - class default_relation_select_equal_and_project_fn; - class default_relation_intersection_filter_fn; - class default_relation_filter_interpreted_and_project_fn; - - class auxiliary_table_transformer_fn; - class auxiliary_table_filter_fn; - - class default_table_join_fn; - class default_table_project_fn; - class null_signature_table_project_fn; - class default_table_join_project_fn; - class default_table_rename_fn; - class default_table_union_fn; - class default_table_filter_equal_fn; - class default_table_filter_identical_fn; - class default_table_filter_interpreted_fn; - class default_table_filter_interpreted_and_project_fn; - class default_table_negation_filter_fn; - class default_table_filter_not_equal_fn; - class default_table_select_equal_and_project_fn; - class default_table_map_fn; - class default_table_project_with_reduce_fn; - - typedef obj_map decl2kind_map; - - typedef u_map kind2plugin_map; - - typedef map, - ptr_eq > tp2trp_map; - typedef map, - ptr_eq > rp2fprp_map; - - typedef map, ptr_eq > relation_map; - typedef ptr_vector table_plugin_vector; - typedef ptr_vector relation_plugin_vector; - - context & m_context; - table_plugin_vector m_table_plugins; - relation_plugin_vector m_relation_plugins; - //table_relation_plugins corresponding to table_plugins - tp2trp_map m_table_relation_plugins; - rp2fprp_map m_finite_product_relation_plugins; - - kind2plugin_map m_kind2plugin; - - table_plugin * m_favourite_table_plugin; - - relation_plugin * m_favourite_relation_plugin; - - relation_map m_relations; - - decl_set m_saturated_rels; - - family_id m_next_table_fid; - family_id m_next_relation_fid; - - /** - Map specifying what kind of relation should be used to represent particular predicate. - */ - decl2kind_map m_pred_kinds; - - void register_relation_plugin_impl(relation_plugin * plugin); - - relation_manager(const relation_manager &); //private and undefined copy constructor - relation_manager & operator=(const relation_manager &); //private and undefined operator= - public: - relation_manager(context & ctx) : - m_context(ctx), - m_favourite_table_plugin(0), - m_favourite_relation_plugin(0), - m_next_table_fid(0), - m_next_relation_fid(0) {} - - virtual ~relation_manager(); - - void reset(); - void reset_relations(); - - context & get_context() const { return m_context; } - dl_decl_util & get_decl_util() const; - - family_id get_next_table_fid() { return m_next_table_fid++; } - family_id get_next_relation_fid(relation_plugin & claimer); - - - /** - Set what kind of relation is going to be used to represent the predicate \c pred. - - This function can be called only before the relation object for \c pred is created - (i.e. before the \c get_relation function is called with \c pred as argument for the - first time). - */ - void set_predicate_kind(func_decl * pred, family_id kind); - /** - Return the relation kind that was requested to represent the predicate \c pred by - \c set_predicate_kind. If there was no such request, return \c null_family_id. - */ - family_id get_requested_predicate_kind(func_decl * pred); - relation_base & get_relation(func_decl * pred); - relation_base * try_get_relation(func_decl * pred) const; - /** - \brief Store the relation \c rel under the predicate \c pred. The \c relation_manager - takes over the relation object. - */ - void store_relation(func_decl * pred, relation_base * rel); - - bool is_saturated(func_decl * pred) const { return m_saturated_rels.contains(pred); } - void mark_saturated(func_decl * pred) { m_saturated_rels.insert(pred); } - void reset_saturated_marks() { - if(!m_saturated_rels.empty()) { - m_saturated_rels.reset(); - } - } - - void collect_non_empty_predicates(decl_set & res) const; - void restrict_predicates(const decl_set & preds); - - void register_plugin(table_plugin * plugin); - /** - table_relation_plugins should not be passed to this function since they are - created automatically when registering a table plugin. - */ - void register_plugin(relation_plugin * plugin) { - SASSERT(!plugin->from_table()); - register_relation_plugin_impl(plugin); - } - - table_plugin & get_appropriate_plugin(const table_signature & t); - relation_plugin & get_appropriate_plugin(const relation_signature & t); - table_plugin * try_get_appropriate_plugin(const table_signature & t); - relation_plugin * try_get_appropriate_plugin(const relation_signature & t); - - table_plugin * get_table_plugin(symbol const& s); - relation_plugin * get_relation_plugin(symbol const& s); - relation_plugin & get_relation_plugin(family_id kind); - table_relation_plugin & get_table_relation_plugin(table_plugin & tp); - bool try_get_finite_product_relation_plugin(const relation_plugin & inner, - finite_product_relation_plugin * & res); - - table_base * mk_empty_table(const table_signature & s); - relation_base * mk_implicit_relation(const relation_signature & s, app * expr); - - relation_base * mk_empty_relation(const relation_signature & s, family_id kind); - relation_base * mk_empty_relation(const relation_signature & s, func_decl* pred); - - relation_base * mk_full_relation(const relation_signature & s, func_decl* pred, family_id kind); - relation_base * mk_full_relation(const relation_signature & s, func_decl* pred); - - relation_base * mk_table_relation(const relation_signature & s, table_base * table); - bool mk_empty_table_relation(const relation_signature & s, relation_base * & result); - - bool is_non_explanation(relation_signature const& s) const; - - - /** - \brief Convert relation value to table one. - - This function can be called only for the relation sorts that have a table counterpart. - */ - void relation_to_table(const relation_sort & sort, const relation_element & from, table_element & to); - - void table_to_relation(const relation_sort & sort, const table_element & from, relation_element & to); - void table_to_relation(const relation_sort & sort, const table_element & from, - const relation_fact::el_proxy & to); - void table_to_relation(const relation_sort & sort, const table_element & from, - relation_element_ref & to); - - bool relation_sort_to_table(const relation_sort & from, table_sort & to); - void from_predicate(func_decl * pred, unsigned arg_index, relation_sort & result); - void from_predicate(func_decl * pred, relation_signature & result); - - /** - \brief Convert relation signature to table signature and return true if successful. If false - is returned, the value of \c to is undefined. - */ - bool relation_signature_to_table(const relation_signature & from, table_signature & to); - - void relation_fact_to_table(const relation_signature & s, const relation_fact & from, - table_fact & to); - void table_fact_to_relation(const relation_signature & s, const table_fact & from, - relation_fact & to); - - - void set_cancel(bool f); - - - // ----------------------------------- - // - // relation operations - // - // ----------------------------------- - - //TODO: If multiple operation implementations are available, we may want to do something to - //select the best one here. - - /** - If \c allow_product_relation is true, we will create a join that builds a product relation, - if there is no other way to do the join. If \c allow_product_relation is false, we will return - zero in that case. - */ - relation_join_fn * mk_join_fn(const relation_base & t1, const relation_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2, bool allow_product_relation=true); - - relation_join_fn * mk_join_fn(const relation_base & t1, const relation_base & t2, - const unsigned_vector & cols1, const unsigned_vector & cols2, bool allow_product_relation=true) { - SASSERT(cols1.size()==cols2.size()); - return mk_join_fn(t1, t2, cols1.size(), cols1.c_ptr(), cols2.c_ptr(), allow_product_relation); - } - - /** - \brief Return functor that transforms a table into one that lacks columns listed in - \c removed_cols array. - - The \c removed_cols cotains columns of table \c t in strictly ascending order. - */ - relation_transformer_fn * mk_project_fn(const relation_base & t, unsigned col_cnt, - const unsigned * removed_cols); - - relation_transformer_fn * mk_project_fn(const relation_base & t, const unsigned_vector & removed_cols) { - return mk_project_fn(t, removed_cols.size(), removed_cols.c_ptr()); - } - - /** - \brief Return an operation that is a composition of a join an a project operation. - */ - relation_join_fn * mk_join_project_fn(const relation_base & t1, const relation_base & t2, - unsigned joined_col_cnt, const unsigned * cols1, const unsigned * cols2, - unsigned removed_col_cnt, const unsigned * removed_cols, bool allow_product_relation_join=true); - - relation_join_fn * mk_join_project_fn(const relation_base & t1, const relation_base & t2, - const unsigned_vector & cols1, const unsigned_vector & cols2, - const unsigned_vector & removed_cols, bool allow_product_relation_join=true) { - return mk_join_project_fn(t1, t2, cols1.size(), cols1.c_ptr(), cols2.c_ptr(), removed_cols.size(), - removed_cols.c_ptr(), allow_product_relation_join); - } - - relation_transformer_fn * mk_rename_fn(const relation_base & t, unsigned permutation_cycle_len, - const unsigned * permutation_cycle); - relation_transformer_fn * mk_rename_fn(const relation_base & t, const unsigned_vector & permutation_cycle) { - return mk_rename_fn(t, permutation_cycle.size(), permutation_cycle.c_ptr()); - } - - /** - Like \c mk_rename_fn, only the permutation is not specified by cycle, but by a permutated array - of column number. - */ - relation_transformer_fn * mk_permutation_rename_fn(const relation_base & t, - const unsigned * permutation); - relation_transformer_fn * mk_permutation_rename_fn(const relation_base & t, - const unsigned_vector permutation) { - SASSERT(t.get_signature().size()==permutation.size()); - return mk_permutation_rename_fn(t, permutation.c_ptr()); - } - - - /** - The post-condition for an ideal union operation is be - - Union(tgt, src, delta): - tgt_1==tgt_0 \union src - delta_1== delta_0 \union ( tgt_1 \setminus tgt_0 ) - - A required post-condition is - - Union(tgt, src, delta): - tgt_1==tgt_0 \union src - tgt_1==tgt_0 => delta_1==delta_0 - delta_0 \subset delta_1 - delta_1 \subset (delta_0 \union tgt_1) - ( tgt_1 \setminus tgt_0 ) \subset delta_1 - - So that a sufficient implementation is - - Union(tgt, src, delta) { - oldTgt:=tgt.clone(); - tgt:=tgt \union src - if(tgt!=oldTgt) { - delta:=delta \union src //also ?delta \union tgt? would work - } - } - - If rules are compiled with all_or_nothing_deltas parameter set to true, a sufficient - post-condition is - Union(tgt, src, delta): - tgt_1==tgt_0 \union src - (tgt_1==tgt_0 || delta_0 is non-empty) <=> delta_1 is non-empty - */ - relation_union_fn * mk_union_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta); - - relation_union_fn * mk_union_fn(const relation_base & tgt, const relation_base & src) { - return mk_union_fn(tgt, src, static_cast(0)); - } - - /** - Similar to union, but this one should be used inside loops to allow for abstract - domain convergence. - */ - relation_union_fn * mk_widen_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta); - - relation_mutator_fn * mk_filter_identical_fn(const relation_base & t, unsigned col_cnt, - const unsigned * identical_cols); - relation_mutator_fn * mk_filter_identical_fn(const relation_base & t, const unsigned_vector identical_cols) { - return mk_filter_identical_fn(t, identical_cols.size(), identical_cols.c_ptr()); - } - - relation_mutator_fn * mk_filter_equal_fn(const relation_base & t, const relation_element & value, - unsigned col); - - relation_mutator_fn * mk_filter_interpreted_fn(const relation_base & t, app * condition); - - relation_transformer_fn * mk_filter_interpreted_and_project_fn(const relation_base & t, app * condition, - unsigned removed_col_cnt, const unsigned * removed_cols); - - /** - \brief Operations that returns all rows of \c t for which is column \c col equal to \c value - with the column \c col removed. - - This operation can often be efficiently implemented and is useful for evaluating rules - of the form - - F(x):-P("c",x). - */ - relation_transformer_fn * mk_select_equal_and_project_fn(const relation_base & t, - const relation_element & value, unsigned col); - - - relation_intersection_filter_fn * mk_filter_by_intersection_fn(const relation_base & tgt, - const relation_base & src, unsigned joined_col_cnt, - const unsigned * tgt_cols, const unsigned * src_cols); - relation_intersection_filter_fn * mk_filter_by_intersection_fn(const relation_base & tgt, - const relation_base & src, const unsigned_vector & tgt_cols, const unsigned_vector & src_cols) { - SASSERT(tgt_cols.size()==src_cols.size()); - return mk_filter_by_intersection_fn(tgt, src, tgt_cols.size(), tgt_cols.c_ptr(), src_cols.c_ptr()); - } - relation_intersection_filter_fn * mk_filter_by_intersection_fn(const relation_base & tgt, - const relation_base & src); - - /** - The filter_by_negation postcondition: - filter_by_negation(tgt, neg, columns in tgt: c1,...,cN, - corresponding columns in neg: d1,...,dN): - tgt_1:={x: x\in tgt_0 && ! \exists y: ( y \in neg & pi_c1(x)= pi_d1(y) & ... & pi_cN(x)= pi_dN(y) ) } - */ - relation_intersection_filter_fn * mk_filter_by_negation_fn(const relation_base & t, - const relation_base & negated_obj, unsigned joined_col_cnt, - const unsigned * t_cols, const unsigned * negated_cols); - relation_intersection_filter_fn * mk_filter_by_negation_fn(const relation_base & t, - const relation_base & negated_obj, const unsigned_vector & t_cols, - const unsigned_vector & negated_cols) { - SASSERT(t_cols.size()==negated_cols.size()); - return mk_filter_by_negation_fn(t, negated_obj, t_cols.size(), t_cols.c_ptr(), negated_cols.c_ptr()); - } - - - // ----------------------------------- - // - // table operations - // - // ----------------------------------- - - - table_join_fn * mk_join_fn(const table_base & t1, const table_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2); - - table_join_fn * mk_join_fn(const table_base & t1, const table_base & t2, - const unsigned_vector & cols1, const unsigned_vector & cols2) { - SASSERT(cols1.size()==cols2.size()); - return mk_join_fn(t1, t2, cols1.size(), cols1.c_ptr(), cols2.c_ptr()); - } - - /** - \brief Return functor that transforms a table into one that lacks columns listed in - \c removed_cols array. - - The \c removed_cols cotains columns of table \c t in strictly ascending order. - - If a project operation removes a non-functional column, all functional columns become - non-functional (so that none of the values in functional columns are lost) - */ - table_transformer_fn * mk_project_fn(const table_base & t, unsigned col_cnt, - const unsigned * removed_cols); - - table_transformer_fn * mk_project_fn(const table_base & t, const unsigned_vector & removed_cols) { - return mk_project_fn(t, removed_cols.size(), removed_cols.c_ptr()); - } - - /** - \brief Return an operation that is a composition of a join an a project operation. - - This operation is equivalent to the two operations performed separately, unless functional - columns are involved. - - The ordinary project would make all of the functional columns into non-functional if any - non-functional column was removed. In function, however, we group columns into equivalence - classes (according to the equalities in \c cols1 and \c cols2) and make everything non-functional - only if some equivalence class of non-functional columns would have no non-functional columns - remain after the removal. - - This behavior is implemented in the \c table_signature::from_join_project function. - */ - table_join_fn * mk_join_project_fn(const table_base & t1, const table_base & t2, - unsigned joined_col_cnt, const unsigned * cols1, const unsigned * cols2, - unsigned removed_col_cnt, const unsigned * removed_cols); - - table_join_fn * mk_join_project_fn(const table_base & t1, const table_base & t2, - const unsigned_vector & cols1, const unsigned_vector & cols2, - const unsigned_vector & removed_cols) { - return mk_join_project_fn(t1, t2, cols1.size(), cols1.c_ptr(), cols2.c_ptr(), removed_cols.size(), - removed_cols.c_ptr()); - } - - table_transformer_fn * mk_rename_fn(const table_base & t, unsigned permutation_cycle_len, - const unsigned * permutation_cycle); - table_transformer_fn * mk_rename_fn(const table_base & t, const unsigned_vector & permutation_cycle) { - return mk_rename_fn(t, permutation_cycle.size(), permutation_cycle.c_ptr()); - } - - /** - Like \c mk_rename_fn, only the permutation is not specified by cycle, but by a permutated array - of column number. - */ - table_transformer_fn * mk_permutation_rename_fn(const table_base & t, const unsigned * permutation); - table_transformer_fn * mk_permutation_rename_fn(const table_base & t, const unsigned_vector permutation) { - SASSERT(t.get_signature().size()==permutation.size()); - return mk_permutation_rename_fn(t, permutation.c_ptr()); - } - - - /** - The post-condition for an ideal union operation is be - - Union(tgt, src, delta): - tgt_1==tgt_0 \union src - delta_1== delta_0 \union ( tgt_1 \setminus tgt_0 ) - - A required post-condition is - - Union(tgt, src, delta): - tgt_1==tgt_0 \union src - tgt_1==tgt_0 => delta_1==delta_0 - delta_0 \subset delta_1 - delta_1 \subset (delta_0 \union tgt_1) - ( tgt_1 \setminus tgt_0 ) \subset delta_1 - - So that a sufficient implementation is - - Union(tgt, src, delta) { - oldTgt:=tgt.clone(); - tgt:=tgt \union src - if(tgt!=oldTgt) { - delta:=delta \union src //also ?delta \union tgt? would work - } - } - - If rules are compiled with all_or_nothing_deltas parameter set to true, a sufficient - post-condition is - Union(tgt, src, delta): - tgt_1==tgt_0 \union src - (tgt_1==tgt_0 || delta_0 is non-empty) <=> delta_1 is non-empty - */ - table_union_fn * mk_union_fn(const table_base & tgt, const table_base & src, - const table_base * delta); - - table_union_fn * mk_union_fn(const table_base & tgt, const table_base & src) { - return mk_union_fn(tgt, src, static_cast(0)); - } - - /** - Similar to union, but this one should be used inside loops to allow for abstract - domain convergence. - */ - table_union_fn * mk_widen_fn(const table_base & tgt, const table_base & src, - const table_base * delta); - - table_mutator_fn * mk_filter_identical_fn(const table_base & t, unsigned col_cnt, - const unsigned * identical_cols); - table_mutator_fn * mk_filter_identical_fn(const table_base & t, const unsigned_vector identical_cols) { - return mk_filter_identical_fn(t, identical_cols.size(), identical_cols.c_ptr()); - } - - table_mutator_fn * mk_filter_equal_fn(const table_base & t, const table_element & value, - unsigned col); - - table_mutator_fn * mk_filter_interpreted_fn(const table_base & t, app * condition); - - table_transformer_fn * mk_filter_interpreted_and_project_fn(const table_base & t, app * condition, - unsigned removed_col_cnt, const unsigned * removed_cols); - - /** - \brief Operations that returns all rows of \c t for which is column \c col equal to \c value - with the column \c col removed. - - This operation can often be efficiently implemented and is useful for evaluating rules - of the form - - F(x):-P("c",x). - */ - table_transformer_fn * mk_select_equal_and_project_fn(const table_base & t, - const table_element & value, unsigned col); - - table_intersection_filter_fn * mk_filter_by_intersection_fn(const table_base & t, - const table_base & src, unsigned joined_col_cnt, const unsigned * t_cols, const unsigned * src_cols); - table_intersection_filter_fn * mk_filter_by_intersection_fn(const table_base & t, - const table_base & src, const unsigned_vector & t_cols, const unsigned_vector & src_cols) { - SASSERT(t_cols.size()==src_cols.size()); - return mk_filter_by_intersection_fn(t, src, t_cols.size(), t_cols.c_ptr(), src_cols.c_ptr()); - } - - /** - The filter_by_negation postcondition: - filter_by_negation(tgt, neg, columns in tgt: c1,...,cN, - corresponding columns in neg: d1,...,dN): - tgt_1:={x: x\in tgt_0 && ! \exists y: ( y \in neg & pi_c1(x)= pi_d1(y) & ... & pi_cN(x)= pi_dN(y) ) } - */ - table_intersection_filter_fn * mk_filter_by_negation_fn(const table_base & t, const table_base & negated_obj, - unsigned joined_col_cnt, const unsigned * t_cols, const unsigned * negated_cols); - table_intersection_filter_fn * mk_filter_by_negation_fn(const table_base & t, const table_base & negated_obj, - const unsigned_vector & t_cols, const unsigned_vector & negated_cols) { - SASSERT(t_cols.size()==negated_cols.size()); - return mk_filter_by_negation_fn(t, negated_obj, t_cols.size(), t_cols.c_ptr(), negated_cols.c_ptr()); - } - - /** - \c t must contain at least one functional column. - - Created object takes ownership of the \c mapper object. - */ - virtual table_mutator_fn * mk_map_fn(const table_base & t, table_row_mutator_fn * mapper); - - /** - \c t must contain at least one functional column. - - Created object takes ownership of the \c mapper object. - */ - virtual table_transformer_fn * mk_project_with_reduce_fn(const table_base & t, unsigned col_cnt, - const unsigned * removed_cols, table_row_pair_reduce_fn * reducer); - - - - - // ----------------------------------- - // - // output functions - // - // ----------------------------------- - - - std::string to_nice_string(const relation_element & el) const; - /** - This one may give a nicer representation of \c el than the - \c to_nice_string(const relation_element & el) function, by unsing the information about the sort - of the element. - */ - std::string to_nice_string(const relation_sort & s, const relation_element & el) const; - std::string to_nice_string(const relation_sort & s) const; - std::string to_nice_string(const relation_signature & s) const; - - void display(std::ostream & out) const; - void display_relation_sizes(std::ostream & out) const; - void display_output_tables(rule_set const& rules, std::ostream & out) const; - - private: - relation_intersection_filter_fn * try_mk_default_filter_by_intersection_fn(const relation_base & t, - const relation_base & src, unsigned joined_col_cnt, - const unsigned * t_cols, const unsigned * src_cols); - - }; - - /** - This is a helper class for relation_plugins whose relations can be of various kinds. - */ - template > - class rel_spec_store { - typedef relation_signature::hash r_hash; - typedef relation_signature::eq r_eq; - - typedef map family_id_idx_store; - typedef map sig2store; - - typedef u_map family_id2spec; - typedef map sig2spec_store; - - relation_plugin & m_parent; - svector m_allocated_kinds; - sig2store m_kind_assignment; - sig2spec_store m_kind_specs; - - - relation_manager & get_manager() { return m_parent.get_manager(); } - - void add_new_kind() { - add_available_kind(get_manager().get_next_relation_fid(m_parent)); - } - - public: - rel_spec_store(relation_plugin & parent) : m_parent(parent) {} - - ~rel_spec_store() { - reset_dealloc_values(m_kind_assignment); - reset_dealloc_values(m_kind_specs); - } - - void add_available_kind(family_id k) { - m_allocated_kinds.push_back(k); - } - - bool contains_signature(relation_signature const& sig) const { - return m_kind_assignment.contains(sig); - } - - family_id get_relation_kind(const relation_signature & sig, const Spec & spec) { - typename sig2store::entry * e = m_kind_assignment.find_core(sig); - if(!e) { - e = m_kind_assignment.insert_if_not_there2(sig, alloc(family_id_idx_store)); - m_kind_specs.insert(sig, alloc(family_id2spec)); - } - family_id_idx_store & ids = *e->get_data().m_value; - - unsigned res_idx; - if(!ids.find(spec, res_idx)) { - res_idx = ids.size(); - if(res_idx==m_allocated_kinds.size()) { - add_new_kind(); - } - SASSERT(res_idxinsert(m_allocated_kinds[res_idx], spec); - } - return m_allocated_kinds[res_idx]; - } - - void get_relation_spec(const relation_signature & sig, family_id kind, Spec & spec) { - family_id2spec * idspecs = m_kind_specs.find(sig); - spec = idspecs->find(kind); - } - - }; - -}; - -#endif /* _DL_RELATION_MANAGER_H_ */ - diff --git a/src/muz/dl_sieve_relation.cpp b/src/muz/dl_sieve_relation.cpp deleted file mode 100644 index 9f9419089..000000000 --- a/src/muz/dl_sieve_relation.cpp +++ /dev/null @@ -1,666 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - dl_mk_explanations.cpp - -Abstract: - - - -Author: - - Krystof Hoder (t-khoder) 2010-11-08. - -Revision History: - ---*/ - -#include -#include"ast_pp.h" -#include"dl_sieve_relation.h" - -namespace datalog { - - // ----------------------------------- - // - // sieve_relation - // - // ----------------------------------- - - sieve_relation::sieve_relation(sieve_relation_plugin & p, const relation_signature & s, - const bool * inner_columns, relation_base * inner) - : relation_base(p, s), m_inner_cols(s.size(), inner_columns), m_inner(inner) { - unsigned n = s.size(); - for(unsigned i=0; i 0; ) { - --i; - unsigned idx = m_inner2sig[i]; - s.push_back(m.mk_var(idx, sig[i])); - } - get_inner().to_formula(tmp); - get_plugin().get_context().get_var_subst()(tmp, sz, s.c_ptr(), fml); - } - - - void sieve_relation::display(std::ostream & out) const { - out << "Sieve relation "; - print_container(m_inner_cols, out); - out <<"\n"; - get_inner().display(out); - } - - - // ----------------------------------- - // - // sieve_relation_plugin - // - // ----------------------------------- - - sieve_relation_plugin & sieve_relation_plugin::get_plugin(relation_manager & rmgr) { - sieve_relation_plugin * res = static_cast(rmgr.get_relation_plugin(get_name())); - if(!res) { - res = alloc(sieve_relation_plugin, rmgr); - rmgr.register_plugin(res); - } - return *res; - } - - sieve_relation& sieve_relation_plugin::get(relation_base& r) { - return dynamic_cast(r); - } - - sieve_relation const & sieve_relation_plugin::get(relation_base const& r) { - return dynamic_cast(r); - } - - sieve_relation* sieve_relation_plugin::get(relation_base* r) { - return dynamic_cast(r); - } - - sieve_relation const* sieve_relation_plugin::get(relation_base const* r) { - return dynamic_cast(r); - } - - sieve_relation_plugin::sieve_relation_plugin(relation_manager & manager) - : relation_plugin(get_name(), manager, ST_SIEVE_RELATION), - m_spec_store(*this) {} - - void sieve_relation_plugin::initialize(family_id fid) { - relation_plugin::initialize(fid); - m_spec_store.add_available_kind(get_kind()); - } - - family_id sieve_relation_plugin::get_relation_kind(const relation_signature & sig, - const bool * inner_columns, family_id inner_kind) { - rel_spec spec(sig.size(), inner_columns, inner_kind); - return m_spec_store.get_relation_kind(sig, spec); - } - - family_id sieve_relation_plugin::get_relation_kind(sieve_relation & r, const bool * inner_columns) { - const relation_signature & sig = r.get_signature(); - return get_relation_kind(sig, inner_columns, r.get_inner().get_kind()); - } - - void sieve_relation_plugin::extract_inner_columns(const relation_signature & s, relation_plugin & inner, - svector & inner_columns) { - SASSERT(inner_columns.size()==s.size()); - unsigned n = s.size(); - relation_signature inner_sig_singleton; - for(unsigned i=0; i & inner_columns, relation_signature & inner_sig) { - SASSERT(inner_columns.size()==s.size()); - inner_sig.reset(); - unsigned n = s.size(); - for(unsigned i=0; i inner_cols(s.size()); - extract_inner_columns(s, inner_cols.c_ptr()); - collect_inner_signature(s, inner_cols, inner_sig); -#endif - } - - bool sieve_relation_plugin::can_handle_signature(const relation_signature & s) { - //we do not want this plugin to handle anything by default - return false; -#if 0 - relation_signature inner_sig; - extract_inner_signature(s, inner_sig); - SASSERT(inner_sig.size()<=s.size()); - return !inner_sig.empty() && inner_sig.size()!=s.size(); -#endif - } - - sieve_relation * sieve_relation_plugin::mk_from_inner(const relation_signature & s, const bool * inner_columns, - relation_base * inner_rel) { - SASSERT(!inner_rel->get_plugin().is_sieve_relation()); //it does not make sense to make a sieve of a sieve - return alloc(sieve_relation, *this, s, inner_columns, inner_rel); - } - - sieve_relation * sieve_relation_plugin::mk_empty(const sieve_relation & original) { - return static_cast(mk_empty(original.get_signature(), original.get_kind())); - } - - relation_base * sieve_relation_plugin::mk_empty(const relation_base & original) { - return mk_empty(static_cast(original)); - } - - relation_base * sieve_relation_plugin::mk_empty(const relation_signature & s, family_id kind) { - rel_spec spec; - m_spec_store.get_relation_spec(s, kind, spec); - relation_signature inner_sig; - collect_inner_signature(s, spec.m_inner_cols, inner_sig); - relation_base * inner = get_manager().mk_empty_relation(inner_sig, spec.m_inner_kind); - return mk_from_inner(s, spec.m_inner_cols.c_ptr(), inner); - } - - - relation_base * sieve_relation_plugin::mk_empty(const relation_signature & s) { - UNREACHABLE(); - return 0; -#if 0 - svector inner_cols(s.size()); - extract_inner_columns(s, inner_cols.c_ptr()); - return mk_empty(s, inner_cols.c_ptr()); -#endif - } - - sieve_relation * sieve_relation_plugin::mk_empty(const relation_signature & s, relation_plugin & inner_plugin) { - SASSERT(!inner_plugin.is_sieve_relation()); //it does not make sense to make a sieve of a sieve - svector inner_cols(s.size()); - extract_inner_columns(s, inner_plugin, inner_cols); - relation_signature inner_sig; - collect_inner_signature(s, inner_cols, inner_sig); - relation_base * inner_rel = inner_plugin.mk_empty(inner_sig); - return mk_from_inner(s, inner_cols, inner_rel); - } - - relation_base * sieve_relation_plugin::mk_full(func_decl* p, const relation_signature & s) { - relation_signature empty_sig; - relation_plugin& plugin = get_manager().get_appropriate_plugin(s); - relation_base * inner = plugin.mk_full(p, empty_sig, null_family_id); - svector inner_cols; - inner_cols.resize(s.size(), false); - return mk_from_inner(s, inner_cols, inner); - } - - sieve_relation * sieve_relation_plugin::mk_full(func_decl* p, const relation_signature & s, relation_plugin & inner_plugin) { - SASSERT(!inner_plugin.is_sieve_relation()); //it does not make sense to make a sieve of a sieve - svector inner_cols(s.size()); - extract_inner_columns(s, inner_plugin, inner_cols); - relation_signature inner_sig; - collect_inner_signature(s, inner_cols, inner_sig); - relation_base * inner_rel = inner_plugin.mk_full(p, inner_sig, null_family_id); - return mk_from_inner(s, inner_cols, inner_rel); - } - - class sieve_relation_plugin::join_fn : public convenient_relation_join_fn { - sieve_relation_plugin & m_plugin; - unsigned_vector m_inner_cols_1; - unsigned_vector m_inner_cols_2; - svector m_result_inner_cols; - - scoped_ptr m_inner_join_fun; - public: - join_fn(sieve_relation_plugin & p, const relation_base & r1, const relation_base & r2, unsigned col_cnt, - const unsigned * cols1, const unsigned * cols2, relation_join_fn * inner_join_fun) - : convenient_relation_join_fn(r1.get_signature(), r2.get_signature(), col_cnt, cols1, cols2), - m_plugin(p), - m_inner_join_fun(inner_join_fun) { - bool r1_sieved = r1.get_plugin().is_sieve_relation(); - bool r2_sieved = r2.get_plugin().is_sieve_relation(); - const sieve_relation * sr1 = r1_sieved ? static_cast(&r1) : 0; - const sieve_relation * sr2 = r2_sieved ? static_cast(&r2) : 0; - if(r1_sieved) { - m_result_inner_cols.append(sr1->m_inner_cols); - } - else { - m_result_inner_cols.resize(r1.get_signature().size(), true); - } - if(r2_sieved) { - m_result_inner_cols.append(sr2->m_inner_cols); - } - else { - m_result_inner_cols.resize(m_result_inner_cols.size() + r2.get_signature().size(), true); - } - } - - virtual relation_base * operator()(const relation_base & r1, const relation_base & r2) { - bool r1_sieved = r1.get_plugin().is_sieve_relation(); - bool r2_sieved = r2.get_plugin().is_sieve_relation(); - SASSERT(r1_sieved || r2_sieved); - const sieve_relation * sr1 = r1_sieved ? static_cast(&r1) : 0; - const sieve_relation * sr2 = r2_sieved ? static_cast(&r2) : 0; - const relation_base & inner1 = r1_sieved ? sr1->get_inner() : r1; - const relation_base & inner2 = r2_sieved ? sr2->get_inner() : r2; - - relation_base * inner_res = (*m_inner_join_fun)(inner1, inner2); - - return m_plugin.mk_from_inner(get_result_signature(), m_result_inner_cols.c_ptr(), inner_res); - } - }; - - relation_join_fn * sieve_relation_plugin::mk_join_fn(const relation_base & r1, const relation_base & r2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) { - if( &r1.get_plugin()!=this && &r2.get_plugin()!=this ) { - //we create just operations that involve the current plugin - return 0; - } - bool r1_sieved = r1.get_plugin().is_sieve_relation(); - bool r2_sieved = r2.get_plugin().is_sieve_relation(); - const sieve_relation * sr1 = r1_sieved ? static_cast(&r1) : 0; - const sieve_relation * sr2 = r2_sieved ? static_cast(&r2) : 0; - const relation_base & inner1 = r1_sieved ? sr1->get_inner() : r1; - const relation_base & inner2 = r2_sieved ? sr2->get_inner() : r2; - - unsigned_vector inner_cols1; - unsigned_vector inner_cols2; - - for(unsigned i=0; iis_inner_col(cols1[i])) { - continue; - } - if(r2_sieved && !sr2->is_inner_col(cols2[i])) { - continue; - } - inner_cols1.push_back( r1_sieved ? sr1->get_inner_col(cols1[i]) : cols1[i] ); - inner_cols2.push_back( r2_sieved ? sr2->get_inner_col(cols2[i]) : cols2[i] ); - } - - relation_join_fn * inner_join_fun = get_manager().mk_join_fn(inner1, inner2, inner_cols1, inner_cols2, false); - if(!inner_join_fun) { - return 0; - } - return alloc(join_fn, *this, r1, r2, col_cnt, cols1, cols2, inner_join_fun); - } - - - class sieve_relation_plugin::transformer_fn : public convenient_relation_transformer_fn { - svector m_result_inner_cols; - - scoped_ptr m_inner_fun; - public: - transformer_fn(relation_transformer_fn * inner_fun, const relation_signature & result_sig, - const bool * result_inner_cols) - : m_result_inner_cols(result_sig.size(), result_inner_cols), m_inner_fun(inner_fun) { - get_result_signature() = result_sig; - } - - virtual relation_base * operator()(const relation_base & r0) { - SASSERT(r0.get_plugin().is_sieve_relation()); - const sieve_relation & r = static_cast(r0); - sieve_relation_plugin & plugin = r.get_plugin(); - - relation_base * inner_res = (*m_inner_fun)(r.get_inner()); - - return plugin.mk_from_inner(get_result_signature(), m_result_inner_cols.c_ptr(), inner_res); - } - }; - - relation_transformer_fn * sieve_relation_plugin::mk_project_fn(const relation_base & r0, unsigned col_cnt, - const unsigned * removed_cols) { - if(&r0.get_plugin()!=this) { - return 0; - } - const sieve_relation & r = static_cast(r0); - unsigned_vector inner_removed_cols; - - for(unsigned i=0; i result_inner_cols = r.m_inner_cols; - project_out_vector_columns(result_inner_cols, col_cnt, removed_cols); - - relation_signature result_sig; - relation_signature::from_project(r.get_signature(), col_cnt, removed_cols, result_sig); - - relation_transformer_fn * inner_fun; - if(inner_removed_cols.empty()) { - inner_fun = alloc(identity_relation_transformer_fn); - } - else { - inner_fun = get_manager().mk_project_fn(r.get_inner(), inner_removed_cols); - } - - if(!inner_fun) { - return 0; - } - return alloc(transformer_fn, inner_fun, result_sig, result_inner_cols.c_ptr()); - } - - relation_transformer_fn * sieve_relation_plugin::mk_rename_fn(const relation_base & r0, - unsigned cycle_len, const unsigned * permutation_cycle) { - if(&r0.get_plugin()!=this) { - return 0; - } - const sieve_relation & r = static_cast(r0); - - unsigned sig_sz = r.get_signature().size(); - unsigned_vector permutation; - add_sequence(0, sig_sz, permutation); - permutate_by_cycle(permutation, cycle_len, permutation_cycle); - - bool inner_identity; - unsigned_vector inner_permutation; - collect_sub_permutation(permutation, r.m_sig2inner, inner_permutation, inner_identity); - - svector result_inner_cols = r.m_inner_cols; - permutate_by_cycle(result_inner_cols, cycle_len, permutation_cycle); - - relation_signature result_sig; - relation_signature::from_rename(r.get_signature(), cycle_len, permutation_cycle, result_sig); - - relation_transformer_fn * inner_fun = - get_manager().mk_permutation_rename_fn(r.get_inner(), inner_permutation); - if(!inner_fun) { - return 0; - } - return alloc(transformer_fn, inner_fun, result_sig, result_inner_cols.c_ptr()); - } - - - class sieve_relation_plugin::union_fn : public relation_union_fn { - scoped_ptr m_union_fun; - public: - union_fn(relation_union_fn * union_fun) : m_union_fun(union_fun) {} - - virtual void operator()(relation_base & tgt, const relation_base & src, relation_base * delta) { - bool tgt_sieved = tgt.get_plugin().is_sieve_relation(); - bool src_sieved = src.get_plugin().is_sieve_relation(); - bool delta_sieved = delta && delta->get_plugin().is_sieve_relation(); - sieve_relation * stgt = tgt_sieved ? static_cast(&tgt) : 0; - const sieve_relation * ssrc = src_sieved ? static_cast(&src) : 0; - sieve_relation * sdelta = delta_sieved ? static_cast(delta) : 0; - relation_base & itgt = tgt_sieved ? stgt->get_inner() : tgt; - const relation_base & isrc = src_sieved ? ssrc->get_inner() : src; - relation_base * idelta = delta_sieved ? &sdelta->get_inner() : delta; - - (*m_union_fun)(itgt, isrc, idelta); - } - }; - - relation_union_fn * sieve_relation_plugin::mk_union_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta) { - if(&tgt.get_plugin()!=this && &src.get_plugin()!=this && (delta && &delta->get_plugin()!=this)) { - //we create the operation only if it involves this plugin - return 0; - } - - bool tgt_sieved = tgt.get_plugin().is_sieve_relation(); - bool src_sieved = src.get_plugin().is_sieve_relation(); - bool delta_sieved = delta && delta->get_plugin().is_sieve_relation(); - const sieve_relation * stgt = tgt_sieved ? static_cast(&tgt) : 0; - const sieve_relation * ssrc = src_sieved ? static_cast(&src) : 0; - const sieve_relation * sdelta = delta_sieved ? static_cast(delta) : 0; - const relation_base & itgt = tgt_sieved ? stgt->get_inner() : tgt; - const relation_base & isrc = src_sieved ? ssrc->get_inner() : src; - const relation_base * idelta = delta_sieved ? &sdelta->get_inner() : delta; - - //Now we require that the sieved and inner columns must match on all relations. - //We may want to allow for some cases of misalignment even though it could introcude imprecision - if( tgt_sieved && src_sieved && (!delta || delta_sieved) ) { - if( !vectors_equal(stgt->m_inner_cols, ssrc->m_inner_cols) - || (delta && !vectors_equal(stgt->m_inner_cols, sdelta->m_inner_cols)) ) { - return 0; - } - } - else { - if( (stgt && !stgt->no_sieved_columns()) - || (ssrc && !ssrc->no_sieved_columns()) - || (sdelta && !sdelta->no_sieved_columns()) ) { - //We have an unsieved relation and then some relation with some sieved columns, - //which means there is an misalignment. - return 0; - } - } - - relation_union_fn * union_fun = get_manager().mk_union_fn(itgt, isrc, idelta); - if(!union_fun) { - return 0; - } - - return alloc(union_fn, union_fun); - } - - - class sieve_relation_plugin::filter_fn : public relation_mutator_fn { - scoped_ptr m_inner_fun; - public: - filter_fn(relation_mutator_fn * inner_fun) - : m_inner_fun(inner_fun) {} - - virtual void operator()(relation_base & r0) { - SASSERT(r0.get_plugin().is_sieve_relation()); - sieve_relation & r = static_cast(r0); - - (*m_inner_fun)(r.get_inner()); - } - }; - - relation_mutator_fn * sieve_relation_plugin::mk_filter_identical_fn(const relation_base & r0, - unsigned col_cnt, const unsigned * identical_cols) { - if(&r0.get_plugin()!=this) { - return 0; - } - const sieve_relation & r = static_cast(r0); - unsigned_vector inner_icols; - - //we ignore the columns which do not belong to the inner relation (which introduces imprecision) - for(unsigned i=0; i(r0); - if(!r.is_inner_col(col)) { - //if the column which do not belong to the inner relation, we do nothing (which introduces imprecision) - return alloc(identity_relation_mutator_fn); - } - unsigned inner_col = r.get_inner_col(col); - - relation_mutator_fn * inner_fun = get_manager().mk_filter_equal_fn(r.get_inner(), value, inner_col); - if(!inner_fun) { - return 0; - } - return alloc(filter_fn, inner_fun); - } - - relation_mutator_fn * sieve_relation_plugin::mk_filter_interpreted_fn(const relation_base & rb, - app * condition) { - if(&rb.get_plugin()!=this) { - return 0; - } - ast_manager & m = get_ast_manager(); - const sieve_relation & r = static_cast(rb); - const relation_signature sig = r.get_signature(); - unsigned sz = sig.size(); - - var_idx_set& cond_vars = get_context().get_rule_manager().collect_vars(condition); - expr_ref_vector subst_vect(m); - subst_vect.resize(sz); - unsigned subst_ofs = sz-1; - for(unsigned i=0; i m_inner_fun; - public: - negation_filter_fn(relation_intersection_filter_fn * inner_fun) - : m_inner_fun(inner_fun) {} - - virtual void operator()(relation_base & r, const relation_base & neg) { - bool r_sieved = r.get_plugin().is_sieve_relation(); - bool neg_sieved = neg.get_plugin().is_sieve_relation(); - SASSERT(r_sieved || neg_sieved); - sieve_relation * sr = r_sieved ? static_cast(&r) : 0; - const sieve_relation * sneg = neg_sieved ? static_cast(&neg) : 0; - relation_base & inner_r = r_sieved ? sr->get_inner() : r; - const relation_base & inner_neg = neg_sieved ? sneg->get_inner() : neg; - - (*m_inner_fun)(inner_r, inner_neg); - } - }; - - relation_intersection_filter_fn * sieve_relation_plugin::mk_filter_by_negation_fn(const relation_base & r, - const relation_base & neg, unsigned col_cnt, const unsigned * r_cols, - const unsigned * neg_cols) { - if(&r.get_plugin()!=this && &neg.get_plugin()!=this) { - //we create just operations that involve the current plugin - return 0; - } - bool r_sieved = r.get_plugin().is_sieve_relation(); - bool neg_sieved = neg.get_plugin().is_sieve_relation(); - SASSERT(r_sieved || neg_sieved); - const sieve_relation * sr = r_sieved ? static_cast(&r) : 0; - const sieve_relation * sneg = neg_sieved ? static_cast(&neg) : 0; - const relation_base & inner_r = r_sieved ? sr->get_inner() : r; - const relation_base & inner_neg = neg_sieved ? sneg->get_inner() : neg; - - unsigned_vector ir_cols; - unsigned_vector ineg_cols; - - for(unsigned i=0; iis_inner_col(r_cols[i]); - bool neg_col_inner = neg_sieved && !sneg->is_inner_col(neg_cols[i]); - if(r_col_inner && neg_col_inner) { - ir_cols.push_back( r_sieved ? sr->get_inner_col(i) : i ); - ineg_cols.push_back( neg_sieved ? sneg->get_inner_col(i) : i ); - } - else if(!r_col_inner && neg_col_inner) { - //Sieved (i.e. full) column in r is matched on an inner column in neg. - //If we assume the column in neg is not full, no rows from the inner relation of - //r would be removed. So in this case we perform no operation at cost of a little - //impresicion. - return alloc(identity_relation_intersection_filter_fn); - } - else { - //Inner or sieved column in r must match a sieved column in neg. - //Since sieved columns are full, this is always true so we can skip the equality. - continue; - } - } - - relation_intersection_filter_fn * inner_fun = - get_manager().mk_filter_by_negation_fn(inner_r, inner_neg, ir_cols, ineg_cols); - if(!inner_fun) { - return 0; - } - return alloc(negation_filter_fn, inner_fun); - } - - -}; diff --git a/src/muz/dl_sieve_relation.h b/src/muz/dl_sieve_relation.h deleted file mode 100644 index 551f5d705..000000000 --- a/src/muz/dl_sieve_relation.h +++ /dev/null @@ -1,197 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - dl_sieve_relation.h - -Abstract: - - - -Author: - - Krystof Hoder (t-khoder) 2010-11-11. - -Revision History: - ---*/ - -#ifndef _DL_SIEVE_RELATION_H_ -#define _DL_SIEVE_RELATION_H_ - -#include "dl_context.h" - -namespace datalog { - - class sieve_relation; - - class sieve_relation_plugin : public relation_plugin { - friend class sieve_relation; - public: - struct rel_spec { - svector m_inner_cols; - family_id m_inner_kind; - - /** - Create uninitialized rel_spec. - */ - rel_spec() {} - /** - \c inner_kind==null_family_id means we will not specify a relation kind when requesting - the relation object from the relation_manager. - - \c inner_kind==null_family_id cannot hold in a specification of existing relation object. - */ - rel_spec(unsigned sig_sz, const bool * inner_cols, family_id inner_kind=null_family_id) - : m_inner_cols(sig_sz, inner_cols), m_inner_kind(inner_kind) {} - - bool operator==(const rel_spec & o) const { - return m_inner_kind==o.m_inner_kind && vectors_equal(m_inner_cols, o.m_inner_cols); - } - - struct hash { - unsigned operator()(const rel_spec & s) const { - return svector_hash()(s.m_inner_cols)^s.m_inner_kind; - } - }; - }; - private: - - class join_fn; - class transformer_fn; - class union_fn; - class filter_fn; - class negation_filter_fn; - - rel_spec_store > m_spec_store; - - family_id get_relation_kind(sieve_relation & r, const bool * inner_columns); - - void extract_inner_columns(const relation_signature & s, relation_plugin & inner, - svector & inner_columns); - void extract_inner_signature(const relation_signature & s, relation_signature & inner_sig); - void collect_inner_signature(const relation_signature & s, const svector & inner_columns, - relation_signature & inner_sig); - public: - static symbol get_name() { return symbol("sieve_relation"); } - static sieve_relation_plugin& get_plugin(relation_manager & rmgr); - - static sieve_relation& get(relation_base& r); - static sieve_relation const & get(relation_base const& r); - static sieve_relation* get(relation_base* r); - static sieve_relation const* get(relation_base const* r); - - sieve_relation_plugin(relation_manager & manager); - - virtual void initialize(family_id fid); - - family_id get_relation_kind(const relation_signature & sig, const bool * inner_columns, - family_id inner_kind); - family_id get_relation_kind(const relation_signature & sig, const svector & inner_columns, - family_id inner_kind) { - SASSERT(sig.size()==inner_columns.size()); - return get_relation_kind(sig, inner_columns.c_ptr(), inner_kind); - } - - virtual bool can_handle_signature(const relation_signature & s); - - virtual relation_base * mk_empty(const relation_signature & s); - sieve_relation * mk_empty(const sieve_relation & original); - virtual relation_base * mk_empty(const relation_base & original); - virtual relation_base * mk_empty(const relation_signature & s, family_id kind); - sieve_relation * mk_empty(const relation_signature & s, relation_plugin & inner_plugin); - - virtual relation_base * mk_full(func_decl* p, const relation_signature & s); - sieve_relation * mk_full(func_decl* p, const relation_signature & s, relation_plugin & inner_plugin); - - - sieve_relation * mk_from_inner(const relation_signature & s, const bool * inner_columns, - relation_base * inner_rel); - sieve_relation * mk_from_inner(const relation_signature & s, const svector inner_columns, - relation_base * inner_rel) { - SASSERT(inner_columns.size()==s.size()); - return mk_from_inner(s, inner_columns.c_ptr(), inner_rel); - } - - protected: - - virtual relation_join_fn * mk_join_fn(const relation_base & t1, const relation_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2); - virtual relation_transformer_fn * mk_project_fn(const relation_base & t, unsigned col_cnt, - const unsigned * removed_cols); - virtual relation_transformer_fn * mk_rename_fn(const relation_base & t, unsigned permutation_cycle_len, - const unsigned * permutation_cycle); - virtual relation_union_fn * mk_union_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta); - virtual relation_mutator_fn * mk_filter_identical_fn(const relation_base & t, unsigned col_cnt, - const unsigned * identical_cols); - virtual relation_mutator_fn * mk_filter_equal_fn(const relation_base & t, const relation_element & value, - unsigned col); - virtual relation_mutator_fn * mk_filter_interpreted_fn(const relation_base & t, app * condition); - virtual relation_intersection_filter_fn * mk_filter_by_negation_fn(const relation_base & t, - const relation_base & negated_obj, unsigned joined_col_cnt, - const unsigned * t_cols, const unsigned * negated_cols); - }; - - - // ----------------------------------- - // - // sieve_relation - // - // ----------------------------------- - - class sieve_relation : public relation_base { - friend class sieve_relation_plugin; - friend class sieve_relation_plugin::join_fn; - friend class sieve_relation_plugin::transformer_fn; - friend class sieve_relation_plugin::union_fn; - friend class sieve_relation_plugin::filter_fn; - - svector m_inner_cols; - - unsigned_vector m_sig2inner; - unsigned_vector m_inner2sig; - unsigned_vector m_ignored_cols; //in ascending order, so that it can be used in project-like functions - - scoped_rel m_inner; - - - sieve_relation(sieve_relation_plugin & p, const relation_signature & s, - const bool * inner_columns, relation_base * inner); - - public: - sieve_relation_plugin & get_plugin() const { - return static_cast(relation_base::get_plugin()); - } - - bool is_inner_col(unsigned idx) const { return m_sig2inner[idx]!=UINT_MAX; } - unsigned get_inner_col(unsigned idx) const { - SASSERT(is_inner_col(idx)); - return m_sig2inner[idx]; - } - bool no_sieved_columns() const { return m_ignored_cols.size()==0; } - bool no_inner_columns() const { return m_ignored_cols.size()==get_signature().size(); } - - relation_base & get_inner() { return *m_inner; } - const relation_base & get_inner() const { return *m_inner; } - - virtual void add_fact(const relation_fact & f); - virtual bool contains_fact(const relation_fact & f) const; - virtual sieve_relation * clone() const; - virtual relation_base * complement(func_decl*p) const; - virtual void to_formula(expr_ref& fml) const; - - virtual bool empty() const { return get_inner().empty(); } - virtual void reset() { get_inner().reset(); } - virtual unsigned get_size_estimate_rows() const { return get_inner().get_size_estimate_rows(); } - virtual unsigned get_size_estimate_bytes() const { return get_inner().get_size_estimate_bytes(); } - - virtual void display(std::ostream & out) const; - }; - - -}; - -#endif /* _DL_SIEVE_RELATION_H_ */ - diff --git a/src/muz/dl_sparse_table.cpp b/src/muz/dl_sparse_table.cpp deleted file mode 100644 index 52d9618b8..000000000 --- a/src/muz/dl_sparse_table.cpp +++ /dev/null @@ -1,1246 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - dl_sparse_table.cpp - -Abstract: - - - -Author: - - Krystof Hoder (t-khoder) 2010-09-24. - -Revision History: - ---*/ - -#include -#include"dl_context.h" -#include"dl_util.h" -#include"dl_sparse_table.h" - -namespace datalog { - - // ----------------------------------- - // - // entry_storage - // - // ----------------------------------- - - entry_storage::store_offset entry_storage::insert_or_get_reserve_content() { - SASSERT(has_reserve()); - store_offset entry_ofs = m_data_indexer.insert_if_not_there(m_reserve); - if (m_reserve == entry_ofs) { - //entry inserted, so reserve is no longer a reserve - m_reserve = NO_RESERVE; - } - return entry_ofs; - } - bool entry_storage::insert_reserve_content() { - SASSERT(has_reserve()); - store_offset entry_ofs = m_data_indexer.insert_if_not_there(m_reserve); - if (m_reserve == entry_ofs) { - //entry inserted, so reserve is no longer a reserve - m_reserve = NO_RESERVE; - return true; - } - return false; - } - - bool entry_storage::remove_reserve_content() { - SASSERT(has_reserve()); - store_offset entry_ofs; - if (!find_reserve_content(entry_ofs)) { - //the fact was not in the table - return false; - } - remove_offset(entry_ofs); - return true; - } - - void entry_storage::remove_offset(store_offset ofs) { - m_data_indexer.remove(ofs); - store_offset last_ofs = after_last_offset() - m_entry_size; - if (ofs!=last_ofs) { - SASSERT(ofs + m_entry_size <= last_ofs); - //we don't want any holes, so we put the last element at the place - //of the removed one - m_data_indexer.remove(last_ofs); - char * base = &m_data.get(0); - memcpy(base+ofs, base+last_ofs, m_entry_size); - m_data_indexer.insert(ofs); - } - if (has_reserve()) { - //we already have a reserve, so we need to shrink a little to keep having just one - resize_data(m_data_size-m_entry_size); - } - m_reserve=last_ofs; - } - - unsigned entry_storage::get_size_estimate_bytes() const { - unsigned sz = m_data.capacity(); - sz += m_data_indexer.capacity()*sizeof(storage_indexer::entry); - return sz; - } - - // ----------------------------------- - // - // sparse_table::column_layout - // - // ----------------------------------- - - unsigned get_domain_length(uint64 dom_size) { - SASSERT(dom_size>0); - - unsigned length = 0; - - unsigned dom_size_sm; - if (dom_size>UINT_MAX) { - dom_size_sm = static_cast(dom_size>>32); - length += 32; - if ( (dom_size&UINT_MAX)!=0 && dom_size_sm!=UINT_MAX ) { - dom_size_sm++; - } - } - else { - dom_size_sm=static_cast(dom_size); - } - if (dom_size_sm == 1) { - length += 1; //unary domains - } - else if (dom_size_sm > 0x80000000u) { - length += 32; - } - else { - length += get_num_1bits(next_power_of_two(dom_size_sm)-1); //ceil(log2(dom_size)) - } - return length; - } - - sparse_table::column_layout::column_layout(const table_signature & sig) - : m_functional_col_cnt(sig.functional_columns()) { - SASSERT(sig.size() > 0); - unsigned ofs = 0; - unsigned sig_sz = sig.size(); - unsigned first_functional = sig_sz-m_functional_col_cnt; - for (unsigned i=0; i0); - SASSERT(length<=64); - - if (size() > 0 && (length > 54 || i == first_functional)) { - //large domains must start byte-aligned, as well as functional columns - make_byte_aligned_end(size()-1); - ofs = back().next_ofs(); - } - - push_back(column_info(ofs, length)); - ofs += length; - } - make_byte_aligned_end(size()-1); - SASSERT(back().next_ofs()%8 == 0);//the entries must be aligned to whole bytes - m_entry_size = back().next_ofs()/8; - if (m_functional_col_cnt) { - SASSERT((*this)[first_functional].m_offset%8 == 0); - m_functional_part_size = m_entry_size - (*this)[first_functional].m_offset/8; - } - else { - m_functional_part_size = 0; - } - } - - void sparse_table::column_layout::make_byte_aligned_end(unsigned col_index0) { - unsigned ofs = (*this)[col_index0].next_ofs(); - unsigned ofs_bit_part = ofs%8; - unsigned rounded_ofs = (ofs_bit_part == 0) ? ofs : (ofs+8-ofs_bit_part); - - if (rounded_ofs!=ofs) { - SASSERT(rounded_ofs>ofs); - int diff = rounded_ofs-ofs; - unsigned col_idx = col_index0+1; - while(diff!=0) { - //we should always be able to fix the alignment by the time we reach zero - SASSERT(col_idx>0); - col_idx--; - column_info & ci = (*this)[col_idx]; - unsigned new_length = ci.m_length; - if (ci.m_length < 64) { - unsigned swallowed = std::min(64-static_cast(ci.m_length), diff); - diff -= swallowed; - new_length += swallowed; - } - unsigned new_ofs = ci.m_offset+diff; - ci = column_info(new_ofs, new_length); - } - } - - SASSERT(rounded_ofs%8 == 0); - SASSERT((*this)[col_index0].next_ofs()%8 == 0); - } - - // ----------------------------------- - // - // sparse_table - // - // ----------------------------------- - - class sparse_table::our_iterator_core : public iterator_core { - - class our_row : public row_interface { - const our_iterator_core & m_parent; - public: - our_row(const sparse_table & t, const our_iterator_core & parent) : - row_interface(t), - m_parent(parent) {} - - virtual table_element operator[](unsigned col) const { - return m_parent.m_layout.get(m_parent.m_ptr, col); - } - - }; - - const char * m_end; - const char * m_ptr; - unsigned m_fact_size; - our_row m_row_obj; - const column_layout & m_layout; - - public: - our_iterator_core(const sparse_table & t, bool finished) : - m_end(t.m_data.after_last()), - m_ptr(finished ? m_end : t.m_data.begin()), - m_fact_size(t.m_fact_size), - m_row_obj(t, *this), - m_layout(t.m_column_layout) {} - - virtual bool is_finished() const { - return m_ptr == m_end; - } - - virtual row_interface & operator*() { - SASSERT(!is_finished()); - return m_row_obj; - } - virtual void operator++() { - SASSERT(!is_finished()); - m_ptr+=m_fact_size; - } - }; - - class sparse_table::key_indexer { - protected: - unsigned_vector m_key_cols; - public: - typedef const store_offset * offset_iterator; - - /** - Iterators returned by \c begin() and \c end() are valid only as long as the \c query_result - object that returned them exists. - */ - struct query_result { - private: - bool m_singleton; - union { - store_offset m_single_result; - struct { - offset_iterator begin; - offset_iterator end; - } m_many; - }; - public: - /** - \brief Empty result. - */ - query_result() : m_singleton(false) { - m_many.begin = 0; - m_many.end = 0; - } - query_result(offset_iterator begin, offset_iterator end) : m_singleton(false) { - m_many.begin = begin; - m_many.end = end; - } - query_result(store_offset single_result) : m_singleton(true), m_single_result(single_result) {} - - offset_iterator begin() const { return m_singleton ? &m_single_result : m_many.begin; } - offset_iterator end() const { return m_singleton ? (&m_single_result+1) : m_many.end; } - bool empty() const { return begin() == end(); } - }; - - key_indexer(unsigned key_len, const unsigned * key_cols) - : m_key_cols(key_len, key_cols) {} - - virtual ~key_indexer() {} - - virtual void update(const sparse_table & t) {} - - virtual query_result get_matching_offsets(const key_value & key) const = 0; - }; - - - class sparse_table::general_key_indexer : public key_indexer { - typedef svector offset_vector; - typedef u_map index_map; - - index_map m_map; - mutable entry_storage m_keys; - store_offset m_first_nonindexed; - - - void key_to_reserve(const key_value & key) const { - m_keys.ensure_reserve(); - m_keys.write_into_reserve(reinterpret_cast(key.c_ptr())); - } - - offset_vector & get_matching_offset_vector(const key_value & key) { - key_to_reserve(key); - store_offset ofs = m_keys.insert_or_get_reserve_content(); - index_map::entry * e = m_map.find_core(ofs); - if (!e) { - TRACE("dl_table_relation", tout << "inserting\n";); - e = m_map.insert_if_not_there2(ofs, offset_vector()); - } - return e->get_data().m_value; - } - public: - general_key_indexer(unsigned key_len, const unsigned * key_cols) - : key_indexer(key_len, key_cols), - m_keys(key_len*sizeof(table_element)), - m_first_nonindexed(0) {} - - virtual void update(const sparse_table & t) { - if (m_first_nonindexed == t.m_data.after_last_offset()) { - return; - } - SASSERT(m_first_nonindexedinsert(ofs); - } - - m_first_nonindexed = t.m_data.after_last_offset(); - } - - virtual query_result get_matching_offsets(const key_value & key) const { - key_to_reserve(key); - store_offset ofs; - if (!m_keys.find_reserve_content(ofs)) { - return query_result(); - } - index_map::entry * e = m_map.find_core(ofs); - if (!e) { - return query_result(); - } - const offset_vector & res = e->get_data().m_value; - return query_result(res.begin(), res.end()); - } - }; - - /** - When doing lookup using this index, the content of the reserve in sparse_table::m_data changes. - */ - class sparse_table::full_signature_key_indexer : public key_indexer { - const sparse_table & m_table; - - /** - Permutation of key columns to make it into table facts. If empty, no permutation is necessary. - */ - unsigned_vector m_permutation; - mutable table_fact m_key_fact; - public: - - static bool can_handle(unsigned key_len, const unsigned * key_cols, const sparse_table & t) { - unsigned non_func_cols = t.get_signature().first_functional(); - if (key_len!=non_func_cols) { - return false; - } - counter ctr; - ctr.count(key_len, key_cols); - if (ctr.get_max_counter_value()!=1 || ctr.get_max_positive()!=non_func_cols-1) { - return false; - } - SASSERT(ctr.get_positive_count() == non_func_cols); - return true; - } - - full_signature_key_indexer(unsigned key_len, const unsigned * key_cols, const sparse_table & t) - : key_indexer(key_len, key_cols), - m_table(t) { - SASSERT(can_handle(key_len, key_cols, t)); - - m_permutation.resize(key_len); - for (unsigned i=0; i(m_table); - t.write_into_reserve(m_key_fact.c_ptr()); - - store_offset res; - if (!t.m_data.find_reserve_content(res)) { - return query_result(); - } - return query_result(res); - } - }; - - sparse_table::sparse_table(sparse_table_plugin & p, const table_signature & sig, unsigned init_capacity) - : table_base(p, sig), - m_column_layout(sig), - m_fact_size(m_column_layout.m_entry_size), - m_data(m_fact_size, m_column_layout.m_functional_part_size, init_capacity) {} - - sparse_table::sparse_table(const sparse_table & t) - : table_base(t.get_plugin(), t.get_signature()), - m_column_layout(t.m_column_layout), - m_fact_size(t.m_fact_size), - m_data(t.m_data) {} - - table_base * sparse_table::clone() const { - return get_plugin().mk_clone(*this); - } - - sparse_table::~sparse_table() { - reset_indexes(); - } - - void sparse_table::reset() { - reset_indexes(); - m_data.reset(); - } - - table_base::iterator sparse_table::begin() const { - return mk_iterator(alloc(our_iterator_core, *this, false)); - } - - table_base::iterator sparse_table::end() const { - return mk_iterator(alloc(our_iterator_core, *this, true)); - } - - sparse_table::key_indexer& sparse_table::get_key_indexer(unsigned key_len, - const unsigned * key_cols) const { -#if Z3DEBUG - //We allow indexes only on non-functional columns because we want to be able to modify them - //without having to worry about updating indexes. - //Maybe we might keep a list of indexes that contain functional columns and on an update reset - //only those. - SASSERT(key_len == 0 || - counter().count(key_len, key_cols).get_max_positive()get_data().m_value) { - if (full_signature_key_indexer::can_handle(key_len, key_cols, *this)) { - key_map_entry->get_data().m_value = alloc(full_signature_key_indexer, key_len, key_cols, *this); - } - else { - key_map_entry->get_data().m_value = alloc(general_key_indexer, key_len, key_cols); - } - } - key_indexer & indexer = *key_map_entry->get_data().m_value; - indexer.update(*this); - return indexer; - } - - void sparse_table::reset_indexes() { - key_index_map::iterator kmit = m_key_indexes.begin(); - key_index_map::iterator kmend = m_key_indexes.end(); - for (; kmit!=kmend; ++kmit) { - dealloc((*kmit).m_value); - } - m_key_indexes.reset(); - } - - void sparse_table::write_into_reserve(const table_element* f) { - TRACE("dl_table_relation", tout << "\n";); - m_data.ensure_reserve(); - char * reserve = m_data.get_reserve_ptr(); - unsigned col_cnt = m_column_layout.size(); - for (unsigned i = 0; i < col_cnt; ++i) { - SASSERT(f[i] < get_signature()[i]); //the value fits into the table signature - m_column_layout.set(reserve, i, f[i]); - } - } - - bool sparse_table::add_fact(const char * data) { - m_data.write_into_reserve(data); - return add_reserve_content(); - } - - void sparse_table::add_fact(const table_fact & f) { - write_into_reserve(f.c_ptr()); - add_reserve_content(); - } - - bool sparse_table::add_reserve_content() { - return m_data.insert_reserve_content(); - } - - bool sparse_table::contains_fact(const table_fact & f) const { - sparse_table & t = const_cast(*this); - t.write_into_reserve(f.c_ptr()); - unsigned func_col_cnt = get_signature().functional_columns(); - if (func_col_cnt == 0) { - return t.m_data.reserve_content_already_present(); - } - else { - store_offset ofs; - if (!t.m_data.find_reserve_content(ofs)) { - return false; - } - unsigned sz = get_signature().size(); - for (unsigned i=func_col_cnt; i(*this); - t.write_into_reserve(f.c_ptr()); - store_offset ofs; - if (!t.m_data.find_reserve_content(ofs)) { - return false; - } - unsigned sz = sig.size(); - for (unsigned i=sig.first_functional(); ipre_projection_idx); - dest_layout.set(dest, dest_idx++, src_layout.get(src, i)); - } - } - - void sparse_table::concatenate_rows(const column_layout & layout1, const column_layout & layout2, - const column_layout & layout_res, const char * ptr1, const char * ptr2, char * res, - const unsigned * removed_cols) { - unsigned t1non_func = layout1.size()-layout1.m_functional_col_cnt; - unsigned t2non_func = layout2.size()-layout2.m_functional_col_cnt; - unsigned t1cols = layout1.size(); - unsigned t2cols = layout2.size(); - unsigned orig_i = 0; - unsigned res_i = 0; - const unsigned * next_removed = removed_cols; - copy_columns(layout1, layout_res, 0, t1non_func, ptr1, res, res_i, orig_i, next_removed); - copy_columns(layout2, layout_res, 0, t2non_func, ptr2, res, res_i, orig_i, next_removed); - copy_columns(layout1, layout_res, t1non_func, t1cols, ptr1, res, res_i, orig_i, next_removed); - copy_columns(layout2, layout_res, t2non_func, t2cols, ptr2, res, res_i, orig_i, next_removed); - } - - void sparse_table::garbage_collect() { - if (memory::above_high_watermark()) { - get_plugin().garbage_collect(); - } - if (memory::above_high_watermark()) { - IF_VERBOSE(1, verbose_stream() << "Ran out of memory while filling table of size: " << get_size_estimate_rows() << " rows " << get_size_estimate_bytes() << " bytes\n";); - throw out_of_memory_error(); - } - } - - void sparse_table::self_agnostic_join_project(const sparse_table & t1, const sparse_table & t2, - unsigned joined_col_cnt, const unsigned * t1_joined_cols, const unsigned * t2_joined_cols, - const unsigned * removed_cols, bool tables_swapped, sparse_table & result) { - - unsigned t1_entry_size = t1.m_fact_size; - unsigned t2_entry_size = t2.m_fact_size; - - unsigned t1idx = 0; - unsigned t1end = t1.m_data.after_last_offset(); - - TRACE("dl_table_relation", - tout << "joined_col_cnt: " << joined_col_cnt << "\n"; - tout << "t1_entry_size: " << t1_entry_size << "\n"; - tout << "t2_entry_size: " << t2_entry_size << "\n"; - t1.display(tout); - t2.display(tout); - tout << (&t1) << " " << (&t2) << " " << (&result) << "\n"; - ); - - if (joined_col_cnt == 0) { - unsigned t2idx = 0; - unsigned t2end = t2.m_data.after_last_offset(); - - for (; t1idx!=t1end; t1idx+=t1_entry_size) { - for (t2idx = 0; t2idx != t2end; t2idx += t2_entry_size) { - result.m_data.ensure_reserve(); - result.garbage_collect(); - char * res_reserve = result.m_data.get_reserve_ptr(); - char const* t1ptr = t1.get_at_offset(t1idx); - char const* t2ptr = t2.get_at_offset(t2idx); - if (tables_swapped) { - concatenate_rows(t2.m_column_layout, t1.m_column_layout, result.m_column_layout, - t2ptr, t1ptr, res_reserve, removed_cols); - } else { - concatenate_rows(t1.m_column_layout, t2.m_column_layout, result.m_column_layout, - t1ptr, t2ptr, res_reserve, removed_cols); - } - result.add_reserve_content(); - } - } - return; - } - - key_value t1_key; - t1_key.resize(joined_col_cnt); - key_indexer& t2_indexer = t2.get_key_indexer(joined_col_cnt, t2_joined_cols); - - bool key_modified = true; - key_indexer::query_result t2_offsets; - - for (; t1idx != t1end; t1idx += t1_entry_size) { - for (unsigned i = 0; i < joined_col_cnt; i++) { - table_element val = t1.m_column_layout.get(t1.get_at_offset(t1idx), t1_joined_cols[i]); - TRACE("dl_table_relation", tout << "val: " << val << " " << t1idx << " " << t1_joined_cols[i] << "\n";); - if (t1_key[i] != val) { - t1_key[i] = val; - key_modified = true; - } - } - if (key_modified) { - t2_offsets = t2_indexer.get_matching_offsets(t1_key); - key_modified = false; - } - - if (t2_offsets.empty()) { - continue; - } - - key_indexer::offset_iterator t2ofs_it = t2_offsets.begin(); - key_indexer::offset_iterator t2ofs_end = t2_offsets.end(); - for (; t2ofs_it != t2ofs_end; ++t2ofs_it) { - store_offset t2ofs = *t2ofs_it; - result.m_data.ensure_reserve(); - result.garbage_collect(); - char * res_reserve = result.m_data.get_reserve_ptr(); - char const * t1ptr = t1.get_at_offset(t1idx); - char const * t2ptr = t2.get_at_offset(t2ofs); - if (tables_swapped) { - concatenate_rows(t2.m_column_layout, t1.m_column_layout, result.m_column_layout, - t2ptr, t1ptr, res_reserve, removed_cols); - } else { - concatenate_rows(t1.m_column_layout, t2.m_column_layout, result.m_column_layout, - t1ptr, t2ptr, res_reserve, removed_cols); - } - result.add_reserve_content(); - } - } - } - - - // ----------------------------------- - // - // sparse_table_plugin - // - // ----------------------------------- - - sparse_table_plugin::sparse_table_plugin(relation_manager & manager) - : table_plugin(symbol("sparse"), manager) {} - - sparse_table_plugin::~sparse_table_plugin() { - reset(); - } - - void sparse_table_plugin::reset() { - table_pool::iterator it = m_pool.begin(); - table_pool::iterator end = m_pool.end(); - for (; it!=end; ++it) { - sp_table_vector * vect = it->m_value; - sp_table_vector::iterator it = vect->begin(); - sp_table_vector::iterator end = vect->end(); - for (; it!=end; ++it) { - (*it)->destroy(); //calling deallocate() would only put the table back into the pool - } - dealloc(vect); - } - m_pool.reset(); - } - - void sparse_table_plugin::garbage_collect() { - IF_VERBOSE(2, verbose_stream() << "garbage collecting "<< memory::get_allocation_size() << " bytes down to ";); - reset(); - IF_VERBOSE(2, verbose_stream() << memory::get_allocation_size() << " bytes\n";); - } - - void sparse_table_plugin::recycle(sparse_table * t) { - const table_signature & sig = t->get_signature(); - t->reset(); - - table_pool::entry * e = m_pool.insert_if_not_there2(sig, 0); - sp_table_vector * & vect = e->get_data().m_value; - if (vect == 0) { - vect = alloc(sp_table_vector); - } - IF_VERBOSE(12, verbose_stream() << "Recycle: " << t->get_size_estimate_bytes() << "\n";); - - vect->push_back(t); - } - - table_base * sparse_table_plugin::mk_empty(const table_signature & s) { - SASSERT(can_handle_signature(s)); - - sp_table_vector * vect; - if (!m_pool.find(s, vect) || vect->empty()) { - return alloc(sparse_table, *this, s); - } - sparse_table * res = vect->back(); - vect->pop_back(); - return res; - } - - sparse_table * sparse_table_plugin::mk_clone(const sparse_table & t) { - sparse_table * res = static_cast(mk_empty(t.get_signature())); - res->m_data = t.m_data; - return res; - } - - - bool sparse_table_plugin::join_involves_functional(const table_signature & s1, const table_signature & s2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) { - if (col_cnt == 0) { - return false; - } - return counter().count(col_cnt, cols1).get_max_positive()>=s1.first_functional() - || counter().count(col_cnt, cols2).get_max_positive()>=s2.first_functional(); - } - - - class sparse_table_plugin::join_project_fn : public convenient_table_join_project_fn { - public: - join_project_fn(const table_signature & t1_sig, const table_signature & t2_sig, unsigned col_cnt, - const unsigned * cols1, const unsigned * cols2, unsigned removed_col_cnt, - const unsigned * removed_cols) - : convenient_table_join_project_fn(t1_sig, t2_sig, col_cnt, cols1, cols2, - removed_col_cnt, removed_cols) { - m_removed_cols.push_back(UINT_MAX); - } - - virtual table_base * operator()(const table_base & tb1, const table_base & tb2) { - - const sparse_table & t1 = static_cast(tb1); - const sparse_table & t2 = static_cast(tb2); - - sparse_table_plugin & plugin = t1.get_plugin(); - - sparse_table * res = static_cast(plugin.mk_empty(get_result_signature())); - - //If we join with some intersection, want to iterate over the smaller table and - //do indexing into the bigger one. If we simply do a product, we want the bigger - //one to be at the outer iteration (then the small one will hopefully fit into - //the cache) - if ( (t1.row_count() > t2.row_count()) == (!m_cols1.empty()) ) { - sparse_table::self_agnostic_join_project(t2, t1, m_cols1.size(), m_cols2.c_ptr(), - m_cols1.c_ptr(), m_removed_cols.c_ptr(), true, *res); - } - else { - sparse_table::self_agnostic_join_project(t1, t2, m_cols1.size(), m_cols1.c_ptr(), - m_cols2.c_ptr(), m_removed_cols.c_ptr(), false, *res); - } - TRACE("dl_table_relation", tb1.display(tout); tb2.display(tout); res->display(tout); ); - return res; - } - }; - - table_join_fn * sparse_table_plugin::mk_join_fn(const table_base & t1, const table_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) { - const table_signature & sig1 = t1.get_signature(); - const table_signature & sig2 = t2.get_signature(); - if (t1.get_kind()!=get_kind() || t2.get_kind()!=get_kind() - || join_involves_functional(sig1, sig2, col_cnt, cols1, cols2)) { - //We also don't allow indexes on functional columns (and they are needed for joins) - return 0; - } - return mk_join_project_fn(t1, t2, col_cnt, cols1, cols2, 0, static_cast(0)); - } - - table_join_fn * sparse_table_plugin::mk_join_project_fn(const table_base & t1, const table_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2, unsigned removed_col_cnt, - const unsigned * removed_cols) { - const table_signature & sig1 = t1.get_signature(); - const table_signature & sig2 = t2.get_signature(); - if (t1.get_kind()!=get_kind() || t2.get_kind()!=get_kind() - || removed_col_cnt == t1.get_signature().size()+t2.get_signature().size() - || join_involves_functional(sig1, sig2, col_cnt, cols1, cols2)) { - //We don't allow sparse tables with zero signatures (and project on all columns leads to such) - //We also don't allow indexes on functional columns. - return 0; - } - return alloc(join_project_fn, t1.get_signature(), t2.get_signature(), col_cnt, cols1, cols2, - removed_col_cnt, removed_cols); - } - - class sparse_table_plugin::union_fn : public table_union_fn { - public: - virtual void operator()(table_base & tgt0, const table_base & src0, table_base * delta0) { - - sparse_table & tgt = static_cast(tgt0); - const sparse_table & src = static_cast(src0); - sparse_table * delta = static_cast(delta0); - - unsigned fact_size = tgt.m_fact_size; - const char* ptr = src.m_data.begin(); - const char* after_last=src.m_data.after_last(); - for (; ptradd_fact(ptr); - } - } - } - }; - - table_union_fn * sparse_table_plugin::mk_union_fn(const table_base & tgt, const table_base & src, - const table_base * delta) { - if (tgt.get_kind()!=get_kind() || src.get_kind()!=get_kind() - || (delta && delta->get_kind()!=get_kind()) - || tgt.get_signature()!=src.get_signature() - || (delta && delta->get_signature()!=tgt.get_signature())) { - return 0; - } - return alloc(union_fn); - } - - class sparse_table_plugin::project_fn : public convenient_table_project_fn { - const unsigned m_inp_col_cnt; - const unsigned m_removed_col_cnt; - const unsigned m_result_col_cnt; - public: - project_fn(const table_signature & orig_sig, unsigned removed_col_cnt, const unsigned * removed_cols) - : convenient_table_project_fn(orig_sig, removed_col_cnt, removed_cols), - m_inp_col_cnt(orig_sig.size()), - m_removed_col_cnt(removed_col_cnt), - m_result_col_cnt(orig_sig.size()-removed_col_cnt) { - SASSERT(removed_col_cnt>0); - } - - virtual void transform_row(const char * src, char * tgt, - const sparse_table::column_layout & src_layout, - const sparse_table::column_layout & tgt_layout) { - unsigned r_idx=0; - unsigned tgt_i=0; - for (unsigned i=0; i(tb); - - unsigned t_fact_size = t.m_fact_size; - - sparse_table_plugin & plugin = t.get_plugin(); - sparse_table * res = static_cast(plugin.mk_empty(get_result_signature())); - - const sparse_table::column_layout & src_layout = t.m_column_layout; - const sparse_table::column_layout & tgt_layout = res->m_column_layout; - - const char* t_ptr = t.m_data.begin(); - const char* t_end = t.m_data.after_last(); - for (; t_ptr!=t_end; t_ptr+=t_fact_size) { - SASSERT(t_ptrm_data.ensure_reserve(); - char * res_ptr = res->m_data.get_reserve_ptr(); - transform_row(t_ptr, res_ptr, src_layout, tgt_layout); - res->m_data.insert_reserve_content(); - } - return res; - } - }; - - table_transformer_fn * sparse_table_plugin::mk_project_fn(const table_base & t, unsigned col_cnt, - const unsigned * removed_cols) { - if (col_cnt == t.get_signature().size()) { - return 0; - } - return alloc(project_fn, t.get_signature(), col_cnt, removed_cols); - } - - - class sparse_table_plugin::select_equal_and_project_fn : public convenient_table_transformer_fn { - const unsigned m_col; - sparse_table::key_value m_key; - public: - select_equal_and_project_fn(const table_signature & orig_sig, table_element val, unsigned col) - : m_col(col) { - table_signature::from_project(orig_sig, 1, &col, get_result_signature()); - m_key.push_back(val); - } - - virtual table_base * operator()(const table_base & tb) { - const sparse_table & t = static_cast(tb); - - sparse_table_plugin & plugin = t.get_plugin(); - sparse_table * res = static_cast(plugin.mk_empty(get_result_signature())); - - const sparse_table::column_layout & t_layout = t.m_column_layout; - const sparse_table::column_layout & res_layout = res->m_column_layout; - unsigned t_cols = t_layout.size(); - - sparse_table::key_indexer & indexer = t.get_key_indexer(1, &m_col); - sparse_table::key_indexer::query_result t_offsets = indexer.get_matching_offsets(m_key); - if (t_offsets.empty()) { - //no matches - return res; - } - sparse_table::key_indexer::offset_iterator ofs_it=t_offsets.begin(); - sparse_table::key_indexer::offset_iterator ofs_end=t_offsets.end(); - - for (; ofs_it!=ofs_end; ++ofs_it) { - sparse_table::store_offset t_ofs = *ofs_it; - const char * t_ptr = t.get_at_offset(t_ofs); - - res->m_data.ensure_reserve(); - char * res_reserve = res->m_data.get_reserve_ptr(); - - unsigned res_i = 0; - for (unsigned i=0; iadd_reserve_content(); - } - return res; - } - }; - - table_transformer_fn * sparse_table_plugin::mk_select_equal_and_project_fn(const table_base & t, - const table_element & value, unsigned col) { - if (t.get_kind()!=get_kind() || t.get_signature().size() == 1 || col>=t.get_signature().first_functional()) { - //We don't allow sparse tables with zero signatures (and project on a single - //column table produces one). - //We also don't allow indexes on functional columns. And our implementation of - //select_equal_and_project uses index on \c col. - return 0; - } - return alloc(select_equal_and_project_fn, t.get_signature(), value, col); - } - - - class sparse_table_plugin::rename_fn : public convenient_table_rename_fn { - unsigned_vector m_out_of_cycle; - public: - rename_fn(const table_signature & orig_sig, unsigned permutation_cycle_len, const unsigned * permutation_cycle) - : convenient_table_rename_fn(orig_sig, permutation_cycle_len, permutation_cycle) { - SASSERT(permutation_cycle_len>=2); - idx_set cycle_cols; - for (unsigned i=0; i < permutation_cycle_len; ++i) { - cycle_cols.insert(permutation_cycle[i]); - } - for (unsigned i=0; i < orig_sig.size(); ++i) { - if (!cycle_cols.contains(i)) { - m_out_of_cycle.push_back(i); - } - } - } - - void transform_row(const char * src, char * tgt, - const sparse_table::column_layout & src_layout, - const sparse_table::column_layout & tgt_layout) { - - for (unsigned i=1; i < m_cycle.size(); ++i) { - tgt_layout.set(tgt, m_cycle[i-1], src_layout.get(src, m_cycle[i])); - } - tgt_layout.set(tgt, m_cycle[m_cycle.size()-1], src_layout.get(src, m_cycle[0])); - - unsigned_vector::const_iterator it = m_out_of_cycle.begin(); - unsigned_vector::const_iterator end = m_out_of_cycle.end(); - for (; it!=end; ++it) { - unsigned col = *it; - tgt_layout.set(tgt, col, src_layout.get(src, col)); - } - } - - virtual table_base * operator()(const table_base & tb) { - - const sparse_table & t = static_cast(tb); - - unsigned t_fact_size = t.m_fact_size; - - sparse_table_plugin & plugin = t.get_plugin(); - sparse_table * res = static_cast(plugin.mk_empty(get_result_signature())); - - unsigned res_fact_size = res->m_fact_size; - unsigned res_data_size = res_fact_size*t.row_count(); - - res->m_data.resize_data(res_data_size); - - //here we can separate data creatin and insertion into hashmap, since we know - //that no row will become duplicit - - //create the data - const char* t_ptr = t.m_data.begin(); - char* res_ptr = res->m_data.begin(); - char* res_end = res_ptr+res_data_size; - for (; res_ptr!=res_end; t_ptr+=t_fact_size, res_ptr+=res_fact_size) { - transform_row(t_ptr, res_ptr, t.m_column_layout, res->m_column_layout); - } - - //and insert them into the hash-map - for (unsigned i=0; i!=res_data_size; i+=res_fact_size) { - TRUSTME(res->m_data.insert_offset(i)); - } - - return res; - } - }; - - table_transformer_fn * sparse_table_plugin::mk_rename_fn(const table_base & t, unsigned permutation_cycle_len, - const unsigned * permutation_cycle) { - if (t.get_kind()!=get_kind()) { - return 0; - } - return alloc(rename_fn, t.get_signature(), permutation_cycle_len, permutation_cycle); - } - - class sparse_table_plugin::negation_filter_fn : public convenient_table_negation_filter_fn { - typedef sparse_table::store_offset store_offset; - typedef sparse_table::key_value key_value; - typedef sparse_table::key_indexer key_indexer; - - bool m_joining_neg_non_functional; - - /** - Used by \c collect_intersection_offsets function. - If tgt_is_first is false, contains the same items as \c res. - */ - idx_set m_intersection_content; - - public: - negation_filter_fn(const table_base & tgt, const table_base & neg, - unsigned joined_col_cnt, const unsigned * t_cols, const unsigned * negated_cols) - : convenient_table_negation_filter_fn(tgt, neg, joined_col_cnt, t_cols, negated_cols) { - unsigned neg_fisrt_func = neg.get_signature().first_functional(); - counter ctr; - ctr.count(m_cols2); - m_joining_neg_non_functional = ctr.get_max_counter_value() == 1 - && ctr.get_positive_count() == neg_fisrt_func - && (neg_fisrt_func == 0 || ctr.get_max_positive() == neg_fisrt_func-1); - } - - /** - Collect offsets of rows in \c t1 or \c t2 (depends on whether \c tgt_is_first is true or false) - that have a match in the other table into \c res. Offsets in \c res are in ascending order. - */ - void collect_intersection_offsets(const sparse_table & t1, const sparse_table & t2, - bool tgt_is_first, svector & res) { - SASSERT(res.empty()); - - if (!tgt_is_first) { - m_intersection_content.reset(); - } - - unsigned joined_col_cnt = m_cols1.size(); - unsigned t1_entry_size = t1.m_data.entry_size(); - - const unsigned * cols1 = tgt_is_first ? m_cols1.c_ptr() : m_cols2.c_ptr(); - const unsigned * cols2 = tgt_is_first ? m_cols2.c_ptr() : m_cols1.c_ptr(); - - key_value t1_key; - t1_key.resize(joined_col_cnt); - key_indexer & t2_indexer = t2.get_key_indexer(joined_col_cnt, cols2); - - bool key_modified=true; - key_indexer::query_result t2_offsets; - store_offset t1_after_last = t1.m_data.after_last_offset(); - for (store_offset t1_ofs=0; t1_ofs(tgt0); - const sparse_table & neg = static_cast(neg0); - - if (m_cols1.size() == 0) { - if (!neg.empty()) { - tgt.reset(); - } - return; - } - - svector to_remove; //offsets here are in increasing order - - //We don't do just the simple tgt.row_count()>neg.row_count() because the swapped case is - //more expensive. The constant 4 is, however, just my guess what the ratio might be. - if (tgt.row_count()/4>neg.row_count()) { - collect_intersection_offsets(neg, tgt, false, to_remove); - } - else { - collect_intersection_offsets(tgt, neg, true, to_remove); - } - - if (to_remove.empty()) { - return; - } - - //the largest offsets are at the end, so we can remove them one by one - while(!to_remove.empty()) { - store_offset removed_ofs = to_remove.back(); - to_remove.pop_back(); - tgt.m_data.remove_offset(removed_ofs); - } - tgt.reset_indexes(); - } - - }; - - table_intersection_filter_fn * sparse_table_plugin::mk_filter_by_negation_fn(const table_base & t, - const table_base & negated_obj, unsigned joined_col_cnt, - const unsigned * t_cols, const unsigned * negated_cols) { - if (!check_kind(t) || !check_kind(negated_obj) - || join_involves_functional(t.get_signature(), negated_obj.get_signature(), joined_col_cnt, - t_cols, negated_cols) ) { - return 0; - } - return alloc(negation_filter_fn, t, negated_obj, joined_col_cnt, t_cols, negated_cols); - } - - unsigned sparse_table::get_size_estimate_bytes() const { - unsigned sz = 0; - sz += m_data.get_size_estimate_bytes(); - sz += m_key_indexes.capacity()*8; // TBD - return sz; - } - - -}; - diff --git a/src/muz/dl_sparse_table.h b/src/muz/dl_sparse_table.h deleted file mode 100644 index 010277b6b..000000000 --- a/src/muz/dl_sparse_table.h +++ /dev/null @@ -1,480 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - dl_table.h - -Abstract: - - - -Author: - - Krystof Hoder (t-khoder) 2010-09-01. - -Revision History: - ---*/ - -#ifndef _DL_SPARSE_TABLE_H_ -#define _DL_SPARSE_TABLE_H_ - -#include -#include -#include - -#include "ast.h" -#include "bit_vector.h" -#include "buffer.h" -#include "hashtable.h" -#include "map.h" -#include "ref_vector.h" -#include "vector.h" - -#include "dl_base.h" - - -namespace datalog { - class sparse_table; - - class sparse_table_plugin : public table_plugin { - friend class sparse_table; - protected: - class join_project_fn; - class union_fn; - class transformer_fn; - class rename_fn; - class project_fn; - class negation_filter_fn; - class select_equal_and_project_fn; - - typedef ptr_vector sp_table_vector; - typedef map table_pool; - - table_pool m_pool; - - void recycle(sparse_table * t); - - void garbage_collect(); - - void reset(); - - static bool join_involves_functional(const table_signature & s1, const table_signature & s2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2); - - public: - typedef sparse_table table; - - sparse_table_plugin(relation_manager & manager); - ~sparse_table_plugin(); - - virtual bool can_handle_signature(const table_signature & s) - { return s.size()>0; } - - virtual table_base * mk_empty(const table_signature & s); - sparse_table * mk_clone(const sparse_table & t); - - protected: - virtual table_join_fn * mk_join_fn(const table_base & t1, const table_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2); - virtual table_join_fn * mk_join_project_fn(const table_base & t1, const table_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2, unsigned removed_col_cnt, - const unsigned * removed_cols); - virtual table_union_fn * mk_union_fn(const table_base & tgt, const table_base & src, - const table_base * delta); - virtual table_transformer_fn * mk_project_fn(const table_base & t, unsigned col_cnt, - const unsigned * removed_cols); - virtual table_transformer_fn * mk_rename_fn(const table_base & t, unsigned permutation_cycle_len, - const unsigned * permutation_cycle); - virtual table_transformer_fn * mk_select_equal_and_project_fn(const table_base & t, - const table_element & value, unsigned col); - virtual table_intersection_filter_fn * mk_filter_by_negation_fn(const table_base & t, - const table_base & negated_obj, unsigned joined_col_cnt, - const unsigned * t_cols, const unsigned * negated_cols); - }; - - class entry_storage { - public: - typedef unsigned store_offset; - private: - typedef svector storage; - - class offset_hash_proc { - storage & m_storage; - unsigned m_unique_entry_size; - public: - offset_hash_proc(storage & s, unsigned unique_entry_sz) - : m_storage(s), m_unique_entry_size(unique_entry_sz) {} - unsigned operator()(store_offset ofs) const { - return string_hash(m_storage.c_ptr()+ofs, m_unique_entry_size, 0); - } - }; - - class offset_eq_proc { - storage & m_storage; - unsigned m_unique_entry_size; - public: - offset_eq_proc(storage & s, unsigned unique_entry_sz) - : m_storage(s), m_unique_entry_size(unique_entry_sz) {} - bool operator()(store_offset o1, store_offset o2) const { - const char * base = m_storage.c_ptr(); - return memcmp(base+o1, base+o2, m_unique_entry_size)==0; - } - }; - - typedef hashtable storage_indexer; - - static const store_offset NO_RESERVE = UINT_MAX; - - unsigned m_entry_size; - unsigned m_unique_part_size; - unsigned m_data_size; - /** - Invariant: Every or all but one blocks of length \c m_entry_size in the \c m_data vector - are unique sequences of bytes and have their offset stored in the \c m_data_indexer hashtable. - If the offset of the last block is not stored in the hashtable, it is stored in the \c m_reserve - variable. Otherwise \c m_reserve==NO_RESERVE. - - The size of m_data is actually 8 bytes larger than stated in m_data_size, so that we may - deref an uint64 pointer at the end of the array. - */ - storage m_data; - storage_indexer m_data_indexer; - store_offset m_reserve; - public: - entry_storage(unsigned entry_size, unsigned functional_size = 0, unsigned init_size = 0) - : m_entry_size(entry_size), - m_unique_part_size(entry_size-functional_size), - m_data_indexer(next_power_of_two(std::max(8u,init_size)), - offset_hash_proc(m_data, m_unique_part_size), offset_eq_proc(m_data, m_unique_part_size)), - m_reserve(NO_RESERVE) { - SASSERT(entry_size>0); - SASSERT(functional_size<=entry_size); - resize_data(init_size); - resize_data(0); - } - entry_storage(const entry_storage &s) - : m_entry_size(s.m_entry_size), - m_unique_part_size(s.m_unique_part_size), - m_data_size(s.m_data_size), - m_data(s.m_data), - m_data_indexer(next_power_of_two(std::max(8u,s.entry_count())), - offset_hash_proc(m_data, m_unique_part_size), offset_eq_proc(m_data, m_unique_part_size)), - m_reserve(s.m_reserve) { - store_offset after_last=after_last_offset(); - for(store_offset i=0; i(this)->get(ofs); } - - unsigned entry_count() const { return m_data_indexer.size(); } - - store_offset after_last_offset() const { - return (m_reserve==NO_RESERVE) ? m_data_size : m_reserve; - } - - char * begin() { return get(0); } - const char * begin() const { return get(0); } - const char * after_last() const { return get(after_last_offset()); } - - - bool has_reserve() const { return m_reserve!=NO_RESERVE; } - store_offset reserve() const { SASSERT(has_reserve()); return m_reserve; } - - void ensure_reserve() { - if(has_reserve()) { - SASSERT(m_reserve==m_data_size-m_entry_size); - return; - } - m_reserve=m_data_size; - resize_data(m_data_size+m_entry_size); - } - - /** - \brief Return pointer to the reserve. - - The reserve must exist when the function is called. - */ - char * get_reserve_ptr() { - SASSERT(has_reserve()); - return &m_data.get(reserve()); - } - - bool reserve_content_already_present() const { - SASSERT(has_reserve()); - return m_data_indexer.contains(reserve()); - } - - bool find_reserve_content(store_offset & result) const { - SASSERT(has_reserve()); - storage_indexer::entry * indexer_entry = m_data_indexer.find_core(reserve()); - if(!indexer_entry) { - return false; - } - result = indexer_entry->get_data(); - return true; - } - - /** - \brief Write fact \c f into the reserve at the end of the \c m_data storage. - - If the reserve does not exist, this function creates it. - */ - void write_into_reserve(const char * data) { - ensure_reserve(); - memcpy(get_reserve_ptr(), data, m_entry_size); - } - - /** - \brief If the fact in reserve is not in the table, insert it there and return true; - otherwise return false. - - When a fact is inserted into the table, the reserve becomes part of the table and - is no longer a reserve. - */ - bool insert_reserve_content(); - store_offset insert_or_get_reserve_content(); - bool remove_reserve_content(); - /** - Remove data at the offset \c ofs. - - Data with offset lower than \c ofs are not be modified by this function, data with - higher offset may be moved. - */ - void remove_offset(store_offset ofs); - - - //the following two operations allow breaking of the object invariant! - void resize_data(unsigned sz) { - m_data_size = sz; - m_data.resize(sz + sizeof(uint64)); - } - - bool insert_offset(store_offset ofs) { - return m_data_indexer.insert_if_not_there(ofs)==ofs; - } - }; - - class sparse_table : public table_base { - friend class sparse_table_plugin; - friend class sparse_table_plugin::join_project_fn; - friend class sparse_table_plugin::union_fn; - friend class sparse_table_plugin::transformer_fn; - friend class sparse_table_plugin::rename_fn; - friend class sparse_table_plugin::project_fn; - friend class sparse_table_plugin::negation_filter_fn; - friend class sparse_table_plugin::select_equal_and_project_fn; - - class our_iterator_core; - class key_indexer; - class general_key_indexer; - class full_signature_key_indexer; - typedef entry_storage::store_offset store_offset; - - - class column_info { - unsigned m_big_offset; - unsigned m_small_offset; - uint64 m_mask; - uint64 m_write_mask; - public: - unsigned m_offset; //!< in bits - unsigned m_length; //!< in bits - - column_info(unsigned offset, unsigned length) \ - : m_big_offset(offset/8), - m_small_offset(offset%8), - m_mask( length==64 ? ULLONG_MAX : (static_cast(1)<(rec+m_big_offset); - uint64 res = *ptr; - res>>=m_small_offset; - res&=m_mask; - return res; - } - void set(char * rec, table_element val) const { - SASSERT( (val&~m_mask)==0 ); //the value fits into the column - uint64 * ptr = reinterpret_cast(rec+m_big_offset); - *ptr&=m_write_mask; - *ptr|=val< { - - void make_byte_aligned_end(unsigned col_index); - public: - - unsigned m_entry_size; - /** - Number of last bytes which correspond to functional columns in the signature. - */ - unsigned m_functional_part_size; - unsigned m_functional_col_cnt; - - column_layout(const table_signature & sig); - - table_element get(const char * rec, unsigned col) const { - return (*this)[col].get(rec); - } - void set(char * rec, unsigned col, table_element val) const { - return (*this)[col].set(rec, val); - } - }; - - - typedef svector key_spec; //sequence of columns in a key - typedef svector key_value; //values of key columns - typedef map, - vector_eq_proc > key_index_map; - - static const store_offset NO_RESERVE = UINT_MAX; - - column_layout m_column_layout; - unsigned m_fact_size; - entry_storage m_data; - mutable key_index_map m_key_indexes; - - - const char * get_at_offset(store_offset i) const { - return m_data.get(i); - } - - table_element get_cell(store_offset ofs, unsigned column) const { - return m_column_layout.get(m_data.get(ofs), column); - } - - void set_cell(store_offset ofs, unsigned column, table_element val) { - m_column_layout.set(m_data.get(ofs), column, val); - } - - void write_into_reserve(const table_element* f); - - /** - \brief Return reference to an indexer over columns in \c key_cols. - - An indexer can retrieve a sequence of offsets that with \c key_cols columns equal to - the specified key. Indexers are populated lazily -- they remember the position of the - last fact they contain, and when an indexer is retrieved by the \c get_key_indexer function, - all the new facts are added into the indexer. - - When a fact is removed from the table, all indexers are destroyed. This is not an extra - expense in the current use scenario, because we first perform all fact removals and do the - joins only after that (joins are the only operations that lead to index construction). - */ - key_indexer& get_key_indexer(unsigned key_len, const unsigned * key_cols) const; - - void reset_indexes(); - - static void copy_columns(const column_layout & src_layout, const column_layout & dest_layout, - unsigned start_index, unsigned after_last, const char * src, char * dest, - unsigned & dest_idx, unsigned & pre_projection_idx, const unsigned * & next_removed); - - /** - \c array \c removed_cols contains column indexes to be removed in ascending order and - is terminated by a number greated than the highest column index of a join the the two tables. - This is to simplify the traversal of the array when building facts. - */ - static void concatenate_rows(const column_layout & layout1, const column_layout & layout2, - const column_layout & layout_res, const char * ptr1, const char * ptr2, char * res, - const unsigned * removed_cols); - - /** - \brief Perform join-project between t1 and t2 iterating through t1 and retrieving relevant - columns from t2 using indexing. - - \c array \c removed_cols contains column indexes to be removed in ascending order and - is terminated by a number greated than the highest column index of a join the the two tables. - This is to simplify the traversal of the array when building facts. - - \c tables_swapped value means that the resulting facts should contain facts from t2 first, - instead of the default behavior that would concatenate the two facts as \c (t1,t2). - - \remark The function is called \c self_agnostic_join since, unlike the virtual method - \c join, it is static and therefore allows to easily swap the roles of the two joined - tables (the indexed and iterated one) in a way that is expected to give better performance. - */ - static void self_agnostic_join_project(const sparse_table & t1, const sparse_table & t2, - unsigned joined_col_cnt, const unsigned * t1_joined_cols, const unsigned * t2_joined_cols, - const unsigned * removed_cols, bool tables_swapped, sparse_table & result); - - - /** - If the fact at \c data (in table's native representation) is not in the table, - add it and return true. Otherwise return false. - */ - bool add_fact(const char * data); - - bool add_reserve_content(); - - void garbage_collect(); - - sparse_table(sparse_table_plugin & p, const table_signature & sig, unsigned init_capacity=0); - sparse_table(const sparse_table & t); - virtual ~sparse_table(); - public: - - virtual void deallocate() { - get_plugin().recycle(this); - } - - unsigned row_count() const { return m_data.entry_count(); } - - sparse_table_plugin & get_plugin() const - { return static_cast(table_base::get_plugin()); } - - virtual bool empty() const { return row_count()==0; } - virtual void add_fact(const table_fact & f); - virtual bool contains_fact(const table_fact & f) const; - virtual bool fetch_fact(table_fact & f) const; - virtual void ensure_fact(const table_fact & f); - virtual void remove_fact(const table_element* fact); - virtual void reset(); - - virtual table_base * clone() const; - - virtual table_base::iterator begin() const; - virtual table_base::iterator end() const; - - virtual unsigned get_size_estimate_rows() const { return row_count(); } - virtual unsigned get_size_estimate_bytes() const; - virtual bool knows_exact_size() const { return true; } - }; - - }; - - #endif /* _DL_SPARSE_TABLE_H_ */ diff --git a/src/muz/dl_table.cpp b/src/muz/dl_table.cpp deleted file mode 100644 index 99a868bea..000000000 --- a/src/muz/dl_table.cpp +++ /dev/null @@ -1,772 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - dl_table.cpp - -Abstract: - - - -Author: - - Krystof Hoder (t-khoder) 2010-09-01. - -Revision History: - ---*/ - -#include"dl_context.h" -#include"dl_util.h" -#include"dl_table.h" - -namespace datalog { - - // ----------------------------------- - // - // hashtable_table - // - // ----------------------------------- - - table_base * hashtable_table_plugin::mk_empty(const table_signature & s) { - SASSERT(can_handle_signature(s)); - return alloc(hashtable_table, *this, s); - } - - - class hashtable_table_plugin::join_fn : public convenient_table_join_fn { - unsigned m_joined_col_cnt; - public: - join_fn(const table_signature & t1_sig, const table_signature & t2_sig, unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) - : convenient_table_join_fn(t1_sig, t2_sig, col_cnt, cols1, cols2), - m_joined_col_cnt(col_cnt) {} - - virtual table_base * operator()(const table_base & t1, const table_base & t2) { - - const hashtable_table & ht1 = static_cast(t1); - const hashtable_table & ht2 = static_cast(t2); - - hashtable_table_plugin & plugin = ht1.get_plugin(); - - hashtable_table * res = static_cast(plugin.mk_empty(get_result_signature())); - - hashtable_table::storage::iterator els1it = ht1.m_data.begin(); - hashtable_table::storage::iterator els1end = ht1.m_data.end(); - hashtable_table::storage::iterator els2end = ht2.m_data.end(); - - table_fact acc; - - for(; els1it!=els1end; ++els1it) { - const table_fact & row1 = *els1it; - - hashtable_table::storage::iterator els2it = ht2.m_data.begin(); - for(; els2it!=els2end; ++els2it) { - const table_fact & row2 = *els2it; - - bool match=true; - for(unsigned i=0; im_data.insert(acc); - } - } - return res; - } - }; - - table_join_fn * hashtable_table_plugin::mk_join_fn(const table_base & t1, const table_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) { - if(t1.get_kind()!=get_kind() || t2.get_kind()!=get_kind()) { - return 0; - } - return alloc(join_fn, t1.get_signature(), t2.get_signature(), col_cnt, cols1, cols2); - } - - - class hashtable_table::our_iterator_core : public iterator_core { - const hashtable_table & m_parent; - storage::iterator m_inner; - storage::iterator m_end; - - class our_row : public row_interface { - const our_iterator_core & m_parent; - public: - our_row(const our_iterator_core & parent) : row_interface(parent.m_parent), m_parent(parent) {} - - virtual void get_fact(table_fact & result) const { - result = *m_parent.m_inner; - } - virtual table_element operator[](unsigned col) const { - return (*m_parent.m_inner)[col]; - } - - }; - - our_row m_row_obj; - - public: - our_iterator_core(const hashtable_table & t, bool finished) : - m_parent(t), m_inner(finished ? t.m_data.end() : t.m_data.begin()), - m_end(t.m_data.end()), m_row_obj(*this) {} - - virtual bool is_finished() const { - return m_inner==m_end; - } - - virtual row_interface & operator*() { - SASSERT(!is_finished()); - return m_row_obj; - } - virtual void operator++() { - SASSERT(!is_finished()); - ++m_inner; - } - }; - - - - table_base::iterator hashtable_table::begin() const { - return mk_iterator(alloc(our_iterator_core, *this, false)); - } - - table_base::iterator hashtable_table::end() const { - return mk_iterator(alloc(our_iterator_core, *this, true)); - } - - // ----------------------------------- - // - // bitvector_table - // - // ----------------------------------- - - bool bitvector_table_plugin::can_handle_signature(const table_signature & sig) { - if(sig.functional_columns()!=0) { - return false; - } - unsigned cols = sig.size(); - unsigned shift = 0; - for (unsigned i = 0; i < cols; ++i) { - unsigned s = static_cast(sig[i]); - if (s != sig[i] || !is_power_of_two(s)) { - return false; - } - unsigned num_bits = 0; - unsigned bit_pos = 1; - for (num_bits = 1; num_bits < 32; ++num_bits) { - if (bit_pos & s) { - break; - } - bit_pos <<= 1; - } - shift += num_bits; - if (shift >= 32) { - return false; - } - } - return true; - } - - table_base * bitvector_table_plugin::mk_empty(const table_signature & s) { - SASSERT(can_handle_signature(s)); - return alloc(bitvector_table, *this, s); - } - - class bitvector_table::bv_iterator : public iterator_core { - - bitvector_table const& m_bv; - unsigned m_offset; - - class our_row : public caching_row_interface { - const bv_iterator& m_parent; - public: - our_row(const bv_iterator & p) : caching_row_interface(p.m_bv), m_parent(p) {} - virtual void get_fact(table_fact& result) const { - if (result.size() < size()) { - result.resize(size(), 0); - } - m_parent.m_bv.offset2fact(m_parent.m_offset, result); - } - }; - our_row m_row_obj; - - public: - bv_iterator(const bitvector_table& bv, bool end): - m_bv(bv), m_offset(end?m_bv.m_bv.size():0), m_row_obj(*this) - { - if (!is_finished() && !m_bv.m_bv.get(m_offset)) { - ++(*this); - } - } - - virtual bool is_finished() const { - return m_offset == m_bv.m_bv.size(); - } - - virtual row_interface & operator*() { - SASSERT(!is_finished()); - return m_row_obj; - } - virtual void operator++() { - SASSERT(!is_finished()); - ++m_offset; - while (!is_finished() && !m_bv.m_bv.get(m_offset)) { - ++m_offset; - } - m_row_obj.reset(); - } - }; - - bitvector_table::bitvector_table(bitvector_table_plugin & plugin, const table_signature & sig) - : table_base(plugin, sig) { - SASSERT(plugin.can_handle_signature(sig)); - - m_num_cols = sig.size(); - unsigned shift = 0; - for (unsigned i = 0; i < m_num_cols; ++i) { - unsigned s = static_cast(sig[i]); - if (s != sig[i] || !is_power_of_two(s)) { - throw default_exception("bit-vector table is specialized to small domains that are powers of two"); - } - m_shift.push_back(shift); - m_mask.push_back(s - 1); - unsigned num_bits = 0; - unsigned bit_pos = 1; - for (num_bits = 1; num_bits < 32; ++num_bits) { - if (bit_pos & s) { - break; - } - bit_pos <<= 1; - } - shift += num_bits; - if (shift >= 32) { - throw default_exception("bit-vector table is specialized to small domains that are powers of two"); - } - m_bv.reserve(1 << shift); - } - } - - unsigned bitvector_table::fact2offset(const table_element* f) const { - unsigned result = 0; - for (unsigned i = 0; i < m_num_cols; ++i) { - SASSERT(f[i]> m_shift[i]); - } - } - - void bitvector_table::add_fact(const table_fact & f) { - m_bv.set(fact2offset(f.c_ptr())); - } - - void bitvector_table::remove_fact(const table_element* fact) { - m_bv.unset(fact2offset(fact)); - } - - bool bitvector_table::contains_fact(const table_fact & f) const { - return m_bv.get(fact2offset(f.c_ptr())); - } - - table_base::iterator bitvector_table::begin() const { - return mk_iterator(alloc(bv_iterator, *this, false)); - } - - table_base::iterator bitvector_table::end() const { - return mk_iterator(alloc(bv_iterator, *this, true)); - } - - - - - // ----------------------------------- - // - // equivalence_table - // - // ----------------------------------- - - bool equivalence_table_plugin::can_handle_signature(const table_signature & sig) { - return sig.functional_columns() == 0 && sig.size() == 2 && sig[0] < UINT_MAX && sig[0] == sig[1]; - } - - bool equivalence_table_plugin::is_equivalence_table(table_base const& tbl) const { - if (tbl.get_kind() != get_kind()) return false; - equivalence_table const& t = static_cast(tbl); - return !t.is_sparse(); - } - - table_base * equivalence_table_plugin::mk_empty(const table_signature & s) { - TRACE("dl", for (unsigned i = 0; i < s.size(); ++i) tout << s[i] << " "; tout << "\n";); - SASSERT(can_handle_signature(s)); - return alloc(equivalence_table, *this, s); - } - - class equivalence_table_plugin::select_equal_and_project_fn : public table_transformer_fn { - unsigned m_val; - table_sort m_sort; - public: - select_equal_and_project_fn(const table_signature & sig, table_element val, unsigned col) - : m_val(static_cast(val)), - m_sort(sig[0]) { - SASSERT(val <= UINT_MAX); - SASSERT(col == 0 || col == 1); - SASSERT(sig.functional_columns() == 0); - SASSERT(sig.size() == 2); - SASSERT(sig[0] < UINT_MAX && sig[0] == sig[1]); - } - - virtual table_base* operator()(const table_base& tb) { - TRACE("dl", tout << "\n";); - table_plugin & plugin = tb.get_plugin(); - table_plugin* rp = plugin.get_manager().get_table_plugin(symbol("sparse")); - SASSERT(rp); - table_signature sig; - sig.push_back(m_sort); - table_base* result = rp->mk_empty(sig); - equivalence_table const& eq_table = static_cast(tb); - if (eq_table.is_valid(m_val)) { - table_fact fact; - fact.resize(1); - unsigned r = m_val; - do { - fact[0] = r; - result->add_fact(fact); - r = eq_table.m_uf.next(r); - } - while (r != m_val); - } - TRACE("dl", tb.display(tout << "src:\n"); result->display(tout << "result\n");); - return result; - } - }; - - table_transformer_fn * equivalence_table_plugin::mk_select_equal_and_project_fn( - const table_base & t, const table_element & value, unsigned col) { - return alloc(select_equal_and_project_fn, t.get_signature(), value, col); - } - - class equivalence_table_plugin::union_fn : public table_union_fn { - - equivalence_table_plugin& m_plugin; - - - void mk_union1(equivalence_table & tgt, const equivalence_table & src, table_base * delta) { - unsigned num_vars = src.m_uf.get_num_vars(); - table_fact fact; - fact.resize(2); - for (unsigned i = 0; i < num_vars; ++i) { - if (src.is_valid(i) && src.m_uf.find(i) == i) { - fact[0] = i; - equivalence_table::class_iterator it = src.class_begin(i); - equivalence_table::class_iterator end = src.class_end(i); - for (; it != end; ++it) { - fact[1] = *it; - if (!tgt.contains_fact(fact)) { - tgt.add_fact(fact); - if (delta) { - delta->add_fact(fact); - } - } - } - } - } - } - - void mk_union2(equivalence_table & tgt, const table_base & src, table_base * delta) { - table_fact fact; - table_base::iterator it = src.begin(), end = src.end(); - for (; it != end; ++it) { - it->get_fact(fact); - if (!tgt.contains_fact(fact)) { - tgt.add_fact(fact); - if (delta) { - delta->add_fact(fact); - TRACE("dl", - tout << "Add: "; - for (unsigned i = 0; i < fact.size(); ++i) tout << fact[i] << " "; - tout << "\n";); - } - } - } - } - - public: - union_fn(equivalence_table_plugin& p) : m_plugin(p) {} - - virtual void operator()(table_base & tgt0, const table_base & src, table_base * delta) { - TRACE("dl", tout << "union\n";); - equivalence_table & tgt = static_cast(tgt0); - if (m_plugin.is_equivalence_table(src)) { - mk_union1(tgt, static_cast(src), delta); - } - else { - mk_union2(tgt, src, delta); - } - TRACE("dl", src.display(tout << "src\n"); tgt.display(tout << "tgt\n"); - if (delta) delta->display(tout << "delta\n");); - } - }; - - table_union_fn * equivalence_table_plugin::mk_union_fn( - const table_base & tgt, const table_base & src, const table_base * delta) { - if (!is_equivalence_table(tgt) || - tgt.get_signature() != src.get_signature() || - (delta && delta->get_signature() != tgt.get_signature())) { - return 0; - } - return alloc(union_fn,*this); - } - - class equivalence_table_plugin::join_project_fn : public convenient_table_join_project_fn { - equivalence_table_plugin& m_plugin; - public: - join_project_fn( - equivalence_table_plugin& plugin, const table_signature & t1_sig, const table_signature & t2_sig, unsigned col_cnt, - const unsigned * cols1, const unsigned * cols2, unsigned removed_col_cnt, - const unsigned * removed_cols) - : convenient_table_join_project_fn(t1_sig, t2_sig, col_cnt, cols1, cols2, removed_col_cnt, removed_cols), - m_plugin(plugin) { - m_removed_cols.push_back(UINT_MAX); - } - - virtual table_base * operator()(const table_base & tb1, const table_base & tb2) { - SASSERT(m_cols1.size() == 1); - const table_signature & res_sign = get_result_signature(); - table_plugin * plugin = &tb1.get_plugin(); - if (!plugin->can_handle_signature(res_sign)) { - plugin = &tb2.get_plugin(); - if (!plugin->can_handle_signature(res_sign)) { - plugin = &tb1.get_manager().get_appropriate_plugin(res_sign); - } - } - SASSERT(plugin->can_handle_signature(res_sign)); - table_base * result = plugin->mk_empty(res_sign); - - if (m_plugin.is_equivalence_table(tb1)) { - mk_join(0, m_cols1[0], static_cast(tb1), - 2, m_cols2[0], tb2, result); - } - else if (m_plugin.is_equivalence_table(tb2)) { - mk_join(tb1.get_signature().size(), m_cols2[0], static_cast(tb2), - 0, m_cols1[0], tb1, result); - } - else { - UNREACHABLE(); - } - TRACE("dl", tb1.display(tout << "tb1\n"); tb2.display(tout << "tb2\n"); result->display(tout << "result\n");); - return result; - } - - private: - table_base * mk_join(unsigned offs1, unsigned col1, equivalence_table const & t1, - unsigned offs2, unsigned col2, table_base const& t2, table_base* res) { - table_base::iterator els2it = t2.begin(); - table_base::iterator els2end = t2.end(); - - table_fact acc, proj; - acc.resize(t1.get_signature().size() + t2.get_signature().size()); - - for(; els2it != els2end; ++els2it) { - const table_base::row_interface & row2 = *els2it; - table_element const& e2 = row2[col2]; - equivalence_table::class_iterator it = t1.class_begin(e2); - equivalence_table::class_iterator end = t1.class_end(e2); - if (it != end) { - for (unsigned i = 0; i < row2.size(); ++i) { - acc[i+offs2] = row2[i]; - } - } - for (; it != end; ++it) { - acc[offs1+col1] = e2; - acc[offs1+1-col1] = *it; - mk_project(acc, proj); - TRACE("dl", for (unsigned i = 0; i < proj.size(); ++i) tout << proj[i] << " "; tout << "\n";); - res->add_fact(proj); - } - } - return res; - } - - virtual void mk_project(table_fact const & f, table_fact & p) const { - unsigned sz = f.size(); - p.reset(); - for (unsigned i = 0, r = 0; i < sz; ++i) { - if (r < m_removed_cols.size() && m_removed_cols[r] == i) { - ++r; - } - else { - p.push_back(f[i]); - } - } - } - - - }; - - table_join_fn * equivalence_table_plugin::mk_join_project_fn( - const table_base & t1, const table_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2, unsigned removed_col_cnt, - const unsigned * removed_cols) { - if (col_cnt != 1) { - TRACE("dl", tout << "WARNING: join_project on multiple columns is not implemented\n";); - return 0; - } - if (is_equivalence_table(t1) || is_equivalence_table(t2)) { - return alloc(join_project_fn, *this, t1.get_signature(), t2.get_signature(), col_cnt, cols1, cols2, - removed_col_cnt, removed_cols); - } - return 0; - } - - class equivalence_table::eq_iterator : public iterator_core { - - equivalence_table const& m_eq; - unsigned m_last; - unsigned m_current; - unsigned m_next; - - class our_row : public caching_row_interface { - const eq_iterator& m_parent; - public: - our_row(const eq_iterator & p) : caching_row_interface(p.m_eq), m_parent(p) {} - - virtual void get_fact(table_fact& result) const { - if (result.size() < size()) { - result.resize(size(), 0); - } - result[0] = m_parent.m_current; - result[1] = m_parent.m_next; - } - - virtual table_element operator[](unsigned col) const { - if (col == 0) return m_parent.m_current; - if (col == 1) return m_parent.m_next; - UNREACHABLE(); - return 0; - } - - }; - our_row m_row_obj; - - public: - eq_iterator(const equivalence_table& eq, bool end): - m_eq(eq), - m_last(eq.m_uf.get_num_vars()), - m_current(end?m_last:0), - m_next(0), - m_row_obj(*this) - { - while (m_current < m_last && !m_eq.is_valid(m_current)) { - m_current++; - m_next = m_current; - } - } - - virtual bool is_finished() const { - return m_current == m_last; - } - - virtual row_interface & operator*() { - SASSERT(!is_finished()); - return m_row_obj; - } - - virtual void operator++() { - SASSERT(!is_finished()); - m_next = m_eq.m_uf.next(m_next); - if (m_next == m_current) { - do { - m_current++; - m_next = m_current; - } - while (m_current < m_last && !m_eq.is_valid(m_current)); - } - } - }; - - equivalence_table::equivalence_table(equivalence_table_plugin & plugin, const table_signature & sig) - : table_base(plugin, sig), m_uf(m_ctx), m_sparse(0) { - SASSERT(plugin.can_handle_signature(sig)); - } - - equivalence_table::~equivalence_table() { - if (is_sparse()) { - m_sparse->deallocate(); - } - } - - - void equivalence_table::add_fact(const table_fact & f) { - if (is_sparse()) { - add_fact_sparse(f); - } - else { - TRACE("dl_verbose", for (unsigned i = 0; i < f.size(); ++i) tout << f[i] << " "; tout << "\n";); - while (first(f) >= m_uf.get_num_vars()) m_uf.mk_var(); - while (second(f) >= m_uf.get_num_vars()) m_uf.mk_var(); - m_uf.merge(first(f), second(f)); - m_valid.reserve(m_uf.get_num_vars()); - m_valid.set(first(f)); - m_valid.set(second(f)); - } - } - - void equivalence_table::remove_fact(const table_element* fact) { - mk_sparse(); - m_sparse->remove_fact(fact); - } - - void equivalence_table::mk_sparse() { - if (m_sparse) return; - - TRACE("dl",tout << "\n";); - table_plugin & plugin = get_plugin(); - table_plugin* rp = plugin.get_manager().get_table_plugin(symbol("sparse")); - SASSERT(rp); - table_base* result = rp->mk_empty(get_signature()); - table_base::iterator it = begin(), e = end(); - table_fact fact; - for (; it != e; ++it) { - it->get_fact(fact); - result->add_fact(fact); - } - m_sparse = result; - } - - void equivalence_table::add_fact_sparse(table_fact const& f) { - table_base::iterator it = m_sparse->begin(), end = m_sparse->end(); - vector to_add; - to_add.push_back(f); - table_fact f1(f); - - f1[0] = f[1]; - f1[1] = f[0]; - to_add.push_back(f1); - - f1[0] = f[1]; - f1[1] = f[1]; - to_add.push_back(f1); - - f1[0] = f[0]; - f1[1] = f[0]; - to_add.push_back(f1); - - for (; it != end; ++it) { - if ((*it)[0] == f[0]) { - f1[0] = f[1]; - f1[1] = (*it)[1]; - to_add.push_back(f1); - std::swap(f1[0],f1[1]); - to_add.push_back(f1); - } - } - for (unsigned i = 0; i < to_add.size(); ++i) { - m_sparse->add_fact(to_add[i]); - } - } - - bool equivalence_table::contains_fact(const table_fact & f) const { - TRACE("dl_verbose", for (unsigned i = 0; i < f.size(); ++i) tout << f[i] << " "; tout << "\n";); - if (is_sparse()) { - return m_sparse->contains_fact(f); - } - return - is_valid(first(f)) && - is_valid(second(f)) && - m_uf.find(first(f)) == m_uf.find(second(f)); - } - - table_base* equivalence_table::clone() const { - if (is_sparse()) { - return m_sparse->clone(); - } - TRACE("dl",tout << "\n";); - table_plugin & plugin = get_plugin(); - table_base* result = plugin.mk_empty(get_signature()); - table_fact fact; - fact.resize(2); - for (unsigned i = 0; i < m_uf.get_num_vars(); ++i) { - if (m_valid.get(i) && m_uf.find(i) == i) { - unsigned n = m_uf.next(i); - fact[0] = i; - while (n != i) { - fact[1] = n; - result->add_fact(fact); - n = m_uf.next(n); - } - } - } - return result; - } - - table_base::iterator equivalence_table::begin() const { - if (is_sparse()) return m_sparse->begin(); - return mk_iterator(alloc(eq_iterator, *this, false)); - } - - table_base::iterator equivalence_table::end() const { - if (is_sparse()) return m_sparse->end(); - return mk_iterator(alloc(eq_iterator, *this, true)); - } - - equivalence_table::class_iterator equivalence_table::class_begin(table_element const& _e) const { - SASSERT(!is_sparse()); - unsigned e = static_cast(_e); - return class_iterator(*this, e, !is_valid(e)); - } - - equivalence_table::class_iterator equivalence_table::class_end(table_element const& _e) const { - SASSERT(!is_sparse()); - unsigned e = static_cast(_e); - return class_iterator(*this, e, true); - } - - void equivalence_table::display(std::ostream& out) const { - if (is_sparse()) { - m_sparse->display(out); - return; - } - for (unsigned i = 0; i < m_uf.get_num_vars(); ++i) { - if (is_valid(i) && m_uf.find(i) == i) { - unsigned j = i, last = i; - do { - out << "<" << i << " " << j << ">\n"; - j = m_uf.next(j); - } - while (last != j); - } - } - } - - unsigned equivalence_table::get_size_estimate_rows() const { - if (is_sparse()) return m_sparse->get_size_estimate_rows(); - return static_cast(get_signature()[0]); - } - - unsigned equivalence_table::get_size_estimate_bytes() const { - if (is_sparse()) return m_sparse->get_size_estimate_bytes(); - return static_cast(get_signature()[0]); - } - - bool equivalence_table::knows_exact_size() const { - return (!is_sparse() || m_sparse->knows_exact_size()); - } - -}; - diff --git a/src/muz/dl_table.h b/src/muz/dl_table.h deleted file mode 100644 index 3a240c337..000000000 --- a/src/muz/dl_table.h +++ /dev/null @@ -1,265 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - dl_table.h - -Abstract: - - - -Author: - - Krystof Hoder (t-khoder) 2010-09-01. - -Revision History: - ---*/ -#ifndef _DL_TABLE_H_ -#define _DL_TABLE_H_ - -#include -#include -#include - -#include "ast.h" -#include "bit_vector.h" -#include "buffer.h" -#include "hashtable.h" -#include "map.h" -#include "ref_vector.h" -#include "vector.h" -#include "union_find.h" -#include "dl_base.h" -#include "dl_util.h" -#include "bit_vector.h" - - -namespace datalog { - - class context; - class variable_intersection; - - - - // ----------------------------------- - // - // hashtable_table - // - // ----------------------------------- - - class hashtable_table; - - class hashtable_table_plugin : public table_plugin { - friend class hashtable_table; - protected: - class join_fn; - public: - typedef hashtable_table table; - - hashtable_table_plugin(relation_manager & manager) - : table_plugin(symbol("hashtable"), manager) {} - - virtual table_base * mk_empty(const table_signature & s); - - virtual table_join_fn * mk_join_fn(const table_base & t1, const table_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2); - }; - - class hashtable_table : public table_base { - friend class hashtable_table_plugin; - friend class hashtable_table_plugin::join_fn; - - class our_iterator_core; - - typedef hashtable, - vector_eq_proc > storage; - - storage m_data; - - hashtable_table(hashtable_table_plugin & plugin, const table_signature & sig) - : table_base(plugin, sig) {} - public: - hashtable_table_plugin & get_plugin() const - { return static_cast(table_base::get_plugin()); } - - virtual void add_fact(const table_fact & f) { - m_data.insert(f); - } - virtual void remove_fact(const table_element* fact) { - table_fact f(get_signature().size(), fact); - m_data.remove(f); - } - virtual bool contains_fact(const table_fact & f) const { - return m_data.contains(f); - } - - virtual iterator begin() const; - virtual iterator end() const; - - virtual unsigned get_size_estimate_rows() const { return m_data.size(); } - virtual unsigned get_size_estimate_bytes() const { return m_data.size()*get_signature().size()*8; } - virtual bool knows_exact_size() const { return true; } - }; - - // ----------------------------------- - // - // bitvector_table - // - // ----------------------------------- - - class bitvector_table; - - class bitvector_table_plugin : public table_plugin { - public: - typedef bitvector_table table; - - bitvector_table_plugin(relation_manager & manager) - : table_plugin(symbol("bitvector"), manager) {} - - virtual bool can_handle_signature(const table_signature & s); - - virtual table_base * mk_empty(const table_signature & s); - }; - - class bitvector_table : public table_base { - friend class bitvector_table_plugin; - - class bv_iterator; - bit_vector m_bv; - unsigned m_num_cols; - unsigned_vector m_shift; - unsigned_vector m_mask; - - unsigned fact2offset(const table_element* f) const; - void offset2fact(unsigned offset, table_fact& f) const; - - bitvector_table(bitvector_table_plugin & plugin, const table_signature & sig); - public: - virtual void add_fact(const table_fact & f); - virtual void remove_fact(const table_element* fact); - virtual bool contains_fact(const table_fact & f) const; - virtual iterator begin() const; - virtual iterator end() const; - }; - - // ------------------------------------------- - // Equivalence table. - // Really: partial equivalence relation table. - // ------------------------------------------- - - class equivalence_table; - - class equivalence_table_plugin : public table_plugin { - class union_fn; - class select_equal_and_project_fn; - class join_project_fn; - - bool is_equivalence_table(table_base const& tbl) const; - - public: - typedef equivalence_table table; - - equivalence_table_plugin(relation_manager & manager) - : table_plugin(symbol("equivalence"), manager) {} - - virtual bool can_handle_signature(const table_signature & s); - - virtual table_base * mk_empty(const table_signature & s); - - protected: - virtual table_union_fn * mk_union_fn(const table_base & tgt, const table_base & src, - const table_base * delta); - virtual table_transformer_fn * mk_select_equal_and_project_fn( - const table_base & t, - const table_element & value, unsigned col); - virtual table_join_fn * mk_join_project_fn(const table_base & t1, const table_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2, unsigned removed_col_cnt, - const unsigned * removed_cols); - - -#if 0 - virtual table_join_fn * mk_join_fn(const table_base & t1, const table_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2); - virtual table_transformer_fn * mk_project_fn(const table_base & t, unsigned col_cnt, - const unsigned * removed_cols); - virtual table_transformer_fn * mk_rename_fn(const table_base & t, unsigned permutation_cycle_len, - const unsigned * permutation_cycle); - const table_element & value, unsigned col); - virtual table_intersection_filter_fn * mk_filter_by_negation_fn(const table_base & t, - const table_base & negated_obj, unsigned joined_col_cnt, - const unsigned * t_cols, const unsigned * negated_cols); -#endif - }; - - class equivalence_table : public table_base { - friend class equivalence_table_plugin; - - class eq_iterator; - union_find_default_ctx m_ctx; - bit_vector m_valid; - union_find<> m_uf; - table_base* m_sparse; - - equivalence_table(equivalence_table_plugin & plugin, const table_signature & sig); - virtual ~equivalence_table(); - - unsigned first(table_fact const& f) const { return static_cast(f[0]); } - unsigned second(table_fact const& f) const { return static_cast(f[1]); } - - bool is_valid(unsigned entry) const { return entry < m_valid.size() && m_valid.get(entry); } - bool is_sparse() const { return m_sparse != 0; } - - // iterator over equivalence class of 'n'. - class class_iterator { - equivalence_table const& m_parent; - unsigned m_current; - unsigned m_last; - bool m_end; - public: - class_iterator(equivalence_table const& s, unsigned n, bool end): - m_parent(s), m_current(n), m_last(n), m_end(end) {} - - unsigned operator*() { return m_current; } - - class_iterator& operator++() { - m_current = m_parent.m_uf.next(m_current); - m_end = (m_current == m_last); - return *this; - } - - bool operator==(const class_iterator & it) const { - return - (m_end && it.m_end) || - (!m_end && !it.m_end && m_current == it.m_current); - } - bool operator!=(const class_iterator & it) const { return !operator==(it); } - - }; - class_iterator class_begin(table_element const& e) const; - class_iterator class_end(table_element const& e) const; - - void add_fact_sparse(table_fact const& f); - void mk_sparse(); - - - public: - virtual void add_fact(const table_fact & f); - virtual void remove_fact(const table_element* fact); - virtual bool contains_fact(const table_fact & f) const; - virtual table_base* clone() const; - virtual iterator begin() const; - virtual iterator end() const; - virtual unsigned get_size_estimate_rows() const; - virtual unsigned get_size_estimate_bytes() const; - virtual bool knows_exact_size() const; - virtual void display(std::ostream & out) const; - - }; - - -}; - -#endif /* _DL_TABLE_H_ */ - diff --git a/src/muz/dl_table_plugin.h b/src/muz/dl_table_plugin.h deleted file mode 100644 index 134389b61..000000000 --- a/src/muz/dl_table_plugin.h +++ /dev/null @@ -1,193 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - dl_table_plugin.h - -Abstract: - - - -Author: - - Krystof Hoder (t-khoder) 2010-09-23. - -Revision History: - ---*/ -#ifndef _DL_TABLE_PLUGIN_H_ -#define _DL_TABLE_PLUGIN_H_ - -#include"ast.h" -#include"map.h" -#include"vector.h" - -#include"dl_table_ops.h" - -namespace datalog { - - /** - Termplate class containing common infrastructure for relations and tables - */ - template - struct tr_infrastructure { - - typedef typename Traits::base_object base_object; - typedef typename Traits::signature signature; - typedef typename Traits::element element; - typedef typename Traits::fact fact; - typedef typename Traits::kind kind; - - class base_fn { - public: - virtual ~base_fn() {} - }; - - class join_fn : public base_fn { - public: - virtual base_object * operator()(const base_object & t1, const base_object & t2); - }; - - class transformer_fn : public base_fn { - public: - virtual base_object * operator()(const base_object & t); - }; - - class union_fn : public base_fn { - public: - virtual void operator()(base_object & tgt, const base_object & src, base_object * delta); - }; - - class mutator_fn : public base_fn { - public: - virtual void operator()(base_object & t); - }; - - class negation_filter_fn : public base_fn { - public: - virtual void operator()(base_object & t, const base_object & negated_obj); - }; - - class plugin_object { - const kind m_kind; - protected: - plugin_object(kind k) : m_kind(k) {} - public: - kind get_kind(); - - virtual base_object * mk_empty(const signature & s) = 0; - - virtual join_fn * mk_join_fn(const table_base & t1, const table_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) { - NOT_IMPLEMENTED_YET(); - } - - virtual transformer_fn * mk_project_fn(const base_object & t, unsigned col_cnt, - const unsigned * removed_cols) = 0 - - virtual transformer_fn * mk_rename_fn(const base_object & t, unsigned permutation_cycle_len, - const unsigned * permutation_cycle) = 0; - - virtual union_fn * mk_union_fn(base_object & tgt, const base_object & src, base_object * delta) = 0; - - virtual mutator_fn * mk_filter_identical_fn(base_object & t, unsigned col_cnt, - const unsigned * identical_cols) = 0; - - virtual mutator_fn * mk_filter_equal_fn(base_object & t, const element & value, - unsigned col) = 0; - - virtual mutator_fn * mk_filter_interpreted_fn(base_object & t, app * condition) = 0; - - virtual negation_filter_fn * mk_filter_interpreted_fn(base_object & t, - const base_object & negated_obj, unsigned joined_col_cnt, - const unsigned * t_cols, const unsigned * negated_cols) = 0; - - }; - - class base_ancestor { - const kind m_kind; - protected: - relation_manager & m_manager; - signature m_signature; - - base_ancestor(kind k, relation_manager & m, const signature & s) - : m_kind(k), m_manager(m), m_signature(s) {} - public: - virtual ~base_ancestor() {} - - kind get_kind() const { return m_kind; } - relation_manager & get_manager() const { return m_manager; } - const signature & get_signature() const { return m_signature; } - - virtual bool empty() const = 0; - virtual void add_fact(const fact & f) = 0; - virtual bool contains_fact(const fact & f) const = 0; - - /** - \brief Return table that contains the same data as the current one. - */ - virtual base_object * clone() const; - - }; - }; - - - // ----------------------------------- - // - // relation_base - // - // ----------------------------------- - - class relation_base1; - - enum relation_kind { - RK_UNKNOWN, - RK_TABLE - }; - - struct relation_traits { - typedef relation_base1 base_object; - typedef relation_signature signature; - typedef app * element; - typedef ptr_vector fact; - typedef relation_kind kind; - }; - - typedef tr_infrastructure relation_infrastructure; - - typedef relation_infrastructure::plugin_object relation_plugin_base; - - class relation_base1 : public relation_infrastructure::base_ancestor { - - }; - - - // ----------------------------------- - // - // table_base - // - // ----------------------------------- - - class table_base1; - - struct table_traits { - typedef table_base1 base_object; - typedef table_signature signature; - typedef unsigned element; - typedef unsigned_vector fact; - typedef table_kind kind; - }; - - typedef tr_infrastructure table_infrastructure; - - typedef table_infrastructure::plugin_object table_plugin_base; - - class table_base1 : public table_infrastructure::base_ancestor { - - }; - -}; - -#endif /* _DL_TABLE_PLUGIN_H_ */ - diff --git a/src/muz/dl_table_relation.cpp b/src/muz/dl_table_relation.cpp deleted file mode 100644 index 3c30c58bb..000000000 --- a/src/muz/dl_table_relation.cpp +++ /dev/null @@ -1,490 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - dl_table_relation.cpp - -Abstract: - - - -Author: - - Krystof Hoder (t-khoder) 2010-09-14. - -Revision History: - ---*/ - - -#include -#include"dl_context.h" -#include"dl_relation_manager.h" -#include"dl_table_relation.h" - - -namespace datalog { - - // ----------------------------------- - // - // table_relation_plugin - // - // ----------------------------------- - - symbol table_relation_plugin::create_plugin_name(const table_plugin &p) { - std::string name = std::string("tr_") + p.get_name().bare_str(); - return symbol(name.c_str()); - } - - bool table_relation_plugin::can_handle_signature(const relation_signature & s) { - table_signature tsig; - if(!get_manager().relation_signature_to_table(s, tsig)) { - return false; - } - return m_table_plugin.can_handle_signature(tsig); - } - - - relation_base * table_relation_plugin::mk_empty(const relation_signature & s) { - table_signature tsig; - if(!get_manager().relation_signature_to_table(s, tsig)) { - return 0; - } - table_base * t = m_table_plugin.mk_empty(tsig); - return alloc(table_relation, *this, s, t); - } - - relation_base * table_relation_plugin::mk_full(const relation_signature & s, func_decl* p, family_id kind) { - table_signature tsig; - if(!get_manager().relation_signature_to_table(s, tsig)) { - return 0; - } - table_base * t = m_table_plugin.mk_full(p, tsig, kind); - return alloc(table_relation, *this, s, t); - } - - relation_base * table_relation_plugin::mk_from_table(const relation_signature & s, table_base * t) { - if (&t->get_plugin() == &m_table_plugin) - return alloc(table_relation, *this, s, t); - table_relation_plugin& other = t->get_manager().get_table_relation_plugin(t->get_plugin()); - return alloc(table_relation, other, s, t); - } - - class table_relation_plugin::tr_join_project_fn : public convenient_relation_join_project_fn { - scoped_ptr m_tfun; - public: - tr_join_project_fn(const relation_signature & s1, const relation_signature & s2, unsigned col_cnt, - const unsigned * cols1, const unsigned * cols2, unsigned removed_col_cnt, - const unsigned * removed_cols, table_join_fn * tfun) - : convenient_relation_join_project_fn(s1, s2, col_cnt, cols1, cols2, removed_col_cnt, - removed_cols), m_tfun(tfun) {} - - virtual relation_base * operator()(const relation_base & t1, const relation_base & t2) { - SASSERT(t1.from_table()); - SASSERT(t2.from_table()); - table_relation_plugin & plugin = static_cast(t1.get_plugin()); - - const table_relation & tr1 = static_cast(t1); - const table_relation & tr2 = static_cast(t2); - - table_base * tres = (*m_tfun)(tr1.get_table(), tr2.get_table()); - - TRACE("dl_table_relation", tout << "# join => "; tres->display(tout);); - if(&tres->get_plugin()!=&plugin.m_table_plugin) { - //Operation returned a table of different type than the one which is associated with - //this plugin. We need to get a correct table_relation_plugin and create the relation - //using it. - return plugin.get_manager().get_table_relation_plugin(tres->get_plugin()) - .mk_from_table(get_result_signature(), tres); - } - return plugin.mk_from_table(get_result_signature(), tres); - } - }; - - relation_join_fn * table_relation_plugin::mk_join_fn(const relation_base & r1, const relation_base & r2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) { - if(!r1.from_table() || !r2.from_table()) { - return 0; - } - const table_relation & tr1 = static_cast(r1); - const table_relation & tr2 = static_cast(r2); - - table_join_fn * tfun = get_manager().mk_join_fn(tr1.get_table(), tr2.get_table(), col_cnt, cols1, cols2); - if(!tfun) { - return 0; - } - - return alloc(tr_join_project_fn, r1.get_signature(), r2.get_signature(), col_cnt, cols1, - cols2, 0, static_cast(0), tfun); - } - - relation_join_fn * table_relation_plugin::mk_join_project_fn(const relation_base & r1, - const relation_base & r2, unsigned joined_col_cnt, const unsigned * cols1, const unsigned * cols2, - unsigned removed_col_cnt, const unsigned * removed_cols) { - if(!r1.from_table() || !r2.from_table()) { - return 0; - } - const table_relation & tr1 = static_cast(r1); - const table_relation & tr2 = static_cast(r2); - - table_join_fn * tfun = get_manager().mk_join_project_fn(tr1.get_table(), tr2.get_table(), joined_col_cnt, - cols1, cols2, removed_col_cnt, removed_cols); - SASSERT(tfun); - - return alloc(tr_join_project_fn, r1.get_signature(), r2.get_signature(), joined_col_cnt, cols1, - cols2, removed_col_cnt, removed_cols, tfun); - } - - - class table_relation_plugin::tr_transformer_fn : public convenient_relation_transformer_fn { - scoped_ptr m_tfun; - public: - tr_transformer_fn(const relation_signature & rsig, table_transformer_fn * tfun) - : m_tfun(tfun) { get_result_signature() = rsig; } - - virtual relation_base * operator()(const relation_base & t) { - SASSERT(t.from_table()); - table_relation_plugin & plugin = static_cast(t.get_plugin()); - - const table_relation & tr = static_cast(t); - - table_base * tres = (*m_tfun)(tr.get_table()); - - TRACE("dl_table_relation", tout << "# transform => "; tres->display(tout);); - if(&tres->get_plugin()!=&plugin.m_table_plugin) { - //Transformation returned a table of different type than the one which is associated with this plugin. - //We need to get a correct table_relation_plugin and create the relation using it. - return plugin.get_manager().get_table_relation_plugin(tres->get_plugin()) - .mk_from_table(get_result_signature(), tres); - } - return plugin.mk_from_table(get_result_signature(), tres); - } - }; - - relation_transformer_fn * table_relation_plugin::mk_project_fn(const relation_base & t, unsigned col_cnt, - const unsigned * removed_cols) { - if(!t.from_table()) { - return 0; - } - const table_relation & tr = static_cast(t); - - table_transformer_fn * tfun = get_manager().mk_project_fn(tr.get_table(), col_cnt, removed_cols); - SASSERT(tfun); - - relation_signature sig; - relation_signature::from_project(t.get_signature(), col_cnt, removed_cols, sig); - - return alloc(tr_transformer_fn, sig, tfun); - } - - relation_transformer_fn * table_relation_plugin::mk_rename_fn(const relation_base & t, unsigned permutation_cycle_len, - const unsigned * permutation_cycle) { - if(!t.from_table()) { - return 0; - } - const table_relation & tr = static_cast(t); - - table_transformer_fn * tfun = get_manager().mk_rename_fn(tr.get_table(), permutation_cycle_len, permutation_cycle); - SASSERT(tfun); - - relation_signature sig; - relation_signature::from_rename(t.get_signature(), permutation_cycle_len, permutation_cycle, sig); - - return alloc(tr_transformer_fn, sig, tfun); - } - - relation_transformer_fn * table_relation_plugin::mk_permutation_rename_fn(const relation_base & t, - const unsigned * permutation) { - if(!t.from_table()) { - return 0; - } - const table_relation & tr = static_cast(t); - - table_transformer_fn * tfun = get_manager().mk_permutation_rename_fn(tr.get_table(), permutation); - SASSERT(tfun); - - relation_signature sig; - relation_signature::from_permutation_rename(t.get_signature(), permutation, sig); - - return alloc(tr_transformer_fn, sig, tfun); - } - - relation_transformer_fn * table_relation_plugin::mk_select_equal_and_project_fn(const relation_base & t, - const relation_element & value, unsigned col) { - if(!t.from_table()) { - return 0; - } - const table_relation & tr = static_cast(t); - - table_element tvalue; - get_manager().relation_to_table(tr.get_signature()[col], value, tvalue); - - table_transformer_fn * tfun = get_manager().mk_select_equal_and_project_fn(tr.get_table(), tvalue, col); - SASSERT(tfun); - relation_signature res_sig; - relation_signature::from_project(t.get_signature(), 1, &col, res_sig); - return alloc(tr_transformer_fn, res_sig, tfun); - } - - /** - Union functor that can unite table relation into any other relation (using any delta relation) - by iterating through the table and calling \c add_fact of the target relation. - */ - class table_relation_plugin::universal_target_union_fn : public relation_union_fn { - virtual void operator()(relation_base & tgt, const relation_base & src, relation_base * delta) { - SASSERT(src.from_table()); - - const table_relation & tr_src = static_cast(src); - relation_manager & rmgr = tr_src.get_manager(); - relation_signature sig = tr_src.get_signature(); - SASSERT(tgt.get_signature()==sig); - SASSERT(!delta || delta->get_signature()==sig); - - table_base::iterator it = tr_src.get_table().begin(); - table_base::iterator end = tr_src.get_table().end(); - - table_fact tfact; - relation_fact rfact(rmgr.get_context()); - for (; it != end; ++it) { - it->get_fact(tfact); - rmgr.table_fact_to_relation(sig, tfact, rfact); - if(delta) { - if(!tgt.contains_fact(rfact)) { - tgt.add_new_fact(rfact); - delta->add_fact(rfact); - } - } - else { - tgt.add_fact(rfact); - } - } - TRACE("dl_table_relation", tout << "# universal union => "; tgt.display(tout);); - } - }; - - class table_relation_plugin::tr_union_fn : public relation_union_fn { - scoped_ptr m_tfun; - public: - tr_union_fn(table_union_fn * tfun) : m_tfun(tfun) {} - - virtual void operator()(relation_base & tgt, const relation_base & src, relation_base * delta) { - SASSERT(tgt.from_table()); - SASSERT(src.from_table()); - SASSERT(!delta || delta->from_table()); - - table_relation & tr_tgt = static_cast(tgt); - const table_relation & tr_src = static_cast(src); - table_relation * tr_delta = static_cast(delta); - - (*m_tfun)(tr_tgt.get_table(), tr_src.get_table(), tr_delta ? &tr_delta->get_table() : 0); - - TRACE("dl_table_relation", tout << "# union => "; tr_tgt.get_table().display(tout);); - } - }; - - relation_union_fn * table_relation_plugin::mk_union_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta) { - if(!src.from_table()) { - return 0; - } - if(!tgt.from_table() || (delta && !delta->from_table())) { - return alloc(universal_target_union_fn); - } - const table_relation & tr_tgt = static_cast(tgt); - const table_relation & tr_src = static_cast(src); - const table_relation * tr_delta = static_cast(delta); - - table_union_fn * tfun = get_manager().mk_union_fn(tr_tgt.get_table(), tr_src.get_table(), - tr_delta ? &tr_delta->get_table() : 0); - SASSERT(tfun); - - return alloc(tr_union_fn, tfun); - } - - - class table_relation_plugin::tr_mutator_fn : public relation_mutator_fn { - scoped_ptr m_tfun; - public: - tr_mutator_fn(table_mutator_fn * tfun) : m_tfun(tfun) {} - - virtual void operator()(relation_base & r) { - SASSERT(r.from_table()); - table_relation & tr = static_cast(r); - (*m_tfun)(tr.get_table()); - TRACE("dl_table_relation", tout << "# mutator => "; tr.get_table().display(tout);); - } - }; - - relation_mutator_fn * table_relation_plugin::mk_filter_identical_fn(const relation_base & t, unsigned col_cnt, - const unsigned * identical_cols) { - if(!t.from_table()) { - return 0; - } - const table_relation & tr = static_cast(t); - - table_mutator_fn * tfun = get_manager().mk_filter_identical_fn(tr.get_table(), col_cnt, identical_cols); - SASSERT(tfun); - return alloc(tr_mutator_fn, tfun); - } - - relation_mutator_fn * table_relation_plugin::mk_filter_equal_fn(const relation_base & t, const relation_element & value, - unsigned col) { - if(!t.from_table()) { - return 0; - } - const table_relation & tr = static_cast(t); - - table_element tvalue; - get_manager().relation_to_table(tr.get_signature()[col], value, tvalue); - - table_mutator_fn * tfun = get_manager().mk_filter_equal_fn(tr.get_table(), tvalue, col); - SASSERT(tfun); - return alloc(tr_mutator_fn, tfun); - } - - relation_mutator_fn * table_relation_plugin::mk_filter_interpreted_fn(const relation_base & t, app * condition) { - bool condition_needs_transforming = false; - if(!t.from_table() || condition_needs_transforming) { - return 0; - } - const table_relation & tr = static_cast(t); - table_mutator_fn * tfun = get_manager().mk_filter_interpreted_fn(tr.get_table(), condition); - SASSERT(tfun); - return alloc(tr_mutator_fn, tfun); - } - - relation_transformer_fn * table_relation_plugin::mk_filter_interpreted_and_project_fn(const relation_base & t, - app * condition, unsigned removed_col_cnt, const unsigned * removed_cols) { - if (!t.from_table()) - return 0; - - const table_relation & tr = static_cast(t); - table_transformer_fn * tfun = get_manager().mk_filter_interpreted_and_project_fn(tr.get_table(), - condition, removed_col_cnt, removed_cols); - SASSERT(tfun); - - relation_signature sig; - relation_signature::from_project(t.get_signature(), removed_col_cnt, removed_cols, sig); - return alloc(tr_transformer_fn, sig, tfun); - } - - class table_relation_plugin::tr_intersection_filter_fn : public relation_intersection_filter_fn { - scoped_ptr m_tfun; - public: - tr_intersection_filter_fn(table_intersection_filter_fn * tfun) : m_tfun(tfun) {} - - virtual void operator()(relation_base & r, const relation_base & src) { - SASSERT(r.from_table()); - SASSERT(src.from_table()); - - table_relation & tr = static_cast(r); - const table_relation & tr_src = static_cast(src); - - (*m_tfun)(tr.get_table(), tr_src.get_table()); - TRACE("dl_table_relation", tout << "# negation_filter => "; tr.get_table().display(tout);); - } - }; - - relation_intersection_filter_fn * table_relation_plugin::mk_filter_by_intersection_fn(const relation_base & r, - const relation_base & src, unsigned joined_col_cnt, const unsigned * r_cols, const unsigned * src_cols) { - if(!r.from_table() || !src.from_table()) { - return 0; - } - const table_relation & tr = static_cast(r); - const table_relation & tr_neg = static_cast(src); - table_intersection_filter_fn * tfun = get_manager().mk_filter_by_intersection_fn(tr.get_table(), - tr_neg.get_table(), joined_col_cnt, r_cols, src_cols); - if(!tfun) { - return 0; - } - - return alloc(tr_intersection_filter_fn, tfun); - } - - - relation_intersection_filter_fn * table_relation_plugin::mk_filter_by_negation_fn(const relation_base & r, - const relation_base & negated_rel, unsigned joined_col_cnt, - const unsigned * r_cols, const unsigned * negated_cols) { - if(!r.from_table() || !negated_rel.from_table()) { - return 0; - } - const table_relation & tr = static_cast(r); - const table_relation & tr_neg = static_cast(negated_rel); - table_intersection_filter_fn * tfun = get_manager().mk_filter_by_negation_fn(tr.get_table(), - tr_neg.get_table(), joined_col_cnt, r_cols, negated_cols); - SASSERT(tfun); - - return alloc(tr_intersection_filter_fn, tfun); - } - - - // ----------------------------------- - // - // table_relation - // - // ----------------------------------- - - void table_relation::add_table_fact(const table_fact & f) { - get_table().add_fact(f); - } - - void table_relation::add_fact(const relation_fact & f) { - SASSERT(f.size()==get_signature().size()); - table_fact vals; - get_manager().relation_fact_to_table(get_signature(), f, vals); - get_table().add_fact(vals); - TRACE("dl_table_relation", tout << "# add fact => "; get_table().display(tout);); - } - - bool table_relation::contains_fact(const relation_fact & f) const { - table_fact vals; - get_manager().relation_fact_to_table(get_signature(), f, vals); - return get_table().contains_fact(vals); - } - - relation_base * table_relation::clone() const { - table_base * tres = get_table().clone(); - return get_plugin().mk_from_table(get_signature(), tres); - } - - relation_base * table_relation::complement(func_decl* p) const { - table_base * tres = get_table().complement(p); - return get_plugin().mk_from_table(get_signature(), tres); - } - - void table_relation::display_tuples(func_decl & pred, std::ostream & out) const { - context & ctx = get_manager().get_context(); - unsigned arity = pred.get_arity(); - - out << "Tuples in " << pred.get_name() << ": \n"; - - table_base::iterator it = get_table().begin(); - table_base::iterator end = get_table().end(); - - table_fact fact; - for (; it != end; ++it) { - it->get_fact(fact); - - out << "\t("; - - for(unsigned i=0;i - -Author: - - Krystof Hoder (t-khoder) 2010-09-24. - -Revision History: - ---*/ -#ifndef _DL_TABLE_RELATION_H_ -#define _DL_TABLE_RELATION_H_ - - -#include "dl_base.h" -#include "dl_util.h" - -namespace datalog { - - class table_relation; - - class table_relation_plugin : public relation_plugin { - friend class table_relation; - - class tr_join_project_fn; - class tr_transformer_fn; - class universal_target_union_fn; - class tr_union_fn; - class tr_mutator_fn; - class tr_intersection_filter_fn; - - table_plugin & m_table_plugin; - - static symbol create_plugin_name(const table_plugin & p); - public: - table_relation_plugin(table_plugin & tp, relation_manager & manager) - : relation_plugin(create_plugin_name(tp), manager, ST_TABLE_RELATION), m_table_plugin(tp) {} - - table_plugin & get_table_plugin() { return m_table_plugin; } - - virtual bool can_handle_signature(const relation_signature & s); - - virtual relation_base * mk_empty(const relation_signature & s); - virtual relation_base * mk_full(const relation_signature & s, func_decl* p, family_id kind); - relation_base * mk_from_table(const relation_signature & s, table_base * t); - - protected: - virtual relation_join_fn * mk_join_fn(const relation_base & t1, const relation_base & t2, - unsigned col_cnt, const unsigned * cols1, const unsigned * cols2); - virtual relation_join_fn * mk_join_project_fn(const relation_base & t1, const relation_base & t2, - unsigned joined_col_cnt, const unsigned * cols1, const unsigned * cols2, unsigned removed_col_cnt, - const unsigned * removed_cols); - virtual relation_transformer_fn * mk_project_fn(const relation_base & t, unsigned col_cnt, - const unsigned * removed_cols); - virtual relation_transformer_fn * mk_rename_fn(const relation_base & t, unsigned permutation_cycle_len, - const unsigned * permutation_cycle); - virtual relation_transformer_fn * mk_permutation_rename_fn(const relation_base & t, - const unsigned * permutation); - virtual relation_union_fn * mk_union_fn(const relation_base & tgt, const relation_base & src, - const relation_base * delta); - virtual relation_mutator_fn * mk_filter_identical_fn(const relation_base & t, unsigned col_cnt, - const unsigned * identical_cols); - virtual relation_mutator_fn * mk_filter_equal_fn(const relation_base & t, const relation_element & value, - unsigned col); - virtual relation_mutator_fn * mk_filter_interpreted_fn(const relation_base & t, app * condition); - virtual relation_transformer_fn * mk_filter_interpreted_and_project_fn(const relation_base & t, - app * condition, unsigned removed_col_cnt, const unsigned * removed_cols); - virtual relation_intersection_filter_fn * mk_filter_by_intersection_fn(const relation_base & t, - const relation_base & src, unsigned joined_col_cnt, const unsigned * t_cols, const unsigned * src_cols); - virtual relation_intersection_filter_fn * mk_filter_by_negation_fn(const relation_base & t, - const relation_base & negated_obj, unsigned joined_col_cnt, - const unsigned * t_cols, const unsigned * negated_cols); - virtual relation_transformer_fn * mk_select_equal_and_project_fn(const relation_base & t, - const relation_element & value, unsigned col); - }; - - class table_relation : public relation_base { - friend class table_relation_plugin; - friend class table_relation_plugin::tr_join_project_fn; - friend class table_relation_plugin::tr_transformer_fn; - - scoped_rel m_table; - - /** - \brief Create a \c table_relation object. - - The newly created object takes ownership of the \c table object. - */ - table_relation(table_relation_plugin & p, const relation_signature & s, table_base * table) - : relation_base(p, s), m_table(table) { - SASSERT(s.size()==table->get_signature().size()); - } - public: - - table_relation_plugin & get_plugin() const { - return static_cast(relation_base::get_plugin()); - } - - table_base & get_table() { return *m_table; } - const table_base & get_table() const { return *m_table; } - - virtual bool empty() const { return m_table->empty(); } - - void add_table_fact(const table_fact & f); - - virtual void add_fact(const relation_fact & f); - virtual bool contains_fact(const relation_fact & f) const; - virtual relation_base * clone() const; - virtual relation_base * complement(func_decl* p) const; - virtual void to_formula(expr_ref& fml) const { get_table().to_formula(get_signature(), fml); } - - virtual void display(std::ostream & out) const { - get_table().display(out); - } - virtual void display_tuples(func_decl & pred, std::ostream & out) const; - - virtual unsigned get_size_estimate_rows() const { return m_table->get_size_estimate_rows(); } - virtual unsigned get_size_estimate_bytes() const { return m_table->get_size_estimate_bytes(); } - virtual bool knows_exact_size() const { return m_table->knows_exact_size(); } - }; - -}; - -#endif /* _DL_TABLE_RELATION_H_ */ - diff --git a/src/muz/dl_util.cpp b/src/muz/dl_util.cpp index 0b88136e2..e32999ddc 100644 --- a/src/muz/dl_util.cpp +++ b/src/muz/dl_util.cpp @@ -32,14 +32,6 @@ Revision History: namespace datalog { - void universal_delete(relation_base* ptr) { - ptr->deallocate(); - } - - void universal_delete(table_base* ptr) { - ptr->deallocate(); - } - bool contains_var(expr * trm, unsigned var_idx) { ptr_vector vars; @@ -420,18 +412,6 @@ namespace datalog { } } - void get_renaming_args(const unsigned_vector & map, const relation_signature & orig_sig, - expr_ref_vector & renaming_arg) { - ast_manager & m = renaming_arg.get_manager(); - unsigned sz = map.size(); - unsigned ofs = sz-1; - renaming_arg.resize(sz, static_cast(0)); - for(unsigned i=0; i & v) { - ptr_vector::iterator it = v.begin(); - ptr_vector::iterator end = v.end(); - for(; it!=end; ++it) { - (*it)->deallocate(); - } - } // ----------------------------------- diff --git a/src/muz/dl_util.h b/src/muz/dl_util.h index debb4d3e2..d805e683b 100644 --- a/src/muz/dl_util.h +++ b/src/muz/dl_util.h @@ -50,52 +50,6 @@ namespace datalog { LAST_CACHE_MODE }; - enum DL_ENGINE { - DATALOG_ENGINE, - PDR_ENGINE, - QPDR_ENGINE, - BMC_ENGINE, - QBMC_ENGINE, - TAB_ENGINE, - CLP_ENGINE, - LAST_ENGINE - }; - - class engine_base { - ast_manager& m; - std::string m_name; - public: - engine_base(ast_manager& m, char const* name): m(m), m_name(name) {} - virtual ~engine_base() {} - - virtual expr_ref get_answer() = 0; - virtual lbool query(expr* q) = 0; - - virtual void reset_statistics() {} - virtual void display_profile(std::ostream& out) const {} - virtual void collect_statistics(statistics& st) const {} - virtual unsigned get_num_levels(func_decl* pred) { - throw default_exception(std::string("get_num_levels is not supported for ") + m_name); - } - virtual expr_ref get_cover_delta(int level, func_decl* pred) { - throw default_exception(std::string("operation is not supported for ") + m_name); - } - virtual void add_cover(int level, func_decl* pred, expr* property) { - throw default_exception(std::string("operation is not supported for ") + m_name); - } - virtual void display_certificate(std::ostream& out) const { - throw default_exception(std::string("certificates are not supported for ") + m_name); - } - virtual model_ref get_model() { - return model_ref(alloc(model, m)); - } - virtual proof_ref get_proof() { - return proof_ref(m.mk_asserted(m.mk_true()), m); - } - virtual void updt_params() {} - virtual void cancel() {} - virtual void cleanup() {} - }; struct std_string_hash_proc { unsigned operator()(const std::string & s) const @@ -435,14 +389,6 @@ namespace datalog { void reverse_renaming(ast_manager & m, const expr_ref_vector & src, expr_ref_vector & tgt); - /** - \brief Populate vector \c renaming_args so that it can be used as an argument to \c var_subst. - The renaming we want is one that transforms variables with numbers of indexes of \c map into the - values of at those indexes. If a value if \c UINT_MAX, it means we do not transform the index - corresponding to it. - */ - void get_renaming_args(const unsigned_vector & map, const relation_signature & orig_sig, - expr_ref_vector & renaming_arg); void print_renaming(const expr_ref_vector & cont, std::ostream & out); @@ -634,8 +580,6 @@ namespace datalog { } } - void dealloc_ptr_vector_content(ptr_vector & v); - /** \brief Add elements from an iterable object \c src into the vector \c vector. */ @@ -792,9 +736,6 @@ namespace datalog { dealloc(ptr); } - void universal_delete(relation_base* ptr); - void universal_delete(table_base* ptr); - template class scoped_rel { T* m_t; diff --git a/src/muz/dl_vector_relation.h b/src/muz/dl_vector_relation.h deleted file mode 100644 index 114f4ca43..000000000 --- a/src/muz/dl_vector_relation.h +++ /dev/null @@ -1,407 +0,0 @@ -/*++ -Copyright (c) 2010 Microsoft Corporation - -Module Name: - - dl_vector_relation.h - -Abstract: - - Basic relation with equivalences. - -Author: - - Nikolaj Bjorner (nbjorner) 2010-2-11 - -Revision History: - ---*/ -#ifndef _DL_VECTOR_RELATION_H_ -#define _DL_VECTOR_RELATION_H_ - -#include "ast_pp.h" -#include "dl_context.h" -#include "union_find.h" - -namespace datalog { - - typedef std::pair u_pair; - - template - class vector_relation_helper { - public: - static void mk_project_t(T& t, unsigned_vector const& renaming) {} - }; - - template > - class vector_relation : public relation_base { - protected: - T m_default; - vector* m_elems; - bool m_empty; - union_find_default_ctx m_ctx; - union_find<>* m_eqs; - - friend class vector_relation_plugin; - - public: - vector_relation(relation_plugin& p, relation_signature const& s, bool is_empty, T const& t = T()): - relation_base(p, s), - m_default(t), - m_elems(alloc(vector)), - m_empty(is_empty), - m_eqs(alloc(union_find<>, m_ctx)) { - m_elems->resize(s.size(), t); - for (unsigned i = 0; i < s.size(); ++i) { - m_eqs->mk_var(); - } - } - - virtual ~vector_relation() { - dealloc(m_eqs); - dealloc(m_elems); - } - - virtual bool can_swap() const { return true; } - - virtual void swap(relation_base& other) { - vector_relation& o = dynamic_cast(other); - if (&o == this) return; - std::swap(o.m_eqs, m_eqs); - std::swap(o.m_empty, m_empty); - std::swap(o.m_elems, m_elems); - } - - void copy(vector_relation const& other) { - SASSERT(get_signature() == other.get_signature()); - if (other.empty()) { - set_empty(); - return; - } - m_empty = false; - for (unsigned i = 0; i < m_elems->size(); ++i) { - (*this)[i] = other[i]; - SASSERT(find(i) == i); - } - for (unsigned i = 0; i < m_elems->size(); ++i) { - merge(i, find(i)); - } - } - - - virtual bool empty() const { return m_empty; } - - T& operator[](unsigned i) { return (*m_elems)[find(i)]; } - - T const& operator[](unsigned i) const { return (*m_elems)[find(i)]; } - - virtual void display_index(unsigned i, T const& t, std::ostream& out) const = 0; - - virtual void display(std::ostream & out) const { - if (empty()) { - out << "empty\n"; - return; - } - for (unsigned i = 0; i < m_elems->size(); ++i) { - if (i == find(i)) { - display_index(i, (*m_elems)[i], out); - } - else { - out << i << " = " << find(i) << "\n"; - } - } - } - - - bool is_subset_of(vector_relation const& other) const { - if (empty()) return true; - if (other.empty()) return false; - for (unsigned i = 0; i < get_signature().size(); ++i) { - if (!is_subset_of((*this)[i], other[i])) { - return false; - } - } - return true; - } - - void set_empty() { - unsigned sz = m_elems->size(); - m_empty = true; - m_elems->reset(); - m_elems->resize(sz, m_default); - dealloc(m_eqs); - m_eqs = alloc(union_find<>,m_ctx); - for (unsigned i = 0; i < sz; ++i) { - m_eqs->mk_var(); - } - } - - - virtual T mk_intersect(T const& t1, T const& t2, bool& is_empty) const = 0; - - virtual T mk_widen(T const& t1, T const& t2) const = 0; - - virtual T mk_unite(T const& t1, T const& t2) const = 0; - - virtual bool is_subset_of(T const& t1, T const& t2) const = 0; - - virtual bool is_full(T const& t) const = 0; - - virtual bool is_empty(unsigned i, T const& t) const = 0; - - virtual void mk_rename_elem(T& t, unsigned col_cnt, unsigned const* cycle) = 0; - - virtual T mk_eq(union_find<> const& old_eqs, union_find<> const& neq_eqs, T const& t) const { return t; } - - void equate(unsigned i, unsigned j) { - SASSERT(i < get_signature().size()); - SASSERT(j < get_signature().size()); - if (!empty() && find(i) != find(j)) { - bool isempty; - T r = mk_intersect((*this)[i], (*this)[j], isempty); - if (isempty || is_empty(find(i),r)) { - m_empty = true; - } - else { - merge(i, j); - (*this)[i] = r; - } - } - } - - bool is_full() const { - for (unsigned i = 0; i < m_elems->size(); ++i) { - if (!is_full((*this)[i])) { - return false; - } - } - return true; - } - - void mk_join(vector_relation const& r1, vector_relation const& r2, - unsigned num_cols, unsigned const* cols1, unsigned const* cols2) { - SASSERT(is_full()); - bool is_empty = r1.empty() || r2.empty(); - if (is_empty) { - m_empty = true; - return; - } - unsigned sz1 = r1.get_signature().size(); - unsigned sz2 = r2.get_signature().size(); - for (unsigned i = 0; i < sz1; ++i) { - (*this)[i] = r1[i]; - } - for (unsigned i = 0; i < sz2; ++i) { - (*this)[sz1+i] = r2[i]; - } - for (unsigned i = 0; i < num_cols; ++i) { - unsigned col1 = cols1[i]; - unsigned col2 = cols2[i]; - equate(col1, sz1 + col2); - } - - TRACE("dl_relation", - r1.display(tout << "r1:\n"); - r2.display(tout << "r2:\n"); - display(tout << "dst:\n"); - ); - } - - void mk_project(vector_relation const& r, unsigned col_cnt, unsigned const* removed_cols) { - SASSERT(is_full()); - unsigned_vector classRep, repNode; - unsigned result_size = get_signature().size(); - unsigned input_size = r.get_signature().size(); - repNode.resize(input_size, UINT_MAX); - - // initialize vector entries and set class representatives. - for (unsigned i = 0, j = 0, c = 0; i < input_size; ++i) { - if (c < col_cnt && removed_cols[c] == i) { - ++c; - } - else { - (*this)[j] = r[i]; - classRep.push_back(r.find(i)); - ++j; - } - } - - // merge remaining equivalence classes. - for (unsigned i = 0; i < result_size; ++i) { - unsigned rep = classRep[i]; - if (repNode[rep] == UINT_MAX) { - repNode[rep] = i; - } - else { - merge(repNode[rep], i); - } - } - - // rename columns in image of vector relation. - unsigned_vector renaming; - for (unsigned i = 0, j = 0, c = 0; i < input_size; ++i) { - if (c < col_cnt && removed_cols[c] == i) { - renaming.push_back(UINT_MAX); - ++c; - } - else { - renaming.push_back(find(j)); - ++j; - } - } - for (unsigned k = 0; k < result_size; ++k) { - Helper::mk_project_t((*this)[k], renaming); - } - - - TRACE("dl_relation", - ast_manager& m = r.get_plugin().get_ast_manager(); - tout << "Signature: "; - for (unsigned i = 0; i < r.get_signature().size(); ++i) { - tout << mk_pp(r.get_signature()[i], m) << " "; - } - tout << "Remove: "; - for (unsigned i = 0; i < col_cnt; ++i) { - tout << removed_cols[i] << " "; - } - tout << "\n"; - r.display(tout); - tout << " --> \n"; - display(tout);); - } - - void mk_rename(vector_relation const& r, unsigned col_cnt, unsigned const* cycle) { - unsigned col1, col2; - SASSERT(is_full()); - - // roundabout way of creating permuted relation. - unsigned_vector classRep, repNode; - for (unsigned i = 0; i < r.m_elems->size(); ++i) { - classRep.push_back(r.find(i)); - repNode.push_back(UINT_MAX); - (*this)[i] = r[i]; - } - for (unsigned i = 0; i + 1 < col_cnt; ++i) { - col1 = cycle[i]; - col2 = cycle[i+1]; - (*this)[col2] = (*r.m_elems)[col1]; - classRep[col2] = r.find(col1); - } - col1 = cycle[col_cnt-1]; - col2 = cycle[0]; - (*this)[col2] = (*r.m_elems)[col1]; - classRep[col2] = r.find(col1); - - for (unsigned i = 0; i < r.m_elems->size(); ++i) { - unsigned rep = classRep[i]; - if (repNode[rep] == UINT_MAX) { - repNode[rep] = i; - } - else { - merge(repNode[rep], i); - } - } - - for (unsigned i = 0; i < r.m_elems->size(); ++i) { - mk_rename_elem((*m_elems)[i], col_cnt, cycle); - } - - TRACE("dl_relation", - ast_manager& m = r.get_plugin().get_ast_manager(); - tout << "cycle: "; - for (unsigned i = 0; i < col_cnt; ++i) { - tout << cycle[i] << " "; - } - tout << "\nold_sig: "; - for (unsigned i = 0; i < r.get_signature().size(); ++i) { - tout << mk_pp(r.get_signature()[i], m) << " "; - } - tout << "\nnew_sig: "; - for (unsigned i = 0; i < get_signature().size(); ++i) { - tout << mk_pp(get_signature()[i], m) << " "; - } - tout << "\n"; - r.display(tout << "src:\n"); - ); - } - - void mk_union(vector_relation const& src, vector_relation* delta, bool is_widen) { - TRACE("dl_relation", display(tout << "dst:\n"); src.display(tout << "src:\n");); - - if (src.empty()) { - if (delta) { - delta->copy(src); - } - return; - } - - if (empty()) { - copy(src); - if (delta) { - delta->copy(src); - } - return; - } - - // find coarsest equivalence class containing joint equalities - union_find<>* uf = alloc(union_find<>, m_ctx); - unsigned size = get_signature().size(); - map, default_eq > mp; - bool change = false; - bit_vector finds; - finds.resize(size, false); - for (unsigned i = 0; i < size; ++i) { - uf->mk_var(); - unsigned w; - u_pair p(std::make_pair(find(i), src.find(i))); - if (mp.find(p, w)) { - uf->merge(i, w); - } - else { - mp.insert(p, i); - // detect change - if (finds.get(find(i))) { - change = true; - } - else { - finds.set(find(i), true); - } - } - } - vector* elems = alloc(vector); - for (unsigned i = 0; i < size; ++i) { - T t1 = mk_eq(*m_eqs, *uf, (*this)[i]); - T t2 = mk_eq(*src.m_eqs, *uf, src[i]); - if (is_widen) { - elems->push_back(mk_widen(t1, t2)); - } - else { - elems->push_back(mk_unite(t1, t2)); - } - TRACE("dl_relation", tout << t1 << " u " << t2 << " = " << elems->back() << "\n";); - change = delta && (change || !((*elems)[i] == (*this)[i])); - } - dealloc(m_eqs); - dealloc(m_elems); - m_eqs = uf; - m_elems = elems; - if (delta && change) { - delta->copy(*this); - } - TRACE("dl_relation", display(tout << "dst':\n");); - } - - unsigned find(unsigned i) const { - return m_eqs->find(i); - } - - void merge(unsigned i, unsigned j) { - m_eqs->merge(i, j); - } - - }; - -}; - -#endif - diff --git a/src/muz/dl_cmds.cpp b/src/muz/fp/dl_cmds.cpp similarity index 98% rename from src/muz/dl_cmds.cpp rename to src/muz/fp/dl_cmds.cpp index dcdf3ebb4..7f73b0895 100644 --- a/src/muz/dl_cmds.cpp +++ b/src/muz/fp/dl_cmds.cpp @@ -19,6 +19,7 @@ Notes: #include"dl_cmds.h" #include"dl_external_relation.h" #include"dl_context.h" +#include"dl_register_engine.h" #include"dl_decl_plugin.h" #include"dl_instruction.h" #include"dl_compiler.h" @@ -37,6 +38,7 @@ struct dl_context { params_ref m_params_ref; fixedpoint_params m_params; cmd_context & m_cmd; + datalog::register_engine m_register_engine; dl_collected_cmds* m_collected_cmds; unsigned m_ref_count; datalog::dl_decl_plugin* m_decl_plugin; @@ -70,7 +72,7 @@ struct dl_context { void init() { ast_manager& m = m_cmd.m(); if (!m_context) { - m_context = alloc(datalog::context, m, m_fparams, m_params_ref); + m_context = alloc(datalog::context, m, m_register_engine, m_fparams, m_params_ref); } if (!m_decl_plugin) { symbol name("datalog_relation"); diff --git a/src/muz/fp/dl_register_engine.cpp b/src/muz/fp/dl_register_engine.cpp new file mode 100644 index 000000000..84b64fafa --- /dev/null +++ b/src/muz/fp/dl_register_engine.cpp @@ -0,0 +1,51 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + dl_register_engine.cpp + +Abstract: + + Class for creating Datalog engines. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-08-28 + +Revision History: + +--*/ +#include "dl_register_engine.h" +#include "dl_bmc_engine.h" +#include "clp_context.h" +#include "tab_context.h" +#include "rel_context.h" +#include "pdr_dl_interface.h" + +namespace datalog { + register_engine::register_engine(): m_ctx(0) {} + + engine_base* register_engine::mk_engine(DL_ENGINE engine_type) { + switch(engine_type) { + case PDR_ENGINE: + case QPDR_ENGINE: + return alloc(pdr::dl_interface, *m_ctx); + case DATALOG_ENGINE: + return alloc(rel_context, *m_ctx); + case BMC_ENGINE: + case QBMC_ENGINE: + return alloc(bmc, *m_ctx); + case TAB_ENGINE: + return alloc(tab, *m_ctx); + case CLP_ENGINE: + return alloc(clp, *m_ctx); + case LAST_ENGINE: + UNREACHABLE(); + return 0; + } + UNREACHABLE(); + return 0; + } + +} diff --git a/src/muz/fp/dl_register_engine.h b/src/muz/fp/dl_register_engine.h new file mode 100644 index 000000000..44f5090e6 --- /dev/null +++ b/src/muz/fp/dl_register_engine.h @@ -0,0 +1,36 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + dl_register_engine.h + +Abstract: + + Class for creating Datalog engines. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-08-28 + +Revision History: + +--*/ +#ifndef _DL_REGISTER_ENGINE_H_ +#define _DL_REGISTER_ENGINE_H_ + +#include "dl_context.h" + +namespace datalog { + + class register_engine : public register_engine_base { + context* m_ctx; + public: + register_engine(); + engine_base* mk_engine(DL_ENGINE engine_type); + void set_context(context* ctx) { m_ctx = ctx; } + }; + +} + +#endif diff --git a/src/muz/horn_tactic.cpp b/src/muz/fp/horn_tactic.cpp similarity index 98% rename from src/muz/horn_tactic.cpp rename to src/muz/fp/horn_tactic.cpp index 07a0e2568..ca6cbc2fb 100644 --- a/src/muz/horn_tactic.cpp +++ b/src/muz/fp/horn_tactic.cpp @@ -21,22 +21,25 @@ Revision History: #include"proof_converter.h" #include"horn_tactic.h" #include"dl_context.h" +#include"dl_register_engine.h" #include"expr_replacer.h" #include"dl_rule_transformer.h" #include"dl_mk_slice.h" #include"filter_model_converter.h" +#include"dl_transforms.h" class horn_tactic : public tactic { struct imp { ast_manager& m; bool m_is_simplify; + datalog::register_engine m_register_engine; datalog::context m_ctx; smt_params m_fparams; imp(bool t, ast_manager & m, params_ref const & p): m(m), m_is_simplify(t), - m_ctx(m, m_fparams) { + m_ctx(m, m_register_engine, m_fparams) { updt_params(p); } @@ -310,7 +313,7 @@ class horn_tactic : public tactic { func_decl* query_pred = to_app(q)->get_decl(); m_ctx.set_output_predicate(query_pred); m_ctx.get_rules(); // flush adding rules. - m_ctx.apply_default_transformation(); + apply_default_transformation(m_ctx); if (m_ctx.get_params().slice()) { datalog::rule_transformer transformer(m_ctx); diff --git a/src/muz/horn_tactic.h b/src/muz/fp/horn_tactic.h similarity index 100% rename from src/muz/horn_tactic.h rename to src/muz/fp/horn_tactic.h diff --git a/src/muz/pdr_context.cpp b/src/muz/pdr/pdr_context.cpp similarity index 100% rename from src/muz/pdr_context.cpp rename to src/muz/pdr/pdr_context.cpp diff --git a/src/muz/pdr_context.h b/src/muz/pdr/pdr_context.h similarity index 99% rename from src/muz/pdr_context.h rename to src/muz/pdr/pdr_context.h index 3501ca7cd..57238abb3 100644 --- a/src/muz/pdr_context.h +++ b/src/muz/pdr/pdr_context.h @@ -26,7 +26,6 @@ Revision History: #endif #include #include "pdr_manager.h" -#include "dl_base.h" #include "pdr_prop_solver.h" #include "pdr_reachable_cache.h" diff --git a/src/muz/pdr_dl_interface.cpp b/src/muz/pdr/pdr_dl_interface.cpp similarity index 98% rename from src/muz/pdr_dl_interface.cpp rename to src/muz/pdr/pdr_dl_interface.cpp index 05a13dfc7..ccd22d57f 100644 --- a/src/muz/pdr_dl_interface.cpp +++ b/src/muz/pdr/pdr_dl_interface.cpp @@ -17,7 +17,6 @@ Revision History: --*/ -#include "dl_cmds.h" #include "dl_context.h" #include "dl_mk_coi_filter.h" #include "dl_mk_interp_tail_simplifier.h" @@ -33,6 +32,7 @@ Revision History: #include "dl_mk_unfold.h" #include "dl_mk_coalesce.h" #include "model_smt2_pp.h" +#include "dl_transforms.h" using namespace pdr; @@ -102,7 +102,7 @@ lbool dl_interface::query(expr * query) { ); - m_ctx.apply_default_transformation(); + apply_default_transformation(m_ctx); if (m_ctx.get_params().slice()) { datalog::rule_transformer transformer(m_ctx); diff --git a/src/muz/pdr_dl_interface.h b/src/muz/pdr/pdr_dl_interface.h similarity index 98% rename from src/muz/pdr_dl_interface.h rename to src/muz/pdr/pdr_dl_interface.h index 2075dff47..610e7fe06 100644 --- a/src/muz/pdr_dl_interface.h +++ b/src/muz/pdr/pdr_dl_interface.h @@ -24,6 +24,7 @@ Revision History: #include "dl_rule.h" #include "dl_rule_set.h" #include "dl_util.h" +#include "dl_engine_base.h" #include "statistics.h" namespace datalog { diff --git a/src/muz/pdr_farkas_learner.cpp b/src/muz/pdr/pdr_farkas_learner.cpp similarity index 100% rename from src/muz/pdr_farkas_learner.cpp rename to src/muz/pdr/pdr_farkas_learner.cpp diff --git a/src/muz/pdr_farkas_learner.h b/src/muz/pdr/pdr_farkas_learner.h similarity index 100% rename from src/muz/pdr_farkas_learner.h rename to src/muz/pdr/pdr_farkas_learner.h diff --git a/src/muz/pdr_generalizers.cpp b/src/muz/pdr/pdr_generalizers.cpp similarity index 99% rename from src/muz/pdr_generalizers.cpp rename to src/muz/pdr/pdr_generalizers.cpp index 883429315..f1ab01070 100644 --- a/src/muz/pdr_generalizers.cpp +++ b/src/muz/pdr/pdr_generalizers.cpp @@ -194,7 +194,7 @@ namespace pdr { } conv1.append(fmls); expr_ref fml = n.pt().get_formulas(n.level(), false); - expr_ref_vector fmls(m); + fmls.reset(); qe::flatten_and(fml, fmls); for (unsigned i = 0; i < fmls.size(); ++i) { fml = m.mk_not(fmls[i].get()); diff --git a/src/muz/pdr_generalizers.h b/src/muz/pdr/pdr_generalizers.h similarity index 100% rename from src/muz/pdr_generalizers.h rename to src/muz/pdr/pdr_generalizers.h diff --git a/src/muz/pdr_manager.cpp b/src/muz/pdr/pdr_manager.cpp similarity index 100% rename from src/muz/pdr_manager.cpp rename to src/muz/pdr/pdr_manager.cpp diff --git a/src/muz/pdr_manager.h b/src/muz/pdr/pdr_manager.h similarity index 100% rename from src/muz/pdr_manager.h rename to src/muz/pdr/pdr_manager.h diff --git a/src/muz/pdr_prop_solver.cpp b/src/muz/pdr/pdr_prop_solver.cpp similarity index 100% rename from src/muz/pdr_prop_solver.cpp rename to src/muz/pdr/pdr_prop_solver.cpp diff --git a/src/muz/pdr_prop_solver.h b/src/muz/pdr/pdr_prop_solver.h similarity index 100% rename from src/muz/pdr_prop_solver.h rename to src/muz/pdr/pdr_prop_solver.h diff --git a/src/muz/pdr_reachable_cache.cpp b/src/muz/pdr/pdr_reachable_cache.cpp similarity index 100% rename from src/muz/pdr_reachable_cache.cpp rename to src/muz/pdr/pdr_reachable_cache.cpp diff --git a/src/muz/pdr_reachable_cache.h b/src/muz/pdr/pdr_reachable_cache.h similarity index 100% rename from src/muz/pdr_reachable_cache.h rename to src/muz/pdr/pdr_reachable_cache.h diff --git a/src/muz/pdr_smt_context_manager.cpp b/src/muz/pdr/pdr_smt_context_manager.cpp similarity index 100% rename from src/muz/pdr_smt_context_manager.cpp rename to src/muz/pdr/pdr_smt_context_manager.cpp diff --git a/src/muz/pdr_smt_context_manager.h b/src/muz/pdr/pdr_smt_context_manager.h similarity index 100% rename from src/muz/pdr_smt_context_manager.h rename to src/muz/pdr/pdr_smt_context_manager.h diff --git a/src/muz/pdr_sym_mux.cpp b/src/muz/pdr/pdr_sym_mux.cpp similarity index 100% rename from src/muz/pdr_sym_mux.cpp rename to src/muz/pdr/pdr_sym_mux.cpp diff --git a/src/muz/pdr_sym_mux.h b/src/muz/pdr/pdr_sym_mux.h similarity index 100% rename from src/muz/pdr_sym_mux.h rename to src/muz/pdr/pdr_sym_mux.h diff --git a/src/muz/pdr_util.cpp b/src/muz/pdr/pdr_util.cpp similarity index 100% rename from src/muz/pdr_util.cpp rename to src/muz/pdr/pdr_util.cpp diff --git a/src/muz/pdr_util.h b/src/muz/pdr/pdr_util.h similarity index 100% rename from src/muz/pdr_util.h rename to src/muz/pdr/pdr_util.h diff --git a/src/muz/aig_exporter.cpp b/src/muz/rel/aig_exporter.cpp similarity index 100% rename from src/muz/aig_exporter.cpp rename to src/muz/rel/aig_exporter.cpp diff --git a/src/muz/aig_exporter.h b/src/muz/rel/aig_exporter.h similarity index 100% rename from src/muz/aig_exporter.h rename to src/muz/rel/aig_exporter.h index 20b31f01b..78ab9fe17 100644 --- a/src/muz/aig_exporter.h +++ b/src/muz/rel/aig_exporter.h @@ -16,9 +16,9 @@ Abstract: #include "aig.h" #include "dl_rule_set.h" -#include "rel_context.h" #include #include +#include "rel_context.h" namespace datalog { class aig_exporter { diff --git a/src/muz/dl_compiler.cpp b/src/muz/rel/dl_compiler.cpp similarity index 99% rename from src/muz/dl_compiler.cpp rename to src/muz/rel/dl_compiler.cpp index 7a2b47c78..931846c35 100644 --- a/src/muz/dl_compiler.cpp +++ b/src/muz/rel/dl_compiler.cpp @@ -21,6 +21,7 @@ Revision History: #include #include"ref_vector.h" #include"dl_context.h" +#include"rel_context.h" #include"dl_rule.h" #include"dl_util.h" #include"dl_compiler.h" diff --git a/src/muz/dl_compiler.h b/src/muz/rel/dl_compiler.h similarity index 100% rename from src/muz/dl_compiler.h rename to src/muz/rel/dl_compiler.h diff --git a/src/muz/dl_instruction.cpp b/src/muz/rel/dl_instruction.cpp similarity index 98% rename from src/muz/dl_instruction.cpp rename to src/muz/rel/dl_instruction.cpp index 55327f55b..a702c27ce 100644 --- a/src/muz/dl_instruction.cpp +++ b/src/muz/rel/dl_instruction.cpp @@ -22,6 +22,7 @@ Revision History: #include"dl_context.h" #include"dl_util.h" #include"dl_instruction.h" +#include"rel_context.h" #include"debug.h" #include"warning.h" @@ -59,7 +60,7 @@ namespace datalog { } rel_context& execution_context::get_rel_context() { - return *m_context.get_rel_context(); + return dynamic_cast(*m_context.get_rel_context()); } struct compare_size_proc { @@ -140,8 +141,9 @@ namespace datalog { process_costs(); } - void instruction::display_indented(rel_context const & ctx, std::ostream & out, std::string indentation) const { + void instruction::display_indented(rel_context_base const & _ctx, std::ostream & out, std::string indentation) const { out << indentation; + rel_context const& ctx = dynamic_cast(_ctx); display_head_impl(ctx, out); if (ctx.output_profile()) { out << " {"; @@ -313,7 +315,7 @@ namespace datalog { out << "while"; print_container(m_controls, out); } - virtual void display_body_impl(rel_context const & ctx, std::ostream & out, std::string indentation) const { + virtual void display_body_impl(rel_context_base const & ctx, std::ostream & out, std::string indentation) const { m_body->display_indented(ctx, out, indentation+" "); } }; @@ -1102,7 +1104,8 @@ namespace datalog { } } - void instruction_block::display_indented(rel_context const& ctx, std::ostream & out, std::string indentation) const { + void instruction_block::display_indented(rel_context_base const& _ctx, std::ostream & out, std::string indentation) const { + rel_context const& ctx = dynamic_cast(_ctx); instr_seq_type::const_iterator it = m_data.begin(); instr_seq_type::const_iterator end = m_data.end(); for(; it!=end; ++it) { diff --git a/src/muz/dl_instruction.h b/src/muz/rel/dl_instruction.h similarity index 96% rename from src/muz/dl_instruction.h rename to src/muz/rel/dl_instruction.h index 97622c6f3..fa705a172 100644 --- a/src/muz/dl_instruction.h +++ b/src/muz/rel/dl_instruction.h @@ -26,6 +26,7 @@ Revision History: #include "vector.h" #include "dl_base.h" #include "dl_costs.h" +#include "dl_context.h" namespace datalog { @@ -231,10 +232,10 @@ namespace datalog { virtual void make_annotations(execution_context & ctx) = 0; - void display(rel_context const& ctx, std::ostream & out) const { + void display(rel_context_base const& ctx, std::ostream & out) const { display_indented(ctx, out, ""); } - void display_indented(rel_context const & ctx, std::ostream & out, std::string indentation) const; + void display_indented(rel_context_base const & ctx, std::ostream & out, std::string indentation) const; static instruction * mk_load(ast_manager & m, func_decl * pred, reg_idx tgt); /** @@ -335,10 +336,10 @@ namespace datalog { void make_annotations(execution_context & ctx); - void display(rel_context const & ctx, std::ostream & out) const { + void display(rel_context_base const & ctx, std::ostream & out) const { display_indented(ctx, out, ""); } - void display_indented(rel_context const & ctx, std::ostream & out, std::string indentation) const; + void display_indented(rel_context_base const & ctx, std::ostream & out, std::string indentation) const; }; diff --git a/src/muz/rel_context.cpp b/src/muz/rel/rel_context.cpp similarity index 89% rename from src/muz/rel_context.cpp rename to src/muz/rel/rel_context.cpp index 75f68c7f1..c57ef2606 100644 --- a/src/muz/rel_context.cpp +++ b/src/muz/rel/rel_context.cpp @@ -29,12 +29,23 @@ Revision History: #include"dl_product_relation.h" #include"dl_bound_relation.h" #include"dl_interval_relation.h" -#include"dl_mk_karr_invariants.h" +#include"karr_relation.h" #include"dl_finite_product_relation.h" #include"dl_sparse_table.h" #include"dl_table.h" #include"dl_table_relation.h" #include"aig_exporter.h" +#include"dl_mk_simple_joins.h" +#include"dl_mk_similarity_compressor.h" +#include"dl_mk_unbound_compressor.h" +#include"dl_mk_subsumption_checker.h" +#include"dl_mk_partial_equiv.h" +#include"dl_mk_coi_filter.h" +#include"dl_mk_filter_rules.h" +#include"dl_mk_rule_inliner.h" +#include"dl_mk_interp_tail_simplifier.h" +#include"dl_mk_bit_blast.h" + namespace datalog { @@ -75,7 +86,7 @@ namespace datalog { }; rel_context::rel_context(context& ctx) - : engine_base(ctx.get_manager(), "datalog"), + : rel_context_base(ctx.get_manager(), "datalog"), m_context(ctx), m(ctx.get_manager()), m_rmanager(ctx), @@ -127,7 +138,7 @@ namespace datalog { m_code.reset(); termination_code.reset(); m_context.ensure_closed(); - m_context.transform_rules(); + transform_rules(); if (m_context.canceled()) { result = l_undef; break; @@ -252,6 +263,39 @@ namespace datalog { return res; } + void rel_context::transform_rules() { + rule_transformer transf(m_context); + transf.register_plugin(alloc(mk_coi_filter, m_context)); + transf.register_plugin(alloc(mk_filter_rules, m_context)); + transf.register_plugin(alloc(mk_simple_joins, m_context)); + if (m_context.unbound_compressor()) { + transf.register_plugin(alloc(mk_unbound_compressor, m_context)); + } + if (m_context.similarity_compressor()) { + transf.register_plugin(alloc(mk_similarity_compressor, m_context)); + } + transf.register_plugin(alloc(mk_partial_equivalence_transformer, m_context)); + transf.register_plugin(alloc(mk_rule_inliner, m_context)); + transf.register_plugin(alloc(mk_interp_tail_simplifier, m_context)); + + if (m_context.get_params().bit_blast()) { + transf.register_plugin(alloc(mk_bit_blast, m_context, 22000)); + transf.register_plugin(alloc(mk_interp_tail_simplifier, m_context, 21000)); + } + m_context.transform_rules(transf); + } + + bool rel_context::try_get_size(func_decl* p, unsigned& rel_size) const { + relation_base* rb = try_get_relation(p); + if (rb && rb->knows_exact_size()) { + rel_size = rb->get_size_estimate_rows(); + return true; + } + else { + return false; + } + } + lbool rel_context::query(expr* query) { get_rmanager().reset_saturated_marks(); scoped_query _scoped_query(m_context); @@ -372,6 +416,20 @@ namespace datalog { relation_base & rel_context::get_relation(func_decl * pred) { return get_rmanager().get_relation(pred); } relation_base * rel_context::try_get_relation(func_decl * pred) const { return get_rmanager().try_get_relation(pred); } + expr_ref rel_context::try_get_formula(func_decl* p) const { + expr_ref result(m); + relation_base* rb = try_get_relation(p); + if (rb) { + rb->to_formula(result); + } + return result; + } + + bool rel_context::is_empty_relation(func_decl* pred) const { + relation_base* rb = try_get_relation(pred); + return !rb || rb->empty(); + } + relation_manager & rel_context::get_rmanager() { return m_rmanager; } const relation_manager & rel_context::get_rmanager() const { return m_rmanager; } diff --git a/src/muz/rel_context.h b/src/muz/rel/rel_context.h similarity index 55% rename from src/muz/rel_context.h rename to src/muz/rel/rel_context.h index 20da827ce..68a6fbd90 100644 --- a/src/muz/rel_context.h +++ b/src/muz/rel/rel_context.h @@ -23,6 +23,8 @@ Revision History: #include "ast.h" #include "dl_relation_manager.h" #include "dl_instruction.h" +#include "dl_engine_base.h" +#include "dl_context.h" #include "lbool.h" namespace datalog { @@ -30,7 +32,7 @@ namespace datalog { class context; typedef vector > fact_vector; - class rel_context : public engine_base { + class rel_context : public rel_context_base { context& m_context; ast_manager& m; relation_manager m_rmanager; @@ -50,30 +52,33 @@ namespace datalog { lbool saturate(scoped_query& sq); + void set_cancel(bool f); + public: rel_context(context& ctx); - ~rel_context(); + virtual ~rel_context(); - relation_manager & get_rmanager(); - const relation_manager & get_rmanager() const; + virtual relation_manager & get_rmanager(); + virtual const relation_manager & get_rmanager() const; ast_manager& get_manager() const { return m; } context& get_context() const { return m_context; } - relation_base & get_relation(func_decl * pred); - relation_base * try_get_relation(func_decl * pred) const; + virtual relation_base & get_relation(func_decl * pred); + virtual relation_base * try_get_relation(func_decl * pred) const; + virtual bool is_empty_relation(func_decl* pred) const; + virtual expr_ref try_get_formula(func_decl * pred) const; virtual expr_ref get_answer() { return m_answer; } - bool output_profile() const; + virtual bool output_profile() const; virtual lbool query(expr* q); - lbool query(unsigned num_rels, func_decl * const* rels); + virtual lbool query(unsigned num_rels, func_decl * const* rels); - void set_predicate_representation(func_decl * pred, unsigned relation_name_cnt, + virtual void set_predicate_representation(func_decl * pred, unsigned relation_name_cnt, symbol const * relation_names); - void inherit_predicate_kind(func_decl* new_pred, func_decl* orig_pred); + virtual void inherit_predicate_kind(func_decl* new_pred, func_decl* orig_pred); - void set_cancel(bool f); virtual void cancel() { set_cancel(true); } virtual void cleanup() { set_cancel(false);} @@ -83,35 +88,41 @@ namespace datalog { The function deallocates unsused relations, it does not deal with rules. */ - void restrict_predicates(func_decl_set const& predicates); + virtual void restrict_predicates(func_decl_set const& predicates); + virtual void transform_rules(); + virtual bool try_get_size(func_decl* pred, unsigned& rel_size) const; /** \brief query result if it contains fact. */ - bool result_contains_fact(relation_fact const& f); + virtual bool result_contains_fact(relation_fact const& f); + + virtual void collect_non_empty_predicates(func_decl_set& ps) { + return get_rmanager().collect_non_empty_predicates(ps); + } /** \brief add facts to relation */ - void add_fact(func_decl* pred, relation_fact const& fact); - void add_fact(func_decl* pred, table_fact const& fact); + virtual void add_fact(func_decl* pred, relation_fact const& fact); + virtual void add_fact(func_decl* pred, table_fact const& fact); /** \brief check if facts were added to relation */ - bool has_facts(func_decl * pred) const; + virtual bool has_facts(func_decl * pred) const; /** \brief Store the relation \c rel under the predicate \c pred. The \c context object takes over the ownership of the relation object. */ - void store_relation(func_decl * pred, relation_base * rel); + virtual void store_relation(func_decl * pred, relation_base * rel); - void display_output_facts(rule_set const& rules, std::ostream & out) const; - void display_facts(std::ostream & out) const; + virtual void display_output_facts(rule_set const& rules, std::ostream & out) const; + virtual void display_facts(std::ostream & out) const; - void display_profile(std::ostream& out); + virtual void display_profile(std::ostream& out); - lbool saturate(); + virtual lbool saturate(); }; }; diff --git a/src/muz/tab_context.cpp b/src/muz/tab/tab_context.cpp similarity index 100% rename from src/muz/tab_context.cpp rename to src/muz/tab/tab_context.cpp diff --git a/src/muz/tab_context.h b/src/muz/tab/tab_context.h similarity index 96% rename from src/muz/tab_context.h rename to src/muz/tab/tab_context.h index c23ccb7d3..4689598c0 100644 --- a/src/muz/tab_context.h +++ b/src/muz/tab/tab_context.h @@ -22,7 +22,7 @@ Revision History: #include "ast.h" #include "lbool.h" #include "statistics.h" -#include "dl_util.h" +#include "dl_engine_base.h" namespace datalog { class context; diff --git a/src/muz/dl_mk_array_blast.cpp b/src/muz/transforms/dl_mk_array_blast.cpp similarity index 100% rename from src/muz/dl_mk_array_blast.cpp rename to src/muz/transforms/dl_mk_array_blast.cpp diff --git a/src/muz/dl_mk_array_blast.h b/src/muz/transforms/dl_mk_array_blast.h similarity index 100% rename from src/muz/dl_mk_array_blast.h rename to src/muz/transforms/dl_mk_array_blast.h diff --git a/src/muz/dl_mk_backwards.cpp b/src/muz/transforms/dl_mk_backwards.cpp similarity index 100% rename from src/muz/dl_mk_backwards.cpp rename to src/muz/transforms/dl_mk_backwards.cpp diff --git a/src/muz/dl_mk_backwards.h b/src/muz/transforms/dl_mk_backwards.h similarity index 100% rename from src/muz/dl_mk_backwards.h rename to src/muz/transforms/dl_mk_backwards.h diff --git a/src/muz/dl_mk_bit_blast.cpp b/src/muz/transforms/dl_mk_bit_blast.cpp similarity index 100% rename from src/muz/dl_mk_bit_blast.cpp rename to src/muz/transforms/dl_mk_bit_blast.cpp diff --git a/src/muz/dl_mk_bit_blast.h b/src/muz/transforms/dl_mk_bit_blast.h similarity index 100% rename from src/muz/dl_mk_bit_blast.h rename to src/muz/transforms/dl_mk_bit_blast.h diff --git a/src/muz/dl_mk_coalesce.cpp b/src/muz/transforms/dl_mk_coalesce.cpp similarity index 100% rename from src/muz/dl_mk_coalesce.cpp rename to src/muz/transforms/dl_mk_coalesce.cpp diff --git a/src/muz/dl_mk_coalesce.h b/src/muz/transforms/dl_mk_coalesce.h similarity index 100% rename from src/muz/dl_mk_coalesce.h rename to src/muz/transforms/dl_mk_coalesce.h diff --git a/src/muz/dl_mk_coi_filter.cpp b/src/muz/transforms/dl_mk_coi_filter.cpp similarity index 92% rename from src/muz/dl_mk_coi_filter.cpp rename to src/muz/transforms/dl_mk_coi_filter.cpp index a0fc845bf..fc4c411ff 100644 --- a/src/muz/dl_mk_coi_filter.cpp +++ b/src/muz/transforms/dl_mk_coi_filter.cpp @@ -48,7 +48,7 @@ namespace datalog { } rule_set * mk_coi_filter::bottom_up(rule_set const & source) { - decl_set all, reached; + func_decl_set all, reached; ptr_vector todo; rule_set::decl2rules body2rules; // initialization for reachability @@ -117,7 +117,7 @@ namespace datalog { // set to false each unreached predicate if (m_context.get_model_converter()) { extension_model_converter* mc0 = alloc(extension_model_converter, m); - for (decl_set::iterator it = all.begin(); it != all.end(); ++it) { + for (func_decl_set::iterator it = all.begin(); it != all.end(); ++it) { if (!reached.contains(*it)) { mc0->insert(*it, m.mk_false()); } @@ -134,13 +134,13 @@ namespace datalog { rule_set * mk_coi_filter::top_down(rule_set const & source) { - decl_set interesting_preds; - decl_set pruned_preds; + func_decl_set interesting_preds; + func_decl_set pruned_preds; ptr_vector todo; { - const decl_set& output_preds = source.get_output_predicates(); - decl_set::iterator oend = output_preds.end(); - for (decl_set::iterator it = output_preds.begin(); it!=oend; ++it) { + const func_decl_set& output_preds = source.get_output_predicates(); + func_decl_set::iterator oend = output_preds.end(); + for (func_decl_set::iterator it = output_preds.begin(); it!=oend; ++it) { todo.push_back(*it); interesting_preds.insert(*it); } @@ -185,8 +185,8 @@ namespace datalog { } if (res && m_context.get_model_converter()) { - decl_set::iterator end = pruned_preds.end(); - decl_set::iterator it = pruned_preds.begin(); + func_decl_set::iterator end = pruned_preds.end(); + func_decl_set::iterator it = pruned_preds.begin(); extension_model_converter* mc0 = alloc(extension_model_converter, m); for (; it != end; ++it) { mc0->insert(*it, m.mk_true()); diff --git a/src/muz/dl_mk_coi_filter.h b/src/muz/transforms/dl_mk_coi_filter.h similarity index 100% rename from src/muz/dl_mk_coi_filter.h rename to src/muz/transforms/dl_mk_coi_filter.h diff --git a/src/muz/dl_mk_different.h b/src/muz/transforms/dl_mk_different.h similarity index 100% rename from src/muz/dl_mk_different.h rename to src/muz/transforms/dl_mk_different.h diff --git a/src/muz/dl_mk_filter_rules.cpp b/src/muz/transforms/dl_mk_filter_rules.cpp similarity index 100% rename from src/muz/dl_mk_filter_rules.cpp rename to src/muz/transforms/dl_mk_filter_rules.cpp diff --git a/src/muz/dl_mk_filter_rules.h b/src/muz/transforms/dl_mk_filter_rules.h similarity index 100% rename from src/muz/dl_mk_filter_rules.h rename to src/muz/transforms/dl_mk_filter_rules.h diff --git a/src/muz/dl_mk_interp_tail_simplifier.cpp b/src/muz/transforms/dl_mk_interp_tail_simplifier.cpp similarity index 100% rename from src/muz/dl_mk_interp_tail_simplifier.cpp rename to src/muz/transforms/dl_mk_interp_tail_simplifier.cpp diff --git a/src/muz/dl_mk_interp_tail_simplifier.h b/src/muz/transforms/dl_mk_interp_tail_simplifier.h similarity index 100% rename from src/muz/dl_mk_interp_tail_simplifier.h rename to src/muz/transforms/dl_mk_interp_tail_simplifier.h diff --git a/src/muz/transforms/dl_mk_karr_invariants.cpp b/src/muz/transforms/dl_mk_karr_invariants.cpp new file mode 100644 index 000000000..4c0a24b65 --- /dev/null +++ b/src/muz/transforms/dl_mk_karr_invariants.cpp @@ -0,0 +1,325 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + dl_mk_karr_invariants.cpp + +Abstract: + + Extract integer linear invariants. + + The linear invariants are extracted according to Karr's method. + A short description is in + Nikolaj Bjorner, Anca Browne and Zohar Manna. Automatic Generation + of Invariants and Intermediate Assertions, in CP 95. + + The algorithm is here adapted to Horn clauses. + The idea is to maintain two data-structures for each recursive relation. + We call them R and RD + - R - set of linear congruences that are true of R. + - RD - the dual basis of of solutions for R. + + RD is updated by accumulating basis vectors for solutions + to R (the homogeneous dual of R) + R is updated from the inhomogeneous dual of RD. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-03-09 + +Revision History: + +--*/ + +#include"expr_safe_replace.h" +#include"bool_rewriter.h" +#include"for_each_expr.h" + +#include"dl_mk_karr_invariants.h" +#include"dl_mk_backwards.h" +#include"dl_mk_loop_counter.h" + +namespace datalog { + + + mk_karr_invariants::mk_karr_invariants(context & ctx, unsigned priority): + rule_transformer::plugin(priority, false), + m_ctx(ctx), + m(ctx.get_manager()), + rm(ctx.get_rule_manager()), + m_inner_ctx(m, ctx.get_register_engine(), ctx.get_fparams()), + a(m), + m_pinned(m), + m_cancel(false) { + params_ref params; + params.set_sym("default_relation", symbol("karr_relation")); + params.set_sym("engine", symbol("datalog")); + params.set_bool("karr", false); + m_inner_ctx.updt_params(params); + } + + mk_karr_invariants::~mk_karr_invariants() { } + + matrix& matrix::operator=(matrix const& other) { + reset(); + append(other); + return *this; + } + + void matrix::display_row( + std::ostream& out, vector const& row, rational const& b, bool is_eq) { + for (unsigned j = 0; j < row.size(); ++j) { + out << row[j] << " "; + } + out << (is_eq?" = ":" >= ") << -b << "\n"; + } + + void matrix::display_ineq( + std::ostream& out, vector const& row, rational const& b, bool is_eq) { + bool first = true; + for (unsigned j = 0; j < row.size(); ++j) { + if (!row[j].is_zero()) { + if (!first && row[j].is_pos()) { + out << "+ "; + } + if (row[j].is_minus_one()) { + out << "- "; + } + if (row[j] > rational(1) || row[j] < rational(-1)) { + out << row[j] << "*"; + } + out << "x" << j << " "; + first = false; + } + } + out << (is_eq?"= ":">= ") << -b << "\n"; + } + + void matrix::display(std::ostream& out) const { + for (unsigned i = 0; i < A.size(); ++i) { + display_row(out, A[i], b[i], eq[i]); + } + } + + + class mk_karr_invariants::add_invariant_model_converter : public model_converter { + ast_manager& m; + arith_util a; + func_decl_ref_vector m_funcs; + expr_ref_vector m_invs; + public: + + add_invariant_model_converter(ast_manager& m): m(m), a(m), m_funcs(m), m_invs(m) {} + + virtual ~add_invariant_model_converter() { } + + void add(func_decl* p, expr* inv) { + if (!m.is_true(inv)) { + m_funcs.push_back(p); + m_invs.push_back(inv); + } + } + + virtual void operator()(model_ref & mr) { + for (unsigned i = 0; i < m_funcs.size(); ++i) { + func_decl* p = m_funcs[i].get(); + func_interp* f = mr->get_func_interp(p); + expr_ref body(m); + unsigned arity = p->get_arity(); + SASSERT(0 < arity); + if (f) { + SASSERT(f->num_entries() == 0); + if (!f->is_partial()) { + bool_rewriter(m).mk_and(f->get_else(), m_invs[i].get(), body); + } + } + else { + f = alloc(func_interp, m, arity); + mr->register_decl(p, f); + body = m.mk_false(); // fragile: assume that relation was pruned by being infeasible. + } + f->set_else(body); + } + } + + virtual model_converter * translate(ast_translation & translator) { + add_invariant_model_converter* mc = alloc(add_invariant_model_converter, m); + for (unsigned i = 0; i < m_funcs.size(); ++i) { + mc->add(translator(m_funcs[i].get()), m_invs[i].get()); + } + return mc; + } + + private: + void mk_body(matrix const& M, expr_ref& body) { + expr_ref_vector conj(m); + for (unsigned i = 0; i < M.size(); ++i) { + mk_body(M.A[i], M.b[i], M.eq[i], conj); + } + bool_rewriter(m).mk_and(conj.size(), conj.c_ptr(), body); + } + + void mk_body(vector const& row, rational const& b, bool is_eq, expr_ref_vector& conj) { + expr_ref_vector sum(m); + expr_ref zero(m), lhs(m); + zero = a.mk_numeral(rational(0), true); + + for (unsigned i = 0; i < row.size(); ++i) { + if (row[i].is_zero()) { + continue; + } + var* var = m.mk_var(i, a.mk_int()); + if (row[i].is_one()) { + sum.push_back(var); + } + else { + sum.push_back(a.mk_mul(a.mk_numeral(row[i], true), var)); + } + } + if (!b.is_zero()) { + sum.push_back(a.mk_numeral(b, true)); + } + lhs = a.mk_add(sum.size(), sum.c_ptr()); + if (is_eq) { + conj.push_back(m.mk_eq(lhs, zero)); + } + else { + conj.push_back(a.mk_ge(lhs, zero)); + } + } + }; + + void mk_karr_invariants::cancel() { + m_cancel = true; + m_inner_ctx.cancel(); + } + + rule_set * mk_karr_invariants::operator()(rule_set const & source) { + if (!m_ctx.get_params().karr()) { + return 0; + } + rule_set::iterator it = source.begin(), end = source.end(); + for (; it != end; ++it) { + rule const& r = **it; + if (r.has_negation()) { + return 0; + } + } + mk_loop_counter lc(m_ctx); + mk_backwards bwd(m_ctx); + + scoped_ptr src_loop = lc(source); + TRACE("dl", src_loop->display(tout << "source loop\n");); + + get_invariants(*src_loop); + + if (m_cancel) { + return 0; + } + + // figure out whether to update same rules as used for saturation. + scoped_ptr rev_source = bwd(*src_loop); + get_invariants(*rev_source); + scoped_ptr src_annot = update_rules(*src_loop); + rule_set* rules = lc.revert(*src_annot); + rules->inherit_predicates(source); + TRACE("dl", rules->display(tout);); + m_pinned.reset(); + m_fun2inv.reset(); + return rules; + } + + void mk_karr_invariants::get_invariants(rule_set const& src) { + m_inner_ctx.reset(); + rel_context_base& rctx = *m_inner_ctx.get_rel_context(); + ptr_vector heads; + func_decl_set const& predicates = m_ctx.get_predicates(); + for (func_decl_set::iterator fit = predicates.begin(); fit != predicates.end(); ++fit) { + m_inner_ctx.register_predicate(*fit, false); + } + m_inner_ctx.ensure_opened(); + m_inner_ctx.replace_rules(src); + m_inner_ctx.close(); + rule_set::decl2rules::iterator dit = src.begin_grouped_rules(); + rule_set::decl2rules::iterator dend = src.end_grouped_rules(); + for (; dit != dend; ++dit) { + heads.push_back(dit->m_key); + } + m_inner_ctx.rel_query(heads.size(), heads.c_ptr()); + + // retrieve invariants. + dit = src.begin_grouped_rules(); + for (; dit != dend; ++dit) { + func_decl* p = dit->m_key; + expr_ref fml = rctx.try_get_formula(p); + if (fml && !m.is_true(fml)) { + expr* inv = 0; + if (m_fun2inv.find(p, inv)) { + fml = m.mk_and(inv, fml); + } + m_pinned.push_back(fml); + m_fun2inv.insert(p, fml); + } + } + } + + rule_set* mk_karr_invariants::update_rules(rule_set const& src) { + scoped_ptr dst = alloc(rule_set, m_ctx); + rule_set::iterator it = src.begin(), end = src.end(); + for (; it != end; ++it) { + update_body(*dst, **it); + } + if (m_ctx.get_model_converter()) { + add_invariant_model_converter* kmc = alloc(add_invariant_model_converter, m); + rule_set::decl2rules::iterator git = src.begin_grouped_rules(); + rule_set::decl2rules::iterator gend = src.end_grouped_rules(); + for (; git != gend; ++git) { + func_decl* p = git->m_key; + expr* fml = 0; + if (m_fun2inv.find(p, fml)) { + kmc->add(p, fml); + } + } + m_ctx.add_model_converter(kmc); + } + + dst->inherit_predicates(src); + return dst.detach(); + } + + void mk_karr_invariants::update_body(rule_set& rules, rule& r) { + unsigned utsz = r.get_uninterpreted_tail_size(); + unsigned tsz = r.get_tail_size(); + app_ref_vector tail(m); + expr_ref fml(m); + for (unsigned i = 0; i < tsz; ++i) { + tail.push_back(r.get_tail(i)); + } + for (unsigned i = 0; i < utsz; ++i) { + func_decl* q = r.get_decl(i); + expr* fml = 0; + if (m_fun2inv.find(q, fml)) { + expr_safe_replace rep(m); + for (unsigned j = 0; j < q->get_arity(); ++j) { + rep.insert(m.mk_var(j, q->get_domain(j)), + r.get_tail(i)->get_arg(j)); + } + expr_ref tmp(fml, m); + rep(tmp); + tail.push_back(to_app(tmp)); + } + } + rule* new_rule = &r; + if (tail.size() != tsz) { + new_rule = rm.mk(r.get_head(), tail.size(), tail.c_ptr(), 0, r.name()); + } + rules.add_rule(new_rule); + rm.mk_rule_rewrite_proof(r, *new_rule); // should be weakening rule. + } + + + + +}; + diff --git a/src/muz/transforms/dl_mk_karr_invariants.h b/src/muz/transforms/dl_mk_karr_invariants.h new file mode 100644 index 000000000..378a7e587 --- /dev/null +++ b/src/muz/transforms/dl_mk_karr_invariants.h @@ -0,0 +1,81 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + dl_mk_karr_invariants.h + +Abstract: + + Extract integer linear invariants. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-03-08 + +Revision History: + +--*/ +#ifndef _DL_MK_KARR_INVARIANTS_H_ +#define _DL_MK_KARR_INVARIANTS_H_ + +#include"dl_context.h" +#include"dl_rule_set.h" +#include"dl_rule_transformer.h" +#include"arith_decl_plugin.h" +#include"hilbert_basis.h" + +namespace datalog { + + /** + \brief Rule transformer that strengthens bodies with invariants. + */ + + struct matrix { + vector > A; + vector b; + svector eq; + unsigned size() const { return A.size(); } + void reset() { A.reset(); b.reset(); eq.reset(); } + matrix& operator=(matrix const& other); + void append(matrix const& other) { A.append(other.A); b.append(other.b); eq.append(other.eq); } + void display(std::ostream& out) const; + static void display_row( + std::ostream& out, vector const& row, rational const& b, bool is_eq); + static void display_ineq( + std::ostream& out, vector const& row, rational const& b, bool is_eq); + }; + + class mk_karr_invariants : public rule_transformer::plugin { + + class add_invariant_model_converter; + + context& m_ctx; + ast_manager& m; + rule_manager& rm; + context m_inner_ctx; + arith_util a; + obj_map m_fun2inv; + ast_ref_vector m_pinned; + volatile bool m_cancel; + + void get_invariants(rule_set const& src); + + void update_body(rule_set& result, rule& r); + rule_set* update_rules(rule_set const& src); + public: + mk_karr_invariants(context & ctx, unsigned priority); + + virtual ~mk_karr_invariants(); + + virtual void cancel(); + + rule_set * operator()(rule_set const & source); + + }; + + +}; + +#endif /* _DL_MK_KARR_INVARIANTS_H_ */ + diff --git a/src/muz/dl_mk_loop_counter.cpp b/src/muz/transforms/dl_mk_loop_counter.cpp similarity index 100% rename from src/muz/dl_mk_loop_counter.cpp rename to src/muz/transforms/dl_mk_loop_counter.cpp diff --git a/src/muz/dl_mk_loop_counter.h b/src/muz/transforms/dl_mk_loop_counter.h similarity index 100% rename from src/muz/dl_mk_loop_counter.h rename to src/muz/transforms/dl_mk_loop_counter.h diff --git a/src/muz/dl_mk_magic_sets.cpp b/src/muz/transforms/dl_mk_magic_sets.cpp similarity index 99% rename from src/muz/dl_mk_magic_sets.cpp rename to src/muz/transforms/dl_mk_magic_sets.cpp index 24d9d01cb..48bd69255 100644 --- a/src/muz/dl_mk_magic_sets.cpp +++ b/src/muz/transforms/dl_mk_magic_sets.cpp @@ -362,7 +362,7 @@ namespace datalog { rule * r = *it; transform_rule(task.m_adornment, r, *result); } - if (!m_context.get_rel_context()->get_relation(task.m_pred).empty()) { + if (!m_context.get_rel_context()->is_empty_relation(task.m_pred)) { //we need a rule to copy facts that are already in a relation into the adorned //relation (since out intentional predicates can have facts, not only rules) create_transfer_rule(task, *result); diff --git a/src/muz/dl_mk_magic_sets.h b/src/muz/transforms/dl_mk_magic_sets.h similarity index 100% rename from src/muz/dl_mk_magic_sets.h rename to src/muz/transforms/dl_mk_magic_sets.h diff --git a/src/muz/dl_mk_magic_symbolic.cpp b/src/muz/transforms/dl_mk_magic_symbolic.cpp similarity index 100% rename from src/muz/dl_mk_magic_symbolic.cpp rename to src/muz/transforms/dl_mk_magic_symbolic.cpp diff --git a/src/muz/dl_mk_magic_symbolic.h b/src/muz/transforms/dl_mk_magic_symbolic.h similarity index 100% rename from src/muz/dl_mk_magic_symbolic.h rename to src/muz/transforms/dl_mk_magic_symbolic.h diff --git a/src/muz/dl_mk_quantifier_abstraction.cpp b/src/muz/transforms/dl_mk_quantifier_abstraction.cpp similarity index 100% rename from src/muz/dl_mk_quantifier_abstraction.cpp rename to src/muz/transforms/dl_mk_quantifier_abstraction.cpp diff --git a/src/muz/dl_mk_quantifier_abstraction.h b/src/muz/transforms/dl_mk_quantifier_abstraction.h similarity index 100% rename from src/muz/dl_mk_quantifier_abstraction.h rename to src/muz/transforms/dl_mk_quantifier_abstraction.h diff --git a/src/muz/dl_mk_quantifier_instantiation.cpp b/src/muz/transforms/dl_mk_quantifier_instantiation.cpp similarity index 100% rename from src/muz/dl_mk_quantifier_instantiation.cpp rename to src/muz/transforms/dl_mk_quantifier_instantiation.cpp diff --git a/src/muz/dl_mk_quantifier_instantiation.h b/src/muz/transforms/dl_mk_quantifier_instantiation.h similarity index 100% rename from src/muz/dl_mk_quantifier_instantiation.h rename to src/muz/transforms/dl_mk_quantifier_instantiation.h diff --git a/src/muz/dl_mk_rule_inliner.cpp b/src/muz/transforms/dl_mk_rule_inliner.cpp similarity index 99% rename from src/muz/dl_mk_rule_inliner.cpp rename to src/muz/transforms/dl_mk_rule_inliner.cpp index 5e0d6446b..65ce44b8b 100644 --- a/src/muz/dl_mk_rule_inliner.cpp +++ b/src/muz/transforms/dl_mk_rule_inliner.cpp @@ -49,9 +49,6 @@ Subsumption transformation (remove rule): #include #include "ast_pp.h" -#include "dl_finite_product_relation.h" -#include "dl_product_relation.h" -#include "dl_sieve_relation.h" #include "rewriter.h" #include "rewriter_def.h" #include "dl_mk_rule_inliner.h" @@ -206,9 +203,9 @@ namespace datalog { void mk_rule_inliner::count_pred_occurrences(rule_set const & orig) { - rel_context* rel = m_context.get_rel_context(); + rel_context_base* rel = m_context.get_rel_context(); if (rel) { - rel->get_rmanager().collect_non_empty_predicates(m_preds_with_facts); + rel->collect_non_empty_predicates(m_preds_with_facts); } rule_set::iterator rend = orig.end(); diff --git a/src/muz/dl_mk_rule_inliner.h b/src/muz/transforms/dl_mk_rule_inliner.h similarity index 98% rename from src/muz/dl_mk_rule_inliner.h rename to src/muz/transforms/dl_mk_rule_inliner.h index 3a933f990..ed555492a 100644 --- a/src/muz/dl_mk_rule_inliner.h +++ b/src/muz/transforms/dl_mk_rule_inliner.h @@ -106,9 +106,9 @@ namespace datalog { context & m_context; th_rewriter& m_simp; rule_ref_vector m_pinned; - decl_set m_forbidden_preds; - decl_set m_preds_with_facts; - decl_set m_preds_with_neg_occurrence; + func_decl_set m_forbidden_preds; + func_decl_set m_preds_with_facts; + func_decl_set m_preds_with_neg_occurrence; ast_counter m_head_pred_ctr; ast_counter m_head_pred_non_empty_tails_ctr; ast_counter m_tail_pred_ctr; diff --git a/src/muz/dl_mk_scale.cpp b/src/muz/transforms/dl_mk_scale.cpp similarity index 100% rename from src/muz/dl_mk_scale.cpp rename to src/muz/transforms/dl_mk_scale.cpp diff --git a/src/muz/dl_mk_scale.h b/src/muz/transforms/dl_mk_scale.h similarity index 100% rename from src/muz/dl_mk_scale.h rename to src/muz/transforms/dl_mk_scale.h diff --git a/src/muz/dl_mk_slice.cpp b/src/muz/transforms/dl_mk_slice.cpp similarity index 100% rename from src/muz/dl_mk_slice.cpp rename to src/muz/transforms/dl_mk_slice.cpp diff --git a/src/muz/dl_mk_slice.h b/src/muz/transforms/dl_mk_slice.h similarity index 100% rename from src/muz/dl_mk_slice.h rename to src/muz/transforms/dl_mk_slice.h diff --git a/src/muz/dl_mk_subsumption_checker.cpp b/src/muz/transforms/dl_mk_subsumption_checker.cpp similarity index 96% rename from src/muz/dl_mk_subsumption_checker.cpp rename to src/muz/transforms/dl_mk_subsumption_checker.cpp index 0d32a5c3b..9b2c5627b 100644 --- a/src/muz/dl_mk_subsumption_checker.cpp +++ b/src/muz/transforms/dl_mk_subsumption_checker.cpp @@ -24,7 +24,6 @@ Revision History: #include "rewriter.h" #include "rewriter_def.h" #include"dl_mk_subsumption_checker.h" -#include"dl_table_relation.h" namespace datalog { @@ -249,23 +248,21 @@ namespace datalog { } void mk_subsumption_checker::scan_for_relations_total_due_to_facts(rule_set const& source) { - rel_context* rel = m_context.get_rel_context(); + rel_context_base* rel = m_context.get_rel_context(); if (!rel) { return; } relation_manager& rm = rel->get_rmanager(); - decl_set const& candidate_preds = m_context.get_predicates(); + func_decl_set const& candidate_preds = m_context.get_predicates(); - decl_set::iterator end = candidate_preds.end(); - for(decl_set::iterator it = candidate_preds.begin(); it!=end; ++it) { + func_decl_set::iterator end = candidate_preds.end(); + for(func_decl_set::iterator it = candidate_preds.begin(); it!=end; ++it) { func_decl * pred = *it; + unsigned rel_sz; - if (m_total_relations.contains(pred)) { continue; } //already total - - relation_base * rel = rm.try_get_relation(pred); - - if (!rel || !rel->knows_exact_size()) { continue; } + if (m_total_relations.contains(pred)) { continue; } // already total + if (!rel->try_get_size(pred, rel_sz)) { continue; } unsigned arity = pred->get_arity(); if (arity > 30) { continue; } @@ -280,7 +277,6 @@ namespace datalog { { unsigned total_size = 1<get_size_estimate_rows(); obj_hashtable * head_store; if(m_ground_unconditional_rule_heads.find(pred, head_store)) { diff --git a/src/muz/dl_mk_subsumption_checker.h b/src/muz/transforms/dl_mk_subsumption_checker.h similarity index 100% rename from src/muz/dl_mk_subsumption_checker.h rename to src/muz/transforms/dl_mk_subsumption_checker.h diff --git a/src/muz/dl_mk_unbound_compressor.cpp b/src/muz/transforms/dl_mk_unbound_compressor.cpp similarity index 99% rename from src/muz/dl_mk_unbound_compressor.cpp rename to src/muz/transforms/dl_mk_unbound_compressor.cpp index 71d4d5479..68c35e2c9 100644 --- a/src/muz/dl_mk_unbound_compressor.cpp +++ b/src/muz/transforms/dl_mk_unbound_compressor.cpp @@ -334,9 +334,9 @@ namespace datalog { // TODO mc m_modified = false; - rel_context* rel = m_context.get_rel_context(); + rel_context_base* rel = m_context.get_rel_context(); if (rel) { - rel->get_rmanager().collect_non_empty_predicates(m_non_empty_rels); + rel->collect_non_empty_predicates(m_non_empty_rels); } unsigned init_rule_cnt = source.get_num_rules(); SASSERT(m_rules.empty()); diff --git a/src/muz/dl_mk_unbound_compressor.h b/src/muz/transforms/dl_mk_unbound_compressor.h similarity index 98% rename from src/muz/dl_mk_unbound_compressor.h rename to src/muz/transforms/dl_mk_unbound_compressor.h index 4e2ff0b3c..44877e646 100644 --- a/src/muz/dl_mk_unbound_compressor.h +++ b/src/muz/transforms/dl_mk_unbound_compressor.h @@ -62,7 +62,7 @@ namespace datalog { /** Relations that contain facts */ - decl_set m_non_empty_rels; + func_decl_set m_non_empty_rels; ast_counter m_head_occurrence_ctr; diff --git a/src/muz/dl_mk_unfold.cpp b/src/muz/transforms/dl_mk_unfold.cpp similarity index 100% rename from src/muz/dl_mk_unfold.cpp rename to src/muz/transforms/dl_mk_unfold.cpp diff --git a/src/muz/dl_mk_unfold.h b/src/muz/transforms/dl_mk_unfold.h similarity index 100% rename from src/muz/dl_mk_unfold.h rename to src/muz/transforms/dl_mk_unfold.h diff --git a/src/muz/transforms/dl_transforms.cpp b/src/muz/transforms/dl_transforms.cpp new file mode 100644 index 000000000..7c5707ccf --- /dev/null +++ b/src/muz/transforms/dl_transforms.cpp @@ -0,0 +1,81 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + dl_transforms.cpp + +Abstract: + + Default transformations. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-08-28. + +Revision History: + + Extracted from dl_context + +--*/ + +#include"dl_transforms.h" +#include"dl_rule_transformer.h" +#include"dl_mk_coi_filter.h" +#include"dl_mk_filter_rules.h" +#include"dl_mk_interp_tail_simplifier.h" +#include"dl_mk_rule_inliner.h" +#include"dl_mk_bit_blast.h" +#include"dl_mk_array_blast.h" +#include"dl_mk_karr_invariants.h" +#include"dl_mk_magic_symbolic.h" +#include"dl_mk_quantifier_abstraction.h" +#include"dl_mk_quantifier_instantiation.h" +#include"dl_mk_subsumption_checker.h" +#include"dl_mk_scale.h" + +namespace datalog { + + void apply_default_transformation(context& ctx) { + rule_transformer transf(ctx); + ctx.ensure_closed(); + transf.reset(); + transf.register_plugin(alloc(datalog::mk_coi_filter, ctx)); + transf.register_plugin(alloc(datalog::mk_interp_tail_simplifier, ctx)); + + transf.register_plugin(alloc(datalog::mk_subsumption_checker, ctx, 35005)); + transf.register_plugin(alloc(datalog::mk_rule_inliner, ctx, 35000)); + transf.register_plugin(alloc(datalog::mk_coi_filter, ctx, 34990)); + transf.register_plugin(alloc(datalog::mk_interp_tail_simplifier, ctx, 34980)); + + //and another round of inlining + transf.register_plugin(alloc(datalog::mk_subsumption_checker, ctx, 34975)); + transf.register_plugin(alloc(datalog::mk_rule_inliner, ctx, 34970)); + transf.register_plugin(alloc(datalog::mk_coi_filter, ctx, 34960)); + transf.register_plugin(alloc(datalog::mk_interp_tail_simplifier, ctx, 34950)); + + transf.register_plugin(alloc(datalog::mk_subsumption_checker, ctx, 34940)); + transf.register_plugin(alloc(datalog::mk_rule_inliner, ctx, 34930)); + transf.register_plugin(alloc(datalog::mk_subsumption_checker, ctx, 34920)); + transf.register_plugin(alloc(datalog::mk_rule_inliner, ctx, 34910)); + transf.register_plugin(alloc(datalog::mk_subsumption_checker, ctx, 34900)); + transf.register_plugin(alloc(datalog::mk_rule_inliner, ctx, 34890)); + transf.register_plugin(alloc(datalog::mk_subsumption_checker, ctx, 34880)); + + + if (ctx.get_params().quantify_arrays()) { + transf.register_plugin(alloc(datalog::mk_quantifier_abstraction, ctx, 33000)); + transf.register_plugin(alloc(datalog::mk_array_blast, ctx, 32500)); + } + transf.register_plugin(alloc(datalog::mk_quantifier_instantiation, ctx, 32000)); + + transf.register_plugin(alloc(datalog::mk_bit_blast, ctx, 35000)); + transf.register_plugin(alloc(datalog::mk_array_blast, ctx, 36000)); + transf.register_plugin(alloc(datalog::mk_karr_invariants, ctx, 36010)); + if (ctx.get_params().magic()) { + transf.register_plugin(alloc(datalog::mk_magic_symbolic, ctx, 36020)); + } + transf.register_plugin(alloc(datalog::mk_scale, ctx, 36030)); + ctx.transform_rules(transf); + } +} diff --git a/src/muz/transforms/dl_transforms.h b/src/muz/transforms/dl_transforms.h new file mode 100644 index 000000000..4f9a92dd8 --- /dev/null +++ b/src/muz/transforms/dl_transforms.h @@ -0,0 +1,30 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + dl_transforms.h + +Abstract: + + Default transformations. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-08-28. + +Revision History: + + Extracted from dl_context + +--*/ +#ifndef _DL_TRANSFORMS_H_ +#define _DL_TRANSFORMS_H_ + +#include "dl_context.h" + +namespace datalog { + void apply_default_transformation(context& ctx); +} + +#endif diff --git a/src/shell/datalog_frontend.cpp b/src/shell/datalog_frontend.cpp index 56f60bfa0..15681ea36 100644 --- a/src/shell/datalog_frontend.cpp +++ b/src/shell/datalog_frontend.cpp @@ -31,6 +31,8 @@ Revision History: #include"dl_mk_filter_rules.h" #include"dl_finite_product_relation.h" #include"dl_context.h" +#include"rel_context.h" +#include"dl_register_engine.h" #include"datalog_parser.h" #include"datalog_frontend.h" #include"timeout.h" @@ -118,13 +120,14 @@ unsigned read_datalog(char const * file) { IF_VERBOSE(1, verbose_stream() << "Z3 Datalog Engine\n";); smt_params s_params; ast_manager m; + datalog::register_engine re; g_overall_time.start(); register_on_timeout_proc(on_timeout); signal(SIGINT, on_ctrl_c); params_ref params; params.set_sym("engine", symbol("datalog")); - datalog::context ctx(m, s_params, params); + datalog::context ctx(m, re, s_params, params); datalog::relation_manager & rmgr = ctx.get_rel_context()->get_rmanager(); datalog::relation_plugin & inner_plg = *rmgr.get_relation_plugin(symbol("tr_hashtable")); SASSERT(&inner_plg); @@ -179,11 +182,11 @@ unsigned read_datalog(char const * file) { bool early_termination; unsigned timeout = ctx.initial_restart_timeout(); - if(timeout == 0) { + if (timeout == 0) { timeout = UINT_MAX; } do { - ctx.transform_rules(); + ctx.get_rel_context()->transform_rules(); datalog::compiler::compile(ctx, ctx.get_rules(), rules_code, termination_code); diff --git a/src/test/datalog_parser.cpp b/src/test/datalog_parser.cpp index 64ee4201e..e23650e3b 100644 --- a/src/test/datalog_parser.cpp +++ b/src/test/datalog_parser.cpp @@ -2,6 +2,7 @@ #include "ast_pp.h" #include "arith_decl_plugin.h" #include "dl_context.h" +#include "dl_register_engine.h" #include "smt_params.h" #include "reg_decl_plugins.h" @@ -12,8 +13,8 @@ static void dparse_string(char const* str) { ast_manager m; smt_params params; reg_decl_plugins(m); - - context ctx(m, params); + register_engine re; + context ctx(m, re, params); parser* p = parser::create(ctx,m); bool res=p->parse_string(str); @@ -39,8 +40,9 @@ static void dparse_file(char const* file) { ast_manager m; smt_params params; reg_decl_plugins(m); + register_engine re; - context ctx(m, params); + context ctx(m, re, params); parser* p = parser::create(ctx,m); if (!p->parse_file(file)) { diff --git a/src/test/dl_context.cpp b/src/test/dl_context.cpp index 9e8a37974..5c70aa8b5 100644 --- a/src/test/dl_context.cpp +++ b/src/test/dl_context.cpp @@ -3,6 +3,7 @@ #include "arith_decl_plugin.h" #include "dl_context.h" #include "smt_params.h" +#include "dl_register_engine.h" using namespace datalog; @@ -26,9 +27,9 @@ static lbool dl_context_eval_unary_predicate(ast_manager & m, context & ctx, cha static void dl_context_simple_query_test(params_ref & params) { ast_manager m; dl_decl_util decl_util(m); - + register_engine re; smt_params fparams; - context ctx(m, fparams); + context ctx(m, re, fparams); ctx.updt_params(params); /* lbool status = */ dl_context_eval_unary_predicate(m, ctx, "Z 64\n\nP(x:Z)\nP(\"a\").", "P"); @@ -50,7 +51,8 @@ void dl_context_saturate_file(params_ref & params, const char * f) { ast_manager m; dl_decl_util decl_util(m); smt_params fparams; - context ctx(m, fparams); + register_engine re; + context ctx(m, re, fparams); ctx.updt_params(params); datalog::parser * parser = datalog::parser::create(ctx, m); diff --git a/src/test/dl_product_relation.cpp b/src/test/dl_product_relation.cpp index d58603be1..357ccd604 100644 --- a/src/test/dl_product_relation.cpp +++ b/src/test/dl_product_relation.cpp @@ -1,7 +1,9 @@ #ifdef _WINDOWS #include "dl_context.h" +#include "dl_register_engine.h" #include "dl_finite_product_relation.h" #include "dl_sparse_table.h" +#include "rel_context.h" namespace datalog { @@ -21,8 +23,9 @@ namespace datalog { void test_functional_columns(smt_params fparams, params_ref& params) { ast_manager m; - context ctx(m, fparams); - rel_context& rctx = *ctx.get_rel_context(); + register_engine re; + context ctx(m, re, fparams); + rel_context_base& rctx = *ctx.get_rel_context(); ctx.updt_params(params); relation_manager & rmgr(rctx.get_rmanager()); @@ -124,7 +127,8 @@ namespace datalog { void test_finite_product_relation(smt_params fparams, params_ref& params) { ast_manager m; - context ctx(m, fparams); + register_engine re; + context ctx(m, re, fparams); ctx.updt_params(params); dl_decl_util dl_util(m); relation_manager & rmgr = ctx.get_rel_context()->get_rmanager(); diff --git a/src/test/dl_query.cpp b/src/test/dl_query.cpp index 17781d7bb..bb991c65f 100644 --- a/src/test/dl_query.cpp +++ b/src/test/dl_query.cpp @@ -2,9 +2,11 @@ #include "ast_pp.h" #include "dl_table_relation.h" #include "dl_context.h" +#include "dl_register_engine.h" #include "smt_params.h" #include "stopwatch.h" #include "reg_decl_plugins.h" +#include "dl_relation_manager.h" using namespace datalog; @@ -50,7 +52,8 @@ void dl_query_test(ast_manager & m, smt_params & fparams, params_ref& params, dl_decl_util decl_util(m); random_gen ran(0); - context ctx_q(m, fparams); + register_engine re; + context ctx_q(m, re, fparams); params.set_bool("magic_sets_for_queries", use_magic_sets); ctx_q.updt_params(params); { @@ -135,7 +138,8 @@ void dl_query_test_wpa(smt_params & fparams, params_ref& params) { dl_decl_util dl_util(m); std::cerr << "Testing queries on " << problem_dir <<"\n"; - context ctx(m, fparams); + register_engine re; + context ctx(m, re, fparams); ctx.updt_params(params); { wpa_parser* p = wpa_parser::create(ctx, m); @@ -204,7 +208,8 @@ void tst_dl_query() { std::cerr << "Testing queries on " << problem_file <<"\n"; - context ctx_base(m, fparams); + register_engine re; + context ctx_base(m, re, fparams); ctx_base.updt_params(params); { parser* p = parser::create(ctx_base,m); diff --git a/src/test/dl_relation.cpp b/src/test/dl_relation.cpp index 609dca3da..bb1c8614c 100644 --- a/src/test/dl_relation.cpp +++ b/src/test/dl_relation.cpp @@ -1,5 +1,7 @@ #ifdef _WINDOWS #include "dl_context.h" +#include "dl_register_engine.h" +#include "dl_relation_manager.h" #include "dl_interval_relation.h" #include "dl_bound_relation.h" #include "dl_product_relation.h" @@ -10,7 +12,8 @@ namespace datalog { static void test_interval_relation() { smt_params params; ast_manager ast_m; - context ctx(ast_m, params); + register_engine re; + context ctx(ast_m, re, params); arith_util autil(ast_m); relation_manager & m = ctx.get_rel_context()->get_rmanager(); m.register_plugin(alloc(interval_relation_plugin, m)); @@ -113,7 +116,8 @@ namespace datalog { smt_params params; ast_manager ast_m; - context ctx(ast_m, params); + register_engine re; + context ctx(ast_m, re, params); arith_util autil(ast_m); relation_manager & m = ctx.get_rel_context()->get_rmanager(); m.register_plugin(alloc(bound_relation_plugin, m)); diff --git a/src/test/dl_table.cpp b/src/test/dl_table.cpp index d7025ed48..d24200f9b 100644 --- a/src/test/dl_table.cpp +++ b/src/test/dl_table.cpp @@ -1,6 +1,8 @@ #ifdef _WINDOWS #include "dl_context.h" #include "dl_table.h" +#include "dl_register_engine.h" +#include "dl_relation_manager.h" typedef datalog::table_base* (*mk_table_fn)(datalog::relation_manager& m, datalog::table_signature& sig); @@ -18,7 +20,8 @@ static void test_table(mk_table_fn mk_table) { sig.push_back(4); smt_params params; ast_manager ast_m; - datalog::context ctx(ast_m, params); + datalog::register_engine re; + datalog::context ctx(ast_m, re, params); datalog::relation_manager & m = ctx.get_rel_context()->get_rmanager(); m.register_plugin(alloc(datalog::bitvector_table_plugin, m));