summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaulMeng <pmtruth@hotmail.com>2016-07-05 13:56:53 -0400
committerPaulMeng <pmtruth@hotmail.com>2016-07-05 13:56:53 -0400
commit36a0d1d948f201471596e092136c5a00103f78af (patch)
tree7a9b0d79074da1cb0c1cbed986584d50792a30e9
parent66525e81928d0d025dbcc197ab3ef772eac31103 (diff)
parenta58abbe71fb1fc07129ff9c7568ac544145fb57c (diff)
Merge branch 'master' of https://github.com/CVC4/CVC4.git
Conflicts: proofs/signatures/Makefile.am src/Makefile.am src/expr/datatype.cpp src/options/datatypes_options src/options/options_template.cpp src/options/quantifiers_options src/proof/arith_proof.cpp src/proof/arith_proof.h src/proof/array_proof.cpp src/proof/array_proof.h src/proof/bitvector_proof.cpp src/proof/bitvector_proof.h src/proof/cnf_proof.cpp src/proof/cnf_proof.h src/proof/proof_manager.cpp src/proof/proof_manager.h src/proof/sat_proof.h src/proof/sat_proof_implementation.h src/proof/skolemization_manager.h src/proof/theory_proof.cpp src/proof/theory_proof.h src/proof/uf_proof.cpp src/proof/uf_proof.h src/prop/cnf_stream.cpp src/prop/cnf_stream.h src/prop/minisat/core/Solver.cc src/prop/prop_engine.cpp src/prop/prop_engine.h src/prop/theory_proxy.cpp src/smt/smt_engine.cpp src/smt/smt_engine_check_proof.cpp src/theory/arrays/array_proof_reconstruction.cpp src/theory/arrays/theory_arrays.cpp src/theory/bv/eager_bitblaster.cpp src/theory/bv/lazy_bitblaster.cpp src/theory/datatypes/theory_datatypes.cpp src/theory/quantifiers/alpha_equivalence.cpp src/theory/quantifiers/candidate_generator.cpp src/theory/quantifiers/candidate_generator.h src/theory/quantifiers/ce_guided_single_inv.cpp src/theory/quantifiers/ceg_instantiator.cpp src/theory/quantifiers/conjecture_generator.cpp src/theory/quantifiers/equality_infer.cpp src/theory/quantifiers/equality_infer.h src/theory/quantifiers/inst_match_generator.cpp src/theory/quantifiers/inst_propagator.cpp src/theory/quantifiers/inst_propagator.h src/theory/quantifiers/inst_strategy_e_matching.cpp src/theory/quantifiers/inst_strategy_e_matching.h src/theory/quantifiers/instantiation_engine.cpp src/theory/quantifiers/model_builder.cpp src/theory/quantifiers/model_engine.cpp src/theory/quantifiers/quant_conflict_find.cpp src/theory/quantifiers/quant_conflict_find.h src/theory/quantifiers/quant_split.cpp src/theory/quantifiers/quant_util.cpp src/theory/quantifiers/quantifiers_rewriter.cpp src/theory/quantifiers/quantifiers_rewriter.h src/theory/quantifiers/term_database.cpp src/theory/quantifiers/term_database.h src/theory/quantifiers/trigger.cpp src/theory/quantifiers/trigger.h src/theory/quantifiers_engine.cpp src/theory/quantifiers_engine.h src/theory/sets/kinds src/theory/sets/theory_sets_private.cpp src/theory/sets/theory_sets_private.h src/theory/sets/theory_sets_rewriter.cpp src/theory/sets/theory_sets_type_rules.h src/theory/strings/theory_strings.cpp src/theory/strings/theory_strings.h src/theory/theory_engine.cpp src/theory/theory_engine.h src/theory/uf/equality_engine.cpp test/regress/regress0/fmf/Makefile.am test/regress/regress0/quantifiers/Makefile.am test/regress/regress0/strings/Makefile.am test/regress/regress0/sygus/Makefile.am test/regress/regress0/sygus/max2-univ.sy
-rw-r--r--AUTHORS22
-rw-r--r--COPYING6
-rw-r--r--NEWS2
-rw-r--r--config/cryptominisat.m487
-rw-r--r--configure.ac23
-rw-r--r--contrib/cryptominisat-4.2.0.patch12
-rw-r--r--contrib/cryptominisat-4.2.0.second.patch11
-rwxr-xr-xcontrib/get-cryptominisat457
-rw-r--r--contrib/lfsc_lsan.supp8
-rw-r--r--contrib/run-script-cascj8-fnt37
-rw-r--r--contrib/run-script-cascj8-fof48
-rw-r--r--contrib/run-script-cascj8-tfa40
-rw-r--r--contrib/run-script-cascj8-tfn37
-rw-r--r--contrib/run-script-smtcomp2016134
-rw-r--r--contrib/run-script-smtcomp2016-application51
-rw-r--r--contrib/run-script-sygusComp2016-CLIA16
-rwxr-xr-xcontrib/run-script-sygusComp2016-GENERAL33
-rw-r--r--contrib/run-script-sygusComp2016-INV16
-rw-r--r--contrib/run-script-sygusComp2016-PBE16
-rw-r--r--proofs/lfsc_checker/check.cpp2
-rw-r--r--proofs/lfsc_checker/expr.cpp2
-rw-r--r--proofs/lfsc_checker/expr.h45
-rw-r--r--proofs/lfsc_checker/main.cpp1
-rw-r--r--proofs/lfsc_checker/scccode.cpp602
-rw-r--r--proofs/lfsc_checker/scccode.h16
-rw-r--r--proofs/lfsc_checker/sccwriter.cpp6
-rw-r--r--proofs/signatures/Makefile.am3
-rwxr-xr-xproofs/signatures/th_arrays.plf2
-rw-r--r--proofs/signatures/th_bv.plf46
-rw-r--r--proofs/signatures/th_bv_bitblast.plf220
-rw-r--r--proofs/signatures/th_bv_rewrites.plf22
-rwxr-xr-xproofs/signatures/th_quant.plf5
-rw-r--r--src/Makefile.am20
-rw-r--r--src/Makefile.theories2
-rw-r--r--src/base/configuration.cpp4
-rw-r--r--src/base/configuration.h2
-rw-r--r--src/base/configuration_private.h6
-rw-r--r--src/context/cdhashmap.h20
-rw-r--r--src/expr/Makefile.am2
-rw-r--r--src/expr/datatype.cpp18
-rw-r--r--src/expr/datatype.h7
-rw-r--r--src/expr/expr_manager_template.cpp7
-rw-r--r--src/expr/expr_manager_template.h8
-rw-r--r--src/expr/node_manager.cpp14
-rw-r--r--src/expr/node_manager.h6
-rw-r--r--src/expr/sepconst.cpp29
-rw-r--r--src/expr/sepconst.h72
-rw-r--r--src/expr/type_node.cpp21
-rw-r--r--src/expr/type_node.h7
-rw-r--r--src/main/interactive_shell.cpp1
-rw-r--r--src/main/portfolio_util.cpp6
-rw-r--r--src/options/Makefile.am15
-rw-r--r--src/options/bv_bitblast_mode.cpp15
-rw-r--r--src/options/bv_bitblast_mode.h7
-rw-r--r--src/options/bv_options3
-rw-r--r--src/options/datatypes_options2
-rw-r--r--src/options/options_handler.cpp140
-rw-r--r--src/options/options_handler.h8
-rw-r--r--src/options/options_template.cpp6
-rw-r--r--src/options/proof_options3
-rw-r--r--src/options/quantifiers_modes.cpp11
-rw-r--r--src/options/quantifiers_modes.h23
-rw-r--r--src/options/quantifiers_options29
-rw-r--r--src/options/sep_options20
-rw-r--r--src/parser/cvc/Cvc.g5
-rw-r--r--src/parser/smt2/Smt2.g26
-rw-r--r--src/parser/smt2/smt2.cpp24
-rw-r--r--src/parser/smt2/smt2.h4
-rw-r--r--src/printer/smt2/smt2_printer.cpp74
-rw-r--r--src/proof/arith_proof.cpp16
-rw-r--r--src/proof/arith_proof.h9
-rw-r--r--src/proof/array_proof.cpp192
-rw-r--r--src/proof/array_proof.h42
-rw-r--r--src/proof/bitvector_proof.cpp568
-rw-r--r--src/proof/bitvector_proof.h42
-rw-r--r--src/proof/cnf_proof.cpp137
-rw-r--r--src/proof/cnf_proof.h43
-rw-r--r--src/proof/lemma_proof.cpp193
-rw-r--r--src/proof/lemma_proof.h79
-rw-r--r--src/proof/proof_manager.cpp209
-rw-r--r--src/proof/proof_manager.h48
-rw-r--r--src/proof/proof_output_channel.cpp82
-rw-r--r--src/proof/proof_output_channel.h50
-rw-r--r--src/proof/proof_utils.cpp52
-rw-r--r--src/proof/proof_utils.h105
-rw-r--r--src/proof/sat_proof.h410
-rw-r--r--src/proof/sat_proof_implementation.h635
-rw-r--r--src/proof/skolemization_manager.h1
-rw-r--r--src/proof/theory_proof.cpp748
-rw-r--r--src/proof/theory_proof.h157
-rw-r--r--src/proof/uf_proof.cpp119
-rw-r--r--src/proof/uf_proof.h10
-rw-r--r--src/prop/bvminisat/bvminisat.h4
-rw-r--r--src/prop/cnf_stream.cpp23
-rw-r--r--src/prop/cnf_stream.h21
-rw-r--r--src/prop/cryptominisat.cpp230
-rw-r--r--src/prop/cryptominisat.h138
-rw-r--r--src/prop/minisat/core/Solver.cc32
-rw-r--r--src/prop/minisat/minisat.cpp16
-rw-r--r--src/prop/minisat/minisat.h3
-rw-r--r--src/prop/prop_engine.cpp4
-rw-r--r--src/prop/prop_engine.h3
-rw-r--r--src/prop/sat_solver.h9
-rw-r--r--src/prop/sat_solver_factory.cpp7
-rw-r--r--src/prop/sat_solver_factory.h2
-rw-r--r--src/prop/theory_proxy.cpp33
-rw-r--r--src/smt/boolean_terms.cpp34
-rw-r--r--src/smt/smt_engine.cpp229
-rw-r--r--src/smt/smt_engine_check_proof.cpp23
-rw-r--r--src/smt/smt_engine_scope.h1
-rw-r--r--src/theory/arrays/array_proof_reconstruction.cpp51
-rw-r--r--src/theory/arrays/theory_arrays.cpp5
-rw-r--r--src/theory/bv/abstraction.cpp352
-rw-r--r--src/theory/bv/abstraction.h90
-rw-r--r--src/theory/bv/aig_bitblaster.cpp26
-rw-r--r--src/theory/bv/bitblaster_template.h8
-rw-r--r--src/theory/bv/bv_subtheory_algebraic.cpp3
-rw-r--r--src/theory/bv/bv_subtheory_bitblast.cpp37
-rw-r--r--src/theory/bv/bv_subtheory_bitblast.h6
-rw-r--r--src/theory/bv/eager_bitblaster.cpp25
-rw-r--r--src/theory/bv/lazy_bitblaster.cpp2
-rw-r--r--src/theory/bv/theory_bv.cpp184
-rw-r--r--src/theory/bv/theory_bv.h47
-rw-r--r--src/theory/bv/theory_bv_rewrite_rules_operator_elimination.h4
-rw-r--r--src/theory/datatypes/datatypes_sygus.cpp283
-rw-r--r--src/theory/datatypes/kinds2
-rw-r--r--src/theory/datatypes/theory_datatypes.cpp337
-rw-r--r--src/theory/datatypes/theory_datatypes.h20
-rw-r--r--src/theory/datatypes/theory_datatypes_type_rules.h3
-rw-r--r--src/theory/datatypes/type_enumerator.cpp2
-rw-r--r--src/theory/datatypes/type_enumerator.h2
-rw-r--r--src/theory/logic_info.cpp11
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/alpha_equivalence.cpp25
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/alpha_equivalence.h0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/ambqi_builder.cpp2
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/ambqi_builder.h0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/anti_skolem.cpp0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/anti_skolem.h0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/bounded_integers.cpp365
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/bounded_integers.h61
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/candidate_generator.cpp10
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/candidate_generator.h16
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/ce_guided_instantiation.cpp182
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/ce_guided_instantiation.h5
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/ce_guided_single_inv.cpp305
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/ce_guided_single_inv.h0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/ce_guided_single_inv_ei.cpp0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/ce_guided_single_inv_ei.h0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/ce_guided_single_inv_sol.cpp0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/ce_guided_single_inv_sol.h0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/ceg_instantiator.cpp48
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/ceg_instantiator.h0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/conjecture_generator.cpp13
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/conjecture_generator.h0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/equality_infer.cpp49
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/equality_infer.h8
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/first_order_model.cpp4
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/first_order_model.h0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/full_model_check.cpp15
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/full_model_check.h0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/fun_def_engine.cpp0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/fun_def_engine.h0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/fun_def_process.cpp0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/fun_def_process.h0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/inst_match.cpp0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/inst_match.h0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/inst_match_generator.cpp43
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/inst_match_generator.h12
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/inst_propagator.cpp476
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/inst_propagator.h28
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/inst_strategy_cbqi.cpp10
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/inst_strategy_cbqi.h0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/inst_strategy_e_matching.cpp145
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/inst_strategy_e_matching.h8
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/instantiation_engine.cpp6
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/instantiation_engine.h0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/kinds0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/local_theory_ext.cpp0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/local_theory_ext.h0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/macros.cpp0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/macros.h0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/model_builder.cpp43
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/model_builder.h11
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/model_engine.cpp56
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/model_engine.h0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/quant_conflict_find.cpp592
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/quant_conflict_find.h26
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/quant_equality_engine.cpp0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/quant_equality_engine.h0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/quant_split.cpp6
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/quant_split.h0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/quant_util.cpp15
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/quant_util.h0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/quantifiers_attributes.cpp0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/quantifiers_attributes.h0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/quantifiers_rewriter.cpp518
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/quantifiers_rewriter.h9
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/relevant_domain.cpp2
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/relevant_domain.h0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/rewrite_engine.cpp2
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/rewrite_engine.h0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/symmetry_breaking.cpp0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/symmetry_breaking.h2
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/term_database.cpp455
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/term_database.h54
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/theory_quantifiers.cpp7
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/theory_quantifiers.h0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/theory_quantifiers_type_rules.h0
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/trigger.cpp169
-rwxr-xr-x[-rw-r--r--]src/theory/quantifiers/trigger.h19
-rw-r--r--src/theory/quantifiers_engine.cpp107
-rw-r--r--src/theory/quantifiers_engine.h8
-rw-r--r--src/theory/rep_set.cpp283
-rw-r--r--src/theory/rep_set.h55
-rw-r--r--src/theory/sep/kinds37
-rw-r--r--src/theory/sep/theory_sep.cpp1534
-rw-r--r--src/theory/sep/theory_sep.h294
-rw-r--r--src/theory/sep/theory_sep_rewriter.cpp184
-rw-r--r--src/theory/sep/theory_sep_rewriter.h53
-rw-r--r--src/theory/sep/theory_sep_type_rules.h114
-rw-r--r--src/theory/sets/kinds1
-rw-r--r--src/theory/sets/theory_sets_private.h14
-rw-r--r--src/theory/sets/theory_sets_type_rules.h1
-rw-r--r--src/theory/strings/regexp_operation.cpp4
-rw-r--r--src/theory/strings/regexp_operation.h1
-rw-r--r--src/theory/strings/theory_strings.cpp511
-rw-r--r--src/theory/strings/theory_strings.h23
-rw-r--r--src/theory/strings/theory_strings_preprocess.cpp4
-rw-r--r--src/theory/strings/theory_strings_preprocess.h1
-rw-r--r--src/theory/term_registration_visitor.cpp56
-rw-r--r--src/theory/theory.h8
-rw-r--r--src/theory/theory_engine.cpp372
-rw-r--r--src/theory/theory_engine.h46
-rw-r--r--src/theory/theory_model.cpp3
-rw-r--r--src/theory/theory_model.h4
-rw-r--r--src/theory/type_enumerator.h2
-rw-r--r--src/theory/uf/equality_engine.cpp26
-rw-r--r--src/theory/uf/equality_engine.h8
-rw-r--r--src/theory/uf/theory_uf.cpp167
-rw-r--r--src/theory/uf/theory_uf.h7
-rw-r--r--src/theory/uf/theory_uf_strong_solver.cpp6
-rw-r--r--src/theory/uf/theory_uf_strong_solver.h2
-rw-r--r--src/theory/valuation.cpp4
-rw-r--r--src/theory/valuation.h6
-rw-r--r--src/util/bitvector.h17
-rw-r--r--src/util/proof.h8
-rw-r--r--test/Makefile.am1
-rw-r--r--test/regress/regress0/Makefile.am2
-rw-r--r--test/regress/regress0/aufbv/Makefile.am1
-rw-r--r--test/regress/regress0/fmf/Makefile.am4
-rw-r--r--test/regress/regress0/fmf/bound-int-alt.smt218
-rw-r--r--test/regress/regress0/fmf/sc-crash-052316.smt235
-rw-r--r--test/regress/regress0/quantifiers/Makefile.am6
-rw-r--r--test/regress/regress0/quantifiers/inst-max-level-segf.smt2326
-rw-r--r--test/regress/regress0/quantifiers/partial-trigger.smt210
-rw-r--r--test/regress/regress0/quantifiers/small-bug1-fixpoint-3.smt215
-rw-r--r--test/regress/regress0/quantifiers/z3.620661-no-fv-trigger.smt287
-rw-r--r--test/regress/regress0/sep/Makefile.am76
-rw-r--r--test/regress/regress0/sep/chain-int.smt211
-rwxr-xr-xtest/regress/regress0/sep/crash1220.smt215
-rw-r--r--test/regress/regress0/sep/dispose-list-4-init.smt236
-rw-r--r--test/regress/regress0/sep/fmf-nemp-2.smt210
-rw-r--r--test/regress/regress0/sep/loop-1220.smt219
-rw-r--r--test/regress/regress0/sep/nemp.smt25
-rwxr-xr-xtest/regress/regress0/sep/nspatial-simp.smt211
-rw-r--r--test/regress/regress0/sep/pto-01.smt213
-rw-r--r--test/regress/regress0/sep/pto-02.smt225
-rw-r--r--test/regress/regress0/sep/pto-04.smt236
-rw-r--r--test/regress/regress0/sep/quant_wand.smt215
-rw-r--r--test/regress/regress0/sep/sep-01.smt214
-rw-r--r--test/regress/regress0/sep/sep-02.smt216
-rw-r--r--test/regress/regress0/sep/sep-03.smt217
-rw-r--r--test/regress/regress0/sep/sep-find2.smt222
-rw-r--r--test/regress/regress0/sep/sep-neg-1refine.smt217
-rw-r--r--test/regress/regress0/sep/sep-neg-nstrict.smt215
-rw-r--r--test/regress/regress0/sep/sep-neg-nstrict2.smt218
-rw-r--r--test/regress/regress0/sep/sep-neg-simple.smt216
-rw-r--r--test/regress/regress0/sep/sep-neg-swap.smt217
-rw-r--r--test/regress/regress0/sep/sep-nterm-again.smt220
-rw-r--r--test/regress/regress0/sep/sep-nterm-val-model.smt217
-rw-r--r--test/regress/regress0/sep/sep-plus1.smt218
-rwxr-xr-xtest/regress/regress0/sep/sep-simp-unc.smt212
-rw-r--r--test/regress/regress0/sep/sep-simp-unsat-emp.smt212
-rw-r--r--test/regress/regress0/sep/simple-neg-sat.smt220
-rw-r--r--test/regress/regress0/sep/split-find-unsat-w-emp.smt218
-rw-r--r--test/regress/regress0/sep/split-find-unsat.smt220
-rw-r--r--test/regress/regress0/sep/wand-0526-sat.smt210
-rw-r--r--test/regress/regress0/sep/wand-crash.smt25
-rw-r--r--test/regress/regress0/sep/wand-nterm-simp.smt27
-rw-r--r--test/regress/regress0/sep/wand-nterm-simp2.smt26
-rwxr-xr-xtest/regress/regress0/sep/wand-simp-sat.smt26
-rwxr-xr-xtest/regress/regress0/sep/wand-simp-sat2.smt26
-rwxr-xr-xtest/regress/regress0/sep/wand-simp-unsat.smt27
-rw-r--r--test/regress/regress0/strings/Makefile.am4
-rw-r--r--test/regress/regress0/strings/cmu-2db2-extf-reg.smt29
-rw-r--r--test/regress/regress0/strings/norn-nel-bug-052116.smt223
-rw-r--r--test/regress/regress0/sygus/Makefile.am5
-rw-r--r--test/regress/regress0/sygus/array_search_2.sy2
-rw-r--r--test/regress/regress0/sygus/array_sum_2_5.sy2
-rw-r--r--test/regress/regress0/sygus/clock-inc-tuple.sy2
-rw-r--r--test/regress/regress0/sygus/commutative.sy4
-rw-r--r--test/regress/regress0/sygus/const-var-test.sy2
-rw-r--r--test/regress/regress0/sygus/constant.sy4
-rw-r--r--test/regress/regress0/sygus/dt-no-syntax.sy2
-rw-r--r--test/regress/regress0/sygus/dt-test-ns.sy2
-rw-r--r--test/regress/regress0/sygus/dup-op.sy2
-rw-r--r--test/regress/regress0/sygus/enum-test.sy4
-rw-r--r--test/regress/regress0/sygus/hd-sdiv.sy16
-rw-r--r--test/regress/regress0/sygus/icfp_28_10.sy2
-rw-r--r--test/regress/regress0/sygus/inv-example.sy4
-rw-r--r--test/regress/regress0/sygus/let-ringer.sy2
-rw-r--r--test/regress/regress0/sygus/let-simp.sy2
-rw-r--r--test/regress/regress0/sygus/list-head-x.sy2
-rw-r--r--test/regress/regress0/sygus/max.sy2
-rw-r--r--test/regress/regress0/sygus/max2-univ.sy2
-rw-r--r--test/regress/regress0/sygus/multi-fun-polynomial2.sy4
-rw-r--r--test/regress/regress0/sygus/nflat-fwd-3.sy2
-rw-r--r--test/regress/regress0/sygus/nflat-fwd.sy2
-rw-r--r--test/regress/regress0/sygus/no-flat-simp.sy2
-rw-r--r--test/regress/regress0/sygus/no-mention.sy2
-rw-r--r--test/regress/regress0/sygus/no-syntax-test-bool.sy2
-rw-r--r--test/regress/regress0/sygus/no-syntax-test-no-si.sy2
-rw-r--r--test/regress/regress0/sygus/no-syntax-test.sy2
-rw-r--r--test/regress/regress0/sygus/parity-AIG-d0.sy4
-rw-r--r--test/regress/regress0/sygus/strings-small.sy35
-rw-r--r--test/regress/regress0/sygus/strings-unconstrained.sy15
-rw-r--r--test/regress/regress0/sygus/sygus-dt.sy4
-rw-r--r--test/regress/regress0/sygus/tl-type.sy2
-rw-r--r--test/regress/regress0/sygus/twolets1.sy2
-rw-r--r--test/regress/regress0/sygus/twolets2-orig.sy2
-rw-r--r--test/regress/regress0/sygus/uminus_one.sy4
-rw-r--r--test/regress/regress0/sygus/unbdd_inv_gen_winf1.sy2
-rw-r--r--test/unit/prop/cnf_stream_white.h8
-rw-r--r--test/unit/theory/logic_info_white.h7
334 files changed, 12772 insertions, 4890 deletions
diff --git a/AUTHORS b/AUTHORS
index 3e85b13c7..d157ec958 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,21 +1,23 @@
The authors, designers, and main contributors to CVC4 are listed below.
CVC4's copyright is held by these individuals and the affiliated
-institutions at the time of their contributions (see the file COPYING).
-All rights reserved.
+institutions at the time of their contributions (note that some authors have
+had more than one affiliated institution). See the file COPYING for details on
+the copyright and licensing of CVC4.
The core designers and authors of CVC4 are:
- Kshitij Bansal, New York University
- Clark Barrett, New York University
- Francois Bobot, The University of Iowa & Commissariat a l'Energie Atomique
+ Kshitij Bansal, New York University, Google, Inc.
+ Clark Barrett, New York University, Google, Inc.
+ Francois Bobot, The University of Iowa, Commissariat a l'Energie Atomique
Martin Brain, University of Oxford
- Christopher Conway, New York University & Google, Inc.
+ Christopher Conway, New York University, Google, Inc.
Morgan Deters, New York University
- Liana Hadarean, New York University & Mentor Graphics Corporation
- Dejan Jovanovic, New York University & SRI International
- Tim King, New York University, Universite Joseph Fourier & Google, Inc.
+ Liana Hadarean, New York University, Mentor Graphics Corporation
+ Dejan Jovanovic, New York University, SRI International
+ Guy Katz, New York University
+ Tim King, New York University, Universite Joseph Fourier, Google, Inc.
Tianyi Liang, The University of Iowa
- Andrew Reynolds, The University of Iowa & EPFL
+ Andrew Reynolds, The University of Iowa, EPFL
Cesare Tinelli, The University of Iowa
Contributors to the CVC4 codebase additionally include:
diff --git a/COPYING b/COPYING
index 87fd0147f..4e3e64bce 100644
--- a/COPYING
+++ b/COPYING
@@ -1,5 +1,5 @@
-CVC4 is copyright (C) 2009, 2010, 2011, 2012, 2013, 2014 by its authors
-and contributors (see the file AUTHORS) and their institutional
+CVC4 is copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 by its
+authors and contributors (see the file AUTHORS) and their institutional
affiliations. All rights reserved.
The source code of CVC4 is open and available to students, researchers,
@@ -39,7 +39,7 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--- Morgan Deters <mdeters@cs.nyu.edu> Thu, 13 Nov 2014
+----------------------------------------------------------------------
CVC4 incorporates MiniSat code, excluded from the above copyright.
See src/sat/minisat. Its copyright:
diff --git a/NEWS b/NEWS
index 89ea1c265..91732d922 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-This file contains a summary of important user-visible changes.
+This file contains a summary of important user-visible changes.
Changes since 1.4
=================
diff --git a/config/cryptominisat.m4 b/config/cryptominisat.m4
new file mode 100644
index 000000000..f7d3a1544
--- /dev/null
+++ b/config/cryptominisat.m4
@@ -0,0 +1,87 @@
+# CVC4_CHECK_FOR_CRYPTOMINISAT
+# ------------------
+# Look for cryptominisat and link it in, but only if user requested.
+AC_DEFUN([CVC4_CHECK_FOR_CRYPTOMINISAT], [
+AC_MSG_CHECKING([whether user requested cryptominisat support])
+
+have_libcryptominisat=0
+CRYPTOMINISAT_LIBS=
+CRYPTOMINISAT_LDFLAGS=
+
+have_libcryptominisat=0
+if test "$with_cryptominisat" = no; then
+ AC_MSG_RESULT([no, cryptominisat disabled by user])
+elif test -n "$with_cryptominisat"; then
+ AC_MSG_RESULT([yes, cryptominisat requested by user])
+ AC_ARG_VAR(CRYPTOMINISAT_HOME, [path to top level of cryptominisat source tree])
+ AC_ARG_WITH(
+ [cryptominisat-dir],
+ AS_HELP_STRING(
+ [--with-cryptominisat-dir=PATH],
+ [path to top level of cryptominisat source tree]
+ ),
+ [CRYPTOMINISAT_HOME="$withval"],
+ [ if test -z "$CRYPTOMINISAT_HOME"; then
+ AC_MSG_FAILURE([must give --with-cryptominisat-dir=PATH or define environment variable CRYPTOMINISAT_HOME!])
+ fi
+ ]
+ )
+
+ if ! test -d "$CRYPTOMINISAT_HOME" || ! test -x "$CRYPTOMINISAT_HOME/install/bin/cryptominisat" ; then
+ AC_MSG_FAILURE([either $CRYPTOMINISAT_HOME is not an cryptominisat install tree or it's not yet built])
+ fi
+
+ CPPFLAGS="$CPPFLAGS -I$CRYPTOMINISAT_HOME/install/include"
+
+ AC_MSG_CHECKING([how to link cryptominisat])
+
+ dnl TODO FIXME:
+ dnl For some reason the CVC4_TRY_CRYPTOMINISAT is not working correctly
+ CVC4_TRY_CRYPTOMINISAT_WITH([])
+ CVC4_TRY_CRYPTOMINISAT_WITH([-lm4ri])
+
+ if test -z "$CRYPTOMINISAT_LIBS"; then
+ AC_MSG_FAILURE([cannot link against libcryptominisat!])
+ else
+ AC_MSG_RESULT([$CRYPTOMINISAT_LIBS])
+ have_libcryptominisat=1
+ fi
+
+ CRYPTOMINISAT_LDFLAGS="-L$CRYPTOMINISAT_HOME/install/lib"
+ CRYPTOMINISAT_LIBS="-lcryptominisat4 -lm4ri"
+
+else
+ AC_MSG_RESULT([no, user didn't request cryptominisat])
+ with_cryptominisat=no
+fi
+
+])# CVC4_CHECK_FOR_CRYPTOMINISAT
+
+# CVC4_TRY_STATIC_CRYPTOMINISAT_WITH(LIBS)
+# ------------------------------
+# Try AC_CHECK_LIB(cryptominisat) with the given linking libraries
+AC_DEFUN([CVC4_TRY_CRYPTOMINISAT_WITH], [
+if test -z "$CRYPTOMINISAT_LIBS"; then
+ AC_LANG_PUSH([C++])
+
+ cvc4_save_LIBS="$LIBS"
+ cvc4_save_LDFLAGS="$LDFLAGS"
+ cvc4_save_CPPFLAGS="$CPPFLAGS"
+
+ LDFLAGS="-L$CRYPTOMINISAT_HOME/install/lib"
+ LIBS="-lcryptominisat4 $1"
+
+
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM([#include <cryptominisat4/cryptominisat.h>],
+ [CMSat::SATSolver test()])], [CRYPTOMINISAT_LIBS="-lcryptominisat4 $1"],
+ [CRYPTOMINISAT_LIBS=])
+
+ LDFLAGS="$cvc4_save_LDFLAGS"
+ CPPFLAGS="$cvc4_save_CPPFLAGS"
+ LIBS="$cvc4_save_LIBS"
+
+ AC_LANG_POP([C++])
+fi
+])# CVC4_TRY_CRYPTOMINISAT_WITH
+
diff --git a/configure.ac b/configure.ac
index c3c29db38..2f343368a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -113,7 +113,7 @@ AC_ARG_WITH([build],
if test -z "${with_build+set}"; then
with_build=production
fi
-if test -z "${enable_optimized+set}" -a -z "${enable_debug_symbols+set}" -a -z "${enable_assertions+set}" -a -z "${enable_tracing+set}" -a -z "${enable_dumping+set}" -a -z "${enable_muzzle+set}" -a -z "${enable_coverage+set}" -a -z "${enable_profiling+set}" -a -z "${enable_statistics+set}" -a -z "${enable_replay+set}" -a -z "${with_gmp+set}" -a -z "${with_cln+set}" -a -z "${with_glpk+set}" -a -z "${with_abc+set}"; then
+if test -z "${enable_optimized+set}" -a -z "${enable_debug_symbols+set}" -a -z "${enable_assertions+set}" -a -z "${enable_tracing+set}" -a -z "${enable_dumping+set}" -a -z "${enable_muzzle+set}" -a -z "${enable_coverage+set}" -a -z "${enable_profiling+set}" -a -z "${enable_statistics+set}" -a -z "${enable_replay+set}" -a -z "${with_gmp+set}" -a -z "${with_cln+set}" -a -z "${with_glpk+set}" -a -z "${with_abc+set}" -a -z "${with_cryptominisat+set}"; then
custom_build_profile=no
else
custom_build_profile=yes
@@ -217,6 +217,12 @@ if test -n "${with_abc+set}"; then
btargs="$btargs abc"
fi
fi
+if test -n "${with_cryptominisat+set}"; then
+ if test "$with_cryptominisat" = yes; then
+ btargs="$btargs cryptominisat"
+ fi
+fi
+
AC_MSG_RESULT([$with_build])
AM_INIT_AUTOMAKE([1.11 no-define tar-pax parallel-tests color-tests subdir-objects])
@@ -775,6 +781,21 @@ AM_CONDITIONAL([CVC4_USE_ABC], [test $have_libabc -eq 1])
AC_SUBST([ABC_LDFLAGS])
AC_SUBST([ABC_LIBS])
+
+# Build with libcryptominisat
+AC_ARG_WITH([cryptominisat],
+ [AS_HELP_STRING([--with-cryptominisat],
+ [use the CRYPTOMINISAT sat solver])], [], [with_cryptominisat=])
+CVC4_CHECK_FOR_CRYPTOMINISAT
+if test $have_libcryptominisat -eq 1; then
+ CVC4CPPFLAGS="${CVC4CPPFLAGS:+$CVC4CPPFLAGS }-DCVC4_USE_CRYPTOMINISAT"
+ CVC4CPPFLAGS="${CVC4CPPFLAGS:+$CVC4CPPFLAGS }-I$CRYPTOMINISAT_HOME/install/include"
+fi
+AM_CONDITIONAL([CVC4_USE_CRYPTOMINISAT], [test $have_libcryptominisat -eq 1])
+AC_SUBST([CRYPTOMINISAT_LDFLAGS])
+AC_SUBST([CRYPTOMINISAT_LIBS])
+
+
# Check to see if this version/architecture of GNU C++ explicitly
# instantiates __gnu_cxx::hash<uint64_t> or not. Some do, some don't.
# See src/util/hash.h.
diff --git a/contrib/cryptominisat-4.2.0.patch b/contrib/cryptominisat-4.2.0.patch
new file mode 100644
index 000000000..30b24a3cc
--- /dev/null
+++ b/contrib/cryptominisat-4.2.0.patch
@@ -0,0 +1,12 @@
+diff -ruN orig/CMakeLists.txt new/CMakeLists.txt
+--- CMakeLists.txt 2016-05-24 22:05:50.702570824 -0700
++++ patched.txt 2016-05-24 22:05:57.778570529 -0700
+@@ -132,7 +132,7 @@
+ set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
+ SET(Boost_USE_STATIC_LIBS ON)
+ set(CMAKE_EXE_LINKER_FLAGS "-static -Wl,--whole-archive -lpthread -Wl,--no-whole-archive")
+-
++ add_cxx_flag_if_supported("-fPIC")
+ set(NOMYSQL ON)
+ else()
+ add_definitions(-DBOOST_TEST_DYN_LINK)
diff --git a/contrib/cryptominisat-4.2.0.second.patch b/contrib/cryptominisat-4.2.0.second.patch
new file mode 100644
index 000000000..4b3fdf722
--- /dev/null
+++ b/contrib/cryptominisat-4.2.0.second.patch
@@ -0,0 +1,11 @@
+--- python/CMakeLists.txt 2016-05-24 22:05:50.698570824 -0700
++++ ../new/python/CMakeLists.txt 2016-05-24 22:05:57.774570529 -0700
+@@ -12,7 +12,7 @@
+
+ add_custom_target(pytarget ALL DEPENDS ${OUTPUT}/timestamp)
+
+-install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} ${SETUP_PY} install --record files.txt)")
++#install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} ${SETUP_PY} install --record files.txt)")
+
+ if (ENABLE_TESTING)
+ #add_test (pytest ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/test_pycryptosat.py")
diff --git a/contrib/get-cryptominisat4 b/contrib/get-cryptominisat4
new file mode 100755
index 000000000..c96bbe03d
--- /dev/null
+++ b/contrib/get-cryptominisat4
@@ -0,0 +1,57 @@
+#!/bin/bash
+#
+set -e
+
+version="4.2.0"
+
+cd "$(dirname "$0")/.."
+
+if ! [ -e src/parser/cvc/Cvc.g ]; then
+ echo "$(basename $0): I expect to be in the contrib/ of a CVC4 source tree," >&2
+ echo "but apparently:" >&2
+ echo >&2
+ echo " $(pwd)" >&2
+ echo >&2
+ echo "is not a CVC4 source tree ?!" >&2
+ exit 1
+fi
+
+function webget {
+ if which wget &>/dev/null; then
+ wget -c -O "$2" "$1"
+ elif which curl &>/dev/null; then
+ curl "$1" >"$2"
+ else
+ echo "Can't figure out how to download from web. Please install wget or curl." >&2
+ exit 1
+ fi
+}
+
+if [ -e cryptominisat4 ]; then
+ echo 'error: file or directory "cryptominisat4" exists; please move it out of the way.' >&2
+ exit 1
+fi
+
+mkdir cryptominisat4
+cd cryptominisat4
+CRYPTOMINISAT_PATH=`pwd`
+
+webget https://github.com/msoos/cryptominisat/archive/$version.tar.gz cryptominisat-$version.tar.gz
+gunzip -f cryptominisat-$version.tar.gz
+tar xfv cryptominisat-$version.tar
+cd cryptominisat-$version
+
+patch -p0 < ../../contrib/cryptominisat-4.2.0.patch
+patch -p0 < ../../contrib/cryptominisat-4.2.0.second.patch
+
+mkdir ../build
+cd ../build
+
+cmake -DCMAKE_INSTALL_PREFIX:PATH=$CRYPTOMINISAT_PATH/install -DSTATICCOMPILE="ON" -DNOM4RI="ON" ../cryptominisat-$version
+make install -j2
+
+cd ../
+
+echo
+echo ===================== Now configure CVC4 with =====================
+echo ./configure --with-cryptominisat --with-cryptominisat-dir=`pwd`
diff --git a/contrib/lfsc_lsan.supp b/contrib/lfsc_lsan.supp
new file mode 100644
index 000000000..63022a8f9
--- /dev/null
+++ b/contrib/lfsc_lsan.supp
@@ -0,0 +1,8 @@
+# LSAN suppressions for memory leaks in LFSC.
+#
+# To use this file, add LSAN_OPTIONS to the commandline invocation.
+# LSAN_OPTIONS=suppressions=contrib/lfsc_lsan.supp ./build/bin/cvc4 ...
+# For more information on the leak sanitizer in ASAN, see
+# https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer
+leak:CVC4::CnfProof::pushCurrentDefinition
+
diff --git a/contrib/run-script-cascj8-fnt b/contrib/run-script-cascj8-fnt
new file mode 100644
index 000000000..bc37180a6
--- /dev/null
+++ b/contrib/run-script-cascj8-fnt
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+here=`dirname $0`
+cvc4=$here/cvc4
+bench="$1"
+
+file=${bench##*/}
+filename=${file%.*}
+
+echo "------- cvc4-fnt casc j8 : $bench at $2..."
+
+# use: trywith [params..]
+# to attempt a run. If an SZS ontology result is printed, then
+# the run script terminates immediately. Otherwise, this
+# function returns normally.
+function trywith {
+ limit=$1; shift;
+ echo "--- Run $@ at $limit...";
+ (ulimit -S -t "$limit";$cvc4 --lang=tptp --no-checking --no-interactive --dump-models --produce-models --force-no-limit-cpu-while-dump "$@" $bench) 2>/dev/null |
+ (read w1 w2 w3 result w4 w5;
+ case "$result" in
+ Satisfiable) echo "$w1 $w2 $w3 $result $w4 $w5";cat;exit 0;;
+ CounterSatisfiable) echo "$w1 $w2 $w3 $result $w4 $w5";cat;exit 0;;
+ esac; exit 1)
+ if [ ${PIPESTATUS[1]} -eq 0 ]; then exit 0; fi
+}
+function finishwith {
+ echo "--- Run $@...";
+ $cvc4 --lang=tptp --no-checking --no-interactive --dump-models --produce-models --force-no-limit-cpu-while-dump "$@" $bench
+}
+
+# designed for 300 seconds
+trywith 60 --finite-model-find --fmf-inst-engine --sort-inference --uf-ss-fair
+trywith 30 --finite-model-find --uf-ss=no-minimal --sort-inference --uf-ss-fair
+trywith 60 --finite-model-find --decision=internal --sort-inference --uf-ss-fair
+finishwith --finite-model-find --mbqi=abs --sort-inference --uf-ss-fair
+# echo "% SZS status" "GaveUp for $filename"
diff --git a/contrib/run-script-cascj8-fof b/contrib/run-script-cascj8-fof
new file mode 100644
index 000000000..fe18c3ed0
--- /dev/null
+++ b/contrib/run-script-cascj8-fof
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+here=`dirname $0`
+cvc4=$here/cvc4
+bench="$1"
+
+file=${bench##*/}
+filename=${file%.*}
+
+echo "------- cvc4-fof casc j8 : $bench at $2..."
+
+# use: trywith [params..]
+# to attempt a run. If an SZS ontology result is printed, then
+# the run script terminates immediately. Otherwise, this
+# function returns normally.
+function trywith {
+ limit=$1; shift;
+ echo "--- Run $@ at $limit...";
+ (ulimit -S -t "$limit";$cvc4 --lang=tptp --no-checking --no-interactive --dump-instantiations --inst-format=szs --force-no-limit-cpu-while-dump "$@" $bench) 2>/dev/null |
+ (read w1 w2 w3 result w4 w5;
+ case "$result" in
+ Unsatisfiable) echo "$w1 $w2 $w3 $result $w4 $w5";cat;exit 0;;
+ Theorem) echo "$w1 $w2 $w3 $result $w4 $w5";cat;exit 0;;
+ esac; exit 1)
+ if [ ${PIPESTATUS[1]} -eq 0 ]; then exit 0; fi
+}
+function finishwith {
+ echo "--- Run $@...";
+ $cvc4 --lang=tptp --no-checking --no-interactive --dump-instantiations --inst-format=szs --force-no-limit-cpu-while-dump "$@" $bench
+}
+
+# designed for 300 seconds
+trywith 20 --relational-triggers --full-saturate-quant
+trywith 20 --no-e-matching --full-saturate-quant
+trywith 15 --finite-model-find --mbqi=abs
+trywith 5 --multi-trigger-when-single --full-saturate-quant
+trywith 5 --trigger-sel=max --full-saturate-quant
+trywith 5 --multi-trigger-when-single --multi-trigger-priority --full-saturate-quant
+trywith 10 --finite-model-find --uf-ss=no-minimal --sort-inference --uf-ss-fair
+trywith 10 --term-db-mode=relevant --full-saturate-quant
+trywith 15 --prenex-quant=none --full-saturate-quant
+trywith 15 --decision=internal --full-saturate-quant
+trywith 30 --relevant-triggers --full-saturate-quant
+trywith 30 --finite-model-find --fmf-inst-engine --sort-inference --uf-ss-fair
+trywith 30 --fs-inst --full-saturate-quant
+trywith 30 --no-quant-cf --full-saturate-quant
+finishwith --qcf-vo-exp --full-saturate-quant
+# echo "% SZS status" "GaveUp for $filename"
diff --git a/contrib/run-script-cascj8-tfa b/contrib/run-script-cascj8-tfa
new file mode 100644
index 000000000..da4056466
--- /dev/null
+++ b/contrib/run-script-cascj8-tfa
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+here=`dirname $0`
+cvc4=$here/cvc4
+bench="$1"
+
+file=${bench##*/}
+filename=${file%.*}
+
+echo "------- cvc4-tfa casc j8 : $bench at $2..."
+
+# use: trywith [params..]
+# to attempt a run. If an SZS ontology result is printed, then
+# the run script terminates immediately. Otherwise, this
+# function returns normally.
+function trywith {
+ limit=$1; shift;
+ echo "--- Run $@ at $limit...";
+ (ulimit -S -t "$limit";$cvc4 --lang=tptp --no-checking --no-interactive --force-logic="UFNIRA" --dump-instantiations --inst-format=szs --force-no-limit-cpu-while-dump "$@" $bench) 2>/dev/null |
+ (read w1 w2 w3 result w4 w5;
+ case "$result" in
+ Unsatisfiable) echo "$w1 $w2 $w3 $result $w4 $w5";cat;exit 0;;
+ Theorem) echo "$w1 $w2 $w3 $result $w4 $w5";cat;exit 0;;
+ esac; exit 1)
+ if [ ${PIPESTATUS[1]} -eq 0 ]; then exit 0; fi
+}
+function finishwith {
+ echo "--- Run $@...";
+ $cvc4 --lang=tptp --no-checking --no-interactive --force-logic="UFNIRA" --dump-instantiations --inst-format=szs --force-no-limit-cpu-while-dump "$@" $bench
+}
+
+trywith 10 --decision=internal --full-saturate-quant
+trywith 10 --finite-model-find --decision=internal
+trywith 10 --purify-quant --full-saturate-quant
+trywith 10 --partial-triggers --full-saturate-quant
+trywith 10 --no-e-matching --full-saturate-quant
+trywith 30 --cbqi-all --purify-triggers --full-saturate-quant
+trywith 60 --cbqi-all --fs-inst --full-saturate-quant
+finishwith --full-saturate-quant
+# echo "% SZS status" "GaveUp for $filename"
diff --git a/contrib/run-script-cascj8-tfn b/contrib/run-script-cascj8-tfn
new file mode 100644
index 000000000..a6fe1e23c
--- /dev/null
+++ b/contrib/run-script-cascj8-tfn
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+here=`dirname $0`
+cvc4=$here/cvc4
+bench="$1"
+
+file=${bench##*/}
+filename=${file%.*}
+
+echo "------- cvc4-fnt casc j8 : $bench at $2..."
+
+# use: trywith [params..]
+# to attempt a run. If an SZS ontology result is printed, then
+# the run script terminates immediately. Otherwise, this
+# function returns normally.
+function trywith {
+ limit=$1; shift;
+ echo "--- Run $@ at $limit...";
+ (ulimit -S -t "$limit";$cvc4 --lang=tptp --no-checking --no-interactive --dump-models --produce-models --force-no-limit-cpu-while-dump "$@" $bench) 2>/dev/null |
+ (read w1 w2 w3 result w4 w5;
+ case "$result" in
+ Satisfiable) echo "$w1 $w2 $w3 $result $w4 $w5";cat;exit 0;;
+ CounterSatisfiable) echo "$w1 $w2 $w3 $result $w4 $w5";cat;exit 0;;
+ esac; exit 1)
+ if [ ${PIPESTATUS[1]} -eq 0 ]; then exit 0; fi
+}
+function finishwith {
+ echo "--- Run $@...";
+ $cvc4 --lang=tptp --no-checking --no-interactive --dump-models --produce-models --force-no-limit-cpu-while-dump "$@" $bench
+}
+
+# designed for 300 seconds
+trywith 60 --finite-model-find --sort-inference --uf-ss-fair
+trywith 30 --full-saturate-quant
+trywith 30 --finite-model-find --fmf-bound-int --macros-quant
+finishwith --finite-model-find --decision=internal --sort-inference --uf-ss-fair
+# echo "% SZS status" "GaveUp for $filename"
diff --git a/contrib/run-script-smtcomp2016 b/contrib/run-script-smtcomp2016
new file mode 100644
index 000000000..58b281b4c
--- /dev/null
+++ b/contrib/run-script-smtcomp2016
@@ -0,0 +1,134 @@
+#!/bin/bash
+
+cvc4=./cvc4
+bench="$1"
+
+logic=$(expr "$(grep -m1 '^[^;]*set-logic' "$bench")" : ' *(set-logic *\([A-Z_]*\) *) *$')
+
+# use: trywith [params..]
+# to attempt a run. Only thing printed on stdout is "sat" or "unsat", in
+# which case this run script terminates immediately. Otherwise, this
+# function returns normally.
+function trywith {
+ limit=$1; shift;
+ result="$(ulimit -S -t "$limit";$cvc4 -L smt2 --no-incremental --no-checking --no-interactive "$@" $bench)"
+ case "$result" in
+ sat|unsat) echo "$result"; exit 0;;
+ esac
+}
+
+# use: finishwith [params..]
+# to run cvc4 and let it output whatever it will to stdout.
+function finishwith {
+ $cvc4 -L smt2 --no-incremental --no-checking --no-interactive "$@" $bench
+}
+
+case "$logic" in
+
+QF_LRA)
+ trywith 200 --enable-miplib-trick --miplib-trick-subs=4 --use-approx --lemmas-on-replay-failure --replay-early-close-depth=4 --replay-lemma-reject-cut=128 --replay-reject-cut=512 --unconstrained-simp --use-soi
+ finishwith --no-restrict-pivots --use-soi --new-prop --unconstrained-simp
+ ;;
+QF_LIA)
+ # same as QF_LRA but add --pb-rewrites
+ finishwith --enable-miplib-trick --miplib-trick-subs=4 --use-approx --lemmas-on-replay-failure --replay-early-close-depth=4 --replay-lemma-reject-cut=128 --replay-reject-cut=512 --unconstrained-simp --use-soi --pb-rewrites
+ ;;
+QF_NIA)
+ trywith 20
+ trywith 1800 --solve-int-as-bv=2 --bitblast=eager --bv-sat-solver=cryptominisat
+ trywith 1800 --solve-int-as-bv=4 --bitblast=eager --bv-sat-solver=cryptominisat
+ trywith 1800 --solve-int-as-bv=8 --bitblast=eager --bv-sat-solver=cryptominisat
+ trywith 1800 --solve-int-as-bv=16 --bitblast=eager --bv-sat-solver=cryptominisat
+ finishwith --solve-int-as-bv=32 --bitblast=eager --bv-sat-solver=cryptominisat
+ ;;
+ALIA|AUFLIA|AUFLIRA|AUFNIRA|UF|UFIDL|UFLIA|UFLRA|UFNIA)
+ # the following is designed for a run time of 2400s (40 min).
+ # initial runs 1min
+ trywith 20 --simplification=none --full-saturate-quant
+ trywith 20 --no-e-matching --full-saturate-quant
+ trywith 20 --fs-inst --decision=internal --full-saturate-quant
+ # trigger selections 2min
+ trywith 30 --relevant-triggers --full-saturate-quant
+ trywith 30 --trigger-sel=max --full-saturate-quant
+ trywith 30 --multi-trigger-when-single --full-saturate-quant
+ trywith 30 --multi-trigger-when-single --multi-trigger-priority --full-saturate-quant
+ # other 2min
+ trywith 30 --pre-skolem-quant --full-saturate-quant
+ trywith 30 --inst-when=full --full-saturate-quant
+ trywith 30 --decision=internal --simplification=none --no-inst-no-entail --no-quant-cf --full-saturate-quant
+ trywith 30 --no-e-matching --no-quant-cf --full-saturate-quant
+ # finite model find 2min
+ trywith 30 --finite-model-find
+ trywith 30 --finite-model-find --uf-ss=no-minimal
+ trywith 60 --finite-model-find --decision=internal
+ # long runs 20min
+ trywith 300 --decision=internal --full-saturate-quant
+ trywith 300 --term-db-mode=relevant --full-saturate-quant
+ trywith 300 --fs-inst --full-saturate-quant
+ trywith 300 --finite-model-find --fmf-inst-engine
+ # finite model find 1min
+ trywith 30 --finite-model-find --fmf-bound-int
+ trywith 30 --finite-model-find --sort-inference
+ # finish 12min
+ finishwith --full-saturate-quant
+ ;;
+UFBV)
+ # many problems in UFBV are essentially BV
+ trywith 300 --full-saturate-quant
+ trywith 300 --finite-model-find
+ finishwith --cbqi-all --full-saturate-quant
+ ;;
+BV)
+ trywith 300 --finite-model-find
+ finishwith --cbqi-all --full-saturate-quant
+ ;;
+LIA|LRA|NIA|NRA)
+ trywith 30 --full-saturate-quant
+ trywith 300 --full-saturate-quant --cbqi-min-bounds
+ trywith 300 --full-saturate-quant --decision=internal
+ finishwith --full-saturate-quant --cbqi-midpoint
+ ;;
+QF_AUFBV)
+ trywith 600
+ finishwith --decision=justification-stoponly
+ ;;
+QF_ABV)
+ trywith 50 --ite-simp --simp-with-care --repeat-simp --arrays-weak-equiv
+ trywith 500 --arrays-weak-equiv
+ finishwith --ite-simp --simp-with-care --repeat-simp --arrays-weak-equiv
+ ;;
+QF_UFBV)
+ finishwith --bitblast=eager --bv-sat-solver=cryptominisat
+ ;;
+QF_BV)
+ exec ./pcvc4 -L smt2 --no-incremental --no-checking --no-interactive --thread-stack=1024 \
+ --threads 2 \
+ --thread0 '--unconstrained-simp --bv-div-zero-const --bv-intro-pow2 --bitblast=eager --bv-sat-solver=cryptominisat --bitblast-aig --no-bv-abstraction' \
+ --thread1 '--unconstrained-simp --bv-div-zero-const --bv-intro-pow2 --bv-eq-slicer=auto --no-bv-abstraction' \
+ --no-wait-to-join \
+ "$bench"
+ #trywith 10 --bv-eq-slicer=auto --decision=justification
+ #trywith 60 --decision=justification
+ #trywith 600 --decision=internal --bitblast-eager
+ #finishwith --decision=justification --decision-use-weight --decision-weight-internal=usr1
+ ;;
+QF_AUFLIA)
+ finishwith --no-arrays-eager-index --arrays-eager-lemmas --decision=justification
+ ;;
+QF_AX)
+ finishwith --no-arrays-eager-index --arrays-eager-lemmas --decision=internal
+ ;;
+QF_AUFNIA)
+ finishwith --decision=justification --no-arrays-eager-index --arrays-eager-lemmas
+ ;;
+QF_ALIA)
+ trywith 70 --decision=justification --arrays-weak-equiv
+ finishwith --decision=justification-stoponly --no-arrays-eager-index --arrays-eager-lemmas
+ ;;
+*)
+ # just run the default
+ finishwith
+ ;;
+
+esac
+
diff --git a/contrib/run-script-smtcomp2016-application b/contrib/run-script-smtcomp2016-application
new file mode 100644
index 000000000..88bbb5f53
--- /dev/null
+++ b/contrib/run-script-smtcomp2016-application
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+cvc4=./cvc4-application
+
+read line
+if [ "$line" != '(set-option :print-success true)' ]; then
+ echo 'ERROR: first line supposed to be set-option :print-success, but got: "'"$line"'"' >&2
+ exit 1
+fi
+echo success
+read line
+logic=$(expr "$line" : ' *(set-logic *\([A-Z_]*\) *) *$')
+if [ -z "$logic" ]; then
+ echo 'ERROR: second line supposed to be set-logic, but got: "'"$line"'"' >&2
+ exit 1
+fi
+echo success
+
+function runcvc4 {
+ # we run in this way for line-buffered input, otherwise memory's a
+ # concern (plus it mimics what we'll end up getting from an
+ # application-track trace runner?)
+ $cvc4 --force-logic="$logic" -L smt2 --print-success --no-checking --no-interactive "$@" <&0-
+}
+
+case "$logic" in
+
+ALIA|QF_ALIA|QF_LRA|QF_UFLIA|QF_UFLRA|UFLRA)
+ runcvc4 --incremental
+ ;;
+ANIA|QF_ANIA|QF_NIA|QF_UFNIA)
+ runcvc4 --tear-down-incremental=1
+ ;;
+LIA)
+ runcvc4 --incremental --cbqi
+ ;;
+QF_AUFLIA)
+ runcvc4 --no-arrays-eager-index --arrays-eager-lemmas --incremental
+ ;;
+QF_BV)
+ runcvc4 --tear-down-incremental=4 --bv-eq-slicer=auto --bv-div-zero-const --bv-intro-pow2
+ ;;
+QF_LIA)
+ runcvc4 --tear-down-incremental=1 --unconstrained-simp
+ ;;
+*)
+ # just run the default
+ runcvc4 --incremental
+ ;;
+
+esac
diff --git a/contrib/run-script-sygusComp2016-CLIA b/contrib/run-script-sygusComp2016-CLIA
new file mode 100644
index 000000000..3dc08d8c0
--- /dev/null
+++ b/contrib/run-script-sygusComp2016-CLIA
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+cvc4=./cvc4
+bench="$1"
+
+function trywith {
+ ($cvc4 --lang=sygus --no-checking --no-interactive --dump-synth --default-dag-thresh=0 "$@" $bench) 2>/dev/null |
+ (read result w1;
+ case "$result" in
+ unsat) echo "$w1";cat;exit 0;;
+ esac; exit 1)
+ if [ ${PIPESTATUS[1]} -eq 0 ]; then exit 0; fi
+}
+
+trywith --decision=internal --cbqi-prereg-inst
+
diff --git a/contrib/run-script-sygusComp2016-GENERAL b/contrib/run-script-sygusComp2016-GENERAL
new file mode 100755
index 000000000..0ee133ea8
--- /dev/null
+++ b/contrib/run-script-sygusComp2016-GENERAL
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+cvc4=./cvc4
+bench="$1"
+
+function runl {
+ limit=$1; shift;
+ ulimit -S -t "$limit";$cvc4 --lang=sygus --no-checking --no-interactive --dump-synth --default-dag-thresh=0 "$@" $bench
+}
+
+function trywith {
+ sol=$(runl $@)
+ status=$?
+ if [ $status -ne 134 ]; then
+ echo $sol |
+ (read result w1;
+ case "$result" in
+ unsat) echo "$w1";cat;exit 0;;
+ esac; exit 1)
+ if [ ${PIPESTATUS[1]} -eq 0 ]; then exit 0; fi
+ fi
+}
+
+function finishwith {
+ $cvc4 --lang=sygus --no-checking --no-interactive --dump-synth --default-dag-thresh=0 "$@" $bench 2>/dev/null |
+ (read result w1;
+ case "$result" in
+ unsat) echo "$w1";cat;exit 0;;
+ esac)
+}
+
+trywith 120 --cegqi-si=all-abort --cegqi-si-abort --decision=internal --cbqi-prereg-inst
+finishwith --cegqi-si=none
diff --git a/contrib/run-script-sygusComp2016-INV b/contrib/run-script-sygusComp2016-INV
new file mode 100644
index 000000000..a25a5f5c8
--- /dev/null
+++ b/contrib/run-script-sygusComp2016-INV
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+cvc4=./cvc4
+bench="$1"
+
+function trywith {
+ ($cvc4 --lang=sygus --no-checking --no-interactive --dump-synth --default-dag-thresh=0 "$@" $bench) 2>/dev/null |
+ (read result w1;
+ case "$result" in
+ unsat) echo "$w1";cat;exit 0;;
+ esac; exit 1)
+ if [ ${PIPESTATUS[1]} -eq 0 ]; then exit 0; fi
+}
+
+trywith --sygus-inv-templ=post
+
diff --git a/contrib/run-script-sygusComp2016-PBE b/contrib/run-script-sygusComp2016-PBE
new file mode 100644
index 000000000..19d8fd891
--- /dev/null
+++ b/contrib/run-script-sygusComp2016-PBE
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+cvc4=./cvc4
+bench="$1"
+
+function trywith {
+ ($cvc4 --lang=sygus --no-checking --no-interactive --dump-synth --default-dag-thresh=0 "$@" $bench) 2>/dev/null |
+ (read result w1;
+ case "$result" in
+ unsat) echo "$w1";cat;exit 0;;
+ esac; exit 1)
+ if [ ${PIPESTATUS[1]} -eq 0 ]; then exit 0; fi
+}
+
+trywith --cegqi-si=none
+
diff --git a/proofs/lfsc_checker/check.cpp b/proofs/lfsc_checker/check.cpp
index c96791aeb..22e326cda 100644
--- a/proofs/lfsc_checker/check.cpp
+++ b/proofs/lfsc_checker/check.cpp
@@ -24,7 +24,7 @@ int colnum = 1;
const char *filename = 0;
FILE *curfile = 0;
-//#define USE_HASH_MAPS
+//#define USE_HASH_MAPS //AJR: deprecated
symmap2 progs;
std::vector< Expr* > ascHoles;
diff --git a/proofs/lfsc_checker/expr.cpp b/proofs/lfsc_checker/expr.cpp
index ae0e49531..5cb774fbf 100644
--- a/proofs/lfsc_checker/expr.cpp
+++ b/proofs/lfsc_checker/expr.cpp
@@ -34,7 +34,6 @@ bool destroy_progs = false;
Expr *r = rr; \
int ref = r->data >> 9; \
ref = ref - 1; \
- r->debugrefcnt(ref,DEC); \
if (ref == 0) { \
_e = r; \
goto start_destroy; \
@@ -43,6 +42,7 @@ bool destroy_progs = false;
r->data = (ref << 9) | (r->data & 511); \
} while(0)
+//removed from below "ref = ref -1;": r->debugrefcnt(ref,DEC);
void Expr::destroy(Expr *_e, bool dec_kids) {
start_destroy:
diff --git a/proofs/lfsc_checker/expr.h b/proofs/lfsc_checker/expr.h
index 32a62ab33..5a505a3d9 100644
--- a/proofs/lfsc_checker/expr.h
+++ b/proofs/lfsc_checker/expr.h
@@ -8,9 +8,9 @@
#include <map>
#include "chunking_memory_management.h"
-#define USE_FLAT_APP
+#define USE_FLAT_APP //AJR: off deprecated
#define MARKVAR_32
-#define DEBUG_SYM_NAMES
+//#define DEBUG_SYM_NAMES
//#define DEBUG_SYMS
// Expr class
@@ -66,7 +66,6 @@ protected:
enum { INC, DEC, CREATE };
void debugrefcnt(int ref, int what) {
-#ifdef DEBUG_REFCNT
std::cout << "[";
debug();
switch(what) {
@@ -83,10 +82,6 @@ protected:
char tmp[10];
sprintf(tmp,"%d",ref);
std::cout << tmp << "]\n";
-#else
- (void)ref;
- (void)what;
-#endif
}
Expr(int _class, int _op)
@@ -114,14 +109,18 @@ public:
// std::cout << " " << ref << std::endl;
//}
ref = ref<4194303 ? ref + 1 : ref;
+#ifdef DEBUG_REFCNT
debugrefcnt(ref,INC);
+#endif
data = (ref << 9) | (data & 511);
}
static void destroy(Expr *, bool);
inline void dec(bool dec_kids = true) {
int ref = getrefcnt();
ref = ref - 1;
+#ifdef DEBUG_REFCNT
debugrefcnt(ref,DEC);
+#endif
if (ref == 0)
destroy(this,dec_kids);
else
@@ -131,10 +130,10 @@ public:
//must pass statType (the expr representing "type") to this function
bool isType( Expr* statType );
- inline bool isDatatype() {
+ inline bool isDatatype() const {
return getclass() == SYMS_EXPR || getop() == MPZ || getop() == MPQ;
}
- inline bool isArithTerm() {
+ inline bool isArithTerm() const {
return getop() == ADD || getop() == NEG;
}
@@ -188,13 +187,17 @@ public:
CExpr(int _op) : Expr(CEXPR, _op), kids() {
kids = new Expr *[1];
kids[0] = 0;
+#ifdef DEBUG_REFCNT
debugrefcnt(1,CREATE);
+#endif
}
CExpr(int _op, Expr *e1) : Expr(CEXPR, _op), kids() {
kids = new Expr *[2];
kids[0] = e1;
kids[1] = 0;
+#ifdef DEBUG_REFCNT
debugrefcnt(1,CREATE);
+#endif
}
CExpr(int _op, Expr *e1, Expr *e2)
: Expr(CEXPR, _op), kids() {
@@ -202,7 +205,9 @@ public:
kids[0] = e1;
kids[1] = e2;
kids[2] = 0;
+#ifdef DEBUG_REFCNT
debugrefcnt(1,CREATE);
+#endif
}
CExpr(int _op, Expr *e1, Expr *e2, Expr *e3)
: Expr(CEXPR, _op), kids() {
@@ -211,7 +216,9 @@ public:
kids[1] = e2;
kids[2] = e3;
kids[3] = 0;
+#ifdef DEBUG_REFCNT
debugrefcnt(1,CREATE);
+#endif
}
CExpr(int _op, Expr *e1, Expr *e2, Expr *e3, Expr *e4)
: Expr(CEXPR, _op), kids() {
@@ -221,7 +228,9 @@ public:
kids[2] = e3;
kids[3] = e4;
kids[4] = 0;
+#ifdef DEBUG_REFCNT
debugrefcnt(1,CREATE);
+#endif
}
CExpr(int _op, const std::vector<Expr *> &_kids)
: Expr(CEXPR, _op), kids() {
@@ -230,13 +239,17 @@ public:
for (i = 0; i < iend; i++)
kids[i] = _kids[i];
kids[i] = 0;
+#ifdef DEBUG_REFCNT
debugrefcnt(1,CREATE);
+#endif
}
// _kids must be null-terminated.
CExpr(int _op, bool dummy, Expr **_kids) : Expr(CEXPR, _op), kids(_kids) {
(void)dummy;
+#ifdef DEBUG_REFCNT
debugrefcnt(1,CREATE);
+#endif
}
Expr *whr();
@@ -253,7 +266,9 @@ class IntExpr : public Expr {
}
IntExpr(mpz_t _n) : Expr(INT_EXPR, 0), n() {
mpz_init_set(n,_n);
+#ifdef DEBUG_REFCNT
debugrefcnt(1,CREATE);
+#endif
}
IntExpr(signed long int _n ) : Expr(INT_EXPR, 0), n() {
mpz_init_set_si( n, _n );
@@ -271,7 +286,9 @@ class RatExpr : public Expr {
RatExpr(mpq_t _n) : Expr(RAT_EXPR, 0), n() {
mpq_init( n );
mpq_set(n,_n);
+#ifdef DEBUG_REFCNT
debugrefcnt(1,CREATE);
+#endif
mpq_canonicalize( n );
}
RatExpr(signed long int _n1, unsigned long int _n2 ) : Expr(RAT_EXPR, 0), n() {
@@ -290,15 +307,19 @@ class SymExpr : public Expr {
: Expr(theclass, 0), val(0)
{
(void)_s;
+#ifdef DEBUG_REFCNT
if (theclass == SYM_EXPR)
debugrefcnt(1,CREATE);
+#endif
}
SymExpr(const SymExpr &e, int theclass = SYM_EXPR)
: Expr(theclass, 0), val(0)
{
(void)e;
+#ifdef DEBUG_REFCNT
if (theclass == SYM_EXPR)
debugrefcnt(1,CREATE);
+#endif
}
#ifdef MARKVAR_32
private:
@@ -317,12 +338,16 @@ class SymSExpr : public SymExpr {
SymSExpr(std::string _s, int theclass = SYMS_EXPR)
: SymExpr(_s, theclass), s(_s)
{
+#ifdef DEBUG_REFCNT
debugrefcnt(1,CREATE);
+#endif
}
SymSExpr(const SymSExpr &e, int theclass = SYMS_EXPR)
: SymExpr(e, theclass), s(e.s)
{
+#ifdef DEBUG_REFCNT
debugrefcnt(1,CREATE);
+#endif
}
};
@@ -338,7 +363,9 @@ public:
#ifdef DEBUG_HOLE_NAMES
id = next_id++;
#endif
+#ifdef DEBUG_REFCNT
debugrefcnt(1,CREATE);
+#endif
}
Expr *val; // may be set during subst(), defeq(), and clone().
};
diff --git a/proofs/lfsc_checker/main.cpp b/proofs/lfsc_checker/main.cpp
index 80f36e69f..1d8ba5809 100644
--- a/proofs/lfsc_checker/main.cpp
+++ b/proofs/lfsc_checker/main.cpp
@@ -133,6 +133,7 @@ int main(int argc, char **argv) {
a.files.clear();
#endif
+ std::cout << "Proof checked successfully!" << std::endl << std::endl;
std::cout << "time = " << (int)clock() - check_time << std::endl;
std::cout << "sym count = " << SymExpr::symmCount << std::endl;
std::cout << "marked count = " << Expr::markedCount << std::endl;
diff --git a/proofs/lfsc_checker/scccode.cpp b/proofs/lfsc_checker/scccode.cpp
index 22f26ec88..19712579c 100644
--- a/proofs/lfsc_checker/scccode.cpp
+++ b/proofs/lfsc_checker/scccode.cpp
@@ -1,609 +1,11 @@
#include "scccode.h"
-Expr* e_pos;
-Expr* e_neg;
-Expr* e_tt;
-Expr* e_ff;
-Expr* e_cln;
-Expr* e_clc;
-Expr* e_concat;
-Expr* e_clr;
-Expr* e_litvar;
-Expr* e_litpol;
-Expr* e_notb;
-Expr* e_iffb;
-Expr* e_clear_mark;
-Expr* e_append;
-Expr* e_simplify_clause_h;
-Expr* e_simplify_clause;
-
void init_compiled_scc(){
- e_pos = symbols->get("pos").first;
- e_neg = symbols->get("neg").first;
- e_tt = symbols->get("tt").first;
- e_ff = symbols->get("ff").first;
- e_cln = symbols->get("cln").first;
- e_clc = symbols->get("clc").first;
- e_concat = symbols->get("concat").first;
- e_clr = symbols->get("clr").first;
- e_litvar = progs["litvar"];
- e_litpol = progs["litpol"];
- e_notb = progs["notb"];
- e_iffb = progs["iffb"];
- e_clear_mark = progs["clear_mark"];
- e_append = progs["append"];
- e_simplify_clause_h = progs["simplify_clause_h"];
- e_simplify_clause = progs["simplify_clause"];
-}
-
-Expr* run_compiled_scc( Expr* p, std::vector< Expr* >& args ){
- if( p==e_litvar ){
- return f_litvar( args[0] );
- }else if( p==e_litpol ){
- return f_litpol( args[0] );
- }else if( p==e_notb ){
- return f_notb( args[0] );
- }else if( p==e_iffb ){
- return f_iffb( args[0], args[1] );
- }else if( p==e_clear_mark ){
- return f_clear_mark( args[0] );
- }else if( p==e_append ){
- return f_append( args[0], args[1] );
- }else if( p==e_simplify_clause_h ){
- return f_simplify_clause_h( args[0], args[1] );
- }else if( p==e_simplify_clause ){
- return f_simplify_clause( args[0] );
- }else{
- return NULL;
- }
-}
-
-Expr* f_litvar( Expr* l ){
- Expr* e0;
- l->inc();
- Expr* e1 = l->followDefs()->get_head();
- Expr* e2;
- e2 = e_pos;
- e2->inc();
- Expr* e3;
- e3 = e_neg;
- e3->inc();
- if( e1==e2 ){
- Expr* x = ((CExpr*)l->followDefs())->kids[1];
- e0 = x;
- e0->inc();
- }else if( e1==e3 ){
- Expr* x = ((CExpr*)l->followDefs())->kids[1];
- e0 = x;
- e0->inc();
- }else{
- std::cout << "Could not find match for expression in function f_litvar ";
- e1->print( std::cout );
- std::cout << std::endl;
- exit( 1 );
- }
- l->dec();
- e2->dec();
- e3->dec();
- return e0;
-}
-
-Expr* f_litpol( Expr* l ){
- Expr* e0;
- l->inc();
- Expr* e1 = l->followDefs()->get_head();
- Expr* e2;
- e2 = e_pos;
- e2->inc();
- Expr* e3;
- e3 = e_neg;
- e3->inc();
- if( e1==e2 ){
- // Expr* x = ((CExpr*)l->followDefs())->kids[1];
- e0 = e_tt;
- e0->inc();
- }else if( e1==e3 ){
- // Expr* x = ((CExpr*)l->followDefs())->kids[1];
- e0 = e_ff;
- e0->inc();
- }else{
- std::cout << "Could not find match for expression in function f_litpol ";
- e1->print( std::cout );
- std::cout << std::endl;
- exit( 1 );
- }
- l->dec();
- e2->dec();
- e3->dec();
- return e0;
-}
-Expr* f_notb( Expr* b ){
- Expr* e0;
- b->inc();
- Expr* e1 = b->followDefs()->get_head();
- Expr* e2;
- e2 = e_ff;
- e2->inc();
- Expr* e3;
- e3 = e_tt;
- e3->inc();
- if( e1==e2 ){
- e0 = e_tt;
- e0->inc();
- }else if( e1==e3 ){
- e0 = e_ff;
- e0->inc();
- }else{
- std::cout << "Could not find match for expression in function f_notb ";
- e1->print( std::cout );
- std::cout << std::endl;
- exit( 1 );
- }
- b->dec();
- e2->dec();
- e3->dec();
- return e0;
}
-Expr* f_iffb( Expr* b1, Expr* b2 ){
- Expr* e0;
- b1->inc();
- Expr* e1 = b1->followDefs()->get_head();
- Expr* e2;
- e2 = e_tt;
- e2->inc();
- Expr* e3;
- e3 = e_ff;
- e3->inc();
- if( e1==e2 ){
- e0 = b2;
- e0->inc();
- }else if( e1==e3 ){
- b2->inc();
- e0 = f_notb( b2 );
- b2->dec();
- }else{
- std::cout << "Could not find match for expression in function f_iffb ";
- e1->print( std::cout );
- std::cout << std::endl;
- exit( 1 );
- }
- b1->dec();
- e2->dec();
- e3->dec();
- return e0;
-}
-
-Expr* f_clear_mark( Expr* v ){
- Expr* e0;
- v->inc();
- if ( ((SymExpr*)v->followDefs())->getmark(0)){
- v->inc();
- if ( ((SymExpr*)v->followDefs())->getmark(0))
- ((SymExpr*)v->followDefs())->clearmark(0);
- else
- ((SymExpr*)v->followDefs())->setmark(0);
- e0 = v;
- e0->inc();
- v->dec();
- }else{
- e0 = v;
- e0->inc();
- }
- v->dec();
- return e0;
-}
-
-Expr* f_append( Expr* c1, Expr* c2 ){
- Expr* e0;
- c1->inc();
- Expr* e1 = c1->followDefs()->get_head();
- Expr* e2;
- e2 = e_cln;
- e2->inc();
- Expr* e3;
- e3 = e_clc;
- e3->inc();
- if( e1==e2 ){
- e0 = c2;
- e0->inc();
- }else if( e1==e3 ){
- Expr* l = ((CExpr*)c1->followDefs())->kids[1];
- Expr* c1h = ((CExpr*)c1->followDefs())->kids[2];
- l->inc();
- Expr* e4;
- c1h->inc();
- c2->inc();
- e4 = f_append( c1h, c2 );
- c1h->dec();
- c2->dec();
- static Expr* e5;
- e5 = e_clc;
- e5->inc();
- e0 = new CExpr( APP, e5, l, e4 );
- }else{
- std::cout << "Could not find match for expression in function f_append ";
- e1->print( std::cout );
- std::cout << std::endl;
- exit( 1 );
- }
- c1->dec();
- e2->dec();
- e3->dec();
- return e0;
-}
-
-Expr* f_simplify_clause_h( Expr* pol, Expr* c ){
- Expr* e0;
- c->inc();
- Expr* e1 = c->followDefs()->get_head();
- Expr* e2;
- e2 = e_cln;
- e2->inc();
- Expr* e3;
- e3 = e_clc;
- e3->inc();
- Expr* e4;
- e4 = e_concat;
- e4->inc();
- Expr* e5;
- e5 = e_clr;
- e5->inc();
- if( e1==e2 ){
- e0 = e_cln;
- e0->inc();
- }else if( e1==e3 ){
- Expr* l = ((CExpr*)c->followDefs())->kids[1];
- Expr* c1 = ((CExpr*)c->followDefs())->kids[2];
- Expr* v;
- l->inc();
- v = f_litvar( l );
- l->dec();
- Expr* e6;
- Expr* e7;
- l->inc();
- e7 = f_litpol( l );
- l->dec();
- pol->inc();
- e6 = f_iffb( e7, pol );
- e7->dec();
- pol->dec();
- Expr* e8 = e6->followDefs()->get_head();
- Expr* e9;
- e9 = e_tt;
- e9->inc();
- Expr* e10;
- e10 = e_ff;
- e10->inc();
- if( e8==e9 ){
- Expr* m;
- v->inc();
- if ( ((SymExpr*)v->followDefs())->getmark(0)){
- m = e_tt;
- m->inc();
- }else{
- Expr* e11;
- v->inc();
- if ( ((SymExpr*)v->followDefs())->getmark(0))
- ((SymExpr*)v->followDefs())->clearmark(0);
- else
- ((SymExpr*)v->followDefs())->setmark(0);
- e11 = v;
- e11->inc();
- v->dec();
- e11->dec();
- m = e_ff;
- m->inc();
- }
- v->dec();
- Expr* ch;
- pol->inc();
- c1->inc();
- ch = f_simplify_clause_h( pol, c1 );
- pol->dec();
- c1->dec();
- m->inc();
- Expr* e12 = m->followDefs()->get_head();
- Expr* e13;
- e13 = e_tt;
- e13->inc();
- Expr* e14;
- e14 = e_ff;
- e14->inc();
- if( e12==e13 ){
- Expr* e15;
- v->inc();
- if ( ((SymExpr*)v->followDefs())->getmark(1)){
- e15 = v;
- e15->inc();
- }else{
- v->inc();
- if ( ((SymExpr*)v->followDefs())->getmark(1))
- ((SymExpr*)v->followDefs())->clearmark(1);
- else
- ((SymExpr*)v->followDefs())->setmark(1);
- e15 = v;
- e15->inc();
- v->dec();
- }
- v->dec();
- e15->dec();
- e0 = ch;
- e0->inc();
- }else if( e12==e14 ){
- Expr* e16;
- Expr* e17;
- v->inc();
- if ( ((SymExpr*)v->followDefs())->getmark(1)){
- v->inc();
- if ( ((SymExpr*)v->followDefs())->getmark(1))
- ((SymExpr*)v->followDefs())->clearmark(1);
- else
- ((SymExpr*)v->followDefs())->setmark(1);
- e17 = v;
- e17->inc();
- v->dec();
- }else{
- e17 = v;
- e17->inc();
- }
- v->dec();
- e17->dec();
- v->inc();
- if ( ((SymExpr*)v->followDefs())->getmark(0))
- ((SymExpr*)v->followDefs())->clearmark(0);
- else
- ((SymExpr*)v->followDefs())->setmark(0);
- e16 = v;
- e16->inc();
- v->dec();
- e16->dec();
- l->inc();
- ch->inc();
- static Expr* e18;
- e18 = e_clc;
- e18->inc();
- e0 = new CExpr( APP, e18, l, ch );
- }else{
- std::cout << "Could not find match for expression in function f_simplify_clause_h ";
- e12->print( std::cout );
- std::cout << std::endl;
- exit( 1 );
- }
- m->dec();
- e13->dec();
- e14->dec();
- ch->dec();
- m->dec();
- }else if( e8==e10 ){
- l->inc();
- Expr* e19;
- pol->inc();
- c1->inc();
- e19 = f_simplify_clause_h( pol, c1 );
- pol->dec();
- c1->dec();
- static Expr* e20;
- e20 = e_clc;
- e20->inc();
- e0 = new CExpr( APP, e20, l, e19 );
- }else{
- std::cout << "Could not find match for expression in function f_simplify_clause_h ";
- e8->print( std::cout );
- std::cout << std::endl;
- exit( 1 );
- }
- e6->dec();
- e9->dec();
- e10->dec();
- v->dec();
- }else if( e1==e4 ){
- Expr* c1 = ((CExpr*)c->followDefs())->kids[1];
- Expr* c2 = ((CExpr*)c->followDefs())->kids[2];
- pol->inc();
- Expr* e21 = pol->followDefs()->get_head();
- Expr* e22;
- e22 = e_ff;
- e22->inc();
- Expr* e23;
- e23 = e_tt;
- e23->inc();
- if( e21==e22 ){
- Expr* e24;
- pol->inc();
- c1->inc();
- e24 = f_simplify_clause_h( pol, c1 );
- pol->dec();
- c1->dec();
- Expr* e25;
- pol->inc();
- c2->inc();
- e25 = f_simplify_clause_h( pol, c2 );
- pol->dec();
- c2->dec();
- static Expr* e26;
- e26 = e_concat;
- e26->inc();
- e0 = new CExpr( APP, e26, e24, e25 );
- }else if( e21==e23 ){
- Expr* e27;
- pol->inc();
- c1->inc();
- e27 = f_simplify_clause_h( pol, c1 );
- pol->dec();
- c1->dec();
- Expr* e28;
- pol->inc();
- c2->inc();
- e28 = f_simplify_clause_h( pol, c2 );
- pol->dec();
- c2->dec();
- e0 = f_append( e27, e28 );
- e27->dec();
- e28->dec();
- }else{
- std::cout << "Could not find match for expression in function f_simplify_clause_h ";
- e21->print( std::cout );
- std::cout << std::endl;
- exit( 1 );
- }
- pol->dec();
- e22->dec();
- e23->dec();
- }else if( e1==e5 ){
- Expr* l = ((CExpr*)c->followDefs())->kids[1];
- Expr* c1 = ((CExpr*)c->followDefs())->kids[2];
- Expr* e29;
- Expr* e30;
- l->inc();
- e30 = f_litpol( l );
- l->dec();
- pol->inc();
- e29 = f_iffb( e30, pol );
- e30->dec();
- pol->dec();
- Expr* e31 = e29->followDefs()->get_head();
- Expr* e32;
- e32 = e_ff;
- e32->inc();
- Expr* e33;
- e33 = e_tt;
- e33->inc();
- if( e31==e32 ){
- l->inc();
- Expr* e34;
- pol->inc();
- c1->inc();
- e34 = f_simplify_clause_h( pol, c1 );
- pol->dec();
- c1->dec();
- static Expr* e35;
- e35 = e_clr;
- e35->inc();
- e0 = new CExpr( APP, e35, l, e34 );
- }else if( e31==e33 ){
- Expr* v;
- l->inc();
- v = f_litvar( l );
- l->dec();
- Expr* m;
- v->inc();
- if ( ((SymExpr*)v->followDefs())->getmark(0)){
- m = e_tt;
- m->inc();
- }else{
- Expr* e36;
- v->inc();
- if ( ((SymExpr*)v->followDefs())->getmark(0))
- ((SymExpr*)v->followDefs())->clearmark(0);
- else
- ((SymExpr*)v->followDefs())->setmark(0);
- e36 = v;
- e36->inc();
- v->dec();
- e36->dec();
- m = e_ff;
- m->inc();
- }
- v->dec();
- Expr* ch;
- pol->inc();
- c1->inc();
- ch = f_simplify_clause_h( pol, c1 );
- pol->dec();
- c1->dec();
- v->inc();
- if ( ((SymExpr*)v->followDefs())->getmark(1)){
- m->inc();
- Expr* e37 = m->followDefs()->get_head();
- Expr* e38;
- e38 = e_tt;
- e38->inc();
- Expr* e39;
- e39 = e_ff;
- e39->inc();
- if( e37==e38 ){
- e0 = ch;
- e0->inc();
- }else if( e37==e39 ){
- Expr* e40;
- Expr* e41;
- v->inc();
- if ( ((SymExpr*)v->followDefs())->getmark(1))
- ((SymExpr*)v->followDefs())->clearmark(1);
- else
- ((SymExpr*)v->followDefs())->setmark(1);
- e41 = v;
- e41->inc();
- v->dec();
- e41->dec();
- v->inc();
- if ( ((SymExpr*)v->followDefs())->getmark(0))
- ((SymExpr*)v->followDefs())->clearmark(0);
- else
- ((SymExpr*)v->followDefs())->setmark(0);
- e40 = v;
- e40->inc();
- v->dec();
- e40->dec();
- e0 = ch;
- e0->inc();
- }else{
- std::cout << "Could not find match for expression in function f_simplify_clause_h ";
- e37->print( std::cout );
- std::cout << std::endl;
- exit( 1 );
- }
- m->dec();
- e38->dec();
- e39->dec();
- }else{
- e0 = NULL;
- }
- v->dec();
- ch->dec();
- m->dec();
- v->dec();
- }else{
- std::cout << "Could not find match for expression in function f_simplify_clause_h ";
- e31->print( std::cout );
- std::cout << std::endl;
- exit( 1 );
- }
- e29->dec();
- e32->dec();
- e33->dec();
- }else{
- std::cout << "Could not find match for expression in function f_simplify_clause_h ";
- e1->print( std::cout );
- std::cout << std::endl;
- exit( 1 );
- }
- c->dec();
- e2->dec();
- e3->dec();
- e4->dec();
- e5->dec();
- return e0;
+Expr* run_compiled_scc( Expr* p, std::vector< Expr* >& args ){
+ return NULL;
}
-Expr* f_simplify_clause( Expr* c ){
- Expr* e0;
- static Expr* e1;
- e1 = e_tt;
- e1->inc();
- Expr* e2;
- static Expr* e3;
- e3 = e_ff;
- e3->inc();
- c->inc();
- e2 = f_simplify_clause_h( e3, c );
- e3->dec();
- c->dec();
- e0 = f_simplify_clause_h( e1, e2 );
- e1->dec();
- e2->dec();
- return e0;
-}
diff --git a/proofs/lfsc_checker/scccode.h b/proofs/lfsc_checker/scccode.h
index 6f5efc8b5..2ab549c10 100644
--- a/proofs/lfsc_checker/scccode.h
+++ b/proofs/lfsc_checker/scccode.h
@@ -7,21 +7,5 @@ void init_compiled_scc();
Expr* run_compiled_scc( Expr* p, std::vector< Expr* >& args );
-inline Expr* f_litvar( Expr* l );
-
-inline Expr* f_litpol( Expr* l );
-
-inline Expr* f_notb( Expr* b );
-
-inline Expr* f_iffb( Expr* b1, Expr* b2 );
-
-inline Expr* f_clear_mark( Expr* v );
-
-inline Expr* f_append( Expr* c1, Expr* c2 );
-
-inline Expr* f_simplify_clause_h( Expr* pol, Expr* c );
-
-inline Expr* f_simplify_clause( Expr* c );
-
#endif
diff --git a/proofs/lfsc_checker/sccwriter.cpp b/proofs/lfsc_checker/sccwriter.cpp
index 5c1da2a3f..d93341ab8 100644
--- a/proofs/lfsc_checker/sccwriter.cpp
+++ b/proofs/lfsc_checker/sccwriter.cpp
@@ -286,7 +286,7 @@ void sccwriter::write_code( Expr* code, std::ostream& os, int ind, const char* r
{
indent( os, ind );
os << retModString.c_str();
- os << "new IntExpr( " << mpz_get_si( ((IntExpr*)code)->n ) << " );" << std::endl;
+ os << "new IntExpr( (signed long int)" << mpz_get_si( ((IntExpr*)code)->n ) << " );" << std::endl;
indent( os, ind );
os << incString.c_str() << std::endl;
}
@@ -527,7 +527,7 @@ void sccwriter::write_code( Expr* code, std::ostream& os, int ind, const char* r
indent( os, ind );
os << "Expr* ";
write_variable( ((SymSExpr*)((CExpr*)code)->kids[0])->s, os );
- os << ";" << std::endl;
+ os << " = NULL;" << std::endl;
std::ostringstream ss;
write_variable( ((SymSExpr*)((CExpr*)code)->kids[0])->s, ss );
write_code( ((CExpr*)code)->kids[1], os, ind, ss.str().c_str() );
@@ -841,7 +841,7 @@ void sccwriter::write_expr( Expr* code, std::ostream& os, int ind, std::string&
{
os << "static ";
}
- os << "Expr* " << ss.str().c_str() << ";" << std::endl;
+ os << "Expr* " << ss.str().c_str() << " = NULL;" << std::endl;
//write the expression
std::ostringstream ss2;
ss2 << ss.str().c_str();
diff --git a/proofs/signatures/Makefile.am b/proofs/signatures/Makefile.am
index 2b6d16cfd..5947ad3f0 100644
--- a/proofs/signatures/Makefile.am
+++ b/proofs/signatures/Makefile.am
@@ -3,7 +3,8 @@
# add support for more theories, just list them here in the same order
# you would to the LFSC proof-checker binary.
#
-CORE_PLFS = sat.plf smt.plf th_base.plf th_arrays.plf th_bv.plf th_bv_bitblast.plf th_real.plf th_int.plf
+
+CORE_PLFS = sat.plf smt.plf th_base.plf th_arrays.plf th_bv.plf th_bv_bitblast.plf th_bv_rewrites.plf th_real.plf th_int.plf
noinst_LTLIBRARIES = libsignatures.la
diff --git a/proofs/signatures/th_arrays.plf b/proofs/signatures/th_arrays.plf
index 5ed3d2f6f..b54a4ed5b 100755
--- a/proofs/signatures/th_arrays.plf
+++ b/proofs/signatures/th_arrays.plf
@@ -60,4 +60,4 @@
(! u1 (! k (term s1)
(! u2 (th_holds (or (= _ t1 t2) (not (= _ (apply _ _ (apply _ _ (read s1 s2) t1) k) (apply _ _ (apply _ _ (read s1 s2) t2) k)))))
(holds cln)))
- (holds cln)))))))
+ (holds cln))))))) \ No newline at end of file
diff --git a/proofs/signatures/th_bv.plf b/proofs/signatures/th_bv.plf
index c93541085..6012e052a 100644
--- a/proofs/signatures/th_bv.plf
+++ b/proofs/signatures/th_bv.plf
@@ -8,7 +8,7 @@
(program mp_ispos ((x mpz)) formula
(mp_ifneg x false true))
-
+
(program mpz_eq ((x mpz) (y mpz)) formula
(mp_ifzero (mpz_sub x y) true false))
@@ -21,7 +21,7 @@
(program mpz_ ((x mpz) (y mpz)) formula
(mp_ifzero (mpz_sub x y) true false))
-
+
; "bitvec" is a term of type "sort"
; (declare BitVec sort)
(declare BitVec (!n mpz sort))
@@ -37,7 +37,7 @@
(declare bvc (! b bit (! v bv bv)))
; calculate the length of a bitvector
-;; (program bv_len ((v bv)) mpz
+;; (program bv_len ((v bv)) mpz
;; (match v
;; (bvn 0)
;; ((bvc b v') (mp_add (bv_len v') 1))))
@@ -48,7 +48,26 @@
(! n mpz
(! v bv
(term (BitVec n)))))
-
+
+(program bv_constants_are_disequal ((x bv) (y bv)) formula
+ (match x
+ (bvn (fail formula))
+ ((bvc bx x')
+ (match y
+ (bvn (fail formula))
+ ((bvc by y') (match bx
+ (b0 (match by (b0 (bv_constants_are_disequal x' y')) (b1 (true))))
+ (b1 (match by (b0 (true)) (b1 (bv_constants_are_disequal x' y'))))
+ ))
+ ))
+))
+
+(declare bv_disequal_constants
+ (! n mpz
+ (! x bv
+ (! y bv
+ (! c (^ (bv_constants_are_disequal x y) true)
+ (th_holds (not (= (BitVec n) (a_bv n x) (a_bv n y)))))))))
; a bv variable
(declare var_bv type)
@@ -61,7 +80,7 @@
; bit vector binary operators
(define bvop2
(! n mpz
- (! x (term (BitVec n))
+ (! x (term (BitVec n))
(! y (term (BitVec n))
(term (BitVec n))))))
@@ -88,7 +107,7 @@
; bit vector unary operators
(define bvop1
(! n mpz
- (! x (term (BitVec n))
+ (! x (term (BitVec n))
(term (BitVec n)))))
@@ -111,8 +130,8 @@
(! t1 (term (BitVec m))
(! t2 (term (BitVec m'))
(term (BitVec n))))))))
-
-;; side-condition fails in signature only??
+
+;; side-condition fails in signature only??
;; (! s (^ (mp_add m m') n)
;; (declare repeat bvopp)
@@ -147,22 +166,22 @@
(term (BitVec n)))))))
-
-;; TODO: add checks for valid typing for these operators
+
+;; TODO: add checks for valid typing for these operators
;; (! c1 (^ (mpz_lte i j)
;; (! c2 (^ (mpz_lt i n) true)
;; (! c3 (^ (mp_ifneg i false true) true)
-;; (! c4 (^ (mp_ifneg j false true) true)
+;; (! c4 (^ (mp_ifneg j false true) true)
;; (! s (^ (mp_add (mpz_sub i j) 1) m)
-
+
; bit vector predicates
(define bvpred
(! n mpz
(! x (term (BitVec n))
(! y (term (BitVec n))
formula))))
-
+
(declare bvult bvpred)
(declare bvule bvpred)
(declare bvugt bvpred)
@@ -171,4 +190,3 @@
(declare bvsle bvpred)
(declare bvsgt bvpred)
(declare bvsge bvpred)
-
diff --git a/proofs/signatures/th_bv_bitblast.plf b/proofs/signatures/th_bv_bitblast.plf
index 8e8c51857..3cc1ec296 100644
--- a/proofs/signatures/th_bv_bitblast.plf
+++ b/proofs/signatures/th_bv_bitblast.plf
@@ -4,7 +4,7 @@
(declare bbltc (! f formula (! v bblt bblt)))
; calculate the length of a bit-blasted term
-(program bblt_len ((v bblt)) mpz
+(program bblt_len ((v bblt)) mpz
(match v
(bbltn 0)
((bbltc b v') (mp_add (bblt_len v') 1))))
@@ -25,6 +25,7 @@
(bblast_term n x y)))))
+; Binds a symbol to the bblast_term to be used later on.
(declare decl_bblast
(! n mpz
(! b bblt
@@ -34,6 +35,16 @@
(! u (! v (bblast_term n t b) (holds cln))
(holds cln))))))))
+(declare decl_bblast_with_alias
+ (! n mpz
+ (! b bblt
+ (! t (term (BitVec n))
+ (! a (term (BitVec n))
+ (! bb (bblast_term n t b)
+ (! e (th_holds (= _ t a))
+ (! s (^ (bblt_len b) n)
+ (! u (! v (bblast_term n a b) (holds cln))
+ (holds cln))))))))))
; a predicate to represent the n^th bit of a bitvector term
(declare bitof
@@ -46,31 +57,31 @@
;; BITBLASTING RULES
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; BITBLAST CONSTANT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(program bblast_const ((v bv) (n mpz)) bblt
- (mp_ifneg n (match v (bvn bbltn)
+ (mp_ifneg n (match v (bvn bbltn)
(default (fail bblt)))
(match v ((bvc b v') (bbltc (match b (b0 false) (b1 true)) (bblast_const v' (mp_add n (~ 1)))))
(default (fail bblt)))))
-
+
(declare bv_bbl_const (! n mpz
(! f bblt
(! v bv
(! c (^ (bblast_const v (mp_add n (~ 1))) f)
(bblast_term n (a_bv n v) f))))))
-
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; BITBLAST VARIABLE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(program bblast_var ((x var_bv) (n mpz)) bblt
- (mp_ifneg n bbltn
+ (mp_ifneg n bbltn
(bbltc (bitof x n) (bblast_var x (mp_add n (~ 1))))))
(declare bv_bbl_var (! n mpz
@@ -79,18 +90,16 @@
(! c (^ (bblast_var x (mp_add n (~ 1))) f)
(bblast_term n (a_var_bv n x) f))))))
-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; BITBLAST CONCAT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(program bblast_concat ((x bblt) (y bblt)) bblt
- (match x
+ (match x
(bbltn (match y ((bbltc by y') (bbltc by (bblast_concat x y')))
(bbltn bbltn)))
((bbltc bx x') (bbltc bx (bblast_concat x' y)))))
-
-
+
(declare bv_bbl_concat (! n mpz
(! m mpz
(! m1 mpz
@@ -104,36 +113,34 @@
(! c (^ (bblast_concat xb yb ) rb)
(bblast_term n (concat n m m1 x y) rb)))))))))))))
-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; BITBLAST EXTRACT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(program bblast_extract_rec ((x bblt) (i mpz) (j mpz) (n mpz)) bblt
- (match x
+ (match x
((bbltc bx x') (mp_ifneg (mpz_sub (mpz_sub j n) 1)
(mp_ifneg (mpz_sub (mpz_sub n i) 1)
(bbltc bx (bblast_extract_rec x' i j (mpz_sub n 1)))
(bblast_extract_rec x' i j (mpz_sub n 1)))
-
+
bbltn))
(bbltn bbltn)))
(program bblast_extract ((x bblt) (i mpz) (j mpz) (n mpz)) bblt
- (bblast_extract_rec x i j (mpz_sub n 1)))
+ (bblast_extract_rec x i j (mpz_sub n 1)))
(declare bv_bbl_extract (! n mpz
(! i mpz
(! j mpz
(! m mpz
- (! x (term (BitVec m))
+ (! x (term (BitVec m))
(! xb bblt
(! rb bblt
(! xbb (bblast_term m x xb)
(! c ( ^ (bblast_extract xb i j m) rb)
(bblast_term n (extract n i j m x) rb)))))))))))
-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; BITBLAST ZERO/SIGN EXTEND
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -148,42 +155,38 @@
(declare bv_bbl_zero_extend (! n mpz
(! k mpz
(! m mpz
- (! x (term (BitVec m))
+ (! x (term (BitVec m))
(! xb bblt
(! rb bblt
(! xbb (bblast_term m x xb)
(! c ( ^ (bblast_zextend xb k m) rb)
(bblast_term n (zero_extend n k m x) rb))))))))))
-
(program bblast_sextend ((x bblt) (i mpz)) bblt
(match x (bbltn (fail bblt))
- ((bbltc xb x') (extend_rec x (mpz_sub i 1) xb))))
+ ((bbltc xb x') (extend_rec x (mpz_sub i 1) xb))))
(declare bv_bbl_sign_extend (! n mpz
(! k mpz
(! m mpz
- (! x (term (BitVec m))
+ (! x (term (BitVec m))
(! xb bblt
(! rb bblt
(! xbb (bblast_term m x xb)
(! c ( ^ (bblast_sextend xb k m) rb)
(bblast_term n (sign_extend n k m x) rb))))))))))
-
-
-
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; BITBLAST BVAND
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
+
(program bblast_bvand ((x bblt) (y bblt)) bblt
- (match x
+ (match x
(bbltn (match y (bbltn bbltn) (default (fail bblt))))
- ((bbltc bx x') (match y
+ ((bbltc bx x') (match y
(bbltn (fail bblt))
((bbltc by y') (bbltc (and bx by) (bblast_bvand x' y')))))))
-
-
+
(declare bv_bbl_bvand (! n mpz
(! x (term (BitVec n))
(! y (term (BitVec n))
@@ -199,11 +202,10 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(program bblast_bvnot ((x bblt)) bblt
- (match x
- (bbltn bbltn)
+ (match x
+ (bbltn bbltn)
((bbltc bx x') (bbltc (not bx) (bblast_bvnot x')))))
-
-
+
(declare bv_bbl_bvnot (! n mpz
(! x (term (BitVec n))
(! xb bblt
@@ -215,15 +217,14 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; BITBLAST BVOR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
+
(program bblast_bvor ((x bblt) (y bblt)) bblt
- (match x
+ (match x
(bbltn (match y (bbltn bbltn) (default (fail bblt))))
- ((bbltc bx x') (match y
+ ((bbltc bx x') (match y
(bbltn (fail bblt))
((bbltc by y') (bbltc (or bx by) (bblast_bvor x' y')))))))
-
-
+
(declare bv_bbl_bvor (! n mpz
(! x (term (BitVec n))
(! y (term (BitVec n))
@@ -238,15 +239,14 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; BITBLAST BVXOR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
+
(program bblast_bvxor ((x bblt) (y bblt)) bblt
- (match x
+ (match x
(bbltn (match y (bbltn bbltn) (default (fail bblt))))
- ((bbltc bx x') (match y
+ ((bbltc bx x') (match y
(bbltn (fail bblt))
((bbltc by y') (bbltc (xor bx by) (bblast_bvxor x' y')))))))
-
-
+
(declare bv_bbl_bvxor (! n mpz
(! x (term (BitVec n))
(! y (term (BitVec n))
@@ -262,8 +262,8 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; BITBLAST BVADD
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; return the carry bit after adding x y
+
+;; return the carry bit after adding x y
;; FIXME: not the most efficient thing in the world
(program bblast_bvadd_carry ((a bblt) (b bblt) (carry formula)) formula
(match a
@@ -272,7 +272,7 @@
(bbltn (fail formula))
((bbltc bi b') (or (and ai bi) (and (xor ai bi) (bblast_bvadd_carry a' b' carry))))))))
-;; ripple carry adder where carry is the initial carry bit
+;; ripple carry adder where carry is the initial carry bit
(program bblast_bvadd ((a bblt) (b bblt) (carry formula)) bblt
(match a
( bbltn (match b (bbltn bbltn) (default (fail bblt))))
@@ -280,8 +280,35 @@
(bbltn (fail bblt))
((bbltc bi b') (bbltc (xor (xor ai bi) (bblast_bvadd_carry a' b' carry))
(bblast_bvadd a' b' carry)))))))
-
-
+
+
+(program reverse_help ((x bblt) (acc bblt)) bblt
+(match x
+ (bbltn acc)
+ ((bbltc xi x') (reverse_help x' (bbltc xi acc)))))
+
+
+(program reverseb ((x bblt)) bblt
+ (reverse_help x bbltn))
+
+
+; AJR: use this version?
+;(program bblast_bvadd_2h ((a bblt) (b bblt) (carry formula)) bblt
+;(match a
+; ( bbltn (match b (bbltn bbltn) (default (fail bblt))))
+; ((bbltc ai a') (match b
+; (bbltn (fail bblt))
+; ((bbltc bi b')
+; (let carry' (or (and ai bi) (and (xor ai bi) carry))
+; (bbltc (xor (xor ai bi) carry)
+; (bblast_bvadd_2h a' b' carry'))))))))
+
+;(program bblast_bvadd_2 ((a bblt) (b bblt) (carry formula)) bblt
+;(let ar (reverseb a) ;; reverse a and b so that we can build the circuit
+;(let br (reverseb b) ;; from the least significant bit up
+;(let ret (bblast_bvadd_2h ar br carry)
+; (reverseb ret)))))
+
(declare bv_bbl_bvadd (! n mpz
(! x (term (BitVec n))
(! y (term (BitVec n))
@@ -293,7 +320,6 @@
(! c (^ (bblast_bvadd xb yb false) rb)
(bblast_term n (bvadd n x y) rb)))))))))))
-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; BITBLAST BVNEG
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -304,8 +330,8 @@
(program bblast_bvneg ((x bblt) (n mpz)) bblt
(bblast_bvadd (bblast_bvnot x) (bblast_zero n) true))
-
-
+
+
(declare bv_bbl_bvneg (! n mpz
(! x (term (BitVec n))
(! xb bblt
@@ -319,23 +345,14 @@
;; BITBLAST BVMUL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; shift add multiplier
-
-(program reverse_help ((x bblt) (acc bblt)) bblt
-(match x
- (bbltn acc)
- ((bbltc xi x') (reverse_help x' (bbltc xi acc)))))
-
-(program reverseb ((x bblt)) bblt
- (reverse_help x bbltn))
+;; shift add multiplier
;; (program concat ((a bblt) (b bblt)) bblt
;; (match a (bbltn b)
;; ((bbltc ai a') (bbltc ai (concat a' b)))))
-
+
(program top_k_bits ((a bblt) (k mpz)) bblt
(mp_ifzero k bbltn
(match a (bbltn (fail bblt))
@@ -344,7 +361,7 @@
(program bottom_k_bits ((a bblt) (k mpz)) bblt
(reverseb (top_k_bits (reverseb a) k)))
-;; assumes the least signigicant bit is at the beginning of the list
+;; assumes the least signigicant bit is at the beginning of the list
(program k_bit ((a bblt) (k mpz)) formula
(mp_ifneg k (fail formula)
(match a (bbltn (fail formula))
@@ -353,7 +370,7 @@
(program and_with_bit ((a bblt) (bt formula)) bblt
(match a (bbltn bbltn)
((bbltc ai a') (bbltc (and bt ai) (and_with_bit a' bt)))))
-
+
;; a is going to be the current result
;; carry is going to be false initially
;; b is the and of a and b[k]
@@ -377,19 +394,19 @@
(let ak (top_k_bits a k')
(let b' (and_with_bit ak (k_bit b k))
(mp_ifzero (mpz_sub k' 1)
- (mult_step_k_h res b' bbltn false k)
+ (mult_step_k_h res b' bbltn false k)
(let res' (mult_step_k_h res b' bbltn false k)
(mult_step a b (reverseb res') n (mp_add k 1))))))))
(program bblast_bvmul ((a bblt) (b bblt) (n mpz)) bblt
-(let ar (reverseb a) ;; reverse a and b so that we can build the circuit
+(let ar (reverseb a) ;; reverse a and b so that we can build the circuit
(let br (reverseb b) ;; from the least significant bit up
(let res (and_with_bit ar (k_bit br 0))
- (mp_ifzero (mpz_sub n 1) ;; if multiplying 1 bit numbers no need to call mult_step
+ (mp_ifzero (mpz_sub n 1) ;; if multiplying 1 bit numbers no need to call mult_step
res
(mult_step ar br res n 1))))))
-
+
(declare bv_bbl_bvmul (! n mpz
(! x (term (BitVec n))
(! y (term (BitVec n))
@@ -402,18 +419,18 @@
(bblast_term n (bvmul n x y) rb)))))))))))
-
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; BITBLAST EQUALS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
+
; bit blast x = y
; for x,y of size n, it will return a conjuction (x.0 = y.0 ^ ( ... ^ (x.{n-1} = y.{n-1})))
; f is the accumulator formula that builds the equality in the right order
(program bblast_eq_rec ((x bblt) (y bblt) (f formula)) formula
- (match x
+ (match x
(bbltn (match y (bbltn f) (default (fail formula))))
- ((bbltc fx x') (match y
+ ((bbltc fx x') (match y
(bbltn (fail formula))
((bbltc fy y') (bblast_eq_rec x' y' (and (iff fx fy) f)))))
(default (fail formula))))
@@ -423,7 +440,23 @@
((bbltc bx x') (match y ((bbltc by y') (bblast_eq_rec x' y' (iff bx by)))
(default (fail formula))))
(default (fail formula))))
-
+
+
+;; TODO: a temporary bypass for rewrites that we don't support yet. As soon
+;; as we do, remove this rule.
+
+(declare bv_bbl_=_false
+ (! n mpz
+ (! x (term (BitVec n))
+ (! y (term (BitVec n))
+ (! bx bblt
+ (! by bblt
+ (! f formula
+ (! bbx (bblast_term n x bx)
+ (! bby (bblast_term n y by)
+ (! c (^ (bblast_eq bx by) f)
+ (th_holds (iff (= (BitVec n) x y) false))))))))))))
+
(declare bv_bbl_=
(! n mpz
(! x (term (BitVec n))
@@ -436,11 +469,22 @@
(! c (^ (bblast_eq bx by) f)
(th_holds (iff (= (BitVec n) x y) f))))))))))))
-
+(declare bv_bbl_=_swap
+ (! n mpz
+ (! x (term (BitVec n))
+ (! y (term (BitVec n))
+ (! bx bblt
+ (! by bblt
+ (! f formula
+ (! bbx (bblast_term n x bx)
+ (! bby (bblast_term n y by)
+ (! c (^ (bblast_eq by bx) f)
+ (th_holds (iff (= (BitVec n) x y) f))))))))))))
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; BITBLAST BVULT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
+
(program bblast_bvult ((x bblt) (y bblt) (n mpz)) formula
(match x
( bbltn (fail formula))
@@ -465,7 +509,7 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; BITBLAST BVSLT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
+
(program bblast_bvslt ((x bblt) (y bblt) (n mpz)) formula
(match x
( bbltn (fail formula))
@@ -488,7 +532,6 @@
(! bby (bblast_term n y by)
(! c (^ (bblast_bvslt bx by n) f)
(th_holds (iff (bvslt n x y) f))))))))))))
-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
@@ -525,8 +568,8 @@
;; REWRITE RULES
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
+
+
; rewrite rule :
; x + y = y + x
(declare bvadd_symm
@@ -534,7 +577,7 @@
(! x (term (BitVec n))
(! y (term (BitVec n))
(th_holds (= (BitVec n) (bvadd _ x y) (bvadd _ y x)))))))
-
+
;; (declare bvcrazy_rewrite
;; (! n mpz
;; (! x (term (BitVec n))
@@ -546,12 +589,12 @@
;; (! s (^ (rewrite_scc xn yn) true)
;; (! u (! x (term (BitVec n)) (holds cln))
;; (holds cln)))))))))))
-
+
;; (th_holds (= (BitVec n) (bvadd x y) (bvadd y x)))))))
-
-
-; necessary?
+
+
+; necessary?
;; (program calc_bvand ((a bv) (b bv)) bv
;; (match a
;; (bvn (match b (bvn bvn) (default (fail bv))))
@@ -560,7 +603,7 @@
;; (default (fail bv))))))
;; ; rewrite rule (w constants) :
-;; ; a & b = c
+;; ; a & b = c
;; (declare bvand_const (! c bv
;; (! a bv
;; (! b bv
@@ -568,7 +611,7 @@
;; (th_holds (= BitVec (bvand (a_bv a) (a_bv b)) (a_bv c))))))))
-;; making constant bit-vectors
+;; making constant bit-vectors
(program mk_ones ((n mpz)) bv
(mp_ifzero n bvn (bvc b1 (mk_ones (mpz_sub n 1)))))
@@ -576,7 +619,7 @@
(mp_ifzero n bvn (bvc b0 (mk_ones (mpz_sub n 1)))))
-
+
;; (bvxnor a b) => (bvnot (bvxor a b))
;; (declare bvxnor_elim
;; (! n mpz
@@ -603,7 +646,7 @@
;; (! rwb (rw_term _ b (a_bv _ zero_bits))
;; (rw_term _ (bvxor _ a b)
;; a'))))))))))
-
+
;; ;; (bvxor a 11) => (bvnot a)
;; (declare bvxor_one
;; (! n mpz
@@ -617,7 +660,7 @@
;; (rw_term _ (bvxor _ a b)
;; (bvnot _ a')))))))))))
-
+
;; ;; (bvnot (bvnot a)) => a
;; (declare bvnot_idemp
;; (! n mpz
@@ -626,4 +669,3 @@
;; (! rwa (rw_term _ a a')
;; (rw_term _ (bvnot _ (bvnot _ a))
;; a'))))))
-
diff --git a/proofs/signatures/th_bv_rewrites.plf b/proofs/signatures/th_bv_rewrites.plf
new file mode 100644
index 000000000..bf5dea9e9
--- /dev/null
+++ b/proofs/signatures/th_bv_rewrites.plf
@@ -0,0 +1,22 @@
+;
+; Equality swap
+;
+
+(declare rr_bv_eq
+ (! n mpz
+ (! t1 (term (BitVec n))
+ (! t2 (term (BitVec n))
+ (th_holds (iff (= (BitVec n) t2 t1) (= (BitVec n) t1 t2)))))))
+
+;
+; Additional rules...
+;
+
+;
+; Default, if nothing else applied
+;
+
+(declare rr_bv_default
+ (! t1 formula
+ (! t2 formula
+ (th_holds (iff t1 t2))))))
diff --git a/proofs/signatures/th_quant.plf b/proofs/signatures/th_quant.plf
index d85b2115c..e212f835d 100755
--- a/proofs/signatures/th_quant.plf
+++ b/proofs/signatures/th_quant.plf
@@ -14,10 +14,7 @@
(match ti
((apply si1 si2 ti1 ti2) (match (is_inst_t ti1 t1 k) (tt (is_inst_t ti2 t2 k)) (ff ff)))
(default ff)))
- (default
- (match ti
- ((apply si1 si2 ti1 ti2) ff)
- (default (eqterm ti (ifmarked t k t)))))))
+ (default (eqterm ti (ifmarked t k t)))))
(program is_inst_f ((fi formula) (f formula) (k term)) bool
(match f
diff --git a/src/Makefile.am b/src/Makefile.am
index 3ffda9f28..0e3f4823b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -96,10 +96,14 @@ libcvc4_la_SOURCES = \
proof/skolemization_manager.h \
proof/theory_proof.cpp \
proof/theory_proof.h \
+ proof/lemma_proof.cpp \
+ proof/lemma_proof.h \
proof/uf_proof.cpp \
proof/uf_proof.h \
proof/unsat_core.cpp \
proof/unsat_core.h \
+ proof/proof_output_channel.cpp \
+ proof/proof_output_channel.h \
prop/cnf_stream.cpp \
prop/cnf_stream.h \
prop/prop_engine.cpp \
@@ -109,6 +113,8 @@ libcvc4_la_SOURCES = \
prop/sat_solver_factory.cpp \
prop/sat_solver_factory.h \
prop/sat_solver_types.h \
+ prop/cryptominisat.h \
+ prop/cryptominisat.cpp \
prop/theory_proxy.cpp \
prop/theory_proxy.h \
smt/boolean_terms.cpp \
@@ -443,7 +449,12 @@ libcvc4_la_SOURCES = \
theory/fp/theory_fp.cpp \
theory/fp/theory_fp_rewriter.h \
theory/fp/theory_fp_rewriter.cpp \
- theory/fp/theory_fp_type_rules.h
+ theory/fp/theory_fp_type_rules.h \
+ theory/sep/theory_sep.h \
+ theory/sep/theory_sep.cpp \
+ theory/sep/theory_sep_rewriter.h \
+ theory/sep/theory_sep_rewriter.cpp \
+ theory/sep/theory_sep_type_rules.h
nodist_libcvc4_la_SOURCES = \
theory/rewriter_tables.h \
@@ -477,6 +488,12 @@ libcvc4_la_LIBADD += $(ABC_LIBS)
libcvc4_la_LDFLAGS += $(ABC_LDFLAGS)
endif
+if CVC4_USE_CRYPTOMINISAT
+libcvc4_la_LIBADD += $(CRYPTOMINISAT_LIBS)
+libcvc4_la_LDFLAGS += $(CRYPTOMINISAT_LDFLAGS)
+endif
+
+
BUILT_SOURCES = \
theory/rewriter_tables.h \
theory/theory_traits.h \
@@ -526,6 +543,7 @@ EXTRA_DIST = \
theory/mktheorytraits \
theory/quantifiers/kinds \
theory/rewriter_tables_template.h \
+ theory/sep/kinds \
theory/sets/kinds \
theory/strings/kinds \
theory/theory_traits_template.h \
diff --git a/src/Makefile.theories b/src/Makefile.theories
index 8b5cef4d5..003128a3c 100644
--- a/src/Makefile.theories
+++ b/src/Makefile.theories
@@ -1,3 +1,3 @@
-THEORIES = builtin booleans uf arith bv fp arrays datatypes sets strings quantifiers idl
+THEORIES = builtin booleans uf arith bv fp arrays datatypes sets sep strings quantifiers idl
diff --git a/src/base/configuration.cpp b/src/base/configuration.cpp
index ce8967a18..db19469fd 100644
--- a/src/base/configuration.cpp
+++ b/src/base/configuration.cpp
@@ -134,6 +134,10 @@ bool Configuration::isBuiltWithAbc() {
return IS_ABC_BUILD;
}
+bool Configuration::isBuiltWithCryptominisat() {
+ return IS_CRYPTOMINISAT_BUILD;
+}
+
bool Configuration::isBuiltWithReadline() {
return IS_READLINE_BUILD;
}
diff --git a/src/base/configuration.h b/src/base/configuration.h
index 498337c4c..5d499174f 100644
--- a/src/base/configuration.h
+++ b/src/base/configuration.h
@@ -93,6 +93,8 @@ public:
static bool isBuiltWithAbc();
+ static bool isBuiltWithCryptominisat();
+
static bool isBuiltWithReadline();
static bool isBuiltWithCudd();
diff --git a/src/base/configuration_private.h b/src/base/configuration_private.h
index 74ce00bdf..f0ef1a795 100644
--- a/src/base/configuration_private.h
+++ b/src/base/configuration_private.h
@@ -114,6 +114,12 @@ namespace CVC4 {
# define IS_ABC_BUILD false
#endif /* CVC4_USE_ABC */
+#if CVC4_USE_CRYPTOMINISAT
+# define IS_CRYPTOMINISAT_BUILD true
+#else /* CVC4_USE_CRYPTOMINISAT */
+# define IS_CRYPTOMINISAT_BUILD false
+#endif /* CVC4_USE_CRYPTOMINISAT */
+
#ifdef HAVE_LIBREADLINE
# define IS_READLINE_BUILD true
#else /* HAVE_LIBREADLINE */
diff --git a/src/context/cdhashmap.h b/src/context/cdhashmap.h
index d080da333..884234eb8 100644
--- a/src/context/cdhashmap.h
+++ b/src/context/cdhashmap.h
@@ -163,7 +163,7 @@ class CDOhash_map : public ContextObj {
d_data = p->d_data;
}
}
- // Explicitly call destructors fro the key and the date as they will not
+ // Explicitly call destructors for the key and the date as they will not
// otherwise get called.
p->d_key.~Key();
p->d_data.~Data();
@@ -478,18 +478,13 @@ public:
typename table_type::iterator i = d_map.find(k);
if(i != d_map.end()) {
Debug("gc") << "key " << k << " obliterated" << std::endl;
- // We can't call ->deleteSelf() here, because it calls the
- // ContextObj destructor, which calls CDOhash_map::destroy(), which
- // restore()'s, which puts the CDOhash_map on the trash, which causes
- // a double-delete.
- (*i).second->~Element();
- // Writing ...->~CDOhash_map() in the above is legal (?) but breaks
- // g++ 4.1, though later versions have no problem.
+ // Restore this object to level 0. If it was inserted after level 0,
+ // nothing else to do as restore will put it in the trash.
+ (*i).second->destroy();
+ // Check if object was inserted at level 0: in that case, still have
+ // to do some work.
typename table_type::iterator j = d_map.find(k);
- // This if() succeeds for objects inserted when in the
- // zero-scope: they were never save()'d there, so restore()
- // never gets a NULL map and so they leak.
if(j != d_map.end()) {
Element* elt = (*j).second;
if(d_first == elt) {
@@ -505,9 +500,8 @@ public:
}
d_map.erase(j);//FIXME multithreading
Debug("gc") << "key " << k << " obliterated zero-scope: " << elt << std::endl;
- // was already destructed, so don't call ->deleteSelf()
if(!elt->d_noTrash) {
- ::operator delete(elt);
+ elt->deleteSelf();
}
}
}
diff --git a/src/expr/Makefile.am b/src/expr/Makefile.am
index c04de4421..9dcbc3b4b 100644
--- a/src/expr/Makefile.am
+++ b/src/expr/Makefile.am
@@ -40,6 +40,8 @@ libexpr_la_SOURCES = \
pickle_data.h \
pickler.cpp \
pickler.h \
+ sepconst.cpp \
+ sepconst.h \
symbol_table.cpp \
symbol_table.h \
type.cpp \
diff --git a/src/expr/datatype.cpp b/src/expr/datatype.cpp
index d14ac26d4..12cab48cc 100644
--- a/src/expr/datatype.cpp
+++ b/src/expr/datatype.cpp
@@ -297,7 +297,7 @@ bool Datatype::isFinite() const throw(IllegalArgumentException) {
return true;
}
-bool Datatype::isUFinite() const throw(IllegalArgumentException) {
+bool Datatype::isInterpretedFinite() const throw(IllegalArgumentException) {
PrettyCheckArgument(isResolved(), this, "this datatype is not yet resolved");
// we're using some internals, so we have to set up this library context
ExprManagerScope ems(d_self);
@@ -310,7 +310,7 @@ bool Datatype::isUFinite() const throw(IllegalArgumentException) {
self.setAttribute(DatatypeUFiniteComputedAttr(), true);
self.setAttribute(DatatypeUFiniteAttr(), false);
for(const_iterator i = begin(), i_end = end(); i != i_end; ++i) {
- if(! (*i).isUFinite()) {
+ if(! (*i).isInterpretedFinite()) {
return false;
}
}
@@ -850,7 +850,7 @@ bool DatatypeConstructor::isFinite() const throw(IllegalArgumentException) {
return true;
}
-bool DatatypeConstructor::isUFinite() const throw(IllegalArgumentException) {
+bool DatatypeConstructor::isInterpretedFinite() const throw(IllegalArgumentException) {
PrettyCheckArgument(isResolved(), this, "this datatype constructor is not yet resolved");
// we're using some internals, so we have to set up this library context
ExprManagerScope ems(d_constructor);
@@ -861,16 +861,8 @@ bool DatatypeConstructor::isUFinite() const throw(IllegalArgumentException) {
}
bool success = true;
for(const_iterator i = begin(), i_end = end(); i != i_end; ++i) {
- Type t = (*i).getRangeType();
- if( t.isDatatype() ){
- const Datatype& dt = ((DatatypeType)t).getDatatype();
- if( !dt.isUFinite() ){
- success = false;
- }
- }else if(!t.isSort() && !t.getCardinality().isFinite()) {
- success = false;
- }
- if(!success ){
+ TypeNode t = TypeNode::fromType( (*i).getRangeType() );
+ if(!t.isInterpretedFinite()) {
self.setAttribute(DatatypeUFiniteComputedAttr(), true);
self.setAttribute(DatatypeUFiniteAttr(), false);
return false;
diff --git a/src/expr/datatype.h b/src/expr/datatype.h
index 1197b4a3b..a0c9cbe6b 100644
--- a/src/expr/datatype.h
+++ b/src/expr/datatype.h
@@ -342,7 +342,7 @@ public:
* uninterpreted sorts are finite. This function can
* only be called for resolved constructors.
*/
- bool isUFinite() const throw(IllegalArgumentException);
+ bool isInterpretedFinite() const throw(IllegalArgumentException);
/**
* Returns true iff this Datatype constructor has already been
@@ -613,6 +613,9 @@ public:
/** get the record representation for this datatype */
inline Record * getRecord() const;
+ /** get the record representation for this datatype */
+ inline Record * getRecord() const;
+
/**
* Return the cardinality of this datatype (the sum of the
* cardinalities of its constructors). The Datatype must be
@@ -634,7 +637,7 @@ public:
* datatype is not well-founded, this function returns false. The
* Datatype must be resolved or an exception is thrown.
*/
- bool isUFinite() const throw(IllegalArgumentException);
+ bool isInterpretedFinite() const throw(IllegalArgumentException);
/**
* Return true iff this datatype is well-founded (there exist ground
diff --git a/src/expr/expr_manager_template.cpp b/src/expr/expr_manager_template.cpp
index 84f674d2b..53e16751e 100644
--- a/src/expr/expr_manager_template.cpp
+++ b/src/expr/expr_manager_template.cpp
@@ -30,7 +30,7 @@ ${includes}
// compiler directs the user to the template file instead of the
// generated one. We don't want the user to modify the generated one,
// since it'll get overwritten on a later build.
-#line 33 "${template}"
+#line 34 "${template}"
#ifdef CVC4_STATISTICS_ON
#define INC_STAT(kind) \
@@ -941,6 +941,11 @@ Expr ExprManager::mkBoundVar(Type type) {
return Expr(this, d_nodeManager->mkBoundVarPtr(*type.d_typeNode));
}
+Expr ExprManager::mkSepNil(Type type) {
+ NodeManagerScope nms(d_nodeManager);
+ return Expr(this, d_nodeManager->mkSepNilPtr(*type.d_typeNode));
+}
+
Expr ExprManager::mkAssociative(Kind kind,
const std::vector<Expr>& children) {
PrettyCheckArgument(
diff --git a/src/expr/expr_manager_template.h b/src/expr/expr_manager_template.h
index 04f2f4289..9c4e554e1 100644
--- a/src/expr/expr_manager_template.h
+++ b/src/expr/expr_manager_template.h
@@ -124,6 +124,9 @@ public:
/** Get the type for regular expressions. */
RegExpType regExpType() const;
+ /** Get the type for regular expressions. */
+ RegExpType regExpType() const;
+
/** Get the type for reals. */
RealType realType() const;
@@ -545,6 +548,11 @@ public:
* @param type the type for the new bound variable
*/
Expr mkBoundVar(Type type);
+
+ /**
+ * Create a (nameless) new nil reference for separation logic of type
+ */
+ Expr mkSepNil(Type type);
/** Get a reference to the statistics registry for this ExprManager */
Statistics getStatistics() const throw();
diff --git a/src/expr/node_manager.cpp b/src/expr/node_manager.cpp
index 0809a0331..d2ac7e2a1 100644
--- a/src/expr/node_manager.cpp
+++ b/src/expr/node_manager.cpp
@@ -681,6 +681,20 @@ Node NodeManager::mkInstConstant(const TypeNode& type) {
return n;
}
+Node NodeManager::mkSepNil(const TypeNode& type) {
+ Node n = NodeBuilder<0>(this, kind::SEP_NIL);
+ n.setAttribute(TypeAttr(), type);
+ n.setAttribute(TypeCheckedAttr(), true);
+ return n;
+}
+
+Node* NodeManager::mkSepNilPtr(const TypeNode& type) {
+ Node* n = NodeBuilder<0>(this, kind::SEP_NIL).constructNodePtr();
+ setAttribute(*n, TypeAttr(), type);
+ setAttribute(*n, TypeCheckedAttr(), true);
+ return n;
+}
+
Node NodeManager::mkAbstractValue(const TypeNode& type) {
Node n = mkConst(AbstractValue(++d_abstractValueCount));
n.setAttribute(TypeAttr(), type);
diff --git a/src/expr/node_manager.h b/src/expr/node_manager.h
index 7d2b13e4c..dcd7005f8 100644
--- a/src/expr/node_manager.h
+++ b/src/expr/node_manager.h
@@ -332,7 +332,7 @@ class NodeManager {
/** Create a variable with the given type. */
Node mkVar(const TypeNode& type, uint32_t flags = ExprManager::VAR_FLAG_NONE);
Node* mkVarPtr(const TypeNode& type, uint32_t flags = ExprManager::VAR_FLAG_NONE);
-
+
public:
explicit NodeManager(ExprManager* exprManager);
@@ -486,6 +486,10 @@ public:
/** Create a instantiation constant with the given type. */
Node mkInstConstant(const TypeNode& type);
+
+ /** Create nil reference for separation logic with the given type. */
+ Node mkSepNil(const TypeNode& type);
+ Node* mkSepNilPtr(const TypeNode& type);
/** Make a new abstract value with the given type. */
Node mkAbstractValue(const TypeNode& type);
diff --git a/src/expr/sepconst.cpp b/src/expr/sepconst.cpp
new file mode 100644
index 000000000..7646b90d3
--- /dev/null
+++ b/src/expr/sepconst.cpp
@@ -0,0 +1,29 @@
+/********************* */
+/*! \file sepconst.cpp
+ ** \verbatim
+ ** Original author: Andrew Reynolds
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2014 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief [[ Add one-line brief description here ]]
+ **
+ ** [[ Add lengthier description here ]]
+ ** \todo document this file
+ **/
+
+#include "expr/sepconst.h"
+#include <iostream>
+
+using namespace std;
+
+namespace CVC4 {
+
+std::ostream& operator<<(std::ostream& out, const NilRef& asa) {
+ return out << "(nil " << asa.getType() << ")";
+}
+
+}/* CVC4 namespace */
diff --git a/src/expr/sepconst.h b/src/expr/sepconst.h
new file mode 100644
index 000000000..9f86c7efc
--- /dev/null
+++ b/src/expr/sepconst.h
@@ -0,0 +1,72 @@
+/********************* */
+/*! \file sepconst.h
+ ** \verbatim
+ ** Original author: Andrew Reynolds
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2014 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief [[ Add one-line brief description here ]]
+ **
+ ** [[ Add lengthier description here ]]
+ ** \todo document this file
+ **/
+
+#include "cvc4_public.h"
+
+#pragma once
+
+namespace CVC4 {
+ // messy; Expr needs NilRef (because it's the payload of a
+ // CONSTANT-kinded expression), and NilRef needs Expr.
+ class CVC4_PUBLIC NilRef;
+ //class CVC4_PUBLIC EmpStar;
+}/* CVC4 namespace */
+
+#include "expr/expr.h"
+#include "expr/type.h"
+#include <iostream>
+
+namespace CVC4 {
+
+class CVC4_PUBLIC NilRef {
+ const Type d_type;
+ NilRef() { }
+public:
+ NilRef(Type refType):d_type(refType) { }
+
+ ~NilRef() throw() {
+ }
+ Type getType() const { return d_type; }
+ bool operator==(const NilRef& es) const throw() {
+ return d_type == es.d_type;
+ }
+ bool operator!=(const NilRef& es) const throw() {
+ return !(*this == es);
+ }
+ bool operator<(const NilRef& es) const throw() {
+ return d_type < es.d_type;
+ }
+ bool operator<=(const NilRef& es) const throw() {
+ return d_type <= es.d_type;
+ }
+ bool operator>(const NilRef& es) const throw() {
+ return !(*this <= es);
+ }
+ bool operator>=(const NilRef& es) const throw() {
+ return !(*this < es);
+ }
+};/* class NilRef */
+
+std::ostream& operator<<(std::ostream& out, const NilRef& es) CVC4_PUBLIC;
+
+struct CVC4_PUBLIC NilRefHashFunction {
+ inline size_t operator()(const NilRef& es) const {
+ return TypeHashFunction()(es.getType());
+ }
+};/* struct NilRefHashFunction */
+
+}/* CVC4 namespace */
diff --git a/src/expr/type_node.cpp b/src/expr/type_node.cpp
index 5d672e6ac..dc2370bea 100644
--- a/src/expr/type_node.cpp
+++ b/src/expr/type_node.cpp
@@ -21,6 +21,7 @@
#include "expr/type_properties.h"
#include "options/base_options.h"
#include "options/expr_options.h"
+#include "options/quantifiers_options.h"
using namespace std;
@@ -64,6 +65,26 @@ Cardinality TypeNode::getCardinality() const {
return kind::getCardinality(*this);
}
+bool TypeNode::isInterpretedFinite() const {
+ if( getCardinality().isFinite() ){
+ return true;
+ }else{
+ if( options::finiteModelFind() ){
+ if( isSort() ){
+ return true;
+ }else if( isDatatype() || isParametricDatatype() ){
+ const Datatype& dt = getDatatype();
+ return dt.isInterpretedFinite();
+ }else if( isArray() ){
+ return getArrayIndexType().isInterpretedFinite() && getArrayConstituentType().isInterpretedFinite();
+ }else if( isSet() ) {
+ return getSetElementType().isInterpretedFinite();
+ }
+ }
+ return false;
+ }
+}
+
bool TypeNode::isWellFounded() const {
return kind::isWellFounded(*this);
}
diff --git a/src/expr/type_node.h b/src/expr/type_node.h
index cfb61a085..46fdaa143 100644
--- a/src/expr/type_node.h
+++ b/src/expr/type_node.h
@@ -419,6 +419,13 @@ public:
* @return a finite or infinite cardinality
*/
Cardinality getCardinality() const;
+
+ /**
+ * Is this type interpreted as being finite.
+ * If finite model finding is enabled, this assumes all uninterpreted sorts
+ * are interpreted as finite.
+ */
+ bool isInterpretedFinite() const;
/**
* Returns whether this type is well-founded.
diff --git a/src/main/interactive_shell.cpp b/src/main/interactive_shell.cpp
index e11f82a40..334373642 100644
--- a/src/main/interactive_shell.cpp
+++ b/src/main/interactive_shell.cpp
@@ -172,6 +172,7 @@ InteractiveShell::~InteractiveShell() {
<< ": " << strerror(err) << std::endl;
}
#endif /* HAVE_LIBREADLINE */
+ delete d_parser;
}
Command* InteractiveShell::readCommand() throw (UnsafeInterruptException) {
diff --git a/src/main/portfolio_util.cpp b/src/main/portfolio_util.cpp
index 03827a917..8e38eb528 100644
--- a/src/main/portfolio_util.cpp
+++ b/src/main/portfolio_util.cpp
@@ -98,12 +98,6 @@ void parseThreadSpecificOptions(OptionsList& threadOptions, const Options& opts)
ss << optid << ": " << e.getMessage();
throw OptionException(ss.str());
}
- if(optind != targc) {
- stringstream ss;
- ss << "unused argument `" << targv[optind]
- << "' in thread configuration " << optid << " !";
- throw OptionException(ss.str());
- }
if(tOpts.getThreads() != numThreads ||
tOpts.getThreadArgv() != opts.getThreadArgv()) {
stringstream ss;
diff --git a/src/options/Makefile.am b/src/options/Makefile.am
index 643932781..1eb84b45f 100644
--- a/src/options/Makefile.am
+++ b/src/options/Makefile.am
@@ -10,7 +10,7 @@
# Step 4: Generate X_options.h from X_options.sed
# Step 5: Generate X_options.cpp from X_options.sed.
# This stage also waits for X_options.h as otherwise it cannot compile.
-#
+#
OPTIONS_SRC_FILES = \
arith_options \
@@ -30,6 +30,7 @@ OPTIONS_SRC_FILES = \
proof_options \
prop_options \
quantifiers_options \
+ sep_options \
sets_options \
smt_options \
strings_options \
@@ -54,6 +55,7 @@ OPTIONS_TEMPS = \
proof_options.tmp \
prop_options.tmp \
quantifiers_options.tmp \
+ sep_options.tmp \
sets_options.tmp \
smt_options.tmp \
strings_options.tmp \
@@ -78,6 +80,7 @@ OPTIONS_OPTIONS_FILES = \
proof_options.options \
prop_options.options \
quantifiers_options.options \
+ sep_options.options \
sets_options.options \
smt_options.options \
strings_options.options \
@@ -102,6 +105,7 @@ OPTIONS_SEDS = \
proof_options.sed \
prop_options.sed \
quantifiers_options.sed \
+ sep_options.sed \
sets_options.sed \
smt_options.sed \
strings_options.sed \
@@ -126,6 +130,7 @@ OPTIONS_HEADS = \
proof_options.h \
prop_options.h \
quantifiers_options.h \
+ sep_options.h \
sets_options.h \
smt_options.h \
strings_options.h \
@@ -150,6 +155,7 @@ OPTIONS_CPPS = \
proof_options.cpp \
prop_options.cpp \
quantifiers_options.cpp \
+ sep_options.cpp \
sets_options.cpp \
smt_options.cpp \
strings_options.cpp \
@@ -295,14 +301,14 @@ options_holder_template.h options_template.cpp options_get_option_template.cpp o
# Make sure the implicit rules never mistake X_options for the -o file for a
# CPP file.
-arith_options arrays_options base_options booleans_options builtin_options bv_options datatypes_options decision_options expr_options fp_options idl_options main_options parser_options printer_options proof_options prop_options quantifiers_options sets_options smt_options strings_options theory_options uf_options:;
+arith_options arrays_options base_options booleans_options builtin_options bv_options datatypes_options decision_options expr_options fp_options idl_options main_options parser_options printer_options proof_options prop_options quantifiers_options sep_options sets_options smt_options strings_options theory_options uf_options:;
# These are phony to force them to be made everytime.
-.PHONY: arith_options.tmp arrays_options.tmp base_options.tmp booleans_options.tmp builtin_options.tmp bv_options.tmp datatypes_options.tmp decision_options.tmp expr_options.tmp fp_options.tmp idl_options.tmp main_options.tmp parser_options.tmp printer_options.tmp proof_options.tmp prop_options.tmp quantifiers_options.tmp sets_options.tmp smt_options.tmp strings_options.tmp theory_options.tmp uf_options.tmp
+.PHONY: arith_options.tmp arrays_options.tmp base_options.tmp booleans_options.tmp builtin_options.tmp bv_options.tmp datatypes_options.tmp decision_options.tmp expr_options.tmp fp_options.tmp idl_options.tmp main_options.tmp parser_options.tmp printer_options.tmp proof_options.tmp prop_options.tmp quantifiers_options.tmp sep_options.tmp sets_options.tmp smt_options.tmp strings_options.tmp theory_options.tmp uf_options.tmp
# Make is happier being listed explictly. Not sure why.
-arith_options.tmp arrays_options.tmp base_options.tmp booleans_options.tmp builtin_options.tmp bv_options.tmp datatypes_options.tmp decision_options.tmp expr_options.tmp fp_options.tmp idl_options.tmp main_options.tmp parser_options.tmp printer_options.tmp proof_options.tmp prop_options.tmp quantifiers_options.tmp sets_options.tmp smt_options.tmp strings_options.tmp theory_options.tmp uf_options.tmp:
+arith_options.tmp arrays_options.tmp base_options.tmp booleans_options.tmp builtin_options.tmp bv_options.tmp datatypes_options.tmp decision_options.tmp expr_options.tmp fp_options.tmp idl_options.tmp main_options.tmp parser_options.tmp printer_options.tmp proof_options.tmp prop_options.tmp quantifiers_options.tmp sep_options.tmp sets_options.tmp smt_options.tmp strings_options.tmp theory_options.tmp uf_options.tmp:
echo "$@" "$(@:.tmp=)"
$(AM_V_GEN)(cp "@srcdir@/$(@:.tmp=)" "$@" || true)
#TIM:
@@ -424,4 +430,3 @@ $(DOCUMENTATION_FILES) : % : %_template %_template.sed mkoptions summary.sed
# directories that are cleaned first. Without this rule, "distclean"
# fails.
%.Plo:; $(MKDIR_P) "$(dir $@)" && : > "$@"
-
diff --git a/src/options/bv_bitblast_mode.cpp b/src/options/bv_bitblast_mode.cpp
index 9cf47fe33..f331345f7 100644
--- a/src/options/bv_bitblast_mode.cpp
+++ b/src/options/bv_bitblast_mode.cpp
@@ -53,4 +53,19 @@ std::ostream& operator<<(std::ostream& out, theory::bv::BvSlicerMode mode) {
return out;
}
+std::ostream& operator<<(std::ostream& out, theory::bv::SatSolverMode solver) {
+ switch(solver) {
+ case theory::bv::SAT_SOLVER_MINISAT:
+ out << "SAT_SOLVER_MINISAT";
+ break;
+ case theory::bv::SAT_SOLVER_CRYPTOMINISAT:
+ out << "SAT_SOLVER_CRYPTOMINISAT";
+ break;
+ default:
+ out << "SatSolverMode:UNKNOWN![" << unsigned(solver) << "]";
+ }
+
+ return out;
+}
+
}/* CVC4 namespace */
diff --git a/src/options/bv_bitblast_mode.h b/src/options/bv_bitblast_mode.h
index 4c8c4f626..3a6474104 100644
--- a/src/options/bv_bitblast_mode.h
+++ b/src/options/bv_bitblast_mode.h
@@ -60,12 +60,19 @@ enum BvSlicerMode {
};/* enum BvSlicerMode */
+/** Enumeration of sat solvers that can be used. */
+enum SatSolverMode {
+ SAT_SOLVER_MINISAT,
+ SAT_SOLVER_CRYPTOMINISAT,
+};/* enum SatSolver */
+
}/* CVC4::theory::bv namespace */
}/* CVC4::theory namespace */
std::ostream& operator<<(std::ostream& out, theory::bv::BitblastMode mode);
std::ostream& operator<<(std::ostream& out, theory::bv::BvSlicerMode mode);
+std::ostream& operator<<(std::ostream& out, theory::bv::SatSolverMode mode);
}/* CVC4 namespace */
diff --git a/src/options/bv_options b/src/options/bv_options
index 8edc809e3..2e6fa2e7a 100644
--- a/src/options/bv_options
+++ b/src/options/bv_options
@@ -7,6 +7,9 @@ module BV "options/bv_options.h" Bitvector theory
# Option to set the bit-blasting mode (lazy, eager)
+expert-option bvSatSolver bv-sat-solver --bv-sat-solver=MODE CVC4::theory::bv::SatSolverMode :predicate satSolverEnabledBuild :handler stringToSatSolver :default CVC4::theory::bv::SAT_SOLVER_MINISAT :read-write :include "options/bv_bitblast_mode.h"
+ choose which sat solver to use, see --bv-sat-solver=help
+
option bitblastMode bitblast --bitblast=MODE CVC4::theory::bv::BitblastMode :handler stringToBitblastMode :default CVC4::theory::bv::BITBLAST_MODE_LAZY :read-write :include "options/bv_bitblast_mode.h"
choose bitblasting mode, see --bitblast=help
diff --git a/src/options/datatypes_options b/src/options/datatypes_options
index e9578f8d7..bb92b4e05 100644
--- a/src/options/datatypes_options
+++ b/src/options/datatypes_options
@@ -27,5 +27,7 @@ option dtInferAsLemmas --dt-infer-as-lemmas bool :default false
always send lemmas out instead of making internal inferences
#option dtRExplainLemmas --dt-rexplain-lemmas bool :default true
# regression explanations for datatype lemmas
+option dtBlastSplits --dt-blast-splits bool :default false
+ when applicable, blast splitting lemmas for all variables at once
endmodule
diff --git a/src/options/options_handler.cpp b/src/options/options_handler.cpp
index a2809bd67..6a5f6cd39 100644
--- a/src/options/options_handler.cpp
+++ b/src/options/options_handler.cpp
@@ -254,15 +254,21 @@ last-call\n\
const std::string OptionsHandler::s_literalMatchHelp = "\
Literal match modes currently supported by the --literal-match option:\n\
\n\
-none (default)\n\
+none \n\
+ Do not use literal matching.\n\
\n\
-predicate\n\
-+ Consider the phase requirements of predicate literals when applying heuristic\n\
- quantifier instantiation. For example, the trigger P( x ) in the quantified \n\
- formula forall( x ). ( P( x ) V ~Q( x ) ) will only be matched with ground\n\
- terms P( t ) where P( t ) is in the equivalence class of false, and likewise\n\
- Q( x ) with Q( s ) where Q( s ) is in the equivalence class of true.\n\
+use (default)\n\
++ Consider phase requirements of triggers conservatively. For example, the\n\
+ trigger P( x ) in forall( x ). ( P( x ) V ~Q( x ) ) will not be matched with\n\
+ terms in the equivalence class of true, and likewise Q( x ) will not be matched\n\
+ terms in the equivalence class of false. Extends to equality.\n\
+\n\
+agg-predicate \n\
++ Consider phase requirements aggressively for predicates. In the above example,\n\
+ only match P( x ) with terms that are in the equivalence class of false.\n\
+\n\
+agg \n\
++ Consider the phase requirements aggressively for all triggers.\n\
\n\
";
@@ -384,7 +390,7 @@ uf-dt-size \n\
+ Enforce fairness using an uninterpreted function for datatypes size.\n\
\n\
default | dt-size \n\
-+ Default, enforce fairness using size theory operator.\n\
++ Default, enforce fairness using size operator.\n\
\n\
dt-height-bound \n\
+ Enforce fairness by height bound predicate.\n\
@@ -419,6 +425,24 @@ all \n\
\n\
";
+const std::string OptionsHandler::s_cegqiSingleInvHelp = "\
+Modes for single invocation techniques, supported by --cegqi-si:\n\
+\n\
+none \n\
++ Do not use single invocation techniques.\n\
+\n\
+use (default) \n\
++ Use single invocation techniques only if grammar is not restrictive.\n\
+\n\
+all-abort \n\
++ Always use single invocation techniques, abort if solution reconstruction will likely fail,\
+ for instance, when the grammar does not have ITE and solution requires it.\n\
+\n\
+all \n\
++ Always use single invocation techniques. \n\
+\n\
+";
+
const std::string OptionsHandler::s_sygusInvTemplHelp = "\
Template modes for sygus invariant synthesis, supported by --sygus-inv-templ:\n\
\n\
@@ -506,10 +530,12 @@ void OptionsHandler::checkInstWhenMode(std::string option, theory::quantifiers::
theory::quantifiers::LiteralMatchMode OptionsHandler::stringToLiteralMatchMode(std::string option, std::string optarg) throw(OptionException) {
if(optarg == "none") {
return theory::quantifiers::LITERAL_MATCH_NONE;
- } else if(optarg == "predicate") {
- return theory::quantifiers::LITERAL_MATCH_PREDICATE;
- } else if(optarg == "equality") {
- return theory::quantifiers::LITERAL_MATCH_EQUALITY;
+ } else if(optarg == "use") {
+ return theory::quantifiers::LITERAL_MATCH_USE;
+ } else if(optarg == "agg-predicate") {
+ return theory::quantifiers::LITERAL_MATCH_AGG_PREDICATE;
+ } else if(optarg == "agg") {
+ return theory::quantifiers::LITERAL_MATCH_AGG;
} else if(optarg == "help") {
puts(s_literalMatchHelp.c_str());
exit(1);
@@ -520,9 +546,7 @@ theory::quantifiers::LiteralMatchMode OptionsHandler::stringToLiteralMatchMode(s
}
void OptionsHandler::checkLiteralMatchMode(std::string option, theory::quantifiers::LiteralMatchMode mode) throw(OptionException) {
- if(mode == theory::quantifiers::LITERAL_MATCH_EQUALITY) {
- throw OptionException(std::string("Mode equality for ") + option + " is not supported in this release.");
- }
+
}
theory::quantifiers::MbqiMode OptionsHandler::stringToMbqiMode(std::string option, std::string optarg) throw(OptionException) {
@@ -651,6 +675,8 @@ theory::quantifiers::CegqiFairMode OptionsHandler::stringToCegqiFairMode(std::st
return theory::quantifiers::CEGQI_FAIR_DT_SIZE;
} else if(optarg == "dt-height-bound" ){
return theory::quantifiers::CEGQI_FAIR_DT_HEIGHT_PRED;
+ //} else if(optarg == "dt-size-bound" ){
+ // return theory::quantifiers::CEGQI_FAIR_DT_SIZE_PRED;
} else if(optarg == "none") {
return theory::quantifiers::CEGQI_FAIR_NONE;
} else if(optarg == "help") {
@@ -692,6 +718,24 @@ theory::quantifiers::IteLiftQuantMode OptionsHandler::stringToIteLiftQuantMode(s
}
}
+theory::quantifiers::CegqiSingleInvMode OptionsHandler::stringToCegqiSingleInvMode(std::string option, std::string optarg) throw(OptionException) {
+ if(optarg == "none" ) {
+ return theory::quantifiers::CEGQI_SI_MODE_NONE;
+ } else if(optarg == "use" || optarg == "default") {
+ return theory::quantifiers::CEGQI_SI_MODE_USE;
+ } else if(optarg == "all-abort") {
+ return theory::quantifiers::CEGQI_SI_MODE_ALL_ABORT;
+ } else if(optarg == "all") {
+ return theory::quantifiers::CEGQI_SI_MODE_ALL;
+ } else if(optarg == "help") {
+ puts(s_cegqiSingleInvHelp.c_str());
+ exit(1);
+ } else {
+ throw OptionException(std::string("unknown option for --cegqi-si: `") +
+ optarg + "'. Try --cegqi-si help.");
+ }
+}
+
theory::quantifiers::SygusInvTemplMode OptionsHandler::stringToSygusInvTemplMode(std::string option, std::string optarg) throw(OptionException) {
if(optarg == "none" ) {
return theory::quantifiers::SYGUS_INV_TEMPL_MODE_NONE;
@@ -777,6 +821,72 @@ void OptionsHandler::abcEnabledBuild(std::string option, std::string value) thro
#endif /* CVC4_USE_ABC */
}
+void OptionsHandler::satSolverEnabledBuild(std::string option,
+ bool value) throw(OptionException) {
+#ifndef CVC4_USE_CRYPTOMINISAT
+ if(value) {
+ std::stringstream ss;
+ ss << "option `" << option << "' requires an cryptominisat-enabled build of CVC4; this binary was not built with cryptominisat support";
+ throw OptionException(ss.str());
+ }
+#endif /* CVC4_USE_CRYPTOMINISAT */
+}
+
+void OptionsHandler::satSolverEnabledBuild(std::string option,
+ std::string value) throw(OptionException) {
+#ifndef CVC4_USE_CRYPTOMINISAT
+ if(!value.empty()) {
+ std::stringstream ss;
+ ss << "option `" << option << "' requires an cryptominisat-enabled build of CVC4; this binary was not built with cryptominisat support";
+ throw OptionException(ss.str());
+ }
+#endif /* CVC4_USE_CRYPTOMINISAT */
+}
+
+const std::string OptionsHandler::s_bvSatSolverHelp = "\
+Sat solvers currently supported by the --bv-sat-solver option:\n\
+\n\
+minisat (default)\n\
+\n\
+cryptominisat\n\
+";
+
+theory::bv::SatSolverMode OptionsHandler::stringToSatSolver(std::string option,
+ std::string optarg) throw(OptionException) {
+ if(optarg == "minisat") {
+ return theory::bv::SAT_SOLVER_MINISAT;
+ } else if(optarg == "cryptominisat") {
+
+ if (options::incrementalSolving() &&
+ options::incrementalSolving.wasSetByUser()) {
+ throw OptionException(std::string("Cryptominsat does not support incremental mode. \n\
+ Try --bv-sat-solver=minisat"));
+ }
+
+ if (options::bitblastMode() == theory::bv::BITBLAST_MODE_LAZY &&
+ options::bitblastMode.wasSetByUser()) {
+ throw OptionException(std::string("Cryptominsat does not support lazy bit-blsating. \n\
+ Try --bv-sat-solver=minisat"));
+ }
+ if (!options::bitvectorToBool.wasSetByUser()) {
+ options::bitvectorToBool.set(true);
+ }
+
+ // if (!options::bvAbstraction.wasSetByUser() &&
+ // !options::skolemizeArguments.wasSetByUser()) {
+ // options::bvAbstraction.set(true);
+ // options::skolemizeArguments.set(true);
+ // }
+ return theory::bv::SAT_SOLVER_CRYPTOMINISAT;
+ } else if(optarg == "help") {
+ puts(s_bvSatSolverHelp.c_str());
+ exit(1);
+ } else {
+ throw OptionException(std::string("unknown option for --bv-sat-solver: `") +
+ optarg + "'. Try --bv-sat-solver=help.");
+ }
+}
+
const std::string OptionsHandler::s_bitblastingModeHelp = "\
Bit-blasting modes currently supported by the --bitblast option:\n\
\n\
diff --git a/src/options/options_handler.h b/src/options/options_handler.h
index baa6cea96..5db2887c0 100644
--- a/src/options/options_handler.h
+++ b/src/options/options_handler.h
@@ -98,6 +98,7 @@ public:
theory::quantifiers::CegqiFairMode stringToCegqiFairMode(std::string option, std::string optarg) throw(OptionException);
theory::quantifiers::TermDbMode stringToTermDbMode(std::string option, std::string optarg) throw(OptionException);
theory::quantifiers::IteLiftQuantMode stringToIteLiftQuantMode(std::string option, std::string optarg) throw(OptionException);
+ theory::quantifiers::CegqiSingleInvMode stringToCegqiSingleInvMode(std::string option, std::string optarg) throw(OptionException);
theory::quantifiers::SygusInvTemplMode stringToSygusInvTemplMode(std::string option, std::string optarg) throw(OptionException);
theory::quantifiers::MacrosQuantMode stringToMacrosQuantMode(std::string option, std::string optarg) throw(OptionException);
theory::quantifiers::QuantDSplitMode stringToQuantDSplitMode(std::string option, std::string optarg) throw(OptionException);
@@ -106,10 +107,15 @@ public:
// theory/bv/options_handlers.h
void abcEnabledBuild(std::string option, bool value) throw(OptionException);
void abcEnabledBuild(std::string option, std::string value) throw(OptionException);
+ void satSolverEnabledBuild(std::string option, bool value) throw(OptionException);
+ void satSolverEnabledBuild(std::string option, std::string optarg) throw(OptionException);
+
theory::bv::BitblastMode stringToBitblastMode(std::string option, std::string optarg) throw(OptionException);
theory::bv::BvSlicerMode stringToBvSlicerMode(std::string option, std::string optarg) throw(OptionException);
void setBitblastAig(std::string option, bool arg) throw(OptionException);
+ theory::bv::SatSolverMode stringToSatSolver(std::string option, std::string optarg) throw(OptionException);
+
// theory/booleans/options_handlers.h
theory::booleans::BooleanTermConversionMode stringToBooleanTermConversionMode(std::string option, std::string optarg) throw(OptionException);
@@ -192,6 +198,7 @@ public:
/* Help strings */
static const std::string s_bitblastingModeHelp;
+ static const std::string s_bvSatSolverHelp;
static const std::string s_booleanTermConversionModeHelp;
static const std::string s_bvSlicerModeHelp;
static const std::string s_cegqiFairModeHelp;
@@ -209,6 +216,7 @@ public:
static const std::string s_qcfModeHelp;
static const std::string s_qcfWhenModeHelp;
static const std::string s_simplificationHelp;
+ static const std::string s_cegqiSingleInvHelp;
static const std::string s_sygusInvTemplHelp;
static const std::string s_termDbModeHelp;
static const std::string s_theoryOfModeHelp;
diff --git a/src/options/options_template.cpp b/src/options/options_template.cpp
index f029dfd17..694d46d31 100644
--- a/src/options/options_template.cpp
+++ b/src/options/options_template.cpp
@@ -720,7 +720,7 @@ void Options::parseOptionsRecursive(Options* options,
switch(c) {
${all_modules_option_handlers}
-#line 722 "${template}"
+#line 724 "${template}"
case ':':
// This can be a long or short option, and the way to get at the
@@ -798,7 +798,7 @@ std::string Options::suggestCommandLineOptions(const std::string& optionName) th
static const char* smtOptions[] = {
${all_modules_smt_options},
-#line 800 "${template}"
+#line 802 "${template}"
NULL
};/* smtOptions[] */
@@ -820,7 +820,7 @@ std::vector< std::vector<std::string> > Options::getOptions() const throw() {
${all_modules_get_options}
-#line 762 "${template}"
+#line 824 "${template}"
return opts;
}
diff --git a/src/options/proof_options b/src/options/proof_options
index 7feb00b0d..a99d858bc 100644
--- a/src/options/proof_options
+++ b/src/options/proof_options
@@ -5,4 +5,7 @@
module PROOF "options/proof_options.h" Proof
+option lfscLetification --lfsc-letification bool :default true
+ turns on global letification in LFSC proofs
+
endmodule
diff --git a/src/options/quantifiers_modes.cpp b/src/options/quantifiers_modes.cpp
index a58120974..e2cd78de5 100644
--- a/src/options/quantifiers_modes.cpp
+++ b/src/options/quantifiers_modes.cpp
@@ -46,11 +46,14 @@ std::ostream& operator<<(std::ostream& out, theory::quantifiers::LiteralMatchMod
case theory::quantifiers::LITERAL_MATCH_NONE:
out << "LITERAL_MATCH_NONE";
break;
- case theory::quantifiers::LITERAL_MATCH_PREDICATE:
- out << "LITERAL_MATCH_PREDICATE";
+ case theory::quantifiers::LITERAL_MATCH_USE:
+ out << "LITERAL_MATCH_USE";
break;
- case theory::quantifiers::LITERAL_MATCH_EQUALITY:
- out << "LITERAL_MATCH_EQUALITY";
+ case theory::quantifiers::LITERAL_MATCH_AGG_PREDICATE:
+ out << "LITERAL_MATCH_AGG_PREDICATE";
+ break;
+ case theory::quantifiers::LITERAL_MATCH_AGG:
+ out << "LITERAL_MATCH_AGG";
break;
default:
out << "LiteralMatchMode!UNKNOWN";
diff --git a/src/options/quantifiers_modes.h b/src/options/quantifiers_modes.h
index 5749da972..65445be17 100644
--- a/src/options/quantifiers_modes.h
+++ b/src/options/quantifiers_modes.h
@@ -44,10 +44,12 @@ enum InstWhenMode {
enum LiteralMatchMode {
/** Do not consider polarity of patterns */
LITERAL_MATCH_NONE,
- /** Consider polarity of boolean predicates only */
- LITERAL_MATCH_PREDICATE,
- /** Consider polarity of boolean predicates, as well as equalities */
- LITERAL_MATCH_EQUALITY,
+ /** Conservatively consider polarity of patterns */
+ LITERAL_MATCH_USE,
+ /** Aggressively consider polarity of Boolean predicates */
+ LITERAL_MATCH_AGG_PREDICATE,
+ /** Aggressively consider polarity of all terms */
+ LITERAL_MATCH_AGG,
};
enum MbqiMode {
@@ -129,6 +131,8 @@ enum CegqiFairMode {
CEGQI_FAIR_DT_SIZE,
/** enforce fairness by datatypes height bound */
CEGQI_FAIR_DT_HEIGHT_PRED,
+ /** enforce fairness by datatypes size bound */
+ CEGQI_FAIR_DT_SIZE_PRED,
/** do not use fair strategy for CEGQI */
CEGQI_FAIR_NONE,
};
@@ -149,6 +153,17 @@ enum IteLiftQuantMode {
ITE_LIFT_QUANT_MODE_ALL,
};
+enum CegqiSingleInvMode {
+ /** do not use single invocation techniques */
+ CEGQI_SI_MODE_NONE,
+ /** use single invocation techniques */
+ CEGQI_SI_MODE_USE,
+ /** always use single invocation techniques, abort if solution reconstruction will fail */
+ CEGQI_SI_MODE_ALL_ABORT,
+ /** always use single invocation techniques */
+ CEGQI_SI_MODE_ALL,
+};
+
enum SygusInvTemplMode {
/** synthesize I( x ) */
SYGUS_INV_TEMPL_MODE_NONE,
diff --git a/src/options/quantifiers_options b/src/options/quantifiers_options
index 74b3011a6..4d228bbad 100644
--- a/src/options/quantifiers_options
+++ b/src/options/quantifiers_options
@@ -54,6 +54,8 @@ option purifyQuant --purify-quant bool :default false
purify quantified formulas
option elimExtArithQuant --elim-ext-arith-quant bool :default true
eliminate extended arithmetic symbols in quantified formulas
+option condRewriteQuant --cond-rewrite-quant bool :default true
+ conditional rewriting of quantified formulas
#### E-matching options
@@ -109,6 +111,8 @@ option instLevelInputOnly --inst-level-input-only bool :default true
only input terms are assigned instantiation level zero
option quantRepMode --quant-rep-mode=MODE CVC4::theory::quantifiers::QuantRepMode :default CVC4::theory::quantifiers::QUANT_REP_MODE_FIRST :read-write :include "options/quantifiers_modes.h" :handler stringToQuantRepMode
selection mode for representatives in quantifiers engine
+option instRelevantCond --inst-rlv-cond bool :default false
+ add relevancy conditions for instantiations
option eagerInstQuant --eager-inst-quant bool :default false
apply quantifier instantiation eagerly
@@ -120,7 +124,7 @@ option fullSaturateQuantRd --full-saturate-quant-rd bool :default true
option fullSaturateInst --fs-inst bool :default false
interleave full saturate instantiation with other techniques
-option literalMatchMode --literal-matching=MODE CVC4::theory::quantifiers::LiteralMatchMode :default CVC4::theory::quantifiers::LITERAL_MATCH_NONE :include "options/quantifiers_modes.h" :handler stringToLiteralMatchMode :predicate checkLiteralMatchMode
+option literalMatchMode --literal-matching=MODE CVC4::theory::quantifiers::LiteralMatchMode :default CVC4::theory::quantifiers::LITERAL_MATCH_USE :include "options/quantifiers_modes.h" :handler stringToLiteralMatchMode :predicate checkLiteralMatchMode
choose literal matching mode
### finite model finding options
@@ -144,7 +148,7 @@ option fmfOneInstPerRound --mbqi-one-inst-per-round bool :read-write :default fa
option fmfOneQuantPerRound --mbqi-one-quant-per-round bool :default false
only add instantiations for one quantifier per round for mbqi
-option fmfInstEngine --fmf-inst-engine bool :default false
+option fmfInstEngine --fmf-inst-engine bool :default false :read-write
use instantiation engine in conjunction with finite model finding
option fmfInstGen --fmf-inst-gen bool :default true
enable Inst-Gen instantiation techniques for finite model finding
@@ -171,13 +175,23 @@ option qcfTConstraint --qcf-tconstraint bool :read-write :default false
enable entailment checks for t-constraints in qcf algorithm
option qcfAllConflict --qcf-all-conflict bool :read-write :default false
add all available conflicting instances during conflict-based instantiation
+option qcfNestedConflict --qcf-nested-conflict bool :default false
+ consider conflicts for nested quantifiers
+option qcfVoExp --qcf-vo-exp bool :default false
+ qcf experimental variable ordering
+
+
option instNoEntail --inst-no-entail bool :read-write :default true
do not consider instances of quantified formulas that are currently entailed
-option instPropagate --inst-propagate bool :read-write :default false
+option instPropagate --inst-prop bool :read-write :default false
internal propagation for instantiations for selecting relevant instances
+option qcfEagerTest --qcf-eager-test bool :default true
+ optimization, test qcf instances eagerly
+option qcfSkipRd --qcf-skip-rd bool :default false
+ optimization, skip instances based on possibly irrelevant portions of quantified formulas
### rewrite rules options
option quantRewriteRules --rewrite-rules bool :default false
@@ -219,8 +233,8 @@ option ceGuidedInst --cegqi bool :default false :read-write
counterexample-guided quantifier instantiation
option ceGuidedInstFair --cegqi-fair=MODE CVC4::theory::quantifiers::CegqiFairMode :default CVC4::theory::quantifiers::CEGQI_FAIR_DT_SIZE :include "options/quantifiers_modes.h" :handler stringToCegqiFairMode
if and how to apply fairness for cegqi
-option cegqiSingleInv --cegqi-si bool :default false :read-write
- process single invocation synthesis conjectures
+option cegqiSingleInvMode --cegqi-si=MODE CVC4::theory::quantifiers::CegqiSingleInvMode :default CVC4::theory::quantifiers::CEGQI_SI_MODE_NONE :include "options/quantifiers_modes.h" :handler stringToCegqiSingleInvMode :read-write
+ mode for processing single invocation synthesis conjectures
option cegqiSingleInvPartial --cegqi-si-partial bool :default false
combined techniques for synthesis conjectures that are partially single invocation
option cegqiSingleInvReconstruct --cegqi-si-reconstruct bool :default true
@@ -229,8 +243,6 @@ option cegqiSingleInvReconstructConst --cegqi-si-reconstruct-const bool :default
include constants when reconstruct solutions for single invocation conjectures in original grammar
option cegqiSingleInvAbort --cegqi-si-abort bool :default false
abort if synthesis conjecture is not single invocation
-option cegqiSingleInvMultiInstAbort --cegqi-si-multi-inst-abort bool :default false
- abort if synthesis conjecture is single invocation with no ITE in grammar and multiple instantiations are tried
option sygusNormalForm --sygus-nf bool :default true
only search for sygus builtin terms that are in normal form
@@ -248,6 +260,9 @@ option sygusNormalFormGlobalContent --sygus-nf-sym-content bool :default true
option sygusInvTemplMode --sygus-inv-templ=MODE CVC4::theory::quantifiers::SygusInvTemplMode :default CVC4::theory::quantifiers::SYGUS_INV_TEMPL_MODE_NONE :include "options/quantifiers_modes.h" :handler stringToSygusInvTemplMode
template mode for sygus invariant synthesis
+option sygusDirectEval --sygus-direct-eval bool :default true
+ direct unfolding of evaluation functions
+
# approach applied to general quantified formulas
option cbqiSplx --cbqi-splx bool :read-write :default false
turns on old implementation of counterexample-based quantifier instantiation
diff --git a/src/options/sep_options b/src/options/sep_options
new file mode 100644
index 000000000..043355bda
--- /dev/null
+++ b/src/options/sep_options
@@ -0,0 +1,20 @@
+#
+# Option specification file for CVC4
+# See src/options/base_options for a description of this file format
+#
+
+module SEP "options/sep_options.h" Sep
+
+option sepCheckNeg --sep-check-neg bool :default true
+ check negated spatial assertions
+
+option sepExp --sep-exp bool :default false
+ experimental flag for sep
+option sepMinimalRefine --sep-min-refine bool :default false
+ only add refinement lemmas for minimal (innermost) assertions
+option sepPreciseBound --sep-prec-bound bool :default false
+ calculate precise bounds for labels
+option sepDisequalC --sep-deq-c bool :default true
+ assume cardinality elements are distinct
+
+endmodule
diff --git a/src/parser/cvc/Cvc.g b/src/parser/cvc/Cvc.g
index c497fcd0d..e6d7f9d86 100644
--- a/src/parser/cvc/Cvc.g
+++ b/src/parser/cvc/Cvc.g
@@ -931,7 +931,10 @@ toplevelDeclaration[CVC4::Command*& cmd]
* A bound variable declaration.
*/
boundVarDecl[std::vector<std::string>& ids, CVC4::Type& t]
- : identifierList[ids,CHECK_NONE,SYM_VARIABLE] COLON declareVariables[*(Command**)NULL,t,ids,false]
+@init {
+ Command* local_cmd = NULL;
+}
+ : identifierList[ids,CHECK_NONE,SYM_VARIABLE] COLON declareVariables[local_cmd,t,ids,false]
;
/**
diff --git a/src/parser/smt2/Smt2.g b/src/parser/smt2/Smt2.g
index 38163c579..29d3e45b6 100644
--- a/src/parser/smt2/Smt2.g
+++ b/src/parser/smt2/Smt2.g
@@ -749,7 +749,7 @@ sygusCommand returns [CVC4::Command* cmd = NULL]
$cmd = new EmptyCommand();
}
| /* check-synth */
- CHECK_SYNTH_TOK { PARSER_STATE->checkThatLogicIsSet(); }
+ CHECK_SYNTH_TOK { PARSER_STATE->checkThatLogicIsSet();PARSER_STATE->defineSygusFuns(); }
{ Expr sygusVar = EXPR_MANAGER->mkVar("sygus", EXPR_MANAGER->booleanType());
Expr sygusAttr = EXPR_MANAGER->mkExpr(kind::INST_PATTERN_LIST, EXPR_MANAGER->mkExpr(kind::INST_ATTRIBUTE, sygusVar));
std::vector<Expr> bodyv;
@@ -760,7 +760,9 @@ sygusCommand returns [CVC4::Command* cmd = NULL]
body = EXPR_MANAGER->mkExpr(kind::EXISTS, EXPR_MANAGER->mkExpr(kind::BOUND_VAR_LIST, PARSER_STATE->getSygusVars()), body);
Debug("parser-sygus") << "...constructed exists " << body << std::endl;
}
- body = EXPR_MANAGER->mkExpr(kind::FORALL, EXPR_MANAGER->mkExpr(kind::BOUND_VAR_LIST, PARSER_STATE->getSygusFunSymbols()), body, sygusAttr);
+ if( !PARSER_STATE->getSygusFunSymbols().empty() ){
+ body = EXPR_MANAGER->mkExpr(kind::FORALL, EXPR_MANAGER->mkExpr(kind::BOUND_VAR_LIST, PARSER_STATE->getSygusFunSymbols()), body, sygusAttr);
+ }
Debug("parser-sygus") << "...constructed forall " << body << std::endl;
Command* c = new SetUserAttributeCommand("sygus", sygusVar);
c->setMuted(true);
@@ -791,6 +793,7 @@ sygusGTerm[CVC4::SygusGTerm& sgt, std::string& fun]
std::string sname;
std::vector< Expr > let_vars;
bool readingLet = false;
+ std::string s;
}
: LPAREN_TOK
//read operator
@@ -799,6 +802,8 @@ sygusGTerm[CVC4::SygusGTerm& sgt, std::string& fun]
//since we enforce satisfaction completeness, immediately convert to total version
if( k==CVC4::kind::BITVECTOR_UDIV ){
k = CVC4::kind::BITVECTOR_UDIV_TOTAL;
+ }else if( k==CVC4::kind::BITVECTOR_UREM ){
+ k = CVC4::kind::BITVECTOR_UREM_TOTAL;
}
sgt.d_name = kind::kindToString(k);
sgt.d_gterm_type = SygusGTerm::gterm_op;
@@ -834,6 +839,8 @@ sygusGTerm[CVC4::SygusGTerm& sgt, std::string& fun]
k = PARSER_STATE->getOperatorKind(name);
if( k==CVC4::kind::BITVECTOR_UDIV ){
k = CVC4::kind::BITVECTOR_UDIV_TOTAL;
+ }else if( k==CVC4::kind::BITVECTOR_UREM ){
+ k = CVC4::kind::BITVECTOR_UREM_TOTAL;
}
sgt.d_name = kind::kindToString(k);
sgt.d_gterm_type = SygusGTerm::gterm_op;
@@ -890,6 +897,12 @@ sygusGTerm[CVC4::SygusGTerm& sgt, std::string& fun]
sgt.d_name = AntlrInput::tokenText($BINARY_LITERAL);
sgt.d_gterm_type = SygusGTerm::gterm_op;
}
+ | str[s,false]
+ { Debug("parser-sygus") << "Sygus grammar " << fun << " : string literal \"" << s << "\"" << std::endl;
+ sgt.d_expr = MK_CONST( ::CVC4::String(s) );
+ sgt.d_name = s;
+ sgt.d_gterm_type = SygusGTerm::gterm_op;
+ }
| symbol[name,CHECK_NONE,SYM_VARIABLE] ( SYGUS_ENUM_CONS_TOK symbol[name2,CHECK_NONE,SYM_VARIABLE] { readEnum = true; } )?
{ if( readEnum ){
name = name + "__Enum__" + name2;
@@ -1594,6 +1607,10 @@ term[CVC4::Expr& expr, CVC4::Expr& expr2]
Debug("parser") << "Empty set encountered: " << f << " "
<< f2 << " " << type << std::endl;
expr = MK_CONST( ::CVC4::EmptySet(type) );
+ } else if(f.getKind() == CVC4::kind::SEP_NIL_REF) {
+ //We don't want the nil reference to be a constant: for instance, it could be of type Int but is not a const rational.
+ //However, the expression has 0 children. So we convert to a SEP_NIL variable.
+ expr = EXPR_MANAGER->mkSepNil(type);
} else {
if(f.getType() != type) {
PARSER_STATE->parseError("Type ascription not satisfied.");
@@ -1898,6 +1915,8 @@ term[CVC4::Expr& expr, CVC4::Expr& expr2]
| EMPTYSET_TOK
{ expr = MK_CONST( ::CVC4::EmptySet(Type())); }
+ | NILREF_TOK
+ { expr = MK_CONST( ::CVC4::NilRef(Type())); }
// NOTE: Theory constants go here
;
@@ -2633,6 +2652,7 @@ FMFCARDVAL_TOK : 'fmf.card.val';
INST_CLOSURE_TOK : 'inst-closure';
EMPTYSET_TOK: { PARSER_STATE->isTheoryEnabled(Smt2::THEORY_SETS) }? 'emptyset';
+NILREF_TOK: { PARSER_STATE->isTheoryEnabled(Smt2::THEORY_SEP) }? 'sep.nil';
// Other set theory operators are not
// tokenized and handled directly when
// processing a term
@@ -2773,7 +2793,7 @@ STRING_LITERAL_2_0
* will be part of the token text. Use the str[] parser rule instead.
*/
STRING_LITERAL_2_5
- : { PARSER_STATE->v2_5() }?=>
+ : { PARSER_STATE->v2_5() || PARSER_STATE->sygus() }?=>
'"' (~('"') | '""')* '"'
;
diff --git a/src/parser/smt2/smt2.cpp b/src/parser/smt2/smt2.cpp
index 463adcb54..9f3c43f09 100644
--- a/src/parser/smt2/smt2.cpp
+++ b/src/parser/smt2/smt2.cpp
@@ -166,6 +166,16 @@ void Smt2::addFloatingPointOperators() {
Parser::addOperator(kind::FLOATINGPOINT_TO_SBV);
}
+void Smt2::addSepOperators() {
+ addOperator(kind::SEP_STAR, "sep");
+ addOperator(kind::SEP_PTO, "pto");
+ addOperator(kind::SEP_WAND, "wand");
+ addOperator(kind::SEP_EMP, "emp");
+ Parser::addOperator(kind::SEP_STAR);
+ Parser::addOperator(kind::SEP_PTO);
+ Parser::addOperator(kind::SEP_WAND);
+ Parser::addOperator(kind::SEP_EMP);
+}
void Smt2::addTheory(Theory theory) {
switch(theory) {
@@ -258,7 +268,11 @@ void Smt2::addTheory(Theory theory) {
defineType("Float128", getExprManager()->mkFloatingPointType(15, 113));
addFloatingPointOperators();
break;
-
+
+ case THEORY_SEP:
+ addSepOperators();
+ break;
+
default:
std::stringstream ss;
ss << "internal error: unsupported theory " << theory;
@@ -311,6 +325,8 @@ bool Smt2::isTheoryEnabled(Theory theory) const {
return d_logic.isTheoryEnabled(theory::THEORY_UF);
case THEORY_FP:
return d_logic.isTheoryEnabled(theory::THEORY_FP);
+ case THEORY_SEP:
+ return d_logic.isTheoryEnabled(theory::THEORY_SEP);
default:
std::stringstream ss;
ss << "internal error: unsupported theory " << theory;
@@ -354,6 +370,8 @@ void Smt2::setLogic(std::string name) {
name = "UFLIRA";
} else if(name == "BV") {
name = "UFBV";
+ } else if(name == "SLIA") {
+ name = "UFSLIA";
} else if(name == "ALL_SUPPORTED") {
//no change
} else {
@@ -417,6 +435,10 @@ void Smt2::setLogic(std::string name) {
addTheory(THEORY_FP);
}
+ if (d_logic.isTheoryEnabled(theory::THEORY_SEP)) {
+ addTheory(THEORY_SEP);
+ }
+
}/* Smt2::setLogic() */
void Smt2::setInfo(const std::string& flag, const SExpr& sexpr) {
diff --git a/src/parser/smt2/smt2.h b/src/parser/smt2/smt2.h
index 1ae2c9dd7..b99e142ba 100644
--- a/src/parser/smt2/smt2.h
+++ b/src/parser/smt2/smt2.h
@@ -51,7 +51,8 @@ public:
THEORY_SETS,
THEORY_STRINGS,
THEORY_UF,
- THEORY_FP
+ THEORY_FP,
+ THEORY_SEP
};
private:
@@ -344,6 +345,7 @@ private:
void addFloatingPointOperators();
+ void addSepOperators();
};/* class Smt2 */
}/* CVC4::parser namespace */
diff --git a/src/printer/smt2/smt2_printer.cpp b/src/printer/smt2/smt2_printer.cpp
index 9d61e5ef8..4006a9e08 100644
--- a/src/printer/smt2/smt2_printer.cpp
+++ b/src/printer/smt2/smt2_printer.cpp
@@ -117,21 +117,26 @@ void Smt2Printer::toStream(std::ostream& out, TNode n,
// variable
if(n.isVar()) {
- string s;
- if(n.getAttribute(expr::VarNameAttr(), s)) {
- out << maybeQuoteSymbol(s);
- } else {
- if(n.getKind() == kind::VARIABLE) {
- out << "var_";
+ if( n.getKind() == kind::SEP_NIL ){
+ out << "(as sep.nil " << n.getType() << ")";
+ return;
+ }else{
+ string s;
+ if(n.getAttribute(expr::VarNameAttr(), s)) {
+ out << maybeQuoteSymbol(s);
} else {
- out << n.getKind() << '_';
+ if(n.getKind() == kind::VARIABLE) {
+ out << "var_";
+ } else {
+ out << n.getKind() << '_';
+ }
+ out << n.getId();
+ }
+ if(types) {
+ // print the whole type, but not *its* type
+ out << ":";
+ n.getType().toStream(out, language::output::LANG_SMTLIB_V2_5);
}
- out << n.getId();
- }
- if(types) {
- // print the whole type, but not *its* type
- out << ":";
- n.getType().toStream(out, language::output::LANG_SMTLIB_V2_5);
}
return;
@@ -291,7 +296,7 @@ void Smt2Printer::toStream(std::ostream& out, TNode n,
case kind::EMPTYSET:
out << "(as emptyset " << n.getConst<EmptySet>().getType() << ")";
break;
-
+
default:
// fall back on whatever operator<< does on underlying type; we
// might luck out and be SMT-LIB v2 compliant
@@ -318,7 +323,7 @@ void Smt2Printer::toStream(std::ostream& out, TNode n,
}
return;
}
-
+
bool stillNeedToPrintParams = true;
bool forceBinary = false; // force N-ary to binary when outputing children
// operator
@@ -585,6 +590,12 @@ void Smt2Printer::toStream(std::ostream& out, TNode n,
case kind::APPLY_SELECTOR_TOTAL:
case kind::PARAMETRIC_DATATYPE:
break;
+
+ //separation
+ case kind::SEP_EMP:
+ case kind::SEP_PTO:
+ case kind::SEP_STAR:
+ case kind::SEP_WAND:out << smtKindString(k) << " "; break;
// quantifiers
case kind::FORALL:
@@ -834,6 +845,39 @@ static string smtKindString(Kind k) throw() {
case kind::FLOATINGPOINT_TO_SBV: return "fp.to_sbv";
case kind::FLOATINGPOINT_TO_REAL: return "fp.to_real";
+ //string theory
+ case kind::STRING_CONCAT: return "str.++";
+ case kind::STRING_LENGTH: return "str.len";
+ case kind::STRING_SUBSTR: return "str.substr" ;
+ case kind::STRING_STRCTN: return "str.contains" ;
+ case kind::STRING_CHARAT: return "str.at" ;
+ case kind::STRING_STRIDOF: return "str.indexof" ;
+ case kind::STRING_STRREPL: return "str.replace" ;
+ case kind::STRING_PREFIX: return "str.prefixof" ;
+ case kind::STRING_SUFFIX: return "str.suffixof" ;
+ case kind::STRING_ITOS: return "int.to.str" ;
+ case kind::STRING_STOI: return "str.to.int" ;
+ case kind::STRING_U16TOS: return "u16.to.str" ;
+ case kind::STRING_STOU16: return "str.to.u16" ;
+ case kind::STRING_U32TOS: return "u32.to.str" ;
+ case kind::STRING_STOU32: return "str.to.u32" ;
+ case kind::STRING_IN_REGEXP: return "str.in.re";
+ case kind::STRING_TO_REGEXP: return "str.to.re";
+ case kind::REGEXP_CONCAT: return "re.++";
+ case kind::REGEXP_UNION: return "re.union";
+ case kind::REGEXP_INTER: return "re.inter";
+ case kind::REGEXP_STAR: return "re.*";
+ case kind::REGEXP_PLUS: return "re.+";
+ case kind::REGEXP_OPT: return "re.opt";
+ case kind::REGEXP_RANGE: return "re.range";
+ case kind::REGEXP_LOOP: return "re.loop";
+
+ //sep theory
+ case kind::SEP_STAR: return "sep";
+ case kind::SEP_PTO: return "pto";
+ case kind::SEP_WAND: return "wand";
+ case kind::SEP_EMP: return "emp";
+
default:
; /* fall through */
}
diff --git a/src/proof/arith_proof.cpp b/src/proof/arith_proof.cpp
index a1287b667..4864cbf46 100644
--- a/src/proof/arith_proof.cpp
+++ b/src/proof/arith_proof.cpp
@@ -69,18 +69,18 @@ inline static bool match(TNode n1, TNode n2) {
void ProofArith::toStream(std::ostream& out) {
Trace("theory-proof-debug") << "; Print Arith proof..." << std::endl;
//AJR : carry this further?
- LetMap map;
+ ProofLetMap map;
toStreamLFSC(out, ProofManager::getArithProof(), d_proof, map);
}
-void ProofArith::toStreamLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, const LetMap& map) {
+void ProofArith::toStreamLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, const ProofLetMap& map) {
Debug("lfsc-arith") << "Printing arith proof in LFSC : " << std::endl;
pf->debug_print("lfsc-arith");
Debug("lfsc-arith") << std::endl;
toStreamRecLFSC( out, tp, pf, 0, map );
}
-Node ProofArith::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, unsigned tb, const LetMap& map) {
+Node ProofArith::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, unsigned tb, const ProofLetMap& map) {
Debug("pf::arith") << std::endl << std::endl << "toStreamRecLFSC called. tb = " << tb << " . proof:" << std::endl;
pf->debug_print("pf::arith");
Debug("pf::arith") << std::endl;
@@ -643,7 +643,7 @@ void ArithProof::registerTerm(Expr term) {
}
}
-void LFSCArithProof::printOwnedTerm(Expr term, std::ostream& os, const LetMap& map) {
+void LFSCArithProof::printOwnedTerm(Expr term, std::ostream& os, const ProofLetMap& map) {
Debug("pf::arith") << "Arith print term: " << term << ". Kind: " << term.getKind()
<< ". Type: " << term.getType()
<< ". Number of children: " << term.getNumChildren() << std::endl;
@@ -810,14 +810,14 @@ void LFSCArithProof::printOwnedSort(Type type, std::ostream& os) {
}
}
-void LFSCArithProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren) {
+void LFSCArithProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren, const ProofLetMap& map) {
os << " ;; Arith Theory Lemma \n;;";
for (unsigned i = 0; i < lemma.size(); ++i) {
os << lemma[i] <<" ";
}
os <<"\n";
//os << " (clausify_false trust)";
- ArithProof::printTheoryLemmaProof( lemma, os, paren );
+ ArithProof::printTheoryLemmaProof(lemma, os, paren, map);
}
void LFSCArithProof::printSortDeclarations(std::ostream& os, std::ostream& paren) {
@@ -830,4 +830,8 @@ void LFSCArithProof::printDeferredDeclarations(std::ostream& os, std::ostream& p
// Nothing to do here at this point.
}
+void LFSCArithProof::printAliasingDeclarations(std::ostream& os, std::ostream& paren) {
+ // Nothing to do here at this point.
+}
+
} /* CVC4 namespace */
diff --git a/src/proof/arith_proof.h b/src/proof/arith_proof.h
index 788e4bd86..d980654c4 100644
--- a/src/proof/arith_proof.h
+++ b/src/proof/arith_proof.h
@@ -29,13 +29,13 @@ namespace CVC4 {
//proof object outputted by TheoryArith
class ProofArith : public Proof {
private:
- static Node toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, unsigned tb, const LetMap& map);
+ static Node toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, unsigned tb, const ProofLetMap& map);
public:
ProofArith( theory::eq::EqProof * pf ) : d_proof( pf ) {}
//it is simply an equality engine proof
theory::eq::EqProof * d_proof;
void toStream(std::ostream& out);
- static void toStreamLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, const LetMap& map);
+ static void toStreamLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, const ProofLetMap& map);
};
@@ -68,12 +68,13 @@ public:
LFSCArithProof(theory::arith::TheoryArith* arith, TheoryProofEngine* proofEngine)
: ArithProof(arith, proofEngine)
{}
- virtual void printOwnedTerm(Expr term, std::ostream& os, const LetMap& map);
+ virtual void printOwnedTerm(Expr term, std::ostream& os, const ProofLetMap& map);
virtual void printOwnedSort(Type type, std::ostream& os);
- virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren);
+ virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren, const ProofLetMap& map);
virtual void printSortDeclarations(std::ostream& os, std::ostream& paren);
virtual void printTermDeclarations(std::ostream& os, std::ostream& paren);
virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren);
+ virtual void printAliasingDeclarations(std::ostream& os, std::ostream& paren);
};
diff --git a/src/proof/array_proof.cpp b/src/proof/array_proof.cpp
index 8aba8dce9..484bc70c8 100644
--- a/src/proof/array_proof.cpp
+++ b/src/proof/array_proof.cpp
@@ -81,27 +81,45 @@ inline static bool match(TNode n1, TNode n2) {
void ProofArray::setRowMergeTag(unsigned tag) {
d_reasonRow = tag;
+ d_proofPrinter.d_row = tag;
}
void ProofArray::setRow1MergeTag(unsigned tag) {
d_reasonRow1 = tag;
+ d_proofPrinter.d_row1 = tag;
}
void ProofArray::setExtMergeTag(unsigned tag) {
d_reasonExt = tag;
+ d_proofPrinter.d_ext = tag;
+}
+
+unsigned ProofArray::getRowMergeTag() const {
+ return d_reasonRow;
+}
+
+unsigned ProofArray::getRow1MergeTag() const {
+ return d_reasonRow1;
+}
+
+unsigned ProofArray::getExtMergeTag() const {
+ return d_reasonExt;
}
void ProofArray::toStream(std::ostream& out) {
+ ProofLetMap map;
+ toStream(out, map);
+}
+
+void ProofArray::toStream(std::ostream& out, const ProofLetMap& map) {
Trace("pf::array") << "; Print Array proof..." << std::endl;
- //AJR : carry this further?
- LetMap map;
toStreamLFSC(out, ProofManager::getArrayProof(), d_proof, map);
Debug("pf::array") << "; Print Array proof done!" << std::endl;
}
-void ProofArray::toStreamLFSC(std::ostream& out, TheoryProof* tp, theory::eq::EqProof* pf, const LetMap& map) {
+void ProofArray::toStreamLFSC(std::ostream& out, TheoryProof* tp, theory::eq::EqProof* pf, const ProofLetMap& map) {
Debug("pf::array") << "Printing array proof in LFSC : " << std::endl;
- pf->debug_print("pf::array");
+ pf->debug_print("pf::array", 0, &d_proofPrinter);
Debug("pf::array") << std::endl;
toStreamRecLFSC( out, tp, pf, 0, map );
Debug("pf::array") << "Printing array proof in LFSC DONE" << std::endl;
@@ -111,10 +129,10 @@ Node ProofArray::toStreamRecLFSC(std::ostream& out,
TheoryProof* tp,
theory::eq::EqProof* pf,
unsigned tb,
- const LetMap& map) {
+ const ProofLetMap& map) {
Debug("pf::array") << std::endl << std::endl << "toStreamRecLFSC called. tb = " << tb << " . proof:" << std::endl;
- pf->debug_print("pf::array");
+ pf->debug_print("pf::array", 0, &d_proofPrinter);
Debug("pf::array") << std::endl;
if(tb == 0) {
@@ -150,7 +168,7 @@ Node ProofArray::toStreamRecLFSC(std::ostream& out,
pf->d_children[i + count]->d_node.isNull();
++count) {
Debug("pf::array") << "Found a congruence: " << std::endl;
- pf->d_children[i+count]->debug_print("pf::array");
+ pf->d_children[i+count]->debug_print("pf::array", 0, &d_proofPrinter);
congruenceClosures.push_back(pf->d_children[i+count]);
}
@@ -220,48 +238,48 @@ Node ProofArray::toStreamRecLFSC(std::ostream& out,
++i;
}
}
- Assert(neg >= 0);
+
+ bool disequalityFound = (neg >= 0);
+ if (!disequalityFound) {
+ Debug("pf::array") << "A disequality was NOT found. UNSAT due to merged constants" << std::endl;
+ Debug("pf::array") << "Proof for: " << pf->d_node << std::endl;
+ Assert(pf->d_node.getKind() == kind::EQUAL);
+ Assert(pf->d_node.getNumChildren() == 2);
+ Assert (pf->d_node[0].isConst() && pf->d_node[1].isConst());
+ }
Node n1;
std::stringstream ss, ss2;
//Assert(subTrans.d_children.size() == pf->d_children.size() - 1);
Debug("mgdx") << "\nsubtrans has " << subTrans.d_children.size() << " children\n";
- if(pf->d_children.size() > 2) {
+ if(!disequalityFound || pf->d_children.size() > 2) {
n1 = toStreamRecLFSC(ss, tp, &subTrans, 1, map);
} else {
n1 = toStreamRecLFSC(ss, tp, subTrans.d_children[0], 1, map);
Debug("mgdx") << "\nsubTrans unique child " << subTrans.d_children[0]->d_id << " was proven\ngot: " << n1 << std::endl;
}
- Node n2 = pf->d_children[neg]->d_node;
- Assert(n2.getKind() == kind::NOT);
- Debug("mgdx") << "\nhave proven: " << n1 << std::endl;
- Debug("mgdx") << "n2 is " << n2 << std::endl;
- Debug("mgdx") << "n2->d_id is " << pf->d_children[neg]->d_id << std::endl;
- Debug("mgdx") << "n2[0] is " << n2[0] << std::endl;
+ out << "(clausify_false (contra _ ";
- if (n2[0].getNumChildren() > 0) { Debug("mgdx") << "\nn2[0]: " << n2[0][0] << std::endl; }
- if (n1.getNumChildren() > 1) { Debug("mgdx") << "n1[1]: " << n1[1] << std::endl; }
+ if (disequalityFound) {
+ Node n2 = pf->d_children[neg]->d_node;
+ Assert(n2.getKind() == kind::NOT);
+ Debug("mgdx") << "\nhave proven: " << n1 << std::endl;
+ Debug("mgdx") << "n2 is " << n2 << std::endl;
+ Debug("mgdx") << "n2->d_id is " << pf->d_children[neg]->d_id << std::endl;
+ Debug("mgdx") << "n2[0] is " << n2[0] << std::endl;
- if (pf->d_children[neg]->d_id == d_reasonExt) {
- // The negative node was created by an EXT rule; e.g. it is a[k]!=b[k], due to a!=b.
-
- // (clausify_false (contra _ .gl2 (or_elim_1 _ _ .gl1 FIXME))))))) (\ .glemc6
-
- out << "(clausify_false (contra _ ";
- out << ss.str();
+ if (n2[0].getNumChildren() > 0) { Debug("mgdx") << "\nn2[0]: " << n2[0][0] << std::endl; }
+ if (n1.getNumChildren() > 1) { Debug("mgdx") << "n1[1]: " << n1[1] << std::endl; }
- toStreamRecLFSC(ss2, tp, pf->d_children[neg], 1, map);
-
- out << " ";
- out << ss2.str();
- out << "))";
-
- } else {
- // The negative node is, e.g., a pure equality
- out << "(clausify_false (contra _ ";
-
- if(n2[0].getKind() == kind::APPLY_UF) {
+ if ((pf->d_children[neg]->d_id == d_reasonExt) ||
+ (pf->d_children[neg]->d_id == theory::eq::MERGED_THROUGH_TRANS)) {
+ // Ext case: The negative node was created by an EXT rule; e.g. it is a[k]!=b[k], due to a!=b.
+ out << ss.str();
+ out << " ";
+ toStreamRecLFSC(ss2, tp, pf->d_children[neg], 1, map);
+ out << ss2.str();
+ } else if (n2[0].getKind() == kind::APPLY_UF) {
out << "(trans _ _ _ _ ";
out << "(symm _ _ _ ";
out << ss.str();
@@ -276,16 +294,27 @@ Node ProofArray::toStreamRecLFSC(std::ostream& out,
Debug("pf::array") << "ArrayProof::toStream: getLitName( " << n2[0] << " ) = " <<
ProofManager::getLitName(n2[0]) << std::endl;
- out << " " << ProofManager::getLitName(n2[0]) << "))" << std::endl;
+ out << " " << ProofManager::getLitName(n2[0]);
}
+ } else {
+ Node n2 = pf->d_node;
+ Assert(n2.getKind() == kind::EQUAL);
+ Assert((n1[0] == n2[0] && n1[1] == n2[1]) || (n1[1] == n2[0] && n1[0] == n2[1]));
+
+ out << ss.str();
+ out << " ";
+ ProofManager::getTheoryProofEngine()->printConstantDisequalityProof(out,
+ n1[0].toExpr(),
+ n1[1].toExpr());
}
+ out << "))" << std::endl;
return Node();
}
if (pf->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE) {
Debug("mgd") << "\nok, looking at congruence:\n";
- pf->debug_print("mgd");
+ pf->debug_print("mgd", 0, &d_proofPrinter);
std::stack<const theory::eq::EqProof*> stk;
for(const theory::eq::EqProof* pf2 = pf; pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE; pf2 = pf2->d_children[0]) {
Assert(!pf2->d_node.isNull());
@@ -315,7 +344,7 @@ Node ProofArray::toStreamRecLFSC(std::ostream& out,
Debug("mgd") << "\nok, in FIRST cong[" << stk.size() << "]" << "\n";
- pf2->debug_print("mgd");
+ pf2->debug_print("mgd", 0, &d_proofPrinter);
// Temp
Debug("mgd") << "n1 is a proof for: " << pf2->d_children[0]->d_node << ". It is: " << n1 << std::endl;
Debug("mgd") << "n2 is a proof for: " << pf2->d_children[1]->d_node << ". It is: " << n2 << std::endl;
@@ -332,7 +361,7 @@ Node ProofArray::toStreamRecLFSC(std::ostream& out,
Debug("mgd") << "SIDE IS 1\n";
if(!match(pf2->d_node, n1[1])) {
Debug("mgd") << "IN BAD CASE, our first subproof is\n";
- pf2->d_children[0]->debug_print("mgd");
+ pf2->d_children[0]->debug_print("mgd", 0, &d_proofPrinter);
}
Assert(match(pf2->d_node, n1[1]));
side = 1;
@@ -546,6 +575,20 @@ Node ProofArray::toStreamRecLFSC(std::ostream& out,
return pf->d_node;
}
+ else if (pf->d_id == theory::eq::MERGED_THROUGH_CONSTANTS) {
+ Debug("pf::array") << "Proof for: " << pf->d_node << std::endl;
+ Assert(pf->d_node.getKind() == kind::NOT);
+ Node n = pf->d_node[0];
+ Assert(n.getKind() == kind::EQUAL);
+ Assert(n.getNumChildren() == 2);
+ Assert(n[0].isConst() && n[1].isConst());
+
+ ProofManager::getTheoryProofEngine()->printConstantDisequalityProof(out,
+ n[0].toExpr(),
+ n[1].toExpr());
+ return pf->d_node;
+ }
+
else if (pf->d_id == theory::eq::MERGED_THROUGH_TRANS) {
bool firstNeg = false;
bool secondNeg = false;
@@ -554,7 +597,7 @@ Node ProofArray::toStreamRecLFSC(std::ostream& out,
Assert(pf->d_children.size() >= 2);
std::stringstream ss;
Debug("mgd") << "\ndoing trans proof[[\n";
- pf->debug_print("mgd");
+ pf->debug_print("mgd", 0, &d_proofPrinter);
Debug("mgd") << "\n";
Node n1 = toStreamRecLFSC(ss, tp, pf->d_children[0], tb + 1, map);
Debug("mgd") << "\ndoing trans proof, got n1 " << n1 << "\n";
@@ -772,7 +815,7 @@ Node ProofArray::toStreamRecLFSC(std::ostream& out,
Warning() << "\n\ntrans proof failure at step " << i << "\n\n";
Warning() << "0 proves " << n1 << "\n";
Warning() << "1 proves " << n2 << "\n\n";
- pf->debug_print("mgdx",0);
+ pf->debug_print("mgdx", 0, &d_proofPrinter);
//toStreamRec(Warning.getStream(), pf, 0);
Warning() << "\n\n";
Unreachable();
@@ -931,6 +974,9 @@ Node ProofArray::toStreamRecLFSC(std::ostream& out,
t4 = pf->d_children[0]->d_node[0][side][0][2];
ret = pf->d_node;
+ // The order of indices needs to match; we might have to swap t1 and t2 and then apply symmetry.
+ bool swap = (t2 == pf->d_children[0]->d_node[0][side][0][1]);
+
Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\nt4 " << t4 << "\n";
Assert(pf->d_children.size() == 1);
@@ -939,28 +985,31 @@ Node ProofArray::toStreamRecLFSC(std::ostream& out,
Debug("pf::array") << "Subproof is: " << ss.str() << std::endl;
+ if (swap) {
+ out << "(symm _ _ _ ";
+ }
+
out << "(negativerow _ _ ";
- tp->printTerm(t1.toExpr(), out, map);
+ tp->printTerm(swap ? t2.toExpr() : t1.toExpr(), out, map);
out << " ";
- tp->printTerm(t2.toExpr(), out, map);
+ tp->printTerm(swap ? t1.toExpr() : t2.toExpr(), out, map);
out << " ";
tp->printTerm(t3.toExpr(), out, map);
out << " ";
tp->printTerm(t4.toExpr(), out, map);
out << " ";
-
- // if (subproof[0][1] == t3) {
- Debug("pf::array") << "Dont need symmetry!" << std::endl;
- out << ss.str();
- // } else {
- // Debug("pf::array") << "Need symmetry!" << std::endl;
- // out << "(negsymm _ _ _ " << ss.str() << ")";
- // }
+ if (side != 0) {
+ out << "(negsymm _ _ _ " << ss.str() << ")";
+ } else {
+ out << ss.str();
+ }
out << ")";
- // Unreachable();
+ if (swap) {
+ out << ") ";
+ }
return ret;
}
@@ -1071,13 +1120,12 @@ void ArrayProof::registerTerm(Expr term) {
}
std::string ArrayProof::skolemToLiteral(Expr skolem) {
+ Debug("pf::array") << "ArrayProof::skolemToLiteral( " << skolem << ")" << std::endl;
Assert(d_skolemToLiteral.find(skolem) != d_skolemToLiteral.end());
return d_skolemToLiteral[skolem];
}
-void LFSCArrayProof::printOwnedTerm(Expr term, std::ostream& os, const LetMap& map) {
- Debug("pf::array") << std::endl << "(pf::array) LFSCArrayProof::printOwnedTerm: term = " << term << std::endl;
-
+void LFSCArrayProof::printOwnedTerm(Expr term, std::ostream& os, const ProofLetMap& map) {
Assert (theory::Theory::theoryOf(term) == theory::THEORY_ARRAY);
if (theory::Theory::theoryOf(term) != theory::THEORY_ARRAY) {
@@ -1154,23 +1202,35 @@ void LFSCArrayProof::printOwnedTerm(Expr term, std::ostream& os, const LetMap& m
void LFSCArrayProof::printOwnedSort(Type type, std::ostream& os) {
Debug("pf::array") << std::endl << "(pf::array) LFSCArrayProof::printOwnedSort: type is: " << type << std::endl;
Assert (type.isArray() || type.isSort());
- os << type <<" ";
+ if (type.isArray()){
+ ArrayType array_type(type);
+
+ Debug("pf::array") << "LFSCArrayProof::printOwnedSort: type is an array. Index type: "
+ << array_type.getIndexType()
+ << ", element type: " << array_type.getConstituentType() << std::endl;
+
+ os << "(Array ";
+ printSort(array_type.getIndexType(), os);
+ os << " ";
+ printSort(array_type.getConstituentType(), os);
+ os << ")";
+ } else {
+ os << type <<" ";
+ }
}
-void LFSCArrayProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren) {
+void LFSCArrayProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren, const ProofLetMap& map) {
os << " ;; Array Theory Lemma \n;;";
for (unsigned i = 0; i < lemma.size(); ++i) {
os << lemma[i] <<" ";
}
os <<"\n";
//os << " (clausify_false trust)";
- ArrayProof::printTheoryLemmaProof(lemma, os, paren);
+ ArrayProof::printTheoryLemmaProof(lemma, os, paren, map);
}
void LFSCArrayProof::printSortDeclarations(std::ostream& os, std::ostream& paren) {
// declaring the sorts
- Debug("pf::array") << "Arrays declaring sorts..." << std::endl;
-
for (TypeSet::const_iterator it = d_sorts.begin(); it != d_sorts.end(); ++it) {
if (!ProofManager::currentPM()->wasPrinted(*it)) {
os << "(% " << *it << " sort\n";
@@ -1229,6 +1289,7 @@ void LFSCArrayProof::printTermDeclarations(std::ostream& os, std::ostream& paren
void LFSCArrayProof::printDeferredDeclarations(std::ostream& os, std::ostream& paren) {
Debug("pf::array") << "Array: print deferred declarations called" << std::endl;
+ unsigned count = 1;
for (ExprSet::const_iterator it = d_skolemDeclarations.begin(); it != d_skolemDeclarations.end(); ++it) {
Expr term = *it;
Node equality = ProofManager::getSkolemizationManager()->getDisequality(*it);
@@ -1237,7 +1298,7 @@ void LFSCArrayProof::printDeferredDeclarations(std::ostream& os, std::ostream& p
<< "It is a witness for: " << equality << std::endl;
std::ostringstream newSkolemLiteral;
- newSkolemLiteral << ".sl" << d_skolemToLiteral.size();
+ newSkolemLiteral << ".sl" << count++;
std::string skolemLiteral = newSkolemLiteral.str();
d_skolemToLiteral[*it] = skolemLiteral;
@@ -1250,14 +1311,13 @@ void LFSCArrayProof::printDeferredDeclarations(std::ostream& os, std::ostream& p
Node array_one = equality[0][0];
Node array_two = equality[0][1];
- LetMap map;
-
+ ProofLetMap map;
os << "(ext _ _ ";
printTerm(array_one.toExpr(), os, map);
os << " ";
printTerm(array_two.toExpr(), os, map);
os << " (\\ ";
- printTerm(*it, os, map);
+ os << ProofManager::sanitize(*it);
os << " (\\ ";
os << skolemLiteral.c_str();
os << "\n";
@@ -1266,4 +1326,8 @@ void LFSCArrayProof::printDeferredDeclarations(std::ostream& os, std::ostream& p
}
}
+void LFSCArrayProof::printAliasingDeclarations(std::ostream& os, std::ostream& paren) {
+ // Nothing to do here at this point.
+}
+
} /* CVC4 namespace */
diff --git a/src/proof/array_proof.h b/src/proof/array_proof.h
index fb25c9433..69e62dbf3 100644
--- a/src/proof/array_proof.h
+++ b/src/proof/array_proof.h
@@ -30,10 +30,36 @@ namespace CVC4 {
//proof object outputted by TheoryARRAY
class ProofArray : public Proof {
private:
+ class ArrayProofPrinter : public theory::eq::EqProof::PrettyPrinter {
+ public:
+ ArrayProofPrinter() : d_row(0), d_row1(0), d_ext(0) {
+ }
+
+ std::string printTag(unsigned tag) {
+ if (tag == theory::eq::MERGED_THROUGH_CONGRUENCE) return "Congruence";
+ if (tag == theory::eq::MERGED_THROUGH_EQUALITY) return "Pure Equality";
+ if (tag == theory::eq::MERGED_THROUGH_REFLEXIVITY) return "Reflexivity";
+ if (tag == theory::eq::MERGED_THROUGH_CONSTANTS) return "Constants";
+ if (tag == theory::eq::MERGED_THROUGH_TRANS) return "Transitivity";
+
+ if (tag == d_row) return "Read Over Write";
+ if (tag == d_row1) return "Read Over Write (1)";
+ if (tag == d_ext) return "Extensionality";
+
+ std::ostringstream result;
+ result << tag;
+ return result.str();
+ }
+
+ unsigned d_row;
+ unsigned d_row1;
+ unsigned d_ext;
+ };
+
Node toStreamRecLFSC(std::ostream& out, TheoryProof* tp,
theory::eq::EqProof* pf,
unsigned tb,
- const LetMap& map);
+ const ProofLetMap& map);
/** Merge tag for ROW applications */
unsigned d_reasonRow;
@@ -41,18 +67,25 @@ private:
unsigned d_reasonRow1;
/** Merge tag for EXT applications */
unsigned d_reasonExt;
+
+ ArrayProofPrinter d_proofPrinter;
public:
ProofArray(theory::eq::EqProof* pf) : d_proof(pf) {}
//it is simply an equality engine proof
theory::eq::EqProof *d_proof;
void toStream(std::ostream& out);
- void toStreamLFSC(std::ostream& out, TheoryProof* tp, theory::eq::EqProof* pf, const LetMap& map);
+ void toStream(std::ostream& out, const ProofLetMap& map);
+ void toStreamLFSC(std::ostream& out, TheoryProof* tp, theory::eq::EqProof* pf, const ProofLetMap& map);
void registerSkolem(Node equality, Node skolem);
void setRowMergeTag(unsigned tag);
void setRow1MergeTag(unsigned tag);
void setExtMergeTag(unsigned tag);
+
+ unsigned getRowMergeTag() const;
+ unsigned getRow1MergeTag() const;
+ unsigned getExtMergeTag() const;
};
namespace theory {
@@ -85,12 +118,13 @@ public:
: ArrayProof(arrays, proofEngine)
{}
- virtual void printOwnedTerm(Expr term, std::ostream& os, const LetMap& map);
+ virtual void printOwnedTerm(Expr term, std::ostream& os, const ProofLetMap& map);
virtual void printOwnedSort(Type type, std::ostream& os);
- virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren);
+ virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren, const ProofLetMap& map);
virtual void printSortDeclarations(std::ostream& os, std::ostream& paren);
virtual void printTermDeclarations(std::ostream& os, std::ostream& paren);
virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren);
+ virtual void printAliasingDeclarations(std::ostream& os, std::ostream& paren);
};
diff --git a/src/proof/bitvector_proof.cpp b/src/proof/bitvector_proof.cpp
index b63782226..f19e45920 100644
--- a/src/proof/bitvector_proof.cpp
+++ b/src/proof/bitvector_proof.cpp
@@ -15,14 +15,17 @@
**/
-#include "proof/bitvector_proof.h"
#include "options/bv_options.h"
+#include "proof/array_proof.h"
+#include "proof/bitvector_proof.h"
#include "proof/clause_id.h"
+#include "proof/proof_output_channel.h"
#include "proof/proof_utils.h"
#include "proof/sat_proof_implementation.h"
#include "prop/bvminisat/bvminisat.h"
#include "theory/bv/bitblaster_template.h"
#include "theory/bv/theory_bv.h"
+#include "theory/bv/theory_bv_rewrite_rules.h"
using namespace CVC4::theory;
using namespace CVC4::theory::bv;
@@ -80,20 +83,40 @@ BVSatProof* BitVectorProof::getSatProof() {
}
void BitVectorProof::registerTermBB(Expr term) {
+ Debug("pf::bv") << "BitVectorProof::registerTermBB( " << term << " )" << std::endl;
+
if (d_seenBBTerms.find(term) != d_seenBBTerms.end())
return;
d_seenBBTerms.insert(term);
d_bbTerms.push_back(term);
+
+ // If this term gets used in the final proof, we will want to register it. However,
+ // we don't know this at this point; and when the theory proof engine sees it, if it belongs
+ // to another theory, it won't register it with this proof. So, we need to tell the
+ // engine to inform us.
+
+ if (theory::Theory::theoryOf(term) != theory::THEORY_BV) {
+ Debug("pf::bv") << "\tMarking term " << term << " for future BV registration" << std::endl;
+ d_proofEngine->markTermForFutureRegistration(term, theory::THEORY_BV);
+ }
}
void BitVectorProof::registerAtomBB(Expr atom, Expr atom_bb) {
+ Debug("pf::bv") << "BitVectorProof::registerAtomBB( " << atom << ", " << atom_bb << " )" << std::endl;
+
Expr def = atom.iffExpr(atom_bb);
- d_bbAtoms.insert(std::make_pair(atom, def));
+ d_bbAtoms.insert(std::make_pair(atom, def));
registerTerm(atom);
+
+ // Register the atom's terms for bitblasting
+ registerTermBB(atom[0]);
+ registerTermBB(atom[1]);
}
void BitVectorProof::registerTerm(Expr term) {
+ Debug("pf::bv") << "BitVectorProof::registerTerm( " << term << " )" << std::endl;
+
d_usedBB.insert(term);
if (Theory::isLeafOf(term, theory::THEORY_BV) &&
@@ -101,6 +124,11 @@ void BitVectorProof::registerTerm(Expr term) {
d_declarations.insert(term);
}
+ Debug("pf::bv") << "Going to register children: " << std::endl;
+ for (unsigned i = 0; i < term.getNumChildren(); ++i) {
+ Debug("pf::bv") << "\t" << term[i] << std::endl;
+ }
+
// don't care about parametric operators for bv?
for (unsigned i = 0; i < term.getNumChildren(); ++i) {
d_proofEngine->registerTerm(term[i]);
@@ -108,6 +136,7 @@ void BitVectorProof::registerTerm(Expr term) {
}
std::string BitVectorProof::getBBTermName(Expr expr) {
+ Debug("pf::bv") << "BitVectorProof::getBBTermName( " << expr << " ) = bt" << expr.getId() << std::endl;
std::ostringstream os;
os << "bt"<< expr.getId();
return os.str();
@@ -122,6 +151,8 @@ void BitVectorProof::startBVConflict(CVC4::BVMinisat::Solver::TLit lit) {
}
void BitVectorProof::endBVConflict(const CVC4::BVMinisat::Solver::TLitVec& confl) {
+ Debug("pf::bv") << "BitVectorProof::endBVConflict called" << std::endl;
+
std::vector<Expr> expr_confl;
for (int i = 0; i < confl.size(); ++i) {
prop::SatLiteral lit = prop::BVMinisatSatSolver::toSatLiteral(confl[i]);
@@ -129,6 +160,7 @@ void BitVectorProof::endBVConflict(const CVC4::BVMinisat::Solver::TLitVec& confl
Expr expr_lit = lit.isNegated() ? atom.notExpr() : atom;
expr_confl.push_back(expr_lit);
}
+
Expr conflict = utils::mkSortedExpr(kind::OR, expr_confl);
Debug("pf::bv") << "Make conflict for " << conflict << std::endl;
@@ -144,30 +176,104 @@ void BitVectorProof::endBVConflict(const CVC4::BVMinisat::Solver::TLitVec& confl
ClauseId clause_id = d_resolutionProof->registerAssumptionConflict(confl);
d_bbConflictMap[conflict] = clause_id;
d_resolutionProof->endResChain(clause_id);
- Debug("pf::bv") << "BitVectorProof::endBVConflict id"<<clause_id<< " => " << conflict << "\n";
+ Debug("pf::bv") << "BitVectorProof::endBVConflict id" <<clause_id<< " => " << conflict << "\n";
d_isAssumptionConflict = false;
}
void BitVectorProof::finalizeConflicts(std::vector<Expr>& conflicts) {
+
if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
Debug("pf::bv") << "Construct full proof." << std::endl;
d_resolutionProof->constructProof();
return;
}
- for(unsigned i = 0; i < conflicts.size(); ++i) {
+
+ for (unsigned i = 0; i < conflicts.size(); ++i) {
Expr confl = conflicts[i];
- Debug("pf::bv") << "Finalize conflict " << confl << std::endl;
- //Assert (d_bbConflictMap.find(confl) != d_bbConflictMap.end());
- if(d_bbConflictMap.find(confl) != d_bbConflictMap.end()){
+ Debug("pf::bv") << "Finalize conflict #" << i << ": " << confl << std::endl;
+
+ // Special case: if the conflict has a (true) or a (not false) in it, it is trivial...
+ bool ignoreConflict = false;
+ if ((confl.isConst() && confl.getConst<bool>()) ||
+ (confl.getKind() == kind::NOT && confl[0].isConst() && !confl[0].getConst<bool>())) {
+ ignoreConflict = true;
+ } else if (confl.getKind() == kind::OR) {
+ for (unsigned k = 0; k < confl.getNumChildren(); ++k) {
+ if ((confl[k].isConst() && confl[k].getConst<bool>()) ||
+ (confl[k].getKind() == kind::NOT && confl[k][0].isConst() && !confl[k][0].getConst<bool>())) {
+ ignoreConflict = true;
+ }
+ }
+ }
+ if (ignoreConflict) {
+ Debug("pf::bv") << "Ignoring conflict due to (true) or (not false)" << std::endl;
+ continue;
+ }
+
+ if (d_bbConflictMap.find(confl) != d_bbConflictMap.end()) {
ClauseId id = d_bbConflictMap[confl];
d_resolutionProof->collectClauses(id);
- }else{
- Debug("pf::bv") << "Do not collect clauses for " << confl << std::endl;
+ } else {
+ // There is no exact match for our conflict, but maybe it is a subset of another conflict
+ ExprToClauseId::const_iterator it;
+ bool matchFound = false;
+ for (it = d_bbConflictMap.begin(); it != d_bbConflictMap.end(); ++it) {
+ Expr possibleMatch = it->first;
+ if (possibleMatch.getKind() != kind::OR) {
+ // This is a single-node conflict. If this node is in the conflict we're trying to prove,
+ // we have a match.
+ for (unsigned k = 0; k < confl.getNumChildren(); ++k) {
+ if (confl[k] == possibleMatch) {
+ matchFound = true;
+ d_resolutionProof->collectClauses(it->second);
+ break;
+ }
+ }
+ } else {
+ if (possibleMatch.getNumChildren() > confl.getNumChildren())
+ continue;
+
+ unsigned k = 0;
+ bool matching = true;
+ for (unsigned j = 0; j < possibleMatch.getNumChildren(); ++j) {
+ // j is the index in possibleMatch
+ // k is the index in confl
+ while (k < confl.getNumChildren() && confl[k] != possibleMatch[j]) {
+ ++k;
+ }
+ if (k == confl.getNumChildren()) {
+ // We couldn't find a match for possibleMatch[j], so not a match
+ matching = false;
+ break;
+ }
+ }
+
+ if (matching) {
+ Debug("pf::bv") << "Collecting info from a sub-conflict" << std::endl;
+ d_resolutionProof->collectClauses(it->second);
+ matchFound = true;
+ break;
+ }
+ }
+ }
+
+ if (!matchFound) {
+ Debug("pf::bv") << "Do not collect clauses for " << confl << std::endl
+ << "Dumping existing conflicts:" << std::endl;
+
+ i = 0;
+ for (it = d_bbConflictMap.begin(); it != d_bbConflictMap.end(); ++it) {
+ ++i;
+ Debug("pf::bv") << "\tConflict #" << i << ": " << it->first << std::endl;
+ }
+
+ Unreachable();
+ }
}
}
}
-void LFSCBitVectorProof::printOwnedTerm(Expr term, std::ostream& os, const LetMap& map) {
+void LFSCBitVectorProof::printOwnedTerm(Expr term, std::ostream& os, const ProofLetMap& map) {
Debug("pf::bv") << std::endl << "(pf::bv) LFSCBitVectorProof::printOwnedTerm( " << term << " ), theory is: "
<< Theory::theoryOf(term) << std::endl;
@@ -238,17 +344,31 @@ void LFSCBitVectorProof::printOwnedTerm(Expr term, std::ostream& os, const LetMa
printBitOf(term, os, map);
return;
}
- case kind::VARIABLE:
+
+ case kind::VARIABLE: {
+ os << "(a_var_bv " << utils::getSize(term)<< " " << ProofManager::sanitize(term) << ")";
+ return;
+ }
+
case kind::SKOLEM: {
- os << "(a_var_bv " << utils::getSize(term)<<" " << ProofManager::sanitize(term) <<")";
+
+ // TODO: we need to distinguish between "real" skolems (e.g. from array) and "fake" skolems,
+ // like ITE terms. Is there a more elegant way?
+
+ if (ProofManager::getSkolemizationManager()->isSkolem(term)) {
+ os << ProofManager::sanitize(term);
+ } else {
+ os << "(a_var_bv " << utils::getSize(term)<< " " << ProofManager::sanitize(term) << ")";
+ }
return;
}
+
default:
Unreachable();
}
}
-void LFSCBitVectorProof::printBitOf(Expr term, std::ostream& os, const LetMap& map) {
+void LFSCBitVectorProof::printBitOf(Expr term, std::ostream& os, const ProofLetMap& map) {
Assert (term.getKind() == kind::BITVECTOR_BITOF);
unsigned bit = term.getOperator().getConst<BitVectorBitOf>().bitIndex;
Expr var = term[0];
@@ -258,14 +378,7 @@ void LFSCBitVectorProof::printBitOf(Expr term, std::ostream& os, const LetMap& m
<< ", var = " << var << std::endl;
os << "(bitof ";
- if (var.getKind() == kind::VARIABLE || var.getKind() == kind::SKOLEM) {
- // If var is "simple", we can just sanitize and print
- os << ProofManager::sanitize(var);
- } else {
- // If var is "complex", it can belong to another theory. Therefore, dispatch again.
- d_proofEngine->printBoundTerm(var, os, map);
- }
-
+ os << d_exprToVariableName[var];
os << " " << bit << ")";
}
@@ -283,7 +396,7 @@ void LFSCBitVectorProof::printConstant(Expr term, std::ostream& os) {
os << paren.str();
}
-void LFSCBitVectorProof::printOperatorNary(Expr term, std::ostream& os, const LetMap& map) {
+void LFSCBitVectorProof::printOperatorNary(Expr term, std::ostream& os, const ProofLetMap& map) {
std::string op = utils::toLFSCKind(term.getKind());
std::ostringstream paren;
std::string holes = term.getKind() == kind::BITVECTOR_CONCAT ? "_ _ " : "";
@@ -301,7 +414,7 @@ void LFSCBitVectorProof::printOperatorNary(Expr term, std::ostream& os, const Le
}
}
-void LFSCBitVectorProof::printOperatorUnary(Expr term, std::ostream& os, const LetMap& map) {
+void LFSCBitVectorProof::printOperatorUnary(Expr term, std::ostream& os, const ProofLetMap& map) {
os <<"(";
os << utils::toLFSCKind(term.getKind()) << " " << utils::getSize(term) <<" ";
os << " ";
@@ -309,7 +422,7 @@ void LFSCBitVectorProof::printOperatorUnary(Expr term, std::ostream& os, const L
os <<")";
}
-void LFSCBitVectorProof::printPredicate(Expr term, std::ostream& os, const LetMap& map) {
+void LFSCBitVectorProof::printPredicate(Expr term, std::ostream& os, const ProofLetMap& map) {
os <<"(";
os << utils::toLFSCKind(term.getKind()) << " " << utils::getSize(term[0]) <<" ";
os << " ";
@@ -319,7 +432,7 @@ void LFSCBitVectorProof::printPredicate(Expr term, std::ostream& os, const LetMa
os <<")";
}
-void LFSCBitVectorProof::printOperatorParametric(Expr term, std::ostream& os, const LetMap& map) {
+void LFSCBitVectorProof::printOperatorParametric(Expr term, std::ostream& os, const ProofLetMap& map) {
os <<"(";
os << utils::toLFSCKind(term.getKind()) << " " << utils::getSize(term) <<" ";
os <<" ";
@@ -349,14 +462,16 @@ void LFSCBitVectorProof::printOperatorParametric(Expr term, std::ostream& os, co
void LFSCBitVectorProof::printOwnedSort(Type type, std::ostream& os) {
Debug("pf::bv") << std::endl << "(pf::bv) LFSCBitVectorProof::printOwnedSort( " << type << " )" << std::endl;
-
Assert (type.isBitVector());
unsigned width = utils::getSize(type);
os << "(BitVec "<<width<<")";
}
-void LFSCBitVectorProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren) {
+void LFSCBitVectorProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren, const ProofLetMap& map) {
+ Debug("pf::bv") << "(pf::bv) LFSCBitVectorProof::printTheoryLemmaProof called" << std::endl;
Expr conflict = utils::mkSortedExpr(kind::OR, lemma);
+ Debug("pf::bv") << "\tconflict = " << conflict << std::endl;
+
if (d_bbConflictMap.find(conflict) != d_bbConflictMap.end()) {
std::ostringstream lemma_paren;
for (unsigned i = 0; i < lemma.size(); ++i) {
@@ -377,7 +492,7 @@ void LFSCBitVectorProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::os
// print corresponding literal in bv sat solver
prop::SatVariable bb_var = d_cnfProof->getLiteral(lit).getSatVariable();
os << pm->getAtomName(bb_var, "bb");
- os <<"(\\unit"<<bb_var<<"\n";
+ os <<"(\\ unit"<<bb_var<<"\n";
lemma_paren <<")";
}
Expr lem = utils::mkOr(lemma);
@@ -386,11 +501,134 @@ void LFSCBitVectorProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::os
d_resolutionProof->printAssumptionsResolution(lemma_id, os, lemma_paren);
os <<lemma_paren.str();
} else {
- Unreachable(); // If we were to reach here, we would crash because BV replay is currently not supported
- // in TheoryProof::printTheoryLemmaProof()
- Debug("pf::bv") << std::endl << "; Print non-bitblast theory conflict " << conflict << std::endl;
- BitVectorProof::printTheoryLemmaProof( lemma, os, paren );
+ Debug("pf::bv") << "Found a non-recorded conflict. Looking for a matching sub-conflict..."
+ << std::endl;
+
+ bool matching;
+
+ ExprToClauseId::const_iterator it;
+ unsigned i = 0;
+ for (it = d_bbConflictMap.begin(); it != d_bbConflictMap.end(); ++it) {
+ // Our conflict is sorted, and the records are also sorted.
+ ++i;
+ Expr possibleMatch = it->first;
+
+ if (possibleMatch.getKind() != kind::OR) {
+ // This is a single-node conflict. If this node is in the conflict we're trying to prove,
+ // we have a match.
+ matching = false;
+
+ for (unsigned k = 0; k < conflict.getNumChildren(); ++k) {
+ if (conflict[k] == possibleMatch) {
+ matching = true;
+ break;
+ }
+ }
+ } else {
+ if (possibleMatch.getNumChildren() > conflict.getNumChildren())
+ continue;
+
+ unsigned k = 0;
+
+ matching = true;
+ for (unsigned j = 0; j < possibleMatch.getNumChildren(); ++j) {
+ // j is the index in possibleMatch
+ // k is the index in conflict
+ while (k < conflict.getNumChildren() && conflict[k] != possibleMatch[j]) {
+ ++k;
+ }
+ if (k == conflict.getNumChildren()) {
+ // We couldn't find a match for possibleMatch[j], so not a match
+ matching = false;
+ break;
+ }
+ }
+ }
+
+ if (matching) {
+ Debug("pf::bv") << "Found a match with conflict #" << i << ": " << std::endl << possibleMatch << std::endl;
+ // The rest is just a copy of the usual handling, if a precise match is found.
+ // We only use the literals that appear in the matching conflict, though, and not in the
+ // original lemma - as these may not have even been bit blasted!
+ std::ostringstream lemma_paren;
+
+ if (possibleMatch.getKind() == kind::OR) {
+ for (unsigned i = 0; i < possibleMatch.getNumChildren(); ++i) {
+ Expr lit = possibleMatch[i];
+
+ if (lit.getKind() == kind::NOT) {
+ os << "(intro_assump_t _ _ _ ";
+ } else {
+ os << "(intro_assump_f _ _ _ ";
+ }
+ lemma_paren <<")";
+ // print corresponding literal in main sat solver
+ ProofManager* pm = ProofManager::currentPM();
+ CnfProof* cnf = pm->getCnfProof();
+ prop::SatLiteral main_lit = cnf->getLiteral(lit);
+ os << pm->getLitName(main_lit);
+ os <<" ";
+ // print corresponding literal in bv sat solver
+ prop::SatVariable bb_var = d_cnfProof->getLiteral(lit).getSatVariable();
+ os << pm->getAtomName(bb_var, "bb");
+ os <<"(\\ unit"<<bb_var<<"\n";
+ lemma_paren <<")";
+ }
+ } else {
+ // The conflict only consists of one node, either positive or negative.
+ Expr lit = possibleMatch;
+ if (lit.getKind() == kind::NOT) {
+ os << "(intro_assump_t _ _ _ ";
+ } else {
+ os << "(intro_assump_f _ _ _ ";
+ }
+ lemma_paren <<")";
+ // print corresponding literal in main sat solver
+ ProofManager* pm = ProofManager::currentPM();
+ CnfProof* cnf = pm->getCnfProof();
+ prop::SatLiteral main_lit = cnf->getLiteral(lit);
+ os << pm->getLitName(main_lit);
+ os <<" ";
+ // print corresponding literal in bv sat solver
+ prop::SatVariable bb_var = d_cnfProof->getLiteral(lit).getSatVariable();
+ os << pm->getAtomName(bb_var, "bb");
+ os <<"(\\ unit"<<bb_var<<"\n";
+ lemma_paren <<")";
+ }
+
+ ClauseId lemma_id = it->second;
+ d_resolutionProof->printAssumptionsResolution(lemma_id, os, lemma_paren);
+ os <<lemma_paren.str();
+
+ return;
+ }
+ }
+
+ // We failed to find a matching sub conflict. The last hope is that the
+ // conflict has a FALSE assertion in it; this can happen in some corner cases,
+ // where the FALSE is the result of a rewrite.
+
+ for (unsigned i = 0; i < lemma.size(); ++i) {
+ if (lemma[i].getKind() == kind::NOT && lemma[i][0] == utils::mkFalse()) {
+ Debug("pf::bv") << "Lemma has a (not false) literal" << std::endl;
+ os << "(clausify_false ";
+ os << ProofManager::getLitName(lemma[i]);
+ os << ")";
+ return;
+ }
+ }
+
+ Debug("pf::bv") << "Failed to find a matching sub-conflict..." << std::endl
+ << "Dumping existing conflicts:" << std::endl;
+
+ i = 0;
+ for (it = d_bbConflictMap.begin(); it != d_bbConflictMap.end(); ++it) {
+ ++i;
+ Debug("pf::bv") << "\tConflict #" << i << ": " << it->first << std::endl;
+ }
+
+ Unreachable();
}
}
@@ -402,7 +640,14 @@ void LFSCBitVectorProof::printTermDeclarations(std::ostream& os, std::ostream& p
ExprSet::const_iterator it = d_declarations.begin();
ExprSet::const_iterator end = d_declarations.end();
for (; it != end; ++it) {
- os << "(% " << ProofManager::sanitize(*it) <<" var_bv\n";
+ if ((it->isVariable() || it->isConst()) && !ProofManager::getSkolemizationManager()->isSkolem(*it)) {
+ d_exprToVariableName[*it] = ProofManager::sanitize(*it);
+ } else {
+ std::string newAlias = assignAlias(*it);
+ d_exprToVariableName[*it] = newAlias;
+ }
+
+ os << "(% " << d_exprToVariableName[*it] <<" var_bv" << "\n";
paren <<")";
}
}
@@ -411,15 +656,43 @@ void LFSCBitVectorProof::printDeferredDeclarations(std::ostream& os, std::ostrea
// Nothing to do here at this point.
}
+void LFSCBitVectorProof::printAliasingDeclarations(std::ostream& os, std::ostream& paren) {
+ // Print "trust" statements to bind complex bv variables to their associated terms
+
+ ExprToString::const_iterator it = d_assignedAliases.begin();
+ ExprToString::const_iterator end = d_assignedAliases.end();
+
+ for (; it != end; ++it) {
+ Debug("pf::bv") << "Printing aliasing declaration for: " << *it << std::endl;
+ std::stringstream declaration;
+ declaration << ".fbvd" << d_aliasToBindDeclaration.size();
+ d_aliasToBindDeclaration[it->second] = declaration.str();
+
+ os << "(th_let_pf _ ";
+
+ os << "(trust_f ";
+ os << "(= (BitVec " << utils::getSize(it->first) << ") ";
+ os << "(a_var_bv " << utils::getSize(it->first) << " " << it->second << ") ";
+ ProofLetMap emptyMap;
+ d_proofEngine->printBoundTerm(it->first, os, emptyMap);
+ os << ")) ";
+ os << "(\\ "<< d_aliasToBindDeclaration[it->second] << "\n";
+ paren << "))";
+ }
+
+ os << "\n";
+}
+
void LFSCBitVectorProof::printTermBitblasting(Expr term, std::ostream& os) {
// TODO: once we have the operator elimination rules remove those that we
// eliminated
Assert (term.getType().isBitVector());
Kind kind = term.getKind();
- if (Theory::isLeafOf(term, theory::THEORY_BV) &&
- !term.isConst()) {
- os << "(bv_bbl_var "<<utils::getSize(term) << " " << ProofManager::sanitize(term) <<" _ )";
+ if (Theory::isLeafOf(term, theory::THEORY_BV) && !term.isConst()) {
+ // A term is a leaf if it has no children, or if it belongs to another theory
+ os << "(bv_bbl_var " << utils::getSize(term) << " " << d_exprToVariableName[term];
+ os << " _)";
return;
}
@@ -448,14 +721,18 @@ void LFSCBitVectorProof::printTermBitblasting(Expr term, std::ostream& os) {
case kind::BITVECTOR_PLUS :
case kind::BITVECTOR_SUB :
case kind::BITVECTOR_CONCAT : {
- for (unsigned i =0; i < term.getNumChildren() - 1; ++i) {
+ Debug("pf::bv") << "Bitblasing kind = " << kind << std::endl;
+
+ for (int i = term.getNumChildren() - 1; i > 0; --i) {
os <<"(bv_bbl_"<< utils::toLFSCKind(kind);
+
if (kind == kind::BITVECTOR_CONCAT) {
- os << " " << utils::getSize(term) <<" _ ";
+ os << " " << utils::getSize(term) << " _";
}
- os <<" _ _ _ _ _ _ ";
+ os << " _ _ _ _ _ _ ";
}
- os << getBBTermName(term[0]) <<" ";
+
+ os << getBBTermName(term[0]) << " ";
for (unsigned i = 1; i < term.getNumChildren(); ++i) {
os << getBBTermName(term[i]);
@@ -463,22 +740,25 @@ void LFSCBitVectorProof::printTermBitblasting(Expr term, std::ostream& os) {
}
return;
}
+
case kind::BITVECTOR_NEG :
case kind::BITVECTOR_NOT :
case kind::BITVECTOR_ROTATE_LEFT :
case kind::BITVECTOR_ROTATE_RIGHT : {
- os <<"(bv_bbl_"<<utils::toLFSCKind(kind);
- os <<" _ _ _ _ ";
+ os << "(bv_bbl_"<<utils::toLFSCKind(kind);
+ os << " _ _ _ _ ";
os << getBBTermName(term[0]);
- os <<")";
+ os << ")";
return;
}
case kind::BITVECTOR_EXTRACT : {
- os <<"(bv_bbl_"<<utils::toLFSCKind(kind) <<" ";
- os << utils::getSize(term) << " ";
+ os <<"(bv_bbl_"<<utils::toLFSCKind(kind);
+
+ os << " " << utils::getSize(term) << " ";
os << utils::getExtractHigh(term) << " ";
os << utils::getExtractLow(term) << " ";
os << " _ _ _ _ ";
+
os << getBBTermName(term[0]);
os <<")";
return;
@@ -486,8 +766,8 @@ void LFSCBitVectorProof::printTermBitblasting(Expr term, std::ostream& os) {
case kind::BITVECTOR_REPEAT :
case kind::BITVECTOR_ZERO_EXTEND :
case kind::BITVECTOR_SIGN_EXTEND : {
- os <<"(bv_bbl_"<<utils::toLFSCKind(kind) <<" ";
- os << utils::getSize(term) <<" ";
+ os << "(bv_bbl_" << utils::toLFSCKind(kind) << " ";
+ os << utils::getSize(term) << " ";
if (term.getKind() == kind::BITVECTOR_REPEAT) {
unsigned amount = term.getOperator().getConst<BitVectorRepeat>().repeatAmount;
os << amount;
@@ -501,6 +781,7 @@ void LFSCBitVectorProof::printTermBitblasting(Expr term, std::ostream& os) {
unsigned amount = term.getOperator().getConst<BitVectorZeroExtend>().zeroExtendAmount;
os << amount;
}
+
os <<" _ _ _ _ ";
os << getBBTermName(term[0]);
os <<")";
@@ -516,7 +797,7 @@ void LFSCBitVectorProof::printTermBitblasting(Expr term, std::ostream& os) {
case kind::BITVECTOR_SHL :
case kind::BITVECTOR_LSHR :
case kind::BITVECTOR_ASHR : {
- // these are terms for which bit-blasting is not supported yet
+ // these are terms for which bit-blasting is not supported yet
std::ostringstream paren;
os <<"(trust_bblast_term _ ";
paren <<")";
@@ -539,7 +820,7 @@ void LFSCBitVectorProof::printTermBitblasting(Expr term, std::ostream& os) {
}
}
-void LFSCBitVectorProof::printAtomBitblasting(Expr atom, std::ostream& os) {
+void LFSCBitVectorProof::printAtomBitblasting(Expr atom, std::ostream& os, bool swap) {
Kind kind = atom.getKind();
switch(kind) {
case kind::BITVECTOR_ULT :
@@ -550,11 +831,19 @@ void LFSCBitVectorProof::printAtomBitblasting(Expr atom, std::ostream& os) {
case kind::BITVECTOR_SLE :
case kind::BITVECTOR_SGT :
case kind::BITVECTOR_SGE :
- case kind::EQUAL:
- {
- os <<"(bv_bbl_" << utils::toLFSCKind(atom.getKind());
+ case kind::EQUAL: {
+ Debug("pf::bv") << "Bitblasing kind = " << kind << std::endl;
+
+ os << "(bv_bbl_" << utils::toLFSCKind(atom.getKind());
+
+ if (swap) {os << "_swap";}
+
os << " _ _ _ _ _ _ ";
- os << getBBTermName(atom[0])<<" " << getBBTermName(atom[1]) <<")";
+ os << getBBTermName(atom[0]);
+ os << " ";
+ os << getBBTermName(atom[1]);
+ os << ")";
+
return;
}
default:
@@ -562,19 +851,62 @@ void LFSCBitVectorProof::printAtomBitblasting(Expr atom, std::ostream& os) {
}
}
+void LFSCBitVectorProof::printAtomBitblastingToFalse(Expr atom, std::ostream& os) {
+ Assert(atom.getKind() == kind::EQUAL);
+
+ os << "(bv_bbl_=_false";
+ os << " _ _ _ _ _ _ ";
+ os << getBBTermName(atom[0]);
+
+ os << " ";
+
+ os << getBBTermName(atom[1]);
+
+ os << ")";
+}
void LFSCBitVectorProof::printBitblasting(std::ostream& os, std::ostream& paren) {
// bit-blast terms
+ {
+ Debug("pf::bv") << "LFSCBitVectorProof::printBitblasting: the bitblasted terms are: " << std::endl;
+ std::vector<Expr>::const_iterator it = d_bbTerms.begin();
+ std::vector<Expr>::const_iterator end = d_bbTerms.end();
+
+ Assert(options::bitblastMode() != theory::bv::BITBLAST_MODE_EAGER);
+
+ for (; it != end; ++it) {
+ if (d_usedBB.find(*it) == d_usedBB.end()) {
+ Debug("pf::bv") << "\t" << *it << "\t(UNUSED)" << std::endl;
+ } else {
+ Debug("pf::bv") << "\t" << *it << std::endl;
+ }
+ }
+
+ Debug("pf::bv") << std::endl;
+ }
+
std::vector<Expr>::const_iterator it = d_bbTerms.begin();
std::vector<Expr>::const_iterator end = d_bbTerms.end();
for (; it != end; ++it) {
if (d_usedBB.find(*it) == d_usedBB.end() &&
options::bitblastMode() != theory::bv::BITBLAST_MODE_EAGER)
continue;
- os <<"(decl_bblast _ _ _ ";
- printTermBitblasting(*it, os);
- os << "(\\ "<< getBBTermName(*it);
- paren <<"\n))";
+
+ // Is this term has an alias, we inject it through the decl_bblast statement
+ if (hasAlias(*it)) {
+ os << "(decl_bblast_with_alias _ _ _ _ ";
+ printTermBitblasting(*it, os);
+ os << " " << d_aliasToBindDeclaration[d_assignedAliases[*it]] << " ";
+ os << "(\\ "<< getBBTermName(*it);
+ os << "\n";
+ paren <<"))";
+ } else {
+ os << "(decl_bblast _ _ _ ";
+ printTermBitblasting(*it, os);
+ os << "(\\ "<< getBBTermName(*it);
+ os << "\n";
+ paren <<"))";
+ }
}
// bit-blast atoms
ExprToExpr::const_iterator ait = d_bbAtoms.begin();
@@ -589,7 +921,35 @@ void LFSCBitVectorProof::printBitblasting(std::ostream& os, std::ostream& paren)
bool val = ait->first.getConst<bool>();
os << "(iff_symm " << (val ? "true" : "false" ) << ")";
} else {
- printAtomBitblasting(ait->first, os);
+ Assert(ait->first == ait->second[0]);
+
+ bool swap = false;
+ if (ait->first.getKind() == kind::EQUAL) {
+ Expr bitwiseEquivalence = ait->second[1];
+ if ((bitwiseEquivalence.getKind() == kind::CONST_BOOLEAN) && !bitwiseEquivalence.getConst<bool>()) {
+ printAtomBitblastingToFalse(ait->first, os);
+ } else {
+ if (bitwiseEquivalence.getKind() != kind::AND) {
+ // Just one bit
+ if (bitwiseEquivalence.getNumChildren() > 0 && bitwiseEquivalence[0].getKind() == kind::BITVECTOR_BITOF) {
+ swap = (ait->first[1] == bitwiseEquivalence[0][0]);
+ }
+ } else {
+ // Multiple bits
+ if (bitwiseEquivalence[0].getNumChildren() > 0 &&
+ bitwiseEquivalence[0][0].getKind() == kind::BITVECTOR_BITOF) {
+ swap = (ait->first[1] == bitwiseEquivalence[0][0][0]);
+ } else if (bitwiseEquivalence[0].getNumChildren() > 0 &&
+ bitwiseEquivalence[0][1].getKind() == kind::BITVECTOR_BITOF) {
+ swap = (ait->first[0] == bitwiseEquivalence[0][1][0]);
+ }
+ }
+
+ printAtomBitblasting(ait->first, os, swap);
+ }
+ } else {
+ printAtomBitblasting(ait->first, os, swap);
+ }
}
os <<"(\\ " << ProofManager::getPreprocessedAssertionName(ait->second) <<"\n";
@@ -597,34 +957,102 @@ void LFSCBitVectorProof::printBitblasting(std::ostream& os, std::ostream& paren)
}
}
-void LFSCBitVectorProof::printResolutionProof(std::ostream& os,
- std::ostream& paren) {
- // collect the input clauses used
+void LFSCBitVectorProof::calculateAtomsInBitblastingProof() {
+ // Collect the input clauses used
IdToSatClause used_lemmas;
IdToSatClause used_inputs;
- d_resolutionProof->collectClausesUsed(used_inputs,
- used_lemmas);
- Assert (used_lemmas.empty());
+ d_resolutionProof->collectClausesUsed(used_inputs, used_lemmas);
+ d_cnfProof->collectAtomsForClauses(used_inputs, d_atomsInBitblastingProof);
+ Assert(used_lemmas.empty());
+}
+
+const std::set<Node>* LFSCBitVectorProof::getAtomsInBitblastingProof() {
+ return &d_atomsInBitblastingProof;
+}
+void LFSCBitVectorProof::printResolutionProof(std::ostream& os,
+ std::ostream& paren,
+ ProofLetMap& letMap) {
// print mapping between theory atoms and internal SAT variables
- os << ";; BB atom mapping\n";
+ os << std::endl << ";; BB atom mapping\n" << std::endl;
- NodeSet atoms;
- d_cnfProof->collectAtomsForClauses(used_inputs,atoms);
+ std::set<Node>::iterator atomIt;
+ Debug("pf::bv") << std::endl << "BV Dumping atoms from inputs: " << std::endl << std::endl;
+ for (atomIt = d_atomsInBitblastingProof.begin(); atomIt != d_atomsInBitblastingProof.end(); ++atomIt) {
+ Debug("pf::bv") << "\tAtom: " << *atomIt << std::endl;
+ }
+ Debug("pf::bv") << std::endl;
// first print bit-blasting
printBitblasting(os, paren);
// print CNF conversion proof for bit-blasted facts
- d_cnfProof->printAtomMapping(atoms, os, paren);
- os << ";; Bit-blasting definitional clauses \n";
+ IdToSatClause used_lemmas;
+ IdToSatClause used_inputs;
+ d_resolutionProof->collectClausesUsed(used_inputs, used_lemmas);
+
+ d_cnfProof->printAtomMapping(d_atomsInBitblastingProof, os, paren, letMap);
+ os << std::endl << ";; Bit-blasting definitional clauses \n" << std::endl;
for (IdToSatClause::iterator it = used_inputs.begin();
it != used_inputs.end(); ++it) {
d_cnfProof->printCnfProofForClause(it->first, it->second, os, paren);
}
- os << ";; Bit-blasting learned clauses \n";
+ os << std::endl << " ;; Bit-blasting learned clauses \n" << std::endl;
d_resolutionProof->printResolutions(os, paren);
}
+std::string LFSCBitVectorProof::assignAlias(Expr expr) {
+ Assert(d_exprToVariableName.find(expr) == d_exprToVariableName.end());
+
+ std::stringstream ss;
+ ss << "fbv" << d_assignedAliases.size();
+ Debug("pf::bv") << "assignAlias( " << expr << ") = " << ss.str() << std::endl;
+ d_assignedAliases[expr] = ss.str();
+ return ss.str();
+}
+
+bool LFSCBitVectorProof::hasAlias(Expr expr) {
+ return d_assignedAliases.find(expr) != d_assignedAliases.end();
+}
+
+void LFSCBitVectorProof::printConstantDisequalityProof(std::ostream& os, Expr c1, Expr c2) {
+ Assert (c1.isConst());
+ Assert (c2.isConst());
+ Assert (utils::getSize(c1) == utils::getSize(c2));
+
+ os << "(bv_disequal_constants " << utils::getSize(c1) << " ";
+
+ std::ostringstream paren;
+
+ for (int i = utils::getSize(c1) - 1; i >= 0; --i) {
+ os << "(bvc ";
+ os << (utils::getBit(c1, i) ? "b1" : "b0") << " ";
+ paren << ")";
+ }
+ os << "bvn";
+ os << paren.str();
+
+ os << " ";
+
+ for (int i = utils::getSize(c2) - 1; i >= 0; --i) {
+ os << "(bvc ";
+ os << (utils::getBit(c2, i) ? "b1" : "b0") << " ";
+
+ }
+ os << "bvn";
+ os << paren.str();
+
+ os << ")";
+}
+
+void LFSCBitVectorProof::printRewriteProof(std::ostream& os, const Node &n1, const Node &n2) {
+ ProofLetMap emptyMap;
+ os << "(rr_bv_default ";
+ d_proofEngine->printBoundTerm(n2.toExpr(), os, emptyMap);
+ os << " ";
+ d_proofEngine->printBoundTerm(n1.toExpr(), os, emptyMap);
+ os << ")";
+}
+
} /* namespace CVC4 */
diff --git a/src/proof/bitvector_proof.h b/src/proof/bitvector_proof.h
index 4a1f4015d..a52292ec9 100644
--- a/src/proof/bitvector_proof.h
+++ b/src/proof/bitvector_proof.h
@@ -60,6 +60,7 @@ typedef __gnu_cxx::hash_set<Expr, ExprHashFunction> ExprSet;
typedef __gnu_cxx::hash_map<Expr, ClauseId, ExprHashFunction> ExprToClauseId;
typedef __gnu_cxx::hash_map<Expr, unsigned, ExprHashFunction> ExprToId;
typedef __gnu_cxx::hash_map<Expr, Expr, ExprHashFunction> ExprToExpr;
+typedef __gnu_cxx::hash_map<Expr, std::string, ExprHashFunction> ExprToString;
class BitVectorProof : public TheoryProof {
protected:
@@ -108,35 +109,52 @@ public:
virtual void registerTerm(Expr term);
virtual void printTermBitblasting(Expr term, std::ostream& os) = 0;
- virtual void printAtomBitblasting(Expr term, std::ostream& os) = 0;
+ virtual void printAtomBitblasting(Expr term, std::ostream& os, bool swap) = 0;
+ virtual void printAtomBitblastingToFalse(Expr term, std::ostream& os) = 0;
virtual void printBitblasting(std::ostream& os, std::ostream& paren) = 0;
- virtual void printResolutionProof(std::ostream& os, std::ostream& paren) = 0;
-
+ virtual void printResolutionProof(std::ostream& os, std::ostream& paren, ProofLetMap& letMap) = 0;
+ virtual const std::set<Node>* getAtomsInBitblastingProof() = 0;
+ virtual void calculateAtomsInBitblastingProof() = 0;
};
class LFSCBitVectorProof: public BitVectorProof {
void printConstant(Expr term, std::ostream& os);
- void printOperatorNary(Expr term, std::ostream& os, const LetMap& map);
- void printOperatorUnary(Expr term, std::ostream& os, const LetMap& map);
- void printPredicate(Expr term, std::ostream& os, const LetMap& map);
- void printOperatorParametric(Expr term, std::ostream& os, const LetMap& map);
- void printBitOf(Expr term, std::ostream& os, const LetMap& map);
+ void printOperatorNary(Expr term, std::ostream& os, const ProofLetMap& map);
+ void printOperatorUnary(Expr term, std::ostream& os, const ProofLetMap& map);
+ void printPredicate(Expr term, std::ostream& os, const ProofLetMap& map);
+ void printOperatorParametric(Expr term, std::ostream& os, const ProofLetMap& map);
+ void printBitOf(Expr term, std::ostream& os, const ProofLetMap& map);
+
+ ExprToString d_exprToVariableName;
+ ExprToString d_assignedAliases;
+ std::map<std::string, std::string> d_aliasToBindDeclaration;
+ std::string assignAlias(Expr expr);
+ bool hasAlias(Expr expr);
+
+ std::set<Node> d_atomsInBitblastingProof;
+
public:
LFSCBitVectorProof(theory::bv::TheoryBV* bv, TheoryProofEngine* proofEngine)
:BitVectorProof(bv, proofEngine)
{}
- virtual void printOwnedTerm(Expr term, std::ostream& os, const LetMap& map);
+ virtual void printOwnedTerm(Expr term, std::ostream& os, const ProofLetMap& map);
virtual void printOwnedSort(Type type, std::ostream& os);
virtual void printTermBitblasting(Expr term, std::ostream& os);
- virtual void printAtomBitblasting(Expr term, std::ostream& os);
- virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren);
+ virtual void printAtomBitblasting(Expr term, std::ostream& os, bool swap);
+ virtual void printAtomBitblastingToFalse(Expr term, std::ostream& os);
+ virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren, const ProofLetMap& map);
virtual void printSortDeclarations(std::ostream& os, std::ostream& paren);
virtual void printTermDeclarations(std::ostream& os, std::ostream& paren);
virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren);
+ virtual void printAliasingDeclarations(std::ostream& os, std::ostream& paren);
virtual void printBitblasting(std::ostream& os, std::ostream& paren);
- virtual void printResolutionProof(std::ostream& os, std::ostream& paren);
+ virtual void printResolutionProof(std::ostream& os, std::ostream& paren, ProofLetMap& letMap);
+ void calculateAtomsInBitblastingProof();
+ const std::set<Node>* getAtomsInBitblastingProof();
+ void printConstantDisequalityProof(std::ostream& os, Expr c1, Expr c2);
+ void printRewriteProof(std::ostream& os, const Node &n1, const Node &n2);
};
}/* CVC4 namespace */
diff --git a/src/proof/cnf_proof.cpp b/src/proof/cnf_proof.cpp
index 19e9cbac9..b58ade35e 100644
--- a/src/proof/cnf_proof.cpp
+++ b/src/proof/cnf_proof.cpp
@@ -19,6 +19,7 @@
#include "proof/clause_id.h"
#include "proof/proof_manager.h"
+#include "proof/proof_utils.h"
#include "proof/theory_proof.h"
#include "prop/cnf_stream.h"
#include "prop/minisat/minisat.h"
@@ -32,7 +33,6 @@ CnfProof::CnfProof(prop::CnfStream* stream,
: d_cnfStream(stream)
, d_clauseToAssertion(ctx)
, d_assertionToProofRule(ctx)
- , d_clauseIdToOwnerTheory(ctx)
, d_currentAssertionStack()
, d_currentDefinitionStack()
, d_clauseToDefinition(ctx)
@@ -103,7 +103,6 @@ void CnfProof::registerConvertedClause(ClauseId clause, bool explanation) {
setClauseAssertion(clause, current_assertion);
setClauseDefinition(clause, current_expr);
- registerExplanationLemma(clause);
}
void CnfProof::setClauseAssertion(ClauseId clause, Node expr) {
@@ -143,16 +142,15 @@ void CnfProof::registerAssertion(Node assertion, ProofRule reason) {
d_assertionToProofRule.insert(assertion, reason);
}
-void CnfProof::registerExplanationLemma(ClauseId clauseId) {
- d_clauseIdToOwnerTheory.insert(clauseId, getExplainerTheory());
+LemmaProofRecipe CnfProof::getProofRecipe(const std::set<Node> &lemma) {
+ Assert(d_lemmaToProofRecipe.find(lemma) != d_lemmaToProofRecipe.end());
+ return d_lemmaToProofRecipe[lemma];
}
-theory::TheoryId CnfProof::getOwnerTheory(ClauseId clause) {
- Assert(d_clauseIdToOwnerTheory.find(clause) != d_clauseIdToOwnerTheory.end());
- return d_clauseIdToOwnerTheory[clause];
+bool CnfProof::haveProofRecipe(const std::set<Node> &lemma) {
+ return d_lemmaToProofRecipe.find(lemma) != d_lemmaToProofRecipe.end();
}
-
void CnfProof::setCnfDependence(Node from, Node to) {
Debug("proof:cnf") << "CnfProof::setCnfDependence "
<< "from " << from << std::endl
@@ -183,12 +181,10 @@ Node CnfProof::getCurrentAssertion() {
return d_currentAssertionStack.back();
}
-void CnfProof::setExplainerTheory(theory::TheoryId theory) {
- d_explainerTheory = theory;
-}
-
-theory::TheoryId CnfProof::getExplainerTheory() {
- return d_explainerTheory;
+void CnfProof::setProofRecipe(LemmaProofRecipe* proofRecipe) {
+ Assert(proofRecipe);
+ Assert(proofRecipe->getNumSteps() > 0);
+ d_lemmaToProofRecipe[proofRecipe->getBaseAssertions()] = *proofRecipe;
}
void CnfProof::pushCurrentDefinition(Node definition) {
@@ -212,22 +208,19 @@ Node CnfProof::getCurrentDefinition() {
return d_currentDefinitionStack.back();
}
-
Node CnfProof::getAtom(prop::SatVariable var) {
prop::SatLiteral lit (var);
Node node = d_cnfStream->getNode(lit);
return node;
}
-
void CnfProof::collectAtoms(const prop::SatClause* clause,
- NodeSet& atoms) {
+ std::set<Node>& atoms) {
for (unsigned i = 0; i < clause->size(); ++i) {
prop::SatLiteral lit = clause->operator[](i);
prop::SatVariable var = lit.getSatVariable();
TNode atom = getAtom(var);
if (atoms.find(atom) == atoms.end()) {
- Assert (atoms.find(atom) == atoms.end());
atoms.insert(atom);
}
}
@@ -237,14 +230,75 @@ prop::SatLiteral CnfProof::getLiteral(TNode atom) {
return d_cnfStream->getLiteral(atom);
}
+bool CnfProof::hasLiteral(TNode atom) {
+ return d_cnfStream->hasLiteral(atom);
+}
+
+void CnfProof::ensureLiteral(TNode atom, bool noPreregistration) {
+ d_cnfStream->ensureLiteral(atom, noPreregistration);
+}
+
void CnfProof::collectAtomsForClauses(const IdToSatClause& clauses,
- NodeSet& atom_map) {
+ std::set<Node>& atoms) {
IdToSatClause::const_iterator it = clauses.begin();
for (; it != clauses.end(); ++it) {
const prop::SatClause* clause = it->second;
- collectAtoms(clause, atom_map);
+ collectAtoms(clause, atoms);
}
+}
+
+void CnfProof::collectAtomsAndRewritesForLemmas(const IdToSatClause& lemmaClauses,
+ std::set<Node>& atoms,
+ NodePairSet& rewrites) {
+ IdToSatClause::const_iterator it = lemmaClauses.begin();
+ for (; it != lemmaClauses.end(); ++it) {
+ const prop::SatClause* clause = it->second;
+
+ // TODO: just calculate the map from ID to recipe once,
+ // instead of redoing this over and over again
+ std::vector<Expr> clause_expr;
+ std::set<Node> clause_expr_nodes;
+ for(unsigned i = 0; i < clause->size(); ++i) {
+ prop::SatLiteral lit = (*clause)[i];
+ Node node = getAtom(lit.getSatVariable());
+ Expr atom = node.toExpr();
+ if (atom.isConst()) {
+ Assert (atom == utils::mkTrue());
+ continue;
+ }
+ clause_expr_nodes.insert(lit.isNegated() ? node.notNode() : node);
+ }
+
+ LemmaProofRecipe recipe = getProofRecipe(clause_expr_nodes);
+
+ for (unsigned i = 0; i < recipe.getNumSteps(); ++i) {
+ const LemmaProofRecipe::ProofStep* proofStep = recipe.getStep(i);
+ Node atom = proofStep->getLiteral();
+
+ if (atom == Node()) {
+ // The last proof step always has the empty node as its target...
+ continue;
+ }
+
+ if (atom.getKind() == kind::NOT) {
+ atom = atom[0];
+ }
+
+ atoms.insert(atom);
+ }
+
+ LemmaProofRecipe::RewriteIterator rewriteIt;
+ for (rewriteIt = recipe.rewriteBegin(); rewriteIt != recipe.rewriteEnd(); ++rewriteIt) {
+ rewrites.insert(NodePair(rewriteIt->first, rewriteIt->second));
+ // The unrewritten terms also need to have literals, so insert them into atoms
+ Node rewritten = rewriteIt->first;
+ if (rewritten.getKind() == kind::NOT) {
+ rewritten = rewritten[0];
+ }
+ atoms.insert(rewritten);
+ }
+ }
}
void CnfProof::collectAssertionsForClauses(const IdToSatClause& clauses,
@@ -263,13 +317,13 @@ void CnfProof::collectAssertionsForClauses(const IdToSatClause& clauses,
}
}
-void LFSCCnfProof::printAtomMapping(const NodeSet& atoms,
+void LFSCCnfProof::printAtomMapping(const std::set<Node>& atoms,
std::ostream& os,
std::ostream& paren) {
- NodeSet::const_iterator it = atoms.begin();
- NodeSet::const_iterator end = atoms.end();
+ std::set<Node>::const_iterator it = atoms.begin();
+ std::set<Node>::const_iterator end = atoms.end();
- for (;it != end; ++it) {
+ for (;it != end; ++it) {
os << "(decl_atom ";
Node atom = *it;
prop::SatVariable var = getLiteral(atom).getSatVariable();
@@ -277,8 +331,30 @@ void LFSCCnfProof::printAtomMapping(const NodeSet& atoms,
LFSCTheoryProofEngine* pe = (LFSCTheoryProofEngine*)ProofManager::currentPM()->getTheoryProofEngine();
pe->printLetTerm(atom.toExpr(), os);
- os << " (\\ " << ProofManager::getVarName(var, d_name)
- << " (\\ " << ProofManager::getAtomName(var, d_name) << "\n";
+ os << " (\\ " << ProofManager::getVarName(var, d_name);
+ os << " (\\ " << ProofManager::getAtomName(var, d_name) << "\n";
+ paren << ")))";
+ }
+}
+
+void LFSCCnfProof::printAtomMapping(const std::set<Node>& atoms,
+ std::ostream& os,
+ std::ostream& paren,
+ ProofLetMap &letMap) {
+ std::set<Node>::const_iterator it = atoms.begin();
+ std::set<Node>::const_iterator end = atoms.end();
+
+ for (;it != end; ++it) {
+ os << "(decl_atom ";
+ Node atom = *it;
+ prop::SatVariable var = getLiteral(atom).getSatVariable();
+ //FIXME hideous
+ LFSCTheoryProofEngine* pe = (LFSCTheoryProofEngine*)ProofManager::currentPM()->getTheoryProofEngine();
+ // pe->printLetTerm(atom.toExpr(), os);
+ pe->printBoundTerm(atom.toExpr(), os, letMap);
+
+ os << " (\\ " << ProofManager::getVarName(var, d_name);
+ os << " (\\ " << ProofManager::getAtomName(var, d_name) << "\n";
paren << ")))";
}
}
@@ -304,6 +380,9 @@ void LFSCCnfProof::printCnfProofForClause(ClauseId id,
const prop::SatClause* clause,
std::ostream& os,
std::ostream& paren) {
+ Debug("cnf-pf") << std::endl << std::endl << "LFSCCnfProof::printCnfProofForClause( " << id << " ) starting "
+ << std::endl;
+
os << "(satlem _ _ ";
std::ostringstream clause_paren;
printClause(*clause, os, clause_paren);
@@ -336,6 +415,10 @@ void LFSCCnfProof::printCnfProofForClause(ClauseId id,
// and prints the proof of the top-level formula
bool is_input = printProofTopLevel(base_assertion, os_base);
+ if (is_input) {
+ Debug("cnf-pf") << std::endl << "; base assertion is input. proof: " << os_base.str() << std::endl;
+ }
+
//get base assertion with polarity
bool base_pol = base_assertion.getKind()!=kind::NOT;
base_assertion = base_assertion.getKind()==kind::NOT ? base_assertion[0] : base_assertion;
@@ -564,6 +647,7 @@ void LFSCCnfProof::printCnfProofForClause(ClauseId id,
if( !pols[0] || num_nots_1==1 ){
os_base_n << "(not_not_intro _ " << ProofManager::getLitName(lit1, d_name) << ") ";
}else{
+ Trace("cnf-pf-debug") << "CALLING getlitname" << std::endl;
os_base_n << ProofManager::getLitName(lit1, d_name) << " ";
}
Assert( elimNum!=0 );
@@ -662,6 +746,7 @@ void LFSCCnfProof::printCnfProofForClause(ClauseId id,
os << ")" << clause_paren.str()
<< " (\\ " << ProofManager::getInputClauseName(id, d_name) << "\n";
+
paren << "))";
}
diff --git a/src/proof/cnf_proof.h b/src/proof/cnf_proof.h
index a21cb1c0e..788526b80 100644
--- a/src/proof/cnf_proof.h
+++ b/src/proof/cnf_proof.h
@@ -27,6 +27,7 @@
#include "context/cdhashmap.h"
#include "proof/clause_id.h"
+#include "proof/lemma_proof.h"
#include "proof/sat_proof.h"
#include "util/proof.h"
@@ -43,7 +44,9 @@ typedef __gnu_cxx::hash_set<ClauseId> ClauseIdSet;
typedef context::CDHashMap<ClauseId, Node> ClauseIdToNode;
typedef context::CDHashMap<Node, ProofRule, NodeHashFunction> NodeToProofRule;
-typedef context::CDHashMap<ClauseId, theory::TheoryId> ClauseIdToTheory;
+typedef std::map<std::set<Node>, LemmaProofRecipe> LemmaToRecipe;
+typedef std::pair<Node, Node> NodePair;
+typedef std::set<NodePair> NodePairSet;
class CnfProof {
protected:
@@ -55,11 +58,8 @@ protected:
/** Map from assertion to reason for adding assertion **/
NodeToProofRule d_assertionToProofRule;
- /** Map from assertion to the theory that added this assertion **/
- ClauseIdToTheory d_clauseIdToOwnerTheory;
-
- /** The last theory to explain a lemma **/
- theory::TheoryId d_explainerTheory;
+ /** Map from lemma to the recipe for proving it **/
+ LemmaToRecipe d_lemmaToProofRecipe;
/** Top of stack is assertion currently being converted to CNF **/
std::vector<Node> d_currentAssertionStack;
@@ -91,10 +91,16 @@ public:
Node getAtom(prop::SatVariable var);
prop::SatLiteral getLiteral(TNode node);
+ bool hasLiteral(TNode node);
+ void ensureLiteral(TNode node, bool noPreregistration = false);
+
void collectAtoms(const prop::SatClause* clause,
- NodeSet& atoms);
+ std::set<Node>& atoms);
void collectAtomsForClauses(const IdToSatClause& clauses,
- NodeSet& atoms);
+ std::set<Node>& atoms);
+ void collectAtomsAndRewritesForLemmas(const IdToSatClause& lemmaClauses,
+ std::set<Node>& atoms,
+ NodePairSet& rewrites);
void collectAssertionsForClauses(const IdToSatClause& clauses,
NodeSet& assertions);
@@ -121,11 +127,9 @@ public:
void popCurrentDefinition();
Node getCurrentDefinition();
- void setExplainerTheory(theory::TheoryId theory);
- theory::TheoryId getExplainerTheory();
- theory::TheoryId getOwnerTheory(ClauseId clause);
-
- void registerExplanationLemma(ClauseId clauseId);
+ void setProofRecipe(LemmaProofRecipe* proofRecipe);
+ LemmaProofRecipe getProofRecipe(const std::set<Node> &lemma);
+ bool haveProofRecipe(const std::set<Node> &lemma);
// accessors for the leaf assertions that are being converted to CNF
bool isAssertion(Node node);
@@ -134,9 +138,13 @@ public:
Node getAssertionForClause(ClauseId clause);
/** Virtual methods for printing things **/
- virtual void printAtomMapping(const NodeSet& atoms,
+ virtual void printAtomMapping(const std::set<Node>& atoms,
std::ostream& os,
std::ostream& paren) = 0;
+ virtual void printAtomMapping(const std::set<Node>& atoms,
+ std::ostream& os,
+ std::ostream& paren,
+ ProofLetMap &letMap) = 0;
virtual void printClause(const prop::SatClause& clause,
std::ostream& os,
@@ -161,10 +169,15 @@ public:
{}
~LFSCCnfProof() {}
- void printAtomMapping(const NodeSet& atoms,
+ void printAtomMapping(const std::set<Node>& atoms,
std::ostream& os,
std::ostream& paren);
+ void printAtomMapping(const std::set<Node>& atoms,
+ std::ostream& os,
+ std::ostream& paren,
+ ProofLetMap &letMap);
+
void printClause(const prop::SatClause& clause,
std::ostream& os,
std::ostream& paren);
diff --git a/src/proof/lemma_proof.cpp b/src/proof/lemma_proof.cpp
new file mode 100644
index 000000000..a12a516cf
--- /dev/null
+++ b/src/proof/lemma_proof.cpp
@@ -0,0 +1,193 @@
+/********************* */
+/*! \file lemma_proof.h
+** \verbatim
+**
+** \brief A class for recoding the steps required in order to prove a theory lemma.
+**
+** A class for recoding the steps required in order to prove a theory lemma.
+**
+**/
+
+#include "proof/lemma_proof.h"
+#include "theory/rewriter.h"
+
+namespace CVC4 {
+
+LemmaProofRecipe::ProofStep::ProofStep(theory::TheoryId theory, Node literalToProve) :
+ d_theory(theory), d_literalToProve(literalToProve) {
+}
+
+theory::TheoryId LemmaProofRecipe::ProofStep::getTheory() const {
+ return d_theory;
+}
+
+Node LemmaProofRecipe::ProofStep::getLiteral() const {
+ return d_literalToProve;
+}
+
+void LemmaProofRecipe::ProofStep::addAssertion(const Node& assertion) {
+ d_assertions.insert(assertion);
+}
+
+std::set<Node> LemmaProofRecipe::ProofStep::getAssertions() const {
+ return d_assertions;
+}
+
+void LemmaProofRecipe::addStep(ProofStep& proofStep) {
+ std::list<ProofStep>::iterator existingFirstStep = d_proofSteps.begin();
+ d_proofSteps.push_front(proofStep);
+}
+
+std::set<Node> LemmaProofRecipe::getMissingAssertionsForStep(unsigned index) const {
+ Assert(index < d_proofSteps.size());
+
+ std::set<Node> existingAssertions = getBaseAssertions();
+
+ std::list<ProofStep>::const_iterator step = d_proofSteps.begin();
+ while (index != 0) {
+ existingAssertions.insert(step->getLiteral().negate());
+ ++step;
+ --index;
+ }
+
+ std::set<Node> neededAssertions = step->getAssertions();
+
+ std::set<Node> result;
+ std::set_difference(neededAssertions.begin(), neededAssertions.end(),
+ existingAssertions.begin(), existingAssertions.end(),
+ std::inserter(result, result.begin()));
+ return result;
+}
+
+void LemmaProofRecipe::dump(const char *tag) const {
+
+ if (d_proofSteps.size() == 1) {
+ Debug(tag) << std::endl << "[Simple lemma]" << std::endl << std::endl;
+ }
+
+ unsigned count = 1;
+ Debug(tag) << "Base assertions:" << std::endl;
+ for (std::set<Node>::iterator baseIt = d_baseAssertions.begin();
+ baseIt != d_baseAssertions.end();
+ ++baseIt) {
+ Debug(tag) << "\t#" << count << ": " << "\t" << *baseIt << std::endl;
+ ++count;
+ }
+
+ Debug(tag) << std::endl << std::endl << "Proof steps:" << std::endl;
+
+ count = 1;
+ for (std::list<ProofStep>::const_iterator step = d_proofSteps.begin(); step != d_proofSteps.end(); ++step) {
+ Debug(tag) << "\tStep #" << count << ": " << "\t[" << step->getTheory() << "] ";
+ if (step->getLiteral() == Node()) {
+ Debug(tag) << "Contradiction";
+ } else {
+ Debug(tag) << step->getLiteral();
+ }
+
+ Debug(tag) << std::endl;
+
+ std::set<Node> missingAssertions = getMissingAssertionsForStep(count - 1);
+ for (std::set<Node>::const_iterator it = missingAssertions.begin(); it != missingAssertions.end(); ++it) {
+ Debug(tag) << "\t\t\tMissing assertion for step: " << *it << std::endl;
+ }
+
+ Debug(tag) << std::endl;
+ ++count;
+ }
+
+ if (!d_assertionToExplanation.empty()) {
+ Debug(tag) << std::endl << "Rewrites used:" << std::endl;
+ count = 1;
+ for (std::map<Node, Node>::const_iterator rewrite = d_assertionToExplanation.begin();
+ rewrite != d_assertionToExplanation.end();
+ ++rewrite) {
+ Debug(tag) << "\tRewrite #" << count << ":" << std::endl
+ << "\t\t" << rewrite->first
+ << std::endl << "\t\trewritten into" << std::endl
+ << "\t\t" << rewrite->second
+ << std::endl << std::endl;
+ ++count;
+ }
+ }
+}
+
+void LemmaProofRecipe::addBaseAssertion(Node baseAssertion) {
+ d_baseAssertions.insert(baseAssertion);
+}
+
+std::set<Node> LemmaProofRecipe::getBaseAssertions() const {
+ return d_baseAssertions;
+}
+
+theory::TheoryId LemmaProofRecipe::getTheory() const {
+ Assert(d_proofSteps.size() > 0);
+ return d_proofSteps.back().getTheory();
+}
+
+void LemmaProofRecipe::addRewriteRule(Node assertion, Node explanation) {
+ if (d_assertionToExplanation.find(assertion) != d_assertionToExplanation.end()) {
+ Assert(d_assertionToExplanation[assertion] == explanation);
+ }
+
+ d_assertionToExplanation[assertion] = explanation;
+}
+
+bool LemmaProofRecipe::wasRewritten(Node assertion) const {
+ return d_assertionToExplanation.find(assertion) != d_assertionToExplanation.end();
+}
+
+Node LemmaProofRecipe::getExplanation(Node assertion) const {
+ Assert(d_assertionToExplanation.find(assertion) != d_assertionToExplanation.end());
+ return d_assertionToExplanation.find(assertion)->second;
+}
+
+LemmaProofRecipe::RewriteIterator LemmaProofRecipe::rewriteBegin() const {
+ return d_assertionToExplanation.begin();
+}
+
+LemmaProofRecipe::RewriteIterator LemmaProofRecipe::rewriteEnd() const {
+ return d_assertionToExplanation.end();
+}
+
+bool LemmaProofRecipe::operator<(const LemmaProofRecipe& other) const {
+ return d_baseAssertions < other.d_baseAssertions;
+ }
+
+bool LemmaProofRecipe::simpleLemma() const {
+ return d_proofSteps.size() == 1;
+}
+
+bool LemmaProofRecipe::compositeLemma() const {
+ return !simpleLemma();
+}
+
+const LemmaProofRecipe::ProofStep* LemmaProofRecipe::getStep(unsigned index) const {
+ Assert(index < d_proofSteps.size());
+
+ std::list<ProofStep>::const_iterator it = d_proofSteps.begin();
+ while (index != 0) {
+ ++it;
+ --index;
+ }
+
+ return &(*it);
+}
+
+LemmaProofRecipe::ProofStep* LemmaProofRecipe::getStep(unsigned index) {
+ Assert(index < d_proofSteps.size());
+
+ std::list<ProofStep>::iterator it = d_proofSteps.begin();
+ while (index != 0) {
+ ++it;
+ --index;
+ }
+
+ return &(*it);
+}
+
+unsigned LemmaProofRecipe::getNumSteps() const {
+ return d_proofSteps.size();
+}
+
+} /* namespace CVC4 */
diff --git a/src/proof/lemma_proof.h b/src/proof/lemma_proof.h
new file mode 100644
index 000000000..e96ff5337
--- /dev/null
+++ b/src/proof/lemma_proof.h
@@ -0,0 +1,79 @@
+/********************* */
+/*! \file lemma_proof.h
+** \verbatim
+**
+** \brief A class for recoding the steps required in order to prove a theory lemma.
+**
+** A class for recoding the steps required in order to prove a theory lemma.
+**
+**/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__LEMMA_PROOF_H
+#define __CVC4__LEMMA_PROOF_H
+
+#include "expr/expr.h"
+#include "proof/clause_id.h"
+#include "prop/sat_solver_types.h"
+#include "util/proof.h"
+#include "expr/node.h"
+
+namespace CVC4 {
+
+class LemmaProofRecipe {
+public:
+ class ProofStep {
+ public:
+ ProofStep(theory::TheoryId theory, Node literalToProve);
+ theory::TheoryId getTheory() const;
+ Node getLiteral() const;
+ void addAssertion(const Node& assertion);
+ std::set<Node> getAssertions() const;
+
+ private:
+ theory::TheoryId d_theory;
+ Node d_literalToProve;
+ std::set<Node> d_assertions;
+ };
+
+ //* The lemma assertions and owner */
+ void addBaseAssertion(Node baseAssertion);
+ std::set<Node> getBaseAssertions() const;
+ theory::TheoryId getTheory() const;
+
+ //* Rewrite rules */
+ typedef std::map<Node, Node>::const_iterator RewriteIterator;
+ RewriteIterator rewriteBegin() const;
+ RewriteIterator rewriteEnd() const;
+
+ void addRewriteRule(Node assertion, Node explanation);
+ bool wasRewritten(Node assertion) const;
+ Node getExplanation(Node assertion) const;
+
+ //* Proof Steps */
+ void addStep(ProofStep& proofStep);
+ const ProofStep* getStep(unsigned index) const;
+ ProofStep* getStep(unsigned index);
+ unsigned getNumSteps() const;
+ std::set<Node> getMissingAssertionsForStep(unsigned index) const;
+ bool simpleLemma() const;
+ bool compositeLemma() const;
+
+ void dump(const char *tag) const;
+ bool operator<(const LemmaProofRecipe& other) const;
+
+private:
+ //* The list of assertions for this lemma */
+ std::set<Node> d_baseAssertions;
+
+ //* The various steps needed to derive the empty clause */
+ std::list<ProofStep> d_proofSteps;
+
+ //* A map from assertions to their rewritten explanations (toAssert --> toExplain) */
+ std::map<Node, Node> d_assertionToExplanation;
+};
+
+} /* CVC4 namespace */
+
+#endif /* __CVC4__LEMMA_PROOF_H */
diff --git a/src/proof/proof_manager.cpp b/src/proof/proof_manager.cpp
index a3689d746..d155630e5 100644
--- a/src/proof/proof_manager.cpp
+++ b/src/proof/proof_manager.cpp
@@ -20,6 +20,7 @@
#include "base/cvc4_assert.h"
#include "context/context.h"
#include "options/bv_options.h"
+#include "options/proof_options.h"
#include "proof/bitvector_proof.h"
#include "proof/clause_id.h"
#include "proof/cnf_proof.h"
@@ -61,10 +62,10 @@ ProofManager::ProofManager(ProofFormat format):
}
ProofManager::~ProofManager() {
- delete d_satProof;
- delete d_cnfProof;
- delete d_theoryProof;
- delete d_fullProof;
+ if (d_satProof) delete d_satProof;
+ if (d_cnfProof) delete d_cnfProof;
+ if (d_theoryProof) delete d_theoryProof;
+ if (d_fullProof) delete d_fullProof;
}
ProofManager* ProofManager::currentPM() {
@@ -95,7 +96,6 @@ CnfProof* ProofManager::getCnfProof() {
}
TheoryProofEngine* ProofManager::getTheoryProofEngine() {
- Assert (options::proof());
Assert (currentPM()->d_theoryProof != NULL);
return currentPM()->d_theoryProof;
}
@@ -200,7 +200,6 @@ std::string ProofManager::getLitName(prop::SatLiteral lit,
return append(prefix+".l", lit.toInt());
}
-
std::string ProofManager::getPreprocessedAssertionName(Node node,
const std::string& prefix) {
node = node.getKind() == kind::BITVECTOR_EAGER_ATOM ? node[0] : node;
@@ -217,9 +216,15 @@ std::string ProofManager::getAtomName(TNode atom,
Assert(!lit.isNegated());
return getAtomName(lit.getSatVariable(), prefix);
}
+
std::string ProofManager::getLitName(TNode lit,
const std::string& prefix) {
- return getLitName(currentPM()->d_cnfProof->getLiteral(lit), prefix);
+ std::string litName = getLitName(currentPM()->d_cnfProof->getLiteral(lit), prefix);
+ if (currentPM()->d_rewriteFilters.find(litName) != currentPM()->d_rewriteFilters.end()) {
+ return currentPM()->d_rewriteFilters[litName];
+ }
+
+ return litName;
}
std::string ProofManager::sanitize(TNode node) {
@@ -330,7 +335,14 @@ LFSCProof::LFSCProof(SmtEngine* smtEngine,
, d_smtEngine(smtEngine)
{}
+void LFSCProof::toStream(std::ostream& out, const ProofLetMap& map) {
+ Unreachable();
+}
+
void LFSCProof::toStream(std::ostream& out) {
+
+ Assert(options::bitblastMode() != theory::bv::BITBLAST_MODE_EAGER);
+
d_satProof->constructProof();
// collecting leaf clauses in resolution proof
@@ -384,8 +396,37 @@ void LFSCProof::toStream(std::ostream& out) {
for (it3 = used_assertions.begin(); it3 != used_assertions.end(); ++it3)
Debug("pf::pm") << "\t assertion = " << *it3 << std::endl;
- NodeSet atoms;
+ std::set<Node> atoms;
+ NodePairSet rewrites;
// collects the atoms in the clauses
+ d_cnfProof->collectAtomsAndRewritesForLemmas(used_lemmas, atoms, rewrites);
+
+ if (!rewrites.empty()) {
+ Debug("pf::pm") << std::endl << "Rewrites used in lemmas: " << std::endl;
+ NodePairSet::const_iterator rewriteIt;
+ for (rewriteIt = rewrites.begin(); rewriteIt != rewrites.end(); ++rewriteIt) {
+ Debug("pf::pm") << "\t" << rewriteIt->first << " --> " << rewriteIt->second << std::endl;
+ }
+ Debug("pf::pm") << std::endl << "Rewrite printing done" << std::endl;
+ } else {
+ Debug("pf::pm") << "No rewrites in lemmas found" << std::endl;
+ }
+
+ // The derived/unrewritten atoms may not have CNF literals required later on.
+ // If they don't, add them.
+ std::set<Node>::const_iterator it;
+ for (it = atoms.begin(); it != atoms.end(); ++it) {
+ Debug("pf::pm") << "Ensure literal for atom: " << *it << std::endl;
+ if (!d_cnfProof->hasLiteral(*it)) {
+ // For arithmetic: these literals are not normalized, causing an error in Arith.
+ if (theory::Theory::theoryOf(*it) == theory::THEORY_ARITH) {
+ d_cnfProof->ensureLiteral(*it, true); // This disables preregistration with the theory solver.
+ } else {
+ d_cnfProof->ensureLiteral(*it); // Normal method, with theory solver preregisteration.
+ }
+ }
+ }
+
d_cnfProof->collectAtomsForClauses(used_inputs, atoms);
d_cnfProof->collectAtomsForClauses(used_lemmas, atoms);
@@ -393,38 +434,23 @@ void LFSCProof::toStream(std::ostream& out) {
for (NodeSet::const_iterator it = used_assertions.begin();
it != used_assertions.end(); ++it) {
utils::collectAtoms(*it, atoms);
+ // utils::collectAtoms(*it, newAtoms);
}
- NodeSet::iterator atomIt;
- Debug("pf::pm") << std::endl << "Dumping atoms from lemmas, inputs and assertions: " << std::endl << std::endl;
+ std::set<Node>::iterator atomIt;
+ Debug("pf::pm") << std::endl << "Dumping atoms from lemmas, inputs and assertions: "
+ << std::endl << std::endl;
for (atomIt = atoms.begin(); atomIt != atoms.end(); ++atomIt) {
Debug("pf::pm") << "\tAtom: " << *atomIt << std::endl;
-
- if (Debug.isOn("proof:pm")) {
- // std::cout << NodeManager::currentNM();
- Debug("proof:pm") << "LFSCProof::Used assertions: "<< std::endl;
- for(NodeSet::const_iterator it = used_assertions.begin(); it != used_assertions.end(); ++it) {
- Debug("proof:pm") << " " << *it << std::endl;
- }
-
- Debug("proof:pm") << "LFSCProof::Used atoms: "<< std::endl;
- for(NodeSet::const_iterator it = atoms.begin(); it != atoms.end(); ++it) {
- Debug("proof:pm") << " " << *it << std::endl;
- }
- }
}
-
smt::SmtScope scope(d_smtEngine);
std::ostringstream paren;
out << "(check\n";
out << " ;; Declarations\n";
// declare the theory atoms
- NodeSet::const_iterator it = atoms.begin();
- NodeSet::const_iterator end = atoms.end();
-
Debug("pf::pm") << "LFSCProof::toStream: registering terms:" << std::endl;
- for(; it != end; ++it) {
+ for(it = atoms.begin(); it != atoms.end(); ++it) {
Debug("pf::pm") << "\tTerm: " << (*it).toExpr() << std::endl;
d_theoryProof->registerTerm((*it).toExpr());
}
@@ -444,15 +470,31 @@ void LFSCProof::toStream(std::ostream& out) {
out << "(: (holds cln)\n\n";
// Have the theory proofs print deferred declarations, e.g. for skolem variables.
- out << " ;; Printing deferred declarations \n";
+ out << " ;; Printing deferred declarations \n\n";
d_theoryProof->printDeferredDeclarations(out, paren);
+ d_theoryProof->finalizeBvConflicts(used_lemmas, out);
+ ProofManager::getBitVectorProof()->calculateAtomsInBitblastingProof();
+
+ out << "\n ;; Printing the global let map \n";
+
+ ProofLetMap globalLetMap;
+ if (options::lfscLetification()) {
+ ProofManager::currentPM()->printGlobalLetMap(atoms, globalLetMap, out, paren);
+ }
+
+ out << " ;; Printing aliasing declarations \n\n";
+ d_theoryProof->printAliasingDeclarations(out, paren);
+
+ out << " ;; Rewrites for Lemmas \n";
+ d_theoryProof->printLemmaRewrites(rewrites, out, paren);
+
// print trust that input assertions are their preprocessed form
- printPreprocessedAssertions(used_assertions, out, paren);
+ printPreprocessedAssertions(used_assertions, out, paren, globalLetMap);
// print mapping between theory atoms and internal SAT variables
out << ";; Printing mapping from preprocessed assertions into atoms \n";
- d_cnfProof->printAtomMapping(atoms, out, paren);
+ d_cnfProof->printAtomMapping(atoms, out, paren, globalLetMap);
Debug("pf::pm") << std::endl << "Printing cnf proof for clauses" << std::endl;
@@ -464,12 +506,8 @@ void LFSCProof::toStream(std::ostream& out) {
Debug("pf::pm") << std::endl << "Printing cnf proof for clauses DONE" << std::endl;
- // FIXME: for now assume all theory lemmas are in CNF form so
- // distinguish between them and inputs
- // print theory lemmas for resolution proof
-
Debug("pf::pm") << "Proof manager: printing theory lemmas" << std::endl;
- d_theoryProof->printTheoryLemmas(used_lemmas, out, paren);
+ d_theoryProof->printTheoryLemmas(used_lemmas, out, paren, globalLetMap);
Debug("pf::pm") << "Proof manager: printing theory lemmas DONE!" << std::endl;
if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER && ProofManager::getBitVectorProof()) {
@@ -491,22 +529,24 @@ void LFSCProof::toStream(std::ostream& out) {
void LFSCProof::printPreprocessedAssertions(const NodeSet& assertions,
std::ostream& os,
- std::ostream& paren) {
+ std::ostream& paren,
+ ProofLetMap& globalLetMap) {
os << "\n ;; In the preprocessor we trust \n";
NodeSet::const_iterator it = assertions.begin();
NodeSet::const_iterator end = assertions.end();
+ Debug("pf::pm") << "LFSCProof::printPreprocessedAssertions starting" << std::endl;
+
for (; it != end; ++it) {
os << "(th_let_pf _ ";
//TODO
os << "(trust_f ";
- ProofManager::currentPM()->getTheoryProofEngine()->printLetTerm((*it).toExpr(), os);
+ ProofManager::currentPM()->getTheoryProofEngine()->printTheoryTerm((*it).toExpr(), os, globalLetMap);
os << ") ";
os << "(\\ "<< ProofManager::getPreprocessedAssertionName(*it, "") << "\n";
paren << "))";
-
}
os << "\n";
@@ -568,6 +608,14 @@ void ProofManager::markPrinted(const Type& type) {
d_printedTypes.insert(type);
}
+void ProofManager::addRewriteFilter(const std::string &original, const std::string &substitute) {
+ d_rewriteFilters[original] = substitute;
+}
+
+void ProofManager::clearRewriteFilters() {
+ d_rewriteFilters.clear();
+}
+
std::ostream& operator<<(std::ostream& out, CVC4::ProofRule k) {
switch(k) {
case RULE_GIVEN:
@@ -607,5 +655,88 @@ std::ostream& operator<<(std::ostream& out, CVC4::ProofRule k) {
return out;
}
+void ProofManager::registerRewrite(unsigned ruleId, Node original, Node result){
+ Assert (currentPM()->d_theoryProof != NULL);
+ currentPM()->d_rewriteLog.push_back(RewriteLogEntry(ruleId, original, result));
+}
+
+void ProofManager::clearRewriteLog() {
+ Assert (currentPM()->d_theoryProof != NULL);
+ currentPM()->d_rewriteLog.clear();
+}
+
+std::vector<RewriteLogEntry> ProofManager::getRewriteLog() {
+ return currentPM()->d_rewriteLog;
+}
+
+void ProofManager::dumpRewriteLog() const {
+ Debug("pf::rr") << "Dumpign rewrite log:" << std::endl;
+
+ for (unsigned i = 0; i < d_rewriteLog.size(); ++i) {
+ Debug("pf::rr") << "\tRule " << d_rewriteLog[i].getRuleId()
+ << ": "
+ << d_rewriteLog[i].getOriginal()
+ << " --> "
+ << d_rewriteLog[i].getResult() << std::endl;
+ }
+}
+
+void bind(Expr term, ProofLetMap& map, Bindings& letOrder) {
+ ProofLetMap::iterator it = map.find(term);
+ if (it != map.end())
+ return;
+
+ for (unsigned i = 0; i < term.getNumChildren(); ++i)
+ bind(term[i], map, letOrder);
+
+ // Special case: chain operators. If we have and(a,b,c), it will be prineted as and(a,and(b,c)).
+ // The subterm and(b,c) may repeat elsewhere, so we need to bind it, too.
+ Kind k = term.getKind();
+ if (((k == kind::OR) || (k == kind::AND)) && term.getNumChildren() > 2) {
+ Node currentExpression = term[term.getNumChildren() - 1];
+ for (int i = term.getNumChildren() - 2; i >= 0; --i) {
+ NodeBuilder<> builder(k);
+ builder << term[i];
+ builder << currentExpression.toExpr();
+ currentExpression = builder;
+ bind(currentExpression.toExpr(), map, letOrder);
+ }
+ } else {
+ unsigned newId = ProofLetCount::newId();
+ ProofLetCount letCount(newId);
+ map[term] = letCount;
+ letOrder.push_back(LetOrderElement(term, newId));
+ }
+}
+
+void ProofManager::printGlobalLetMap(std::set<Node>& atoms,
+ ProofLetMap& letMap,
+ std::ostream& out,
+ std::ostringstream& paren) {
+ Bindings letOrder;
+ std::set<Node>::const_iterator atom;
+ for (atom = atoms.begin(); atom != atoms.end(); ++atom) {
+ bind(atom->toExpr(), letMap, letOrder);
+ }
+
+ // TODO: give each theory a chance to add atoms. For now, just query BV directly...
+ const std::set<Node>* additionalAtoms = ProofManager::getBitVectorProof()->getAtomsInBitblastingProof();
+ for (atom = additionalAtoms->begin(); atom != additionalAtoms->end(); ++atom) {
+ bind(atom->toExpr(), letMap, letOrder);
+ }
+
+ for (unsigned i = 0; i < letOrder.size(); ++i) {
+ Expr currentExpr = letOrder[i].expr;
+ unsigned letId = letOrder[i].id;
+ ProofLetMap::iterator it = letMap.find(currentExpr);
+ Assert(it != letMap.end());
+ out << "\n(@ let" << letId << " ";
+ d_theoryProof->printBoundTerm(currentExpr, out, letMap);
+ paren << ")";
+ it->second.increment();
+ }
+
+ out << std::endl << std::endl;
+}
} /* CVC4 namespace */
diff --git a/src/proof/proof_manager.h b/src/proof/proof_manager.h
index c74aac237..14793f380 100644
--- a/src/proof/proof_manager.h
+++ b/src/proof/proof_manager.h
@@ -22,6 +22,7 @@
#include <iosfwd>
#include <map>
#include "proof/proof.h"
+#include "proof/proof_utils.h"
#include "proof/skolemization_manager.h"
#include "util/proof.h"
#include "expr/node.h"
@@ -34,6 +35,8 @@
namespace CVC4 {
+class SmtGlobals;
+
// forward declarations
namespace Minisat {
class Solver;
@@ -113,6 +116,30 @@ enum ProofRule {
RULE_ARRAYS_ROW, /* arrays, read-over-write */
};/* enum ProofRules */
+class RewriteLogEntry {
+public:
+ RewriteLogEntry(unsigned ruleId, Node original, Node result)
+ : d_ruleId(ruleId), d_original(original), d_result(result) {
+ }
+
+ unsigned getRuleId() const {
+ return d_ruleId;
+ }
+
+ Node getOriginal() const {
+ return d_original;
+ }
+
+ Node getResult() const {
+ return d_result;
+ }
+
+private:
+ unsigned d_ruleId;
+ Node d_original;
+ Node d_result;
+};
+
class ProofManager {
CoreSatProof* d_satProof;
CnfProof* d_cnfProof;
@@ -136,6 +163,10 @@ class ProofManager {
std::set<Type> d_printedTypes;
+ std::map<std::string, std::string> d_rewriteFilters;
+
+ std::vector<RewriteLogEntry> d_rewriteLog;
+
protected:
LogicInfo d_logic;
@@ -224,6 +255,19 @@ public:
void markPrinted(const Type& type);
bool wasPrinted(const Type& type) const;
+ void addRewriteFilter(const std::string &original, const std::string &substitute);
+ void clearRewriteFilters();
+
+ static void registerRewrite(unsigned ruleId, Node original, Node result);
+ static void clearRewriteLog();
+
+ std::vector<RewriteLogEntry> getRewriteLog();
+ void dumpRewriteLog() const;
+
+ void printGlobalLetMap(std::set<Node>& atoms,
+ ProofLetMap& letMap,
+ std::ostream& out,
+ std::ostringstream& paren);
};/* class ProofManager */
class LFSCProof : public Proof {
@@ -235,13 +279,15 @@ class LFSCProof : public Proof {
// FIXME: hack until we get preprocessing
void printPreprocessedAssertions(const NodeSet& assertions,
std::ostream& os,
- std::ostream& paren);
+ std::ostream& paren,
+ ProofLetMap& globalLetMap);
public:
LFSCProof(SmtEngine* smtEngine,
LFSCCoreSatProof* sat,
LFSCCnfProof* cnf,
LFSCTheoryProofEngine* theory);
virtual void toStream(std::ostream& out);
+ virtual void toStream(std::ostream& out, const ProofLetMap& map);
virtual ~LFSCProof() {}
};/* class LFSCProof */
diff --git a/src/proof/proof_output_channel.cpp b/src/proof/proof_output_channel.cpp
new file mode 100644
index 000000000..6d729db1f
--- /dev/null
+++ b/src/proof/proof_output_channel.cpp
@@ -0,0 +1,82 @@
+/********************* */
+/*! \file proof_output_channel.cpp
+** \verbatim
+** \brief [[ Add one-line brief description here ]]
+**
+** [[ Add lengthier description here ]]
+** \todo document this file
+**/
+
+#include "base/cvc4_assert.h"
+#include "proof_output_channel.h"
+#include "theory/term_registration_visitor.h"
+#include "theory/valuation.h"
+
+namespace CVC4 {
+
+ProofOutputChannel::ProofOutputChannel() : d_conflict(), d_proof(NULL) {}
+
+void ProofOutputChannel::conflict(TNode n, Proof* pf) throw() {
+ Trace("pf::tp") << "ProofOutputChannel: CONFLICT: " << n << std::endl;
+ Assert(d_conflict.isNull());
+ Assert(!n.isNull());
+ d_conflict = n;
+ Assert(pf != NULL);
+ d_proof = pf;
+}
+
+bool ProofOutputChannel::propagate(TNode x) throw() {
+ Trace("pf::tp") << "ProofOutputChannel: got a propagation: " << x << std::endl;
+ d_propagations.insert(x);
+ return true;
+}
+
+theory::LemmaStatus ProofOutputChannel::lemma(TNode n, ProofRule rule, bool, bool, bool) throw() {
+ Trace("pf::tp") << "ProofOutputChannel: new lemma: " << n << std::endl;
+ d_lemma = n;
+ return theory::LemmaStatus(TNode::null(), 0);
+}
+
+theory::LemmaStatus ProofOutputChannel::splitLemma(TNode, bool) throw() {
+ AlwaysAssert(false);
+ return theory::LemmaStatus(TNode::null(), 0);
+}
+
+void ProofOutputChannel::requirePhase(TNode n, bool b) throw() {
+ Debug("pf::tp") << "ProofOutputChannel::requirePhase called" << std::endl;
+ Trace("pf::tp") << "requirePhase " << n << " " << b << std::endl;
+}
+
+bool ProofOutputChannel::flipDecision() throw() {
+ Debug("pf::tp") << "ProofOutputChannel::flipDecision called" << std::endl;
+ AlwaysAssert(false);
+ return false;
+}
+
+void ProofOutputChannel::setIncomplete() throw() {
+ Debug("pf::tp") << "ProofOutputChannel::setIncomplete called" << std::endl;
+ AlwaysAssert(false);
+}
+
+
+MyPreRegisterVisitor::MyPreRegisterVisitor(theory::Theory* theory)
+ : d_theory(theory)
+ , d_visited() {
+}
+
+bool MyPreRegisterVisitor::alreadyVisited(TNode current, TNode parent) {
+ return d_visited.find(current) != d_visited.end();
+}
+
+void MyPreRegisterVisitor::visit(TNode current, TNode parent) {
+ d_theory->preRegisterTerm(current);
+ d_visited.insert(current);
+}
+
+void MyPreRegisterVisitor::start(TNode node) {
+}
+
+void MyPreRegisterVisitor::done(TNode node) {
+}
+
+} /* namespace CVC4 */
diff --git a/src/proof/proof_output_channel.h b/src/proof/proof_output_channel.h
new file mode 100644
index 000000000..b85af5fb5
--- /dev/null
+++ b/src/proof/proof_output_channel.h
@@ -0,0 +1,50 @@
+/********************* */
+/*! \file proof_output_channel.h
+ ** \verbatim
+ **
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__PROOF_OUTPUT_CHANNEL_H
+#define __CVC4__PROOF_OUTPUT_CHANNEL_H
+
+#include "theory/output_channel.h"
+
+namespace CVC4 {
+
+class ProofOutputChannel : public theory::OutputChannel {
+public:
+ Node d_conflict;
+ Proof* d_proof;
+ Node d_lemma;
+ std::set<Node> d_propagations;
+
+ ProofOutputChannel();
+
+ virtual ~ProofOutputChannel() throw() {}
+
+ void conflict(TNode n, Proof* pf) throw();
+ bool propagate(TNode x) throw();
+ theory::LemmaStatus lemma(TNode n, ProofRule rule, bool, bool, bool) throw();
+ theory::LemmaStatus splitLemma(TNode, bool) throw();
+ void requirePhase(TNode n, bool b) throw();
+ bool flipDecision() throw();
+ void setIncomplete() throw();
+};/* class ProofOutputChannel */
+
+class MyPreRegisterVisitor {
+ theory::Theory* d_theory;
+ __gnu_cxx::hash_set<TNode, TNodeHashFunction> d_visited;
+public:
+ typedef void return_type;
+ MyPreRegisterVisitor(theory::Theory* theory);
+ bool alreadyVisited(TNode current, TNode parent);
+ void visit(TNode current, TNode parent);
+ void start(TNode node);
+ void done(TNode node);
+}; /* class MyPreRegisterVisitor */
+
+} /* CVC4 namespace */
+
+#endif /* __CVC4__PROOF_OUTPUT_CHANNEL_H */
diff --git a/src/proof/proof_utils.cpp b/src/proof/proof_utils.cpp
index 5b04c281d..fe0d42242 100644
--- a/src/proof/proof_utils.cpp
+++ b/src/proof/proof_utils.cpp
@@ -21,14 +21,14 @@
namespace CVC4 {
namespace utils {
-void collectAtoms(TNode node, CVC4::NodeSet& seen) {
+void collectAtoms(TNode node, std::set<Node>& seen) {
if (seen.find(node) != seen.end())
return;
if (theory::Theory::theoryOf(node) != theory::THEORY_BOOL || node.isVar()) {
seen.insert(node);
return;
}
-
+
for (unsigned i = 0; i < node.getNumChildren(); ++i) {
collectAtoms(node[i], seen);
}
@@ -47,23 +47,23 @@ std::string toLFSCKind(Kind kind) {
// bit-vector kinds
case kind::BITVECTOR_AND :
- return "bvand";
+ return "bvand";
case kind::BITVECTOR_OR :
- return "bvor";
+ return "bvor";
case kind::BITVECTOR_XOR :
- return "bvxor";
+ return "bvxor";
case kind::BITVECTOR_NAND :
- return "bvnand";
+ return "bvnand";
case kind::BITVECTOR_NOR :
- return "bvnor";
+ return "bvnor";
case kind::BITVECTOR_XNOR :
- return "bvxnor";
+ return "bvxnor";
case kind::BITVECTOR_COMP :
- return "bvcomp";
+ return "bvcomp";
case kind::BITVECTOR_MULT :
return "bvmul";
case kind::BITVECTOR_PLUS :
- return "bvadd";
+ return "bvadd";
case kind::BITVECTOR_SUB :
return "bvsub";
case kind::BITVECTOR_UDIV :
@@ -71,49 +71,49 @@ std::string toLFSCKind(Kind kind) {
return "bvudiv";
case kind::BITVECTOR_UREM :
case kind::BITVECTOR_UREM_TOTAL :
- return "bvurem";
+ return "bvurem";
case kind::BITVECTOR_SDIV :
- return "bvsdiv";
+ return "bvsdiv";
case kind::BITVECTOR_SREM :
return "bvsrem";
case kind::BITVECTOR_SMOD :
- return "bvsmod";
+ return "bvsmod";
case kind::BITVECTOR_SHL :
- return "bvshl";
+ return "bvshl";
case kind::BITVECTOR_LSHR :
return "bvlshr";
case kind::BITVECTOR_ASHR :
return "bvashr";
case kind::BITVECTOR_CONCAT :
- return "concat";
+ return "concat";
case kind::BITVECTOR_NEG :
- return "bvneg";
+ return "bvneg";
case kind::BITVECTOR_NOT :
- return "bvnot";
+ return "bvnot";
case kind::BITVECTOR_ROTATE_LEFT :
- return "rotate_left";
+ return "rotate_left";
case kind::BITVECTOR_ROTATE_RIGHT :
return "rotate_right";
case kind::BITVECTOR_ULT :
- return "bvult";
+ return "bvult";
case kind::BITVECTOR_ULE :
- return "bvule";
+ return "bvule";
case kind::BITVECTOR_UGT :
return "bvugt";
case kind::BITVECTOR_UGE :
return "bvuge";
case kind::BITVECTOR_SLT :
- return "bvslt";
+ return "bvslt";
case kind::BITVECTOR_SLE :
- return "bvsle";
+ return "bvsle";
case kind::BITVECTOR_SGT :
- return "bvsgt";
+ return "bvsgt";
case kind::BITVECTOR_SGE :
- return "bvsge";
+ return "bvsge";
case kind::BITVECTOR_EXTRACT :
- return "extract";
+ return "extract";
case kind::BITVECTOR_REPEAT :
- return "repeat";
+ return "repeat";
case kind::BITVECTOR_ZERO_EXTEND :
return "zero_extend";
case kind::BITVECTOR_SIGN_EXTEND :
diff --git a/src/proof/proof_utils.h b/src/proof/proof_utils.h
index da10c33a0..546d419fc 100644
--- a/src/proof/proof_utils.h
+++ b/src/proof/proof_utils.h
@@ -17,7 +17,7 @@
#include "cvc4_private.h"
-#pragma once
+#pragma once
#include <set>
#include <vector>
@@ -29,6 +29,61 @@ namespace CVC4 {
typedef __gnu_cxx::hash_set<Expr, ExprHashFunction> ExprSet;
typedef __gnu_cxx::hash_set<Node, NodeHashFunction> NodeSet;
+typedef std::pair<Node, Node> NodePair;
+typedef std::set<NodePair> NodePairSet;
+
+
+struct ProofLetCount {
+ static unsigned counter;
+ static void resetCounter() { counter = 0; }
+ static unsigned newId() { return ++counter; }
+
+ unsigned count;
+ unsigned id;
+ ProofLetCount()
+ : count(0)
+ , id(-1)
+ {}
+
+ void increment() { ++count; }
+ ProofLetCount(unsigned i)
+ : count(1)
+ , id(i)
+ {}
+
+ ProofLetCount(const ProofLetCount& other)
+ : count(other.count)
+ , id (other.id)
+ {}
+
+ bool operator==(const ProofLetCount &other) const {
+ return other.id == id && other.count == count;
+ }
+
+ ProofLetCount& operator=(const ProofLetCount &rhs) {
+ if (&rhs == this) return *this;
+ id = rhs.id;
+ count = rhs.count;
+ return *this;
+ }
+};
+
+struct LetOrderElement {
+ Expr expr;
+ unsigned id;
+ LetOrderElement(Expr e, unsigned i)
+ : expr(e)
+ , id(i)
+ {}
+
+ LetOrderElement()
+ : expr()
+ , id(-1)
+ {}
+};
+
+typedef std::vector<LetOrderElement> Bindings;
+
namespace utils {
std::string toLFSCKind(Kind kind);
@@ -42,7 +97,7 @@ inline unsigned getExtractLow(Expr node) {
}
inline unsigned getSize(Type type) {
- BitVectorType bv(type);
+ BitVectorType bv(type);
return bv.getSize();
}
@@ -60,8 +115,8 @@ inline Expr mkFalse() {
return NodeManager::currentNM()->toExprManager()->mkConst<bool>(false);
}
inline BitVector mkBitVectorOnes(unsigned size) {
- Assert(size > 0);
- return BitVector(1, Integer(1)).signExtend(size - 1);
+ Assert(size > 0);
+ return BitVector(1, Integer(1)).signExtend(size - 1);
}
inline Expr mkExpr(Kind k , Expr expr) {
@@ -73,16 +128,16 @@ inline Expr mkExpr(Kind k , Expr e1, Expr e2) {
inline Expr mkExpr(Kind k , std::vector<Expr>& children) {
return NodeManager::currentNM()->toExprManager()->mkExpr(k, children);
}
-
-
+
+
inline Expr mkOnes(unsigned size) {
- BitVector val = mkBitVectorOnes(size);
- return NodeManager::currentNM()->toExprManager()->mkConst<BitVector>(val);
+ BitVector val = mkBitVectorOnes(size);
+ return NodeManager::currentNM()->toExprManager()->mkConst<BitVector>(val);
}
inline Expr mkConst(unsigned size, unsigned int value) {
BitVector val(size, value);
- return NodeManager::currentNM()->toExprManager()->mkConst<BitVector>(val);
+ return NodeManager::currentNM()->toExprManager()->mkConst<BitVector>(val);
}
inline Expr mkConst(const BitVector& value) {
@@ -92,14 +147,14 @@ inline Expr mkConst(const BitVector& value) {
inline Expr mkOr(const std::vector<Expr>& nodes) {
std::set<Expr> all;
all.insert(nodes.begin(), nodes.end());
- Assert(all.size() != 0 );
+ Assert(all.size() != 0 );
if (all.size() == 1) {
// All the same, or just one
return nodes[0];
}
-
-
+
+
NodeBuilder<> disjunction(kind::OR);
std::set<Expr>::const_iterator it = all.begin();
std::set<Expr>::const_iterator it_end = all.end();
@@ -109,23 +164,23 @@ inline Expr mkOr(const std::vector<Expr>& nodes) {
}
Node res = disjunction;
- return res.toExpr();
+ return res.toExpr();
}/* mkOr() */
-
+
inline Expr mkAnd(const std::vector<Expr>& conjunctions) {
std::set<Expr> all;
all.insert(conjunctions.begin(), conjunctions.end());
if (all.size() == 0) {
- return mkTrue();
+ return mkTrue();
}
-
+
if (all.size() == 1) {
// All the same, or just one
return conjunctions[0];
}
-
+
NodeBuilder<> conjunction(kind::AND);
std::set<Expr>::const_iterator it = all.begin();
@@ -135,7 +190,7 @@ inline Expr mkAnd(const std::vector<Expr>& conjunctions) {
++ it;
}
- Node res = conjunction;
+ Node res = conjunction;
return res.toExpr();
}/* mkAnd() */
@@ -144,14 +199,14 @@ inline Expr mkSortedExpr(Kind kind, const std::vector<Expr>& children) {
all.insert(children.begin(), children.end());
if (all.size() == 0) {
- return mkTrue();
+ return mkTrue();
}
-
+
if (all.size() == 1) {
// All the same, or just one
return children[0];
}
-
+
NodeBuilder<> res(kind);
std::set<Expr>::const_iterator it = all.begin();
@@ -165,13 +220,13 @@ inline Expr mkSortedExpr(Kind kind, const std::vector<Expr>& children) {
}/* mkSortedNode() */
inline const bool getBit(Expr expr, unsigned i) {
- Assert (i < utils::getSize(expr) &&
- expr.isConst());
+ Assert (i < utils::getSize(expr) &&
+ expr.isConst());
Integer bit = expr.getConst<BitVector>().extract(i, i).getValue();
- return (bit == 1u);
+ return (bit == 1u);
}
-void collectAtoms(TNode node, NodeSet& seen);
+void collectAtoms(TNode node, std::set<Node>& seen);
}
diff --git a/src/proof/sat_proof.h b/src/proof/sat_proof.h
index d94b61bf3..bda8094be 100644
--- a/src/proof/sat_proof.h
+++ b/src/proof/sat_proof.h
@@ -34,175 +34,99 @@
#include "util/proof.h"
#include "util/statistics_registry.h"
+// Forward declarations.
namespace CVC4 {
-
class CnfProof;
+template <class Solver>
+class ProofProxy;
+} /* namespace CVC4 */
+namespace CVC4 {
/**
* Helper debugging functions
*/
-template <class Solver> void printDebug(typename Solver::TLit l);
-template <class Solver> void printDebug(typename Solver::TClause& c);
+template <class Solver>
+void printDebug(typename Solver::TLit l);
+template <class Solver>
+void printDebug(typename Solver::TClause& c);
enum ClauseKind {
INPUT,
- THEORY_LEMMA, // we need to distinguish because we must reprove deleted theory lemmas
+ THEORY_LEMMA, // we need to distinguish because we must reprove deleted
+ // theory lemmas
LEARNT
-};/* enum ClauseKind */
-
+}; /* enum ClauseKind */
template <class Solver>
struct ResStep {
typename Solver::TLit lit;
ClauseId id;
bool sign;
- ResStep(typename Solver::TLit l, ClauseId i, bool s) :
- lit(l),
- id(i),
- sign(s)
- {}
-};/* struct ResStep */
+ ResStep(typename Solver::TLit l, ClauseId i, bool s)
+ : lit(l), id(i), sign(s) {}
+}; /* struct ResStep */
template <class Solver>
class ResChain {
-public:
- typedef std::vector< ResStep<Solver> > ResSteps;
- typedef std::set < typename Solver::TLit> LitSet;
-
-private:
- ClauseId d_start;
- ResSteps d_steps;
- LitSet* d_redundantLits;
-public:
+ public:
+ typedef std::vector<ResStep<Solver> > ResSteps;
+ typedef std::set<typename Solver::TLit> LitSet;
+
ResChain(ClauseId start);
+ ~ResChain();
+
void addStep(typename Solver::TLit, ClauseId, bool);
- bool redundantRemoved() { return (d_redundantLits == NULL || d_redundantLits->empty()); }
+ bool redundantRemoved() {
+ return (d_redundantLits == NULL || d_redundantLits->empty());
+ }
void addRedundantLit(typename Solver::TLit lit);
- ~ResChain();
- // accessor methods
- ClauseId getStart() { return d_start; }
- ResSteps& getSteps() { return d_steps; }
- LitSet* getRedundant() { return d_redundantLits; }
-};/* class ResChain */
-template <class Solver> class ProofProxy;
+ // accessor methods
+ ClauseId getStart() const { return d_start; }
+ const ResSteps& getSteps() const { return d_steps; }
+ LitSet* getRedundant() const { return d_redundantLits; }
-class CnfProof;
+ private:
+ ClauseId d_start;
+ ResSteps d_steps;
+ LitSet* d_redundantLits;
+}; /* class ResChain */
-template<class Solver>
+template <class Solver>
class TSatProof {
-protected:
- typedef std::set < typename Solver::TLit> LitSet;
- typedef std::set < typename Solver::TVar> VarSet;
- typedef std::hash_map < ClauseId, typename Solver::TCRef > IdCRefMap;
- typedef std::hash_map < typename Solver::TCRef, ClauseId > ClauseIdMap;
- typedef std::hash_map < ClauseId, typename Solver::TLit> IdUnitMap;
- typedef std::hash_map < int, ClauseId> UnitIdMap;
- typedef std::hash_map < ClauseId, ResChain<Solver>* > IdResMap;
- typedef std::hash_map < ClauseId, uint64_t > IdProofRuleMap;
- typedef std::vector < ResChain<Solver>* > ResStack;
- //typedef std::hash_map <ClauseId, prop::SatClause* > IdToSatClause;
- typedef std::set < ClauseId > IdSet;
- typedef std::vector < typename Solver::TLit > LitVector;
- typedef __gnu_cxx::hash_map<ClauseId, typename Solver::TClause& > IdToMinisatClause;
- typedef __gnu_cxx::hash_map<ClauseId, LitVector* > IdToConflicts;
-
- typename Solver::Solver* d_solver;
- CnfProof* d_cnfProof;
-
- // clauses
- IdCRefMap d_idClause;
- ClauseIdMap d_clauseId;
- IdUnitMap d_idUnit;
- UnitIdMap d_unitId;
- IdHashSet d_deleted;
- IdToSatClause d_deletedTheoryLemmas;
-
-protected:
- IdHashSet d_inputClauses;
- IdHashSet d_lemmaClauses;
- VarSet d_assumptions; // assumption literals for bv solver
- IdHashSet d_assumptionConflicts; // assumption conflicts not actually added to SAT solver
- IdToConflicts d_assumptionConflictsDebug;
-
- // resolutions
- IdResMap d_resChains;
- ResStack d_resStack;
- bool d_checkRes;
-
- const ClauseId d_emptyClauseId;
- const ClauseId d_nullId;
- // proxy class to break circular dependencies
- ProofProxy<Solver>* d_proxy;
-
- // temporary map for updating CRefs
- ClauseIdMap d_temp_clauseId;
- IdCRefMap d_temp_idClause;
-
- // unit conflict
- ClauseId d_unitConflictId;
- bool d_storedUnitConflict;
-
- ClauseId d_trueLit;
- ClauseId d_falseLit;
-
- std::string d_name;
-public:
+ protected:
+ typedef ResChain<Solver> ResolutionChain;
+
+ typedef std::set<typename Solver::TLit> LitSet;
+ typedef std::set<typename Solver::TVar> VarSet;
+ typedef std::hash_map<ClauseId, typename Solver::TCRef> IdCRefMap;
+ typedef std::hash_map<typename Solver::TCRef, ClauseId> ClauseIdMap;
+ typedef std::hash_map<ClauseId, typename Solver::TLit> IdUnitMap;
+ typedef std::hash_map<int, ClauseId> UnitIdMap;
+ typedef std::hash_map<ClauseId, ResolutionChain*> IdResMap;
+ typedef std::hash_map<ClauseId, uint64_t> IdProofRuleMap;
+ typedef std::vector<ResolutionChain*> ResStack;
+ typedef std::set<ClauseId> IdSet;
+ typedef std::vector<typename Solver::TLit> LitVector;
+ typedef __gnu_cxx::hash_map<ClauseId, typename Solver::TClause&>
+ IdToMinisatClause;
+ typedef __gnu_cxx::hash_map<ClauseId, LitVector*> IdToConflicts;
+
+ public:
TSatProof(Solver* solver, const std::string& name, bool checkRes = false);
virtual ~TSatProof();
void setCnfProof(CnfProof* cnf_proof);
-protected:
- void print(ClauseId id);
- void printRes(ClauseId id);
- void printRes(ResChain<Solver>* res);
-
- bool isInputClause(ClauseId id);
- bool isLemmaClause(ClauseId id);
- bool isAssumptionConflict(ClauseId id);
- bool isUnit(ClauseId id);
- bool isUnit(typename Solver::TLit lit);
- bool hasResolution(ClauseId id);
- void createLitSet(ClauseId id, LitSet& set);
- void registerResolution(ClauseId id, ResChain<Solver>* res);
-
- ClauseId getClauseId(typename Solver::TCRef clause);
- ClauseId getClauseId(typename Solver::TLit lit);
- typename Solver::TCRef getClauseRef(ClauseId id);
- typename Solver::TLit getUnit(ClauseId id);
- ClauseId getUnitId(typename Solver::TLit lit);
- typename Solver::TClause& getClause(typename Solver::TCRef ref);
- void getLitVec(ClauseId id, LitVector& vec);
- virtual void toStream(std::ostream& out);
- bool checkResolution(ClauseId id);
- /**
- * Constructs a resolution tree that proves lit
- * and returns the ClauseId for the unit clause lit
- * @param lit the literal we are proving
- *
- * @return
- */
- ClauseId resolveUnit(typename Solver::TLit lit);
- /**
- * Does a depth first search on removed literals and adds the literals
- * to be removed in the proper order to the stack.
- *
- * @param lit the literal we are recursing on
- * @param removedSet the previously computed set of redundant literals
- * @param removeStack the stack of literals in reverse order of resolution
- */
- void removedDfs(typename Solver::TLit lit, LitSet* removedSet, LitVector& removeStack, LitSet& inClause, LitSet& seen);
- void removeRedundantFromRes(ResChain<Solver>* res, ClauseId id);
-public:
void startResChain(typename Solver::TLit start);
void startResChain(typename Solver::TCRef start);
- void addResolutionStep(typename Solver::TLit lit, typename Solver::TCRef clause, bool sign);
+ void addResolutionStep(typename Solver::TLit lit,
+ typename Solver::TCRef clause, bool sign);
/**
* Pops the current resolution of the stack and stores it
* in the resolution map. Also registers the 'clause' parameter
* @param clause the clause the resolution is proving
*/
- //void endResChain(typename Solver::TCRef clause);
+ // void endResChain(typename Solver::TCRef clause);
void endResChain(typename Solver::TLit lit);
void endResChain(ClauseId id);
@@ -219,7 +143,8 @@ public:
void storeLitRedundant(typename Solver::TLit lit);
/// update the CRef Id maps when Minisat does memory reallocation x
- void updateCRef(typename Solver::TCRef old_ref, typename Solver::TCRef new_ref);
+ void updateCRef(typename Solver::TCRef old_ref,
+ typename Solver::TCRef new_ref);
void finishUpdateCRef();
/**
@@ -231,25 +156,22 @@ public:
/// clause registration methods
- ClauseId registerClause(const typename Solver::TCRef clause,
- ClauseKind kind);
- ClauseId registerUnitClause(const typename Solver::TLit lit,
- ClauseKind kind);
+ ClauseId registerClause(const typename Solver::TCRef clause, ClauseKind kind);
+ ClauseId registerUnitClause(const typename Solver::TLit lit, ClauseKind kind);
void registerTrueLit(const typename Solver::TLit lit);
void registerFalseLit(const typename Solver::TLit lit);
ClauseId getTrueUnit() const;
ClauseId getFalseUnit() const;
-
void registerAssumption(const typename Solver::TVar var);
ClauseId registerAssumptionConflict(const typename Solver::TLitVec& confl);
- ClauseId storeUnitConflict(typename Solver::TLit lit,
- ClauseKind kind);
+ ClauseId storeUnitConflict(typename Solver::TLit lit, ClauseKind kind);
/**
- * Marks the deleted clauses as deleted. Note we may still use them in the final
+ * Marks the deleted clauses as deleted. Note we may still use them in the
+ * final
* resolution.
* @param clause
*/
@@ -268,43 +190,171 @@ public:
*/
void storeUnitResolution(typename Solver::TLit lit);
- ProofProxy<Solver>* getProxy() {return d_proxy; }
+ ProofProxy<Solver>* getProxy() { return d_proxy; }
/**
* Constructs the SAT proof for the given clause,
* by collecting the needed clauses in the d_seen
* data-structures, also notifying the proofmanager.
*/
void constructProof(ClauseId id);
- void constructProof() {
- constructProof(d_emptyClauseId);
- }
+ void constructProof() { constructProof(d_emptyClauseId); }
void collectClauses(ClauseId id);
prop::SatClause* buildClause(ClauseId id);
-protected:
- IdSet d_seenLearnt;
- IdToSatClause d_seenInputs;
- IdToSatClause d_seenLemmas;
+
+ virtual void printResolution(ClauseId id, std::ostream& out,
+ std::ostream& paren) = 0;
+ virtual void printResolutions(std::ostream& out, std::ostream& paren) = 0;
+ virtual void printResolutionEmptyClause(std::ostream& out,
+ std::ostream& paren) = 0;
+ virtual void printAssumptionsResolution(ClauseId id, std::ostream& out,
+ std::ostream& paren) = 0;
+
+ void collectClausesUsed(IdToSatClause& inputs, IdToSatClause& lemmas);
+
+ void storeClauseGlue(ClauseId clause, int glue);
+
+ protected:
+ void print(ClauseId id) const;
+ void printRes(ClauseId id) const;
+ void printRes(const ResolutionChain& res) const;
+
+ bool isInputClause(ClauseId id) const;
+ bool isLemmaClause(ClauseId id) const;
+ bool isAssumptionConflict(ClauseId id) const;
+
+ bool isUnit(ClauseId id) const;
+ typename Solver::TLit getUnit(ClauseId id) const;
+
+ bool isUnit(typename Solver::TLit lit) const;
+ ClauseId getUnitId(typename Solver::TLit lit) const;
+
+
+
+ bool hasResolutionChain(ClauseId id) const;
+
+ /** Returns the resolution chain associated with id. Assert fails if
+ * hasResolution(id) does not hold. */
+ const ResolutionChain& getResolutionChain(ClauseId id) const;
+
+ /** Returns a mutable pointer to the resolution chain associated with id.
+ * Assert fails if hasResolution(id) does not hold. */
+ ResolutionChain* getMutableResolutionChain(ClauseId id);
+
+ void createLitSet(ClauseId id, LitSet& set);
+
+ /**
+ * Registers a ClauseId with a resolution chain res.
+ * Takes ownership of the memory associated with res.
+ */
+ void registerResolution(ClauseId id, ResolutionChain* res);
+
+
+ bool hasClauseIdForCRef(typename Solver::TCRef clause) const;
+ ClauseId getClauseIdForCRef(typename Solver::TCRef clause) const;
+
+ bool hasClauseIdForLiteral(typename Solver::TLit lit) const;
+ ClauseId getClauseIdForLiteral(typename Solver::TLit lit) const;
+
+ bool hasClauseRef(ClauseId id) const;
+ typename Solver::TCRef getClauseRef(ClauseId id) const;
+
+
+ const typename Solver::TClause& getClause(typename Solver::TCRef ref) const;
+ typename Solver::TClause* getMutableClause(typename Solver::TCRef ref);
+
+ void getLitVec(ClauseId id, LitVector& vec);
+ virtual void toStream(std::ostream& out);
+
+ bool checkResolution(ClauseId id);
+
+ /**
+ * Constructs a resolution tree that proves lit
+ * and returns the ClauseId for the unit clause lit
+ * @param lit the literal we are proving
+ *
+ * @return
+ */
+ ClauseId resolveUnit(typename Solver::TLit lit);
+
+ /**
+ * Does a depth first search on removed literals and adds the literals
+ * to be removed in the proper order to the stack.
+ *
+ * @param lit the literal we are recursing on
+ * @param removedSet the previously computed set of redundant literals
+ * @param removeStack the stack of literals in reverse order of resolution
+ */
+ void removedDfs(typename Solver::TLit lit, LitSet* removedSet,
+ LitVector& removeStack, LitSet& inClause, LitSet& seen);
+ void removeRedundantFromRes(ResChain<Solver>* res, ClauseId id);
std::string varName(typename Solver::TLit lit);
std::string clauseName(ClauseId id);
-
void addToProofManager(ClauseId id, ClauseKind kind);
void addToCnfProof(ClauseId id);
-public:
- virtual void printResolution(ClauseId id, std::ostream& out, std::ostream& paren) = 0;
- virtual void printResolutions(std::ostream& out, std::ostream& paren) = 0;
- virtual void printResolutionEmptyClause(std::ostream& out, std::ostream& paren) = 0;
- virtual void printAssumptionsResolution(ClauseId id, std::ostream& out, std::ostream& paren) = 0;
- void collectClausesUsed(IdToSatClause& inputs,
- IdToSatClause& lemmas);
+ // Internal data.
+ typename Solver::Solver* d_solver;
+ CnfProof* d_cnfProof;
- void storeClauseGlue(ClauseId clause, int glue);
+ // clauses
+ IdCRefMap d_idClause;
+ ClauseIdMap d_clauseId;
+ IdUnitMap d_idUnit;
+ UnitIdMap d_unitId;
+ IdHashSet d_deleted;
+ IdToSatClause d_deletedTheoryLemmas;
+
+ IdHashSet d_inputClauses;
+ IdHashSet d_lemmaClauses;
+ VarSet d_assumptions; // assumption literals for bv solver
+ IdHashSet d_assumptionConflicts; // assumption conflicts not actually added
+ // to SAT solver
+ IdToConflicts d_assumptionConflictsDebug;
+
+ // Resolutions.
+ /**
+ * Map from ClauseId to resolution chain corresponding proving the
+ * clause corresponding to the ClauseId. d_resolutionChains owns the
+ * memory of the ResChain* it contains.
+ */
+ IdResMap d_resolutionChains;
+
+ /*
+ * Stack containting current ResChain* we are working on. d_resStack
+ * owns the memory for the ResChain* it contains. Invariant: no
+ * ResChain* pointer can be both in d_resStack and
+ * d_resolutionChains. Memory ownership is transfered from
+ * d_resStack to d_resolutionChains via registerResolution.
+ */
+ ResStack d_resStack;
+ bool d_checkRes;
+
+ const ClauseId d_emptyClauseId;
+ const ClauseId d_nullId;
+ // proxy class to break circular dependencies
+ ProofProxy<Solver>* d_proxy;
+ // temporary map for updating CRefs
+ ClauseIdMap d_temp_clauseId;
+ IdCRefMap d_temp_idClause;
-private:
+ // unit conflict
+ ClauseId d_unitConflictId;
+ bool d_storedUnitConflict;
+
+ ClauseId d_trueLit;
+ ClauseId d_falseLit;
+
+ std::string d_name;
+
+ IdSet d_seenLearnt;
+ IdToSatClause d_seenInputs;
+ IdToSatClause d_seenLemmas;
+
+ private:
__gnu_cxx::hash_map<ClauseId, int> d_glueMap;
struct Statistics {
IntStat d_numLearnedClauses;
@@ -320,49 +370,47 @@ private:
};
Statistics d_statistics;
-};/* class TSatProof */
+}; /* class TSatProof */
template <class S>
class ProofProxy {
-private:
+ private:
TSatProof<S>* d_proof;
-public:
+
+ public:
ProofProxy(TSatProof<S>* pf);
void updateCRef(typename S::TCRef oldref, typename S::TCRef newref);
-};/* class ProofProxy */
-
+}; /* class ProofProxy */
template <class SatSolver>
class LFSCSatProof : public TSatProof<SatSolver> {
-private:
-
-public:
- LFSCSatProof(SatSolver* solver, const std::string& name, bool checkRes = false)
- : TSatProof<SatSolver>(solver, name, checkRes)
- {}
- virtual void printResolution(ClauseId id, std::ostream& out, std::ostream& paren);
+ private:
+ public:
+ LFSCSatProof(SatSolver* solver, const std::string& name,
+ bool checkRes = false)
+ : TSatProof<SatSolver>(solver, name, checkRes) {}
+ virtual void printResolution(ClauseId id, std::ostream& out,
+ std::ostream& paren);
virtual void printResolutions(std::ostream& out, std::ostream& paren);
- virtual void printResolutionEmptyClause(std::ostream& out, std::ostream& paren);
- virtual void printAssumptionsResolution(ClauseId id, std::ostream& out, std::ostream& paren);
-};/* class LFSCSatProof */
-
-
+ virtual void printResolutionEmptyClause(std::ostream& out,
+ std::ostream& paren);
+ virtual void printAssumptionsResolution(ClauseId id, std::ostream& out,
+ std::ostream& paren);
+}; /* class LFSCSatProof */
-template<class Solver>
+template <class Solver>
prop::SatLiteral toSatLiteral(typename Solver::TLit lit);
-
/**
* Convert from minisat clause to SatClause
*
* @param minisat_cl
* @param sat_cl
*/
-template<class Solver>
+template <class Solver>
void toSatClause(const typename Solver::TClause& minisat_cl,
prop::SatClause& sat_cl);
-
-}/* CVC4 namespace */
+} /* CVC4 namespace */
#endif /* __CVC4__SAT__PROOF_H */
diff --git a/src/proof/sat_proof_implementation.h b/src/proof/sat_proof_implementation.h
index e773e4b47..1e01e4dce 100644
--- a/src/proof/sat_proof_implementation.h
+++ b/src/proof/sat_proof_implementation.h
@@ -32,29 +32,28 @@
namespace CVC4 {
template <class Solver>
-void printLit (typename Solver::TLit l) {
+void printLit(typename Solver::TLit l) {
Debug("proof:sat") << (sign(l) ? "-" : "") << var(l) + 1;
}
template <class Solver>
-void printClause (typename Solver::TClause& c) {
+void printClause(const typename Solver::TClause& c) {
for (int i = 0; i < c.size(); i++) {
Debug("proof:sat") << (sign(c[i]) ? "-" : "") << var(c[i]) + 1 << " ";
}
}
template <class Solver>
-void printClause (std::vector<typename Solver::TLit>& c) {
+void printClause(const std::vector<typename Solver::TLit>& c) {
for (unsigned i = 0; i < c.size(); i++) {
Debug("proof:sat") << (sign(c[i]) ? "-" : "") << var(c[i]) + 1 << " ";
}
}
-
template <class Solver>
void printLitSet(const std::set<typename Solver::TLit>& s) {
- typename std::set < typename Solver::TLit>::const_iterator it = s.begin();
- for(; it != s.end(); ++it) {
+ typename std::set<typename Solver::TLit>::const_iterator it = s.begin();
+ for (; it != s.end(); ++it) {
printLit<Solver>(*it);
Debug("proof:sat") << " ";
}
@@ -63,18 +62,17 @@ void printLitSet(const std::set<typename Solver::TLit>& s) {
// purely debugging functions
template <class Solver>
-void printDebug (typename Solver::TLit l) {
+void printDebug(typename Solver::TLit l) {
Debug("proof:sat") << (sign(l) ? "-" : "") << var(l) + 1 << std::endl;
}
template <class Solver>
-void printDebug (typename Solver::TClause& c) {
+void printDebug(typename Solver::TClause& c) {
for (int i = 0; i < c.size(); i++) {
Debug("proof:sat") << (sign(c[i]) ? "-" : "") << var(c[i]) + 1 << " ";
}
Debug("proof:sat") << std::endl;
}
-
/**
* Converts the clause associated to id to a set of literals
*
@@ -84,11 +82,11 @@ void printDebug (typename Solver::TClause& c) {
template <class Solver>
void TSatProof<Solver>::createLitSet(ClauseId id, LitSet& set) {
Assert(set.empty());
- if(isUnit(id)) {
+ if (isUnit(id)) {
set.insert(getUnit(id));
return;
}
- if ( id == d_emptyClauseId) {
+ if (id == d_emptyClauseId) {
return;
}
// if it's an assumption
@@ -101,13 +99,12 @@ void TSatProof<Solver>::createLitSet(ClauseId id, LitSet& set) {
}
typename Solver::TCRef ref = getClauseRef(id);
- typename Solver::TClause& c = getClause(ref);
+ const typename Solver::TClause& c = getClause(ref);
for (int i = 0; i < c.size(); i++) {
set.insert(c[i]);
}
}
-
/**
* Resolves clause1 and clause2 on variable var and stores the
* result in clause1
@@ -124,8 +121,8 @@ bool resolve(const typename Solver::TLit v,
typename Solver::TLit var = sign(v) ? ~v : v;
if (s) {
// literal appears positive in the first clause
- if( !clause2.count(~var)) {
- if(Debug.isOn("proof:sat")) {
+ if (!clause2.count(~var)) {
+ if (Debug.isOn("proof:sat")) {
Debug("proof:sat") << "proof:resolve: Missing literal ";
printLit<Solver>(var);
Debug("proof:sat") << std::endl;
@@ -135,13 +132,13 @@ bool resolve(const typename Solver::TLit v,
clause1.erase(var);
clause2.erase(~var);
typename std::set<typename Solver::TLit>::iterator it = clause2.begin();
- for (; it!= clause2.end(); ++it) {
+ for (; it != clause2.end(); ++it) {
clause1.insert(*it);
}
} else {
// literal appears negative in the first clause
- if( !clause1.count(~var) || !clause2.count(var)) {
- if(Debug.isOn("proof:sat")) {
+ if (!clause1.count(~var) || !clause2.count(var)) {
+ if (Debug.isOn("proof:sat")) {
Debug("proof:sat") << "proof:resolve: Missing literal ";
printLit<Solver>(var);
Debug("proof:sat") << std::endl;
@@ -151,7 +148,7 @@ bool resolve(const typename Solver::TLit v,
clause1.erase(~var);
clause2.erase(var);
typename std::set<typename Solver::TLit>::iterator it = clause2.begin();
- for (; it!= clause2.end(); ++it) {
+ for (; it != clause2.end(); ++it) {
clause1.insert(*it);
}
}
@@ -160,13 +157,19 @@ bool resolve(const typename Solver::TLit v,
/// ResChain
template <class Solver>
-ResChain<Solver>::ResChain(ClauseId start) :
- d_start(start),
- d_steps(),
- d_redundantLits(NULL)
- {}
+ResChain<Solver>::ResChain(ClauseId start)
+ : d_start(start), d_steps(), d_redundantLits(NULL) {}
+
+template <class Solver>
+ResChain<Solver>::~ResChain() {
+ if (d_redundantLits != NULL) {
+ delete d_redundantLits;
+ }
+}
+
template <class Solver>
-void ResChain<Solver>::addStep(typename Solver::TLit lit, ClauseId id, bool sign) {
+void ResChain<Solver>::addStep(typename Solver::TLit lit, ClauseId id,
+ bool sign) {
ResStep<Solver> step(lit, id, sign);
d_steps.push_back(step);
}
@@ -181,50 +184,47 @@ void ResChain<Solver>::addRedundantLit(typename Solver::TLit lit) {
}
}
-
/// ProxyProof
template <class Solver>
-ProofProxy<Solver>::ProofProxy(TSatProof<Solver>* proof):
- d_proof(proof)
-{}
+ProofProxy<Solver>::ProofProxy(TSatProof<Solver>* proof) : d_proof(proof) {}
template <class Solver>
-void ProofProxy<Solver>::updateCRef(typename Solver::TCRef oldref, typename Solver::TCRef newref) {
+void ProofProxy<Solver>::updateCRef(typename Solver::TCRef oldref,
+ typename Solver::TCRef newref) {
d_proof->updateCRef(oldref, newref);
}
-
/// SatProof
template <class Solver>
-TSatProof<Solver>::TSatProof(Solver* solver, const std::string& name, bool checkRes)
- : d_solver(solver)
- , d_cnfProof(NULL)
- , d_idClause()
- , d_clauseId()
- , d_idUnit()
- , d_deleted()
- , d_inputClauses()
- , d_lemmaClauses()
- , d_assumptions()
- , d_assumptionConflicts()
- , d_assumptionConflictsDebug()
- , d_resChains()
- , d_resStack()
- , d_checkRes(checkRes)
- , d_emptyClauseId(ClauseIdEmpty)
- , d_nullId(-2)
- , d_temp_clauseId()
- , d_temp_idClause()
- , d_unitConflictId()
- , d_storedUnitConflict(false)
- , d_trueLit(ClauseIdUndef)
- , d_falseLit(ClauseIdUndef)
- , d_name(name)
- , d_seenLearnt()
- , d_seenInputs()
- , d_seenLemmas()
- , d_statistics(name)
-{
+TSatProof<Solver>::TSatProof(Solver* solver, const std::string& name,
+ bool checkRes)
+ : d_solver(solver),
+ d_cnfProof(NULL),
+ d_idClause(),
+ d_clauseId(),
+ d_idUnit(),
+ d_deleted(),
+ d_inputClauses(),
+ d_lemmaClauses(),
+ d_assumptions(),
+ d_assumptionConflicts(),
+ d_assumptionConflictsDebug(),
+ d_resolutionChains(),
+ d_resStack(),
+ d_checkRes(checkRes),
+ d_emptyClauseId(ClauseIdEmpty),
+ d_nullId(-2),
+ d_temp_clauseId(),
+ d_temp_idClause(),
+ d_unitConflictId(),
+ d_storedUnitConflict(false),
+ d_trueLit(ClauseIdUndef),
+ d_falseLit(ClauseIdUndef),
+ d_name(name),
+ d_seenLearnt(),
+ d_seenInputs(),
+ d_seenLemmas(),
+ d_statistics(name) {
d_proxy = new ProofProxy<Solver>(this);
}
@@ -233,34 +233,53 @@ TSatProof<Solver>::~TSatProof() {
delete d_proxy;
// FIXME: double free if deleted clause also appears in d_seenLemmas?
- IdToSatClause::iterator it = d_deletedTheoryLemmas.begin();
- IdToSatClause::iterator end = d_deletedTheoryLemmas.end();
+ IdToSatClause::const_iterator it = d_deletedTheoryLemmas.begin();
+ IdToSatClause::const_iterator end = d_deletedTheoryLemmas.end();
for (; it != end; ++it) {
ClauseId id = it->first;
// otherwise deleted in next loop
- if (d_seenLemmas.find(id) == d_seenLemmas.end())
+ if (d_seenLemmas.find(id) == d_seenLemmas.end()) {
delete it->second;
+ }
}
- IdToSatClause::iterator seen_it = d_seenLemmas.begin();
- IdToSatClause::iterator seen_end = d_seenLemmas.end();
+ IdToSatClause::const_iterator seen_lemma_it = d_seenLemmas.begin();
+ IdToSatClause::const_iterator seen_lemma_end = d_seenLemmas.end();
- for (; seen_it != seen_end; ++seen_it) {
- delete seen_it->second;
+ for (; seen_lemma_it != seen_lemma_end; ++seen_lemma_it) {
+ delete seen_lemma_it->second;
}
- seen_it = d_seenInputs.begin();
- seen_end = d_seenInputs.end();
+ IdToSatClause::const_iterator seen_input_it = d_seenInputs.begin();
+ IdToSatClause::const_iterator seen_input_end = d_seenInputs.end();
- for (; seen_it != seen_end; ++seen_it) {
- delete seen_it->second;
+ for (; seen_input_it != seen_input_end; ++seen_input_it) {
+ delete seen_input_it->second;
+ }
+
+ typedef typename IdResMap::const_iterator ResolutionChainIterator;
+ ResolutionChainIterator resolution_it = d_resolutionChains.begin();
+ ResolutionChainIterator resolution_it_end = d_resolutionChains.end();
+ for (; resolution_it != resolution_it_end; ++resolution_it) {
+ ResChain<Solver>* current = resolution_it->second;
+ delete current;
+ }
+
+ // It could be the case that d_resStack is not empty at destruction time
+ // (for example in the SAT case).
+ typename ResStack::const_iterator resolution_stack_it = d_resStack.begin();
+ typename ResStack::const_iterator resolution_stack_it_end = d_resStack.end();
+ for (; resolution_stack_it != resolution_stack_it_end;
+ ++resolution_stack_it) {
+ ResChain<Solver>* current = *resolution_stack_it;
+ delete current;
}
}
template <class Solver>
void TSatProof<Solver>::setCnfProof(CnfProof* cnf_proof) {
- Assert (d_cnfProof == NULL);
+ Assert(d_cnfProof == NULL);
d_cnfProof = cnf_proof;
}
@@ -273,19 +292,19 @@ void TSatProof<Solver>::setCnfProof(CnfProof* cnf_proof) {
*/
template <class Solver>
bool TSatProof<Solver>::checkResolution(ClauseId id) {
- if(d_checkRes) {
+ if (d_checkRes) {
bool validRes = true;
- Assert(d_resChains.find(id) != d_resChains.end());
- ResChain<Solver>* res = d_resChains[id];
+ Assert(hasResolutionChain(id));
+ const ResolutionChain& res = getResolutionChain(id);
LitSet clause1;
- createLitSet(res->getStart(), clause1);
- typename ResChain<Solver>::ResSteps& steps = res->getSteps();
+ createLitSet(res.getStart(), clause1);
+ const typename ResolutionChain::ResSteps& steps = res.getSteps();
for (unsigned i = 0; i < steps.size(); i++) {
- typename Solver::TLit var = steps[i].lit;
+ typename Solver::TLit var = steps[i].lit;
LitSet clause2;
- createLitSet (steps[i].id, clause2);
- bool res = resolve<Solver> (var, clause1, clause2, steps[i].sign);
- if(res == false) {
+ createLitSet(steps[i].id, clause2);
+ bool res = resolve<Solver>(var, clause1, clause2, steps[i].sign);
+ if (res == false) {
validRes = false;
break;
}
@@ -307,8 +326,9 @@ bool TSatProof<Solver>::checkResolution(ClauseId id) {
for (unsigned i = 0; i < c.size(); ++i) {
int count = clause1.erase(c[i]);
if (count == 0) {
- if(Debug.isOn("proof:sat")) {
- Debug("proof:sat") << "proof:checkResolution::literal not in computed result ";
+ if (Debug.isOn("proof:sat")) {
+ Debug("proof:sat")
+ << "proof:checkResolution::literal not in computed result ";
printLit<Solver>(c[i]);
Debug("proof:sat") << "\n";
}
@@ -316,9 +336,10 @@ bool TSatProof<Solver>::checkResolution(ClauseId id) {
}
}
validRes = clause1.empty();
- if (! validRes) {
- if(Debug.isOn("proof:sat")) {
- Debug("proof:sat") << "proof:checkResolution::Invalid Resolution, unremoved literals: \n";
+ if (!validRes) {
+ if (Debug.isOn("proof:sat")) {
+ Debug("proof:sat") << "proof:checkResolution::Invalid Resolution, "
+ "unremoved literals: \n";
printLitSet<Solver>(clause1);
Debug("proof:sat") << "proof:checkResolution:: result should be: \n";
printClause<Solver>(c);
@@ -331,37 +352,54 @@ bool TSatProof<Solver>::checkResolution(ClauseId id) {
}
}
-
-
-
/// helper methods
template <class Solver>
-ClauseId TSatProof<Solver>::getClauseId(typename Solver::TCRef ref) {
- if(d_clauseId.find(ref) == d_clauseId.end()) {
+bool TSatProof<Solver>::hasClauseIdForCRef(typename Solver::TCRef ref) const {
+ return d_clauseId.find(ref) != d_clauseId.end();
+}
+
+template <class Solver>
+ClauseId TSatProof<Solver>::getClauseIdForCRef(
+ typename Solver::TCRef ref) const {
+ if (d_clauseId.find(ref) == d_clauseId.end()) {
Debug("proof:sat") << "Missing clause \n";
}
- Assert(d_clauseId.find(ref) != d_clauseId.end());
- return d_clauseId[ref];
+ Assert(hasClauseIdForCRef(ref));
+ return d_clauseId.find(ref)->second;
+}
+
+template <class Solver>
+bool TSatProof<Solver>::hasClauseIdForLiteral(typename Solver::TLit lit) const {
+ return d_unitId.find(toInt(lit)) != d_unitId.end();
+}
+
+template <class Solver>
+ClauseId TSatProof<Solver>::getClauseIdForLiteral(
+ typename Solver::TLit lit) const {
+ Assert(hasClauseIdForLiteral(lit));
+ return d_unitId.find(toInt(lit))->second;
}
template <class Solver>
-ClauseId TSatProof<Solver>::getClauseId(typename Solver::TLit lit) {
- Assert(d_unitId.find(toInt(lit)) != d_unitId.end());
- return d_unitId[toInt(lit)];
+bool TSatProof<Solver>::hasClauseRef(ClauseId id) const {
+ return d_idClause.find(id) != d_idClause.end();
}
+
template <class Solver>
-typename Solver::TCRef TSatProof<Solver>::getClauseRef(ClauseId id) {
- if (d_idClause.find(id) == d_idClause.end()) {
- Debug("proof:sat") << "proof:getClauseRef cannot find clause "<<id<<" "
- << ((d_deleted.find(id) != d_deleted.end()) ? "deleted" : "")
- << (isUnit(id)? "Unit" : "") << std::endl;
+typename Solver::TCRef TSatProof<Solver>::getClauseRef(ClauseId id) const {
+ if (!hasClauseRef(id)) {
+ Debug("proof:sat") << "proof:getClauseRef cannot find clause " << id << " "
+ << ((d_deleted.find(id) != d_deleted.end()) ? "deleted"
+ : "")
+ << (isUnit(id) ? "Unit" : "") << std::endl;
}
- Assert(d_idClause.find(id) != d_idClause.end());
- return d_idClause[id];
+ Assert(hasClauseRef(id));
+ return d_idClause.find(id)->second;
}
template <class Solver>
-typename Solver::TClause& TSatProof<Solver>::getClause(typename Solver::TCRef ref) {
+const typename Solver::TClause& TSatProof<Solver>::getClause(
+ typename Solver::TCRef ref) const {
Assert(ref != Solver::TCRef_Undef);
Assert(ref >= 0 && ref < d_solver->ca.size());
return d_solver->ca[ref];
@@ -379,85 +417,106 @@ void TSatProof<Solver>::getLitVec(ClauseId id, LitVector& vec) {
return;
}
typename Solver::TCRef cref = getClauseRef(id);
- typename Solver::TClause& cl = getClause(cref);
+ const typename Solver::TClause& cl = getClause(cref);
for (int i = 0; i < cl.size(); ++i) {
vec.push_back(cl[i]);
}
}
-
template <class Solver>
-typename Solver::TLit TSatProof<Solver>::getUnit(ClauseId id) {
- Assert(d_idUnit.find(id) != d_idUnit.end());
- return d_idUnit[id];
+bool TSatProof<Solver>::isUnit(ClauseId id) const {
+ return d_idUnit.find(id) != d_idUnit.end();
}
+
template <class Solver>
-bool TSatProof<Solver>::isUnit(ClauseId id) {
- return d_idUnit.find(id) != d_idUnit.end();
+typename Solver::TLit TSatProof<Solver>::getUnit(ClauseId id) const {
+ Assert(isUnit(id));
+ return d_idUnit.find(id)->second;
}
+
template <class Solver>
-bool TSatProof<Solver>::isUnit(typename Solver::TLit lit) {
+bool TSatProof<Solver>::isUnit(typename Solver::TLit lit) const {
return d_unitId.find(toInt(lit)) != d_unitId.end();
}
+
template <class Solver>
-ClauseId TSatProof<Solver>::getUnitId(typename Solver::TLit lit) {
+ClauseId TSatProof<Solver>::getUnitId(typename Solver::TLit lit) const {
Assert(isUnit(lit));
- return d_unitId[toInt(lit)];
+ return d_unitId.find(toInt(lit))->second;
}
+
template <class Solver>
-bool TSatProof<Solver>::hasResolution(ClauseId id) {
- return d_resChains.find(id) != d_resChains.end();
+bool TSatProof<Solver>::hasResolutionChain(ClauseId id) const {
+ return d_resolutionChains.find(id) != d_resolutionChains.end();
}
+
template <class Solver>
-bool TSatProof<Solver>::isInputClause(ClauseId id) {
- return (d_inputClauses.find(id) != d_inputClauses.end());
+const typename TSatProof<Solver>::ResolutionChain&
+TSatProof<Solver>::getResolutionChain(ClauseId id) const {
+ Assert(hasResolutionChain(id));
+ const ResolutionChain* chain = d_resolutionChains.find(id)->second;
+ return *chain;
}
+
template <class Solver>
-bool TSatProof<Solver>::isLemmaClause(ClauseId id) {
- return (d_lemmaClauses.find(id) != d_lemmaClauses.end());
+typename TSatProof<Solver>::ResolutionChain*
+TSatProof<Solver>::getMutableResolutionChain(ClauseId id) {
+ Assert(hasResolutionChain(id));
+ ResolutionChain* chain = d_resolutionChains.find(id)->second;
+ return chain;
}
template <class Solver>
-bool TSatProof<Solver>::isAssumptionConflict(ClauseId id) {
- return d_assumptionConflicts.find(id) != d_assumptionConflicts.end();
+bool TSatProof<Solver>::isInputClause(ClauseId id) const {
+ return d_inputClauses.find(id) != d_inputClauses.end();
}
+template <class Solver>
+bool TSatProof<Solver>::isLemmaClause(ClauseId id) const {
+ return d_lemmaClauses.find(id) != d_lemmaClauses.end();
+}
+
+template <class Solver>
+bool TSatProof<Solver>::isAssumptionConflict(ClauseId id) const {
+ return d_assumptionConflicts.find(id) != d_assumptionConflicts.end();
+}
template <class Solver>
-void TSatProof<Solver>::print(ClauseId id) {
+void TSatProof<Solver>::print(ClauseId id) const {
if (d_deleted.find(id) != d_deleted.end()) {
- Debug("proof:sat") << "del"<<id;
+ Debug("proof:sat") << "del" << id;
} else if (isUnit(id)) {
printLit<Solver>(getUnit(id));
} else if (id == d_emptyClauseId) {
- Debug("proof:sat") << "empty "<< std::endl;
- }
- else {
+ Debug("proof:sat") << "empty " << std::endl;
+ } else {
typename Solver::TCRef ref = getClauseRef(id);
printClause<Solver>(getClause(ref));
}
}
+
template <class Solver>
-void TSatProof<Solver>::printRes(ClauseId id) {
- Assert(hasResolution(id));
- Debug("proof:sat") << "id "<< id <<": ";
- printRes(d_resChains[id]);
+void TSatProof<Solver>::printRes(ClauseId id) const {
+ Assert(hasResolutionChain(id));
+ Debug("proof:sat") << "id " << id << ": ";
+ printRes(getResolutionChain(id));
}
+
template <class Solver>
-void TSatProof<Solver>::printRes(ResChain<Solver>* res) {
- ClauseId start_id = res->getStart();
+void TSatProof<Solver>::printRes(const ResolutionChain& res) const {
+ ClauseId start_id = res.getStart();
- if(Debug.isOn("proof:sat")) {
+ if (Debug.isOn("proof:sat")) {
Debug("proof:sat") << "(";
print(start_id);
}
- typename ResChain<Solver>::ResSteps& steps = res->getSteps();
- for(unsigned i = 0; i < steps.size(); i++ ) {
+ const typename ResolutionChain::ResSteps& steps = res.getSteps();
+ for (unsigned i = 0; i < steps.size(); i++) {
typename Solver::TLit v = steps[i].lit;
ClauseId id = steps[i].id;
- if(Debug.isOn("proof:sat")) {
+ if (Debug.isOn("proof:sat")) {
Debug("proof:sat") << "[";
printLit<Solver>(v);
Debug("proof:sat") << "] ";
@@ -469,8 +528,8 @@ void TSatProof<Solver>::printRes(ResChain<Solver>* res) {
/// registration methods
template <class Solver>
- ClauseId TSatProof<Solver>::registerClause(typename Solver::TCRef clause,
- ClauseKind kind) {
+ClauseId TSatProof<Solver>::registerClause(typename Solver::TCRef clause,
+ ClauseKind kind) {
Assert(clause != Solver::TCRef_Undef);
typename ClauseIdMap::iterator it = d_clauseId.find(clause);
if (it == d_clauseId.end()) {
@@ -485,10 +544,8 @@ template <class Solver>
Assert(d_lemmaClauses.find(newId) == d_lemmaClauses.end());
d_lemmaClauses.insert(newId);
Debug("pf::sat") << "TSatProof::registerClause registering a new lemma clause: "
- << newId << " = " << *buildClause(newId)
- << ". Explainer theory: " << d_cnfProof->getExplainerTheory()
- << std::endl;
- d_cnfProof->registerExplanationLemma(newId);
+ << newId << " = " << *buildClause(newId)
+ << std::endl;
}
}
@@ -496,15 +553,16 @@ template <class Solver>
Assert(kind != INPUT || d_inputClauses.count(id));
Assert(kind != THEORY_LEMMA || d_lemmaClauses.count(id));
- Debug("proof:sat:detailed") << "registerClause CRef: " << clause << " id: " << d_clauseId[clause]
- <<" kind: " << kind << "\n";
- //ProofManager::currentPM()->setRegisteredClauseId( d_clauseId[clause] );
+ Debug("proof:sat:detailed") << "registerClause CRef: " << clause
+ << " id: " << d_clauseId[clause]
+ << " kind: " << kind << "\n";
+ // ProofManager::currentPM()->setRegisteredClauseId( d_clauseId[clause] );
return id;
}
template <class Solver>
ClauseId TSatProof<Solver>::registerUnitClause(typename Solver::TLit lit,
- ClauseKind kind) {
+ ClauseKind kind) {
Debug("cores") << "registerUnitClause " << kind << std::endl;
typename UnitIdMap::iterator it = d_unitId.find(toInt(lit));
if (it == d_unitId.end()) {
@@ -519,59 +577,57 @@ ClauseId TSatProof<Solver>::registerUnitClause(typename Solver::TLit lit,
if (kind == THEORY_LEMMA) {
Assert(d_lemmaClauses.find(newId) == d_lemmaClauses.end());
Debug("pf::sat") << "TSatProof::registerUnitClause: registering a new lemma (UNIT CLAUSE): "
- << lit
- << ". Explainer theory: " << d_cnfProof->getExplainerTheory()
- << std::endl;
+ << lit
+ << std::endl;
d_lemmaClauses.insert(newId);
- d_cnfProof->registerExplanationLemma(newId);
}
}
ClauseId id = d_unitId[toInt(lit)];
Assert(kind != INPUT || d_inputClauses.count(id));
Assert(kind != THEORY_LEMMA || d_lemmaClauses.count(id));
Debug("proof:sat:detailed") << "registerUnitClause id: " << id
- <<" kind: " << kind << "\n";
+ << " kind: " << kind << "\n";
// ProofManager::currentPM()->setRegisteredClauseId( d_unitId[toInt(lit)] );
return id;
}
template <class Solver>
void TSatProof<Solver>::registerTrueLit(const typename Solver::TLit lit) {
- Assert (d_trueLit == ClauseIdUndef);
+ Assert(d_trueLit == ClauseIdUndef);
d_trueLit = registerUnitClause(lit, INPUT);
}
template <class Solver>
void TSatProof<Solver>::registerFalseLit(const typename Solver::TLit lit) {
- Assert (d_falseLit == ClauseIdUndef);
+ Assert(d_falseLit == ClauseIdUndef);
d_falseLit = registerUnitClause(lit, INPUT);
}
template <class Solver>
ClauseId TSatProof<Solver>::getTrueUnit() const {
- Assert (d_trueLit != ClauseIdUndef);
+ Assert(d_trueLit != ClauseIdUndef);
return d_trueLit;
}
template <class Solver>
ClauseId TSatProof<Solver>::getFalseUnit() const {
- Assert (d_falseLit != ClauseIdUndef);
+ Assert(d_falseLit != ClauseIdUndef);
return d_falseLit;
}
-
template <class Solver>
void TSatProof<Solver>::registerAssumption(const typename Solver::TVar var) {
- Assert (d_assumptions.find(var) == d_assumptions.end());
+ Assert(d_assumptions.find(var) == d_assumptions.end());
d_assumptions.insert(var);
}
template <class Solver>
-ClauseId TSatProof<Solver>::registerAssumptionConflict(const typename Solver::TLitVec& confl) {
+ClauseId TSatProof<Solver>::registerAssumptionConflict(
+ const typename Solver::TLitVec& confl) {
Debug("proof:sat:detailed") << "registerAssumptionConflict " << std::endl;
// Uniqueness is checked in the bit-vector proof
// should be vars
for (int i = 0; i < confl.size(); ++i) {
- Assert (d_assumptions.find(var(confl[i])) != d_assumptions.end());
+ Assert(d_assumptions.find(var(confl[i])) != d_assumptions.end());
}
ClauseId new_id = ProofManager::currentPM()->nextId();
d_assumptionConflicts.insert(new_id);
@@ -588,9 +644,10 @@ ClauseId TSatProof<Solver>::registerAssumptionConflict(const typename Solver::TL
return new_id;
}
-
template <class Solver>
-void TSatProof<Solver>::removedDfs(typename Solver::TLit lit, LitSet* removedSet, LitVector& removeStack, LitSet& inClause, LitSet& seen) {
+void TSatProof<Solver>::removedDfs(typename Solver::TLit lit,
+ LitSet* removedSet, LitVector& removeStack,
+ LitSet& inClause, LitSet& seen) {
// if we already added the literal return
if (seen.count(lit)) {
return;
@@ -604,20 +661,21 @@ void TSatProof<Solver>::removedDfs(typename Solver::TLit lit, LitSet* removedSet
}
int size = getClause(reason_ref).size();
- for (int i = 1; i < size; i++ ) {
+ for (int i = 1; i < size; i++) {
typename Solver::TLit v = getClause(reason_ref)[i];
- if(inClause.count(v) == 0 && seen.count(v) == 0) {
+ if (inClause.count(v) == 0 && seen.count(v) == 0) {
removedDfs(v, removedSet, removeStack, inClause, seen);
}
}
- if(seen.count(lit) == 0) {
+ if (seen.count(lit) == 0) {
seen.insert(lit);
removeStack.push_back(lit);
}
}
template <class Solver>
-void TSatProof<Solver>::removeRedundantFromRes(ResChain<Solver>* res, ClauseId id) {
+void TSatProof<Solver>::removeRedundantFromRes(ResChain<Solver>* res,
+ ClauseId id) {
LitSet* removed = res->getRedundant();
if (removed == NULL) {
return;
@@ -628,11 +686,12 @@ void TSatProof<Solver>::removeRedundantFromRes(ResChain<Solver>* res, ClauseId i
LitVector removeStack;
LitSet seen;
- for (typename LitSet::iterator it = removed->begin(); it != removed->end(); ++it) {
+ for (typename LitSet::iterator it = removed->begin(); it != removed->end();
+ ++it) {
removedDfs(*it, removed, removeStack, inClause, seen);
}
- for (int i = removeStack.size()-1; i >= 0; --i) {
+ for (int i = removeStack.size() - 1; i >= 0; --i) {
typename Solver::TLit lit = removeStack[i];
typename Solver::TCRef reason_ref = d_solver->reason(var(lit));
ClauseId reason_id;
@@ -655,41 +714,50 @@ void TSatProof<Solver>::registerResolution(ClauseId id, ResChain<Solver>* res) {
removeRedundantFromRes(res, id);
Assert(res->redundantRemoved());
- d_resChains[id] = res;
- if(Debug.isOn("proof:sat")) {
+ // Because the SAT solver can add the same clause multiple times, it
+ // could be the case that a resolution chain for this clause already
+ // exists (e.g. when removing units in addClause).
+ if (hasResolutionChain(id)) {
+ ResChain<Solver>* current = d_resolutionChains.find(id)->second;
+ delete current;
+ d_resolutionChains.erase(id);
+ }
+ Assert(!hasResolutionChain(id));
+
+ d_resolutionChains.insert(std::make_pair(id, res));
+ if (Debug.isOn("proof:sat")) {
printRes(id);
}
- if(d_checkRes) {
+ if (d_checkRes) {
Assert(checkResolution(id));
}
- PSTATS(
- d_statistics.d_resChainLengths << ((uint64_t)res->getSteps().size());
- d_statistics.d_avgChainLength.addEntry((uint64_t)res->getSteps().size());
- ++(d_statistics.d_numLearnedClauses);
- )
+ PSTATS(uint64_t resolutionSteps =
+ static_cast<uint64_t>(res.getSteps().size());
+ d_statistics.d_resChainLengths << resolutionSteps;
+ d_statistics.d_avgChainLength.addEntry(resolutionSteps);
+ ++(d_statistics.d_numLearnedClauses);)
}
-
/// recording resolutions
template <class Solver>
void TSatProof<Solver>::startResChain(typename Solver::TCRef start) {
- ClauseId id = getClauseId(start);
- ResChain<Solver>* res = new ResChain<Solver>(id);
+ ClauseId id = getClauseIdForCRef(start);
+ ResolutionChain* res = new ResolutionChain(id);
d_resStack.push_back(res);
}
template <class Solver>
void TSatProof<Solver>::startResChain(typename Solver::TLit start) {
ClauseId id = getUnitId(start);
- ResChain<Solver>* res = new ResChain<Solver>(id);
+ ResolutionChain* res = new ResolutionChain(id);
d_resStack.push_back(res);
}
-
template <class Solver>
void TSatProof<Solver>::addResolutionStep(typename Solver::TLit lit,
- typename Solver::TCRef clause, bool sign) {
+ typename Solver::TCRef clause,
+ bool sign) {
ClauseId id = registerClause(clause, LEARNT);
ResChain<Solver>* res = d_resStack.back();
res->addStep(lit, id, sign);
@@ -697,14 +765,13 @@ void TSatProof<Solver>::addResolutionStep(typename Solver::TLit lit,
template <class Solver>
void TSatProof<Solver>::endResChain(ClauseId id) {
- Debug("proof:sat:detailed") <<"endResChain " << id << "\n";
+ Debug("proof:sat:detailed") << "endResChain " << id << "\n";
Assert(d_resStack.size() > 0);
ResChain<Solver>* res = d_resStack.back();
registerResolution(id, res);
d_resStack.pop_back();
}
-
// template <class Solver>
// void TSatProof<Solver>::endResChain(typename Solver::TCRef clause) {
// Assert(d_resStack.size() > 0);
@@ -718,25 +785,25 @@ template <class Solver>
void TSatProof<Solver>::endResChain(typename Solver::TLit lit) {
Assert(d_resStack.size() > 0);
ClauseId id = registerUnitClause(lit, LEARNT);
- Debug("proof:sat:detailed") <<"endResChain unit " << id << "\n";
- ResChain<Solver>* res = d_resStack.back();
+ Debug("proof:sat:detailed") << "endResChain unit " << id << "\n";
+ ResolutionChain* res = d_resStack.back();
d_glueMap[id] = 1;
registerResolution(id, res);
d_resStack.pop_back();
}
-
template <class Solver>
void TSatProof<Solver>::cancelResChain() {
Assert(d_resStack.size() > 0);
+ ResolutionChain* back = d_resStack.back();
+ delete back;
d_resStack.pop_back();
}
-
template <class Solver>
void TSatProof<Solver>::storeLitRedundant(typename Solver::TLit lit) {
Assert(d_resStack.size() > 0);
- ResChain<Solver>* res = d_resStack.back();
+ ResolutionChain* res = d_resStack.back();
res->addRedundantLit(lit);
}
@@ -755,9 +822,9 @@ void TSatProof<Solver>::storeUnitResolution(typename Solver::TLit lit) {
template <class Solver>
ClauseId TSatProof<Solver>::resolveUnit(typename Solver::TLit lit) {
// first check if we already have a resolution for lit
- if(isUnit(lit)) {
- ClauseId id = getClauseId(lit);
- Assert(hasResolution(id) || isInputClause(id) || isLemmaClause(id));
+ if (isUnit(lit)) {
+ ClauseId id = getClauseIdForLiteral(lit);
+ Assert(hasResolutionChain(id) || isInputClause(id) || isLemmaClause(id));
return id;
}
typename Solver::TCRef reason_ref = d_solver->reason(var(lit));
@@ -768,12 +835,13 @@ ClauseId TSatProof<Solver>::resolveUnit(typename Solver::TLit lit) {
ResChain<Solver>* res = new ResChain<Solver>(reason_id);
// Here, the call to resolveUnit() can reallocate memory in the
// clause allocator. So reload reason ptr each time.
- typename Solver::TClause* reason = &getClause(reason_ref);
- for (int i = 0;
- i < reason->size();
- i++, reason = &getClause(reason_ref)) {
- typename Solver::TLit l = (*reason)[i];
- if(lit != l) {
+ const typename Solver::TClause& initial_reason = getClause(reason_ref);
+ size_t current_reason_size = initial_reason.size();
+ for (size_t i = 0; i < current_reason_size; i++) {
+ const typename Solver::TClause& current_reason = getClause(reason_ref);
+ current_reason_size = current_reason.size();
+ typename Solver::TLit l = current_reason[i];
+ if (lit != l) {
ClauseId res_id = resolveUnit(~l);
res->addStep(l, res_id, !sign(l));
}
@@ -787,16 +855,19 @@ void TSatProof<Solver>::toStream(std::ostream& out) {
Debug("proof:sat") << "TSatProof<Solver>::printProof\n";
Unimplemented("native proof printing not supported yet");
}
+
template <class Solver>
-ClauseId TSatProof<Solver>::storeUnitConflict(typename Solver::TLit conflict_lit,
- ClauseKind kind) {
+ClauseId TSatProof<Solver>::storeUnitConflict(
+ typename Solver::TLit conflict_lit, ClauseKind kind) {
Debug("cores") << "STORE UNIT CONFLICT" << std::endl;
Assert(!d_storedUnitConflict);
d_unitConflictId = registerUnitClause(conflict_lit, kind);
d_storedUnitConflict = true;
- Debug("proof:sat:detailed") <<"storeUnitConflict " << d_unitConflictId << "\n";
+ Debug("proof:sat:detailed") << "storeUnitConflict " << d_unitConflictId
+ << "\n";
return d_unitConflictId;
}
+
template <class Solver>
void TSatProof<Solver>::finalizeProof(typename Solver::TCRef conflict_ref) {
Assert(d_resStack.size() == 0);
@@ -816,10 +887,10 @@ void TSatProof<Solver>::finalizeProof(typename Solver::TCRef conflict_ref) {
return;
} else {
Assert(!d_storedUnitConflict);
- conflict_id = registerClause(conflict_ref, LEARNT); //FIXME
+ conflict_id = registerClause(conflict_ref, LEARNT); // FIXME
}
- if(Debug.isOn("proof:sat")) {
+ if (Debug.isOn("proof:sat")) {
Debug("proof:sat") << "proof::finalizeProof Final Conflict ";
print(conflict_id);
}
@@ -827,13 +898,13 @@ void TSatProof<Solver>::finalizeProof(typename Solver::TCRef conflict_ref) {
ResChain<Solver>* res = new ResChain<Solver>(conflict_id);
// Here, the call to resolveUnit() can reallocate memory in the
// clause allocator. So reload conflict ptr each time.
- typename Solver::TClause* conflict = &getClause(conflict_ref);
- for (int i = 0;
- i < conflict->size();
- ++i, conflict = &getClause(conflict_ref)) {
- typename Solver::TLit lit = (*conflict)[i];
+ size_t conflict_size = getClause(conflict_ref).size();
+ for (size_t i = 0; i < conflict_size; ++i) {
+ const typename Solver::TClause& conflict = getClause(conflict_ref);
+ typename Solver::TLit lit = conflict[i];
ClauseId res_id = resolveUnit(~lit);
res->addStep(lit, res_id, !sign(lit));
+ conflict_size = conflict.size();
}
registerResolution(d_emptyClauseId, res);
}
@@ -845,12 +916,13 @@ void TSatProof<Solver>::updateCRef(typename Solver::TCRef oldref,
if (d_clauseId.find(oldref) == d_clauseId.end()) {
return;
}
- ClauseId id = getClauseId(oldref);
+ ClauseId id = getClauseIdForCRef(oldref);
Assert(d_temp_clauseId.find(newref) == d_temp_clauseId.end());
Assert(d_temp_idClause.find(id) == d_temp_idClause.end());
d_temp_clauseId[newref] = id;
d_temp_idClause[id] = newref;
}
+
template <class Solver>
void TSatProof<Solver>::finishUpdateCRef() {
d_clauseId.swap(d_temp_clauseId);
@@ -859,10 +931,11 @@ void TSatProof<Solver>::finishUpdateCRef() {
d_idClause.swap(d_temp_idClause);
d_temp_idClause.clear();
}
+
template <class Solver>
void TSatProof<Solver>::markDeleted(typename Solver::TCRef clause) {
- if (d_clauseId.find(clause) != d_clauseId.end()) {
- ClauseId id = getClauseId(clause);
+ if (hasClauseIdForCRef(clause)) {
+ ClauseId id = getClauseIdForCRef(clause);
Assert(d_deleted.find(id) == d_deleted.end());
d_deleted.insert(id);
if (isLemmaClause(id)) {
@@ -875,14 +948,13 @@ void TSatProof<Solver>::markDeleted(typename Solver::TCRef clause) {
}
// template<>
-// void toSatClause< ::BVMinisat::Solver> (const BVMinisat::Solver::TClause& minisat_cl,
+// void toSatClause< ::BVMinisat::Solver> (const BVMinisat::Solver::TClause&
+// minisat_cl,
// prop::SatClause& sat_cl) {
// prop::BVMinisatSatSolver::toSatClause(minisat_cl, sat_cl);
// }
-
-
template <class Solver>
void TSatProof<Solver>::constructProof(ClauseId conflict) {
collectClauses(conflict);
@@ -894,11 +966,10 @@ std::string TSatProof<Solver>::clauseName(ClauseId id) {
if (isInputClause(id)) {
os << ProofManager::getInputClauseName(id, d_name);
return os.str();
- } else
- if (isLemmaClause(id)) {
+ } else if (isLemmaClause(id)) {
os << ProofManager::getLemmaClauseName(id, d_name);
return os.str();
- }else {
+ } else {
os << ProofManager::getLearntClauseName(id, d_name);
return os.str();
}
@@ -944,17 +1015,15 @@ void TSatProof<Solver>::collectClauses(ClauseId id) {
d_seenLearnt.insert(id);
}
- Assert(d_resChains.find(id) != d_resChains.end());
- ResChain<Solver>* res = d_resChains[id];
- PSTATS(
- d_statistics.d_usedResChainLengths << ((uint64_t)res->getSteps().size());
- d_statistics.d_usedClauseGlue << ((uint64_t) d_glueMap[id]);
- );
- ClauseId start = res->getStart();
+ const ResolutionChain& res = getResolutionChain(id);
+ const typename ResolutionChain::ResSteps& steps = res.getSteps();
+ PSTATS(d_statistics.d_usedResChainLengths
+ << ((uint64_t)steps.size());
+ d_statistics.d_usedClauseGlue << ((uint64_t)d_glueMap[id]););
+ ClauseId start = res.getStart();
collectClauses(start);
- typename ResChain<Solver>::ResSteps steps = res->getSteps();
- for(size_t i = 0; i < steps.size(); i++) {
+ for (size_t i = 0; i < steps.size(); i++) {
collectClauses(steps[i].id);
}
}
@@ -964,28 +1033,27 @@ void TSatProof<Solver>::collectClausesUsed(IdToSatClause& inputs,
IdToSatClause& lemmas) {
inputs = d_seenInputs;
lemmas = d_seenLemmas;
- PSTATS (
- d_statistics.d_numLearnedInProof.setData(d_seenLearnt.size());
- d_statistics.d_numLemmasInProof.setData(d_seenLemmas.size());
- );
+ PSTATS(d_statistics.d_numLearnedInProof.setData(d_seenLearnt.size());
+ d_statistics.d_numLemmasInProof.setData(d_seenLemmas.size()););
}
template <class Solver>
void TSatProof<Solver>::storeClauseGlue(ClauseId clause, int glue) {
- Assert (d_glueMap.find(clause) == d_glueMap.end());
+ Assert(d_glueMap.find(clause) == d_glueMap.end());
d_glueMap.insert(std::make_pair(clause, glue));
}
template <class Solver>
TSatProof<Solver>::Statistics::Statistics(const std::string& prefix)
- : d_numLearnedClauses("satproof::"+prefix+"::NumLearnedClauses", 0)
- , d_numLearnedInProof("satproof::"+prefix+"::NumLearnedInProof", 0)
- , d_numLemmasInProof("satproof::"+prefix+"::NumLemmasInProof", 0)
- , d_avgChainLength("satproof::"+prefix+"::AvgResChainLength")
- , d_resChainLengths("satproof::"+prefix+"::ResChainLengthsHist")
- , d_usedResChainLengths("satproof::"+prefix+"::UsedResChainLengthsHist")
- , d_clauseGlue("satproof::"+prefix+"::ClauseGlueHist")
- , d_usedClauseGlue("satproof::"+prefix+"::UsedClauseGlueHist") {
+ : d_numLearnedClauses("satproof::" + prefix + "::NumLearnedClauses", 0),
+ d_numLearnedInProof("satproof::" + prefix + "::NumLearnedInProof", 0),
+ d_numLemmasInProof("satproof::" + prefix + "::NumLemmasInProof", 0),
+ d_avgChainLength("satproof::" + prefix + "::AvgResChainLength"),
+ d_resChainLengths("satproof::" + prefix + "::ResChainLengthsHist"),
+ d_usedResChainLengths("satproof::" + prefix +
+ "::UsedResChainLengthsHist"),
+ d_clauseGlue("satproof::" + prefix + "::ClauseGlueHist"),
+ d_usedClauseGlue("satproof::" + prefix + "::UsedClauseGlueHist") {
smtStatisticsRegistry()->registerStat(&d_numLearnedClauses);
smtStatisticsRegistry()->registerStat(&d_numLearnedInProof);
smtStatisticsRegistry()->registerStat(&d_numLemmasInProof);
@@ -1008,73 +1076,78 @@ TSatProof<Solver>::Statistics::~Statistics() {
smtStatisticsRegistry()->unregisterStat(&d_usedClauseGlue);
}
-
/// LFSCSatProof class
template <class Solver>
-void LFSCSatProof<Solver>::printResolution(ClauseId id, std::ostream& out, std::ostream& paren) {
+void LFSCSatProof<Solver>::printResolution(ClauseId id, std::ostream& out,
+ std::ostream& paren) {
out << "(satlem_simplify _ _ _ ";
- ResChain<Solver>* res = this->d_resChains[id];
- typename ResChain<Solver>::ResSteps& steps = res->getSteps();
+ const ResChain<Solver>& res = this->getResolutionChain(id);
+ const typename ResChain<Solver>::ResSteps& steps = res.getSteps();
- for (int i = steps.size()-1; i >= 0; i--) {
+ for (int i = steps.size() - 1; i >= 0; i--) {
out << "(";
- out << (steps[i].sign? "R" : "Q") << " _ _ ";
+ out << (steps[i].sign ? "R" : "Q") << " _ _ ";
}
- ClauseId start_id = res->getStart();
+ ClauseId start_id = res.getStart();
out << this->clauseName(start_id) << " ";
- for(unsigned i = 0; i < steps.size(); i++) {
- prop::SatVariable v = prop::MinisatSatSolver::toSatVariable(var(steps[i].lit));
- out << this->clauseName(steps[i].id) << " "<<ProofManager::getVarName(v, this->d_name) <<")";
+ for (unsigned i = 0; i < steps.size(); i++) {
+ prop::SatVariable v =
+ prop::MinisatSatSolver::toSatVariable(var(steps[i].lit));
+ out << this->clauseName(steps[i].id) << " "
+ << ProofManager::getVarName(v, this->d_name) << ")";
}
if (id == this->d_emptyClauseId) {
- out <<"(\\empty empty)";
+ out <<"(\\ empty empty)";
return;
}
- out << "(\\" << this->clauseName(id) << "\n"; // bind to lemma name
+ out << "(\\ " << this->clauseName(id) << "\n"; // bind to lemma name
paren << "))"; // closing parethesis for lemma binding and satlem
}
/// LFSCSatProof class
template <class Solver>
-void LFSCSatProof<Solver>::printAssumptionsResolution(ClauseId id, std::ostream& out, std::ostream& paren) {
- Assert (this->isAssumptionConflict(id));
+void LFSCSatProof<Solver>::printAssumptionsResolution(ClauseId id,
+ std::ostream& out,
+ std::ostream& paren) {
+ Assert(this->isAssumptionConflict(id));
// print the resolution proving the assumption conflict
printResolution(id, out, paren);
// resolve out assumptions to prove empty clause
out << "(satlem_simplify _ _ _ ";
- std::vector<typename Solver::TLit>& confl = *(this->d_assumptionConflictsDebug[id]);
+ std::vector<typename Solver::TLit>& confl =
+ *(this->d_assumptionConflictsDebug[id]);
- Assert (confl.size());
+ Assert(confl.size());
for (unsigned i = 0; i < confl.size(); ++i) {
prop::SatLiteral lit = toSatLiteral<Solver>(confl[i]);
- out <<"(";
- out << (lit.isNegated() ? "Q" : "R") <<" _ _ ";
+ out << "(";
+ out << (lit.isNegated() ? "Q" : "R") << " _ _ ";
}
- out << this->clauseName(id)<< " ";
+ out << this->clauseName(id) << " ";
for (int i = confl.size() - 1; i >= 0; --i) {
prop::SatLiteral lit = toSatLiteral<Solver>(confl[i]);
prop::SatVariable v = lit.getSatVariable();
- out << "unit"<< v <<" ";
- out << ProofManager::getVarName(v, this->d_name) <<")";
+ out << "unit" << v << " ";
+ out << ProofManager::getVarName(v, this->d_name) << ")";
}
- out <<"(\\ e e)\n";
- paren <<")";
+ out << "(\\ e e)\n";
+ paren << ")";
}
-
template <class Solver>
-void LFSCSatProof<Solver>::printResolutions(std::ostream& out, std::ostream& paren) {
+void LFSCSatProof<Solver>::printResolutions(std::ostream& out,
+ std::ostream& paren) {
Debug("bv-proof") << "; print resolutions" << std::endl;
std::set<ClauseId>::iterator it = this->d_seenLearnt.begin();
- for(; it!= this->d_seenLearnt.end(); ++it) {
- if(*it != this->d_emptyClauseId) {
+ for (; it != this->d_seenLearnt.end(); ++it) {
+ if (*it != this->d_emptyClauseId) {
Debug("bv-proof") << "; print resolution for " << *it << std::endl;
printResolution(*it, out, paren);
}
@@ -1083,29 +1156,29 @@ void LFSCSatProof<Solver>::printResolutions(std::ostream& out, std::ostream& par
}
template <class Solver>
-void LFSCSatProof<Solver>::printResolutionEmptyClause(std::ostream& out, std::ostream& paren) {
+void LFSCSatProof<Solver>::printResolutionEmptyClause(std::ostream& out,
+ std::ostream& paren) {
printResolution(this->d_emptyClauseId, out, paren);
}
-
inline std::ostream& operator<<(std::ostream& out, CVC4::ClauseKind k) {
- switch(k) {
- case CVC4::INPUT:
- out << "INPUT";
- break;
- case CVC4::THEORY_LEMMA:
- out << "THEORY_LEMMA";
- break;
- case CVC4::LEARNT:
- out << "LEARNT";
- break;
- default:
- out << "ClauseKind Unknown! [" << unsigned(k) << "]";
+ switch (k) {
+ case CVC4::INPUT:
+ out << "INPUT";
+ break;
+ case CVC4::THEORY_LEMMA:
+ out << "THEORY_LEMMA";
+ break;
+ case CVC4::LEARNT:
+ out << "LEARNT";
+ break;
+ default:
+ out << "ClauseKind Unknown! [" << unsigned(k) << "]";
}
return out;
}
-}/* CVC4 namespace */
+} /* CVC4 namespace */
#endif /* __CVC4__SAT__PROOF_IMPLEMENTATION_H */
diff --git a/src/proof/skolemization_manager.h b/src/proof/skolemization_manager.h
index de510e514..b026e21c2 100644
--- a/src/proof/skolemization_manager.h
+++ b/src/proof/skolemization_manager.h
@@ -37,7 +37,6 @@ public:
Node getSkolem(Node disequality);
Node getDisequality(Node skolem);
bool isSkolem(Node skolem);
-
void clear();
std::hash_map<Node, Node, NodeHashFunction>::const_iterator begin();
diff --git a/src/proof/theory_proof.cpp b/src/proof/theory_proof.cpp
index 088275b3f..d12b561a6 100644
--- a/src/proof/theory_proof.cpp
+++ b/src/proof/theory_proof.cpp
@@ -19,12 +19,14 @@
#include "base/cvc4_assert.h"
#include "context/context.h"
#include "options/bv_options.h"
+#include "options/proof_options.h"
#include "proof/arith_proof.h"
#include "proof/array_proof.h"
#include "proof/bitvector_proof.h"
#include "proof/clause_id.h"
#include "proof/cnf_proof.h"
#include "proof/proof_manager.h"
+#include "proof/proof_output_channel.h"
#include "proof/proof_utils.h"
#include "proof/sat_proof.h"
#include "proof/uf_proof.h"
@@ -45,77 +47,9 @@
namespace CVC4 {
-unsigned CVC4::LetCount::counter = 0;
+unsigned CVC4::ProofLetCount::counter = 0;
static unsigned LET_COUNT = 1;
-//for proof replay
-class ProofOutputChannel : public theory::OutputChannel {
-public:
- Node d_conflict;
- Proof* d_proof;
- Node d_lemma;
-
- ProofOutputChannel() : d_conflict(), d_proof(NULL) {}
- virtual ~ProofOutputChannel() throw() {}
-
- void conflict(TNode n, Proof* pf) throw() {
- Trace("theory-proof-debug") << "; CONFLICT: " << n << std::endl;
- Assert(d_conflict.isNull());
- Assert(!n.isNull());
- d_conflict = n;
- Assert(pf != NULL);
- d_proof = pf;
- }
- bool propagate(TNode x) throw() {
- Trace("theory-proof-debug") << "got a propagation: " << x << std::endl;
- return true;
- }
- theory::LemmaStatus lemma(TNode n, ProofRule rule, bool, bool, bool) throw() {
- Trace("theory-proof-debug") << "new lemma: " << n << std::endl;
- d_lemma = n;
- return theory::LemmaStatus(TNode::null(), 0);
- }
- theory::LemmaStatus splitLemma(TNode, bool) throw() {
- AlwaysAssert(false);
- return theory::LemmaStatus(TNode::null(), 0);
- }
- void requirePhase(TNode n, bool b) throw() {
- Debug("theory-proof-debug") << "ProofOutputChannel::requirePhase called" << std::endl;
- Trace("theory-proof-debug") << "requirePhase " << n << " " << b << std::endl;
- }
- bool flipDecision() throw() {
- Debug("theory-proof-debug") << "ProofOutputChannel::flipDecision called" << std::endl;
- AlwaysAssert(false);
- return false;
- }
- void setIncomplete() throw() {
- Debug("theory-proof-debug") << "ProofOutputChannel::setIncomplete called" << std::endl;
- AlwaysAssert(false);
- }
-};/* class ProofOutputChannel */
-
-//for proof replay
-class MyPreRegisterVisitor {
- theory::Theory* d_theory;
- __gnu_cxx::hash_set<TNode, TNodeHashFunction> d_visited;
-public:
- typedef void return_type;
- MyPreRegisterVisitor(theory::Theory* theory)
- : d_theory(theory)
- , d_visited()
- {}
- bool alreadyVisited(TNode current, TNode parent) { return d_visited.find(current) != d_visited.end(); }
- void visit(TNode current, TNode parent) {
- if(theory::Theory::theoryOf(current) == d_theory->getId()) {
- //Trace("theory-proof-debug") << "preregister " << current << std::endl;
- d_theory->preRegisterTerm(current);
- d_visited.insert(current);
- }
- }
- void start(TNode node) { }
- void done(TNode node) { }
-}; /* class MyPreRegisterVisitor */
-
TheoryProofEngine::TheoryProofEngine()
: d_registrationCache()
, d_theoryProofTable()
@@ -131,13 +65,12 @@ TheoryProofEngine::~TheoryProofEngine() {
}
}
-
void TheoryProofEngine::registerTheory(theory::Theory* th) {
- if( th ){
+ if (th) {
theory::TheoryId id = th->getId();
if(d_theoryProofTable.find(id) == d_theoryProofTable.end()) {
- Trace("theory-proof-debug") << "; register theory " << id << std::endl;
+ Trace("pf::tp") << "TheoryProofEngine::registerTheory: " << id << std::endl;
if (id == theory::THEORY_UF) {
d_theoryProofTable[id] = new LFSCUFProof((theory::uf::TheoryUF*)th, this);
@@ -147,7 +80,6 @@ void TheoryProofEngine::registerTheory(theory::Theory* th) {
if (id == theory::THEORY_BV) {
BitVectorProof * bvp = new LFSCBitVectorProof((theory::bv::TheoryBV*)th, this);
d_theoryProofTable[id] = bvp;
- ((theory::bv::TheoryBV*)th)->setProofLog( bvp );
return;
}
@@ -166,20 +98,54 @@ void TheoryProofEngine::registerTheory(theory::Theory* th) {
}
}
+void TheoryProofEngine::finishRegisterTheory(theory::Theory* th) {
+ if (th) {
+ theory::TheoryId id = th->getId();
+ if (id == theory::THEORY_BV) {
+ Assert(d_theoryProofTable.find(id) != d_theoryProofTable.end());
+
+ BitVectorProof *bvp = (BitVectorProof *)d_theoryProofTable[id];
+ ((theory::bv::TheoryBV*)th)->setProofLog( bvp );
+ return;
+ }
+ }
+}
+
TheoryProof* TheoryProofEngine::getTheoryProof(theory::TheoryId id) {
+ // The UF theory handles queries for the Builtin theory.
+ if (id == theory::THEORY_BUILTIN) {
+ Debug("pf::tp") << "TheoryProofEngine::getTheoryProof: BUILTIN --> UF" << std::endl;
+ id = theory::THEORY_UF;
+ }
+
Assert (d_theoryProofTable.find(id) != d_theoryProofTable.end());
return d_theoryProofTable[id];
}
+void TheoryProofEngine::markTermForFutureRegistration(Expr term, theory::TheoryId id) {
+ d_exprToTheoryIds[term].insert(id);
+}
+
+void TheoryProofEngine::printConstantDisequalityProof(std::ostream& os, Expr c1, Expr c2) {
+ Assert(c1.isConst());
+ Assert(c2.isConst());
+
+ Assert(theory::Theory::theoryOf(c1) == theory::Theory::theoryOf(c2));
+ getTheoryProof(theory::Theory::theoryOf(c1))->printConstantDisequalityProof(os, c1, c2);
+}
+
void TheoryProofEngine::registerTerm(Expr term) {
+ Debug("pf::tp") << "TheoryProofEngine::registerTerm: registering term: " << term << std::endl;
+
if (d_registrationCache.count(term)) {
return;
}
- Debug("pf::tp") << "TheoryProofEngine::registerTerm: registering new term: " << term << std::endl;
+
+ Debug("pf::tp") << "TheoryProofEngine::registerTerm: registering NEW term: " << term << std::endl;
theory::TheoryId theory_id = theory::Theory::theoryOf(term);
- Debug("pf::tp") << "Term's theory: " << theory_id << std::endl;
+ Debug("pf::tp") << "Term's theory( " << term << " ) = " << theory_id << std::endl;
// don't need to register boolean terms
if (theory_id == theory::THEORY_BUILTIN ||
@@ -193,58 +159,64 @@ void TheoryProofEngine::registerTerm(Expr term) {
if (!supportedTheory(theory_id)) return;
+ // Register the term with its owner theory
getTheoryProof(theory_id)->registerTerm(term);
+
+ // A special case: the array theory needs to know of every skolem, even if
+ // it belongs to another theory (e.g., a BV skolem)
+ if (ProofManager::getSkolemizationManager()->isSkolem(term) && theory_id != theory::THEORY_ARRAY) {
+ Debug("pf::tp") << "TheoryProofEngine::registerTerm: Special case: registering a non-array skolem: " << term << std::endl;
+ getTheoryProof(theory::THEORY_ARRAY)->registerTerm(term);
+ }
+
d_registrationCache.insert(term);
}
-theory::TheoryId TheoryProofEngine::getTheoryForLemma(ClauseId id) {
+theory::TheoryId TheoryProofEngine::getTheoryForLemma(const prop::SatClause* clause) {
ProofManager* pm = ProofManager::currentPM();
- Debug("pf::tp") << "TheoryProofEngine::getTheoryForLemma( " << id << " )"
- << " = " << pm->getCnfProof()->getOwnerTheory(id) << std::endl;
+ std::set<Node> nodes;
+ for(unsigned i = 0; i < clause->size(); ++i) {
+ prop::SatLiteral lit = (*clause)[i];
+ Node node = pm->getCnfProof()->getAtom(lit.getSatVariable());
+ Expr atom = node.toExpr();
+ if (atom.isConst()) {
+ Assert (atom == utils::mkTrue());
+ continue;
+ }
- if ((pm->getLogic() == "QF_UFLIA") || (pm->getLogic() == "QF_UFLRA")) {
- Debug("pf::tp") << "TheoryProofEngine::getTheoryForLemma: special hack for Arithmetic-with-holes support. "
- << "Returning THEORY_ARITH" << std::endl;
- return theory::THEORY_ARITH;
+ nodes.insert(lit.isNegated() ? node.notNode() : node);
}
- return pm->getCnfProof()->getOwnerTheory(id);
-
- // if (pm->getLogic() == "QF_UF") return theory::THEORY_UF;
- // if (pm->getLogic() == "QF_BV") return theory::THEORY_BV;
- // if (pm->getLogic() == "QF_AX") return theory::THEORY_ARRAY;
- // if (pm->getLogic() == "ALL_SUPPORTED") return theory::THEORY_BV;
-
- // Debug("pf::tp") << "Unsupported logic (" << pm->getLogic() << ")" << std::endl;
-
- // Unreachable();
+ // Ensure that the lemma is in the database.
+ Assert (pm->getCnfProof()->haveProofRecipe(nodes));
+ return pm->getCnfProof()->getProofRecipe(nodes).getTheory();
}
-void LFSCTheoryProofEngine::bind(Expr term, LetMap& map, Bindings& let_order) {
- LetMap::iterator it = map.find(term);
+void LFSCTheoryProofEngine::bind(Expr term, ProofLetMap& map, Bindings& let_order) {
+ ProofLetMap::iterator it = map.find(term);
if (it != map.end()) {
- LetCount& count = it->second;
+ ProofLetCount& count = it->second;
count.increment();
return;
}
for (unsigned i = 0; i < term.getNumChildren(); ++i) {
bind(term[i], map, let_order);
}
- unsigned new_id = LetCount::newId();
- map[term] = LetCount(new_id);
+ unsigned new_id = ProofLetCount::newId();
+ map[term] = ProofLetCount(new_id);
let_order.push_back(LetOrderElement(term, new_id));
}
void LFSCTheoryProofEngine::printLetTerm(Expr term, std::ostream& os) {
- LetMap map;
+ ProofLetMap map;
Bindings let_order;
bind(term, map, let_order);
std::ostringstream paren;
for (unsigned i = 0; i < let_order.size(); ++i) {
Expr current_expr = let_order[i].expr;
unsigned let_id = let_order[i].id;
- LetMap::const_iterator it = map.find(current_expr);
+ ProofLetMap::const_iterator it = map.find(current_expr);
Assert (it != map.end());
unsigned let_count = it->second.count;
Assert(let_count);
@@ -253,7 +225,7 @@ void LFSCTheoryProofEngine::printLetTerm(Expr term, std::ostream& os) {
continue;
}
- os << "(@ let"<<let_id << " ";
+ os << "(@ let" <<let_id << " ";
printTheoryTerm(current_expr, os, map);
paren <<")";
}
@@ -264,16 +236,13 @@ void LFSCTheoryProofEngine::printLetTerm(Expr term, std::ostream& os) {
printTheoryTerm(last, os, map);
}
else {
- os << " let"<< last_let_id;
+ os << " let" << last_let_id;
}
os << paren.str();
}
-
-void LFSCTheoryProofEngine::printTheoryTerm(Expr term, std::ostream& os, const LetMap& map) {
+void LFSCTheoryProofEngine::printTheoryTerm(Expr term, std::ostream& os, const ProofLetMap& map) {
theory::TheoryId theory_id = theory::Theory::theoryOf(term);
- Debug("pf::tp") << std::endl << "LFSCTheoryProofEngine::printTheoryTerm: term = " << term
- << ", theory_id = " << theory_id << std::endl;
// boolean terms and ITEs are special because they
// are common to all theories
@@ -315,6 +284,29 @@ void LFSCTheoryProofEngine::printSort(Type type, std::ostream& os) {
Unreachable();
}
+void LFSCTheoryProofEngine::performExtraRegistrations() {
+ ExprToTheoryIds::const_iterator it;
+ for (it = d_exprToTheoryIds.begin(); it != d_exprToTheoryIds.end(); ++it) {
+ if (d_registrationCache.count(it->first)) { // Only register if the term appeared
+ TheoryIdSet::const_iterator theoryIt;
+ for (theoryIt = it->second.begin(); theoryIt != it->second.end(); ++theoryIt) {
+ Debug("pf::tp") << "\tExtra registration of term " << it->first
+ << " with theory: " << *theoryIt << std::endl;
+ Assert(supportedTheory(*theoryIt));
+ getTheoryProof(*theoryIt)->registerTerm(it->first);
+ }
+ }
+ }
+}
+
+void LFSCTheoryProofEngine::treatBoolsAsFormulas(bool value) {
+ TheoryProofTable::const_iterator it = d_theoryProofTable.begin();
+ TheoryProofTable::const_iterator end = d_theoryProofTable.end();
+ for (; it != end; ++it) {
+ it->second->treatBoolsAsFormulas(value);
+ }
+}
+
void LFSCTheoryProofEngine::registerTermsFromAssertions() {
ProofManager::assertions_iterator it = ProofManager::currentPM()->begin_assertions();
ProofManager::assertions_iterator end = ProofManager::currentPM()->end_assertions();
@@ -322,6 +314,8 @@ void LFSCTheoryProofEngine::registerTermsFromAssertions() {
for(; it != end; ++it) {
registerTerm(*it);
}
+
+ performExtraRegistrations();
}
void LFSCTheoryProofEngine::printAssertions(std::ostream& os, std::ostream& paren) {
@@ -333,17 +327,51 @@ void LFSCTheoryProofEngine::printAssertions(std::ostream& os, std::ostream& pare
for (; it != end; ++it) {
Debug("pf::tp") << "printAssertions: assertion is: " << *it << std::endl;
- // FIXME: merge this with counter
- os << "(% A" << counter++ << " (th_holds ";
- printLetTerm(*it, os);
+ std::ostringstream name;
+ name << "A" << counter++;
+ os << "(% " << name.str() << " (th_holds ";
+
+ // Assertions appear before the global let map, so we use a dummpMap to avoid letification here.
+ ProofLetMap dummyMap;
+ printBoundTerm(*it, os, dummyMap);
+
os << ")\n";
paren << ")";
}
- //store map between assertion and counter
- // ProofManager::currentPM()->setAssertion( *it );
+
Debug("pf::tp") << "LFSCTheoryProofEngine::printAssertions done" << std::endl << std::endl;
}
+void LFSCTheoryProofEngine::printLemmaRewrites(NodePairSet& rewrites,
+ std::ostream& os,
+ std::ostream& paren) {
+ Debug("pf::tp") << "LFSCTheoryProofEngine::printLemmaRewrites called" << std::endl << std::endl;
+
+ NodePairSet::const_iterator it;
+
+ for (it = rewrites.begin(); it != rewrites.end(); ++it) {
+ Debug("pf::tp") << "printLemmaRewrites: " << it->first << " --> " << it->second << std::endl;
+
+ Node n1 = it->first;
+ Node n2 = it->second;
+ Assert(n1.toExpr() == utils::mkFalse() ||
+ theory::Theory::theoryOf(n1) == theory::Theory::theoryOf(n2));
+
+ std::ostringstream rewriteRule;
+ rewriteRule << ".lrr" << d_assertionToRewrite.size();
+
+ os << "(th_let_pf _ ";
+ getTheoryProof(theory::Theory::theoryOf(n1))->printRewriteProof(os, n1, n2);
+ os << "(\\ " << rewriteRule.str() << "\n";
+
+ d_assertionToRewrite[it->first] = rewriteRule.str();
+ Debug("pf::tp") << "d_assertionToRewrite[" << it->first << "] = " << rewriteRule.str() << std::endl;
+ paren << "))";
+ }
+
+ Debug("pf::tp") << "LFSCTheoryProofEngine::printLemmaRewrites done" << std::endl << std::endl;
+}
+
void LFSCTheoryProofEngine::printSortDeclarations(std::ostream& os, std::ostream& paren) {
Debug("pf::tp") << "LFSCTheoryProofEngine::printSortDeclarations called" << std::endl << std::endl;
@@ -378,55 +406,150 @@ void LFSCTheoryProofEngine::printDeferredDeclarations(std::ostream& os, std::ost
}
}
-void LFSCTheoryProofEngine::printTheoryLemmas(const IdToSatClause& lemmas,
- std::ostream& os,
- std::ostream& paren) {
- os << " ;; Theory Lemmas \n";
- ProofManager* pm = ProofManager::currentPM();
- IdToSatClause::const_iterator it = lemmas.begin();
- IdToSatClause::const_iterator end = lemmas.end();
-
- Debug("pf::tp") << "LFSCTheoryProofEngine::printTheoryLemmas: checking lemma owners..." << std::endl;
+void LFSCTheoryProofEngine::printAliasingDeclarations(std::ostream& os, std::ostream& paren) {
+ Debug("pf::tp") << "LFSCTheoryProofEngine::printAliasingDeclarations called" << std::endl;
+ TheoryProofTable::const_iterator it = d_theoryProofTable.begin();
+ TheoryProofTable::const_iterator end = d_theoryProofTable.end();
for (; it != end; ++it) {
- Debug("pf::tp") << "LFSCTheoryProofEngine::printTheoryLemmas: new lemma" << std::endl;
- ClauseId id = it->first;
- Debug("pf::tp") << "\tLemma = " << id
- << ". Owner theory: " << pm->getCnfProof()->getOwnerTheory(id) << std::endl;
+ it->second->printAliasingDeclarations(os, paren);
}
- it = lemmas.begin();
+}
- // BitVector theory is special case: must know all
- // conflicts needed ahead of time for resolution
- // proof lemmas
- std::vector<Expr> bv_lemmas;
- for (; it != end; ++it) {
+void LFSCTheoryProofEngine::dumpTheoryLemmas(const IdToSatClause& lemmas) {
+ Debug("pf::dumpLemmas") << "Dumping ALL theory lemmas" << std::endl << std::endl;
+
+ ProofManager* pm = ProofManager::currentPM();
+ for (IdToSatClause::const_iterator it = lemmas.begin(); it != lemmas.end(); ++it) {
ClauseId id = it->first;
+ Debug("pf::dumpLemmas") << "**** \tLemma ID = " << id << std::endl;
const prop::SatClause* clause = it->second;
+ std::set<Node> nodes;
+ for(unsigned i = 0; i < clause->size(); ++i) {
+ prop::SatLiteral lit = (*clause)[i];
+ Node node = pm->getCnfProof()->getAtom(lit.getSatVariable());
+ if (node.isConst()) {
+ Assert (node.toExpr() == utils::mkTrue());
+ continue;
+ }
+ nodes.insert(lit.isNegated() ? node.notNode() : node);
+ }
+
+ LemmaProofRecipe recipe = pm->getCnfProof()->getProofRecipe(nodes);
+ recipe.dump("pf::dumpLemmas");
+ }
+
+ Debug("pf::dumpLemmas") << "Theory lemma printing DONE" << std::endl << std::endl;
+}
- theory::TheoryId theory_id = getTheoryForLemma(id);
- if (theory_id != theory::THEORY_BV) continue;
+// TODO: this function should be moved into the BV prover.
+void LFSCTheoryProofEngine::finalizeBvConflicts(const IdToSatClause& lemmas, std::ostream& os) {
+ // BitVector theory is special case: must know all conflicts needed
+ // ahead of time for resolution proof lemmas
+ std::vector<Expr> bv_lemmas;
+
+ for (IdToSatClause::const_iterator it = lemmas.begin(); it != lemmas.end(); ++it) {
+ const prop::SatClause* clause = it->second;
std::vector<Expr> conflict;
+ std::set<Node> conflictNodes;
for(unsigned i = 0; i < clause->size(); ++i) {
prop::SatLiteral lit = (*clause)[i];
- Expr atom = pm->getCnfProof()->getAtom(lit.getSatVariable()).toExpr();
+ Node node = ProofManager::currentPM()->getCnfProof()->getAtom(lit.getSatVariable());
+ Expr atom = node.toExpr();
+
+ // The literals (true) and (not false) are omitted from conflicts
if (atom.isConst()) {
Assert (atom == utils::mkTrue() ||
(atom == utils::mkFalse() && lit.isNegated()));
continue;
}
+
Expr expr_lit = lit.isNegated() ? atom.notExpr() : atom;
conflict.push_back(expr_lit);
+ conflictNodes.insert(lit.isNegated() ? node.notNode() : node);
+ }
+
+ LemmaProofRecipe recipe = ProofManager::currentPM()->getCnfProof()->getProofRecipe(conflictNodes);
+
+ unsigned numberOfSteps = recipe.getNumSteps();
+
+ prop::SatClause currentClause = *clause;
+ std::vector<Expr> currentClauseExpr = conflict;
+
+ for (unsigned i = 0; i < numberOfSteps; ++i) {
+ const LemmaProofRecipe::ProofStep* currentStep = recipe.getStep(i);
+
+ if (currentStep->getTheory() != theory::THEORY_BV) {
+ continue;
+ }
+
+ // If any rewrites took place, we need to update the conflict clause accordingly
+ std::set<Node> missingAssertions = recipe.getMissingAssertionsForStep(i);
+ std::map<Node, Node> explanationToMissingAssertion;
+ std::set<Node>::iterator assertionIt;
+ for (assertionIt = missingAssertions.begin();
+ assertionIt != missingAssertions.end();
+ ++assertionIt) {
+ Node negated = (*assertionIt).negate();
+ explanationToMissingAssertion[recipe.getExplanation(negated)] = negated;
+ }
+
+ currentClause = *clause;
+ currentClauseExpr = conflict;
+
+ for (unsigned j = 0; j < i; ++j) {
+ // Literals already used in previous steps need to be negated
+ Node previousLiteralNode = recipe.getStep(j)->getLiteral();
+
+ // If this literal is the result of a rewrite, we need to translate it
+ if (explanationToMissingAssertion.find(previousLiteralNode) !=
+ explanationToMissingAssertion.end()) {
+ previousLiteralNode = explanationToMissingAssertion[previousLiteralNode];
+ }
+
+ Node previousLiteralNodeNegated = previousLiteralNode.negate();
+ prop::SatLiteral previousLiteralNegated =
+ ProofManager::currentPM()->getCnfProof()->getLiteral(previousLiteralNodeNegated);
+
+ currentClause.push_back(previousLiteralNegated);
+ currentClauseExpr.push_back(previousLiteralNodeNegated.toExpr());
+ }
+
+ // If we're in the final step, the last literal is Null and should not be added.
+ // Otherwise, the current literal does NOT need to be negated
+ Node currentLiteralNode = currentStep->getLiteral();
+
+ if (currentLiteralNode != Node()) {
+ prop::SatLiteral currentLiteral =
+ ProofManager::currentPM()->getCnfProof()->getLiteral(currentLiteralNode);
+
+ currentClause.push_back(currentLiteral);
+ currentClauseExpr.push_back(currentLiteralNode.toExpr());
+ }
+
+ bv_lemmas.push_back(utils::mkSortedExpr(kind::OR, currentClauseExpr));
}
- bv_lemmas.push_back(utils::mkSortedExpr(kind::OR, conflict));
}
- // FIXME: ugly, move into bit-vector proof by adding lemma
- // queue inside each theory_proof
+
BitVectorProof* bv = ProofManager::getBitVectorProof();
bv->finalizeConflicts(bv_lemmas);
+ // bv->printResolutionProof(os, paren, letMap);
+}
- bv->printResolutionProof(os, paren);
+void LFSCTheoryProofEngine::printTheoryLemmas(const IdToSatClause& lemmas,
+ std::ostream& os,
+ std::ostream& paren,
+ ProofLetMap& map) {
+ os << " ;; Theory Lemmas \n";
+ Debug("pf::tp") << "LFSCTheoryProofEngine::printTheoryLemmas: starting" << std::endl;
+
+ if (Debug.isOn("pf::dumpLemmas")) {
+ dumpTheoryLemmas(lemmas);
+ }
+
+ // finalizeBvConflicts(lemmas, os, paren, map);
+ ProofManager::getBitVectorProof()->printResolutionProof(os, paren, map);
if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
Assert (lemmas.size() == 1);
@@ -434,61 +557,255 @@ void LFSCTheoryProofEngine::printTheoryLemmas(const IdToSatClause& lemmas,
return;
}
- it = lemmas.begin();
-
+ ProofManager* pm = ProofManager::currentPM();
Debug("pf::tp") << "LFSCTheoryProofEngine::printTheoryLemmas: printing lemmas..." << std::endl;
- for (; it != end; ++it) {
- Debug("pf::tp") << "LFSCTheoryProofEngine::printTheoryLemmas: printing a new lemma!" << std::endl;
-
- // Debug("pf::tp") << "\tLemma = " << it->first << ", " << *(it->second) << std::endl;
+ for (IdToSatClause::const_iterator it = lemmas.begin(); it != lemmas.end(); ++it) {
ClauseId id = it->first;
- Debug("pf::tp") << "Owner theory:" << pm->getCnfProof()->getOwnerTheory(id) << std::endl;
const prop::SatClause* clause = it->second;
- // printing clause as it appears in resolution proof
- os << "(satlem _ _ ";
- std::ostringstream clause_paren;
- Debug("pf::tp") << "CnfProof printing clause..." << std::endl;
- pm->getCnfProof()->printClause(*clause, os, clause_paren);
- Debug("pf::tp") << "CnfProof printing clause - Done!" << std::endl;
+ Debug("pf::tp") << "LFSCTheoryProofEngine::printTheoryLemmas: printing lemma. ID = "
+ << id << std::endl;
std::vector<Expr> clause_expr;
+ std::set<Node> clause_expr_nodes;
for(unsigned i = 0; i < clause->size(); ++i) {
prop::SatLiteral lit = (*clause)[i];
- Expr atom = pm->getCnfProof()->getAtom(lit.getSatVariable()).toExpr();
+ Node node = pm->getCnfProof()->getAtom(lit.getSatVariable());
+ Expr atom = node.toExpr();
if (atom.isConst()) {
Assert (atom == utils::mkTrue());
continue;
}
Expr expr_lit = lit.isNegated() ? atom.notExpr(): atom;
clause_expr.push_back(expr_lit);
+ clause_expr_nodes.insert(lit.isNegated() ? node.notNode() : node);
}
- Debug("pf::tp") << "Expression printing done!" << std::endl;
-
- // query appropriate theory for proof of clause
- theory::TheoryId theory_id = getTheoryForLemma(id);
- Debug("pf::tp") << "Get theory lemma from " << theory_id << "..." << std::endl;
- Debug("theory-proof-debug") << ";; Get theory lemma from " << theory_id << "..." << std::endl;
- getTheoryProof(theory_id)->printTheoryLemmaProof(clause_expr, os, paren);
- Debug("pf::tp") << "Get theory lemma from " << theory_id << "... DONE!" << std::endl;
- // os << " (clausify_false trust)";
- os << clause_paren.str();
- os << "( \\ " << pm->getLemmaClauseName(id) <<"\n";
- paren << "))";
+ LemmaProofRecipe recipe = pm->getCnfProof()->getProofRecipe(clause_expr_nodes);
+
+ if (recipe.simpleLemma()) {
+ // In a simple lemma, there will be no propositional resolution in the end
+
+ Debug("pf::tp") << "Simple lemma" << std::endl;
+ // Printing the clause as it appears in resolution proof
+ os << "(satlem _ _ ";
+ std::ostringstream clause_paren;
+ pm->getCnfProof()->printClause(*clause, os, clause_paren);
+
+ // Find and handle missing assertions, due to rewrites
+ std::set<Node> missingAssertions = recipe.getMissingAssertionsForStep(0);
+ if (!missingAssertions.empty()) {
+ Debug("pf::tp") << "Have missing assertions for this simple lemma!" << std::endl;
+ }
+
+ std::set<Node>::const_iterator missingAssertion;
+ for (missingAssertion = missingAssertions.begin();
+ missingAssertion != missingAssertions.end();
+ ++missingAssertion) {
+
+ Debug("pf::tp") << "Working on missing assertion: " << *missingAssertion << std::endl;
+ Assert(recipe.wasRewritten(missingAssertion->negate()));
+ Node explanation = recipe.getExplanation(missingAssertion->negate()).negate();
+ Debug("pf::tp") << "Found explanation: " << explanation << std::endl;
+
+ // We have a missing assertion.
+ // rewriteIt->first is the assertion after the rewrite (the explanation),
+ // rewriteIt->second is the original assertion that needs to be fed into the theory.
+
+ bool found = false;
+ unsigned k;
+ for (k = 0; k < clause_expr.size(); ++k) {
+ if (clause_expr[k] == explanation.toExpr()) {
+ found = true;
+ break;
+ }
+ }
+
+ AlwaysAssert(found);
+ Debug("pf::tp") << "Replacing theory assertion "
+ << clause_expr[k]
+ << " with "
+ << *missingAssertion
+ << std::endl;
+
+ clause_expr[k] = missingAssertion->toExpr();
+
+ std::ostringstream rewritten;
+ rewritten << "(or_elim_1 _ _ ";
+ rewritten << "(not_not_intro _ ";
+ rewritten << pm->getLitName(explanation);
+ rewritten << ") (iff_elim_1 _ _ ";
+ rewritten << d_assertionToRewrite[missingAssertion->negate()];
+ rewritten << "))";
+
+ Debug("pf::tp") << "Setting a rewrite filter for this proof: " << std::endl
+ << pm->getLitName(*missingAssertion) << " --> " << rewritten.str()
+ << std::endl << std::endl;
+
+ pm->addRewriteFilter(pm->getLitName(*missingAssertion), rewritten.str());
+ }
+
+ // Query the appropriate theory for a proof of this clause
+ theory::TheoryId theory_id = getTheoryForLemma(clause);
+ Debug("pf::tp") << "Get theory lemma from " << theory_id << "..." << std::endl;
+ getTheoryProof(theory_id)->printTheoryLemmaProof(clause_expr, os, paren, map);
+
+ // Turn rewrite filter OFF
+ pm->clearRewriteFilters();
+
+ Debug("pf::tp") << "Get theory lemma from " << theory_id << "... DONE!" << std::endl;
+ os << clause_paren.str();
+ os << "( \\ " << pm->getLemmaClauseName(id) <<"\n";
+ paren << "))";
+ } else { // This is a composite lemma
+
+ unsigned numberOfSteps = recipe.getNumSteps();
+ prop::SatClause currentClause = *clause;
+ std::vector<Expr> currentClauseExpr = clause_expr;
+
+ for (unsigned i = 0; i < numberOfSteps; ++i) {
+ const LemmaProofRecipe::ProofStep* currentStep = recipe.getStep(i);
+
+ currentClause = *clause;
+ currentClauseExpr = clause_expr;
+
+ for (unsigned j = 0; j < i; ++j) {
+ // Literals already used in previous steps need to be negated
+ Node previousLiteralNode = recipe.getStep(j)->getLiteral();
+ Node previousLiteralNodeNegated = previousLiteralNode.negate();
+ prop::SatLiteral previousLiteralNegated =
+ ProofManager::currentPM()->getCnfProof()->getLiteral(previousLiteralNodeNegated);
+ currentClause.push_back(previousLiteralNegated);
+ currentClauseExpr.push_back(previousLiteralNodeNegated.toExpr());
+ }
+
+ // If the current literal is NULL, can ignore (final step)
+ // Otherwise, the current literal does NOT need to be negated
+ Node currentLiteralNode = currentStep->getLiteral();
+ if (currentLiteralNode != Node()) {
+ prop::SatLiteral currentLiteral =
+ ProofManager::currentPM()->getCnfProof()->getLiteral(currentLiteralNode);
+
+ currentClause.push_back(currentLiteral);
+ currentClauseExpr.push_back(currentLiteralNode.toExpr());
+ }
+
+ os << "(satlem _ _ ";
+ std::ostringstream clause_paren;
+
+ pm->getCnfProof()->printClause(currentClause, os, clause_paren);
+
+ // query appropriate theory for proof of clause
+ theory::TheoryId theory_id = currentStep->getTheory();
+ Debug("pf::tp") << "Get theory lemma from " << theory_id << "..." << std::endl;
+
+ std::set<Node> missingAssertions = recipe.getMissingAssertionsForStep(i);
+ if (!missingAssertions.empty()) {
+ Debug("pf::tp") << "Have missing assertions for this step!" << std::endl;
+ }
+
+ // Turn rewrite filter ON
+ std::set<Node>::const_iterator missingAssertion;
+ for (missingAssertion = missingAssertions.begin();
+ missingAssertion != missingAssertions.end();
+ ++missingAssertion) {
+
+ Debug("pf::tp") << "Working on missing assertion: " << *missingAssertion << std::endl;
+
+ Assert(recipe.wasRewritten(missingAssertion->negate()));
+ Node explanation = recipe.getExplanation(missingAssertion->negate()).negate();
+
+ Debug("pf::tp") << "Found explanation: " << explanation << std::endl;
+
+ // We have a missing assertion.
+ // rewriteIt->first is the assertion after the rewrite (the explanation),
+ // rewriteIt->second is the original assertion that needs to be fed into the theory.
+
+ bool found = false;
+ unsigned k;
+ for (k = 0; k < currentClauseExpr.size(); ++k) {
+ if (currentClauseExpr[k] == explanation.toExpr()) {
+ found = true;
+ break;
+ }
+ }
+
+ AlwaysAssert(found);
+
+ Debug("pf::tp") << "Replacing theory assertion "
+ << currentClauseExpr[k]
+ << " with "
+ << *missingAssertion
+ << std::endl;
+
+ currentClauseExpr[k] = missingAssertion->toExpr();
+
+ std::ostringstream rewritten;
+ rewritten << "(or_elim_1 _ _ ";
+ rewritten << "(not_not_intro _ ";
+ rewritten << pm->getLitName(explanation);
+ rewritten << ") (iff_elim_1 _ _ ";
+ rewritten << d_assertionToRewrite[missingAssertion->negate()];
+ rewritten << "))";
+
+ Debug("pf::tp") << "Setting a rewrite filter for this proof: " << std::endl
+ << pm->getLitName(*missingAssertion) << " --> " << rewritten.str()
+ << std::endl << std::endl;
+
+ pm->addRewriteFilter(pm->getLitName(*missingAssertion), rewritten.str());
+ }
+
+ getTheoryProof(theory_id)->printTheoryLemmaProof(currentClauseExpr, os, paren, map);
+
+ // Turn rewrite filter OFF
+ pm->clearRewriteFilters();
+
+ Debug("pf::tp") << "Get theory lemma from " << theory_id << "... DONE!" << std::endl;
+ os << clause_paren.str();
+ os << "( \\ " << pm->getLemmaClauseName(id) << "s" << i <<"\n";
+ paren << "))";
+ }
+
+ Assert(numberOfSteps >= 2);
+
+ os << "(satlem_simplify _ _ _ ";
+ for (unsigned i = 0; i < numberOfSteps - 1; ++i) {
+ // Resolve step i with step i + 1
+ if (recipe.getStep(i)->getLiteral().getKind() == kind::NOT) {
+ os << "(Q _ _ ";
+ } else {
+ os << "(R _ _ ";
+ }
+
+ os << pm->getLemmaClauseName(id) << "s" << i;
+ os << " ";
+ }
+
+ os << pm->getLemmaClauseName(id) << "s" << numberOfSteps - 1 << " ";
+
+ prop::SatLiteral v;
+ for (int i = numberOfSteps - 2; i >= 0; --i) {
+ v = ProofManager::currentPM()->getCnfProof()->getLiteral(recipe.getStep(i)->getLiteral());
+ os << ProofManager::getVarName(v.getSatVariable(), "") << ") ";
+ }
+
+ os << "( \\ " << pm->getLemmaClauseName(id) << "\n";
+ paren << "))";
+ }
}
}
-void LFSCTheoryProofEngine::printBoundTerm(Expr term, std::ostream& os, const LetMap& map) {
- // Debug("pf::tp") << "LFSCTheoryProofEngine::printBoundTerm( " << term << " ) " << std::endl;
+void LFSCTheoryProofEngine::printBoundTerm(Expr term, std::ostream& os, const ProofLetMap& map) {
+ Debug("pf::tp") << "LFSCTheoryProofEngine::printBoundTerm( " << term << " ) " << std::endl;
- LetMap::const_iterator it = map.find(term);
+ ProofLetMap::const_iterator it = map.find(term);
if (it != map.end()) {
unsigned id = it->second.id;
unsigned count = it->second.count;
+
if (count > LET_COUNT) {
- os <<"let"<<id;
+ os << "let" << id;
return;
}
}
@@ -496,7 +813,7 @@ void LFSCTheoryProofEngine::printBoundTerm(Expr term, std::ostream& os, const Le
printTheoryTerm(term, os, map);
}
-void LFSCTheoryProofEngine::printCoreTerm(Expr term, std::ostream& os, const LetMap& map) {
+void LFSCTheoryProofEngine::printCoreTerm(Expr term, std::ostream& os, const ProofLetMap& map) {
if (term.isVariable()) {
os << ProofManager::sanitize(term);
return;
@@ -596,20 +913,25 @@ void LFSCTheoryProofEngine::printCoreTerm(Expr term, std::ostream& os, const Let
}
-void TheoryProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren) {
- //default method for replaying proofs: assert (negated) literals back to a fresh copy of the theory
- Assert( d_theory!=NULL );
+void TheoryProof::printTheoryLemmaProof(std::vector<Expr>& lemma,
+ std::ostream& os,
+ std::ostream& paren,
+ const ProofLetMap& map) {
+ // Default method for replaying proofs: assert (negated) literals back to a fresh copy of the theory
+ Assert(d_theory!=NULL);
+
context::UserContext fakeContext;
ProofOutputChannel oc;
theory::Valuation v(NULL);
//make new copy of theory
theory::Theory* th;
- Trace("theory-proof-debug") << ";; Print theory lemma proof, theory id = " << d_theory->getId() << std::endl;
- if(d_theory->getId()==theory::THEORY_UF) {
+ Trace("pf::tp") << ";; Print theory lemma proof, theory id = " << d_theory->getId() << std::endl;
+
+ if (d_theory->getId()==theory::THEORY_UF) {
th = new theory::uf::TheoryUF(&fakeContext, &fakeContext, oc, v,
ProofManager::currentPM()->getLogicInfo(),
"replay::");
- } else if(d_theory->getId()==theory::THEORY_ARRAY) {
+ } else if (d_theory->getId()==theory::THEORY_ARRAY) {
th = new theory::arrays::TheoryArrays(&fakeContext, &fakeContext, oc, v,
ProofManager::currentPM()->getLogicInfo(),
"replay::");
@@ -626,11 +948,15 @@ void TheoryProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream&
Debug("pf::tp") << "TheoryProof::printTheoryLemmaProof - th->ProduceProofs() DONE" << std::endl;
MyPreRegisterVisitor preRegVisitor(th);
- for( unsigned i=0; i<lemma.size(); i++ ){
- Node lit = Node::fromExpr( lemma[i] ).negate();
- Trace("pf::tp") << "; preregistering and asserting " << lit << std::endl;
- NodeVisitor<MyPreRegisterVisitor>::run(preRegVisitor, lit);
- th->assertFact(lit, false);
+ for (unsigned i=0; i<lemma.size(); i++) {
+ Node strippedLit = (lemma[i].getKind() == kind::NOT) ? lemma[i][0] : lemma[i];
+ if (strippedLit.getKind() == kind::EQUAL ||
+ d_theory->getId() == theory::Theory::theoryOf(strippedLit)) {
+ Node lit = Node::fromExpr( lemma[i] ).negate();
+ Trace("pf::tp") << "; preregistering and asserting " << lit << std::endl;
+ NodeVisitor<MyPreRegisterVisitor>::run(preRegVisitor, lit);
+ th->assertFact(lit, false);
+ }
}
Debug("pf::tp") << "TheoryProof::printTheoryLemmaProof - calling th->check()" << std::endl;
@@ -679,7 +1005,7 @@ void TheoryProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream&
th->check(theory::Theory::EFFORT_FULL);
}
Debug("pf::tp") << "Calling oc.d_proof->toStream(os)" << std::endl;
- oc.d_proof->toStream(os);
+ oc.d_proof->toStream(os, map);
Debug("pf::tp") << "Calling oc.d_proof->toStream(os) -- DONE!" << std::endl;
Debug("pf::tp") << "About to delete the theory solver used for proving the lemma... " << std::endl;
@@ -711,10 +1037,13 @@ void BooleanProof::registerTerm(Expr term) {
}
}
-void LFSCBooleanProof::printOwnedTerm(Expr term, std::ostream& os, const LetMap& map) {
+void LFSCBooleanProof::printOwnedTerm(Expr term, std::ostream& os, const ProofLetMap& map) {
Assert (term.getType().isBoolean());
if (term.isVariable()) {
- os << "(p_app " << ProofManager::sanitize(term) <<")";
+ if (d_treatBoolsAsFormulas)
+ os << "(p_app " << ProofManager::sanitize(term) <<")";
+ else
+ os << ProofManager::sanitize(term);
return;
}
@@ -722,6 +1051,32 @@ void LFSCBooleanProof::printOwnedTerm(Expr term, std::ostream& os, const LetMap&
switch(k) {
case kind::OR:
case kind::AND:
+ if (options::lfscLetification() && term.getNumChildren() > 2) {
+ // If letification is on, the entire term is probably a let expression.
+ // However, we need to transform it from (and a b c) into (and a (and b c)) form first.
+ Node currentExpression = term[term.getNumChildren() - 1];
+ for (int i = term.getNumChildren() - 2; i >= 0; --i) {
+ NodeBuilder<> builder(k);
+ builder << term[i];
+ builder << currentExpression.toExpr();
+ currentExpression = builder;
+ }
+
+ // The let map should already have the current expression.
+ ProofLetMap::const_iterator it = map.find(term);
+ if (it != map.end()) {
+ unsigned id = it->second.id;
+ unsigned count = it->second.count;
+
+ if (count > LET_COUNT) {
+ os << "let" << id;
+ break;
+ }
+ }
+ }
+
+ // If letification is off or there were 2 children, same treatment as the other cases.
+ // (No break is intentional).
case kind::XOR:
case kind::IFF:
case kind::IMPLIES:
@@ -753,7 +1108,10 @@ void LFSCBooleanProof::printOwnedTerm(Expr term, std::ostream& os, const LetMap&
return;
case kind::CONST_BOOLEAN:
- os << (term.getConst<bool>() ? "true" : "false");
+ if (d_treatBoolsAsFormulas)
+ os << (term.getConst<bool>() ? "true" : "false");
+ else
+ os << (term.getConst<bool>() ? "t_true" : "t_false");
return;
default:
@@ -786,10 +1144,36 @@ void LFSCBooleanProof::printDeferredDeclarations(std::ostream& os, std::ostream&
// Nothing to do here at this point.
}
+void LFSCBooleanProof::printAliasingDeclarations(std::ostream& os, std::ostream& paren) {
+ // Nothing to do here at this point.
+}
+
void LFSCBooleanProof::printTheoryLemmaProof(std::vector<Expr>& lemma,
std::ostream& os,
std::ostream& paren) {
Unreachable("No boolean lemmas yet!");
}
+void TheoryProof::printConstantDisequalityProof(std::ostream& os, Expr c1, Expr c2) {
+ // By default, we just print a trust statement. Specific theories can implement
+ // better proofs.
+ ProofLetMap emptyMap;
+
+ os << "(trust_f (not (= _ ";
+ d_proofEngine->printBoundTerm(c1, os, emptyMap);
+ os << " ";
+ d_proofEngine->printBoundTerm(c2, os, emptyMap);
+ os << ")))";
+}
+
+void TheoryProof::printRewriteProof(std::ostream& os, const Node &n1, const Node &n2) {
+ // This is the default for a rewrite proof: just a trust statement.
+ ProofLetMap emptyMap;
+ os << "(trust_f (iff ";
+ d_proofEngine->printBoundTerm(n1.toExpr(), os, emptyMap);
+ os << " ";
+ d_proofEngine->printBoundTerm(n2.toExpr(), os, emptyMap);
+ os << "))";
+}
+
} /* namespace CVC4 */
diff --git a/src/proof/theory_proof.h b/src/proof/theory_proof.h
index 54c86f3f3..5907f9bd5 100644
--- a/src/proof/theory_proof.h
+++ b/src/proof/theory_proof.h
@@ -27,6 +27,7 @@
#include "proof/clause_id.h"
#include "prop/sat_solver_types.h"
#include "util/proof.h"
+#include "proof/proof_utils.h"
namespace CVC4 {
@@ -34,66 +35,21 @@ namespace theory {
class Theory;
} /* namespace CVC4::theory */
-struct LetCount {
- static unsigned counter;
- static void resetCounter() { counter = 0; }
- static unsigned newId() { return ++counter; }
-
- unsigned count;
- unsigned id;
- LetCount()
- : count(0)
- , id(-1)
- {}
-
- void increment() { ++count; }
- LetCount(unsigned i)
- : count(1)
- , id(i)
- {}
- LetCount(const LetCount& other)
- : count(other.count)
- , id (other.id)
- {}
- bool operator==(const LetCount &other) const {
- return other.id == id && other.count == count;
- }
- LetCount& operator=(const LetCount &rhs) {
- if (&rhs == this) return *this;
- id = rhs.id;
- count = rhs.count;
- return *this;
- }
-};
-
-struct LetOrderElement {
- Expr expr;
- unsigned id;
- LetOrderElement(Expr e, unsigned i)
- : expr(e)
- , id(i)
- {}
-
- LetOrderElement()
- : expr()
- , id(-1)
- {}
-};
-
typedef __gnu_cxx::hash_map < ClauseId, prop::SatClause* > IdToSatClause;
-typedef __gnu_cxx::hash_map<Expr, LetCount, ExprHashFunction> LetMap;
-typedef std::vector<LetOrderElement> Bindings;
-
class TheoryProof;
typedef __gnu_cxx::hash_set<Expr, ExprHashFunction > ExprSet;
typedef std::map<theory::TheoryId, TheoryProof* > TheoryProofTable;
+typedef std::set<theory::TheoryId> TheoryIdSet;
+typedef std::map<Expr, TheoryIdSet> ExprToTheoryIds;
+
class TheoryProofEngine {
protected:
ExprSet d_registrationCache;
TheoryProofTable d_theoryProofTable;
+ ExprToTheoryIds d_exprToTheoryIds;
/**
* Returns whether the theory is currently supported in proof
@@ -113,7 +69,7 @@ public:
*/
virtual void printLetTerm(Expr term, std::ostream& os) = 0;
virtual void printBoundTerm(Expr term, std::ostream& os,
- const LetMap& map) = 0;
+ const ProofLetMap& map) = 0;
/**
* Print the proof representation of the given sort.
@@ -148,6 +104,14 @@ public:
virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren) = 0;
/**
+ * Print aliasing declarations.
+ *
+ * @param os
+ * @param paren closing parenthesis
+ */
+ virtual void printAliasingDeclarations(std::ostream& os, std::ostream& paren) = 0;
+
+ /**
* Print proofs of all the theory lemmas (must prove
* actual clause used in resolution proof).
*
@@ -155,7 +119,7 @@ public:
* @param paren
*/
virtual void printTheoryLemmas(const IdToSatClause& lemmas, std::ostream& os,
- std::ostream& paren) = 0;
+ std::ostream& paren, ProofLetMap& map) = 0;
/**
* Register theory atom (ensures all terms and atoms are declared).
@@ -166,35 +130,67 @@ public:
/**
* Ensures that a theory proof class for the given theory is created.
+ * This method can be invoked regardless of whether the "proof" option
+ * has been set.
*
* @param theory
*/
void registerTheory(theory::Theory* theory);
+ /**
+ * Additional configuration of the theory proof class for the given theory.
+ * This method should only be invoked when the "proof" option has been set.
+ *
+ * @param theory
+ */
+ void finishRegisterTheory(theory::Theory* theory);
- theory::TheoryId getTheoryForLemma(ClauseId id);
+ theory::TheoryId getTheoryForLemma(const prop::SatClause* clause);
TheoryProof* getTheoryProof(theory::TheoryId id);
+
+ void markTermForFutureRegistration(Expr term, theory::TheoryId id);
+
+ void printConstantDisequalityProof(std::ostream& os, Expr c1, Expr c2);
+
+ virtual void treatBoolsAsFormulas(bool value) {};
+
+ virtual void printTheoryTerm(Expr term, std::ostream& os, const ProofLetMap& map) = 0;
};
class LFSCTheoryProofEngine : public TheoryProofEngine {
- LetMap d_letMap;
- void printTheoryTerm(Expr term, std::ostream& os, const LetMap& map);
- void bind(Expr term, LetMap& map, Bindings& let_order);
+ void bind(Expr term, ProofLetMap& map, Bindings& let_order);
public:
LFSCTheoryProofEngine()
: TheoryProofEngine() {}
+ void printTheoryTerm(Expr term, std::ostream& os, const ProofLetMap& map);
+
void registerTermsFromAssertions();
void printSortDeclarations(std::ostream& os, std::ostream& paren);
void printTermDeclarations(std::ostream& os, std::ostream& paren);
- virtual void printCoreTerm(Expr term, std::ostream& os, const LetMap& map);
+ virtual void printCoreTerm(Expr term, std::ostream& os, const ProofLetMap& map);
virtual void printLetTerm(Expr term, std::ostream& os);
- virtual void printBoundTerm(Expr term, std::ostream& os, const LetMap& map);
+ virtual void printBoundTerm(Expr term, std::ostream& os, const ProofLetMap& map);
virtual void printAssertions(std::ostream& os, std::ostream& paren);
+ virtual void printLemmaRewrites(NodePairSet& rewrites, std::ostream& os, std::ostream& paren);
virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren);
+ virtual void printAliasingDeclarations(std::ostream& os, std::ostream& paren);
virtual void printTheoryLemmas(const IdToSatClause& lemmas,
std::ostream& os,
- std::ostream& paren);
+ std::ostream& paren,
+ ProofLetMap& map);
virtual void printSort(Type type, std::ostream& os);
+
+ void performExtraRegistrations();
+
+ void treatBoolsAsFormulas(bool value);
+ void finalizeBvConflicts(const IdToSatClause& lemmas, std::ostream& os);
+
+private:
+ static void dumpTheoryLemmas(const IdToSatClause& lemmas);
+
+ // TODO: this function should be moved into the BV prover.
+
+ std::map<Node, std::string> d_assertionToRewrite;
};
class TheoryProof {
@@ -214,7 +210,7 @@ public:
* @param term expresion representing term
* @param os output stream
*/
- void printTerm(Expr term, std::ostream& os, const LetMap& map) {
+ void printTerm(Expr term, std::ostream& os, const ProofLetMap& map) {
d_proofEngine->printBoundTerm(term, os, map);
}
/**
@@ -223,7 +219,7 @@ public:
* @param term expresion representing term
* @param os output stream
*/
- virtual void printOwnedTerm(Expr term, std::ostream& os, const LetMap& map) = 0;
+ virtual void printOwnedTerm(Expr term, std::ostream& os, const ProofLetMap& map) = 0;
/**
* Print the proof representation of the given type that belongs to some theory.
*
@@ -246,7 +242,10 @@ public:
*
* @param os output stream
*/
- virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren);
+ virtual void printTheoryLemmaProof(std::vector<Expr>& lemma,
+ std::ostream& os,
+ std::ostream& paren,
+ const ProofLetMap& map);
/**
* Print the sorts declarations for this theory.
*
@@ -270,11 +269,32 @@ public:
*/
virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren) = 0;
/**
+ * Print any aliasing declarations.
+ *
+ * @param os
+ * @param paren
+ */
+ virtual void printAliasingDeclarations(std::ostream& os, std::ostream& paren) = 0;
+ /**
* Register a term of this theory that appears in the proof.
*
* @param term
*/
virtual void registerTerm(Expr term) = 0;
+ /**
+ * Print a proof for the disequality of two constants that belong to this theory.
+ *
+ * @param term
+ */
+ virtual void printConstantDisequalityProof(std::ostream& os, Expr c1, Expr c2);
+ /**
+ * Print a proof for the equivalence of n1 and n2.
+ *
+ * @param term
+ */
+ virtual void printRewriteProof(std::ostream& os, const Node &n1, const Node &n2);
+
+ virtual void treatBoolsAsFormulas(bool value) {}
};
class BooleanProof : public TheoryProof {
@@ -285,26 +305,35 @@ public:
virtual void registerTerm(Expr term);
- virtual void printOwnedTerm(Expr term, std::ostream& os, const LetMap& map) = 0;
+ virtual void printOwnedTerm(Expr term, std::ostream& os, const ProofLetMap& map) = 0;
virtual void printOwnedSort(Type type, std::ostream& os) = 0;
virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren) = 0;
virtual void printSortDeclarations(std::ostream& os, std::ostream& paren) = 0;
virtual void printTermDeclarations(std::ostream& os, std::ostream& paren) = 0;
virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren) = 0;
+ virtual void printAliasingDeclarations(std::ostream& os, std::ostream& paren) = 0;
};
class LFSCBooleanProof : public BooleanProof {
public:
LFSCBooleanProof(TheoryProofEngine* proofEngine)
- : BooleanProof(proofEngine)
+ : BooleanProof(proofEngine), d_treatBoolsAsFormulas(true)
{}
- virtual void printOwnedTerm(Expr term, std::ostream& os, const LetMap& map);
+ virtual void printOwnedTerm(Expr term, std::ostream& os, const ProofLetMap& map);
virtual void printOwnedSort(Type type, std::ostream& os);
virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren);
virtual void printSortDeclarations(std::ostream& os, std::ostream& paren);
virtual void printTermDeclarations(std::ostream& os, std::ostream& paren);
virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren);
+ virtual void printAliasingDeclarations(std::ostream& os, std::ostream& paren);
+
+ void treatBoolsAsFormulas(bool value) {
+ d_treatBoolsAsFormulas = value;
+ }
+
+private:
+ bool d_treatBoolsAsFormulas;
};
} /* CVC4 namespace */
diff --git a/src/proof/uf_proof.cpp b/src/proof/uf_proof.cpp
index 32ca122b0..139ce5ed2 100644
--- a/src/proof/uf_proof.cpp
+++ b/src/proof/uf_proof.cpp
@@ -67,13 +67,17 @@ inline static bool match(TNode n1, TNode n2) {
void ProofUF::toStream(std::ostream& out) {
+ ProofLetMap map;
+ toStream(out, map);
+}
+
+void ProofUF::toStream(std::ostream& out, const ProofLetMap& map) {
Trace("theory-proof-debug") << "; Print UF proof..." << std::endl;
//AJR : carry this further?
- LetMap map;
toStreamLFSC(out, ProofManager::getUfProof(), d_proof, map);
}
-void ProofUF::toStreamLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, const LetMap& map) {
+void ProofUF::toStreamLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, const ProofLetMap& map) {
Debug("pf::uf") << "ProofUF::toStreamLFSC starting" << std::endl;
Debug("lfsc-uf") << "Printing uf proof in LFSC : " << std::endl;
pf->debug_print("lfsc-uf");
@@ -81,12 +85,21 @@ void ProofUF::toStreamLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqPr
toStreamRecLFSC( out, tp, pf, 0, map );
}
-Node ProofUF::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, unsigned tb, const LetMap& map) {
+Node ProofUF::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, unsigned tb, const ProofLetMap& map) {
Debug("pf::uf") << std::endl << std::endl << "toStreamRecLFSC called. tb = " << tb << " . proof:" << std::endl;
pf->debug_print("pf::uf");
Debug("pf::uf") << std::endl;
- if(tb == 0) {
+ if (tb == 0) {
+ // Special case: false was an input, so the proof is just "false".
+ if (pf->d_id == theory::eq::MERGED_THROUGH_EQUALITY &&
+ pf->d_node == NodeManager::currentNM()->mkConst(false)) {
+ out << "(clausify_false ";
+ out << ProofManager::getLitName(NodeManager::currentNM()->mkConst(false).notNode());
+ out << ")" << std::endl;
+ return Node();
+ }
+
Assert(pf->d_id == theory::eq::MERGED_THROUGH_TRANS);
Assert(!pf->d_node.isNull());
Assert(pf->d_children.size() >= 2);
@@ -190,42 +203,71 @@ Node ProofUF::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::E
++i;
}
}
- Assert(neg >= 0);
+
+ bool disequalityFound = (neg >= 0);
+ if (!disequalityFound) {
+ Debug("pf::uf") << "A disequality was NOT found. UNSAT due to merged constants" << std::endl;
+ Debug("pf::uf") << "Proof for: " << pf->d_node << std::endl;
+ Assert(pf->d_node.getKind() == kind::EQUAL);
+ Assert(pf->d_node.getNumChildren() == 2);
+ Assert (pf->d_node[0].isConst() && pf->d_node[1].isConst());
+ }
Node n1;
std::stringstream ss;
- //Assert(subTrans.d_children.size() == pf->d_children.size() - 1);
Debug("pf::uf") << "\nsubtrans has " << subTrans.d_children.size() << " children\n";
- if(pf->d_children.size() > 2) {
+
+ if(!disequalityFound || subTrans.d_children.size() >= 2) {
n1 = toStreamRecLFSC(ss, tp, &subTrans, 1, map);
} else {
n1 = toStreamRecLFSC(ss, tp, subTrans.d_children[0], 1, map);
Debug("pf::uf") << "\nsubTrans unique child " << subTrans.d_children[0]->d_id << " was proven\ngot: " << n1 << std::endl;
}
- Node n2 = pf->d_children[neg]->d_node;
- Assert(n2.getKind() == kind::NOT);
- out << "(clausify_false (contra _ ";
Debug("pf::uf") << "\nhave proven: " << n1 << std::endl;
- Debug("pf::uf") << "n2 is " << n2[0] << std::endl;
- if (n2[0].getNumChildren() > 0) { Debug("pf::uf") << "\nn2[0]: " << n2[0][0] << std::endl; }
- if (n1.getNumChildren() > 1) { Debug("pf::uf") << "n1[1]: " << n1[1] << std::endl; }
+ out << "(clausify_false (contra _ ";
- if(n2[0].getKind() == kind::APPLY_UF) {
- out << "(trans _ _ _ _ ";
- out << "(symm _ _ _ ";
- out << ss.str();
- out << ") (pred_eq_f _ " << ProofManager::getLitName(n2[0]) << ")) t_t_neq_f))" << std::endl;
- } else {
- Assert((n1[0] == n2[0][0] && n1[1] == n2[0][1]) || (n1[1] == n2[0][0] && n1[0] == n2[0][1]));
- if(n1[1] == n2[0][0]) {
- out << "(symm _ _ _ " << ss.str() << ")";
+ if (disequalityFound) {
+ Node n2 = pf->d_children[neg]->d_node;
+ Assert(n2.getKind() == kind::NOT);
+ Debug("pf::uf") << "n2 is " << n2[0] << std::endl;
+
+ if (n2[0].getNumChildren() > 0) { Debug("pf::uf") << "\nn2[0]: " << n2[0][0] << std::endl; }
+ if (n1.getNumChildren() > 1) { Debug("pf::uf") << "n1[1]: " << n1[1] << std::endl; }
+
+ if(n2[0].getKind() == kind::APPLY_UF) {
+ out << "(trans _ _ _ _ ";
+
+ if (n1[0] == n2[0]) {
+ out << "(symm _ _ _ ";
+ out << ss.str();
+ out << ") ";
+ } else {
+ Assert(n1[1] == n2[0]);
+ out << ss.str();
+ }
+ out << "(pred_eq_f _ " << ProofManager::getLitName(n2[0]) << ")) t_t_neq_f))" << std::endl;
} else {
- out << ss.str();
+ Assert((n1[0] == n2[0][0] && n1[1] == n2[0][1]) || (n1[1] == n2[0][0] && n1[0] == n2[0][1]));
+ if(n1[1] == n2[0][0]) {
+ out << "(symm _ _ _ " << ss.str() << ")";
+ } else {
+ out << ss.str();
+ }
+ out << " " << ProofManager::getLitName(n2[0]) << "))" << std::endl;
}
- out << " " << ProofManager::getLitName(n2[0]) << "))" << std::endl;
+ } else {
+ Node n2 = pf->d_node;
+ Assert(n2.getKind() == kind::EQUAL);
+ Assert((n1[0] == n2[0] && n1[1] == n2[1]) || (n1[1] == n2[0] && n1[0] == n2[1]));
+
+ out << ss.str();
+ out << " ";
+ ProofManager::getTheoryProofEngine()->printConstantDisequalityProof(out, n1[0].toExpr(), n1[1].toExpr());
+ out << "))" << std::endl;
}
+
return Node();
}
@@ -584,10 +626,10 @@ Node ProofUF::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::E
} else if(n1.getKind() == kind::EQUAL || n1.getKind() == kind::IFF) {
// n1 is an equality/iff, but n2 is a predicate
if(n1[0] == n2) {
- n1 = n1[1];
+ n1 = n1[1].iffNode(NodeManager::currentNM()->mkConst(true));
ss << "(symm _ _ _ " << ss1.str() << ") (pred_eq_t _ " << ss2.str() << ")";
} else if(n1[1] == n2) {
- n1 = n1[0];
+ n1 = n1[0].iffNode(NodeManager::currentNM()->mkConst(true));
ss << ss1.str() << " (pred_eq_t _ " << ss2.str() << ")";
} else {
Unreachable();
@@ -595,16 +637,16 @@ Node ProofUF::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::E
} else if(n2.getKind() == kind::EQUAL || n2.getKind() == kind::IFF) {
// n2 is an equality/iff, but n1 is a predicate
if(n2[0] == n1) {
- n1 = n2[1];
+ n1 = n2[1].iffNode(NodeManager::currentNM()->mkConst(true));
ss << "(symm _ _ _ " << ss2.str() << ") (pred_eq_t _ " << ss1.str() << ")";
} else if(n2[1] == n1) {
- n1 = n2[0];
+ n1 = n2[0].iffNode(NodeManager::currentNM()->mkConst(true));
ss << ss2.str() << " (pred_eq_t _ " << ss1.str() << ")";
} else {
Unreachable();
}
} else {
- // Both n1 and n2 are prediacates. Don't know what to do...
+ // Both n1 and n2 are predicates. Don't know what to do...
Unreachable();
}
@@ -655,7 +697,7 @@ void UFProof::registerTerm(Expr term) {
}
}
-void LFSCUFProof::printOwnedTerm(Expr term, std::ostream& os, const LetMap& map) {
+void LFSCUFProof::printOwnedTerm(Expr term, std::ostream& os, const ProofLetMap& map) {
Debug("pf::uf") << std::endl << "(pf::uf) LFSCUfProof::printOwnedTerm: term = " << term << std::endl;
Assert (theory::Theory::theoryOf(term) == theory::THEORY_UF);
@@ -667,6 +709,7 @@ void LFSCUFProof::printOwnedTerm(Expr term, std::ostream& os, const LetMap& map)
}
Assert (term.getKind() == kind::APPLY_UF);
+ d_proofEngine->treatBoolsAsFormulas(false);
if(term.getType().isBoolean()) {
os << "(p_app ";
@@ -683,6 +726,7 @@ void LFSCUFProof::printOwnedTerm(Expr term, std::ostream& os, const LetMap& map)
if(term.getType().isBoolean()) {
os << ")";
}
+ d_proofEngine->treatBoolsAsFormulas(true);
}
void LFSCUFProof::printOwnedSort(Type type, std::ostream& os) {
@@ -692,14 +736,14 @@ void LFSCUFProof::printOwnedSort(Type type, std::ostream& os) {
os << type <<" ";
}
-void LFSCUFProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren) {
+void LFSCUFProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren, const ProofLetMap& map) {
os << " ;; UF Theory Lemma \n;;";
for (unsigned i = 0; i < lemma.size(); ++i) {
os << lemma[i] <<" ";
}
os <<"\n";
//os << " (clausify_false trust)";
- UFProof::printTheoryLemmaProof( lemma, os, paren );
+ UFProof::printTheoryLemmaProof(lemma, os, paren, map);
}
void LFSCUFProof::printSortDeclarations(std::ostream& os, std::ostream& paren) {
@@ -714,6 +758,8 @@ void LFSCUFProof::printSortDeclarations(std::ostream& os, std::ostream& paren) {
void LFSCUFProof::printTermDeclarations(std::ostream& os, std::ostream& paren) {
// declaring the terms
+ Debug("pf::uf") << "LFSCUFProof::printTermDeclarations called" << std::endl;
+
for (ExprSet::const_iterator it = d_declarations.begin(); it != d_declarations.end(); ++it) {
Expr term = *it;
@@ -729,7 +775,8 @@ void LFSCUFProof::printTermDeclarations(std::ostream& os, std::ostream& paren) {
os << "(arrow";
for (unsigned i = 0; i < args.size(); i++) {
Type arg_type = args[i];
- os << " " << arg_type;
+ os << " ";
+ d_proofEngine->printSort(arg_type, os);
if (i < args.size() - 2) {
os << " (arrow";
fparen << ")";
@@ -742,10 +789,16 @@ void LFSCUFProof::printTermDeclarations(std::ostream& os, std::ostream& paren) {
}
paren << ")";
}
+
+ Debug("pf::uf") << "LFSCUFProof::printTermDeclarations done" << std::endl;
}
void LFSCUFProof::printDeferredDeclarations(std::ostream& os, std::ostream& paren) {
// Nothing to do here at this point.
}
+void LFSCUFProof::printAliasingDeclarations(std::ostream& os, std::ostream& paren) {
+ // Nothing to do here at this point.
+}
+
} /* namespace CVC4 */
diff --git a/src/proof/uf_proof.h b/src/proof/uf_proof.h
index e359eaebd..444b602dc 100644
--- a/src/proof/uf_proof.h
+++ b/src/proof/uf_proof.h
@@ -28,13 +28,14 @@ namespace CVC4 {
//proof object outputted by TheoryUF
class ProofUF : public Proof {
private:
- static Node toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, unsigned tb, const LetMap& map);
+ static Node toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, unsigned tb, const ProofLetMap& map);
public:
ProofUF( theory::eq::EqProof * pf ) : d_proof( pf ) {}
//it is simply an equality engine proof
theory::eq::EqProof * d_proof;
void toStream(std::ostream& out);
- static void toStreamLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, const LetMap& map);
+ void toStream(std::ostream& out, const ProofLetMap& map);
+ static void toStreamLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, const ProofLetMap& map);
};
@@ -63,12 +64,13 @@ public:
LFSCUFProof(theory::uf::TheoryUF* uf, TheoryProofEngine* proofEngine)
: UFProof(uf, proofEngine)
{}
- virtual void printOwnedTerm(Expr term, std::ostream& os, const LetMap& map);
+ virtual void printOwnedTerm(Expr term, std::ostream& os, const ProofLetMap& map);
virtual void printOwnedSort(Type type, std::ostream& os);
- virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren);
+ virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren, const ProofLetMap& map);
virtual void printSortDeclarations(std::ostream& os, std::ostream& paren);
virtual void printTermDeclarations(std::ostream& os, std::ostream& paren);
virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren);
+ virtual void printAliasingDeclarations(std::ostream& os, std::ostream& paren);
};
diff --git a/src/prop/bvminisat/bvminisat.h b/src/prop/bvminisat/bvminisat.h
index 20724efd2..56a7c61e2 100644
--- a/src/prop/bvminisat/bvminisat.h
+++ b/src/prop/bvminisat/bvminisat.h
@@ -78,6 +78,10 @@ public:
ClauseId addClause(SatClause& clause, bool removable);
+ ClauseId addXorClause(SatClause& clause, bool rhs, bool removable) {
+ Unreachable("Minisat does not support native XOR reasoning");
+ }
+
SatValue propagate();
SatVariable newVar(bool isTheoryAtom = false, bool preRegister = false, bool canErase = true);
diff --git a/src/prop/cnf_stream.cpp b/src/prop/cnf_stream.cpp
index aa1fc9587..eda736b8a 100644
--- a/src/prop/cnf_stream.cpp
+++ b/src/prop/cnf_stream.cpp
@@ -120,7 +120,7 @@ bool CnfStream::hasLiteral(TNode n) const {
return find != d_nodeToLiteralMap.end();
}
-void TseitinCnfStream::ensureLiteral(TNode n) {
+void TseitinCnfStream::ensureLiteral(TNode n, bool noPreregistration) {
// These are not removable and have no proof ID
d_removable = false;
@@ -163,7 +163,7 @@ void TseitinCnfStream::ensureLiteral(TNode n) {
d_literalToNodeMap.insert_safe(~lit, n.notNode());
} else {
// We have a theory atom or variable.
- lit = convertAtom(n);
+ lit = convertAtom(n, noPreregistration);
}
Assert(hasLiteral(n) && getNode(lit) == n);
@@ -232,7 +232,7 @@ void CnfStream::setProof(CnfProof* proof) {
d_cnfProof = proof;
}
-SatLiteral CnfStream::convertAtom(TNode node) {
+SatLiteral CnfStream::convertAtom(TNode node, bool noPreregistration) {
Debug("cnf") << "convertAtom(" << node << ")" << endl;
Assert(!hasLiteral(node), "atom already mapped!");
@@ -247,7 +247,7 @@ SatLiteral CnfStream::convertAtom(TNode node) {
} else {
theoryLiteral = true;
canEliminate = false;
- preRegister = true;
+ preRegister = !noPreregistration;
}
// Make a new literal (variables are not considered theory literals)
@@ -258,7 +258,11 @@ SatLiteral CnfStream::convertAtom(TNode node) {
SatLiteral CnfStream::getLiteral(TNode node) {
Assert(!node.isNull(), "CnfStream: can't getLiteral() of null node");
- Assert(d_nodeToLiteralMap.contains(node), "Literal not in the CNF Cache: %s\n", node.toString().c_str());
+
+ Assert(d_nodeToLiteralMap.contains(node),
+ "Literal not in the CNF Cache: %s\n",
+ node.toString().c_str());
+
SatLiteral literal = d_nodeToLiteralMap[node];
Debug("cnf") << "CnfStream::getLiteral(" << node << ") => " << literal << std::endl;
return literal;
@@ -675,7 +679,7 @@ void TseitinCnfStream::convertAndAssert(TNode node,
bool negated,
ProofRule proof_id,
TNode from,
- theory::TheoryId ownerTheory) {
+ LemmaProofRecipe* proofRecipe) {
Debug("cnf") << "convertAndAssert(" << node
<< ", removable = " << (removable ? "true" : "false")
<< ", negated = " << (negated ? "true" : "false") << ")" << endl;
@@ -685,7 +689,12 @@ void TseitinCnfStream::convertAndAssert(TNode node,
Node assertion = negated ? node.notNode() : (Node)node;
Node from_assertion = negated? from.notNode() : (Node) from;
- d_cnfProof->setExplainerTheory(ownerTheory);
+ if (proofRecipe) {
+ Debug("pf::sat") << "TseitinCnfStream::convertAndAssert: setting proof recipe" << std::endl;
+ proofRecipe->dump("pf::sat");
+ d_cnfProof->setProofRecipe(proofRecipe);
+ }
+
if (proof_id != RULE_INVALID) {
d_cnfProof->pushCurrentAssertion(from.isNull() ? assertion : from_assertion);
d_cnfProof->registerAssertion(from.isNull() ? assertion : from_assertion, proof_id);
diff --git a/src/prop/cnf_stream.h b/src/prop/cnf_stream.h
index cf9d519a7..6cc10d878 100644
--- a/src/prop/cnf_stream.h
+++ b/src/prop/cnf_stream.h
@@ -36,6 +36,9 @@
#include "smt_util/lemma_channels.h"
namespace CVC4 {
+
+class LemmaProofRecipe;
+
namespace prop {
class PropEngine;
@@ -174,7 +177,7 @@ protected:
* structure in this expression. Assumed to not be in the
* translation cache.
*/
- SatLiteral convertAtom(TNode node);
+ SatLiteral convertAtom(TNode node, bool noPreprocessing = false);
public:
@@ -207,14 +210,10 @@ public:
* @param node node to convert and assert
* @param removable whether the sat solver can choose to remove the clauses
* @param negated whether we are asserting the node negated
- * @param ownerTheory indicates the theory that should invoked to prove the formula.
+ * @param proofRecipe contains the proof recipe for proving this node
*/
- virtual void convertAndAssert(TNode node,
- bool removable,
- bool negated,
- ProofRule proof_id,
- TNode from = TNode::null(),
- theory::TheoryId ownerTheory = theory::THEORY_LAST) = 0;
+ virtual void convertAndAssert(TNode node, bool removable, bool negated, ProofRule proof_id, TNode from = TNode::null(), LemmaProofRecipe* proofRecipe = NULL) = 0;
+
/**
* Get the node that is represented by the given SatLiteral.
* @param literal the literal from the sat solver
@@ -235,7 +234,7 @@ public:
* this is like a "convert-but-don't-assert" version of
* convertAndAssert().
*/
- virtual void ensureLiteral(TNode n) = 0;
+ virtual void ensureLiteral(TNode n, bool noPreregistration = false) = 0;
/**
* Returns the literal that represents the given node in the SAT CNF
@@ -284,7 +283,7 @@ public:
*/
void convertAndAssert(TNode node, bool removable,
bool negated, ProofRule rule, TNode from = TNode::null(),
- theory::TheoryId ownerTheory = theory::THEORY_LAST);
+ LemmaProofRecipe* proofRecipe = NULL);
/**
* Constructs the stream to use the given sat solver.
@@ -337,7 +336,7 @@ private:
*/
SatLiteral toCNF(TNode node, bool negated = false);
- void ensureLiteral(TNode n);
+ void ensureLiteral(TNode n, bool noPreregistration = false);
};/* class TseitinCnfStream */
diff --git a/src/prop/cryptominisat.cpp b/src/prop/cryptominisat.cpp
new file mode 100644
index 000000000..d8f25a786
--- /dev/null
+++ b/src/prop/cryptominisat.cpp
@@ -0,0 +1,230 @@
+/********************* */
+/*! \file cryptominisat.cpp
+ ** \verbatim
+ ** Original author: lianah
+ ** Major contributors:
+ ** Minor contributors (to current version):
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009-2014 The Analysis of Computer Systems Group (ACSys)
+ ** Courant Institute of Mathematical Sciences
+ ** New York University
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief SAT Solver.
+ **
+ ** Implementation of the cryptominisat for cvc4 (bitvectors).
+ **/
+
+#include "prop/cryptominisat.h"
+
+#include "proof/clause_id.h"
+#include "proof/sat_proof.h"
+
+using namespace CVC4;
+using namespace prop;
+
+#ifdef CVC4_USE_CRYPTOMINISAT
+
+CryptoMinisatSolver::CryptoMinisatSolver(StatisticsRegistry* registry,
+ const std::string& name)
+: d_solver(new CMSat::SATSolver())
+, d_numVariables(0)
+, d_okay(true)
+, d_statistics(registry, name)
+{
+ d_true = newVar();
+ d_false = newVar();
+
+ std::vector<CMSat::Lit> clause(1);
+ clause[0] = CMSat::Lit(d_true, false);
+ d_solver->add_clause(clause);
+
+ clause[0] = CMSat::Lit(d_false, true);
+ d_solver->add_clause(clause);
+}
+
+
+CryptoMinisatSolver::~CryptoMinisatSolver() throw(AssertionException) {
+ delete d_solver;
+}
+
+ClauseId CryptoMinisatSolver::addXorClause(SatClause& clause,
+ bool rhs,
+ bool removable) {
+ Debug("sat::cryptominisat") << "Add xor clause " << clause <<" = " << rhs << "\n";
+
+ if (!d_okay) {
+ Debug("sat::cryptominisat") << "Solver unsat: not adding clause.\n";
+ return ClauseIdError;
+ }
+
+ ++(d_statistics.d_xorClausesAdded);
+
+ // ensure all sat literals have positive polarity by pushing
+ // the negation on the result
+ std::vector<CMSat::Var> xor_clause;
+ for (unsigned i = 0; i < clause.size(); ++i) {
+ xor_clause.push_back(toInternalLit(clause[i]).var());
+ rhs ^= clause[i].isNegated();
+ }
+ bool res = d_solver->add_xor_clause(xor_clause, rhs);
+ d_okay &= res;
+ return ClauseIdError;
+}
+
+ClauseId CryptoMinisatSolver::addClause(SatClause& clause, bool removable){
+ Debug("sat::cryptominisat") << "Add clause " << clause <<"\n";
+
+ if (!d_okay) {
+ Debug("sat::cryptominisat") << "Solver unsat: not adding clause.\n";
+ return ClauseIdError;
+ }
+
+ ++(d_statistics.d_clausesAdded);
+
+ std::vector<CMSat::Lit> internal_clause;
+ toInternalClause(clause, internal_clause);
+ bool res = d_solver->add_clause(internal_clause);
+ d_okay &= res;
+ return ClauseIdError;
+}
+
+bool CryptoMinisatSolver::ok() const {
+ return d_okay;
+}
+
+
+SatVariable CryptoMinisatSolver::newVar(bool isTheoryAtom, bool preRegister, bool canErase){
+ d_solver->new_var();
+ ++d_numVariables;
+ Assert (d_numVariables == d_solver->nVars());
+ return d_numVariables - 1;
+}
+
+SatVariable CryptoMinisatSolver::trueVar() {
+ return d_true;
+}
+
+SatVariable CryptoMinisatSolver::falseVar() {
+ return d_false;
+}
+
+void CryptoMinisatSolver::markUnremovable(SatLiteral lit) {
+ // cryptominisat supports dynamically adding back variables (?)
+ // so this is a no-op
+ return;
+}
+
+void CryptoMinisatSolver::interrupt(){
+ d_solver->interrupt_asap();
+}
+
+SatValue CryptoMinisatSolver::solve(){
+ TimerStat::CodeTimer codeTimer(d_statistics.d_solveTime);
+ ++d_statistics.d_statCallsToSolve;
+ return toSatLiteralValue(d_solver->solve());
+}
+
+SatValue CryptoMinisatSolver::solve(long unsigned int& resource) {
+ // CMSat::SalverConf conf = d_solver->getConf();
+ Unreachable("Not sure how to set different limits for calls to solve in Cryptominisat");
+ return solve();
+}
+
+SatValue CryptoMinisatSolver::value(SatLiteral l){
+ const std::vector<CMSat::lbool> model = d_solver->get_model();
+ CMSat::Var var = l.getSatVariable();
+ Assert (var < model.size());
+ CMSat::lbool value = model[var];
+ return toSatLiteralValue(value);
+}
+
+SatValue CryptoMinisatSolver::modelValue(SatLiteral l){
+ return value(l);
+}
+
+unsigned CryptoMinisatSolver::getAssertionLevel() const {
+ Unreachable("No interface to get assertion level in Cryptominisat");
+ return -1;
+}
+
+// converting from internal sat solver representation
+
+SatVariable CryptoMinisatSolver::toSatVariable(CMSat::Var var) {
+ if (var == CMSat::var_Undef) {
+ return undefSatVariable;
+ }
+ return SatVariable(var);
+}
+
+CMSat::Lit CryptoMinisatSolver::toInternalLit(SatLiteral lit) {
+ if (lit == undefSatLiteral) {
+ return CMSat::lit_Undef;
+ }
+ return CMSat::Lit(lit.getSatVariable(), lit.isNegated());
+}
+
+SatLiteral CryptoMinisatSolver::toSatLiteral(CMSat::Lit lit) {
+ Assert (lit != CMSat::lit_Error);
+ if (lit == CMSat::lit_Undef) {
+ return undefSatLiteral;
+ }
+
+ return SatLiteral(SatVariable(lit.var()),
+ lit.sign());
+}
+
+SatValue CryptoMinisatSolver::toSatLiteralValue(CMSat::lbool res) {
+ if(res == CMSat::l_True) return SAT_VALUE_TRUE;
+ if(res == CMSat::l_Undef) return SAT_VALUE_UNKNOWN;
+ Assert(res == CMSat::l_False);
+ return SAT_VALUE_FALSE;
+}
+
+void CryptoMinisatSolver::toInternalClause(SatClause& clause,
+ std::vector<CMSat::Lit>& internal_clause) {
+ for (unsigned i = 0; i < clause.size(); ++i) {
+ internal_clause.push_back(toInternalLit(clause[i]));
+ }
+ Assert(clause.size() == internal_clause.size());
+}
+
+void CryptoMinisatSolver::toSatClause(std::vector<CMSat::Lit>& clause,
+ SatClause& sat_clause) {
+ for (unsigned i = 0; i < clause.size(); ++i) {
+ sat_clause.push_back(toSatLiteral(clause[i]));
+ }
+ Assert(clause.size() == sat_clause.size());
+}
+
+
+// Satistics for CryptoMinisatSolver
+
+CryptoMinisatSolver::Statistics::Statistics(StatisticsRegistry* registry,
+ const std::string& prefix) :
+ d_registry(registry),
+ d_statCallsToSolve("theory::bv::"+prefix+"::cryptominisat::calls_to_solve", 0),
+ d_xorClausesAdded("theory::bv::"+prefix+"::cryptominisat::xor_clauses", 0),
+ d_clausesAdded("theory::bv::"+prefix+"::cryptominisat::clauses", 0),
+ d_solveTime("theory::bv::"+prefix+"::cryptominisat::solve_time"),
+ d_registerStats(!prefix.empty())
+{
+ if (!d_registerStats)
+ return;
+
+ d_registry->registerStat(&d_statCallsToSolve);
+ d_registry->registerStat(&d_xorClausesAdded);
+ d_registry->registerStat(&d_clausesAdded);
+ d_registry->registerStat(&d_solveTime);
+}
+
+CryptoMinisatSolver::Statistics::~Statistics() {
+ if (!d_registerStats)
+ return;
+ d_registry->unregisterStat(&d_statCallsToSolve);
+ d_registry->unregisterStat(&d_xorClausesAdded);
+ d_registry->unregisterStat(&d_clausesAdded);
+ d_registry->unregisterStat(&d_solveTime);
+}
+#endif
diff --git a/src/prop/cryptominisat.h b/src/prop/cryptominisat.h
new file mode 100644
index 000000000..54d52af0e
--- /dev/null
+++ b/src/prop/cryptominisat.h
@@ -0,0 +1,138 @@
+/********************* */
+/*! \file cryptominisat.h
+ ** \verbatim
+ ** Original author: lianah
+ ** Major contributors:
+ ** Minor contributors (to current version):
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009-2014 The Analysis of Computer Systems Group (ACSys)
+ ** Courant Institute of Mathematical Sciences
+ ** New York University
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief SAT Solver.
+ **
+ ** Implementation of the cryptominisat sat solver for cvc4 (bitvectors).
+ **/
+
+#include "cvc4_private.h"
+
+#pragma once
+
+#include "prop/sat_solver.h"
+
+#ifdef CVC4_USE_CRYPTOMINISAT
+#include <cryptominisat4/cryptominisat.h>
+namespace CVC4 {
+namespace prop {
+
+class CryptoMinisatSolver : public SatSolver {
+
+private:
+ CMSat::SATSolver* d_solver;
+ unsigned d_numVariables;
+ bool d_okay;
+ SatVariable d_true;
+ SatVariable d_false;
+public:
+ CryptoMinisatSolver(StatisticsRegistry* registry,
+ const std::string& name = "");
+ ~CryptoMinisatSolver() throw(AssertionException);
+
+ ClauseId addClause(SatClause& clause, bool removable);
+ ClauseId addXorClause(SatClause& clause, bool rhs, bool removable);
+
+ bool nativeXor() { return true; }
+
+ SatVariable newVar(bool isTheoryAtom = false, bool preRegister = false, bool canErase = true);
+
+ SatVariable trueVar();
+ SatVariable falseVar();
+
+ void markUnremovable(SatLiteral lit);
+
+ void interrupt();
+
+ SatValue solve();
+ SatValue solve(long unsigned int&);
+ bool ok() const;
+ SatValue value(SatLiteral l);
+ SatValue modelValue(SatLiteral l);
+
+ unsigned getAssertionLevel() const;
+
+
+ // helper methods for converting from the internal Minisat representation
+
+ static SatVariable toSatVariable(CMSat::Var var);
+ static CMSat::Lit toInternalLit(SatLiteral lit);
+ static SatLiteral toSatLiteral(CMSat::Lit lit);
+ static SatValue toSatLiteralValue(bool res);
+ static SatValue toSatLiteralValue(CMSat::lbool res);
+
+ static void toInternalClause(SatClause& clause, std::vector<CMSat::Lit>& internal_clause);
+ static void toSatClause (std::vector<CMSat::Lit>& clause, SatClause& sat_clause);
+
+ class Statistics {
+ public:
+ StatisticsRegistry* d_registry;
+ IntStat d_statCallsToSolve;
+ IntStat d_xorClausesAdded;
+ IntStat d_clausesAdded;
+ TimerStat d_solveTime;
+ bool d_registerStats;
+ Statistics(StatisticsRegistry* registry,
+ const std::string& prefix);
+ ~Statistics();
+ };
+
+ Statistics d_statistics;
+};
+} // CVC4::prop
+} // CVC4
+
+#else // CVC4_USE_CRYPTOMINISAT
+
+namespace CVC4 {
+namespace prop {
+
+class CryptoMinisatSolver : public SatSolver {
+
+public:
+ CryptoMinisatSolver(StatisticsRegistry* registry,
+ const std::string& name = "") { Unreachable(); }
+ /** Assert a clause in the solver. */
+ ClauseId addClause(SatClause& clause, bool removable) {
+ Unreachable();
+ }
+
+ /** Return true if the solver supports native xor resoning */
+ bool nativeXor() { Unreachable(); }
+
+ /** Add a clause corresponding to rhs = l1 xor .. xor ln */
+ ClauseId addXorClause(SatClause& clause, bool rhs, bool removable) {
+ Unreachable();
+ }
+
+ SatVariable newVar(bool isTheoryAtom, bool preRegister, bool canErase) { Unreachable(); }
+ SatVariable trueVar() { Unreachable(); }
+ SatVariable falseVar() { Unreachable(); }
+ SatValue solve() { Unreachable(); }
+ SatValue solve(long unsigned int&) { Unreachable(); }
+ void interrupt() { Unreachable(); }
+ SatValue value(SatLiteral l) { Unreachable(); }
+ SatValue modelValue(SatLiteral l) { Unreachable(); }
+ unsigned getAssertionLevel() const { Unreachable(); }
+ bool ok() const { return false;};
+
+
+};/* class CryptoMinisatSolver */
+} // CVC4::prop
+} // CVC4
+
+#endif // CVC4_USE_CRYPTOMINISAT
+
+
+
+
diff --git a/src/prop/minisat/core/Solver.cc b/src/prop/minisat/core/Solver.cc
index 411b89514..a682a893b 100644
--- a/src/prop/minisat/core/Solver.cc
+++ b/src/prop/minisat/core/Solver.cc
@@ -232,6 +232,8 @@ CRef Solver::reason(Var x) {
vec<Lit> explanation;
MinisatSatSolver::toMinisatClause(explanation_cl, explanation);
+ Debug("pf::sat") << "Solver::reason: explanation_cl = " << explanation_cl << std::endl;
+
// Sort the literals by trail index level
lemma_lt lt(*this);
sort(explanation, lt);
@@ -266,6 +268,12 @@ CRef Solver::reason(Var x) {
}
explanation.shrink(i - j);
+ Debug("pf::sat") << "Solver::reason: explanation = " ;
+ for (int i = 0; i < explanation.size(); ++i) {
+ Debug("pf::sat") << explanation[i] << " ";
+ }
+ Debug("pf::sat") << std::endl;
+
// We need an explanation clause so we add a fake literal
if (j == 1) {
// Add not TRUE to the clause
@@ -276,6 +284,7 @@ CRef Solver::reason(Var x) {
CRef real_reason = ca.alloc(explLevel, explanation, true);
// FIXME: at some point will need more information about where this explanation
// came from (ie. the theory/sharing)
+ Debug("pf::sat") << "Minisat::Solver registering a THEORY_LEMMA (1)" << std::endl;
PROOF (ClauseId id = ProofManager::getSatProof()->registerClause(real_reason, THEORY_LEMMA);
ProofManager::getCnfProof()->registerConvertedClause(id, true);
// no need to pop current assertion as this is not converted to cnf
@@ -336,6 +345,12 @@ bool Solver::addClause_(vec<Lit>& ps, bool removable, ClauseId& id)
// If we are in solve or decision level > 0
if (minisat_busy || decisionLevel() > 0) {
+ Debug("pf::sat") << "Add clause adding a new lemma: ";
+ for (int k = 0; k < ps.size(); ++k) {
+ Debug("pf::sat") << ps[k] << " ";
+ }
+ Debug("pf::sat") << std::endl;
+
lemmas.push();
ps.copyTo(lemmas.last());
lemmas_removable.push(removable);
@@ -379,7 +394,7 @@ bool Solver::addClause_(vec<Lit>& ps, bool removable, ClauseId& id)
cr = ca.alloc(clauseLevel, ps, false);
clauses_persistent.push(cr);
- attachClause(cr);
+ attachClause(cr);
if(PROOF_ON()) {
PROOF(
@@ -1234,12 +1249,12 @@ lbool Solver::search(int nof_conflicts)
} else {
- // If this was a final check, we are satisfiable
+ // If this was a final check, we are satisfiable
if (check_type == CHECK_FINAL) {
- bool decisionEngineDone = proxy->isDecisionEngineDone();
+ bool decisionEngineDone = proxy->isDecisionEngineDone();
// Unless a lemma has added more stuff to the queues
if (!decisionEngineDone &&
- (!order_heap.empty() || qhead < trail.size()) ) {
+ (!order_heap.empty() || qhead < trail.size()) ) {
check_type = CHECK_WITH_THEORY;
continue;
} else if (recheck) {
@@ -1666,6 +1681,13 @@ CRef Solver::updateLemmas() {
{
// The current lemma
vec<Lit>& lemma = lemmas[i];
+
+ Debug("pf::sat") << "Solver::updateLemmas: working on lemma: ";
+ for (int k = 0; k < lemma.size(); ++k) {
+ Debug("pf::sat") << lemma[k] << " ";
+ }
+ Debug("pf::sat") << std::endl;
+
// If it's an empty lemma, we have a conflict at zero level
if (lemma.size() == 0) {
Assert (! PROOF_ON());
@@ -1725,6 +1747,7 @@ CRef Solver::updateLemmas() {
TNode cnf_assertion = lemmas_cnf_assertion[i].first;
TNode cnf_def = lemmas_cnf_assertion[i].second;
+ Debug("pf::sat") << "Minisat::Solver registering a THEORY_LEMMA (2)" << std::endl;
ClauseId id = ProofManager::getSatProof()->registerClause(lemma_ref, THEORY_LEMMA);
ProofManager::getCnfProof()->setClauseAssertion(id, cnf_assertion);
ProofManager::getCnfProof()->setClauseDefinition(id, cnf_def);
@@ -1741,6 +1764,7 @@ CRef Solver::updateLemmas() {
Node cnf_assertion = lemmas_cnf_assertion[i].first;
Node cnf_def = lemmas_cnf_assertion[i].second;
+ Debug("pf::sat") << "Minisat::Solver registering a THEORY_LEMMA (3)" << std::endl;
ClauseId id = ProofManager::getSatProof()->registerUnitClause(lemma[0], THEORY_LEMMA);
ProofManager::getCnfProof()->setClauseAssertion(id, cnf_assertion);
ProofManager::getCnfProof()->setClauseDefinition(id, cnf_def);
diff --git a/src/prop/minisat/minisat.cpp b/src/prop/minisat/minisat.cpp
index bfbf9da6f..ff726e299 100644
--- a/src/prop/minisat/minisat.cpp
+++ b/src/prop/minisat/minisat.cpp
@@ -150,7 +150,7 @@ ClauseId MinisatSatSolver::addClause(SatClause& clause, bool removable) {
// FIXME: This relies on the invariant that when ok() is false
// the SAT solver does not add the clause (which is what Minisat currently does)
if (!ok()) {
- return ClauseIdUndef;
+ return ClauseIdUndef;
}
d_minisat->addClause(minisat_clause, removable, clause_id);
PROOF( Assert (clause_id != ClauseIdError););
@@ -185,7 +185,7 @@ SatValue MinisatSatSolver::solve() {
}
bool MinisatSatSolver::ok() const {
- return d_minisat->okay();
+ return d_minisat->okay();
}
void MinisatSatSolver::interrupt() {
@@ -204,20 +204,20 @@ bool MinisatSatSolver::properExplanation(SatLiteral lit, SatLiteral expl) const
return true;
}
-void MinisatSatSolver::requirePhase(SatLiteral lit) {
+void MinisatSatSolver::requirePhase(SatLiteral lit) {
Assert(!d_minisat->rnd_pol);
Debug("minisat") << "requirePhase(" << lit << ")" << " " << lit.getSatVariable() << " " << lit.isNegated() << std::endl;
SatVariable v = lit.getSatVariable();
d_minisat->freezePolarity(v, lit.isNegated());
}
-bool MinisatSatSolver::flipDecision() {
+bool MinisatSatSolver::flipDecision() {
Debug("minisat") << "flipDecision()" << std::endl;
return d_minisat->flipDecision();
}
-bool MinisatSatSolver::isDecision(SatVariable decn) const {
- return d_minisat->isDecision( decn );
+bool MinisatSatSolver::isDecision(SatVariable decn) const {
+ return d_minisat->isDecision( decn );
}
/** Incremental interface */
@@ -291,7 +291,7 @@ namespace CVC4 {
template<>
prop::SatLiteral toSatLiteral< CVC4::Minisat::Solver>(Minisat::Solver::TLit lit) {
return prop::MinisatSatSolver::toSatLiteral(lit);
-}
+}
template<>
void toSatClause< CVC4::Minisat::Solver> (const CVC4::Minisat::Solver::TClause& minisat_cl,
@@ -300,5 +300,3 @@ void toSatClause< CVC4::Minisat::Solver> (const CVC4::Minisat::Solver::TClause&
}
} /* namespace CVC4 */
-
-
diff --git a/src/prop/minisat/minisat.h b/src/prop/minisat/minisat.h
index 535ce1a47..ec5297bb7 100644
--- a/src/prop/minisat/minisat.h
+++ b/src/prop/minisat/minisat.h
@@ -44,6 +44,9 @@ public:
void initialize(context::Context* context, TheoryProxy* theoryProxy);
ClauseId addClause(SatClause& clause, bool removable);
+ ClauseId addXorClause(SatClause& clause, bool rhs, bool removable) {
+ Unreachable("Minisat does not support native XOR reasoning");
+ }
SatVariable newVar(bool isTheoryAtom, bool preRegister, bool canErase);
SatVariable trueVar() { return d_minisat->trueVar(); }
diff --git a/src/prop/prop_engine.cpp b/src/prop/prop_engine.cpp
index 54cf4c457..eb607e901 100644
--- a/src/prop/prop_engine.cpp
+++ b/src/prop/prop_engine.cpp
@@ -132,13 +132,13 @@ void PropEngine::assertFormula(TNode node) {
void PropEngine::assertLemma(TNode node, bool negated,
bool removable,
ProofRule rule,
- theory::TheoryId ownerTheory,
+ LemmaProofRecipe* proofRecipe,
TNode from) {
//Assert(d_inCheckSat, "Sat solver should be in solve()!");
Debug("prop::lemmas") << "assertLemma(" << node << ")" << endl;
// Assert as (possibly) removable
- d_cnfStream->convertAndAssert(node, removable, negated, rule, from, ownerTheory);
+ d_cnfStream->convertAndAssert(node, removable, negated, rule, from, proofRecipe);
}
void PropEngine::requirePhase(TNode n, bool phase) {
diff --git a/src/prop/prop_engine.h b/src/prop/prop_engine.h
index b9ce7ca7e..c02015931 100644
--- a/src/prop/prop_engine.h
+++ b/src/prop/prop_engine.h
@@ -37,6 +37,7 @@ namespace CVC4 {
class ResourceManager;
class DecisionEngine;
class TheoryEngine;
+class LemmaProofRecipe;
namespace theory {
class TheoryRegistrar;
@@ -134,7 +135,7 @@ public:
* @param removable whether this lemma can be quietly removed based
* on an activity heuristic (or not)
*/
- void assertLemma(TNode node, bool negated, bool removable, ProofRule rule, theory::TheoryId ownerTheory, TNode from = TNode::null());
+ void assertLemma(TNode node, bool negated, bool removable, ProofRule rule, LemmaProofRecipe* proofRecipe, TNode from = TNode::null());
/**
* If ever n is decided upon, it must be in the given phase. This
diff --git a/src/prop/sat_solver.h b/src/prop/sat_solver.h
index 92696ae25..81fb94242 100644
--- a/src/prop/sat_solver.h
+++ b/src/prop/sat_solver.h
@@ -49,6 +49,12 @@ public:
virtual ClauseId addClause(SatClause& clause,
bool removable) = 0;
+ /** Return true if the solver supports native xor resoning */
+ virtual bool nativeXor() { return false; }
+
+ /** Add a clause corresponding to rhs = l1 xor .. xor ln */
+ virtual ClauseId addXorClause(SatClause& clause, bool rhs, bool removable) = 0;
+
/**
* Create a new boolean variable in the solver.
* @param isTheoryAtom is this a theory atom that needs to be asserted to theory
@@ -84,7 +90,8 @@ public:
/** Check if the solver is in an inconsistent state */
virtual bool ok() const = 0;
-
+
+ virtual void setProofLog( BitVectorProof * bvp ) {}
};/* class SatSolver */
diff --git a/src/prop/sat_solver_factory.cpp b/src/prop/sat_solver_factory.cpp
index 092ec72f2..7fdc44e66 100644
--- a/src/prop/sat_solver_factory.cpp
+++ b/src/prop/sat_solver_factory.cpp
@@ -16,6 +16,7 @@
#include "prop/sat_solver_factory.h"
+#include "prop/cryptominisat.h"
#include "prop/minisat/minisat.h"
#include "prop/bvminisat/bvminisat.h"
@@ -26,6 +27,12 @@ BVSatSolverInterface* SatSolverFactory::createMinisat(context::Context* mainSatC
return new BVMinisatSatSolver(registry, mainSatContext, name);
}
+SatSolver* SatSolverFactory::createCryptoMinisat(StatisticsRegistry* registry,
+ const std::string& name) {
+return new CryptoMinisatSolver(registry, name);
+}
+
+
DPLLSatSolverInterface* SatSolverFactory::createDPLLMinisat(StatisticsRegistry* registry) {
return new MinisatSatSolver(registry);
}
diff --git a/src/prop/sat_solver_factory.h b/src/prop/sat_solver_factory.h
index 7cc23a8e8..a04bcaaf4 100644
--- a/src/prop/sat_solver_factory.h
+++ b/src/prop/sat_solver_factory.h
@@ -35,6 +35,8 @@ public:
StatisticsRegistry* registry,
const std::string& name = "");
static DPLLSatSolverInterface* createDPLLMinisat(StatisticsRegistry* registry);
+ static SatSolver* createCryptoMinisat(StatisticsRegistry* registry,
+ const std::string& name = "");
};/* class SatSolverFactory */
diff --git a/src/prop/theory_proxy.cpp b/src/prop/theory_proxy.cpp
index 4a4515eb9..6e8f1fbbf 100644
--- a/src/prop/theory_proxy.cpp
+++ b/src/prop/theory_proxy.cpp
@@ -99,29 +99,34 @@ void TheoryProxy::explainPropagation(SatLiteral l, SatClause& explanation) {
TNode lNode = d_cnfStream->getNode(l);
Debug("prop-explain") << "explainPropagation(" << lNode << ")" << std::endl;
- NodeTheoryPair theoryExplanation = d_theoryEngine->getExplanationAndExplainer(lNode);
- Node explanationNode = theoryExplanation.node;
- theory::TheoryId explainerTheory = theoryExplanation.theory;
+ LemmaProofRecipe* proofRecipe = NULL;
+ PROOF(proofRecipe = new LemmaProofRecipe;);
+
+ Node theoryExplanation = d_theoryEngine->getExplanationAndRecipe(lNode, proofRecipe);
PROOF({
- ProofManager::getCnfProof()->pushCurrentAssertion(explanationNode);
- ProofManager::getCnfProof()->setExplainerTheory(explainerTheory);
+ ProofManager::getCnfProof()->pushCurrentAssertion(theoryExplanation);
+ ProofManager::getCnfProof()->setProofRecipe(proofRecipe);
+
+ Debug("pf::sat") << "TheoryProxy::explainPropagation: setting lemma recipe to: "
+ << std::endl;
+ proofRecipe->dump("pf::sat");
- Debug("pf::sat") << "TheoryProxy::explainPropagation: setting explainer theory to: "
- << explainerTheory << std::endl;
+ delete proofRecipe;
+ proofRecipe = NULL;
});
- Debug("prop-explain") << "explainPropagation() => " << explanationNode << std::endl;
- if (explanationNode.getKind() == kind::AND) {
- Node::const_iterator it = explanationNode.begin();
- Node::const_iterator it_end = explanationNode.end();
+ Debug("prop-explain") << "explainPropagation() => " << theoryExplanation << std::endl;
+ if (theoryExplanation.getKind() == kind::AND) {
+ Node::const_iterator it = theoryExplanation.begin();
+ Node::const_iterator it_end = theoryExplanation.end();
explanation.push_back(l);
for (; it != it_end; ++ it) {
explanation.push_back(~d_cnfStream->getLiteral(*it));
}
} else {
explanation.push_back(l);
- explanation.push_back(~d_cnfStream->getLiteral(explanationNode));
+ explanation.push_back(~d_cnfStream->getLiteral(theoryExplanation));
}
}
@@ -175,7 +180,9 @@ void TheoryProxy::notifyRestart() {
if(lemmaCount % 1 == 0) {
Debug("shared") << "=) " << asNode << std::endl;
}
- d_propEngine->assertLemma(d_theoryEngine->preprocess(asNode), false, true, RULE_INVALID, theory::THEORY_LAST);
+
+ LemmaProofRecipe* noProofRecipe = NULL;
+ d_propEngine->assertLemma(d_theoryEngine->preprocess(asNode), false, true, RULE_INVALID, noProofRecipe);
} else {
Debug("shared") << "=(" << asNode << std::endl;
}
diff --git a/src/smt/boolean_terms.cpp b/src/smt/boolean_terms.cpp
index 40b757598..8957ad7f7 100644
--- a/src/smt/boolean_terms.cpp
+++ b/src/smt/boolean_terms.cpp
@@ -458,7 +458,7 @@ Node BooleanTermConverter::rewriteBooleanTermsRec(TNode top, theory::TheoryId pa
goto next_worklist;
}
- if(parentTheory != theory::THEORY_BOOL && top.getType().isBoolean()) {
+ if(parentTheory != theory::THEORY_BOOL && top.getType().isBoolean() && top.getKind()!=kind::SEP_STAR && top.getKind()!=kind::SEP_WAND) {
// still need to rewrite e.g. function applications over boolean
Node topRewritten = rewriteBooleanTermsRec(top, theory::THEORY_BOOL, quantBoolVars);
Node n;
@@ -682,20 +682,22 @@ Node BooleanTermConverter::rewriteBooleanTermsRec(TNode top, theory::TheoryId pa
goto next_worklist;
}
} else if(!t.isSort() && t.getNumChildren() > 0) {
- for(TypeNode::iterator i = t.begin(); i != t.end(); ++i) {
- if((*i).isBoolean()) {
- vector<TypeNode> argTypes(t.begin(), t.end());
- replace(argTypes.begin(), argTypes.end(), *i, d_tt.getType());
- TypeNode newType = nm->mkTypeNode(t.getKind(), argTypes);
- Node n = nm->mkSkolem(top.getAttribute(expr::VarNameAttr()),
- newType, "a variable introduced by Boolean-term conversion",
- NodeManager::SKOLEM_EXACT_NAME);
- Debug("boolean-terms") << "constructed: " << n << " of type " << newType << endl;
- top.setAttribute(BooleanTermAttr(), n);
- d_varCache[top] = n;
- result.top() << n;
- worklist.pop();
- goto next_worklist;
+ if( t.getKind()!=kind::SEP_STAR && t.getKind()!=kind::SEP_WAND ){
+ for(TypeNode::iterator i = t.begin(); i != t.end(); ++i) {
+ if((*i).isBoolean()) {
+ vector<TypeNode> argTypes(t.begin(), t.end());
+ replace(argTypes.begin(), argTypes.end(), *i, d_tt.getType());
+ TypeNode newType = nm->mkTypeNode(t.getKind(), argTypes);
+ Node n = nm->mkSkolem(top.getAttribute(expr::VarNameAttr()),
+ newType, "a variable introduced by Boolean-term conversion",
+ NodeManager::SKOLEM_EXACT_NAME);
+ Debug("boolean-terms") << "constructed: " << n << " of type " << newType << endl;
+ top.setAttribute(BooleanTermAttr(), n);
+ d_varCache[top] = n;
+ result.top() << n;
+ worklist.pop();
+ goto next_worklist;
+ }
}
}
}
@@ -714,6 +716,8 @@ Node BooleanTermConverter::rewriteBooleanTermsRec(TNode top, theory::TheoryId pa
case kind::RR_REWRITE:
case kind::RR_DEDUCTION:
case kind::RR_REDUCTION:
+ case kind::SEP_STAR:
+ case kind::SEP_WAND:
// not yet supported
result.top() << top;
worklist.pop();
diff --git a/src/smt/smt_engine.cpp b/src/smt/smt_engine.cpp
index 5bd1cbdfc..08495c936 100644
--- a/src/smt/smt_engine.cpp
+++ b/src/smt/smt_engine.cpp
@@ -94,6 +94,7 @@
#include "theory/quantifiers/quantifiers_rewriter.h"
#include "theory/sort_inference.h"
#include "theory/strings/theory_strings.h"
+#include "theory/sep/theory_sep.h"
#include "theory/substitutions.h"
#include "theory/theory_engine.h"
#include "theory/theory_model.h"
@@ -552,10 +553,10 @@ class SmtEnginePrivate : public NodeManagerListener {
*/
unsigned d_simplifyAssertionsDepth;
- /** whether certain preprocess steps are necessary */
- bool d_needsExpandDefs;
- bool d_needsRewriteBoolTerms;
- bool d_needsConstrainSubTypes;
+ /** TODO: whether certain preprocess steps are necessary */
+ //bool d_needsExpandDefs;
+ //bool d_needsRewriteBoolTerms;
+ //bool d_needsConstrainSubTypes;
public:
/**
@@ -684,9 +685,9 @@ public:
d_abstractValueMap(&d_fakeContext),
d_abstractValues(),
d_simplifyAssertionsDepth(0),
- d_needsExpandDefs(true),
- d_needsRewriteBoolTerms(true),
- d_needsConstrainSubTypes(true), //TODO
+ //d_needsExpandDefs(true),
+ //d_needsRewriteBoolTerms(true),
+ //d_needsConstrainSubTypes(true), //TODO
d_iteSkolemMap(),
d_iteRemover(smt.d_userContext),
d_pbsProcessor(smt.d_userContext),
@@ -990,7 +991,7 @@ public:
Trace("smt-qe-debug") << " return : " << ret << std::endl;
//recursive (for nested quantification)
ret = replaceQuantifiersWithInstantiations( reti, insts, visited );
- }
+ }
}else if( n.getNumChildren()>0 ){
bool childChanged = false;
std::vector< Node > children;
@@ -1061,12 +1062,16 @@ SmtEngine::SmtEngine(ExprManager* em) throw() :
// The ProofManager is constructed before any other proof objects such as
// SatProof and TheoryProofs. The TheoryProofEngine and the SatProof are
- // initialized in TheoryEngine and PropEngine respectively.
+ // initialized in TheoryEngine and PropEngine respectively.
Assert(d_proofManager == NULL);
+
+ // d_proofManager must be created before Options has been finished
+ // being parsed from the input file. Because of this, we cannot trust
+ // that options::proof() is set correctly yet.
#ifdef CVC4_PROOF
d_proofManager = new ProofManager();
#endif
-
+
// We have mutual dependency here, so we add the prop engine to the theory
// engine later (it is non-essential there)
d_theoryEngine = new TheoryEngine(d_context, d_userContext,
@@ -1078,7 +1083,9 @@ SmtEngine::SmtEngine(ExprManager* em) throw() :
for(TheoryId id = theory::THEORY_FIRST; id < theory::THEORY_LAST; ++id) {
TheoryConstructor::addTheory(d_theoryEngine, id);
//register with proof engine if applicable
- THEORY_PROOF(ProofManager::currentPM()->getTheoryProofEngine()->registerTheory(d_theoryEngine->theoryOf(id)); );
+#ifdef CVC4_PROOF
+ ProofManager::currentPM()->getTheoryProofEngine()->registerTheory(d_theoryEngine->theoryOf(id));
+#endif
}
d_private->addUseTheoryListListener(d_theoryEngine);
@@ -1100,7 +1107,7 @@ void SmtEngine::finishInit() {
Trace("smt-debug") << "SmtEngine::finishInit" << std::endl;
// ensure that our heuristics are properly set up
setDefaults();
-
+
Trace("smt-debug") << "Making decision engine..." << std::endl;
d_decisionEngine = new DecisionEngine(d_context, d_userContext);
@@ -1147,6 +1154,13 @@ void SmtEngine::finishInit() {
d_dumpCommands.clear();
PROOF( ProofManager::currentPM()->setLogic(d_logic); );
+ PROOF({
+ for(TheoryId id = theory::THEORY_FIRST; id < theory::THEORY_LAST; ++id) {
+ ProofManager::currentPM()->getTheoryProofEngine()->
+ finishRegisterTheory(d_theoryEngine->theoryOf(id));
+ }
+ });
+
Trace("smt-debug") << "SmtEngine::finishInit done" << std::endl;
}
@@ -1237,8 +1251,14 @@ SmtEngine::~SmtEngine() throw() {
delete d_decisionEngine;
d_decisionEngine = NULL;
- PROOF(delete d_proofManager;);
- PROOF(d_proofManager = NULL;);
+
+// d_proofManager is always created when proofs are enabled at configure time.
+// Becuase of this, this code should not be wrapped in PROOF() which
+// additionally checks flags such as options::proof().
+#ifdef CVC4_PROOF
+ delete d_proofManager;
+ d_proofManager = NULL;
+#endif
delete d_stats;
d_stats = NULL;
@@ -1306,9 +1326,9 @@ void SmtEngine::setDefaults() {
}
else if (options::solveIntAsBV() > 0) {
d_logic = LogicInfo("QF_BV");
- // } else if (d_logic.getLogicString() == "QF_UFBV" &&
- // options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
- // d_logic = LogicInfo("QF_BV");
+ } else if (d_logic.getLogicString() == "QF_UFBV" &&
+ options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
+ d_logic = LogicInfo("QF_BV");
}
// set strings-exp
@@ -1333,6 +1353,10 @@ void SmtEngine::setDefaults() {
options::fmfBoundInt.set( true );
Trace("smt") << "turning on fmf-bound-int, for strings-exp" << std::endl;
}
+ if(! options::fmfInstEngine.wasSetByUser()) {
+ options::fmfInstEngine.set( true );
+ Trace("smt") << "turning on fmf-inst-engine, for strings-exp" << std::endl;
+ }
/*
if(! options::rewriteDivk.wasSetByUser()) {
options::rewriteDivk.set( true );
@@ -1709,20 +1733,24 @@ void SmtEngine::setDefaults() {
//must have finite model finding on
options::finiteModelFind.set( true );
}
-
+
//if it contains a theory with non-termination, do not strictly enforce that quantifiers and theory combination must be interleaved
if( d_logic.isTheoryEnabled(THEORY_STRINGS) || (d_logic.isTheoryEnabled(THEORY_ARITH) && !d_logic.isLinear()) ){
if( !options::instWhenStrictInterleave.wasSetByUser() ){
options::instWhenStrictInterleave.set( false );
}
}
-
+
//local theory extensions
if( options::localTheoryExt() ){
if( !options::instMaxLevel.wasSetByUser() ){
options::instMaxLevel.set( 0 );
}
}
+ if( options::instMaxLevel()!=-1 ){
+ Notice() << "SmtEngine: turning off cbqi to support instMaxLevel" << endl;
+ options::cbqi.set(false);
+ }
if(options::fmfBoundIntLazy.wasSetByUser() && options::fmfBoundIntLazy()) {
options::fmfBoundInt.set( true );
@@ -1783,13 +1811,15 @@ void SmtEngine::setDefaults() {
}
//apply counterexample guided instantiation options
- if( options::cegqiSingleInv() ){
- options::ceGuidedInst.set( true );
+ if( options::cegqiSingleInvMode()!=quantifiers::CEGQI_SI_MODE_NONE ){
+ if( !options::ceGuidedInst.wasSetByUser() ){
+ options::ceGuidedInst.set( true );
+ }
}
if( options::ceGuidedInst() ){
//counterexample-guided instantiation for sygus
- if( !options::cegqiSingleInv.wasSetByUser() ){
- options::cegqiSingleInv.set( true );
+ if( !options::cegqiSingleInvMode.wasSetByUser() ){
+ options::cegqiSingleInvMode.set( quantifiers::CEGQI_SI_MODE_USE );
}
if( !options::quantConflictFind.wasSetByUser() ){
options::quantConflictFind.set( false );
@@ -1824,8 +1854,8 @@ void SmtEngine::setDefaults() {
}
}
//counterexample-guided instantiation for non-sygus
- // enable if any quantifiers with arithmetic or datatypes
- if( ( d_logic.isQuantified() && ( d_logic.isTheoryEnabled(THEORY_ARITH) || d_logic.isTheoryEnabled(THEORY_DATATYPES) ) ) ||
+ // enable if any possible quantifiers with arithmetic, datatypes or bitvectors
+ if( ( d_logic.isQuantified() && ( d_logic.isTheoryEnabled(THEORY_ARITH) || d_logic.isTheoryEnabled(THEORY_DATATYPES) || d_logic.isTheoryEnabled(THEORY_BV) ) ) ||
options::cbqiAll() ){
if( !options::cbqi.wasSetByUser() ){
options::cbqi.set( true );
@@ -2583,8 +2613,9 @@ Node SmtEnginePrivate::intToBV(TNode n, NodeMap& cache) {
case kind::CONST_RATIONAL: {
Rational constant = current.getConst<Rational>();
AlwaysAssert(constant.isIntegral());
+ AlwaysAssert(constant >= 0);
BitVector bv(size, constant.getNumerator());
- if (bv.getValue() != constant.getNumerator()) {
+ if (bv.toSignedInt() != constant.getNumerator()) {
throw TypeCheckingException(current.toExpr(), string("Not enough bits for constant in intToBV: ") + current.toString());
}
result = nm->mkConst(bv);
@@ -3837,7 +3868,7 @@ void SmtEnginePrivate::processAssertions() {
ProofManager::currentPM()->addAssertion(d_assertions[i].toExpr());
}
);
-
+
Debug("smt") << " d_assertions : " << d_assertions.size() << endl;
if( options::ceGuidedInst() ){
@@ -3856,8 +3887,8 @@ void SmtEnginePrivate::processAssertions() {
}
if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER &&
- !d_smt.d_logic.isPure(THEORY_BV)) {
- // && d_smt.d_logic.getLogicString() != "QF_UFBV")
+ !d_smt.d_logic.isPure(THEORY_BV) &&
+ d_smt.d_logic.getLogicString() != "QF_UFBV") {
throw ModalException("Eager bit-blasting does not currently support theory combination. "
"Note that in a QF_BV problem UF symbols can be introduced for division. "
"Try --bv-div-zero-const to interpret division by zero as a constant.");
@@ -3885,7 +3916,6 @@ void SmtEnginePrivate::processAssertions() {
Debug("smt") << " d_assertions : " << d_assertions.size() << endl;
-
dumpAssertions("pre-constrain-subtypes", d_assertions);
{
// Any variables of subtype types need to be constrained properly.
@@ -3965,6 +3995,10 @@ void SmtEnginePrivate::processAssertions() {
Trace("smt-proc") << "SmtEnginePrivate::processAssertions() : post-strings-preprocess" << endl;
dumpAssertions("post-strings-pp", d_assertions);
}
+ if( d_smt.d_logic.isTheoryEnabled(THEORY_SEP) ) {
+ //separation logic solver needs to register the entire input
+ ((theory::sep::TheorySep*)d_smt.d_theoryEngine->theoryOf(THEORY_SEP))->processAssertions( d_assertions.ref() );
+ }
if( d_smt.d_logic.isQuantified() ){
Trace("smt-proc") << "SmtEnginePrivate::processAssertions() : pre-quant-preprocess" << endl;
//remove rewrite rules
@@ -4220,7 +4254,7 @@ void SmtEnginePrivate::processAssertions() {
Trace("smt-proc") << "SmtEnginePrivate::processAssertions() end" << endl;
dumpAssertions("post-everything", d_assertions);
-
+
//set instantiation level of everything to zero
if( options::instLevelInputOnly() && options::instMaxLevel()!=-1 ){
@@ -4410,74 +4444,75 @@ Result SmtEngine::checkSynth(const Expr& e) throw(TypeCheckingException, ModalEx
Trace("smt-synth") << "Check synthesis conjecture: " << e << std::endl;
Expr e_check = e;
Node conj = Node::fromExpr( e );
- Assert( conj.getKind()==kind::FORALL );
- //possibly run quantifier elimination to make formula into single invocation
- if( conj[1].getKind()==kind::EXISTS ){
- Node conj_se = conj[1][1];
-
- Trace("smt-synth") << "Compute single invocation for " << conj_se << "..." << std::endl;
- quantifiers::SingleInvocationPartition sip( kind::APPLY );
- sip.init( conj_se );
- Trace("smt-synth") << "...finished, got:" << std::endl;
- sip.debugPrint("smt-synth");
-
- if( !sip.isPurelySingleInvocation() && sip.isNonGroundSingleInvocation() ){
- //We are in the case where our synthesis conjecture is exists f. forall xy. P( f( x ), x, y ), P does not contain f.
- //The following will run QE on (exists z x.) exists y. P( z, x, y ) to obtain Q( z, x ),
- // and then constructs exists f. forall x. Q( f( x ), x ), where Q does not contain f. We invoke synthesis solver on this result.
-
- //create new smt engine to do quantifier elimination
- SmtEngine smt_qe( d_exprManager );
- smt_qe.setLogic(getLogicInfo());
- Trace("smt-synth") << "Property is non-ground single invocation, run QE to obtain single invocation." << std::endl;
- //partition variables
- std::vector< Node > qe_vars;
- std::vector< Node > nqe_vars;
- for( unsigned i=0; i<sip.d_all_vars.size(); i++ ){
- Node v = sip.d_all_vars[i];
- if( std::find( sip.d_si_vars.begin(), sip.d_si_vars.end(), v )==sip.d_si_vars.end() ){
- qe_vars.push_back( v );
- }else{
- nqe_vars.push_back( v );
+ if( conj.getKind()==kind::FORALL ){
+ //possibly run quantifier elimination to make formula into single invocation
+ if( conj[1].getKind()==kind::EXISTS ){
+ Node conj_se = conj[1][1];
+
+ Trace("smt-synth") << "Compute single invocation for " << conj_se << "..." << std::endl;
+ quantifiers::SingleInvocationPartition sip( kind::APPLY );
+ sip.init( conj_se );
+ Trace("smt-synth") << "...finished, got:" << std::endl;
+ sip.debugPrint("smt-synth");
+
+ if( !sip.isPurelySingleInvocation() && sip.isNonGroundSingleInvocation() ){
+ //We are in the case where our synthesis conjecture is exists f. forall xy. P( f( x ), x, y ), P does not contain f.
+ //The following will run QE on (exists z x.) exists y. P( z, x, y ) to obtain Q( z, x ),
+ // and then constructs exists f. forall x. Q( f( x ), x ), where Q does not contain f. We invoke synthesis solver on this result.
+
+ //create new smt engine to do quantifier elimination
+ SmtEngine smt_qe( d_exprManager );
+ smt_qe.setLogic(getLogicInfo());
+ Trace("smt-synth") << "Property is non-ground single invocation, run QE to obtain single invocation." << std::endl;
+ //partition variables
+ std::vector< Node > qe_vars;
+ std::vector< Node > nqe_vars;
+ for( unsigned i=0; i<sip.d_all_vars.size(); i++ ){
+ Node v = sip.d_all_vars[i];
+ if( std::find( sip.d_si_vars.begin(), sip.d_si_vars.end(), v )==sip.d_si_vars.end() ){
+ qe_vars.push_back( v );
+ }else{
+ nqe_vars.push_back( v );
+ }
}
+ std::vector< Node > orig;
+ std::vector< Node > subs;
+ //skolemize non-qe variables
+ for( unsigned i=0; i<nqe_vars.size(); i++ ){
+ Node k = NodeManager::currentNM()->mkSkolem( "k", nqe_vars[i].getType(), "qe for non-ground single invocation" );
+ orig.push_back( nqe_vars[i] );
+ subs.push_back( k );
+ Trace("smt-synth") << " subs : " << nqe_vars[i] << " -> " << k << std::endl;
+ }
+ for( std::map< Node, bool >::iterator it = sip.d_funcs.begin(); it != sip.d_funcs.end(); ++it ){
+ orig.push_back( sip.d_func_inv[it->first] );
+ Node k = NodeManager::currentNM()->mkSkolem( "k", sip.d_func_fo_var[it->first].getType(), "qe for function in non-ground single invocation" );
+ subs.push_back( k );
+ Trace("smt-synth") << " subs : " << sip.d_func_inv[it->first] << " -> " << k << std::endl;
+ }
+ Node conj_se_ngsi = sip.getFullSpecification();
+ Node conj_se_ngsi_subs = conj_se_ngsi.substitute( orig.begin(), orig.end(), subs.begin(), subs.end() );
+ Assert( !qe_vars.empty() );
+ conj_se_ngsi_subs = NodeManager::currentNM()->mkNode( kind::EXISTS, NodeManager::currentNM()->mkNode( kind::BOUND_VAR_LIST, qe_vars ), conj_se_ngsi_subs );
+
+ Trace("smt-synth") << "Run quantifier elimination on " << conj_se_ngsi_subs << std::endl;
+ Expr qe_res = smt_qe.doQuantifierElimination( conj_se_ngsi_subs.toExpr(), true, false );
+ Trace("smt-synth") << "Result : " << qe_res << std::endl;
+
+ //create single invocation conjecture
+ Node qe_res_n = Node::fromExpr( qe_res );
+ qe_res_n = qe_res_n.substitute( subs.begin(), subs.end(), orig.begin(), orig.end() );
+ if( !nqe_vars.empty() ){
+ qe_res_n = NodeManager::currentNM()->mkNode( kind::EXISTS, NodeManager::currentNM()->mkNode( kind::BOUND_VAR_LIST, nqe_vars ), qe_res_n );
+ }
+ Assert( conj.getNumChildren()==3 );
+ qe_res_n = NodeManager::currentNM()->mkNode( kind::FORALL, conj[0], qe_res_n, conj[2] );
+ Trace("smt-synth") << "Converted conjecture after QE : " << qe_res_n << std::endl;
+ e_check = qe_res_n.toExpr();
}
- std::vector< Node > orig;
- std::vector< Node > subs;
- //skolemize non-qe variables
- for( unsigned i=0; i<nqe_vars.size(); i++ ){
- Node k = NodeManager::currentNM()->mkSkolem( "k", nqe_vars[i].getType(), "qe for non-ground single invocation" );
- orig.push_back( nqe_vars[i] );
- subs.push_back( k );
- Trace("smt-synth") << " subs : " << nqe_vars[i] << " -> " << k << std::endl;
- }
- for( std::map< Node, bool >::iterator it = sip.d_funcs.begin(); it != sip.d_funcs.end(); ++it ){
- orig.push_back( sip.d_func_inv[it->first] );
- Node k = NodeManager::currentNM()->mkSkolem( "k", sip.d_func_fo_var[it->first].getType(), "qe for function in non-ground single invocation" );
- subs.push_back( k );
- Trace("smt-synth") << " subs : " << sip.d_func_inv[it->first] << " -> " << k << std::endl;
- }
- Node conj_se_ngsi = sip.getFullSpecification();
- Node conj_se_ngsi_subs = conj_se_ngsi.substitute( orig.begin(), orig.end(), subs.begin(), subs.end() );
- Assert( !qe_vars.empty() );
- conj_se_ngsi_subs = NodeManager::currentNM()->mkNode( kind::EXISTS, NodeManager::currentNM()->mkNode( kind::BOUND_VAR_LIST, qe_vars ), conj_se_ngsi_subs );
-
- Trace("smt-synth") << "Run quantifier elimination on " << conj_se_ngsi_subs << std::endl;
- Expr qe_res = smt_qe.doQuantifierElimination( conj_se_ngsi_subs.toExpr(), true, false );
- Trace("smt-synth") << "Result : " << qe_res << std::endl;
-
- //create single invocation conjecture
- Node qe_res_n = Node::fromExpr( qe_res );
- qe_res_n = qe_res_n.substitute( subs.begin(), subs.end(), orig.begin(), orig.end() );
- if( !nqe_vars.empty() ){
- qe_res_n = NodeManager::currentNM()->mkNode( kind::EXISTS, NodeManager::currentNM()->mkNode( kind::BOUND_VAR_LIST, nqe_vars ), qe_res_n );
- }
- Assert( conj.getNumChildren()==3 );
- qe_res_n = NodeManager::currentNM()->mkNode( kind::FORALL, conj[0], qe_res_n, conj[2] );
- Trace("smt-synth") << "Converted conjecture after QE : " << qe_res_n << std::endl;
- e_check = qe_res_n.toExpr();
}
}
-
+
return checkSatisfiability( e_check, true, false );
}
@@ -5104,7 +5139,7 @@ Expr SmtEngine::doQuantifierElimination(const Expr& e, bool doFull, bool strict)
Warning() << "Unexpected logic for quantifier elimination " << d_logic << endl;
}
Trace("smt-qe") << "Do quantifier elimination " << e << std::endl;
- Node n_e = Node::fromExpr( e );
+ Node n_e = Node::fromExpr( e );
if( n_e.getKind()!=kind::EXISTS ){
throw ModalException("Expecting an existentially quantified formula as argument to get-qe.");
}
@@ -5131,7 +5166,7 @@ Expr SmtEngine::doQuantifierElimination(const Expr& e, bool doFull, bool strict)
InternalError(ss.str().c_str());
}
//get the instantiations for all quantified formulas
- std::map< Node, std::vector< Node > > insts;
+ std::map< Node, std::vector< Node > > insts;
d_theoryEngine->getInstantiations( insts );
//find the quantified formula that corresponds to the input
Node top_q;
diff --git a/src/smt/smt_engine_check_proof.cpp b/src/smt/smt_engine_check_proof.cpp
index 5634a4651..808f5162c 100644
--- a/src/smt/smt_engine_check_proof.cpp
+++ b/src/smt/smt_engine_check_proof.cpp
@@ -63,14 +63,21 @@ void SmtEngine::checkProof() {
Chat() << "checking proof..." << endl;
- if ( !(d_logic.isPure(theory::THEORY_BOOL) ||
- d_logic.isPure(theory::THEORY_BV) ||
- d_logic.isPure(theory::THEORY_ARRAY) ||
- (d_logic.isPure(theory::THEORY_UF) &&
- ! d_logic.hasCardinalityConstraints())) ||
- d_logic.isQuantified()) {
- // no checking for these yet
- Notice() << "Notice: no proof-checking for non-UF/Bool/BV proofs yet" << endl;
+ std::string logicString = d_logic.getLogicString();
+
+ if (!(
+ // Pure logics
+ logicString == "QF_UF" ||
+ logicString == "QF_AX" ||
+ logicString == "QF_BV" ||
+ // Non-pure logics
+ logicString == "QF_AUF" ||
+ logicString == "QF_UFBV" ||
+ logicString == "QF_ABV" ||
+ logicString == "QF_AUFBV"
+ )) {
+ // This logic is not yet supported
+ Notice() << "Notice: no proof-checking for " << logicString << " proofs yet" << endl;
return;
}
diff --git a/src/smt/smt_engine_scope.h b/src/smt/smt_engine_scope.h
index e00be40d4..9407ff498 100644
--- a/src/smt/smt_engine_scope.h
+++ b/src/smt/smt_engine_scope.h
@@ -49,7 +49,6 @@ inline bool smtEngineInScope() {
// FIXME: Maybe move into SmtScope?
inline ProofManager* currentProofManager() {
#if IS_PROOFS_BUILD
- Assert(options::proof() || options::unsatCores());
Assert(s_smtEngine_current != NULL);
return s_smtEngine_current->d_proofManager;
#else /* IS_PROOFS_BUILD */
diff --git a/src/theory/arrays/array_proof_reconstruction.cpp b/src/theory/arrays/array_proof_reconstruction.cpp
index 11c3dc081..6dfd14157 100644
--- a/src/theory/arrays/array_proof_reconstruction.cpp
+++ b/src/theory/arrays/array_proof_reconstruction.cpp
@@ -101,8 +101,59 @@ void ArrayProofReconstruction::notify(unsigned reasonType, Node reason, Node a,
Debug("pf::ee") << "Getting explanation for ROW guard: "
<< indexOne << " != " << indexTwo << std::endl;
+
eq::EqProof* childProof = new eq::EqProof;
d_equalityEngine->explainEquality(indexOne, indexTwo, false, equalities, childProof);
+
+ // It could be that the guard condition is a constant disequality. In this case,
+ // we need to change it to a different format.
+ if (childProof->d_id == theory::eq::MERGED_THROUGH_CONSTANTS) {
+ // The proof has two children, explaining why each index is a (different) constant.
+ Assert(childProof->d_children.size() == 2);
+
+ Node constantOne, constantTwo;
+ // Each subproof explains why one of the indices is constant.
+
+ if (childProof->d_children[0]->d_id == theory::eq::MERGED_THROUGH_REFLEXIVITY) {
+ constantOne = childProof->d_children[0]->d_node;
+ } else {
+ Assert(childProof->d_children[0]->d_id == theory::eq::MERGED_THROUGH_EQUALITY);
+ if ((childProof->d_children[0]->d_node[0] == indexOne) ||
+ (childProof->d_children[0]->d_node[0] == indexTwo)) {
+ constantOne = childProof->d_children[0]->d_node[1];
+ } else {
+ constantOne = childProof->d_children[0]->d_node[0];
+ }
+ }
+
+ if (childProof->d_children[1]->d_id == theory::eq::MERGED_THROUGH_REFLEXIVITY) {
+ constantTwo = childProof->d_children[1]->d_node;
+ } else {
+ Assert(childProof->d_children[1]->d_id == theory::eq::MERGED_THROUGH_EQUALITY);
+ if ((childProof->d_children[1]->d_node[0] == indexOne) ||
+ (childProof->d_children[1]->d_node[0] == indexTwo)) {
+ constantTwo = childProof->d_children[1]->d_node[1];
+ } else {
+ constantTwo = childProof->d_children[1]->d_node[0];
+ }
+ }
+
+ eq::EqProof* constantDisequalityProof = new eq::EqProof;
+ constantDisequalityProof->d_id = theory::eq::MERGED_THROUGH_CONSTANTS;
+ constantDisequalityProof->d_node =
+ NodeManager::currentNM()->mkNode(kind::EQUAL, constantOne, constantTwo).negate();
+
+ // Middle is where we need to insert the new disequality
+ std::vector<eq::EqProof *>::iterator middle = childProof->d_children.begin();
+ ++middle;
+
+ childProof->d_children.insert(middle, constantDisequalityProof);
+
+ childProof->d_id = theory::eq::MERGED_THROUGH_TRANS;
+ childProof->d_node =
+ NodeManager::currentNM()->mkNode(kind::EQUAL, indexOne, indexTwo).negate();
+ }
+
proof->d_children.push_back(childProof);
} else {
// This is the case of (i == k) because ((a[i]:=t)[k] != a[k]),
diff --git a/src/theory/arrays/theory_arrays.cpp b/src/theory/arrays/theory_arrays.cpp
index 6add1b55f..28a08630e 100644
--- a/src/theory/arrays/theory_arrays.cpp
+++ b/src/theory/arrays/theory_arrays.cpp
@@ -829,7 +829,8 @@ void TheoryArrays::propagate(Effort e)
Node TheoryArrays::explain(TNode literal) {
- return explain(literal, NULL);
+ Node explanation = explain(literal, NULL);
+ return explanation;
}
Node TheoryArrays::explain(TNode literal, eq::EqProof *proof)
@@ -1394,6 +1395,7 @@ void TheoryArrays::check(Effort e) {
break;
default:
Unreachable();
+ break;
}
}
@@ -2231,6 +2233,7 @@ bool TheoryArrays::dischargeLemmas()
void TheoryArrays::conflict(TNode a, TNode b) {
Debug("pf::array") << "TheoryArrays::Conflict called" << std::endl;
eq::EqProof* proof = d_proofsEnabled ? new eq::EqProof() : NULL;
+
if (a.getKind() == kind::CONST_BOOLEAN) {
d_conflictNode = explain(a.iffNode(b), proof);
} else {
diff --git a/src/theory/bv/abstraction.cpp b/src/theory/bv/abstraction.cpp
index fdc36ce72..dc5520411 100644
--- a/src/theory/bv/abstraction.cpp
+++ b/src/theory/bv/abstraction.cpp
@@ -41,7 +41,7 @@ bool AbstractionModule::applyAbstraction(const std::vector<Node>& assertions, st
continue;
}
Node signature = computeSignature(assertions[i][j]);
- storeSignature(signature, assertions[i][j]);
+ storeSignature(signature, assertions[i][j]);
Debug("bv-abstraction") << " assertion: " << assertions[i][j] <<"\n";
Debug("bv-abstraction") << " signature: " << signature <<"\n";
}
@@ -52,7 +52,7 @@ bool AbstractionModule::applyAbstraction(const std::vector<Node>& assertions, st
for (unsigned i = 0; i < assertions.size(); ++i) {
if (assertions[i].getKind() == kind::OR &&
assertions[i][0].getKind() == kind::AND) {
- std::vector<Node> new_children;
+ std::vector<Node> new_children;
for (unsigned j = 0; j < assertions[i].getNumChildren(); ++j) {
if (hasSignature(assertions[i][j])) {
new_children.push_back(abstractSignatures(assertions[i][j]));
@@ -60,10 +60,10 @@ bool AbstractionModule::applyAbstraction(const std::vector<Node>& assertions, st
new_children.push_back(assertions[i][j]);
}
}
- new_assertions.push_back(utils::mkNode(kind::OR, new_children));
+ new_assertions.push_back(utils::mkNode(kind::OR, new_children));
} else {
// assertions that are not changed
- new_assertions.push_back(assertions[i]);
+ new_assertions.push_back(assertions[i]);
}
}
@@ -71,21 +71,21 @@ bool AbstractionModule::applyAbstraction(const std::vector<Node>& assertions, st
skolemizeArguments(new_assertions);
}
-
+
// if we are using the eager solver reverse the abstraction
if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
if (d_funcToSignature.size() == 0) {
// we did not change anything
return false;
}
- NodeNodeMap seen;
+ NodeNodeMap seen;
for (unsigned i = 0; i < new_assertions.size(); ++i) {
- new_assertions[i] = reverseAbstraction(new_assertions[i], seen);
+ new_assertions[i] = reverseAbstraction(new_assertions[i], seen);
}
// we undo the abstraction functions so the logic is QF_BV still
- return true;
+ return true;
}
-
+
// return true if we have created new function symbols for the problem
return d_funcToSignature.size() != 0;
}
@@ -99,7 +99,7 @@ bool AbstractionModule::isConjunctionOfAtoms(TNode node) {
bool AbstractionModule::isConjunctionOfAtomsRec(TNode node, TNodeSet& seen) {
if (seen.find(node)!= seen.end())
return true;
-
+
if (!node.getType().isBitVector()) {
return (node.getKind() == kind::AND || utils::isBVPredicate(node));
}
@@ -120,30 +120,30 @@ Node AbstractionModule::reverseAbstraction(Node assertion, NodeNodeMap& seen) {
if (seen.find(assertion) != seen.end())
return seen[assertion];
-
+
if (isAbstraction(assertion)) {
Node interp = getInterpretation(assertion);
seen[assertion] = interp;
- Assert (interp.getType() == assertion.getType());
+ Assert (interp.getType() == assertion.getType());
return interp;
}
if (assertion.getNumChildren() == 0) {
seen[assertion] = assertion;
- return assertion;
+ return assertion;
}
-
+
NodeBuilder<> result(assertion.getKind());
if (assertion.getMetaKind() == kind::metakind::PARAMETERIZED) {
- result << assertion.getOperator();
+ result << assertion.getOperator();
}
for (unsigned i = 0; i < assertion.getNumChildren(); ++i) {
- result << reverseAbstraction(assertion[i], seen);
+ result << reverseAbstraction(assertion[i], seen);
}
Node res = result;
seen[assertion] = res;
- return res;
+ return res;
}
void AbstractionModule::skolemizeArguments(std::vector<Node>& assertions) {
@@ -151,7 +151,7 @@ void AbstractionModule::skolemizeArguments(std::vector<Node>& assertions) {
TNode assertion = assertions[i];
if (assertion.getKind() != kind::OR)
continue;
-
+
bool is_skolemizable = true;
for (unsigned k = 0; k < assertion.getNumChildren(); ++k) {
if (assertion[k].getKind() != kind::EQUAL ||
@@ -191,54 +191,54 @@ void AbstractionModule::skolemizeArguments(std::vector<Node>& assertions) {
NodeBuilder<> skolem_func (kind::APPLY_UF);
skolem_func << func;
std::vector<Node> skolem_args;
-
+
for (unsigned j = 0; j < args.getArity(); ++j) {
bool all_same = true;
for (unsigned k = 1; k < args.getNumEntries(); ++k) {
if ( args.getEntry(k)[j] != args.getEntry(0)[j])
- all_same = false;
+ all_same = false;
}
- Node new_arg = all_same ? (Node)args.getEntry(0)[j] : utils::mkVar(utils::getSize(args.getEntry(0)[j]));
+ Node new_arg = all_same ? (Node)args.getEntry(0)[j] : utils::mkVar(utils::getSize(args.getEntry(0)[j]));
skolem_args.push_back(new_arg);
- skolem_func << new_arg;
+ skolem_func << new_arg;
}
-
- Node skolem_func_eq1 = utils::mkNode(kind::EQUAL, (Node)skolem_func, utils::mkConst(1, 1u));
-
+
+ Node skolem_func_eq1 = utils::mkNode(kind::EQUAL, (Node)skolem_func, utils::mkConst(1, 1u));
+
// enumerate arguments assignments
- std::vector<Node> or_assignments;
+ std::vector<Node> or_assignments;
for (ArgsTableEntry::iterator it = args.begin(); it != args.end(); ++it) {
NodeBuilder<> arg_assignment(kind::AND);
ArgsVec& args = *it;
for (unsigned k = 0; k < args.size(); ++k) {
Node eq = utils::mkNode(kind::EQUAL, args[k], skolem_args[k]);
- arg_assignment << eq;
+ arg_assignment << eq;
}
or_assignments.push_back(arg_assignment);
}
-
+
Node new_func_def = utils::mkNode(kind::AND, skolem_func_eq1, utils::mkNode(kind::OR, or_assignments));
- assertion_builder << new_func_def;
+ assertion_builder << new_func_def;
}
Node new_assertion = assertion_builder;
Debug("bv-abstraction-dbg") << "AbstractionModule::skolemizeArguments " << assertions[i] << " => \n";
- Debug("bv-abstraction-dbg") << " " << new_assertion;
+ Debug("bv-abstraction-dbg") << " " << new_assertion;
assertions[i] = new_assertion;
}
}
void AbstractionModule::storeSignature(Node signature, TNode assertion) {
if(d_signatures.find(signature) == d_signatures.end()) {
- d_signatures[signature] = 0;
+ d_signatures[signature] = 0;
}
- d_signatures[signature] = d_signatures[signature] + 1;
- d_assertionToSignature[assertion] = signature;
+ d_signatures[signature] = d_signatures[signature] + 1;
+ d_assertionToSignature[assertion] = signature;
}
Node AbstractionModule::computeSignature(TNode node) {
- resetSignatureIndex();
- NodeNodeMap cache;
+ resetSignatureIndex();
+ NodeNodeMap cache;
Node sig = computeSignatureRec(node, cache);
return sig;
}
@@ -247,17 +247,17 @@ Node AbstractionModule::getSignatureSkolem(TNode node) {
Assert (node.getKind() == kind::VARIABLE);
unsigned bitwidth = utils::getSize(node);
if (d_signatureSkolems.find(bitwidth) == d_signatureSkolems.end()) {
- d_signatureSkolems[bitwidth] = vector<Node>();
+ d_signatureSkolems[bitwidth] = vector<Node>();
}
-
+
vector<Node>& skolems = d_signatureSkolems[bitwidth];
// get the index of bv variables of this size
- unsigned index = getBitwidthIndex(bitwidth);
+ unsigned index = getBitwidthIndex(bitwidth);
Assert (skolems.size() + 1 >= index );
if (skolems.size() == index) {
ostringstream os;
os << "sig_" <<bitwidth <<"_" << index;
- NodeManager* nm = NodeManager::currentNM();
+ NodeManager* nm = NodeManager::currentNM();
skolems.push_back(nm->mkSkolem(os.str(), nm->mkBitVectorType(bitwidth), "skolem for computing signatures"));
}
++(d_signatureIndices[bitwidth]);
@@ -268,12 +268,12 @@ unsigned AbstractionModule::getBitwidthIndex(unsigned bitwidth) {
if (d_signatureIndices.find(bitwidth) == d_signatureIndices.end()) {
d_signatureIndices[bitwidth] = 0;
}
- return d_signatureIndices[bitwidth];
+ return d_signatureIndices[bitwidth];
}
void AbstractionModule::resetSignatureIndex() {
for (IndexMap::iterator it = d_signatureIndices.begin(); it != d_signatureIndices.end(); ++it) {
- it->second = 0;
+ it->second = 0;
}
}
@@ -282,24 +282,24 @@ bool AbstractionModule::hasSignature(Node node) {
}
Node AbstractionModule::getGeneralizedSignature(Node node) {
- NodeNodeMap::const_iterator it = d_assertionToSignature.find(node);
+ NodeNodeMap::const_iterator it = d_assertionToSignature.find(node);
Assert (it != d_assertionToSignature.end());
- Node generalized_signature = getGeneralization(it->second);
- return generalized_signature;
+ Node generalized_signature = getGeneralization(it->second);
+ return generalized_signature;
}
Node AbstractionModule::computeSignatureRec(TNode node, NodeNodeMap& cache) {
if (cache.find(node) != cache.end()) {
- return cache.find(node)->second;
+ return cache.find(node)->second;
}
-
+
if (node.getNumChildren() == 0) {
if (node.getKind() == kind::CONST_BITVECTOR)
return node;
Node sig = getSignatureSkolem(node);
- cache[node] = sig;
- return sig;
+ cache[node] = sig;
+ return sig;
}
NodeBuilder<> builder(node.getKind());
@@ -308,30 +308,30 @@ Node AbstractionModule::computeSignatureRec(TNode node, NodeNodeMap& cache) {
}
for (unsigned i = 0; i < node.getNumChildren(); ++i) {
Node converted = computeSignatureRec(node[i], cache);
- builder << converted;
+ builder << converted;
}
Node result = builder;
cache[node] = result;
- return result;
+ return result;
}
-/**
+/**
* Returns 0, if the two are equal,
* 1 if s is a generalization of t
* 2 if t is a generalization of s
* -1 if the two cannot be unified
*
- * @param s
- * @param t
- *
- * @return
+ * @param s
+ * @param t
+ *
+ * @return
*/
int AbstractionModule::comparePatterns(TNode s, TNode t) {
if (s.getKind() == kind::SKOLEM &&
t.getKind() == kind::SKOLEM) {
return 0;
}
-
+
if (s.getKind() == kind::CONST_BITVECTOR &&
t.getKind() == kind::CONST_BITVECTOR) {
if (s == t) {
@@ -350,7 +350,7 @@ int AbstractionModule::comparePatterns(TNode s, TNode t) {
t.getKind() == kind::SKOLEM) {
return 2;
}
-
+
if (s.getNumChildren() != t.getNumChildren() ||
s.getKind() != t.getKind())
return -1;
@@ -370,26 +370,26 @@ int AbstractionModule::comparePatterns(TNode s, TNode t) {
}
TNode AbstractionModule::getGeneralization(TNode term) {
- NodeNodeMap::iterator it = d_sigToGeneralization.find(term);
+ NodeNodeMap::iterator it = d_sigToGeneralization.find(term);
// if not in the map we add it
if (it == d_sigToGeneralization.end()) {
d_sigToGeneralization[term] = term;
- return term;
+ return term;
}
- // doesn't have a generalization
+ // doesn't have a generalization
if (it->second == term)
return term;
-
+
TNode generalization = getGeneralization(it->second);
Assert (generalization != term);
d_sigToGeneralization[term] = generalization;
- return generalization;
+ return generalization;
}
void AbstractionModule::storeGeneralization(TNode s, TNode t) {
Assert (s == getGeneralization(s));
Assert (t == getGeneralization(t));
- d_sigToGeneralization[s] = t;
+ d_sigToGeneralization[s] = t;
}
void AbstractionModule::finalizeSignatures() {
@@ -402,29 +402,29 @@ void AbstractionModule::finalizeSignatures() {
for (SignatureMap::const_iterator tt = ss; tt != d_signatures.end(); ++tt) {
TNode t = getGeneralization(tt->first);
TNode s = getGeneralization(ss->first);
-
+
if (t != s) {
int status = comparePatterns(s, t);
- Assert (status);
+ Assert (status);
if (status < 0)
continue;
if (status == 1) {
- storeGeneralization(t, s);
+ storeGeneralization(t, s);
} else {
- storeGeneralization(s, t);
+ storeGeneralization(s, t);
}
}
}
}
// keep only most general signatures
for (SignatureMap::iterator it = d_signatures.begin(); it != d_signatures.end(); ) {
- TNode sig = it->first;
+ TNode sig = it->first;
TNode gen = getGeneralization(sig);
if (sig != gen) {
- Assert (d_signatures.find(gen) != d_signatures.end());
+ Assert (d_signatures.find(gen) != d_signatures.end());
// update the count
d_signatures[gen]+= d_signatures[sig];
- d_signatures.erase(it++);
+ d_signatures.erase(it++);
} else {
++it;
}
@@ -434,12 +434,12 @@ void AbstractionModule::finalizeSignatures() {
// remove signatures that are not frequent enough
for (SignatureMap::iterator it = d_signatures.begin(); it != d_signatures.end(); ) {
if (it->second <= 7) {
- d_signatures.erase(it++);
+ d_signatures.erase(it++);
} else {
++it;
}
}
-
+
for (SignatureMap::const_iterator it = d_signatures.begin(); it != d_signatures.end(); ++it) {
TNode signature = it->first;
// we already processed this signature
@@ -451,31 +451,31 @@ void AbstractionModule::finalizeSignatures() {
collectArgumentTypes(signature, arg_types, seen);
Assert (signature.getType().isBoolean());
// make function return a bitvector of size 1
- //Node bv_function = utils::mkNode(kind::ITE, signature, utils::mkConst(1, 1u), utils::mkConst(1, 0u));
+ //Node bv_function = utils::mkNode(kind::ITE, signature, utils::mkConst(1, 1u), utils::mkConst(1, 0u));
TypeNode range = NodeManager::currentNM()->mkBitVectorType(1);
-
+
TypeNode abs_type = nm->mkFunctionType(arg_types, range);
Node abs_func = nm->mkSkolem("abs_$$", abs_type, "abstraction function for bv theory");
Debug("bv-abstraction") << " abstracted by function " << abs_func << "\n";
// NOTE: signature expression type is BOOLEAN
d_signatureToFunc[signature] = abs_func;
- d_funcToSignature[abs_func] = signature;
+ d_funcToSignature[abs_func] = signature;
}
d_statistics.d_numFunctionsAbstracted.setData(d_signatureToFunc.size());
-
+
Debug("bv-abstraction") << "AbstractionModule::finalizeSignatures abstracted " << d_signatureToFunc.size() << " signatures. \n";
}
void AbstractionModule::collectArgumentTypes(TNode sig, std::vector<TypeNode>& types, TNodeSet& seen) {
if (seen.find(sig) != seen.end())
return;
-
+
if (sig.getKind() == kind::SKOLEM) {
types.push_back(sig.getType());
- seen.insert(sig);
- return;
+ seen.insert(sig);
+ return;
}
for (unsigned i = 0; i < sig.getNumChildren(); ++i) {
@@ -487,36 +487,36 @@ void AbstractionModule::collectArgumentTypes(TNode sig, std::vector<TypeNode>& t
void AbstractionModule::collectArguments(TNode node, TNode signature, std::vector<Node>& args, TNodeSet& seen) {
if (seen.find(node)!= seen.end())
return;
-
+
if (node.getKind() == kind::VARIABLE ||
node.getKind() == kind::CONST_BITVECTOR) {
// a constant in the node can either map to an argument of the abstraction
- // or can be hard-coded and part of the abstraction
+ // or can be hard-coded and part of the abstraction
if (signature.getKind() == kind::SKOLEM) {
args.push_back(node);
seen.insert(node);
} else {
- Assert (signature.getKind() == kind::CONST_BITVECTOR);
+ Assert (signature.getKind() == kind::CONST_BITVECTOR);
}
- //
- return;
+ //
+ return;
}
Assert (node.getKind() == signature.getKind() &&
- node.getNumChildren() == signature.getNumChildren());
+ node.getNumChildren() == signature.getNumChildren());
for (unsigned i = 0; i < node.getNumChildren(); ++i) {
- collectArguments(node[i], signature[i], args, seen);
- seen.insert(node);
+ collectArguments(node[i], signature[i], args, seen);
+ seen.insert(node);
}
}
Node AbstractionModule::abstractSignatures(TNode assertion) {
- Debug("bv-abstraction") << "AbstractionModule::abstractSignatures "<< assertion <<"\n";
+ Debug("bv-abstraction") << "AbstractionModule::abstractSignatures "<< assertion <<"\n";
// assume the assertion has been fully abstracted
Node signature = getGeneralizedSignature(assertion);
-
- Debug("bv-abstraction") << " with sig "<< signature <<"\n";
+
+ Debug("bv-abstraction") << " with sig "<< signature <<"\n";
NodeNodeMap::iterator it = d_signatureToFunc.find(signature);
if (it!= d_signatureToFunc.end()) {
std::vector<Node> args;
@@ -527,16 +527,16 @@ Node AbstractionModule::abstractSignatures(TNode assertion) {
collectArguments(assertion, signature, args, seen);
std::vector<TNode> real_args;
for (unsigned i = 1; i < args.size(); ++i) {
- real_args.push_back(args[i]);
+ real_args.push_back(args[i]);
}
- d_argsTable.addEntry(func, real_args);
- Node result = utils::mkNode(kind::EQUAL, utils::mkNode(kind::APPLY_UF, args),
+ d_argsTable.addEntry(func, real_args);
+ Node result = utils::mkNode(kind::EQUAL, utils::mkNode(kind::APPLY_UF, args),
utils::mkConst(1, 1u));
- Debug("bv-abstraction") << "=> "<< result << "\n";
- Assert (result.getType() == assertion.getType());
- return result;
+ Debug("bv-abstraction") << "=> "<< result << "\n";
+ Assert (result.getType() == assertion.getType());
+ return result;
}
- return assertion;
+ return assertion;
}
bool AbstractionModule::isAbstraction(TNode node) {
@@ -557,11 +557,11 @@ bool AbstractionModule::isAbstraction(TNode node) {
if (constant != utils::mkConst(1, 1u))
return false;
- TNode func_symbol = func.getOperator();
+ TNode func_symbol = func.getOperator();
if (d_funcToSignature.find(func_symbol) == d_funcToSignature.end())
return false;
- return true;
+ return true;
}
Node AbstractionModule::getInterpretation(TNode node) {
@@ -571,51 +571,51 @@ Node AbstractionModule::getInterpretation(TNode node) {
Assert (constant.getKind() == kind::CONST_BITVECTOR &&
apply.getKind() == kind::APPLY_UF);
- Node func = apply.getOperator();
+ Node func = apply.getOperator();
Assert (d_funcToSignature.find(func) != d_funcToSignature.end());
-
+
Node sig = d_funcToSignature[func];
-
+
// substitute arguments in signature
TNodeTNodeMap seen;
unsigned index = 0;
Node result = substituteArguments(sig, apply, index, seen);
- Assert (result.getType().isBoolean());
+ Assert (result.getType().isBoolean());
Assert (index == apply.getNumChildren());
// Debug("bv-abstraction") << "AbstractionModule::getInterpretation " << node << "\n";
// Debug("bv-abstraction") << " => " << result << "\n";
- return result;
+ return result;
}
Node AbstractionModule::substituteArguments(TNode signature, TNode apply, unsigned& index, TNodeTNodeMap& seen) {
if (seen.find(signature) != seen.end()) {
- return seen[signature];
+ return seen[signature];
}
-
+
if (signature.getKind() == kind::SKOLEM) {
// return corresponding argument and increment counter
seen[signature] = apply[index];
- return apply[index++];
+ return apply[index++];
}
if (signature.getNumChildren() == 0) {
Assert (signature.getKind() != kind::VARIABLE &&
- signature.getKind() != kind::SKOLEM);
+ signature.getKind() != kind::SKOLEM);
seen[signature] = signature;
- return signature;
+ return signature;
}
-
+
NodeBuilder<> builder(signature.getKind());
if (signature.getMetaKind() == kind::metakind::PARAMETERIZED) {
builder << signature.getOperator();
}
-
+
for (unsigned i = 0; i < signature.getNumChildren(); ++i) {
Node child = substituteArguments(signature[i], apply, index, seen);
- builder << child;
+ builder << child;
}
- Node result = builder;
+ Node result = builder;
seen[signature]= result;
return result;
@@ -625,20 +625,20 @@ Node AbstractionModule::simplifyConflict(TNode conflict) {
if (Dump.isOn("bv-abstraction")) {
NodeNodeMap seen;
Node c = reverseAbstraction(conflict, seen);
- Dump("bv-abstraction") << PushCommand();
+ Dump("bv-abstraction") << PushCommand();
Dump("bv-abstraction") << AssertCommand(c.toExpr());
Dump("bv-abstraction") << CheckSatCommand();
- Dump("bv-abstraction") << PopCommand();
+ Dump("bv-abstraction") << PopCommand();
}
- Debug("bv-abstraction-dbg") << "AbstractionModule::simplifyConflict " << conflict << "\n";
+ Debug("bv-abstraction-dbg") << "AbstractionModule::simplifyConflict " << conflict << "\n";
if (conflict.getKind() != kind::AND)
- return conflict;
+ return conflict;
std::vector<Node> conjuncts;
for (unsigned i = 0; i < conflict.getNumChildren(); ++i)
conjuncts.push_back(conflict[i]);
-
+
theory::SubstitutionMap subst(new context::Context());
for (unsigned i = 0; i < conjuncts.size(); ++i) {
TNode conjunct = conjuncts[i];
@@ -658,12 +658,12 @@ Node AbstractionModule::simplifyConflict(TNode conflict) {
} else {
continue;
}
-
+
Assert (!subst.hasSubstitution(s));
Assert (!t.isNull() &&
!s.isNull() &&
s!= t);
- subst.addSubstitution(s, t);
+ subst.addSubstitution(s, t);
for (unsigned k = 0; k < conjuncts.size(); k++) {
conjuncts[k] = subst.apply(conjuncts[k]);
@@ -671,28 +671,28 @@ Node AbstractionModule::simplifyConflict(TNode conflict) {
}
}
Node new_conflict = Rewriter::rewrite(utils::mkAnd(conjuncts));
-
+
Debug("bv-abstraction") << "AbstractionModule::simplifyConflict conflict " << conflict <<"\n";
Debug("bv-abstraction") << " => " << new_conflict <<"\n";
if (Dump.isOn("bv-abstraction")) {
-
+
NodeNodeMap seen;
Node nc = reverseAbstraction(new_conflict, seen);
- Dump("bv-abstraction") << PushCommand();
+ Dump("bv-abstraction") << PushCommand();
Dump("bv-abstraction") << AssertCommand(nc.toExpr());
Dump("bv-abstraction") << CheckSatCommand();
- Dump("bv-abstraction") << PopCommand();
+ Dump("bv-abstraction") << PopCommand();
}
-
- return new_conflict;
+
+ return new_conflict;
}
void DebugPrintInstantiations(const std::vector< std::vector<ArgsVec> >& instantiations,
const std::vector<TNode> functions) {
// print header
- Debug("bv-abstraction-dbg") <<"[ ";
+ Debug("bv-abstraction-dbg") <<"[ ";
for (unsigned i = 0; i < functions.size(); ++i) {
for (unsigned j = 1; j < functions[i].getNumChildren(); ++j) {
Debug("bv-abstraction-dgb") << functions[i][j] <<" ";
@@ -706,16 +706,16 @@ void DebugPrintInstantiations(const std::vector< std::vector<ArgsVec> >& instant
const std::vector<ArgsVec>& inst = instantiations[i];
for (unsigned j = 0; j < inst.size(); ++j) {
for (unsigned k = 0; k < inst[j].size(); ++k) {
- Debug("bv-abstraction-dbg") << inst[j][k] << " ";
+ Debug("bv-abstraction-dbg") << inst[j][k] << " ";
}
- Debug("bv-abstraction-dbg") << " || ";
+ Debug("bv-abstraction-dbg") << " || ";
}
Debug("bv-abstraction-dbg") <<"]\n";
}
}
void AbstractionModule::generalizeConflict(TNode conflict, std::vector<Node>& lemmas) {
- Debug("bv-abstraction") << "AbstractionModule::generalizeConflict " << conflict << "\n";
+ Debug("bv-abstraction") << "AbstractionModule::generalizeConflict " << conflict << "\n";
std::vector<TNode> functions;
// collect abstract functions
@@ -737,11 +737,11 @@ void AbstractionModule::generalizeConflict(TNode conflict, std::vector<Node>& le
// if (functions.size() >= 3) {
// // dump conflict
// NodeNodeMap seen;
- // Node reversed = reverseAbstraction(conflict, seen);
- // std::cout << "CONFLICT " << reversed << "\n";
+ // Node reversed = reverseAbstraction(conflict, seen);
+ // std::cout << "CONFLICT " << reversed << "\n";
// }
-
+
if (functions.size() == 0 || functions.size() > options::bvNumFunc()) {
return;
}
@@ -751,31 +751,31 @@ void AbstractionModule::generalizeConflict(TNode conflict, std::vector<Node>& le
SubstitutionMap skolem_subst(new context::Context());
SubstitutionMap reverse_skolem(new context::Context());
makeFreshSkolems(conflict, skolem_subst, reverse_skolem);
-
+
Node skolemized_conflict = skolem_subst.apply(conflict);
for (unsigned i = 0; i < functions.size(); ++i) {
functions[i] = skolem_subst.apply(functions[i]);
}
- conflict = skolem_subst.apply(conflict);
+ conflict = skolem_subst.apply(conflict);
LemmaInstantiatior inst(functions, d_argsTable, conflict);
std::vector<Node> new_lemmas;
- inst.generateInstantiations(new_lemmas);
+ inst.generateInstantiations(new_lemmas);
for (unsigned i = 0; i < new_lemmas.size(); ++i) {
TNode lemma = reverse_skolem.apply(new_lemmas[i]);
if (d_addedLemmas.find(lemma) == d_addedLemmas.end()) {
lemmas.push_back(lemma);
- Debug("bv-abstraction-gen") << "adding lemma " << lemma << "\n";
+ Debug("bv-abstraction-gen") << "adding lemma " << lemma << "\n";
storeLemma(lemma);
if (Dump.isOn("bv-abstraction")) {
NodeNodeMap seen;
Node l = reverseAbstraction(lemma, seen);
- Dump("bv-abstraction") << PushCommand();
+ Dump("bv-abstraction") << PushCommand();
Dump("bv-abstraction") << AssertCommand(l.toExpr());
Dump("bv-abstraction") << CheckSatCommand();
- Dump("bv-abstraction") << PopCommand();
+ Dump("bv-abstraction") << PopCommand();
}
}
}
@@ -787,18 +787,18 @@ int AbstractionModule::LemmaInstantiatior::next(int val, int index) {
return -1;
}
-/**
+/**
* Assumes the stack without top is consistent, and checks that the
* full stack is consistent
- *
- * @param stack
- *
- * @return
+ *
+ * @param stack
+ *
+ * @return
*/
bool AbstractionModule::LemmaInstantiatior::isConsistent(const vector<int>& stack) {
if (stack.empty())
return true;
-
+
unsigned current = stack.size() - 1;
TNode func = d_functions[current];
ArgsTableEntry& matches = d_argsTable.getEntry(func.getOperator());
@@ -807,12 +807,12 @@ bool AbstractionModule::LemmaInstantiatior::isConsistent(const vector<int>& stac
for (unsigned k = 0; k < args.size(); ++k) {
TNode s = func[k];
TNode t = args[k];
-
+
TNode s0 = s;
while (d_subst.hasSubstitution(s0)) {
s0 = d_subst.getSubstitution(s0);
}
-
+
TNode t0 = t;
while (d_subst.hasSubstitution(t0)) {
t0 = d_subst.getSubstitution(t0);
@@ -824,7 +824,7 @@ bool AbstractionModule::LemmaInstantiatior::isConsistent(const vector<int>& stac
else
continue;
}
-
+
if(s0.getMetaKind() == kind::metakind::VARIABLE &&
t0.isConst()) {
d_subst.addSubstitution(s0, t0);
@@ -839,12 +839,12 @@ bool AbstractionModule::LemmaInstantiatior::isConsistent(const vector<int>& stac
Assert (s0.getMetaKind() == kind::metakind::VARIABLE &&
t0.getMetaKind() == kind::metakind::VARIABLE);
-
+
if (s0 != t0) {
d_subst.addSubstitution(s0, t0);
}
}
- return true;
+ return true;
}
bool AbstractionModule::LemmaInstantiatior::accept(const vector<int>& stack) {
@@ -854,13 +854,13 @@ bool AbstractionModule::LemmaInstantiatior::accept(const vector<int>& stack) {
void AbstractionModule::LemmaInstantiatior::mkLemma() {
Node lemma = d_subst.apply(d_conflict);
// Debug("bv-abstraction-gen") << "AbstractionModule::LemmaInstantiatior::mkLemma " << lemma <<"\n";
- d_lemmas.push_back(lemma);
+ d_lemmas.push_back(lemma);
}
void AbstractionModule::LemmaInstantiatior::backtrack(vector<int>& stack) {
if (!isConsistent(stack))
return;
-
+
if (accept(stack)) {
mkLemma();
return;
@@ -871,7 +871,7 @@ void AbstractionModule::LemmaInstantiatior::backtrack(vector<int>& stack) {
d_ctx->push();
stack.push_back(x);
backtrack(stack);
-
+
d_ctx->pop();
stack.pop_back();
x = next(x, stack.size());
@@ -880,13 +880,13 @@ void AbstractionModule::LemmaInstantiatior::backtrack(vector<int>& stack) {
void AbstractionModule::LemmaInstantiatior::generateInstantiations(std::vector<Node>& lemmas) {
- Debug("bv-abstraction-gen") << "AbstractionModule::LemmaInstantiatior::generateInstantiations ";
+ Debug("bv-abstraction-gen") << "AbstractionModule::LemmaInstantiatior::generateInstantiations ";
std::vector<int> stack;
backtrack(stack);
- Assert (d_ctx->getLevel() == 0);
- Debug("bv-abstraction-gen") << "numLemmas=" << d_lemmas.size() <<"\n";
- lemmas.swap(d_lemmas);
+ Assert (d_ctx->getLevel() == 0);
+ Debug("bv-abstraction-gen") << "numLemmas=" << d_lemmas.size() <<"\n";
+ lemmas.swap(d_lemmas);
}
void AbstractionModule::makeFreshSkolems(TNode node, SubstitutionMap& map, SubstitutionMap& reverse_map) {
@@ -910,7 +910,7 @@ void AbstractionModule::makeFreshSkolems(TNode node, SubstitutionMap& map, Subst
void AbstractionModule::makeFreshArgs(TNode func, std::vector<Node>& fresh_args) {
Assert (fresh_args.size() == 0);
Assert (func.getKind() == kind::APPLY_UF);
- TNodeNodeMap d_map;
+ TNodeNodeMap d_map;
for (unsigned i = 0; i < func.getNumChildren(); ++i) {
TNode arg = func[i];
if (arg.isConst()) {
@@ -918,9 +918,9 @@ void AbstractionModule::makeFreshArgs(TNode func, std::vector<Node>& fresh_args)
continue;
}
Assert (arg.getMetaKind() == kind::metakind::VARIABLE);
- TNodeNodeMap::iterator it = d_map.find(arg);
+ TNodeNodeMap::iterator it = d_map.find(arg);
if (it != d_map.end()) {
- fresh_args.push_back(it->second);
+ fresh_args.push_back(it->second);
} else {
Node skolem = utils::mkVar(utils::getSize(arg));
d_map[arg] = skolem;
@@ -947,7 +947,7 @@ Node AbstractionModule::tryMatching(const std::vector<Node>& ss, const std::vect
Debug("bv-abstraction-dbg") <<"\n";
}
-
+
SubstitutionMap subst(new context::Context());
for (unsigned i = 0; i < ss.size(); ++i) {
@@ -982,10 +982,10 @@ Node AbstractionModule::tryMatching(const std::vector<Node>& ss, const std::vect
Assert (s0 != t0);
subst.addSubstitution(s0, t0);
}
-
+
Node res = subst.apply(conflict);
- Debug("bv-abstraction-dbg") << " Lemma: " << res <<"\n";
- return res;
+ Debug("bv-abstraction-dbg") << " Lemma: " << res <<"\n";
+ return res;
}
void AbstractionModule::storeLemma(TNode lemma) {
@@ -996,7 +996,7 @@ void AbstractionModule::storeLemma(TNode lemma) {
atom = atom.getKind() == kind::NOT ? atom[0] : atom;
Assert (atom.getKind() != kind::NOT);
Assert (utils::isBVPredicate(atom));
- d_lemmaAtoms.insert(atom);
+ d_lemmaAtoms.insert(atom);
}
} else {
lemma = lemma.getKind() == kind::NOT? lemma[0] : lemma;
@@ -1009,9 +1009,9 @@ void AbstractionModule::storeLemma(TNode lemma) {
bool AbstractionModule::isLemmaAtom(TNode node) const {
Assert (node.getType().isBoolean());
node = node.getKind() == kind::NOT? node[0] : node;
-
+
return d_inputAtoms.find(node) == d_inputAtoms.end() &&
- d_lemmaAtoms.find(node) != d_lemmaAtoms.end();
+ d_lemmaAtoms.find(node) != d_lemmaAtoms.end();
}
void AbstractionModule::addInputAtom(TNode atom) {
@@ -1022,31 +1022,31 @@ void AbstractionModule::addInputAtom(TNode atom) {
void AbstractionModule::ArgsTableEntry::addArguments(const ArgsVec& args) {
Assert (args.size() == d_arity);
- d_data.push_back(args);
+ d_data.push_back(args);
}
void AbstractionModule::ArgsTable::addEntry(TNode signature, const ArgsVec& args) {
if (d_data.find(signature) == d_data.end()) {
- d_data[signature] = ArgsTableEntry(args.size());
+ d_data[signature] = ArgsTableEntry(args.size());
}
ArgsTableEntry& entry = d_data[signature];
- entry.addArguments(args);
+ entry.addArguments(args);
}
bool AbstractionModule::ArgsTable::hasEntry(TNode signature) const {
- return d_data.find(signature) != d_data.end();
+ return d_data.find(signature) != d_data.end();
}
AbstractionModule::ArgsTableEntry& AbstractionModule::ArgsTable::getEntry(TNode signature) {
Assert (hasEntry(signature));
- return d_data.find(signature)->second;
+ return d_data.find(signature)->second;
}
-AbstractionModule::Statistics::Statistics()
- : d_numFunctionsAbstracted("theory::bv::AbstractioModule::NumFunctionsAbstracted", 0)
- , d_numArgsSkolemized("theory::bv::AbstractioModule::NumArgsSkolemized", 0)
- , d_abstractionTime("theory::bv::AbstractioModule::AbstractionTime")
+AbstractionModule::Statistics::Statistics(const std::string& name)
+ : d_numFunctionsAbstracted(name + "theory::bv::AbstractioModule::NumFunctionsAbstracted", 0)
+ , d_numArgsSkolemized(name + "theory::bv::AbstractioModule::NumArgsSkolemized", 0)
+ , d_abstractionTime(name + "theory::bv::AbstractioModule::AbstractionTime")
{
smtStatisticsRegistry()->registerStat(&d_numFunctionsAbstracted);
smtStatisticsRegistry()->registerStat(&d_numArgsSkolemized);
diff --git a/src/theory/bv/abstraction.h b/src/theory/bv/abstraction.h
index 5d580f6ce..5d48b926e 100644
--- a/src/theory/bv/abstraction.h
+++ b/src/theory/bv/abstraction.h
@@ -38,11 +38,11 @@ class AbstractionModule {
IntStat d_numFunctionsAbstracted;
IntStat d_numArgsSkolemized;
TimerStat d_abstractionTime;
- Statistics();
+ Statistics(const std::string& name);
~Statistics();
};
-
+
class ArgsTableEntry {
std::vector<ArgsVec> d_data;
unsigned d_arity;
@@ -61,11 +61,11 @@ class AbstractionModule {
unsigned getArity() { return d_arity; }
unsigned getNumEntries() { return d_data.size(); }
ArgsVec& getEntry(unsigned i ) { Assert (i < d_data.size()); return d_data[i]; }
- };
+ };
class ArgsTable {
__gnu_cxx::hash_map<TNode, ArgsTableEntry, TNodeHashFunction > d_data;
- bool hasEntry(TNode signature) const;
+ bool hasEntry(TNode signature) const;
public:
typedef __gnu_cxx::hash_map<TNode, ArgsTableEntry, TNodeHashFunction >::iterator iterator;
ArgsTable() {}
@@ -75,12 +75,12 @@ class AbstractionModule {
iterator end() { return d_data.end(); }
};
- /**
+ /**
* Checks if one pattern is a generalization of the other
- *
- * @param s
- * @param t
- *
+ *
+ * @param s
+ * @param t
+ *
* @return 1 if s :> t, 2 if s <: t, 0 if they equivalent and -1 if they are incomparable
*/
static int comparePatterns(TNode s, TNode t);
@@ -93,7 +93,7 @@ class AbstractionModule {
theory::SubstitutionMap d_subst;
TNode d_conflict;
std::vector<Node> d_lemmas;
-
+
void backtrack(std::vector<int>& stack);
int next(int val, int index);
bool isConsistent(const std::vector<int>& stack);
@@ -108,7 +108,7 @@ class AbstractionModule {
, d_conflict(conflict)
, d_lemmas()
{
- Debug("bv-abstraction-gen") << "LemmaInstantiator conflict:" << conflict << "\n";
+ Debug("bv-abstraction-gen") << "LemmaInstantiator conflict:" << conflict << "\n";
// initializing the search space
for (unsigned i = 0; i < functions.size(); ++i) {
TNode func_op = functions[i].getOperator();
@@ -118,31 +118,31 @@ class AbstractionModule {
}
}
- void generateInstantiations(std::vector<Node>& lemmas);
-
+ void generateInstantiations(std::vector<Node>& lemmas);
+
};
-
+
typedef __gnu_cxx::hash_map<Node, std::vector<Node>, NodeHashFunction> NodeVecMap;
typedef __gnu_cxx::hash_map<Node, TNode, NodeHashFunction> NodeTNodeMap;
typedef __gnu_cxx::hash_map<TNode, TNode, TNodeHashFunction> TNodeTNodeMap;
typedef __gnu_cxx::hash_map<Node, Node, NodeHashFunction> NodeNodeMap;
typedef __gnu_cxx::hash_map<Node, TNode, NodeHashFunction> TNodeNodeMap;
typedef __gnu_cxx::hash_set<TNode, TNodeHashFunction> TNodeSet;
- typedef __gnu_cxx::hash_map<unsigned, Node> IntNodeMap;
+ typedef __gnu_cxx::hash_map<unsigned, Node> IntNodeMap;
typedef __gnu_cxx::hash_map<unsigned, unsigned> IndexMap;
typedef __gnu_cxx::hash_map<unsigned, std::vector<Node> > SkolemMap;
typedef __gnu_cxx::hash_map<TNode, unsigned, TNodeHashFunction > SignatureMap;
-
- ArgsTable d_argsTable;
+
+ ArgsTable d_argsTable;
// mapping between signature and uninterpreted function symbol used to
// abstract the signature
NodeNodeMap d_signatureToFunc;
- NodeNodeMap d_funcToSignature;
+ NodeNodeMap d_funcToSignature;
- NodeNodeMap d_assertionToSignature;
+ NodeNodeMap d_assertionToSignature;
SignatureMap d_signatures;
- NodeNodeMap d_sigToGeneralization;
+ NodeNodeMap d_sigToGeneralization;
TNodeSet d_skolems;
// skolems maps
@@ -165,7 +165,7 @@ class AbstractionModule {
Node getGeneralizedSignature(Node node);
Node getSignatureSkolem(TNode node);
- unsigned getBitwidthIndex(unsigned bitwidth);
+ unsigned getBitwidthIndex(unsigned bitwidth);
void resetSignatureIndex();
Node computeSignatureRec(TNode, NodeNodeMap&);
void storeSignature(Node signature, TNode assertion);
@@ -175,14 +175,14 @@ class AbstractionModule {
// crazy instantiation methods
void generateInstantiations(unsigned current,
- std::vector<ArgsTableEntry>& matches,
+ std::vector<ArgsTableEntry>& matches,
std::vector<std::vector<ArgsVec> >& instantiations,
std::vector<std::vector<ArgsVec> >& new_instantiations);
Node tryMatching(const std::vector<Node>& ss, const std::vector<TNode>& tt, TNode conflict);
void makeFreshArgs(TNode func, std::vector<Node>& fresh_args);
void makeFreshSkolems(TNode node, SubstitutionMap& map, SubstitutionMap& reverse_map);
-
+
void skolemizeArguments(std::vector<Node>& assertions);
Node reverseAbstraction(Node assertion, NodeNodeMap& seen);
@@ -192,9 +192,9 @@ class AbstractionModule {
void storeLemma(TNode lemma);
Statistics d_statistics;
-
+
public:
- AbstractionModule()
+ AbstractionModule(const std::string& name)
: d_argsTable()
, d_signatureToFunc()
, d_funcToSignature()
@@ -207,34 +207,34 @@ public:
, d_addedLemmas()
, d_lemmaAtoms()
, d_inputAtoms()
- , d_statistics()
+ , d_statistics(name)
{}
- /**
+ /**
* returns true if there are new uninterepreted functions symbols in the output
- *
- * @param assertions
- * @param new_assertions
- *
- * @return
+ *
+ * @param assertions
+ * @param new_assertions
+ *
+ * @return
*/
bool applyAbstraction(const std::vector<Node>& assertions, std::vector<Node>& new_assertions);
- /**
- * Returns true if the node represents an abstraction predicate.
- *
- * @param node
- *
- * @return
+ /**
+ * Returns true if the node represents an abstraction predicate.
+ *
+ * @param node
+ *
+ * @return
*/
bool isAbstraction(TNode node);
- /**
- * Returns the interpretation of the abstraction predicate.
- *
- * @param node
- *
- * @return
+ /**
+ * Returns the interpretation of the abstraction predicate.
+ *
+ * @param node
+ *
+ * @return
*/
Node getInterpretation(TNode node);
- Node simplifyConflict(TNode conflict);
+ Node simplifyConflict(TNode conflict);
void generalizeConflict(TNode conflict, std::vector<Node>& lemmas);
void addInputAtom(TNode atom);
bool isLemmaAtom(TNode node) const;
diff --git a/src/theory/bv/aig_bitblaster.cpp b/src/theory/bv/aig_bitblaster.cpp
index 887daa1bd..37e9f4476 100644
--- a/src/theory/bv/aig_bitblaster.cpp
+++ b/src/theory/bv/aig_bitblaster.cpp
@@ -19,7 +19,7 @@
#include "options/bv_options.h"
#include "prop/cnf_stream.h"
#include "prop/sat_solver_factory.h"
-
+#include "smt/smt_statistics_registry.h"
#ifdef CVC4_USE_ABC
// Function is defined as static in ABC. Not sure how else to do this.
@@ -140,10 +140,24 @@ AigBitblaster::AigBitblaster()
, d_bbAtoms()
, d_aigOutputNode(NULL)
{
- d_nullContext = new context::Context();
- d_satSolver = prop::SatSolverFactory::createMinisat(d_nullContext, "AigBitblaster");
- MinisatEmptyNotify* notify = new MinisatEmptyNotify();
- d_satSolver->setNotify(notify);
+ d_nullContext = new context::Context();
+ switch(options::bvSatSolver()) {
+ case SAT_SOLVER_MINISAT: {
+ prop::BVSatSolverInterface* minisat = prop::SatSolverFactory::createMinisat(d_nullContext,
+ smtStatisticsRegistry(),
+ "AigBitblaster");
+ MinisatEmptyNotify* notify = new MinisatEmptyNotify();
+ minisat->setNotify(notify);
+ d_satSolver = minisat;
+ break;
+ }
+ case SAT_SOLVER_CRYPTOMINISAT:
+ d_satSolver = prop::SatSolverFactory::createCryptoMinisat(smtStatisticsRegistry(),
+ "AigBitblaster");
+ break;
+ default:
+ Unreachable("Unknown SAT solver type");
+ }
}
AigBitblaster::~AigBitblaster() {
@@ -402,7 +416,7 @@ void AigBitblaster::assertToSatSolver(Cnf_Dat_t* pCnf) {
prop::SatLiteral lit(sat_variables[index-1], int_lit < 0);
clause.push_back(lit);
}
- d_satSolver->addClause(clause, false, RULE_INVALID);
+ d_satSolver->addClause(clause, false);
}
}
diff --git a/src/theory/bv/bitblaster_template.h b/src/theory/bv/bitblaster_template.h
index cfbadbf32..c6c0d6def 100644
--- a/src/theory/bv/bitblaster_template.h
+++ b/src/theory/bv/bitblaster_template.h
@@ -257,7 +257,7 @@ public:
class EagerBitblaster : public TBitblaster<Node> {
typedef __gnu_cxx::hash_set<TNode, TNodeHashFunction> TNodeSet;
// sat solver used for bitblasting and associated CnfStream
- prop::BVSatSolverInterface* d_satSolver;
+ prop::SatSolver* d_satSolver;
BitblastingRegistrar* d_bitblastingRegistrar;
context::Context* d_nullContext;
prop::CnfStream* d_cnfStream;
@@ -268,6 +268,8 @@ class EagerBitblaster : public TBitblaster<Node> {
MinisatEmptyNotify d_notify;
+ MinisatEmptyNotify d_notify;
+
Node getModelFromSatSolver(TNode a, bool fullModel);
bool isSharedTerm(TNode node);
@@ -306,7 +308,7 @@ class AigBitblaster : public TBitblaster<Abc_Obj_t*> {
static Abc_Ntk_t* abcAigNetwork;
context::Context* d_nullContext;
- prop::BVSatSolverInterface* d_satSolver;
+ prop::SatSolver* d_satSolver;
TNodeAigMap d_aigCache;
NodeAigMap d_bbAtoms;
@@ -459,7 +461,7 @@ Node TBitblaster<T>::getTermModel(TNode node, bool fullModel) {
if (Theory::isLeafOf(node, theory::THEORY_BV)) {
// if it is a leaf may ask for fullModel
- value = getModelFromSatSolver(node, fullModel);
+ value = getModelFromSatSolver(node, true);
Debug("bv-equality-status")<< "TLazyBitblaster::getTermModel from VarValue" << node <<" => " << value <<"\n";
Assert ((fullModel && !value.isNull() && value.isConst()) || !fullModel);
if (!value.isNull()) {
diff --git a/src/theory/bv/bv_subtheory_algebraic.cpp b/src/theory/bv/bv_subtheory_algebraic.cpp
index 00d337395..b7e973928 100644
--- a/src/theory/bv/bv_subtheory_algebraic.cpp
+++ b/src/theory/bv/bv_subtheory_algebraic.cpp
@@ -714,7 +714,8 @@ void AlgebraicSolver::collectModelInfo(TheoryModel* model, bool fullModel) {
Assert (!value.isNull() || !fullModel);
// may be a shared term that did not appear in the current assertions
- if (!value.isNull()) {
+ // AJR: need to check whether already in map for cases where collectModelInfo is called multiple times in the same context
+ if (!value.isNull() && !d_modelMap->hasSubstitution(var)) {
Debug("bitvector-model") << " " << var << " => " << value << "\n";
Assert (value.getKind() == kind::CONST_BITVECTOR);
d_modelMap->addSubstitution(var, value);
diff --git a/src/theory/bv/bv_subtheory_bitblast.cpp b/src/theory/bv/bv_subtheory_bitblast.cpp
index b7619c4bb..6c6c13ee8 100644
--- a/src/theory/bv/bv_subtheory_bitblast.cpp
+++ b/src/theory/bv/bv_subtheory_bitblast.cpp
@@ -37,9 +37,9 @@ namespace bv {
BitblastSolver::BitblastSolver(context::Context* c, TheoryBV* bv)
: SubtheorySolver(c, bv),
- d_bitblaster(new TLazyBitblaster(c, bv, "lazy")),
+ d_bitblaster(new TLazyBitblaster(c, bv, bv->getFullInstanceName() + "lazy")),
d_bitblastQueue(c),
- d_statistics(),
+ d_statistics(bv->getFullInstanceName()),
d_validModelCache(c, true),
d_lemmaAtomsQueue(c),
d_useSatPropagation(options::bitvectorPropagate()),
@@ -55,9 +55,9 @@ BitblastSolver::~BitblastSolver() {
delete d_bitblaster;
}
-BitblastSolver::Statistics::Statistics()
- : d_numCallstoCheck("theory::bv::BitblastSolver::NumCallsToCheck", 0)
- , d_numBBLemmas("theory::bv::BitblastSolver::NumTimesLemmasBB", 0)
+BitblastSolver::Statistics::Statistics(const std::string &instanceName)
+ : d_numCallstoCheck(instanceName + "theory::bv::BitblastSolver::NumCallsToCheck", 0)
+ , d_numBBLemmas(instanceName + "theory::bv::BitblastSolver::NumTimesLemmasBB", 0)
{
smtStatisticsRegistry()->registerStat(&d_numCallstoCheck);
smtStatisticsRegistry()->registerStat(&d_numBBLemmas);
@@ -68,8 +68,8 @@ BitblastSolver::Statistics::~Statistics() {
}
void BitblastSolver::setAbstraction(AbstractionModule* abs) {
- d_abstractionModule = abs;
- d_bitblaster->setAbstraction(abs);
+ d_abstractionModule = abs;
+ d_bitblaster->setAbstraction(abs);
}
void BitblastSolver::preRegister(TNode node) {
@@ -117,7 +117,7 @@ void BitblastSolver::bitblastQueue() {
bool BitblastSolver::check(Theory::Effort e) {
Debug("bv-bitblast") << "BitblastSolver::check (" << e << ")\n";
- Assert(options::bitblastMode() == theory::bv::BITBLAST_MODE_LAZY);
+ Assert(options::bitblastMode() == theory::bv::BITBLAST_MODE_LAZY);
++(d_statistics.d_numCallstoCheck);
@@ -135,10 +135,10 @@ bool BitblastSolver::check(Theory::Effort e) {
// skip atoms that are the result of abstraction lemmas
if (d_abstractionModule->isLemmaAtom(fact)) {
d_lemmaAtomsQueue.push_back(fact);
- continue;
+ continue;
}
}
-
+
if (!d_bv->inConflict() &&
(!d_bv->wasPropagatedBySubtheory(fact) || d_bv->getPropagatingSubtheory(fact) != SUB_BITBLAST)) {
// Some atoms have not been bit-blasted yet
@@ -183,7 +183,7 @@ bool BitblastSolver::check(Theory::Effort e) {
if (options::bvAbstraction() &&
e == Theory::EFFORT_FULL &&
d_lemmaAtomsQueue.size()) {
-
+
// bit-blast lemma atoms
while(!d_lemmaAtomsQueue.empty()) {
TNode lemma_atom = d_lemmaAtomsQueue.front();
@@ -199,7 +199,7 @@ bool BitblastSolver::check(Theory::Effort e) {
return false;
}
}
-
+
Assert(!d_bv->inConflict());
bool ok = d_bitblaster->solve();
if (!ok) {
@@ -210,9 +210,9 @@ bool BitblastSolver::check(Theory::Effort e) {
++(d_statistics.d_numBBLemmas);
return false;
}
-
+
}
-
+
return true;
}
@@ -228,9 +228,9 @@ void BitblastSolver::collectModelInfo(TheoryModel* m, bool fullModel) {
Node BitblastSolver::getModelValue(TNode node)
{
if (d_bv->d_invalidateModelCache.get()) {
- d_bitblaster->invalidateModelCache();
+ d_bitblaster->invalidateModelCache();
}
- d_bv->d_invalidateModelCache.set(false);
+ d_bv->d_invalidateModelCache.set(false);
Node val = d_bitblaster->getTermModel(node, true);
return val;
}
@@ -241,9 +241,9 @@ void BitblastSolver::setConflict(TNode conflict) {
Node final_conflict = conflict;
if (options::bitvectorQuickXplain() &&
conflict.getKind() == kind::AND) {
- // std::cout << "Original conflict " << conflict.getNumChildren() << "\n";
+ // std::cout << "Original conflict " << conflict.getNumChildren() << "\n";
final_conflict = d_quickXplain->minimizeConflict(conflict);
- //std::cout << "Minimized conflict " << final_conflict.getNumChildren() << "\n";
+ //std::cout << "Minimized conflict " << final_conflict.getNumChildren() << "\n";
}
d_bv->setConflict(final_conflict);
}
@@ -256,4 +256,3 @@ void BitblastSolver::setProofLog( BitVectorProof * bvp ) {
}/* namespace CVC4::theory::bv */
}/* namespace CVC4::theory */
}/* namespace CVC4 */
-
diff --git a/src/theory/bv/bv_subtheory_bitblast.h b/src/theory/bv/bv_subtheory_bitblast.h
index e9300138b..fe16d2702 100644
--- a/src/theory/bv/bv_subtheory_bitblast.h
+++ b/src/theory/bv/bv_subtheory_bitblast.h
@@ -37,7 +37,7 @@ class BitblastSolver : public SubtheorySolver {
struct Statistics {
IntStat d_numCallstoCheck;
IntStat d_numBBLemmas;
- Statistics();
+ Statistics(const std::string &instanceName);
~Statistics();
};
/** Bitblaster */
@@ -71,8 +71,8 @@ public:
Node getModelValue(TNode node);
bool isComplete() { return true; }
void bitblastQueue();
- void setAbstraction(AbstractionModule* module);
- uint64_t computeAtomWeight(TNode atom);
+ void setAbstraction(AbstractionModule* module);
+ uint64_t computeAtomWeight(TNode atom);
void setProofLog( BitVectorProof * bvp );
};
diff --git a/src/theory/bv/eager_bitblaster.cpp b/src/theory/bv/eager_bitblaster.cpp
index 3b54e3794..53fb4f94b 100644
--- a/src/theory/bv/eager_bitblaster.cpp
+++ b/src/theory/bv/eager_bitblaster.cpp
@@ -47,15 +47,30 @@ EagerBitblaster::EagerBitblaster(TheoryBV* theory_bv)
{
d_bitblastingRegistrar = new BitblastingRegistrar(this);
d_nullContext = new context::Context();
-
- d_satSolver = prop::SatSolverFactory::createMinisat(
- d_nullContext, smtStatisticsRegistry(), "EagerBitblaster");
+
+ switch(options::bvSatSolver()) {
+ case SAT_SOLVER_MINISAT: {
+ prop::BVSatSolverInterface* minisat =
+ prop::SatSolverFactory::createMinisat(d_nullContext,
+ smtStatisticsRegistry(),
+ "EagerBitblaster");
+ MinisatEmptyNotify* notify = new MinisatEmptyNotify();
+ minisat->setNotify(notify);
+ d_satSolver = minisat;
+ break;
+ }
+ case SAT_SOLVER_CRYPTOMINISAT:
+ d_satSolver = prop::SatSolverFactory::createCryptoMinisat(smtStatisticsRegistry(),
+ "EagerBitblaster");
+ break;
+ default:
+ Unreachable("Unknown SAT solver type");
+ }
d_cnfStream = new prop::TseitinCnfStream(
d_satSolver, d_bitblastingRegistrar, d_nullContext, options::proof(),
"EagerBitblaster");
- d_satSolver->setNotify(&d_notify);
d_bvp = NULL;
}
@@ -216,7 +231,7 @@ void EagerBitblaster::collectModelInfo(TheoryModel* m, bool fullModel) {
// only shared terms could not have been bit-blasted
Assert (hasBBTerm(var) || isSharedTerm(var));
- Node const_value = getModelFromSatSolver(var, fullModel);
+ Node const_value = getModelFromSatSolver(var, true);
if(const_value != Node()) {
Debug("bitvector-model") << "EagerBitblaster::collectModelInfo (assert (= "
diff --git a/src/theory/bv/lazy_bitblaster.cpp b/src/theory/bv/lazy_bitblaster.cpp
index c821b50cd..b549c329a 100644
--- a/src/theory/bv/lazy_bitblaster.cpp
+++ b/src/theory/bv/lazy_bitblaster.cpp
@@ -491,7 +491,7 @@ void TLazyBitblaster::collectModelInfo(TheoryModel* m, bool fullModel) {
// only shared terms could not have been bit-blasted
Assert (hasBBTerm(var) || isSharedTerm(var));
- Node const_value = getModelFromSatSolver(var, fullModel);
+ Node const_value = getModelFromSatSolver(var, true);
Assert (const_value.isNull() || const_value.isConst());
if(const_value != Node()) {
Debug("bitvector-model") << "TLazyBitblaster::collectModelInfo (assert (= "
diff --git a/src/theory/bv/theory_bv.cpp b/src/theory/bv/theory_bv.cpp
index 2edadce72..fec93e033 100644
--- a/src/theory/bv/theory_bv.cpp
+++ b/src/theory/bv/theory_bv.cpp
@@ -44,25 +44,29 @@ namespace bv {
TheoryBV::TheoryBV(context::Context* c, context::UserContext* u,
OutputChannel& out, Valuation valuation,
- const LogicInfo& logicInfo)
- : Theory(THEORY_BV, c, u, out, valuation, logicInfo),
- d_context(c),
- d_alreadyPropagatedSet(c),
- d_sharedTermsSet(c),
- d_subtheories(),
- d_subtheoryMap(),
- d_statistics(),
- d_staticLearnCache(),
- d_lemmasAdded(c, false),
- d_conflict(c, false),
- d_invalidateModelCache(c, true),
- d_literalsToPropagate(c),
- d_literalsToPropagateIndex(c, 0),
- d_propagatedBy(c),
- d_eagerSolver(NULL),
- d_abstractionModule(new AbstractionModule()),
- d_isCoreTheory(false),
- d_calledPreregister(false)
+ const LogicInfo& logicInfo, std::string name)
+ : Theory(THEORY_BV, c, u, out, valuation, logicInfo, name),
+ d_context(c),
+ d_alreadyPropagatedSet(c),
+ d_sharedTermsSet(c),
+ d_subtheories(),
+ d_subtheoryMap(),
+ d_statistics(getFullInstanceName()),
+ d_staticLearnCache(),
+ d_BVDivByZero(),
+ d_BVRemByZero(),
+ d_funcToArgs(),
+ d_funcToSkolem(u),
+ d_lemmasAdded(c, false),
+ d_conflict(c, false),
+ d_invalidateModelCache(c, true),
+ d_literalsToPropagate(c),
+ d_literalsToPropagateIndex(c, 0),
+ d_propagatedBy(c),
+ d_eagerSolver(NULL),
+ d_abstractionModule(new AbstractionModule(getFullInstanceName())),
+ d_isCoreTheory(false),
+ d_calledPreregister(false)
{
if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
@@ -117,14 +121,14 @@ void TheoryBV::spendResource(unsigned ammount) throw(UnsafeInterruptException) {
getOutputChannel().spendResource(ammount);
}
-TheoryBV::Statistics::Statistics():
- d_avgConflictSize("theory::bv::AvgBVConflictSize"),
- d_solveSubstitutions("theory::bv::NumberOfSolveSubstitutions", 0),
- d_solveTimer("theory::bv::solveTimer"),
- d_numCallsToCheckFullEffort("theory::bv::NumberOfFullCheckCalls", 0),
- d_numCallsToCheckStandardEffort("theory::bv::NumberOfStandardCheckCalls", 0),
- d_weightComputationTimer("theory::bv::weightComputationTimer"),
- d_numMultSlice("theory::bv::NumMultSliceApplied", 0)
+TheoryBV::Statistics::Statistics(const std::string &name):
+ d_avgConflictSize(name + "theory::bv::AvgBVConflictSize"),
+ d_solveSubstitutions(name + "theory::bv::NumberOfSolveSubstitutions", 0),
+ d_solveTimer(name + "theory::bv::solveTimer"),
+ d_numCallsToCheckFullEffort(name + "theory::bv::NumberOfFullCheckCalls", 0),
+ d_numCallsToCheckStandardEffort(name + "theory::bv::NumberOfStandardCheckCalls", 0),
+ d_weightComputationTimer(name + "theory::bv::weightComputationTimer"),
+ d_numMultSlice(name + "theory::bv::NumMultSliceApplied", 0)
{
smtStatisticsRegistry()->registerStat(&d_avgConflictSize);
smtStatisticsRegistry()->registerStat(&d_solveSubstitutions);
@@ -175,30 +179,31 @@ Node TheoryBV::getBVDivByZero(Kind k, unsigned width) {
}
-void TheoryBV::collectNumerators(TNode term, TNodeSet& seen) {
+void TheoryBV::collectFunctionSymbols(TNode term, TNodeSet& seen) {
if (seen.find(term) != seen.end())
return;
- if (term.getKind() == kind::BITVECTOR_ACKERMANIZE_UDIV) {
- unsigned size = utils::getSize(term[0]);
- if (d_BVDivByZeroAckerman.find(size) == d_BVDivByZeroAckerman.end()) {
- d_BVDivByZeroAckerman[size] = TNodeSet();
- }
- d_BVDivByZeroAckerman[size].insert(term[0]);
- seen.insert(term);
- } else if (term.getKind() == kind::BITVECTOR_ACKERMANIZE_UREM) {
- unsigned size = utils::getSize(term[0]);
- if (d_BVRemByZeroAckerman.find(size) == d_BVRemByZeroAckerman.end()) {
- d_BVRemByZeroAckerman[size] = TNodeSet();
- }
- d_BVRemByZeroAckerman[size].insert(term[0]);
- seen.insert(term);
+ if (term.getKind() == kind::APPLY_UF) {
+ TNode func = term.getOperator();
+ storeFunction(func, term);
}
for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- collectNumerators(term[i], seen);
+ collectFunctionSymbols(term[i], seen);
}
seen.insert(term);
}
+void TheoryBV::storeFunction(TNode func, TNode term) {
+ if (d_funcToArgs.find(func) == d_funcToArgs.end()) {
+ d_funcToArgs.insert(make_pair(func, NodeSet()));
+ }
+ NodeSet& set = d_funcToArgs[func];
+ if (set.find(term) == set.end()) {
+ set.insert(term);
+ Node skolem = utils::mkVar(utils::getSize(term));
+ d_funcToSkolem.addSubstitution(term, skolem);
+ }
+}
+
void TheoryBV::mkAckermanizationAsssertions(std::vector<Node>& assertions) {
Debug("bv-ackermanize") << "TheoryBV::mkAckermanizationAsssertions\n";
@@ -206,51 +211,44 @@ void TheoryBV::mkAckermanizationAsssertions(std::vector<Node>& assertions) {
AlwaysAssert(!options::incrementalSolving());
TNodeSet seen;
for (unsigned i = 0; i < assertions.size(); ++i) {
- collectNumerators(assertions[i], seen);
- }
-
- // process division UF
- Debug("bv-ackermanize") << "Process division UF...\n";
- for (WidthToNumerators::const_iterator it = d_BVDivByZeroAckerman.begin(); it != d_BVDivByZeroAckerman.end(); ++it) {
- const TNodeSet& numerators= it->second;
- for (TNodeSet::const_iterator i = numerators.begin(); i != numerators.end(); ++i) {
- TNodeSet::const_iterator j = i;
- j++;
- for (; j != numerators.end(); ++j) {
- TNode arg1 = *i;
- TNode arg2 = *j;
- TNode acker1 = utils::mkNode(kind::BITVECTOR_ACKERMANIZE_UDIV, arg1);
- TNode acker2 = utils::mkNode(kind::BITVECTOR_ACKERMANIZE_UDIV, arg2);
-
- Node arg_eq = utils::mkNode(kind::EQUAL, arg1, arg2);
- Node acker_eq = utils::mkNode(kind::EQUAL, acker1, acker2);
- Node lemma = utils::mkNode(kind::IMPLIES, arg_eq, acker_eq);
- Debug("bv-ackermanize") << " " << lemma << "\n";
- assertions.push_back(lemma);
- }
- }
+ collectFunctionSymbols(assertions[i], seen);
}
- // process remainder UF
- Debug("bv-ackermanize") << "Process remainder UF...\n";
- for (WidthToNumerators::const_iterator it = d_BVRemByZeroAckerman.begin(); it != d_BVRemByZeroAckerman.end(); ++it) {
- const TNodeSet& numerators= it->second;
- for (TNodeSet::const_iterator i = numerators.begin(); i != numerators.end(); ++i) {
- TNodeSet::const_iterator j = i;
- j++;
- for (; j != numerators.end(); ++j) {
- TNode arg1 = *i;
- TNode arg2 = *j;
- TNode acker1 = utils::mkNode(kind::BITVECTOR_ACKERMANIZE_UREM, arg1);
- TNode acker2 = utils::mkNode(kind::BITVECTOR_ACKERMANIZE_UREM, arg2);
-
- Node arg_eq = utils::mkNode(kind::EQUAL, arg1, arg2);
- Node acker_eq = utils::mkNode(kind::EQUAL, acker1, acker2);
- Node lemma = utils::mkNode(kind::IMPLIES, arg_eq, acker_eq);
- Debug("bv-ackermanize") << " " << lemma << "\n";
+
+ FunctionToArgs::const_iterator it = d_funcToArgs.begin();
+ NodeManager* nm = NodeManager::currentNM();
+ for (; it!= d_funcToArgs.end(); ++it) {
+ TNode func = it->first;
+ const NodeSet& args = it->second;
+ NodeSet::const_iterator it1 = args.begin();
+ for ( ; it1 != args.end(); ++it1) {
+ for(NodeSet::const_iterator it2 = it1; it2 != args.end(); ++it2) {
+ TNode args1 = *it1;
+ TNode args2 = *it2;
+
+ AlwaysAssert (args1.getKind() == kind::APPLY_UF &&
+ args1.getOperator() == func);
+ AlwaysAssert (args2.getKind() == kind::APPLY_UF &&
+ args2.getOperator() == func);
+ AlwaysAssert (args1.getNumChildren() == args2.getNumChildren());
+
+ std::vector<Node> eqs(args1.getNumChildren());
+
+ for (unsigned i = 0; i < args1.getNumChildren(); ++i) {
+ eqs[i] = nm->mkNode(kind::EQUAL, args1[i], args2[i]);
+ }
+
+ Node args_eq = eqs.size() == 1 ? eqs[0] : nm->mkNode(kind::AND, eqs);
+ Node func_eq = nm->mkNode(kind::EQUAL, args1, args2);
+ Node lemma = nm->mkNode(kind::IMPLIES, args_eq, func_eq);
assertions.push_back(lemma);
}
}
}
+
+ // replace applications of UF by skolems (FIXME for model building)
+ for(unsigned i = 0; i < assertions.size(); ++i) {
+ assertions[i] = d_funcToSkolem.apply(assertions[i]);
+ }
}
Node TheoryBV::expandDefinition(LogicRequest &logicRequest, Node node) {
@@ -278,18 +276,18 @@ Node TheoryBV::expandDefinition(LogicRequest &logicRequest, Node node) {
Node divTotalNumDen = nm->mkNode(node.getKind() == kind::BITVECTOR_UDIV ? kind::BITVECTOR_UDIV_TOTAL :
kind::BITVECTOR_UREM_TOTAL, num, den);
- if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
- // Ackermanize UF if using eager bit-blasting
- Node ackerman_var = nm->mkNode(node.getKind() == kind::BITVECTOR_UDIV ? kind::BITVECTOR_ACKERMANIZE_UDIV : kind::BITVECTOR_ACKERMANIZE_UREM, num);
- node = nm->mkNode(kind::ITE, den_eq_0, ackerman_var, divTotalNumDen);
- return node;
- } else {
+ // if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
+ // // Ackermanize UF if using eager bit-blasting
+ // Node ackerman_var = nm->mkNode(node.getKind() == kind::BITVECTOR_UDIV ? kind::BITVECTOR_ACKERMANIZE_UDIV : kind::BITVECTOR_ACKERMANIZE_UREM, num);
+ // node = nm->mkNode(kind::ITE, den_eq_0, ackerman_var, divTotalNumDen);
+ // return node;
+ // } else {
Node divByZero = getBVDivByZero(node.getKind(), width);
Node divByZeroNum = nm->mkNode(kind::APPLY_UF, divByZero, num);
node = nm->mkNode(kind::ITE, den_eq_0, divByZeroNum, divTotalNumDen);
logicRequest.widenLogic(THEORY_UF);
return node;
- }
+ //}
}
break;
@@ -331,7 +329,7 @@ void TheoryBV::sendConflict() {
if (d_conflictNode.isNull()) {
return;
} else {
- Debug("bitvector") << indent() << "TheoryBV::check(): conflict " << d_conflictNode;
+ Debug("bitvector") << indent() << "TheoryBV::check(): conflict " << d_conflictNode << std::endl;
d_out->conflict(d_conflictNode);
d_statistics.d_avgConflictSize.addEntry(d_conflictNode.getNumChildren());
d_conflictNode = Node::null();
@@ -707,7 +705,7 @@ Node TheoryBV::explain(TNode node) {
// return the explanation
Node explanation = utils::mkAnd(assumptions);
Debug("bitvector::explain") << "TheoryBV::explain(" << node << ") => " << explanation << std::endl;
- Debug("bitvector::explain") << "TheoryBV::explain done. \n";
+ Debug("bitvector::explain") << "TheoryBV::explain done. \n";
return explanation;
}
@@ -725,6 +723,8 @@ void TheoryBV::addSharedTerm(TNode t) {
EqualityStatus TheoryBV::getEqualityStatus(TNode a, TNode b)
{
+ if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER)
+ return EQUALITY_UNKNOWN;
Assert (options::bitblastMode() == theory::bv::BITBLAST_MODE_LAZY);
for (unsigned i = 0; i < d_subtheories.size(); ++i) {
EqualityStatus status = d_subtheories[i]->getEqualityStatus(a, b);
diff --git a/src/theory/bv/theory_bv.h b/src/theory/bv/theory_bv.h
index 0bbcba9b0..ba2a4fc2a 100644
--- a/src/theory/bv/theory_bv.h
+++ b/src/theory/bv/theory_bv.h
@@ -56,7 +56,8 @@ class TheoryBV : public Theory {
public:
TheoryBV(context::Context* c, context::UserContext* u, OutputChannel& out,
- Valuation valuation, const LogicInfo& logicInfo);
+ Valuation valuation, const LogicInfo& logicInfo,
+ std::string name = "");
~TheoryBV();
@@ -88,8 +89,8 @@ public:
void presolve();
- bool applyAbstraction(const std::vector<Node>& assertions, std::vector<Node>& new_assertions);
-
+ bool applyAbstraction(const std::vector<Node>& assertions, std::vector<Node>& new_assertions);
+
void setProofLog( BitVectorProof * bvp );
private:
@@ -100,10 +101,10 @@ private:
IntStat d_solveSubstitutions;
TimerStat d_solveTimer;
IntStat d_numCallsToCheckFullEffort;
- IntStat d_numCallsToCheckStandardEffort;
+ IntStat d_numCallsToCheckStandardEffort;
TimerStat d_weightComputationTimer;
IntStat d_numMultSlice;
- Statistics();
+ Statistics(const std::string &name);
~Statistics();
};
@@ -121,12 +122,12 @@ private:
*/
Node getBVDivByZero(Kind k, unsigned width);
- typedef __gnu_cxx::hash_set<TNode, TNodeHashFunction> TNodeSet;
- void collectNumerators(TNode term, TNodeSet& seen);
-
+ typedef __gnu_cxx::hash_set<TNode, TNodeHashFunction> TNodeSet;
+ void collectFunctionSymbols(TNode term, TNodeSet& seen);
+ void storeFunction(TNode func, TNode term);
typedef __gnu_cxx::hash_set<Node, NodeHashFunction> NodeSet;
NodeSet d_staticLearnCache;
-
+
/**
* Maps from bit-vector width to division-by-zero uninterpreted
* function symbols.
@@ -134,17 +135,15 @@ private:
__gnu_cxx::hash_map<unsigned, Node> d_BVDivByZero;
__gnu_cxx::hash_map<unsigned, Node> d_BVRemByZero;
- /**
- * Maps from bit-vector width to numerators
- * of uninterpreted function symbol
- */
- typedef __gnu_cxx::hash_map<unsigned, TNodeSet > WidthToNumerators;
- WidthToNumerators d_BVDivByZeroAckerman;
- WidthToNumerators d_BVRemByZeroAckerman;
+ typedef __gnu_cxx::hash_map<Node, NodeSet, NodeHashFunction> FunctionToArgs;
+ typedef __gnu_cxx::hash_map<Node, Node, NodeHashFunction> NodeToNode;
+ // for ackermanization
+ FunctionToArgs d_funcToArgs;
+ CVC4::theory::SubstitutionMap d_funcToSkolem;
context::CDO<bool> d_lemmasAdded;
-
+
// Are we in conflict?
context::CDO<bool> d_conflict;
@@ -167,17 +166,17 @@ private:
typedef context::CDHashMap<Node, SubTheory, NodeHashFunction> PropagatedMap;
PropagatedMap d_propagatedBy;
- EagerBitblastSolver* d_eagerSolver;
+ EagerBitblastSolver* d_eagerSolver;
AbstractionModule* d_abstractionModule;
bool d_isCoreTheory;
bool d_calledPreregister;
-
+
bool wasPropagatedBySubtheory(TNode literal) const {
- return d_propagatedBy.find(literal) != d_propagatedBy.end();
+ return d_propagatedBy.find(literal) != d_propagatedBy.end();
}
-
+
SubTheory getPropagatingSubtheory(TNode literal) const {
- Assert(wasPropagatedBySubtheory(literal));
+ Assert(wasPropagatedBySubtheory(literal));
PropagatedMap::const_iterator find = d_propagatedBy.find(literal);
return (*find).second;
}
@@ -193,7 +192,7 @@ private:
void addSharedTerm(TNode t);
bool isSharedTerm(TNode t) { return d_sharedTermsSet.contains(t); }
-
+
EqualityStatus getEqualityStatus(TNode a, TNode b);
Node getModelValue(TNode var);
@@ -214,7 +213,7 @@ private:
void lemma(TNode node) { d_out->lemma(node, RULE_CONFLICT); d_lemmasAdded = true; }
- void checkForLemma(TNode node);
+ void checkForLemma(TNode node);
friend class LazyBitblaster;
friend class TLazyBitblaster;
diff --git a/src/theory/bv/theory_bv_rewrite_rules_operator_elimination.h b/src/theory/bv/theory_bv_rewrite_rules_operator_elimination.h
index 152a335a5..2bcb6ca1b 100644
--- a/src/theory/bv/theory_bv_rewrite_rules_operator_elimination.h
+++ b/src/theory/bv/theory_bv_rewrite_rules_operator_elimination.h
@@ -349,7 +349,7 @@ Node RewriteRule<SdivEliminate>::apply(TNode node) {
Node abs_a = utils::mkNode(kind::ITE, a_lt_0, utils::mkNode(kind::BITVECTOR_NEG, a), a);
Node abs_b = utils::mkNode(kind::ITE, b_lt_0, utils::mkNode(kind::BITVECTOR_NEG, b), b);
- Node a_udiv_b = utils::mkNode(kind::BITVECTOR_UDIV, abs_a, abs_b);
+ Node a_udiv_b = utils::mkNode(options::bitvectorDivByZeroConst() ? kind::BITVECTOR_UDIV_TOTAL : kind::BITVECTOR_UDIV, abs_a, abs_b);
Node neg_result = utils::mkNode(kind::BITVECTOR_NEG, a_udiv_b);
Node condition = utils::mkNode(kind::XOR, a_lt_0, b_lt_0);
@@ -377,7 +377,7 @@ Node RewriteRule<SremEliminate>::apply(TNode node) {
Node abs_a = utils::mkNode(kind::ITE, a_lt_0, utils::mkNode(kind::BITVECTOR_NEG, a), a);
Node abs_b = utils::mkNode(kind::ITE, b_lt_0, utils::mkNode(kind::BITVECTOR_NEG, b), b);
- Node a_urem_b = utils::mkNode(kind::BITVECTOR_UREM, abs_a, abs_b);
+ Node a_urem_b = utils::mkNode( options::bitvectorDivByZeroConst() ? kind::BITVECTOR_UREM_TOTAL : kind::BITVECTOR_UREM, abs_a, abs_b);
Node neg_result = utils::mkNode(kind::BITVECTOR_NEG, a_urem_b);
Node result = utils::mkNode(kind::ITE, a_lt_0, neg_result, a_urem_b);
diff --git a/src/theory/datatypes/datatypes_sygus.cpp b/src/theory/datatypes/datatypes_sygus.cpp
index 5bd6680f2..4514453db 100644
--- a/src/theory/datatypes/datatypes_sygus.cpp
+++ b/src/theory/datatypes/datatypes_sygus.cpp
@@ -402,6 +402,60 @@ void SygusSplit::registerSygusTypeConstructorArg( TypeNode tnn, const Datatype&
}
}
+class ReqTrie {
+public:
+ ReqTrie() : d_req_kind( UNDEFINED_KIND ){}
+ std::map< unsigned, ReqTrie > d_children;
+ Kind d_req_kind;
+ TypeNode d_req_type;
+ Node d_req_const;
+ void print( const char * c, int indent = 0 ){
+ if( d_req_kind!=UNDEFINED_KIND ){
+ Trace(c) << d_req_kind << " ";
+ }else if( !d_req_type.isNull() ){
+ Trace(c) << d_req_type;
+ }else if( !d_req_const.isNull() ){
+ Trace(c) << d_req_const;
+ }else{
+ Trace(c) << "_";
+ }
+ Trace(c) << std::endl;
+ for( std::map< unsigned, ReqTrie >::iterator it = d_children.begin(); it != d_children.end(); ++it ){
+ for( int i=0; i<=indent; i++ ) { Trace(c) << " "; }
+ Trace(c) << it->first << " : ";
+ it->second.print( c, indent+1 );
+ }
+ }
+ bool satisfiedBy( quantifiers::TermDbSygus * tdb, TypeNode tn ){
+ if( d_req_kind!=UNDEFINED_KIND ){
+ int c = tdb->getKindArg( tn, d_req_kind );
+ if( c!=-1 ){
+ const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
+ for( std::map< unsigned, ReqTrie >::iterator it = d_children.begin(); it != d_children.end(); ++it ){
+ if( it->first<dt[c].getNumArgs() ){
+ TypeNode tnc = tdb->getArgType( dt[c], it->first );
+ if( !it->second.satisfiedBy( tdb, tnc ) ){
+ return false;
+ }
+ }else{
+ return false;
+ }
+ }
+ return true;
+ }else{
+ return false;
+ }
+ }else if( !d_req_const.isNull() ){
+ return tdb->hasConst( tn, d_req_const );
+ }else if( !d_req_type.isNull() ){
+ return tn==d_req_type;
+ }else{
+ return true;
+ }
+ }
+};
+
+
//this function gets all easy redundant cases, before consulting rewriters
bool SygusSplit::considerSygusSplitKind( const Datatype& dt, const Datatype& pdt, TypeNode tn, TypeNode tnp, Kind k, Kind parent, int arg ) {
Assert( d_tds->hasKind( tn, k ) );
@@ -419,101 +473,168 @@ bool SygusSplit::considerSygusSplitKind( const Datatype& dt, const Datatype& pdt
return arg==firstArg;
}
}
- //push
+ //describes the shape of an alternate term to construct
+ // we check whether this term is in the sygus grammar below
+ ReqTrie rt;
+ bool rt_valid = false;
+
+ //construct rt by cases
if( parent==NOT || parent==BITVECTOR_NOT || parent==UMINUS || parent==BITVECTOR_NEG ){
- //negation normal form
- if( parent==k && isArgDatatype( dt[c], 0, pdt ) ){
- return false;
- }
- Kind nk = UNDEFINED_KIND;
- Kind reqk = UNDEFINED_KIND; //required kind for all children
- if( parent==NOT ){
- if( k==AND ) {
- nk = OR;reqk = NOT;
- }else if( k==OR ){
- nk = AND;reqk = NOT;
- }else if( k==IFF ) {
- nk = XOR;
- }else if( k==XOR ) {
- nk = IFF;
- }
- }
- if( parent==BITVECTOR_NOT ){
- if( k==BITVECTOR_AND ) {
- nk = BITVECTOR_OR;reqk = BITVECTOR_NOT;
- }else if( k==BITVECTOR_OR ){
- nk = BITVECTOR_AND;reqk = BITVECTOR_NOT;
- }else if( k==BITVECTOR_XNOR ) {
- nk = BITVECTOR_XOR;
- }else if( k==BITVECTOR_XOR ) {
- nk = BITVECTOR_XNOR;
- }
- }
- if( parent==UMINUS ){
- if( k==PLUS ){
- nk = PLUS;reqk = UMINUS;
- }
- }
- if( parent==BITVECTOR_NEG ){
- if( k==PLUS ){
- nk = PLUS;reqk = BITVECTOR_NEG;
- }
- }
- if( nk!=UNDEFINED_KIND ){
- Trace("sygus-split-debug") << "Push " << parent << " over " << k << " to " << nk;
- if( reqk!=UNDEFINED_KIND ){
- Trace("sygus-split-debug") << ", reqk = " << reqk;
+ rt_valid = true;
+ //negation normal form
+ if( parent==k ){
+ rt.d_req_type = d_tds->getArgType( dt[c], 0 );
+ }else{
+ Kind reqk = UNDEFINED_KIND; //required kind for all children
+ std::map< unsigned, Kind > reqkc; //required kind for some children
+ if( parent==NOT ){
+ if( k==AND ) {
+ rt.d_req_kind = OR;reqk = NOT;
+ }else if( k==OR ){
+ rt.d_req_kind = AND;reqk = NOT;
+ }else if( k==IFF ) {
+ rt.d_req_kind = XOR;
+ }else if( k==XOR ) {
+ rt.d_req_kind = IFF;
+ }else if( k==ITE ){
+ rt.d_req_kind = ITE;reqkc[1] = NOT;reqkc[2] = NOT;
+ rt.d_children[0].d_req_type = d_tds->getArgType( dt[c], 0 );
+ }else if( k==LEQ || k==GT ){
+ // (not (~ x y)) -----> (~ (+ y 1) x)
+ rt.d_req_kind = k;
+ rt.d_children[0].d_req_kind = PLUS;
+ rt.d_children[0].d_children[0].d_req_type = d_tds->getArgType( dt[c], 1 );
+ rt.d_children[0].d_children[1].d_req_const = NodeManager::currentNM()->mkConst( Rational( 1 ) );
+ rt.d_children[1].d_req_type = d_tds->getArgType( dt[c], 0 );
+ //TODO: other possibilities?
+ }else if( k==LT || k==GEQ ){
+ // (not (~ x y)) -----> (~ y (+ x 1))
+ rt.d_req_kind = k;
+ rt.d_children[0].d_req_type = d_tds->getArgType( dt[c], 1 );
+ rt.d_children[1].d_req_kind = PLUS;
+ rt.d_children[1].d_children[0].d_req_type = d_tds->getArgType( dt[c], 0 );
+ rt.d_children[1].d_children[1].d_req_const = NodeManager::currentNM()->mkConst( Rational( 1 ) );
+ }else{
+ rt_valid = false;
+ }
+ }else if( parent==BITVECTOR_NOT ){
+ if( k==BITVECTOR_AND ) {
+ rt.d_req_kind = BITVECTOR_OR;reqk = BITVECTOR_NOT;
+ }else if( k==BITVECTOR_OR ){
+ rt.d_req_kind = BITVECTOR_AND;reqk = BITVECTOR_NOT;
+ }else if( k==BITVECTOR_XNOR ) {
+ rt.d_req_kind = BITVECTOR_XOR;
+ }else if( k==BITVECTOR_XOR ) {
+ rt.d_req_kind = BITVECTOR_XNOR;
+ }else{
+ rt_valid = false;
+ }
+ }else if( parent==UMINUS ){
+ if( k==PLUS ){
+ rt.d_req_kind = PLUS;reqk = UMINUS;
+ }else{
+ rt_valid = false;
+ }
+ }else if( parent==BITVECTOR_NEG ){
+ if( k==PLUS ){
+ rt.d_req_kind = PLUS;reqk = BITVECTOR_NEG;
+ }else{
+ rt_valid = false;
+ }
}
- Trace("sygus-split-debug") << "?" << std::endl;
- int pcr = d_tds->getKindArg( tnp, nk );
- if( pcr!=-1 ){
- Assert( pcr<(int)pdt.getNumConstructors() );
- if( reqk!=UNDEFINED_KIND ){
+ if( rt_valid && ( reqk!=UNDEFINED_KIND || !reqkc.empty() ) ){
+ int pcr = d_tds->getKindArg( tnp, rt.d_req_kind );
+ if( pcr!=-1 ){
+ Assert( pcr<(int)pdt.getNumConstructors() );
//must have same number of arguments
if( pdt[pcr].getNumArgs()==dt[c].getNumArgs() ){
- bool success = true;
- std::map< int, TypeNode > childTypes;
for( unsigned i=0; i<pdt[pcr].getNumArgs(); i++ ){
- TypeNode tna = d_tds->getArgType( pdt[pcr], i );
- Assert( datatypes::DatatypesRewriter::isTypeDatatype( tna ) );
- if( reqk!=UNDEFINED_KIND ){
- //child must have a NOT
- int nindex = d_tds->getKindArg( tna, reqk );
- if( nindex!=-1 ){
- const Datatype& adt = ((DatatypeType)(tn).toType()).getDatatype();
- if( d_tds->getArgType( dt[c], i )!=d_tds->getArgType( adt[nindex], 0 ) ){
- Trace("sygus-split-debug") << "...arg " << i << " type mismatch." << std::endl;
- success = false;
- break;
- }
- }else{
- Trace("sygus-split-debug") << "...argument " << i << " does not have " << reqk << "." << std::endl;
- success = false;
- break;
+ Kind rk = reqk;
+ if( reqk==UNDEFINED_KIND ){
+ std::map< unsigned, Kind >::iterator itr = reqkc.find( i );
+ if( itr!=reqkc.end() ){
+ rk = itr->second;
}
- }else{
- childTypes[i] = tna;
}
- }
- if( success ){
- Trace("sygus-split-debug") << "...success" << std::endl;
- return false;
+ if( rk!=UNDEFINED_KIND ){
+ rt.d_children[i].d_req_kind = rk;
+ rt.d_children[i].d_children[0].d_req_type = d_tds->getArgType( dt[c], i );
+ }
}
}else{
- Trace("sygus-split-debug") << "...#arg mismatch." << std::endl;
+ rt_valid = false;
}
}else{
- return !isTypeMatch( pdt[pcr], dt[c] );
+ rt_valid = false;
}
- }else{
- Trace("sygus-split-debug") << "...operator not available." << std::endl;
}
}
+ }else if( k==MINUS || k==BITVECTOR_SUB ){
+ if( parent==EQUAL ||
+ parent==MINUS || parent==BITVECTOR_SUB ||
+ parent==LEQ || parent==LT || parent==GEQ || parent==GT ){
+ int oarg = arg==0 ? 1 : 0;
+ // (~ x (- y z)) ----> (~ (+ x z) y)
+ // (~ (- y z) x) ----> (~ y (+ x z))
+ rt.d_req_kind = parent;
+ rt.d_children[arg].d_req_type = d_tds->getArgType( dt[c], 0 );
+ rt.d_children[oarg].d_req_kind = k==MINUS ? PLUS : BITVECTOR_PLUS;
+ rt.d_children[oarg].d_children[0].d_req_type = d_tds->getArgType( pdt[pc], oarg );
+ rt.d_children[oarg].d_children[1].d_req_type = d_tds->getArgType( dt[c], 1 );
+ rt_valid = true;
+ }else if( parent==PLUS || parent==BITVECTOR_PLUS ){
+ // (+ x (- y z)) -----> (- (+ x y) z)
+ // (+ (- y z) x) -----> (- (+ x y) z)
+ rt.d_req_kind = parent==PLUS ? MINUS : BITVECTOR_SUB;
+ int oarg = arg==0 ? 1 : 0;
+ rt.d_children[0].d_req_kind = parent;
+ rt.d_children[0].d_children[0].d_req_type = d_tds->getArgType( pdt[pc], oarg );
+ rt.d_children[0].d_children[1].d_req_type = d_tds->getArgType( dt[c], 0 );
+ rt.d_children[1].d_req_type = d_tds->getArgType( dt[c], 1 );
+ rt_valid = true;
+ }
+ }else if( k==ITE ){
+ if( parent!=ITE ){
+ // (o X (ite y z w) X') -----> (ite y (o X z X') (o X w X'))
+ rt.d_req_kind = ITE;
+ rt.d_children[0].d_req_type = d_tds->getArgType( dt[c], 0 );
+ unsigned n_args = pdt[pc].getNumArgs();
+ for( unsigned r=1; r<=2; r++ ){
+ rt.d_children[r].d_req_kind = parent;
+ for( unsigned q=0; q<n_args; q++ ){
+ if( (int)q==arg ){
+ rt.d_children[r].d_children[q].d_req_type = d_tds->getArgType( dt[c], r );
+ }else{
+ rt.d_children[r].d_children[q].d_req_type = d_tds->getArgType( pdt[pc], q );
+ }
+ }
+ }
+ rt_valid = true;
+ //TODO: this increases term size but is probably a good idea
+ }
+ }else if( k==NOT ){
+ if( parent==ITE ){
+ // (ite (not y) z w) -----> (ite y w z)
+ rt.d_req_kind = ITE;
+ rt.d_children[0].d_req_type = d_tds->getArgType( dt[c], 0 );
+ rt.d_children[1].d_req_type = d_tds->getArgType( pdt[pc], 2 );
+ rt.d_children[2].d_req_type = d_tds->getArgType( pdt[pc], 1 );
+ }
}
- if( parent==MINUS || parent==BITVECTOR_SUB ){
-
-
+ Trace("sygus-consider-split") << "Consider sygus split kind " << k << ", parent = " << parent << ", arg = " << arg << "?" << std::endl;
+ if( rt_valid ){
+ rt.print("sygus-consider-split");
+ //check if it meets the requirements
+ if( rt.satisfiedBy( d_tds, tnp ) ){
+ Trace("sygus-consider-split") << "...success!" << std::endl;
+ //do not need to consider the kind in the search since there are ways to construct equivalent terms
+ return false;
+ }else{
+ Trace("sygus-consider-split") << "...failed." << std::endl;
+ }
+ Trace("sygus-consider-split") << std::endl;
}
+ //must consider this kind in the search
return true;
}
@@ -616,6 +737,7 @@ bool SygusSplit::isGenericRedundant( TypeNode tn, Node g, bool active ) {
d_gen_terms[tn][gr] = g;
d_gen_terms_inactive[tn][gr] = g;
Trace("sygus-gnf-debug") << "...not redundant." << std::endl;
+ Trace("sygus-nf-reg") << "*** Sygus (generic) normal form : normal form of " << g << " is " << gr << std::endl;
}else{
Trace("sygus-gnf-debug") << "...redundant." << std::endl;
Trace("sygus-nf") << "* Sygus normal form : simplify since " << g << " and " << itg->second << " both rewrite to " << gr << std::endl;
@@ -849,6 +971,7 @@ bool SygusSymBreak::processCurrentProgram( Node a, TypeNode at, int depth, Node
}else{
d_redundant[at][prog] = false;
red = false;
+ Trace("sygus-nf-reg") << "*** Sygus normal form : normal form of " << prog << " is " << progr << std::endl;
}
}else{
rep_prog = itnp->second;
@@ -858,6 +981,7 @@ bool SygusSymBreak::processCurrentProgram( Node a, TypeNode at, int depth, Node
d_redundant[at].erase( rep_prog );
d_redundant[at][prog] = false;
red = false;
+ Trace("sygus-nf-reg") << "*** Sygus normal form : normal form of " << prog << " is " << progr << " (redundant but smaller than " << rep_prog << ") " << std::endl;
}else{
Assert( prog!=itnp->second );
d_redundant[at][prog] = true;
@@ -1090,6 +1214,7 @@ bool SygusSymBreak::processCurrentProgram( Node a, TypeNode at, int depth, Node
}
}else{
red = it->second;
+ Trace("sygus-nf-debug") << "Already processed, redundant : " << red << std::endl;
}
if( red ){
if( std::find( d_lemmas_reported[at][prog].begin(), d_lemmas_reported[at][prog].end(), a )==d_lemmas_reported[at][prog].end() ){
diff --git a/src/theory/datatypes/kinds b/src/theory/datatypes/kinds
index d035f0fa7..3338e5f31 100644
--- a/src/theory/datatypes/kinds
+++ b/src/theory/datatypes/kinds
@@ -105,7 +105,7 @@ typerule RECORD_UPDATE ::CVC4::theory::datatypes::RecordUpdateTypeRule
operator DT_SIZE 1 "datatypes size"
typerule DT_SIZE ::CVC4::theory::datatypes::DtSizeTypeRule
-operator DT_HEIGHT_BOUND 1 "datatypes height bound"
+operator DT_HEIGHT_BOUND 2 "datatypes height bound"
typerule DT_HEIGHT_BOUND ::CVC4::theory::datatypes::DtHeightBoundTypeRule
endtheory
diff --git a/src/theory/datatypes/theory_datatypes.cpp b/src/theory/datatypes/theory_datatypes.cpp
index eb8b23973..a2f995935 100644
--- a/src/theory/datatypes/theory_datatypes.cpp
+++ b/src/theory/datatypes/theory_datatypes.cpp
@@ -27,9 +27,11 @@
#include "theory/datatypes/datatypes_rewriter.h"
#include "theory/datatypes/theory_datatypes_type_rules.h"
#include "theory/quantifiers_engine.h"
+#include "theory/quantifiers/term_database.h"
#include "theory/theory_model.h"
#include "theory/type_enumerator.h"
#include "theory/valuation.h"
+#include "options/theory_options.h"
using namespace std;
using namespace CVC4::kind;
@@ -54,8 +56,7 @@ TheoryDatatypes::TheoryDatatypes(Context* c, UserContext* u, OutputChannel& out,
//d_consEqc( c ),
d_conflict( c, false ),
d_collectTermsCache( c ),
- d_consTerms( c ),
- d_selTerms( c ),
+ d_functionTerms( c ),
d_singleton_eq( u ),
d_lemmas_produced_c( u )
{
@@ -81,6 +82,8 @@ TheoryDatatypes::~TheoryDatatypes() {
Assert(current != NULL);
delete current;
}
+ delete d_sygus_split;
+ delete d_sygus_sym_break;
}
void TheoryDatatypes::setMasterEqualityEngine(eq::EqualityEngine* eq) {
@@ -91,9 +94,7 @@ TheoryDatatypes::EqcInfo* TheoryDatatypes::getOrMakeEqcInfo( TNode n, bool doMak
if( !hasEqcInfo( n ) ){
if( doMake ){
//add to labels
- NodeList* lbl = new(getSatContext()->getCMM()) NodeList( true, getSatContext(), false,
- ContextMemoryAllocator<TNode>(getSatContext()->getCMM()) );
- d_labels.insertDataFromContextMemory( n, lbl );
+ d_labels[ n ] = 0;
std::map< Node, EqcInfo* >::iterator eqc_i = d_eqc_info.find( n );
EqcInfo* ei;
@@ -106,10 +107,10 @@ TheoryDatatypes::EqcInfo* TheoryDatatypes::getOrMakeEqcInfo( TNode n, bool doMak
if( n.getKind()==APPLY_CONSTRUCTOR ){
ei->d_constructor = n;
}
+
//add to selectors
- NodeList* sel = new(getSatContext()->getCMM()) NodeList( true, getSatContext(), false,
- ContextMemoryAllocator<TNode>(getSatContext()->getCMM()) );
- d_selector_apps.insertDataFromContextMemory( n, sel );
+ d_selector_apps[n] = 0;
+
return ei;
}else{
return NULL;
@@ -178,6 +179,7 @@ void TheoryDatatypes::check(Effort e) {
Trace("datatypes-debug") << "Check for splits " << e << endl;
do {
d_addedFact = false;
+ bool added_split = false;
std::map< TypeNode, Node > rec_singletons;
eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( &d_equalityEngine );
while( !eqcs_i.isFinished() ){
@@ -190,7 +192,7 @@ void TheoryDatatypes::check(Effort e) {
if( !hasLabel( eqc, n ) ){
Trace("datatypes-debug") << "No constructor..." << std::endl;
const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
- Trace("datatypes-debug") << "Datatype " << dt << " is " << dt.isFinite() << " " << dt.isUFinite() << " " << dt.isRecursiveSingleton() << std::endl;
+ Trace("datatypes-debug") << "Datatype " << dt << " is " << dt.isFinite() << " " << dt.isInterpretedFinite() << " " << dt.isRecursiveSingleton() << std::endl;
bool continueProc = true;
if( dt.isRecursiveSingleton() ){
Trace("datatypes-debug") << "Check recursive singleton..." << std::endl;
@@ -251,7 +253,7 @@ void TheoryDatatypes::check(Effort e) {
if( consIndex==-1 ){
consIndex = j;
}
- if( options::finiteModelFind() ? !dt[ j ].isUFinite() : !dt[ j ].isFinite() ) {
+ if( !dt[ j ].isInterpretedFinite() ) {
if( !eqc || !eqc->d_selectors ){
needSplit = false;
}
@@ -311,7 +313,10 @@ void TheoryDatatypes::check(Effort e) {
//doSendLemma( lemma );
d_out->lemma( lemma, false, false, true );
}
- return;
+ added_split = true;
+ if( !options::dtBlastSplits() ){
+ return;
+ }
}
}else{
Trace("dt-split-debug") << "Do not split constructor for " << n << " : " << n.getType() << " " << dt.getNumConstructors() << std::endl;
@@ -323,6 +328,9 @@ void TheoryDatatypes::check(Effort e) {
}
++eqcs_i;
}
+ if( added_split ){
+ return;
+ }
Trace("datatypes-debug") << "Flush pending facts..." << std::endl;
flushPendingFacts();
/*
@@ -870,33 +878,36 @@ void TheoryDatatypes::merge( Node t1, Node t2 ){
//merge labels
- NodeListMap::iterator lbl_i = d_labels.find( t2 );
+ NodeIntMap::iterator lbl_i = d_labels.find( t2 );
if( lbl_i != d_labels.end() ){
Trace("datatypes-debug") << " merge labels from " << eqc2 << " " << t2 << std::endl;
- NodeList* lbl = (*lbl_i).second;
- for( NodeList::const_iterator j = lbl->begin(); j != lbl->end(); ++j ){
- Node tt = (*j).getKind()==kind::NOT ? (*j)[0] : (*j);
+ int n_label = (*lbl_i).second;
+ for( int i=0; i<n_label; i++ ){
+ Assert( i<(int)d_labels_data[ t2 ].size() );
+ Node t = d_labels_data[ t2 ][i];
+ Node tt = t.getKind()==kind::NOT ? t[0] : t;
Node t_arg;
int tindex = DatatypesRewriter::isTester( tt, t_arg );
Assert( tindex!=-1 );
- addTester( tindex, *j, eqc1, t1, t_arg );
+ addTester( tindex, t, eqc1, t1, t_arg );
if( d_conflict ){
Trace("datatypes-debug") << " conflict!" << std::endl;
return;
}
}
+
}
//merge selectors
if( !eqc1->d_selectors && eqc2->d_selectors ){
eqc1->d_selectors = true;
checkInst = true;
}
- NodeListMap::iterator sel_i = d_selector_apps.find( t2 );
+ NodeIntMap::iterator sel_i = d_selector_apps.find( t2 );
if( sel_i != d_selector_apps.end() ){
Trace("datatypes-debug") << " merge selectors from " << eqc2 << " " << t2 << std::endl;
- NodeList* sel = (*sel_i).second;
- for( NodeList::const_iterator j = sel->begin(); j != sel->end(); ++j ){
- addSelector( *j, eqc1, t1, eqc2->d_constructor.get().isNull() );
+ int n_sel = (*sel_i).second;
+ for( int j=0; j<n_sel; j++ ){
+ addSelector( d_selector_apps_data[t2][j], eqc1, t1, eqc2->d_constructor.get().isNull() );
}
}
if( checkInst ){
@@ -927,11 +938,11 @@ bool TheoryDatatypes::hasLabel( EqcInfo* eqc, Node n ){
}
Node TheoryDatatypes::getLabel( Node n ) {
- NodeListMap::iterator lbl_i = d_labels.find( n );
+ NodeIntMap::iterator lbl_i = d_labels.find( n );
if( lbl_i != d_labels.end() ){
- NodeList* lbl = (*lbl_i).second;
- if( !(*lbl).empty() && (*lbl)[ (*lbl).size() - 1 ].getKind()!=kind::NOT ){
- return (*lbl)[ (*lbl).size() - 1 ];
+ unsigned n_lbl = (*lbl_i).second;
+ if( n_lbl>0 && d_labels_data[n][ n_lbl-1 ].getKind()!=kind::NOT ){
+ return d_labels_data[n][ n_lbl-1 ];
}
}
return Node::null();
@@ -954,9 +965,9 @@ int TheoryDatatypes::getLabelIndex( EqcInfo* eqc, Node n ){
}
bool TheoryDatatypes::hasTester( Node n ) {
- NodeListMap::iterator lbl_i = d_labels.find( n );
+ NodeIntMap::iterator lbl_i = d_labels.find( n );
if( lbl_i != d_labels.end() ){
- return !(*(*lbl_i).second).empty();
+ return (*lbl_i).second>0;
}else{
return false;
}
@@ -969,13 +980,14 @@ void TheoryDatatypes::getPossibleCons( EqcInfo* eqc, Node n, std::vector< bool >
if( lindex!=-1 ){
pcons[ lindex ] = true;
}else{
- NodeListMap::iterator lbl_i = d_labels.find( n );
+ NodeIntMap::iterator lbl_i = d_labels.find( n );
if( lbl_i != d_labels.end() ){
- NodeList* lbl = (*lbl_i).second;
- for( NodeList::const_iterator i = lbl->begin(); i != lbl->end(); i++ ) {
- Assert( (*i).getKind()==NOT );
- //pcons[ Datatype::indexOf( (*i)[0].getOperator().toExpr() ) ] = false;
- int tindex = DatatypesRewriter::isTester( (*i)[0] );
+ int n_lbl = (*lbl_i).second;
+ for( int i=0; i<n_lbl; i++ ){
+ Node t = d_labels_data[n][i];
+ Assert( t.getKind()==NOT );
+ //pcons[ Datatype::indexOf( t[0].getOperator().toExpr() ) ] = false;
+ int tindex = DatatypesRewriter::isTester( t[0] );
Assert( tindex!=-1 );
pcons[ tindex ] = false;
}
@@ -984,11 +996,11 @@ void TheoryDatatypes::getPossibleCons( EqcInfo* eqc, Node n, std::vector< bool >
}
void TheoryDatatypes::getSelectorsForCons( Node r, std::map< int, bool >& sels ) {
- NodeListMap::iterator sel_i = d_selector_apps.find( r );
+ NodeIntMap::iterator sel_i = d_selector_apps.find( r );
if( sel_i != d_selector_apps.end() ){
- NodeList* sel = (*sel_i).second;
- for( NodeList::const_iterator j = sel->begin(); j != sel->end(); j++ ){
- int sindex = Datatype::indexOf( (*j).getOperator().toExpr() );
+ int n_sel = (*sel_i).second;
+ for( int j=0; j<n_sel; j++ ){
+ int sindex = Datatype::indexOf( d_selector_apps_data[r][j].getOperator().toExpr() );
sels[sindex] = true;
}
}
@@ -1055,12 +1067,13 @@ void TheoryDatatypes::addTester( int ttindex, Node t, EqcInfo* eqc, Node n, Node
}
}else{
//otherwise, scan list of labels
- NodeListMap::iterator lbl_i = d_labels.find( n );
+ NodeIntMap::iterator lbl_i = d_labels.find( n );
Assert( lbl_i != d_labels.end() );
- NodeList* lbl = (*lbl_i).second;
- for( NodeList::const_iterator i = lbl->begin(); i != lbl->end(); i++ ) {
- Assert( (*i).getKind()==NOT );
- j = *i;
+ int n_lbl = (*lbl_i).second;
+ for( int i=0; i<n_lbl; i++ ){
+ Node ti = d_labels_data[n][i];
+ Assert( ti.getKind()==NOT );
+ j = ti;
jt = j[0];
//int jtindex = Datatype::indexOf( jt.getOperator().toExpr() );
int jtindex = DatatypesRewriter::isTester( jt );
@@ -1076,16 +1089,24 @@ void TheoryDatatypes::addTester( int ttindex, Node t, EqcInfo* eqc, Node n, Node
}
if( !makeConflict ){
Debug("datatypes-labels") << "Add to labels " << t << std::endl;
- lbl->push_back( t );
+ //lbl->push_back( t );
+ d_labels[n] = n_lbl + 1;
+ if( n_lbl<(int)d_labels_data[n].size() ){
+ d_labels_data[n][n_lbl] = t;
+ }else{
+ d_labels_data[n].push_back( t );
+ }
+ n_lbl++;
+
const Datatype& dt = ((DatatypeType)(t_arg.getType()).toType()).getDatatype();
- Debug("datatypes-labels") << "Labels at " << lbl->size() << " / " << dt.getNumConstructors() << std::endl;
+ Debug("datatypes-labels") << "Labels at " << n_lbl << " / " << dt.getNumConstructors() << std::endl;
if( tpolarity ){
instantiate( eqc, n );
}else{
//check if we have reached the maximum number of testers
// in this case, add the positive tester
//this should not be done for sygus, since cases may be limited
- if( lbl->size()==dt.getNumConstructors()-1 && !dt.isSygus() ){
+ if( n_lbl==(int)dt.getNumConstructors()-1 && !dt.isSygus() ){
std::vector< bool > pcons;
getPossibleCons( eqc, n, pcons );
int testerIndex = -1;
@@ -1099,11 +1120,14 @@ void TheoryDatatypes::addTester( int ttindex, Node t, EqcInfo* eqc, Node n, Node
//we must explain why each term in the set of testers for this equivalence class is equal
std::vector< Node > eq_terms;
NodeBuilder<> nb(kind::AND);
- for( NodeList::const_iterator i = lbl->begin(); i != lbl->end(); i++ ) {
- nb << (*i);
- Assert( (*i).getKind()==NOT );
+ //for( NodeList::const_iterator i = lbl->begin(); i != lbl->end(); i++ ) {
+
+ for( int i=0; i<n_lbl; i++ ){
+ Node ti = d_labels_data[n][i];
+ nb << ti;
+ Assert( ti.getKind()==NOT );
Node t_arg2;
- DatatypesRewriter::isTester( (*i)[0], t_arg2 );
+ DatatypesRewriter::isTester( ti[0], t_arg2 );
//Assert( tindex!=-1 );
if( std::find( eq_terms.begin(), eq_terms.end(), t_arg2 )==eq_terms.end() ){
eq_terms.push_back( t_arg2 );
@@ -1140,19 +1164,26 @@ void TheoryDatatypes::addTester( int ttindex, Node t, EqcInfo* eqc, Node n, Node
void TheoryDatatypes::addSelector( Node s, EqcInfo* eqc, Node n, bool assertFacts ) {
Trace("dt-collapse-sel") << "Add selector : " << s << " to eqc(" << n << ")" << std::endl;
//check to see if it is redundant
- NodeListMap::iterator sel_i = d_selector_apps.find( n );
+ NodeIntMap::iterator sel_i = d_selector_apps.find( n );
Assert( sel_i != d_selector_apps.end() );
if( sel_i != d_selector_apps.end() ){
- NodeList* sel = (*sel_i).second;
- for( NodeList::const_iterator j = sel->begin(); j != sel->end(); ++j ){
- Node ss = *j;
+ int n_sel = (*sel_i).second;
+ for( int j=0; j<n_sel; j++ ){
+ Node ss = d_selector_apps_data[n][j];
if( s.getOperator()==ss.getOperator() && ( s.getKind()!=DT_HEIGHT_BOUND || s[1]==ss[1] ) ){
Trace("dt-collapse-sel") << "...redundant." << std::endl;
return;
}
}
//add it to the vector
- sel->push_back( s );
+ //sel->push_back( s );
+ d_selector_apps[n] = n_sel + 1;
+ if( n_sel<(int)d_selector_apps_data[n].size() ){
+ d_selector_apps_data[n][n_sel] = s;
+ }else{
+ d_selector_apps_data[n].push_back( s );
+ }
+
eqc->d_selectors = true;
}
if( assertFacts && !eqc->d_constructor.get().isNull() ){
@@ -1165,19 +1196,19 @@ void TheoryDatatypes::addConstructor( Node c, EqcInfo* eqc, Node n ){
Trace("datatypes-debug") << "Add constructor : " << c << " to eqc(" << n << ")" << std::endl;
Assert( eqc->d_constructor.get().isNull() );
//check labels
- NodeListMap::iterator lbl_i = d_labels.find( n );
+ NodeIntMap::iterator lbl_i = d_labels.find( n );
if( lbl_i != d_labels.end() ){
size_t constructorIndex = Datatype::indexOf(c.getOperator().toExpr());
- NodeList* lbl = (*lbl_i).second;
- for( NodeList::const_iterator i = lbl->begin(); i != lbl->end(); i++ ) {
- if( (*i).getKind()==NOT ){
- int tindex = DatatypesRewriter::isTester( (*i)[0] );
+ int n_lbl = (*lbl_i).second;
+ for( int i=0; i<n_lbl; i++ ){
+ Node t = d_labels_data[n][i];
+ if( t.getKind()==NOT ){
+ int tindex = DatatypesRewriter::isTester( t[0] );
Assert( tindex!=-1 );
if( tindex==(int)constructorIndex ){
- Node n = *i;
std::vector< TNode > assumptions;
- explain( *i, assumptions );
- explainEquality( c, (*i)[0][0], true, assumptions );
+ explain( t, assumptions );
+ explainEquality( c, t[0][0], true, assumptions );
d_conflictNode = mkAnd( assumptions );
Trace("dt-conflict") << "CONFLICT: Tester merge eq conflict : " << d_conflictNode << std::endl;
d_out->conflict( d_conflictNode );
@@ -1188,12 +1219,13 @@ void TheoryDatatypes::addConstructor( Node c, EqcInfo* eqc, Node n ){
}
}
//check selectors
- NodeListMap::iterator sel_i = d_selector_apps.find( n );
+ NodeIntMap::iterator sel_i = d_selector_apps.find( n );
if( sel_i != d_selector_apps.end() ){
- NodeList* sel = (*sel_i).second;
- for( NodeList::const_iterator j = sel->begin(); j != sel->end(); ++j ){
+ int n_sel = (*sel_i).second;
+ for( int j=0; j<n_sel; j++ ){
+ Node s = d_selector_apps_data[n][j];
//collapse the selector
- collapseSelector( *j, c );
+ collapseSelector( s, c );
}
}
eqc->d_constructor.set( c );
@@ -1277,61 +1309,114 @@ EqualityStatus TheoryDatatypes::getEqualityStatus(TNode a, TNode b){
return EQUALITY_FALSE_IN_MODEL;
}
-void TheoryDatatypes::computeCareGraph(){
- Trace("dt-cg") << "Compute graph for dt..." << std::endl;
- vector< pair<TNode, TNode> > currentPairs;
- for( unsigned r=0; r<2; r++ ){
- unsigned functionTerms = r==0 ? d_consTerms.size() : d_selTerms.size();
- for( unsigned i=0; i<functionTerms; i++ ){
- TNode f1 = r==0 ? d_consTerms[i] : d_selTerms[i];
- Assert(d_equalityEngine.hasTerm(f1));
- for( unsigned j=i+1; j<functionTerms; j++ ){
- TNode f2 = r==0 ? d_consTerms[j] : d_selTerms[j];
- Trace("dt-cg-debug") << "dt-cg(" << r << "): " << f1 << " and " << f2 << " " << (f1.getOperator()==f2.getOperator()) << " " << areEqual( f1, f2 ) << std::endl;
- Assert(d_equalityEngine.hasTerm(f2));
- if( f1.getOperator()==f2.getOperator() &&
- ( ( f1.getKind()!=DT_SIZE && f1.getKind()!=DT_HEIGHT_BOUND ) || f1[0].getType()==f2[0].getType() ) &&
- !areEqual( f1, f2 ) ){
- Trace("dt-cg") << "Check " << f1 << " and " << f2 << std::endl;
- bool somePairIsDisequal = false;
- currentPairs.clear();
- for (unsigned k = 0; k < f1.getNumChildren(); ++ k) {
- TNode x = f1[k];
- TNode y = f2[k];
- Assert(d_equalityEngine.hasTerm(x));
- Assert(d_equalityEngine.hasTerm(y));
- //need to consider types for parametric selectors
- if( x.getType()!=y.getType() || areDisequal(x, y) ){
- somePairIsDisequal = true;
- break;
- }else if( !d_equalityEngine.areEqual( x, y ) ){
- Trace("dt-cg") << "Arg #" << k << " is " << x << " " << y << std::endl;
- if( d_equalityEngine.isTriggerTerm(x, THEORY_DATATYPES) && d_equalityEngine.isTriggerTerm(y, THEORY_DATATYPES) ){
- TNode x_shared = d_equalityEngine.getTriggerTermRepresentative(x, THEORY_DATATYPES);
- TNode y_shared = d_equalityEngine.getTriggerTermRepresentative(y, THEORY_DATATYPES);
- Trace("dt-cg") << "Arg #" << k << " shared term is " << x_shared << " " << y_shared << std::endl;
- EqualityStatus eqStatus = d_valuation.getEqualityStatus(x_shared, y_shared);
- Trace("dt-cg") << "...eq status is " << eqStatus << std::endl;
- if( eqStatus==EQUALITY_FALSE_AND_PROPAGATED || eqStatus==EQUALITY_FALSE || eqStatus==EQUALITY_FALSE_IN_MODEL ){
- somePairIsDisequal = true;
- break;
- }else{
- currentPairs.push_back(make_pair(x_shared, y_shared));
- }
+
+
+void TheoryDatatypes::addCarePairs( quantifiers::TermArgTrie * t1, quantifiers::TermArgTrie * t2, unsigned arity, unsigned depth, unsigned& n_pairs ){
+ if( depth==arity ){
+ if( t2!=NULL ){
+ Node f1 = t1->getNodeData();
+ Node f2 = t2->getNodeData();
+ if( !areEqual( f1, f2 ) ){
+ Trace("dt-cg") << "Check " << f1 << " and " << f2 << std::endl;
+ vector< pair<TNode, TNode> > currentPairs;
+ for (unsigned k = 0; k < f1.getNumChildren(); ++ k) {
+ TNode x = f1[k];
+ TNode y = f2[k];
+ Assert( d_equalityEngine.hasTerm(x) );
+ Assert( d_equalityEngine.hasTerm(y) );
+ Assert( !areDisequal( x, y ) );
+ if( !d_equalityEngine.areEqual( x, y ) ){
+ Trace("dt-cg") << "Arg #" << k << " is " << x << " " << y << std::endl;
+ if( d_equalityEngine.isTriggerTerm(x, THEORY_DATATYPES) && d_equalityEngine.isTriggerTerm(y, THEORY_DATATYPES) ){
+ TNode x_shared = d_equalityEngine.getTriggerTermRepresentative(x, THEORY_DATATYPES);
+ TNode y_shared = d_equalityEngine.getTriggerTermRepresentative(y, THEORY_DATATYPES);
+ Trace("dt-cg") << "Arg #" << k << " shared term is " << x_shared << " " << y_shared << std::endl;
+ EqualityStatus eqStatus = d_valuation.getEqualityStatus(x_shared, y_shared);
+ Trace("dt-cg") << "...eq status is " << eqStatus << std::endl;
+ if( eqStatus==EQUALITY_FALSE_AND_PROPAGATED || eqStatus==EQUALITY_FALSE || eqStatus==EQUALITY_FALSE_IN_MODEL ){
+ //an argument is disequal, we are done
+ return;
+ }else{
+ currentPairs.push_back(make_pair(x_shared, y_shared));
}
}
}
- if (!somePairIsDisequal) {
- for (unsigned c = 0; c < currentPairs.size(); ++ c) {
- Trace("dt-cg-pair") << "Pair : " << currentPairs[c].first << " " << currentPairs[c].second << std::endl;
- addCarePair(currentPairs[c].first, currentPairs[c].second);
- }
+ }
+ for (unsigned c = 0; c < currentPairs.size(); ++ c) {
+ Trace("dt-cg-pair") << "Pair : " << currentPairs[c].first << " " << currentPairs[c].second << std::endl;
+ addCarePair(currentPairs[c].first, currentPairs[c].second);
+ n_pairs++;
+ }
+ }
+ }
+ }else{
+ if( t2==NULL ){
+ if( depth<(arity-1) ){
+ //add care pairs internal to each child
+ for( std::map< TNode, quantifiers::TermArgTrie >::iterator it = t1->d_data.begin(); it != t1->d_data.end(); ++it ){
+ addCarePairs( &it->second, NULL, arity, depth+1, n_pairs );
+ }
+ }
+ //add care pairs based on each pair of non-disequal arguments
+ for( std::map< TNode, quantifiers::TermArgTrie >::iterator it = t1->d_data.begin(); it != t1->d_data.end(); ++it ){
+ std::map< TNode, quantifiers::TermArgTrie >::iterator it2 = it;
+ ++it2;
+ for( ; it2 != t1->d_data.end(); ++it2 ){
+ if( !areDisequal(it->first, it2->first) ){
+ addCarePairs( &it->second, &it2->second, arity, depth+1, n_pairs );
+ }
+ }
+ }
+ }else{
+ //add care pairs based on product of indices, non-disequal arguments
+ for( std::map< TNode, quantifiers::TermArgTrie >::iterator it = t1->d_data.begin(); it != t1->d_data.end(); ++it ){
+ for( std::map< TNode, quantifiers::TermArgTrie >::iterator it2 = t2->d_data.begin(); it2 != t2->d_data.end(); ++it2 ){
+ if( !areDisequal(it->first, it2->first) ){
+ addCarePairs( &it->second, &it2->second, arity, depth+1, n_pairs );
}
}
}
}
}
- Trace("dt-cg") << "Done Compute graph for dt." << std::endl;
+}
+
+void TheoryDatatypes::computeCareGraph(){
+ unsigned n_pairs = 0;
+ Trace("dt-cg-summary") << "Compute graph for dt..." << d_functionTerms.size() << " " << d_sharedTerms.size() << std::endl;
+ Trace("dt-cg") << "Build indices..." << std::endl;
+ std::map< TypeNode, std::map< Node, quantifiers::TermArgTrie > > index;
+ std::map< Node, unsigned > arity;
+ //populate indices
+ unsigned functionTerms = d_functionTerms.size();
+ for( unsigned i=0; i<functionTerms; i++ ){
+ TNode f1 = d_functionTerms[i];
+ Assert(d_equalityEngine.hasTerm(f1));
+ Trace("dt-cg-debug") << "...build for " << f1 << std::endl;
+ //break into index based on operator, and type of first argument (since some operators are parametric)
+ Node op = f1.getOperator();
+ TypeNode tn = f1[0].getType();
+ std::vector< TNode > reps;
+ bool has_trigger_arg = false;
+ for( unsigned j=0; j<f1.getNumChildren(); j++ ){
+ reps.push_back( d_equalityEngine.getRepresentative( f1[j] ) );
+ if( d_equalityEngine.isTriggerTerm( f1[j], THEORY_DATATYPES ) ){
+ has_trigger_arg = true;
+ }
+ }
+ //only may contribute to care pairs if has at least one trigger argument
+ if( has_trigger_arg ){
+ index[tn][op].addTerm( f1, reps );
+ arity[op] = reps.size();
+ }
+ }
+ //for each index
+ for( std::map< TypeNode, std::map< Node, quantifiers::TermArgTrie > >::iterator iti = index.begin(); iti != index.end(); ++iti ){
+ for( std::map< Node, quantifiers::TermArgTrie >::iterator itii = iti->second.begin(); itii != iti->second.end(); ++itii ){
+ Trace("dt-cg") << "Process index " << itii->first << ", " << iti->first << "..." << std::endl;
+ addCarePairs( &itii->second, NULL, arity[ itii->first ], 0, n_pairs );
+ }
+ }
+ Trace("dt-cg-summary") << "...done, # pairs = " << n_pairs << std::endl;
}
void TheoryDatatypes::collectModelInfo( TheoryModel* m, bool fullModel ){
@@ -1443,7 +1528,7 @@ void TheoryDatatypes::collectModelInfo( TheoryModel* m, bool fullModel ){
if( neqc.isNull() ){
for( unsigned i=0; i<pcons.size(); i++ ){
//must try the infinite ones first
- bool cfinite = options::finiteModelFind() ? dt[ i ].isUFinite() : dt[ i ].isFinite();
+ bool cfinite = dt[ i ].isInterpretedFinite();
if( pcons[i] && (r==1)==cfinite ){
neqc = DatatypesRewriter::getInstCons( eqc, dt, i );
//for( unsigned j=0; j<neqc.getNumChildren(); j++ ){
@@ -1543,16 +1628,18 @@ Node TheoryDatatypes::getSingletonLemma( TypeNode tn, bool pol ) {
void TheoryDatatypes::collectTerms( Node n ) {
if( d_collectTermsCache.find( n )==d_collectTermsCache.end() ){
d_collectTermsCache[n] = true;
- for( int i=0; i<(int)n.getNumChildren(); i++ ) {
- collectTerms( n[i] );
- }
+ //for( int i=0; i<(int)n.getNumChildren(); i++ ) {
+ // collectTerms( n[i] );
+ //}
if( n.getKind() == APPLY_CONSTRUCTOR ){
Debug("datatypes") << " Found constructor " << n << endl;
- d_consTerms.push_back( n );
+ if( n.getNumChildren()>0 ){
+ d_functionTerms.push_back( n );
+ }
}else{
if( n.getKind() == APPLY_SELECTOR_TOTAL || n.getKind() == DT_SIZE || n.getKind() == DT_HEIGHT_BOUND ){
- d_selTerms.push_back( n );
+ d_functionTerms.push_back( n );
//we must also record which selectors exist
Trace("dt-collapse-sel") << " Found selector " << n << endl;
Node rep = getRepresentative( n[0] );
@@ -2040,21 +2127,19 @@ void TheoryDatatypes::printModelDebug( const char* c ){
if( hasLabel( ei, eqc ) ){
Trace( c ) << getLabel( eqc );
}else{
- NodeListMap::iterator lbl_i = d_labels.find( eqc );
+ NodeIntMap::iterator lbl_i = d_labels.find( eqc );
if( lbl_i != d_labels.end() ){
- NodeList* lbl = (*lbl_i).second;
- for( NodeList::const_iterator j = lbl->begin(); j != lbl->end(); j++ ){
- Trace( c ) << *j << " ";
+ for( int j=0; j<(*lbl_i).second; j++ ){
+ Trace( c ) << d_labels_data[eqc][j] << " ";
}
}
}
Trace( c ) << std::endl;
Trace( c ) << " Selectors : " << ( ei->d_selectors ? "yes, " : "no " );
- NodeListMap::iterator sel_i = d_selector_apps.find( eqc );
+ NodeIntMap::iterator sel_i = d_selector_apps.find( eqc );
if( sel_i != d_selector_apps.end() ){
- NodeList* sel = (*sel_i).second;
- for( NodeList::const_iterator j = sel->begin(); j != sel->end(); j++ ){
- Trace( c ) << *j << " ";
+ for( int j=0; j<(*sel_i).second; j++ ){
+ Trace( c ) << d_selector_apps_data[eqc][j] << " ";
}
}
Trace( c ) << std::endl;
diff --git a/src/theory/datatypes/theory_datatypes.h b/src/theory/datatypes/theory_datatypes.h
index 4bf04e08c..5722e7822 100644
--- a/src/theory/datatypes/theory_datatypes.h
+++ b/src/theory/datatypes/theory_datatypes.h
@@ -32,12 +32,17 @@
namespace CVC4 {
namespace theory {
+
+namespace quantifiers{
+ class TermArgTrie;
+}
+
namespace datatypes {
class TheoryDatatypes : public Theory {
private:
typedef context::CDChunkList<Node> NodeList;
- typedef context::CDHashMap<Node, NodeList*, NodeHashFunction> NodeListMap;
+ typedef context::CDHashMap< Node, int, NodeHashFunction> NodeIntMap;
typedef context::CDHashMap< Node, bool, NodeHashFunction > BoolMap;
typedef context::CDHashMap< Node, Node, NodeHashFunction > NodeMap;
@@ -157,9 +162,11 @@ private:
* NOT is_[constructor_1]( t )...NOT is_[constructor_n]( t ) followed by
* is_[constructor_(n+1)]( t ), each of which is a unique tester.
*/
- NodeListMap d_labels;
+ NodeIntMap d_labels;
+ std::map< Node, std::vector< Node > > d_labels_data;
/** selector apps for eqch equivalence class */
- NodeListMap d_selector_apps;
+ NodeIntMap d_selector_apps;
+ std::map< Node, std::vector< Node > > d_selector_apps_data;
/** constructor terms */
//BoolMap d_consEqc;
/** Are we in conflict */
@@ -176,10 +183,8 @@ private:
std::vector< Node > d_pending;
std::map< Node, Node > d_pending_exp;
std::vector< Node > d_pending_merge;
- /** All the constructor terms that the theory has seen */
- context::CDList<TNode> d_consTerms;
- /** All the selector terms that the theory has seen */
- context::CDList<TNode> d_selTerms;
+ /** All the function terms that the theory has seen */
+ context::CDList<TNode> d_functionTerms;
/** counter for forcing assignments (ensures fairness) */
unsigned d_dtfCounter;
/** expand definition skolem functions */
@@ -216,6 +221,7 @@ private:
TNode getEqcConstructor( TNode r );
protected:
+ void addCarePairs( quantifiers::TermArgTrie * t1, quantifiers::TermArgTrie * t2, unsigned arity, unsigned depth, unsigned& n_pairs );
/** compute care graph */
void computeCareGraph();
diff --git a/src/theory/datatypes/theory_datatypes_type_rules.h b/src/theory/datatypes/theory_datatypes_type_rules.h
index 5a3645691..9c8387958 100644
--- a/src/theory/datatypes/theory_datatypes_type_rules.h
+++ b/src/theory/datatypes/theory_datatypes_type_rules.h
@@ -299,11 +299,10 @@ public:
throw TypeCheckingExceptionPrivate(n, "datatype height bound must be non-negative");
}
}
- return nodeManager->integerType();
+ return nodeManager->booleanType();
}
};/* class DtHeightBoundTypeRule */
-
}/* CVC4::theory::datatypes namespace */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
diff --git a/src/theory/datatypes/type_enumerator.cpp b/src/theory/datatypes/type_enumerator.cpp
index 6c1155237..c0539743f 100644
--- a/src/theory/datatypes/type_enumerator.cpp
+++ b/src/theory/datatypes/type_enumerator.cpp
@@ -172,7 +172,7 @@ Node DatatypesEnumerator::getTermEnum( TypeNode tn, unsigned i ){
Debug("dt-enum") << "datatype is " << d_type << std::endl;
Debug("dt-enum") << "properties : " << d_datatype.isCodatatype() << " " << d_datatype.isRecursiveSingleton();
Debug("dt-enum") << " " << d_datatype.isFinite() << std::endl;
- Debug("dt-enum") << " " << d_datatype.isUFinite() << std::endl;
+ Debug("dt-enum") << " " << d_datatype.isInterpretedFinite() << std::endl;
if( d_datatype.isCodatatype() && hasCyclesDt( d_datatype ) ){
//start with uninterpreted constant
diff --git a/src/theory/datatypes/type_enumerator.h b/src/theory/datatypes/type_enumerator.h
index bbfd951b3..8473b5d69 100644
--- a/src/theory/datatypes/type_enumerator.h
+++ b/src/theory/datatypes/type_enumerator.h
@@ -159,7 +159,7 @@ public:
}
if( d_ctor>=d_has_debruijn+d_datatype.getNumConstructors() ){
//try next size limit as long as new terms were generated at last size, or other cases
- if( prevSize==d_size_limit || ( d_size_limit==0 && d_datatype.isCodatatype() ) || ( options::finiteModelFind() ? !d_datatype.isUFinite() : !d_datatype.isFinite() ) ){
+ if( prevSize==d_size_limit || ( d_size_limit==0 && d_datatype.isCodatatype() ) || !d_datatype.isInterpretedFinite() ){
d_size_limit++;
d_ctor = d_zeroCtor;
for( unsigned i=0; i<d_sel_sum.size(); i++ ){
diff --git a/src/theory/logic_info.cpp b/src/theory/logic_info.cpp
index 04cac7ae5..6ac1c5e32 100644
--- a/src/theory/logic_info.cpp
+++ b/src/theory/logic_info.cpp
@@ -270,7 +270,7 @@ std::string LogicInfo::getLogicString() const {
if(d_theories[THEORY_FP]) {
ss << "FP";
++seen;
- }
+ }
if(d_theories[THEORY_DATATYPES]) {
ss << "DT";
++seen;
@@ -296,7 +296,10 @@ std::string LogicInfo::getLogicString() const {
ss << "FS";
++seen;
}
-
+ if(d_theories[THEORY_SEP]) {
+ ss << "SEP";
+ ++seen;
+ }
if(seen != d_sharingTheories) {
Unhandled("can't extract a logic string from LogicInfo; at least one "
"active theory is unknown to LogicInfo::getLogicString() !");
@@ -439,6 +442,10 @@ void LogicInfo::setLogicString(std::string logicString) throw(IllegalArgumentExc
enableTheory(THEORY_SETS);
p += 2;
}
+ if(!strncmp(p, "SEP", 3)) {
+ enableTheory(THEORY_SEP);
+ p += 3;
+ }
}
}
if(*p != '\0') {
diff --git a/src/theory/quantifiers/alpha_equivalence.cpp b/src/theory/quantifiers/alpha_equivalence.cpp
index 80066d690..a00d6d8a1 100644..100755
--- a/src/theory/quantifiers/alpha_equivalence.cpp
+++ b/src/theory/quantifiers/alpha_equivalence.cpp
@@ -30,17 +30,30 @@ struct sortTypeOrder {
};
Node AlphaEquivalenceNode::registerNode( AlphaEquivalenceNode* aen, QuantifiersEngine* qe, Node q, std::vector< Node >& tt, std::vector< int >& arg_index ) {
+ std::map< Node, bool > visited;
while( !tt.empty() ){
if( tt.size()==arg_index.size()+1 ){
Node t = tt.back();
- Node op = t.hasOperator() ? t.getOperator() : t;
- arg_index.push_back( 0 );
+ Node op;
+ if( t.hasOperator() ){
+ if( visited.find( t )==visited.end() ){
+ visited[t] = true;
+ op = t.getOperator();
+ arg_index.push_back( 0 );
+ }else{
+ op = t;
+ arg_index.push_back( -1 );
+ }
+ }else{
+ op = t;
+ arg_index.push_back( 0 );
+ }
Trace("aeq-debug") << op << " ";
aen = &(aen->d_children[op][t.getNumChildren()]);
}else{
Node t = tt.back();
int i = arg_index.back();
- if( i==(int)t.getNumChildren() ){
+ if( i==-1 || i==(int)t.getNumChildren() ){
tt.pop_back();
arg_index.pop_back();
}else{
@@ -56,9 +69,9 @@ Node AlphaEquivalenceNode::registerNode( AlphaEquivalenceNode* aen, QuantifiersE
}else{
if( q.getNumChildren()==2 ){
//lemma ( q <=> d_quant )
- Trace("quant-ae") << "Alpha equivalent : " << std::endl;
- Trace("quant-ae") << " " << q << std::endl;
- Trace("quant-ae") << " " << aen->d_quant << std::endl;
+ Trace("alpha-eq") << "Alpha equivalent : " << std::endl;
+ Trace("alpha-eq") << " " << q << std::endl;
+ Trace("alpha-eq") << " " << aen->d_quant << std::endl;
lem = q.iffNode( aen->d_quant );
}else{
//do not reduce annotated quantified formulas based on alpha equivalence
diff --git a/src/theory/quantifiers/alpha_equivalence.h b/src/theory/quantifiers/alpha_equivalence.h
index 8e7556eb6..8e7556eb6 100644..100755
--- a/src/theory/quantifiers/alpha_equivalence.h
+++ b/src/theory/quantifiers/alpha_equivalence.h
diff --git a/src/theory/quantifiers/ambqi_builder.cpp b/src/theory/quantifiers/ambqi_builder.cpp
index 5192da7de..97116dee4 100644..100755
--- a/src/theory/quantifiers/ambqi_builder.cpp
+++ b/src/theory/quantifiers/ambqi_builder.cpp
@@ -787,7 +787,7 @@ void AbsMbqiBuilder::processBuildModel(TheoryModel* m, bool fullModel) {
Trace("ambqi-model-debug") << "Initial terms: " << std::endl;
for( size_t i=0; i<fm->d_uf_terms[f].size(); i++ ){
Node n = fm->d_uf_terms[f][i];
- if( !n.getAttribute(NoMatchAttribute()) ){
+ if( d_qe->getTermDatabase()->isTermActive( n ) ){
Trace("ambqi-model-debug") << " " << n << " -> " << fm->getRepresentativeId( n ) << std::endl;
fapps.push_back( n );
}
diff --git a/src/theory/quantifiers/ambqi_builder.h b/src/theory/quantifiers/ambqi_builder.h
index 3669d38b7..3669d38b7 100644..100755
--- a/src/theory/quantifiers/ambqi_builder.h
+++ b/src/theory/quantifiers/ambqi_builder.h
diff --git a/src/theory/quantifiers/anti_skolem.cpp b/src/theory/quantifiers/anti_skolem.cpp
index c8d18aced..c8d18aced 100644..100755
--- a/src/theory/quantifiers/anti_skolem.cpp
+++ b/src/theory/quantifiers/anti_skolem.cpp
diff --git a/src/theory/quantifiers/anti_skolem.h b/src/theory/quantifiers/anti_skolem.h
index 721371159..721371159 100644..100755
--- a/src/theory/quantifiers/anti_skolem.h
+++ b/src/theory/quantifiers/anti_skolem.h
diff --git a/src/theory/quantifiers/bounded_integers.cpp b/src/theory/quantifiers/bounded_integers.cpp
index d32ef59a1..7184624da 100644..100755
--- a/src/theory/quantifiers/bounded_integers.cpp
+++ b/src/theory/quantifiers/bounded_integers.cpp
@@ -28,7 +28,7 @@ using namespace CVC4::theory::quantifiers;
using namespace CVC4::kind;
-BoundedIntegers::RangeModel::RangeModel(BoundedIntegers * bi, Node r, context::Context* c, context::Context* u, bool isProxy) : d_bi(bi),
+BoundedIntegers::IntRangeModel::IntRangeModel(BoundedIntegers * bi, Node r, context::Context* c, context::Context* u, bool isProxy) : d_bi(bi),
d_range(r), d_curr_max(-1), d_lit_to_range(u), d_range_assertions(c), d_has_range(c,false), d_curr_range(c,-1), d_ranges_proxied(u) {
if( options::fmfBoundIntLazy() ){
d_proxy_range = isProxy ? r : NodeManager::currentNM()->mkSkolem( "pbir", r.getType() );
@@ -40,7 +40,7 @@ BoundedIntegers::RangeModel::RangeModel(BoundedIntegers * bi, Node r, context::C
}
}
-void BoundedIntegers::RangeModel::initialize() {
+void BoundedIntegers::IntRangeModel::initialize() {
//add initial split lemma
Node ltr = NodeManager::currentNM()->mkNode( LT, d_proxy_range, NodeManager::currentNM()->mkConst( Rational(0) ) );
ltr = Rewriter::rewrite( ltr );
@@ -55,7 +55,7 @@ void BoundedIntegers::RangeModel::initialize() {
d_bi->addLiteralFromRange(ltr_lit, d_range);
}
-void BoundedIntegers::RangeModel::assertNode(Node n) {
+void BoundedIntegers::IntRangeModel::assertNode(Node n) {
bool pol = n.getKind()!=NOT;
Node nlit = n.getKind()==NOT ? n[0] : n;
if( d_lit_to_range.find( nlit )!=d_lit_to_range.end() ){
@@ -93,7 +93,7 @@ void BoundedIntegers::RangeModel::assertNode(Node n) {
}
}
-void BoundedIntegers::RangeModel::allocateRange() {
+void BoundedIntegers::IntRangeModel::allocateRange() {
d_curr_max++;
int newBound = d_curr_max;
Trace("bound-int-proc") << "Allocate range bound " << newBound << " for " << d_range << std::endl;
@@ -110,7 +110,7 @@ void BoundedIntegers::RangeModel::allocateRange() {
d_bi->addLiteralFromRange(ltr_lit, d_range);
}
-Node BoundedIntegers::RangeModel::getNextDecisionRequest() {
+Node BoundedIntegers::IntRangeModel::getNextDecisionRequest() {
//request the current cardinality as a decision literal, if not already asserted
for( NodeIntMap::iterator it = d_lit_to_range.begin(); it != d_lit_to_range.end(); ++it ){
int i = (*it).second;
@@ -129,7 +129,7 @@ Node BoundedIntegers::RangeModel::getNextDecisionRequest() {
return Node::null();
}
-bool BoundedIntegers::RangeModel::proxyCurrentRange() {
+bool BoundedIntegers::IntRangeModel::proxyCurrentRange() {
//Trace("model-engine") << "Range(" << d_range << ") currently is " << d_curr_max.get() << std::endl;
if( d_range!=d_proxy_range ){
//int curr = d_curr_range.get();
@@ -148,11 +148,24 @@ bool BoundedIntegers::RangeModel::proxyCurrentRange() {
}
+
+
+
BoundedIntegers::BoundedIntegers(context::Context* c, QuantifiersEngine* qe) :
QuantifiersModule(qe), d_assertions(c){
}
+BoundedIntegers::~BoundedIntegers() {
+ for( std::map< Node, RangeModel * >::iterator it = d_rms.begin(); it != d_rms.end(); ++it ){
+ delete it->second;
+ }
+}
+
+void BoundedIntegers::presolve() {
+ d_bnd_it.clear();
+}
+
bool BoundedIntegers::isBound( Node f, Node v ) {
return std::find( d_set[f].begin(), d_set[f].end(), v )!=d_set[f].end();
}
@@ -172,62 +185,79 @@ bool BoundedIntegers::hasNonBoundVar( Node f, Node b ) {
return false;
}
-void BoundedIntegers::processLiteral( Node f, Node lit, bool pol,
+void BoundedIntegers::processLiteral( Node q, Node lit, bool pol,
+ std::map< Node, unsigned >& bound_lit_type_map,
std::map< int, std::map< Node, Node > >& bound_lit_map,
- std::map< int, std::map< Node, bool > >& bound_lit_pol_map ) {
- if( lit.getKind()==GEQ && lit[0].getType().isInteger() ){
- std::map< Node, Node > msum;
- if (QuantArith::getMonomialSumLit( lit, msum )){
- Trace("bound-int-debug") << "Literal (polarity = " << pol << ") " << lit << " is monomial sum : " << std::endl;
- QuantArith::debugPrintMonomialSum( msum, "bound-int-debug" );
- for( std::map< Node, Node >::iterator it = msum.begin(); it != msum.end(); ++it ){
- if ( !it->first.isNull() && it->first.getKind()==BOUND_VARIABLE && !isBound( f, it->first ) ){
- Node veq;
- if( QuantArith::isolate( it->first, msum, veq, GEQ )!=0 ){
- Node n1 = veq[0];
- Node n2 = veq[1];
- if(pol){
- //flip
- n1 = veq[1];
- n2 = veq[0];
- if( n1.getKind()==BOUND_VARIABLE ){
- n2 = QuantArith::offset( n2, 1 );
+ std::map< int, std::map< Node, bool > >& bound_lit_pol_map,
+ std::map< int, std::map< Node, Node > >& bound_int_range_term ) {
+ if( lit.getKind()==GEQ ){
+ if( lit[0].getType().isInteger() ){
+ std::map< Node, Node > msum;
+ if( QuantArith::getMonomialSumLit( lit, msum ) ){
+ Trace("bound-int-debug") << "Literal (polarity = " << pol << ") " << lit << " is monomial sum : " << std::endl;
+ QuantArith::debugPrintMonomialSum( msum, "bound-int-debug" );
+ for( std::map< Node, Node >::iterator it = msum.begin(); it != msum.end(); ++it ){
+ if ( !it->first.isNull() && it->first.getKind()==BOUND_VARIABLE && !isBound( q, it->first ) ){
+ Node veq;
+ if( QuantArith::isolate( it->first, msum, veq, GEQ )!=0 ){
+ Node n1 = veq[0];
+ Node n2 = veq[1];
+ if(pol){
+ //flip
+ n1 = veq[1];
+ n2 = veq[0];
+ if( n1.getKind()==BOUND_VARIABLE ){
+ n2 = QuantArith::offset( n2, 1 );
+ }else{
+ n1 = QuantArith::offset( n1, -1 );
+ }
+ veq = NodeManager::currentNM()->mkNode( GEQ, n1, n2 );
+ }
+ Trace("bound-int-debug") << "Isolated for " << it->first << " : (" << n1 << " >= " << n2 << ")" << std::endl;
+ Node t = n1==it->first ? n2 : n1;
+ if( !hasNonBoundVar( q, t ) ) {
+ Trace("bound-int-debug") << "The bound is relevant." << std::endl;
+ int loru = n1==it->first ? 0 : 1;
+ bound_lit_type_map[it->first] = BOUND_INT_RANGE;
+ bound_int_range_term[loru][it->first] = t;
+ bound_lit_map[loru][it->first] = lit;
+ bound_lit_pol_map[loru][it->first] = pol;
}else{
- n1 = QuantArith::offset( n1, -1 );
+ Trace("bound-int-debug") << "The term " << t << " has non-bound variable." << std::endl;
}
- veq = NodeManager::currentNM()->mkNode( GEQ, n1, n2 );
- }
- Trace("bound-int-debug") << "Isolated for " << it->first << " : (" << n1 << " >= " << n2 << ")" << std::endl;
- Node t = n1==it->first ? n2 : n1;
- if( !hasNonBoundVar( f, t ) ) {
- Trace("bound-int-debug") << "The bound is relevant." << std::endl;
- int loru = n1==it->first ? 0 : 1;
- d_bounds[loru][f][it->first] = t;
- bound_lit_map[loru][it->first] = lit;
- bound_lit_pol_map[loru][it->first] = pol;
- }else{
- Trace("bound-int-debug") << "The term " << t << " has non-bound variable." << std::endl;
}
}
}
}
}
+ }else if( lit.getKind()==MEMBER ){
+ //TODO: enable this when sets models are fixed
+ /*
+ if( !pol && lit[0].getKind()==BOUND_VARIABLE && !isBound( q, lit[0] ) && !lit[1].hasBoundVar() ){
+ Trace("bound-int-debug") << "Literal (polarity = " << pol << ") " << lit << " is membership." << std::endl;
+ bound_lit_type_map[lit[0]] = BOUND_SET_MEMBER;
+ bound_lit_map[0][lit[0]] = lit;
+ bound_lit_pol_map[0][lit[0]] = pol;
+ }
+ */
}else if( lit.getKind()==LEQ || lit.getKind()==LT || lit.getKind()==GT ) {
Message() << "BoundedIntegers : Bad kind for literal : " << lit << std::endl;
}
}
-void BoundedIntegers::process( Node f, Node n, bool pol,
+void BoundedIntegers::process( Node q, Node n, bool pol,
+ std::map< Node, unsigned >& bound_lit_type_map,
std::map< int, std::map< Node, Node > >& bound_lit_map,
- std::map< int, std::map< Node, bool > >& bound_lit_pol_map ){
+ std::map< int, std::map< Node, bool > >& bound_lit_pol_map,
+ std::map< int, std::map< Node, Node > >& bound_int_range_term ){
if( (n.getKind()==OR && pol) || (n.getKind()==AND && !pol) ){
for( unsigned i=0; i<n.getNumChildren(); i++) {
- process( f, n[i], pol, bound_lit_map, bound_lit_pol_map );
+ process( q, n[i], pol, bound_lit_type_map, bound_lit_map, bound_lit_pol_map, bound_int_range_term );
}
}else if( n.getKind()==NOT ){
- process( f, n[0], !pol, bound_lit_map, bound_lit_pol_map );
+ process( q, n[0], !pol, bound_lit_type_map, bound_lit_map, bound_lit_pol_map, bound_int_range_term );
}else {
- processLiteral( f, n, pol, bound_lit_map, bound_lit_pol_map );
+ processLiteral( q, n, pol, bound_lit_type_map, bound_lit_map, bound_lit_pol_map, bound_int_range_term );
}
}
@@ -258,58 +288,99 @@ void BoundedIntegers::addLiteralFromRange( Node lit, Node r ) {
}
}
+void BoundedIntegers::setBoundedVar( Node q, Node v, unsigned bound_type ) {
+ d_bound_type[q][v] = bound_type;
+ d_set_nums[q][v] = d_set[q].size();
+ d_set[q].push_back( v );
+ Trace("bound-int-var") << "Bound variable #" << d_set_nums[q][v] << " : " << v << std::endl;
+}
+
void BoundedIntegers::registerQuantifier( Node f ) {
Trace("bound-int") << "Register quantifier " << f << std::endl;
- bool hasIntType = false;
- int finiteTypes = 0;
- std::map< Node, int > numMap;
- for( unsigned i=0; i<f[0].getNumChildren(); i++) {
- numMap[f[0][i]] = i;
- if( f[0][i].getType().isInteger() ){
- hasIntType = true;
- }
- else if( f[0][i].getType().isSort() || f[0][i].getType().getCardinality().isFinite() ){
- finiteTypes++;
- }
- }
- if( hasIntType ){
- bool success;
- do{
- std::map< int, std::map< Node, Node > > bound_lit_map;
- std::map< int, std::map< Node, bool > > bound_lit_pol_map;
- success = false;
- process( f, f[1], true, bound_lit_map, bound_lit_pol_map );
- for( std::map< Node, Node >::iterator it = d_bounds[0][f].begin(); it != d_bounds[0][f].end(); ++it ){
- Node v = it->first;
- if( !isBound(f,v) ){
- if( d_bounds[1][f].find(v)!=d_bounds[1][f].end() ){
- d_set[f].push_back(v);
- d_set_nums[f].push_back(numMap[v]);
+
+ bool success;
+ do{
+ std::map< Node, unsigned > bound_lit_type_map;
+ std::map< int, std::map< Node, Node > > bound_lit_map;
+ std::map< int, std::map< Node, bool > > bound_lit_pol_map;
+ std::map< int, std::map< Node, Node > > bound_int_range_term;
+ success = false;
+ process( f, f[1], true, bound_lit_type_map, bound_lit_map, bound_lit_pol_map, bound_int_range_term );
+ //for( std::map< Node, Node >::iterator it = d_bounds[0][f].begin(); it != d_bounds[0][f].end(); ++it ){
+ for( std::map< Node, unsigned >::iterator it = bound_lit_type_map.begin(); it != bound_lit_type_map.end(); ++it ){
+ Node v = it->first;
+ if( !isBound( f, v ) ){
+ bool setBoundVar = false;
+ if( it->second==BOUND_INT_RANGE ){
+ //must have both
+ if( bound_lit_map[0].find( v )!=bound_lit_map[0].end() && bound_lit_map[1].find( v )!=bound_lit_map[1].end() ){
+ setBoundedVar( f, v, BOUND_INT_RANGE );
+ setBoundVar = true;
success = true;
- //set Attributes on literals
for( unsigned b=0; b<2; b++ ){
- Assert( bound_lit_map[b].find( v )!=bound_lit_map[b].end() );
+ //set the bounds
+ Assert( bound_int_range_term[b].find( v )!=bound_int_range_term[b].end() );
+ d_bounds[b][f][v] = bound_int_range_term[b][v];
+ }
+ Node r = NodeManager::currentNM()->mkNode( MINUS, d_bounds[1][f][v], d_bounds[0][f][v] );
+ d_range[f][v] = Rewriter::rewrite( r );
+ Trace("bound-int") << "Variable " << v << " is bound because of int range literals " << bound_lit_map[0][v] << " and " << bound_lit_map[1][v] << std::endl;
+ }
+ }else if( it->second==BOUND_SET_MEMBER ){
+ setBoundedVar( f, v, BOUND_SET_MEMBER );
+ setBoundVar = true;
+ d_setm_range[f][v] = bound_lit_map[0][v][1];
+ Trace("bound-int") << "Variable " << v << " is bound because of set membership literal " << bound_lit_map[0][v] << std::endl;
+ }
+ if( setBoundVar ){
+ //set Attributes on literals
+ for( unsigned b=0; b<2; b++ ){
+ if( bound_lit_map[b].find( v )!=bound_lit_map[b].end() ){
Assert( bound_lit_pol_map[b].find( v )!=bound_lit_pol_map[b].end() );
BoundIntLitAttribute bila;
bound_lit_map[b][v].setAttribute( bila, bound_lit_pol_map[b][v] ? 1 : 0 );
+ }else{
+ Assert( it->second!=BOUND_INT_RANGE );
}
- Trace("bound-int") << "Variable " << v << " is bound because of literals " << bound_lit_map[0][v] << " and " << bound_lit_map[1][v] << std::endl;
}
}
}
- }while( success );
- Trace("bound-int") << "Bounds are : " << std::endl;
- for( unsigned i=0; i<d_set[f].size(); i++) {
- Node v = d_set[f][i];
- Node r = NodeManager::currentNM()->mkNode( MINUS, d_bounds[1][f][v], d_bounds[0][f][v] );
- d_range[f][v] = Rewriter::rewrite( r );
+ }
+ }while( success );
+
+ Trace("bound-int") << "Bounds are : " << std::endl;
+ for( unsigned i=0; i<d_set[f].size(); i++) {
+ Node v = d_set[f][i];
+ if( d_bound_type[f][v]==BOUND_INT_RANGE ){
Trace("bound-int") << " " << d_bounds[0][f][v] << " <= " << v << " <= " << d_bounds[1][f][v] << " (range is " << d_range[f][v] << ")" << std::endl;
+ }else if( d_bound_type[f][v]==BOUND_SET_MEMBER ){
+ Trace("bound-int") << " " << v << " in " << d_setm_range[f][v] << std::endl;
+ }
+ }
+
+ bool bound_success = true;
+ for( unsigned i=0; i<f[0].getNumChildren(); i++) {
+ if( d_bound_type[f].find( f[0][i] )==d_bound_type[f].end() ){
+ TypeNode tn = f[0][i].getType();
+ if( !tn.isSort() && !getTermDatabase()->mayComplete( tn ) ){
+ Trace("bound-int-warn") << "Warning : Bounded Integers : Due to quantification on " << f[0][i] << ", could not find bounds for " << f << std::endl;
+ bound_success = false;
+ break;
+ }
}
- if( d_set[f].size()==(f[0].getNumChildren()-finiteTypes) ){
- d_bound_quants.push_back( f );
- for( unsigned i=0; i<d_set[f].size(); i++) {
- Node v = d_set[f][i];
- Node r = d_range[f][v];
+ }
+
+ if( bound_success ){
+ d_bound_quants.push_back( f );
+ for( unsigned i=0; i<d_set[f].size(); i++) {
+ Node v = d_set[f][i];
+ if( d_bound_type[f][v]==BOUND_INT_RANGE || d_bound_type[f][v]==BOUND_SET_MEMBER ){
+ Node r;
+ if( d_bound_type[f][v]==BOUND_INT_RANGE ){
+ r = d_range[f][v];
+ }else if( d_bound_type[f][v]==BOUND_SET_MEMBER ){
+ r = NodeManager::currentNM()->mkNode( CARD, d_setm_range[f][v] );
+ }
bool isProxy = false;
if( r.hasBoundVar() ){
//introduce a new bound
@@ -319,18 +390,15 @@ void BoundedIntegers::registerQuantifier( Node f ) {
r = new_range;
isProxy = true;
}
- if( r.getKind()!=CONST_RATIONAL ){
+ if( !r.isConst() ){
if( std::find(d_ranges.begin(), d_ranges.end(), r)==d_ranges.end() ){
- Trace("bound-int") << "For " << v << ", bounded Integer Module will try to minimize : " << r << " " << r.getKind() << std::endl;
+ Trace("bound-int") << "For " << v << ", bounded Integer Module will try to minimize : " << r << std::endl;
d_ranges.push_back( r );
- d_rms[r] = new RangeModel(this, r, d_quantEngine->getSatContext(), d_quantEngine->getUserContext(), isProxy );
+ d_rms[r] = new IntRangeModel( this, r, d_quantEngine->getSatContext(), d_quantEngine->getUserContext(), isProxy );
d_rms[r]->initialize();
}
}
}
- }else{
- Trace("bound-int-warn") << "Warning : Bounded Integers : Could not find bounds for " << f << std::endl;
- //Message() << "Bound integers : Cannot infer bounds of " << f << std::endl;
}
}
}
@@ -376,39 +444,28 @@ Node BoundedIntegers::getNextDecisionRequest() {
return Node::null();
}
+unsigned BoundedIntegers::getBoundVarType( Node q, Node v ) {
+ std::map< Node, unsigned >::iterator it = d_bound_type[q].find( v );
+ if( it==d_bound_type[q].end() ){
+ return BOUND_NONE;
+ }else{
+ return it->second;
+ }
+}
+
void BoundedIntegers::getBounds( Node f, Node v, RepSetIterator * rsi, Node & l, Node & u ) {
l = d_bounds[0][f][v];
u = d_bounds[1][f][v];
if( d_nground_range[f].find(v)!=d_nground_range[f].end() ){
- //must create substitution
+ //get the substitution
std::vector< Node > vars;
std::vector< Node > subs;
- Trace("bound-int-rsi") << "Get bound value in model of variable " << v << std::endl;
- for( unsigned i=0; i<d_set[f].size(); i++) {
- if( d_set[f][i]!=v ){
- Trace("bound-int-rsi") << "Look up the value for " << d_set[f][i] << " " << rsi->d_var_order[d_set_nums[f][i]] << std::endl;
- Trace("bound-int-rsi") << "term : " << rsi->getTerm(rsi->d_var_order[d_set_nums[f][i]]) << std::endl;
- vars.push_back(d_set[f][i]);
- subs.push_back(rsi->getTerm(rsi->d_var_order[d_set_nums[f][i]]));
- }else{
- break;
- }
- }
- Trace("bound-int-rsi") << "Do substitution..." << std::endl;
- //check if it has been instantiated
- if (!vars.empty() && !d_bnd_it[f][v].hasInstantiated(subs)){
- //must add the lemma
- Node nn = d_nground_range[f][v];
- nn = nn.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
- Node lem = NodeManager::currentNM()->mkNode( LEQ, nn, d_range[f][v] );
- Trace("bound-int-lemma") << "*** Add lemma to minimize instantiated non-ground term " << lem << std::endl;
- d_quantEngine->getOutputChannel().lemma(lem, false, true);
- l = Node::null();
- u = Node::null();
- return;
- }else{
+ if( getRsiSubsitution( f, v, vars, subs, rsi ) ){
u = u.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
l = l.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
+ }else{
+ u = Node::null();
+ l = Node::null();
}
}
}
@@ -416,12 +473,86 @@ void BoundedIntegers::getBounds( Node f, Node v, RepSetIterator * rsi, Node & l,
void BoundedIntegers::getBoundValues( Node f, Node v, RepSetIterator * rsi, Node & l, Node & u ) {
getBounds( f, v, rsi, l, u );
Trace("bound-int-rsi") << "Get value in model for..." << l << " and " << u << std::endl;
- l = d_quantEngine->getModel()->getCurrentModelValue( l );
- u = d_quantEngine->getModel()->getCurrentModelValue( u );
+ if( !l.isNull() ){
+ l = d_quantEngine->getModel()->getCurrentModelValue( l );
+ }
+ if( !u.isNull() ){
+ u = d_quantEngine->getModel()->getCurrentModelValue( u );
+ }
Trace("bound-int-rsi") << "Value is " << l << " ... " << u << std::endl;
return;
}
-bool BoundedIntegers::isGroundRange(Node f, Node v) {
- return isBoundVar(f,v) && !getLowerBound(f,v).hasBoundVar() && !getUpperBound(f,v).hasBoundVar();
+bool BoundedIntegers::isGroundRange( Node q, Node v ) {
+ if( isBoundVar(q,v) ){
+ if( d_bound_type[q][v]==BOUND_INT_RANGE ){
+ return !getLowerBound(q,v).hasBoundVar() && !getUpperBound(q,v).hasBoundVar();
+ }else if( d_bound_type[q][v]==BOUND_SET_MEMBER ){
+ return !d_setm_range[q][v].hasBoundVar();
+ }
+ }
+ return false;
}
+
+Node BoundedIntegers::getSetRange( Node q, Node v, RepSetIterator * rsi ) {
+ Node sr = d_setm_range[q][v];
+ if( d_nground_range[q].find(v)!=d_nground_range[q].end() ){
+ //get the substitution
+ std::vector< Node > vars;
+ std::vector< Node > subs;
+ if( getRsiSubsitution( q, v, vars, subs, rsi ) ){
+ sr = sr.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
+ }else{
+ sr = Node::null();
+ }
+ }
+ return sr;
+}
+
+Node BoundedIntegers::getSetRangeValue( Node q, Node v, RepSetIterator * rsi ) {
+ Node sr = getSetRange( q, v, rsi );
+ if( !sr.isNull() ){
+ Trace("bound-int-rsi") << "Get value in model for..." << sr << std::endl;
+ sr = d_quantEngine->getModel()->getCurrentModelValue( sr );
+ Trace("bound-int-rsi") << "Value is " << sr << std::endl;
+ }
+ return sr;
+}
+
+bool BoundedIntegers::getRsiSubsitution( Node q, Node v, std::vector< Node >& vars, std::vector< Node >& subs, RepSetIterator * rsi ) {
+
+ Trace("bound-int-rsi") << "Get bound value in model of variable " << v << std::endl;
+ Assert( d_set_nums[q].find( v )!=d_set_nums[q].end() );
+ int vindex = d_set_nums[q][v];
+ Assert( d_set_nums[q][v]==vindex );
+ Trace("bound-int-rsi-debug") << " index order is " << vindex << std::endl;
+ //must take substitution for all variables that are iterating at higher level
+ for( int i=0; i<vindex; i++) {
+ Assert( d_set_nums[q][d_set[q][i]]==i );
+ Trace("bound-int-rsi") << "Look up the value for " << d_set[q][i] << " " << i << std::endl;
+ int v = rsi->getVariableOrder( i );
+ Assert( q[0][v]==d_set[q][i] );
+ Node t = rsi->getCurrentTerm( v );
+ Trace("bound-int-rsi") << "term : " << t << std::endl;
+ vars.push_back( d_set[q][i] );
+ subs.push_back( t );
+ }
+
+ //check if it has been instantiated
+ if( !vars.empty() && !d_bnd_it[q][v].hasInstantiated(subs) ){
+ if( d_bound_type[q][v]==BOUND_INT_RANGE ){
+ //must add the lemma
+ Node nn = d_nground_range[q][v];
+ nn = nn.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
+ Node lem = NodeManager::currentNM()->mkNode( LEQ, nn, d_range[q][v] );
+ Trace("bound-int-lemma") << "*** Add lemma to minimize instantiated non-ground term " << lem << std::endl;
+ d_quantEngine->getOutputChannel().lemma(lem, false, true);
+ }else{
+ //TODO : sets
+ }
+ return false;
+ }else{
+ return true;
+ }
+}
+
diff --git a/src/theory/quantifiers/bounded_integers.h b/src/theory/quantifiers/bounded_integers.h
index 7d15097bd..ab4bcba96 100644..100755
--- a/src/theory/quantifiers/bounded_integers.h
+++ b/src/theory/quantifiers/bounded_integers.h
@@ -39,31 +39,57 @@ class BoundedIntegers : public QuantifiersModule
typedef context::CDHashMap<Node, int, NodeHashFunction> NodeIntMap;
typedef context::CDHashMap<Node, Node, NodeHashFunction> NodeNodeMap;
typedef context::CDHashMap<int, bool> IntBoolMap;
+public:
+ enum {
+ BOUND_FINITE,
+ BOUND_INT_RANGE,
+ BOUND_SET_MEMBER,
+ BOUND_NONE
+ };
private:
//for determining bounds
bool isBound( Node f, Node v );
bool hasNonBoundVar( Node f, Node b );
- std::map< Node, std::map< Node, Node > > d_bounds[2];
+ //bound type
+ std::map< Node, std::map< Node, unsigned > > d_bound_type;
std::map< Node, std::vector< Node > > d_set;
- std::map< Node, std::vector< int > > d_set_nums;
+ std::map< Node, std::map< Node, int > > d_set_nums;
+ //integer lower/upper bounds
+ std::map< Node, std::map< Node, Node > > d_bounds[2];
std::map< Node, std::map< Node, Node > > d_range;
std::map< Node, std::map< Node, Node > > d_nground_range;
+ //set membership range
+ std::map< Node, std::map< Node, Node > > d_setm_range;
void hasFreeVar( Node f, Node n );
void process( Node f, Node n, bool pol,
+ std::map< Node, unsigned >& bound_lit_type_map,
std::map< int, std::map< Node, Node > >& bound_lit_map,
- std::map< int, std::map< Node, bool > >& bound_lit_pol_map );
+ std::map< int, std::map< Node, bool > >& bound_lit_pol_map,
+ std::map< int, std::map< Node, Node > >& bound_int_range_term );
void processLiteral( Node f, Node lit, bool pol,
+ std::map< Node, unsigned >& bound_lit_type_map,
std::map< int, std::map< Node, Node > >& bound_lit_map,
- std::map< int, std::map< Node, bool > >& bound_lit_pol_map );
+ std::map< int, std::map< Node, bool > >& bound_lit_pol_map,
+ std::map< int, std::map< Node, Node > >& bound_int_range_term );
std::vector< Node > d_bound_quants;
private:
class RangeModel {
+ public:
+ RangeModel(){}
+ virtual ~RangeModel(){}
+ virtual void initialize() = 0;
+ virtual void assertNode(Node n) = 0;
+ virtual Node getNextDecisionRequest() = 0;
+ virtual bool proxyCurrentRange() = 0;
+ };
+ class IntRangeModel : public RangeModel {
private:
BoundedIntegers * d_bi;
void allocateRange();
Node d_proxy_range;
public:
- RangeModel(BoundedIntegers * bi, Node r, context::Context* c, context::Context* u, bool isProxy);
+ IntRangeModel( BoundedIntegers * bi, Node r, context::Context* c, context::Context* u, bool isProxy);
+ virtual ~IntRangeModel(){}
Node d_range;
int d_curr_max;
std::map< int, Node > d_range_literal;
@@ -108,27 +134,36 @@ private:
std::map< Node, std::map< Node, BoundInstTrie > > d_bnd_it;
private:
void addLiteralFromRange( Node lit, Node r );
+
+ void setBoundedVar( Node f, Node v, unsigned bound_type );
public:
BoundedIntegers( context::Context* c, QuantifiersEngine* qe );
- ~BoundedIntegers() throw() {}
-
+ virtual ~BoundedIntegers();
+
+ void presolve();
bool needsCheck( Theory::Effort e );
void check( Theory::Effort e, unsigned quant_e );
void registerQuantifier( Node f );
void assertNode( Node n );
Node getNextDecisionRequest();
- bool isBoundVar( Node f, Node v ) { return std::find( d_set[f].begin(), d_set[f].end(), v )!=d_set[f].end(); }
- unsigned getNumBoundVars( Node f ) { return d_set[f].size(); }
- Node getBoundVar( Node f, int i ) { return d_set[f][i]; }
- int getBoundVarNum( Node f, int i ) { return d_set_nums[f][i]; }
- Node getLowerBound( Node f, Node v ){ return d_bounds[0][f][v]; }
- Node getUpperBound( Node f, Node v ){ return d_bounds[1][f][v]; }
+ bool isBoundVar( Node q, Node v ) { return std::find( d_set[q].begin(), d_set[q].end(), v )!=d_set[q].end(); }
+ unsigned getBoundVarType( Node q, Node v );
+ unsigned getNumBoundVars( Node q ) { return d_set[q].size(); }
+ Node getBoundVar( Node q, int i ) { return d_set[q][i]; }
+ //for integer range
+ Node getLowerBound( Node q, Node v ){ return d_bounds[0][q][v]; }
+ Node getUpperBound( Node q, Node v ){ return d_bounds[1][q][v]; }
void getBounds( Node f, Node v, RepSetIterator * rsi, Node & l, Node & u );
void getBoundValues( Node f, Node v, RepSetIterator * rsi, Node & l, Node & u );
bool isGroundRange(Node f, Node v);
+ //for set range
+ Node getSetRange( Node q, Node v, RepSetIterator * rsi );
+ Node getSetRangeValue( Node q, Node v, RepSetIterator * rsi );
/** Identify this module */
std::string identify() const { return "BoundedIntegers"; }
+private:
+ bool getRsiSubsitution( Node q, Node v, std::vector< Node >& vars, std::vector< Node >& subs, RepSetIterator * rsi );
};
}
diff --git a/src/theory/quantifiers/candidate_generator.cpp b/src/theory/quantifiers/candidate_generator.cpp
index 43f5ee2fd..a0d9bda0f 100644..100755
--- a/src/theory/quantifiers/candidate_generator.cpp
+++ b/src/theory/quantifiers/candidate_generator.cpp
@@ -28,7 +28,7 @@ using namespace CVC4::theory;
using namespace CVC4::theory::inst;
bool CandidateGenerator::isLegalCandidate( Node n ){
- return ( !n.getAttribute(NoMatchAttribute()) && ( !options::cbqi() || !quantifiers::TermDb::hasInstConstAttr(n) ) );
+ return d_qe->getTermDatabase()->isTermActive( n ) && ( !options::cbqi() || !quantifiers::TermDb::hasInstConstAttr(n) );
}
void CandidateGeneratorQueue::addCandidate( Node n ) {
@@ -59,7 +59,7 @@ Node CandidateGeneratorQueue::getNextCandidate(){
}
CandidateGeneratorQE::CandidateGeneratorQE( QuantifiersEngine* qe, Node pat ) :
- d_qe( qe ), d_term_iter( -1 ){
+CandidateGenerator( qe ), d_term_iter( -1 ){
d_op = qe->getTermDatabase()->getMatchOperator( pat );
Assert( !d_op.isNull() );
d_op_arity = pat.getNumChildren();
@@ -186,7 +186,7 @@ Node CandidateGeneratorQE::getNextCandidate(){
}
CandidateGeneratorQELitEq::CandidateGeneratorQELitEq( QuantifiersEngine* qe, Node mpat ) :
- d_match_pattern( mpat ), d_qe( qe ){
+ CandidateGenerator( qe ), d_match_pattern( mpat ){
Assert( mpat.getKind()==EQUAL );
for( unsigned i=0; i<2; i++ ){
if( !quantifiers::TermDb::hasInstConstAttr(mpat[i]) ){
@@ -225,7 +225,7 @@ Node CandidateGeneratorQELitEq::getNextCandidate(){
CandidateGeneratorQELitDeq::CandidateGeneratorQELitDeq( QuantifiersEngine* qe, Node mpat ) :
- d_match_pattern( mpat ), d_qe( qe ){
+CandidateGenerator( qe ), d_match_pattern( mpat ){
Assert( d_match_pattern.getKind()==EQUAL || d_match_pattern.getKind()==IFF );
d_match_pattern_type = d_match_pattern[0].getType();
@@ -259,7 +259,7 @@ Node CandidateGeneratorQELitDeq::getNextCandidate(){
CandidateGeneratorQEAll::CandidateGeneratorQEAll( QuantifiersEngine* qe, Node mpat ) :
- d_match_pattern( mpat ), d_qe( qe ){
+ CandidateGenerator( qe ), d_match_pattern( mpat ){
d_match_pattern_type = mpat.getType();
Assert( mpat.getKind()==INST_CONSTANT );
d_f = quantifiers::TermDb::getInstConstAttr( mpat );
diff --git a/src/theory/quantifiers/candidate_generator.h b/src/theory/quantifiers/candidate_generator.h
index 18ef6a086..4fc6969fc 100644..100755
--- a/src/theory/quantifiers/candidate_generator.h
+++ b/src/theory/quantifiers/candidate_generator.h
@@ -33,8 +33,10 @@ namespace inst {
/** base class for generating candidates for matching */
class CandidateGenerator {
+protected:
+ QuantifiersEngine* d_qe;
public:
- CandidateGenerator(){}
+ CandidateGenerator( QuantifiersEngine* qe ) : d_qe( qe ){}
virtual ~CandidateGenerator(){}
/** Get candidates functions. These set up a context to get all match candidates.
@@ -54,7 +56,7 @@ public:
virtual void resetInstantiationRound() = 0;
public:
/** legal candidate */
- static bool isLegalCandidate( Node n );
+ bool isLegalCandidate( Node n );
};/* class CandidateGenerator */
/** candidate generator queue (for manual candidate generation) */
@@ -63,7 +65,7 @@ private:
std::vector< Node > d_candidates;
int d_candidate_index;
public:
- CandidateGeneratorQueue() : d_candidate_index( 0 ){}
+ CandidateGeneratorQueue( QuantifiersEngine* qe ) : CandidateGenerator( qe ), d_candidate_index( 0 ){}
~CandidateGeneratorQueue() throw() {}
void addCandidate( Node n );
@@ -80,8 +82,6 @@ class CandidateGeneratorQE : public CandidateGenerator
private:
//operator you are looking for
Node d_op;
- //instantiator pointer
- QuantifiersEngine* d_qe;
//the equality class iterator
unsigned d_op_arity;
std::vector< quantifiers::TermArgTrie* > d_tindex;
@@ -122,8 +122,6 @@ private:
Node d_match_pattern;
Node d_match_gterm;
bool d_do_mgt;
- //einstantiator pointer
- QuantifiersEngine* d_qe;
public:
CandidateGeneratorQELitEq( QuantifiersEngine* qe, Node mpat );
~CandidateGeneratorQELitEq() throw() {}
@@ -142,8 +140,6 @@ private:
Node d_match_pattern;
//type of disequality
TypeNode d_match_pattern_type;
- //einstantiator pointer
- QuantifiersEngine* d_qe;
public:
CandidateGeneratorQELitDeq( QuantifiersEngine* qe, Node mpat );
~CandidateGeneratorQELitDeq() throw() {}
@@ -161,8 +157,6 @@ private:
//equality you are trying to match equalities for
Node d_match_pattern;
TypeNode d_match_pattern_type;
- //einstantiator pointer
- QuantifiersEngine* d_qe;
// quantifier/index for the variable we are matching
Node d_f;
unsigned d_index;
diff --git a/src/theory/quantifiers/ce_guided_instantiation.cpp b/src/theory/quantifiers/ce_guided_instantiation.cpp
index d9059a3e6..71bf7c426 100644..100755
--- a/src/theory/quantifiers/ce_guided_instantiation.cpp
+++ b/src/theory/quantifiers/ce_guided_instantiation.cpp
@@ -21,6 +21,8 @@
#include "theory/quantifiers/first_order_model.h"
#include "theory/quantifiers/term_database.h"
#include "theory/theory_engine.h"
+#include "prop/prop_engine.h"
+#include "theory/bv/theory_bv_rewriter.h"
using namespace CVC4::kind;
using namespace std;
@@ -46,7 +48,7 @@ void CegConjecture::assign( Node q ) {
Assert( q.getKind()==FORALL );
d_assert_quant = q;
//register with single invocation if applicable
- if( d_qe->getTermDatabase()->isQAttrSygus( d_assert_quant ) && options::cegqiSingleInv() ){
+ if( d_qe->getTermDatabase()->isQAttrSygus( d_assert_quant ) && options::cegqiSingleInvMode()!=CEGQI_SI_MODE_NONE ){
d_ceg_si->initialize( q );
if( q!=d_ceg_si->d_quant ){
//Node red_lem = NodeManager::currentNM()->mkNode( OR, q.negate(), d_cegqi_si->d_quant );
@@ -55,12 +57,15 @@ void CegConjecture::assign( Node q ) {
}
}
d_quant = q;
+ Assert( d_candidates.empty() );
+ std::vector< Node > vars;
for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
+ vars.push_back( q[0][i] );
d_candidates.push_back( NodeManager::currentNM()->mkSkolem( "e", q[0][i].getType() ) );
}
Trace("cegqi") << "Base quantified formula is : " << q << std::endl;
//construct base instantiation
- d_base_inst = Rewriter::rewrite( d_qe->getInstantiation( q, d_candidates ) );
+ d_base_inst = Rewriter::rewrite( d_qe->getInstantiation( q, vars, d_candidates ) );
Trace("cegqi") << "Base instantiation is : " << d_base_inst << std::endl;
if( d_qe->getTermDatabase()->isQAttrSygus( d_assert_quant ) ){
CegInstantiation::collectDisjuncts( d_base_inst, d_base_disj );
@@ -130,14 +135,18 @@ Node CegConjecture::getLiteral( QuantifiersEngine * qe, int i ) {
qe->getOutputChannel().lemma( lem );
qe->getOutputChannel().requirePhase( lit, true );
- if( getCegqiFairMode()==CEGQI_FAIR_DT_HEIGHT_PRED ){
+ if( getCegqiFairMode()==CEGQI_FAIR_DT_HEIGHT_PRED || getCegqiFairMode()==CEGQI_FAIR_DT_SIZE_PRED ){
//implies height bounds on each candidate variable
std::vector< Node > lem_c;
for( unsigned j=0; j<d_candidates.size(); j++ ){
- lem_c.push_back( NodeManager::currentNM()->mkNode( DT_HEIGHT_BOUND, d_candidates[j], c ) );
+ if( getCegqiFairMode()==CEGQI_FAIR_DT_HEIGHT_PRED ){
+ lem_c.push_back( NodeManager::currentNM()->mkNode( DT_HEIGHT_BOUND, d_candidates[j], c ) );
+ }else{
+ //lem_c.push_back( NodeManager::currentNM()->mkNode( DT_SIZE_BOUND, d_candidates[j], c ) );
+ }
}
Node hlem = NodeManager::currentNM()->mkNode( OR, lit.negate(), lem_c.size()==1 ? lem_c[0] : NodeManager::currentNM()->mkNode( AND, lem_c ) );
- Trace("cegqi-lemma") << "Cegqi::Lemma : Fairness expansion (dt-height-pred) : " << hlem << std::endl;
+ Trace("cegqi-lemma") << "Cegqi::Lemma : Fairness expansion (pred) : " << hlem << std::endl;
qe->getOutputChannel().lemma( hlem );
}
return lit;
@@ -257,8 +266,45 @@ void CegInstantiation::check( Theory::Effort e, unsigned quant_e ) {
}
}
+void CegInstantiation::preRegisterQuantifier( Node q ) {
+ if( options::sygusDirectEval() ){
+ if( q.getNumChildren()==3 && q[2].getKind()==INST_PATTERN_LIST && q[2][0].getKind()==INST_PATTERN ){
+ //check whether it is an evaluation axiom
+ Node pat = q[2][0][0];
+ if( pat.getKind()==APPLY_UF ){
+ TypeNode tn = pat[0].getType();
+ if( datatypes::DatatypesRewriter::isTypeDatatype(tn) ){
+ const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
+ if( dt.isSygus() ){
+ //do unfolding if it induces Boolean structure,
+ //do direct evaluation if it does not induce Boolean structure,
+ // the reasoning is unfolding over these terms does not lead to helpful conflict analysis, and introduces many shared terms
+ bool directEval = true;
+ TypeNode ptn = pat.getType();
+ if( ptn.isBoolean() || ptn.isBitVector() ){
+ directEval = false;
+ }else{
+ unsigned cindex = Datatype::indexOf(pat[0].getOperator().toExpr() );
+ Node base = d_quantEngine->getTermDatabaseSygus()->getGenericBase( tn, dt, cindex );
+ Trace("cegqi-debug") << "Generic base term for " << pat[0] << " is " << base << std::endl;
+ if( base.getKind()==ITE ){
+ directEval = false;
+ }
+ }
+ if( directEval ){
+ //take ownership of this quantified formula (will use direct evaluation instead of unfolding instantiation)
+ d_quantEngine->setOwner( q, this );
+ d_eval_axioms[q] = true;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
void CegInstantiation::registerQuantifier( Node q ) {
- if( d_quantEngine->getOwner( q )==this ){
+ if( d_quantEngine->getOwner( q )==this && d_eval_axioms.find( q )==d_eval_axioms.end() ){
if( !d_conj->isAssigned() ){
Trace("cegqi") << "Register conjecture : " << q << std::endl;
d_conj->assign( q );
@@ -278,7 +324,7 @@ void CegInstantiation::registerQuantifier( Node q ) {
if( it!=d_uf_measure.end() ){
mc.push_back( NodeManager::currentNM()->mkNode( APPLY_UF, it->second, d_conj->d_candidates[j] ) );
}
- }else if( d_conj->getCegqiFairMode()==CEGQI_FAIR_DT_HEIGHT_PRED ){
+ }else if( d_conj->getCegqiFairMode()==CEGQI_FAIR_DT_HEIGHT_PRED || d_conj->getCegqiFairMode()==CEGQI_FAIR_DT_SIZE_PRED ){
//measure term is a fresh constant
mc.push_back( NodeManager::currentNM()->mkSkolem( "K", NodeManager::currentNM()->integerType() ) );
}
@@ -291,6 +337,8 @@ void CegInstantiation::registerQuantifier( Node q ) {
}else{
Assert( d_conj->d_quant==q );
}
+ }else{
+ Trace("cegqi-debug") << "Register quantifier : " << q << std::endl;
}
}
@@ -317,7 +365,7 @@ Node CegInstantiation::getNextDecisionRequest() {
Trace("cegqi-debug") << "CEGQI : Decide next on : " << req_dec[i] << "..." << std::endl;
return req_dec[i];
}else{
- Trace("cegqi-debug") << "CEGQI : " << req_dec[i] << " already has value " << value << std::endl;
+ Trace("cegqi-debug2") << "CEGQI : " << req_dec[i] << " already has value " << value << std::endl;
}
}
@@ -350,6 +398,11 @@ void CegInstantiation::checkCegConjecture( CegConjecture * conj ) {
Trace("cegqi-engine-debug") << conj->d_candidates[i] << " ";
}
Trace("cegqi-engine-debug") << std::endl;
+ Trace("cegqi-engine-debug") << " * Candidate ce skolems : ";
+ for( unsigned i=0; i<conj->d_ce_sk.size(); i++ ){
+ Trace("cegqi-engine-debug") << conj->d_ce_sk[i] << " ";
+ }
+ Trace("cegqi-engine-debug") << std::endl;
if( conj->getCegqiFairMode()!=CEGQI_FAIR_NONE ){
Trace("cegqi-engine") << " * Current term size : " << conj->d_curr_lit.get() << std::endl;
}
@@ -374,6 +427,24 @@ void CegInstantiation::checkCegConjecture( CegConjecture * conj ) {
}
std::vector< Node > model_values;
if( getModelValues( conj, conj->d_candidates, model_values ) ){
+ if( options::sygusDirectEval() ){
+ std::vector< Node > eager_eval_lem;
+ for( unsigned j=0; j<conj->d_candidates.size(); j++ ){
+ d_quantEngine->getTermDatabaseSygus()->registerModelValue( conj->d_candidates[j], model_values[j], eager_eval_lem );
+ }
+ if( !eager_eval_lem.empty() ){
+ for( unsigned j=0; j<eager_eval_lem.size(); j++ ){
+ Node lem = eager_eval_lem[j];
+ if( d_quantEngine->getTheoryEngine()->isTheoryEnabled(THEORY_BV) ){
+ //FIXME: hack to incorporate hacks from BV for division by zero
+ lem = bv::TheoryBVRewriter::eliminateBVSDiv( lem );
+ }
+ Trace("cegqi-lemma") << "Cegqi::Lemma : evaluation : " << lem << std::endl;
+ d_quantEngine->addLemma( lem );
+ }
+ return;
+ }
+ }
//check if we must apply fairness lemmas
if( conj->getCegqiFairMode()==CEGQI_FAIR_UF_DT_SIZE ){
std::vector< Node > lems;
@@ -390,6 +461,7 @@ void CegInstantiation::checkCegConjecture( CegConjecture * conj ) {
}
}
//must get a counterexample to the value of the current candidate
+ Assert( conj->d_candidates.size()==model_values.size() );
Node inst = conj->d_base_inst.substitute( conj->d_candidates.begin(), conj->d_candidates.end(), model_values.begin(), model_values.end() );
//check whether we will run CEGIS on inner skolem variables
bool sk_refine = ( !conj->isGround() || conj->d_refine_count==0 );
@@ -422,10 +494,30 @@ void CegInstantiation::checkCegConjecture( CegConjecture * conj ) {
Node lem = NodeManager::currentNM()->mkNode( OR, ic );
lem = Rewriter::rewrite( lem );
d_last_inst_si = false;
+ //eagerly unfold applications of evaluation function
+ if( options::sygusDirectEval() ){
+ Trace("cegqi-eager") << "pre-unfold counterexample : " << lem << std::endl;
+ std::map< Node, Node > visited_n;
+ lem = getEagerUnfold( lem, visited_n );
+ }
+
Trace("cegqi-lemma") << "Cegqi::Lemma : counterexample : " << lem << std::endl;
- d_quantEngine->addLemma( lem );
- ++(d_statistics.d_cegqi_lemmas_ce);
- Trace("cegqi-engine") << " ...find counterexample." << std::endl;
+ if( d_quantEngine->addLemma( lem ) ){
+ ++(d_statistics.d_cegqi_lemmas_ce);
+ Trace("cegqi-engine") << " ...find counterexample." << std::endl;
+ }else{
+ //this may happen if we eagerly unfold, simplify to true
+ if( !options::sygusDirectEval() ){
+ Trace("cegqi-engine") << " ...FAILED to add candidate!" << std::endl;
+ }else{
+ Trace("cegqi-engine-debug") << " ...FAILED to add candidate!" << std::endl;
+ }
+ if( conj->d_refine_count==0 ){
+ //immediately go to refine candidate
+ checkCegConjecture( conj );
+ return;
+ }
+ }
}
}else{
@@ -589,6 +681,74 @@ void CegInstantiation::getMeasureLemmas( Node n, Node v, std::vector< Node >& le
}
}
+Node CegInstantiation::getEagerUnfold( Node n, std::map< Node, Node >& visited ) {
+ std::map< Node, Node >::iterator itv = visited.find( n );
+ if( itv==visited.end() ){
+ Trace("cegqi-eager-debug") << "getEagerUnfold " << n << std::endl;
+ Node ret;
+ if( n.getKind()==APPLY_UF ){
+ TypeNode tn = n[0].getType();
+ Trace("cegqi-eager-debug") << "check " << n[0].getType() << std::endl;
+ if( datatypes::DatatypesRewriter::isTypeDatatype(tn) ){
+ const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
+ if( dt.isSygus() ){
+ Trace("cegqi-eager") << "Unfold eager : " << n << std::endl;
+ Node bTerm = d_quantEngine->getTermDatabaseSygus()->sygusToBuiltin( n[0], tn );
+ Trace("cegqi-eager") << "Built-in term : " << bTerm << std::endl;
+ std::vector< Node > vars;
+ std::vector< Node > subs;
+ Node var_list = Node::fromExpr( dt.getSygusVarList() );
+ Assert( var_list.getNumChildren()+1==n.getNumChildren() );
+ for( unsigned j=0; j<var_list.getNumChildren(); j++ ){
+ vars.push_back( var_list[j] );
+ }
+ for( unsigned j=1; j<n.getNumChildren(); j++ ){
+ Node nc = getEagerUnfold( n[j], visited );
+ if( var_list[j-1].getType().isBoolean() ){
+ //TODO: remove this case when boolean term conversion is eliminated
+ Node c = NodeManager::currentNM()->mkConst(BitVector(1u, 1u));
+ subs.push_back( nc.eqNode( c ) );
+ }else{
+ subs.push_back( nc );
+ }
+ Assert( subs[j-1].getType()==var_list[j-1].getType() );
+ }
+ Assert( vars.size()==subs.size() );
+ bTerm = bTerm.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
+ Trace("cegqi-eager") << "Built-in term after subs : " << bTerm << std::endl;
+ Trace("cegqi-eager-debug") << "Types : " << bTerm.getType() << " " << n.getType() << std::endl;
+ Assert( n.getType()==bTerm.getType() );
+ ret = bTerm;
+ }
+ }
+ }
+ if( ret.isNull() ){
+ if( n.getKind()!=FORALL ){
+ bool childChanged = false;
+ std::vector< Node > children;
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ Node nc = getEagerUnfold( n[i], visited );
+ childChanged = childChanged || n[i]!=nc;
+ children.push_back( nc );
+ }
+ if( childChanged ){
+ if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){
+ children.insert( children.begin(), n.getOperator() );
+ }
+ ret = NodeManager::currentNM()->mkNode( n.getKind(), children );
+ }
+ }
+ if( ret.isNull() ){
+ ret = n;
+ }
+ }
+ visited[n] = ret;
+ return ret;
+ }else{
+ return itv->second;
+ }
+}
+
void CegInstantiation::printSynthSolution( std::ostream& out ) {
if( d_conj->isAssigned() ){
Trace("cegqi-debug") << "Printing synth solution..." << std::endl;
diff --git a/src/theory/quantifiers/ce_guided_instantiation.h b/src/theory/quantifiers/ce_guided_instantiation.h
index 57dc31850..c8b41c035 100644..100755
--- a/src/theory/quantifiers/ce_guided_instantiation.h
+++ b/src/theory/quantifiers/ce_guided_instantiation.h
@@ -126,6 +126,8 @@ private:
CegConjecture * d_conj;
/** last instantiation by single invocation module? */
bool d_last_inst_si;
+ /** evaluation axioms */
+ std::map< Node, bool > d_eval_axioms;
private: //for enforcing fairness
/** measure functions */
std::map< TypeNode, Node > d_uf_measure;
@@ -139,6 +141,8 @@ private: //for enforcing fairness
std::map< Node, std::map< int, Node > > d_size_term_lemma;
/** get measure lemmas */
void getMeasureLemmas( Node n, Node v, std::vector< Node >& lems );
+ /** get eager unfolding */
+ Node getEagerUnfold( Node n, std::map< Node, Node >& visited );
private:
/** check conjecture */
void checkCegConjecture( CegConjecture * conj );
@@ -156,6 +160,7 @@ public:
/* Call during quantifier engine's check */
void check( Theory::Effort e, unsigned quant_e );
/* Called for new quantifiers */
+ void preRegisterQuantifier( Node q );
void registerQuantifier( Node q );
void assertNode( Node n );
Node getNextDecisionRequest();
diff --git a/src/theory/quantifiers/ce_guided_single_inv.cpp b/src/theory/quantifiers/ce_guided_single_inv.cpp
index 33856d226..3177739ac 100644..100755
--- a/src/theory/quantifiers/ce_guided_single_inv.cpp
+++ b/src/theory/quantifiers/ce_guided_single_inv.cpp
@@ -111,6 +111,7 @@ void CegConjectureSingleInv::getInitialSingleInvLemma( std::vector< Node >& lems
void CegConjectureSingleInv::initialize( Node q ) {
Assert( d_quant.isNull() );
+ Assert( options::cegqiSingleInvMode()!=CEGQI_SI_MODE_NONE );
//initialize data
d_quant = q;
//process
@@ -121,6 +122,7 @@ void CegConjectureSingleInv::initialize( Node q ) {
std::map< Node, std::map< Node, std::vector< Node > > > prog_invoke;
std::vector< Node > progs;
std::map< Node, std::map< Node, bool > > contains;
+ bool is_syntax_restricted = false;
for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
progs.push_back( q[0][i] );
//check whether all types have ITE
@@ -131,161 +133,173 @@ void CegConjectureSingleInv::initialize( Node q ) {
d_has_ites = false;
}
}
+ Assert( datatypes::DatatypesRewriter::isTypeDatatype(tn) );
+ const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
+ Assert( dt.isSygus() );
+ if( !dt.getSygusAllowAll() ){
+ is_syntax_restricted = true;
+ }
}
- Node qq = q[1];
- if( q[1].getKind()==NOT && q[1][0].getKind()==FORALL ){
- qq = q[1][0][1];
- }else{
- qq = TermDb::simpleNegate( qq );
- }
- //remove the deep embedding
- std::map< Node, Node > visited;
- std::vector< TypeNode > types;
- std::vector< Node > order_vars;
- std::map< Node, Node > single_inv_app_map;
- int type_valid = 0;
- qq = removeDeepEmbedding( qq, progs, types, type_valid, visited );
- Trace("cegqi-si-debug") << "- Remove deep embedding, got : " << qq << ", type valid = " << type_valid << std::endl;
+ //abort if not aggressive
bool singleInvocation = true;
- if( type_valid==0 ){
- //process the single invocation-ness of the property
- d_sip->init( types, qq );
- Trace("cegqi-si") << "- Partitioned to single invocation parts : " << std::endl;
- d_sip->debugPrint( "cegqi-si" );
- //map from program to bound variables
- for( unsigned j=0; j<progs.size(); j++ ){
- Node prog = progs[j];
- std::map< Node, Node >::iterator it_nsi = d_nsi_op_map.find( prog );
- if( it_nsi!=d_nsi_op_map.end() ){
- Node op = it_nsi->second;
- std::map< Node, Node >::iterator it_fov = d_sip->d_func_fo_var.find( op );
- if( it_fov!=d_sip->d_func_fo_var.end() ){
- Node pv = it_fov->second;
- Assert( d_sip->d_func_inv.find( op )!=d_sip->d_func_inv.end() );
- Node inv = d_sip->d_func_inv[op];
- single_inv_app_map[prog] = inv;
- Trace("cegqi-si") << " " << pv << ", " << inv << " is associated with program " << prog << std::endl;
- d_prog_to_sol_index[prog] = order_vars.size();
- order_vars.push_back( pv );
+ if( options::cegqiSingleInvMode()==CEGQI_SI_MODE_USE && is_syntax_restricted ){
+ singleInvocation = false;
+ Trace("cegqi-si") << "...grammar is restricted, do not use single invocation techniques." << std::endl;
+ }else{
+ Node qq = q[1];
+ if( q[1].getKind()==NOT && q[1][0].getKind()==FORALL ){
+ qq = q[1][0][1];
+ }else{
+ qq = TermDb::simpleNegate( qq );
+ }
+ //remove the deep embedding
+ std::map< Node, Node > visited;
+ std::vector< TypeNode > types;
+ std::vector< Node > order_vars;
+ std::map< Node, Node > single_inv_app_map;
+ int type_valid = 0;
+ qq = removeDeepEmbedding( qq, progs, types, type_valid, visited );
+ Trace("cegqi-si-debug") << "- Remove deep embedding, got : " << qq << ", type valid = " << type_valid << std::endl;
+ if( type_valid==0 ){
+ //process the single invocation-ness of the property
+ d_sip->init( types, qq );
+ Trace("cegqi-si") << "- Partitioned to single invocation parts : " << std::endl;
+ d_sip->debugPrint( "cegqi-si" );
+ //map from program to bound variables
+ for( unsigned j=0; j<progs.size(); j++ ){
+ Node prog = progs[j];
+ std::map< Node, Node >::iterator it_nsi = d_nsi_op_map.find( prog );
+ if( it_nsi!=d_nsi_op_map.end() ){
+ Node op = it_nsi->second;
+ std::map< Node, Node >::iterator it_fov = d_sip->d_func_fo_var.find( op );
+ if( it_fov!=d_sip->d_func_fo_var.end() ){
+ Node pv = it_fov->second;
+ Assert( d_sip->d_func_inv.find( op )!=d_sip->d_func_inv.end() );
+ Node inv = d_sip->d_func_inv[op];
+ single_inv_app_map[prog] = inv;
+ Trace("cegqi-si") << " " << pv << ", " << inv << " is associated with program " << prog << std::endl;
+ d_prog_to_sol_index[prog] = order_vars.size();
+ order_vars.push_back( pv );
+ }
+ }else{
+ //does not mention the function
}
- }else{
- //does not mention the function
}
- }
- //reorder the variables
- Assert( d_sip->d_func_vars.size()==order_vars.size() );
- d_sip->d_func_vars.clear();
- d_sip->d_func_vars.insert( d_sip->d_func_vars.begin(), order_vars.begin(), order_vars.end() );
+ //reorder the variables
+ Assert( d_sip->d_func_vars.size()==order_vars.size() );
+ d_sip->d_func_vars.clear();
+ d_sip->d_func_vars.insert( d_sip->d_func_vars.begin(), order_vars.begin(), order_vars.end() );
- //check if it is single invocation
- if( !d_sip->d_conjuncts[1].empty() ){
- singleInvocation = false;
- if( options::cegqiSingleInvPartial() ){
- //this enables partially single invocation techniques
- d_nsingle_inv = d_sip->getNonSingleInvocation();
- d_nsingle_inv = TermDb::simpleNegate( d_nsingle_inv );
- d_full_inv = d_sip->getFullSpecification();
- d_full_inv = TermDb::simpleNegate( d_full_inv );
- singleInvocation = true;
- }else if( options::sygusInvTemplMode() != SYGUS_INV_TEMPL_MODE_NONE ){
- //if we are doing invariant templates, then construct the template
- std::map< Node, bool > has_inv;
- std::map< Node, std::vector< Node > > inv_pre_post[2];
- for( unsigned i=0; i<d_sip->d_conjuncts[2].size(); i++ ){
- std::vector< Node > disjuncts;
- Node func;
- int pol = -1;
- Trace("cegqi-inv") << "INV process " << d_sip->d_conjuncts[2][i] << std::endl;
- d_sip->extractInvariant( d_sip->d_conjuncts[2][i], func, pol, disjuncts );
- if( pol>=0 ){
- Assert( d_nsi_op_map_to_prog.find( func )!=d_nsi_op_map_to_prog.end() );
- Node prog = d_nsi_op_map_to_prog[func];
- Trace("cegqi-inv") << "..." << ( pol==0 ? "pre" : "post" ) << "-condition for " << prog << "." << std::endl;
- Node c = disjuncts.empty() ? d_qe->getTermDatabase()->d_false : ( disjuncts.size()==1 ? disjuncts[0] : NodeManager::currentNM()->mkNode( OR, disjuncts ) );
- c = pol==0 ? TermDb::simpleNegate( c ) : c;
- Trace("cegqi-inv-debug") << "...extracted : " << c << std::endl;
- inv_pre_post[pol][prog].push_back( c );
- has_inv[prog] = true;
- }else{
- Trace("cegqi-inv") << "...no status." << std::endl;
+ //check if it is single invocation
+ if( !d_sip->d_conjuncts[1].empty() ){
+ singleInvocation = false;
+ if( options::cegqiSingleInvPartial() ){
+ //this enables partially single invocation techniques
+ d_nsingle_inv = d_sip->getNonSingleInvocation();
+ d_nsingle_inv = TermDb::simpleNegate( d_nsingle_inv );
+ d_full_inv = d_sip->getFullSpecification();
+ d_full_inv = TermDb::simpleNegate( d_full_inv );
+ singleInvocation = true;
+ }else if( options::sygusInvTemplMode() != SYGUS_INV_TEMPL_MODE_NONE ){
+ //if we are doing invariant templates, then construct the template
+ std::map< Node, bool > has_inv;
+ std::map< Node, std::vector< Node > > inv_pre_post[2];
+ for( unsigned i=0; i<d_sip->d_conjuncts[2].size(); i++ ){
+ std::vector< Node > disjuncts;
+ Node func;
+ int pol = -1;
+ Trace("cegqi-inv") << "INV process " << d_sip->d_conjuncts[2][i] << std::endl;
+ d_sip->extractInvariant( d_sip->d_conjuncts[2][i], func, pol, disjuncts );
+ if( pol>=0 ){
+ Assert( d_nsi_op_map_to_prog.find( func )!=d_nsi_op_map_to_prog.end() );
+ Node prog = d_nsi_op_map_to_prog[func];
+ Trace("cegqi-inv") << "..." << ( pol==0 ? "pre" : "post" ) << "-condition for " << prog << "." << std::endl;
+ Node c = disjuncts.empty() ? d_qe->getTermDatabase()->d_false : ( disjuncts.size()==1 ? disjuncts[0] : NodeManager::currentNM()->mkNode( OR, disjuncts ) );
+ c = pol==0 ? TermDb::simpleNegate( c ) : c;
+ Trace("cegqi-inv-debug") << "...extracted : " << c << std::endl;
+ inv_pre_post[pol][prog].push_back( c );
+ has_inv[prog] = true;
+ }else{
+ Trace("cegqi-inv") << "...no status." << std::endl;
+ }
}
- }
- Trace("cegqi-inv") << "Constructing invariant templates..." << std::endl;
- //now, contruct the template for the invariant(s)
- std::map< Node, Node > prog_templ;
- for( std::map< Node, bool >::iterator iti = has_inv.begin(); iti != has_inv.end(); ++iti ){
- Node prog = iti->first;
- Trace("cegqi-inv") << "...for " << prog << "..." << std::endl;
- Trace("cegqi-inv") << " args : ";
+ Trace("cegqi-inv") << "Constructing invariant templates..." << std::endl;
+ //now, contruct the template for the invariant(s)
+ std::map< Node, Node > prog_templ;
+ for( std::map< Node, bool >::iterator iti = has_inv.begin(); iti != has_inv.end(); ++iti ){
+ Node prog = iti->first;
+ Trace("cegqi-inv") << "...for " << prog << "..." << std::endl;
+ Trace("cegqi-inv") << " args : ";
+ for( unsigned j=0; j<d_sip->d_si_vars.size(); j++ ){
+ std::stringstream ss;
+ ss << "i_" << j;
+ Node v = NodeManager::currentNM()->mkBoundVar( ss.str(), d_sip->d_si_vars[j].getType() );
+ d_prog_templ_vars[prog].push_back( v );
+ Trace("cegqi-inv") << v << " ";
+ }
+ Trace("cegqi-inv") << std::endl;
+ Node pre = inv_pre_post[0][prog].empty() ? NodeManager::currentNM()->mkConst( false ) :
+ ( inv_pre_post[0][prog].size()==1 ? inv_pre_post[0][prog][0] : NodeManager::currentNM()->mkNode( OR, inv_pre_post[0][prog] ) );
+ d_trans_pre[prog] = pre.substitute( d_sip->d_si_vars.begin(), d_sip->d_si_vars.end(), d_prog_templ_vars[prog].begin(), d_prog_templ_vars[prog].end() );
+ Node post = inv_pre_post[1][prog].empty() ? NodeManager::currentNM()->mkConst( true ) :
+ ( inv_pre_post[1][prog].size()==1 ? inv_pre_post[1][prog][0] : NodeManager::currentNM()->mkNode( AND, inv_pre_post[1][prog] ) );
+ d_trans_post[prog] = post.substitute( d_sip->d_si_vars.begin(), d_sip->d_si_vars.end(), d_prog_templ_vars[prog].begin(), d_prog_templ_vars[prog].end() );
+ Trace("cegqi-inv") << " precondition : " << d_trans_pre[prog] << std::endl;
+ Trace("cegqi-inv") << " postcondition : " << d_trans_post[prog] << std::endl;
+ Node invariant = single_inv_app_map[prog];
+ invariant = invariant.substitute( d_sip->d_si_vars.begin(), d_sip->d_si_vars.end(), d_prog_templ_vars[prog].begin(), d_prog_templ_vars[prog].end() );
+ Trace("cegqi-inv") << " invariant : " << invariant << std::endl;
+ //construct template
+ Node templ;
+ if( options::sygusInvTemplMode() == SYGUS_INV_TEMPL_MODE_PRE ){
+ //templ = NodeManager::currentNM()->mkNode( AND, NodeManager::currentNM()->mkNode( OR, d_trans_pre[prog], invariant ), d_trans_post[prog] );
+ templ = NodeManager::currentNM()->mkNode( OR, d_trans_pre[prog], invariant );
+ }else{
+ Assert( options::sygusInvTemplMode() == SYGUS_INV_TEMPL_MODE_POST );
+ //templ = NodeManager::currentNM()->mkNode( OR, d_trans_pre[prog], NodeManager::currentNM()->mkNode( AND, d_trans_post[prog], invariant ) );
+ templ = NodeManager::currentNM()->mkNode( AND, d_trans_post[prog], invariant );
+ }
+ visited.clear();
+ templ = addDeepEmbedding( templ, visited );
+ Trace("cegqi-inv") << " template : " << templ << std::endl;
+ prog_templ[prog] = templ;
+ }
+ Node bd = d_sip->d_conjuncts[2].size()==1 ? d_sip->d_conjuncts[2][0] : NodeManager::currentNM()->mkNode( AND, d_sip->d_conjuncts[2] );
+ visited.clear();
+ bd = addDeepEmbedding( bd, visited );
+ Trace("cegqi-inv") << " body : " << bd << std::endl;
+ bd = substituteInvariantTemplates( bd, prog_templ, d_prog_templ_vars );
+ Trace("cegqi-inv-debug") << " templ-subs body : " << bd << std::endl;
+ //make inner existential
+ std::vector< Node > new_var_bv;
for( unsigned j=0; j<d_sip->d_si_vars.size(); j++ ){
std::stringstream ss;
- ss << "i_" << j;
- Node v = NodeManager::currentNM()->mkBoundVar( ss.str(), d_sip->d_si_vars[j].getType() );
- d_prog_templ_vars[prog].push_back( v );
- Trace("cegqi-inv") << v << " ";
+ ss << "ss_" << j;
+ new_var_bv.push_back( NodeManager::currentNM()->mkBoundVar( ss.str(), d_sip->d_si_vars[j].getType() ) );
}
- Trace("cegqi-inv") << std::endl;
- Node pre = inv_pre_post[0][prog].empty() ? NodeManager::currentNM()->mkConst( false ) :
- ( inv_pre_post[0][prog].size()==1 ? inv_pre_post[0][prog][0] : NodeManager::currentNM()->mkNode( OR, inv_pre_post[0][prog] ) );
- d_trans_pre[prog] = pre.substitute( d_sip->d_si_vars.begin(), d_sip->d_si_vars.end(), d_prog_templ_vars[prog].begin(), d_prog_templ_vars[prog].end() );
- Node post = inv_pre_post[1][prog].empty() ? NodeManager::currentNM()->mkConst( true ) :
- ( inv_pre_post[1][prog].size()==1 ? inv_pre_post[1][prog][0] : NodeManager::currentNM()->mkNode( AND, inv_pre_post[1][prog] ) );
- d_trans_post[prog] = post.substitute( d_sip->d_si_vars.begin(), d_sip->d_si_vars.end(), d_prog_templ_vars[prog].begin(), d_prog_templ_vars[prog].end() );
- Trace("cegqi-inv") << " precondition : " << d_trans_pre[prog] << std::endl;
- Trace("cegqi-inv") << " postcondition : " << d_trans_post[prog] << std::endl;
- Node invariant = single_inv_app_map[prog];
- invariant = invariant.substitute( d_sip->d_si_vars.begin(), d_sip->d_si_vars.end(), d_prog_templ_vars[prog].begin(), d_prog_templ_vars[prog].end() );
- Trace("cegqi-inv") << " invariant : " << invariant << std::endl;
- //construct template
- Node templ;
- if( options::sygusInvTemplMode() == SYGUS_INV_TEMPL_MODE_PRE ){
- //templ = NodeManager::currentNM()->mkNode( AND, NodeManager::currentNM()->mkNode( OR, d_trans_pre[prog], invariant ), d_trans_post[prog] );
- templ = NodeManager::currentNM()->mkNode( OR, d_trans_pre[prog], invariant );
- }else{
- Assert( options::sygusInvTemplMode() == SYGUS_INV_TEMPL_MODE_POST );
- //templ = NodeManager::currentNM()->mkNode( OR, d_trans_pre[prog], NodeManager::currentNM()->mkNode( AND, d_trans_post[prog], invariant ) );
- templ = NodeManager::currentNM()->mkNode( AND, d_trans_post[prog], invariant );
+ bd = bd.substitute( d_sip->d_si_vars.begin(), d_sip->d_si_vars.end(), new_var_bv.begin(), new_var_bv.end() );
+ Assert( q[1].getKind()==NOT && q[1][0].getKind()==FORALL );
+ for( unsigned j=0; j<q[1][0][0].getNumChildren(); j++ ){
+ new_var_bv.push_back( q[1][0][0][j] );
}
- visited.clear();
- templ = addDeepEmbedding( templ, visited );
- Trace("cegqi-inv") << " template : " << templ << std::endl;
- prog_templ[prog] = templ;
- }
- Node bd = d_sip->d_conjuncts[2].size()==1 ? d_sip->d_conjuncts[2][0] : NodeManager::currentNM()->mkNode( AND, d_sip->d_conjuncts[2] );
- visited.clear();
- bd = addDeepEmbedding( bd, visited );
- Trace("cegqi-inv") << " body : " << bd << std::endl;
- bd = substituteInvariantTemplates( bd, prog_templ, d_prog_templ_vars );
- Trace("cegqi-inv-debug") << " templ-subs body : " << bd << std::endl;
- //make inner existential
- std::vector< Node > new_var_bv;
- for( unsigned j=0; j<d_sip->d_si_vars.size(); j++ ){
- std::stringstream ss;
- ss << "ss_" << j;
- new_var_bv.push_back( NodeManager::currentNM()->mkBoundVar( ss.str(), d_sip->d_si_vars[j].getType() ) );
- }
- bd = bd.substitute( d_sip->d_si_vars.begin(), d_sip->d_si_vars.end(), new_var_bv.begin(), new_var_bv.end() );
- Assert( q[1].getKind()==NOT && q[1][0].getKind()==FORALL );
- for( unsigned j=0; j<q[1][0][0].getNumChildren(); j++ ){
- new_var_bv.push_back( q[1][0][0][j] );
- }
- if( !new_var_bv.empty() ){
- Node bvl = NodeManager::currentNM()->mkNode( BOUND_VAR_LIST, new_var_bv );
- bd = NodeManager::currentNM()->mkNode( FORALL, bvl, bd ).negate();
+ if( !new_var_bv.empty() ){
+ Node bvl = NodeManager::currentNM()->mkNode( BOUND_VAR_LIST, new_var_bv );
+ bd = NodeManager::currentNM()->mkNode( FORALL, bvl, bd ).negate();
+ }
+ //make outer universal
+ bd = NodeManager::currentNM()->mkNode( FORALL, q[0], bd );
+ bd = Rewriter::rewrite( bd );
+ Trace("cegqi-inv") << " rtempl-subs body : " << bd << std::endl;
+ d_quant = bd;
}
- //make outer universal
- bd = NodeManager::currentNM()->mkNode( FORALL, q[0], bd );
- bd = Rewriter::rewrite( bd );
- Trace("cegqi-inv") << " rtempl-subs body : " << bd << std::endl;
- d_quant = bd;
+ }else{
+ //we are fully single invocation
}
}else{
- //we are fully single invocation
+ Trace("cegqi-si") << "...property is not single invocation, involves functions with different argument sorts." << std::endl;
+ singleInvocation = false;
}
- }else{
- Trace("cegqi-si") << "...property is not single invocation, involves functions with different argument sorts." << std::endl;
- singleInvocation = false;
}
if( singleInvocation ){
d_single_inv = d_sip->getSingleInvocation();
@@ -534,6 +548,7 @@ bool CegConjectureSingleInv::doAddInstantiation( std::vector< Node >& subs ){
return false;
}else{
Trace("cegqi-engine") << siss.str() << std::endl;
+ Assert( d_single_inv_var.size()==subs.size() );
Node lem = d_single_inv[1].substitute( d_single_inv_var.begin(), d_single_inv_var.end(), subs.begin(), subs.end() );
if( d_qe->getTermDatabase()->containsVtsTerm( lem ) ){
Trace("cegqi-engine-debug") << "Rewrite based on vts symbols..." << std::endl;
@@ -595,6 +610,7 @@ bool CegConjectureSingleInv::check( std::vector< Node >& lems ) {
for( unsigned i=0; i<d_sip->d_all_vars.size(); i++ ){
subs.push_back( NodeManager::currentNM()->mkSkolem( "kv", d_sip->d_all_vars[i].getType(), "created for verifying nsi" ) );
}
+ Assert( d_sip->d_all_vars.size()==subs.size() );
inst = inst.substitute( d_sip->d_all_vars.begin(), d_sip->d_all_vars.end(), subs.begin(), subs.end() );
Trace("cegqi-nsi") << "NSI : verification : " << inst << std::endl;
Trace("cegqi-lemma") << "Cegqi::Lemma : verification lemma : " << inst << std::endl;
@@ -751,6 +767,7 @@ Node CegConjectureSingleInv::getSolution( unsigned sol_index, TypeNode stn, int&
std::sort( indices.begin(), indices.end(), ssii );
Trace("csi-sol") << "Construct solution" << std::endl;
s = constructSolution( indices, sol_index, 0 );
+ Assert( vars.size()==d_sol->d_varList.size() );
s = s.substitute( vars.begin(), vars.end(), d_sol->d_varList.begin(), d_sol->d_varList.end() );
}
d_orig_solution = s;
@@ -826,8 +843,8 @@ Node CegConjectureSingleInv::reconstructToSyntax( Node s, TypeNode stn, int& rec
}
bool CegConjectureSingleInv::needsCheck() {
- if( options::cegqiSingleInvMultiInstAbort() ){
- if( !hasITEs() ){
+ if( options::cegqiSingleInvMode()==CEGQI_SI_MODE_ALL_ABORT ){
+ if( !d_has_ites ){
return d_inst.empty();
}
}
@@ -922,6 +939,7 @@ void SingleInvocationPartition::process( Node n ) {
std::vector< Node > funcs;
//normalize the invocations
if( !terms.empty() ){
+ Assert( terms.size()==subs.size() );
cr = cr.substitute( terms.begin(), terms.end(), subs.begin(), subs.end() );
}
std::vector< Node > children;
@@ -940,6 +958,7 @@ void SingleInvocationPartition::process( Node n ) {
}
Trace("si-prt") << std::endl;
cr = children.size()==1 ? children[0] : NodeManager::currentNM()->mkNode( OR, children );
+ Assert( terms.size()==subs.size() );
cr = cr.substitute( terms.begin(), terms.end(), subs.begin(), subs.end() );
Trace("si-prt-debug") << "...normalized invocations to " << cr << std::endl;
//now must check if it has other bound variables
@@ -974,6 +993,7 @@ void SingleInvocationPartition::process( Node n ) {
}
}
}
+ Assert( terms.size()==subs.size() );
cr = cr.substitute( terms.begin(), terms.end(), subs.begin(), subs.end() );
}
cr = Rewriter::rewrite( cr );
@@ -982,6 +1002,7 @@ void SingleInvocationPartition::process( Node n ) {
TermDb::getBoundVars( cr, d_all_vars );
if( singleInvocation ){
//replace with single invocation formulation
+ Assert( si_terms.size()==si_subs.size() );
cr = cr.substitute( si_terms.begin(), si_terms.end(), si_subs.begin(), si_subs.end() );
cr = Rewriter::rewrite( cr );
Trace("si-prt") << ".....si version=" << cr << std::endl;
diff --git a/src/theory/quantifiers/ce_guided_single_inv.h b/src/theory/quantifiers/ce_guided_single_inv.h
index 4d2f9a0e5..4d2f9a0e5 100644..100755
--- a/src/theory/quantifiers/ce_guided_single_inv.h
+++ b/src/theory/quantifiers/ce_guided_single_inv.h
diff --git a/src/theory/quantifiers/ce_guided_single_inv_ei.cpp b/src/theory/quantifiers/ce_guided_single_inv_ei.cpp
index 6394fca3d..6394fca3d 100644..100755
--- a/src/theory/quantifiers/ce_guided_single_inv_ei.cpp
+++ b/src/theory/quantifiers/ce_guided_single_inv_ei.cpp
diff --git a/src/theory/quantifiers/ce_guided_single_inv_ei.h b/src/theory/quantifiers/ce_guided_single_inv_ei.h
index 42e0b0820..42e0b0820 100644..100755
--- a/src/theory/quantifiers/ce_guided_single_inv_ei.h
+++ b/src/theory/quantifiers/ce_guided_single_inv_ei.h
diff --git a/src/theory/quantifiers/ce_guided_single_inv_sol.cpp b/src/theory/quantifiers/ce_guided_single_inv_sol.cpp
index 240c2ed12..240c2ed12 100644..100755
--- a/src/theory/quantifiers/ce_guided_single_inv_sol.cpp
+++ b/src/theory/quantifiers/ce_guided_single_inv_sol.cpp
diff --git a/src/theory/quantifiers/ce_guided_single_inv_sol.h b/src/theory/quantifiers/ce_guided_single_inv_sol.h
index cb6f6bc41..cb6f6bc41 100644..100755
--- a/src/theory/quantifiers/ce_guided_single_inv_sol.h
+++ b/src/theory/quantifiers/ce_guided_single_inv_sol.h
diff --git a/src/theory/quantifiers/ceg_instantiator.cpp b/src/theory/quantifiers/ceg_instantiator.cpp
index da488ea98..cd263e90c 100644..100755
--- a/src/theory/quantifiers/ceg_instantiator.cpp
+++ b/src/theory/quantifiers/ceg_instantiator.cpp
@@ -22,6 +22,9 @@
#include "theory/quantifiers/term_database.h"
#include "theory/theory_engine.h"
+#include "theory/bv/theory_bv_utils.h"
+#include "util/bitvector.h"
+
//#define MBP_STRICT_ASSERTIONS
using namespace std;
@@ -466,6 +469,36 @@ bool CegInstantiator::doAddInstantiation( SolvedForm& sf, SolvedForm& ssf, std::
}
}
}
+ /* TODO: algebraic reasoning for bitvector instantiation
+ else if( pvtn.isBitVector() ){
+ if( atom.getKind()==BITVECTOR_ULT || atom.getKind()==BITVECTOR_ULE ){
+ for( unsigned t=0; t<2; t++ ){
+ if( atom[t]==pv ){
+ computeProgVars( atom[1-t] );
+ if( d_inelig.find( atom[1-t] )==d_inelig.end() ){
+ //only ground terms TODO: more
+ if( d_prog_var[atom[1-t]].empty() ){
+ Node veq_c;
+ Node uval;
+ if( ( !pol && atom.getKind()==BITVECTOR_ULT ) || ( pol && atom.getKind()==BITVECTOR_ULE ) ){
+ uval = atom[1-t];
+ }else{
+ uval = NodeManager::currentNM()->mkNode( (atom.getKind()==BITVECTOR_ULT)==(t==1) ? BITVECTOR_PLUS : BITVECTOR_SUB, atom[1-t],
+ bv::utils::mkConst(pvtn.getConst<BitVectorSize>(), 1) );
+ }
+ if( subs_proc[uval].find( veq_c )==subs_proc[uval].end() ){
+ subs_proc[uval][veq_c] = true;
+ if( doAddInstantiationInc( uval, pv, veq_c, 0, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ */
}
}
}
@@ -685,7 +718,7 @@ bool CegInstantiator::doAddInstantiation( SolvedForm& sf, SolvedForm& ssf, std::
//[5] resort to using value in model
// do so if we are in effort=1, or if the variable is boolean, or if we are solving for a subfield of a datatype
- if( ( effort>0 || pvtn.isBoolean() || !curr_var.empty() ) && d_qe->getTermDatabase()->isClosedEnumerableType( pvtn ) ){
+ if( ( effort>0 || pvtn.isBoolean() || pvtn.isBitVector() || !curr_var.empty() ) && d_qe->getTermDatabase()->isClosedEnumerableType( pvtn ) ){
Node mv = getModelValue( pv );
Node pv_coeff_m;
Trace("cbqi-inst-debug") << "[5] " << i << "...try model value " << mv << std::endl;
@@ -781,6 +814,7 @@ bool CegInstantiator::doAddInstantiationInc( Node n, Node pv, Node pv_coeff, int
}
}
if( success ){
+ Trace("cbqi-inst-debug2") << "Adding to vectors..." << std::endl;
vars.push_back( pv );
btyp.push_back( bt );
sf.push_back( pv, n, pv_coeff );
@@ -800,8 +834,10 @@ bool CegInstantiator::doAddInstantiationInc( Node n, Node pv, Node pv_coeff, int
curr_var.pop_back();
is_cv = true;
}
+ Trace("cbqi-inst-debug2") << "Recurse..." << std::endl;
success = doAddInstantiation( sf, ssf, vars, btyp, new_theta, curr_var.empty() ? i+1 : i, effort, cons, curr_var );
if( !success ){
+ Trace("cbqi-inst-debug2") << "Removing from vectors..." << std::endl;
if( is_cv ){
curr_var.push_back( pv );
}
@@ -814,6 +850,7 @@ bool CegInstantiator::doAddInstantiationInc( Node n, Node pv, Node pv_coeff, int
if( success ){
return true;
}else{
+ Trace("cbqi-inst-debug2") << "Revert substitutions..." << std::endl;
//revert substitution information
for( std::map< int, Node >::iterator it = prev_subs.begin(); it != prev_subs.end(); it++ ){
sf.d_subs[it->first] = it->second;
@@ -1035,7 +1072,13 @@ Node CegInstantiator::applySubstitution( TypeNode tn, Node n, std::vector< Node
if( !it->second.isNull() ){
c_coeff = NodeManager::currentNM()->mkNode( MULT, c_coeff, it->second );
}
- Node c = NodeManager::currentNM()->mkNode( MULT, c_coeff, msum_term[it->first] );
+ Assert( !c_coeff.isNull() );
+ Node c;
+ if( msum_term[it->first].isNull() ){
+ c = c_coeff;
+ }else{
+ c = NodeManager::currentNM()->mkNode( MULT, c_coeff, msum_term[it->first] );
+ }
children.push_back( c );
Trace("cegqi-si-apply-subs-debug") << "Add child : " << c << std::endl;
}
@@ -1594,6 +1637,7 @@ int CegInstantiator::solve_arith( Node pv, Node atom, Node& veq_c, Node& val, No
realPart = real_part.empty() ? d_zero : ( real_part.size()==1 ? real_part[0] : NodeManager::currentNM()->mkNode( PLUS, real_part ) );
Assert( d_out->isEligibleForInstantiation( realPart ) );
//re-isolate
+ Trace("cbqi-inst-debug") << "Re-isolate..." << std::endl;
ires = QuantArith::isolate( pv, msum, veq_c, val, atom.getKind() );
Trace("cbqi-inst-debug") << "Isolate for mixed Int/Real : " << veq_c << " * " << pv << " " << atom.getKind() << " " << val << std::endl;
Trace("cbqi-inst-debug") << " real part : " << realPart << std::endl;
diff --git a/src/theory/quantifiers/ceg_instantiator.h b/src/theory/quantifiers/ceg_instantiator.h
index 3d7bbcb55..3d7bbcb55 100644..100755
--- a/src/theory/quantifiers/ceg_instantiator.h
+++ b/src/theory/quantifiers/ceg_instantiator.h
diff --git a/src/theory/quantifiers/conjecture_generator.cpp b/src/theory/quantifiers/conjecture_generator.cpp
index 2cc49ef5a..f4eb67d74 100644..100755
--- a/src/theory/quantifiers/conjecture_generator.cpp
+++ b/src/theory/quantifiers/conjecture_generator.cpp
@@ -285,7 +285,7 @@ Node ConjectureGenerator::getFreeVar( TypeNode tn, unsigned i ) {
}
bool ConjectureGenerator::isHandledTerm( TNode n ){
- return !n.getAttribute(NoMatchAttribute()) && inst::Trigger::isAtomicTrigger( n ) && ( n.getKind()!=APPLY_UF || n.getOperator().getKind()!=SKOLEM );
+ return d_quantEngine->getTermDatabase()->isTermActive( n ) && inst::Trigger::isAtomicTrigger( n ) && ( n.getKind()!=APPLY_UF || n.getOperator().getKind()!=SKOLEM );
}
Node ConjectureGenerator::getGroundEqc( TNode r ) {
@@ -425,7 +425,7 @@ void ConjectureGenerator::check( Theory::Effort e, unsigned quant_e ) {
eq::EqClassIterator eqc_i = eq::EqClassIterator( r, ee );
while( !eqc_i.isFinished() ){
TNode n = (*eqc_i);
- if( getTermDatabase()->hasTermCurrent( n ) && !n.getAttribute(NoMatchAttribute()) && ( n.getKind()!=EQUAL || isFalse ) ){
+ if( getTermDatabase()->hasTermCurrent( n ) && getTermDatabase()->isTermActive( n ) && ( n.getKind()!=EQUAL || isFalse ) ){
if( firstTime ){
Trace("sg-gen-eqc") << "e" << d_em[r] << " : { " << std::endl;
firstTime = false;
@@ -1572,7 +1572,6 @@ bool TermGenerator::getNextMatch( TermGenEnv * s, TNode eqc, std::map< TypeNode,
if( d_match_status_child_num==0 ){
//initial binding
TNode f = s->getTgFunc( d_typ, d_status_num );
- //std::map< TNode, TermArgTrie >::iterator it = s->getTermDatabase()->d_func_map_eqc_trie[f].d_data.find( eqc );
Assert( !eqc.isNull() );
TermArgTrie * tat = s->getTermDatabase()->getTermArgTrie( eqc, f );
if( tat ){
@@ -1726,9 +1725,9 @@ void TermGenEnv::collectSignatureInformation() {
d_func_kind.clear();
d_func_args.clear();
TypeNode tnull;
- for( std::map< Node, TermArgTrie >::iterator it = getTermDatabase()->d_func_map_trie.begin(); it != getTermDatabase()->d_func_map_trie.end(); ++it ){
- if( getTermDatabase()->getNumGroundTerms( it->first )>0 ){
- Node nn = getTermDatabase()->getGroundTerm( it->first, 0 );
+ for( std::map< Node, std::vector< Node > >::iterator it = getTermDatabase()->d_op_map.begin(); it != getTermDatabase()->d_op_map.end(); ++it ){
+ if( !it->second.empty() ){
+ Node nn = it->second[0];
Trace("sg-rel-sig-debug") << "Check in signature : " << nn << std::endl;
if( d_cg->isHandledTerm( nn ) && nn.getKind()!=APPLY_SELECTOR_TOTAL && !nn.getType().isBoolean() ){
bool do_enum = true;
@@ -1750,7 +1749,7 @@ void TermGenEnv::collectSignatureInformation() {
d_typ_tg_funcs[nn.getType()].push_back( it->first );
d_tg_func_param[it->first] = ( nn.getMetaKind() == kind::metakind::PARAMETERIZED );
Trace("sg-rel-sig") << "Will enumerate function applications of : " << it->first << ", #args = " << d_func_args[it->first].size() << ", kind = " << nn.getKind() << std::endl;
- getTermDatabase()->computeUfEqcTerms( it->first );
+ //getTermDatabase()->computeUfEqcTerms( it->first );
}
}
Trace("sg-rel-sig-debug") << "Done check in signature : " << nn << std::endl;
diff --git a/src/theory/quantifiers/conjecture_generator.h b/src/theory/quantifiers/conjecture_generator.h
index c89d0f2ee..c89d0f2ee 100644..100755
--- a/src/theory/quantifiers/conjecture_generator.h
+++ b/src/theory/quantifiers/conjecture_generator.h
diff --git a/src/theory/quantifiers/equality_infer.cpp b/src/theory/quantifiers/equality_infer.cpp
index c3064116f..5190025ee 100644..100755
--- a/src/theory/quantifiers/equality_infer.cpp
+++ b/src/theory/quantifiers/equality_infer.cpp
@@ -53,10 +53,10 @@ void EqualityInference::addToExplanation( std::vector< Node >& exp, Node e ) {
}
void EqualityInference::addToExplanationEqc( std::vector< Node >& exp, Node eqc ) {
- NodeListMap::iterator re_i = d_rep_exp.find( eqc );
+ NodeIntMap::iterator re_i = d_rep_exp.find( eqc );
if( re_i!=d_rep_exp.end() ){
- for( unsigned i=0; i<(*re_i).second->size(); i++ ){
- addToExplanation( exp, (*(*re_i).second)[i] );
+ for( int i=0; i<(*re_i).second; i++ ){
+ addToExplanation( exp, d_rep_exp_data[eqc][i] );
}
}
//for( unsigned i=0; i<d_eqci[n]->d_rep_exp.size(); i++ ){
@@ -65,16 +65,19 @@ void EqualityInference::addToExplanationEqc( std::vector< Node >& exp, Node eqc
}
void EqualityInference::addToExplanationEqc( Node eqc, std::vector< Node >& exp_to_add ) {
- NodeListMap::iterator re_i = d_rep_exp.find( eqc );
- NodeList* re;
+ NodeIntMap::iterator re_i = d_rep_exp.find( eqc );
+ int n_re = 0;
if( re_i != d_rep_exp.end() ){
- re = (*re_i).second;
- }else{
- re = new(d_c->getCMM()) NodeList( true, d_c, false, context::ContextMemoryAllocator<TNode>(d_c->getCMM()) );
- d_rep_exp.insertDataFromContextMemory( eqc, re );
+ n_re = (*re_i).second;
}
+ d_rep_exp[eqc] = n_re + exp_to_add.size();
for( unsigned i=0; i<exp_to_add.size(); i++ ){
- re->push_back( exp_to_add[i] );
+ if( n_re<(int)d_rep_exp_data[eqc].size() ){
+ d_rep_exp_data[eqc][n_re] = exp_to_add[i];
+ }else{
+ d_rep_exp_data[eqc].push_back( exp_to_add[i] );
+ }
+ n_re++;
}
//for( unsigned i=0; i<exp_to_add.size(); i++ ){
// eqci->d_rep_exp.push_back( exp_to_add[i] );
@@ -204,16 +207,18 @@ void EqualityInference::eqNotifyNewClass(TNode t) {
void EqualityInference::addToUseList( Node used, Node eqc ) {
#if 1
- NodeListMap::iterator ul_i = d_uselist.find( used );
- NodeList* ul;
+ NodeIntMap::iterator ul_i = d_uselist.find( used );
+ int n_ul = 0;
if( ul_i != d_uselist.end() ){
- ul = (*ul_i).second;
- }else{
- ul = new(d_c->getCMM()) NodeList( true, d_c, false, context::ContextMemoryAllocator<TNode>(d_c->getCMM()) );
- d_uselist.insertDataFromContextMemory( used, ul );
+ n_ul = (*ul_i).second;
}
+ d_uselist[ used ] = n_ul + 1;
Trace("eq-infer-debug") << " add to use list : " << used << " -> " << eqc << std::endl;
- (*ul).push_back( eqc );
+ if( n_ul<(int)d_uselist_data[used].size() ){
+ d_uselist_data[used][n_ul] = eqc;
+ }else{
+ d_uselist_data[used].push_back( eqc );
+ }
#else
std::map< Node, EqcInfo * >::iterator itu = d_eqci.find( used );
EqcInfo * eqci_used;
@@ -356,12 +361,12 @@ void EqualityInference::eqNotifyMerge(TNode t1, TNode t2) {
//go through all equivalence classes that may refer to v_solve
std::map< Node, bool > processed;
processed[v_solve] = true;
- NodeListMap::iterator ul_i = d_uselist.find( v_solve );
+ NodeIntMap::iterator ul_i = d_uselist.find( v_solve );
if( ul_i != d_uselist.end() ){
- NodeList* ul = (*ul_i).second;
- Trace("eq-infer-debug") << " use list size = " << ul->size() << std::endl;
- for( unsigned j=0; j<ul->size(); j++ ){
- Node r = (*ul)[j];
+ int n_ul = (*ul_i).second;
+ Trace("eq-infer-debug") << " use list size = " << n_ul << std::endl;
+ for( int j=0; j<n_ul; j++ ){
+ Node r = d_uselist_data[v_solve][j];
//Trace("eq-infer-debug") << " use list size = " << eqci_solved->d_uselist.size() << std::endl;
//for( unsigned j=0; j<eqci_solved->d_uselist.size(); j++ ){
// Node r = eqci_solved->d_uselist[j];
diff --git a/src/theory/quantifiers/equality_infer.h b/src/theory/quantifiers/equality_infer.h
index 93c7bd080..80d6ef98b 100644..100755
--- a/src/theory/quantifiers/equality_infer.h
+++ b/src/theory/quantifiers/equality_infer.h
@@ -39,7 +39,7 @@ class EqualityInference
typedef context::CDHashMap< Node, Node, NodeHashFunction > NodeMap;
typedef context::CDHashMap< Node, bool, NodeHashFunction > BoolMap;
typedef context::CDChunkList<Node> NodeList;
- typedef context::CDHashMap< Node, NodeList *, NodeHashFunction > NodeListMap;
+ typedef context::CDHashMap< Node, int, NodeHashFunction > NodeIntMap;
private:
context::Context * d_c;
Node d_one;
@@ -67,11 +67,13 @@ private:
BoolMap d_elim_vars;
std::map< Node, EqcInfo * > d_eqci;
NodeMap d_rep_to_eqc;
- NodeListMap d_rep_exp;
+ NodeIntMap d_rep_exp;
+ std::map< Node, std::vector< Node > > d_rep_exp_data;
/** set eqc rep */
void setEqcRep( Node t, Node r, std::vector< Node >& exp_to_add, EqcInfo * eqci );
/** use list */
- NodeListMap d_uselist;
+ NodeIntMap d_uselist;
+ std::map< Node, std::vector< Node > > d_uselist_data;
void addToUseList( Node used, Node eqc );
/** pending merges */
NodeList d_pending_merges;
diff --git a/src/theory/quantifiers/first_order_model.cpp b/src/theory/quantifiers/first_order_model.cpp
index a833f48d2..670f0eff3 100644..100755
--- a/src/theory/quantifiers/first_order_model.cpp
+++ b/src/theory/quantifiers/first_order_model.cpp
@@ -406,8 +406,8 @@ Node FirstOrderModelIG::evaluateTerm( Node n, int& depIndex, RepSetIterator* ri
//check the type of n
if( n.getKind()==INST_CONSTANT ){
int v = n.getAttribute(InstVarNumAttribute());
- depIndex = ri->d_var_order[ v ];
- val = ri->getTerm( v );
+ depIndex = ri->getIndexOrder( v );
+ val = ri->getCurrentTerm( v );
}else if( n.getKind()==ITE ){
int depIndex1, depIndex2;
int eval = evaluate( n[0], depIndex1, ri );
diff --git a/src/theory/quantifiers/first_order_model.h b/src/theory/quantifiers/first_order_model.h
index cbe83cfa5..cbe83cfa5 100644..100755
--- a/src/theory/quantifiers/first_order_model.h
+++ b/src/theory/quantifiers/first_order_model.h
diff --git a/src/theory/quantifiers/full_model_check.cpp b/src/theory/quantifiers/full_model_check.cpp
index 33c853328..a0665cb7f 100644..100755
--- a/src/theory/quantifiers/full_model_check.cpp
+++ b/src/theory/quantifiers/full_model_check.cpp
@@ -405,7 +405,7 @@ void FullModelChecker::processBuildModel(TheoryModel* m, bool fullModel){
bool needsDefault = true;
for( size_t i=0; i<fm->d_uf_terms[op].size(); i++ ){
Node n = fm->d_uf_terms[op][i];
- if( !n.getAttribute(NoMatchAttribute()) ){
+ if( d_qe->getTermDatabase()->isTermActive( n ) ){
add_conds.push_back( n );
add_values.push_back( n );
Node r = fm->getUsedRepresentative(n);
@@ -764,7 +764,7 @@ bool FullModelChecker::exhaustiveInstantiate(FirstOrderModelFmc * fm, Node f, No
Trace("fmc-exh-debug") << "Set element domains..." << std::endl;
//set the domains based on the entry
for (unsigned i=0; i<c.getNumChildren(); i++) {
- if (riter.d_enum_type[i]==RepSetIterator::ENUM_DOMAIN_ELEMENTS) {
+ if( riter.d_enum_type[i]==RepSetIterator::ENUM_DOMAIN_ELEMENTS || riter.d_enum_type[i]==RepSetIterator::ENUM_SET_MEMBERS ){
TypeNode tn = c[i].getType();
if( d_rep_ids.find(tn)!=d_rep_ids.end() ){
if( fm->isInterval(c[i]) || fm->isStar(c[i]) ){
@@ -773,6 +773,7 @@ bool FullModelChecker::exhaustiveInstantiate(FirstOrderModelFmc * fm, Node f, No
if (d_rep_ids[tn].find(c[i])!=d_rep_ids[tn].end()) {
riter.d_domain[i].clear();
riter.d_domain[i].push_back(d_rep_ids[tn][c[i]]);
+ riter.d_enum_type[i] = RepSetIterator::ENUM_DOMAIN_ELEMENTS;
}else{
Trace("fmc-exh") << "---- Does not have rep : " << c[i] << " for type " << tn << std::endl;
return false;
@@ -792,7 +793,7 @@ bool FullModelChecker::exhaustiveInstantiate(FirstOrderModelFmc * fm, Node f, No
std::vector< Node > ev_inst;
std::vector< Node > inst;
for( int i=0; i<riter.getNumTerms(); i++ ){
- Node rr = riter.getTerm( i );
+ Node rr = riter.getCurrentTerm( i );
Node r = rr;
//if( r.getType().isSort() ){
r = fm->getUsedRepresentative( r );
@@ -826,18 +827,18 @@ bool FullModelChecker::exhaustiveInstantiate(FirstOrderModelFmc * fm, Node f, No
int index = riter.increment();
Trace("fmc-exh-debug") << "Incremented index " << index << std::endl;
if( !riter.isFinished() ){
- if (index>=0 && riter.d_index[index]>0 && addedLemmas>0 && riter.d_enum_type[index]==RepSetIterator::ENUM_RANGE) {
+ if (index>=0 && riter.d_index[index]>0 && addedLemmas>0 && riter.d_enum_type[index]==RepSetIterator::ENUM_INT_RANGE) {
Trace("fmc-exh-debug") << "Since this is a range enumeration, skip to the next..." << std::endl;
riter.increment2( index-1 );
}
}
}
d_addedLemmas += addedLemmas;
- Trace("fmc-exh") << "----Finished Exhaustive instantiate, lemmas = " << addedLemmas << ", incomplete=" << riter.d_incomplete << std::endl;
- return addedLemmas>0 || !riter.d_incomplete;
+ Trace("fmc-exh") << "----Finished Exhaustive instantiate, lemmas = " << addedLemmas << ", incomplete=" << riter.isIncomplete() << std::endl;
+ return addedLemmas>0 || !riter.isIncomplete();
}else{
Trace("fmc-exh") << "----Finished Exhaustive instantiate, failed." << std::endl;
- return false;
+ return !riter.isIncomplete();
}
}
diff --git a/src/theory/quantifiers/full_model_check.h b/src/theory/quantifiers/full_model_check.h
index 411b7a5eb..411b7a5eb 100644..100755
--- a/src/theory/quantifiers/full_model_check.h
+++ b/src/theory/quantifiers/full_model_check.h
diff --git a/src/theory/quantifiers/fun_def_engine.cpp b/src/theory/quantifiers/fun_def_engine.cpp
index cf1d14663..cf1d14663 100644..100755
--- a/src/theory/quantifiers/fun_def_engine.cpp
+++ b/src/theory/quantifiers/fun_def_engine.cpp
diff --git a/src/theory/quantifiers/fun_def_engine.h b/src/theory/quantifiers/fun_def_engine.h
index 3b95281c0..3b95281c0 100644..100755
--- a/src/theory/quantifiers/fun_def_engine.h
+++ b/src/theory/quantifiers/fun_def_engine.h
diff --git a/src/theory/quantifiers/fun_def_process.cpp b/src/theory/quantifiers/fun_def_process.cpp
index 9109aab8a..9109aab8a 100644..100755
--- a/src/theory/quantifiers/fun_def_process.cpp
+++ b/src/theory/quantifiers/fun_def_process.cpp
diff --git a/src/theory/quantifiers/fun_def_process.h b/src/theory/quantifiers/fun_def_process.h
index 1f6ee6562..1f6ee6562 100644..100755
--- a/src/theory/quantifiers/fun_def_process.h
+++ b/src/theory/quantifiers/fun_def_process.h
diff --git a/src/theory/quantifiers/inst_match.cpp b/src/theory/quantifiers/inst_match.cpp
index 8818175db..8818175db 100644..100755
--- a/src/theory/quantifiers/inst_match.cpp
+++ b/src/theory/quantifiers/inst_match.cpp
diff --git a/src/theory/quantifiers/inst_match.h b/src/theory/quantifiers/inst_match.h
index ad287c1a3..ad287c1a3 100644..100755
--- a/src/theory/quantifiers/inst_match.h
+++ b/src/theory/quantifiers/inst_match.h
diff --git a/src/theory/quantifiers/inst_match_generator.cpp b/src/theory/quantifiers/inst_match_generator.cpp
index bf05de3bb..2d3bf76f6 100644..100755
--- a/src/theory/quantifiers/inst_match_generator.cpp
+++ b/src/theory/quantifiers/inst_match_generator.cpp
@@ -32,6 +32,7 @@ namespace theory {
namespace inst {
InstMatchGenerator::InstMatchGenerator( Node pat ){
+ d_cg = NULL;
d_needsReset = true;
d_active_add = false;
Assert( quantifiers::TermDb::hasInstConstAttr(pat) );
@@ -43,12 +44,20 @@ InstMatchGenerator::InstMatchGenerator( Node pat ){
}
InstMatchGenerator::InstMatchGenerator() {
+ d_cg = NULL;
d_needsReset = true;
d_active_add = false;
d_next = NULL;
d_matchPolicy = MATCH_GEN_DEFAULT;
}
+InstMatchGenerator::~InstMatchGenerator() throw() {
+ for( unsigned i=0; i<d_children.size(); i++ ){
+ delete d_children[i];
+ }
+ delete d_cg;
+}
+
void InstMatchGenerator::setActiveAdd(bool val){
d_active_add = val;
if( d_next!=NULL ){
@@ -150,7 +159,7 @@ void InstMatchGenerator::initialize( Node q, QuantifiersEngine* qe, std::vector<
d_cg = new inst::CandidateGeneratorQELitDeq( qe, d_match_pattern );
}
}else{
- d_cg = new CandidateGeneratorQueue;
+ d_cg = new CandidateGeneratorQueue( qe );
Trace("inst-match-gen-warn") << "(?) Unknown matching pattern is " << d_match_pattern << std::endl;
d_matchPolicy = MATCH_GEN_INTERNAL_ERROR;
}
@@ -249,7 +258,7 @@ bool InstMatchGenerator::getMatch( Node f, Node t, InstMatch& m, QuantifiersEngi
Trace("matching-debug2") << "Reset children..." << std::endl;
//now, fit children into match
//we will be requesting candidates for matching terms for each child
- for( int i=0; i<(int)d_children.size(); i++ ){
+ for( unsigned i=0; i<d_children.size(); i++ ){
d_children[i]->reset( t[ d_children_index[i] ], qe );
}
Trace("matching-debug2") << "Continue next " << d_next << std::endl;
@@ -484,7 +493,7 @@ d_f( q ){
}
Debug("smart-multi-trigger") << std::endl;
}
- for( int i=0; i<(int)pats.size(); i++ ){
+ for( unsigned i=0; i<pats.size(); i++ ){
Node n = pats[i];
//make the match generator
d_children.push_back( InstMatchGenerator::mkInstMatchGenerator(q, n, qe ) );
@@ -492,7 +501,7 @@ d_f( q ){
std::vector< int > unique_vars;
std::map< int, bool > shared_vars;
int numSharedVars = 0;
- for( int j=0; j<(int)d_var_contains[n].size(); j++ ){
+ for( unsigned j=0; j<d_var_contains[n].size(); j++ ){
if( d_var_to_node[ d_var_contains[n][j] ].size()==1 ){
Debug("smart-multi-trigger") << "Var " << d_var_contains[n][j] << " is unique to " << pats[i] << std::endl;
unique_vars.push_back( d_var_contains[n][j] );
@@ -503,7 +512,7 @@ d_f( q ){
}
//we use the latest shared variables, then unique variables
std::vector< int > vars;
- int index = i==0 ? (int)(pats.size()-1) : (i-1);
+ unsigned index = i==0 ? pats.size()-1 : (i-1);
while( numSharedVars>0 && index!=i ){
for( std::map< int, bool >::iterator it = shared_vars.begin(); it != shared_vars.end(); ++it ){
if( it->second ){
@@ -519,16 +528,24 @@ d_f( q ){
}
vars.insert( vars.end(), unique_vars.begin(), unique_vars.end() );
Debug("smart-multi-trigger") << " Index[" << i << "]: ";
- for( int i=0; i<(int)vars.size(); i++ ){
- Debug("smart-multi-trigger") << vars[i] << " ";
+ for( unsigned j=0; j<vars.size(); j++ ){
+ Debug("smart-multi-trigger") << vars[j] << " ";
}
Debug("smart-multi-trigger") << std::endl;
//make ordered inst match trie
- InstMatchTrie::ImtIndexOrder* imtio = new InstMatchTrie::ImtIndexOrder;
- imtio->d_order.insert( imtio->d_order.begin(), vars.begin(), vars.end() );
- d_children_trie.push_back( InstMatchTrieOrdered( imtio ) );
+ d_imtio[i] = new InstMatchTrie::ImtIndexOrder;
+ d_imtio[i]->d_order.insert( d_imtio[i]->d_order.begin(), vars.begin(), vars.end() );
+ d_children_trie.push_back( InstMatchTrieOrdered( d_imtio[i] ) );
}
+}
+InstMatchGeneratorMulti::~InstMatchGeneratorMulti() throw() {
+ for( unsigned i=0; i<d_children.size(); i++ ){
+ delete d_children[i];
+ }
+ for( std::map< unsigned, InstMatchTrie::ImtIndexOrder* >::iterator it = d_imtio.begin(); it != d_imtio.end(); ++it ){
+ delete it->second;
+ }
}
/** reset instantiation round (call this whenever equivalence classes have changed) */
@@ -697,7 +714,7 @@ int InstMatchGeneratorMulti::addTerm( Node q, Node t, QuantifiersEngine* qe ){
return addedLemmas;
}
-InstMatchGeneratorSimple::InstMatchGeneratorSimple( Node q, Node pat ) : d_f( q ), d_match_pattern( pat ) {
+InstMatchGeneratorSimple::InstMatchGeneratorSimple( Node q, Node pat, QuantifiersEngine* qe ) : d_f( q ), d_match_pattern( pat ) {
if( d_match_pattern.getKind()==NOT ){
d_match_pattern = d_match_pattern[0];
d_pol = false;
@@ -720,10 +737,11 @@ InstMatchGeneratorSimple::InstMatchGeneratorSimple( Node q, Node pat ) : d_f( q
}
d_match_pattern_arg_types.push_back( d_match_pattern[i].getType() );
}
+ d_op = qe->getTermDatabase()->getMatchOperator( d_match_pattern );
}
void InstMatchGeneratorSimple::resetInstantiationRound( QuantifiersEngine* qe ) {
- d_op = qe->getTermDatabase()->getMatchOperator( d_match_pattern );
+
}
int InstMatchGeneratorSimple::addInstantiations( Node q, InstMatch& baseMatch, QuantifiersEngine* qe ){
@@ -751,6 +769,7 @@ int InstMatchGeneratorSimple::addInstantiations( Node q, InstMatch& baseMatch, Q
tat = NULL;
}
}
+ Debug("simple-trigger-debug") << "Adding instantiations based on " << tat << " from " << d_op << " " << d_eqc << std::endl;
if( tat ){
InstMatch m( q );
m.add( baseMatch );
diff --git a/src/theory/quantifiers/inst_match_generator.h b/src/theory/quantifiers/inst_match_generator.h
index a1d907001..096774c51 100644..100755
--- a/src/theory/quantifiers/inst_match_generator.h
+++ b/src/theory/quantifiers/inst_match_generator.h
@@ -91,7 +91,7 @@ public:
InstMatchGenerator( Node pat );
InstMatchGenerator();
/** destructor */
- ~InstMatchGenerator() throw() {}
+ virtual ~InstMatchGenerator() throw();
/** The pattern we are producing matches for.
If null, this is a multi trigger that is merging matches from d_children.
*/
@@ -125,7 +125,7 @@ public:
class VarMatchGeneratorBooleanTerm : public InstMatchGenerator {
public:
VarMatchGeneratorBooleanTerm( Node var, Node comp );
- ~VarMatchGeneratorBooleanTerm() throw() {}
+ virtual ~VarMatchGeneratorBooleanTerm() throw() {}
Node d_comp;
bool d_rm_prev;
/** reset instantiation round (call this at beginning of instantiation round) */
@@ -142,7 +142,7 @@ public:
class VarMatchGeneratorTermSubs : public InstMatchGenerator {
public:
VarMatchGeneratorTermSubs( Node var, Node subs );
- ~VarMatchGeneratorTermSubs() throw() {}
+ virtual ~VarMatchGeneratorTermSubs() throw() {}
TNode d_var;
TypeNode d_var_type;
Node d_subs;
@@ -183,6 +183,8 @@ private:
int d_matchPolicy;
/** children generators */
std::vector< InstMatchGenerator* > d_children;
+ /** order */
+ std::map< unsigned, InstMatchTrie::ImtIndexOrder* > d_imtio;
/** inst match tries for each child */
std::vector< InstMatchTrieOrdered > d_children_trie;
/** calculate matches */
@@ -191,7 +193,7 @@ public:
/** constructors */
InstMatchGeneratorMulti( Node q, std::vector< Node >& pats, QuantifiersEngine* qe );
/** destructor */
- ~InstMatchGeneratorMulti() throw() {}
+ virtual ~InstMatchGeneratorMulti() throw();
/** reset instantiation round (call this whenever equivalence classes have changed) */
void resetInstantiationRound( QuantifiersEngine* qe );
/** reset, eqc is the equivalence class to search in (any if eqc=null) */
@@ -224,7 +226,7 @@ private:
void addInstantiations( InstMatch& m, QuantifiersEngine* qe, int& addedLemmas, int argIndex, quantifiers::TermArgTrie* tat );
public:
/** constructors */
- InstMatchGeneratorSimple( Node q, Node pat );
+ InstMatchGeneratorSimple( Node q, Node pat, QuantifiersEngine* qe );
/** destructor */
~InstMatchGeneratorSimple() throw() {}
/** reset instantiation round (call this whenever equivalence classes have changed) */
diff --git a/src/theory/quantifiers/inst_propagator.cpp b/src/theory/quantifiers/inst_propagator.cpp
index d4be58636..41c9c40c8 100644..100755
--- a/src/theory/quantifiers/inst_propagator.cpp
+++ b/src/theory/quantifiers/inst_propagator.cpp
@@ -34,6 +34,7 @@ bool EqualityQueryInstProp::reset( Theory::Effort e ) {
d_uf.clear();
d_uf_exp.clear();
d_diseq_list.clear();
+ d_uf_func_map_trie.clear();
return true;
}
@@ -103,8 +104,7 @@ TNode EqualityQueryInstProp::getCongruentTerm( Node f, std::vector< TNode >& arg
if( !t.isNull() ){
return t;
}else{
- //TODO?
- return TNode::null();
+ return d_uf_func_map_trie[f].existsTerm( args );
}
}
@@ -118,6 +118,7 @@ Node EqualityQueryInstProp::getRepresentativeExp( Node a, std::vector< Node >& e
Node ar = getUfRepresentative( a, exp );
if( !ar.isNull() ){
if( engine_has_a || getEngine()->hasTerm( ar ) ){
+ Trace("qip-eq") << "getRepresentativeExp " << a << " returns " << ar << std::endl;
Assert( getEngine()->hasTerm( ar ) );
Assert( getEngine()->getRepresentative( ar )==ar );
return ar;
@@ -168,6 +169,21 @@ bool EqualityQueryInstProp::areDisequalExp( Node a, Node b, std::vector< Node >&
}
}
+TNode EqualityQueryInstProp::getCongruentTermExp( Node f, std::vector< TNode >& args, std::vector< Node >& exp ) {
+ TNode t = d_qe->getTermDatabase()->getCongruentTerm( f, args );
+ if( !t.isNull() ){
+ return t;
+ }else{
+ TNode tt = d_uf_func_map_trie[f].existsTerm( args );
+ if( !tt.isNull() ){
+ //TODO?
+ return tt;
+ }else{
+ return tt;
+ }
+ }
+}
+
Node EqualityQueryInstProp::getUfRepresentative( Node a, std::vector< Node >& exp ) {
Assert( exp.empty() );
std::map< Node, Node >::iterator it = d_uf.find( a );
@@ -252,7 +268,7 @@ int EqualityQueryInstProp::setEqual( Node& a, Node& b, bool pol, std::vector< No
}
}
}
-
+
if( swap ){
//swap
Node temp_r = ar;
@@ -262,7 +278,7 @@ int EqualityQueryInstProp::setEqual( Node& a, Node& b, bool pol, std::vector< No
Assert( !getEngine()->hasTerm( ar ) || getEngine()->hasTerm( br ) );
Assert( ar!=br );
-
+
std::vector< Node > exp_d;
if( areDisequalExp( ar, br, exp_d ) ){
if( pol ){
@@ -279,18 +295,20 @@ int EqualityQueryInstProp::setEqual( Node& a, Node& b, bool pol, std::vector< No
Assert( d_uf_exp[ar].empty() );
Assert( d_uf_exp[br].empty() );
+ //registerUfTerm( ar );
d_uf[ar] = br;
merge_exp( d_uf_exp[ar], exp_a );
merge_exp( d_uf_exp[ar], exp_b );
merge_exp( d_uf_exp[ar], reason );
+ //registerUfTerm( br );
d_uf[br] = br;
d_uf_exp[br].clear();
Trace("qip-eq") << "EqualityQueryInstProp::setEqual : merge " << ar << " -> " << br << ", exp size = " << d_uf_exp[ar].size() << ", status = " << status << std::endl;
a = ar;
b = br;
-
+
//carry disequality list
std::map< Node, std::map< Node, std::vector< Node > > >::iterator itd = d_diseq_list.find( ar );
if( itd!=d_diseq_list.end() ){
@@ -302,13 +320,13 @@ int EqualityQueryInstProp::setEqual( Node& a, Node& b, bool pol, std::vector< No
}
}
}
-
+
return status;
}else{
Trace("qip-eq") << "EqualityQueryInstProp::setEqual : disequal " << ar << " <> " << br << std::endl;
Assert( d_diseq_list[ar].find( br )==d_diseq_list[ar].end() );
Assert( d_diseq_list[br].find( ar )==d_diseq_list[br].end() );
-
+
merge_exp( d_diseq_list[ar][br], reason );
merge_exp( d_diseq_list[br][ar], reason );
return STATUS_NONE;
@@ -316,187 +334,234 @@ int EqualityQueryInstProp::setEqual( Node& a, Node& b, bool pol, std::vector< No
}
}
-void EqualityQueryInstProp::addArgument( std::vector< Node >& args, std::vector< Node >& props, Node n, bool is_prop, bool pol ) {
- if( is_prop ){
- if( isLiteral( n ) ){
- props.push_back( pol ? n : n.negate() );
- return;
+void EqualityQueryInstProp::registerUfTerm( TNode n ) {
+ if( d_uf.find( n )==d_uf.end() ){
+ if( !getEngine()->hasTerm( n ) ){
+ TNode f = d_qe->getTermDatabase()->getMatchOperator( n );
+ if( !f.isNull() ){
+ std::vector< TNode > args;
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ if( !getEngine()->hasTerm( n[i] ) ){
+ return;
+ }else{
+ args.push_back( n[i] );
+ }
+ }
+ d_uf_func_map_trie[f].addTerm( n, args );
+ }
}
}
+}
+
+//void EqualityQueryInstProp::addArgument( std::vector< Node >& args, std::vector< Node >& props, Node n, bool is_prop, bool pol ) {
+void EqualityQueryInstProp::addArgument( Node n, std::vector< Node >& args, std::vector< Node >& watch, bool is_watch ) {
+ if( is_watch ){
+ watch.push_back( n );
+ }
args.push_back( n );
}
-bool EqualityQueryInstProp::isLiteral( Node n ) {
- Kind ak = n.getKind()==NOT ? n[0].getKind() : n.getKind();
- Assert( ak!=NOT );
- return ak!=AND && ak!=OR && ak!=IFF && ak!=ITE;
+bool EqualityQueryInstProp::isPropagateLiteral( Node n ) {
+ if( n==d_true || n==d_false ){
+ return false;
+ }else{
+ Kind ak = n.getKind()==NOT ? n[0].getKind() : n.getKind();
+ Assert( ak!=NOT );
+ return ak!=AND && ak!=OR && ak!=IFF && ak!=ITE;
+ }
+}
+
+void EqualityQueryInstProp::setWatchList( Node n, std::vector< Node >& watch, std::map< Node, std::vector< Node > >& watch_list_out ) {
+ if( watch.empty() ){
+ watch.push_back( n );
+ }
+ for( unsigned j=0; j<watch.size(); j++ ){
+ Trace("qip-eval") << "Watch : " << n << " -> " << watch[j] << std::endl;
+ watch_list_out[n].push_back( watch[j] );
+ }
+}
+
+void EqualityQueryInstProp::collectWatchList( Node n, std::map< Node, std::vector< Node > >& watch_list_out, std::vector< Node >& watch_list ) {
+ std::map< Node, std::vector< Node > >::iterator it = watch_list_out.find( n );
+ if( it!=watch_list_out.end() && std::find( watch_list.begin(), watch_list.end(), n )==watch_list.end() ){
+ watch_list.push_back( n );
+ for( unsigned j=0; j<it->second.size(); j++ ){
+ collectWatchList( it->second[j], watch_list_out, watch_list );
+ }
+ }
}
-//this is identical to TermDb::evaluateTerm2, but tracks more information
-Node EqualityQueryInstProp::evaluateTermExp( Node n, std::vector< Node >& exp, std::map< Node, Node >& visited, bool hasPol, bool pol,
- std::map< Node, bool >& watch_list_out, std::vector< Node >& props ) {
- std::map< Node, Node >::iterator itv = visited.find( n );
- if( itv != visited.end() ){
+//this is similar to TermDb::evaluateTerm2, but tracks more information
+Node EqualityQueryInstProp::evaluateTermExp( Node n, std::vector< Node >& exp, std::map< int, std::map< Node, Node > >& visited,
+ bool hasPol, bool pol, std::map< Node, std::vector< Node > >& watch_list_out, std::vector< Node >& props ) {
+ int polIndex = hasPol ? ( pol ? 1 : -1 ) : 0;
+ std::map< Node, Node >::iterator itv = visited[polIndex].find( n );
+ if( itv!=visited[polIndex].end() ){
return itv->second;
}else{
- visited[n] = n;
- Trace("qip-eval") << "evaluate term : " << n << std::endl;
- std::vector< Node > exp_n;
- Node ret = getRepresentativeExp( n, exp_n );
- if( ret.isNull() ){
- //term is not known to be equal to a representative in equality engine, evaluate it
- Kind k = n.getKind();
- if( k==FORALL ){
- ret = Node::null();
- }else{
- std::map< Node, bool > watch_list_out_curr;
- TNode f = d_qe->getTermDatabase()->getMatchOperator( n );
- std::vector< Node > args;
- bool ret_set = false;
- bool childChanged = false;
- int abort_i = -1;
- //get the child entailed polarity
- Assert( n.getKind()!=IMPLIES );
- bool newHasPol, newPol;
- QuantPhaseReq::getEntailPolarity( n, 0, hasPol, pol, newHasPol, newPol );
- //for each child
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- Node c = evaluateTermExp( n[i], exp, visited, newHasPol, newPol, watch_list_out_curr, props );
- if( c.isNull() ){
- ret = Node::null();
- ret_set = true;
- break;
- }else if( c==d_true || c==d_false ){
- //short-circuiting
- if( k==kind::AND || k==kind::OR ){
- if( (k==kind::AND)==(c==d_false) ){
- ret = c;
- ret_set = true;
- break;
- }else{
- //redundant
- c = Node::null();
- childChanged = true;
- }
- }else if( k==kind::ITE && i==0 ){
- Assert( watch_list_out_curr.empty() );
- ret = evaluateTermExp( n[ c==d_true ? 1 : 2], exp, visited, hasPol, pol, watch_list_out_curr, props );
- ret_set = true;
- break;
- }else if( k==kind::NOT ){
- ret = c==d_true ? d_false : d_true;
+ visited[polIndex][n] = n;
+ Node ret;
+ //check if it should be propagated in this context
+ if( hasPol && isPropagateLiteral( n ) ){
+ Assert( n.getType().isBoolean() );
+ //must be Boolean
+ ret = evaluateTermExp( n, exp, visited, false, pol, watch_list_out, props );
+ if( isPropagateLiteral( ret ) ){
+ Trace("qip-eval") << "-----> propagate : " << ret << std::endl;
+ props.push_back( pol ? ret : ret.negate() );
+ ret = pol ? d_true : d_false;
+ }
+ }else{
+ Trace("qip-eval") << "evaluate term : " << n << " [" << polIndex << "]" << std::endl;
+ std::vector< Node > exp_n;
+ ret = getRepresentativeExp( n, exp_n );
+ if( ret.isNull() ){
+ //term is not known to be equal to a representative in equality engine, evaluate it
+ Kind k = n.getKind();
+ if( k!=FORALL ){
+ TNode f = d_qe->getTermDatabase()->getMatchOperator( n );
+ std::vector< Node > args;
+ bool ret_set = false;
+ bool childChanged = false;
+ int abort_i = -1;
+ //get the child entailed polarity
+ Assert( n.getKind()!=IMPLIES );
+ bool newHasPol, newPol;
+ QuantPhaseReq::getEntailPolarity( n, 0, hasPol, pol, newHasPol, newPol );
+ std::vector< Node > watch;
+ //for each child
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ Node c = evaluateTermExp( n[i], exp, visited, newHasPol, newPol, watch_list_out, props );
+ if( c.isNull() ){
+ ret = Node::null();
ret_set = true;
break;
- }
- }
- if( !c.isNull() ){
- childChanged = childChanged || n[i]!=c;
- if( !f.isNull() && !watch_list_out_curr.empty() ){
- // we are done if this is an UF application and an argument is unevaluated
- args.push_back( c );
- abort_i = i;
- break;
- }else if( ( k==kind::AND || k==kind::OR ) ){
- if( c.getKind()==k ){
- //flatten
- for( unsigned j=0; j<c.getNumChildren(); j++ ){
- addArgument( args, props, c[j], newHasPol, newPol );
+ }else if( c==d_true || c==d_false ){
+ //short-circuiting
+ if( k==kind::AND || k==kind::OR ){
+ if( (k==kind::AND)==(c==d_false) ){
+ ret = c;
+ ret_set = true;
+ break;
+ }else{
+ //redundant
+ c = Node::null();
+ childChanged = true;
}
- }else{
- addArgument( args, props, c, newHasPol, newPol );
+ }else if( k==kind::ITE && i==0 ){
+ ret = evaluateTermExp( n[ c==d_true ? 1 : 2], exp, visited, hasPol, pol, watch_list_out, props );
+ ret_set = true;
+ break;
+ }else if( k==kind::NOT ){
+ ret = c==d_true ? d_false : d_true;
+ ret_set = true;
+ break;
}
- //if we are in a branching position
- if( hasPol && !newHasPol && args.size()>=2 ){
- //we are done if at least two args are unevaluated
+ }
+ if( !c.isNull() ){
+ childChanged = childChanged || n[i]!=c;
+ bool is_watch = watch_list_out.find( c )!=watch_list_out.end();
+ if( !f.isNull() && is_watch ){
+ // we are done if this is an UF application and an argument is unevaluated
+ addArgument( c, args, watch, is_watch );
abort_i = i;
break;
+ }else if( k==kind::AND || k==kind::OR || k==kind::ITE || k==IFF ){
+ Trace("qip-eval-debug") << "Adding argument " << c << " to " << k << ", isProp = " << newHasPol << std::endl;
+ if( ( k==kind::AND || k==kind::OR ) && c.getKind()==k ){
+ //flatten
+ for( unsigned j=0; j<c.getNumChildren(); j++ ){
+ addArgument( c[j], args, watch, is_watch );
+ }
+ }else{
+ addArgument( c, args, watch, is_watch );
+ }
+ Trace("qip-eval-debug") << "props/args = " << props.size() << "/" << args.size() << std::endl;
+ //if we are in a branching position
+ if( hasPol && !newHasPol && args.size()>=2 ){
+ //we are done if at least two args are unevaluated
+ abort_i = i;
+ break;
+ }
+ }else{
+ addArgument( c, args, watch, is_watch );
}
- }else if( k==kind::ITE ){
- //we are done if we are ITE and condition is unevaluated
- Assert( i==0 );
- args.push_back( c );
- abort_i = i;
- break;
- }else{
- args.push_back( c );
}
}
- }
- //add remaining children if we aborted
- if( abort_i!=-1 ){
- for( int i=(abort_i+1); i<(int)n.getNumChildren(); i++ ){
- args.push_back( n[i] );
- }
- }
- //copy over the watch list
- for( std::map< Node, bool >::iterator itc = watch_list_out_curr.begin(); itc != watch_list_out_curr.end(); ++itc ){
- watch_list_out[itc->first] = itc->second;
- }
-
- //if we have not short-circuited evaluation
- if( !ret_set ){
- //if it is an indexed term, return the congruent term
- if( !f.isNull() && watch_list_out.empty() ){
- std::vector< TNode > t_args;
- for( unsigned i=0; i<args.size(); i++ ) {
- t_args.push_back( args[i] );
- }
- Assert( args.size()==n.getNumChildren() );
- //args contains terms known by the equality engine
- TNode nn = getCongruentTerm( f, t_args );
- Trace("qip-eval") << " got congruent term " << nn << " from DB for " << n << std::endl;
- if( !nn.isNull() ){
- //successfully constructed representative in EE
- Assert( exp_n.empty() );
- ret = getRepresentativeExp( nn, exp_n );
- Trace("qip-eval") << "return rep, exp size = " << exp_n.size() << std::endl;
- merge_exp( exp, exp_n );
- ret_set = true;
- Assert( !ret.isNull() );
+ //add remaining children if we aborted
+ if( abort_i!=-1 ){
+ Trace("qip-eval-debug") << "..." << n << " aborted at " << abort_i << std::endl;
+ for( int i=(abort_i+1); i<(int)n.getNumChildren(); i++ ){
+ args.push_back( n[i] );
}
}
+ //if we have not short-circuited evaluation
if( !ret_set ){
- if( childChanged ){
- Trace("qip-eval") << "return rewrite" << std::endl;
- if( ( k==kind::AND || k==kind::OR ) ){
- if( args.empty() ){
- ret = k==kind::AND ? d_true : d_false;
- ret_set = true;
- }else if( args.size()==1 ){
- ret = args[0];
- ret_set = true;
- }
+ //if it is an indexed term, return the congruent term
+ if( !f.isNull() && watch.empty() ){
+ std::vector< TNode > t_args;
+ for( unsigned i=0; i<args.size(); i++ ) {
+ Trace("qip-eval") << "arg " << i << " : " << args[i] << std::endl;
+ t_args.push_back( args[i] );
+ }
+ Assert( args.size()==n.getNumChildren() );
+ //args contains terms known by the equality engine
+ TNode nn = getCongruentTerm( f, t_args );
+ Trace("qip-eval") << " got congruent term " << nn << " for " << n << std::endl;
+ if( !nn.isNull() ){
+ //successfully constructed representative in EE
+ Assert( exp_n.empty() );
+ ret = getRepresentativeExp( nn, exp_n );
+ Trace("qip-eval") << "return rep, exp size = " << exp_n.size() << std::endl;
+ merge_exp( exp, exp_n );
+ ret_set = true;
+ Assert( !ret.isNull() );
+ Assert( ret!=n );
+ // we have that n == ret, check if the union find should be updated TODO?
}else{
- Assert( args.size()==n.getNumChildren() );
+ watch.push_back( ret );
}
- if( !ret_set ){
- if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){
- args.insert( args.begin(), n.getOperator() );
+ }
+ if( !ret_set ){
+ if( childChanged || args.size()!=n.getNumChildren() ){
+ Trace("qip-eval") << "return rewrite" << std::endl;
+ if( k==kind::AND || k==kind::OR ){
+ if( args.empty() ){
+ ret = k==kind::AND ? d_true : d_false;
+ ret_set = true;
+ }else if( args.size()==1 ){
+ //need to re-evaluate (may be new propagations)
+ ret = evaluateTermExp( args[0], exp, visited, hasPol, pol, watch_list_out, props );
+ ret_set = true;
+ }
+ }else{
+ Assert( args.size()==n.getNumChildren() );
}
- ret = NodeManager::currentNM()->mkNode( k, args );
- ret = Rewriter::rewrite( ret );
- //re-evaluate
- Node ret_eval = getRepresentativeExp( ret, exp_n );
- if( !ret_eval.isNull() ){
- ret = ret_eval;
- watch_list_out.clear();
- }else{
- watch_list_out[ret] = true;
+ if( !ret_set ){
+ if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){
+ args.insert( args.begin(), n.getOperator() );
+ }
+ ret = NodeManager::currentNM()->mkNode( k, args );
+ setWatchList( ret, watch, watch_list_out );
+ ret = Rewriter::rewrite( ret );
+ //need to re-evaluate
+ ret = evaluateTermExp( ret, exp, visited, hasPol, pol, watch_list_out, props );
}
+ }else{
+ ret = n;
+ setWatchList( ret, watch, watch_list_out );
}
- }else{
- ret = n;
- watch_list_out[ret] = true;
}
}
}
+ }else{
+ Trace("qip-eval") << "...exists in ee, return rep, exp size = " << exp_n.size() << std::endl;
+ merge_exp( exp, exp_n );
}
- }else{
- Trace("qip-eval") << "...exists in ee, return rep, exp size = " << exp_n.size() << std::endl;
- merge_exp( exp, exp_n );
}
- Trace("qip-eval") << "evaluated term : " << n << ", got : " << ret << ", exp size = " << exp.size() << std::endl;
- visited[n] = ret;
+
+ Trace("qip-eval") << "evaluated term : " << n << " [" << polIndex << "], got : " << ret << ", exp size = " << exp.size() << ", watch list size = " << watch_list_out.size() << std::endl;
+ visited[polIndex][n] = ret;
return ret;
}
}
@@ -545,6 +610,7 @@ bool InstPropagator::reset( Theory::Effort e ) {
d_watch_list.clear();
d_update_list.clear();
d_relevant_inst.clear();
+ d_has_relevant_inst = false;
return d_qy.reset( e );
}
@@ -556,10 +622,7 @@ bool InstPropagator::notifyInstantiation( unsigned quant_e, Node q, Node lem, st
Trace("qip-prop") << " " << terms[i] << std::endl;
}
}
- unsigned id = d_icount;
- d_icount++;
- Trace("qip-prop") << "...assign id=" << id << std::endl;
- d_ii[id].init( q, lem, terms, body );
+ unsigned id = allocateInstantiation( q, lem, terms, body );
//initialize the information
if( cacheConclusion( id, body ) ){
Assert( d_update_list.empty() );
@@ -582,35 +645,67 @@ bool InstPropagator::notifyInstantiation( unsigned quant_e, Node q, Node lem, st
return !d_conflict;
}else{
Assert( false );
- return true;
+ return false;
+ }
+}
+
+void InstPropagator::filterInstantiations() {
+ if( d_has_relevant_inst ){
+ //now, inform quantifiers engine which instances should be retracted
+ Trace("qip-prop-debug") << "...remove instantiation ids : ";
+ for( std::map< unsigned, InstInfo >::iterator it = d_ii.begin(); it != d_ii.end(); ++it ){
+ if( !it->second.d_q.isNull() ){
+ if( d_relevant_inst.find( it->first )==d_relevant_inst.end() ){
+ if( !d_qe->removeInstantiation( it->second.d_q, it->second.d_lem, it->second.d_terms ) ){
+ Trace("qip-warn") << "WARNING : did not remove instantiation id " << it->first << std::endl;
+ Assert( false );
+ }else{
+ Trace("qip-prop-debug") << it->first << " ";
+ }
+ }else{
+ //mark the quantified formula as relevant
+ d_qe->markRelevant( it->second.d_q );
+ }
+ }
+ }
+ Trace("qip-prop-debug") << std::endl;
+ Trace("quant-engine-conflict") << "-----> InstPropagator::" << ( d_conflict ? "conflict" : "propagate" ) << " with " << d_relevant_inst.size() << " instances." << std::endl;
}
}
+unsigned InstPropagator::allocateInstantiation( Node q, Node lem, std::vector< Node >& terms, Node body ) {
+ unsigned id = d_icount;
+ d_icount++;
+ Trace("qip-prop") << "...assign id=" << id << std::endl;
+ d_ii[id].init( q, lem, terms, body );
+ return id;
+}
+
bool InstPropagator::update( unsigned id, InstInfo& ii, bool firstTime ) {
Assert( !d_conflict );
Assert( ii.d_active );
Trace("qip-prop-debug") << "Update info [" << id << "]..." << std::endl;
//update the evaluation of the current lemma
- std::map< Node, Node > visited;
- std::map< Node, bool > watch_list;
+ std::map< Node, std::vector< Node > > watch_list_out;
+ std::map< int, std::map< Node, Node > > visited;
+ std::vector< Node > exp;
std::vector< Node > props;
- Node eval = d_qy.evaluateTermExp( ii.d_curr, ii.d_curr_exp, visited, true, true, watch_list, props );
+ Node eval = d_qy.evaluateTermExp( ii.d_curr, exp, visited, true, true, watch_list_out, props );
+ EqualityQueryInstProp::merge_exp( ii.d_curr_exp, exp );
if( eval.isNull() ){
ii.d_active = false;
}else if( firstTime || eval!=ii.d_curr ){
- if( EqualityQueryInstProp::isLiteral( eval ) ){
- props.push_back( eval );
- eval = d_qy.d_true;
- watch_list.clear();
- }
+ std::vector< Node > watch_list;
+ d_qy.collectWatchList( eval, watch_list_out, watch_list );
if( Trace.isOn("qip-prop") ){
Trace("qip-prop") << "Update info [" << id << "]..." << std::endl;
- Trace("qip-prop") << "...updated lemma " << ii.d_curr << " -> " << eval << ", exp = ";
+ Trace("qip-prop") << "...updated lemma " << ii.d_curr << " -> " << eval << std::endl;
+ Trace("qip-prop") << "...explanation = ";
debugPrintExplanation( ii.d_curr_exp, "qip-prop" );
Trace("qip-prop") << std::endl;
Trace("qip-prop") << "...watch list: " << std::endl;
- for( std::map< Node, bool >::iterator itw = watch_list.begin(); itw!=watch_list.end(); ++itw ){
- Trace("qip-prop") << " " << itw->first << std::endl;
+ for( unsigned i=0; i<watch_list.size(); i++ ){
+ Trace("qip-prop") << " " << watch_list[i] << std::endl;
}
Trace("qip-prop") << "...new propagations: " << std::endl;
for( unsigned i=0; i<props.size(); i++ ){
@@ -627,8 +722,13 @@ bool InstPropagator::update( unsigned id, InstInfo& ii, bool firstTime ) {
}else{
for( unsigned i=0; i<props.size(); i++ ){
Trace("qip-prop-debug2") << "Process propagation " << props[i] << std::endl;
+ Assert( d_qy.isPropagateLiteral( props[i] ) );
//if we haven't propagated this literal yet
if( cacheConclusion( id, props[i], 1 ) ){
+ //watch list for propagated literal: may not yet be purely EE representatives
+ std::vector< Node > prop_watch_list;
+ d_qy.collectWatchList( props[i], watch_list_out, prop_watch_list );
+
Node lit = props[i].getKind()==NOT ? props[i][0] : props[i];
bool pol = props[i].getKind()!=NOT;
if( lit.getKind()==EQUAL ){
@@ -647,10 +747,10 @@ bool InstPropagator::update( unsigned id, InstInfo& ii, bool firstTime ) {
ii.d_curr = eval;
//update the watch list
Trace("qip-prop-debug") << "...updating watch list for [" << id << "], curr is " << ii.d_curr << std::endl;
- //Here, we need to be notified of enough terms such that if we are not notified, then update( ii ) will return no propagations.
- // Similar to two-watched literals, but since we are in UF, we need to watch all terms on a complete path of two terms.
- for( std::map< Node, bool >::iterator itw = watch_list.begin(); itw != watch_list.end(); ++itw ){
- d_watch_list[ itw->first ][ id ] = true;
+ //Here, we need to be notified of enough terms such that if we are not notified, then update( id, ii ) will return no propagations.
+ // Similar to two-watched literals, but since we are taking into account UF, we need to watch all terms on a complete path of two terms.
+ for( unsigned i=0; i<watch_list.size(); i++ ){
+ d_watch_list[ watch_list[i] ][ id ] = true;
}
}else{
Trace("qip-prop-debug") << "...conclusion " << eval << " is duplicate." << std::endl;
@@ -682,10 +782,12 @@ void InstPropagator::propagate( Node a, Node b, bool pol, std::vector< Node >& e
}
if( pol ){
if( status==EqualityQueryInstProp::STATUS_MERGED_KNOWN ){
+ Trace("qip-rlv-propagate") << "Relevant propagation : " << a << ( pol ? " == " : " != " ) << b << std::endl;
Assert( d_qy.getEngine()->hasTerm( a ) );
Assert( d_qy.getEngine()->hasTerm( b ) );
Trace("qip-prop-debug") << "...equality between known terms." << std::endl;
addRelevantInstances( exp, "qip-propagate" );
+ //d_has_relevant_inst = true;
}
Trace("qip-prop-debug") << "...merged representatives " << a << " and " << b << std::endl;
for( unsigned i=0; i<2; i++ ){
@@ -712,25 +814,7 @@ void InstPropagator::conflict( std::vector< Node >& exp ) {
d_conflict = true;
d_relevant_inst.clear();
addRelevantInstances( exp, "qip-propagate" );
-
- //now, inform quantifiers engine which instances should be retracted
- Trace("qip-prop-debug") << "...remove instantiation ids : ";
- for( std::map< unsigned, InstInfo >::iterator it = d_ii.begin(); it != d_ii.end(); ++it ){
- if( d_relevant_inst.find( it->first )==d_relevant_inst.end() ){
- if( !d_qe->removeInstantiation( it->second.d_q, it->second.d_lem, it->second.d_terms ) ){
- Trace("qip-warn") << "WARNING : did not remove instantiation id " << it->first << std::endl;
- Assert( false );
- }else{
- Trace("qip-prop-debug") << it->first << " ";
- }
- }else{
- //mark the quantified formula as relevant
- d_qe->markRelevant( it->second.d_q );
- }
- }
- Trace("qip-prop-debug") << std::endl;
- //will interupt the quantifiers engine
- Trace("quant-engine-conflict") << "-----> InstPropagator::conflict with " << exp.size() << " instances." << std::endl;
+ d_has_relevant_inst = true;
}
bool InstPropagator::cacheConclusion( unsigned id, Node body, int prop_index ) {
diff --git a/src/theory/quantifiers/inst_propagator.h b/src/theory/quantifiers/inst_propagator.h
index 0c02c7f95..6201cf152 100644..100755
--- a/src/theory/quantifiers/inst_propagator.h
+++ b/src/theory/quantifiers/inst_propagator.h
@@ -64,9 +64,11 @@ public:
bool areEqualExp( Node a, Node b, std::vector< Node >& exp );
/** returns true is a and b are disequal in the current context */
bool areDisequalExp( Node a, Node b, std::vector< Node >& exp );
+ /** get congruent term */
+ TNode getCongruentTermExp( Node f, std::vector< TNode >& args, std::vector< Node >& exp );
private:
/** term index */
- std::map< Node, TermArgTrie > d_func_map_trie;
+ std::map< Node, TermArgTrie > d_uf_func_map_trie;
/** union find for terms beyond what is stored in equality engine */
std::map< Node, Node > d_uf;
std::map< Node, std::vector< Node > > d_uf_exp;
@@ -74,7 +76,9 @@ private:
/** disequality list, stores explanations */
std::map< Node, std::map< Node, std::vector< Node > > > d_diseq_list;
/** add arg */
- void addArgument( std::vector< Node >& args, std::vector< Node >& props, Node n, bool is_prop, bool pol );
+ void addArgument( Node n, std::vector< Node >& args, std::vector< Node >& watch, bool is_watch );
+ /** register term */
+ void registerUfTerm( TNode n );
public:
enum {
STATUS_CONFLICT,
@@ -89,10 +93,13 @@ public:
public:
//for explanations
static void merge_exp( std::vector< Node >& v, std::vector< Node >& v_to_merge, int up_to_size = -1 );
+ //for watch list
+ static void setWatchList( Node n, std::vector< Node >& watch, std::map< Node, std::vector< Node > >& watch_list_out );
+ static void collectWatchList( Node n, std::map< Node, std::vector< Node > >& watch_list_out, std::vector< Node >& watch_list );
- Node evaluateTermExp( Node n, std::vector< Node >& exp, std::map< Node, Node >& visited, bool hasPol, bool pol,
- std::map< Node, bool >& watch_list_out, std::vector< Node >& props );
- static bool isLiteral( Node n );
+ Node evaluateTermExp( Node n, std::vector< Node >& exp, std::map< int, std::map< Node, Node > >& visited,
+ bool hasPol, bool pol, std::map< Node, std::vector< Node > >& watch_list_out, std::vector< Node >& props );
+ bool isPropagateLiteral( Node n );
};
class InstPropagator : public QuantifiersUtil {
@@ -104,13 +111,18 @@ private:
InstPropagator& d_ip;
public:
InstantiationNotifyInstPropagator(InstPropagator& ip): d_ip(ip) {}
- virtual bool notifyInstantiation( unsigned quant_e, Node q, Node lem, std::vector< Node >& terms, Node body ) {
- return d_ip.notifyInstantiation( quant_e, q, lem, terms, body );
+ virtual bool notifyInstantiation( unsigned quant_e, Node q, Node lem, std::vector< Node >& terms, Node body ) {
+ return d_ip.notifyInstantiation( quant_e, q, lem, terms, body );
}
+ virtual void filterInstantiations() { d_ip.filterInstantiations(); }
};
InstantiationNotifyInstPropagator d_notify;
/** notify instantiation method */
bool notifyInstantiation( unsigned quant_e, Node q, Node lem, std::vector< Node >& terms, Node body );
+ /** remove instance ids */
+ void filterInstantiations();
+ /** allocate instantiation */
+ unsigned allocateInstantiation( Node q, Node lem, std::vector< Node >& terms, Node body );
/** equality query */
EqualityQueryInstProp d_qy;
class InstInfo {
@@ -137,13 +149,13 @@ private:
std::vector< unsigned > d_update_list;
/** relevant instances */
std::map< unsigned, bool > d_relevant_inst;
+ bool d_has_relevant_inst;
private:
bool update( unsigned id, InstInfo& i, bool firstTime = false );
void propagate( Node a, Node b, bool pol, std::vector< Node >& exp );
void conflict( std::vector< Node >& exp );
bool cacheConclusion( unsigned id, Node body, int prop_index = 0 );
void addRelevantInstances( std::vector< Node >& exp, const char * c );
-
void debugPrintExplanation( std::vector< Node >& exp, const char * c );
public:
InstPropagator( QuantifiersEngine* qe );
diff --git a/src/theory/quantifiers/inst_strategy_cbqi.cpp b/src/theory/quantifiers/inst_strategy_cbqi.cpp
index 149330c61..523d868b5 100644..100755
--- a/src/theory/quantifiers/inst_strategy_cbqi.cpp
+++ b/src/theory/quantifiers/inst_strategy_cbqi.cpp
@@ -190,7 +190,7 @@ bool InstStrategyCbqi::hasNonCbqiOperator( Node n, std::map< Node, bool >& visit
bool InstStrategyCbqi::hasNonCbqiVariable( Node q ){
for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
TypeNode tn = q[0][i].getType();
- if( !tn.isInteger() && !tn.isReal() && !tn.isBoolean() ){
+ if( !tn.isInteger() && !tn.isReal() && !tn.isBoolean() && !tn.isBitVector() ){
if( options::cbqiSplx() ){
return true;
}else{
@@ -242,7 +242,7 @@ Node InstStrategyCbqi::getNextDecisionRequest(){
Node cel = d_quantEngine->getTermDatabase()->getCounterexampleLiteral( q );
bool value;
if( !d_quantEngine->getValuation().hasSatValue( cel, value ) ){
- Trace("cbqi-debug2") << "CBQI: get next decision " << cel << std::endl;
+ Trace("cbqi-dec") << "CBQI: get next decision " << cel << std::endl;
return cel;
}
}
@@ -692,8 +692,10 @@ CegInstantiator * InstStrategyCegqi::getInstantiator( Node q ) {
void InstStrategyCegqi::registerQuantifier( Node q ) {
if( options::cbqiPreRegInst() ){
- //just get the instantiator
- getInstantiator( q );
+ if( doCbqi( q ) ){
+ //just get the instantiator
+ getInstantiator( q );
+ }
}
}
diff --git a/src/theory/quantifiers/inst_strategy_cbqi.h b/src/theory/quantifiers/inst_strategy_cbqi.h
index 8ed59778b..8ed59778b 100644..100755
--- a/src/theory/quantifiers/inst_strategy_cbqi.h
+++ b/src/theory/quantifiers/inst_strategy_cbqi.h
diff --git a/src/theory/quantifiers/inst_strategy_e_matching.cpp b/src/theory/quantifiers/inst_strategy_e_matching.cpp
index 630880690..efd765c86 100644..100755
--- a/src/theory/quantifiers/inst_strategy_e_matching.cpp
+++ b/src/theory/quantifiers/inst_strategy_e_matching.cpp
@@ -34,9 +34,10 @@ using namespace CVC4::theory::quantifiers;
struct sortQuantifiersForSymbol {
QuantifiersEngine* d_qe;
+ std::map< Node, Node > d_op_map;
bool operator() (Node i, Node j) {
- int nqfsi = d_qe->getQuantifierRelevance()->getNumQuantifiersForSymbol( i.getOperator() );
- int nqfsj = d_qe->getQuantifierRelevance()->getNumQuantifiersForSymbol( j.getOperator() );
+ int nqfsi = d_qe->getQuantifierRelevance()->getNumQuantifiersForSymbol( d_op_map[i] );
+ int nqfsj = d_qe->getQuantifierRelevance()->getNumQuantifiersForSymbol( d_op_map[j] );
if( nqfsi<nqfsj ){
return true;
}else if( nqfsi>nqfsj ){
@@ -83,9 +84,8 @@ int InstStrategyUserPatterns::process( Node f, Theory::Effort effort, int e ){
Trace("inst-alg") << "-> User-provided instantiate " << f << "..." << std::endl;
if( d_quantEngine->getInstUserPatMode()==USER_PAT_MODE_RESORT ){
- int matchOption = 0;
for( unsigned i=0; i<d_user_gen_wait[f].size(); i++ ){
- Trigger * t = Trigger::mkTrigger( d_quantEngine, f, d_user_gen_wait[f][i], matchOption, true, Trigger::TR_RETURN_NULL );
+ Trigger * t = Trigger::mkTrigger( d_quantEngine, f, d_user_gen_wait[f][i], true, Trigger::TR_RETURN_NULL );
if( t ){
d_user_gen[f].push_back( t );
}
@@ -134,11 +134,10 @@ void InstStrategyUserPatterns::addUserPattern( Node q, Node pat ){
if( usable ){
Trace("user-pat") << "Add user pattern: " << pat << " for " << q << std::endl;
//check match option
- int matchOption = 0;
if( d_quantEngine->getInstUserPatMode()==USER_PAT_MODE_RESORT ){
d_user_gen_wait[q].push_back( nodes );
}else{
- Trigger * t = Trigger::mkTrigger( d_quantEngine, q, nodes, matchOption, true, Trigger::TR_MAKE_NEW );
+ Trigger * t = Trigger::mkTrigger( d_quantEngine, q, nodes, true, Trigger::TR_MAKE_NEW );
if( t ){
d_user_gen[q].push_back( t );
}else{
@@ -279,8 +278,8 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
Trace("auto-gen-trigger-debug") << "Collected pat terms for " << bd << ", no-patterns : " << d_user_no_gen[f].size() << std::endl;
for( unsigned i=0; i<patTermsF.size(); i++ ){
Assert( tinfo.find( patTermsF[i] )!=tinfo.end() );
- Trace("auto-gen-trigger-debug") << " " << patTermsF[i];
- Trace("auto-gen-trigger-debug") << " info[" << tinfo[patTermsF[i]].d_reqPol << ", " << tinfo[patTermsF[i]].d_reqPolEq << ", " << tinfo[patTermsF[i]].d_fv.size() << "]" << std::endl;
+ Trace("auto-gen-trigger-debug") << " " << patTermsF[i] << std::endl;
+ Trace("auto-gen-trigger-debug2") << " info = [" << tinfo[patTermsF[i]].d_reqPol << ", " << tinfo[patTermsF[i]].d_reqPolEq << ", " << tinfo[patTermsF[i]].d_fv.size() << "]" << std::endl;
}
Trace("auto-gen-trigger-debug") << std::endl;
}
@@ -306,10 +305,28 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
last_weight = curr_w;
}
}
+ d_num_trigger_vars[f] = vcMap.size();
+ if( d_num_trigger_vars[f]>0 && d_num_trigger_vars[f]<f[0].getNumChildren() ){
+ Trace("auto-gen-trigger-partial") << "Quantified formula : " << f << std::endl;
+ Trace("auto-gen-trigger-partial") << "...does not contain all variables in triggers!!!" << std::endl;
+ if( options::partialTriggers() ){
+ std::vector< Node > vcs[2];
+ for( unsigned i=0; i<f[0].getNumChildren(); i++ ){
+ Node ic = d_quantEngine->getTermDatabase()->getInstantiationConstant( f, i );
+ vcs[ vcMap.find( ic )==vcMap.end() ? 0 : 1 ].push_back( f[0][i] );
+ }
+ for( unsigned i=0; i<2; i++ ){
+ d_vc_partition[i][f] = NodeManager::currentNM()->mkNode( BOUND_VAR_LIST, vcs[i] );
+ }
+ }else{
+ return;
+ }
+ }
for( unsigned i=0; i<patTermsF.size(); i++ ){
Node pat = patTermsF[i];
if( rmPatTermsF.find( pat )==rmPatTermsF.end() ){
Trace("auto-gen-trigger-debug") << "...processing pattern " << pat << std::endl;
+ Node mpat = pat;
//process the pattern: if it has a required polarity, consider it
Assert( tinfo.find( pat )!=tinfo.end() );
int rpol = tinfo[pat].d_reqPol;
@@ -317,19 +334,30 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
unsigned num_fv = tinfo[pat].d_fv.size();
Trace("auto-gen-trigger-debug") << "...required polarity for " << pat << " is " << rpol << ", eq=" << rpoleq << std::endl;
if( rpol!=0 ){
+ Assert( rpol==1 || rpol==-1 );
if( Trigger::isRelationalTrigger( pat ) ){
pat = rpol==-1 ? pat.negate() : pat;
}else{
Assert( Trigger::isAtomicTrigger( pat ) );
if( pat.getType().isBoolean() && rpoleq.isNull() ){
- pat = NodeManager::currentNM()->mkNode( IFF, pat, NodeManager::currentNM()->mkConst( rpol==-1 ) ).negate();
+ if( options::literalMatchMode()==LITERAL_MATCH_USE ){
+ pat = NodeManager::currentNM()->mkNode( IFF, pat, NodeManager::currentNM()->mkConst( rpol==-1 ) ).negate();
+ }else if( options::literalMatchMode()!=LITERAL_MATCH_NONE ){
+ pat = NodeManager::currentNM()->mkNode( IFF, pat, NodeManager::currentNM()->mkConst( rpol==1 ) );
+ }
}else{
Assert( !rpoleq.isNull() );
if( rpol==-1 ){
- //all equivalence classes except rpoleq
- pat = NodeManager::currentNM()->mkNode( EQUAL, pat, rpoleq ).negate();
+ if( options::literalMatchMode()!=LITERAL_MATCH_NONE ){
+ //all equivalence classes except rpoleq
+ pat = NodeManager::currentNM()->mkNode( EQUAL, pat, rpoleq ).negate();
+ }
}else if( rpol==1 ){
- //all equivalence classes that are not disequal to rpoleq TODO
+ if( options::literalMatchMode()==LITERAL_MATCH_AGG ){
+ //only equivalence class rpoleq
+ pat = NodeManager::currentNM()->mkNode( EQUAL, pat, rpoleq );
+ }
+ //all equivalence classes that are not disequal to rpoleq TODO?
}
}
}
@@ -337,10 +365,10 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
}else{
if( Trigger::isRelationalTrigger( pat ) ){
//consider both polarities
- addPatternToPool( f, pat.negate(), num_fv );
+ addPatternToPool( f, pat.negate(), num_fv, mpat );
}
}
- addPatternToPool( f, pat, num_fv );
+ addPatternToPool( f, pat, num_fv, mpat );
}
}
//tinfo not used below this point
@@ -372,19 +400,23 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
if( options::relevantTriggers() ){
sortQuantifiersForSymbol sqfs;
sqfs.d_qe = d_quantEngine;
+ for( unsigned i=0; i<patTerms.size(); i++ ){
+ Assert( d_pat_to_mpat.find( patTerms[i] )!=d_pat_to_mpat.end() );
+ Assert( d_pat_to_mpat[patTerms[i]].hasOperator() );
+ sqfs.d_op_map[ patTerms[i] ] = d_pat_to_mpat[patTerms[i]].getOperator();
+ }
//sort based on # occurrences (this will cause Trigger to select rarer symbols)
std::sort( patTerms.begin(), patTerms.end(), sqfs );
Debug("relevant-trigger") << "Terms based on relevance: " << std::endl;
for( unsigned i=0; i<patTerms.size(); i++ ){
- Debug("relevant-trigger") << " " << patTerms[i] << " (";
- Debug("relevant-trigger") << d_quantEngine->getQuantifierRelevance()->getNumQuantifiersForSymbol( patTerms[i].getOperator() ) << ")" << std::endl;
+ Debug("relevant-trigger") << " " << patTerms[i] << " from " << d_pat_to_mpat[patTerms[i]] << " (";
+ Debug("relevant-trigger") << d_quantEngine->getQuantifierRelevance()->getNumQuantifiersForSymbol( d_pat_to_mpat[patTerms[i]].getOperator() ) << ")" << std::endl;
}
}
//now, generate the trigger...
- int matchOption = 0;
Trigger* tr = NULL;
if( d_is_single_trigger[ patTerms[0] ] ){
- tr = Trigger::mkTrigger( d_quantEngine, f, patTerms[0], matchOption, false, Trigger::TR_RETURN_NULL );
+ tr = Trigger::mkTrigger( d_quantEngine, f, patTerms[0], false, Trigger::TR_RETURN_NULL, d_num_trigger_vars[f] );
d_single_trigger_gen[ patTerms[0] ] = true;
}else{
//only generate multi trigger if option set, or if no single triggers exist
@@ -402,29 +434,14 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
d_made_multi_trigger[f] = true;
}
//will possibly want to get an old trigger
- tr = Trigger::mkTrigger( d_quantEngine, f, patTerms, matchOption, false, Trigger::TR_GET_OLD );
+ tr = Trigger::mkTrigger( d_quantEngine, f, patTerms, false, Trigger::TR_GET_OLD, d_num_trigger_vars[f] );
}
if( tr ){
- unsigned tindex;
- if( tr->isMultiTrigger() ){
- //disable all other multi triggers
- for( std::map< Trigger*, bool >::iterator it = d_auto_gen_trigger[1][f].begin(); it != d_auto_gen_trigger[1][f].end(); ++it ){
- d_auto_gen_trigger[1][f][ it->first ] = false;
- }
- tindex = 1;
- }else{
- tindex = 0;
- }
- //making it during an instantiation round, so must reset
- if( d_auto_gen_trigger[tindex][f].find( tr )==d_auto_gen_trigger[tindex][f].end() ){
- tr->resetInstantiationRound();
- tr->reset( Node::null() );
- }
- d_auto_gen_trigger[tindex][f][tr] = true;
+ addTrigger( tr, f );
//if we are generating additional triggers...
- if( tindex==0 ){
- int index = 0;
- if( index<(int)patTerms.size() ){
+ if( !tr->isMultiTrigger() ){
+ unsigned index = 0;
+ if( index<patTerms.size() ){
//Notice() << "check add additional" << std::endl;
//check if similar patterns exist, and if so, add them additionally
int nqfs_curr = 0;
@@ -433,18 +450,13 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
}
index++;
bool success = true;
- while( success && index<(int)patTerms.size() && d_is_single_trigger[ patTerms[index] ] ){
+ while( success && index<patTerms.size() && d_is_single_trigger[ patTerms[index] ] ){
success = false;
if( !options::relevantTriggers() ||
d_quantEngine->getQuantifierRelevance()->getNumQuantifiersForSymbol( patTerms[index].getOperator() )<=nqfs_curr ){
d_single_trigger_gen[ patTerms[index] ] = true;
- Trigger* tr2 = Trigger::mkTrigger( d_quantEngine, f, patTerms[index], matchOption, false, Trigger::TR_RETURN_NULL );
- if( tr2 ){
- //Notice() << "Add additional trigger " << patTerms[index] << std::endl;
- tr2->resetInstantiationRound();
- tr2->reset( Node::null() );
- d_auto_gen_trigger[0][f][tr2] = true;
- }
+ Trigger* tr2 = Trigger::mkTrigger( d_quantEngine, f, patTerms[index], false, Trigger::TR_RETURN_NULL, d_num_trigger_vars[f] );
+ addTrigger( tr2, f );
success = true;
}
index++;
@@ -457,8 +469,10 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
}
}
-void InstStrategyAutoGenTriggers::addPatternToPool( Node q, Node pat, unsigned num_fv ) {
- if( num_fv==q[0].getNumChildren() && ( options::pureThTriggers() || !Trigger::isPureTheoryTrigger( pat ) ) ){
+void InstStrategyAutoGenTriggers::addPatternToPool( Node q, Node pat, unsigned num_fv, Node mpat ) {
+ d_pat_to_mpat[pat] = mpat;
+ unsigned num_vars = options::partialTriggers() ? d_num_trigger_vars[q] : q[0].getNumChildren();
+ if( num_fv==num_vars && ( options::pureThTriggers() || !Trigger::isPureTheoryTrigger( pat ) ) ){
d_patTerms[0][q].push_back( pat );
d_is_single_trigger[ pat ] = true;
}else{
@@ -467,6 +481,38 @@ void InstStrategyAutoGenTriggers::addPatternToPool( Node q, Node pat, unsigned n
}
}
+
+void InstStrategyAutoGenTriggers::addTrigger( inst::Trigger * tr, Node q ) {
+ if( tr ){
+ if( d_num_trigger_vars[q]<q[0].getNumChildren() ){
+ //partial trigger : generate implication to mark user pattern
+ Node ipl = NodeManager::currentNM()->mkNode( INST_PATTERN_LIST, d_quantEngine->getTermDatabase()->getVariableNode( tr->getInstPattern(), q ) );
+ Node qq = NodeManager::currentNM()->mkNode( FORALL, d_vc_partition[1][q], NodeManager::currentNM()->mkNode( FORALL, d_vc_partition[0][q], q[1] ), ipl );
+ Trace("auto-gen-trigger-partial") << "Make partially specified user pattern: " << std::endl;
+ Trace("auto-gen-trigger-partial") << " " << qq << std::endl;
+ Node lem = NodeManager::currentNM()->mkNode( OR, q.negate(), qq );
+ d_quantEngine->addLemma( lem );
+ }else{
+ unsigned tindex;
+ if( tr->isMultiTrigger() ){
+ //disable all other multi triggers
+ for( std::map< Trigger*, bool >::iterator it = d_auto_gen_trigger[1][q].begin(); it != d_auto_gen_trigger[1][q].end(); ++it ){
+ d_auto_gen_trigger[1][q][ it->first ] = false;
+ }
+ tindex = 1;
+ }else{
+ tindex = 0;
+ }
+ //making it during an instantiation round, so must reset
+ if( d_auto_gen_trigger[tindex][q].find( tr )==d_auto_gen_trigger[tindex][q].end() ){
+ tr->resetInstantiationRound();
+ tr->reset( Node::null() );
+ }
+ d_auto_gen_trigger[tindex][q][tr] = true;
+ }
+ }
+}
+
bool InstStrategyAutoGenTriggers::hasUserPatterns( Node q ) {
if( q.getNumChildren()==3 ){
std::map< Node, bool >::iterator it = d_hasUserPatterns.find( q );
@@ -519,8 +565,7 @@ bool InstStrategyLocalTheoryExt::isLocalTheoryExt( Node f ) {
Trace("local-t-ext") << " " << patTerms[i] << std::endl;
}
Trace("local-t-ext") << std::endl;
- int matchOption = 0;
- Trigger * tr = Trigger::mkTrigger( d_quantEngine, f, patTerms, matchOption, true, Trigger::TR_GET_OLD );
+ Trigger * tr = Trigger::mkTrigger( d_quantEngine, f, patTerms, true, Trigger::TR_GET_OLD );
d_lte_trigger[f] = tr;
}else{
Trace("local-t-ext") << "No local theory extensions trigger for " << f << "." << std::endl;
diff --git a/src/theory/quantifiers/inst_strategy_e_matching.h b/src/theory/quantifiers/inst_strategy_e_matching.h
index 028f24b27..e6d993294 100644..100755
--- a/src/theory/quantifiers/inst_strategy_e_matching.h
+++ b/src/theory/quantifiers/inst_strategy_e_matching.h
@@ -83,14 +83,18 @@ private:
std::map< Node, std::map< inst::Trigger*, bool > > d_processed_trigger;
//instantiation no patterns
std::map< Node, std::vector< Node > > d_user_no_gen;
+ // number of trigger variables per quantifier
+ std::map< Node, unsigned > d_num_trigger_vars;
+ std::map< Node, Node > d_vc_partition[2];
+ std::map< Node, Node > d_pat_to_mpat;
private:
/** process functions */
void processResetInstantiationRound( Theory::Effort effort );
int process( Node q, Theory::Effort effort, int e );
/** generate triggers */
void generateTriggers( Node q );
- void addPatternToPool( Node q, Node pat, unsigned num_fv );
- //bool addTrigger( inst::Trigger * tr, Node f, unsigned r );
+ void addPatternToPool( Node q, Node pat, unsigned num_fv, Node mpat );
+ void addTrigger( inst::Trigger * tr, Node f );
/** has user patterns */
bool hasUserPatterns( Node q );
/** has user patterns */
diff --git a/src/theory/quantifiers/instantiation_engine.cpp b/src/theory/quantifiers/instantiation_engine.cpp
index 955dc5d86..db597d031 100644..100755
--- a/src/theory/quantifiers/instantiation_engine.cpp
+++ b/src/theory/quantifiers/instantiation_engine.cpp
@@ -137,11 +137,7 @@ void InstantiationEngine::check( Theory::Effort e, unsigned quant_e ){
doInstantiationRound( e );
if( d_quantEngine->inConflict() ){
Assert( d_quantEngine->getNumLemmasWaiting()>lastWaiting );
- Trace("inst-engine") << "Conflict = " << d_quantEngine->getNumLemmasWaiting() << " / " << d_quantEngine->getNumLemmasAddedThisRound();
- if( lastWaiting>0 ){
- Trace("inst-engine") << " (prev " << lastWaiting << ")";
- }
- Trace("inst-engine") << std::endl;
+ Trace("inst-engine") << "Conflict, added lemmas = " << (d_quantEngine->getNumLemmasWaiting()-lastWaiting) << std::endl;
}else if( d_quantEngine->hasAddedLemma() ){
Trace("inst-engine") << "Added lemmas = " << (d_quantEngine->getNumLemmasWaiting()-lastWaiting) << std::endl;
}
diff --git a/src/theory/quantifiers/instantiation_engine.h b/src/theory/quantifiers/instantiation_engine.h
index d2b3740a1..d2b3740a1 100644..100755
--- a/src/theory/quantifiers/instantiation_engine.h
+++ b/src/theory/quantifiers/instantiation_engine.h
diff --git a/src/theory/quantifiers/kinds b/src/theory/quantifiers/kinds
index b03c4ad3b..b03c4ad3b 100644..100755
--- a/src/theory/quantifiers/kinds
+++ b/src/theory/quantifiers/kinds
diff --git a/src/theory/quantifiers/local_theory_ext.cpp b/src/theory/quantifiers/local_theory_ext.cpp
index ada28c084..ada28c084 100644..100755
--- a/src/theory/quantifiers/local_theory_ext.cpp
+++ b/src/theory/quantifiers/local_theory_ext.cpp
diff --git a/src/theory/quantifiers/local_theory_ext.h b/src/theory/quantifiers/local_theory_ext.h
index 94abf3c90..94abf3c90 100644..100755
--- a/src/theory/quantifiers/local_theory_ext.h
+++ b/src/theory/quantifiers/local_theory_ext.h
diff --git a/src/theory/quantifiers/macros.cpp b/src/theory/quantifiers/macros.cpp
index 582599680..582599680 100644..100755
--- a/src/theory/quantifiers/macros.cpp
+++ b/src/theory/quantifiers/macros.cpp
diff --git a/src/theory/quantifiers/macros.h b/src/theory/quantifiers/macros.h
index 39ec2f0a1..39ec2f0a1 100644..100755
--- a/src/theory/quantifiers/macros.h
+++ b/src/theory/quantifiers/macros.h
diff --git a/src/theory/quantifiers/model_builder.cpp b/src/theory/quantifiers/model_builder.cpp
index 3ae36b1d4..10a5ae41b 100644..100755
--- a/src/theory/quantifiers/model_builder.cpp
+++ b/src/theory/quantifiers/model_builder.cpp
@@ -66,7 +66,7 @@ void QModelBuilder::debugModel( FirstOrderModel* fm ){
tests++;
std::vector< Node > terms;
for( int k=0; k<riter.getNumTerms(); k++ ){
- terms.push_back( riter.getTerm( k ) );
+ terms.push_back( riter.getCurrentTerm( k ) );
}
Node n = d_qe->getInstantiation( f, vars, terms );
Node val = fm->getValue( n );
@@ -84,7 +84,9 @@ void QModelBuilder::debugModel( FirstOrderModel* fm ){
}
Trace("quant-check-model") << "." << std::endl;
}else{
- Trace("quant-check-model") << "Warning: Could not test quantifier " << f << std::endl;
+ if( riter.isIncomplete() ){
+ Trace("quant-check-model") << "Warning: Could not test quantifier " << f << std::endl;
+ }
}
}
}
@@ -114,7 +116,7 @@ bool TermArgBasisTrie::addTerm2( FirstOrderModel* fm, Node n, int argIndex ){
QModelBuilderIG::QModelBuilderIG( context::Context* c, QuantifiersEngine* qe ) :
-QModelBuilder( c, qe ) {
+QModelBuilder( c, qe ), d_basisNoMatch( c ) {
}
@@ -302,7 +304,7 @@ void QModelBuilderIG::analyzeModel( FirstOrderModel* fm ){
for( size_t i=0; i<fmig->d_uf_terms[op].size(); i++ ){
Node n = fmig->d_uf_terms[op][i];
//for calculating if op is constant
- if( !n.getAttribute(NoMatchAttribute()) ){
+ if( d_qe->getTermDatabase()->isTermActive( n ) ){
Node v = fmig->getRepresentative( n );
if( i==0 ){
d_uf_prefs[op].d_const_val = v;
@@ -312,12 +314,11 @@ void QModelBuilderIG::analyzeModel( FirstOrderModel* fm ){
}
}
//for calculating terms that we don't need to consider
- if( !n.getAttribute(NoMatchAttribute()) || n.getAttribute(ModelBasisArgAttribute())!=0 ){
- if( !n.getAttribute(BasisNoMatchAttribute()) ){
+ if( d_qe->getTermDatabase()->isTermActive( n ) || n.getAttribute(ModelBasisArgAttribute())!=0 ){
+ if( d_basisNoMatch.find( n )==d_basisNoMatch.end() ){
//need to consider if it is not congruent modulo model basis
if( !tabt.addTerm( fmig, n ) ){
- BasisNoMatchAttribute bnma;
- n.setAttribute(bnma,true);
+ d_basisNoMatch[n] = true;
}
}
}
@@ -382,8 +383,8 @@ bool QModelBuilderIG::isQuantifierActive( Node f ){
}
bool QModelBuilderIG::isTermActive( Node n ){
- return !n.getAttribute(NoMatchAttribute()) || //it is not congruent to another active term
- ( n.getAttribute(ModelBasisArgAttribute())!=0 && !n.getAttribute(BasisNoMatchAttribute()) ); //or it has model basis arguments
+ return d_qe->getTermDatabase()->isTermActive( n ) || //it is not congruent to another active term
+ ( n.getAttribute(ModelBasisArgAttribute())!=0 && d_basisNoMatch.find( n )==d_basisNoMatch.end() ); //or it has model basis arguments
//and is not congruent modulo model basis
//to another active term
}
@@ -400,15 +401,19 @@ bool QModelBuilderIG::doExhaustiveInstantiation( FirstOrderModel * fm, Node f, i
Debug("inst-fmf-ei") << "Begin instantiation..." << std::endl;
while( !riter.isFinished() && ( d_addedLemmas==0 || !options::fmfOneInstPerRound() ) ){
d_triedLemmas++;
- for( int i=0; i<(int)riter.d_index.size(); i++ ){
- Trace("try") << i << " : " << riter.d_index[i] << " : " << riter.getTerm( i ) << std::endl;
+ if( Debug.isOn("inst-fmf-ei-debug") ){
+ for( int i=0; i<(int)riter.d_index.size(); i++ ){
+ Debug("inst-fmf-ei-debug") << i << " : " << riter.d_index[i] << " : " << riter.getCurrentTerm( i ) << std::endl;
+ }
}
int eval = 0;
int depIndex;
//see if instantiation is already true in current model
- Debug("fmf-model-eval") << "Evaluating ";
- riter.debugPrintSmall("fmf-model-eval");
- Debug("fmf-model-eval") << "Done calculating terms." << std::endl;
+ if( Debug.isOn("fmf-model-eval") ){
+ Debug("fmf-model-eval") << "Evaluating ";
+ riter.debugPrintSmall("fmf-model-eval");
+ Debug("fmf-model-eval") << "Done calculating terms." << std::endl;
+ }
//if evaluate(...)==1, then the instantiation is already true in the model
// depIndex is the index of the least significant variable that this evaluation relies upon
depIndex = riter.getNumTerms()-1;
@@ -426,7 +431,7 @@ bool QModelBuilderIG::doExhaustiveInstantiation( FirstOrderModel * fm, Node f, i
//instantiation was not shown to be true, construct the match
InstMatch m( f );
for( int i=0; i<riter.getNumTerms(); i++ ){
- m.set( d_qe, riter.d_index_order[i], riter.getTerm( i ) );
+ m.set( d_qe, i, riter.getCurrentTerm( i ) );
}
Debug("fmf-model-eval") << "* Add instantiation " << m << std::endl;
//add as instantiation
@@ -464,8 +469,8 @@ bool QModelBuilderIG::doExhaustiveInstantiation( FirstOrderModel * fm, Node f, i
Trace("model-engine-warn") << std::endl;
}
}
- //if the iterator is incomplete, we will return unknown instead of sat if no instantiations are added this round
- d_incomplete_check = riter.d_incomplete;
+ //if the iterator is incomplete, we will return unknown instead of sat if no instantiations are added this round
+ d_incomplete_check = riter.isIncomplete();
return true;
}else{
return false;
@@ -667,7 +672,7 @@ int QModelBuilderDefault::doInstGen( FirstOrderModel* fm, Node f ){
//if applicable, try to add exceptions here
if( !tr_terms.empty() ){
//make a trigger for these terms, add instantiations
- inst::Trigger* tr = inst::Trigger::mkTrigger( d_qe, f, tr_terms, 0, true, inst::Trigger::TR_MAKE_NEW );
+ inst::Trigger* tr = inst::Trigger::mkTrigger( d_qe, f, tr_terms, true, inst::Trigger::TR_MAKE_NEW );
//Notice() << "Trigger = " << (*tr) << std::endl;
tr->resetInstantiationRound();
tr->reset( Node::null() );
diff --git a/src/theory/quantifiers/model_builder.h b/src/theory/quantifiers/model_builder.h
index 906673903..e4f9529a8 100644..100755
--- a/src/theory/quantifiers/model_builder.h
+++ b/src/theory/quantifiers/model_builder.h
@@ -57,15 +57,6 @@ public:
-/** Attribute true for nodes that should not be used when considered for inst-gen basis */
-struct BasisNoMatchAttributeId {};
-/** use the special for boolean flag */
-typedef expr::Attribute< BasisNoMatchAttributeId,
- bool,
- expr::attr::NullCleanupStrategy,
- true // context dependent
- > BasisNoMatchAttribute;
-
class TermArgBasisTrie {
private:
bool addTerm2( FirstOrderModel* fm, Node n, int argIndex );
@@ -85,7 +76,9 @@ public:
*/
class QModelBuilderIG : public QModelBuilder
{
+ typedef context::CDHashMap<Node, bool, NodeHashFunction> BoolMap;
protected:
+ BoolMap d_basisNoMatch;
//map from operators to model preference data
std::map< Node, uf::UfModelPreferenceData > d_uf_prefs;
//built model uf
diff --git a/src/theory/quantifiers/model_engine.cpp b/src/theory/quantifiers/model_engine.cpp
index 0bbca88eb..5d575969f 100644..100755
--- a/src/theory/quantifiers/model_engine.cpp
+++ b/src/theory/quantifiers/model_engine.cpp
@@ -153,27 +153,23 @@ int ModelEngine::checkModel(){
//d_quantEngine->getEqualityQuery()->flattenRepresentatives( fm->d_rep_set.d_type_reps );
//for debugging
- if( Trace.isOn("model-engine") || Trace.isOn("model-engine-debug") ){
- for( std::map< TypeNode, std::vector< Node > >::iterator it = fm->d_rep_set.d_type_reps.begin();
- it != fm->d_rep_set.d_type_reps.end(); ++it ){
- if( it->first.isSort() ){
- Trace("model-engine") << "Cardinality( " << it->first << " )" << " = " << it->second.size() << std::endl;
- if( Trace.isOn("model-engine-debug") ){
- Trace("model-engine-debug") << " Reps : ";
- for( size_t i=0; i<it->second.size(); i++ ){
- Trace("model-engine-debug") << it->second[i] << " ";
- }
- Trace("model-engine-debug") << std::endl;
- Trace("model-engine-debug") << " Term reps : ";
- for( size_t i=0; i<it->second.size(); i++ ){
- Node r = d_quantEngine->getEqualityQuery()->getInternalRepresentative( it->second[i], Node::null(), 0 );
- Trace("model-engine-debug") << r << " ";
- }
- Trace("model-engine-debug") << std::endl;
- Node mbt = d_quantEngine->getTermDatabase()->getModelBasisTerm(it->first);
- Trace("model-engine-debug") << " Basis term : " << mbt << std::endl;
- }
+ for( std::map< TypeNode, std::vector< Node > >::iterator it = fm->d_rep_set.d_type_reps.begin();
+ it != fm->d_rep_set.d_type_reps.end(); ++it ){
+ if( it->first.isSort() ){
+ Trace("model-engine") << "Cardinality( " << it->first << " )" << " = " << it->second.size() << std::endl;
+ Trace("model-engine-debug") << " Reps : ";
+ for( size_t i=0; i<it->second.size(); i++ ){
+ Trace("model-engine-debug") << it->second[i] << " ";
}
+ Trace("model-engine-debug") << std::endl;
+ Trace("model-engine-debug") << " Term reps : ";
+ for( size_t i=0; i<it->second.size(); i++ ){
+ Node r = d_quantEngine->getEqualityQuery()->getInternalRepresentative( it->second[i], Node::null(), 0 );
+ Trace("model-engine-debug") << r << " ";
+ }
+ Trace("model-engine-debug") << std::endl;
+ Node mbt = d_quantEngine->getTermDatabase()->getModelBasisTerm(it->first);
+ Trace("model-engine-debug") << " Basis term : " << mbt << std::endl;
}
}
@@ -221,11 +217,12 @@ int ModelEngine::checkModel(){
//print debug information
if( d_quantEngine->inConflict() ){
- Trace("model-engine") << "Conflict = " << d_quantEngine->getNumLemmasWaiting() << " / " << d_quantEngine->getNumLemmasAddedThisRound() << std::endl;
+ Trace("model-engine") << "Conflict, added lemmas = ";
}else{
- Trace("model-engine") << "Added Lemmas = " << d_addedLemmas << " / " << d_triedLemmas << " / ";
- Trace("model-engine") << d_totalLemmas << std::endl;
- }
+ Trace("model-engine") << "Added Lemmas = ";
+ }
+ Trace("model-engine") << d_addedLemmas << " / " << d_triedLemmas << " / ";
+ Trace("model-engine") << d_totalLemmas << std::endl;
return d_addedLemmas;
}
@@ -281,15 +278,15 @@ void ModelEngine::exhaustiveInstantiate( Node f, int effort ){
//create a rep set iterator and iterate over the (relevant) domain of the quantifier
RepSetIterator riter( d_quantEngine, &(d_quantEngine->getModel()->d_rep_set) );
if( riter.setQuantifier( f ) ){
- Trace("fmf-exh-inst") << "...exhaustive instantiation set, incomplete=" << riter.d_incomplete << "..." << std::endl;
- if( !riter.d_incomplete ){
+ Trace("fmf-exh-inst") << "...exhaustive instantiation set, incomplete=" << riter.isIncomplete() << "..." << std::endl;
+ if( !riter.isIncomplete() ){
int triedLemmas = 0;
int addedLemmas = 0;
while( !riter.isFinished() && ( addedLemmas==0 || !options::fmfOneInstPerRound() ) ){
//instantiation was not shown to be true, construct the match
InstMatch m( f );
for( int i=0; i<riter.getNumTerms(); i++ ){
- m.set( d_quantEngine, riter.d_index_order[i], riter.getTerm( i ) );
+ m.set( d_quantEngine, i, riter.getCurrentTerm( i ) );
}
Debug("fmf-model-eval") << "* Add instantiation " << m << std::endl;
triedLemmas++;
@@ -309,11 +306,10 @@ void ModelEngine::exhaustiveInstantiate( Node f, int effort ){
d_statistics.d_exh_inst_lemmas += addedLemmas;
}
}else{
- Trace("fmf-exh-inst") << "...exhaustive instantiation failed to set, incomplete=" << riter.d_incomplete << "..." << std::endl;
- Assert( riter.d_incomplete );
+ Trace("fmf-exh-inst") << "...exhaustive instantiation did set, incomplete=" << riter.isIncomplete() << "..." << std::endl;
}
//if the iterator is incomplete, we will return unknown instead of sat if no instantiations are added this round
- d_incomplete_check = d_incomplete_check || riter.d_incomplete;
+ d_incomplete_check = d_incomplete_check || riter.isIncomplete();
}
}
diff --git a/src/theory/quantifiers/model_engine.h b/src/theory/quantifiers/model_engine.h
index 12f18aa08..12f18aa08 100644..100755
--- a/src/theory/quantifiers/model_engine.h
+++ b/src/theory/quantifiers/model_engine.h
diff --git a/src/theory/quantifiers/quant_conflict_find.cpp b/src/theory/quantifiers/quant_conflict_find.cpp
index ca87a607d..bac2aa35c 100644..100755
--- a/src/theory/quantifiers/quant_conflict_find.cpp
+++ b/src/theory/quantifiers/quant_conflict_find.cpp
@@ -49,6 +49,7 @@ QuantInfo::~QuantInfo() {
void QuantInfo::initialize( QuantConflictFind * p, Node q, Node qn ) {
d_q = q;
+ d_extra_var.clear();
for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
d_match.push_back( TNode::null() );
d_match_term.push_back( TNode::null() );
@@ -77,33 +78,31 @@ void QuantInfo::initialize( QuantConflictFind * p, Node q, Node qn ) {
}
}
*/
- if( d_mg->isValid() ){
- for( unsigned j=q[0].getNumChildren(); j<d_vars.size(); j++ ){
- if( d_vars[j].getKind()!=BOUND_VARIABLE ){
- d_var_mg[j] = NULL;
- bool is_tsym = false;
- if( !MatchGen::isHandledUfTerm( d_vars[j] ) && d_vars[j].getKind()!=ITE ){
- is_tsym = true;
- d_tsym_vars.push_back( j );
- }
- if( !is_tsym || options::qcfTConstraint() ){
- d_var_mg[j] = new MatchGen( this, d_vars[j], true );
- }
- if( !d_var_mg[j] || !d_var_mg[j]->isValid() ){
- Trace("qcf-invalid") << "QCF invalid : cannot match for " << d_vars[j] << std::endl;
- d_mg->setInvalid();
- break;
- }else{
- std::vector< int > bvars;
- d_var_mg[j]->determineVariableOrder( this, bvars );
- }
+ for( unsigned j=q[0].getNumChildren(); j<d_vars.size(); j++ ){
+ if( d_vars[j].getKind()!=BOUND_VARIABLE ){
+ d_var_mg[j] = NULL;
+ bool is_tsym = false;
+ if( !MatchGen::isHandledUfTerm( d_vars[j] ) && d_vars[j].getKind()!=ITE ){
+ is_tsym = true;
+ d_tsym_vars.push_back( j );
+ }
+ if( !is_tsym || options::qcfTConstraint() ){
+ d_var_mg[j] = new MatchGen( this, d_vars[j], true );
+ }
+ if( !d_var_mg[j] || !d_var_mg[j]->isValid() ){
+ Trace("qcf-invalid") << "QCF invalid : cannot match for " << d_vars[j] << std::endl;
+ d_mg->setInvalid();
+ break;
+ }else{
+ std::vector< int > bvars;
+ d_var_mg[j]->determineVariableOrder( this, bvars );
}
- }
- if( d_mg->isValid() ){
- std::vector< int > bvars;
- d_mg->determineVariableOrder( this, bvars );
}
}
+ if( d_mg->isValid() ){
+ std::vector< int > bvars;
+ d_mg->determineVariableOrder( this, bvars );
+ }
}else{
Trace("qcf-invalid") << "QCF invalid : body of formula cannot be processed." << std::endl;
}
@@ -113,14 +112,15 @@ void QuantInfo::initialize( QuantConflictFind * p, Node q, Node qn ) {
//optimization : record variable argument positions for terms that must be matched
std::vector< TNode > vars;
//TODO: revisit this, makes QCF faster, but misses conflicts due to caring about paths that may not be relevant (starExec jobs 14136/14137)
- //if( options::qcfSkipRd() ){
- // for( unsigned j=q[0].getNumChildren(); j<d_vars.size(); j++ ){
- // vars.push_back( d_vars[j] );
- // }
- //}
- //get all variables that are always relevant
- std::map< TNode, bool > visited;
- getPropagateVars( vars, q[1], false, visited );
+ if( options::qcfSkipRd() ){
+ for( unsigned j=q[0].getNumChildren(); j<d_vars.size(); j++ ){
+ vars.push_back( d_vars[j] );
+ }
+ }else{
+ //get all variables that are always relevant
+ std::map< TNode, bool > visited;
+ getPropagateVars( p, vars, q[1], false, visited );
+ }
for( unsigned j=0; j<vars.size(); j++ ){
Node v = vars[j];
TNode f = p->getTermDatabase()->getMatchOperator( v );
@@ -141,7 +141,7 @@ void QuantInfo::initialize( QuantConflictFind * p, Node q, Node qn ) {
}
}
-void QuantInfo::getPropagateVars( std::vector< TNode >& vars, TNode n, bool pol, std::map< TNode, bool >& visited ){
+void QuantInfo::getPropagateVars( QuantConflictFind * p, std::vector< TNode >& vars, TNode n, bool pol, std::map< TNode, bool >& visited ){
std::map< TNode, bool >::iterator itv = visited.find( n );
if( itv==visited.end() ){
visited[n] = true;
@@ -150,6 +150,12 @@ void QuantInfo::getPropagateVars( std::vector< TNode >& vars, TNode n, bool pol,
if( d_var_num.find( n )!=d_var_num.end() ){
Assert( std::find( vars.begin(), vars.end(), n )==vars.end() );
vars.push_back( n );
+ TNode f = p->getTermDatabase()->getMatchOperator( n );
+ if( !f.isNull() ){
+ if( std::find( p->d_func_rel_dom[f].begin(), p->d_func_rel_dom[f].end(), d_q )==p->d_func_rel_dom[f].end() ){
+ p->d_func_rel_dom[f].push_back( d_q );
+ }
+ }
}else if( MatchGen::isHandledBoolConnective( n ) ){
Assert( n.getKind()!=IMPLIES );
QuantPhaseReq::getEntailPolarity( n, 0, true, pol, rec, newPol );
@@ -157,12 +163,16 @@ void QuantInfo::getPropagateVars( std::vector< TNode >& vars, TNode n, bool pol,
Trace("qcf-opt-debug") << "getPropagateVars " << n << ", pol = " << pol << ", rec = " << rec << std::endl;
if( rec ){
for( unsigned i=0; i<n.getNumChildren(); i++ ){
- getPropagateVars( vars, n[i], pol, visited );
+ getPropagateVars( p, vars, n[i], pol, visited );
}
}
}
}
+bool QuantInfo::isBaseMatchComplete() {
+ return d_vars_set.size()==(d_q[0].getNumChildren()+d_extra_var.size());
+}
+
void QuantInfo::registerNode( Node n, bool hasPol, bool pol, bool beneathQuant ) {
Trace("qcf-qregister-debug2") << "Register : " << n << std::endl;
if( n.getKind()==FORALL ){
@@ -209,7 +219,6 @@ void QuantInfo::flatten( Node n, bool beneathQuant ) {
if( n.getKind()==BOUND_VARIABLE ){
d_inMatchConstraint[n] = true;
}
- //if( MatchGen::isHandledUfTerm( n ) || n.getKind()==ITE ){
if( d_var_num.find( n )==d_var_num.end() ){
Trace("qcf-qregister-debug2") << "Add FLATTEN VAR : " << n << std::endl;
d_var_num[n] = d_vars.size();
@@ -219,6 +228,8 @@ void QuantInfo::flatten( Node n, bool beneathQuant ) {
d_match_term.push_back( TNode::null() );
if( n.getKind()==ITE ){
registerNode( n, false, false );
+ }else if( n.getKind()==BOUND_VARIABLE ){
+ d_extra_var.push_back( n );
}else{
for( unsigned i=0; i<n.getNumChildren(); i++ ){
flatten( n[i], beneathQuant );
@@ -233,13 +244,15 @@ void QuantInfo::flatten( Node n, bool beneathQuant ) {
}
-void QuantInfo::reset_round( QuantConflictFind * p ) {
+bool QuantInfo::reset_round( QuantConflictFind * p ) {
for( unsigned i=0; i<d_match.size(); i++ ){
d_match[i] = TNode::null();
d_match_term[i] = TNode::null();
}
+ d_vars_set.clear();
d_curr_var_deq.clear();
d_tconstraints.clear();
+
//add built-in variable constraints
for( unsigned r=0; r<2; r++ ){
for( std::map< int, std::vector< Node > >::iterator it = d_var_constraint[r].begin();
@@ -257,7 +270,7 @@ void QuantInfo::reset_round( QuantConflictFind * p ) {
d_mg->d_children.clear();
d_mg->d_n = NodeManager::currentNM()->mkConst( true );
d_mg->d_type = MatchGen::typ_ground;
- return;
+ return false;
}
}
}
@@ -268,6 +281,7 @@ void QuantInfo::reset_round( QuantConflictFind * p ) {
}
//now, reset for matching
d_mg->reset( p, false, this );
+ return true;
}
int QuantInfo::getCurrentRepVar( int v ) {
@@ -377,11 +391,12 @@ int QuantInfo::addConstraint( QuantConflictFind * p, int v, TNode n, int vn, boo
}
}
}
- d_match[v] = TNode::null();
+ unsetMatch( p, v );
return 1;
}else{
//std::map< int, TNode >::iterator itm = d_match.find( v );
bool isGroundRep = false;
+ bool isGround = false;
if( vn!=-1 ){
Debug("qcf-match-debug") << " ...Variable bound to variable" << std::endl;
//std::map< int, TNode >::iterator itmn = d_match.find( vn );
@@ -428,13 +443,14 @@ int QuantInfo::addConstraint( QuantConflictFind * p, int v, TNode n, int vn, boo
Debug("qcf-match-debug") << " ...Variable bound to ground" << std::endl;
if( d_match[v].isNull() ){
//isGroundRep = true; ??
+ isGround = true;
}else{
//compare ground values
Debug("qcf-match-debug") << " -> Ground value, compare " << d_match[v] << " "<< n << std::endl;
return p->areMatchEqual( d_match[v], n ) ? 0 : -1;
}
}
- if( setMatch( p, v, n, isGroundRep ) ){
+ if( setMatch( p, v, n, isGroundRep, isGround ) ){
Debug("qcf-match-debug") << " -> success" << std::endl;
return 1;
}else{
@@ -500,7 +516,7 @@ bool QuantInfo::isConstrainedVar( int v ) {
}
}
-bool QuantInfo::setMatch( QuantConflictFind * p, int v, TNode n, bool isGroundRep ) {
+bool QuantInfo::setMatch( QuantConflictFind * p, int v, TNode n, bool isGroundRep, bool isGround ) {
if( getCurrentCanBeEqual( p, v, n ) ){
if( isGroundRep ){
//fail if n does not exist in the relevant domain of each of the argument positions
@@ -518,6 +534,12 @@ bool QuantInfo::setMatch( QuantConflictFind * p, int v, TNode n, bool isGroundRe
}
}
Debug("qcf-match-debug") << "-- bind : " << v << " -> " << n << ", checked " << d_curr_var_deq[v].size() << " disequalities" << std::endl;
+ if( isGround ){
+ if( d_vars[v].getKind()==BOUND_VARIABLE ){
+ d_vars_set[v] = true;
+ Debug("qcf-match-debug") << "---- now bound " << d_vars_set.size() << " / " << d_q[0].getNumChildren() << " base variables." << std::endl;
+ }
+ }
d_match[v] = n;
return true;
}else{
@@ -525,6 +547,14 @@ bool QuantInfo::setMatch( QuantConflictFind * p, int v, TNode n, bool isGroundRe
}
}
+void QuantInfo::unsetMatch( QuantConflictFind * p, int v ) {
+ Debug("qcf-match-debug") << "-- unbind : " << v << std::endl;
+ if( d_vars[v].getKind()==BOUND_VARIABLE && d_vars_set.find( v )!=d_vars_set.end() ){
+ d_vars_set.erase( v );
+ }
+ d_match[ v ] = TNode::null();
+}
+
bool QuantInfo::isMatchSpurious( QuantConflictFind * p ) {
for( int i=0; i<getNumVars(); i++ ){
//std::map< int, TNode >::iterator it = d_match.find( i );
@@ -538,6 +568,42 @@ bool QuantInfo::isMatchSpurious( QuantConflictFind * p ) {
}
bool QuantInfo::isTConstraintSpurious( QuantConflictFind * p, std::vector< Node >& terms ) {
+ if( options::qcfEagerTest() ){
+ //check whether the instantiation evaluates as expected
+ if( p->d_effort==QuantConflictFind::effort_conflict ){
+ Trace("qcf-instance-check") << "Possible conflict instance for " << d_q << " : " << std::endl;
+ std::map< TNode, TNode > subs;
+ for( unsigned i=0; i<terms.size(); i++ ){
+ Trace("qcf-instance-check") << " " << terms[i] << std::endl;
+ subs[d_q[0][i]] = terms[i];
+ }
+ for( unsigned i=0; i<d_extra_var.size(); i++ ){
+ Node n = getCurrentExpValue( d_extra_var[i] );
+ Trace("qcf-instance-check") << " " << d_extra_var[i] << " -> " << n << std::endl;
+ subs[d_extra_var[i]] = n;
+ }
+ if( !p->getTermDatabase()->isEntailed( d_q[1], subs, false, false ) ){
+ Trace("qcf-instance-check") << "...not entailed to be false." << std::endl;
+ return true;
+ }
+ }else{
+ Node inst = p->d_quantEngine->getInstantiation( d_q, terms );
+ Node inst_eval = p->getTermDatabase()->evaluateTerm( inst, NULL, options::qcfTConstraint() );
+ if( Trace.isOn("qcf-instance-check") ){
+ Trace("qcf-instance-check") << "Possible propagating instance for " << d_q << " : " << std::endl;
+ for( unsigned i=0; i<terms.size(); i++ ){
+ Trace("qcf-instance-check") << " " << terms[i] << std::endl;
+ }
+ Trace("qcf-instance-check") << "...evaluates to " << inst_eval << std::endl;
+ }
+ if( inst_eval.isNull() || inst_eval==p->getTermDatabase()->d_true || !isPropagatingInstance( p, inst_eval ) ){
+ Trace("qcf-instance-check") << "...spurious." << std::endl;
+ return true;
+ }else{
+ Trace("qcf-instance-check") << "...not spurious." << std::endl;
+ }
+ }
+ }
if( !d_tconstraints.empty() ){
//check constraints
for( std::map< Node, bool >::iterator it = d_tconstraints.begin(); it != d_tconstraints.end(); ++it ){
@@ -552,6 +618,26 @@ bool QuantInfo::isTConstraintSpurious( QuantConflictFind * p, std::vector< Node
return false;
}
+bool QuantInfo::isPropagatingInstance( QuantConflictFind * p, Node n ) {
+ if( n.getKind()==FORALL ){
+ //TODO?
+ return true;
+ }else if( n.getKind()==NOT || n.getKind()==AND || n.getKind()==OR || n.getKind()==EQUAL || n.getKind()==ITE || n.getKind()==IFF ){
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ if( !isPropagatingInstance( p, n[i] ) ){
+ return false;
+ }
+ }
+ return true;
+ }else{
+ if( p->getEqualityEngine()->hasTerm( n ) || isGroundSubterm( n ) ){
+ return true;
+ }
+ }
+ Trace("qcf-instance-check-debug") << "...not propagating instance because of " << n << std::endl;
+ return false;
+}
+
bool QuantInfo::entailmentTest( QuantConflictFind * p, Node lit, bool chEnt ) {
Trace("qcf-tconstraint-debug") << "Check : " << lit << std::endl;
Node rew = Rewriter::rewrite( lit );
@@ -606,6 +692,9 @@ bool QuantInfo::completeMatch( QuantConflictFind * p, std::vector< int >& assign
doFail = true;
success = false;
}else{
+ if( isBaseMatchComplete() && options::qcfEagerTest() ){
+ return true;
+ }
//solve for interpreted symbol matches
// this breaks the invariant that all introduced constraints are over existing terms
for( int i=(int)(d_tsym_vars.size()-1); i>=0; i-- ){
@@ -636,7 +725,7 @@ bool QuantInfo::completeMatch( QuantConflictFind * p, std::vector< int >& assign
if( !z.isNull() ){
Trace("qcf-tconstraint-debug") << "...set " << d_vars[vn] << " = " << z << std::endl;
assigned.push_back( vn );
- if( !setMatch( p, vn, z, false ) ){
+ if( !setMatch( p, vn, z, false, true ) ){
success = false;
break;
}
@@ -678,7 +767,7 @@ bool QuantInfo::completeMatch( QuantConflictFind * p, std::vector< int >& assign
if( !sum.isNull() ){
assigned.push_back( slv_v );
Trace("qcf-tconstraint-debug") << "...set " << d_vars[slv_v] << " = " << sum << std::endl;
- if( !setMatch( p, slv_v, sum, false ) ){
+ if( !setMatch( p, slv_v, sum, false, true ) ){
success = false;
}
p->d_tempCache.push_back( sum );
@@ -764,7 +853,7 @@ bool QuantInfo::completeMatch( QuantConflictFind * p, std::vector< int >& assign
int currIndex = d_una_eqc_count[d_una_index];
d_una_eqc_count[d_una_index]++;
Trace("qcf-check-unassign") << d_unassigned[d_una_index] << "->" << p->d_eqcs[d_unassigned_tn[d_una_index]][currIndex] << std::endl;
- if( setMatch( p, d_unassigned[d_una_index], p->d_eqcs[d_unassigned_tn[d_una_index]][currIndex], true ) ){
+ if( setMatch( p, d_unassigned[d_una_index], p->d_eqcs[d_unassigned_tn[d_una_index]][currIndex], true, true ) ){
d_match_term[d_unassigned[d_una_index]] = TNode::null();
Trace("qcf-check-unassign") << "Succeeded match " << d_una_index << std::endl;
d_una_index++;
@@ -813,9 +902,7 @@ bool QuantInfo::completeMatch( QuantConflictFind * p, std::vector< int >& assign
}
return true;
}else{
- for( unsigned i=0; i<assigned.size(); i++ ){
- d_match[ assigned[i] ] = TNode::null();
- }
+ revertMatch( p, assigned );
assigned.clear();
return false;
}
@@ -837,9 +924,9 @@ void QuantInfo::getMatch( std::vector< Node >& terms ){
}
}
-void QuantInfo::revertMatch( std::vector< int >& assigned ) {
+void QuantInfo::revertMatch( QuantConflictFind * p, std::vector< int >& assigned ) {
for( unsigned i=0; i<assigned.size(); i++ ){
- d_match[ assigned[i] ] = TNode::null();
+ unsetMatch( p, assigned[i] );
}
}
@@ -899,26 +986,7 @@ MatchGen::MatchGen( QuantInfo * qi, Node n, bool isVar )
if( isVar ){
Assert( qi->d_var_num.find( n )!=qi->d_var_num.end() );
if( n.getKind()==ITE ){
- /*
- d_type = typ_ite_var;
- d_type_not = false;
- d_n = n;
- d_children.push_back( MatchGen( qi, d_n[0] ) );
- if( d_children[0].isValid() ){
- d_type = typ_ite_var;
- for( unsigned i=1; i<=2; i++ ){
- Node nn = n.eqNode( n[i] );
- d_children.push_back( MatchGen( qi, nn ) );
- d_children[d_children.size()-1].d_qni_bound_except.push_back( 0 );
- if( !d_children[d_children.size()-1].isValid() ){
- setInvalid();
- break;
- }
- }
- }else{
-*/
- d_type = typ_invalid;
- //}
+ d_type = typ_invalid;
}else{
d_type = isHandledUfTerm( n ) ? typ_var : typ_tsym;
d_qni_var_num[0] = qi->getVarNum( n );
@@ -961,26 +1029,6 @@ MatchGen::MatchGen( QuantInfo * qi, Node n, bool isVar )
break;
}
}
- /*
- else if( isTop && n.getKind()==OR && d_children[d_children.size()-1].d_type==typ_var_eq ){
- Trace("qcf-qregister-debug") << "Remove child, make built-in constraint" << std::endl;
- //if variable equality/disequality at top level, remove immediately
- bool cIsNot = d_children[d_children.size()-1].d_type_not;
- Node cn = d_children[d_children.size()-1].d_n;
- Assert( cn.getKind()==EQUAL );
- Assert( p->d_qinfo[q].isVar( cn[0] ) || p->d_qinfo[q].isVar( cn[1] ) );
- //make it a built-in constraint instead
- for( unsigned i=0; i<2; i++ ){
- if( p->d_qinfo[q].isVar( cn[i] ) ){
- int v = p->d_qinfo[q].getVarNum( cn[i] );
- Node cno = cn[i==0 ? 1 : 0];
- p->d_qinfo[q].d_var_constraint[ cIsNot ? 0 : 1 ][v].push_back( cno );
- break;
- }
- }
- d_children.pop_back();
- }
- */
}
}else{
d_type = typ_invalid;
@@ -1003,6 +1051,7 @@ MatchGen::MatchGen( QuantInfo * qi, Node n, bool isVar )
}
}else{
d_qni_gterm[i] = d_n[i];
+ qi->setGroundSubterm( d_n[i] );
}
}
d_type = d_n.getKind()==EQUAL ? typ_eq : typ_tconstraint;
@@ -1013,21 +1062,8 @@ MatchGen::MatchGen( QuantInfo * qi, Node n, bool isVar )
//we will just evaluate
d_n = n;
d_type = typ_ground;
+ qi->setGroundSubterm( d_n );
}
- //if( d_type!=typ_invalid ){
- //determine an efficient children ordering
- //if( !d_children.empty() ){
- //for( unsigned i=0; i<d_children.size(); i++ ){
- // d_children_order.push_back( i );
- //}
- //if( !d_n.isNull() && ( d_n.getKind()==OR || d_n.getKind()==AND || d_n.getKind()==IFF ) ){
- //sort based on the type of the constraint : ground comes first, then literals, then others
- //MatchGenSort mgs;
- //mgs.d_mg = this;
- //std::sort( d_children_order.begin(), d_children_order.end(), mgs );
- //}
- //}
- //}
}
Trace("qcf-qregister-debug") << "Done make match gen " << n << ", type = ";
debugPrintType( "qcf-qregister-debug", d_type, true );
@@ -1036,78 +1072,96 @@ MatchGen::MatchGen( QuantInfo * qi, Node n, bool isVar )
}
-void MatchGen::collectBoundVar( QuantInfo * qi, Node n, std::vector< int >& cbvars ) {
- int v = qi->getVarNum( n );
- if( v!=-1 && std::find( cbvars.begin(), cbvars.end(), v )==cbvars.end() ){
- cbvars.push_back( v );
- }
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- collectBoundVar( qi, n[i], cbvars );
+void MatchGen::collectBoundVar( QuantInfo * qi, Node n, std::vector< int >& cbvars, std::map< Node, bool >& visited, bool& hasNested ) {
+ if( visited.find( n )==visited.end() ){
+ visited[n] = true;
+ if( n.getKind()==FORALL ){
+ hasNested = true;
+ }
+ int v = qi->getVarNum( n );
+ if( v!=-1 && std::find( cbvars.begin(), cbvars.end(), v )==cbvars.end() ){
+ cbvars.push_back( v );
+ }
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ collectBoundVar( qi, n[i], cbvars, visited, hasNested );
+ }
}
}
void MatchGen::determineVariableOrder( QuantInfo * qi, std::vector< int >& bvars ) {
- Trace("qcf-qregister-debug") << "Determine variable order " << d_n << std::endl;
- bool isCom = d_type==typ_formula && ( d_n.getKind()==OR || d_n.getKind()==AND || d_n.getKind()==IFF );
- std::map< int, std::vector< int > > c_to_vars;
- std::map< int, std::vector< int > > vars_to_c;
- std::map< int, int > vb_count;
- std::map< int, int > vu_count;
- std::vector< bool > assigned;
- Trace("qcf-qregister-debug") << "Calculate bound variables..." << std::endl;
- for( unsigned i=0; i<d_children.size(); i++ ){
- collectBoundVar( qi, d_children[i].d_n, c_to_vars[i] );
- assigned.push_back( false );
- vb_count[i] = 0;
- vu_count[i] = 0;
- for( unsigned j=0; j<c_to_vars[i].size(); j++ ){
- int v = c_to_vars[i][j];
- vars_to_c[v].push_back( i );
- if( std::find( bvars.begin(), bvars.end(), v )==bvars.end() ){
- vu_count[i]++;
- if( !isCom ){
- bvars.push_back( v );
+ Trace("qcf-qregister-debug") << "Determine variable order " << d_n << ", #bvars = " << bvars.size() << std::endl;
+ bool isComm = d_type==typ_formula && ( d_n.getKind()==OR || d_n.getKind()==AND || d_n.getKind()==IFF );
+ if( isComm ){
+ std::map< int, std::vector< int > > c_to_vars;
+ std::map< int, std::vector< int > > vars_to_c;
+ std::map< int, int > vb_count;
+ std::map< int, int > vu_count;
+ std::map< int, bool > has_nested;
+ std::vector< bool > assigned;
+ Trace("qcf-qregister-debug") << "Calculate bound variables..." << std::endl;
+ for( unsigned i=0; i<d_children.size(); i++ ){
+ std::map< Node, bool > visited;
+ has_nested[i] = false;
+ collectBoundVar( qi, d_children[i].d_n, c_to_vars[i], visited, has_nested[i] );
+ assigned.push_back( false );
+ vb_count[i] = 0;
+ vu_count[i] = 0;
+ for( unsigned j=0; j<c_to_vars[i].size(); j++ ){
+ int v = c_to_vars[i][j];
+ vars_to_c[v].push_back( i );
+ if( std::find( bvars.begin(), bvars.end(), v )==bvars.end() ){
+ vu_count[i]++;
+ }else{
+ vb_count[i]++;
}
- }else{
- vb_count[i]++;
}
}
- }
- if( isCom ){
- //children that bind the least number of unbound variables go first
+ //children that bind no unbound variable, then the most number of bound, unbound variables go first
+ Trace("qcf-qregister-vo") << "Variable order for " << d_n << " : " << std::endl;
do {
+ int min_score0 = -1;
int min_score = -1;
int min_score_index = -1;
for( unsigned i=0; i<d_children.size(); i++ ){
if( !assigned[i] ){
- int score = vu_count[i];
- if( min_score==-1 || score<min_score ){
+ Trace("qcf-qregister-debug2") << "Child " << i << " has b/ub : " << vb_count[i] << "/" << vu_count[i] << std::endl;
+ int score0 = 0;//has_nested[i] ? 0 : 1;
+ int score;
+ if( !options::qcfVoExp() ){
+ score = vu_count[i];
+ }else{
+ score = vu_count[i]==0 ? 0 : ( 1 + qi->d_vars.size()*( qi->d_vars.size() - vb_count[i] ) + ( qi->d_vars.size() - vu_count[i] ) );
+ }
+ if( min_score==-1 || score0<min_score0 || ( score0==min_score0 && score<min_score ) ){
+ min_score0 = score0;
min_score = score;
min_score_index = i;
}
}
}
- Trace("qcf-qregister-debug") << "...assign child " << min_score_index << "/" << d_children.size() << std::endl;
+ Trace("qcf-qregister-vo") << " " << d_children_order.size()+1 << ": " << d_children[min_score_index].d_n << " : ";
+ Trace("qcf-qregister-vo") << vu_count[min_score_index] << " " << vb_count[min_score_index] << " " << has_nested[min_score_index] << std::endl;
+ Trace("qcf-qregister-debug") << "...assign child " << min_score_index << std::endl;
+ Trace("qcf-qregister-debug") << "...score : " << min_score << std::endl;
Assert( min_score_index!=-1 );
//add to children order
d_children_order.push_back( min_score_index );
assigned[min_score_index] = true;
- //if( vb_count[min_score_index]==0 ){
- // d_independent.push_back( min_score_index );
- //}
//determine order internal to children
d_children[min_score_index].determineVariableOrder( qi, bvars );
Trace("qcf-qregister-debug") << "...bind variables" << std::endl;
//now, make it a bound variable
- for( unsigned i=0; i<c_to_vars[min_score_index].size(); i++ ){
- int v = c_to_vars[min_score_index][i];
- if( std::find( bvars.begin(), bvars.end(), v )==bvars.end() ){
- for( unsigned j=0; j<vars_to_c[v].size(); j++ ){
- int vc = vars_to_c[v][j];
- vu_count[vc]--;
- vb_count[vc]++;
+ if( vu_count[min_score_index]>0 ){
+ for( unsigned i=0; i<c_to_vars[min_score_index].size(); i++ ){
+ int v = c_to_vars[min_score_index][i];
+ if( std::find( bvars.begin(), bvars.end(), v )==bvars.end() ){
+ for( unsigned j=0; j<vars_to_c[v].size(); j++ ){
+ int vc = vars_to_c[v][j];
+ vu_count[vc]--;
+ vb_count[vc]++;
+ }
+ bvars.push_back( v );
}
- bvars.push_back( v );
}
}
Trace("qcf-qregister-debug") << "...done assign child " << min_score_index << std::endl;
@@ -1117,6 +1171,16 @@ void MatchGen::determineVariableOrder( QuantInfo * qi, std::vector< int >& bvars
for( unsigned i=0; i<d_children.size(); i++ ){
d_children_order.push_back( i );
d_children[i].determineVariableOrder( qi, bvars );
+ //now add to bvars
+ std::map< Node, bool > visited;
+ std::vector< int > cvars;
+ bool has_nested = false;
+ collectBoundVar( qi, d_children[i].d_n, cvars, visited, has_nested );
+ for( unsigned j=0; j<cvars.size(); j++ ){
+ if( std::find( bvars.begin(), bvars.end(), cvars[j] )==bvars.end() ){
+ bvars.push_back( cvars[j] );
+ }
+ }
}
}
}
@@ -1169,15 +1233,20 @@ void MatchGen::reset( QuantConflictFind * p, bool tgt, QuantInfo * qi ) {
d_qni.clear();
d_qni_bound.clear();
d_child_counter = -1;
+ d_use_children = true;
d_tgt_orig = d_tgt;
//set up processing matches
if( d_type==typ_invalid ){
- //do nothing
+ d_use_children = false;
}else if( d_type==typ_ground ){
+ d_use_children = false;
if( d_ground_eval[0]==( d_tgt ? p->d_true : p->d_false ) ){
d_child_counter = 0;
}
+ }else if( qi->isBaseMatchComplete() && options::qcfEagerTest() ){
+ d_use_children = false;
+ d_child_counter = 0;
}else if( d_type==typ_bool_var ){
//get current value of the variable
TNode n = qi->getCurrentValue( d_n );
@@ -1195,7 +1264,7 @@ void MatchGen::reset( QuantConflictFind * p, bool tgt, QuantInfo * qi ) {
}else{
//unassigned, set match to true/false
d_qni_bound[0] = vn;
- qi->setMatch( p, vn, d_tgt ? p->d_true : p->d_false, false );
+ qi->setMatch( p, vn, d_tgt ? p->d_true : p->d_false, false, true );
d_child_counter = 0;
}
if( d_child_counter==0 ){
@@ -1203,11 +1272,14 @@ void MatchGen::reset( QuantConflictFind * p, bool tgt, QuantInfo * qi ) {
}
}else if( d_type==typ_var ){
Assert( isHandledUfTerm( d_n ) );
- Node f = getMatchOperator( p, d_n );
+ TNode f = getMatchOperator( p, d_n );
Debug("qcf-match-debug") << " reset: Var will match operators of " << f << std::endl;
TermArgTrie * qni = p->getTermDatabase()->getTermArgTrie( Node::null(), f );
if( qni!=NULL ){
d_qn.push_back( qni );
+ }else{
+ //inform irrelevant quantifiers
+ p->setIrrelevantFunction( f );
}
d_matched_basis = false;
}else if( d_type==typ_tsym || d_type==typ_tconstraint ){
@@ -1257,7 +1329,7 @@ void MatchGen::reset( QuantConflictFind * p, bool tgt, QuantInfo * qi ) {
}
}
}else{
- //otherwise, add a constraint to a variable
+ //otherwise, add a constraint to a variable TODO: this may be over-eager at effort > conflict, since equality may be a propagation
if( vn[1]!=-1 && vn[0]==-1 ){
//swap
Node t = nn[1];
@@ -1292,7 +1364,9 @@ void MatchGen::reset( QuantConflictFind * p, bool tgt, QuantInfo * qi ) {
d_qn.push_back( NULL );
}else{
if( d_tgt && d_n.getKind()==FORALL ){
- //do nothing
+ //fail
+ }else if( d_n.getKind()==FORALL && p->d_effort==QuantConflictFind::effort_conflict && !options::qcfNestedConflict() ){
+ //fail
}else{
//reset the first child to d_tgt
d_child_counter = 0;
@@ -1309,7 +1383,7 @@ bool MatchGen::getNextMatch( QuantConflictFind * p, QuantInfo * qi ) {
Debug("qcf-match") << " Get next match for : " << d_n << ", type = ";
debugPrintType( "qcf-match", d_type );
Debug("qcf-match") << ", children = " << d_children.size() << ", binding = " << d_binding << std::endl;
- if( d_type==typ_invalid || d_type==typ_ground ){
+ if( !d_use_children ){
if( d_child_counter==0 ){
d_child_counter = -1;
return true;
@@ -1423,7 +1497,7 @@ bool MatchGen::getNextMatch( QuantConflictFind * p, QuantInfo * qi ) {
for( std::map< int, int >::iterator it = d_qni_bound.begin(); it != d_qni_bound.end(); ++it ){
Debug("qcf-match") << " Clean up bound var " << it->second << std::endl;
Assert( it->second<qi->getNumVars() );
- qi->d_match[ it->second ] = TNode::null();
+ qi->unsetMatch( p, it->second );
qi->d_match_term[ it->second ] = TNode::null();
}
d_qni_bound.clear();
@@ -1654,7 +1728,7 @@ bool MatchGen::doMatching( QuantConflictFind * p, QuantInfo * qi ) {
if( it != d_qn[index]->d_data.end() ) {
d_qni.push_back( it );
//set the match
- if( it->first.getType().isComparableTo( qi->d_var_types[repVar] ) && qi->setMatch( p, d_qni_bound[index], it->first, true ) ){
+ if( it->first.getType().isComparableTo( qi->d_var_types[repVar] ) && qi->setMatch( p, d_qni_bound[index], it->first, true, true ) ){
Debug("qcf-match-debug") << " Binding variable" << std::endl;
if( d_qn.size()<d_qni_size ){
d_qn.push_back( &it->second );
@@ -1699,7 +1773,7 @@ bool MatchGen::doMatching( QuantConflictFind * p, QuantInfo * qi ) {
d_qni[index]++;
if( d_qni[index]!=d_qn[index]->d_data.end() ){
success = true;
- if( qi->setMatch( p, itb->second, d_qni[index]->first, true ) ){
+ if( qi->setMatch( p, itb->second, d_qni[index]->first, true, true ) ){
Debug("qcf-match-debug") << " Bind next variable" << std::endl;
if( d_qn.size()<d_qni_size ){
d_qn.push_back( &d_qni[index]->second );
@@ -1709,7 +1783,7 @@ bool MatchGen::doMatching( QuantConflictFind * p, QuantInfo * qi ) {
invalidMatch = true;
}
}else{
- qi->d_match[ itb->second ] = TNode::null();
+ qi->unsetMatch( p, itb->second );
qi->d_match_term[ itb->second ] = TNode::null();
Debug("qcf-match-debug") << " Bind next variable, no more variables to bind" << std::endl;
}
@@ -1779,7 +1853,7 @@ void MatchGen::setInvalid() {
}
bool MatchGen::isHandledBoolConnective( TNode n ) {
- return n.getType().isBoolean() && TermDb::isBoolConnective( n.getKind() );
+ return TermDb::isBoolConnective( n.getKind() ) && ( n.getKind()!=ITE || n.getType().isBoolean() );
}
bool MatchGen::isHandledUfTerm( TNode n ) {
@@ -1835,28 +1909,31 @@ void QuantConflictFind::registerQuantifier( Node q ) {
if( d_quantEngine->hasOwnership( q, this ) ){
d_quants.push_back( q );
d_quant_id[q] = d_quants.size();
- Trace("qcf-qregister") << "Register ";
- debugPrintQuant( "qcf-qregister", q );
- Trace("qcf-qregister") << " : " << q << std::endl;
+ if( Trace.isOn("qcf-qregister") ){
+ Trace("qcf-qregister") << "Register ";
+ debugPrintQuant( "qcf-qregister", q );
+ Trace("qcf-qregister") << " : " << q << std::endl;
+ }
//make QcfNode structure
Trace("qcf-qregister") << "- Get relevant equality/disequality pairs, calculate flattening..." << std::endl;
d_qinfo[q].initialize( this, q, q[1] );
//debug print
- Trace("qcf-qregister") << "- Flattened structure is :" << std::endl;
- Trace("qcf-qregister") << " ";
- debugPrintQuantBody( "qcf-qregister", q, q[1] );
- Trace("qcf-qregister") << std::endl;
- if( d_qinfo[q].d_vars.size()>q[0].getNumChildren() ){
- Trace("qcf-qregister") << " with additional constraints : " << std::endl;
- for( unsigned j=q[0].getNumChildren(); j<d_qinfo[q].d_vars.size(); j++ ){
- Trace("qcf-qregister") << " ?x" << j << " = ";
- debugPrintQuantBody( "qcf-qregister", q, d_qinfo[q].d_vars[j], false );
- Trace("qcf-qregister") << std::endl;
- }
- }
-
- Trace("qcf-qregister") << "Done registering quantifier." << std::endl;
+ if( Trace.isOn("qcf-qregister") ){
+ Trace("qcf-qregister") << "- Flattened structure is :" << std::endl;
+ Trace("qcf-qregister") << " ";
+ debugPrintQuantBody( "qcf-qregister", q, q[1] );
+ Trace("qcf-qregister") << std::endl;
+ if( d_qinfo[q].d_vars.size()>q[0].getNumChildren() ){
+ Trace("qcf-qregister") << " with additional constraints : " << std::endl;
+ for( unsigned j=q[0].getNumChildren(); j<d_qinfo[q].d_vars.size(); j++ ){
+ Trace("qcf-qregister") << " ?x" << j << " = ";
+ debugPrintQuantBody( "qcf-qregister", q, d_qinfo[q].d_vars[j], false );
+ Trace("qcf-qregister") << std::endl;
+ }
+ }
+ Trace("qcf-qregister") << "Done registering quantifier." << std::endl;
+ }
}
}
@@ -1933,6 +2010,18 @@ void QuantConflictFind::reset_round( Theory::Effort level ) {
d_needs_computeRelEqr = true;
}
+void QuantConflictFind::setIrrelevantFunction( TNode f ) {
+ if( d_irr_func.find( f )==d_irr_func.end() ){
+ d_irr_func[f] = true;
+ std::map< TNode, std::vector< Node > >::iterator it = d_func_rel_dom.find( f );
+ if( it != d_func_rel_dom.end()){
+ for( unsigned j=0; j<it->second.size(); j++ ){
+ d_irr_quant[it->second[j]] = true;
+ }
+ }
+ }
+}
+
/** check */
void QuantConflictFind::check( Theory::Effort level, unsigned quant_e ) {
if( quant_e==QuantifiersEngine::QEFFORT_CONFLICT ){
@@ -1955,14 +2044,9 @@ void QuantConflictFind::check( Theory::Effort level, unsigned quant_e ) {
}
computeRelevantEqr();
- //determine order for quantified formulas
- std::vector< Node > qorder;
- for( unsigned i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
- Node q = d_quantEngine->getModel()->getAssertedQuantifier( i, true );
- if( d_quantEngine->hasOwnership( q, this ) ){
- qorder.push_back( q );
- }
- }
+ d_irr_func.clear();
+ d_irr_quant.clear();
+
if( Trace.isOn("qcf-debug") ){
Trace("qcf-debug") << std::endl;
debugPrint("qcf-debug");
@@ -1973,77 +2057,83 @@ void QuantConflictFind::check( Theory::Effort level, unsigned quant_e ) {
for( short e = effort_conflict; e<=end_e; e++ ){
d_effort = e;
Trace("qcf-check") << "Checking quantified formulas at effort " << e << "..." << std::endl;
- for( unsigned j=0; j<qorder.size(); j++ ){
- Node q = qorder[j];
- QuantInfo * qi = &d_qinfo[q];
-
- Assert( d_qinfo.find( q )!=d_qinfo.end() );
- if( qi->matchGeneratorIsValid() ){
- Trace("qcf-check") << "Check quantified formula ";
- debugPrintQuant("qcf-check", q);
- Trace("qcf-check") << " : " << q << "..." << std::endl;
-
- Trace("qcf-check-debug") << "Reset round..." << std::endl;
- qi->reset_round( this );
- //try to make a matches making the body false
- Trace("qcf-check-debug") << "Get next match..." << std::endl;
- while( qi->getNextMatch( this ) ){
- Trace("qcf-inst") << "*** Produced match at effort " << e << " : " << std::endl;
- qi->debugPrintMatch("qcf-inst");
- Trace("qcf-inst") << std::endl;
- std::vector< int > assigned;
- if( !qi->isMatchSpurious( this ) ){
- if( qi->completeMatch( this, assigned ) ){
- std::vector< Node > terms;
- qi->getMatch( terms );
- if( !qi->isTConstraintSpurious( this, terms ) ){
- //for debugging
- if( Debug.isOn("qcf-check-inst") ){
- Node inst = d_quantEngine->getInstantiation( q, terms );
- Debug("qcf-check-inst") << "Check instantiation " << inst << "..." << std::endl;
- Assert( !getTermDatabase()->isEntailed( inst, true ) );
- Assert( getTermDatabase()->isEntailed( inst, false ) || e>effort_conflict );
- }
- if( d_quantEngine->addInstantiation( q, terms ) ){
- Trace("qcf-check") << " ... Added instantiation" << std::endl;
- Trace("qcf-inst") << "*** Was from effort " << e << " : " << std::endl;
- qi->debugPrintMatch("qcf-inst");
- Trace("qcf-inst") << std::endl;
- ++addedLemmas;
- if( e==effort_conflict ){
- d_quantEngine->markRelevant( q );
- ++(d_statistics.d_conflict_inst);
- if( options::qcfAllConflict() ){
- isConflict = true;
+ for( unsigned i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+ Node q = d_quantEngine->getModel()->getAssertedQuantifier( i, true );
+ if( d_quantEngine->hasOwnership( q, this ) && d_irr_quant.find( q )==d_irr_quant.end() ){
+ QuantInfo * qi = &d_qinfo[q];
+
+ Assert( d_qinfo.find( q )!=d_qinfo.end() );
+ if( qi->matchGeneratorIsValid() ){
+ Trace("qcf-check") << "Check quantified formula ";
+ debugPrintQuant("qcf-check", q);
+ Trace("qcf-check") << " : " << q << "..." << std::endl;
+
+ Trace("qcf-check-debug") << "Reset round..." << std::endl;
+ if( qi->reset_round( this ) ){
+ //try to make a matches making the body false
+ Trace("qcf-check-debug") << "Get next match..." << std::endl;
+ while( qi->getNextMatch( this ) ){
+ Trace("qcf-inst") << "*** Produced match at effort " << e << " : " << std::endl;
+ qi->debugPrintMatch("qcf-inst");
+ Trace("qcf-inst") << std::endl;
+ if( !qi->isMatchSpurious( this ) ){
+ std::vector< int > assigned;
+ if( qi->completeMatch( this, assigned ) ){
+ std::vector< Node > terms;
+ qi->getMatch( terms );
+ bool tcs = qi->isTConstraintSpurious( this, terms );
+ if( !tcs ){
+ //for debugging
+ if( Debug.isOn("qcf-check-inst") ){
+ Node inst = d_quantEngine->getInstantiation( q, terms );
+ Debug("qcf-check-inst") << "Check instantiation " << inst << "..." << std::endl;
+ Assert( !getTermDatabase()->isEntailed( inst, true ) );
+ Assert( getTermDatabase()->isEntailed( inst, false ) || e>effort_conflict );
+ }
+ if( d_quantEngine->addInstantiation( q, terms ) ){
+ Trace("qcf-check") << " ... Added instantiation" << std::endl;
+ Trace("qcf-inst") << "*** Was from effort " << e << " : " << std::endl;
+ qi->debugPrintMatch("qcf-inst");
+ Trace("qcf-inst") << std::endl;
+ ++addedLemmas;
+ if( e==effort_conflict ){
+ d_quantEngine->markRelevant( q );
+ ++(d_statistics.d_conflict_inst);
+ if( options::qcfAllConflict() ){
+ isConflict = true;
+ }else{
+ d_conflict.set( true );
+ }
+ break;
+ }else if( e==effort_prop_eq ){
+ d_quantEngine->markRelevant( q );
+ ++(d_statistics.d_prop_inst);
+ }
}else{
- d_conflict.set( true );
+ Trace("qcf-inst") << " ... Failed to add instantiation" << std::endl;
+ //this should only happen if the algorithm generates the same propagating instance twice this round
+ //in this case, break to avoid exponential behavior
+ break;
}
- break;
- }else if( e==effort_prop_eq ){
- d_quantEngine->markRelevant( q );
- ++(d_statistics.d_prop_inst);
+ }else{
+ Trace("qcf-inst") << " ... Spurious instantiation (match is T-inconsistent)" << std::endl;
}
+ //clean up assigned
+ qi->revertMatch( this, assigned );
+ d_tempCache.clear();
}else{
- Trace("qcf-inst") << " ... Failed to add instantiation" << std::endl;
- //this should only happen if the algorithm generates the same propagating instance twice this round
- //in this case, break to avoid exponential behavior
- break;
+ Trace("qcf-inst") << " ... Spurious instantiation (cannot assign unassigned variables)" << std::endl;
}
+ }else{
+ Trace("qcf-inst") << " ... Spurious instantiation (match is inconsistent)" << std::endl;
}
- //clean up assigned
- qi->revertMatch( assigned );
- d_tempCache.clear();
- }else{
- Trace("qcf-inst") << " ... Spurious instantiation (cannot assign unassigned variables)" << std::endl;
}
- }else{
- Trace("qcf-inst") << " ... Spurious instantiation (match is inconsistent)" << std::endl;
+ Trace("qcf-check") << "Done, conflict = " << d_conflict << std::endl;
+ if( d_conflict ){
+ break;
+ }
}
}
- Trace("qcf-check") << "Done, conflict = " << d_conflict << std::endl;
- if( d_conflict ){
- break;
- }
}
}
if( addedLemmas>0 ){
@@ -2074,17 +2164,9 @@ void QuantConflictFind::check( Theory::Effort level, unsigned quant_e ) {
void QuantConflictFind::computeRelevantEqr() {
if( d_needs_computeRelEqr ){
d_needs_computeRelEqr = false;
- Trace("qcf-check") << "Compute relevant equalities..." << std::endl;
- //d_uf_terms.clear();
- //d_eqc_uf_terms.clear();
+ Trace("qcf-check") << "Compute relevant equivalence classes..." << std::endl;
d_eqcs.clear();
- //d_arg_reps.clear();
- //double clSet = 0;
- //if( Trace.isOn("qcf-opt") ){
- // clSet = double(clock())/double(CLOCKS_PER_SEC);
- //}
- //now, store matches
eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( getEqualityEngine() );
while( !eqcs_i.isFinished() ){
Node r = (*eqcs_i);
diff --git a/src/theory/quantifiers/quant_conflict_find.h b/src/theory/quantifiers/quant_conflict_find.h
index 8b42b0916..47a66b1b1 100644..100755
--- a/src/theory/quantifiers/quant_conflict_find.h
+++ b/src/theory/quantifiers/quant_conflict_find.h
@@ -35,6 +35,7 @@ class MatchGen {
private:
//current children information
int d_child_counter;
+ bool d_use_children;
//children of this object
std::vector< int > d_children_order;
unsigned getNumChildren() { return d_children.size(); }
@@ -61,7 +62,7 @@ private:
std::map< int, Node > d_ground_eval;
//determine variable order
void determineVariableOrder( QuantInfo * qi, std::vector< int >& bvars );
- void collectBoundVar( QuantInfo * qi, Node n, std::vector< int >& cbvars );
+ void collectBoundVar( QuantInfo * qi, Node n, std::vector< int >& cbvars, std::map< Node, bool >& visited, bool& hasNested );
public:
//type of the match generator
enum {
@@ -116,7 +117,16 @@ private: //for completing match
std::vector< int > d_una_eqc_count;
//optimization: track which arguments variables appear under UF terms in
std::map< int, std::map< TNode, std::vector< unsigned > > > d_var_rel_dom;
- void getPropagateVars( std::vector< TNode >& vars, TNode n, bool pol, std::map< TNode, bool >& visited );
+ void getPropagateVars( QuantConflictFind * p, std::vector< TNode >& vars, TNode n, bool pol, std::map< TNode, bool >& visited );
+ //optimization: number of variables set, to track when we can stop
+ std::map< int, bool > d_vars_set;
+ std::map< Node, bool > d_ground_terms;
+ std::vector< Node > d_extra_var;
+public:
+ void setGroundSubterm( Node t ) { d_ground_terms[t] = true; }
+ bool isGroundSubterm( Node t ) { return d_ground_terms.find( t )!=d_ground_terms.end(); }
+ bool isBaseMatchComplete();
+ bool isPropagatingInstance( QuantConflictFind * p, Node n );
public:
QuantInfo();
~QuantInfo();
@@ -146,7 +156,7 @@ public:
}
Node d_q;
- void reset_round( QuantConflictFind * p );
+ bool reset_round( QuantConflictFind * p );
public:
//initialize
void initialize( QuantConflictFind * p, Node q, Node qn );
@@ -161,12 +171,13 @@ public:
bool getCurrentCanBeEqual( QuantConflictFind * p, int v, TNode n, bool chDiseq = false );
int addConstraint( QuantConflictFind * p, int v, TNode n, bool polarity );
int addConstraint( QuantConflictFind * p, int v, TNode n, int vn, bool polarity, bool doRemove );
- bool setMatch( QuantConflictFind * p, int v, TNode n, bool isGroundRep );
+ bool setMatch( QuantConflictFind * p, int v, TNode n, bool isGroundRep, bool isGround );
+ void unsetMatch( QuantConflictFind * p, int v );
bool isMatchSpurious( QuantConflictFind * p );
bool isTConstraintSpurious( QuantConflictFind * p, std::vector< Node >& terms );
bool entailmentTest( QuantConflictFind * p, Node lit, bool chEnt = true );
bool completeMatch( QuantConflictFind * p, std::vector< int >& assigned, bool doContinue = false );
- void revertMatch( std::vector< int >& assigned );
+ void revertMatch( QuantConflictFind * p, std::vector< int >& assigned );
void debugPrintMatch( const char * c );
bool isConstrainedVar( int v );
public:
@@ -184,6 +195,11 @@ private:
std::map< Kind, Node > d_zero;
//for storing nodes created during t-constraint solving (prevents memory leaks)
std::vector< Node > d_tempCache;
+ //optimization: list of quantifiers that depend on ground function applications
+ std::map< TNode, std::vector< Node > > d_func_rel_dom;
+ std::map< TNode, bool > d_irr_func;
+ std::map< Node, bool > d_irr_quant;
+ void setIrrelevantFunction( TNode f );
private:
std::map< Node, Node > d_op_node;
int d_fid_count;
diff --git a/src/theory/quantifiers/quant_equality_engine.cpp b/src/theory/quantifiers/quant_equality_engine.cpp
index 3f89a799c..3f89a799c 100644..100755
--- a/src/theory/quantifiers/quant_equality_engine.cpp
+++ b/src/theory/quantifiers/quant_equality_engine.cpp
diff --git a/src/theory/quantifiers/quant_equality_engine.h b/src/theory/quantifiers/quant_equality_engine.h
index 26654de4d..26654de4d 100644..100755
--- a/src/theory/quantifiers/quant_equality_engine.h
+++ b/src/theory/quantifiers/quant_equality_engine.h
diff --git a/src/theory/quantifiers/quant_split.cpp b/src/theory/quantifiers/quant_split.cpp
index 9fb943e5e..5aff1a848 100644..100755
--- a/src/theory/quantifiers/quant_split.cpp
+++ b/src/theory/quantifiers/quant_split.cpp
@@ -48,11 +48,11 @@ void QuantDSplit::preRegisterQuantifier( Node q ) {
}else{
int score = -1;
if( options::quantDynamicSplit()==quantifiers::QUANT_DSPLIT_MODE_AGG ){
- score = dt.isUFinite() ? 1 : -1;
+ score = dt.isInterpretedFinite() ? 1 : -1;
}else if( options::quantDynamicSplit()==quantifiers::QUANT_DSPLIT_MODE_DEFAULT ){
- score = dt.isUFinite() ? 1 : -1;
+ score = dt.isInterpretedFinite() ? 1 : -1;
}
- Trace("quant-dsplit-debug") << "Datatype " << dt.getName() << " is score " << score << " (" << dt.isUFinite() << " " << dt.isFinite() << ")" << std::endl;
+ Trace("quant-dsplit-debug") << "Datatype " << dt.getName() << " is score " << score << " (" << dt.isInterpretedFinite() << " " << dt.isFinite() << ")" << std::endl;
if( score>max_score ){
max_index = i;
max_score = score;
diff --git a/src/theory/quantifiers/quant_split.h b/src/theory/quantifiers/quant_split.h
index d36824998..d36824998 100644..100755
--- a/src/theory/quantifiers/quant_split.h
+++ b/src/theory/quantifiers/quant_split.h
diff --git a/src/theory/quantifiers/quant_util.cpp b/src/theory/quantifiers/quant_util.cpp
index 3b7787a20..b9aab0236 100644..100755
--- a/src/theory/quantifiers/quant_util.cpp
+++ b/src/theory/quantifiers/quant_util.cpp
@@ -33,22 +33,15 @@ eq::EqualityEngine * QuantifiersModule::getEqualityEngine() {
}
bool QuantifiersModule::areEqual( TNode n1, TNode n2 ) {
- eq::EqualityEngine * ee = getEqualityEngine();
- return n1==n2 || ( ee->hasTerm( n1 ) && ee->hasTerm( n2 ) && ee->areEqual( n1, n2 ) );
+ return d_quantEngine->getEqualityQuery()->areEqual( n1, n2 );
}
bool QuantifiersModule::areDisequal( TNode n1, TNode n2 ) {
- eq::EqualityEngine * ee = getEqualityEngine();
- return n1!=n2 && ee->hasTerm( n1 ) && ee->hasTerm( n2 ) && ee->areDisequal( n1, n2, false );
+ return d_quantEngine->getEqualityQuery()->areDisequal( n1, n2 );
}
TNode QuantifiersModule::getRepresentative( TNode n ) {
- eq::EqualityEngine * ee = getEqualityEngine();
- if( ee->hasTerm( n ) ){
- return ee->getRepresentative( n );
- }else{
- return n;
- }
+ return d_quantEngine->getEqualityQuery()->getRepresentative( n );
}
quantifiers::TermDb * QuantifiersModule::getTermDatabase() {
@@ -389,7 +382,7 @@ void QuantPhaseReq::computePhaseReqs( Node n, bool polarity, std::map< Node, int
}
void QuantPhaseReq::getPolarity( Node n, int child, bool hasPol, bool pol, bool& newHasPol, bool& newPol ) {
- if( n.getKind()==AND || n.getKind()==OR ){
+ if( n.getKind()==AND || n.getKind()==OR || n.getKind()==SEP_STAR ){
newHasPol = hasPol;
newPol = pol;
}else if( n.getKind()==IMPLIES ){
diff --git a/src/theory/quantifiers/quant_util.h b/src/theory/quantifiers/quant_util.h
index 79cdae437..79cdae437 100644..100755
--- a/src/theory/quantifiers/quant_util.h
+++ b/src/theory/quantifiers/quant_util.h
diff --git a/src/theory/quantifiers/quantifiers_attributes.cpp b/src/theory/quantifiers/quantifiers_attributes.cpp
index b797f4ce9..b797f4ce9 100644..100755
--- a/src/theory/quantifiers/quantifiers_attributes.cpp
+++ b/src/theory/quantifiers/quantifiers_attributes.cpp
diff --git a/src/theory/quantifiers/quantifiers_attributes.h b/src/theory/quantifiers/quantifiers_attributes.h
index 53cef796a..53cef796a 100644..100755
--- a/src/theory/quantifiers/quantifiers_attributes.h
+++ b/src/theory/quantifiers/quantifiers_attributes.h
diff --git a/src/theory/quantifiers/quantifiers_rewriter.cpp b/src/theory/quantifiers/quantifiers_rewriter.cpp
index 5aae4d640..68f824c57 100644..100755
--- a/src/theory/quantifiers/quantifiers_rewriter.cpp
+++ b/src/theory/quantifiers/quantifiers_rewriter.cpp
@@ -48,7 +48,7 @@ bool QuantifiersRewriter::isClause( Node n ){
bool QuantifiersRewriter::isLiteral( Node n ){
switch( n.getKind() ){
case NOT:
- return isLiteral( n[0] );
+ return n[0].getKind()!=NOT && isLiteral( n[0] );
break;
case OR:
case AND:
@@ -59,7 +59,8 @@ bool QuantifiersRewriter::isLiteral( Node n ){
return false;
break;
case EQUAL:
- return n[0].getType()!=NodeManager::currentNM()->booleanType();
+ //for boolean terms
+ return !n[0].getType().isBoolean();
break;
default:
break;
@@ -185,19 +186,10 @@ RewriteResponse QuantifiersRewriter::preRewrite(TNode in) {
if( in.getKind()==kind::EXISTS || in.getKind()==kind::FORALL ){
Trace("quantifiers-rewrite-debug") << "pre-rewriting " << in << std::endl;
std::vector< Node > args;
- for( int i=0; i<(int)in[0].getNumChildren(); i++ ){
- args.push_back( in[0][i] );
- }
- Node body = in[1];
+ Node body = in;
bool doRewrite = false;
- std::vector< Node > ipl;
- while( body.getNumChildren()>=2 && body.getKind()==in.getKind() ){
- if( body.getNumChildren()==3 ){
- for( unsigned i=0; i<body[2].getNumChildren(); i++ ){
- ipl.push_back( body[2][i] );
- }
- }
- for( int i=0; i<(int)body[0].getNumChildren(); i++ ){
+ while( body.getNumChildren()==2 && body.getKind()==body[1].getKind() ){
+ for( unsigned i=0; i<body[0].getNumChildren(); i++ ){
args.push_back( body[0][i] );
}
body = body[1];
@@ -205,16 +197,11 @@ RewriteResponse QuantifiersRewriter::preRewrite(TNode in) {
}
if( doRewrite ){
std::vector< Node > children;
+ for( unsigned i=0; i<body[0].getNumChildren(); i++ ){
+ args.push_back( body[0][i] );
+ }
children.push_back( NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST,args) );
- children.push_back( body );
- if( in.getNumChildren()==3 ){
- for( unsigned i=0; i<in[2].getNumChildren(); i++ ){
- ipl.push_back( in[2][i] );
- }
- }
- if( !ipl.empty() ){
- children.push_back( NodeManager::currentNM()->mkNode( INST_PATTERN_LIST, ipl ) );
- }
+ children.push_back( body[1] );
Node n = NodeManager::currentNM()->mkNode( in.getKind(), children );
if( in!=n ){
Trace("quantifiers-pre-rewrite") << "*** pre-rewrite " << in << std::endl;
@@ -244,7 +231,7 @@ RewriteResponse QuantifiersRewriter::postRewrite(TNode in) {
ret = ret.negate();
status = REWRITE_AGAIN_FULL;
}else if( in.getKind()==FORALL ){
- if( in[1].isConst() ){
+ if( in[1].isConst() && in.getNumChildren()==2 ){
return RewriteResponse( status, in[1] );
}else{
//compute attributes
@@ -273,121 +260,98 @@ RewriteResponse QuantifiersRewriter::postRewrite(TNode in) {
return RewriteResponse( status, ret );
}
-Node QuantifiersRewriter::computeElimSymbols( Node body ) {
- if( isLiteral( body ) ){
- return body;
- }else{
- bool childrenChanged = false;
- Kind k = body.getKind();
- if( body.getKind()==IMPLIES ){
- k = OR;
- childrenChanged = true;
- }else if( body.getKind()==XOR ){
- k = IFF;
+bool QuantifiersRewriter::addCheckElimChild( std::vector< Node >& children, Node c, Kind k, std::map< Node, bool >& lit_pol, bool& childrenChanged ){
+ if( ( k==OR || k==AND ) && options::elimTautQuant() ){
+ Node lit = c.getKind()==NOT ? c[0] : c;
+ bool pol = c.getKind()!=NOT;
+ std::map< Node, bool >::iterator it = lit_pol.find( lit );
+ if( it==lit_pol.end() ){
+ lit_pol[lit] = pol;
+ children.push_back( c );
+ }else{
childrenChanged = true;
- }
- std::vector< Node > children;
- std::map< Node, bool > lit_pol;
- for( unsigned i=0; i<body.getNumChildren(); i++ ){
- Node c = computeElimSymbols( body[i] );
- if( i==0 && ( body.getKind()==IMPLIES || body.getKind()==XOR ) ){
- c = c.negate();
- }
- if( ( k==OR || k==AND ) && options::elimTautQuant() ){
- Node lit = c.getKind()==NOT ? c[0] : c;
- bool pol = c.getKind()!=NOT;
- std::map< Node, bool >::iterator it = lit_pol.find( lit );
- if( it==lit_pol.end() ){
- lit_pol[lit] = pol;
- children.push_back( c );
- }else{
- childrenChanged = true;
- if( it->second!=pol ){
- return NodeManager::currentNM()->mkConst( k==OR );
- }
- }
- }else{
- children.push_back( c );
+ if( it->second!=pol ){
+ return false;
}
- childrenChanged = childrenChanged || c!=body[i];
- }
- //if( body.getKind()==ITE && isLiteral( body[0] ) ){
- // ret = NodeManager::currentNM()->mkNode( AND, NodeManager::currentNM()->mkNode( OR, body[0].negate(), body[1] ),
- // NodeManager::currentNM()->mkNode( OR, body[0], body[2] ) );
- //}
- if( childrenChanged ){
- return ( children.size()==1 && k!=NOT ) ? children[0] : NodeManager::currentNM()->mkNode( k, children );
- }else{
- return body;
}
+ }else{
+ children.push_back( c );
}
+ return true;
}
-Node QuantifiersRewriter::computeNNF( Node body ){
- if( body.getKind()==NOT ){
+// eliminates IMPLIES/XOR, removes duplicates/infers tautologies of AND/OR, and computes NNF
+Node QuantifiersRewriter::computeElimSymbols( Node body ) {
+ Kind ok = body.getKind();
+ Kind k = ok;
+ bool negAllCh = false;
+ bool negCh1 = false;
+ if( ok==IMPLIES ){
+ k = OR;
+ negCh1 = true;
+ }else if( ok==XOR ){
+ k = IFF;
+ negCh1 = true;
+ }else if( ok==NOT ){
if( body[0].getKind()==NOT ){
- return computeNNF( body[0][0] );
- }else if( isLiteral( body[0] ) ){
- return body;
+ return computeElimSymbols( body[0][0] );
+ }else if( body[0].getKind()==OR || body[0].getKind()==IMPLIES ){
+ k = AND;
+ negAllCh = true;
+ negCh1 = body[0].getKind()==IMPLIES;
+ body = body[0];
+ }else if( body[0].getKind()==AND ){
+ k = OR;
+ negAllCh = true;
+ body = body[0];
+ }else if( body[0].getKind()==XOR || body[0].getKind()==IFF ){
+ k = IFF;
+ negCh1 = ( body[0].getKind()==IFF );
+ body = body[0];
+ }else if( body[0].getKind()==ITE ){
+ k = body[0].getKind();
+ negAllCh = true;
+ negCh1 = true;
+ body = body[0];
}else{
- std::vector< Node > children;
- Kind k = body[0].getKind();
-
- if( body[0].getKind()==OR || body[0].getKind()==AND ){
- k = body[0].getKind()==AND ? OR : AND;
- for( int i=0; i<(int)body[0].getNumChildren(); i++ ){
- Node nc = computeNNF( body[0][i].notNode() );
- if( nc.getKind()==k ){
- for( unsigned j=0; j<nc.getNumChildren(); j++ ){
- children.push_back( nc[j] );
- }
- }else{
- children.push_back( nc );
- }
- }
- }else if( body[0].getKind()==IFF ){
- for( int i=0; i<2; i++ ){
- Node nn = i==0 ? body[0][i] : body[0][i].notNode();
- children.push_back( computeNNF( nn ) );
- }
- }else if( body[0].getKind()==ITE ){
- for( int i=0; i<3; i++ ){
- Node nn = i==0 ? body[0][i] : body[0][i].notNode();
- children.push_back( computeNNF( nn ) );
- }
- }else{
- Notice() << "Unhandled Quantifiers NNF: " << body << std::endl;
- return body;
- }
- return NodeManager::currentNM()->mkNode( k, children );
+ return body;
}
- }else if( isLiteral( body ) ){
+ }else if( ok!=IFF && ok!=ITE && ok!=AND && ok!=OR ){
+ //a literal
return body;
- }else{
- std::vector< Node > children;
- bool childrenChanged = false;
- bool isAssoc = body.getKind()==AND || body.getKind()==OR;
- for( int i=0; i<(int)body.getNumChildren(); i++ ){
- Node nc = computeNNF( body[i] );
- if( isAssoc && nc.getKind()==body.getKind() ){
- for( unsigned j=0; j<nc.getNumChildren(); j++ ){
- children.push_back( nc[j] );
+ }
+ bool childrenChanged = false;
+ std::vector< Node > children;
+ std::map< Node, bool > lit_pol;
+ for( unsigned i=0; i<body.getNumChildren(); i++ ){
+ Node c = computeElimSymbols( ( i==0 && negCh1 )!=negAllCh ? body[i].negate() : body[i] );
+ bool success = true;
+ if( c.getKind()==k && ( k==OR || k==AND ) ){
+ //flatten
+ childrenChanged = true;
+ for( unsigned j=0; j<c.getNumChildren(); j++ ){
+ if( !addCheckElimChild( children, c[j], k, lit_pol, childrenChanged ) ){
+ success = false;
+ break;
}
- childrenChanged = true;
- }else{
- children.push_back( nc );
- childrenChanged = childrenChanged || nc!=body[i];
}
- }
- if( childrenChanged ){
- return NodeManager::currentNM()->mkNode( body.getKind(), children );
}else{
- return body;
+ success = addCheckElimChild( children, c, k, lit_pol, childrenChanged );
}
+ if( !success ){
+ // tautology
+ Assert( k==OR || k==AND );
+ return NodeManager::currentNM()->mkConst( k==OR );
+ }
+ childrenChanged = childrenChanged || c!=body[i];
+ }
+ if( childrenChanged || k!=ok ){
+ return ( children.size()==1 && k!=NOT ) ? children[0] : NodeManager::currentNM()->mkNode( k, children );
+ }else{
+ return body;
}
}
-
void QuantifiersRewriter::computeDtTesterIteSplit( Node n, std::map< Node, Node >& pcons, std::map< Node, std::map< int, Node > >& ncons,
std::vector< Node >& conj ){
if( n.getKind()==ITE && n[0].getKind()==APPLY_TESTER && n[1].getType().isBoolean() ){
@@ -463,6 +427,8 @@ int getEntailedCond( Node n, std::map< Node, bool >& currCond ){
std::map< Node, bool >::iterator it = currCond.find( n );
if( it!=currCond.end() ){
return it->second ? 1 : -1;
+ }else if( n.getKind()==NOT ){
+ return -getEntailedCond( n[0], currCond );
}else if( n.getKind()==AND || n.getKind()==OR ){
bool hasZero = false;
for( unsigned i=0; i<n.getNumChildren(); i++ ){
@@ -483,8 +449,7 @@ int getEntailedCond( Node n, std::map< Node, bool >& currCond ){
}else if( res==-1 ){
return getEntailedCond( n[2], currCond );
}
- }
- if( n.getKind()==IFF || n.getKind()==ITE ){
+ }else if( n.getKind()==IFF || n.getKind()==ITE ){
unsigned start = n.getKind()==IFF ? 0 : 1;
int res1 = 0;
for( unsigned j=start; j<=(start+1); j++ ){
@@ -1049,144 +1014,6 @@ Node QuantifiersRewriter::computeVarElimination( Node body, std::vector< Node >&
return body;
}
-Node QuantifiersRewriter::computeClause( Node n ){
- Assert( isClause( n ) );
- if( isLiteral( n ) ){
- return n;
- }else{
- NodeBuilder<> t(OR);
- if( n.getKind()==NOT ){
- if( n[0].getKind()==NOT ){
- return computeClause( n[0][0] );
- }else{
- //De-Morgan's law
- Assert( n[0].getKind()==AND );
- for( int i=0; i<(int)n[0].getNumChildren(); i++ ){
- Node nn = computeClause( n[0][i].notNode() );
- addNodeToOrBuilder( nn, t );
- }
- }
- }else{
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- Node nn = computeClause( n[i] );
- addNodeToOrBuilder( nn, t );
- }
- }
- return t.constructNode();
- }
-}
-
-Node QuantifiersRewriter::computeCNF( Node n, std::vector< Node >& args, NodeBuilder<>& defs, bool forcePred ){
- if( isLiteral( n ) ){
- return n;
- }else if( !forcePred && isClause( n ) ){
- return computeClause( n );
- }else{
- Kind k = n.getKind();
- NodeBuilder<> t(k);
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- Node nc = n[i];
- Node ncnf = computeCNF( nc, args, defs, k!=OR );
- if( k==OR ){
- addNodeToOrBuilder( ncnf, t );
- }else{
- t << ncnf;
- }
- }
- if( !forcePred && k==OR ){
- return t.constructNode();
- }else{
- //compute the free variables
- Node nt = t;
- std::vector< Node > activeArgs;
- computeArgVec( args, activeArgs, nt );
- std::vector< TypeNode > argTypes;
- for( int i=0; i<(int)activeArgs.size(); i++ ){
- argTypes.push_back( activeArgs[i].getType() );
- }
- //create the predicate
- Assert( argTypes.size()>0 );
- TypeNode typ = NodeManager::currentNM()->mkFunctionType( argTypes, NodeManager::currentNM()->booleanType() );
- std::stringstream ss;
- ss << "cnf_" << n.getKind() << "_" << n.getId();
- Node op = NodeManager::currentNM()->mkSkolem( ss.str(), typ, "was created by the quantifiers rewriter" );
- std::vector< Node > predArgs;
- predArgs.push_back( op );
- predArgs.insert( predArgs.end(), activeArgs.begin(), activeArgs.end() );
- Node pred = NodeManager::currentNM()->mkNode( APPLY_UF, predArgs );
- Trace("quantifiers-rewrite-cnf-debug") << "Made predicate " << pred << " for " << nt << std::endl;
- //create the bound var list
- Node bvl = NodeManager::currentNM()->mkNode( BOUND_VAR_LIST, activeArgs );
- //now, look at the structure of nt
- if( nt.getKind()==NOT ){
- //case for NOT
- for( int i=0; i<2; i++ ){
- NodeBuilder<> tt(OR);
- tt << ( i==0 ? nt[0].notNode() : nt[0] );
- tt << ( i==0 ? pred.notNode() : pred );
- defs << NodeManager::currentNM()->mkNode( FORALL, bvl, tt.constructNode() );
- }
- }else if( nt.getKind()==OR ){
- //case for OR
- for( int i=0; i<(int)nt.getNumChildren(); i++ ){
- NodeBuilder<> tt(OR);
- tt << nt[i].notNode() << pred;
- defs << NodeManager::currentNM()->mkNode( FORALL, bvl, tt.constructNode() );
- }
- NodeBuilder<> tt(OR);
- for( int i=0; i<(int)nt.getNumChildren(); i++ ){
- tt << nt[i];
- }
- tt << pred.notNode();
- defs << NodeManager::currentNM()->mkNode( FORALL, bvl, tt.constructNode() );
- }else if( nt.getKind()==AND ){
- //case for AND
- for( int i=0; i<(int)nt.getNumChildren(); i++ ){
- NodeBuilder<> tt(OR);
- tt << nt[i] << pred.notNode();
- defs << NodeManager::currentNM()->mkNode( FORALL, bvl, tt.constructNode() );
- }
- NodeBuilder<> tt(OR);
- for( int i=0; i<(int)nt.getNumChildren(); i++ ){
- tt << nt[i].notNode();
- }
- tt << pred;
- defs << NodeManager::currentNM()->mkNode( FORALL, bvl, tt.constructNode() );
- }else if( nt.getKind()==IFF ){
- //case for IFF
- for( int i=0; i<4; i++ ){
- NodeBuilder<> tt(OR);
- tt << ( ( i==0 || i==3 ) ? nt[0].notNode() : nt[0] );
- tt << ( ( i==1 || i==3 ) ? nt[1].notNode() : nt[1] );
- tt << ( ( i==0 || i==1 ) ? pred.notNode() : pred );
- defs << NodeManager::currentNM()->mkNode( FORALL, bvl, tt.constructNode() );
- }
- }else if( nt.getKind()==ITE ){
- //case for ITE
- for( int j=1; j<=2; j++ ){
- for( int i=0; i<2; i++ ){
- NodeBuilder<> tt(OR);
- tt << ( ( j==1 ) ? nt[0].notNode() : nt[0] );
- tt << ( ( i==1 ) ? nt[j].notNode() : nt[j] );
- tt << ( ( i==0 ) ? pred.notNode() : pred );
- defs << NodeManager::currentNM()->mkNode( FORALL, bvl, tt.constructNode() );
- }
- }
- for( int i=0; i<2; i++ ){
- NodeBuilder<> tt(OR);
- tt << ( i==0 ? nt[1].notNode() : nt[1] );
- tt << ( i==0 ? nt[2].notNode() : nt[2] );
- tt << ( i==1 ? pred.notNode() : pred );
- defs << NodeManager::currentNM()->mkNode( FORALL, bvl, tt.constructNode() );
- }
- }else{
- Notice() << "Unhandled Quantifiers CNF: " << nt << std::endl;
- }
- return pred;
- }
- }
-}
-
Node QuantifiersRewriter::computePrenex( Node body, std::vector< Node >& args, bool pol ){
if( body.getKind()==FORALL ){
if( pol && ( options::prenexQuant()==PRENEX_ALL || body.getNumChildren()==2 ) ){
@@ -1194,15 +1021,13 @@ Node QuantifiersRewriter::computePrenex( Node body, std::vector< Node >& args, b
std::vector< Node > subs;
//for doing prenexing of same-signed quantifiers
//must rename each variable that already exists
- for( int i=0; i<(int)body[0].getNumChildren(); i++ ){
- //if( std::find( args.begin(), args.end(), body[0][i] )!=args.end() ){
+ for( unsigned i=0; i<body[0].getNumChildren(); i++ ){
terms.push_back( body[0][i] );
subs.push_back( NodeManager::currentNM()->mkBoundVar( body[0][i].getType() ) );
}
args.insert( args.end(), subs.begin(), subs.end() );
Node newBody = body[1];
newBody = newBody.substitute( terms.begin(), terms.end(), subs.begin(), subs.end() );
- Debug("quantifiers-substitute-debug") << "Did substitute have an effect" << (body[1] != newBody) << body[1] << " became " << newBody << endl;
return newBody;
}else{
return body;
@@ -1211,7 +1036,7 @@ Node QuantifiersRewriter::computePrenex( Node body, std::vector< Node >& args, b
Assert( body.getKind()!=EXISTS );
bool childrenChanged = false;
std::vector< Node > newChildren;
- for( int i=0; i<(int)body.getNumChildren(); i++ ){
+ for( unsigned i=0; i<body.getNumChildren(); i++ ){
bool newHasPol;
bool newPol;
QuantPhaseReq::getPolarity( body, i, true, pol, newHasPol, newPol );
@@ -1237,7 +1062,7 @@ Node QuantifiersRewriter::computePrenex( Node body, std::vector< Node >& args, b
}
}
-Node QuantifiersRewriter::computeSplit( Node f, std::vector< Node >& args, Node body ) {
+Node QuantifiersRewriter::computeSplit( std::vector< Node >& args, Node body, QAttributes& qa ) {
Assert( body.getKind()==OR );
size_t var_found_count = 0;
size_t eqc_count = 0;
@@ -1253,8 +1078,8 @@ Node QuantifiersRewriter::computeSplit( Node f, std::vector< Node >& args, Node
Node n = body[i];
std::vector< Node > lit_args;
computeArgVec( args, lit_args, n );
- if (lit_args.empty()) {
- lits.push_back(n);
+ if( lit_args.empty() ){
+ lits.push_back( n );
}else {
//collect the equivalence classes this literal belongs to, and the new variables it contributes
std::vector< int > eqcs;
@@ -1306,8 +1131,8 @@ Node QuantifiersRewriter::computeSplit( Node f, std::vector< Node >& args, Node
eqc_to_lit[eqcz].push_back(n);
}
}
- if ( eqc_active>1 || !lits.empty() ){
- Trace("clause-split-debug") << "Split clause " << f << std::endl;
+ if ( eqc_active>1 || !lits.empty() || var_to_eqc.size()!=args.size() ){
+ Trace("clause-split-debug") << "Split quantified formula with body " << body << std::endl;
Trace("clause-split-debug") << " Ground literals: " << std::endl;
for( size_t i=0; i<lits.size(); i++) {
Trace("clause-split-debug") << " " << lits[i] << std::endl;
@@ -1330,27 +1155,21 @@ Node QuantifiersRewriter::computeSplit( Node f, std::vector< Node >& args, Node
Node fa = NodeManager::currentNM()->mkNode( FORALL, bvl, body );
lits.push_back(fa);
}
- Assert( lits.size()>1 );
- Node nf = NodeManager::currentNM()->mkNode(OR,lits);
+ Assert( !lits.empty() );
+ Node nf = lits.size()==1 ? lits[0] : NodeManager::currentNM()->mkNode(OR,lits);
Trace("clause-split-debug") << "Made node : " << nf << std::endl;
return nf;
+ }else{
+ return mkForAll( args, body, qa );
}
- return f;
}
Node QuantifiersRewriter::mkForAll( std::vector< Node >& args, Node body, QAttributes& qa ){
- std::vector< Node > activeArgs;
- //if cegqi is on, may be synthesis conjecture, in which case we want to keep all variables
- if( options::ceGuidedInst() && qa.d_sygus ){
- activeArgs.insert( activeArgs.end(), args.begin(), args.end() );
- }else{
- computeArgVec2( args, activeArgs, body, qa.d_ipl );
- }
- if( activeArgs.empty() ){
+ if( args.empty() ){
return body;
}else{
std::vector< Node > children;
- children.push_back( NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST, activeArgs ) );
+ children.push_back( NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST, args ) );
children.push_back( body );
if( !qa.d_ipl.isNull() ){
children.push_back( qa.d_ipl );
@@ -1359,82 +1178,59 @@ Node QuantifiersRewriter::mkForAll( std::vector< Node >& args, Node body, QAttri
}
}
-Node QuantifiersRewriter::computeMiniscoping( Node f, std::vector< Node >& args, Node body, QAttributes& qa ){
+//computes miniscoping, also eliminates variables that do not occur free in body
+Node QuantifiersRewriter::computeMiniscoping( std::vector< Node >& args, Node body, QAttributes& qa ){
if( body.getKind()==FORALL ){
- //combine arguments
+ //combine prenex
std::vector< Node > newArgs;
- for( int i=0; i<(int)body[0].getNumChildren(); i++ ){
+ newArgs.insert( newArgs.end(), args.begin(), args.end() );
+ for( unsigned i=0; i<body[0].getNumChildren(); i++ ){
newArgs.push_back( body[0][i] );
}
- newArgs.insert( newArgs.end(), args.begin(), args.end() );
- return mkForAll( newArgs, body[ 1 ], qa );
- }else{
- if( body.getKind()==NOT ){
- //push not downwards
- if( body[0].getKind()==NOT ){
- return computeMiniscoping( f, args, body[0][0], qa );
- }else if( body[0].getKind()==AND ){
- if( options::miniscopeQuantFreeVar() ){
- NodeBuilder<> t(kind::OR);
- for( int i=0; i<(int)body[0].getNumChildren(); i++ ){
- t << ( body[0][i].getKind()==NOT ? body[0][i][0] : body[0][i].notNode() );
- }
- return computeMiniscoping( f, args, t.constructNode(), qa );
- }
- }else if( body[0].getKind()==OR ){
- if( options::miniscopeQuant() ){
- NodeBuilder<> t(kind::AND);
- for( int i=0; i<(int)body[0].getNumChildren(); i++ ){
- Node trm = body[0][i].negate();
- t << computeMiniscoping( f, args, trm, qa );
- }
- return t.constructNode();
+ return mkForAll( newArgs, body[1], qa );
+ }else if( body.getKind()==AND ){
+ if( options::miniscopeQuant() ){
+ //break apart
+ NodeBuilder<> t(kind::AND);
+ for( unsigned i=0; i<body.getNumChildren(); i++ ){
+ t << computeMiniscoping( args, body[i], qa );
+ }
+ Node retVal = t;
+ return retVal;
+ }
+ }else if( body.getKind()==OR ){
+ if( options::quantSplit() ){
+ //splitting subsumes free variable miniscoping, apply it with higher priority
+ return computeSplit( args, body, qa );
+ }else if( options::miniscopeQuantFreeVar() ){
+ Node newBody = body;
+ NodeBuilder<> body_split(kind::OR);
+ NodeBuilder<> tb(kind::OR);
+ for( unsigned i=0; i<body.getNumChildren(); i++ ){
+ Node trm = body[i];
+ if( TermDb::containsTerms( body[i], args ) ){
+ tb << trm;
+ }else{
+ body_split << trm;
}
}
- }else if( body.getKind()==AND ){
- if( options::miniscopeQuant() ){
- //break apart
- NodeBuilder<> t(kind::AND);
- for( unsigned i=0; i<body.getNumChildren(); i++ ){
- t << computeMiniscoping( f, args, body[i], qa );
- }
- Node retVal = t;
- return retVal;
- }
- }else if( body.getKind()==OR ){
- if( options::quantSplit() ){
- //splitting subsumes free variable miniscoping, apply it with higher priority
- Node nf = computeSplit( f, args, body );
- if( nf!=f ){
- return nf;
- }
- }else if( options::miniscopeQuantFreeVar() ){
- Node newBody = body;
- NodeBuilder<> body_split(kind::OR);
- NodeBuilder<> tb(kind::OR);
- for( unsigned i=0; i<body.getNumChildren(); i++ ){
- Node trm = body[i];
- if( TermDb::containsTerms( body[i], args ) ){
- tb << trm;
- }else{
- body_split << trm;
- }
- }
- if( tb.getNumChildren()==0 ){
- return body_split;
- }else if( body_split.getNumChildren()>0 ){
- newBody = tb.getNumChildren()==1 ? tb.getChild( 0 ) : tb;
- body_split << mkForAll( args, newBody, qa );
- return body_split.getNumChildren()==1 ? body_split.getChild( 0 ) : body_split;
- }
+ if( tb.getNumChildren()==0 ){
+ return body_split;
+ }else if( body_split.getNumChildren()>0 ){
+ newBody = tb.getNumChildren()==1 ? tb.getChild( 0 ) : tb;
+ std::vector< Node > activeArgs;
+ computeArgVec2( args, activeArgs, newBody, qa.d_ipl );
+ body_split << mkForAll( activeArgs, newBody, qa );
+ return body_split.getNumChildren()==1 ? body_split.getChild( 0 ) : body_split;
}
}
+ }else if( body.getKind()==NOT ){
+ Assert( isLiteral( body[0] ) );
}
- //if( body==f[1] ){
- // return f;
- //}else{
- return mkForAll( args, body, qa );
- //}
+ //remove variables that don't occur
+ std::vector< Node > activeArgs;
+ computeArgVec2( args, activeArgs, body, qa.d_ipl );
+ return mkForAll( activeArgs, body, qa );
}
Node QuantifiersRewriter::computeAggressiveMiniscoping( std::vector< Node >& args, Node body ){
@@ -1552,19 +1348,14 @@ bool QuantifiersRewriter::doOperation( Node q, int computeOption, QAttributes& q
return is_std;
}else if( computeOption==COMPUTE_AGGRESSIVE_MINISCOPING ){
return options::aggressiveMiniscopeQuant() && is_std;
- }else if( computeOption==COMPUTE_NNF ){
- return true;
}else if( computeOption==COMPUTE_PROCESS_TERMS ){
- return true;
- //return options::iteLiftQuant()!=ITE_LIFT_QUANT_MODE_NONE || options::iteCondVarSplitQuant();
+ return options::condRewriteQuant();
}else if( computeOption==COMPUTE_COND_SPLIT ){
return ( options::iteDtTesterSplitQuant() || options::condVarSplitQuant() ) && !is_strict_trigger;
}else if( computeOption==COMPUTE_PRENEX ){
return options::prenexQuant()!=PRENEX_NONE && !options::aggressiveMiniscopeQuant() && is_std;
}else if( computeOption==COMPUTE_VAR_ELIMINATION ){
return ( options::varElimQuant() || options::dtVarExpandQuant() || options::purifyQuant() ) && is_std;
- //}else if( computeOption==COMPUTE_CNF ){
- // return options::cnfQuant();
}else if( computeOption==COMPUTE_PURIFY_EXPAND ){
return options::purifyQuant() && is_std;
}else{
@@ -1584,11 +1375,9 @@ Node QuantifiersRewriter::computeOperation( Node f, int computeOption, QAttribut
n = computeElimSymbols( n );
}else if( computeOption==COMPUTE_MINISCOPING ){
//return directly
- return computeMiniscoping( f, args, n, qa );
+ return computeMiniscoping( args, n, qa );
}else if( computeOption==COMPUTE_AGGRESSIVE_MINISCOPING ){
return computeAggressiveMiniscoping( args, n );
- }else if( computeOption==COMPUTE_NNF ){
- n = computeNNF( n );
}else if( computeOption==COMPUTE_PROCESS_TERMS ){
std::vector< Node > new_conds;
n = computeProcessTerms( n, args, new_conds, f, qa );
@@ -1602,9 +1391,6 @@ Node QuantifiersRewriter::computeOperation( Node f, int computeOption, QAttribut
n = computePrenex( n, args, true );
}else if( computeOption==COMPUTE_VAR_ELIMINATION ){
n = computeVarElimination( n, args, qa );
- //}else if( computeOption==COMPUTE_CNF ){
- //n = computeCNF( n, args, defs, false );
- //ipl = Node::null();
}else if( computeOption==COMPUTE_PURIFY_EXPAND ){
std::vector< Node > conj;
computePurifyExpand( n, conj, args, qa );
@@ -1738,15 +1524,15 @@ struct ContainsQuantAttributeId {};
typedef expr::Attribute<ContainsQuantAttributeId, uint64_t> ContainsQuantAttribute;
// check if the given node contains a universal quantifier
-bool QuantifiersRewriter::containsQuantifiers(Node n) {
+bool QuantifiersRewriter::containsQuantifiers( Node n ){
if( n.hasAttribute(ContainsQuantAttribute()) ){
return n.getAttribute(ContainsQuantAttribute())==1;
- } else if(n.getKind() == kind::FORALL) {
+ }else if( n.getKind() == kind::FORALL ){
return true;
- } else {
+ }else{
bool cq = false;
for( unsigned i = 0; i < n.getNumChildren(); ++i ){
- if( containsQuantifiers(n[i]) ){
+ if( containsQuantifiers( n[i] ) ){
cq = true;
break;
}
diff --git a/src/theory/quantifiers/quantifiers_rewriter.h b/src/theory/quantifiers/quantifiers_rewriter.h
index 2071d1793..776517109 100644..100755
--- a/src/theory/quantifiers/quantifiers_rewriter.h
+++ b/src/theory/quantifiers/quantifiers_rewriter.h
@@ -38,6 +38,7 @@ public:
static int getPurifyId( Node n );
static int getPurifyIdLit( Node n );
private:
+ static bool addCheckElimChild( std::vector< Node >& children, Node c, Kind k, std::map< Node, bool >& lit_pol, bool& childrenChanged );
static void addNodeToOrBuilder( Node n, NodeBuilder<>& t );
static Node mkForAll( std::vector< Node >& args, Node body, QAttributes& qa );
static void computeArgs( std::vector< Node >& args, std::map< Node, bool >& activeMap, Node n, std::map< Node, bool >& visited );
@@ -46,7 +47,6 @@ private:
static Node computeProcessTerms2( Node body, bool hasPol, bool pol, std::map< Node, bool >& currCond, int nCurrCond,
std::map< Node, Node >& cache, std::map< Node, Node >& icache,
std::vector< Node >& new_vars, std::vector< Node >& new_conds );
- static Node computeClause( Node n );
static void computeDtTesterIteSplit( Node n, std::map< Node, Node >& pcons, std::map< Node, std::map< int, Node > >& ncons, std::vector< Node >& conj );
static bool isConditionalVariableElim( Node n, int pol=0 );
static bool isVariableElim( Node v, Node s, std::map< Node, std::vector< int > >& var_parent );
@@ -57,15 +57,13 @@ private:
static Node computeVarElimination2( Node body, std::vector< Node >& args, QAttributes& qa, std::map< Node, std::vector< int > >& var_parent );
private:
static Node computeElimSymbols( Node body );
- static Node computeMiniscoping( Node f, std::vector< Node >& args, Node body, QAttributes& qa );
+ static Node computeMiniscoping( std::vector< Node >& args, Node body, QAttributes& qa );
static Node computeAggressiveMiniscoping( std::vector< Node >& args, Node body );
- static Node computeNNF( Node body );
//cache is dependent upon currCond, icache is not, new_conds are negated conditions
static Node computeProcessTerms( Node body, std::vector< Node >& new_vars, std::vector< Node >& new_conds, Node q, QAttributes& qa );
static Node computeCondSplit( Node body, QAttributes& qa );
- static Node computeCNF( Node body, std::vector< Node >& args, NodeBuilder<>& defs, bool forcePred );
static Node computePrenex( Node body, std::vector< Node >& args, bool pol );
- static Node computeSplit( Node f, std::vector< Node >& args, Node body );
+ static Node computeSplit( std::vector< Node >& args, Node body, QAttributes& qa );
static Node computeVarElimination( Node body, std::vector< Node >& args, QAttributes& qa );
static Node computePurify( Node body, std::vector< Node >& args, std::map< Node, std::vector< int > >& var_parent );
static void computePurifyExpand( Node body, std::vector< Node >& conj, std::vector< Node >& args, QAttributes& qa );
@@ -74,7 +72,6 @@ private:
COMPUTE_ELIM_SYMBOLS = 0,
COMPUTE_MINISCOPING,
COMPUTE_AGGRESSIVE_MINISCOPING,
- COMPUTE_NNF,
COMPUTE_PROCESS_TERMS,
COMPUTE_PRENEX,
COMPUTE_VAR_ELIMINATION,
diff --git a/src/theory/quantifiers/relevant_domain.cpp b/src/theory/quantifiers/relevant_domain.cpp
index b353fce2f..b4b51fd84 100644..100755
--- a/src/theory/quantifiers/relevant_domain.cpp
+++ b/src/theory/quantifiers/relevant_domain.cpp
@@ -110,7 +110,7 @@ void RelevantDomain::compute(){
for( unsigned i=0; i<sz; i++ ){
Node n = it->second[i];
//if it is a non-redundant term
- if( !n.getAttribute(NoMatchAttribute()) ){
+ if( db->isTermActive( n ) ){
for( unsigned j=0; j<n.getNumChildren(); j++ ){
RDomain * rf = getRDomain( op, j );
rf->addTerm( n[j] );
diff --git a/src/theory/quantifiers/relevant_domain.h b/src/theory/quantifiers/relevant_domain.h
index 2b90520fd..2b90520fd 100644..100755
--- a/src/theory/quantifiers/relevant_domain.h
+++ b/src/theory/quantifiers/relevant_domain.h
diff --git a/src/theory/quantifiers/rewrite_engine.cpp b/src/theory/quantifiers/rewrite_engine.cpp
index 5365dbcfa..2c58b8f77 100644..100755
--- a/src/theory/quantifiers/rewrite_engine.cpp
+++ b/src/theory/quantifiers/rewrite_engine.cpp
@@ -175,7 +175,7 @@ int RewriteEngine::checkRewriteRule( Node f, Theory::Effort e ) {
for( unsigned j=0; j<to_remove.size(); j++ ){
Node ns = d_quantEngine->getSubstitute( to_remove[j], inst );
Trace("rewrite-engine-inst-debug") << "Will remove : " << ns << std::endl;
- ns.setAttribute(NoMatchAttribute(),true);
+ d_quantEngine->getTermDatabase()->setTermInactive( ns );
}
*/
}else{
diff --git a/src/theory/quantifiers/rewrite_engine.h b/src/theory/quantifiers/rewrite_engine.h
index 424530696..424530696 100644..100755
--- a/src/theory/quantifiers/rewrite_engine.h
+++ b/src/theory/quantifiers/rewrite_engine.h
diff --git a/src/theory/quantifiers/symmetry_breaking.cpp b/src/theory/quantifiers/symmetry_breaking.cpp
index 2a2b13583..2a2b13583 100644..100755
--- a/src/theory/quantifiers/symmetry_breaking.cpp
+++ b/src/theory/quantifiers/symmetry_breaking.cpp
diff --git a/src/theory/quantifiers/symmetry_breaking.h b/src/theory/quantifiers/symmetry_breaking.h
index 38fea4f45..e682955e7 100644..100755
--- a/src/theory/quantifiers/symmetry_breaking.h
+++ b/src/theory/quantifiers/symmetry_breaking.h
@@ -42,9 +42,7 @@ class SubsortSymmetryBreaker {
typedef context::CDHashMap<Node, bool, NodeHashFunction> NodeBoolMap;
typedef context::CDHashMap<Node, int, NodeHashFunction> NodeIntMap;
typedef context::CDHashMap<Node, Node, NodeHashFunction> NodeNodeMap;
- //typedef context::CDChunkList<int> IntList;
typedef context::CDList<Node> NodeList;
- typedef context::CDHashMap<Node, NodeList*, NodeHashFunction> NodeListMap;
private:
/** quantifiers engine */
QuantifiersEngine* d_qe;
diff --git a/src/theory/quantifiers/term_database.cpp b/src/theory/quantifiers/term_database.cpp
index 8b09d8e5d..d3a5e178f 100644..100755
--- a/src/theory/quantifiers/term_database.cpp
+++ b/src/theory/quantifiers/term_database.cpp
@@ -84,13 +84,13 @@ void TermArgTrie::debugPrint( const char * c, Node n, unsigned depth ) {
}
}
-TermDb::TermDb( context::Context* c, context::UserContext* u, QuantifiersEngine* qe ) : d_quantEngine( qe ), d_op_id_count( 0 ), d_typ_id_count( 0 ) {
+TermDb::TermDb( context::Context* c, context::UserContext* u, QuantifiersEngine* qe ) : d_quantEngine( qe ), d_inactive_map( c ), d_op_id_count( 0 ), d_typ_id_count( 0 ) {
d_true = NodeManager::currentNM()->mkConst( true );
d_false = NodeManager::currentNM()->mkConst( false );
d_zero = NodeManager::currentNM()->mkConst( Rational( 0 ) );
d_one = NodeManager::currentNM()->mkConst( Rational( 1 ) );
if( options::ceGuidedInst() ){
- d_sygus_tdb = new TermDbSygus;
+ d_sygus_tdb = new TermDbSygus( c, qe );
}else{
d_sygus_tdb = NULL;
}
@@ -163,9 +163,18 @@ void TermDb::addTerm( Node n, std::set< Node >& added, bool withinQuant, bool wi
//if this is an atomic trigger, consider adding it
if( inst::Trigger::isAtomicTrigger( n ) ){
Trace("term-db") << "register term in db " << n << std::endl;
+ if( options::finiteModelFind() ){
+ computeModelBasisArgAttribute( n );
+ }
+
Node op = getMatchOperator( n );
+ Trace("term-db-debug") << " match operator is : " << op << std::endl;
d_op_map[op].push_back( n );
added.insert( n );
+
+ if( d_sygus_tdb ){
+ d_sygus_tdb->registerEvalTerm( n );
+ }
if( options::eagerInstQuant() ){
for( unsigned i=0; i<n.getNumChildren(); i++ ){
@@ -178,6 +187,8 @@ void TermDb::addTerm( Node n, std::set< Node >& added, bool withinQuant, bool wi
}
}
}
+ }else{
+ setTermInactive( n );
}
rec = true;
}
@@ -210,7 +221,7 @@ void TermDb::computeUfEqcTerms( TNode f ) {
for( unsigned i=0; i<d_op_map[f].size(); i++ ){
TNode n = d_op_map[f][i];
if( hasTermCurrent( n ) ){
- if( !n.getAttribute(NoMatchAttribute()) ){
+ if( isTermActive( n ) ){
computeArgReps( n );
TNode r = ee->hasTerm( n ) ? ee->getRepresentative( n ) : n;
d_func_map_eqc_trie[f].d_data[r].addTerm( n, d_arg_reps[n] );
@@ -220,7 +231,84 @@ void TermDb::computeUfEqcTerms( TNode f ) {
}
}
+void TermDb::computeUfTerms( TNode f ) {
+ if( d_op_nonred_count.find( f )==d_op_nonred_count.end() ){
+ d_op_nonred_count[ f ] = 0;
+ std::map< Node, std::vector< Node > >::iterator it = d_op_map.find( f );
+ if( it!=d_op_map.end() ){
+ eq::EqualityEngine* ee = d_quantEngine->getMasterEqualityEngine();
+ Trace("term-db-debug") << "Adding terms for operator " << f << std::endl;
+ unsigned congruentCount = 0;
+ unsigned nonCongruentCount = 0;
+ unsigned alreadyCongruentCount = 0;
+ unsigned relevantCount = 0;
+ for( unsigned i=0; i<it->second.size(); i++ ){
+ Node n = it->second[i];
+ //to be added to term index, term must be relevant, and exist in EE
+ if( hasTermCurrent( n ) && ee->hasTerm( n ) ){
+ relevantCount++;
+ if( isTermActive( n ) ){
+ computeArgReps( n );
+
+ Trace("term-db-debug") << "Adding term " << n << " with arg reps : ";
+ for( unsigned i=0; i<d_arg_reps[n].size(); i++ ){
+ Trace("term-db-debug") << d_arg_reps[n][i] << " ";
+ if( std::find( d_func_map_rel_dom[f][i].begin(),
+ d_func_map_rel_dom[f][i].end(), d_arg_reps[n][i] ) == d_func_map_rel_dom[f][i].end() ){
+ d_func_map_rel_dom[f][i].push_back( d_arg_reps[n][i] );
+ }
+ }
+ Trace("term-db-debug") << std::endl;
+ Trace("term-db-debug") << " and value : " << ee->getRepresentative( n ) << std::endl;
+ Node at = d_func_map_trie[ f ].addOrGetTerm( n, d_arg_reps[n] );
+ Trace("term-db-debug2") << "...add term returned " << at << std::endl;
+ if( at!=n && ee->areEqual( at, n ) ){
+ setTermInactive( n );
+ Trace("term-db-debug") << n << " is redundant." << std::endl;
+ congruentCount++;
+ }else{
+ if( at!=n && ee->areDisequal( at, n, false ) ){
+ std::vector< Node > lits;
+ lits.push_back( NodeManager::currentNM()->mkNode( at.getType().isBoolean() ? IFF : EQUAL, at, n ) );
+ for( unsigned i=0; i<at.getNumChildren(); i++ ){
+ if( at[i]!=n[i] ){
+ lits.push_back( NodeManager::currentNM()->mkNode( at[i].getType().isBoolean() ? IFF : EQUAL, at[i], n[i] ).negate() );
+ }
+ }
+ Node lem = lits.size()==1 ? lits[0] : NodeManager::currentNM()->mkNode( OR, lits );
+ if( Trace.isOn("term-db-lemma") ){
+ Trace("term-db-lemma") << "Disequal congruent terms : " << at << " " << n << "!!!!" << std::endl;
+ if( !d_quantEngine->getTheoryEngine()->needCheck() ){
+ Trace("term-db-lemma") << " all theories passed with no lemmas." << std::endl;
+ }
+ Trace("term-db-lemma") << " add lemma : " << lem << std::endl;
+ }
+ d_quantEngine->addLemma( lem );
+ d_consistent_ee = false;
+ return;
+ }
+ nonCongruentCount++;
+ d_op_nonred_count[ f ]++;
+ }
+ }else{
+ Trace("term-db-debug") << n << " is already redundant." << std::endl;
+ alreadyCongruentCount++;
+ }
+ }else{
+ Trace("term-db-debug") << n << " is not relevant." << std::endl;
+ }
+ }
+ if( Trace.isOn("tdb") ){
+ Trace("tdb") << "Term db size [" << f << "] : " << nonCongruentCount << " / ";
+ Trace("tdb") << ( nonCongruentCount + congruentCount ) << " / " << ( nonCongruentCount + congruentCount + alreadyCongruentCount ) << " / ";
+ Trace("tdb") << relevantCount << " / " << it->second.size() << std::endl;
+ }
+ }
+ }
+}
+
bool TermDb::inRelevantDomain( TNode f, unsigned i, TNode r ) {
+ computeUfTerms( f );
Assert( d_quantEngine->getTheoryEngine()->getMasterEqualityEngine()->getRepresentative( r )==r );
std::map< Node, std::map< unsigned, std::vector< Node > > >::iterator it = d_func_map_rel_dom.find( f );
if( it != d_func_map_rel_dom.end() ){
@@ -237,25 +325,23 @@ bool TermDb::inRelevantDomain( TNode f, unsigned i, TNode r ) {
//return a term n' equivalent to n
// maximal subterms of n' are representatives in the equality engine qy
-Node TermDb::evaluateTerm2( TNode n, std::map< TNode, Node >& visited, EqualityQuery * qy ) {
+Node TermDb::evaluateTerm2( TNode n, std::map< TNode, Node >& visited, EqualityQuery * qy, bool useEntailmentTests ) {
std::map< TNode, Node >::iterator itv = visited.find( n );
if( itv != visited.end() ){
return itv->second;
}
Trace("term-db-eval") << "evaluate term : " << n << std::endl;
- Node ret;
- if( n.getKind()==BOUND_VARIABLE ){
- return n;
+ Node ret = n;
+ if( n.getKind()==FORALL || n.getKind()==BOUND_VARIABLE ){
+ //do nothing
}else if( !qy->hasTerm( n ) ){
//term is not known to be equal to a representative in equality engine, evaluate it
- if( n.getKind()==FORALL ){
- ret = Node::null();
- }else if( n.hasOperator() ){
+ if( n.hasOperator() ){
TNode f = getMatchOperator( n );
std::vector< TNode > args;
bool ret_set = false;
for( unsigned i=0; i<n.getNumChildren(); i++ ){
- TNode c = evaluateTerm2( n[i], visited, qy );
+ TNode c = evaluateTerm2( n[i], visited, qy, useEntailmentTests );
if( c.isNull() ){
ret = Node::null();
ret_set = true;
@@ -267,7 +353,7 @@ Node TermDb::evaluateTerm2( TNode n, std::map< TNode, Node >& visited, EqualityQ
ret_set = true;
break;
}else if( n.getKind()==kind::ITE && i==0 ){
- ret = evaluateTerm2( n[ c==d_true ? 1 : 2], visited, qy );
+ ret = evaluateTerm2( n[ c==d_true ? 1 : 2], visited, qy, useEntailmentTests );
ret_set = true;
break;
}
@@ -295,6 +381,22 @@ Node TermDb::evaluateTerm2( TNode n, std::map< TNode, Node >& visited, EqualityQ
}
ret = NodeManager::currentNM()->mkNode( n.getKind(), args );
ret = Rewriter::rewrite( ret );
+ if( ret.getKind()==kind::EQUAL ){
+ if( qy->areDisequal( ret[0], ret[1] ) ){
+ ret = d_false;
+ }
+ }
+ if( useEntailmentTests ){
+ if( ret.getKind()==kind::EQUAL || ret.getKind()==kind::GEQ ){
+ for( unsigned j=0; j<2; j++ ){
+ std::pair<bool, Node> et = d_quantEngine->getTheoryEngine()->entailmentCheck(THEORY_OF_TYPE_BASED, j==0 ? ret : ret.negate() );
+ if( et.first ){
+ ret = j==0 ? d_true : d_false;
+ break;
+ }
+ }
+ }
+ }
}
}
}
@@ -316,14 +418,16 @@ TNode TermDb::getEntailedTerm2( TNode n, std::map< TNode, TNode >& subs, bool su
return n;
}else if( n.getKind()==BOUND_VARIABLE ){
if( hasSubs ){
- Assert( subs.find( n )!=subs.end() );
- Trace("term-db-entail") << "...substitution is : " << subs[n] << std::endl;
- if( subsRep ){
- Assert( qy->getEngine()->hasTerm( subs[n] ) );
- Assert( qy->getEngine()->getRepresentative( subs[n] )==subs[n] );
- return subs[n];
- }else{
- return getEntailedTerm2( subs[n], subs, subsRep, hasSubs, qy );
+ std::map< TNode, TNode >::iterator it = subs.find( n );
+ if( it!=subs.end() ){
+ Trace("term-db-entail") << "...substitution is : " << it->second << std::endl;
+ if( subsRep ){
+ Assert( qy->getEngine()->hasTerm( it->second ) );
+ Assert( qy->getEngine()->getRepresentative( it->second )==it->second );
+ return it->second;
+ }else{
+ return getEntailedTerm2( it->second, subs, subsRep, hasSubs, qy );
+ }
}
}
}else if( n.getKind()==ITE ){
@@ -355,12 +459,12 @@ TNode TermDb::getEntailedTerm2( TNode n, std::map< TNode, TNode >& subs, bool su
return TNode::null();
}
-Node TermDb::evaluateTerm( TNode n, EqualityQuery * qy ) {
+Node TermDb::evaluateTerm( TNode n, EqualityQuery * qy, bool useEntailmentTests ) {
if( qy==NULL ){
qy = d_quantEngine->getEqualityQuery();
}
std::map< TNode, Node > visited;
- return evaluateTerm2( n, visited, qy );
+ return evaluateTerm2( n, visited, qy, useEntailmentTests );
}
TNode TermDb::getEntailedTerm( TNode n, std::map< TNode, TNode >& subs, bool subsRep, EqualityQuery * qy ) {
@@ -436,6 +540,8 @@ bool TermDb::isEntailed2( TNode n, std::map< TNode, TNode >& subs, bool subsRep,
return qy->getEngine()->getRepresentative( n1 ) == ( pol ? d_true : d_false );
}
}
+ }else if( n.getKind()==FORALL && !pol ){
+ return isEntailed2( n[1], subs, subsRep, hasSubs, pol, qy );
}
return false;
}
@@ -457,6 +563,18 @@ bool TermDb::isEntailed( TNode n, std::map< TNode, TNode >& subs, bool subsRep,
return isEntailed2( n, subs, subsRep, true, pol, qy );
}
+bool TermDb::isTermActive( Node n ) {
+ return d_inactive_map.find( n )==d_inactive_map.end();
+ //return !n.getAttribute(NoMatchAttribute());
+}
+
+void TermDb::setTermInactive( Node n ) {
+ d_inactive_map[n] = true;
+ //Trace("term-db-debug2") << "set no match attribute" << std::endl;
+ //NoMatchAttribute nma;
+ //n.setAttribute(nma,true);
+}
+
bool TermDb::hasTermCurrent( Node n, bool useMode ) {
if( !useMode ){
return d_has_map.find( n )!=d_has_map.end();
@@ -556,10 +674,6 @@ void TermDb::presolve() {
}
bool TermDb::reset( Theory::Effort effort ){
- int nonCongruentCount = 0;
- int congruentCount = 0;
- int alreadyCongruentCount = 0;
- int nonRelevantCount = 0;
d_op_nonred_count.clear();
d_arg_reps.clear();
d_func_map_trie.clear();
@@ -614,89 +728,20 @@ bool TermDb::reset( Theory::Effort effort ){
}
}
+/*
//rebuild d_func/pred_map_trie for each operation, this will calculate all congruent terms
for( std::map< Node, std::vector< Node > >::iterator it = d_op_map.begin(); it != d_op_map.end(); ++it ){
- d_op_nonred_count[ it->first ] = 0;
- Trace("term-db-debug") << "Adding terms for operator " << it->first << std::endl;
- for( unsigned i=0; i<it->second.size(); i++ ){
- Node n = it->second[i];
- //to be added to term index, term must be relevant, and exist in EE
- if( hasTermCurrent( n ) && ee->hasTerm( n ) ){
- if( !n.getAttribute(NoMatchAttribute()) ){
- if( options::finiteModelFind() ){
- computeModelBasisArgAttribute( n );
- }
- computeArgReps( n );
-
- Trace("term-db-debug") << "Adding term " << n << " with arg reps : ";
- for( unsigned i=0; i<d_arg_reps[n].size(); i++ ){
- Trace("term-db-debug") << d_arg_reps[n][i] << " ";
- if( std::find( d_func_map_rel_dom[it->first][i].begin(),
- d_func_map_rel_dom[it->first][i].end(), d_arg_reps[n][i] ) == d_func_map_rel_dom[it->first][i].end() ){
- d_func_map_rel_dom[it->first][i].push_back( d_arg_reps[n][i] );
- }
- }
- Trace("term-db-debug") << std::endl;
- if( ee->hasTerm( n ) ){
- Trace("term-db-debug") << " and value : " << ee->getRepresentative( n ) << std::endl;
- }
- Node at = d_func_map_trie[ it->first ].addOrGetTerm( n, d_arg_reps[n] );
- if( at!=n && ee->areEqual( at, n ) ){
- NoMatchAttribute nma;
- n.setAttribute(nma,true);
- Trace("term-db-debug") << n << " is redundant." << std::endl;
- congruentCount++;
- }else{
- if( at!=n && ee->areDisequal( at, n, false ) ){
- std::vector< Node > lits;
- lits.push_back( NodeManager::currentNM()->mkNode( at.getType().isBoolean() ? IFF : EQUAL, at, n ) );
- for( unsigned i=0; i<at.getNumChildren(); i++ ){
- if( at[i]!=n[i] ){
- lits.push_back( NodeManager::currentNM()->mkNode( at[i].getType().isBoolean() ? IFF : EQUAL, at[i], n[i] ).negate() );
- }
- }
- Node lem = lits.size()==1 ? lits[0] : NodeManager::currentNM()->mkNode( OR, lits );
- if( Trace.isOn("term-db-lemma") ){
- Trace("term-db-lemma") << "Disequal congruent terms : " << at << " " << n << "!!!!" << std::endl;
- if( !d_quantEngine->getTheoryEngine()->needCheck() ){
- Trace("term-db-lemma") << " all theories passed with no lemmas." << std::endl;
- }
- Trace("term-db-lemma") << " add lemma : " << lem << std::endl;
- }
- d_quantEngine->addLemma( lem );
- d_consistent_ee = false;
- return false;
- }
- nonCongruentCount++;
- d_op_nonred_count[ it->first ]++;
- }
- }else{
- Trace("term-db-debug") << n << " is already redundant." << std::endl;
- congruentCount++;
- alreadyCongruentCount++;
- }
- }else{
- Trace("term-db-debug") << n << " is not relevant." << std::endl;
- nonRelevantCount++;
- }
- }
- }
- Trace("term-db-stats") << "TermDb: Reset" << std::endl;
- Trace("term-db-stats") << "Non-Congruent/Congruent/Non-Relevant = ";
- Trace("term-db-stats") << nonCongruentCount << " / " << congruentCount << " (" << alreadyCongruentCount << ") / " << nonRelevantCount << std::endl;
- if( Trace.isOn("term-db-index") ){
- Trace("term-db-index") << "functions : " << std::endl;
- for( std::map< Node, std::vector< Node > >::iterator it = d_op_map.begin(); it != d_op_map.end(); ++it ){
- if( it->second.size()>0 ){
- Trace("term-db-index") << "- " << it->first << std::endl;
- d_func_map_trie[ it->first ].debugPrint("term-db-index", it->second[0]);
- }
+ computeUfTerms( it->first );
+ if( !d_consistent_ee ){
+ return false;
}
}
+*/
return true;
}
TermArgTrie * TermDb::getTermArgTrie( Node f ) {
+ computeUfTerms( f );
std::map< Node, TermArgTrie >::iterator itut = d_func_map_trie.find( f );
if( itut!=d_func_map_trie.end() ){
return &itut->second;
@@ -725,11 +770,18 @@ TermArgTrie * TermDb::getTermArgTrie( Node eqc, Node f ) {
}
TNode TermDb::getCongruentTerm( Node f, Node n ) {
- computeArgReps( n );
- return d_func_map_trie[f].existsTerm( d_arg_reps[n] );
+ computeUfTerms( f );
+ std::map< Node, TermArgTrie >::iterator itut = d_func_map_trie.find( f );
+ if( itut!=d_func_map_trie.end() ){
+ computeArgReps( n );
+ return itut->second.existsTerm( d_arg_reps[n] );
+ }else{
+ return TNode::null();
+ }
}
TNode TermDb::getCongruentTerm( Node f, std::vector< TNode >& args ) {
+ computeUfTerms( f );
return d_func_map_trie[f].existsTerm( args );
}
@@ -822,6 +874,7 @@ void TermDb::makeInstantiationConstantsFor( Node q ){
Debug("quantifiers-engine") << "Instantiation constants for " << q << " : " << std::endl;
for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
d_vars[q].push_back( q[0][i] );
+ d_var_num[q][q[0][i]] = i;
//make instantiation constants
Node ic = NodeManager::currentNM()->mkInstConstant( q[0][i].getType() );
d_inst_constants_map[ic] = q;
@@ -832,9 +885,8 @@ void TermDb::makeInstantiationConstantsFor( Node q ){
ic.setAttribute( ivna, i );
InstConstantAttribute ica;
ic.setAttribute( ica, q );
- //also set the no-match attribute
- NoMatchAttribute nma;
- ic.setAttribute(nma,true);
+ //also set the term inactive
+ setTermInactive( ic );
}
}
}
@@ -892,11 +944,6 @@ Node TermDb::getInstConstAttr( Node n ) {
}
InstConstantAttribute ica;
n.setAttribute(ica, q);
- if( !q.isNull() ){
- //also set the no-match attribute
- NoMatchAttribute nma;
- n.setAttribute(nma,true);
- }
}
return n.getAttribute(InstConstantAttribute());
}
@@ -1005,9 +1052,12 @@ Node TermDb::getCounterexampleLiteral( Node q ){
Node TermDb::getInstConstantNode( Node n, Node q ){
makeInstantiationConstantsFor( q );
- Node n2 = n.substitute( d_vars[q].begin(), d_vars[q].end(),
- d_inst_constants[q].begin(), d_inst_constants[q].end() );
- return n2;
+ return n.substitute( d_vars[q].begin(), d_vars[q].end(), d_inst_constants[q].begin(), d_inst_constants[q].end() );
+}
+
+Node TermDb::getVariableNode( Node n, Node q ) {
+ makeInstantiationConstantsFor( q );
+ return n.substitute( d_inst_constants[q].begin(), d_inst_constants[q].end(), d_vars[q].begin(), d_vars[q].end() );
}
Node TermDb::getInstantiatedNode( Node n, Node q, std::vector< Node >& terms ) {
@@ -1512,7 +1562,7 @@ struct sortTermOrder {
//this function makes a canonical representation of a term (
// - orders variables left to right
// - if apply_torder, then sort direct subterms of commutative operators
-Node TermDb::getCanonicalTerm( TNode n, std::map< TypeNode, unsigned >& var_count, std::map< TNode, TNode >& subs, bool apply_torder ) {
+Node TermDb::getCanonicalTerm( TNode n, std::map< TypeNode, unsigned >& var_count, std::map< TNode, TNode >& subs, bool apply_torder, std::map< TNode, Node >& visited ) {
Trace("canon-term-debug") << "Get canonical term for " << n << std::endl;
if( n.getKind()==BOUND_VARIABLE ){
std::map< TNode, TNode >::iterator it = subs.find( n );
@@ -1529,32 +1579,38 @@ Node TermDb::getCanonicalTerm( TNode n, std::map< TypeNode, unsigned >& var_coun
return it->second;
}
}else if( n.getNumChildren()>0 ){
- //collect children
- Trace("canon-term-debug") << "Collect children" << std::endl;
- std::vector< Node > cchildren;
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- cchildren.push_back( n[i] );
- }
- //if applicable, first sort by term order
- if( apply_torder && isComm( n.getKind() ) ){
- Trace("canon-term-debug") << "Sort based on commutative operator " << n.getKind() << std::endl;
- sortTermOrder sto;
- sto.d_tdb = this;
- std::sort( cchildren.begin(), cchildren.end(), sto );
- }
- //now make canonical
- Trace("canon-term-debug") << "Make canonical children" << std::endl;
- for( unsigned i=0; i<cchildren.size(); i++ ){
- cchildren[i] = getCanonicalTerm( cchildren[i], var_count, subs, apply_torder );
- }
- if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){
- Trace("canon-term-debug") << "Insert operator " << n.getOperator() << std::endl;
- cchildren.insert( cchildren.begin(), n.getOperator() );
- }
- Trace("canon-term-debug") << "...constructing for " << n << "." << std::endl;
- Node ret = NodeManager::currentNM()->mkNode( n.getKind(), cchildren );
- Trace("canon-term-debug") << "...constructed " << ret << " for " << n << "." << std::endl;
- return ret;
+ std::map< TNode, Node >::iterator it = visited.find( n );
+ if( it!=visited.end() ){
+ return it->second;
+ }else{
+ //collect children
+ Trace("canon-term-debug") << "Collect children" << std::endl;
+ std::vector< Node > cchildren;
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ cchildren.push_back( n[i] );
+ }
+ //if applicable, first sort by term order
+ if( apply_torder && isComm( n.getKind() ) ){
+ Trace("canon-term-debug") << "Sort based on commutative operator " << n.getKind() << std::endl;
+ sortTermOrder sto;
+ sto.d_tdb = this;
+ std::sort( cchildren.begin(), cchildren.end(), sto );
+ }
+ //now make canonical
+ Trace("canon-term-debug") << "Make canonical children" << std::endl;
+ for( unsigned i=0; i<cchildren.size(); i++ ){
+ cchildren[i] = getCanonicalTerm( cchildren[i], var_count, subs, apply_torder, visited );
+ }
+ if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){
+ Trace("canon-term-debug") << "Insert operator " << n.getOperator() << std::endl;
+ cchildren.insert( cchildren.begin(), n.getOperator() );
+ }
+ Trace("canon-term-debug") << "...constructing for " << n << "." << std::endl;
+ Node ret = NodeManager::currentNM()->mkNode( n.getKind(), cchildren );
+ Trace("canon-term-debug") << "...constructed " << ret << " for " << n << "." << std::endl;
+ visited[n] = ret;
+ return ret;
+ }
}else{
Trace("canon-term-debug") << "...return 0-child term." << std::endl;
return n;
@@ -1564,7 +1620,8 @@ Node TermDb::getCanonicalTerm( TNode n, std::map< TypeNode, unsigned >& var_coun
Node TermDb::getCanonicalTerm( TNode n, bool apply_torder ){
std::map< TypeNode, unsigned > var_count;
std::map< TNode, TNode > subs;
- return getCanonicalTerm( n, var_count, subs, apply_torder );
+ std::map< TNode, Node > visited;
+ return getCanonicalTerm( n, var_count, subs, apply_torder, visited );
}
void TermDb::getVtsTerms( std::vector< Node >& t, bool isFree, bool create, bool inc_delta ) {
@@ -1790,6 +1847,18 @@ bool TermDb::getEnsureTypeCondition( Node n, TypeNode tn, std::vector< Node >& c
}
}
+void TermDb::getRelevancyCondition( Node n, std::vector< Node >& cond ) {
+ if( n.getKind()==APPLY_SELECTOR_TOTAL ){
+ unsigned scindex = Datatype::cindexOf(n.getOperator().toExpr());
+ const Datatype& dt = ((DatatypeType)(n[0].getType()).toType()).getDatatype();
+ Node rc = NodeManager::currentNM()->mkNode( APPLY_TESTER, Node::fromExpr( dt[scindex].getTester() ), n[0] ).negate();
+ if( std::find( cond.begin(), cond.end(), rc )==cond.end() ){
+ cond.push_back( rc );
+ }
+ getRelevancyCondition( n[0], cond );
+ }
+}
+
bool TermDb::containsTerm2( Node n, Node t, std::map< Node, bool >& visited ) {
if( n==t ){
return true;
@@ -1856,7 +1925,7 @@ bool TermDb::containsUninterpretedConstant( Node n ) {
bool ret = false;
if( n.getKind()==UNINTERPRETED_CONSTANT ){
ret = true;
- }else{
+ }else{
for( unsigned i=0; i<n.getNumChildren(); i++ ){
if( containsUninterpretedConstant( n[i] ) ){
ret = true;
@@ -1884,7 +1953,8 @@ Node TermDb::simpleNegate( Node n ){
bool TermDb::isAssoc( Kind k ) {
return k==PLUS || k==MULT || k==AND || k==OR || k==XOR || k==IFF ||
- k==BITVECTOR_PLUS || k==BITVECTOR_MULT || k==BITVECTOR_AND || k==BITVECTOR_OR || k==BITVECTOR_XOR || k==BITVECTOR_XNOR || k==BITVECTOR_CONCAT;
+ k==BITVECTOR_PLUS || k==BITVECTOR_MULT || k==BITVECTOR_AND || k==BITVECTOR_OR || k==BITVECTOR_XOR || k==BITVECTOR_XNOR || k==BITVECTOR_CONCAT ||
+ k==STRING_CONCAT;
}
bool TermDb::isComm( Kind k ) {
@@ -2184,11 +2254,15 @@ bool TermDb::isQAttrQuantElimPartial( Node q ) {
}
}
-TermDbSygus::TermDbSygus(){
+TermDbSygus::TermDbSygus( context::Context* c, QuantifiersEngine* qe ) : d_quantEngine( qe ){
d_true = NodeManager::currentNM()->mkConst( true );
d_false = NodeManager::currentNM()->mkConst( false );
}
+bool TermDbSygus::reset( Theory::Effort e ) {
+ return true;
+}
+
TNode TermDbSygus::getVar( TypeNode tn, int i ) {
while( i>=(int)d_fv[tn].size() ){
std::stringstream ss;
@@ -2400,8 +2474,8 @@ Node TermDbSygus::sygusToBuiltin( Node n, TypeNode tn ) {
std::map< Node, Node >::iterator it = d_sygus_to_builtin[tn].find( n );
if( it==d_sygus_to_builtin[tn].end() ){
Trace("sygus-db-debug") << "SygusToBuiltin : compute for " << n << ", type = " << tn << std::endl;
- Assert( n.getKind()==APPLY_CONSTRUCTOR );
const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
+ Assert( n.getKind()==APPLY_CONSTRUCTOR );
unsigned i = Datatype::indexOf( n.getOperator().toExpr() );
Assert( n.getNumChildren()==dt[i].getNumArgs() );
std::map< TypeNode, int > var_count;
@@ -3051,6 +3125,7 @@ void TermDbSygus::printSygusTerm( std::ostream& out, Node n, std::vector< Node >
std::string name = std::string( str.begin() + found +1, str.end() );
out << name;
}else{
+ Trace("ajr-temp") << "[[print operator " << op << "]]" << std::endl;
out << op;
}
if( n.getNumChildren()>0 ){
@@ -3118,3 +3193,91 @@ void TermDbSygus::printSygusTerm( std::ostream& out, Node n, std::vector< Node >
out << n;
}
}
+
+Node TermDbSygus::getAnchor( Node n ) {
+ if( n.getKind()==APPLY_SELECTOR_TOTAL ){
+ return getAnchor( n[0] );
+ }else{
+ return n;
+ }
+}
+
+void TermDbSygus::registerEvalTerm( Node n ) {
+ if( options::sygusDirectEval() ){
+ if( n.getKind()==APPLY_UF && !n.getType().isBoolean() ){
+ Trace("sygus-eager") << "TermDbSygus::eager: Register eval term : " << n << std::endl;
+ TypeNode tn = n[0].getType();
+ if( datatypes::DatatypesRewriter::isTypeDatatype(tn) ){
+ const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
+ if( dt.isSygus() ){
+ Node f = n.getOperator();
+ Trace("sygus-eager") << "...the evaluation function is : " << f << std::endl;
+ if( n[0].getKind()!=APPLY_CONSTRUCTOR ){
+ d_evals[n[0]].push_back( n );
+ TypeNode tn = n[0].getType();
+ Assert( datatypes::DatatypesRewriter::isTypeDatatype(tn) );
+ const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
+ Node var_list = Node::fromExpr( dt.getSygusVarList() );
+ Assert( dt.isSygus() );
+ d_eval_args[n[0]].push_back( std::vector< Node >() );
+ for( unsigned j=1; j<n.getNumChildren(); j++ ){
+ if( var_list[j-1].getType().isBoolean() ){
+ //TODO: remove this case when boolean term conversion is eliminated
+ Node c = NodeManager::currentNM()->mkConst(BitVector(1u, 1u));
+ d_eval_args[n[0]].back().push_back( n[j].eqNode( c ) );
+ }else{
+ d_eval_args[n[0]].back().push_back( n[j] );
+ }
+ }
+ Node a = getAnchor( n[0] );
+ d_subterms[a][n[0]] = true;
+ }
+ }
+ }
+ }
+ }
+}
+
+void TermDbSygus::registerModelValue( Node a, Node v, std::vector< Node >& lems ) {
+ std::map< Node, std::map< Node, bool > >::iterator its = d_subterms.find( a );
+ if( its!=d_subterms.end() ){
+ Trace("sygus-eager") << "registerModelValue : " << a << ", has " << its->second.size() << " registered subterms." << std::endl;
+ for( std::map< Node, bool >::iterator itss = its->second.begin(); itss != its->second.end(); ++itss ){
+ Node n = itss->first;
+ Trace("sygus-eager-debug") << "...process : " << n << std::endl;
+ std::map< Node, std::vector< std::vector< Node > > >::iterator it = d_eval_args.find( n );
+ if( it!=d_eval_args.end() && !it->second.empty() ){
+ TNode at = a;
+ TNode vt = v;
+ Node vn = n.substitute( at, vt );
+ vn = Rewriter::rewrite( vn );
+ unsigned start = d_node_mv_args_proc[n][vn];
+ Node antec = n.eqNode( vn ).negate();
+ TypeNode tn = n.getType();
+ Assert( datatypes::DatatypesRewriter::isTypeDatatype(tn) );
+ const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
+ Assert( dt.isSygus() );
+ Trace("sygus-eager") << "TermDbSygus::eager: Register model value : " << vn << " for " << n << std::endl;
+ Trace("sygus-eager") << "...it has " << it->second.size() << " evaluations, already processed " << start << "." << std::endl;
+ Node bTerm = d_quantEngine->getTermDatabaseSygus()->sygusToBuiltin( vn, tn );
+ Trace("sygus-eager") << "Built-in term : " << bTerm << std::endl;
+ std::vector< Node > vars;
+ Node var_list = Node::fromExpr( dt.getSygusVarList() );
+ for( unsigned j=0; j<var_list.getNumChildren(); j++ ){
+ vars.push_back( var_list[j] );
+ }
+ //for each evaluation
+ for( unsigned i=start; i<it->second.size(); i++ ){
+ Assert( vars.size()==it->second[i].size() );
+ Node sBTerm = bTerm.substitute( vars.begin(), vars.end(), it->second[i].begin(), it->second[i].end() );
+ Node lem = NodeManager::currentNM()->mkNode( n.getType().isBoolean() ? IFF : EQUAL, d_evals[n][i], sBTerm );
+ lem = NodeManager::currentNM()->mkNode( OR, antec, lem );
+ Trace("sygus-eager") << "Lemma : " << lem << std::endl;
+ lems.push_back( lem );
+ }
+ d_node_mv_args_proc[n][vn] = it->second.size();
+ }
+ }
+ }
+}
+
diff --git a/src/theory/quantifiers/term_database.h b/src/theory/quantifiers/term_database.h
index a62b343a2..7ab3668eb 100644..100755
--- a/src/theory/quantifiers/term_database.h
+++ b/src/theory/quantifiers/term_database.h
@@ -47,15 +47,6 @@ typedef expr::Attribute< SygusAttributeId, bool > SygusAttribute;
struct SynthesisAttributeId {};
typedef expr::Attribute< SynthesisAttributeId, bool > SynthesisAttribute;
-/** Attribute true for nodes that should not be used for matching */
-struct NoMatchAttributeId {};
-/** use the special for boolean flag */
-typedef expr::Attribute< NoMatchAttributeId,
- bool,
- expr::attr::NullCleanupStrategy,
- true // context dependent
- > NoMatchAttribute;
-
// attribute for "contains instantiation constants from"
struct InstConstantAttributeId {};
typedef expr::Attribute<InstConstantAttributeId, Node> InstConstantAttribute;
@@ -179,6 +170,7 @@ class TermDb : public QuantifiersUtil {
friend class ::CVC4::theory::quantifiers::ConjectureGenerator;
friend class ::CVC4::theory::quantifiers::TermGenEnv;
typedef context::CDHashMap<Node, int, NodeHashFunction> NodeIntMap;
+ typedef context::CDHashMap<Node, bool, NodeHashFunction> NodeBoolMap;
private:
/** reference to the quantifiers engine */
QuantifiersEngine* d_quantEngine;
@@ -211,6 +203,8 @@ private:
std::map< Node, std::vector< Node > > d_op_map;
/** map from type nodes to terms of that type */
std::map< TypeNode, std::vector< Node > > d_type_map;
+ /** inactive map */
+ NodeBoolMap d_inactive_map;
/** count number of non-redundant ground terms per operator */
std::map< Node, int > d_op_nonred_count;
@@ -228,7 +222,7 @@ private:
/** set has term */
void setHasTerm( Node n );
/** evaluate term */
- Node evaluateTerm2( TNode n, std::map< TNode, Node >& visited, EqualityQuery * qy );
+ Node evaluateTerm2( TNode n, std::map< TNode, Node >& visited, EqualityQuery * qy, bool useEntailmentTests );
TNode getEntailedTerm2( TNode n, std::map< TNode, TNode >& subs, bool subsRep, bool hasSubs, EqualityQuery * qy );
bool isEntailed2( TNode n, std::map< TNode, TNode >& subs, bool subsRep, bool hasSubs, bool pol, EqualityQuery * qy );
public:
@@ -254,18 +248,23 @@ public:
void computeArgReps( TNode n );
/** compute uf eqc terms */
void computeUfEqcTerms( TNode f );
+ /** compute uf terms */
+ void computeUfTerms( TNode f );
/** in relevant domain */
bool inRelevantDomain( TNode f, unsigned i, TNode r );
/** evaluate a term under a substitution. Return representative in EE if possible.
* subsRep is whether subs contains only representatives
*/
- Node evaluateTerm( TNode n, EqualityQuery * qy = NULL );
+ Node evaluateTerm( TNode n, EqualityQuery * qy = NULL, bool useEntailmentTests = false );
/** get entailed term, does not construct new terms, less aggressive */
TNode getEntailedTerm( TNode n, EqualityQuery * qy = NULL );
TNode getEntailedTerm( TNode n, std::map< TNode, TNode >& subs, bool subsRep, EqualityQuery * qy = NULL );
/** is entailed (incomplete check) */
bool isEntailed( TNode n, bool pol, EqualityQuery * qy = NULL );
bool isEntailed( TNode n, std::map< TNode, TNode >& subs, bool subsRep, bool pol, EqualityQuery * qy = NULL );
+ /** is active */
+ bool isTermActive( Node n );
+ void setTermInactive( Node n );
/** has term */
bool hasTermCurrent( Node n, bool useMode = true );
/** is term eligble for instantiation? */
@@ -274,7 +273,7 @@ public:
Node getEligibleTermInEqc( TNode r );
/** is inst closure */
bool isInstClosure( Node r );
-
+
//for model basis
private:
//map from types to model basis terms
@@ -301,6 +300,7 @@ public:
private:
/** map from universal quantifiers to the list of variables */
std::map< Node, std::vector< Node > > d_vars;
+ std::map< Node, std::map< Node, unsigned > > d_var_num;
/** map from universal quantifiers to the list of instantiation constants */
std::map< Node, std::vector< Node > > d_inst_constants;
/** map from universal quantifiers to their inst constant body */
@@ -312,6 +312,8 @@ private:
/** make instantiation constants for */
void makeInstantiationConstantsFor( Node q );
public:
+ /** get variable number */
+ unsigned getVariableNum( Node q, Node v ) { return d_var_num[q][v]; }
/** get the i^th instantiation constant of q */
Node getInstantiationConstant( Node q, int i ) const;
/** get number of instantiation constants for q */
@@ -327,6 +329,7 @@ public:
instantiation.
*/
Node getInstConstantNode( Node n, Node q );
+ Node getVariableNode( Node n, Node q );
/** get substituted node */
Node getInstantiatedNode( Node n, Node q, std::vector< Node >& terms );
@@ -419,7 +422,8 @@ private:
//free variables
std::map< TypeNode, std::vector< Node > > d_cn_free_var;
// get canonical term, return null if it contains a term apart from handled signature
- Node getCanonicalTerm( TNode n, std::map< TypeNode, unsigned >& var_count, std::map< TNode, TNode >& subs, bool apply_torder );
+ Node getCanonicalTerm( TNode n, std::map< TypeNode, unsigned >& var_count, std::map< TNode, TNode >& subs, bool apply_torder,
+ std::map< TNode, Node >& visited );
public:
/** get id for operator */
int getIdForOperator( Node op );
@@ -461,6 +465,8 @@ public:
static Node ensureType( Node n, TypeNode tn );
/** get ensure type condition */
static bool getEnsureTypeCondition( Node n, TypeNode tn, std::vector< Node >& cond );
+ /** get relevancy condition */
+ static void getRelevancyCondition( Node n, std::vector< Node >& cond );
private:
//helper for contains term
static bool containsTerm2( Node n, Node t, std::map< Node, bool >& visited );
@@ -541,6 +547,8 @@ public:
class TermDbSygus {
private:
+ /** reference to the quantifiers engine */
+ QuantifiersEngine* d_quantEngine;
std::map< TypeNode, std::vector< Node > > d_fv;
std::map< Node, TypeNode > d_fv_stype;
std::map< Node, int > d_fv_num;
@@ -554,7 +562,6 @@ public:
private:
std::map< TypeNode, std::map< int, Node > > d_generic_base;
std::map< TypeNode, std::vector< Node > > d_generic_templ;
- Node getGenericBase( TypeNode tn, const Datatype& dt, int c );
bool getMatch( Node p, Node n, std::map< int, Node >& s );
bool getMatch2( Node p, Node n, std::map< int, Node >& s, std::vector< int >& new_s );
public:
@@ -581,7 +588,11 @@ private:
std::map< TypeNode, std::map< Node, Node > > d_sygus_to_builtin;
std::map< TypeNode, std::map< Node, Node > > d_builtin_const_to_sygus;
public:
- TermDbSygus();
+ TermDbSygus( context::Context* c, QuantifiersEngine* qe );
+ ~TermDbSygus(){}
+ bool reset( Theory::Effort e );
+ std::string identify() const { return "TermDbSygus"; }
+
bool isRegistered( TypeNode tn );
TypeNode sygusToBuiltinType( TypeNode tn );
int getKindArg( TypeNode tn, Kind k );
@@ -615,6 +626,7 @@ public:
/** get value */
Node getTypeMaxValue( TypeNode tn );
TypeNode getSygusTypeForVar( Node v );
+ Node getGenericBase( TypeNode tn, const Datatype& dt, int c );
Node mkGeneric( const Datatype& dt, int c, std::map< TypeNode, int >& var_count, std::map< int, Node >& pre );
Node sygusToBuiltin( Node n, TypeNode tn );
Node builtinToSygusConst( Node c, TypeNode tn, int rcons_depth = 0 );
@@ -633,6 +645,18 @@ public:
static Kind getOperatorKind( Node op );
/** print sygus term */
static void printSygusTerm( std::ostream& out, Node n, std::vector< Node >& lvs );
+
+ /** get anchor */
+ static Node getAnchor( Node n );
+//for eager instantiation
+private:
+ std::map< Node, std::map< Node, bool > > d_subterms;
+ std::map< Node, std::vector< Node > > d_evals;
+ std::map< Node, std::vector< std::vector< Node > > > d_eval_args;
+ std::map< Node, std::map< Node, unsigned > > d_node_mv_args_proc;
+public:
+ void registerEvalTerm( Node n );
+ void registerModelValue( Node n, Node v, std::vector< Node >& lems );
};
}/* CVC4::theory::quantifiers namespace */
diff --git a/src/theory/quantifiers/theory_quantifiers.cpp b/src/theory/quantifiers/theory_quantifiers.cpp
index efe40aaa8..7ad13b3a8 100644..100755
--- a/src/theory/quantifiers/theory_quantifiers.cpp
+++ b/src/theory/quantifiers/theory_quantifiers.cpp
@@ -72,8 +72,11 @@ void TheoryQuantifiers::notifyEq(TNode lhs, TNode rhs) {
void TheoryQuantifiers::preRegisterTerm(TNode n) {
Debug("quantifiers-prereg") << "TheoryQuantifiers::preRegisterTerm() " << n << endl;
- if( n.getKind()==FORALL && !TermDb::hasInstConstAttr(n) ){
- getQuantifiersEngine()->registerQuantifier( n );
+ if( n.getKind()==FORALL ){
+ if( !options::cbqi() || options::recurseCbqi() || !TermDb::hasInstConstAttr(n) ){
+ getQuantifiersEngine()->registerQuantifier( n );
+ Debug("quantifiers-prereg") << "TheoryQuantifiers::preRegisterTerm() done " << n << endl;
+ }
}
}
diff --git a/src/theory/quantifiers/theory_quantifiers.h b/src/theory/quantifiers/theory_quantifiers.h
index 6775e0536..6775e0536 100644..100755
--- a/src/theory/quantifiers/theory_quantifiers.h
+++ b/src/theory/quantifiers/theory_quantifiers.h
diff --git a/src/theory/quantifiers/theory_quantifiers_type_rules.h b/src/theory/quantifiers/theory_quantifiers_type_rules.h
index 6ba57afb4..6ba57afb4 100644..100755
--- a/src/theory/quantifiers/theory_quantifiers_type_rules.h
+++ b/src/theory/quantifiers/theory_quantifiers_type_rules.h
diff --git a/src/theory/quantifiers/trigger.cpp b/src/theory/quantifiers/trigger.cpp
index 38635b37b..ee091919d 100644..100755
--- a/src/theory/quantifiers/trigger.cpp
+++ b/src/theory/quantifiers/trigger.cpp
@@ -43,9 +43,8 @@ void TriggerTermInfo::init( Node q, Node n, int reqPol, Node reqPolEq ){
}
/** trigger class constructor */
-Trigger::Trigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes, int matchOption )
- : d_quantEngine( qe ), d_f( f )
-{
+Trigger::Trigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes )
+ : d_quantEngine( qe ), d_f( f ) {
d_nodes.insert( d_nodes.begin(), nodes.begin(), nodes.end() );
Trace("trigger") << "Trigger for " << f << ": " << std::endl;
for( unsigned i=0; i<d_nodes.size(); i++ ){
@@ -53,7 +52,7 @@ Trigger::Trigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes, int
}
if( d_nodes.size()==1 ){
if( isSimpleTrigger( d_nodes[0] ) ){
- d_mg = new InstMatchGeneratorSimple( f, d_nodes[0] );
+ d_mg = new InstMatchGeneratorSimple( f, d_nodes[0], qe );
}else{
d_mg = InstMatchGenerator::mkInstMatchGenerator( f, d_nodes[0], qe );
d_mg->setActiveAdd(true);
@@ -87,7 +86,7 @@ Trigger::Trigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes, int
}
Trigger::~Trigger() {
- if(d_mg != NULL) { delete d_mg; }
+ delete d_mg;
}
void Trigger::resetInstantiationRound(){
@@ -112,6 +111,10 @@ int Trigger::addTerm( Node t ){
return d_mg->addTerm( d_f, t, d_quantEngine );
}
+Node Trigger::getInstPattern(){
+ return NodeManager::currentNM()->mkNode( INST_PATTERN, d_nodes );
+}
+
int Trigger::addInstantiations( InstMatch& baseMatch ){
int addedLemmas = d_mg->addInstantiations( d_f, baseMatch, d_quantEngine );
if( addedLemmas>0 ){
@@ -124,77 +127,85 @@ int Trigger::addInstantiations( InstMatch& baseMatch ){
return addedLemmas;
}
-Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes, int matchOption, bool keepAll, int trOption ){
- std::vector< Node > trNodes;
- if( !keepAll ){
- //only take nodes that contribute variables to the trigger when added
- std::vector< Node > temp;
- temp.insert( temp.begin(), nodes.begin(), nodes.end() );
- std::map< Node, bool > vars;
- std::map< Node, std::vector< Node > > patterns;
- size_t varCount = 0;
- std::map< Node, std::vector< Node > > varContains;
- quantifiers::TermDb::getVarContains( f, temp, varContains );
- for( unsigned i=0; i<temp.size(); i++ ){
- bool foundVar = false;
+bool Trigger::mkTriggerTerms( Node q, std::vector< Node >& nodes, unsigned n_vars, std::vector< Node >& trNodes ) {
+ //only take nodes that contribute variables to the trigger when added
+ std::vector< Node > temp;
+ temp.insert( temp.begin(), nodes.begin(), nodes.end() );
+ std::map< Node, bool > vars;
+ std::map< Node, std::vector< Node > > patterns;
+ size_t varCount = 0;
+ std::map< Node, std::vector< Node > > varContains;
+ quantifiers::TermDb::getVarContains( q, temp, varContains );
+ for( unsigned i=0; i<temp.size(); i++ ){
+ bool foundVar = false;
+ for( unsigned j=0; j<varContains[ temp[i] ].size(); j++ ){
+ Node v = varContains[ temp[i] ][j];
+ Assert( quantifiers::TermDb::getInstConstAttr(v)==q );
+ if( vars.find( v )==vars.end() ){
+ varCount++;
+ vars[ v ] = true;
+ foundVar = true;
+ }
+ }
+ if( foundVar ){
+ trNodes.push_back( temp[i] );
for( unsigned j=0; j<varContains[ temp[i] ].size(); j++ ){
Node v = varContains[ temp[i] ][j];
- Assert( quantifiers::TermDb::getInstConstAttr(v)==f );
- if( vars.find( v )==vars.end() ){
- varCount++;
- vars[ v ] = true;
- foundVar = true;
- }
- }
- if( foundVar ){
- trNodes.push_back( temp[i] );
- for( unsigned j=0; j<varContains[ temp[i] ].size(); j++ ){
- Node v = varContains[ temp[i] ][j];
- patterns[ v ].push_back( temp[i] );
- }
- }
- if( varCount==f[0].getNumChildren() ){
- break;
+ patterns[ v ].push_back( temp[i] );
}
}
- if( varCount<f[0].getNumChildren() && !options::partialTriggers() ){
- Trace("trigger-debug") << "Don't consider trigger since it does not contain all variables in " << f << std::endl;
- for( unsigned i=0; i<nodes.size(); i++) {
- Trace("trigger-debug") << nodes[i] << " ";
- }
- Trace("trigger-debug") << std::endl;
+ if( varCount==n_vars ){
+ break;
+ }
+ }
+ if( varCount<n_vars ){
+ Trace("trigger-debug") << "Don't consider trigger since it does not contain specified number of variables." << std::endl;
+ for( unsigned i=0; i<nodes.size(); i++) {
+ Trace("trigger-debug") << nodes[i] << " ";
+ }
+ Trace("trigger-debug") << std::endl;
- //do not generate multi-trigger if it does not contain all variables
- return NULL;
- }else{
- //now, minimize the trigger
- for( unsigned i=0; i<trNodes.size(); i++ ){
- bool keepPattern = false;
- Node n = trNodes[i];
+ //do not generate multi-trigger if it does not contain all variables
+ return false;
+ }else{
+ //now, minimize the trigger
+ for( unsigned i=0; i<trNodes.size(); i++ ){
+ bool keepPattern = false;
+ Node n = trNodes[i];
+ for( unsigned j=0; j<varContains[ n ].size(); j++ ){
+ Node v = varContains[ n ][j];
+ if( patterns[v].size()==1 ){
+ keepPattern = true;
+ break;
+ }
+ }
+ if( !keepPattern ){
+ //remove from pattern vector
for( unsigned j=0; j<varContains[ n ].size(); j++ ){
Node v = varContains[ n ][j];
- if( patterns[v].size()==1 ){
- keepPattern = true;
- break;
- }
- }
- if( !keepPattern ){
- //remove from pattern vector
- for( unsigned j=0; j<varContains[ n ].size(); j++ ){
- Node v = varContains[ n ][j];
- for( unsigned k=0; k<patterns[v].size(); k++ ){
- if( patterns[v][k]==n ){
- patterns[v].erase( patterns[v].begin() + k, patterns[v].begin() + k + 1 );
- break;
- }
+ for( unsigned k=0; k<patterns[v].size(); k++ ){
+ if( patterns[v][k]==n ){
+ patterns[v].erase( patterns[v].begin() + k, patterns[v].begin() + k + 1 );
+ break;
}
}
- //remove from trigger nodes
- trNodes.erase( trNodes.begin() + i, trNodes.begin() + i + 1 );
- i--;
}
+ //remove from trigger nodes
+ trNodes.erase( trNodes.begin() + i, trNodes.begin() + i + 1 );
+ i--;
}
}
+ }
+ return true;
+}
+
+Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes, bool keepAll, int trOption, unsigned use_n_vars ){
+ std::vector< Node > trNodes;
+ if( !keepAll ){
+ unsigned n_vars = use_n_vars==0 ? f[0].getNumChildren() : use_n_vars;
+ if( !mkTriggerTerms( f, nodes, n_vars, trNodes ) ){
+ return NULL;
+ }
}else{
trNodes.insert( trNodes.begin(), nodes.begin(), nodes.end() );
}
@@ -211,15 +222,15 @@ Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >&
}
}
}
- Trigger* t = new Trigger( qe, f, trNodes, matchOption );
+ Trigger* t = new Trigger( qe, f, trNodes );
qe->getTriggerDatabase()->addTrigger( trNodes, t );
return t;
}
-Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, Node n, int matchOption, bool keepAll, int trOption ){
+Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, Node n, bool keepAll, int trOption, unsigned use_n_vars ){
std::vector< Node > nodes;
nodes.push_back( n );
- return mkTrigger( qe, f, nodes, matchOption, keepAll, trOption );
+ return mkTrigger( qe, f, nodes, keepAll, trOption, use_n_vars );
}
bool Trigger::isUsable( Node n, Node q ){
@@ -273,7 +284,7 @@ bool Trigger::isUsableEqTerms( Node q, Node n1, Node n2 ) {
return true;
}
}
- }else if( isAtomicTrigger( n1 ) && isUsable( n1, q ) ){
+ }else if( isUsableAtomicTrigger( n1, q ) ){
if( options::relationalTriggers() && n2.getKind()==INST_CONSTANT && !quantifiers::TermDb::containsTerm( n1, n2 ) ){
return true;
}else if( !quantifiers::TermDb::hasInstConstAttr(n2) ){
@@ -328,24 +339,25 @@ Node Trigger::getIsUsableTrigger( Node n, Node q ) {
return rtr2;
}
}else{
- bool usable = quantifiers::TermDb::getInstConstAttr(n)==q && isAtomicTrigger( n ) && isUsable( n, q );
- Trace("trigger-debug") << n << " usable : " << (quantifiers::TermDb::getInstConstAttr(n)==q) << " " << isAtomicTrigger( n ) << " " << isUsable( n, q ) << std::endl;
- if( usable ){
+ Trace("trigger-debug") << n << " usable : " << ( quantifiers::TermDb::getInstConstAttr(n)==q ) << " " << isAtomicTrigger( n ) << " " << isUsable( n, q ) << std::endl;
+ if( isUsableAtomicTrigger( n, q ) ){
return pol ? n : NodeManager::currentNM()->mkNode( IFF, n, NodeManager::currentNM()->mkConst( true ) ).notNode();
}
}
return Node::null();
}
+bool Trigger::isUsableAtomicTrigger( Node n, Node q ) {
+ return quantifiers::TermDb::getInstConstAttr( n )==q && isAtomicTrigger( n ) && isUsable( n, q );
+}
+
bool Trigger::isUsableTrigger( Node n, Node q ){
Node nu = getIsUsableTrigger( n, q );
return !nu.isNull();
}
bool Trigger::isAtomicTrigger( Node n ){
- Kind k = n.getKind();
- return ( k==APPLY_UF && !n.getOperator().getAttribute(NoMatchAttribute()) ) ||
- ( k!=APPLY_UF && isAtomicTriggerKind( k ) );
+ return isAtomicTriggerKind( n.getKind() );
}
bool Trigger::isAtomicTriggerKind( Kind k ) {
@@ -363,8 +375,13 @@ bool Trigger::isRelationalTriggerKind( Kind k ) {
}
bool Trigger::isCbqiKind( Kind k ) {
- return quantifiers::TermDb::isBoolConnective( k ) || k==PLUS || k==GEQ || k==EQUAL || k==MULT ||
- k==APPLY_CONSTRUCTOR || k==APPLY_SELECTOR_TOTAL || k==APPLY_TESTER;
+ if( quantifiers::TermDb::isBoolConnective( k ) || k==PLUS || k==GEQ || k==EQUAL || k==MULT ){
+ return true;
+ }else{
+ //CBQI typically works for satisfaction-complete theories
+ TheoryId t = kindToTheoryId( k );
+ return t==THEORY_BV || t==THEORY_DATATYPES;
+ }
}
bool Trigger::isSimpleTrigger( Node n ){
diff --git a/src/theory/quantifiers/trigger.h b/src/theory/quantifiers/trigger.h
index 41f2a1c38..a3da4d398 100644..100755
--- a/src/theory/quantifiers/trigger.h
+++ b/src/theory/quantifiers/trigger.h
@@ -76,6 +76,8 @@ class Trigger {
int addTerm( Node t );
/** return whether this is a multi-trigger */
bool isMultiTrigger() { return d_nodes.size()>1; }
+ /** get inst pattern list */
+ Node getInstPattern();
/** add all available instantiations exhaustively, in any equivalence class
if limitInst>0, limitInst is the max # of instantiations to try */
@@ -84,8 +86,6 @@ class Trigger {
ie : quantifier engine;
f : forall something ....
nodes : (multi-)trigger
- matchOption : which policy to use for creating matches
- (one of InstMatchGenerator::MATCH_GEN_* )
keepAll: don't remove unneeded patterns;
trOption : policy for dealing with triggers that already existed
(see below)
@@ -95,18 +95,19 @@ class Trigger {
TR_GET_OLD, //return a previous trigger if it had already been created
TR_RETURN_NULL //return null if a duplicate is found
};
- static Trigger* mkTrigger( QuantifiersEngine* qe, Node f,
- std::vector< Node >& nodes, int matchOption = 0,
- bool keepAll = true, int trOption = TR_MAKE_NEW );
- static Trigger* mkTrigger( QuantifiersEngine* qe, Node f, Node n,
- int matchOption = 0, bool keepAll = true,
- int trOption = TR_MAKE_NEW );
+ //nodes input, trNodes output
+ static bool mkTriggerTerms( Node q, std::vector< Node >& nodes, unsigned n_vars, std::vector< Node >& trNodes );
+ static Trigger* mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes,
+ bool keepAll = true, int trOption = TR_MAKE_NEW, unsigned use_n_vars = 0 );
+ static Trigger* mkTrigger( QuantifiersEngine* qe, Node f, Node n, bool keepAll = true,
+ int trOption = TR_MAKE_NEW, unsigned use_n_vars = 0 );
static void collectPatTerms( Node q, Node n, std::vector< Node >& patTerms, quantifiers::TriggerSelMode tstrt,
std::vector< Node >& exclude, std::map< Node, TriggerTermInfo >& tinfo,
bool filterInst = false );
/** is usable trigger */
static bool isUsableTrigger( Node n, Node q );
static Node getIsUsableTrigger( Node n, Node q );
+ static bool isUsableAtomicTrigger( Node n, Node q );
static bool isAtomicTrigger( Node n );
static bool isAtomicTriggerKind( Kind k );
static bool isRelationalTrigger( Node n );
@@ -135,7 +136,7 @@ class Trigger {
}
private:
/** trigger constructor */
- Trigger( QuantifiersEngine* ie, Node f, std::vector< Node >& nodes, int matchOption = 0 );
+ Trigger( QuantifiersEngine* ie, Node f, std::vector< Node >& nodes );
/** is subterm of trigger usable */
static bool isUsable( Node n, Node q );
diff --git a/src/theory/quantifiers_engine.cpp b/src/theory/quantifiers_engine.cpp
index 6d3b17254..d81efe1da 100644
--- a/src/theory/quantifiers_engine.cpp
+++ b/src/theory/quantifiers_engine.cpp
@@ -57,6 +57,7 @@ using namespace CVC4::theory::inst;
QuantifiersEngine::QuantifiersEngine(context::Context* c, context::UserContext* u, TheoryEngine* te):
d_te( te ),
+ d_conflict_c(c, false),
//d_quants(u),
d_quants_red(u),
d_lemmas_produced_c(u),
@@ -88,7 +89,6 @@ QuantifiersEngine::QuantifiersEngine(context::Context* c, context::UserContext*
d_tr_trie = new inst::TriggerTrie;
d_curr_effort_level = QEFFORT_NONE;
d_conflict = false;
- d_num_added_lemmas_round = 0;
d_hasAddedLemma = false;
//don't add true lemma
d_lemmas_produced_c[d_term_db->d_true] = true;
@@ -352,7 +352,7 @@ void QuantifiersEngine::check( Theory::Effort e ){
std::vector< QuantifiersModule* > qm;
if( d_model->checkNeeded() ){
needsCheck = needsCheck || e>=Theory::EFFORT_LAST_CALL; //always need to check at or above last call
- for( int i=0; i<(int)d_modules.size(); i++ ){
+ for( unsigned i=0; i<d_modules.size(); i++ ){
if( d_modules[i]->needsCheck( e ) ){
qm.push_back( d_modules[i] );
needsCheck = true;
@@ -366,7 +366,6 @@ void QuantifiersEngine::check( Theory::Effort e ){
}
d_conflict = false;
- d_num_added_lemmas_round = 0;
d_hasAddedLemma = false;
bool setIncomplete = false;
if( e==Theory::EFFORT_LAST_CALL ){
@@ -380,6 +379,8 @@ void QuantifiersEngine::check( Theory::Effort e ){
Trace("quant-engine-debug2") << "Quantifiers Engine call to check, level = " << e << ", needsCheck=" << needsCheck << std::endl;
if( needsCheck ){
+ //this will fail if a set of instances is marked as a conflict, but is not
+ Assert( !d_conflict_c.get() );
//flush previous lemmas (for instance, if was interupted), or other lemmas to process
flushLemmas();
if( d_hasAddedLemma ){
@@ -393,6 +394,12 @@ void QuantifiersEngine::check( Theory::Effort e ){
}
d_recorded_inst.clear();
}
+
+ double clSet = 0;
+ if( Trace.isOn("quant-engine") ){
+ clSet = double(clock())/double(CLOCKS_PER_SEC);
+ Trace("quant-engine") << ">>>>> Quantifiers Engine Round, effort = " << e << " <<<<<" << std::endl;
+ }
if( Trace.isOn("quant-engine-debug") ){
Trace("quant-engine-debug") << "Quantifiers Engine check, level = " << e << std::endl;
@@ -453,7 +460,6 @@ void QuantifiersEngine::check( Theory::Effort e ){
flushLemmas();
if( d_hasAddedLemma ){
return;
-
}
if( e==Theory::EFFORT_LAST_CALL ){
@@ -545,6 +551,13 @@ void QuantifiersEngine::check( Theory::Effort e ){
}
}
}
+ if( Trace.isOn("quant-engine") ){
+ double clSet2 = double(clock())/double(CLOCKS_PER_SEC);
+ Trace("quant-engine") << "Finished quantifiers engine, total time = " << (clSet2-clSet);
+ Trace("quant-engine") << ", added lemma = " << d_hasAddedLemma;
+ Trace("quant-engine") << std::endl;
+ }
+
Trace("quant-engine-debug2") << "Finished quantifiers engine check." << std::endl;
}else{
Trace("quant-engine-debug2") << "Quantifiers Engine does not need check." << std::endl;
@@ -564,7 +577,7 @@ void QuantifiersEngine::check( Theory::Effort e ){
}
}
if( setIncomplete ){
- Trace("quant-engine-debug") << "Set incomplete flag." << std::endl;
+ Trace("quant-engine") << "Set incomplete flag." << std::endl;
getOutputChannel().setIncomplete();
}
//output debug stats
@@ -621,6 +634,7 @@ bool QuantifiersEngine::registerQuantifier( Node f ){
//check whether we should apply a reduction
if( reduceQuantifier( f ) ){
+ Trace("quant") << "...reduced." << std::endl;
d_quants[f] = false;
return false;
}else{
@@ -628,6 +642,7 @@ bool QuantifiersEngine::registerQuantifier( Node f ){
d_term_db->makeInstantiationConstantsFor( f );
d_term_db->computeAttributes( f );
for( unsigned i=0; i<d_modules.size(); i++ ){
+ Trace("quant-debug") << "pre-register with " << d_modules[i]->identify() << "..." << std::endl;
d_modules[i]->preRegisterQuantifier( f );
}
QuantifiersModule * qm = getOwner( f );
@@ -640,11 +655,11 @@ bool QuantifiersEngine::registerQuantifier( Node f ){
}
//register with each module
for( unsigned i=0; i<d_modules.size(); i++ ){
+ Trace("quant-debug") << "register with " << d_modules[i]->identify() << "..." << std::endl;
d_modules[i]->registerQuantifier( f );
}
+ //TODO: remove this
Node ceBody = d_term_db->getInstConstantBody( f );
- //generate the phase requirements
- //d_phase_reqs[f] = new QuantPhaseReq( ceBody, true );
//also register it with the strong solver
//if( options::finiteModelFind() ){
// ((uf::TheoryUF*)d_te->theoryOf( THEORY_UF ))->getStrongSolver()->registerQuantifier( f );
@@ -874,8 +889,9 @@ Node QuantifiersEngine::getSubstitute( Node n, std::vector< Node >& terms ){
Node QuantifiersEngine::getInstantiation( Node q, std::vector< Node >& vars, std::vector< Node >& terms, bool doVts ){
Node body;
+ Assert( vars.size()==terms.size() );
//process partial instantiation if necessary
- if( d_term_db->d_vars[q].size()!=vars.size() ){
+ if( q[0].getNumChildren()!=vars.size() ){
body = q[ 1 ].substitute( vars.begin(), vars.end(), terms.begin(), terms.end() );
std::vector< Node > uninst_vars;
//doing a partial instantiation, must add quantifier for all uninstantiated variables
@@ -884,6 +900,8 @@ Node QuantifiersEngine::getInstantiation( Node q, std::vector< Node >& vars, std
uninst_vars.push_back( q[0][i] );
}
}
+ Trace("partial-inst") << "Partially instantiating with " << vars.size() << " / " << q[0].getNumChildren() << " for " << q << std::endl;
+ Assert( !uninst_vars.empty() );
Node bvl = NodeManager::currentNM()->mkNode( BOUND_VAR_LIST, uninst_vars );
body = NodeManager::currentNM()->mkNode( FORALL, bvl, body );
Trace("partial-inst") << "Partial instantiation : " << q << std::endl;
@@ -922,6 +940,7 @@ Node QuantifiersEngine::getInstantiation( Node q, InstMatch& m, bool doVts ){
}
Node QuantifiersEngine::getInstantiation( Node q, std::vector< Node >& terms, bool doVts ) {
+ Assert( d_term_db->d_vars.find( q )!=d_term_db->d_vars.end() );
return getInstantiation( q, d_term_db->d_vars[q], terms, doVts );
}
@@ -956,7 +975,6 @@ bool QuantifiersEngine::addLemma( Node lem, bool doCache, bool doRewrite ){
d_lemmas_produced_c[ lem ] = true;
d_lemmas_waiting.push_back( lem );
Trace("inst-add-debug") << "Added lemma" << std::endl;
- d_num_added_lemmas_round++;
return true;
}else{
Trace("inst-add-debug") << "Duplicate." << std::endl;
@@ -965,7 +983,6 @@ bool QuantifiersEngine::addLemma( Node lem, bool doCache, bool doRewrite ){
}else{
//do not need to rewrite, will be rewritten after sending
d_lemmas_waiting.push_back( lem );
- d_num_added_lemmas_round++;
return true;
}
}
@@ -997,6 +1014,7 @@ bool QuantifiersEngine::addInstantiation( Node q, std::vector< Node >& terms, bo
Assert( !d_conflict );
Assert( terms.size()==q[0].getNumChildren() );
Trace("inst-add-debug") << "For quantified formula " << q << ", add instantiation: " << std::endl;
+ std::vector< Node > rlv_cond;
for( unsigned i=0; i<terms.size(); i++ ){
Trace("inst-add-debug") << " " << q[0][i];
Trace("inst-add-debug2") << " -> " << terms[i];
@@ -1014,20 +1032,29 @@ bool QuantifiersEngine::addInstantiation( Node q, std::vector< Node >& terms, bo
if( terms[i].isNull() ){
Trace("inst-add-debug") << " --> Failed to make term vector, due to term/type restrictions." << std::endl;
return false;
+ }else{
+ //get relevancy conditions
+ if( options::instRelevantCond() ){
+ quantifiers::TermDb::getRelevancyCondition( terms[i], rlv_cond );
+ }
}
#ifdef CVC4_ASSERTIONS
bool bad_inst = false;
if( quantifiers::TermDb::containsUninterpretedConstant( terms[i] ) ){
+ Trace("inst") << "***& inst contains uninterpreted constant : " << terms[i] << std::endl;
bad_inst = true;
}else if( !terms[i].getType().isSubtypeOf( q[0][i].getType() ) ){
+ Trace("inst") << "***& inst bad type : " << terms[i] << " " << terms[i].getType() << "/" << q[0][i].getType() << std::endl;
bad_inst = true;
}else if( options::cbqi() ){
Node icf = quantifiers::TermDb::getInstConstAttr(terms[i]);
if( !icf.isNull() ){
if( icf==q ){
+ Trace("inst") << "***& inst contains inst constant attr : " << terms[i] << std::endl;
+ bad_inst = true;
+ }else if( quantifiers::TermDb::containsTerms( terms[i], d_term_db->d_inst_constants[q] ) ){
+ Trace("inst") << "***& inst contains inst constants : " << terms[i] << std::endl;
bad_inst = true;
- }else{
- bad_inst = quantifiers::TermDb::containsTerms( terms[i], d_term_db->d_inst_constants[q] );
}
}
}
@@ -1079,13 +1106,21 @@ bool QuantifiersEngine::addInstantiation( Node q, std::vector< Node >& terms, bo
Trace("inst-add-debug") << "Constructing instantiation..." << std::endl;
Assert( d_term_db->d_vars[q].size()==terms.size() );
Node body = getInstantiation( q, d_term_db->d_vars[q], terms, doVts ); //do virtual term substitution
+ Node orig_body = body;
body = quantifiers::QuantifiersRewriter::preprocess( body, true );
Trace("inst-debug") << "...preprocess to " << body << std::endl;
//construct the lemma
Trace("inst-assert") << "(assert " << body << ")" << std::endl;
body = Rewriter::rewrite(body);
- Node lem = NodeManager::currentNM()->mkNode( kind::OR, q.negate(), body );
+ Node lem;
+ if( rlv_cond.empty() ){
+ lem = NodeManager::currentNM()->mkNode( kind::OR, q.negate(), body );
+ }else{
+ rlv_cond.push_back( q.negate() );
+ rlv_cond.push_back( body );
+ lem = NodeManager::currentNM()->mkNode( kind::OR, rlv_cond );
+ }
lem = Rewriter::rewrite(lem);
//check for lemma duplication
@@ -1106,15 +1141,20 @@ bool QuantifiersEngine::addInstantiation( Node q, std::vector< Node >& terms, bo
}
}
if( options::instMaxLevel()!=-1 ){
- uint64_t maxInstLevel = 0;
- for( unsigned i=0; i<terms.size(); i++ ){
- if( terms[i].hasAttribute(InstLevelAttribute()) ){
- if( terms[i].getAttribute(InstLevelAttribute())>maxInstLevel ){
- maxInstLevel = terms[i].getAttribute(InstLevelAttribute());
+ if( doVts ){
+ //virtual term substitution/instantiation level features are incompatible
+ Assert( false );
+ }else{
+ uint64_t maxInstLevel = 0;
+ for( unsigned i=0; i<terms.size(); i++ ){
+ if( terms[i].hasAttribute(InstLevelAttribute()) ){
+ if( terms[i].getAttribute(InstLevelAttribute())>maxInstLevel ){
+ maxInstLevel = terms[i].getAttribute(InstLevelAttribute());
+ }
}
}
+ setInstantiationLevelAttr( orig_body, q[1], maxInstLevel+1 );
}
- setInstantiationLevelAttr( body, q[1], maxInstLevel+1 );
}
if( d_curr_effort_level>QEFFORT_CONFLICT && d_curr_effort_level<QEFFORT_NONE ){
//notify listeners
@@ -1122,6 +1162,7 @@ bool QuantifiersEngine::addInstantiation( Node q, std::vector< Node >& terms, bo
if( !d_inst_notify[j]->notifyInstantiation( d_curr_effort_level, q, lem, terms, body ) ){
Trace("inst-add-debug") << "...we are in conflict." << std::endl;
d_conflict = true;
+ d_conflict_c = true;
Assert( !d_lemmas_waiting.empty() );
break;
}
@@ -1205,9 +1246,19 @@ quantifiers::UserPatMode QuantifiersEngine::getInstUserPatMode() {
void QuantifiersEngine::flushLemmas(){
if( !d_lemmas_waiting.empty() ){
+ //filter based on notify classes
+ if( !d_inst_notify.empty() ){
+ unsigned prev_lem_sz = d_lemmas_waiting.size();
+ for( unsigned j=0; j<d_inst_notify.size(); j++ ){
+ d_inst_notify[j]->filterInstantiations();
+ }
+ if( prev_lem_sz!=d_lemmas_waiting.size() ){
+ Trace("quant-engine") << "...filtered instances : " << d_lemmas_waiting.size() << " / " << prev_lem_sz << std::endl;
+ }
+ }
//take default output channel if none is provided
d_hasAddedLemma = true;
- for( int i=0; i<(int)d_lemmas_waiting.size(); i++ ){
+ for( unsigned i=0; i<d_lemmas_waiting.size(); i++ ){
Trace("qe-lemma") << "Lemma : " << d_lemmas_waiting[i] << std::endl;
getOutputChannel().lemma( d_lemmas_waiting[i], false, true );
}
@@ -1403,7 +1454,7 @@ bool EqualityQueryQuantifiersEngine::processInferences( Theory::Effort e ) {
Trace("quant-engine-ee-proc") << " explanation : " << eq_exp << std::endl;
Assert( ee->hasTerm( eq[0] ) );
Assert( ee->hasTerm( eq[1] ) );
- if( ee->areDisequal( eq[0], eq[1], false ) ){
+ if( areDisequal( eq[0], eq[1] ) ){
Trace("quant-engine-ee-proc") << "processInferences : Conflict : " << eq << std::endl;
if( Trace.isOn("term-db-lemma") ){
Trace("term-db-lemma") << "Disequal terms, equal by normalization : " << eq[0] << " " << eq[1] << "!!!!" << std::endl;
@@ -1445,11 +1496,10 @@ bool EqualityQueryQuantifiersEngine::areEqual( Node a, Node b ){
}else{
eq::EqualityEngine* ee = getEngine();
if( ee->hasTerm( a ) && ee->hasTerm( b ) ){
- if( ee->areEqual( a, b ) ){
- return true;
- }
+ return ee->areEqual( a, b );
+ }else{
+ return false;
}
- return false;
}
}
@@ -1459,11 +1509,10 @@ bool EqualityQueryQuantifiersEngine::areDisequal( Node a, Node b ){
}else{
eq::EqualityEngine* ee = getEngine();
if( ee->hasTerm( a ) && ee->hasTerm( b ) ){
- if( ee->areDisequal( a, b, false ) ){
- return true;
- }
+ return ee->areDisequal( a, b, false );
+ }else{
+ return a.isConst() && b.isConst();
}
- return false;
}
}
diff --git a/src/theory/quantifiers_engine.h b/src/theory/quantifiers_engine.h
index 4ee66f9e7..1f4a04218 100644
--- a/src/theory/quantifiers_engine.h
+++ b/src/theory/quantifiers_engine.h
@@ -48,6 +48,7 @@ class InstantiationNotify {
public:
InstantiationNotify(){}
virtual bool notifyInstantiation( unsigned quant_e, Node q, Node lem, std::vector< Node >& terms, Node body ) = 0;
+ virtual void filterInstantiations() = 0;
};
namespace quantifiers {
@@ -156,8 +157,7 @@ private: //this information is reset during check
unsigned d_curr_effort_level;
/** are we in conflict */
bool d_conflict;
- /** number of lemmas we actually added this round (for debugging) */
- unsigned d_num_added_lemmas_round;
+ context::CDO< bool > d_conflict_c;
/** has added lemma this round */
bool d_hasAddedLemma;
private:
@@ -295,9 +295,9 @@ private:
bool removeInstantiationInternal( Node q, std::vector< Node >& terms );
/** set instantiation level attr */
static void setInstantiationLevelAttr( Node n, Node qn, uint64_t level );
+public:
/** flush lemmas */
void flushLemmas();
-public:
/** get instantiation */
Node getInstantiation( Node q, std::vector< Node >& vars, std::vector< Node >& terms, bool doVts = false );
/** get instantiation */
@@ -330,8 +330,6 @@ public:
bool inConflict() { return d_conflict; }
/** get number of waiting lemmas */
unsigned getNumLemmasWaiting() { return d_lemmas_waiting.size(); }
- /** get number of waiting lemmas */
- unsigned getNumLemmasAddedThisRound() { return d_num_added_lemmas_round; }
/** get needs check */
bool getInstWhenNeedsCheck( Theory::Effort e );
/** get user pat mode */
diff --git a/src/theory/rep_set.cpp b/src/theory/rep_set.cpp
index d7178a8c1..184553ba7 100644
--- a/src/theory/rep_set.cpp
+++ b/src/theory/rep_set.cpp
@@ -127,19 +127,11 @@ int RepSet::getNumRelevantGroundReps( TypeNode t ) {
}
void RepSet::toStream(std::ostream& out){
-#if 0
- for( std::map< TypeNode, std::vector< Node > >::iterator it = d_type_reps.begin(); it != d_type_reps.end(); ++it ){
- out << it->first << " : " << std::endl;
- for( int i=0; i<(int)it->second.size(); i++ ){
- out << " " << i << ": " << it->second[i] << std::endl;
- }
- }
-#else
for( std::map< TypeNode, std::vector< Node > >::iterator it = d_type_reps.begin(); it != d_type_reps.end(); ++it ){
if( !it->first.isFunction() && !it->first.isPredicate() ){
out << "(" << it->first << " " << it->second.size();
out << " (";
- for( int i=0; i<(int)it->second.size(); i++ ){
+ for( unsigned i=0; i<it->second.size(); i++ ){
if( i>0 ){ out << " "; }
out << it->second[i];
}
@@ -147,7 +139,6 @@ void RepSet::toStream(std::ostream& out){
out << ")" << std::endl;
}
}
-#endif
}
@@ -157,10 +148,11 @@ RepSetIterator::RepSetIterator( QuantifiersEngine * qe, RepSet* rs ) : d_qe(qe),
int RepSetIterator::domainSize( int i ) {
Assert(i>=0);
- if( d_enum_type[i]==ENUM_DOMAIN_ELEMENTS ){
- return d_domain[i].size();
+ int v = d_var_order[i];
+ if( d_enum_type[v]==ENUM_DOMAIN_ELEMENTS ){
+ return d_domain[v].size();
}else{
- return d_domain[i][0];
+ return d_domain[v][0];
}
}
@@ -188,15 +180,15 @@ bool RepSetIterator::setFunctionDomain( Node op ){
bool RepSetIterator::initialize(){
Trace("rsi") << "Initialize rep set iterator..." << std::endl;
- for( size_t i=0; i<d_types.size(); i++ ){
+ for( unsigned v=0; v<d_types.size(); v++ ){
d_index.push_back( 0 );
//store default index order
- d_index_order.push_back( i );
- d_var_order[i] = i;
+ d_index_order.push_back( v );
+ d_var_order[v] = v;
//store default domain
d_domain.push_back( RepDomain() );
- TypeNode tn = d_types[i];
- Trace("rsi") << "Var #" << i << " is type " << tn << "..." << std::endl;
+ TypeNode tn = d_types[v];
+ Trace("rsi") << "Var #" << v << " is type " << tn << "..." << std::endl;
if( tn.isSort() ){
//must ensure uninterpreted type is non-empty.
if( !d_rep_set->hasType( tn ) ){
@@ -209,59 +201,59 @@ bool RepSetIterator::initialize(){
Trace("mkVar") << "RepSetIterator:: Make variable " << var << " : " << tn << std::endl;
d_rep_set->add( tn, var );
}
- }else if( tn.isInteger() ){
- bool inc = false;
- //check if it is bound
+ }else{
+ bool inc = true;
+ //check if it is bound by bounded integer module
if( d_owner.getKind()==FORALL && d_qe && d_qe->getBoundedIntegers() ){
- if( d_qe->getBoundedIntegers()->isBoundVar( d_owner, d_owner[0][i] ) ){
+ unsigned bvt = d_qe->getBoundedIntegers()->getBoundVarType( d_owner, d_owner[0][v] );
+ if( bvt==quantifiers::BoundedIntegers::BOUND_INT_RANGE ){
Trace("rsi") << " variable is bounded integer." << std::endl;
- d_enum_type.push_back( ENUM_RANGE );
- }else{
- inc = true;
+ d_enum_type.push_back( ENUM_INT_RANGE );
+ inc = false;
+ }else if( bvt==quantifiers::BoundedIntegers::BOUND_SET_MEMBER ){
+ Trace("rsi") << " variable is bounded by set membership." << std::endl;
+ d_enum_type.push_back( ENUM_SET_MEMBERS );
+ inc = false;
}
- }else{
- inc = true;
}
if( inc ){
//check if it is otherwise bound
- if( d_bounds[0].find(i)!=d_bounds[0].end() && d_bounds[1].find(i)!=d_bounds[1].end() ){
+ if( d_bounds[0].find( v )!=d_bounds[0].end() && d_bounds[1].find( v )!=d_bounds[1].end() ){
Trace("rsi") << " variable is bounded." << std::endl;
- d_enum_type.push_back( ENUM_RANGE );
+ d_enum_type.push_back( ENUM_INT_RANGE );
+ }else if( d_qe->getTermDatabase()->mayComplete( tn ) ){
+ Trace("rsi") << " do complete, since cardinality is small (" << tn.getCardinality() << ")..." << std::endl;
+ d_rep_set->complete( tn );
+ //must have succeeded
+ Assert( d_rep_set->hasType( tn ) );
}else{
Trace("rsi") << " variable cannot be bounded." << std::endl;
- Trace("fmf-incomplete") << "Incomplete because of integer quantification of " << d_owner[0][i] << "." << std::endl;
+ Trace("fmf-incomplete") << "Incomplete because of quantification of type " << tn << std::endl;
d_incomplete = true;
}
}
- //enumerate if the sort is reasonably small
- }else if( d_qe->getTermDatabase()->mayComplete( tn ) ){
- Trace("rsi") << " do complete, since cardinality is small (" << tn.getCardinality() << ")..." << std::endl;
- d_rep_set->complete( tn );
- //must have succeeded
- Assert( d_rep_set->hasType( tn ) );
- }else{
- Trace("rsi") << " variable cannot be bounded." << std::endl;
- Trace("fmf-incomplete") << "Incomplete because of quantification of type " << tn << std::endl;
- d_incomplete = true;
}
//if we have yet to determine the type of enumeration
- if( d_enum_type.size()<=i ){
+ if( d_enum_type.size()<=v ){
d_enum_type.push_back( ENUM_DOMAIN_ELEMENTS );
if( d_rep_set->hasType( tn ) ){
- for( size_t j=0; j<d_rep_set->d_type_reps[tn].size(); j++ ){
- d_domain[i].push_back( j );
+ for( unsigned j=0; j<d_rep_set->d_type_reps[tn].size(); j++ ){
+ d_domain[v].push_back( j );
}
}else{
+ Assert( d_incomplete );
return false;
}
}
}
//must set a variable index order based on bounded integers
- if (d_owner.getKind()==FORALL && d_qe && d_qe->getBoundedIntegers()) {
+ if( d_owner.getKind()==FORALL && d_qe && d_qe->getBoundedIntegers() ){
Trace("bound-int-rsi") << "Calculating variable order..." << std::endl;
std::vector< int > varOrder;
- for( unsigned i=0; i<d_qe->getBoundedIntegers()->getNumBoundVars(d_owner); i++ ){
- varOrder.push_back(d_qe->getBoundedIntegers()->getBoundVarNum(d_owner,i));
+ for( unsigned i=0; i<d_qe->getBoundedIntegers()->getNumBoundVars( d_owner ); i++ ){
+ Node v = d_qe->getBoundedIntegers()->getBoundVar( d_owner, i );
+ Trace("bound-int-rsi") << " bound var #" << i << " is " << v << std::endl;
+ varOrder.push_back( d_qe->getTermDatabase()->getVariableNum( d_owner, v ) );
}
for( unsigned i=0; i<d_owner[0].getNumChildren(); i++) {
if( !d_qe->getBoundedIntegers()->isBoundVar(d_owner, d_owner[0][i])) {
@@ -283,14 +275,10 @@ bool RepSetIterator::initialize(){
Trace("bound-int-rsi") << indexOrder[i] << " ";
}
Trace("bound-int-rsi") << std::endl;
- setIndexOrder(indexOrder);
+ setIndexOrder( indexOrder );
}
//now reset the indices
- for (unsigned i=0; i<d_index.size(); i++) {
- if (!resetIndex(i, true)){
- break;
- }
- }
+ do_reset_increment( -1, true );
return true;
}
@@ -298,46 +286,40 @@ void RepSetIterator::setIndexOrder( std::vector< int >& indexOrder ){
d_index_order.clear();
d_index_order.insert( d_index_order.begin(), indexOrder.begin(), indexOrder.end() );
//make the d_var_order mapping
- for( int i=0; i<(int)d_index_order.size(); i++ ){
+ for( unsigned i=0; i<d_index_order.size(); i++ ){
d_var_order[d_index_order[i]] = i;
}
}
-/*
-void RepSetIterator::setDomain( std::vector< RepDomain >& domain ){
- d_domain.clear();
- d_domain.insert( d_domain.begin(), domain.begin(), domain.end() );
- //we are done if a domain is empty
- for( int i=0; i<(int)d_domain.size(); i++ ){
- if( d_domain[i].empty() ){
- d_index.clear();
- }
- }
-}
-*/
-bool RepSetIterator::resetIndex( int i, bool initial ) {
+
+int RepSetIterator::resetIndex( int i, bool initial ) {
d_index[i] = 0;
- int ii = d_index_order[i];
- Trace("bound-int-rsi") << "Reset " << i << " " << ii << " " << initial << std::endl;
+ int v = d_var_order[i];
+ Trace("bound-int-rsi") << "Reset " << i << ", var order = " << v << ", initial = " << initial << std::endl;
//determine the current range
- if( d_enum_type[ii]==ENUM_RANGE ){
- if( initial || ( d_qe->getBoundedIntegers() && !d_qe->getBoundedIntegers()->isGroundRange( d_owner, d_owner[0][ii] ) ) ){
- Trace("bound-int-rsi") << "Getting range of " << d_owner[0][ii] << std::endl;
+ if( initial || ( d_owner.getKind()==FORALL && d_qe && d_qe->getBoundedIntegers() &&
+ d_qe->getBoundedIntegers()->isBoundVar( d_owner, d_owner[0][v] ) &&
+ !d_qe->getBoundedIntegers()->isGroundRange( d_owner, d_owner[0][v] ) ) ){
+ Trace("bound-int-rsi") << "Getting range of " << d_owner[0][v] << std::endl;
+ if( d_enum_type[v]==ENUM_INT_RANGE ){
Node actual_l;
Node l, u;
- if( d_qe->getBoundedIntegers() && d_qe->getBoundedIntegers()->isBoundVar( d_owner, d_owner[0][ii] ) ){
- d_qe->getBoundedIntegers()->getBoundValues( d_owner, d_owner[0][ii], this, l, u );
+ if( d_qe->getBoundedIntegers() ){
+ unsigned bvt = d_qe->getBoundedIntegers()->getBoundVarType( d_owner, d_owner[0][v] );
+ if( bvt==quantifiers::BoundedIntegers::BOUND_INT_RANGE ){
+ d_qe->getBoundedIntegers()->getBoundValues( d_owner, d_owner[0][v], this, l, u );
+ }
}
for( unsigned b=0; b<2; b++ ){
- if( d_bounds[b].find(ii)!=d_bounds[b].end() ){
- Trace("bound-int-rsi") << "May further limit bound(" << b << ") based on " << d_bounds[b][ii] << std::endl;
- if( b==0 && (l.isNull() || d_bounds[b][ii].getConst<Rational>() > l.getConst<Rational>()) ){
+ if( d_bounds[b].find(v)!=d_bounds[b].end() ){
+ Trace("bound-int-rsi") << "May further limit bound(" << b << ") based on " << d_bounds[b][v] << std::endl;
+ if( b==0 && (l.isNull() || d_bounds[b][v].getConst<Rational>() > l.getConst<Rational>()) ){
if( !l.isNull() ){
//bound was limited externally, record that the value lower bound is not equal to the term lower bound
- actual_l = NodeManager::currentNM()->mkNode( MINUS, d_bounds[b][ii], l );
+ actual_l = NodeManager::currentNM()->mkNode( MINUS, d_bounds[b][v], l );
}
- l = d_bounds[b][ii];
- }else if( b==1 && (u.isNull() || d_bounds[b][ii].getConst<Rational>() <= u.getConst<Rational>()) ){
- u = NodeManager::currentNM()->mkNode( MINUS, d_bounds[b][ii],
+ l = d_bounds[b][v];
+ }else if( b==1 && (u.isNull() || d_bounds[b][v].getConst<Rational>() <= u.getConst<Rational>()) ){
+ u = NodeManager::currentNM()->mkNode( MINUS, d_bounds[b][v],
NodeManager::currentNM()->mkConst( Rational(1) ) );
u = Rewriter::rewrite( u );
}
@@ -346,73 +328,109 @@ bool RepSetIterator::resetIndex( int i, bool initial ) {
if( l.isNull() || u.isNull() ){
//failed, abort the iterator
- d_index.clear();
- return false;
+ return -1;
}else{
- Trace("bound-int-rsi") << "Can limit bounds of " << d_owner[0][ii] << " to " << l << "..." << u << std::endl;
+ Trace("bound-int-rsi") << "Can limit bounds of " << d_owner[0][v] << " to " << l << "..." << u << std::endl;
Node range = Rewriter::rewrite( NodeManager::currentNM()->mkNode( MINUS, u, l ) );
Node ra = Rewriter::rewrite( NodeManager::currentNM()->mkNode( LEQ, range, NodeManager::currentNM()->mkConst( Rational( 9999 ) ) ) );
- d_domain[ii].clear();
+ d_domain[v].clear();
Node tl = l;
Node tu = u;
- if( d_qe->getBoundedIntegers() && d_qe->getBoundedIntegers()->isBoundVar( d_owner, d_owner[0][ii] ) ){
- d_qe->getBoundedIntegers()->getBounds( d_owner, d_owner[0][ii], this, tl, tu );
+ if( d_qe->getBoundedIntegers() && d_qe->getBoundedIntegers()->isBoundVar( d_owner, d_owner[0][v] ) ){
+ d_qe->getBoundedIntegers()->getBounds( d_owner, d_owner[0][v], this, tl, tu );
}
- d_lower_bounds[ii] = tl;
+ d_lower_bounds[v] = tl;
if( !actual_l.isNull() ){
//if bound was limited externally, must consider the offset
- d_lower_bounds[ii] = Rewriter::rewrite( NodeManager::currentNM()->mkNode( PLUS, tl, actual_l ) );
+ d_lower_bounds[v] = Rewriter::rewrite( NodeManager::currentNM()->mkNode( PLUS, tl, actual_l ) );
}
- if( ra==NodeManager::currentNM()->mkConst(true) ){
+ if( ra==d_qe->getTermDatabase()->d_true ){
long rr = range.getConst<Rational>().getNumerator().getLong()+1;
Trace("bound-int-rsi") << "Actual bound range is " << rr << std::endl;
- d_domain[ii].push_back( (int)rr );
+ d_domain[v].push_back( (int)rr );
+ if( rr<=0 ){
+ return 0;
+ }
}else{
- Trace("fmf-incomplete") << "Incomplete because of integer quantification, bounds are too big for " << d_owner[0][ii] << "." << std::endl;
- d_incomplete = true;
- d_domain[ii].push_back( 0 );
+ Trace("fmf-incomplete") << "Incomplete because of integer quantification, bounds are too big for " << d_owner[0][v] << "." << std::endl;
+ return -1;
}
}
- }else{
- Trace("bound-int-rsi") << d_owner[0][ii] << " has ground range, skip." << std::endl;
+ }else if( d_enum_type[v]==ENUM_SET_MEMBERS ){
+ Assert( d_qe->getBoundedIntegers()->getBoundVarType( d_owner, d_owner[0][v] )==quantifiers::BoundedIntegers::BOUND_SET_MEMBER );
+ Node srv = d_qe->getBoundedIntegers()->getSetRangeValue( d_owner, d_owner[0][v], this );
+ if( srv.isNull() ){
+ return -1;
+ }
+ Trace("bound-int-rsi") << "Bounded by set membership : " << srv << std::endl;
+ d_domain[v].clear();
+ d_setm_bounds[v].clear();
+ if( srv.getKind()!=EMPTYSET ){
+ //TODO: need term model, not value model
+ while( srv.getKind()==UNION ){
+ Assert( srv[1].getKind()==kind::SINGLETON );
+ d_setm_bounds[v].push_back( srv[1][0] );
+ srv = srv[0];
+ }
+ d_setm_bounds[v].push_back( srv[0] );
+ d_domain[v].push_back( d_setm_bounds[v].size() );
+ }else{
+ d_domain[v].push_back( 0 );
+ return 0;
+ }
}
}
- return true;
+ return 1;
}
-int RepSetIterator::increment2( int counter ){
+int RepSetIterator::increment2( int i ){
Assert( !isFinished() );
#ifdef DISABLE_EVAL_SKIP_MULTIPLE
- counter = (int)d_index.size()-1;
+ i = (int)d_index.size()-1;
#endif
//increment d_index
- if( counter>=0){
- Trace("rsi-debug") << "domain size of " << counter << " is " << domainSize(counter) << std::endl;
+ if( i>=0){
+ Trace("rsi-debug") << "domain size of " << i << " is " << domainSize(i) << std::endl;
}
- while( counter>=0 && d_index[counter]>=(int)(domainSize(counter)-1) ){
- counter--;
- if( counter>=0){
- Trace("rsi-debug") << "domain size of " << counter << " is " << domainSize(counter) << std::endl;
+ while( i>=0 && d_index[i]>=(int)(domainSize(i)-1) ){
+ i--;
+ if( i>=0){
+ Trace("rsi-debug") << "domain size of " << i << " is " << domainSize(i) << std::endl;
}
}
- if( counter==-1 ){
+ if( i==-1 ){
d_index.clear();
+ return -1;
}else{
- d_index[counter]++;
- bool emptyDomain = false;
- for( int i=(int)d_index.size()-1; i>counter; i-- ){
- if (!resetIndex(i)){
- break;
- }else if( domainSize(i)<=0 ){
- emptyDomain = true;
- }
+ Trace("rsi-debug") << "increment " << i << std::endl;
+ d_index[i]++;
+ return do_reset_increment( i );
+ }
+}
+
+int RepSetIterator::do_reset_increment( int i, bool initial ) {
+ bool emptyDomain = false;
+ for( unsigned ii=(i+1); ii<d_index.size(); ii++ ){
+ int ri_res = resetIndex( ii, initial );
+ if( ri_res==-1 ){
+ //failed
+ d_index.clear();
+ d_incomplete = true;
+ break;
+ }else if( ri_res==0 ){
+ emptyDomain = true;
}
+ //force next iteration if currently an empty domain
if( emptyDomain ){
- Trace("rsi-debug") << "This is an empty domain, increment again." << std::endl;
- return increment();
+ d_index[ii] = domainSize(ii)-1;
}
}
- return counter;
+ if( emptyDomain ){
+ Trace("rsi-debug") << "This is an empty domain, increment." << std::endl;
+ return increment();
+ }else{
+ return i;
+ }
}
int RepSetIterator::increment(){
@@ -427,33 +445,38 @@ bool RepSetIterator::isFinished(){
return d_index.empty();
}
-Node RepSetIterator::getTerm( int i ){
- Trace("rsi-debug") << "rsi : get term " << i << ", index order = " << d_index_order[i] << std::endl;
- //int index = d_index_order[i];
- int index = i;
- if( d_enum_type[index]==ENUM_DOMAIN_ELEMENTS ){
- TypeNode tn = d_types[index];
+Node RepSetIterator::getCurrentTerm( int v ){
+ Trace("rsi-debug") << "rsi : get term " << v << ", index order = " << d_index_order[v] << std::endl;
+ int ii = d_index_order[v];
+ int curr = d_index[ii];
+ if( d_enum_type[v]==ENUM_DOMAIN_ELEMENTS ){
+ TypeNode tn = d_types[v];
Assert( d_rep_set->d_type_reps.find( tn )!=d_rep_set->d_type_reps.end() );
- return d_rep_set->d_type_reps[tn][d_domain[index][d_index[index]]];
+ Assert( 0<=d_domain[v][curr] && d_domain[v][curr]<(int)d_rep_set->d_type_reps[tn].size() );
+ return d_rep_set->d_type_reps[tn][d_domain[v][curr]];
+ }else if( d_enum_type[v]==ENUM_SET_MEMBERS ){
+ Assert( 0<=curr && curr<(int)d_setm_bounds[v].size() );
+ return d_setm_bounds[v][curr];
}else{
- Trace("rsi-debug") << "Get, with offset : " << index << " " << d_lower_bounds[index] << " " << d_index[index] << std::endl;
- Node t = NodeManager::currentNM()->mkNode(PLUS, d_lower_bounds[index],
- NodeManager::currentNM()->mkConst( Rational(d_index[index]) ) );
+ Trace("rsi-debug") << "Get, with offset : " << v << " " << d_lower_bounds[v] << " " << curr << std::endl;
+ Assert( !d_lower_bounds[v].isNull() );
+ Node t = NodeManager::currentNM()->mkNode(PLUS, d_lower_bounds[v], NodeManager::currentNM()->mkConst( Rational(curr) ) );
t = Rewriter::rewrite( t );
return t;
}
}
void RepSetIterator::debugPrint( const char* c ){
- for( int i=0; i<(int)d_index.size(); i++ ){
- Debug( c ) << i << " : " << d_index[i] << " : " << getTerm( i ) << std::endl;
+ for( unsigned v=0; v<d_index.size(); v++ ){
+ Debug( c ) << v << " : " << getCurrentTerm( v ) << std::endl;
}
}
void RepSetIterator::debugPrintSmall( const char* c ){
Debug( c ) << "RI: ";
- for( int i=0; i<(int)d_index.size(); i++ ){
- Debug( c ) << d_index[i] << ": " << getTerm( i ) << " ";
+ for( unsigned v=0; v<d_index.size(); v++ ){
+ Debug( c ) << v << ": " << getCurrentTerm( v ) << " ";
}
Debug( c ) << std::endl;
}
+
diff --git a/src/theory/rep_set.h b/src/theory/rep_set.h
index 08fc7dd52..ee927de86 100644
--- a/src/theory/rep_set.h
+++ b/src/theory/rep_set.h
@@ -64,22 +64,42 @@ class RepSetIterator {
public:
enum {
ENUM_DOMAIN_ELEMENTS,
- ENUM_RANGE,
+ ENUM_INT_RANGE,
+ ENUM_SET_MEMBERS,
};
private:
QuantifiersEngine * d_qe;
//initialize function
bool initialize();
- //for enum ranges
+ //for int ranges
std::map< int, Node > d_lower_bounds;
+ //for set ranges
+ std::map< int, std::vector< Node > > d_setm_bounds;
//domain size
int domainSize( int i );
//node this is rep set iterator is for
Node d_owner;
- //reset index
- bool resetIndex( int i, bool initial = false );
+ //reset index, 1:success, 0:empty, -1:fail
+ int resetIndex( int i, bool initial = false );
/** set index order */
void setIndexOrder( std::vector< int >& indexOrder );
+ /** do reset increment the iterator at index=counter */
+ int do_reset_increment( int counter, bool initial = false );
+ //ordering for variables we are indexing over
+ // for example, given reps = { a, b } and quantifier forall( x, y, z ) P( x, y, z ) with d_index_order = { 2, 0, 1 },
+ // then we consider instantiations in this order:
+ // a/x a/y a/z
+ // a/x b/y a/z
+ // b/x a/y a/z
+ // b/x b/y a/z
+ // ...
+ std::vector< int > d_index_order;
+ //variables to index they are considered at
+ // for example, if d_index_order = { 2, 0, 1 }
+ // then d_var_order = { 0 -> 1, 1 -> 2, 2 -> 0 }
+ std::map< int, int > d_var_order;
+ //are we only considering a strict subset of the domain of the quantifier?
+ bool d_incomplete;
public:
RepSetIterator( QuantifiersEngine * qe, RepSet* rs );
~RepSetIterator(){}
@@ -92,43 +112,34 @@ public:
RepSet* d_rep_set;
//enumeration type?
std::vector< int > d_enum_type;
- //index we are considering
+ //current tuple we are considering
std::vector< int > d_index;
//types we are considering
std::vector< TypeNode > d_types;
//domain we are considering
std::vector< RepDomain > d_domain;
- //are we only considering a strict subset of the domain of the quantifier?
- bool d_incomplete;
- //ordering for variables we are indexing over
- // for example, given reps = { a, b } and quantifier forall( x, y, z ) P( x, y, z ) with d_index_order = { 2, 0, 1 },
- // then we consider instantiations in this order:
- // a/x a/y a/z
- // a/x b/y a/z
- // b/x a/y a/z
- // b/x b/y a/z
- // ...
- std::vector< int > d_index_order;
- //variables to index they are considered at
- // for example, if d_index_order = { 2, 0, 1 }
- // then d_var_order = { 0 -> 1, 1 -> 2, 2 -> 0 }
- std::map< int, int > d_var_order;
//intervals
std::map< int, Node > d_bounds[2];
public:
/** increment the iterator at index=counter */
- int increment2( int counter );
+ int increment2( int i );
/** increment the iterator */
int increment();
/** is the iterator finished? */
bool isFinished();
/** get the i_th term we are considering */
- Node getTerm( int i );
+ Node getCurrentTerm( int v );
/** get the number of terms we are considering */
int getNumTerms() { return (int)d_index_order.size(); }
/** debug print */
void debugPrint( const char* c );
void debugPrintSmall( const char* c );
+ //get index order, returns var #
+ int getIndexOrder( int v ) { return d_index_order[v]; }
+ //get variable order, returns index #
+ int getVariableOrder( int i ) { return d_var_order[i]; }
+ //is incomplete
+ bool isIncomplete() { return d_incomplete; }
};/* class RepSetIterator */
}/* CVC4::theory namespace */
diff --git a/src/theory/sep/kinds b/src/theory/sep/kinds
new file mode 100644
index 000000000..6c4ad33db
--- /dev/null
+++ b/src/theory/sep/kinds
@@ -0,0 +1,37 @@
+# kinds -*- sh -*-
+#
+# For documentation on this file format, please refer to
+# src/theory/builtin/kinds.
+#
+
+theory THEORY_SEP ::CVC4::theory::sep::TheorySep "theory/sep/theory_sep.h"
+typechecker "theory/sep/theory_sep_type_rules.h"
+
+properties polite stable-infinite parametric
+properties check propagate presolve getNextDecisionRequest
+
+rewriter ::CVC4::theory::sep::TheorySepRewriter "theory/sep/theory_sep_rewriter.h"
+
+# constants
+constant SEP_NIL_REF \
+ ::CVC4::NilRef \
+ ::CVC4::NilRefHashFunction \
+ "expr/sepconst.h" \
+ "the nil reference constant; payload is an instance of the CVC4::NilRef class"
+
+variable SEP_NIL "separation nil"
+
+operator SEP_EMP 1 "separation empty heap"
+operator SEP_PTO 2 "points to relation"
+operator SEP_STAR 2: "separation star"
+operator SEP_WAND 2 "separation magic wand"
+operator SEP_LABEL 2 "separation label"
+
+typerule SEP_NIL_REF ::CVC4::theory::sep::SepNilRefTypeRule
+typerule SEP_EMP ::CVC4::theory::sep::SepEmpTypeRule
+typerule SEP_PTO ::CVC4::theory::sep::SepPtoTypeRule
+typerule SEP_STAR ::CVC4::theory::sep::SepStarTypeRule
+typerule SEP_WAND ::CVC4::theory::sep::SepWandTypeRule
+typerule SEP_LABEL ::CVC4::theory::sep::SepLabelTypeRule
+
+endtheory
diff --git a/src/theory/sep/theory_sep.cpp b/src/theory/sep/theory_sep.cpp
new file mode 100644
index 000000000..836a04afa
--- /dev/null
+++ b/src/theory/sep/theory_sep.cpp
@@ -0,0 +1,1534 @@
+/********************* */
+/*! \file theory_sep.cpp
+ ** \verbatim
+ ** Original author: Andrew Reynolds
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2014 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Implementation of the theory of sep.
+ **
+ ** Implementation of the theory of sep.
+ **/
+
+
+#include "theory/sep/theory_sep.h"
+#include "theory/valuation.h"
+#include "expr/kind.h"
+#include <map>
+#include "theory/rewriter.h"
+#include "theory/theory_model.h"
+#include "options/sep_options.h"
+#include "options/smt_options.h"
+#include "smt/logic_exception.h"
+#include "theory/quantifiers_engine.h"
+#include "theory/quantifiers/term_database.h"
+
+using namespace std;
+
+namespace CVC4 {
+namespace theory {
+namespace sep {
+
+TheorySep::TheorySep(context::Context* c, context::UserContext* u, OutputChannel& out, Valuation valuation, const LogicInfo& logicInfo) :
+ Theory(THEORY_SEP, c, u, out, valuation, logicInfo),
+ d_notify(*this),
+ d_equalityEngine(d_notify, c, "theory::sep::TheorySep", true),
+ d_conflict(c, false),
+ d_reduce(u),
+ d_infer(c),
+ d_infer_exp(c),
+ d_spatial_assertions(c)
+{
+ d_true = NodeManager::currentNM()->mkConst<bool>(true);
+ d_false = NodeManager::currentNM()->mkConst<bool>(false);
+
+ // The kinds we are treating as function application in congruence
+ d_equalityEngine.addFunctionKind(kind::SEP_PTO);
+ //d_equalityEngine.addFunctionKind(kind::SEP_STAR);
+}
+
+TheorySep::~TheorySep() {
+ for( std::map< Node, HeapAssertInfo * >::iterator it = d_eqc_info.begin(); it != d_eqc_info.end(); ++it ){
+ delete it->second;
+ }
+}
+
+void TheorySep::setMasterEqualityEngine(eq::EqualityEngine* eq) {
+ d_equalityEngine.setMasterEqualityEngine(eq);
+}
+
+Node TheorySep::mkAnd( std::vector< TNode >& assumptions ) {
+ if( assumptions.empty() ){
+ return d_true;
+ }else if( assumptions.size()==1 ){
+ return assumptions[0];
+ }else{
+ return NodeManager::currentNM()->mkNode( kind::AND, assumptions );
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// PREPROCESSING
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+Node TheorySep::ppRewrite(TNode term) {
+ Trace("sep-pp") << "ppRewrite : " << term << std::endl;
+/*
+ Node s_atom = term.getKind()==kind::NOT ? term[0] : term;
+ if( s_atom.getKind()==kind::SEP_PTO || s_atom.getKind()==kind::SEP_STAR || s_atom.getKind()==kind::SEP_WAND || s_atom.getKind()==kind::SEP_EMP ){
+ //get the reference type (will compute d_type_references)
+ int card = 0;
+ TypeNode tn = getReferenceType( s_atom, card );
+ Trace("sep-pp") << " reference type is " << tn << ", card is " << card << std::endl;
+ }
+*/
+ return term;
+}
+
+//must process assertions at preprocess so that quantified assertions are processed properly
+void TheorySep::processAssertions( std::vector< Node >& assertions ) {
+ std::map< Node, bool > visited;
+ for( unsigned i=0; i<assertions.size(); i++ ){
+ processAssertion( assertions[i], visited );
+ }
+}
+
+void TheorySep::processAssertion( Node n, std::map< Node, bool >& visited ) {
+ if( visited.find( n )==visited.end() ){
+ visited[n] = true;
+ if( n.getKind()==kind::SEP_PTO || n.getKind()==kind::SEP_STAR || n.getKind()==kind::SEP_WAND || n.getKind()==kind::SEP_EMP ){
+ //get the reference type (will compute d_type_references)
+ int card = 0;
+ TypeNode tn = getReferenceType( n, card );
+ Trace("sep-pp") << " reference type is " << tn << ", card is " << card << std::endl;
+ }else{
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ processAssertion( n[i], visited );
+ }
+ }
+ }
+}
+
+Theory::PPAssertStatus TheorySep::ppAssert(TNode in, SubstitutionMap& outSubstitutions) {
+
+ return PP_ASSERT_STATUS_UNSOLVED;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// T-PROPAGATION / REGISTRATION
+/////////////////////////////////////////////////////////////////////////////
+
+
+bool TheorySep::propagate(TNode literal)
+{
+ Debug("sep") << "TheorySep::propagate(" << literal << ")" << std::endl;
+ // If already in conflict, no more propagation
+ if (d_conflict) {
+ Debug("sep") << "TheorySep::propagate(" << literal << "): already in conflict" << std::endl;
+ return false;
+ }
+ bool ok = d_out->propagate(literal);
+ if (!ok) {
+ d_conflict = true;
+ }
+ return ok;
+}/* TheorySep::propagate(TNode) */
+
+
+void TheorySep::explain(TNode literal, std::vector<TNode>& assumptions) {
+ if( literal.getKind()==kind::SEP_LABEL ||
+ ( literal.getKind()==kind::NOT && literal[0].getKind()==kind::SEP_LABEL ) ){
+ //labelled assertions are never given to equality engine and should only come from the outside
+ assumptions.push_back( literal );
+ }else{
+ // Do the work
+ bool polarity = literal.getKind() != kind::NOT;
+ TNode atom = polarity ? literal : literal[0];
+ if (atom.getKind() == kind::EQUAL || atom.getKind() == kind::IFF) {
+ d_equalityEngine.explainEquality( atom[0], atom[1], polarity, assumptions, NULL );
+ } else {
+ d_equalityEngine.explainPredicate( atom, polarity, assumptions );
+ }
+ }
+}
+
+void TheorySep::preRegisterTermRec(TNode t, std::map< TNode, bool >& visited ) {
+ if( visited.find( t )==visited.end() ){
+ visited[t] = true;
+ Trace("sep-prereg-debug") << "Preregister : " << t << std::endl;
+ if( t.getKind()==kind::SEP_NIL ){
+ Trace("sep-prereg") << "Preregister nil : " << t << std::endl;
+ //per type, all nil variable references are equal
+ TypeNode tn = t.getType();
+ std::map< TypeNode, Node >::iterator it = d_nil_ref.find( tn );
+ if( it==d_nil_ref.end() ){
+ Trace("sep-prereg") << "...set as reference." << std::endl;
+ d_nil_ref[tn] = t;
+ }else{
+ Node nr = it->second;
+ Trace("sep-prereg") << "...reference is " << nr << "." << std::endl;
+ if( t!=nr ){
+ if( d_reduce.find( t )==d_reduce.end() ){
+ d_reduce.insert( t );
+ Node lem = NodeManager::currentNM()->mkNode( tn.isBoolean() ? kind::IFF : kind::EQUAL, t, nr );
+ Trace("sep-lemma") << "Sep::Lemma: nil ref eq : " << lem << std::endl;
+ d_out->lemma( lem );
+ }
+ }
+ }
+ }else{
+ for( unsigned i=0; i<t.getNumChildren(); i++ ){
+ preRegisterTermRec( t[i], visited );
+ }
+ }
+ }
+}
+
+void TheorySep::preRegisterTerm(TNode term){
+ std::map< TNode, bool > visited;
+ preRegisterTermRec( term, visited );
+}
+
+
+void TheorySep::propagate(Effort e){
+
+}
+
+
+Node TheorySep::explain(TNode literal)
+{
+ Debug("sep") << "TheorySep::explain(" << literal << ")" << std::endl;
+ std::vector<TNode> assumptions;
+ explain(literal, assumptions);
+ return mkAnd(assumptions);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// SHARING
+/////////////////////////////////////////////////////////////////////////////
+
+
+void TheorySep::addSharedTerm(TNode t) {
+ Debug("sep") << "TheorySep::addSharedTerm(" << t << ")" << std::endl;
+ d_equalityEngine.addTriggerTerm(t, THEORY_SEP);
+}
+
+
+EqualityStatus TheorySep::getEqualityStatus(TNode a, TNode b) {
+ Assert(d_equalityEngine.hasTerm(a) && d_equalityEngine.hasTerm(b));
+ if (d_equalityEngine.areEqual(a, b)) {
+ // The terms are implied to be equal
+ return EQUALITY_TRUE;
+ }
+ else if (d_equalityEngine.areDisequal(a, b, false)) {
+ // The terms are implied to be dis-equal
+ return EQUALITY_FALSE;
+ }
+ return EQUALITY_UNKNOWN;//FALSE_IN_MODEL;
+}
+
+
+void TheorySep::computeCareGraph() {
+ Debug("sharing") << "Theory::computeCareGraph<" << getId() << ">()" << endl;
+ for (unsigned i = 0; i < d_sharedTerms.size(); ++ i) {
+ TNode a = d_sharedTerms[i];
+ TypeNode aType = a.getType();
+ for (unsigned j = i + 1; j < d_sharedTerms.size(); ++ j) {
+ TNode b = d_sharedTerms[j];
+ if (b.getType() != aType) {
+ // We don't care about the terms of different types
+ continue;
+ }
+ switch (d_valuation.getEqualityStatus(a, b)) {
+ case EQUALITY_TRUE_AND_PROPAGATED:
+ case EQUALITY_FALSE_AND_PROPAGATED:
+ // If we know about it, we should have propagated it, so we can skip
+ break;
+ default:
+ // Let's split on it
+ addCarePair(a, b);
+ break;
+ }
+ }
+ }
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// MODEL GENERATION
+/////////////////////////////////////////////////////////////////////////////
+
+
+void TheorySep::collectModelInfo( TheoryModel* m, bool fullModel )
+{
+ // Send the equality engine information to the model
+ m->assertEqualityEngine( &d_equalityEngine );
+
+ if( fullModel ){
+ for( std::map< TypeNode, Node >::iterator it = d_base_label.begin(); it != d_base_label.end(); ++it ){
+ Trace("sep-model") << "; Model for heap, type = " << it->first << " : " << std::endl;
+ computeLabelModel( it->second, d_tmodel );
+ if( d_label_model[it->second].d_heap_locs_model.empty() ){
+ Trace("sep-model") << "; [empty]" << std::endl;
+ }else{
+ for( unsigned j=0; j<d_label_model[it->second].d_heap_locs_model.size(); j++ ){
+ Assert( d_label_model[it->second].d_heap_locs_model[j].getKind()==kind::SINGLETON );
+ Node l = d_label_model[it->second].d_heap_locs_model[j][0];
+ Trace("sep-model") << "; " << l << " -> ";
+ if( d_pto_model[l].isNull() ){
+ Trace("sep-model") << "_";
+ }else{
+ Trace("sep-model") << d_pto_model[l];
+ }
+ Trace("sep-model") << std::endl;
+ }
+ }
+ Node nil = getNilRef( it->first );
+ Node vnil = d_valuation.getModel()->getRepresentative( nil );
+ Trace("sep-model") << "; sep.nil = " << vnil << std::endl;
+ Trace("sep-model") << std::endl;
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// NOTIFICATIONS
+/////////////////////////////////////////////////////////////////////////////
+
+
+void TheorySep::presolve() {
+ Trace("sep-pp") << "Presolving" << std::endl;
+ //TODO: cleanup if incremental?
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// MAIN SOLVER
+/////////////////////////////////////////////////////////////////////////////
+
+
+void TheorySep::check(Effort e) {
+ if (done() && !fullEffort(e) && e != EFFORT_LAST_CALL) {
+ return;
+ }
+
+ getOutputChannel().spendResource(options::theoryCheckStep());
+
+ TimerStat::CodeTimer checkTimer(d_checkTime);
+ Trace("sep-check") << "Sep::check(): " << e << endl;
+
+ while( !done() && !d_conflict ){
+ // Get all the assertions
+ Assertion assertion = get();
+ TNode fact = assertion.assertion;
+
+ Trace("sep-assert") << "TheorySep::check(): processing " << fact << std::endl;
+
+ bool polarity = fact.getKind() != kind::NOT;
+ TNode atom = polarity ? fact : fact[0];
+ if( atom.getKind()==kind::SEP_EMP ){
+ TypeNode tn = atom[0].getType();
+ if( d_emp_arg.find( tn )==d_emp_arg.end() ){
+ d_emp_arg[tn] = atom[0];
+ }else{
+ //normalize argument TODO
+ }
+ }
+ TNode s_atom = atom.getKind()==kind::SEP_LABEL ? atom[0] : atom;
+ TNode s_lbl = atom.getKind()==kind::SEP_LABEL ? atom[1] : TNode::null();
+ bool is_spatial = s_atom.getKind()==kind::SEP_STAR || s_atom.getKind()==kind::SEP_WAND || s_atom.getKind()==kind::SEP_PTO || s_atom.getKind()==kind::SEP_EMP;
+ if( is_spatial && s_lbl.isNull() ){
+ if( d_reduce.find( fact )==d_reduce.end() ){
+ Trace("sep-lemma-debug") << "Reducing unlabelled assertion " << atom << std::endl;
+ d_reduce.insert( fact );
+ //introduce top-level label, add iff
+ int card;
+ TypeNode refType = getReferenceType( s_atom, card );
+ Trace("sep-lemma-debug") << "...reference type is : " << refType << ", card is " << card << std::endl;
+ Node b_lbl = getBaseLabel( refType );
+ Node s_atom_new = NodeManager::currentNM()->mkNode( kind::SEP_LABEL, s_atom, b_lbl );
+ Node lem;
+ if( polarity ){
+ lem = NodeManager::currentNM()->mkNode( kind::OR, s_atom.negate(), s_atom_new );
+ }else{
+ lem = NodeManager::currentNM()->mkNode( kind::OR, s_atom, s_atom_new.negate() );
+ }
+ Trace("sep-lemma-debug") << "Sep::Lemma : base reduction : " << lem << std::endl;
+ d_out->lemma( lem );
+ }
+ }else{
+ //do reductions
+ if( is_spatial ){
+ if( d_reduce.find( fact )==d_reduce.end() ){
+ Trace("sep-lemma-debug") << "Reducing assertion " << fact << std::endl;
+ d_reduce.insert( fact );
+ Node conc;
+ std::map< Node, Node >::iterator its = d_red_conc[s_lbl].find( s_atom );
+ if( its==d_red_conc[s_lbl].end() ){
+ //make conclusion based on type of assertion
+ if( s_atom.getKind()==kind::SEP_STAR || s_atom.getKind()==kind::SEP_WAND ){
+ std::vector< Node > children;
+ std::vector< Node > c_lems;
+ int card;
+ TypeNode tn = getReferenceType( s_atom, card );
+ Assert( d_reference_bound.find( tn )!=d_reference_bound.end() );
+ c_lems.push_back( NodeManager::currentNM()->mkNode( kind::SUBSET, s_lbl, d_reference_bound[tn] ) );
+ if( options::sepPreciseBound() ){
+ //more precise bound
+ Trace("sep-bound") << "Propagate Bound(" << s_lbl << ") = ";
+ Assert( d_lbl_reference_bound.find( s_lbl )!=d_lbl_reference_bound.end() );
+ for( unsigned j=0; j<d_lbl_reference_bound[s_lbl].size(); j++ ){
+ Trace("sep-bound") << d_lbl_reference_bound[s_lbl][j] << " ";
+ }
+ Trace("sep-bound") << std::endl << " to children of " << s_atom << std::endl;
+ //int rb_start = 0;
+ for( unsigned j=0; j<s_atom.getNumChildren(); j++ ){
+ int ccard = 0;
+ getReferenceType( s_atom, ccard, j );
+ Node c_lbl = getLabel( s_atom, j, s_lbl );
+ Trace("sep-bound") << " for " << c_lbl << ", card = " << ccard << " : ";
+ std::vector< Node > bound_loc;
+ bound_loc.insert( bound_loc.end(), d_references[s_atom][j].begin(), d_references[s_atom][j].end() );
+/* //this is unsound
+ for( int k=0; k<ccard; k++ ){
+ Assert( rb_start<(int)d_lbl_reference_bound[s_lbl].size() );
+ d_lbl_reference_bound[c_lbl].push_back( d_lbl_reference_bound[s_lbl][rb_start] );
+ Trace("sep-bound") << d_lbl_reference_bound[s_lbl][rb_start] << " ";
+ bound_loc.push_back( d_lbl_reference_bound[s_lbl][rb_start] );
+ rb_start++;
+ }
+*/
+ //carry all locations for now
+ bound_loc.insert( bound_loc.end(), d_lbl_reference_bound[s_lbl].begin(), d_lbl_reference_bound[s_lbl].end() );
+ Trace("sep-bound") << std::endl;
+ Node bound_v = mkUnion( tn, bound_loc );
+ Trace("sep-bound") << " ...bound value : " << bound_v << std::endl;
+ children.push_back( NodeManager::currentNM()->mkNode( kind::SUBSET, c_lbl, bound_v ) );
+ }
+ Trace("sep-bound") << "Done propagate Bound(" << s_lbl << ")" << std::endl;
+ }
+ std::vector< Node > labels;
+ getLabelChildren( s_atom, s_lbl, children, labels );
+ Node empSet = NodeManager::currentNM()->mkConst(EmptySet(s_lbl.getType().toType()));
+ Assert( children.size()>1 );
+ if( s_atom.getKind()==kind::SEP_STAR ){
+ //reduction for heap : union, pairwise disjoint
+ Node ulem = NodeManager::currentNM()->mkNode( kind::UNION, labels[0], labels[1] );
+ for( unsigned i=2; i<labels.size(); i++ ){
+ ulem = NodeManager::currentNM()->mkNode( kind::UNION, ulem, labels[i] );
+ }
+ ulem = s_lbl.eqNode( ulem );
+ Trace("sep-lemma-debug") << "Sep::Lemma : star reduction, union : " << ulem << std::endl;
+ c_lems.push_back( ulem );
+ for( unsigned i=0; i<labels.size(); i++ ){
+ for( unsigned j=(i+1); j<labels.size(); j++ ){
+ Node s = NodeManager::currentNM()->mkNode( kind::INTERSECTION, labels[i], labels[j] );
+ Node ilem = s.eqNode( empSet );
+ Trace("sep-lemma-debug") << "Sep::Lemma : star reduction, disjoint : " << ilem << std::endl;
+ c_lems.push_back( ilem );
+ }
+ }
+ }else{
+ Node ulem = NodeManager::currentNM()->mkNode( kind::UNION, s_lbl, labels[0] );
+ ulem = ulem.eqNode( labels[1] );
+ Trace("sep-lemma-debug") << "Sep::Lemma : wand reduction, union : " << ulem << std::endl;
+ c_lems.push_back( ulem );
+ Node s = NodeManager::currentNM()->mkNode( kind::INTERSECTION, s_lbl, labels[0] );
+ Node ilem = s.eqNode( empSet );
+ Trace("sep-lemma-debug") << "Sep::Lemma : wand reduction, disjoint : " << ilem << std::endl;
+ c_lems.push_back( ilem );
+ }
+ //send out definitional lemmas for introduced sets
+ for( unsigned j=0; j<c_lems.size(); j++ ){
+ Trace("sep-lemma") << "Sep::Lemma : definition : " << c_lems[j] << std::endl;
+ d_out->lemma( c_lems[j] );
+ }
+ //children.insert( children.end(), c_lems.begin(), c_lems.end() );
+ conc = NodeManager::currentNM()->mkNode( kind::AND, children );
+ }else if( s_atom.getKind()==kind::SEP_PTO ){
+ Node ss = NodeManager::currentNM()->mkNode( kind::SINGLETON, s_atom[0] );
+ if( s_lbl!=ss ){
+ conc = s_lbl.eqNode( ss );
+ }
+ Node ssn = NodeManager::currentNM()->mkNode( kind::EQUAL, s_atom[0], getNilRef(s_atom[0].getType()) ).negate();
+ conc = conc.isNull() ? ssn : NodeManager::currentNM()->mkNode( kind::AND, conc, ssn );
+ }else{
+ //labeled emp should be rewritten
+ Assert( false );
+ }
+ d_red_conc[s_lbl][s_atom] = conc;
+ }else{
+ conc = its->second;
+ }
+ if( !conc.isNull() ){
+ bool use_polarity = s_atom.getKind()==kind::SEP_WAND ? !polarity : polarity;
+ if( !use_polarity ){
+ // introduce guard, assert positive version
+ Trace("sep-lemma-debug") << "Negated spatial constraint asserted to sep theory: " << fact << std::endl;
+ Node lit = Rewriter::rewrite( NodeManager::currentNM()->mkSkolem( "G", NodeManager::currentNM()->booleanType() ) );
+ lit = getValuation().ensureLiteral( lit );
+ d_neg_guard[s_lbl][s_atom] = lit;
+ Trace("sep-lemma-debug") << "Neg guard : " << s_lbl << " " << s_atom << " " << lit << std::endl;
+ AlwaysAssert( !lit.isNull() );
+ d_out->requirePhase( lit, true );
+ d_neg_guards.push_back( lit );
+ d_guard_to_assertion[lit] = s_atom;
+ //Node lem = NodeManager::currentNM()->mkNode( kind::IFF, lit, conc );
+ Node lem = NodeManager::currentNM()->mkNode( kind::OR, lit.negate(), conc );
+ Trace("sep-lemma") << "Sep::Lemma : (neg) reduction : " << lem << std::endl;
+ d_out->lemma( lem );
+ }else{
+ //reduce based on implication
+ Node ant = atom;
+ if( polarity ){
+ ant = atom.negate();
+ }
+ Node lem = NodeManager::currentNM()->mkNode( kind::OR, ant, conc );
+ Trace("sep-lemma") << "Sep::Lemma : reduction : " << lem << std::endl;
+ d_out->lemma( lem );
+ }
+ }else{
+ Trace("sep-lemma-debug") << "Trivial conclusion, do not add lemma." << std::endl;
+ }
+ }
+ }
+ //assert to equality engine
+ if( !is_spatial ){
+ Trace("sep-assert") << "Asserting " << atom << ", pol = " << polarity << " to EE..." << std::endl;
+ if( s_atom.getKind()==kind::EQUAL ){
+ d_equalityEngine.assertEquality(atom, polarity, fact);
+ }else{
+ d_equalityEngine.assertPredicate(atom, polarity, fact);
+ }
+ Trace("sep-assert") << "Done asserting " << atom << " to EE." << std::endl;
+ }else if( s_atom.getKind()==kind::SEP_PTO ){
+ Node pto_lbl = NodeManager::currentNM()->mkNode( kind::SINGLETON, s_atom[0] );
+ if( polarity && s_lbl!=pto_lbl ){
+ //also propagate equality
+ Node eq = s_lbl.eqNode( pto_lbl );
+ Trace("sep-assert") << "Asserting implied equality " << eq << " to EE..." << std::endl;
+ d_equalityEngine.assertEquality(eq, true, fact);
+ Trace("sep-assert") << "Done asserting implied equality " << eq << " to EE." << std::endl;
+ }
+ //associate the equivalence class of the lhs with this pto
+ Node r = getRepresentative( s_lbl );
+ HeapAssertInfo * ei = getOrMakeEqcInfo( r, true );
+ addPto( ei, r, atom, polarity );
+ }
+ //maybe propagate
+ doPendingFacts();
+ //add to spatial assertions
+ if( !d_conflict && is_spatial ){
+ d_spatial_assertions.push_back( fact );
+ }
+ }
+ }
+
+ if( e == EFFORT_LAST_CALL && !d_conflict && !d_valuation.needCheck() ){
+ Trace("sep-process") << "Checking heap at full effort..." << std::endl;
+ d_label_model.clear();
+ d_tmodel.clear();
+ d_pto_model.clear();
+ Trace("sep-process") << "---Locations---" << std::endl;
+ for( std::map< TypeNode, std::vector< Node > >::iterator itt = d_type_references_all.begin(); itt != d_type_references_all.end(); ++itt ){
+ for( unsigned k=0; k<itt->second.size(); k++ ){
+ Node t = itt->second[k];
+ Trace("sep-process") << " " << t << " = ";
+ if( d_valuation.getModel()->hasTerm( t ) ){
+ Node v = d_valuation.getModel()->getRepresentative( t );
+ Trace("sep-process") << v << std::endl;
+ d_tmodel[v] = t;
+ }else{
+ Trace("sep-process") << "?" << std::endl;
+ }
+ }
+ }
+ Trace("sep-process") << "---" << std::endl;
+ //build positive/negative assertion lists for labels
+ std::map< Node, bool > assert_active;
+ //get the inactive assertions
+ std::map< Node, std::vector< Node > > lbl_to_assertions;
+ for( NodeList::const_iterator i = d_spatial_assertions.begin(); i != d_spatial_assertions.end(); ++i ) {
+ Node fact = (*i);
+ bool polarity = fact.getKind() != kind::NOT;
+ TNode atom = polarity ? fact : fact[0];
+ Assert( atom.getKind()==kind::SEP_LABEL );
+ TNode s_atom = atom[0];
+ TNode s_lbl = atom[1];
+ lbl_to_assertions[s_lbl].push_back( fact );
+ //check whether assertion is active : either polarity=true, or guard is not asserted false
+ assert_active[fact] = true;
+ bool use_polarity = s_atom.getKind()==kind::SEP_WAND ? !polarity : polarity;
+ if( use_polarity ){
+ if( s_atom.getKind()==kind::SEP_PTO ){
+ Node vv = d_valuation.getModel()->getRepresentative( s_atom[0] );
+ if( d_pto_model.find( vv )==d_pto_model.end() ){
+ Trace("sep-inst") << "Pto : " << s_atom[0] << " (" << vv << ") -> " << s_atom[1] << std::endl;
+ d_pto_model[vv] = s_atom[1];
+ }
+ }
+ }else{
+ if( d_neg_guard[s_lbl].find( s_atom )!=d_neg_guard[s_lbl].end() ){
+ //check if the guard is asserted positively
+ Node guard = d_neg_guard[s_lbl][s_atom];
+ bool value;
+ if( getValuation().hasSatValue( guard, value ) ) {
+ assert_active[fact] = value;
+ }
+ }
+ }
+ }
+ //(recursively) set inactive sub-assertions
+ for( NodeList::const_iterator i = d_spatial_assertions.begin(); i != d_spatial_assertions.end(); ++i ) {
+ Node fact = (*i);
+ if( !assert_active[fact] ){
+ setInactiveAssertionRec( fact, lbl_to_assertions, assert_active );
+ }
+ }
+ //set up model information based on active assertions
+ for( NodeList::const_iterator i = d_spatial_assertions.begin(); i != d_spatial_assertions.end(); ++i ) {
+ Node fact = (*i);
+ bool polarity = fact.getKind() != kind::NOT;
+ TNode atom = polarity ? fact : fact[0];
+ TNode s_atom = atom[0];
+ TNode s_lbl = atom[1];
+ if( assert_active[fact] ){
+ computeLabelModel( s_lbl, d_tmodel );
+ }
+ }
+ //debug print
+ if( Trace.isOn("sep-process") ){
+ Trace("sep-process") << "--- Current spatial assertions : " << std::endl;
+ for( NodeList::const_iterator i = d_spatial_assertions.begin(); i != d_spatial_assertions.end(); ++i ) {
+ Node fact = (*i);
+ Trace("sep-process") << " " << fact;
+ if( !assert_active[fact] ){
+ Trace("sep-process") << " [inactive]";
+ }
+ Trace("sep-process") << std::endl;
+ }
+ Trace("sep-process") << "---" << std::endl;
+ }
+ if(Trace.isOn("sep-eqc")) {
+ eq::EqClassesIterator eqcs2_i = eq::EqClassesIterator( &d_equalityEngine );
+ Trace("sep-eqc") << "EQC:" << std::endl;
+ while( !eqcs2_i.isFinished() ){
+ Node eqc = (*eqcs2_i);
+ eq::EqClassIterator eqc2_i = eq::EqClassIterator( eqc, &d_equalityEngine );
+ Trace("sep-eqc") << "Eqc( " << eqc << " ) : { ";
+ while( !eqc2_i.isFinished() ) {
+ if( (*eqc2_i)!=eqc ){
+ Trace("sep-eqc") << (*eqc2_i) << " ";
+ }
+ ++eqc2_i;
+ }
+ Trace("sep-eqc") << " } " << std::endl;
+ ++eqcs2_i;
+ }
+ Trace("sep-eqc") << std::endl;
+ }
+
+ if( options::sepCheckNeg() ){
+ //get active labels
+ std::map< Node, bool > active_lbl;
+ if( options::sepMinimalRefine() ){
+ for( NodeList::const_iterator i = d_spatial_assertions.begin(); i != d_spatial_assertions.end(); ++i ) {
+ Node fact = (*i);
+ bool polarity = fact.getKind() != kind::NOT;
+ TNode atom = polarity ? fact : fact[0];
+ TNode s_atom = atom[0];
+ bool use_polarity = s_atom.getKind()==kind::SEP_WAND ? !polarity : polarity;
+ if( !use_polarity ){
+ Assert( assert_active.find( fact )!=assert_active.end() );
+ if( assert_active[fact] ){
+ Assert( atom.getKind()==kind::SEP_LABEL );
+ TNode s_lbl = atom[1];
+ if( d_label_map[s_atom].find( s_lbl )!=d_label_map[s_atom].end() ){
+ Trace("sep-process-debug") << "Active lbl : " << s_lbl << std::endl;
+ active_lbl[s_lbl] = true;
+ }
+ }
+ }
+ }
+ }
+
+ //process spatial assertions
+ bool addedLemma = false;
+ bool needAddLemma = false;
+ for( NodeList::const_iterator i = d_spatial_assertions.begin(); i != d_spatial_assertions.end(); ++i ) {
+ Node fact = (*i);
+ bool polarity = fact.getKind() != kind::NOT;
+ TNode atom = polarity ? fact : fact[0];
+ TNode s_atom = atom[0];
+
+ bool use_polarity = s_atom.getKind()==kind::SEP_WAND ? !polarity : polarity;
+ Trace("sep-process-debug") << " check atom : " << s_atom << " use polarity " << use_polarity << std::endl;
+ if( !use_polarity ){
+ Assert( assert_active.find( fact )!=assert_active.end() );
+ if( assert_active[fact] ){
+ Assert( atom.getKind()==kind::SEP_LABEL );
+ TNode s_lbl = atom[1];
+ Trace("sep-process") << "--> Active negated atom : " << s_atom << ", lbl = " << s_lbl << std::endl;
+ //add refinement lemma
+ if( d_label_map[s_atom].find( s_lbl )!=d_label_map[s_atom].end() ){
+ needAddLemma = true;
+ int card;
+ TypeNode tn = getReferenceType( s_atom, card );
+ tn = NodeManager::currentNM()->mkSetType(tn);
+ //tn = NodeManager::currentNM()->mkSetType(NodeManager::currentNM()->mkRefType(tn));
+ Node o_b_lbl_mval = d_label_model[s_lbl].getValue( tn );
+ Trace("sep-process") << " Model for " << s_lbl << " : " << o_b_lbl_mval << std::endl;
+
+ //get model values
+ std::map< int, Node > mvals;
+ for( std::map< int, Node >::iterator itl = d_label_map[s_atom][s_lbl].begin(); itl != d_label_map[s_atom][s_lbl].end(); ++itl ){
+ Node sub_lbl = itl->second;
+ int sub_index = itl->first;
+ computeLabelModel( sub_lbl, d_tmodel );
+ Node lbl_mval = d_label_model[sub_lbl].getValue( tn );
+ Trace("sep-process-debug") << " child " << sub_index << " : " << sub_lbl << ", mval = " << lbl_mval << std::endl;
+ mvals[sub_index] = lbl_mval;
+ }
+
+ // Now, assert model-instantiated implication based on the negation
+ Assert( d_label_model.find( s_lbl )!=d_label_model.end() );
+ std::vector< Node > conc;
+ bool inst_success = true;
+ if( options::sepExp() ){
+ //old refinement lemmas
+ for( std::map< int, Node >::iterator itl = d_label_map[s_atom][s_lbl].begin(); itl != d_label_map[s_atom][s_lbl].end(); ++itl ){
+ int sub_index = itl->first;
+ std::map< Node, Node > visited;
+ Node c = applyLabel( s_atom[itl->first], mvals[sub_index], visited );
+ Trace("sep-process-debug") << " applied inst : " << c << std::endl;
+ if( s_atom.getKind()==kind::SEP_STAR || sub_index==0 ){
+ conc.push_back( c.negate() );
+ }else{
+ conc.push_back( c );
+ }
+ }
+ }else{
+ //new refinement
+ std::map< Node, Node > visited;
+ Node inst = instantiateLabel( s_atom, s_lbl, s_lbl, o_b_lbl_mval, visited, d_pto_model, d_tmodel, tn, active_lbl );
+ Trace("sep-inst-debug") << " applied inst : " << inst << std::endl;
+ if( inst.isNull() ){
+ inst_success = false;
+ }else{
+ inst = Rewriter::rewrite( inst );
+ if( inst==( polarity ? d_true : d_false ) ){
+ inst_success = false;
+ }
+ conc.push_back( polarity ? inst : inst.negate() );
+ }
+ }
+ if( inst_success ){
+ std::vector< Node > lemc;
+ Node pol_atom = atom;
+ if( polarity ){
+ pol_atom = atom.negate();
+ }
+ lemc.push_back( pol_atom );
+ //lemc.push_back( s_lbl.eqNode( o_b_lbl_mval ).negate() );
+ //lemc.push_back( NodeManager::currentNM()->mkNode( kind::SUBSET, o_b_lbl_mval, s_lbl ).negate() );
+ lemc.insert( lemc.end(), conc.begin(), conc.end() );
+ Node lem = NodeManager::currentNM()->mkNode( kind::OR, lemc );
+ if( std::find( d_refinement_lem[s_atom][s_lbl].begin(), d_refinement_lem[s_atom][s_lbl].end(), lem )==d_refinement_lem[s_atom][s_lbl].end() ){
+ d_refinement_lem[s_atom][s_lbl].push_back( lem );
+ Trace("sep-process") << "-----> refinement lemma (#" << d_refinement_lem[s_atom][s_lbl].size() << ") : " << lem << std::endl;
+ Trace("sep-lemma") << "Sep::Lemma : negated star/wand refinement : " << lem << std::endl;
+ d_out->lemma( lem );
+ addedLemma = true;
+ }else{
+ Trace("sep-process") << "*** repeated refinement lemma : " << lem << std::endl;
+ }
+ }
+ }else{
+ Trace("sep-process-debug") << " no children." << std::endl;
+ Assert( s_atom.getKind()==kind::SEP_PTO );
+ }
+ }else{
+ Trace("sep-process-debug") << "--> inactive negated assertion " << s_atom << std::endl;
+ }
+ }
+ }
+ if( !addedLemma ){
+ if( needAddLemma ){
+ Trace("sep-process") << "WARNING : could not find refinement lemma!!!" << std::endl;
+ Assert( false );
+ d_out->setIncomplete();
+ }
+ }
+ }
+ }
+ Trace("sep-check") << "Sep::check(): " << e << " done, conflict=" << d_conflict.get() << endl;
+}
+
+
+Node TheorySep::getNextDecisionRequest() {
+ for( unsigned i=0; i<d_neg_guards.size(); i++ ){
+ Node g = d_neg_guards[i];
+ bool success = true;
+ if( getLogicInfo().isQuantified() ){
+ Assert( d_guard_to_assertion.find( g )!= d_guard_to_assertion.end() );
+ Node a = d_guard_to_assertion[g];
+ Node q = quantifiers::TermDb::getInstConstAttr( a );
+ if( !q.isNull() ){
+ //must wait to decide on counterexample literal from quantified formula
+ Node cel = getQuantifiersEngine()->getTermDatabase()->getCounterexampleLiteral( q );
+ bool value;
+ if( d_valuation.hasSatValue( cel, value ) ){
+ success = value;
+ }else{
+ Trace("sep-dec-debug") << "TheorySep::getNextDecisionRequest : wait to decide on " << g << " until " << cel << " is set " << std::endl;
+ success = false;
+ }
+ }
+ }
+ if( success ){
+ bool value;
+ if( !d_valuation.hasSatValue( g, value ) ) {
+ Trace("sep-dec") << "TheorySep::getNextDecisionRequest : " << g << " (" << i << "/" << d_neg_guards.size() << ")" << std::endl;
+ return g;
+ }
+ }
+ }
+ Trace("sep-dec-debug") << "TheorySep::getNextDecisionRequest : null" << std::endl;
+ return Node::null();
+}
+
+void TheorySep::conflict(TNode a, TNode b) {
+ Trace("sep-conflict") << "Sep::conflict : " << a << " " << b << std::endl;
+ Node conflictNode;
+ if (a.getKind() == kind::CONST_BOOLEAN) {
+ conflictNode = explain(a.iffNode(b));
+ } else {
+ conflictNode = explain(a.eqNode(b));
+ }
+ d_conflict = true;
+ d_out->conflict( conflictNode );
+}
+
+
+TheorySep::HeapAssertInfo::HeapAssertInfo( context::Context* c ) : d_pto(c), d_has_neg_pto(c,false) {
+
+}
+
+TheorySep::HeapAssertInfo * TheorySep::getOrMakeEqcInfo( Node n, bool doMake ) {
+ std::map< Node, HeapAssertInfo* >::iterator e_i = d_eqc_info.find( n );
+ if( e_i==d_eqc_info.end() ){
+ if( doMake ){
+ HeapAssertInfo* ei = new HeapAssertInfo( getSatContext() );
+ d_eqc_info[n] = ei;
+ return ei;
+ }else{
+ return NULL;
+ }
+ }else{
+ return (*e_i).second;
+ }
+}
+
+TypeNode TheorySep::getReferenceType( Node atom, int& card, int index ) {
+ Trace("sep-type") << "getReference type " << atom << " " << index << std::endl;
+ Assert( atom.getKind()==kind::SEP_PTO || atom.getKind()==kind::SEP_STAR || atom.getKind()==kind::SEP_WAND || atom.getKind()==kind::SEP_EMP || index!=-1 );
+ std::map< int, TypeNode >::iterator it = d_reference_type[atom].find( index );
+ if( it==d_reference_type[atom].end() ){
+ card = 0;
+ TypeNode tn;
+ if( index==-1 && ( atom.getKind()==kind::SEP_STAR || atom.getKind()==kind::SEP_WAND ) ){
+ for( unsigned i=0; i<atom.getNumChildren(); i++ ){
+ int cardc = 0;
+ TypeNode ctn = getReferenceType( atom, cardc, i );
+ if( !ctn.isNull() ){
+ tn = ctn;
+ }
+ for( unsigned j=0; j<d_references[atom][i].size(); j++ ){
+ if( std::find( d_references[atom][index].begin(), d_references[atom][index].end(), d_references[atom][i][j] )==d_references[atom][index].end() ){
+ d_references[atom][index].push_back( d_references[atom][i][j] );
+ }
+ }
+ card = card + cardc;
+ }
+ }else{
+ Node n = index==-1 ? atom : atom[index];
+ //will compute d_references as well
+ std::map< Node, int > visited;
+ tn = getReferenceType2( atom, card, index, n, visited );
+ }
+ if( tn.isNull() && index==-1 ){
+ tn = NodeManager::currentNM()->booleanType();
+ }
+ d_reference_type[atom][index] = tn;
+ d_reference_type_card[atom][index] = card;
+ Trace("sep-type") << "...ref type return " << card << " for " << atom << " " << index << std::endl;
+ //add to d_type_references
+ if( index==-1 ){
+ //only contributes if top-level (index=-1)
+ for( unsigned i=0; i<d_references[atom][index].size(); i++ ){
+ Assert( !d_references[atom][index][i].isNull() );
+ if( std::find( d_type_references[tn].begin(), d_type_references[tn].end(), d_references[atom][index][i] )==d_type_references[tn].end() ){
+ d_type_references[tn].push_back( d_references[atom][index][i] );
+ }
+ }
+ // update maximum cardinality value
+ if( card>(int)d_card_max[tn] ){
+ d_card_max[tn] = card;
+ }
+ }
+ return tn;
+ }else{
+ Assert( d_reference_type_card[atom].find( index )!=d_reference_type_card[atom].end() );
+ card = d_reference_type_card[atom][index];
+ return it->second;
+ }
+}
+
+TypeNode TheorySep::getReferenceType2( Node atom, int& card, int index, Node n, std::map< Node, int >& visited ) {
+ if( visited.find( n )==visited.end() ){
+ Trace("sep-type-debug") << "visit : " << n << " : " << atom << " " << index << std::endl;
+ visited[n] = -1;
+ if( n.getKind()==kind::SEP_PTO ){
+ TypeNode tn1 = n[0].getType();
+ TypeNode tn2 = n[1].getType();
+ if( quantifiers::TermDb::hasBoundVarAttr( n[0] ) ){
+ d_reference_bound_invalid[tn1] = true;
+ }else{
+ if( std::find( d_references[atom][index].begin(), d_references[atom][index].end(), n[0] )==d_references[atom][index].end() ){
+ d_references[atom][index].push_back( n[0] );
+ }
+ }
+ std::map< TypeNode, TypeNode >::iterator itt = d_loc_to_data_type.find( tn1 );
+ if( itt==d_loc_to_data_type.end() ){
+ Trace("sep-type") << "Sep: assume location type " << tn1 << " is associated with data type " << tn2 << " (from " << atom << ")" << std::endl;
+ d_loc_to_data_type[tn1] = tn2;
+ }else{
+ if( itt->second!=tn2 ){
+ std::stringstream ss;
+ ss << "ERROR: location type " << tn1 << " is already associated with data type " << itt->second << ", offending atom is " << atom << " with data type " << tn2 << std::endl;
+ throw LogicException(ss.str());
+ Assert( false );
+ }
+ }
+ card = 1;
+ visited[n] = card;
+ return tn1;
+ //return n[1].getType();
+ }else if( n.getKind()==kind::SEP_EMP ){
+ card = 1;
+ visited[n] = card;
+ return n[0].getType();
+ }else if( n.getKind()==kind::SEP_STAR || n.getKind()==kind::SEP_WAND ){
+ Assert( n!=atom );
+ //get the references
+ card = 0;
+ TypeNode tn = getReferenceType( n, card );
+ for( unsigned j=0; j<d_references[n][-1].size(); j++ ){
+ if( std::find( d_references[atom][index].begin(), d_references[atom][index].end(), d_references[n][-1][j] )==d_references[atom][index].end() ){
+ d_references[atom][index].push_back( d_references[n][-1][j] );
+ }
+ }
+ visited[n] = card;
+ return tn;
+ }else{
+ card = 0;
+ TypeNode otn;
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ int cardc = 0;
+ TypeNode tn = getReferenceType2( atom, cardc, index, n[i], visited );
+ if( !tn.isNull() ){
+ otn = tn;
+ }
+ card = cardc>card ? cardc : card;
+ }
+ visited[n] = card;
+ return otn;
+ }
+ }else{
+ Trace("sep-type-debug") << "already visit : " << n << " : " << atom << " " << index << std::endl;
+ card = 0;
+ return TypeNode::null();
+ }
+}
+/*
+
+int TheorySep::getCardinality( Node n, std::vector< Node >& refs ) {
+ std::map< Node, int > visited;
+ return getCardinality2( n, refs, visited );
+}
+
+int TheorySep::getCardinality2( Node n, std::vector< Node >& refs, std::map< Node, int >& visited ) {
+ std::map< Node, int >::iterator it = visited.find( n );
+ if( it!=visited.end() ){
+ return it->second;
+ }else{
+
+
+ }
+}
+*/
+
+Node TheorySep::getBaseLabel( TypeNode tn ) {
+ std::map< TypeNode, Node >::iterator it = d_base_label.find( tn );
+ if( it==d_base_label.end() ){
+ Trace("sep") << "Make base label for " << tn << std::endl;
+ std::stringstream ss;
+ ss << "__Lb";
+ TypeNode ltn = NodeManager::currentNM()->mkSetType(tn);
+ //TypeNode ltn = NodeManager::currentNM()->mkSetType(NodeManager::currentNM()->mkRefType(tn));
+ Node n_lbl = NodeManager::currentNM()->mkSkolem( ss.str(), ltn, "" );
+ d_base_label[tn] = n_lbl;
+ //make reference bound
+ Trace("sep") << "Make reference bound label for " << tn << std::endl;
+ std::stringstream ss2;
+ ss2 << "__Lu";
+ d_reference_bound[tn] = NodeManager::currentNM()->mkSkolem( ss2.str(), ltn, "" );
+ d_type_references_all[tn].insert( d_type_references_all[tn].end(), d_type_references[tn].begin(), d_type_references[tn].end() );
+ //add a reference type for maximum occurrences of empty in a constraint
+ unsigned n_emp = d_card_max[tn]>d_card_max[TypeNode::null()] ? d_card_max[tn] : d_card_max[TypeNode::null()];
+ for( unsigned r=0; r<n_emp; r++ ){
+ Node e = NodeManager::currentNM()->mkSkolem( "e", tn, "cardinality bound element for seplog" );
+ //d_type_references_all[tn].push_back( NodeManager::currentNM()->mkSkolem( "e", NodeManager::currentNM()->mkRefType(tn) ) );
+ if( options::sepDisequalC() ){
+ //ensure that it is distinct from all other references so far
+ for( unsigned j=0; j<d_type_references_all[tn].size(); j++ ){
+ Node eq = NodeManager::currentNM()->mkNode( e.getType().isBoolean() ? kind::IFF : kind::EQUAL, e, d_type_references_all[tn][j] );
+ d_out->lemma( eq.negate() );
+ }
+ }
+ d_type_references_all[tn].push_back( e );
+ d_lbl_reference_bound[d_base_label[tn]].push_back( e );
+ }
+ //construct bound
+ d_reference_bound_max[tn] = mkUnion( tn, d_type_references_all[tn] );
+ Trace("sep-bound") << "overall bound for " << d_base_label[tn] << " : " << d_reference_bound_max[tn] << std::endl;
+
+ if( d_reference_bound_invalid.find( tn )==d_reference_bound_invalid.end() ){
+ Node slem = NodeManager::currentNM()->mkNode( kind::SUBSET, d_reference_bound[tn], d_reference_bound_max[tn] );
+ Trace("sep-lemma") << "Sep::Lemma: reference bound for " << tn << " : " << slem << std::endl;
+ d_out->lemma( slem );
+ }else{
+ Trace("sep-bound") << "reference cannot be bound (possibly due to quantified pto)." << std::endl;
+ }
+ //slem = NodeManager::currentNM()->mkNode( kind::SUBSET, d_base_label[tn], d_reference_bound_max[tn] );
+ //Trace("sep-lemma") << "Sep::Lemma: base reference bound for " << tn << " : " << slem << std::endl;
+ //d_out->lemma( slem );
+ return n_lbl;
+ }else{
+ return it->second;
+ }
+}
+
+Node TheorySep::getNilRef( TypeNode tn ) {
+ std::map< TypeNode, Node >::iterator it = d_nil_ref.find( tn );
+ if( it==d_nil_ref.end() ){
+ Node nil = NodeManager::currentNM()->mkSepNil( tn );
+ d_nil_ref[tn] = nil;
+ return nil;
+ }else{
+ return it->second;
+ }
+}
+
+Node TheorySep::mkUnion( TypeNode tn, std::vector< Node >& locs ) {
+ Node u;
+ if( locs.empty() ){
+ TypeNode ltn = NodeManager::currentNM()->mkSetType(tn);
+ return NodeManager::currentNM()->mkConst(EmptySet(ltn.toType()));
+ }else{
+ for( unsigned i=0; i<locs.size(); i++ ){
+ Node s = locs[i];
+ Assert( !s.isNull() );
+ s = NodeManager::currentNM()->mkNode( kind::SINGLETON, s );
+ if( u.isNull() ){
+ u = s;
+ }else{
+ u = NodeManager::currentNM()->mkNode( kind::UNION, s, u );
+ }
+ }
+ return u;
+ }
+}
+
+Node TheorySep::getLabel( Node atom, int child, Node lbl ) {
+ std::map< int, Node >::iterator it = d_label_map[atom][lbl].find( child );
+ if( it==d_label_map[atom][lbl].end() ){
+ int card;
+ TypeNode refType = getReferenceType( atom, card );
+ std::stringstream ss;
+ ss << "__Lc" << child;
+ TypeNode ltn = NodeManager::currentNM()->mkSetType(refType);
+ //TypeNode ltn = NodeManager::currentNM()->mkSetType(NodeManager::currentNM()->mkRefType(refType));
+ Node n_lbl = NodeManager::currentNM()->mkSkolem( ss.str(), ltn, "" );
+ d_label_map[atom][lbl][child] = n_lbl;
+ d_label_map_parent[n_lbl] = lbl;
+ return n_lbl;
+ }else{
+ return (*it).second;
+ }
+}
+
+Node TheorySep::applyLabel( Node n, Node lbl, std::map< Node, Node >& visited ) {
+ Assert( n.getKind()!=kind::SEP_LABEL );
+ if( n.getKind()==kind::SEP_STAR || n.getKind()==kind::SEP_WAND || n.getKind()==kind::SEP_PTO || n.getKind()==kind::SEP_EMP ){
+ return NodeManager::currentNM()->mkNode( kind::SEP_LABEL, n, lbl );
+ }else if( !n.getType().isBoolean() || n.getNumChildren()==0 ){
+ return n;
+ }else{
+ std::map< Node, Node >::iterator it = visited.find( n );
+ if( it==visited.end() ){
+ std::vector< Node > children;
+ if (n.getMetaKind() == kind::metakind::PARAMETERIZED) {
+ children.push_back( n.getOperator() );
+ }
+ bool childChanged = false;
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ Node aln = applyLabel( n[i], lbl, visited );
+ children.push_back( aln );
+ childChanged = childChanged || aln!=n[i];
+ }
+ Node ret = n;
+ if( childChanged ){
+ ret = NodeManager::currentNM()->mkNode( n.getKind(), children );
+ }
+ visited[n] = ret;
+ return ret;
+ }else{
+ return it->second;
+ }
+ }
+}
+
+Node TheorySep::instantiateLabel( Node n, Node o_lbl, Node lbl, Node lbl_v, std::map< Node, Node >& visited, std::map< Node, Node >& pto_model, std::map< Node, Node >& tmodel,
+ TypeNode rtn, std::map< Node, bool >& active_lbl, unsigned ind ) {
+ Trace("sep-inst-debug") << "Instantiate label " << n << " " << lbl << " " << lbl_v << std::endl;
+ if( options::sepMinimalRefine() && lbl!=o_lbl && active_lbl.find( lbl )!=active_lbl.end() ){
+ Trace("sep-inst") << "...do not instantiate " << o_lbl << " since it has an active sublabel " << lbl << std::endl;
+ return Node::null();
+ }else{
+ if( Trace.isOn("sep-inst") ){
+ if( n.getKind()==kind::SEP_STAR || n.getKind()==kind::SEP_WAND || n.getKind()==kind::SEP_PTO || n.getKind()==kind::SEP_EMP ){
+ for( unsigned j=0; j<ind; j++ ){ Trace("sep-inst") << " "; }
+ Trace("sep-inst") << n << "[" << lbl << "] :: " << lbl_v << std::endl;
+ }
+ }
+ Assert( n.getKind()!=kind::SEP_LABEL );
+ if( n.getKind()==kind::SEP_STAR || n.getKind()==kind::SEP_WAND ){
+ if( lbl==o_lbl ){
+ std::vector< Node > children;
+ children.resize( n.getNumChildren() );
+ Assert( d_label_map[n].find( lbl )!=d_label_map[n].end() );
+ for( std::map< int, Node >::iterator itl = d_label_map[n][lbl].begin(); itl != d_label_map[n][lbl].end(); ++itl ){
+ Node sub_lbl = itl->second;
+ int sub_index = itl->first;
+ Assert( sub_index>=0 && sub_index<(int)children.size() );
+ Trace("sep-inst-debug") << "Sublabel " << sub_index << " is " << sub_lbl << std::endl;
+ Node lbl_mval;
+ if( n.getKind()==kind::SEP_WAND && sub_index==1 ){
+ Assert( d_label_map[n][lbl].find( 0 )!=d_label_map[n][lbl].end() );
+ Node sub_lbl_0 = d_label_map[n][lbl][0];
+ computeLabelModel( sub_lbl_0, tmodel );
+ Assert( d_label_model.find( sub_lbl_0 )!=d_label_model.end() );
+ lbl_mval = NodeManager::currentNM()->mkNode( kind::UNION, lbl, d_label_model[sub_lbl_0].getValue( rtn ) );
+ }else{
+ computeLabelModel( sub_lbl, tmodel );
+ Assert( d_label_model.find( sub_lbl )!=d_label_model.end() );
+ lbl_mval = d_label_model[sub_lbl].getValue( rtn );
+ }
+ Trace("sep-inst-debug") << "Sublabel value is " << lbl_mval << std::endl;
+ children[sub_index] = instantiateLabel( n[sub_index], o_lbl, sub_lbl, lbl_mval, visited, pto_model, tmodel, rtn, active_lbl, ind+1 );
+ if( children[sub_index].isNull() ){
+ return Node::null();
+ }
+ }
+ if( n.getKind()==kind::SEP_STAR ){
+ Assert( children.size()>1 );
+ return NodeManager::currentNM()->mkNode( kind::AND, children );
+ }else{
+ return NodeManager::currentNM()->mkNode( kind::OR, children[0].negate(), children[1] );
+ }
+ }else{
+ //nested star/wand, label it and return
+ return NodeManager::currentNM()->mkNode( kind::SEP_LABEL, n, lbl_v );
+ }
+ }else if( n.getKind()==kind::SEP_PTO ){
+ //check if this pto reference is in the base label, if not, then it does not need to be added as an assumption
+ Assert( d_label_model.find( o_lbl )!=d_label_model.end() );
+ Node vr = d_valuation.getModel()->getRepresentative( n[0] );
+ Node svr = NodeManager::currentNM()->mkNode( kind::SINGLETON, vr );
+ bool inBaseHeap = std::find( d_label_model[o_lbl].d_heap_locs_model.begin(), d_label_model[o_lbl].d_heap_locs_model.end(), svr )!=d_label_model[o_lbl].d_heap_locs_model.end();
+ Trace("sep-inst-debug") << "Is in base (non-instantiating) heap : " << inBaseHeap << " for value ref " << vr << " in " << o_lbl << std::endl;
+ std::vector< Node > children;
+ if( inBaseHeap ){
+ Node s = NodeManager::currentNM()->mkNode( kind::SINGLETON, n[0] );
+ children.push_back( NodeManager::currentNM()->mkNode( kind::SEP_LABEL, NodeManager::currentNM()->mkNode( kind::SEP_PTO, n[0], n[1] ), s ) );
+ }else{
+ //look up value of data
+ std::map< Node, Node >::iterator it = pto_model.find( vr );
+ if( it!=pto_model.end() ){
+ if( n[1]!=it->second ){
+ children.push_back( NodeManager::currentNM()->mkNode( n[1].getType().isBoolean() ? kind::IFF : kind::EQUAL, n[1], it->second ) );
+ }
+ }else{
+ Trace("sep-inst-debug") << "Data for " << vr << " was not specified, do not add condition." << std::endl;
+ }
+ }
+ children.push_back( NodeManager::currentNM()->mkNode( kind::EQUAL, NodeManager::currentNM()->mkNode( kind::SINGLETON, n[0] ), lbl_v ) );
+ Node ret = children.empty() ? NodeManager::currentNM()->mkConst( true ) : ( children.size()==1 ? children[0] : NodeManager::currentNM()->mkNode( kind::AND, children ) );
+ Trace("sep-inst-debug") << "Return " << ret << std::endl;
+ return ret;
+ }else if( n.getKind()==kind::SEP_EMP ){
+ //return NodeManager::currentNM()->mkConst( lbl_v.getKind()==kind::EMPTYSET );
+ return lbl_v.eqNode( NodeManager::currentNM()->mkConst(EmptySet(lbl_v.getType().toType())) );
+ }else{
+ std::map< Node, Node >::iterator it = visited.find( n );
+ if( it==visited.end() ){
+ std::vector< Node > children;
+ if (n.getMetaKind() == kind::metakind::PARAMETERIZED) {
+ children.push_back( n.getOperator() );
+ }
+ bool childChanged = false;
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ Node aln = instantiateLabel( n[i], o_lbl, lbl, lbl_v, visited, pto_model, tmodel, rtn, active_lbl, ind );
+ if( aln.isNull() ){
+ return Node::null();
+ }else{
+ children.push_back( aln );
+ childChanged = childChanged || aln!=n[i];
+ }
+ }
+ Node ret = n;
+ if( childChanged ){
+ ret = NodeManager::currentNM()->mkNode( n.getKind(), children );
+ }
+ //careful about caching
+ //visited[n] = ret;
+ return ret;
+ }else{
+ return it->second;
+ }
+ }
+ }
+}
+
+void TheorySep::setInactiveAssertionRec( Node fact, std::map< Node, std::vector< Node > >& lbl_to_assertions, std::map< Node, bool >& assert_active ) {
+ Trace("sep-process-debug") << "setInactiveAssertionRec::inactive : " << fact << std::endl;
+ assert_active[fact] = false;
+ bool polarity = fact.getKind() != kind::NOT;
+ TNode atom = polarity ? fact : fact[0];
+ TNode s_atom = atom[0];
+ TNode s_lbl = atom[1];
+ if( s_atom.getKind()==kind::SEP_WAND || s_atom.getKind()==kind::SEP_STAR ){
+ for( unsigned j=0; j<s_atom.getNumChildren(); j++ ){
+ Node lblc = getLabel( s_atom, j, s_lbl );
+ for( unsigned k=0; k<lbl_to_assertions[lblc].size(); k++ ){
+ setInactiveAssertionRec( lbl_to_assertions[lblc][k], lbl_to_assertions, assert_active );
+ }
+ }
+ }
+}
+
+void TheorySep::getLabelChildren( Node s_atom, Node lbl, std::vector< Node >& children, std::vector< Node >& labels ) {
+ for( unsigned i=0; i<s_atom.getNumChildren(); i++ ){
+ Node lblc = getLabel( s_atom, i, lbl );
+ Assert( !lblc.isNull() );
+ std::map< Node, Node > visited;
+ Node lc = applyLabel( s_atom[i], lblc, visited );
+ Assert( !lc.isNull() );
+ if( i==1 && s_atom.getKind()==kind::SEP_WAND ){
+ lc = lc.negate();
+ }
+ children.push_back( lc );
+ labels.push_back( lblc );
+ }
+ Assert( children.size()>1 );
+}
+
+void TheorySep::computeLabelModel( Node lbl, std::map< Node, Node >& tmodel ) {
+ if( !d_label_model[lbl].d_computed ){
+ d_label_model[lbl].d_computed = true;
+
+ //we must get the value of lbl from the model: this is being run at last call, after the model is constructed
+ //Assert(...); TODO
+ Node v_val = d_valuation.getModel()->getRepresentative( lbl );
+ Trace("sep-process") << "Model value (from valuation) for " << lbl << " : " << v_val << std::endl;
+ if( v_val.getKind()!=kind::EMPTYSET ){
+ while( v_val.getKind()==kind::UNION ){
+ Assert( v_val[1].getKind()==kind::SINGLETON );
+ d_label_model[lbl].d_heap_locs_model.push_back( v_val[1] );
+ v_val = v_val[0];
+ }
+ Assert( v_val.getKind()==kind::SINGLETON );
+ d_label_model[lbl].d_heap_locs_model.push_back( v_val );
+ }
+ //end hack
+ for( unsigned j=0; j<d_label_model[lbl].d_heap_locs_model.size(); j++ ){
+ Node u = d_label_model[lbl].d_heap_locs_model[j];
+ Assert( u.getKind()==kind::SINGLETON );
+ u = u[0];
+ Node tt;
+ std::map< Node, Node >::iterator itm = tmodel.find( u );
+ if( itm==tmodel.end() ) {
+ //Trace("sep-process") << "WARNING: could not find symbolic term in model for " << u << std::endl;
+ //Assert( false );
+ //tt = u;
+ //TypeNode tn = u.getType().getRefConstituentType();
+ TypeNode tn = u.getType();
+ Trace("sep-process") << "WARNING: could not find symbolic term in model for " << u << ", cref type " << tn << std::endl;
+ Assert( d_type_references_all.find( tn )!=d_type_references_all.end() && !d_type_references_all[tn].empty() );
+ tt = d_type_references_all[tn][0];
+ }else{
+ tt = itm->second;
+ }
+ Node stt = NodeManager::currentNM()->mkNode( kind::SINGLETON, tt );
+ Trace("sep-process-debug") << "...model : add " << tt << " for " << u << " in lbl " << lbl << std::endl;
+ d_label_model[lbl].d_heap_locs.push_back( stt );
+ }
+ }
+}
+
+Node TheorySep::getRepresentative( Node t ) {
+ if( d_equalityEngine.hasTerm( t ) ){
+ return d_equalityEngine.getRepresentative( t );
+ }else{
+ return t;
+ }
+}
+
+bool TheorySep::hasTerm( Node a ){
+ return d_equalityEngine.hasTerm( a );
+}
+
+bool TheorySep::areEqual( Node a, Node b ){
+ if( a==b ){
+ return true;
+ }else if( hasTerm( a ) && hasTerm( b ) ){
+ return d_equalityEngine.areEqual( a, b );
+ }else{
+ return false;
+ }
+}
+
+bool TheorySep::areDisequal( Node a, Node b ){
+ if( a==b ){
+ return false;
+ }else if( hasTerm( a ) && hasTerm( b ) ){
+ if( d_equalityEngine.areDisequal( a, b, false ) ){
+ return true;
+ }
+ }
+ return false;
+}
+
+
+void TheorySep::eqNotifyPreMerge(TNode t1, TNode t2) {
+
+}
+
+void TheorySep::eqNotifyPostMerge(TNode t1, TNode t2) {
+ HeapAssertInfo * e2 = getOrMakeEqcInfo( t2, false );
+ if( e2 && ( !e2->d_pto.get().isNull() || e2->d_has_neg_pto.get() ) ){
+ HeapAssertInfo * e1 = getOrMakeEqcInfo( t1, true );
+ if( !e2->d_pto.get().isNull() ){
+ if( !e1->d_pto.get().isNull() ){
+ Trace("sep-pto-debug") << "While merging " << t1 << " " << t2 << ", merge pto." << std::endl;
+ mergePto( e1->d_pto.get(), e2->d_pto.get() );
+ }else{
+ e1->d_pto.set( e2->d_pto.get() );
+ }
+ }
+ e1->d_has_neg_pto.set( e1->d_has_neg_pto.get() || e2->d_has_neg_pto.get() );
+ //validate
+ validatePto( e1, t1 );
+ }
+}
+
+void TheorySep::validatePto( HeapAssertInfo * ei, Node ei_n ) {
+ if( !ei->d_pto.get().isNull() && ei->d_has_neg_pto.get() ){
+ for( NodeList::const_iterator i = d_spatial_assertions.begin(); i != d_spatial_assertions.end(); ++i ) {
+ Node fact = (*i);
+ bool polarity = fact.getKind() != kind::NOT;
+ if( !polarity ){
+ TNode atom = polarity ? fact : fact[0];
+ Assert( atom.getKind()==kind::SEP_LABEL );
+ TNode s_atom = atom[0];
+ if( s_atom.getKind()==kind::SEP_PTO ){
+ if( areEqual( atom[1], ei_n ) ){
+ addPto( ei, ei_n, atom, false );
+ }
+ }
+ }
+ }
+ //we have now processed all pending negated pto
+ ei->d_has_neg_pto.set( false );
+ }
+}
+
+void TheorySep::addPto( HeapAssertInfo * ei, Node ei_n, Node p, bool polarity ) {
+ Trace("sep-pto") << "Add pto " << p << ", pol = " << polarity << " to eqc " << ei_n << std::endl;
+ if( !ei->d_pto.get().isNull() ){
+ if( polarity ){
+ Trace("sep-pto-debug") << "...eqc " << ei_n << " already has pto " << ei->d_pto.get() << ", merge." << std::endl;
+ mergePto( ei->d_pto.get(), p );
+ }else{
+ Node pb = ei->d_pto.get();
+ Trace("sep-pto") << "Process positive/negated pto " << " " << pb << " " << p << std::endl;
+ Assert( pb.getKind()==kind::SEP_LABEL && pb[0].getKind()==kind::SEP_PTO );
+ Assert( p.getKind()==kind::SEP_LABEL && p[0].getKind()==kind::SEP_PTO );
+ Assert( areEqual( pb[1], p[1] ) );
+ std::vector< Node > exp;
+ if( pb[1]!=p[1] ){
+ exp.push_back( pb[1].eqNode( p[1] ) );
+ }
+ exp.push_back( pb );
+ exp.push_back( p.negate() );
+ std::vector< Node > conc;
+ if( pb[0][1]!=p[0][1] ){
+ conc.push_back( pb[0][1].eqNode( p[0][1] ).negate() );
+ }
+ if( pb[1]!=p[1] ){
+ conc.push_back( pb[1].eqNode( p[1] ).negate() );
+ }
+ Node n_conc = conc.empty() ? d_false : ( conc.size()==1 ? conc[0] : NodeManager::currentNM()->mkNode( kind::OR, conc ) );
+ sendLemma( exp, n_conc, "PTO_NEG_PROP" );
+ }
+ }else{
+ if( polarity ){
+ ei->d_pto.set( p );
+ validatePto( ei, ei_n );
+ }else{
+ ei->d_has_neg_pto.set( true );
+ }
+ }
+}
+
+void TheorySep::mergePto( Node p1, Node p2 ) {
+ Trace("sep-lemma-debug") << "Merge pto " << p1 << " " << p2 << std::endl;
+ Assert( p1.getKind()==kind::SEP_LABEL && p1[0].getKind()==kind::SEP_PTO );
+ Assert( p2.getKind()==kind::SEP_LABEL && p2[0].getKind()==kind::SEP_PTO );
+ if( !areEqual( p1[0][1], p2[0][1] ) ){
+ std::vector< Node > exp;
+ if( p1[1]!=p2[1] ){
+ Assert( areEqual( p1[1], p2[1] ) );
+ exp.push_back( p1[1].eqNode( p2[1] ) );
+ }
+ exp.push_back( p1 );
+ exp.push_back( p2 );
+ sendLemma( exp, p1[0][1].eqNode( p2[0][1] ), "PTO_PROP" );
+ }
+}
+
+void TheorySep::sendLemma( std::vector< Node >& ant, Node conc, const char * c, bool infer ) {
+ Trace("sep-lemma-debug") << "Do rewrite on inference : " << conc << std::endl;
+ conc = Rewriter::rewrite( conc );
+ Trace("sep-lemma-debug") << "Got : " << conc << std::endl;
+ if( conc!=d_true ){
+ if( infer && conc!=d_false ){
+ Node ant_n;
+ if( ant.empty() ){
+ ant_n = d_true;
+ }else if( ant.size()==1 ){
+ ant_n = ant[0];
+ }else{
+ ant_n = NodeManager::currentNM()->mkNode( kind::AND, ant );
+ }
+ Trace("sep-lemma") << "Sep::Infer: " << conc << " from " << ant_n << " by " << c << std::endl;
+ d_pending_exp.push_back( ant_n );
+ d_pending.push_back( conc );
+ d_infer.push_back( ant_n );
+ d_infer_exp.push_back( conc );
+ }else{
+ std::vector< TNode > ant_e;
+ for( unsigned i=0; i<ant.size(); i++ ){
+ Trace("sep-lemma-debug") << "Explain : " << ant[i] << std::endl;
+ explain( ant[i], ant_e );
+ }
+ Node ant_n;
+ if( ant_e.empty() ){
+ ant_n = d_true;
+ }else if( ant_e.size()==1 ){
+ ant_n = ant_e[0];
+ }else{
+ ant_n = NodeManager::currentNM()->mkNode( kind::AND, ant_e );
+ }
+ if( conc==d_false ){
+ Trace("sep-lemma") << "Sep::Conflict: " << ant_n << " by " << c << std::endl;
+ d_out->conflict( ant_n );
+ d_conflict = true;
+ }else{
+ Trace("sep-lemma") << "Sep::Lemma: " << conc << " from " << ant_n << " by " << c << std::endl;
+ d_pending_exp.push_back( ant_n );
+ d_pending.push_back( conc );
+ d_pending_lem.push_back( d_pending.size()-1 );
+ }
+ }
+ }
+}
+
+void TheorySep::doPendingFacts() {
+ if( d_pending_lem.empty() ){
+ for( unsigned i=0; i<d_pending.size(); i++ ){
+ if( d_conflict ){
+ break;
+ }
+ Node atom = d_pending[i].getKind()==kind::NOT ? d_pending[i][0] : d_pending[i];
+ bool pol = d_pending[i].getKind()!=kind::NOT;
+ Trace("sep-pending") << "Sep : Assert to EE : " << atom << ", pol = " << pol << std::endl;
+ if( atom.getKind()==kind::EQUAL ){
+ d_equalityEngine.assertEquality(atom, pol, d_pending_exp[i]);
+ }else{
+ d_equalityEngine.assertPredicate(atom, pol, d_pending_exp[i]);
+ }
+ }
+ }else{
+ for( unsigned i=0; i<d_pending_lem.size(); i++ ){
+ if( d_conflict ){
+ break;
+ }
+ int index = d_pending_lem[i];
+ Node lem = NodeManager::currentNM()->mkNode( kind::IMPLIES, d_pending_exp[index], d_pending[index] );
+ d_out->lemma( lem );
+ Trace("sep-pending") << "Sep : Lemma : " << lem << std::endl;
+ }
+ }
+ d_pending_exp.clear();
+ d_pending.clear();
+ d_pending_lem.clear();
+}
+
+void TheorySep::debugPrintHeap( HeapInfo& heap, const char * c ) {
+ Trace(c) << "[" << std::endl;
+ Trace(c) << " ";
+ for( unsigned j=0; j<heap.d_heap_locs.size(); j++ ){
+ Trace(c) << heap.d_heap_locs[j] << " ";
+ }
+ Trace(c) << std::endl;
+ Trace(c) << "]" << std::endl;
+}
+
+Node TheorySep::HeapInfo::getValue( TypeNode tn ) {
+ Assert( d_heap_locs.size()==d_heap_locs_model.size() );
+ if( d_heap_locs.empty() ){
+ return NodeManager::currentNM()->mkConst(EmptySet(tn.toType()));
+ }else if( d_heap_locs.size()==1 ){
+ return d_heap_locs[0];
+ }else{
+ Node curr = NodeManager::currentNM()->mkNode( kind::UNION, d_heap_locs[0], d_heap_locs[1] );
+ for( unsigned j=2; j<d_heap_locs.size(); j++ ){
+ curr = NodeManager::currentNM()->mkNode( kind::UNION, curr, d_heap_locs[j] );
+ }
+ return curr;
+ }
+}
+
+}/* CVC4::theory::sep namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
diff --git a/src/theory/sep/theory_sep.h b/src/theory/sep/theory_sep.h
new file mode 100644
index 000000000..852a36721
--- /dev/null
+++ b/src/theory/sep/theory_sep.h
@@ -0,0 +1,294 @@
+/********************* */
+/*! \file theory_sep.h
+ ** \verbatim
+ ** Original author: Andrew Reynolds
+ ** Major contributors: Dejan Jovanovic, Clark Barrett
+ ** Minor contributors (to current version): Tim King, Andrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2014 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Theory of sep
+ **
+ ** Theory of sep.
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__SEP__THEORY_SEP_H
+#define __CVC4__THEORY__SEP__THEORY_SEP_H
+
+#include "theory/theory.h"
+#include "util/statistics_registry.h"
+#include "theory/uf/equality_engine.h"
+#include "context/cdchunk_list.h"
+#include "context/cdhashmap.h"
+#include "context/cdhashset.h"
+#include "context/cdqueue.h"
+
+namespace CVC4 {
+namespace theory {
+
+class TheoryModel;
+
+namespace sep {
+
+class TheorySep : public Theory {
+ typedef context::CDChunkList<Node> NodeList;
+ typedef context::CDHashSet<Node, NodeHashFunction> NodeSet;
+ typedef context::CDHashMap<Node, Node, NodeHashFunction> NodeNodeMap;
+
+ /////////////////////////////////////////////////////////////////////////////
+ // MISC
+ /////////////////////////////////////////////////////////////////////////////
+
+ private:
+
+ /** True node for predicates = true */
+ Node d_true;
+
+ /** True node for predicates = false */
+ Node d_false;
+
+ Node mkAnd( std::vector< TNode >& assumptions );
+
+ void processAssertion( Node n, std::map< Node, bool >& visited );
+
+ public:
+
+ TheorySep(context::Context* c, context::UserContext* u, OutputChannel& out, Valuation valuation, const LogicInfo& logicInfo);
+ ~TheorySep();
+
+ void setMasterEqualityEngine(eq::EqualityEngine* eq);
+
+ std::string identify() const { return std::string("TheorySep"); }
+
+ /////////////////////////////////////////////////////////////////////////////
+ // PREPROCESSING
+ /////////////////////////////////////////////////////////////////////////////
+
+ public:
+
+ PPAssertStatus ppAssert(TNode in, SubstitutionMap& outSubstitutions);
+ Node ppRewrite(TNode atom);
+
+ void processAssertions( std::vector< Node >& assertions );
+ /////////////////////////////////////////////////////////////////////////////
+ // T-PROPAGATION / REGISTRATION
+ /////////////////////////////////////////////////////////////////////////////
+
+ private:
+
+ /** Should be called to propagate the literal. */
+ bool propagate(TNode literal);
+
+ /** Explain why this literal is true by adding assumptions */
+ void explain(TNode literal, std::vector<TNode>& assumptions);
+
+ void preRegisterTermRec(TNode t, std::map< TNode, bool >& visited );
+ public:
+
+ void preRegisterTerm(TNode t);
+ void propagate(Effort e);
+ Node explain(TNode n);
+
+ public:
+
+ void addSharedTerm(TNode t);
+ EqualityStatus getEqualityStatus(TNode a, TNode b);
+ void computeCareGraph();
+
+ /////////////////////////////////////////////////////////////////////////////
+ // MODEL GENERATION
+ /////////////////////////////////////////////////////////////////////////////
+
+ public:
+
+ void collectModelInfo(TheoryModel* m, bool fullModel);
+
+ /////////////////////////////////////////////////////////////////////////////
+ // NOTIFICATIONS
+ /////////////////////////////////////////////////////////////////////////////
+
+ private:
+ public:
+
+ Node getNextDecisionRequest();
+
+ void presolve();
+ void shutdown() { }
+
+ /////////////////////////////////////////////////////////////////////////////
+ // MAIN SOLVER
+ /////////////////////////////////////////////////////////////////////////////
+ public:
+
+ void check(Effort e);
+
+ private:
+
+ // NotifyClass: template helper class for d_equalityEngine - handles call-back from congruence closure module
+ class NotifyClass : public eq::EqualityEngineNotify {
+ TheorySep& d_sep;
+ public:
+ NotifyClass(TheorySep& sep): d_sep(sep) {}
+
+ bool eqNotifyTriggerEquality(TNode equality, bool value) {
+ Debug("sep::propagate") << "NotifyClass::eqNotifyTriggerEquality(" << equality << ", " << (value ? "true" : "false") << ")" << std::endl;
+ // Just forward to sep
+ if (value) {
+ return d_sep.propagate(equality);
+ } else {
+ return d_sep.propagate(equality.notNode());
+ }
+ }
+
+ bool eqNotifyTriggerPredicate(TNode predicate, bool value) {
+ Unreachable();
+ }
+
+ bool eqNotifyTriggerTermEquality(TheoryId tag, TNode t1, TNode t2, bool value) {
+ Debug("sep::propagate") << "NotifyClass::eqNotifyTriggerTermEquality(" << t1 << ", " << t2 << ", " << (value ? "true" : "false") << ")" << std::endl;
+ if (value) {
+ // Propagate equality between shared terms
+ return d_sep.propagate(t1.eqNode(t2));
+ } else {
+ return d_sep.propagate(t1.eqNode(t2).notNode());
+ }
+ return true;
+ }
+
+ void eqNotifyConstantTermMerge(TNode t1, TNode t2) {
+ Debug("sep::propagate") << "NotifyClass::eqNotifyConstantTermMerge(" << t1 << ", " << t2 << ")" << std::endl;
+ d_sep.conflict(t1, t2);
+ }
+
+ void eqNotifyNewClass(TNode t) { }
+ void eqNotifyPreMerge(TNode t1, TNode t2) { d_sep.eqNotifyPreMerge( t1, t2 ); }
+ void eqNotifyPostMerge(TNode t1, TNode t2) { d_sep.eqNotifyPostMerge( t1, t2 ); }
+ void eqNotifyDisequal(TNode t1, TNode t2, TNode reason) { }
+ };
+
+ /** The notify class for d_equalityEngine */
+ NotifyClass d_notify;
+
+ /** Equaltity engine */
+ eq::EqualityEngine d_equalityEngine;
+
+ /** Are we in conflict? */
+ context::CDO<bool> d_conflict;
+ std::vector< Node > d_pending_exp;
+ std::vector< Node > d_pending;
+ std::vector< int > d_pending_lem;
+
+ /** list of all refinement lemms */
+ std::map< Node, std::map< Node, std::vector< Node > > > d_refinement_lem;
+
+ /** Conflict when merging constants */
+ void conflict(TNode a, TNode b);
+
+ //cache for positive polarity start reduction
+ NodeSet d_reduce;
+ std::map< Node, std::map< Node, Node > > d_red_conc;
+ std::map< Node, std::map< Node, Node > > d_neg_guard;
+ std::vector< Node > d_neg_guards;
+ std::map< Node, Node > d_guard_to_assertion;
+ //cache for references
+ std::map< Node, std::map< int, TypeNode > > d_reference_type;
+ std::map< Node, std::map< int, int > > d_reference_type_card;
+ std::map< Node, std::map< int, std::vector< Node > > > d_references;
+ /** inferences: maintained to ensure ref count for internally introduced nodes */
+ NodeList d_infer;
+ NodeList d_infer_exp;
+ NodeList d_spatial_assertions;
+
+ //currently fix one data type for each location type, throw error if using more than one
+ std::map< TypeNode, TypeNode > d_loc_to_data_type;
+ //information about types
+ std::map< TypeNode, Node > d_base_label;
+ std::map< TypeNode, Node > d_nil_ref;
+ //reference bound
+ std::map< TypeNode, Node > d_reference_bound;
+ std::map< TypeNode, Node > d_reference_bound_max;
+ std::map< TypeNode, bool > d_reference_bound_invalid;
+ std::map< TypeNode, std::vector< Node > > d_type_references;
+ std::map< TypeNode, std::vector< Node > > d_type_references_all;
+ std::map< TypeNode, unsigned > d_card_max;
+ //bounds for labels
+ std::map< Node, std::vector< Node > > d_lbl_reference_bound;
+ //for empty argument
+ std::map< TypeNode, Node > d_emp_arg;
+ //map from ( atom, label, child index ) -> label
+ std::map< Node, std::map< Node, std::map< int, Node > > > d_label_map;
+ std::map< Node, Node > d_label_map_parent;
+
+ //term model
+ std::map< Node, Node > d_tmodel;
+ std::map< Node, Node > d_pto_model;
+
+ class HeapAssertInfo {
+ public:
+ HeapAssertInfo( context::Context* c );
+ ~HeapAssertInfo(){}
+ context::CDO< Node > d_pto;
+ context::CDO< bool > d_has_neg_pto;
+ };
+ std::map< Node, HeapAssertInfo * > d_eqc_info;
+ HeapAssertInfo * getOrMakeEqcInfo( Node n, bool doMake = false );
+
+ //calculate the element type of the heap for spatial assertions
+ TypeNode getReferenceType( Node atom, int& card, int index = -1 );
+ TypeNode getReferenceType2( Node atom, int& card, int index, Node n, std::map< Node, int >& visited);
+ //get the base label for the spatial assertion
+ Node getBaseLabel( TypeNode tn );
+ Node getNilRef( TypeNode tn );
+ Node getLabel( Node atom, int child, Node lbl );
+ Node applyLabel( Node n, Node lbl, std::map< Node, Node >& visited );
+ void getLabelChildren( Node atom, Node lbl, std::vector< Node >& children, std::vector< Node >& labels );
+
+ class HeapInfo {
+ public:
+ HeapInfo() : d_computed(false) {}
+ //information about the model
+ bool d_computed;
+ std::vector< Node > d_heap_locs;
+ std::vector< Node > d_heap_locs_model;
+ //get value
+ Node getValue( TypeNode tn );
+ };
+ //heap info ( label -> HeapInfo )
+ std::map< Node, HeapInfo > d_label_model;
+
+ void debugPrintHeap( HeapInfo& heap, const char * c );
+ void validatePto( HeapAssertInfo * ei, Node ei_n );
+ void addPto( HeapAssertInfo * ei, Node ei_n, Node p, bool polarity );
+ void mergePto( Node p1, Node p2 );
+ void computeLabelModel( Node lbl, std::map< Node, Node >& tmodel );
+ Node instantiateLabel( Node n, Node o_lbl, Node lbl, Node lbl_v, std::map< Node, Node >& visited, std::map< Node, Node >& pto_model, std::map< Node, Node >& tmodel,
+ TypeNode rtn, std::map< Node, bool >& active_lbl, unsigned ind = 0 );
+ void setInactiveAssertionRec( Node fact, std::map< Node, std::vector< Node > >& lbl_to_assertions, std::map< Node, bool >& assert_active );
+
+ Node mkUnion( TypeNode tn, std::vector< Node >& locs );
+private:
+ Node getRepresentative( Node t );
+ bool hasTerm( Node a );
+ bool areEqual( Node a, Node b );
+ bool areDisequal( Node a, Node b );
+ void eqNotifyPreMerge(TNode t1, TNode t2);
+ void eqNotifyPostMerge(TNode t1, TNode t2);
+
+ void sendLemma( std::vector< Node >& ant, Node conc, const char * c, bool infer = false );
+ void doPendingFacts();
+public:
+ eq::EqualityEngine* getEqualityEngine() {
+ return &d_equalityEngine;
+ }
+
+};/* class TheorySep */
+
+}/* CVC4::theory::sep namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
+
+#endif /* __CVC4__THEORY__SEP__THEORY_SEP_H */
diff --git a/src/theory/sep/theory_sep_rewriter.cpp b/src/theory/sep/theory_sep_rewriter.cpp
new file mode 100644
index 000000000..d58c2c13d
--- /dev/null
+++ b/src/theory/sep/theory_sep_rewriter.cpp
@@ -0,0 +1,184 @@
+/********************* */
+/*! \file theory_sep_rewriter.cpp
+ ** \verbatim
+ ** Original author: Andrew Reynolds
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2014 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief [[ Add one-line brief description here ]]
+ **
+ ** [[ Add lengthier description here ]]
+ ** \todo document this file
+ **/
+
+#include "expr/attribute.h"
+#include "theory/sep/theory_sep_rewriter.h"
+
+namespace CVC4 {
+namespace theory {
+namespace sep {
+
+void TheorySepRewriter::getStarChildren( Node n, std::vector< Node >& s_children, std::vector< Node >& ns_children ){
+ Assert( n.getKind()==kind::SEP_STAR );
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ if( n[i].getKind()==kind::SEP_EMP ){
+ s_children.push_back( n[i] );
+ }else if( n[i].getKind()==kind::SEP_STAR ){
+ getStarChildren( n[i], s_children, ns_children );
+ }else if( n[i].getKind()==kind::SEP_PTO ){
+ s_children.push_back( n[i] );
+ }else{
+ std::vector< Node > temp_s_children;
+ getAndChildren( n[i], temp_s_children, ns_children );
+ Node to_add;
+ if( temp_s_children.size()==0 ){
+ to_add = NodeManager::currentNM()->mkConst( true );
+ }else{
+ //remove empty star
+ std::vector< Node > temp_s_children2;
+ for( unsigned i=0; i<temp_s_children.size(); i++ ){
+ if( temp_s_children[i].getKind()!=kind::SEP_EMP ){
+ temp_s_children2.push_back( temp_s_children[i] );
+ }
+ }
+ if( temp_s_children2.size()==1 ){
+ to_add = temp_s_children2[0];
+ }else if( temp_s_children2.size()>1 ){
+ to_add = NodeManager::currentNM()->mkNode( kind::AND, temp_s_children2 );
+ }
+ }
+ if( !to_add.isNull() ){
+ //flatten star
+ if( to_add.getKind()==kind::SEP_STAR ){
+ getStarChildren( to_add, s_children, ns_children );
+ }else if( std::find( s_children.begin(), s_children.end(), to_add )==s_children.end() ){
+ s_children.push_back( to_add );
+ }
+ }
+ }
+ }
+}
+
+void TheorySepRewriter::getAndChildren( Node n, std::vector< Node >& s_children, std::vector< Node >& ns_children ) {
+ if( n.getKind()==kind::AND ){
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ getAndChildren( n[i], s_children, ns_children );
+ }
+ }else{
+ std::map< Node, bool > visited;
+ if( isSpatial( n, visited ) ){
+ if( std::find( s_children.begin(), s_children.end(), n )==s_children.end() ){
+ s_children.push_back( n );
+ }
+ }else{
+ if( std::find( ns_children.begin(), ns_children.end(), n )==ns_children.end() ){
+ if( n!=NodeManager::currentNM()->mkConst(true) ){
+ ns_children.push_back( n );
+ }
+ }
+ }
+ }
+}
+
+bool TheorySepRewriter::isSpatial( Node n, std::map< Node, bool >& visited ) {
+ if( visited.find( n )==visited.end() ){
+ visited[n] = true;
+ if( n.getKind()==kind::SEP_STAR || n.getKind()==kind::SEP_PTO || n.getKind()==kind::SEP_EMP || n.getKind()==kind::SEP_LABEL ){
+ return true;
+ }else if( n.getType().isBoolean() ){
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ if( isSpatial( n[i], visited ) ){
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+RewriteResponse TheorySepRewriter::postRewrite(TNode node) {
+ Trace("sep-postrewrite") << "Sep::postRewrite start " << node << std::endl;
+ Node retNode = node;
+ switch (node.getKind()) {
+ case kind::SEP_LABEL: {
+ if( node[0].getKind()==kind::SEP_PTO ){
+ Node s = NodeManager::currentNM()->mkNode( kind::SINGLETON, node[0][0] );
+ if( node[1]!=s ){
+ Node c1 = node[1].eqNode( s );
+ Node c2 = NodeManager::currentNM()->mkNode( kind::SEP_LABEL, NodeManager::currentNM()->mkNode( kind::SEP_PTO, node[0][0], node[0][1] ), s );
+ retNode = NodeManager::currentNM()->mkNode( kind::AND, c1, c2 );
+ }
+ }
+ if( node[0].getKind()==kind::SEP_EMP ){
+ retNode = node[1].eqNode( NodeManager::currentNM()->mkConst(EmptySet(node[1].getType().toType())) );
+ }
+ break;
+ }
+ case kind::SEP_PTO: {
+ break;
+ }
+ case kind::SEP_STAR: {
+ //flatten
+ std::vector< Node > s_children;
+ std::vector< Node > ns_children;
+ getStarChildren( node, s_children, ns_children );
+ if( !s_children.empty() ){
+ Node schild;
+ if( s_children.size()==1 ) {
+ schild = s_children[0];
+ }else{
+ schild = NodeManager::currentNM()->mkNode( kind::SEP_STAR, s_children );
+ }
+ ns_children.push_back( schild );
+ }
+ Assert( !ns_children.empty() );
+ if( ns_children.size()==1 ){
+ retNode = ns_children[0];
+ }else{
+ retNode = NodeManager::currentNM()->mkNode( kind::AND, ns_children );
+ }
+ break;
+ }
+ case kind::EQUAL:
+ case kind::IFF: {
+ if(node[0] == node[1]) {
+ return RewriteResponse(REWRITE_DONE, NodeManager::currentNM()->mkConst(true));
+ }
+ else if (node[0].isConst() && node[1].isConst()) {
+ return RewriteResponse(REWRITE_DONE, NodeManager::currentNM()->mkConst(false));
+ }
+ if (node[0] > node[1]) {
+ Node newNode = NodeManager::currentNM()->mkNode(node.getKind(), node[1], node[0]);
+ return RewriteResponse(REWRITE_DONE, newNode);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ if( node!=retNode ){
+ Trace("sep-rewrite") << "Sep::rewrite : " << node << " -> " << retNode << std::endl;
+ }
+ return RewriteResponse(node==retNode ? REWRITE_DONE : REWRITE_AGAIN_FULL, retNode);
+}
+
+
+/*
+RewriteResponse TheorySepRewriter::preRewrite(TNode node) {
+ if( node.getKind()==kind::SEP_EMP ){
+ Trace("sep-prerewrite") << "Sep::preRewrite emp star " << std::endl;
+ return RewriteResponse(REWRITE_DONE, NodeManager::currentNM()->mkNode( kind::SEP_EMP, NodeManager::currentNM()->mkConst( true ) ) );
+ }else{
+ Trace("sep-prerewrite") << "Sep::preRewrite returning " << node << std::endl;
+ return RewriteResponse(REWRITE_DONE, node);
+ }
+}
+*/
+
+}/* CVC4::theory::sep namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
diff --git a/src/theory/sep/theory_sep_rewriter.h b/src/theory/sep/theory_sep_rewriter.h
new file mode 100644
index 000000000..02adbebe5
--- /dev/null
+++ b/src/theory/sep/theory_sep_rewriter.h
@@ -0,0 +1,53 @@
+/********************* */
+/*! \file theory_sep_rewriter.h
+ ** \verbatim
+ ** Original author: Andrew Reynolds
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2014 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief [[ Add one-line brief description here ]]
+ **
+ ** [[ Add lengthier description here ]]
+ ** \todo document this file
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__SEP__THEORY_SEP_REWRITER_H
+#define __CVC4__THEORY__SEP__THEORY_SEP_REWRITER_H
+
+#include "theory/rewriter.h"
+#include "theory/type_enumerator.h"
+
+namespace CVC4 {
+namespace theory {
+namespace sep {
+
+
+class TheorySepRewriter {
+private:
+ static void getStarChildren( Node n, std::vector< Node >& s_children, std::vector< Node >& ns_children );
+ static void getAndChildren( Node n, std::vector< Node >& s_children, std::vector< Node >& ns_children );
+ static bool isSpatial( Node n, std::map< Node, bool >& visited );
+public:
+
+ static RewriteResponse postRewrite(TNode node);
+ static inline RewriteResponse preRewrite(TNode node) {
+ Trace("sep-prerewrite") << "Sep::preRewrite returning " << node << std::endl;
+ return RewriteResponse(REWRITE_DONE, node);
+ }
+
+ static inline void init() {}
+ static inline void shutdown() {}
+
+};/* class TheorySepRewriter */
+
+}/* CVC4::theory::sep namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
+
+#endif /* __CVC4__THEORY__SEP__THEORY_SEP_REWRITER_H */
diff --git a/src/theory/sep/theory_sep_type_rules.h b/src/theory/sep/theory_sep_type_rules.h
new file mode 100644
index 000000000..7d4eb303e
--- /dev/null
+++ b/src/theory/sep/theory_sep_type_rules.h
@@ -0,0 +1,114 @@
+/********************* */
+/*! \file theory_sep_type_rules.h
+ ** \verbatim
+ ** Original author: Andrew Reynolds
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2014 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Typing and cardinality rules for the theory of sep
+ **
+ ** Typing and cardinality rules for the theory of sep.
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__SEP__THEORY_SEP_TYPE_RULES_H
+#define __CVC4__THEORY__SEP__THEORY_SEP_TYPE_RULES_H
+
+#include "theory/type_enumerator.h"
+
+namespace CVC4 {
+namespace theory {
+namespace sep {
+
+class SepNilRefTypeRule {
+public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
+ throw (TypeCheckingExceptionPrivate, AssertionException) {
+ return TypeNode::fromType( n.getConst<NilRef>().getType() );
+ }
+};
+
+class SepEmpTypeRule {
+public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
+ throw (TypeCheckingExceptionPrivate, AssertionException) {
+ Assert(n.getKind() == kind::SEP_EMP);
+ return nodeManager->booleanType();
+ }
+};
+
+struct SepPtoTypeRule {
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
+ throw (TypeCheckingExceptionPrivate, AssertionException) {
+ Assert(n.getKind() == kind::SEP_PTO);
+ if( check ) {
+ TypeNode refType = n[0].getType(check);
+ TypeNode ptType = n[1].getType(check);
+ }
+ return nodeManager->booleanType();
+ }
+};/* struct SepSelectTypeRule */
+
+struct SepStarTypeRule {
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
+ throw (TypeCheckingExceptionPrivate, AssertionException) {
+ TypeNode btype = nodeManager->booleanType();
+ Assert(n.getKind() == kind::SEP_STAR);
+ if( check ){
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ TypeNode ctype = n[i].getType( check );
+ if( ctype!=btype ){
+ throw TypeCheckingExceptionPrivate(n, "child of sep star is not Boolean");
+ }
+ }
+ }
+ return btype;
+ }
+};/* struct SepStarTypeRule */
+
+struct SepWandTypeRule {
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
+ throw (TypeCheckingExceptionPrivate, AssertionException) {
+ TypeNode btype = nodeManager->booleanType();
+ Assert(n.getKind() == kind::SEP_WAND);
+ if( check ){
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ TypeNode ctype = n[i].getType( check );
+ if( ctype!=btype ){
+ throw TypeCheckingExceptionPrivate(n, "child of sep magic wand is not Boolean");
+ }
+ }
+ }
+ return btype;
+ }
+};/* struct SepWandTypeRule */
+
+struct SepLabelTypeRule {
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
+ throw (TypeCheckingExceptionPrivate, AssertionException) {
+ TypeNode btype = nodeManager->booleanType();
+ Assert(n.getKind() == kind::SEP_LABEL);
+ if( check ){
+ TypeNode ctype = n[0].getType( check );
+ if( ctype!=btype ){
+ throw TypeCheckingExceptionPrivate(n, "child of sep label is not Boolean");
+ }
+ TypeNode stype = n[1].getType( check );
+ if( !stype.isSet() ){
+ throw TypeCheckingExceptionPrivate(n, "label of sep label is not a set");
+ }
+ }
+ return btype;
+ }
+};/* struct SepLabelTypeRule */
+
+}/* CVC4::theory::sep namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
+
+#endif /* __CVC4__THEORY__SEP__THEORY_SEP_TYPE_RULES_H */
diff --git a/src/theory/sets/kinds b/src/theory/sets/kinds
index 3fb73749d..c92eab4bd 100644
--- a/src/theory/sets/kinds
+++ b/src/theory/sets/kinds
@@ -64,6 +64,7 @@ typerule PRODUCT ::CVC4::theory::sets::RelBinaryOperatorTypeRule
typerule TRANSPOSE ::CVC4::theory::sets::RelTransposeTypeRule
typerule TCLOSURE ::CVC4::theory::sets::RelTransClosureTypeRule
+
construle UNION ::CVC4::theory::sets::SetsBinaryOperatorTypeRule
construle INTERSECTION ::CVC4::theory::sets::SetsBinaryOperatorTypeRule
construle SETMINUS ::CVC4::theory::sets::SetsBinaryOperatorTypeRule
diff --git a/src/theory/sets/theory_sets_private.h b/src/theory/sets/theory_sets_private.h
index 217432670..37071eb2e 100644
--- a/src/theory/sets/theory_sets_private.h
+++ b/src/theory/sets/theory_sets_private.h
@@ -139,6 +139,20 @@ private:
*/
bool lemma(Node n, SetsLemmaTag t);
+ /** send out a lemma */
+ enum SetsLemmaTag {
+ SETS_LEMMA_DISEQUAL,
+ SETS_LEMMA_MEMBER,
+ SETS_LEMMA_GRAPH,
+ SETS_LEMMA_OTHER
+ };
+
+ /**
+ * returns true if a lemmas was generated
+ * returns false otherwise (found in cache)
+ */
+ bool lemma(Node n, SetsLemmaTag t);
+
class TermInfoManager {
TheorySetsPrivate& d_theory;
context::Context* d_context;
diff --git a/src/theory/sets/theory_sets_type_rules.h b/src/theory/sets/theory_sets_type_rules.h
index 92d6c9b6d..478dcbdb6 100644
--- a/src/theory/sets/theory_sets_type_rules.h
+++ b/src/theory/sets/theory_sets_type_rules.h
@@ -275,6 +275,7 @@ struct RelTransClosureTypeRule {
}
};/* struct RelTransClosureTypeRule */
+
struct SetsProperties {
inline static Cardinality computeCardinality(TypeNode type) {
Assert(type.getKind() == kind::SET_TYPE);
diff --git a/src/theory/strings/regexp_operation.cpp b/src/theory/strings/regexp_operation.cpp
index 53344dd6c..a665a02c1 100644
--- a/src/theory/strings/regexp_operation.cpp
+++ b/src/theory/strings/regexp_operation.cpp
@@ -39,6 +39,10 @@ RegExpOpr::RegExpOpr()
d_sigma_star = NodeManager::currentNM()->mkNode( kind::REGEXP_STAR, d_sigma );
}
+RegExpOpr::~RegExpOpr(){
+
+}
+
int RegExpOpr::gcd ( int a, int b ) {
int c;
while ( a != 0 ) {
diff --git a/src/theory/strings/regexp_operation.h b/src/theory/strings/regexp_operation.h
index c537553f2..075391370 100644
--- a/src/theory/strings/regexp_operation.h
+++ b/src/theory/strings/regexp_operation.h
@@ -99,6 +99,7 @@ private:
public:
RegExpOpr();
+ ~RegExpOpr();
bool checkConstRegExp( Node r );
void simplify(Node t, std::vector< Node > &new_nodes, bool polarity);
diff --git a/src/theory/strings/theory_strings.cpp b/src/theory/strings/theory_strings.cpp
index b3e1925ae..57344236e 100644
--- a/src/theory/strings/theory_strings.cpp
+++ b/src/theory/strings/theory_strings.cpp
@@ -28,6 +28,7 @@
#include "theory/strings/type_enumerator.h"
#include "theory/theory_model.h"
#include "theory/valuation.h"
+#include "theory/quantifiers/term_database.h"
using namespace std;
using namespace CVC4::context;
@@ -74,9 +75,11 @@ TheoryStrings::TheoryStrings(context::Context* c, context::UserContext* u,
d_preproc(u),
d_preproc_cache(u),
d_extf_infer_cache(c),
+ d_ee_disequalities(c),
d_congruent(c),
d_proxy_var(u),
d_proxy_var_to_length(u),
+ d_functionsTerms(c),
d_neg_ctn_eqlen(c),
d_neg_ctn_ulen(c),
d_neg_ctn_cached(u),
@@ -124,7 +127,9 @@ TheoryStrings::TheoryStrings(context::Context* c, context::UserContext* u,
}
TheoryStrings::~TheoryStrings() {
-
+ for( std::map< Node, EqcInfo* >::iterator it = d_eqc_info.begin(); it != d_eqc_info.end(); ++it ){
+ delete it->second;
+ }
}
Node TheoryStrings::getRepresentative( Node t ) {
@@ -467,18 +472,30 @@ void TheoryStrings::preRegisterTerm(TNode n) {
break;
}
default: {
- if( n.getType().isString() ) {
+ TypeNode tn = n.getType();
+ if( tn.isString() ) {
registerTerm( n, 0 );
// FMF
if( n.getKind() == kind::VARIABLE && options::stringFMF() ){
d_input_vars.insert(n);
}
- } else if (n.getType().isBoolean()) {
+ d_equalityEngine.addTerm(n);
+ } else if (tn.isBoolean()) {
// Get triggered for both equal and dis-equal
d_equalityEngine.addTriggerPredicate(n);
} else {
// Function applications/predicates
d_equalityEngine.addTerm(n);
+ if( options::stringExp() ){
+ //collect extended functions here: some may not be asserted to strings (such as those with return type Int),
+ // but we need to record them so they are treated properly
+ std::map< Node, bool > visited;
+ collectExtendedFuncTerms( n, visited );
+ }
+ }
+ //concat terms do not contribute to theory combination? TODO: verify
+ if( n.hasOperator() && kindToTheoryId( n.getKind() )==THEORY_STRINGS && n.getKind()!=kind::STRING_CONCAT ){
+ d_functionsTerms.push_back( n );
}
}
}
@@ -486,6 +503,7 @@ void TheoryStrings::preRegisterTerm(TNode n) {
}
Node TheoryStrings::expandDefinition(LogicRequest &logicRequest, Node node) {
+ Trace("strings-exp-def") << "TheoryStrings::expandDefinition : " << node << std::endl;
return node;
}
@@ -740,53 +758,23 @@ void TheoryStrings::eqNotifyNewClass(TNode t){
/** called when two equivalance classes will merge */
void TheoryStrings::eqNotifyPreMerge(TNode t1, TNode t2){
- EqcInfo * e2 = getOrMakeEqcInfo(t2, false);
- if( e2 ){
- EqcInfo * e1 = getOrMakeEqcInfo( t1 );
- //add information from e2 to e1
- if( !e2->d_const_term.get().isNull() ){
- e1->d_const_term.set( e2->d_const_term );
- }
- if( !e2->d_length_term.get().isNull() ){
- e1->d_length_term.set( e2->d_length_term );
- }
- if( e2->d_cardinality_lem_k.get()>e1->d_cardinality_lem_k.get() ) {
- e1->d_cardinality_lem_k.set( e2->d_cardinality_lem_k );
- }
- if( !e2->d_normalized_length.get().isNull() ){
- e1->d_normalized_length.set( e2->d_normalized_length );
- }
+ EqcInfo * e2 = getOrMakeEqcInfo(t2, false);
+ if( e2 ){
+ EqcInfo * e1 = getOrMakeEqcInfo( t1 );
+ //add information from e2 to e1
+ if( !e2->d_const_term.get().isNull() ){
+ e1->d_const_term.set( e2->d_const_term );
}
- /*
- if( hasTerm( d_zero ) ){
- Node leqc;
- if( areEqual(d_zero, t1) ){
- leqc = t2;
- }else if( areEqual(d_zero, t2) ){
- leqc = t1;
- }
- if( !leqc.isNull() ){
- //scan equivalence class to see if we apply
- eq::EqClassIterator eqc_i = eq::EqClassIterator( leqc, &d_equalityEngine );
- while( !eqc_i.isFinished() ){
- Node n = (*eqc_i);
- if( n.getKind()==kind::STRING_LENGTH ){
- if( !hasTerm( d_emptyString ) || !areEqual(n[0], d_emptyString ) ){
- //apply the rule length(n[0])==0 => n[0] == ""
- Node eq = NodeManager::currentNM()->mkNode( kind::EQUAL, n[0], d_emptyString );
- d_pending.push_back( eq );
- Node eq_exp = NodeManager::currentNM()->mkNode( kind::EQUAL, n, d_zero );
- d_pending_exp[eq] = eq_exp;
- Trace("strings-infer") << "Strings : Infer Empty : " << eq << " from " << eq_exp << std::endl;
- d_infer.push_back(eq);
- d_infer_exp.push_back(eq_exp);
- }
- }
- ++eqc_i;
- }
- }
+ if( !e2->d_length_term.get().isNull() ){
+ e1->d_length_term.set( e2->d_length_term );
+ }
+ if( e2->d_cardinality_lem_k.get()>e1->d_cardinality_lem_k.get() ) {
+ e1->d_cardinality_lem_k.set( e2->d_cardinality_lem_k );
}
- */
+ if( !e2->d_normalized_length.get().isNull() ){
+ e1->d_normalized_length.set( e2->d_normalized_length );
+ }
+ }
}
/** called when two equivalance classes have merged */
@@ -796,11 +784,106 @@ void TheoryStrings::eqNotifyPostMerge(TNode t1, TNode t2) {
/** called when two equivalance classes are disequal */
void TheoryStrings::eqNotifyDisequal(TNode t1, TNode t2, TNode reason) {
+ if( t1.getType().isString() ){
+ //store disequalities between strings, may need to check if their lengths are equal/disequal
+ d_ee_disequalities.push_back( t1.eqNode( t2 ) );
+ }
+}
+void TheoryStrings::addCarePairs( quantifiers::TermArgTrie * t1, quantifiers::TermArgTrie * t2, unsigned arity, unsigned depth ) {
+ if( depth==arity ){
+ if( t2!=NULL ){
+ Node f1 = t1->getNodeData();
+ Node f2 = t2->getNodeData();
+ if( !d_equalityEngine.areEqual( f1, f2 ) ){
+ Trace("strings-cg-debug") << "TheoryStrings::computeCareGraph(): checking function " << f1 << " and " << f2 << std::endl;
+ vector< pair<TNode, TNode> > currentPairs;
+ for (unsigned k = 0; k < f1.getNumChildren(); ++ k) {
+ TNode x = f1[k];
+ TNode y = f2[k];
+ Assert( d_equalityEngine.hasTerm(x) );
+ Assert( d_equalityEngine.hasTerm(y) );
+ Assert( !d_equalityEngine.areDisequal( x, y, false ) );
+ if( !d_equalityEngine.areEqual( x, y ) ){
+ if( d_equalityEngine.isTriggerTerm(x, THEORY_STRINGS) && d_equalityEngine.isTriggerTerm(y, THEORY_STRINGS) ){
+ TNode x_shared = d_equalityEngine.getTriggerTermRepresentative(x, THEORY_STRINGS);
+ TNode y_shared = d_equalityEngine.getTriggerTermRepresentative(y, THEORY_STRINGS);
+ EqualityStatus eqStatus = d_valuation.getEqualityStatus(x_shared, y_shared);
+ if( eqStatus==EQUALITY_FALSE_AND_PROPAGATED || eqStatus==EQUALITY_FALSE || eqStatus==EQUALITY_FALSE_IN_MODEL ){
+ //an argument is disequal, we are done
+ return;
+ }else{
+ currentPairs.push_back(make_pair(x_shared, y_shared));
+ }
+ }
+ }
+ }
+ for (unsigned c = 0; c < currentPairs.size(); ++ c) {
+ Trace("strings-cg-pair") << "TheoryStrings::computeCareGraph(): pair : " << currentPairs[c].first << " " << currentPairs[c].second << std::endl;
+ Trace("ajr-temp") << currentPairs[c].first << ", " << currentPairs[c].second << std::endl;
+ addCarePair(currentPairs[c].first, currentPairs[c].second);
+ }
+ }
+ }
+ }else{
+ if( t2==NULL ){
+ if( depth<(arity-1) ){
+ //add care pairs internal to each child
+ for( std::map< TNode, quantifiers::TermArgTrie >::iterator it = t1->d_data.begin(); it != t1->d_data.end(); ++it ){
+ addCarePairs( &it->second, NULL, arity, depth+1 );
+ }
+ }
+ //add care pairs based on each pair of non-disequal arguments
+ for( std::map< TNode, quantifiers::TermArgTrie >::iterator it = t1->d_data.begin(); it != t1->d_data.end(); ++it ){
+ std::map< TNode, quantifiers::TermArgTrie >::iterator it2 = it;
+ ++it2;
+ for( ; it2 != t1->d_data.end(); ++it2 ){
+ if( !d_equalityEngine.areDisequal(it->first, it2->first, false) ){
+ addCarePairs( &it->second, &it2->second, arity, depth+1 );
+ }
+ }
+ }
+ }else{
+ //add care pairs based on product of indices, non-disequal arguments
+ for( std::map< TNode, quantifiers::TermArgTrie >::iterator it = t1->d_data.begin(); it != t1->d_data.end(); ++it ){
+ for( std::map< TNode, quantifiers::TermArgTrie >::iterator it2 = t2->d_data.begin(); it2 != t2->d_data.end(); ++it2 ){
+ if( !d_equalityEngine.areDisequal(it->first, it2->first, false) ){
+ addCarePairs( &it->second, &it2->second, arity, depth+1 );
+ }
+ }
+ }
+ }
+ }
}
void TheoryStrings::computeCareGraph(){
- Theory::computeCareGraph();
+ //computing the care graph here is probably still necessary, due to operators that take non-string arguments TODO: verify
+ Trace("strings-cg") << "TheoryStrings::computeCareGraph(): Build term indices..." << std::endl;
+ std::map< Node, quantifiers::TermArgTrie > index;
+ std::map< Node, unsigned > arity;
+ unsigned functionTerms = d_functionsTerms.size();
+ for (unsigned i = 0; i < functionTerms; ++ i) {
+ TNode f1 = d_functionsTerms[i];
+ Trace("strings-cg") << "...build for " << f1 << std::endl;
+ Node op = f1.getOperator();
+ std::vector< TNode > reps;
+ bool has_trigger_arg = false;
+ for( unsigned j=0; j<f1.getNumChildren(); j++ ){
+ reps.push_back( d_equalityEngine.getRepresentative( f1[j] ) );
+ if( d_equalityEngine.isTriggerTerm( f1[j], THEORY_STRINGS ) ){
+ has_trigger_arg = true;
+ }
+ }
+ if( has_trigger_arg ){
+ index[op].addTerm( f1, reps );
+ arity[op] = reps.size();
+ }
+ }
+ //for each index
+ for( std::map< Node, quantifiers::TermArgTrie >::iterator itii = index.begin(); itii != index.end(); ++itii ){
+ Trace("strings-cg") << "TheoryStrings::computeCareGraph(): Process index " << itii->first << "..." << std::endl;
+ addCarePairs( &itii->second, NULL, arity[ itii->first ], 0 );
+ }
}
void TheoryStrings::assertPendingFact(Node atom, bool polarity, Node exp) {
@@ -1136,8 +1219,12 @@ void TheoryStrings::checkExtendedFuncsEval( int effort ) {
}else{
if( !areEqual( n, nrc ) ){
if( n.getType().isBoolean() ){
- d_extf_exp[n].push_back( nrc==d_true ? n.negate() : n );
- conc = d_false;
+ if( areEqual( n, nrc==d_true ? d_false : d_true ) ){
+ d_extf_exp[n].push_back( nrc==d_true ? n.negate() : n );
+ conc = d_false;
+ }else{
+ conc = nrc==d_true ? n : n.negate();
+ }
}else{
conc = n.eqNode( nrc );
}
@@ -1145,7 +1232,7 @@ void TheoryStrings::checkExtendedFuncsEval( int effort ) {
}
if( !conc.isNull() ){
Trace("strings-extf") << " resolve extf : " << nr << " -> " << nrc << std::endl;
- sendInference( d_extf_exp[n], conc, effort==0 ? "EXTF" : "EXTF-N", n.getType().isInteger() || d_extf_exp[n].empty() );
+ sendInference( d_extf_exp[n], conc, effort==0 ? "EXTF" : "EXTF-N", true );
if( d_conflict ){
Trace("strings-extf-debug") << " conflict, return." << std::endl;
return;
@@ -1745,9 +1832,9 @@ bool TheoryStrings::normalizeEquivalenceClass( Node eqc, std::vector< Node > & n
}
nf.insert( nf.end(), normal_forms[nf_index].begin(), normal_forms[nf_index].end() );
nf_exp.insert( nf_exp.end(), normal_forms_exp[nf_index].begin(), normal_forms_exp[nf_index].end() );
- //if( eqc!=normal_form_src[nf_index] ){
- // nf_exp.push_back( eqc.eqNode( normal_form_src[nf_index] ) );
- //}
+ if( eqc!=normal_form_src[nf_index] ){
+ nf_exp.push_back( eqc.eqNode( normal_form_src[nf_index] ) );
+ }
Trace("strings-solve-debug2") << "take normal form ... done" << std::endl;
d_normal_forms_base[eqc] = normal_form_src[nf_index];
//*/
@@ -2639,23 +2726,17 @@ int TheoryStrings::processSimpleDeq( std::vector< Node >& nfi, std::vector< Node
void TheoryStrings::addNormalFormPair( Node n1, Node n2 ){
if( !isNormalFormPair( n1, n2 ) ){
- //Assert( !isNormalFormPair( n1, n2 ) );
- NodeList* lst;
- NodeListMap::iterator nf_i = d_nf_pairs.find( n1 );
- if( nf_i == d_nf_pairs.end() ){
- if( d_nf_pairs.find( n2 )!=d_nf_pairs.end() ){
- addNormalFormPair( n2, n1 );
- return;
- }
- lst = new(getSatContext()->getCMM()) NodeList( true, getSatContext(), false,
- ContextMemoryAllocator<TNode>(getSatContext()->getCMM()) );
- d_nf_pairs.insertDataFromContextMemory( n1, lst );
- Trace("strings-nf") << "Create cache for " << n1 << std::endl;
- } else {
- lst = (*nf_i).second;
- }
- Trace("strings-nf") << "Add normal form pair : " << n1 << " " << n2 << std::endl;
- lst->push_back( n2 );
+ int index = 0;
+ NodeIntMap::const_iterator it = d_nf_pairs.find( n1 );
+ if( it!=d_nf_pairs.end() ){
+ index = (*it).second;
+ }
+ d_nf_pairs[n1] = index + 1;
+ if( index<(int)d_nf_pairs_data[n1].size() ){
+ d_nf_pairs_data[n1][index] = n2;
+ }else{
+ d_nf_pairs_data[n1].push_back( n2 );
+ }
Assert( isNormalFormPair( n1, n2 ) );
} else {
Trace("strings-nf-debug") << "Already a normal form pair " << n1 << " " << n2 << std::endl;
@@ -2668,15 +2749,14 @@ bool TheoryStrings::isNormalFormPair( Node n1, Node n2 ) {
}
bool TheoryStrings::isNormalFormPair2( Node n1, Node n2 ) {
- //Trace("strings-debug") << "is normal form pair. " << n1 << " " << n2 << std::endl;
- NodeList* lst;
- NodeListMap::iterator nf_i = d_nf_pairs.find( n1 );
- if( nf_i != d_nf_pairs.end() ) {
- lst = (*nf_i).second;
- for( NodeList::const_iterator i = lst->begin(); i != lst->end(); ++i ) {
- Node n = *i;
- if( n==n2 ) {
- return true;
+ //Trace("strings-debug") << "is normal form pair. " << n1 << " " << n2 << std::endl;
+ NodeIntMap::const_iterator it = d_nf_pairs.find( n1 );
+ if( it!=d_nf_pairs.end() ){
+ Assert( d_nf_pairs_data.find( n1 )!=d_nf_pairs_data.end() );
+ for( int i=0; i<(*it).second; i++ ){
+ Assert( i<(int)d_nf_pairs_data[n1].size() );
+ if( d_nf_pairs_data[n1][i]==n2 ){
+ return true;
}
}
}
@@ -2752,7 +2832,7 @@ void TheoryStrings::sendInference( std::vector< Node >& exp, std::vector< Node >
eq = eq.isNull() ? d_false : Rewriter::rewrite( eq );
if( eq!=d_true ){
if( Trace.isOn("strings-infer-debug") ){
- Trace("strings-infer-debug") << "infer : " << eq << " from: " << std::endl;
+ Trace("strings-infer-debug") << "By " << c << ", infer : " << eq << " from: " << std::endl;
for( unsigned i=0; i<exp.size(); i++ ){
Trace("strings-infer-debug") << " " << exp[i] << std::endl;
}
@@ -2761,8 +2841,8 @@ void TheoryStrings::sendInference( std::vector< Node >& exp, std::vector< Node >
}
//Trace("strings-infer-debug") << "as lemma : " << asLemma << std::endl;
}
- bool doSendLemma = ( asLemma || eq==d_false || eq.getKind()==kind::OR || options::stringInferAsLemmas() );
- if( doSendLemma ){
+ //check if we should send a lemma or an inference
+ if( asLemma || eq==d_false || eq.getKind()==kind::OR || !exp_n.empty() || options::stringInferAsLemmas() ){
Node eq_exp;
if( options::stringRExplainLemmas() ){
eq_exp = mkExplain( exp, exp_n );
@@ -2780,7 +2860,6 @@ void TheoryStrings::sendInference( std::vector< Node >& exp, std::vector< Node >
}
sendLemma( eq_exp, eq, c );
}else{
- Assert( exp_n.empty() );
sendInfer( mkAnd( exp ), eq, c );
}
}
@@ -3064,30 +3143,56 @@ void TheoryStrings::getConcatVec( Node n, std::vector< Node >& c ) {
void TheoryStrings::checkDeqNF() {
std::vector< std::vector< Node > > cols;
std::vector< Node > lts;
- separateByLength( d_strings_eqc, cols, lts );
- for( unsigned i=0; i<cols.size(); i++ ){
- if( cols[i].size()>1 && d_lemma_cache.empty() ){
- Trace("strings-solve") << "- Verify disequalities are processed for " << cols[i][0];
- printConcat( d_normal_forms[cols[i][0]], "strings-solve" );
- Trace("strings-solve") << "... #eql = " << cols[i].size() << std::endl;
- //must ensure that normal forms are disequal
- for( unsigned j=0; j<cols[i].size(); j++ ){
- for( unsigned k=(j+1); k<cols[i].size(); k++ ){
- if( areDisequal( cols[i][j], cols[i][k] ) ){
- Assert( !d_conflict );
- //if( !areDisequal( cols[i][j], cols[i][k] ) ){
- // sendSplit( cols[i][j], cols[i][k], "D-NORM", true );
- // return;
- //}else{
- Trace("strings-solve") << "- Compare " << cols[i][j] << " ";
- printConcat( d_normal_forms[cols[i][j]], "strings-solve" );
- Trace("strings-solve") << " against " << cols[i][k] << " ";
- printConcat( d_normal_forms[cols[i][k]], "strings-solve" );
- Trace("strings-solve") << "..." << std::endl;
- if( processDeq( cols[i][j], cols[i][k] ) ){
- return;
+ std::map< Node, std::map< Node, bool > > processed;
+
+ //for each pair of disequal strings, must determine whether their lengths are equal or disequal
+ bool addedLSplit = false;
+ for( NodeList::const_iterator id = d_ee_disequalities.begin(); id != d_ee_disequalities.end(); ++id ) {
+ Node eq = *id;
+ Node n[2];
+ for( unsigned i=0; i<2; i++ ){
+ n[i] = d_equalityEngine.getRepresentative( eq[i] );
+ }
+ if( processed[n[0]].find( n[1] )==processed[n[0]].end() ){
+ processed[n[0]][n[1]] = true;
+ Node lt[2];
+ for( unsigned i=0; i<2; i++ ){
+ EqcInfo* ei = getOrMakeEqcInfo( n[i], false );
+ lt[i] = ei ? ei->d_length_term : Node::null();
+ if( lt[i].isNull() ){
+ lt[i] = eq[i];
+ }
+ lt[i] = NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, lt[i] );
+ }
+ if( !areEqual( lt[0], lt[1] ) && !areDisequal( lt[0], lt[1] ) ){
+ addedLSplit = true;
+ sendSplit( lt[0], lt[1], "DEQ-LENGTH-SP" );
+ }
+ }
+ }
+
+ if( !addedLSplit ){
+ separateByLength( d_strings_eqc, cols, lts );
+ for( unsigned i=0; i<cols.size(); i++ ){
+ if( cols[i].size()>1 && d_lemma_cache.empty() ){
+ Trace("strings-solve") << "- Verify disequalities are processed for " << cols[i][0] << ", normal form : ";
+ printConcat( d_normal_forms[cols[i][0]], "strings-solve" );
+ Trace("strings-solve") << "... #eql = " << cols[i].size() << std::endl;
+ //must ensure that normal forms are disequal
+ for( unsigned j=0; j<cols[i].size(); j++ ){
+ for( unsigned k=(j+1); k<cols[i].size(); k++ ){
+ //for strings that are disequal, but have the same length
+ if( areDisequal( cols[i][j], cols[i][k] ) ){
+ Assert( !d_conflict );
+ Trace("strings-solve") << "- Compare " << cols[i][j] << " ";
+ printConcat( d_normal_forms[cols[i][j]], "strings-solve" );
+ Trace("strings-solve") << " against " << cols[i][k] << " ";
+ printConcat( d_normal_forms[cols[i][k]], "strings-solve" );
+ Trace("strings-solve") << "..." << std::endl;
+ if( processDeq( cols[i][j], cols[i][k] ) ){
+ return;
+ }
}
- //}
}
}
}
@@ -3149,6 +3254,9 @@ void TheoryStrings::checkCardinality() {
//int cardinality = options::stringCharCardinality();
//Trace("strings-solve-debug2") << "get cardinality: " << cardinality << endl;
+ //AJR: this will create a partition of eqc, where each collection has length that are pairwise propagated to be equal.
+ // we do not require disequalities between the lengths of each collection, since we split on disequalities between lengths of string terms that are disequal (DEQ-LENGTH-SP).
+ // TODO: revisit this?
std::vector< std::vector< Node > > cols;
std::vector< Node > lts;
separateByLength( d_strings_eqc, cols, lts );
@@ -3159,54 +3267,51 @@ void TheoryStrings::checkCardinality() {
if( cols[i].size() > 1 ) {
// size > c^k
unsigned card_need = 1;
- double curr = (double)cols[i].size()-1;
+ double curr = (double)cols[i].size();
while( curr>d_card_size ){
curr = curr/(double)d_card_size;
card_need++;
}
+ Trace("strings-card") << "Need length " << card_need << " for this number of strings (where alphabet size is " << d_card_size << ")." << std::endl;
Node cmp = NodeManager::currentNM()->mkNode( kind::GEQ, lr, NodeManager::currentNM()->mkConst( Rational( card_need ) ) );
cmp = Rewriter::rewrite( cmp );
if( cmp!=d_true ){
unsigned int int_k = (unsigned int)card_need;
- bool allDisequal = true;
for( std::vector< Node >::iterator itr1 = cols[i].begin();
itr1 != cols[i].end(); ++itr1) {
for( std::vector< Node >::iterator itr2 = itr1 + 1;
itr2 != cols[i].end(); ++itr2) {
if(!areDisequal( *itr1, *itr2 )) {
- allDisequal = false;
// add split lemma
sendSplit( *itr1, *itr2, "CARD-SP" );
return;
}
}
}
- if( allDisequal ){
- EqcInfo* ei = getOrMakeEqcInfo( lr, true );
- Trace("strings-card") << "Previous cardinality used for " << lr << " is " << ((int)ei->d_cardinality_lem_k.get()-1) << std::endl;
- if( int_k+1 > ei->d_cardinality_lem_k.get() ){
- Node k_node = NodeManager::currentNM()->mkConst( ::CVC4::Rational( int_k ) );
- //add cardinality lemma
- Node dist = NodeManager::currentNM()->mkNode( kind::DISTINCT, cols[i] );
- std::vector< Node > vec_node;
- vec_node.push_back( dist );
- for( std::vector< Node >::iterator itr1 = cols[i].begin();
- itr1 != cols[i].end(); ++itr1) {
- Node len = NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, *itr1 );
- if( len!=lr ) {
- Node len_eq_lr = len.eqNode(lr);
- vec_node.push_back( len_eq_lr );
- }
- }
- Node len = NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, cols[i][0] );
- Node cons = NodeManager::currentNM()->mkNode( kind::GEQ, len, k_node );
- cons = Rewriter::rewrite( cons );
- ei->d_cardinality_lem_k.set( int_k+1 );
- if( cons!=d_true ){
- sendInference( d_empty_vec, vec_node, cons, "CARDINALITY", true );
- return;
+ EqcInfo* ei = getOrMakeEqcInfo( lr, true );
+ Trace("strings-card") << "Previous cardinality used for " << lr << " is " << ((int)ei->d_cardinality_lem_k.get()-1) << std::endl;
+ if( int_k+1 > ei->d_cardinality_lem_k.get() ){
+ Node k_node = NodeManager::currentNM()->mkConst( ::CVC4::Rational( int_k ) );
+ //add cardinality lemma
+ Node dist = NodeManager::currentNM()->mkNode( kind::DISTINCT, cols[i] );
+ std::vector< Node > vec_node;
+ vec_node.push_back( dist );
+ for( std::vector< Node >::iterator itr1 = cols[i].begin();
+ itr1 != cols[i].end(); ++itr1) {
+ Node len = NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, *itr1 );
+ if( len!=lr ) {
+ Node len_eq_lr = len.eqNode(lr);
+ vec_node.push_back( len_eq_lr );
}
}
+ Node len = NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, cols[i][0] );
+ Node cons = NodeManager::currentNM()->mkNode( kind::GEQ, len, k_node );
+ cons = Rewriter::rewrite( cons );
+ ei->d_cardinality_lem_k.set( int_k+1 );
+ if( cons!=d_true ){
+ sendInference( d_empty_vec, vec_node, cons, "CARDINALITY", true );
+ return;
+ }
}
}
}
@@ -3275,11 +3380,9 @@ void TheoryStrings::separateByLength(std::vector< Node >& n,
Assert( d_equalityEngine.getRepresentative(eqc)==eqc );
EqcInfo* ei = getOrMakeEqcInfo( eqc, false );
Node lt = ei ? ei->d_length_term : Node::null();
- Trace("ajr-temp") << "Length term for " << eqc << " is " << lt << std::endl;
if( !lt.isNull() ){
lt = NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, lt );
Node r = d_equalityEngine.getRepresentative( lt );
- Trace("ajr-temp") << "Length term rep for " << eqc << " is " << lt << std::endl;
if( eqc_to_leqc.find( r )==eqc_to_leqc.end() ){
eqc_to_leqc[r] = leqc_counter;
leqc_to_eqc[leqc_counter] = r;
@@ -3318,6 +3421,26 @@ void TheoryStrings::updateMpl( Node n, int b ) {
}
*/
+
+unsigned TheoryStrings::getNumMemberships( Node n, bool isPos ) {
+ if( isPos ){
+ NodeIntMap::const_iterator it = d_pos_memberships.find( n );
+ if( it!=d_pos_memberships.end() ){
+ return (*it).second;
+ }
+ }else{
+ NodeIntMap::const_iterator it = d_neg_memberships.find( n );
+ if( it!=d_neg_memberships.end() ){
+ return (*it).second;
+ }
+ }
+ return 0;
+}
+
+Node TheoryStrings::getMembership( Node n, bool isPos, unsigned i ) {
+ return isPos ? d_pos_memberships_data[n][i] : d_neg_memberships_data[n][i];
+}
+
//// Regular Expressions
Node TheoryStrings::mkRegExpAntec(Node atom, Node ant) {
if(d_regexp_ant.find(atom) == d_regexp_ant.end()) {
@@ -3395,10 +3518,8 @@ bool TheoryStrings::normalizePosMemberships(std::map< Node, std::vector< Node >
Trace("regexp-check") << "Normalizing Positive Memberships ... " << std::endl;
- for(NodeListMap::const_iterator itr_xr = d_pos_memberships.begin();
- itr_xr != d_pos_memberships.end(); ++itr_xr ) {
+ for( NodeIntMap::const_iterator itr_xr = d_pos_memberships.begin(); itr_xr != d_pos_memberships.end(); ++itr_xr ){
Node x = (*itr_xr).first;
- NodeList* lst = (*itr_xr).second;
Node nf_x = x;
std::vector< Node > nf_x_exp;
if(d_normal_forms.find( x ) != d_normal_forms.end()) {
@@ -3412,10 +3533,11 @@ bool TheoryStrings::normalizePosMemberships(std::map< Node, std::vector< Node >
std::vector< Node > vec_x;
std::vector< Node > vec_r;
- for(NodeList::const_iterator itr_lst = lst->begin();
- itr_lst != lst->end(); ++itr_lst) {
- Node r = *itr_lst;
- Node nf_r = normalizeRegexp((*lst)[0]);
+ unsigned n_pmem = (*itr_xr).second;
+ Assert( getNumMemberships( x, true )==n_pmem );
+ for( unsigned k=0; k<n_pmem; k++ ){
+ Node r = getMembership( x, true, k );
+ Node nf_r = normalizeRegexp( r ); //AJR: fixed (was normalizing mem #0 always)
Node memb = NodeManager::currentNM()->mkNode(kind::STRING_IN_REGEXP, nf_x, nf_r);
if(d_processed_memberships.find(memb) == d_processed_memberships.end()) {
if(d_regexp_opr.checkConstRegExp(nf_r)) {
@@ -3645,46 +3767,43 @@ void TheoryStrings::checkMemberships() {
Trace("regexp-debug") << "Checking Memberships ... " << std::endl;
//if(options::stringEIT()) {
//TODO: Opt for normal forms
- for(NodeListMap::const_iterator itr_xr = d_pos_memberships.begin();
- itr_xr != d_pos_memberships.end(); ++itr_xr ) {
+ for( NodeIntMap::const_iterator itr_xr = d_pos_memberships.begin(); itr_xr != d_pos_memberships.end(); ++itr_xr ){
bool spflag = false;
Node x = (*itr_xr).first;
- NodeList* lst = (*itr_xr).second;
Trace("regexp-debug") << "Checking Memberships for " << x << std::endl;
if(d_inter_index.find(x) == d_inter_index.end()) {
d_inter_index[x] = 0;
}
int cur_inter_idx = d_inter_index[x];
- if(cur_inter_idx != (int)lst->size()) {
- if(lst->size() == 1) {
- d_inter_cache[x] = (*lst)[0];
+ unsigned n_pmem = (*itr_xr).second;
+ Assert( getNumMemberships( x, true )==n_pmem );
+ if( cur_inter_idx != (int)n_pmem ) {
+ if( n_pmem == 1) {
+ d_inter_cache[x] = getMembership( x, true, 0 );
d_inter_index[x] = 1;
Trace("regexp-debug") << "... only one choice " << std::endl;
- } else if(lst->size() > 1) {
+ } else if(n_pmem > 1) {
Node r;
if(d_inter_cache.find(x) != d_inter_cache.end()) {
r = d_inter_cache[x];
}
if(r.isNull()) {
- r = (*lst)[0];
+ r = getMembership( x, true, 0 );
cur_inter_idx = 1;
}
- NodeList::const_iterator itr_lst = lst->begin();
- for(int i=0; i<cur_inter_idx; i++) {
- ++itr_lst;
- }
- Trace("regexp-debug") << "... staring from : " << cur_inter_idx << ", we have " << lst->size() << std::endl;
- for(;itr_lst != lst->end(); ++itr_lst) {
- Node r2 = *itr_lst;
+
+ unsigned k_start = cur_inter_idx;
+ Trace("regexp-debug") << "... staring from : " << cur_inter_idx << ", we have " << n_pmem << std::endl;
+ for(unsigned k = k_start; k<n_pmem; k++) {
+ Node r2 = getMembership( x, true, k );
r = d_regexp_opr.intersect(r, r2, spflag);
if(spflag) {
break;
} else if(r == d_emptyRegexp) {
std::vector< Node > vec_nodes;
- ++itr_lst;
- for(NodeList::const_iterator itr2 = lst->begin();
- itr2 != itr_lst; ++itr2) {
- Node n = NodeManager::currentNM()->mkNode(kind::STRING_IN_REGEXP, x, *itr2);
+ for( unsigned kk=0; kk<=k; kk++ ){
+ Node rr = getMembership( x, true, kk );
+ Node n = NodeManager::currentNM()->mkNode(kind::STRING_IN_REGEXP, x, rr);
vec_nodes.push_back( n );
}
Node conc;
@@ -3699,7 +3818,7 @@ void TheoryStrings::checkMemberships() {
//updates
if(!d_conflict && !spflag) {
d_inter_cache[x] = r;
- d_inter_index[x] = (int)lst->size();
+ d_inter_index[x] = (int)n_pmem;
}
}
}
@@ -4322,44 +4441,52 @@ void TheoryStrings::addMembership(Node assertion) {
Node x = atom[0];
Node r = atom[1];
if(polarity) {
- NodeList* lst;
- NodeListMap::iterator itr_xr = d_pos_memberships.find( x );
- if( itr_xr == d_pos_memberships.end() ){
- lst = new(getSatContext()->getCMM()) NodeList( true, getSatContext(), false,
- ContextMemoryAllocator<TNode>(getSatContext()->getCMM()) );
- d_pos_memberships.insertDataFromContextMemory( x, lst );
- } else {
- lst = (*itr_xr).second;
- }
- //check
- for( NodeList::const_iterator itr = lst->begin(); itr != lst->end(); ++itr ) {
- if( r == *itr ) {
- return;
+ int index = 0;
+ NodeIntMap::const_iterator it = d_pos_memberships.find( x );
+ if( it!=d_nf_pairs.end() ){
+ index = (*it).second;
+ for( int k=0; k<index; k++ ){
+ if( k<(int)d_pos_memberships_data[x].size() ){
+ if( d_pos_memberships_data[x][k]==r ){
+ return;
+ }
+ }else{
+ break;
+ }
}
}
- lst->push_back( r );
+ d_pos_memberships[x] = index + 1;
+ if( index<(int)d_pos_memberships_data[x].size() ){
+ d_pos_memberships_data[x][index] = r;
+ }else{
+ d_pos_memberships_data[x].push_back( r );
+ }
} else if(!options::stringIgnNegMembership()) {
/*if(options::stringEIT() && d_regexp_opr.checkConstRegExp(r)) {
int rt;
Node r2 = d_regexp_opr.complement(r, rt);
Node a = NodeManager::currentNM()->mkNode(kind::STRING_IN_REGEXP, x, r2);
}*/
- NodeList* lst;
- NodeListMap::iterator itr_xr = d_neg_memberships.find( x );
- if( itr_xr == d_neg_memberships.end() ){
- lst = new(getSatContext()->getCMM()) NodeList( true, getSatContext(), false,
- ContextMemoryAllocator<TNode>(getSatContext()->getCMM()) );
- d_neg_memberships.insertDataFromContextMemory( x, lst );
- } else {
- lst = (*itr_xr).second;
- }
- //check
- for( NodeList::const_iterator itr = lst->begin(); itr != lst->end(); ++itr ) {
- if( r == *itr ) {
- return;
+ int index = 0;
+ NodeIntMap::const_iterator it = d_neg_memberships.find( x );
+ if( it!=d_nf_pairs.end() ){
+ index = (*it).second;
+ for( int k=0; k<index; k++ ){
+ if( k<(int)d_neg_memberships_data[x].size() ){
+ if( d_neg_memberships_data[x][k]==r ){
+ return;
+ }
+ }else{
+ break;
+ }
}
}
- lst->push_back( r );
+ d_neg_memberships[x] = index + 1;
+ if( index<(int)d_neg_memberships_data[x].size() ){
+ d_neg_memberships_data[x][index] = r;
+ }else{
+ d_neg_memberships_data[x].push_back( r );
+ }
}
// old
if(polarity || !options::stringIgnNegMembership()) {
diff --git a/src/theory/strings/theory_strings.h b/src/theory/strings/theory_strings.h
index b9da524de..2deb09654 100644
--- a/src/theory/strings/theory_strings.h
+++ b/src/theory/strings/theory_strings.h
@@ -33,6 +33,11 @@
namespace CVC4 {
namespace theory {
+
+namespace quantifiers{
+ class TermArgTrie;
+}
+
namespace strings {
/**
@@ -45,7 +50,6 @@ typedef expr::Attribute< StringsProxyVarAttributeId, bool > StringsProxyVarAttri
class TheoryStrings : public Theory {
typedef context::CDChunkList<Node> NodeList;
- typedef context::CDHashMap<Node, NodeList*, NodeHashFunction> NodeListMap;
typedef context::CDHashMap<Node, bool, NodeHashFunction> NodeBoolMap;
typedef context::CDHashMap<Node, int, NodeHashFunction> NodeIntMap;
typedef context::CDHashMap<Node, Node, NodeHashFunction> NodeNodeMap;
@@ -160,7 +164,8 @@ private:
std::map< Node, std::vector< Node > > d_normal_forms_exp;
std::map< Node, std::map< Node, std::map< bool, int > > > d_normal_forms_exp_depend;
//map of pairs of terms that have the same normal form
- NodeListMap d_nf_pairs;
+ NodeIntMap d_nf_pairs;
+ std::map< Node, std::vector< Node > > d_nf_pairs_data;
void addNormalFormPair( Node n1, Node n2 );
bool isNormalFormPair( Node n1, Node n2 );
bool isNormalFormPair2( Node n1, Node n2 );
@@ -176,6 +181,8 @@ private:
// extended functions inferences cache
NodeSet d_extf_infer_cache;
std::vector< Node > d_empty_vec;
+ //
+ NodeList d_ee_disequalities;
private:
NodeSet d_congruent;
std::map< Node, Node > d_eqc_to_const;
@@ -236,6 +243,8 @@ private:
//maintain which concat terms have the length lemma instantiated
NodeNodeMap d_proxy_var;
NodeNodeMap d_proxy_var_to_length;
+ /** All the function terms that the theory has seen */
+ context::CDList<TNode> d_functionsTerms;
private:
//initial check
void checkInit();
@@ -304,6 +313,8 @@ private:
//cardinality check
void checkCardinality();
+private:
+ void addCarePairs( quantifiers::TermArgTrie * t1, quantifiers::TermArgTrie * t2, unsigned arity, unsigned depth );
public:
/** preregister term */
void preRegisterTerm(TNode n);
@@ -410,8 +421,12 @@ private:
NodeSet d_regexp_ucached;
NodeSet d_regexp_ccached;
// stored assertions
- NodeListMap d_pos_memberships;
- NodeListMap d_neg_memberships;
+ NodeIntMap d_pos_memberships;
+ std::map< Node, std::vector< Node > > d_pos_memberships_data;
+ NodeIntMap d_neg_memberships;
+ std::map< Node, std::vector< Node > > d_neg_memberships_data;
+ unsigned getNumMemberships( Node n, bool isPos );
+ Node getMembership( Node n, bool isPos, unsigned i );
// semi normal forms for symbolic expression
std::map< Node, Node > d_nf_regexps;
std::map< Node, std::vector< Node > > d_nf_regexps_exp;
diff --git a/src/theory/strings/theory_strings_preprocess.cpp b/src/theory/strings/theory_strings_preprocess.cpp
index a4f42bddd..ba811644a 100644
--- a/src/theory/strings/theory_strings_preprocess.cpp
+++ b/src/theory/strings/theory_strings_preprocess.cpp
@@ -33,6 +33,10 @@ StringsPreprocess::StringsPreprocess( context::UserContext* u ) : d_cache( u ){
d_zero = NodeManager::currentNM()->mkConst( ::CVC4::Rational(0) );
}
+StringsPreprocess::~StringsPreprocess(){
+
+}
+
/*
int StringsPreprocess::checkFixLenVar( Node t ) {
int ret = 2;
diff --git a/src/theory/strings/theory_strings_preprocess.h b/src/theory/strings/theory_strings_preprocess.h
index 5bc9667ea..abc7b5a91 100644
--- a/src/theory/strings/theory_strings_preprocess.h
+++ b/src/theory/strings/theory_strings_preprocess.h
@@ -40,6 +40,7 @@ private:
Node simplify( Node t, std::vector< Node > &new_nodes );
public:
StringsPreprocess( context::UserContext* u );
+ ~StringsPreprocess();
Node decompose( Node t, std::vector< Node > &new_nodes );
void simplify(std::vector< Node > &vec_node);
diff --git a/src/theory/term_registration_visitor.cpp b/src/theory/term_registration_visitor.cpp
index 830e7f809..e758002fa 100644
--- a/src/theory/term_registration_visitor.cpp
+++ b/src/theory/term_registration_visitor.cpp
@@ -37,8 +37,12 @@ bool PreRegisterVisitor::alreadyVisited(TNode current, TNode parent) {
if( ( parent.getKind() == kind::FORALL ||
parent.getKind() == kind::EXISTS ||
- parent.getKind() == kind::REWRITE_RULE /*||
- parent.getKind() == kind::CARDINALITY_CONSTRAINT*/ ) &&
+ parent.getKind() == kind::REWRITE_RULE ||
+ parent.getKind() == kind::SEP_STAR ||
+ parent.getKind() == kind::SEP_WAND ||
+ ( parent.getKind() == kind::SEP_LABEL && current.getType().isBoolean() )
+ // parent.getKind() == kind::CARDINALITY_CONSTRAINT
+ ) &&
current != parent ) {
Debug("register::internal") << "quantifier:true" << std::endl;
return true;
@@ -64,14 +68,8 @@ bool PreRegisterVisitor::alreadyVisited(TNode current, TNode parent) {
TypeNode type = current.getType();
typeTheoryId = Theory::theoryOf(type);
if (typeTheoryId != currentTheoryId) {
- if (options::finiteModelFind() && type.isSort()) {
- // We're looking for finite models
+ if (type.isInterpretedFinite()) {
useType = true;
- } else {
- Cardinality card = type.getCardinality();
- if (card.isFinite()) {
- useType = true;
- }
}
}
}
@@ -130,14 +128,8 @@ void PreRegisterVisitor::visit(TNode current, TNode parent) {
TypeNode type = current.getType();
typeTheoryId = Theory::theoryOf(type);
if (typeTheoryId != currentTheoryId) {
- if (options::finiteModelFind() && type.isSort()) {
- // We're looking for finite models
+ if (type.isInterpretedFinite()) {
useType = true;
- } else {
- Cardinality card = type.getCardinality();
- if (card.isFinite()) {
- useType = true;
- }
}
}
}
@@ -189,8 +181,12 @@ bool SharedTermsVisitor::alreadyVisited(TNode current, TNode parent) const {
if( ( parent.getKind() == kind::FORALL ||
parent.getKind() == kind::EXISTS ||
- parent.getKind() == kind::REWRITE_RULE /*||
- parent.getKind() == kind::CARDINALITY_CONSTRAINT*/ ) &&
+ parent.getKind() == kind::REWRITE_RULE ||
+ parent.getKind() == kind::SEP_STAR ||
+ parent.getKind() == kind::SEP_WAND ||
+ ( parent.getKind() == kind::SEP_LABEL && current.getType().isBoolean() )
+ // parent.getKind() == kind::CARDINALITY_CONSTRAINT
+ ) &&
current != parent ) {
Debug("register::internal") << "quantifier:true" << std::endl;
return true;
@@ -222,14 +218,8 @@ bool SharedTermsVisitor::alreadyVisited(TNode current, TNode parent) const {
TypeNode type = current.getType();
typeTheoryId = Theory::theoryOf(type);
if (typeTheoryId != currentTheoryId) {
- if (options::finiteModelFind() && type.isSort()) {
- // We're looking for finite models
+ if (type.isInterpretedFinite()) {
useType = true;
- } else {
- Cardinality card = type.getCardinality();
- if (card.isFinite()) {
- useType = true;
- }
}
}
}
@@ -244,14 +234,8 @@ bool SharedTermsVisitor::alreadyVisited(TNode current, TNode parent) const {
TypeNode type = current.getType();
typeTheoryId = Theory::theoryOf(type);
if (typeTheoryId != currentTheoryId) {
- if (options::finiteModelFind() && type.isSort()) {
- // We're looking for finite models
+ if (type.isInterpretedFinite()) {
useType = true;
- } else {
- Cardinality card = type.getCardinality();
- if (card.isFinite()) {
- useType = true;
- }
}
}
}
@@ -297,14 +281,8 @@ void SharedTermsVisitor::visit(TNode current, TNode parent) {
TypeNode type = current.getType();
typeTheoryId = Theory::theoryOf(type);
if (typeTheoryId != currentTheoryId) {
- if (options::finiteModelFind() && type.isSort()) {
- // We're looking for finite models
+ if (type.isInterpretedFinite()) {
useType = true;
- } else {
- Cardinality card = type.getCardinality();
- if (card.isFinite()) {
- useType = true;
- }
}
}
}
diff --git a/src/theory/theory.h b/src/theory/theory.h
index 382d4cf65..e8518b1f6 100644
--- a/src/theory/theory.h
+++ b/src/theory/theory.h
@@ -781,6 +781,14 @@ public:
assertions_iterator facts_end() const {
return d_facts.end();
}
+ /**
+ * Whether facts have been asserted to this theory.
+ *
+ * @return true iff facts have been asserted to this theory.
+ */
+ bool hasFacts() {
+ return !d_facts.empty();
+ }
typedef context::CDList<TNode>::const_iterator shared_terms_iterator;
diff --git a/src/theory/theory_engine.cpp b/src/theory/theory_engine.cpp
index f2231ff7a..881acdddd 100644
--- a/src/theory/theory_engine.cpp
+++ b/src/theory/theory_engine.cpp
@@ -26,6 +26,8 @@
#include "options/bv_options.h"
#include "options/options.h"
#include "options/quantifiers_options.h"
+#include "proof/cnf_proof.h"
+#include "proof/lemma_proof.h"
#include "proof/proof_manager.h"
#include "proof/theory_proof.h"
#include "smt/ite_removal.h"
@@ -53,6 +55,104 @@ using namespace CVC4::theory;
namespace CVC4 {
+inline void flattenAnd(Node n, std::vector<TNode>& out){
+ Assert(n.getKind() == kind::AND);
+ for(Node::iterator i=n.begin(), i_end=n.end(); i != i_end; ++i){
+ Node curr = *i;
+ if(curr.getKind() == kind::AND){
+ flattenAnd(curr, out);
+ }else{
+ out.push_back(curr);
+ }
+ }
+}
+
+inline Node flattenAnd(Node n){
+ std::vector<TNode> out;
+ flattenAnd(n, out);
+ return NodeManager::currentNM()->mkNode(kind::AND, out);
+}
+
+theory::LemmaStatus TheoryEngine::EngineOutputChannel::lemma(TNode lemma,
+ ProofRule rule,
+ bool removable,
+ bool preprocess,
+ bool sendAtoms)
+ throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException) {
+ Debug("theory::lemma") << "EngineOutputChannel<" << d_theory << ">::lemma(" << lemma << ")" << ", preprocess = " << preprocess << std::endl;
+ ++ d_statistics.lemmas;
+ d_engine->d_outputChannelUsed = true;
+
+ LemmaProofRecipe* proofRecipe = NULL;
+ PROOF({
+ // Theory lemmas have one step that proves the empty clause
+ proofRecipe = new LemmaProofRecipe;
+
+ Node emptyNode;
+ LemmaProofRecipe::ProofStep proofStep(d_theory, emptyNode);
+
+ Node rewritten;
+ if (lemma.getKind() == kind::OR) {
+ for (unsigned i = 0; i < lemma.getNumChildren(); ++i) {
+ rewritten = theory::Rewriter::rewrite(lemma[i]);
+ if (rewritten != lemma[i]) {
+ proofRecipe->addRewriteRule(lemma[i].negate(), rewritten.negate());
+ }
+ proofStep.addAssertion(lemma[i]);
+ proofRecipe->addBaseAssertion(rewritten);
+ }
+ } else {
+ rewritten = theory::Rewriter::rewrite(lemma);
+ if (rewritten != lemma) {
+ proofRecipe->addRewriteRule(lemma.negate(), rewritten.negate());
+ }
+ proofStep.addAssertion(lemma);
+ proofRecipe->addBaseAssertion(rewritten);
+ }
+ proofRecipe->addStep(proofStep);
+ });
+
+ theory::LemmaStatus result = d_engine->lemma(lemma,
+ rule,
+ false,
+ removable,
+ preprocess,
+ sendAtoms ? d_theory : theory::THEORY_LAST,
+ proofRecipe);
+ PROOF(delete proofRecipe;);
+ return result;
+}
+
+theory::LemmaStatus TheoryEngine::EngineOutputChannel::splitLemma(TNode lemma, bool removable)
+ throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException) {
+ Debug("theory::lemma") << "EngineOutputChannel<" << d_theory << ">::lemma(" << lemma << ")" << std::endl;
+ ++ d_statistics.lemmas;
+ d_engine->d_outputChannelUsed = true;
+
+
+ LemmaProofRecipe* proofRecipe = NULL;
+ Debug("pf::explain") << "TheoryEngine::EngineOutputChannel::splitLemma( " << lemma << " )" << std::endl;
+ theory::LemmaStatus result = d_engine->lemma(lemma, RULE_SPLIT, false, removable, false, d_theory, proofRecipe);
+ return result;
+}
+
+bool TheoryEngine::EngineOutputChannel::propagate(TNode literal)
+ throw(AssertionException, UnsafeInterruptException) {
+ Debug("theory::propagate") << "EngineOutputChannel<" << d_theory << ">::propagate(" << literal << ")" << std::endl;
+ ++ d_statistics.propagations;
+ d_engine->d_outputChannelUsed = true;
+ return d_engine->propagate(literal, d_theory);
+}
+
+void TheoryEngine::EngineOutputChannel::conflict(TNode conflictNode, Proof* pf)
+ throw(AssertionException, UnsafeInterruptException) {
+ Trace("theory::conflict") << "EngineOutputChannel<" << d_theory << ">::conflict(" << conflictNode << ")" << std::endl;
+ Assert (pf == NULL); // Theory shouldn't be producing proofs yet
+ ++ d_statistics.conflicts;
+ d_engine->d_outputChannelUsed = true;
+ d_engine->conflict(conflictNode, d_theory);
+}
+
void TheoryEngine::finishInit() {
// initialize the quantifiers engine
d_quantEngine = new QuantifiersEngine(d_context, d_userContext, this);
@@ -161,7 +261,9 @@ TheoryEngine::TheoryEngine(context::Context* context,
d_true = NodeManager::currentNM()->mkConst<bool>(true);
d_false = NodeManager::currentNM()->mkConst<bool>(false);
- PROOF (ProofManager::currentPM()->initTheoryProofEngine(); );
+#ifdef CVC4_PROOF
+ ProofManager::currentPM()->initTheoryProofEngine();
+#endif
d_iteUtilities = new ITEUtilities(d_iteRemover.getContainsVisitor());
@@ -416,18 +518,29 @@ void TheoryEngine::check(Theory::Effort effort) {
// Must consult quantifiers theory for last call to ensure sat, or otherwise add a lemma
if( effort == Theory::EFFORT_FULL && ! d_inConflict && ! needCheck() ) {
- //d_theoryTable[THEORY_STRINGS]->check(Theory::EFFORT_LAST_CALL);
- if(d_logicInfo.isQuantified()) {
- // quantifiers engine must pass effort last call check
- d_quantEngine->check(Theory::EFFORT_LAST_CALL);
- // if returning incomplete or SAT, we have ensured that the model in the quantifiers engine has been built
- } else if(options::produceModels()) {
- // must build model at this point
- d_curr_model_builder->buildModel(d_curr_model, true);
+ //calls to theories requiring the model go here
+ //FIXME: this should not be theory-specific
+ if(d_logicInfo.isTheoryEnabled(THEORY_SEP)) {
+ Assert( d_theoryTable[THEORY_SEP]!=NULL );
+ if( d_theoryTable[THEORY_SEP]->hasFacts() ){
+ // must build model at this point
+ d_curr_model_builder->buildModel(getModel(), false);
+ d_theoryTable[THEORY_SEP]->check(Theory::EFFORT_LAST_CALL);
+ }
}
- Trace("theory::assertions-model") << endl;
- if (Trace.isOn("theory::assertions-model")) {
- printAssertions("theory::assertions-model");
+ if( ! d_inConflict && ! needCheck() ){
+ if(d_logicInfo.isQuantified()) {
+ // quantifiers engine must pass effort last call check
+ d_quantEngine->check(Theory::EFFORT_LAST_CALL);
+ // if returning incomplete or SAT, we have ensured that the model in the quantifiers engine has been built
+ } else if(options::produceModels()) {
+ // must build model at this point
+ d_curr_model_builder->buildModel(getModel(), true);
+ }
+ Trace("theory::assertions-model") << endl;
+ if (Trace.isOn("theory::assertions-model")) {
+ printAssertions("theory::assertions-model");
+ }
}
}
@@ -497,7 +610,10 @@ void TheoryEngine::combineTheories() {
// We need to split on it
Debug("combineTheories") << "TheoryEngine::combineTheories(): requesting a split " << endl;
- lemma(equality.orNode(equality.notNode()), RULE_INVALID, false, false, false, carePair.theory, carePair.theory);
+
+ LemmaProofRecipe* proofRecipe = NULL;
+ lemma(equality.orNode(equality.notNode()), RULE_INVALID, false, false, false, carePair.theory, proofRecipe);
+
// This code is supposed to force preference to follow what the theory models already have
// but it doesn't seem to make a big difference - need to explore more -Clark
// if (true) {
@@ -963,7 +1079,7 @@ bool TheoryEngine::markPropagation(TNode assertion, TNode originalAssertion, the
void TheoryEngine::assertToTheory(TNode assertion, TNode originalAssertion, theory::TheoryId toTheoryId, theory::TheoryId fromTheoryId) {
- Trace("theory::assertToTheory") << "TheoryEngine::assertToTheory(" << assertion << ", " << toTheoryId << ", " << fromTheoryId << ")" << endl;
+ Trace("theory::assertToTheory") << "TheoryEngine::assertToTheory(" << assertion << ", " << originalAssertion << "," << toTheoryId << ", " << fromTheoryId << ")" << endl;
Assert(toTheoryId != fromTheoryId);
if(toTheoryId != THEORY_SAT_SOLVER &&
@@ -1176,6 +1292,23 @@ bool TheoryEngine::propagate(TNode literal, theory::TheoryId theory) {
assertToTheory(literal, literal, /* to */ THEORY_BUILTIN, /* from */ theory);
}
} else {
+ // We could be propagating a unit-clause lemma. In this case, we need to provide a
+ // recipe.
+ // TODO: Consider putting this someplace else? This is the only refence to the proof
+ // manager in this class.
+
+ PROOF({
+ LemmaProofRecipe proofRecipe;
+ proofRecipe.addBaseAssertion(literal);
+
+ Node emptyNode;
+ LemmaProofRecipe::ProofStep proofStep(theory, emptyNode);
+ proofStep.addAssertion(literal);
+ proofRecipe.addStep(proofStep);
+
+ ProofManager::getCnfProof()->setProofRecipe(&proofRecipe);
+ });
+
// Just send off to the SAT solver
Assert(d_propEngine->isSatLiteral(literal));
assertToTheory(literal, literal, /* to */ THEORY_SAT_SOLVER, /* from */ theory);
@@ -1270,7 +1403,7 @@ static Node mkExplanation(const std::vector<NodeTheoryPair>& explanation) {
return conjunction;
}
-NodeTheoryPair TheoryEngine::getExplanationAndExplainer(TNode node) {
+Node TheoryEngine::getExplanationAndRecipe(TNode node, LemmaProofRecipe* proofRecipe) {
Debug("theory::explain") << "TheoryEngine::getExplanation(" << node << "): current propagation index = " << d_propagationMapTimestamp << endl;
bool polarity = node.getKind() != kind::NOT;
@@ -1278,32 +1411,90 @@ NodeTheoryPair TheoryEngine::getExplanationAndExplainer(TNode node) {
// If we're not in shared mode, explanations are simple
if (!d_logicInfo.isSharingEnabled()) {
+ Debug("theory::explain") << "TheoryEngine::getExplanation: sharing is NOT enabled. "
+ << " Responsible theory is: "
+ << theoryOf(atom)->getId() << std::endl;
+
Node explanation = theoryOf(atom)->explain(node);
Debug("theory::explain") << "TheoryEngine::getExplanation(" << node << ") => " << explanation << endl;
- return NodeTheoryPair(explanation, theoryOf(atom)->getId());
+ PROOF({
+ if(proofRecipe) {
+ Node emptyNode;
+ LemmaProofRecipe::ProofStep proofStep(theoryOf(atom)->getId(), emptyNode);
+ proofStep.addAssertion(node);
+ proofRecipe->addBaseAssertion(node);
+
+ if (explanation.getKind() == kind::AND) {
+ // If the explanation is a conjunction, the recipe for the corresponding lemma is
+ // the negation of its conjuncts.
+ Node flat = flattenAnd(explanation);
+ for (unsigned i = 0; i < flat.getNumChildren(); ++i) {
+ if (flat[i].isConst() && flat[i].getConst<bool>()) {
+ ++ i;
+ continue;
+ }
+ if (flat[i].getKind() == kind::NOT &&
+ flat[i][0].isConst() && !flat[i][0].getConst<bool>()) {
+ ++ i;
+ continue;
+ }
+ Debug("theory::explain") << "TheoryEngine::getExplanationAndRecipe: adding recipe assertion: "
+ << flat[i].negate() << std::endl;
+ proofStep.addAssertion(flat[i].negate());
+ proofRecipe->addBaseAssertion(flat[i].negate());
+ }
+ } else {
+ // The recipe for proving it is by negating it. "True" is not an acceptable reason.
+ if (!((explanation.isConst() && explanation.getConst<bool>()) ||
+ (explanation.getKind() == kind::NOT &&
+ explanation[0].isConst() && !explanation[0].getConst<bool>()))) {
+ proofStep.addAssertion(explanation.negate());
+ proofRecipe->addBaseAssertion(explanation.negate());
+ }
+ }
+
+ proofRecipe->addStep(proofStep);
+ }
+ });
+
+ return explanation;
}
+ Debug("theory::explain") << "TheoryEngine::getExplanation: sharing IS enabled" << std::endl;
+
// Initial thing to explain
NodeTheoryPair toExplain(node, THEORY_SAT_SOLVER, d_propagationMapTimestamp);
Assert(d_propagationMap.find(toExplain) != d_propagationMap.end());
NodeTheoryPair nodeExplainerPair = d_propagationMap[toExplain];
+ Debug("theory::explain") << "TheoryEngine::getExplanation: explainer for node "
+ << nodeExplainerPair.node
+ << " is theory: " << nodeExplainerPair.theory << std::endl;
TheoryId explainer = nodeExplainerPair.theory;
// Create the workplace for explanations
std::vector<NodeTheoryPair> explanationVector;
explanationVector.push_back(d_propagationMap[toExplain]);
// Process the explanation
- getExplanation(explanationVector);
+ if (proofRecipe) {
+ Node emptyNode;
+ LemmaProofRecipe::ProofStep proofStep(explainer, emptyNode);
+ proofStep.addAssertion(node);
+ proofRecipe->addStep(proofStep);
+ proofRecipe->addBaseAssertion(node);
+ }
+
+ getExplanation(explanationVector, proofRecipe);
Node explanation = mkExplanation(explanationVector);
Debug("theory::explain") << "TheoryEngine::getExplanation(" << node << ") => " << explanation << endl;
- return NodeTheoryPair(explanation, explainer);
+ return explanation;
}
Node TheoryEngine::getExplanation(TNode node) {
- return getExplanationAndExplainer(node).node;
+ LemmaProofRecipe *dontCareRecipe = NULL;
+ return getExplanationAndRecipe(node, dontCareRecipe);
}
struct AtomsCollect {
@@ -1406,7 +1597,7 @@ theory::LemmaStatus TheoryEngine::lemma(TNode node,
bool removable,
bool preprocess,
theory::TheoryId atomsTo,
- theory::TheoryId ownerTheory) {
+ LemmaProofRecipe* proofRecipe) {
// For resource-limiting (also does a time check).
// spendResource();
@@ -1456,10 +1647,10 @@ theory::LemmaStatus TheoryEngine::lemma(TNode node,
}
// assert to prop engine
- d_propEngine->assertLemma(additionalLemmas[0], negated, removable, rule, ownerTheory, node);
+ d_propEngine->assertLemma(additionalLemmas[0], negated, removable, rule, proofRecipe, node);
for (unsigned i = 1; i < additionalLemmas.size(); ++ i) {
additionalLemmas[i] = theory::Rewriter::rewrite(additionalLemmas[i]);
- d_propEngine->assertLemma(additionalLemmas[i], false, removable, rule, ownerTheory, node);
+ d_propEngine->assertLemma(additionalLemmas[i], false, removable, rule, proofRecipe, node);
}
// WARNING: Below this point don't assume additionalLemmas[0] to be not negated.
@@ -1493,22 +1684,69 @@ void TheoryEngine::conflict(TNode conflict, TheoryId theoryId) {
<< CheckSatCommand(conflict.toExpr());
}
+ LemmaProofRecipe* proofRecipe = NULL;
+ PROOF({
+ proofRecipe = new LemmaProofRecipe;
+ Node emptyNode;
+ LemmaProofRecipe::ProofStep proofStep(theoryId, emptyNode);
+
+ if (conflict.getKind() == kind::AND) {
+ for (unsigned i = 0; i < conflict.getNumChildren(); ++i) {
+ proofStep.addAssertion(conflict[i].negate());
+ }
+ } else {
+ proofStep.addAssertion(conflict.negate());
+ }
+
+ proofRecipe->addStep(proofStep);
+ });
+
// In the multiple-theories case, we need to reconstruct the conflict
if (d_logicInfo.isSharingEnabled()) {
// Create the workplace for explanations
std::vector<NodeTheoryPair> explanationVector;
explanationVector.push_back(NodeTheoryPair(conflict, theoryId, d_propagationMapTimestamp));
+
// Process the explanation
- getExplanation(explanationVector);
+ getExplanation(explanationVector, proofRecipe);
Node fullConflict = mkExplanation(explanationVector);
Debug("theory::conflict") << "TheoryEngine::conflict(" << conflict << ", " << theoryId << "): full = " << fullConflict << endl;
Assert(properConflict(fullConflict));
- lemma(fullConflict, RULE_CONFLICT, true, true, false, THEORY_LAST, theoryId);
+ lemma(fullConflict, RULE_CONFLICT, true, true, false, THEORY_LAST, proofRecipe);
+
} else {
// When only one theory, the conflict should need no processing
Assert(properConflict(conflict));
- lemma(conflict, RULE_CONFLICT, true, true, false, THEORY_LAST, theoryId);
+ PROOF({
+ if (conflict.getKind() == kind::AND) {
+ // If the conflict is a conjunction, the corresponding lemma is derived by negating
+ // its conjuncts.
+ for (unsigned i = 0; i < conflict.getNumChildren(); ++i) {
+ if (conflict[i].isConst() && conflict[i].getConst<bool>()) {
+ ++ i;
+ continue;
+ }
+ if (conflict[i].getKind() == kind::NOT &&
+ conflict[i][0].isConst() && !conflict[i][0].getConst<bool>()) {
+ ++ i;
+ continue;
+ }
+ proofRecipe->getStep(0)->addAssertion(conflict[i].negate());
+ proofRecipe->addBaseAssertion(conflict[i].negate());
+ }
+ } else {
+ proofRecipe->getStep(0)->addAssertion(conflict.negate());
+ proofRecipe->addBaseAssertion(conflict.negate());
+ }
+ });
+
+ lemma(conflict, RULE_CONFLICT, true, true, false, THEORY_LAST, proofRecipe);
}
+
+ PROOF({
+ delete proofRecipe;
+ proofRecipe = NULL;
+ });
}
void TheoryEngine::staticInitializeBVOptions(const std::vector<Node>& assertions) {
@@ -1558,15 +1796,9 @@ void TheoryEngine::mkAckermanizationAsssertions(std::vector<Node>& assertions) {
Node TheoryEngine::ppSimpITE(TNode assertion)
{
- if(options::incrementalSolving()){
- // disabling the d_iteUtilities->simpITE(assertion) pass for incremental solving.
- // This is paranoia. We do not actually know of a bug coming from this.
- // TODO re-enable
+ if (!d_iteRemover.containsTermITE(assertion)) {
return assertion;
- } else if(!d_iteRemover.containsTermITE(assertion)){
- return assertion;
- }else{
-
+ } else {
Node result = d_iteUtilities->simpITE(assertion);
Node res_rewritten = Rewriter::rewrite(result);
@@ -1576,10 +1808,9 @@ Node TheoryEngine::ppSimpITE(TNode assertion)
Chat() << "ending simplifyWithCare()"
<< " post simplifyWithCare()" << postSimpWithCare.getId() << endl;
result = Rewriter::rewrite(postSimpWithCare);
- }else{
+ } else {
result = res_rewritten;
}
-
return result;
}
}
@@ -1667,19 +1898,21 @@ bool TheoryEngine::donePPSimpITE(std::vector<Node>& assertions){
return result;
}
-void TheoryEngine::getExplanation(std::vector<NodeTheoryPair>& explanationVector)
-{
+void TheoryEngine::getExplanation(std::vector<NodeTheoryPair>& explanationVector, LemmaProofRecipe* proofRecipe) {
Assert(explanationVector.size() > 0);
unsigned i = 0; // Index of the current literal we are processing
unsigned j = 0; // Index of the last literal we are keeping
- while (i < explanationVector.size()) {
+ std::set<Node> inputAssertions;
+ PROOF(inputAssertions = proofRecipe->getStep(0)->getAssertions(););
+ while (i < explanationVector.size()) {
// Get the current literal to explain
NodeTheoryPair toExplain = explanationVector[i];
- Debug("theory::explain") << "TheoryEngine::explain(): processing [" << toExplain.timestamp << "] " << toExplain.node << " sent from " << toExplain.theory << endl;
+ Debug("theory::explain") << "[i=" << i << "] TheoryEngine::explain(): processing [" << toExplain.timestamp << "] " << toExplain.node << " sent from " << toExplain.theory << endl;
+
// If a true constant or a negation of a false constant we can ignore it
if (toExplain.node.isConst() && toExplain.node.getConst<bool>()) {
@@ -1693,6 +1926,7 @@ void TheoryEngine::getExplanation(std::vector<NodeTheoryPair>& explanationVector
// If from the SAT solver, keep it
if (toExplain.theory == THEORY_SAT_SOLVER) {
+ Debug("theory::explain") << "\tLiteral came from THEORY_SAT_SOLVER. Kepping it." << endl;
explanationVector[j++] = explanationVector[i++];
continue;
}
@@ -1711,10 +1945,26 @@ void TheoryEngine::getExplanation(std::vector<NodeTheoryPair>& explanationVector
// See if it was sent to the theory by another theory
PropagationMap::const_iterator find = d_propagationMap.find(toExplain);
if (find != d_propagationMap.end()) {
+ Debug("theory::explain") << "\tTerm was propagated by another theory (theory = "
+ << theoryOf((*find).second.theory)->getId() << ")" << std::endl;
// There is some propagation, check if its a timely one
if ((*find).second.timestamp < toExplain.timestamp) {
+ Debug("theory::explain") << "\tRelevant timetsamp, pushing "
+ << (*find).second.node << "to index = " << explanationVector.size() << std::endl;
explanationVector.push_back((*find).second);
- ++ i;
+ ++i;
+
+ PROOF({
+ if (toExplain.node != (*find).second.node) {
+ Debug("pf::explain") << "TheoryEngine::getExplanation: Rewrite alert! toAssert = " << toExplain.node
+ << ", toExplain = " << (*find).second.node << std::endl;
+
+ if (proofRecipe) {
+ proofRecipe->addRewriteRule(toExplain.node, (*find).second.node);
+ }
+ }
+ })
+
continue;
}
}
@@ -1723,21 +1973,61 @@ void TheoryEngine::getExplanation(std::vector<NodeTheoryPair>& explanationVector
Node explanation;
if (toExplain.theory == THEORY_BUILTIN) {
explanation = d_sharedTerms.explain(toExplain.node);
+ Debug("theory::explain") << "\tTerm was propagated by THEORY_BUILTIN. Explanation: " << explanation << std::endl;
} else {
explanation = theoryOf(toExplain.theory)->explain(toExplain.node);
+ Debug("theory::explain") << "\tTerm was propagated by owner theory: "
+ << theoryOf(toExplain.theory)->getId()
+ << ". Explanation: " << explanation << std::endl;
}
+
Debug("theory::explain") << "TheoryEngine::explain(): got explanation " << explanation << " got from " << toExplain.theory << endl;
Assert(explanation != toExplain.node, "wasn't sent to you, so why are you explaining it trivially");
// Mark the explanation
NodeTheoryPair newExplain(explanation, toExplain.theory, toExplain.timestamp);
explanationVector.push_back(newExplain);
+
++ i;
+
+ PROOF({
+ if (proofRecipe) {
+ // If we're expanding the target node of the explanation (this is the first expansion...),
+ // we don't want to add it as a separate proof step. It is already part of the assertions.
+ if (inputAssertions.find(toExplain.node) == inputAssertions.end()) {
+ LemmaProofRecipe::ProofStep proofStep(toExplain.theory, toExplain.node);
+ if (explanation.getKind() == kind::AND) {
+ Node flat = flattenAnd(explanation);
+ for (unsigned k = 0; k < flat.getNumChildren(); ++ k) {
+ // If a true constant or a negation of a false constant we can ignore it
+ if (! ((flat[k].isConst() && flat[k].getConst<bool>()) ||
+ (flat[k].getKind() == kind::NOT && flat[k][0].isConst() && !flat[k][0].getConst<bool>()))) {
+ proofStep.addAssertion(flat[k].negate());
+ }
+ }
+ } else {
+ if (! ((explanation.isConst() && explanation.getConst<bool>()) ||
+ (explanation.getKind() == kind::NOT && explanation[0].isConst() && !explanation[0].getConst<bool>()))) {
+ proofStep.addAssertion(explanation.negate());
+ }
+ }
+ proofRecipe->addStep(proofStep);
+ }
+ }
+ });
}
// Keep only the relevant literals
explanationVector.resize(j);
-}
+ PROOF({
+ if (proofRecipe) {
+ // The remaining literals are the base of the proof
+ for (unsigned k = 0; k < explanationVector.size(); ++k) {
+ proofRecipe->addBaseAssertion(explanationVector[k].node.negate());
+ }
+ }
+ });
+}
void TheoryEngine::ppUnconstrainedSimp(vector<Node>& assertions)
{
diff --git a/src/theory/theory_engine.h b/src/theory/theory_engine.h
index db94edd7c..53c4aac77 100644
--- a/src/theory/theory_engine.h
+++ b/src/theory/theory_engine.h
@@ -50,6 +50,7 @@
namespace CVC4 {
class ResourceManager;
+class LemmaProofRecipe;
/**
* A pair of a theory and a node. This is used to mark the flow of
@@ -270,46 +271,18 @@ class TheoryEngine {
}
}
- void conflict(TNode conflictNode, Proof* pf = NULL) throw(AssertionException, UnsafeInterruptException) {
- Trace("theory::conflict") << "EngineOutputChannel<" << d_theory << ">::conflict(" << conflictNode << ")" << std::endl;
- Assert(pf == NULL); // theory shouldn't be producing proofs yet
- ++ d_statistics.conflicts;
- d_engine->d_outputChannelUsed = true;
- d_engine->conflict(conflictNode, d_theory);
- }
+ void conflict(TNode conflictNode, Proof* pf = NULL) throw(AssertionException, UnsafeInterruptException);
- bool propagate(TNode literal) throw(AssertionException, UnsafeInterruptException) {
- Trace("theory::propagate") << "EngineOutputChannel<" << d_theory << ">::propagate(" << literal << ")" << std::endl;
- ++ d_statistics.propagations;
- d_engine->d_outputChannelUsed = true;
- return d_engine->propagate(literal, d_theory);
- }
+ bool propagate(TNode literal) throw(AssertionException, UnsafeInterruptException);
theory::LemmaStatus lemma(TNode lemma,
ProofRule rule,
bool removable = false,
bool preprocess = false,
bool sendAtoms = false)
- throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException) {
- Trace("theory::lemma") << "EngineOutputChannel<" << d_theory << ">::lemma(" << lemma << ")" << std::endl;
- ++ d_statistics.lemmas;
- d_engine->d_outputChannelUsed = true;
- return d_engine->lemma(lemma, rule, false, removable, preprocess, sendAtoms ? d_theory : theory::THEORY_LAST, d_theory);
- }
+ throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException);
- /*theory::LemmaStatus preservedLemma(TNode lemma, bool removable = false, bool preprocess = false) throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException, LogicException) {
- Trace("theory::lemma") << "EngineOutputChannel<" << d_theory << ">::preservedLemma(" << lemma << ")" << std::endl;
- ++ d_statistics.lemmas;
- d_engine->d_outputChannelUsed = true;
- return d_engine->lemma(lemma, false, removable, preprocess, d_theory);
- }*/
-
- theory::LemmaStatus splitLemma(TNode lemma, bool removable = false) throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException) {
- Trace("theory::lemma") << "EngineOutputChannel<" << d_theory << ">::splitLemma(" << lemma << ")" << std::endl;
- ++ d_statistics.lemmas;
- d_engine->d_outputChannelUsed = true;
- return d_engine->lemma(lemma, RULE_SPLIT, false, removable, false, d_theory, d_theory);
- }
+ theory::LemmaStatus splitLemma(TNode lemma, bool removable = false) throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException);
void demandRestart() throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException) {
NodeManager* curr = NodeManager::currentNM();
@@ -456,7 +429,7 @@ class TheoryEngine {
bool removable,
bool preprocess,
theory::TheoryId atomsTo,
- theory::TheoryId ownerTheory);
+ LemmaProofRecipe* proofRecipe);
/** Enusre that the given atoms are send to the given theory */
void ensureLemmaAtoms(const std::vector<TNode>& atoms, theory::TheoryId theory);
@@ -606,9 +579,10 @@ private:
* asking relevant theories to explain the propagations. Initially
* the explanation vector should contain only the element (node, theory)
* where the node is the one to be explained, and the theory is the
- * theory that sent the literal.
+ * theory that sent the literal. The lemmaProofRecipe will contain a list
+ * of the explanation steps required to produce the original node.
*/
- void getExplanation(std::vector<NodeTheoryPair>& explanationVector);
+ void getExplanation(std::vector<NodeTheoryPair>& explanationVector, LemmaProofRecipe* lemmaProofRecipe);
public:
@@ -730,7 +704,7 @@ public:
* Returns an explanation of the node propagated to the SAT solver and the theory
* that propagated it.
*/
- NodeTheoryPair getExplanationAndExplainer(TNode node);
+ Node getExplanationAndRecipe(TNode node, LemmaProofRecipe* proofRecipe);
/**
* collect model info
diff --git a/src/theory/theory_model.cpp b/src/theory/theory_model.cpp
index fa7e497e2..f43a2aa7f 100644
--- a/src/theory/theory_model.cpp
+++ b/src/theory/theory_model.cpp
@@ -561,7 +561,7 @@ void TheoryEngineModelBuilder::buildModel(Model* m, bool fullModel)
TheoryModel* tm = (TheoryModel*)m;
// buildModel with fullModel = true should only be called once in any context
- Assert(!tm->d_modelBuilt);
+ Assert(!tm->isBuilt());
tm->d_modelBuilt = fullModel;
// Reset model
@@ -832,6 +832,7 @@ void TheoryEngineModelBuilder::buildModel(Model* m, bool fullModel)
Assert(!t.isBoolean() || (*i2).getKind() == kind::APPLY_UF);
Node n;
if (t.getCardinality().isInfinite()) {
+ // if (!t.isInterpretedFinite()) {
bool success;
do{
Trace("model-builder-debug") << "Enumerate term of type " << t << std::endl;
diff --git a/src/theory/theory_model.h b/src/theory/theory_model.h
index 6e4f77336..833b124eb 100644
--- a/src/theory/theory_model.h
+++ b/src/theory/theory_model.h
@@ -36,6 +36,7 @@ class TheoryModel : public Model
protected:
/** substitution map for this model */
SubstitutionMap d_substitutions;
+ context::CDO<bool> d_modelBuilt;
public:
TheoryModel(context::Context* c, std::string name, bool enableFuncModels);
virtual ~TheoryModel() throw();
@@ -51,7 +52,6 @@ public:
/** true/false nodes */
Node d_true;
Node d_false;
- context::CDO<bool> d_modelBuilt;
mutable std::hash_map<Node, Node, NodeHashFunction> d_modelCache;
protected:
@@ -62,6 +62,8 @@ protected:
*/
Node getModelValue(TNode n, bool hasBoundVars = false, bool useDontCares = false) const;
public:
+ /** is built */
+ bool isBuilt() { return d_modelBuilt.get(); }
/**
* Get value function. This should be called only after a ModelBuilder has called buildModel(...)
* on this model.
diff --git a/src/theory/type_enumerator.h b/src/theory/type_enumerator.h
index d1318aaa8..bcd7e695f 100644
--- a/src/theory/type_enumerator.h
+++ b/src/theory/type_enumerator.h
@@ -115,7 +115,7 @@ public:
// On Mac clang, there appears to be a code generation bug in an exception
// block here. For now, there doesn't appear a good workaround; just disable
// assertions on that setup.
-#if defined(CVC4_ASSERTIONS) && !(defined(__APPLE__) && defined(__clang__))
+#if defined(CVC4_ASSERTIONS) && !(defined(__clang__))
if(d_te->isFinished()) {
try {
**d_te;
diff --git a/src/theory/uf/equality_engine.cpp b/src/theory/uf/equality_engine.cpp
index 9b429765e..25b12f75f 100644
--- a/src/theory/uf/equality_engine.cpp
+++ b/src/theory/uf/equality_engine.cpp
@@ -964,12 +964,9 @@ void EqualityEngine::explainEquality(TNode t1, TNode t2, bool polarity, std::vec
std::vector<EqProof *> orderedChildren;
bool nullCongruenceFound = false;
for (unsigned i = 0; i < eqpc->d_children.size(); ++i) {
- if (eqpc->d_children[i]->d_id==eq::MERGED_THROUGH_CONGRUENCE && eqpc->d_children[i]->d_node.isNull()) {
-
- // For now, assume there can only be one null congruence child
- Assert(!nullCongruenceFound);
+ if (eqpc->d_children[i]->d_id==eq::MERGED_THROUGH_CONGRUENCE &&
+ eqpc->d_children[i]->d_node.isNull()) {
nullCongruenceFound = true;
-
Debug("pf::ee") << "Have congruence with empty d_node. Splitting..." << std::endl;
orderedChildren.insert(orderedChildren.begin(), eqpc->d_children[i]->d_children[0]);
orderedChildren.push_back(eqpc->d_children[i]->d_children[1]);
@@ -1192,6 +1189,9 @@ void EqualityEngine::getExplanation(EqualityNodeId t1Id, EqualityNodeId t2Id, st
getExplanation(childId, getEqualityNode(childId).getFind(), equalities, eqpcc);
if( eqpc ) {
eqpc->d_children.push_back( eqpcc );
+
+ Debug("pf::ee") << "MERGED_THROUGH_CONSTANTS. Dumping the child proof" << std::endl;
+ eqpc->debug_print("pf::ee", 1);
}
}
@@ -1605,6 +1605,7 @@ void EqualityEngine::propagate() {
}
void EqualityEngine::debugPrintGraph() const {
+ Debug("equality::graph") << std::endl << "Dumping graph" << std::endl;
for (EqualityNodeId nodeId = 0; nodeId < d_nodes.size(); ++ nodeId) {
Debug("equality::graph") << d_nodes[nodeId] << " " << nodeId << "(" << getEqualityNode(nodeId).getFind() << "):";
@@ -1618,6 +1619,7 @@ void EqualityEngine::debugPrintGraph() const {
Debug("equality::graph") << std::endl;
}
+ Debug("equality::graph") << std::endl;
}
bool EqualityEngine::areEqual(TNode t1, TNode t2) const {
@@ -2209,9 +2211,15 @@ bool EqClassIterator::isFinished() const {
return d_current == null_id;
}
-void EqProof::debug_print( const char * c, unsigned tb ) const{
- for( unsigned i=0; i<tb; i++ ) { Debug( c ) << " "; }
- Debug( c ) << d_id << "(";
+void EqProof::debug_print(const char* c, unsigned tb, PrettyPrinter* prettyPrinter) const {
+ for(unsigned i=0; i<tb; i++) { Debug( c ) << " "; }
+
+ if (prettyPrinter)
+ Debug( c ) << prettyPrinter->printTag(d_id);
+ else
+ Debug( c ) << d_id;
+
+ Debug( c ) << "(";
if( !d_children.empty() || !d_node.isNull() ){
if( !d_node.isNull() ){
Debug( c ) << std::endl;
@@ -2221,7 +2229,7 @@ void EqProof::debug_print( const char * c, unsigned tb ) const{
for( unsigned i=0; i<d_children.size(); i++ ){
if( i>0 || !d_node.isNull() ) Debug( c ) << ",";
Debug( c ) << std::endl;
- d_children[i]->debug_print( c, tb+1 );
+ d_children[i]->debug_print( c, tb+1, prettyPrinter );
}
}
Debug( c ) << ")" << std::endl;
diff --git a/src/theory/uf/equality_engine.h b/src/theory/uf/equality_engine.h
index f30f1e8a0..843e7ce7f 100644
--- a/src/theory/uf/equality_engine.h
+++ b/src/theory/uf/equality_engine.h
@@ -902,11 +902,17 @@ public:
class EqProof
{
public:
+ class PrettyPrinter {
+ public:
+ virtual ~PrettyPrinter() {}
+ virtual std::string printTag(unsigned tag) = 0;
+ };
+
EqProof() : d_id(MERGED_THROUGH_REFLEXIVITY){}
unsigned d_id;
Node d_node;
std::vector< EqProof * > d_children;
- void debug_print( const char * c, unsigned tb = 0 ) const;
+ void debug_print(const char * c, unsigned tb = 0, PrettyPrinter* prettyPrinter = NULL) const;
};/* class EqProof */
} // Namespace eq
diff --git a/src/theory/uf/theory_uf.cpp b/src/theory/uf/theory_uf.cpp
index 0c7bed773..ae935798e 100644
--- a/src/theory/uf/theory_uf.cpp
+++ b/src/theory/uf/theory_uf.cpp
@@ -26,6 +26,8 @@
#include "theory/theory_model.h"
#include "theory/type_enumerator.h"
#include "theory/uf/theory_uf_strong_solver.h"
+#include "theory/quantifiers/term_database.h"
+#include "options/theory_options.h"
using namespace std;
@@ -431,100 +433,107 @@ void TheoryUF::addSharedTerm(TNode t) {
d_equalityEngine.addTriggerTerm(t, THEORY_UF);
}
-void TheoryUF::computeCareGraph() {
-
- if (d_sharedTerms.size() > 0) {
-
- vector< pair<TNode, TNode> > currentPairs;
-
- // Go through the function terms and see if there are any to split on
- unsigned functionTerms = d_functionsTerms.size();
- for (unsigned i = 0; i < functionTerms; ++ i) {
-
- TNode f1 = d_functionsTerms[i];
- Node op = f1.getOperator();
-
- for (unsigned j = i + 1; j < functionTerms; ++ j) {
-
- TNode f2 = d_functionsTerms[j];
-
- // If the operators are not the same, we can skip this pair
- if (f2.getOperator() != op) {
- continue;
- }
-
+//TODO: move quantifiers::TermArgTrie to src/theory/
+void TheoryUF::addCarePairs( quantifiers::TermArgTrie * t1, quantifiers::TermArgTrie * t2, unsigned arity, unsigned depth ){
+ if( depth==arity ){
+ if( t2!=NULL ){
+ Node f1 = t1->getNodeData();
+ Node f2 = t2->getNodeData();
+ if( !d_equalityEngine.areEqual( f1, f2 ) ){
Debug("uf::sharing") << "TheoryUf::computeCareGraph(): checking function " << f1 << " and " << f2 << std::endl;
-
- // If the terms are already known to be equal, we are also in good shape
- if (d_equalityEngine.areEqual(f1, f2)) {
- Debug("uf::sharing") << "TheoryUf::computeCareGraph(): equal, skipping" << std::endl;
- continue;
- }
-
- // We have two functions f(x1, ..., xn) and f(y1, ..., yn) no known to be equal
- // We split on the argument pairs that are are not known, unless there is some
- // argument pair that is already dis-equal.
- bool somePairIsDisequal = false;
- currentPairs.clear();
+ vector< pair<TNode, TNode> > currentPairs;
for (unsigned k = 0; k < f1.getNumChildren(); ++ k) {
-
TNode x = f1[k];
TNode y = f2[k];
-
- Debug("uf::sharing") << "TheoryUf::computeCareGraph(): checking arguments " << x << " and " << y << std::endl;
-
- if (d_equalityEngine.areDisequal(x, y, false)) {
- // Mark that there is a dis-equal pair and break
- somePairIsDisequal = true;
- Debug("uf::sharing") << "TheoryUf::computeCareGraph(): disequal, disregarding all" << std::endl;
- break;
+ Assert( d_equalityEngine.hasTerm(x) );
+ Assert( d_equalityEngine.hasTerm(y) );
+ Assert( !d_equalityEngine.areDisequal( x, y, false ) );
+ if( !d_equalityEngine.areEqual( x, y ) ){
+ if( d_equalityEngine.isTriggerTerm(x, THEORY_UF) && d_equalityEngine.isTriggerTerm(y, THEORY_UF) ){
+ TNode x_shared = d_equalityEngine.getTriggerTermRepresentative(x, THEORY_UF);
+ TNode y_shared = d_equalityEngine.getTriggerTermRepresentative(y, THEORY_UF);
+ EqualityStatus eqStatus = d_valuation.getEqualityStatus(x_shared, y_shared);
+ if( eqStatus==EQUALITY_FALSE_AND_PROPAGATED || eqStatus==EQUALITY_FALSE || eqStatus==EQUALITY_FALSE_IN_MODEL ){
+ //an argument is disequal, we are done
+ return;
+ }else{
+ currentPairs.push_back(make_pair(x_shared, y_shared));
+ }
+ }
}
-
- if (d_equalityEngine.areEqual(x, y)) {
- // We don't need this one
- Debug("uf::sharing") << "TheoryUf::computeCareGraph(): equal" << std::endl;
- continue;
- }
-
- if (!d_equalityEngine.isTriggerTerm(x, THEORY_UF) || !d_equalityEngine.isTriggerTerm(y, THEORY_UF)) {
- // Not connected to shared terms, we don't care
- continue;
+ }
+ for (unsigned c = 0; c < currentPairs.size(); ++ c) {
+ Debug("uf::sharing") << "TheoryUf::computeCareGraph(): adding to care-graph" << std::endl;
+ addCarePair(currentPairs[c].first, currentPairs[c].second);
+ }
+ }
+ }
+ }else{
+ if( t2==NULL ){
+ if( depth<(arity-1) ){
+ //add care pairs internal to each child
+ for( std::map< TNode, quantifiers::TermArgTrie >::iterator it = t1->d_data.begin(); it != t1->d_data.end(); ++it ){
+ addCarePairs( &it->second, NULL, arity, depth+1 );
+ }
+ }
+ //add care pairs based on each pair of non-disequal arguments
+ for( std::map< TNode, quantifiers::TermArgTrie >::iterator it = t1->d_data.begin(); it != t1->d_data.end(); ++it ){
+ std::map< TNode, quantifiers::TermArgTrie >::iterator it2 = it;
+ ++it2;
+ for( ; it2 != t1->d_data.end(); ++it2 ){
+ if( !d_equalityEngine.areDisequal(it->first, it2->first, false) ){
+ addCarePairs( &it->second, &it2->second, arity, depth+1 );
}
-
- // Get representative trigger terms
- TNode x_shared = d_equalityEngine.getTriggerTermRepresentative(x, THEORY_UF);
- TNode y_shared = d_equalityEngine.getTriggerTermRepresentative(y, THEORY_UF);
-
- EqualityStatus eqStatusDomain = d_valuation.getEqualityStatus(x_shared, y_shared);
- switch (eqStatusDomain) {
- case EQUALITY_FALSE_AND_PROPAGATED:
- case EQUALITY_FALSE:
- case EQUALITY_FALSE_IN_MODEL:
- somePairIsDisequal = true;
- continue;
- break;
- default:
- break;
- // nothing
+ }
+ }
+ }else{
+ //add care pairs based on product of indices, non-disequal arguments
+ for( std::map< TNode, quantifiers::TermArgTrie >::iterator it = t1->d_data.begin(); it != t1->d_data.end(); ++it ){
+ for( std::map< TNode, quantifiers::TermArgTrie >::iterator it2 = t2->d_data.begin(); it2 != t2->d_data.end(); ++it2 ){
+ if( !d_equalityEngine.areDisequal(it->first, it2->first, false) ){
+ addCarePairs( &it->second, &it2->second, arity, depth+1 );
}
-
- // Otherwise, we need to figure it out
- Debug("uf::sharing") << "TheoryUf::computeCareGraph(): adding to care-graph" << std::endl;
- currentPairs.push_back(make_pair(x_shared, y_shared));
}
+ }
+ }
+ }
+}
- if (!somePairIsDisequal) {
- for (unsigned i = 0; i < currentPairs.size(); ++ i) {
- addCarePair(currentPairs[i].first, currentPairs[i].second);
- }
+void TheoryUF::computeCareGraph() {
+
+ if (d_sharedTerms.size() > 0) {
+ //use term indexing
+ Debug("uf::sharing") << "TheoryUf::computeCareGraph(): Build term indices..." << std::endl;
+ std::map< Node, quantifiers::TermArgTrie > index;
+ std::map< Node, unsigned > arity;
+ unsigned functionTerms = d_functionsTerms.size();
+ for (unsigned i = 0; i < functionTerms; ++ i) {
+ TNode f1 = d_functionsTerms[i];
+ Node op = f1.getOperator();
+ std::vector< TNode > reps;
+ bool has_trigger_arg = false;
+ for( unsigned j=0; j<f1.getNumChildren(); j++ ){
+ reps.push_back( d_equalityEngine.getRepresentative( f1[j] ) );
+ if( d_equalityEngine.isTriggerTerm( f1[j], THEORY_UF ) ){
+ has_trigger_arg = true;
}
}
+ if( has_trigger_arg ){
+ index[op].addTerm( f1, reps );
+ arity[op] = reps.size();
+ }
+ }
+ //for each index
+ for( std::map< Node, quantifiers::TermArgTrie >::iterator itii = index.begin(); itii != index.end(); ++itii ){
+ Debug("uf::sharing") << "TheoryUf::computeCareGraph(): Process index " << itii->first << "..." << std::endl;
+ addCarePairs( &itii->second, NULL, arity[ itii->first ], 0 );
}
}
}/* TheoryUF::computeCareGraph() */
void TheoryUF::conflict(TNode a, TNode b) {
eq::EqProof* pf = d_proofsEnabled ? new eq::EqProof() : NULL;
+
if (a.getKind() == kind::CONST_BOOLEAN) {
d_conflictNode = explain(a.iffNode(b),pf);
} else {
@@ -542,9 +551,9 @@ void TheoryUF::eqNotifyNewClass(TNode t) {
}
void TheoryUF::eqNotifyPreMerge(TNode t1, TNode t2) {
- if (getLogicInfo().isQuantified()) {
+ //if (getLogicInfo().isQuantified()) {
//getQuantifiersEngine()->getEfficientEMatcher()->merge( t1, t2 );
- }
+ //}
}
void TheoryUF::eqNotifyPostMerge(TNode t1, TNode t2) {
diff --git a/src/theory/uf/theory_uf.h b/src/theory/uf/theory_uf.h
index 42a804c09..3a83decec 100644
--- a/src/theory/uf/theory_uf.h
+++ b/src/theory/uf/theory_uf.h
@@ -32,6 +32,11 @@
namespace CVC4 {
namespace theory {
+
+namespace quantifiers{
+ class TermArgTrie;
+}
+
namespace uf {
class UfTermDb;
@@ -204,6 +209,8 @@ public:
StrongSolverTheoryUF* getStrongSolver() {
return d_thss;
}
+private:
+ void addCarePairs( quantifiers::TermArgTrie * t1, quantifiers::TermArgTrie * t2, unsigned arity, unsigned depth );
};/* class TheoryUF */
}/* CVC4::theory::uf namespace */
diff --git a/src/theory/uf/theory_uf_strong_solver.cpp b/src/theory/uf/theory_uf_strong_solver.cpp
index ed28cc2fc..cda94e1c4 100644
--- a/src/theory/uf/theory_uf_strong_solver.cpp
+++ b/src/theory/uf/theory_uf_strong_solver.cpp
@@ -1670,6 +1670,12 @@ StrongSolverTheoryUF::StrongSolverTheoryUF(context::Context* c,
}
}
+StrongSolverTheoryUF::~StrongSolverTheoryUF() {
+ for( std::map< TypeNode, SortModel* >::iterator it = d_rep_model.begin(); it != d_rep_model.end(); ++it ){
+ delete it->second;
+ }
+}
+
SortInference* StrongSolverTheoryUF::getSortInference() {
return d_th->getQuantifiersEngine()->getTheoryEngine()->getSortInference();
}
diff --git a/src/theory/uf/theory_uf_strong_solver.h b/src/theory/uf/theory_uf_strong_solver.h
index 11f0664f3..4e4dbef83 100644
--- a/src/theory/uf/theory_uf_strong_solver.h
+++ b/src/theory/uf/theory_uf_strong_solver.h
@@ -414,7 +414,7 @@ private:
SubsortSymmetryBreaker* d_sym_break;
public:
StrongSolverTheoryUF(context::Context* c, context::UserContext* u, OutputChannel& out, TheoryUF* th);
- ~StrongSolverTheoryUF() {}
+ ~StrongSolverTheoryUF();
/** get theory */
TheoryUF* getTheory() { return d_th; }
/** disequality propagator */
diff --git a/src/theory/valuation.cpp b/src/theory/valuation.cpp
index 165937c13..7e13668cd 100644
--- a/src/theory/valuation.cpp
+++ b/src/theory/valuation.cpp
@@ -87,6 +87,10 @@ Node Valuation::getModelValue(TNode var) {
return d_engine->getModelValue(var);
}
+TheoryModel* Valuation::getModel() {
+ return d_engine->getModel();
+}
+
Node Valuation::ensureLiteral(TNode n) {
return d_engine->ensureLiteral(n);
}
diff --git a/src/theory/valuation.h b/src/theory/valuation.h
index 4ecdecad0..54af14fdd 100644
--- a/src/theory/valuation.h
+++ b/src/theory/valuation.h
@@ -32,6 +32,7 @@ namespace theory {
class EntailmentCheckParameters;
class EntailmentCheckSideEffects;
+class TheoryModel;
/**
* The status of an equality in the current context.
@@ -106,6 +107,11 @@ public:
Node getModelValue(TNode var);
/**
+ * Returns pointer to model.
+ */
+ TheoryModel* getModel();
+
+ /**
* Ensure that the given node will have a designated SAT literal
* that is definitionally equal to it. The result of this function
* is a Node that can be queried via getSatValue().
diff --git a/src/util/bitvector.h b/src/util/bitvector.h
index a04cbb58f..4a74c1c53 100644
--- a/src/util/bitvector.h
+++ b/src/util/bitvector.h
@@ -338,6 +338,15 @@ public:
return d_value;
}
+ Integer toSignedInt() const {
+ // returns Integer corresponding to two's complement interpretation of bv
+ unsigned size = d_size;
+ Integer sign_bit = d_value.extractBitRange(1,size-1);
+ Integer val = d_value.extractBitRange(size-1, 0);
+ Integer res = Integer(-1) * sign_bit.multiplyByPow2(size - 1) + val;
+ return res;
+ }
+
/**
Returns k is the integer is equal to 2^{k-1} and zero
otherwise
@@ -356,14 +365,6 @@ private:
unsigned d_size;
Integer d_value;
- Integer toSignedInt() const {
- // returns Integer corresponding to two's complement interpretation of bv
- unsigned size = d_size;
- Integer sign_bit = d_value.extractBitRange(1,size-1);
- Integer val = d_value.extractBitRange(size-1, 0);
- Integer res = Integer(-1) * sign_bit.multiplyByPow2(size - 1) + val;
- return res;
- }
};/* class BitVector */
diff --git a/src/util/proof.h b/src/util/proof.h
index fc5f7f901..b4a8a3d29 100644
--- a/src/util/proof.h
+++ b/src/util/proof.h
@@ -21,13 +21,21 @@
#define __CVC4__PROOF_H
#include <iosfwd>
+#include <ext/hash_map>
namespace CVC4 {
+class Expr;
+class ProofLetCount;
+struct ExprHashFunction;
+
+typedef __gnu_cxx::hash_map<Expr, ProofLetCount, ExprHashFunction> ProofLetMap;
+
class CVC4_PUBLIC Proof {
public:
virtual ~Proof() { }
virtual void toStream(std::ostream& out) = 0;
+ virtual void toStream(std::ostream& out, const ProofLetMap& map) = 0;
};/* class Proof */
}/* CVC4 namespace */
diff --git a/test/Makefile.am b/test/Makefile.am
index dcb58b591..931228f41 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -59,6 +59,7 @@ subdirs_to_check = \
regress/regress0/sets \
regress/regress0/parser \
regress/regress0/sygus \
+ regress/regress0/sep \
regress/regress1 \
regress/regress1/arith \
regress/regress2 \
diff --git a/test/regress/regress0/Makefile.am b/test/regress/regress0/Makefile.am
index 7d7690d22..45842065f 100644
--- a/test/regress/regress0/Makefile.am
+++ b/test/regress/regress0/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = . arith precedence uf uflra uflia bv arrays aufbv auflia datatypes quantifiers rewriterules lemmas push-pop preprocess tptp unconstrained decision fmf strings sets parser sygus
+SUBDIRS = . arith precedence uf uflra uflia bv arrays aufbv auflia datatypes quantifiers rewriterules lemmas push-pop preprocess tptp unconstrained decision fmf strings sets parser sygus sep
DIST_SUBDIRS = $(SUBDIRS)
# don't override a BINARY imported from a personal.mk
diff --git a/test/regress/regress0/aufbv/Makefile.am b/test/regress/regress0/aufbv/Makefile.am
index 38b58cedd..38705c22a 100644
--- a/test/regress/regress0/aufbv/Makefile.am
+++ b/test/regress/regress0/aufbv/Makefile.am
@@ -22,7 +22,6 @@ TESTS = \
bug00.smt \
bug338.smt2 \
bug347.smt \
- bug348.smt \
bug451.smt \
bug509.smt \
bug580.smt2 \
diff --git a/test/regress/regress0/fmf/Makefile.am b/test/regress/regress0/fmf/Makefile.am
index 575aa4159..b7daadfd1 100644
--- a/test/regress/regress0/fmf/Makefile.am
+++ b/test/regress/regress0/fmf/Makefile.am
@@ -55,7 +55,9 @@ TESTS = \
datatypes-ufinite-nested.smt2 \
ForElimination-scala-9.smt2 \
agree466.smt2 \
- LeftistHeap.scala-8-ncm.smt2
+ LeftistHeap.scala-8-ncm.smt2 \
+ sc-crash-052316.smt2 \
+ bound-int-alt.smt2
EXTRA_DIST = $(TESTS)
diff --git a/test/regress/regress0/fmf/bound-int-alt.smt2 b/test/regress/regress0/fmf/bound-int-alt.smt2
new file mode 100644
index 000000000..146487925
--- /dev/null
+++ b/test/regress/regress0/fmf/bound-int-alt.smt2
@@ -0,0 +1,18 @@
+; COMMAND-LINE: --fmf-bound-int
+; EXPECT: sat
+(set-logic UFLIA)
+(set-info :status sat)
+(declare-sort U 0)
+(declare-sort V 0)
+(declare-fun P (U Int V Int U Int) Bool)
+
+(assert (forall ((x U) (y Int) (z V) (w Int) (v U) (d Int)) (=> (and (<= 0 d 1) (<= 2 y 6) (<= 40 w (+ 37 y))) (P x y z w v d))))
+
+(declare-fun a () U)
+(declare-fun b () V)
+
+(assert (not (P a 2 b 40 a 0)))
+(assert (not (P a 6 b 39 a 0)))
+(assert (not (P a 6 b 44 a 0)))
+
+(check-sat)
diff --git a/test/regress/regress0/fmf/sc-crash-052316.smt2 b/test/regress/regress0/fmf/sc-crash-052316.smt2
new file mode 100644
index 000000000..2fc86cbed
--- /dev/null
+++ b/test/regress/regress0/fmf/sc-crash-052316.smt2
@@ -0,0 +1,35 @@
+; COMMAND-LINE: --finite-model-find
+; EXPECT: unsat
+ (set-logic ALL_SUPPORTED)
+ (set-info :status unsat)
+ (declare-sort g_ 0)
+ (declare-fun __nun_card_witness_0_ () g_)
+ (declare-sort f_ 0)
+ (declare-fun __nun_card_witness_1_ () f_)
+ (declare-sort e_ 0)
+ (declare-fun __nun_card_witness_2_ () e_)
+(declare-datatypes ()
+ ((prod1_ (Pair1_ (_select_Pair1__0 e_) (_select_Pair1__1 f_)))))
+ (declare-sort d_ 0)
+ (declare-fun __nun_card_witness_3_ () d_)
+ (declare-sort c_ 0)
+ (declare-fun __nun_card_witness_4_ () c_)
+ (declare-sort b_ 0)
+ (declare-fun __nun_card_witness_5_ () b_)
+ (declare-sort a_ 0)
+ (declare-fun __nun_card_witness_6_ () a_)
+(declare-datatypes ()
+ ((prod_ (Pair_ (_select_Pair__0 a_) (_select_Pair__1 b_)))))
+ (declare-fun f1_ (prod_ c_ d_ prod1_) g_)
+ (declare-fun g1_ (prod_) c_)
+ (declare-fun h_ (prod_ d_) prod1_)
+ (declare-fun nun_sk_0_ () prod_)
+(declare-fun nun_sk_1_ (c_) d_)
+ (assert
+ (not
+ (exists ((v/72 c_))
+ (exists ((x/73 prod1_))
+ (= (f1_ nun_sk_0_ v/72 (nun_sk_1_ v/72) x/73)
+ (f1_ nun_sk_0_ (g1_ nun_sk_0_) (nun_sk_1_ v/72)
+ (h_ nun_sk_0_ (nun_sk_1_ v/72))))))))
+(check-sat)
diff --git a/test/regress/regress0/quantifiers/Makefile.am b/test/regress/regress0/quantifiers/Makefile.am
index 6b5e0d1ed..4c657adf1 100644
--- a/test/regress/regress0/quantifiers/Makefile.am
+++ b/test/regress/regress0/quantifiers/Makefile.am
@@ -79,7 +79,11 @@ TESTS = \
florian-case-ax.smt2 \
double-pattern.smt2 \
qcf-rel-dom-opt.smt2 \
- parametric-lists.smt2
+ parametric-lists.smt2 \
+ partial-trigger.smt2 \
+ inst-max-level-segf.smt2 \
+ small-bug1-fixpoint-3.smt2 \
+ z3.620661-no-fv-trigger.smt2
# regression can be solved with --finite-model-find --fmf-inst-engine
diff --git a/test/regress/regress0/quantifiers/inst-max-level-segf.smt2 b/test/regress/regress0/quantifiers/inst-max-level-segf.smt2
new file mode 100644
index 000000000..d85f3d094
--- /dev/null
+++ b/test/regress/regress0/quantifiers/inst-max-level-segf.smt2
@@ -0,0 +1,326 @@
+; COMMAND-LINE: --inst-max-level=0 --simplification=none
+; EXPECT: unsat
+(set-logic UF)
+(set-info :status unsat)
+(declare-sort Node 0)
+(declare-sort GrassPat 0)
+(declare-sort GrassArray 1)
+(declare-sort ArrayCell 1)
+(declare-sort Loc 1)
+(declare-sort Set 1)
+(declare-sort Map 2)
+(declare-sort GrassByte 0)
+(declare-fun grass_null$0 () (Loc Node))
+(declare-fun grass_read$0 ((Map (Loc Node) (Loc Node)) (Loc Node))
+ (Loc Node))
+(declare-fun grass_emptyset$0 () (Set (Loc Node)))
+(declare-fun grass_singleton$0 ((Loc Node)) (Set (Loc Node)))
+(declare-fun grass_union$0 ((Set (Loc Node)) (Set (Loc Node)))
+ (Set (Loc Node)))
+(declare-fun grass_intersection$0 ((Set (Loc Node)) (Set (Loc Node)))
+ (Set (Loc Node)))
+(declare-fun grass_setminus$0 ((Set (Loc Node)) (Set (Loc Node)))
+ (Set (Loc Node)))
+(declare-fun grass_Btwn$0 ((Map (Loc Node) (Loc Node)) (Loc Node) (Loc Node)
+ (Loc Node)) Bool)
+(declare-fun grass_member$0 ((Loc Node) (Set (Loc Node))) Bool)
+(declare-fun grass_known$0 ((Map (Loc Node) (Loc Node))) GrassPat)
+(declare-fun grass_known$1 (Bool) GrassPat)
+(declare-fun Alloc_Node$0 () (Set (Loc Node)))
+(declare-fun FP_Caller_Node$0 () (Set (Loc Node)))
+(declare-fun FP_Caller_Node_1$0 () (Set (Loc Node)))
+(declare-fun FP_Caller_final_Node_2$0 () (Set (Loc Node)))
+(declare-fun FP_Node$0 () (Set (Loc Node)))
+(declare-fun Label$0 () Bool)
+(declare-fun Label_1$0 () Bool)
+(declare-fun Label_2$0 () Bool)
+(declare-fun Label_3$0 () Bool)
+(declare-fun elt$0 () (Loc Node))
+(declare-fun lseg$0 ((Map (Loc Node) (Loc Node)) (Loc Node) (Loc Node)
+ (Set (Loc Node))) Bool)
+(declare-fun lst$0 () (Loc Node))
+(declare-fun next$0 () (Map (Loc Node) (Loc Node)))
+(declare-fun res_2$0 () (Loc Node))
+(declare-fun set_compr$0 ((Map (Loc Node) (Loc Node)) (Loc Node) (Loc Node))
+ (Set (Loc Node)))
+(declare-fun sk_?X$0 () (Set (Loc Node)))
+(declare-fun sk_?X_1$0 () (Set (Loc Node)))
+(declare-fun sk_?X_2$0 () (Set (Loc Node)))
+(declare-fun sk_?X_3$0 () (Set (Loc Node)))
+(declare-fun sk_?X_4$0 () (Set (Loc Node)))
+(declare-fun sk_?e$0 () (Loc Node))
+
+(assert (not (grass_member$0 grass_null$0 Alloc_Node$0)))
+(assert
+ (and
+ (or
+ (or
+ (and (and (grass_member$0 sk_?e$0 sk_?X_4$0) Label_1$0)
+ (and
+ (not
+ (grass_member$0 sk_?e$0
+ (set_compr$0 next$0 res_2$0 grass_null$0)))
+ Label_1$0))
+ (and
+ (and
+ (grass_member$0 sk_?e$0
+ (set_compr$0 next$0 res_2$0 grass_null$0))
+ Label_1$0)
+ (and (not (grass_member$0 sk_?e$0 sk_?X_4$0)) Label_1$0)))
+ (and
+ (not (grass_Btwn$0 next$0 res_2$0 grass_null$0 grass_null$0))
+ Label$0))
+ Label_2$0))
+(assert (forall ((x (Loc Node))) (not (grass_member$0 x grass_emptyset$0))))
+(assert
+ (forall ((y (Loc Node)) (x (Loc Node)))
+ (or (and (= x y) (grass_member$0 x (grass_singleton$0 y)))
+ (and (not (= x y))
+ (not (grass_member$0 x (grass_singleton$0 y)))))))
+(assert
+ (forall ((x (Loc Node)))
+ (or
+ (and (grass_member$0 x FP_Caller_Node$0)
+ (grass_member$0 x
+ (grass_setminus$0 FP_Caller_Node$0 FP_Node$0))
+ (not (grass_member$0 x FP_Node$0)))
+ (and
+ (or (grass_member$0 x FP_Node$0)
+ (not (grass_member$0 x FP_Caller_Node$0)))
+ (not
+ (grass_member$0 x
+ (grass_setminus$0 FP_Caller_Node$0 FP_Node$0)))))))
+(assert
+ (forall ((x (Loc Node)))
+ (or
+ (and (grass_member$0 x Alloc_Node$0)
+ (grass_member$0 x
+ (grass_setminus$0 Alloc_Node$0 Alloc_Node$0))
+ (not (grass_member$0 x Alloc_Node$0)))
+ (and
+ (or (grass_member$0 x Alloc_Node$0)
+ (not (grass_member$0 x Alloc_Node$0)))
+ (not
+ (grass_member$0 x
+ (grass_setminus$0 Alloc_Node$0 Alloc_Node$0)))))))
+(assert
+ (forall ((x (Loc Node)))
+ (or
+ (and (grass_member$0 x Alloc_Node$0)
+ (grass_member$0 x FP_Node$0)
+ (grass_member$0 x
+ (grass_intersection$0 Alloc_Node$0 FP_Node$0)))
+ (and
+ (or (not (grass_member$0 x Alloc_Node$0))
+ (not (grass_member$0 x FP_Node$0)))
+ (not
+ (grass_member$0 x
+ (grass_intersection$0 Alloc_Node$0 FP_Node$0)))))))
+(assert
+ (forall ((x (Loc Node)))
+ (or
+ (and (grass_member$0 x sk_?X$0)
+ (grass_member$0 x sk_?X_1$0)
+ (grass_member$0 x
+ (grass_intersection$0 sk_?X$0 sk_?X_1$0)))
+ (and
+ (or (not (grass_member$0 x sk_?X$0))
+ (not (grass_member$0 x sk_?X_1$0)))
+ (not
+ (grass_member$0 x
+ (grass_intersection$0 sk_?X$0 sk_?X_1$0)))))))
+(assert
+ (forall ((x (Loc Node)))
+ (or
+ (and
+ (grass_member$0 x
+ (grass_union$0
+ (grass_intersection$0 Alloc_Node$0 FP_Node$0)
+ (grass_setminus$0 Alloc_Node$0 Alloc_Node$0)))
+ (or
+ (grass_member$0 x
+ (grass_intersection$0 Alloc_Node$0 FP_Node$0))
+ (grass_member$0 x
+ (grass_setminus$0 Alloc_Node$0 Alloc_Node$0))))
+ (and
+ (not
+ (grass_member$0 x
+ (grass_intersection$0 Alloc_Node$0 FP_Node$0)))
+ (not
+ (grass_member$0 x
+ (grass_setminus$0 Alloc_Node$0 Alloc_Node$0)))
+ (not
+ (grass_member$0 x
+ (grass_union$0
+ (grass_intersection$0 Alloc_Node$0 FP_Node$0)
+ (grass_setminus$0 Alloc_Node$0 Alloc_Node$0))))))))
+(assert
+ (forall ((x (Loc Node)))
+ (or
+ (and (grass_member$0 x (grass_union$0 sk_?X$0 sk_?X_1$0))
+ (or (grass_member$0 x sk_?X$0)
+ (grass_member$0 x sk_?X_1$0)))
+ (and (not (grass_member$0 x sk_?X$0))
+ (not (grass_member$0 x sk_?X_1$0))
+ (not
+ (grass_member$0 x (grass_union$0 sk_?X$0 sk_?X_1$0)))))))
+(assert
+ (forall ((x (Loc Node)))
+ (or
+ (and
+ (grass_member$0 x
+ (grass_union$0 FP_Caller_Node_1$0 FP_Node$0))
+ (or (grass_member$0 x FP_Caller_Node_1$0)
+ (grass_member$0 x FP_Node$0)))
+ (and (not (grass_member$0 x FP_Caller_Node_1$0))
+ (not (grass_member$0 x FP_Node$0))
+ (not
+ (grass_member$0 x
+ (grass_union$0 FP_Caller_Node_1$0 FP_Node$0)))))))
+(assert
+ (forall ((x (Loc Node)))
+ (or
+ (and
+ (grass_member$0 x
+ (grass_union$0 FP_Node$0 FP_Caller_Node$0))
+ (or (grass_member$0 x FP_Node$0)
+ (grass_member$0 x FP_Caller_Node$0)))
+ (and (not (grass_member$0 x FP_Node$0))
+ (not (grass_member$0 x FP_Caller_Node$0))
+ (not
+ (grass_member$0 x
+ (grass_union$0 FP_Node$0 FP_Caller_Node$0)))))))
+(assert
+ (forall ((x (Loc Node)))
+ (or
+ (and
+ (grass_member$0 x
+ (grass_union$0 FP_Caller_Node$0 Alloc_Node$0))
+ (or (grass_member$0 x FP_Caller_Node$0)
+ (grass_member$0 x Alloc_Node$0)))
+ (and (not (grass_member$0 x FP_Caller_Node$0))
+ (not (grass_member$0 x Alloc_Node$0))
+ (not
+ (grass_member$0 x
+ (grass_union$0 FP_Caller_Node$0 Alloc_Node$0)))))))
+(assert
+ (or (grass_Btwn$0 next$0 lst$0 lst$0 lst$0)
+ (not (lseg$0 next$0 lst$0 lst$0 sk_?X$0))))
+(assert
+ (forall
+ ((next (Map (Loc Node) (Loc Node))) (x (Loc Node))
+ (y (Loc Node)) (z (Loc Node)))
+ (or
+ (and (grass_Btwn$0 next x z y)
+ (grass_member$0 z (set_compr$0 next x y)) (not (= z y)))
+ (and (or (= z y) (not (grass_Btwn$0 next x z y)))
+ (not (grass_member$0 z (set_compr$0 next x y)))))))
+(assert
+ (forall
+ ((?u (Loc Node)) (?x (Loc Node)) (?y (Loc Node))
+ (?z (Loc Node)))
+ (or (not (grass_Btwn$0 next$0 ?x ?y ?z))
+ (not (grass_Btwn$0 next$0 ?x ?u ?y))
+ (and (grass_Btwn$0 next$0 ?x ?u ?z)
+ (grass_Btwn$0 next$0 ?u ?y ?z)))))
+(assert
+ (forall
+ ((?u (Loc Node)) (?x (Loc Node)) (?y (Loc Node))
+ (?z (Loc Node)))
+ (or (not (grass_Btwn$0 next$0 ?x ?y ?z))
+ (not (grass_Btwn$0 next$0 ?y ?u ?z))
+ (and (grass_Btwn$0 next$0 ?x ?y ?u)
+ (grass_Btwn$0 next$0 ?x ?u ?z)))))
+(assert
+ (forall ((?x (Loc Node)) (?y (Loc Node)) (?z (Loc Node)))
+ (or (not (grass_Btwn$0 next$0 ?x ?y ?y))
+ (not (grass_Btwn$0 next$0 ?y ?z ?z))
+ (grass_Btwn$0 next$0 ?x ?z ?z))))
+(assert
+ (forall ((?x (Loc Node)) (?y (Loc Node)) (?z (Loc Node)))
+ (or (not (grass_Btwn$0 next$0 ?x ?y ?z))
+ (and (grass_Btwn$0 next$0 ?x ?y ?y)
+ (grass_Btwn$0 next$0 ?y ?z ?z)))))
+(assert
+ (forall ((?x (Loc Node)) (?y (Loc Node)) (?z (Loc Node)))
+ (or (not (grass_Btwn$0 next$0 ?x ?y ?y))
+ (not (grass_Btwn$0 next$0 ?x ?z ?z))
+ (grass_Btwn$0 next$0 ?x ?y ?z)
+ (grass_Btwn$0 next$0 ?x ?z ?y))))
+(assert
+ (forall ((?x (Loc Node)) (?y (Loc Node)))
+ (or (not (grass_Btwn$0 next$0 ?x ?y ?x)) (= ?x ?y))))
+(assert
+ (forall ((?y (Loc Node)))
+ (or (not (grass_Btwn$0 next$0 res_2$0 ?y ?y)) (= res_2$0 ?y)
+ (grass_Btwn$0 next$0 res_2$0 (grass_read$0 next$0 res_2$0)
+ ?y))))
+(assert
+ (forall ((?y (Loc Node)))
+ (or (not (grass_Btwn$0 next$0 lst$0 ?y ?y)) (= lst$0 ?y)
+ (grass_Btwn$0 next$0 lst$0 (grass_read$0 next$0 lst$0) ?y))))
+(assert
+ (forall ((?y (Loc Node)))
+ (or (not (= (grass_read$0 next$0 res_2$0) res_2$0))
+ (not (grass_Btwn$0 next$0 res_2$0 ?y ?y)) (= res_2$0 ?y))))
+(assert
+ (forall ((?y (Loc Node)))
+ (or (not (= (grass_read$0 next$0 lst$0) lst$0))
+ (not (grass_Btwn$0 next$0 lst$0 ?y ?y)) (= lst$0 ?y))))
+(assert
+ (grass_Btwn$0 next$0 res_2$0 (grass_read$0 next$0 res_2$0)
+ (grass_read$0 next$0 res_2$0)))
+(assert
+ (grass_Btwn$0 next$0 lst$0 (grass_read$0 next$0 lst$0)
+ (grass_read$0 next$0 lst$0)))
+(assert (forall ((?x (Loc Node))) (grass_Btwn$0 next$0 ?x ?x ?x)))
+(assert
+ (or (= sk_?X$0 (set_compr$0 next$0 lst$0 lst$0))
+ (not (lseg$0 next$0 lst$0 lst$0 sk_?X$0))))
+(assert (= (grass_read$0 next$0 grass_null$0) grass_null$0))
+(assert (= FP_Caller_Node_1$0 (grass_setminus$0 FP_Caller_Node$0 FP_Node$0)))
+(assert (and (= lst$0 grass_null$0) Label_3$0))
+(assert (= Alloc_Node$0 (grass_union$0 FP_Caller_Node$0 Alloc_Node$0)))
+(assert
+ (= sk_?X_4$0
+ (grass_union$0 (grass_intersection$0 Alloc_Node$0 FP_Node$0)
+ (grass_setminus$0 Alloc_Node$0 Alloc_Node$0))))
+(assert (= sk_?X_3$0 (grass_union$0 sk_?X$0 sk_?X_2$0)))
+(assert (= sk_?X_2$0 sk_?X_1$0))
+(assert (= sk_?X_1$0 (grass_singleton$0 elt$0)))
+(assert (= (grass_read$0 next$0 elt$0) grass_null$0))
+(assert (= FP_Node$0 sk_?X_3$0))
+(assert (= FP_Caller_Node$0 (grass_union$0 FP_Node$0 FP_Caller_Node$0)))
+(assert (= grass_emptyset$0 (grass_intersection$0 sk_?X$0 sk_?X_2$0)))
+(assert (= grass_emptyset$0 grass_emptyset$0))
+(assert (lseg$0 next$0 lst$0 grass_null$0 sk_?X$0))
+(assert
+ (= FP_Caller_final_Node_2$0
+ (grass_union$0 FP_Caller_Node_1$0 FP_Node$0)))
+(assert (= res_2$0 elt$0))
+(assert (= (grass_union$0 FP_Caller_Node$0 Alloc_Node$0) Alloc_Node$0))
+(assert (= (grass_read$0 next$0 grass_null$0) grass_null$0))
+(assert (= (grass_read$0 next$0 grass_null$0) lst$0))
+(assert (= (grass_read$0 next$0 grass_null$0) (grass_read$0 next$0 elt$0)))
+(assert
+ (= (grass_known$1 (lseg$0 next$0 lst$0 grass_null$0 sk_?X$0))
+ (grass_known$1 (lseg$0 next$0 lst$0 lst$0 sk_?X$0))))
+(assert (= (grass_intersection$0 sk_?X$0 sk_?X_2$0) grass_emptyset$0))
+(assert
+ (=
+ (grass_union$0 (grass_intersection$0 Alloc_Node$0 FP_Node$0)
+ (grass_setminus$0 Alloc_Node$0 Alloc_Node$0))
+ sk_?X_4$0))
+(assert (= res_2$0 elt$0))
+(assert (= (grass_union$0 FP_Node$0 FP_Caller_Node$0) FP_Caller_Node$0))
+(assert (= sk_?X_1$0 (grass_singleton$0 elt$0)))
+(assert (= sk_?X_1$0 sk_?X_2$0))
+(assert
+ (= FP_Caller_final_Node_2$0
+ (grass_union$0 FP_Caller_Node_1$0 FP_Node$0)))
+(assert (= FP_Node$0 sk_?X_3$0))
+(assert (= FP_Node$0 (grass_union$0 sk_?X$0 sk_?X_2$0)))
+(assert (= FP_Caller_Node_1$0 (grass_setminus$0 FP_Caller_Node$0 FP_Node$0)))
+(assert (= sk_?X$0 (set_compr$0 next$0 lst$0 lst$0)))
+(assert (= sk_?X$0 (set_compr$0 next$0 lst$0 grass_null$0)))
+(check-sat)
diff --git a/test/regress/regress0/quantifiers/partial-trigger.smt2 b/test/regress/regress0/quantifiers/partial-trigger.smt2
new file mode 100644
index 000000000..beea57bdb
--- /dev/null
+++ b/test/regress/regress0/quantifiers/partial-trigger.smt2
@@ -0,0 +1,10 @@
+; COMMAND-LINE: --partial-triggers
+; EXPECT: unsat
+(set-logic ALL_SUPPORTED)
+(set-info :status unsat)
+(declare-fun P (Int) Bool)
+(assert (forall ((x Int) (y Int)) (=> (> y 6) (or (> x y) (P x)))))
+
+(assert (not (P 5)))
+
+(check-sat)
diff --git a/test/regress/regress0/quantifiers/small-bug1-fixpoint-3.smt2 b/test/regress/regress0/quantifiers/small-bug1-fixpoint-3.smt2
new file mode 100644
index 000000000..da48f5e68
--- /dev/null
+++ b/test/regress/regress0/quantifiers/small-bug1-fixpoint-3.smt2
@@ -0,0 +1,15 @@
+; COMMAND-LINE: --cbqi-all --no-check-models
+; EXPECT: sat
+(set-logic UFBV)
+(set-info :status sat)
+(declare-fun Verilog__main.impl_PC_valid_64_1_39_!3 (Bool Bool Bool Bool Bool Bool Bool Bool Bool Bool Bool) Bool)
+(declare-fun Verilog__main.impl_flush_64_1_39_!1 (Bool Bool Bool Bool Bool Bool Bool Bool Bool Bool Bool) Bool)
+(declare-fun Verilog__main.reset_64_0_39_!4 (Bool Bool Bool Bool Bool Bool Bool Bool Bool Bool Bool) Bool)
+(declare-fun Verilog__main.impl_PC_valid_64_2_39_!6 (Bool Bool Bool Bool Bool Bool Bool Bool Bool Bool Bool) Bool)
+(declare-fun Verilog__main.impl_flush_64_0_39_!0 (Bool Bool Bool Bool Bool Bool Bool Bool Bool Bool Bool) Bool)
+(declare-fun Verilog__main.reset_64_1_39_!7 (Bool Bool Bool Bool Bool Bool Bool Bool Bool Bool Bool) Bool)
+(declare-fun Verilog__main.impl_PC_valid_64_0_39_!5 (Bool Bool Bool Bool Bool Bool Bool Bool Bool Bool Bool) Bool)
+(declare-fun Verilog__main.impl_flush_64_2_39_!2 (Bool Bool Bool Bool Bool Bool Bool Bool Bool Bool Bool) Bool)
+(assert (forall ((Verilog__main.impl_flush_64_0 Bool) (Verilog__main.impl_flush_64_1 Bool) (Verilog__main.impl_flush_64_2 Bool) (Verilog__main.impl_flush_64_3 Bool) (Verilog__main.impl_PC_valid_64_1 Bool) (Verilog__main.reset_64_0 Bool) (Verilog__main.impl_PC_valid_64_0 Bool) (Verilog__main.impl_PC_valid_64_2 Bool) (Verilog__main.reset_64_1 Bool) (Verilog__main.impl_PC_valid_64_3 Bool) (Verilog__main.reset_64_2 Bool)) (=> (and (= Verilog__main.impl_flush_64_0 false) (= Verilog__main.impl_flush_64_1 false) (= Verilog__main.impl_flush_64_2 false) (= Verilog__main.impl_flush_64_3 false) (= Verilog__main.impl_PC_valid_64_1 (ite Verilog__main.reset_64_0 true (ite Verilog__main.impl_flush_64_0 false Verilog__main.impl_PC_valid_64_0))) (= Verilog__main.impl_PC_valid_64_2 (ite Verilog__main.reset_64_1 true (ite Verilog__main.impl_flush_64_1 false Verilog__main.impl_PC_valid_64_1))) (= Verilog__main.impl_PC_valid_64_3 (ite Verilog__main.reset_64_2 true (ite Verilog__main.impl_flush_64_2 false Verilog__main.impl_PC_valid_64_2)))) (and (= (Verilog__main.impl_flush_64_0_39_!0 Verilog__main.reset_64_2 Verilog__main.impl_PC_valid_64_3 Verilog__main.reset_64_1 Verilog__main.impl_PC_valid_64_2 Verilog__main.impl_PC_valid_64_0 Verilog__main.reset_64_0 Verilog__main.impl_PC_valid_64_1 Verilog__main.impl_flush_64_3 Verilog__main.impl_flush_64_2 Verilog__main.impl_flush_64_1 Verilog__main.impl_flush_64_0) false) (= (Verilog__main.impl_flush_64_1_39_!1 Verilog__main.reset_64_2 Verilog__main.impl_PC_valid_64_3 Verilog__main.reset_64_1 Verilog__main.impl_PC_valid_64_2 Verilog__main.impl_PC_valid_64_0 Verilog__main.reset_64_0 Verilog__main.impl_PC_valid_64_1 Verilog__main.impl_flush_64_3 Verilog__main.impl_flush_64_2 Verilog__main.impl_flush_64_1 Verilog__main.impl_flush_64_0) false) (= (Verilog__main.impl_flush_64_2_39_!2 Verilog__main.reset_64_2 Verilog__main.impl_PC_valid_64_3 Verilog__main.reset_64_1 Verilog__main.impl_PC_valid_64_2 Verilog__main.impl_PC_valid_64_0 Verilog__main.reset_64_0 Verilog__main.impl_PC_valid_64_1 Verilog__main.impl_flush_64_3 Verilog__main.impl_flush_64_2 Verilog__main.impl_flush_64_1 Verilog__main.impl_flush_64_0) false) (= (Verilog__main.impl_PC_valid_64_1_39_!3 Verilog__main.reset_64_2 Verilog__main.impl_PC_valid_64_3 Verilog__main.reset_64_1 Verilog__main.impl_PC_valid_64_2 Verilog__main.impl_PC_valid_64_0 Verilog__main.reset_64_0 Verilog__main.impl_PC_valid_64_1 Verilog__main.impl_flush_64_3 Verilog__main.impl_flush_64_2 Verilog__main.impl_flush_64_1 Verilog__main.impl_flush_64_0) (ite (Verilog__main.reset_64_0_39_!4 Verilog__main.reset_64_2 Verilog__main.impl_PC_valid_64_3 Verilog__main.reset_64_1 Verilog__main.impl_PC_valid_64_2 Verilog__main.impl_PC_valid_64_0 Verilog__main.reset_64_0 Verilog__main.impl_PC_valid_64_1 Verilog__main.impl_flush_64_3 Verilog__main.impl_flush_64_2 Verilog__main.impl_flush_64_1 Verilog__main.impl_flush_64_0) true (ite (Verilog__main.impl_flush_64_0_39_!0 Verilog__main.reset_64_2 Verilog__main.impl_PC_valid_64_3 Verilog__main.reset_64_1 Verilog__main.impl_PC_valid_64_2 Verilog__main.impl_PC_valid_64_0 Verilog__main.reset_64_0 Verilog__main.impl_PC_valid_64_1 Verilog__main.impl_flush_64_3 Verilog__main.impl_flush_64_2 Verilog__main.impl_flush_64_1 Verilog__main.impl_flush_64_0) false (Verilog__main.impl_PC_valid_64_0_39_!5 Verilog__main.reset_64_2 Verilog__main.impl_PC_valid_64_3 Verilog__main.reset_64_1 Verilog__main.impl_PC_valid_64_2 Verilog__main.impl_PC_valid_64_0 Verilog__main.reset_64_0 Verilog__main.impl_PC_valid_64_1 Verilog__main.impl_flush_64_3 Verilog__main.impl_flush_64_2 Verilog__main.impl_flush_64_1 Verilog__main.impl_flush_64_0)))) (= (Verilog__main.impl_PC_valid_64_2_39_!6 Verilog__main.reset_64_2 Verilog__main.impl_PC_valid_64_3 Verilog__main.reset_64_1 Verilog__main.impl_PC_valid_64_2 Verilog__main.impl_PC_valid_64_0 Verilog__main.reset_64_0 Verilog__main.impl_PC_valid_64_1 Verilog__main.impl_flush_64_3 Verilog__main.impl_flush_64_2 Verilog__main.impl_flush_64_1 Verilog__main.impl_flush_64_0) (ite (Verilog__main.reset_64_1_39_!7 Verilog__main.reset_64_2 Verilog__main.impl_PC_valid_64_3 Verilog__main.reset_64_1 Verilog__main.impl_PC_valid_64_2 Verilog__main.impl_PC_valid_64_0 Verilog__main.reset_64_0 Verilog__main.impl_PC_valid_64_1 Verilog__main.impl_flush_64_3 Verilog__main.impl_flush_64_2 Verilog__main.impl_flush_64_1 Verilog__main.impl_flush_64_0) true (ite (Verilog__main.impl_flush_64_1_39_!1 Verilog__main.reset_64_2 Verilog__main.impl_PC_valid_64_3 Verilog__main.reset_64_1 Verilog__main.impl_PC_valid_64_2 Verilog__main.impl_PC_valid_64_0 Verilog__main.reset_64_0 Verilog__main.impl_PC_valid_64_1 Verilog__main.impl_flush_64_3 Verilog__main.impl_flush_64_2 Verilog__main.impl_flush_64_1 Verilog__main.impl_flush_64_0) false (Verilog__main.impl_PC_valid_64_1_39_!3 Verilog__main.reset_64_2 Verilog__main.impl_PC_valid_64_3 Verilog__main.reset_64_1 Verilog__main.impl_PC_valid_64_2 Verilog__main.impl_PC_valid_64_0 Verilog__main.reset_64_0 Verilog__main.impl_PC_valid_64_1 Verilog__main.impl_flush_64_3 Verilog__main.impl_flush_64_2 Verilog__main.impl_flush_64_1 Verilog__main.impl_flush_64_0)))) (or (and (= Verilog__main.impl_flush_64_3 (Verilog__main.impl_flush_64_0_39_!0 Verilog__main.reset_64_2 Verilog__main.impl_PC_valid_64_3 Verilog__main.reset_64_1 Verilog__main.impl_PC_valid_64_2 Verilog__main.impl_PC_valid_64_0 Verilog__main.reset_64_0 Verilog__main.impl_PC_valid_64_1 Verilog__main.impl_flush_64_3 Verilog__main.impl_flush_64_2 Verilog__main.impl_flush_64_1 Verilog__main.impl_flush_64_0)) (= Verilog__main.impl_PC_valid_64_3 (Verilog__main.impl_PC_valid_64_0_39_!5 Verilog__main.reset_64_2 Verilog__main.impl_PC_valid_64_3 Verilog__main.reset_64_1 Verilog__main.impl_PC_valid_64_2 Verilog__main.impl_PC_valid_64_0 Verilog__main.reset_64_0 Verilog__main.impl_PC_valid_64_1 Verilog__main.impl_flush_64_3 Verilog__main.impl_flush_64_2 Verilog__main.impl_flush_64_1 Verilog__main.impl_flush_64_0))) (and (= Verilog__main.impl_flush_64_3 (Verilog__main.impl_flush_64_1_39_!1 Verilog__main.reset_64_2 Verilog__main.impl_PC_valid_64_3 Verilog__main.reset_64_1 Verilog__main.impl_PC_valid_64_2 Verilog__main.impl_PC_valid_64_0 Verilog__main.reset_64_0 Verilog__main.impl_PC_valid_64_1 Verilog__main.impl_flush_64_3 Verilog__main.impl_flush_64_2 Verilog__main.impl_flush_64_1 Verilog__main.impl_flush_64_0)) (= Verilog__main.impl_PC_valid_64_3 (Verilog__main.impl_PC_valid_64_1_39_!3 Verilog__main.reset_64_2 Verilog__main.impl_PC_valid_64_3 Verilog__main.reset_64_1 Verilog__main.impl_PC_valid_64_2 Verilog__main.impl_PC_valid_64_0 Verilog__main.reset_64_0 Verilog__main.impl_PC_valid_64_1 Verilog__main.impl_flush_64_3 Verilog__main.impl_flush_64_2 Verilog__main.impl_flush_64_1 Verilog__main.impl_flush_64_0))) (and (= Verilog__main.impl_flush_64_3 (Verilog__main.impl_flush_64_2_39_!2 Verilog__main.reset_64_2 Verilog__main.impl_PC_valid_64_3 Verilog__main.reset_64_1 Verilog__main.impl_PC_valid_64_2 Verilog__main.impl_PC_valid_64_0 Verilog__main.reset_64_0 Verilog__main.impl_PC_valid_64_1 Verilog__main.impl_flush_64_3 Verilog__main.impl_flush_64_2 Verilog__main.impl_flush_64_1 Verilog__main.impl_flush_64_0)) (= Verilog__main.impl_PC_valid_64_3 (Verilog__main.impl_PC_valid_64_2_39_!6 Verilog__main.reset_64_2 Verilog__main.impl_PC_valid_64_3 Verilog__main.reset_64_1 Verilog__main.impl_PC_valid_64_2 Verilog__main.impl_PC_valid_64_0 Verilog__main.reset_64_0 Verilog__main.impl_PC_valid_64_1 Verilog__main.impl_flush_64_3 Verilog__main.impl_flush_64_2 Verilog__main.impl_flush_64_1 Verilog__main.impl_flush_64_0)))))) ))
+(check-sat)
+(exit)
diff --git a/test/regress/regress0/quantifiers/z3.620661-no-fv-trigger.smt2 b/test/regress/regress0/quantifiers/z3.620661-no-fv-trigger.smt2
new file mode 100644
index 000000000..aad2a4691
--- /dev/null
+++ b/test/regress/regress0/quantifiers/z3.620661-no-fv-trigger.smt2
@@ -0,0 +1,87 @@
+(set-logic AUFNIRA)
+(set-info :status unsat)
+(declare-sort S1 0)
+(declare-sort S2 0)
+(declare-sort S3 0)
+(declare-sort S4 0)
+(declare-sort S5 0)
+(declare-sort S6 0)
+(declare-sort S7 0)
+(declare-sort S8 0)
+(declare-sort S9 0)
+(declare-sort S10 0)
+(declare-sort S11 0)
+(declare-sort S12 0)
+(declare-sort S13 0)
+(declare-fun f1 () S1)
+(declare-fun f2 () S1)
+(declare-fun f3 (S2 Real) Real)
+(declare-fun f4 (S3 Real) S2)
+(declare-fun f5 () S3)
+(declare-fun f6 (S4 Int) Int)
+(declare-fun f7 (S5 Int) S4)
+(declare-fun f8 () S5)
+(declare-fun f9 () S2)
+(declare-fun f10 () Real)
+(declare-fun f11 () Real)
+(declare-fun f12 () S2)
+(declare-fun f13 (S7 S6) Real)
+(declare-fun f14 () S7)
+(declare-fun f15 () S2)
+(declare-fun f16 () S2)
+(declare-fun f17 (S8 Int) S6)
+(declare-fun f18 () S8)
+(declare-fun f19 (S9 S6) Int)
+(declare-fun f20 () S9)
+(declare-fun f21 (S10 Real) S7)
+(declare-fun f22 () S10)
+(declare-fun f23 () S2)
+(declare-fun f24 (S11 S6) S6)
+(declare-fun f25 (S12 S6) S11)
+(declare-fun f26 () S12)
+(declare-fun f27 () S12)
+(declare-fun f28 (S13 Int) S9)
+(declare-fun f29 () S13)
+(declare-fun f30 () S2)
+(declare-fun f31 () S4)
+(assert (not (= f1 f2)))
+(assert (forall ((?v0 Real) (?v1 Real)) (= (f3 (f4 f5 ?v0) ?v1) (* ?v0 ?v1))))
+(assert (forall ((?v0 Int) (?v1 Int)) (= (f6 (f7 f8 ?v0) ?v1) (* ?v0 ?v1))))
+(assert (not (= (f3 f9 (- f10 f11)) (- (f3 f9 f10)))))
+(assert (= (f3 f9 f11) 0.0))
+(assert (forall ((?v0 Real)) (= (f3 f9 (+ f11 ?v0)) (- (f3 f9 ?v0)))))
+(assert (= (f3 f9 (/ f11 2.0)) 1.0))
+(assert (= (f3 f9 (/ f11 6.0)) (/ 1.0 2.0)))
+(assert (= (f3 f9 (* 2.0 f11)) 0.0))
+(assert (= (f3 f9 (* (/ 3.0 2.0) f11)) (- 1.0)))
+(assert (let ((?v_0 2.0)) (<= (/ f11 ?v_0) ?v_0)))
+(assert (let ((?v_0 2.0)) (< (/ f11 ?v_0) ?v_0)))
+(assert (< (- (* 2.0 f11)) f11))
+(assert (< (- (/ f11 2.0)) 0.0))
+(assert (<= 2.0 f11))
+(assert (<= 0.0 (/ f11 2.0)))
+(assert (< 0.0 (/ f11 2.0)))
+(assert (< f11 4.0))
+(assert (<= 0.0 f11))
+(assert (< 0.0 f11))
+(assert (let ((?v_0 2.0)) (not (= (/ f11 ?v_0) ?v_0))))
+(assert (not (= (/ f11 2.0) 0.0)))
+(assert (not (< f11 0.0)))
+(assert (not (= f11 0.0)))
+(assert (forall ((?v0 S6) (?v1 S6)) (= (= (f13 f14 ?v0) (f13 f14 ?v1)) (= ?v0 ?v1))))
+(assert (forall ((?v0 S6) (?v1 S6)) (= (< (f13 f14 ?v0) (f13 f14 ?v1)) (< (f19 f20 ?v0) (f19 f20 ?v1)))))
+(assert (forall ((?v0 S6) (?v1 S6)) (= (<= (f13 f14 ?v0) (f13 f14 ?v1)) (<= (f19 f20 ?v0) (f19 f20 ?v1)))))
+(assert (forall ((?v0 S6) (?v1 S6)) (let ((?v_0 (f19 f20 ?v1)) (?v_1 (f19 f20 ?v0))) (=> (<= ?v_1 ?v_0) (= (f13 f14 (f17 f18 (- ?v_0 ?v_1))) (- (f13 f14 ?v1) (f13 f14 ?v0)))))))
+(assert (forall ((?v0 Real) (?v1 Real)) (exists ((?v2 Real) (?v3 Real)) (and (= ?v0 (* ?v2 (f3 f15 ?v3))) (= ?v1 (* ?v2 (f3 f9 ?v3)))))))
+(assert (< 1.0 (f3 f16 2.0)))
+(assert (< 0.0 (f3 f16 2.0)))
+(assert (<= 0.0 (f3 f16 2.0)))
+(assert (forall ((?v0 Real) (?v1 Real)) (<= 0.0 (f3 f16 (+ (* ?v0 ?v0) (* ?v1 ?v1))))))
+(assert (forall ((?v0 Real) (?v1 Real)) (=> (<= ?v0 ?v1) (<= (f3 f16 ?v0) (f3 f16 ?v1)))))
+(assert (forall ((?v0 Real) (?v1 Real)) (=> (< ?v0 ?v1) (< (f3 f16 ?v0) (f3 f16 ?v1)))))
+(assert (forall ((?v0 Real)) (let ((?v_0 0.0)) (=> (<= ?v_0 ?v0) (=> (= (f3 f16 ?v0) ?v_0) (= ?v0 ?v_0))))))
+(assert (forall ((?v0 Real)) (=> (< 0.0 ?v0) (< (/ ?v0 (f3 f16 2.0)) ?v0))))
+(assert (forall ((?v0 Real)) (let ((?v_0 0.0)) (=> (<= ?v_0 ?v0) (<= ?v_0 (f3 f16 ?v0))))))
+(assert (forall ((?v0 Real)) (let ((?v_0 1.0)) (=> (<= ?v_0 ?v0) (<= ?v_0 (f3 f16 ?v0))))))
+(check-sat)
+(exit)
diff --git a/test/regress/regress0/sep/Makefile.am b/test/regress/regress0/sep/Makefile.am
new file mode 100644
index 000000000..9d2abaa18
--- /dev/null
+++ b/test/regress/regress0/sep/Makefile.am
@@ -0,0 +1,76 @@
+# don't override a BINARY imported from a personal.mk
+@mk_if@eq ($(BINARY),)
+@mk_empty@BINARY = cvc4
+end@mk_if@
+
+LOG_COMPILER = @srcdir@/../../run_regression
+AM_LOG_FLAGS = $(RUN_REGRESSION_ARGS) @abs_top_builddir@/src/main/$(BINARY)$(EXEEXT)
+
+if AUTOMAKE_1_11
+# old-style (pre-automake 1.12) test harness
+TESTS_ENVIRONMENT = \
+ $(LOG_COMPILER) \
+ $(AM_LOG_FLAGS) $(LOG_FLAGS)
+endif
+
+MAKEFLAGS = -k
+
+# These are run for all build profiles.
+# If a test shouldn't be run in e.g. competition mode,
+# put it below in "TESTS +="
+TESTS = \
+ pto-01.smt2 \
+ pto-02.smt2 \
+ pto-04.smt2 \
+ sep-01.smt2 \
+ sep-02.smt2 \
+ sep-03.smt2 \
+ sep-find2.smt2 \
+ sep-neg-nstrict.smt2 \
+ sep-plus1.smt2 \
+ sep-nterm-val-model.smt2 \
+ crash1220.smt2 \
+ nspatial-simp.smt2 \
+ sep-neg-1refine.smt2 \
+ sep-neg-simple.smt2 \
+ sep-simp-unc.smt2 \
+ sep-simp-unsat-emp.smt2 \
+ simple-neg-sat.smt2 \
+ wand-simp-sat.smt2 \
+ wand-simp-sat2.smt2 \
+ wand-simp-unsat.smt2 \
+ sep-nterm-again.smt2 \
+ split-find-unsat.smt2 \
+ split-find-unsat-w-emp.smt2 \
+ nemp.smt2 \
+ wand-crash.smt2 \
+ wand-nterm-simp.smt2 \
+ wand-nterm-simp2.smt2 \
+ loop-1220.smt2 \
+ chain-int.smt2 \
+ sep-neg-swap.smt2 \
+ sep-neg-nstrict2.smt2 \
+ dispose-list-4-init.smt2 \
+ wand-0526-sat.smt2 \
+ quant_wand.smt2 \
+ fmf-nemp-2.smt2
+
+
+FAILING_TESTS =
+# loop-1220.smt2 (slow)
+
+EXTRA_DIST = $(TESTS)
+
+# slow after changes on Nov 20 : artemis-0512-nonterm.smt2
+# slow after decision engine respects requirePhase: type003.smt2 loop007.smt2
+
+# and make sure to distribute it
+EXTRA_DIST +=
+
+# synonyms for "check"
+.PHONY: regress regress0 test
+regress regress0 test: check
+
+# do nothing in this subdir
+.PHONY: regress1 regress2 regress3
+regress1 regress2 regress3:
diff --git a/test/regress/regress0/sep/chain-int.smt2 b/test/regress/regress0/sep/chain-int.smt2
new file mode 100644
index 000000000..d3245e33f
--- /dev/null
+++ b/test/regress/regress0/sep/chain-int.smt2
@@ -0,0 +1,11 @@
+(set-logic ALL_SUPPORTED)
+(set-info :status unsat)
+
+(declare-const x Int)
+(declare-const y Int)
+(declare-const z Int)
+
+(assert (sep (pto x y) (pto y z)))
+(assert (and (> x 3) (< x 5)))
+(assert (and (> y 3) (< y 5)))
+(check-sat)
diff --git a/test/regress/regress0/sep/crash1220.smt2 b/test/regress/regress0/sep/crash1220.smt2
new file mode 100755
index 000000000..a0fc5a187
--- /dev/null
+++ b/test/regress/regress0/sep/crash1220.smt2
@@ -0,0 +1,15 @@
+; COMMAND-LINE: --no-check-models
+; EXPECT: sat
+(set-logic ALL_SUPPORTED)
+(set-info :status sat)
+
+(declare-const x Int)
+(declare-const a Int)
+
+(declare-const y Int)
+(declare-const b Int)
+
+(assert (or (pto x a) (sep (pto x a) (pto y b))))
+(assert (or (not (pto x a)) (sep (not (pto x a)) (not (pto y b)))))
+
+(check-sat)
diff --git a/test/regress/regress0/sep/dispose-list-4-init.smt2 b/test/regress/regress0/sep/dispose-list-4-init.smt2
new file mode 100644
index 000000000..766354cd9
--- /dev/null
+++ b/test/regress/regress0/sep/dispose-list-4-init.smt2
@@ -0,0 +1,36 @@
+; COMMAND-LINE: --no-check-models
+; EXPECT: sat
+(set-logic ALL_SUPPORTED)
+
+(declare-sort Loc 0)
+
+(declare-const w Loc)
+(declare-const u1 Loc)
+(declare-const u2 Loc)
+(declare-const u3 Loc)
+(declare-const nil Loc)
+
+(declare-const w1 Loc)
+(declare-const w2 Loc)
+(declare-const w3 Loc)
+(declare-const w4 Loc)
+
+; allocated (not nil)
+(assert (not (= w nil)))
+(assert (not (= u1 nil)))
+(assert (not (= u2 nil)))
+(assert (not (= u3 nil)))
+(assert (not (= w1 nil)))
+(assert (not (= w2 nil)))
+(assert (not (= w4 nil)))
+
+; from model
+;(assert (= w1 u3))
+;(assert (= w2 u2))
+;(assert (= w3 u1))
+;(assert (= w4 u1))
+
+(assert (sep (pto w u1) (pto u1 u2) (pto u2 u3) (pto u3 nil)))
+(assert (and (sep (sep (pto w4 w1) (pto w1 w2) (pto w2 nil)) (pto w w3)) (sep (pto w w4) true)))
+
+(check-sat)
diff --git a/test/regress/regress0/sep/fmf-nemp-2.smt2 b/test/regress/regress0/sep/fmf-nemp-2.smt2
new file mode 100644
index 000000000..71fe96d71
--- /dev/null
+++ b/test/regress/regress0/sep/fmf-nemp-2.smt2
@@ -0,0 +1,10 @@
+; COMMAND-LINE: --finite-model-find --no-check-models
+; EXPECT: sat
+(set-logic ALL_SUPPORTED)
+(declare-sort U 0)
+(declare-fun u1 () U)
+(declare-fun u2 () U)
+(assert (not (= u1 u2)))
+(assert (forall ((x U)) (=> (not (= x (as sep.nil U))) (sep (not (emp u1)) (pto x 0)))))
+; satisfiable with heap of size 2, model of U of size 3
+(check-sat)
diff --git a/test/regress/regress0/sep/loop-1220.smt2 b/test/regress/regress0/sep/loop-1220.smt2
new file mode 100644
index 000000000..2981606d8
--- /dev/null
+++ b/test/regress/regress0/sep/loop-1220.smt2
@@ -0,0 +1,19 @@
+; COMMAND-LINE: --no-check-models
+; EXPECT: sat
+(set-logic ALL_SUPPORTED)
+(set-info :status sat)
+
+(declare-const x Int)
+(declare-const a Int)
+
+(declare-const y Int)
+(declare-const b Int)
+(declare-const y0 Int)
+(declare-const b0 Int)
+(declare-const y00 Int)
+(declare-const b00 Int)
+
+(assert (or false (sep (pto x a) (or false (sep (pto y b) (or false (sep (pto y0 b0) (pto y00 b00) )))))))
+(assert (not (or false (sep (pto x a) (not (or false (sep (pto y b) (not (or false (sep (pto y0 b0) (not (pto y00 b00)) ))))))))))
+
+(check-sat)
diff --git a/test/regress/regress0/sep/nemp.smt2 b/test/regress/regress0/sep/nemp.smt2
new file mode 100644
index 000000000..e1e21dd10
--- /dev/null
+++ b/test/regress/regress0/sep/nemp.smt2
@@ -0,0 +1,5 @@
+; COMMAND-LINE: --no-check-models
+; EXPECT: sat
+(set-logic ALL_SUPPORTED)
+(assert (not (emp 0)))
+(check-sat)
diff --git a/test/regress/regress0/sep/nspatial-simp.smt2 b/test/regress/regress0/sep/nspatial-simp.smt2
new file mode 100755
index 000000000..0c93719c9
--- /dev/null
+++ b/test/regress/regress0/sep/nspatial-simp.smt2
@@ -0,0 +1,11 @@
+; COMMAND-LINE: --no-check-models
+; EXPECT: sat
+(set-logic ALL_SUPPORTED)
+(set-info :status sat)
+(declare-fun x () Int)
+
+(assert (sep (= x 0) (not (= x 5))))
+
+(declare-fun y () Int)
+(assert (pto y 0))
+(check-sat)
diff --git a/test/regress/regress0/sep/pto-01.smt2 b/test/regress/regress0/sep/pto-01.smt2
new file mode 100644
index 000000000..b0dece248
--- /dev/null
+++ b/test/regress/regress0/sep/pto-01.smt2
@@ -0,0 +1,13 @@
+(set-logic ALL_SUPPORTED)
+(set-info :status unsat)
+
+(declare-const x Int)
+
+(declare-const a Int)
+(declare-const b Int)
+
+(assert (and (pto x a) (pto x b)))
+
+(assert (not (= a b)))
+
+(check-sat)
diff --git a/test/regress/regress0/sep/pto-02.smt2 b/test/regress/regress0/sep/pto-02.smt2
new file mode 100644
index 000000000..f0b6d2dee
--- /dev/null
+++ b/test/regress/regress0/sep/pto-02.smt2
@@ -0,0 +1,25 @@
+(set-logic ALL_SUPPORTED)
+(set-info :status unsat)
+
+
+(declare-const x Int)
+
+(declare-const a1 Int)
+(declare-const a2 Int)
+(declare-const a3 Int)
+(declare-const a4 Int)
+(declare-const a5 Int)
+(declare-const a6 Int)
+(declare-const a7 Int)
+(declare-const a8 Int)
+(declare-const a9 Int)
+
+(assert (and (pto x a1) (pto x a2) (pto x a3)
+ (pto x a4) (pto x a5) (pto x a6)
+ (pto x a7) (pto x a8) (pto x a9)
+ )
+)
+
+(assert (not (= a1 a2 a3 a4 a5 a6 a7 a8 a9)))
+
+(check-sat)
diff --git a/test/regress/regress0/sep/pto-04.smt2 b/test/regress/regress0/sep/pto-04.smt2
new file mode 100644
index 000000000..1734c93bb
--- /dev/null
+++ b/test/regress/regress0/sep/pto-04.smt2
@@ -0,0 +1,36 @@
+(set-logic ALL_SUPPORTED)
+(set-info :status unsat)
+
+(declare-const x1 Int)
+(declare-const x2 Int)
+(declare-const x3 Int)
+(declare-const x4 Int)
+(declare-const x5 Int)
+(declare-const x6 Int)
+(declare-const x7 Int)
+(declare-const x8 Int)
+(declare-const x9 Int)
+
+(declare-const a1 Int)
+(declare-const a2 Int)
+(declare-const a3 Int)
+(declare-const a4 Int)
+(declare-const a5 Int)
+(declare-const a6 Int)
+(declare-const a7 Int)
+(declare-const a8 Int)
+(declare-const a9 Int)
+
+(assert (and (pto x1 a1) (pto x2 a2) (pto x3 a3)
+ (pto x4 a4) (pto x5 a5) (pto x6 a6)
+ (pto x7 a7) (pto x8 a8) (pto x9 a9)
+ )
+)
+
+(assert (not (and (= x1 x2 x3 x4 x5 x6 x7 x8 x9)
+ (= a1 a2 a3 a4 a5 a6 a7 a8 a9)
+ )
+ )
+)
+
+(check-sat)
diff --git a/test/regress/regress0/sep/quant_wand.smt2 b/test/regress/regress0/sep/quant_wand.smt2
new file mode 100644
index 000000000..d71b937fc
--- /dev/null
+++ b/test/regress/regress0/sep/quant_wand.smt2
@@ -0,0 +1,15 @@
+; COMMAND-LINE: --cbqi-all
+; EXPECT: unsat
+(set-logic ALL_SUPPORTED)
+(set-info :status unsat)
+
+(declare-const u Int)
+
+(assert (emp 0))
+
+(assert
+(forall ((y Int))
+(not (wand (pto u 5) (and (= y 42) (pto u 5))))
+))
+
+(check-sat)
diff --git a/test/regress/regress0/sep/sep-01.smt2 b/test/regress/regress0/sep/sep-01.smt2
new file mode 100644
index 000000000..c3330f036
--- /dev/null
+++ b/test/regress/regress0/sep/sep-01.smt2
@@ -0,0 +1,14 @@
+(set-logic ALL_SUPPORTED)
+(set-info :status unsat)
+
+(declare-const x Int)
+(declare-const y Int)
+
+(declare-const a Int)
+(declare-const b Int)
+
+(assert (sep (pto x a) (pto y b)))
+
+(assert (= x y))
+
+(check-sat)
diff --git a/test/regress/regress0/sep/sep-02.smt2 b/test/regress/regress0/sep/sep-02.smt2
new file mode 100644
index 000000000..403bcf077
--- /dev/null
+++ b/test/regress/regress0/sep/sep-02.smt2
@@ -0,0 +1,16 @@
+(set-logic ALL_SUPPORTED)
+(set-info :status unsat)
+
+(declare-const x Int)
+(declare-const y Int)
+(declare-const z Int)
+
+(declare-const a Int)
+(declare-const b Int)
+(declare-const c Int)
+
+(assert (sep (pto x a) (pto y b) (pto z c)))
+
+(assert (or (= x y) (= y z) (= x z)))
+
+(check-sat)
diff --git a/test/regress/regress0/sep/sep-03.smt2 b/test/regress/regress0/sep/sep-03.smt2
new file mode 100644
index 000000000..427c44b50
--- /dev/null
+++ b/test/regress/regress0/sep/sep-03.smt2
@@ -0,0 +1,17 @@
+(set-logic ALL_SUPPORTED)
+(set-info :status unsat)
+
+(declare-const x Int)
+(declare-const y Int)
+
+(declare-const a Int)
+(declare-const b Int)
+
+(assert (and (sep (pto x a) (or (pto x a) (pto y b)))
+ (sep (pto y b) (or (pto x a) (pto y b)))
+ )
+)
+
+(assert (not (sep (pto x a) (pto y b))))
+
+(check-sat)
diff --git a/test/regress/regress0/sep/sep-find2.smt2 b/test/regress/regress0/sep/sep-find2.smt2
new file mode 100644
index 000000000..26a27eb22
--- /dev/null
+++ b/test/regress/regress0/sep/sep-find2.smt2
@@ -0,0 +1,22 @@
+(set-logic ALL_SUPPORTED)
+(set-info :status unsat)
+
+(declare-const x1 Int)
+(declare-const x2 Int)
+(declare-const x3 Int)
+(declare-const x4 Int)
+(declare-const x5 Int)
+(declare-const x6 Int)
+(declare-const x7 Int)
+
+(declare-const a1 Int)
+(declare-const a2 Int)
+
+(assert (and
+(sep (pto x1 a1) (pto x2 a2) (pto x4 a2) (pto x5 a2) (pto x6 a2) (pto x7 a2))
+(sep (pto x1 a1) (pto x3 a2))
+))
+
+(assert (distinct x3 x2 x4 x5 x6 x7))
+
+(check-sat)
diff --git a/test/regress/regress0/sep/sep-neg-1refine.smt2 b/test/regress/regress0/sep/sep-neg-1refine.smt2
new file mode 100644
index 000000000..8ddbdd05f
--- /dev/null
+++ b/test/regress/regress0/sep/sep-neg-1refine.smt2
@@ -0,0 +1,17 @@
+; COMMAND-LINE: --no-check-models
+; EXPECT: sat
+(set-logic ALL_SUPPORTED)
+(set-info :status sat)
+
+(declare-const x Int)
+(declare-const y Int)
+(declare-const z Int)
+
+(declare-const a Int)
+(declare-const b Int)
+
+(assert (not (sep (pto x a) (pto y b))))
+(assert (sep (pto x a) (pto z b)))
+
+; sat with model where y != z
+(check-sat)
diff --git a/test/regress/regress0/sep/sep-neg-nstrict.smt2 b/test/regress/regress0/sep/sep-neg-nstrict.smt2
new file mode 100644
index 000000000..1a69336a8
--- /dev/null
+++ b/test/regress/regress0/sep/sep-neg-nstrict.smt2
@@ -0,0 +1,15 @@
+(set-logic ALL_SUPPORTED)
+(set-info :status unsat)
+
+(declare-const x Int)
+(declare-const y Int)
+(declare-const z Int)
+
+(declare-const a Int)
+(declare-const b Int)
+
+(assert (not (sep true (pto x a))))
+(assert (sep (pto x a) (pto z b)))
+
+
+(check-sat)
diff --git a/test/regress/regress0/sep/sep-neg-nstrict2.smt2 b/test/regress/regress0/sep/sep-neg-nstrict2.smt2
new file mode 100644
index 000000000..e71e6a51a
--- /dev/null
+++ b/test/regress/regress0/sep/sep-neg-nstrict2.smt2
@@ -0,0 +1,18 @@
+; COMMAND-LINE: --no-check-models
+; EXPECT: sat
+(set-logic ALL_SUPPORTED)
+(set-info :status sat)
+
+(declare-const x Int)
+(declare-const y Int)
+(declare-const z Int)
+
+(declare-const a Int)
+(declare-const b Int)
+
+(assert (not (= a b)))
+(assert (not (sep true (pto x b))))
+(assert (sep (pto x a) (pto z b)))
+
+
+(check-sat)
diff --git a/test/regress/regress0/sep/sep-neg-simple.smt2 b/test/regress/regress0/sep/sep-neg-simple.smt2
new file mode 100644
index 000000000..191e7527f
--- /dev/null
+++ b/test/regress/regress0/sep/sep-neg-simple.smt2
@@ -0,0 +1,16 @@
+; COMMAND-LINE: --no-check-models
+; EXPECT: sat
+(set-logic ALL_SUPPORTED)
+(set-info :status sat)
+
+(declare-const x Int)
+(declare-const y Int)
+(declare-const z Int)
+
+(declare-const a Int)
+(declare-const b Int)
+
+(assert (not (pto x a)))
+(assert (sep (pto x a) (pto z b)))
+
+(check-sat)
diff --git a/test/regress/regress0/sep/sep-neg-swap.smt2 b/test/regress/regress0/sep/sep-neg-swap.smt2
new file mode 100644
index 000000000..f89a9c0ac
--- /dev/null
+++ b/test/regress/regress0/sep/sep-neg-swap.smt2
@@ -0,0 +1,17 @@
+; COMMAND-LINE: --no-check-models
+; EXPECT: sat
+(set-logic ALL_SUPPORTED)
+(set-info :status sat)
+
+(declare-const x Int)
+(declare-const y Int)
+(declare-const z Int)
+
+(declare-const a Int)
+(declare-const b Int)
+
+(assert (not (sep (pto y a) (pto x b))))
+(assert (sep (pto x a) (pto y b)))
+
+
+(check-sat)
diff --git a/test/regress/regress0/sep/sep-nterm-again.smt2 b/test/regress/regress0/sep/sep-nterm-again.smt2
new file mode 100644
index 000000000..9b4afe36a
--- /dev/null
+++ b/test/regress/regress0/sep/sep-nterm-again.smt2
@@ -0,0 +1,20 @@
+; COMMAND-LINE: --no-check-models
+; EXPECT: sat
+(set-logic ALL_SUPPORTED)
+(set-info :status sat)
+
+(declare-const x Int)
+(declare-const y Int)
+(declare-const z Int)
+
+(declare-const a Int)
+(declare-const b Int)
+(declare-const c Int)
+
+(assert (and
+ (not (sep (not (sep (not (pto x a)) (not (pto y b)))) (pto x a) ))
+ (sep (pto x a) (pto y b))
+ )
+)
+
+(check-sat)
diff --git a/test/regress/regress0/sep/sep-nterm-val-model.smt2 b/test/regress/regress0/sep/sep-nterm-val-model.smt2
new file mode 100644
index 000000000..0178134cb
--- /dev/null
+++ b/test/regress/regress0/sep/sep-nterm-val-model.smt2
@@ -0,0 +1,17 @@
+(set-logic ALL_SUPPORTED)
+(set-info :status unsat)
+
+(declare-const x Int)
+(declare-const y Int)
+(declare-const z Int)
+
+(declare-const a Int)
+(declare-const b Int)
+
+(assert (and
+ (not (sep (not (pto x a)) (not (pto y b)) ))
+ (sep (pto x (+ a 1)) (pto y (+ b 1)))
+ )
+)
+
+(check-sat)
diff --git a/test/regress/regress0/sep/sep-plus1.smt2 b/test/regress/regress0/sep/sep-plus1.smt2
new file mode 100644
index 000000000..772acd981
--- /dev/null
+++ b/test/regress/regress0/sep/sep-plus1.smt2
@@ -0,0 +1,18 @@
+(set-logic ALL_SUPPORTED)
+(set-info :status unsat)
+
+(declare-const x Int)
+(declare-const y Int)
+(declare-const z Int)
+
+(declare-const a Int)
+(declare-const b Int)
+(declare-const c Int)
+
+(assert (and
+ (sep (pto x a) true)
+ (sep (pto y (+ a 1)) true)
+))
+(assert (= x y))
+
+(check-sat)
diff --git a/test/regress/regress0/sep/sep-simp-unc.smt2 b/test/regress/regress0/sep/sep-simp-unc.smt2
new file mode 100755
index 000000000..6cdf51294
--- /dev/null
+++ b/test/regress/regress0/sep/sep-simp-unc.smt2
@@ -0,0 +1,12 @@
+; COMMAND-LINE: --no-check-models
+; EXPECT: sat
+(set-logic ALL_SUPPORTED)
+(set-info :status sat)
+(declare-sort U 0)
+(declare-fun x () U)
+(declare-fun y () U)
+(declare-fun a () U)
+(declare-fun b () U)
+
+(assert (not (sep (not (pto x a)) (pto y b))))
+(check-sat)
diff --git a/test/regress/regress0/sep/sep-simp-unsat-emp.smt2 b/test/regress/regress0/sep/sep-simp-unsat-emp.smt2
new file mode 100644
index 000000000..fb58b9d10
--- /dev/null
+++ b/test/regress/regress0/sep/sep-simp-unsat-emp.smt2
@@ -0,0 +1,12 @@
+(set-logic ALL_SUPPORTED)
+(set-info :status unsat)
+
+(declare-sort U 0)
+(declare-fun x () U)
+(declare-fun y () U)
+(declare-fun a () U)
+(declare-fun b () U)
+
+(assert (emp x))
+(assert (sep (pto x a) (pto y b)))
+(check-sat)
diff --git a/test/regress/regress0/sep/simple-neg-sat.smt2 b/test/regress/regress0/sep/simple-neg-sat.smt2
new file mode 100644
index 000000000..0c0b6a9a3
--- /dev/null
+++ b/test/regress/regress0/sep/simple-neg-sat.smt2
@@ -0,0 +1,20 @@
+; COMMAND-LINE: --no-check-models
+; EXPECT: sat
+(set-logic ALL_SUPPORTED)
+(set-info :status sat)
+
+(declare-const x Int)
+(declare-const y Int)
+(declare-const z Int)
+
+(declare-const a Int)
+(declare-const b Int)
+(declare-const c Int)
+
+(assert (and
+ (not (sep (not (pto x a)) (pto y b) ))
+ (sep (pto x a) (pto y b))
+ )
+)
+
+(check-sat)
diff --git a/test/regress/regress0/sep/split-find-unsat-w-emp.smt2 b/test/regress/regress0/sep/split-find-unsat-w-emp.smt2
new file mode 100644
index 000000000..ed3187a96
--- /dev/null
+++ b/test/regress/regress0/sep/split-find-unsat-w-emp.smt2
@@ -0,0 +1,18 @@
+(set-logic ALL_SUPPORTED)
+(set-info :status unsat)
+
+(declare-const x Int)
+(declare-const y Int)
+(declare-const z Int)
+
+(declare-const a Int)
+(declare-const b Int)
+(declare-const c Int)
+
+(assert (and
+ (not (sep (not (pto x a)) (not (pto y b)) (not (sep (pto x a) (pto y b))) (not (emp x)) ))
+ (sep (pto x a) (pto y b))
+ )
+)
+
+(check-sat)
diff --git a/test/regress/regress0/sep/split-find-unsat.smt2 b/test/regress/regress0/sep/split-find-unsat.smt2
new file mode 100644
index 000000000..54530cbf4
--- /dev/null
+++ b/test/regress/regress0/sep/split-find-unsat.smt2
@@ -0,0 +1,20 @@
+; COMMAND-LINE: --no-check-models
+; EXPECT: sat
+(set-logic ALL_SUPPORTED)
+(set-info :status sat)
+
+(declare-const x Int)
+(declare-const y Int)
+(declare-const z Int)
+
+(declare-const a Int)
+(declare-const b Int)
+(declare-const c Int)
+
+(assert (and
+ (not (sep (not (pto x a)) (not (pto y b)) (not (sep (pto x a) (pto y b))) ))
+ (sep (pto x a) (pto y b))
+ )
+)
+
+(check-sat)
diff --git a/test/regress/regress0/sep/wand-0526-sat.smt2 b/test/regress/regress0/sep/wand-0526-sat.smt2
new file mode 100644
index 000000000..0c0ee72ad
--- /dev/null
+++ b/test/regress/regress0/sep/wand-0526-sat.smt2
@@ -0,0 +1,10 @@
+; COMMAND-LINE: --no-check-models
+; EXPECT: sat
+(set-logic ALL_SUPPORTED)
+(declare-fun x () Int)
+(declare-fun y () Int)
+(declare-fun u () Int)
+(declare-fun v () Int)
+(assert (wand (pto x u) (pto y v)))
+(assert (emp 0))
+(check-sat)
diff --git a/test/regress/regress0/sep/wand-crash.smt2 b/test/regress/regress0/sep/wand-crash.smt2
new file mode 100644
index 000000000..9b4871323
--- /dev/null
+++ b/test/regress/regress0/sep/wand-crash.smt2
@@ -0,0 +1,5 @@
+; COMMAND-LINE: --no-check-models
+; EXPECT: sat
+(set-logic ALL_SUPPORTED)
+(assert (wand (emp 0) (emp 0)))
+(check-sat)
diff --git a/test/regress/regress0/sep/wand-nterm-simp.smt2 b/test/regress/regress0/sep/wand-nterm-simp.smt2
new file mode 100644
index 000000000..e8ee4252c
--- /dev/null
+++ b/test/regress/regress0/sep/wand-nterm-simp.smt2
@@ -0,0 +1,7 @@
+; COMMAND-LINE: --no-check-models
+; EXPECT: sat
+(set-logic ALL_SUPPORTED)
+(declare-fun x () Int)
+(assert (wand (emp x) (pto x 3)))
+(check-sat)
+
diff --git a/test/regress/regress0/sep/wand-nterm-simp2.smt2 b/test/regress/regress0/sep/wand-nterm-simp2.smt2
new file mode 100644
index 000000000..69305e95c
--- /dev/null
+++ b/test/regress/regress0/sep/wand-nterm-simp2.smt2
@@ -0,0 +1,6 @@
+; COMMAND-LINE: --no-check-models
+; EXPECT: unsat
+(set-logic ALL_SUPPORTED)
+(declare-fun x () Int)
+(assert (wand (pto x 1) (emp x)))
+(check-sat)
diff --git a/test/regress/regress0/sep/wand-simp-sat.smt2 b/test/regress/regress0/sep/wand-simp-sat.smt2
new file mode 100755
index 000000000..df4bfa6d8
--- /dev/null
+++ b/test/regress/regress0/sep/wand-simp-sat.smt2
@@ -0,0 +1,6 @@
+; COMMAND-LINE: --no-check-models
+; EXPECT: sat
+(set-logic ALL_SUPPORTED)
+(declare-fun x () Int)
+(assert (wand (pto x 1) (pto x 1)))
+(check-sat)
diff --git a/test/regress/regress0/sep/wand-simp-sat2.smt2 b/test/regress/regress0/sep/wand-simp-sat2.smt2
new file mode 100755
index 000000000..ebc115fdd
--- /dev/null
+++ b/test/regress/regress0/sep/wand-simp-sat2.smt2
@@ -0,0 +1,6 @@
+; COMMAND-LINE: --no-check-models
+; EXPECT: unsat
+(set-logic ALL_SUPPORTED)
+(declare-fun x () Int)
+(assert (wand (pto x 1) (pto x 3)))
+(check-sat)
diff --git a/test/regress/regress0/sep/wand-simp-unsat.smt2 b/test/regress/regress0/sep/wand-simp-unsat.smt2
new file mode 100755
index 000000000..95bc85537
--- /dev/null
+++ b/test/regress/regress0/sep/wand-simp-unsat.smt2
@@ -0,0 +1,7 @@
+; COMMAND-LINE: --no-check-models
+; EXPECT: unsat
+(set-logic ALL_SUPPORTED)
+(declare-fun x () Int)
+(assert (wand (pto x 1) (pto x 3)))
+(assert (emp x))
+(check-sat)
diff --git a/test/regress/regress0/strings/Makefile.am b/test/regress/regress0/strings/Makefile.am
index 771b9f031..477d336e6 100644
--- a/test/regress/regress0/strings/Makefile.am
+++ b/test/regress/regress0/strings/Makefile.am
@@ -76,7 +76,9 @@ TESTS = \
type002.smt2 \
crash-1019.smt2 \
norn-31.smt2 \
- strings-native-simple.cvc
+ strings-native-simple.cvc \
+ cmu-2db2-extf-reg.smt2 \
+ norn-nel-bug-052116.smt2
FAILING_TESTS =
diff --git a/test/regress/regress0/strings/cmu-2db2-extf-reg.smt2 b/test/regress/regress0/strings/cmu-2db2-extf-reg.smt2
new file mode 100644
index 000000000..b513494b8
--- /dev/null
+++ b/test/regress/regress0/strings/cmu-2db2-extf-reg.smt2
@@ -0,0 +1,9 @@
+(set-logic ALL_SUPPORTED)
+(set-info :status sat)
+(set-option :strings-exp true)
+
+(declare-fun s () String)
+
+(assert (and (not (not (= (ite (= (str.indexof s "bar" 1) (- 1)) 1 0) 0))) (not (not (= (ite (= (str.indexof s "bar" 1) 3) 1 0) 0)))))
+
+(check-sat)
diff --git a/test/regress/regress0/strings/norn-nel-bug-052116.smt2 b/test/regress/regress0/strings/norn-nel-bug-052116.smt2
new file mode 100644
index 000000000..f0c2534a1
--- /dev/null
+++ b/test/regress/regress0/strings/norn-nel-bug-052116.smt2
@@ -0,0 +1,23 @@
+(set-logic QF_S)
+(set-info :status sat)
+(set-option :strings-exp true)
+
+(declare-fun var_0 () String)
+(declare-fun var_1 () String)
+(declare-fun var_2 () String)
+(declare-fun var_3 () String)
+(declare-fun var_4 () String)
+(declare-fun var_5 () String)
+(declare-fun var_6 () String)
+(declare-fun var_7 () String)
+(declare-fun var_8 () String)
+(declare-fun var_9 () String)
+(declare-fun var_10 () String)
+(declare-fun var_11 () String)
+(declare-fun var_12 () String)
+
+(assert (str.in.re var_4 (re.* (re.range "a" "u"))))
+(assert (str.in.re var_4 (re.++ (re.* (re.union (str.to.re "a") (re.++ (str.to.re "b") (str.to.re "a")))) (str.to.re "b"))))
+(assert (str.in.re (str.++ "a" var_4 "b" ) (re.* (re.range "a" "u"))))
+(assert (not (str.in.re (str.++ "a" var_4 "b" ) (re.++ (re.* (str.to.re "a")) (re.++ (str.to.re "b") (re.* (str.to.re "b")))))))
+(check-sat)
diff --git a/test/regress/regress0/sygus/Makefile.am b/test/regress/regress0/sygus/Makefile.am
index 2ca807662..b503a65b8 100644
--- a/test/regress/regress0/sygus/Makefile.am
+++ b/test/regress/regress0/sygus/Makefile.am
@@ -48,7 +48,10 @@ TESTS = commutative.sy \
clock-inc-tuple.sy \
dt-test-ns.sy \
no-mention.sy \
- max2-univ.sy
+ max2-univ.sy \
+ strings-small.sy \
+ strings-unconstrained.sy \
+ hd-sdiv.sy
# sygus tests currently taking too long for make regress
EXTRA_DIST = $(TESTS) \
diff --git a/test/regress/regress0/sygus/array_search_2.sy b/test/regress/regress0/sygus/array_search_2.sy
index 56a30b210..e6683ced9 100644
--- a/test/regress/regress0/sygus/array_search_2.sy
+++ b/test/regress/regress0/sygus/array_search_2.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi-si --no-dump-synth
+; COMMAND-LINE: --cegqi-si=all --no-dump-synth
(set-logic LIA)
(synth-fun findIdx ( (y1 Int) (y2 Int) (k1 Int)) Int ((Start Int ( 0 1 2 y1 y2 k1 (ite BoolExpr Start Start))) (BoolExpr Bool ((< Start Start) (<= Start Start) (> Start Start) (>= Start Start)))))
(declare-var x1 Int)
diff --git a/test/regress/regress0/sygus/array_sum_2_5.sy b/test/regress/regress0/sygus/array_sum_2_5.sy
index f6c0320e2..387ce9487 100644
--- a/test/regress/regress0/sygus/array_sum_2_5.sy
+++ b/test/regress/regress0/sygus/array_sum_2_5.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi-si --no-dump-synth
+; COMMAND-LINE: --cegqi-si=all --no-dump-synth
(set-logic LIA)
(synth-fun findSum ( (y1 Int) (y2 Int) )Int ((Start Int ( 0 1 2 y1 y2 (+ Start Start) (ite BoolExpr Start Start))) (BoolExpr Bool ((< Start Start) (<= Start Start) (> Start Start) (>= Start Start)))))
(declare-var x1 Int)
diff --git a/test/regress/regress0/sygus/clock-inc-tuple.sy b/test/regress/regress0/sygus/clock-inc-tuple.sy
index 09bdb8b4d..3519319bd 100644
--- a/test/regress/regress0/sygus/clock-inc-tuple.sy
+++ b/test/regress/regress0/sygus/clock-inc-tuple.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi-si --no-dump-synth
+; COMMAND-LINE: --cegqi-si=all --no-dump-synth
(set-logic ALL_SUPPORTED)
(declare-var m Int)
diff --git a/test/regress/regress0/sygus/commutative.sy b/test/regress/regress0/sygus/commutative.sy
index 46dbd2981..f675bddad 100644
--- a/test/regress/regress0/sygus/commutative.sy
+++ b/test/regress/regress0/sygus/commutative.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi --no-dump-synth
+; COMMAND-LINE: --no-dump-synth
(set-logic LIA)
@@ -19,4 +19,4 @@
(check-synth)
-; (+ x y) is a valid solution \ No newline at end of file
+; (+ x y) is a valid solution
diff --git a/test/regress/regress0/sygus/const-var-test.sy b/test/regress/regress0/sygus/const-var-test.sy
index 428cb2adc..b79b7eeec 100644
--- a/test/regress/regress0/sygus/const-var-test.sy
+++ b/test/regress/regress0/sygus/const-var-test.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi-si --no-dump-synth
+; COMMAND-LINE: --cegqi-si=all --no-dump-synth
(set-logic LIA)
diff --git a/test/regress/regress0/sygus/constant.sy b/test/regress/regress0/sygus/constant.sy
index 0059f6947..5c48f5e39 100644
--- a/test/regress/regress0/sygus/constant.sy
+++ b/test/regress/regress0/sygus/constant.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi --no-dump-synth
+; COMMAND-LINE: --no-dump-synth
(set-logic LIA)
@@ -20,4 +20,4 @@
(check-synth)
-; 0, 1, (- x x) are valid solutions \ No newline at end of file
+; 0, 1, (- x x) are valid solutions
diff --git a/test/regress/regress0/sygus/dt-no-syntax.sy b/test/regress/regress0/sygus/dt-no-syntax.sy
index e0f8112ce..42382ac91 100644
--- a/test/regress/regress0/sygus/dt-no-syntax.sy
+++ b/test/regress/regress0/sygus/dt-no-syntax.sy
@@ -1,4 +1,4 @@
-; COMMAND-LINE: --cegqi --no-dump-synth
+; COMMAND-LINE: --no-dump-synth
; EXPECT: unsat
(set-logic LIA)
diff --git a/test/regress/regress0/sygus/dt-test-ns.sy b/test/regress/regress0/sygus/dt-test-ns.sy
index ed17f4ff2..052065061 100644
--- a/test/regress/regress0/sygus/dt-test-ns.sy
+++ b/test/regress/regress0/sygus/dt-test-ns.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi-si --no-dump-synth
+; COMMAND-LINE: --cegqi-si=all --no-dump-synth
(set-logic LIA)
(declare-datatypes () ((List (cons (head Int) (tail List)) (nil))))
diff --git a/test/regress/regress0/sygus/dup-op.sy b/test/regress/regress0/sygus/dup-op.sy
index e5448d626..bed9972fd 100644
--- a/test/regress/regress0/sygus/dup-op.sy
+++ b/test/regress/regress0/sygus/dup-op.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi --no-cegqi-si --no-dump-synth
+; COMMAND-LINE: --cegqi-si=none --no-dump-synth
(set-logic LIA)
(synth-fun f ((x Int)) Int
((Start Int ((+ Con Con) (+ Start Start) x))
diff --git a/test/regress/regress0/sygus/enum-test.sy b/test/regress/regress0/sygus/enum-test.sy
index cd129385e..7b59f5f1a 100644
--- a/test/regress/regress0/sygus/enum-test.sy
+++ b/test/regress/regress0/sygus/enum-test.sy
@@ -1,8 +1,8 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi-si --no-dump-synth
+; COMMAND-LINE: --cegqi-si=all --no-dump-synth
(set-logic LIA)
(define-sort D (Enum (a b)))
(define-fun f ((x D)) Int (ite (= x D::a) 3 7))
(synth-fun g () D ((Start D (D::a D::b))))
(constraint (= (f g) 7))
-(check-synth) \ No newline at end of file
+(check-synth)
diff --git a/test/regress/regress0/sygus/hd-sdiv.sy b/test/regress/regress0/sygus/hd-sdiv.sy
new file mode 100644
index 000000000..019b48a1c
--- /dev/null
+++ b/test/regress/regress0/sygus/hd-sdiv.sy
@@ -0,0 +1,16 @@
+; EXPECT: unsat
+; COMMAND-LINE: --cegqi-si=none --no-dump-synth
+(set-logic BV)
+
+(define-fun hd01 ((x (BitVec 32))) (BitVec 32) (bvand x #x00000001))
+
+(synth-fun f ((x (BitVec 32))) (BitVec 32)
+ ((Start (BitVec 32) ((bvsdiv Start Start)
+ (bvand Start Start)
+ x
+ #x00000001))))
+
+(declare-var y (BitVec 32))
+(constraint (= (hd01 y) (f y)))
+(check-synth)
+
diff --git a/test/regress/regress0/sygus/icfp_28_10.sy b/test/regress/regress0/sygus/icfp_28_10.sy
index b07be0e98..74e054159 100644
--- a/test/regress/regress0/sygus/icfp_28_10.sy
+++ b/test/regress/regress0/sygus/icfp_28_10.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi --no-dump-synth
+; COMMAND-LINE: --no-dump-synth
(set-logic BV)
diff --git a/test/regress/regress0/sygus/inv-example.sy b/test/regress/regress0/sygus/inv-example.sy
index aafbbd987..b56425964 100644
--- a/test/regress/regress0/sygus/inv-example.sy
+++ b/test/regress/regress0/sygus/inv-example.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi-si --no-dump-synth
+; COMMAND-LINE: --no-dump-synth
(set-logic LIA)
(synth-inv inv-f ((x Int) (y Int) (b Bool)))
(declare-primed-var x Int)
@@ -9,4 +9,4 @@
(define-fun trans-f ((x Int) (y Int) (b Bool) (x! Int) (y! Int) (b! Bool)) Bool (and (and (= b! b) (= y! x)) (ite b (= x! (+ x 10)) (= x! (+ x 12)))))
(define-fun post-f ((x Int) (y Int) (b Bool)) Bool (<= y x))
(inv-constraint inv-f pre-f trans-f post-f)
-(check-synth) \ No newline at end of file
+(check-synth)
diff --git a/test/regress/regress0/sygus/let-ringer.sy b/test/regress/regress0/sygus/let-ringer.sy
index 4bae90b00..d5d40ace4 100644
--- a/test/regress/regress0/sygus/let-ringer.sy
+++ b/test/regress/regress0/sygus/let-ringer.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi-si --no-dump-synth
+; COMMAND-LINE: --cegqi-si=all --no-dump-synth
(set-logic LIA)
(define-fun g ((x Int)) Int (ite (= x 1) 15 19))
(synth-fun f ((x Int)) Int
diff --git a/test/regress/regress0/sygus/let-simp.sy b/test/regress/regress0/sygus/let-simp.sy
index 71cd27e8f..d07f6a717 100644
--- a/test/regress/regress0/sygus/let-simp.sy
+++ b/test/regress/regress0/sygus/let-simp.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi-si --no-dump-synth
+; COMMAND-LINE: --cegqi-si=all --no-dump-synth
(set-logic LIA)
(synth-fun f ((x Int) (y Int)) Int
((Start Int (x
diff --git a/test/regress/regress0/sygus/list-head-x.sy b/test/regress/regress0/sygus/list-head-x.sy
index a5977d1e7..21362dc2c 100644
--- a/test/regress/regress0/sygus/list-head-x.sy
+++ b/test/regress/regress0/sygus/list-head-x.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi-si --no-dump-synth
+; COMMAND-LINE: --cegqi-si=all --no-dump-synth
(set-logic ALL_SUPPORTED)
(declare-datatypes () ((List (cons (head Int) (tail List)) (nil))))
diff --git a/test/regress/regress0/sygus/max.sy b/test/regress/regress0/sygus/max.sy
index dec4594d7..e6e3de5fc 100644
--- a/test/regress/regress0/sygus/max.sy
+++ b/test/regress/regress0/sygus/max.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi-si --no-dump-synth
+; COMMAND-LINE: --cegqi-si=all --no-dump-synth
(set-logic LIA)
(synth-fun max ((x Int) (y Int)) Int
diff --git a/test/regress/regress0/sygus/max2-univ.sy b/test/regress/regress0/sygus/max2-univ.sy
index 3f8aac3b2..927148d81 100644
--- a/test/regress/regress0/sygus/max2-univ.sy
+++ b/test/regress/regress0/sygus/max2-univ.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi --no-dump-synth
+; COMMAND-LINE: --no-dump-synth
; Synthesize the maximum of 2 integers, but property has 4 variables (requires 2 passes)
(set-logic LIA)
(synth-fun max2 ((x Int) (y Int)) Int)
diff --git a/test/regress/regress0/sygus/multi-fun-polynomial2.sy b/test/regress/regress0/sygus/multi-fun-polynomial2.sy
index 6d185ba3f..c238de5dd 100644
--- a/test/regress/regress0/sygus/multi-fun-polynomial2.sy
+++ b/test/regress/regress0/sygus/multi-fun-polynomial2.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi --no-dump-synth
+; COMMAND-LINE: --no-dump-synth
(set-logic LIA)
@@ -32,4 +32,4 @@
(check-synth)
-; (x, y), (x-y, 0) ... are valid solutions \ No newline at end of file
+; (x, y), (x-y, 0) ... are valid solutions
diff --git a/test/regress/regress0/sygus/nflat-fwd-3.sy b/test/regress/regress0/sygus/nflat-fwd-3.sy
index 9065a1025..d3624a731 100644
--- a/test/regress/regress0/sygus/nflat-fwd-3.sy
+++ b/test/regress/regress0/sygus/nflat-fwd-3.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi-si --no-dump-synth
+; COMMAND-LINE: --no-dump-synth
(set-logic LIA)
(synth-fun f ((x Int)) Int
((Start Int ((+ (+ Con Con) Con) x))
diff --git a/test/regress/regress0/sygus/nflat-fwd.sy b/test/regress/regress0/sygus/nflat-fwd.sy
index d211d475b..3f15d5915 100644
--- a/test/regress/regress0/sygus/nflat-fwd.sy
+++ b/test/regress/regress0/sygus/nflat-fwd.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi --no-dump-synth
+; COMMAND-LINE: --no-dump-synth
(set-logic LIA)
(synth-fun f ((x Int)) Int
((Start Int ((+ Con Con) (+ (+ Start Start) Con) x))
diff --git a/test/regress/regress0/sygus/no-flat-simp.sy b/test/regress/regress0/sygus/no-flat-simp.sy
index cb284b180..af1284f13 100644
--- a/test/regress/regress0/sygus/no-flat-simp.sy
+++ b/test/regress/regress0/sygus/no-flat-simp.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi-si --no-dump-synth
+; COMMAND-LINE: --no-dump-synth
(set-logic LIA)
diff --git a/test/regress/regress0/sygus/no-mention.sy b/test/regress/regress0/sygus/no-mention.sy
index 05dfbced3..60efc1b74 100644
--- a/test/regress/regress0/sygus/no-mention.sy
+++ b/test/regress/regress0/sygus/no-mention.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi --no-dump-synth
+; COMMAND-LINE: --no-dump-synth
(set-logic LIA)
(synth-fun p ((x Int) (y Int)) Int)
diff --git a/test/regress/regress0/sygus/no-syntax-test-bool.sy b/test/regress/regress0/sygus/no-syntax-test-bool.sy
index 4b3fa22e6..ee27b30eb 100644
--- a/test/regress/regress0/sygus/no-syntax-test-bool.sy
+++ b/test/regress/regress0/sygus/no-syntax-test-bool.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi-si --no-dump-synth
+; COMMAND-LINE: --no-dump-synth
(set-logic LIA)
diff --git a/test/regress/regress0/sygus/no-syntax-test-no-si.sy b/test/regress/regress0/sygus/no-syntax-test-no-si.sy
index 86b60638b..bd8da1900 100644
--- a/test/regress/regress0/sygus/no-syntax-test-no-si.sy
+++ b/test/regress/regress0/sygus/no-syntax-test-no-si.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi --no-dump-synth
+; COMMAND-LINE: --no-dump-synth
(set-logic LIA)
diff --git a/test/regress/regress0/sygus/no-syntax-test.sy b/test/regress/regress0/sygus/no-syntax-test.sy
index b95f31aa7..2b3d5f3e9 100644
--- a/test/regress/regress0/sygus/no-syntax-test.sy
+++ b/test/regress/regress0/sygus/no-syntax-test.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi-si --no-dump-synth
+; COMMAND-LINE: --no-dump-synth
(set-logic LIA)
diff --git a/test/regress/regress0/sygus/parity-AIG-d0.sy b/test/regress/regress0/sygus/parity-AIG-d0.sy
index 03d180634..3cc577bd8 100644
--- a/test/regress/regress0/sygus/parity-AIG-d0.sy
+++ b/test/regress/regress0/sygus/parity-AIG-d0.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi-si --no-dump-synth
+; COMMAND-LINE: --cegqi-si=all --no-dump-synth
(set-logic BV)
(define-fun parity ((a Bool) (b Bool) (c Bool) (d Bool)) Bool
@@ -27,4 +27,4 @@
;(not
; (and
; (and (not (and (not a) b)) (not (and d (not c))))
-; (and (not (and (not b) a)) (not (and (not d) c)))))) \ No newline at end of file
+; (and (not (and (not b) a)) (not (and (not d) c))))))
diff --git a/test/regress/regress0/sygus/strings-small.sy b/test/regress/regress0/sygus/strings-small.sy
new file mode 100644
index 000000000..40346bcdf
--- /dev/null
+++ b/test/regress/regress0/sygus/strings-small.sy
@@ -0,0 +1,35 @@
+; EXPECT: unsat
+; COMMAND-LINE: --no-dump-synth
+(set-logic SLIA)
+(synth-fun f ((firstname String) (lastname String)) String
+((Start String (ntString))
+
+(ntString String (
+firstname
+lastname
+" "
+(str.++ ntString ntString)))
+
+(ntInt Int (
+0
+1
+2
+(+ ntInt ntInt)
+(- ntInt ntInt)
+(str.len ntString)
+(str.to.int ntString)
+(str.indexof ntString ntString ntInt)))
+
+(ntBool Bool (
+true
+false
+(str.prefixof ntString ntString)
+(str.suffixof ntString ntString)
+(str.contains ntString ntString)))
+
+))
+
+(constraint (= (f "Nancy" "FreeHafer") "Nancy FreeHafer"))
+
+(check-synth)
+
diff --git a/test/regress/regress0/sygus/strings-unconstrained.sy b/test/regress/regress0/sygus/strings-unconstrained.sy
new file mode 100644
index 000000000..38e69e337
--- /dev/null
+++ b/test/regress/regress0/sygus/strings-unconstrained.sy
@@ -0,0 +1,15 @@
+; EXPECT: unsat
+; COMMAND-LINE: --no-dump-synth
+(set-logic SLIA)
+(synth-fun f ((firstname String) (lastname String)) String
+((Start String (ntString))
+
+(ntString String (
+firstname
+lastname
+" "
+(str.++ ntString ntString)))
+))
+
+(check-synth)
+
diff --git a/test/regress/regress0/sygus/sygus-dt.sy b/test/regress/regress0/sygus/sygus-dt.sy
index e842477e8..be6749139 100644
--- a/test/regress/regress0/sygus/sygus-dt.sy
+++ b/test/regress/regress0/sygus/sygus-dt.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi --no-dump-synth
+; COMMAND-LINE: --no-dump-synth
(set-logic LIA)
@@ -13,4 +13,4 @@
(declare-var x Int)
(constraint (= (f x) (cons x nil)))
-(check-synth) \ No newline at end of file
+(check-synth)
diff --git a/test/regress/regress0/sygus/tl-type.sy b/test/regress/regress0/sygus/tl-type.sy
index 1545f86cd..a6980425a 100644
--- a/test/regress/regress0/sygus/tl-type.sy
+++ b/test/regress/regress0/sygus/tl-type.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi --no-cegqi-si --no-dump-synth
+; COMMAND-LINE: --cegqi-si=none --no-dump-synth
(set-logic LIA)
(synth-fun f ((x Int)) Int
((Start Int (Term (+ Start Start)))
diff --git a/test/regress/regress0/sygus/twolets1.sy b/test/regress/regress0/sygus/twolets1.sy
index 7f84ce06c..b016872b4 100644
--- a/test/regress/regress0/sygus/twolets1.sy
+++ b/test/regress/regress0/sygus/twolets1.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi-si --no-dump-synth
+; COMMAND-LINE: --cegqi-si=all --no-dump-synth
(set-logic LIA)
;; f1 is x plus 2 ;; f2 is 2x plus 5
diff --git a/test/regress/regress0/sygus/twolets2-orig.sy b/test/regress/regress0/sygus/twolets2-orig.sy
index 91bab5ece..70d1ffa02 100644
--- a/test/regress/regress0/sygus/twolets2-orig.sy
+++ b/test/regress/regress0/sygus/twolets2-orig.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi-si --no-dump-synth
+; COMMAND-LINE: --cegqi-si=all --no-dump-synth
(set-logic LIA)
(synth-fun f1 ((x Int)) Int
(
diff --git a/test/regress/regress0/sygus/uminus_one.sy b/test/regress/regress0/sygus/uminus_one.sy
index 9886f6a7b..e98be942b 100644
--- a/test/regress/regress0/sygus/uminus_one.sy
+++ b/test/regress/regress0/sygus/uminus_one.sy
@@ -1,7 +1,7 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi --no-dump-synth
+; COMMAND-LINE: --no-dump-synth
(set-logic LIA)
(synth-fun f ((x Int)) Int ((Start Int ((- 1)))))
(declare-var x Int)
(constraint (= (f x) (- 1)))
-(check-synth) \ No newline at end of file
+(check-synth)
diff --git a/test/regress/regress0/sygus/unbdd_inv_gen_winf1.sy b/test/regress/regress0/sygus/unbdd_inv_gen_winf1.sy
index 7c9d6c601..300b6b65c 100644
--- a/test/regress/regress0/sygus/unbdd_inv_gen_winf1.sy
+++ b/test/regress/regress0/sygus/unbdd_inv_gen_winf1.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --cegqi --no-dump-synth
+; COMMAND-LINE: --no-dump-synth
(set-logic LIA)
(synth-fun inv ((x Int)) Bool
diff --git a/test/unit/prop/cnf_stream_white.h b/test/unit/prop/cnf_stream_white.h
index bf28e5996..98417c492 100644
--- a/test/unit/prop/cnf_stream_white.h
+++ b/test/unit/prop/cnf_stream_white.h
@@ -69,6 +69,14 @@ public:
return ClauseIdUndef;
}
+ ClauseId addXorClause(SatClause& clause, bool rhs, bool removable) {
+ d_addClauseCalled = true;
+ return ClauseIdUndef;
+ }
+
+ bool nativeXor() { return false; }
+
+
void reset() {
d_addClauseCalled = false;
}
diff --git a/test/unit/theory/logic_info_white.h b/test/unit/theory/logic_info_white.h
index 6332563ed..3baa43dff 100644
--- a/test/unit/theory/logic_info_white.h
+++ b/test/unit/theory/logic_info_white.h
@@ -514,13 +514,13 @@ public:
info.arithOnlyLinear();
info.disableIntegers();
info.lock();
- TS_ASSERT_EQUALS( info.getLogicString(), "AUFBVFPDTLRA" );
+ TS_ASSERT_EQUALS( info.getLogicString(), "AUFBVFPDTLRASEP" );
info = info.getUnlockedCopy();
TS_ASSERT( !info.isLocked() );
info.disableQuantifiers();
info.lock();
- TS_ASSERT_EQUALS( info.getLogicString(), "QF_AUFBVFPDTLRA" );
+ TS_ASSERT_EQUALS( info.getLogicString(), "QF_AUFBVFPDTLRASEP" );
info = info.getUnlockedCopy();
TS_ASSERT( !info.isLocked() );
@@ -529,13 +529,14 @@ public:
info.enableIntegers();
info.disableReals();
info.lock();
- TS_ASSERT_EQUALS( info.getLogicString(), "QF_AUFFPLIA" );
+ TS_ASSERT_EQUALS( info.getLogicString(), "QF_AUFFPLIASEP" );
info = info.getUnlockedCopy();
TS_ASSERT( !info.isLocked() );
info.disableTheory(THEORY_ARITH);
info.disableTheory(THEORY_UF);
info.disableTheory(THEORY_FP);
+ info.disableTheory(THEORY_SEP);
info.lock();
TS_ASSERT_EQUALS( info.getLogicString(), "QF_AX" );
TS_ASSERT( info.isPure( THEORY_ARRAY ) );
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback