summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/docs_upload.yml6
-rw-r--r--cmake/version-base.cmake1
-rw-r--r--cmake/version-base.cmake.template1
-rw-r--r--cmake/version.cmake22
-rw-r--r--docs/api/api.rst10
-rw-r--r--docs/api/cpp/Doxyfile.in2
-rw-r--r--docs/api/cpp/cpp.rst3
-rw-r--r--docs/api/java/CMakeLists.txt1
-rw-r--r--docs/api/java/index.rst2
-rw-r--r--docs/api/java/java.rst83
-rw-r--r--docs/api/java/quickstart.rst191
-rw-r--r--docs/api/python/python.rst17
-rw-r--r--docs/api/python/regular/kind.rst8
-rw-r--r--docs/api/python/regular/python.rst4
-rw-r--r--docs/api/python/regular/quickstart.rst2
-rw-r--r--docs/api/python/z3compat/z3compat.rst2
-rw-r--r--docs/conf.py.in1
-rw-r--r--docs/examples/examples.rst1
-rw-r--r--docs/ext/autoenum.py41
-rw-r--r--docs/theories/separation-logic.rst2
-rw-r--r--docs/theories/sets-and-relations.rst4
-rw-r--r--docs/theories/transcendentals.rst1
-rw-r--r--examples/api/java/QuickStart.java31
-rw-r--r--examples/api/java/Relations.java5
-rw-r--r--examples/api/python/bitvectors.py30
-rw-r--r--examples/api/python/bitvectors_and_arrays.py18
-rw-r--r--examples/api/python/combination.py22
-rw-r--r--examples/api/python/datatypes.py18
-rw-r--r--examples/api/python/exceptions.py2
-rw-r--r--examples/api/python/extract.py15
-rw-r--r--examples/api/python/floating_point.py28
-rw-r--r--examples/api/python/helloworld.py2
-rw-r--r--examples/api/python/id.py1
-rw-r--r--examples/api/python/linear_arith.py18
-rw-r--r--examples/api/python/quickstart.py22
-rw-r--r--examples/api/python/sequences.py14
-rw-r--r--examples/api/python/sets.py30
-rw-r--r--examples/api/python/strings.py34
-rw-r--r--examples/api/python/sygus-fun.py26
-rw-r--r--examples/api/python/sygus-grammar.py16
-rw-r--r--examples/api/python/sygus-inv.py14
-rw-r--r--examples/api/python/transcendentals.py14
-rw-r--r--examples/api/python/utils.py4
-rw-r--r--src/CMakeLists.txt8
-rw-r--r--src/api/cpp/cvc5.cpp48
-rw-r--r--src/api/cpp/cvc5.h150
-rw-r--r--src/api/cpp/cvc5_kind.h2
-rw-r--r--src/api/java/genkinds.py.in8
-rw-r--r--src/api/java/io/github/cvc5/api/Datatype.java12
-rw-r--r--src/api/java/io/github/cvc5/api/DatatypeConstructor.java9
-rw-r--r--src/api/java/io/github/cvc5/api/Solver.java18
-rw-r--r--src/api/java/io/github/cvc5/api/Sort.java8
-rw-r--r--src/api/java/io/github/cvc5/api/Term.java15
-rw-r--r--src/api/java/jni/datatype.cpp22
-rw-r--r--src/api/java/jni/datatype_constructor.cpp6
-rw-r--r--src/api/parsekinds.py26
-rw-r--r--src/api/python/CMakeLists.txt1
-rw-r--r--src/api/python/__init__.py.in2
-rw-r--r--src/api/python/cvc5.pxd3
-rw-r--r--src/api/python/cvc5.pxi130
-rw-r--r--src/api/python/genkinds.py.in108
-rw-r--r--src/base/CMakeLists.txt1
-rw-r--r--src/base/output.h92
-rw-r--r--src/base/versioninfo.cpp.in2
-rw-r--r--src/expr/bound_var_manager.cpp2
-rw-r--r--src/expr/dtype.cpp2
-rw-r--r--src/expr/dtype_cons.cpp18
-rw-r--r--src/expr/dtype_cons.h8
-rw-r--r--src/expr/nary_term_util.cpp4
-rw-r--r--src/expr/node_manager.h6
-rw-r--r--src/expr/node_manager_template.cpp11
-rw-r--r--src/expr/sequence.cpp4
-rw-r--r--src/expr/skolem_manager.cpp6
-rw-r--r--src/expr/skolem_manager.h6
-rw-r--r--src/expr/term_context.cpp2
-rw-r--r--src/expr/term_context_node.cpp2
-rw-r--r--src/expr/term_context_node.h2
-rw-r--r--src/options/README.md56
-rw-r--r--src/options/arith_options.toml8
-rw-r--r--src/options/base_options.toml21
-rw-r--r--src/options/managed_streams.cpp14
-rw-r--r--src/options/managed_streams.h8
-rw-r--r--src/options/mkoptions.py76
-rw-r--r--src/options/module_template.h2
-rw-r--r--src/options/options_handler.cpp53
-rw-r--r--src/options/options_handler.h7
-rw-r--r--src/options/options_public_template.cpp2
-rw-r--r--src/options/proof_options.toml16
-rw-r--r--src/options/smt_options.toml3
-rw-r--r--src/options/strings_options.toml18
-rw-r--r--src/parser/parser.cpp2
-rw-r--r--src/parser/smt2/Smt2.g19
-rw-r--r--src/preprocessing/passes/apply_substs.cpp5
-rw-r--r--src/preprocessing/passes/bv_to_int.cpp1034
-rw-r--r--src/preprocessing/passes/bv_to_int.h261
-rw-r--r--src/preprocessing/passes/int_to_bv.cpp26
-rw-r--r--src/preprocessing/passes/learned_rewrite.cpp2
-rw-r--r--src/preprocessing/passes/miplib_trick.cpp41
-rw-r--r--src/preprocessing/passes/non_clausal_simp.cpp14
-rw-r--r--src/preprocessing/passes/pseudo_boolean_processor.cpp7
-rw-r--r--src/preprocessing/passes/real_to_int.cpp16
-rw-r--r--src/preprocessing/passes/sygus_inference.cpp7
-rw-r--r--src/preprocessing/passes/unconstrained_simplifier.cpp4
-rw-r--r--src/proof/alethe/alethe_post_processor.cpp339
-rw-r--r--src/proof/annotation_proof_generator.cpp87
-rw-r--r--src/proof/annotation_proof_generator.h102
-rw-r--r--src/proof/lazy_proof_chain.cpp44
-rw-r--r--src/proof/lazy_proof_chain.h18
-rw-r--r--src/proof/lfsc/lfsc_node_converter.cpp59
-rw-r--r--src/proof/lfsc/lfsc_util.cpp4
-rw-r--r--src/proof/method_id.cpp4
-rw-r--r--src/proof/proof_checker.cpp4
-rw-r--r--src/proof/proof_node_manager.cpp12
-rw-r--r--src/proof/proof_node_manager.h7
-rw-r--r--src/proof/proof_node_to_sexpr.cpp6
-rw-r--r--src/proof/proof_rule.cpp1
-rw-r--r--src/proof/proof_rule.h8
-rw-r--r--src/proof/unsat_core.cpp3
-rw-r--r--src/prop/minisat/core/Solver.cc18
-rw-r--r--src/prop/minisat/core/Solver.h10
-rw-r--r--src/prop/minisat/minisat.cpp3
-rw-r--r--src/prop/minisat/simp/SimpSolver.cc31
-rw-r--r--src/prop/minisat/simp/SimpSolver.h3
-rw-r--r--src/prop/proof_cnf_stream.cpp8
-rw-r--r--src/prop/prop_engine.cpp28
-rw-r--r--src/prop/prop_engine.h8
-rw-r--r--src/prop/theory_proxy.cpp14
-rw-r--r--src/prop/theory_proxy.h12
-rw-r--r--src/smt/abduction_solver.cpp10
-rw-r--r--src/smt/abstract_values.h6
-rw-r--r--src/smt/check_models.cpp2
-rw-r--r--src/smt/difficulty_post_processor.cpp2
-rw-r--r--src/smt/interpolation_solver.cpp1
-rw-r--r--src/smt/model.cpp3
-rw-r--r--src/smt/preprocessor.cpp4
-rw-r--r--src/smt/proof_final_callback.cpp30
-rw-r--r--src/smt/proof_final_callback.h5
-rw-r--r--src/smt/proof_manager.cpp23
-rw-r--r--src/smt/proof_post_processor.cpp9
-rw-r--r--src/smt/set_defaults.cpp9
-rw-r--r--src/smt/smt_solver.cpp8
-rw-r--r--src/smt/solver_engine.cpp23
-rw-r--r--src/smt/solver_engine.h16
-rw-r--r--src/smt/sygus_solver.cpp315
-rw-r--r--src/smt/sygus_solver.h98
-rw-r--r--src/theory/arith/arith_msum.cpp78
-rw-r--r--src/theory/arith/arith_msum.h13
-rw-r--r--src/theory/arith/arith_rewriter.cpp11
-rw-r--r--src/theory/arith/bound_inference.cpp35
-rw-r--r--src/theory/arith/bound_inference.h6
-rw-r--r--src/theory/arith/constraint.cpp3
-rw-r--r--src/theory/arith/infer_bounds.cpp4
-rw-r--r--src/theory/arith/nl/cad/cdcac.cpp49
-rw-r--r--src/theory/arith/nl/cad/cdcac.h15
-rw-r--r--src/theory/arith/nl/cad/lazard_evaluation.cpp48
-rw-r--r--src/theory/arith/nl/cad/lazard_evaluation.h5
-rw-r--r--src/theory/arith/nl/cad_solver.cpp53
-rw-r--r--src/theory/arith/nl/cad_solver.h4
-rw-r--r--src/theory/arith/nl/equality_substitution.cpp183
-rw-r--r--src/theory/arith/nl/equality_substitution.h102
-rw-r--r--src/theory/arith/nl/ext/factoring_check.cpp4
-rw-r--r--src/theory/arith/nl/ext/monomial.cpp1
-rw-r--r--src/theory/arith/nl/iand_solver.cpp16
-rw-r--r--src/theory/arith/nl/iand_solver.h4
-rw-r--r--src/theory/arith/nl/iand_utils.cpp37
-rw-r--r--src/theory/arith/nl/icp/icp_solver.cpp2
-rw-r--r--src/theory/arith/nl/icp/icp_solver.h4
-rw-r--r--src/theory/arith/nl/nl_model.cpp28
-rw-r--r--src/theory/arith/nl/nl_model.h5
-rw-r--r--src/theory/arith/nl/nonlinear_extension.cpp81
-rw-r--r--src/theory/arith/nl/pow2_solver.cpp9
-rw-r--r--src/theory/arith/nl/pow2_solver.h2
-rw-r--r--src/theory/arith/nl/strategy.cpp5
-rw-r--r--src/theory/arith/nl/transcendental/exponential_solver.cpp2
-rw-r--r--src/theory/arith/nl/transcendental/proof_checker.cpp127
-rw-r--r--src/theory/arith/nl/transcendental/sine_solver.cpp36
-rw-r--r--src/theory/arith/nl/transcendental/taylor_generator.cpp62
-rw-r--r--src/theory/arith/nl/transcendental/taylor_generator.h1
-rw-r--r--src/theory/arith/nl/transcendental/transcendental_solver.cpp6
-rw-r--r--src/theory/arith/nl/transcendental/transcendental_state.cpp79
-rw-r--r--src/theory/arith/nl/transcendental/transcendental_state.h6
-rw-r--r--src/theory/arith/operator_elim.cpp85
-rw-r--r--src/theory/arith/proof_checker.cpp21
-rw-r--r--src/theory/arith/theory_arith_private.cpp14
-rw-r--r--src/theory/arith/theory_arith_private.h34
-rw-r--r--src/theory/bags/bag_reduction.cpp104
-rw-r--r--src/theory/bags/bag_reduction.h54
-rw-r--r--src/theory/bags/bag_solver.cpp25
-rw-r--r--src/theory/bags/bags_rewriter.cpp4
-rw-r--r--src/theory/bags/inference_generator.cpp4
-rw-r--r--src/theory/bags/normal_form.cpp14
-rw-r--r--src/theory/bags/solver_state.cpp2
-rw-r--r--src/theory/bags/theory_bags.cpp51
-rw-r--r--src/theory/bags/theory_bags.h2
-rw-r--r--src/theory/bags/theory_bags_type_enumerator.cpp2
-rw-r--r--src/theory/booleans/proof_circuit_propagator.cpp12
-rw-r--r--src/theory/builtin/proof_checker.cpp10
-rw-r--r--src/theory/bv/int_blaster.cpp105
-rw-r--r--src/theory/bv/int_blaster.h9
-rw-r--r--src/theory/bv/theory_bv_rewrite_rules_operator_elimination.h78
-rw-r--r--src/theory/bv/theory_bv_utils.cpp16
-rw-r--r--src/theory/datatypes/datatypes_rewriter.cpp21
-rw-r--r--src/theory/datatypes/infer_proof_cons.cpp4
-rw-r--r--src/theory/datatypes/kinds4
-rw-r--r--src/theory/datatypes/sygus_extension.cpp12
-rw-r--r--src/theory/datatypes/sygus_simple_sym.cpp4
-rw-r--r--src/theory/datatypes/theory_datatypes.cpp4
-rw-r--r--src/theory/datatypes/theory_datatypes_type_rules.cpp56
-rw-r--r--src/theory/datatypes/theory_datatypes_type_rules.h7
-rw-r--r--src/theory/datatypes/theory_datatypes_utils.cpp7
-rw-r--r--src/theory/datatypes/type_enumerator.cpp8
-rw-r--r--src/theory/difficulty_manager.cpp28
-rw-r--r--src/theory/difficulty_manager.h16
-rw-r--r--src/theory/evaluator.cpp23
-rw-r--r--src/theory/ext_theory.h2
-rw-r--r--src/theory/fp/fp_word_blaster.h18
-rw-r--r--src/theory/incomplete_id.cpp2
-rw-r--r--src/theory/incomplete_id.h3
-rw-r--r--src/theory/inference_id.cpp16
-rw-r--r--src/theory/inference_id.h13
-rw-r--r--src/theory/inference_id_proof_annotator.cpp55
-rw-r--r--src/theory/inference_id_proof_annotator.h64
-rw-r--r--src/theory/inference_manager_buffered.cpp4
-rw-r--r--src/theory/inference_manager_buffered.h5
-rw-r--r--src/theory/quantifiers/cegqi/ceg_arith_instantiator.cpp11
-rw-r--r--src/theory/quantifiers/cegqi/ceg_arith_instantiator.h2
-rw-r--r--src/theory/quantifiers/cegqi/ceg_instantiator.cpp16
-rw-r--r--src/theory/quantifiers/cegqi/inst_strategy_cegqi.cpp13
-rw-r--r--src/theory/quantifiers/cegqi/vts_term_cache.cpp23
-rw-r--r--src/theory/quantifiers/cegqi/vts_term_cache.h8
-rw-r--r--src/theory/quantifiers/ematching/pattern_term_selector.cpp6
-rw-r--r--src/theory/quantifiers/extended_rewrite.cpp10
-rw-r--r--src/theory/quantifiers/extended_rewrite.h2
-rw-r--r--src/theory/quantifiers/fmf/bounded_integers.cpp26
-rw-r--r--src/theory/quantifiers/fmf/full_model_check.cpp5
-rw-r--r--src/theory/quantifiers/instantiation_list.cpp7
-rw-r--r--src/theory/quantifiers/quant_bound_inference.cpp5
-rw-r--r--src/theory/quantifiers/quant_conflict_find.cpp34
-rw-r--r--src/theory/quantifiers/quant_conflict_find.h7
-rw-r--r--src/theory/quantifiers/quant_split.cpp2
-rw-r--r--src/theory/quantifiers/quantifiers_rewriter.cpp14
-rw-r--r--src/theory/quantifiers/query_generator_unsat.cpp7
-rw-r--r--src/theory/quantifiers/relevant_domain.cpp10
-rw-r--r--src/theory/quantifiers/single_inv_partition.cpp3
-rw-r--r--src/theory/quantifiers/skolemize.cpp12
-rw-r--r--src/theory/quantifiers/sygus/cegis_unif.cpp6
-rw-r--r--src/theory/quantifiers/sygus/sygus_abduct.cpp3
-rw-r--r--src/theory/quantifiers/sygus/sygus_enumerator.cpp2
-rw-r--r--src/theory/quantifiers/sygus/sygus_grammar_cons.cpp20
-rw-r--r--src/theory/quantifiers/sygus/sygus_process_conj.cpp12
-rw-r--r--src/theory/quantifiers/sygus/sygus_process_conj.h9
-rw-r--r--src/theory/quantifiers/sygus/synth_conjecture.cpp27
-rw-r--r--src/theory/quantifiers/sygus/synth_verify.cpp2
-rw-r--r--src/theory/quantifiers/sygus/template_infer.cpp6
-rw-r--r--src/theory/quantifiers/sygus_sampler.cpp6
-rw-r--r--src/theory/quantifiers/term_util.cpp2
-rw-r--r--src/theory/relevance_manager.cpp224
-rw-r--r--src/theory/relevance_manager.h75
-rw-r--r--src/theory/sets/cardinality_extension.cpp8
-rw-r--r--src/theory/sets/theory_sets_private.cpp4
-rw-r--r--src/theory/sets/theory_sets_rewriter.cpp7
-rw-r--r--src/theory/sort_inference.cpp16
-rw-r--r--src/theory/strings/arith_entail.cpp34
-rw-r--r--src/theory/strings/array_core_solver.cpp300
-rw-r--r--src/theory/strings/array_core_solver.h146
-rw-r--r--src/theory/strings/array_solver.cpp39
-rw-r--r--src/theory/strings/array_solver.h29
-rw-r--r--src/theory/strings/base_solver.cpp7
-rw-r--r--src/theory/strings/core_solver.cpp18
-rw-r--r--src/theory/strings/eager_solver.cpp7
-rw-r--r--src/theory/strings/infer_proof_cons.cpp6
-rw-r--r--src/theory/strings/inference_manager.cpp4
-rw-r--r--src/theory/strings/proof_checker.cpp10
-rw-r--r--src/theory/strings/regexp_elim.cpp27
-rw-r--r--src/theory/strings/regexp_entail.cpp14
-rw-r--r--src/theory/strings/regexp_operation.cpp18
-rw-r--r--src/theory/strings/rewrites.cpp2
-rw-r--r--src/theory/strings/rewrites.h4
-rw-r--r--src/theory/strings/sequences_rewriter.cpp87
-rw-r--r--src/theory/strings/skolem_cache.cpp13
-rw-r--r--src/theory/strings/solver_state.cpp2
-rw-r--r--src/theory/strings/strategy.cpp20
-rw-r--r--src/theory/strings/strategy.h4
-rw-r--r--src/theory/strings/strings_entail.cpp8
-rw-r--r--src/theory/strings/strings_fmf.cpp3
-rw-r--r--src/theory/strings/strings_rewriter.cpp17
-rw-r--r--src/theory/strings/term_registry.cpp38
-rw-r--r--src/theory/strings/theory_strings.cpp14
-rw-r--r--src/theory/strings/theory_strings_preprocess.cpp23
-rw-r--r--src/theory/strings/theory_strings_utils.cpp3
-rw-r--r--src/theory/substitutions.cpp27
-rw-r--r--src/theory/substitutions.h17
-rw-r--r--src/theory/theory_engine.cpp38
-rw-r--r--src/theory/theory_engine.h10
-rw-r--r--src/theory/theory_inference_manager.cpp54
-rw-r--r--src/theory/theory_inference_manager.h14
-rw-r--r--src/theory/theory_model.cpp1
-rw-r--r--src/theory/theory_model_builder.cpp5
-rw-r--r--src/theory/trust_substitutions.cpp8
-rw-r--r--src/theory/trust_substitutions.h7
-rw-r--r--src/theory/uf/cardinality_extension.cpp21
-rw-r--r--src/theory/uf/cardinality_extension.h5
-rw-r--r--src/theory/uf/proof_equality_engine.cpp5
-rw-r--r--src/theory/uf/proof_equality_engine.h3
-rw-r--r--src/theory/uf/theory_uf_model.cpp21
-rw-r--r--src/theory/uf/theory_uf_model.h15
-rw-r--r--src/util/didyoumean.cpp6
-rw-r--r--src/util/hash.h5
-rw-r--r--src/util/integer_cln_imp.cpp57
-rw-r--r--src/util/integer_cln_imp.h12
-rw-r--r--src/util/integer_gmp_imp.cpp97
-rw-r--r--src/util/integer_gmp_imp.h16
-rw-r--r--src/util/string.cpp15
-rw-r--r--src/util/string.h11
-rw-r--r--test/api/cpp/CMakeLists.txt2
-rw-r--r--test/api/cpp/proj-issue344.cpp33
-rw-r--r--test/api/cpp/proj-issue345.cpp34
-rw-r--r--test/api/cpp/sep_log_api.cpp3
-rw-r--r--test/api/python/issue4889.py8
-rw-r--r--test/api/python/issue5074.py10
-rw-r--r--test/api/python/issue6111.py12
-rw-r--r--test/api/python/proj-issue306.py8
-rw-r--r--test/api/python/reset_assertions.py8
-rw-r--r--test/api/python/sep_log_api.py22
-rw-r--r--test/regress/CMakeLists.txt23
-rw-r--r--test/regress/regress0/arith/issue5219-conflict-rewrite.smt22
-rw-r--r--test/regress/regress0/bv/bv_to_int1.smt21
-rw-r--r--test/regress/regress0/bv/bv_to_int_bvmul2.smt21
-rw-r--r--test/regress/regress0/bv/bv_to_int_bvuf_to_intuf.smt21
-rw-r--r--test/regress/regress0/bv/bv_to_int_bvuf_to_intuf_sorts.smt21
-rw-r--r--test/regress/regress0/bv/bv_to_int_elim_err.smt23
-rw-r--r--test/regress/regress0/bv/bv_to_int_int1.smt211
-rw-r--r--test/regress/regress0/bv/bv_to_int_zext.smt21
-rw-r--r--test/regress/regress0/bv/proj-issue343.smt27
-rw-r--r--test/regress/regress0/datatypes/par-updater-type-rule.smt211
-rw-r--r--test/regress/regress0/datatypes/proj-issue172.smt27
-rw-r--r--test/regress/regress0/difficulty-model-ex.smt222
-rw-r--r--test/regress/regress0/difficulty-simple.smt216
-rw-r--r--test/regress/regress0/options/didyoumean.smt21
-rw-r--r--test/regress/regress0/options/named_muted.smt26
-rw-r--r--test/regress/regress0/sygus/incremental-modify-ex.sy26
-rw-r--r--test/regress/regress1/bags/card1.smt211
-rw-r--r--test/regress/regress1/bags/card2.smt211
-rw-r--r--test/regress/regress1/bags/murxla1.smt26
-rw-r--r--test/regress/regress1/bags/murxla2.smt26
-rw-r--r--test/regress/regress1/difficulty-polarity.smt231
-rw-r--r--test/regress/regress1/nl/cos1-tc.smt22
-rw-r--r--test/regress/regress1/proj-issue175.smt283
-rw-r--r--test/regress/regress1/sets/proj-issue164.smt210
-rw-r--r--test/regress/regress1/sets/proj-issue178.smt210
-rw-r--r--test/regress/regress1/sygus/proj-issue181.smt28
-rw-r--r--test/regress/regress1/sygus/proj-issue183.smt220
-rw-r--r--test/regress/regress1/sygus/proj-issue185.smt212
-rw-r--r--test/regress/regress2/bv_to_int2.smt21
-rw-r--r--test/regress/regress2/bv_to_int_ashr.smt21
-rw-r--r--test/regress/regress2/bv_to_int_bitwise.smt212
-rw-r--r--test/regress/regress2/bv_to_int_bvmul1.smt21
-rw-r--r--test/regress/regress2/bv_to_int_bvuf_to_intuf_smtlib.smt23
-rw-r--r--test/regress/regress2/bv_to_int_inc1.smt21
-rw-r--r--test/regress/regress2/bv_to_int_mask_array_1.smt25
-rw-r--r--test/regress/regress2/bv_to_int_mask_array_2.smt21
-rw-r--r--test/regress/regress2/bv_to_int_mask_array_3.smt21
-rw-r--r--test/regress/regress2/bv_to_int_quantifiers_bvand.smt29
-rw-r--r--test/regress/regress2/bv_to_int_shifts.smt21
-rw-r--r--test/regress/regress2/strings/strings-alpha-card-129.smt2393
-rw-r--r--test/regress/regress2/strings/strings-alpha-card-65.smt2201
-rw-r--r--test/regress/regress2/sygus/multi-udiv.sy2
-rw-r--r--test/regress/regress2/sygus/sets-fun-test.sy2
-rw-r--r--test/regress/regress2/sygus/three.sy2
-rw-r--r--test/regress/regress3/bv_to_int_and_or.smt26
-rw-r--r--test/regress/regress3/bv_to_int_bench_9839.smt2.minimized.smt25
-rw-r--r--test/regress/regress3/bv_to_int_check_bvsgt_bvlshr0_4bit.smt2.minimized.smt26
-rw-r--r--test/regress/regress3/bv_to_int_input_mouser_detect.c.smt2.minimized.smt22
-rw-r--r--test/unit/api/cpp/datatype_api_black.cpp11
-rw-r--r--test/unit/api/cpp/solver_black.cpp175
-rw-r--r--test/unit/api/java/DatatypeTest.java8
-rw-r--r--test/unit/api/java/SolverTest.java12
-rw-r--r--test/unit/api/python/test_datatype_api.py11
-rw-r--r--test/unit/api/python/test_grammar.py2
-rw-r--r--test/unit/api/python/test_op.py82
-rw-r--r--test/unit/api/python/test_result.py1
-rw-r--r--test/unit/api/python/test_solver.py336
-rw-r--r--test/unit/api/python/test_sort.py1
-rw-r--r--test/unit/api/python/test_term.py144
-rw-r--r--test/unit/api/python/test_to_python_obj.py14
-rw-r--r--test/unit/context/cdlist_black.cpp20
-rw-r--r--test/unit/memory.h93
-rw-r--r--test/unit/options/options_black.cpp5
-rw-r--r--test/unit/theory/theory_bv_int_blaster_white.cpp50
-rw-r--r--test/unit/util/integer_black.cpp55
390 files changed, 6246 insertions, 4718 deletions
diff --git a/.github/workflows/docs_upload.yml b/.github/workflows/docs_upload.yml
index 98eb24943..937496d0a 100644
--- a/.github/workflows/docs_upload.yml
+++ b/.github/workflows/docs_upload.yml
@@ -53,6 +53,12 @@ jobs:
- name: Unpack artifact
run: unzip download.zip -d docs-new/
+ - name: Check for broken links
+ continue-on-error: true
+ run: |
+ python3 -m pip install linkchecker
+ linkchecker --check-extern docs-new/index.html
+
- name: Setup Context
run: |
HASH=${{ github.event.workflow_run.head_commit.id }}
diff --git a/cmake/version-base.cmake b/cmake/version-base.cmake
index c3cca6a08..811209a96 100644
--- a/cmake/version-base.cmake
+++ b/cmake/version-base.cmake
@@ -5,7 +5,6 @@ set(CVC5_IS_RELEASE "false")
# These are used in other places in cmake
# If possible, they are updated by version.cmake
set(GIT_BUILD "false")
-set(CVC5_IS_RELEASE "false")
set(CVC5_VERSION "${CVC5_LAST_RELEASE}")
set(CVC5_FULL_VERSION "${CVC5_LAST_RELEASE}")
set(CVC5_GIT_INFO "")
diff --git a/cmake/version-base.cmake.template b/cmake/version-base.cmake.template
index e149ea380..ec31ccd69 100644
--- a/cmake/version-base.cmake.template
+++ b/cmake/version-base.cmake.template
@@ -5,7 +5,6 @@ set(CVC5_IS_RELEASE "{{IS_RELEASE}}")
# These are used in other places in cmake
# If possible, they are updated by version.cmake
set(GIT_BUILD "false")
-set(CVC5_IS_RELEASE "false")
set(CVC5_VERSION "${CVC5_LAST_RELEASE}")
set(CVC5_FULL_VERSION "${CVC5_LAST_RELEASE}")
set(CVC5_GIT_INFO "")
diff --git a/cmake/version.cmake b/cmake/version.cmake
index e6edd528c..183fe213b 100644
--- a/cmake/version.cmake
+++ b/cmake/version.cmake
@@ -25,13 +25,20 @@ if(CMAKE_SCRIPT_MODE_FILE)
else()
# was run within the overall cmake project
# add target to update versioninfo.cpp at build time
- add_custom_target(gen-versioninfo
- BYPRODUCTS
+ add_custom_command(
+ OUTPUT
${CMAKE_BINARY_DIR}/src/base/versioninfo.cpp
COMMAND ${CMAKE_COMMAND}
-DPROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR}
-DCMAKE_BINARY_DIR=${CMAKE_BINARY_DIR}
- -P ${PROJECT_SOURCE_DIR}/cmake/version.cmake)
+ -P ${PROJECT_SOURCE_DIR}/cmake/version.cmake
+ DEPENDS
+ ${PROJECT_SOURCE_DIR}/cmake/version-base.cmake
+ ${PROJECT_SOURCE_DIR}/cmake/version.cmake
+ )
+ add_custom_target(gen-versioninfo
+ DEPENDS ${CMAKE_BINARY_DIR}/src/base/versioninfo.cpp
+ )
endif()
# include basic version information
@@ -112,8 +119,13 @@ if(GIT_FOUND)
list(LENGTH VERSION_LIST VERSION_LIST_LENGTH)
endwhile()
- set(CVC5_VERSION "${GIT_LAST_TAG}-dev")
- set(CVC5_FULL_VERSION "${GIT_LAST_TAG}-dev.${GIT_COMMITS_SINCE_TAG}.${GIT_COMMIT}")
+ if(CVC5_IS_RELEASE)
+ set(CVC5_VERSION "${CVC5_VERSION}-modified")
+ set(CVC5_FULL_VERSION "${CVC5_FULL_VERSION}-modified")
+ else()
+ set(CVC5_VERSION "${GIT_LAST_TAG}-dev")
+ set(CVC5_FULL_VERSION "${GIT_LAST_TAG}-dev.${GIT_COMMITS_SINCE_TAG}.${GIT_COMMIT}")
+ endif()
set(CVC5_GIT_INFO "git ${GIT_COMMIT} on branch ${GIT_BRANCH}${GIT_DIRTY_MSG}")
endif()
endif()
diff --git a/docs/api/api.rst b/docs/api/api.rst
index 727caea4d..3eff4bd1c 100644
--- a/docs/api/api.rst
+++ b/docs/api/api.rst
@@ -3,12 +3,12 @@ API Documentation
In addition to using cvc5 :doc:`as a binary <../binary/binary>`, cvc5 features APIs
for several different programming languages.
-While the :doc:`C++ API <cpp/cpp>` is considered the primary interface to cvc5, both the :doc:`Java API <java/index>` and the :doc:`Python API <python/python>` implement a thin wrapper around it.
-Additionally, a more pythonic Python API is availble at https://github.com/cvc5/cvc5_z3py_compat.
+While the :doc:`C++ API <cpp/cpp>` is considered the primary interface to cvc5, both the :doc:`Java API <java/java>` and the :doc:`Python API <python/python>` implement a thin wrapper around it.
+Additionally, a more pythonic Python API is available at https://github.com/cvc5/cvc5_z3py_compat.
.. toctree::
:maxdepth: 1
- C++ API <cpp/cpp>
- Java API <java/index>
- Python API <python/python>
+ cpp/cpp
+ java/java
+ python/python
diff --git a/docs/api/cpp/Doxyfile.in b/docs/api/cpp/Doxyfile.in
index 75a732ceb..b55c4ec48 100644
--- a/docs/api/cpp/Doxyfile.in
+++ b/docs/api/cpp/Doxyfile.in
@@ -270,6 +270,8 @@ TAB_SIZE = 4
# a double escape (\\{ and \\})
ALIASES =
+ALIASES += "rst=\verbatim embed:rst"
+ALIASES += "endrst=\endverbatim"
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
# only. Doxygen will then generate output that is more tailored for C. For
diff --git a/docs/api/cpp/cpp.rst b/docs/api/cpp/cpp.rst
index 96177e7d8..49548222a 100644
--- a/docs/api/cpp/cpp.rst
+++ b/docs/api/cpp/cpp.rst
@@ -1,4 +1,4 @@
-C++ API Documentation
+C++ API
=====================
The C++ API is the primary interface for cvc5 and exposes the full functionality of cvc5.
@@ -9,7 +9,6 @@ For most applications, the :cpp:class:`Solver <cvc5::api::Solver>` class is the
.. container:: hide-toctree
.. toctree::
- :maxdepth: 0
quickstart
exceptions
diff --git a/docs/api/java/CMakeLists.txt b/docs/api/java/CMakeLists.txt
index 8a728407f..2fcf74767 100644
--- a/docs/api/java/CMakeLists.txt
+++ b/docs/api/java/CMakeLists.txt
@@ -31,6 +31,7 @@ if(BUILD_BINDINGS_JAVA)
-sourcepath ${CMAKE_SOURCE_DIR}/src/api/java/:${CMAKE_BINARY_DIR}/src/api/java/
-d ${JAVADOC_OUTPUT_DIR}
-cp ${CVC5_JAR_FILE}
+ -tag "apiNote:a:Note:"
-notimestamp
COMMAND find ${JAVADOC_OUTPUT_DIR} -type f -exec sed -i'orig' 's/<!-- Generated by javadoc [^>]* -->//' {} "\;"
COMMAND find ${SPHINX_GH_OUTPUT_DIR} -name '*orig' -delete
diff --git a/docs/api/java/index.rst b/docs/api/java/index.rst
index f805880cc..75d81a090 100644
--- a/docs/api/java/index.rst
+++ b/docs/api/java/index.rst
@@ -1,4 +1,4 @@
-Java API Documentation
+Java API
======================
This documentation was built while Java bindings were disabled. This part of the documentation is empty. Please enable :code:`BUILD_BINDINGS_JAVA` in :code:`cmake` and build the documentation again.
diff --git a/docs/api/java/java.rst b/docs/api/java/java.rst
new file mode 100644
index 000000000..725e2bf7c
--- /dev/null
+++ b/docs/api/java/java.rst
@@ -0,0 +1,83 @@
+Java API
+======================
+
+The Java API for cvc5 mostly mirrors the :doc:`C++ API <../cpp/cpp>` and supports operator
+overloading, iterators, and exceptions.
+There are a few differences from the C++ API, such as using arbitrary-precision integer pairs,
+specifically, pairs of Java `BigInteger` objects, to represent rational numbers.
+The :doc:`quickstart guide <quickstart>` gives a short introduction,
+and more examples can be found `here <../../examples/examples.html>`_.
+
+
+For most applications, the `Solver <io/github/cvc5/api/Solver.html>`_ class is the main entry point to cvc5.
+The class hierarchy of `cvc5 package <io/github/cvc5/api/package-summary.html>`_
+provides more details on the individual classes.
+
+.. toctree::
+ :hidden:
+
+ quickstart
+ API documentation <index>
+
+Building cvc5 Java API
+^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: bash
+
+ $ git clone https://github.com/cvc5/cvc5
+ $ cd cvc5
+ $ ./configure.sh production --java-bindings --auto-download --prefix=build/install
+ $ cd build
+ $ make
+ $ make install
+
+ $ ls install/lib
+ cmake libcvc5jni.so libcvc5parser.so libcvc5parser.so.1 libcvc5.so
+ libpicpoly.a libpicpolyxx.a libpoly.so libpoly.so.0 libpoly.so.0.1.9
+ libpolyxx.so libpolyxx.so.0 libpolyxx.so.0.1.9 objects-Production
+ $ ls install/share/java/
+ cvc5-0.0.5-dev.jar cvc5.jar
+
+ # compile example QuickStart.java with cvc5 jar file
+ $ javac -cp "install/share/java/cvc5.jar" ../examples/api/java/QuickStart.java -d .
+
+ # run example QuickStart with cvc5 jar file and cvc5 shared libraries
+ $ java -cp "install/share/java/cvc5.jar:." "-Djava.library.path=install/lib" QuickStart
+ expected: sat
+ result: sat
+ value for x: 1/6
+ value for y: 1/6
+ expected: unsat
+ result: unsat
+ unsat core size: 3
+ unsat core:
+ (< 0 a)
+ (< 0 b)
+ (< (+ a b) 1)
+
+`Package io.github.cvc5.api <io/github/cvc5/api/package-summary.html>`_
+^^^^^^^^^^^^^^^
+
+ * class `Datatype <io/github/cvc5/api/Datatype.html>`_
+ * class `DatatypeConstructor <io/github/cvc5/api/DatatypeConstructor.html>`_
+ * class `DatatypeConstructorDecl <io/github/cvc5/api/DatatypeConstructorDecl.html>`_
+ * class `DatatypeDecl <io/github/cvc5/api/DatatypeDecl.html>`_
+ * class `DatatypeSelector <io/github/cvc5/api/DatatypeSelector.html>`_
+ * class `Grammar <io/github/cvc5/api/Grammar.html>`_
+ * class `Op <io/github/cvc5/api/Op.html>`_
+ * class `OptionInfo <io/github/cvc5/api/OptionInfo.html>`_
+ * class `Pair<K,V> <io/github/cvc5/api/Pair.html>`_
+ * class `Result <io/github/cvc5/api/Result.html>`_
+ * class `Solver <io/github/cvc5/api/Solver.html>`_
+ * class `Sort <io/github/cvc5/api/Sort.html>`_
+ * class `Stat <io/github/cvc5/api/Stat.html>`_
+ * class `Statistics <io/github/cvc5/api/Statistics.html>`_
+ * class `Term <io/github/cvc5/api/Term.html>`_
+ * class `Triplet<A,B,C> <io/github/cvc5/api/Triplet.html>`_
+ * class `Utils <io/github/cvc5/api/Utils.html>`_
+ * enum `Kind <io/github/cvc5/api/Kind.html>`_
+ * enum `Result.UnknownExplanation <io/github/cvc5/api/Result.UnknownExplanation.html>`_
+ * enum `RoundingMode <io/github/cvc5/api/RoundingMode.html>`_
+ * exception `CVC5ApiException <io/github/cvc5/api/CVC5ApiException.html>`_
+ * exception `CVC5ApiOptionException <io/github/cvc5/api/CVC5ApiOptionException.html>`_
+ * exception `CVC5ApiRecoverableException <io/github/cvc5/api/CVC5ApiRecoverableException.html>`_
diff --git a/docs/api/java/quickstart.rst b/docs/api/java/quickstart.rst
new file mode 100644
index 000000000..2c986ab55
--- /dev/null
+++ b/docs/api/java/quickstart.rst
@@ -0,0 +1,191 @@
+Quickstart Guide
+================
+
+First, create a cvc5 `Solver <io/github/cvc5/api/Solver.html>`_
+instance using try with resources:
+
+.. code-block:: java
+
+ try (Solver solver = new Solver())
+ {
+ /** write your code here */
+ }
+
+To produce models and unsat cores, we have to enable the following options.
+
+.. literalinclude:: ../../../examples/api/java/QuickStart.java
+ :language: java
+ :lines: 32-33
+ :dedent: 6
+
+Next we set the logic.
+The simplest way to set a logic for the solver is to choose ``"ALL"``.
+This enables all logics in the solver.
+Alternatively, ``"QF_ALL"`` enables all logics without quantifiers.
+To optimize the solver's behavior for a more specific logic,
+use the logic name, e.g. ``"QF_BV"`` or ``"QF_AUFBV"``.
+
+.. literalinclude:: ../../../examples/api/java/QuickStart.java
+ :language: java
+ :lines: 42
+ :dedent: 6
+
+In the following, we will define real and integer constraints.
+For this, we first query the solver for the corresponding sorts.
+
+.. literalinclude:: ../../../examples/api/java/QuickStart.java
+ :language: java
+ :lines: 46-47
+ :dedent: 6
+
+Now, we create two constants ``x`` and ``y`` of sort ``Real``,
+and two constants ``a`` and ``b`` of sort ``Integer``.
+Notice that these are *symbolic* constants, not actual values.
+
+.. literalinclude:: ../../../examples/api/java/QuickStart.java
+ :language: java
+ :lines: 52-55
+ :dedent: 6
+
+We define the following constraints regarding ``x`` and ``y``:
+
+.. math::
+
+ (0 < x) \wedge (0 < y) \wedge (x + y < 1) \wedge (x \leq y)
+
+We construct the required terms and assert them as follows:
+
+.. literalinclude:: ../../../examples/api/java/QuickStart.java
+ :language: java
+ :lines: 65-89
+ :dedent: 6
+
+Now we check if the asserted formula is satisfiable, that is, we check if
+there exist values of sort ``Real`` for ``x`` and ``y`` that satisfy all
+the constraints.
+
+.. literalinclude:: ../../../examples/api/java/QuickStart.java
+ :language: java
+ :lines: 93
+ :dedent: 6
+
+The result we get from this satisfiability check is either ``sat``, ``unsat``
+or ``unknown``.
+It's status can be queried via
+`Result.isSat <io/github/cvc5/api/Result.html#isSat()>`_,
+`Result.isUnsat <io/github/cvc5/api/Result.html#isUnsat()>`_ and
+`Result.isSatUnknown <io/github/cvc5/api/Result.html#isSatUnknown()>`_.
+Alternatively, it can also be printed.
+
+.. literalinclude:: ../../../examples/api/java/QuickStart.java
+ :language: java
+ :lines: 97-98
+ :dedent: 6
+
+This will print:
+
+.. code:: text
+
+ expected: sat
+ result: sat
+
+Now, we query the solver for the values for ``x`` and ``y`` that satisfy
+the constraints.
+
+.. literalinclude:: ../../../examples/api/java/QuickStart.java
+ :language: java
+ :lines: 101-102
+ :dedent: 6
+
+It is also possible to get values for terms that do not appear in the original
+formula.
+
+.. literalinclude:: ../../../examples/api/java/QuickStart.java
+ :language: java
+ :lines: 106-107
+ :dedent: 6
+
+We can convert these values to Java types.
+
+.. literalinclude:: ../../../examples/api/java/QuickStart.java
+ :language: java
+ :lines: 109-116
+ :dedent: 6
+
+Another way to independently compute the value of ``x - y`` would be to
+perform the (rational) arithmetic manually.
+However, for more complex terms, it is easier to let the solver do the
+evaluation.
+
+.. literalinclude:: ../../../examples/api/java/QuickStart.java
+ :language: java
+ :lines: 122-134
+ :dedent: 6
+
+This will print:
+
+.. code:: text
+
+ computed correctly
+
+Next, we will check satisfiability of the same formula,
+only this time over integer variables ``a`` and ``b``.
+For this, we first reset the assertions added to the solver.
+
+.. literalinclude:: ../../../examples/api/java/QuickStart.java
+ :language: java
+ :lines: 140
+ :dedent: 6
+
+Next, we assert the same assertions as above, but with integers.
+This time, we inline the construction of terms
+in the assertion command.
+
+.. literalinclude:: ../../../examples/api/java/QuickStart.java
+ :language: java
+ :lines: 145-149
+ :dedent: 6
+
+Now, we check whether the revised assertion is satisfiable.
+
+.. literalinclude:: ../../../examples/api/java/QuickStart.java
+ :language: java
+ :lines: 152-156
+ :dedent: 6
+
+This time the asserted formula is unsatisfiable:
+
+.. code:: text
+
+ expected: unsat
+ result: unsat
+
+We can query the solver for an unsatisfiable core, that is, a subset
+of the assertions that is already unsatisfiable.
+
+.. literalinclude:: ../../../examples/api/java/QuickStart.java
+ :language: java
+ :lines: 160-166
+ :dedent: 6
+
+This will print:
+
+.. code:: text
+
+ unsat core size: 3
+ unsat core:
+ (< 0 a)
+ (< 0 b)
+ (< (+ a b) 1)
+
+Example
+-------
+
+| The SMT-LIB input for this example can be found at `examples/api/smtlib/quickstart.smt2 <https://github.com/cvc5/cvc5/blob/master/examples/api/smtlib/quickstart.smt2>`_.
+| The source code for this example can be found at `examples/api/java/QuickStart.java <https://github.com/cvc5/cvc5/blob/master/examples/api/java/QuickStart.java>`_.
+
+.. api-examples::
+ <examples>/api/java/QuickStart.java
+ <examples>/api/cpp/quickstart.cpp
+ <examples>/api/python/quickstart.py
+ <examples>/api/smtlib/quickstart.smt2
diff --git a/docs/api/python/python.rst b/docs/api/python/python.rst
index 3697cf579..b3bd865be 100644
--- a/docs/api/python/python.rst
+++ b/docs/api/python/python.rst
@@ -1,13 +1,6 @@
-Python API Documentation
+Python API
========================
-.. toctree::
- :maxdepth: 1
- :hidden:
-
- z3py compatibility API <z3compat/z3compat>
- regular Python API <regular/python>
-
.. only:: not bindings_python
.. warning::
@@ -16,7 +9,13 @@ Python API Documentation
cvc5 offers two separate APIs for Python users.
The :doc:`regular Python API <regular/python>` is an almost exact copy of the :doc:`C++ API <../cpp/cpp>`.
-Alternatively, the :doc:`z3py compatibility API <z3compat/z3compat>` is a more pythonic API that aims to be fully compatible with `Z3s Python API <https://z3prover.github.io/api/html/namespacez3py.html>`_ while adding functionality that Z3 does not support.
+Alternatively, the :doc:`z3py compatibility Python API <z3compat/z3compat>` is a more pythonic API that aims to be fully compatible with `Z3s Python API <https://z3prover.github.io/api/html/namespacez3py.html>`_ while adding functionality that Z3 does not support.
+
+.. toctree::
+ :maxdepth: 1
+
+ z3compat/z3compat
+ regular/python
Which Python API should I use?
diff --git a/docs/api/python/regular/kind.rst b/docs/api/python/regular/kind.rst
index f2dd8550b..b4be797e0 100644
--- a/docs/api/python/regular/kind.rst
+++ b/docs/api/python/regular/kind.rst
@@ -2,11 +2,11 @@ Kind
================
Every :py:class:`Term <pycvc5.Term>` has a kind which represents its type, for
-example whether it is an equality (:py:obj:`Equal <pycvc5.kinds.Equal>`), a
-conjunction (:py:obj:`And <pycvc5.kinds.And>`), or a bit-vector addtion
-(:py:obj:`BVAdd <pycvc5.kinds.BVAdd>`).
+example whether it is an equality (:py:obj:`Equal <pycvc5.Kind.Equal>`), a
+conjunction (:py:obj:`And <pycvc5.Kind.And>`), or a bit-vector addtion
+(:py:obj:`BVAdd <pycvc5.Kind.BVAdd>`).
The kinds below directly correspond to the enum values of the C++ :cpp:enum:`Kind <cvc5::api::Kind>` enum.
-.. autoclass:: pycvc5.kinds
+.. autoclass:: pycvc5.Kind
:members:
:undoc-members:
diff --git a/docs/api/python/regular/python.rst b/docs/api/python/regular/python.rst
index b054cbe16..84593b17f 100644
--- a/docs/api/python/regular/python.rst
+++ b/docs/api/python/regular/python.rst
@@ -1,4 +1,4 @@
-Python API Documentation
+Regular Python API
========================
.. only:: not bindings_python
@@ -8,7 +8,7 @@ Python API Documentation
This documentation was built while python bindings were disabled. This part of the documentation is likely either empty or outdated. Please enable :code:`BUILD_BINDINGS_PYTHON` in :code:`cmake` and build the documentation again.
.. toctree::
- :maxdepth: 1
+ :maxdepth: 2
quickstart
datatype
diff --git a/docs/api/python/regular/quickstart.rst b/docs/api/python/regular/quickstart.rst
index 783bcfd1f..ba3360db8 100644
--- a/docs/api/python/regular/quickstart.rst
+++ b/docs/api/python/regular/quickstart.rst
@@ -166,7 +166,7 @@ Example
-------
| The SMT-LIB input for this example can be found at `examples/api/smtlib/quickstart.smt2 <https://github.com/cvc5/cvc5/blob/master/examples/api/smtlib/quickstart.smt2>`_.
-| The source code for this example can be found at `examples/api/python/quickstart.py <https://github.com/cvc5/cvc5/blob/master/examples/api/python/quickstart.cpp>`_.
+| The source code for this example can be found at `examples/api/python/quickstart.py <https://github.com/cvc5/cvc5/blob/master/examples/api/python/quickstart.py>`_.
.. api-examples::
<examples>/api/cpp/quickstart.cpp
diff --git a/docs/api/python/z3compat/z3compat.rst b/docs/api/python/z3compat/z3compat.rst
index ad7c8524b..d5a06195d 100644
--- a/docs/api/python/z3compat/z3compat.rst
+++ b/docs/api/python/z3compat/z3compat.rst
@@ -1,4 +1,4 @@
-z3py compatibility API
+z3py compatibility Python API
=========================================
.. only:: not bindings_python
diff --git a/docs/conf.py.in b/docs/conf.py.in
index 453a56aad..37f7adfe8 100644
--- a/docs/conf.py.in
+++ b/docs/conf.py.in
@@ -46,6 +46,7 @@ extensions = [
'sphinxcontrib.bibtex',
'sphinxcontrib.programoutput',
'sphinx_tabs.tabs',
+ 'autoenum',
'examples',
'include_build_file',
]
diff --git a/docs/examples/examples.rst b/docs/examples/examples.rst
index accdd004f..b9303f1d9 100644
--- a/docs/examples/examples.rst
+++ b/docs/examples/examples.rst
@@ -8,7 +8,6 @@ input mechanisms.
.. toctree::
- :maxdepth: 2
helloworld
exceptions
diff --git a/docs/ext/autoenum.py b/docs/ext/autoenum.py
new file mode 100644
index 000000000..9066a6109
--- /dev/null
+++ b/docs/ext/autoenum.py
@@ -0,0 +1,41 @@
+import enum
+from typing import Any, Optional
+
+from docutils.statemachine import StringList
+from sphinx.application import Sphinx
+from sphinx.ext.autodoc import ClassDocumenter, bool_option
+
+
+class EnumDocumenter(ClassDocumenter):
+ """Adds a custom "documenter" for the autodoc extension. This particular
+ documenter is internally used for enum values of a ``enum.Enum`` base class.
+
+ This documenter assumes that the enum class injects proper docstrings into
+ the ``__doc__`` property of every single enum value.
+ """
+
+ objtype = 'enum'
+ directivetype = 'class'
+ priority = 10 + ClassDocumenter.priority
+ option_spec = dict(ClassDocumenter.option_spec)
+
+ @classmethod
+ def can_document_member(cls, member: Any, membername: str, isattr: bool,
+ parent: Any) -> bool:
+ """Document instances of (derived classes of) ``enum.Enum``."""
+ return isinstance(member, enum.Enum)
+
+ def add_content(self,
+ more_content: Optional[StringList],
+ no_docstring: bool = False) -> None:
+ """Add the docstring for this object."""
+
+ # overriding this flag prints __doc__ just as we want to.
+ self.doc_as_attr = False
+ super().add_content(more_content, no_docstring)
+ self.doc_as_attr = True
+
+
+def setup(app: Sphinx) -> None:
+ app.setup_extension('sphinx.ext.autodoc')
+ app.add_autodocumenter(EnumDocumenter)
diff --git a/docs/theories/separation-logic.rst b/docs/theories/separation-logic.rst
index 86f802ef8..36d3a165f 100644
--- a/docs/theories/separation-logic.rst
+++ b/docs/theories/separation-logic.rst
@@ -121,7 +121,7 @@ formula ``(not (emp x 0))`` is satisfied by heaps ``U -> Int`` (the sorts of
(check-sat)
The following input on heaps ``Int -> Node`` is satisfiable, where ``Node``
-denotes a user-defined inductive `datatypes <datatypes>`__.
+denotes a user-defined inductive :doc:`datatypes`.
.. code:: smtlib
diff --git a/docs/theories/sets-and-relations.rst b/docs/theories/sets-and-relations.rst
index 2da6715e3..33c0d4cd0 100644
--- a/docs/theories/sets-and-relations.rst
+++ b/docs/theories/sets-and-relations.rst
@@ -9,6 +9,7 @@ The simplest way to get a sense of the syntax is to look at an example:
.. api-examples::
<examples>/api/cpp/sets.cpp
+ <examples>/api/java/Sets.java
<examples>/api/python/sets.py
<examples>/api/smtlib/sets.smt2
@@ -16,7 +17,8 @@ The source code of these examples is available at:
* `SMT-LIB 2 language example <https://github.com/cvc5/cvc5/blob/master/examples/api/smtlib/sets.smt2>`__
* `C++ API example <https://github.com/cvc5/cvc5/blob/master/examples/api/cpp/sets.cpp>`__
-* `Python API example <https://github.com/cvc5/cvc5/blob/master/examples/api/python/sets.cpp>`__
+* `Java API example <https://github.com/cvc5/cvc5/blob/master/examples/api/java/Sets.java>`__
+* `Python API example <https://github.com/cvc5/cvc5/blob/master/examples/api/python/sets.py>`__
Below is a short summary of the sorts, constants, functions and
diff --git a/docs/theories/transcendentals.rst b/docs/theories/transcendentals.rst
index 6d35e6cce..6b76e7b41 100644
--- a/docs/theories/transcendentals.rst
+++ b/docs/theories/transcendentals.rst
@@ -51,5 +51,6 @@ Examples
.. api-examples::
<examples>/api/cpp/transcendentals.cpp
+ <examples>/api/java/Transcendentals.java
<examples>/api/python/transcendentals.py
<examples>/api/smtlib/transcendentals.smt2 \ No newline at end of file
diff --git a/examples/api/java/QuickStart.java b/examples/api/java/QuickStart.java
index a79263cbf..c815278cc 100644
--- a/examples/api/java/QuickStart.java
+++ b/examples/api/java/QuickStart.java
@@ -106,11 +106,32 @@ public class QuickStart
Term xMinusY = solver.mkTerm(Kind.MINUS, x, y);
Term xMinusYVal = solver.getValue(xMinusY);
- // Further, we can convert the values to java types,
- Pair<BigInteger, BigInteger> xRational = xVal.getRealValue();
- Pair<BigInteger, BigInteger> yRational = yVal.getRealValue();
- System.out.println("value for x: " + xRational.first + "/" + xRational.second);
- System.out.println("value for y: " + yRational.first + "/" + yRational.second);
+ // Further, we can convert the values to java types
+ Pair<BigInteger, BigInteger> xPair = xVal.getRealValue();
+ Pair<BigInteger, BigInteger> yPair = yVal.getRealValue();
+ Pair<BigInteger, BigInteger> xMinusYPair = xMinusYVal.getRealValue();
+
+ System.out.println("value for x: " + xPair.first + "/" + xPair.second);
+ System.out.println("value for y: " + yPair.first + "/" + yPair.second);
+ System.out.println("value for x - y: " + xMinusYPair.first + "/" + xMinusYPair.second);
+
+ // Another way to independently compute the value of x - y would be
+ // to perform the (rational) arithmetic manually.
+ // However, for more complex terms,
+ // it is easier to let the solver do the evaluation.
+ Pair<BigInteger, BigInteger> xMinusYComputed =
+ new Pair(xPair.first.multiply(yPair.second).subtract(xPair.second.multiply(yPair.first)),
+ xPair.second.multiply(yPair.second));
+ BigInteger g = xMinusYComputed.first.gcd(xMinusYComputed.second);
+ xMinusYComputed = new Pair(xMinusYComputed.first.divide(g), xMinusYComputed.second.divide(g));
+ if (xMinusYComputed.equals(xMinusYPair))
+ {
+ System.out.println("computed correctly");
+ }
+ else
+ {
+ System.out.println("computed incorrectly");
+ }
// Next, we will check satisfiability of the same formula,
// only this time over integer variables a and b.
diff --git a/examples/api/java/Relations.java b/examples/api/java/Relations.java
index a3e2b2a7e..95aede591 100644
--- a/examples/api/java/Relations.java
+++ b/examples/api/java/Relations.java
@@ -152,10 +152,9 @@ public class Relations
Term transpose = solver.mkTerm(RELATION_TRANSPOSE, descendant);
Term ancestorFormula = solver.mkTerm(EQUAL, ancestor, transpose);
- // (assert (forall ((x Person)) (not (set.member (mkTuple x x) ancestor))))
+ // (assert (forall ((x Person)) (not (set.member (tuple x x) ancestor))))
Term x = solver.mkVar(personSort, "x");
- DatatypeConstructor constructor = tupleArity2.getDatatype().getConstructor(0);
- Term xxTuple = solver.mkTerm(APPLY_CONSTRUCTOR, constructor.getConstructorTerm(), x, x);
+ Term xxTuple = solver.mkTuple(new Sort[]{personSort, personSort}, new Term[] {x, x});
Term member = solver.mkTerm(SET_MEMBER, xxTuple, ancestor);
Term notMember = solver.mkTerm(NOT, member);
diff --git a/examples/api/python/bitvectors.py b/examples/api/python/bitvectors.py
index ff99bd785..e785fd790 100644
--- a/examples/api/python/bitvectors.py
+++ b/examples/api/python/bitvectors.py
@@ -17,7 +17,7 @@
##
import pycvc5
-from pycvc5 import kinds
+from pycvc5 import Kind
if __name__ == "__main__":
slv = pycvc5.Solver()
@@ -50,9 +50,9 @@ if __name__ == "__main__":
b = slv.mkConst(bitvector32, "b")
# First encode the assumption that x must be equal to a or b
- x_eq_a = slv.mkTerm(kinds.Equal, x, a)
- x_eq_b = slv.mkTerm(kinds.Equal, x, b)
- assumption = slv.mkTerm(kinds.Or, x_eq_a, x_eq_b)
+ x_eq_a = slv.mkTerm(Kind.Equal, x, a)
+ x_eq_b = slv.mkTerm(Kind.Equal, x, b)
+ assumption = slv.mkTerm(Kind.Or, x_eq_a, x_eq_b)
# Assert the assumption
slv.assertFormula(assumption)
@@ -65,8 +65,8 @@ if __name__ == "__main__":
# Encoding code (0)
# new_x = x == a ? b : a
- ite = slv.mkTerm(kinds.Ite, x_eq_a, b, a)
- assignment0 = slv.mkTerm(kinds.Equal, new_x, ite)
+ ite = slv.mkTerm(Kind.Ite, x_eq_a, b, a)
+ assignment0 = slv.mkTerm(Kind.Equal, new_x, ite)
# Assert the encoding of code (0)
print("Asserting {} to cvc5".format(assignment0))
@@ -76,13 +76,13 @@ if __name__ == "__main__":
# Encoding code (1)
# new_x_ = a xor b xor x
- a_xor_b_xor_x = slv.mkTerm(kinds.BVXor, a, b, x)
- assignment1 = slv.mkTerm(kinds.Equal, new_x_, a_xor_b_xor_x)
+ a_xor_b_xor_x = slv.mkTerm(Kind.BVXor, a, b, x)
+ assignment1 = slv.mkTerm(Kind.Equal, new_x_, a_xor_b_xor_x)
# Assert encoding to cvc5 in current context
print("Asserting {} to cvc5".format(assignment1))
slv.assertFormula(assignment1)
- new_x_eq_new_x_ = slv.mkTerm(kinds.Equal, new_x, new_x_)
+ new_x_eq_new_x_ = slv.mkTerm(Kind.Equal, new_x, new_x_)
print("Checking entailment assuming:", new_x_eq_new_x_)
print("Expect ENTAILED.")
@@ -92,9 +92,9 @@ if __name__ == "__main__":
# Encoding code (2)
# new_x_ = a + b - x
- a_plus_b = slv.mkTerm(kinds.BVAdd, a, b)
- a_plus_b_minus_x = slv.mkTerm(kinds.BVSub, a_plus_b, x)
- assignment2 = slv.mkTerm(kinds.Equal, new_x_, a_plus_b_minus_x)
+ a_plus_b = slv.mkTerm(Kind.BVAdd, a, b)
+ a_plus_b_minus_x = slv.mkTerm(Kind.BVSub, a_plus_b, x)
+ assignment2 = slv.mkTerm(Kind.Equal, new_x_, a_plus_b_minus_x)
# Assert encoding to cvc5 in current context
print("Asserting {} to cvc5".format(assignment2))
@@ -105,17 +105,17 @@ if __name__ == "__main__":
print("cvc5:", slv.checkEntailed(new_x_eq_new_x_))
- x_neq_x = slv.mkTerm(kinds.Equal, x, x).notTerm()
+ x_neq_x = slv.mkTerm(Kind.Equal, x, x).notTerm()
v = [new_x_eq_new_x_, x_neq_x]
print("Check entailment assuming: ", v)
print("Expect NOT_ENTAILED.")
print("cvc5:", slv.checkEntailed(v))
# Assert that a is odd
- extract_op = slv.mkOp(kinds.BVExtract, 0, 0)
+ extract_op = slv.mkOp(Kind.BVExtract, 0, 0)
lsb_of_a = slv.mkTerm(extract_op, a)
print("Sort of {} is {}".format(lsb_of_a, lsb_of_a.getSort()))
- a_odd = slv.mkTerm(kinds.Equal, lsb_of_a, slv.mkBitVector(1, 1))
+ a_odd = slv.mkTerm(Kind.Equal, lsb_of_a, slv.mkBitVector(1, 1))
print("Assert", a_odd)
print("Check satisifiability")
slv.assertFormula(a_odd)
diff --git a/examples/api/python/bitvectors_and_arrays.py b/examples/api/python/bitvectors_and_arrays.py
index be38077ca..d3c8caf75 100644
--- a/examples/api/python/bitvectors_and_arrays.py
+++ b/examples/api/python/bitvectors_and_arrays.py
@@ -17,7 +17,7 @@
##
import pycvc5
-from pycvc5 import kinds
+from pycvc5 import Kind
import math
@@ -58,29 +58,29 @@ if __name__ == "__main__":
constarr0 = slv.mkConstArray(arraySort, slv.mkBitVector(32, 0))
# Asserting that current_array[0] > 0
- current_array0 = slv.mkTerm(kinds.Select, current_array, zero)
- current_array0_gt_0 = slv.mkTerm(kinds.BVSgt,
+ current_array0 = slv.mkTerm(Kind.Select, current_array, zero)
+ current_array0_gt_0 = slv.mkTerm(Kind.BVSgt,
current_array0,
slv.mkBitVector(32, 0))
slv.assertFormula(current_array0_gt_0)
# Building the assertions in the loop unrolling
index = slv.mkBitVector(index_size, 0)
- old_current = slv.mkTerm(kinds.Select, current_array, index)
+ old_current = slv.mkTerm(Kind.Select, current_array, index)
two = slv.mkBitVector(32, 2)
assertions = []
for i in range(1, k):
index = slv.mkBitVector(index_size, i)
- new_current = slv.mkTerm(kinds.BVMult, two, old_current)
+ new_current = slv.mkTerm(Kind.BVMult, two, old_current)
# current[i] = 2*current[i-1]
- current_array = slv.mkTerm(kinds.Store, current_array, index, new_current)
+ current_array = slv.mkTerm(Kind.Store, current_array, index, new_current)
# current[i-1] < current[i]
- current_slt_new_current = slv.mkTerm(kinds.BVSlt, old_current, new_current)
+ current_slt_new_current = slv.mkTerm(Kind.BVSlt, old_current, new_current)
assertions.append(current_slt_new_current)
- old_current = slv.mkTerm(kinds.Select, current_array, index)
+ old_current = slv.mkTerm(Kind.Select, current_array, index)
- query = slv.mkTerm(kinds.Not, slv.mkTerm(kinds.And, assertions))
+ query = slv.mkTerm(Kind.Not, slv.mkTerm(Kind.And, assertions))
print("Asserting {} to cvc5".format(query))
slv.assertFormula(query)
diff --git a/examples/api/python/combination.py b/examples/api/python/combination.py
index 990149434..bceb7e738 100644
--- a/examples/api/python/combination.py
+++ b/examples/api/python/combination.py
@@ -17,7 +17,7 @@
##
import pycvc5
-from pycvc5 import kinds
+from pycvc5 import Kind
def prefixPrintGetValue(slv, t, level=0):
print("slv.getValue({}): {}".format(t, slv.getValue(t)))
@@ -51,18 +51,18 @@ if __name__ == "__main__":
one = slv.mkInteger(1)
# Terms
- f_x = slv.mkTerm(kinds.ApplyUf, f, x)
- f_y = slv.mkTerm(kinds.ApplyUf, f, y)
- sum_ = slv.mkTerm(kinds.Plus, f_x, f_y)
- p_0 = slv.mkTerm(kinds.ApplyUf, p, zero)
- p_f_y = slv.mkTerm(kinds.ApplyUf, p, f_y)
+ f_x = slv.mkTerm(Kind.ApplyUf, f, x)
+ f_y = slv.mkTerm(Kind.ApplyUf, f, y)
+ sum_ = slv.mkTerm(Kind.Plus, f_x, f_y)
+ p_0 = slv.mkTerm(Kind.ApplyUf, p, zero)
+ p_f_y = slv.mkTerm(Kind.ApplyUf, p, f_y)
# Construct the assertions
- assertions = slv.mkTerm(kinds.And,
+ assertions = slv.mkTerm(Kind.And,
[
- slv.mkTerm(kinds.Leq, zero, f_x), # 0 <= f(x)
- slv.mkTerm(kinds.Leq, zero, f_y), # 0 <= f(y)
- slv.mkTerm(kinds.Leq, sum_, one), # f(x) + f(y) <= 1
+ slv.mkTerm(Kind.Leq, zero, f_x), # 0 <= f(x)
+ slv.mkTerm(Kind.Leq, zero, f_y), # 0 <= f(y)
+ slv.mkTerm(Kind.Leq, sum_, one), # f(x) + f(y) <= 1
p_0.notTerm(), # not p(0)
p_f_y # p(f(y))
])
@@ -71,7 +71,7 @@ if __name__ == "__main__":
print("Given the following assertions:", assertions, "\n")
print("Prove x /= y is entailed.\ncvc5: ",
- slv.checkEntailed(slv.mkTerm(kinds.Distinct, x, y)), "\n")
+ slv.checkEntailed(slv.mkTerm(Kind.Distinct, x, y)), "\n")
print("Call checkSat to show that the assertions are satisfiable")
print("cvc5:", slv.checkSat(), "\n")
diff --git a/examples/api/python/datatypes.py b/examples/api/python/datatypes.py
index 96116da08..cc4ca719a 100644
--- a/examples/api/python/datatypes.py
+++ b/examples/api/python/datatypes.py
@@ -17,7 +17,7 @@
##
import pycvc5
-from pycvc5 import kinds
+from pycvc5 import Kind
def test(slv, consListSort):
# Now our old "consListSpec" is useless--the relevant information
@@ -34,9 +34,9 @@ def test(slv, consListSort):
# which is equivalent to consList["cons"].getConstructor(). Note that
# "nil" is a constructor too
- t = slv.mkTerm(kinds.ApplyConstructor, consList.getConstructorTerm("cons"),
+ t = slv.mkTerm(Kind.ApplyConstructor, consList.getConstructorTerm("cons"),
slv.mkInteger(0),
- slv.mkTerm(kinds.ApplyConstructor, consList.getConstructorTerm("nil")))
+ slv.mkTerm(Kind.ApplyConstructor, consList.getConstructorTerm("nil")))
print("t is {}\nsort of cons is {}\n sort of nil is {}".format(
t,
@@ -49,7 +49,7 @@ def test(slv, consListSort):
# consList["cons"]) in order to get the "head" selector symbol
# to apply.
- t2 = slv.mkTerm(kinds.ApplySelector, consList["cons"].getSelectorTerm("head"), t)
+ t2 = slv.mkTerm(Kind.ApplySelector, consList["cons"].getSelectorTerm("head"), t)
print("t2 is {}\nsimplify(t2) is {}\n\n".format(t2, slv.simplify(t2)))
@@ -63,16 +63,16 @@ def test(slv, consListSort):
# You can also define a tester term for constructor 'cons': (_ is cons)
t_is_cons = slv.mkTerm(
- kinds.ApplyTester, consList["cons"].getTesterTerm(), t)
+ Kind.ApplyTester, consList["cons"].getTesterTerm(), t)
print("t_is_cons is {}\n\n".format(t_is_cons))
slv.assertFormula(t_is_cons)
# Updating t at 'head' with value 1 is defined as follows:
- t_updated = slv.mkTerm(kinds.ApplyUpdater,
+ t_updated = slv.mkTerm(Kind.ApplyUpdater,
consList["cons"]["head"].getUpdaterTerm(),
t,
slv.mkInteger(1))
print("t_updated is {}\n\n".format(t_updated))
- slv.assertFormula(slv.mkTerm(kinds.Distinct, t, t_updated))
+ slv.assertFormula(slv.mkTerm(Kind.Distinct, t, t_updated))
# You can also define parameterized datatypes.
# This example builds a simple parameterized list of sort T, with one
@@ -93,11 +93,11 @@ def test(slv, consListSort):
a = slv.mkConst(paramConsIntListSort, "a")
print("term {} is of sort {}".format(a, a.getSort()))
- head_a = slv.mkTerm(kinds.ApplySelector, paramConsList["cons"].getSelectorTerm("head"), a)
+ head_a = slv.mkTerm(Kind.ApplySelector, paramConsList["cons"].getSelectorTerm("head"), a)
print("head_a is {} of sort {}".format(head_a, head_a.getSort()))
print("sort of cons is", paramConsList.getConstructorTerm("cons").getSort())
- assertion = slv.mkTerm(kinds.Gt, head_a, slv.mkInteger(50))
+ assertion = slv.mkTerm(Kind.Gt, head_a, slv.mkInteger(50))
print("Assert", assertion)
slv.assertFormula(assertion)
print("Expect sat.")
diff --git a/examples/api/python/exceptions.py b/examples/api/python/exceptions.py
index a4597d12b..dcfff09e4 100644
--- a/examples/api/python/exceptions.py
+++ b/examples/api/python/exceptions.py
@@ -17,7 +17,7 @@
##
import pycvc5
-from pycvc5 import kinds
+from pycvc5 import Kind
import sys
diff --git a/examples/api/python/extract.py b/examples/api/python/extract.py
index 4e7026e97..fa7350285 100644
--- a/examples/api/python/extract.py
+++ b/examples/api/python/extract.py
@@ -16,8 +16,7 @@
# extract-new.cpp.
##
-from pycvc5 import Solver
-from pycvc5.kinds import BVExtract, Equal
+from pycvc5 import Solver, Kind
if __name__ == "__main__":
slv = Solver()
@@ -27,26 +26,26 @@ if __name__ == "__main__":
x = slv.mkConst(bitvector32, "a")
- ext_31_1 = slv.mkOp(BVExtract, 31, 1)
+ ext_31_1 = slv.mkOp(Kind.BVExtract, 31, 1)
x_31_1 = slv.mkTerm(ext_31_1, x)
- ext_30_0 = slv.mkOp(BVExtract, 30, 0)
+ ext_30_0 = slv.mkOp(Kind.BVExtract, 30, 0)
x_30_0 = slv.mkTerm(ext_30_0, x)
- ext_31_31 = slv.mkOp(BVExtract, 31, 31)
+ ext_31_31 = slv.mkOp(Kind.BVExtract, 31, 31)
x_31_31 = slv.mkTerm(ext_31_31, x)
- ext_0_0 = slv.mkOp(BVExtract, 0, 0)
+ ext_0_0 = slv.mkOp(Kind.BVExtract, 0, 0)
x_0_0 = slv.mkTerm(ext_0_0, x)
# test getting indices
assert ext_30_0.getIndices() == (30, 0)
- eq = slv.mkTerm(Equal, x_31_1, x_30_0)
+ eq = slv.mkTerm(Kind.Equal, x_31_1, x_30_0)
print("Asserting:", eq)
slv.assertFormula(eq)
- eq2 = slv.mkTerm(Equal, x_31_31, x_0_0)
+ eq2 = slv.mkTerm(Kind.Equal, x_31_31, x_0_0)
print("Check entailment assuming:", eq2)
print("Expect ENTAILED")
print("cvc5:", slv.checkEntailed(eq2))
diff --git a/examples/api/python/floating_point.py b/examples/api/python/floating_point.py
index d6ba8d754..29f0d16d7 100644
--- a/examples/api/python/floating_point.py
+++ b/examples/api/python/floating_point.py
@@ -17,7 +17,7 @@
##
import pycvc5
-from pycvc5 import kinds
+from pycvc5 import Kind
if __name__ == "__main__":
slv = pycvc5.Solver()
@@ -37,10 +37,10 @@ if __name__ == "__main__":
z = slv.mkConst(fp32, 'z')
# check floating-point arithmetic is commutative, i.e. x + y == y + x
- commutative = slv.mkTerm(kinds.FPEq, slv.mkTerm(kinds.FPAdd, rm, x, y), slv.mkTerm(kinds.FPAdd, rm, y, x))
+ commutative = slv.mkTerm(Kind.FPEq, slv.mkTerm(Kind.FPAdd, rm, x, y), slv.mkTerm(Kind.FPAdd, rm, y, x))
slv.push()
- slv.assertFormula(slv.mkTerm(kinds.Not, commutative))
+ slv.assertFormula(slv.mkTerm(Kind.Not, commutative))
print("Checking floating-point commutativity")
print("Expect SAT (property does not hold for NaN and Infinities).")
print("cvc5:", slv.checkSat())
@@ -48,10 +48,10 @@ if __name__ == "__main__":
print("Model for y:", slv.getValue(y))
# disallow NaNs and Infinities
- slv.assertFormula(slv.mkTerm(kinds.Not, slv.mkTerm(kinds.FPIsNan, x)))
- slv.assertFormula(slv.mkTerm(kinds.Not, slv.mkTerm(kinds.FPIsInf, x)))
- slv.assertFormula(slv.mkTerm(kinds.Not, slv.mkTerm(kinds.FPIsNan, y)))
- slv.assertFormula(slv.mkTerm(kinds.Not, slv.mkTerm(kinds.FPIsInf, y)))
+ slv.assertFormula(slv.mkTerm(Kind.Not, slv.mkTerm(Kind.FPIsNan, x)))
+ slv.assertFormula(slv.mkTerm(Kind.Not, slv.mkTerm(Kind.FPIsInf, x)))
+ slv.assertFormula(slv.mkTerm(Kind.Not, slv.mkTerm(Kind.FPIsNan, y)))
+ slv.assertFormula(slv.mkTerm(Kind.Not, slv.mkTerm(Kind.FPIsInf, y)))
print("Checking floating-point commutativity assuming x and y are not NaN or Infinity")
print("Expect UNSAT.")
@@ -70,15 +70,15 @@ if __name__ == "__main__":
24,
slv.mkBitVector(32, "01000000010010001111010111000011", 2)) # 3.14
- bounds_x = slv.mkTerm(kinds.And, slv.mkTerm(kinds.FPLeq, a, x), slv.mkTerm(kinds.FPLeq, x, b))
- bounds_y = slv.mkTerm(kinds.And, slv.mkTerm(kinds.FPLeq, a, y), slv.mkTerm(kinds.FPLeq, y, b))
- bounds_z = slv.mkTerm(kinds.And, slv.mkTerm(kinds.FPLeq, a, z), slv.mkTerm(kinds.FPLeq, z, b))
- slv.assertFormula(slv.mkTerm(kinds.And, slv.mkTerm(kinds.And, bounds_x, bounds_y), bounds_z))
+ bounds_x = slv.mkTerm(Kind.And, slv.mkTerm(Kind.FPLeq, a, x), slv.mkTerm(Kind.FPLeq, x, b))
+ bounds_y = slv.mkTerm(Kind.And, slv.mkTerm(Kind.FPLeq, a, y), slv.mkTerm(Kind.FPLeq, y, b))
+ bounds_z = slv.mkTerm(Kind.And, slv.mkTerm(Kind.FPLeq, a, z), slv.mkTerm(Kind.FPLeq, z, b))
+ slv.assertFormula(slv.mkTerm(Kind.And, slv.mkTerm(Kind.And, bounds_x, bounds_y), bounds_z))
# (x + y) + z == x + (y + z)
- lhs = slv.mkTerm(kinds.FPAdd, rm, slv.mkTerm(kinds.FPAdd, rm, x, y), z)
- rhs = slv.mkTerm(kinds.FPAdd, rm, x, slv.mkTerm(kinds.FPAdd, rm, y, z))
- associative = slv.mkTerm(kinds.Not, slv.mkTerm(kinds.FPEq, lhs, rhs))
+ lhs = slv.mkTerm(Kind.FPAdd, rm, slv.mkTerm(Kind.FPAdd, rm, x, y), z)
+ rhs = slv.mkTerm(Kind.FPAdd, rm, x, slv.mkTerm(Kind.FPAdd, rm, y, z))
+ associative = slv.mkTerm(Kind.Not, slv.mkTerm(Kind.FPEq, lhs, rhs))
slv.assertFormula(associative)
diff --git a/examples/api/python/helloworld.py b/examples/api/python/helloworld.py
index 6e6ce32ab..b437efc86 100644
--- a/examples/api/python/helloworld.py
+++ b/examples/api/python/helloworld.py
@@ -15,7 +15,7 @@
##
import pycvc5
-from pycvc5 import kinds
+from pycvc5 import Kind
if __name__ == "__main__":
slv = pycvc5.Solver()
diff --git a/examples/api/python/id.py b/examples/api/python/id.py
index fb3672dbc..c7a2ed0bc 100644
--- a/examples/api/python/id.py
+++ b/examples/api/python/id.py
@@ -16,7 +16,6 @@
##
import pycvc5
-from pycvc5 import kinds
if __name__ == "__main__":
slv = pycvc5.Solver()
diff --git a/examples/api/python/linear_arith.py b/examples/api/python/linear_arith.py
index f8dad6a71..a2f303a5d 100644
--- a/examples/api/python/linear_arith.py
+++ b/examples/api/python/linear_arith.py
@@ -17,7 +17,7 @@
##
import pycvc5
-from pycvc5 import kinds
+from pycvc5 import Kind
if __name__ == "__main__":
slv = pycvc5.Solver()
@@ -40,21 +40,21 @@ if __name__ == "__main__":
two_thirds = slv.mkReal(2, 3)
# Terms
- three_y = slv.mkTerm(kinds.Mult, three, y)
- diff = slv.mkTerm(kinds.Minus, y, x)
+ three_y = slv.mkTerm(Kind.Mult, three, y)
+ diff = slv.mkTerm(Kind.Minus, y, x)
# Formulas
- x_geq_3y = slv.mkTerm(kinds.Geq, x, three_y)
- x_leq_y = slv.mkTerm(kinds.Leq, x ,y)
- neg2_lt_x = slv.mkTerm(kinds.Lt, neg2, x)
+ x_geq_3y = slv.mkTerm(Kind.Geq, x, three_y)
+ x_leq_y = slv.mkTerm(Kind.Leq, x ,y)
+ neg2_lt_x = slv.mkTerm(Kind.Lt, neg2, x)
- assertions = slv.mkTerm(kinds.And, x_geq_3y, x_leq_y, neg2_lt_x)
+ assertions = slv.mkTerm(Kind.And, x_geq_3y, x_leq_y, neg2_lt_x)
print("Given the assertions", assertions)
slv.assertFormula(assertions)
slv.push()
- diff_leq_two_thirds = slv.mkTerm(kinds.Leq, diff, two_thirds)
+ diff_leq_two_thirds = slv.mkTerm(Kind.Leq, diff, two_thirds)
print("Prove that", diff_leq_two_thirds, "with cvc5")
print("cvc5 should report ENTAILED")
print("Result from cvc5 is:",
@@ -64,7 +64,7 @@ if __name__ == "__main__":
print()
slv.push()
- diff_is_two_thirds = slv.mkTerm(kinds.Equal, diff, two_thirds)
+ diff_is_two_thirds = slv.mkTerm(Kind.Equal, diff, two_thirds)
slv.assertFormula(diff_is_two_thirds)
print("Show that the assertions are consistent with\n", diff_is_two_thirds, "with cvc5")
print("cvc5 should report SAT")
diff --git a/examples/api/python/quickstart.py b/examples/api/python/quickstart.py
index 389e08be1..8261b3d70 100644
--- a/examples/api/python/quickstart.py
+++ b/examples/api/python/quickstart.py
@@ -15,7 +15,7 @@
##
import pycvc5
-from pycvc5 import kinds
+from pycvc5 import Kind
if __name__ == "__main__":
# Create a solver
@@ -64,15 +64,15 @@ if __name__ == "__main__":
one = solver.mkReal(1);
# Next, we construct the term x + y
- xPlusY = solver.mkTerm(kinds.Plus, x, y);
+ xPlusY = solver.mkTerm(Kind.Plus, x, y);
# Now we can define the constraints.
# They use the operators +, <=, and <.
# In the API, these are denoted by Plus, Leq, and Lt.
- constraint1 = solver.mkTerm(kinds.Lt, zero, x);
- constraint2 = solver.mkTerm(kinds.Lt, zero, y);
- constraint3 = solver.mkTerm(kinds.Lt, xPlusY, one);
- constraint4 = solver.mkTerm(kinds.Leq, x, y);
+ constraint1 = solver.mkTerm(Kind.Lt, zero, x);
+ constraint2 = solver.mkTerm(Kind.Lt, zero, y);
+ constraint3 = solver.mkTerm(Kind.Lt, xPlusY, one);
+ constraint4 = solver.mkTerm(Kind.Leq, x, y);
# Now we assert the constraints to the solver.
solver.assertFormula(constraint1);
@@ -95,7 +95,7 @@ if __name__ == "__main__":
# It is also possible to get values for compound terms,
# even if those did not appear in the original formula.
- xMinusY = solver.mkTerm(kinds.Minus, x, y);
+ xMinusY = solver.mkTerm(Kind.Minus, x, y);
xMinusYVal = solver.getValue(xMinusY);
# We can now obtain the values as python values
@@ -132,11 +132,11 @@ if __name__ == "__main__":
# Next, we assert the same assertions above with integers.
# This time, we inline the construction of terms
# to the assertion command.
- solver.assertFormula(solver.mkTerm(kinds.Lt, solver.mkInteger(0), a));
- solver.assertFormula(solver.mkTerm(kinds.Lt, solver.mkInteger(0), b));
+ solver.assertFormula(solver.mkTerm(Kind.Lt, solver.mkInteger(0), a));
+ solver.assertFormula(solver.mkTerm(Kind.Lt, solver.mkInteger(0), b));
solver.assertFormula(
- solver.mkTerm(kinds.Lt, solver.mkTerm(kinds.Plus, a, b), solver.mkInteger(1)));
- solver.assertFormula(solver.mkTerm(kinds.Leq, a, b));
+ solver.mkTerm(Kind.Lt, solver.mkTerm(Kind.Plus, a, b), solver.mkInteger(1)));
+ solver.assertFormula(solver.mkTerm(Kind.Leq, a, b));
# We check whether the revised assertion is satisfiable.
r2 = solver.checkSat();
diff --git a/examples/api/python/sequences.py b/examples/api/python/sequences.py
index f9fd925fb..66a4c1353 100644
--- a/examples/api/python/sequences.py
+++ b/examples/api/python/sequences.py
@@ -16,7 +16,7 @@
##
import pycvc5
-from pycvc5 import kinds
+from pycvc5 import Kind
if __name__ == "__main__":
slv = pycvc5.Solver()
@@ -39,18 +39,18 @@ if __name__ == "__main__":
# Empty sequence
empty = slv.mkEmptySequence(slv.getIntegerSort())
# Sequence concatenation: x.y.empty
- concat = slv.mkTerm(kinds.SeqConcat, x, y, empty)
+ concat = slv.mkTerm(Kind.SeqConcat, x, y, empty)
# Sequence length: |x.y.empty|
- concat_len = slv.mkTerm(kinds.SeqLength, concat)
+ concat_len = slv.mkTerm(Kind.SeqLength, concat)
# |x.y.empty| > 1
- formula1 = slv.mkTerm(kinds.Gt, concat_len, slv.mkInteger(1))
+ formula1 = slv.mkTerm(Kind.Gt, concat_len, slv.mkInteger(1))
# Sequence unit: seq(1)
- unit = slv.mkTerm(kinds.SeqUnit, slv.mkInteger(1))
+ unit = slv.mkTerm(Kind.SeqUnit, slv.mkInteger(1))
# x = seq(1)
- formula2 = slv.mkTerm(kinds.Equal, x, unit)
+ formula2 = slv.mkTerm(Kind.Equal, x, unit)
# Make a query
- q = slv.mkTerm(kinds.And, formula1, formula2)
+ q = slv.mkTerm(Kind.And, formula1, formula2)
# Check satisfiability
result = slv.checkSatAssuming(q)
diff --git a/examples/api/python/sets.py b/examples/api/python/sets.py
index 31f20dfeb..4bd6c4029 100644
--- a/examples/api/python/sets.py
+++ b/examples/api/python/sets.py
@@ -16,7 +16,7 @@
##
import pycvc5
-from pycvc5 import kinds
+from pycvc5 import Kind
if __name__ == "__main__":
slv = pycvc5.Solver()
@@ -39,14 +39,14 @@ if __name__ == "__main__":
B = slv.mkConst(set_, "B")
C = slv.mkConst(set_, "C")
- unionAB = slv.mkTerm(kinds.SetUnion, A, B)
- lhs = slv.mkTerm(kinds.SetInter, unionAB, C)
+ unionAB = slv.mkTerm(Kind.SetUnion, A, B)
+ lhs = slv.mkTerm(Kind.SetInter, unionAB, C)
- intersectionAC = slv.mkTerm(kinds.SetInter, A, C)
- intersectionBC = slv.mkTerm(kinds.SetInter, B, C)
- rhs = slv.mkTerm(kinds.SetUnion, intersectionAC, intersectionBC)
+ intersectionAC = slv.mkTerm(Kind.SetInter, A, C)
+ intersectionBC = slv.mkTerm(Kind.SetInter, B, C)
+ rhs = slv.mkTerm(Kind.SetUnion, intersectionAC, intersectionBC)
- theorem = slv.mkTerm(kinds.Equal, lhs, rhs)
+ theorem = slv.mkTerm(Kind.Equal, lhs, rhs)
print("cvc5 reports: {} is {}".format(theorem,
slv.checkEntailed(theorem)))
@@ -56,7 +56,7 @@ if __name__ == "__main__":
A = slv.mkConst(set_, "A")
emptyset = slv.mkEmptySet(set_)
- theorem = slv.mkTerm(kinds.SetSubset, emptyset, A)
+ theorem = slv.mkTerm(Kind.SetSubset, emptyset, A)
print("cvc5 reports: {} is {}".format(theorem,
slv.checkEntailed(theorem)))
@@ -67,16 +67,16 @@ if __name__ == "__main__":
two = slv.mkInteger(2)
three = slv.mkInteger(3)
- singleton_one = slv.mkTerm(kinds.SetSingleton, one)
- singleton_two = slv.mkTerm(kinds.SetSingleton, two)
- singleton_three = slv.mkTerm(kinds.SetSingleton, three)
- one_two = slv.mkTerm(kinds.SetUnion, singleton_one, singleton_two)
- two_three = slv.mkTerm(kinds.SetUnion, singleton_two, singleton_three)
- intersection = slv.mkTerm(kinds.SetInter, one_two, two_three)
+ singleton_one = slv.mkTerm(Kind.SetSingleton, one)
+ singleton_two = slv.mkTerm(Kind.SetSingleton, two)
+ singleton_three = slv.mkTerm(Kind.SetSingleton, three)
+ one_two = slv.mkTerm(Kind.SetUnion, singleton_one, singleton_two)
+ two_three = slv.mkTerm(Kind.SetUnion, singleton_two, singleton_three)
+ intersection = slv.mkTerm(Kind.SetInter, one_two, two_three)
x = slv.mkConst(integer, "x")
- e = slv.mkTerm(kinds.SetMember, x, intersection)
+ e = slv.mkTerm(Kind.SetMember, x, intersection)
result = slv.checkSatAssuming(e)
diff --git a/examples/api/python/strings.py b/examples/api/python/strings.py
index 64ce06548..c1087eaac 100644
--- a/examples/api/python/strings.py
+++ b/examples/api/python/strings.py
@@ -16,7 +16,7 @@
##
import pycvc5
-from pycvc5 import kinds
+from pycvc5 import Kind
if __name__ == "__main__":
slv = pycvc5.Solver()
@@ -43,38 +43,38 @@ if __name__ == "__main__":
z = slv.mkConst(string, "z")
# String concatenation: x.ab.y
- lhs = slv.mkTerm(kinds.StringConcat, x, ab, y)
+ lhs = slv.mkTerm(Kind.StringConcat, x, ab, y)
# String concatenation: abc.z
- rhs = slv.mkTerm(kinds.StringConcat, abc, z)
+ rhs = slv.mkTerm(Kind.StringConcat, abc, z)
# x.ab.y = abc.z
- formula1 = slv.mkTerm(kinds.Equal, lhs, rhs)
+ formula1 = slv.mkTerm(Kind.Equal, lhs, rhs)
# Length of y: |y|
- leny = slv.mkTerm(kinds.StringLength, y)
+ leny = slv.mkTerm(Kind.StringLength, y)
# |y| >= 0
- formula2 = slv.mkTerm(kinds.Geq, leny, slv.mkInteger(0))
+ formula2 = slv.mkTerm(Kind.Geq, leny, slv.mkInteger(0))
# Regular expression: (ab[c-e]*f)|g|h
- r = slv.mkTerm(kinds.RegexpUnion,
- slv.mkTerm(kinds.RegexpConcat,
- slv.mkTerm(kinds.StringToRegexp, slv.mkString("ab")),
- slv.mkTerm(kinds.RegexpStar,
- slv.mkTerm(kinds.RegexpRange, slv.mkString("c"), slv.mkString("e"))),
- slv.mkTerm(kinds.StringToRegexp, slv.mkString("f"))),
- slv.mkTerm(kinds.StringToRegexp, slv.mkString("g")),
- slv.mkTerm(kinds.StringToRegexp, slv.mkString("h")))
+ r = slv.mkTerm(Kind.RegexpUnion,
+ slv.mkTerm(Kind.RegexpConcat,
+ slv.mkTerm(Kind.StringToRegexp, slv.mkString("ab")),
+ slv.mkTerm(Kind.RegexpStar,
+ slv.mkTerm(Kind.RegexpRange, slv.mkString("c"), slv.mkString("e"))),
+ slv.mkTerm(Kind.StringToRegexp, slv.mkString("f"))),
+ slv.mkTerm(Kind.StringToRegexp, slv.mkString("g")),
+ slv.mkTerm(Kind.StringToRegexp, slv.mkString("h")))
# String variables
s1 = slv.mkConst(string, "s1")
s2 = slv.mkConst(string, "s2")
# String concatenation: s1.s2
- s = slv.mkTerm(kinds.StringConcat, s1, s2)
+ s = slv.mkTerm(Kind.StringConcat, s1, s2)
# s1.s2 in (ab[c-e]*f)|g|h
- formula3 = slv.mkTerm(kinds.StringInRegexp, s, r)
+ formula3 = slv.mkTerm(Kind.StringInRegexp, s, r)
# Make a query
- q = slv.mkTerm(kinds.And,
+ q = slv.mkTerm(Kind.And,
formula1,
formula2,
formula3)
diff --git a/examples/api/python/sygus-fun.py b/examples/api/python/sygus-fun.py
index d2ad1feb4..3cacc33d2 100644
--- a/examples/api/python/sygus-fun.py
+++ b/examples/api/python/sygus-fun.py
@@ -18,7 +18,7 @@
import copy
import pycvc5
import utils
-from pycvc5 import kinds
+from pycvc5 import Kind
if __name__ == "__main__":
slv = pycvc5.Solver()
@@ -45,13 +45,13 @@ if __name__ == "__main__":
zero = slv.mkInteger(0)
one = slv.mkInteger(1)
- plus = slv.mkTerm(kinds.Plus, start, start)
- minus = slv.mkTerm(kinds.Minus, start, start)
- ite = slv.mkTerm(kinds.Ite, start_bool, start, start)
+ plus = slv.mkTerm(Kind.Plus, start, start)
+ minus = slv.mkTerm(Kind.Minus, start, start)
+ ite = slv.mkTerm(Kind.Ite, start_bool, start, start)
- And = slv.mkTerm(kinds.And, start_bool, start_bool)
- Not = slv.mkTerm(kinds.Not, start_bool)
- leq = slv.mkTerm(kinds.Leq, start, start)
+ And = slv.mkTerm(Kind.And, start_bool, start_bool)
+ Not = slv.mkTerm(Kind.Not, start_bool)
+ leq = slv.mkTerm(Kind.Leq, start, start)
# create the grammar object
g = slv.mkSygusGrammar([x, y], [start, start_bool])
@@ -69,25 +69,25 @@ if __name__ == "__main__":
varX = slv.mkSygusVar(integer, "x")
varY = slv.mkSygusVar(integer, "y")
- max_x_y = slv.mkTerm(kinds.ApplyUf, max, varX, varY)
- min_x_y = slv.mkTerm(kinds.ApplyUf, min, varX, varY)
+ max_x_y = slv.mkTerm(Kind.ApplyUf, max, varX, varY)
+ min_x_y = slv.mkTerm(Kind.ApplyUf, min, varX, varY)
# add semantic constraints
# (constraint (>= (max x y) x))
- slv.addSygusConstraint(slv.mkTerm(kinds.Geq, max_x_y, varX))
+ slv.addSygusConstraint(slv.mkTerm(Kind.Geq, max_x_y, varX))
# (constraint (>= (max x y) y))
- slv.addSygusConstraint(slv.mkTerm(kinds.Geq, max_x_y, varY))
+ slv.addSygusConstraint(slv.mkTerm(Kind.Geq, max_x_y, varY))
# (constraint (or (= x (max x y))
# (= y (max x y))))
slv.addSygusConstraint(slv.mkTerm(
- kinds.Or, slv.mkTerm(kinds.Equal, max_x_y, varX), slv.mkTerm(kinds.Equal, max_x_y, varY)))
+ Kind.Or, slv.mkTerm(Kind.Equal, max_x_y, varX), slv.mkTerm(Kind.Equal, max_x_y, varY)))
# (constraint (= (+ (max x y) (min x y))
# (+ x y)))
slv.addSygusConstraint(slv.mkTerm(
- kinds.Equal, slv.mkTerm(kinds.Plus, max_x_y, min_x_y), slv.mkTerm(kinds.Plus, varX, varY)))
+ Kind.Equal, slv.mkTerm(Kind.Plus, max_x_y, min_x_y), slv.mkTerm(Kind.Plus, varX, varY)))
# print solutions if available
if (slv.checkSynth().isUnsat()):
diff --git a/examples/api/python/sygus-grammar.py b/examples/api/python/sygus-grammar.py
index 02a7dff48..466e2cdd3 100644
--- a/examples/api/python/sygus-grammar.py
+++ b/examples/api/python/sygus-grammar.py
@@ -19,7 +19,7 @@
import copy
import utils
import pycvc5
-from pycvc5 import kinds
+from pycvc5 import Kind
if __name__ == "__main__":
slv = pycvc5.Solver()
@@ -42,8 +42,8 @@ if __name__ == "__main__":
# define the rules
zero = slv.mkInteger(0)
- neg_x = slv.mkTerm(kinds.Uminus, x)
- plus = slv.mkTerm(kinds.Plus, x, start)
+ neg_x = slv.mkTerm(Kind.Uminus, x)
+ plus = slv.mkTerm(Kind.Plus, x, start)
# create the grammar object
g1 = slv.mkSygusGrammar({x}, {start})
@@ -72,14 +72,14 @@ if __name__ == "__main__":
# declare universal variables.
varX = slv.mkSygusVar(integer, "x")
- id1_x = slv.mkTerm(kinds.ApplyUf, id1, varX)
- id2_x = slv.mkTerm(kinds.ApplyUf, id2, varX)
- id3_x = slv.mkTerm(kinds.ApplyUf, id3, varX)
- id4_x = slv.mkTerm(kinds.ApplyUf, id4, varX)
+ id1_x = slv.mkTerm(Kind.ApplyUf, id1, varX)
+ id2_x = slv.mkTerm(Kind.ApplyUf, id2, varX)
+ id3_x = slv.mkTerm(Kind.ApplyUf, id3, varX)
+ id4_x = slv.mkTerm(Kind.ApplyUf, id4, varX)
# add semantic constraints
# (constraint (= (id1 x) (id2 x) (id3 x) (id4 x) x))
- slv.addSygusConstraint(slv.mkTerm(kinds.And, [slv.mkTerm(kinds.Equal, id1_x, id2_x), slv.mkTerm(kinds.Equal, id1_x, id3_x), slv.mkTerm(kinds.Equal, id1_x, id4_x), slv.mkTerm(kinds.Equal, id1_x, varX)]))
+ slv.addSygusConstraint(slv.mkTerm(Kind.And, [slv.mkTerm(Kind.Equal, id1_x, id2_x), slv.mkTerm(Kind.Equal, id1_x, id3_x), slv.mkTerm(Kind.Equal, id1_x, id4_x), slv.mkTerm(Kind.Equal, id1_x, varX)]))
# print solutions if available
if (slv.checkSynth().isUnsat()):
diff --git a/examples/api/python/sygus-inv.py b/examples/api/python/sygus-inv.py
index 50fa3f04f..3af4ac5ec 100644
--- a/examples/api/python/sygus-inv.py
+++ b/examples/api/python/sygus-inv.py
@@ -18,7 +18,7 @@
import utils
import pycvc5
-from pycvc5 import kinds
+from pycvc5 import Kind
if __name__ == "__main__":
slv = pycvc5.Solver()
@@ -42,15 +42,15 @@ if __name__ == "__main__":
xp = slv.mkVar(integer, "xp")
# (ite (< x 10) (= xp (+ x 1)) (= xp x))
- ite = slv.mkTerm(kinds.Ite,
- slv.mkTerm(kinds.Lt, x, ten),
- slv.mkTerm(kinds.Equal, xp, slv.mkTerm(kinds.Plus, x, one)),
- slv.mkTerm(kinds.Equal, xp, x))
+ ite = slv.mkTerm(Kind.Ite,
+ slv.mkTerm(Kind.Lt, x, ten),
+ slv.mkTerm(Kind.Equal, xp, slv.mkTerm(Kind.Plus, x, one)),
+ slv.mkTerm(Kind.Equal, xp, x))
# define the pre-conditions, transition relations, and post-conditions
- pre_f = slv.defineFun("pre-f", [x], boolean, slv.mkTerm(kinds.Equal, x, zero))
+ pre_f = slv.defineFun("pre-f", [x], boolean, slv.mkTerm(Kind.Equal, x, zero))
trans_f = slv.defineFun("trans-f", [x, xp], boolean, ite)
- post_f = slv.defineFun("post-f", [x], boolean, slv.mkTerm(kinds.Leq, x, ten))
+ post_f = slv.defineFun("post-f", [x], boolean, slv.mkTerm(Kind.Leq, x, ten))
# declare the invariant-to-synthesize
inv_f = slv.synthInv("inv-f", {x})
diff --git a/examples/api/python/transcendentals.py b/examples/api/python/transcendentals.py
index 39bb343c7..ffeb0c775 100644
--- a/examples/api/python/transcendentals.py
+++ b/examples/api/python/transcendentals.py
@@ -15,7 +15,7 @@
##
import pycvc5
-from pycvc5 import kinds
+from pycvc5 import Kind
if __name__ == "__main__":
slv = pycvc5.Solver()
@@ -30,14 +30,14 @@ if __name__ == "__main__":
# Helper terms
two = slv.mkReal(2)
pi = slv.mkPi()
- twopi = slv.mkTerm(kinds.Mult, two, pi)
- ysq = slv.mkTerm(kinds.Mult, y, y)
- sinx = slv.mkTerm(kinds.Sine, x)
+ twopi = slv.mkTerm(Kind.Mult, two, pi)
+ ysq = slv.mkTerm(Kind.Mult, y, y)
+ sinx = slv.mkTerm(Kind.Sine, x)
# Formulas
- x_gt_pi = slv.mkTerm(kinds.Gt, x, pi)
- x_lt_tpi = slv.mkTerm(kinds.Lt, x, twopi)
- ysq_lt_sinx = slv.mkTerm(kinds.Lt, ysq, sinx)
+ x_gt_pi = slv.mkTerm(Kind.Gt, x, pi)
+ x_lt_tpi = slv.mkTerm(Kind.Lt, x, twopi)
+ ysq_lt_sinx = slv.mkTerm(Kind.Lt, ysq, sinx)
slv.assertFormula(x_gt_pi)
slv.assertFormula(x_lt_tpi)
diff --git a/examples/api/python/utils.py b/examples/api/python/utils.py
index 6d42325b5..cf906bc7a 100644
--- a/examples/api/python/utils.py
+++ b/examples/api/python/utils.py
@@ -15,7 +15,7 @@
##
import pycvc5
-from pycvc5 import kinds
+from pycvc5 import Kind
# Get the string version of define-fun command.
# @param f the function to print
@@ -47,7 +47,7 @@ def print_synth_solutions(terms, sols):
result = ""
for i in range(0, len(terms)):
params = []
- if sols[i].getKind() == kinds.Lambda:
+ if sols[i].getKind() == Kind.Lambda:
params += sols[i][0]
body = sols[i][1]
result += " " + define_fun_to_string(terms[i], params, body) + "\n"
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 96de9afeb..1d57dfeb4 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -151,6 +151,8 @@ libcvc5_add_sources(
printer/smt2/smt2_printer.h
printer/tptp/tptp_printer.cpp
printer/tptp/tptp_printer.h
+ proof/annotation_proof_generator.cpp
+ proof/annotation_proof_generator.h
proof/assumption_proof_generator.cpp
proof/assumption_proof_generator.h
proof/buffered_proof_generator.cpp
@@ -420,6 +422,8 @@ libcvc5_add_sources(
theory/arith/nl/cad/proof_generator.h
theory/arith/nl/cad/variable_ordering.cpp
theory/arith/nl/cad/variable_ordering.h
+ theory/arith/nl/equality_substitution.cpp
+ theory/arith/nl/equality_substitution.h
theory/arith/nl/ext/constraint.cpp
theory/arith/nl/ext/constraint.h
theory/arith/nl/ext/factoring_check.cpp
@@ -681,6 +685,8 @@ libcvc5_add_sources(
theory/incomplete_id.h
theory/inference_id.cpp
theory/inference_id.h
+ theory/inference_id_proof_annotator.cpp
+ theory/inference_id_proof_annotator.h
theory/inference_manager_buffered.cpp
theory/inference_manager_buffered.h
theory/logic_info.cpp
@@ -1013,6 +1019,8 @@ libcvc5_add_sources(
theory/sort_inference.h
theory/strings/array_solver.cpp
theory/strings/array_solver.h
+ theory/strings/array_core_solver.cpp
+ theory/strings/array_core_solver.h
theory/strings/arith_entail.cpp
theory/strings/arith_entail.h
theory/strings/base_solver.cpp
diff --git a/src/api/cpp/cvc5.cpp b/src/api/cpp/cvc5.cpp
index c62dde511..4202a7fab 100644
--- a/src/api/cpp/cvc5.cpp
+++ b/src/api/cpp/cvc5.cpp
@@ -1763,7 +1763,7 @@ size_t Sort::getDatatypeArity() const
CVC5_API_CHECK_NOT_NULL;
CVC5_API_CHECK(isDatatype()) << "Not a datatype sort.";
//////// all checks before this line
- return d_type->getNumChildren() - 1;
+ return d_type->isParametricDatatype() ? d_type->getNumChildren() - 1 : 0;
////////
CVC5_API_TRY_CATCH_END;
}
@@ -2908,7 +2908,7 @@ std::int64_t Term::getInt64Value() const
CVC5_API_ARG_CHECK_EXPECTED(detail::isInt64(*d_node), *d_node)
<< "Term to be a 64-bit integer value when calling getInt64Value()";
//////// all checks before this line
- return detail::getInteger(*d_node).getLong();
+ return detail::getInteger(*d_node).getSigned64();
////////
CVC5_API_TRY_CATCH_END;
}
@@ -2931,7 +2931,7 @@ std::uint64_t Term::getUInt64Value() const
<< "Term to be a unsigned 64-bit integer value when calling "
"getUInt64Value()";
//////// all checks before this line
- return detail::getInteger(*d_node).getUnsignedLong();
+ return detail::getInteger(*d_node).getUnsigned64();
////////
CVC5_API_TRY_CATCH_END;
}
@@ -3029,8 +3029,8 @@ std::pair<std::int64_t, std::uint64_t> Term::getReal64Value() const
<< "Term to be a 64-bit rational value when calling getReal64Value()";
//////// all checks before this line
const Rational& r = detail::getRational(*d_node);
- return std::make_pair(r.getNumerator().getLong(),
- r.getDenominator().getUnsignedLong());
+ return std::make_pair(r.getNumerator().getSigned64(),
+ r.getDenominator().getUnsigned64());
////////
CVC5_API_TRY_CATCH_END;
}
@@ -3558,6 +3558,11 @@ std::ostream& operator<<(std::ostream& out,
bool DatatypeConstructorDecl::isNullHelper() const { return d_ctor == nullptr; }
+bool DatatypeConstructorDecl::isResolved() const
+{
+ return d_ctor == nullptr || d_ctor->isResolved();
+}
+
/* DatatypeDecl ------------------------------------------------------------- */
DatatypeDecl::DatatypeDecl() : d_solver(nullptr), d_dtype(nullptr) {}
@@ -3799,7 +3804,7 @@ Term DatatypeConstructor::getConstructorTerm() const
CVC5_API_TRY_CATCH_END;
}
-Term DatatypeConstructor::getSpecializedConstructorTerm(
+Term DatatypeConstructor::getInstantiatedConstructorTerm(
const Sort& retSort) const
{
CVC5_API_TRY_CATCH_BEGIN;
@@ -3810,13 +3815,7 @@ Term DatatypeConstructor::getSpecializedConstructorTerm(
<< "Cannot get specialized constructor type for non-datatype type "
<< retSort;
//////// all checks before this line
-
- NodeManager* nm = d_solver->getNodeManager();
- Node ret =
- nm->mkNode(kind::APPLY_TYPE_ASCRIPTION,
- nm->mkConst(AscriptionType(
- d_ctor->getSpecializedConstructorType(*retSort.d_type))),
- d_ctor->getConstructor());
+ Node ret = d_ctor->getInstantiatedConstructor(*retSort.d_type);
(void)ret.getType(true); /* kick off type checking */
// apply type ascription to the operator
Term sctor = api::Term(d_solver, ret);
@@ -4110,6 +4109,18 @@ size_t Datatype::getNumConstructors() const
CVC5_API_TRY_CATCH_END;
}
+std::vector<Sort> Datatype::getParameters() const
+{
+ CVC5_API_TRY_CATCH_BEGIN;
+ CVC5_API_CHECK_NOT_NULL;
+ CVC5_API_CHECK(isParametric()) << "Expected parametric datatype";
+ //////// all checks before this line
+ std::vector<cvc5::TypeNode> params = d_dtype->getParameters();
+ return Sort::typeNodeVectorToSorts(d_solver, params);
+ ////////
+ CVC5_API_TRY_CATCH_END;
+}
+
bool Datatype::isParametric() const
{
CVC5_API_TRY_CATCH_BEGIN;
@@ -6737,6 +6748,11 @@ Sort Solver::declareDatatype(
CVC5_API_ARG_CHECK_EXPECTED(ctors.size() > 0, ctors)
<< "a datatype declaration with at least one constructor";
CVC5_API_SOLVER_CHECK_DTCTORDECLS(ctors);
+ for (size_t i = 0, size = ctors.size(); i < size; i++)
+ {
+ CVC5_API_CHECK(!ctors[i].isResolved())
+ << "cannot use a constructor for multiple datatypes";
+ }
//////// all checks before this line
DatatypeDecl dtdecl(this, symbol);
for (size_t i = 0, size = ctors.size(); i < size; i++)
@@ -7296,6 +7312,9 @@ Term Solver::getValue(const Term& term) const
CVC5_API_SOLVER_CHECK_TERM(term);
CVC5_API_RECOVERABLE_CHECK(term.getSort().isFirstClass())
<< "Cannot get value of a term that is not first class.";
+ CVC5_API_RECOVERABLE_CHECK(!term.getSort().isDatatype()
+ || term.getSort().getDatatype().isWellFounded())
+ << "Cannot get value of a term of non-well-founded datatype sort.";
//////// all checks before this line
return getValueHelper(term);
////////
@@ -7314,6 +7333,9 @@ std::vector<Term> Solver::getValue(const std::vector<Term>& terms) const
{
CVC5_API_RECOVERABLE_CHECK(t.getSort().isFirstClass())
<< "Cannot get value of a term that is not first class.";
+ CVC5_API_RECOVERABLE_CHECK(!t.getSort().isDatatype()
+ || t.getSort().getDatatype().isWellFounded())
+ << "Cannot get value of a term of non-well-founded datatype sort.";
}
CVC5_API_SOLVER_CHECK_TERMS(terms);
//////// all checks before this line
diff --git a/src/api/cpp/cvc5.h b/src/api/cpp/cvc5.h
index cd448123a..e3f64349f 100644
--- a/src/api/cpp/cvc5.h
+++ b/src/api/cpp/cvc5.h
@@ -275,8 +275,9 @@ class CVC5_EXPORT Result
/**
* The interal result wrapped by this result.
- * Note: This is a shared_ptr rather than a unique_ptr since cvc5::Result is
- * not ref counted.
+ *
+ * @note This is a ``std::shared_ptr`` rather than a ``std::unique_ptr``
+ * since ``cvc5::Result`` is not ref counted.
*/
std::shared_ptr<cvc5::Result> d_result;
};
@@ -314,6 +315,7 @@ class CVC5_EXPORT Sort
friend class DatatypeConstructorDecl;
friend class DatatypeSelector;
friend class DatatypeDecl;
+ friend class Datatype;
friend class Op;
friend class Solver;
friend class Grammar;
@@ -433,7 +435,11 @@ class CVC5_EXPORT Sort
bool isDatatype() const;
/**
- * Is this a parametric datatype sort?
+ * Is this a parametric datatype sort? A parametric datatype sort is either
+ * one that is returned by a call to Solver::mkDatatypeSort() or
+ * Solver::mkDatatypeSorts() for a parametric datatype, or an instantiated
+ * datatype sort returned by Sort::instantiate() for parametric datatype
+ * sort `s`.
* @return true if the sort is a parametric datatype sort
*/
bool isParametricDatatype() const;
@@ -544,7 +550,7 @@ class CVC5_EXPORT Sort
* or return value for any term that is function-like.
* This is mainly to avoid higher order.
*
- * Note that arrays are explicitly not considered function-like here.
+ * @note Arrays are explicitly not considered function-like here.
*
* @return true if this is a function-like sort
*/
@@ -639,6 +645,9 @@ class CVC5_EXPORT Sort
/**
* @return the codomain sort of a tester sort, which is the Boolean sort
+ *
+ * @note We mainly need this for the symbol table, which doesn't have
+ * access to the solver object.
*/
Sort getTesterCodomainSort() const;
@@ -743,7 +752,14 @@ class CVC5_EXPORT Sort
/* Datatype sort ------------------------------------------------------- */
/**
- * @return the parameter sorts of a datatype sort
+ *
+ * Return the parameters of a parametric datatype sort. If this sort is a
+ * non-instantiated parametric datatype, this returns the parameter sorts of
+ * the underlying datatype. If this sort is an instantiated parametric
+ * datatype, then this returns the sort parameters that were used to
+ * construct the sort via Sort::instantiate().
+ *
+ * @return the parameter sorts of a parametric datatype sort.
*/
std::vector<Sort> getDatatypeParamSorts() const;
@@ -798,9 +814,10 @@ class CVC5_EXPORT Sort
/**
* The internal type wrapped by this sort.
- * Note: This is a shared_ptr rather than a unique_ptr to avoid overhead due
- * to memory allocation (cvc5::Type is already ref counted, so this
- * could be a unique_ptr instead).
+ *
+ * @note This is a ``std::shared_ptr`` rather than a ``std::unique_ptr`` to
+ * avoid overhead due to memory allocation (``cvc5::Type`` is already
+ * ref counted, so this could be a ``std::unique_ptr`` instead).
*/
std::shared_ptr<cvc5::TypeNode> d_type;
};
@@ -947,9 +964,11 @@ class CVC5_EXPORT Op
bool isNullHelper() const;
/**
- * Note: An indexed operator has a non-null internal node, d_node
- * Note 2: We use a helper method to avoid having API functions call
- * other API functions (we need to call this internally)
+ * @note An indexed operator has a non-null internal node (``d_node``).
+ *
+ * @note We use a helper method to avoid having API functions call other API
+ * functions (we need to call this internally).
+ *
* @return true iff this Op is indexed
*/
bool isIndexedHelper() const;
@@ -977,9 +996,10 @@ class CVC5_EXPORT Op
/**
* The internal node wrapped by this operator.
- * Note: This is a shared_ptr rather than a unique_ptr to avoid overhead due
- * to memory allocation (cvc5::Node is already ref counted, so this
- * could be a unique_ptr instead).
+ *
+ * @note This is a ``std::shared_ptr`` rather than a ``std::unique_ptr`` to
+ * avoid overhead due to memory allocation (``cvc5::Node`` is already
+ * ref counted, so this could be a ``std::unique_ptr`` instead).
*/
std::shared_ptr<cvc5::Node> d_node;
};
@@ -1123,8 +1143,9 @@ class CVC5_EXPORT Term
bool hasOp() const;
/**
+ * @note This is safe to call when hasOp() returns true.
+ *
* @return the Op used to create this term
- * Note: This is safe to call when hasOp() returns true.
*/
Op getOp() const;
@@ -1200,9 +1221,9 @@ class CVC5_EXPORT Term
/**
* Iterator for the children of a Term.
- * Note: This treats uninterpreted functions as Term just like any other term
- * for example, the term f(x, y) will have Kind APPLY_UF and three
- * children: f, x, and y
+ * @note This treats uninterpreted functions as Term just like any other term
+ * for example, the term ``f(x, y)`` will have Kind ``APPLY_UF`` and
+ * three children: ``f``, ``x``, and ``y``
*/
class CVC5_EXPORT const_iterator
{
@@ -1236,7 +1257,7 @@ class CVC5_EXPORT Term
/**
* Constructor
* @param slv the associated solver object
- * @param e a shared pointer to the node that we're iterating over
+ * @param e a ``std::shared pointer`` to the node that we're iterating over
* @param p the position of the iterator (e.g. which child it's on)
*/
const_iterator(const Solver* slv,
@@ -1359,9 +1380,9 @@ class CVC5_EXPORT Term
*/
bool isStringValue() const;
/**
- * Note: This method is not to be confused with toString() which returns
- * the term in some string representation, whatever data it may hold. Asserts
- * isStringValue().
+ * Asserts isStringValue().
+ * @note This method is not to be confused with toString(), which returns
+ * some string representation of the term, whatever data it may hold.
* @return the string term as a native string value.
*/
std::wstring getStringValue() const;
@@ -1389,9 +1410,8 @@ class CVC5_EXPORT Term
*/
std::pair<int64_t, uint64_t> getReal64Value() const;
/**
+ * @note A term of kind PI is not considered to be a real value.
* @return true if the term is a rational value.
- *
- * Note that a term of kind PI is not considered to be a real value.
*/
bool isRealValue() const;
/**
@@ -1496,8 +1516,8 @@ class CVC5_EXPORT Term
* where `c1 ... cn` are values ordered by id such that `c1 > ... > cn` (see
* also @ref Term::operator>(const Term&) const).
*
- * Note that a universe set term (kind SET_UNIVERSE) is not considered to be
- * a set value.
+ * @note A universe set term (kind SET_UNIVERSE) is not considered to be
+ * a set value.
*/
bool isSetValue() const;
/**
@@ -1512,9 +1532,9 @@ class CVC5_EXPORT Term
bool isSequenceValue() const;
/**
* Asserts isSequenceValue().
- * Note that it is usually necessary for sequences to call
- * `Solver::simplify()` to turn a sequence that is constructed by, e.g.,
- * concatenation of unit sequences, into a sequence value.
+ * @note It is usually necessary for sequences to call `Solver::simplify()`
+ * to turn a sequence that is constructed by, e.g., concatenation of
+ * unit sequences, into a sequence value.
* @return the representation of a sequence value as a vector of terms.
*/
std::vector<Term> getSequenceValue() const;
@@ -1582,9 +1602,9 @@ class CVC5_EXPORT Term
bool isCastedReal() const;
/**
* The internal node wrapped by this term.
- * Note: This is a shared_ptr rather than a unique_ptr to avoid overhead due
- * to memory allocation (cvc5::Node is already ref counted, so this
- * could be a unique_ptr instead).
+ * @note This is a ``std::shared_ptr`` rather than a ``std::unique_ptr`` to
+ * avoid overhead due to memory allocation (``cvc5::Node`` is already
+ * ref counted, so this could be a ``std::unique_ptr`` instead).
*/
std::shared_ptr<cvc5::Node> d_node;
};
@@ -1726,6 +1746,12 @@ class CVC5_EXPORT DatatypeConstructorDecl
bool isNullHelper() const;
/**
+ * Is the underlying constructor resolved (i.e. has it been used to declare
+ * a datatype already)?
+ */
+ bool isResolved() const;
+
+ /**
* The associated solver object.
*/
const Solver* d_solver;
@@ -1733,8 +1759,8 @@ class CVC5_EXPORT DatatypeConstructorDecl
/**
* The internal (intermediate) datatype constructor wrapped by this
* datatype constructor declaration.
- * Note: This is a shared_ptr rather than a unique_ptr since
- * cvc5::DTypeConstructor is not ref counted.
+ * @note This is a ``std::shared_ptr`` rather than a ``std::unique_ptr``
+ * since ``cvc5::DTypeConstructor`` is not ref counted.
*/
std::shared_ptr<cvc5::DTypeConstructor> d_ctor;
};
@@ -1839,8 +1865,8 @@ class CVC5_EXPORT DatatypeDecl
/**
* The internal (intermediate) datatype wrapped by this datatype
* declaration.
- * Note: This is a shared_ptr rather than a unique_ptr since cvc5::DType is
- * not ref counted.
+ * @note This is a ``std::shared_ptr`` rather than a ``std::unique_ptr``
+ * since ``cvc5::DType`` is not ref counted.
*/
std::shared_ptr<cvc5::DType> d_dtype;
};
@@ -1915,8 +1941,8 @@ class CVC5_EXPORT DatatypeSelector
/**
* The internal datatype selector wrapped by this datatype selector.
- * Note: This is a shared_ptr rather than a unique_ptr since cvc5::DType is
- * not ref counted.
+ * @note This is a ``std::shared_ptr`` rather than a ``std::unique_ptr``
+ * since ``cvc5::DType`` is not ref counted.
*/
std::shared_ptr<cvc5::DTypeSelector> d_stor;
};
@@ -1965,14 +1991,14 @@ class CVC5_EXPORT DatatypeConstructor
* DatatypeConstructor is the one corresponding to nil, and retSort is
* (List Int).
*
- * Furthermore note that the returned constructor term t is an operator,
- * while Solver::mkTerm(APPLY_CONSTRUCTOR, t) is used to construct the above
- * (nullary) application of nil.
+ * @note the returned constructor term ``t`` is an operator, while
+ * ``Solver::mkTerm(APPLY_CONSTRUCTOR, t)`` is used to construct the
+ * above (nullary) application of nil.
*
* @param retSort the desired return sort of the constructor
* @return the constructor term
*/
- Term getSpecializedConstructorTerm(const Sort& retSort) const;
+ Term getInstantiatedConstructorTerm(const Sort& retSort) const;
/**
* Get the tester operator of this datatype constructor.
@@ -2160,8 +2186,8 @@ class CVC5_EXPORT DatatypeConstructor
/**
* The internal datatype constructor wrapped by this datatype constructor.
- * Note: This is a shared_ptr rather than a unique_ptr since cvc5::DType is
- * not ref counted.
+ * @note This is a ``std::shared_ptr`` rather than a ``std::unique_ptr``
+ * since ``cvc5::DType`` is not ref counted.
*/
std::shared_ptr<cvc5::DTypeConstructor> d_ctor;
};
@@ -2223,6 +2249,12 @@ class CVC5_EXPORT Datatype
/** @return the number of constructors for this Datatype. */
size_t getNumConstructors() const;
+ /**
+ * @return the parameters of this datatype, if it is parametric. An exception
+ * is thrown if this datatype is not parametric.
+ */
+ std::vector<Sort> getParameters() const;
+
/** @return true if this datatype is parametric */
bool isParametric() const;
@@ -2417,8 +2449,8 @@ class CVC5_EXPORT Datatype
/**
* The internal datatype wrapped by this datatype.
- * Note: This is a shared_ptr rather than a unique_ptr since cvc5::DType is
- * not ref counted.
+ * @note This is a ``std::shared_ptr`` rather than a ``std::unique_ptr``
+ * since ``cvc5::DType`` is not ref counted.
*/
std::shared_ptr<cvc5::DType> d_dtype;
};
@@ -2557,6 +2589,8 @@ class CVC5_EXPORT Grammar
* with bound variables via purifySygusGTerm, and binding these variables
* via a lambda.
*
+ * @note Create unresolved sorts with Solver::mkUninterpretedSort().
+ *
* @param dt the non-terminal's datatype to which a constructor is added
* @param term the sygus operator of the constructor
* @param ntsToUnres mapping from non-terminals to their unresolved sorts
@@ -3120,6 +3154,8 @@ class CVC5_EXPORT Solver
* When constructing datatypes, unresolved sorts are replaced by the datatype
* sort constructed for the datatype declaration it is associated with.
*
+ * @note Create unresolved sorts with Solver::mkUninterpretedSort().
+ *
* @param dtypedecls the datatype declarations from which the sort is created
* @param unresolvedSorts the list of unresolved sorts
* @return the datatype sorts
@@ -3324,12 +3360,13 @@ class CVC5_EXPORT Solver
/* .................................................................... */
/**
- * Create an operator for a builtin Kind
+ * Create an operator for a builtin Kind.
+ *
* The Kind may not be the Kind for an indexed operator
- * (e.g. BITVECTOR_EXTRACT)
- * Note: in this case, the Op simply wraps the Kind.
- * The Kind can be used in mkTerm directly without
- * creating an op first.
+ * (e.g. BITVECTOR_EXTRACT).
+ *
+ * @note In this case, the ``Op`` simply wraps the ``Kind``. The Kind can be
+ * used in ``Solver::mkTerm`` directly without creating an ``Op`` first.
* @param kind the kind to wrap
*/
Op mkOp(Kind kind) const;
@@ -3535,7 +3572,7 @@ class CVC5_EXPORT Solver
/**
* Create a bit-vector constant of given size and value.
*
- * Note: The given value must fit into a bit-vector of the given size.
+ * @note The given value must fit into a bit-vector of the given size.
*
* @param size the bit-width of the bit-vector sort
* @param val the value of the constant
@@ -3547,7 +3584,7 @@ class CVC5_EXPORT Solver
* Create a bit-vector constant of a given bit-width from a given string of
* base 2, 10 or 16.
*
- * Note: The given value must fit into a bit-vector of the given size.
+ * @note The given value must fit into a bit-vector of the given size.
*
* @param size the bit-width of the constant
* @param s the string representation of the constant
@@ -4312,9 +4349,10 @@ class CVC5_EXPORT Solver
void setOption(const std::string& option, const std::string& value) const;
/**
- * If needed, convert this term to a given sort. Note that the sort of the
- * term must be convertible into the target sort. Currently only Int to Real
- * conversions are supported.
+ * If needed, convert this term to a given sort.
+ *
+ * @note The sort of the term must be convertible into the target sort.
+ * Currently only Int to Real conversions are supported.
* @param t the term
* @param s the target sort
* @return the term wrapped into a sort conversion if needed
diff --git a/src/api/cpp/cvc5_kind.h b/src/api/cpp/cvc5_kind.h
index 73843f9b5..e465a8faa 100644
--- a/src/api/cpp/cvc5_kind.h
+++ b/src/api/cpp/cvc5_kind.h
@@ -2013,7 +2013,7 @@ enum Kind : int32_t
* Operator for tuple projection indices
*
* Parameters:
- * - 1: The tuple projection indices
+ * - 1: A vector of tuple projection indices.
*
* Create with:
* - `Solver::mkOp(Kind TUPLE_PROJECT, std::vector<uint32_t> param) const`
diff --git a/src/api/java/genkinds.py.in b/src/api/java/genkinds.py.in
index d44ae3c0d..18ac5ec3c 100644
--- a/src/api/java/genkinds.py.in
+++ b/src/api/java/genkinds.py.in
@@ -21,7 +21,7 @@ import argparse
import os
import sys
import re
-
+import textwrap
# get access to cvc5/src/api/parsekinds.py
@@ -110,11 +110,7 @@ CPP_JAVA_MAPPING = \
def format_comment(comment):
for pattern, replacement in CPP_JAVA_MAPPING.items():
comment = re.sub(pattern, replacement, comment)
- java_comment = "\n /**"
- for line in comment.split("\n"):
- java_comment += "\n * " + line
- java_comment = " " + java_comment.strip() + "/"
- return java_comment
+ return """ /**\n{}\n */""".format(textwrap.indent(comment, ' * '))
# Files generation
diff --git a/src/api/java/io/github/cvc5/api/Datatype.java b/src/api/java/io/github/cvc5/api/Datatype.java
index bc33ba10b..39ea2bb19 100644
--- a/src/api/java/io/github/cvc5/api/Datatype.java
+++ b/src/api/java/io/github/cvc5/api/Datatype.java
@@ -108,6 +108,18 @@ public class Datatype extends AbstractPointer implements Iterable<DatatypeConstr
private native int getNumConstructors(long pointer);
+ /**
+ * @return the parameters of this datatype, if it is parametric. An exception
+ * is thrown if this datatype is not parametric.
+ */
+ public Sort[] getParameters() {
+ long[] sortPointers = getParameters(pointer);
+ Sort[] sorts = Utils.getSorts(solver, sortPointers);
+ return sorts;
+ }
+
+ private native long[] getParameters(long pointer);
+
/** @return true if this datatype is parametric */
public boolean isParametric()
{
diff --git a/src/api/java/io/github/cvc5/api/DatatypeConstructor.java b/src/api/java/io/github/cvc5/api/DatatypeConstructor.java
index 5fd9d8407..4a041dd99 100644
--- a/src/api/java/io/github/cvc5/api/DatatypeConstructor.java
+++ b/src/api/java/io/github/cvc5/api/DatatypeConstructor.java
@@ -78,13 +78,14 @@ public class DatatypeConstructor extends AbstractPointer implements Iterable<Dat
* @param retSort the desired return sort of the constructor
* @return the constructor term
*/
- public Term getSpecializedConstructorTerm(Sort retSort)
- {
- long termPointer = getSpecializedConstructorTerm(pointer, retSort.getPointer());
+ public Term getInstantiatedConstructorTerm(Sort retSort) {
+ long termPointer =
+ getInstantiatedConstructorTerm(pointer, retSort.getPointer());
return new Term(solver, termPointer);
}
- private native long getSpecializedConstructorTerm(long pointer, long retSortPointer);
+ private native long getInstantiatedConstructorTerm(
+ long pointer, long retSortPointer);
/**
* Get the tester operator of this datatype constructor.
diff --git a/src/api/java/io/github/cvc5/api/Solver.java b/src/api/java/io/github/cvc5/api/Solver.java
index 16220228c..6f86928ca 100644
--- a/src/api/java/io/github/cvc5/api/Solver.java
+++ b/src/api/java/io/github/cvc5/api/Solver.java
@@ -639,10 +639,9 @@ public class Solver implements IPointer, AutoCloseable
/**
* Create an operator for a builtin Kind
* The Kind may not be the Kind for an indexed operator
- * (e.g. BITVECTOR_EXTRACT)
- * Note: in this case, the Op simply wraps the Kind.
- * The Kind can be used in mkTerm directly without
- * creating an op first.
+ * (e.g. BITVECTOR_EXTRACT).
+ * @apiNote In this case, the Op simply wraps the Kind. The Kind can be used
+ * in mkTerm directly without creating an op first.
* @param kind the kind to wrap
*/
public Op mkOp(Kind kind)
@@ -1017,7 +1016,7 @@ public class Solver implements IPointer, AutoCloseable
/**
* Create a bit-vector constant of given size and value.
*
- * Note: The given value must fit into a bit-vector of the given size.
+ * @apiNote The given value must fit into a bit-vector of the given size.
*
* @param size the bit-width of the bit-vector sort
* @param val the value of the constant
@@ -1037,7 +1036,7 @@ public class Solver implements IPointer, AutoCloseable
* Create a bit-vector constant of a given bit-width from a given string of
* base 2, 10 or 16.
*
- * Note: The given value must fit into a bit-vector of the given size.
+ * @apiNote The given value must fit into a bit-vector of the given size.
*
* @param size the bit-width of the constant
* @param s the string representation of the constant
@@ -2355,9 +2354,10 @@ public class Solver implements IPointer, AutoCloseable
private native void setOption(long pointer, String option, String value);
/**
- * If needed, convert this term to a given sort. Note that the sort of the
- * term must be convertible into the target sort. Currently only Int to Real
- * conversions are supported.
+ * If needed, convert this term to a given sort.
+ *
+ * @apiNote The sort of the term must be convertible into the target sort.
+ * Currently only Int to Real conversions are supported.
* @param t the term
* @param s the target sort
* @return the term wrapped into a sort conversion if needed
diff --git a/src/api/java/io/github/cvc5/api/Sort.java b/src/api/java/io/github/cvc5/api/Sort.java
index 440b1ba59..6bd87a9af 100644
--- a/src/api/java/io/github/cvc5/api/Sort.java
+++ b/src/api/java/io/github/cvc5/api/Sort.java
@@ -372,7 +372,7 @@ public class Sort extends AbstractPointer implements Comparable<Sort>
* or return value for any term that is function-like.
* This is mainly to avoid higher order.
*
- * Note that arrays are explicitly not considered function-like here.
+ * @apiNote Arrays are explicitly not considered function-like here.
*
* @return true if this is a function-like sort
*/
@@ -752,6 +752,12 @@ public class Sort extends AbstractPointer implements Comparable<Sort>
/* Datatype sort ------------------------------------------------------- */
/**
+ * Return the parameters of a parametric datatype sort. If this sort is a
+ * non-instantiated parametric datatype, this returns the parameter sorts of
+ * the underlying datatype. If this sort is an instantiated parametric
+ * datatype, then this returns the sort parameters that were used to
+ * construct the sort via Sort.instantiate().
+ *
* @return the parameter sorts of a datatype sort
*/
public Sort[] getDatatypeParamSorts()
diff --git a/src/api/java/io/github/cvc5/api/Term.java b/src/api/java/io/github/cvc5/api/Term.java
index fc09767ed..db780f9bd 100644
--- a/src/api/java/io/github/cvc5/api/Term.java
+++ b/src/api/java/io/github/cvc5/api/Term.java
@@ -190,7 +190,7 @@ public class Term extends AbstractPointer implements Comparable<Term>, Iterable<
/**
* @return the Op used to create this term
- * Note: This is safe to call when hasOp() returns true.
+ * @apiNote This is safe to call when hasOp() returns true.
*/
public Op getOp()
{
@@ -367,10 +367,11 @@ public class Term extends AbstractPointer implements Comparable<Term>, Iterable<
/**
* @return the stored string constant.
- * <p>
- * Note: This method is not to be confused with toString() which returns the
- * term in some string representation, whatever data it may hold.
+ *
* Asserts isString().
+ *
+ * @apiNote This method is not to be confused with toString() which returns
+ * the term in some string representation, whatever data it may hold.
*/
public String getStringValue()
{
@@ -623,9 +624,9 @@ public class Term extends AbstractPointer implements Comparable<Term>, Iterable<
/**
* Asserts isSequenceValue().
- * Note that it is usually necessary for sequences to call
- * `Solver::simplify()` to turn a sequence that is constructed by, e.g.,
- * concatenation of unit sequences, into a sequence value.
+ * @apiNote It is usually necessary for sequences to call
+ * `Solver::simplify()` to turn a sequence that is constructed by,
+ * e.g., concatenation of unit sequences, into a sequence value.
* @return the representation of a sequence value as a vector of terms.
*/
public Term[] getSequenceValue()
diff --git a/src/api/java/jni/datatype.cpp b/src/api/java/jni/datatype.cpp
index 3f340c93c..6cc8ba58e 100644
--- a/src/api/java/jni/datatype.cpp
+++ b/src/api/java/jni/datatype.cpp
@@ -114,6 +114,28 @@ JNIEXPORT jint JNICALL Java_io_github_cvc5_api_Datatype_getNumConstructors(
/*
* Class: io_github_cvc5_api_Datatype
+ * Method: getParameters
+ * Signature: (J)[J
+ */
+JNIEXPORT jlongArray JNICALL Java_io_github_cvc5_api_Datatype_getParameters(
+ JNIEnv* env, jobject, jlong pointer)
+{
+ CVC5_JAVA_API_TRY_CATCH_BEGIN;
+ Datatype* current = (Datatype*)pointer;
+ std::vector<Sort> sorts = current->getParameters();
+ std::vector<jlong> sortPointers(sorts.size());
+ for (size_t i = 0; i < sorts.size(); i++)
+ {
+ sortPointers[i] = reinterpret_cast<jlong>(new Sort(sorts[i]));
+ }
+ jlongArray ret = env->NewLongArray(sorts.size());
+ env->SetLongArrayRegion(ret, 0, sorts.size(), sortPointers.data());
+ return ret;
+ CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, nullptr);
+}
+
+/*
+ * Class: io_github_cvc5_api_Datatype
* Method: isParametric
* Signature: (J)Z
*/
diff --git a/src/api/java/jni/datatype_constructor.cpp b/src/api/java/jni/datatype_constructor.cpp
index 7fe5f21c6..de9e4fa4c 100644
--- a/src/api/java/jni/datatype_constructor.cpp
+++ b/src/api/java/jni/datatype_constructor.cpp
@@ -65,17 +65,17 @@ Java_io_github_cvc5_api_DatatypeConstructor_getConstructorTerm(JNIEnv* env,
/*
* Class: io_github_cvc5_api_DatatypeConstructor
- * Method: getSpecializedConstructorTerm
+ * Method: getInstantiatedConstructorTerm
* Signature: (JJ)J
*/
JNIEXPORT jlong JNICALL
-Java_io_github_cvc5_api_DatatypeConstructor_getSpecializedConstructorTerm(
+Java_io_github_cvc5_api_DatatypeConstructor_getInstantiatedConstructorTerm(
JNIEnv* env, jobject, jlong pointer, jlong retSortPointer)
{
CVC5_JAVA_API_TRY_CATCH_BEGIN;
DatatypeConstructor* current = (DatatypeConstructor*)pointer;
Sort* sort = (Sort*)retSortPointer;
- Term* retPointer = new Term(current->getSpecializedConstructorTerm(*sort));
+ Term* retPointer = new Term(current->getInstantiatedConstructorTerm(*sort));
return (jlong)retPointer;
CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, 0);
}
diff --git a/src/api/parsekinds.py b/src/api/parsekinds.py
index 14762c24c..db72b20c9 100644
--- a/src/api/parsekinds.py
+++ b/src/api/parsekinds.py
@@ -22,7 +22,7 @@ handle nested '#if 0' pairs.
"""
from collections import OrderedDict
-
+import textwrap
##################### Useful Constants ################
OCB = '{'
@@ -120,19 +120,19 @@ class KindsParser:
def format_comment(self, comment):
'''
- Removes the C++ syntax for block comments and returns just the text
+ Removes the C++ syntax for block comments and returns just the text.
'''
- assert comment[0] == '/', \
- "Expecting to start with / but got %s" % comment[0]
- assert comment[-1] == '/', \
- "Expecting to end with / but got %s" % comment[-1]
- res = ""
- for line in comment.strip("/* \t").split("\n"):
- line = line.strip("*")
- if line:
- res += line
- res += "\n"
- return res
+ assert comment[:2] == '/*', \
+ "Expecting to start with /* but got \"{}\"".format(comment[:2])
+ assert comment[-2:] == '*/', \
+ "Expecting to end with */ but got \"{}\"".format(comment[-2:])
+ comment = comment[2:-2].strip('*\n') # /** ... */ -> ...
+ comment = textwrap.dedent(comment) # remove indentation
+ comment = comment.replace('\n*', '\n') # remove leading "*""
+ comment = textwrap.dedent(comment) # remove indentation
+ comment = comment.replace('\\rst', '').replace('\\endrst', '')
+ comment = comment.strip() # remove leading and trailing spaces
+ return comment
def ignore_block(self, line):
'''
diff --git a/src/api/python/CMakeLists.txt b/src/api/python/CMakeLists.txt
index 32022effe..bcf5d3379 100644
--- a/src/api/python/CMakeLists.txt
+++ b/src/api/python/CMakeLists.txt
@@ -64,6 +64,7 @@ add_custom_command(
--kinds-file-prefix "${CMAKE_CURRENT_BINARY_DIR}/cvc5kinds"
DEPENDS
"${CMAKE_CURRENT_BINARY_DIR}/genkinds.py"
+ "${PROJECT_SOURCE_DIR}/src/api/parsekinds.py"
"${PROJECT_SOURCE_DIR}/src/api/cpp/cvc5_kind.h"
)
diff --git a/src/api/python/__init__.py.in b/src/api/python/__init__.py.in
index 9116976c3..8ce03e26d 100644
--- a/src/api/python/__init__.py.in
+++ b/src/api/python/__init__.py.in
@@ -1,4 +1,2 @@
import sys
from .pycvc5 import *
-# fake a submodule for dotted imports, e.g. from pycvc5.kinds import *
-sys.modules['%s.%s'%(__name__, kinds.__name__)] = kinds
diff --git a/src/api/python/cvc5.pxd b/src/api/python/cvc5.pxd
index f5dc2aca2..2baed575a 100644
--- a/src/api/python/cvc5.pxd
+++ b/src/api/python/cvc5.pxd
@@ -51,6 +51,7 @@ cdef extern from "api/cpp/cvc5.h" namespace "cvc5::api":
DatatypeSelector getSelector(const string& name) except +
string getName() except +
size_t getNumConstructors() except +
+ vector[Sort] getParameters() except +
bint isParametric() except +
bint isCodatatype() except +
bint isTuple() except +
@@ -76,7 +77,7 @@ cdef extern from "api/cpp/cvc5.h" namespace "cvc5::api":
DatatypeSelector operator[](const string& name) except +
string getName() except +
Term getConstructorTerm() except +
- Term getSpecializedConstructorTerm(const Sort& retSort) except +
+ Term getInstantiatedConstructorTerm(const Sort& retSort) except +
Term getTesterTerm() except +
size_t getNumSelectors() except +
DatatypeSelector getSelector(const string& name) except +
diff --git a/src/api/python/cvc5.pxi b/src/api/python/cvc5.pxi
index aa207cd40..5c75047ef 100644
--- a/src/api/python/cvc5.pxi
+++ b/src/api/python/cvc5.pxi
@@ -153,6 +153,18 @@ cdef class Datatype:
"""
return self.cd.getNumConstructors()
+ def getParameters(self):
+ """
+ :return: the parameters of this datatype, if it is parametric. An
+ exception is thrown if this datatype is not parametric.
+ """
+ param_sorts = []
+ for s in self.cd.getParameters():
+ sort = Sort(self.solver)
+ sort.csort = s
+ param_sorts.append(sort)
+ return param_sorts
+
def isParametric(self):
""":return: True if this datatype is parametric."""
return self.cd.isParametric()
@@ -233,15 +245,17 @@ cdef class DatatypeConstructor:
term.cterm = self.cdc.getConstructorTerm()
return term
- def getSpecializedConstructorTerm(self, Sort retSort):
+ def getInstantiatedConstructorTerm(self, Sort retSort):
"""
- Specialized method for parametric datatypes (see :cpp:func:`DatatypeConstructor::getSpecializedConstructorTerm() <cvc5::api::DatatypeConstructor::getSpecializedConstructorTerm>`).
+ Specialized method for parametric datatypes (see
+ :cpp:func:`DatatypeConstructor::getInstantiatedConstructorTerm()
+ <cvc5::api::DatatypeConstructor::getInstantiatedConstructorTerm>`).
:param retSort: the desired return sort of the constructor
:return: the constructor operator as a term.
"""
cdef Term term = Term(self.solver)
- term.cterm = self.cdc.getSpecializedConstructorTerm(retSort.csort)
+ term.cterm = self.cdc.getInstantiatedConstructorTerm(retSort.csort)
return term
def getTesterTerm(self):
@@ -464,7 +478,7 @@ cdef class Op:
"""
:return: the kind of this operator.
"""
- return kind(<int> self.cop.getKind())
+ return Kind(<int> self.cop.getKind())
def isIndexed(self):
"""
@@ -982,7 +996,7 @@ cdef class Solver:
cdef vector[c_Term] v
op = kind_or_op
- if isinstance(kind_or_op, kind):
+ if isinstance(kind_or_op, Kind):
op = self.mkOp(kind_or_op)
if len(args) == 0:
@@ -1012,7 +1026,7 @@ cdef class Solver:
return result
@expand_list_arg(num_req_args=0)
- def mkOp(self, kind k, *args):
+ def mkOp(self, k, *args):
"""
Supports the following uses:
@@ -1027,27 +1041,27 @@ cdef class Solver:
cdef vector[uint32_t] v
if len(args) == 0:
- op.cop = self.csolver.mkOp(k.k)
+ op.cop = self.csolver.mkOp(<c_Kind> k.value)
elif len(args) == 1:
if isinstance(args[0], str):
- op.cop = self.csolver.mkOp(k.k,
+ op.cop = self.csolver.mkOp(<c_Kind> k.value,
<const string &>
args[0].encode())
elif isinstance(args[0], int):
- op.cop = self.csolver.mkOp(k.k, <int?> args[0])
+ op.cop = self.csolver.mkOp(<c_Kind> k.value, <int?> args[0])
elif isinstance(args[0], list):
for a in args[0]:
if a < 0 or a >= 2 ** 31:
raise ValueError("Argument {} must fit in a uint32_t".format(a))
v.push_back((<uint32_t?> a))
- op.cop = self.csolver.mkOp(k.k, <const vector[uint32_t]&> v)
+ op.cop = self.csolver.mkOp(<c_Kind> k.value, <const vector[uint32_t]&> v)
else:
raise ValueError("Unsupported signature"
" mkOp: {}".format(" X ".join([str(k), str(args[0])])))
elif len(args) == 2:
if isinstance(args[0], int) and isinstance(args[1], int):
- op.cop = self.csolver.mkOp(k.k, <int> args[0], <int> args[1])
+ op.cop = self.csolver.mkOp(<c_Kind> k.value, <int> args[0], <int> args[1])
else:
raise ValueError("Unsupported signature"
" mkOp: {}".format(" X ".join([k, args[0], args[1]])))
@@ -2439,16 +2453,16 @@ cdef class Sort:
def isFunctionLike(self):
"""
- Is this a function-LIKE sort?
+ Is this a function-LIKE sort?
- Anything function-like except arrays (e.g., datatype selectors) is
- considered a function here. Function-like terms can not be the argument
- or return value for any term that is function-like.
- This is mainly to avoid higher order.
+ Anything function-like except arrays (e.g., datatype selectors) is
+ considered a function here. Function-like terms can not be the argument
+ or return value for any term that is function-like.
+ This is mainly to avoid higher order.
- Note that arrays are explicitly not considered function-like here.
+ .. note:: Arrays are explicitly not considered function-like here.
- :return: True if this is a function-like sort
+ :return: True if this is a function-like sort
"""
return self.csort.isFunctionLike()
@@ -2706,7 +2720,14 @@ cdef class Sort:
def getDatatypeParamSorts(self):
"""
- :return: the parameter sorts of a datatype sort
+ Return the parameters of a parametric datatype sort. If this sort
+ is a non-instantiated parametric datatype, this returns the
+ parameter sorts of the underlying datatype. If this sort is an
+ instantiated parametric datatype, then this returns the sort
+ parameters that were used to construct the sort via
+ :py:meth:`instantiate()`.
+
+ :return: the parameter sorts of a parametric datatype sort
"""
param_sorts = []
for s in self.csort.getDatatypeParamSorts():
@@ -2801,7 +2822,7 @@ cdef class Term:
def getKind(self):
""":return: the :py:class:`pycvc5.Kind` of this term."""
- return kind(<int> self.cterm.getKind())
+ return Kind(<int> self.cterm.getKind())
def getSort(self):
""":return: the :py:class:`pycvc5.Sort` of this term."""
@@ -2848,10 +2869,10 @@ cdef class Term:
def getOp(self):
"""
- Note: This is safe to call when :py:meth:`hasOp()` returns True.
+ .. note:: This is safe to call when :py:meth:`hasOp()` returns True.
- :return: the :py:class:`pycvc5.Op` used to create this Term.
- """
+ :return: the :py:class:`pycvc5.Op` used to create this Term.
+ """
cdef Op op = Op(self.solver)
op.cop = self.cterm.getOp()
return op
@@ -2981,13 +3002,15 @@ cdef class Term:
def getStringValue(self):
"""
- Note: This method is not to be confused with :py:meth:`__str__()` which
- returns the term in some string representation, whatever data it
- may hold.
- Asserts :py:meth:`isStringValue()`.
+ Asserts :py:meth:`isStringValue()`.
- :return: the string term as a native string value.
- """
+ .. note::
+ This method is not to be confused with :py:meth:`__str__()` which
+ returns the term in some string representation, whatever data it
+ may hold.
+
+ :return: the string term as a native string value.
+ """
cdef Py_ssize_t size
cdef c_wstring s = self.cterm.getStringValue()
return PyUnicode_FromWideChar(s.data(), s.size())
@@ -3053,19 +3076,23 @@ cdef class Term:
def isSetValue(self):
"""
- A term is a set value if it is considered to be a (canonical) constant set
- value. A canonical set value is one whose AST is:
-
- (union (singleton c1) ... (union (singleton c_{n-1}) (singleton c_n))))
-
- where ``c1 ... cn`` are values ordered by id such that ``c1 > ... > cn`` (see
- also :cpp:func:`cvc5::api::Term::operator>()`).
-
- Note that a universe set term ``(kind SET_UNIVERSE)`` is not considered to be
+ A term is a set value if it is considered to be a (canonical) constant
+ set value. A canonical set value is one whose AST is:
+
+ .. code::
+
+ (union
+ (singleton c1) ... (union (singleton c_{n-1}) (singleton c_n))))
+
+ where ``c1 ... cn`` are values ordered by id such that
+ ``c1 > ... > cn`` (see also :cpp:func:`cvc5::api::Term::operator>()`).
+
+ .. note::
+ A universe set term ``(kind SET_UNIVERSE)`` is not considered to be
a set value.
- :return: True if the term is a set value.
- """
+ :return: True if the term is a set value.
+ """
return self.cterm.isSetValue()
def getSetValue(self):
@@ -3087,14 +3114,15 @@ cdef class Term:
def getSequenceValue(self):
"""
- Asserts :py:meth:`isSequenceValue()`.
-
- Note that it is usually necessary for sequences to call
- :py:meth:`Solver.simplify()` to turn a sequence that is constructed by, e.g.,
- concatenation of unit sequences, into a sequence value.
-
- :return: the representation of a sequence value as a vector of terms.
- """
+ Asserts :py:meth:`isSequenceValue()`.
+
+ .. note::
+ It is usually necessary for sequences to call
+ :py:meth:`Solver.simplify()` to turn a sequence that is constructed
+ by, e.g., concatenation of unit sequences, into a sequence value.
+
+ :return: the representation of a sequence value as a vector of terms.
+ """
elems = []
for e in self.cterm.getSequenceValue():
term = Term(self.solver)
@@ -3137,7 +3165,7 @@ cdef class Term:
def isRealValue(self):
"""
- Note that a term of kind PI is not considered to be a real value.
+ .. note:: A term of kind PI is not considered to be a real value.
:return: True iff this term is a rational value.
"""
@@ -3199,13 +3227,13 @@ cdef class Term:
# on a constant array
while to_visit:
t = to_visit.pop()
- if t.getKind() == kinds.Store:
+ if t.getKind().value == c_Kind.STORE:
# save the mappings
keys.append(t[1].toPythonObj())
values.append(t[2].toPythonObj())
to_visit.append(t[0])
else:
- assert t.getKind() == kinds.ConstArray
+ assert t.getKind().value == c_Kind.CONST_ARRAY
base_value = t.getConstArrayBase().toPythonObj()
assert len(keys) == len(values)
diff --git a/src/api/python/genkinds.py.in b/src/api/python/genkinds.py.in
index 8c8de35ac..4af1f526e 100644
--- a/src/api/python/genkinds.py.in
+++ b/src/api/python/genkinds.py.in
@@ -39,97 +39,49 @@ DEFAULT_PREFIX = 'kinds'
################ Comments and Macro Tokens ############
PYCOMMENT = '#'
-####################### Code Blocks ###################
-CDEF_KIND = " cdef Kind "
-
KINDS_PXD_TOP = \
r"""cdef extern from "api/cpp/cvc5_kind.h" namespace "cvc5::api":
- cdef cppclass Kind:
- pass
-
-
-# Kind declarations: See cpp/cvc5_kind.h for additional information
-cdef extern from "api/cpp/cvc5_kind.h" namespace "cvc5::api::Kind":
+ enum Kind:
"""
KINDS_PXI_TOP = \
-r"""# distutils: language = c++
+r'''# distutils: language = c++
# distutils: extra_compile_args = -std=c++11
-from cvc5kinds cimport *
-import sys
-from types import ModuleType
-
-from libcpp.string cimport string
-from libcpp.unordered_map cimport unordered_map
-
-# these maps are used for creating a kind
-# it is needed for dynamically making a kind
-# e.g. for getKind()
-cdef unordered_map[int, Kind] int2kind
-cdef unordered_map[int, string] int2name
-
-cdef class kind:
- cdef Kind k
- cdef str name
- def __cinit__(self, int kindint):
- self.k = int2kind[kindint]
- self.name = str(int2name[kindint])
-
- def __eq__(self, kind other):
- return (<int> self.k) == (<int> other.k)
-
- def __ne__(self, kind other):
- return (<int> self.k) != (<int> other.k)
+from cvc5kinds cimport Kind as c_Kind
+from enum import Enum
- def __hash__(self):
- return hash((<int> self.k, self.name))
-
- def __str__(self):
- return self.name
-
- def __repr__(self):
- return self.name
-
- def as_int(self):
- return <int> self.k
-
-# create a kinds submodule
-kinds = ModuleType('kinds')
-kinds.__file__ = kinds.__name__ + ".py"
-"""
-
-KINDS_ATTR_TEMPLATE = \
-r"""
-int2kind[<int> {kind}] = {kind}
-int2name[<int> {kind}] = b"{name}"
-cdef kind {name} = kind(<int> {kind})
-setattr(kinds, "{name}", {name})
-"""
+class Kind(Enum):
+ """The Kinds enum"""
+ def __new__(cls, value, doc):
+ self = object.__new__(cls)
+ self._value_ = value
+ self.__doc__ = doc
+ return self
+'''
+KINDS_ATTR_TEMPLATE = r''' {name}=c_Kind.{kind}, """{doc}"""
+'''
def gen_pxd(parser: KindsParser, filename):
- f = open(filename, "w")
- f.write(KINDS_PXD_TOP)
- # include the format_name docstring in the generated file
- # could be helpful for users to see the formatting rules
- for line in parser.format_name.__doc__.split(NL):
- f.write(PYCOMMENT)
- if not line.isspace():
- f.write(line)
- f.write(NL)
- for kind in parser.kinds:
- f.write(CDEF_KIND + kind + NL)
- f.close()
+ with open(filename, "w") as f:
+ # include the format_name docstring in the generated file
+ # could be helpful for users to see the formatting rules
+ for line in parser.format_name.__doc__.split(NL):
+ f.write(PYCOMMENT)
+ if not line.isspace():
+ f.write(line)
+ f.write(NL)
+ f.write(KINDS_PXD_TOP)
+ for kind in parser.kinds:
+ f.write(' {},\n'.format(kind))
def gen_pxi(parser : KindsParser, filename):
- f = open(filename, "w")
- pxi = KINDS_PXI_TOP
- for kind, name in parser.kinds.items():
- pxi += KINDS_ATTR_TEMPLATE.format(name=name, kind=kind)
- f.write(pxi)
- f.close()
-
+ with open(filename, "w") as f:
+ f.write(KINDS_PXI_TOP)
+ for kind, name in parser.kinds.items():
+ doc = parser.kinds_doc.get(name, '')
+ f.write(KINDS_ATTR_TEMPLATE.format(name=name, kind=kind, doc=doc))
if __name__ == "__main__":
parser = argparse.ArgumentParser('Read a kinds header file and generate a '
diff --git a/src/base/CMakeLists.txt b/src/base/CMakeLists.txt
index d2c763159..8769ac323 100644
--- a/src/base/CMakeLists.txt
+++ b/src/base/CMakeLists.txt
@@ -48,7 +48,6 @@ file(GLOB_RECURSE source_files
${PROJECT_SOURCE_DIR}/src/*.cc
${PROJECT_SOURCE_DIR}/src/*.h
${PROJECT_SOURCE_DIR}/src/*.g)
-string(REPLACE ";" " " source_files_list "${source_files}")
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Debug_tags.h
diff --git a/src/base/output.h b/src/base/output.h
index 7bfae7bca..9ae5ad8db 100644
--- a/src/base/output.h
+++ b/src/base/output.h
@@ -357,82 +357,6 @@ class __cvc5_true
inline operator bool() { return true; }
}; /* __cvc5_true */
-#if defined(CVC5_DEBUG) && defined(CVC5_TRACING)
-
-class ScopedDebug
-{
- std::string d_tag;
- bool d_oldSetting;
-
-public:
-
- ScopedDebug(std::string tag, bool newSetting = true) :
- d_tag(tag) {
- d_oldSetting = Debug.isOn(d_tag);
- if(newSetting) {
- Debug.on(d_tag);
- } else {
- Debug.off(d_tag);
- }
- }
-
- ~ScopedDebug() {
- if(d_oldSetting) {
- Debug.on(d_tag);
- } else {
- Debug.off(d_tag);
- }
- }
-}; /* class ScopedDebug */
-
-#else /* CVC5_DEBUG && CVC5_TRACING */
-
-class ScopedDebug
-{
- public:
- ScopedDebug(std::string tag, bool newSetting = true) {}
-}; /* class ScopedDebug */
-
-#endif /* CVC5_DEBUG && CVC5_TRACING */
-
-#ifdef CVC5_TRACING
-
-class ScopedTrace
-{
- std::string d_tag;
- bool d_oldSetting;
-
-public:
-
- ScopedTrace(std::string tag, bool newSetting = true) :
- d_tag(tag) {
- d_oldSetting = Trace.isOn(d_tag);
- if(newSetting) {
- Trace.on(d_tag);
- } else {
- Trace.off(d_tag);
- }
- }
-
- ~ScopedTrace() {
- if(d_oldSetting) {
- Trace.on(d_tag);
- } else {
- Trace.off(d_tag);
- }
- }
-}; /* class ScopedTrace */
-
-#else /* CVC5_TRACING */
-
-class ScopedTrace
-{
- public:
- ScopedTrace(std::string tag, bool newSetting = true) {}
-}; /* class ScopedTrace */
-
-#endif /* CVC5_TRACING */
-
/**
* Pushes an indentation level on construction, pop on destruction.
* Useful for tracing recursive functions especially, but also can be
@@ -442,23 +366,11 @@ class ScopedTrace
class IndentedScope
{
Cvc5ostream d_out;
-
public:
- inline IndentedScope(Cvc5ostream out);
- inline ~IndentedScope();
+ inline IndentedScope(Cvc5ostream out) : d_out(out) { d_out << push; }
+ inline ~IndentedScope() { d_out << pop; }
}; /* class IndentedScope */
-#if defined(CVC5_DEBUG) && defined(CVC5_TRACING)
-inline IndentedScope::IndentedScope(Cvc5ostream out) : d_out(out)
-{
- d_out << push;
-}
-inline IndentedScope::~IndentedScope() { d_out << pop; }
-#else /* CVC5_DEBUG && CVC5_TRACING */
-inline IndentedScope::IndentedScope(Cvc5ostream out) {}
-inline IndentedScope::~IndentedScope() {}
-#endif /* CVC5_DEBUG && CVC5_TRACING */
-
} // namespace cvc5
#endif /* CVC5__OUTPUT_H */
diff --git a/src/base/versioninfo.cpp.in b/src/base/versioninfo.cpp.in
index 0e873d7b3..af4129f6d 100644
--- a/src/base/versioninfo.cpp.in
+++ b/src/base/versioninfo.cpp.in
@@ -19,4 +19,4 @@ const bool ::cvc5::Configuration::GIT_BUILD = @GIT_BUILD@;
const bool ::cvc5::Configuration::CVC5_IS_RELEASE = @CVC5_IS_RELEASE@;
const char* const ::cvc5::Configuration::CVC5_VERSION = "@CVC5_VERSION@";
const char* const ::cvc5::Configuration::CVC5_FULL_VERSION = "@CVC5_FULL_VERSION@";
-const char* const ::cvc5::Configuration::CVC5_GIT_INFO = "@CVC5_GIT_INFO@"; \ No newline at end of file
+const char* const ::cvc5::Configuration::CVC5_GIT_INFO = "@CVC5_GIT_INFO@";
diff --git a/src/expr/bound_var_manager.cpp b/src/expr/bound_var_manager.cpp
index 53c87fb97..450b2358f 100644
--- a/src/expr/bound_var_manager.cpp
+++ b/src/expr/bound_var_manager.cpp
@@ -53,7 +53,7 @@ Node BoundVarManager::getCacheValue(TNode cv1, TNode cv2, size_t i)
Node BoundVarManager::getCacheValue(size_t i)
{
- return NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(i));
+ return NodeManager::currentNM()->mkConstInt(Rational(i));
}
Node BoundVarManager::getCacheValue(TNode cv, size_t i)
diff --git a/src/expr/dtype.cpp b/src/expr/dtype.cpp
index 5b2503454..4902b1562 100644
--- a/src/expr/dtype.cpp
+++ b/src/expr/dtype.cpp
@@ -867,7 +867,7 @@ Node DType::getSharedSelector(TypeNode dtt, TypeNode t, size_t index) const
ss << "sel_" << index;
SkolemManager* sm = nm->getSkolemManager();
TypeNode stype = nm->mkSelectorType(dtt, t);
- Node nindex = nm->mkConst(CONST_RATIONAL, Rational(index));
+ Node nindex = nm->mkConstInt(Rational(index));
s = sm->mkSkolemFunction(SkolemFunId::SHARED_SELECTOR, stype, nindex);
d_sharedSel[dtt][t][index] = s;
Trace("dt-shared-sel") << "Made " << s << " of type " << dtt << " -> " << t
diff --git a/src/expr/dtype_cons.cpp b/src/expr/dtype_cons.cpp
index 6ba3970c9..a054dffb8 100644
--- a/src/expr/dtype_cons.cpp
+++ b/src/expr/dtype_cons.cpp
@@ -83,6 +83,16 @@ Node DTypeConstructor::getConstructor() const
return d_constructor;
}
+Node DTypeConstructor::getInstantiatedConstructor(TypeNode returnType) const
+{
+ Assert(isResolved());
+ NodeManager* nm = NodeManager::currentNM();
+ return nm->mkNode(
+ kind::APPLY_TYPE_ASCRIPTION,
+ nm->mkConst(AscriptionType(getInstantiatedConstructorType(returnType))),
+ d_constructor);
+}
+
Node DTypeConstructor::getTester() const
{
Assert(isResolved());
@@ -116,12 +126,12 @@ unsigned DTypeConstructor::getWeight() const
size_t DTypeConstructor::getNumArgs() const { return d_args.size(); }
-TypeNode DTypeConstructor::getSpecializedConstructorType(
+TypeNode DTypeConstructor::getInstantiatedConstructorType(
TypeNode returnType) const
{
Assert(isResolved());
Assert(returnType.isDatatype())
- << "DTypeConstructor::getSpecializedConstructorType: expected datatype, "
+ << "DTypeConstructor::getInstantiatedConstructorType: expected datatype, "
"got "
<< returnType;
TypeNode ctn = d_constructor.getType();
@@ -439,7 +449,7 @@ Node DTypeConstructor::computeGroundTerm(TypeNode t,
<< ", ascribe to " << t << std::endl;
groundTerms[0] = nm->mkNode(
APPLY_TYPE_ASCRIPTION,
- nm->mkConst(AscriptionType(getSpecializedConstructorType(t))),
+ nm->mkConst(AscriptionType(getInstantiatedConstructorType(t))),
groundTerms[0]);
groundTerm = nm->mkNode(APPLY_CONSTRUCTOR, groundTerms);
}
@@ -456,7 +466,7 @@ void DTypeConstructor::computeSharedSelectors(TypeNode domainType) const
TypeNode ctype;
if (domainType.isParametricDatatype())
{
- ctype = getSpecializedConstructorType(domainType);
+ ctype = getInstantiatedConstructorType(domainType);
}
else
{
diff --git a/src/expr/dtype_cons.h b/src/expr/dtype_cons.h
index a6268aad1..657f6b7b8 100644
--- a/src/expr/dtype_cons.h
+++ b/src/expr/dtype_cons.h
@@ -85,6 +85,12 @@ class DTypeConstructor
* DType must be resolved.
*/
Node getConstructor() const;
+ /**
+ * Get the specialized constructor term of this constructor, which is
+ * the constructor wrapped in a APPLY_TYPE_ASCRIPTION. This is required
+ * for constructing applications of constructors for parametric datatypes.
+ */
+ Node getInstantiatedConstructor(TypeNode returnType) const;
/**
* Get the tester operator of this constructor. The
@@ -139,7 +145,7 @@ class DTypeConstructor
* "cons" constructor type for lists of int---namely,
* "int -> list[int] -> list[int]".
*/
- TypeNode getSpecializedConstructorType(TypeNode returnType) const;
+ TypeNode getInstantiatedConstructorType(TypeNode returnType) const;
/**
* Return the cardinality of this constructor (the product of the
diff --git a/src/expr/nary_term_util.cpp b/src/expr/nary_term_util.cpp
index a872c64c7..03ce637e4 100644
--- a/src/expr/nary_term_util.cpp
+++ b/src/expr/nary_term_util.cpp
@@ -119,10 +119,10 @@ Node getNullTerminator(Kind k, TypeNode tn)
case OR: nullTerm = nm->mkConst(false); break;
case AND:
case SEP_STAR: nullTerm = nm->mkConst(true); break;
- case PLUS: nullTerm = nm->mkConst(CONST_RATIONAL, Rational(0)); break;
+ case PLUS: nullTerm = nm->mkConstRealOrInt(tn, Rational(0)); break;
case MULT:
case NONLINEAR_MULT:
- nullTerm = nm->mkConst(CONST_RATIONAL, Rational(1));
+ nullTerm = nm->mkConstRealOrInt(tn, Rational(1));
break;
case STRING_CONCAT:
// handles strings and sequences
diff --git a/src/expr/node_manager.h b/src/expr/node_manager.h
index 6435c488a..b2682661e 100644
--- a/src/expr/node_manager.h
+++ b/src/expr/node_manager.h
@@ -579,6 +579,12 @@ class NodeManager
*/
Node mkConstInt(const Rational& r);
+ /**
+ * Make constant real or int, which calls one of the above methods based
+ * on the type tn.
+ */
+ Node mkConstRealOrInt(const TypeNode& tn, const Rational& r);
+
/** Create a node with children. */
TypeNode mkTypeNode(Kind kind, TypeNode child1);
TypeNode mkTypeNode(Kind kind, TypeNode child1, TypeNode child2);
diff --git a/src/expr/node_manager_template.cpp b/src/expr/node_manager_template.cpp
index b00d79322..4f235a53a 100644
--- a/src/expr/node_manager_template.cpp
+++ b/src/expr/node_manager_template.cpp
@@ -1298,4 +1298,15 @@ Node NodeManager::mkConstInt(const Rational& r)
return mkConst(kind::CONST_RATIONAL, r);
}
+Node NodeManager::mkConstRealOrInt(const TypeNode& tn, const Rational& r)
+{
+ Assert(tn.isRealOrInt()) << "Expected real or int for mkConstRealOrInt, got "
+ << tn;
+ if (tn.isReal())
+ {
+ return mkConstReal(r);
+ }
+ return mkConstInt(r);
+}
+
} // namespace cvc5
diff --git a/src/expr/sequence.cpp b/src/expr/sequence.cpp
index 6b15f33e0..82c83e0ea 100644
--- a/src/expr/sequence.cpp
+++ b/src/expr/sequence.cpp
@@ -371,13 +371,13 @@ std::ostream& operator<<(std::ostream& os, const Sequence& s)
size_t SequenceHashFunction::operator()(const Sequence& s) const
{
- size_t ret = 0;
+ uint64_t ret = fnv1a::offsetBasis;
const std::vector<Node>& vec = s.getVec();
for (const Node& n : vec)
{
ret = fnv1a::fnv1a_64(ret, std::hash<Node>()(n));
}
- return ret;
+ return static_cast<size_t>(ret);
}
} // namespace cvc5
diff --git a/src/expr/skolem_manager.cpp b/src/expr/skolem_manager.cpp
index 476517820..f08ffc5f4 100644
--- a/src/expr/skolem_manager.cpp
+++ b/src/expr/skolem_manager.cpp
@@ -67,6 +67,12 @@ const char* toString(SkolemFunId id)
case SkolemFunId::SK_FIRST_MATCH: return "SK_FIRST_MATCH";
case SkolemFunId::SK_FIRST_MATCH_POST: return "SK_FIRST_MATCH_POST";
case SkolemFunId::RE_UNFOLD_POS_COMPONENT: return "RE_UNFOLD_POS_COMPONENT";
+ case SkolemFunId::SEQ_MODEL_BASE_ELEMENT: return "SEQ_MODEL_BASE_ELEMENT";
+ case SkolemFunId::BAGS_CARD_CARDINALITY: return "BAGS_CARD_CARDINALITY";
+ case SkolemFunId::BAGS_CARD_ELEMENTS: return "BAGS_CARD_ELEMENTS";
+ case SkolemFunId::BAGS_CARD_N: return "BAGS_CARD_N";
+ case SkolemFunId::BAGS_CARD_UNION_DISJOINT:
+ return "BAGS_CARD_UNION_DISJOINT";
case SkolemFunId::BAGS_CHOOSE: return "BAGS_CHOOSE";
case SkolemFunId::BAGS_FOLD_CARD: return "BAGS_FOLD_CARD";
case SkolemFunId::BAGS_FOLD_COMBINE: return "BAGS_FOLD_COMBINE";
diff --git a/src/expr/skolem_manager.h b/src/expr/skolem_manager.h
index 780413d17..cca28ccf0 100644
--- a/src/expr/skolem_manager.h
+++ b/src/expr/skolem_manager.h
@@ -112,6 +112,12 @@ enum class SkolemFunId
* i = 0, ..., n.
*/
RE_UNFOLD_POS_COMPONENT,
+ /** Sequence model construction, element for base */
+ SEQ_MODEL_BASE_ELEMENT,
+ BAGS_CARD_CARDINALITY,
+ BAGS_CARD_ELEMENTS,
+ BAGS_CARD_N,
+ BAGS_CARD_UNION_DISJOINT,
BAGS_FOLD_CARD,
BAGS_FOLD_COMBINE,
BAGS_FOLD_ELEMENTS,
diff --git a/src/expr/term_context.cpp b/src/expr/term_context.cpp
index 7f8aa9eac..02ec8981b 100644
--- a/src/expr/term_context.cpp
+++ b/src/expr/term_context.cpp
@@ -131,7 +131,7 @@ uint32_t PolarityTermContext::getValue(bool hasPol, bool pol)
void PolarityTermContext::getFlags(uint32_t val, bool& hasPol, bool& pol)
{
- hasPol = val == 0;
+ hasPol = val != 0;
pol = val == 2;
}
diff --git a/src/expr/term_context_node.cpp b/src/expr/term_context_node.cpp
index 3be9faad0..91e6dbfd3 100644
--- a/src/expr/term_context_node.cpp
+++ b/src/expr/term_context_node.cpp
@@ -54,7 +54,7 @@ Node TCtxNode::getNodeHash() const { return computeNodeHash(d_node, d_val); }
Node TCtxNode::computeNodeHash(Node n, uint32_t val)
{
NodeManager* nm = NodeManager::currentNM();
- return nm->mkNode(kind::SEXPR, n, nm->mkConst(CONST_RATIONAL, Rational(val)));
+ return nm->mkNode(kind::SEXPR, n, nm->mkConstInt(Rational(val)));
}
Node TCtxNode::decomposeNodeHash(Node h, uint32_t& val)
diff --git a/src/expr/term_context_node.h b/src/expr/term_context_node.h
index ac89b0d71..9e4fe90de 100644
--- a/src/expr/term_context_node.h
+++ b/src/expr/term_context_node.h
@@ -54,7 +54,7 @@ class TCtxNode
Node getNodeHash() const;
/**
* Get node hash, which is a unique node representation of the pair (n, val).
- * In particular, this returns (SEXPR n (CONST_RATIONAL val)).
+ * In particular, this returns (SEXPR n (CONST_INTEGER val)).
*/
static Node computeNodeHash(Node n, uint32_t val);
/**
diff --git a/src/options/README.md b/src/options/README.md
index 54d7d4878..c3e018215 100644
--- a/src/options/README.md
+++ b/src/options/README.md
@@ -64,7 +64,6 @@ Option types
Though not enforced explicitly, option types are commonly expected to come from
a rather restricted set of C++ types:
-some options are merely used to have a handler function called and use `void`;
Boolean options should use `bool`;
numeric options should use one of `int64_t`, `uint64_t` and `double`, possibly
using `minimum` and `maximum` to further restrict the options domain;
@@ -81,10 +80,9 @@ Handler functions
Custom handler functions are used to turn the option value from an `std::string`
into the type specified by `type`. Standard handler functions are provided for
basic types (`std::string`, `bool`, `int64_t`, `uint64_t`, and `double`) as
-well as enums specified by `mode`. A custom handler function needs to be member
-function of `options::OptionsHandler` with signature
-`{type} {handler}(const std::string& flag, const std::string& optionvalue)`, or
-alternatively `void {handler}(const std::string& flag)` if the `type` is `void`.
+well as enums specified by `mode`. A custom handler function needs to be a
+member function of `options::OptionsHandler` with signature
+`{type} {handler}(const std::string& flag, const std::string& optionvalue)`.
The parameter `flag` holds the actually used option name, which may be an alias
name, and should only be used in user messages.
@@ -92,16 +90,14 @@ name, and should only be used in user messages.
Predicate functions
-------------------
-Predicate functions are used to check whether an option value is valid after it
-has been parsed by a (standard or custom) handler function. Like a handler
-function, a predicate function needs to be a member function of
-`options::OptionsHandler` with signature
+Predicate functions are called after an option value has been parsed by a
+(standard or custom) handler function. They usually either check whether the
+parsed option value is valid, or to trigger some action (e.g. print some
+message or set another option). Like a handler function, a predicate function
+needs to be a member function of `options::OptionsHandler` with signature
`void {predicate}(const std::string& flag, {type} value)`.
-If the check fails, the predicate should raise an `OptionException`.
-
-Note that a predicate function may not only check the value, but may also
-trigger some other action. Examples include enabling trace tags or enforcing
-dependencies between several options.
+A predicate function is expected to raise an `OptionException` if the option
+value is not valid for some reason.
Mode options
@@ -144,15 +140,15 @@ Generated code
The entire options setup heavily relies on generating a lot of code from the
information retrieved from the `*_options.toml` files. After code generation,
files related to options live either in `src/options/` (if not changed) or in
-`build/src/options/` (if automatically generated). After all code has been
-generated, the entire options setup consists of the following components:
+`build/src/options/` (if automatically generated). Additionally, code that is
+only needed when using cvc5 on the command line lives in `src/main/` and
+`build/src/main`. After all code has been generated, the entire options setup
+consists of the following components:
-* `options.h`: core `Options` class
-* `options_api.h`: utility methods used by the API (`parse()`, `set()`, `get()`,
- ...)
-* `options_public.h`: utility methods used to access options from outside of
- libcvc5
-* `{module}_options.h`: specifics for one single options module
+* `options/options.h`: core `Options` class
+* `options/options_public.h`: utility methods used by the API (`getNames()`, `get()`, `set()` and `getInfo()`)
+* `options/{module}_options.h`: specifics for one single options module
+* `main/options.h`: utility methods used by the CLI (`parse()` and `printUsage()`)
`Options` class
@@ -172,20 +168,13 @@ Option modules
--------------
Every option module declares an "option holder" class, which is a simple struct
-that has two members for every option (that is not declared as `type = void`):
+that has two members for every option (that specifies a `name`):
the actual option value as `{option.type} {option.name}` and a Boolean flag
-`bool {option.name}__setByUser` that indicates whether the option value was
+`bool {option.name}WasSetByUser` that indicates whether the option value was
explicitly set by the user. If any of the options of a module is a mode option,
the option module also defines an enum class that corresponds to the mode,
including `operator<<()` and `stringTo{mode type}`.
-For convenience, the option modules also provide methods `void
-{module.id}::setDefault{option.name}(Options& opts, {option.type} value)`. Each
-such method sets the option value to the given value, if the option was not yet
-set by the user, i.e., the `__setByUser` flag is false. Additionally, every
-option module exports the `long` option name as `static constexpr const char*
-{module.id}::{option.name}__name`.
-
Full Example
============
@@ -218,6 +207,5 @@ with `--decision-mode=justification`, and similarly from an SMT-LIB input with
`(set-option :decision internal)` and `(set-option :decision-mode
justification)`. The command-line help for this option looks as follows:
- --output-lang=LANG | --output-language=LANG
- force output language (default is "auto"; see
- --output-lang help)
+ --decision=MODE | --decision-mode=MODE
+ choose decision mode, see --decision=help
diff --git a/src/options/arith_options.toml b/src/options/arith_options.toml
index e5f65684b..5e6796864 100644
--- a/src/options/arith_options.toml
+++ b/src/options/arith_options.toml
@@ -500,6 +500,14 @@ name = "Arithmetic Theory"
help = "whether to use the cylindrical algebraic coverings solver for non-linear arithmetic"
[[option]]
+ name = "nlCadVarElim"
+ category = "regular"
+ long = "nl-cad-var-elim"
+ type = "bool"
+ default = "false"
+ help = "whether to eliminate variables using equalities before going into the cylindrical algebraic coverings solver"
+
+[[option]]
name = "nlCadPrune"
category = "regular"
long = "nl-cad-prune"
diff --git a/src/options/base_options.toml b/src/options/base_options.toml
index 8255da027..042fd6b8a 100644
--- a/src/options/base_options.toml
+++ b/src/options/base_options.toml
@@ -63,16 +63,18 @@ name = "Base"
category = "common"
short = "v"
long = "verbose"
- type = "void"
- handler = "increaseVerbosity"
+ type = "bool"
+ alternate = false
+ predicates = ["increaseVerbosity"]
help = "increase verbosity (may be repeated)"
[[option]]
category = "common"
short = "q"
long = "quiet"
- type = "void"
- handler = "decreaseVerbosity"
+ type = "bool"
+ alternate = false
+ predicates = ["decreaseVerbosity"]
help = "decrease verbosity (may be repeated)"
[[option]]
@@ -136,24 +138,23 @@ name = "Base"
short = "t"
long = "trace=TAG"
type = "std::string"
- handler = "enableTraceTag"
- help = "trace something (e.g. -t pushpop), can repeat"
+ predicates = ["enableTraceTag"]
+ help = "trace something (e.g. -t pushpop), can repeat and may contain wildcards like (e.g. -t theory::*)"
[[option]]
category = "regular"
short = "d"
long = "debug=TAG"
type = "std::string"
- handler = "enableDebugTag"
+ predicates = ["enableDebugTag"]
help = "debug something (e.g. -d arith), can repeat"
[[option]]
- name = "outputTag"
short = "o"
long = "output=TAG"
type = "OutputTag"
default = "NONE"
- handler = "enableOutputTag"
+ predicates = ["enableOutputTag"]
category = "regular"
help = "Enable output tag."
help_mode = "Output tags."
@@ -241,7 +242,7 @@ name = "Base"
category = "expert"
long = "rweight=VAL=N"
type = "std::string"
- handler = "setResourceWeight"
+ predicates = ["setResourceWeight"]
help = "set a single resource weight"
[[option]]
diff --git a/src/options/managed_streams.cpp b/src/options/managed_streams.cpp
index 90090df25..935b75a35 100644
--- a/src/options/managed_streams.cpp
+++ b/src/options/managed_streams.cpp
@@ -72,12 +72,11 @@ std::string cvc5_errno_failreason()
namespace detail {
-std::ostream* openOStream(const std::string& filename)
+std::unique_ptr<std::ostream> openOStream(const std::string& filename)
{
errno = 0;
- std::ostream* res;
- res = new std::ofstream(filename);
- if (res == nullptr || !*res)
+ std::unique_ptr<std::ostream> res = std::make_unique<std::ofstream>(filename);
+ if (!res || !*res)
{
std::stringstream ss;
ss << "Cannot open file: `" << filename << "': " << cvc5_errno_failreason();
@@ -85,12 +84,11 @@ std::ostream* openOStream(const std::string& filename)
}
return res;
}
-std::istream* openIStream(const std::string& filename)
+std::unique_ptr<std::istream> openIStream(const std::string& filename)
{
errno = 0;
- std::istream* res;
- res = new std::ifstream(filename);
- if (res == nullptr || !*res)
+ std::unique_ptr<std::istream> res = std::make_unique<std::ifstream>(filename);
+ if (!res || !*res)
{
std::stringstream ss;
ss << "Cannot open file: `" << filename << "': " << cvc5_errno_failreason();
diff --git a/src/options/managed_streams.h b/src/options/managed_streams.h
index cf1820de6..830916b2f 100644
--- a/src/options/managed_streams.h
+++ b/src/options/managed_streams.h
@@ -31,12 +31,12 @@ namespace detail {
* Open a file as an output stream and return it as a pointer. The caller
* assumes the ownership of the returned pointer.
*/
-std::ostream* openOStream(const std::string& filename);
+std::unique_ptr<std::ostream> openOStream(const std::string& filename);
/*
* Open a file as an input stream and return it as a pointer. The caller
* assumes the ownership of the returned pointer.
*/
-std::istream* openIStream(const std::string& filename);
+std::unique_ptr<std::istream> openIStream(const std::string& filename);
} // namespace detail
/**
@@ -64,13 +64,13 @@ class ManagedStream
if constexpr (std::is_same<Stream, std::ostream>::value)
{
d_nonowned = nullptr;
- d_owned.reset(detail::openOStream(value));
+ d_owned = detail::openOStream(value);
d_description = value;
}
else if constexpr (std::is_same<Stream, std::istream>::value)
{
d_nonowned = nullptr;
- d_owned.reset(detail::openIStream(value));
+ d_owned = detail::openIStream(value);
d_description = value;
}
}
diff --git a/src/options/mkoptions.py b/src/options/mkoptions.py
index 3022c5d4b..8a7dbf605 100644
--- a/src/options/mkoptions.py
+++ b/src/options/mkoptions.py
@@ -287,16 +287,13 @@ def generate_get_impl(modules):
ret = '{{ std::stringstream s; s << options.{}.{}; return s.str(); }}'.format(
module.id, option.name)
res.append('if ({}) {}'.format(cond, ret))
- return '\n '.join(res)
+ return '\n '.join(res)
def _set_handlers(option):
"""Render handler call for options::set()."""
if option.handler:
- if option.type == 'void':
- return 'opts.handler().{}(name)'.format(option.handler)
- else:
- return 'opts.handler().{}(name, optionarg)'.format(option.handler)
+ return 'opts.handler().{}(name, optionarg)'.format(option.handler)
elif option.mode:
return 'stringTo{}(optionarg)'.format(option.type)
return 'handlers::handleOption<{}>(name, optionarg)'.format(option.type)
@@ -304,9 +301,6 @@ def _set_handlers(option):
def _set_predicates(option):
"""Render predicate calls for options::set()."""
- if option.type == 'void':
- return []
- assert option.type != 'void'
res = []
if option.minimum:
res.append(
@@ -317,20 +311,11 @@ def _set_predicates(option):
'opts.handler().checkMaximum(name, value, static_cast<{}>({}));'
.format(option.type, option.maximum))
res += [
- 'opts.handler().{}(name, value);'.format(x)
- for x in option.predicates
+ 'opts.handler().{}(name, value);'.format(x) for x in option.predicates
]
return res
-TPL_SET = ''' opts.{module}.{name} = {handler};
- opts.{module}.{name}WasSetByUser = true;'''
-TPL_SET_PRED = ''' auto value = {handler};
- {predicates}
- opts.{module}.{name} = value;
- opts.{module}.{name}WasSetByUser = true;'''
-
-
def generate_set_impl(modules):
"""Generates the implementation for options::set()."""
res = []
@@ -338,31 +323,19 @@ def generate_set_impl(modules):
if not option.long:
continue
cond = ' || '.join(['name == "{}"'.format(x) for x in option.names])
- predicates = _set_predicates(option)
if res:
- res.append(' }} else if ({}) {{'.format(cond))
+ res.append('}} else if ({}) {{'.format(cond))
else:
res.append('if ({}) {{'.format(cond))
- if option.name and not (option.handler and option.mode):
- if predicates:
- res.append(
- TPL_SET_PRED.format(module=module.id,
- name=option.name,
- handler=_set_handlers(option),
- predicates='\n '.join(predicates)))
- else:
- res.append(
- TPL_SET.format(module=module.id,
- name=option.name,
- handler=_set_handlers(option)))
- elif option.handler:
- h = ' opts.handler().{handler}(name'
- if option.type not in ['bool', 'void']:
- h += ', optionarg'
- h += ');'
- res.append(
- h.format(handler=option.handler, smtname=option.long_name))
- return '\n'.join(res)
+ res.append(' auto value = {};'.format(_set_handlers(option)))
+ for pred in _set_predicates(option):
+ res.append(' {}'.format(pred))
+ if option.name:
+ res.append(' opts.{module}.{name} = value;'.format(
+ module=module.id, name=option.name))
+ res.append(' opts.{module}.{name}WasSetByUser = true;'.format(
+ module=module.id, name=option.name))
+ return '\n '.join(res)
def generate_getinfo_impl(modules):
@@ -431,7 +404,7 @@ def generate_module_mode_decl(module):
"""Generates the declarations of mode enums and utility functions."""
res = []
for option in module.options:
- if option.name is None or not option.mode:
+ if not option.mode:
continue
values = list(option.mode.keys())
res.append(
@@ -523,12 +496,12 @@ def generate_module_mode_impl(module):
"""Generates the declarations of mode enums and utility functions."""
res = []
for option in module.options:
- if option.name is None or not option.mode:
+ if not option.mode:
continue
cases = [
'case {type}::{enum}: return os << "{name}";'.format(
type=option.type, enum=enum, name=info[0]['name'])
- for enum,info in option.mode.items()
+ for enum, info in option.mode.items()
]
res.append(
TPL_MODE_STREAM_OPERATOR.format(type=option.type,
@@ -566,7 +539,7 @@ def generate_module_mode_impl(module):
def _add_cmdoption(option, name, opts, next_id):
fmt = {
'name': name,
- 'arg': 'no' if option.type in ['bool', 'void'] else 'required',
+ 'arg': 'no' if option.type == 'bool' else 'required',
'next_id': next_id
}
opts.append(
@@ -590,7 +563,7 @@ def generate_parsing(modules):
needs_impl = True
code.append("case '{0}': // -{0}".format(option.short))
short += option.short
- if option.type not in ['bool', 'void']:
+ if option.type != 'bool':
short += ':'
if option.long: # long option
needs_impl = True
@@ -609,9 +582,6 @@ def generate_parsing(modules):
if option.type == 'bool':
code.append(' solver.setOption("{}", "true"); break;'.format(
option.long_name))
- elif option.type == 'void':
- code.append(' solver.setOption("{}", ""); break;'.format(
- option.long_name))
else:
code.append(
' solver.setOption("{}", optionarg); break;'.format(
@@ -824,14 +794,14 @@ def generate_sphinx_help(modules):
def generate_sphinx_output_tags(modules, src_dir, build_dir):
"""Render help for the --output option for sphinx."""
base = next(filter(lambda m: m.id == 'base', modules))
- opt = next(filter(lambda o: o.name == 'outputTag', base.options))
+ opt = next(filter(lambda o: o.long == 'output=TAG', base.options))
# The programoutput extension has weird semantics about the cwd:
# https://sphinxcontrib-programoutput.readthedocs.io/en/latest/#usage
cwd = '/' + os.path.relpath(build_dir, src_dir)
res = []
- for name,info in opt.mode.items():
+ for name, info in opt.mode.items():
info = info[0]
if 'description' not in info:
continue
@@ -1002,9 +972,9 @@ class Checker:
self.__check_option_long(o, o.long_name)
if o.alternate:
self.__check_option_long(o, 'no-' + o.long_name)
- if o.type in ['bool', 'void'] and '=' in o.long:
- self.perr('must not have an argument description', option=o)
- if o.type not in ['bool', 'void'] and not '=' in o.long:
+ if o.type == 'bool' and '=' in o.long:
+ self.perr('bool options must not have an argument description', option=o)
+ if o.type != 'bool' and not '=' in o.long:
self.perr("needs argument description ('{}=...')",
o.long,
option=o)
diff --git a/src/options/module_template.h b/src/options/module_template.h
index c613c1cba..00bf7c0ca 100644
--- a/src/options/module_template.h
+++ b/src/options/module_template.h
@@ -42,7 +42,7 @@ ${modes_decl}$
struct Holder${id_cap}$
{
// clang-format off
-${holder_decl}$
+ ${holder_decl}$
// clang-format on
};
diff --git a/src/options/options_handler.cpp b/src/options/options_handler.cpp
index 7af82df42..132525e6d 100644
--- a/src/options/options_handler.cpp
+++ b/src/options/options_handler.cpp
@@ -18,6 +18,7 @@
#include <cerrno>
#include <iostream>
#include <ostream>
+#include <regex>
#include <string>
#include "base/check.h"
@@ -66,6 +67,40 @@ std::string suggestTags(const std::vector<std::string>& validTags,
return didYouMean.getMatchAsString(inputTag);
}
+/**
+ * Select all tags from validTags that match the given (globbing) pattern.
+ * The pattern may contain `*` as wildcards. These are internally converted to
+ * `.*` and matched using std::regex. If no wildcards are present, regular
+ * string comparisons are used.
+ */
+std::vector<std::string> selectTags(const std::vector<std::string>& validTags, std::string pattern)
+{
+ bool isRegex = false;
+ size_t pos = 0;
+ while ((pos = pattern.find('*', pos)) != std::string::npos)
+ {
+ pattern.replace(pos, 1, ".*");
+ pos += 2;
+ isRegex = true;
+ }
+ std::vector<std::string> results;
+ if (isRegex)
+ {
+ std::regex re(pattern);
+ std::copy_if(validTags.begin(), validTags.end(), std::back_inserter(results),
+ [&re](const auto& tag){ return std::regex_match(tag, re); }
+ );
+ }
+ else
+ {
+ if (std::find(validTags.begin(), validTags.end(), pattern) != validTags.end())
+ {
+ results.emplace_back(pattern);
+ }
+ }
+ return results;
+}
+
} // namespace
OptionsHandler::OptionsHandler(Options* options) : d_options(options) { }
@@ -142,13 +177,13 @@ void OptionsHandler::setVerbosity(const std::string& flag, int value)
}
}
-void OptionsHandler::decreaseVerbosity(const std::string& flag)
+void OptionsHandler::decreaseVerbosity(const std::string& flag, bool value)
{
d_options->base.verbosity -= 1;
setVerbosity(flag, d_options->base.verbosity);
}
-void OptionsHandler::increaseVerbosity(const std::string& flag)
+void OptionsHandler::increaseVerbosity(const std::string& flag, bool value)
{
d_options->base.verbosity += 1;
setVerbosity(flag, d_options->base.verbosity);
@@ -199,7 +234,8 @@ void OptionsHandler::enableTraceTag(const std::string& flag,
{
throw OptionException("trace tags not available in non-tracing builds");
}
- else if (!Configuration::isTraceTag(optarg))
+ auto tags = selectTags(Configuration::getTraceTags(), optarg);
+ if (tags.empty())
{
if (optarg == "help")
{
@@ -209,10 +245,13 @@ void OptionsHandler::enableTraceTag(const std::string& flag,
}
throw OptionException(
- std::string("trace tag ") + optarg + std::string(" not available.")
+ std::string("no trace tag matching ") + optarg + std::string(" was found.")
+ suggestTags(Configuration::getTraceTags(), optarg, {}));
}
- Trace.on(optarg);
+ for (const auto& tag: tags)
+ {
+ Trace.on(tag);
+ }
}
void OptionsHandler::enableDebugTag(const std::string& flag,
@@ -247,9 +286,9 @@ void OptionsHandler::enableDebugTag(const std::string& flag,
}
void OptionsHandler::enableOutputTag(const std::string& flag,
- const std::string& optarg)
+ OutputTag optarg)
{
- size_t tagid = static_cast<size_t>(stringToOutputTag(optarg));
+ size_t tagid = static_cast<size_t>(optarg);
Assert(d_options->base.outputTagHolder.size() > tagid)
<< "Output tag is larger than the bitset that holds it.";
d_options->base.outputTagHolder.set(tagid);
diff --git a/src/options/options_handler.h b/src/options/options_handler.h
index 6f5016c6c..a70a46a4a 100644
--- a/src/options/options_handler.h
+++ b/src/options/options_handler.h
@@ -22,6 +22,7 @@
#include <sstream>
#include <string>
+#include "options/base_options.h"
#include "options/bv_options.h"
#include "options/decision_options.h"
#include "options/language.h"
@@ -83,9 +84,9 @@ class OptionsHandler
/** Apply verbosity to the different output channels */
void setVerbosity(const std::string& flag, int value);
/** Decrease verbosity and call setVerbosity */
- void decreaseVerbosity(const std::string& flag);
+ void decreaseVerbosity(const std::string& flag, bool value);
/** Increase verbosity and call setVerbosity */
- void increaseVerbosity(const std::string& flag);
+ void increaseVerbosity(const std::string& flag, bool value);
/** If statistics are disabled, disable statistics sub-options */
void setStats(const std::string& flag, bool value);
/** If statistics sub-option is disabled, enable statistics */
@@ -95,7 +96,7 @@ class OptionsHandler
/** Enable a particular debug tag */
void enableDebugTag(const std::string& flag, const std::string& optarg);
/** Enable a particular output tag */
- void enableOutputTag(const std::string& flag, const std::string& optarg);
+ void enableOutputTag(const std::string& flag, OutputTag optarg);
/** Apply print success flag to the different output channels */
void setPrintSuccess(const std::string& flag, bool value);
/** Pass the resource weight specification to the resource manager */
diff --git a/src/options/options_public_template.cpp b/src/options/options_public_template.cpp
index a6ab6efde..952b4c7f8 100644
--- a/src/options/options_public_template.cpp
+++ b/src/options/options_public_template.cpp
@@ -206,7 +206,7 @@ namespace cvc5::options
Trace("options") << "set option " << name << " = " << optionarg
<< std::endl;
// clang-format off
- ${set_impl}$
+ ${set_impl}$
// clang-format on
}
else
diff --git a/src/options/proof_options.toml b/src/options/proof_options.toml
index 3eb32060e..8eb2fd783 100644
--- a/src/options/proof_options.toml
+++ b/src/options/proof_options.toml
@@ -92,6 +92,22 @@ name = "Proof"
help = "Allow DSL rewrites and evaluation steps, expand macros, rewrite, substitution, and theory rewrite steps."
[[option]]
+ name = "proofAnnotate"
+ category = "regular"
+ long = "proof-annotate"
+ type = "bool"
+ default = "false"
+ help = "add optional annotations to proofs, which enables statistics for inference ids for lemmas and conflicts appearing in final proof"
+
+[[option]]
+ name = "proofPruneInput"
+ category = "regular"
+ long = "proof-prune-input"
+ type = "bool"
+ default = "false"
+ help = "Prune unused input assumptions from final scope"
+
+[[option]]
name = "proofAletheResPivots"
category = "regular"
long = "proof-alethe-res-pivots"
diff --git a/src/options/smt_options.toml b/src/options/smt_options.toml
index 2e2742e73..026c8f494 100644
--- a/src/options/smt_options.toml
+++ b/src/options/smt_options.toml
@@ -395,6 +395,9 @@ name = "SMT Layer"
[[option.mode.BV]]
name = "bv"
help = "Translate bvand back to bit-vectors"
+[[option.mode.BITWISE]]
+ name = "bitwise"
+ help = "Introduce a UF operator for bvand, and eagerly add bitwise lemmas"
[[option]]
name = "BVAndIntegerGranularity"
diff --git a/src/options/strings_options.toml b/src/options/strings_options.toml
index 46f53147b..74112b286 100644
--- a/src/options/strings_options.toml
+++ b/src/options/strings_options.toml
@@ -223,3 +223,21 @@ name = "Strings Theory"
type = "bool"
default = "true"
help = "use regular expression inclusion"
+
+[[option]]
+ name = "seqArray"
+ category = "expert"
+ long = "seq-array=MODE"
+ type = "SeqArrayMode"
+ default = "NONE"
+ help = "use array-inspired solver for sequence updates in eager or lazy mode"
+ help_mode = "use array-inspired solver for sequence updates in eager or lazy mode"
+[[option.mode.LAZY]]
+ name = "lazy"
+ help = "use array-inspired solver for sequence updates in lazy mode"
+[[option.mode.EAGER]]
+ name = "eager"
+ help = "use array-inspired solver for sequence updates in eager mode"
+[[option.mode.NONE]]
+ name = "none"
+ help = "do not use array-inspired solver for sequence updates"
diff --git a/src/parser/parser.cpp b/src/parser/parser.cpp
index c94e39748..1481d66fe 100644
--- a/src/parser/parser.cpp
+++ b/src/parser/parser.cpp
@@ -583,7 +583,7 @@ api::Term Parser::applyTypeAscription(api::Term t, api::Sort s)
// lookup by name
api::DatatypeConstructor dc = d.getConstructor(t.toString());
// ask the constructor for the specialized constructor term
- t = dc.getSpecializedConstructorTerm(s);
+ t = dc.getInstantiatedConstructorTerm(s);
}
// the type of t does not match the sort s by design (constructor type
// vs datatype type), thus we use an alternative check here.
diff --git a/src/parser/smt2/Smt2.g b/src/parser/smt2/Smt2.g
index 5924ecde6..41cd4869a 100644
--- a/src/parser/smt2/Smt2.g
+++ b/src/parser/smt2/Smt2.g
@@ -371,7 +371,8 @@ command [std::unique_ptr<cvc5::Command>* cmd]
}
| /* check-sat */
CHECK_SAT_TOK { PARSER_STATE->checkThatLogicIsSet(); }
- { if (PARSER_STATE->sygus()) {
+ {
+ if (PARSER_STATE->sygus()) {
PARSER_STATE->parseError("Sygus does not support check-sat command.");
}
cmd->reset(new CheckSatCommand());
@@ -405,10 +406,6 @@ command [std::unique_ptr<cvc5::Command>* cmd]
{ cmd->reset(new GetDifficultyCommand); }
| /* push */
PUSH_TOK { PARSER_STATE->checkThatLogicIsSet(); }
- { if( PARSER_STATE->sygus() ){
- PARSER_STATE->parseError("Sygus does not support push command.");
- }
- }
( k=INTEGER_LITERAL
{ unsigned num = AntlrInput::tokenToUnsigned(k);
if(num == 0) {
@@ -438,10 +435,6 @@ command [std::unique_ptr<cvc5::Command>* cmd]
}
} )
| POP_TOK { PARSER_STATE->checkThatLogicIsSet(); }
- { if( PARSER_STATE->sygus() ){
- PARSER_STATE->parseError("Sygus does not support pop command.");
- }
- }
( k=INTEGER_LITERAL
{ unsigned num = AntlrInput::tokenToUnsigned(k);
// we don't compare num to PARSER_STATE->scopeLevel() here, since
@@ -1371,7 +1364,7 @@ termNonVariable[cvc5::api::Term& expr, cvc5::api::Term& expr2]
{
// lookup constructor by name
api::DatatypeConstructor dc = dt.getConstructor(f.toString());
- api::Term scons = dc.getSpecializedConstructorTerm(expr.getSort());
+ api::Term scons = dc.getInstantiatedConstructorTerm(expr.getSort());
// take the type of the specialized constructor instead
type = scons.getSort();
}
@@ -1801,8 +1794,10 @@ attribute[cvc5::api::Term& expr, cvc5::api::Term& retExpr]
| ATTRIBUTE_NAMED_TOK symbol[s,CHECK_UNDECLARED,SYM_VARIABLE]
{
// notify that expression was given a name
- PARSER_STATE->preemptCommand(
- new DefineFunctionCommand(s, expr.getSort(), expr));
+ DefineFunctionCommand* defFunCmd =
+ new DefineFunctionCommand(s, expr.getSort(), expr);
+ defFunCmd->setMuted(true);
+ PARSER_STATE->preemptCommand(defFunCmd);
PARSER_STATE->notifyNamedExpression(expr, s);
}
;
diff --git a/src/preprocessing/passes/apply_substs.cpp b/src/preprocessing/passes/apply_substs.cpp
index 99bded47a..82122fa7f 100644
--- a/src/preprocessing/passes/apply_substs.cpp
+++ b/src/preprocessing/passes/apply_substs.cpp
@@ -21,7 +21,7 @@
#include "context/cdo.h"
#include "preprocessing/assertion_pipeline.h"
#include "preprocessing/preprocessing_pass_context.h"
-#include "theory/rewriter.h"
+#include "smt/env.h"
#include "theory/substitutions.h"
namespace cvc5 {
@@ -55,7 +55,8 @@ PreprocessingPassResult ApplySubsts::applyInternal(
<< std::endl;
d_preprocContext->spendResource(Resource::PreprocessStep);
assertionsToPreprocess->replaceTrusted(
- i, tlsm.applyTrusted((*assertionsToPreprocess)[i]));
+ i,
+ tlsm.applyTrusted((*assertionsToPreprocess)[i], d_env.getRewriter()));
Trace("apply-substs") << " got " << (*assertionsToPreprocess)[i]
<< std::endl;
}
diff --git a/src/preprocessing/passes/bv_to_int.cpp b/src/preprocessing/passes/bv_to_int.cpp
index 33f3dd445..ac1edeb96 100644
--- a/src/preprocessing/passes/bv_to_int.cpp
+++ b/src/preprocessing/passes/bv_to_int.cpp
@@ -19,1054 +19,90 @@
#include "preprocessing/passes/bv_to_int.h"
#include <cmath>
-#include <sstream>
#include <string>
#include <unordered_map>
#include <vector>
#include "expr/node.h"
#include "expr/node_traversal.h"
-#include "expr/skolem_manager.h"
#include "options/smt_options.h"
#include "options/uf_options.h"
-#include "preprocessing/assertion_pipeline.h"
-#include "preprocessing/preprocessing_pass_context.h"
#include "theory/bv/theory_bv_rewrite_rules_operator_elimination.h"
+#include "preprocessing/assertion_pipeline.h"
#include "theory/bv/theory_bv_rewrite_rules_simplification.h"
#include "theory/rewriter.h"
-#include "util/bitvector.h"
-#include "util/iand.h"
-#include "util/rational.h"
namespace cvc5 {
namespace preprocessing {
namespace passes {
using namespace std;
-using namespace cvc5::kind;
using namespace cvc5::theory;
using namespace cvc5::theory::bv;
-namespace {
-
-Rational intpow2(uint64_t b)
-{
- return Rational(Integer(2).pow(b), Integer(1));
-}
-
-} //end empty namespace
-
-Node BVToInt::mkRangeConstraint(Node newVar, uint64_t k)
-{
- Node lower = d_nm->mkNode(kind::LEQ, d_zero, newVar);
- Node upper = d_nm->mkNode(kind::LT, newVar, pow2(k));
- Node result = d_nm->mkNode(kind::AND, lower, upper);
- return rewrite(result);
-}
-
-Node BVToInt::maxInt(uint64_t k)
-{
- Assert(k > 0);
- Rational max_value = intpow2(k) - 1;
- return d_nm->mkConst(CONST_RATIONAL, max_value);
-}
-
-Node BVToInt::pow2(uint64_t k)
-{
- Assert(k >= 0);
- return d_nm->mkConst(CONST_RATIONAL, Rational(intpow2(k)));
-}
-
-Node BVToInt::modpow2(Node n, uint64_t exponent)
-{
- Node p2 = d_nm->mkConst(CONST_RATIONAL, Rational(intpow2(exponent)));
- return d_nm->mkNode(kind::INTS_MODULUS_TOTAL, n, p2);
-}
-
-/**
- * Binarizing n via post-order traversal.
- */
-Node BVToInt::makeBinary(Node n)
-{
- for (TNode current : NodeDfsIterable(n,
- VisitOrder::POSTORDER,
- // skip visited nodes
- [this](TNode tn) {
- return d_binarizeCache.find(tn)
- != d_binarizeCache.end();
- }))
- {
- uint64_t numChildren = current.getNumChildren();
- /*
- * We already visited the sub-dag rooted at the current node,
- * and binarized all its children.
- * Now we binarize the current node itself.
- */
- kind::Kind_t k = current.getKind();
- if ((numChildren > 2)
- && (k == kind::BITVECTOR_ADD || k == kind::BITVECTOR_MULT
- || k == kind::BITVECTOR_AND || k == kind::BITVECTOR_OR
- || k == kind::BITVECTOR_XOR || k == kind::BITVECTOR_CONCAT))
- {
- // We only binarize bvadd, bvmul, bvand, bvor, bvxor, bvconcat
- Assert(d_binarizeCache.find(current[0]) != d_binarizeCache.end());
- Node result = d_binarizeCache[current[0]];
- for (uint64_t i = 1; i < numChildren; i++)
- {
- Assert(d_binarizeCache.find(current[i]) != d_binarizeCache.end());
- Node child = d_binarizeCache[current[i]];
- result = d_nm->mkNode(current.getKind(), result, child);
- }
- d_binarizeCache[current] = result;
- }
- else if (numChildren > 0)
- {
- // current has children, but we do not binarize it
- NodeBuilder builder(k);
- if (current.getMetaKind() == kind::metakind::PARAMETERIZED)
- {
- builder << current.getOperator();
- }
- for (Node child : current)
- {
- builder << d_binarizeCache[child].get();
- }
- d_binarizeCache[current] = builder.constructNode();
- }
- else
- {
- // current has no children
- d_binarizeCache[current] = current;
- }
- }
- return d_binarizeCache[n];
-}
-
-/**
- * We traverse n and perform rewrites both on the way down and on the way up.
- * On the way down we rewrite the node but not it's children.
- * On the way up, we update the node's children to the rewritten ones.
- * For each sub-node, we perform rewrites to eliminate operators.
- * Then, the original children are added to toVisit stack so that we rewrite
- * them as well.
- */
-Node BVToInt::eliminationPass(Node n)
-{
- std::vector<Node> toVisit;
- toVisit.push_back(n);
- Node current;
- while (!toVisit.empty())
- {
- current = toVisit.back();
- // assert that the node is binarized
- // The following variable is only used in assertions
- CVC5_UNUSED kind::Kind_t k = current.getKind();
- uint64_t numChildren = current.getNumChildren();
- Assert((numChildren == 2)
- || !(k == kind::BITVECTOR_ADD || k == kind::BITVECTOR_MULT
- || k == kind::BITVECTOR_AND || k == kind::BITVECTOR_OR
- || k == kind::BITVECTOR_XOR || k == kind::BITVECTOR_CONCAT));
- toVisit.pop_back();
- bool inEliminationCache =
- (d_eliminationCache.find(current) != d_eliminationCache.end());
- bool inRebuildCache =
- (d_rebuildCache.find(current) != d_rebuildCache.end());
- if (!inEliminationCache)
- {
- // current is not the elimination of any previously-visited node
- // current hasn't been eliminated yet.
- // eliminate operators from it using rewrite rules
- Node currentEliminated =
- FixpointRewriteStrategy<RewriteRule<UdivZero>,
- RewriteRule<SdivEliminateFewerBitwiseOps>,
- RewriteRule<SremEliminateFewerBitwiseOps>,
- RewriteRule<SmodEliminateFewerBitwiseOps>,
- RewriteRule<XnorEliminate>,
- RewriteRule<NandEliminate>,
- RewriteRule<NorEliminate>,
- RewriteRule<NegEliminate>,
- RewriteRule<XorEliminate>,
- RewriteRule<OrEliminate>,
- RewriteRule<SubEliminate>,
- RewriteRule<RepeatEliminate>,
- RewriteRule<RotateRightEliminate>,
- RewriteRule<RotateLeftEliminate>,
- RewriteRule<CompEliminate>,
- RewriteRule<SleEliminate>,
- RewriteRule<SltEliminate>,
- RewriteRule<SgtEliminate>,
- RewriteRule<SgeEliminate>>::apply(current);
-
- // save in the cache
- d_eliminationCache[current] = currentEliminated;
- // also assign the eliminated now to itself to avoid revisiting.
- d_eliminationCache[currentEliminated] = currentEliminated;
- // put the eliminated node in the rebuild cache, but mark that it hasn't
- // yet been rebuilt by assigning null.
- d_rebuildCache[currentEliminated] = Node();
- // Push the eliminated node to the stack
- toVisit.push_back(currentEliminated);
- // Add the children to the stack for future processing.
- toVisit.insert(
- toVisit.end(), currentEliminated.begin(), currentEliminated.end());
- }
- if (inRebuildCache)
- {
- // current was already added to the rebuild cache.
- if (d_rebuildCache[current].get().isNull())
- {
- // current wasn't rebuilt yet.
- numChildren = current.getNumChildren();
- if (numChildren == 0)
- {
- // We only eliminate operators that are not nullary.
- d_rebuildCache[current] = current;
- }
- else
- {
- // The main operator is replaced, and the children
- // are replaced with their eliminated counterparts.
- NodeBuilder builder(current.getKind());
- if (current.getMetaKind() == kind::metakind::PARAMETERIZED)
- {
- builder << current.getOperator();
- }
- for (Node child : current)
- {
- Assert(d_eliminationCache.find(child) != d_eliminationCache.end());
- Node eliminatedChild = d_eliminationCache[child];
- Assert(d_rebuildCache.find(eliminatedChild) != d_eliminationCache.end());
- Assert(!d_rebuildCache[eliminatedChild].get().isNull());
- builder << d_rebuildCache[eliminatedChild].get();
- }
- d_rebuildCache[current] = builder.constructNode();
- }
- }
- }
- }
- Assert(d_eliminationCache.find(n) != d_eliminationCache.end());
- Node eliminated = d_eliminationCache[n];
- Assert(d_rebuildCache.find(eliminated) != d_rebuildCache.end());
- Assert(!d_rebuildCache[eliminated].get().isNull());
- return d_rebuildCache[eliminated];
-}
-
-/**
- * Translate n to Integers via post-order traversal.
- */
-Node BVToInt::bvToInt(Node n)
-{
- // make sure the node is re-written before processing it.
- n = rewrite(n);
- n = makeBinary(n);
- n = eliminationPass(n);
- // binarize again, in case the elimination pass introduced
- // non-binary terms (as can happen by RepeatEliminate, for example).
- n = makeBinary(n);
- vector<Node> toVisit;
- toVisit.push_back(n);
-
- while (!toVisit.empty())
- {
- Node current = toVisit.back();
- uint64_t currentNumChildren = current.getNumChildren();
- if (d_bvToIntCache.find(current) == d_bvToIntCache.end())
- {
- // This is the first time we visit this node and it is not in the cache.
- // We mark this node as visited but not translated by assiging
- // a null node to it.
- d_bvToIntCache[current] = Node();
- // all the node's children are added to the stack to be visited
- // before visiting this node again.
- toVisit.insert(toVisit.end(), current.begin(), current.end());
- // If this is a UF applicatinon, we also add the function to
- // toVisit.
- if (current.getKind() == kind::APPLY_UF)
- {
- toVisit.push_back(current.getOperator());
- }
- }
- else
- {
- // We already visited and translated this node
- if (!d_bvToIntCache[current].get().isNull())
- {
- // We are done computing the translation for current
- toVisit.pop_back();
- }
- else
- {
- // We are now visiting current on the way back up.
- // This is when we do the actual translation.
- Node translation;
- if (currentNumChildren == 0)
- {
- translation = translateNoChildren(current);
- }
- else
- {
- /**
- * The current node has children.
- * Since we are on the way back up,
- * these children were already translated.
- * We save their translation for easy access.
- * If the node's kind is APPLY_UF,
- * we also need to include the translated uninterpreted function in
- * this list.
- */
- vector<Node> translated_children;
- if (current.getKind() == kind::APPLY_UF)
- {
- translated_children.push_back(
- d_bvToIntCache[current.getOperator()]);
- }
- for (uint64_t i = 0; i < currentNumChildren; i++)
- {
- translated_children.push_back(d_bvToIntCache[current[i]]);
- }
- translation = translateWithChildren(current, translated_children);
- }
- // Map the current node to its translation in the cache.
- d_bvToIntCache[current] = translation;
- // Also map the translation to itself.
- d_bvToIntCache[translation] = translation;
- toVisit.pop_back();
- }
- }
- }
- return d_bvToIntCache[n].get();
-}
-
-Node BVToInt::translateWithChildren(Node original,
- const vector<Node>& translated_children)
-{
- // The translation of the original node is determined by the kind of
- // the node.
- kind::Kind_t oldKind = original.getKind();
- // ultbv and sltbv were supposed to be eliminated before this point.
- Assert(oldKind != kind::BITVECTOR_ULTBV);
- Assert(oldKind != kind::BITVECTOR_SLTBV);
- // The following variable will only be used in assertions.
- CVC5_UNUSED uint64_t originalNumChildren = original.getNumChildren();
- Node returnNode;
- switch (oldKind)
- {
- case kind::BITVECTOR_ADD:
- {
- Assert(originalNumChildren == 2);
- uint64_t bvsize = original[0].getType().getBitVectorSize();
- Node plus = d_nm->mkNode(kind::PLUS, translated_children);
- Node p2 = pow2(bvsize);
- returnNode = d_nm->mkNode(kind::INTS_MODULUS_TOTAL, plus, p2);
- break;
- }
- case kind::BITVECTOR_MULT:
- {
- Assert(originalNumChildren == 2);
- uint64_t bvsize = original[0].getType().getBitVectorSize();
- Node mult = d_nm->mkNode(kind::MULT, translated_children);
- Node p2 = pow2(bvsize);
- returnNode = d_nm->mkNode(kind::INTS_MODULUS_TOTAL, mult, p2);
- break;
- }
- case kind::BITVECTOR_UDIV:
- {
- uint64_t bvsize = original[0].getType().getBitVectorSize();
- // we use an ITE for the case where the second operand is 0.
- Node pow2BvSize = pow2(bvsize);
- Node divNode =
- d_nm->mkNode(kind::INTS_DIVISION_TOTAL, translated_children);
- returnNode = d_nm->mkNode(
- kind::ITE,
- d_nm->mkNode(kind::EQUAL, translated_children[1], d_zero),
- d_nm->mkNode(kind::MINUS, pow2BvSize, d_one),
- divNode);
- break;
- }
- case kind::BITVECTOR_UREM:
- {
- // we use an ITE for the case where the second operand is 0.
- Node modNode =
- d_nm->mkNode(kind::INTS_MODULUS_TOTAL, translated_children);
- returnNode = d_nm->mkNode(
- kind::ITE,
- d_nm->mkNode(kind::EQUAL, translated_children[1], d_zero),
- translated_children[0],
- modNode);
- break;
- }
- case kind::BITVECTOR_NOT:
- {
- uint64_t bvsize = original[0].getType().getBitVectorSize();
- // we use a specified function to generate the node.
- returnNode = createBVNotNode(translated_children[0], bvsize);
- break;
- }
- case kind::BITVECTOR_TO_NAT:
- {
- // In this case, we already translated the child to integer.
- // So the result is the translated child.
- returnNode = translated_children[0];
- break;
- }
- case kind::INT_TO_BITVECTOR:
- {
- // ((_ int2bv n) t) ---> (mod t 2^n)
- size_t sz = original.getOperator().getConst<IntToBitVector>().d_size;
- returnNode = d_nm->mkNode(
- kind::INTS_MODULUS_TOTAL, translated_children[0], pow2(sz));
- }
- break;
- case kind::BITVECTOR_AND:
- {
- // We support three configurations:
- // 1. translating to IAND
- // 2. translating back to BV (using BITVECTOR_TO_NAT and INT_TO_BV
- // operators)
- // 3. translating into a sum
- uint64_t bvsize = original[0].getType().getBitVectorSize();
- if (options().smt.solveBVAsInt == options::SolveBVAsIntMode::IAND)
- {
- Node iAndOp = d_nm->mkConst(IntAnd(bvsize));
- returnNode = d_nm->mkNode(
- kind::IAND, iAndOp, translated_children[0], translated_children[1]);
- }
- else if (options().smt.solveBVAsInt == options::SolveBVAsIntMode::BV)
- {
- // translate the children back to BV
- Node intToBVOp = d_nm->mkConst<IntToBitVector>(IntToBitVector(bvsize));
- Node x = translated_children[0];
- Node y = translated_children[1];
- Node bvx = d_nm->mkNode(intToBVOp, x);
- Node bvy = d_nm->mkNode(intToBVOp, y);
- // perform bvand on the bit-vectors
- Node bvand = d_nm->mkNode(kind::BITVECTOR_AND, bvx, bvy);
- // translate the result to integers
- returnNode = d_nm->mkNode(kind::BITVECTOR_TO_NAT, bvand);
- }
- else
- {
- Assert(options().smt.solveBVAsInt == options::SolveBVAsIntMode::SUM);
- // Construct a sum of ites, based on granularity.
- Assert(translated_children.size() == 2);
- returnNode =
- d_iandUtils.createSumNode(translated_children[0],
- translated_children[1],
- bvsize,
- options().smt.BVAndIntegerGranularity);
- }
- break;
- }
- case kind::BITVECTOR_SHL:
- {
- /**
- * a << b is a*2^b.
- * The exponentiation is simulated by an ite.
- * Only cases where b <= bit width are considered.
- * Otherwise, the result is 0.
- */
- uint64_t bvsize = original[0].getType().getBitVectorSize();
- returnNode = createShiftNode(translated_children, bvsize, true);
- break;
- }
- case kind::BITVECTOR_LSHR:
- {
- /**
- * a >> b is a div 2^b.
- * The exponentiation is simulated by an ite.
- * Only cases where b <= bit width are considered.
- * Otherwise, the result is 0.
- */
- uint64_t bvsize = original[0].getType().getBitVectorSize();
- returnNode = createShiftNode(translated_children, bvsize, false);
- break;
- }
- case kind::BITVECTOR_ASHR:
- {
- /* From SMT-LIB2:
- * (bvashr s t) abbreviates
- * (ite (= ((_ extract |m-1| |m-1|) s) #b0)
- * (bvlshr s t)
- * (bvnot (bvlshr (bvnot s) t)))
- *
- * Equivalently:
- * (bvashr s t) abbreviates
- * (ite (bvult s 100000...)
- * (bvlshr s t)
- * (bvnot (bvlshr (bvnot s) t)))
- *
- */
- uint64_t bvsize = original[0].getType().getBitVectorSize();
- // signed_min is 100000...
- Node signed_min = pow2(bvsize - 1);
- Node condition =
- d_nm->mkNode(kind::LT, translated_children[0], signed_min);
- Node thenNode = createShiftNode(translated_children, bvsize, false);
- vector<Node> children = {createBVNotNode(translated_children[0], bvsize),
- translated_children[1]};
- Node elseNode =
- createBVNotNode(createShiftNode(children, bvsize, false), bvsize);
- returnNode = d_nm->mkNode(kind::ITE, condition, thenNode, elseNode);
- break;
- }
- case kind::BITVECTOR_ITE:
- {
- // Lifted to a boolean ite.
- Node cond = d_nm->mkNode(kind::EQUAL, translated_children[0], d_one);
- returnNode = d_nm->mkNode(
- kind::ITE, cond, translated_children[1], translated_children[2]);
- break;
- }
- case kind::BITVECTOR_ZERO_EXTEND:
- {
- returnNode = translated_children[0];
- break;
- }
- case kind::BITVECTOR_SIGN_EXTEND:
- {
- uint64_t bvsize = original[0].getType().getBitVectorSize();
- Node arg = translated_children[0];
- if (arg.isConst())
- {
- Rational c(arg.getConst<Rational>());
- Rational twoToKMinusOne(intpow2(bvsize - 1));
- uint64_t amount = bv::utils::getSignExtendAmount(original);
- /* if the msb is 0, this is like zero_extend.
- * msb is 0 <-> the value is less than 2^{bvsize-1}
- */
- if (c < twoToKMinusOne || amount == 0)
- {
- returnNode = arg;
- }
- else
- {
- /* otherwise, we add the integer equivalent of
- * 11....1 `amount` times
- */
- Rational max_of_amount = intpow2(amount) - 1;
- Rational mul = max_of_amount * intpow2(bvsize);
- Rational sum = mul + c;
- returnNode = d_nm->mkConst(CONST_RATIONAL, sum);
- }
- }
- else
- {
- uint64_t amount = bv::utils::getSignExtendAmount(original);
- if (amount == 0)
- {
- returnNode = translated_children[0];
- }
- else
- {
- Rational twoToKMinusOne(intpow2(bvsize - 1));
- Node minSigned = d_nm->mkConst(CONST_RATIONAL, twoToKMinusOne);
- /* condition checks whether the msb is 1.
- * This holds when the integer value is smaller than
- * 100...0, which is 2^{bvsize-1}.
- */
- Node condition = d_nm->mkNode(kind::LT, arg, minSigned);
- Node thenResult = arg;
- Node left = maxInt(amount);
- Node mul = d_nm->mkNode(kind::MULT, left, pow2(bvsize));
- Node sum = d_nm->mkNode(kind::PLUS, mul, arg);
- Node elseResult = sum;
- Node ite = d_nm->mkNode(kind::ITE, condition, thenResult, elseResult);
- returnNode = ite;
- }
- }
- break;
- }
- case kind::BITVECTOR_CONCAT:
- {
- // (concat a b) translates to a*2^k+b, k being the bitwidth of b.
- uint64_t bvsizeRight = original[1].getType().getBitVectorSize();
- Node pow2BvSizeRight = pow2(bvsizeRight);
- Node a =
- d_nm->mkNode(kind::MULT, translated_children[0], pow2BvSizeRight);
- Node b = translated_children[1];
- returnNode = d_nm->mkNode(kind::PLUS, a, b);
- break;
- }
- case kind::BITVECTOR_EXTRACT:
- {
- // ((_ extract i j) a) is a / 2^j mod 2^{i-j+1}
- // original = a[i:j]
- uint64_t i = bv::utils::getExtractHigh(original);
- uint64_t j = bv::utils::getExtractLow(original);
- Assert(i >= j);
- Node div = d_nm->mkNode(
- kind::INTS_DIVISION_TOTAL, translated_children[0], pow2(j));
- returnNode = modpow2(div, i - j + 1);
- break;
- }
- case kind::EQUAL:
- {
- returnNode = d_nm->mkNode(kind::EQUAL, translated_children);
- break;
- }
- case kind::BITVECTOR_ULT:
- {
- returnNode = d_nm->mkNode(kind::LT, translated_children);
- break;
- }
- case kind::BITVECTOR_ULE:
- {
- returnNode = d_nm->mkNode(kind::LEQ, translated_children);
- break;
- }
- case kind::BITVECTOR_UGT:
- {
- returnNode = d_nm->mkNode(kind::GT, translated_children);
- break;
- }
- case kind::BITVECTOR_UGE:
- {
- returnNode = d_nm->mkNode(kind::GEQ, translated_children);
- break;
- }
- case kind::LT:
- {
- returnNode = d_nm->mkNode(kind::LT, translated_children);
- break;
- }
- case kind::LEQ:
- {
- returnNode = d_nm->mkNode(kind::LEQ, translated_children);
- break;
- }
- case kind::GT:
- {
- returnNode = d_nm->mkNode(kind::GT, translated_children);
- break;
- }
- case kind::GEQ:
- {
- returnNode = d_nm->mkNode(kind::GEQ, translated_children);
- break;
- }
- case kind::ITE:
- {
- returnNode = d_nm->mkNode(oldKind, translated_children);
- break;
- }
- case kind::APPLY_UF:
- {
- /**
- * higher order logic allows comparing between functions
- * The translation does not support this,
- * as the translated functions may be different outside
- * of the bounds that were relevant for the original
- * bit-vectors.
- */
- if (childrenTypesChanged(original) && logicInfo().isHigherOrder())
- {
- throw TypeCheckingExceptionPrivate(
- original,
- string("Cannot translate to Int: ") + original.toString());
- }
- // Insert the translated application term to the cache
- returnNode = d_nm->mkNode(kind::APPLY_UF, translated_children);
- // Add range constraints if necessary.
- // If the original range was a BV sort, the original application of
- // the function Must be within the range determined by the
- // bitwidth.
- if (original.getType().isBitVector())
- {
- d_rangeAssertions.insert(mkRangeConstraint(
- returnNode, original.getType().getBitVectorSize()));
- }
- break;
- }
- case kind::BOUND_VAR_LIST:
- {
- returnNode = d_nm->mkNode(oldKind, translated_children);
- break;
- }
- case kind::FORALL:
- {
- returnNode = translateQuantifiedFormula(original);
- break;
- }
- default:
- {
- Assert(oldKind != kind::EXISTS); // Exists is eliminated by the rewriter.
- // In the default case, we have reached an operator that we do not
- // translate directly to integers. The children whose types have
- // changed from bv to int should be adjusted back to bv and then
- // this term is reconstructed.
- TypeNode resultingType;
- if (original.getType().isBitVector())
- {
- resultingType = d_nm->integerType();
- }
- else
- {
- resultingType = original.getType();
- }
- Node reconstruction =
- reconstructNode(original, resultingType, translated_children);
- returnNode = reconstruction;
- break;
- }
- }
- Trace("bv-to-int-debug") << "original: " << original << endl;
- Trace("bv-to-int-debug") << "returnNode: " << returnNode << endl;
- return returnNode;
-}
-
-Node BVToInt::translateNoChildren(Node original)
-{
- SkolemManager* sm = d_nm->getSkolemManager();
- Node translation;
- Assert(original.isVar() || original.isConst());
- if (original.isVar())
- {
- if (original.getType().isBitVector())
- {
- // For bit-vector variables, we create fresh integer variables.
- if (original.getKind() == kind::BOUND_VARIABLE)
- {
- // Range constraints for the bound integer variables are not added now.
- // they will be added once the quantifier itself is handled.
- std::stringstream ss;
- ss << original;
- translation = d_nm->mkBoundVar(ss.str() + "_int", d_nm->integerType());
- }
- else
- {
- // New integer variables that are not bound (symbolic constants)
- // are added together with range constraints induced by the
- // bit-width of the original bit-vector variables.
- Node newVar = sm->mkDummySkolem("__bvToInt_var",
- d_nm->integerType(),
- "Variable introduced in bvToInt "
- "pass instead of original variable "
- + original.toString());
- uint64_t bvsize = original.getType().getBitVectorSize();
- translation = newVar;
- d_rangeAssertions.insert(mkRangeConstraint(newVar, bvsize));
- defineBVUFAsIntUF(original, newVar);
- }
- }
- else if (original.getType().isFunction())
- {
- translation = translateFunctionSymbol(original);
- }
- else
- {
- // variables other than bit-vector variables and function symbols
- // are left intact
- translation = original;
- }
- }
- else
- {
- // original is a const
- if (original.getKind() == kind::CONST_BITVECTOR)
- {
- // Bit-vector constants are transformed into their integer value.
- BitVector constant(original.getConst<BitVector>());
- Integer c = constant.toInteger();
- translation = d_nm->mkConst(CONST_RATIONAL, Rational(c));
- }
- else
- {
- // Other constants stay the same.
- translation = original;
- }
- }
- return translation;
-}
-
-Node BVToInt::translateFunctionSymbol(Node bvUF)
-{
- // construct the new function symbol.
- Node intUF;
- TypeNode tn = bvUF.getType();
- TypeNode bvRange = tn.getRangeType();
- // The function symbol has not been converted yet
- vector<TypeNode> bvDomain = tn.getArgTypes();
- vector<TypeNode> intDomain;
- /**
- * if the original range is a bit-vector sort,
- * the new range should be an integer sort.
- * Otherwise, we keep the original range.
- * Similarly for the domains.
- */
- TypeNode intRange = bvRange.isBitVector() ? d_nm->integerType() : bvRange;
- for (TypeNode d : bvDomain)
- {
- intDomain.push_back(d.isBitVector() ? d_nm->integerType() : d);
- }
- SkolemManager* sm = d_nm->getSkolemManager();
- ostringstream os;
- os << "__bvToInt_fun_" << bvUF << "_int";
- intUF = sm->mkDummySkolem(
- os.str(), d_nm->mkFunctionType(intDomain, intRange), "bv2int function");
- // introduce a `define-fun` in the smt-engine to keep
- // the correspondence between the original
- // function symbol and the new one.
- defineBVUFAsIntUF(bvUF, intUF);
- return intUF;
-}
-
-void BVToInt::defineBVUFAsIntUF(Node bvUF, Node intUF)
-{
- // The resulting term
- Node result;
- // The type of the resulting term
- TypeNode resultType;
- // symbolic arguments of original function
- vector<Node> args;
- if (!bvUF.getType().isFunction()) {
- // bvUF is a variable.
- // in this case, the result is just the original term
- // (it will be casted later if needed)
- result = intUF;
- resultType = bvUF.getType();
- } else {
- // bvUF is a function with arguments
- // The arguments need to be casted as well.
- TypeNode tn = bvUF.getType();
- resultType = tn.getRangeType();
- vector<TypeNode> bvDomain = tn.getArgTypes();
- // children of the new symbolic application
- vector<Node> achildren;
- achildren.push_back(intUF);
- int i = 0;
- for (const TypeNode& d : bvDomain)
- {
- // Each bit-vector argument is casted to a natural number
- // Other arguments are left intact.
- Node fresh_bound_var = d_nm->mkBoundVar(d);
- args.push_back(fresh_bound_var);
- Node castedArg = args[i];
- if (d.isBitVector())
- {
- castedArg = castToType(castedArg, d_nm->integerType());
- }
- achildren.push_back(castedArg);
- i++;
- }
- result = d_nm->mkNode(kind::APPLY_UF, achildren);
- }
- // If the result is BV, it needs to be casted back.
- result = castToType(result, resultType);
- // add the substitution to the preprocessing context, which ensures the
- // model for bvUF is correct, as well as substituting it in the input
- // assertions when necessary.
- if (!args.empty())
- {
- result = d_nm->mkNode(
- kind::LAMBDA, d_nm->mkNode(kind::BOUND_VAR_LIST, args), result);
- }
- d_preprocContext->addSubstitution(bvUF, result);
-}
-
-bool BVToInt::childrenTypesChanged(Node n)
-{
- bool result = false;
- for (const Node& child : n)
- {
- TypeNode originalType = child.getType();
- TypeNode newType = d_bvToIntCache[child].get().getType();
- if (!newType.isSubtypeOf(originalType))
- {
- result = true;
- break;
- }
- }
- return result;
-}
-
-Node BVToInt::castToType(Node n, TypeNode tn)
-{
- // If there is no reason to cast, return the
- // original node.
- if (n.getType().isSubtypeOf(tn))
- {
- return n;
- }
- // We only case int to bv or vice verse.
- Assert((n.getType().isBitVector() && tn.isInteger())
- || (n.getType().isInteger() && tn.isBitVector()));
- if (n.getType().isInteger())
- {
- Assert(tn.isBitVector());
- unsigned bvsize = tn.getBitVectorSize();
- Node intToBVOp = d_nm->mkConst<IntToBitVector>(IntToBitVector(bvsize));
- return d_nm->mkNode(intToBVOp, n);
- }
- Assert(n.getType().isBitVector());
- Assert(tn.isInteger());
- return d_nm->mkNode(kind::BITVECTOR_TO_NAT, n);
-}
-
-Node BVToInt::reconstructNode(Node originalNode,
- TypeNode resultType,
- const vector<Node>& translated_children)
-{
- // first, we adjust the children of the node as needed.
- // re-construct the term with the adjusted children.
- kind::Kind_t oldKind = originalNode.getKind();
- NodeBuilder builder(oldKind);
- if (originalNode.getMetaKind() == kind::metakind::PARAMETERIZED)
- {
- builder << originalNode.getOperator();
- }
- for (size_t i = 0; i < originalNode.getNumChildren(); i++)
- {
- Node originalChild = originalNode[i];
- Node translatedChild = translated_children[i];
- Node adjustedChild = castToType(translatedChild, originalChild.getType());
- builder << adjustedChild;
- }
- Node reconstruction = builder.constructNode();
- // cast to tn in case the reconstruction is a bit-vector.
- reconstruction = castToType(reconstruction, resultType);
- return reconstruction;
-}
-
BVToInt::BVToInt(PreprocessingPassContext* preprocContext)
: PreprocessingPass(preprocContext, "bv-to-int"),
- d_binarizeCache(userContext()),
- d_eliminationCache(userContext()),
- d_rebuildCache(userContext()),
- d_bvToIntCache(userContext()),
- d_rangeAssertions(userContext())
-{
- d_nm = NodeManager::currentNM();
- d_zero = d_nm->mkConst(CONST_RATIONAL, Rational(0));
- d_one = d_nm->mkConst(CONST_RATIONAL, Rational(1));
-};
+ d_intBlaster(preprocContext->getEnv(),
+ options::solveBVAsInt(),
+ options::BVAndIntegerGranularity()) {}
PreprocessingPassResult BVToInt::applyInternal(
AssertionPipeline* assertionsToPreprocess)
{
+ // vector of boolean nodes for additional constraints
+ // this will always contain range constraints
+ // and for options::SolveBVAsIntMode::BITWISE, it will
+ // also include bitwise assertion constraints
+ std::vector<Node> additionalConstraints;
+ std::map<Node, Node> skolems;
for (uint64_t i = 0; i < assertionsToPreprocess->size(); ++i)
{
Node bvNode = (*assertionsToPreprocess)[i];
- Node intNode = bvToInt(bvNode);
+ Node intNode =
+ d_intBlaster.intBlast(bvNode, additionalConstraints, skolems);
Node rwNode = rewrite(intNode);
Trace("bv-to-int-debug") << "bv node: " << bvNode << std::endl;
Trace("bv-to-int-debug") << "int node: " << intNode << std::endl;
Trace("bv-to-int-debug") << "rw node: " << rwNode << std::endl;
assertionsToPreprocess->replace(i, rwNode);
}
- addFinalizeRangeAssertions(assertionsToPreprocess);
+ addFinalizeAssertions(assertionsToPreprocess, additionalConstraints);
+ addSkolemDefinitions(skolems);
return PreprocessingPassResult::NO_CONFLICT;
}
-void BVToInt::addFinalizeRangeAssertions(
- AssertionPipeline* assertionsToPreprocess)
-{
- // collect the range assertions from d_rangeAssertions
- // (which is a context-dependent set)
- // into a vector.
- vector<Node> vec_range;
- vec_range.assign(d_rangeAssertions.key_begin(), d_rangeAssertions.key_end());
- // conjoin all range assertions and add the conjunction
- // as a new assertion
- Node rangeAssertions = rewrite(d_nm->mkAnd(vec_range));
- assertionsToPreprocess->push_back(rangeAssertions);
- Trace("bv-to-int-debug") << "range constraints: "
- << rangeAssertions.toString() << std::endl;
-}
-
-Node BVToInt::createShiftNode(vector<Node> children,
- uint64_t bvsize,
- bool isLeftShift)
+void BVToInt::addSkolemDefinitions(const std::map<Node, Node>& skolems)
{
- /**
- * from SMT-LIB:
- * [[(bvshl s t)]] := nat2bv[m](bv2nat([[s]]) * 2^(bv2nat([[t]])))
- * [[(bvlshr s t)]] := nat2bv[m](bv2nat([[s]]) div 2^(bv2nat([[t]])))
- * Since we don't have exponentiation, we use an ite.
- * Important note: below we use INTS_DIVISION_TOTAL, which is safe here
- * because we divide by 2^... which is never 0.
- */
- Node x = children[0];
- Node y = children[1];
- // shifting by const is eliminated by the theory rewriter
- Assert(!y.isConst());
- Node ite = d_zero;
- Node body;
- for (uint64_t i = 0; i < bvsize; i++)
+ map<Node, Node>::const_iterator it;
+ for (it = skolems.begin(); it != skolems.end(); it++)
{
- if (isLeftShift)
+ Node originalSkolem = it->first;
+ Node definition = it->second;
+ std::vector<Node> args;
+ Node body;
+ if (definition.getType().isFunction())
{
- body = d_nm->mkNode(kind::INTS_MODULUS_TOTAL,
- d_nm->mkNode(kind::MULT, x, pow2(i)),
- pow2(bvsize));
+ args.insert(args.end(), definition[0].begin(), definition[0].end());
+ body = definition[1];
}
else
{
- body = d_nm->mkNode(kind::INTS_DIVISION_TOTAL, x, pow2(i));
+ body = definition;
}
- ite = d_nm->mkNode(
- kind::ITE,
- d_nm->mkNode(
- kind::EQUAL, y, d_nm->mkConst(CONST_RATIONAL, Rational(i))),
- body,
- ite);
+ Trace("bv-to-int-debug") << "adding substitution: " << "[" << originalSkolem << "] ----> [" << definition << "]" << std::endl;
+ d_preprocContext->addSubstitution(originalSkolem, definition);
}
- return ite;
-}
-
-Node BVToInt::translateQuantifiedFormula(Node quantifiedNode)
-{
- kind::Kind_t k = quantifiedNode.getKind();
- Node boundVarList = quantifiedNode[0];
- Assert(boundVarList.getKind() == kind::BOUND_VAR_LIST);
- // Since bit-vector variables are being translated to
- // integer variables, we need to substitute the new ones
- // for the old ones.
- vector<Node> oldBoundVars;
- vector<Node> newBoundVars;
- vector<Node> rangeConstraints;
- for (Node bv : quantifiedNode[0])
- {
- oldBoundVars.push_back(bv);
- if (bv.getType().isBitVector())
- {
- // bit-vector variables are replaced by integer ones.
- // the new variables induce range constraints based on the
- // original bit-width.
- Node newBoundVar = d_bvToIntCache[bv];
- newBoundVars.push_back(newBoundVar);
- rangeConstraints.push_back(
- mkRangeConstraint(newBoundVar, bv.getType().getBitVectorSize()));
- }
- else
- {
- // variables that are not bit-vectors are not changed
- newBoundVars.push_back(bv);
- }
- }
-
- // the body of the quantifier
- Node matrix = d_bvToIntCache[quantifiedNode[1]];
- // make the substitution
- matrix = matrix.substitute(oldBoundVars.begin(),
- oldBoundVars.end(),
- newBoundVars.begin(),
- newBoundVars.end());
- // A node to represent all the range constraints.
- Node ranges = d_nm->mkAnd(rangeConstraints);
- // Add the range constraints to the body of the quantifier.
- // For "exists", this is added conjunctively
- // For "forall", this is added to the left side of an implication.
- matrix = d_nm->mkNode(
- k == kind::FORALL ? kind::IMPLIES : kind::AND, ranges, matrix);
- // create the new quantified formula and return it.
- Node newBoundVarsList = d_nm->mkNode(kind::BOUND_VAR_LIST, newBoundVars);
- Node result = d_nm->mkNode(kind::FORALL, newBoundVarsList, matrix);
- return result;
}
-Node BVToInt::createBVNotNode(Node n, uint64_t bvsize)
+void BVToInt::addFinalizeAssertions(
+ AssertionPipeline* assertionsToPreprocess,
+ const std::vector<Node>& additionalConstraints)
{
- return d_nm->mkNode(kind::MINUS, maxInt(bvsize), n);
+ NodeManager* nm = NodeManager::currentNM();
+ Node lemmas = nm->mkAnd(additionalConstraints);
+ assertionsToPreprocess->push_back(lemmas);
+ Trace("bv-to-int-debug") << "range constraints: " << lemmas.toString()
+ << std::endl;
}
} // namespace passes
diff --git a/src/preprocessing/passes/bv_to_int.h b/src/preprocessing/passes/bv_to_int.h
index d09f9e738..24fc185b5 100644
--- a/src/preprocessing/passes/bv_to_int.h
+++ b/src/preprocessing/passes/bv_to_int.h
@@ -1,6 +1,7 @@
+
/******************************************************************************
* Top contributors (to current version):
- * Yoni Zohar, Gereon Kremer, Makai Mann
+ * Yoni Zohar
*
* This file is part of the cvc5 project.
*
@@ -10,69 +11,18 @@
* directory for licensing information.
* ****************************************************************************
*
- * The BVToInt preprocessing pass
- *
- * Converts bit-vector formulas to integer formulas.
- * The conversion is implemented using a translation function Tr,
- * roughly described as follows:
- *
- * Tr(x) = fresh_x for every bit-vector variable x, where fresh_x is a fresh
- * integer variable.
- * Tr(c) = the integer value of c, for any bit-vector constant c.
- * Tr((bvadd s t)) = Tr(s) + Tr(t) mod 2^k, where k is the bit width of
- * s and t.
- * Similar transformations are done for bvmul, bvsub, bvudiv, bvurem, bvneg,
- * bvnot, bvconcat, bvextract
- * Tr((_ zero_extend m) x) = Tr(x)
- * Tr((_ sign_extend m) x) = ite(msb(x)=0, x, 2^k*(2^m-1) + x))
- * explanation: if the msb is 0, this is the same as zero_extend,
- * which does not change the integer value.
- * If the msb is 1, then the result should correspond to
- * concat(1...1, x), with m 1's.
- * m 1's is 2^m-1, and multiplying it by x's width (k) moves it
- * to the front.
- *
- * Tr((bvand s t)) depends on the granularity, which is provided by the user
- * when enabling this preprocessing pass.
- * We divide s and t to blocks.
- * The size of each block is the granularity, and so the number of
- * blocks is:
- * bit width/granularity (rounded down).
- * We create an ITE that represents an arbitrary block,
- * and then create a sum by mutiplying each block by the
- * appropriate power of two.
- * More formally:
- * Let g denote the granularity.
- * Let k denote the bit width of s and t.
- * Let b denote floor(k/g) if k >= g, or just k otherwise.
- * Tr((bvand s t)) =
- * Sigma_{i=0}^{b-1}(bvand s[(i+1)*g, i*g] t[(i+1)*g, i*g])*2^(i*g)
- *
- * Similar transformations are done for bvor, bvxor, bvxnor, bvnand, bvnor.
- *
- * Tr((bvshl a b)) = ite(Tr(b) >= k, 0, Tr(a)*ITE), where k is the bit width of
- * a and b, and ITE represents exponentiation up to k, that is:
- * ITE = ite(Tr(b)=0, 1, ite(Tr(b)=1), 2, ite(Tr(b)=2, 4, ...))
- * Similar transformations are done for bvlshr.
- *
- * Tr(a=b) = Tr(a)=Tr(b)
- * Tr((bvult a b)) = Tr(a) < Tr(b)
- * Similar transformations are done for bvule, bvugt, and bvuge.
- *
- * Bit-vector operators that are not listed above are either eliminated using
- * the function eliminationPass, or are not supported.
- *
+ * The bv-to-int preprocessing pass.
*/
-#include "cvc5_private.h"
-
#ifndef __CVC5__PREPROCESSING__PASSES__BV_TO_INT_H
#define __CVC5__PREPROCESSING__PASSES__BV_TO_INT_H
#include "context/cdhashmap.h"
-#include "context/cdhashset.h"
+#include "context/cdo.h"
+#include "context/context.h"
#include "preprocessing/preprocessing_pass.h"
-#include "theory/arith/nl/iand_utils.h"
+#include "preprocessing/preprocessing_pass_context.h"
+#include "theory/bv/int_blaster.h"
namespace cvc5 {
namespace preprocessing {
@@ -88,200 +38,15 @@ class BVToInt : public PreprocessingPass
protected:
PreprocessingPassResult applyInternal(
AssertionPipeline* assertionsToPreprocess) override;
- /**
- * A generic function that creates a logical shift node (either left or
- * right). a << b gets translated to a * 2^b mod 2^k, where k is the bit
- * width. a >> b gets translated to a div 2^b mod 2^k, where k is the bit
- * width. The exponentiation operation is translated to an ite for possible
- * values of the exponent, from 0 to k-1.
- * If the right operand of the shift is greater than k-1,
- * the result is 0.
- * @param children the two operands for the shift
- * @param bvsize the original bit widths of the operands
- * (before translation to integers)
- * @param isLeftShift true iff the desired operation is a left shift.
- * @return a node representing the shift.
- *
- */
- Node createShiftNode(std::vector<Node> children,
- uint64_t bvsize,
- bool isLeftShift);
-
- /**
- * Returns a node that represents the bitwise negation of n.
- */
- Node createBVNotNode(Node n, uint64_t bvsize);
-
- /**
- * The result is an integer term and is computed
- * according to the translation specified above.
- * @param n is a bit-vector term or formula to be translated.
- * @return integer node that corresponds to n.
- */
- Node bvToInt(Node n);
-
- /**
- * Whenever we introduce an integer variable that represents a bit-vector
- * variable, we need to guard the range of the newly introduced variable.
- * For bit width k, the constraint is 0 <= newVar < 2^k.
- * @param newVar the newly introduced integer variable
- * @param k the bit width of the original bit-vector variable.
- * @return a node representing the range constraint.
- */
- Node mkRangeConstraint(Node newVar, uint64_t k);
-
- /**
- * In the translation to integers, it is convenient to assume that certain
- * bit-vector operators do not occur in the original formula (e.g., repeat).
- * This function eliminates all these operators.
- */
- Node eliminationPass(Node n);
-
- /**
- * Some bit-vector operators (e.g., bvadd, bvand) are binary, but allow more
- * than two arguments as a syntactic sugar.
- * For example, we can have a node for (bvand x y z),
- * that represents (bvand (x (bvand y z))).
- * This function makes all such operators strictly binary.
- */
- Node makeBinary(Node n);
-
- /**
- * @param k A non-negative integer
- * @return A node that represents the constant 2^k
- */
- Node pow2(uint64_t k);
-
- /**
- * @param k A positive integer k
- * @return A node that represent the constant 2^k-1
- * For example, if k is 4, the result is a node representing the
- * constant 15.
- */
- Node maxInt(uint64_t k);
-
- /**
- * @param n A node representing an integer term
- * @param exponent A non-negative integer
- * @return A node representing (n mod (2^exponent))
- */
- Node modpow2(Node n, uint64_t exponent);
-
- bool childrenTypesChanged(Node n);
-
- /**
- * Add the range assertions collected in d_rangeAssertions
- * (using mkRangeConstraint) to the assertion pipeline.
- * If there are no range constraints, do nothing.
- * If there is a single range constraint, add it to the pipeline.
- * Otherwise, add all of them as a single conjunction
- */
- void addFinalizeRangeAssertions(AssertionPipeline* assertionsToPreprocess);
-
- /**
- * @param quantifiedNode a node whose main operator is forall/exists.
- * @return a node opbtained from quantifiedNode by:
- * 1. Replacing all bound BV variables by new bound integer variables.
- * 2. Add range constraints for the new variables, induced by the original
- * bit-width. These range constraints are added with "AND" in case of exists
- * and with "IMPLIES" in case of forall.
- */
- Node translateQuantifiedFormula(Node quantifiedNode);
-
- /**
- * Reconstructs a node whose main operator cannot be
- * translated to integers.
- * Reconstruction is done by casting to integers/bit-vectors
- * as needed.
- * For example, if node is (select A x) where A
- * is a bit-vector array, we do not change A to be
- * an integer array, even though x was translated
- * to integers.
- * In this case we cast x to (bv2nat x) during
- * the reconstruction.
- *
- * @param originalNode the node that we are reconstructing
- * @param resultType the desired type for the reconstruction
- * @param translated_children the children of originalNode
- * after their translation to integers.
- * @return A node with originalNode's operator that has type resultType.
- */
- Node reconstructNode(Node originalNode,
- TypeNode resultType,
- const std::vector<Node>& translated_children);
-
- /**
- * A useful utility function.
- * if n is an integer and tn is bit-vector,
- * applies the IntToBitVector operator on n.
- * if n is a vit-vector and tn is integer,
- * applies BitVector_TO_NAT operator.
- * Otherwise, keeps n intact.
- */
- Node castToType(Node n, TypeNode tn);
-
- /**
- * When a UF f is translated to a UF g,
- * we add a define-fun command to the smt-engine
- * to relate between f and g.
- * We do the same when f and g are just variables.
- * This is useful, for example, when asking
- * for a model-value of a term that includes the
- * original UF f.
- * @param bvUF the original function or variable
- * @param intUF the translated function or variable
- */
- void defineBVUFAsIntUF(Node bvUF, Node intUF);
-
- /**
- * @param bvUF is an uninterpreted function symbol from the original formula
- * @return a fresh uninterpreted function symbol, obtained from bvUF
- by replacing every argument of type BV to an argument of type Integer,
- and the return type becomes integer in case it was BV.
- */
- Node translateFunctionSymbol(Node bvUF);
-
- /**
- * Performs the actual translation to integers for nodes
- * that have children.
- */
- Node translateWithChildren(Node original,
- const std::vector<Node>& translated_children);
-
- /**
- * Performs the actual translation to integers for nodes
- * that don't have children (variables, constants, uninterpreted function
- * symbols).
- */
- Node translateNoChildren(Node original);
-
- /**
- * Caches for the different functions
- */
- CDNodeMap d_binarizeCache;
- CDNodeMap d_eliminationCache;
- CDNodeMap d_rebuildCache;
- CDNodeMap d_bvToIntCache;
- /**
- * Node manager that is used throughout the pass
- */
- NodeManager* d_nm;
+ // Add the lemmas in `additionalConstraints` to the assertions pipeline.
+ void addFinalizeAssertions(AssertionPipeline* assertionsToPreprocess,
+ const std::vector<Node>& additionalConstraints);
- /**
- * A set of constraints of the form 0 <= x < 2^k
- * These are added for every new integer variable that we introduce.
- */
- context::CDHashSet<Node> d_rangeAssertions;
+ // include the skolem map as substitutions
+ void addSkolemDefinitions(const std::map<Node, Node>& skolems);
- /**
- * Useful constants
- */
- Node d_zero;
- Node d_one;
-
- /** helper class for handeling bvand translation */
- theory::arith::nl::IAndUtils d_iandUtils;
+ IntBlaster d_intBlaster;
};
} // namespace passes
diff --git a/src/preprocessing/passes/int_to_bv.cpp b/src/preprocessing/passes/int_to_bv.cpp
index e6b5a4bca..2ff45aef0 100644
--- a/src/preprocessing/passes/int_to_bv.cpp
+++ b/src/preprocessing/passes/int_to_bv.cpp
@@ -235,25 +235,19 @@ Node IntToBV::intToBV(TNode n, NodeMap& cache)
}
else if (current.isConst())
{
- switch (current.getKind())
+ if (current.getType().isInteger())
{
- case kind::CONST_RATIONAL:
+ Rational constant = current.getConst<Rational>();
+ Assert (constant.isIntegral());
+ BitVector bv(size, constant.getNumerator());
+ if (bv.toSignedInteger() != constant.getNumerator())
{
- Rational constant = current.getConst<Rational>();
- if (constant.isIntegral()) {
- BitVector bv(size, constant.getNumerator());
- if (bv.toSignedInteger() != constant.getNumerator())
- {
- throw TypeCheckingExceptionPrivate(
- current,
- string("Not enough bits for constant in intToBV: ")
- + current.toString());
- }
- result = nm->mkConst(bv);
- }
- break;
+ throw TypeCheckingExceptionPrivate(
+ current,
+ string("Not enough bits for constant in intToBV: ")
+ + current.toString());
}
- default: break;
+ result = nm->mkConst(bv);
}
}
else
diff --git a/src/preprocessing/passes/learned_rewrite.cpp b/src/preprocessing/passes/learned_rewrite.cpp
index 642a63aa4..3922525f2 100644
--- a/src/preprocessing/passes/learned_rewrite.cpp
+++ b/src/preprocessing/passes/learned_rewrite.cpp
@@ -61,7 +61,7 @@ PreprocessingPassResult LearnedRewrite::applyInternal(
AssertionPipeline* assertionsToPreprocess)
{
NodeManager* nm = NodeManager::currentNM();
- arith::BoundInference binfer;
+ arith::BoundInference binfer(d_env);
std::vector<Node> learnedLits = d_preprocContext->getLearnedLiterals();
std::unordered_set<Node> llrw;
std::unordered_map<TNode, Node> visited;
diff --git a/src/preprocessing/passes/miplib_trick.cpp b/src/preprocessing/passes/miplib_trick.cpp
index 66646b766..1be5ee81b 100644
--- a/src/preprocessing/passes/miplib_trick.cpp
+++ b/src/preprocessing/passes/miplib_trick.cpp
@@ -213,8 +213,7 @@ PreprocessingPassResult MipLibTrick::applyInternal(
NodeManager* nm = NodeManager::currentNM();
SkolemManager* sm = nm->getSkolemManager();
- Node zero = nm->mkConst(CONST_RATIONAL, Rational(0)),
- one = nm->mkConst(CONST_RATIONAL, Rational(1));
+ Node zero = nm->mkConstInt(Rational(0)), one = nm->mkConstInt(Rational(1));
Node trueNode = nm->mkConst(true);
unordered_map<TNode, Node> intVars;
@@ -276,10 +275,8 @@ PreprocessingPassResult MipLibTrick::applyInternal(
break;
}
if ((*j1)[1].getKind() != kind::EQUAL
- || !(((*j1)[1][0].isVar()
- && (*j1)[1][1].getKind() == kind::CONST_RATIONAL)
- || ((*j1)[1][0].getKind() == kind::CONST_RATIONAL
- && (*j1)[1][1].isVar())))
+ || !(((*j1)[1][0].isVar() && (*j1)[1][1].isConst())
+ || ((*j1)[1][0].isConst() && (*j1)[1][1].isVar())))
{
eligible = false;
Debug("miplib") << " -- INELIGIBLE -- (=> (and X X) X)" << endl;
@@ -332,14 +329,11 @@ PreprocessingPassResult MipLibTrick::applyInternal(
}
sort(posv.begin(), posv.end());
const Node pos = NodeManager::currentNM()->mkNode(kind::AND, posv);
- const TNode var = ((*j1)[1][0].getKind() == kind::CONST_RATIONAL)
- ? (*j1)[1][1]
- : (*j1)[1][0];
+ const TNode var = ((*j1)[1][0].isConst()) ? (*j1)[1][1] : (*j1)[1][0];
const pair<Node, Node> pos_var(pos, var);
- const Rational& constant =
- ((*j1)[1][0].getKind() == kind::CONST_RATIONAL)
- ? (*j1)[1][0].getConst<Rational>()
- : (*j1)[1][1].getConst<Rational>();
+ const Rational& constant = ((*j1)[1][0].isConst())
+ ? (*j1)[1][0].getConst<Rational>()
+ : (*j1)[1][1].getConst<Rational>();
uint64_t mark = 0;
unsigned countneg = 0, thepos = 0;
for (unsigned ii = 0; ii < pos.getNumChildren(); ++ii)
@@ -406,14 +400,11 @@ PreprocessingPassResult MipLibTrick::applyInternal(
const bool xneg = (x.getKind() == kind::NOT);
x = xneg ? x[0] : x;
Debug("miplib") << " x:" << x << " " << xneg << endl;
- const TNode var = ((*j1)[1][0].getKind() == kind::CONST_RATIONAL)
- ? (*j1)[1][1]
- : (*j1)[1][0];
+ const TNode var = ((*j1)[1][0].isConst()) ? (*j1)[1][1] : (*j1)[1][0];
const pair<Node, Node> x_var(x, var);
- const Rational& constant =
- ((*j1)[1][0].getKind() == kind::CONST_RATIONAL)
- ? (*j1)[1][0].getConst<Rational>()
- : (*j1)[1][1].getConst<Rational>();
+ const Rational& constant = ((*j1)[1][0].isConst())
+ ? (*j1)[1][0].getConst<Rational>()
+ : (*j1)[1][1].getConst<Rational>();
unsigned mark = (xneg ? 0 : 1);
if ((marks[x_var] & (1u << mark)) != 0)
{
@@ -573,17 +564,15 @@ PreprocessingPassResult MipLibTrick::applyInternal(
NodeBuilder sumb(kind::PLUS);
for (size_t jj = 0; jj < pos.getNumChildren(); ++jj)
{
- sumb << nm->mkNode(kind::MULT,
- nm->mkConst(CONST_RATIONAL, coef[pos_var][jj]),
- newVars[jj]);
+ sumb << nm->mkNode(
+ kind::MULT, nm->mkConstInt(coef[pos_var][jj]), newVars[jj]);
}
sum = sumb;
}
else
{
- sum = nm->mkNode(kind::MULT,
- nm->mkConst(CONST_RATIONAL, coef[pos_var][0]),
- newVars[0]);
+ sum = nm->mkNode(
+ kind::MULT, nm->mkConstInt(coef[pos_var][0]), newVars[0]);
}
Debug("miplib") << "vars[] " << var << endl
<< " eq " << rewrite(sum) << endl;
diff --git a/src/preprocessing/passes/non_clausal_simp.cpp b/src/preprocessing/passes/non_clausal_simp.cpp
index 4bf29157e..247a8b72e 100644
--- a/src/preprocessing/passes/non_clausal_simp.cpp
+++ b/src/preprocessing/passes/non_clausal_simp.cpp
@@ -120,6 +120,7 @@ PreprocessingPassResult NonClausalSimp::applyInternal(
<< " learned literals." << std::endl;
// No conflict, go through the literals and solve them
context::Context* u = userContext();
+ Rewriter* rw = d_env.getRewriter();
TrustSubstitutionMap& ttls = d_preprocContext->getTopLevelSubstitutions();
CVC5_UNUSED SubstitutionMap& top_level_substs = ttls.get();
// constant propagations
@@ -228,7 +229,7 @@ PreprocessingPassResult NonClausalSimp::applyInternal(
c = learnedLiteral[1];
}
Assert(!t.isConst());
- Assert(cps.apply(t, true) == t);
+ Assert(rewrite(cps.apply(t)) == t);
Assert(top_level_substs.apply(t) == t);
Assert(nss.apply(t) == t);
// also add to learned literal
@@ -293,7 +294,7 @@ PreprocessingPassResult NonClausalSimp::applyInternal(
for (size_t i = 0, size = assertionsToPreprocess->size(); i < size; ++i)
{
Node assertion = (*assertionsToPreprocess)[i];
- TrustNode assertionNew = newSubstitutions->applyTrusted(assertion);
+ TrustNode assertionNew = newSubstitutions->applyTrusted(assertion, rw);
Trace("non-clausal-simplify") << "assertion = " << assertion << std::endl;
if (!assertionNew.isNull())
{
@@ -305,7 +306,7 @@ PreprocessingPassResult NonClausalSimp::applyInternal(
}
for (;;)
{
- assertionNew = constantPropagations->applyTrusted(assertion);
+ assertionNew = constantPropagations->applyTrusted(assertion, rw);
if (assertionNew.isNull())
{
break;
@@ -340,7 +341,7 @@ PreprocessingPassResult NonClausalSimp::applyInternal(
if (d_preprocContext->getSymsInAssertions().contains(lhs))
{
// if it has, the substitution becomes an assertion
- TrustNode trhs = newSubstitutions->applyTrusted(lhs);
+ TrustNode trhs = newSubstitutions->applyTrusted(lhs, rw);
Assert(!trhs.isNull());
Trace("non-clausal-simplify")
<< "substitute: will notify SAT layer of substitution: "
@@ -446,10 +447,11 @@ Node NonClausalSimp::processLearnedLit(Node lit,
theory::TrustSubstitutionMap* subs,
theory::TrustSubstitutionMap* cp)
{
+ Rewriter* rw = d_env.getRewriter();
TrustNode tlit;
if (subs != nullptr)
{
- tlit = subs->applyTrusted(lit);
+ tlit = subs->applyTrusted(lit, rw);
if (!tlit.isNull())
{
lit = processRewrittenLearnedLit(tlit);
@@ -462,7 +464,7 @@ Node NonClausalSimp::processLearnedLit(Node lit,
{
for (;;)
{
- tlit = cp->applyTrusted(lit);
+ tlit = cp->applyTrusted(lit, rw);
if (tlit.isNull())
{
break;
diff --git a/src/preprocessing/passes/pseudo_boolean_processor.cpp b/src/preprocessing/passes/pseudo_boolean_processor.cpp
index 6c93eba15..0e7ac9c79 100644
--- a/src/preprocessing/passes/pseudo_boolean_processor.cpp
+++ b/src/preprocessing/passes/pseudo_boolean_processor.cpp
@@ -66,7 +66,7 @@ bool PseudoBooleanProcessor::decomposeAssertion(Node assertion, bool negated)
Node l = assertion[0];
Node r = assertion[1];
- if (r.getKind() != kind::CONST_RATIONAL)
+ if (!r.isConst())
{
Debug("pbs::rewrites") << "not rhs constant" << assertion << std::endl;
return false;
@@ -216,7 +216,7 @@ void PseudoBooleanProcessor::learnRewrittenGeq(Node assertion,
Node l = assertion[0];
Node r = assertion[1];
- if (r.getKind() == kind::CONST_RATIONAL)
+ if (r.isConst())
{
const Rational& rc = r.getConst<Rational>();
if (isIntVar(l))
@@ -233,8 +233,7 @@ void PseudoBooleanProcessor::learnRewrittenGeq(Node assertion,
else if (l.getKind() == kind::MULT && l.getNumChildren() == 2)
{
Node c = l[0], v = l[1];
- if (c.getKind() == kind::CONST_RATIONAL
- && c.getConst<Rational>().isNegativeOne())
+ if (c.isConst() && c.getConst<Rational>().isNegativeOne())
{
if (isIntVar(v))
{
diff --git a/src/preprocessing/passes/real_to_int.cpp b/src/preprocessing/passes/real_to_int.cpp
index 5c4539808..d2cde7b46 100644
--- a/src/preprocessing/passes/real_to_int.cpp
+++ b/src/preprocessing/passes/real_to_int.cpp
@@ -78,8 +78,7 @@ Node RealToInt::realToIntInternal(TNode n, NodeMap& cache, std::vector<Node>& va
if (!c.isNull())
{
Assert(c.isConst());
- coeffs.push_back(NodeManager::currentNM()->mkConst(
- CONST_RATIONAL,
+ coeffs.push_back(nm->mkConstInt(
Rational(c.getConst<Rational>().getDenominator())));
}
}
@@ -134,15 +133,10 @@ Node RealToInt::realToIntInternal(TNode n, NodeMap& cache, std::vector<Node>& va
}
Node sumt =
sum.empty()
- ? NodeManager::currentNM()->mkConst(CONST_RATIONAL,
- Rational(0))
- : (sum.size() == 1
- ? sum[0]
- : NodeManager::currentNM()->mkNode(kind::PLUS, sum));
- ret = NodeManager::currentNM()->mkNode(
- ret_lit.getKind(),
- sumt,
- NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(0)));
+ ? nm->mkConstInt(Rational(0))
+ : (sum.size() == 1 ? sum[0] : nm->mkNode(kind::PLUS, sum));
+ ret = nm->mkNode(
+ ret_lit.getKind(), sumt, nm->mkConstInt(Rational(0)));
if (!ret_pol)
{
ret = ret.negate();
diff --git a/src/preprocessing/passes/sygus_inference.cpp b/src/preprocessing/passes/sygus_inference.cpp
index 3da75beb2..cdbd6099e 100644
--- a/src/preprocessing/passes/sygus_inference.cpp
+++ b/src/preprocessing/passes/sygus_inference.cpp
@@ -301,14 +301,13 @@ bool SygusInference::solveSygus(const std::vector<Node>& assertions,
Trace("sygus-infer") << "*** Check sat..." << std::endl;
Result r = rrSygus->checkSat();
Trace("sygus-infer") << "...result : " << r << std::endl;
- if (r.asSatisfiabilityResult().isSat() != Result::UNSAT)
+ // get the synthesis solutions
+ std::map<Node, Node> synth_sols;
+ if (!rrSygus->getSubsolverSynthSolutions(synth_sols))
{
// failed, conjecture was infeasible
return false;
}
- // get the synthesis solutions
- std::map<Node, Node> synth_sols;
- rrSygus->getSynthSolutions(synth_sols);
std::vector<Node> final_ff;
std::vector<Node> final_ff_sol;
diff --git a/src/preprocessing/passes/unconstrained_simplifier.cpp b/src/preprocessing/passes/unconstrained_simplifier.cpp
index ae05d6b87..027be232b 100644
--- a/src/preprocessing/passes/unconstrained_simplifier.cpp
+++ b/src/preprocessing/passes/unconstrained_simplifier.cpp
@@ -515,9 +515,9 @@ void UnconstrainedSimplifier::processUnconstrained()
if (current.getType().isInteger())
{
// div/mult by 1 should have been simplified
- Assert(other != nm->mkConst(CONST_RATIONAL, Rational(1)));
+ Assert(other != nm->mkConstInt(Rational(1)));
// div by -1 should have been simplified
- if (other != nm->mkConst(CONST_RATIONAL, Rational(-1)))
+ if (other != nm->mkConstInt(Rational(-1)))
{
break;
}
diff --git a/src/proof/alethe/alethe_post_processor.cpp b/src/proof/alethe/alethe_post_processor.cpp
index 2254c025f..af683ffc6 100644
--- a/src/proof/alethe/alethe_post_processor.cpp
+++ b/src/proof/alethe/alethe_post_processor.cpp
@@ -20,6 +20,7 @@
#include "proof/proof.h"
#include "proof/proof_checker.h"
#include "proof/proof_node_algorithm.h"
+#include "proof/proof_node_manager.h"
#include "theory/builtin/proof_checker.h"
#include "util/rational.h"
@@ -465,7 +466,7 @@ bool AletheProofPostprocessCallback::update(Node res,
res,
nm->mkNode(kind::SEXPR, d_cl, res),
children,
- {nm->mkConst(CONST_RATIONAL, Rational(1))},
+ {nm->mkConstInt(Rational(1))},
*cdp);
}
default:
@@ -1351,7 +1352,7 @@ bool AletheProofPostprocessCallback::update(Node res,
{
Node vp1 = nm->mkNode(kind::SEXPR, d_cl, children[0], res);
std::vector<Node> new_children = {vp1, children[0]};
- new_args.push_back(nm->mkConst<Rational>(CONST_RATIONAL, 1));
+ new_args.push_back(nm->mkConstInt(Rational(1)));
return addAletheStep(AletheRule::LA_GENERIC, vp1, vp1, {}, new_args, *cdp)
&& addAletheStep(AletheRule::RESOLUTION,
res,
@@ -1374,7 +1375,7 @@ bool AletheProofPostprocessCallback::update(Node res,
{
Node vp1 = nm->mkNode(kind::SEXPR, d_cl, children[0], res);
std::vector<Node> new_children = {vp1, children[0]};
- new_args.push_back(nm->mkConst<Rational>(CONST_RATIONAL, 1));
+ new_args.push_back(nm->mkConstInt(Rational(1)));
return addAletheStep(AletheRule::LA_GENERIC, vp1, vp1, {}, new_args, *cdp)
&& addAletheStep(AletheRule::RESOLUTION,
res,
@@ -1383,6 +1384,232 @@ bool AletheProofPostprocessCallback::update(Node res,
{},
*cdp);
}
+ // ======== Trichotomy of the reals
+ // See proof_rule.h for documentation on the ARITH_TRICHOTOMY rule. This
+ // comment uses variable names as introduced there.
+ //
+ // If C = (= x c) or C = (> x c) pre-processing has to transform (>= x c)
+ // into (<= c x)
+ //
+ // ------------------------------------------------------ LA_DISEQUALITY
+ // (VP1: (cl (or (= x c) (not (<= x c)) (not (<= c x)))))
+ // -------------------------------------------------------- OR
+ // (VP2: (cl (= x c) (not (<= x c)) (not (<= c x))))
+ //
+ // If C = (> x c) or C = (< x c) post-processing has to be added. In these
+ // cases resolution on VP2 A B yields (not (<=x c)) or (not (<= c x)) and
+ // comp_simplify is used to transform it into C. Otherwise,
+ //
+ // VP2 A B
+ // ---------------- RESOLUTION
+ // (cl C)*
+ //
+ // * the corresponding proof node is C
+ case PfRule::ARITH_TRICHOTOMY:
+ {
+ bool success = true;
+ Node equal, lesser, greater;
+
+ Kind k = res.getKind();
+ if (k == kind::EQUAL)
+ {
+ equal = res;
+ if (children[0].getKind() == kind::LEQ)
+ {
+ greater = children[0];
+ lesser = children[1];
+ }
+ else
+ {
+ greater = children[1];
+ lesser = children[0];
+ }
+ }
+ // Add case where res is not =
+ else if (res.getKind() == kind::GT)
+ {
+ greater = res;
+ if (children[0].getKind() == kind::NOT)
+ {
+ equal = children[0];
+ lesser = children[1];
+ }
+ else
+ {
+ equal = children[1];
+ lesser = children[0];
+ }
+ }
+ else
+ {
+ lesser = res;
+ if (children[0].getKind() == kind::NOT)
+ {
+ equal = children[0];
+ greater = children[1];
+ }
+ else
+ {
+ equal = children[1];
+ greater = children[0];
+ }
+ }
+
+ Node x, c;
+ if (equal.getKind() == kind::NOT)
+ {
+ x = equal[0][0];
+ c = equal[0][1];
+ }
+ else
+ {
+ x = equal[0];
+ c = equal[1];
+ }
+ Node vp_child1 = children[0], vp_child2 = children[1];
+
+ // Preprocessing
+ if (res == equal || res == greater)
+ { // C = (= x c) or C = (> x c)
+ // lesser = (>= x c)
+ Node vpc2 = nm->mkNode(
+ kind::SEXPR,
+ d_cl,
+ nm->mkNode(kind::GEQ, x, c).eqNode(nm->mkNode(kind::LEQ, c, x)));
+ // (cl (= (>= x c) (<= c x)))
+ Node vpc1 = nm->mkNode(kind::SEXPR,
+ {d_cl,
+ vpc2[1].notNode(),
+ nm->mkNode(kind::GEQ, x, c).notNode(),
+ nm->mkNode(kind::LEQ, c, x)});
+ // (cl (not(= (>= x c) (<= c x))) (not (>= x c)) (<= c x))
+ vp_child1 = nm->mkNode(
+ kind::SEXPR, d_cl, nm->mkNode(kind::LEQ, c, x)); // (cl (<= c x))
+
+ success &=
+ addAletheStep(AletheRule::EQUIV_POS2, vpc1, vpc1, {}, {}, *cdp)
+ && addAletheStep(
+ AletheRule::COMP_SIMPLIFY, vpc2, vpc2, {}, {}, *cdp)
+ && addAletheStep(AletheRule::RESOLUTION,
+ vp_child1,
+ vp_child1,
+ {vpc1, vpc2, lesser},
+ {},
+ *cdp);
+ // greater = (<= x c) or greater = (not (= x c)) -> no preprocessing
+ // necessary
+ vp_child2 = res == equal ? greater : equal;
+ }
+
+ // Process
+ Node vp1 = nm->mkNode(kind::SEXPR,
+ d_cl,
+ nm->mkNode(kind::OR,
+ nm->mkNode(kind::EQUAL, x, c),
+ nm->mkNode(kind::LEQ, x, c).notNode(),
+ nm->mkNode(kind::LEQ, c, x).notNode()));
+ // (cl (or (= x c) (not (<= x c)) (not (<= c x))))
+ Node vp2 = nm->mkNode(kind::SEXPR,
+ {d_cl,
+ nm->mkNode(kind::EQUAL, x, c),
+ nm->mkNode(kind::LEQ, x, c).notNode(),
+ nm->mkNode(kind::LEQ, c, x).notNode()});
+ // (cl (= x c) (not (<= x c)) (not (<= c x)))
+ success &=
+ addAletheStep(AletheRule::LA_DISEQUALITY, vp1, vp1, {}, {}, *cdp)
+ && addAletheStep(AletheRule::OR, vp2, vp2, {vp1}, {}, *cdp);
+
+ // Postprocessing
+ if (res == equal)
+ { // no postprocessing necessary
+ return success
+ && addAletheStep(AletheRule::RESOLUTION,
+ res,
+ nm->mkNode(kind::SEXPR, d_cl, res),
+ {vp2, vp_child1, vp_child2},
+ {},
+ *cdp);
+ }
+ if (res == greater)
+ { // have (not (<= x c)) but result should be (> x c)
+ Node vp3 = nm->mkNode(
+ kind::SEXPR,
+ d_cl,
+ nm->mkNode(kind::LEQ, x, c).notNode()); // (cl (not (<= x c)))
+ Node vp4 = nm->mkNode(
+ kind::SEXPR,
+ {d_cl,
+ nm->mkNode(kind::EQUAL,
+ nm->mkNode(kind::GT, x, c),
+ nm->mkNode(kind::LEQ, x, c).notNode())
+ .notNode(),
+ nm->mkNode(kind::GT, x, c),
+ nm->mkNode(kind::LEQ, x, c)
+ .notNode()
+ .notNode()}); // (cl (not(= (> x c) (not (<= x c)))) (> x c)
+ // (not (not (<= x c))))
+ Node vp5 =
+ nm->mkNode(kind::SEXPR,
+ d_cl,
+ nm->mkNode(kind::GT, x, c)
+ .eqNode(nm->mkNode(kind::LEQ, x, c).notNode()));
+ // (cl (= (> x c) (not (<= x c))))
+
+ return success
+ && addAletheStep(AletheRule::RESOLUTION,
+ vp3,
+ vp3,
+ {vp2, vp_child1, vp_child2},
+ {},
+ *cdp)
+ && addAletheStep(AletheRule::EQUIV_POS1, vp4, vp4, {}, {}, *cdp)
+ && addAletheStep(
+ AletheRule::COMP_SIMPLIFY, vp5, vp5, {}, {}, *cdp)
+ && addAletheStep(AletheRule::RESOLUTION,
+ res,
+ nm->mkNode(kind::SEXPR, d_cl, res),
+ {vp3, vp4, vp5},
+ {},
+ *cdp);
+ }
+ // have (not (<= c x)) but result should be (< x c)
+ Node vp3 = nm->mkNode(
+ kind::SEXPR,
+ d_cl,
+ nm->mkNode(kind::LEQ, c, x).notNode()); // (cl (not (<= c x)))
+ Node vp4 =
+ nm->mkNode(kind::SEXPR,
+ {d_cl,
+ nm->mkNode(kind::LT, x, c)
+ .eqNode(nm->mkNode(kind::LEQ, c, x).notNode())
+ .notNode(),
+ nm->mkNode(kind::LT, x, c),
+ nm->mkNode(kind::LEQ, c, x)
+ .notNode()
+ .notNode()}); // (cl (not(= (< x c) (not (<= c x))))
+ // (< x c) (not (not (<= c x))))
+ Node vp5 = nm->mkNode(
+ kind::SEXPR,
+ d_cl,
+ nm->mkNode(kind::LT, x, c)
+ .eqNode(nm->mkNode(kind::LEQ, c, x)
+ .notNode())); // (cl (= (< x c) (not (<= c x))))
+ return success
+ && addAletheStep(AletheRule::RESOLUTION,
+ vp3,
+ vp3,
+ {vp2, vp_child1, vp_child2},
+ {},
+ *cdp)
+ && addAletheStep(AletheRule::EQUIV_POS1, vp4, vp4, {}, {}, *cdp)
+ && addAletheStep(AletheRule::COMP_SIMPLIFY, vp5, vp5, {}, {}, *cdp)
+ && addAletheStep(AletheRule::RESOLUTION,
+ res,
+ nm->mkNode(kind::SEXPR, d_cl, res),
+ {vp3, vp4, vp5},
+ {},
+ *cdp);
+ }
default:
{
return addAletheStep(AletheRule::UNDEFINED,
@@ -1445,17 +1672,28 @@ bool AletheProofPostprocessCallback::finalize(Node res,
{
std::shared_ptr<ProofNode> childPf = cdp->getProofFor(children[0]);
Node childConclusion = childPf->getArguments()[2];
+ AletheRule childRule = getAletheRule(childPf->getArguments()[0]);
// if child conclusion is of the form (sexpr cl (or ...)), then we need
// to add an OR step, since this child must not be a singleton
- if (childConclusion.getNumChildren() == 2 && childConclusion[0] == d_cl
- && childConclusion[1].getKind() == kind::OR)
+ if ((childConclusion.getNumChildren() == 2 && childConclusion[0] == d_cl
+ && childConclusion[1].getKind() == kind::OR)
+ || (childRule == AletheRule::ASSUME
+ && childConclusion.getKind() == kind::OR))
{
hasUpdated = true;
// Add or step
std::vector<Node> subterms{d_cl};
- subterms.insert(subterms.end(),
- childConclusion[1].begin(),
- childConclusion[1].end());
+ if (childRule == AletheRule::ASSUME)
+ {
+ subterms.insert(
+ subterms.end(), childConclusion.begin(), childConclusion.end());
+ }
+ else
+ {
+ subterms.insert(subterms.end(),
+ childConclusion[1].begin(),
+ childConclusion[1].end());
+ }
Node newConclusion = nm->mkNode(kind::SEXPR, subterms);
addAletheStep(AletheRule::OR,
newConclusion,
@@ -1484,16 +1722,27 @@ bool AletheProofPostprocessCallback::finalize(Node res,
{
std::shared_ptr<ProofNode> childPf = cdp->getProofFor(children[i]);
Node childConclusion = childPf->getArguments()[2];
+ AletheRule childRule = getAletheRule(childPf->getArguments()[0]);
// Add or step
- if (childConclusion.getNumChildren() == 2
- && childConclusion[0] == d_cl
- && childConclusion[1].getKind() == kind::OR)
+ if ((childConclusion.getNumChildren() == 2
+ && childConclusion[0] == d_cl
+ && childConclusion[1].getKind() == kind::OR)
+ || (childRule == AletheRule::ASSUME
+ && childConclusion.getKind() == kind::OR))
{
hasUpdated = true;
std::vector<Node> lits{d_cl};
- lits.insert(lits.end(),
- childConclusion[1].begin(),
- childConclusion[1].end());
+ if (childRule == AletheRule::ASSUME)
+ {
+ lits.insert(
+ lits.end(), childConclusion.begin(), childConclusion.end());
+ }
+ else
+ {
+ lits.insert(lits.end(),
+ childConclusion[1].begin(),
+ childConclusion[1].end());
+ }
Node conclusion = nm->mkNode(kind::SEXPR, lits);
addAletheStep(AletheRule::OR,
conclusion,
@@ -1547,14 +1796,25 @@ bool AletheProofPostprocessCallback::finalize(Node res,
{
std::shared_ptr<ProofNode> childPf = cdp->getProofFor(children[0]);
Node childConclusion = childPf->getArguments()[2];
- if (childConclusion.getNumChildren() == 2 && childConclusion[0] == d_cl
- && childConclusion[1].getKind() == kind::OR)
+ AletheRule childRule = getAletheRule(childPf->getArguments()[0]);
+ if ((childConclusion.getNumChildren() == 2 && childConclusion[0] == d_cl
+ && childConclusion[1].getKind() == kind::OR)
+ || (childRule == AletheRule::ASSUME
+ && childConclusion.getKind() == kind::OR))
{
// Add or step for child
std::vector<Node> subterms{d_cl};
- subterms.insert(subterms.end(),
- childConclusion[1].begin(),
- childConclusion[1].end());
+ if (getAletheRule(childPf->getArguments()[0]) == AletheRule::ASSUME)
+ {
+ subterms.insert(
+ subterms.end(), childConclusion.begin(), childConclusion.end());
+ }
+ else
+ {
+ subterms.insert(subterms.end(),
+ childConclusion[1].begin(),
+ childConclusion[1].end());
+ }
Node newChild = nm->mkNode(kind::SEXPR, subterms);
addAletheStep(
AletheRule::OR, newChild, newChild, {children[0]}, {}, *cdp);
@@ -1614,10 +1874,7 @@ bool AletheProofPostprocessCallback::finalStep(
if (id != PfRule::ALETHE_RULE)
{
std::vector<Node> sanitized_args{
- res,
- res,
- nm->mkConst<Rational>(CONST_RATIONAL,
- static_cast<unsigned>(AletheRule::ASSUME))};
+ res, res, nm->mkConstInt(static_cast<uint32_t>(AletheRule::ASSUME))};
for (const Node& arg : args)
{
sanitized_args.push_back(d_anc.convert(arg));
@@ -1680,8 +1937,8 @@ bool AletheProofPostprocessCallback::addAletheStep(
}
std::vector<Node> new_args = std::vector<Node>();
- new_args.push_back(NodeManager::currentNM()->mkConst(
- CONST_RATIONAL, Rational(static_cast<unsigned>(rule))));
+ new_args.push_back(NodeManager::currentNM()->mkConstInt(
+ Rational(static_cast<uint32_t>(rule))));
new_args.push_back(res);
new_args.push_back(sanitized_conclusion);
new_args.insert(new_args.end(), args.begin(), args.end());
@@ -1712,7 +1969,37 @@ AletheProofPostprocess::AletheProofPostprocess(ProofNodeManager* pnm,
AletheProofPostprocess::~AletheProofPostprocess() {}
-void AletheProofPostprocess::process(std::shared_ptr<ProofNode> pf) {}
+void AletheProofPostprocess::process(std::shared_ptr<ProofNode> pf) {
+ // Translate proof node
+ ProofNodeUpdater updater(d_pnm, d_cb,true,false);
+ updater.process(pf->getChildren()[0]);
+
+ // In the Alethe proof format the final step has to be (cl). However, after
+ // the translation it might be (cl false). In that case additional steps are
+ // required.
+ // The function has the additional purpose of sanitizing the attributes of the
+ // first SCOPE
+ CDProof cpf(d_pnm, nullptr, "ProofNodeUpdater::CDProof", true);
+ const std::vector<std::shared_ptr<ProofNode>>& cc = pf->getChildren();
+ std::vector<Node> ccn;
+ for (const std::shared_ptr<ProofNode>& cp : cc)
+ {
+ Node cpres = cp->getResult();
+ ccn.push_back(cpres);
+ // store in the proof
+ cpf.addProof(cp);
+ }
+ if (d_cb.finalStep(
+ pf->getResult(), pf->getRule(), ccn, pf->getArguments(), &cpf))
+ {
+ std::shared_ptr<ProofNode> npn = cpf.getProofFor(pf->getResult());
+
+ // then, update the original proof node based on this one
+ Trace("pf-process-debug") << "Update node..." << std::endl;
+ d_pnm->updateNode(pf.get(), npn.get());
+ Trace("pf-process-debug") << "...update node finished." << std::endl;
+ }
+}
} // namespace proof
diff --git a/src/proof/annotation_proof_generator.cpp b/src/proof/annotation_proof_generator.cpp
new file mode 100644
index 000000000..e9467276b
--- /dev/null
+++ b/src/proof/annotation_proof_generator.cpp
@@ -0,0 +1,87 @@
+/******************************************************************************
+ * Top contributors (to current version):
+ * Andrew Reynolds
+ *
+ * This file is part of the cvc5 project.
+ *
+ * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+ * in the top-level source directory and their institutional affiliations.
+ * All rights reserved. See the file COPYING in the top-level source
+ * directory for licensing information.
+ * ****************************************************************************
+ *
+ * Implementation of the annotation proof generator class.
+ */
+
+#include "proof/annotation_proof_generator.h"
+
+#include "proof/proof.h"
+#include "proof/proof_node.h"
+#include "proof/proof_node_manager.h"
+
+namespace cvc5 {
+
+AnnotationProofGenerator::AnnotationProofGenerator(ProofNodeManager* pnm,
+ context::Context* c,
+ std::string name)
+ : d_pnm(pnm),
+ d_name(name),
+ d_exps(c == nullptr ? &d_context : c),
+ d_proofs(c == nullptr ? &d_context : c)
+{
+}
+
+void AnnotationProofGenerator::setExplanationFor(Node f,
+ ProofGenerator* pg,
+ Annotator* a)
+{
+ Assert(pg != nullptr);
+ d_exps[f] = std::pair<ProofGenerator*, Annotator*>(pg, a);
+}
+
+std::shared_ptr<ProofNode> AnnotationProofGenerator::getProofFor(Node f)
+{
+ // is the proof already cached?
+ NodeProofNodeMap::iterator it = d_proofs.find(f);
+ if (it != d_proofs.end())
+ {
+ return (*it).second;
+ }
+ // make it into an actual proof now
+ NodeExpMap::iterator itx = d_exps.find(f);
+ if (itx == d_exps.end())
+ {
+ return nullptr;
+ }
+ // get the proof from the proof generator
+ std::shared_ptr<ProofNode> pf = itx->second.first->getProofFor(f);
+ if (pf == nullptr)
+ {
+ d_proofs[f] = nullptr;
+ return nullptr;
+ }
+ // now anntoate it if an annotator was provided
+ std::shared_ptr<ProofNode> pfa = pf;
+ if (itx->second.second != nullptr)
+ {
+ pfa = itx->second.second->annotate(pf);
+ }
+ d_proofs[f] = pfa;
+ return pfa;
+}
+
+TrustNode AnnotationProofGenerator::transform(const TrustNode& trn,
+ Annotator* a)
+{
+ setExplanationFor(trn.getProven(), trn.getGenerator(), a);
+ return TrustNode::mkReplaceGenTrustNode(trn, this);
+}
+
+bool AnnotationProofGenerator::hasProofFor(Node f)
+{
+ return d_exps.find(f) != d_exps.end();
+}
+
+std::string AnnotationProofGenerator::identify() const { return d_name; }
+
+} // namespace cvc5
diff --git a/src/proof/annotation_proof_generator.h b/src/proof/annotation_proof_generator.h
new file mode 100644
index 000000000..fb737dc44
--- /dev/null
+++ b/src/proof/annotation_proof_generator.h
@@ -0,0 +1,102 @@
+/******************************************************************************
+ * Top contributors (to current version):
+ * Andrew Reynolds
+ *
+ * This file is part of the cvc5 project.
+ *
+ * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+ * in the top-level source directory and their institutional affiliations.
+ * All rights reserved. See the file COPYING in the top-level source
+ * directory for licensing information.
+ * ****************************************************************************
+ *
+ * The annotation proof generator class.
+ */
+
+#include "cvc5_private.h"
+
+#ifndef CVC5__PROOF__ANNOTATION_PROOF_GENERATOR_H
+#define CVC5__PROOF__ANNOTATION_PROOF_GENERATOR_H
+
+#include "context/cdhashmap.h"
+#include "expr/node.h"
+#include "proof/proof_generator.h"
+#include "proof/trust_node.h"
+
+namespace cvc5 {
+
+class ProofNodeManager;
+
+/**
+ * Base class for annotators. An annotator is a utility that implements a
+ * simple transformation on proofs: `annotate` below.
+ */
+class Annotator
+{
+ public:
+ Annotator() {}
+ virtual ~Annotator() {}
+ /**
+ * Annotate the proof node. This must return a proof node that concludes the
+ * same thing as p.
+ */
+ virtual std::shared_ptr<ProofNode> annotate(std::shared_ptr<ProofNode> p) = 0;
+};
+
+/**
+ * Annotation proof generator, used to "wrap" proofs of other proof generators
+ * via the annotate method above.
+ */
+class AnnotationProofGenerator : public ProofGenerator
+{
+ typedef context::CDHashMap<Node, std::pair<ProofGenerator*, Annotator*>>
+ NodeExpMap;
+ typedef context::CDHashMap<Node, std::shared_ptr<ProofNode>> NodeProofNodeMap;
+
+ public:
+ AnnotationProofGenerator(ProofNodeManager* pnm,
+ context::Context* c = nullptr,
+ std::string name = "AnnotationProofGenerator");
+ ~AnnotationProofGenerator() {}
+ /** Get the proof for formula f. */
+ std::shared_ptr<ProofNode> getProofFor(Node f) override;
+ /** Can we give the proof for formula f? */
+ bool hasProofFor(Node f) override;
+ /**
+ * Set explanation for fact f, called when pg has a proof for f.
+ *
+ * @param f The fact proven by pg,
+ * @param pg The proof generator that can prove f.
+ * @param a The annotator that will annotate the proof of f, if necessary.
+ */
+ void setExplanationFor(Node f, ProofGenerator* pg, Annotator* a);
+ /**
+ * Transform trust node, will be annotated by the given annotator.
+ */
+ TrustNode transform(const TrustNode& trn, Annotator* a);
+ /** identify */
+ std::string identify() const override;
+
+ protected:
+ /** The proof node manager */
+ ProofNodeManager* d_pnm;
+ /** Name identifier */
+ std::string d_name;
+ /** A dummy context used by this class if none is provided */
+ context::Context d_context;
+ /**
+ * A context-dependent map from formulas to a generator + annotation
+ * pair, which will be used to generate the proof of formulas if asked.
+ * We use the context provided to this class or otherwise d_context above.
+ */
+ NodeExpMap d_exps;
+ /**
+ * A context-dependent map from formulas to the proof nodes we have
+ * returned in calls to getProofFor.
+ */
+ NodeProofNodeMap d_proofs;
+};
+
+} // namespace cvc5
+
+#endif /* CVC5__PROOF__ANNOTATION_PROOF_GENERATOR_H */
diff --git a/src/proof/lazy_proof_chain.cpp b/src/proof/lazy_proof_chain.cpp
index 0de5673ab..3280626ad 100644
--- a/src/proof/lazy_proof_chain.cpp
+++ b/src/proof/lazy_proof_chain.cpp
@@ -30,7 +30,8 @@ LazyCDProofChain::LazyCDProofChain(ProofNodeManager* pnm,
ProofGenerator* defGen,
bool defRec,
const std::string& name)
- : d_manager(pnm),
+ : CDProof(pnm, c, name, false),
+ d_manager(pnm),
d_cyclic(cyclic),
d_defRec(defRec),
d_context(),
@@ -85,21 +86,10 @@ std::shared_ptr<ProofNode> LazyCDProofChain::getProofFor(Node fact)
Trace("lazy-cdproofchain")
<< "LazyCDProofChain::getProofFor: check " << cur << "\n";
Assert(toConnect.find(cur) == toConnect.end());
+ // The current fact may be justified by concrete steps added to this
+ // proof, in which case we do not use the generators.
bool rec = true;
- ProofGenerator* pg = getGeneratorForInternal(cur, rec);
- if (!pg)
- {
- Trace("lazy-cdproofchain")
- << "LazyCDProofChain::getProofFor: nothing to do\n";
- // nothing to do for this fact, it'll be a leaf in the final proof
- // node, don't post-traverse.
- visited[cur] = true;
- continue;
- }
- Trace("lazy-cdproofchain")
- << "LazyCDProofChain::getProofFor: Call generator " << pg->identify()
- << " for chain link " << cur << "\n";
- std::shared_ptr<ProofNode> curPfn = pg->getProofFor(cur);
+ std::shared_ptr<ProofNode> curPfn = getProofForInternal(cur, rec);
if (curPfn == nullptr)
{
Trace("lazy-cdproofchain")
@@ -107,7 +97,8 @@ std::shared_ptr<ProofNode> LazyCDProofChain::getProofFor(Node fact)
visited[cur] = true;
continue;
}
- // map node whose proof node must be expanded to the respective poof node
+ // map node whose proof node must be expanded to the respective poof
+ // node
toConnect[cur] = curPfn;
// We may not want to recursively connect this proof so we skip.
if (!rec)
@@ -368,6 +359,27 @@ ProofGenerator* LazyCDProofChain::getGeneratorForInternal(Node fact, bool& rec)
return nullptr;
}
+std::shared_ptr<ProofNode> LazyCDProofChain::getProofForInternal(Node fact,
+ bool& rec)
+{
+ std::shared_ptr<ProofNode> pfn = CDProof::getProofFor(fact);
+ Assert(pfn != nullptr);
+ // If concrete proof, save it, otherwise try generators.
+ if (pfn->getRule() != PfRule::ASSUME)
+ {
+ return pfn;
+ }
+ ProofGenerator* pg = getGeneratorForInternal(fact, rec);
+ if (!pg)
+ {
+ return nullptr;
+ }
+ Trace("lazy-cdproofchain")
+ << "LazyCDProofChain::getProofFor: Call generator " << pg->identify()
+ << " for chain link " << fact << "\n";
+ return pg->getProofFor(fact);
+}
+
std::string LazyCDProofChain::identify() const { return d_name; }
} // namespace cvc5
diff --git a/src/proof/lazy_proof_chain.h b/src/proof/lazy_proof_chain.h
index d15b8f9e2..114e2310e 100644
--- a/src/proof/lazy_proof_chain.h
+++ b/src/proof/lazy_proof_chain.h
@@ -20,8 +20,7 @@
#include <vector>
-#include "context/cdhashmap.h"
-#include "proof/proof_generator.h"
+#include "proof/proof.h"
namespace cvc5 {
@@ -36,7 +35,7 @@ class ProofNodeManager;
* connecting, for the proof generated to one fact, assumptions to the proofs
* generated for those assumptinos that are registered in the chain.
*/
-class LazyCDProofChain : public ProofGenerator
+class LazyCDProofChain : public CDProof
{
public:
/** Constructor
@@ -92,6 +91,11 @@ class LazyCDProofChain : public ProofGenerator
* it is required to do so. This mapping is maintained in the remainder of
* the current context (according to the context c provided to this class).
*
+ * It is important to note that pg is asked to provide a proof for expected
+ * only when no other call for the fact expected is provided via the addStep
+ * method of this class. In particular, pg is asked to prove expected when it
+ * appears as the conclusion of an ASSUME leaf within CDProof::getProofFor.
+ *
* Moreover the lazy steps of this class are expected to fulfill the
* requirement that pg.getProofFor(expected) generates a proof node closed
* with relation to
@@ -136,6 +140,14 @@ class LazyCDProofChain : public ProofGenerator
* true if we should recurse on its proof.
*/
ProofGenerator* getGeneratorForInternal(Node fact, bool& rec);
+ /**
+ * Get internal proof for fact from the underlying CDProof, if any, otherwise
+ * via a call to the above method.
+ *
+ * Returns a nullptr when no internal proof stored.
+ */
+ std::shared_ptr<ProofNode> getProofForInternal(Node fact, bool& rec);
+
/** The proof manager, used for allocating new ProofNode objects */
ProofNodeManager* d_manager;
/** Whether this instance is robust to cycles in the chain. */
diff --git a/src/proof/lfsc/lfsc_node_converter.cpp b/src/proof/lfsc/lfsc_node_converter.cpp
index 6eab9b036..5af1c2b7e 100644
--- a/src/proof/lfsc/lfsc_node_converter.cpp
+++ b/src/proof/lfsc/lfsc_node_converter.cpp
@@ -89,7 +89,7 @@ Node LfscNodeConverter::postConvert(Node n)
}
// bound variable v is (bvar x T)
TypeNode intType = nm->integerType();
- Node x = nm->mkConst(CONST_RATIONAL, Rational(getOrAssignIndexForVar(n)));
+ Node x = nm->mkConstInt(Rational(getOrAssignIndexForVar(n)));
Node tc = typeAsNode(convertType(tn));
TypeNode ftype = nm->mkFunctionType({intType, d_sortType}, tn);
Node bvarOp = getSymbolInternal(k, ftype, "bvar");
@@ -136,8 +136,7 @@ Node LfscNodeConverter::postConvert(Node n)
TypeNode intType = nm->integerType();
TypeNode varType = nm->mkFunctionType({intType, d_sortType}, tn);
Node var = mkInternalSymbol("var", varType);
- Node index =
- nm->mkConst(CONST_RATIONAL, Rational(getOrAssignIndexForVar(n)));
+ Node index = nm->mkConstInt(Rational(getOrAssignIndexForVar(n)));
Node tc = typeAsNode(convertType(tn));
return nm->mkNode(APPLY_UF, var, index, tc);
}
@@ -176,7 +175,7 @@ Node LfscNodeConverter::postConvert(Node n)
Node hconstf = getSymbolInternal(k, tnh, "apply");
return nm->mkNode(APPLY_UF, hconstf, n[0], n[1]);
}
- else if (k == CONST_RATIONAL || k == CAST_TO_REAL)
+ else if (k == CONST_RATIONAL || k == CONST_INTEGER || k == CAST_TO_REAL)
{
if (k == CAST_TO_REAL)
{
@@ -184,8 +183,9 @@ Node LfscNodeConverter::postConvert(Node n)
do
{
n = n[0];
- Assert(n.getKind() == APPLY_UF || n.getKind() == CONST_RATIONAL);
- } while (n.getKind() != CONST_RATIONAL);
+ Assert(n.getKind() == APPLY_UF || n.getKind() == CONST_RATIONAL
+ || n.getKind() == CONST_INTEGER);
+ } while (n.getKind() != CONST_RATIONAL && n.getKind() != CONST_INTEGER);
}
TypeNode tnv = nm->mkFunctionType(tn, tn);
Node rconstf;
@@ -198,7 +198,7 @@ Node LfscNodeConverter::postConvert(Node n)
{
// use LFSC syntax for mpz negation
Node mpzn = getSymbolInternal(k, nm->mkFunctionType(tn, tn), "~");
- arg = nm->mkNode(APPLY_UF, mpzn, nm->mkConst(CONST_RATIONAL, r.abs()));
+ arg = nm->mkNode(APPLY_UF, mpzn, nm->mkConstInt(r.abs()));
}
else
{
@@ -344,8 +344,8 @@ Node LfscNodeConverter::postConvert(Node n)
Node rop = getSymbolInternal(
k, relType, printer::smt2::Smt2Printer::smtKindString(k));
RegExpLoop op = n.getOperator().getConst<RegExpLoop>();
- Node n1 = nm->mkConst(CONST_RATIONAL, Rational(op.d_loopMinOcc));
- Node n2 = nm->mkConst(CONST_RATIONAL, Rational(op.d_loopMaxOcc));
+ Node n1 = nm->mkConstInt(Rational(op.d_loopMinOcc));
+ Node n2 = nm->mkConstInt(Rational(op.d_loopMaxOcc));
return nm->mkNode(APPLY_UF, nm->mkNode(APPLY_UF, rop, n1, n2), n[0]);
}
else if (k == MATCH)
@@ -485,16 +485,14 @@ TypeNode LfscNodeConverter::postConvertType(TypeNode tn)
else if (k == BITVECTOR_TYPE)
{
tnn = d_typeKindToNodeCons[k];
- Node w = nm->mkConst(CONST_RATIONAL, Rational(tn.getBitVectorSize()));
+ Node w = nm->mkConstInt(Rational(tn.getBitVectorSize()));
tnn = nm->mkNode(APPLY_UF, tnn, w);
}
else if (k == FLOATINGPOINT_TYPE)
{
tnn = d_typeKindToNodeCons[k];
- Node e = nm->mkConst(CONST_RATIONAL,
- Rational(tn.getFloatingPointExponentSize()));
- Node s = nm->mkConst(CONST_RATIONAL,
- Rational(tn.getFloatingPointSignificandSize()));
+ Node e = nm->mkConstInt(Rational(tn.getFloatingPointExponentSize()));
+ Node s = nm->mkConstInt(Rational(tn.getFloatingPointSignificandSize()));
tnn = nm->mkNode(APPLY_UF, tnn, e, s);
}
else if (tn.getNumChildren() == 0)
@@ -723,8 +721,7 @@ void LfscNodeConverter::getCharVectorInternal(Node c, std::vector<Node>& chars)
Node aconstf = getSymbolInternal(CONST_STRING, tnc, "char");
for (unsigned i = 0, size = vec.size(); i < size; i++)
{
- Node cc = nm->mkNode(
- APPLY_UF, aconstf, nm->mkConst(CONST_RATIONAL, Rational(vec[i])));
+ Node cc = nm->mkNode(APPLY_UF, aconstf, nm->mkConstInt(Rational(vec[i])));
chars.push_back(cc);
}
}
@@ -747,42 +744,36 @@ std::vector<Node> LfscNodeConverter::getOperatorIndices(Kind k, Node n)
case BITVECTOR_EXTRACT:
{
BitVectorExtract p = n.getConst<BitVectorExtract>();
- indices.push_back(nm->mkConst(CONST_RATIONAL, Rational(p.d_high)));
- indices.push_back(nm->mkConst(CONST_RATIONAL, Rational(p.d_low)));
+ indices.push_back(nm->mkConstInt(Rational(p.d_high)));
+ indices.push_back(nm->mkConstInt(Rational(p.d_low)));
break;
}
case BITVECTOR_REPEAT:
- indices.push_back(
- nm->mkConst(CONST_RATIONAL,
- Rational(n.getConst<BitVectorRepeat>().d_repeatAmount)));
+ indices.push_back(nm->mkConstInt(
+ Rational(n.getConst<BitVectorRepeat>().d_repeatAmount)));
break;
case BITVECTOR_ZERO_EXTEND:
- indices.push_back(nm->mkConst(
- CONST_RATIONAL,
+ indices.push_back(nm->mkConstInt(
Rational(n.getConst<BitVectorZeroExtend>().d_zeroExtendAmount)));
break;
case BITVECTOR_SIGN_EXTEND:
- indices.push_back(nm->mkConst(
- CONST_RATIONAL,
+ indices.push_back(nm->mkConstInt(
Rational(n.getConst<BitVectorSignExtend>().d_signExtendAmount)));
break;
case BITVECTOR_ROTATE_LEFT:
- indices.push_back(nm->mkConst(
- CONST_RATIONAL,
+ indices.push_back(nm->mkConstInt(
Rational(n.getConst<BitVectorRotateLeft>().d_rotateLeftAmount)));
break;
case BITVECTOR_ROTATE_RIGHT:
- indices.push_back(nm->mkConst(
- CONST_RATIONAL,
+ indices.push_back(nm->mkConstInt(
Rational(n.getConst<BitVectorRotateRight>().d_rotateRightAmount)));
break;
case INT_TO_BITVECTOR:
- indices.push_back(nm->mkConst(
- CONST_RATIONAL, Rational(n.getConst<IntToBitVector>().d_size)));
+ indices.push_back(
+ nm->mkConstInt(Rational(n.getConst<IntToBitVector>().d_size)));
break;
case IAND:
- indices.push_back(
- nm->mkConst(CONST_RATIONAL, Rational(n.getConst<IntAnd>().d_size)));
+ indices.push_back(nm->mkConstInt(Rational(n.getConst<IntAnd>().d_size)));
break;
case APPLY_TESTER:
{
@@ -1023,7 +1014,7 @@ Node LfscNodeConverter::getOperatorOfClosure(Node q, bool macroApply)
Node LfscNodeConverter::getOperatorOfBoundVar(Node cop, Node v)
{
NodeManager* nm = NodeManager::currentNM();
- Node x = nm->mkConst(CONST_RATIONAL, Rational(getOrAssignIndexForVar(v)));
+ Node x = nm->mkConstInt(Rational(getOrAssignIndexForVar(v)));
Node tc = typeAsNode(convertType(v.getType()));
return nm->mkNode(APPLY_UF, cop, x, tc);
}
diff --git a/src/proof/lfsc/lfsc_util.cpp b/src/proof/lfsc/lfsc_util.cpp
index 06bedb895..aca884ddc 100644
--- a/src/proof/lfsc/lfsc_util.cpp
+++ b/src/proof/lfsc/lfsc_util.cpp
@@ -68,8 +68,8 @@ LfscRule getLfscRule(Node n)
Node mkLfscRuleNode(LfscRule r)
{
- return NodeManager::currentNM()->mkConst(CONST_RATIONAL,
- Rational(static_cast<uint32_t>(r)));
+ return NodeManager::currentNM()->mkConstInt(
+ Rational(static_cast<uint32_t>(r)));
}
bool LfscProofLetifyTraverseCallback::shouldTraverse(const ProofNode* pn)
diff --git a/src/proof/method_id.cpp b/src/proof/method_id.cpp
index 9567590a8..042df92bb 100644
--- a/src/proof/method_id.cpp
+++ b/src/proof/method_id.cpp
@@ -51,8 +51,8 @@ std::ostream& operator<<(std::ostream& out, MethodId id)
Node mkMethodId(MethodId id)
{
- return NodeManager::currentNM()->mkConst(CONST_RATIONAL,
- Rational(static_cast<uint32_t>(id)));
+ return NodeManager::currentNM()->mkConstInt(
+ Rational(static_cast<uint32_t>(id)));
}
bool getMethodId(TNode n, MethodId& i)
diff --git a/src/proof/proof_checker.cpp b/src/proof/proof_checker.cpp
index 5289d77ff..b688a28f3 100644
--- a/src/proof/proof_checker.cpp
+++ b/src/proof/proof_checker.cpp
@@ -74,8 +74,8 @@ Node ProofRuleChecker::mkKindNode(Kind k)
// UNDEFINED_KIND is negative, hence return null to avoid cast
return Node::null();
}
- return NodeManager::currentNM()->mkConst(CONST_RATIONAL,
- Rational(static_cast<uint32_t>(k)));
+ return NodeManager::currentNM()->mkConstInt(
+ Rational(static_cast<uint32_t>(k)));
}
ProofCheckerStatistics::ProofCheckerStatistics()
diff --git a/src/proof/proof_node_manager.cpp b/src/proof/proof_node_manager.cpp
index e0a7f81c0..c832ac3fa 100644
--- a/src/proof/proof_node_manager.cpp
+++ b/src/proof/proof_node_manager.cpp
@@ -28,8 +28,10 @@ using namespace cvc5::kind;
namespace cvc5 {
-ProofNodeManager::ProofNodeManager(theory::Rewriter* rr, ProofChecker* pc)
- : d_rewriter(rr), d_checker(pc)
+ProofNodeManager::ProofNodeManager(const Options& opts,
+ theory::Rewriter* rr,
+ ProofChecker* pc)
+ : d_opts(opts), d_rewriter(rr), d_checker(pc)
{
d_true = NodeManager::currentNM()->mkConst(true);
// we always allocate a proof checker, regardless of the proof checking mode
@@ -329,8 +331,8 @@ Node ProofNodeManager::checkInternal(
// a proof checking mode that does not eagerly check rule applications
if (!expected.isNull())
{
- if (options::proofCheck() == options::ProofCheckMode::LAZY
- || options::proofCheck() == options::ProofCheckMode::NONE)
+ if (d_opts.proof.proofCheck == options::ProofCheckMode::LAZY
+ || d_opts.proof.proofCheck == options::ProofCheckMode::NONE)
{
return expected;
}
@@ -435,7 +437,7 @@ bool ProofNodeManager::updateNodeInternal(
{
Assert(pn != nullptr);
// ---------------- check for cyclic
- if (options::proofCheck() == options::ProofCheckMode::EAGER)
+ if (d_opts.proof.proofCheck == options::ProofCheckMode::EAGER)
{
std::unordered_set<const ProofNode*> visited;
for (const std::shared_ptr<ProofNode>& cpc : children)
diff --git a/src/proof/proof_node_manager.h b/src/proof/proof_node_manager.h
index 533f6d173..5926a5f2e 100644
--- a/src/proof/proof_node_manager.h
+++ b/src/proof/proof_node_manager.h
@@ -27,6 +27,7 @@ namespace cvc5 {
class ProofChecker;
class ProofNode;
+class Options;
namespace theory {
class Rewriter;
@@ -58,7 +59,9 @@ class Rewriter;
class ProofNodeManager
{
public:
- ProofNodeManager(theory::Rewriter* rr, ProofChecker* pc = nullptr);
+ ProofNodeManager(const Options& opts,
+ theory::Rewriter* rr,
+ ProofChecker* pc = nullptr);
~ProofNodeManager() {}
/**
* This constructs a ProofNode with the given arguments. The expected
@@ -188,6 +191,8 @@ class ProofNodeManager
static ProofNode* cancelDoubleSymm(ProofNode* pn);
private:
+ /** Reference to the options */
+ const Options& d_opts;
/** The rewriter */
theory::Rewriter* d_rewriter;
/** The (optional) proof checker */
diff --git a/src/proof/proof_node_to_sexpr.cpp b/src/proof/proof_node_to_sexpr.cpp
index e8871af34..910af3d90 100644
--- a/src/proof/proof_node_to_sexpr.cpp
+++ b/src/proof/proof_node_to_sexpr.cpp
@@ -297,6 +297,12 @@ ProofNodeToSExpr::ArgFormat ProofNodeToSExpr::getArgumentFormat(
}
}
break;
+ case PfRule::ANNOTATION:
+ if (i == 0)
+ {
+ return ArgFormat::INFERENCE_ID;
+ }
+ break;
default: break;
}
return ArgFormat::DEFAULT;
diff --git a/src/proof/proof_rule.cpp b/src/proof/proof_rule.cpp
index c82928dc5..9bd714161 100644
--- a/src/proof/proof_rule.cpp
+++ b/src/proof/proof_rule.cpp
@@ -33,6 +33,7 @@ const char* toString(PfRule id)
case PfRule::MACRO_SR_PRED_INTRO: return "MACRO_SR_PRED_INTRO";
case PfRule::MACRO_SR_PRED_ELIM: return "MACRO_SR_PRED_ELIM";
case PfRule::MACRO_SR_PRED_TRANSFORM: return "MACRO_SR_PRED_TRANSFORM";
+ case PfRule::ANNOTATION: return "ANNOTATION";
case PfRule::REMOVE_TERM_FORMULA_AXIOM: return "REMOVE_TERM_FORMULA_AXIOM";
//================================================= Trusted rules
case PfRule::THEORY_LEMMA: return "THEORY_LEMMA";
diff --git a/src/proof/proof_rule.h b/src/proof/proof_rule.h
index d9e92fa92..eaa92c02c 100644
--- a/src/proof/proof_rule.h
+++ b/src/proof/proof_rule.h
@@ -185,6 +185,14 @@ enum class PfRule : uint32_t
// where F' and G' are the result of each side of the equation above. Here,
// original forms are used in a similar manner to MACRO_SR_PRED_INTRO above.
MACRO_SR_PRED_TRANSFORM,
+ // ======== Annotation
+ // Children: (P1:F)
+ // Arguments: (a1 ... an)
+ // ----------------------------------------
+ // Conclusion: F
+ // The terms a1 ... an can be anything used to annotate the proof node, one
+ // example is where a1 is a theory::InferenceId.
+ ANNOTATION,
//================================================= Processing rules
// ======== Remove Term Formulas Axiom
// Children: none
diff --git a/src/proof/unsat_core.cpp b/src/proof/unsat_core.cpp
index 68e0f9a85..419dda9e2 100644
--- a/src/proof/unsat_core.cpp
+++ b/src/proof/unsat_core.cpp
@@ -52,7 +52,8 @@ UnsatCore::const_iterator UnsatCore::end() const {
void UnsatCore::toStream(std::ostream& out) const {
options::ioutils::Scope scope(out);
options::ioutils::applyDagThresh(out, 0);
- Printer::getPrinter(options::outputLanguage())->toStream(out, *this);
+ auto language = options::ioutils::getOutputLang(out);
+ Printer::getPrinter(language)->toStream(out, *this);
}
std::ostream& operator<<(std::ostream& out, const UnsatCore& core) {
diff --git a/src/prop/minisat/core/Solver.cc b/src/prop/minisat/core/Solver.cc
index 36f31eba9..a82ab5e06 100644
--- a/src/prop/minisat/core/Solver.cc
+++ b/src/prop/minisat/core/Solver.cc
@@ -145,12 +145,14 @@ class ScopedBool
//=================================================================================================
// Constructor/Destructor:
-Solver::Solver(cvc5::prop::TheoryProxy* proxy,
+Solver::Solver(Env& env,
+ cvc5::prop::TheoryProxy* proxy,
cvc5::context::Context* context,
cvc5::context::UserContext* userContext,
ProofNodeManager* pnm,
bool enableIncremental)
- : d_proxy(proxy),
+ : EnvObj(env),
+ d_proxy(proxy),
d_context(context),
assertionLevel(0),
d_pfManager(nullptr),
@@ -454,7 +456,7 @@ bool Solver::addClause_(vec<Lit>& ps, bool removable, ClauseId& id)
// If a literal is false at 0 level (both sat and user level) we also
// ignore it, unless we are tracking the SAT solver's reasoning
if (value(ps[i]) == l_False) {
- if (!options::unsatCores() && !needProof() && level(var(ps[i])) == 0
+ if (!options().smt.unsatCores && !needProof() && level(var(ps[i])) == 0
&& user_level(var(ps[i])) == 0)
{
continue;
@@ -489,7 +491,7 @@ bool Solver::addClause_(vec<Lit>& ps, bool removable, ClauseId& id)
// If all false, we're in conflict
if (ps.size() == falseLiteralsCount) {
- if (options::unsatCores() || needProof())
+ if (options().smt.unsatCores || needProof())
{
// Take care of false units here; otherwise, we need to
// construct the clause below to give to the proof manager
@@ -520,7 +522,7 @@ bool Solver::addClause_(vec<Lit>& ps, bool removable, ClauseId& id)
clauses_persistent.push(cr);
attachClause(cr);
- if (options::unsatCores() || needProof())
+ if (options().smt.unsatCores || needProof())
{
if (ps.size() == falseLiteralsCount)
{
@@ -2043,7 +2045,7 @@ CRef Solver::updateLemmas() {
// If it's an empty lemma, we have a conflict at zero level
if (lemma.size() == 0) {
- Assert(!options::unsatCores() && !needProof());
+ Assert(!options().smt.unsatCores && !needProof());
conflict = CRef_Lazy;
backtrackLevel = 0;
Debug("minisat::lemmas") << "Solver::updateLemmas(): found empty clause" << std::endl;
@@ -2189,8 +2191,8 @@ bool Solver::isProofEnabled() const { return d_pfManager != nullptr; }
bool Solver::needProof() const
{
return isProofEnabled()
- && options::unsatCoresMode() != options::UnsatCoresMode::ASSUMPTIONS
- && options::unsatCoresMode() != options::UnsatCoresMode::PP_ONLY;
+ && options().smt.unsatCoresMode != options::UnsatCoresMode::ASSUMPTIONS
+ && options().smt.unsatCoresMode != options::UnsatCoresMode::PP_ONLY;
}
} // namespace Minisat
diff --git a/src/prop/minisat/core/Solver.h b/src/prop/minisat/core/Solver.h
index d0f5006e1..c5dc807ac 100644
--- a/src/prop/minisat/core/Solver.h
+++ b/src/prop/minisat/core/Solver.h
@@ -35,6 +35,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
#include "prop/minisat/mtl/Vec.h"
#include "prop/minisat/utils/Options.h"
#include "prop/sat_proof_manager.h"
+#include "smt/env_obj.h"
#include "theory/theory.h"
#include "util/resource_manager.h"
@@ -52,7 +53,8 @@ namespace Minisat {
//=================================================================================================
// Solver -- the main class:
-class Solver {
+class Solver : protected EnvObj
+{
/** The only two cvc5 entry points to the private solver data */
friend class cvc5::prop::PropEngine;
friend class cvc5::prop::TheoryProxy;
@@ -128,7 +130,8 @@ public:
// Constructor/Destructor:
//
- Solver(cvc5::prop::TheoryProxy* proxy,
+ Solver(Env& env,
+ cvc5::prop::TheoryProxy* proxy,
cvc5::context::Context* context,
cvc5::context::UserContext* userContext,
ProofNodeManager* pnm,
@@ -549,11 +552,8 @@ public:
// Returns a random integer 0 <= x < size. Seed must never be 0.
static inline int irand(double& seed, int size) {
return (int)(drand(seed) * size); }
-
};
-
-
//=================================================================================================
// Implementation of inline methods:
diff --git a/src/prop/minisat/minisat.cpp b/src/prop/minisat/minisat.cpp
index a681aa4f1..a8da07753 100644
--- a/src/prop/minisat/minisat.cpp
+++ b/src/prop/minisat/minisat.cpp
@@ -121,7 +121,8 @@ void MinisatSatSolver::initialize(context::Context* context,
// Create the solver
d_minisat =
- new Minisat::SimpSolver(theoryProxy,
+ new Minisat::SimpSolver(d_env,
+ theoryProxy,
d_context,
userContext,
pnm,
diff --git a/src/prop/minisat/simp/SimpSolver.cc b/src/prop/minisat/simp/SimpSolver.cc
index 04db5e3cb..32b0b736f 100644
--- a/src/prop/minisat/simp/SimpSolver.cc
+++ b/src/prop/minisat/simp/SimpSolver.cc
@@ -48,25 +48,26 @@ static DoubleOption opt_simp_garbage_frac(_cat, "simp-gc-frac", "The fraction of
//=================================================================================================
// Constructor/Destructor:
-SimpSolver::SimpSolver(cvc5::prop::TheoryProxy* proxy,
+SimpSolver::SimpSolver(Env& env,
+ cvc5::prop::TheoryProxy* proxy,
cvc5::context::Context* context,
cvc5::context::UserContext* userContext,
ProofNodeManager* pnm,
bool enableIncremental)
- : Solver(proxy, context, userContext, pnm, enableIncremental),
+ : Solver(env, proxy, context, userContext, pnm, enableIncremental),
grow(opt_grow),
clause_lim(opt_clause_lim),
subsumption_lim(opt_subsumption_lim),
simp_garbage_frac(opt_simp_garbage_frac),
use_asymm(opt_use_asymm),
// make sure this is not enabled if unsat cores or proofs are on
- use_rcheck(opt_use_rcheck && !options::unsatCores() && !pnm),
- use_elim(options::minisatUseElim() && !enableIncremental),
+ use_rcheck(opt_use_rcheck && !options().smt.unsatCores && !pnm),
+ use_elim(options().prop.minisatUseElim && !enableIncremental),
merges(0),
asymm_lits(0),
eliminated_vars(0),
elimorder(1),
- use_simplification(!enableIncremental && !options::unsatCores()
+ use_simplification(!enableIncremental && !options().smt.unsatCores
&& !pnm) // TODO: turn off simplifications if
// proofs are on initially
,
@@ -75,11 +76,12 @@ SimpSolver::SimpSolver(cvc5::prop::TheoryProxy* proxy,
bwdsub_assigns(0),
n_touched(0)
{
- if(options::minisatUseElim() &&
- Options::current().prop.minisatUseElimWasSetByUser &&
- enableIncremental) {
- WarningOnce() << "Incremental mode incompatible with --minisat-elim" << std::endl;
- }
+ if (options().prop.minisatUseElim && options().prop.minisatUseElimWasSetByUser
+ && enableIncremental)
+ {
+ WarningOnce() << "Incremental mode incompatible with --minisat-elim"
+ << std::endl;
+ }
vec<Lit> dummy(1,lit_Undef);
ca.extra_clause_field = true; // NOTE: must happen before allocating the dummy clause below.
@@ -124,10 +126,11 @@ Var SimpSolver::newVar(bool sign, bool dvar, bool isTheoryAtom, bool preRegister
lbool SimpSolver::solve_(bool do_simp, bool turn_off_simp)
{
- if (options::minisatDumpDimacs()) {
- toDimacs();
- return l_Undef;
- }
+ if (options().prop.minisatDumpDimacs)
+ {
+ toDimacs();
+ return l_Undef;
+ }
Assert(decisionLevel() == 0);
vec<Var> extra_frozen;
diff --git a/src/prop/minisat/simp/SimpSolver.h b/src/prop/minisat/simp/SimpSolver.h
index 5e218419c..3d116d500 100644
--- a/src/prop/minisat/simp/SimpSolver.h
+++ b/src/prop/minisat/simp/SimpSolver.h
@@ -42,7 +42,8 @@ class SimpSolver : public Solver {
public:
// Constructor/Destructor:
//
- SimpSolver(cvc5::prop::TheoryProxy* proxy,
+ SimpSolver(Env& env,
+ cvc5::prop::TheoryProxy* proxy,
cvc5::context::Context* context,
cvc5::context::UserContext* userContext,
ProofNodeManager* pnm,
diff --git a/src/prop/proof_cnf_stream.cpp b/src/prop/proof_cnf_stream.cpp
index 61a1a298c..b5542ab35 100644
--- a/src/prop/proof_cnf_stream.cpp
+++ b/src/prop/proof_cnf_stream.cpp
@@ -173,7 +173,7 @@ void ProofCnfStream::convertAndAssertAnd(TNode node, bool negated)
for (unsigned i = 0, size = node.getNumChildren(); i < size; ++i)
{
// Create a proof step for each n_i
- Node iNode = nm->mkConst<Rational>(CONST_RATIONAL, i);
+ Node iNode = nm->mkConstInt(i);
d_proof.addStep(node[i], PfRule::AND_ELIM, {node}, {iNode});
Trace("cnf") << "ProofCnfStream::convertAndAssertAnd: AND_ELIM " << i
<< " added norm " << node[i] << "\n";
@@ -232,7 +232,7 @@ void ProofCnfStream::convertAndAssertOr(TNode node, bool negated)
for (unsigned i = 0, size = node.getNumChildren(); i < size; ++i)
{
// Create a proof step for each (not n_i)
- Node iNode = nm->mkConst<Rational>(CONST_RATIONAL, i);
+ Node iNode = nm->mkConstInt(i);
d_proof.addStep(
node[i].notNode(), PfRule::NOT_OR_ELIM, {node.notNode()}, {iNode});
Trace("cnf") << "ProofCnfStream::convertAndAssertOr: NOT_OR_ELIM " << i
@@ -687,7 +687,7 @@ SatLiteral ProofCnfStream::handleAnd(TNode node)
if (added)
{
Node clauseNode = nm->mkNode(kind::OR, node.notNode(), node[i]);
- Node iNode = nm->mkConst<Rational>(CONST_RATIONAL, i);
+ Node iNode = nm->mkConstInt(i);
d_proof.addStep(clauseNode, PfRule::CNF_AND_POS, {}, {node, iNode});
Trace("cnf") << "ProofCnfStream::handleAnd: CNF_AND_POS " << i
<< " added " << clauseNode << "\n";
@@ -747,7 +747,7 @@ SatLiteral ProofCnfStream::handleOr(TNode node)
if (added)
{
Node clauseNode = nm->mkNode(kind::OR, node, node[i].notNode());
- Node iNode = nm->mkConst<Rational>(CONST_RATIONAL, i);
+ Node iNode = nm->mkConstInt(i);
d_proof.addStep(clauseNode, PfRule::CNF_OR_NEG, {}, {node, iNode});
Trace("cnf") << "ProofCnfStream::handleOr: CNF_OR_NEG " << i << " added "
<< clauseNode << "\n";
diff --git a/src/prop/prop_engine.cpp b/src/prop/prop_engine.cpp
index eeca414e2..df18f9a85 100644
--- a/src/prop/prop_engine.cpp
+++ b/src/prop/prop_engine.cpp
@@ -65,10 +65,10 @@ public:
}
};
-PropEngine::PropEngine(TheoryEngine* te, Env& env)
- : d_inCheckSat(false),
+PropEngine::PropEngine(Env& env, TheoryEngine* te)
+ : EnvObj(env),
+ d_inCheckSat(false),
d_theoryEngine(te),
- d_env(env),
d_skdm(new SkolemDefManager(d_env.getContext(), d_env.getUserContext())),
d_theoryProxy(nullptr),
d_satSolver(nullptr),
@@ -83,7 +83,7 @@ PropEngine::PropEngine(TheoryEngine* te, Env& env)
ProofNodeManager* pnm = d_env.getProofNodeManager();
ResourceManager* rm = d_env.getResourceManager();
- options::DecisionMode dmode = options::decisionMode();
+ options::DecisionMode dmode = options().decision.decisionMode;
if (dmode == options::DecisionMode::JUSTIFICATION
|| dmode == options::DecisionMode::STOPONLY)
{
@@ -105,7 +105,7 @@ PropEngine::PropEngine(TheoryEngine* te, Env& env)
// CNF stream and theory proxy required pointers to each other, make the
// theory proxy first
d_theoryProxy = new TheoryProxy(
- this, d_theoryEngine, d_decisionEngine.get(), d_skdm.get(), d_env);
+ d_env, this, d_theoryEngine, d_decisionEngine.get(), d_skdm.get());
d_cnfStream = new CnfStream(d_satSolver,
d_theoryProxy,
userContext,
@@ -214,7 +214,7 @@ void PropEngine::assertLemma(TrustNode tlemma, theory::LemmaProperty p)
// do final checks on the lemmas we are about to send
if (isProofEnabled()
- && options::proofCheck() == options::ProofCheckMode::EAGER)
+ && options().proof.proofCheck == options::ProofCheckMode::EAGER)
{
Assert(tplemma.getGenerator() != nullptr);
// ensure closed, make the proof node eagerly here to debug
@@ -245,11 +245,8 @@ void PropEngine::assertTrustedLemmaInternal(TrustNode trn, bool removable)
Node node = trn.getNode();
Debug("prop::lemmas") << "assertLemma(" << node << ")" << std::endl;
bool negated = trn.getKind() == TrustNodeKind::CONFLICT;
- Assert(
- !isProofEnabled() || trn.getGenerator() != nullptr
- || options::unsatCores()
- || (options::unsatCores()
- && options::unsatCoresMode() != options::UnsatCoresMode::FULL_PROOF));
+ Assert(!isProofEnabled() || trn.getGenerator() != nullptr
+ || options().smt.unsatCores);
assertInternal(trn.getNode(), negated, removable, false, trn.getGenerator());
}
@@ -257,7 +254,7 @@ void PropEngine::assertInternal(
TNode node, bool negated, bool removable, bool input, ProofGenerator* pg)
{
// Assert as (possibly) removable
- if (options::unsatCoresMode() == options::UnsatCoresMode::ASSUMPTIONS)
+ if (options().smt.unsatCoresMode == options::UnsatCoresMode::ASSUMPTIONS)
{
if (input)
{
@@ -378,7 +375,8 @@ Result PropEngine::checkSat() {
// Note this currently ignores conflicts (a dangerous practice).
d_theoryProxy->presolve();
- if(options::preprocessOnly()) {
+ if (options().base.preprocessOnly)
+ {
return Result(Result::SAT_UNKNOWN, Result::REQUIRES_FULL_CHECK);
}
@@ -673,7 +671,7 @@ bool PropEngine::isProofEnabled() const { return d_pfCnfStream != nullptr; }
void PropEngine::getUnsatCore(std::vector<Node>& core)
{
- Assert(options::unsatCoresMode() == options::UnsatCoresMode::ASSUMPTIONS);
+ Assert(options().smt.unsatCoresMode == options::UnsatCoresMode::ASSUMPTIONS);
std::vector<SatLiteral> unsat_assumptions;
d_satSolver->getUnsatAssumptions(unsat_assumptions);
for (const SatLiteral& lit : unsat_assumptions)
@@ -684,7 +682,7 @@ void PropEngine::getUnsatCore(std::vector<Node>& core)
std::shared_ptr<ProofNode> PropEngine::getRefutation()
{
- Assert(options::unsatCoresMode() == options::UnsatCoresMode::ASSUMPTIONS);
+ Assert(options().smt.unsatCoresMode == options::UnsatCoresMode::ASSUMPTIONS);
std::vector<Node> core;
getUnsatCore(core);
CDProof cdp(d_env.getProofNodeManager());
diff --git a/src/prop/prop_engine.h b/src/prop/prop_engine.h
index 2f569ba72..da6a50b9a 100644
--- a/src/prop/prop_engine.h
+++ b/src/prop/prop_engine.h
@@ -24,6 +24,7 @@
#include "expr/node.h"
#include "proof/trust_node.h"
#include "prop/skolem_def_manager.h"
+#include "smt/env_obj.h"
#include "theory/output_channel.h"
#include "theory/skolem_lemma.h"
#include "util/result.h"
@@ -51,13 +52,13 @@ class TheoryProxy;
* PropEngine is the abstraction of a Sat Solver, providing methods for
* solving the SAT problem and conversion to CNF (via the CnfStream).
*/
-class PropEngine
+class PropEngine : protected EnvObj
{
public:
/**
* Create a PropEngine with a particular decision and theory engine.
*/
- PropEngine(TheoryEngine* te, Env& env);
+ PropEngine(Env& env, TheoryEngine* te);
/**
* Destructor.
@@ -348,9 +349,6 @@ class PropEngine
/** The theory engine we will be using */
TheoryEngine* d_theoryEngine;
- /** Reference to the environment */
- Env& d_env;
-
/** The decision engine we will be using */
std::unique_ptr<decision::DecisionEngine> d_decisionEngine;
diff --git a/src/prop/theory_proxy.cpp b/src/prop/theory_proxy.cpp
index ff00acc51..269921da2 100644
--- a/src/prop/theory_proxy.cpp
+++ b/src/prop/theory_proxy.cpp
@@ -33,20 +33,20 @@
namespace cvc5 {
namespace prop {
-TheoryProxy::TheoryProxy(PropEngine* propEngine,
+TheoryProxy::TheoryProxy(Env& env,
+ PropEngine* propEngine,
TheoryEngine* theoryEngine,
decision::DecisionEngine* decisionEngine,
- SkolemDefManager* skdm,
- Env& env)
- : d_propEngine(propEngine),
+ SkolemDefManager* skdm)
+ : EnvObj(env),
+ d_propEngine(propEngine),
d_cnfStream(nullptr),
d_decisionEngine(decisionEngine),
d_dmNeedsActiveDefs(d_decisionEngine->needsActiveSkolemDefs()),
d_theoryEngine(theoryEngine),
d_queue(env.getContext()),
d_tpp(env, *theoryEngine),
- d_skdm(skdm),
- d_env(env)
+ d_skdm(skdm)
{
}
@@ -120,7 +120,7 @@ void TheoryProxy::explainPropagation(SatLiteral l, SatClause& explanation) {
Node theoryExplanation = tte.getNode();
if (d_env.isSatProofProducing())
{
- Assert(options::unsatCoresMode() != options::UnsatCoresMode::FULL_PROOF
+ Assert(options().smt.unsatCoresMode != options::UnsatCoresMode::FULL_PROOF
|| tte.getGenerator());
d_propEngine->getProofCnfStream()->convertPropagation(tte);
}
diff --git a/src/prop/theory_proxy.h b/src/prop/theory_proxy.h
index d4f8fb3a2..8e998583d 100644
--- a/src/prop/theory_proxy.h
+++ b/src/prop/theory_proxy.h
@@ -25,6 +25,7 @@
#include "proof/trust_node.h"
#include "prop/registrar.h"
#include "prop/sat_solver_types.h"
+#include "smt/env_obj.h"
#include "theory/theory.h"
#include "theory/theory_preprocessor.h"
#include "util/resource_manager.h"
@@ -47,14 +48,14 @@ class SkolemDefManager;
/**
* The proxy class that allows the SatSolver to communicate with the theories
*/
-class TheoryProxy : public Registrar
+class TheoryProxy : protected EnvObj, public Registrar
{
public:
- TheoryProxy(PropEngine* propEngine,
+ TheoryProxy(Env& env,
+ PropEngine* propEngine,
TheoryEngine* theoryEngine,
decision::DecisionEngine* decisionEngine,
- SkolemDefManager* skdm,
- Env& env);
+ SkolemDefManager* skdm);
~TheoryProxy();
@@ -167,9 +168,6 @@ class TheoryProxy : public Registrar
/** The skolem definition manager */
SkolemDefManager* d_skdm;
-
- /** Reference to the environment */
- Env& d_env;
}; /* class TheoryProxy */
} // namespace prop
diff --git a/src/smt/abduction_solver.cpp b/src/smt/abduction_solver.cpp
index ce11c5718..f17e768c9 100644
--- a/src/smt/abduction_solver.cpp
+++ b/src/smt/abduction_solver.cpp
@@ -50,6 +50,7 @@ bool AbductionSolver::getAbduct(const std::vector<Node>& axioms,
std::vector<Node> asserts(axioms.begin(), axioms.end());
// must expand definitions
Node conjn = d_env.getTopLevelSubstitutions().apply(goal);
+ conjn = rewrite(conjn);
// now negate
conjn = conjn.negate();
d_abdConj = conjn;
@@ -93,11 +94,12 @@ bool AbductionSolver::getAbductInternal(const std::vector<Node>& axioms,
Result r = d_subsolver->checkSat();
Trace("sygus-abduct") << " SolverEngine::getAbduct result: " << r
<< std::endl;
- if (r.asSatisfiabilityResult().isSat() == Result::UNSAT)
+ // get the synthesis solution
+ std::map<Node, Node> sols;
+ // use the "getSubsolverSynthSolutions" interface, since we asserted the
+ // internal form of the SyGuS conjecture and used check-sat.
+ if (d_subsolver->getSubsolverSynthSolutions(sols))
{
- // get the synthesis solution
- std::map<Node, Node> sols;
- d_subsolver->getSynthSolutions(sols);
Assert(sols.size() == 1);
std::map<Node, Node>::iterator its = sols.find(d_sssf);
if (its != sols.end())
diff --git a/src/smt/abstract_values.h b/src/smt/abstract_values.h
index 32cff9378..354b8691f 100644
--- a/src/smt/abstract_values.h
+++ b/src/smt/abstract_values.h
@@ -48,7 +48,7 @@ class AbstractValues
/**
* Make a new (or return an existing) abstract value for a node.
- * Can only use this if options::abstractValues() is on.
+ * Can only use this if abstractValues option is on.
*/
Node mkAbstractValue(TNode n);
@@ -63,7 +63,7 @@ class AbstractValues
/**
* A map of AbsractValues to their actual constants. Only used if
- * options::abstractValues() is on.
+ * abstractValues option is on.
*/
theory::SubstitutionMap d_abstractValueMap;
@@ -71,7 +71,7 @@ class AbstractValues
* A mapping of all abstract values (actual value |-> abstract) that
* we've handed out. This is necessary to ensure that we give the
* same AbstractValues for the same real constants. Only used if
- * options::abstractValues() is on.
+ * abstractValues option is on.
*/
NodeToNodeHashMap d_abstractValues;
};
diff --git a/src/smt/check_models.cpp b/src/smt/check_models.cpp
index 7d546eae7..f3393caae 100644
--- a/src/smt/check_models.cpp
+++ b/src/smt/check_models.cpp
@@ -71,7 +71,7 @@ void CheckModels::checkModel(TheoryModel* m,
// evaluate e.g. divide-by-zero. This is intentional since the evaluation
// is not trustworthy, since the UF introduced by expanding definitions may
// not be properly constrained.
- Node n = sm.apply(assertion, false);
+ Node n = sm.apply(assertion);
verbose(1) << "SolverEngine::checkModel(): -- substitutes to " << n
<< std::endl;
diff --git a/src/smt/difficulty_post_processor.cpp b/src/smt/difficulty_post_processor.cpp
index 31797ba5e..6d1882a4e 100644
--- a/src/smt/difficulty_post_processor.cpp
+++ b/src/smt/difficulty_post_processor.cpp
@@ -69,7 +69,7 @@ void DifficultyPostprocessCallback::getDifficultyMap(
NodeManager* nm = NodeManager::currentNM();
for (const std::pair<const Node, uint64_t>& d : d_accMap)
{
- dmap[d.first] = nm->mkConst(CONST_RATIONAL, Rational(d.second));
+ dmap[d.first] = nm->mkConstInt(Rational(d.second));
}
}
diff --git a/src/smt/interpolation_solver.cpp b/src/smt/interpolation_solver.cpp
index 36f8e2a8d..20be53e85 100644
--- a/src/smt/interpolation_solver.cpp
+++ b/src/smt/interpolation_solver.cpp
@@ -51,6 +51,7 @@ bool InterpolationSolver::getInterpol(const std::vector<Node>& axioms,
<< std::endl;
// must expand definitions
Node conjn = d_env.getTopLevelSubstitutions().apply(conj);
+ conjn = rewrite(conjn);
std::string name("__internal_interpol");
quantifiers::SygusInterpol interpolSolver(d_env);
diff --git a/src/smt/model.cpp b/src/smt/model.cpp
index 5c427fa46..69dddded8 100644
--- a/src/smt/model.cpp
+++ b/src/smt/model.cpp
@@ -30,7 +30,8 @@ Model::Model(bool isKnownSat, const std::string& inputName)
std::ostream& operator<<(std::ostream& out, const Model& m) {
options::ioutils::Scope scope(out);
options::ioutils::applyDagThresh(out, 0);
- Printer::getPrinter(options::outputLanguage())->toStream(out, m);
+ auto language = options::ioutils::getOutputLang(out);
+ Printer::getPrinter(language)->toStream(out, m);
return out;
}
diff --git a/src/smt/preprocessor.cpp b/src/smt/preprocessor.cpp
index 41653b6ee..0fdb569c8 100644
--- a/src/smt/preprocessor.cpp
+++ b/src/smt/preprocessor.cpp
@@ -125,8 +125,8 @@ Node Preprocessor::expandDefinitions(const Node& node,
// Ensure node is type-checked at this point.
n.getType(true);
}
- // we apply substitutions here, before expanding definitions
- n = d_env.getTopLevelSubstitutions().apply(n, false);
+ // apply substitutions here (without rewriting), before expanding definitions
+ n = d_env.getTopLevelSubstitutions().apply(n);
// now call expand definitions
n = d_exDefs.expandDefinitions(n, cache);
return n;
diff --git a/src/smt/proof_final_callback.cpp b/src/smt/proof_final_callback.cpp
index 93b4cae19..484f0dd73 100644
--- a/src/smt/proof_final_callback.cpp
+++ b/src/smt/proof_final_callback.cpp
@@ -34,6 +34,9 @@ ProofFinalCallback::ProofFinalCallback(ProofNodeManager* pnm)
d_instRuleIds(
smtStatisticsRegistry().registerHistogram<theory::InferenceId>(
"finalProof::instRuleId")),
+ d_annotationRuleIds(
+ smtStatisticsRegistry().registerHistogram<theory::InferenceId>(
+ "finalProof::annotationRuleId")),
d_totalRuleCount(
smtStatisticsRegistry().registerInt("finalProof::totalRuleCount")),
d_minPedanticLevel(
@@ -96,6 +99,33 @@ bool ProofFinalCallback::shouldUpdate(std::shared_ptr<ProofNode> pn,
}
}
}
+ else if (r == PfRule::ANNOTATION)
+ {
+ // we currently assume the annotation is a single inference id
+ const std::vector<Node>& args = pn->getArguments();
+ if (args.size() > 0)
+ {
+ InferenceId id;
+ if (getInferenceId(args[0], id))
+ {
+ d_annotationRuleIds << id;
+ }
+ }
+ }
+ // print for debugging
+ if (Trace.isOn("final-pf-hole"))
+ {
+ // currently only track theory rewrites
+ if (r == PfRule::THEORY_REWRITE)
+ {
+ const std::vector<Node>& args = pn->getArguments();
+ Node eq = args[0];
+ TheoryId tid = THEORY_BUILTIN;
+ builtin::BuiltinProofRuleChecker::getTheoryId(args[1], tid);
+ Trace("final-pf-hole") << "hole " << r << " " << tid << " : " << eq[0]
+ << " ---> " << eq[1] << std::endl;
+ }
+ }
return false;
}
diff --git a/src/smt/proof_final_callback.h b/src/smt/proof_final_callback.h
index 88b8e20ef..a1e6b1f69 100644
--- a/src/smt/proof_final_callback.h
+++ b/src/smt/proof_final_callback.h
@@ -54,6 +54,11 @@ class ProofFinalCallback : public ProofNodeUpdaterCallback
* marked with the given inference id.
*/
HistogramStat<theory::InferenceId> d_instRuleIds;
+ /**
+ * Counts number of postprocessed proof nodes of rule ANNOTATION that were
+ * marked with the given inference id.
+ */
+ HistogramStat<theory::InferenceId> d_annotationRuleIds;
/** Total number of postprocessed rule applications */
IntStat d_totalRuleCount;
/** The minimum pedantic level of any rule encountered */
diff --git a/src/smt/proof_manager.cpp b/src/smt/proof_manager.cpp
index 4cb9d5bf9..04f601680 100644
--- a/src/smt/proof_manager.cpp
+++ b/src/smt/proof_manager.cpp
@@ -41,7 +41,8 @@ PfManager::PfManager(Env& env)
d_pchecker(new ProofChecker(
options().proof.proofCheck == options::ProofCheckMode::EAGER,
options().proof.proofPedantic)),
- d_pnm(new ProofNodeManager(env.getRewriter(), d_pchecker.get())),
+ d_pnm(new ProofNodeManager(
+ env.getOptions(), env.getRewriter(), d_pchecker.get())),
d_pppg(new PreprocessProofGenerator(
d_pnm.get(), env.getUserContext(), "smt::PreprocessProofGenerator")),
d_pfpp(nullptr),
@@ -150,8 +151,10 @@ void PfManager::setFinalProof(std::shared_ptr<ProofNode> pfn, Assertions& as)
Trace("smt-proof") << "SolverEngine::setFinalProof(): make scope...\n";
// Now make the final scope, which ensures that the only open leaves of the
- // proof are the assertions.
- d_finalProof = d_pnm->mkScope(pfn, assertions);
+ // proof are the assertions. If we are pruning the input, we will try to
+ // minimize the used assertions.
+ d_finalProof =
+ d_pnm->mkScope(pfn, assertions, true, options().proof.proofPruneInput);
Trace("smt-proof") << "SolverEngine::setFinalProof(): finished.\n";
}
@@ -227,20 +230,14 @@ void PfManager::translateDifficultyMap(std::map<Node, Node>& dmap,
std::map<Node, Node> dmapp = dmap;
dmap.clear();
std::vector<Node> ppAsserts;
- std::vector<Node> asserts;
- getAssertions(as, asserts);
for (const std::pair<const Node, Node>& ppa : dmapp)
{
Trace("difficulty") << " preprocess difficulty: " << ppa.second << " for "
<< ppa.first << std::endl;
- // Ensure that only input assertions are marked as having a difficulty.
- // In some cases, a lemma may be marked as having a difficulty
- // internally, e.g. for lemmas that require justification, which we should
- // skip or otherwise we end up with an open proof below.
- if (std::find(asserts.begin(), asserts.end(), ppa.first) != asserts.end())
- {
- ppAsserts.push_back(ppa.first);
- }
+ // The difficulty manager should only report difficulty for preprocessed
+ // assertions, or we will get an open proof below. This is ensured
+ // internally by the difficuly manager.
+ ppAsserts.push_back(ppa.first);
}
// assume a SAT refutation from all input assertions that were marked
// as having a difficulty
diff --git a/src/smt/proof_post_processor.cpp b/src/smt/proof_post_processor.cpp
index a292fec8f..167a82e26 100644
--- a/src/smt/proof_post_processor.cpp
+++ b/src/smt/proof_post_processor.cpp
@@ -422,6 +422,7 @@ Node ProofPostprocessCallback::expandMacros(PfRule id,
// not eliminated
return Node::null();
}
+ Trace("smt-proof-pp-debug") << "Expand macro " << id << std::endl;
// macro elimination
if (id == PfRule::MACRO_SR_EQ_INTRO)
{
@@ -855,7 +856,7 @@ Node ProofPostprocessCallback::expandMacros(PfRule id,
for (size_t j = 0, nchildi = children[i].getNumChildren(); j < nchildi;
j++)
{
- Node nodej = nm->mkConst(CONST_RATIONAL, Rational(j));
+ Node nodej = nm->mkConstInt(Rational(j));
cdp->addStep(
children[i][j], PfRule::AND_ELIM, {children[i]}, {nodej});
}
@@ -1086,8 +1087,10 @@ Node ProofPostprocessCallback::expandMacros(PfRule id,
TNode child = children[i];
TNode scalar = args[i];
bool isPos = scalar.getConst<Rational>() > 0;
- Node scalarCmp = nm->mkNode(
- isPos ? GT : LT, scalar, nm->mkConst(CONST_RATIONAL, Rational(0)));
+ Node scalarCmp =
+ nm->mkNode(isPos ? GT : LT,
+ scalar,
+ nm->mkConstRealOrInt(scalar.getType(), Rational(0)));
// (= scalarCmp true)
Node scalarCmpOrTrue = steps.tryStep(PfRule::EVALUATE, {}, {scalarCmp});
Assert(!scalarCmpOrTrue.isNull());
diff --git a/src/smt/set_defaults.cpp b/src/smt/set_defaults.cpp
index b2fe2b5d6..194290399 100644
--- a/src/smt/set_defaults.cpp
+++ b/src/smt/set_defaults.cpp
@@ -373,7 +373,7 @@ void SetDefaults::setDefaultsPost(const LogicInfo& logic, Options& opts) const
|| opts.smt.produceInterpols != options::ProduceInterpols::NONE
|| opts.smt.modelCoresMode != options::ModelCoresMode::NONE
|| opts.smt.blockModelsMode != options::BlockModelsMode::NONE
- || opts.smt.produceProofs)
+ || opts.smt.produceProofs || isSygus(opts))
&& !opts.smt.produceAssertions)
{
verbose(1) << "SolverEngine: turning on produce-assertions to support "
@@ -807,6 +807,7 @@ void SetDefaults::setDefaultsPost(const LogicInfo& logic, Options& opts) const
if (!opts.arith.nlCad && !opts.arith.nlCadWasSetByUser)
{
opts.arith.nlCad = true;
+ opts.arith.nlCadVarElim = true;
if (!opts.arith.nlExtWasSetByUser)
{
opts.arith.nlExt = options::NlExtMode::LIGHT;
@@ -823,6 +824,7 @@ void SetDefaults::setDefaultsPost(const LogicInfo& logic, Options& opts) const
if (!opts.arith.nlCad && !opts.arith.nlCadWasSetByUser)
{
opts.arith.nlCad = true;
+ opts.arith.nlCadVarElim = true;
if (!opts.arith.nlExtWasSetByUser)
{
opts.arith.nlExt = options::NlExtMode::LIGHT;
@@ -1161,9 +1163,8 @@ bool SetDefaults::incompatibleWithUnsatCores(Options& opts,
bool SetDefaults::safeUnsatCores(const Options& opts) const
{
// whether we want to force safe unsat cores, i.e., if we are in the default
- // ASSUMPTIONS mode or PP_ONLY, since other ones are experimental
- return opts.smt.unsatCoresMode == options::UnsatCoresMode::ASSUMPTIONS
- || opts.smt.unsatCoresMode == options::UnsatCoresMode::PP_ONLY;
+ // ASSUMPTIONS mode, since other ones are experimental
+ return opts.smt.unsatCoresMode == options::UnsatCoresMode::ASSUMPTIONS;
}
bool SetDefaults::incompatibleWithQuantifiers(Options& opts,
diff --git a/src/smt/smt_solver.cpp b/src/smt/smt_solver.cpp
index 4530df774..25c6f5f9f 100644
--- a/src/smt/smt_solver.cpp
+++ b/src/smt/smt_solver.cpp
@@ -71,7 +71,7 @@ void SmtSolver::finishInit()
* are unregistered by the obsolete PropEngine object before registered
* again by the new PropEngine object */
d_propEngine.reset(nullptr);
- d_propEngine.reset(new prop::PropEngine(d_theoryEngine.get(), d_env));
+ d_propEngine.reset(new prop::PropEngine(d_env, d_theoryEngine.get()));
Trace("smt-debug") << "Setting up theory engine..." << std::endl;
d_theoryEngine->setPropEngine(getPropEngine());
@@ -89,7 +89,7 @@ void SmtSolver::resetAssertions()
* statistics are unregistered by the obsolete PropEngine object before
* registered again by the new PropEngine object */
d_propEngine.reset(nullptr);
- d_propEngine.reset(new prop::PropEngine(d_theoryEngine.get(), d_env));
+ d_propEngine.reset(new prop::PropEngine(d_env, d_theoryEngine.get()));
d_theoryEngine->setPropEngine(getPropEngine());
// Notice that we do not reset TheoryEngine, nor does it require calling
// finishInit again. In particular, TheoryEngine::finishInit does not
@@ -158,13 +158,15 @@ Result SmtSolver::checkSatisfiability(Assertions& as,
d_env.verbose(2) << "solving..." << std::endl;
Trace("smt") << "SmtSolver::check(): running check" << endl;
Result result = d_propEngine->checkSat();
+ Trace("smt") << "SmtSolver::check(): result " << result << std::endl;
rm->endCall();
Trace("limit") << "SmtSolver::check(): cumulative millis "
<< rm->getTimeUsage() << ", resources "
<< rm->getResourceUsage() << endl;
- if ((options::solveRealAsInt() || options::solveIntAsBV() > 0)
+ if ((d_env.getOptions().smt.solveRealAsInt
+ || d_env.getOptions().smt.solveIntAsBV > 0)
&& result.asSatisfiabilityResult().isSat() == Result::UNSAT)
{
result = Result(Result::SAT_UNKNOWN, Result::UNKNOWN_REASON);
diff --git a/src/smt/solver_engine.cpp b/src/smt/solver_engine.cpp
index 2cf4862a9..32838eccf 100644
--- a/src/smt/solver_engine.cpp
+++ b/src/smt/solver_engine.cpp
@@ -1193,6 +1193,8 @@ std::vector<Node> SolverEngine::getAssertionsInternal()
return res;
}
+const Options& SolverEngine::options() const { return d_env->getOptions(); }
+
std::vector<Node> SolverEngine::getExpandedAssertions()
{
std::vector<Node> easserts = getAssertions();
@@ -1270,7 +1272,7 @@ UnsatCore SolverEngine::getUnsatCoreInternal()
Assert(pe != nullptr);
std::shared_ptr<ProofNode> pepf;
- if (options::unsatCoresMode() == options::UnsatCoresMode::ASSUMPTIONS)
+ if (options().smt.unsatCoresMode == options::UnsatCoresMode::ASSUMPTIONS)
{
pepf = pe->getRefutation();
}
@@ -1282,7 +1284,7 @@ UnsatCore SolverEngine::getUnsatCoreInternal()
std::shared_ptr<ProofNode> pfn = d_pfManager->getFinalProof(pepf, *d_asserts);
std::vector<Node> core;
d_ucManager->getUnsatCore(pfn, *d_asserts, core);
- if (options::minimalUnsatCores())
+ if (options().smt.minimalUnsatCores)
{
core = reduceUnsatCore(core);
}
@@ -1291,7 +1293,7 @@ UnsatCore SolverEngine::getUnsatCoreInternal()
std::vector<Node> SolverEngine::reduceUnsatCore(const std::vector<Node>& core)
{
- Assert(options::unsatCores())
+ Assert(options().smt.unsatCores)
<< "cannot reduce unsat core if unsat cores are turned off";
d_env->verbose(1) << "SolverEngine::reduceUnsatCore(): reducing unsat core"
@@ -1386,7 +1388,7 @@ void SolverEngine::checkUnsatCore()
theory::TrustSubstitutionMap& tls = d_env->getTopLevelSubstitutions();
for (UnsatCore::iterator i = core.begin(); i != core.end(); ++i)
{
- Node assertionAfterExpansion = tls.apply(*i, false);
+ Node assertionAfterExpansion = tls.apply(*i);
d_env->verbose(1) << "SolverEngine::checkUnsatCore(): pushing core member "
<< *i << ", expanded to " << assertionAfterExpansion
<< std::endl;
@@ -1432,7 +1434,7 @@ void SolverEngine::checkModel(bool hardFailure)
Assert(m != nullptr);
// check the model with the theory engine for debugging
- if (options::debugCheckModels())
+ if (options().smt.debugCheckModels)
{
TheoryEngine* te = getTheoryEngine();
Assert(te != nullptr);
@@ -1527,8 +1529,8 @@ void SolverEngine::printInstantiations(std::ostream& out)
&& getSmtMode() == SmtMode::UNSAT)
{
// minimize instantiations based on proof manager
- getRelevantInstantiationTermVectors(rinsts,
- options::dumpInstantiationsDebug());
+ getRelevantInstantiationTermVectors(
+ rinsts, options().driver.dumpInstantiationsDebug);
}
else
{
@@ -1601,6 +1603,13 @@ bool SolverEngine::getSynthSolutions(std::map<Node, Node>& solMap)
return d_sygusSolver->getSynthSolutions(solMap);
}
+bool SolverEngine::getSubsolverSynthSolutions(std::map<Node, Node>& solMap)
+{
+ SolverEngineScope smts(this);
+ finishInit();
+ return d_sygusSolver->getSubsolverSynthSolutions(solMap);
+}
+
Node SolverEngine::getQuantifierElimination(Node q, bool doFull, bool strict)
{
SolverEngineScope smts(this);
diff --git a/src/smt/solver_engine.h b/src/smt/solver_engine.h
index d7df78f08..95b31eab2 100644
--- a/src/smt/solver_engine.h
+++ b/src/smt/solver_engine.h
@@ -563,6 +563,16 @@ class CVC5_EXPORT SolverEngine
* is a valid formula.
*/
bool getSynthSolutions(std::map<Node, Node>& solMap);
+ /**
+ * Same as above, but used for getting synthesis solutions from a "subsolver"
+ * that has been initialized to assert the synthesis conjecture as a
+ * normal assertion.
+ *
+ * This method returns true if we are in a state immediately preceded by
+ * a successful call to checkSat, where this SolverEngine has an asserted
+ * synthesis conjecture.
+ */
+ bool getSubsolverSynthSolutions(std::map<Node, Node>& solMap);
/**
* Do quantifier elimination.
@@ -1025,6 +1035,12 @@ class CVC5_EXPORT SolverEngine
* changes.
*/
std::vector<Node> getAssertionsInternal();
+
+ /**
+ * Return a reference to options like for `EnvObj`.
+ */
+ const Options& options() const;
+
/* Members -------------------------------------------------------------- */
/** Solver instance that owns this SolverEngine instance. */
diff --git a/src/smt/sygus_solver.cpp b/src/smt/sygus_solver.cpp
index 4c8d3e5bd..70ad65644 100644
--- a/src/smt/sygus_solver.cpp
+++ b/src/smt/sygus_solver.cpp
@@ -42,7 +42,14 @@ namespace cvc5 {
namespace smt {
SygusSolver::SygusSolver(Env& env, SmtSolver& sms)
- : EnvObj(env), d_smtSolver(sms), d_sygusConjectureStale(userContext(), true)
+ : EnvObj(env),
+ d_smtSolver(sms),
+ d_sygusVars(userContext()),
+ d_sygusConstraints(userContext()),
+ d_sygusAssumps(userContext()),
+ d_sygusFunSymbols(userContext()),
+ d_sygusConjectureStale(userContext(), true),
+ d_subsolverCd(userContext(), nullptr)
{
}
@@ -84,7 +91,7 @@ void SygusSolver::declareSynthFun(Node fn,
}
// sygus conjecture is now stale
- setSygusConjectureStale();
+ d_sygusConjectureStale = true;
}
void SygusSolver::assertSygusConstraint(Node n, bool isAssume)
@@ -101,7 +108,7 @@ void SygusSolver::assertSygusConstraint(Node n, bool isAssume)
}
// sygus conjecture is now stale
- setSygusConjectureStale();
+ d_sygusConjectureStale = true;
}
void SygusSolver::assertSygusInvConstraint(Node inv,
@@ -173,44 +180,50 @@ void SygusSolver::assertSygusInvConstraint(Node inv,
d_sygusConstraints.push_back(constraint);
// sygus conjecture is now stale
- setSygusConjectureStale();
+ d_sygusConjectureStale = true;
}
Result SygusSolver::checkSynth(Assertions& as)
{
- if (options().base.incrementalSolving)
+ Trace("smt") << "SygusSolver::checkSynth" << std::endl;
+ // if applicable, check if the subsolver is the correct one
+ if (usingSygusSubsolver() && d_subsolverCd.get() != d_subsolver.get())
{
- // TODO (project #7)
- throw ModalException(
- "Cannot make check-synth commands when incremental solving is enabled");
+ // this can occur if we backtrack to a place where we were using a different
+ // subsolver than the current one. In this case, we should reconstruct
+ // the subsolver.
+ d_sygusConjectureStale = true;
}
- Trace("smt") << "SygusSolver::checkSynth" << std::endl;
- std::vector<Node> query;
+ // TODO (project #7): we currently must always rebuild the synthesis
+ // conjecture + subsolver, since it answers unsat. When the subsolver is
+ // updated to treat "sat" as solution for synthesis conjecture, this line
+ // will be deleted.
+ d_sygusConjectureStale = true;
if (d_sygusConjectureStale)
{
NodeManager* nm = NodeManager::currentNM();
// build synthesis conjecture from asserted constraints and declared
// variables/functions
Trace("smt") << "Sygus : Constructing sygus constraint...\n";
- Node body = nm->mkAnd(d_sygusConstraints);
+ Node body = nm->mkAnd(listToVector(d_sygusConstraints));
// note that if there are no constraints, then assumptions are irrelevant
if (!d_sygusConstraints.empty() && !d_sygusAssumps.empty())
{
- Node bodyAssump = nm->mkAnd(d_sygusAssumps);
+ Node bodyAssump = nm->mkAnd(listToVector(d_sygusAssumps));
body = nm->mkNode(IMPLIES, bodyAssump, body);
}
body = body.notNode();
Trace("smt") << "...constructed sygus constraint " << body << std::endl;
if (!d_sygusVars.empty())
{
- Node boundVars = nm->mkNode(BOUND_VAR_LIST, d_sygusVars);
+ Node boundVars = nm->mkNode(BOUND_VAR_LIST, listToVector(d_sygusVars));
body = nm->mkNode(EXISTS, boundVars, body);
Trace("smt") << "...constructed exists " << body << std::endl;
}
if (!d_sygusFunSymbols.empty())
{
- body =
- quantifiers::SygusUtils::mkSygusConjecture(d_sygusFunSymbols, body);
+ body = quantifiers::SygusUtils::mkSygusConjecture(
+ listToVector(d_sygusFunSymbols), body);
}
Trace("smt") << "...constructed forall " << body << std::endl;
@@ -218,59 +231,119 @@ Result SygusSolver::checkSynth(Assertions& as)
d_sygusConjectureStale = false;
- // TODO (project #7): if incremental, we should push a context and assert
- query.push_back(body);
- }
+ d_conj = body;
+
+ // if we are using a subsolver, initialize it now
+ if (usingSygusSubsolver())
+ {
+ // we generate a new solver engine to do the SyGuS query
+ initializeSygusSubsolver(d_subsolver, as);
- Result r = d_smtSolver.checkSatisfiability(as, query, false);
+ // store the pointer (context-dependent)
+ d_subsolverCd = d_subsolver.get();
- // Check that synthesis solutions satisfy the conjecture
- if (options().smt.checkSynthSol
- && r.asSatisfiabilityResult().isSat() == Result::UNSAT)
+ // also assert the internal SyGuS conjecture
+ d_subsolver->assertFormula(d_conj);
+ }
+ }
+ else
+ {
+ Assert(d_subsolver != nullptr);
+ }
+ Result r;
+ if (usingSygusSubsolver())
+ {
+ r = d_subsolver->checkSat();
+ }
+ else
+ {
+ std::vector<Node> query;
+ query.push_back(d_conj);
+ r = d_smtSolver.checkSatisfiability(as, query, false);
+ }
+ // The result returned by the above call is typically "unknown", which may
+ // or may not correspond to a state in which we solved the conjecture
+ // successfully. Instead we call getSynthSolutions below. If this returns
+ // true, then we were successful. In this case, we set the result to "unsat",
+ // since the synthesis conjecture was negated when asserted to the subsolver.
+ //
+ // This behavior is done for 2 reasons:
+ // (1) if we do not negate the synthesis conjecture, the subsolver in some
+ // cases cannot answer "sat", e.g. in the presence of recursive function
+ // definitions. Instead the SyGuS language standard itself indicates that
+ // a correct solution for a conjecture is one where the synthesis conjecture
+ // is *T-valid* (in the presence of defined recursive functions). In other
+ // words, a SyGuS query asks to prove that the conjecture is valid when
+ // witnessed by the given solution.
+ // (2) we do not want the solver to explicitly answer "unsat" by giving an
+ // unsatisfiable set of formulas to the underlying PropEngine, or otherwise
+ // we will not be able to ask for further solutions. This is critical for
+ // incremental solving where multiple solutions are returned for the same
+ // set of constraints. Thus, the internal SyGuS solver will mark unknown
+ // with IncompleteId::QUANTIFIERS_SYGUS_SOLVED. Furthermore, this id may be
+ // overwritten by other means of incompleteness, so we cannot rely on this
+ // identifier being the final reason for unknown.
+ //
+ // Thus, we use getSynthSolutions as means of knowing the conjecture was
+ // solved.
+ std::map<Node, Node> sol_map;
+ if (getSynthSolutions(sol_map))
{
- checkSynthSolution(as);
+ // if we have solutions, we return "unsat" by convention
+ r = Result(Result::UNSAT);
+ // Check that synthesis solutions satisfy the conjecture
+ if (options().smt.checkSynthSol)
+ {
+ checkSynthSolution(as, sol_map);
+ }
+ }
+ else
+ {
+ // otherwise, we return "unknown"
+ r = Result(Result::SAT_UNKNOWN, Result::UNKNOWN_REASON);
}
return r;
}
-bool SygusSolver::getSynthSolutions(std::map<Node, Node>& sol_map)
+bool SygusSolver::getSynthSolutions(std::map<Node, Node>& solMap)
{
Trace("smt") << "SygusSolver::getSynthSolutions" << std::endl;
- std::map<Node, std::map<Node, Node>> sol_mapn;
+ if (usingSygusSubsolver())
+ {
+ // use the call to get the synth solutions from the subsolver
+ return d_subsolver->getSubsolverSynthSolutions(solMap);
+ }
+ return getSubsolverSynthSolutions(solMap);
+}
+
+bool SygusSolver::getSubsolverSynthSolutions(std::map<Node, Node>& solMap)
+{
+ Trace("smt") << "SygusSolver::getSubsolverSynthSolutions" << std::endl;
+ std::map<Node, std::map<Node, Node>> solMapn;
// fail if the theory engine does not have synthesis solutions
QuantifiersEngine* qe = d_smtSolver.getQuantifiersEngine();
- if (qe == nullptr || !qe->getSynthSolutions(sol_mapn))
+ if (qe == nullptr || !qe->getSynthSolutions(solMapn))
{
return false;
}
- for (std::pair<const Node, std::map<Node, Node>>& cs : sol_mapn)
+ for (std::pair<const Node, std::map<Node, Node>>& cs : solMapn)
{
for (std::pair<const Node, Node>& s : cs.second)
{
- sol_map[s.first] = s.second;
+ solMap[s.first] = s.second;
}
}
return true;
}
-void SygusSolver::checkSynthSolution(Assertions& as)
+void SygusSolver::checkSynthSolution(Assertions& as,
+ const std::map<Node, Node>& sol_map)
{
- NodeManager* nm = NodeManager::currentNM();
- SkolemManager* sm = nm->getSkolemManager();
if (isVerboseOn(1))
{
verbose(1) << "SyGuS::checkSynthSolution: checking synthesis solution"
<< std::endl;
}
- std::map<Node, std::map<Node, Node>> sol_map;
- // Get solutions and build auxiliary vectors for substituting
- QuantifiersEngine* qe = d_smtSolver.getQuantifiersEngine();
- if (qe == nullptr || !qe->getSynthSolutions(sol_map))
- {
- InternalError()
- << "SygusSolver::checkSynthSolution(): No solution to check!";
- return;
- }
if (sol_map.empty())
{
InternalError() << "SygusSolver::checkSynthSolution(): Got empty solution!";
@@ -279,100 +352,39 @@ void SygusSolver::checkSynthSolution(Assertions& as)
Trace("check-synth-sol") << "Got solution map:\n";
// the set of synthesis conjectures in our assertions
std::unordered_set<Node> conjs;
+ conjs.insert(d_conj);
// For each of the above conjectures, the functions-to-synthesis and their
// solutions. This is used as a substitution below.
- std::map<Node, std::vector<Node>> fvarMap;
- std::map<Node, std::vector<Node>> fsolMap;
- for (const std::pair<const Node, std::map<Node, Node>>& cmap : sol_map)
+ std::vector<Node> fvars;
+ std::vector<Node> fsols;
+ for (const std::pair<const Node, Node>& pair : sol_map)
{
- Trace("check-synth-sol") << "For conjecture " << cmap.first << ":\n";
- conjs.insert(cmap.first);
- std::vector<Node>& fvars = fvarMap[cmap.first];
- std::vector<Node>& fsols = fsolMap[cmap.first];
- for (const std::pair<const Node, Node>& pair : cmap.second)
- {
- Trace("check-synth-sol")
- << " " << pair.first << " --> " << pair.second << "\n";
- fvars.push_back(pair.first);
- fsols.push_back(pair.second);
- }
+ Trace("check-synth-sol")
+ << " " << pair.first << " --> " << pair.second << "\n";
+ fvars.push_back(pair.first);
+ fsols.push_back(pair.second);
}
+
Trace("check-synth-sol") << "Starting new SMT Engine\n";
Trace("check-synth-sol") << "Retrieving assertions\n";
// Build conjecture from original assertions
- const context::CDList<Node>& alist = as.getAssertionList();
- Assert(options().smt.produceAssertions)
- << "Expected produce assertions to be true when checking synthesis "
- "solution";
- // auxiliary assertions
- std::vector<Node> auxAssertions;
- // expand definitions cache
- std::unordered_map<Node, Node> cache;
- for (const Node& assertion : alist)
- {
- if (isVerboseOn(1))
- {
- verbose(1) << "SyGuS::checkSynthSolution: checking assertion "
- << assertion << std::endl;
- }
- Trace("check-synth-sol") << "Retrieving assertion " << assertion << "\n";
- // Apply any define-funs from the problem.
- Node n = d_smtSolver.getPreprocessor()->expandDefinitions(assertion, cache);
- if (isVerboseOn(1))
- {
- verbose(1) << "SyGuS::checkSynthSolution: -- expands to " << n
- << std::endl;
- }
- Trace("check-synth-sol") << "Expanded assertion " << n << "\n";
- if (conjs.find(n) == conjs.end())
- {
- Trace("check-synth-sol") << "It is an auxiliary assertion\n";
- auxAssertions.push_back(n);
- }
- else
- {
- Trace("check-synth-sol") << "It is a synthesis conjecture\n";
- }
- }
// check all conjectures
- for (Node conj : conjs)
+ for (const Node& conj : conjs)
{
// Start new SMT engine to check solutions
std::unique_ptr<SolverEngine> solChecker;
- initializeSubsolver(solChecker, d_env);
+ initializeSygusSubsolver(solChecker, as);
solChecker->getOptions().smt.checkSynthSol = false;
solChecker->getOptions().quantifiers.sygusRecFun = false;
- // get the solution for this conjecture
- std::vector<Node>& fvars = fvarMap[conj];
- std::vector<Node>& fsols = fsolMap[conj];
+ Assert(conj.getKind() == FORALL);
+ Node conjBody = conj[1];
+ // we must expand definitions here, since define-fun may contain the
+ // function-to-synthesize, which needs to be substituted.
+ conjBody = d_smtSolver.getPreprocessor()->expandDefinitions(conjBody);
// Apply solution map to conjecture body
- Node conjBody;
- /* Whether property is quantifier free */
- if (conj[1].getKind() != EXISTS)
- {
- conjBody = conj[1].substitute(
- fvars.begin(), fvars.end(), fsols.begin(), fsols.end());
- }
- else
- {
- conjBody = conj[1][1].substitute(
- fvars.begin(), fvars.end(), fsols.begin(), fsols.end());
-
- /* Skolemize property */
- std::vector<Node> vars, skos;
- for (unsigned j = 0, size = conj[1][0].getNumChildren(); j < size; ++j)
- {
- vars.push_back(conj[1][0][j]);
- std::stringstream ss;
- ss << "sk_" << j;
- skos.push_back(sm->mkDummySkolem(ss.str(), conj[1][0][j].getType()));
- Trace("check-synth-sol") << "\tSkolemizing " << conj[1][0][j] << " to "
- << skos.back() << "\n";
- }
- conjBody = conjBody.substitute(
- vars.begin(), vars.end(), skos.begin(), skos.end());
- }
+ conjBody = conjBody.substitute(
+ fvars.begin(), fvars.end(), fsols.begin(), fsols.end());
if (isVerboseOn(1))
{
@@ -382,17 +394,6 @@ void SygusSolver::checkSynthSolution(Assertions& as)
Trace("check-synth-sol")
<< "Substituted body of assertion to " << conjBody << "\n";
solChecker->assertFormula(conjBody);
- // Assert all auxiliary assertions. This may include recursive function
- // definitions that were added as assertions to the sygus problem.
- for (Node a : auxAssertions)
- {
- // We require rewriting here, e.g. so that define-fun from the original
- // problem are rewritten to true. If this is not the case, then the
- // assertions module of the subsolver will complain about assertions
- // with free variables.
- Node ar = rewrite(a);
- solChecker->assertFormula(ar);
- }
Result r = solChecker->checkSat();
if (isVerboseOn(1))
{
@@ -414,15 +415,47 @@ void SygusSolver::checkSynthSolution(Assertions& as)
}
}
-void SygusSolver::setSygusConjectureStale()
+void SygusSolver::initializeSygusSubsolver(std::unique_ptr<SolverEngine>& se,
+ Assertions& as)
{
- if (d_sygusConjectureStale)
+ initializeSubsolver(se, d_env);
+ // carry the ordinary define-fun definitions
+ const context::CDList<Node>& alistDefs = as.getAssertionListDefinitions();
+ std::unordered_set<Node> processed;
+ for (const Node& def : alistDefs)
{
- // already stale
- return;
+ // only consider define-fun, represented as (= f (lambda ...)).
+ if (def.getKind() == EQUAL)
+ {
+ Assert(def[0].isVar());
+ std::vector<Node> formals;
+ Node dbody = def[1];
+ if (def[1].getKind() == LAMBDA)
+ {
+ formals.insert(formals.end(), def[1][0].begin(), def[1][0].end());
+ dbody = dbody[1];
+ }
+ se->defineFunction(def[0], formals, dbody);
+ processed.insert(def);
+ }
}
- d_sygusConjectureStale = true;
- // TODO (project #7): if incremental, we should pop a context
+ // Also assert auxiliary assertions
+ const context::CDList<Node>& alist = as.getAssertionList();
+ for (size_t i = 0, asize = alist.size(); i < asize; ++i)
+ {
+ Node a = alist[i];
+ // ignore definitions here
+ if (processed.find(a) == processed.end())
+ {
+ se->assertFormula(a);
+ }
+ }
+}
+
+bool SygusSolver::usingSygusSubsolver() const
+{
+ // use SyGuS subsolver if in incremental mode
+ return options().base.incrementalSolving;
}
void SygusSolver::expandDefinitionsSygusDt(TypeNode tn) const
@@ -467,5 +500,15 @@ void SygusSolver::expandDefinitionsSygusDt(TypeNode tn) const
}
}
+std::vector<Node> SygusSolver::listToVector(const NodeList& list)
+{
+ std::vector<Node> vec;
+ for (const Node& n : list)
+ {
+ vec.push_back(n);
+ }
+ return vec;
+}
+
} // namespace smt
} // namespace cvc5
diff --git a/src/smt/sygus_solver.h b/src/smt/sygus_solver.h
index 0c742fbd4..4e7a04364 100644
--- a/src/smt/sygus_solver.h
+++ b/src/smt/sygus_solver.h
@@ -18,6 +18,7 @@
#ifndef CVC5__SMT__SYGUS_SOLVER_H
#define CVC5__SMT__SYGUS_SOLVER_H
+#include "context/cdlist.h"
#include "context/cdo.h"
#include "expr/node.h"
#include "expr/type_node.h"
@@ -27,7 +28,7 @@
namespace cvc5 {
-class OutputManager;
+class SolverEngine;
namespace smt {
@@ -37,13 +38,28 @@ class SmtSolver;
* A solver for sygus queries.
*
* This class is responsible for responding to check-synth commands. It calls
- * check satisfiability using an underlying SmtSolver object.
+ * check satisfiability using a separate SolverEngine "subsolver".
*
- * It also maintains a reference to a preprocessor for implementing
- * checkSynthSolution.
+ * This solver operates in two modes.
+ *
+ * If in incremental mode, then the "main" SolverEngine for SyGuS inputs only
+ * maintains a (user-context) dependent state of SyGuS assertions, as well as
+ * assertions corresponding to (recursive) function definitions. The subsolver
+ * that solves SyGuS conjectures may be called to checkSat multiple times,
+ * however, push/pop (which impact SyGuS constraints) impacts only the main
+ * solver. This means that the conjecture being handled by the subsolver is
+ * reconstructed when the SyGuS conjecture is updated. The key property that
+ * this enables is that the subsolver does *not* get calls to push/pop,
+ * although it may receive multiple check-sat if the sygus functions and
+ * constraints are not updated between check-sat calls.
+ *
+ * If not in incremental mode, then the internal SyGuS conjecture is asserted
+ * to the "main" SolverEngine.
*/
class SygusSolver : protected EnvObj
{
+ using NodeList = context::CDList<Node>;
+
public:
SygusSolver(Env& env, SmtSolver& sms);
~SygusSolver();
@@ -134,6 +150,16 @@ class SygusSolver : protected EnvObj
* is a valid formula.
*/
bool getSynthSolutions(std::map<Node, Node>& sol_map);
+ /**
+ * Same as above, but used for getting synthesis solutions from a "subsolver"
+ * that has been initialized to assert the synthesis conjecture as a
+ * normal assertion.
+ *
+ * This method returns true if we are in a state immediately preceded by
+ * a successful call to checkSat, where this SolverEngine has an asserted
+ * synthesis conjecture.
+ */
+ bool getSubsolverSynthSolutions(std::map<Node, Node>& solMap);
private:
/**
@@ -143,21 +169,13 @@ class SygusSolver : protected EnvObj
* conjecture in which the functions-to-synthesize have been replaced by the
* synthesized solutions, which is a quantifier-free formula, is
* unsatisfiable. If not, then the found solutions are wrong.
- */
- void checkSynthSolution(Assertions& as);
- /**
- * Set sygus conjecture is stale. The sygus conjecture is stale if either:
- * (1) no sygus conjecture has been added as an assertion to this SMT engine,
- * (2) there is a sygus conjecture that has been added as an assertion
- * internally to this SMT engine, and there have been further calls such that
- * the asserted conjecture is no longer up-to-date.
*
- * This method should be called when new sygus constraints are asserted and
- * when functions-to-synthesize are declared. This function pops a user
- * context if we are in incremental mode and the sygus conjecture was
- * previously not stale.
+ * @param as The background assertions, which may include define-fun and
+ * define-fun-rec,
+ * @param sol_map Map from functions-to-synthesize to their solution (of the
+ * same type) for the asserted synthesis conjecture.
*/
- void setSygusConjectureStale();
+ void checkSynthSolution(Assertions& as, const std::map<Node, Node>& solMap);
/**
* Expand definitions in sygus datatype tn, which ensures that all
* sygus constructors that are used to build values of sygus datatype
@@ -170,7 +188,19 @@ class SygusSolver : protected EnvObj
* expansion.
*/
void expandDefinitionsSygusDt(TypeNode tn) const;
- /** The SMT solver, which is used during checkSynth. */
+ /** List to vector helper */
+ static std::vector<Node> listToVector(const NodeList& list);
+ /**
+ * Initialize SyGuS subsolver based on the assertions from the "main" solver.
+ * This is used for check-synth using a subsolver, and for check-synth-sol.
+ * This constructs a subsolver se, and makes calls to add all define-fun
+ * and auxilary assertions.
+ */
+ void initializeSygusSubsolver(std::unique_ptr<SolverEngine>& se,
+ Assertions& as);
+ /** Are we using a subsolver for the SyGuS query? */
+ bool usingSygusSubsolver() const;
+ /** The SMT solver. */
SmtSolver& d_smtSolver;
/**
* sygus variables declared (from "declare-var" and "declare-fun" commands)
@@ -178,17 +208,41 @@ class SygusSolver : protected EnvObj
* The SyGuS semantics for declared variables is that they are implicitly
* universally quantified in the constraints.
*/
- std::vector<Node> d_sygusVars;
+ NodeList d_sygusVars;
/** sygus constraints */
- std::vector<Node> d_sygusConstraints;
+ NodeList d_sygusConstraints;
/** sygus assumptions */
- std::vector<Node> d_sygusAssumps;
+ NodeList d_sygusAssumps;
/** functions-to-synthesize */
- std::vector<Node> d_sygusFunSymbols;
+ NodeList d_sygusFunSymbols;
+ /** The current sygus conjecture */
+ Node d_conj;
/**
* Whether we need to reconstruct the sygus conjecture.
+ *
+ * The sygus conjecture is stale if either:
+ * (1) no sygus conjecture has been added as an assertion to this SMT engine,
+ * (2) there is a sygus conjecture that has been added as an assertion
+ * internally to this SMT engine, and there have been further calls such that
+ * the asserted conjecture is no longer up-to-date.
+ *
+ * This flag should be set to true when new sygus constraints are asserted and
+ * when functions-to-synthesize are declared.
*/
context::CDO<bool> d_sygusConjectureStale;
+ /**
+ * The (context-dependent) pointer to the subsolver we have constructed.
+ * This is used to verify if the current subsolver is current, in case
+ * user-context dependent pop has a occurred. If this pointer does not match
+ * d_subsolver, then d_subsolver must be reconstructed in this context.
+ */
+ context::CDO<SolverEngine*> d_subsolverCd;
+ /**
+ * The subsolver we are using. This is a separate copy of the SolverEngine
+ * which has the asserted synthesis conjecture, i.e. a formula returned by
+ * quantifiers::SygusUtils::mkSygusConjecture.
+ */
+ std::unique_ptr<SolverEngine> d_subsolver;
};
} // namespace smt
diff --git a/src/theory/arith/arith_msum.cpp b/src/theory/arith/arith_msum.cpp
index a8edb0e79..0621c1391 100644
--- a/src/theory/arith/arith_msum.cpp
+++ b/src/theory/arith/arith_msum.cpp
@@ -81,7 +81,8 @@ bool ArithMSum::getMonomialSum(Node n, std::map<Node, Node>& msum)
bool ArithMSum::getMonomialSumLit(Node lit, std::map<Node, Node>& msum)
{
- if (lit.getKind() == GEQ || lit.getKind() == EQUAL)
+ if (lit.getKind() == GEQ
+ || (lit.getKind() == EQUAL && lit[0].getType().isRealOrInt()))
{
if (getMonomialSum(lit[0], msum))
{
@@ -96,6 +97,7 @@ bool ArithMSum::getMonomialSumLit(Node lit, std::map<Node, Node>& msum)
NodeManager* nm = NodeManager::currentNM();
if (getMonomialSum(lit[1], msum2))
{
+ TypeNode tn = lit[0].getType();
for (std::map<Node, Node>::iterator it = msum2.begin();
it != msum2.end();
++it)
@@ -103,20 +105,20 @@ bool ArithMSum::getMonomialSumLit(Node lit, std::map<Node, Node>& msum)
std::map<Node, Node>::iterator it2 = msum.find(it->first);
if (it2 != msum.end())
{
- Node r = nm->mkNode(MINUS,
- it2->second.isNull()
- ? nm->mkConst(CONST_RATIONAL, Rational(1))
- : it2->second,
- it->second.isNull()
- ? nm->mkConst(CONST_RATIONAL, Rational(1))
- : it->second);
- msum[it->first] = Rewriter::rewrite(r);
+ Rational r1 = it2->second.isNull()
+ ? Rational(1)
+ : it2->second.getConst<Rational>();
+ Rational r2 = it->second.isNull()
+ ? Rational(1)
+ : it->second.getConst<Rational>();
+ msum[it->first] = nm->mkConstRealOrInt(tn, r1 - r2);
}
else
{
msum[it->first] = it->second.isNull()
- ? nm->mkConst(CONST_RATIONAL, Rational(-1))
- : negate(it->second);
+ ? nm->mkConstRealOrInt(tn, Rational(-1))
+ : nm->mkConstRealOrInt(
+ tn, -it->second.getConst<Rational>());
}
}
return true;
@@ -127,7 +129,7 @@ bool ArithMSum::getMonomialSumLit(Node lit, std::map<Node, Node>& msum)
return false;
}
-Node ArithMSum::mkNode(const std::map<Node, Node>& msum)
+Node ArithMSum::mkNode(TypeNode tn, const std::map<Node, Node>& msum)
{
NodeManager* nm = NodeManager::currentNM();
std::vector<Node> children;
@@ -146,10 +148,10 @@ Node ArithMSum::mkNode(const std::map<Node, Node>& msum)
}
children.push_back(m);
}
- return children.size() > 1 ? nm->mkNode(PLUS, children)
- : (children.size() == 1
- ? children[0]
- : nm->mkConst(CONST_RATIONAL, Rational(0)));
+ return children.size() > 1
+ ? nm->mkNode(PLUS, children)
+ : (children.size() == 1 ? children[0]
+ : nm->mkConstRealOrInt(tn, Rational(0)));
}
int ArithMSum::isolate(
@@ -159,11 +161,13 @@ int ArithMSum::isolate(
std::map<Node, Node>::const_iterator itv = msum.find(v);
if (itv != msum.end())
{
+ NodeManager* nm = NodeManager::currentNM();
std::vector<Node> children;
Rational r =
itv->second.isNull() ? Rational(1) : itv->second.getConst<Rational>();
if (r.sgn() != 0)
{
+ TypeNode vtn = v.getType();
for (std::map<Node, Node>::const_iterator it = msum.begin();
it != msum.end();
++it)
@@ -182,27 +186,25 @@ int ArithMSum::isolate(
children.push_back(m);
}
}
- val = children.size() > 1
- ? NodeManager::currentNM()->mkNode(PLUS, children)
- : (children.size() == 1 ? children[0]
- : NodeManager::currentNM()->mkConst(
- CONST_RATIONAL, Rational(0)));
+ val =
+ children.size() > 1
+ ? nm->mkNode(PLUS, children)
+ : (children.size() == 1 ? children[0]
+ : nm->mkConstRealOrInt(vtn, Rational(0)));
if (!r.isOne() && !r.isNegativeOne())
{
- if (v.getType().isInteger())
+ if (vtn.isInteger())
{
- veq_c = NodeManager::currentNM()->mkConst(CONST_RATIONAL, r.abs());
+ veq_c = nm->mkConstInt(r.abs());
}
else
{
- val = NodeManager::currentNM()->mkNode(
- MULT,
- val,
- NodeManager::currentNM()->mkConst(CONST_RATIONAL,
- Rational(1) / r.abs()));
+ val = nm->mkNode(MULT, val, nm->mkConstReal(Rational(1) / r.abs()));
}
}
- val = r.sgn() == 1 ? negate(val) : Rewriter::rewrite(val);
+ val = r.sgn() == 1
+ ? nm->mkNode(MULT, nm->mkConstRealOrInt(vtn, Rational(-1)), val)
+ : val;
return (r.sgn() == 1 || k == EQUAL) ? 1 : -1;
}
}
@@ -284,29 +286,13 @@ bool ArithMSum::decompose(Node n, Node v, Node& coeff, Node& rem)
{
coeff = it->second;
msum.erase(v);
- rem = mkNode(msum);
+ rem = mkNode(n.getType(), msum);
return true;
}
}
return false;
}
-Node ArithMSum::negate(Node t)
-{
- Node tt = NodeManager::currentNM()->mkNode(
- MULT, NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(-1)), t);
- tt = Rewriter::rewrite(tt);
- return tt;
-}
-
-Node ArithMSum::offset(Node t, int i)
-{
- Node tt = NodeManager::currentNM()->mkNode(
- PLUS, NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(i)), t);
- tt = Rewriter::rewrite(tt);
- return tt;
-}
-
void ArithMSum::debugPrintMonomialSum(std::map<Node, Node>& msum, const char* c)
{
for (std::map<Node, Node>::iterator it = msum.begin(); it != msum.end(); ++it)
diff --git a/src/theory/arith/arith_msum.h b/src/theory/arith/arith_msum.h
index 87f56e64f..ae57ee1cb 100644
--- a/src/theory/arith/arith_msum.h
+++ b/src/theory/arith/arith_msum.h
@@ -103,8 +103,13 @@ class ArithMSum
*
* Make the Node corresponding to the interpretation of msum, [msum], where:
* [msum] = sum_{( v, c ) \in msum } [c]*[v]
+ *
+ * @param tn The type of the node to return, which is used only if msum is
+ * empty
+ * @param msum The monomial sum
+ * @return The node corresponding to the monomial sum
*/
- static Node mkNode(const std::map<Node, Node>& msum);
+ static Node mkNode(TypeNode tn, const std::map<Node, Node>& msum);
/** make coefficent term
*
@@ -173,12 +178,6 @@ class ArithMSum
*/
static bool decompose(Node n, Node v, Node& coeff, Node& rem);
- /** return the rewritten form of (UMINUS t) */
- static Node negate(Node t);
-
- /** return the rewritten form of (PLUS t (CONST_RATIONAL i)) */
- static Node offset(Node t, int i);
-
/** debug print for a monmoial sum, prints to Trace(c) */
static void debugPrintMonomialSum(std::map<Node, Node>& msum, const char* c);
};
diff --git a/src/theory/arith/arith_rewriter.cpp b/src/theory/arith/arith_rewriter.cpp
index 8408f15bb..af6f23c1f 100644
--- a/src/theory/arith/arith_rewriter.cpp
+++ b/src/theory/arith/arith_rewriter.cpp
@@ -214,7 +214,7 @@ RewriteResponse ArithRewriter::postRewriteTerm(TNode t){
return RewriteResponse(REWRITE_DONE, t);
case kind::TO_REAL:
case kind::CAST_TO_REAL: return RewriteResponse(REWRITE_DONE, t[0]);
- case kind::TO_INTEGER:return rewriteExtIntegerOp(t);
+ case kind::TO_INTEGER: return rewriteExtIntegerOp(t);
case kind::POW:
{
if(t[1].getKind() == kind::CONST_RATIONAL){
@@ -402,11 +402,11 @@ RewriteResponse ArithRewriter::postRewritePow2(TNode t)
RewriteResponse ArithRewriter::postRewriteIAnd(TNode t)
{
Assert(t.getKind() == kind::IAND);
+ size_t bsize = t.getOperator().getConst<IntAnd>().d_size;
NodeManager* nm = NodeManager::currentNM();
// if constant, we eliminate
if (t[0].isConst() && t[1].isConst())
{
- size_t bsize = t.getOperator().getConst<IntAnd>().d_size;
Node iToBvop = nm->mkConst(IntToBitVector(bsize));
Node arg1 = nm->mkNode(kind::INT_TO_BITVECTOR, iToBvop, t[0]);
Node arg2 = nm->mkNode(kind::INT_TO_BITVECTOR, iToBvop, t[1]);
@@ -437,6 +437,11 @@ RewriteResponse ArithRewriter::postRewriteIAnd(TNode t)
// ((_ iand k) 0 y) ---> 0
return RewriteResponse(REWRITE_DONE, t[i]);
}
+ if (t[i].getConst<Rational>().getNumerator() == Integer(2).pow(bsize) - 1)
+ {
+ // ((_ iand k) 111...1 y) ---> y
+ return RewriteResponse(REWRITE_DONE, t[i == 0 ? 1 : 0]);
+ }
}
return RewriteResponse(REWRITE_DONE, t);
}
@@ -511,7 +516,7 @@ RewriteResponse ArithRewriter::postRewriteTranscendental(TNode t) {
msum.erase(pi);
if (!msum.empty())
{
- rem = ArithMSum::mkNode(msum);
+ rem = ArithMSum::mkNode(t[0].getType(), msum);
}
}
}
diff --git a/src/theory/arith/bound_inference.cpp b/src/theory/arith/bound_inference.cpp
index cd688660a..4423cae61 100644
--- a/src/theory/arith/bound_inference.cpp
+++ b/src/theory/arith/bound_inference.cpp
@@ -15,6 +15,7 @@
#include "theory/arith/bound_inference.h"
+#include "smt/env.h"
#include "theory/arith/normal_form.h"
#include "theory/rewriter.h"
@@ -29,6 +30,8 @@ std::ostream& operator<<(std::ostream& os, const Bounds& b) {
<< b.upper_value << (b.upper_strict ? ')' : ']');
}
+BoundInference::BoundInference(Env& env) : EnvObj(env) {}
+
void BoundInference::reset() { d_bounds.clear(); }
Bounds& BoundInference::get_or_add(const Node& lhs)
@@ -53,7 +56,7 @@ Bounds BoundInference::get(const Node& lhs) const
const std::map<Node, Bounds>& BoundInference::get() const { return d_bounds; }
bool BoundInference::add(const Node& n, bool onlyVariables)
{
- Node tmp = Rewriter::rewrite(n);
+ Node tmp = rewrite(n);
if (tmp.getKind() == Kind::CONST_BOOLEAN)
{
return false;
@@ -175,19 +178,19 @@ void BoundInference::update_lower_bound(const Node& origin,
if (!b.lower_strict && !b.upper_strict && b.lower_value == b.upper_value)
{
b.lower_bound = b.upper_bound =
- Rewriter::rewrite(nm->mkNode(Kind::EQUAL, lhs, value));
+ rewrite(nm->mkNode(Kind::EQUAL, lhs, value));
}
else
{
- b.lower_bound = Rewriter::rewrite(
- nm->mkNode(strict ? Kind::GT : Kind::GEQ, lhs, value));
+ b.lower_bound =
+ rewrite(nm->mkNode(strict ? Kind::GT : Kind::GEQ, lhs, value));
}
}
else if (strict && b.lower_value == value)
{
auto* nm = NodeManager::currentNM();
b.lower_strict = strict;
- b.lower_bound = Rewriter::rewrite(nm->mkNode(Kind::GT, lhs, value));
+ b.lower_bound = rewrite(nm->mkNode(Kind::GT, lhs, value));
b.lower_origin = origin;
}
}
@@ -210,19 +213,19 @@ void BoundInference::update_upper_bound(const Node& origin,
if (!b.lower_strict && !b.upper_strict && b.lower_value == b.upper_value)
{
b.lower_bound = b.upper_bound =
- Rewriter::rewrite(nm->mkNode(Kind::EQUAL, lhs, value));
+ rewrite(nm->mkNode(Kind::EQUAL, lhs, value));
}
else
{
- b.upper_bound = Rewriter::rewrite(
- nm->mkNode(strict ? Kind::LT : Kind::LEQ, lhs, value));
+ b.upper_bound =
+ rewrite(nm->mkNode(strict ? Kind::LT : Kind::LEQ, lhs, value));
}
}
else if (strict && b.upper_value == value)
{
auto* nm = NodeManager::currentNM();
b.upper_strict = strict;
- b.upper_bound = Rewriter::rewrite(nm->mkNode(Kind::LT, lhs, value));
+ b.upper_bound = rewrite(nm->mkNode(Kind::LT, lhs, value));
b.upper_origin = origin;
}
}
@@ -238,20 +241,6 @@ std::ostream& operator<<(std::ostream& os, const BoundInference& bi)
return os;
}
-std::map<Node, std::pair<Node,Node>> getBounds(const std::vector<Node>& assertions) {
- BoundInference bi;
- for (const auto& a: assertions) {
- bi.add(a);
- }
- std::map<Node, std::pair<Node,Node>> res;
- for (const auto& b : bi.get())
- {
- res.emplace(b.first,
- std::make_pair(b.second.lower_value, b.second.upper_value));
- }
- return res;
-}
-
} // namespace arith
} // namespace theory
} // namespace cvc5
diff --git a/src/theory/arith/bound_inference.h b/src/theory/arith/bound_inference.h
index e8d7a294f..a3043ee93 100644
--- a/src/theory/arith/bound_inference.h
+++ b/src/theory/arith/bound_inference.h
@@ -21,6 +21,7 @@
#include <vector>
#include "expr/node.h"
+#include "smt/env_obj.h"
namespace cvc5 {
namespace theory {
@@ -53,9 +54,10 @@ namespace arith {
* A utility class that extracts direct bounds on arithmetic terms from theory
* atoms.
*/
- class BoundInference
+ class BoundInference : protected EnvObj
{
public:
+ BoundInference(Env& env);
void reset();
/**
@@ -110,8 +112,6 @@ namespace arith {
/** Print the current variable bounds. */
std::ostream& operator<<(std::ostream& os, const BoundInference& bi);
-std::map<Node, std::pair<Node,Node>> getBounds(const std::vector<Node>& assertions);
-
} // namespace arith
} // namespace theory
} // namespace cvc5
diff --git a/src/theory/arith/constraint.cpp b/src/theory/arith/constraint.cpp
index cffacdc39..a9576e0cc 100644
--- a/src/theory/arith/constraint.cpp
+++ b/src/theory/arith/constraint.cpp
@@ -1551,9 +1551,6 @@ TrustNode Constraint::externalExplainForPropagation(TNode lit) const
Node n = safeConstructNary(nb);
if (d_database->isProofEnabled())
{
- // Check that the literal we're explaining via this constraint actually
- // matches the constraint's canonical literal.
- Assert(Rewriter::rewrite(lit) == getLiteral());
std::vector<Node> assumptions;
if (n.getKind() == Kind::AND)
{
diff --git a/src/theory/arith/infer_bounds.cpp b/src/theory/arith/infer_bounds.cpp
index aae9bae62..21f698e45 100644
--- a/src/theory/arith/infer_bounds.cpp
+++ b/src/theory/arith/infer_bounds.cpp
@@ -163,9 +163,7 @@ Node InferBoundsResult::getLiteral() const{
Assert(getValue().infinitesimalSgn() >= 0);
k = boundIsRational() ? kind::GEQ : kind::GT;
}
- Node atom = nm->mkNode(k, getTerm(), qnode);
- Node lit = Rewriter::rewrite(atom);
- return lit;
+ return nm->mkNode(k, getTerm(), qnode);
}
/* If there is a bound, this is a node that explains the bound. */
diff --git a/src/theory/arith/nl/cad/cdcac.cpp b/src/theory/arith/nl/cad/cdcac.cpp
index 2fc77be1b..18ccf7aca 100644
--- a/src/theory/arith/nl/cad/cdcac.cpp
+++ b/src/theory/arith/nl/cad/cdcac.cpp
@@ -105,16 +105,7 @@ std::vector<CACInterval> CDCAC::getUnsatIntervals(std::size_t cur_variable)
{
std::vector<CACInterval> res;
LazardEvaluation le;
- if (options().arith.nlCadLifting
- == options::NlCadLiftingMode::LAZARD)
- {
- for (size_t vid = 0; vid < cur_variable; ++vid)
- {
- const auto& val = d_assignment.get(d_variableOrdering[vid]);
- le.add(d_variableOrdering[vid], val);
- }
- le.addFreeVariable(d_variableOrdering[cur_variable]);
- }
+ prepareRootIsolation(le, cur_variable);
for (const auto& c : d_constraints.getConstraints())
{
const poly::Polynomial& p = std::get<0>(c);
@@ -428,11 +419,17 @@ CACInterval CDCAC::intervalFromCharacterization(
m.pushDownPolys(d, d_variableOrdering[cur_variable]);
// Collect -oo, all roots, oo
+
+ LazardEvaluation le;
+ prepareRootIsolation(le, cur_variable);
std::vector<poly::Value> roots;
roots.emplace_back(poly::Value::minus_infty());
for (const auto& p : m)
{
- auto tmp = isolate_real_roots(p, d_assignment);
+ Trace("cdcac") << "Isolating real roots of " << p << " over "
+ << d_assignment << std::endl;
+
+ auto tmp = isolateRealRoots(le, p);
roots.insert(roots.end(), tmp.begin(), tmp.end());
}
roots.emplace_back(poly::Value::plus_infty());
@@ -464,6 +461,8 @@ CACInterval CDCAC::intervalFromCharacterization(
d_assignment.set(d_variableOrdering[cur_variable], lower);
for (const auto& p : m)
{
+ Trace("cdcac") << "Evaluating " << p << " = 0 over " << d_assignment
+ << std::endl;
if (evaluate_constraint(p, d_assignment, poly::SignCondition::EQ))
{
l.add(p, true);
@@ -477,6 +476,8 @@ CACInterval CDCAC::intervalFromCharacterization(
d_assignment.set(d_variableOrdering[cur_variable], upper);
for (const auto& p : m)
{
+ Trace("cdcac") << "Evaluating " << p << " = 0 over " << d_assignment
+ << std::endl;
if (evaluate_constraint(p, d_assignment, poly::SignCondition::EQ))
{
u.add(p, true);
@@ -570,8 +571,10 @@ std::vector<CACInterval> CDCAC::getUnsatCoverImpl(std::size_t curVariable,
d_assignment.unset(d_variableOrdering[curVariable]);
+ Trace("cdcac") << "Building interval..." << std::endl;
auto newInterval =
intervalFromCharacterization(characterization, curVariable, sample);
+ Trace("cdcac") << "New interval: " << newInterval.d_interval << std::endl;
newInterval.d_origins = collectConstraints(cov);
intervals.emplace_back(newInterval);
if (isProofEnabled())
@@ -730,6 +733,30 @@ void CDCAC::pruneRedundantIntervals(std::vector<CACInterval>& intervals)
}
}
+void CDCAC::prepareRootIsolation(LazardEvaluation& le,
+ size_t cur_variable) const
+{
+ if (options().arith.nlCadLifting == options::NlCadLiftingMode::LAZARD)
+ {
+ for (size_t vid = 0; vid < cur_variable; ++vid)
+ {
+ const auto& val = d_assignment.get(d_variableOrdering[vid]);
+ le.add(d_variableOrdering[vid], val);
+ }
+ le.addFreeVariable(d_variableOrdering[cur_variable]);
+ }
+}
+
+std::vector<poly::Value> CDCAC::isolateRealRoots(
+ LazardEvaluation& le, const poly::Polynomial& p) const
+{
+ if (options().arith.nlCadLifting == options::NlCadLiftingMode::LAZARD)
+ {
+ return le.isolateRealRoots(p);
+ }
+ return poly::isolate_real_roots(p, d_assignment);
+}
+
} // namespace cad
} // namespace nl
} // namespace arith
diff --git a/src/theory/arith/nl/cad/cdcac.h b/src/theory/arith/nl/cad/cdcac.h
index 04b5cab24..8317c0813 100644
--- a/src/theory/arith/nl/cad/cdcac.h
+++ b/src/theory/arith/nl/cad/cdcac.h
@@ -29,6 +29,7 @@
#include "smt/env_obj.h"
#include "theory/arith/nl/cad/cdcac_utils.h"
#include "theory/arith/nl/cad/constraints.h"
+#include "theory/arith/nl/cad/lazard_evaluation.h"
#include "theory/arith/nl/cad/proof_generator.h"
#include "theory/arith/nl/cad/variable_ordering.h"
@@ -196,6 +197,20 @@ class CDCAC : protected EnvObj
void pruneRedundantIntervals(std::vector<CACInterval>& intervals);
/**
+ * Prepare the lazard evaluation object with the current assignment, if the
+ * lazard lifting is enabled. Otherwise, this function does nothing.
+ */
+ void prepareRootIsolation(LazardEvaluation& le, size_t cur_variable) const;
+
+ /**
+ * Isolates the real roots of the polynomial `p`. If the lazard lifting is
+ * enabled, this function uses `le.isolateRealRoots()`, otherwise uses the
+ * regular `poly::isolate_real_roots()`.
+ */
+ std::vector<poly::Value> isolateRealRoots(LazardEvaluation& le,
+ const poly::Polynomial& p) const;
+
+ /**
* The current assignment. When the method terminates with SAT, it contains a
* model for the input constraints.
*/
diff --git a/src/theory/arith/nl/cad/lazard_evaluation.cpp b/src/theory/arith/nl/cad/lazard_evaluation.cpp
index aec0d46e3..032565d3d 100644
--- a/src/theory/arith/nl/cad/lazard_evaluation.cpp
+++ b/src/theory/arith/nl/cad/lazard_evaluation.cpp
@@ -821,22 +821,11 @@ std::vector<poly::Polynomial> LazardEvaluation::reducePolynomial(
return {p};
}
-/**
- * Compute the infeasible regions of the given polynomial according to a sign
- * condition. We first reduce the polynomial and isolate the real roots of every
- * resulting polynomial. We store all roots (except for -infty, +infty and none)
- * in a set. Then, we transform the set of roots into a list of infeasible
- * regions by generating intervals between -infty and the first root, in between
- * every two consecutive roots and between the last root and +infty. While doing
- * this, we only keep those intervals that are actually infeasible for the
- * original polynomial q over the partial assignment. Finally, we go over the
- * intervals and aggregate consecutive intervals that connect.
- */
-std::vector<poly::Interval> LazardEvaluation::infeasibleRegions(
- const poly::Polynomial& q, poly::SignCondition sc) const
+std::vector<poly::Value> LazardEvaluation::isolateRealRoots(
+ const poly::Polynomial& q) const
{
poly::Assignment a;
- std::set<poly::Value> roots;
+ std::vector<poly::Value> roots;
// reduce q to a set of reduced polynomials p
for (const auto& p : reducePolynomial(q))
{
@@ -849,9 +838,28 @@ std::vector<poly::Interval> LazardEvaluation::infeasibleRegions(
if (poly::is_minus_infinity(r)) continue;
if (poly::is_none(r)) continue;
if (poly::is_plus_infinity(r)) continue;
- roots.insert(r);
+ roots.emplace_back(r);
}
}
+ std::sort(roots.begin(), roots.end());
+ return roots;
+}
+
+/**
+ * Compute the infeasible regions of the given polynomial according to a sign
+ * condition. We first reduce the polynomial and isolate the real roots of every
+ * resulting polynomial. We store all roots (except for -infty, +infty and none)
+ * in a set. Then, we transform the set of roots into a list of infeasible
+ * regions by generating intervals between -infty and the first root, in between
+ * every two consecutive roots and between the last root and +infty. While doing
+ * this, we only keep those intervals that are actually infeasible for the
+ * original polynomial q over the partial assignment. Finally, we go over the
+ * intervals and aggregate consecutive intervals that connect.
+ */
+std::vector<poly::Interval> LazardEvaluation::infeasibleRegions(
+ const poly::Polynomial& q, poly::SignCondition sc) const
+{
+ std::vector<poly::Value> roots = isolateRealRoots(q);
// generate all intervals
// (-infty,root_0), [root_0], (root_0,root_1), ..., [root_m], (root_m,+infty)
@@ -962,6 +970,16 @@ std::vector<poly::Polynomial> LazardEvaluation::reducePolynomial(
{
return {p};
}
+
+std::vector<poly::Value> LazardEvaluation::isolateRealRoots(
+ const poly::Polynomial& q) const
+{
+ WarningOnce()
+ << "CAD::LazardEvaluation is disabled because CoCoA is not available. "
+ "Falling back to regular real root isolation."
+ << std::endl;
+ return poly::isolate_real_roots(q, d_state->d_assignment);
+}
std::vector<poly::Interval> LazardEvaluation::infeasibleRegions(
const poly::Polynomial& q, poly::SignCondition sc) const
{
diff --git a/src/theory/arith/nl/cad/lazard_evaluation.h b/src/theory/arith/nl/cad/lazard_evaluation.h
index 3bb971c4c..2afccb462 100644
--- a/src/theory/arith/nl/cad/lazard_evaluation.h
+++ b/src/theory/arith/nl/cad/lazard_evaluation.h
@@ -94,6 +94,11 @@ class LazardEvaluation
const poly::Polynomial& q) const;
/**
+ * Isolates the real roots of the given polynomials.
+ */
+ std::vector<poly::Value> isolateRealRoots(const poly::Polynomial& q) const;
+
+ /**
* Compute the infeasible regions of q under the given sign condition.
* Uses reducePolynomial and then performs real root isolation on the
* resulting polynomials to obtain the intervals. Mimics
diff --git a/src/theory/arith/nl/cad_solver.cpp b/src/theory/arith/nl/cad_solver.cpp
index 721308a3d..f4582ac20 100644
--- a/src/theory/arith/nl/cad_solver.cpp
+++ b/src/theory/arith/nl/cad_solver.cpp
@@ -16,12 +16,14 @@
#include "theory/arith/nl/cad_solver.h"
#include "expr/skolem_manager.h"
+#include "options/arith_options.h"
#include "smt/env.h"
#include "theory/arith/inference_manager.h"
#include "theory/arith/nl/cad/cdcac.h"
#include "theory/arith/nl/nl_model.h"
#include "theory/arith/nl/poly_conversion.h"
#include "theory/inference_id.h"
+#include "theory/theory.h"
namespace cvc5 {
namespace theory {
@@ -36,7 +38,8 @@ CadSolver::CadSolver(Env& env, InferenceManager& im, NlModel& model)
#endif
d_foundSatisfiability(false),
d_im(im),
- d_model(model)
+ d_model(model),
+ d_eqsubs(env)
{
NodeManager* nm = NodeManager::currentNM();
SkolemManager* sm = nm->getSkolemManager();
@@ -65,11 +68,41 @@ void CadSolver::initLastCall(const std::vector<Node>& assertions)
Trace("nl-cad") << " " << a << std::endl;
}
}
- // store or process assertions
- d_CAC.reset();
- for (const Node& a : assertions)
+ if (options().arith.nlCadVarElim)
{
- d_CAC.getConstraints().addConstraint(a);
+ d_eqsubs.reset();
+ std::vector<Node> processed = d_eqsubs.eliminateEqualities(assertions);
+ if (d_eqsubs.hasConflict())
+ {
+ Node lem = NodeManager::currentNM()->mkAnd(d_eqsubs.getConflict()).negate();
+ d_im.addPendingLemma(lem, InferenceId::ARITH_NL_CAD_CONFLICT, nullptr);
+ Trace("nl-cad") << "Found conflict: " << lem << std::endl;
+ return;
+ }
+ if (Trace.isOn("nl-cad"))
+ {
+ Trace("nl-cad") << "After simplifications" << std::endl;
+ Trace("nl-cad") << "* Assertions: " << std::endl;
+ for (const Node& a : processed)
+ {
+ Trace("nl-cad") << " " << a << std::endl;
+ }
+ }
+ d_CAC.reset();
+ for (const Node& a : processed)
+ {
+ Assert(!a.isConst());
+ d_CAC.getConstraints().addConstraint(a);
+ }
+ }
+ else
+ {
+ d_CAC.reset();
+ for (const Node& a : assertions)
+ {
+ Assert(!a.isConst());
+ d_CAC.getConstraints().addConstraint(a);
+ }
}
d_CAC.computeVariableOrdering();
d_CAC.retrieveInitialAssignment(d_model, d_ranVariable);
@@ -84,6 +117,7 @@ void CadSolver::checkFull()
{
#ifdef CVC5_POLY_IMP
if (d_CAC.getConstraints().getConstraints().empty()) {
+ d_foundSatisfiability = true;
Trace("nl-cad") << "No constraints. Return." << std::endl;
return;
}
@@ -101,6 +135,8 @@ void CadSolver::checkFull()
Trace("nl-cad") << "Collected MIS: " << mis << std::endl;
Assert(!mis.empty()) << "Infeasible subset can not be empty";
Trace("nl-cad") << "UNSAT with MIS: " << mis << std::endl;
+ d_eqsubs.postprocessConflict(mis);
+ Trace("nl-cad") << "After postprocessing: " << mis << std::endl;
Node lem = NodeManager::currentNM()->mkAnd(mis).negate();
ProofGenerator* proof = d_CAC.closeProof(mis);
d_im.addPendingLemma(lem, InferenceId::ARITH_NL_CAD_CONFLICT, proof);
@@ -170,10 +206,15 @@ bool CadSolver::constructModelIfAvailable(std::vector<Node>& assertions)
return false;
}
bool foundNonVariable = false;
+ for (const auto& sub: d_eqsubs.getSubstitutions())
+ {
+ d_model.addSubstitution(sub.first, sub.second);
+ Trace("nl-cad") << "-> " << sub.first << " = " << sub.second << std::endl;
+ }
for (const auto& v : d_CAC.getVariableOrdering())
{
Node variable = d_CAC.getConstraints().varMapper()(v);
- if (!variable.isVar())
+ if (!Theory::isLeafOf(variable, TheoryId::THEORY_ARITH))
{
Trace("nl-cad") << "Not a variable: " << variable << std::endl;
foundNonVariable = true;
diff --git a/src/theory/arith/nl/cad_solver.h b/src/theory/arith/nl/cad_solver.h
index bedffcaa9..73d09378b 100644
--- a/src/theory/arith/nl/cad_solver.h
+++ b/src/theory/arith/nl/cad_solver.h
@@ -23,6 +23,7 @@
#include "smt/env_obj.h"
#include "theory/arith/nl/cad/cdcac.h"
#include "theory/arith/nl/cad/proof_checker.h"
+#include "theory/arith/nl/equality_substitution.h"
namespace cvc5 {
@@ -104,6 +105,9 @@ class CadSolver: protected EnvObj
InferenceManager& d_im;
/** Reference to the non-linear model object */
NlModel& d_model;
+ /** Utility to eliminate variables from simple equalities before going into
+ * the actual coverings solver */
+ EqualitySubstitution d_eqsubs;
}; /* class CadSolver */
} // namespace nl
diff --git a/src/theory/arith/nl/equality_substitution.cpp b/src/theory/arith/nl/equality_substitution.cpp
new file mode 100644
index 000000000..9b3a79cd4
--- /dev/null
+++ b/src/theory/arith/nl/equality_substitution.cpp
@@ -0,0 +1,183 @@
+/******************************************************************************
+ * Top contributors (to current version):
+ * Gereon Kremer, Andrew Reynolds, Andres Noetzli
+ *
+ * This file is part of the cvc5 project.
+ *
+ * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+ * in the top-level source directory and their institutional affiliations.
+ * All rights reserved. See the file COPYING in the top-level source
+ * directory for licensing information.
+ * ****************************************************************************
+ *
+ * Implementation of new non-linear solver.
+ */
+
+#include "theory/arith/nl/equality_substitution.h"
+
+#include "smt/env.h"
+
+namespace cvc5 {
+namespace theory {
+namespace arith {
+namespace nl {
+
+EqualitySubstitution::EqualitySubstitution(Env& env)
+ : EnvObj(env), d_substitutions(std::make_unique<SubstitutionMap>())
+{
+}
+void EqualitySubstitution::reset()
+{
+ d_substitutions = std::make_unique<SubstitutionMap>();
+ d_conflict.clear();
+ d_conflictMap.clear();
+ d_trackOrigin.clear();
+}
+
+std::vector<Node> EqualitySubstitution::eliminateEqualities(
+ const std::vector<Node>& assertions)
+{
+ Trace("nl-eqs") << "Input:" << std::endl;
+ for (const auto& a : assertions)
+ {
+ Trace("nl-eqs") << "\t" << a << std::endl;
+ }
+ std::set<TNode> tracker;
+ std::vector<Node> asserts = assertions;
+ std::vector<Node> next;
+
+ size_t last_size = 0;
+ while (asserts.size() != last_size)
+ {
+ last_size = asserts.size();
+ // collect all eliminations from original into d_substitutions
+ for (const auto& orig : asserts)
+ {
+ if (orig.getKind() != Kind::EQUAL) continue;
+ tracker.clear();
+ d_substitutions->invalidateCache();
+ Node o = d_substitutions->apply(orig, d_env.getRewriter(), &tracker);
+ Trace("nl-eqs") << "Simplified for subst " << orig << " -> " << o
+ << std::endl;
+ if (o.getKind() != Kind::EQUAL) continue;
+ Assert(o.getNumChildren() == 2);
+ for (size_t i = 0; i < 2; ++i)
+ {
+ const auto& l = o[i];
+ const auto& r = o[1 - i];
+ if (l.isConst()) continue;
+ if (!Theory::isLeafOf(l, TheoryId::THEORY_ARITH)) continue;
+ if (d_substitutions->hasSubstitution(l)) continue;
+ if (expr::hasSubterm(r, l, true)) continue;
+ Trace("nl-eqs") << "Found substitution " << l << " -> " << r
+ << std::endl
+ << " from " << o << " / " << orig << std::endl;
+ d_substitutions->addSubstitution(l, r);
+ d_trackOrigin.emplace(l, o);
+ if (o != orig)
+ {
+ addToConflictMap(o, orig, tracker);
+ }
+ break;
+ }
+ }
+
+ // simplify with subs from original into next
+ next.clear();
+ for (const auto& a : asserts)
+ {
+ tracker.clear();
+ d_substitutions->invalidateCache();
+ Node simp = d_substitutions->apply(a, d_env.getRewriter(), &tracker);
+ if (simp.isConst())
+ {
+ if (simp.getConst<bool>())
+ {
+ continue;
+ }
+ Trace("nl-eqs") << "Simplified " << a << " to " << simp << std::endl;
+ for (TNode t : tracker)
+ {
+ Trace("nl-eqs") << "Tracker has " << t << std::endl;
+ auto toit = d_trackOrigin.find(t);
+ Assert(toit != d_trackOrigin.end());
+ d_conflict.emplace_back(toit->second);
+ }
+ d_conflict.emplace_back(a);
+ postprocessConflict(d_conflict);
+ Trace("nl-eqs") << "Direct conflict: " << d_conflict << std::endl;
+ Trace("nl-eqs") << std::endl
+ << d_conflict.size() << " vs "
+ << std::distance(d_substitutions->begin(),
+ d_substitutions->end())
+ << std::endl
+ << std::endl;
+ return {};
+ }
+ if (simp != a)
+ {
+ Trace("nl-eqs") << "Simplified " << a << " to " << simp << std::endl;
+ addToConflictMap(simp, a, tracker);
+ }
+ next.emplace_back(simp);
+ }
+ asserts = std::move(next);
+ }
+ d_conflict.clear();
+ return asserts;
+}
+void EqualitySubstitution::postprocessConflict(
+ std::vector<Node>& conflict) const
+{
+ Trace("nl-eqs") << "Postprocessing " << conflict << std::endl;
+ std::set<Node> result;
+ for (const auto& c : conflict)
+ {
+ auto it = d_conflictMap.find(c);
+ if (it == d_conflictMap.end())
+ {
+ result.insert(c);
+ }
+ else
+ {
+ Trace("nl-eqs") << "Origin of " << c << ": " << it->second << std::endl;
+ result.insert(it->second.begin(), it->second.end());
+ }
+ }
+ conflict.clear();
+ conflict.insert(conflict.end(), result.begin(), result.end());
+ Trace("nl-eqs") << "-> " << conflict << std::endl;
+}
+void EqualitySubstitution::insertOrigins(std::set<Node>& dest,
+ const Node& n) const
+{
+ auto it = d_conflictMap.find(n);
+ if (it == d_conflictMap.end())
+ {
+ dest.insert(n);
+ }
+ else
+ {
+ dest.insert(it->second.begin(), it->second.end());
+ }
+}
+void EqualitySubstitution::addToConflictMap(const Node& n,
+ const Node& orig,
+ const std::set<TNode>& tracker)
+{
+ std::set<Node> origins;
+ insertOrigins(origins, orig);
+ for (const auto& t : tracker)
+ {
+ auto tit = d_trackOrigin.find(t);
+ Assert(tit != d_trackOrigin.end());
+ insertOrigins(origins, tit->second);
+ }
+ Trace("nl-eqs") << "ConflictMap: " << n << " -> " << origins << std::endl;
+ d_conflictMap.emplace(n, std::vector<Node>(origins.begin(), origins.end()));
+}
+
+} // namespace nl
+} // namespace arith
+} // namespace theory
+} // namespace cvc5
diff --git a/src/theory/arith/nl/equality_substitution.h b/src/theory/arith/nl/equality_substitution.h
new file mode 100644
index 000000000..b095af8df
--- /dev/null
+++ b/src/theory/arith/nl/equality_substitution.h
@@ -0,0 +1,102 @@
+/******************************************************************************
+ * Top contributors (to current version):
+ * Gereon Kremer
+ *
+ * This file is part of the cvc5 project.
+ *
+ * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+ * in the top-level source directory and their institutional affiliations.
+ * All rights reserved. See the file COPYING in the top-level source
+ * directory for licensing information.
+ * ****************************************************************************
+ *
+ * CAD-based solver based on https://arxiv.org/pdf/2003.05633.pdf.
+ */
+
+#ifndef CVC5__THEORY__ARITH__NL__EQUALITY_SUBSTITUTION_H
+#define CVC5__THEORY__ARITH__NL__EQUALITY_SUBSTITUTION_H
+
+#include <vector>
+
+#include "context/context.h"
+#include "expr/node.h"
+#include "expr/node_algorithm.h"
+#include "smt/env_obj.h"
+#include "theory/substitutions.h"
+#include "theory/theory.h"
+
+namespace cvc5 {
+namespace theory {
+namespace arith {
+namespace nl {
+
+/**
+ * This class is a general utility to eliminate variables from a set of
+ * assertions.
+ */
+class EqualitySubstitution : protected EnvObj
+{
+ public:
+ EqualitySubstitution(Env& env);
+ /** Reset this object */
+ void reset();
+
+ /**
+ * Eliminate variables using equalities from the set of assertions.
+ * Returns a set of assertions where some variables may have been eliminated.
+ * Substitutions for the eliminated variables can be obtained from
+ * getSubstitutions().
+ */
+ std::vector<Node> eliminateEqualities(const std::vector<Node>& assertions);
+ /**
+ * Can be called after eliminateEqualities(). Returns the substitutions that
+ * were found and eliminated.
+ */
+ const SubstitutionMap& getSubstitutions() const { return *d_substitutions; }
+ /**
+ * Can be called after eliminateEqualities(). Checks whether a direct conflict
+ * was found, that is an assertion simplified to false during
+ * eliminateEqualities().
+ */
+ bool hasConflict() const { return !d_conflict.empty(); }
+ /**
+ * Return the conflict found in eliminateEqualities() as a set of assertions
+ * that is a subset of the input assertions provided to eliminateEqualities().
+ */
+ const std::vector<Node>& getConflict() const { return d_conflict; }
+ /**
+ * Postprocess a conflict found in the result of eliminateEqualities.
+ * Replaces assertions within the conflict by their origins, i.e. the input
+ * assertions and the assertions that gave rise to the substitutions being
+ * used.
+ */
+ void postprocessConflict(std::vector<Node>& conflict) const;
+
+ private:
+ /** Utility method for addToConflictMap. Checks for n in d_conflictMap */
+ void insertOrigins(std::set<Node>& dest, const Node& n) const;
+ /** Add n -> { orig, *tracker } to the conflict map. The tracked nodes are
+ * first resolved using d_trackOrigin, and everything is run through
+ * insertOrigins to make sure that all origins are input assertions. */
+ void addToConflictMap(const Node& n,
+ const Node& orig,
+ const std::set<TNode>& tracker);
+
+ // The SubstitutionMap
+ std::unique_ptr<SubstitutionMap> d_substitutions;
+ // conflicting assertions, if a conflict was found
+ std::vector<Node> d_conflict;
+ // Maps a simplified assertion to the original assertion + set of original
+ // assertions used for substitutions
+ std::map<Node, std::vector<Node>> d_conflictMap;
+ // Maps substituted terms (what will end up in the tracker) to the equality
+ // from which the substitution was derived.
+ std::map<Node, Node> d_trackOrigin;
+};
+
+} // namespace nl
+} // namespace arith
+} // namespace theory
+} // namespace cvc5
+
+#endif /* CVC5__THEORY__ARITH__NL__EQUALITY_SUBSTITUTION_H */
diff --git a/src/theory/arith/nl/ext/factoring_check.cpp b/src/theory/arith/nl/ext/factoring_check.cpp
index 06d6aeaab..32b630fa8 100644
--- a/src/theory/arith/nl/ext/factoring_check.cpp
+++ b/src/theory/arith/nl/ext/factoring_check.cpp
@@ -35,7 +35,6 @@ namespace nl {
FactoringCheck::FactoringCheck(Env& env, ExtState* data)
: EnvObj(env), d_data(data)
{
- d_zero = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(0));
d_one = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(1));
}
@@ -155,7 +154,8 @@ void FactoringCheck::check(const std::vector<Node>& asserts,
poly.size() == 1 ? poly[0] : nm->mkNode(Kind::PLUS, poly);
Trace("nl-ext-factor")
<< "...factored polynomial : " << polyn << std::endl;
- Node conc_lit = nm->mkNode(atom.getKind(), polyn, d_zero);
+ Node zero = nm->mkConstRealOrInt(polyn.getType(), Rational(0));
+ Node conc_lit = nm->mkNode(atom.getKind(), polyn, zero);
conc_lit = rewrite(conc_lit);
if (!polarity)
{
diff --git a/src/theory/arith/nl/ext/monomial.cpp b/src/theory/arith/nl/ext/monomial.cpp
index 83d0ff71f..47beb6959 100644
--- a/src/theory/arith/nl/ext/monomial.cpp
+++ b/src/theory/arith/nl/ext/monomial.cpp
@@ -326,7 +326,6 @@ Node MonomialDb::mkMonomialRemFactor(Node n,
children.insert(children.end(), inc, v);
}
Node ret = safeConstructNary(MULT, children);
- ret = Rewriter::rewrite(ret);
Trace("nl-ext-mono-factor") << "...return : " << ret << std::endl;
return ret;
}
diff --git a/src/theory/arith/nl/iand_solver.cpp b/src/theory/arith/nl/iand_solver.cpp
index 5d4862307..c661dab4b 100644
--- a/src/theory/arith/nl/iand_solver.cpp
+++ b/src/theory/arith/nl/iand_solver.cpp
@@ -47,9 +47,9 @@ IAndSolver::IAndSolver(Env& env,
NodeManager* nm = NodeManager::currentNM();
d_false = nm->mkConst(false);
d_true = nm->mkConst(true);
- d_zero = nm->mkConst(CONST_RATIONAL, Rational(0));
- d_one = nm->mkConst(CONST_RATIONAL, Rational(1));
- d_two = nm->mkConst(CONST_RATIONAL, Rational(2));
+ d_zero = nm->mkConstInt(Rational(0));
+ d_one = nm->mkConstInt(Rational(1));
+ d_two = nm->mkConstInt(Rational(2));
}
IAndSolver::~IAndSolver() {}
@@ -100,7 +100,7 @@ void IAndSolver::checkInitialRefine()
// conj.push_back(i.eqNode(nm->mkNode(IAND, op, i[1], i[0])));
// 0 <= iand(x,y) < 2^k
conj.push_back(nm->mkNode(LEQ, d_zero, i));
- conj.push_back(nm->mkNode(LT, i, d_iandUtils.twoToK(k)));
+ conj.push_back(nm->mkNode(LT, i, rewrite(d_iandUtils.twoToK(k))));
// iand(x,y)<=x
conj.push_back(nm->mkNode(LEQ, i, i[0]));
// iand(x,y)<=y
@@ -280,8 +280,8 @@ Node IAndSolver::bitwiseLemma(Node i)
// compare each bit to bvI
Node cond;
Node bitIAnd;
- unsigned high_bit;
- for (unsigned j = 0; j < bvsize; j += granularity)
+ uint64_t high_bit;
+ for (uint64_t j = 0; j < bvsize; j += granularity)
{
high_bit = j + granularity - 1;
// don't let high_bit pass bvsize
@@ -296,7 +296,9 @@ Node IAndSolver::bitwiseLemma(Node i)
bitIAnd = d_iandUtils.createBitwiseIAndNode(x, y, high_bit, j);
// enforce bitwise equality
lem = nm->mkNode(
- AND, lem, d_iandUtils.iextract(high_bit, j, i).eqNode(bitIAnd));
+ AND,
+ lem,
+ rewrite(d_iandUtils.iextract(high_bit, j, i)).eqNode(bitIAnd));
}
}
return lem;
diff --git a/src/theory/arith/nl/iand_solver.h b/src/theory/arith/nl/iand_solver.h
index 0b6a1fac6..997112fee 100644
--- a/src/theory/arith/nl/iand_solver.h
+++ b/src/theory/arith/nl/iand_solver.h
@@ -103,7 +103,7 @@ class IAndSolver : protected EnvObj
/**
* convert integer value to bitvector value of bitwidth k,
- * equivalent to Rewriter::rewrite( ((_ intToBv k) n) ).
+ * equivalent to rewrite( ((_ intToBv k) n) ).
*/
Node convertToBvK(unsigned k, Node n) const;
/** make iand */
@@ -115,7 +115,7 @@ class IAndSolver : protected EnvObj
/**
* Value-based refinement lemma for i of the form ((_ iand k) x y). Returns:
* x = M(x) ^ y = M(y) =>
- * ((_ iand k) x y) = Rewriter::rewrite(((_ iand k) M(x) M(y)))
+ * ((_ iand k) x y) = rewrite(((_ iand k) M(x) M(y)))
*/
Node valueBasedLemma(Node i);
/**
diff --git a/src/theory/arith/nl/iand_utils.cpp b/src/theory/arith/nl/iand_utils.cpp
index 50e03bfa5..700eb6de9 100644
--- a/src/theory/arith/nl/iand_utils.cpp
+++ b/src/theory/arith/nl/iand_utils.cpp
@@ -38,7 +38,7 @@ Node pow2(uint64_t k)
{
Assert(k >= 0);
NodeManager* nm = NodeManager::currentNM();
- return nm->mkConst(CONST_RATIONAL, Rational(intpow2(k)));
+ return nm->mkConstInt(Rational(intpow2(k)));
}
bool oneBitAnd(bool a, bool b) { return (a && b); }
@@ -60,9 +60,9 @@ Node intExtract(Node x, uint64_t i, uint64_t size)
IAndUtils::IAndUtils()
{
NodeManager* nm = NodeManager::currentNM();
- d_zero = nm->mkConst(CONST_RATIONAL, Rational(0));
- d_one = nm->mkConst(CONST_RATIONAL, Rational(1));
- d_two = nm->mkConst(CONST_RATIONAL, Rational(2));
+ d_zero = nm->mkConstInt(Rational(0));
+ d_one = nm->mkConstInt(Rational(1));
+ d_two = nm->mkConstInt(Rational(2));
}
Node IAndUtils::createITEFromTable(
@@ -80,8 +80,7 @@ Node IAndUtils::createITEFromTable(
Assert(table.size() == 1 + ((uint64_t)(num_of_values * num_of_values)));
// start with the default, most common value.
// this value is represented in the table by (-1, -1).
- Node ite =
- nm->mkConst(CONST_RATIONAL, Rational(table.at(std::make_pair(-1, -1))));
+ Node ite = nm->mkConstInt(Rational(table.at(std::make_pair(-1, -1))));
for (uint64_t i = 0; i < num_of_values; i++)
{
for (uint64_t j = 0; j < num_of_values; j++)
@@ -94,13 +93,10 @@ Node IAndUtils::createITEFromTable(
// append the current value to the ite.
ite = nm->mkNode(
kind::ITE,
- nm->mkNode(
- kind::AND,
- nm->mkNode(
- kind::EQUAL, x, nm->mkConst(CONST_RATIONAL, Rational(i))),
- nm->mkNode(
- kind::EQUAL, y, nm->mkConst(CONST_RATIONAL, Rational(j)))),
- nm->mkConst(CONST_RATIONAL, Rational(table.at(std::make_pair(i, j)))),
+ nm->mkNode(kind::AND,
+ nm->mkNode(kind::EQUAL, x, nm->mkConstInt(Rational(i))),
+ nm->mkNode(kind::EQUAL, y, nm->mkConstInt(Rational(j)))),
+ nm->mkConstInt(Rational(table.at(std::make_pair(i, j)))),
ite);
}
}
@@ -139,7 +135,7 @@ Node IAndUtils::createSumNode(Node x,
// number of elements in the sum expression
uint64_t sumSize = bvsize / granularity;
// initialize the sum
- Node sumNode = nm->mkConst(CONST_RATIONAL, Rational(0));
+ Node sumNode = nm->mkConstInt(Rational(0));
// compute the table for the current granularity if needed
if (d_bvandTable.find(granularity) == d_bvandTable.end())
{
@@ -186,9 +182,7 @@ Node IAndUtils::iextract(unsigned i, unsigned j, Node n) const
NodeManager* nm = NodeManager::currentNM();
// ((_ extract i j) n) is n / 2^j mod 2^{i-j+1}
Node n2j = nm->mkNode(kind::INTS_DIVISION_TOTAL, n, twoToK(j));
- Node ret = nm->mkNode(kind::INTS_MODULUS_TOTAL, n2j, twoToK(i - j + 1));
- ret = Rewriter::rewrite(ret);
- return ret;
+ return nm->mkNode(kind::INTS_MODULUS_TOTAL, n2j, twoToK(i - j + 1));
}
void IAndUtils::computeAndTable(uint64_t granularity)
@@ -266,19 +260,14 @@ Node IAndUtils::twoToK(unsigned k) const
{
// could be faster
NodeManager* nm = NodeManager::currentNM();
- Node ret =
- nm->mkNode(kind::POW, d_two, nm->mkConst(CONST_RATIONAL, Rational(k)));
- ret = Rewriter::rewrite(ret);
- return ret;
+ return nm->mkNode(kind::POW, d_two, nm->mkConstInt(Rational(k)));
}
Node IAndUtils::twoToKMinusOne(unsigned k) const
{
// could be faster
NodeManager* nm = NodeManager::currentNM();
- Node ret = nm->mkNode(kind::MINUS, twoToK(k), d_one);
- ret = Rewriter::rewrite(ret);
- return ret;
+ return nm->mkNode(kind::MINUS, twoToK(k), d_one);
}
} // namespace nl
diff --git a/src/theory/arith/nl/icp/icp_solver.cpp b/src/theory/arith/nl/icp/icp_solver.cpp
index 92c7d3ddd..aab63325e 100644
--- a/src/theory/arith/nl/icp/icp_solver.cpp
+++ b/src/theory/arith/nl/icp/icp_solver.cpp
@@ -66,7 +66,7 @@ inline std::ostream& operator<<(std::ostream& os, const IAWrapper& iaw)
} // namespace
ICPSolver::ICPSolver(Env& env, InferenceManager& im)
- : EnvObj(env), d_im(im), d_state(d_mapper)
+ : EnvObj(env), d_im(im), d_state(env, d_mapper)
{
}
diff --git a/src/theory/arith/nl/icp/icp_solver.h b/src/theory/arith/nl/icp/icp_solver.h
index 8b0fbf583..b849255cc 100644
--- a/src/theory/arith/nl/icp/icp_solver.h
+++ b/src/theory/arith/nl/icp/icp_solver.h
@@ -86,12 +86,12 @@ class ICPSolver : protected EnvObj
std::vector<Node> d_conflict;
/** Initialized the variable bounds with a variable mapper */
- ICPState(VariableMapper& vm) {}
+ ICPState(Env& env, VariableMapper& vm) : d_bounds(env) {}
/** Reset this state */
void reset()
{
- d_bounds = BoundInference();
+ d_bounds.reset();
d_candidates.clear();
d_assignment.clear();
d_origins = ContractionOriginManager();
diff --git a/src/theory/arith/nl/nl_model.cpp b/src/theory/arith/nl/nl_model.cpp
index d23ddd53d..90138bf3e 100644
--- a/src/theory/arith/nl/nl_model.cpp
+++ b/src/theory/arith/nl/nl_model.cpp
@@ -32,7 +32,7 @@ namespace theory {
namespace arith {
namespace nl {
-NlModel::NlModel() : d_used_approx(false)
+NlModel::NlModel(Env& env) : EnvObj(env), d_used_approx(false)
{
d_true = NodeManager::currentNM()->mkConst(true);
d_false = NodeManager::currentNM()->mkConst(false);
@@ -122,7 +122,7 @@ Node NlModel::computeModelValue(TNode n, bool isConcrete)
children.emplace_back(computeModelValue(n[i], isConcrete));
}
ret = NodeManager::currentNM()->mkNode(n.getKind(), children);
- ret = Rewriter::rewrite(ret);
+ ret = rewrite(ret);
}
}
Trace("nl-ext-mv-debug") << "computed " << (isConcrete ? "M" : "M_A") << "["
@@ -246,7 +246,7 @@ bool NlModel::checkModel(const std::vector<Node>& assertions,
// apply the substitution to a
if (!d_substitutions.empty())
{
- av = Rewriter::rewrite(arithSubstitute(av, d_substitutions));
+ av = rewrite(arithSubstitute(av, d_substitutions));
}
// simple check literal
if (!simpleCheckModelLit(av))
@@ -307,7 +307,7 @@ bool NlModel::addSubstitution(TNode v, TNode s)
Node ms = arithSubstitute(sub, tmp);
if (ms != sub)
{
- sub = Rewriter::rewrite(ms);
+ sub = rewrite(ms);
}
}
d_substitutions.add(v, s);
@@ -376,7 +376,7 @@ bool NlModel::solveEqualitySimple(Node eq,
if (!d_substitutions.empty())
{
seq = arithSubstitute(eq, d_substitutions);
- seq = Rewriter::rewrite(seq);
+ seq = rewrite(seq);
if (seq.isConst())
{
if (seq.getConst<bool>())
@@ -580,7 +580,7 @@ bool NlModel::simpleCheckModelLit(Node lit)
{
lit2 = lit2.negate();
}
- lit2 = Rewriter::rewrite(lit2);
+ lit2 = rewrite(lit2);
bool success = simpleCheckModelLit(lit2);
if (success != pol)
{
@@ -669,7 +669,7 @@ bool NlModel::simpleCheckModelLit(Node lit)
b = it->second;
t = nm->mkNode(PLUS, t, nm->mkNode(MULT, b, v));
}
- t = Rewriter::rewrite(t);
+ t = rewrite(t);
Trace("nl-ext-cms-debug") << "Trying to find min/max for quadratic "
<< t << "..." << std::endl;
Trace("nl-ext-cms-debug") << " a = " << a << std::endl;
@@ -677,7 +677,7 @@ bool NlModel::simpleCheckModelLit(Node lit)
// find maximal/minimal value on the interval
Node apex = nm->mkNode(
DIVISION, nm->mkNode(UMINUS, b), nm->mkNode(MULT, d_two, a));
- apex = Rewriter::rewrite(apex);
+ apex = rewrite(apex);
Assert(apex.isConst());
// for lower, upper, whether we are greater than the apex
bool cmp[2];
@@ -686,7 +686,7 @@ bool NlModel::simpleCheckModelLit(Node lit)
{
boundn[r] = r == 0 ? bit->second.first : bit->second.second;
Node cmpn = nm->mkNode(GT, boundn[r], apex);
- cmpn = Rewriter::rewrite(cmpn);
+ cmpn = rewrite(cmpn);
Assert(cmpn.isConst());
cmp[r] = cmpn.getConst<bool>();
}
@@ -717,12 +717,12 @@ bool NlModel::simpleCheckModelLit(Node lit)
{
qsub.d_subs.back() = boundn[r];
Node ts = arithSubstitute(t, qsub);
- tcmpn[r] = Rewriter::rewrite(ts);
+ tcmpn[r] = rewrite(ts);
}
Node tcmp = nm->mkNode(LT, tcmpn[0], tcmpn[1]);
Trace("nl-ext-cms-debug")
<< " ...both sides of apex, compare " << tcmp << std::endl;
- tcmp = Rewriter::rewrite(tcmp);
+ tcmp = rewrite(tcmp);
Assert(tcmp.isConst());
unsigned bindex_use = (tcmp.getConst<bool>() == pol) ? 1 : 0;
Trace("nl-ext-cms-debug")
@@ -756,7 +756,7 @@ bool NlModel::simpleCheckModelLit(Node lit)
if (!qsub.empty())
{
Node slit = arithSubstitute(lit, qsub);
- slit = Rewriter::rewrite(slit);
+ slit = rewrite(slit);
return simpleCheckModelLit(slit);
}
return false;
@@ -1003,7 +1003,7 @@ bool NlModel::simpleCheckModelMsum(const std::map<Node, Node>& msum, bool pol)
comp = comp.negate();
}
Trace("nl-ext-cms") << " comparison is : " << comp << std::endl;
- comp = Rewriter::rewrite(comp);
+ comp = rewrite(comp);
Assert(comp.isConst());
Trace("nl-ext-cms") << " returned : " << comp << std::endl;
return comp == d_true;
@@ -1073,7 +1073,7 @@ void NlModel::getModelValueRepair(
witness = nm->mkNode(MULT,
nm->mkConst(CONST_RATIONAL, Rational(1, 2)),
nm->mkNode(PLUS, l, u));
- witness = Rewriter::rewrite(witness);
+ witness = rewrite(witness);
Trace("nl-model") << v << " witness is " << witness << std::endl;
}
approximations[v] = std::pair<Node, Node>(pred, witness);
diff --git a/src/theory/arith/nl/nl_model.h b/src/theory/arith/nl/nl_model.h
index 7dcd89a4a..e195aa9b2 100644
--- a/src/theory/arith/nl/nl_model.h
+++ b/src/theory/arith/nl/nl_model.h
@@ -23,6 +23,7 @@
#include "expr/kind.h"
#include "expr/node.h"
#include "expr/subs.h"
+#include "smt/env_obj.h"
namespace cvc5 {
@@ -48,12 +49,12 @@ class NonlinearExtension;
* model in the case it can determine that a model exists. These include
* techniques based on solving (quadratic) equations and bound analysis.
*/
-class NlModel
+class NlModel : protected EnvObj
{
friend class NonlinearExtension;
public:
- NlModel();
+ NlModel(Env& env);
~NlModel();
/**
* This method is called once at the beginning of a last call effort check,
diff --git a/src/theory/arith/nl/nonlinear_extension.cpp b/src/theory/arith/nl/nonlinear_extension.cpp
index e75741096..3f60f8596 100644
--- a/src/theory/arith/nl/nonlinear_extension.cpp
+++ b/src/theory/arith/nl/nonlinear_extension.cpp
@@ -48,7 +48,7 @@ NonlinearExtension::NonlinearExtension(Env& env,
d_checkCounter(0),
d_extTheoryCb(state.getEqualityEngine()),
d_extTheory(env, d_extTheoryCb, d_im),
- d_model(),
+ d_model(env),
d_trSlv(d_env, d_im, d_model),
d_extState(d_im, d_model, d_env),
d_factoringSlv(d_env, &d_extState),
@@ -122,7 +122,7 @@ void NonlinearExtension::getAssertions(std::vector<Node>& assertions)
}
Valuation v = d_containing.getValuation();
- BoundInference bounds;
+ BoundInference bounds(d_env);
std::unordered_set<Node> init_assertions;
@@ -353,45 +353,6 @@ Result::Sat NonlinearExtension::modelBasedRefinement(const std::set<Node>& termS
}
// compute whether shared terms have correct values
- unsigned num_shared_wrong_value = 0;
- std::vector<Node> shared_term_value_splits;
- // must ensure that shared terms are equal to their concrete value
- Trace("nl-ext-mv") << "Shared terms : " << std::endl;
- for (context::CDList<TNode>::const_iterator its =
- d_containing.shared_terms_begin();
- its != d_containing.shared_terms_end();
- ++its)
- {
- TNode shared_term = *its;
- // compute its value in the model, and its evaluation in the model
- Node stv0 = d_model.computeConcreteModelValue(shared_term);
- Node stv1 = d_model.computeAbstractModelValue(shared_term);
- d_model.printModelValue("nl-ext-mv", shared_term);
- if (stv0 != stv1)
- {
- num_shared_wrong_value++;
- Trace("nl-ext-mv") << "Bad shared term value : " << shared_term
- << std::endl;
- if (shared_term != stv0)
- {
- // split on the value, this is non-terminating in general, TODO :
- // improve this
- Node eq = shared_term.eqNode(stv0);
- shared_term_value_splits.push_back(eq);
- }
- else
- {
- // this can happen for transcendental functions
- // the problem is that we cannot evaluate transcendental functions
- // (they don't have a rewriter that returns constants)
- // thus, the actual value in their model can be themselves, hence we
- // have no reference point to rule out the current model. In this
- // case, we may set incomplete below.
- }
- }
- }
- Trace("nl-ext-debug") << " " << num_shared_wrong_value
- << " shared terms with wrong model value." << std::endl;
bool needsRecheck;
do
{
@@ -402,9 +363,9 @@ Result::Sat NonlinearExtension::modelBasedRefinement(const std::set<Node>& termS
int complete_status = 1;
// We require a check either if an assertion is false or a shared term has
// a wrong value
- if (!false_asserts.empty() || num_shared_wrong_value > 0)
+ if (!false_asserts.empty())
{
- complete_status = num_shared_wrong_value > 0 ? -1 : 0;
+ complete_status = 0;
runStrategy(Theory::Effort::EFFORT_FULL, assertions, false_asserts, xts);
if (d_im.hasSentLemma() || d_im.hasPendingLemma())
{
@@ -446,40 +407,6 @@ Result::Sat NonlinearExtension::modelBasedRefinement(const std::set<Node>& termS
<< std::endl;
return Result::Sat::UNSAT;
}
- // resort to splitting on shared terms with their model value
- // if we did not add any lemmas
- if (num_shared_wrong_value > 0)
- {
- complete_status = -1;
- if (!shared_term_value_splits.empty())
- {
- for (const Node& eq : shared_term_value_splits)
- {
- Node req = rewrite(eq);
- Node literal = d_containing.getValuation().ensureLiteral(req);
- d_containing.getOutputChannel().requirePhase(literal, true);
- Trace("nl-ext-debug") << "Split on : " << literal << std::endl;
- Node split = literal.orNode(literal.negate());
- d_im.addPendingLemma(split,
- InferenceId::ARITH_NL_SHARED_TERM_VALUE_SPLIT,
- nullptr,
- true);
- }
- if (d_im.hasWaitingLemma())
- {
- d_im.flushWaitingLemmas();
- Trace("nl-ext") << "...added " << d_im.numPendingLemmas()
- << " shared term value split lemmas." << std::endl;
- return Result::Sat::UNSAT;
- }
- }
- else
- {
- // this can happen if we are trying to do theory combination with
- // trancendental functions
- // since their model value cannot even be computed exactly
- }
- }
// we are incomplete
if (options().arith.nlExt == options::NlExtMode::FULL
diff --git a/src/theory/arith/nl/pow2_solver.cpp b/src/theory/arith/nl/pow2_solver.cpp
index e3a26397e..59bf89151 100644
--- a/src/theory/arith/nl/pow2_solver.cpp
+++ b/src/theory/arith/nl/pow2_solver.cpp
@@ -42,9 +42,9 @@ Pow2Solver::Pow2Solver(Env& env,
NodeManager* nm = NodeManager::currentNM();
d_false = nm->mkConst(false);
d_true = nm->mkConst(true);
- d_zero = nm->mkConst(CONST_RATIONAL, Rational(0));
- d_one = nm->mkConst(CONST_RATIONAL, Rational(1));
- d_two = nm->mkConst(CONST_RATIONAL, Rational(2));
+ d_zero = nm->mkConstInt(Rational(0));
+ d_one = nm->mkConstInt(Rational(1));
+ d_two = nm->mkConstInt(Rational(2));
}
Pow2Solver::~Pow2Solver() {}
@@ -190,8 +190,7 @@ Node Pow2Solver::valueBasedLemma(Node i)
Node valC = nm->mkNode(POW2, valX);
valC = rewrite(valC);
- Node lem = nm->mkNode(IMPLIES, x.eqNode(valX), i.eqNode(valC));
- return lem;
+ return nm->mkNode(IMPLIES, x.eqNode(valX), i.eqNode(valC));
}
} // namespace nl
diff --git a/src/theory/arith/nl/pow2_solver.h b/src/theory/arith/nl/pow2_solver.h
index b4e12616c..42586f206 100644
--- a/src/theory/arith/nl/pow2_solver.h
+++ b/src/theory/arith/nl/pow2_solver.h
@@ -100,7 +100,7 @@ class Pow2Solver : protected EnvObj
/**
* Value-based refinement lemma for i of the form (pow2 x). Returns:
* x = M(x) /\ x>= 0 ---->
- * (pow2 x) = Rewriter::rewrite((pow2 M(x)))
+ * (pow2 x) = rewrite((pow2 M(x)))
*/
Node valueBasedLemma(Node i);
}; /* class Pow2Solver */
diff --git a/src/theory/arith/nl/strategy.cpp b/src/theory/arith/nl/strategy.cpp
index b33e45129..a14841f67 100644
--- a/src/theory/arith/nl/strategy.cpp
+++ b/src/theory/arith/nl/strategy.cpp
@@ -172,10 +172,7 @@ void Strategy::initializeStrategy(const Options& options)
one << InferStep::POW2_FULL << InferStep::BREAK;
if (options.arith.nlCad)
{
- one << InferStep::CAD_INIT;
- }
- if (options.arith.nlCad)
- {
+ one << InferStep::CAD_INIT << InferStep::BREAK;
one << InferStep::CAD_FULL << InferStep::BREAK;
}
diff --git a/src/theory/arith/nl/transcendental/exponential_solver.cpp b/src/theory/arith/nl/transcendental/exponential_solver.cpp
index c4f7f6ca9..77e5f9f3f 100644
--- a/src/theory/arith/nl/transcendental/exponential_solver.cpp
+++ b/src/theory/arith/nl/transcendental/exponential_solver.cpp
@@ -230,7 +230,7 @@ void ExponentialSolver::doTangentLemma(TNode e,
proof->addStep(lem,
PfRule::ARITH_TRANS_EXP_APPROX_BELOW,
{},
- {nm->mkConst(CONST_RATIONAL, Rational(d)), e[0]});
+ {nm->mkConstInt(Rational(d)), e[0]});
}
d_data->d_im.addPendingLemma(
lem, InferenceId::ARITH_NL_T_TANGENT, proof, true);
diff --git a/src/theory/arith/nl/transcendental/proof_checker.cpp b/src/theory/arith/nl/transcendental/proof_checker.cpp
index ca1afb9f6..3bf1ace98 100644
--- a/src/theory/arith/nl/transcendental/proof_checker.cpp
+++ b/src/theory/arith/nl/transcendental/proof_checker.cpp
@@ -18,7 +18,7 @@
#include "expr/sequence.h"
#include "theory/arith/arith_utilities.h"
#include "theory/arith/nl/transcendental/taylor_generator.h"
-#include "theory/rewriter.h"
+#include "theory/evaluator.h"
using namespace cvc5::kind;
@@ -42,18 +42,18 @@ Node mkBounds(TNode t, TNode lb, TNode ub)
/**
* Helper method to construct a secant plane:
- * ((evall - evalu) / (l - u)) * (t - l) + evall
+ * evall + ((evall - evalu) / (l - u)) * (t - l)
*/
Node mkSecant(TNode t, TNode l, TNode u, TNode evall, TNode evalu)
{
NodeManager* nm = NodeManager::currentNM();
return nm->mkNode(Kind::PLUS,
+ evall,
nm->mkNode(Kind::MULT,
nm->mkNode(Kind::DIVISION,
nm->mkNode(Kind::MINUS, evall, evalu),
nm->mkNode(Kind::MINUS, l, u)),
- nm->mkNode(Kind::MINUS, t, l)),
- evall);
+ nm->mkNode(Kind::MINUS, t, l)));
}
} // namespace
@@ -83,11 +83,11 @@ Node TranscendentalProofRuleChecker::checkInternal(
PfRule id, const std::vector<Node>& children, const std::vector<Node>& args)
{
NodeManager* nm = NodeManager::currentNM();
- auto zero = nm->mkConst<Rational>(CONST_RATIONAL, 0);
- auto one = nm->mkConst<Rational>(CONST_RATIONAL, 1);
- auto mone = nm->mkConst<Rational>(CONST_RATIONAL, -1);
- auto pi = nm->mkNullaryOperator(nm->realType(), Kind::PI);
- auto mpi = nm->mkNode(Kind::MULT, mone, pi);
+ Node zero = nm->mkConstReal(Rational(0));
+ Node one = nm->mkConstReal(Rational(1));
+ Node mone = nm->mkConstReal(Rational(-1));
+ Node pi = nm->mkNullaryOperator(nm->realType(), Kind::PI);
+ Node mpi = nm->mkNode(Kind::MULT, mone, pi);
Trace("nl-trans-checker") << "Checking " << id << std::endl;
Trace("nl-trans-checker") << "Children:" << std::endl;
for (const auto& c : children)
@@ -141,11 +141,10 @@ Node TranscendentalProofRuleChecker::checkInternal(
{
Assert(children.empty());
Assert(args.size() == 4);
- Assert(args[0].isConst() && args[0].getKind() == Kind::CONST_RATIONAL
- && args[0].getConst<Rational>().isIntegral());
+ Assert(args[0].isConst() && args[0].getType().isInteger());
Assert(args[1].getType().isReal());
- Assert(args[2].isConst() && args[2].getKind() == Kind::CONST_RATIONAL);
- Assert(args[3].isConst() && args[3].getKind() == Kind::CONST_RATIONAL);
+ Assert(args[2].isConst() && args[2].getType().isRealOrInt());
+ Assert(args[3].isConst() && args[3].getType().isRealOrInt());
std::uint64_t d =
args[0].getConst<Rational>().getNumerator().toUnsignedInt();
Node t = args[1];
@@ -154,26 +153,24 @@ Node TranscendentalProofRuleChecker::checkInternal(
TaylorGenerator tg;
TaylorGenerator::ApproximationBounds bounds;
tg.getPolynomialApproximationBounds(Kind::EXPONENTIAL, d / 2, bounds);
- Node evall = Rewriter::rewrite(
- bounds.d_upperPos.substitute(tg.getTaylorVariable(), l));
- Node evalu = Rewriter::rewrite(
- bounds.d_upperPos.substitute(tg.getTaylorVariable(), u));
+ Evaluator eval(nullptr);
+ Node evall = eval.eval(bounds.d_upperPos, {tg.getTaylorVariable()}, {l});
+ Node evalu = eval.eval(bounds.d_upperPos, {tg.getTaylorVariable()}, {u});
Node evalsecant = mkSecant(t, l, u, evall, evalu);
Node lem = nm->mkNode(
Kind::IMPLIES,
mkBounds(t, l, u),
nm->mkNode(Kind::LEQ, nm->mkNode(Kind::EXPONENTIAL, t), evalsecant));
- return Rewriter::rewrite(lem);
+ return lem;
}
else if (id == PfRule::ARITH_TRANS_EXP_APPROX_ABOVE_NEG)
{
Assert(children.empty());
Assert(args.size() == 4);
- Assert(args[0].isConst() && args[0].getKind() == Kind::CONST_RATIONAL
- && args[0].getConst<Rational>().isIntegral());
+ Assert(args[0].isConst() && args[0].getType().isInteger());
Assert(args[1].getType().isReal());
- Assert(args[2].isConst() && args[2].getKind() == Kind::CONST_RATIONAL);
- Assert(args[3].isConst() && args[3].getKind() == Kind::CONST_RATIONAL);
+ Assert(args[2].isConst() && args[2].getType().isRealOrInt());
+ Assert(args[3].isConst() && args[3].getType().isRealOrInt());
std::uint64_t d =
args[0].getConst<Rational>().getNumerator().toUnsignedInt();
Node t = args[1];
@@ -182,23 +179,21 @@ Node TranscendentalProofRuleChecker::checkInternal(
TaylorGenerator tg;
TaylorGenerator::ApproximationBounds bounds;
tg.getPolynomialApproximationBounds(Kind::EXPONENTIAL, d / 2, bounds);
- Node evall = Rewriter::rewrite(
- bounds.d_upperNeg.substitute(tg.getTaylorVariable(), l));
- Node evalu = Rewriter::rewrite(
- bounds.d_upperNeg.substitute(tg.getTaylorVariable(), u));
+ Evaluator eval(nullptr);
+ Node evall = eval.eval(bounds.d_upperNeg, {tg.getTaylorVariable()}, {l});
+ Node evalu = eval.eval(bounds.d_upperNeg, {tg.getTaylorVariable()}, {u});
Node evalsecant = mkSecant(t, l, u, evall, evalu);
Node lem = nm->mkNode(
Kind::IMPLIES,
mkBounds(t, l, u),
nm->mkNode(Kind::LEQ, nm->mkNode(Kind::EXPONENTIAL, t), evalsecant));
- return Rewriter::rewrite(lem);
+ return lem;
}
else if (id == PfRule::ARITH_TRANS_EXP_APPROX_BELOW)
{
Assert(children.empty());
Assert(args.size() == 2);
- Assert(args[0].isConst() && args[0].getKind() == Kind::CONST_RATIONAL
- && args[0].getConst<Rational>().isIntegral());
+ Assert(args[0].isConst() && args[0].getType().isInteger());
Assert(args[1].getType().isReal());
std::uint64_t d =
args[0].getConst<Rational>().getNumerator().toUnsignedInt();
@@ -206,10 +201,10 @@ Node TranscendentalProofRuleChecker::checkInternal(
TaylorGenerator tg;
TaylorGenerator::ApproximationBounds bounds;
tg.getPolynomialApproximationBounds(Kind::EXPONENTIAL, d, bounds);
- Node eval =
- Rewriter::rewrite(bounds.d_lower.substitute(tg.getTaylorVariable(), t));
+ Evaluator eval(nullptr);
+ Node evalt = eval.eval(bounds.d_lower, {tg.getTaylorVariable()}, {t});
return nm->mkNode(
- Kind::GEQ, std::vector<Node>{nm->mkNode(Kind::EXPONENTIAL, t), eval});
+ Kind::GEQ, std::vector<Node>{nm->mkNode(Kind::EXPONENTIAL, t), evalt});
}
else if (id == PfRule::ARITH_TRANS_SINE_BOUNDS)
{
@@ -240,10 +235,7 @@ Node TranscendentalProofRuleChecker::checkInternal(
x.eqNode(
nm->mkNode(Kind::PLUS,
y,
- nm->mkNode(Kind::MULT,
- nm->mkConst<Rational>(CONST_RATIONAL, 2),
- s,
- pi)))),
+ nm->mkNode(Kind::MULT, nm->mkConstReal(2), s, pi)))),
nm->mkNode(Kind::SINE, y).eqNode(nm->mkNode(Kind::SINE, x))});
}
else if (id == PfRule::ARITH_TRANS_SINE_SYMMETRY)
@@ -252,8 +244,7 @@ Node TranscendentalProofRuleChecker::checkInternal(
Assert(args.size() == 1);
Assert(args[0].getType().isReal());
Node s1 = nm->mkNode(Kind::SINE, args[0]);
- Node s2 = nm->mkNode(
- Kind::SINE, Rewriter::rewrite(nm->mkNode(Kind::MULT, mone, args[0])));
+ Node s2 = nm->mkNode(Kind::SINE, nm->mkNode(Kind::MULT, mone, args[0]));
return nm->mkNode(PLUS, s1, s2).eqNode(zero);
}
else if (id == PfRule::ARITH_TRANS_SINE_TANGENT_ZERO)
@@ -289,13 +280,12 @@ Node TranscendentalProofRuleChecker::checkInternal(
{
Assert(children.empty());
Assert(args.size() == 6);
- Assert(args[0].isConst() && args[0].getKind() == Kind::CONST_RATIONAL
- && args[0].getConst<Rational>().isIntegral());
+ Assert(args[0].isConst() && args[0].getType().isInteger());
Assert(args[1].getType().isReal());
Assert(args[2].getType().isReal());
Assert(args[3].getType().isReal());
- Assert(args[4].isConst() && args[4].getKind() == Kind::CONST_RATIONAL);
- Assert(args[5].isConst() && args[5].getKind() == Kind::CONST_RATIONAL);
+ Assert(args[4].isConst() && args[4].getType().isRealOrInt());
+ Assert(args[5].isConst() && args[5].getType().isRealOrInt());
std::uint64_t d =
args[0].getConst<Rational>().getNumerator().toUnsignedInt();
Node t = args[1];
@@ -306,23 +296,21 @@ Node TranscendentalProofRuleChecker::checkInternal(
TaylorGenerator tg;
TaylorGenerator::ApproximationBounds bounds;
tg.getPolynomialApproximationBounds(Kind::SINE, d / 2, bounds);
- Node evall = Rewriter::rewrite(
- bounds.d_upperNeg.substitute(tg.getTaylorVariable(), l));
- Node evalu = Rewriter::rewrite(
- bounds.d_upperNeg.substitute(tg.getTaylorVariable(), u));
+ Evaluator eval(nullptr);
+ Node evall = eval.eval(bounds.d_upperNeg, {tg.getTaylorVariable()}, {l});
+ Node evalu = eval.eval(bounds.d_upperNeg, {tg.getTaylorVariable()}, {u});
Node lem = nm->mkNode(
Kind::IMPLIES,
mkBounds(t, lb, ub),
nm->mkNode(
Kind::LEQ, nm->mkNode(Kind::SINE, t), mkSecant(t, lb, ub, l, u)));
- return Rewriter::rewrite(lem);
+ return lem;
}
else if (id == PfRule::ARITH_TRANS_SINE_APPROX_ABOVE_POS)
{
Assert(children.empty());
Assert(args.size() == 5);
- Assert(args[0].isConst() && args[0].getKind() == Kind::CONST_RATIONAL
- && args[0].getConst<Rational>().isIntegral());
+ Assert(args[0].isConst() && args[0].getType().isInteger());
Assert(args[1].getType().isReal());
Assert(args[2].getType().isReal());
Assert(args[3].getType().isReal());
@@ -335,24 +323,22 @@ Node TranscendentalProofRuleChecker::checkInternal(
TaylorGenerator tg;
TaylorGenerator::ApproximationBounds bounds;
tg.getPolynomialApproximationBounds(Kind::SINE, d / 2, bounds);
- Node eval = Rewriter::rewrite(
- bounds.d_upperPos.substitute(tg.getTaylorVariable(), c));
- return Rewriter::rewrite(
- nm->mkNode(Kind::IMPLIES,
- mkBounds(t, lb, ub),
- nm->mkNode(Kind::LEQ, nm->mkNode(Kind::SINE, t), eval)));
+ Evaluator eval(nullptr);
+ Node evalc = eval.eval(bounds.d_upperPos, {tg.getTaylorVariable()}, {c});
+ return nm->mkNode(Kind::IMPLIES,
+ mkBounds(t, lb, ub),
+ nm->mkNode(Kind::LEQ, nm->mkNode(Kind::SINE, t), evalc));
}
else if (id == PfRule::ARITH_TRANS_SINE_APPROX_BELOW_POS)
{
Assert(children.empty());
Assert(args.size() == 6);
- Assert(args[0].isConst() && args[0].getKind() == Kind::CONST_RATIONAL
- && args[0].getConst<Rational>().isIntegral());
+ Assert(args[0].isConst() && args[0].getType().isInteger());
Assert(args[1].getType().isReal());
Assert(args[2].getType().isReal());
Assert(args[3].getType().isReal());
- Assert(args[4].isConst() && args[4].getKind() == Kind::CONST_RATIONAL);
- Assert(args[5].isConst() && args[5].getKind() == Kind::CONST_RATIONAL);
+ Assert(args[4].isConst() && args[4].getType().isRealOrInt());
+ Assert(args[5].isConst() && args[5].getType().isRealOrInt());
std::uint64_t d =
args[0].getConst<Rational>().getNumerator().toUnsignedInt();
Node t = args[1];
@@ -363,23 +349,21 @@ Node TranscendentalProofRuleChecker::checkInternal(
TaylorGenerator tg;
TaylorGenerator::ApproximationBounds bounds;
tg.getPolynomialApproximationBounds(Kind::SINE, d / 2, bounds);
- Node evall =
- Rewriter::rewrite(bounds.d_lower.substitute(tg.getTaylorVariable(), l));
- Node evalu =
- Rewriter::rewrite(bounds.d_lower.substitute(tg.getTaylorVariable(), u));
+ Evaluator eval(nullptr);
+ Node evall = eval.eval(bounds.d_lower, {tg.getTaylorVariable()}, {l});
+ Node evalu = eval.eval(bounds.d_lower, {tg.getTaylorVariable()}, {u});
Node lem = nm->mkNode(
Kind::IMPLIES,
mkBounds(t, lb, ub),
nm->mkNode(
Kind::GEQ, nm->mkNode(Kind::SINE, t), mkSecant(t, lb, ub, l, u)));
- return Rewriter::rewrite(lem);
+ return lem;
}
else if (id == PfRule::ARITH_TRANS_SINE_APPROX_BELOW_NEG)
{
Assert(children.empty());
Assert(args.size() == 5);
- Assert(args[0].isConst() && args[0].getKind() == Kind::CONST_RATIONAL
- && args[0].getConst<Rational>().isIntegral());
+ Assert(args[0].isConst() && args[0].getType().isInteger());
Assert(args[1].getType().isReal());
Assert(args[2].getType().isReal());
Assert(args[3].getType().isReal());
@@ -392,12 +376,11 @@ Node TranscendentalProofRuleChecker::checkInternal(
TaylorGenerator tg;
TaylorGenerator::ApproximationBounds bounds;
tg.getPolynomialApproximationBounds(Kind::SINE, d / 2, bounds);
- Node eval =
- Rewriter::rewrite(bounds.d_lower.substitute(tg.getTaylorVariable(), c));
- return Rewriter::rewrite(
- nm->mkNode(Kind::IMPLIES,
- mkBounds(t, lb, ub),
- nm->mkNode(Kind::GEQ, nm->mkNode(Kind::SINE, t), eval)));
+ Evaluator eval(nullptr);
+ Node evalc = eval.eval(bounds.d_lower, {tg.getTaylorVariable()}, {c});
+ return nm->mkNode(Kind::IMPLIES,
+ mkBounds(t, lb, ub),
+ nm->mkNode(Kind::GEQ, nm->mkNode(Kind::SINE, t), evalc));
}
return Node::null();
}
diff --git a/src/theory/arith/nl/transcendental/sine_solver.cpp b/src/theory/arith/nl/transcendental/sine_solver.cpp
index b6b5c92c1..6c1bec647 100644
--- a/src/theory/arith/nl/transcendental/sine_solver.cpp
+++ b/src/theory/arith/nl/transcendental/sine_solver.cpp
@@ -75,13 +75,12 @@ void SineSolver::doPhaseShift(TNode a, TNode new_a, TNode y)
nm->mkNode(Kind::ITE,
mkValidPhase(a[0], d_data->d_pi),
a[0].eqNode(y),
- a[0].eqNode(nm->mkNode(
- Kind::PLUS,
- y,
- nm->mkNode(Kind::MULT,
- nm->mkConst(CONST_RATIONAL, Rational(2)),
- shift,
- d_data->d_pi)))),
+ a[0].eqNode(nm->mkNode(Kind::PLUS,
+ y,
+ nm->mkNode(Kind::MULT,
+ nm->mkConstReal(Rational(2)),
+ shift,
+ d_data->d_pi)))),
new_a.eqNode(a));
CDProof* proof = nullptr;
if (d_data->isProofEnabled())
@@ -143,7 +142,17 @@ void SineSolver::checkInitialRefine()
if (d_data->isProofEnabled())
{
proof = d_data->getProof();
- proof->addStep(lem, PfRule::ARITH_TRANS_SINE_SYMMETRY, {}, {t[0]});
+ Node tmplem =
+ nm->mkNode(Kind::PLUS,
+ t,
+ nm->mkNode(
+ Kind::SINE,
+ nm->mkNode(Kind::MULT, d_data->d_neg_one, t[0])))
+ .eqNode(d_data->d_zero);
+ proof->addStep(
+ tmplem, PfRule::ARITH_TRANS_SINE_SYMMETRY, {}, {t[0]});
+ proof->addStep(
+ lem, PfRule::MACRO_SR_PRED_TRANSFORM, {tmplem}, {lem});
}
d_data->d_im.addPendingLemma(
lem, InferenceId::ARITH_NL_T_INIT_REFINE, proof);
@@ -385,9 +394,6 @@ void SineSolver::doTangentLemma(
e,
poly_approx));
- Trace("nl-ext-sine") << "*** Tangent plane lemma (pre-rewrite): " << lem
- << std::endl;
- lem = rewrite(lem);
Trace("nl-ext-sine") << "*** Tangent plane lemma : " << lem << std::endl;
Assert(d_data->d_model.computeAbstractModelValue(lem) == d_data->d_false);
// Figure 3 : line 9
@@ -402,7 +408,7 @@ void SineSolver::doTangentLemma(
proof->addStep(lem,
PfRule::ARITH_TRANS_SINE_APPROX_BELOW_NEG,
{},
- {nm->mkConst(CONST_RATIONAL, Rational(2 * d)),
+ {nm->mkConstInt(Rational(2 * d)),
e[0],
c,
regionToLowerBound(region),
@@ -413,7 +419,7 @@ void SineSolver::doTangentLemma(
proof->addStep(lem,
PfRule::ARITH_TRANS_SINE_APPROX_BELOW_NEG,
{},
- {nm->mkConst(CONST_RATIONAL, Rational(2 * d)),
+ {nm->mkConstInt(Rational(2 * d)),
e[0],
c,
c,
@@ -427,7 +433,7 @@ void SineSolver::doTangentLemma(
proof->addStep(lem,
PfRule::ARITH_TRANS_SINE_APPROX_ABOVE_POS,
{},
- {nm->mkConst(CONST_RATIONAL, Rational(2 * d)),
+ {nm->mkConstInt(Rational(2 * d)),
e[0],
c,
regionToLowerBound(region),
@@ -438,7 +444,7 @@ void SineSolver::doTangentLemma(
proof->addStep(lem,
PfRule::ARITH_TRANS_SINE_APPROX_ABOVE_POS,
{},
- {nm->mkConst(CONST_RATIONAL, Rational(2 * d)),
+ {nm->mkConstInt(Rational(2 * d)),
e[0],
c,
c,
diff --git a/src/theory/arith/nl/transcendental/taylor_generator.cpp b/src/theory/arith/nl/transcendental/taylor_generator.cpp
index 2a231bc2b..c9e0015e2 100644
--- a/src/theory/arith/nl/transcendental/taylor_generator.cpp
+++ b/src/theory/arith/nl/transcendental/taylor_generator.cpp
@@ -17,6 +17,7 @@
#include "theory/arith/arith_utilities.h"
#include "theory/arith/nl/nl_model.h"
+#include "theory/evaluator.h"
#include "theory/rewriter.h"
using namespace cvc5::kind;
@@ -28,8 +29,8 @@ namespace nl {
namespace transcendental {
TaylorGenerator::TaylorGenerator()
- : d_nm(NodeManager::currentNM()),
- d_taylor_real_fv(d_nm->mkBoundVar("x", d_nm->realType()))
+ : d_taylor_real_fv(NodeManager::currentNM()->mkBoundVar(
+ "x", NodeManager::currentNM()->realType()))
{
}
@@ -50,7 +51,7 @@ std::pair<Node, Node> TaylorGenerator::getTaylor(Kind k, std::uint64_t n)
// the current factorial `counter!`
Integer factorial = 1;
// the current variable power `x^counter`
- Node varpow = nm->mkConst(CONST_RATIONAL, Rational(1));
+ Node varpow = nm->mkConstReal(Rational(1));
std::vector<Node> sum;
for (std::uint64_t counter = 1; counter <= n; ++counter)
{
@@ -59,9 +60,7 @@ std::pair<Node, Node> TaylorGenerator::getTaylor(Kind k, std::uint64_t n)
// Maclaurin series for exponential:
// \sum_{n=0}^\infty x^n / n!
sum.push_back(
- nm->mkNode(Kind::DIVISION,
- varpow,
- nm->mkConst<Rational>(CONST_RATIONAL, factorial)));
+ nm->mkNode(Kind::DIVISION, varpow, nm->mkConstReal(factorial)));
}
else if (k == Kind::SINE)
{
@@ -70,24 +69,19 @@ std::pair<Node, Node> TaylorGenerator::getTaylor(Kind k, std::uint64_t n)
if (counter % 2 == 0)
{
int sign = (counter % 4 == 0 ? -1 : 1);
- sum.push_back(nm->mkNode(
- Kind::MULT,
- nm->mkNode(Kind::DIVISION,
- nm->mkConst<Rational>(CONST_RATIONAL, sign),
- nm->mkConst<Rational>(CONST_RATIONAL, factorial)),
- varpow));
+ sum.push_back(nm->mkNode(Kind::MULT,
+ nm->mkNode(Kind::DIVISION,
+ nm->mkConstReal(sign),
+ nm->mkConstReal(factorial)),
+ varpow));
}
}
factorial *= counter;
- varpow =
- Rewriter::rewrite(nm->mkNode(Kind::MULT, d_taylor_real_fv, varpow));
+ varpow = nm->mkNode(Kind::MULT, d_taylor_real_fv, varpow);
}
- Node taylor_sum =
- Rewriter::rewrite(sum.size() == 1 ? sum[0] : nm->mkNode(Kind::PLUS, sum));
- Node taylor_rem = Rewriter::rewrite(
- nm->mkNode(Kind::DIVISION,
- varpow,
- nm->mkConst<Rational>(CONST_RATIONAL, factorial)));
+ Node taylor_sum = (sum.size() == 1 ? sum[0] : nm->mkNode(Kind::PLUS, sum));
+ Node taylor_rem =
+ nm->mkNode(Kind::DIVISION, varpow, nm->mkConstReal(factorial));
auto res = std::make_pair(taylor_sum, taylor_rem);
@@ -118,19 +112,17 @@ void TaylorGenerator::getPolynomialApproximationBounds(
if (k == Kind::EXPONENTIAL)
{
pbounds.d_lower = taylor_sum;
- pbounds.d_upperNeg =
- Rewriter::rewrite(nm->mkNode(Kind::PLUS, taylor_sum, ru));
- pbounds.d_upperPos = Rewriter::rewrite(nm->mkNode(
- Kind::MULT,
- taylor_sum,
- nm->mkNode(
- Kind::PLUS, nm->mkConst(CONST_RATIONAL, Rational(1)), ru)));
+ pbounds.d_upperNeg = nm->mkNode(Kind::PLUS, taylor_sum, ru);
+ pbounds.d_upperPos =
+ nm->mkNode(Kind::MULT,
+ taylor_sum,
+ nm->mkNode(Kind::PLUS, nm->mkConstReal(Rational(1)), ru));
}
else
{
Assert(k == Kind::SINE);
- Node l = Rewriter::rewrite(nm->mkNode(Kind::MINUS, taylor_sum, ru));
- Node u = Rewriter::rewrite(nm->mkNode(Kind::PLUS, taylor_sum, ru));
+ Node l = nm->mkNode(Kind::MINUS, taylor_sum, ru);
+ Node u = nm->mkNode(Kind::PLUS, taylor_sum, ru);
pbounds.d_lower = l;
pbounds.d_upperNeg = u;
pbounds.d_upperPos = u;
@@ -160,6 +152,7 @@ std::uint64_t TaylorGenerator::getPolynomialApproximationBoundForArg(
std::uint64_t ds = d;
TNode ttrf = getTaylorVariable();
TNode tc = c;
+ Evaluator eval(nullptr);
do
{
success = true;
@@ -167,8 +160,7 @@ std::uint64_t TaylorGenerator::getPolynomialApproximationBoundForArg(
std::pair<Node, Node> taylor = getTaylor(k, n);
// check that 1-c^{n+1}/(n+1)! > 0
Node ru = taylor.second;
- Node rus = ru.substitute(ttrf, tc);
- rus = Rewriter::rewrite(rus);
+ Node rus = eval.eval(ru, {ttrf}, {tc});
Assert(rus.isConst());
if (rus.getConst<Rational>() > 1)
{
@@ -206,11 +198,11 @@ std::pair<Node, Node> TaylorGenerator::getTfModelBounds(Node tf,
// at zero, its trivial
if (k == Kind::SINE)
{
- Node zero = nm->mkConst(CONST_RATIONAL, Rational(0));
+ Node zero = nm->mkConstReal(Rational(0));
return std::pair<Node, Node>(zero, zero);
}
Assert(k == Kind::EXPONENTIAL);
- Node one = nm->mkConst(CONST_RATIONAL, Rational(1));
+ Node one = nm->mkConstReal(Rational(1));
return std::pair<Node, Node>(one, one);
}
bool isNeg = csign == -1;
@@ -221,6 +213,7 @@ std::pair<Node, Node> TaylorGenerator::getTfModelBounds(Node tf,
std::vector<Node> bounds;
TNode tfv = getTaylorVariable();
TNode tfs = tf[0];
+ Evaluator eval(nullptr);
for (unsigned d2 = 0; d2 < 2; d2++)
{
Node pab = (d2 == 0 ? pbounds.d_lower
@@ -235,8 +228,7 @@ std::pair<Node, Node> TaylorGenerator::getTfModelBounds(Node tf,
// M_A( x*x { x -> t } ) = M_A( t*t )
// where M_A denotes the abstract model.
Node mtfs = model.computeAbstractModelValue(tfs);
- pab = pab.substitute(tfv, mtfs);
- pab = Rewriter::rewrite(pab);
+ pab = eval.eval(pab, {tfv}, {mtfs});
Assert(pab.isConst());
bounds.push_back(pab);
}
diff --git a/src/theory/arith/nl/transcendental/taylor_generator.h b/src/theory/arith/nl/transcendental/taylor_generator.h
index df4cb128c..ea082d87b 100644
--- a/src/theory/arith/nl/transcendental/taylor_generator.h
+++ b/src/theory/arith/nl/transcendental/taylor_generator.h
@@ -104,7 +104,6 @@ class TaylorGenerator
NlModel& model);
private:
- NodeManager* d_nm;
const Node d_taylor_real_fv;
/**
diff --git a/src/theory/arith/nl/transcendental/transcendental_solver.cpp b/src/theory/arith/nl/transcendental/transcendental_solver.cpp
index 9e204f582..25a5a511f 100644
--- a/src/theory/arith/nl/transcendental/transcendental_solver.cpp
+++ b/src/theory/arith/nl/transcendental/transcendental_solver.cpp
@@ -41,11 +41,11 @@ TranscendentalSolver::TranscendentalSolver(Env& env,
InferenceManager& im,
NlModel& m)
: EnvObj(env),
- d_tstate(im, m, env),
+ d_tstate(env, im, m),
d_expSlv(env, &d_tstate),
d_sineSlv(env, &d_tstate)
{
- d_taylor_degree = d_tstate.d_env.getOptions().arith.nlExtTfTaylorDegree;
+ d_taylor_degree = options().arith.nlExtTfTaylorDegree;
}
TranscendentalSolver::~TranscendentalSolver() {}
@@ -187,7 +187,7 @@ void TranscendentalSolver::processSideEffect(const NlLemma& se)
auto it = secant_points.find(d);
if (it == secant_points.end())
{
- it = secant_points.emplace(d, d_tstate.d_env.getUserContext()).first;
+ it = secant_points.emplace(d, userContext()).first;
}
it->second.push_back(c);
}
diff --git a/src/theory/arith/nl/transcendental/transcendental_state.cpp b/src/theory/arith/nl/transcendental/transcendental_state.cpp
index 870eddc86..e32f336ac 100644
--- a/src/theory/arith/nl/transcendental/transcendental_state.cpp
+++ b/src/theory/arith/nl/transcendental/transcendental_state.cpp
@@ -30,16 +30,16 @@ namespace arith {
namespace nl {
namespace transcendental {
-TranscendentalState::TranscendentalState(InferenceManager& im,
- NlModel& model,
- Env& env)
- : d_im(im), d_model(model), d_env(env)
+TranscendentalState::TranscendentalState(Env& env,
+ InferenceManager& im,
+ NlModel& model)
+ : EnvObj(env), d_im(im), d_model(model)
{
d_true = NodeManager::currentNM()->mkConst(true);
d_false = NodeManager::currentNM()->mkConst(false);
- d_zero = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(0));
- d_one = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(1));
- d_neg_one = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(-1));
+ d_zero = NodeManager::currentNM()->mkConstReal(Rational(0));
+ d_one = NodeManager::currentNM()->mkConstReal(Rational(1));
+ d_neg_one = NodeManager::currentNM()->mkConstReal(Rational(-1));
if (d_env.isTheoryProofProducing())
{
d_proof.reset(new CDProofSet<CDProof>(
@@ -204,21 +204,15 @@ void TranscendentalState::mkPi()
if (d_pi.isNull())
{
d_pi = nm->mkNullaryOperator(nm->realType(), Kind::PI);
- d_pi_2 = Rewriter::rewrite(
- nm->mkNode(Kind::MULT,
- d_pi,
- nm->mkConst(CONST_RATIONAL, Rational(1) / Rational(2))));
- d_pi_neg_2 = Rewriter::rewrite(
- nm->mkNode(Kind::MULT,
- d_pi,
- nm->mkConst(CONST_RATIONAL, Rational(-1) / Rational(2))));
- d_pi_neg = Rewriter::rewrite(nm->mkNode(
- Kind::MULT, d_pi, nm->mkConst(CONST_RATIONAL, Rational(-1))));
+ d_pi_2 = rewrite(nm->mkNode(
+ Kind::MULT, d_pi, nm->mkConstReal(Rational(1) / Rational(2))));
+ d_pi_neg_2 = rewrite(nm->mkNode(
+ Kind::MULT, d_pi, nm->mkConstReal(Rational(-1) / Rational(2))));
+ d_pi_neg =
+ rewrite(nm->mkNode(Kind::MULT, d_pi, nm->mkConstReal(Rational(-1))));
// initialize bounds
- d_pi_bound[0] =
- nm->mkConst(CONST_RATIONAL, Rational(103993) / Rational(33102));
- d_pi_bound[1] =
- nm->mkConst(CONST_RATIONAL, Rational(104348) / Rational(33215));
+ d_pi_bound[0] = nm->mkConstReal(Rational(103993) / Rational(33102));
+ d_pi_bound[1] = nm->mkConstReal(Rational(104348) / Rational(33215));
}
}
@@ -274,7 +268,7 @@ Node TranscendentalState::mkSecantPlane(
{
NodeManager* nm = NodeManager::currentNM();
// Figure 3: S_l( x ), S_u( x ) for s = 0,1
- Node rcoeff_n = Rewriter::rewrite(nm->mkNode(Kind::MINUS, lower, upper));
+ Node rcoeff_n = rewrite(nm->mkNode(Kind::MINUS, lower, upper));
Assert(rcoeff_n.isConst());
Rational rcoeff = rcoeff_n.getConst<Rational>();
Assert(rcoeff.sgn() != 0);
@@ -291,7 +285,7 @@ Node TranscendentalState::mkSecantPlane(
Trace("nl-trans") << "\tfrom ( " << lower << " ; " << lval << " ) to ( "
<< upper << " ; " << uval << " )" << std::endl;
Trace("nl-trans") << "\t" << res << std::endl;
- Trace("nl-trans") << "\trewritten: " << Rewriter::rewrite(res) << std::endl;
+ Trace("nl-trans") << "\trewritten: " << rewrite(res) << std::endl;
return res;
}
@@ -331,9 +325,6 @@ NlLemma TranscendentalState::mkSecantLemma(TNode lower,
antec_n,
nm->mkNode(
convexity == Convexity::CONVEX ? Kind::LEQ : Kind::GEQ, tf, splane));
- Trace("nl-trans-lemma") << "*** Secant plane lemma (pre-rewrite) : " << lem
- << std::endl;
- lem = Rewriter::rewrite(lem);
Trace("nl-trans-lemma") << "*** Secant plane lemma : " << lem << std::endl;
Assert(d_model.computeAbstractModelValue(lem) == d_false);
CDProof* proof = nullptr;
@@ -347,44 +338,34 @@ NlLemma TranscendentalState::mkSecantLemma(TNode lower,
proof->addStep(lem,
PfRule::ARITH_TRANS_EXP_APPROX_ABOVE_POS,
{},
- {nm->mkConst<Rational>(CONST_RATIONAL, 2 * actual_d),
- tf[0],
- lower,
- upper});
+ {nm->mkConstInt(2 * actual_d), tf[0], lower, upper});
}
else
{
proof->addStep(lem,
PfRule::ARITH_TRANS_EXP_APPROX_ABOVE_NEG,
{},
- {nm->mkConst<Rational>(CONST_RATIONAL, 2 * actual_d),
- tf[0],
- lower,
- upper});
+ {nm->mkConstInt(2 * actual_d), tf[0], lower, upper});
}
}
else if (tf.getKind() == Kind::SINE)
{
if (convexity == Convexity::CONCAVE)
{
- proof->addStep(lem,
- PfRule::ARITH_TRANS_SINE_APPROX_BELOW_POS,
- {},
- {nm->mkConst<Rational>(CONST_RATIONAL, 2 * actual_d),
- tf[0],
- lower,
- upper,
- lapprox,
- uapprox
+ proof->addStep(
+ lem,
+ PfRule::ARITH_TRANS_SINE_APPROX_BELOW_POS,
+ {},
+ {nm->mkConstInt(2 * actual_d), tf[0], lower, upper, lapprox, uapprox
- });
+ });
}
else
{
proof->addStep(lem,
PfRule::ARITH_TRANS_SINE_APPROX_ABOVE_NEG,
{},
- {nm->mkConst<Rational>(CONST_RATIONAL, 2 * actual_d),
+ {nm->mkConstInt(2 * actual_d),
tf[0],
lower,
upper,
@@ -419,8 +400,8 @@ void TranscendentalState::doSecantLemmas(const std::pair<Node, Node>& bounds,
if (lower != center)
{
// Figure 3 : P(l), P(u), for s = 0
- Node lval = Rewriter::rewrite(
- poly_approx.substitute(d_taylor.getTaylorVariable(), lower));
+ Node lval =
+ rewrite(poly_approx.substitute(d_taylor.getTaylorVariable(), lower));
Node splane = mkSecantPlane(tf[0], lower, center, lval, cval);
NlLemma nlem = mkSecantLemma(
lower, center, lval, cval, csign, convexity, tf, splane, actual_d);
@@ -438,8 +419,8 @@ void TranscendentalState::doSecantLemmas(const std::pair<Node, Node>& bounds,
if (center != upper)
{
// Figure 3 : P(l), P(u), for s = 1
- Node uval = Rewriter::rewrite(
- poly_approx.substitute(d_taylor.getTaylorVariable(), upper));
+ Node uval =
+ rewrite(poly_approx.substitute(d_taylor.getTaylorVariable(), upper));
Node splane = mkSecantPlane(tf[0], center, upper, cval, uval);
NlLemma nlem = mkSecantLemma(
center, upper, cval, uval, csign, convexity, tf, splane, actual_d);
diff --git a/src/theory/arith/nl/transcendental/transcendental_state.h b/src/theory/arith/nl/transcendental/transcendental_state.h
index 77fcf57fb..ede8079a4 100644
--- a/src/theory/arith/nl/transcendental/transcendental_state.h
+++ b/src/theory/arith/nl/transcendental/transcendental_state.h
@@ -60,9 +60,9 @@ inline std::ostream& operator<<(std::ostream& os, Convexity c) {
* This includes common lookups and caches as well as generic utilities for
* secant plane lemmas and taylor approximations.
*/
-struct TranscendentalState
+struct TranscendentalState : protected EnvObj
{
- TranscendentalState(InferenceManager& im, NlModel& model, Env& env);
+ TranscendentalState(Env& env, InferenceManager& im, NlModel& model);
/**
* Checks whether proofs are enabled.
@@ -168,8 +168,6 @@ struct TranscendentalState
InferenceManager& d_im;
/** Reference to the non-linear model object */
NlModel& d_model;
- /** Reference to the environment */
- Env& d_env;
/** Utility to compute taylor approximations */
TaylorGenerator d_taylor;
/**
diff --git a/src/theory/arith/operator_elim.cpp b/src/theory/arith/operator_elim.cpp
index 17efa53a5..99f5621d6 100644
--- a/src/theory/arith/operator_elim.cpp
+++ b/src/theory/arith/operator_elim.cpp
@@ -173,22 +173,20 @@ Node OperatorElim::eliminateOperators(Node node,
nm->mkNode(
MULT,
den,
- nm->mkNode(
- PLUS, v, nm->mkConst(CONST_RATIONAL, Rational(1))))));
+ nm->mkNode(PLUS, v, nm->mkConstInt(Rational(1))))));
}
else
{
lem = nm->mkNode(
AND,
leqNum,
- nm->mkNode(LT,
- num,
- nm->mkNode(MULT,
- den,
- nm->mkNode(PLUS,
- v,
- nm->mkConst(CONST_RATIONAL,
- Rational(-1))))));
+ nm->mkNode(
+ LT,
+ num,
+ nm->mkNode(
+ MULT,
+ den,
+ nm->mkNode(PLUS, v, nm->mkConstInt(Rational(-1))))));
}
}
else
@@ -198,34 +196,32 @@ Node OperatorElim::eliminateOperators(Node node,
AND,
nm->mkNode(
IMPLIES,
- nm->mkNode(GT, den, nm->mkConst(CONST_RATIONAL, Rational(0))),
+ nm->mkNode(GT, den, nm->mkConstInt(Rational(0))),
nm->mkNode(
AND,
leqNum,
nm->mkNode(
LT,
num,
- nm->mkNode(MULT,
- den,
- nm->mkNode(PLUS,
- v,
- nm->mkConst(CONST_RATIONAL,
- Rational(1))))))),
+ nm->mkNode(
+ MULT,
+ den,
+ nm->mkNode(
+ PLUS, v, nm->mkConstInt(Rational(1))))))),
nm->mkNode(
IMPLIES,
- nm->mkNode(LT, den, nm->mkConst(CONST_RATIONAL, Rational(0))),
+ nm->mkNode(LT, den, nm->mkConstInt(Rational(0))),
nm->mkNode(
AND,
leqNum,
nm->mkNode(
LT,
num,
- nm->mkNode(MULT,
- den,
- nm->mkNode(PLUS,
- v,
- nm->mkConst(CONST_RATIONAL,
- Rational(-1))))))));
+ nm->mkNode(
+ MULT,
+ den,
+ nm->mkNode(
+ PLUS, v, nm->mkConstInt(Rational(-1))))))));
}
Node intVar = mkWitnessTerm(
v, lem, "linearIntDiv", "the result of an intdiv-by-k term", lems);
@@ -259,10 +255,9 @@ Node OperatorElim::eliminateOperators(Node node,
checkNonLinearLogic(node);
Node rw = nm->mkNode(k, num, den);
Node v = bvm->mkBoundVar<ArithWitnessVarAttribute>(rw, nm->realType());
- Node lem = nm->mkNode(
- IMPLIES,
- den.eqNode(nm->mkConst(CONST_RATIONAL, Rational(0))).negate(),
- nm->mkNode(MULT, den, v).eqNode(num));
+ Node lem = nm->mkNode(IMPLIES,
+ den.eqNode(nm->mkConstReal(Rational(0))).negate(),
+ nm->mkNode(MULT, den, v).eqNode(num));
return mkWitnessTerm(
v, lem, "nonlinearDiv", "the result of a non-linear div term", lems);
break;
@@ -276,8 +271,7 @@ Node OperatorElim::eliminateOperators(Node node,
{
checkNonLinearLogic(node);
Node divByZeroNum = getArithSkolemApp(num, SkolemFunId::DIV_BY_ZERO);
- Node denEq0 =
- nm->mkNode(EQUAL, den, nm->mkConst(CONST_RATIONAL, Rational(0)));
+ Node denEq0 = nm->mkNode(EQUAL, den, nm->mkConstReal(Rational(0)));
ret = nm->mkNode(ITE, denEq0, divByZeroNum, ret);
}
return ret;
@@ -295,8 +289,7 @@ Node OperatorElim::eliminateOperators(Node node,
checkNonLinearLogic(node);
Node intDivByZeroNum =
getArithSkolemApp(num, SkolemFunId::INT_DIV_BY_ZERO);
- Node denEq0 =
- nm->mkNode(EQUAL, den, nm->mkConst(CONST_RATIONAL, Rational(0)));
+ Node denEq0 = nm->mkNode(EQUAL, den, nm->mkConstInt(Rational(0)));
ret = nm->mkNode(ITE, denEq0, intDivByZeroNum, ret);
}
return ret;
@@ -313,8 +306,7 @@ Node OperatorElim::eliminateOperators(Node node,
{
checkNonLinearLogic(node);
Node modZeroNum = getArithSkolemApp(num, SkolemFunId::MOD_BY_ZERO);
- Node denEq0 =
- nm->mkNode(EQUAL, den, nm->mkConst(CONST_RATIONAL, Rational(0)));
+ Node denEq0 = nm->mkNode(EQUAL, den, nm->mkConstInt(Rational(0)));
ret = nm->mkNode(ITE, denEq0, modZeroNum, ret);
}
return ret;
@@ -325,7 +317,9 @@ Node OperatorElim::eliminateOperators(Node node,
{
return nm->mkNode(
ITE,
- nm->mkNode(LT, node[0], nm->mkConst(CONST_RATIONAL, Rational(0))),
+ nm->mkNode(LT,
+ node[0],
+ nm->mkConstRealOrInt(node[0].getType(), Rational(0))),
nm->mkNode(UMINUS, node[0]),
node[0]);
break;
@@ -363,11 +357,10 @@ Node OperatorElim::eliminateOperators(Node node,
// satisfiable. On the original formula, this would require that we
// simultaneously interpret sqrt(1) as 1 and -1, which is not a valid
// model.
- lem = nm->mkNode(
- ITE,
- nm->mkNode(GEQ, node[0], nm->mkConst(CONST_RATIONAL, Rational(0))),
- nonNeg,
- uf);
+ lem = nm->mkNode(ITE,
+ nm->mkNode(GEQ, node[0], nm->mkConstReal(Rational(0))),
+ nonNeg,
+ uf);
}
else
{
@@ -377,10 +370,9 @@ Node OperatorElim::eliminateOperators(Node node,
Node rlem;
if (k == ARCSINE || k == ARCTANGENT || k == ARCCOSECANT)
{
- Node half = nm->mkConst(CONST_RATIONAL, Rational(1) / Rational(2));
+ Node half = nm->mkConstReal(Rational(1) / Rational(2));
Node pi2 = nm->mkNode(MULT, half, pi);
- Node npi2 =
- nm->mkNode(MULT, nm->mkConst(CONST_RATIONAL, Rational(-1)), pi2);
+ Node npi2 = nm->mkNode(MULT, nm->mkConstReal(Rational(-1)), pi2);
// -pi/2 < var <= pi/2
rlem = nm->mkNode(
AND, nm->mkNode(LT, npi2, var), nm->mkNode(LEQ, var, pi2));
@@ -388,10 +380,9 @@ Node OperatorElim::eliminateOperators(Node node,
else
{
// 0 <= var < pi
- rlem = nm->mkNode(
- AND,
- nm->mkNode(LEQ, nm->mkConst(CONST_RATIONAL, Rational(0)), var),
- nm->mkNode(LT, var, pi));
+ rlem = nm->mkNode(AND,
+ nm->mkNode(LEQ, nm->mkConstReal(Rational(0)), var),
+ nm->mkNode(LT, var, pi));
}
Kind rk =
diff --git a/src/theory/arith/proof_checker.cpp b/src/theory/arith/proof_checker.cpp
index 69fe98734..c05f6ae0a 100644
--- a/src/theory/arith/proof_checker.cpp
+++ b/src/theory/arith/proof_checker.cpp
@@ -49,7 +49,6 @@ Node ArithProofRuleChecker::checkInternal(PfRule id,
const std::vector<Node>& args)
{
NodeManager* nm = NodeManager::currentNM();
- auto zero = nm->mkConst<Rational>(CONST_RATIONAL, 0);
if (Debug.isOn("arith::pf::check"))
{
Debug("arith::pf::check") << "Arith PfRule:" << id << std::endl;
@@ -76,6 +75,7 @@ Node ArithProofRuleChecker::checkInternal(PfRule id,
|| rel == Kind::LEQ || rel == Kind::GT || rel == Kind::GEQ);
Node lhs = args[1][0];
Node rhs = args[1][1];
+ Node zero = nm->mkConstRealOrInt(mult.getType(), Rational(0));
return nm->mkNode(Kind::IMPLIES,
nm->mkAnd(std::vector<Node>{
nm->mkNode(Kind::GT, mult, zero), args[1]}),
@@ -94,6 +94,7 @@ Node ArithProofRuleChecker::checkInternal(PfRule id,
Kind rel_inv = (rel == Kind::DISTINCT ? rel : reverseRelationKind(rel));
Node lhs = args[1][0];
Node rhs = args[1][1];
+ Node zero = nm->mkConstRealOrInt(mult.getType(), Rational(0));
return nm->mkNode(Kind::IMPLIES,
nm->mkAnd(std::vector<Node>{
nm->mkNode(Kind::LT, mult, zero), args[1]}),
@@ -243,12 +244,8 @@ Node ArithProofRuleChecker::checkInternal(PfRule id,
<< "Bad kind: " << children[i].getKind() << std::endl;
}
}
- leftSum << nm->mkNode(Kind::MULT,
- nm->mkConst<Rational>(CONST_RATIONAL, scalar),
- children[i][0]);
- rightSum << nm->mkNode(Kind::MULT,
- nm->mkConst<Rational>(CONST_RATIONAL, scalar),
- children[i][1]);
+ leftSum << nm->mkNode(Kind::MULT, args[i], children[i][0]);
+ rightSum << nm->mkNode(Kind::MULT, args[i], children[i][1]);
}
Node r = nm->mkNode(strict ? Kind::LT : Kind::LEQ,
leftSum.constructNode(),
@@ -265,8 +262,7 @@ Node ArithProofRuleChecker::checkInternal(PfRule id,
if (children.size() != 1
|| (children[0].getKind() != Kind::GT
&& children[0].getKind() != Kind::GEQ)
- || !children[0][0].getType().isInteger()
- || children[0][1].getKind() != Kind::CONST_RATIONAL)
+ || !children[0][0].getType().isInteger() || !children[0][1].isConst())
{
Debug("arith::pf::check") << "Illformed input: " << children;
return Node::null();
@@ -275,7 +271,7 @@ Node ArithProofRuleChecker::checkInternal(PfRule id,
{
Rational originalBound = children[0][1].getConst<Rational>();
Rational newBound = leastIntGreaterThan(originalBound);
- Node rational = nm->mkConst<Rational>(CONST_RATIONAL, newBound);
+ Node rational = nm->mkConstInt(newBound);
return nm->mkNode(kind::GEQ, children[0][0], rational);
}
}
@@ -290,8 +286,7 @@ Node ArithProofRuleChecker::checkInternal(PfRule id,
if (children.size() != 1
|| (children[0].getKind() != Kind::LT
&& children[0].getKind() != Kind::LEQ)
- || !children[0][0].getType().isInteger()
- || children[0][1].getKind() != Kind::CONST_RATIONAL)
+ || !children[0][0].getType().isInteger() || !children[0][1].isConst())
{
Debug("arith::pf::check") << "Illformed input: " << children;
return Node::null();
@@ -300,7 +295,7 @@ Node ArithProofRuleChecker::checkInternal(PfRule id,
{
Rational originalBound = children[0][1].getConst<Rational>();
Rational newBound = greatestIntLessThan(originalBound);
- Node rational = nm->mkConst<Rational>(CONST_RATIONAL, newBound);
+ Node rational = nm->mkConstInt(newBound);
return nm->mkNode(kind::LEQ, children[0][0], rational);
}
}
diff --git a/src/theory/arith/theory_arith_private.cpp b/src/theory/arith/theory_arith_private.cpp
index 643ba9a28..bf8798485 100644
--- a/src/theory/arith/theory_arith_private.cpp
+++ b/src/theory/arith/theory_arith_private.cpp
@@ -4782,8 +4782,11 @@ std::pair<bool, Node> TheoryArithPrivate::entailmentCheck(TNode lit, const Arith
return make_pair(false, Node::null());
}
-bool TheoryArithPrivate::decomposeTerm(Node term, Rational& m, Node& p, Rational& c){
- Node t = Rewriter::rewrite(term);
+bool TheoryArithPrivate::decomposeTerm(Node t,
+ Rational& m,
+ Node& p,
+ Rational& c)
+{
if(!Polynomial::isMember(t)){
return false;
}
@@ -4879,12 +4882,13 @@ bool TheoryArithPrivate::decomposeLiteral(Node lit, Kind& k, int& dir, Rational&
// left : lm*( lp ) + lc
// right: rm*( rp ) + rc
Rational lc, rc;
- bool success = decomposeTerm(left, lm, lp, lc);
+ bool success = decomposeTerm(rewrite(left), lm, lp, lc);
if(!success){ return false; }
- success = decomposeTerm(right, rm, rp, rc);
+ success = decomposeTerm(rewrite(right), rm, rp, rc);
if(!success){ return false; }
- Node diff = Rewriter::rewrite(NodeManager::currentNM()->mkNode(kind::MINUS, left, right));
+ Node diff =
+ rewrite(NodeManager::currentNM()->mkNode(kind::MINUS, left, right));
Rational dc;
success = decomposeTerm(diff, dm, dp, dc);
Assert(success);
diff --git a/src/theory/arith/theory_arith_private.h b/src/theory/arith/theory_arith_private.h
index 918f73a53..7c90352d2 100644
--- a/src/theory/arith/theory_arith_private.h
+++ b/src/theory/arith/theory_arith_private.h
@@ -162,20 +162,26 @@ private:
//std::pair<DeltaRational, Node> inferBound(TNode term, bool lb, int maxRounds = -1, const DeltaRational* threshold = NULL);
private:
- static bool decomposeTerm(Node term, Rational& m, Node& p, Rational& c);
- static bool decomposeLiteral(Node lit, Kind& k, int& dir, Rational& lm, Node& lp, Rational& rm, Node& rp, Rational& dm, Node& dp, DeltaRational& sep);
- static void setToMin(int sgn, std::pair<Node, DeltaRational>& min, const std::pair<Node, DeltaRational>& e);
-
- /**
- * The map between arith variables to nodes.
- */
- //ArithVarNodeMap d_arithvarNodeMap;
-
- typedef ArithVariables::var_iterator var_iterator;
- var_iterator var_begin() const { return d_partialModel.var_begin(); }
- var_iterator var_end() const { return d_partialModel.var_end(); }
-
- NodeSet d_setupNodes;
+ static bool decomposeTerm(Node t, Rational& m, Node& p, Rational& c);
+ bool decomposeLiteral(Node lit,
+ Kind& k,
+ int& dir,
+ Rational& lm,
+ Node& lp,
+ Rational& rm,
+ Node& rp,
+ Rational& dm,
+ Node& dp,
+ DeltaRational& sep);
+ static void setToMin(int sgn,
+ std::pair<Node, DeltaRational>& min,
+ const std::pair<Node, DeltaRational>& e);
+
+ typedef ArithVariables::var_iterator var_iterator;
+ var_iterator var_begin() const { return d_partialModel.var_begin(); }
+ var_iterator var_end() const { return d_partialModel.var_end(); }
+
+ NodeSet d_setupNodes;
public:
bool isSetup(Node n) const {
return d_setupNodes.find(n) != d_setupNodes.end();
diff --git a/src/theory/bags/bag_reduction.cpp b/src/theory/bags/bag_reduction.cpp
index 9203a1c45..3e6544882 100644
--- a/src/theory/bags/bag_reduction.cpp
+++ b/src/theory/bags/bag_reduction.cpp
@@ -34,13 +34,26 @@ BagReduction::~BagReduction() {}
/**
* A bound variable corresponding to the universally quantified integer
- * variable used to range over the distinct elements in a bag, used
+ * variable used to range over (may be distinct) elements in a bag, used
* for axiomatizing the behavior of some term.
+ * If there are multiple quantifiers, this variable should be the first one.
*/
-struct IndexVarAttributeId
+struct FirstIndexVarAttributeId
{
};
-typedef expr::Attribute<IndexVarAttributeId, Node> IndexVarAttribute;
+typedef expr::Attribute<FirstIndexVarAttributeId, Node> FirstIndexVarAttribute;
+
+/**
+ * A bound variable corresponding to the universally quantified integer
+ * variable used to range over (may be distinct) elements in a bag, used
+ * for axiomatizing the behavior of some term.
+ * This variable should be the second of multiple quantifiers.
+ */
+struct SecondIndexVarAttributeId
+{
+};
+typedef expr::Attribute<SecondIndexVarAttributeId, Node>
+ SecondIndexVarAttribute;
Node BagReduction::reduceFoldOperator(Node node, std::vector<Node>& asserts)
{
@@ -52,8 +65,8 @@ Node BagReduction::reduceFoldOperator(Node node, std::vector<Node>& asserts)
Node f = node[0];
Node t = node[1];
Node A = node[2];
- Node zero = nm->mkConst(CONST_RATIONAL, Rational(0));
- Node one = nm->mkConst(CONST_RATIONAL, Rational(1));
+ Node zero = nm->mkConstInt(Rational(0));
+ Node one = nm->mkConstInt(Rational(1));
// types
TypeNode bagType = A.getType();
TypeNode elementType = A.getType().getBagElementType();
@@ -71,7 +84,8 @@ Node BagReduction::reduceFoldOperator(Node node, std::vector<Node>& asserts)
SkolemFunId::BAGS_FOLD_COMBINE, combineType, {f, t, A});
BoundVarManager* bvm = nm->getBoundVarManager();
- Node i = bvm->mkBoundVar<IndexVarAttribute>(node, "i", nm->integerType());
+ Node i =
+ bvm->mkBoundVar<FirstIndexVarAttribute>(node, "i", nm->integerType());
Node iList = nm->mkNode(BOUND_VAR_LIST, i);
Node iMinusOne = nm->mkNode(MINUS, i, one);
Node uf_i = nm->mkNode(APPLY_UF, uf, i);
@@ -114,6 +128,84 @@ Node BagReduction::reduceFoldOperator(Node node, std::vector<Node>& asserts)
return Node::null();
}
+Node BagReduction::reduceCardOperator(Node node, std::vector<Node>& asserts)
+{
+ Assert(node.getKind() == BAG_CARD);
+ NodeManager* nm = NodeManager::currentNM();
+ SkolemManager* sm = nm->getSkolemManager();
+ Node A = node[0];
+ Node zero = nm->mkConst(CONST_RATIONAL, Rational(0));
+ Node one = nm->mkConst(CONST_RATIONAL, Rational(1));
+ // types
+ TypeNode bagType = A.getType();
+ TypeNode elementType = A.getType().getBagElementType();
+ TypeNode integerType = nm->integerType();
+ TypeNode ufType = nm->mkFunctionType(integerType, elementType);
+ TypeNode cardinalityType = nm->mkFunctionType(integerType, integerType);
+ TypeNode unionDisjointType = nm->mkFunctionType(integerType, bagType);
+ // skolem functions
+ Node n = sm->mkSkolemFunction(SkolemFunId::BAGS_CARD_N, integerType, A);
+ Node uf = sm->mkSkolemFunction(SkolemFunId::BAGS_CARD_ELEMENTS, ufType, A);
+ Node unionDisjoint = sm->mkSkolemFunction(
+ SkolemFunId::BAGS_CARD_UNION_DISJOINT, unionDisjointType, A);
+ Node cardinality = sm->mkSkolemFunction(
+ SkolemFunId::BAGS_CARD_CARDINALITY, cardinalityType, A);
+
+ BoundVarManager* bvm = nm->getBoundVarManager();
+ Node i =
+ bvm->mkBoundVar<FirstIndexVarAttribute>(node, "i", nm->integerType());
+ Node j =
+ bvm->mkBoundVar<SecondIndexVarAttribute>(node, "j", nm->integerType());
+ Node iList = nm->mkNode(BOUND_VAR_LIST, i);
+ Node jList = nm->mkNode(BOUND_VAR_LIST, j);
+ Node iMinusOne = nm->mkNode(MINUS, i, one);
+ Node uf_i = nm->mkNode(APPLY_UF, uf, i);
+ Node uf_j = nm->mkNode(APPLY_UF, uf, j);
+ Node cardinality_0 = nm->mkNode(APPLY_UF, cardinality, zero);
+ Node cardinality_iMinusOne = nm->mkNode(APPLY_UF, cardinality, iMinusOne);
+ Node cardinality_i = nm->mkNode(APPLY_UF, cardinality, i);
+ Node cardinality_n = nm->mkNode(APPLY_UF, cardinality, n);
+ Node unionDisjoint_0 = nm->mkNode(APPLY_UF, unionDisjoint, zero);
+ Node unionDisjoint_iMinusOne = nm->mkNode(APPLY_UF, unionDisjoint, iMinusOne);
+ Node unionDisjoint_i = nm->mkNode(APPLY_UF, unionDisjoint, i);
+ Node unionDisjoint_n = nm->mkNode(APPLY_UF, unionDisjoint, n);
+ Node cardinality_0_equal = cardinality_0.eqNode(zero);
+ Node uf_i_multiplicity = nm->mkNode(BAG_COUNT, uf_i, A);
+ Node cardinality_i_equal = cardinality_i.eqNode(
+ nm->mkNode(PLUS, uf_i_multiplicity, cardinality_iMinusOne));
+ Node unionDisjoint_0_equal =
+ unionDisjoint_0.eqNode(nm->mkConst(EmptyBag(bagType)));
+ Node bag = nm->mkBag(elementType, uf_i, uf_i_multiplicity);
+
+ Node unionDisjoint_i_equal = unionDisjoint_i.eqNode(
+ nm->mkNode(BAG_UNION_DISJOINT, bag, unionDisjoint_iMinusOne));
+ // 1 <= i <= n
+ Node interval_i =
+ nm->mkNode(AND, nm->mkNode(GEQ, i, one), nm->mkNode(LEQ, i, n));
+
+ // i < j <= n
+ Node interval_j =
+ nm->mkNode(AND, nm->mkNode(LT, i, j), nm->mkNode(LEQ, j, n));
+ // uf(i) != uf(j)
+ Node uf_i_equals_uf_j = nm->mkNode(EQUAL, uf_i, uf_j);
+ Node notEqual = nm->mkNode(EQUAL, uf_i, uf_j).negate();
+ Node body_j = nm->mkNode(OR, interval_j.negate(), notEqual);
+ Node forAll_j = quantifiers::BoundedIntegers::mkBoundedForall(jList, body_j);
+ Node body_i = nm->mkNode(
+ IMPLIES,
+ interval_i,
+ nm->mkNode(AND, cardinality_i_equal, unionDisjoint_i_equal, forAll_j));
+ Node forAll_i = quantifiers::BoundedIntegers::mkBoundedForall(iList, body_i);
+ Node nonNegative = nm->mkNode(GEQ, n, zero);
+ Node unionDisjoint_n_equal = A.eqNode(unionDisjoint_n);
+ asserts.push_back(forAll_i);
+ asserts.push_back(cardinality_0_equal);
+ asserts.push_back(unionDisjoint_0_equal);
+ asserts.push_back(unionDisjoint_n_equal);
+ asserts.push_back(nonNegative);
+ return cardinality_n;
+}
+
} // namespace bags
} // namespace theory
} // namespace cvc5
diff --git a/src/theory/bags/bag_reduction.h b/src/theory/bags/bag_reduction.h
index 11f091f94..694379dfc 100644
--- a/src/theory/bags/bag_reduction.h
+++ b/src/theory/bags/bag_reduction.h
@@ -41,9 +41,8 @@ class BagReduction : EnvObj
* t: T2 is the initial value
* A: (Bag T1) is a bag
* @param asserts a list of assertions generated by this reduction
- * @return the reduction term (combine n) such that
- * (and
- * (forall ((i Int))
+ * @return the reduction term (combine n) with asserts:
+ * - (forall ((i Int))
* (let ((iMinusOne (- i 1)))
* (let ((uf_i (uf i)))
* (=>
@@ -55,18 +54,49 @@ class BagReduction : EnvObj
* (bag.union_disjoint
* (bag uf_i 1)
* (unionDisjoint iMinusOne))))))))
- * (= (combine 0) t)
- * (= (unionDisjoint 0) (as bag.empty (Bag T1)))
- * (= A (unionDisjoint n))
- * (>= n 0))
- * where
- * n: Int is the cardinality of bag A
- * uf:Int -> T1 is an uninterpreted function that represents elements of A
- * combine: Int -> T2 is an uninterpreted function
- * unionDisjoint: Int -> (Bag T1) is an uninterpreted function
+ * - (= (combine 0) t)
+ * - (= (unionDisjoint 0) (as bag.empty (Bag T1)))
+ * - (= A (unionDisjoint n))
+ * - (>= n 0))
+ * where
+ * n: Int is the cardinality of bag A
+ * uf:Int -> T1 is an uninterpreted function that represents elements of A
+ * combine: Int -> T2 is an uninterpreted function
+ * unionDisjoint: Int -> (Bag T1) is an uninterpreted function
*/
Node reduceFoldOperator(Node node, std::vector<Node>& asserts);
+ /**
+ * @param node a term of the form (bag.card A) where A: (Bag T) is a bag
+ * @param asserts a list of assertions generated by this reduction
+ * @return the reduction term (cardinality n) with asserts:
+ * - (forall ((i Int))
+ * (let ((uf_i (uf i)))
+ * (let ((count_uf_i (bag.count uf_i A)))
+ * (=>
+ * (and (>= i 1) (<= i n))
+ * (and
+ * (= (cardinality i) (+ count_uf_i (cardinality (- i 1))))
+ * (=
+ * (unionDisjoint i)
+ * (bag.union_disjoint (bag uf_i count_uf_i) (unionDisjoint (- i 1))))
+ * (forall ((j Int))
+ * (or (not (and (< i j) (<= j n)))
+ * (not (= (uf i) (uf j))))))))))
+ * - (= (cardinality 0) 0)
+ * - (= (unionDisjoint 0) (as bag.empty (Bag String)))
+ * - (= A (unionDisjoint n))
+ * - (>= n 0)
+ *
+ * where
+ * n: number of distinct elements in A
+ * uf:Int -> T is an uninterpreted function that represents distinct
+ * elements of A
+ * cardinality: Int -> Int is an uninterpreted function
+ * unionDisjoint: Int -> (Bag T1) is an uninterpreted function
+ */
+ Node reduceCardOperator(Node node, std::vector<Node>& asserts);
+
private:
};
diff --git a/src/theory/bags/bag_solver.cpp b/src/theory/bags/bag_solver.cpp
index 444878574..80ccd6707 100644
--- a/src/theory/bags/bag_solver.cpp
+++ b/src/theory/bags/bag_solver.cpp
@@ -42,8 +42,8 @@ BagSolver::BagSolver(Env& env,
d_termReg(tr),
d_mapCache(userContext())
{
- d_zero = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(0));
- d_one = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(1));
+ d_zero = NodeManager::currentNM()->mkConstInt(Rational(0));
+ d_one = NodeManager::currentNM()->mkConstInt(Rational(1));
d_true = NodeManager::currentNM()->mkConst(true);
d_false = NodeManager::currentNM()->mkConst(false);
}
@@ -89,7 +89,7 @@ void BagSolver::postCheck()
{
for (const Node& e : d_state.getElements(n))
{
- checkNonNegativeCountTerms(n, e);
+ checkNonNegativeCountTerms(n, d_state.getRepresentative(e));
}
}
}
@@ -115,7 +115,7 @@ void BagSolver::checkEmpty(const Node& n)
Assert(n.getKind() == BAG_EMPTY);
for (const Node& e : d_state.getElements(n))
{
- InferInfo i = d_ig.empty(n, e);
+ InferInfo i = d_ig.empty(n, d_state.getRepresentative(e));
d_im.lemmaTheoryInference(&i);
}
}
@@ -126,7 +126,7 @@ void BagSolver::checkUnionDisjoint(const Node& n)
std::set<Node> elements = getElementsForBinaryOperator(n);
for (const Node& e : elements)
{
- InferInfo i = d_ig.unionDisjoint(n, e);
+ InferInfo i = d_ig.unionDisjoint(n, d_state.getRepresentative(e));
d_im.lemmaTheoryInference(&i);
}
}
@@ -137,7 +137,7 @@ void BagSolver::checkUnionMax(const Node& n)
std::set<Node> elements = getElementsForBinaryOperator(n);
for (const Node& e : elements)
{
- InferInfo i = d_ig.unionMax(n, e);
+ InferInfo i = d_ig.unionMax(n, d_state.getRepresentative(e));
d_im.lemmaTheoryInference(&i);
}
}
@@ -148,7 +148,7 @@ void BagSolver::checkIntersectionMin(const Node& n)
std::set<Node> elements = getElementsForBinaryOperator(n);
for (const Node& e : elements)
{
- InferInfo i = d_ig.intersection(n, e);
+ InferInfo i = d_ig.intersection(n, d_state.getRepresentative(e));
d_im.lemmaTheoryInference(&i);
}
}
@@ -159,7 +159,7 @@ void BagSolver::checkDifferenceSubtract(const Node& n)
std::set<Node> elements = getElementsForBinaryOperator(n);
for (const Node& e : elements)
{
- InferInfo i = d_ig.differenceSubtract(n, e);
+ InferInfo i = d_ig.differenceSubtract(n, d_state.getRepresentative(e));
d_im.lemmaTheoryInference(&i);
}
}
@@ -172,7 +172,7 @@ void BagSolver::checkBagMake(const Node& n)
<< " are: " << d_state.getElements(n) << std::endl;
for (const Node& e : d_state.getElements(n))
{
- InferInfo i = d_ig.bagMake(n, e);
+ InferInfo i = d_ig.bagMake(n, d_state.getRepresentative(e));
d_im.lemmaTheoryInference(&i);
}
}
@@ -188,7 +188,7 @@ void BagSolver::checkDifferenceRemove(const Node& n)
std::set<Node> elements = getElementsForBinaryOperator(n);
for (const Node& e : elements)
{
- InferInfo i = d_ig.differenceRemove(n, e);
+ InferInfo i = d_ig.differenceRemove(n, d_state.getRepresentative(e));
d_im.lemmaTheoryInference(&i);
}
}
@@ -205,7 +205,7 @@ void BagSolver::checkDuplicateRemoval(Node n)
for (const Node& e : elements)
{
- InferInfo i = d_ig.duplicateRemoval(n, e);
+ InferInfo i = d_ig.duplicateRemoval(n, d_state.getRepresentative(e));
d_im.lemmaTheoryInference(&i);
}
}
@@ -224,8 +224,9 @@ void BagSolver::checkMap(Node n)
Assert(n.getKind() == BAG_MAP);
const set<Node>& downwards = d_state.getElements(n);
const set<Node>& upwards = d_state.getElements(n[1]);
- for (const Node& y : downwards)
+ for (const Node& z : downwards)
{
+ Node y = d_state.getRepresentative(z);
if (d_mapCache.count(n) && d_mapCache[n].get()->contains(y))
{
continue;
diff --git a/src/theory/bags/bags_rewriter.cpp b/src/theory/bags/bags_rewriter.cpp
index 766731806..a5fb206aa 100644
--- a/src/theory/bags/bags_rewriter.cpp
+++ b/src/theory/bags/bags_rewriter.cpp
@@ -45,8 +45,8 @@ BagsRewriter::BagsRewriter(HistogramStat<Rewrite>* statistics)
: d_statistics(statistics)
{
d_nm = NodeManager::currentNM();
- d_zero = d_nm->mkConst(CONST_RATIONAL, Rational(0));
- d_one = d_nm->mkConst(CONST_RATIONAL, Rational(1));
+ d_zero = d_nm->mkConstInt(Rational(0));
+ d_one = d_nm->mkConstInt(Rational(1));
}
RewriteResponse BagsRewriter::postRewrite(TNode n)
diff --git a/src/theory/bags/inference_generator.cpp b/src/theory/bags/inference_generator.cpp
index a433ceb2d..cb6a3ea70 100644
--- a/src/theory/bags/inference_generator.cpp
+++ b/src/theory/bags/inference_generator.cpp
@@ -36,8 +36,8 @@ InferenceGenerator::InferenceGenerator(SolverState* state, InferenceManager* im)
d_nm = NodeManager::currentNM();
d_sm = d_nm->getSkolemManager();
d_true = d_nm->mkConst(true);
- d_zero = d_nm->mkConst(CONST_RATIONAL, Rational(0));
- d_one = d_nm->mkConst(CONST_RATIONAL, Rational(1));
+ d_zero = d_nm->mkConstInt(Rational(0));
+ d_one = d_nm->mkConstInt(Rational(1));
}
InferInfo InferenceGenerator::nonNegativeCount(Node n, Node e)
diff --git a/src/theory/bags/normal_form.cpp b/src/theory/bags/normal_form.cpp
index 9a510c6f5..6cf26d357 100644
--- a/src/theory/bags/normal_form.cpp
+++ b/src/theory/bags/normal_form.cpp
@@ -201,14 +201,10 @@ Node NormalForm::constructConstantBagFromElements(
}
TypeNode elementType = t.getBagElementType();
std::map<Node, Rational>::const_reverse_iterator it = elements.rbegin();
- Node bag = nm->mkBag(elementType,
- it->first,
- nm->mkConst<Rational>(CONST_RATIONAL, it->second));
+ Node bag = nm->mkBag(elementType, it->first, nm->mkConstInt(it->second));
while (++it != elements.rend())
{
- Node n = nm->mkBag(elementType,
- it->first,
- nm->mkConst<Rational>(CONST_RATIONAL, it->second));
+ Node n = nm->mkBag(elementType, it->first, nm->mkConstInt(it->second));
bag = nm->mkNode(BAG_UNION_DISJOINT, n, bag);
}
return bag;
@@ -261,10 +257,10 @@ Node NormalForm::evaluateBagCount(TNode n)
NodeManager* nm = NodeManager::currentNM();
if (it != elements.end())
{
- Node count = nm->mkConst(CONST_RATIONAL, it->second);
+ Node count = nm->mkConstInt(it->second);
return count;
}
- return nm->mkConst(CONST_RATIONAL, Rational(0));
+ return nm->mkConstInt(Rational(0));
}
Node NormalForm::evaluateDuplicateRemoval(TNode n)
@@ -592,7 +588,7 @@ Node NormalForm::evaluateCard(TNode n)
}
NodeManager* nm = NodeManager::currentNM();
- Node sumNode = nm->mkConst(CONST_RATIONAL, sum);
+ Node sumNode = nm->mkConstInt(sum);
return sumNode;
}
diff --git a/src/theory/bags/solver_state.cpp b/src/theory/bags/solver_state.cpp
index 5c7c1dd73..ad817062f 100644
--- a/src/theory/bags/solver_state.cpp
+++ b/src/theory/bags/solver_state.cpp
@@ -43,7 +43,7 @@ void SolverState::registerBag(TNode n)
void SolverState::registerCountTerm(TNode n)
{
Assert(n.getKind() == BAG_COUNT);
- Node element = getRepresentative(n[0]);
+ Node element = n[0];
Node bag = getRepresentative(n[1]);
d_bagElements[bag].insert(element);
}
diff --git a/src/theory/bags/theory_bags.cpp b/src/theory/bags/theory_bags.cpp
index 68bdb7b1b..0694c179b 100644
--- a/src/theory/bags/theory_bags.cpp
+++ b/src/theory/bags/theory_bags.cpp
@@ -88,7 +88,18 @@ TrustNode TheoryBags::ppRewrite(TNode atom, std::vector<SkolemLemma>& lems)
switch (atom.getKind())
{
case kind::BAG_CHOOSE: return expandChooseOperator(atom, lems);
- case kind::BAG_CARD: return expandCardOperator(atom, lems);
+ case kind::BAG_CARD:
+ {
+ std::vector<Node> asserts;
+ Node ret = d_bagReduction.reduceCardOperator(atom, asserts);
+ NodeManager* nm = NodeManager::currentNM();
+ Node andNode = nm->mkNode(AND, asserts);
+ Trace("bags::ppr") << "reduce(" << atom << ") = " << ret
+ << " such that:" << std::endl
+ << andNode << std::endl;
+ d_im.lemma(andNode, InferenceId::BAGS_CARD);
+ return TrustNode::mkTrustRewrite(atom, ret, nullptr);
+ }
case kind::BAG_FOLD:
{
std::vector<Node> asserts;
@@ -98,7 +109,7 @@ TrustNode TheoryBags::ppRewrite(TNode atom, std::vector<SkolemLemma>& lems)
d_im.lemma(andNode, InferenceId::BAGS_FOLD);
Trace("bags::ppr") << "reduce(" << atom << ") = " << ret
<< " such that:" << std::endl
- << asserts << std::endl;
+ << andNode << std::endl;
return TrustNode::mkTrustRewrite(atom, ret, nullptr);
}
default: return TrustNode::null();
@@ -134,7 +145,7 @@ TrustNode TheoryBags::expandChooseOperator(const Node& node,
Node emptyBag = nm->mkConst(EmptyBag(bagType));
Node isEmpty = A.eqNode(emptyBag);
Node count = nm->mkNode(BAG_COUNT, x, A);
- Node one = nm->mkConst(CONST_RATIONAL, Rational(1));
+ Node one = nm->mkConstInt(Rational(1));
Node geqOne = nm->mkNode(GEQ, count, one);
Node geqOneAndEqual = geqOne.andNode(equal);
Node ite = nm->mkNode(ITE, isEmpty, equal, geqOneAndEqual);
@@ -145,27 +156,6 @@ TrustNode TheoryBags::expandChooseOperator(const Node& node,
return TrustNode::mkTrustRewrite(node, ret, nullptr);
}
-TrustNode TheoryBags::expandCardOperator(TNode n, std::vector<SkolemLemma>&)
-{
- Assert(n.getKind() == BAG_CARD);
- if (d_env.getLogicInfo().isHigherOrder())
- {
- // (bag.card A) = (bag.count 1 (bag.map (lambda ((x E)) 1) A)),
- // where E is the type of elements of A
- NodeManager* nm = NodeManager::currentNM();
- Node one = nm->mkConst(CONST_RATIONAL, Rational(1));
- TypeNode type = n[0].getType().getBagElementType();
- Node x = nm->mkBoundVar("x", type);
- Node lambda = nm->mkNode(LAMBDA, nm->mkNode(BOUND_VAR_LIST, x), one);
- Node map = nm->mkNode(kind::BAG_MAP, lambda, n[0]);
- Node countOne = nm->mkNode(kind::BAG_COUNT, one, map);
- Trace("TheoryBags::ppRewrite")
- << "ppRewrite(" << n << ") = " << countOne << std::endl;
- return TrustNode::mkTrustRewrite(n, countOne, nullptr);
- }
- return TrustNode::null();
-}
-
void TheoryBags::postCheck(Effort effort)
{
d_im.doPendingFacts();
@@ -270,7 +260,18 @@ bool TheoryBags::collectModelValues(TheoryModel* m,
{
Node key = d_state.getRepresentative(e);
Node countTerm = NodeManager::currentNM()->mkNode(BAG_COUNT, e, r);
- Node value = d_state.getRepresentative(countTerm);
+ context::CDList<TNode>::const_iterator shared_it =
+ std::find(d_sharedTerms.begin(), d_sharedTerms.end(), countTerm);
+ eq::EqClassIterator it =
+ eq::EqClassIterator(r, d_state.getEqualityEngine());
+ while (!it.isFinished() && shared_it == d_sharedTerms.end())
+ {
+ Node bag = *(++it);
+ countTerm = NodeManager::currentNM()->mkNode(BAG_COUNT, e, bag);
+ shared_it =
+ std::find(d_sharedTerms.begin(), d_sharedTerms.end(), countTerm);
+ }
+ Node value = d_valuation.getModelValue(countTerm);
elementReps[key] = value;
}
Node rep = NormalForm::constructBagFromElements(tn, elementReps);
diff --git a/src/theory/bags/theory_bags.h b/src/theory/bags/theory_bags.h
index 1a8af780e..8d15947ef 100644
--- a/src/theory/bags/theory_bags.h
+++ b/src/theory/bags/theory_bags.h
@@ -93,8 +93,6 @@ class TheoryBags : public Theory
/** expand the definition of the bag.choose operator */
TrustNode expandChooseOperator(const Node& node,
std::vector<SkolemLemma>& lems);
- /** expand the definition of bag.card operator */
- TrustNode expandCardOperator(TNode n, std::vector<SkolemLemma>& lems);
/** The state of the bags solver at full effort */
SolverState d_state;
diff --git a/src/theory/bags/theory_bags_type_enumerator.cpp b/src/theory/bags/theory_bags_type_enumerator.cpp
index 58a1b3291..0bfef55d2 100644
--- a/src/theory/bags/theory_bags_type_enumerator.cpp
+++ b/src/theory/bags/theory_bags_type_enumerator.cpp
@@ -57,7 +57,7 @@ Node BagEnumerator::operator*()
BagEnumerator& BagEnumerator::operator++()
{
// increase the multiplicity by one
- Node one = d_nodeManager->mkConst(CONST_RATIONAL, Rational(1));
+ Node one = d_nodeManager->mkConstInt(Rational(1));
TypeNode elementType = d_elementTypeEnumerator.getType();
Node singleton = d_nodeManager->mkBag(elementType, d_element, one);
if (d_currentBag.getKind() == kind::BAG_EMPTY)
diff --git a/src/theory/booleans/proof_circuit_propagator.cpp b/src/theory/booleans/proof_circuit_propagator.cpp
index 9190f423f..60ded97b6 100644
--- a/src/theory/booleans/proof_circuit_propagator.cpp
+++ b/src/theory/booleans/proof_circuit_propagator.cpp
@@ -31,9 +31,9 @@ namespace {
/** Shorthand to create a Node from a constant number */
template <typename T>
-Node mkRat(T val)
+Node mkInt(T val)
{
- return NodeManager::currentNM()->mkConst<Rational>(CONST_RATIONAL, val);
+ return NodeManager::currentNM()->mkConstInt(Rational(val));
}
/**
@@ -356,7 +356,7 @@ std::shared_ptr<ProofNode> ProofCircuitPropagatorBackward::andTrue(
return nullptr;
}
return mkProof(
- PfRule::AND_ELIM, {assume(d_parent)}, {mkRat(i - d_parent.begin())});
+ PfRule::AND_ELIM, {assume(d_parent)}, {mkInt(i - d_parent.begin())});
}
std::shared_ptr<ProofNode> ProofCircuitPropagatorBackward::orFalse(
@@ -368,7 +368,7 @@ std::shared_ptr<ProofNode> ProofCircuitPropagatorBackward::orFalse(
}
return mkNot(mkProof(PfRule::NOT_OR_ELIM,
{assume(d_parent.notNode())},
- {mkRat(i - d_parent.begin())}));
+ {mkInt(i - d_parent.begin())}));
}
std::shared_ptr<ProofNode> ProofCircuitPropagatorBackward::iteC(bool c)
@@ -463,7 +463,7 @@ std::shared_ptr<ProofNode> ProofCircuitPropagatorForward::andOneFalse()
auto it = std::find(d_parent.begin(), d_parent.end(), d_child);
return mkResolution(
mkProof(
- PfRule::CNF_AND_POS, {}, {d_parent, mkRat(it - d_parent.begin())}),
+ PfRule::CNF_AND_POS, {}, {d_parent, mkInt(it - d_parent.begin())}),
d_child,
true);
}
@@ -476,7 +476,7 @@ std::shared_ptr<ProofNode> ProofCircuitPropagatorForward::orOneTrue()
}
auto it = std::find(d_parent.begin(), d_parent.end(), d_child);
return mkNot(mkResolution(
- mkProof(PfRule::CNF_OR_NEG, {}, {d_parent, mkRat(it - d_parent.begin())}),
+ mkProof(PfRule::CNF_OR_NEG, {}, {d_parent, mkInt(it - d_parent.begin())}),
d_child,
false));
}
diff --git a/src/theory/builtin/proof_checker.cpp b/src/theory/builtin/proof_checker.cpp
index 9c05407b7..1c714b856 100644
--- a/src/theory/builtin/proof_checker.cpp
+++ b/src/theory/builtin/proof_checker.cpp
@@ -43,6 +43,7 @@ void BuiltinProofRuleChecker::registerTo(ProofChecker* pc)
pc->registerChecker(PfRule::MACRO_SR_PRED_ELIM, this);
pc->registerChecker(PfRule::MACRO_SR_PRED_TRANSFORM, this);
pc->registerChecker(PfRule::THEORY_REWRITE, this);
+ pc->registerChecker(PfRule::ANNOTATION, this);
pc->registerChecker(PfRule::REMOVE_TERM_FORMULA_AXIOM, this);
// trusted rules
pc->registerTrustedChecker(PfRule::THEORY_LEMMA, this, 1);
@@ -381,6 +382,11 @@ Node BuiltinProofRuleChecker::checkInternal(PfRule id,
Assert(args[0].getType().isBoolean());
return args[0];
}
+ else if (id == PfRule::ANNOTATION)
+ {
+ Assert(children.size() == 1);
+ return children[0];
+ }
// no rule
return Node::null();
@@ -399,8 +405,8 @@ bool BuiltinProofRuleChecker::getTheoryId(TNode n, TheoryId& tid)
Node BuiltinProofRuleChecker::mkTheoryIdNode(TheoryId tid)
{
- return NodeManager::currentNM()->mkConst(
- CONST_RATIONAL, Rational(static_cast<uint32_t>(tid)));
+ return NodeManager::currentNM()->mkConstInt(
+ Rational(static_cast<uint32_t>(tid)));
}
} // namespace builtin
diff --git a/src/theory/bv/int_blaster.cpp b/src/theory/bv/int_blaster.cpp
index 649be5aab..58c12ceff 100644
--- a/src/theory/bv/int_blaster.cpp
+++ b/src/theory/bv/int_blaster.cpp
@@ -48,8 +48,7 @@ Rational intpow2(uint64_t b) { return Rational(Integer(2).pow(b), Integer(1)); }
IntBlaster::IntBlaster(Env& env,
options::SolveBVAsIntMode mode,
- uint64_t granularity,
- bool introduceFreshIntVars)
+ uint64_t granularity)
: EnvObj(env),
d_binarizeCache(userContext()),
d_intblastCache(userContext()),
@@ -57,12 +56,11 @@ IntBlaster::IntBlaster(Env& env,
d_bitwiseAssertions(userContext()),
d_mode(mode),
d_granularity(granularity),
- d_context(userContext()),
- d_introduceFreshIntVars(introduceFreshIntVars)
+ d_context(userContext())
{
d_nm = NodeManager::currentNM();
- d_zero = d_nm->mkConst(CONST_RATIONAL, Rational(0));
- d_one = d_nm->mkConst(CONST_RATIONAL, Rational(1));
+ d_zero = d_nm->mkConstInt(0);
+ d_one = d_nm->mkConstInt(1);
};
IntBlaster::~IntBlaster() {}
@@ -108,18 +106,18 @@ Node IntBlaster::maxInt(uint64_t k)
{
Assert(k > 0);
Rational max_value = intpow2(k) - 1;
- return d_nm->mkConst(CONST_RATIONAL, max_value);
+ return d_nm->mkConstInt(max_value);
}
Node IntBlaster::pow2(uint64_t k)
{
Assert(k >= 0);
- return d_nm->mkConst(CONST_RATIONAL, intpow2(k));
+ return d_nm->mkConstInt(intpow2(k));
}
Node IntBlaster::modpow2(Node n, uint64_t exponent)
{
- Node p2 = d_nm->mkConst(CONST_RATIONAL, intpow2(exponent));
+ Node p2 = d_nm->mkConstInt(intpow2(exponent));
return d_nm->mkNode(kind::INTS_MODULUS_TOTAL, n, p2);
}
@@ -547,6 +545,11 @@ Node IntBlaster::translateWithChildren(
case kind::BOUND_VAR_LIST:
{
returnNode = d_nm->mkNode(oldKind, translated_children);
+ if (d_mode == options::SolveBVAsIntMode::BITWISE)
+ {
+ throw OptionException(
+ "--solve-bv-as-int=bitwise does not support quantifiers");
+ }
break;
}
case kind::FORALL:
@@ -588,7 +591,7 @@ Node IntBlaster::uts(Node x, uint64_t bvsize)
{
Node powNode = pow2(bvsize - 1);
Node modNode = d_nm->mkNode(kind::INTS_MODULUS_TOTAL, x, powNode);
- Node two = d_nm->mkConst(CONST_RATIONAL, Rational(2));
+ Node two = d_nm->mkConstInt(Rational(2));
Node twoTimesNode = d_nm->mkNode(kind::MULT, two, modNode);
return d_nm->mkNode(kind::MINUS, twoTimesNode, x);
}
@@ -615,7 +618,7 @@ Node IntBlaster::createSignExtendNode(Node x, uint64_t bvsize, uint64_t amount)
Rational max_of_amount = intpow2(amount) - 1;
Rational mul = max_of_amount * intpow2(bvsize);
Rational sum = mul + c;
- returnNode = d_nm->mkConst(CONST_RATIONAL, sum);
+ returnNode = d_nm->mkConstInt(sum);
}
}
else
@@ -627,7 +630,7 @@ Node IntBlaster::createSignExtendNode(Node x, uint64_t bvsize, uint64_t amount)
else
{
Rational twoToKMinusOne(intpow2(bvsize - 1));
- Node minSigned = d_nm->mkConst(CONST_RATIONAL, twoToKMinusOne);
+ Node minSigned = d_nm->mkConstInt(twoToKMinusOne);
/* condition checks whether the msb is 1.
* This holds when the integer value is smaller than
* 100...0, which is 2^{bvsize-1}.
@@ -673,38 +676,18 @@ Node IntBlaster::translateNoChildren(Node original,
}
else
{
- // original is a bit-vector variable (symbolic constant).
- // Either we translate it to a fresh integer variable,
- // or we translate it to (bv2nat original).
- // In the former case, we must include range lemmas, while in the
- // latter we don't.
- // This is determined by the option bv-to-int-fresh-vars.
- // The variables intCast and bvCast are used for models:
- // even if we introduce a fresh variable,
- // it is associated with intCast (which is (bv2nat original)).
- // bvCast is either ( (_ nat2bv k) original) or just original.
Node intCast = castToType(original, d_nm->integerType());
Node bvCast;
- if (d_introduceFreshIntVars)
- {
- // we introduce a fresh variable, add range constraints, and save the
- // connection between original and the new variable via intCast
- translation = d_nm->getSkolemManager()->mkPurifySkolem(
- intCast,
- "__intblast__var",
- "Variable introduced in intblasting for " + original.toString());
- uint64_t bvsize = original.getType().getBitVectorSize();
- addRangeConstraint(translation, bvsize, lemmas);
- // put new definition of old variable in skolems
- bvCast = castToType(translation, original.getType());
- }
- else
- {
- // we just translate original to (bv2nat original)
- translation = intCast;
- // no need to do any casting back to bit-vector in this case.
- bvCast = original;
- }
+ // we introduce a fresh variable, add range constraints, and save the
+ // connection between original and the new variable via intCast
+ translation = d_nm->getSkolemManager()->mkPurifySkolem(
+ intCast,
+ "__intblast__var",
+ "Variable introduced in intblasting for " + original.toString());
+ uint64_t bvsize = original.getType().getBitVectorSize();
+ addRangeConstraint(translation, bvsize, lemmas);
+ // put new definition of old variable in skolems
+ bvCast = castToType(translation, original.getType());
// add bvCast to skolems if it is not already there.
if (skolems.find(original) == skolems.end())
@@ -737,7 +720,7 @@ Node IntBlaster::translateNoChildren(Node original,
BitVector constant(original.getConst<BitVector>());
Integer c = constant.toInteger();
Rational r = Rational(c, Integer(1));
- translation = d_nm->mkConst(CONST_RATIONAL, r);
+ translation = d_nm->mkConstInt(r);
}
else
{
@@ -916,9 +899,7 @@ Node IntBlaster::createShiftNode(std::vector<Node> children,
ite = d_nm->mkNode(
kind::ITE,
d_nm->mkNode(
- kind::EQUAL,
- y,
- d_nm->mkConst(CONST_RATIONAL, Rational(Integer(i), Integer(1)))),
+ kind::EQUAL, y, d_nm->mkConstInt(Rational(Integer(i), Integer(1)))),
body,
ite);
}
@@ -1008,6 +989,38 @@ Node IntBlaster::createBVAndNode(Node x,
// Construct a sum of ites, based on granularity.
returnNode = d_iandUtils.createSumNode(x, y, bvsize, d_granularity);
}
+ else
+ {
+ Assert(d_mode == options::SolveBVAsIntMode::BITWISE);
+ // Enforce semantics over individual bits with iextract and ites
+ uint64_t granularity = options().smt.BVAndIntegerGranularity;
+
+ Node iAndOp = d_nm->mkConst(IntAnd(bvsize));
+ Node iAnd = d_nm->mkNode(kind::IAND, iAndOp, x, y);
+ // get a skolem so the IAND solver knows not to do work
+ returnNode = d_nm->getSkolemManager()->mkPurifySkolem(
+ iAnd,
+ "__intblast__iand",
+ "skolem for an IAND node in bitwise mode " + iAnd.toString());
+ addRangeConstraint(returnNode, bvsize, lemmas);
+
+ // eagerly add bitwise lemmas according to the provided granularity
+ uint64_t high_bit;
+ for (uint64_t j = 0; j < bvsize; j += granularity)
+ {
+ high_bit = j + granularity - 1;
+ // don't let high_bit pass bvsize
+ if (high_bit >= bvsize)
+ {
+ high_bit = bvsize - 1;
+ }
+ Node extractedReturnNode = d_iandUtils.iextract(high_bit, j, returnNode);
+ addBitwiseConstraint(
+ extractedReturnNode.eqNode(
+ d_iandUtils.createBitwiseIAndNode(x, y, high_bit, j)),
+ lemmas);
+ }
+ }
return returnNode;
}
diff --git a/src/theory/bv/int_blaster.h b/src/theory/bv/int_blaster.h
index ed8ed10c6..fb7291f6e 100644
--- a/src/theory/bv/int_blaster.h
+++ b/src/theory/bv/int_blaster.h
@@ -101,14 +101,12 @@ class IntBlaster : protected EnvObj
* @param context user context
* @param mode bv-to-int translation mode
* @param granularity bv-to-int translation granularity
- * @param introduceFreshIntVars determines whether bit-vector variables are
* translated to integer variables, or are directly casted using `bv2nat`
* operator. not purely bit-vector nodes.
*/
IntBlaster(Env& env,
options::SolveBVAsIntMode mode,
- uint64_t granluarity = 1,
- bool introduceFreshIntVars = true);
+ uint64_t granluarity = 1);
~IntBlaster();
@@ -371,11 +369,6 @@ class IntBlaster : protected EnvObj
/** an SolverEngine for context */
context::Context* d_context;
- /** true iff the translator should introduce
- * fresh integer variables for bit-vector variables.
- * Otherwise, we introduce a nat2bv term.
- */
- bool d_introduceFreshIntVars;
};
} // namespace cvc5
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 496a625ee..a8ac27a81 100644
--- a/src/theory/bv/theory_bv_rewrite_rules_operator_elimination.h
+++ b/src/theory/bv/theory_bv_rewrite_rules_operator_elimination.h
@@ -29,84 +29,6 @@ namespace cvc5 {
namespace theory {
namespace bv {
-/*
- * This rewrite is not meant to be used by the BV rewriter.
- * It is specifically designed for the bv-to-int preprocessing pass.
- * Based on Hacker's Delight section 2-2 equation a:
- * -x = ~x+1
- */
-template <>
-inline bool RewriteRule<NegEliminate>::applies(TNode node)
-{
- return (node.getKind() == kind::BITVECTOR_NEG);
-}
-
-template <>
-inline Node RewriteRule<NegEliminate>::apply(TNode node)
-{
- Debug("bv-rewrite") << "RewriteRule<NegEliminate>(" << node << ")"
- << std::endl;
- NodeManager* nm = NodeManager::currentNM();
- TNode a = node[0];
- unsigned size = utils::getSize(a);
- Node one = utils::mkOne(size);
- Node nota = nm->mkNode(kind::BITVECTOR_NOT, a);
- Node bvadd = nm->mkNode(kind::BITVECTOR_ADD, nota, one);
- return bvadd;
-}
-
-/*
- * This rewrite is not meant to be used by the BV rewriter.
- * It is specifically designed for the bv-to-int preprocessing pass.
- * Based on Hacker's Delight section 2-2 equation h:
- * x+y = x|y + x&y
- */
-template <>
-inline bool RewriteRule<OrEliminate>::applies(TNode node)
-{
- return (node.getKind() == kind::BITVECTOR_OR);
-}
-
-template <>
-inline Node RewriteRule<OrEliminate>::apply(TNode node)
-{
- Debug("bv-rewrite") << "RewriteRule<OrEliminate>(" << node << ")"
- << std::endl;
- NodeManager* nm = NodeManager::currentNM();
- TNode a = node[0];
- TNode b = node[1];
- Node bvadd = nm->mkNode(kind::BITVECTOR_ADD, a, b);
- Node bvand = nm->mkNode(kind::BITVECTOR_AND, a, b);
- Node result =
- nm->mkNode(kind::BITVECTOR_SUB, bvadd, bvand);
- return result;
-}
-
-/*
- * This rewrite is not meant to be used by the BV rewriter.
- * It is specifically designed for the bv-to-int preprocessing pass.
- * Based on Hacker's Delight section 2-2 equation n:
- * x xor y = x|y - x&y
- */
-template <>
-inline bool RewriteRule<XorEliminate>::applies(TNode node)
-{
- return (node.getKind() == kind::BITVECTOR_XOR);
-}
-
-template <>
-inline Node RewriteRule<XorEliminate>::apply(TNode node)
-{
- Debug("bv-rewrite") << "RewriteRule<XorEliminate>(" << node << ")"
- << std::endl;
- NodeManager* nm = NodeManager::currentNM();
- TNode a = node[0];
- TNode b = node[1];
- Node bvor = nm->mkNode(kind::BITVECTOR_OR, a, b);
- Node bvand = nm->mkNode(kind::BITVECTOR_AND, a, b);
- Node result = nm->mkNode(kind::BITVECTOR_SUB, bvor, bvand);
- return result;
-}
template <>
inline bool RewriteRule<UgtEliminate>::applies(TNode node)
diff --git a/src/theory/bv/theory_bv_utils.cpp b/src/theory/bv/theory_bv_utils.cpp
index adb067045..fd300fe41 100644
--- a/src/theory/bv/theory_bv_utils.cpp
+++ b/src/theory/bv/theory_bv_utils.cpp
@@ -467,7 +467,7 @@ Node eliminateBv2Nat(TNode node)
{
const unsigned size = utils::getSize(node[0]);
NodeManager* const nm = NodeManager::currentNM();
- const Node z = nm->mkConst(CONST_RATIONAL, Rational(0));
+ const Node z = nm->mkConstInt(Rational(0));
const Node bvone = utils::mkOne(1);
Integer i = 1;
@@ -478,8 +478,8 @@ Node eliminateBv2Nat(TNode node)
nm->mkNode(kind::EQUAL,
nm->mkNode(nm->mkConst(BitVectorExtract(bit, bit)), node[0]),
bvone);
- children.push_back(nm->mkNode(
- kind::ITE, cond, nm->mkConst(CONST_RATIONAL, Rational(i)), z));
+ children.push_back(
+ nm->mkNode(kind::ITE, cond, nm->mkConstInt(Rational(i)), z));
}
// avoid plus with one child
return children.size() == 1 ? children[0] : nm->mkNode(kind::PLUS, children);
@@ -496,11 +496,11 @@ Node eliminateInt2Bv(TNode node)
Integer i = 2;
while (v.size() < size)
{
- Node cond = nm->mkNode(kind::GEQ,
- nm->mkNode(kind::INTS_MODULUS_TOTAL,
- node[0],
- nm->mkConst(CONST_RATIONAL, Rational(i))),
- nm->mkConst(CONST_RATIONAL, Rational(i, 2)));
+ Node cond = nm->mkNode(
+ kind::GEQ,
+ nm->mkNode(
+ kind::INTS_MODULUS_TOTAL, node[0], nm->mkConstInt(Rational(i))),
+ nm->mkConstInt(Rational(i, 2)));
v.push_back(nm->mkNode(kind::ITE, cond, bvone, bvzero));
i *= 2;
}
diff --git a/src/theory/datatypes/datatypes_rewriter.cpp b/src/theory/datatypes/datatypes_rewriter.cpp
index 903a08bb4..196b4f01d 100644
--- a/src/theory/datatypes/datatypes_rewriter.cpp
+++ b/src/theory/datatypes/datatypes_rewriter.cpp
@@ -78,7 +78,7 @@ RewriteResponse DatatypesRewriter::postRewrite(TNode in)
const DType& dt = utils::datatypeOf(constructor);
const DTypeConstructor& c = dt[constructorIndex];
unsigned weight = c.getWeight();
- children.push_back(nm->mkConst(CONST_RATIONAL, Rational(weight)));
+ children.push_back(nm->mkConstInt(Rational(weight)));
Node res =
children.size() == 1 ? children[0] : nm->mkNode(kind::PLUS, children);
Trace("datatypes-rewrite")
@@ -104,9 +104,8 @@ RewriteResponse DatatypesRewriter::postRewrite(TNode in)
res = nm->mkConst(false);
break;
}
- children.push_back(nm->mkNode(kind::DT_HEIGHT_BOUND,
- in[0][i],
- nm->mkConst(CONST_RATIONAL, rmo)));
+ children.push_back(
+ nm->mkNode(kind::DT_HEIGHT_BOUND, in[0][i], nm->mkConstInt(rmo)));
}
}
if (res.isNull())
@@ -329,10 +328,7 @@ RewriteResponse DatatypesRewriter::preRewrite(TNode in)
// get the constructor object
const DTypeConstructor& dtc = utils::datatypeOf(op)[utils::indexOf(op)];
// create ascribed constructor type
- Node tc = NodeManager::currentNM()->mkConst(
- AscriptionType(dtc.getSpecializedConstructorType(tn)));
- Node op_new = NodeManager::currentNM()->mkNode(
- kind::APPLY_TYPE_ASCRIPTION, tc, op);
+ Node op_new = dtc.getInstantiatedConstructor(tn);
// make new node
std::vector<Node> children;
children.push_back(op_new);
@@ -891,7 +887,14 @@ TrustNode DatatypesRewriter::expandDefinition(Node n)
size_t cindex = utils::cindexOf(op);
const DTypeConstructor& dc = dt[cindex];
NodeBuilder b(APPLY_CONSTRUCTOR);
- b << dc.getConstructor();
+ if (tn.isParametricDatatype())
+ {
+ b << dc.getInstantiatedConstructor(n[0].getType());
+ }
+ else
+ {
+ b << dc.getConstructor();
+ }
Trace("dt-expand") << "Expand updater " << n << std::endl;
Trace("dt-expand") << "expr is " << n << std::endl;
Trace("dt-expand") << "updateIndex is " << updateIndex << std::endl;
diff --git a/src/theory/datatypes/infer_proof_cons.cpp b/src/theory/datatypes/infer_proof_cons.cpp
index 7ca58905f..4ed6e3da9 100644
--- a/src/theory/datatypes/infer_proof_cons.cpp
+++ b/src/theory/datatypes/infer_proof_cons.cpp
@@ -108,7 +108,7 @@ void InferProofCons::convert(InferenceId infer, TNode conc, TNode exp, CDProof*
}
if (argSuccess)
{
- narg = nm->mkConst(CONST_RATIONAL, Rational(i));
+ narg = nm->mkConstInt(Rational(i));
break;
}
}
@@ -141,7 +141,7 @@ void InferProofCons::convert(InferenceId infer, TNode conc, TNode exp, CDProof*
if (n >= 0)
{
Node t = exp[0];
- Node nn = nm->mkConst(CONST_RATIONAL, Rational(n));
+ Node nn = nm->mkConstInt(Rational(n));
Node eq = exp.eqNode(conc);
cdp->addStep(eq, PfRule::DT_INST, {}, {t, nn});
cdp->addStep(conc, PfRule::EQ_RESOLVE, {exp, eq}, {});
diff --git a/src/theory/datatypes/kinds b/src/theory/datatypes/kinds
index 5324e1c79..ee42add6b 100644
--- a/src/theory/datatypes/kinds
+++ b/src/theory/datatypes/kinds
@@ -107,10 +107,10 @@ operator DT_SIZE_BOUND 2 "datatypes height bound"
typerule DT_SIZE_BOUND ::cvc5::theory::datatypes::DtBoundTypeRule
operator DT_SYGUS_BOUND 2 "datatypes sygus bound"
-typerule DT_SYGUS_BOUND ::cvc5::theory::datatypes::DtSygusBoundTypeRule
+typerule DT_SYGUS_BOUND ::cvc5::theory::datatypes::DtBoundTypeRule
operator DT_SYGUS_EVAL 1: "datatypes sygus evaluation function"
-typerule DT_SYGUS_EVAL ::cvc5::theory::datatypes::DtSyguEvalTypeRule
+typerule DT_SYGUS_EVAL ::cvc5::theory::datatypes::DtSygusEvalTypeRule
# Kinds for match terms. For example, the match term
diff --git a/src/theory/datatypes/sygus_extension.cpp b/src/theory/datatypes/sygus_extension.cpp
index 88a3e43d7..90511112c 100644
--- a/src/theory/datatypes/sygus_extension.cpp
+++ b/src/theory/datatypes/sygus_extension.cpp
@@ -57,7 +57,7 @@ SygusExtension::SygusExtension(Env& env,
d_active_terms(context()),
d_currTermSize(context())
{
- d_zero = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(0));
+ d_zero = NodeManager::currentNM()->mkConstInt(Rational(0));
d_true = NodeManager::currentNM()->mkConst(true);
}
@@ -1772,8 +1772,8 @@ Node SygusExtension::SygusSizeDecisionStrategy::getOrMkMeasureValue()
NodeManager* nm = NodeManager::currentNM();
SkolemManager* sm = nm->getSkolemManager();
d_measure_value = sm->mkDummySkolem("mt", nm->integerType());
- Node mtlem = nm->mkNode(
- kind::GEQ, d_measure_value, nm->mkConst(CONST_RATIONAL, Rational(0)));
+ Node mtlem =
+ nm->mkNode(kind::GEQ, d_measure_value, nm->mkConstInt(Rational(0)));
d_im.lemma(mtlem, InferenceId::DATATYPES_SYGUS_MT_POS);
}
return d_measure_value;
@@ -1787,8 +1787,7 @@ Node SygusExtension::SygusSizeDecisionStrategy::getOrMkActiveMeasureValue(
NodeManager* nm = NodeManager::currentNM();
SkolemManager* sm = nm->getSkolemManager();
Node new_mt = sm->mkDummySkolem("mt", nm->integerType());
- Node mtlem =
- nm->mkNode(kind::GEQ, new_mt, nm->mkConst(CONST_RATIONAL, Rational(0)));
+ Node mtlem = nm->mkNode(kind::GEQ, new_mt, nm->mkConstInt(Rational(0)));
d_measure_value_active = new_mt;
d_im.lemma(mtlem, InferenceId::DATATYPES_SYGUS_MT_POS);
}
@@ -1817,8 +1816,7 @@ Node SygusExtension::SygusSizeDecisionStrategy::mkLiteral(unsigned s)
NodeManager* nm = NodeManager::currentNM();
Trace("sygus-engine") << "******* Sygus : allocate size literal " << s
<< " for " << d_this << std::endl;
- return nm->mkNode(
- DT_SYGUS_BOUND, d_this, nm->mkConst(CONST_RATIONAL, Rational(s)));
+ return nm->mkNode(DT_SYGUS_BOUND, d_this, nm->mkConstInt(Rational(s)));
}
int SygusExtension::getGuardStatus( Node g ) {
diff --git a/src/theory/datatypes/sygus_simple_sym.cpp b/src/theory/datatypes/sygus_simple_sym.cpp
index 1b5e37bc3..4826e87bc 100644
--- a/src/theory/datatypes/sygus_simple_sym.cpp
+++ b/src/theory/datatypes/sygus_simple_sym.cpp
@@ -245,7 +245,7 @@ bool SygusSimpleSymBreak::considerArgKind(
rt.d_children[0].d_req_kind = PLUS;
rt.d_children[0].d_children[0].d_req_type = dt[c].getArgType(1);
rt.d_children[0].d_children[1].d_req_const =
- NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(1));
+ NodeManager::currentNM()->mkConstInt(Rational(1));
rt.d_children[1].d_req_type = dt[c].getArgType(0);
}
else if (k == LT || k == GEQ)
@@ -256,7 +256,7 @@ bool SygusSimpleSymBreak::considerArgKind(
rt.d_children[1].d_req_kind = PLUS;
rt.d_children[1].d_children[0].d_req_type = dt[c].getArgType(0);
rt.d_children[1].d_children[1].d_req_const =
- NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(1));
+ NodeManager::currentNM()->mkConstInt(Rational(1));
}
}
else if (pk == BITVECTOR_NOT)
diff --git a/src/theory/datatypes/theory_datatypes.cpp b/src/theory/datatypes/theory_datatypes.cpp
index a9f0c3198..3f13886ed 100644
--- a/src/theory/datatypes/theory_datatypes.cpp
+++ b/src/theory/datatypes/theory_datatypes.cpp
@@ -68,7 +68,7 @@ TheoryDatatypes::TheoryDatatypes(Env& env,
{
d_true = NodeManager::currentNM()->mkConst( true );
- d_zero = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(0));
+ d_zero = NodeManager::currentNM()->mkConstInt(Rational(0));
d_dtfCounter = 0;
// indicate we are using the default theory state object
@@ -1244,7 +1244,7 @@ bool TheoryDatatypes::collectModelValues(TheoryModel* m,
for( unsigned i=0; i<pcons.size(); i++ ){
// must try the infinite ones first
bool cfinite =
- d_env.isFiniteType(dt[i].getSpecializedConstructorType(tt));
+ d_env.isFiniteType(dt[i].getInstantiatedConstructorType(tt));
if( pcons[i] && (r==1)==cfinite ){
neqc = utils::getInstCons(eqc, dt, i);
break;
diff --git a/src/theory/datatypes/theory_datatypes_type_rules.cpp b/src/theory/datatypes/theory_datatypes_type_rules.cpp
index 86a11357b..422af1731 100644
--- a/src/theory/datatypes/theory_datatypes_type_rules.cpp
+++ b/src/theory/datatypes/theory_datatypes_type_rules.cpp
@@ -36,6 +36,10 @@ TypeNode DatatypeConstructorTypeRule::computeType(NodeManager* nodeManager,
{
Assert(n.getKind() == kind::APPLY_CONSTRUCTOR);
TypeNode consType = n.getOperator().getType(check);
+ if (!consType.isConstructor())
+ {
+ throw TypeCheckingExceptionPrivate(n, "expected constructor to apply");
+ }
TypeNode t = consType.getConstructorRangeType();
Assert(t.isDatatype());
TNode::iterator child_it = n.begin();
@@ -215,16 +219,17 @@ TypeNode DatatypeUpdateTypeRule::computeType(NodeManager* nodeManager,
Assert(updType.getNumChildren() == 2);
if (check)
{
+ TypeNode t = updType[0];
for (size_t i = 0; i < 2; i++)
{
TypeNode childType = n[i].getType(check);
- TypeNode t = updType[i];
+ TypeNode targ = updType[i];
+ Trace("typecheck-idt") << "typecheck update: " << n << "[" << i
+ << "]: " << targ << " " << childType << std::endl;
if (t.isParametricDatatype())
{
- Debug("typecheck-idt")
- << "typecheck parameterized update: " << n << std::endl;
TypeMatcher m(t);
- if (!m.doMatching(t, childType))
+ if (!m.doMatching(targ, childType))
{
throw TypeCheckingExceptionPrivate(
n,
@@ -233,9 +238,7 @@ TypeNode DatatypeUpdateTypeRule::computeType(NodeManager* nodeManager,
}
else
{
- Debug("typecheck-idt") << "typecheck update: " << n << std::endl;
- Debug("typecheck-idt") << "test type: " << updType << std::endl;
- if (!t.isComparableTo(childType))
+ if (!targ.isComparableTo(childType))
{
throw TypeCheckingExceptionPrivate(n, "bad type for update argument");
}
@@ -243,7 +246,7 @@ TypeNode DatatypeUpdateTypeRule::computeType(NodeManager* nodeManager,
}
}
// type is the first argument
- return updType[0];
+ return n[0].getType();
}
TypeNode DatatypeAscriptionTypeRule::computeType(NodeManager* nodeManager,
@@ -319,10 +322,10 @@ TypeNode DtBoundTypeRule::computeType(NodeManager* nodeManager,
throw TypeCheckingExceptionPrivate(
n, "expecting datatype bound term to have datatype argument.");
}
- if (n[1].getKind() != kind::CONST_RATIONAL)
+ if (!n[1].isConst() || !n[1].getType().isInteger())
{
- throw TypeCheckingExceptionPrivate(n,
- "datatype bound must be a constant");
+ throw TypeCheckingExceptionPrivate(
+ n, "datatype bound must be a constant integer");
}
if (n[1].getConst<Rational>().getNumerator().sgn() == -1)
{
@@ -333,34 +336,9 @@ TypeNode DtBoundTypeRule::computeType(NodeManager* nodeManager,
return nodeManager->booleanType();
}
-TypeNode DtSygusBoundTypeRule::computeType(NodeManager* nodeManager,
- TNode n,
- bool check)
-{
- if (check)
- {
- if (!n[0].getType().isDatatype())
- {
- throw TypeCheckingExceptionPrivate(
- n, "datatype sygus bound takes a datatype");
- }
- if (n[1].getKind() != kind::CONST_RATIONAL)
- {
- throw TypeCheckingExceptionPrivate(
- n, "datatype sygus bound must be a constant");
- }
- if (n[1].getConst<Rational>().getNumerator().sgn() == -1)
- {
- throw TypeCheckingExceptionPrivate(
- n, "datatype sygus bound must be non-negative");
- }
- }
- return nodeManager->booleanType();
-}
-
-TypeNode DtSyguEvalTypeRule::computeType(NodeManager* nodeManager,
- TNode n,
- bool check)
+TypeNode DtSygusEvalTypeRule::computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
{
TypeNode headType = n[0].getType(check);
if (!headType.isDatatype())
diff --git a/src/theory/datatypes/theory_datatypes_type_rules.h b/src/theory/datatypes/theory_datatypes_type_rules.h
index 7cf98aa74..3b1276221 100644
--- a/src/theory/datatypes/theory_datatypes_type_rules.h
+++ b/src/theory/datatypes/theory_datatypes_type_rules.h
@@ -64,12 +64,7 @@ class DtBoundTypeRule {
static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check);
};
-class DtSygusBoundTypeRule {
- public:
- static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check);
-};
-
-class DtSyguEvalTypeRule
+class DtSygusEvalTypeRule
{
public:
static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check);
diff --git a/src/theory/datatypes/theory_datatypes_utils.cpp b/src/theory/datatypes/theory_datatypes_utils.cpp
index 3b36ad2f2..a429f8333 100644
--- a/src/theory/datatypes/theory_datatypes_utils.cpp
+++ b/src/theory/datatypes/theory_datatypes_utils.cpp
@@ -63,12 +63,7 @@ Node mkApplyCons(TypeNode tn,
// add type ascription for ambiguous constructor types
Debug("datatypes-parametric")
<< "Constructor is " << dt[index] << std::endl;
- TypeNode tspec = dt[index].getSpecializedConstructorType(tn);
- Debug("datatypes-parametric")
- << "Type specification is " << tspec << std::endl;
- cchildren[0] = nm->mkNode(APPLY_TYPE_ASCRIPTION,
- nm->mkConst(AscriptionType(tspec)),
- cchildren[0]);
+ cchildren[0] = dt[index].getInstantiatedConstructor(tn);
}
return nm->mkNode(APPLY_CONSTRUCTOR, cchildren);
}
diff --git a/src/theory/datatypes/type_enumerator.cpp b/src/theory/datatypes/type_enumerator.cpp
index 6528f1052..69ebc9c78 100644
--- a/src/theory/datatypes/type_enumerator.cpp
+++ b/src/theory/datatypes/type_enumerator.cpp
@@ -143,11 +143,7 @@ Node DatatypesEnumerator::getTermEnum( TypeNode tn, unsigned i ){
NodeBuilder b(kind::APPLY_CONSTRUCTOR);
if (d_datatype.isParametric())
{
- NodeManager* nm = NodeManager::currentNM();
- TypeNode typ = ctor.getSpecializedConstructorType(d_type);
- b << nm->mkNode(kind::APPLY_TYPE_ASCRIPTION,
- nm->mkConst(AscriptionType(typ)),
- ctor.getConstructor());
+ b << ctor.getInstantiatedConstructor(d_type);
}
else
{
@@ -245,7 +241,7 @@ Node DatatypesEnumerator::getTermEnum( TypeNode tn, unsigned i ){
TypeNode typ;
if (d_datatype.isParametric())
{
- typ = ctor.getSpecializedConstructorType(d_type);
+ typ = ctor.getInstantiatedConstructorType(d_type);
}
for (unsigned a = 0; a < ctor.getNumArgs(); ++a)
{
diff --git a/src/theory/difficulty_manager.cpp b/src/theory/difficulty_manager.cpp
index 0a9eba60d..7714abfa9 100644
--- a/src/theory/difficulty_manager.cpp
+++ b/src/theory/difficulty_manager.cpp
@@ -26,20 +26,30 @@ namespace cvc5 {
namespace theory {
DifficultyManager::DifficultyManager(context::Context* c, Valuation val)
- : d_val(val), d_dfmap(c)
+ : d_input(c), d_val(val), d_dfmap(c)
{
}
+void DifficultyManager::notifyInputAssertions(
+ const std::vector<Node>& assertions)
+{
+ for (const Node& a : assertions)
+ {
+ d_input.insert(a);
+ }
+}
+
void DifficultyManager::getDifficultyMap(std::map<Node, Node>& dmap)
{
NodeManager* nm = NodeManager::currentNM();
for (const std::pair<const Node, uint64_t> p : d_dfmap)
{
- dmap[p.first] = nm->mkConst(CONST_RATIONAL, Rational(p.second));
+ dmap[p.first] = nm->mkConstInt(Rational(p.second));
}
}
-void DifficultyManager::notifyLemma(const std::map<TNode, TNode>& rse, Node n)
+void DifficultyManager::notifyLemma(const context::CDHashMap<Node, Node>& rse,
+ Node n)
{
if (options::difficultyMode() != options::DifficultyMode::LEMMA_LITERAL)
{
@@ -63,7 +73,7 @@ void DifficultyManager::notifyLemma(const std::map<TNode, TNode>& rse, Node n)
{
litsToCheck.push_back(n);
}
- std::map<TNode, TNode>::const_iterator it;
+ context::CDHashMap<Node, Node>::const_iterator it;
for (TNode nc : litsToCheck)
{
bool pol = nc.getKind() != kind::NOT;
@@ -72,23 +82,23 @@ void DifficultyManager::notifyLemma(const std::map<TNode, TNode>& rse, Node n)
Trace("diff-man-debug")
<< "Check literal: " << atom << ", has reason = " << (it != rse.end())
<< std::endl;
- if (it != rse.end())
+ // must be an input assertion
+ if (it != rse.end() && d_input.find(it->second) != d_input.end())
{
incrementDifficulty(it->second);
}
}
}
-void DifficultyManager::notifyCandidateModel(const NodeList& input,
- TheoryModel* m)
+void DifficultyManager::notifyCandidateModel(TheoryModel* m)
{
if (options::difficultyMode() != options::DifficultyMode::MODEL_CHECK)
{
return;
}
Trace("diff-man") << "DifficultyManager::notifyCandidateModel, #input="
- << input.size() << std::endl;
- for (const Node& a : input)
+ << d_input.size() << std::endl;
+ for (const Node& a : d_input)
{
// should have miniscoped the assertions upstream
Assert(a.getKind() != kind::AND);
diff --git a/src/theory/difficulty_manager.h b/src/theory/difficulty_manager.h
index 3030bcc9b..1437965fe 100644
--- a/src/theory/difficulty_manager.h
+++ b/src/theory/difficulty_manager.h
@@ -19,7 +19,7 @@
#define CVC5__THEORY__DIFFICULTY_MANAGER__H
#include "context/cdhashmap.h"
-#include "context/cdlist.h"
+#include "context/cdhashset.h"
#include "expr/node.h"
#include "theory/valuation.h"
@@ -34,11 +34,13 @@ class TheoryModel;
*/
class DifficultyManager
{
- typedef context::CDList<Node> NodeList;
+ typedef context::CDHashSet<Node> NodeSet;
typedef context::CDHashMap<Node, uint64_t> NodeUIntMap;
public:
DifficultyManager(context::Context* c, Valuation val);
+ /** Notify input assertions */
+ void notifyInputAssertions(const std::vector<Node>& assertions);
/**
* Get difficulty map, which populates dmap mapping preprocessed assertions
* to a difficulty measure (a constant integer).
@@ -56,19 +58,23 @@ class DifficultyManager
* the reason why that literal was relevant in the current context
* @param lem The lemma
*/
- void notifyLemma(const std::map<TNode, TNode>& rse, Node lem);
+ void notifyLemma(const context::CDHashMap<Node, Node>& rse, Node lem);
/**
* Notify that `m` is a (candidate) model. This increments the difficulty
* of assertions that are not satisfied by that model.
*
- * @param input The list of preprocessed assertions
* @param m The candidate model.
*/
- void notifyCandidateModel(const NodeList& input, TheoryModel* m);
+ void notifyCandidateModel(TheoryModel* m);
private:
/** Increment difficulty on assertion a */
void incrementDifficulty(TNode a, uint64_t amount = 1);
+ /**
+ * The input assertions, tracked to ensure we do not increment difficulty
+ * on lemmas.
+ */
+ NodeSet d_input;
/** The valuation object, used to query current value of theory literals */
Valuation d_val;
/**
diff --git a/src/theory/evaluator.cpp b/src/theory/evaluator.cpp
index 27e67dd9f..9451f9995 100644
--- a/src/theory/evaluator.cpp
+++ b/src/theory/evaluator.cpp
@@ -458,6 +458,29 @@ EvalResult Evaluator::evalInternal(
results[currNode] = EvalResult(res);
break;
}
+ case kind::DIVISION:
+ case kind::DIVISION_TOTAL:
+ {
+ Rational res = results[currNode[0]].d_rat;
+ bool divbyzero = false;
+ for (size_t i = 1, end = currNode.getNumChildren(); i < end; i++)
+ {
+ if (results[currNode[i]].d_rat.isZero())
+ {
+ Trace("evaluator")
+ << "Division by zero not supported" << std::endl;
+ divbyzero = true;
+ results[currNode] = EvalResult();
+ break;
+ }
+ res = res / results[currNode[i]].d_rat;
+ }
+ if (!divbyzero)
+ {
+ results[currNode] = EvalResult(res);
+ }
+ break;
+ }
case kind::GEQ:
{
diff --git a/src/theory/ext_theory.h b/src/theory/ext_theory.h
index 998dac146..ecd061e7c 100644
--- a/src/theory/ext_theory.h
+++ b/src/theory/ext_theory.h
@@ -77,6 +77,8 @@ enum class ExtReducedId
STRINGS_REGEXP_INCLUDE,
// subsumed due to RE inclusion reasoning for negative memberships
STRINGS_REGEXP_INCLUDE_NEG,
+ // reduction for seq.nth over seq.rev
+ STRINGS_NTH_REV,
};
/**
* Converts an ext reduced identifier to a string.
diff --git a/src/theory/fp/fp_word_blaster.h b/src/theory/fp/fp_word_blaster.h
index f9ec4fd4e..f7c7f26be 100644
--- a/src/theory/fp/fp_word_blaster.h
+++ b/src/theory/fp/fp_word_blaster.h
@@ -34,15 +34,6 @@
#include "util/floatingpoint_size.h"
#include "util/hash.h"
-#ifdef CVC5_SYM_SYMBOLIC_EVAL
-// This allows debugging of the cvc5 symbolic back-end.
-// By enabling this and disabling constant folding in the rewriter,
-// SMT files that have operations on constants will be evaluated
-// during the encoding step, which means that the expressions
-// generated by the symbolic back-end can be debugged with gdb.
-#include "theory/rewriter.h"
-#endif
-
namespace cvc5 {
namespace theory {
namespace fp {
@@ -100,16 +91,7 @@ typedef traits::bwt bwt;
class nodeWrapper : public Node
{
protected:
-/* CVC5_SYM_SYMBOLIC_EVAL is for debugging cvc5 symbolic back-end issues.
- * Enable this and disabling constant folding will mean that operations
- * that are input with constant args are 'folded' using the symbolic encoding
- * allowing them to be traced via GDB.
- */
-#ifdef CVC5_SYM_SYMBOLIC_EVAL
- nodeWrapper(const Node& n) : Node(theory::Rewriter::rewrite(n)) {}
-#else
nodeWrapper(const Node& n) : Node(n) {}
-#endif
};
class symbolicProposition : public nodeWrapper
diff --git a/src/theory/incomplete_id.cpp b/src/theory/incomplete_id.cpp
index c763fb9a0..b1071b5ae 100644
--- a/src/theory/incomplete_id.cpp
+++ b/src/theory/incomplete_id.cpp
@@ -35,6 +35,8 @@ const char* toString(IncompleteId i)
return "QUANTIFIERS_RECORDED_INST";
case IncompleteId::QUANTIFIERS_MAX_INST_ROUNDS:
return "QUANTIFIERS_MAX_INST_ROUNDS";
+ case IncompleteId::QUANTIFIERS_SYGUS_SOLVED:
+ return "QUANTIFIERS_SYGUS_SOLVED";
case IncompleteId::SEP: return "SEP";
case IncompleteId::SETS_RELS_CARD: return "SETS_RELS_CARD";
case IncompleteId::STRINGS_LOOP_SKIP: return "STRINGS_LOOP_SKIP";
diff --git a/src/theory/incomplete_id.h b/src/theory/incomplete_id.h
index aaa458d8e..1e8bf155a 100644
--- a/src/theory/incomplete_id.h
+++ b/src/theory/incomplete_id.h
@@ -44,6 +44,9 @@ enum class IncompleteId
QUANTIFIERS_RECORDED_INST,
// incomplete due to limited number of allowed instantiation rounds
QUANTIFIERS_MAX_INST_ROUNDS,
+ // we solved a negated synthesis conjecture and will terminate as a subsolver
+ // with unknown
+ QUANTIFIERS_SYGUS_SOLVED,
// incomplete due to separation logic
SEP,
// relations were used in combination with set cardinality constraints
diff --git a/src/theory/inference_id.cpp b/src/theory/inference_id.cpp
index 56d2f0500..ced885abb 100644
--- a/src/theory/inference_id.cpp
+++ b/src/theory/inference_id.cpp
@@ -119,6 +119,7 @@ const char* toString(InferenceId i)
case InferenceId::BAGS_DUPLICATE_REMOVAL: return "BAGS_DUPLICATE_REMOVAL";
case InferenceId::BAGS_MAP: return "BAGS_MAP";
case InferenceId::BAGS_FOLD: return "BAGS_FOLD";
+ case InferenceId::BAGS_CARD: return "BAGS_CARD";
case InferenceId::BV_BITBLAST_CONFLICT: return "BV_BITBLAST_CONFLICT";
case InferenceId::BV_BITBLAST_INTERNAL_EAGER_LEMMA:
@@ -229,12 +230,6 @@ const char* toString(InferenceId i)
return "QUANTIFIERS_SYGUS_EXCLUDE_CURRENT";
case InferenceId::QUANTIFIERS_SYGUS_STREAM_EXCLUDE_CURRENT:
return "QUANTIFIERS_SYGUS_STREAM_EXCLUDE_CURRENT";
- case InferenceId::QUANTIFIERS_SYGUS_SI_SOLVED:
- return "QUANTIFIERS_SYGUS_SI_SOLVED";
- case InferenceId::QUANTIFIERS_SYGUS_SAMPLE_TRUST_SOLVED:
- return "QUANTIFIERS_SYGUS_SAMPLE_TRUST_SOLVED";
- case InferenceId::QUANTIFIERS_SYGUS_VERIFY_SOLVED:
- return "QUANTIFIERS_SYGUS_VERIFY_SOLVED";
case InferenceId::QUANTIFIERS_SYGUS_EXAMPLE_INFER_CONTRA:
return "QUANTIFIERS_SYGUS_EXAMPLE_INFER_CONTRA";
case InferenceId::QUANTIFIERS_SYGUS_UNIF_PI_INTER_ENUM_SB:
@@ -412,6 +407,11 @@ const char* toString(InferenceId i)
case InferenceId::STRINGS_ARRAY_NTH_UNIT: return "STRINGS_ARRAY_NTH_UNIT";
case InferenceId::STRINGS_ARRAY_NTH_CONCAT:
return "STRINGS_ARRAY_NTH_CONCAT";
+ case InferenceId::STRINGS_ARRAY_NTH_EXTRACT:
+ return "STRINGS_ARRAY_NTH_EXTRACT";
+ case InferenceId::STRINGS_ARRAY_NTH_UPDATE:
+ return "STRINGS_ARRAY_NTH_UPDATE";
+ case InferenceId::STRINGS_ARRAY_NTH_REV: return "STRINGS_ARRAY_NTH_REV";
case InferenceId::STRINGS_RE_NF_CONFLICT: return "STRINGS_RE_NF_CONFLICT";
case InferenceId::STRINGS_RE_UNFOLD_POS: return "STRINGS_RE_UNFOLD_POS";
case InferenceId::STRINGS_RE_UNFOLD_NEG: return "STRINGS_RE_UNFOLD_NEG";
@@ -470,8 +470,8 @@ std::ostream& operator<<(std::ostream& out, InferenceId i)
Node mkInferenceIdNode(InferenceId i)
{
- return NodeManager::currentNM()->mkConst(CONST_RATIONAL,
- Rational(static_cast<uint32_t>(i)));
+ return NodeManager::currentNM()->mkConstInt(
+ Rational(static_cast<uint32_t>(i)));
}
bool getInferenceId(TNode n, InferenceId& i)
diff --git a/src/theory/inference_id.h b/src/theory/inference_id.h
index d98d3ff25..f0c726f78 100644
--- a/src/theory/inference_id.h
+++ b/src/theory/inference_id.h
@@ -181,6 +181,7 @@ enum class InferenceId
BAGS_DUPLICATE_REMOVAL,
BAGS_MAP,
BAGS_FOLD,
+ BAGS_CARD,
// ---------------------------------- end bags theory
// ---------------------------------- bitvector theory
@@ -342,12 +343,6 @@ enum class InferenceId
QUANTIFIERS_SYGUS_EXCLUDE_CURRENT,
// manual exclusion of a current solution for sygus-stream
QUANTIFIERS_SYGUS_STREAM_EXCLUDE_CURRENT,
- // Q where Q was solved by a subcall to the single invocation module
- QUANTIFIERS_SYGUS_SI_SOLVED,
- // Q where Q was (trusted) solved by sampling
- QUANTIFIERS_SYGUS_SAMPLE_TRUST_SOLVED,
- // Q where Q was solved by a verification subcall
- QUANTIFIERS_SYGUS_VERIFY_SOLVED,
// ~Q where Q is a PBE conjecture with conflicting examples
QUANTIFIERS_SYGUS_EXAMPLE_INFER_CONTRA,
// unif+pi symmetry breaking between multiple enumerators
@@ -693,6 +688,12 @@ enum class InferenceId
STRINGS_ARRAY_NTH_UNIT,
// nth over conatenation
STRINGS_ARRAY_NTH_CONCAT,
+ // nth over extract
+ STRINGS_ARRAY_NTH_EXTRACT,
+ // nth over update
+ STRINGS_ARRAY_NTH_UPDATE,
+ // nth over reverse
+ STRINGS_ARRAY_NTH_REV,
//-------------------- regexp solver
// regular expression normal form conflict
// ( x in R ^ x = y ^ rewrite((str.in_re y R)) = false ) => false
diff --git a/src/theory/inference_id_proof_annotator.cpp b/src/theory/inference_id_proof_annotator.cpp
new file mode 100644
index 000000000..5af98c4bf
--- /dev/null
+++ b/src/theory/inference_id_proof_annotator.cpp
@@ -0,0 +1,55 @@
+/******************************************************************************
+ * Top contributors (to current version):
+ * Andrew Reynolds
+ *
+ * This file is part of the cvc5 project.
+ *
+ * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+ * in the top-level source directory and their institutional affiliations.
+ * All rights reserved. See the file COPYING in the top-level source
+ * directory for licensing information.
+ * ****************************************************************************
+ *
+ * The inference id annotator class.
+ */
+
+#include "theory/inference_id_proof_annotator.h"
+
+#include "proof/proof_node.h"
+#include "proof/proof_node_manager.h"
+
+namespace cvc5 {
+namespace theory {
+
+InferenceIdProofAnnotator::InferenceIdProofAnnotator(ProofNodeManager* pnm,
+ context::Context* c)
+ : d_pnm(pnm), d_ids(c), d_list(c)
+{
+}
+void InferenceIdProofAnnotator::setAnnotation(Node f, InferenceId id)
+{
+ d_ids[f] = id;
+}
+
+std::shared_ptr<ProofNode> InferenceIdProofAnnotator::annotate(
+ std::shared_ptr<ProofNode> p)
+{
+ Node f = p->getResult();
+ NodeInferenceIdMap::iterator it = d_ids.find(f);
+ if (it != d_ids.end())
+ {
+ std::vector<Node> pfArgs;
+ pfArgs.push_back(mkInferenceIdNode(it->second));
+ std::shared_ptr<ProofNode> pa =
+ d_pnm->mkNode(PfRule::ANNOTATION, {p}, pfArgs);
+ // for now, do a double annotation to make stats accurate
+ std::shared_ptr<ProofNode> paf =
+ d_pnm->mkNode(PfRule::ANNOTATION, {pa}, {});
+ d_list.push_back(paf);
+ return paf;
+ }
+ return p;
+}
+
+} // namespace theory
+} // namespace cvc5
diff --git a/src/theory/inference_id_proof_annotator.h b/src/theory/inference_id_proof_annotator.h
new file mode 100644
index 000000000..8346370f1
--- /dev/null
+++ b/src/theory/inference_id_proof_annotator.h
@@ -0,0 +1,64 @@
+/******************************************************************************
+ * Top contributors (to current version):
+ * Andrew Reynolds
+ *
+ * This file is part of the cvc5 project.
+ *
+ * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+ * in the top-level source directory and their institutional affiliations.
+ * All rights reserved. See the file COPYING in the top-level source
+ * directory for licensing information.
+ * ****************************************************************************
+ *
+ * The inference id annotator class.
+ */
+
+#include "cvc5_private.h"
+
+#ifndef CVC5__THEORY__INFERENCE_ID_PROOF_ANNOTATOR_H
+#define CVC5__THEORY__INFERENCE_ID_PROOF_ANNOTATOR_H
+
+#include "context/cdhashmap.h"
+#include "context/cdlist.h"
+#include "expr/node.h"
+#include "proof/annotation_proof_generator.h"
+#include "theory/inference_id.h"
+
+namespace cvc5 {
+namespace theory {
+
+/** A class that tracks formulas to inference id annotations */
+class InferenceIdProofAnnotator : public Annotator
+{
+ typedef context::CDHashMap<Node, InferenceId> NodeInferenceIdMap;
+ typedef context::CDList<std::shared_ptr<ProofNode>> ProofNodeList;
+
+ public:
+ InferenceIdProofAnnotator(ProofNodeManager* pnm, context::Context* c);
+ /** Set annotation, that formula f should be annotated by id */
+ void setAnnotation(Node f, InferenceId id);
+ /**
+ * Annotate the proof node with the appropriate inference ID. Given proof
+ * P proving F that was generated as a lemma with inference id `i`, this
+ * returns (ANNOTATION (ANNOTATION P : args i)). The outer ANNOTATION is
+ * used since commonly a proof node is "linked" into another, where its
+ * children and rule are copied into another. Using ANNOTATION (with no
+ * arguments) ensures the top-most ANNOTATION may be linked/copied
+ * multiple times; however its child (which counts `i`) will only appear
+ * once in the final proof.
+ */
+ std::shared_ptr<ProofNode> annotate(std::shared_ptr<ProofNode> p) override;
+
+ private:
+ /** The proof node manager of the theory */
+ ProofNodeManager* d_pnm;
+ /** The inference id for each formula */
+ NodeInferenceIdMap d_ids;
+ /** Ensure we keep proof nodes alive */
+ ProofNodeList d_list;
+};
+
+} // namespace theory
+} // namespace cvc5
+
+#endif /* CVC5__THEORY__INFERENCE_ID_PROOF_ANNOTATOR_H */
diff --git a/src/theory/inference_manager_buffered.cpp b/src/theory/inference_manager_buffered.cpp
index 8b4880feb..963e0b95c 100644
--- a/src/theory/inference_manager_buffered.cpp
+++ b/src/theory/inference_manager_buffered.cpp
@@ -161,14 +161,14 @@ std::size_t InferenceManagerBuffered::numPendingFacts() const
return d_pendingFact.size();
}
-void InferenceManagerBuffered::lemmaTheoryInference(TheoryInference* lem)
+bool InferenceManagerBuffered::lemmaTheoryInference(TheoryInference* lem)
{
// process this lemma
LemmaProperty p = LemmaProperty::NONE;
TrustNode tlem = lem->processLemma(p);
Assert(!tlem.isNull());
// send the lemma
- trustedLemma(tlem, lem->getId(), p);
+ return trustedLemma(tlem, lem->getId(), p);
}
void InferenceManagerBuffered::assertInternalFactTheoryInference(
diff --git a/src/theory/inference_manager_buffered.h b/src/theory/inference_manager_buffered.h
index e93152f72..579b1ae87 100644
--- a/src/theory/inference_manager_buffered.h
+++ b/src/theory/inference_manager_buffered.h
@@ -149,9 +149,10 @@ class InferenceManagerBuffered : public TheoryInferenceManager
/**
* Send the given theory inference as a lemma on the output channel of this
* inference manager. This calls TheoryInferenceManager::trustedLemma based
- * on the provided theory inference.
+ * on the provided theory inference, and returns true if the lemma was
+ * successfully sent.
*/
- void lemmaTheoryInference(TheoryInference* lem);
+ bool lemmaTheoryInference(TheoryInference* lem);
/**
* Add the given theory inference as an internal fact. This calls
* TheoryInferenceManager::assertInternalFact based on the provided theory
diff --git a/src/theory/quantifiers/cegqi/ceg_arith_instantiator.cpp b/src/theory/quantifiers/cegqi/ceg_arith_instantiator.cpp
index 2d483d502..56debbbac 100644
--- a/src/theory/quantifiers/cegqi/ceg_arith_instantiator.cpp
+++ b/src/theory/quantifiers/cegqi/ceg_arith_instantiator.cpp
@@ -818,7 +818,7 @@ CegTermType ArithInstantiator::solve_arith(CegInstantiator* ci,
// multiply by the coefficient we will isolate for
if (itv->second.isNull())
{
- vts_coeff[t] = ArithMSum::negate(vts_coeff[t]);
+ vts_coeff[t] = negate(vts_coeff[t]);
}
else
{
@@ -833,7 +833,7 @@ CegTermType ArithInstantiator::solve_arith(CegInstantiator* ci,
}
else if (itv->second.getConst<Rational>().sgn() == 1)
{
- vts_coeff[t] = ArithMSum::negate(vts_coeff[t]);
+ vts_coeff[t] = negate(vts_coeff[t]);
}
}
}
@@ -1040,6 +1040,13 @@ Node ArithInstantiator::getModelBasedProjectionValue(CegInstantiator* ci,
return val;
}
+Node ArithInstantiator::negate(const Node& t) const
+{
+ NodeManager* nm = NodeManager::currentNM();
+ return rewrite(
+ nm->mkNode(MULT, nm->mkConstRealOrInt(t.getType(), Rational(-1)), t));
+}
+
} // namespace quantifiers
} // namespace theory
} // namespace cvc5
diff --git a/src/theory/quantifiers/cegqi/ceg_arith_instantiator.h b/src/theory/quantifiers/cegqi/ceg_arith_instantiator.h
index e102b834e..d44ab4993 100644
--- a/src/theory/quantifiers/cegqi/ceg_arith_instantiator.h
+++ b/src/theory/quantifiers/cegqi/ceg_arith_instantiator.h
@@ -206,6 +206,8 @@ class ArithInstantiator : public Instantiator
Node theta,
Node inf_coeff,
Node delta_coeff);
+ /** Return the rewritten form of the negation of t */
+ Node negate(const Node& t) const;
};
} // namespace quantifiers
diff --git a/src/theory/quantifiers/cegqi/ceg_instantiator.cpp b/src/theory/quantifiers/cegqi/ceg_instantiator.cpp
index 9556d3f9c..81ae18f4f 100644
--- a/src/theory/quantifiers/cegqi/ceg_instantiator.cpp
+++ b/src/theory/quantifiers/cegqi/ceg_instantiator.cpp
@@ -163,8 +163,8 @@ void SolvedForm::push_back(Node pv, Node n, TermProperties& pv_prop)
}
else
{
- Assert(new_theta.getKind() == CONST_RATIONAL);
- Assert(pv_prop.d_coeff.getKind() == CONST_RATIONAL);
+ Assert(new_theta.isConst());
+ Assert(pv_prop.d_coeff.isConst());
NodeManager* nm = NodeManager::currentNM();
new_theta = nm->mkConst(CONST_RATIONAL,
Rational(new_theta.getConst<Rational>()
@@ -357,7 +357,7 @@ CegHandledStatus CegInstantiator::isCbqiSort(
if (dt.isParametric())
{
// if parametric, must instantiate the argument types
- consType = dt[i].getSpecializedConstructorType(tn);
+ consType = dt[i].getInstantiatedConstructorType(tn);
}
else
{
@@ -1165,8 +1165,7 @@ Node CegInstantiator::applySubstitution( TypeNode tn, Node n, std::vector< Node
Node nn = NodeManager::currentNM()->mkNode(
MULT,
subs[i],
- NodeManager::currentNM()->mkConst(
- CONST_RATIONAL,
+ NodeManager::currentNM()->mkConstReal(
Rational(1) / prop[i].d_coeff.getConst<Rational>()));
nn = NodeManager::currentNM()->mkNode( kind::TO_INTEGER, nn );
nn = rewrite(nn);
@@ -1214,10 +1213,9 @@ Node CegInstantiator::applySubstitution( TypeNode tn, Node n, std::vector< Node
for( std::map< Node, Node >::iterator it = msum.begin(); it != msum.end(); ++it ){
Node c_coeff;
if( !msum_coeff[it->first].isNull() ){
- c_coeff = rewrite(NodeManager::currentNM()->mkConst(
- CONST_RATIONAL,
+ c_coeff = rewrite(NodeManager::currentNM()->mkConstReal(
pv_prop.d_coeff.getConst<Rational>()
- / msum_coeff[it->first].getConst<Rational>()));
+ / msum_coeff[it->first].getConst<Rational>()));
}else{
c_coeff = pv_prop.d_coeff;
}
@@ -1283,7 +1281,7 @@ Node CegInstantiator::applySubstitutionToLiteral( Node lit, std::vector< Node >&
}else{
atom_lhs = nm->mkNode(MINUS, atom[0], atom[1]);
atom_lhs = rewrite(atom_lhs);
- atom_rhs = nm->mkConst(CONST_RATIONAL, Rational(0));
+ atom_rhs = nm->mkConstRealOrInt(atom_lhs.getType(), Rational(0));
}
//must be an eligible term
if( isEligible( atom_lhs ) ){
diff --git a/src/theory/quantifiers/cegqi/inst_strategy_cegqi.cpp b/src/theory/quantifiers/cegqi/inst_strategy_cegqi.cpp
index 65ad79e29..2555ff637 100644
--- a/src/theory/quantifiers/cegqi/inst_strategy_cegqi.cpp
+++ b/src/theory/quantifiers/cegqi/inst_strategy_cegqi.cpp
@@ -56,10 +56,10 @@ InstStrategyCegqi::InstStrategyCegqi(Env& env,
d_cbqi_set_quant_inactive(false),
d_incomplete_check(false),
d_added_cbqi_lemma(userContext()),
- d_vtsCache(new VtsTermCache(qim)),
+ d_vtsCache(new VtsTermCache(env, qim)),
d_bv_invert(nullptr),
- d_small_const_multiplier(NodeManager::currentNM()->mkConst(
- CONST_RATIONAL, Rational(1) / Rational(1000000))),
+ d_small_const_multiplier(NodeManager::currentNM()->mkConstReal(
+ Rational(1) / Rational(1000000))),
d_small_const(d_small_const_multiplier)
{
d_check_vts_lemma_lc = false;
@@ -435,6 +435,7 @@ void InstStrategyCegqi::process( Node q, Theory::Effort effort, int e ) {
}
d_curr_quant = Node::null();
}else if( e==1 ){
+ NodeManager* nm = NodeManager::currentNM();
//minimize the free delta heuristically on demand
if( d_check_vts_lemma_lc ){
Trace("inst-alg") << "-> Minimize delta heuristic, for " << q << std::endl;
@@ -453,12 +454,10 @@ void InstStrategyCegqi::process( Node q, Theory::Effort effort, int e ) {
d_vtsCache->getVtsTerms(inf, true, false, false);
for( unsigned i=0; i<inf.size(); i++ ){
Trace("quant-vts-debug") << "Infinity lemma for " << inf[i] << " " << d_small_const << std::endl;
- Node inf_lem_lb = NodeManager::currentNM()->mkNode(
+ Node inf_lem_lb = nm->mkNode(
GT,
inf[i],
- NodeManager::currentNM()->mkConst(
- CONST_RATIONAL,
- Rational(1) / d_small_const.getConst<Rational>()));
+ nm->mkConstReal(Rational(1) / d_small_const.getConst<Rational>()));
d_qim.lemma(inf_lem_lb, InferenceId::QUANTIFIERS_CEGQI_VTS_LB_INF);
}
}
diff --git a/src/theory/quantifiers/cegqi/vts_term_cache.cpp b/src/theory/quantifiers/cegqi/vts_term_cache.cpp
index 37ded9b7f..058b6a8bf 100644
--- a/src/theory/quantifiers/cegqi/vts_term_cache.cpp
+++ b/src/theory/quantifiers/cegqi/vts_term_cache.cpp
@@ -28,9 +28,9 @@ namespace cvc5 {
namespace theory {
namespace quantifiers {
-VtsTermCache::VtsTermCache(QuantifiersInferenceManager& qim) : d_qim(qim)
+VtsTermCache::VtsTermCache(Env& env, QuantifiersInferenceManager& qim)
+ : EnvObj(env), d_qim(qim)
{
- d_zero = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(0));
}
void VtsTermCache::getVtsTerms(std::vector<Node>& t,
@@ -70,7 +70,8 @@ Node VtsTermCache::getVtsDelta(bool isFree, bool create)
sm->mkDummySkolem("delta_free",
nm->realType(),
"free delta for virtual term substitution");
- Node delta_lem = nm->mkNode(GT, d_vts_delta_free, d_zero);
+ Node zero = nm->mkConstReal(Rational(0));
+ Node delta_lem = nm->mkNode(GT, d_vts_delta_free, zero);
d_qim.lemma(delta_lem, InferenceId::QUANTIFIERS_CEGQI_VTS_LB_DELTA);
}
if (d_vts_delta.isNull())
@@ -155,7 +156,7 @@ Node VtsTermCache::rewriteVtsSymbols(Node n)
subs_lhs.end(),
subs_rhs.begin(),
subs_rhs.end());
- n = Rewriter::rewrite(n);
+ n = rewrite(n);
// may have cancelled
if (!expr::hasSubterm(n, rew_vts_inf))
{
@@ -215,13 +216,17 @@ Node VtsTermCache::rewriteVtsSymbols(Node n)
{
nlit = nm->mkConst(false);
}
- else if (res == 1)
- {
- nlit = nm->mkNode(GEQ, d_zero, slv);
- }
else
{
- nlit = nm->mkNode(GT, slv, d_zero);
+ Node zero = nm->mkConstRealOrInt(slv.getType(), Rational(0));
+ if (res == 1)
+ {
+ nlit = nm->mkNode(GEQ, zero, slv);
+ }
+ else
+ {
+ nlit = nm->mkNode(GT, slv, zero);
+ }
}
}
}
diff --git a/src/theory/quantifiers/cegqi/vts_term_cache.h b/src/theory/quantifiers/cegqi/vts_term_cache.h
index d3a6558cf..7ae16aec8 100644
--- a/src/theory/quantifiers/cegqi/vts_term_cache.h
+++ b/src/theory/quantifiers/cegqi/vts_term_cache.h
@@ -19,8 +19,10 @@
#define CVC5__THEORY__QUANTIFIERS__CEGQI__VTS_TERM_CACHE_H
#include <map>
+
#include "expr/attribute.h"
#include "expr/node.h"
+#include "smt/env_obj.h"
namespace cvc5 {
namespace theory {
@@ -68,10 +70,10 @@ class QuantifiersInferenceManager;
* that combine instantiating quantified formulas with nested quantifiers
* with terms containing virtual terms.
*/
-class VtsTermCache
+class VtsTermCache : protected EnvObj
{
public:
- VtsTermCache(QuantifiersInferenceManager& qim);
+ VtsTermCache(Env& env, QuantifiersInferenceManager& qim);
~VtsTermCache() {}
/**
* Get vts delta. The argument isFree indicates if we are getting the
@@ -125,8 +127,6 @@ class VtsTermCache
private:
/** Reference to the quantifiers inference manager */
QuantifiersInferenceManager& d_qim;
- /** constants */
- Node d_zero;
/** The virtual term substitution delta */
Node d_vts_delta;
/** The virtual term substitution "free delta" */
diff --git a/src/theory/quantifiers/ematching/pattern_term_selector.cpp b/src/theory/quantifiers/ematching/pattern_term_selector.cpp
index 9933eb6c9..e4d7436c8 100644
--- a/src/theory/quantifiers/ematching/pattern_term_selector.cpp
+++ b/src/theory/quantifiers/ematching/pattern_term_selector.cpp
@@ -678,8 +678,7 @@ Node PatternTermSelector::getInversion(Node n, Node x)
Assert(nc.isConst());
if (x.getType().isInteger())
{
- Node coeff =
- nm->mkConst(CONST_RATIONAL, nc.getConst<Rational>().abs());
+ Node coeff = nm->mkConstInt(nc.getConst<Rational>().abs());
if (!nc.getConst<Rational>().abs().isOne())
{
x = nm->mkNode(INTS_DIVISION_TOTAL, x, coeff);
@@ -691,8 +690,7 @@ Node PatternTermSelector::getInversion(Node n, Node x)
}
else
{
- Node coeff = nm->mkConst(CONST_RATIONAL,
- Rational(1) / nc.getConst<Rational>());
+ Node coeff = nm->mkConstReal(Rational(1) / nc.getConst<Rational>());
x = nm->mkNode(MULT, x, coeff);
}
}
diff --git a/src/theory/quantifiers/extended_rewrite.cpp b/src/theory/quantifiers/extended_rewrite.cpp
index 4ed918b43..1152267e8 100644
--- a/src/theory/quantifiers/extended_rewrite.cpp
+++ b/src/theory/quantifiers/extended_rewrite.cpp
@@ -49,7 +49,7 @@ ExtendedRewriter::ExtendedRewriter(Rewriter& rew, bool aggr)
{
d_true = NodeManager::currentNM()->mkConst(true);
d_false = NodeManager::currentNM()->mkConst(false);
- d_zero = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(0));
+ d_intZero = NodeManager::currentNM()->mkConstInt(Rational(0));
}
void ExtendedRewriter::setCache(Node n, Node ret) const
@@ -1723,7 +1723,7 @@ Node ExtendedRewriter::extendedRewriteStrings(Node node) const
strings::ArithEntail aent(&d_rew);
// (str.substr s x y) --> "" if x < len(s) |= 0 >= y
Node n1_lt_tot_len = d_rew.rewrite(nm->mkNode(LT, node[1], tot_len));
- if (aent.checkWithAssumption(n1_lt_tot_len, d_zero, node[2], false))
+ if (aent.checkWithAssumption(n1_lt_tot_len, d_intZero, node[2], false))
{
Node ret = strings::Word::mkEmptyWord(node.getType());
debugExtendedRewrite(node, ret, "SS_START_ENTAILS_ZERO_LEN");
@@ -1731,7 +1731,7 @@ Node ExtendedRewriter::extendedRewriteStrings(Node node) const
}
// (str.substr s x y) --> "" if 0 < y |= x >= str.len(s)
- Node non_zero_len = d_rew.rewrite(nm->mkNode(LT, d_zero, node[2]));
+ Node non_zero_len = d_rew.rewrite(nm->mkNode(LT, d_intZero, node[2]));
if (aent.checkWithAssumption(non_zero_len, node[1], tot_len, false))
{
Node ret = strings::Word::mkEmptyWord(node.getType());
@@ -1739,8 +1739,8 @@ Node ExtendedRewriter::extendedRewriteStrings(Node node) const
return ret;
}
// (str.substr s x y) --> "" if x >= 0 |= 0 >= str.len(s)
- Node geq_zero_start = d_rew.rewrite(nm->mkNode(GEQ, node[1], d_zero));
- if (aent.checkWithAssumption(geq_zero_start, d_zero, tot_len, false))
+ Node geq_zero_start = d_rew.rewrite(nm->mkNode(GEQ, node[1], d_intZero));
+ if (aent.checkWithAssumption(geq_zero_start, d_intZero, tot_len, false))
{
Node ret = strings::Word::mkEmptyWord(node.getType());
debugExtendedRewrite(node, ret, "SS_GEQ_ZERO_START_ENTAILS_EMP_S");
diff --git a/src/theory/quantifiers/extended_rewrite.h b/src/theory/quantifiers/extended_rewrite.h
index 1b9d0dae4..bf5829e03 100644
--- a/src/theory/quantifiers/extended_rewrite.h
+++ b/src/theory/quantifiers/extended_rewrite.h
@@ -262,7 +262,7 @@ class ExtendedRewriter
/** Common constant nodes */
Node d_true;
Node d_false;
- Node d_zero;
+ Node d_intZero;
};
} // namespace quantifiers
diff --git a/src/theory/quantifiers/fmf/bounded_integers.cpp b/src/theory/quantifiers/fmf/bounded_integers.cpp
index b5b9e7d88..5c0283863 100644
--- a/src/theory/quantifiers/fmf/bounded_integers.cpp
+++ b/src/theory/quantifiers/fmf/bounded_integers.cpp
@@ -59,7 +59,7 @@ BoundedIntegers::IntRangeDecisionHeuristic::IntRangeDecisionHeuristic(
Node BoundedIntegers::IntRangeDecisionHeuristic::mkLiteral(unsigned n)
{
NodeManager* nm = NodeManager::currentNM();
- Node cn = nm->mkConst(CONST_RATIONAL, Rational(n == 0 ? 0 : n - 1));
+ Node cn = nm->mkConstInt(Rational(n == 0 ? 0 : n - 1));
return nm->mkNode(n == 0 ? LT : LEQ, d_proxy_range, cn);
}
@@ -84,10 +84,9 @@ Node BoundedIntegers::IntRangeDecisionHeuristic::proxyCurrentRangeLemma()
Node lem = nm->mkNode(
EQUAL,
currLit,
- nm->mkNode(
- curr == 0 ? LT : LEQ,
- d_range,
- nm->mkConst(CONST_RATIONAL, Rational(curr == 0 ? 0 : curr - 1))));
+ nm->mkNode(curr == 0 ? LT : LEQ,
+ d_range,
+ nm->mkConstInt(Rational(curr == 0 ? 0 : curr - 1))));
return lem;
}
@@ -224,6 +223,7 @@ void BoundedIntegers::process( Node q, Node n, bool pol,
std::map< Node, Node > msum;
if (ArithMSum::getMonomialSumLit(n, msum))
{
+ NodeManager* nm = NodeManager::currentNM();
Trace("bound-int-debug") << "literal (polarity = " << pol << ") " << n << " is monomial sum : " << std::endl;
ArithMSum::debugPrintMonomialSum(msum, "bound-int-debug");
for( std::map< Node, Node >::iterator it = msum.begin(); it != msum.end(); ++it ){
@@ -240,11 +240,11 @@ void BoundedIntegers::process( Node q, Node n, bool pol,
n1 = veq[1];
n2 = veq[0];
if( n1.getKind()==BOUND_VARIABLE ){
- n2 = ArithMSum::offset(n2, 1);
+ n2 = nm->mkNode(PLUS, n2, nm->mkConstInt(Rational(1)));
}else{
- n1 = ArithMSum::offset(n1, -1);
+ n1 = nm->mkNode(PLUS, n1, nm->mkConstInt(Rational(-1)));
}
- veq = NodeManager::currentNM()->mkNode( GEQ, n1, n2 );
+ veq = nm->mkNode(GEQ, n1, n2);
}
Trace("bound-int-debug") << "Isolated for " << it->first << " : (" << n1 << " >= " << n2 << ")" << std::endl;
Node t = n1==it->first ? n2 : n1;
@@ -693,8 +693,7 @@ Node BoundedIntegers::getSetRangeValue( Node q, Node v, RepSetIterator * rsi ) {
}
choices.pop_back();
Node bvl = nm->mkNode(BOUND_VAR_LIST, choice_i);
- Node cMinCard =
- nm->mkNode(LEQ, srCardN, nm->mkConst(CONST_RATIONAL, Rational(i)));
+ Node cMinCard = nm->mkNode(LEQ, srCardN, nm->mkConstInt(Rational(i)));
choice_i = nm->mkNode(WITNESS, bvl, nm->mkNode(OR, cMinCard, cBody));
d_setm_choice[sro].push_back(choice_i);
}
@@ -818,8 +817,8 @@ bool BoundedIntegers::getBoundElements( RepSetIterator * rsi, bool initial, Node
Node range = rewrite(nm->mkNode(MINUS, u, l));
// 9999 is an arbitrary range past which we do not do exhaustive
// bounded instantation, based on the check below.
- Node ra = rewrite(nm->mkNode(
- LEQ, range, nm->mkConst(CONST_RATIONAL, Rational(9999))));
+ Node ra =
+ rewrite(nm->mkNode(LEQ, range, nm->mkConstInt(Rational(9999))));
Node tl = l;
Node tu = u;
getBounds( q, v, rsi, tl, tu );
@@ -830,8 +829,7 @@ bool BoundedIntegers::getBoundElements( RepSetIterator * rsi, bool initial, Node
Trace("bound-int-rsi") << "Actual bound range is " << rr << std::endl;
for (long k = 0; k < rr; k++)
{
- Node t =
- nm->mkNode(PLUS, tl, nm->mkConst(CONST_RATIONAL, Rational(k)));
+ Node t = nm->mkNode(PLUS, tl, nm->mkConstInt(Rational(k)));
t = rewrite(t);
elements.push_back( t );
}
diff --git a/src/theory/quantifiers/fmf/full_model_check.cpp b/src/theory/quantifiers/fmf/full_model_check.cpp
index be69617c7..c9e08b7a8 100644
--- a/src/theory/quantifiers/fmf/full_model_check.cpp
+++ b/src/theory/quantifiers/fmf/full_model_check.cpp
@@ -67,8 +67,9 @@ bool EntryTrie::hasGeneralization( FirstOrderModelFmc * m, Node c, int index ) {
}
if( c[index].getType().isSort() ){
//for star: check if all children are defined and have generalizations
- if( c[index]==st ){ ///options::fmfFmcCoverSimplify()
- //check if all children exist and are complete
+ if (c[index] == st)
+ { /// option fmfFmcCoverSimplify
+ // check if all children exist and are complete
unsigned num_child_def =
d_child.size() - (d_child.find(st) != d_child.end() ? 1 : 0);
if (num_child_def == m->getRepSet()->getNumRepresentatives(tn))
diff --git a/src/theory/quantifiers/instantiation_list.cpp b/src/theory/quantifiers/instantiation_list.cpp
index f4b52619a..81ef84ae0 100644
--- a/src/theory/quantifiers/instantiation_list.cpp
+++ b/src/theory/quantifiers/instantiation_list.cpp
@@ -16,6 +16,7 @@
#include "theory/quantifiers/instantiation_list.h"
#include "options/base_options.h"
+#include "options/io_utils.h"
#include "printer/printer.h"
namespace cvc5 {
@@ -30,13 +31,15 @@ InstantiationVec::InstantiationVec(const std::vector<Node>& vec,
void InstantiationList::initialize(Node q) { d_quant = q; }
std::ostream& operator<<(std::ostream& out, const InstantiationList& ilist)
{
- Printer::getPrinter(options::outputLanguage())->toStream(out, ilist);
+ auto language = options::ioutils::getOutputLang(out);
+ Printer::getPrinter(language)->toStream(out, ilist);
return out;
}
std::ostream& operator<<(std::ostream& out, const SkolemList& skl)
{
- Printer::getPrinter(options::outputLanguage())->toStream(out, skl);
+ auto language = options::ioutils::getOutputLang(out);
+ Printer::getPrinter(language)->toStream(out, skl);
return out;
}
diff --git a/src/theory/quantifiers/quant_bound_inference.cpp b/src/theory/quantifiers/quant_bound_inference.cpp
index af72e2a7c..dfffe64cf 100644
--- a/src/theory/quantifiers/quant_bound_inference.cpp
+++ b/src/theory/quantifiers/quant_bound_inference.cpp
@@ -61,10 +61,9 @@ bool QuantifiersBoundInference::mayComplete(TypeNode tn, unsigned maxCard)
if (!c.isLargeFinite())
{
NodeManager* nm = NodeManager::currentNM();
- Node card =
- nm->mkConst(CONST_RATIONAL, Rational(c.getFiniteCardinality()));
+ Node card = nm->mkConstInt(Rational(c.getFiniteCardinality()));
// check if less than fixed upper bound
- Node oth = nm->mkConst(CONST_RATIONAL, Rational(maxCard));
+ Node oth = nm->mkConstInt(Rational(maxCard));
Node eq = nm->mkNode(LEQ, card, oth);
eq = Rewriter::rewrite(eq);
mc = eq.isConst() && eq.getConst<bool>();
diff --git a/src/theory/quantifiers/quant_conflict_find.cpp b/src/theory/quantifiers/quant_conflict_find.cpp
index 9f7b270de..d39212ddc 100644
--- a/src/theory/quantifiers/quant_conflict_find.cpp
+++ b/src/theory/quantifiers/quant_conflict_find.cpp
@@ -721,7 +721,7 @@ bool QuantInfo::completeMatch( QuantConflictFind * p, std::vector< int >& assign
break;
}
}else{
- Node z = p->getZero( k );
+ Node z = p->getZero(d_vars[index].getType(), k);
if( !z.isNull() ){
Trace("qcf-tconstraint-debug") << "...set " << d_vars[vn] << " = " << z << std::endl;
assigned.push_back( vn );
@@ -744,7 +744,7 @@ bool QuantInfo::completeMatch( QuantConflictFind * p, std::vector< int >& assign
if( slv_v!=-1 ){
Node lhs;
if( children.empty() ){
- lhs = p->getZero( k );
+ lhs = p->getZero(d_vars[index].getType(), k);
}else if( children.size()==1 ){
lhs = children[0];
}else{
@@ -1918,13 +1918,17 @@ bool QuantConflictFind::areMatchDisequal( TNode n1, TNode n2 ) {
bool QuantConflictFind::needsCheck( Theory::Effort level ) {
bool performCheck = false;
- if( options::quantConflictFind() && !d_conflict ){
+ if (options().quantifiers.quantConflictFind && !d_conflict)
+ {
if( level==Theory::EFFORT_LAST_CALL ){
- performCheck = options::qcfWhenMode() == options::QcfWhenMode::LAST_CALL;
+ performCheck =
+ options().quantifiers.qcfWhenMode == options::QcfWhenMode::LAST_CALL;
}else if( level==Theory::EFFORT_FULL ){
- performCheck = options::qcfWhenMode() == options::QcfWhenMode::DEFAULT;
+ performCheck =
+ options().quantifiers.qcfWhenMode == options::QcfWhenMode::DEFAULT;
}else if( level==Theory::EFFORT_STANDARD ){
- performCheck = options::qcfWhenMode() == options::QcfWhenMode::STD;
+ performCheck =
+ options().quantifiers.qcfWhenMode == options::QcfWhenMode::STD;
}
}
return performCheck;
@@ -1943,7 +1947,7 @@ void QuantConflictFind::reset_round( Theory::Effort level ) {
if (tdb->hasTermCurrent(r))
{
TypeNode rtn = r.getType();
- if (!options::cegqi() || !TermUtil::hasInstConstAttr(r))
+ if (!options().quantifiers.cegqi || !TermUtil::hasInstConstAttr(r))
{
d_eqcs[rtn].push_back(r);
}
@@ -2276,18 +2280,20 @@ QuantConflictFind::Statistics::Statistics()
{
}
-TNode QuantConflictFind::getZero( Kind k ) {
- std::map< Kind, Node >::iterator it = d_zero.find( k );
- if( it==d_zero.end() ){
+TNode QuantConflictFind::getZero(TypeNode tn, Kind k)
+{
+ std::pair<TypeNode, Kind> key(tn, k);
+ std::map<std::pair<TypeNode, Kind>, Node>::iterator it = d_zero.find(key);
+ if (it == d_zero.end())
+ {
Node nn;
if( k==PLUS ){
- nn = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(0));
+ nn = NodeManager::currentNM()->mkConstRealOrInt(tn, Rational(0));
}
- d_zero[k] = nn;
+ d_zero[key] = nn;
return nn;
- }else{
- return it->second;
}
+ return it->second;
}
std::ostream& operator<<(std::ostream& os, const QuantConflictFind::Effort& e) {
diff --git a/src/theory/quantifiers/quant_conflict_find.h b/src/theory/quantifiers/quant_conflict_find.h
index d14e281fb..82a925d3b 100644
--- a/src/theory/quantifiers/quant_conflict_find.h
+++ b/src/theory/quantifiers/quant_conflict_find.h
@@ -195,7 +195,7 @@ class QuantConflictFind : public QuantifiersModule
private:
context::CDO< bool > d_conflict;
- std::map< Kind, Node > d_zero;
+ std::map<std::pair<TypeNode, 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
@@ -209,8 +209,9 @@ private:
public: //for ground terms
Node d_true;
Node d_false;
- TNode getZero( Kind k );
-private:
+ TNode getZero(TypeNode tn, Kind k);
+
+ private:
std::map< Node, QuantInfo > d_qinfo;
private: //for equivalence classes
// type -> list(eqc)
diff --git a/src/theory/quantifiers/quant_split.cpp b/src/theory/quantifiers/quant_split.cpp
index 55fa2a1e5..e6cee778b 100644
--- a/src/theory/quantifiers/quant_split.cpp
+++ b/src/theory/quantifiers/quant_split.cpp
@@ -167,7 +167,7 @@ void QuantDSplit::check(Theory::Effort e, QEffort quant_e)
for (unsigned j = 0, ncons = dt.getNumConstructors(); j < ncons; j++)
{
std::vector<Node> vars;
- TypeNode dtjtn = dt[j].getSpecializedConstructorType(tn);
+ TypeNode dtjtn = dt[j].getInstantiatedConstructorType(tn);
Assert(dtjtn.getNumChildren() == dt[j].getNumArgs() + 1);
for (unsigned k = 0, nargs = dt[j].getNumArgs(); k < nargs; k++)
{
diff --git a/src/theory/quantifiers/quantifiers_rewriter.cpp b/src/theory/quantifiers/quantifiers_rewriter.cpp
index c38d0aa91..c53809d6e 100644
--- a/src/theory/quantifiers/quantifiers_rewriter.cpp
+++ b/src/theory/quantifiers/quantifiers_rewriter.cpp
@@ -443,7 +443,7 @@ Node QuantifiersRewriter::computeProcessTerms(Node body,
{
Node r = computeProcessTerms2(fbody, cache, new_vars, new_conds);
Assert(new_vars.size() == h.getNumChildren());
- return Rewriter::rewrite(NodeManager::currentNM()->mkNode(EQUAL, h, r));
+ return NodeManager::currentNM()->mkNode(EQUAL, h, r);
}
// It can happen that we can't infer the shape of the function definition,
// for example: forall xy. f( x, y ) = 1 + f( x, y ), this is rewritten to
@@ -906,9 +906,9 @@ bool QuantifiersRewriter::getVarElimLit(Node body,
// take into account if parametric
if (dt.isParametric())
{
- tspec = c.getSpecializedConstructorType(lit[0].getType());
- cons = nm->mkNode(
- APPLY_TYPE_ASCRIPTION, nm->mkConst(AscriptionType(tspec)), cons);
+ TypeNode ltn = lit[0].getType();
+ tspec = c.getInstantiatedConstructorType(ltn);
+ cons = c.getInstantiatedConstructor(ltn);
}
else
{
@@ -920,7 +920,7 @@ bool QuantifiersRewriter::getVarElimLit(Node body,
for (size_t j = 0, nargs = c.getNumArgs(); j < nargs; j++)
{
TypeNode tn = tspec[j];
- Node rn = nm->mkConst(CONST_RATIONAL, Rational(j));
+ Node rn = nm->mkConstInt(Rational(j));
Node cacheVal = BoundVarManager::getCacheValue(body, lit, rn);
Node v = bvm->mkBoundVar<QRewDtExpandAttribute>(cacheVal, tn);
newChildren.push_back(v);
@@ -1028,12 +1028,11 @@ bool QuantifiersRewriter::getVarElimInternal(Node body,
std::vector<Node>& subs) const
{
Kind nk = n.getKind();
- if (nk == NOT)
+ while (nk == NOT)
{
n = n[0];
pol = !pol;
nk = n.getKind();
- Assert(nk != NOT);
}
if ((nk == AND && pol) || (nk == OR && !pol))
{
@@ -1326,7 +1325,6 @@ Node QuantifiersRewriter::computeVarElimination(Node body,
// remake with eliminated nodes
body =
body.substitute(vars.begin(), vars.end(), subs.begin(), subs.end());
- body = Rewriter::rewrite(body);
if (!qa.d_ipl.isNull())
{
qa.d_ipl = qa.d_ipl.substitute(
diff --git a/src/theory/quantifiers/query_generator_unsat.cpp b/src/theory/quantifiers/query_generator_unsat.cpp
index ae7288080..40131ffaa 100644
--- a/src/theory/quantifiers/query_generator_unsat.cpp
+++ b/src/theory/quantifiers/query_generator_unsat.cpp
@@ -66,18 +66,19 @@ bool QueryGeneratorUnsat::addTerm(Node n, std::ostream& out)
size_t checkCount = 0;
while (checkCount < 10)
{
- Assert(!activeTerms.empty());
// if we just successfully added a term, do a satisfiability check
if (addSuccess)
{
+ Assert(!activeTerms.empty());
checkCount++;
// check the current for satisfiability
currModel.clear();
// Shuffle active terms to maximize the different possible behaviors
// in the subsolver. This is instead of making multiple queries with
// the same assertion order for a subsequence.
- std::shuffle(activeTerms.begin(), activeTerms.end(), Random::getRandom());
- Result r = checkCurrent(activeTerms, out, currModel);
+ std::vector<Node> aTermCurr = activeTerms;
+ std::shuffle(aTermCurr.begin(), aTermCurr.end(), Random::getRandom());
+ Result r = checkCurrent(aTermCurr, out, currModel);
if (r.asSatisfiabilityResult().isSat() == Result::UNSAT)
{
// exclude the last active term
diff --git a/src/theory/quantifiers/relevant_domain.cpp b/src/theory/quantifiers/relevant_domain.cpp
index 0f3699990..f0684f04a 100644
--- a/src/theory/quantifiers/relevant_domain.cpp
+++ b/src/theory/quantifiers/relevant_domain.cpp
@@ -24,6 +24,7 @@
#include "theory/quantifiers/term_database.h"
#include "theory/quantifiers/term_registry.h"
#include "theory/quantifiers/term_util.h"
+#include "util/rational.h"
using namespace cvc5::kind;
@@ -301,6 +302,7 @@ void RelevantDomain::computeRelevantDomainOpCh( RDomain * rf, Node n ) {
void RelevantDomain::computeRelevantDomainLit( Node q, bool hasPol, bool pol, Node n ) {
if( d_rel_dom_lit[hasPol][pol].find( n )==d_rel_dom_lit[hasPol][pol].end() ){
+ NodeManager* nm = NodeManager::currentNM();
RDomainLit& rdl = d_rel_dom_lit[hasPol][pol][n];
rdl.d_merge = false;
int varCount = 0;
@@ -405,10 +407,14 @@ void RelevantDomain::computeRelevantDomainLit( Node q, bool hasPol, bool pol, No
if( ( !hasPol || pol ) && n[0].getType().isInteger() ){
if( n.getKind()==EQUAL ){
for( unsigned i=0; i<2; i++ ){
- rdl.d_val.push_back(ArithMSum::offset(r_add, i == 0 ? 1 : -1));
+ Node roff = nm->mkNode(
+ PLUS, r_add, nm->mkConstInt(Rational(i == 0 ? 1 : -1)));
+ rdl.d_val.push_back(roff);
}
}else if( n.getKind()==GEQ ){
- rdl.d_val.push_back(ArithMSum::offset(r_add, varLhs ? 1 : -1));
+ Node roff = nm->mkNode(
+ PLUS, r_add, nm->mkConstInt(Rational(varLhs ? 1 : -1)));
+ rdl.d_val.push_back(roff);
}
}
}
diff --git a/src/theory/quantifiers/single_inv_partition.cpp b/src/theory/quantifiers/single_inv_partition.cpp
index 73bcad535..2725e1826 100644
--- a/src/theory/quantifiers/single_inv_partition.cpp
+++ b/src/theory/quantifiers/single_inv_partition.cpp
@@ -19,7 +19,6 @@
#include "expr/node_algorithm.h"
#include "expr/skolem_manager.h"
#include "theory/quantifiers/term_util.h"
-#include "theory/rewriter.h"
using namespace cvc5;
using namespace cvc5::kind;
@@ -336,7 +335,6 @@ bool SingleInvocationPartition::init(std::vector<Node>& funcs,
cr = cr.substitute(
termsNs.begin(), termsNs.end(), subsNs.begin(), subsNs.end());
}
- cr = Rewriter::rewrite(cr);
Trace("si-prt") << ".....got si=" << singleInvocation
<< ", result : " << cr << std::endl;
d_conjuncts[2].push_back(cr);
@@ -349,7 +347,6 @@ bool SingleInvocationPartition::init(std::vector<Node>& funcs,
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;
d_conjuncts[0].push_back(cr);
}
diff --git a/src/theory/quantifiers/skolemize.cpp b/src/theory/quantifiers/skolemize.cpp
index 4dea0dc22..6399340aa 100644
--- a/src/theory/quantifiers/skolemize.cpp
+++ b/src/theory/quantifiers/skolemize.cpp
@@ -137,8 +137,8 @@ void Skolemize::getSelfSel(const DType& dt,
TypeNode tspec;
if (dt.isParametric())
{
- tspec = dc.getSpecializedConstructorType(n.getType());
- Trace("sk-ind-debug") << "Specialized constructor type : " << tspec
+ tspec = dc.getInstantiatedConstructorType(n.getType());
+ Trace("sk-ind-debug") << "Instantiated constructor type : " << tspec
<< std::endl;
Assert(tspec.getNumChildren() == dc.getNumArgs());
}
@@ -285,11 +285,10 @@ Node Skolemize::mkSkolemizedBody(Node f,
}
else if (options::intWfInduction() && tn.isInteger())
{
- Node icond = nm->mkNode(GEQ, k, nm->mkConst(CONST_RATIONAL, Rational(0)));
+ Node icond = nm->mkNode(GEQ, k, nm->mkConstInt(Rational(0)));
Node iret =
- ret.substitute(
- ind_vars[0],
- nm->mkNode(MINUS, k, nm->mkConst(CONST_RATIONAL, Rational(1))))
+ ret.substitute(ind_vars[0],
+ nm->mkNode(MINUS, k, nm->mkConstInt(Rational(1))))
.negate();
n_str_ind = nm->mkNode(OR, icond.negate(), iret);
n_str_ind = nm->mkNode(AND, icond, n_str_ind);
@@ -309,7 +308,6 @@ Node Skolemize::mkSkolemizedBody(Node f,
{
Node bvl = nm->mkNode(BOUND_VAR_LIST, rem_ind_vars);
nret = nm->mkNode(FORALL, bvl, nret);
- nret = Rewriter::rewrite(nret);
sub = nret;
sub_vars.insert(
sub_vars.end(), ind_var_indicies.begin() + 1, ind_var_indicies.end());
diff --git a/src/theory/quantifiers/sygus/cegis_unif.cpp b/src/theory/quantifiers/sygus/cegis_unif.cpp
index be80992ea..c9706b40f 100644
--- a/src/theory/quantifiers/sygus/cegis_unif.cpp
+++ b/src/theory/quantifiers/sygus/cegis_unif.cpp
@@ -480,7 +480,7 @@ Node CegisUnifEnumDecisionStrategy::mkLiteral(unsigned n)
std::set<TypeNode> unresolvedTypes;
unresolvedTypes.insert(u);
std::vector<TypeNode> cargsEmpty;
- Node cr = nm->mkConst(CONST_RATIONAL, Rational(1));
+ Node cr = nm->mkConstInt(Rational(1));
sdt.addConstructor(cr, "1", cargsEmpty);
std::vector<TypeNode> cargsPlus;
cargsPlus.push_back(u);
@@ -503,8 +503,8 @@ Node CegisUnifEnumDecisionStrategy::mkLiteral(unsigned n)
if (pow_two > 0)
{
Node size_ve = nm->mkNode(DT_SIZE, d_virtual_enum);
- Node fair_lemma = nm->mkNode(
- GEQ, size_ve, nm->mkConst(CONST_RATIONAL, Rational(pow_two - 1)));
+ Node fair_lemma =
+ nm->mkNode(GEQ, size_ve, nm->mkConstInt(Rational(pow_two - 1)));
fair_lemma = nm->mkNode(OR, newLit, fair_lemma);
Trace("cegis-unif-enum-lemma")
<< "CegisUnifEnum::lemma, fairness size:" << fair_lemma << "\n";
diff --git a/src/theory/quantifiers/sygus/sygus_abduct.cpp b/src/theory/quantifiers/sygus/sygus_abduct.cpp
index fc7e7a1b9..3da55ff50 100644
--- a/src/theory/quantifiers/sygus/sygus_abduct.cpp
+++ b/src/theory/quantifiers/sygus/sygus_abduct.cpp
@@ -28,7 +28,6 @@
#include "theory/quantifiers/sygus/sygus_grammar_cons.h"
#include "theory/quantifiers/sygus/sygus_utils.h"
#include "theory/quantifiers/term_util.h"
-#include "theory/rewriter.h"
using namespace std;
using namespace cvc5::kind;
@@ -184,8 +183,6 @@ Node SygusAbduct::mkAbductionConjecture(const std::string& name,
res = SygusUtils::mkSygusConjecture({abd}, res, {instAttr});
Trace("sygus-abduct-debug") << "...finish" << std::endl;
- res = theory::Rewriter::rewrite(res);
-
Trace("sygus-abduct") << "Generate: " << res << std::endl;
return res;
diff --git a/src/theory/quantifiers/sygus/sygus_enumerator.cpp b/src/theory/quantifiers/sygus/sygus_enumerator.cpp
index 674183b20..711d390f8 100644
--- a/src/theory/quantifiers/sygus/sygus_enumerator.cpp
+++ b/src/theory/quantifiers/sygus/sygus_enumerator.cpp
@@ -257,7 +257,7 @@ void SygusEnumerator::TermCache::initialize(SygusStatistics* s,
// more aggressive merging of constructor classes. On the negative side,
// this adds another level of indirection to remember which argument
// positions the argument types occur in, for each constructor.
- Node n = nm->mkConst(CONST_RATIONAL, Rational(i));
+ Node n = nm->mkConstInt(Rational(i));
nToC[n] = i;
tnit.add(n, argTypes[i]);
}
diff --git a/src/theory/quantifiers/sygus/sygus_grammar_cons.cpp b/src/theory/quantifiers/sygus/sygus_grammar_cons.cpp
index 438afbe82..7227b7184 100644
--- a/src/theory/quantifiers/sygus/sygus_grammar_cons.cpp
+++ b/src/theory/quantifiers/sygus/sygus_grammar_cons.cpp
@@ -85,11 +85,12 @@ void CegGrammarConstructor::collectTerms(
Node c = cur;
if (tn.isRealOrInt())
{
- c = nm->mkConst(CONST_RATIONAL, c.getConst<Rational>().abs());
+ c = nm->mkConstRealOrInt(tn, c.getConst<Rational>().abs());
}
consts[tn].insert(c);
if (tn.isInteger())
{
+ c = nm->mkConstReal(c.getConst<Rational>().abs());
TypeNode rtype = nm->realType();
consts[rtype].insert(c);
}
@@ -410,8 +411,8 @@ void CegGrammarConstructor::mkSygusConstantsForType(TypeNode type,
NodeManager* nm = NodeManager::currentNM();
if (type.isRealOrInt())
{
- ops.push_back(nm->mkConst(CONST_RATIONAL, Rational(0)));
- ops.push_back(nm->mkConst(CONST_RATIONAL, Rational(1)));
+ ops.push_back(nm->mkConstRealOrInt(type, Rational(0)));
+ ops.push_back(nm->mkConstRealOrInt(type, Rational(1)));
}
else if (type.isBitVector())
{
@@ -483,7 +484,7 @@ void CegGrammarConstructor::collectSygusGrammarTypesFor(
{
// get the specialized constructor type, which accounts for
// parametric datatypes
- TypeNode ctn = dt[i].getSpecializedConstructorType(range);
+ TypeNode ctn = dt[i].getInstantiatedConstructorType(range);
std::vector<TypeNode> argTypes = ctn.getArgTypes();
for (size_t j = 0, nargs = argTypes.size(); j < nargs; ++j)
{
@@ -556,7 +557,7 @@ Node CegGrammarConstructor::createLambdaWithZeroArg(
Assert(bArgType.isRealOrInt() || bArgType.isBitVector());
if (bArgType.isRealOrInt())
{
- zarg = nm->mkConst(CONST_RATIONAL, Rational(0));
+ zarg = nm->mkConstRealOrInt(bArgType, Rational(0));
}
else
{
@@ -800,7 +801,7 @@ void CegGrammarConstructor::mkSygusDefaultGrammar(
Trace("sygus-grammar-def") << "\t...add for 1 to Pos_Int\n";
std::vector<TypeNode> cargsEmpty;
sdts.back().addConstructor(
- nm->mkConst(CONST_RATIONAL, Rational(1)), "1", cargsEmpty);
+ nm->mkConstInt(Rational(1)), "1", cargsEmpty);
/* Add operator PLUS */
Kind kind = PLUS;
Trace("sygus-grammar-def") << "\t...add for PLUS to Pos_Int\n";
@@ -1010,12 +1011,11 @@ void CegGrammarConstructor::mkSygusDefaultGrammar(
{
Trace("sygus-grammar-def") << "...for " << dt[l].getName() << std::endl;
Node cop = dt[l].getConstructor();
- TypeNode tspec = dt[l].getSpecializedConstructorType(types[i]);
+ TypeNode tspec = dt[l].getInstantiatedConstructorType(types[i]);
// must specialize if a parametric datatype
if (dt.isParametric())
{
- cop = nm->mkNode(
- APPLY_TYPE_ASCRIPTION, nm->mkConst(AscriptionType(tspec)), cop);
+ cop = dt[l].getInstantiatedConstructor(types[i]);
}
if (dt[l].getNumArgs() == 0)
{
@@ -1151,7 +1151,7 @@ void CegGrammarConstructor::mkSygusDefaultGrammar(
{
const SygusDatatypeConstructor& sdc = sdti.getConstructor(k);
Node sop = sdc.d_op;
- bool isBuiltinArithOp = (sop.getKind() == CONST_RATIONAL);
+ bool isBuiltinArithOp = (sop.getType().isRealOrInt() && sop.isConst());
bool hasExternalType = false;
for (unsigned j = 0, nargs = sdc.d_argTypes.size(); j < nargs; j++)
{
diff --git a/src/theory/quantifiers/sygus/sygus_process_conj.cpp b/src/theory/quantifiers/sygus/sygus_process_conj.cpp
index f5cadc607..a1f197596 100644
--- a/src/theory/quantifiers/sygus/sygus_process_conj.cpp
+++ b/src/theory/quantifiers/sygus/sygus_process_conj.cpp
@@ -30,6 +30,8 @@ namespace cvc5 {
namespace theory {
namespace quantifiers {
+SynthConjectureProcessFun::SynthConjectureProcessFun(Env& env) : EnvObj(env) {}
+
void SynthConjectureProcessFun::init(Node f)
{
d_synth_fun = f;
@@ -511,7 +513,7 @@ void SynthConjectureProcessFun::getIrrelevantArgs(
}
}
-SynthConjectureProcess::SynthConjectureProcess() {}
+SynthConjectureProcess::SynthConjectureProcess(Env& env) : EnvObj(env) {}
SynthConjectureProcess::~SynthConjectureProcess() {}
Node SynthConjectureProcess::preSimplify(Node q)
{
@@ -524,7 +526,7 @@ Node SynthConjectureProcess::postSimplify(Node q)
Trace("sygus-process") << "Post-simplify conjecture : " << q << std::endl;
Assert(q.getKind() == FORALL);
- if (options::sygusArgRelevant())
+ if (options().quantifiers.sygusArgRelevant)
{
// initialize the information about each function to synthesize
for (unsigned i = 0, size = q[0].getNumChildren(); i < size; i++)
@@ -532,7 +534,9 @@ Node SynthConjectureProcess::postSimplify(Node q)
Node f = q[0][i];
if (f.getType().isFunction())
{
- d_sf_info[f].init(f);
+ std::pair<std::map<Node, SynthConjectureProcessFun>::iterator, bool>
+ it = d_sf_info.emplace(f, d_env);
+ it.first->second.init(f);
}
}
@@ -582,7 +586,7 @@ void SynthConjectureProcess::initialize(Node n, std::vector<Node>& candidates)
bool SynthConjectureProcess::isArgRelevant(Node f, unsigned i)
{
- if (!options::sygusArgRelevant())
+ if (!options().quantifiers.sygusArgRelevant)
{
return true;
}
diff --git a/src/theory/quantifiers/sygus/sygus_process_conj.h b/src/theory/quantifiers/sygus/sygus_process_conj.h
index d751e4c9c..b0b87c65b 100644
--- a/src/theory/quantifiers/sygus/sygus_process_conj.h
+++ b/src/theory/quantifiers/sygus/sygus_process_conj.h
@@ -25,6 +25,7 @@
#include "expr/node.h"
#include "expr/type_node.h"
+#include "smt/env_obj.h"
namespace cvc5 {
namespace theory {
@@ -119,10 +120,10 @@ class SynthConjectureProcessArg
* It maintains information about each of the function to
* synthesize's arguments.
*/
-struct SynthConjectureProcessFun
+struct SynthConjectureProcessFun : protected EnvObj
{
public:
- SynthConjectureProcessFun() {}
+ SynthConjectureProcessFun(Env& env);
~SynthConjectureProcessFun() {}
/** initialize this class for function f */
void init(Node f);
@@ -266,10 +267,10 @@ struct SynthConjectureProcessFun
* sygus to SynthConjectureProcess::getSymmetryBreakingPredicate(...), which are
* used for pruning search space based on conjecture-specific analysis.
*/
-class SynthConjectureProcess
+class SynthConjectureProcess : protected EnvObj
{
public:
- SynthConjectureProcess();
+ SynthConjectureProcess(Env& env);
~SynthConjectureProcess();
/** simplify the synthesis conjecture q
* Returns a formula that is equivalent to q.
diff --git a/src/theory/quantifiers/sygus/synth_conjecture.cpp b/src/theory/quantifiers/sygus/synth_conjecture.cpp
index e7d0ef58b..e5dfe408b 100644
--- a/src/theory/quantifiers/sygus/synth_conjecture.cpp
+++ b/src/theory/quantifiers/sygus/synth_conjecture.cpp
@@ -61,7 +61,7 @@ SynthConjecture::SynthConjecture(Env& env,
d_hasSolution(false),
d_ceg_si(new CegSingleInv(env, tr, s)),
d_templInfer(new SygusTemplateInfer(env)),
- d_ceg_proc(new SynthConjectureProcess),
+ d_ceg_proc(new SynthConjectureProcess(env)),
d_ceg_gc(new CegGrammarConstructor(env, d_tds, this)),
d_sygus_rconst(new SygusRepairConst(env, d_tds)),
d_exampleInfer(new ExampleInfer(d_tds)),
@@ -306,6 +306,10 @@ bool SynthConjecture::needsCheck()
bool SynthConjecture::doCheck()
{
+ if (d_hasSolution)
+ {
+ return true;
+ }
if (isSingleInvocation())
{
// We now try to solve with the single invocation solver, which may or may
@@ -314,14 +318,12 @@ bool SynthConjecture::doCheck()
if (d_ceg_si->solve())
{
d_hasSolution = true;
- // the conjecture has a solution, so its negation holds
- Node qn = d_quant.negate();
- d_qim.addPendingLemma(qn, InferenceId::QUANTIFIERS_SYGUS_SI_SOLVED);
+ // the conjecture has a solution, we set incomplete
+ d_qim.setIncomplete(IncompleteId::QUANTIFIERS_SYGUS_SOLVED);
}
return true;
}
Assert(d_master != nullptr);
- Assert(!d_hasSolution);
// get the list of terms that the master strategy is interested in
std::vector<Node> terms;
@@ -506,11 +508,10 @@ bool SynthConjecture::doCheck()
if (options().quantifiers.cegisSample == options::CegisSampleMode::TRUST)
{
// we have that the current candidate passed a sample test
- // since we trust sampling in this mode, we assert there is no
- // counterexample to the conjecture here.
- Node qn = d_quant.negate();
- d_qim.addPendingLemma(qn,
- InferenceId::QUANTIFIERS_SYGUS_SAMPLE_TRUST_SOLVED);
+ // since we trust sampling in this mode, we assume there is a solution here
+ // and set incomplete.
+ d_hasSolution = true;
+ d_qim.setIncomplete(IncompleteId::QUANTIFIERS_SYGUS_SOLVED);
recordSolution(candidate_values);
return true;
}
@@ -573,10 +574,8 @@ bool SynthConjecture::doCheck()
d_hasSolution = false;
return false;
}
- // Use lemma to terminate with "unsat", this is justified by the verification
- // check above, which confirms the synthesis conjecture is solved.
- Node qn = d_quant.negate();
- d_qim.addPendingLemma(qn, InferenceId::QUANTIFIERS_SYGUS_VERIFY_SOLVED);
+ // We set incomplete and terminate with unknown.
+ d_qim.setIncomplete(IncompleteId::QUANTIFIERS_SYGUS_SOLVED);
return true;
}
diff --git a/src/theory/quantifiers/sygus/synth_verify.cpp b/src/theory/quantifiers/sygus/synth_verify.cpp
index 5b26efef5..6b4796949 100644
--- a/src/theory/quantifiers/sygus/synth_verify.cpp
+++ b/src/theory/quantifiers/sygus/synth_verify.cpp
@@ -124,7 +124,7 @@ Result SynthVerify::verify(Node query,
Trace("cegqi-debug") << "...squery : " << squery << std::endl;
squery = rewrite(squery);
Trace("cegqi-debug") << "...rewrites to : " << squery << std::endl;
- Assert(options::sygusRecFun()
+ Assert(options().quantifiers.sygusRecFun
|| (squery.isConst() && squery.getConst<bool>()));
}
}
diff --git a/src/theory/quantifiers/sygus/template_infer.cpp b/src/theory/quantifiers/sygus/template_infer.cpp
index ab9d5f845..043e8f5ed 100644
--- a/src/theory/quantifiers/sygus/template_infer.cpp
+++ b/src/theory/quantifiers/sygus/template_infer.cpp
@@ -36,7 +36,7 @@ void SygusTemplateInfer::initialize(Node q)
// We are processing without single invocation techniques, now check if
// we should fix an invariant template (post-condition strengthening or
// pre-condition weakening).
- options::SygusInvTemplMode tmode = options::sygusInvTemplMode();
+ options::SygusInvTemplMode tmode = options().quantifiers.sygusInvTemplMode;
if (tmode != options::SygusInvTemplMode::NONE)
{
// currently only works for single predicate synthesis
@@ -44,7 +44,7 @@ void SygusTemplateInfer::initialize(Node q)
{
tmode = options::SygusInvTemplMode::NONE;
}
- else if (!options::sygusInvTemplWhenSyntax())
+ else if (!options().quantifiers.sygusInvTemplWhenSyntax)
{
// only use invariant templates if no syntactic restrictions
if (CegGrammarConstructor::hasSyntaxRestrictions(q))
@@ -106,7 +106,7 @@ void SygusTemplateInfer::initialize(Node q)
// construct template
Node templ;
- if (options::sygusInvAutoUnfold())
+ if (options().quantifiers.sygusInvAutoUnfold)
{
if (d_ti.isComplete())
{
diff --git a/src/theory/quantifiers/sygus_sampler.cpp b/src/theory/quantifiers/sygus_sampler.cpp
index 89cee0145..1402c845c 100644
--- a/src/theory/quantifiers/sygus_sampler.cpp
+++ b/src/theory/quantifiers/sygus_sampler.cpp
@@ -589,14 +589,14 @@ Node SygusSampler::getRandomValue(TypeNode tn)
std::vector<Node> sum;
for (unsigned j = 0, size = vec.size(); j < size; j++)
{
- Node digit = nm->mkConst(CONST_RATIONAL, Rational(vec[j]) * curr);
+ Node digit = nm->mkConstInt(Rational(vec[j]) * curr);
sum.push_back(digit);
curr = curr * baser;
}
Node ret;
if (sum.empty())
{
- ret = nm->mkConst(CONST_RATIONAL, Rational(0));
+ ret = nm->mkConstInt(Rational(0));
}
else if (sum.size() == 1)
{
@@ -631,7 +631,7 @@ Node SygusSampler::getRandomValue(TypeNode tn)
}
else
{
- return nm->mkConst(CONST_RATIONAL, sr / rr);
+ return nm->mkConstReal(sr / rr);
}
}
}
diff --git a/src/theory/quantifiers/term_util.cpp b/src/theory/quantifiers/term_util.cpp
index 1dfcc044e..18f9ec7e2 100644
--- a/src/theory/quantifiers/term_util.cpp
+++ b/src/theory/quantifiers/term_util.cpp
@@ -332,7 +332,7 @@ Node TermUtil::mkTypeValue(TypeNode tn, int32_t val)
if (tn.isRealOrInt())
{
Rational c(val);
- n = NodeManager::currentNM()->mkConst(CONST_RATIONAL, c);
+ n = NodeManager::currentNM()->mkConstRealOrInt(tn, c);
}
else if (tn.isBitVector())
{
diff --git a/src/theory/relevance_manager.cpp b/src/theory/relevance_manager.cpp
index 972a2918c..9acf2dffc 100644
--- a/src/theory/relevance_manager.cpp
+++ b/src/theory/relevance_manager.cpp
@@ -17,6 +17,7 @@
#include <sstream>
+#include "expr/term_context_stack.h"
#include "options/smt_options.h"
#include "smt/env.h"
@@ -25,17 +26,21 @@ using namespace cvc5::kind;
namespace cvc5 {
namespace theory {
-RelevanceManager::RelevanceManager(context::Context* lemContext, Valuation val)
- : d_val(val),
- d_input(lemContext),
- d_computed(false),
+RelevanceManager::RelevanceManager(Env& env, Valuation val)
+ : EnvObj(env),
+ d_val(val),
+ d_input(userContext()),
+ d_rset(context()),
+ d_inFullEffortCheck(false),
d_success(false),
d_trackRSetExp(false),
- d_miniscopeTopLevel(true)
+ d_miniscopeTopLevel(true),
+ d_rsetExp(context()),
+ d_jcache(context())
{
- if (options::produceDifficulty())
+ if (options().smt.produceDifficulty)
{
- d_dman.reset(new DifficultyManager(lemContext, val));
+ d_dman.reset(new DifficultyManager(userContext(), val));
d_trackRSetExp = true;
// we cannot miniscope AND at the top level, since we need to
// preserve the exact form of preprocessed assertions so the dependencies
@@ -45,7 +50,7 @@ RelevanceManager::RelevanceManager(context::Context* lemContext, Valuation val)
}
void RelevanceManager::notifyPreprocessedAssertions(
- const std::vector<Node>& assertions)
+ const std::vector<Node>& assertions, bool isInput)
{
// add to input list, which is user-context dependent
std::vector<Node> toProcess;
@@ -65,13 +70,18 @@ void RelevanceManager::notifyPreprocessedAssertions(
}
}
addAssertionsInternal(toProcess);
+ // notify the difficulty manager if these are input assertions
+ if (isInput && d_dman != nullptr)
+ {
+ d_dman->notifyInputAssertions(assertions);
+ }
}
-void RelevanceManager::notifyPreprocessedAssertion(Node n)
+void RelevanceManager::notifyPreprocessedAssertion(Node n, bool isInput)
{
std::vector<Node> toProcess;
toProcess.push_back(n);
- addAssertionsInternal(toProcess);
+ notifyPreprocessedAssertions(toProcess, isInput);
}
void RelevanceManager::addAssertionsInternal(std::vector<Node>& toProcess)
@@ -100,47 +110,53 @@ void RelevanceManager::addAssertionsInternal(std::vector<Node>& toProcess)
}
}
-void RelevanceManager::beginRound()
-{
- d_computed = false;
-}
+void RelevanceManager::beginRound() { d_inFullEffortCheck = true; }
+
+void RelevanceManager::endRound() { d_inFullEffortCheck = false; }
void RelevanceManager::computeRelevance()
{
- d_computed = true;
- d_rset.clear();
- d_rsetExp.clear();
- Trace("rel-manager") << "RelevanceManager::computeRelevance..." << std::endl;
- std::unordered_map<TNode, int> cache;
- d_success = true;
+ // if not at full effort, should be tracking something else, e.g. explanation
+ // for why literals are relevant.
+ Assert(d_inFullEffortCheck || d_trackRSetExp);
+ Trace("rel-manager") << "RelevanceManager::computeRelevance, full effort = "
+ << d_inFullEffortCheck << "..." << std::endl;
for (const Node& node: d_input)
{
TNode n = node;
- int val = justify(n, cache);
+ int32_t val = justify(n);
if (val != 1)
{
- if (Trace.isOn("rel-manager"))
+ // if we are in full effort check and fail to justify, then we should
+ // give a failure and set success to false, or otherwise calls to
+ // isRelevant cannot be trusted.
+ if (d_inFullEffortCheck)
{
std::stringstream serr;
serr
<< "RelevanceManager::computeRelevance: WARNING: failed to justify "
<< n;
Trace("rel-manager") << serr.str() << std::endl;
+ Assert(false) << serr.str();
+ d_success = false;
+ return;
}
- d_success = false;
- // If we fail to justify an assertion, we set success to false and
- // continue to try to justify the remaining assertions. This is important
- // for cases where the difficulty manager is measuring based on lemmas
- // that are being sent at STANDARD effort, before all assertions are
- // satisfied.
}
}
- if (!d_success)
+ if (Trace.isOn("rel-manager"))
{
- d_rset.clear();
- return;
+ if (d_inFullEffortCheck)
+ {
+ Trace("rel-manager") << "...success (full), size = " << d_rset.size()
+ << std::endl;
+ }
+ else
+ {
+ Trace("rel-manager") << "...success, exp size = " << d_rsetExp.size()
+ << std::endl;
+ }
}
- Trace("rel-manager") << "...success, size = " << d_rset.size() << std::endl;
+ d_success = true;
}
bool RelevanceManager::isBooleanConnective(TNode cur)
@@ -150,27 +166,27 @@ bool RelevanceManager::isBooleanConnective(TNode cur)
|| (k == EQUAL && cur[0].getType().isBoolean());
}
-bool RelevanceManager::updateJustifyLastChild(
- TNode cur,
- std::vector<int>& childrenJustify,
- std::unordered_map<TNode, int>& cache)
+bool RelevanceManager::updateJustifyLastChild(const RlvPair& cur,
+ std::vector<int32_t>& childrenJustify)
{
// This method is run when we are informed that child index of cur
// has justify status lastChildJustify. We return true if we would like to
// compute the next child, in this case we push the status of the current
// child to childrenJustify.
- size_t nchildren = cur.getNumChildren();
- Assert(isBooleanConnective(cur));
+ size_t nchildren = cur.first.getNumChildren();
+ Assert(isBooleanConnective(cur.first));
size_t index = childrenJustify.size();
Assert(index < nchildren);
- Assert(cache.find(cur[index]) != cache.end());
- Kind k = cur.getKind();
+ Kind k = cur.first.getKind();
// Lookup the last child's value in the overall cache, we may choose to
// add this to childrenJustify if we return true.
- int lastChildJustify = cache[cur[index]];
+ RlvPair cp(cur.first[index],
+ d_ptctx.computeValue(cur.first, cur.second, index));
+ Assert(d_jcache.find(cp) != d_jcache.end());
+ int32_t lastChildJustify = d_jcache[cp];
if (k == NOT)
{
- cache[cur] = -lastChildJustify;
+ d_jcache[cur] = -lastChildJustify;
}
else if (k == IMPLIES || k == AND || k == OR)
{
@@ -181,7 +197,7 @@ bool RelevanceManager::updateJustifyLastChild(
if (lastChildJustify
== ((k == AND || (k == IMPLIES && index == 0)) ? -1 : 1))
{
- cache[cur] = k == AND ? -1 : 1;
+ d_jcache[cur] = k == AND ? -1 : 1;
return false;
}
}
@@ -197,7 +213,7 @@ bool RelevanceManager::updateJustifyLastChild(
break;
}
}
- cache[cur] = ret;
+ d_jcache[cur] = ret;
}
else
{
@@ -209,7 +225,7 @@ bool RelevanceManager::updateJustifyLastChild(
else if (lastChildJustify == 0)
{
// all other cases, an unknown child implies we are unknown
- cache[cur] = 0;
+ d_jcache[cur] = 0;
}
else if (k == ITE)
{
@@ -230,7 +246,7 @@ bool RelevanceManager::updateJustifyLastChild(
// should be in proper branch
Assert(childrenJustify[0] == (index == 1 ? 1 : -1));
// we are the value of the branch
- cache[cur] = lastChildJustify;
+ d_jcache[cur] = lastChildJustify;
}
}
else
@@ -248,7 +264,7 @@ bool RelevanceManager::updateJustifyLastChild(
{
// both children known, compute value
Assert(childrenJustify.size() == 1 && childrenJustify[0] != 0);
- cache[cur] =
+ d_jcache[cur] =
((k == XOR ? -1 : 1) * lastChildJustify == childrenJustify[0]) ? 1
: -1;
}
@@ -256,85 +272,110 @@ bool RelevanceManager::updateJustifyLastChild(
return false;
}
-int RelevanceManager::justify(TNode n, std::unordered_map<TNode, int>& cache)
+int32_t RelevanceManager::justify(TNode n)
{
+ // The set of nodes that we have computed currently have no value. Those
+ // that are marked as having no value in d_jcache must be recomputed, since
+ // the values for SAT literals may have changed.
+ std::unordered_set<RlvPair, RlvPairHashFunction> noJustify;
// the vector of values of children
- std::unordered_map<TNode, std::vector<int>> childJustify;
- std::unordered_map<TNode, int>::iterator it;
- std::unordered_map<TNode, std::vector<int>>::iterator itc;
- std::vector<TNode> visit;
- TNode cur;
- visit.push_back(n);
+ std::unordered_map<RlvPair, std::vector<int32_t>, RlvPairHashFunction>
+ childJustify;
+ RlvPairIntMap::iterator it;
+ std::unordered_map<RlvPair, std::vector<int32_t>, RlvPairHashFunction>::iterator
+ itc;
+ RlvPair cur;
+ TCtxStack visit(&d_ptctx);
+ visit.pushInitial(n);
do
{
- cur = visit.back();
+ cur = visit.getCurrent();
// should always have Boolean type
- Assert(cur.getType().isBoolean());
- it = cache.find(cur);
- if (it != cache.end())
+ Assert(cur.first.getType().isBoolean());
+ it = d_jcache.find(cur);
+ if (it != d_jcache.end())
{
- visit.pop_back();
- // already computed value
- continue;
+ if (it->second != 0 || noJustify.find(cur) != noJustify.end())
+ {
+ visit.pop();
+ // already computed value
+ continue;
+ }
}
itc = childJustify.find(cur);
// have we traversed to children yet?
if (itc == childJustify.end())
{
// are we not a Boolean connective (including NOT)?
- if (isBooleanConnective(cur))
+ if (isBooleanConnective(cur.first))
{
// initialize its children justify vector as empty
childJustify[cur].clear();
// start with the first child
- visit.push_back(cur[0]);
+ visit.pushChild(cur.first, cur.second, 0);
}
else
{
- visit.pop_back();
+ visit.pop();
// The atom case, lookup the value in the valuation class to
// see its current value in the SAT solver, if it has one.
int ret = 0;
// otherwise we look up the value
bool value;
- if (d_val.hasSatValue(cur, value))
+ if (d_val.hasSatValue(cur.first, value))
{
ret = value ? 1 : -1;
- d_rset.insert(cur);
- if (d_trackRSetExp)
+ bool hasPol, pol;
+ PolarityTermContext::getFlags(cur.second, hasPol, pol);
+ // relevant if weakly matches polarity
+ if (!hasPol || pol == value)
{
- d_rsetExp[cur] = n;
+ d_rset.insert(cur.first);
+ if (d_trackRSetExp)
+ {
+ d_rsetExp[cur.first] = n;
+ Trace("rel-manager-exp")
+ << "Reason for " << cur.first << " is " << n
+ << ", polarity is " << hasPol << "/" << pol << std::endl;
+ }
}
}
- cache[cur] = ret;
+ d_jcache[cur] = ret;
+ if (ret == 0)
+ {
+ noJustify.insert(cur);
+ }
}
}
else
{
// this processes the impact of the current child on the value of cur,
// and possibly requests that a new child is computed.
- if (updateJustifyLastChild(cur, itc->second, cache))
+ if (updateJustifyLastChild(cur, itc->second))
{
- Assert(itc->second.size() < cur.getNumChildren());
- TNode nextChild = cur[itc->second.size()];
- visit.push_back(nextChild);
+ Assert(itc->second.size() < cur.first.getNumChildren());
+ visit.pushChild(cur.first, cur.second, itc->second.size());
}
else
{
- visit.pop_back();
+ visit.pop();
+ Assert(d_jcache.find(cur) != d_jcache.end());
+ if (d_jcache[cur] == 0)
+ {
+ noJustify.insert(cur);
+ }
}
}
} while (!visit.empty());
- Assert(cache.find(n) != cache.end());
- return cache[n];
+ RlvPair ci(n, d_ptctx.initialValue());
+ Assert(d_jcache.find(ci) != d_jcache.end());
+ return d_jcache[ci];
}
bool RelevanceManager::isRelevant(Node lit)
{
- if (!d_computed)
- {
- computeRelevance();
- }
+ Assert(d_inFullEffortCheck);
+ computeRelevance();
if (!d_success)
{
// always relevant if we failed to compute
@@ -348,22 +389,25 @@ bool RelevanceManager::isRelevant(Node lit)
return d_rset.find(lit) != d_rset.end();
}
-const std::unordered_set<TNode>& RelevanceManager::getRelevantAssertions(
- bool& success)
+std::unordered_set<TNode> RelevanceManager::getRelevantAssertions(bool& success)
{
- if (!d_computed)
- {
- computeRelevance();
- }
+ computeRelevance();
// update success flag
success = d_success;
- return d_rset;
+ std::unordered_set<TNode> rset;
+ if (success)
+ {
+ for (const Node& a : d_rset)
+ {
+ rset.insert(a);
+ }
+ }
+ return rset;
}
void RelevanceManager::notifyLemma(Node n)
{
- // only consider lemmas that were sent at full effort, when we have a
- // complete SAT assignment.
+ // notice that we may be in FULL or STANDARD effort here.
if (d_dman != nullptr)
{
// ensure we know which literals are relevant, and why
@@ -376,7 +420,7 @@ void RelevanceManager::notifyCandidateModel(TheoryModel* m)
{
if (d_dman != nullptr)
{
- d_dman->notifyCandidateModel(d_input, m);
+ d_dman->notifyCandidateModel(m);
}
}
diff --git a/src/theory/relevance_manager.h b/src/theory/relevance_manager.h
index fbc50801c..582a8a938 100644
--- a/src/theory/relevance_manager.h
+++ b/src/theory/relevance_manager.h
@@ -21,8 +21,12 @@
#include <unordered_map>
#include <unordered_set>
+#include "context/cdhashmap.h"
+#include "context/cdhashset.h"
#include "context/cdlist.h"
#include "expr/node.h"
+#include "expr/term_context.h"
+#include "smt/env_obj.h"
#include "theory/difficulty_manager.h"
#include "theory/valuation.h"
@@ -71,28 +75,42 @@ class TheoryModel;
* selection is computed lazily, i.e. only when someone asks if a literal is
* relevant, and only at most once per FULL effort check.
*/
-class RelevanceManager
+class RelevanceManager : protected EnvObj
{
- typedef context::CDList<Node> NodeList;
+ using RlvPair = std::pair<Node, uint32_t>;
+ using RlvPairHashFunction = PairHashFunction<Node, uint32_t, std::hash<Node>>;
+ using NodeList = context::CDList<Node>;
+ using NodeMap = context::CDHashMap<Node, Node>;
+ using NodeSet = context::CDHashSet<Node>;
+ using RlvPairIntMap =
+ context::CDHashMap<RlvPair, int32_t, RlvPairHashFunction>;
public:
/**
- * @param lemContext The context which lemmas live at
+ * @param env The environment
* @param val The valuation class, for computing what is relevant.
*/
- RelevanceManager(context::Context* lemContext, Valuation val);
+ RelevanceManager(Env& env, Valuation val);
/**
* Notify (preprocessed) assertions. This is called for input formulas or
* lemmas that need justification that have been fully processed, just before
* adding them to the PropEngine.
+ *
+ * @param assertions The assertions
+ * @param isInput Whether the assertions are preprocessed input assertions;
+ * this flag is false for lemmas.
*/
- void notifyPreprocessedAssertions(const std::vector<Node>& assertions);
+ void notifyPreprocessedAssertions(const std::vector<Node>& assertions,
+ bool isInput);
/** Singleton version of above */
- void notifyPreprocessedAssertion(Node n);
+ void notifyPreprocessedAssertion(Node n, bool isInput);
/**
- * Begin round, called at the beginning of a check in TheoryEngine.
+ * Begin round, called at the beginning of a full effort check in
+ * TheoryEngine.
*/
void beginRound();
+ /** End round, called at the end of a full effort check in TheoryEngine. */
+ void endRound();
/**
* Is lit part of the current relevant selection? This computes the set of
* relevant assertions if not already done so. This call is valid during a
@@ -110,8 +128,11 @@ class RelevanceManager
* the assertions we are notified of. This should never happen.
*
* The value of this return is only valid if success was not updated to false.
+ *
+ * Note that this returns a context-independent set to the user, which
+ * copies the assertions.
*/
- const std::unordered_set<TNode>& getRelevantAssertions(bool& success);
+ std::unordered_set<TNode> getRelevantAssertions(bool& success);
/** Notify lemma, for difficulty measurements */
void notifyLemma(Node n);
/** Notify that m is a (candidate) model, for difficulty measurements */
@@ -138,32 +159,32 @@ class RelevanceManager
* This method returns 1 if we justified n to be true, -1 means
* justified n to be false, 0 means n could not be justified.
*/
- int justify(TNode n, std::unordered_map<TNode, int>& cache);
+ int32_t justify(TNode n);
/** Is the top symbol of cur a Boolean connective? */
- bool isBooleanConnective(TNode cur);
+ static bool isBooleanConnective(TNode cur);
/**
* Update justify last child. This method is a helper function for justify,
* which is called at the moment that Boolean connective formula cur
- * has a new child that has been computed in the justify cache.
+ * has a new child that has been computed in the justify cache maintained
+ * by this class.
*
* @param cur The Boolean connective formula
* @param childrenJustify The values of the previous children (not including
* the current one)
- * @param cache The justify cache
* @return True if we wish to visit the next child. If this is the case, then
* the justify value of the current child is added to childrenJustify.
*/
- bool updateJustifyLastChild(TNode cur,
- std::vector<int>& childrenJustify,
- std::unordered_map<TNode, int>& cache);
+ bool updateJustifyLastChild(const RlvPair& cur,
+ std::vector<int32_t>& childrenJustify);
/** The valuation object, used to query current value of theory literals */
Valuation d_val;
/** The input assertions */
NodeList d_input;
- /** The current relevant selection. */
- std::unordered_set<TNode> d_rset;
- /** Have we computed the relevant selection this round? */
- bool d_computed;
+ /**
+ * The current relevant selection, SAT-context dependent, includes
+ * literals that are definitely relevant in this context.
+ */
+ NodeSet d_rset;
/** Are we in a full effort check? */
bool d_inFullEffortCheck;
/**
@@ -172,6 +193,8 @@ class RelevanceManager
* assignment since this class found that the input formula was not satisfied
* by the assignment. This should never happen, but if it does, this class
* aborts and indicates that all literals are relevant.
+ *
+ * This flag is only valid at FULL effort.
*/
bool d_success;
/** Are we tracking the sources of why a literal is relevant */
@@ -187,7 +210,19 @@ class RelevanceManager
* Map from the domain of d_rset to the assertion in d_input that is the
* reason why that literal is currently relevant.
*/
- std::map<TNode, TNode> d_rsetExp;
+ NodeMap d_rsetExp;
+ /** For computing polarity on terms */
+ PolarityTermContext d_ptctx;
+ /**
+ * Set of nodes that we have justified (SAT context dependent). This is SAT
+ * context dependent to avoid repeated calls to justify for uses of
+ * the relevance manager at standard effort. Notice that we pair each node
+ * with its polarity. We take into account the polarity of the node when
+ * computing relevance, where a node is only relevant if it is asserted
+ * and either does not have a polarity in the overall formula, or if its
+ * asserted value matches its polarity.
+ */
+ RlvPairIntMap d_jcache;
/** Difficulty module */
std::unique_ptr<DifficultyManager> d_dman;
};
diff --git a/src/theory/sets/cardinality_extension.cpp b/src/theory/sets/cardinality_extension.cpp
index e2181b4c6..7bb752acd 100644
--- a/src/theory/sets/cardinality_extension.cpp
+++ b/src/theory/sets/cardinality_extension.cpp
@@ -47,7 +47,7 @@ CardinalityExtension::CardinalityExtension(Env& env,
d_finite_type_constants_processed(false)
{
d_true = NodeManager::currentNM()->mkConst(true);
- d_zero = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(0));
+ d_zero = NodeManager::currentNM()->mkConstInt(Rational(0));
}
void CardinalityExtension::reset()
@@ -134,7 +134,7 @@ void CardinalityExtension::checkCardinalityExtended(TypeNode& t)
if (finiteType)
{
Node typeCardinality =
- nm->mkConst(CONST_RATIONAL, Rational(card.getFiniteCardinality()));
+ nm->mkConstInt(Rational(card.getFiniteCardinality()));
Node cardUniv = nm->mkNode(kind::SET_CARD, proxy);
Node leq = nm->mkNode(kind::LEQ, cardUniv, typeCardinality);
@@ -980,8 +980,8 @@ void CardinalityExtension::checkMinCard()
}
if (!members.empty())
{
- Node conc = nm->mkNode(
- GEQ, cardTerm, nm->mkConst(CONST_RATIONAL, Rational(members.size())));
+ Node conc =
+ nm->mkNode(GEQ, cardTerm, nm->mkConstInt(Rational(members.size())));
Node expn = exp.size() == 1 ? exp[0] : nm->mkNode(AND, exp);
d_im.assertInference(conc, InferenceId::SETS_CARD_MINIMAL, expn, 1);
}
diff --git a/src/theory/sets/theory_sets_private.cpp b/src/theory/sets/theory_sets_private.cpp
index f06580292..a08c051f6 100644
--- a/src/theory/sets/theory_sets_private.cpp
+++ b/src/theory/sets/theory_sets_private.cpp
@@ -59,7 +59,7 @@ TheorySetsPrivate::TheorySetsPrivate(Env& env,
{
d_true = NodeManager::currentNM()->mkConst(true);
d_false = NodeManager::currentNM()->mkConst(false);
- d_zero = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(0));
+ d_zero = NodeManager::currentNM()->mkConstInt(Rational(0));
}
TheorySetsPrivate::~TheorySetsPrivate()
@@ -1289,7 +1289,7 @@ void TheorySetsPrivate::preRegisterTerm(TNode node)
case kind::RELATION_JOIN_IMAGE:
{
// these are logic exceptions, not type checking exceptions
- if (node[1].getKind() != kind::CONST_RATIONAL)
+ if (!node[1].isConst())
{
throw LogicException(
"JoinImage cardinality constraint must be a constant");
diff --git a/src/theory/sets/theory_sets_rewriter.cpp b/src/theory/sets/theory_sets_rewriter.cpp
index d603946c4..cb9b26731 100644
--- a/src/theory/sets/theory_sets_rewriter.cpp
+++ b/src/theory/sets/theory_sets_rewriter.cpp
@@ -272,13 +272,12 @@ RewriteResponse TheorySetsRewriter::postRewrite(TNode node) {
{
if(node[0].isConst()) {
std::set<Node> elements = NormalForm::getElementsFromNormalConstant(node[0]);
- return RewriteResponse(
- REWRITE_DONE, nm->mkConst(CONST_RATIONAL, Rational(elements.size())));
+ return RewriteResponse(REWRITE_DONE,
+ nm->mkConstInt(Rational(elements.size())));
}
else if (node[0].getKind() == kind::SET_SINGLETON)
{
- return RewriteResponse(REWRITE_DONE,
- nm->mkConst(CONST_RATIONAL, Rational(1)));
+ return RewriteResponse(REWRITE_DONE, nm->mkConstInt(Rational(1)));
}
else if (node[0].getKind() == kind::SET_UNION)
{
diff --git a/src/theory/sort_inference.cpp b/src/theory/sort_inference.cpp
index 83062ce48..d44492259 100644
--- a/src/theory/sort_inference.cpp
+++ b/src/theory/sort_inference.cpp
@@ -405,10 +405,10 @@ int SortInference::process( Node n, std::map< Node, Node >& var_bound, std::map<
for( size_t i=0; i<n.getNumChildren(); i++ ){
bool processChild = true;
if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
- processChild =
- options::userPatternsQuant() == options::UserPatMode::IGNORE
- ? i == 1
- : i >= 1;
+ processChild = options().quantifiers.userPatternsQuant
+ == options::UserPatMode::IGNORE
+ ? i == 1
+ : i >= 1;
}
if( processChild ){
children.push_back( n[i] );
@@ -672,10 +672,10 @@ Node SortInference::simplifyNode(
for( size_t i=0; i<n.getNumChildren(); i++ ){
bool processChild = true;
if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
- processChild =
- options::userPatternsQuant() == options::UserPatMode::IGNORE
- ? i == 1
- : i >= 1;
+ processChild = options().quantifiers.userPatternsQuant
+ == options::UserPatMode::IGNORE
+ ? i == 1
+ : i >= 1;
}
if( processChild ){
if (isHandledApplyUf(n.getKind()))
diff --git a/src/theory/strings/arith_entail.cpp b/src/theory/strings/arith_entail.cpp
index 8eaa50354..19f1bc97d 100644
--- a/src/theory/strings/arith_entail.cpp
+++ b/src/theory/strings/arith_entail.cpp
@@ -32,7 +32,7 @@ namespace strings {
ArithEntail::ArithEntail(Rewriter* r) : d_rr(r)
{
- d_zero = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(0));
+ d_zero = NodeManager::currentNM()->mkConstInt(Rational(0));
}
Node ArithEntail::rewrite(Node a) { return d_rr->rewrite(a); }
@@ -76,11 +76,10 @@ bool ArithEntail::check(Node a, bool strict)
return a.getConst<Rational>().sgn() >= (strict ? 1 : 0);
}
- Node ar = strict ? NodeManager::currentNM()->mkNode(
- kind::MINUS,
- a,
- NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(1)))
- : a;
+ Node ar =
+ strict ? NodeManager::currentNM()->mkNode(
+ kind::MINUS, a, NodeManager::currentNM()->mkConstInt(Rational(1)))
+ : a;
ar = d_rr->rewrite(ar);
if (ar.getAttribute(StrCheckEntailArithComputedAttr()))
@@ -133,7 +132,7 @@ bool ArithEntail::checkApprox(Node ar)
<< "Get approximations " << v << "..." << std::endl;
if (v.isNull())
{
- Node mn = c.isNull() ? nm->mkConst(CONST_RATIONAL, Rational(1)) : c;
+ Node mn = c.isNull() ? nm->mkConstInt(Rational(1)) : c;
aarSum.push_back(mn);
}
else
@@ -496,8 +495,8 @@ void ArithEntail::getArithApproximations(Node a,
{
// x >= 0 implies
// x+1 >= len( int.to.str( x ) )
- approx.push_back(nm->mkNode(
- PLUS, nm->mkConst(CONST_RATIONAL, Rational(1)), a[0][0]));
+ approx.push_back(
+ nm->mkNode(PLUS, nm->mkConstInt(Rational(1)), a[0][0]));
}
}
}
@@ -507,7 +506,7 @@ void ArithEntail::getArithApproximations(Node a,
{
// x >= 0 implies
// len( int.to.str( x ) ) >= 1
- approx.push_back(nm->mkConst(CONST_RATIONAL, Rational(1)));
+ approx.push_back(nm->mkConstInt(Rational(1)));
}
// other crazy things are possible here, e.g.
// len( int.to.str( len( y ) + 10 ) ) >= 2
@@ -541,7 +540,7 @@ void ArithEntail::getArithApproximations(Node a,
// ...hard to test, runs risk of non-termination
// -1 <= indexof( x, y, n )
- approx.push_back(nm->mkConst(CONST_RATIONAL, Rational(-1)));
+ approx.push_back(nm->mkConstInt(Rational(-1)));
}
}
else if (ak == STRING_STOI)
@@ -556,7 +555,7 @@ void ArithEntail::getArithApproximations(Node a,
else
{
// -1 <= str.to.int( x )
- approx.push_back(nm->mkConst(CONST_RATIONAL, Rational(-1)));
+ approx.push_back(nm->mkConstInt(Rational(-1)));
}
}
Trace("strings-ent-approx-debug") << "Return " << approx.size() << std::endl;
@@ -661,9 +660,8 @@ bool ArithEntail::checkWithAssumption(Node assumption,
// (not (>= s t)) --> (>= (t - 1) s)
Assert(assumption.getKind() == kind::NOT
&& assumption[0].getKind() == kind::GEQ);
- x = nm->mkNode(kind::MINUS,
- assumption[0][1],
- nm->mkConst(CONST_RATIONAL, Rational(1)));
+ x = nm->mkNode(
+ kind::MINUS, assumption[0][1], nm->mkConstInt(Rational(1)));
y = assumption[0][0];
}
@@ -866,7 +864,7 @@ Node ArithEntail::getConstantBoundLength(TNode s, bool isLower) const
if (s.isConst())
{
size_t len = Word::getLength(s);
- ret = nm->mkConst(CONST_RATIONAL, Rational(len));
+ ret = nm->mkConstInt(Rational(len));
}
else if (s.getKind() == STRING_CONCAT)
{
@@ -885,12 +883,12 @@ Node ArithEntail::getConstantBoundLength(TNode s, bool isLower) const
success = false;
break;
}
- Assert(b.getKind() == CONST_RATIONAL);
+ Assert(b.isConst());
sum = sum + b.getConst<Rational>();
}
if (success && (!isLower || sum.sgn() != 0))
{
- ret = nm->mkConst(CONST_RATIONAL, sum);
+ ret = nm->mkConstInt(sum);
}
}
if (ret.isNull() && isLower)
diff --git a/src/theory/strings/array_core_solver.cpp b/src/theory/strings/array_core_solver.cpp
new file mode 100644
index 000000000..3b8fdeff4
--- /dev/null
+++ b/src/theory/strings/array_core_solver.cpp
@@ -0,0 +1,300 @@
+/******************************************************************************
+ * Top contributors (to current version):
+ * Andres Noetzli
+ *
+ * This file is part of the cvc5 project.
+ *
+ * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+ * in the top-level source directory and their institutional affiliations.
+ * All rights reserved. See the file COPYING in the top-level source
+ * directory for licensing information.
+ * ****************************************************************************
+ *
+ * Sequences solver for seq.nth/seq.update.
+ */
+
+#include "theory/strings/array_core_solver.h"
+
+#include "theory/strings/array_solver.h"
+#include "theory/strings/theory_strings_utils.h"
+#include "theory/strings/word.h"
+#include "util/rational.h"
+
+using namespace cvc5::context;
+using namespace cvc5::kind;
+
+namespace cvc5 {
+namespace theory {
+namespace strings {
+
+ArrayCoreSolver::ArrayCoreSolver(Env& env,
+ SolverState& s,
+ InferenceManager& im,
+ TermRegistry& tr,
+ CoreSolver& cs,
+ ExtfSolver& es,
+ ExtTheory& extt)
+ : EnvObj(env),
+ d_state(s),
+ d_im(im),
+ d_termReg(tr),
+ d_csolver(cs),
+ d_esolver(es),
+ d_extt(extt),
+ d_lem(context())
+{
+}
+
+ArrayCoreSolver::~ArrayCoreSolver() {}
+
+void ArrayCoreSolver::sendInference(const std::vector<Node>& exp,
+ const Node& lem,
+ const InferenceId iid)
+{
+ if (d_lem.find(lem) == d_lem.end())
+ {
+ d_lem.insert(lem);
+ Trace("seq-update") << "- send lemma - " << lem << std::endl;
+ d_im.sendInference(exp, lem, iid);
+ }
+}
+
+void ArrayCoreSolver::checkNth(const std::vector<Node>& nthTerms)
+{
+ NodeManager* nm = NodeManager::currentNM();
+ std::vector<Node> extractTerms = d_esolver.getActive(STRING_SUBSTR);
+ for (const Node& n : extractTerms)
+ {
+ if (d_termReg.isHandledUpdate(n))
+ {
+ // (seq.extract A i l) ^ (<= 0 i) ^ (< i (str.len A)) --> (seq.unit
+ // (seq.nth A i))
+ std::vector<Node> exp;
+ Node cond1 = nm->mkNode(LEQ, nm->mkConstInt(Rational(0)), n[1]);
+ Node cond2 = nm->mkNode(LT, n[1], nm->mkNode(STRING_LENGTH, n[0]));
+ Node cond = nm->mkNode(AND, cond1, cond2);
+ Node body1 = nm->mkNode(
+ EQUAL, n, nm->mkNode(SEQ_UNIT, nm->mkNode(SEQ_NTH, n[0], n[1])));
+ Node body2 = nm->mkNode(EQUAL, n, Word::mkEmptyWord(n.getType()));
+ Node lem = nm->mkNode(ITE, cond, body1, body2);
+ sendInference(exp, lem, InferenceId::STRINGS_ARRAY_NTH_EXTRACT);
+ }
+ }
+}
+
+void ArrayCoreSolver::checkUpdate(const std::vector<Node>& updateTerms)
+{
+ NodeManager* nm = NodeManager::currentNM();
+
+ Trace("seq-array-debug") << "updateTerms number: " << updateTerms.size()
+ << std::endl;
+ for (const Node& n : updateTerms)
+ {
+ // current term (seq.update x i a)
+
+ // inference rule is:
+ // (seq.update x i a) in TERMS
+ // (seq.nth t j) in TERMS
+ // t == (seq.update x i a)
+ // ----------------------------------------------------------------------
+ // (seq.nth (seq.update x i a) j) =
+ // (ITE, j in range(i, i+len(a)), (seq.nth a (j - i)), (seq.nth x j))
+
+ // t == (seq.update x i a) =>
+ // (seq.nth t j) = (ITE, j in range(i, i+len(a)), (seq.nth a (j - i)),
+ // (seq.nth x j))
+
+ // note that the term could rewrites to a skolem
+ // get proxy variable for the update term as t
+ Node termProxy = d_termReg.getProxyVariableFor(n);
+ Trace("seq-update") << "- " << termProxy << " = " << n << std::endl;
+ std::vector<Node> exp;
+ d_im.addToExplanation(termProxy, n, exp);
+
+ // optimization: add a short cut t == (seq.update n[0] n[1] n[2]) => t[i] ==
+ // n[2][0]
+ Node left = nm->mkNode(SEQ_NTH, termProxy, n[1]);
+ Node right =
+ nm->mkNode(SEQ_NTH, n[2], nm->mkConstInt(Rational(0))); // n[2][0]
+ right = Rewriter::rewrite(right);
+ Node lem = nm->mkNode(EQUAL, left, right);
+ Trace("seq-array-debug") << "enter" << std::endl;
+ sendInference(exp, lem, InferenceId::STRINGS_ARRAY_NTH_UPDATE);
+
+ // enumerate possible index
+ for (auto nth : d_index_map)
+ {
+ Node seq = nth.first;
+ if (d_state.areEqual(seq, n) || d_state.areEqual(seq, n[0]))
+ {
+ std::set<Node> indexes = nth.second;
+ for (Node j : indexes)
+ {
+ // optimization: add a short cut for special case (seq.update n[0]
+ // n[1] (seq.unit e))
+ if (n[2].getKind() == SEQ_UNIT)
+ {
+ left = nm->mkNode(DISTINCT, n[1], j);
+ Node nth1 = nm->mkNode(SEQ_NTH, termProxy, j);
+ Node nth2 = nm->mkNode(SEQ_NTH, n[0], j);
+ right = nm->mkNode(EQUAL, nth1, nth2);
+ lem = nm->mkNode(IMPLIES, left, right);
+ sendInference(exp, lem, InferenceId::STRINGS_ARRAY_NTH_UPDATE);
+ }
+
+ // normal cases
+ left = nm->mkNode(SEQ_NTH, termProxy, j);
+ Node cond = nm->mkNode(
+ AND,
+ nm->mkNode(LEQ, n[1], j),
+ nm->mkNode(
+ LT,
+ j,
+ nm->mkNode(PLUS, n[1], nm->mkNode(STRING_LENGTH, n[2]))));
+ Node body1 = nm->mkNode(SEQ_NTH, n[2], nm->mkNode(MINUS, j, n[1]));
+ Node body2 = nm->mkNode(SEQ_NTH, n[0], j);
+ right = nm->mkNode(ITE, cond, body1, body2);
+ lem = nm->mkNode(EQUAL, left, right);
+ sendInference(exp, lem, InferenceId::STRINGS_ARRAY_NTH_UPDATE);
+ }
+ }
+ }
+ }
+}
+
+void ArrayCoreSolver::check(const std::vector<Node>& nthTerms,
+ const std::vector<Node>& updateTerms)
+{
+ NodeManager* nm = NodeManager::currentNM();
+
+ Trace("seq-array-debug") << "NTH SIZE: " << nthTerms.size() << std::endl;
+ if (Trace.isOn("seq-array-terms"))
+ {
+ for (const Node& n : nthTerms)
+ {
+ Trace("seq-array-terms") << n << std::endl;
+ }
+ }
+ Trace("seq-array-debug") << "UPDATE SIZE: " << updateTerms.size()
+ << std::endl;
+ if (Trace.isOn("seq-array-terms"))
+ {
+ for (const Node& n : updateTerms)
+ {
+ Trace("seq-array-terms") << n << std::endl;
+ }
+ }
+ Trace("seq-update") << "SequencesArraySolver::check..." << std::endl;
+ d_writeModel.clear();
+ d_index_map.clear();
+ for (const Node& n : nthTerms)
+ {
+ // (seq.nth n[0] n[1])
+ Node r = d_state.getRepresentative(n[0]);
+ Trace("seq-update") << "- " << r << ": " << n[1] << " -> " << n
+ << std::endl;
+ d_writeModel[r][n[1]] = n;
+ if (d_index_map.find(r) == d_index_map.end())
+ {
+ std::set<Node> indexes;
+ indexes.insert(n[1]);
+ d_index_map[r] = indexes;
+ }
+ else
+ {
+ d_index_map[r].insert(n[1]);
+ }
+
+ if (n[0].getKind() == STRING_REV)
+ {
+ Node s = n[0][0];
+ Node i = n[1];
+ Node sLen = nm->mkNode(STRING_LENGTH, s);
+ Node iRev = nm->mkNode(
+ MINUS, sLen, nm->mkNode(PLUS, i, nm->mkConstInt(Rational(1))));
+
+ std::vector<Node> nexp;
+ nexp.push_back(nm->mkNode(LEQ, nm->mkConstInt(Rational(0)), i));
+ nexp.push_back(nm->mkNode(LT, i, sLen));
+
+ // 0 <= i ^ i < len(s) => seq.nth(seq.rev(s), i) = seq.nth(s, len(s) - i -
+ // 1)
+ Node ret = nm->mkNode(SEQ_NTH, s, iRev);
+ d_im.sendInference(
+ {}, nexp, n.eqNode(ret), InferenceId::STRINGS_ARRAY_NTH_REV);
+ d_extt.markReduced(n, ExtReducedId::STRINGS_NTH_REV);
+ }
+ }
+ checkNth(nthTerms);
+ checkUpdate(updateTerms);
+ // compute connected sequences
+ if (!d_im.hasSent())
+ {
+ computeConnected(updateTerms);
+ }
+}
+
+void ArrayCoreSolver::computeConnected(const std::vector<Node>& updateTerms)
+{
+ d_connectedSeq.clear();
+ std::map<Node, Node> conTmp;
+ std::map<Node, Node>::iterator it;
+ for (const Node& n : updateTerms)
+ {
+ Node newRep;
+ for (size_t i = 0; i < 2; i++)
+ {
+ Node s = i == 0 ? n[0] : n;
+ TNode r = d_state.getRepresentative(s);
+ // get the find
+ it = conTmp.find(r);
+ while (it != conTmp.end())
+ {
+ r = it->second;
+ it = conTmp.find(r);
+ }
+ if (i == 0)
+ {
+ newRep = r;
+ }
+ else if (newRep != r)
+ {
+ conTmp[newRep] = r;
+ }
+ }
+ }
+ // go back and normalize the find to representatives
+ for (std::pair<const Node, Node>& c : conTmp)
+ {
+ TNode r = c.first;
+ it = conTmp.find(r);
+ while (it != conTmp.end())
+ {
+ r = it->second;
+ it = conTmp.find(r);
+ }
+ d_connectedSeq[c.first] = r;
+ }
+}
+
+const std::map<Node, Node>& ArrayCoreSolver::getWriteModel(Node eqc)
+{
+ if (Trace.isOn("seq-write-model"))
+ {
+ Trace("seq-write-model") << "write model of " << eqc << ":" << std::endl;
+ for (auto& x : d_writeModel[eqc])
+ {
+ Trace("seq-write-model") << x.first << ": " << x.second << std::endl;
+ }
+ }
+ return d_writeModel[eqc];
+}
+
+const std::map<Node, Node>& ArrayCoreSolver::getConnectedSequences()
+{
+ return d_connectedSeq;
+}
+
+} // namespace strings
+} // namespace theory
+} // namespace cvc5
diff --git a/src/theory/strings/array_core_solver.h b/src/theory/strings/array_core_solver.h
new file mode 100644
index 000000000..3873f6a69
--- /dev/null
+++ b/src/theory/strings/array_core_solver.h
@@ -0,0 +1,146 @@
+/******************************************************************************
+ * Top contributors (to current version):
+ * Andres Noetzli
+ *
+ * This file is part of the cvc5 project.
+ *
+ * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+ * in the top-level source directory and their institutional affiliations.
+ * All rights reserved. See the file COPYING in the top-level source
+ * directory for licensing information.
+ * ****************************************************************************
+ *
+ * Sequences solver for seq.nth/seq.update.
+ */
+
+#include "cvc5_private.h"
+
+#ifndef CVC5__THEORY__STRINGS__ARRAY_CORE_SOLVER_H
+#define CVC5__THEORY__STRINGS__ARRAY_CORE_SOLVER_H
+
+#include "theory/strings/core_solver.h"
+#include "theory/strings/extf_solver.h"
+#include "theory/strings/inference_manager.h"
+#include "theory/strings/solver_state.h"
+#include "theory/strings/term_registry.h"
+
+namespace cvc5 {
+namespace theory {
+namespace strings {
+
+class ArrayCoreSolver : protected EnvObj
+{
+ public:
+ ArrayCoreSolver(Env& env,
+ SolverState& s,
+ InferenceManager& im,
+ TermRegistry& tr,
+ CoreSolver& cs,
+ ExtfSolver& es,
+ ExtTheory& extt);
+ ~ArrayCoreSolver();
+
+ /**
+ * Perform reasoning about seq.nth and seq.update operations.
+ *
+ * Can assume that seq.update / seq.nth terms only apply to concatenation-free
+ * equivalence classes.
+ */
+ void check(const std::vector<Node>& nthTerms,
+ const std::vector<Node>& updateTerms);
+
+ /**
+ *
+ * @param eqc The sequence equivalence class representative. We can assume
+ * the equivalence class of eqc contains no concatenation terms.
+ * @return the map corresponding to the model for eqc. The domain of
+ * the returned map should be in distinct integer equivalence classes of the
+ * equality engine of strings theory. The model assigned to eqc will be
+ * a skeleton constructed via seq.++ where the components take values from
+ * this map.
+ */
+ const std::map<Node, Node>& getWriteModel(Node eqc);
+
+ /**
+ * Get connected sequences, see documentation of computeConnected.
+ * @return a map M such that sequence equivalence class representatives x and
+ * y are connected if an only if M[x] = M[y].
+ */
+ const std::map<Node, Node>& getConnectedSequences();
+
+ private:
+ void sendInference(const std::vector<Node>& exp,
+ const Node& lem,
+ const InferenceId iid);
+
+ /**
+ * Perform reasoning about seq.nth operation.
+ * It handled the reduction from seq.extract to seq.nth, following the rule
+ * below: (t = (seq.extract A i 1)) ^ (0 <= i) ^ (i < (str.len A))
+ * ----------------------------------------------------------------------
+ * t = (seq.unit (seq.nth A i))
+ */
+ void checkNth(const std::vector<Node>& nthTerms);
+
+ /**
+ * Perform reasoning about seq.update operation.
+ * It handled the reduction from seq.update to seq.nth, following the rule
+ * below: (seq.update x i a) in TERMS (seq.nth t j) in TERMS t == (seq.update
+ * x i a)
+ * ----------------------------------------------------------------------
+ * (seq.nth (seq.update x i a) j) = (ITE, j in range(i, i+len(a)), (seq.nth a
+ * (j - i)), (seq.nth x j))
+ */
+ void checkUpdate(const std::vector<Node>& updateTerms);
+
+ /**
+ * Given the current set of update terms, this computes the connected
+ * sequences implied by the current equality information + this set of terms.
+ * Connected sequences is a reflexive transitive relation where additionally
+ * a and b are connected if there exists an update term (seq.update a n x)
+ * that is currently equal to b.
+ *
+ * This method runs a union find algorithm to compute all connected sequences.
+ *
+ * As a result of running this method, the map d_connectedSeq is populated
+ * with information regarding which sequences are connected.
+ */
+ void computeConnected(const std::vector<Node>& updateTerms);
+
+ /** The solver state object */
+ SolverState& d_state;
+ /** The (custom) output channel of the theory of strings */
+ InferenceManager& d_im;
+ /** Reference to the term registry of theory of strings */
+ TermRegistry& d_termReg;
+ /** reference to the core solver, used for certain queries */
+ CoreSolver& d_csolver;
+ /** reference to the extended solver, used for certain queries */
+ ExtfSolver& d_esolver;
+ /** the extended theory object for the theory of strings */
+ ExtTheory& d_extt;
+ /** The write model */
+ std::map<Node, std::map<Node, Node>> d_writeModel;
+ /**
+ * Map from sequences to their "connected representative". Two sequences are
+ * connected (based on the definition described in computeConnected) iff they
+ * have the same connected representative. Sequences that do not occur in
+ * this map are assumed to be their own connected representative.
+ *
+ * This map is only valid after running computeConnected, and is valid
+ * only during model building.
+ */
+ std::map<Node, Node> d_connectedSeq;
+ /** The set of lemmas been sent */
+ context::CDHashSet<Node> d_lem;
+
+ // ========= data structure =========
+ /** Map sequence variable to indices that occurred in nth terms */
+ std::map<Node, std::set<Node>> d_index_map;
+};
+
+} // namespace strings
+} // namespace theory
+} // namespace cvc5
+
+#endif
diff --git a/src/theory/strings/array_solver.cpp b/src/theory/strings/array_solver.cpp
index 65ff4cde4..672ca8b76 100644
--- a/src/theory/strings/array_solver.cpp
+++ b/src/theory/strings/array_solver.cpp
@@ -41,10 +41,11 @@ ArraySolver::ArraySolver(Env& env,
d_termReg(tr),
d_csolver(cs),
d_esolver(es),
+ d_coreSolver(env, s, im, tr, cs, es, extt),
d_eqProc(context())
{
NodeManager* nm = NodeManager::currentNM();
- d_zero = nm->mkConst(CONST_RATIONAL, Rational(0));
+ d_zero = nm->mkConstInt(Rational(0));
}
ArraySolver::~ArraySolver() {}
@@ -63,6 +64,32 @@ void ArraySolver::checkArrayConcat()
checkTerms(SEQ_NTH);
}
+void ArraySolver::checkArray()
+{
+ if (!d_termReg.hasSeqUpdate())
+ {
+ Trace("seq-array") << "No seq.update/seq.nth terms, skipping check..."
+ << std::endl;
+ return;
+ }
+ Trace("seq-array") << "ArraySolver::checkArray..." << std::endl;
+ d_coreSolver.check(d_currTerms[SEQ_NTH], d_currTerms[STRING_UPDATE]);
+}
+
+void ArraySolver::checkArrayEager()
+{
+ if (!d_termReg.hasSeqUpdate())
+ {
+ Trace("seq-array") << "No seq.update/seq.nth terms, skipping check..."
+ << std::endl;
+ return;
+ }
+ Trace("seq-array") << "ArraySolver::checkArray..." << std::endl;
+ std::vector<Node> nthTerms = d_esolver.getActive(SEQ_NTH);
+ std::vector<Node> updateTerms = d_esolver.getActive(STRING_UPDATE);
+ d_coreSolver.check(nthTerms, updateTerms);
+}
+
void ArraySolver::checkTerms(Kind k)
{
Assert(k == STRING_UPDATE || k == SEQ_NTH);
@@ -271,6 +298,16 @@ void ArraySolver::checkTerms(Kind k)
}
}
+const std::map<Node, Node>& ArraySolver::getWriteModel(Node eqc)
+{
+ return d_coreSolver.getWriteModel(eqc);
+}
+
+const std::map<Node, Node>& ArraySolver::getConnectedSequences()
+{
+ return d_coreSolver.getConnectedSequences();
+}
+
} // namespace strings
} // namespace theory
} // namespace cvc5
diff --git a/src/theory/strings/array_solver.h b/src/theory/strings/array_solver.h
index 941061e9e..23bacd118 100644
--- a/src/theory/strings/array_solver.h
+++ b/src/theory/strings/array_solver.h
@@ -19,6 +19,7 @@
#define CVC5__THEORY__STRINGS__ARRAY_SOLVER_H
#include "context/cdhashset.h"
+#include "theory/strings/array_core_solver.h"
#include "theory/strings/core_solver.h"
#include "theory/strings/extf_solver.h"
#include "theory/strings/inference_manager.h"
@@ -54,6 +55,32 @@ class ArraySolver : protected EnvObj
* their application to concatenation terms.
*/
void checkArrayConcat();
+ /**
+ * Perform reasoning about seq.nth and seq.update operations (lazily), which
+ * calls the core sequences-array solver for the set of nth/update terms over atomic
+ * equivalence classes.
+ */
+ void checkArray();
+ /**
+ * Same as `checkArray`, but called eagerly, and for all nth/update terms, not just
+ * those over atomic equivalence classes.
+ */
+ void checkArrayEager();
+
+ /**
+ * @param eqc The sequence equivalence class representative. We can assume
+ * the equivalence class of eqc contains no concatenation terms.
+ * @return the map corresponding to the model for eqc. The domain of
+ * the returned map should be in distinct integer equivalence classes of the
+ * equality engine of strings theory. The model assigned to eqc will be
+ * a skeleton constructed via seq.++ where the components take values from
+ * this map.
+ */
+ const std::map<Node, Node>& getWriteModel(Node eqc);
+ /**
+ * Get connected sequences from the core array solver.
+ */
+ const std::map<Node, Node>& getConnectedSequences();
private:
/** check terms of given kind */
@@ -72,6 +99,8 @@ class ArraySolver : protected EnvObj
std::map<Kind, std::vector<Node> > d_currTerms;
/** Common constants */
Node d_zero;
+ /** The core array solver */
+ ArrayCoreSolver d_coreSolver;
/** Equalities we have processed in the current context */
NodeSet d_eqProc;
};
diff --git a/src/theory/strings/base_solver.cpp b/src/theory/strings/base_solver.cpp
index 69d50a7d9..2d25a0d1e 100644
--- a/src/theory/strings/base_solver.cpp
+++ b/src/theory/strings/base_solver.cpp
@@ -604,8 +604,7 @@ void BaseSolver::checkCardinalityType(TypeNode tn,
if (lr.isConst())
{
// if constant, compare
- Node cmp =
- nm->mkNode(GEQ, lr, nm->mkConst(CONST_RATIONAL, Rational(card_need)));
+ Node cmp = nm->mkNode(GEQ, lr, nm->mkConstInt(Rational(card_need)));
cmp = rewrite(cmp);
needsSplit = !cmp.getConst<bool>();
}
@@ -619,7 +618,7 @@ void BaseSolver::checkCardinalityType(TypeNode tn,
bool success = true;
while (r < card_need && success)
{
- Node rr = nm->mkConst(CONST_RATIONAL, Rational(r));
+ Node rr = nm->mkConstInt(Rational(r));
if (d_state.areDisequal(rr, lr))
{
r++;
@@ -669,7 +668,7 @@ void BaseSolver::checkCardinalityType(TypeNode tn,
<< std::endl;
if (int_k + 1 > ei->d_cardinalityLemK.get())
{
- Node k_node = nm->mkConst(CONST_RATIONAL, Rational(int_k));
+ Node k_node = nm->mkConstInt(Rational(int_k));
// add cardinality lemma
Node dist = nm->mkNode(DISTINCT, cols[i]);
std::vector<Node> expn;
diff --git a/src/theory/strings/core_solver.cpp b/src/theory/strings/core_solver.cpp
index 46f75bd10..ab214c9ce 100644
--- a/src/theory/strings/core_solver.cpp
+++ b/src/theory/strings/core_solver.cpp
@@ -50,9 +50,9 @@ CoreSolver::CoreSolver(Env& env,
d_nfPairs(context()),
d_extDeq(userContext())
{
- d_zero = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(0));
- d_one = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(1));
- d_neg_one = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(-1));
+ d_zero = NodeManager::currentNM()->mkConstInt(Rational(0));
+ d_one = NodeManager::currentNM()->mkConstInt(Rational(1));
+ d_neg_one = NodeManager::currentNM()->mkConstInt(Rational(-1));
d_true = NodeManager::currentNM()->mkConst( true );
d_false = NodeManager::currentNM()->mkConst( false );
}
@@ -776,12 +776,12 @@ Node CoreSolver::getConclusion(Node x,
{
// we can assume its length is greater than zero
Node emp = Word::mkEmptyWord(sk1.getType());
- conc = nm->mkNode(AND,
- conc,
- sk1.eqNode(emp).negate(),
- nm->mkNode(GT,
- nm->mkNode(STRING_LENGTH, sk1),
- nm->mkConst(CONST_RATIONAL, Rational(0))));
+ conc = nm->mkNode(
+ AND,
+ conc,
+ sk1.eqNode(emp).negate(),
+ nm->mkNode(
+ GT, nm->mkNode(STRING_LENGTH, sk1), nm->mkConstInt(Rational(0))));
}
}
else if (rule == PfRule::CONCAT_CSPLIT)
diff --git a/src/theory/strings/eager_solver.cpp b/src/theory/strings/eager_solver.cpp
index ac8e815df..0e5c19658 100644
--- a/src/theory/strings/eager_solver.cpp
+++ b/src/theory/strings/eager_solver.cpp
@@ -227,7 +227,7 @@ bool EagerSolver::addArithmeticBound(EqcInfo* e, Node t, bool isLower)
Assert(e != nullptr);
Assert(!t.isNull());
Node tb = t.isConst() ? t : getBoundForLength(t, isLower);
- Assert(!tb.isNull() && tb.getKind() == CONST_RATIONAL)
+ Assert(!tb.isNull() && tb.isConst() && tb.getType().isInteger())
<< "Unexpected bound " << tb << " from " << t;
Rational br = tb.getConst<Rational>();
Node prev = isLower ? e->d_firstBound : e->d_secondBound;
@@ -236,7 +236,7 @@ bool EagerSolver::addArithmeticBound(EqcInfo* e, Node t, bool isLower)
{
// convert to bound
Node prevb = prev.isConst() ? prev : getBoundForLength(prev, isLower);
- Assert(!prevb.isNull() && prevb.getKind() == CONST_RATIONAL);
+ Assert(!prevb.isNull() && prevb.isConst() && prevb.getType().isInteger());
Rational prevbr = prevb.getConst<Rational>();
if (prevbr == br || (br < prevbr) == isLower)
{
@@ -251,7 +251,8 @@ bool EagerSolver::addArithmeticBound(EqcInfo* e, Node t, bool isLower)
{
// are we in conflict?
Node prevob = prevo.isConst() ? prevo : getBoundForLength(prevo, !isLower);
- Assert(!prevob.isNull() && prevob.getKind() == CONST_RATIONAL);
+ Assert(!prevob.isNull() && prevob.isConst()
+ && prevob.getType().isInteger());
Rational prevobr = prevob.getConst<Rational>();
if (prevobr != br && (prevobr < br) == isLower)
{
diff --git a/src/theory/strings/infer_proof_cons.cpp b/src/theory/strings/infer_proof_cons.cpp
index edfb91c64..81da50062 100644
--- a/src/theory/strings/infer_proof_cons.cpp
+++ b/src/theory/strings/infer_proof_cons.cpp
@@ -499,7 +499,7 @@ void InferProofCons::convert(InferenceId infer,
{
// it should be the case that lenConstraint => lenReq
lenReq = nm->mkNode(STRING_LENGTH, t0)
- .eqNode(nm->mkConst(CONST_RATIONAL, Rational(0)))
+ .eqNode(nm->mkConstInt(Rational(0)))
.notNode();
lenSuccess = convertLengthPf(lenReq, lenConstraint, psb);
rule = PfRule::CONCAT_CSPLIT;
@@ -530,7 +530,7 @@ void InferProofCons::convert(InferenceId infer,
{
// it should be the case that lenConstraint => lenReq
lenReq = nm->mkNode(STRING_LENGTH, t0)
- .eqNode(nm->mkConst(CONST_RATIONAL, Rational(0)))
+ .eqNode(nm->mkConstInt(Rational(0)))
.notNode();
lenSuccess = convertLengthPf(lenReq, lenConstraint, psb);
rule = PfRule::CONCAT_CPROP;
@@ -837,7 +837,7 @@ void InferProofCons::convert(InferenceId infer,
std::vector<Node> childrenAE;
childrenAE.push_back(eunf);
std::vector<Node> argsAE;
- argsAE.push_back(nm->mkConst(CONST_RATIONAL, Rational(0)));
+ argsAE.push_back(nm->mkConstInt(Rational(0)));
Node eunfAE = psb.tryStep(PfRule::AND_ELIM, childrenAE, argsAE);
Trace("strings-ipc-prefix")
<< "--- and elim to " << eunfAE << std::endl;
diff --git a/src/theory/strings/inference_manager.cpp b/src/theory/strings/inference_manager.cpp
index 5247e222d..c7020869f 100644
--- a/src/theory/strings/inference_manager.cpp
+++ b/src/theory/strings/inference_manager.cpp
@@ -51,8 +51,8 @@ InferenceManager::InferenceManager(Env& env,
: nullptr)
{
NodeManager* nm = NodeManager::currentNM();
- d_zero = nm->mkConst(CONST_RATIONAL, Rational(0));
- d_one = nm->mkConst(CONST_RATIONAL, Rational(1));
+ d_zero = nm->mkConstInt(Rational(0));
+ d_one = nm->mkConstInt(Rational(1));
d_true = nm->mkConst(true);
d_false = nm->mkConst(false);
}
diff --git a/src/theory/strings/proof_checker.cpp b/src/theory/strings/proof_checker.cpp
index edb38e702..dc01bb6d7 100644
--- a/src/theory/strings/proof_checker.cpp
+++ b/src/theory/strings/proof_checker.cpp
@@ -212,8 +212,8 @@ Node StringProofRuleChecker::checkInternal(PfRule id,
else if (id == PfRule::CONCAT_CSPLIT)
{
Assert(children.size() == 2);
- Node zero = nm->mkConst(CONST_RATIONAL, Rational(0));
- Node one = nm->mkConst(CONST_RATIONAL, Rational(1));
+ Node zero = nm->mkConstInt(Rational(0));
+ Node one = nm->mkConstInt(Rational(1));
if (children[1].getKind() != NOT || children[1][0].getKind() != EQUAL
|| children[1][0][0].getKind() != STRING_LENGTH
|| children[1][0][0][0] != t0 || children[1][0][1] != zero)
@@ -240,7 +240,7 @@ Node StringProofRuleChecker::checkInternal(PfRule id,
else if (id == PfRule::CONCAT_CPROP)
{
Assert(children.size() == 2);
- Node zero = nm->mkConst(CONST_RATIONAL, Rational(0));
+ Node zero = nm->mkConstInt(Rational(0));
Trace("pfcheck-strings-cprop")
<< "CONCAT_PROP, isRev=" << isRev << std::endl;
@@ -352,7 +352,7 @@ Node StringProofRuleChecker::checkInternal(PfRule id,
{
return Node::null();
}
- Node zero = nm->mkConst(CONST_RATIONAL, Rational(0));
+ Node zero = nm->mkConstInt(Rational(0));
Node clen = nm->mkNode(STRING_LENGTH, nemp[0][0]);
return clen.eqNode(zero).notNode();
}
@@ -462,7 +462,7 @@ Node StringProofRuleChecker::checkInternal(PfRule id,
&& args[1].getType().isStringLike());
Node c1 = nm->mkNode(STRING_TO_CODE, args[0]);
Node c2 = nm->mkNode(STRING_TO_CODE, args[1]);
- Node eqNegOne = c1.eqNode(nm->mkConst(CONST_RATIONAL, Rational(-1)));
+ Node eqNegOne = c1.eqNode(nm->mkConstInt(Rational(-1)));
Node deq = c1.eqNode(c2).negate();
Node eqn = args[0].eqNode(args[1]);
return nm->mkNode(kind::OR, eqNegOne, deq, eqn);
diff --git a/src/theory/strings/regexp_elim.cpp b/src/theory/strings/regexp_elim.cpp
index 8a96e22d2..477533bee 100644
--- a/src/theory/strings/regexp_elim.cpp
+++ b/src/theory/strings/regexp_elim.cpp
@@ -98,7 +98,7 @@ Node RegExpElimination::eliminateConcat(Node atom, bool isAgg)
Node x = atom[0];
Node lenx = nm->mkNode(STRING_LENGTH, x);
Node re = atom[1];
- Node zero = nm->mkConst(CONST_RATIONAL, Rational(0));
+ Node zero = nm->mkConstInt(Rational(0));
std::vector<Node> children;
utils::getConcat(re, children);
@@ -252,10 +252,8 @@ Node RegExpElimination::eliminateConcat(Node atom, bool isAgg)
if (gap_minsize[i] > 0)
{
// the gap to this child is at least gap_minsize[i]
- prev_end =
- nm->mkNode(PLUS,
- prev_end,
- nm->mkConst(CONST_RATIONAL, Rational(gap_minsize[i])));
+ prev_end = nm->mkNode(
+ PLUS, prev_end, nm->mkConstInt(Rational(gap_minsize[i])));
}
prev_ends.push_back(prev_end);
Node sc = sep_children[i];
@@ -280,8 +278,8 @@ Node RegExpElimination::eliminateConcat(Node atom, bool isAgg)
}
// if the gap after this one is strict, we need a non-greedy find
// thus, we add a symbolic constant
- Node cacheVal = BoundVarManager::getCacheValue(
- atom, nm->mkConst(CONST_RATIONAL, Rational(i)));
+ Node cacheVal =
+ BoundVarManager::getCacheValue(atom, nm->mkConstInt(Rational(i)));
TypeNode intType = nm->integerType();
Node k =
bvm->mkBoundVar<ReElimConcatIndexAttribute>(cacheVal, intType);
@@ -289,8 +287,7 @@ Node RegExpElimination::eliminateConcat(Node atom, bool isAgg)
prev_end = nm->mkNode(PLUS, prev_end, k);
}
Node curr = nm->mkNode(STRING_INDEXOF, x, sc, prev_end);
- Node idofFind =
- curr.eqNode(nm->mkConst(CONST_RATIONAL, Rational(-1))).negate();
+ Node idofFind = curr.eqNode(nm->mkConstInt(Rational(-1))).negate();
conj.push_back(idofFind);
prev_end = nm->mkNode(PLUS, curr, lensc);
}
@@ -305,7 +302,7 @@ Node RegExpElimination::eliminateConcat(Node atom, bool isAgg)
// then the last indexof/substr constraint entails the following
// constraint, so it is not necessary to add.
// Below, we may write "A" for (str.to.re "A") and _ for re.allchar:
- Node cEnd = nm->mkConst(CONST_RATIONAL, Rational(gap_minsize_end));
+ Node cEnd = nm->mkConstInt(Rational(gap_minsize_end));
if (gap_exact_end)
{
Assert(!sep_children.empty());
@@ -477,8 +474,8 @@ Node RegExpElimination::eliminateConcat(Node atom, bool isAgg)
}
else
{
- Node cacheVal = BoundVarManager::getCacheValue(
- atom, nm->mkConst(CONST_RATIONAL, Rational(i)));
+ Node cacheVal =
+ BoundVarManager::getCacheValue(atom, nm->mkConstInt(Rational(i)));
TypeNode intType = nm->integerType();
k = bvm->mkBoundVar<ReElimConcatIndexAttribute>(cacheVal, intType);
Node bound =
@@ -541,7 +538,7 @@ Node RegExpElimination::eliminateStar(Node atom, bool isAgg)
Node x = atom[0];
Node lenx = nm->mkNode(STRING_LENGTH, x);
Node re = atom[1];
- Node zero = nm->mkConst(CONST_RATIONAL, Rational(0));
+ Node zero = nm->mkConstInt(Rational(0));
// for regular expression star,
// if the period is a fixed constant, we can turn it into a bounded
// quantifier
@@ -561,8 +558,8 @@ Node RegExpElimination::eliminateStar(Node atom, bool isAgg)
std::vector<Node> char_constraints;
TypeNode intType = nm->integerType();
Node index = bvm->mkBoundVar<ReElimStarIndexAttribute>(atom, intType);
- Node substr_ch = nm->mkNode(
- STRING_SUBSTR, x, index, nm->mkConst(CONST_RATIONAL, Rational(1)));
+ Node substr_ch =
+ nm->mkNode(STRING_SUBSTR, x, index, nm->mkConstInt(Rational(1)));
substr_ch = Rewriter::rewrite(substr_ch);
// handle the case where it is purely characters
for (const Node& r : disj)
diff --git a/src/theory/strings/regexp_entail.cpp b/src/theory/strings/regexp_entail.cpp
index 645dc05cd..aa69f9ecf 100644
--- a/src/theory/strings/regexp_entail.cpp
+++ b/src/theory/strings/regexp_entail.cpp
@@ -30,8 +30,8 @@ namespace strings {
RegExpEntail::RegExpEntail(Rewriter* r) : d_rewriter(r), d_aent(r)
{
- d_zero = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(0));
- d_one = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(1));
+ d_zero = NodeManager::currentNM()->mkConstInt(Rational(0));
+ d_one = NodeManager::currentNM()->mkConstInt(Rational(1));
}
Node RegExpEntail::simpleRegexpConsume(std::vector<Node>& mchildren,
@@ -584,7 +584,7 @@ bool RegExpEntail::testConstStringInRegExp(cvc5::String& s,
}
else
{
- Node num2 = nm->mkConst(CONST_RATIONAL, cvc5::Rational(u - 1));
+ Node num2 = nm->mkConstInt(cvc5::Rational(u - 1));
Node r2 = nm->mkNode(REGEXP_LOOP, r[0], r[1], num2);
if (testConstStringInRegExp(s, index_start + len, r2))
{
@@ -616,7 +616,7 @@ bool RegExpEntail::testConstStringInRegExp(cvc5::String& s,
cvc5::String t = s.substr(index_start, len);
if (testConstStringInRegExp(t, 0, r[0]))
{
- Node num2 = nm->mkConst(CONST_RATIONAL, cvc5::Rational(l - 1));
+ Node num2 = nm->mkConstInt(cvc5::Rational(l - 1));
Node r2 = nm->mkNode(REGEXP_LOOP, r[0], num2, num2);
if (testConstStringInRegExp(s, index_start + len, r2))
{
@@ -668,7 +668,7 @@ Node RegExpEntail::getFixedLengthForRegexp(TNode n)
}
else if (k == REGEXP_ALLCHAR || k == REGEXP_RANGE)
{
- return nm->mkConst(CONST_RATIONAL, Rational(1));
+ return nm->mkConstInt(Rational(1));
}
else if (k == REGEXP_UNION || k == REGEXP_INTER)
{
@@ -749,7 +749,7 @@ Node RegExpEntail::getConstantBoundLengthForRegexp(TNode n, bool isLower) const
continue;
}
}
- Assert(bc.getKind() == CONST_RATIONAL);
+ Assert(bc.isConst() && bc.getType().isInteger());
Rational r = bc.getConst<Rational>();
if (k == REGEXP_CONCAT)
{
@@ -772,7 +772,7 @@ Node RegExpEntail::getConstantBoundLengthForRegexp(TNode n, bool isLower) const
// if we were successful and didn't ignore all components
if (success && !firstTime)
{
- ret = nm->mkConst(CONST_RATIONAL, rr);
+ ret = nm->mkConstInt(rr);
}
}
if (ret.isNull() && isLower)
diff --git a/src/theory/strings/regexp_operation.cpp b/src/theory/strings/regexp_operation.cpp
index a7ba37b18..eb6d2d355 100644
--- a/src/theory/strings/regexp_operation.cpp
+++ b/src/theory/strings/regexp_operation.cpp
@@ -37,10 +37,8 @@ RegExpOpr::RegExpOpr(Env& env, SkolemCache* sc)
d_false(NodeManager::currentNM()->mkConst(false)),
d_emptyRegexp(NodeManager::currentNM()->mkNode(kind::REGEXP_NONE,
std::vector<Node>{})),
- d_zero(NodeManager::currentNM()->mkConst(CONST_RATIONAL,
- ::cvc5::Rational(0))),
- d_one(NodeManager::currentNM()->mkConst(CONST_RATIONAL,
- ::cvc5::Rational(1))),
+ d_zero(NodeManager::currentNM()->mkConstInt(Rational(0))),
+ d_one(NodeManager::currentNM()->mkConstInt(Rational(1))),
d_sigma(NodeManager::currentNM()->mkNode(kind::REGEXP_ALLCHAR,
std::vector<Node>{})),
d_sigma_star(
@@ -911,7 +909,7 @@ Node RegExpOpr::reduceRegExpNeg(Node mem)
Node r = mem[0][1];
NodeManager* nm = NodeManager::currentNM();
Kind k = r.getKind();
- Node zero = nm->mkConst(CONST_RATIONAL, Rational(0));
+ Node zero = nm->mkConstInt(Rational(0));
Node conc;
if (k == REGEXP_CONCAT)
{
@@ -955,7 +953,7 @@ Node RegExpOpr::reduceRegExpNegConcatFixed(Node mem, Node reLen, size_t index)
Node r = mem[0][1];
NodeManager* nm = NodeManager::currentNM();
Assert(r.getKind() == REGEXP_CONCAT);
- Node zero = nm->mkConst(CONST_RATIONAL, Rational(0));
+ Node zero = nm->mkConstInt(Rational(0));
// The following simplification states that
// ~( s in R1 ++ R2 ++... ++ Rn )
// is equivalent to
@@ -1040,7 +1038,7 @@ Node RegExpOpr::reduceRegExpPos(Node mem,
}
else
{
- Node ivalue = nm->mkConst(CONST_RATIONAL, Rational(i));
+ Node ivalue = nm->mkConstInt(Rational(i));
Node sk = sm->mkSkolemFunction(SkolemFunId::RE_UNFOLD_POS_COMPONENT,
s.getType(),
{mem[0], mem[1], ivalue});
@@ -1321,10 +1319,8 @@ Node RegExpOpr::intersectInternal( Node r1, Node r2, std::map< PairNodes, Node >
rt = itr2->second;
} else {
std::map< PairNodes, Node > cache2(cache);
- cache2[p] = NodeManager::currentNM()->mkNode(
- kind::REGEXP_RV,
- NodeManager::currentNM()->mkConst(CONST_RATIONAL,
- cvc5::Rational(cnt)));
+ cache2[p] =
+ nm->mkNode(kind::REGEXP_RV, nm->mkConstInt(Rational(cnt)));
rt = intersectInternal(r1l, r2l, cache2, cnt+1);
cacheX[ pp ] = rt;
}
diff --git a/src/theory/strings/rewrites.cpp b/src/theory/strings/rewrites.cpp
index 4da6e5600..bfe9021aa 100644
--- a/src/theory/strings/rewrites.cpp
+++ b/src/theory/strings/rewrites.cpp
@@ -154,6 +154,7 @@ const char* toString(Rewrite r)
case Rewrite::UPD_CONST_INDEX_MAX_OOB: return "UPD_CONST_INDEX_MAX_OOB";
case Rewrite::UPD_CONST_INDEX_NEG: return "UPD_CONST_INDEX_NEG";
case Rewrite::UPD_CONST_INDEX_OOB: return "UPD_CONST_INDEX_OOB";
+ case Rewrite::UPD_REV: return "UPD_REV";
case Rewrite::STOI_CONCAT_NONNUM: return "STOI_CONCAT_NONNUM";
case Rewrite::STOI_EVAL: return "STOI_EVAL";
case Rewrite::STR_CONV_CONST: return "STR_CONV_CONST";
@@ -223,6 +224,7 @@ const char* toString(Rewrite r)
case Rewrite::SEQ_UNIT_EVAL: return "SEQ_UNIT_EVAL";
case Rewrite::SEQ_NTH_EVAL: return "SEQ_NTH_EVAL";
case Rewrite::SEQ_NTH_TOTAL_OOB: return "SEQ_NTH_TOTAL_OOB";
+ case Rewrite::SEQ_NTH_UNIT: return "SEQ_NTH_UNIT";
default: return "?";
}
}
diff --git a/src/theory/strings/rewrites.h b/src/theory/strings/rewrites.h
index c96dffcde..b57c5f276 100644
--- a/src/theory/strings/rewrites.h
+++ b/src/theory/strings/rewrites.h
@@ -155,6 +155,7 @@ enum class Rewrite : uint32_t
UPD_CONST_INDEX_MAX_OOB,
UPD_CONST_INDEX_NEG,
UPD_CONST_INDEX_OOB,
+ UPD_REV,
STOI_CONCAT_NONNUM,
STOI_EVAL,
STR_CONV_CONST,
@@ -223,7 +224,8 @@ enum class Rewrite : uint32_t
CHARAT_ELIM,
SEQ_UNIT_EVAL,
SEQ_NTH_EVAL,
- SEQ_NTH_TOTAL_OOB
+ SEQ_NTH_TOTAL_OOB,
+ SEQ_NTH_UNIT
};
/**
diff --git a/src/theory/strings/sequences_rewriter.cpp b/src/theory/strings/sequences_rewriter.cpp
index 1d82f9abd..1ccb67490 100644
--- a/src/theory/strings/sequences_rewriter.cpp
+++ b/src/theory/strings/sequences_rewriter.cpp
@@ -352,7 +352,7 @@ Node SequencesRewriter::rewriteStrEqualityExt(Node node)
}
else if (ne.getKind() == STRING_SUBSTR)
{
- Node zero = nm->mkConst(CONST_RATIONAL, Rational(0));
+ Node zero = nm->mkConstInt(Rational(0));
if (d_arithEntail.check(ne[1], false)
&& d_arithEntail.check(ne[2], true))
@@ -586,8 +586,7 @@ Node SequencesRewriter::rewriteLength(Node node)
Kind nk0 = node[0].getKind();
if (node[0].isConst())
{
- Node retNode =
- nm->mkConst(CONST_RATIONAL, Rational(Word::getLength(node[0])));
+ Node retNode = nm->mkConstInt(Rational(Word::getLength(node[0])));
return returnRewrite(node, retNode, Rewrite::LEN_EVAL);
}
else if (nk0 == kind::STRING_CONCAT)
@@ -600,8 +599,8 @@ Node SequencesRewriter::rewriteLength(Node node)
{
if (tmpNode[i].isConst())
{
- node_vec.push_back(nm->mkConst(
- CONST_RATIONAL, Rational(Word::getLength(tmpNode[i]))));
+ node_vec.push_back(
+ nm->mkConstInt(Rational(Word::getLength(tmpNode[i]))));
}
else
{
@@ -634,7 +633,7 @@ Node SequencesRewriter::rewriteLength(Node node)
}
else if (nk0 == SEQ_UNIT)
{
- Node retNode = nm->mkConst(CONST_RATIONAL, Rational(1));
+ Node retNode = nm->mkConstInt(Rational(1));
return returnRewrite(node, retNode, Rewrite::LEN_SEQ_UNIT);
}
return node;
@@ -1311,7 +1310,7 @@ Node SequencesRewriter::rewriteMembership(TNode node)
}
else if (r.getKind() == kind::REGEXP_ALLCHAR)
{
- Node one = nm->mkConst(CONST_RATIONAL, Rational(1));
+ Node one = nm->mkConstInt(Rational(1));
Node retNode = one.eqNode(nm->mkNode(STRING_LENGTH, x));
return returnRewrite(node, retNode, Rewrite::RE_IN_SIGMA);
}
@@ -1344,7 +1343,7 @@ Node SequencesRewriter::rewriteMembership(TNode node)
Node flr = RegExpEntail::getFixedLengthForRegexp(r[0]);
if (!flr.isNull())
{
- Node one = nm->mkConst(CONST_RATIONAL, Rational(1));
+ Node one = nm->mkConstInt(Rational(1));
if (flr == one)
{
NodeBuilder nb(AND);
@@ -1430,7 +1429,7 @@ Node SequencesRewriter::rewriteMembership(TNode node)
if (constStr.isNull())
{
// x in re.++(_*, _, _) ---> str.len(x) >= 2
- Node num = nm->mkConst(CONST_RATIONAL, Rational(allSigmaMinSize));
+ Node num = nm->mkConstInt(Rational(allSigmaMinSize));
Node lenx = nm->mkNode(STRING_LENGTH, x);
Node retNode = nm->mkNode(allSigmaStrict ? EQUAL : GEQ, lenx, num);
return returnRewrite(node, retNode, Rewrite::RE_CONCAT_PURE_ALLCHAR);
@@ -1722,10 +1721,9 @@ TrustNode SequencesRewriter::expandDefinition(Node node)
Node s = node[0];
Node n = node[1];
// seq.nth(s, n) --> ite(0 <= n < len(s), seq.nth_total(s,n), Uf(s, n))
- Node cond =
- nm->mkNode(AND,
- nm->mkNode(LEQ, nm->mkConst(CONST_RATIONAL, Rational(0)), n),
- nm->mkNode(LT, n, nm->mkNode(STRING_LENGTH, s)));
+ Node cond = nm->mkNode(AND,
+ nm->mkNode(LEQ, nm->mkConstInt(Rational(0)), n),
+ nm->mkNode(LT, n, nm->mkNode(STRING_LENGTH, s)));
Node ss = nm->mkNode(SEQ_NTH_TOTAL, s, n);
Node uf = SkolemCache::mkSkolemSeqNth(s.getType(), "Uf");
Node u = nm->mkNode(APPLY_UF, uf, s, n);
@@ -1761,22 +1759,22 @@ Node SequencesRewriter::rewriteSeqNth(Node node)
Node ret = nm->mkGroundValue(s.getType().getSequenceElementType());
return returnRewrite(node, ret, Rewrite::SEQ_NTH_TOTAL_OOB);
}
- else
- {
- return node;
- }
}
- else
+
+ if (s.getKind() == SEQ_UNIT && i.isConst() && i.getConst<Rational>().isZero())
{
- return node;
+ Node ret = s[0];
+ return returnRewrite(node, ret, Rewrite::SEQ_NTH_UNIT);
}
+
+ return node;
}
Node SequencesRewriter::rewriteCharAt(Node node)
{
Assert(node.getKind() == STRING_CHARAT);
NodeManager* nm = NodeManager::currentNM();
- Node one = nm->mkConst(CONST_RATIONAL, Rational(1));
+ Node one = nm->mkConstInt(Rational(1));
Node retNode = nm->mkNode(STRING_SUBSTR, node[0], node[1], one);
return returnRewrite(node, retNode, Rewrite::CHARAT_ELIM);
}
@@ -1854,7 +1852,7 @@ Node SequencesRewriter::rewriteSubstr(Node node)
}
}
}
- Node zero = nm->mkConst(CONST_RATIONAL, cvc5::Rational(0));
+ Node zero = nm->mkConstInt(cvc5::Rational(0));
// if entailed non-positive length or negative start point
if (d_arithEntail.check(zero, node[1], true))
@@ -2047,6 +2045,8 @@ Node SequencesRewriter::rewriteUpdate(Node node)
{
Assert(node.getKind() == kind::STRING_UPDATE);
Node s = node[0];
+ Node i = node[1];
+ Node x = node[2];
if (s.isConst())
{
if (Word::isEmpty(s))
@@ -2084,6 +2084,16 @@ Node SequencesRewriter::rewriteUpdate(Node node)
}
}
+ if (s.getKind() == STRING_REV)
+ {
+ NodeManager* nm = NodeManager::currentNM();
+ Node idx = nm->mkNode(MINUS,
+ nm->mkNode(STRING_LENGTH, s),
+ nm->mkNode(PLUS, i, nm->mkConst(Rational(1))));
+ Node ret = nm->mkNode(STRING_REV, nm->mkNode(STRING_UPDATE, s, idx, x));
+ return returnRewrite(node, ret, Rewrite::UPD_REV);
+ }
+
return node;
}
@@ -2453,7 +2463,7 @@ Node SequencesRewriter::rewriteIndexof(Node node)
if (node[2].isConst() && node[2].getConst<Rational>().sgn() < 0)
{
// z<0 implies str.indexof( x, y, z ) --> -1
- Node negone = nm->mkConst(CONST_RATIONAL, Rational(-1));
+ Node negone = nm->mkConstInt(Rational(-1));
return returnRewrite(node, negone, Rewrite::IDOF_NEG);
}
@@ -2471,7 +2481,7 @@ Node SequencesRewriter::rewriteIndexof(Node node)
// We know that, due to limitations on the size of string constants
// in our implementation, that accessing a position greater than
// rMaxInt is guaranteed to be out of bounds.
- Node negone = nm->mkConst(CONST_RATIONAL, Rational(-1));
+ Node negone = nm->mkConstInt(Rational(-1));
return returnRewrite(node, negone, Rewrite::IDOF_MAX);
}
Assert(node[2].getConst<Rational>().sgn() >= 0);
@@ -2482,13 +2492,12 @@ Node SequencesRewriter::rewriteIndexof(Node node)
std::size_t ret = Word::find(s, t, start);
if (ret != std::string::npos)
{
- Node retv =
- nm->mkConst(CONST_RATIONAL, Rational(static_cast<unsigned>(ret)));
+ Node retv = nm->mkConstInt(Rational(static_cast<unsigned>(ret)));
return returnRewrite(node, retv, Rewrite::IDOF_FIND);
}
else if (children0.size() == 1)
{
- Node negone = nm->mkConst(CONST_RATIONAL, Rational(-1));
+ Node negone = nm->mkConstInt(Rational(-1));
return returnRewrite(node, negone, Rewrite::IDOF_NFIND);
}
}
@@ -2500,14 +2509,14 @@ Node SequencesRewriter::rewriteIndexof(Node node)
if (node[2].getConst<Rational>().sgn() == 0)
{
// indexof( x, x, 0 ) --> 0
- Node zero = nm->mkConst(CONST_RATIONAL, Rational(0));
+ Node zero = nm->mkConstInt(Rational(0));
return returnRewrite(node, zero, Rewrite::IDOF_EQ_CST_START);
}
}
if (d_arithEntail.check(node[2], true))
{
// y>0 implies indexof( x, x, y ) --> -1
- Node negone = nm->mkConst(CONST_RATIONAL, Rational(-1));
+ Node negone = nm->mkConstInt(Rational(-1));
return returnRewrite(node, negone, Rewrite::IDOF_EQ_NSTART);
}
Node emp = Word::mkEmptyWord(stype);
@@ -2538,7 +2547,7 @@ Node SequencesRewriter::rewriteIndexof(Node node)
if (d_arithEntail.check(len1, len0m2, true))
{
// len(x)-z < len(y) implies indexof( x, y, z ) ----> -1
- Node negone = nm->mkConst(CONST_RATIONAL, Rational(-1));
+ Node negone = nm->mkConstInt(Rational(-1));
return returnRewrite(node, negone, Rewrite::IDOF_LEN);
}
@@ -2620,7 +2629,7 @@ Node SequencesRewriter::rewriteIndexof(Node node)
else
{
// str.contains( x, y ) --> false implies str.indexof(x,y,z) --> -1
- Node negone = nm->mkConst(CONST_RATIONAL, Rational(-1));
+ Node negone = nm->mkConstInt(Rational(-1));
return returnRewrite(node, negone, Rewrite::IDOF_NCTN);
}
}
@@ -2675,12 +2684,12 @@ Node SequencesRewriter::rewriteIndexofRe(Node node)
Node s = node[0];
Node r = node[1];
Node n = node[2];
- Node zero = nm->mkConst(CONST_RATIONAL, Rational(0));
+ Node zero = nm->mkConstInt(Rational(0));
Node slen = nm->mkNode(STRING_LENGTH, s);
if (d_arithEntail.check(zero, n, true) || d_arithEntail.check(n, slen, true))
{
- Node ret = nm->mkConst(CONST_RATIONAL, Rational(-1));
+ Node ret = nm->mkConstInt(Rational(-1));
return returnRewrite(node, ret, Rewrite::INDEXOF_RE_INVALID_INDEX);
}
@@ -2695,15 +2704,14 @@ Node SequencesRewriter::rewriteIndexofRe(Node node)
// We know that, due to limitations on the size of string constants
// in our implementation, that accessing a position greater than
// rMaxInt is guaranteed to be out of bounds.
- Node negone = nm->mkConst(CONST_RATIONAL, Rational(-1));
+ Node negone = nm->mkConstInt(Rational(-1));
return returnRewrite(node, negone, Rewrite::INDEXOF_RE_MAX_INDEX);
}
uint32_t start = nrat.getNumerator().toUnsignedInt();
Node rem = nm->mkConst(s.getConst<String>().substr(start));
std::pair<size_t, size_t> match = firstMatch(rem, r);
- Node ret = nm->mkConst(
- CONST_RATIONAL,
+ Node ret = nm->mkConstInt(
Rational(match.first == string::npos
? -1
: static_cast<int64_t>(start + match.first)));
@@ -2967,8 +2975,8 @@ Node SequencesRewriter::rewriteReplace(Node node)
nm->mkNode(kind::STRING_LENGTH, utils::mkConcat(children1, stype));
Node maxLen1 = nm->mkNode(kind::PLUS, partLen1, lastChild1[2]);
- Node zero = nm->mkConst(CONST_RATIONAL, Rational(0));
- Node one = nm->mkConst(CONST_RATIONAL, Rational(1));
+ Node zero = nm->mkConstInt(Rational(0));
+ Node one = nm->mkConstInt(Rational(1));
Node len0 = nm->mkNode(kind::STRING_LENGTH, node[0]);
Node len0_1 = nm->mkNode(kind::PLUS, len0, one);
// Check len(t) + j > len(x) + 1
@@ -3491,8 +3499,7 @@ Node SequencesRewriter::rewritePrefixSuffix(Node n)
Node val;
if (isPrefix)
{
- val =
- NodeManager::currentNM()->mkConst(CONST_RATIONAL, ::cvc5::Rational(0));
+ val = NodeManager::currentNM()->mkConstInt(::cvc5::Rational(0));
}
else
{
@@ -3527,7 +3534,7 @@ Node SequencesRewriter::canonicalStrForSymbolicLength(Node len, TypeNode stype)
NodeManager* nm = NodeManager::currentNM();
Node res;
- if (len.getKind() == CONST_RATIONAL)
+ if (len.isConst())
{
// c -> "A" repeated c times
Rational ratLen = len.getConst<Rational>();
diff --git a/src/theory/strings/skolem_cache.cpp b/src/theory/strings/skolem_cache.cpp
index eb09ff187..03c9f9375 100644
--- a/src/theory/strings/skolem_cache.cpp
+++ b/src/theory/strings/skolem_cache.cpp
@@ -54,7 +54,7 @@ SkolemCache::SkolemCache(Rewriter* rr) : d_rr(rr)
{
NodeManager* nm = NodeManager::currentNM();
d_strType = nm->stringType();
- d_zero = nm->mkConst(CONST_RATIONAL, Rational(0));
+ d_zero = nm->mkConstInt(Rational(0));
}
Node SkolemCache::mkSkolemCached(Node a, Node b, SkolemId id, const char* c)
@@ -217,27 +217,26 @@ SkolemCache::normalizeStringSkolem(SkolemId id, Node a, Node b)
{
// SK_ID_VC_SPT(x, y) ---> SK_SUFFIX_REM(x, 1)
id = SK_SUFFIX_REM;
- b = nm->mkConst(CONST_RATIONAL, Rational(1));
+ b = nm->mkConstInt(Rational(1));
}
else if (id == SK_ID_VC_SPT_REV)
{
// SK_ID_VC_SPT_REV(x, y) ---> SK_PREFIX(x, (- (str.len x) 1))
id = SK_PREFIX;
- b = nm->mkNode(MINUS,
- nm->mkNode(STRING_LENGTH, a),
- nm->mkConst(CONST_RATIONAL, Rational(1)));
+ b = nm->mkNode(
+ MINUS, nm->mkNode(STRING_LENGTH, a), nm->mkConstInt(Rational(1)));
}
else if (id == SK_ID_DC_SPT)
{
// SK_ID_DC_SPT(x, y) ---> SK_PREFIX(x, 1)
id = SK_PREFIX;
- b = nm->mkConst(CONST_RATIONAL, Rational(1));
+ b = nm->mkConstInt(Rational(1));
}
else if (id == SK_ID_DC_SPT_REM)
{
// SK_ID_DC_SPT_REM(x, y) ---> SK_SUFFIX_REM(x, 1)
id = SK_SUFFIX_REM;
- b = nm->mkConst(CONST_RATIONAL, Rational(1));
+ b = nm->mkConstInt(Rational(1));
}
else if (id == SK_ID_DEQ_X)
{
diff --git a/src/theory/strings/solver_state.cpp b/src/theory/strings/solver_state.cpp
index 045347cbb..6b7fc699b 100644
--- a/src/theory/strings/solver_state.cpp
+++ b/src/theory/strings/solver_state.cpp
@@ -34,7 +34,7 @@ SolverState::SolverState(Env& env, Valuation& v)
d_pendingConflictSet(env.getContext(), false),
d_pendingConflict(InferenceId::UNKNOWN)
{
- d_zero = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(0));
+ d_zero = NodeManager::currentNM()->mkConstInt(Rational(0));
d_false = NodeManager::currentNM()->mkConst(false);
}
diff --git a/src/theory/strings/strategy.cpp b/src/theory/strings/strategy.cpp
index 7338b99fd..921a676d7 100644
--- a/src/theory/strings/strategy.cpp
+++ b/src/theory/strings/strategy.cpp
@@ -43,7 +43,7 @@ std::ostream& operator<<(std::ostream& out, InferStep s)
return out;
}
-Strategy::Strategy() : d_strategy_init(false) {}
+Strategy::Strategy(Env& env) : EnvObj(env), d_strategy_init(false) {}
Strategy::~Strategy() {}
@@ -93,7 +93,7 @@ void Strategy::initializeStrategy()
d_strategy_init = true;
// beginning indices
step_begin[Theory::EFFORT_FULL] = 0;
- if (options::stringEager())
+ if (options().strings.stringEager)
{
step_begin[Theory::EFFORT_STANDARD] = 0;
}
@@ -103,45 +103,45 @@ void Strategy::initializeStrategy()
addStrategyStep(CHECK_EXTF_EVAL, 0);
// we must check cycles before using flat forms
addStrategyStep(CHECK_CYCLES);
- if (options::stringFlatForms())
+ if (options().strings.stringFlatForms)
{
addStrategyStep(CHECK_FLAT_FORMS);
}
addStrategyStep(CHECK_EXTF_REDUCTION, 1);
- if (options::stringEager())
+ if (options().strings.stringEager)
{
// do only the above inferences at standard effort, if applicable
step_end[Theory::EFFORT_STANDARD] = d_infer_steps.size() - 1;
}
- if (!options::stringEagerLen())
+ if (!options().strings.stringEagerLen)
{
addStrategyStep(CHECK_REGISTER_TERMS_PRE_NF);
}
addStrategyStep(CHECK_NORMAL_FORMS_EQ);
addStrategyStep(CHECK_EXTF_EVAL, 1);
- if (!options::stringEagerLen() && options::stringLenNorm())
+ if (!options().strings.stringEagerLen && options().strings.stringLenNorm)
{
addStrategyStep(CHECK_LENGTH_EQC, 0, false);
addStrategyStep(CHECK_REGISTER_TERMS_NF);
}
addStrategyStep(CHECK_NORMAL_FORMS_DEQ);
addStrategyStep(CHECK_CODES);
- if (options::stringEagerLen() && options::stringLenNorm())
+ if (options().strings.stringEagerLen && options().strings.stringLenNorm)
{
addStrategyStep(CHECK_LENGTH_EQC);
}
- if (options::stringExp())
+ if (options().strings.stringExp)
{
addStrategyStep(CHECK_EXTF_REDUCTION, 2);
}
addStrategyStep(CHECK_MEMBERSHIP);
addStrategyStep(CHECK_CARDINALITY);
step_end[Theory::EFFORT_FULL] = d_infer_steps.size() - 1;
- if (options::stringModelBasedReduction())
+ if (options().strings.stringModelBasedReduction)
{
step_begin[Theory::EFFORT_LAST_CALL] = d_infer_steps.size();
addStrategyStep(CHECK_EXTF_EVAL, 3);
- if (options::stringExp())
+ if (options().strings.stringExp)
{
addStrategyStep(CHECK_EXTF_REDUCTION, 3);
}
diff --git a/src/theory/strings/strategy.h b/src/theory/strings/strategy.h
index c390c5594..48253c64a 100644
--- a/src/theory/strings/strategy.h
+++ b/src/theory/strings/strategy.h
@@ -74,10 +74,10 @@ std::ostream& operator<<(std::ostream& out, InferStep i);
* This stores a sequence of the above enum that indicates the calls to
* runInferStep to make on the theory of strings, given by parent.
*/
-class Strategy
+class Strategy : protected EnvObj
{
public:
- Strategy();
+ Strategy(Env& env);
~Strategy();
/** is this strategy initialized? */
bool isStrategyInit() const;
diff --git a/src/theory/strings/strings_entail.cpp b/src/theory/strings/strings_entail.cpp
index 6e4ba25a5..952a1a36b 100644
--- a/src/theory/strings/strings_entail.cpp
+++ b/src/theory/strings/strings_entail.cpp
@@ -123,7 +123,7 @@ bool StringsEntail::stripSymbolicLength(std::vector<Node>& n1,
Assert(dir == 1 || dir == -1);
Assert(nr.empty());
NodeManager* nm = NodeManager::currentNM();
- Node zero = nm->mkConst(CONST_RATIONAL, cvc5::Rational(0));
+ Node zero = nm->mkConstInt(cvc5::Rational(0));
bool ret = false;
bool success = true;
unsigned sindex = 0;
@@ -145,7 +145,7 @@ bool StringsEntail::stripSymbolicLength(std::vector<Node>& n1,
Assert(d_arithEntail.check(curr, true));
Node s = n1[sindex_use];
size_t slen = Word::getLength(s);
- Node ncl = nm->mkConst(CONST_RATIONAL, cvc5::Rational(slen));
+ Node ncl = nm->mkConstInt(cvc5::Rational(slen));
Node next_s = nm->mkNode(MINUS, lowerBound, ncl);
next_s = d_rr->rewrite(next_s);
Assert(next_s.isConst());
@@ -461,7 +461,7 @@ bool StringsEntail::componentContainsBase(
{
n1rb = nm->mkNode(STRING_SUBSTR,
n2[0],
- nm->mkConst(CONST_RATIONAL, Rational(0)),
+ nm->mkConstInt(Rational(0)),
start_pos);
}
if (dir != 1)
@@ -714,7 +714,7 @@ bool StringsEntail::checkNonEmpty(Node a)
bool StringsEntail::checkLengthOne(Node s, bool strict)
{
NodeManager* nm = NodeManager::currentNM();
- Node one = nm->mkConst(CONST_RATIONAL, Rational(1));
+ Node one = nm->mkConstInt(Rational(1));
Node len = nm->mkNode(STRING_LENGTH, s);
len = d_rr->rewrite(len);
return d_arithEntail.check(one, len)
diff --git a/src/theory/strings/strings_fmf.cpp b/src/theory/strings/strings_fmf.cpp
index 2951c86a2..a3ae03099 100644
--- a/src/theory/strings/strings_fmf.cpp
+++ b/src/theory/strings/strings_fmf.cpp
@@ -85,8 +85,7 @@ Node StringsFmf::StringSumLengthDecisionStrategy::mkLiteral(unsigned i)
return Node::null();
}
NodeManager* nm = NodeManager::currentNM();
- Node lit = nm->mkNode(
- LEQ, d_inputVarLsum.get(), nm->mkConst(CONST_RATIONAL, Rational(i)));
+ Node lit = nm->mkNode(LEQ, d_inputVarLsum.get(), nm->mkConstInt(Rational(i)));
Trace("strings-fmf") << "StringsFMF::mkLiteral: " << lit << std::endl;
return lit;
}
diff --git a/src/theory/strings/strings_rewriter.cpp b/src/theory/strings/strings_rewriter.cpp
index e4b91d4d8..2ff7598b5 100644
--- a/src/theory/strings/strings_rewriter.cpp
+++ b/src/theory/strings/strings_rewriter.cpp
@@ -100,11 +100,11 @@ Node StringsRewriter::rewriteStrToInt(Node node)
String s = node[0].getConst<String>();
if (s.isNumber())
{
- ret = nm->mkConst(CONST_RATIONAL, s.toNumber());
+ ret = nm->mkConstInt(s.toNumber());
}
else
{
- ret = nm->mkConst(CONST_RATIONAL, Rational(-1));
+ ret = nm->mkConstInt(Rational(-1));
}
return returnRewrite(node, ret, Rewrite::STOI_EVAL);
}
@@ -117,7 +117,7 @@ Node StringsRewriter::rewriteStrToInt(Node node)
String t = nc.getConst<String>();
if (!t.isNumber())
{
- Node ret = nm->mkConst(CONST_RATIONAL, Rational(-1));
+ Node ret = nm->mkConstInt(Rational(-1));
return returnRewrite(node, ret, Rewrite::STOI_CONCAT_NONNUM);
}
}
@@ -303,11 +303,11 @@ Node StringsRewriter::rewriteStringToCode(Node n)
{
std::vector<unsigned> vec = s.getVec();
Assert(vec.size() == 1);
- ret = nm->mkConst(CONST_RATIONAL, Rational(vec[0]));
+ ret = nm->mkConstInt(Rational(vec[0]));
}
else
{
- ret = nm->mkConst(CONST_RATIONAL, Rational(-1));
+ ret = nm->mkConstInt(Rational(-1));
}
return returnRewrite(n, ret, Rewrite::TO_CODE_EVAL);
}
@@ -320,10 +320,9 @@ Node StringsRewriter::rewriteStringIsDigit(Node n)
NodeManager* nm = NodeManager::currentNM();
// eliminate str.is_digit(s) ----> 48 <= str.to_code(s) <= 57
Node t = nm->mkNode(STRING_TO_CODE, n[0]);
- Node retNode =
- nm->mkNode(AND,
- nm->mkNode(LEQ, nm->mkConst(CONST_RATIONAL, Rational(48)), t),
- nm->mkNode(LEQ, t, nm->mkConst(CONST_RATIONAL, Rational(57))));
+ Node retNode = nm->mkNode(AND,
+ nm->mkNode(LEQ, nm->mkConstInt(Rational(48)), t),
+ nm->mkNode(LEQ, t, nm->mkConstInt(Rational(57))));
return returnRewrite(n, retNode, Rewrite::IS_DIGIT_ELIM);
}
diff --git a/src/theory/strings/term_registry.cpp b/src/theory/strings/term_registry.cpp
index 85027370e..d2d723276 100644
--- a/src/theory/strings/term_registry.cpp
+++ b/src/theory/strings/term_registry.cpp
@@ -60,9 +60,9 @@ TermRegistry::TermRegistry(Env& env,
: nullptr)
{
NodeManager* nm = NodeManager::currentNM();
- d_zero = nm->mkConst(CONST_RATIONAL, Rational(0));
- d_one = nm->mkConst(CONST_RATIONAL, Rational(1));
- d_negOne = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(-1));
+ d_zero = nm->mkConstInt(Rational(0));
+ d_one = nm->mkConstInt(Rational(1));
+ d_negOne = NodeManager::currentNM()->mkConstInt(Rational(-1));
Assert(options().strings.stringsAlphaCard <= String::num_codes());
d_alphaCard = options().strings.stringsAlphaCard;
}
@@ -81,13 +81,12 @@ Node TermRegistry::eagerReduce(Node t, SkolemCache* sc, uint32_t alphaCard)
if (tk == STRING_TO_CODE)
{
// ite( str.len(s)==1, 0 <= str.code(s) < |A|, str.code(s)=-1 )
- Node code_len =
- utils::mkNLength(t[0]).eqNode(nm->mkConst(CONST_RATIONAL, Rational(1)));
- Node code_eq_neg1 = t.eqNode(nm->mkConst(CONST_RATIONAL, Rational(-1)));
- Node code_range = nm->mkNode(
- AND,
- nm->mkNode(GEQ, t, nm->mkConst(CONST_RATIONAL, Rational(0))),
- nm->mkNode(LT, t, nm->mkConst(CONST_RATIONAL, Rational(alphaCard))));
+ Node code_len = utils::mkNLength(t[0]).eqNode(nm->mkConstInt(Rational(1)));
+ Node code_eq_neg1 = t.eqNode(nm->mkConstInt(Rational(-1)));
+ Node code_range =
+ nm->mkNode(AND,
+ nm->mkNode(GEQ, t, nm->mkConstInt(Rational(0))),
+ nm->mkNode(LT, t, nm->mkConstInt(Rational(alphaCard))));
lemma = nm->mkNode(ITE, code_len, code_range, code_eq_neg1);
}
else if (tk == STRING_INDEXOF || tk == STRING_INDEXOF_RE)
@@ -98,17 +97,16 @@ Node TermRegistry::eagerReduce(Node t, SkolemCache* sc, uint32_t alphaCard)
//
// where f in { str.indexof, str.indexof_re }
Node l = nm->mkNode(STRING_LENGTH, t[0]);
- lemma = nm->mkNode(
- AND,
- nm->mkNode(OR,
- t.eqNode(nm->mkConst(CONST_RATIONAL, Rational(-1))),
- nm->mkNode(GEQ, t, t[2])),
- nm->mkNode(LEQ, t, l));
+ lemma = nm->mkNode(AND,
+ nm->mkNode(OR,
+ t.eqNode(nm->mkConstInt(Rational(-1))),
+ nm->mkNode(GEQ, t, t[2])),
+ nm->mkNode(LEQ, t, l));
}
else if (tk == STRING_STOI)
{
// (>= (str.to_int x) (- 1))
- lemma = nm->mkNode(GEQ, t, nm->mkConst(CONST_RATIONAL, Rational(-1)));
+ lemma = nm->mkNode(GEQ, t, nm->mkConstInt(Rational(-1)));
}
else if (tk == STRING_CONTAINS)
{
@@ -126,7 +124,7 @@ Node TermRegistry::eagerReduce(Node t, SkolemCache* sc, uint32_t alphaCard)
Node TermRegistry::lengthPositive(Node t)
{
NodeManager* nm = NodeManager::currentNM();
- Node zero = nm->mkConst(CONST_RATIONAL, Rational(0));
+ Node zero = nm->mkConstInt(Rational(0));
Node emp = Word::mkEmptyWord(t.getType());
Node tlen = nm->mkNode(STRING_LENGTH, t);
Node tlenEqZero = tlen.eqNode(zero);
@@ -416,7 +414,7 @@ TrustNode TermRegistry::getRegisterTermLemma(Node n)
}
else if (n.isConst())
{
- lsum = nm->mkConst(CONST_RATIONAL, Rational(Word::getLength(n)));
+ lsum = nm->mkConstInt(Rational(Word::getLength(n)));
}
Assert(!lsum.isNull());
d_proxyVarToLength[sk] = lsum;
@@ -486,7 +484,7 @@ bool TermRegistry::isHandledUpdate(Node n)
{
lenN = nm->mkNode(STRING_LENGTH, n[2]);
}
- Node one = nm->mkConst(CONST_RATIONAL, Rational(1));
+ Node one = nm->mkConstInt(Rational(1));
return d_aent.checkEq(lenN, one);
}
diff --git a/src/theory/strings/theory_strings.cpp b/src/theory/strings/theory_strings.cpp
index 557dd7783..25db8d190 100644
--- a/src/theory/strings/theory_strings.cpp
+++ b/src/theory/strings/theory_strings.cpp
@@ -81,13 +81,14 @@ TheoryStrings::TheoryStrings(Env& env, OutputChannel& out, Valuation valuation)
d_rsolver(
env, d_state, d_im, d_termReg, d_csolver, d_esolver, d_statistics),
d_regexp_elim(options().strings.regExpElimAgg, d_pnm, userContext()),
- d_stringsFmf(env, valuation, d_termReg)
+ d_stringsFmf(env, valuation, d_termReg),
+ d_strat(d_env)
{
d_termReg.finishInit(&d_im);
- d_zero = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(0));
- d_one = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(1));
- d_neg_one = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(-1));
+ d_zero = NodeManager::currentNM()->mkConstInt(Rational(0));
+ d_one = NodeManager::currentNM()->mkConstInt(Rational(1));
+ d_neg_one = NodeManager::currentNM()->mkConstInt(Rational(-1));
d_true = NodeManager::currentNM()->mkConst( true );
d_false = NodeManager::currentNM()->mkConst( false );
@@ -426,7 +427,7 @@ bool TheoryStrings::collectModelInfoType(
lvalue++;
}
Trace("strings-model") << "*** Decide to make length of " << lvalue << std::endl;
- lts_values[i] = nm->mkConst(CONST_RATIONAL, Rational(lvalue));
+ lts_values[i] = nm->mkConstInt(Rational(lvalue));
values_used[lvalue] = Node::null();
}
Trace("strings-model") << "Need to assign values of length " << lts_values[i] << " to equivalence classes ";
@@ -1081,8 +1082,7 @@ TrustNode TheoryStrings::ppRewrite(TNode atom, std::vector<SkolemLemma>& lems)
SkolemCache* sc = d_termReg.getSkolemCache();
Node k = sc->mkSkolemCached(atom, SkolemCache::SK_PURIFY, "kFromCode");
Node t = atom[0];
- Node card = nm->mkConst(CONST_RATIONAL,
- Rational(d_termReg.getAlphabetCardinality()));
+ Node card = nm->mkConstInt(Rational(d_termReg.getAlphabetCardinality()));
Node cond =
nm->mkNode(AND, nm->mkNode(LEQ, d_zero, t), nm->mkNode(LT, t, card));
Node emp = Word::mkEmptyWord(atom.getType());
diff --git a/src/theory/strings/theory_strings_preprocess.cpp b/src/theory/strings/theory_strings_preprocess.cpp
index 4f27371ff..4c2319b4e 100644
--- a/src/theory/strings/theory_strings_preprocess.cpp
+++ b/src/theory/strings/theory_strings_preprocess.cpp
@@ -53,9 +53,9 @@ Node StringsPreprocess::reduce(Node t,
<< "StringsPreprocess::reduce: " << t << std::endl;
Node retNode = t;
NodeManager* nm = NodeManager::currentNM();
- Node zero = nm->mkConst(CONST_RATIONAL, Rational(0));
- Node one = nm->mkConst(CONST_RATIONAL, Rational(1));
- Node negOne = nm->mkConst(CONST_RATIONAL, Rational(-1));
+ Node zero = nm->mkConstInt(Rational(0));
+ Node one = nm->mkConstInt(Rational(1));
+ Node negOne = nm->mkConstInt(Rational(-1));
if( t.getKind() == kind::STRING_SUBSTR ) {
// processing term: substr( s, n, m )
@@ -184,7 +184,7 @@ Node StringsPreprocess::reduce(Node t,
Node skk = sc->mkTypedSkolemCached(
nm->integerType(), t, SkolemCache::SK_PURIFY, "iok");
- Node negone = nm->mkConst(CONST_RATIONAL, Rational(-1));
+ Node negone = nm->mkConstInt(Rational(-1));
// substr( x, n, len( x ) - n )
Node st = nm->mkNode(STRING_SUBSTR,
@@ -364,7 +364,7 @@ Node StringsPreprocess::reduce(Node t,
Node c0 = nm->mkNode(STRING_TO_CODE, nm->mkConst(String("0")));
Node c = nm->mkNode(MINUS, nm->mkNode(STRING_TO_CODE, sx), c0);
- Node ten = nm->mkConst(CONST_RATIONAL, Rational(10));
+ Node ten = nm->mkConstInt(Rational(10));
Node eq = ux1.eqNode(nm->mkNode(PLUS, c, nm->mkNode(MULT, ten, ux)));
Node leadingZeroPos =
nm->mkNode(AND, x.eqNode(zero), nm->mkNode(GT, leni, one));
@@ -431,7 +431,7 @@ Node StringsPreprocess::reduce(Node t,
MINUS,
nm->mkNode(STRING_TO_CODE, nm->mkNode(STRING_SUBSTR, s, k, one)),
c0);
- Node ten = nm->mkConst(CONST_RATIONAL, Rational(10));
+ Node ten = nm->mkConstInt(Rational(10));
Node kc3 = nm->mkNode(
OR, nm->mkNode(LT, codeSk, zero), nm->mkNode(GEQ, codeSk, ten));
conc1.push_back(nm->mkNode(OR, sEmpty, nm->mkNode(AND, kc1, kc2, kc3)));
@@ -865,12 +865,11 @@ Node StringsPreprocess::reduce(Node t,
Node ci = nm->mkNode(STRING_TO_CODE, nm->mkNode(STRING_SUBSTR, x, i, one));
Node ri = nm->mkNode(STRING_TO_CODE, nm->mkNode(STRING_SUBSTR, r, i, one));
- Node lb = nm->mkConst(CONST_RATIONAL,
- Rational(t.getKind() == STRING_TOUPPER ? 97 : 65));
- Node ub = nm->mkConst(CONST_RATIONAL,
- Rational(t.getKind() == STRING_TOUPPER ? 122 : 90));
- Node offset = nm->mkConst(
- CONST_RATIONAL, Rational(t.getKind() == STRING_TOUPPER ? -32 : 32));
+ Node lb = nm->mkConstInt(Rational(t.getKind() == STRING_TOUPPER ? 97 : 65));
+ Node ub =
+ nm->mkConstInt(Rational(t.getKind() == STRING_TOUPPER ? 122 : 90));
+ Node offset =
+ nm->mkConstInt(Rational(t.getKind() == STRING_TOUPPER ? -32 : 32));
Node res = nm->mkNode(
ITE,
diff --git a/src/theory/strings/theory_strings_utils.cpp b/src/theory/strings/theory_strings_utils.cpp
index a133babba..0ee2e906d 100644
--- a/src/theory/strings/theory_strings_utils.cpp
+++ b/src/theory/strings/theory_strings_utils.cpp
@@ -165,8 +165,7 @@ Node mkNLength(Node t)
Node mkPrefix(Node t, Node n)
{
NodeManager* nm = NodeManager::currentNM();
- return nm->mkNode(
- STRING_SUBSTR, t, nm->mkConst(CONST_RATIONAL, Rational(0)), n);
+ return nm->mkNode(STRING_SUBSTR, t, nm->mkConstInt(Rational(0)), n);
}
Node mkSuffix(Node t, Node n)
diff --git a/src/theory/substitutions.cpp b/src/theory/substitutions.cpp
index 70e3deb63..e49563046 100644
--- a/src/theory/substitutions.cpp
+++ b/src/theory/substitutions.cpp
@@ -39,7 +39,7 @@ struct substitution_stack_element {
}
};/* struct substitution_stack_element */
-Node SubstitutionMap::internalSubstitute(TNode t, NodeCache& cache) {
+Node SubstitutionMap::internalSubstitute(TNode t, NodeCache& cache, std::set<TNode>* tracker) {
Debug("substitution::internal") << "SubstitutionMap::internalSubstitute(" << t << ")" << endl;
@@ -70,10 +70,17 @@ Node SubstitutionMap::internalSubstitute(TNode t, NodeCache& cache) {
if (find2 != d_substitutions.end()) {
Node rhs = (*find2).second;
Assert(rhs != current);
- internalSubstitute(rhs, cache);
- d_substitutions[current] = cache[rhs];
+ internalSubstitute(rhs, cache, tracker);
+ if (tracker == nullptr)
+ {
+ d_substitutions[current] = cache[rhs];
+ }
cache[current] = cache[rhs];
toVisit.pop_back();
+ if (tracker != nullptr)
+ {
+ tracker->insert(current);
+ }
continue;
}
@@ -101,10 +108,14 @@ Node SubstitutionMap::internalSubstitute(TNode t, NodeCache& cache) {
if (find2 != d_substitutions.end()) {
Node rhs = (*find2).second;
Assert(rhs != result);
- internalSubstitute(rhs, cache);
+ internalSubstitute(rhs, cache, tracker);
d_substitutions[result] = cache[rhs];
cache[result] = cache[rhs];
result = cache[rhs];
+ if (tracker != nullptr)
+ {
+ tracker->insert(result);
+ }
}
}
}
@@ -184,7 +195,7 @@ void SubstitutionMap::addSubstitutions(SubstitutionMap& subMap, bool invalidateC
}
}
-Node SubstitutionMap::apply(TNode t, bool doRewrite) {
+Node SubstitutionMap::apply(TNode t, Rewriter* r, std::set<TNode>* tracker) {
Debug("substitution") << "SubstitutionMap::apply(" << t << ")" << endl;
@@ -196,12 +207,12 @@ Node SubstitutionMap::apply(TNode t, bool doRewrite) {
}
// Perform the substitution
- Node result = internalSubstitute(t, d_substitutionCache);
+ Node result = internalSubstitute(t, d_substitutionCache, tracker);
Debug("substitution") << "SubstitutionMap::apply(" << t << ") => " << result << endl;
- if (doRewrite)
+ if (r != nullptr)
{
- result = Rewriter::rewrite(result);
+ result = r->rewrite(result);
}
return result;
diff --git a/src/theory/substitutions.h b/src/theory/substitutions.h
index 1de636fb3..2154c7fd5 100644
--- a/src/theory/substitutions.h
+++ b/src/theory/substitutions.h
@@ -32,6 +32,8 @@
namespace cvc5 {
namespace theory {
+class Rewriter;
+
/**
* The type for the Substitutions mapping output by
* Theory::simplify(), TheoryEngine::simplify(), and
@@ -63,7 +65,7 @@ class SubstitutionMap
bool d_cacheInvalidated;
/** Internal method that performs substitution */
- Node internalSubstitute(TNode t, NodeCache& cache);
+ Node internalSubstitute(TNode t, NodeCache& cache, std::set<TNode>* tracker);
/** Helper class to invalidate cache on user pop */
class CacheInvalidator : public context::ContextNotifyObj
@@ -125,16 +127,17 @@ class SubstitutionMap
}
/**
- * Apply the substitutions to the node.
+ * Apply the substitutions to the node, optionally rewrite if a non-null
+ * Rewriter pointer is passed.
*/
- Node apply(TNode t, bool doRewrite = false);
+ Node apply(TNode t, Rewriter* r = nullptr, std::set<TNode>* tracker = nullptr);
/**
* Apply the substitutions to the node.
*/
- Node apply(TNode t, bool doRewrite = false) const
+ Node apply(TNode t, Rewriter* r = nullptr) const
{
- return const_cast<SubstitutionMap*>(this)->apply(t, doRewrite);
+ return const_cast<SubstitutionMap*>(this)->apply(t, r);
}
iterator begin() { return d_substitutions.begin(); }
@@ -152,6 +155,10 @@ class SubstitutionMap
*/
void print(std::ostream& out) const;
+ void invalidateCache() {
+ d_cacheInvalidated = true;
+ }
+
}; /* class SubstitutionMap */
inline std::ostream& operator << (std::ostream& out, const SubstitutionMap& subst) {
diff --git a/src/theory/theory_engine.cpp b/src/theory/theory_engine.cpp
index 1b2ad3358..ae71ac484 100644
--- a/src/theory/theory_engine.cpp
+++ b/src/theory/theory_engine.cpp
@@ -155,7 +155,7 @@ void TheoryEngine::finishInit()
// create the relevance filter if any option requires it
if (options().theory.relevanceFilter || options().smt.produceDifficulty)
{
- d_relManager.reset(new RelevanceManager(userContext(), Valuation(this)));
+ d_relManager.reset(new RelevanceManager(d_env, Valuation(this)));
}
// initialize the quantifiers engine
@@ -384,15 +384,15 @@ void TheoryEngine::check(Theory::Effort effort) {
Debug("theory") << "TheoryEngine::check(" << effort << "): d_factsAsserted = " << (d_factsAsserted ? "true" : "false") << endl;
- // Reset round for the relevance manager, which notice only sets a flag
- // to indicate that its information must be recomputed.
- if (d_relManager != nullptr)
- {
- d_relManager->beginRound();
- }
// If in full effort, we have a fake new assertion just to jumpstart the checking
if (Theory::fullEffort(effort)) {
d_factsAsserted = true;
+ // Reset round for the relevance manager, which notice only sets a flag
+ // to indicate that its information must be recomputed.
+ if (d_relManager != nullptr)
+ {
+ d_relManager->beginRound();
+ }
d_tc->resetRound();
}
@@ -488,6 +488,10 @@ void TheoryEngine::check(Theory::Effort effort) {
if (Theory::fullEffort(effort))
{
+ if (d_relManager != nullptr)
+ {
+ d_relManager->endRound();
+ }
if (!d_inConflict && !needCheck())
{
// Do post-processing of model from the theories (e.g. used for
@@ -775,7 +779,7 @@ void TheoryEngine::notifyPreprocessedAssertions(
}
if (d_relManager != nullptr)
{
- d_relManager->notifyPreprocessedAssertions(assertions);
+ d_relManager->notifyPreprocessedAssertions(assertions, true);
}
}
@@ -1075,14 +1079,14 @@ theory::EqualityStatus TheoryEngine::getEqualityStatus(TNode a, TNode b) {
return d_sharedSolver->getEqualityStatus(a, b);
}
-const std::unordered_set<TNode>& TheoryEngine::getRelevantAssertions(
- bool& success)
+std::unordered_set<TNode> TheoryEngine::getRelevantAssertions(bool& success)
{
// if we are not in SAT mode, or there is no relevance manager, we fail
if (!d_inSatMode || d_relManager == nullptr)
{
success = false;
- return d_emptyRelevantSet;
+ // return empty set
+ return std::unordered_set<TNode>();
}
return d_relManager->getRelevantAssertions(success);
}
@@ -1093,13 +1097,19 @@ void TheoryEngine::getDifficultyMap(std::map<Node, Node>& dmap)
d_relManager->getDifficultyMap(dmap);
}
+theory::IncompleteId TheoryEngine::getIncompleteId() const
+{
+ return d_incompleteId.get();
+}
+
Node TheoryEngine::getModelValue(TNode var) {
if (var.isConst())
{
// the model value of a constant must be itself
return var;
}
- Assert(d_sharedSolver->isShared(var));
+ Assert(d_sharedSolver->isShared(var))
+ << "node " << var << " is not shared" << std::endl;
return theoryOf(Theory::theoryOf(var.getType()))->getModelValue(var);
}
@@ -1317,8 +1327,8 @@ void TheoryEngine::lemma(TrustNode tlemma,
d_propEngine->getPreprocessedTerm(tlemma.getProven(), skAsserts, sks);
if (options().theory.relevanceFilter && isLemmaPropertyNeedsJustify(p))
{
- d_relManager->notifyPreprocessedAssertion(retLemma);
- d_relManager->notifyPreprocessedAssertions(skAsserts);
+ d_relManager->notifyPreprocessedAssertion(retLemma, false);
+ d_relManager->notifyPreprocessedAssertions(skAsserts, false);
}
d_relManager->notifyLemma(retLemma);
}
diff --git a/src/theory/theory_engine.h b/src/theory/theory_engine.h
index efde513a9..f1e178055 100644
--- a/src/theory/theory_engine.h
+++ b/src/theory/theory_engine.h
@@ -374,7 +374,7 @@ class TheoryEngine : protected EnvObj
* relevance manager failed to compute relevant assertions due to an internal
* error.
*/
- const std::unordered_set<TNode>& getRelevantAssertions(bool& success);
+ std::unordered_set<TNode> getRelevantAssertions(bool& success);
/**
* Get difficulty map, which populates dmap, mapping preprocessed assertions
@@ -384,6 +384,9 @@ class TheoryEngine : protected EnvObj
*/
void getDifficultyMap(std::map<Node, Node>& dmap);
+ /** Get incomplete id, valid immediately after an `unknown` response. */
+ theory::IncompleteId getIncompleteId() const;
+
/**
* Forwards an entailment check according to the given theoryOfMode.
* See theory.h for documentation on entailmentCheck().
@@ -544,11 +547,6 @@ class TheoryEngine : protected EnvObj
std::unique_ptr<theory::DecisionManager> d_decManager;
/** The relevance manager */
std::unique_ptr<theory::RelevanceManager> d_relManager;
- /**
- * An empty set of relevant assertions, which is returned as a dummy value for
- * getRelevantAssertions when relevance is disabled.
- */
- std::unordered_set<TNode> d_emptyRelevantSet;
/** are we in eager model building mode? (see setEagerModelBuilding). */
bool d_eager_model_building;
diff --git a/src/theory/theory_inference_manager.cpp b/src/theory/theory_inference_manager.cpp
index 4ed01b618..fda6d0881 100644
--- a/src/theory/theory_inference_manager.cpp
+++ b/src/theory/theory_inference_manager.cpp
@@ -15,7 +15,13 @@
#include "theory/theory_inference_manager.h"
+#include "options/proof_options.h"
+#include "proof/annotation_proof_generator.h"
+#include "proof/eager_proof_generator.h"
#include "smt/smt_statistics_registry.h"
+#include "smt/solver_engine_scope.h"
+#include "theory/builtin/proof_checker.h"
+#include "theory/inference_id_proof_annotator.h"
#include "theory/output_channel.h"
#include "theory/rewriter.h"
#include "theory/theory.h"
@@ -56,6 +62,20 @@ TheoryInferenceManager::TheoryInferenceManager(Env& env,
// don't add true lemma
Node truen = NodeManager::currentNM()->mkConst(true);
d_lemmasSent.insert(truen);
+
+ if (isProofEnabled())
+ {
+ context::UserContext* u = userContext();
+ ProofNodeManager* pnm = env.getProofNodeManager();
+ d_defaultPg.reset(
+ new EagerProofGenerator(pnm, u, statsName + "EagerProofGenerator"));
+ if (options().proof.proofAnnotate)
+ {
+ d_iipa.reset(new InferenceIdProofAnnotator(pnm, u));
+ d_apg.reset(new AnnotationProofGenerator(
+ pnm, u, statsName + "AnnotationProofGenerator"));
+ }
+ }
}
TheoryInferenceManager::~TheoryInferenceManager()
@@ -127,6 +147,11 @@ void TheoryInferenceManager::trustedConflict(TrustNode tconf, InferenceId id)
resourceManager()->spendResource(id);
Trace("im") << "(conflict " << id << " " << tconf.getProven() << ")"
<< std::endl;
+ // annotate if the annotation proof generator is active
+ if (d_apg != nullptr)
+ {
+ tconf = annotateId(tconf, id);
+ }
d_out.trustedConflict(tconf);
++d_numConflicts;
}
@@ -261,7 +286,16 @@ bool TheoryInferenceManager::trustedLemma(const TrustNode& tlem,
// shouldn't send trivially true or false lemmas
Assert(!rewrite(tlem.getProven()).isConst());
d_numCurrentLemmas++;
- d_out.trustedLemma(tlem, p);
+ // annotate if the annotation proof generator is active
+ if (d_apg != nullptr)
+ {
+ TrustNode tlema = annotateId(tlem, id);
+ d_out.trustedLemma(tlema, p);
+ }
+ else
+ {
+ d_out.trustedLemma(tlem, p);
+ }
return true;
}
@@ -544,6 +578,24 @@ bool TheoryInferenceManager::cacheLemma(TNode lem, LemmaProperty p)
return true;
}
+TrustNode TheoryInferenceManager::annotateId(const TrustNode& trn,
+ InferenceId id)
+{
+ Assert(d_iipa != nullptr && d_apg != nullptr);
+ Node lemma = trn.getProven();
+ TrustNode trna = trn;
+ // ensure we have a proof generator, make trusted theory lemma if not
+ if (trn.getGenerator() == nullptr)
+ {
+ Node tidn =
+ builtin::BuiltinProofRuleChecker::mkTheoryIdNode(d_theory.getId());
+ trna = d_defaultPg->mkTrustNode(
+ lemma, PfRule::THEORY_LEMMA, {}, {lemma, tidn});
+ }
+ d_iipa->setAnnotation(lemma, id);
+ return d_apg->transform(trna, d_iipa.get());
+}
+
DecisionManager* TheoryInferenceManager::getDecisionManager()
{
return d_decManager;
diff --git a/src/theory/theory_inference_manager.h b/src/theory/theory_inference_manager.h
index d7334d0e6..c626bbef9 100644
--- a/src/theory/theory_inference_manager.h
+++ b/src/theory/theory_inference_manager.h
@@ -32,12 +32,15 @@
namespace cvc5 {
class ProofNodeManager;
+class AnnotationProofGenerator;
+class EagerProofGenerator;
namespace theory {
class Theory;
class TheoryState;
class DecisionManager;
+class InferenceIdProofAnnotator;
namespace eq {
class EqualityEngine;
class ProofEqEngine;
@@ -426,6 +429,11 @@ class TheoryInferenceManager : protected EnvObj
* override this method to take the lemma property into account as needed.
*/
virtual bool cacheLemma(TNode lem, LemmaProperty p);
+ /**
+ * Return the trust node that is equivalent to trn, but its proof (if asked
+ * for) will be wrapped in (ANNOTATE ... :args id).
+ */
+ TrustNode annotateId(const TrustNode& trn, InferenceId id);
/** The theory object */
Theory& d_theory;
/** Reference to the state of theory */
@@ -440,6 +448,12 @@ class TheoryInferenceManager : protected EnvObj
eq::ProofEqEngine* d_pfee;
/** The proof equality engine we allocated */
std::unique_ptr<eq::ProofEqEngine> d_pfeeAlloc;
+ /** Proof generator for trusted THEORY_LEMMA steps */
+ std::unique_ptr<EagerProofGenerator> d_defaultPg;
+ /** The inference id proof annotator */
+ std::unique_ptr<InferenceIdProofAnnotator> d_iipa;
+ /** The annotation proof generator */
+ std::unique_ptr<AnnotationProofGenerator> d_apg;
/** Whether this manager caches lemmas */
bool d_cacheLemmas;
/**
diff --git a/src/theory/theory_model.cpp b/src/theory/theory_model.cpp
index 079683116..33ec5b23b 100644
--- a/src/theory/theory_model.cpp
+++ b/src/theory/theory_model.cpp
@@ -135,6 +135,7 @@ Node TheoryModel::getValue(TNode n) const
{
//apply substitutions
Node nn = d_env.getTopLevelSubstitutions().apply(n);
+ nn = rewrite(nn);
Debug("model-getvalue-debug") << "[model-getvalue] getValue : substitute " << n << " to " << nn << std::endl;
//get value in model
nn = getModelValue(nn);
diff --git a/src/theory/theory_model_builder.cpp b/src/theory/theory_model_builder.cpp
index bc63aef97..a83527004 100644
--- a/src/theory/theory_model_builder.cpp
+++ b/src/theory/theory_model_builder.cpp
@@ -1034,7 +1034,7 @@ bool TheoryEngineModelBuilder::buildModel(TheoryModel* tm)
if (!repSet.empty())
{
Trace("model-builder") << "***Non-empty repSet, size = " << repSet.size()
- << ", first = " << *(repSet.begin()) << endl;
+ << ", repSet = " << repSet << endl;
Assert(false);
}
}
@@ -1278,7 +1278,8 @@ void TheoryEngineModelBuilder::assignFunction(TheoryModel* m, Node f)
}
std::stringstream ss;
ss << "_arg_";
- Node val = ufmt.getFunctionValue(ss.str().c_str(), condenseFuncValues);
+ Rewriter* r = condenseFuncValues ? d_env.getRewriter() : nullptr;
+ Node val = ufmt.getFunctionValue(ss.str(), r);
m->assignFunctionDefinition(f, val);
// ufmt.debugPrint( std::cout, m );
}
diff --git a/src/theory/trust_substitutions.cpp b/src/theory/trust_substitutions.cpp
index c73265095..ea87829a9 100644
--- a/src/theory/trust_substitutions.cpp
+++ b/src/theory/trust_substitutions.cpp
@@ -145,11 +145,11 @@ void TrustSubstitutionMap::addSubstitutions(TrustSubstitutionMap& t)
}
}
-TrustNode TrustSubstitutionMap::applyTrusted(Node n, bool doRewrite)
+TrustNode TrustSubstitutionMap::applyTrusted(Node n, Rewriter* r)
{
Trace("trust-subs") << "TrustSubstitutionMap::addSubstitution: apply " << n
<< std::endl;
- Node ns = d_subs.apply(n, doRewrite);
+ Node ns = d_subs.apply(n, r);
Trace("trust-subs") << "...subs " << ns << std::endl;
if (n == ns)
{
@@ -172,9 +172,9 @@ TrustNode TrustSubstitutionMap::applyTrusted(Node n, bool doRewrite)
return TrustNode::mkTrustRewrite(n, ns, this);
}
-Node TrustSubstitutionMap::apply(Node n, bool doRewrite)
+Node TrustSubstitutionMap::apply(Node n, Rewriter* r)
{
- return d_subs.apply(n, doRewrite);
+ return d_subs.apply(n, r);
}
std::shared_ptr<ProofNode> TrustSubstitutionMap::getProofFor(Node eq)
diff --git a/src/theory/trust_substitutions.h b/src/theory/trust_substitutions.h
index cc08c870d..abcf039ba 100644
--- a/src/theory/trust_substitutions.h
+++ b/src/theory/trust_substitutions.h
@@ -87,11 +87,12 @@ class TrustSubstitutionMap : public ProofGenerator
/**
* Apply substitutions in this class to node n. Returns a trust node
* proving n = n*sigma, where the proof generator is provided by this class
- * (when proofs are enabled).
+ * (when proofs are enabled). If a non-null rewriter is provided, the result
+ * of the substitution is rewritten.
*/
- TrustNode applyTrusted(Node n, bool doRewrite = true);
+ TrustNode applyTrusted(Node n, Rewriter* r = nullptr);
/** Same as above, without proofs */
- Node apply(Node n, bool doRewrite = true);
+ Node apply(Node n, Rewriter* r = nullptr);
/** Get the proof for formula f */
std::shared_ptr<ProofNode> getProofFor(Node f) override;
diff --git a/src/theory/uf/cardinality_extension.cpp b/src/theory/uf/cardinality_extension.cpp
index f5f6ff565..2ebdf5a24 100644
--- a/src/theory/uf/cardinality_extension.cpp
+++ b/src/theory/uf/cardinality_extension.cpp
@@ -465,11 +465,13 @@ std::string SortModel::CardinalityDecisionStrategy::identify() const
return std::string("uf_card");
}
-SortModel::SortModel(TypeNode tn,
+SortModel::SortModel(Env& env,
+ TypeNode tn,
TheoryState& state,
TheoryInferenceManager& im,
CardinalityExtension* thss)
- : d_type(tn),
+ : EnvObj(env),
+ d_type(tn),
d_state(state),
d_im(im),
d_thss(thss),
@@ -484,8 +486,7 @@ SortModel::SortModel(TypeNode tn,
d_initialized(thss->userContext(), false),
d_c_dec_strat(nullptr)
{
-
- if (options::ufssMode() == options::UfssMode::FULL)
+ if (options().uf.ufssMode == options::UfssMode::FULL)
{
// Register the strategy with the decision manager of the theory.
// We are guaranteed that the decision manager is ready since we
@@ -672,7 +673,7 @@ bool SortModel::areDisequal( Node a, Node b ) {
void SortModel::check(Theory::Effort level)
{
- Assert(options::ufssMode() == options::UfssMode::FULL);
+ Assert(options().uf.ufssMode == options::UfssMode::FULL);
if (!d_hasCard && d_state.isInConflict())
{
// not necessary to check
@@ -885,11 +886,11 @@ void SortModel::assertCardinality(uint32_t c, bool val)
}
}
// we assert it positively, if its beyond the bound, abort
- if (options::ufssAbortCardinality() >= 0
- && c >= static_cast<uint32_t>(options::ufssAbortCardinality()))
+ if (options().uf.ufssAbortCardinality >= 0
+ && c >= static_cast<uint32_t>(options().uf.ufssAbortCardinality))
{
std::stringstream ss;
- ss << "Maximum cardinality (" << options::ufssAbortCardinality()
+ ss << "Maximum cardinality (" << options().uf.ufssAbortCardinality
<< ") for finite model finding exceeded." << std::endl;
throw LogicException(ss.str());
}
@@ -1011,7 +1012,7 @@ int SortModel::addSplit(Region* r)
if (!s.isNull() ){
//add lemma to output channel
Assert(s.getKind() == EQUAL);
- Node ss = Rewriter::rewrite( s );
+ Node ss = rewrite(s);
if( ss.getKind()!=EQUAL ){
Node b_t = NodeManager::currentNM()->mkConst( true );
Node b_f = NodeManager::currentNM()->mkConst( false );
@@ -1620,7 +1621,7 @@ void CardinalityExtension::preRegisterTerm(TNode n)
if (tn.isSort())
{
Trace("uf-ss-register") << "Create sort model " << tn << "." << std::endl;
- rm = new SortModel(tn, d_state, d_im, this);
+ rm = new SortModel(d_env, tn, d_state, d_im, this);
}
if (rm)
{
diff --git a/src/theory/uf/cardinality_extension.h b/src/theory/uf/cardinality_extension.h
index 7a6d44ee9..822f13f23 100644
--- a/src/theory/uf/cardinality_extension.h
+++ b/src/theory/uf/cardinality_extension.h
@@ -48,7 +48,7 @@ class CardinalityExtension : protected EnvObj
* Information for incremental conflict/clique finding for a
* particular sort.
*/
- class SortModel
+ class SortModel : protected EnvObj
{
private:
std::map< Node, std::vector< int > > d_totality_lems;
@@ -281,7 +281,8 @@ class CardinalityExtension : protected EnvObj
void simpleCheckCardinality();
public:
- SortModel(TypeNode tn,
+ SortModel(Env& env,
+ TypeNode tn,
TheoryState& state,
TheoryInferenceManager& im,
CardinalityExtension* thss);
diff --git a/src/theory/uf/proof_equality_engine.cpp b/src/theory/uf/proof_equality_engine.cpp
index 71688fc15..856dce011 100644
--- a/src/theory/uf/proof_equality_engine.cpp
+++ b/src/theory/uf/proof_equality_engine.cpp
@@ -31,7 +31,8 @@ namespace theory {
namespace eq {
ProofEqEngine::ProofEqEngine(Env& env, EqualityEngine& ee)
- : EagerProofGenerator(env.getProofNodeManager(),
+ : EnvObj(env),
+ EagerProofGenerator(env.getProofNodeManager(),
env.getUserContext(),
"pfee::" + ee.identify()),
d_ee(ee),
@@ -180,7 +181,7 @@ TrustNode ProofEqEngine::assertConflict(Node lit)
// lit may not be equivalent to false, but should rewrite to false
if (lit != d_false)
{
- Assert(Rewriter::rewrite(lit) == d_false)
+ Assert(rewrite(lit) == d_false)
<< "pfee::assertConflict: conflict literal is not rewritable to "
"false";
std::vector<Node> exp;
diff --git a/src/theory/uf/proof_equality_engine.h b/src/theory/uf/proof_equality_engine.h
index fc8520dd1..47bb2fe0d 100644
--- a/src/theory/uf/proof_equality_engine.h
+++ b/src/theory/uf/proof_equality_engine.h
@@ -27,6 +27,7 @@
#include "proof/buffered_proof_generator.h"
#include "proof/eager_proof_generator.h"
#include "proof/lazy_proof.h"
+#include "smt/env_obj.h"
namespace cvc5 {
@@ -80,7 +81,7 @@ class EqualityEngine;
* - explain, for explaining why a literal is true in the current state.
* Details on these methods can be found below.
*/
-class ProofEqEngine : public EagerProofGenerator
+class ProofEqEngine : protected EnvObj, public EagerProofGenerator
{
typedef context::CDHashSet<Node> NodeSet;
typedef context::CDHashMap<Node, std::shared_ptr<ProofNode>> NodeProofMap;
diff --git a/src/theory/uf/theory_uf_model.cpp b/src/theory/uf/theory_uf_model.cpp
index 861f12d64..6d8d421ba 100644
--- a/src/theory/uf/theory_uf_model.cpp
+++ b/src/theory/uf/theory_uf_model.cpp
@@ -57,7 +57,11 @@ void UfModelTreeNode::setValue( TheoryModel* m, Node n, Node v, std::vector< int
}
}
-Node UfModelTreeNode::getFunctionValue(std::vector<Node>& args, int index, Node argDefaultValue, bool simplify) {
+Node UfModelTreeNode::getFunctionValue(const std::vector<Node>& args,
+ int index,
+ Node argDefaultValue,
+ bool simplify)
+{
if(!d_data.empty()) {
Node defaultValue = argDefaultValue;
if(d_data.find(Node::null()) != d_data.end()) {
@@ -222,16 +226,19 @@ void UfModelTreeNode::debugPrint( std::ostream& out, TheoryModel* m, std::vector
}
}
-Node UfModelTree::getFunctionValue( std::vector< Node >& args, bool simplify ){
- Node body = d_tree.getFunctionValue( args, 0, Node::null(), simplify );
- if(simplify) {
- body = Rewriter::rewrite( body );
+Node UfModelTree::getFunctionValue(const std::vector<Node>& args, Rewriter* r)
+{
+ Node body = d_tree.getFunctionValue(args, 0, Node::null(), r != nullptr);
+ if (r != nullptr)
+ {
+ body = r->rewrite(body);
}
Node boundVarList = NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST, args);
return NodeManager::currentNM()->mkNode(kind::LAMBDA, boundVarList, body);
}
-Node UfModelTree::getFunctionValue( const char* argPrefix, bool simplify ){
+Node UfModelTree::getFunctionValue(const std::string& argPrefix, Rewriter* r)
+{
TypeNode type = d_op.getType();
std::vector< Node > vars;
for( size_t i=0; i<type.getNumChildren()-1; i++ ){
@@ -239,7 +246,7 @@ Node UfModelTree::getFunctionValue( const char* argPrefix, bool simplify ){
ss << argPrefix << (i+1);
vars.push_back( NodeManager::currentNM()->mkBoundVar( ss.str(), type[i] ) );
}
- return getFunctionValue( vars, simplify );
+ return getFunctionValue(vars, r);
}
} // namespace uf
diff --git a/src/theory/uf/theory_uf_model.h b/src/theory/uf/theory_uf_model.h
index f386c2f99..e4235623e 100644
--- a/src/theory/uf/theory_uf_model.h
+++ b/src/theory/uf/theory_uf_model.h
@@ -26,6 +26,7 @@ namespace cvc5 {
namespace theory {
class TheoryModel;
+class Rewriter;
namespace uf {
@@ -45,7 +46,10 @@ public:
/** setValue function */
void setValue( TheoryModel* m, Node n, Node v, std::vector< int >& indexOrder, bool ground, int argIndex );
/** getFunctionValue */
- Node getFunctionValue( std::vector< Node >& args, int index, Node argDefaultValue, bool simplify = true );
+ Node getFunctionValue(const std::vector<Node>& args,
+ int index,
+ Node argDefaultValue,
+ bool simplify = true);
/** update function */
void update( TheoryModel* m );
/** simplify function */
@@ -92,11 +96,12 @@ public:
d_tree.setValue( m, Node::null(), v, d_index_order, false, 0 );
}
/** getFunctionValue
- * Returns a representation of this function.
- */
- Node getFunctionValue( std::vector< Node >& args, bool simplify = true );
+ * Returns a representation of this function. The body of the function is
+ * rewritten if r is non-null.
+ */
+ Node getFunctionValue(const std::vector<Node>& args, Rewriter* r);
/** getFunctionValue for args with set prefix */
- Node getFunctionValue( const char* argPrefix, bool simplify = true );
+ Node getFunctionValue(const std::string& argPrefix, Rewriter* r);
/** update
* This will update all values in the tree to be representatives in m.
*/
diff --git a/src/util/didyoumean.cpp b/src/util/didyoumean.cpp
index 0f95722fd..f4dbbbd36 100644
--- a/src/util/didyoumean.cpp
+++ b/src/util/didyoumean.cpp
@@ -37,7 +37,7 @@ uint64_t editDistance(const std::string& a, const std::string& b) {
constexpr uint64_t swapCost = 0;
constexpr uint64_t substituteCost = 2;
constexpr uint64_t addCost = 1;
- constexpr uint64_t deleteCost = 3;
+ constexpr uint64_t deleteCost = 2;
constexpr uint64_t switchCaseCost = 0;
uint64_t len1 = a.size();
@@ -104,7 +104,7 @@ std::vector<std::string> DidYouMean::getMatch(const std::string& input)
}
/** Magic numbers */
- constexpr uint64_t similarityThreshold = 7;
+ constexpr uint64_t similarityThreshold = 10;
constexpr uint64_t numMatchesThreshold = 10;
std::vector<std::pair<uint64_t,std::string>> scores;
@@ -127,7 +127,7 @@ std::vector<std::string> DidYouMean::getMatch(const std::string& input)
// from here on, matches are not similar enough
if (score.first > similarityThreshold) break;
// from here on, matches are way worse than the best one
- if (score.first > min_score + 2) break;
+ if (score.first > min_score + 4) break;
// we already have enough matches
if (ret.size() >= numMatchesThreshold) break;
ret.push_back(score.second);
diff --git a/src/util/hash.h b/src/util/hash.h
index db280984b..ef8bf4a2a 100644
--- a/src/util/hash.h
+++ b/src/util/hash.h
@@ -43,12 +43,15 @@ namespace cvc5 {
namespace fnv1a {
+constexpr uint64_t offsetBasis = 14695981039346656037U;
+
/**
* FNV-1a hash algorithm for 64-bit numbers.
*
* More details here: http://www.isthe.com/chongo/tech/comp/fnv/index.html
*/
-inline uint64_t fnv1a_64(uint64_t v, uint64_t hash = 14695981039346656037U) {
+inline uint64_t fnv1a_64(uint64_t v, uint64_t hash = offsetBasis)
+{
hash ^= v;
// Compute (hash * 1099511628211)
return hash + (hash << 1) + (hash << 4) + (hash << 5) + (hash << 7) +
diff --git a/src/util/integer_cln_imp.cpp b/src/util/integer_cln_imp.cpp
index e09708ae5..149e02edc 100644
--- a/src/util/integer_cln_imp.cpp
+++ b/src/util/integer_cln_imp.cpp
@@ -483,16 +483,6 @@ unsigned int Integer::getUnsignedInt() const
return cln::cl_I_to_uint(d_value);
}
-bool Integer::fitsSignedLong() const
-{
- return d_value <= s_signedLongMax && d_value >= s_signedLongMin;
-}
-
-bool Integer::fitsUnsignedLong() const
-{
- return sgn() >= 0 && d_value <= s_unsignedLongMax;
-}
-
long Integer::getLong() const
{
// ensure there isn't overflow
@@ -517,6 +507,53 @@ unsigned long Integer::getUnsignedLong() const
return cln::cl_I_to_ulong(d_value);
}
+int64_t Integer::getSigned64() const
+{
+ if constexpr (sizeof(int64_t) == sizeof(signed long int))
+ {
+ return getLong();
+ }
+ else
+ {
+ if (std::numeric_limits<long>::min() <= d_value
+ && d_value <= std::numeric_limits<long>::max())
+ {
+ return getLong();
+ }
+ // ensure there isn't overflow
+ CheckArgument(d_value <= std::numeric_limits<int64_t>::max(),
+ this,
+ "Overflow detected in Integer::getSigned64()");
+ CheckArgument(d_value >= std::numeric_limits<int64_t>::min(),
+ this,
+ "Overflow detected in Integer::getSigned64()");
+ return std::stoll(toString());
+ }
+}
+uint64_t Integer::getUnsigned64() const
+{
+ if constexpr (sizeof(uint64_t) == sizeof(unsigned long int))
+ {
+ return getUnsignedLong();
+ }
+ else
+ {
+ if (std::numeric_limits<unsigned long>::min() <= d_value
+ && d_value <= std::numeric_limits<unsigned long>::max())
+ {
+ return getUnsignedLong();
+ }
+ // ensure there isn't overflow
+ CheckArgument(d_value <= std::numeric_limits<uint64_t>::max(),
+ this,
+ "Overflow detected in Integer::getSigned64()");
+ CheckArgument(d_value >= std::numeric_limits<uint64_t>::min(),
+ this,
+ "Overflow detected in Integer::getSigned64()");
+ return std::stoull(toString());
+ }
+}
+
size_t Integer::hash() const { return equal_hashcode(d_value); }
bool Integer::testBit(unsigned n) const { return cln::logbitp(n, d_value); }
diff --git a/src/util/integer_cln_imp.h b/src/util/integer_cln_imp.h
index 2120a4d5d..333d8f502 100644
--- a/src/util/integer_cln_imp.h
+++ b/src/util/integer_cln_imp.h
@@ -274,18 +274,18 @@ class CVC5_EXPORT Integer
/** Return the unsigned int representation of this Integer. */
unsigned int getUnsignedInt() const;
- /** Return true if this Integer fits into a signed long. */
- bool fitsSignedLong() const;
-
- /** Return true if this Integer fits into an unsigned long. */
- bool fitsUnsignedLong() const;
-
/** Return the signed long representation of this Integer. */
long getLong() const;
/** Return the unsigned long representation of this Integer. */
unsigned long getUnsignedLong() const;
+ /** Return the int64_t representation of this Integer. */
+ int64_t getSigned64() const;
+
+ /** Return the uint64_t representation of this Integer. */
+ uint64_t getUnsigned64() const;
+
/**
* Computes the hash of the node from the first word of the
* numerator, the denominator.
diff --git a/src/util/integer_gmp_imp.cpp b/src/util/integer_gmp_imp.cpp
index f33a90408..8d9f7d050 100644
--- a/src/util/integer_gmp_imp.cpp
+++ b/src/util/integer_gmp_imp.cpp
@@ -14,6 +14,7 @@
*/
#include <cmath>
+#include <limits>
#include <sstream>
#include <string>
@@ -38,6 +39,33 @@ Integer::Integer(const std::string& s, unsigned base)
: d_value(s, base)
{}
+#ifdef CVC5_NEED_INT64_T_OVERLOADS
+Integer::Integer(int64_t z)
+{
+ if (std::numeric_limits<signed long int>::min() <= z
+ && z <= std::numeric_limits<signed long int>::max())
+ {
+ d_value = static_cast<signed long int>(z);
+ }
+ else
+ {
+ d_value = std::to_string(z);
+ }
+}
+Integer::Integer(uint64_t z)
+{
+ if (std::numeric_limits<unsigned long int>::min() <= z
+ && z <= std::numeric_limits<unsigned long int>::max())
+ {
+ d_value = static_cast<unsigned long int>(z);
+ }
+ else
+ {
+ d_value = std::to_string(z);
+ }
+}
+#endif /* CVC5_NEED_INT64_T_OVERLOADS */
+
Integer& Integer::operator=(const Integer& x)
{
if (this == &x) return *this;
@@ -402,28 +430,73 @@ unsigned int Integer::getUnsignedInt() const
return (unsigned int)d_value.get_ui();
}
-bool Integer::fitsSignedLong() const { return d_value.fits_slong_p(); }
-
-bool Integer::fitsUnsignedLong() const { return d_value.fits_ulong_p(); }
-
long Integer::getLong() const
{
- long si = d_value.get_si();
- // ensure there wasn't overflow
- CheckArgument(mpz_cmp_si(d_value.get_mpz_t(), si) == 0,
+ // ensure there it fits
+ CheckArgument(mpz_fits_slong_p(d_value.get_mpz_t()) != 0,
this,
"Overflow detected in Integer::getLong().");
- return si;
+ return d_value.get_si();
}
unsigned long Integer::getUnsignedLong() const
{
- unsigned long ui = d_value.get_ui();
- // ensure there wasn't overflow
- CheckArgument(mpz_cmp_ui(d_value.get_mpz_t(), ui) == 0,
+ // ensure that it fits
+ CheckArgument(mpz_fits_ulong_p(d_value.get_mpz_t()) != 0,
this,
"Overflow detected in Integer::getUnsignedLong().");
- return ui;
+ return d_value.get_ui();
+}
+
+int64_t Integer::getSigned64() const
+{
+ if constexpr (sizeof(int64_t) == sizeof(signed long int))
+ {
+ return getLong();
+ }
+ else
+ {
+ if (mpz_fits_slong_p(d_value.get_mpz_t()) != 0)
+ {
+ return getLong();
+ }
+ try
+ {
+ return std::stoll(toString());
+ }
+ catch (const std::exception& e)
+ {
+ CheckArgument(
+ false, this, "Overflow detected in Integer::getSigned64().");
+ }
+ }
+ return 0;
+}
+uint64_t Integer::getUnsigned64() const
+{
+ if constexpr (sizeof(uint64_t) == sizeof(unsigned long int))
+ {
+ return getUnsignedLong();
+ }
+ else
+ {
+ if (mpz_fits_ulong_p(d_value.get_mpz_t()) != 0)
+ {
+ return getUnsignedLong();
+ }
+ try
+ {
+ CheckArgument(
+ sgn() >= 0, this, "Overflow detected in Integer::getUnsigned64().");
+ return std::stoull(toString());
+ }
+ catch (const std::exception& e)
+ {
+ CheckArgument(
+ false, this, "Overflow detected in Integer::getUnsigned64().");
+ }
+ }
+ return 0;
}
size_t Integer::hash() const { return gmpz_hash(d_value.get_mpz_t()); }
diff --git a/src/util/integer_gmp_imp.h b/src/util/integer_gmp_imp.h
index ff2ea9815..397455f87 100644
--- a/src/util/integer_gmp_imp.h
+++ b/src/util/integer_gmp_imp.h
@@ -59,8 +59,8 @@ class CVC5_EXPORT Integer
Integer(unsigned long int z) : d_value(z) {}
#ifdef CVC5_NEED_INT64_T_OVERLOADS
- Integer(int64_t z) : d_value(static_cast<long>(z)) {}
- Integer(uint64_t z) : d_value(static_cast<unsigned long>(z)) {}
+ Integer(int64_t z);
+ Integer(uint64_t z);
#endif /* CVC5_NEED_INT64_T_OVERLOADS */
/** Destructor. */
@@ -257,18 +257,18 @@ class CVC5_EXPORT Integer
/** Return the unsigned int representation of this Integer. */
unsigned int getUnsignedInt() const;
- /** Return true if this Integer fits into a signed long. */
- bool fitsSignedLong() const;
-
- /** Return true if this Integer fits into an unsigned long. */
- bool fitsUnsignedLong() const;
-
/** Return the signed long representation of this Integer. */
long getLong() const;
/** Return the unsigned long representation of this Integer. */
unsigned long getUnsignedLong() const;
+ /** Return the int64_t representation of this Integer. */
+ int64_t getSigned64() const;
+
+ /** Return the uint64_t representation of this Integer. */
+ uint64_t getUnsigned64() const;
+
/**
* Computes the hash of the node from the first word of the
* numerator, the denominator.
diff --git a/src/util/string.cpp b/src/util/string.cpp
index 50b0a7199..2235ac5ee 100644
--- a/src/util/string.cpp
+++ b/src/util/string.cpp
@@ -23,6 +23,7 @@
#include "base/check.h"
#include "base/exception.h"
+#include "util/hash.h"
using namespace std;
@@ -519,6 +520,20 @@ Rational String::toNumber() const
return Rational(toString());
}
+namespace strings {
+
+size_t StringHashFunction::operator()(const ::cvc5::String& s) const
+{
+ uint64_t ret = fnv1a::offsetBasis;
+ for (unsigned c : s.d_str)
+ {
+ ret = fnv1a::fnv1a_64(c, ret);
+ }
+ return static_cast<size_t>(ret);
+}
+
+} // namespace strings
+
std::ostream &operator<<(std::ostream &os, const String &s) {
return os << "\"" << s.toString() << "\"";
}
diff --git a/src/util/string.h b/src/util/string.h
index 3f6384082..017c60fb8 100644
--- a/src/util/string.h
+++ b/src/util/string.h
@@ -26,6 +26,10 @@
namespace cvc5 {
+namespace strings {
+struct StringHashFunction;
+}
+
/** The cvc5 string class
*
* This data structure is the domain of values for the string type. It can also
@@ -33,6 +37,8 @@ namespace cvc5 {
*/
class String
{
+ friend strings::StringHashFunction;
+
public:
/**
* This is the cardinality of the alphabet that is representable by this
@@ -267,10 +273,7 @@ namespace strings {
struct StringHashFunction
{
- size_t operator()(const ::cvc5::String& s) const
- {
- return std::hash<std::string>()(s.toString());
- }
+ size_t operator()(const ::cvc5::String& s) const;
}; /* struct StringHashFunction */
} // namespace strings
diff --git a/test/api/cpp/CMakeLists.txt b/test/api/cpp/CMakeLists.txt
index eae57f3b9..929c5bef2 100644
--- a/test/api/cpp/CMakeLists.txt
+++ b/test/api/cpp/CMakeLists.txt
@@ -54,3 +54,5 @@ cvc5_add_api_test(issue4889)
cvc5_add_api_test(issue6111)
cvc5_add_api_test(proj-issue306)
cvc5_add_api_test(proj-issue334)
+cvc5_add_api_test(proj-issue344)
+cvc5_add_api_test(proj-issue345)
diff --git a/test/api/cpp/proj-issue344.cpp b/test/api/cpp/proj-issue344.cpp
new file mode 100644
index 000000000..5f486706c
--- /dev/null
+++ b/test/api/cpp/proj-issue344.cpp
@@ -0,0 +1,33 @@
+/******************************************************************************
+ * Top contributors (to current version):
+ * Yoni Zohar
+ *
+ * This file is part of the cvc5 project.
+ *
+ * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+ * in the top-level source directory and their institutional affiliations.
+ * All rights reserved. See the file COPYING in the top-level source
+ * directory for licensing information.
+ * ****************************************************************************
+ *
+ * Test for project issue #345
+ *
+ */
+
+
+#include "api/cpp/cvc5.h"
+#include <cassert>
+
+using namespace cvc5::api;
+
+int main(void)
+{
+ Solver slv;
+ slv.setOption("solve-bv-as-int", "iand");
+ Sort s12 = slv.getIntegerSort();
+ Term t13 = slv.mkConst(s12, "_x11");
+ Term t25 = slv.mkTerm(slv.mkOp(Kind::INT_TO_BITVECTOR, 4124876294), {t13});
+ Term t66 = slv.mkTerm(Kind::BITVECTOR_ULTBV, {t25, t25});
+ Term t154 = slv.mkTerm(Kind::BITVECTOR_SGT, {t66, t66});
+ slv.checkEntailed({t154, t154, t154, t154});
+}
diff --git a/test/api/cpp/proj-issue345.cpp b/test/api/cpp/proj-issue345.cpp
new file mode 100644
index 000000000..c33e9e5b8
--- /dev/null
+++ b/test/api/cpp/proj-issue345.cpp
@@ -0,0 +1,34 @@
+/******************************************************************************
+ * Top contributors (to current version):
+ * Yoni Zohar
+ *
+ * This file is part of the cvc5 project.
+ *
+ * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+ * in the top-level source directory and their institutional affiliations.
+ * All rights reserved. See the file COPYING in the top-level source
+ * directory for licensing information.
+ * ****************************************************************************
+ *
+ * Test for project issue #345
+ *
+ */
+
+
+#include "api/cpp/cvc5.h"
+#include <cassert>
+
+using namespace cvc5::api;
+
+int main(void)
+{
+ Solver slv;
+ slv.setOption("solve-bv-as-int", "iand");
+ Sort s12 = slv.getIntegerSort();
+ Term t13 = slv.mkConst(s12, "_x11");
+ Term t25 = slv.mkTerm(slv.mkOp(Kind::INT_TO_BITVECTOR, 4124876294), {t13});
+ Term t66 = slv.mkTerm(Kind::BITVECTOR_SLTBV, {t25, t25});
+ Term t154 = slv.mkTerm(Kind::BITVECTOR_SGT, {t66, t66});
+ slv.checkEntailed({t154, t154, t154, t154});
+}
+
diff --git a/test/api/cpp/sep_log_api.cpp b/test/api/cpp/sep_log_api.cpp
index 5795de794..6a2fc9740 100644
--- a/test/api/cpp/sep_log_api.cpp
+++ b/test/api/cpp/sep_log_api.cpp
@@ -247,8 +247,7 @@ int validate_getters(void)
* than the random constant -- if we get a value that is LTE, then
* something has gone wrong!
*/
- if (std::stoll(value.toString())
- <= std::stoll(random_constant.toString()))
+ if (value.getInt64Value() <= random_constant.getInt64Value())
{
return -1;
}
diff --git a/test/api/python/issue4889.py b/test/api/python/issue4889.py
index 538c9f2ca..eae0ecad7 100644
--- a/test/api/python/issue4889.py
+++ b/test/api/python/issue4889.py
@@ -14,7 +14,7 @@
##
import pycvc5
-from pycvc5 import kinds
+from pycvc5 import Kind
slv = pycvc5.Solver()
sort_int = slv.getIntegerSort()
@@ -25,7 +25,7 @@ sort_bool = slv.getBooleanSort()
const0 = slv.mkConst(sort_fp32, "_c0")
const1 = slv.mkConst(sort_fp32, "_c2")
const2 = slv.mkConst(sort_bool, "_c4")
-ite = slv.mkTerm(kinds.Ite, const2, const1, const0)
-rem = slv.mkTerm(kinds.FPRem, ite, const1)
-isnan = slv.mkTerm(kinds.FPIsNan, rem)
+ite = slv.mkTerm(Kind.Ite, const2, const1, const0)
+rem = slv.mkTerm(Kind.FPRem, ite, const1)
+isnan = slv.mkTerm(Kind.FPIsNan, rem)
slv.checkSatAssuming(isnan)
diff --git a/test/api/python/issue5074.py b/test/api/python/issue5074.py
index 05fc84ad6..f07b5c8fa 100644
--- a/test/api/python/issue5074.py
+++ b/test/api/python/issue5074.py
@@ -14,12 +14,12 @@
##
import pycvc5
-from pycvc5 import kinds
+from pycvc5 import Kind
slv = pycvc5.Solver()
c1 = slv.mkConst(slv.getIntegerSort())
-t6 = slv.mkTerm(kinds.StringFromCode, c1)
-t12 = slv.mkTerm(kinds.StringToRegexp, t6)
-t14 = slv.mkTerm(kinds.StringReplaceRe, [t6, t12, t6])
-t16 = slv.mkTerm(kinds.StringContains, [t14, t14])
+t6 = slv.mkTerm(Kind.StringFromCode, c1)
+t12 = slv.mkTerm(Kind.StringToRegexp, t6)
+t14 = slv.mkTerm(Kind.StringReplaceRe, [t6, t12, t6])
+t16 = slv.mkTerm(Kind.StringContains, [t14, t14])
slv.checkEntailed(t16)
diff --git a/test/api/python/issue6111.py b/test/api/python/issue6111.py
index 6a4ec3842..9bbda286c 100644
--- a/test/api/python/issue6111.py
+++ b/test/api/python/issue6111.py
@@ -14,7 +14,7 @@
##
import pycvc5
-from pycvc5 import kinds
+from pycvc5 import Kind
solver = pycvc5.Solver()
solver.setLogic("QF_BV")
@@ -25,7 +25,7 @@ zero = solver.mkBitVector(bvsort12979.getBitVectorSize(), "0", 10)
args1 = []
args1.append(zero)
args1.append(input2_1)
-bvult_res = solver.mkTerm(kinds.BVUlt, args1)
+bvult_res = solver.mkTerm(Kind.BVUlt, args1)
solver.assertFormula(bvult_res)
bvsort4 = solver.mkBitVectorSort(4)
@@ -36,13 +36,13 @@ concat_result_43 = solver.mkConst(bvsort8, "concat_result_43")
args2 = []
args2.append(concat_result_42)
args2.append(
- solver.mkTerm(solver.mkOp(kinds.BVExtract, 7, 4), [concat_result_43]))
-solver.assertFormula(solver.mkTerm(kinds.Equal, args2))
+ solver.mkTerm(solver.mkOp(Kind.BVExtract, 7, 4), [concat_result_43]))
+solver.assertFormula(solver.mkTerm(Kind.Equal, args2))
args3 = []
args3.append(concat_result_42)
args3.append(
- solver.mkTerm(solver.mkOp(kinds.BVExtract, 3, 0), [concat_result_43]))
-solver.assertFormula(solver.mkTerm(kinds.Equal, args3))
+ solver.mkTerm(solver.mkOp(Kind.BVExtract, 3, 0), [concat_result_43]))
+solver.assertFormula(solver.mkTerm(Kind.Equal, args3))
print(solver.checkSat())
diff --git a/test/api/python/proj-issue306.py b/test/api/python/proj-issue306.py
index 5d84f65b6..7dbdd6b41 100644
--- a/test/api/python/proj-issue306.py
+++ b/test/api/python/proj-issue306.py
@@ -13,7 +13,7 @@
##
import pycvc5
-from pycvc5 import kinds
+from pycvc5 import Kind
slv = pycvc5.Solver()
slv.setOption("check-proofs", "true")
@@ -24,8 +24,8 @@ t1 = slv.mkConst(s3, "_x0")
t3 = slv.mkConst(s1, "_x2")
t11 = slv.mkString("")
t14 = slv.mkConst(s3, "_x11")
-t42 = slv.mkTerm(kinds.Ite, t3, t14, t1)
-t58 = slv.mkTerm(kinds.StringLeq, t14, t11)
-t95 = slv.mkTerm(kinds.Equal, t14, t42)
+t42 = slv.mkTerm(Kind.Ite, t3, t14, t1)
+t58 = slv.mkTerm(Kind.StringLeq, t14, t11)
+t95 = slv.mkTerm(Kind.Equal, t14, t42)
slv.assertFormula(t95)
slv.checkSatAssuming([t58])
diff --git a/test/api/python/reset_assertions.py b/test/api/python/reset_assertions.py
index 221f1c884..8c3a4e44c 100644
--- a/test/api/python/reset_assertions.py
+++ b/test/api/python/reset_assertions.py
@@ -19,7 +19,7 @@
##
import pycvc5
-from pycvc5 import kinds
+from pycvc5 import Kind
slv = pycvc5.Solver()
slv.setOption("incremental", "true")
@@ -27,7 +27,7 @@ slv.setOption("incremental", "true")
real = slv.getRealSort()
x = slv.mkConst(real, "x")
four = slv.mkInteger(4)
-xEqFour = slv.mkTerm(kinds.Equal, x, four)
+xEqFour = slv.mkTerm(Kind.Equal, x, four)
slv.assertFormula(xEqFour)
print(slv.checkSat())
@@ -37,8 +37,8 @@ elementType = slv.getIntegerSort()
indexType = slv.getIntegerSort()
arrayType = slv.mkArraySort(indexType, elementType)
array = slv.mkConst(arrayType, "array")
-arrayAtFour = slv.mkTerm(kinds.Select, array, four)
+arrayAtFour = slv.mkTerm(Kind.Select, array, four)
ten = slv.mkInteger(10)
-arrayAtFour_eq_ten = slv.mkTerm(kinds.Equal, arrayAtFour, ten)
+arrayAtFour_eq_ten = slv.mkTerm(Kind.Equal, arrayAtFour, ten)
slv.assertFormula(arrayAtFour_eq_ten)
print(slv.checkSat())
diff --git a/test/api/python/sep_log_api.py b/test/api/python/sep_log_api.py
index 4e2fbb750..8bbef42fa 100644
--- a/test/api/python/sep_log_api.py
+++ b/test/api/python/sep_log_api.py
@@ -20,7 +20,7 @@
##
import pycvc5
-from pycvc5 import kinds
+from pycvc5 import Kind
# Test function to validate that we *cannot* obtain the heap/nil expressions
@@ -43,7 +43,7 @@ def validate_exception():
y = slv.mkConst(integer, "y")
# y > x
- y_gt_x = slv.mkTerm(kinds.Gt, y, x)
+ y_gt_x = slv.mkTerm(Kind.Gt, y, x)
# assert it
slv.assertFormula(y_gt_x)
@@ -124,18 +124,18 @@ def validate_getters():
p2 = slv.mkConst(integer, "p2")
# Constraints on x and y
- x_equal_const = slv.mkTerm(kinds.Equal, x, random_constant)
- y_gt_x = slv.mkTerm(kinds.Gt, y, x)
+ x_equal_const = slv.mkTerm(Kind.Equal, x, random_constant)
+ y_gt_x = slv.mkTerm(Kind.Gt, y, x)
# Points-to expressions
- p1_to_x = slv.mkTerm(kinds.SepPto, p1, x)
- p2_to_y = slv.mkTerm(kinds.SepPto, p2, y)
+ p1_to_x = slv.mkTerm(Kind.SepPto, p1, x)
+ p2_to_y = slv.mkTerm(Kind.SepPto, p2, y)
# Heap -- the points-to have to be "starred"!
- heap = slv.mkTerm(kinds.SepStar, p1_to_x, p2_to_y)
+ heap = slv.mkTerm(Kind.SepStar, p1_to_x, p2_to_y)
# Constain "nil" to be something random
- fix_nil = slv.mkTerm(kinds.Equal, nil, expr_nil_val)
+ fix_nil = slv.mkTerm(Kind.Equal, nil, expr_nil_val)
# Add it all to the solver!
slv.assertFormula(x_equal_const)
@@ -157,11 +157,11 @@ def validate_getters():
nil_expr = slv.getValueSepNil()
# If the heap is not a separating conjunction, bail-out
- if (heap_expr.getKind() != kinds.SepStar):
+ if (heap_expr.getKind() != Kind.SepStar):
return False
# If nil is not a direct equality, bail-out
- if (nil_expr.getKind() != kinds.Equal):
+ if (nil_expr.getKind() != Kind.Equal):
return False
# Obtain the values for our "pointers"
@@ -175,7 +175,7 @@ def validate_getters():
# Walk all the children
for child in heap_expr:
# If we don't have a PTO operator, bail-out
- if (child.getKind() != kinds.SepPto):
+ if (child.getKind() != Kind.SepPto):
return False
# Find both sides of the PTO operator
diff --git a/test/regress/CMakeLists.txt b/test/regress/CMakeLists.txt
index 4169036ba..20722a1da 100644
--- a/test/regress/CMakeLists.txt
+++ b/test/regress/CMakeLists.txt
@@ -257,6 +257,7 @@ set(regress_0_tests
regress0/bv/bv_to_int_bvuf_to_intuf.smt2
regress0/bv/bv_to_int_bvuf_to_intuf_sorts.smt2
regress0/bv/bv_to_int_elim_err.smt2
+ regress0/bv/bv_to_int_int1.smt2
regress0/bv/bv_to_int_zext.smt2
regress0/bv/bvcomp.cvc.smt2
regress0/bv/bvmul-pow2-only.smt2
@@ -434,6 +435,7 @@ set(regress_0_tests
regress0/bv/mult-pow2-negative.smt2
regress0/bv/pr4993-bvugt-bvurem-a.smt2
regress0/bv/pr4993-bvugt-bvurem-b.smt2
+ regress0/bv/proj-issue343.smt2
regress0/bv/reset-assertions-assert-input.smt2
regress0/bv/sizecheck.cvc.smt2
regress0/bv/smtcompbug.smtv1.smt2
@@ -510,7 +512,9 @@ set(regress_0_tests
regress0/datatypes/mutually-recursive.cvc.smt2
regress0/datatypes/pair-bool-bool.cvc.smt2
regress0/datatypes/pair-real-bool.smt2
+ regress0/datatypes/par-updater-type-rule.smt2
regress0/datatypes/parametric-alt-list.cvc.smt2
+ regress0/datatypes/proj-issue172.smt2
regress0/datatypes/rec1.cvc.smt2
regress0/datatypes/rec2.cvc.smt2
regress0/datatypes/rec4.cvc.smt2
@@ -557,6 +561,8 @@ set(regress_0_tests
regress0/declare-fun-is-match.smt2
regress0/declare-funs.smt2
regress0/define-fun-model.smt2
+ regress0/difficulty-simple.smt2
+ regress0/difficulty-model-ex.smt2
regress0/distinct.smtv1.smt2
regress0/dump-unsat-core-full.smt2
regress0/echo.smt2
@@ -783,6 +789,7 @@ set(regress_0_tests
regress0/options/didyoumean.smt2
regress0/options/help.smt2
regress0/options/interactive-mode.smt2
+ regress0/options/named_muted.smt2
regress0/options/set-after-init.smt2
regress0/options/set-and-get-options.smt2
regress0/options/statistics.smt2
@@ -1303,6 +1310,7 @@ set(regress_0_tests
regress0/sygus/General_plus10.sy
regress0/sygus/hd-05-d1-prog-nogrammar.sy
regress0/sygus/ho-occ-synth-fun.sy
+ regress0/sygus/incremental-modify-ex.sy
regress0/sygus/inv-different-var-order.sy
regress0/sygus/issue3356-syg-inf-usort.smt2
regress0/sygus/issue3624.sy
@@ -1597,6 +1605,7 @@ set(regress_1_tests
regress1/bug694-Unapply1.scala-0.smt2
regress1/bug800.smt2
regress1/bags/card1.smt2
+ regress1/bags/card2.smt2
regress1/bags/choose1.smt2
regress1/bags/choose2.smt2
regress1/bags/choose3.smt2
@@ -1616,10 +1625,12 @@ set(regress_1_tests
regress1/bags/intersection_min1.smt2
regress1/bags/intersection_min2.smt2
regress1/bags/issue5759.smt2
- regress1/bags/map-lazy-lam.smt2
regress1/bags/map1.smt2
regress1/bags/map2.smt2
regress1/bags/map3.smt2
+ regress1/bags/map-lazy-lam.smt2
+ regress1/bags/murxla1.smt2
+ regress1/bags/murxla2.smt2
regress1/bags/subbag1.smt2
regress1/bags/subbag2.smt2
regress1/bags/union_disjoint.smt2
@@ -1679,6 +1690,7 @@ set(regress_1_tests
regress1/decision/wishue149-2.smt2
regress1/decision/wishue149-3.smt2
regress1/decision/wishue160.smt2
+ regress1/difficulty-polarity.smt2
regress1/errorcrash.smt2
regress1/fp/fp_to_real.smt2
regress1/fp/rti_3_5_bug_report.smt2
@@ -1845,6 +1857,7 @@ set(regress_1_tests
regress1/nl/tan-rewrite2.smt2
regress1/nl/zero-subset.smt2
regress1/non-fatal-errors.smt2
+ regress1/proj-issue175.smt2
regress1/proof00.smt2
regress1/proofs/issue6625-unsat-core-proofs.smt2
regress1/proofs/macro-res-exp-crowding-lit-inside-unit.smt2
@@ -2218,6 +2231,8 @@ set(regress_1_tests
regress1/sets/issue5342_difference_version.smt2
regress1/sets/issue5942-witness.smt2
regress1/sets/lemmabug-ListElts317minimized.smt2
+ regress1/sets/proj-issue164.smt2
+ regress1/sets/proj-issue178.smt2
regress1/sets/remove_check_free_31_6.smt2
regress1/sets/sets-disequal.smt2
regress1/sets/sets-tuple-poly.cvc.smt2
@@ -2510,6 +2525,9 @@ set(regress_1_tests
regress1/sygus/phone-1-long.sy
regress1/sygus/planning-unif.sy
regress1/sygus/process-10-vars.sy
+ regress1/sygus/proj-issue181.smt2
+ regress1/sygus/proj-issue183.smt2
+ regress1/sygus/proj-issue185.smt2
regress1/sygus/pLTL_5_trace.sy
regress1/sygus/qe.sy
regress1/sygus/qf_abv.smt2
@@ -2612,6 +2630,7 @@ set(regress_2_tests
regress2/bv_to_int_mask_array_2.smt2
regress2/bv_to_int_mask_array_3.smt2
regress2/bv_to_int_shifts.smt2
+ regress2/bv_to_int_quantifiers_bvand.smt2
regress2/error1.smtv1.smt2
regress2/fp/issue7056.smt2
regress2/fuzz_2.smtv1.smt2
@@ -2677,7 +2696,7 @@ set(regress_2_tests
regress2/strings/replaceall-diffrange.smt2
regress2/strings/replaceall-len-c.smt2
regress2/strings/small-1.smt2
- regress2/strings/strings-alpha-card-129.smt2
+ regress2/strings/strings-alpha-card-65.smt2
regress2/strings/update-ex3.smt2
regress2/strings/update-ex4-seq.smt2
regress2/sygus/MPwL_d1s3.sy
diff --git a/test/regress/regress0/arith/issue5219-conflict-rewrite.smt2 b/test/regress/regress0/arith/issue5219-conflict-rewrite.smt2
index ccb50c55d..b49287c30 100644
--- a/test/regress/regress0/arith/issue5219-conflict-rewrite.smt2
+++ b/test/regress/regress0/arith/issue5219-conflict-rewrite.smt2
@@ -1,6 +1,6 @@
; REQUIRES: poly
; COMMAND-LINE: --theoryof-mode=term --nl-icp
-; EXPECT: unknown
+; EXPECT: sat
(set-logic QF_NRA)
(set-option :check-proofs true)
(declare-fun x () Real)
diff --git a/test/regress/regress0/bv/bv_to_int1.smt2 b/test/regress/regress0/bv/bv_to_int1.smt2
index 3908cdb16..eb8e75803 100644
--- a/test/regress/regress0/bv/bv_to_int1.smt2
+++ b/test/regress/regress0/bv/bv_to_int1.smt2
@@ -1,4 +1,5 @@
; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1
; EXPECT: unsat
(set-logic QF_BV)
(declare-fun x () (_ BitVec 4))
diff --git a/test/regress/regress0/bv/bv_to_int_bvmul2.smt2 b/test/regress/regress0/bv/bv_to_int_bvmul2.smt2
index 91e0c45fd..eced6e0e9 100644
--- a/test/regress/regress0/bv/bv_to_int_bvmul2.smt2
+++ b/test/regress/regress0/bv/bv_to_int_bvmul2.smt2
@@ -1,4 +1,5 @@
; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1 --no-check-unsat-cores
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1 --no-check-unsat-cores
; EXPECT: unsat
(set-logic QF_BV)
(declare-fun T4_180 () (_ BitVec 32))
diff --git a/test/regress/regress0/bv/bv_to_int_bvuf_to_intuf.smt2 b/test/regress/regress0/bv/bv_to_int_bvuf_to_intuf.smt2
index 3e545ef03..45d539f04 100644
--- a/test/regress/regress0/bv/bv_to_int_bvuf_to_intuf.smt2
+++ b/test/regress/regress0/bv/bv_to_int_bvuf_to_intuf.smt2
@@ -1,4 +1,5 @@
; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1
; EXPECT: sat
(set-logic QF_UFBV)
(declare-fun a () (_ BitVec 4))
diff --git a/test/regress/regress0/bv/bv_to_int_bvuf_to_intuf_sorts.smt2 b/test/regress/regress0/bv/bv_to_int_bvuf_to_intuf_sorts.smt2
index 0a0ec7b20..ae77380dd 100644
--- a/test/regress/regress0/bv/bv_to_int_bvuf_to_intuf_sorts.smt2
+++ b/test/regress/regress0/bv/bv_to_int_bvuf_to_intuf_sorts.smt2
@@ -1,4 +1,5 @@
; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1
; EXPECT: sat
(set-logic QF_UFBV)
(declare-sort S 0)
diff --git a/test/regress/regress0/bv/bv_to_int_elim_err.smt2 b/test/regress/regress0/bv/bv_to_int_elim_err.smt2
index 01ee5dad8..cb7eefbb2 100644
--- a/test/regress/regress0/bv/bv_to_int_elim_err.smt2
+++ b/test/regress/regress0/bv/bv_to_int_elim_err.smt2
@@ -1,4 +1,5 @@
-; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
+; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1
; EXPECT: sat
(set-logic QF_BV)
(declare-fun _substvar_183_ () (_ BitVec 32))
diff --git a/test/regress/regress0/bv/bv_to_int_int1.smt2 b/test/regress/regress0/bv/bv_to_int_int1.smt2
new file mode 100644
index 000000000..3295d3481
--- /dev/null
+++ b/test/regress/regress0/bv/bv_to_int_int1.smt2
@@ -0,0 +1,11 @@
+; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
+; EXPECT: sat
+(set-logic QF_ALL)
+(declare-fun x () (_ BitVec 4))
+(declare-fun y () (_ BitVec 4))
+(declare-fun z () Int)
+(declare-fun w () Int)
+(assert (= x (_ bv3 4)))
+(assert (= y (_ bv3 4)))
+(assert (> z w))
+(check-sat)
diff --git a/test/regress/regress0/bv/bv_to_int_zext.smt2 b/test/regress/regress0/bv/bv_to_int_zext.smt2
index 8bf4a825d..4fd6109f4 100644
--- a/test/regress/regress0/bv/bv_to_int_zext.smt2
+++ b/test/regress/regress0/bv/bv_to_int_zext.smt2
@@ -1,4 +1,5 @@
; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1
; EXPECT: unsat
(set-logic QF_BV)
(declare-fun T1_31078 () (_ BitVec 8))
diff --git a/test/regress/regress0/bv/proj-issue343.smt2 b/test/regress/regress0/bv/proj-issue343.smt2
new file mode 100644
index 000000000..6d2971ad8
--- /dev/null
+++ b/test/regress/regress0/bv/proj-issue343.smt2
@@ -0,0 +1,7 @@
+; EXPECT: sat
+; COMMAND-LINE: --no-check-models
+(set-logic ALL)
+(set-option :solve-bv-as-int bv)
+(declare-const _x8 Real)
+(assert (distinct real.pi _x8))
+(check-sat)
diff --git a/test/regress/regress0/datatypes/par-updater-type-rule.smt2 b/test/regress/regress0/datatypes/par-updater-type-rule.smt2
new file mode 100644
index 000000000..0b4af0287
--- /dev/null
+++ b/test/regress/regress0/datatypes/par-updater-type-rule.smt2
@@ -0,0 +1,11 @@
+(set-option :global-declarations true)
+(set-logic ALL)
+(set-info :status unsat)
+(declare-datatype _x0 ( (_x6 (_x1 Bool))))
+(declare-datatype _x36 ( (_x42 (_x37 Bool))))
+(declare-const _x53 Bool)
+(declare-const _x56 _x36)
+(declare-const _x58 _x0)
+(declare-datatype _x176 ( par ( _x178 ) ( (_x186 (_x185 _x178)) (_x184 (_x180 _x0)))) )
+(assert (let ((_let0 ((_ update _x185) (_x184 _x58) _x58)))(distinct _let0 _let0)))
+(check-sat)
diff --git a/test/regress/regress0/datatypes/proj-issue172.smt2 b/test/regress/regress0/datatypes/proj-issue172.smt2
new file mode 100644
index 000000000..f9f5a2ffc
--- /dev/null
+++ b/test/regress/regress0/datatypes/proj-issue172.smt2
@@ -0,0 +1,7 @@
+(set-logic ALL)
+(set-info :status sat)
+(declare-codatatypes ((a 0)) (((b (c Int) (d a)))))
+(declare-fun e () a)
+(declare-fun f () a)
+(assert (= e f))
+(check-sat)
diff --git a/test/regress/regress0/difficulty-model-ex.smt2 b/test/regress/regress0/difficulty-model-ex.smt2
new file mode 100644
index 000000000..0546b5118
--- /dev/null
+++ b/test/regress/regress0/difficulty-model-ex.smt2
@@ -0,0 +1,22 @@
+; COMMAND-LINE: --produce-difficulty --difficulty-mode=model-check
+; SCRUBBER: sed 's/.*//g'
+; EXIT: 0
+
+(set-logic ALL)
+(set-option :produce-difficulty true)
+(declare-fun P (Int) Bool)
+(declare-fun x () Int)
+(declare-fun y () Int)
+(declare-fun z () Int)
+
+(assert (= z 78))
+
+(assert (! (= (* x x) z) :named a1))
+
+(assert (= y 0))
+
+(assert (P y))
+
+(check-sat)
+
+(get-difficulty)
diff --git a/test/regress/regress0/difficulty-simple.smt2 b/test/regress/regress0/difficulty-simple.smt2
new file mode 100644
index 000000000..a82a96550
--- /dev/null
+++ b/test/regress/regress0/difficulty-simple.smt2
@@ -0,0 +1,16 @@
+; COMMAND-LINE: --produce-difficulty
+; SCRUBBER: sed 's/.*//g'
+; EXIT: 0
+
+(set-logic ALL)
+(set-option :produce-difficulty true)
+(declare-fun a () Int)
+(declare-fun b () Int)
+(declare-fun c () Int)
+
+(assert (or (> a 0) (> b 0) (> c 0)))
+
+(assert (< (ite (> a b) a b) 0))
+
+(check-sat)
+(get-difficulty)
diff --git a/test/regress/regress0/options/didyoumean.smt2 b/test/regress/regress0/options/didyoumean.smt2
index d95c1bde9..100e1e6fb 100644
--- a/test/regress/regress0/options/didyoumean.smt2
+++ b/test/regress/regress0/options/didyoumean.smt2
@@ -1,3 +1,4 @@
+; REQUIRES: no-competition
; COMMAND-LINE: --input-agnuage
; ERROR-SCRUBBER: grep -o "--[a-zA-Z-]+"
; ERROR-EXPECT: --input-language
diff --git a/test/regress/regress0/options/named_muted.smt2 b/test/regress/regress0/options/named_muted.smt2
new file mode 100644
index 000000000..7026298c6
--- /dev/null
+++ b/test/regress/regress0/options/named_muted.smt2
@@ -0,0 +1,6 @@
+; COMMAND-LINE: --print-success
+; EXPECT: success
+; EXPECT: success
+
+(set-logic UF)
+(assert (! true :named t))
diff --git a/test/regress/regress0/sygus/incremental-modify-ex.sy b/test/regress/regress0/sygus/incremental-modify-ex.sy
new file mode 100644
index 000000000..f453964b0
--- /dev/null
+++ b/test/regress/regress0/sygus/incremental-modify-ex.sy
@@ -0,0 +1,26 @@
+; COMMAND-LINE: -i --sygus-out=status
+;EXPECT: unsat
+;EXPECT: unsat
+(set-logic LIA)
+
+(synth-fun f ((x Int) (y Int)) Int
+ ((Start Int) (StartBool Bool))
+ ((Start Int (0 1 x y
+ (+ Start Start)
+ (- Start Start)
+ (ite StartBool Start Start)))
+ (StartBool Bool ((and StartBool StartBool)
+ (not StartBool)
+ (<= Start Start)))))
+
+
+(declare-var x Int)
+(declare-var y Int)
+
+(push 1)
+(constraint (>= (f x y) 0))
+(check-synth)
+(pop 1)
+
+(constraint (< (f x y) 0))
+(check-synth)
diff --git a/test/regress/regress1/bags/card1.smt2 b/test/regress/regress1/bags/card1.smt2
index 4ea5488d2..3b19fb2cf 100644
--- a/test/regress/regress1/bags/card1.smt2
+++ b/test/regress/regress1/bags/card1.smt2
@@ -1,7 +1,8 @@
-; COMMAND-LINE: --fmf-bound --uf-lazy-ll
-; EXPECT: sat
-(set-logic HO_ALL)
-(define-fun f ((x String)) Int 1)
+(set-logic ALL)
+(set-option :fmf-bound true)
+(set-option :produce-models true)
+(set-info :status sat)
(declare-fun A () (Bag String))
-(assert (= (bag.card A) 20))
+(assert (= (bag.card A) 10000000))
(check-sat)
+
diff --git a/test/regress/regress1/bags/card2.smt2 b/test/regress/regress1/bags/card2.smt2
new file mode 100644
index 000000000..260c6927f
--- /dev/null
+++ b/test/regress/regress1/bags/card2.smt2
@@ -0,0 +1,11 @@
+(set-logic ALL)
+(set-option :fmf-bound true)
+(set-option :produce-models true)
+(set-info :status sat)
+(declare-fun A () (Bag String))
+(declare-fun B () (Bag String))
+(declare-fun C () (Bag String))
+(assert (distinct A B C (as bag.empty (Bag String))))
+(assert (= C (bag.union_disjoint A B)))
+(assert (= (bag.card C) 10000000))
+(check-sat)
diff --git a/test/regress/regress1/bags/murxla1.smt2 b/test/regress/regress1/bags/murxla1.smt2
new file mode 100644
index 000000000..248f566f0
--- /dev/null
+++ b/test/regress/regress1/bags/murxla1.smt2
@@ -0,0 +1,6 @@
+(set-logic ALL)
+(set-option :produce-models true)
+(set-info :status sat)
+(declare-const A (Bag Bool))
+(declare-const B (Bag Bool))
+(check-sat-assuming ((distinct A B)))
diff --git a/test/regress/regress1/bags/murxla2.smt2 b/test/regress/regress1/bags/murxla2.smt2
new file mode 100644
index 000000000..82ca2e90c
--- /dev/null
+++ b/test/regress/regress1/bags/murxla2.smt2
@@ -0,0 +1,6 @@
+(set-logic ALL)
+(set-info :status sat)
+(set-option :strings-exp true)
+(declare-const x Int)
+(assert (seq.contains (seq.at (seq.unit (bag false x)) x) (seq.unit (bag false x))))
+(check-sat)
diff --git a/test/regress/regress1/difficulty-polarity.smt2 b/test/regress/regress1/difficulty-polarity.smt2
new file mode 100644
index 000000000..ce2388c54
--- /dev/null
+++ b/test/regress/regress1/difficulty-polarity.smt2
@@ -0,0 +1,31 @@
+; COMMAND-LINE: --produce-difficulty
+; SCRUBBER: sed 's/.*//g'
+; EXIT: 0
+
+(set-logic ALL)
+(set-option :finite-model-find true)
+(set-option :mbqi none)
+(set-option :produce-difficulty true)
+
+(declare-sort U 0)
+(declare-fun a () U)
+(declare-fun b () U)
+(declare-fun c () U)
+(assert (distinct a b c))
+(declare-fun P (U U) Bool)
+(declare-fun R (U) Bool)
+(declare-fun S (U) Bool)
+
+(define-fun Q () Bool (forall ((x U) (y U)) (P x y)))
+
+(assert (or (not Q) (S a)))
+(assert (R a))
+(assert (=> (R a) Q))
+
+; This example will instantiate the quantified formula 9 times, hence the
+; explanation for why it is relevant will be incremented by 9.
+; The explanation for why Q is relevant should be (=> (R b) Q) and
+; not (or (not Q) (S a)), since the former is the reason it is asserted true.
+
+(check-sat)
+(get-difficulty)
diff --git a/test/regress/regress1/nl/cos1-tc.smt2 b/test/regress/regress1/nl/cos1-tc.smt2
index bedc0209b..ba49f23fe 100644
--- a/test/regress/regress1/nl/cos1-tc.smt2
+++ b/test/regress/regress1/nl/cos1-tc.smt2
@@ -1,5 +1,5 @@
; COMMAND-LINE: --nl-ext=full --no-nl-ext-tf-tplanes --no-nl-ext-inc-prec
-; EXPECT: unknown
+; EXPECT: sat
(set-logic UFNRAT)
(declare-fun f (Real) Real)
diff --git a/test/regress/regress1/proj-issue175.smt2 b/test/regress/regress1/proj-issue175.smt2
new file mode 100644
index 000000000..2df1e21e6
--- /dev/null
+++ b/test/regress/regress1/proj-issue175.smt2
@@ -0,0 +1,83 @@
+(set-logic QF_AUFNIA)
+(set-info :status sat)
+(declare-fun |#offset~STRUCT#?type~INT?length~UINT?off~UINT?data~$Pointer$?input~$Pointer$?comp~$Pointer$#~data| () Int)
+(declare-fun |ssl3_accept_#t~mem38_491| () Int)
+(declare-fun |#offset~STRUCT#?version~INT?type~INT?method~$Pointer$?rbio~$Pointer$?wbio~$Pointer$?bbio~$Pointer$?rwstate~INT?in_handshake~INT?handshake_func~$Pointer$?server~INT?new_session~INT?quiet_shutdown~INT?shutdown~INT?state~INT?rstate~INT?init_buf~$Pointer$?init_num~INT?init_off~INT?packet~$Pointer$?packet_length~UINT?s2~$Pointer$?s3~$Pointer$?read_ahead~INT?hit~INT?purpose~INT?trust~INT?cipher_list~$Pointer$?cipher_list_by_id~$Pointer$?enc_read_ctx~$Pointer$?read_hash~$Pointer$?expand~$Pointer$?enc_write_ctx~$Pointer$?write_hash~$Pointer$?compress~$Pointer$?cert~$Pointer$?sid_ctx_length~UINT?sid_ctx~ARRAY#_32_~UCHAR#?session~$Pointer$?verify_mode~INT?verify_depth~INT?verify_callback~$Pointer$?info_callback~$Pointer$?error~INT?error_code~INT?ctx~$Pointer$?debug~INT?verify_result~LONG?ex_data~~CRYPTO_EX_DATA?client_CA~$Pointer$?references~INT?options~ULONG?mode~ULONG?first_packet~INT?client_version~INT#~state| () Int)
+(declare-fun ssl3_accept_~s.offset_12 () Int)
+(declare-fun ssl3_accept_~s.base_12 () Int)
+(declare-fun |#memory_int_136| () (Array Int (Array Int Int)))
+(declare-fun |ssl3_accept_#t~mem35_173| () Int)
+(declare-fun |ssl3_accept_#t~mem49_513| () Int)
+(declare-fun |ssl3_accept_#t~mem29_161| () Int)
+(declare-fun |#memory_int_53| () (Array Int (Array Int Int)))
+(declare-fun |ssl3_accept_#t~mem24_68| () Int)
+(declare-fun |#memory_int_601| () (Array Int (Array Int Int)))
+(declare-fun |ssl3_accept_#t~mem31_631| () Int)
+(declare-fun |#offset~STRUCT#?version~INT?type~INT?method~$Pointer$?rbio~$Pointer$?wbio~$Pointer$?bbio~$Pointer$?rwstate~INT?in_handshake~INT?handshake_func~$Pointer$?server~INT?new_session~INT?quiet_shutdown~INT?shutdown~INT?state~INT?rstate~INT?init_buf~$Pointer$?init_num~INT?init_off~INT?packet~$Pointer$?packet_length~UINT?s2~$Pointer$?s3~$Pointer$?read_ahead~INT?hit~INT?purpose~INT?trust~INT?cipher_list~$Pointer$?cipher_list_by_id~$Pointer$?enc_read_ctx~$Pointer$?read_hash~$Pointer$?expand~$Pointer$?enc_write_ctx~$Pointer$?write_hash~$Pointer$?compress~$Pointer$?cert~$Pointer$?sid_ctx_length~UINT?sid_ctx~ARRAY#_32_~UCHAR#?session~$Pointer$?verify_mode~INT?verify_depth~INT?verify_callback~$Pointer$?info_callback~$Pointer$?error~INT?error_code~INT?ctx~$Pointer$?debug~INT?verify_result~LONG?ex_data~~CRYPTO_EX_DATA?client_CA~$Pointer$?references~INT?options~ULONG?mode~ULONG?first_packet~INT?client_version~INT#~init_num| () Int)
+(declare-fun |#memory_$Pointer$.base_53| () (Array Int (Array Int Int)))
+(declare-fun |#memory_$Pointer$.base_52| () (Array Int (Array Int Int)))
+(declare-fun |ssl3_accept_#t~nondet159_515| () Int)
+(declare-fun ssl3_accept_~ret~10_753 () Int)
+(declare-fun ssl3_accept_~ret~10_314 () Int)
+(declare-fun |ssl3_accept_#t~mem22_459| () Int)
+(declare-fun |#offset~STRUCT#?version~INT?type~INT?method~$Pointer$?rbio~$Pointer$?wbio~$Pointer$?bbio~$Pointer$?rwstate~INT?in_handshake~INT?handshake_func~$Pointer$?server~INT?new_session~INT?quiet_shutdown~INT?shutdown~INT?state~INT?rstate~INT?init_buf~$Pointer$?init_num~INT?init_off~INT?packet~$Pointer$?packet_length~UINT?s2~$Pointer$?s3~$Pointer$?read_ahead~INT?hit~INT?purpose~INT?trust~INT?cipher_list~$Pointer$?cipher_list_by_id~$Pointer$?enc_read_ctx~$Pointer$?read_hash~$Pointer$?expand~$Pointer$?enc_write_ctx~$Pointer$?write_hash~$Pointer$?compress~$Pointer$?cert~$Pointer$?sid_ctx_length~UINT?sid_ctx~ARRAY#_32_~UCHAR#?session~$Pointer$?verify_mode~INT?verify_depth~INT?verify_callback~$Pointer$?info_callback~$Pointer$?error~INT?error_code~INT?ctx~$Pointer$?debug~INT?verify_result~LONG?ex_data~~CRYPTO_EX_DATA?client_CA~$Pointer$?references~INT?options~ULONG?mode~ULONG?first_packet~INT?client_version~INT#~s3| () Int)
+(declare-fun |#memory_$Pointer$.offset_521| () (Array Int (Array Int Int)))
+(declare-fun |ssl3_accept_#t~mem165.offset_593| () Int)
+(declare-fun |ssl3_accept_#t~mem23_461| () Int)
+(declare-fun |#offset~STRUCT#?version~INT?type~INT?method~$Pointer$?rbio~$Pointer$?wbio~$Pointer$?bbio~$Pointer$?rwstate~INT?in_handshake~INT?handshake_func~$Pointer$?server~INT?new_session~INT?quiet_shutdown~INT?shutdown~INT?state~INT?rstate~INT?init_buf~$Pointer$?init_num~INT?init_off~INT?packet~$Pointer$?packet_length~UINT?s2~$Pointer$?s3~$Pointer$?read_ahead~INT?hit~INT?purpose~INT?trust~INT?cipher_list~$Pointer$?cipher_list_by_id~$Pointer$?enc_read_ctx~$Pointer$?read_hash~$Pointer$?expand~$Pointer$?enc_write_ctx~$Pointer$?write_hash~$Pointer$?compress~$Pointer$?cert~$Pointer$?sid_ctx_length~UINT?sid_ctx~ARRAY#_32_~UCHAR#?session~$Pointer$?verify_mode~INT?verify_depth~INT?verify_callback~$Pointer$?info_callback~$Pointer$?error~INT?error_code~INT?ctx~$Pointer$?debug~INT?verify_result~LONG?ex_data~~CRYPTO_EX_DATA?client_CA~$Pointer$?references~INT?options~ULONG?mode~ULONG?first_packet~INT?client_version~INT#~packet| () Int)
+(assert
+ (let (($x220 (= |#offset~STRUCT#?type~INT?length~UINT?off~UINT?data~$Pointer$?input~$Pointer$?comp~$Pointer$#~data| 12)))
+ (let (($x2621 (= |ssl3_accept_#t~mem38_491| 8544)))
+ (let (($x2622 (not $x2621)))
+ (let (($x10875 (not $x2622)))
+ (let (($x23085 (and $x10875 $x220)))
+ (not $x23085)))))))
+(assert
+ (let ((?x806 (+ ssl3_accept_~s.offset_12 |#offset~STRUCT#?version~INT?type~INT?method~$Pointer$?rbio~$Pointer$?wbio~$Pointer$?bbio~$Pointer$?rwstate~INT?in_handshake~INT?handshake_func~$Pointer$?server~INT?new_session~INT?quiet_shutdown~INT?shutdown~INT?state~INT?rstate~INT?init_buf~$Pointer$?init_num~INT?init_off~INT?packet~$Pointer$?packet_length~UINT?s2~$Pointer$?s3~$Pointer$?read_ahead~INT?hit~INT?purpose~INT?trust~INT?cipher_list~$Pointer$?cipher_list_by_id~$Pointer$?enc_read_ctx~$Pointer$?read_hash~$Pointer$?expand~$Pointer$?enc_write_ctx~$Pointer$?write_hash~$Pointer$?compress~$Pointer$?cert~$Pointer$?sid_ctx_length~UINT?sid_ctx~ARRAY#_32_~UCHAR#?session~$Pointer$?verify_mode~INT?verify_depth~INT?verify_callback~$Pointer$?info_callback~$Pointer$?error~INT?error_code~INT?ctx~$Pointer$?debug~INT?verify_result~LONG?ex_data~~CRYPTO_EX_DATA?client_CA~$Pointer$?references~INT?options~ULONG?mode~ULONG?first_packet~INT?client_version~INT#~state|)))
+ (let ((?x1399 (select |#memory_int_136| ssl3_accept_~s.base_12)))
+ (let ((?x1400 (select ?x1399 ?x806)))
+ (let (($x1478 (>= |ssl3_accept_#t~mem35_173| ?x1400)))
+ (not $x1478))))))
+(assert
+ (let (($x2678 (>= |ssl3_accept_#t~mem49_513| 8640)))
+ (not $x2678)))
+(assert
+ (let ((?x806 (+ ssl3_accept_~s.offset_12 |#offset~STRUCT#?version~INT?type~INT?method~$Pointer$?rbio~$Pointer$?wbio~$Pointer$?bbio~$Pointer$?rwstate~INT?in_handshake~INT?handshake_func~$Pointer$?server~INT?new_session~INT?quiet_shutdown~INT?shutdown~INT?state~INT?rstate~INT?init_buf~$Pointer$?init_num~INT?init_off~INT?packet~$Pointer$?packet_length~UINT?s2~$Pointer$?s3~$Pointer$?read_ahead~INT?hit~INT?purpose~INT?trust~INT?cipher_list~$Pointer$?cipher_list_by_id~$Pointer$?enc_read_ctx~$Pointer$?read_hash~$Pointer$?expand~$Pointer$?enc_write_ctx~$Pointer$?write_hash~$Pointer$?compress~$Pointer$?cert~$Pointer$?sid_ctx_length~UINT?sid_ctx~ARRAY#_32_~UCHAR#?session~$Pointer$?verify_mode~INT?verify_depth~INT?verify_callback~$Pointer$?info_callback~$Pointer$?error~INT?error_code~INT?ctx~$Pointer$?debug~INT?verify_result~LONG?ex_data~~CRYPTO_EX_DATA?client_CA~$Pointer$?references~INT?options~ULONG?mode~ULONG?first_packet~INT?client_version~INT#~state|)))
+ (let ((?x1399 (select |#memory_int_136| ssl3_accept_~s.base_12)))
+ (let ((?x1400 (select ?x1399 ?x806)))
+ (let (($x1447 (<= |ssl3_accept_#t~mem29_161| ?x1400)))
+ (let ((?x1089 (select |#memory_int_53| ssl3_accept_~s.base_12)))
+ (let ((?x1090 (select ?x1089 ?x806)))
+ (let (($x1113 (>= |ssl3_accept_#t~mem24_68| ?x1090)))
+ (let (($x19982 (and $x1113 $x1447)))
+ (not $x19982))))))))))
+(assert
+ (let ((?x806 (+ ssl3_accept_~s.offset_12 |#offset~STRUCT#?version~INT?type~INT?method~$Pointer$?rbio~$Pointer$?wbio~$Pointer$?bbio~$Pointer$?rwstate~INT?in_handshake~INT?handshake_func~$Pointer$?server~INT?new_session~INT?quiet_shutdown~INT?shutdown~INT?state~INT?rstate~INT?init_buf~$Pointer$?init_num~INT?init_off~INT?packet~$Pointer$?packet_length~UINT?s2~$Pointer$?s3~$Pointer$?read_ahead~INT?hit~INT?purpose~INT?trust~INT?cipher_list~$Pointer$?cipher_list_by_id~$Pointer$?enc_read_ctx~$Pointer$?read_hash~$Pointer$?expand~$Pointer$?enc_write_ctx~$Pointer$?write_hash~$Pointer$?compress~$Pointer$?cert~$Pointer$?sid_ctx_length~UINT?sid_ctx~ARRAY#_32_~UCHAR#?session~$Pointer$?verify_mode~INT?verify_depth~INT?verify_callback~$Pointer$?info_callback~$Pointer$?error~INT?error_code~INT?ctx~$Pointer$?debug~INT?verify_result~LONG?ex_data~~CRYPTO_EX_DATA?client_CA~$Pointer$?references~INT?options~ULONG?mode~ULONG?first_packet~INT?client_version~INT#~state|)))
+ (let ((?x3029 (select |#memory_int_601| ssl3_accept_~s.base_12)))
+ (let ((?x3030 (select ?x3029 ?x806)))
+ (let (($x3088 (>= |ssl3_accept_#t~mem31_631| ?x3030)))
+ (let ((?x1050 (+ ssl3_accept_~s.offset_12 |#offset~STRUCT#?version~INT?type~INT?method~$Pointer$?rbio~$Pointer$?wbio~$Pointer$?bbio~$Pointer$?rwstate~INT?in_handshake~INT?handshake_func~$Pointer$?server~INT?new_session~INT?quiet_shutdown~INT?shutdown~INT?state~INT?rstate~INT?init_buf~$Pointer$?init_num~INT?init_off~INT?packet~$Pointer$?packet_length~UINT?s2~$Pointer$?s3~$Pointer$?read_ahead~INT?hit~INT?purpose~INT?trust~INT?cipher_list~$Pointer$?cipher_list_by_id~$Pointer$?enc_read_ctx~$Pointer$?read_hash~$Pointer$?expand~$Pointer$?enc_write_ctx~$Pointer$?write_hash~$Pointer$?compress~$Pointer$?cert~$Pointer$?sid_ctx_length~UINT?sid_ctx~ARRAY#_32_~UCHAR#?session~$Pointer$?verify_mode~INT?verify_depth~INT?verify_callback~$Pointer$?info_callback~$Pointer$?error~INT?error_code~INT?ctx~$Pointer$?debug~INT?verify_result~LONG?ex_data~~CRYPTO_EX_DATA?client_CA~$Pointer$?references~INT?options~ULONG?mode~ULONG?first_packet~INT?client_version~INT#~init_num|)))
+ (let ((?x1051 (select |#memory_$Pointer$.base_53| ssl3_accept_~s.base_12)))
+ (let ((?x1032 (select |#memory_$Pointer$.base_52| ssl3_accept_~s.base_12)))
+ (let ((?x1054 (store |#memory_$Pointer$.base_52| ssl3_accept_~s.base_12 (store ?x1032 ?x1050 (select ?x1051 ?x1050)))))
+ (let (($x1055 (= |#memory_$Pointer$.base_53| ?x1054)))
+ (let (($x11490 (and $x1055 $x3088)))
+ (not $x11490))))))))))))
+(assert
+ (let (($x3458 (>= ssl3_accept_~ret~10_753 |ssl3_accept_#t~nondet159_515|)))
+ (let (($x2065 (not (<= ssl3_accept_~ret~10_314 0))))
+ (let (($x50182 (and $x2065 $x3458)))
+ (not $x50182)))))
+(assert
+ (let (($x2542 (not (= |ssl3_accept_#t~mem22_459| 16384))))
+ (let ((?x1068 (+ ssl3_accept_~s.offset_12 |#offset~STRUCT#?version~INT?type~INT?method~$Pointer$?rbio~$Pointer$?wbio~$Pointer$?bbio~$Pointer$?rwstate~INT?in_handshake~INT?handshake_func~$Pointer$?server~INT?new_session~INT?quiet_shutdown~INT?shutdown~INT?state~INT?rstate~INT?init_buf~$Pointer$?init_num~INT?init_off~INT?packet~$Pointer$?packet_length~UINT?s2~$Pointer$?s3~$Pointer$?read_ahead~INT?hit~INT?purpose~INT?trust~INT?cipher_list~$Pointer$?cipher_list_by_id~$Pointer$?enc_read_ctx~$Pointer$?read_hash~$Pointer$?expand~$Pointer$?enc_write_ctx~$Pointer$?write_hash~$Pointer$?compress~$Pointer$?cert~$Pointer$?sid_ctx_length~UINT?sid_ctx~ARRAY#_32_~UCHAR#?session~$Pointer$?verify_mode~INT?verify_depth~INT?verify_callback~$Pointer$?info_callback~$Pointer$?error~INT?error_code~INT?ctx~$Pointer$?debug~INT?verify_result~LONG?ex_data~~CRYPTO_EX_DATA?client_CA~$Pointer$?references~INT?options~ULONG?mode~ULONG?first_packet~INT?client_version~INT#~s3|)))
+ (let ((?x2719 (select |#memory_$Pointer$.offset_521| ssl3_accept_~s.base_12)))
+ (let ((?x2734 (select ?x2719 ?x1068)))
+ (let (($x2925 (<= |ssl3_accept_#t~mem165.offset_593| ?x2734)))
+ (and $x2925 $x2542)))))))
+(assert
+ (let (($x2547 (not (= |ssl3_accept_#t~mem23_461| 8192))))
+ (let (($x73 (= |#offset~STRUCT#?version~INT?type~INT?method~$Pointer$?rbio~$Pointer$?wbio~$Pointer$?bbio~$Pointer$?rwstate~INT?in_handshake~INT?handshake_func~$Pointer$?server~INT?new_session~INT?quiet_shutdown~INT?shutdown~INT?state~INT?rstate~INT?init_buf~$Pointer$?init_num~INT?init_off~INT?packet~$Pointer$?packet_length~UINT?s2~$Pointer$?s3~$Pointer$?read_ahead~INT?hit~INT?purpose~INT?trust~INT?cipher_list~$Pointer$?cipher_list_by_id~$Pointer$?enc_read_ctx~$Pointer$?read_hash~$Pointer$?expand~$Pointer$?enc_write_ctx~$Pointer$?write_hash~$Pointer$?compress~$Pointer$?cert~$Pointer$?sid_ctx_length~UINT?sid_ctx~ARRAY#_32_~UCHAR#?session~$Pointer$?verify_mode~INT?verify_depth~INT?verify_callback~$Pointer$?info_callback~$Pointer$?error~INT?error_code~INT?ctx~$Pointer$?debug~INT?verify_result~LONG?ex_data~~CRYPTO_EX_DATA?client_CA~$Pointer$?references~INT?options~ULONG?mode~ULONG?first_packet~INT?client_version~INT#~packet| 72)))
+ (let (($x11452 (and $x73 $x2547)))
+ (not $x11452)))))
+(check-sat)
diff --git a/test/regress/regress1/sets/proj-issue164.smt2 b/test/regress/regress1/sets/proj-issue164.smt2
new file mode 100644
index 000000000..5e343156e
--- /dev/null
+++ b/test/regress/regress1/sets/proj-issue164.smt2
@@ -0,0 +1,10 @@
+(set-logic ALL)
+(set-info :status sat)
+(declare-fun b () (Set String))
+(declare-fun c () (Set (Tuple Int Int)))
+(declare-fun d () (Set (Tuple Int Int)))
+(declare-fun e () Int)
+(assert (distinct c (set.insert (tuple 0 0) (set.singleton (tuple 1 1)))))
+(assert (distinct d (rel.tclosure c)))
+(assert (distinct e (set.card b)))
+(check-sat)
diff --git a/test/regress/regress1/sets/proj-issue178.smt2 b/test/regress/regress1/sets/proj-issue178.smt2
new file mode 100644
index 000000000..2b95f43c9
--- /dev/null
+++ b/test/regress/regress1/sets/proj-issue178.smt2
@@ -0,0 +1,10 @@
+(set-logic ALL)
+(set-info :status sat)
+(set-option :sygus-inference true)
+(set-option :sets-infer-as-lemmas false)
+(declare-fun a () (Set Int))
+(declare-fun b () (Set Int))
+(declare-fun c () (Set Int))
+(declare-fun d () Int)
+(assert (> (set.card (set.minus a (set.inter (set.minus a b) (set.minus a c)))) d))
+(check-sat)
diff --git a/test/regress/regress1/sygus/proj-issue181.smt2 b/test/regress/regress1/sygus/proj-issue181.smt2
new file mode 100644
index 000000000..656d1e757
--- /dev/null
+++ b/test/regress/regress1/sygus/proj-issue181.smt2
@@ -0,0 +1,8 @@
+(set-logic ALL)
+(set-option :sygus-inference true)
+(set-info :status sat)
+(declare-fun a (Int) Int)
+(assert (exists ((b Int)) (distinct (a b) (- b 29))))
+(assert (distinct (a 0) (- 4)))
+(assert (= (a (- 99)) (- 107)))
+(check-sat)
diff --git a/test/regress/regress1/sygus/proj-issue183.smt2 b/test/regress/regress1/sygus/proj-issue183.smt2
new file mode 100644
index 000000000..e50e035f3
--- /dev/null
+++ b/test/regress/regress1/sygus/proj-issue183.smt2
@@ -0,0 +1,20 @@
+; COMMAND-LINE: --strings-exp
+; EXPECT: sat
+(set-logic ALL)
+(set-option :sygus-inference true)
+(set-info :status sat)
+(declare-fun a () String)
+(declare-fun b () String)
+(declare-const c String)
+(declare-const d String)
+(declare-fun g () Bool)
+(declare-fun e () Bool)
+(declare-fun f () String)
+(assert (str.in_re (str.substr a 0 (str.len (str.substr a 0 (str.len (str.substr a 0 (str.len c)))))) (re.* (re.++ (str.to_re "") (re.* (str.to_re "aa"))))))
+(assert (str.in_re (str.substr b 0 (str.len d)) (re.* (re.++ (re.* (str.to_re "")) (str.to_re "bb")))))
+(assert (= 4 (str.len d)))
+(assert (not (= (str.substr a 0 (str.len c)) d)))
+(assert (= g (not (= "file" (str.substr a (str.len c) (str.len f))))))
+(assert (= e (not g)))
+(assert e)
+(check-sat)
diff --git a/test/regress/regress1/sygus/proj-issue185.smt2 b/test/regress/regress1/sygus/proj-issue185.smt2
new file mode 100644
index 000000000..a3e4b8205
--- /dev/null
+++ b/test/regress/regress1/sygus/proj-issue185.smt2
@@ -0,0 +1,12 @@
+; COMMAND-LINE: -q
+; EXPECT: unsat
+(set-logic ALL)
+(set-option :sygus-inference true)
+(set-info :status unsat)
+(declare-codatatypes ((a 0)) (((b (c Int) (d a)))))
+(declare-fun e () a)
+(declare-fun f () a)
+(assert (= e (b 0 (b 0 e))))
+(assert (distinct f (b 0 f)))
+(assert (not (distinct e f)))
+(check-sat)
diff --git a/test/regress/regress2/bv_to_int2.smt2 b/test/regress/regress2/bv_to_int2.smt2
index 424e95b27..b9c27c6b8 100644
--- a/test/regress/regress2/bv_to_int2.smt2
+++ b/test/regress/regress2/bv_to_int2.smt2
@@ -1,4 +1,5 @@
; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1
; EXPECT: sat
(set-logic QF_BV)
(declare-fun a () (_ BitVec 8))
diff --git a/test/regress/regress2/bv_to_int_ashr.smt2 b/test/regress/regress2/bv_to_int_ashr.smt2
index 0c6768546..1f5df2c31 100644
--- a/test/regress/regress2/bv_to_int_ashr.smt2
+++ b/test/regress/regress2/bv_to_int_ashr.smt2
@@ -1,4 +1,5 @@
; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1
; EXPECT: unsat
(set-logic QF_BV)
(declare-fun a () (_ BitVec 8))
diff --git a/test/regress/regress2/bv_to_int_bitwise.smt2 b/test/regress/regress2/bv_to_int_bitwise.smt2
index 23624e12c..4dc37a94c 100644
--- a/test/regress/regress2/bv_to_int_bitwise.smt2
+++ b/test/regress/regress2/bv_to_int_bitwise.smt2
@@ -1,8 +1,10 @@
-; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
-; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=5
-; COMMAND-LINE: --solve-bv-as-int=iand --iand-mode=value
-; COMMAND-LINE: --solve-bv-as-int=iand --iand-mode=sum
-; COMMAND-LINE: --solve-bv-as-int=bv
+; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1 --no-check-unsat-cores
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1 --no-check-unsat-cores
+; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=5 --no-check-unsat-cores
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=5 --no-check-unsat-cores
+; COMMAND-LINE: --solve-bv-as-int=iand --iand-mode=value --no-check-unsat-cores
+; COMMAND-LINE: --solve-bv-as-int=iand --iand-mode=sum --no-check-unsat-cores
+; COMMAND-LINE: --solve-bv-as-int=bv --no-check-unsat-cores
; EXPECT: unsat
(set-logic QF_BV)
(declare-fun s () (_ BitVec 4))
diff --git a/test/regress/regress2/bv_to_int_bvmul1.smt2 b/test/regress/regress2/bv_to_int_bvmul1.smt2
index 232959f33..bf6f2cfc4 100644
--- a/test/regress/regress2/bv_to_int_bvmul1.smt2
+++ b/test/regress/regress2/bv_to_int_bvmul1.smt2
@@ -1,4 +1,5 @@
; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1
; EXPECT: sat
(set-logic QF_BV)
(declare-fun a () (_ BitVec 8))
diff --git a/test/regress/regress2/bv_to_int_bvuf_to_intuf_smtlib.smt2 b/test/regress/regress2/bv_to_int_bvuf_to_intuf_smtlib.smt2
index babf9af32..2ecd0fe6c 100644
--- a/test/regress/regress2/bv_to_int_bvuf_to_intuf_smtlib.smt2
+++ b/test/regress/regress2/bv_to_int_bvuf_to_intuf_smtlib.smt2
@@ -1,4 +1,5 @@
-;COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1 --no-produce-unsat-cores
+;COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1 --no-check-unsat-cores
+;COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1 --no-check-unsat-cores
;EXPECT: unsat
(set-logic QF_UFBV)
(declare-fun z$n0s32 () (_ BitVec 32))
diff --git a/test/regress/regress2/bv_to_int_inc1.smt2 b/test/regress/regress2/bv_to_int_inc1.smt2
index 4b22c8ed8..28fb86f76 100644
--- a/test/regress/regress2/bv_to_int_inc1.smt2
+++ b/test/regress/regress2/bv_to_int_inc1.smt2
@@ -1,4 +1,5 @@
; COMMAND-LINE: --incremental --solve-bv-as-int=sum
+; COMMAND-LINE: --incremental --solve-bv-as-int=bitwise
; COMMAND-LINE: --incremental --solve-bv-as-int=iand
; COMMAND-LINE: --incremental --solve-bv-as-int=bv
; EXPECT sat
diff --git a/test/regress/regress2/bv_to_int_mask_array_1.smt2 b/test/regress/regress2/bv_to_int_mask_array_1.smt2
index 3b55c035d..c12138091 100644
--- a/test/regress/regress2/bv_to_int_mask_array_1.smt2
+++ b/test/regress/regress2/bv_to_int_mask_array_1.smt2
@@ -1,5 +1,6 @@
-; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
-; COMMAND-LINE: --solve-bv-as-int=iand --iand-mode=value
+; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1 --no-check-unsat-cores
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1 --no-check-unsat-cores
+; COMMAND-LINE: --solve-bv-as-int=iand --iand-mode=value --no-check-unsat-cores
; COMMAND-LINE: --solve-bv-as-int=iand --iand-mode=sum --no-check-unsat-cores
; COMMAND-LINE: --solve-bv-as-int=bv --no-check-unsat-cores
; EXPECT: unsat
diff --git a/test/regress/regress2/bv_to_int_mask_array_2.smt2 b/test/regress/regress2/bv_to_int_mask_array_2.smt2
index edcc14149..17a113f85 100644
--- a/test/regress/regress2/bv_to_int_mask_array_2.smt2
+++ b/test/regress/regress2/bv_to_int_mask_array_2.smt2
@@ -1,4 +1,5 @@
; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1
; COMMAND-LINE: --solve-bv-as-int=iand --iand-mode=value
; COMMAND-LINE: --solve-bv-as-int=iand --iand-mode=sum
; COMMAND-LINE: --solve-bv-as-int=bv
diff --git a/test/regress/regress2/bv_to_int_mask_array_3.smt2 b/test/regress/regress2/bv_to_int_mask_array_3.smt2
index 74e5ca95a..2b411209d 100644
--- a/test/regress/regress2/bv_to_int_mask_array_3.smt2
+++ b/test/regress/regress2/bv_to_int_mask_array_3.smt2
@@ -1,4 +1,5 @@
; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1
; EXPECT: sat
(set-logic ALL)
(declare-fun A () (Array (_ BitVec 4) (_ BitVec 4)))
diff --git a/test/regress/regress2/bv_to_int_quantifiers_bvand.smt2 b/test/regress/regress2/bv_to_int_quantifiers_bvand.smt2
new file mode 100644
index 000000000..d454ad630
--- /dev/null
+++ b/test/regress/regress2/bv_to_int_quantifiers_bvand.smt2
@@ -0,0 +1,9 @@
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1 --no-check-unsat-cores
+; EXPECT: (error "Error in option parsing: --solve-bv-as-int=bitwise does not support quantifiers")
+; EXIT: 1
+(set-logic BV)
+(declare-const x (_ BitVec 8))
+(assert (forall ((y (_ BitVec 8)))
+ (distinct #b00000000
+ (bvand x y))))
+(check-sat)
diff --git a/test/regress/regress2/bv_to_int_shifts.smt2 b/test/regress/regress2/bv_to_int_shifts.smt2
index bcc31c38c..173f1a552 100644
--- a/test/regress/regress2/bv_to_int_shifts.smt2
+++ b/test/regress/regress2/bv_to_int_shifts.smt2
@@ -1,4 +1,5 @@
; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1
; EXPECT: sat
(set-logic QF_BV)
(declare-fun s () (_ BitVec 4))
diff --git a/test/regress/regress2/strings/strings-alpha-card-129.smt2 b/test/regress/regress2/strings/strings-alpha-card-129.smt2
deleted file mode 100644
index c0b4ae0a2..000000000
--- a/test/regress/regress2/strings/strings-alpha-card-129.smt2
+++ /dev/null
@@ -1,393 +0,0 @@
-; COMMAND-LINE: --strings-alpha-card=128 --simplification=none
-; EXPECT: unsat
-(set-logic QF_SLIA)
-(declare-fun s1 () String)
-(assert (= (str.len s1) 1))
-(declare-fun s2 () String)
-(assert (= (str.len s2) 1))
-(declare-fun s3 () String)
-(assert (= (str.len s3) 1))
-(declare-fun s4 () String)
-(assert (= (str.len s4) 1))
-(declare-fun s5 () String)
-(assert (= (str.len s5) 1))
-(declare-fun s6 () String)
-(assert (= (str.len s6) 1))
-(declare-fun s7 () String)
-(assert (= (str.len s7) 1))
-(declare-fun s8 () String)
-(assert (= (str.len s8) 1))
-(declare-fun s9 () String)
-(assert (= (str.len s9) 1))
-(declare-fun s10 () String)
-(assert (= (str.len s10) 1))
-(declare-fun s11 () String)
-(assert (= (str.len s11) 1))
-(declare-fun s12 () String)
-(assert (= (str.len s12) 1))
-(declare-fun s13 () String)
-(assert (= (str.len s13) 1))
-(declare-fun s14 () String)
-(assert (= (str.len s14) 1))
-(declare-fun s15 () String)
-(assert (= (str.len s15) 1))
-(declare-fun s16 () String)
-(assert (= (str.len s16) 1))
-(declare-fun s17 () String)
-(assert (= (str.len s17) 1))
-(declare-fun s18 () String)
-(assert (= (str.len s18) 1))
-(declare-fun s19 () String)
-(assert (= (str.len s19) 1))
-(declare-fun s20 () String)
-(assert (= (str.len s20) 1))
-(declare-fun s21 () String)
-(assert (= (str.len s21) 1))
-(declare-fun s22 () String)
-(assert (= (str.len s22) 1))
-(declare-fun s23 () String)
-(assert (= (str.len s23) 1))
-(declare-fun s24 () String)
-(assert (= (str.len s24) 1))
-(declare-fun s25 () String)
-(assert (= (str.len s25) 1))
-(declare-fun s26 () String)
-(assert (= (str.len s26) 1))
-(declare-fun s27 () String)
-(assert (= (str.len s27) 1))
-(declare-fun s28 () String)
-(assert (= (str.len s28) 1))
-(declare-fun s29 () String)
-(assert (= (str.len s29) 1))
-(declare-fun s30 () String)
-(assert (= (str.len s30) 1))
-(declare-fun s31 () String)
-(assert (= (str.len s31) 1))
-(declare-fun s32 () String)
-(assert (= (str.len s32) 1))
-(declare-fun s33 () String)
-(assert (= (str.len s33) 1))
-(declare-fun s34 () String)
-(assert (= (str.len s34) 1))
-(declare-fun s35 () String)
-(assert (= (str.len s35) 1))
-(declare-fun s36 () String)
-(assert (= (str.len s36) 1))
-(declare-fun s37 () String)
-(assert (= (str.len s37) 1))
-(declare-fun s38 () String)
-(assert (= (str.len s38) 1))
-(declare-fun s39 () String)
-(assert (= (str.len s39) 1))
-(declare-fun s40 () String)
-(assert (= (str.len s40) 1))
-(declare-fun s41 () String)
-(assert (= (str.len s41) 1))
-(declare-fun s42 () String)
-(assert (= (str.len s42) 1))
-(declare-fun s43 () String)
-(assert (= (str.len s43) 1))
-(declare-fun s44 () String)
-(assert (= (str.len s44) 1))
-(declare-fun s45 () String)
-(assert (= (str.len s45) 1))
-(declare-fun s46 () String)
-(assert (= (str.len s46) 1))
-(declare-fun s47 () String)
-(assert (= (str.len s47) 1))
-(declare-fun s48 () String)
-(assert (= (str.len s48) 1))
-(declare-fun s49 () String)
-(assert (= (str.len s49) 1))
-(declare-fun s50 () String)
-(assert (= (str.len s50) 1))
-(declare-fun s51 () String)
-(assert (= (str.len s51) 1))
-(declare-fun s52 () String)
-(assert (= (str.len s52) 1))
-(declare-fun s53 () String)
-(assert (= (str.len s53) 1))
-(declare-fun s54 () String)
-(assert (= (str.len s54) 1))
-(declare-fun s55 () String)
-(assert (= (str.len s55) 1))
-(declare-fun s56 () String)
-(assert (= (str.len s56) 1))
-(declare-fun s57 () String)
-(assert (= (str.len s57) 1))
-(declare-fun s58 () String)
-(assert (= (str.len s58) 1))
-(declare-fun s59 () String)
-(assert (= (str.len s59) 1))
-(declare-fun s60 () String)
-(assert (= (str.len s60) 1))
-(declare-fun s61 () String)
-(assert (= (str.len s61) 1))
-(declare-fun s62 () String)
-(assert (= (str.len s62) 1))
-(declare-fun s63 () String)
-(assert (= (str.len s63) 1))
-(declare-fun s64 () String)
-(assert (= (str.len s64) 1))
-(declare-fun s65 () String)
-(assert (= (str.len s65) 1))
-(declare-fun s66 () String)
-(assert (= (str.len s66) 1))
-(declare-fun s67 () String)
-(assert (= (str.len s67) 1))
-(declare-fun s68 () String)
-(assert (= (str.len s68) 1))
-(declare-fun s69 () String)
-(assert (= (str.len s69) 1))
-(declare-fun s70 () String)
-(assert (= (str.len s70) 1))
-(declare-fun s71 () String)
-(assert (= (str.len s71) 1))
-(declare-fun s72 () String)
-(assert (= (str.len s72) 1))
-(declare-fun s73 () String)
-(assert (= (str.len s73) 1))
-(declare-fun s74 () String)
-(assert (= (str.len s74) 1))
-(declare-fun s75 () String)
-(assert (= (str.len s75) 1))
-(declare-fun s76 () String)
-(assert (= (str.len s76) 1))
-(declare-fun s77 () String)
-(assert (= (str.len s77) 1))
-(declare-fun s78 () String)
-(assert (= (str.len s78) 1))
-(declare-fun s79 () String)
-(assert (= (str.len s79) 1))
-(declare-fun s80 () String)
-(assert (= (str.len s80) 1))
-(declare-fun s81 () String)
-(assert (= (str.len s81) 1))
-(declare-fun s82 () String)
-(assert (= (str.len s82) 1))
-(declare-fun s83 () String)
-(assert (= (str.len s83) 1))
-(declare-fun s84 () String)
-(assert (= (str.len s84) 1))
-(declare-fun s85 () String)
-(assert (= (str.len s85) 1))
-(declare-fun s86 () String)
-(assert (= (str.len s86) 1))
-(declare-fun s87 () String)
-(assert (= (str.len s87) 1))
-(declare-fun s88 () String)
-(assert (= (str.len s88) 1))
-(declare-fun s89 () String)
-(assert (= (str.len s89) 1))
-(declare-fun s90 () String)
-(assert (= (str.len s90) 1))
-(declare-fun s91 () String)
-(assert (= (str.len s91) 1))
-(declare-fun s92 () String)
-(assert (= (str.len s92) 1))
-(declare-fun s93 () String)
-(assert (= (str.len s93) 1))
-(declare-fun s94 () String)
-(assert (= (str.len s94) 1))
-(declare-fun s95 () String)
-(assert (= (str.len s95) 1))
-(declare-fun s96 () String)
-(assert (= (str.len s96) 1))
-(declare-fun s97 () String)
-(assert (= (str.len s97) 1))
-(declare-fun s98 () String)
-(assert (= (str.len s98) 1))
-(declare-fun s99 () String)
-(assert (= (str.len s99) 1))
-(declare-fun s100 () String)
-(assert (= (str.len s100) 1))
-(declare-fun s101 () String)
-(assert (= (str.len s101) 1))
-(declare-fun s102 () String)
-(assert (= (str.len s102) 1))
-(declare-fun s103 () String)
-(assert (= (str.len s103) 1))
-(declare-fun s104 () String)
-(assert (= (str.len s104) 1))
-(declare-fun s105 () String)
-(assert (= (str.len s105) 1))
-(declare-fun s106 () String)
-(assert (= (str.len s106) 1))
-(declare-fun s107 () String)
-(assert (= (str.len s107) 1))
-(declare-fun s108 () String)
-(assert (= (str.len s108) 1))
-(declare-fun s109 () String)
-(assert (= (str.len s109) 1))
-(declare-fun s110 () String)
-(assert (= (str.len s110) 1))
-(declare-fun s111 () String)
-(assert (= (str.len s111) 1))
-(declare-fun s112 () String)
-(assert (= (str.len s112) 1))
-(declare-fun s113 () String)
-(assert (= (str.len s113) 1))
-(declare-fun s114 () String)
-(assert (= (str.len s114) 1))
-(declare-fun s115 () String)
-(assert (= (str.len s115) 1))
-(declare-fun s116 () String)
-(assert (= (str.len s116) 1))
-(declare-fun s117 () String)
-(assert (= (str.len s117) 1))
-(declare-fun s118 () String)
-(assert (= (str.len s118) 1))
-(declare-fun s119 () String)
-(assert (= (str.len s119) 1))
-(declare-fun s120 () String)
-(assert (= (str.len s120) 1))
-(declare-fun s121 () String)
-(assert (= (str.len s121) 1))
-(declare-fun s122 () String)
-(assert (= (str.len s122) 1))
-(declare-fun s123 () String)
-(assert (= (str.len s123) 1))
-(declare-fun s124 () String)
-(assert (= (str.len s124) 1))
-(declare-fun s125 () String)
-(assert (= (str.len s125) 1))
-(declare-fun s126 () String)
-(assert (= (str.len s126) 1))
-(declare-fun s127 () String)
-(assert (= (str.len s127) 1))
-(declare-fun s128 () String)
-(assert (= (str.len s128) 1))
-(declare-fun s129 () String)
-(assert (= (str.len s129) 1))
-(assert (distinct
-s1
-s2
-s3
-s4
-s5
-s6
-s7
-s8
-s9
-s10
-s11
-s12
-s13
-s14
-s15
-s16
-s17
-s18
-s19
-s20
-s21
-s22
-s23
-s24
-s25
-s26
-s27
-s28
-s29
-s30
-s31
-s32
-s33
-s34
-s35
-s36
-s37
-s38
-s39
-s40
-s41
-s42
-s43
-s44
-s45
-s46
-s47
-s48
-s49
-s50
-s51
-s52
-s53
-s54
-s55
-s56
-s57
-s58
-s59
-s60
-s61
-s62
-s63
-s64
-s65
-s66
-s67
-s68
-s69
-s70
-s71
-s72
-s73
-s74
-s75
-s76
-s77
-s78
-s79
-s80
-s81
-s82
-s83
-s84
-s85
-s86
-s87
-s88
-s89
-s90
-s91
-s92
-s93
-s94
-s95
-s96
-s97
-s98
-s99
-s100
-s101
-s102
-s103
-s104
-s105
-s106
-s107
-s108
-s109
-s110
-s111
-s112
-s113
-s114
-s115
-s116
-s117
-s118
-s119
-s120
-s121
-s122
-s123
-s124
-s125
-s126
-s127
-s128
-s129
-))
-(check-sat)
diff --git a/test/regress/regress2/strings/strings-alpha-card-65.smt2 b/test/regress/regress2/strings/strings-alpha-card-65.smt2
new file mode 100644
index 000000000..82ab06ea9
--- /dev/null
+++ b/test/regress/regress2/strings/strings-alpha-card-65.smt2
@@ -0,0 +1,201 @@
+; COMMAND-LINE: --strings-alpha-card=64 --simplification=none
+; EXPECT: unsat
+(set-logic QF_SLIA)
+(declare-fun s1 () String)
+(assert (= (str.len s1) 1))
+(declare-fun s2 () String)
+(assert (= (str.len s2) 1))
+(declare-fun s3 () String)
+(assert (= (str.len s3) 1))
+(declare-fun s4 () String)
+(assert (= (str.len s4) 1))
+(declare-fun s5 () String)
+(assert (= (str.len s5) 1))
+(declare-fun s6 () String)
+(assert (= (str.len s6) 1))
+(declare-fun s7 () String)
+(assert (= (str.len s7) 1))
+(declare-fun s8 () String)
+(assert (= (str.len s8) 1))
+(declare-fun s9 () String)
+(assert (= (str.len s9) 1))
+(declare-fun s10 () String)
+(assert (= (str.len s10) 1))
+(declare-fun s11 () String)
+(assert (= (str.len s11) 1))
+(declare-fun s12 () String)
+(assert (= (str.len s12) 1))
+(declare-fun s13 () String)
+(assert (= (str.len s13) 1))
+(declare-fun s14 () String)
+(assert (= (str.len s14) 1))
+(declare-fun s15 () String)
+(assert (= (str.len s15) 1))
+(declare-fun s16 () String)
+(assert (= (str.len s16) 1))
+(declare-fun s17 () String)
+(assert (= (str.len s17) 1))
+(declare-fun s18 () String)
+(assert (= (str.len s18) 1))
+(declare-fun s19 () String)
+(assert (= (str.len s19) 1))
+(declare-fun s20 () String)
+(assert (= (str.len s20) 1))
+(declare-fun s21 () String)
+(assert (= (str.len s21) 1))
+(declare-fun s22 () String)
+(assert (= (str.len s22) 1))
+(declare-fun s23 () String)
+(assert (= (str.len s23) 1))
+(declare-fun s24 () String)
+(assert (= (str.len s24) 1))
+(declare-fun s25 () String)
+(assert (= (str.len s25) 1))
+(declare-fun s26 () String)
+(assert (= (str.len s26) 1))
+(declare-fun s27 () String)
+(assert (= (str.len s27) 1))
+(declare-fun s28 () String)
+(assert (= (str.len s28) 1))
+(declare-fun s29 () String)
+(assert (= (str.len s29) 1))
+(declare-fun s30 () String)
+(assert (= (str.len s30) 1))
+(declare-fun s31 () String)
+(assert (= (str.len s31) 1))
+(declare-fun s32 () String)
+(assert (= (str.len s32) 1))
+(declare-fun s33 () String)
+(assert (= (str.len s33) 1))
+(declare-fun s34 () String)
+(assert (= (str.len s34) 1))
+(declare-fun s35 () String)
+(assert (= (str.len s35) 1))
+(declare-fun s36 () String)
+(assert (= (str.len s36) 1))
+(declare-fun s37 () String)
+(assert (= (str.len s37) 1))
+(declare-fun s38 () String)
+(assert (= (str.len s38) 1))
+(declare-fun s39 () String)
+(assert (= (str.len s39) 1))
+(declare-fun s40 () String)
+(assert (= (str.len s40) 1))
+(declare-fun s41 () String)
+(assert (= (str.len s41) 1))
+(declare-fun s42 () String)
+(assert (= (str.len s42) 1))
+(declare-fun s43 () String)
+(assert (= (str.len s43) 1))
+(declare-fun s44 () String)
+(assert (= (str.len s44) 1))
+(declare-fun s45 () String)
+(assert (= (str.len s45) 1))
+(declare-fun s46 () String)
+(assert (= (str.len s46) 1))
+(declare-fun s47 () String)
+(assert (= (str.len s47) 1))
+(declare-fun s48 () String)
+(assert (= (str.len s48) 1))
+(declare-fun s49 () String)
+(assert (= (str.len s49) 1))
+(declare-fun s50 () String)
+(assert (= (str.len s50) 1))
+(declare-fun s51 () String)
+(assert (= (str.len s51) 1))
+(declare-fun s52 () String)
+(assert (= (str.len s52) 1))
+(declare-fun s53 () String)
+(assert (= (str.len s53) 1))
+(declare-fun s54 () String)
+(assert (= (str.len s54) 1))
+(declare-fun s55 () String)
+(assert (= (str.len s55) 1))
+(declare-fun s56 () String)
+(assert (= (str.len s56) 1))
+(declare-fun s57 () String)
+(assert (= (str.len s57) 1))
+(declare-fun s58 () String)
+(assert (= (str.len s58) 1))
+(declare-fun s59 () String)
+(assert (= (str.len s59) 1))
+(declare-fun s60 () String)
+(assert (= (str.len s60) 1))
+(declare-fun s61 () String)
+(assert (= (str.len s61) 1))
+(declare-fun s62 () String)
+(assert (= (str.len s62) 1))
+(declare-fun s63 () String)
+(assert (= (str.len s63) 1))
+(declare-fun s64 () String)
+(assert (= (str.len s64) 1))
+(declare-fun s65 () String)
+(assert (= (str.len s65) 1))
+(assert (distinct
+s1
+s2
+s3
+s4
+s5
+s6
+s7
+s8
+s9
+s10
+s11
+s12
+s13
+s14
+s15
+s16
+s17
+s18
+s19
+s20
+s21
+s22
+s23
+s24
+s25
+s26
+s27
+s28
+s29
+s30
+s31
+s32
+s33
+s34
+s35
+s36
+s37
+s38
+s39
+s40
+s41
+s42
+s43
+s44
+s45
+s46
+s47
+s48
+s49
+s50
+s51
+s52
+s53
+s54
+s55
+s56
+s57
+s58
+s59
+s60
+s61
+s62
+s63
+s64
+s65
+))
+(check-sat)
diff --git a/test/regress/regress2/sygus/multi-udiv.sy b/test/regress/regress2/sygus/multi-udiv.sy
index d9deb28a3..65e5d428f 100644
--- a/test/regress/regress2/sygus/multi-udiv.sy
+++ b/test/regress/regress2/sygus/multi-udiv.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --lang=sygus2 --sygus-out=status
+; COMMAND-LINE: --lang=sygus2 --sygus-out=status --sygus-active-gen=enum
(set-logic BV)
(define-fun hd05 ((x (_ BitVec 32))) (_ BitVec 32) (bvor x (bvsub x #x00000001)))
diff --git a/test/regress/regress2/sygus/sets-fun-test.sy b/test/regress/regress2/sygus/sets-fun-test.sy
index 43a8b36a9..23abc5c7e 100644
--- a/test/regress/regress2/sygus/sets-fun-test.sy
+++ b/test/regress/regress2/sygus/sets-fun-test.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --lang=sygus2 --sygus-out=status
+; COMMAND-LINE: --lang=sygus2 --sygus-out=status --sygus-active-gen=enum
(set-logic ALL)
(synth-fun f ((x Int)) (Set Int))
diff --git a/test/regress/regress2/sygus/three.sy b/test/regress/regress2/sygus/three.sy
index 239f7f498..9bed1e667 100644
--- a/test/regress/regress2/sygus/three.sy
+++ b/test/regress/regress2/sygus/three.sy
@@ -1,5 +1,5 @@
; EXPECT: unsat
-; COMMAND-LINE: --lang=sygus2 --sygus-out=status
+; COMMAND-LINE: --lang=sygus2 --sygus-out=status --sygus-active-gen=enum
(set-logic NIA)
diff --git a/test/regress/regress3/bv_to_int_and_or.smt2 b/test/regress/regress3/bv_to_int_and_or.smt2
index 2c728417d..8ae10a04f 100644
--- a/test/regress/regress3/bv_to_int_and_or.smt2
+++ b/test/regress/regress3/bv_to_int_and_or.smt2
@@ -1,5 +1,7 @@
-; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1
-; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=2
+; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=1 --no-check-unsat-cores --no-check-proofs
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=1 --no-check-unsat-cores --no-check-proofs
+; COMMAND-LINE: --solve-bv-as-int=sum --bvand-integer-granularity=2 --no-check-unsat-cores --no-check-proofs
+; COMMAND-LINE: --solve-bv-as-int=bitwise --bvand-integer-granularity=2 --no-check-unsat-cores --no-check-proofs
; EXPECT: unsat
(set-logic QF_BV)
(declare-fun a () (_ BitVec 4))
diff --git a/test/regress/regress3/bv_to_int_bench_9839.smt2.minimized.smt2 b/test/regress/regress3/bv_to_int_bench_9839.smt2.minimized.smt2
index aeacda35e..3a0320119 100644
--- a/test/regress/regress3/bv_to_int_bench_9839.smt2.minimized.smt2
+++ b/test/regress/regress3/bv_to_int_bench_9839.smt2.minimized.smt2
@@ -1,5 +1,6 @@
-; COMMAND-LINE: --solve-bv-as-int=bv
-; COMMAND-LINE: --bvand-integer-granularity=1 --solve-bv-as-int=sum
+; COMMAND-LINE: --solve-bv-as-int=bv
+; COMMAND-LINE: --bvand-integer-granularity=1 --solve-bv-as-int=sum
+; COMMAND-LINE: --bvand-integer-granularity=1 --solve-bv-as-int=bitwise
; EXPECT: sat
(set-logic QF_BV)
(declare-fun _substvar_1171_ () (_ BitVec 32))
diff --git a/test/regress/regress3/bv_to_int_check_bvsgt_bvlshr0_4bit.smt2.minimized.smt2 b/test/regress/regress3/bv_to_int_check_bvsgt_bvlshr0_4bit.smt2.minimized.smt2
index c4988e3c6..3c50acc1c 100644
--- a/test/regress/regress3/bv_to_int_check_bvsgt_bvlshr0_4bit.smt2.minimized.smt2
+++ b/test/regress/regress3/bv_to_int_check_bvsgt_bvlshr0_4bit.smt2.minimized.smt2
@@ -1,6 +1,6 @@
-; COMMAND-LINE: --solve-bv-as-int=bv
-; COMMAND-LINE: --solve-bv-as-int=sum
-; COMMAND-LINE: --solve-bv-as-int=iand --iand-mode=sum
+; COMMAND-LINE: --solve-bv-as-int=bv
+; COMMAND-LINE: --solve-bv-as-int=sum
+; COMMAND-LINE: --solve-bv-as-int=iand --iand-mode=sum
; COMMAND-LINE: --solve-bv-as-int=iand --iand-mode=bitwise
; COMMAND-LINE: --solve-bv-as-int=iand --iand-mode=value
; EXPECT: unsat
diff --git a/test/regress/regress3/bv_to_int_input_mouser_detect.c.smt2.minimized.smt2 b/test/regress/regress3/bv_to_int_input_mouser_detect.c.smt2.minimized.smt2
index dd7e11a50..b37dc371d 100644
--- a/test/regress/regress3/bv_to_int_input_mouser_detect.c.smt2.minimized.smt2
+++ b/test/regress/regress3/bv_to_int_input_mouser_detect.c.smt2.minimized.smt2
@@ -1,5 +1,5 @@
; COMMAND-LINE: --solve-bv-as-int=bv --no-check-models
-; COMMAND-LINE: --bvand-integer-granularity=1 --solve-bv-as-int=sum --full-saturate-quant --cegqi-all --no-check-models
+; COMMAND-LINE: --bvand-integer-granularity=1 --solve-bv-as-int=sum --full-saturate-quant --cegqi-all --no-check-models
;EXPECT: sat
(set-logic BV)
(assert (exists ((c__detect__main__1__i_36_C (_ BitVec 32))) (bvslt ((_ sign_extend 32) c__detect__main__1__i_36_C) (_ bv0 64))))
diff --git a/test/unit/api/cpp/datatype_api_black.cpp b/test/unit/api/cpp/datatype_api_black.cpp
index 745abc17c..fecf228a5 100644
--- a/test/unit/api/cpp/datatype_api_black.cpp
+++ b/test/unit/api/cpp/datatype_api_black.cpp
@@ -231,6 +231,7 @@ TEST_F(TestApiBlackDatatype, datatypeNames)
dtypeSpec.addConstructor(nil);
Sort dtypeSort = d_solver.mkDatatypeSort(dtypeSpec);
Datatype dt = dtypeSort.getDatatype();
+ ASSERT_THROW(dt.getParameters(), CVC5ApiException);
ASSERT_EQ(dt.getName(), std::string("list"));
ASSERT_NO_THROW(dt.getConstructor("nil"));
ASSERT_NO_THROW(dt["cons"]);
@@ -274,6 +275,8 @@ TEST_F(TestApiBlackDatatype, parametricDatatype)
Sort pairType = d_solver.mkDatatypeSort(pairSpec);
ASSERT_TRUE(pairType.getDatatype().isParametric());
+ std::vector<Sort> dparams = pairType.getDatatype().getParameters();
+ ASSERT_TRUE(dparams[0] == t1 && dparams[1] == t2);
v.clear();
v.push_back(d_solver.getIntegerSort());
@@ -576,12 +579,16 @@ TEST_F(TestApiBlackDatatype, datatypeSpecializedCons)
iargs.push_back(isort);
Sort listInt = dtsorts[0].instantiate(iargs);
+ std::vector<Sort> liparams = listInt.getDatatype().getParameters();
+ // the parameter of the datatype is not instantiated
+ ASSERT_TRUE(liparams.size() == 1 && liparams[0] == x);
+
Term testConsTerm;
// get the specialized constructor term for list[Int]
- ASSERT_NO_THROW(testConsTerm = nilc.getSpecializedConstructorTerm(listInt));
+ ASSERT_NO_THROW(testConsTerm = nilc.getInstantiatedConstructorTerm(listInt));
ASSERT_NE(testConsTerm, nilc.getConstructorTerm());
// error to get the specialized constructor term for Int
- ASSERT_THROW(nilc.getSpecializedConstructorTerm(isort), CVC5ApiException);
+ ASSERT_THROW(nilc.getInstantiatedConstructorTerm(isort), CVC5ApiException);
}
} // namespace test
} // namespace cvc5
diff --git a/test/unit/api/cpp/solver_black.cpp b/test/unit/api/cpp/solver_black.cpp
index 36b669bca..b17054637 100644
--- a/test/unit/api/cpp/solver_black.cpp
+++ b/test/unit/api/cpp/solver_black.cpp
@@ -929,22 +929,35 @@ TEST_F(TestApiBlackSolver, mkConstArray)
TEST_F(TestApiBlackSolver, declareDatatype)
{
+ DatatypeConstructorDecl lin = d_solver.mkDatatypeConstructorDecl("lin");
+ std::vector<DatatypeConstructorDecl> ctors0 = {lin};
+ ASSERT_NO_THROW(d_solver.declareDatatype(std::string(""), ctors0));
+
DatatypeConstructorDecl nil = d_solver.mkDatatypeConstructorDecl("nil");
std::vector<DatatypeConstructorDecl> ctors1 = {nil};
ASSERT_NO_THROW(d_solver.declareDatatype(std::string("a"), ctors1));
+
DatatypeConstructorDecl cons = d_solver.mkDatatypeConstructorDecl("cons");
DatatypeConstructorDecl nil2 = d_solver.mkDatatypeConstructorDecl("nil");
std::vector<DatatypeConstructorDecl> ctors2 = {cons, nil2};
ASSERT_NO_THROW(d_solver.declareDatatype(std::string("b"), ctors2));
+
DatatypeConstructorDecl cons2 = d_solver.mkDatatypeConstructorDecl("cons");
DatatypeConstructorDecl nil3 = d_solver.mkDatatypeConstructorDecl("nil");
std::vector<DatatypeConstructorDecl> ctors3 = {cons2, nil3};
ASSERT_NO_THROW(d_solver.declareDatatype(std::string(""), ctors3));
+
+ // must have at least one constructor
std::vector<DatatypeConstructorDecl> ctors4;
ASSERT_THROW(d_solver.declareDatatype(std::string("c"), ctors4),
CVC5ApiException);
- ASSERT_THROW(d_solver.declareDatatype(std::string(""), ctors4),
+ // constructors may not be reused
+ DatatypeConstructorDecl ctor1 = d_solver.mkDatatypeConstructorDecl("_x21");
+ DatatypeConstructorDecl ctor2 = d_solver.mkDatatypeConstructorDecl("_x31");
+ Sort s3 = d_solver.declareDatatype(std::string("_x17"), {ctor1, ctor2});
+ ASSERT_THROW(d_solver.declareDatatype(std::string("_x86"), {ctor1, ctor2}),
CVC5ApiException);
+ // constructor belongs to different solver instance
Solver slv;
ASSERT_THROW(slv.declareDatatype(std::string("a"), ctors1), CVC5ApiException);
}
@@ -1443,13 +1456,16 @@ TEST_F(TestApiBlackSolver, getOptionInfo)
}
{
// mode option
- api::OptionInfo info = d_solver.getOptionInfo("output");
- EXPECT_EQ("output", info.name);
- EXPECT_EQ(std::vector<std::string>{}, info.aliases);
+ api::OptionInfo info = d_solver.getOptionInfo("simplification");
+ EXPECT_EQ("simplification", info.name);
+ EXPECT_EQ(std::vector<std::string>{"simplification-mode"}, info.aliases);
EXPECT_TRUE(std::holds_alternative<OptionInfo::ModeInfo>(info.valueInfo));
auto modeInfo = std::get<OptionInfo::ModeInfo>(info.valueInfo);
- EXPECT_EQ("none", modeInfo.defaultValue);
- EXPECT_EQ("none", modeInfo.currentValue);
+ EXPECT_EQ("batch", modeInfo.defaultValue);
+ EXPECT_EQ("batch", modeInfo.currentValue);
+ EXPECT_EQ(2, modeInfo.modes.size());
+ EXPECT_TRUE(std::find(modeInfo.modes.begin(), modeInfo.modes.end(), "batch")
+ != modeInfo.modes.end());
EXPECT_TRUE(std::find(modeInfo.modes.begin(), modeInfo.modes.end(), "none")
!= modeInfo.modes.end());
}
@@ -2639,5 +2655,152 @@ TEST_F(TestApiBlackSolver, issue5893)
ASSERT_NO_FATAL_FAILURE(distinct.getOp());
}
+TEST_F(TestApiBlackSolver, proj_issue373)
+{
+ Sort s1 = d_solver.getRealSort();
+
+ DatatypeConstructorDecl ctor13 = d_solver.mkDatatypeConstructorDecl("_x115");
+ ctor13.addSelector("_x109", s1);
+ Sort s4 = d_solver.declareDatatype("_x86", {ctor13});
+
+ Term t452 = d_solver.mkVar(s1, "_x281");
+ Term bvl = d_solver.mkTerm(d_solver.mkOp(VARIABLE_LIST), {t452});
+ Term acons =
+ d_solver.mkTerm(d_solver.mkOp(APPLY_CONSTRUCTOR),
+ {s4.getDatatype().getConstructorTerm("_x115"), t452});
+ // type exception
+ ASSERT_THROW(
+ d_solver.mkTerm(d_solver.mkOp(APPLY_CONSTRUCTOR), {bvl, acons, t452}),
+ CVC5ApiException);
+}
+
+TEST_F(TestApiBlackSolver, proj_issue378)
+{
+ DatatypeDecl dtdecl;
+ DatatypeConstructorDecl cdecl;
+
+ Sort s1 = d_solver.getBooleanSort();
+
+ dtdecl = d_solver.mkDatatypeDecl("_x0");
+ cdecl = d_solver.mkDatatypeConstructorDecl("_x6");
+ cdecl.addSelector("_x1", s1);
+ dtdecl.addConstructor(cdecl);
+ Sort s2 = d_solver.mkDatatypeSort(dtdecl);
+
+ dtdecl = d_solver.mkDatatypeDecl("_x36");
+ cdecl = d_solver.mkDatatypeConstructorDecl("_x42");
+ cdecl.addSelector("_x37", s1);
+ dtdecl.addConstructor(cdecl);
+ Sort s4 = d_solver.mkDatatypeSort(dtdecl);
+
+ Term t1 = d_solver.mkConst(s1, "_x53");
+ Term t4 = d_solver.mkConst(s4, "_x56");
+ Term t7 = d_solver.mkConst(s2, "_x58");
+
+ Sort sp = d_solver.mkParamSort("_x178");
+ dtdecl = d_solver.mkDatatypeDecl("_x176", sp);
+ cdecl = d_solver.mkDatatypeConstructorDecl("_x184");
+ cdecl.addSelector("_x180", s2);
+ dtdecl.addConstructor(cdecl);
+ cdecl = d_solver.mkDatatypeConstructorDecl("_x186");
+ cdecl.addSelector("_x185", sp);
+ dtdecl.addConstructor(cdecl);
+ Sort s7 = d_solver.mkDatatypeSort(dtdecl);
+ Sort s9 = s7.instantiate({s2});
+ Term t1507 = d_solver.mkTerm(
+ APPLY_CONSTRUCTOR, s9.getDatatype().getConstructorTerm("_x184"), t7);
+ ASSERT_NO_THROW(d_solver.mkTerm(
+ APPLY_UPDATER,
+ s9.getDatatype().getConstructor("_x186").getSelectorTerm("_x185"),
+ t1507,
+ t7));
+}
+
+TEST_F(TestApiBlackSolver, proj_issue379)
+{
+ Sort bsort = d_solver.getBooleanSort();
+ Sort psort = d_solver.mkParamSort("_x1");
+ DatatypeConstructorDecl cdecl;
+ DatatypeDecl dtdecl = d_solver.mkDatatypeDecl("x_0", psort);
+ cdecl = d_solver.mkDatatypeConstructorDecl("_x8");
+ cdecl.addSelector("_x7", bsort);
+ dtdecl.addConstructor(cdecl);
+ cdecl = d_solver.mkDatatypeConstructorDecl("_x6");
+ cdecl.addSelector("_x2", psort);
+ cdecl.addSelectorSelf("_x3");
+ cdecl.addSelector("_x4", psort);
+ cdecl.addSelector("_x5", bsort);
+ Sort s2 = d_solver.mkDatatypeSort(dtdecl);
+ Sort s6 = s2.instantiate({bsort});
+ Term t317 = d_solver.mkConst(bsort, "_x345");
+ Term t843 = d_solver.mkConst(s6, "_x346");
+ Term t879 = d_solver.mkTerm(APPLY_UPDATER,
+ t843.getSort()
+ .getDatatype()
+ .getConstructor("_x8")
+ .getSelector("_x7")
+ .getUpdaterTerm(),
+ t843,
+ t317);
+ ASSERT_EQ(t879.getSort(), s6);
+}
+
+TEST_F(TestApiBlackSolver, getDatatypeArity)
+{
+ DatatypeConstructorDecl ctor1 = d_solver.mkDatatypeConstructorDecl("_x21");
+ DatatypeConstructorDecl ctor2 = d_solver.mkDatatypeConstructorDecl("_x31");
+ Sort s3 = d_solver.declareDatatype(std::string("_x17"), {ctor1, ctor2});
+ ASSERT_EQ(s3.getDatatypeArity(), 0);
+}
+
+TEST_F(TestApiBlackSolver, proj_issue381)
+{
+ Sort s1 = d_solver.getBooleanSort();
+
+ Sort psort = d_solver.mkParamSort("_x9");
+ DatatypeDecl dtdecl = d_solver.mkDatatypeDecl("_x8", psort);
+ DatatypeConstructorDecl ctor = d_solver.mkDatatypeConstructorDecl("_x22");
+ ctor.addSelector("_x19", s1);
+ dtdecl.addConstructor(ctor);
+ Sort s3 = d_solver.mkDatatypeSort(dtdecl);
+ Sort s6 = s3.instantiate({s1});
+ Term t26 = d_solver.mkConst(s6, "_x63");
+ Term t5 = d_solver.mkTrue();
+ Term t187 = d_solver.mkTerm(APPLY_UPDATER,
+ t26.getSort()
+ .getDatatype()
+ .getConstructor("_x22")
+ .getSelector("_x19")
+ .getUpdaterTerm(),
+ t26,
+ t5);
+ ASSERT_NO_THROW(d_solver.simplify(t187));
+}
+
+TEST_F(TestApiBlackSolver, proj_issue383)
+{
+ d_solver.setOption("produce-models", "true");
+
+ Sort s1 = d_solver.getBooleanSort();
+
+ DatatypeConstructorDecl ctordecl = d_solver.mkDatatypeConstructorDecl("_x5");
+ DatatypeDecl dtdecl = d_solver.mkDatatypeDecl("_x0");
+ dtdecl.addConstructor(ctordecl);
+ Sort s2 = d_solver.mkDatatypeSort(dtdecl);
+
+ ctordecl = d_solver.mkDatatypeConstructorDecl("_x23");
+ ctordecl.addSelectorSelf("_x21");
+ dtdecl = d_solver.mkDatatypeDecl("_x12");
+ dtdecl.addConstructor(ctordecl);
+ Sort s4 = d_solver.mkDatatypeSort(dtdecl);
+ ASSERT_FALSE(s4.getDatatype().isWellFounded());
+
+ Term t3 = d_solver.mkConst(s4, "_x25");
+ Term t13 = d_solver.mkConst(s1, "_x34");
+
+ d_solver.checkEntailed(t13);
+ ASSERT_THROW(d_solver.getValue(t3), CVC5ApiException);
+}
+
} // namespace test
} // namespace cvc5
diff --git a/test/unit/api/java/DatatypeTest.java b/test/unit/api/java/DatatypeTest.java
index fb23ea515..e94785b08 100644
--- a/test/unit/api/java/DatatypeTest.java
+++ b/test/unit/api/java/DatatypeTest.java
@@ -248,6 +248,8 @@ class DatatypeTest
Sort pairType = d_solver.mkDatatypeSort(pairSpec);
assertTrue(pairType.getDatatype().isParametric());
+ Sort[] dparams = pairType.getDatatype().getParameters();
+ assertTrue(dparams[0].equals(t1) && dparams[1].equals(t2));
v.clear();
v.add(d_solver.getIntegerSort());
@@ -562,10 +564,12 @@ class DatatypeTest
AtomicReference<Term> atomicTerm = new AtomicReference<>();
// get the specialized constructor term for list[Int]
- assertDoesNotThrow(() -> atomicTerm.set(nilc.getSpecializedConstructorTerm(listInt)));
+ assertDoesNotThrow(
+ () -> atomicTerm.set(nilc.getInstantiatedConstructorTerm(listInt)));
Term testConsTerm = atomicTerm.get();
assertNotEquals(testConsTerm, nilc.getConstructorTerm());
// error to get the specialized constructor term for Int
- assertThrows(CVC5ApiException.class, () -> nilc.getSpecializedConstructorTerm(isort));
+ assertThrows(CVC5ApiException.class,
+ () -> nilc.getInstantiatedConstructorTerm(isort));
}
}
diff --git a/test/unit/api/java/SolverTest.java b/test/unit/api/java/SolverTest.java
index ed2f7491d..5d651e82a 100644
--- a/test/unit/api/java/SolverTest.java
+++ b/test/unit/api/java/SolverTest.java
@@ -1428,15 +1428,17 @@ class SolverTest
}
{
// mode option
- OptionInfo info = d_solver.getOptionInfo("output");
+ OptionInfo info = d_solver.getOptionInfo("simplification");
assertions.clear();
- assertions.add(() -> assertEquals("output", info.getName()));
+ assertions.add(() -> assertEquals("simplification", info.getName()));
assertions.add(
- () -> assertEquals(Arrays.asList(new String[] {}), Arrays.asList(info.getAliases())));
+ () -> assertEquals(Arrays.asList(new String[] {"simplification-mode"}), Arrays.asList(info.getAliases())));
assertions.add(() -> assertTrue(info.getBaseInfo().getClass() == OptionInfo.ModeInfo.class));
OptionInfo.ModeInfo modeInfo = (OptionInfo.ModeInfo) info.getBaseInfo();
- assertions.add(() -> assertEquals("none", modeInfo.getDefaultValue()));
- assertions.add(() -> assertEquals("none", modeInfo.getCurrentValue()));
+ assertions.add(() -> assertEquals("batch", modeInfo.getDefaultValue()));
+ assertions.add(() -> assertEquals("batch", modeInfo.getCurrentValue()));
+ assertions.add(() -> assertEquals(2, modeInfo.getModes().length));
+ assertions.add(() -> assertTrue(Arrays.asList(modeInfo.getModes()).contains("batch")));
assertions.add(() -> assertTrue(Arrays.asList(modeInfo.getModes()).contains("none")));
}
assertAll(assertions);
diff --git a/test/unit/api/python/test_datatype_api.py b/test/unit/api/python/test_datatype_api.py
index d8a4c26f7..af34e098e 100644
--- a/test/unit/api/python/test_datatype_api.py
+++ b/test/unit/api/python/test_datatype_api.py
@@ -13,7 +13,6 @@
import pytest
import pycvc5
-from pycvc5 import kinds
from pycvc5 import Sort, Term
from pycvc5 import DatatypeDecl
from pycvc5 import Datatype
@@ -156,6 +155,8 @@ def test_datatype_structs(solver):
dtypeSpec.addConstructor(nil)
dtypeSort = solver.mkDatatypeSort(dtypeSpec)
dt = dtypeSort.getDatatype()
+ # not parametric datatype
+ with pytest.raises(RuntimeError): dt.getParameters()
assert not dt.isCodatatype()
assert not dt.isTuple()
assert not dt.isRecord()
@@ -263,7 +264,7 @@ def test_parametric_datatype(solver):
v.append(t1)
v.append(t2)
pairSpec = solver.mkDatatypeDecl("pair", v)
-
+
mkpair = solver.mkDatatypeConstructorDecl("mk-pair")
mkpair.addSelector("first", t1)
mkpair.addSelector("second", t2)
@@ -272,6 +273,8 @@ def test_parametric_datatype(solver):
pairType = solver.mkDatatypeSort(pairSpec)
assert pairType.getDatatype().isParametric()
+ dparams = pairType.getDatatype().getParameters()
+ assert dparams[0]==t1 and dparams[1]==t2
v.clear()
v.append(solver.getIntegerSort())
@@ -559,8 +562,8 @@ def test_datatype_specialized_cons(solver):
testConsTerm = Term(solver)
# get the specialized constructor term for list[Int]
- testConsTerm = nilc.getSpecializedConstructorTerm(listInt)
+ testConsTerm = nilc.getInstantiatedConstructorTerm(listInt)
assert testConsTerm != nilc.getConstructorTerm()
# error to get the specialized constructor term for Int
with pytest.raises(RuntimeError):
- nilc.getSpecializedConstructorTerm(isort)
+ nilc.getInstantiatedConstructorTerm(isort)
diff --git a/test/unit/api/python/test_grammar.py b/test/unit/api/python/test_grammar.py
index db567a6ba..6225844e3 100644
--- a/test/unit/api/python/test_grammar.py
+++ b/test/unit/api/python/test_grammar.py
@@ -16,7 +16,7 @@
import pytest
import pycvc5
-from pycvc5 import kinds, Term
+from pycvc5 import Term
@pytest.fixture
diff --git a/test/unit/api/python/test_op.py b/test/unit/api/python/test_op.py
index 5126a481d..a79fd0426 100644
--- a/test/unit/api/python/test_op.py
+++ b/test/unit/api/python/test_op.py
@@ -17,7 +17,7 @@
import pytest
import pycvc5
-from pycvc5 import kinds
+from pycvc5 import Kind
from pycvc5 import Sort
from pycvc5 import Op
@@ -28,44 +28,44 @@ def solver():
def test_get_kind(solver):
- x = solver.mkOp(kinds.BVExtract, 31, 1)
+ x = solver.mkOp(Kind.BVExtract, 31, 1)
x.getKind()
def test_is_null(solver):
x = Op(solver)
assert x.isNull()
- x = solver.mkOp(kinds.BVExtract, 31, 1)
+ x = solver.mkOp(Kind.BVExtract, 31, 1)
assert not x.isNull()
def test_op_from_kind(solver):
- solver.mkOp(kinds.Plus)
+ solver.mkOp(Kind.Plus)
with pytest.raises(RuntimeError):
- solver.mkOp(kinds.BVExtract)
+ solver.mkOp(Kind.BVExtract)
def test_get_num_indices(solver):
- plus = solver.mkOp(kinds.Plus)
- divisible = solver.mkOp(kinds.Divisible, 4)
- bitvector_repeat = solver.mkOp(kinds.BVRepeat, 5)
- bitvector_zero_extend = solver.mkOp(kinds.BVZeroExtend, 6)
- bitvector_sign_extend = solver.mkOp(kinds.BVSignExtend, 7)
- bitvector_rotate_left = solver.mkOp(kinds.BVRotateLeft, 8)
- bitvector_rotate_right = solver.mkOp(kinds.BVRotateRight, 9)
- int_to_bitvector = solver.mkOp(kinds.IntToBV, 10)
- iand = solver.mkOp(kinds.Iand, 3)
- floatingpoint_to_ubv = solver.mkOp(kinds.FPToUbv, 11)
- floatingopint_to_sbv = solver.mkOp(kinds.FPToSbv, 13)
- floatingpoint_to_fp_ieee_bitvector = solver.mkOp(kinds.FPToFpIeeeBV, 4, 25)
- floatingpoint_to_fp_floatingpoint = solver.mkOp(kinds.FPToFpFP, 4, 25)
- floatingpoint_to_fp_real = solver.mkOp(kinds.FPToFpReal, 4, 25)
- floatingpoint_to_fp_signed_bitvector = solver.mkOp(kinds.FPToFpSignedBV, 4,
+ plus = solver.mkOp(Kind.Plus)
+ divisible = solver.mkOp(Kind.Divisible, 4)
+ bitvector_repeat = solver.mkOp(Kind.BVRepeat, 5)
+ bitvector_zero_extend = solver.mkOp(Kind.BVZeroExtend, 6)
+ bitvector_sign_extend = solver.mkOp(Kind.BVSignExtend, 7)
+ bitvector_rotate_left = solver.mkOp(Kind.BVRotateLeft, 8)
+ bitvector_rotate_right = solver.mkOp(Kind.BVRotateRight, 9)
+ int_to_bitvector = solver.mkOp(Kind.IntToBV, 10)
+ iand = solver.mkOp(Kind.Iand, 3)
+ floatingpoint_to_ubv = solver.mkOp(Kind.FPToUbv, 11)
+ floatingopint_to_sbv = solver.mkOp(Kind.FPToSbv, 13)
+ floatingpoint_to_fp_ieee_bitvector = solver.mkOp(Kind.FPToFpIeeeBV, 4, 25)
+ floatingpoint_to_fp_floatingpoint = solver.mkOp(Kind.FPToFpFP, 4, 25)
+ floatingpoint_to_fp_real = solver.mkOp(Kind.FPToFpReal, 4, 25)
+ floatingpoint_to_fp_signed_bitvector = solver.mkOp(Kind.FPToFpSignedBV, 4,
25)
floatingpoint_to_fp_unsigned_bitvector = solver.mkOp(
- kinds.FPToFpUnsignedBV, 4, 25)
- floatingpoint_to_fp_generic = solver.mkOp(kinds.FPToFpGeneric, 4, 25)
- regexp_loop = solver.mkOp(kinds.RegexpLoop, 2, 3)
+ Kind.FPToFpUnsignedBV, 4, 25)
+ floatingpoint_to_fp_generic = solver.mkOp(Kind.FPToFpGeneric, 4, 25)
+ regexp_loop = solver.mkOp(Kind.RegexpLoop, 2, 3)
assert 0 == plus.getNumIndices()
assert 1 == divisible.getNumIndices()
@@ -87,7 +87,7 @@ def test_get_num_indices(solver):
assert 2 == regexp_loop.getNumIndices()
def test_op_indices_list(solver):
- with_list = solver.mkOp(kinds.TupleProject, [4, 25])
+ with_list = solver.mkOp(Kind.TupleProject, [4, 25])
assert 2 == with_list.getNumIndices()
def test_get_indices_string(solver):
@@ -95,87 +95,87 @@ def test_get_indices_string(solver):
with pytest.raises(RuntimeError):
x.getIndices()
- divisible_ot = solver.mkOp(kinds.Divisible, 4)
+ divisible_ot = solver.mkOp(Kind.Divisible, 4)
assert divisible_ot.isIndexed()
divisible_idx = divisible_ot.getIndices()
assert divisible_idx == "4"
def test_get_indices_uint(solver):
- bitvector_repeat_ot = solver.mkOp(kinds.BVRepeat, 5)
+ bitvector_repeat_ot = solver.mkOp(Kind.BVRepeat, 5)
assert bitvector_repeat_ot.isIndexed()
bitvector_repeat_idx = bitvector_repeat_ot.getIndices()
assert bitvector_repeat_idx == 5
- bitvector_zero_extend_ot = solver.mkOp(kinds.BVZeroExtend, 6)
+ bitvector_zero_extend_ot = solver.mkOp(Kind.BVZeroExtend, 6)
bitvector_zero_extend_idx = bitvector_zero_extend_ot.getIndices()
assert bitvector_zero_extend_idx == 6
- bitvector_sign_extend_ot = solver.mkOp(kinds.BVSignExtend, 7)
+ bitvector_sign_extend_ot = solver.mkOp(Kind.BVSignExtend, 7)
bitvector_sign_extend_idx = bitvector_sign_extend_ot.getIndices()
assert bitvector_sign_extend_idx == 7
- bitvector_rotate_left_ot = solver.mkOp(kinds.BVRotateLeft, 8)
+ bitvector_rotate_left_ot = solver.mkOp(Kind.BVRotateLeft, 8)
bitvector_rotate_left_idx = bitvector_rotate_left_ot.getIndices()
assert bitvector_rotate_left_idx == 8
- bitvector_rotate_right_ot = solver.mkOp(kinds.BVRotateRight, 9)
+ bitvector_rotate_right_ot = solver.mkOp(Kind.BVRotateRight, 9)
bitvector_rotate_right_idx = bitvector_rotate_right_ot.getIndices()
assert bitvector_rotate_right_idx == 9
- int_to_bitvector_ot = solver.mkOp(kinds.IntToBV, 10)
+ int_to_bitvector_ot = solver.mkOp(Kind.IntToBV, 10)
int_to_bitvector_idx = int_to_bitvector_ot.getIndices()
assert int_to_bitvector_idx == 10
- floatingpoint_to_ubv_ot = solver.mkOp(kinds.FPToUbv, 11)
+ floatingpoint_to_ubv_ot = solver.mkOp(Kind.FPToUbv, 11)
floatingpoint_to_ubv_idx = floatingpoint_to_ubv_ot.getIndices()
assert floatingpoint_to_ubv_idx == 11
- floatingpoint_to_sbv_ot = solver.mkOp(kinds.FPToSbv, 13)
+ floatingpoint_to_sbv_ot = solver.mkOp(Kind.FPToSbv, 13)
floatingpoint_to_sbv_idx = floatingpoint_to_sbv_ot.getIndices()
assert floatingpoint_to_sbv_idx == 13
def test_get_indices_pair_uint(solver):
- bitvector_extract_ot = solver.mkOp(kinds.BVExtract, 4, 0)
+ bitvector_extract_ot = solver.mkOp(Kind.BVExtract, 4, 0)
assert bitvector_extract_ot.isIndexed()
bitvector_extract_indices = bitvector_extract_ot.getIndices()
assert bitvector_extract_indices == (4, 0)
floatingpoint_to_fp_ieee_bitvector_ot = solver.mkOp(
- kinds.FPToFpIeeeBV, 4, 25)
+ Kind.FPToFpIeeeBV, 4, 25)
floatingpoint_to_fp_ieee_bitvector_indices = floatingpoint_to_fp_ieee_bitvector_ot.getIndices(
)
assert floatingpoint_to_fp_ieee_bitvector_indices == (4, 25)
- floatingpoint_to_fp_floatingpoint_ot = solver.mkOp(kinds.FPToFpFP, 4, 25)
+ floatingpoint_to_fp_floatingpoint_ot = solver.mkOp(Kind.FPToFpFP, 4, 25)
floatingpoint_to_fp_floatingpoint_indices = floatingpoint_to_fp_floatingpoint_ot.getIndices(
)
assert floatingpoint_to_fp_floatingpoint_indices == (4, 25)
- floatingpoint_to_fp_real_ot = solver.mkOp(kinds.FPToFpReal, 4, 25)
+ floatingpoint_to_fp_real_ot = solver.mkOp(Kind.FPToFpReal, 4, 25)
floatingpoint_to_fp_real_indices = floatingpoint_to_fp_real_ot.getIndices()
assert floatingpoint_to_fp_real_indices == (4, 25)
floatingpoint_to_fp_signed_bitvector_ot = solver.mkOp(
- kinds.FPToFpSignedBV, 4, 25)
+ Kind.FPToFpSignedBV, 4, 25)
floatingpoint_to_fp_signed_bitvector_indices = floatingpoint_to_fp_signed_bitvector_ot.getIndices(
)
assert floatingpoint_to_fp_signed_bitvector_indices == (4, 25)
floatingpoint_to_fp_unsigned_bitvector_ot = solver.mkOp(
- kinds.FPToFpUnsignedBV, 4, 25)
+ Kind.FPToFpUnsignedBV, 4, 25)
floatingpoint_to_fp_unsigned_bitvector_indices = floatingpoint_to_fp_unsigned_bitvector_ot.getIndices(
)
assert floatingpoint_to_fp_unsigned_bitvector_indices == (4, 25)
- floatingpoint_to_fp_generic_ot = solver.mkOp(kinds.FPToFpGeneric, 4, 25)
+ floatingpoint_to_fp_generic_ot = solver.mkOp(Kind.FPToFpGeneric, 4, 25)
floatingpoint_to_fp_generic_indices = floatingpoint_to_fp_generic_ot.getIndices(
)
assert floatingpoint_to_fp_generic_indices == (4, 25)
def test_op_scoping_to_string(solver):
- bitvector_repeat_ot = solver.mkOp(kinds.BVRepeat, 5)
+ bitvector_repeat_ot = solver.mkOp(Kind.BVRepeat, 5)
op_repr = str(bitvector_repeat_ot)
assert str(bitvector_repeat_ot) == op_repr
diff --git a/test/unit/api/python/test_result.py b/test/unit/api/python/test_result.py
index bd97646f9..e6ca3cf1e 100644
--- a/test/unit/api/python/test_result.py
+++ b/test/unit/api/python/test_result.py
@@ -17,7 +17,6 @@
import pytest
import pycvc5
-from pycvc5 import kinds
from pycvc5 import Result
from pycvc5 import UnknownExplanation
diff --git a/test/unit/api/python/test_solver.py b/test/unit/api/python/test_solver.py
index b6520e0d3..d9d6a6c36 100644
--- a/test/unit/api/python/test_solver.py
+++ b/test/unit/api/python/test_solver.py
@@ -15,7 +15,7 @@ import pytest
import pycvc5
import sys
-from pycvc5 import kinds
+from pycvc5 import Kind
@pytest.fixture
@@ -495,24 +495,24 @@ def test_mk_pos_zero(solver):
def test_mk_op(solver):
with pytest.raises(ValueError):
- solver.mkOp(kinds.BVExtract, kinds.Equal)
+ solver.mkOp(Kind.BVExtract, Kind.Equal)
- solver.mkOp(kinds.Divisible, "2147483648")
+ solver.mkOp(Kind.Divisible, "2147483648")
with pytest.raises(RuntimeError):
- solver.mkOp(kinds.BVExtract, "asdf")
+ solver.mkOp(Kind.BVExtract, "asdf")
- solver.mkOp(kinds.Divisible, 1)
- solver.mkOp(kinds.BVRotateLeft, 1)
- solver.mkOp(kinds.BVRotateRight, 1)
+ solver.mkOp(Kind.Divisible, 1)
+ solver.mkOp(Kind.BVRotateLeft, 1)
+ solver.mkOp(Kind.BVRotateRight, 1)
with pytest.raises(RuntimeError):
- solver.mkOp(kinds.BVExtract, 1)
+ solver.mkOp(Kind.BVExtract, 1)
- solver.mkOp(kinds.BVExtract, 1, 1)
+ solver.mkOp(Kind.BVExtract, 1, 1)
with pytest.raises(RuntimeError):
- solver.mkOp(kinds.Divisible, 1, 2)
+ solver.mkOp(Kind.Divisible, 1, 2)
args = [1, 2, 2]
- solver.mkOp(kinds.TupleProject, args)
+ solver.mkOp(Kind.TupleProject, args)
def test_mk_pi(solver):
@@ -644,19 +644,19 @@ def test_mk_real(solver):
def test_mk_regexp_none(solver):
strSort = solver.getStringSort()
s = solver.mkConst(strSort, "s")
- solver.mkTerm(kinds.StringInRegexp, s, solver.mkRegexpNone())
+ solver.mkTerm(Kind.StringInRegexp, s, solver.mkRegexpNone())
def test_mk_regexp_all(solver):
strSort = solver.getStringSort()
s = solver.mkConst(strSort, "s")
- solver.mkTerm(kinds.StringInRegexp, s, solver.mkRegexpAll())
+ solver.mkTerm(Kind.StringInRegexp, s, solver.mkRegexpAll())
def test_mk_regexp_allchar(solver):
strSort = solver.getStringSort()
s = solver.mkConst(strSort, "s")
- solver.mkTerm(kinds.StringInRegexp, s, solver.mkRegexpAllchar())
+ solver.mkTerm(Kind.StringInRegexp, s, solver.mkRegexpAllchar())
def test_mk_sep_emp(solver):
@@ -694,100 +694,100 @@ def test_mk_term(solver):
# mkTerm(Kind kind) const
solver.mkPi()
- solver.mkTerm(kinds.Pi)
- solver.mkTerm(kinds.Pi, v6)
- solver.mkTerm(solver.mkOp(kinds.Pi))
- solver.mkTerm(solver.mkOp(kinds.Pi), v6)
- solver.mkTerm(kinds.RegexpNone)
- solver.mkTerm(kinds.RegexpNone, v6)
- solver.mkTerm(solver.mkOp(kinds.RegexpNone))
- solver.mkTerm(solver.mkOp(kinds.RegexpNone), v6)
- solver.mkTerm(kinds.RegexpAllchar)
- solver.mkTerm(kinds.RegexpAllchar, v6)
- solver.mkTerm(solver.mkOp(kinds.RegexpAllchar))
- solver.mkTerm(solver.mkOp(kinds.RegexpAllchar), v6)
- solver.mkTerm(kinds.SepEmp)
- solver.mkTerm(kinds.SepEmp, v6)
- solver.mkTerm(solver.mkOp(kinds.SepEmp))
- solver.mkTerm(solver.mkOp(kinds.SepEmp), v6)
- with pytest.raises(RuntimeError):
- solver.mkTerm(kinds.ConstBV)
+ solver.mkTerm(Kind.Pi)
+ solver.mkTerm(Kind.Pi, v6)
+ solver.mkTerm(solver.mkOp(Kind.Pi))
+ solver.mkTerm(solver.mkOp(Kind.Pi), v6)
+ solver.mkTerm(Kind.RegexpNone)
+ solver.mkTerm(Kind.RegexpNone, v6)
+ solver.mkTerm(solver.mkOp(Kind.RegexpNone))
+ solver.mkTerm(solver.mkOp(Kind.RegexpNone), v6)
+ solver.mkTerm(Kind.RegexpAllchar)
+ solver.mkTerm(Kind.RegexpAllchar, v6)
+ solver.mkTerm(solver.mkOp(Kind.RegexpAllchar))
+ solver.mkTerm(solver.mkOp(Kind.RegexpAllchar), v6)
+ solver.mkTerm(Kind.SepEmp)
+ solver.mkTerm(Kind.SepEmp, v6)
+ solver.mkTerm(solver.mkOp(Kind.SepEmp))
+ solver.mkTerm(solver.mkOp(Kind.SepEmp), v6)
+ with pytest.raises(RuntimeError):
+ solver.mkTerm(Kind.ConstBV)
# mkTerm(Kind kind, Term child) const
- solver.mkTerm(kinds.Not, solver.mkTrue())
+ solver.mkTerm(Kind.Not, solver.mkTrue())
with pytest.raises(RuntimeError):
- solver.mkTerm(kinds.Not, pycvc5.Term(solver))
+ solver.mkTerm(Kind.Not, pycvc5.Term(solver))
with pytest.raises(RuntimeError):
- solver.mkTerm(kinds.Not, a)
+ solver.mkTerm(Kind.Not, a)
with pytest.raises(RuntimeError):
- slv.mkTerm(kinds.Not, solver.mkTrue())
+ slv.mkTerm(Kind.Not, solver.mkTrue())
# mkTerm(Kind kind, Term child1, Term child2) const
- solver.mkTerm(kinds.Equal, a, b)
+ solver.mkTerm(Kind.Equal, a, b)
with pytest.raises(RuntimeError):
- solver.mkTerm(kinds.Equal, pycvc5.Term(solver), b)
+ solver.mkTerm(Kind.Equal, pycvc5.Term(solver), b)
with pytest.raises(RuntimeError):
- solver.mkTerm(kinds.Equal, a, pycvc5.Term(solver))
+ solver.mkTerm(Kind.Equal, a, pycvc5.Term(solver))
with pytest.raises(RuntimeError):
- solver.mkTerm(kinds.Equal, a, solver.mkTrue())
+ solver.mkTerm(Kind.Equal, a, solver.mkTrue())
with pytest.raises(RuntimeError):
- slv.mkTerm(kinds.Equal, a, b)
+ slv.mkTerm(Kind.Equal, a, b)
# mkTerm(Kind kind, Term child1, Term child2, Term child3) const
- solver.mkTerm(kinds.Ite, solver.mkTrue(), solver.mkTrue(), solver.mkTrue())
+ solver.mkTerm(Kind.Ite, solver.mkTrue(), solver.mkTrue(), solver.mkTrue())
with pytest.raises(RuntimeError):
- solver.mkTerm(kinds.Ite, pycvc5.Term(solver), solver.mkTrue(),
+ solver.mkTerm(Kind.Ite, pycvc5.Term(solver), solver.mkTrue(),
solver.mkTrue())
with pytest.raises(RuntimeError):
- solver.mkTerm(kinds.Ite, solver.mkTrue(), pycvc5.Term(solver),
+ solver.mkTerm(Kind.Ite, solver.mkTrue(), pycvc5.Term(solver),
solver.mkTrue())
with pytest.raises(RuntimeError):
- solver.mkTerm(kinds.Ite, solver.mkTrue(), solver.mkTrue(),
+ solver.mkTerm(Kind.Ite, solver.mkTrue(), solver.mkTrue(),
pycvc5.Term(solver))
with pytest.raises(RuntimeError):
- solver.mkTerm(kinds.Ite, solver.mkTrue(), solver.mkTrue(), b)
+ solver.mkTerm(Kind.Ite, solver.mkTrue(), solver.mkTrue(), b)
with pytest.raises(RuntimeError):
- slv.mkTerm(kinds.Ite, solver.mkTrue(), solver.mkTrue(),
+ slv.mkTerm(Kind.Ite, solver.mkTrue(), solver.mkTrue(),
solver.mkTrue())
- solver.mkTerm(kinds.Equal, v1)
+ solver.mkTerm(Kind.Equal, v1)
with pytest.raises(RuntimeError):
- solver.mkTerm(kinds.Equal, v2)
+ solver.mkTerm(Kind.Equal, v2)
with pytest.raises(RuntimeError):
- solver.mkTerm(kinds.Equal, v3)
+ solver.mkTerm(Kind.Equal, v3)
with pytest.raises(RuntimeError):
- solver.mkTerm(kinds.Distinct, v6)
+ solver.mkTerm(Kind.Distinct, v6)
# Test cases that are nary via the API but have arity = 2 internally
s_bool = solver.getBooleanSort()
t_bool = solver.mkConst(s_bool, "t_bool")
- solver.mkTerm(kinds.Implies, [t_bool, t_bool, t_bool])
- solver.mkTerm(kinds.Xor, [t_bool, t_bool, t_bool])
- solver.mkTerm(solver.mkOp(kinds.Xor), [t_bool, t_bool, t_bool])
+ solver.mkTerm(Kind.Implies, [t_bool, t_bool, t_bool])
+ solver.mkTerm(Kind.Xor, [t_bool, t_bool, t_bool])
+ solver.mkTerm(solver.mkOp(Kind.Xor), [t_bool, t_bool, t_bool])
t_int = solver.mkConst(solver.getIntegerSort(), "t_int")
- solver.mkTerm(kinds.Division, [t_int, t_int, t_int])
- solver.mkTerm(solver.mkOp(kinds.Division), [t_int, t_int, t_int])
- solver.mkTerm(kinds.IntsDivision, [t_int, t_int, t_int])
- solver.mkTerm(solver.mkOp(kinds.IntsDivision), [t_int, t_int, t_int])
- solver.mkTerm(kinds.Minus, [t_int, t_int, t_int])
- solver.mkTerm(solver.mkOp(kinds.Minus), [t_int, t_int, t_int])
- solver.mkTerm(kinds.Equal, [t_int, t_int, t_int])
- solver.mkTerm(solver.mkOp(kinds.Equal), [t_int, t_int, t_int])
- solver.mkTerm(kinds.Lt, [t_int, t_int, t_int])
- solver.mkTerm(solver.mkOp(kinds.Lt), [t_int, t_int, t_int])
- solver.mkTerm(kinds.Gt, [t_int, t_int, t_int])
- solver.mkTerm(solver.mkOp(kinds.Gt), [t_int, t_int, t_int])
- solver.mkTerm(kinds.Leq, [t_int, t_int, t_int])
- solver.mkTerm(solver.mkOp(kinds.Leq), [t_int, t_int, t_int])
- solver.mkTerm(kinds.Geq, [t_int, t_int, t_int])
- solver.mkTerm(solver.mkOp(kinds.Geq), [t_int, t_int, t_int])
+ solver.mkTerm(Kind.Division, [t_int, t_int, t_int])
+ solver.mkTerm(solver.mkOp(Kind.Division), [t_int, t_int, t_int])
+ solver.mkTerm(Kind.IntsDivision, [t_int, t_int, t_int])
+ solver.mkTerm(solver.mkOp(Kind.IntsDivision), [t_int, t_int, t_int])
+ solver.mkTerm(Kind.Minus, [t_int, t_int, t_int])
+ solver.mkTerm(solver.mkOp(Kind.Minus), [t_int, t_int, t_int])
+ solver.mkTerm(Kind.Equal, [t_int, t_int, t_int])
+ solver.mkTerm(solver.mkOp(Kind.Equal), [t_int, t_int, t_int])
+ solver.mkTerm(Kind.Lt, [t_int, t_int, t_int])
+ solver.mkTerm(solver.mkOp(Kind.Lt), [t_int, t_int, t_int])
+ solver.mkTerm(Kind.Gt, [t_int, t_int, t_int])
+ solver.mkTerm(solver.mkOp(Kind.Gt), [t_int, t_int, t_int])
+ solver.mkTerm(Kind.Leq, [t_int, t_int, t_int])
+ solver.mkTerm(solver.mkOp(Kind.Leq), [t_int, t_int, t_int])
+ solver.mkTerm(Kind.Geq, [t_int, t_int, t_int])
+ solver.mkTerm(solver.mkOp(Kind.Geq), [t_int, t_int, t_int])
t_reg = solver.mkConst(solver.getRegExpSort(), "t_reg")
- solver.mkTerm(kinds.RegexpDiff, [t_reg, t_reg, t_reg])
- solver.mkTerm(solver.mkOp(kinds.RegexpDiff), [t_reg, t_reg, t_reg])
+ solver.mkTerm(Kind.RegexpDiff, [t_reg, t_reg, t_reg])
+ solver.mkTerm(solver.mkOp(Kind.RegexpDiff), [t_reg, t_reg, t_reg])
t_fun = solver.mkConst(solver.mkFunctionSort(
[s_bool, s_bool, s_bool], s_bool))
- solver.mkTerm(kinds.HoApply, [t_fun, t_bool, t_bool, t_bool])
- solver.mkTerm(solver.mkOp(kinds.HoApply), [t_fun, t_bool, t_bool, t_bool])
+ solver.mkTerm(Kind.HoApply, [t_fun, t_bool, t_bool, t_bool])
+ solver.mkTerm(solver.mkOp(Kind.HoApply), [t_fun, t_bool, t_bool, t_bool])
def test_mk_term_from_op(solver):
bv32 = solver.mkBitVectorSort(32)
@@ -800,8 +800,8 @@ def test_mk_term_from_op(solver):
slv = pycvc5.Solver()
# simple operator terms
- opterm1 = solver.mkOp(kinds.BVExtract, 2, 1)
- opterm2 = solver.mkOp(kinds.Divisible, 1)
+ opterm1 = solver.mkOp(Kind.BVExtract, 2, 1)
+ opterm2 = solver.mkOp(Kind.Divisible, 1)
# list datatype
sort = solver.mkParamSort("T")
@@ -829,40 +829,40 @@ def test_mk_term_from_op(solver):
tailTerm2 = lis["cons"]["tail"].getSelectorTerm()
# mkTerm(Op op, Term term) const
- solver.mkTerm(kinds.ApplyConstructor, nilTerm1)
- solver.mkTerm(kinds.ApplyConstructor, nilTerm2)
+ solver.mkTerm(Kind.ApplyConstructor, nilTerm1)
+ solver.mkTerm(Kind.ApplyConstructor, nilTerm2)
with pytest.raises(RuntimeError):
- solver.mkTerm(kinds.ApplySelector, nilTerm1)
+ solver.mkTerm(Kind.ApplySelector, nilTerm1)
with pytest.raises(RuntimeError):
- solver.mkTerm(kinds.ApplySelector, consTerm1)
+ solver.mkTerm(Kind.ApplySelector, consTerm1)
with pytest.raises(RuntimeError):
- solver.mkTerm(kinds.ApplyConstructor, consTerm2)
+ solver.mkTerm(Kind.ApplyConstructor, consTerm2)
with pytest.raises(RuntimeError):
solver.mkTerm(opterm1)
with pytest.raises(RuntimeError):
- solver.mkTerm(kinds.ApplySelector, headTerm1)
+ solver.mkTerm(Kind.ApplySelector, headTerm1)
with pytest.raises(RuntimeError):
solver.mkTerm(opterm1)
with pytest.raises(RuntimeError):
- slv.mkTerm(kinds.ApplyConstructor, nilTerm1)
+ slv.mkTerm(Kind.ApplyConstructor, nilTerm1)
# mkTerm(Op op, Term child) const
solver.mkTerm(opterm1, a)
solver.mkTerm(opterm2, solver.mkInteger(1))
- solver.mkTerm(kinds.ApplySelector, headTerm1, c)
- solver.mkTerm(kinds.ApplySelector, tailTerm2, c)
+ solver.mkTerm(Kind.ApplySelector, headTerm1, c)
+ solver.mkTerm(Kind.ApplySelector, tailTerm2, c)
with pytest.raises(RuntimeError):
solver.mkTerm(opterm2, a)
with pytest.raises(RuntimeError):
solver.mkTerm(opterm1, pycvc5.Term(solver))
with pytest.raises(RuntimeError):
- solver.mkTerm(kinds.ApplyConstructor, consTerm1, solver.mkInteger(0))
+ solver.mkTerm(Kind.ApplyConstructor, consTerm1, solver.mkInteger(0))
with pytest.raises(RuntimeError):
slv.mkTerm(opterm1, a)
# mkTerm(Op op, Term child1, Term child2) const
- solver.mkTerm(kinds.ApplyConstructor, consTerm1, solver.mkInteger(0),
- solver.mkTerm(kinds.ApplyConstructor, nilTerm1))
+ solver.mkTerm(Kind.ApplyConstructor, consTerm1, solver.mkInteger(0),
+ solver.mkTerm(Kind.ApplyConstructor, nilTerm1))
with pytest.raises(RuntimeError):
solver.mkTerm(opterm2, solver.mkInteger(1), solver.mkInteger(2))
with pytest.raises(RuntimeError):
@@ -872,10 +872,10 @@ def test_mk_term_from_op(solver):
with pytest.raises(RuntimeError):
solver.mkTerm(opterm2, pycvc5.Term(solver), solver.mkInteger(1))
with pytest.raises(RuntimeError):
- slv.mkTerm(kinds.ApplyConstructor,\
+ slv.mkTerm(Kind.ApplyConstructor,\
consTerm1,\
solver.mkInteger(0),\
- solver.mkTerm(kinds.ApplyConstructor, nilTerm1))
+ solver.mkTerm(Kind.ApplyConstructor, nilTerm1))
# mkTerm(Op op, Term child1, Term child2, Term child3) const
with pytest.raises(RuntimeError):
@@ -1113,7 +1113,7 @@ def test_uf_iteration(solver):
x = solver.mkConst(intSort, "x")
y = solver.mkConst(intSort, "y")
f = solver.mkConst(funSort, "f")
- fxy = solver.mkTerm(kinds.ApplyUf, f, x, y)
+ fxy = solver.mkTerm(Kind.ApplyUf, f, x, y)
# Expecting the uninterpreted function to be one of the children
expected_children = [f, x, y]
@@ -1133,7 +1133,7 @@ def test_get_info(solver):
def test_get_op(solver):
bv32 = solver.mkBitVectorSort(32)
a = solver.mkConst(bv32, "a")
- ext = solver.mkOp(kinds.BVExtract, 2, 1)
+ ext = solver.mkOp(Kind.BVExtract, 2, 1)
exta = solver.mkTerm(ext, a)
assert not a.hasOp()
@@ -1157,10 +1157,10 @@ def test_get_op(solver):
nilTerm = consList.getConstructorTerm("nil")
headTerm = consList["cons"].getSelectorTerm("head")
- listnil = solver.mkTerm(kinds.ApplyConstructor, nilTerm)
- listcons1 = solver.mkTerm(kinds.ApplyConstructor, consTerm,
+ listnil = solver.mkTerm(Kind.ApplyConstructor, nilTerm)
+ listcons1 = solver.mkTerm(Kind.ApplyConstructor, consTerm,
solver.mkInteger(1), listnil)
- listhead = solver.mkTerm(kinds.ApplySelector, headTerm, listcons1)
+ listhead = solver.mkTerm(Kind.ApplySelector, headTerm, listcons1)
assert listnil.hasOp()
assert listcons1.hasOp()
@@ -1231,14 +1231,14 @@ def test_get_unsat_core3(solver):
p = solver.mkConst(intPredSort, "p")
zero = solver.mkInteger(0)
one = solver.mkInteger(1)
- f_x = solver.mkTerm(kinds.ApplyUf, f, x)
- f_y = solver.mkTerm(kinds.ApplyUf, f, y)
- summ = solver.mkTerm(kinds.Plus, f_x, f_y)
- p_0 = solver.mkTerm(kinds.ApplyUf, p, zero)
- p_f_y = solver.mkTerm(kinds.ApplyUf, p, f_y)
- solver.assertFormula(solver.mkTerm(kinds.Gt, zero, f_x))
- solver.assertFormula(solver.mkTerm(kinds.Gt, zero, f_y))
- solver.assertFormula(solver.mkTerm(kinds.Gt, summ, one))
+ f_x = solver.mkTerm(Kind.ApplyUf, f, x)
+ f_y = solver.mkTerm(Kind.ApplyUf, f, y)
+ summ = solver.mkTerm(Kind.Plus, f_x, f_y)
+ p_0 = solver.mkTerm(Kind.ApplyUf, p, zero)
+ p_f_y = solver.mkTerm(Kind.ApplyUf, p, f_y)
+ solver.assertFormula(solver.mkTerm(Kind.Gt, zero, f_x))
+ solver.assertFormula(solver.mkTerm(Kind.Gt, zero, f_y))
+ solver.assertFormula(solver.mkTerm(Kind.Gt, summ, one))
solver.assertFormula(p_0)
solver.assertFormula(p_f_y.notTerm())
assert solver.checkSat().isUnsat()
@@ -1285,15 +1285,15 @@ def test_get_value3(solver):
p = solver.mkConst(intPredSort, "p")
zero = solver.mkInteger(0)
one = solver.mkInteger(1)
- f_x = solver.mkTerm(kinds.ApplyUf, f, x)
- f_y = solver.mkTerm(kinds.ApplyUf, f, y)
- summ = solver.mkTerm(kinds.Plus, f_x, f_y)
- p_0 = solver.mkTerm(kinds.ApplyUf, p, zero)
- p_f_y = solver.mkTerm(kinds.ApplyUf, p, f_y)
-
- solver.assertFormula(solver.mkTerm(kinds.Leq, zero, f_x))
- solver.assertFormula(solver.mkTerm(kinds.Leq, zero, f_y))
- solver.assertFormula(solver.mkTerm(kinds.Leq, summ, one))
+ f_x = solver.mkTerm(Kind.ApplyUf, f, x)
+ f_y = solver.mkTerm(Kind.ApplyUf, f, y)
+ summ = solver.mkTerm(Kind.Plus, f_x, f_y)
+ p_0 = solver.mkTerm(Kind.ApplyUf, p, zero)
+ p_f_y = solver.mkTerm(Kind.ApplyUf, p, f_y)
+
+ solver.assertFormula(solver.mkTerm(Kind.Leq, zero, f_x))
+ solver.assertFormula(solver.mkTerm(Kind.Leq, zero, f_y))
+ solver.assertFormula(solver.mkTerm(Kind.Leq, summ, one))
solver.assertFormula(p_0.notTerm())
solver.assertFormula(p_f_y)
assert solver.checkSat().isSat()
@@ -1325,7 +1325,7 @@ def checkSimpleSeparationConstraints(slv):
slv.declareSepHeap(integer, integer)
x = slv.mkConst(integer, "x")
p = slv.mkConst(integer, "p")
- heap = slv.mkTerm(kinds.SepPto, p, x)
+ heap = slv.mkTerm(Kind.SepPto, p, x)
slv.assertFormula(heap)
nil = slv.mkSepNil(integer)
slv.assertFormula(nil.eqTerm(slv.mkReal(5)))
@@ -1518,11 +1518,11 @@ def test_simplify(solver):
solver.simplify(a)
b = solver.mkConst(bvSort, "b")
solver.simplify(b)
- x_eq_x = solver.mkTerm(kinds.Equal, x, x)
+ x_eq_x = solver.mkTerm(Kind.Equal, x, x)
solver.simplify(x_eq_x)
assert solver.mkTrue() != x_eq_x
assert solver.mkTrue() == solver.simplify(x_eq_x)
- x_eq_b = solver.mkTerm(kinds.Equal, x, b)
+ x_eq_b = solver.mkTerm(Kind.Equal, x, b)
solver.simplify(x_eq_b)
assert solver.mkTrue() != x_eq_b
assert solver.mkTrue() != solver.simplify(x_eq_b)
@@ -1532,24 +1532,24 @@ def test_simplify(solver):
i1 = solver.mkConst(solver.getIntegerSort(), "i1")
solver.simplify(i1)
- i2 = solver.mkTerm(kinds.Mult, i1, solver.mkInteger("23"))
+ i2 = solver.mkTerm(Kind.Mult, i1, solver.mkInteger("23"))
solver.simplify(i2)
assert i1 != i2
assert i1 != solver.simplify(i2)
- i3 = solver.mkTerm(kinds.Plus, i1, solver.mkInteger(0))
+ i3 = solver.mkTerm(Kind.Plus, i1, solver.mkInteger(0))
solver.simplify(i3)
assert i1 != i3
assert i1 == solver.simplify(i3)
consList = consListSort.getDatatype()
dt1 = solver.mkTerm(\
- kinds.ApplyConstructor,\
+ Kind.ApplyConstructor,\
consList.getConstructorTerm("cons"),\
solver.mkInteger(0),\
- solver.mkTerm(kinds.ApplyConstructor, consList.getConstructorTerm("nil")))
+ solver.mkTerm(Kind.ApplyConstructor, consList.getConstructorTerm("nil")))
solver.simplify(dt1)
dt2 = solver.mkTerm(\
- kinds.ApplySelector, consList["cons"].getSelectorTerm("head"), dt1)
+ Kind.ApplySelector, consList["cons"].getSelectorTerm("head"), dt1)
solver.simplify(dt2)
b1 = solver.mkVar(bvSort, "b1")
@@ -1594,7 +1594,7 @@ def test_check_entailed1(solver):
boolSort = solver.getBooleanSort()
x = solver.mkConst(boolSort, "x")
y = solver.mkConst(boolSort, "y")
- z = solver.mkTerm(kinds.And, x, y)
+ z = solver.mkTerm(Kind.And, x, y)
solver.setOption("incremental", "true")
solver.checkEntailed(solver.mkTrue())
with pytest.raises(RuntimeError):
@@ -1626,30 +1626,30 @@ def test_check_entailed2(solver):
zero = solver.mkInteger(0)
one = solver.mkInteger(1)
# Terms
- f_x = solver.mkTerm(kinds.ApplyUf, f, x)
- f_y = solver.mkTerm(kinds.ApplyUf, f, y)
- summ = solver.mkTerm(kinds.Plus, f_x, f_y)
- p_0 = solver.mkTerm(kinds.ApplyUf, p, zero)
- p_f_y = solver.mkTerm(kinds.ApplyUf, p, f_y)
+ f_x = solver.mkTerm(Kind.ApplyUf, f, x)
+ f_y = solver.mkTerm(Kind.ApplyUf, f, y)
+ summ = solver.mkTerm(Kind.Plus, f_x, f_y)
+ p_0 = solver.mkTerm(Kind.ApplyUf, p, zero)
+ p_f_y = solver.mkTerm(Kind.ApplyUf, p, f_y)
# Assertions
assertions =\
- solver.mkTerm(kinds.And,\
- [solver.mkTerm(kinds.Leq, zero, f_x), # 0 <= f(x)
- solver.mkTerm(kinds.Leq, zero, f_y), # 0 <= f(y)
- solver.mkTerm(kinds.Leq, summ, one), # f(x) + f(y) <= 1
+ solver.mkTerm(Kind.And,\
+ [solver.mkTerm(Kind.Leq, zero, f_x), # 0 <= f(x)
+ solver.mkTerm(Kind.Leq, zero, f_y), # 0 <= f(y)
+ solver.mkTerm(Kind.Leq, summ, one), # f(x) + f(y) <= 1
p_0.notTerm(), # not p(0)
p_f_y # p(f(y))
])
solver.checkEntailed(solver.mkTrue())
solver.assertFormula(assertions)
- solver.checkEntailed(solver.mkTerm(kinds.Distinct, x, y))
+ solver.checkEntailed(solver.mkTerm(Kind.Distinct, x, y))
solver.checkEntailed(\
- [solver.mkFalse(), solver.mkTerm(kinds.Distinct, x, y)])
+ [solver.mkFalse(), solver.mkTerm(Kind.Distinct, x, y)])
with pytest.raises(RuntimeError):
solver.checkEntailed(n)
with pytest.raises(RuntimeError):
- solver.checkEntailed([n, solver.mkTerm(kinds.Distinct, x, y)])
+ solver.checkEntailed([n, solver.mkTerm(Kind.Distinct, x, y)])
slv = pycvc5.Solver()
with pytest.raises(RuntimeError):
slv.checkEntailed(solver.mkTrue())
@@ -1676,7 +1676,7 @@ def test_check_sat_assuming1(solver):
boolSort = solver.getBooleanSort()
x = solver.mkConst(boolSort, "x")
y = solver.mkConst(boolSort, "y")
- z = solver.mkTerm(kinds.And, x, y)
+ z = solver.mkTerm(Kind.And, x, y)
solver.setOption("incremental", "true")
solver.checkSatAssuming(solver.mkTrue())
with pytest.raises(RuntimeError):
@@ -1708,31 +1708,31 @@ def test_check_sat_assuming2(solver):
zero = solver.mkInteger(0)
one = solver.mkInteger(1)
# Terms
- f_x = solver.mkTerm(kinds.ApplyUf, f, x)
- f_y = solver.mkTerm(kinds.ApplyUf, f, y)
- summ = solver.mkTerm(kinds.Plus, f_x, f_y)
- p_0 = solver.mkTerm(kinds.ApplyUf, p, zero)
- p_f_y = solver.mkTerm(kinds.ApplyUf, p, f_y)
+ f_x = solver.mkTerm(Kind.ApplyUf, f, x)
+ f_y = solver.mkTerm(Kind.ApplyUf, f, y)
+ summ = solver.mkTerm(Kind.Plus, f_x, f_y)
+ p_0 = solver.mkTerm(Kind.ApplyUf, p, zero)
+ p_f_y = solver.mkTerm(Kind.ApplyUf, p, f_y)
# Assertions
assertions =\
- solver.mkTerm(kinds.And,\
- [solver.mkTerm(kinds.Leq, zero, f_x), # 0 <= f(x)
- solver.mkTerm(kinds.Leq, zero, f_y), # 0 <= f(y)
- solver.mkTerm(kinds.Leq, summ, one), # f(x) + f(y) <= 1
+ solver.mkTerm(Kind.And,\
+ [solver.mkTerm(Kind.Leq, zero, f_x), # 0 <= f(x)
+ solver.mkTerm(Kind.Leq, zero, f_y), # 0 <= f(y)
+ solver.mkTerm(Kind.Leq, summ, one), # f(x) + f(y) <= 1
p_0.notTerm(), # not p(0)
p_f_y # p(f(y))
])
solver.checkSatAssuming(solver.mkTrue())
solver.assertFormula(assertions)
- solver.checkSatAssuming(solver.mkTerm(kinds.Distinct, x, y))
+ solver.checkSatAssuming(solver.mkTerm(Kind.Distinct, x, y))
solver.checkSatAssuming(
[solver.mkFalse(),
- solver.mkTerm(kinds.Distinct, x, y)])
+ solver.mkTerm(Kind.Distinct, x, y)])
with pytest.raises(RuntimeError):
solver.checkSatAssuming(n)
with pytest.raises(RuntimeError):
- solver.checkSatAssuming([n, solver.mkTerm(kinds.Distinct, x, y)])
+ solver.checkSatAssuming([n, solver.mkTerm(Kind.Distinct, x, y)])
slv = pycvc5.Solver()
with pytest.raises(RuntimeError):
slv.checkSatAssuming(solver.mkTrue())
@@ -1762,10 +1762,10 @@ def test_reset_assertions(solver):
bvSort = solver.mkBitVectorSort(4)
one = solver.mkBitVector(4, 1)
x = solver.mkConst(bvSort, "x")
- ule = solver.mkTerm(kinds.BVUle, x, one)
- srem = solver.mkTerm(kinds.BVSrem, one, x)
+ ule = solver.mkTerm(Kind.BVUle, x, one)
+ srem = solver.mkTerm(Kind.BVSrem, one, x)
solver.push(4)
- slt = solver.mkTerm(kinds.BVSlt, srem, one)
+ slt = solver.mkTerm(Kind.BVSlt, srem, one)
solver.resetAssertions()
solver.checkSatAssuming([slt, ule])
@@ -1970,14 +1970,14 @@ def test_define_fun_global(solver):
# (assert (or (not f) (not (g true))))
solver.assertFormula(
- solver.mkTerm(kinds.Or, f.notTerm(),
- solver.mkTerm(kinds.ApplyUf, g, bTrue).notTerm()))
+ solver.mkTerm(Kind.Or, f.notTerm(),
+ solver.mkTerm(Kind.ApplyUf, g, bTrue).notTerm()))
assert solver.checkSat().isUnsat()
solver.resetAssertions()
# (assert (or (not f) (not (g true))))
solver.assertFormula(
- solver.mkTerm(kinds.Or, f.notTerm(),
- solver.mkTerm(kinds.ApplyUf, g, bTrue).notTerm()))
+ solver.mkTerm(Kind.Or, f.notTerm(),
+ solver.mkTerm(Kind.ApplyUf, g, bTrue).notTerm()))
assert solver.checkSat().isUnsat()
@@ -2001,7 +2001,7 @@ def test_get_model_domain_elements(solver):
x = solver.mkConst(uSort, "x")
y = solver.mkConst(uSort, "y")
z = solver.mkConst(uSort, "z")
- f = solver.mkTerm(kinds.Distinct, x, y, z)
+ f = solver.mkTerm(Kind.Distinct, x, y, z)
solver.assertFormula(f)
solver.checkSat()
solver.getModelDomainElements(uSort)
@@ -2146,7 +2146,7 @@ def test_is_model_core_symbol(solver):
y = solver.mkConst(uSort, "y")
z = solver.mkConst(uSort, "z")
zero = solver.mkInteger(0)
- f = solver.mkTerm(kinds.Not, solver.mkTerm(kinds.Equal, x, y))
+ f = solver.mkTerm(Kind.Not, solver.mkTerm(Kind.Equal, x, y))
solver.assertFormula(f)
solver.checkSat()
assert solver.isModelCoreSymbol(x)
@@ -2164,8 +2164,8 @@ def test_issue5893(solver):
arr = solver.mkConst(arrsort, "arr")
idx = solver.mkConst(bvsort4, "idx")
ten = solver.mkBitVector(8, "10", 10)
- sel = solver.mkTerm(kinds.Select, arr, idx)
- distinct = solver.mkTerm(kinds.Distinct, sel, ten)
+ sel = solver.mkTerm(Kind.Select, arr, idx)
+ distinct = solver.mkTerm(Kind.Distinct, sel, ten)
distinct.getOp()
@@ -2177,8 +2177,8 @@ def test_issue7000(solver):
t7 = solver.mkConst(s3, "_x5")
t37 = solver.mkConst(s2, "_x32")
t59 = solver.mkConst(s2, "_x51")
- t72 = solver.mkTerm(kinds.Equal, t37, t59)
- t74 = solver.mkTerm(kinds.Gt, t4, t7)
+ t72 = solver.mkTerm(Kind.Equal, t37, t59)
+ t74 = solver.mkTerm(Kind.Gt, t4, t7)
# throws logic exception since logic is not higher order by default
with pytest.raises(RuntimeError):
solver.checkEntailed(t72, t74, t72, t72)
@@ -2247,7 +2247,7 @@ def test_tuple_project(solver):
solver.mkBoolean(True), \
solver.mkInteger(3),\
solver.mkString("C"),\
- solver.mkTerm(kinds.SetSingleton, solver.mkString("Z"))]
+ solver.mkTerm(Kind.SetSingleton, solver.mkString("Z"))]
tuple = solver.mkTuple(sorts, elements)
@@ -2258,22 +2258,22 @@ def test_tuple_project(solver):
indices5 = [4]
indices6 = [0, 4]
- solver.mkTerm(solver.mkOp(kinds.TupleProject, indices1), tuple)
+ solver.mkTerm(solver.mkOp(Kind.TupleProject, indices1), tuple)
- solver.mkTerm(solver.mkOp(kinds.TupleProject, indices2), tuple)
+ solver.mkTerm(solver.mkOp(Kind.TupleProject, indices2), tuple)
- solver.mkTerm(solver.mkOp(kinds.TupleProject, indices3), tuple)
+ solver.mkTerm(solver.mkOp(Kind.TupleProject, indices3), tuple)
- solver.mkTerm(solver.mkOp(kinds.TupleProject, indices4), tuple)
+ solver.mkTerm(solver.mkOp(Kind.TupleProject, indices4), tuple)
with pytest.raises(RuntimeError):
- solver.mkTerm(solver.mkOp(kinds.TupleProject, indices5), tuple)
+ solver.mkTerm(solver.mkOp(Kind.TupleProject, indices5), tuple)
with pytest.raises(RuntimeError):
- solver.mkTerm(solver.mkOp(kinds.TupleProject, indices6), tuple)
+ solver.mkTerm(solver.mkOp(Kind.TupleProject, indices6), tuple)
indices = [0, 3, 2, 0, 1, 2]
- op = solver.mkOp(kinds.TupleProject, indices)
+ op = solver.mkOp(Kind.TupleProject, indices)
projection = solver.mkTerm(op, tuple)
datatype = tuple.getSort().getDatatype()
@@ -2282,7 +2282,7 @@ def test_tuple_project(solver):
for i in indices:
selectorTerm = constructor[i].getSelectorTerm()
- selectedTerm = solver.mkTerm(kinds.ApplySelector, selectorTerm, tuple)
+ selectedTerm = solver.mkTerm(Kind.ApplySelector, selectorTerm, tuple)
simplifiedTerm = solver.simplify(selectedTerm)
assert elements[i] == simplifiedTerm
diff --git a/test/unit/api/python/test_sort.py b/test/unit/api/python/test_sort.py
index 98cf76d76..9c9458792 100644
--- a/test/unit/api/python/test_sort.py
+++ b/test/unit/api/python/test_sort.py
@@ -17,7 +17,6 @@
import pytest
import pycvc5
-from pycvc5 import kinds
from pycvc5 import Sort
diff --git a/test/unit/api/python/test_term.py b/test/unit/api/python/test_term.py
index 49314638f..27702bd23 100644
--- a/test/unit/api/python/test_term.py
+++ b/test/unit/api/python/test_term.py
@@ -13,7 +13,7 @@
import pytest
import pycvc5
-from pycvc5 import kinds
+from pycvc5 import Kind
from pycvc5 import Sort, Term
from fractions import Fraction
@@ -73,23 +73,23 @@ def test_get_kind(solver):
zero = solver.mkInteger(0)
zero.getKind()
- f_x = solver.mkTerm(kinds.ApplyUf, f, x)
+ f_x = solver.mkTerm(Kind.ApplyUf, f, x)
f_x.getKind()
- f_y = solver.mkTerm(kinds.ApplyUf, f, y)
+ f_y = solver.mkTerm(Kind.ApplyUf, f, y)
f_y.getKind()
- sum = solver.mkTerm(kinds.Plus, f_x, f_y)
+ sum = solver.mkTerm(Kind.Plus, f_x, f_y)
sum.getKind()
- p_0 = solver.mkTerm(kinds.ApplyUf, p, zero)
+ p_0 = solver.mkTerm(Kind.ApplyUf, p, zero)
p_0.getKind()
- p_f_y = solver.mkTerm(kinds.ApplyUf, p, f_y)
+ p_f_y = solver.mkTerm(Kind.ApplyUf, p, f_y)
p_f_y.getKind()
# Sequence kinds do not exist internally, test that the API properly
# converts them back.
seqSort = solver.mkSequenceSort(intSort)
s = solver.mkConst(seqSort, "s")
- ss = solver.mkTerm(kinds.SeqConcat, s, s)
- assert ss.getKind() == kinds.SeqConcat
+ ss = solver.mkTerm(Kind.SeqConcat, s, s)
+ assert ss.getKind() == Kind.SeqConcat
def test_get_sort(solver):
@@ -120,19 +120,19 @@ def test_get_sort(solver):
zero.getSort()
assert zero.getSort() == intSort
- f_x = solver.mkTerm(kinds.ApplyUf, f, x)
+ f_x = solver.mkTerm(Kind.ApplyUf, f, x)
f_x.getSort()
assert f_x.getSort() == intSort
- f_y = solver.mkTerm(kinds.ApplyUf, f, y)
+ f_y = solver.mkTerm(Kind.ApplyUf, f, y)
f_y.getSort()
assert f_y.getSort() == intSort
- sum = solver.mkTerm(kinds.Plus, f_x, f_y)
+ sum = solver.mkTerm(Kind.Plus, f_x, f_y)
sum.getSort()
assert sum.getSort() == intSort
- p_0 = solver.mkTerm(kinds.ApplyUf, p, zero)
+ p_0 = solver.mkTerm(Kind.ApplyUf, p, zero)
p_0.getSort()
assert p_0.getSort() == boolSort
- p_f_y = solver.mkTerm(kinds.ApplyUf, p, f_y)
+ p_f_y = solver.mkTerm(Kind.ApplyUf, p, f_y)
p_f_y.getSort()
assert p_f_y.getSort() == boolSort
@@ -151,8 +151,8 @@ def test_get_op(solver):
with pytest.raises(RuntimeError):
x.getOp()
- ab = solver.mkTerm(kinds.Select, a, b)
- ext = solver.mkOp(kinds.BVExtract, 4, 0)
+ ab = solver.mkTerm(Kind.Select, a, b)
+ ext = solver.mkOp(Kind.BVExtract, 4, 0)
extb = solver.mkTerm(ext, b)
assert ab.hasOp()
@@ -163,7 +163,7 @@ def test_get_op(solver):
assert extb.getOp() == ext
f = solver.mkConst(funsort, "f")
- fx = solver.mkTerm(kinds.ApplyUf, f, x)
+ fx = solver.mkTerm(Kind.ApplyUf, f, x)
assert not f.hasOp()
with pytest.raises(RuntimeError):
@@ -192,11 +192,11 @@ def test_get_op(solver):
headOpTerm = list1["cons"].getSelectorTerm("head")
tailOpTerm = list1["cons"].getSelectorTerm("tail")
- nilTerm = solver.mkTerm(kinds.ApplyConstructor, nilOpTerm)
- consTerm = solver.mkTerm(kinds.ApplyConstructor, consOpTerm,
+ nilTerm = solver.mkTerm(Kind.ApplyConstructor, nilOpTerm)
+ consTerm = solver.mkTerm(Kind.ApplyConstructor, consOpTerm,
solver.mkInteger(0), nilTerm)
- headTerm = solver.mkTerm(kinds.ApplySelector, headOpTerm, consTerm)
- tailTerm = solver.mkTerm(kinds.ApplySelector, tailOpTerm, consTerm)
+ headTerm = solver.mkTerm(Kind.ApplySelector, headOpTerm, consTerm)
+ tailTerm = solver.mkTerm(Kind.ApplySelector, tailOpTerm, consTerm)
assert nilTerm.hasOp()
assert consTerm.hasOp()
@@ -255,15 +255,15 @@ def test_not_term(solver):
zero = solver.mkInteger(0)
with pytest.raises(RuntimeError):
zero.notTerm()
- f_x = solver.mkTerm(kinds.ApplyUf, f, x)
+ f_x = solver.mkTerm(Kind.ApplyUf, f, x)
with pytest.raises(RuntimeError):
f_x.notTerm()
- sum = solver.mkTerm(kinds.Plus, f_x, f_x)
+ sum = solver.mkTerm(Kind.Plus, f_x, f_x)
with pytest.raises(RuntimeError):
sum.notTerm()
- p_0 = solver.mkTerm(kinds.ApplyUf, p, zero)
+ p_0 = solver.mkTerm(Kind.ApplyUf, p, zero)
p_0.notTerm()
- p_f_x = solver.mkTerm(kinds.ApplyUf, p, f_x)
+ p_f_x = solver.mkTerm(Kind.ApplyUf, p, f_x)
p_f_x.notTerm()
@@ -312,7 +312,7 @@ def test_and_term(solver):
zero.andTerm(p)
with pytest.raises(RuntimeError):
zero.andTerm(zero)
- f_x = solver.mkTerm(kinds.ApplyUf, f, x)
+ f_x = solver.mkTerm(Kind.ApplyUf, f, x)
with pytest.raises(RuntimeError):
f_x.andTerm(b)
with pytest.raises(RuntimeError):
@@ -325,7 +325,7 @@ def test_and_term(solver):
f_x.andTerm(zero)
with pytest.raises(RuntimeError):
f_x.andTerm(f_x)
- sum = solver.mkTerm(kinds.Plus, f_x, f_x)
+ sum = solver.mkTerm(Kind.Plus, f_x, f_x)
with pytest.raises(RuntimeError):
sum.andTerm(b)
with pytest.raises(RuntimeError):
@@ -340,7 +340,7 @@ def test_and_term(solver):
sum.andTerm(f_x)
with pytest.raises(RuntimeError):
sum.andTerm(sum)
- p_0 = solver.mkTerm(kinds.ApplyUf, p, zero)
+ p_0 = solver.mkTerm(Kind.ApplyUf, p, zero)
p_0.andTerm(b)
with pytest.raises(RuntimeError):
p_0.andTerm(x)
@@ -355,7 +355,7 @@ def test_and_term(solver):
with pytest.raises(RuntimeError):
p_0.andTerm(sum)
p_0.andTerm(p_0)
- p_f_x = solver.mkTerm(kinds.ApplyUf, p, f_x)
+ p_f_x = solver.mkTerm(Kind.ApplyUf, p, f_x)
p_f_x.andTerm(b)
with pytest.raises(RuntimeError):
p_f_x.andTerm(x)
@@ -418,7 +418,7 @@ def test_or_term(solver):
zero.orTerm(p)
with pytest.raises(RuntimeError):
zero.orTerm(zero)
- f_x = solver.mkTerm(kinds.ApplyUf, f, x)
+ f_x = solver.mkTerm(Kind.ApplyUf, f, x)
with pytest.raises(RuntimeError):
f_x.orTerm(b)
with pytest.raises(RuntimeError):
@@ -431,7 +431,7 @@ def test_or_term(solver):
f_x.orTerm(zero)
with pytest.raises(RuntimeError):
f_x.orTerm(f_x)
- sum = solver.mkTerm(kinds.Plus, f_x, f_x)
+ sum = solver.mkTerm(Kind.Plus, f_x, f_x)
with pytest.raises(RuntimeError):
sum.orTerm(b)
with pytest.raises(RuntimeError):
@@ -446,7 +446,7 @@ def test_or_term(solver):
sum.orTerm(f_x)
with pytest.raises(RuntimeError):
sum.orTerm(sum)
- p_0 = solver.mkTerm(kinds.ApplyUf, p, zero)
+ p_0 = solver.mkTerm(Kind.ApplyUf, p, zero)
p_0.orTerm(b)
with pytest.raises(RuntimeError):
p_0.orTerm(x)
@@ -461,7 +461,7 @@ def test_or_term(solver):
with pytest.raises(RuntimeError):
p_0.orTerm(sum)
p_0.orTerm(p_0)
- p_f_x = solver.mkTerm(kinds.ApplyUf, p, f_x)
+ p_f_x = solver.mkTerm(Kind.ApplyUf, p, f_x)
p_f_x.orTerm(b)
with pytest.raises(RuntimeError):
p_f_x.orTerm(x)
@@ -524,7 +524,7 @@ def test_xor_term(solver):
zero.xorTerm(p)
with pytest.raises(RuntimeError):
zero.xorTerm(zero)
- f_x = solver.mkTerm(kinds.ApplyUf, f, x)
+ f_x = solver.mkTerm(Kind.ApplyUf, f, x)
with pytest.raises(RuntimeError):
f_x.xorTerm(b)
with pytest.raises(RuntimeError):
@@ -537,7 +537,7 @@ def test_xor_term(solver):
f_x.xorTerm(zero)
with pytest.raises(RuntimeError):
f_x.xorTerm(f_x)
- sum = solver.mkTerm(kinds.Plus, f_x, f_x)
+ sum = solver.mkTerm(Kind.Plus, f_x, f_x)
with pytest.raises(RuntimeError):
sum.xorTerm(b)
with pytest.raises(RuntimeError):
@@ -552,7 +552,7 @@ def test_xor_term(solver):
sum.xorTerm(f_x)
with pytest.raises(RuntimeError):
sum.xorTerm(sum)
- p_0 = solver.mkTerm(kinds.ApplyUf, p, zero)
+ p_0 = solver.mkTerm(Kind.ApplyUf, p, zero)
p_0.xorTerm(b)
with pytest.raises(RuntimeError):
p_0.xorTerm(x)
@@ -567,7 +567,7 @@ def test_xor_term(solver):
with pytest.raises(RuntimeError):
p_0.xorTerm(sum)
p_0.xorTerm(p_0)
- p_f_x = solver.mkTerm(kinds.ApplyUf, p, f_x)
+ p_f_x = solver.mkTerm(Kind.ApplyUf, p, f_x)
p_f_x.xorTerm(b)
with pytest.raises(RuntimeError):
p_f_x.xorTerm(x)
@@ -626,7 +626,7 @@ def test_eq_term(solver):
with pytest.raises(RuntimeError):
zero.eqTerm(p)
zero.eqTerm(zero)
- f_x = solver.mkTerm(kinds.ApplyUf, f, x)
+ f_x = solver.mkTerm(Kind.ApplyUf, f, x)
with pytest.raises(RuntimeError):
f_x.eqTerm(b)
with pytest.raises(RuntimeError):
@@ -637,7 +637,7 @@ def test_eq_term(solver):
f_x.eqTerm(p)
f_x.eqTerm(zero)
f_x.eqTerm(f_x)
- sum = solver.mkTerm(kinds.Plus, f_x, f_x)
+ sum = solver.mkTerm(Kind.Plus, f_x, f_x)
with pytest.raises(RuntimeError):
sum.eqTerm(b)
with pytest.raises(RuntimeError):
@@ -649,7 +649,7 @@ def test_eq_term(solver):
sum.eqTerm(zero)
sum.eqTerm(f_x)
sum.eqTerm(sum)
- p_0 = solver.mkTerm(kinds.ApplyUf, p, zero)
+ p_0 = solver.mkTerm(Kind.ApplyUf, p, zero)
p_0.eqTerm(b)
with pytest.raises(RuntimeError):
p_0.eqTerm(x)
@@ -664,7 +664,7 @@ def test_eq_term(solver):
with pytest.raises(RuntimeError):
p_0.eqTerm(sum)
p_0.eqTerm(p_0)
- p_f_x = solver.mkTerm(kinds.ApplyUf, p, f_x)
+ p_f_x = solver.mkTerm(Kind.ApplyUf, p, f_x)
p_f_x.eqTerm(b)
with pytest.raises(RuntimeError):
p_f_x.eqTerm(x)
@@ -727,7 +727,7 @@ def test_imp_term(solver):
zero.impTerm(p)
with pytest.raises(RuntimeError):
zero.impTerm(zero)
- f_x = solver.mkTerm(kinds.ApplyUf, f, x)
+ f_x = solver.mkTerm(Kind.ApplyUf, f, x)
with pytest.raises(RuntimeError):
f_x.impTerm(b)
with pytest.raises(RuntimeError):
@@ -740,7 +740,7 @@ def test_imp_term(solver):
f_x.impTerm(zero)
with pytest.raises(RuntimeError):
f_x.impTerm(f_x)
- sum = solver.mkTerm(kinds.Plus, f_x, f_x)
+ sum = solver.mkTerm(Kind.Plus, f_x, f_x)
with pytest.raises(RuntimeError):
sum.impTerm(b)
with pytest.raises(RuntimeError):
@@ -755,7 +755,7 @@ def test_imp_term(solver):
sum.impTerm(f_x)
with pytest.raises(RuntimeError):
sum.impTerm(sum)
- p_0 = solver.mkTerm(kinds.ApplyUf, p, zero)
+ p_0 = solver.mkTerm(Kind.ApplyUf, p, zero)
p_0.impTerm(b)
with pytest.raises(RuntimeError):
p_0.impTerm(x)
@@ -770,7 +770,7 @@ def test_imp_term(solver):
with pytest.raises(RuntimeError):
p_0.impTerm(sum)
p_0.impTerm(p_0)
- p_f_x = solver.mkTerm(kinds.ApplyUf, p, f_x)
+ p_f_x = solver.mkTerm(Kind.ApplyUf, p, f_x)
p_f_x.impTerm(b)
with pytest.raises(RuntimeError):
p_f_x.impTerm(x)
@@ -827,22 +827,22 @@ def test_ite_term(solver):
zero.iteTerm(x, x)
with pytest.raises(RuntimeError):
zero.iteTerm(x, b)
- f_x = solver.mkTerm(kinds.ApplyUf, f, x)
+ f_x = solver.mkTerm(Kind.ApplyUf, f, x)
with pytest.raises(RuntimeError):
f_x.iteTerm(b, b)
with pytest.raises(RuntimeError):
f_x.iteTerm(b, x)
- sum = solver.mkTerm(kinds.Plus, f_x, f_x)
+ sum = solver.mkTerm(Kind.Plus, f_x, f_x)
with pytest.raises(RuntimeError):
sum.iteTerm(x, x)
with pytest.raises(RuntimeError):
sum.iteTerm(b, x)
- p_0 = solver.mkTerm(kinds.ApplyUf, p, zero)
+ p_0 = solver.mkTerm(Kind.ApplyUf, p, zero)
p_0.iteTerm(b, b)
p_0.iteTerm(x, x)
with pytest.raises(RuntimeError):
p_0.iteTerm(x, b)
- p_f_x = solver.mkTerm(kinds.ApplyUf, p, f_x)
+ p_f_x = solver.mkTerm(Kind.ApplyUf, p, f_x)
p_f_x.iteTerm(b, b)
p_f_x.iteTerm(x, x)
with pytest.raises(RuntimeError):
@@ -860,8 +860,8 @@ def test_substitute(solver):
x = solver.mkConst(solver.getIntegerSort(), "x")
one = solver.mkInteger(1)
ttrue = solver.mkTrue()
- xpx = solver.mkTerm(kinds.Plus, x, x)
- onepone = solver.mkTerm(kinds.Plus, one, one)
+ xpx = solver.mkTerm(Kind.Plus, x, x)
+ onepone = solver.mkTerm(Kind.Plus, one, one)
assert xpx.substitute(x, one) == onepone
assert onepone.substitute(one, x) == xpx
@@ -871,8 +871,8 @@ def test_substitute(solver):
# simultaneous substitution
y = solver.mkConst(solver.getIntegerSort(), "y")
- xpy = solver.mkTerm(kinds.Plus, x, y)
- xpone = solver.mkTerm(kinds.Plus, y, one)
+ xpy = solver.mkTerm(Kind.Plus, x, y)
+ xpone = solver.mkTerm(Kind.Plus, y, one)
es = []
rs = []
es.append(x)
@@ -917,8 +917,8 @@ def test_substitute(solver):
def test_term_compare(solver):
t1 = solver.mkInteger(1)
- t2 = solver.mkTerm(kinds.Plus, solver.mkInteger(2), solver.mkInteger(2))
- t3 = solver.mkTerm(kinds.Plus, solver.mkInteger(2), solver.mkInteger(2))
+ t2 = solver.mkTerm(Kind.Plus, solver.mkInteger(2), solver.mkInteger(2))
+ t3 = solver.mkTerm(Kind.Plus, solver.mkInteger(2), solver.mkInteger(2))
assert t2 >= t3
assert t2 <= t3
assert (t1 > t2) != (t1 < t2)
@@ -928,7 +928,7 @@ def test_term_compare(solver):
def test_term_children(solver):
# simple term 2+3
two = solver.mkInteger(2)
- t1 = solver.mkTerm(kinds.Plus, two, solver.mkInteger(3))
+ t1 = solver.mkTerm(Kind.Plus, two, solver.mkInteger(3))
assert t1[0] == two
assert t1.getNumChildren() == 2
tnull = Term(solver)
@@ -939,8 +939,8 @@ def test_term_children(solver):
intSort = solver.getIntegerSort()
fsort = solver.mkFunctionSort(intSort, intSort)
f = solver.mkConst(fsort, "f")
- t2 = solver.mkTerm(kinds.ApplyUf, f, two)
- # due to our higher-order view of terms, we treat f as a child of kinds.ApplyUf
+ t2 = solver.mkTerm(Kind.ApplyUf, f, two)
+ # due to our higher-order view of terms, we treat f as a child of Kind.ApplyUf
assert t2.getNumChildren() == 2
assert t2[0] == f
assert t2[1] == two
@@ -993,11 +993,11 @@ def test_get_set(solver):
i2 = solver.mkInteger(7)
s1 = solver.mkEmptySet(s)
- s2 = solver.mkTerm(kinds.SetSingleton, i1)
- s3 = solver.mkTerm(kinds.SetSingleton, i1)
- s4 = solver.mkTerm(kinds.SetSingleton, i2)
+ s2 = solver.mkTerm(Kind.SetSingleton, i1)
+ s3 = solver.mkTerm(Kind.SetSingleton, i1)
+ s4 = solver.mkTerm(Kind.SetSingleton, i2)
s5 = solver.mkTerm(
- kinds.SetUnion, s2, solver.mkTerm(kinds.SetUnion, s3, s4))
+ Kind.SetUnion, s2, solver.mkTerm(Kind.SetUnion, s3, s4))
assert s1.isSetValue()
assert s2.isSetValue()
@@ -1021,11 +1021,11 @@ def test_get_sequence(solver):
i2 = solver.mkInteger(7)
s1 = solver.mkEmptySequence(s)
- s2 = solver.mkTerm(kinds.SeqUnit, i1)
- s3 = solver.mkTerm(kinds.SeqUnit, i1)
- s4 = solver.mkTerm(kinds.SeqUnit, i2)
- s5 = solver.mkTerm(kinds.SeqConcat, s2,
- solver.mkTerm(kinds.SeqConcat, s3, s4))
+ s2 = solver.mkTerm(Kind.SeqUnit, i1)
+ s3 = solver.mkTerm(Kind.SeqUnit, i1)
+ s4 = solver.mkTerm(Kind.SeqUnit, i2)
+ s5 = solver.mkTerm(Kind.SeqConcat, s2,
+ solver.mkTerm(Kind.SeqConcat, s3, s4))
assert s1.isSequenceValue()
assert not s2.isSequenceValue()
@@ -1244,18 +1244,18 @@ def test_const_array(solver):
one = solver.mkInteger(1)
constarr = solver.mkConstArray(arrsort, one)
- assert constarr.getKind() == kinds.ConstArray
+ assert constarr.getKind() == Kind.ConstArray
assert constarr.getConstArrayBase() == one
with pytest.raises(RuntimeError):
a.getConstArrayBase()
arrsort = solver.mkArraySort(solver.getRealSort(), solver.getRealSort())
zero_array = solver.mkConstArray(arrsort, solver.mkReal(0))
- stores = solver.mkTerm(kinds.Store, zero_array, solver.mkReal(1),
+ stores = solver.mkTerm(Kind.Store, zero_array, solver.mkReal(1),
solver.mkReal(2))
- stores = solver.mkTerm(kinds.Store, stores, solver.mkReal(2),
+ stores = solver.mkTerm(Kind.Store, stores, solver.mkReal(2),
solver.mkReal(3))
- stores = solver.mkTerm(kinds.Store, stores, solver.mkReal(4),
+ stores = solver.mkTerm(Kind.Store, stores, solver.mkReal(4),
solver.mkReal(5))
@@ -1264,14 +1264,14 @@ def test_const_sequence_elements(solver):
seqsort = solver.mkSequenceSort(realsort)
s = solver.mkEmptySequence(seqsort)
- assert s.getKind() == kinds.ConstSequence
+ assert s.getKind() == Kind.ConstSequence
# empty sequence has zero elements
cs = s.getSequenceValue()
assert len(cs) == 0
# A seq.unit app is not a constant sequence (regardless of whether it is
# applied to a constant).
- su = solver.mkTerm(kinds.SeqUnit, solver.mkReal(1))
+ su = solver.mkTerm(Kind.SeqUnit, solver.mkReal(1))
with pytest.raises(RuntimeError):
su.getSequenceValue()
diff --git a/test/unit/api/python/test_to_python_obj.py b/test/unit/api/python/test_to_python_obj.py
index bb30fae8f..bef7e78c0 100644
--- a/test/unit/api/python/test_to_python_obj.py
+++ b/test/unit/api/python/test_to_python_obj.py
@@ -15,7 +15,7 @@ from fractions import Fraction
import pytest
import pycvc5
-from pycvc5 import kinds
+from pycvc5 import Kind
def testGetBool():
@@ -54,9 +54,9 @@ def testGetArray():
solver = pycvc5.Solver()
arrsort = solver.mkArraySort(solver.getRealSort(), solver.getRealSort())
zero_array = solver.mkConstArray(arrsort, solver.mkInteger(0))
- stores = solver.mkTerm(kinds.Store, zero_array, solver.mkInteger(1), solver.mkInteger(2))
- stores = solver.mkTerm(kinds.Store, stores, solver.mkInteger(2), solver.mkInteger(3))
- stores = solver.mkTerm(kinds.Store, stores, solver.mkInteger(4), solver.mkInteger(5))
+ stores = solver.mkTerm(Kind.Store, zero_array, solver.mkInteger(1), solver.mkInteger(2))
+ stores = solver.mkTerm(Kind.Store, stores, solver.mkInteger(2), solver.mkInteger(3))
+ stores = solver.mkTerm(Kind.Store, stores, solver.mkInteger(4), solver.mkInteger(5))
array_dict = stores.toPythonObj()
@@ -90,7 +90,7 @@ def testGetValueInt():
intsort = solver.getIntegerSort()
x = solver.mkConst(intsort, "x")
- solver.assertFormula(solver.mkTerm(kinds.Equal, x, solver.mkInteger(6)))
+ solver.assertFormula(solver.mkTerm(Kind.Equal, x, solver.mkInteger(6)))
r = solver.checkSat()
assert r.isSat()
@@ -106,8 +106,8 @@ def testGetValueReal():
realsort = solver.getRealSort()
x = solver.mkConst(realsort, "x")
y = solver.mkConst(realsort, "y")
- solver.assertFormula(solver.mkTerm(kinds.Equal, x, solver.mkReal("6")))
- solver.assertFormula(solver.mkTerm(kinds.Equal, y, solver.mkReal("8.33")))
+ solver.assertFormula(solver.mkTerm(Kind.Equal, x, solver.mkReal("6")))
+ solver.assertFormula(solver.mkTerm(Kind.Equal, y, solver.mkReal("8.33")))
r = solver.checkSat()
assert r.isSat()
diff --git a/test/unit/context/cdlist_black.cpp b/test/unit/context/cdlist_black.cpp
index a8d9f952b..6bc48f9d0 100644
--- a/test/unit/context/cdlist_black.cpp
+++ b/test/unit/context/cdlist_black.cpp
@@ -20,7 +20,6 @@
#include "base/exception.h"
#include "context/cdlist.h"
-#include "memory.h"
#include "test_context.h"
namespace cvc5 {
@@ -135,25 +134,6 @@ TEST_F(TestContextBlackCDList, empty_iterator)
list->deleteSelf();
}
-TEST_F(TestContextBlackCDList, out_of_memory)
-{
-#ifndef CVC5_MEMORY_LIMITING_DISABLED
- CDList<uint32_t> list(d_context.get());
- test::WithLimitedMemory wlm(1);
-
- ASSERT_THROW(
- {
- // We cap it at UINT32_MAX, preferring to terminate with a
- // failure than run indefinitely.
- for (uint32_t i = 0; i < UINT32_MAX; ++i)
- {
- list.push_back(i);
- }
- },
- std::bad_alloc);
-#endif
-}
-
TEST_F(TestContextBlackCDList, pop_below_level_created)
{
d_context->push();
diff --git a/test/unit/memory.h b/test/unit/memory.h
deleted file mode 100644
index 574488e21..000000000
--- a/test/unit/memory.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/******************************************************************************
- * Top contributors (to current version):
- * Tim King, Morgan Deters, Aina Niemetz
- *
- * This file is part of the cvc5 project.
- *
- * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
- * in the top-level source directory and their institutional affiliations.
- * All rights reserved. See the file COPYING in the top-level source
- * directory for licensing information.
- * ****************************************************************************
- *
- * Utility class to help testing out-of-memory conditions.
- *
- * Use it like this (for example):
- *
- * cvc5::test::WithLimitedMemory wlm(amount);
- * ASSERT_THROW( foo(), bad_alloc );
- *
- * The WithLimitedMemory destructor will re-establish the previous limit.
- *
- * This class does not exist in CVC5_MEMORY_LIMITING_DISABLED is defined.
- * This can be disabled for a variety of reasons.
- */
-
-#include "test.h"
-
-#ifndef __CVC5__TEST__UNIT__MEMORY_H
-#define __CVC5__TEST__UNIT__MEMORY_H
-
-#include <string>
-#include <sys/resource.h>
-#include <sys/time.h>
-
-#include "base/check.h"
-#include "base/configuration_private.h"
-
-// Conditionally define CVC5_MEMORY_LIMITING_DISABLED.
-#ifdef __APPLE__
-#define CVC5_MEMORY_LIMITING_DISABLED 1
-#define CVC5_MEMORY_LIMITING_DISABLED_REASON "setrlimit() is broken on Mac."
-#else /* __APPLE__ */
-
-// Tests cannot expect bad_alloc to be thrown due to limit memory using
-// setrlimit when ASAN is enable. ASAN instead aborts on mmap failures.
-# if IS_ASAN_BUILD
-#define CVC5_MEMORY_LIMITING_DISABLED 1
-#define CVC5_MEMORY_LIMITING_DISABLED_REASON "ASAN's mmap failures abort."
-# endif
-#endif
-
-namespace cvc5 {
-namespace test {
-
-#ifndef CVC5_MEMORY_LIMITING_DISABLED
-class WithLimitedMemory {
- public:
- WithLimitedMemory() { remember(); }
-
- WithLimitedMemory(rlim_t amount) {
- remember();
- set(amount);
- }
-
- ~WithLimitedMemory() { set(d_prevAmount); }
-
- void set(rlim_t amount) {
- struct rlimit rlim;
- rlim.rlim_cur = amount;
- rlim.rlim_max = RLIM_INFINITY;
- ASSERT_EQ(setrlimit(RLIMIT_AS, &rlim), 0);
- }
-
- private:
- void remember() {
- struct rlimit rlim;
- ASSERT_EQ(getrlimit(RLIMIT_AS, &rlim), 0);
- d_prevAmount = rlim.rlim_cur;
- }
-
- rlim_t d_prevAmount;
-}; /* class WithLimitedMemory */
-#endif
-
-} // namespace test
-} // namespace cvc5
-
-// Remove CVC5_MEMORY_LIMITING_DISABLED_REASON if it is defined.
-#ifdef CVC5_MEMORY_LIMITING_DISABLED_REASON
-#undef CVC5_MEMORY_LIMITING_DISABLED_REASON
-#endif /* CVC5_MEMORY_LIMITING_DISABLED_REASON */
-
-#endif /* __CVC5__TEST__MEMORY_H */
diff --git a/test/unit/options/options_black.cpp b/test/unit/options/options_black.cpp
index 1ab4bce23..0aa160677 100644
--- a/test/unit/options/options_black.cpp
+++ b/test/unit/options/options_black.cpp
@@ -92,11 +92,13 @@ TEST_F(TestBlackOptions, set)
}
EXPECT_NO_THROW(d_solver.setOption(
name, std::to_string((range.first + range.second) / 2)));
+ EXPECT_THROW(d_solver.setOption(name, "0123abc"), CVC5ApiOptionException);
},
[this, &name](const OptionInfo::NumberInfo<uint64_t>& v) {
std::pair<uint64_t, uint64_t> range{
std::numeric_limits<uint64_t>::min(),
std::numeric_limits<uint64_t>::max()};
+ EXPECT_THROW(d_solver.setOption(name, "-1"), CVC5ApiOptionException);
if (v.minimum)
{
EXPECT_THROW(
@@ -117,6 +119,7 @@ TEST_F(TestBlackOptions, set)
}
EXPECT_NO_THROW(d_solver.setOption(
name, std::to_string((range.first + range.second) / 2)));
+ EXPECT_THROW(d_solver.setOption(name, "0123abc"), CVC5ApiOptionException);
},
[this, &name](const OptionInfo::NumberInfo<double>& v) {
std::pair<double, double> range{
@@ -149,7 +152,9 @@ TEST_F(TestBlackOptions, set)
for (const auto& m : v.modes)
{
d_solver.setOption(name, m);
+ EXPECT_EQ(d_solver.getOption(name), m);
}
+ EXPECT_DEATH(d_solver.setOption(name, "help"), "");
},
},
info.valueInfo);
diff --git a/test/unit/theory/theory_bv_int_blaster_white.cpp b/test/unit/theory/theory_bv_int_blaster_white.cpp
index 2ad8695de..e8238ecbb 100644
--- a/test/unit/theory/theory_bv_int_blaster_white.cpp
+++ b/test/unit/theory/theory_bv_int_blaster_white.cpp
@@ -61,7 +61,7 @@ TEST_F(TestTheoryWhiteBvIntblaster, intblaster_constants)
Env env(d_nodeManager, &opts);
env.d_logic.setLogicString("QF_UFBV");
env.d_logic.lock();
- IntBlaster intBlaster(env, options::SolveBVAsIntMode::SUM, 1, false);
+ IntBlaster intBlaster(env, options::SolveBVAsIntMode::SUM, 1);
Node result = intBlaster.translateNoChildren(bv7_4, lemmas, skolems);
Node seven = d_nodeManager->mkConst(CONST_RATIONAL, Rational(7));
ASSERT_EQ(seven, result);
@@ -86,7 +86,7 @@ TEST_F(TestTheoryWhiteBvIntblaster, intblaster_symbolic_constant)
Env env(d_nodeManager, &opts);
env.d_logic.setLogicString("QF_UFBV");
env.d_logic.lock();
- IntBlaster intBlaster(env, options::SolveBVAsIntMode::SUM, 1, true);
+ IntBlaster intBlaster(env, options::SolveBVAsIntMode::SUM, 1);
Node result = intBlaster.translateNoChildren(bv, lemmas, skolems);
ASSERT_TRUE(result.isVar() && result.getType().isInteger());
@@ -116,7 +116,7 @@ TEST_F(TestTheoryWhiteBvIntblaster, intblaster_uf)
Env env(d_nodeManager, &opts);
env.d_logic.setLogicString("QF_UFBV");
env.d_logic.lock();
- IntBlaster intBlaster(env, options::SolveBVAsIntMode::SUM, 1, true);
+ IntBlaster intBlaster(env, options::SolveBVAsIntMode::SUM, 1);
Node result = intBlaster.translateNoChildren(f, lemmas, skolems);
TypeNode resultType = result.getType();
std::vector<TypeNode> resultDomain = resultType.getArgTypes();
@@ -130,7 +130,7 @@ TEST_F(TestTheoryWhiteBvIntblaster, intblaster_uf)
}
/** Check all cases of the translation.
- * This is a sanity check, that noly verifies
+ * This is a sanity check, that only verifies
* the expected type, and that there were no
* failures.
*/
@@ -143,7 +143,7 @@ TEST_F(TestTheoryWhiteBvIntblaster, intblaster_with_children)
Env env(d_nodeManager, &opts);
env.d_logic.setLogicString("QF_UFBV");
env.d_logic.lock();
- IntBlaster intBlaster(env, options::SolveBVAsIntMode::SUM, 1, true);
+ IntBlaster intBlaster(env, options::SolveBVAsIntMode::SUM, 1);
// bit-vector variables
TypeNode bvType = d_nodeManager->mkBitVectorType(4);
@@ -280,5 +280,45 @@ TEST_F(TestTheoryWhiteBvIntblaster, intblaster_with_children)
ASSERT_TRUE(result.getType().isInteger());
}
+/** Check AND translation for bitwise option.
+ * This is a sanity check, that only verifies
+ * the expected kind, and that there were no
+ * failures.
+ */
+TEST_F(TestTheoryWhiteBvIntblaster, intblaster_bitwise)
+{
+ // place holders for lemmas and skolem
+ std::vector<Node> lemmas;
+ std::map<Node, Node> skolems;
+ Options opts;
+ Env env(d_nodeManager, &opts);
+ env.d_logic.setLogicString("QF_UFBV");
+ env.d_logic.lock();
+ IntBlaster intBlaster(env, options::SolveBVAsIntMode::BITWISE, 1);
+
+ // bit-vector variables
+ TypeNode bvType = d_nodeManager->mkBitVectorType(4);
+ Node v1 = d_nodeManager->mkVar("v1", bvType);
+ Node v2 = d_nodeManager->mkVar("v2", bvType);
+
+ // translated integer variables
+ Node i1 = intBlaster.translateNoChildren(v1, lemmas, skolems);
+ Node i2 = intBlaster.translateNoChildren(v2, lemmas, skolems);
+
+ // if original is BV, result should be Int.
+ // Otherwise, they should have the same type.
+ Node original;
+ Node result;
+
+ // bvand
+ original = d_nodeManager->mkNode(BITVECTOR_AND, v1, v2);
+ size_t orig_num_lemmas = lemmas.size();
+ result = intBlaster.translateWithChildren(original, {i1, i2}, lemmas);
+ // should have kind skolem, would use bitwise comparisons to refine
+ ASSERT_TRUE(result.getKind() == kind::SKOLEM);
+ // check that a lemma was added
+ ASSERT_TRUE(lemmas.size() > orig_num_lemmas);
+}
+
} // namespace test
} // namespace cvc5
diff --git a/test/unit/util/integer_black.cpp b/test/unit/util/integer_black.cpp
index 368f12222..2be2515eb 100644
--- a/test/unit/util/integer_black.cpp
+++ b/test/unit/util/integer_black.cpp
@@ -333,18 +333,69 @@ TEST_F(TestUtilBlackInteger, pow)
ASSERT_EQ(Integer(-1000), Integer(-10).pow(3));
}
-TEST_F(TestUtilBlackInteger, overly_long)
+TEST_F(TestUtilBlackInteger, overly_long_signed)
+{
+ int64_t sl = std::numeric_limits<int64_t>::max();
+ Integer i(sl);
+ if constexpr (sizeof(unsigned long) == sizeof(uint64_t))
+ {
+ ASSERT_EQ(i.getLong(), sl);
+ }
+ ASSERT_NO_THROW(i.getSigned64());
+ ASSERT_EQ(i.getSigned64(), sl);
+ i = i + 1;
+ ASSERT_THROW(i.getSigned64(), IllegalArgumentException);
+}
+
+TEST_F(TestUtilBlackInteger, overly_long_unsigned)
{
uint64_t ul = std::numeric_limits<uint64_t>::max();
Integer i(ul);
- ASSERT_EQ(i.getUnsignedLong(), ul);
+ if constexpr (sizeof(unsigned long) == sizeof(uint64_t))
+ {
+ ASSERT_EQ(i.getUnsignedLong(), ul);
+ }
ASSERT_THROW(i.getLong(), IllegalArgumentException);
+ ASSERT_NO_THROW(i.getUnsigned64());
+ ASSERT_EQ(i.getUnsigned64(), ul);
uint64_t ulplus1 = ul + 1;
ASSERT_EQ(ulplus1, 0);
i = i + 1;
ASSERT_THROW(i.getUnsignedLong(), IllegalArgumentException);
}
+TEST_F(TestUtilBlackInteger, getSigned64)
+{
+ {
+ int64_t i = std::numeric_limits<int64_t>::max();
+ Integer a(i);
+ EXPECT_EQ(a.getSigned64(), i);
+ EXPECT_THROW((a + 1).getSigned64(), IllegalArgumentException);
+ }
+ {
+ int64_t i = std::numeric_limits<int64_t>::min();
+ Integer a(i);
+ EXPECT_EQ(a.getSigned64(), i);
+ EXPECT_THROW((a - 1).getSigned64(), IllegalArgumentException);
+ }
+}
+
+TEST_F(TestUtilBlackInteger, getUnsigned64)
+{
+ {
+ uint64_t i = std::numeric_limits<uint64_t>::max();
+ Integer a(i);
+ EXPECT_EQ(a.getUnsigned64(), i);
+ EXPECT_THROW((a + 1).getUnsigned64(), IllegalArgumentException);
+ }
+ {
+ uint64_t i = std::numeric_limits<uint64_t>::min();
+ Integer a(i);
+ EXPECT_EQ(a.getUnsigned64(), i);
+ EXPECT_THROW((a - 1).getUnsigned64(), IllegalArgumentException);
+ }
+}
+
TEST_F(TestUtilBlackInteger, testBit)
{
ASSERT_FALSE(Integer(0).testBit(6));
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback