summaryrefslogtreecommitdiff
path: root/src/theory
diff options
context:
space:
mode:
authorPaulMeng <baolmeng@gmail.com>2016-04-20 14:43:18 -0500
committerPaulMeng <baolmeng@gmail.com>2016-04-20 14:43:18 -0500
commit904ffb6e73402bae537aa89e7fd8f0ab2e9d60e2 (patch)
treed96bb0c974bdea6170957d3e39d47a98f5c85ca0 /src/theory
parenta0054e9cc78822416d745e955c30f69cbb2a3aa7 (diff)
update from the master
Diffstat (limited to 'src/theory')
-rw-r--r--src/theory/arith/approx_simplex.cpp12
-rw-r--r--src/theory/arith/approx_simplex.h12
-rw-r--r--src/theory/arith/arith_ite_utils.cpp12
-rw-r--r--src/theory/arith/arith_ite_utils.h12
-rw-r--r--src/theory/arith/arith_rewriter.cpp12
-rw-r--r--src/theory/arith/arith_rewriter.h12
-rw-r--r--src/theory/arith/arith_static_learner.cpp12
-rw-r--r--src/theory/arith/arith_static_learner.h12
-rw-r--r--src/theory/arith/arith_utilities.h12
-rw-r--r--src/theory/arith/arithvar.cpp12
-rw-r--r--src/theory/arith/arithvar.h12
-rw-r--r--src/theory/arith/arithvar_node_map.h12
-rw-r--r--src/theory/arith/attempt_solution_simplex.cpp12
-rw-r--r--src/theory/arith/attempt_solution_simplex.h12
-rw-r--r--src/theory/arith/bound_counts.h12
-rw-r--r--src/theory/arith/callbacks.cpp12
-rw-r--r--src/theory/arith/callbacks.h12
-rw-r--r--src/theory/arith/congruence_manager.cpp107
-rw-r--r--src/theory/arith/congruence_manager.h27
-rw-r--r--src/theory/arith/constraint.cpp12
-rw-r--r--src/theory/arith/constraint.h12
-rw-r--r--src/theory/arith/constraint_forward.h12
-rw-r--r--src/theory/arith/cut_log.cpp12
-rw-r--r--src/theory/arith/cut_log.h12
-rw-r--r--src/theory/arith/delta_rational.cpp12
-rw-r--r--src/theory/arith/delta_rational.h12
-rw-r--r--src/theory/arith/dio_solver.cpp12
-rw-r--r--src/theory/arith/dio_solver.h12
-rw-r--r--src/theory/arith/dual_simplex.cpp12
-rw-r--r--src/theory/arith/dual_simplex.h12
-rw-r--r--src/theory/arith/error_set.cpp12
-rw-r--r--src/theory/arith/error_set.h12
-rw-r--r--src/theory/arith/fc_simplex.cpp12
-rw-r--r--src/theory/arith/fc_simplex.h12
-rw-r--r--src/theory/arith/infer_bounds.cpp12
-rw-r--r--src/theory/arith/infer_bounds.h12
-rw-r--r--src/theory/arith/linear_equality.cpp12
-rw-r--r--src/theory/arith/linear_equality.h12
-rw-r--r--src/theory/arith/matrix.cpp12
-rw-r--r--src/theory/arith/matrix.h12
-rw-r--r--src/theory/arith/normal_form.cpp12
-rw-r--r--src/theory/arith/normal_form.h12
-rw-r--r--src/theory/arith/partial_model.cpp12
-rw-r--r--src/theory/arith/partial_model.h12
-rw-r--r--src/theory/arith/pseudoboolean_proc.cpp12
-rw-r--r--src/theory/arith/pseudoboolean_proc.h12
-rw-r--r--src/theory/arith/simplex.cpp12
-rw-r--r--src/theory/arith/simplex.h12
-rw-r--r--src/theory/arith/simplex_update.cpp12
-rw-r--r--src/theory/arith/simplex_update.h12
-rw-r--r--src/theory/arith/soi_simplex.cpp12
-rw-r--r--src/theory/arith/soi_simplex.h12
-rw-r--r--src/theory/arith/tableau.cpp12
-rw-r--r--src/theory/arith/tableau.h12
-rw-r--r--src/theory/arith/tableau_sizes.cpp12
-rw-r--r--src/theory/arith/tableau_sizes.h12
-rw-r--r--src/theory/arith/theory_arith.cpp12
-rw-r--r--src/theory/arith/theory_arith.h12
-rw-r--r--src/theory/arith/theory_arith_private.cpp12
-rw-r--r--src/theory/arith/theory_arith_private.h12
-rw-r--r--src/theory/arith/theory_arith_private_forward.h12
-rw-r--r--src/theory/arith/theory_arith_type_rules.h12
-rw-r--r--src/theory/arith/type_enumerator.h12
-rw-r--r--src/theory/arrays/array_info.cpp36
-rw-r--r--src/theory/arrays/array_info.h15
-rw-r--r--src/theory/arrays/array_proof_reconstruction.cpp134
-rw-r--r--src/theory/arrays/array_proof_reconstruction.h58
-rw-r--r--src/theory/arrays/kinds5
-rw-r--r--src/theory/arrays/static_fact_manager.cpp12
-rw-r--r--src/theory/arrays/static_fact_manager.h12
-rw-r--r--src/theory/arrays/theory_arrays.cpp193
-rw-r--r--src/theory/arrays/theory_arrays.h30
-rw-r--r--src/theory/arrays/theory_arrays_rewriter.cpp12
-rw-r--r--src/theory/arrays/theory_arrays_rewriter.h12
-rw-r--r--src/theory/arrays/theory_arrays_type_rules.h21
-rw-r--r--src/theory/arrays/type_enumerator.h12
-rw-r--r--src/theory/arrays/union_find.cpp12
-rw-r--r--src/theory/arrays/union_find.h12
-rw-r--r--src/theory/atom_requests.cpp12
-rw-r--r--src/theory/atom_requests.h12
-rw-r--r--src/theory/booleans/circuit_propagator.cpp12
-rw-r--r--src/theory/booleans/circuit_propagator.h12
-rw-r--r--src/theory/booleans/theory_bool.cpp12
-rw-r--r--src/theory/booleans/theory_bool.h12
-rw-r--r--src/theory/booleans/theory_bool_rewriter.cpp12
-rw-r--r--src/theory/booleans/theory_bool_rewriter.h12
-rw-r--r--src/theory/booleans/theory_bool_type_rules.h12
-rw-r--r--src/theory/booleans/type_enumerator.h12
-rw-r--r--src/theory/builtin/theory_builtin.cpp12
-rw-r--r--src/theory/builtin/theory_builtin.h12
-rw-r--r--src/theory/builtin/theory_builtin_rewriter.cpp12
-rw-r--r--src/theory/builtin/theory_builtin_rewriter.h12
-rw-r--r--src/theory/builtin/theory_builtin_type_rules.h12
-rw-r--r--src/theory/builtin/type_enumerator.h12
-rw-r--r--src/theory/bv/abstraction.cpp12
-rw-r--r--src/theory/bv/abstraction.h12
-rw-r--r--src/theory/bv/aig_bitblaster.cpp12
-rw-r--r--src/theory/bv/bitblast_strategies_template.h12
-rw-r--r--src/theory/bv/bitblast_utils.h12
-rw-r--r--src/theory/bv/bitblaster_template.h14
-rw-r--r--src/theory/bv/bv_eager_solver.cpp12
-rw-r--r--src/theory/bv/bv_eager_solver.h12
-rw-r--r--src/theory/bv/bv_inequality_graph.cpp12
-rw-r--r--src/theory/bv/bv_inequality_graph.h12
-rw-r--r--src/theory/bv/bv_quick_check.cpp12
-rw-r--r--src/theory/bv/bv_quick_check.h12
-rw-r--r--src/theory/bv/bv_subtheory.h12
-rw-r--r--src/theory/bv/bv_subtheory_algebraic.cpp12
-rw-r--r--src/theory/bv/bv_subtheory_algebraic.h12
-rw-r--r--src/theory/bv/bv_subtheory_bitblast.cpp12
-rw-r--r--src/theory/bv/bv_subtheory_bitblast.h12
-rw-r--r--src/theory/bv/bv_subtheory_core.cpp12
-rw-r--r--src/theory/bv/bv_subtheory_core.h12
-rw-r--r--src/theory/bv/bv_subtheory_inequality.cpp12
-rw-r--r--src/theory/bv/bv_subtheory_inequality.h12
-rw-r--r--src/theory/bv/bv_to_bool.cpp12
-rw-r--r--src/theory/bv/bv_to_bool.h12
-rw-r--r--src/theory/bv/bvintropow2.cpp12
-rw-r--r--src/theory/bv/bvintropow2.h12
-rw-r--r--src/theory/bv/cd_set_collection.h12
-rw-r--r--src/theory/bv/eager_bitblaster.cpp30
-rw-r--r--src/theory/bv/lazy_bitblaster.cpp68
-rw-r--r--src/theory/bv/slicer.cpp12
-rw-r--r--src/theory/bv/slicer.h12
-rw-r--r--src/theory/bv/theory_bv.cpp12
-rw-r--r--src/theory/bv/theory_bv.h12
-rw-r--r--src/theory/bv/theory_bv_rewrite_rules.h12
-rw-r--r--src/theory/bv/theory_bv_rewrite_rules_constant_evaluation.h12
-rw-r--r--src/theory/bv/theory_bv_rewrite_rules_core.h12
-rw-r--r--src/theory/bv/theory_bv_rewrite_rules_normalization.h12
-rw-r--r--src/theory/bv/theory_bv_rewrite_rules_operator_elimination.h12
-rw-r--r--src/theory/bv/theory_bv_rewrite_rules_simplification.h12
-rw-r--r--src/theory/bv/theory_bv_rewriter.cpp12
-rw-r--r--src/theory/bv/theory_bv_rewriter.h12
-rw-r--r--src/theory/bv/theory_bv_type_rules.h12
-rw-r--r--src/theory/bv/theory_bv_utils.cpp12
-rw-r--r--src/theory/bv/theory_bv_utils.h12
-rw-r--r--src/theory/bv/type_enumerator.h12
-rw-r--r--src/theory/datatypes/datatypes_rewriter.h44
-rw-r--r--src/theory/datatypes/datatypes_sygus.cpp14
-rw-r--r--src/theory/datatypes/datatypes_sygus.h14
-rw-r--r--src/theory/datatypes/kinds22
-rw-r--r--src/theory/datatypes/theory_datatypes.cpp184
-rw-r--r--src/theory/datatypes/theory_datatypes.h30
-rw-r--r--src/theory/datatypes/theory_datatypes_type_rules.h73
-rw-r--r--src/theory/datatypes/type_enumerator.cpp12
-rw-r--r--src/theory/datatypes/type_enumerator.h98
-rw-r--r--src/theory/example/ecdata.cpp12
-rw-r--r--src/theory/example/ecdata.h12
-rw-r--r--src/theory/example/theory_uf_tim.cpp12
-rw-r--r--src/theory/example/theory_uf_tim.h12
-rw-r--r--src/theory/fp/theory_fp.cpp17
-rw-r--r--src/theory/fp/theory_fp.h17
-rw-r--r--src/theory/fp/theory_fp_rewriter.cpp13
-rw-r--r--src/theory/fp/theory_fp_rewriter.h17
-rw-r--r--src/theory/fp/theory_fp_type_rules.h17
-rw-r--r--src/theory/idl/idl_assertion.cpp12
-rw-r--r--src/theory/idl/idl_assertion.h12
-rw-r--r--src/theory/idl/idl_assertion_db.cpp12
-rw-r--r--src/theory/idl/idl_assertion_db.h12
-rw-r--r--src/theory/idl/idl_model.cpp12
-rw-r--r--src/theory/idl/idl_model.h12
-rw-r--r--src/theory/idl/theory_idl.cpp12
-rw-r--r--src/theory/idl/theory_idl.h12
-rw-r--r--src/theory/interrupted.h12
-rw-r--r--src/theory/ite_utilities.cpp243
-rw-r--r--src/theory/ite_utilities.h41
-rw-r--r--src/theory/logic_info.cpp12
-rw-r--r--src/theory/logic_info.h12
-rw-r--r--src/theory/output_channel.h13
-rw-r--r--src/theory/quantifiers/alpha_equivalence.cpp38
-rw-r--r--src/theory/quantifiers/alpha_equivalence.h20
-rw-r--r--src/theory/quantifiers/ambqi_builder.cpp16
-rw-r--r--src/theory/quantifiers/ambqi_builder.h12
-rw-r--r--src/theory/quantifiers/anti_skolem.cpp269
-rw-r--r--src/theory/quantifiers/anti_skolem.h75
-rw-r--r--src/theory/quantifiers/bounded_integers.cpp12
-rw-r--r--src/theory/quantifiers/bounded_integers.h12
-rw-r--r--src/theory/quantifiers/candidate_generator.cpp134
-rw-r--r--src/theory/quantifiers/candidate_generator.h28
-rw-r--r--src/theory/quantifiers/ce_guided_instantiation.cpp104
-rw-r--r--src/theory/quantifiers/ce_guided_instantiation.h50
-rw-r--r--src/theory/quantifiers/ce_guided_single_inv.cpp147
-rw-r--r--src/theory/quantifiers/ce_guided_single_inv.h83
-rw-r--r--src/theory/quantifiers/ce_guided_single_inv_ei.cpp12
-rw-r--r--src/theory/quantifiers/ce_guided_single_inv_ei.h12
-rw-r--r--src/theory/quantifiers/ce_guided_single_inv_sol.cpp14
-rw-r--r--src/theory/quantifiers/ce_guided_single_inv_sol.h12
-rw-r--r--src/theory/quantifiers/ceg_instantiator.cpp310
-rw-r--r--src/theory/quantifiers/ceg_instantiator.h25
-rw-r--r--src/theory/quantifiers/conjecture_generator.cpp37
-rw-r--r--src/theory/quantifiers/conjecture_generator.h14
-rw-r--r--src/theory/quantifiers/equality_infer.cpp427
-rw-r--r--src/theory/quantifiers/equality_infer.h103
-rw-r--r--src/theory/quantifiers/first_order_model.cpp127
-rw-r--r--src/theory/quantifiers/first_order_model.h34
-rw-r--r--src/theory/quantifiers/full_model_check.cpp96
-rw-r--r--src/theory/quantifiers/full_model_check.h12
-rw-r--r--src/theory/quantifiers/fun_def_engine.cpp14
-rw-r--r--src/theory/quantifiers/fun_def_engine.h12
-rw-r--r--src/theory/quantifiers/fun_def_process.cpp12
-rw-r--r--src/theory/quantifiers/fun_def_process.h12
-rw-r--r--src/theory/quantifiers/inst_match.cpp131
-rw-r--r--src/theory/quantifiers/inst_match.h74
-rw-r--r--src/theory/quantifiers/inst_match_generator.cpp207
-rw-r--r--src/theory/quantifiers/inst_match_generator.h17
-rw-r--r--src/theory/quantifiers/inst_propagator.cpp761
-rw-r--r--src/theory/quantifiers/inst_propagator.h163
-rw-r--r--src/theory/quantifiers/inst_strategy_cbqi.cpp130
-rw-r--r--src/theory/quantifiers/inst_strategy_cbqi.h18
-rw-r--r--src/theory/quantifiers/inst_strategy_e_matching.cpp197
-rw-r--r--src/theory/quantifiers/inst_strategy_e_matching.h18
-rw-r--r--src/theory/quantifiers/instantiation_engine.cpp61
-rw-r--r--src/theory/quantifiers/instantiation_engine.h15
-rw-r--r--src/theory/quantifiers/local_theory_ext.cpp125
-rw-r--r--src/theory/quantifiers/local_theory_ext.h16
-rw-r--r--src/theory/quantifiers/macros.cpp86
-rw-r--r--src/theory/quantifiers/macros.h12
-rw-r--r--src/theory/quantifiers/model_builder.cpp59
-rw-r--r--src/theory/quantifiers/model_builder.h12
-rw-r--r--src/theory/quantifiers/model_engine.cpp113
-rw-r--r--src/theory/quantifiers/model_engine.h12
-rw-r--r--src/theory/quantifiers/quant_conflict_find.cpp437
-rw-r--r--src/theory/quantifiers/quant_conflict_find.h53
-rw-r--r--src/theory/quantifiers/quant_equality_engine.cpp151
-rw-r--r--src/theory/quantifiers/quant_equality_engine.h21
-rw-r--r--src/theory/quantifiers/quant_split.cpp134
-rw-r--r--src/theory/quantifiers/quant_split.h54
-rw-r--r--src/theory/quantifiers/quant_util.cpp147
-rw-r--r--src/theory/quantifiers/quant_util.h76
-rw-r--r--src/theory/quantifiers/quantifiers_attributes.cpp22
-rw-r--r--src/theory/quantifiers/quantifiers_attributes.h14
-rw-r--r--src/theory/quantifiers/quantifiers_rewriter.cpp590
-rw-r--r--src/theory/quantifiers/quantifiers_rewriter.h32
-rw-r--r--src/theory/quantifiers/relevant_domain.cpp19
-rw-r--r--src/theory/quantifiers/relevant_domain.h19
-rw-r--r--src/theory/quantifiers/rewrite_engine.cpp32
-rw-r--r--src/theory/quantifiers/rewrite_engine.h12
-rw-r--r--src/theory/quantifiers/symmetry_breaking.cpp12
-rw-r--r--src/theory/quantifiers/symmetry_breaking.h12
-rw-r--r--src/theory/quantifiers/term_database.cpp627
-rw-r--r--src/theory/quantifiers/term_database.h164
-rw-r--r--src/theory/quantifiers/theory_quantifiers.cpp14
-rw-r--r--src/theory/quantifiers/theory_quantifiers.h12
-rw-r--r--src/theory/quantifiers/theory_quantifiers_type_rules.h12
-rw-r--r--src/theory/quantifiers/trigger.cpp447
-rw-r--r--src/theory/quantifiers/trigger.h151
-rw-r--r--src/theory/quantifiers_engine.cpp746
-rw-r--r--src/theory/quantifiers_engine.h153
-rw-r--r--src/theory/rep_set.cpp12
-rw-r--r--src/theory/rep_set.h12
-rw-r--r--src/theory/rewriter.cpp12
-rw-r--r--src/theory/rewriter.h12
-rw-r--r--src/theory/rewriter_attributes.h12
-rw-r--r--src/theory/rewriter_tables_template.h12
-rw-r--r--src/theory/sets/card_unused_implementation.cpp312
-rw-r--r--src/theory/sets/expr_patterns.h16
-rw-r--r--src/theory/sets/kinds5
-rw-r--r--src/theory/sets/normal_form.h12
-rw-r--r--src/theory/sets/scrutinize.h12
-rw-r--r--src/theory/sets/term_info.h12
-rw-r--r--src/theory/sets/theory_sets.cpp16
-rw-r--r--src/theory/sets/theory_sets.h14
-rw-r--r--src/theory/sets/theory_sets_private.cpp1218
-rw-r--r--src/theory/sets/theory_sets_private.h104
-rw-r--r--src/theory/sets/theory_sets_rewriter.cpp409
-rw-r--r--src/theory/sets/theory_sets_rewriter.h16
-rw-r--r--src/theory/sets/theory_sets_type_enumerator.h12
-rw-r--r--src/theory/sets/theory_sets_type_rules.h32
-rw-r--r--src/theory/shared_terms_database.cpp14
-rw-r--r--src/theory/shared_terms_database.h12
-rw-r--r--src/theory/sort_inference.cpp584
-rw-r--r--src/theory/sort_inference.h19
-rw-r--r--src/theory/strings/regexp_operation.cpp12
-rw-r--r--src/theory/strings/regexp_operation.h12
-rw-r--r--src/theory/strings/theory_strings.cpp883
-rw-r--r--src/theory/strings/theory_strings.h49
-rw-r--r--src/theory/strings/theory_strings_preprocess.cpp12
-rw-r--r--src/theory/strings/theory_strings_preprocess.h12
-rw-r--r--src/theory/strings/theory_strings_rewriter.cpp12
-rw-r--r--src/theory/strings/theory_strings_rewriter.h12
-rw-r--r--src/theory/strings/theory_strings_type_rules.h38
-rw-r--r--src/theory/strings/type_enumerator.h12
-rw-r--r--src/theory/substitutions.cpp12
-rw-r--r--src/theory/substitutions.h12
-rw-r--r--src/theory/term_registration_visitor.cpp12
-rw-r--r--src/theory/term_registration_visitor.h12
-rw-r--r--src/theory/theory.cpp16
-rw-r--r--src/theory/theory.h16
-rw-r--r--src/theory/theory_engine.cpp85
-rw-r--r--src/theory/theory_engine.h45
-rw-r--r--src/theory/theory_model.cpp16
-rw-r--r--src/theory/theory_model.h12
-rw-r--r--src/theory/theory_registrar.h12
-rw-r--r--src/theory/theory_test_utils.h12
-rw-r--r--src/theory/theory_traits_template.h12
-rw-r--r--src/theory/type_enumerator.h12
-rw-r--r--src/theory/type_enumerator_template.cpp12
-rw-r--r--src/theory/uf/equality_engine.cpp210
-rw-r--r--src/theory/uf/equality_engine.h55
-rw-r--r--src/theory/uf/equality_engine_types.h26
-rw-r--r--src/theory/uf/symmetry_breaker.cpp12
-rw-r--r--src/theory/uf/symmetry_breaker.h12
-rw-r--r--src/theory/uf/theory_uf.cpp27
-rw-r--r--src/theory/uf/theory_uf.h14
-rw-r--r--src/theory/uf/theory_uf_model.cpp12
-rw-r--r--src/theory/uf/theory_uf_model.h12
-rw-r--r--src/theory/uf/theory_uf_rewriter.h12
-rw-r--r--src/theory/uf/theory_uf_strong_solver.cpp561
-rw-r--r--src/theory/uf/theory_uf_strong_solver.h215
-rw-r--r--src/theory/uf/theory_uf_type_rules.h12
-rw-r--r--src/theory/unconstrained_simplifier.cpp12
-rw-r--r--src/theory/unconstrained_simplifier.h12
-rw-r--r--src/theory/valuation.cpp12
-rw-r--r--src/theory/valuation.h12
315 files changed, 11911 insertions, 5522 deletions
diff --git a/src/theory/arith/approx_simplex.cpp b/src/theory/arith/approx_simplex.cpp
index 5bbe29bc5..9b8efb783 100644
--- a/src/theory/arith/approx_simplex.cpp
+++ b/src/theory/arith/approx_simplex.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file approx_simplex.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/approx_simplex.h b/src/theory/arith/approx_simplex.h
index 97e6d6b3e..8832fce71 100644
--- a/src/theory/arith/approx_simplex.h
+++ b/src/theory/arith/approx_simplex.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file approx_simplex.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/arith_ite_utils.cpp b/src/theory/arith/arith_ite_utils.cpp
index cd180e59e..6695e641f 100644
--- a/src/theory/arith/arith_ite_utils.cpp
+++ b/src/theory/arith/arith_ite_utils.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file arith_ite_utils.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Kshitij Bansal
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters, Kshitij Bansal
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/arith_ite_utils.h b/src/theory/arith/arith_ite_utils.h
index 84948cd4b..44c3c080b 100644
--- a/src/theory/arith/arith_ite_utils.h
+++ b/src/theory/arith/arith_ite_utils.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file arith_ite_utils.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/arith_rewriter.cpp b/src/theory/arith/arith_rewriter.cpp
index ca286d53a..e53e2ee97 100644
--- a/src/theory/arith/arith_rewriter.cpp
+++ b/src/theory/arith/arith_rewriter.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file arith_rewriter.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): Dejan Jovanovic
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters, Dejan Jovanovic
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/arith_rewriter.h b/src/theory/arith/arith_rewriter.h
index abc25b4af..3cb502249 100644
--- a/src/theory/arith/arith_rewriter.h
+++ b/src/theory/arith/arith_rewriter.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file arith_rewriter.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: Morgan Deters, Dejan Jovanovic
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Tim King, Dejan Jovanovic, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Rewriter for arithmetic.
**
diff --git a/src/theory/arith/arith_static_learner.cpp b/src/theory/arith/arith_static_learner.cpp
index aac792377..7c648c941 100644
--- a/src/theory/arith/arith_static_learner.cpp
+++ b/src/theory/arith/arith_static_learner.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file arith_static_learner.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: Dejan Jovanovic
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Dejan Jovanovic, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/arith_static_learner.h b/src/theory/arith/arith_static_learner.h
index 2aa9c9332..4951d34d7 100644
--- a/src/theory/arith/arith_static_learner.h
+++ b/src/theory/arith/arith_static_learner.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file arith_static_learner.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): Dejan Jovanovic
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters, Dejan Jovanovic
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/arith_utilities.h b/src/theory/arith/arith_utilities.h
index ffa896012..14329ce4d 100644
--- a/src/theory/arith/arith_utilities.h
+++ b/src/theory/arith/arith_utilities.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file arith_utilities.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Dejan Jovanovic, Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters, Dejan Jovanovic
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Arith utilities are common inline functions for dealing with nodes.
**
diff --git a/src/theory/arith/arithvar.cpp b/src/theory/arith/arithvar.cpp
index acae61db0..1ab125a47 100644
--- a/src/theory/arith/arithvar.cpp
+++ b/src/theory/arith/arithvar.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file arithvar.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/arithvar.h b/src/theory/arith/arithvar.h
index 9e4dab4c3..f9ff6da26 100644
--- a/src/theory/arith/arithvar.h
+++ b/src/theory/arith/arithvar.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file arithvar.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Defines ArithVar which is the internal representation of variables in arithmetic
**
diff --git a/src/theory/arith/arithvar_node_map.h b/src/theory/arith/arithvar_node_map.h
index ede29017b..da0b03ef2 100644
--- a/src/theory/arith/arithvar_node_map.h
+++ b/src/theory/arith/arithvar_node_map.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file arithvar_node_map.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): Dejan Jovanovic
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters, Dejan Jovanovic
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/attempt_solution_simplex.cpp b/src/theory/arith/attempt_solution_simplex.cpp
index d7b31e2e2..333b0bfae 100644
--- a/src/theory/arith/attempt_solution_simplex.cpp
+++ b/src/theory/arith/attempt_solution_simplex.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file attempt_solution_simplex.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/attempt_solution_simplex.h b/src/theory/arith/attempt_solution_simplex.h
index 49a2dda29..00df8c075 100644
--- a/src/theory/arith/attempt_solution_simplex.h
+++ b/src/theory/arith/attempt_solution_simplex.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file attempt_solution_simplex.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief This is an implementation of the Simplex Module for the Simplex for DPLL(T)
** decision procedure.
diff --git a/src/theory/arith/bound_counts.h b/src/theory/arith/bound_counts.h
index b5e0124c1..b6417ed63 100644
--- a/src/theory/arith/bound_counts.h
+++ b/src/theory/arith/bound_counts.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file bound_counts.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters, Clark Barrett
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/callbacks.cpp b/src/theory/arith/callbacks.cpp
index b6e579465..766c7424a 100644
--- a/src/theory/arith/callbacks.cpp
+++ b/src/theory/arith/callbacks.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file callbacks.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/callbacks.h b/src/theory/arith/callbacks.h
index d180ceab5..606f4111b 100644
--- a/src/theory/arith/callbacks.h
+++ b/src/theory/arith/callbacks.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file callbacks.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters, Clark Barrett
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/congruence_manager.cpp b/src/theory/arith/congruence_manager.cpp
index 746121b70..cb8cd8dca 100644
--- a/src/theory/arith/congruence_manager.cpp
+++ b/src/theory/arith/congruence_manager.cpp
@@ -1,24 +1,28 @@
+/********************* */
/*! \file congruence_manager.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters, Dejan Jovanovic
+ ** Top contributors (to current version):
+ ** Tim King, Dejan Jovanovic, Morgan Deters, Andrew Reynolds
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
** [[ Add lengthier description here ]]
** \todo document this file
**/
+
#include "theory/arith/congruence_manager.h"
#include "base/output.h"
#include "smt/smt_statistics_registry.h"
#include "theory/arith/arith_utilities.h"
#include "theory/arith/constraint.h"
+#include "theory/quantifiers/equality_infer.h"
+#include "options/arith_options.h"
namespace CVC4 {
namespace theory {
@@ -28,6 +32,8 @@ ArithCongruenceManager::ArithCongruenceManager(context::Context* c, ConstraintDa
: d_inConflict(c),
d_raiseConflict(raiseConflict),
d_notify(*this),
+ d_eq_infer(NULL),
+ d_eqi_counter(0,c),
d_keepAlive(c),
d_propagatations(c),
d_explanationMap(c),
@@ -35,7 +41,19 @@ ArithCongruenceManager::ArithCongruenceManager(context::Context* c, ConstraintDa
d_setupLiteral(setup),
d_avariables(avars),
d_ee(d_notify, c, "theory::arith::ArithCongruenceManager", true)
-{}
+{
+ //module to infer additional equalities based on normalization
+ if( options::sNormInferEq() ){
+ d_eq_infer = new quantifiers::EqualityInference(c, true);
+ d_true = NodeManager::currentNM()->mkConst( true );
+ }
+}
+
+ArithCongruenceManager::~ArithCongruenceManager() {
+ if( d_eq_infer ){
+ delete d_eq_infer;
+ }
+}
ArithCongruenceManager::Statistics::Statistics():
d_watchedVariables("theory::arith::congruence::watchedVariables", 0),
@@ -98,10 +116,12 @@ void ArithCongruenceManager::ArithCongruenceNotify::eqNotifyConstantTermMerge(TN
}
}
void ArithCongruenceManager::ArithCongruenceNotify::eqNotifyNewClass(TNode t) {
+ d_acm.eqNotifyNewClass(t);
}
void ArithCongruenceManager::ArithCongruenceNotify::eqNotifyPreMerge(TNode t1, TNode t2) {
}
void ArithCongruenceManager::ArithCongruenceNotify::eqNotifyPostMerge(TNode t1, TNode t2) {
+ d_acm.eqNotifyPostMerge(t1,t2);
}
void ArithCongruenceManager::ArithCongruenceNotify::eqNotifyDisequal(TNode t1, TNode t2, TNode reason) {
}
@@ -297,9 +317,9 @@ bool ArithCongruenceManager::propagate(TNode x){
c->setEqualityEngineProof();
}else if(c->hasProof() && x != rewritten){
if(c->assertedToTheTheory()){
- pushBack(x, rewritten, c->getWitness());
+ pushBack(x);
}else{
- pushBack(x, rewritten);
+ pushBack(x);
}
}else{
Assert(c->hasProof() && x == rewritten);
@@ -339,8 +359,24 @@ Node ArithCongruenceManager::explainInternal(TNode internal){
return conjunction;
}
}
+
+void ArithCongruenceManager::eqNotifyNewClass(TNode t) {
+ if( d_eq_infer ){
+ d_eq_infer->eqNotifyNewClass(t);
+ fixpointInfer();
+ }
+}
+void ArithCongruenceManager::eqNotifyPostMerge(TNode t1, TNode t2) {
+ if( d_eq_infer ){
+ d_eq_infer->eqNotifyMerge(t1, t2);
+ fixpointInfer();
+ }
+}
+
Node ArithCongruenceManager::explain(TNode external){
+ Trace("arith-ee") << "Ask for explanation of " << external << std::endl;
Node internal = externalToInternal(external);
+ Trace("arith-ee") << "...internal = " << internal << std::endl;
return explainInternal(internal);
}
@@ -376,6 +412,7 @@ void ArithCongruenceManager::assertionToEqualityEngine(bool isEquality, ArithVar
TNode eq = d_watchedEqualities[s];
Assert(eq.getKind() == kind::EQUAL);
+ Trace("arith-ee") << "Assert " << eq << ", pol " << isEquality << ", reason " << reason << std::endl;
if(isEquality){
d_ee.assertEquality(eq, true, reason);
}else{
@@ -401,6 +438,7 @@ void ArithCongruenceManager::equalsConstant(ConstraintCP c){
Node reason = c->externalExplainByAssertions();
d_keepAlive.push_back(reason);
+ Trace("arith-ee") << "Assert equalsConstant " << eq << ", reason " << reason << std::endl;
d_ee.assertEquality(eq, true, reason);
}
@@ -424,7 +462,7 @@ void ArithCongruenceManager::equalsConstant(ConstraintCP lb, ConstraintCP ub){
d_keepAlive.push_back(eq);
d_keepAlive.push_back(reason);
-
+ Trace("arith-ee") << "Assert equalsConstant2 " << eq << ", reason " << reason << std::endl;
d_ee.assertEquality(eq, true, reason);
}
@@ -432,6 +470,55 @@ void ArithCongruenceManager::addSharedTerm(Node x){
d_ee.addTriggerTerm(x, THEORY_ARITH);
}
+bool ArithCongruenceManager::fixpointInfer() {
+ if( d_eq_infer ){
+ while(! inConflict() && d_eqi_counter.get()<d_eq_infer->getNumPendingMerges() ) {
+ Trace("snorm-infer-eq-debug") << "Processing " << d_eqi_counter.get() << " / " << d_eq_infer->getNumPendingMerges() << std::endl;
+ Node eq = d_eq_infer->getPendingMerge( d_eqi_counter.get() );
+ Trace("snorm-infer-eq") << "ArithCongruenceManager : Infer by normalization : " << eq << std::endl;
+ if( !d_ee.areEqual( eq[0], eq[1] ) ){
+ Node eq_exp = d_eq_infer->getPendingMergeExplanation( d_eqi_counter.get() );
+ Trace("snorm-infer-eq") << " explanation : " << eq_exp << std::endl;
+ //regress explanation
+ std::vector<TNode> assumptions;
+ if( eq_exp.getKind()==kind::AND ){
+ for( unsigned i=0; i<eq_exp.getNumChildren(); i++ ){
+ explain( eq_exp[i], assumptions );
+ }
+ }else if( eq_exp.getKind()==kind::EQUAL ){
+ explain( eq_exp, assumptions );
+ }else{
+ //eq_exp should be true
+ Assert( eq_exp==d_true );
+ }
+ Node req_exp;
+ if( assumptions.empty() ){
+ req_exp = d_true;
+ }else{
+ std::set<TNode> assumptionSet;
+ assumptionSet.insert(assumptions.begin(), assumptions.end());
+ if( assumptionSet.size()==1 ){
+ req_exp = assumptions[0];
+ }else{
+ NodeBuilder<> conjunction(kind::AND);
+ enqueueIntoNB(assumptionSet, conjunction);
+ req_exp = conjunction;
+ }
+ }
+ Trace("snorm-infer-eq") << " regressed explanation : " << req_exp << std::endl;
+ d_ee.assertEquality( eq, true, req_exp );
+ d_keepAlive.push_back( req_exp );
+ }else{
+ Trace("snorm-infer-eq") << "...already equal." << std::endl;
+ }
+ d_eqi_counter = d_eqi_counter.get() + 1;
+ }
+ }
+ return inConflict();
+}
+
+
+
}/* CVC4::theory::arith namespace */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
diff --git a/src/theory/arith/congruence_manager.h b/src/theory/arith/congruence_manager.h
index 138805b6e..a02f36a0f 100644
--- a/src/theory/arith/congruence_manager.h
+++ b/src/theory/arith/congruence_manager.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file congruence_manager.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Dejan Jovanovic, Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters, Dejan Jovanovic, Andrew Reynolds
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
@@ -33,6 +33,11 @@
namespace CVC4 {
namespace theory {
+
+namespace quantifiers {
+class EqualityInference;
+}
+
namespace arith {
class ArithCongruenceManager {
@@ -69,6 +74,11 @@ private:
void eqNotifyDisequal(TNode t1, TNode t2, TNode reason);
};
ArithCongruenceNotify d_notify;
+
+ /** module for shostak normalization, d_eqi_counter is how many pending merges in d_eq_infer we have processed */
+ quantifiers::EqualityInference * d_eq_infer;
+ context::CDO< unsigned > d_eqi_counter;
+ Node d_true;
context::CDList<Node> d_keepAlive;
@@ -127,9 +137,12 @@ private:
Node explainInternal(TNode internal);
+ void eqNotifyNewClass(TNode t);
+ void eqNotifyPostMerge(TNode t1, TNode t2);
public:
ArithCongruenceManager(context::Context* satContext, ConstraintDatabase&, SetupLiteralCallBack, const ArithVariables&, RaiseEqualityEngineConflict raiseConflict);
+ ~ArithCongruenceManager();
Node explain(TNode literal);
void explain(TNode lit, NodeBuilder<>& out);
@@ -160,6 +173,8 @@ public:
void addSharedTerm(Node x);
+ /** process inferred equalities based on Shostak normalization */
+ bool fixpointInfer();
private:
class Statistics {
public:
diff --git a/src/theory/arith/constraint.cpp b/src/theory/arith/constraint.cpp
index 5dc0ba1ac..a82ec4c95 100644
--- a/src/theory/arith/constraint.cpp
+++ b/src/theory/arith/constraint.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file constraint.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Dejan Jovanovic, Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters, Dejan Jovanovic
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/constraint.h b/src/theory/arith/constraint.h
index 2c8fa9bcd..3ae2d0b29 100644
--- a/src/theory/arith/constraint.h
+++ b/src/theory/arith/constraint.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file constraint.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Defines Constraint and ConstraintDatabase which is the internal representation of variables in arithmetic
**
diff --git a/src/theory/arith/constraint_forward.h b/src/theory/arith/constraint_forward.h
index bfa42af46..1ebffc1b0 100644
--- a/src/theory/arith/constraint_forward.h
+++ b/src/theory/arith/constraint_forward.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file constraint_forward.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Forward declarations of the ConstraintValue and ConstraintDatabase classes.
**
diff --git a/src/theory/arith/cut_log.cpp b/src/theory/arith/cut_log.cpp
index d94e1c760..3af2a7178 100644
--- a/src/theory/arith/cut_log.cpp
+++ b/src/theory/arith/cut_log.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file cut_log.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/cut_log.h b/src/theory/arith/cut_log.h
index 82d45871f..548035aec 100644
--- a/src/theory/arith/cut_log.h
+++ b/src/theory/arith/cut_log.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file cut_log.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Kshitij Bansal, Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters, Kshitij Bansal
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/delta_rational.cpp b/src/theory/arith/delta_rational.cpp
index 550e4b503..207fd79a4 100644
--- a/src/theory/arith/delta_rational.cpp
+++ b/src/theory/arith/delta_rational.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file delta_rational.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/delta_rational.h b/src/theory/arith/delta_rational.h
index 39d5a9d64..afe4c0eb0 100644
--- a/src/theory/arith/delta_rational.h
+++ b/src/theory/arith/delta_rational.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file delta_rational.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Dejan Jovanovic, Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters, Dejan Jovanovic
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/dio_solver.cpp b/src/theory/arith/dio_solver.cpp
index 71ad6de45..f34bbc67a 100644
--- a/src/theory/arith/dio_solver.cpp
+++ b/src/theory/arith/dio_solver.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file dio_solver.cpp
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Tim King
- ** Minor contributors (to current version): Dejan Jovanovic
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters, Dejan Jovanovic
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Diophantine equation solver
**
diff --git a/src/theory/arith/dio_solver.h b/src/theory/arith/dio_solver.h
index ccaff47c7..6c53d6ad0 100644
--- a/src/theory/arith/dio_solver.h
+++ b/src/theory/arith/dio_solver.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file dio_solver.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Tim King
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Diophantine equation solver
**
diff --git a/src/theory/arith/dual_simplex.cpp b/src/theory/arith/dual_simplex.cpp
index 907d5eefb..72d7a8602 100644
--- a/src/theory/arith/dual_simplex.cpp
+++ b/src/theory/arith/dual_simplex.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file dual_simplex.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/dual_simplex.h b/src/theory/arith/dual_simplex.h
index e5ab76da8..25461972c 100644
--- a/src/theory/arith/dual_simplex.h
+++ b/src/theory/arith/dual_simplex.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file dual_simplex.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief This is an implementation of the Simplex Module for the Simplex for DPLL(T)
** decision procedure.
diff --git a/src/theory/arith/error_set.cpp b/src/theory/arith/error_set.cpp
index e918f4c7d..7c8efc4e8 100644
--- a/src/theory/arith/error_set.cpp
+++ b/src/theory/arith/error_set.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file error_set.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/error_set.h b/src/theory/arith/error_set.h
index fb3117a98..4b88e3f50 100644
--- a/src/theory/arith/error_set.h
+++ b/src/theory/arith/error_set.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file error_set.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/fc_simplex.cpp b/src/theory/arith/fc_simplex.cpp
index 888e29732..ef5ff93c7 100644
--- a/src/theory/arith/fc_simplex.cpp
+++ b/src/theory/arith/fc_simplex.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file fc_simplex.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/fc_simplex.h b/src/theory/arith/fc_simplex.h
index c416af1c6..ca1e666fc 100644
--- a/src/theory/arith/fc_simplex.h
+++ b/src/theory/arith/fc_simplex.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file fc_simplex.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief This is an implementation of the Simplex Module for the Simplex for DPLL(T)
** decision procedure.
diff --git a/src/theory/arith/infer_bounds.cpp b/src/theory/arith/infer_bounds.cpp
index 05a520d35..96b2a6189 100644
--- a/src/theory/arith/infer_bounds.cpp
+++ b/src/theory/arith/infer_bounds.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file infer_bounds.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/infer_bounds.h b/src/theory/arith/infer_bounds.h
index 770d9d1b3..f65952f7c 100644
--- a/src/theory/arith/infer_bounds.h
+++ b/src/theory/arith/infer_bounds.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file infer_bounds.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/linear_equality.cpp b/src/theory/arith/linear_equality.cpp
index 6d86a1ab1..7e1d84ebb 100644
--- a/src/theory/arith/linear_equality.cpp
+++ b/src/theory/arith/linear_equality.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file linear_equality.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief This implements the LinearEqualityModule.
**
diff --git a/src/theory/arith/linear_equality.h b/src/theory/arith/linear_equality.h
index f3cf17d81..aa6b10c5e 100644
--- a/src/theory/arith/linear_equality.h
+++ b/src/theory/arith/linear_equality.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file linear_equality.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Clark Barrett, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief This module maintains the relationship between a Tableau and PartialModel.
**
diff --git a/src/theory/arith/matrix.cpp b/src/theory/arith/matrix.cpp
index 9ace1d3d1..25ed96b0c 100644
--- a/src/theory/arith/matrix.cpp
+++ b/src/theory/arith/matrix.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file matrix.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/matrix.h b/src/theory/arith/matrix.h
index 647df886f..f0d4ec42c 100644
--- a/src/theory/arith/matrix.h
+++ b/src/theory/arith/matrix.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file matrix.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters, Clark Barrett
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Sparse matrix implementations for different types.
**
diff --git a/src/theory/arith/normal_form.cpp b/src/theory/arith/normal_form.cpp
index e22a5e2e3..d7c580395 100644
--- a/src/theory/arith/normal_form.cpp
+++ b/src/theory/arith/normal_form.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file normal_form.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Dejan Jovanovic, Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters, Dejan Jovanovic
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/normal_form.h b/src/theory/arith/normal_form.h
index eeb56f597..d57d781f1 100644
--- a/src/theory/arith/normal_form.h
+++ b/src/theory/arith/normal_form.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file normal_form.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Dejan Jovanovic, Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters, Dejan Jovanovic
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/partial_model.cpp b/src/theory/arith/partial_model.cpp
index 0124ee0f9..632be2a81 100644
--- a/src/theory/arith/partial_model.cpp
+++ b/src/theory/arith/partial_model.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file partial_model.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/partial_model.h b/src/theory/arith/partial_model.h
index 1e6f2f5ab..b5eafb2c4 100644
--- a/src/theory/arith/partial_model.h
+++ b/src/theory/arith/partial_model.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file partial_model.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Datastructures that track variable by variable information.
**
diff --git a/src/theory/arith/pseudoboolean_proc.cpp b/src/theory/arith/pseudoboolean_proc.cpp
index c09b0180a..0c1496a89 100644
--- a/src/theory/arith/pseudoboolean_proc.cpp
+++ b/src/theory/arith/pseudoboolean_proc.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file pseudoboolean_proc.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/pseudoboolean_proc.h b/src/theory/arith/pseudoboolean_proc.h
index d1e10f695..23065ca48 100644
--- a/src/theory/arith/pseudoboolean_proc.h
+++ b/src/theory/arith/pseudoboolean_proc.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file pseudoboolean_proc.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/simplex.cpp b/src/theory/arith/simplex.cpp
index 24c6ce432..a1ffe90b5 100644
--- a/src/theory/arith/simplex.cpp
+++ b/src/theory/arith/simplex.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file simplex.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/simplex.h b/src/theory/arith/simplex.h
index 1cd617b64..b4cd54a78 100644
--- a/src/theory/arith/simplex.h
+++ b/src/theory/arith/simplex.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file simplex.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters, Clark Barrett
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief This is an implementation of the Simplex Module for the Simplex for DPLL(T)
** decision procedure.
diff --git a/src/theory/arith/simplex_update.cpp b/src/theory/arith/simplex_update.cpp
index 14bdc9a69..adf0dc039 100644
--- a/src/theory/arith/simplex_update.cpp
+++ b/src/theory/arith/simplex_update.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file simplex_update.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief This implements UpdateInfo.
**
diff --git a/src/theory/arith/simplex_update.h b/src/theory/arith/simplex_update.h
index 1a5c42188..2c02e3f77 100644
--- a/src/theory/arith/simplex_update.h
+++ b/src/theory/arith/simplex_update.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file simplex_update.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief This provides a class for summarizing pivot proposals.
**
diff --git a/src/theory/arith/soi_simplex.cpp b/src/theory/arith/soi_simplex.cpp
index df32ec8a4..0a437cde0 100644
--- a/src/theory/arith/soi_simplex.cpp
+++ b/src/theory/arith/soi_simplex.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file soi_simplex.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/soi_simplex.h b/src/theory/arith/soi_simplex.h
index 73a2330a3..c2afe062a 100644
--- a/src/theory/arith/soi_simplex.h
+++ b/src/theory/arith/soi_simplex.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file soi_simplex.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief This is an implementation of the Simplex Module for the Simplex for DPLL(T)
** decision procedure.
diff --git a/src/theory/arith/tableau.cpp b/src/theory/arith/tableau.cpp
index 744dda6b7..0bd130985 100644
--- a/src/theory/arith/tableau.cpp
+++ b/src/theory/arith/tableau.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file tableau.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/tableau.h b/src/theory/arith/tableau.h
index 77187c798..c4c8cfba3 100644
--- a/src/theory/arith/tableau.h
+++ b/src/theory/arith/tableau.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file tableau.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/tableau_sizes.cpp b/src/theory/arith/tableau_sizes.cpp
index 64bae22fe..08f7a69d8 100644
--- a/src/theory/arith/tableau_sizes.cpp
+++ b/src/theory/arith/tableau_sizes.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file tableau_sizes.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/tableau_sizes.h b/src/theory/arith/tableau_sizes.h
index fd62e71a2..635330798 100644
--- a/src/theory/arith/tableau_sizes.h
+++ b/src/theory/arith/tableau_sizes.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file tableau_sizes.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/theory_arith.cpp b/src/theory/arith/theory_arith.cpp
index 3c7a767c6..9627b9a1a 100644
--- a/src/theory/arith/theory_arith.cpp
+++ b/src/theory/arith/theory_arith.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_arith.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): Andrew Reynolds, Martin Brain <>, Tianyi Liang, Dejan Jovanovic
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters, Dejan Jovanovic
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/theory_arith.h b/src/theory/arith/theory_arith.h
index b69d51966..3e414ca6d 100644
--- a/src/theory/arith/theory_arith.h
+++ b/src/theory/arith/theory_arith.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_arith.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Dejan Jovanovic, Tim King
- ** Minor contributors (to current version): Martin Brain <>, Tianyi Liang, Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters, Dejan Jovanovic
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Arithmetic theory.
** Arithmetic theory.
diff --git a/src/theory/arith/theory_arith_private.cpp b/src/theory/arith/theory_arith_private.cpp
index e6b14d2b1..e47231128 100644
--- a/src/theory/arith/theory_arith_private.cpp
+++ b/src/theory/arith/theory_arith_private.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_arith_private.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Andrew Reynolds, Tianyi Liang, Kshitij Bansal, Martin Brain <>, Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters, Martin Brain
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/theory_arith_private.h b/src/theory/arith/theory_arith_private.h
index 1009dceb8..edc3a5bc0 100644
--- a/src/theory/arith/theory_arith_private.h
+++ b/src/theory/arith/theory_arith_private.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_arith_private.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Andrew Reynolds, Tianyi Liang, Morgan Deters, Martin Brain <>
+ ** Top contributors (to current version):
+ ** Tim King, Martin Brain, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/theory_arith_private_forward.h b/src/theory/arith/theory_arith_private_forward.h
index 10b954c7d..ffab816f1 100644
--- a/src/theory/arith/theory_arith_private_forward.h
+++ b/src/theory/arith/theory_arith_private_forward.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_arith_private_forward.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arith/theory_arith_type_rules.h b/src/theory/arith/theory_arith_type_rules.h
index d1cd435a2..071ec9391 100644
--- a/src/theory/arith/theory_arith_type_rules.h
+++ b/src/theory/arith/theory_arith_type_rules.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_arith_type_rules.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Christopher L. Conway, Morgan Deters
- ** Minor contributors (to current version): Tim King
+ ** Top contributors (to current version):
+ ** Morgan Deters, Dejan Jovanovic, Christopher L. Conway
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add brief comments here ]]
**
diff --git a/src/theory/arith/type_enumerator.h b/src/theory/arith/type_enumerator.h
index dc2b6f115..36b7b543a 100644
--- a/src/theory/arith/type_enumerator.h
+++ b/src/theory/arith/type_enumerator.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file type_enumerator.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: none
- ** Minor contributors (to current version): Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Morgan Deters, Tim King, Andrew Reynolds
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Enumerators for rationals and integers
**
diff --git a/src/theory/arrays/array_info.cpp b/src/theory/arrays/array_info.cpp
index 55f013f8c..c63d528a7 100644
--- a/src/theory/arrays/array_info.cpp
+++ b/src/theory/arrays/array_info.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file array_info.cpp
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Clark Barrett
- ** Minor contributors (to current version): Dejan Jovanovic
+ ** Top contributors (to current version):
+ ** Morgan Deters, Clark Barrett, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Contains additional classes to store context dependent information
** for each term of type array
@@ -44,16 +44,16 @@ Info::~Info() {
in_stores->deleteSelf();
}
-ArrayInfo::ArrayInfo(context::Context* c, Backtracker<TNode>* b)
+ArrayInfo::ArrayInfo(context::Context* c, Backtracker<TNode>* b, std::string statisticsPrefix)
: ct(c), bck(b), info_map(),
- d_mergeInfoTimer("theory::arrays::mergeInfoTimer"),
- d_avgIndexListLength("theory::arrays::avgIndexListLength"),
- d_avgStoresListLength("theory::arrays::avgStoresListLength"),
- d_avgInStoresListLength("theory::arrays::avgInStoresListLength"),
- d_listsCount("theory::arrays::listsCount",0),
- d_callsMergeInfo("theory::arrays::callsMergeInfo",0),
- d_maxList("theory::arrays::maxList",0),
- d_tableSize("theory::arrays::infoTableSize", info_map) {
+ d_mergeInfoTimer(statisticsPrefix + "theory::arrays::mergeInfoTimer"),
+ d_avgIndexListLength(statisticsPrefix + "theory::arrays::avgIndexListLength"),
+ d_avgStoresListLength(statisticsPrefix + "theory::arrays::avgStoresListLength"),
+ d_avgInStoresListLength(statisticsPrefix + "theory::arrays::avgInStoresListLength"),
+ d_listsCount(statisticsPrefix + "theory::arrays::listsCount",0),
+ d_callsMergeInfo(statisticsPrefix + "theory::arrays::callsMergeInfo",0),
+ d_maxList(statisticsPrefix + "theory::arrays::maxList",0),
+ d_tableSize(statisticsPrefix + "theory::arrays::infoTableSize", info_map) {
emptyList = new(true) CTNodeList(ct);
emptyInfo = new Info(ct, bck);
smtStatisticsRegistry()->registerStat(&d_mergeInfoTimer);
@@ -208,7 +208,7 @@ void ArrayInfo::setNonLinear(const TNode a) {
} else {
(*it).second->isNonLinear = true;
}
-
+
}
void ArrayInfo::setRIntro1Applied(const TNode a) {
@@ -222,7 +222,7 @@ void ArrayInfo::setRIntro1Applied(const TNode a) {
} else {
(*it).second->rIntro1Applied = true;
}
-
+
}
void ArrayInfo::setModelRep(const TNode a, const TNode b) {
@@ -236,7 +236,7 @@ void ArrayInfo::setModelRep(const TNode a, const TNode b) {
} else {
(*it).second->modelRep = b;
}
-
+
}
void ArrayInfo::setConstArr(const TNode a, const TNode constArr) {
diff --git a/src/theory/arrays/array_info.h b/src/theory/arrays/array_info.h
index 319864c34..11455a97d 100644
--- a/src/theory/arrays/array_info.h
+++ b/src/theory/arrays/array_info.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file array_info.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: none
- ** Minor contributors (to current version): Dejan Jovanovic, Clark Barrett
+ ** Top contributors (to current version):
+ ** Morgan Deters, Clark Barrett, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Contains additional classes to store context dependent information
** for each term of type array
@@ -155,7 +155,8 @@ public:
currentStatisticsRegistry()->registerStat(&d_maxList);
currentStatisticsRegistry()->registerStat(&d_tableSize);
}*/
- ArrayInfo(context::Context* c, Backtracker<TNode>* b);
+
+ ArrayInfo(context::Context* c, Backtracker<TNode>* b, std::string statisticsPrefix = "");
~ArrayInfo();
diff --git a/src/theory/arrays/array_proof_reconstruction.cpp b/src/theory/arrays/array_proof_reconstruction.cpp
new file mode 100644
index 000000000..11c3dc081
--- /dev/null
+++ b/src/theory/arrays/array_proof_reconstruction.cpp
@@ -0,0 +1,134 @@
+/********************* */
+/*! \file array_proof_reconstruction.cpp
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Guy Katz
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2016 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.\endverbatim
+ **
+ ** [[ Add lengthier description here ]]
+
+ ** \todo document this file
+
+**/
+
+#include "theory/arrays/array_proof_reconstruction.h"
+
+namespace CVC4 {
+namespace theory {
+namespace arrays {
+
+ArrayProofReconstruction::ArrayProofReconstruction(const eq::EqualityEngine* equalityEngine)
+ : d_equalityEngine(equalityEngine) {
+}
+
+void ArrayProofReconstruction::setRowMergeTag(unsigned tag) {
+ d_reasonRow = tag;
+}
+
+void ArrayProofReconstruction::setRow1MergeTag(unsigned tag) {
+ d_reasonRow1 = tag;
+}
+
+void ArrayProofReconstruction::setExtMergeTag(unsigned tag) {
+ d_reasonExt = tag;
+}
+
+void ArrayProofReconstruction::notify(unsigned reasonType, Node reason, Node a, Node b,
+ std::vector<TNode>& equalities, eq::EqProof* proof) const {
+
+ Debug("pf::array") << "ArrayProofReconstruction::notify( "
+ << reason << ", " << a << ", " << b << std::endl;
+
+
+ if (reasonType == d_reasonExt) {
+ if (proof) {
+ // Todo: here we assume that a=b is an assertion. We should probably call explain()
+ // recursively, to explain this.
+ eq::EqProof* childProof = new eq::EqProof;
+ childProof->d_node = reason;
+ proof->d_children.push_back(childProof);
+ }
+ }
+
+ else if (reasonType == d_reasonRow) {
+ // ROW rules mean that (i==k) OR ((a[i]:=t)[k] == a[k])
+ // The equality here will be either (i == k) because ((a[i]:=t)[k] != a[k]),
+ // or ((a[i]:=t)[k] == a[k]) because (i != k).
+
+ if (proof) {
+ if (a.getNumChildren() == 2) {
+ // This is the case of ((a[i]:=t)[k] == a[k]) because (i != k).
+
+ // The edge is ((a[i]:=t)[k], a[k]), or (a[k], (a[i]:=t)[k]). This flag should be
+ // false in the first case and true in the second case.
+ bool currentNodeIsUnchangedArray;
+
+ Assert(a.getNumChildren() == 2);
+ Assert(b.getNumChildren() == 2);
+
+ if (a[0].getKind() == kind::VARIABLE || a[0].getKind() == kind::SKOLEM) {
+ currentNodeIsUnchangedArray = true;
+ } else if (b[0].getKind() == kind::VARIABLE || b[0].getKind() == kind::SKOLEM) {
+ currentNodeIsUnchangedArray = false;
+ } else {
+ Assert(a[0].getKind() == kind::STORE);
+ Assert(b[0].getKind() == kind::STORE);
+
+ if (a[0][0] == b[0]) {
+ currentNodeIsUnchangedArray = false;
+ } else if (b[0][0] == a[0]) {
+ currentNodeIsUnchangedArray = true;
+ } else {
+ Unreachable();
+ }
+ }
+
+ Node indexOne = currentNodeIsUnchangedArray ? a[1] : a[0][1];
+ Node indexTwo = currentNodeIsUnchangedArray ? b[0][1] : b[1];
+
+ // Some assertions to ensure that the theory of arrays behaves as expected
+ Assert(a[1] == b[1]);
+ if (currentNodeIsUnchangedArray) {
+ Assert(a[0] == b[0][0]);
+ } else {
+ Assert(a[0][0] == b[0]);
+ }
+
+ Debug("pf::ee") << "Getting explanation for ROW guard: "
+ << indexOne << " != " << indexTwo << std::endl;
+
+ eq::EqProof* childProof = new eq::EqProof;
+ d_equalityEngine->explainEquality(indexOne, indexTwo, false, equalities, childProof);
+ proof->d_children.push_back(childProof);
+ } else {
+ // This is the case of (i == k) because ((a[i]:=t)[k] != a[k]),
+
+ Node indexOne = a;
+ Node indexTwo = b;
+
+ Debug("pf::ee") << "The two indices are: " << indexOne << ", " << indexTwo << std::endl
+ << "The reason for the edge is: " << reason << std::endl;
+
+ Assert(reason.getNumChildren() == 2);
+ Debug("pf::ee") << "Getting explanation for ROW guard: " << reason[1] << std::endl;
+
+ eq::EqProof* childProof = new eq::EqProof;
+ d_equalityEngine->explainEquality(reason[1][0], reason[1][1], false, equalities, childProof);
+ proof->d_children.push_back(childProof);
+ }
+ }
+
+ }
+
+ else if (reasonType == d_reasonRow1) {
+ // No special handling required at this time
+ }
+}
+
+}/* CVC4::theory::arrays namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
diff --git a/src/theory/arrays/array_proof_reconstruction.h b/src/theory/arrays/array_proof_reconstruction.h
new file mode 100644
index 000000000..ef3e09aed
--- /dev/null
+++ b/src/theory/arrays/array_proof_reconstruction.h
@@ -0,0 +1,58 @@
+/********************* */
+/*! \file array_proof_reconstruction.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Guy Katz
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2016 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.\endverbatim
+ **
+ ** \brief Array-specific proof construction logic to be used during the
+ ** equality engine's path reconstruction
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__ARRAYS__ARRAY_PROOF_RECONSTRUCTION_H
+#define __CVC4__THEORY__ARRAYS__ARRAY_PROOF_RECONSTRUCTION_H
+
+#include "theory/uf/equality_engine.h"
+
+namespace CVC4 {
+namespace theory {
+namespace arrays {
+
+/**
+ * A callback class to be invoked whenever the equality engine traverses
+ * an "array-owned" edge during path reconstruction.
+ */
+
+class ArrayProofReconstruction : public eq::PathReconstructionNotify {
+public:
+ ArrayProofReconstruction(const eq::EqualityEngine* equalityEngine);
+
+ void notify(unsigned reasonType, Node reason, Node a, Node b,
+ std::vector<TNode>& equalities, eq::EqProof* proof) const;
+
+ void setRowMergeTag(unsigned tag);
+ void setRow1MergeTag(unsigned tag);
+ void setExtMergeTag(unsigned tag);
+
+private:
+ /** Merge tag for ROW applications */
+ unsigned d_reasonRow;
+ /** Merge tag for ROW1 applications */
+ unsigned d_reasonRow1;
+ /** Merge tag for EXT applications */
+ unsigned d_reasonExt;
+
+ const eq::EqualityEngine* d_equalityEngine;
+}; /* class ArrayProofReconstruction */
+
+}/* CVC4::theory::arrays namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
+
+#endif /* __CVC4__THEORY__ARRAYS__ARRAY_PROOF_RECONSTRUCTION_H */
diff --git a/src/theory/arrays/kinds b/src/theory/arrays/kinds
index d5f313ca1..be16d684d 100644
--- a/src/theory/arrays/kinds
+++ b/src/theory/arrays/kinds
@@ -54,6 +54,11 @@ typerule STORE_ALL ::CVC4::theory::arrays::ArrayStoreTypeRule
typerule ARR_TABLE_FUN ::CVC4::theory::arrays::ArrayTableFunTypeRule
typerule ARRAY_LAMBDA ::CVC4::theory::arrays::ArrayLambdaTypeRule
+operator PARTIAL_SELECT_0 0:2 "partial array select, for internal use only"
+operator PARTIAL_SELECT_1 0:2 "partial array select, for internal use only"
+typerule PARTIAL_SELECT_0 ::CVC4::theory::arrays::ArrayPartialSelectTypeRule
+typerule PARTIAL_SELECT_1 ::CVC4::theory::arrays::ArrayPartialSelectTypeRule
+
# store operations that are ordered (by index) over a store-all are constant
construle STORE ::CVC4::theory::arrays::ArrayStoreTypeRule
diff --git a/src/theory/arrays/static_fact_manager.cpp b/src/theory/arrays/static_fact_manager.cpp
index 0d04ce097..da1d7bba9 100644
--- a/src/theory/arrays/static_fact_manager.cpp
+++ b/src/theory/arrays/static_fact_manager.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file static_fact_manager.cpp
** \verbatim
- ** Original author: Clark Barrett
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Clark Barrett, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Path-compressing, backtrackable union-find using an undo
** stack. Refactored from the UF union-find.
diff --git a/src/theory/arrays/static_fact_manager.h b/src/theory/arrays/static_fact_manager.h
index 220bd0437..d40f56e61 100644
--- a/src/theory/arrays/static_fact_manager.h
+++ b/src/theory/arrays/static_fact_manager.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file static_fact_manager.h
** \verbatim
- ** Original author: Clark Barrett
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Clark Barrett, Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Path-compressing, backtrackable union-find using an undo
** stack. Refactored from the UF union-find.
diff --git a/src/theory/arrays/theory_arrays.cpp b/src/theory/arrays/theory_arrays.cpp
index 8f1ba5fca..6add1b55f 100644
--- a/src/theory/arrays/theory_arrays.cpp
+++ b/src/theory/arrays/theory_arrays.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_arrays.cpp
** \verbatim
- ** Original author: Clark Barrett
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): Tim King, Kshitij Bansal, Andrew Reynolds, Dejan Jovanovic
+ ** Top contributors (to current version):
+ ** Clark Barrett, Morgan Deters, Guy Katz
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of the theory of arrays.
**
@@ -21,13 +21,14 @@
#include "expr/kind.h"
#include "options/arrays_options.h"
#include "options/smt_options.h"
+#include "proof/array_proof.h"
+#include "proof/proof_manager.h"
+#include "proof/theory_proof.h"
#include "smt/command.h"
#include "smt/logic_exception.h"
#include "smt/smt_statistics_registry.h"
#include "theory/rewriter.h"
#include "theory/theory_model.h"
-#include "proof/theory_proof.h"
-#include "proof/proof_manager.h"
#include "theory/valuation.h"
using namespace std;
@@ -78,7 +79,7 @@ TheoryArrays::TheoryArrays(context::Context* c, context::UserContext* u,
d_equalityEngine(d_notify, c, name + "theory::arrays::TheoryArrays", true),
d_conflict(c, false),
d_backtracker(c),
- d_infoMap(c, &d_backtracker),
+ d_infoMap(c, &d_backtracker, name),
d_mergeQueue(c),
d_mergeInProgress(false),
d_RowQueue(c),
@@ -98,7 +99,8 @@ TheoryArrays::TheoryArrays(context::Context* c, context::UserContext* u,
d_defValues(c),
d_readTableContext(new context::Context()),
d_arrayMerges(c),
- d_inCheckModel(false)
+ d_inCheckModel(false),
+ d_proofReconstruction(&d_equalityEngine)
{
smtStatisticsRegistry()->registerStat(&d_numRow);
smtStatisticsRegistry()->registerStat(&d_numExt);
@@ -126,6 +128,18 @@ TheoryArrays::TheoryArrays(context::Context* c, context::UserContext* u,
if (d_useArrTable) {
d_equalityEngine.addFunctionKind(kind::ARR_TABLE_FUN);
}
+
+ d_reasonRow = d_equalityEngine.getFreshMergeReasonType();
+ d_reasonRow1 = d_equalityEngine.getFreshMergeReasonType();
+ d_reasonExt = d_equalityEngine.getFreshMergeReasonType();
+
+ d_proofReconstruction.setRowMergeTag(d_reasonRow);
+ d_proofReconstruction.setRow1MergeTag(d_reasonRow1);
+ d_proofReconstruction.setExtMergeTag(d_reasonExt);
+
+ d_equalityEngine.addPathReconstructionTrigger(d_reasonRow, &d_proofReconstruction);
+ d_equalityEngine.addPathReconstructionTrigger(d_reasonRow1, &d_proofReconstruction);
+ d_equalityEngine.addPathReconstructionTrigger(d_reasonExt, &d_proofReconstruction);
}
TheoryArrays::~TheoryArrays() {
@@ -383,21 +397,27 @@ bool TheoryArrays::propagate(TNode literal)
}/* TheoryArrays::propagate(TNode) */
-void TheoryArrays::explain(TNode literal, std::vector<TNode>& assumptions) {
+void TheoryArrays::explain(TNode literal, std::vector<TNode>& assumptions, eq::EqProof *proof) {
// Do the work
bool polarity = literal.getKind() != kind::NOT;
TNode atom = polarity ? literal : literal[0];
//eq::EqProof * eqp = new eq::EqProof;
- eq::EqProof * eqp = NULL;
+ // eq::EqProof * eqp = NULL;
if (atom.getKind() == kind::EQUAL || atom.getKind() == kind::IFF) {
- d_equalityEngine.explainEquality(atom[0], atom[1], polarity, assumptions, eqp);
+ d_equalityEngine.explainEquality(atom[0], atom[1], polarity, assumptions, proof);
} else {
- d_equalityEngine.explainPredicate(atom, polarity, assumptions);
+ d_equalityEngine.explainPredicate(atom, polarity, assumptions, proof);
+ }
+ if(proof){
+ Debug("pf::array") << " Proof is : " << std::endl;
+ proof->debug_print("pf::array");
}
- if( eqp ){
- Debug("array-pf") << " Proof is : " << std::endl;
- eqp->debug_print("array-pf");
+
+ Debug("pf::array") << "Array: explain( " << literal << " ):" << std::endl << "\t";
+ for (unsigned i = 0; i < assumptions.size(); ++i) {
+ Debug("pf::array") << assumptions[i] << " ";
}
+ Debug("pf::array") << std::endl;
}
TNode TheoryArrays::weakEquivGetRep(TNode node) {
@@ -597,7 +617,7 @@ void TheoryArrays::checkWeakEquiv(bool arraysMerged) {
}
}
}
- }
+ }
}
/**
@@ -653,7 +673,7 @@ void TheoryArrays::preRegisterTermInternal(TNode node)
if (ni != node) {
preRegisterTermInternal(ni);
}
- d_equalityEngine.assertEquality(ni.eqNode(s[2]), true, d_true, eq::MERGED_ARRAYS_ROW1);
+ d_equalityEngine.assertEquality(ni.eqNode(s[2]), true, d_true, d_reasonRow1);
Assert(++it == stores->end());
}
}
@@ -739,7 +759,7 @@ void TheoryArrays::preRegisterTermInternal(TNode node)
}
// Apply RIntro1 Rule
- d_equalityEngine.assertEquality(ni.eqNode(v), true, d_true, eq::MERGED_ARRAYS_ROW1);
+ d_equalityEngine.assertEquality(ni.eqNode(v), true, d_true, d_reasonRow1);
}
d_infoMap.addStore(node, node);
@@ -787,6 +807,7 @@ void TheoryArrays::preRegisterTermInternal(TNode node)
else {
d_equalityEngine.addTerm(node);
}
+
break;
}
// Invariant: preregistered terms are exactly the terms in the equality engine
@@ -807,12 +828,16 @@ void TheoryArrays::propagate(Effort e)
}
-Node TheoryArrays::explain(TNode literal)
+Node TheoryArrays::explain(TNode literal) {
+ return explain(literal, NULL);
+}
+
+Node TheoryArrays::explain(TNode literal, eq::EqProof *proof)
{
++d_numExplain;
Debug("arrays") << spaces(getSatContext()->getLevel()) << "TheoryArrays::explain(" << literal << ")" << std::endl;
std::vector<TNode> assumptions;
- explain(literal, assumptions);
+ explain(literal, assumptions, proof);
return mkAnd(assumptions);
}
@@ -1133,7 +1158,7 @@ void TheoryArrays::collectModelInfo( TheoryModel* m, bool fullModel )
TypeSet defaultValuesSet;
// Compute all default values already in use
- if (fullModel) {
+ //if (fullModel) {
for (size_t i=0; i<arrays.size(); ++i) {
TNode nrep = d_equalityEngine.getRepresentative(arrays[i]);
d_mayEqualEqualityEngine.addTerm(nrep); // add the term in case it isn't there already
@@ -1143,14 +1168,14 @@ void TheoryArrays::collectModelInfo( TheoryModel* m, bool fullModel )
defaultValuesSet.add(nrep.getType().getArrayConstituentType(), (*it).second);
}
}
- }
+ //}
// Loop through all array equivalence classes that need a representative computed
for (size_t i=0; i<arrays.size(); ++i) {
TNode n = arrays[i];
TNode nrep = d_equalityEngine.getRepresentative(n);
- if (fullModel) {
+ //if (fullModel) {
// Compute default value for this array - there is one default value for every mayEqual equivalence class
TNode mayRep = d_mayEqualEqualityEngine.getRepresentative(nrep);
it = d_defValues.find(mayRep);
@@ -1171,6 +1196,7 @@ void TheoryArrays::collectModelInfo( TheoryModel* m, bool fullModel )
// Build the STORE_ALL term with the default value
rep = nm->mkConst(ArrayStoreAll(nrep.getType().toType(), rep.toExpr()));
+ /*
}
else {
std::hash_map<Node, Node, NodeHashFunction>::iterator it = d_skolemCache.find(n);
@@ -1182,6 +1208,7 @@ void TheoryArrays::collectModelInfo( TheoryModel* m, bool fullModel )
rep = (*it).second;
}
}
+*/
// For each read, require that the rep stores the right value
vector<Node>& reads = selects[nrep];
@@ -1228,7 +1255,11 @@ Node TheoryArrays::getSkolem(TNode ref, const string& name, const TypeNode& type
makeEqual = false;
}
}
+
+ Debug("pf::array") << "Pregistering a Skolem" << std::endl;
preRegisterTermInternal(skolem);
+ Debug("pf::array") << "Pregistering a Skolem DONE" << std::endl;
+
if (makeEqual) {
Node d = skolem.eqNode(ref);
Debug("arrays-model-based") << "Asserting skolem equality " << d << endl;
@@ -1237,6 +1268,8 @@ Node TheoryArrays::getSkolem(TNode ref, const string& name, const TypeNode& type
d_skolemAssertions.push_back(d);
d_skolemIndex = d_skolemIndex + 1;
}
+
+ Debug("pf::array") << "getSkolem DONE" << std::endl;
return skolem;
}
@@ -1291,28 +1324,76 @@ void TheoryArrays::check(Effort e) {
// Apply ArrDiseq Rule if diseq is between arrays
if(fact[0][0].getType().isArray() && !d_conflict) {
+ if (d_conflict) { Debug("pf::array") << "Entering the skolemization branch" << std::endl; }
+
NodeManager* nm = NodeManager::currentNM();
TypeNode indexType = fact[0][0].getType()[0];
- TNode k = getSkolem(fact,"array_ext_index", indexType, "an extensional lemma index variable from the theory of arrays", false);
+
+ TNode k;
+ // k is the skolem for this disequality.
+ if (!d_proofsEnabled) {
+ Debug("pf::array") << "Check: kind::NOT: array theory making a skolem" << std::endl;
+
+ // If not in replay mode, generate a fresh skolem variable
+ k = getSkolem(fact,
+ "array_ext_index",
+ indexType,
+ "an extensional lemma index variable from the theory of arrays",
+ false);
+
+ // Register this skolem for the proof replay phase
+ PROOF(ProofManager::getSkolemizationManager()->registerSkolem(fact, k));
+ } else {
+ if (!ProofManager::getSkolemizationManager()->hasSkolem(fact)) {
+ // In the solution pass we didn't need this skolem. Therefore, we don't need it
+ // in this reply pass, either.
+ break;
+ }
+
+ // Reuse the same skolem as in the solution pass
+ k = ProofManager::getSkolemizationManager()->getSkolem(fact);
+ Debug("pf::array") << "Skolem = " << k << std::endl;
+ }
Node ak = nm->mkNode(kind::SELECT, fact[0][0], k);
Node bk = nm->mkNode(kind::SELECT, fact[0][1], k);
Node eq = ak.eqNode(bk);
Node lemma = fact[0].orNode(eq.notNode());
+
+ // In solve mode we don't care if ak and bk are registered. If they aren't, they'll be registered
+ // when we output the lemma. However, in replay need the lemma to be propagated, and so we
+ // preregister manually.
+ if (d_proofsEnabled) {
+ if (!d_equalityEngine.hasTerm(ak)) { preRegisterTermInternal(ak); }
+ if (!d_equalityEngine.hasTerm(bk)) { preRegisterTermInternal(bk); }
+ }
+
if (options::arraysPropagate() > 0 && d_equalityEngine.hasTerm(ak) && d_equalityEngine.hasTerm(bk)) {
// Propagate witness disequality - might produce a conflict
d_permRef.push_back(lemma);
- d_equalityEngine.assertEquality(eq, false, lemma, eq::MERGED_ARRAYS_EXT);
+ Debug("pf::array") << "Asserting to the equality engine:" << std::endl
+ << "\teq = " << eq << std::endl
+ << "\treason = " << fact << std::endl;
+
+ d_equalityEngine.assertEquality(eq, false, fact, d_reasonExt);
++d_numProp;
}
- Trace("arrays-lem")<<"Arrays::addExtLemma " << lemma <<"\n";
- d_out->lemma(lemma);
- ++d_numExt;
+
+ if (!d_proofsEnabled) {
+ // If this is the solution pass, generate the lemma. Otherwise, don't generate it -
+ // as this is the lemma that we're reproving...
+ Trace("arrays-lem")<<"Arrays::addExtLemma " << lemma <<"\n";
+ d_out->lemma(lemma);
+ ++d_numExt;
+ }
+ } else {
+ Debug("pf::array") << "Check: kind::NOT: array theory NOT making a skolem" << std::endl;
+ d_modelConstraints.push_back(fact);
}
}
break;
- default:
- Unreachable();
+ default:
+ Unreachable();
}
}
@@ -1387,8 +1468,10 @@ void TheoryArrays::check(Effort e) {
weakEquivBuildCond(r2[0], r[1], conjunctions);
lemma = mkAnd(conjunctions, true);
// LSH FIXME: which kind of arrays lemma is this
+ Trace("arrays-lem") << "Arrays::addExtLemma " << lemma <<"\n";
d_out->lemma(lemma, RULE_INVALID, false, false, true);
d_readTableContext->pop();
+ Trace("arrays") << spaces(getSatContext()->getLevel()) << "Arrays::check(): done" << endl;
return;
}
}
@@ -1399,7 +1482,7 @@ void TheoryArrays::check(Effort e) {
if(!options::arraysEagerLemmas() && fullEffort(e) && !d_conflict && !options::arraysWeakEquivalence()) {
// generate the lemmas on the worklist
- Trace("arrays-lem")<<"Arrays::discharging lemmas: "<<d_RowQueue.size()<<"\n";
+ Trace("arrays-lem")<< "Arrays::discharging lemmas. Number of queued lemmas: " << d_RowQueue.size() << "\n";
while (d_RowQueue.size() > 0 && !d_conflict) {
if (dischargeLemmas()) {
break;
@@ -1594,7 +1677,7 @@ void TheoryArrays::checkRIntro1(TNode a, TNode b)
d_infoMap.setRIntro1Applied(s);
Node ni = nm->mkNode(kind::SELECT, s, s[1]);
preRegisterTermInternal(ni);
- d_equalityEngine.assertEquality(ni.eqNode(s[2]), true, d_true, eq::MERGED_ARRAYS_ROW1);
+ d_equalityEngine.assertEquality(ni.eqNode(s[2]), true, d_true, d_reasonRow1);
}
}
@@ -1863,6 +1946,9 @@ void TheoryArrays::checkRowLemmas(TNode a, TNode b)
void TheoryArrays::propagate(RowLemmaType lem)
{
+ Debug("pf::array") << "TheoryArrays: RowLemma Propagate called. options::arraysPropagate() = "
+ << options::arraysPropagate() << std::endl;
+
TNode a = lem.first;
TNode b = lem.second;
TNode i = lem.third;
@@ -1898,7 +1984,7 @@ void TheoryArrays::propagate(RowLemmaType lem)
if (!bjExists) {
preRegisterTermInternal(bj);
}
- d_equalityEngine.assertEquality(aj_eq_bj, true, reason, eq::MERGED_ARRAYS_ROW);
+ d_equalityEngine.assertEquality(aj_eq_bj, true, reason, d_reasonRow);
++d_numProp;
return;
}
@@ -1908,7 +1994,7 @@ void TheoryArrays::propagate(RowLemmaType lem)
Node i_eq_j = i.eqNode(j);
Node reason = nm->mkNode(kind::OR, i_eq_j, aj_eq_bj);
d_permRef.push_back(reason);
- d_equalityEngine.assertEquality(i_eq_j, true, reason, eq::MERGED_ARRAYS_ROW);
+ d_equalityEngine.assertEquality(i_eq_j, true, reason, d_reasonRow);
++d_numProp;
return;
}
@@ -1917,6 +2003,8 @@ void TheoryArrays::propagate(RowLemmaType lem)
void TheoryArrays::queueRowLemma(RowLemmaType lem)
{
+ Debug("pf::array") << "Array solver: queue row lemma called" << std::endl;
+
if (d_conflict || d_RowAlreadyAdded.contains(lem)) {
return;
}
@@ -1956,15 +2044,20 @@ void TheoryArrays::queueRowLemma(RowLemmaType lem)
// Prefer equality between indexes so as not to introduce new read terms
if (options::arraysEagerIndexSplitting() && !bothExist && !d_equalityEngine.areDisequal(i,j, false)) {
- Node i_eq_j = d_valuation.ensureLiteral(i.eqNode(j));
+ Node i_eq_j;
+ if (!d_proofsEnabled) {
+ i_eq_j = d_valuation.ensureLiteral(i.eqNode(j)); // TODO: think about this
+ } else {
+ i_eq_j = i.eqNode(j);
+ }
+
getOutputChannel().requirePhase(i_eq_j, true);
d_decisionRequests.push(i_eq_j);
}
// TODO: maybe add triggers here
- if (options::arraysEagerLemmas() || bothExist) {
-
+ if ((options::arraysEagerLemmas() || bothExist) && !d_proofsEnabled) {
// Make sure that any terms introduced by rewriting are appropriately stored in the equality database
Node aj2 = Rewriter::rewrite(aj);
if (aj != aj2) {
@@ -2094,6 +2187,7 @@ bool TheoryArrays::dischargeLemmas()
preRegisterTermInternal(bj2);
}
d_equalityEngine.assertEquality(bj.eqNode(bj2), true, d_true);
+
}
if (aj2 == bj2) {
continue;
@@ -2135,18 +2229,31 @@ bool TheoryArrays::dischargeLemmas()
}
void TheoryArrays::conflict(TNode a, TNode b) {
+ Debug("pf::array") << "TheoryArrays::Conflict called" << std::endl;
+ eq::EqProof* proof = d_proofsEnabled ? new eq::EqProof() : NULL;
if (a.getKind() == kind::CONST_BOOLEAN) {
- d_conflictNode = explain(a.iffNode(b));
+ d_conflictNode = explain(a.iffNode(b), proof);
} else {
- d_conflictNode = explain(a.eqNode(b));
+ d_conflictNode = explain(a.eqNode(b), proof);
}
+
if (!d_inCheckModel) {
- d_out->conflict(d_conflictNode);
+ ProofArray* proof_array = NULL;
+
+ if (d_proofsEnabled) {
+ proof->debug_print("pf::array");
+ proof_array = new ProofArray( proof );
+ proof_array->setRowMergeTag(d_reasonRow);
+ proof_array->setRow1MergeTag(d_reasonRow1);
+ proof_array->setExtMergeTag(d_reasonExt);
+ }
+
+ d_out->conflict(d_conflictNode, proof_array);
}
+
d_conflict = true;
}
-
}/* CVC4::theory::arrays namespace */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
diff --git a/src/theory/arrays/theory_arrays.h b/src/theory/arrays/theory_arrays.h
index eba6c000e..c1223474c 100644
--- a/src/theory/arrays/theory_arrays.h
+++ b/src/theory/arrays/theory_arrays.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_arrays.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Dejan Jovanovic, Clark Barrett
- ** Minor contributors (to current version): Tim King, Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Morgan Deters, Clark Barrett, Dejan Jovanovic
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Theory of arrays
**
@@ -23,6 +23,7 @@
#include "context/cdhashset.h"
#include "context/cdqueue.h"
#include "theory/arrays/array_info.h"
+#include "theory/arrays/array_proof_reconstruction.h"
#include "theory/theory.h"
#include "theory/uf/equality_engine.h"
#include "util/statistics_registry.h"
@@ -124,11 +125,20 @@ class TheoryArrays : public Theory {
/** conflicts in setModelVal */
IntStat d_numSetModelValConflicts;
+ // Merge reason types
+
+ /** Merge tag for ROW applications */
+ unsigned d_reasonRow;
+ /** Merge tag for ROW1 applications */
+ unsigned d_reasonRow1;
+ /** Merge tag for EXT applications */
+ unsigned d_reasonExt;
+
public:
TheoryArrays(context::Context* c, context::UserContext* u, OutputChannel& out,
Valuation valuation, const LogicInfo& logicInfo,
- std::string instanceName = "");
+ std::string name = "");
~TheoryArrays();
void setMasterEqualityEngine(eq::EqualityEngine* eq);
@@ -183,7 +193,7 @@ class TheoryArrays : public Theory {
bool propagate(TNode literal);
/** Explain why this literal is true by adding assumptions */
- void explain(TNode literal, std::vector<TNode>& assumptions);
+ void explain(TNode literal, std::vector<TNode>& assumptions, eq::EqProof *proof);
/** For debugging only- checks invariants about when things are preregistered*/
context::CDHashSet<Node, NodeHashFunction > d_isPreRegistered;
@@ -195,6 +205,7 @@ class TheoryArrays : public Theory {
void preRegisterTerm(TNode n);
void propagate(Effort e);
+ Node explain(TNode n, eq::EqProof *proof);
Node explain(TNode n);
/////////////////////////////////////////////////////////////////////////////
@@ -429,6 +440,9 @@ class TheoryArrays : public Theory {
bool d_inCheckModel;
int d_topLevel;
+ /** An equality-engine callback for proof reconstruction */
+ ArrayProofReconstruction d_proofReconstruction;
+
public:
eq::EqualityEngine* getEqualityEngine() {
diff --git a/src/theory/arrays/theory_arrays_rewriter.cpp b/src/theory/arrays/theory_arrays_rewriter.cpp
index 01a7a9584..f1cf1d320 100644
--- a/src/theory/arrays/theory_arrays_rewriter.cpp
+++ b/src/theory/arrays/theory_arrays_rewriter.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_arrays_rewriter.cpp
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arrays/theory_arrays_rewriter.h b/src/theory/arrays/theory_arrays_rewriter.h
index 7753e11b9..de10a861b 100644
--- a/src/theory/arrays/theory_arrays_rewriter.h
+++ b/src/theory/arrays/theory_arrays_rewriter.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_arrays_rewriter.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Morgan Deters, Clark Barrett
- ** Minor contributors (to current version): Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Clark Barrett, Morgan Deters, Dejan Jovanovic
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/arrays/theory_arrays_type_rules.h b/src/theory/arrays/theory_arrays_type_rules.h
index 70e1c1a5b..d817fb179 100644
--- a/src/theory/arrays/theory_arrays_type_rules.h
+++ b/src/theory/arrays/theory_arrays_type_rules.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_arrays_type_rules.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Clark Barrett
- ** Minor contributors (to current version): Christopher L. Conway
+ ** Top contributors (to current version):
+ ** Morgan Deters, Clark Barrett, Guy Katz
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Typing and cardinality rules for the theory of arrays
**
@@ -214,6 +214,15 @@ struct ArraysProperties {
}
};/* struct ArraysProperties */
+
+struct ArrayPartialSelectTypeRule {
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
+ throw (TypeCheckingExceptionPrivate, AssertionException) {
+ Assert(n.getKind() == kind::PARTIAL_SELECT_0 || n.getKind() == kind::PARTIAL_SELECT_1);
+ return nodeManager->integerType();
+ }
+};/* struct ArrayPartialSelectTypeRule */
+
}/* CVC4::theory::arrays namespace */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
diff --git a/src/theory/arrays/type_enumerator.h b/src/theory/arrays/type_enumerator.h
index ace23eb82..0208fe52d 100644
--- a/src/theory/arrays/type_enumerator.h
+++ b/src/theory/arrays/type_enumerator.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file type_enumerator.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Clark Barrett
- ** Minor contributors (to current version): Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Morgan Deters, Clark Barrett, Andrew Reynolds
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief An enumerator for arrays
**
diff --git a/src/theory/arrays/union_find.cpp b/src/theory/arrays/union_find.cpp
index 3f71b350e..7899e85d5 100644
--- a/src/theory/arrays/union_find.cpp
+++ b/src/theory/arrays/union_find.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file union_find.cpp
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Path-compressing, backtrackable union-find using an undo
** stack. Refactored from the UF union-find.
diff --git a/src/theory/arrays/union_find.h b/src/theory/arrays/union_find.h
index aef2b8007..5d59e8dcd 100644
--- a/src/theory/arrays/union_find.h
+++ b/src/theory/arrays/union_find.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file union_find.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Path-compressing, backtrackable union-find using an undo
** stack. Refactored from the UF union-find.
diff --git a/src/theory/atom_requests.cpp b/src/theory/atom_requests.cpp
index 22ae054a3..e3f30cc6e 100644
--- a/src/theory/atom_requests.cpp
+++ b/src/theory/atom_requests.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file atom_requests.cpp
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/atom_requests.h b/src/theory/atom_requests.h
index 313a50730..7f6194192 100644
--- a/src/theory/atom_requests.h
+++ b/src/theory/atom_requests.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file atom_requests.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/booleans/circuit_propagator.cpp b/src/theory/booleans/circuit_propagator.cpp
index cd6b8dc53..297ff6d9f 100644
--- a/src/theory/booleans/circuit_propagator.cpp
+++ b/src/theory/booleans/circuit_propagator.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file circuit_propagator.cpp
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Dejan Jovanovic
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief A non-clausal circuit propagator for Boolean simplification
**
diff --git a/src/theory/booleans/circuit_propagator.h b/src/theory/booleans/circuit_propagator.h
index 169ac6fa7..5a6e46269 100644
--- a/src/theory/booleans/circuit_propagator.h
+++ b/src/theory/booleans/circuit_propagator.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file circuit_propagator.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Dejan Jovanovic
- ** Minor contributors (to current version): Tim King, Clark Barrett
+ ** Top contributors (to current version):
+ ** Morgan Deters, Dejan Jovanovic, Clark Barrett
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief A non-clausal circuit propagator for Boolean simplification
**
diff --git a/src/theory/booleans/theory_bool.cpp b/src/theory/booleans/theory_bool.cpp
index a286f1605..d483ba105 100644
--- a/src/theory/booleans/theory_bool.cpp
+++ b/src/theory/booleans/theory_bool.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_bool.cpp
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Dejan Jovanovic
- ** Minor contributors (to current version): Clark Barrett
+ ** Top contributors (to current version):
+ ** Morgan Deters, Dejan Jovanovic, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief The theory of booleans.
**
diff --git a/src/theory/booleans/theory_bool.h b/src/theory/booleans/theory_bool.h
index dc42fc281..eef379bf9 100644
--- a/src/theory/booleans/theory_bool.h
+++ b/src/theory/booleans/theory_bool.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_bool.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: none
- ** Minor contributors (to current version): Dejan Jovanovic
+ ** Top contributors (to current version):
+ ** Morgan Deters, Tim King, Dejan Jovanovic
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief The theory of booleans
**
diff --git a/src/theory/booleans/theory_bool_rewriter.cpp b/src/theory/booleans/theory_bool_rewriter.cpp
index 05bb99680..cc9eb54b9 100644
--- a/src/theory/booleans/theory_bool_rewriter.cpp
+++ b/src/theory/booleans/theory_bool_rewriter.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_bool_rewriter.cpp
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Kshitij Bansal, Tim King
- ** Minor contributors (to current version): Morgan Deters, Clark Barrett
+ ** Top contributors (to current version):
+ ** Tim King, Dejan Jovanovic, Kshitij Bansal
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/booleans/theory_bool_rewriter.h b/src/theory/booleans/theory_bool_rewriter.h
index f0f0afe87..b7512ad09 100644
--- a/src/theory/booleans/theory_bool_rewriter.h
+++ b/src/theory/booleans/theory_bool_rewriter.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_bool_rewriter.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): Tim King
+ ** Top contributors (to current version):
+ ** Morgan Deters, Dejan Jovanovic, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/booleans/theory_bool_type_rules.h b/src/theory/booleans/theory_bool_type_rules.h
index 9d12e1bb1..050796e50 100644
--- a/src/theory/booleans/theory_bool_type_rules.h
+++ b/src/theory/booleans/theory_bool_type_rules.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_bool_type_rules.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Christopher L. Conway, Morgan Deters
- ** Minor contributors (to current version): Tim King
+ ** Top contributors (to current version):
+ ** Morgan Deters, Dejan Jovanovic, Christopher L. Conway
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add brief comments here ]]
**
diff --git a/src/theory/booleans/type_enumerator.h b/src/theory/booleans/type_enumerator.h
index 3849f8435..3949d15d5 100644
--- a/src/theory/booleans/type_enumerator.h
+++ b/src/theory/booleans/type_enumerator.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file type_enumerator.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: none
- ** Minor contributors (to current version): Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Morgan Deters, Tim King, Andrew Reynolds
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief An enumerator for Booleans
**
diff --git a/src/theory/builtin/theory_builtin.cpp b/src/theory/builtin/theory_builtin.cpp
index 07761b72e..cea66dafe 100644
--- a/src/theory/builtin/theory_builtin.cpp
+++ b/src/theory/builtin/theory_builtin.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_builtin.cpp
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of the builtin theory.
**
diff --git a/src/theory/builtin/theory_builtin.h b/src/theory/builtin/theory_builtin.h
index facc10c67..205db5b4d 100644
--- a/src/theory/builtin/theory_builtin.h
+++ b/src/theory/builtin/theory_builtin.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_builtin.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Built-in theory.
**
diff --git a/src/theory/builtin/theory_builtin_rewriter.cpp b/src/theory/builtin/theory_builtin_rewriter.cpp
index e91c7e411..300a2b0d4 100644
--- a/src/theory/builtin/theory_builtin_rewriter.cpp
+++ b/src/theory/builtin/theory_builtin_rewriter.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_builtin_rewriter.cpp
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Dejan Jovanovic, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/builtin/theory_builtin_rewriter.h b/src/theory/builtin/theory_builtin_rewriter.h
index 83df76d66..9ac259027 100644
--- a/src/theory/builtin/theory_builtin_rewriter.h
+++ b/src/theory/builtin/theory_builtin_rewriter.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_builtin_rewriter.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Dejan Jovanovic, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/builtin/theory_builtin_type_rules.h b/src/theory/builtin/theory_builtin_type_rules.h
index 977a097d0..af25feaa5 100644
--- a/src/theory/builtin/theory_builtin_type_rules.h
+++ b/src/theory/builtin/theory_builtin_type_rules.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_builtin_type_rules.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: none
- ** Minor contributors (to current version): Kshitij Bansal, Tim King, Christopher L. Conway, Andrew Reynolds, Dejan Jovanovic
+ ** Top contributors (to current version):
+ ** Morgan Deters, Dejan Jovanovic, Christopher L. Conway
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Type rules for the builtin theory
**
diff --git a/src/theory/builtin/type_enumerator.h b/src/theory/builtin/type_enumerator.h
index 5ef0e4ab8..3840bb3b1 100644
--- a/src/theory/builtin/type_enumerator.h
+++ b/src/theory/builtin/type_enumerator.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file type_enumerator.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: none
- ** Minor contributors (to current version): Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Morgan Deters, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Enumerator for uninterpreted sorts
**
diff --git a/src/theory/bv/abstraction.cpp b/src/theory/bv/abstraction.cpp
index 27ca61cfd..fdc36ce72 100644
--- a/src/theory/bv/abstraction.cpp
+++ b/src/theory/bv/abstraction.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file abstraction.cpp
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** [[ Add lengthier description here ]]
** \todo document this file
diff --git a/src/theory/bv/abstraction.h b/src/theory/bv/abstraction.h
index cba170d76..5d580f6ce 100644
--- a/src/theory/bv/abstraction.h
+++ b/src/theory/bv/abstraction.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file abstraction.h
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Bitvector theory.
**
diff --git a/src/theory/bv/aig_bitblaster.cpp b/src/theory/bv/aig_bitblaster.cpp
index d84493daf..887daa1bd 100644
--- a/src/theory/bv/aig_bitblaster.cpp
+++ b/src/theory/bv/aig_bitblaster.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file aig_bitblaster.cpp
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief
**
diff --git a/src/theory/bv/bitblast_strategies_template.h b/src/theory/bv/bitblast_strategies_template.h
index bc022a02d..48221aad4 100644
--- a/src/theory/bv/bitblast_strategies_template.h
+++ b/src/theory/bv/bitblast_strategies_template.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file bitblast_strategies_template.h
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters, Tim King
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of bitblasting functions for various operators.
**
diff --git a/src/theory/bv/bitblast_utils.h b/src/theory/bv/bitblast_utils.h
index adaed31c1..a63c548a2 100644
--- a/src/theory/bv/bitblast_utils.h
+++ b/src/theory/bv/bitblast_utils.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file bitblast_utils.h
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Various utility functions for bit-blasting.
**
diff --git a/src/theory/bv/bitblaster_template.h b/src/theory/bv/bitblaster_template.h
index 9c6c4af9b..cfbadbf32 100644
--- a/src/theory/bv/bitblaster_template.h
+++ b/src/theory/bv/bitblaster_template.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file bitblaster_template.h
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Wrapper around the SAT solver used for bitblasting
**
@@ -266,6 +266,8 @@ class EagerBitblaster : public TBitblaster<Node> {
TNodeSet d_bbAtoms;
TNodeSet d_variables;
+ MinisatEmptyNotify d_notify;
+
Node getModelFromSatSolver(TNode a, bool fullModel);
bool isSharedTerm(TNode node);
diff --git a/src/theory/bv/bv_eager_solver.cpp b/src/theory/bv/bv_eager_solver.cpp
index 2af8d04d6..cad59f5ca 100644
--- a/src/theory/bv/bv_eager_solver.cpp
+++ b/src/theory/bv/bv_eager_solver.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file bv_eager_solver.cpp
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Eager bit-blasting solver.
**
diff --git a/src/theory/bv/bv_eager_solver.h b/src/theory/bv/bv_eager_solver.h
index cfc84dae1..7ac05379b 100644
--- a/src/theory/bv/bv_eager_solver.h
+++ b/src/theory/bv/bv_eager_solver.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file bv_eager_solver.h
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Eager bit-blasting solver.
**
diff --git a/src/theory/bv/bv_inequality_graph.cpp b/src/theory/bv/bv_inequality_graph.cpp
index dca679194..f03d3a683 100644
--- a/src/theory/bv/bv_inequality_graph.cpp
+++ b/src/theory/bv/bv_inequality_graph.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file bv_inequality_graph.cpp
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief A graph representation of the currently asserted bv inequalities.
**
diff --git a/src/theory/bv/bv_inequality_graph.h b/src/theory/bv/bv_inequality_graph.h
index 3c67f506f..452172586 100644
--- a/src/theory/bv/bv_inequality_graph.h
+++ b/src/theory/bv/bv_inequality_graph.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file bv_inequality_graph.h
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Algebraic solver.
**
diff --git a/src/theory/bv/bv_quick_check.cpp b/src/theory/bv/bv_quick_check.cpp
index 40ac3d560..0a9ae819d 100644
--- a/src/theory/bv/bv_quick_check.cpp
+++ b/src/theory/bv/bv_quick_check.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file bv_quick_check.cpp
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Wrapper around the SAT solver used for bitblasting.
**
diff --git a/src/theory/bv/bv_quick_check.h b/src/theory/bv/bv_quick_check.h
index 8d2a62287..96f9c246e 100644
--- a/src/theory/bv/bv_quick_check.h
+++ b/src/theory/bv/bv_quick_check.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file bv_quick_check.h
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Sandboxed sat solver for bv quickchecks.
**
diff --git a/src/theory/bv/bv_subtheory.h b/src/theory/bv/bv_subtheory.h
index 402dd6be3..3c5777af9 100644
--- a/src/theory/bv/bv_subtheory.h
+++ b/src/theory/bv/bv_subtheory.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file bv_subtheory.h
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: Andrew Reynolds, Dejan Jovanovic
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Dejan Jovanovic, Andrew Reynolds
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Interface for bit-vectors sub-solvers.
**
diff --git a/src/theory/bv/bv_subtheory_algebraic.cpp b/src/theory/bv/bv_subtheory_algebraic.cpp
index beca25a88..00d337395 100644
--- a/src/theory/bv/bv_subtheory_algebraic.cpp
+++ b/src/theory/bv/bv_subtheory_algebraic.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file bv_subtheory_algebraic.cpp
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Algebraic solver.
**
diff --git a/src/theory/bv/bv_subtheory_algebraic.h b/src/theory/bv/bv_subtheory_algebraic.h
index 03588a78f..0e0e02151 100644
--- a/src/theory/bv/bv_subtheory_algebraic.h
+++ b/src/theory/bv/bv_subtheory_algebraic.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file bv_subtheory_algebraic.h
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Algebraic solver.
**
diff --git a/src/theory/bv/bv_subtheory_bitblast.cpp b/src/theory/bv/bv_subtheory_bitblast.cpp
index e7630bb3f..b7619c4bb 100644
--- a/src/theory/bv/bv_subtheory_bitblast.cpp
+++ b/src/theory/bv/bv_subtheory_bitblast.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file bv_subtheory_bitblast.cpp
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Clark Barrett, Liana Hadarean
- ** Minor contributors (to current version): Morgan Deters, Kshitij Bansal, Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Dejan Jovanovic, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Algebraic solver.
**
diff --git a/src/theory/bv/bv_subtheory_bitblast.h b/src/theory/bv/bv_subtheory_bitblast.h
index c69069109..e9300138b 100644
--- a/src/theory/bv/bv_subtheory_bitblast.h
+++ b/src/theory/bv/bv_subtheory_bitblast.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file bv_subtheory_bitblast.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Liana Hadarean
- ** Minor contributors (to current version): Morgan Deters, Andrew Reynolds, Clark Barrett
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Liana Hadarean, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Algebraic solver.
**
diff --git a/src/theory/bv/bv_subtheory_core.cpp b/src/theory/bv/bv_subtheory_core.cpp
index ec257468e..97cbdb215 100644
--- a/src/theory/bv/bv_subtheory_core.cpp
+++ b/src/theory/bv/bv_subtheory_core.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file bv_subtheory_core.cpp
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Algebraic solver.
**
diff --git a/src/theory/bv/bv_subtheory_core.h b/src/theory/bv/bv_subtheory_core.h
index 0ff193b41..643093327 100644
--- a/src/theory/bv/bv_subtheory_core.h
+++ b/src/theory/bv/bv_subtheory_core.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file bv_subtheory_core.h
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): Dejan Jovanovic, Morgan Deters
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Algebraic solver.
**
diff --git a/src/theory/bv/bv_subtheory_inequality.cpp b/src/theory/bv/bv_subtheory_inequality.cpp
index 7916d941e..7d68f19b2 100644
--- a/src/theory/bv/bv_subtheory_inequality.cpp
+++ b/src/theory/bv/bv_subtheory_inequality.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file bv_subtheory_inequality.cpp
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Algebraic solver.
**
diff --git a/src/theory/bv/bv_subtheory_inequality.h b/src/theory/bv/bv_subtheory_inequality.h
index c9d9dabd3..9607c0296 100644
--- a/src/theory/bv/bv_subtheory_inequality.h
+++ b/src/theory/bv/bv_subtheory_inequality.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file bv_subtheory_inequality.h
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Andrew Reynolds, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Algebraic solver.
**
diff --git a/src/theory/bv/bv_to_bool.cpp b/src/theory/bv/bv_to_bool.cpp
index 66ad4fec0..36772406d 100644
--- a/src/theory/bv/bv_to_bool.cpp
+++ b/src/theory/bv/bv_to_bool.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file bv_to_bool.cpp
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Preprocessing pass that lifts bit-vectors of size 1 to booleans.
**
diff --git a/src/theory/bv/bv_to_bool.h b/src/theory/bv/bv_to_bool.h
index e6c126440..25d67b98e 100644
--- a/src/theory/bv/bv_to_bool.h
+++ b/src/theory/bv/bv_to_bool.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file bv_to_bool.h
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Preprocessing pass that lifts bit-vectors of size 1 to booleans.
**
diff --git a/src/theory/bv/bvintropow2.cpp b/src/theory/bv/bvintropow2.cpp
index 5df170e21..022aaf2fd 100644
--- a/src/theory/bv/bvintropow2.cpp
+++ b/src/theory/bv/bvintropow2.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file bvintropow2.cpp
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/bv/bvintropow2.h b/src/theory/bv/bvintropow2.h
index 774645560..09d3d9259 100644
--- a/src/theory/bv/bvintropow2.h
+++ b/src/theory/bv/bvintropow2.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file bvintropow2.h
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/bv/cd_set_collection.h b/src/theory/bv/cd_set_collection.h
index 5ffe7032a..456552ebd 100644
--- a/src/theory/bv/cd_set_collection.h
+++ b/src/theory/bv/cd_set_collection.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file cd_set_collection.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: none
- ** Minor contributors (to current version): Tim King, Morgan Deters
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/bv/eager_bitblaster.cpp b/src/theory/bv/eager_bitblaster.cpp
index dd561667c..3b54e3794 100644
--- a/src/theory/bv/eager_bitblaster.cpp
+++ b/src/theory/bv/eager_bitblaster.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file eager_bitblaster.cpp
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Tim King, Guy Katz
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief
**
@@ -36,9 +36,14 @@ void BitblastingRegistrar::preRegister(Node n) {
EagerBitblaster::EagerBitblaster(TheoryBV* theory_bv)
: TBitblaster<Node>()
+ , d_satSolver(NULL)
+ , d_bitblastingRegistrar(NULL)
+ , d_nullContext(NULL)
+ , d_cnfStream(NULL)
, d_bv(theory_bv)
, d_bbAtoms()
, d_variables()
+ , d_notify()
{
d_bitblastingRegistrar = new BitblastingRegistrar(this);
d_nullContext = new context::Context();
@@ -50,8 +55,7 @@ EagerBitblaster::EagerBitblaster(TheoryBV* theory_bv)
d_satSolver, d_bitblastingRegistrar, d_nullContext, options::proof(),
"EagerBitblaster");
- MinisatEmptyNotify* notify = new MinisatEmptyNotify();
- d_satSolver->setNotify(notify);
+ d_satSolver->setNotify(&d_notify);
d_bvp = NULL;
}
@@ -95,7 +99,7 @@ void EagerBitblaster::bbAtom(TNode node) {
// asserting that the atom is true iff the definition holds
Node atom_definition = utils::mkNode(kind::IFF, node, atom_bb);
- AlwaysAssert (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER);
+ AlwaysAssert (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER);
storeBBAtom(node, atom_bb);
d_cnfStream->convertAndAssert(atom_definition, false, false, RULE_INVALID, TNode::null());
}
@@ -104,7 +108,7 @@ void EagerBitblaster::storeBBAtom(TNode atom, Node atom_bb) {
if( d_bvp ){
d_bvp->registerAtomBB(atom.toExpr(), atom_bb.toExpr());
}
- d_bbAtoms.insert(atom);
+ d_bbAtoms.insert(atom);
}
void EagerBitblaster::storeBBTerm(TNode node, const Bits& bits) {
@@ -136,13 +140,13 @@ void EagerBitblaster::bbTerm(TNode node, Bits& bits) {
void EagerBitblaster::makeVariable(TNode var, Bits& bits) {
Assert(bits.size() == 0);
for (unsigned i = 0; i < utils::getSize(var); ++i) {
- bits.push_back(utils::mkBitOf(var, i));
+ bits.push_back(utils::mkBitOf(var, i));
}
- d_variables.insert(var);
+ d_variables.insert(var);
}
Node EagerBitblaster::getBBAtom(TNode node) const {
- return node;
+ return node;
}
diff --git a/src/theory/bv/lazy_bitblaster.cpp b/src/theory/bv/lazy_bitblaster.cpp
index ca21e98c4..c821b50cd 100644
--- a/src/theory/bv/lazy_bitblaster.cpp
+++ b/src/theory/bv/lazy_bitblaster.cpp
@@ -1,17 +1,17 @@
/********************* */
/*! \file lazy_bitblaster.cpp
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
- ** \brief Bitblaster for the lazy bv solver.
+ ** \brief Bitblaster for the lazy bv solver.
**
- ** Bitblaster for the lazy bv solver.
+ ** Bitblaster for the lazy bv solver.
**/
#include "bitblaster_template.h"
@@ -123,11 +123,11 @@ void TLazyBitblaster::bbAtom(TNode node) {
}
atom_bb = utils::mkAnd(atoms);
}
- Assert (!atom_bb.isNull());
+ Assert (!atom_bb.isNull());
Node atom_definition = utils::mkNode(kind::IFF, node, atom_bb);
storeBBAtom(node, atom_bb);
d_cnfStream->convertAndAssert(atom_definition, false, false, RULE_INVALID, TNode::null());
- return;
+ return;
}
// the bitblasted definition of the atom
@@ -138,7 +138,7 @@ void TLazyBitblaster::bbAtom(TNode node) {
if (!options::proof()) {
atom_bb = Rewriter::rewrite(atom_bb);
}
-
+
// asserting that the atom is true iff the definition holds
Node atom_definition = utils::mkNode(kind::IFF, node, atom_bb);
storeBBAtom(node, atom_bb);
@@ -150,7 +150,7 @@ void TLazyBitblaster::storeBBAtom(TNode atom, Node atom_bb) {
if( d_bvp != NULL ){
d_bvp->registerAtomBB(atom.toExpr(), atom_bb.toExpr());
}
- d_bbAtoms.insert(atom);
+ d_bbAtoms.insert(atom);
}
void TLazyBitblaster::storeBBTerm(TNode node, const Bits& bits) {
@@ -160,16 +160,16 @@ void TLazyBitblaster::storeBBTerm(TNode node, const Bits& bits) {
bool TLazyBitblaster::hasBBAtom(TNode atom) const {
- return d_bbAtoms.find(atom) != d_bbAtoms.end();
+ return d_bbAtoms.find(atom) != d_bbAtoms.end();
}
void TLazyBitblaster::makeVariable(TNode var, Bits& bits) {
Assert(bits.size() == 0);
for (unsigned i = 0; i < utils::getSize(var); ++i) {
- bits.push_back(utils::mkBitOf(var, i));
+ bits.push_back(utils::mkBitOf(var, i));
}
- d_variables.insert(var);
+ d_variables.insert(var);
}
uint64_t TLazyBitblaster::computeAtomWeight(TNode node, NodeSet& seen) {
@@ -182,7 +182,7 @@ uint64_t TLazyBitblaster::computeAtomWeight(TNode node, NodeSet& seen) {
// cnf conversion ensures the atom represents itself
Node TLazyBitblaster::getBBAtom(TNode node) const {
- return node;
+ return node;
}
void TLazyBitblaster::bbTerm(TNode node, Bits& bits) {
@@ -220,9 +220,9 @@ void TLazyBitblaster::explain(TNode atom, std::vector<TNode>& explanation) {
for (unsigned i = 0; i < literal_explanation.size(); ++i) {
explanation.push_back(d_cnfStream->getNode(literal_explanation[i]));
}
- return;
+ return;
}
-
+
std::vector<prop::SatLiteral> literal_explanation;
d_satSolver->explain(lit, literal_explanation);
for (unsigned i = 0; i < literal_explanation.size(); ++i) {
@@ -285,7 +285,7 @@ bool TLazyBitblaster::solve() {
}
}
Debug("bitvector") << "TLazyBitblaster::solve() asserted atoms " << d_assertedAtoms->size() <<"\n";
- d_satSolverFullModel.set(true);
+ d_satSolverFullModel.set(true);
return prop::SAT_VALUE_TRUE == d_satSolver->solve();
}
@@ -357,11 +357,11 @@ bool TLazyBitblaster::MinisatNotify::notify(prop::SatLiteral lit) {
d_lazyBB->d_explanations->insert(lit, literal_explanation);
} else {
// we propagated it at a lower level
- return true;
+ return true;
}
}
++(d_lazyBB->d_statistics.d_numBitblastingPropagations);
- TNode atom = d_cnf->getNode(lit);
+ TNode atom = d_cnf->getNode(lit);
return d_bv->storePropagation(atom, SUB_BITBLAST);
}
@@ -398,13 +398,13 @@ EqualityStatus TLazyBitblaster::getEqualityStatus(TNode a, TNode b) {
if (a_eq_b == utils::mkTrue()) return theory::EQUALITY_TRUE;
if (!d_satSolverFullModel.get())
- return theory::EQUALITY_UNKNOWN;
-
+ return theory::EQUALITY_UNKNOWN;
+
// Check if cache is valid (invalidated in check and pops)
if (d_bv->d_invalidateModelCache.get()) {
- invalidateModelCache();
+ invalidateModelCache();
}
- d_bv->d_invalidateModelCache.set(false);
+ d_bv->d_invalidateModelCache.set(false);
Node a_value = getTermModel(a, true);
Node b_value = getTermModel(b, true);
@@ -414,10 +414,10 @@ EqualityStatus TLazyBitblaster::getEqualityStatus(TNode a, TNode b) {
if (a_value == b_value) {
Debug("bv-equality-status")<< "theory::EQUALITY_TRUE_IN_MODEL\n";
- return theory::EQUALITY_TRUE_IN_MODEL;
+ return theory::EQUALITY_TRUE_IN_MODEL;
}
Debug("bv-equality-status")<< "theory::EQUALITY_FALSE_IN_MODEL\n";
- return theory::EQUALITY_FALSE_IN_MODEL;
+ return theory::EQUALITY_FALSE_IN_MODEL;
}
@@ -426,9 +426,9 @@ bool TLazyBitblaster::isSharedTerm(TNode node) {
}
bool TLazyBitblaster::hasValue(TNode a) {
- Assert (hasBBTerm(a));
+ Assert (hasBBTerm(a));
Bits bits;
- getBBTerm(a, bits);
+ getBBTerm(a, bits);
for (int i = bits.size() -1; i >= 0; --i) {
prop::SatValue bit_value;
if (d_cnfStream->hasLiteral(bits[i])) {
@@ -456,7 +456,7 @@ Node TLazyBitblaster::getModelFromSatSolver(TNode a, bool fullModel) {
if (!hasBBTerm(a)) {
return fullModel? utils::mkConst(utils::getSize(a), 0u) : Node();
}
-
+
Bits bits;
getBBTerm(a, bits);
Integer value(0);
@@ -486,13 +486,13 @@ void TLazyBitblaster::collectModelInfo(TheoryModel* m, bool fullModel) {
// not actually a leaf of the bit-vector theory
if (d_variables.find(var) == d_variables.end())
continue;
-
- Assert (Theory::theoryOf(var) == theory::THEORY_BV || isSharedTerm(var));
+
+ Assert (Theory::theoryOf(var) == theory::THEORY_BV || isSharedTerm(var));
// only shared terms could not have been bit-blasted
Assert (hasBBTerm(var) || isSharedTerm(var));
-
+
Node const_value = getModelFromSatSolver(var, fullModel);
- Assert (const_value.isNull() || const_value.isConst());
+ Assert (const_value.isNull() || const_value.isConst());
if(const_value != Node()) {
Debug("bitvector-model") << "TLazyBitblaster::collectModelInfo (assert (= "
<< var << " "
diff --git a/src/theory/bv/slicer.cpp b/src/theory/bv/slicer.cpp
index 0e6815f47..150f73ac9 100644
--- a/src/theory/bv/slicer.cpp
+++ b/src/theory/bv/slicer.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file slicer.cpp
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Bitvector theory.
**
diff --git a/src/theory/bv/slicer.h b/src/theory/bv/slicer.h
index 68642784f..4eae27963 100644
--- a/src/theory/bv/slicer.h
+++ b/src/theory/bv/slicer.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file slicer.h
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Bitvector theory.
**
diff --git a/src/theory/bv/theory_bv.cpp b/src/theory/bv/theory_bv.cpp
index 191f70638..2edadce72 100644
--- a/src/theory/bv/theory_bv.cpp
+++ b/src/theory/bv/theory_bv.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_bv.cpp
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Liana Hadarean
- ** Minor contributors (to current version): Tim King, Kshitij Bansal, Clark Barrett, Andrew Reynolds, Morgan Deters, Martin Brain <>
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Tim King, Dejan Jovanovic
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** [[ Add lengthier description here ]]
** \todo document this file
diff --git a/src/theory/bv/theory_bv.h b/src/theory/bv/theory_bv.h
index 1da15abf8..0bbcba9b0 100644
--- a/src/theory/bv/theory_bv.h
+++ b/src/theory/bv/theory_bv.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_bv.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Dejan Jovanovic, Liana Hadarean
- ** Minor contributors (to current version): Clark Barrett, Kshitij Bansal, Tim King, Andrew Reynolds, Martin Brain <>
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Morgan Deters, Dejan Jovanovic
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Bitvector theory.
**
diff --git a/src/theory/bv/theory_bv_rewrite_rules.h b/src/theory/bv/theory_bv_rewrite_rules.h
index 9f3c34e8e..7200d1dec 100644
--- a/src/theory/bv/theory_bv_rewrite_rules.h
+++ b/src/theory/bv/theory_bv_rewrite_rules.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_bv_rewrite_rules.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Liana Hadarean
- ** Minor contributors (to current version): Tim King, Clark Barrett, Morgan Deters
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Dejan Jovanovic, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/bv/theory_bv_rewrite_rules_constant_evaluation.h b/src/theory/bv/theory_bv_rewrite_rules_constant_evaluation.h
index 1f8799682..a7e50974c 100644
--- a/src/theory/bv/theory_bv_rewrite_rules_constant_evaluation.h
+++ b/src/theory/bv/theory_bv_rewrite_rules_constant_evaluation.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_bv_rewrite_rules_constant_evaluation.h
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: Clark Barrett
- ** Minor contributors (to current version): Morgan Deters, Tim King
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Clark Barrett, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/bv/theory_bv_rewrite_rules_core.h b/src/theory/bv/theory_bv_rewrite_rules_core.h
index 185985b3b..395949f03 100644
--- a/src/theory/bv/theory_bv_rewrite_rules_core.h
+++ b/src/theory/bv/theory_bv_rewrite_rules_core.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_bv_rewrite_rules_core.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: none
- ** Minor contributors (to current version): Tim King, Clark Barrett, Liana Hadarean, Morgan Deters
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Liana Hadarean, Clark Barrett
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/bv/theory_bv_rewrite_rules_normalization.h b/src/theory/bv/theory_bv_rewrite_rules_normalization.h
index 0911b6ccf..4abd02e73 100644
--- a/src/theory/bv/theory_bv_rewrite_rules_normalization.h
+++ b/src/theory/bv/theory_bv_rewrite_rules_normalization.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_bv_rewrite_rules_normalization.h
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: Clark Barrett
- ** Minor contributors (to current version): Dejan Jovanovic, Morgan Deters, Tim King
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Clark Barrett, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
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 d5d6c39dd..152a335a5 100644
--- a/src/theory/bv/theory_bv_rewrite_rules_operator_elimination.h
+++ b/src/theory/bv/theory_bv_rewrite_rules_operator_elimination.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_bv_rewrite_rules_operator_elimination.h
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: Morgan Deters, Clark Barrett
- ** Minor contributors (to current version): Tim King
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Clark Barrett, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/bv/theory_bv_rewrite_rules_simplification.h b/src/theory/bv/theory_bv_rewrite_rules_simplification.h
index 4d3b676c9..d84a07780 100644
--- a/src/theory/bv/theory_bv_rewrite_rules_simplification.h
+++ b/src/theory/bv/theory_bv_rewrite_rules_simplification.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_bv_rewrite_rules_simplification.h
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters, Dejan Jovanovic, Tim King, Clark Barrett
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Clark Barrett, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/bv/theory_bv_rewriter.cpp b/src/theory/bv/theory_bv_rewriter.cpp
index 6e2fdf58e..acb12d649 100644
--- a/src/theory/bv/theory_bv_rewriter.cpp
+++ b/src/theory/bv/theory_bv_rewriter.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_bv_rewriter.cpp
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Liana Hadarean
- ** Minor contributors (to current version): Tim King, Clark Barrett, Morgan Deters
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Morgan Deters, Clark Barrett
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/bv/theory_bv_rewriter.h b/src/theory/bv/theory_bv_rewriter.h
index 3f0fa8194..538754a4b 100644
--- a/src/theory/bv/theory_bv_rewriter.h
+++ b/src/theory/bv/theory_bv_rewriter.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_bv_rewriter.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Morgan Deters, Liana Hadarean
- ** Minor contributors (to current version): Tim King
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Morgan Deters, Dejan Jovanovic
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/bv/theory_bv_type_rules.h b/src/theory/bv/theory_bv_type_rules.h
index fbb285fe0..b531129f7 100644
--- a/src/theory/bv/theory_bv_type_rules.h
+++ b/src/theory/bv/theory_bv_type_rules.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_bv_type_rules.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Christopher L. Conway, Liana Hadarean, Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Dejan Jovanovic, Liana Hadarean
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Bitvector theory typing rules
**
diff --git a/src/theory/bv/theory_bv_utils.cpp b/src/theory/bv/theory_bv_utils.cpp
index f57ccec48..f743e2d64 100644
--- a/src/theory/bv/theory_bv_utils.cpp
+++ b/src/theory/bv/theory_bv_utils.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_bv_utils.cpp
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/bv/theory_bv_utils.h b/src/theory/bv/theory_bv_utils.h
index 993be309b..dc3463c84 100644
--- a/src/theory/bv/theory_bv_utils.h
+++ b/src/theory/bv/theory_bv_utils.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_bv_utils.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Liana Hadarean
- ** Minor contributors (to current version): Kshitij Bansal, Clark Barrett, Morgan Deters
+ ** Top contributors (to current version):
+ ** Liana Hadarean, Dejan Jovanovic, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/bv/type_enumerator.h b/src/theory/bv/type_enumerator.h
index da06b1152..39f1e87f6 100644
--- a/src/theory/bv/type_enumerator.h
+++ b/src/theory/bv/type_enumerator.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file type_enumerator.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: none
- ** Minor contributors (to current version): Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Morgan Deters, Tim King, Andrew Reynolds
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief An enumerator for bitvectors
**
diff --git a/src/theory/datatypes/datatypes_rewriter.h b/src/theory/datatypes/datatypes_rewriter.h
index 0c00ed8df..dd2803d30 100644
--- a/src/theory/datatypes/datatypes_rewriter.h
+++ b/src/theory/datatypes/datatypes_rewriter.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file datatypes_rewriter.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): Kshitij Bansal
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Rewriter for the theory of inductive datatypes
**
@@ -200,20 +200,24 @@ public:
}
}
- if(in.getKind() == kind::EQUAL && in[0] == in[1]) {
- return RewriteResponse(REWRITE_DONE,
- NodeManager::currentNM()->mkConst(true));
- }
if(in.getKind() == kind::EQUAL ) {
- std::vector< Node > rew;
- if( checkClash(in[0], in[1], rew) ){
- Trace("datatypes-rewrite") << "Rewrite clashing equality " << in << " to false" << std::endl;
- return RewriteResponse(REWRITE_DONE, NodeManager::currentNM()->mkConst(false));
- }else if( rew.size()==1 && rew[0]!=in ){
- Trace("datatypes-rewrite") << "Rewrite equality " << in << " to " << rew[0] << std::endl;
- return RewriteResponse(REWRITE_AGAIN_FULL, rew[0] );
+ if(in[0] == in[1]) {
+ return RewriteResponse(REWRITE_DONE, NodeManager::currentNM()->mkConst(true));
}else{
- Trace("datatypes-rewrite-debug") << "Did not rewrite equality " << in << " " << in[0].getKind() << " " << in[1].getKind() << std::endl;
+ std::vector< Node > rew;
+ if( checkClash(in[0], in[1], rew) ){
+ Trace("datatypes-rewrite") << "Rewrite clashing equality " << in << " to false" << std::endl;
+ return RewriteResponse(REWRITE_DONE, NodeManager::currentNM()->mkConst(false));
+ //}else if( rew.size()==1 && rew[0]!=in ){
+ // Trace("datatypes-rewrite") << "Rewrite equality " << in << " to " << rew[0] << std::endl;
+ // return RewriteResponse(REWRITE_AGAIN_FULL, rew[0] );
+ }else if( in[1]<in[0] ){
+ Node ins = NodeManager::currentNM()->mkNode(in.getKind(), in[1], in[0]);
+ Trace("datatypes-rewrite") << "Swap equality " << in << " to " << ins << std::endl;
+ return RewriteResponse(REWRITE_DONE, ins);
+ }else{
+ Trace("datatypes-rewrite-debug") << "Did not rewrite equality " << in << " " << in[0].getKind() << " " << in[1].getKind() << std::endl;
+ }
}
}
@@ -256,10 +260,6 @@ public:
/** get instantiate cons */
static Node getInstCons( Node n, const Datatype& dt, int index ) {
Assert( index>=0 && index<(int)dt.getNumConstructors() );
- Type tspec;
- if( dt.isParametric() ){
- tspec = dt[index].getSpecializedConstructorType(n.getType().toType());
- }
std::vector< Node > children;
children.push_back( Node::fromExpr( dt[index].getConstructor() ) );
for( int i=0; i<(int)dt[index].getNumArgs(); i++ ){
diff --git a/src/theory/datatypes/datatypes_sygus.cpp b/src/theory/datatypes/datatypes_sygus.cpp
index 07fb60e57..5bd6680f2 100644
--- a/src/theory/datatypes/datatypes_sygus.cpp
+++ b/src/theory/datatypes/datatypes_sygus.cpp
@@ -1,13 +1,13 @@
/********************* */
-/*! \file theory_datatypes.cpp
+/*! \file datatypes_sygus.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of sygus utilities for theory of datatypes
**
diff --git a/src/theory/datatypes/datatypes_sygus.h b/src/theory/datatypes/datatypes_sygus.h
index b00fade36..0add578f0 100644
--- a/src/theory/datatypes/datatypes_sygus.h
+++ b/src/theory/datatypes/datatypes_sygus.h
@@ -1,13 +1,13 @@
/********************* */
-/*! \file theory_datatypes.h
+/*! \file datatypes_sygus.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Sygus utilities for theory of datatypes
**
diff --git a/src/theory/datatypes/kinds b/src/theory/datatypes/kinds
index c31a462bd..d035f0fa7 100644
--- a/src/theory/datatypes/kinds
+++ b/src/theory/datatypes/kinds
@@ -85,12 +85,6 @@ typerule APPLY_TYPE_ASCRIPTION ::CVC4::theory::datatypes::DatatypeAscriptionType
# constructor applications are constant if they are applied only to constants
construle APPLY_CONSTRUCTOR ::CVC4::theory::datatypes::DatatypeConstructorTypeRule
-## for co-datatypes
-operator MU 2 "a mu operator, first argument is a bound variable, second argument is body"
-typerule MU ::CVC4::theory::datatypes::DatatypeMuTypeRule
-# mu applications are constant expressions
-construle MU ::CVC4::theory::datatypes::DatatypeMuTypeRule
-
constant TUPLE_UPDATE_OP \
::CVC4::TupleUpdate \
::CVC4::TupleUpdateHashFunction \
@@ -99,22 +93,6 @@ constant TUPLE_UPDATE_OP \
parameterized TUPLE_UPDATE TUPLE_UPDATE_OP 2 "tuple update; first parameter is a TUPLE_UPDATE_OP (which references an index), second is the tuple, third is the element to store in the tuple at the given index"
typerule TUPLE_UPDATE ::CVC4::theory::datatypes::TupleUpdateTypeRule
-constant RECORD_TYPE \
- ::CVC4::Record \
- ::CVC4::RecordHashFunction \
- "expr/record.h" \
- "record type"
-cardinality RECORD_TYPE \
- "::CVC4::theory::datatypes::RecordProperties::computeCardinality(%TYPE%)" \
- "theory/datatypes/theory_datatypes_type_rules.h"
-well-founded RECORD_TYPE \
- "::CVC4::theory::datatypes::RecordProperties::isWellFounded(%TYPE%)" \
- "::CVC4::theory::datatypes::RecordProperties::mkGroundTerm(%TYPE%)" \
- "theory/datatypes/theory_datatypes_type_rules.h"
-enumerator RECORD_TYPE \
- "::CVC4::theory::datatypes::RecordEnumerator" \
- "theory/datatypes/type_enumerator.h"
-
constant RECORD_UPDATE_OP \
::CVC4::RecordUpdate \
::CVC4::RecordUpdateHashFunction \
diff --git a/src/theory/datatypes/theory_datatypes.cpp b/src/theory/datatypes/theory_datatypes.cpp
index ad2b1a297..eb8b23973 100644
--- a/src/theory/datatypes/theory_datatypes.cpp
+++ b/src/theory/datatypes/theory_datatypes.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_datatypes.cpp
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): Dejan Jovanovic
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of the theory of datatypes
**
@@ -75,6 +75,12 @@ TheoryDatatypes::TheoryDatatypes(Context* c, UserContext* u, OutputChannel& out,
}
TheoryDatatypes::~TheoryDatatypes() {
+ for(std::map< Node, EqcInfo* >::iterator i = d_eqc_info.begin(), iend = d_eqc_info.end();
+ i != iend; ++i){
+ EqcInfo* current = (*i).second;
+ Assert(current != NULL);
+ delete current;
+ }
}
void TheoryDatatypes::setMasterEqualityEngine(eq::EqualityEngine* eq) {
@@ -91,7 +97,7 @@ TheoryDatatypes::EqcInfo* TheoryDatatypes::getOrMakeEqcInfo( TNode n, bool doMak
std::map< Node, EqcInfo* >::iterator eqc_i = d_eqc_info.find( n );
EqcInfo* ei;
- if( eqc_i!=d_eqc_info.end() ){
+ if( eqc_i != d_eqc_info.end() ){
ei = eqc_i->second;
}else{
ei = new EqcInfo( getSatContext() );
@@ -159,20 +165,19 @@ void TheoryDatatypes::check(Effort e) {
if( e == EFFORT_FULL && !d_conflict && !d_addedLemma && !d_valuation.needCheck() ) {
//check for cycles
Assert( d_pending.empty() && d_pending_merge.empty() );
- bool addedFact;
do {
+ d_addedFact = false;
checkCycles();
- addedFact = !d_pending.empty() || !d_pending_merge.empty();
flushPendingFacts();
if( d_conflict || d_addedLemma ){
return;
}
- }while( addedFact );
+ }while( d_addedFact );
//check for splits
Trace("datatypes-debug") << "Check for splits " << e << endl;
- addedFact = false;
do {
+ d_addedFact = false;
std::map< TypeNode, Node > rec_singletons;
eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( &d_equalityEngine );
while( !eqcs_i.isFinished() ){
@@ -233,9 +238,11 @@ void TheoryDatatypes::check(Effort e) {
//all other cases
std::vector< bool > pcons;
getPossibleCons( eqc, n, pcons );
+ //std::map< int, bool > sel_apps;
+ //getSelectorsForCons( n, sel_apps );
//check if we do not need to resolve the constructor type for this equivalence class.
- // this is if there are no selectors for this equivalence class, its possible values are infinite,
- // and we are not producing a model, then do not split.
+ // this is if there are no selectors for this equivalence class, and its possible values are infinite,
+ // then do not split.
int consIndex = -1;
int fconsIndex = -1;
bool needSplit = true;
@@ -317,7 +324,6 @@ void TheoryDatatypes::check(Effort e) {
++eqcs_i;
}
Trace("datatypes-debug") << "Flush pending facts..." << std::endl;
- addedFact = !d_pending.empty() || !d_pending_merge.empty();
flushPendingFacts();
/*
if( !d_conflict ){
@@ -331,8 +337,8 @@ void TheoryDatatypes::check(Effort e) {
}
}
*/
- }while( !d_conflict && !d_addedLemma && addedFact );
- Trace("datatypes-debug") << "Finished. " << d_conflict << std::endl;
+ }while( !d_conflict && !d_addedLemma && d_addedFact );
+ Trace("datatypes-debug") << "Finished, conflict=" << d_conflict << ", lemmas=" << d_addedLemma << std::endl;
if( !d_conflict ){
Trace("dt-model-debug") << std::endl;
printModelDebug("dt-model-debug");
@@ -347,6 +353,7 @@ void TheoryDatatypes::check(Effort e) {
void TheoryDatatypes::flushPendingFacts(){
doPendingMerges();
+ //pending lemmas: used infrequently, only for definitional lemmas
if( !d_pending_lem.empty() ){
int i = 0;
while( i<(int)d_pending_lem.size() ){
@@ -368,16 +375,31 @@ void TheoryDatatypes::flushPendingFacts(){
Trace("dt-lemma-debug") << "Trivial explanation." << std::endl;
}else{
Trace("dt-lemma-debug") << "Get explanation..." << std::endl;
- Node ee_exp = explain( exp );
- Trace("dt-lemma-debug") << "Explanation : " << ee_exp << std::endl;
- lem = NodeManager::currentNM()->mkNode( OR, ee_exp.negate(), fact );
- lem = Rewriter::rewrite( lem );
+ std::vector< TNode > assumptions;
+ //if( options::dtRExplainLemmas() ){
+ explain( exp, assumptions );
+ //}else{
+ // ee_exp = exp;
+ //}
+ //Trace("dt-lemma-debug") << "Explanation : " << ee_exp << std::endl;
+ if( assumptions.empty() ){
+ lem = fact;
+ }else{
+ std::vector< Node > children;
+ for( unsigned i=0; i<assumptions.size(); i++ ){
+ children.push_back( assumptions[i].negate() );
+ }
+ children.push_back( fact );
+ lem = NodeManager::currentNM()->mkNode( OR, children );
+ }
}
Trace("dt-lemma") << "Datatypes lemma : " << lem << std::endl;
- doSendLemma( lem );
- d_addedLemma = true;
+ if( doSendLemma( lem ) ){
+ d_addedLemma = true;
+ }
}else{
assertFact( fact, exp );
+ d_addedFact = true;
}
Trace("datatypes-debug") << "Finished fact " << fact << ", now = " << d_conflict << " " << d_pending.size() << std::endl;
i++;
@@ -518,8 +540,9 @@ Node TheoryDatatypes::expandDefinition(LogicRequest &logicRequest, Node n) {
if( tst==d_true ){
n_ret = sel;
}else{
- mkExpDefSkolem( selector, n[0].getType(), n.getType() );
- Node sk = NodeManager::currentNM()->mkNode( kind::APPLY_UF, d_exp_def_skolem[ selector ], n[0] );
+ TypeNode ndt = n[0].getType();
+ mkExpDefSkolem( selector, ndt, n.getType() );
+ Node sk = NodeManager::currentNM()->mkNode( kind::APPLY_UF, d_exp_def_skolem[ndt][ selector ], n[0] );
if( tst==NodeManager::currentNM()->mkConst( false ) ){
n_ret = sk;
}else{
@@ -582,20 +605,6 @@ Node TheoryDatatypes::ppRewrite(TNode in) {
return n;
}
- if((t.isTuple() || t.isRecord()) && in.hasAttribute(smt::BooleanTermAttr())) {
- Debug("tuprec") << "should map " << in << " of type " << t << " back to " << in.getAttribute(smt::BooleanTermAttr()).getType() << endl;
- Debug("tuprec") << "so " << t.getDatatype() << " goes to " << in.getAttribute(smt::BooleanTermAttr()).getType().getDatatype() << endl;
- if(t.isTuple()) {
- Debug("tuprec") << "current datatype-tuple-attr is " << t.getAttribute(expr::DatatypeTupleAttr()) << endl;
- Debug("tuprec") << "setting to " << in.getAttribute(smt::BooleanTermAttr()).getType().getAttribute(expr::DatatypeTupleAttr()) << endl;
- t.setAttribute(expr::DatatypeTupleAttr(), in.getAttribute(smt::BooleanTermAttr()).getType().getAttribute(expr::DatatypeTupleAttr()));
- } else {
- Debug("tuprec") << "current datatype-record-attr is " << t.getAttribute(expr::DatatypeRecordAttr()) << endl;
- Debug("tuprec") << "setting to " << in.getAttribute(smt::BooleanTermAttr()).getType().getAttribute(expr::DatatypeRecordAttr()) << endl;
- t.setAttribute(expr::DatatypeRecordAttr(), in.getAttribute(smt::BooleanTermAttr()).getType().getAttribute(expr::DatatypeRecordAttr()));
- }
- }
-
if( in.getKind()==EQUAL ){
Node nn;
std::vector< Node > rew;
@@ -907,10 +916,11 @@ void TheoryDatatypes::eqNotifyDisequal(TNode t1, TNode t2, TNode reason){
}
-TheoryDatatypes::EqcInfo::EqcInfo( context::Context* c ) :
-d_inst( c, false ), d_constructor( c, Node::null() ), d_selectors( c, false ){
-
-}
+TheoryDatatypes::EqcInfo::EqcInfo( context::Context* c )
+ : d_inst( c, false )
+ , d_constructor( c, Node::null() )
+ , d_selectors( c, false )
+{}
bool TheoryDatatypes::hasLabel( EqcInfo* eqc, Node n ){
return ( eqc && !eqc->d_constructor.get().isNull() ) || !getLabel( n ).isNull();
@@ -973,11 +983,22 @@ void TheoryDatatypes::getPossibleCons( EqcInfo* eqc, Node n, std::vector< bool >
}
}
+void TheoryDatatypes::getSelectorsForCons( Node r, std::map< int, bool >& sels ) {
+ NodeListMap::iterator sel_i = d_selector_apps.find( r );
+ if( sel_i != d_selector_apps.end() ){
+ NodeList* sel = (*sel_i).second;
+ for( NodeList::const_iterator j = sel->begin(); j != sel->end(); j++ ){
+ int sindex = Datatype::indexOf( (*j).getOperator().toExpr() );
+ sels[sindex] = true;
+ }
+ }
+}
+
void TheoryDatatypes::mkExpDefSkolem( Node sel, TypeNode dt, TypeNode rt ) {
- if( d_exp_def_skolem.find( sel )==d_exp_def_skolem.end() ){
+ if( d_exp_def_skolem[dt].find( sel )==d_exp_def_skolem[dt].end() ){
std::stringstream ss;
ss << sel << "_uf";
- d_exp_def_skolem[ sel ] = NodeManager::currentNM()->mkSkolem( ss.str().c_str(),
+ d_exp_def_skolem[dt][ sel ] = NodeManager::currentNM()->mkSkolem( ss.str().c_str(),
NodeManager::currentNM()->mkFunctionType( dt, rt ) );
}
}
@@ -1279,7 +1300,8 @@ void TheoryDatatypes::computeCareGraph(){
TNode y = f2[k];
Assert(d_equalityEngine.hasTerm(x));
Assert(d_equalityEngine.hasTerm(y));
- if( areDisequal(x, y) ){
+ //need to consider types for parametric selectors
+ if( x.getType()!=y.getType() || areDisequal(x, y) ){
somePairIsDisequal = true;
break;
}else if( !d_equalityEngine.areEqual( x, y ) ){
@@ -1927,14 +1949,9 @@ bool TheoryDatatypes::mustCommunicateFact( Node n, Node exp ){
//We may need to communicate outwards if the conclusions involve other theories. Also communicate (6) and OR conclusions.
Trace("dt-lemma-debug") << "Compute for " << exp << " => " << n << std::endl;
bool addLemma = false;
- if( n.getKind()==EQUAL || n.getKind()==IFF ){
- /*
- for( unsigned i=0; i<2; i++ ){
- if( !n[i].isVar() && n[i].getKind()!=APPLY_SELECTOR_TOTAL && n[i].getKind()!=APPLY_CONSTRUCTOR ){
- addLemma = true;
- }
- }
- */
+ if( options::dtInferAsLemmas() && exp!=d_true ){
+ addLemma = true;
+ }else if( n.getKind()==EQUAL ){
TypeNode tn = n[0].getType();
if( !DatatypesRewriter::isTypeDatatype( tn ) ){
addLemma = true;
@@ -1942,35 +1959,16 @@ bool TheoryDatatypes::mustCommunicateFact( Node n, Node exp ){
const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
addLemma = dt.involvesExternalType();
}
- //for( int j=0; j<(int)n[1].getNumChildren(); j++ ){
- // if( !DatatypesRewriter::isTermDatatype( n[1][j] ) ){
- // addLemma = true;
- // break;
- // }
- //}
- }else if( n.getKind()==LEQ ){
- addLemma = true;
- }else if( n.getKind()==OR ){
+ }else if( n.getKind()==LEQ || n.getKind()==IFF || n.getKind()==OR ){
addLemma = true;
}
if( addLemma ){
- //check if we have already added this lemma
- //if( std::find( d_inst_lemmas[ n[0] ].begin(), d_inst_lemmas[ n[0] ].end(), n[1] )==d_inst_lemmas[ n[0] ].end() ){
- // d_inst_lemmas[ n[0] ].push_back( n[1] );
Trace("dt-lemma-debug") << "Communicate " << n << std::endl;
return true;
- //}else{
- // Trace("dt-lemma-debug") << "Already communicated " << n << std::endl;
- // return false;
- //}
+ }else{
+ Trace("dt-lemma-debug") << "Do not need to communicate " << n << std::endl;
+ return false;
}
- //else if( exp.getKind()==APPLY_TESTER ){
- //if( n.getKind()==EQUAL && !DatatypesRewriter::isTermDatatype( n[0] ) ){
- // return true;
- //}
- //}
- Trace("dt-lemma-debug") << "Do not need to communicate " << n << std::endl;
- return false;
}
bool TheoryDatatypes::hasTerm( TNode a ){
@@ -2109,6 +2107,40 @@ bool TheoryDatatypes::checkClashModEq( TNode n1, TNode n2, std::vector< Node >&
return false;
}
+std::pair<bool, Node> TheoryDatatypes::entailmentCheck(TNode lit, const EntailmentCheckParameters* params, EntailmentCheckSideEffects* out) {
+ Trace("dt-entail") << "Check entailed : " << lit << std::endl;
+ Node atom = lit.getKind()==NOT ? lit[0] : lit;
+ bool pol = lit.getKind()!=NOT;
+ if( atom.getKind()==APPLY_TESTER ){
+ Node n = atom[0];
+ if( hasTerm( n ) ){
+ Node r = d_equalityEngine.getRepresentative( n );
+ EqcInfo * ei = getOrMakeEqcInfo( r, false );
+ int l_index = getLabelIndex( ei, r );
+ int t_index = (int)Datatype::indexOf( atom.getOperator().toExpr() );
+ Trace("dt-entail") << " Tester indices are " << t_index << " and " << l_index << std::endl;
+ if( l_index!=-1 && (l_index==t_index)==pol ){
+ std::vector< TNode > exp_c;
+ if( ei && !ei->d_constructor.get().isNull() ){
+ explainEquality( n, ei->d_constructor.get(), true, exp_c );
+ }else{
+ Node lbl = getLabel( n );
+ Assert( !lbl.isNull() );
+ exp_c.push_back( lbl );
+ Assert( areEqual( n, lbl[0] ) );
+ explainEquality( n, lbl[0], true, exp_c );
+ }
+ Node exp = mkAnd( exp_c );
+ Trace("dt-entail") << " entailed, explanation is " << exp << std::endl;
+ return make_pair(true, exp);
+ }
+ }
+ }else{
+
+ }
+ return make_pair(false, Node::null());
+}
+
} /* namepsace CVC4::theory::datatypes */
} /* namepsace CVC4::theory */
} /* namepsace CVC4 */
diff --git a/src/theory/datatypes/theory_datatypes.h b/src/theory/datatypes/theory_datatypes.h
index d56538b2a..4bf04e08c 100644
--- a/src/theory/datatypes/theory_datatypes.h
+++ b/src/theory/datatypes/theory_datatypes.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_datatypes.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): Francois Bobot, Dejan Jovanovic
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Theory of datatypes.
**
@@ -87,19 +87,19 @@ private:
d_dt.conflict(t1, t2);
}
void eqNotifyNewClass(TNode t) {
- Debug("dt") << "NotifyClass::eqNotifyNewClass(" << t << std::endl;
+ Debug("dt") << "NotifyClass::eqNotifyNewClass(" << t << ")" << std::endl;
d_dt.eqNotifyNewClass(t);
}
void eqNotifyPreMerge(TNode t1, TNode t2) {
- Debug("dt") << "NotifyClass::eqNotifyPreMerge(" << t1 << ", " << t2 << std::endl;
+ Debug("dt") << "NotifyClass::eqNotifyPreMerge(" << t1 << ", " << t2 << ")" << std::endl;
d_dt.eqNotifyPreMerge(t1, t2);
}
void eqNotifyPostMerge(TNode t1, TNode t2) {
- Debug("dt") << "NotifyClass::eqNotifyPostMerge(" << t1 << ", " << t2 << std::endl;
+ Debug("dt") << "NotifyClass::eqNotifyPostMerge(" << t1 << ", " << t2 << ")" << std::endl;
d_dt.eqNotifyPostMerge(t1, t2);
}
void eqNotifyDisequal(TNode t1, TNode t2, TNode reason) {
- Debug("dt") << "NotifyClass::eqNotifyDisequal(" << t1 << ", " << t2 << ", " << reason << std::endl;
+ Debug("dt") << "NotifyClass::eqNotifyDisequal(" << t1 << ", " << t2 << ", " << reason << ")" << std::endl;
d_dt.eqNotifyDisequal(t1, t2, reason);
}
};/* class TheoryDatatypes::NotifyClass */
@@ -131,9 +131,10 @@ private:
bool hasTester( Node n );
/** get the possible constructors for n */
void getPossibleCons( EqcInfo* eqc, Node n, std::vector< bool >& cons );
+ void getSelectorsForCons( Node r, std::map< int, bool >& sels );
/** mkExpDefSkolem */
- void mkExpDefSkolem( Node sel, TypeNode dt, TypeNode rt );
- /** skolems for terms */
+ void mkExpDefSkolem( Node sel, TypeNode dt, TypeNode rt );
+ /** skolems for terms */
NodeMap d_term_sk;
Node getTermSkolemFor( Node n );
private:
@@ -165,6 +166,7 @@ private:
context::CDO<bool> d_conflict;
/** Added lemma ? */
bool d_addedLemma;
+ bool d_addedFact;
/** The conflict node */
Node d_conflictNode;
/** cache for which terms we have called collectTerms(...) on */
@@ -181,7 +183,7 @@ private:
/** counter for forcing assignments (ensures fairness) */
unsigned d_dtfCounter;
/** expand definition skolem functions */
- std::map< Node, Node > d_exp_def_skolem;
+ std::map< TypeNode, std::map< Node, Node > > d_exp_def_skolem;
/** sygus utilities */
SygusSplit * d_sygus_split;
SygusSymBreak * d_sygus_sym_break;
@@ -260,6 +262,8 @@ public:
std::string identify() const { return std::string("TheoryDatatypes"); }
/** debug print */
void printModelDebug( const char* c );
+ /** entailment check */
+ virtual std::pair<bool, Node> entailmentCheck(TNode lit, const EntailmentCheckParameters* params = NULL, EntailmentCheckSideEffects* out = NULL);
private:
/** add tester to equivalence class info */
void addTester( int ttindex, Node t, EqcInfo* eqc, Node n, Node t_arg );
diff --git a/src/theory/datatypes/theory_datatypes_type_rules.h b/src/theory/datatypes/theory_datatypes_type_rules.h
index 477ce6ba5..5a3645691 100644
--- a/src/theory/datatypes/theory_datatypes_type_rules.h
+++ b/src/theory/datatypes/theory_datatypes_type_rules.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_datatypes_type_rules.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): Tim King
+ ** Top contributors (to current version):
+ ** Morgan Deters, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Theory of datatypes
**
@@ -210,49 +210,6 @@ struct DatatypeAscriptionTypeRule {
}
};/* struct DatatypeAscriptionTypeRule */
-/* For co-datatypes */
-class DatatypeMuTypeRule {
-private:
- //a Mu-expression is constant iff its body is composed of constructors applied to constant expr and bound variables only
- inline static bool computeIsConstNode(TNode n, std::vector< TNode >& fv ){
- if( n.getKind()==kind::MU ){
- fv.push_back( n[0] );
- bool ret = computeIsConstNode( n[1], fv );
- fv.pop_back();
- return ret;
- }else if( n.isConst() || std::find( fv.begin(), fv.end(), n )!=fv.end() ){
- return true;
- }else if( n.getKind()==kind::APPLY_CONSTRUCTOR ){
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- if( !computeIsConstNode( n[i], fv ) ){
- return false;
- }
- }
- return true;
- }else{
- return false;
- }
- }
-public:
- inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check) {
- if( n[0].getKind()!=kind::BOUND_VARIABLE ) {
- std::stringstream ss;
- ss << "expected a bound var for MU expression, got `"
- << n[0] << "'";
- throw TypeCheckingExceptionPrivate(n, ss.str());
- }
- return n[1].getType(check);
- }
- inline static bool computeIsConst(NodeManager* nodeManager, TNode n)
- throw(AssertionException) {
- Assert(n.getKind() == kind::MU);
- NodeManagerScope nms(nodeManager);
- std::vector< TNode > fv;
- return computeIsConstNode( n, fv );
- }
-};
-
-
struct ConstructorProperties {
inline static Cardinality computeCardinality(TypeNode type) {
// Constructors aren't exactly functions, they're like
@@ -276,7 +233,6 @@ struct TupleUpdateTypeRule {
if(check) {
if(!tupleType.isTuple()) {
throw TypeCheckingExceptionPrivate(n, "Tuple-update expression formed over non-tuple");
- tupleType = tupleType.getAttribute(expr::DatatypeTupleAttr());
}
if(tu.getIndex() >= tupleType.getTupleLength()) {
std::stringstream ss;
@@ -313,23 +269,6 @@ struct RecordUpdateTypeRule {
}
};/* struct RecordUpdateTypeRule */
-struct RecordProperties {
- inline static Node mkGroundTerm(TypeNode type) {
- Assert(type.getKind() == kind::RECORD_TYPE);
- return Node::null();
- }
- inline static bool computeIsConst(NodeManager* nodeManager, TNode n) {
- return true;
- }
- inline static Cardinality computeCardinality(TypeNode type) {
- Cardinality card(1);
- return card;
- }
- inline static bool isWellFounded(TypeNode type) {
- return true;
- }
-};/* struct RecordProperties */
-
class DtSizeTypeRule {
public:
inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
diff --git a/src/theory/datatypes/type_enumerator.cpp b/src/theory/datatypes/type_enumerator.cpp
index 77db1968a..6c1155237 100644
--- a/src/theory/datatypes/type_enumerator.cpp
+++ b/src/theory/datatypes/type_enumerator.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file type_enumerator.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Enumerators for datatypes
**
diff --git a/src/theory/datatypes/type_enumerator.h b/src/theory/datatypes/type_enumerator.h
index 1f30498d6..bbfd951b3 100644
--- a/src/theory/datatypes/type_enumerator.h
+++ b/src/theory/datatypes/type_enumerator.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file type_enumerator.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): Dejan Jovanovic
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief An enumerator for datatypes
**
@@ -177,92 +177,6 @@ public:
};/* DatatypesEnumerator */
-
-class RecordEnumerator : public TypeEnumeratorBase<RecordEnumerator> {
- TypeEnumeratorProperties * d_tep;
- TypeEnumerator** d_enumerators;
-
- /** Allocate and initialize the delegate enumerators */
- void newEnumerators() {
- const Record& rec = getType().getConst<Record>();
- d_enumerators = new TypeEnumerator*[rec.getNumFields()];
- for(size_t i = 0; i < rec.getNumFields(); ++i) {
- d_enumerators[i] = new TypeEnumerator(TypeNode::fromType(rec[i].second));
- }
- }
-
- void deleteEnumerators() throw() {
- if(d_enumerators != NULL) {
- const Record& rec = getType().getConst<Record>();
- for(size_t i = 0; i < rec.getNumFields(); ++i) {
- delete d_enumerators[i];
- }
- delete [] d_enumerators;
- d_enumerators = NULL;
- }
- }
-
-public:
-
- RecordEnumerator(TypeNode type, TypeEnumeratorProperties * tep = NULL) throw() :
- TypeEnumeratorBase<RecordEnumerator>(type), d_tep(tep) {
- Assert(type.isRecord());
- newEnumerators();
- }
-
- RecordEnumerator(const RecordEnumerator& re) throw() :
- TypeEnumeratorBase<RecordEnumerator>(re.getType()),
- d_tep(re.d_tep),
- d_enumerators(NULL) {
-
- if(re.d_enumerators != NULL) {
- newEnumerators();
- for(size_t i = 0; i < getType().getNumChildren(); ++i) {
- *d_enumerators[i] = TypeEnumerator(*re.d_enumerators[i]);
- }
- }
- }
-
- virtual ~RecordEnumerator() throw() {
- deleteEnumerators();
- }
-
- Node operator*() throw(NoMoreValuesException) {
- if(isFinished()) {
- throw NoMoreValuesException(getType());
- }
-
-
- return Node::null();
- }
-
- RecordEnumerator& operator++() throw() {
- if(isFinished()) {
- return *this;
- }
-
- size_t i;
- const Record& rec = getType().getConst<Record>();
- for(i = 0; i < rec.getNumFields(); ++i) {
- if(d_enumerators[i]->isFinished()) {
- *d_enumerators[i] = TypeEnumerator(TypeNode::fromType(rec[i].second));
- } else {
- ++*d_enumerators[i];
- return *this;
- }
- }
-
- deleteEnumerators();
-
- return *this;
- }
-
- bool isFinished() throw() {
- return d_enumerators == NULL;
- }
-
-};/* RecordEnumerator */
-
}/* CVC4::theory::datatypes namespace */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
diff --git a/src/theory/example/ecdata.cpp b/src/theory/example/ecdata.cpp
index f9e3b53e7..a85db3cc9 100644
--- a/src/theory/example/ecdata.cpp
+++ b/src/theory/example/ecdata.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file ecdata.cpp
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of equivalence class data for UF theory.
**
diff --git a/src/theory/example/ecdata.h b/src/theory/example/ecdata.h
index 3f4b1b97d..cd582c150 100644
--- a/src/theory/example/ecdata.h
+++ b/src/theory/example/ecdata.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file ecdata.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Context dependent equivalence class datastructure for nodes.
**
diff --git a/src/theory/example/theory_uf_tim.cpp b/src/theory/example/theory_uf_tim.cpp
index 139a811b8..825c8fbe4 100644
--- a/src/theory/example/theory_uf_tim.cpp
+++ b/src/theory/example/theory_uf_tim.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_uf_tim.cpp
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of the theory of uninterpreted functions.
**
diff --git a/src/theory/example/theory_uf_tim.h b/src/theory/example/theory_uf_tim.h
index ef74a04f8..7470b4d57 100644
--- a/src/theory/example/theory_uf_tim.h
+++ b/src/theory/example/theory_uf_tim.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_uf_tim.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief This is a basic implementation of the Theory of Uninterpreted Functions
** with Equality.
diff --git a/src/theory/fp/theory_fp.cpp b/src/theory/fp/theory_fp.cpp
index 18bf993ad..f3212277b 100644
--- a/src/theory/fp/theory_fp.cpp
+++ b/src/theory/fp/theory_fp.cpp
@@ -1,3 +1,20 @@
+/********************* */
+/*! \file theory_fp.cpp
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Martin Brain, Tim King
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2016 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.\endverbatim
+ **
+ ** \brief [[ Add one-line brief description here ]]
+ **
+ ** [[ Add lengthier description here ]]
+ ** \todo document this file
+ **/
+
#include "theory/fp/theory_fp.h"
using namespace std;
diff --git a/src/theory/fp/theory_fp.h b/src/theory/fp/theory_fp.h
index ac2c68ac4..b1915e3b7 100644
--- a/src/theory/fp/theory_fp.h
+++ b/src/theory/fp/theory_fp.h
@@ -1,3 +1,20 @@
+/********************* */
+/*! \file theory_fp.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Martin Brain, Tim King
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2016 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.\endverbatim
+ **
+ ** \brief [[ Add one-line brief description here ]]
+ **
+ ** [[ Add lengthier description here ]]
+ ** \todo document this file
+ **/
+
#include "cvc4_private.h"
#ifndef __CVC4__THEORY__FP__THEORY_FP_H
diff --git a/src/theory/fp/theory_fp_rewriter.cpp b/src/theory/fp/theory_fp_rewriter.cpp
index 59ff4692f..612112db7 100644
--- a/src/theory/fp/theory_fp_rewriter.cpp
+++ b/src/theory/fp/theory_fp_rewriter.cpp
@@ -1,13 +1,14 @@
/********************* */
/*! \file theory_fp_rewriter.cpp
** \verbatim
- ** Original author: Martin Brain
- ** Major contributors:
- ** Minor contributors (to current version):
- ** This file is part of the CVC4 project.
+ ** Top contributors (to current version):
+ ** Martin Brain, Tim King, Clark Barrett
** Copyright (c) 2013 University of Oxford
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Rewrite rules for floating point theories. ]]
**
diff --git a/src/theory/fp/theory_fp_rewriter.h b/src/theory/fp/theory_fp_rewriter.h
index 8a8f1c933..93547b4de 100644
--- a/src/theory/fp/theory_fp_rewriter.h
+++ b/src/theory/fp/theory_fp_rewriter.h
@@ -1,3 +1,20 @@
+/********************* */
+/*! \file theory_fp_rewriter.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Martin Brain
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2016 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.\endverbatim
+ **
+ ** \brief [[ Add one-line brief description here ]]
+ **
+ ** [[ Add lengthier description here ]]
+ ** \todo document this file
+ **/
+
#include "cvc4_private.h"
#ifndef __CVC4__THEORY__FP__THEORY_FP_REWRITER_H
diff --git a/src/theory/fp/theory_fp_type_rules.h b/src/theory/fp/theory_fp_type_rules.h
index 2c9a67984..f9bf2e432 100644
--- a/src/theory/fp/theory_fp_type_rules.h
+++ b/src/theory/fp/theory_fp_type_rules.h
@@ -1,3 +1,20 @@
+/********************* */
+/*! \file theory_fp_type_rules.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Martin Brain
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2016 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.\endverbatim
+ **
+ ** \brief [[ Add one-line brief description here ]]
+ **
+ ** [[ Add lengthier description here ]]
+ ** \todo document this file
+ **/
+
#include "cvc4_private.h"
#ifndef __CVC4__THEORY__FP__THEORY_FP_TYPE_RULES_H
diff --git a/src/theory/idl/idl_assertion.cpp b/src/theory/idl/idl_assertion.cpp
index c6a1a5c0e..1d42f771d 100644
--- a/src/theory/idl/idl_assertion.cpp
+++ b/src/theory/idl/idl_assertion.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file idl_assertion.cpp
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/idl/idl_assertion.h b/src/theory/idl/idl_assertion.h
index 9a31f283d..5db1db0fe 100644
--- a/src/theory/idl/idl_assertion.h
+++ b/src/theory/idl/idl_assertion.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file idl_assertion.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/idl/idl_assertion_db.cpp b/src/theory/idl/idl_assertion_db.cpp
index f2c29cb20..c08cb644f 100644
--- a/src/theory/idl/idl_assertion_db.cpp
+++ b/src/theory/idl/idl_assertion_db.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file idl_assertion_db.cpp
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/idl/idl_assertion_db.h b/src/theory/idl/idl_assertion_db.h
index 23f5e84d5..6481deba5 100644
--- a/src/theory/idl/idl_assertion_db.h
+++ b/src/theory/idl/idl_assertion_db.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file idl_assertion_db.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/idl/idl_model.cpp b/src/theory/idl/idl_model.cpp
index 848399fbc..4d2071962 100644
--- a/src/theory/idl/idl_model.cpp
+++ b/src/theory/idl/idl_model.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file idl_model.cpp
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/idl/idl_model.h b/src/theory/idl/idl_model.h
index 5a284457a..35663a256 100644
--- a/src/theory/idl/idl_model.h
+++ b/src/theory/idl/idl_model.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file idl_model.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/idl/theory_idl.cpp b/src/theory/idl/theory_idl.cpp
index 815f5e76a..8f85dc9b0 100644
--- a/src/theory/idl/theory_idl.cpp
+++ b/src/theory/idl/theory_idl.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_idl.cpp
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/idl/theory_idl.h b/src/theory/idl/theory_idl.h
index 7c879e722..1d2aecad6 100644
--- a/src/theory/idl/theory_idl.h
+++ b/src/theory/idl/theory_idl.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_idl.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/interrupted.h b/src/theory/interrupted.h
index 6c59146e1..e56f3513c 100644
--- a/src/theory/interrupted.h
+++ b/src/theory/interrupted.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file interrupted.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief An exception signaling that a Theory should immediately
** stop performing processing
diff --git a/src/theory/ite_utilities.cpp b/src/theory/ite_utilities.cpp
index 2791a9555..6fab100de 100644
--- a/src/theory/ite_utilities.cpp
+++ b/src/theory/ite_utilities.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file ite_utilities.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Kshitij Bansal, Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters, Kshitij Bansal
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Simplifications for ITE expressions
**
@@ -657,6 +657,8 @@ ITESimplifier::NodeVec* ITESimplifier::computeConstantLeaves(TNode ite){
// special case 2 constant children
if(thenB.isConst() && elseB.isConst()){
NodeVec* pair = new NodeVec(2);
+ d_allocatedConstantLeaves.push_back(pair);
+
(*pair)[0] = std::min(thenB, elseB);
(*pair)[1] = std::max(thenB, elseB);
d_constantLeaves[ite] = pair;
@@ -694,6 +696,7 @@ ITESimplifier::NodeVec* ITESimplifier::computeConstantLeaves(TNode ite){
}
NodeVec* both = new NodeVec(defChildren->size()+maybeChildren->size());
+ d_allocatedConstantLeaves.push_back(both);
NodeVec::iterator newEnd;
newEnd = std::set_union(defChildren->begin(), defChildren->end(),
maybeChildren->begin(), maybeChildren->end(),
@@ -1399,25 +1402,32 @@ Node ITESimplifier::simpITE(TNode assertion)
}
ITECareSimplifier::ITECareSimplifier()
- : d_usedSets()
+ : d_careSetsOutstanding(0)
+ , d_usedSets()
{
d_true = NodeManager::currentNM()->mkConst<bool>(true);
d_false = NodeManager::currentNM()->mkConst<bool>(false);
}
-ITECareSimplifier::~ITECareSimplifier(){}
+ITECareSimplifier::~ITECareSimplifier(){
+ Assert(d_usedSets.empty());
+ Assert(d_careSetsOutstanding == 0);
+}
void ITECareSimplifier::clear(){
- d_usedSets.clear();
+ Assert(d_usedSets.empty());
+ Assert(d_careSetsOutstanding == 0);
}
ITECareSimplifier::CareSetPtr ITECareSimplifier::getNewSet()
{
if (d_usedSets.empty()) {
+ d_careSetsOutstanding++;
return ITECareSimplifier::CareSetPtr::mkNew(*this);
}
else {
- ITECareSimplifier::CareSetPtr cs = ITECareSimplifier::CareSetPtr::recycle(d_usedSets.back());
+ ITECareSimplifier::CareSetPtr cs =
+ ITECareSimplifier::CareSetPtr::recycle(d_usedSets.back());
cs.getCareSet().clear();
d_usedSets.pop_back();
return cs;
@@ -1488,125 +1498,144 @@ Node ITECareSimplifier::substitute(TNode e, TNodeMap& substTable, TNodeMap& cach
Node ITECareSimplifier::simplifyWithCare(TNode e)
{
TNodeMap substTable;
- CareMap queue;
- CareMap::iterator it;
- ITECareSimplifier::CareSetPtr cs = getNewSet();
- ITECareSimplifier::CareSetPtr cs2;
- queue[e] = cs;
-
- TNode v;
- bool done;
- unsigned i;
-
- while (!queue.empty()) {
- it = queue.end();
- --it;
- v = it->first;
- cs = it->second;
- set<Node>& css = cs.getCareSet();
- queue.erase(v);
-
- done = false;
- set<Node>::iterator iCare, iCareEnd = css.end();
-
- switch (v.getKind()) {
- case kind::ITE: {
- iCare = css.find(v[0]);
- if (iCare != iCareEnd) {
- Assert(substTable.find(v) == substTable.end());
- substTable[v] = v[1];
- updateQueue(queue, v[1], cs);
- done = true;
- break;
- }
- else {
- iCare = css.find(v[0].negate());
+
+ /* This extra block is to trigger the destructors for cs and cs2
+ * before starting garbage collection.
+ */
+ {
+ CareMap queue;
+ CareMap::iterator it;
+ ITECareSimplifier::CareSetPtr cs = getNewSet();
+ ITECareSimplifier::CareSetPtr cs2;
+ queue[e] = cs;
+
+ TNode v;
+ bool done;
+ unsigned i;
+
+ while (!queue.empty()) {
+ it = queue.end();
+ --it;
+ v = it->first;
+ cs = it->second;
+ set<Node>& css = cs.getCareSet();
+ queue.erase(v);
+
+ done = false;
+ set<Node>::iterator iCare, iCareEnd = css.end();
+
+ switch (v.getKind()) {
+ case kind::ITE: {
+ iCare = css.find(v[0]);
if (iCare != iCareEnd) {
Assert(substTable.find(v) == substTable.end());
- substTable[v] = v[2];
- updateQueue(queue, v[2], cs);
+ substTable[v] = v[1];
+ updateQueue(queue, v[1], cs);
done = true;
break;
}
- }
- updateQueue(queue, v[0], cs);
- cs2 = getNewSet();
- cs2.getCareSet() = css;
- cs2.getCareSet().insert(v[0]);
- updateQueue(queue, v[1], cs2);
- cs2 = getNewSet();
- cs2.getCareSet() = css;
- cs2.getCareSet().insert(v[0].negate());
- updateQueue(queue, v[2], cs2);
- done = true;
- break;
- }
- case kind::AND: {
- for (i = 0; i < v.getNumChildren(); ++i) {
- iCare = css.find(v[i].negate());
- if (iCare != iCareEnd) {
- Assert(substTable.find(v) == substTable.end());
- substTable[v] = d_false;
- done = true;
- break;
+ else {
+ iCare = css.find(v[0].negate());
+ if (iCare != iCareEnd) {
+ Assert(substTable.find(v) == substTable.end());
+ substTable[v] = v[2];
+ updateQueue(queue, v[2], cs);
+ done = true;
+ break;
+ }
}
+ updateQueue(queue, v[0], cs);
+ cs2 = getNewSet();
+ cs2.getCareSet() = css;
+ cs2.getCareSet().insert(v[0]);
+ updateQueue(queue, v[1], cs2);
+ cs2 = getNewSet();
+ cs2.getCareSet() = css;
+ cs2.getCareSet().insert(v[0].negate());
+ updateQueue(queue, v[2], cs2);
+ done = true;
+ break;
}
- if (done) break;
-
- Assert(v.getNumChildren() > 1);
- updateQueue(queue, v[0], cs);
- cs2 = getNewSet();
- cs2.getCareSet() = css;
- cs2.getCareSet().insert(v[0]);
- for (i = 1; i < v.getNumChildren(); ++i) {
- updateQueue(queue, v[i], cs2);
- }
- done = true;
- break;
- }
- case kind::OR: {
- for (i = 0; i < v.getNumChildren(); ++i) {
- iCare = css.find(v[i]);
- if (iCare != iCareEnd) {
- Assert(substTable.find(v) == substTable.end());
- substTable[v] = d_true;
- done = true;
- break;
+ case kind::AND: {
+ for (i = 0; i < v.getNumChildren(); ++i) {
+ iCare = css.find(v[i].negate());
+ if (iCare != iCareEnd) {
+ Assert(substTable.find(v) == substTable.end());
+ substTable[v] = d_false;
+ done = true;
+ break;
+ }
+ }
+ if (done) break;
+
+ Assert(v.getNumChildren() > 1);
+ updateQueue(queue, v[0], cs);
+ cs2 = getNewSet();
+ cs2.getCareSet() = css;
+ cs2.getCareSet().insert(v[0]);
+ for (i = 1; i < v.getNumChildren(); ++i) {
+ updateQueue(queue, v[i], cs2);
}
+ done = true;
+ break;
}
- if (done) break;
-
- Assert(v.getNumChildren() > 1);
- updateQueue(queue, v[0], cs);
- cs2 = getNewSet();
- cs2.getCareSet() = css;
- cs2.getCareSet().insert(v[0].negate());
- for (i = 1; i < v.getNumChildren(); ++i) {
- updateQueue(queue, v[i], cs2);
+ case kind::OR: {
+ for (i = 0; i < v.getNumChildren(); ++i) {
+ iCare = css.find(v[i]);
+ if (iCare != iCareEnd) {
+ Assert(substTable.find(v) == substTable.end());
+ substTable[v] = d_true;
+ done = true;
+ break;
+ }
+ }
+ if (done) break;
+
+ Assert(v.getNumChildren() > 1);
+ updateQueue(queue, v[0], cs);
+ cs2 = getNewSet();
+ cs2.getCareSet() = css;
+ cs2.getCareSet().insert(v[0].negate());
+ for (i = 1; i < v.getNumChildren(); ++i) {
+ updateQueue(queue, v[i], cs2);
+ }
+ done = true;
+ break;
}
- done = true;
- break;
+ default:
+ break;
}
- default:
- break;
- }
- if (done) {
- continue;
- }
+ if (done) {
+ continue;
+ }
- for (unsigned i = 0; i < v.getNumChildren(); ++i) {
- updateQueue(queue, v[i], cs);
+ for (unsigned i = 0; i < v.getNumChildren(); ++i) {
+ updateQueue(queue, v[i], cs);
+ }
}
}
+ /* Perform garbage collection. */
while (!d_usedSets.empty()) {
- delete d_usedSets.back();
+ CareSetPtrVal* used = d_usedSets.back();
d_usedSets.pop_back();
+ Assert(used->safeToGarbageCollect());
+ delete used;
+ Assert(d_careSetsOutstanding > 0);
+ d_careSetsOutstanding--;
}
TNodeMap cache;
return substitute(e, substTable, cache);
}
+ITECareSimplifier::CareSetPtr ITECareSimplifier::CareSetPtr::mkNew(
+ ITECareSimplifier& simp) {
+ CareSetPtrVal* val = new CareSetPtrVal(simp);
+ return CareSetPtr(val);
+}
+
+
+
} /* namespace theory */
} /* namespace CVC4 */
diff --git a/src/theory/ite_utilities.h b/src/theory/ite_utilities.h
index 10fe2853b..98141d4e3 100644
--- a/src/theory/ite_utilities.h
+++ b/src/theory/ite_utilities.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file ite_utilities.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Simplifications for ITE expressions
**
@@ -133,7 +133,7 @@ public:
private:
typedef std::hash_map<Node, uint32_t, NodeHashFunction> NodeCountMap;
NodeCountMap d_termITEHeight;
-};
+}; /* class TermITEHeightCounter */
/**
* A routine designed to undo the potentially large blow up
@@ -177,7 +177,7 @@ private:
~Statistics();
};
Statistics d_statistics;
-};
+}; /* class ITECompressor */
class ITESimplifier {
public:
@@ -302,6 +302,15 @@ public:
void clear();
private:
+
+ /**
+ * This should always equal the number of care sets allocated by
+ * this object - the number of these that have been deleted. This is
+ * initially 0 and should always be 0 at the *start* of
+ * ~ITECareSimplifier().
+ */
+ unsigned d_careSetsOutstanding;
+
Node d_true;
Node d_false;
@@ -309,12 +318,16 @@ private:
class CareSetPtr;
class CareSetPtrVal {
+ public:
+ bool safeToGarbageCollect() const { return d_refCount == 0; }
+ private:
friend class ITECareSimplifier::CareSetPtr;
ITECareSimplifier& d_iteSimplifier;
unsigned d_refCount;
std::set<Node> d_careSet;
- CareSetPtrVal(ITECareSimplifier& simp) : d_iteSimplifier(simp), d_refCount(1) {}
- };
+ CareSetPtrVal(ITECareSimplifier& simp)
+ : d_iteSimplifier(simp), d_refCount(1) {}
+ }; /* class ITECareSimplifier::CareSetPtrVal */
std::vector<CareSetPtrVal*> d_usedSets;
void careSetPtrGC(CareSetPtrVal* val) {
@@ -350,16 +363,14 @@ private:
return *this;
}
std::set<Node>& getCareSet() { return d_val->d_careSet; }
- static CareSetPtr mkNew(ITECareSimplifier& simp) {
- CareSetPtrVal* val = new CareSetPtrVal(simp);
- return CareSetPtr(val);
- }
+
+ static CareSetPtr mkNew(ITECareSimplifier& simp);
static CareSetPtr recycle(CareSetPtrVal* val) {
Assert(val != NULL && val->d_refCount == 0);
val->d_refCount = 1;
return CareSetPtr(val);
}
- };
+ }; /* class ITECareSimplifier::CareSetPtr */
CareSetPtr getNewSet();
diff --git a/src/theory/logic_info.cpp b/src/theory/logic_info.cpp
index fb689609d..04cac7ae5 100644
--- a/src/theory/logic_info.cpp
+++ b/src/theory/logic_info.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file logic_info.cpp
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: none
- ** Minor contributors (to current version): Dejan Jovanovic, Tianyi Liang, Kshitij Bansal, Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Morgan Deters, Tim King, Andrew Reynolds
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief A class giving information about a logic (group a theory modules
** and configuration information)
diff --git a/src/theory/logic_info.h b/src/theory/logic_info.h
index 6d7297c63..6efdd4615 100644
--- a/src/theory/logic_info.h
+++ b/src/theory/logic_info.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file logic_info.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: none
- ** Minor contributors (to current version): Dejan Jovanovic, Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Morgan Deters, Tim King, Dejan Jovanovic
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief A class giving information about a logic (group a theory modules
** and configuration information)
diff --git a/src/theory/output_channel.h b/src/theory/output_channel.h
index d5c12457a..639793c7f 100644
--- a/src/theory/output_channel.h
+++ b/src/theory/output_channel.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file output_channel.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: none
- ** Minor contributors (to current version): Andrew Reynolds, Dejan Jovanovic, Tim King
+ ** Top contributors (to current version):
+ ** Morgan Deters, Liana Hadarean, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief The theory output channel interface
**
@@ -142,7 +142,6 @@ public:
return lemma(n, RULE_INVALID, removable, preprocess, sendAtoms);
}
-
/**
* Request a split on a new theory atom. This is equivalent to
* calling lemma({OR n (NOT n)}).
diff --git a/src/theory/quantifiers/alpha_equivalence.cpp b/src/theory/quantifiers/alpha_equivalence.cpp
index b72f15a01..80066d690 100644
--- a/src/theory/quantifiers/alpha_equivalence.cpp
+++ b/src/theory/quantifiers/alpha_equivalence.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file alpha_equivalence.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2015 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Alpha equivalence checking
**
@@ -29,7 +29,7 @@ struct sortTypeOrder {
}
};
-bool AlphaEquivalenceNode::registerNode( AlphaEquivalenceNode* aen, QuantifiersEngine* qe, Node q, std::vector< Node >& tt, std::vector< int >& arg_index ) {
+Node AlphaEquivalenceNode::registerNode( AlphaEquivalenceNode* aen, QuantifiersEngine* qe, Node q, std::vector< Node >& tt, std::vector< int >& arg_index ) {
while( !tt.empty() ){
if( tt.size()==arg_index.size()+1 ){
Node t = tt.back();
@@ -49,21 +49,25 @@ bool AlphaEquivalenceNode::registerNode( AlphaEquivalenceNode* aen, QuantifiersE
}
}
}
+ Node lem;
Trace("aeq-debug") << std::endl;
if( aen->d_quant.isNull() ){
aen->d_quant = q;
- return true;
}else{
- //lemma ( q <=> d_quant )
- Trace("quant-ae") << "Alpha equivalent : " << std::endl;
- Trace("quant-ae") << " " << q << std::endl;
- Trace("quant-ae") << " " << aen->d_quant << std::endl;
- qe->getOutputChannel().lemma( q.iffNode( aen->d_quant ) );
- return false;
+ if( q.getNumChildren()==2 ){
+ //lemma ( q <=> d_quant )
+ Trace("quant-ae") << "Alpha equivalent : " << std::endl;
+ Trace("quant-ae") << " " << q << std::endl;
+ Trace("quant-ae") << " " << aen->d_quant << std::endl;
+ lem = q.iffNode( aen->d_quant );
+ }else{
+ //do not reduce annotated quantified formulas based on alpha equivalence
+ }
}
+ return lem;
}
-bool AlphaEquivalenceTypeNode::registerNode( AlphaEquivalenceTypeNode* aetn,
+Node AlphaEquivalenceTypeNode::registerNode( AlphaEquivalenceTypeNode* aetn,
QuantifiersEngine* qe, Node q, Node t, std::vector< TypeNode >& typs, std::map< TypeNode, int >& typ_count, int index ){
while( index<(int)typs.size() ){
TypeNode curr = typs[index];
@@ -79,7 +83,7 @@ bool AlphaEquivalenceTypeNode::registerNode( AlphaEquivalenceTypeNode* aetn,
return AlphaEquivalenceNode::registerNode( &(aetn->d_data), qe, q, tt, arg_index );
}
-bool AlphaEquivalence::registerQuantifier( Node q ) {
+Node AlphaEquivalence::reduceQuantifier( Node q ) {
Assert( q.getKind()==FORALL );
Trace("aeq") << "Alpha equivalence : register " << q << std::endl;
//construct canonical quantified formula
@@ -99,7 +103,7 @@ bool AlphaEquivalence::registerQuantifier( Node q ) {
sto.d_tdb = d_qe->getTermDatabase();
std::sort( typs.begin(), typs.end(), sto );
Trace("aeq-debug") << " ";
- bool ret = AlphaEquivalenceTypeNode::registerNode( &d_ae_typ_trie, d_qe, q, t, typs, typ_count );
+ Node ret = AlphaEquivalenceTypeNode::registerNode( &d_ae_typ_trie, d_qe, q, t, typs, typ_count );
Trace("aeq") << " ...result : " << ret << std::endl;
return ret;
}
diff --git a/src/theory/quantifiers/alpha_equivalence.h b/src/theory/quantifiers/alpha_equivalence.h
index 99517fd2a..8e7556eb6 100644
--- a/src/theory/quantifiers/alpha_equivalence.h
+++ b/src/theory/quantifiers/alpha_equivalence.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file alpha_equivalence.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2015 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Alpha equivalence checking
**/
@@ -28,14 +28,14 @@ class AlphaEquivalenceNode {
public:
std::map< Node, std::map< int, AlphaEquivalenceNode > > d_children;
Node d_quant;
- static bool registerNode( AlphaEquivalenceNode* aen, QuantifiersEngine* qe, Node q, std::vector< Node >& tt, std::vector< int >& arg_index );
+ static Node registerNode( AlphaEquivalenceNode* aen, QuantifiersEngine* qe, Node q, std::vector< Node >& tt, std::vector< int >& arg_index );
};
class AlphaEquivalenceTypeNode {
public:
std::map< TypeNode, std::map< int, AlphaEquivalenceTypeNode > > d_children;
AlphaEquivalenceNode d_data;
- static bool registerNode( AlphaEquivalenceTypeNode* aetn,
+ static Node registerNode( AlphaEquivalenceTypeNode* aetn,
QuantifiersEngine* qe, Node q, Node t, std::vector< TypeNode >& typs, std::map< TypeNode, int >& typ_count, int index = 0 );
};
@@ -47,8 +47,8 @@ private:
public:
AlphaEquivalence( QuantifiersEngine* qe ) : d_qe( qe ){}
~AlphaEquivalence(){}
-
- bool registerQuantifier( Node q );
+ /** reduce quantifier, return value (if non-null) is lemma justifying why q ia reducible. */
+ Node reduceQuantifier( Node q );
};
}
diff --git a/src/theory/quantifiers/ambqi_builder.cpp b/src/theory/quantifiers/ambqi_builder.cpp
index b18676cbc..5192da7de 100644
--- a/src/theory/quantifiers/ambqi_builder.cpp
+++ b/src/theory/quantifiers/ambqi_builder.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file ambqi_builder.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Tim King, Andrew Reynolds
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of abstract MBQI builder
**/
@@ -159,7 +159,7 @@ bool AbsDef::addInstantiations( FirstOrderModelAbs * m, QuantifiersEngine * qe,
return true;
}else{
if( depth==q[0].getNumChildren() ){
- if( qe->addInstantiation( q, terms ) ){
+ if( qe->addInstantiation( q, terms, true ) ){
Trace("ambqi-inst-debug") << "-> Added instantiation." << std::endl;
inst++;
return true;
@@ -190,7 +190,7 @@ bool AbsDef::addInstantiations( FirstOrderModelAbs * m, QuantifiersEngine * qe,
success = true;
}
}
- }while( !success && index<32 );
+ }while( !qe->inConflict() && !success && index<32 );
//mark if we are incomplete
osuccess = osuccess && success;
}
diff --git a/src/theory/quantifiers/ambqi_builder.h b/src/theory/quantifiers/ambqi_builder.h
index b2c49c8a3..3669d38b7 100644
--- a/src/theory/quantifiers/ambqi_builder.h
+++ b/src/theory/quantifiers/ambqi_builder.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file ambqi_builder.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Tim King, Clark Barrett
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Abstract MBQI model builder class
**/
diff --git a/src/theory/quantifiers/anti_skolem.cpp b/src/theory/quantifiers/anti_skolem.cpp
new file mode 100644
index 000000000..c8d18aced
--- /dev/null
+++ b/src/theory/quantifiers/anti_skolem.cpp
@@ -0,0 +1,269 @@
+/********************* */
+/*! \file anti_skolem.cpp
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2016 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.\endverbatim
+ **
+ ** \brief Implementation of anti-skolemization
+ ** ( forall x. P[ f( x ) ] ^ forall x. Q[ f( x ) ] ) => forall x. exists y. ( P[ y ] ^ Q[ y ] )
+ **/
+
+#include "theory/quantifiers/anti_skolem.h"
+#include "theory/quantifiers/term_database.h"
+#include "theory/quantifiers_engine.h"
+#include "theory/quantifiers/first_order_model.h"
+#include "options/quantifiers_options.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::quantifiers;
+
+
+struct sortTypeOrder {
+ TermDb* d_tdb;
+ bool operator() (TypeNode i, TypeNode j) {
+ return d_tdb->getIdForType( i )<d_tdb->getIdForType( j );
+ }
+};
+
+void QuantAntiSkolem::SkQuantTypeCache::add( std::vector< TypeNode >& typs, Node q, unsigned index ) {
+ if( index==typs.size() ){
+ Assert( std::find( d_quants.begin(), d_quants.end(), q )==d_quants.end() );
+ d_quants.push_back( q );
+ }else{
+ d_children[typs[index]].add( typs, q, index+1 );
+ }
+}
+
+void QuantAntiSkolem::SkQuantTypeCache::sendLemmas( QuantAntiSkolem * ask ) {
+ for( std::map< TypeNode, SkQuantTypeCache >::iterator it = d_children.begin(); it != d_children.end(); ++it ){
+ it->second.sendLemmas( ask );
+ }
+ if( !d_quants.empty() ){
+ ask->sendAntiSkolemizeLemma( d_quants );
+ }
+}
+
+bool QuantAntiSkolem::CDSkQuantCache::add( context::Context* c, std::vector< Node >& quants, unsigned index ) {
+ if( index==quants.size() ){
+ if( !d_valid.get() ){
+ d_valid.set( true );
+ return true;
+ }else{
+ return false;
+ }
+ }else{
+ Node n = quants[index];
+ std::map< Node, CDSkQuantCache* >::iterator it = d_data.find( n );
+ CDSkQuantCache* skc;
+ if( it==d_data.end() ){
+ skc = new CDSkQuantCache( c );
+ d_data[n] = skc;
+ }else{
+ skc = it->second;
+ }
+ return skc->add( c, quants, index+1 );
+ }
+}
+
+QuantAntiSkolem::QuantAntiSkolem( QuantifiersEngine * qe ) : QuantifiersModule( qe ){
+ d_sqc = new CDSkQuantCache( qe->getUserContext() );
+}
+
+/* Call during quantifier engine's check */
+void QuantAntiSkolem::check( Theory::Effort e, unsigned quant_e ) {
+ if( quant_e==QuantifiersEngine::QEFFORT_STANDARD ){
+ d_sqtc.clear();
+ for( unsigned i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+ Node q = d_quantEngine->getModel()->getAssertedQuantifier( i );
+ if( d_quant_processed.find( q )==d_quant_processed.end() ){
+ d_quant_processed[q] = true;
+ Trace("anti-sk") << "Process quantified formula : " << q << std::endl;
+ bool success = false;
+ if( d_quant_sip[q].init( q[1] ) ){
+ Trace("anti-sk") << "- Partitioned to single invocation parts : " << std::endl;
+ d_quant_sip[q].debugPrint( "anti-sk" );
+ //check if it is single invocation
+ if( d_quant_sip[q].isPurelySingleInvocation() ){
+ //for now, only do purely single invocation
+ success = true;
+ }
+ }else{
+ Trace("anti-sk") << "- Failed to initialize." << std::endl;
+ }
+ if( success ){
+ //sort the argument variables
+ d_ask_types[q].insert( d_ask_types[q].end(), d_quant_sip[q].d_arg_types.begin(), d_quant_sip[q].d_arg_types.end() );
+ std::map< TypeNode, std::vector< unsigned > > indices;
+ for( unsigned j=0; j<d_ask_types[q].size(); j++ ){
+ indices[d_ask_types[q][j]].push_back( j );
+ }
+ sortTypeOrder sto;
+ sto.d_tdb = d_quantEngine->getTermDatabase();
+ std::sort( d_ask_types[q].begin(), d_ask_types[q].end(), sto );
+ //increment j on inner loop
+ for( unsigned j=0; j<d_ask_types[q].size(); ){
+ TypeNode curr = d_ask_types[q][j];
+ for( unsigned k=0; k<indices[curr].size(); k++ ){
+ Assert( d_ask_types[q][j]==curr );
+ d_ask_types_index[q].push_back( indices[curr][k] );
+ j++;
+ }
+ }
+ Assert( d_ask_types_index[q].size()==d_ask_types[q].size() );
+ }else{
+ d_quant_sip.erase( q );
+ }
+ }
+ //now, activate the quantified formula
+ std::map< Node, std::vector< TypeNode > >::iterator it = d_ask_types.find( q );
+ if( it!=d_ask_types.end() ){
+ d_sqtc.add( it->second, q );
+ }
+ }
+ Trace("anti-sk-debug") << "Process lemmas..." << std::endl;
+ //send out lemmas for each anti-skolemizable group of quantified formulas
+ d_sqtc.sendLemmas( this );
+ Trace("anti-sk-debug") << "...Finished process lemmas" << std::endl;
+ }
+}
+
+bool QuantAntiSkolem::sendAntiSkolemizeLemma( std::vector< Node >& quants, bool pconnected ) {
+ Assert( !quants.empty() );
+ std::sort( quants.begin(), quants.end() );
+ if( d_sqc->add( d_quantEngine->getUserContext(), quants ) ){
+ //partition into connected components
+ if( pconnected && quants.size()>1 ){
+ Trace("anti-sk-debug") << "Partition into connected components..." << std::endl;
+ int eqc_count = 0;
+ std::map< Node, int > func_to_eqc;
+ std::map< int, std::vector< Node > > eqc_to_func;
+ std::map< int, std::vector< Node > > eqc_to_quant;
+ for( unsigned i=0; i<quants.size(); i++ ){
+ Node q = quants[i];
+ std::vector< int > eqcs;
+ for( std::map< Node, bool >::iterator it = d_quant_sip[q].d_funcs.begin(); it != d_quant_sip[q].d_funcs.end(); ++it ){
+ Node f = it->first;
+ std::map< Node, int >::iterator itf = func_to_eqc.find( f );
+ if( itf == func_to_eqc.end() ){
+ if( eqcs.empty() ){
+ func_to_eqc[f] = eqc_count;
+ eqc_to_func[eqc_count].push_back( f );
+ eqc_count++;
+ }else{
+ func_to_eqc[f] = eqcs[0];
+ eqc_to_func[eqcs[0]].push_back( f );
+ }
+ }
+ if( std::find( eqcs.begin(), eqcs.end(), func_to_eqc[f] )==eqcs.end() ){
+ eqcs.push_back( func_to_eqc[f] );
+ }
+ }
+ Assert( !eqcs.empty() );
+ //merge equivalence classes
+ int id = eqcs[0];
+ eqc_to_quant[id].push_back( q );
+ for( unsigned j=1; j<eqcs.size(); j++ ){
+ int id2 = eqcs[j];
+ std::map< int, std::vector< Node > >::iterator itef = eqc_to_func.find( id2 );
+ if( itef!=eqc_to_func.end() ){
+ for( unsigned k=0; k<itef->second.size(); k++ ){
+ func_to_eqc[itef->second[k]] = id;
+ eqc_to_func[id].push_back( itef->second[k] );
+ }
+ eqc_to_func.erase( id2 );
+ }
+ itef = eqc_to_quant.find( id2 );
+ if( itef!=eqc_to_quant.end() ){
+ eqc_to_quant[id].insert( eqc_to_quant[id].end(), itef->second.begin(), itef->second.end() );
+ eqc_to_quant.erase( id2 );
+ }
+ }
+ }
+ if( eqc_to_quant.size()>1 ){
+ bool addedLemma = false;
+ for( std::map< int, std::vector< Node > >::iterator it = eqc_to_quant.begin(); it != eqc_to_quant.end(); ++it ){
+ Assert( it->second.size()<quants.size() );
+ bool ret = sendAntiSkolemizeLemma( it->second, false );
+ addedLemma = addedLemma || ret;
+ }
+ return addedLemma;
+ }
+ }
+
+ Trace("anti-sk") << "Anti-skolemize group : " << std::endl;
+ for( unsigned i=0; i<quants.size(); i++ ){
+ Trace("anti-sk") << " " << quants[i] << std::endl;
+ }
+
+ std::vector< Node > outer_vars;
+ std::vector< Node > inner_vars;
+ Node q = quants[0];
+ for( unsigned i=0; i<d_ask_types[q].size(); i++ ){
+ Node v = NodeManager::currentNM()->mkBoundVar( d_ask_types[q][i] );
+ Trace("anti-sk-debug") << "Outer var " << i << " : " << v << std::endl;
+ outer_vars.push_back( v );
+ }
+
+ std::map< Node, Node > func_to_var;
+ std::vector< Node > conj;
+ for( unsigned i=0; i<quants.size(); i++ ){
+ Node q = quants[i];
+ Trace("anti-sk-debug") << "Process " << q << std::endl;
+ std::vector< Node > subs_lhs;
+ std::vector< Node > subs_rhs;
+ //get outer variable substitution
+ Assert( d_ask_types_index[q].size()==d_ask_types[q].size() );
+ for( unsigned j=0; j<d_ask_types_index[q].size(); j++ ){
+ Trace("anti-sk-debug") << " o_subs : " << d_quant_sip[q].d_si_vars[d_ask_types_index[q][j]] << " -> " << outer_vars[j] << std::endl;
+ subs_lhs.push_back( d_quant_sip[q].d_si_vars[d_ask_types_index[q][j]] );
+ subs_rhs.push_back( outer_vars[j] );
+ }
+ //get function substitution
+ for( std::map< Node, bool >::iterator it = d_quant_sip[q].d_funcs.begin(); it != d_quant_sip[q].d_funcs.end(); ++it ){
+ Node f = it->first;
+ Node fv = d_quant_sip[q].d_func_fo_var[it->first];
+ if( func_to_var.find( f )==func_to_var.end() ){
+ Node v = NodeManager::currentNM()->mkBoundVar( fv.getType() );
+ Trace("anti-sk-debug") << "Inner var for " << f << " : " << v << std::endl;
+ inner_vars.push_back( v );
+ func_to_var[f] = v;
+ }
+ subs_lhs.push_back( fv );
+ subs_rhs.push_back( func_to_var[f] );
+ Trace("anti-sk-debug") << " i_subs : " << fv << " -> " << func_to_var[f] << std::endl;
+ }
+ Node c = d_quant_sip[q].getSingleInvocation();
+ if( !subs_lhs.empty() ){
+ c = c.substitute( subs_lhs.begin(), subs_lhs.end(), subs_rhs.begin(), subs_rhs.end() );
+ }
+ conj.push_back( c );
+ }
+ Node body = conj.size()==1 ? conj[0] : NodeManager::currentNM()->mkNode( kind::AND, conj );
+ if( !inner_vars.empty() ){
+ Node bvl = NodeManager::currentNM()->mkNode( kind::BOUND_VAR_LIST, inner_vars );
+ body = NodeManager::currentNM()->mkNode( kind::EXISTS, bvl, body );
+ }
+ if( !outer_vars.empty() ){
+ Node bvl = NodeManager::currentNM()->mkNode( kind::BOUND_VAR_LIST, outer_vars );
+ body = NodeManager::currentNM()->mkNode( kind::FORALL, bvl, body );
+ }
+ Trace("anti-sk") << "Produced : " << body << std::endl;
+ quants.push_back( body.negate() );
+ Node lem = NodeManager::currentNM()->mkNode( kind::AND, quants ).negate();
+ Trace("anti-sk-lemma") << "Anti-skolemize lemma : " << lem << std::endl;
+ quants.pop_back();
+ return d_quantEngine->addLemma( lem );
+ }else{
+ return false;
+ }
+}
+
diff --git a/src/theory/quantifiers/anti_skolem.h b/src/theory/quantifiers/anti_skolem.h
new file mode 100644
index 000000000..721371159
--- /dev/null
+++ b/src/theory/quantifiers/anti_skolem.h
@@ -0,0 +1,75 @@
+/********************* */
+/*! \file anti_skolem.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2016 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.\endverbatim
+ **
+ ** \brief dynamic quantifiers splitting
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__QUANT_ANTI_SKOLEM_H
+#define __CVC4__THEORY__QUANT_ANTI_SKOLEM_H
+
+#include "theory/quantifiers_engine.h"
+#include "context/cdo.h"
+#include "theory/quantifiers/ce_guided_single_inv.h"
+
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
+
+class QuantAntiSkolem : public QuantifiersModule {
+ typedef context::CDHashSet<Node, NodeHashFunction> NodeSet;
+private:
+ std::map< Node, bool > d_quant_processed;
+ std::map< Node, SingleInvocationPartition > d_quant_sip;
+ std::map< Node, std::vector< TypeNode > > d_ask_types;
+ std::map< Node, std::vector< unsigned > > d_ask_types_index;
+
+ class SkQuantTypeCache {
+ public:
+ std::map< TypeNode, SkQuantTypeCache > d_children;
+ std::vector< Node > d_quants;
+ void add( std::vector< TypeNode >& typs, Node q, unsigned index = 0 );
+ void clear() {
+ d_children.clear();
+ d_quants.clear();
+ }
+ void sendLemmas( QuantAntiSkolem * ask );
+ };
+ SkQuantTypeCache d_sqtc;
+
+ class CDSkQuantCache {
+ public:
+ CDSkQuantCache( context::Context* c ) : d_valid( c, false ){}
+ std::map< Node, CDSkQuantCache* > d_data;
+ context::CDO< bool > d_valid;
+ bool add( context::Context* c, std::vector< Node >& quants, unsigned index = 0 );
+ };
+ CDSkQuantCache * d_sqc;
+public:
+ bool sendAntiSkolemizeLemma( std::vector< Node >& quants, bool pconnected = true );
+public:
+ QuantAntiSkolem( QuantifiersEngine * qe );
+
+ /* Call during quantifier engine's check */
+ void check( Theory::Effort e, unsigned quant_e );
+ /* Called for new quantifiers */
+ void registerQuantifier( Node q ) {}
+ void assertNode( Node n ) {}
+ /** Identify this module (for debugging, dynamic configuration, etc..) */
+ std::string identify() const { return "QuantAntiSkolem"; }
+};
+
+}
+}
+}
+
+#endif
diff --git a/src/theory/quantifiers/bounded_integers.cpp b/src/theory/quantifiers/bounded_integers.cpp
index ceab8394f..d32ef59a1 100644
--- a/src/theory/quantifiers/bounded_integers.cpp
+++ b/src/theory/quantifiers/bounded_integers.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file bounded_integers.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): Kshitij Bansal
+ ** Top contributors (to current version):
+ ** Morgan Deters, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Bounded integers module
**
diff --git a/src/theory/quantifiers/bounded_integers.h b/src/theory/quantifiers/bounded_integers.h
index dd241b15e..7d15097bd 100644
--- a/src/theory/quantifiers/bounded_integers.h
+++ b/src/theory/quantifiers/bounded_integers.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file bounded_integers.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** [[ Add lengthier description here ]]
** \todo document this file
diff --git a/src/theory/quantifiers/candidate_generator.cpp b/src/theory/quantifiers/candidate_generator.cpp
index 0cdb22be4..43f5ee2fd 100644
--- a/src/theory/quantifiers/candidate_generator.cpp
+++ b/src/theory/quantifiers/candidate_generator.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file candidate_generator.cpp
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of theory uf candidate generator class
**/
@@ -58,10 +58,13 @@ Node CandidateGeneratorQueue::getNextCandidate(){
}
}
-CandidateGeneratorQE::CandidateGeneratorQE( QuantifiersEngine* qe, Node op ) :
- d_op( op ), d_qe( qe ), d_term_iter( -1 ){
+CandidateGeneratorQE::CandidateGeneratorQE( QuantifiersEngine* qe, Node pat ) :
+ d_qe( qe ), d_term_iter( -1 ){
+ d_op = qe->getTermDatabase()->getMatchOperator( pat );
Assert( !d_op.isNull() );
+ d_op_arity = pat.getNumChildren();
}
+
void CandidateGeneratorQE::resetInstantiationRound(){
d_term_iter_limit = d_qe->getTermDatabase()->getNumGroundTerms( d_op );
}
@@ -71,26 +74,38 @@ void CandidateGeneratorQE::reset( Node eqc ){
if( eqc.isNull() ){
d_mode = cand_term_db;
}else{
- //create an equivalence class iterator in eq class eqc
- //d_qe->getEqualityQuery()->getEquivalenceClass( eqc, d_eqc );
-
- eq::EqualityEngine* ee = d_qe->getEqualityQuery()->getEngine();
- if( ee->hasTerm( eqc ) ){
- Node rep = ee->getRepresentative( eqc );
- d_eqc_iter = eq::EqClassIterator( rep, ee );
- d_mode = cand_term_eqc;
+ if( isExcludedEqc( eqc ) ){
+ d_mode = cand_term_none;
}else{
- d_n = eqc;
- d_mode = cand_term_ident;
+ eq::EqualityEngine* ee = d_qe->getEqualityQuery()->getEngine();
+ if( ee->hasTerm( eqc ) ){
+ quantifiers::TermArgTrie * tat = d_qe->getTermDatabase()->getTermArgTrie( eqc, d_op );
+ if( tat ){
+#if 1
+ //create an equivalence class iterator in eq class eqc
+ Node rep = ee->getRepresentative( eqc );
+ d_eqc_iter = eq::EqClassIterator( rep, ee );
+ d_mode = cand_term_eqc;
+#else
+ d_tindex.push_back( tat );
+ d_tindex_iter.push_back( tat->d_data.begin() );
+ d_mode = cand_term_tindex;
+#endif
+ }else{
+ d_mode = cand_term_none;
+ }
+ }else{
+ //the only match is this term itself
+ d_n = eqc;
+ d_mode = cand_term_ident;
+ }
}
- //a should be in its equivalence class
- //Assert( std::find( eqc.begin(), eqc.end(), a )!=eqc.end() );
}
}
bool CandidateGeneratorQE::isLegalOpCandidate( Node n ) {
if( n.hasOperator() ){
if( isLegalCandidate( n ) ){
- return d_qe->getTermDatabase()->getOperator( n )==d_op;
+ return d_qe->getTermDatabase()->getMatchOperator( n )==d_op;
}
}
return false;
@@ -98,25 +113,67 @@ bool CandidateGeneratorQE::isLegalOpCandidate( Node n ) {
Node CandidateGeneratorQE::getNextCandidate(){
if( d_mode==cand_term_db ){
+ Debug("cand-gen-qe") << "...get next candidate in tbd" << std::endl;
//get next candidate term in the uf term database
while( d_term_iter<d_term_iter_limit ){
Node n = d_qe->getTermDatabase()->getGroundTerm( d_op, d_term_iter );
d_term_iter++;
if( isLegalCandidate( n ) ){
if( d_qe->getTermDatabase()->hasTermCurrent( n ) ){
- return n;
+ if( d_exclude_eqc.empty() ){
+ return n;
+ }else{
+ Node r = d_qe->getEqualityQuery()->getRepresentative( n );
+ if( d_exclude_eqc.find( r )==d_exclude_eqc.end() ){
+ Debug("cand-gen-qe") << "...returning " << n << std::endl;
+ return n;
+ }
+ }
}
}
}
}else if( d_mode==cand_term_eqc ){
+ Debug("cand-gen-qe") << "...get next candidate in eqc" << std::endl;
while( !d_eqc_iter.isFinished() ){
Node n = *d_eqc_iter;
++d_eqc_iter;
if( isLegalOpCandidate( n ) ){
+ Debug("cand-gen-qe") << "...returning " << n << std::endl;
return n;
}
}
+ }else if( d_mode==cand_term_tindex ){
+ Debug("cand-gen-qe") << "...get next candidate in tindex " << d_op << " " << d_op_arity << std::endl;
+ //increment the term index iterator
+ if( !d_tindex.empty() ){
+ //populate the vector
+ while( d_tindex_iter.size()<=d_op_arity ){
+ Assert( !d_tindex_iter.empty() );
+ Assert( !d_tindex_iter.back()->second.d_data.empty() );
+ d_tindex.push_back( &(d_tindex_iter.back()->second) );
+ d_tindex_iter.push_back( d_tindex_iter.back()->second.d_data.begin() );
+ }
+ //get the current node
+ Assert( d_tindex_iter.back()->second.hasNodeData() );
+ Node n = d_tindex_iter.back()->second.getNodeData();
+ Debug("cand-gen-qe") << "...returning " << n << std::endl;
+ Assert( !n.isNull() );
+ Assert( isLegalOpCandidate( n ) );
+ //increment
+ bool success = false;
+ do{
+ ++d_tindex_iter.back();
+ if( d_tindex_iter.back()==d_tindex.back()->d_data.end() ){
+ d_tindex.pop_back();
+ d_tindex_iter.pop_back();
+ }else{
+ success = true;
+ }
+ }while( !success && !d_tindex.empty() );
+ return n;
+ }
}else if( d_mode==cand_term_ident ){
+ Debug("cand-gen-qe") << "...get next candidate identity" << std::endl;
if( !d_n.isNull() ){
Node n = d_n;
d_n = Node::null();
@@ -130,21 +187,37 @@ Node CandidateGeneratorQE::getNextCandidate(){
CandidateGeneratorQELitEq::CandidateGeneratorQELitEq( QuantifiersEngine* qe, Node mpat ) :
d_match_pattern( mpat ), d_qe( qe ){
-
+ Assert( mpat.getKind()==EQUAL );
+ for( unsigned i=0; i<2; i++ ){
+ if( !quantifiers::TermDb::hasInstConstAttr(mpat[i]) ){
+ d_match_gterm = mpat[i];
+ }
+ }
}
void CandidateGeneratorQELitEq::resetInstantiationRound(){
}
void CandidateGeneratorQELitEq::reset( Node eqc ){
- d_eq = eq::EqClassesIterator( d_qe->getEqualityQuery()->getEngine() );
+ if( d_match_gterm.isNull() ){
+ d_eq = eq::EqClassesIterator( d_qe->getEqualityQuery()->getEngine() );
+ }else{
+ d_do_mgt = true;
+ }
}
Node CandidateGeneratorQELitEq::getNextCandidate(){
- while( !d_eq.isFinished() ){
- Node n = (*d_eq);
- ++d_eq;
- if( n.getType().isComparableTo( d_match_pattern[0].getType() ) ){
- //an equivalence class with the same type as the pattern, return reflexive equality
- return NodeManager::currentNM()->mkNode( d_match_pattern.getKind(), n, n );
+ if( d_match_gterm.isNull() ){
+ while( !d_eq.isFinished() ){
+ Node n = (*d_eq);
+ ++d_eq;
+ if( n.getType().isComparableTo( d_match_pattern[0].getType() ) ){
+ //an equivalence class with the same type as the pattern, return reflexive equality
+ return NodeManager::currentNM()->mkNode( d_match_pattern.getKind(), n, n );
+ }
+ }
+ }else{
+ if( d_do_mgt ){
+ d_do_mgt = false;
+ return NodeManager::currentNM()->mkNode( d_match_pattern.getKind(), d_match_gterm, d_match_gterm );
}
}
return Node::null();
@@ -225,7 +298,6 @@ Node CandidateGeneratorQEAll::getNextCandidate() {
}
}
if( d_firstTime ){
- Assert( d_qe->getTermDatabase()->d_type_map[d_match_pattern_type].empty() );
//must return something
d_firstTime = false;
return d_qe->getTermDatabase()->getModelBasisTerm( d_match_pattern_type );
diff --git a/src/theory/quantifiers/candidate_generator.h b/src/theory/quantifiers/candidate_generator.h
index fb120dd08..18ef6a086 100644
--- a/src/theory/quantifiers/candidate_generator.h
+++ b/src/theory/quantifiers/candidate_generator.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file candidate_generator.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Andrew Reynolds, Clark Barrett
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Theory uf candidate generator
**/
@@ -23,6 +23,10 @@
namespace CVC4 {
namespace theory {
+namespace quantifiers {
+ class TermArgTrie;
+}
+
class QuantifiersEngine;
namespace inst {
@@ -79,6 +83,9 @@ private:
//instantiator pointer
QuantifiersEngine* d_qe;
//the equality class iterator
+ unsigned d_op_arity;
+ std::vector< quantifiers::TermArgTrie* > d_tindex;
+ std::vector< std::map< TNode, quantifiers::TermArgTrie >::iterator > d_tindex_iter;
eq::EqClassIterator d_eqc_iter;
//std::vector< Node > d_eqc;
int d_term_iter;
@@ -88,17 +95,22 @@ private:
cand_term_db,
cand_term_ident,
cand_term_eqc,
+ cand_term_tindex,
+ cand_term_none,
};
short d_mode;
bool isLegalOpCandidate( Node n );
Node d_n;
+ std::map< Node, bool > d_exclude_eqc;
public:
- CandidateGeneratorQE( QuantifiersEngine* qe, Node op );
+ CandidateGeneratorQE( QuantifiersEngine* qe, Node pat );
~CandidateGeneratorQE() throw() {}
void resetInstantiationRound();
void reset( Node eqc );
Node getNextCandidate();
+ void excludeEqc( Node r ) { d_exclude_eqc[r] = true; }
+ bool isExcludedEqc( Node r ) { return d_exclude_eqc.find( r )!=d_exclude_eqc.end(); }
};
class CandidateGeneratorQELitEq : public CandidateGenerator
@@ -108,6 +120,8 @@ private:
eq::EqClassesIterator d_eq;
//equality you are trying to match equalities for
Node d_match_pattern;
+ Node d_match_gterm;
+ bool d_do_mgt;
//einstantiator pointer
QuantifiersEngine* d_qe;
public:
diff --git a/src/theory/quantifiers/ce_guided_instantiation.cpp b/src/theory/quantifiers/ce_guided_instantiation.cpp
index 345a5eaef..d9059a3e6 100644
--- a/src/theory/quantifiers/ce_guided_instantiation.cpp
+++ b/src/theory/quantifiers/ce_guided_instantiation.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file ce_guided_instantiation.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief counterexample guided instantiation class
**
@@ -22,19 +22,25 @@
#include "theory/quantifiers/term_database.h"
#include "theory/theory_engine.h"
-using namespace CVC4;
using namespace CVC4::kind;
-using namespace CVC4::theory;
-using namespace CVC4::theory::quantifiers;
using namespace std;
namespace CVC4 {
+namespace theory {
+namespace quantifiers {
-CegConjecture::CegConjecture( QuantifiersEngine * qe, context::Context* c ) : d_qe( qe ), d_curr_lit( c, 0 ){
+
+CegConjecture::CegConjecture( QuantifiersEngine * qe, context::Context* c )
+ : d_qe( qe ), d_curr_lit( c, 0 )
+{
d_refine_count = 0;
d_ceg_si = new CegConjectureSingleInv( qe, this );
}
+CegConjecture::~CegConjecture() {
+ delete d_ceg_si;
+}
+
void CegConjecture::assign( Node q ) {
Assert( d_quant.isNull() );
Assert( q.getKind()==FORALL );
@@ -149,7 +155,7 @@ CegqiFairMode CegConjecture::getCegqiFairMode() {
return isSingleInvocation() ? CEGQI_FAIR_NONE : options::ceGuidedInstFair();
}
-bool CegConjecture::isSingleInvocation() {
+bool CegConjecture::isSingleInvocation() const {
return d_ceg_si->isSingleInvocation();
}
@@ -219,11 +225,13 @@ bool CegInstantiation::needsCheck( Theory::Effort e ) {
}
unsigned CegInstantiation::needsModel( Theory::Effort e ) {
- return d_conj->d_ceg_si->isSingleInvocation() ? QuantifiersEngine::QEFFORT_STANDARD : QuantifiersEngine::QEFFORT_MODEL;
+ return d_conj->getCegConjectureSingleInv()->isSingleInvocation()
+ ? QuantifiersEngine::QEFFORT_STANDARD : QuantifiersEngine::QEFFORT_MODEL;
}
void CegInstantiation::check( Theory::Effort e, unsigned quant_e ) {
- unsigned echeck = d_conj->d_ceg_si->isSingleInvocation() ? QuantifiersEngine::QEFFORT_STANDARD : QuantifiersEngine::QEFFORT_MODEL;
+ unsigned echeck = d_conj->getCegConjectureSingleInv()->isSingleInvocation() ?
+ QuantifiersEngine::QEFFORT_STANDARD : QuantifiersEngine::QEFFORT_MODEL;
if( quant_e==echeck ){
Trace("cegqi-engine") << "---Counterexample Guided Instantiation Engine---" << std::endl;
Trace("cegqi-engine-debug") << std::endl;
@@ -294,12 +302,13 @@ Node CegInstantiation::getNextDecisionRequest() {
if( d_conj->isAssigned() ){
d_conj->initializeGuard( d_quantEngine );
std::vector< Node > req_dec;
- if( !d_conj->d_ceg_si->d_full_guard.isNull() ){
- req_dec.push_back( d_conj->d_ceg_si->d_full_guard );
+ const CegConjectureSingleInv* ceg_si = d_conj->getCegConjectureSingleInv();
+ if( ! ceg_si->d_full_guard.isNull() ){
+ req_dec.push_back( ceg_si->d_full_guard );
}
//must decide ns guard before s guard
- if( !d_conj->d_ceg_si->d_ns_guard.isNull() ){
- req_dec.push_back( d_conj->d_ceg_si->d_ns_guard );
+ if( !ceg_si->d_ns_guard.isNull() ){
+ req_dec.push_back( ceg_si->d_ns_guard );
}
req_dec.push_back( d_conj->getGuard() );
for( unsigned i=0; i<req_dec.size(); i++ ){
@@ -348,9 +357,9 @@ void CegInstantiation::checkCegConjecture( CegConjecture * conj ) {
if( conj->d_ce_sk.empty() ){
Trace("cegqi-engine") << " *** Check candidate phase..." << std::endl;
if( conj->d_syntax_guided ){
- if( conj->d_ceg_si ){
+ if( conj->getCegConjectureSingleInv() != NULL ){
std::vector< Node > lems;
- if( conj->d_ceg_si->check( lems ) ){
+ if( conj->doCegConjectureCheck( lems ) ){
if( !lems.empty() ){
d_last_inst_si = true;
for( unsigned j=0; j<lems.size(); j++ ){
@@ -423,7 +432,7 @@ void CegInstantiation::checkCegConjecture( CegConjecture * conj ) {
Assert( aq==q );
std::vector< Node > model_terms;
if( getModelValues( conj, conj->d_candidates, model_terms ) ){
- d_quantEngine->addInstantiation( q, model_terms, false );
+ d_quantEngine->addInstantiation( q, model_terms );
}
}
}else{
@@ -600,39 +609,53 @@ void CegInstantiation::printSynthSolution( std::ostream& out ) {
Node sol;
int status;
if( d_last_inst_si ){
- Assert( d_conj->d_ceg_si );
- sol = d_conj->d_ceg_si->getSolution( i, tn, status );
+ Assert( d_conj->getCegConjectureSingleInv() != NULL );
+ sol = d_conj->getSingleInvocationSolution( i, tn, status );
sol = sol.getKind()==LAMBDA ? sol[1] : sol;
}else{
if( !d_conj->d_candidate_inst[i].empty() ){
sol = d_conj->d_candidate_inst[i].back();
- //check if this was based on a template, if so, we must do reconstruction
+ // Check if this was based on a template, if so, we must do
+ // Reconstruction
if( d_conj->d_assert_quant!=d_conj->d_quant ){
Node sygus_sol = sol;
- Trace("cegqi-inv") << "Sygus version of solution is : " << sol << ", type : " << sol.getType() << std::endl;
+ Trace("cegqi-inv") << "Sygus version of solution is : " << sol
+ << ", type : " << sol.getType() << std::endl;
std::vector< Node > subs;
Expr svl = dt.getSygusVarList();
for( unsigned j=0; j<svl.getNumChildren(); j++ ){
subs.push_back( Node::fromExpr( svl[j] ) );
}
if( options::sygusInvTemplMode() == SYGUS_INV_TEMPL_MODE_PRE ){
- if( d_conj->d_ceg_si->d_trans_pre.find( prog )!=d_conj->d_ceg_si->d_trans_pre.end() ){
- Assert( d_conj->d_ceg_si->d_prog_templ_vars[prog].size()==subs.size() );
- Node pre = d_conj->d_ceg_si->d_trans_pre[prog];
- pre = pre.substitute( d_conj->d_ceg_si->d_prog_templ_vars[prog].begin(), d_conj->d_ceg_si->d_prog_templ_vars[prog].end(),
+ const CegConjectureSingleInv* ceg_si =
+ d_conj->getCegConjectureSingleInv();
+ if(ceg_si->d_trans_pre.find( prog ) != ceg_si->d_trans_pre.end()){
+ std::vector<Node>& templ_vars = d_conj->getProgTempVars(prog);
+ Assert(templ_vars.size() == subs.size());
+ Node pre = ceg_si->getTransPre(prog);
+ pre = pre.substitute( templ_vars.begin(), templ_vars.end(),
subs.begin(), subs.end() );
- sol = getTermDatabase()->getTermDatabaseSygus()->sygusToBuiltin( sol, sol.getType() );
- Trace("cegqi-inv") << "Builtin version of solution is : " << sol << ", type : " << sol.getType() << std::endl;
+ TermDbSygus* sygusDb = getTermDatabase()->getTermDatabaseSygus();
+ sol = sygusDb->sygusToBuiltin( sol, sol.getType() );
+ Trace("cegqi-inv") << "Builtin version of solution is : "
+ << sol << ", type : " << sol.getType()
+ << std::endl;
sol = NodeManager::currentNM()->mkNode( OR, sol, pre );
}
- }else if( options::sygusInvTemplMode() == SYGUS_INV_TEMPL_MODE_POST ){
- if( d_conj->d_ceg_si->d_trans_post.find( prog )!=d_conj->d_ceg_si->d_trans_post.end() ){
- Assert( d_conj->d_ceg_si->d_prog_templ_vars[prog].size()==subs.size() );
- Node post = d_conj->d_ceg_si->d_trans_post[prog];
- post = post.substitute( d_conj->d_ceg_si->d_prog_templ_vars[prog].begin(), d_conj->d_ceg_si->d_prog_templ_vars[prog].end(),
+ }else if(options::sygusInvTemplMode() == SYGUS_INV_TEMPL_MODE_POST){
+ const CegConjectureSingleInv* ceg_si =
+ d_conj->getCegConjectureSingleInv();
+ if(ceg_si->d_trans_post.find(prog) != ceg_si->d_trans_post.end()){
+ std::vector<Node>& templ_vars = d_conj->getProgTempVars(prog);
+ Assert( templ_vars.size()==subs.size() );
+ Node post = ceg_si->getTransPost(prog);
+ post = post.substitute( templ_vars.begin(), templ_vars.end(),
subs.begin(), subs.end() );
- sol = getTermDatabase()->getTermDatabaseSygus()->sygusToBuiltin( sol, sol.getType() );
- Trace("cegqi-inv") << "Builtin version of solution is : " << sol << ", type : " << sol.getType() << std::endl;
+ TermDbSygus* sygusDb = getTermDatabase()->getTermDatabaseSygus();
+ sol = sygusDb->sygusToBuiltin( sol, sol.getType() );
+ Trace("cegqi-inv") << "Builtin version of solution is : "
+ << sol << ", type : " << sol.getType()
+ << std::endl;
sol = NodeManager::currentNM()->mkNode( AND, sol, post );
}
}
@@ -643,7 +666,7 @@ void CegInstantiation::printSynthSolution( std::ostream& out ) {
Trace("cegqi-inv-debug") << "With template : " << sol << std::endl;
sol = Rewriter::rewrite( sol );
Trace("cegqi-inv-debug") << "Simplified : " << sol << std::endl;
- sol = d_conj->d_ceg_si->reconstructToSyntax( sol, tn, status );
+ sol = d_conj->reconstructToSyntaxSingleInvocation(sol, tn, status);
sol = sol.getKind()==LAMBDA ? sol[1] : sol;
}
}else{
@@ -712,5 +735,6 @@ CegInstantiation::Statistics::~Statistics(){
smtStatisticsRegistry()->unregisterStat(&d_cegqi_si_lemmas);
}
-
-}
+}/* namespace CVC4::theory::quantifiers */
+}/* namespace CVC4::theory */
+}/* namespace CVC4 */
diff --git a/src/theory/quantifiers/ce_guided_instantiation.h b/src/theory/quantifiers/ce_guided_instantiation.h
index 8274561ca..57dc31850 100644
--- a/src/theory/quantifiers/ce_guided_instantiation.h
+++ b/src/theory/quantifiers/ce_guided_instantiation.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file ce_guided_instantiation.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief counterexample guided instantiation class
**/
@@ -33,6 +33,8 @@ private:
QuantifiersEngine * d_qe;
public:
CegConjecture( QuantifiersEngine * qe, context::Context* c );
+ ~CegConjecture();
+
/** quantified formula asserted */
Node d_assert_quant;
/** quantified formula (after processing) */
@@ -56,12 +58,36 @@ public:
unsigned d_refine_count;
/** current extential quantifeirs whose couterexamples we must refine */
std::vector< std::vector< Node > > d_ce_sk;
+
+ const CegConjectureSingleInv* getCegConjectureSingleInv() const {
+ return d_ceg_si;
+ }
+
+ bool doCegConjectureCheck(std::vector< Node >& lems) {
+ return d_ceg_si->check(lems);
+ }
+
+ Node getSingleInvocationSolution(unsigned sol_index, TypeNode stn,
+ int& reconstructed, bool rconsSygus=true){
+ return d_ceg_si->getSolution(sol_index, stn, reconstructed, rconsSygus);
+ }
+
+ Node reconstructToSyntaxSingleInvocation(
+ Node s, TypeNode stn, int& reconstructed, bool rconsSygus = true ) {
+ return d_ceg_si->reconstructToSyntax(s, stn, reconstructed, rconsSygus);
+ }
+
+ std::vector<Node>& getProgTempVars(Node prog) {
+ return d_ceg_si->d_prog_templ_vars[prog];
+ }
+
+ private:
/** single invocation utility */
CegConjectureSingleInv * d_ceg_si;
public: //non-syntax guided (deprecated)
/** guard */
bool d_syntax_guided;
- Node d_nsg_guard;
+ Node d_nsg_guard;
public: //for fairness
/** the cardinality literals */
std::map< int, Node > d_lits;
@@ -76,7 +102,7 @@ public: //for fairness
/** fairness */
CegqiFairMode getCegqiFairMode();
/** is single invocation */
- bool isSingleInvocation();
+ bool isSingleInvocation() const;
/** is single invocation */
bool isFullySingleInvocation();
/** needs check */
@@ -151,10 +177,10 @@ public:
~Statistics();
};/* class CegInstantiation::Statistics */
Statistics d_statistics;
-};
+}; /* class CegInstantiation */
-}
-}
-}
+} /* namespace CVC4::theory::quantifiers */
+} /* namespace CVC4::theory */
+} /* namespace CVC4 */
#endif
diff --git a/src/theory/quantifiers/ce_guided_single_inv.cpp b/src/theory/quantifiers/ce_guided_single_inv.cpp
index 7ef23077f..33856d226 100644
--- a/src/theory/quantifiers/ce_guided_single_inv.cpp
+++ b/src/theory/quantifiers/ce_guided_single_inv.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file ce_guided_single_inv.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief utility for processing single invocation synthesis conjectures
**
@@ -33,8 +33,8 @@ using namespace std;
namespace CVC4 {
-bool CegqiOutputSingleInv::addInstantiation( std::vector< Node >& subs ) {
- return d_out->addInstantiation( subs );
+bool CegqiOutputSingleInv::doAddInstantiation( std::vector< Node >& subs ) {
+ return d_out->doAddInstantiation( subs );
}
bool CegqiOutputSingleInv::isEligibleForInstantiation( Node n ) {
@@ -55,12 +55,12 @@ CegConjectureSingleInv::CegConjectureSingleInv( QuantifiersEngine * qe, CegConje
}
d_cosi = new CegqiOutputSingleInv( this );
// third and fourth arguments set to (false,false) until we have solution reconstruction for delta and infinity
- d_cinst = new CegInstantiator( d_qe, d_cosi, false, false );
+ d_cinst = new CegInstantiator( d_qe, d_cosi, false, false );
d_sol = new CegConjectureSingleInvSol( qe );
d_sip = new SingleInvocationPartition;
-
+
if( options::cegqiSingleInvPartial() ){
d_ei = new CegEntailmentInfer( qe, d_sip );
}else{
@@ -104,7 +104,7 @@ void CegConjectureSingleInv::getInitialSingleInvLemma( std::vector< Node >& lems
if( d_cinst ){
delete d_cinst;
}
- d_cinst = new CegInstantiator( d_qe, d_cosi, false, false );
+ d_cinst = new CegInstantiator( d_qe, d_cosi, false, false );
d_cinst->registerCounterexampleLemma( lems, d_single_inv_sk );
}
}
@@ -149,8 +149,7 @@ void CegConjectureSingleInv::initialize( Node q ) {
bool singleInvocation = true;
if( type_valid==0 ){
//process the single invocation-ness of the property
- d_sip->init( types );
- d_sip->process( qq );
+ d_sip->init( types, qq );
Trace("cegqi-si") << "- Partitioned to single invocation parts : " << std::endl;
d_sip->debugPrint( "cegqi-si" );
//map from program to bound variables
@@ -481,7 +480,7 @@ void CegConjectureSingleInv::initializeNextSiConjecture() {
if( d_single_inv.isNull() ){
if( d_ei->getEntailedConjecture( d_single_inv, d_single_inv_exp ) ){
Trace("cegqi-nsi") << "NSI : got : " << d_single_inv << std::endl;
- Trace("cegqi-nsi") << "NSI : exp : " << d_single_inv_exp << std::endl;
+ Trace("cegqi-nsi") << "NSI : exp : " << d_single_inv_exp << std::endl;
}else{
Trace("cegqi-nsi") << "NSI : failed to construct next conjecture." << std::endl;
Notice() << "Incomplete due to --cegqi-si-partial." << std::endl;
@@ -492,7 +491,7 @@ void CegConjectureSingleInv::initializeNextSiConjecture() {
Trace("cegqi-nsi") << "NSI : have : " << d_single_inv << std::endl;
Assert( d_single_inv_exp.isNull() );
}
-
+
d_si_guard = Node::null();
d_ns_guard = Rewriter::rewrite( NodeManager::currentNM()->mkSkolem( "GS", NodeManager::currentNM()->booleanType() ) );
d_ns_guard = d_qe->getValuation().ensureLiteral( d_ns_guard );
@@ -509,7 +508,7 @@ void CegConjectureSingleInv::initializeNextSiConjecture() {
Trace("cegqi-nsi") << "NSI : conjecture is " << d_single_inv << std::endl;
}
-bool CegConjectureSingleInv::addInstantiation( std::vector< Node >& subs ){
+bool CegConjectureSingleInv::doAddInstantiation( std::vector< Node >& subs ){
std::stringstream siss;
if( Trace.isOn("cegqi-si-inst-debug") || Trace.isOn("cegqi-engine") ){
siss << " * single invocation: " << std::endl;
@@ -839,7 +838,42 @@ void CegConjectureSingleInv::preregisterConjecture( Node q ) {
d_orig_conjecture = q;
}
-void SingleInvocationPartition::init( std::vector< TypeNode >& typs ){
+bool SingleInvocationPartition::init( Node n ) {
+ //first, get types of arguments for functions
+ std::vector< TypeNode > typs;
+ std::map< Node, bool > visited;
+ if( inferArgTypes( n, typs, visited ) ){
+ return init( typs, n );
+ }else{
+ Trace("si-prt") << "Could not infer argument types." << std::endl;
+ return false;
+ }
+}
+
+bool SingleInvocationPartition::inferArgTypes( Node n, std::vector< TypeNode >& typs, std::map< Node, bool >& visited ) {
+ if( visited.find( n )==visited.end() ){
+ visited[n] = true;
+ if( n.getKind()!=FORALL ){
+ //if( TermDb::hasBoundVarAttr( n ) ){
+ if( n.getKind()==d_checkKind ){
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ typs.push_back( n[i].getType() );
+ }
+ return true;
+ }else{
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ if( inferArgTypes( n[i], typs, visited ) ){
+ return true;
+ }
+ }
+ }
+ //}
+ }
+ }
+ return false;
+}
+
+bool SingleInvocationPartition::init( std::vector< TypeNode >& typs, Node n ){
Assert( d_arg_types.empty() );
Assert( d_si_vars.empty() );
d_arg_types.insert( d_arg_types.end(), typs.begin(), typs.end() );
@@ -849,6 +883,9 @@ void SingleInvocationPartition::init( std::vector< TypeNode >& typs ){
Node si_v = NodeManager::currentNM()->mkBoundVar( ss.str(), d_arg_types[j] );
d_si_vars.push_back( si_v );
}
+ Trace("si-prt") << "Process the formula..." << std::endl;
+ process( n );
+ return true;
}
@@ -874,6 +911,7 @@ void SingleInvocationPartition::process( Node n ) {
std::vector< Node > terms;
std::vector< Node > subs;
bool singleInvocation = true;
+ bool ngroundSingleInvocation = false;
if( processConjunct( cr, visited, args, terms, subs ) ){
for( unsigned j=0; j<terms.size(); j++ ){
si_terms.push_back( subs[j] );
@@ -909,6 +947,7 @@ void SingleInvocationPartition::process( Node n ) {
TermDb::getBoundVars( cr, bvs );
if( bvs.size()>d_si_vars.size() ){
Trace("si-prt") << "...not ground single invocation." << std::endl;
+ ngroundSingleInvocation = true;
singleInvocation = false;
}else{
Trace("si-prt") << "...ground single invocation : success." << std::endl;
@@ -949,6 +988,9 @@ void SingleInvocationPartition::process( Node n ) {
d_conjuncts[0].push_back( cr );
}else{
d_conjuncts[1].push_back( cr );
+ if( ngroundSingleInvocation ){
+ d_conjuncts[3].push_back( cr );
+ }
}
}
}else{
@@ -984,43 +1026,45 @@ bool SingleInvocationPartition::processConjunct( Node n, std::map< Node, bool >&
return true;
}else{
bool ret = true;
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- if( !processConjunct( n[i], visited, args, terms, subs ) ){
- ret = false;
+ //if( TermDb::hasBoundVarAttr( n ) ){
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ if( !processConjunct( n[i], visited, args, terms, subs ) ){
+ ret = false;
+ }
}
- }
- if( ret ){
- if( n.getKind()==APPLY_UF ){
- if( std::find( terms.begin(), terms.end(), n )==terms.end() ){
- Node f = n.getOperator();
- //check if it matches the type requirement
- if( isAntiSkolemizableType( f ) ){
- if( args.empty() ){
- //record arguments
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- args.push_back( n[i] );
- }
- }else{
- //arguments must be the same as those already recorded
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- if( args[i]!=n[i] ){
- Trace("si-prt-debug") << "...bad invocation : " << n << " at arg " << i << "." << std::endl;
- ret = false;
- break;
+ if( ret ){
+ if( n.getKind()==d_checkKind ){
+ if( std::find( terms.begin(), terms.end(), n )==terms.end() ){
+ Node f = n.getOperator();
+ //check if it matches the type requirement
+ if( isAntiSkolemizableType( f ) ){
+ if( args.empty() ){
+ //record arguments
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ args.push_back( n[i] );
+ }
+ }else{
+ //arguments must be the same as those already recorded
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ if( args[i]!=n[i] ){
+ Trace("si-prt-debug") << "...bad invocation : " << n << " at arg " << i << "." << std::endl;
+ ret = false;
+ break;
+ }
}
}
+ if( ret ){
+ terms.push_back( n );
+ subs.push_back( d_func_inv[f] );
+ }
+ }else{
+ Trace("si-prt-debug") << "... " << f << " is a bad operator." << std::endl;
+ ret = false;
}
- if( ret ){
- terms.push_back( n );
- subs.push_back( d_func_inv[f] );
- }
- }else{
- Trace("si-prt-debug") << "... " << f << " is a bad operator." << std::endl;
- ret = false;
}
}
}
- }
+ //}
visited[n] = ret;
return ret;
}
@@ -1037,6 +1081,7 @@ bool SingleInvocationPartition::isAntiSkolemizableType( Node f ) {
ret = true;
std::vector< Node > children;
children.push_back( f );
+ //TODO: permutations of arguments
for( unsigned i=0; i<d_arg_types.size(); i++ ){
children.push_back( d_si_vars[i] );
if( tn[i]!=d_arg_types[i] ){
@@ -1045,7 +1090,7 @@ bool SingleInvocationPartition::isAntiSkolemizableType( Node f ) {
}
}
if( ret ){
- Node t = NodeManager::currentNM()->mkNode( APPLY_UF, children );
+ Node t = NodeManager::currentNM()->mkNode( d_checkKind, children );
d_func_inv[f] = t;
d_inv_to_func[t] = f;
std::stringstream ss;
@@ -1079,7 +1124,7 @@ Node SingleInvocationPartition::getSpecificationInst( Node n, std::map< Node, No
childChanged = childChanged || ( nn!=n[i] );
}
Node ret;
- if( n.getKind()==APPLY_UF ){
+ if( n.getKind()==d_checkKind ){
std::map< Node, Node >::iterator itl = lam.find( n.getOperator() );
if( itl!=lam.end() ){
Assert( itl->second[0].getNumChildren()==children.size() );
@@ -1176,8 +1221,8 @@ void SingleInvocationPartition::debugPrint( const char * c ) {
Trace(c) << "not incorporated." << std::endl;
}
}
- for( unsigned i=0; i<3; i++ ){
- Trace(c) << ( i==0 ? "Single invocation" : ( i==1 ? "Non-single invocation" : "All" ) );
+ for( unsigned i=0; i<4; i++ ){
+ Trace(c) << ( i==0 ? "Single invocation" : ( i==1 ? "Non-single invocation" : ( i==2 ? "All" : "Non-ground single invocation" ) ) );
Trace(c) << " conjuncts: " << std::endl;
for( unsigned j=0; j<d_conjuncts[i].size(); j++ ){
Trace(c) << " " << (j+1) << " : " << d_conjuncts[i][j] << std::endl;
diff --git a/src/theory/quantifiers/ce_guided_single_inv.h b/src/theory/quantifiers/ce_guided_single_inv.h
index c414a51bd..4d2f9a0e5 100644
--- a/src/theory/quantifiers/ce_guided_single_inv.h
+++ b/src/theory/quantifiers/ce_guided_single_inv.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file ce_guided_single_inv.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King, Clark Barrett
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief utility for processing single invocation synthesis conjectures
**/
@@ -37,7 +37,7 @@ public:
CegqiOutputSingleInv( CegConjectureSingleInv * out ) : d_out( out ){}
~CegqiOutputSingleInv() {}
CegConjectureSingleInv * d_out;
- bool addInstantiation( std::vector< Node >& subs );
+ bool doAddInstantiation( std::vector< Node >& subs );
bool isEligibleForInstantiation( Node n );
bool addLemma( Node lem );
};
@@ -58,13 +58,21 @@ private:
CegqiOutputSingleInv * d_cosi;
CegInstantiator * d_cinst;
//for recognizing templates for invariant synthesis
- Node substituteInvariantTemplates( Node n, std::map< Node, Node >& prog_templ, std::map< Node, std::vector< Node > >& prog_templ_vars );
+ Node substituteInvariantTemplates(
+ Node n, std::map< Node, Node >& prog_templ,
+ std::map< Node, std::vector< Node > >& prog_templ_vars );
// partially single invocation
- Node removeDeepEmbedding( Node n, std::vector< Node >& progs, std::vector< TypeNode >& types, int& type_valid, std::map< Node, Node >& visited );
+ Node removeDeepEmbedding( Node n, std::vector< Node >& progs,
+ std::vector< TypeNode >& types, int& type_valid,
+ std::map< Node, Node >& visited );
Node addDeepEmbedding( Node n, std::map< Node, Node >& visited );
//presolve
- void collectPresolveEqTerms( Node n, std::map< Node, std::vector< Node > >& teq );
- void getPresolveEqConjuncts( std::vector< Node >& vars, std::vector< Node >& terms, std::map< Node, std::vector< Node > >& teq, Node n, std::vector< Node >& conj );
+ void collectPresolveEqTerms( Node n,
+ std::map< Node, std::vector< Node > >& teq );
+ void getPresolveEqConjuncts( std::vector< Node >& vars,
+ std::vector< Node >& terms,
+ std::map< Node, std::vector< Node > >& teq,
+ Node n, std::vector< Node >& conj );
//constructing solution
Node constructSolution( std::vector< unsigned >& indices, unsigned i, unsigned index );
Node postProcessSolution( Node n );
@@ -94,7 +102,7 @@ public:
private:
std::vector< Node > d_curr_lemmas;
//add instantiation
- bool addInstantiation( std::vector< Node >& subs );
+ bool doAddInstantiation( std::vector< Node >& subs );
//is eligible for instantiation
bool isEligibleForInstantiation( Node n );
// add lemma
@@ -113,7 +121,7 @@ public:
Node d_full_inv;
Node d_full_guard;
//explanation for current single invocation conjecture
- Node d_single_inv_exp;
+ Node d_single_inv_exp;
// transition relation version per program
std::map< Node, Node > d_trans_pre;
std::map< Node, Node > d_trans_post;
@@ -132,19 +140,33 @@ public:
//get solution
Node getSolution( unsigned sol_index, TypeNode stn, int& reconstructed, bool rconsSygus = true );
//reconstruct to syntax
- Node reconstructToSyntax( Node s, TypeNode stn, int& reconstructed, bool rconsSygus = true );
+ Node reconstructToSyntax( Node s, TypeNode stn, int& reconstructed,
+ bool rconsSygus = true );
// has ites
bool hasITEs() { return d_has_ites; }
// is single invocation
- bool isSingleInvocation() { return !d_single_inv.isNull(); }
+ bool isSingleInvocation() const { return !d_single_inv.isNull(); }
// is single invocation
- bool isFullySingleInvocation() { return !d_single_inv.isNull() && d_nsingle_inv.isNull(); }
+ bool isFullySingleInvocation() const {
+ return !d_single_inv.isNull() && d_nsingle_inv.isNull();
+ }
//needs check
bool needsCheck();
/** preregister conjecture */
void preregisterConjecture( Node q );
//initialize next candidate si conjecture (if not fully single invocation)
- void initializeNextSiConjecture();
+ void initializeNextSiConjecture();
+
+ Node getTransPre(Node prog) const {
+ std::map<Node, Node>::const_iterator location = d_trans_pre.find(prog);
+ return location->second;
+ }
+
+ Node getTransPost(Node prog) const {
+ std::map<Node, Node>::const_iterator location = d_trans_post.find(prog);
+ return location->second;
+ }
+
};
// partitions any formulas given to it into single invocation/non-single invocation
@@ -153,18 +175,23 @@ public:
class SingleInvocationPartition
{
private:
+ //options
+ Kind d_checkKind;
+ bool inferArgTypes( Node n, std::vector< TypeNode >& typs, std::map< Node, bool >& visited );
+ void process( Node n );
bool collectConjuncts( Node n, bool pol, std::vector< Node >& conj );
bool processConjunct( Node n, std::map< Node, bool >& visited, std::vector< Node >& args,
std::vector< Node >& terms, std::vector< Node >& subs );
Node getSpecificationInst( Node n, std::map< Node, Node >& lam, std::map< Node, Node >& visited );
void extractInvariant2( Node n, Node& func, int& pol, std::vector< Node >& disjuncts, bool hasPol, std::map< Node, bool >& visited );
public:
- void init( std::vector< TypeNode >& typs );
- //inputs
- void process( Node n );
- std::vector< TypeNode > d_arg_types;
+ SingleInvocationPartition( Kind checkKind = kind::APPLY_UF ) : d_checkKind( checkKind ){}
+ ~SingleInvocationPartition(){}
+ bool init( Node n );
+ bool init( std::vector< TypeNode >& typs, Node n );
//outputs (everything is with bound var)
+ std::vector< TypeNode > d_arg_types;
std::map< Node, bool > d_funcs;
std::map< Node, Node > d_func_inv;
std::map< Node, Node > d_inv_to_func;
@@ -173,8 +200,8 @@ public:
std::vector< Node > d_func_vars; //the first-order variables corresponding to all functions
std::vector< Node > d_si_vars; //the arguments that we based the anti-skolemization on
std::vector< Node > d_all_vars; //every free variable of conjuncts[2]
- // si, nsi, all
- std::vector< Node > d_conjuncts[3];
+ // si, nsi, all, non-ground si
+ std::vector< Node > d_conjuncts[4];
bool isAntiSkolemizableType( Node f );
@@ -187,12 +214,14 @@ public:
void extractInvariant( Node n, Node& func, int& pol, std::vector< Node >& disjuncts );
+ bool isPurelySingleInvocation() { return d_conjuncts[1].empty(); }
+ bool isNonGroundSingleInvocation() { return d_conjuncts[3].size()==d_conjuncts[1].size(); }
+
void debugPrint( const char * c );
};
-
-}
-}
-}
+}/* namespace CVC4::theory::quantifiers */
+}/* namespace CVC4::theory */
+}/* namespace CVC4 */
#endif
diff --git a/src/theory/quantifiers/ce_guided_single_inv_ei.cpp b/src/theory/quantifiers/ce_guided_single_inv_ei.cpp
index f45285851..6394fca3d 100644
--- a/src/theory/quantifiers/ce_guided_single_inv_ei.cpp
+++ b/src/theory/quantifiers/ce_guided_single_inv_ei.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file ce_guided_single_inv_ei.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief utility for inferring entailments for cegqi
**
diff --git a/src/theory/quantifiers/ce_guided_single_inv_ei.h b/src/theory/quantifiers/ce_guided_single_inv_ei.h
index 0645c406a..42e0b0820 100644
--- a/src/theory/quantifiers/ce_guided_single_inv_ei.h
+++ b/src/theory/quantifiers/ce_guided_single_inv_ei.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file ce_guided_single_inv_ei.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief utility for inferring entailments for cegqi
**/
diff --git a/src/theory/quantifiers/ce_guided_single_inv_sol.cpp b/src/theory/quantifiers/ce_guided_single_inv_sol.cpp
index 6ba5bed02..240c2ed12 100644
--- a/src/theory/quantifiers/ce_guided_single_inv_sol.cpp
+++ b/src/theory/quantifiers/ce_guided_single_inv_sol.cpp
@@ -1,13 +1,13 @@
/********************* */
-/*! \file ce_guided_single_inv.cpp
+/*! \file ce_guided_single_inv_sol.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief utility for processing single invocation synthesis conjectures
**
diff --git a/src/theory/quantifiers/ce_guided_single_inv_sol.h b/src/theory/quantifiers/ce_guided_single_inv_sol.h
index adcc7bf85..cb6f6bc41 100644
--- a/src/theory/quantifiers/ce_guided_single_inv_sol.h
+++ b/src/theory/quantifiers/ce_guided_single_inv_sol.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file ce_guided_single_inv_sol.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief utility for reconstructing solutions for single invocation synthesis conjectures
**/
diff --git a/src/theory/quantifiers/ceg_instantiator.cpp b/src/theory/quantifiers/ceg_instantiator.cpp
index b02c9a740..da488ea98 100644
--- a/src/theory/quantifiers/ceg_instantiator.cpp
+++ b/src/theory/quantifiers/ceg_instantiator.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file ceg_instantiator.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of counterexample-guided quantifier instantiation
**/
@@ -65,9 +65,9 @@ void CegInstantiator::computeProgVars( Node n ){
}
}
-bool CegInstantiator::addInstantiation( SolvedForm& sf, SolvedForm& ssf, std::vector< Node >& vars,
- std::vector< int >& btyp, Node theta, unsigned i, unsigned effort,
- std::map< Node, Node >& cons, std::vector< Node >& curr_var ){
+bool CegInstantiator::doAddInstantiation( SolvedForm& sf, SolvedForm& ssf, std::vector< Node >& vars,
+ std::vector< int >& btyp, Node theta, unsigned i, unsigned effort,
+ std::map< Node, Node >& cons, std::vector< Node >& curr_var ){
if( i==d_vars.size() ){
//solved for all variables, now construct instantiation
if( !sf.d_has_coeff.empty() ){
@@ -75,12 +75,12 @@ bool CegInstantiator::addInstantiation( SolvedForm& sf, SolvedForm& ssf, std::ve
//use symbolic solved forms
SolvedForm csf;
csf.copy( ssf );
- return addInstantiationCoeff( csf, vars, btyp, 0, cons );
+ return doAddInstantiationCoeff( csf, vars, btyp, 0, cons );
}else{
- return addInstantiationCoeff( sf, vars, btyp, 0, cons );
+ return doAddInstantiationCoeff( sf, vars, btyp, 0, cons );
}
}else{
- return addInstantiation( sf.d_subs, vars, cons );
+ return doAddInstantiation( sf.d_subs, vars, cons );
}
}else{
std::map< Node, std::map< Node, bool > > subs_proc;
@@ -94,16 +94,17 @@ bool CegInstantiator::addInstantiation( SolvedForm& sf, SolvedForm& ssf, std::ve
is_cv = true;
}
TypeNode pvtn = pv.getType();
- Trace("cbqi-inst-debug") << "[Find instantiation for " << pv << "]" << std::endl;
+ TypeNode pvtnb = pvtn.getBaseType();
+ Node pvr = pv;
+ if( d_qe->getMasterEqualityEngine()->hasTerm( pv ) ){
+ pvr = d_qe->getMasterEqualityEngine()->getRepresentative( pv );
+ }
+ Trace("cbqi-inst-debug") << "[Find instantiation for " << pv << "], rep=" << pvr << std::endl;
Node pv_value;
if( options::cbqiModel() ){
pv_value = getModelValue( pv );
Trace("cbqi-bound2") << "...M( " << pv << " ) = " << pv_value << std::endl;
}
- Node pvr = pv;
- if( d_qe->getMasterEqualityEngine()->hasTerm( pv ) ){
- pvr = d_qe->getMasterEqualityEngine()->getRepresentative( pv );
- }
//if in effort=2, we must choose at least one model value
if( (i+1)<d_vars.size() || effort!=2 ){
@@ -138,53 +139,89 @@ bool CegInstantiator::addInstantiation( SolvedForm& sf, SolvedForm& ssf, std::ve
if( proc ){
//try the substitution
subs_proc[ns][pv_coeff] = true;
- if( addInstantiationInc( ns, pv, pv_coeff, 0, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
+ if( doAddInstantiationInc( ns, pv, pv_coeff, 0, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
return true;
}
}
}
}
}
+ if( pvtn.isDatatype() ){
+ Trace("cbqi-inst-debug") << "[2] try based on constructors in equivalence class." << std::endl;
+ //[2] look in equivalence class for a constructor
+ for( unsigned k=0; k<it_eqc->second.size(); k++ ){
+ Node n = it_eqc->second[k];
+ if( n.getKind()==APPLY_CONSTRUCTOR ){
+ Trace("cbqi-inst-debug") << "... " << i << "...try based on constructor term " << n << std::endl;
+ cons[pv] = n.getOperator();
+ const Datatype& dt = ((DatatypeType)(pvtn).toType()).getDatatype();
+ unsigned cindex = Datatype::indexOf( n.getOperator().toExpr() );
+ if( is_cv ){
+ curr_var.pop_back();
+ }
+ //now must solve for selectors applied to pv
+ for( unsigned j=0; j<dt[cindex].getNumArgs(); j++ ){
+ curr_var.push_back( NodeManager::currentNM()->mkNode( APPLY_SELECTOR_TOTAL, Node::fromExpr( dt[cindex][j].getSelector() ), pv ) );
+ }
+ if( doAddInstantiation( sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
+ return true;
+ }else{
+ //cleanup
+ cons.erase( pv );
+ Assert( curr_var.size()>=dt[cindex].getNumArgs() );
+ for( unsigned j=0; j<dt[cindex].getNumArgs(); j++ ){
+ curr_var.pop_back();
+ }
+ if( is_cv ){
+ curr_var.push_back( pv );
+ }
+ break;
+ }
+ }
+ }
+ }
}else{
Trace("cbqi-inst-debug2") << "...eqc not found." << std::endl;
}
- //[2] : we can solve an equality for pv
- if( pvtn.isInteger() || pvtn.isReal() ){
- ///iterate over equivalence classes to find cases where we can solve for the variable
- TypeNode pvtnb = pvtn.getBaseType();
- Trace("cbqi-inst-debug") << "[2] try based on solving arithmetic equivalence classes." << std::endl;
- for( unsigned k=0; k<d_curr_type_eqc[pvtnb].size(); k++ ){
- Node r = d_curr_type_eqc[pvtnb][k];
- std::map< Node, std::vector< Node > >::iterator it_reqc = d_curr_eqc.find( r );
- std::vector< Node > lhs;
- std::vector< bool > lhs_v;
- std::vector< Node > lhs_coeff;
- Assert( it_reqc!=d_curr_eqc.end() );
- for( unsigned kk=0; kk<it_reqc->second.size(); kk++ ){
- Node n = it_reqc->second[kk];
- Trace("cbqi-inst-debug2") << "...look at term " << n << std::endl;
- //compute the variables in n
- computeProgVars( n );
- //must be an eligible term
- if( d_inelig.find( n )==d_inelig.end() ){
- Node ns;
- Node pv_coeff;
- if( !d_prog_var[n].empty() ){
- ns = applySubstitution( pvtn, n, sf, vars, pv_coeff );
- if( !ns.isNull() ){
- computeProgVars( ns );
- }
- }else{
- ns = n;
- }
+ //[3] : we can solve an equality for pv
+ ///iterate over equivalence classes to find cases where we can solve for the variable
+ Trace("cbqi-inst-debug") << "[3] try based on solving equalities." << std::endl;
+ for( unsigned k=0; k<d_curr_type_eqc[pvtnb].size(); k++ ){
+ Node r = d_curr_type_eqc[pvtnb][k];
+ std::map< Node, std::vector< Node > >::iterator it_reqc = d_curr_eqc.find( r );
+ std::vector< Node > lhs;
+ std::vector< bool > lhs_v;
+ std::vector< Node > lhs_coeff;
+ Assert( it_reqc!=d_curr_eqc.end() );
+ for( unsigned kk=0; kk<it_reqc->second.size(); kk++ ){
+ Node n = it_reqc->second[kk];
+ Trace("cbqi-inst-debug2") << "...look at term " << n << std::endl;
+ //compute the variables in n
+ computeProgVars( n );
+ //must be an eligible term
+ if( d_inelig.find( n )==d_inelig.end() ){
+ Node ns;
+ Node pv_coeff;
+ if( !d_prog_var[n].empty() ){
+ ns = applySubstitution( pvtn, n, sf, vars, pv_coeff );
if( !ns.isNull() ){
- bool hasVar = d_prog_var[ns].find( pv )!=d_prog_var[ns].end();
- Trace("cbqi-inst-debug2") << "... " << ns << " has var " << pv << " : " << hasVar << std::endl;
- for( unsigned j=0; j<lhs.size(); j++ ){
- //if this term or the another has pv in it, try to solve for it
- if( hasVar || lhs_v[j] ){
- Trace("cbqi-inst-debug") << "... " << i << "...try based on equality " << lhs[j] << " = " << ns << std::endl;
+ computeProgVars( ns );
+ }
+ }else{
+ ns = n;
+ }
+ if( !ns.isNull() ){
+ bool hasVar = d_prog_var[ns].find( pv )!=d_prog_var[ns].end();
+ Trace("cbqi-inst-debug2") << "... " << ns << " has var " << pv << " : " << hasVar << std::endl;
+ for( unsigned j=0; j<lhs.size(); j++ ){
+ //if this term or the another has pv in it, try to solve for it
+ if( hasVar || lhs_v[j] ){
+ Trace("cbqi-inst-debug") << "... " << i << "...try based on equality " << lhs[j] << " = " << ns << std::endl;
+ Node val;
+ Node veq_c;
+ bool success = false;
+ if( pvtnb.isReal() ){
Node eq_lhs = lhs[j];
Node eq_rhs = ns;
//make the same coefficient
@@ -204,17 +241,10 @@ bool CegInstantiator::addInstantiation( SolvedForm& sf, SolvedForm& ssf, std::ve
eq = Rewriter::rewrite( eq );
Node vts_coeff_inf;
Node vts_coeff_delta;
- Node val;
- Node veq_c;
//isolate pv in the equality
- int ires = isolate( pv, eq, veq_c, val, vts_coeff_inf, vts_coeff_delta );
+ int ires = solve_arith( pv, eq, veq_c, val, vts_coeff_inf, vts_coeff_delta );
if( ires!=0 ){
- if( subs_proc[val].find( veq_c )==subs_proc[val].end() ){
- subs_proc[val][veq_c] = true;
- if( addInstantiationInc( val, pv, veq_c, 0, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
- return true;
- }
- }
+ success = true;
}
/*
//cannot contain infinity?
@@ -240,67 +270,43 @@ bool CegInstantiator::addInstantiation( SolvedForm& sf, SolvedForm& ssf, std::ve
Node val = veq[1];
if( subs_proc[val].find( veq_c )==subs_proc[val].end() ){
subs_proc[val][veq_c] = true;
- if( addInstantiationInc( val, pv, veq_c, 0, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
+ if( doAddInstantiationInc( val, pv, veq_c, 0, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
return true;
}
}
}
}
*/
+ }else if( pvtnb.isDatatype() ){
+ val = solve_dt( pv, lhs[j], ns, lhs[j], ns );
+ if( !val.isNull() ){
+ success = true;
+ }
+ }
+ if( success ){
+ if( subs_proc[val].find( veq_c )==subs_proc[val].end() ){
+ subs_proc[val][veq_c] = true;
+ if( doAddInstantiationInc( val, pv, veq_c, 0, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
+ return true;
+ }
+ }
}
}
- lhs.push_back( ns );
- lhs_v.push_back( hasVar );
- lhs_coeff.push_back( pv_coeff );
- }else{
- Trace("cbqi-inst-debug2") << "... term " << n << " is ineligible after substitution." << std::endl;
}
+ lhs.push_back( ns );
+ lhs_v.push_back( hasVar );
+ lhs_coeff.push_back( pv_coeff );
}else{
- Trace("cbqi-inst-debug2") << "... term " << n << " is ineligible." << std::endl;
- }
- }
- }
- }else if( pvtn.isDatatype() ){
- Trace("cbqi-inst-debug") << "[2] try based on constructors in equivalence class." << std::endl;
- //look in equivalence class for a constructor
- if( it_eqc!=d_curr_eqc.end() ){
- for( unsigned k=0; k<it_eqc->second.size(); k++ ){
- Node n = it_eqc->second[k];
- if( n.getKind()==APPLY_CONSTRUCTOR ){
- Trace("cbqi-inst-debug") << "... " << i << "...try based on constructor term " << n << std::endl;
- cons[pv] = n.getOperator();
- const Datatype& dt = ((DatatypeType)(pvtn).toType()).getDatatype();
- unsigned cindex = Datatype::indexOf( n.getOperator().toExpr() );
- if( is_cv ){
- curr_var.pop_back();
- }
- //now must solve for selectors applied to pv
- for( unsigned j=0; j<dt[cindex].getNumArgs(); j++ ){
- curr_var.push_back( NodeManager::currentNM()->mkNode( APPLY_SELECTOR_TOTAL, Node::fromExpr( dt[cindex][j].getSelector() ), pv ) );
- }
- if( addInstantiation( sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
- return true;
- }else{
- //cleanup
- cons.erase( pv );
- Assert( curr_var.size()>=dt[cindex].getNumArgs() );
- for( unsigned j=0; j<dt[cindex].getNumArgs(); j++ ){
- curr_var.pop_back();
- }
- if( is_cv ){
- curr_var.push_back( pv );
- }
- break;
- }
+ Trace("cbqi-inst-debug2") << "... term " << n << " is ineligible after substitution." << std::endl;
}
+ }else{
+ Trace("cbqi-inst-debug2") << "... term " << n << " is ineligible." << std::endl;
}
- }else{
- Trace("cbqi-inst-debug2") << "... " << i << " does not have an eqc." << std::endl;
}
}
- //[3] directly look at assertions
- Trace("cbqi-inst-debug") << "[3] try based on assertions." << std::endl;
+ //[4] directly look at assertions
+ Trace("cbqi-inst-debug") << "[4] try based on assertions." << std::endl;
d_vts_sym[0] = d_qe->getTermDatabase()->getVtsInfinity( pvtn, false, false );
d_vts_sym[1] = d_qe->getTermDatabase()->getVtsDelta( false, false );
std::vector< Node > mbp_bounds[2];
@@ -360,7 +366,7 @@ bool CegInstantiator::addInstantiation( SolvedForm& sf, SolvedForm& ssf, std::ve
Node val;
Node veq_c;
//isolate pv in the inequality
- int ires = isolate( pv, satom, veq_c, val, vts_coeff_inf, vts_coeff_delta );
+ int ires = solve_arith( pv, satom, veq_c, val, vts_coeff_inf, vts_coeff_delta );
if( ires!=0 ){
//disequalities are either strict upper or lower bounds
unsigned rmax = ( atom.getKind()==GEQ && options::cbqiModel() ) ? 1 : 2;
@@ -449,7 +455,7 @@ bool CegInstantiator::addInstantiation( SolvedForm& sf, SolvedForm& ssf, std::ve
//try this bound
if( subs_proc[uval].find( veq_c )==subs_proc[uval].end() ){
subs_proc[uval][veq_c] = true;
- if( addInstantiationInc( uval, pv, veq_c, uires>0 ? 1 : -1, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
+ if( doAddInstantiationInc( uval, pv, veq_c, uires>0 ? 1 : -1, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
return true;
}
}
@@ -486,7 +492,7 @@ bool CegInstantiator::addInstantiation( SolvedForm& sf, SolvedForm& ssf, std::ve
val = NodeManager::currentNM()->mkNode( UMINUS, val );
val = Rewriter::rewrite( val );
}
- if( addInstantiationInc( val, pv, Node::null(), 0, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
+ if( doAddInstantiationInc( val, pv, Node::null(), 0, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
return true;
}
}
@@ -582,7 +588,7 @@ bool CegInstantiator::addInstantiation( SolvedForm& sf, SolvedForm& ssf, std::ve
if( !val.isNull() ){
if( subs_proc[val].find( mbp_coeff[rr][best] )==subs_proc[val].end() ){
subs_proc[val][mbp_coeff[rr][best]] = true;
- if( addInstantiationInc( val, pv, mbp_coeff[rr][best], rr==0 ? 1 : -1, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
+ if( doAddInstantiationInc( val, pv, mbp_coeff[rr][best], rr==0 ? 1 : -1, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
return true;
}
}
@@ -599,7 +605,7 @@ bool CegInstantiator::addInstantiation( SolvedForm& sf, SolvedForm& ssf, std::ve
if( !val.isNull() ){
if( subs_proc[val].find( c )==subs_proc[val].end() ){
subs_proc[val][c] = true;
- if( addInstantiationInc( val, pv, c, 0, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
+ if( doAddInstantiationInc( val, pv, c, 0, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
return true;
}
}
@@ -643,7 +649,7 @@ bool CegInstantiator::addInstantiation( SolvedForm& sf, SolvedForm& ssf, std::ve
if( !val.isNull() ){
if( subs_proc[val].find( Node::null() )==subs_proc[val].end() ){
subs_proc[val][Node::null()] = true;
- if( addInstantiationInc( val, pv, Node::null(), 0, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
+ if( doAddInstantiationInc( val, pv, Node::null(), 0, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
return true;
}
}
@@ -664,7 +670,7 @@ bool CegInstantiator::addInstantiation( SolvedForm& sf, SolvedForm& ssf, std::ve
if( !val.isNull() ){
if( subs_proc[val].find( mbp_coeff[rr][j] )==subs_proc[val].end() ){
subs_proc[val][mbp_coeff[rr][j]] = true;
- if( addInstantiationInc( val, pv, mbp_coeff[rr][j], rr==0 ? 1 : -1, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
+ if( doAddInstantiationInc( val, pv, mbp_coeff[rr][j], rr==0 ? 1 : -1, sf, ssf, vars, btyp, theta, i, effort, cons, curr_var ) ){
return true;
}
}
@@ -677,18 +683,18 @@ bool CegInstantiator::addInstantiation( SolvedForm& sf, SolvedForm& ssf, std::ve
}
}
- //[4] resort to using value in model
+ //[5] resort to using value in model
// do so if we are in effort=1, or if the variable is boolean, or if we are solving for a subfield of a datatype
if( ( effort>0 || pvtn.isBoolean() || !curr_var.empty() ) && d_qe->getTermDatabase()->isClosedEnumerableType( pvtn ) ){
Node mv = getModelValue( pv );
Node pv_coeff_m;
- Trace("cbqi-inst-debug") << "[4] " << i << "...try model value " << mv << std::endl;
+ Trace("cbqi-inst-debug") << "[5] " << i << "...try model value " << mv << std::endl;
int new_effort = pvtn.isBoolean() ? effort : 1;
#ifdef MBP_STRICT_ASSERTIONS
//we only resort to values in the case of booleans
Assert( ( pvtn.isInteger() ? !options::cbqiUseInfInt() : !options::cbqiUseInfReal() ) || pvtn.isBoolean() );
#endif
- if( addInstantiationInc( mv, pv, pv_coeff_m, 0, sf, ssf, vars, btyp, theta, i, new_effort, cons, curr_var ) ){
+ if( doAddInstantiationInc( mv, pv, pv_coeff_m, 0, sf, ssf, vars, btyp, theta, i, new_effort, cons, curr_var ) ){
return true;
}
}
@@ -698,9 +704,9 @@ bool CegInstantiator::addInstantiation( SolvedForm& sf, SolvedForm& ssf, std::ve
}
-bool CegInstantiator::addInstantiationInc( Node n, Node pv, Node pv_coeff, int bt, SolvedForm& sf, SolvedForm& ssf, std::vector< Node >& vars,
- std::vector< int >& btyp, Node theta, unsigned i, unsigned effort,
- std::map< Node, Node >& cons, std::vector< Node >& curr_var ) {
+bool CegInstantiator::doAddInstantiationInc( Node n, Node pv, Node pv_coeff, int bt, SolvedForm& sf, SolvedForm& ssf, std::vector< Node >& vars,
+ std::vector< int >& btyp, Node theta, unsigned i, unsigned effort,
+ std::map< Node, Node >& cons, std::vector< Node >& curr_var ) {
if( Trace.isOn("cbqi-inst") ){
for( unsigned j=0; j<sf.d_subs.size(); j++ ){
Trace("cbqi-inst") << " ";
@@ -794,7 +800,7 @@ bool CegInstantiator::addInstantiationInc( Node n, Node pv, Node pv_coeff, int b
curr_var.pop_back();
is_cv = true;
}
- success = addInstantiation( sf, ssf, vars, btyp, new_theta, curr_var.empty() ? i+1 : i, effort, cons, curr_var );
+ success = doAddInstantiation( sf, ssf, vars, btyp, new_theta, curr_var.empty() ? i+1 : i, effort, cons, curr_var );
if( !success ){
if( is_cv ){
curr_var.push_back( pv );
@@ -825,12 +831,12 @@ bool CegInstantiator::addInstantiationInc( Node n, Node pv, Node pv_coeff, int b
}
}
-bool CegInstantiator::addInstantiationCoeff( SolvedForm& sf, std::vector< Node >& vars, std::vector< int >& btyp,
+bool CegInstantiator::doAddInstantiationCoeff( SolvedForm& sf, std::vector< Node >& vars, std::vector< int >& btyp,
unsigned j, std::map< Node, Node >& cons ) {
if( j==sf.d_has_coeff.size() ){
- return addInstantiation( sf.d_subs, vars, cons );
+ return doAddInstantiation( sf.d_subs, vars, cons );
}else{
Assert( std::find( vars.begin(), vars.end(), sf.d_has_coeff[j] )!=vars.end() );
unsigned index = std::find( vars.begin(), vars.end(), sf.d_has_coeff[j] )-vars.begin();
@@ -888,7 +894,7 @@ bool CegInstantiator::addInstantiationCoeff( SolvedForm& sf, std::vector< Node >
}
}
}
- if( addInstantiationCoeff( sf, vars, btyp, j+1, cons ) ){
+ if( doAddInstantiationCoeff( sf, vars, btyp, j+1, cons ) ){
return true;
}
}
@@ -899,7 +905,7 @@ bool CegInstantiator::addInstantiationCoeff( SolvedForm& sf, std::vector< Node >
}
}
-bool CegInstantiator::addInstantiation( std::vector< Node >& subs, std::vector< Node >& vars, std::map< Node, Node >& cons ) {
+bool CegInstantiator::doAddInstantiation( std::vector< Node >& subs, std::vector< Node >& vars, std::map< Node, Node >& cons ) {
if( vars.size()>d_vars.size() ){
Trace("cbqi-inst-debug") << "Reconstructing instantiations...." << std::endl;
std::map< Node, Node > subs_map;
@@ -921,7 +927,7 @@ bool CegInstantiator::addInstantiation( std::vector< Node >& subs, std::vector<
subs.push_back( subs_orig[d_var_order_index[i]] );
}
}
- bool ret = d_out->addInstantiation( subs );
+ bool ret = d_out->doAddInstantiation( subs );
#ifdef MBP_STRICT_ASSERTIONS
Assert( ret );
#endif
@@ -1121,7 +1127,7 @@ bool CegInstantiator::check() {
std::map< Node, Node > cons;
std::vector< Node > curr_var;
//try to add an instantiation
- if( addInstantiation( sf, ssf, vars, btyp, theta, 0, r==0 ? 0 : 2, cons, curr_var ) ){
+ if( doAddInstantiation( sf, ssf, vars, btyp, theta, 0, r==0 ? 0 : 2, cons, curr_var ) ){
return true;
}
}
@@ -1493,8 +1499,10 @@ void CegInstantiator::registerCounterexampleLemma( std::vector< Node >& lems, st
}
}
-//this isolates the monomial sum into solved form (pv k t), ensures t is Int if pv is Int, and t does not contain vts symbols
-int CegInstantiator::isolate( Node pv, Node atom, Node& veq_c, Node& val, Node& vts_coeff_inf, Node& vts_coeff_delta ) {
+//this isolates the atom into solved form
+// veq_c * pv <> val + vts_coeff_delta * delta + vts_coeff_inf * inf
+// ensures val is Int if pv is Int, and val does not contain vts symbols
+int CegInstantiator::solve_arith( Node pv, Node atom, Node& veq_c, Node& val, Node& vts_coeff_inf, Node& vts_coeff_delta ) {
int ires = 0;
Trace("cbqi-inst-debug") << "isolate for " << pv << " in " << atom << std::endl;
std::map< Node, Node > msum;
@@ -1602,6 +1610,46 @@ int CegInstantiator::isolate( Node pv, Node atom, Node& veq_c, Node& val, Node&
vts_coeff_inf = vts_coeff[0];
vts_coeff_delta = vts_coeff[1];
}
-
return ires;
}
+
+Node CegInstantiator::solve_dt( Node v, Node a, Node b, Node sa, Node sb ) {
+ Trace("cbqi-inst-debug2") << "Solve dt : " << v << " " << a << " " << b << " " << sa << " " << sb << std::endl;
+ Node ret;
+ if( !a.isNull() && a==v ){
+ ret = sb;
+ }else if( !b.isNull() && b==v ){
+ ret = sa;
+ }else if( !a.isNull() && a.getKind()==APPLY_CONSTRUCTOR ){
+ if( !b.isNull() && b.getKind()==APPLY_CONSTRUCTOR ){
+ if( a.getOperator()==b.getOperator() ){
+ for( unsigned i=0; i<a.getNumChildren(); i++ ){
+ Node s = solve_dt( v, a[i], b[i], sa[i], sb[i] );
+ if( !s.isNull() ){
+ return s;
+ }
+ }
+ }
+ }else{
+ unsigned cindex = Datatype::indexOf( a.getOperator().toExpr() );
+ TypeNode tn = a.getType();
+ const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
+ for( unsigned i=0; i<a.getNumChildren(); i++ ){
+ Node nn = NodeManager::currentNM()->mkNode( APPLY_SELECTOR_TOTAL, Node::fromExpr( dt[cindex][i].getSelector() ), sb );
+ Node s = solve_dt( v, a[i], Node::null(), sa[i], nn );
+ if( !s.isNull() ){
+ return s;
+ }
+ }
+ }
+ }else if( !b.isNull() && b.getKind()==APPLY_CONSTRUCTOR ){
+ return solve_dt( v, b, a, sb, sa );
+ }
+ if( !ret.isNull() ){
+ //ensure does not contain
+ if( TermDb::containsTerm( ret, v ) ){
+ ret = Node::null();
+ }
+ }
+ return ret;
+}
diff --git a/src/theory/quantifiers/ceg_instantiator.h b/src/theory/quantifiers/ceg_instantiator.h
index 9504bd407..3d7bbcb55 100644
--- a/src/theory/quantifiers/ceg_instantiator.h
+++ b/src/theory/quantifiers/ceg_instantiator.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file ceg_instantiator.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief counterexample-guided quantifier instantiation
**/
@@ -33,7 +33,7 @@ namespace quantifiers {
class CegqiOutput {
public:
virtual ~CegqiOutput() {}
- virtual bool addInstantiation( std::vector< Node >& subs ) = 0;
+ virtual bool doAddInstantiation( std::vector< Node >& subs ) = 0;
virtual bool isEligibleForInstantiation( Node n ) = 0;
virtual bool addLemma( Node lem ) = 0;
};
@@ -108,16 +108,16 @@ private:
};
*/
// effort=0 : do not use model value, 1: use model value, 2: one must use model value
- bool addInstantiation( SolvedForm& sf, SolvedForm& ssf, std::vector< Node >& vars,
+ bool doAddInstantiation( SolvedForm& sf, SolvedForm& ssf, std::vector< Node >& vars,
std::vector< int >& btyp, Node theta, unsigned i, unsigned effort,
std::map< Node, Node >& cons, std::vector< Node >& curr_var );
- bool addInstantiationInc( Node n, Node pv, Node pv_coeff, int bt, SolvedForm& sf, SolvedForm& ssf, std::vector< Node >& vars,
+ bool doAddInstantiationInc( Node n, Node pv, Node pv_coeff, int bt, SolvedForm& sf, SolvedForm& ssf, std::vector< Node >& vars,
std::vector< int >& btyp, Node theta, unsigned i, unsigned effort,
std::map< Node, Node >& cons, std::vector< Node >& curr_var );
- bool addInstantiationCoeff( SolvedForm& sf,
+ bool doAddInstantiationCoeff( SolvedForm& sf,
std::vector< Node >& vars, std::vector< int >& btyp,
unsigned j, std::map< Node, Node >& cons );
- bool addInstantiation( std::vector< Node >& subs, std::vector< Node >& vars, std::map< Node, Node >& cons );
+ bool doAddInstantiation( std::vector< Node >& subs, std::vector< Node >& vars, std::map< Node, Node >& cons );
Node constructInstantiation( Node n, std::map< Node, Node >& subs_map, std::map< Node, Node >& cons );
Node applySubstitution( TypeNode tn, Node n, SolvedForm& sf, std::vector< Node >& vars, Node& pv_coeff, bool try_coeff = true ) {
return applySubstitution( tn, n, sf.d_subs, sf.d_coeff, sf.d_has_coeff, vars, pv_coeff, try_coeff );
@@ -130,7 +130,8 @@ private:
//get model value
Node getModelValue( Node n );
private:
- int isolate( Node v, Node atom, Node & veq_c, Node & val, Node& vts_coeff_inf, Node& vts_coeff_delta );
+ int solve_arith( Node v, Node atom, Node & veq_c, Node & val, Node& vts_coeff_inf, Node& vts_coeff_delta );
+ Node solve_dt( Node v, Node a, Node b, Node sa, Node sb );
public:
CegInstantiator( QuantifiersEngine * qe, CegqiOutput * out, bool use_vts_delta = true, bool use_vts_inf = true );
//check : add instantiations based on valuation of d_vars
diff --git a/src/theory/quantifiers/conjecture_generator.cpp b/src/theory/quantifiers/conjecture_generator.cpp
index 8e083ae1e..2cc49ef5a 100644
--- a/src/theory/quantifiers/conjecture_generator.cpp
+++ b/src/theory/quantifiers/conjecture_generator.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file conjecture_generator.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Clark Barrett, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief conjecture generator class
**
@@ -34,7 +34,7 @@ struct sortConjectureScore {
};
-void OpArgIndex::addTerm( ConjectureGenerator * s, TNode n, unsigned index ){
+void OpArgIndex::addTerm( std::vector< TNode >& terms, TNode n, unsigned index ){
if( index==n.getNumChildren() ){
Assert( n.hasOperator() );
if( std::find( d_ops.begin(), d_ops.end(), n.getOperator() )==d_ops.end() ){
@@ -42,7 +42,7 @@ void OpArgIndex::addTerm( ConjectureGenerator * s, TNode n, unsigned index ){
d_op_terms.push_back( n );
}
}else{
- d_child[s->getTermDatabase()->d_arg_reps[n][index]].addTerm( s, n, index+1 );
+ d_child[terms[index]].addTerm( terms, n, index+1 );
}
}
@@ -369,7 +369,7 @@ void ConjectureGenerator::check( Theory::Effort e, unsigned quant_e ) {
TNode n = (*ieqc_i);
if( getTermDatabase()->hasTermCurrent( n ) ){
if( isHandledTerm( n ) ){
- d_op_arg_index[r].addTerm( this, n );
+ d_op_arg_index[r].addTerm( getTermDatabase()->d_arg_reps[n], n );
}
}
++ieqc_i;
@@ -489,7 +489,7 @@ void ConjectureGenerator::check( Theory::Effort e, unsigned quant_e ) {
d_thm_index.clear();
std::vector< Node > provenConj;
quantifiers::FirstOrderModel* m = d_quantEngine->getModel();
- for( int i=0; i<m->getNumAssertedQuantifiers(); i++ ){
+ for( unsigned i=0; i<m->getNumAssertedQuantifiers(); i++ ){
Node q = m->getAssertedQuantifier( i );
Trace("thm-db-debug") << "Is " << q << " a relevant theorem?" << std::endl;
Node conjEq;
@@ -605,7 +605,8 @@ void ConjectureGenerator::check( Theory::Effort e, unsigned quant_e ) {
std::vector< TypeNode > rt_types;
std::map< TypeNode, std::map< int, std::vector< Node > > > conj_lhs;
unsigned addedLemmas = 0;
- for( unsigned depth=1; depth<=3; depth++ ){
+ unsigned maxDepth = options::conjectureGenMaxDepth();
+ for( unsigned depth=1; depth<=maxDepth; depth++ ){
Trace("sg-proc") << "Generate relevant LHS at depth " << depth << "..." << std::endl;
Trace("sg-rel-term") << "Relevant terms of depth " << depth << " : " << std::endl;
//set up environment
@@ -1167,6 +1168,8 @@ void ConjectureGenerator::processCandidateConjecture( TNode lhs, TNode rhs, unsi
d_waiting_conjectures_score.push_back( score );
d_waiting_conjectures[lhs].push_back( rhs );
d_waiting_conjectures[rhs].push_back( lhs );
+ }else{
+ Trace("sg-conjecture-debug2") << "...do not consider " << lhs << " == " << rhs << ", score = " << score << std::endl;
}
}
@@ -1273,7 +1276,7 @@ bool ConjectureGenerator::notifySubstitution( TNode glhs, std::map< TNode, TNode
}
Trace("sg-cconj-debug") << "Evaluate RHS : : " << rhs << std::endl;
//get the representative of rhs with substitution subs
- TNode grhs = getTermDatabase()->evaluateTerm( rhs, subs, true );
+ TNode grhs = getTermDatabase()->getEntailedTerm( rhs, subs, true );
Trace("sg-cconj-debug") << "...done evaluating term, got : " << grhs << std::endl;
if( !grhs.isNull() ){
if( glhs!=grhs ){
@@ -1569,10 +1572,12 @@ bool TermGenerator::getNextMatch( TermGenEnv * s, TNode eqc, std::map< TypeNode,
if( d_match_status_child_num==0 ){
//initial binding
TNode f = s->getTgFunc( d_typ, d_status_num );
- std::map< TNode, TermArgTrie >::iterator it = s->getTermDatabase()->d_func_map_eqc_trie[f].d_data.find( eqc );
- if( it!=s->getTermDatabase()->d_func_map_eqc_trie[f].d_data.end() ){
- d_match_children.push_back( it->second.d_data.begin() );
- d_match_children_end.push_back( it->second.d_data.end() );
+ //std::map< TNode, TermArgTrie >::iterator it = s->getTermDatabase()->d_func_map_eqc_trie[f].d_data.find( eqc );
+ Assert( !eqc.isNull() );
+ TermArgTrie * tat = s->getTermDatabase()->getTermArgTrie( eqc, f );
+ if( tat ){
+ d_match_children.push_back( tat->d_data.begin() );
+ d_match_children_end.push_back( tat->d_data.end() );
}else{
d_match_status++;
d_match_status_child_num--;
diff --git a/src/theory/quantifiers/conjecture_generator.h b/src/theory/quantifiers/conjecture_generator.h
index 3aa932296..c89d0f2ee 100644
--- a/src/theory/quantifiers/conjecture_generator.h
+++ b/src/theory/quantifiers/conjecture_generator.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file conjecture_generator.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Clark Barrett, Tim King, Andrew Reynolds
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief conjecture generator class
**/
@@ -39,7 +39,7 @@ public:
std::map< TNode, OpArgIndex > d_child;
std::vector< TNode > d_ops;
std::vector< TNode > d_op_terms;
- void addTerm( ConjectureGenerator * s, TNode n, unsigned index = 0 );
+ void addTerm( std::vector< TNode >& terms, TNode n, unsigned index = 0 );
Node getGroundTerm( ConjectureGenerator * s, std::vector< TNode >& args );
void getGroundTerms( ConjectureGenerator * s, std::vector< TNode >& terms );
};
diff --git a/src/theory/quantifiers/equality_infer.cpp b/src/theory/quantifiers/equality_infer.cpp
new file mode 100644
index 000000000..c3064116f
--- /dev/null
+++ b/src/theory/quantifiers/equality_infer.cpp
@@ -0,0 +1,427 @@
+/********************* */
+/*! \file equality_infer.cpp
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2016 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.\endverbatim
+ **
+ ** \brief Method for inferring equalities between arithmetic equivalence classes,
+ ** inspired by "A generalization of Shostak's method for combining decision procedures" Barrett et al. Figure 1.
+ **
+ **/
+
+#include "theory/quantifiers/equality_infer.h"
+#include "theory/quantifiers/quant_util.h"
+#include "context/context_mm.h"
+
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::theory;
+using namespace CVC4::theory::quantifiers;
+using namespace std;
+
+namespace CVC4 {
+
+EqualityInference::EqcInfo::EqcInfo(context::Context* c) : d_rep( c ), d_valid( c, false ), d_solved( c, false ), d_master(c)
+//, d_rep_exp(c), d_uselist(c)
+{
+
+}
+
+EqualityInference::EqualityInference( context::Context* c, bool trackExp ) :
+d_c( c ), d_trackExplain( trackExp ), d_elim_vars( c ),
+d_rep_to_eqc( c ), d_rep_exp( c ), d_uselist( c ), d_pending_merges( c ), d_pending_merge_exp( c ){
+ d_one = NodeManager::currentNM()->mkConst( Rational( 1 ) );
+ d_true = NodeManager::currentNM()->mkConst( true );
+}
+
+EqualityInference::~EqualityInference(){
+ for( std::map< Node, EqcInfo * >::iterator it = d_eqci.begin(); it != d_eqci.end(); ++it ){
+ delete it->second;
+ }
+}
+
+void EqualityInference::addToExplanation( std::vector< Node >& exp, Node e ) {
+ if( std::find( exp.begin(), exp.end(), e )==exp.end() ){
+ Trace("eq-infer-debug2") << "......add to explanation " << e << std::endl;
+ exp.push_back( e );
+ }
+}
+
+void EqualityInference::addToExplanationEqc( std::vector< Node >& exp, Node eqc ) {
+ NodeListMap::iterator re_i = d_rep_exp.find( eqc );
+ if( re_i!=d_rep_exp.end() ){
+ for( unsigned i=0; i<(*re_i).second->size(); i++ ){
+ addToExplanation( exp, (*(*re_i).second)[i] );
+ }
+ }
+ //for( unsigned i=0; i<d_eqci[n]->d_rep_exp.size(); i++ ){
+ // addToExplanation( exp, d_eqci[n]->d_rep_exp[i] );
+ //}
+}
+
+void EqualityInference::addToExplanationEqc( Node eqc, std::vector< Node >& exp_to_add ) {
+ NodeListMap::iterator re_i = d_rep_exp.find( eqc );
+ NodeList* re;
+ if( re_i != d_rep_exp.end() ){
+ re = (*re_i).second;
+ }else{
+ re = new(d_c->getCMM()) NodeList( true, d_c, false, context::ContextMemoryAllocator<TNode>(d_c->getCMM()) );
+ d_rep_exp.insertDataFromContextMemory( eqc, re );
+ }
+ for( unsigned i=0; i<exp_to_add.size(); i++ ){
+ re->push_back( exp_to_add[i] );
+ }
+ //for( unsigned i=0; i<exp_to_add.size(); i++ ){
+ // eqci->d_rep_exp.push_back( exp_to_add[i] );
+ //}
+}
+
+Node EqualityInference::getMaster( Node t, EqcInfo * eqc, bool& updated, Node new_m ) {
+ if( !eqc->d_master.get().isNull() ){
+ if( eqc->d_master.get()==t ){
+ if( !new_m.isNull() && t!=new_m ){
+ eqc->d_master = new_m;
+ updated = true;
+ return new_m;
+ }else{
+ return t;
+ }
+ }else{
+ Assert( d_eqci.find( eqc->d_master.get() )!=d_eqci.end() );
+ EqcInfo * eqc_m = d_eqci[eqc->d_master.get()];
+ Node m = getMaster( eqc->d_master.get(), eqc_m, updated, new_m );
+ eqc->d_master = m;
+ return m;
+ }
+ }else{
+ return Node::null();
+ }
+}
+
+//update the internal "master" representative of the equivalence class, return true if the merge was non-redundant
+bool EqualityInference::updateMaster( Node t1, Node t2, EqcInfo * eqc1, EqcInfo * eqc2 ) {
+ bool updated = false;
+ Node m1 = getMaster( t1, eqc1, updated );
+ if( m1.isNull() ){
+ eqc1->d_master = t2;
+ if( eqc2->d_master.get().isNull() ){
+ eqc2->d_master = t2;
+ }
+ return true;
+ }else{
+ updated = false;
+ Node m2 = getMaster( t2, eqc2, updated, m1);
+ if( m2.isNull() ){
+ eqc2->d_master = m1;
+ return true;
+ }else{
+ return updated;
+ }
+ }
+}
+
+void EqualityInference::eqNotifyNewClass(TNode t) {
+ if( t.getType().isReal() ){
+ Trace("eq-infer") << "Notify equivalence class : " << t << std::endl;
+ EqcInfo * eqci;
+ std::map< Node, EqcInfo * >::iterator itec = d_eqci.find( t );
+ if( itec==d_eqci.end() ){
+ eqci = new EqcInfo( d_c );
+ d_eqci[t] = eqci;
+ }else{
+ eqci = itec->second;
+ }
+ Assert( !eqci->d_valid.get() );
+ if( !eqci->d_solved.get() ){
+ //somewhat strange: t may not be in rewritten form
+ Node r = Rewriter::rewrite( t );
+ std::map< Node, Node > msum;
+ if( QuantArith::getMonomialSum( r, msum ) ){
+ Trace("eq-infer-debug2") << "...process monomial sum, size = " << msum.size() << std::endl;
+ eqci->d_valid = true;
+ bool changed = false;
+ std::vector< Node > exp;
+ std::vector< Node > children;
+ for( std::map< Node, Node >::iterator it = msum.begin(); it != msum.end(); ++it ) {
+ Trace("eq-infer-debug2") << "...process child " << it->first << ", " << it->second << std::endl;
+ if( !it->first.isNull() ){
+ Node n = it->first;
+ BoolMap::const_iterator itv = d_elim_vars.find( n );
+ if( itv!=d_elim_vars.end() ){
+ changed = true;
+ Assert( d_eqci.find( n )!=d_eqci.end() );
+ Assert( n!=t );
+ Assert( d_eqci[n]->d_solved.get() );
+ Trace("eq-infer-debug2") << "......its solved form is " << d_eqci[n]->d_rep.get() << std::endl;
+ if( d_trackExplain ){
+ //track the explanation: justified by explanation for each substitution
+ addToExplanationEqc( exp, n );
+ }
+ n = d_eqci[n]->d_rep;
+ Assert( !n.isNull() );
+ }
+ if( it->second.isNull() ){
+ children.push_back( n );
+ }else{
+ children.push_back( NodeManager::currentNM()->mkNode( MULT, it->second, n ) );
+ }
+ }else{
+ Assert( !it->second.isNull() );
+ children.push_back( it->second );
+ }
+ }
+ Trace("eq-infer-debug2") << "...children size = " << children.size() << std::endl;
+ bool mvalid = true;
+ if( changed ){
+ r = children.size()==1 ? children[0] : NodeManager::currentNM()->mkNode( PLUS, children );
+ Trace("eq-infer-debug2") << "...pre-rewrite : " << r << std::endl;
+ r = Rewriter::rewrite( r );
+ msum.clear();
+ if( !QuantArith::getMonomialSum( r, msum ) ){
+ mvalid = false;
+ }
+ }
+ Trace("eq-infer") << "...value is " << r << std::endl;
+ setEqcRep( t, r, exp, eqci );
+ if( mvalid ){
+ for( std::map< Node, Node >::iterator it = msum.begin(); it != msum.end(); ++it ){
+ if( !it->first.isNull() ){
+ addToUseList( it->first, t );
+ }
+ }
+ }
+ }else{
+ eqci->d_valid = false;
+ }
+ }
+ }
+}
+
+void EqualityInference::addToUseList( Node used, Node eqc ) {
+#if 1
+ NodeListMap::iterator ul_i = d_uselist.find( used );
+ NodeList* ul;
+ if( ul_i != d_uselist.end() ){
+ ul = (*ul_i).second;
+ }else{
+ ul = new(d_c->getCMM()) NodeList( true, d_c, false, context::ContextMemoryAllocator<TNode>(d_c->getCMM()) );
+ d_uselist.insertDataFromContextMemory( used, ul );
+ }
+ Trace("eq-infer-debug") << " add to use list : " << used << " -> " << eqc << std::endl;
+ (*ul).push_back( eqc );
+#else
+ std::map< Node, EqcInfo * >::iterator itu = d_eqci.find( used );
+ EqcInfo * eqci_used;
+ if( itu==d_eqci.end() ){
+ eqci_used = new EqcInfo( d_c );
+ d_eqci[used] = eqci_used;
+ }else{
+ eqci_used = itu->second;
+ }
+ Trace("eq-infer-debug") << " add to use list : " << used << " -> " << eqc << std::endl;
+ eqci_used->d_uselist.push_back( eqc );
+#endif
+}
+
+void EqualityInference::setEqcRep( Node t, Node r, std::vector< Node >& exp_to_add, EqcInfo * eqci ) {
+ eqci->d_rep = r;
+ if( d_trackExplain ){
+ addToExplanationEqc( t, exp_to_add );
+ }
+ //if this is an active equivalence class
+ if( eqci->d_valid.get() ){
+ Trace("eq-infer-debug") << "Set eqc rep " << t << " -> " << r << std::endl;
+ NodeMap::const_iterator itr = d_rep_to_eqc.find( r );
+ if( itr==d_rep_to_eqc.end() ){
+ d_rep_to_eqc[r] = t;
+ }else{
+ //merge two equivalence classes
+ Node t2 = (*itr).second;
+ //check if it is valid
+ std::map< Node, EqcInfo * >::iterator itc = d_eqci.find( t2 );
+ if( itc!=d_eqci.end() && itc->second->d_valid.get() ){
+ //if we haven't already determined they should be merged
+ if( updateMaster( t, t2, eqci, itc->second ) ){
+ Trace("eq-infer") << "Infer two equivalence classes are equal : " << t << " " << t2 << std::endl;
+ Trace("eq-infer") << " since they both normalize to : " << r << std::endl;
+ d_pending_merges.push_back( t.eqNode( t2 ) );
+ if( d_trackExplain ){
+ std::vector< Node > exp;
+ for( unsigned j=0; j<2; j++ ){
+ addToExplanationEqc( exp, j==0 ? t : t2 );
+ }
+ Node exp_n = exp.empty() ? d_true : ( exp.size()==1 ? exp[0] : NodeManager::currentNM()->mkNode( AND, exp ) );
+ Trace("eq-infer") << " explanation : " << exp_n << std::endl;
+ d_pending_merge_exp.push_back( exp_n );
+ }
+ }
+ }
+ }
+ }
+}
+
+void EqualityInference::eqNotifyMerge(TNode t1, TNode t2) {
+ Assert( !t1.isNull() );
+ Assert( !t2.isNull() );
+ std::map< Node, EqcInfo * >::iterator itv1 = d_eqci.find( t1 );
+ if( itv1!=d_eqci.end() ){
+ std::map< Node, EqcInfo * >::iterator itv2 = d_eqci.find( t2 );
+ if( itv2!=d_eqci.end() ){
+ Trace("eq-infer") << "Merge equivalence classes : " << t2 << " into " << t1 << std::endl;
+ Node tr1 = itv1->second->d_rep;
+ Node tr2 = itv2->second->d_rep;
+ itv2->second->d_valid = false;
+ Trace("eq-infer") << "Representatives : " << tr2 << " into " << tr1 << std::endl;
+ if( tr1!=tr2 ){
+ Node eq = tr1.eqNode( tr2 );
+ std::map< Node, Node > msum;
+ if( QuantArith::getMonomialSumLit( eq, msum ) ){
+ Node v_solve;
+ //solve for variables with no coefficient
+ if( Trace.isOn("eq-infer-debug2") ){
+ Trace("eq-infer-debug2") << "Monomial sum : " << std::endl;
+ for( std::map< Node, Node >::iterator it = msum.begin(); it != msum.end(); ++it ) {
+ Trace("eq-infer-debug2") << " " << it->first << " * " << it->second << std::endl;
+ }
+ }
+ for( std::map< Node, Node >::iterator it = msum.begin(); it != msum.end(); ++it ) {
+ Node n = it->first;
+ if( !n.isNull() ){
+ bool canSolve = false;
+ if( it->second.isNull() ){
+ canSolve = true;
+ }else{
+ //Assert( it->second.isConst() );
+ Rational r = it->second.getConst<Rational>();
+ canSolve = r.isOne() || r.isNegativeOne();
+ }
+ if( canSolve ){
+ v_solve = n;
+ break;
+ }
+ }
+ }
+ Trace("eq-infer-debug") << "solve for variable : " << v_solve << std::endl;
+ if( !v_solve.isNull() ){
+ //solve for v_solve
+ Node veq;
+ if( QuantArith::isolate( v_solve, msum, veq, kind::EQUAL, true )==1 ){
+ Node v_value = veq[1];
+ Trace("eq-infer") << "...solved " << v_solve << " == " << v_value << std::endl;
+ Assert( d_elim_vars.find( v_solve )==d_elim_vars.end() );
+ d_elim_vars[v_solve] = true;
+ //store value in eqc info
+ EqcInfo * eqci_solved;
+ std::map< Node, EqcInfo * >::iterator itec = d_eqci.find( v_solve );
+ if( itec==d_eqci.end() ){
+ eqci_solved = new EqcInfo( d_c );
+ d_eqci[v_solve] = eqci_solved;
+ }else{
+ eqci_solved = itec->second;
+ }
+ eqci_solved->d_solved = true;
+ eqci_solved->d_rep = v_value;
+ //track the explanation
+ std::vector< Node > exp;
+ if( d_trackExplain ){
+ //explanation is t1 = t2 + their explanations
+ exp.push_back( t1.eqNode( t2 ) );
+ for( unsigned i=0; i<2; i++ ){
+ addToExplanationEqc( exp, i==0 ? t1 : t2 );
+ }
+ if( Trace.isOn("eq-infer-debug") ){
+ Trace("eq-infer-debug") << " explanation for solving " << v_solve << " is ";
+ for( unsigned i=0; i<exp.size(); i++ ){
+ Trace("eq-infer-debug") << exp[i] << " ";
+ }
+ Trace("eq-infer-debug") << std::endl;
+ }
+ addToExplanationEqc( v_solve, exp );
+ }
+
+ std::vector< Node > new_use;
+ for( std::map< Node, Node >::iterator itmm = msum.begin(); itmm != msum.end(); ++itmm ){
+ Node n = itmm->first;
+ if( !n.isNull() && n!=v_solve ){
+ new_use.push_back( n );
+ addToUseList( n, v_solve );
+ }
+ }
+
+ //go through all equivalence classes that may refer to v_solve
+ std::map< Node, bool > processed;
+ processed[v_solve] = true;
+ NodeListMap::iterator ul_i = d_uselist.find( v_solve );
+ if( ul_i != d_uselist.end() ){
+ NodeList* ul = (*ul_i).second;
+ Trace("eq-infer-debug") << " use list size = " << ul->size() << std::endl;
+ for( unsigned j=0; j<ul->size(); j++ ){
+ Node r = (*ul)[j];
+ //Trace("eq-infer-debug") << " use list size = " << eqci_solved->d_uselist.size() << std::endl;
+ //for( unsigned j=0; j<eqci_solved->d_uselist.size(); j++ ){
+ // Node r = eqci_solved->d_uselist[j];
+ if( processed.find( r )==processed.end() ){
+ processed[r] = true;
+ std::map< Node, EqcInfo * >::iterator itt = d_eqci.find( r );
+ if( itt!=d_eqci.end() && ( itt->second->d_valid || itt->second->d_solved ) ){
+ std::map< Node, Node > msum2;
+ if( QuantArith::getMonomialSum( itt->second->d_rep.get(), msum2 ) ){
+ std::map< Node, Node >::iterator itm = msum2.find( v_solve );
+ if( itm!=msum2.end() ){
+ //substitute in solved form
+ std::map< Node, Node >::iterator itm2 = msum2.find( v_value );
+ if( itm2 == msum2.end() ){
+ msum2[v_value] = itm->second;
+ }else{
+ msum2[v_value] = NodeManager::currentNM()->mkNode( PLUS, itm2->second.isNull() ? d_one : itm2->second,
+ itm->second.isNull() ? d_one : itm->second );
+ }
+ msum2.erase( itm );
+ Node rr = QuantArith::mkNode( msum2 );
+ rr = Rewriter::rewrite( rr );
+ Trace("eq-infer") << "......update " << itt->first << " => " << rr << std::endl;
+ setEqcRep( itt->first, rr, exp, itt->second );
+ //update use list
+ for( unsigned i=0; i<new_use.size(); i++ ){
+ addToUseList( new_use[i], r );
+ }
+ }
+ }else{
+ itt->second->d_valid = false;
+ }
+ }
+ }
+ }
+ }
+ Trace("eq-infer") << "...finished solved." << std::endl;
+ }
+ }
+ }
+ }
+ }else{
+ //no information to merge
+ }
+ }else{
+ //carry information (this might happen for non-linear t1 and linear t2?)
+ std::map< Node, EqcInfo * >::iterator itv2 = d_eqci.find( t2 );
+ if( itv2!=d_eqci.end() ){
+ d_eqci[t1] = d_eqci[t2];
+ d_eqci[t2] = NULL;
+ }
+ }
+}
+
+Node EqualityInference::getPendingMergeExplanation( unsigned i ) {
+ if( d_trackExplain ){
+ return d_pending_merge_exp[i];
+ }else{
+ return d_pending_merges[i];
+ }
+}
+
+}
diff --git a/src/theory/quantifiers/equality_infer.h b/src/theory/quantifiers/equality_infer.h
new file mode 100644
index 000000000..93c7bd080
--- /dev/null
+++ b/src/theory/quantifiers/equality_infer.h
@@ -0,0 +1,103 @@
+/********************* */
+/*! \file equality_infer.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2016 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.\endverbatim
+ **
+ ** \brief additional inference for equalities
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__QUANTIFIERS__EQUALITY_INFER_H
+#define __CVC4__THEORY__QUANTIFIERS__EQUALITY_INFER_H
+
+#include <ext/hash_set>
+#include <iostream>
+#include <map>
+#include <vector>
+
+#include "context/context.h"
+#include "context/context_mm.h"
+#include "context/cdhashmap.h"
+#include "context/cdchunk_list.h"
+#include "context/cdhashset.h"
+#include "theory/theory.h"
+
+
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
+
+class EqualityInference
+{
+ typedef context::CDHashMap< Node, Node, NodeHashFunction > NodeMap;
+ typedef context::CDHashMap< Node, bool, NodeHashFunction > BoolMap;
+ typedef context::CDChunkList<Node> NodeList;
+ typedef context::CDHashMap< Node, NodeList *, NodeHashFunction > NodeListMap;
+private:
+ context::Context * d_c;
+ Node d_one;
+ Node d_true;
+ class EqcInfo {
+ public:
+ EqcInfo(context::Context* c);
+ ~EqcInfo(){}
+ context::CDO< Node > d_rep;
+ //whether the eqc of this info is a representative and d_rep can been computed successfully
+ context::CDO< bool > d_valid;
+ //whether the eqc of this info is a solved variable
+ context::CDO< bool > d_solved;
+ //master equivalence class (a union find)
+ context::CDO< Node > d_master;
+ //a vector of equalities t1=t2 for which eqNotifyMerge(t1,t2) was called that explains d_rep
+ //NodeList d_rep_exp;
+ //the list of other eqc where this variable may be appear
+ //NodeList d_uselist;
+ };
+
+ /** track explanations */
+ bool d_trackExplain;
+ /** information necessary for equivalence classes */
+ BoolMap d_elim_vars;
+ std::map< Node, EqcInfo * > d_eqci;
+ NodeMap d_rep_to_eqc;
+ NodeListMap d_rep_exp;
+ /** set eqc rep */
+ void setEqcRep( Node t, Node r, std::vector< Node >& exp_to_add, EqcInfo * eqci );
+ /** use list */
+ NodeListMap d_uselist;
+ void addToUseList( Node used, Node eqc );
+ /** pending merges */
+ NodeList d_pending_merges;
+ NodeList d_pending_merge_exp;
+ /** add to explanation */
+ void addToExplanation( std::vector< Node >& exp, Node e );
+ void addToExplanationEqc( std::vector< Node >& exp, Node eqc );
+ void addToExplanationEqc( Node eqc, std::vector< Node >& exp_to_add );
+ /** for setting master/slave */
+ Node getMaster( Node t, EqcInfo * eqc, bool& updated, Node new_m = Node::null() );
+ bool updateMaster( Node t1, Node t2, EqcInfo * eqc1, EqcInfo * eqc2 );
+public:
+ //second argument is whether explanations should be tracked
+ EqualityInference(context::Context* c, bool trackExp = false);
+ virtual ~EqualityInference();
+ /** input : notification when equality engine is updated */
+ void eqNotifyNewClass(TNode t);
+ void eqNotifyMerge(TNode t1, TNode t2);
+ /** output : inferred equalities */
+ unsigned getNumPendingMerges() { return d_pending_merges.size(); }
+ Node getPendingMerge( unsigned i ) { return d_pending_merges[i]; }
+ Node getPendingMergeExplanation( unsigned i );
+};
+
+}
+}
+}
+
+#endif
diff --git a/src/theory/quantifiers/first_order_model.cpp b/src/theory/quantifiers/first_order_model.cpp
index 272f16be8..a833f48d2 100644
--- a/src/theory/quantifiers/first_order_model.cpp
+++ b/src/theory/quantifiers/first_order_model.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file first_order_model.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): Kshitij Bansal, Morgan Deters
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of model engine model class
**/
@@ -30,24 +30,43 @@ using namespace CVC4::theory;
using namespace CVC4::theory::quantifiers;
using namespace CVC4::theory::quantifiers::fmcheck;
+struct sortQuantifierRelevance {
+ FirstOrderModel * d_fm;
+ bool operator() (Node i, Node j) {
+ int wi = d_fm->getRelevanceValue( i );
+ int wj = d_fm->getRelevanceValue( j );
+ if( wi==wj ){
+ return i<j;
+ }else{
+ return wi<wj;
+ }
+ }
+};
+
FirstOrderModel::FirstOrderModel(QuantifiersEngine * qe, context::Context* c, std::string name ) :
TheoryModel( c, name, true ),
d_qe( qe ), d_forall_asserts( c ), d_isModelSet( c, false ){
+ d_rlv_count = 0;
+}
+
+void FirstOrderModel::assertQuantifier( Node n ){
+ if( n.getKind()==FORALL ){
+ d_forall_asserts.push_back( n );
+ }else if( n.getKind()==NOT ){
+ Assert( n[0].getKind()==FORALL );
+ }
+}
+unsigned FirstOrderModel::getNumAssertedQuantifiers() {
+ return d_forall_asserts.size();
}
-void FirstOrderModel::assertQuantifier( Node n, bool reduced ){
- if( !reduced ){
- if( n.getKind()==FORALL ){
- d_forall_asserts.push_back( n );
- }else if( n.getKind()==NOT ){
- Assert( n[0].getKind()==FORALL );
- }
+Node FirstOrderModel::getAssertedQuantifier( unsigned i, bool ordered ) {
+ if( !ordered || d_forall_rlv_assert.empty() ){
+ return d_forall_asserts[i];
}else{
- Assert( n.getKind()==FORALL );
- Assert( d_forall_to_reduce.find( n )==d_forall_to_reduce.end() );
- d_forall_to_reduce[n] = true;
- Trace("quant") << "Mark to reduce : " << n << std::endl;
+ Assert( d_forall_rlv_assert.size()==d_forall_asserts.size() );
+ return d_forall_rlv_assert[i];
}
}
@@ -81,11 +100,11 @@ void FirstOrderModel::initialize() {
processInitialize( true );
//this is called after representatives have been chosen and the equality engine has been built
//for each quantifier, collect all operators we care about
- for( int i=0; i<getNumAssertedQuantifiers(); i++ ){
+ for( unsigned i=0; i<getNumAssertedQuantifiers(); i++ ){
Node f = getAssertedQuantifier( i );
if( d_quant_var_id.find( f )==d_quant_var_id.end() ){
- for(unsigned i=0; i<f[0].getNumChildren(); i++){
- d_quant_var_id[f][f[0][i]] = i;
+ for(unsigned j=0; j<f[0].getNumChildren(); j++){
+ d_quant_var_id[f][f[0][j]] = j;
}
}
processInitializeQuantifier( f );
@@ -122,20 +141,72 @@ Node FirstOrderModel::getSomeDomainElement(TypeNode tn){
/** needs check */
bool FirstOrderModel::checkNeeded() {
- return d_forall_asserts.size()>0 || !d_forall_to_reduce.empty();
-}
-
-/** mark reduced */
-void FirstOrderModel::markQuantifierReduced( Node q ) {
- Assert( d_forall_to_reduce.find( q )!=d_forall_to_reduce.end() );
- d_forall_to_reduce.erase( q );
- Trace("quant") << "Mark reduced : " << q << std::endl;
+ return d_forall_asserts.size()>0;
}
void FirstOrderModel::reset_round() {
d_quant_active.clear();
+
+ //order the quantified formulas
+ if( !d_forall_rlv_vec.empty() ){
+ Trace("fm-relevant") << "Build sorted relevant list..." << std::endl;
+ d_forall_rlv_assert.clear();
+ Trace("fm-relevant-debug") << "Mark asserted quantified formulas..." << std::endl;
+ std::map< Node, bool > qassert;
+ for( unsigned i=0; i<d_forall_asserts.size(); i++ ){
+ qassert[d_forall_asserts[i]] = true;
+ }
+ Trace("fm-relevant-debug") << "Sort the relevant quantified formulas..." << std::endl;
+ sortQuantifierRelevance sqr;
+ sqr.d_fm = this;
+ std::sort( d_forall_rlv_vec.begin(), d_forall_rlv_vec.end(), sqr );
+ Trace("fm-relevant-debug") << "Add relevant asserted formulas..." << std::endl;
+ for( int i=(int)(d_forall_rlv_vec.size()-1); i>=0; i-- ){
+ Node q = d_forall_rlv_vec[i];
+ if( qassert.find( q )!=qassert.end() ){
+ Trace("fm-relevant") << " " << d_forall_rlv[q] << " : " << q << std::endl;
+ d_forall_rlv_assert.push_back( q );
+ }
+ }
+ Trace("fm-relevant-debug") << "Add remaining asserted formulas..." << std::endl;
+ for( unsigned i=0; i<d_forall_asserts.size(); i++ ){
+ Node q = d_forall_asserts[i];
+ if( std::find( d_forall_rlv_assert.begin(), d_forall_rlv_assert.end(), q )==d_forall_rlv_assert.end() ){
+ d_forall_rlv_assert.push_back( q );
+ }else{
+ Trace("fm-relevant-debug") << "...already included " << q << std::endl;
+ }
+ }
+ Trace("fm-relevant-debug") << "Sizes : " << d_forall_rlv_assert.size() << " " << d_forall_asserts.size() << std::endl;
+ Assert( d_forall_rlv_assert.size()==d_forall_asserts.size() );
+ }
+}
+
+void FirstOrderModel::markRelevant( Node q ) {
+ if( q!=d_last_forall_rlv ){
+ Trace("fm-relevant") << "Mark relevant : " << q << std::endl;
+ if( std::find( d_forall_rlv_vec.begin(), d_forall_rlv_vec.end(), q )==d_forall_rlv_vec.end() ){
+ d_forall_rlv_vec.push_back( q );
+ }
+ d_forall_rlv[ q ] = d_rlv_count;
+ d_rlv_count++;
+ d_last_forall_rlv = q;
+ }
}
+int FirstOrderModel::getRelevanceValue( Node q ) {
+ std::map< Node, unsigned >::iterator it = d_forall_rlv.find( q );
+ if( it==d_forall_rlv.end() ){
+ return -1;
+ }else{
+ return it->second;
+ }
+}
+
+//bool FirstOrderModel::isQuantifierAsserted( TNode q ) {
+// return d_forall_asserts.find( q )!=d_forall_asserts.end();
+//}
+
void FirstOrderModel::setQuantifierActive( TNode q, bool active ) {
d_quant_active[q] = active;
}
diff --git a/src/theory/quantifiers/first_order_model.h b/src/theory/quantifiers/first_order_model.h
index d42eb61e3..cbe83cfa5 100644
--- a/src/theory/quantifiers/first_order_model.h
+++ b/src/theory/quantifiers/first_order_model.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file first_order_model.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Model extended classes
**/
@@ -49,8 +49,12 @@ protected:
QuantifiersEngine * d_qe;
/** list of quantifiers asserted in the current context */
context::CDList<Node> d_forall_asserts;
- /** list of quantifiers that have been marked to reduce */
- std::map< Node, bool > d_forall_to_reduce;
+ /** quantified formulas marked as relevant */
+ unsigned d_rlv_count;
+ std::map< Node, unsigned > d_forall_rlv;
+ std::vector< Node > d_forall_rlv_vec;
+ Node d_last_forall_rlv;
+ std::vector< Node > d_forall_rlv_assert;
/** is model set */
context::CDO< bool > d_isModelSet;
/** get variable id */
@@ -59,13 +63,11 @@ protected:
virtual Node getCurrentUfModelValue( Node n, std::vector< Node > & args, bool partial ) = 0;
public: //for Theory Quantifiers:
/** assert quantifier */
- void assertQuantifier( Node n, bool reduced = false );
+ void assertQuantifier( Node n );
/** get number of asserted quantifiers */
- int getNumAssertedQuantifiers() { return (int)d_forall_asserts.size(); }
+ unsigned getNumAssertedQuantifiers();
/** get asserted quantifier */
- Node getAssertedQuantifier( int i ) { return d_forall_asserts[i]; }
- /** get number to reduce quantifiers */
- unsigned getNumToReduceQuantifiers() { return d_forall_to_reduce.size(); }
+ Node getAssertedQuantifier( unsigned i, bool ordered = false );
/** initialize model for term */
void initializeModelForTerm( Node n, std::map< Node, bool >& visited );
virtual void processInitializeModelForTerm( Node n ) = 0;
@@ -94,14 +96,16 @@ public:
Node getSomeDomainElement(TypeNode tn);
/** do we need to do any work? */
bool checkNeeded();
- /** mark reduced */
- void markQuantifierReduced( Node q );
private:
//list of inactive quantified formulas
std::map< TNode, bool > d_quant_active;
public:
/** reset round */
void reset_round();
+ /** mark quantified formula relevant */
+ void markRelevant( Node q );
+ /** get relevance value */
+ int getRelevanceValue( Node q );
/** set quantified formula active/inactive
* a quantified formula may be set inactive if for instance:
* - it is entailed by other quantified formulas
diff --git a/src/theory/quantifiers/full_model_check.cpp b/src/theory/quantifiers/full_model_check.cpp
index ff0da13e1..33c853328 100644
--- a/src/theory/quantifiers/full_model_check.cpp
+++ b/src/theory/quantifiers/full_model_check.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file full_model_check.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): Kshitij Bansal
+ ** Top contributors (to current version):
+ ** Morgan Deters, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of full model check class
**/
@@ -350,11 +350,11 @@ void FullModelChecker::preProcessBuildModel(TheoryModel* m, bool fullModel) {
}
//do not have to introduce terms for sorts of domains of quantified formulas if we are allowed to assume empty sorts
if( !options::fmfEmptySorts() ){
- for( int i=0; i<fm->getNumAssertedQuantifiers(); i++ ){
+ for( unsigned i=0; i<fm->getNumAssertedQuantifiers(); i++ ){
Node q = fm->getAssertedQuantifier( i );
//make sure all types are set
- for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
- preInitializeType( fm, q[0][i].getType() );
+ for( unsigned j=0; j<q[0].getNumChildren(); j++ ){
+ preInitializeType( fm, q[0][j].getType() );
}
}
}
@@ -411,6 +411,11 @@ void FullModelChecker::processBuildModel(TheoryModel* m, bool fullModel){
Node r = fm->getUsedRepresentative(n);
Trace("fmc-model-debug") << n << " -> " << r << std::endl;
//AlwaysAssert( fm->areEqual( fm->d_uf_terms[op][i], r ) );
+ }else{
+ if( Trace.isOn("fmc-model-debug") ){
+ Node r = fm->getUsedRepresentative(n);
+ Trace("fmc-model-debug") << "[redundant] " << n << " -> " << r << std::endl;
+ }
}
}
Trace("fmc-model-debug") << std::endl;
@@ -456,7 +461,7 @@ void FullModelChecker::processBuildModel(TheoryModel* m, bool fullModel){
}
}
if( !isStar && !ri.isConst() ){
- Trace("fmc-warn") << "Warning : model has non-constant argument in model " << ri << " (from " << c[i] << ")" << std::endl;
+ Trace("fmc-warn") << "Warning : model for " << op << " has non-constant argument in model " << ri << " (from " << c[i] << ")" << std::endl;
Assert( false );
}
entry_children.push_back(ri);
@@ -464,7 +469,7 @@ void FullModelChecker::processBuildModel(TheoryModel* m, bool fullModel){
Node n = NodeManager::currentNM()->mkNode( APPLY_UF, children );
Node nv = fm->getUsedRepresentative( v );
if( !nv.isConst() ){
- Trace("fmc-warn") << "Warning : model has non-constant value in model " << nv << std::endl;
+ Trace("fmc-warn") << "Warning : model for " << op << " has non-constant value in model " << nv << std::endl;
Assert( false );
}
Node en = (useSimpleModels() && hasNonStar) ? n : NodeManager::currentNM()->mkNode( APPLY_UF, entry_children );
@@ -586,6 +591,7 @@ void FullModelChecker::debugPrint(const char * tr, Node n, bool dispStar) {
bool FullModelChecker::doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort ) {
Trace("fmc") << "Full model check " << f << ", effort = " << effort << "..." << std::endl;
+ Assert( !d_qe->inConflict() );
if( optUseModel() ){
FirstOrderModelFmc * fmfmc = fm->asFirstOrderModelFmc();
if (effort==0) {
@@ -614,7 +620,7 @@ bool FullModelChecker::doExhaustiveInstantiation( FirstOrderModel * fm, Node f,
//consider all entries going to non-true
for (unsigned i=0; i<d_quant_models[f].d_cond.size(); i++) {
- if( d_quant_models[f].d_value[i]!=d_true) {
+ if( d_quant_models[f].d_value[i]!=d_true ) {
Trace("fmc-inst") << "Instantiate based on " << d_quant_models[f].d_cond[i] << "..." << std::endl;
bool hasStar = false;
std::vector< Node > inst;
@@ -676,15 +682,21 @@ bool FullModelChecker::doExhaustiveInstantiation( FirstOrderModel * fm, Node f,
}else{
//just add the instance
d_triedLemmas++;
- if( d_qe->addInstantiation( f, inst ) ){
+ if( d_qe->addInstantiation( f, inst, true ) ){
Trace("fmc-debug-inst") << "** Added instantiation." << std::endl;
d_addedLemmas++;
- if( options::fmfOneInstPerRound() ){
+ if( d_qe->inConflict() || options::fmfOneInstPerRound() ){
break;
}
}else{
Trace("fmc-debug-inst") << "** Instantiation was duplicate." << std::endl;
- //this can happen if evaluation is unknown
+ //this can happen if evaluation is unknown, or if we are generalizing a star that already has a value
+ //if( !hasStar && d_quant_models[f].d_value[i]==d_false ){
+ // Trace("fmc-warn") << "**** FMC warning: inconsistent duplicate instantiation." << std::endl;
+ //}
+ //this assertion can happen if two instantiations from this round are identical
+ // (0,1)->false (1,0)->false for forall xy. f( x, y ) = f( y, x )
+ //Assert( hasStar || d_quant_models[f].d_value[i]!=d_false );
//might try it next effort level
d_star_insts[f].push_back(i);
}
@@ -733,12 +745,14 @@ bool FullModelChecker::exhaustiveInstantiate(FirstOrderModelFmc * fm, Node f, No
for( unsigned i=0; i<c.getNumChildren(); i++ ){
if( c[i].getType().isInteger() ){
if( fm->isInterval(c[i]) ){
+ Trace("fmc-exh-debug") << "...set " << i << " based on interval." << std::endl;
for( unsigned b=0; b<2; b++ ){
if( !fm->isStar(c[i][b]) ){
riter.d_bounds[b][i] = c[i][b];
}
}
}else if( !fm->isStar(c[i]) ){
+ Trace("fmc-exh-debug") << "...set " << i << " based on point." << std::endl;
riter.d_bounds[0][i] = c[i];
riter.d_bounds[1][i] = QuantArith::offset( c[i], 1 );
}
@@ -780,11 +794,11 @@ bool FullModelChecker::exhaustiveInstantiate(FirstOrderModelFmc * fm, Node f, No
for( int i=0; i<riter.getNumTerms(); i++ ){
Node rr = riter.getTerm( i );
Node r = rr;
- if( r.getType().isSort() ){
- r = fm->getUsedRepresentative( r );
- }else{
- r = fm->getCurrentModelValue( r );
- }
+ //if( r.getType().isSort() ){
+ r = fm->getUsedRepresentative( r );
+ //}else{
+ // r = fm->getCurrentModelValue( r );
+ //}
debugPrint("fmc-exh-debug", r);
Trace("fmc-exh-debug") << " (term : " << rr << ")";
ev_inst.push_back( r );
@@ -796,10 +810,10 @@ bool FullModelChecker::exhaustiveInstantiate(FirstOrderModelFmc * fm, Node f, No
if (ev!=d_true) {
Trace("fmc-exh-debug") << ", add!";
//add as instantiation
- if( d_qe->addInstantiation( f, inst ) ){
+ if( d_qe->addInstantiation( f, inst, true ) ){
Trace("fmc-exh-debug") << " ...success.";
addedLemmas++;
- if( options::fmfOneInstPerRound() ){
+ if( d_qe->inConflict() || options::fmfOneInstPerRound() ){
break;
}
}else{
@@ -846,38 +860,12 @@ void FullModelChecker::doCheck(FirstOrderModelFmc * fm, Node f, Def & d, Node n
d.addEntry(fm, mkCondDefault(fm, f), Node::null());
}
else if( n.getType().isArray() ){
- //make the definition
- bool success = false;
- /*
- Node r = fm->getRepresentative(n);
- Trace("fmc-debug") << "Representative for array is " << r << std::endl;
- while( r.getKind() == kind::STORE ){
- Node i = fm->getUsedRepresentative( r[1] );
- Node e = fm->getUsedRepresentative( r[2] );
- d.addEntry(fm, mkArrayCond(i), e );
- r = fm->getRepresentative( r[0] );
- }
- Node defC = mkArrayCond(fm->getStar(n.getType().getArrayIndexType()));
- bool success = false;
- Node odefaultValue;
- if( r.getKind() == kind::STORE_ALL ){
- ArrayStoreAll storeAll = r.getConst<ArrayStoreAll>();
- odefaultValue = Node::fromExpr(storeAll.getExpr());
- Node defaultValue = fm->getUsedRepresentative( odefaultValue, true );
- if( !defaultValue.isNull() ){
- d.addEntry(fm, defC, defaultValue);
- success = true;
- }
- }
- */
- if( !success ){
- //Trace("fmc-warn") << "WARNING : ARRAYS : Can't process base array " << r << std::endl;
- //Trace("fmc-warn") << " Default value was : " << odefaultValue << std::endl;
- //Trace("fmc-debug") << "Can't process base array " << r << std::endl;
- //can't process this array
- d.reset();
- d.addEntry(fm, mkCondDefault(fm, f), Node::null());
- }
+ //Trace("fmc-warn") << "WARNING : ARRAYS : Can't process base array " << r << std::endl;
+ //Trace("fmc-warn") << " Default value was : " << odefaultValue << std::endl;
+ //Trace("fmc-debug") << "Can't process base array " << r << std::endl;
+ //can't process this array
+ d.reset();
+ d.addEntry(fm, mkCondDefault(fm, f), Node::null());
}
else if( n.getNumChildren()==0 ){
Node r = n;
diff --git a/src/theory/quantifiers/full_model_check.h b/src/theory/quantifiers/full_model_check.h
index c7bfcd189..411b7a5eb 100644
--- a/src/theory/quantifiers/full_model_check.h
+++ b/src/theory/quantifiers/full_model_check.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file full_model_check.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Full model check class
**/
diff --git a/src/theory/quantifiers/fun_def_engine.cpp b/src/theory/quantifiers/fun_def_engine.cpp
index 56214f540..cf1d14663 100644
--- a/src/theory/quantifiers/fun_def_engine.cpp
+++ b/src/theory/quantifiers/fun_def_engine.cpp
@@ -1,13 +1,13 @@
/********************* */
-/*! \file fun_def_process.cpp
+/*! \file fun_def_engine.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** This class implements specialized techniques for (recursively) defined functions
**/
diff --git a/src/theory/quantifiers/fun_def_engine.h b/src/theory/quantifiers/fun_def_engine.h
index be73d51a9..3b95281c0 100644
--- a/src/theory/quantifiers/fun_def_engine.h
+++ b/src/theory/quantifiers/fun_def_engine.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file fun_def_engine.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Specialized techniques for (recursively) defined functions
**/
diff --git a/src/theory/quantifiers/fun_def_process.cpp b/src/theory/quantifiers/fun_def_process.cpp
index 7d5e33fdb..9109aab8a 100644
--- a/src/theory/quantifiers/fun_def_process.cpp
+++ b/src/theory/quantifiers/fun_def_process.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file fun_def_process.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): Kshitij Bansal
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Sort inference module
**
diff --git a/src/theory/quantifiers/fun_def_process.h b/src/theory/quantifiers/fun_def_process.h
index 8cff6c952..1f6ee6562 100644
--- a/src/theory/quantifiers/fun_def_process.h
+++ b/src/theory/quantifiers/fun_def_process.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file fun_def_process.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Pre-process steps for well-defined functions
**/
diff --git a/src/theory/quantifiers/inst_match.cpp b/src/theory/quantifiers/inst_match.cpp
index 5eca87903..8818175db 100644
--- a/src/theory/quantifiers/inst_match.cpp
+++ b/src/theory/quantifiers/inst_match.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file inst_match.cpp
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): Kshitij Bansal, Francois Bobot, Clark Barrett
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of inst match class
**/
@@ -142,7 +142,7 @@ bool InstMatch::set( QuantifiersEngine* qe, int i, TNode n ) {
}
bool InstMatchTrie::addInstMatch( QuantifiersEngine* qe, Node f, std::vector< Node >& m, bool modEq,
- bool modInst, ImtIndexOrder* imtio, bool onlyExist, int index ) {
+ ImtIndexOrder* imtio, bool onlyExist, int index ) {
if( index==(int)f[0].getNumChildren() || ( imtio && index==(int)imtio->d_order.size() ) ){
return false;
}else{
@@ -150,25 +150,11 @@ bool InstMatchTrie::addInstMatch( QuantifiersEngine* qe, Node f, std::vector< No
Node n = m[i_index];
std::map< Node, InstMatchTrie >::iterator it = d_data.find( n );
if( it!=d_data.end() ){
- bool ret = it->second.addInstMatch( qe, f, m, modEq, modInst, imtio, onlyExist, index+1 );
+ bool ret = it->second.addInstMatch( qe, f, m, modEq, imtio, onlyExist, index+1 );
if( !onlyExist || !ret ){
return ret;
}
}
- /*
- //check if m is an instance of another instantiation if modInst is true
- if( modInst ){
- if( !n.isNull() ){
- Node nl;
- std::map< Node, InstMatchTrie >::iterator itm = d_data.find( nl );
- if( itm!=d_data.end() ){
- if( !itm->second.addInstMatch( qe, f, m, modEq, modInst, imtio, true, index+1 ) ){
- return false;
- }
- }
- }
- }
- */
if( modEq ){
//check modulo equality if any other instantiation match exists
if( !n.isNull() && qe->getEqualityQuery()->getEngine()->hasTerm( n ) ){
@@ -179,7 +165,7 @@ bool InstMatchTrie::addInstMatch( QuantifiersEngine* qe, Node f, std::vector< No
if( en!=n ){
std::map< Node, InstMatchTrie >::iterator itc = d_data.find( en );
if( itc!=d_data.end() ){
- if( itc->second.addInstMatch( qe, f, m, modEq, modInst, imtio, true, index+1 ) ){
+ if( itc->second.addInstMatch( qe, f, m, modEq, imtio, true, index+1 ) ){
return false;
}
}
@@ -189,12 +175,30 @@ bool InstMatchTrie::addInstMatch( QuantifiersEngine* qe, Node f, std::vector< No
}
}
if( !onlyExist ){
- d_data[n].addInstMatch( qe, f, m, modEq, modInst, imtio, false, index+1 );
+ d_data[n].addInstMatch( qe, f, m, modEq, imtio, false, index+1 );
}
return true;
}
}
+bool InstMatchTrie::removeInstMatch( QuantifiersEngine* qe, Node q, std::vector< Node >& m, ImtIndexOrder* imtio, int index ) {
+ Assert( index<(int)q[0].getNumChildren() );
+ Assert( !imtio || index<(int)imtio->d_order.size() );
+ int i_index = imtio ? imtio->d_order[index] : index;
+ Node n = m[i_index];
+ std::map< Node, InstMatchTrie >::iterator it = d_data.find( n );
+ if( it!=d_data.end() ){
+ if( (index+1)==(int)q[0].getNumChildren() || ( imtio && (index+1)==(int)imtio->d_order.size() ) ){
+ d_data.erase( n );
+ return true;
+ }else{
+ return it->second.removeInstMatch( qe, q, m, imtio, index+1 );
+ }
+ }else{
+ return false;
+ }
+}
+
void InstMatchTrie::print( std::ostream& out, Node q, std::vector< TNode >& terms ) const {
if( terms.size()==q[0].getNumChildren() ){
out << " ( ";
@@ -212,9 +216,31 @@ void InstMatchTrie::print( std::ostream& out, Node q, std::vector< TNode >& term
}
}
+void InstMatchTrie::getInstantiations( std::vector< Node >& insts, Node q, std::vector< Node >& terms, QuantifiersEngine * qe ) const {
+ if( terms.size()==q[0].getNumChildren() ){
+ //insts.push_back( q[1].substitute( vars.begin(), vars.end(), terms.begin(), terms.end() ) );
+ insts.push_back( qe->getInstantiation( q, terms, true ) );
+ }else{
+ for( std::map< Node, InstMatchTrie >::const_iterator it = d_data.begin(); it != d_data.end(); ++it ){
+ terms.push_back( it->first );
+ it->second.getInstantiations( insts, q, terms, qe );
+ terms.pop_back();
+ }
+ }
+}
+
+CDInstMatchTrie::~CDInstMatchTrie() {
+ for(std::map< Node, CDInstMatchTrie* >::iterator i = d_data.begin(),
+ iend = d_data.end(); i != iend; ++i) {
+ CDInstMatchTrie* current = (*i).second;
+ delete current;
+ }
+ d_data.clear();
+}
+
bool CDInstMatchTrie::addInstMatch( QuantifiersEngine* qe, Node f, std::vector< Node >& m,
- context::Context* c, bool modEq, bool modInst, int index, bool onlyExist ){
+ context::Context* c, bool modEq, int index, bool onlyExist ){
bool reset = false;
if( !d_valid.get() ){
if( onlyExist ){
@@ -230,25 +256,11 @@ bool CDInstMatchTrie::addInstMatch( QuantifiersEngine* qe, Node f, std::vector<
Node n = m[ index ];
std::map< Node, CDInstMatchTrie* >::iterator it = d_data.find( n );
if( it!=d_data.end() ){
- bool ret = it->second->addInstMatch( qe, f, m, c, modEq, modInst, index+1, onlyExist );
+ bool ret = it->second->addInstMatch( qe, f, m, c, modEq, index+1, onlyExist );
if( !onlyExist || !ret ){
return reset || ret;
}
}
- //check if m is an instance of another instantiation if modInst is true
- /*
- if( modInst ){
- if( !n.isNull() ){
- Node nl;
- std::map< Node, CDInstMatchTrie* >::iterator itm = d_data.find( nl );
- if( itm!=d_data.end() ){
- if( !itm->second->addInstMatch( qe, f, m, c, modEq, modInst, index+1, true ) ){
- return false;
- }
- }
- }
- }
- */
if( modEq ){
//check modulo equality if any other instantiation match exists
if( !n.isNull() && qe->getEqualityQuery()->getEngine()->hasTerm( n ) ){
@@ -259,7 +271,7 @@ bool CDInstMatchTrie::addInstMatch( QuantifiersEngine* qe, Node f, std::vector<
if( en!=n ){
std::map< Node, CDInstMatchTrie* >::iterator itc = d_data.find( en );
if( itc!=d_data.end() ){
- if( itc->second->addInstMatch( qe, f, m, c, modEq, modInst, index+1, true ) ){
+ if( itc->second->addInstMatch( qe, f, m, c, modEq, index+1, true ) ){
return false;
}
}
@@ -272,13 +284,33 @@ bool CDInstMatchTrie::addInstMatch( QuantifiersEngine* qe, Node f, std::vector<
if( !onlyExist ){
// std::map< Node, CDInstMatchTrie* >::iterator it = d_data.find( n );
CDInstMatchTrie* imt = new CDInstMatchTrie( c );
+ Assert(d_data.find(n) == d_data.end());
d_data[n] = imt;
- imt->addInstMatch( qe, f, m, c, modEq, modInst, index+1, false );
+ imt->addInstMatch( qe, f, m, c, modEq, index+1, false );
}
return true;
}
}
+bool CDInstMatchTrie::removeInstMatch( QuantifiersEngine* qe, Node q, std::vector< Node >& m, int index ) {
+ if( index==(int)q[0].getNumChildren() ){
+ if( d_valid.get() ){
+ d_valid.set( false );
+ return true;
+ }else{
+ return false;
+ }
+ }else{
+ Node n = m[index];
+ std::map< Node, CDInstMatchTrie* >::iterator it = d_data.find( n );
+ if( it!=d_data.end() ){
+ return it->second->removeInstMatch( qe, q, m, index+1 );
+ }else{
+ return false;
+ }
+ }
+}
+
void CDInstMatchTrie::print( std::ostream& out, Node q, std::vector< TNode >& terms ) const{
if( d_valid.get() ){
if( terms.size()==q[0].getNumChildren() ){
@@ -298,6 +330,21 @@ void CDInstMatchTrie::print( std::ostream& out, Node q, std::vector< TNode >& te
}
}
+void CDInstMatchTrie::getInstantiations( std::vector< Node >& insts, Node q, std::vector< Node >& terms, QuantifiersEngine * qe ) const{
+ if( d_valid.get() ){
+ if( terms.size()==q[0].getNumChildren() ){
+ //insts.push_back( q[1].substitute( vars.begin(), vars.end(), terms.begin(), terms.end() ) );
+ insts.push_back( qe->getInstantiation( q, terms, true ) );
+ }else{
+ for( std::map< Node, CDInstMatchTrie* >::const_iterator it = d_data.begin(); it != d_data.end(); ++it ){
+ terms.push_back( it->first );
+ it->second->getInstantiations( insts, q, terms, qe );
+ terms.pop_back();
+ }
+ }
+ }
+}
+
}/* CVC4::theory::inst namespace */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
diff --git a/src/theory/quantifiers/inst_match.h b/src/theory/quantifiers/inst_match.h
index f1c1c952a..ad287c1a3 100644
--- a/src/theory/quantifiers/inst_match.h
+++ b/src/theory/quantifiers/inst_match.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file inst_match.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): Francois Bobot
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief inst match class
**/
@@ -96,11 +96,12 @@ public:
public:
std::vector< int > d_order;
};/* class InstMatchTrie ImtIndexOrder */
-public:
+
/** the data */
std::map< Node, InstMatchTrie > d_data;
private:
void print( std::ostream& out, Node q, std::vector< TNode >& terms ) const;
+ void getInstantiations( std::vector< Node >& insts, Node q, std::vector< Node >& terms, QuantifiersEngine * qe ) const;
public:
InstMatchTrie(){}
~InstMatchTrie(){}
@@ -110,69 +111,80 @@ public:
modInst is if we return true if m is an instance of a match that exists
*/
bool existsInstMatch( QuantifiersEngine* qe, Node f, InstMatch& m, bool modEq = false,
- bool modInst = false, ImtIndexOrder* imtio = NULL, int index = 0 ) {
- return !addInstMatch( qe, f, m, modEq, modInst, imtio, true, index );
+ ImtIndexOrder* imtio = NULL, int index = 0 ) {
+ return !addInstMatch( qe, f, m, modEq, imtio, true, index );
}
bool existsInstMatch( QuantifiersEngine* qe, Node f, std::vector< Node >& m, bool modEq = false,
- bool modInst = false, ImtIndexOrder* imtio = NULL, int index = 0 ) {
- return !addInstMatch( qe, f, m, modEq, modInst, imtio, true, index );
+ ImtIndexOrder* imtio = NULL, int index = 0 ) {
+ return !addInstMatch( qe, f, m, modEq, imtio, true, index );
}
/** add match m for quantifier f, take into account equalities if modEq = true,
if imtio is non-null, this is the order to add to trie
return true if successful
*/
bool addInstMatch( QuantifiersEngine* qe, Node f, InstMatch& m, bool modEq = false,
- bool modInst = false, ImtIndexOrder* imtio = NULL, bool onlyExist = false, int index = 0 ){
- return addInstMatch( qe, f, m.d_vals, modEq, modInst, imtio, onlyExist, index );
+ ImtIndexOrder* imtio = NULL, bool onlyExist = false, int index = 0 ){
+ return addInstMatch( qe, f, m.d_vals, modEq, imtio, onlyExist, index );
}
bool addInstMatch( QuantifiersEngine* qe, Node f, std::vector< Node >& m, bool modEq = false,
- bool modInst = false, ImtIndexOrder* imtio = NULL, bool onlyExist = false, int index = 0 );
+ ImtIndexOrder* imtio = NULL, bool onlyExist = false, int index = 0 );
+ bool removeInstMatch( QuantifiersEngine* qe, Node f, std::vector< Node >& m, ImtIndexOrder* imtio = NULL, int index = 0 );
void print( std::ostream& out, Node q ) const{
std::vector< TNode > terms;
print( out, q, terms );
}
+ void getInstantiations( std::vector< Node >& insts, Node q, QuantifiersEngine * qe ) {
+ std::vector< Node > terms;
+ getInstantiations( insts, q, terms, qe );
+ }
void clear() { d_data.clear(); }
};/* class InstMatchTrie */
/** trie for InstMatch objects */
class CDInstMatchTrie {
-public:
+private:
/** the data */
std::map< Node, CDInstMatchTrie* > d_data;
/** is valid */
context::CDO< bool > d_valid;
-private:
+
void print( std::ostream& out, Node q, std::vector< TNode >& terms ) const;
+ void getInstantiations( std::vector< Node >& insts, Node q, std::vector< Node >& terms, QuantifiersEngine * qe ) const;
public:
CDInstMatchTrie( context::Context* c ) : d_valid( c, false ){}
- ~CDInstMatchTrie(){}
-public:
+ ~CDInstMatchTrie();
+
/** return true if m exists in this trie
modEq is if we check modulo equality
modInst is if we return true if m is an instance of a match that exists
*/
- bool existsInstMatch( QuantifiersEngine* qe, Node f, InstMatch& m, context::Context* c, bool modEq = false,
- bool modInst = false, int index = 0 ) {
- return !addInstMatch( qe, f, m, c, modEq, modInst, index, true );
+ bool existsInstMatch( QuantifiersEngine* qe, Node q, InstMatch& m, context::Context* c, bool modEq = false,
+ int index = 0 ) {
+ return !addInstMatch( qe, q, m, c, modEq, index, true );
}
- bool existsInstMatch( QuantifiersEngine* qe, Node f, std::vector< Node >& m, context::Context* c, bool modEq = false,
- bool modInst = false, int index = 0 ) {
- return !addInstMatch( qe, f, m, c, modEq, modInst, index, true );
+ bool existsInstMatch( QuantifiersEngine* qe, Node q, std::vector< Node >& m, context::Context* c, bool modEq = false,
+ int index = 0 ) {
+ return !addInstMatch( qe, q, m, c, modEq, index, true );
}
/** add match m for quantifier f, take into account equalities if modEq = true,
if imtio is non-null, this is the order to add to trie
return true if successful
*/
- bool addInstMatch( QuantifiersEngine* qe, Node f, InstMatch& m, context::Context* c, bool modEq = false,
- bool modInst = false, int index = 0, bool onlyExist = false ) {
- return addInstMatch( qe, f, m.d_vals, c, modEq, modInst, index, onlyExist );
+ bool addInstMatch( QuantifiersEngine* qe, Node q, InstMatch& m, context::Context* c, bool modEq = false,
+ int index = 0, bool onlyExist = false ) {
+ return addInstMatch( qe, q, m.d_vals, c, modEq, index, onlyExist );
}
- bool addInstMatch( QuantifiersEngine* qe, Node f, std::vector< Node >& m, context::Context* c, bool modEq = false,
- bool modInst = false, int index = 0, bool onlyExist = false );
+ bool addInstMatch( QuantifiersEngine* qe, Node q, std::vector< Node >& m, context::Context* c, bool modEq = false,
+ int index = 0, bool onlyExist = false );
+ bool removeInstMatch( QuantifiersEngine* qe, Node q, std::vector< Node >& m, int index = 0 );
void print( std::ostream& out, Node q ) const{
std::vector< TNode > terms;
print( out, q, terms );
}
+ void getInstantiations( std::vector< Node >& insts, Node q, QuantifiersEngine * qe ) {
+ std::vector< Node > terms;
+ getInstantiations( insts, q, terms, qe );
+ }
};/* class CDInstMatchTrie */
@@ -190,10 +202,10 @@ public:
public:
/** add match m, return true if successful */
bool addInstMatch( QuantifiersEngine* qe, Node f, InstMatch& m, bool modEq = false, bool modInst = false ){
- return d_imt.addInstMatch( qe, f, m, modEq, modInst, d_imtio );
+ return d_imt.addInstMatch( qe, f, m, modEq, d_imtio );
}
bool existsInstMatch( QuantifiersEngine* qe, Node f, InstMatch& m, bool modEq = false, bool modInst = false ){
- return d_imt.existsInstMatch( qe, f, m, modEq, modInst, d_imtio );
+ return d_imt.existsInstMatch( qe, f, m, modEq, d_imtio );
}
};/* class InstMatchTrieOrdered */
diff --git a/src/theory/quantifiers/inst_match_generator.cpp b/src/theory/quantifiers/inst_match_generator.cpp
index 89c2d4868..bf05de3bb 100644
--- a/src/theory/quantifiers/inst_match_generator.cpp
+++ b/src/theory/quantifiers/inst_match_generator.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file inst_match_generator.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** [[ Add lengthier description here ]]
** \todo document this file
@@ -40,7 +40,6 @@ InstMatchGenerator::InstMatchGenerator( Node pat ){
d_match_pattern_type = pat.getType();
d_next = NULL;
d_matchPolicy = MATCH_GEN_DEFAULT;
- d_eq_class_rel = false;
}
InstMatchGenerator::InstMatchGenerator() {
@@ -59,7 +58,7 @@ void InstMatchGenerator::setActiveAdd(bool val){
void InstMatchGenerator::initialize( Node q, QuantifiersEngine* qe, std::vector< InstMatchGenerator * > & gens ){
if( !d_pattern.isNull() ){
- Debug("inst-match-gen") << "Pattern term is " << d_pattern << std::endl;
+ Trace("inst-match-gen") << "Initialize, pattern term is " << d_pattern << std::endl;
if( d_match_pattern.getKind()==NOT ){
//we want to add the children of the NOT
d_match_pattern = d_pattern[0];
@@ -67,29 +66,23 @@ void InstMatchGenerator::initialize( Node q, QuantifiersEngine* qe, std::vector<
if( d_match_pattern.getKind()==IFF || d_match_pattern.getKind()==EQUAL || d_match_pattern.getKind()==GEQ ){
//make sure the matching portion of the equality is on the LHS of d_pattern
// and record what d_match_pattern is
- if( !quantifiers::TermDb::hasInstConstAttr(d_match_pattern[0]) || d_match_pattern[0].getKind()==INST_CONSTANT ){
- if( d_match_pattern[1].getKind()!=INST_CONSTANT ){
- Assert( quantifiers::TermDb::hasInstConstAttr(d_match_pattern[1]) );
- Node mp = d_match_pattern[1];
- //swap sides
- Node pat = d_pattern;
- if(d_match_pattern.getKind()==GEQ){
- d_pattern = NodeManager::currentNM()->mkNode( kind::GT, d_match_pattern[1], d_match_pattern[0] );
- d_pattern = d_pattern.negate();
- }else{
- d_pattern = NodeManager::currentNM()->mkNode( d_match_pattern.getKind(), d_match_pattern[1], d_match_pattern[0] );
- }
- d_pattern = pat.getKind()==NOT ? d_pattern.negate() : d_pattern;
- d_match_pattern = mp;
- }
- }else if( !quantifiers::TermDb::hasInstConstAttr(d_match_pattern[1]) || d_match_pattern[1].getKind()==INST_CONSTANT ){
- if( d_match_pattern[0].getKind()!=INST_CONSTANT ){
- Assert( quantifiers::TermDb::hasInstConstAttr(d_match_pattern[0]) );
- if( d_pattern.getKind()!=NOT ){ //TEMPORARY until we do better implementation of disequality matching
- d_match_pattern = d_match_pattern[0];
- }else if( d_match_pattern[1].getKind()==INST_CONSTANT ){
- d_match_pattern = d_match_pattern[0];
+ for( unsigned i=0; i<2; i++ ){
+ if( !quantifiers::TermDb::hasInstConstAttr(d_match_pattern[i]) || d_match_pattern[i].getKind()==INST_CONSTANT ){
+ Node mp = d_match_pattern[1-i];
+ Node mpo = d_match_pattern[i];
+ if( mp.getKind()!=INST_CONSTANT ){
+ if( i==0 ){
+ if( d_match_pattern.getKind()==GEQ ){
+ d_pattern = NodeManager::currentNM()->mkNode( kind::GT, mp, mpo );
+ d_pattern = d_pattern.negate();
+ }else{
+ d_pattern = NodeManager::currentNM()->mkNode( d_match_pattern.getKind(), mp, mpo );
+ }
+ }
+ d_eq_class_rel = mpo;
+ d_match_pattern = mp;
}
+ break;
}
}
}else if( d_match_pattern.getKind()==APPLY_SELECTOR_TOTAL && d_match_pattern[0].getKind()==INST_CONSTANT && options::purifyDtTriggers() ){
@@ -97,11 +90,10 @@ void InstMatchGenerator::initialize( Node q, QuantifiersEngine* qe, std::vector<
}
d_match_pattern_type = d_match_pattern.getType();
Trace("inst-match-gen") << "Pattern is " << d_pattern << ", match pattern is " << d_match_pattern << std::endl;
- d_match_pattern_op = qe->getTermDatabase()->getOperator( d_match_pattern );
+ d_match_pattern_op = qe->getTermDatabase()->getMatchOperator( d_match_pattern );
//now, collect children of d_match_pattern
- //int childMatchPolicy = MATCH_GEN_DEFAULT;
- for( int i=0; i<(int)d_match_pattern.getNumChildren(); i++ ){
+ for( unsigned i=0; i<d_match_pattern.getNumChildren(); i++ ){
Node qa = quantifiers::TermDb::getInstConstAttr(d_match_pattern[i]);
if( !qa.isNull() ){
InstMatchGenerator * cimg = Trigger::getInstMatchGenerator( q, d_match_pattern[i] );
@@ -127,9 +119,17 @@ void InstMatchGenerator::initialize( Node q, QuantifiersEngine* qe, std::vector<
}
//create candidate generator
- if( d_match_pattern.getKind()==INST_CONSTANT ){
+ if( Trigger::isAtomicTrigger( d_match_pattern ) ){
+ //we will be scanning lists trying to find d_match_pattern.getOperator()
+ d_cg = new inst::CandidateGeneratorQE( qe, d_match_pattern );
+ //if matching on disequality, inform the candidate generator not to match on eqc
+ if( d_pattern.getKind()==NOT && ( d_pattern[0].getKind()==IFF || d_pattern[0].getKind()==EQUAL ) ){
+ ((inst::CandidateGeneratorQE*)d_cg)->excludeEqc( d_eq_class_rel );
+ d_eq_class_rel = Node::null();
+ }
+ }else if( d_match_pattern.getKind()==INST_CONSTANT ){
if( d_pattern.getKind()==APPLY_SELECTOR_TOTAL ){
- Expr selectorExpr = qe->getTermDatabase()->getOperator( d_pattern ).toExpr();
+ Expr selectorExpr = qe->getTermDatabase()->getMatchOperator( d_pattern ).toExpr();
size_t selectorIndex = Datatype::cindexOf(selectorExpr);
const Datatype& dt = Datatype::datatypeOf(selectorExpr);
const DatatypeConstructor& c = dt[selectorIndex];
@@ -139,7 +139,8 @@ void InstMatchGenerator::initialize( Node q, QuantifiersEngine* qe, std::vector<
}else{
d_cg = new CandidateGeneratorQEAll( qe, d_match_pattern );
}
- }else if( d_match_pattern.getKind()==EQUAL || d_match_pattern.getKind()==IFF ){
+ }else if( ( d_match_pattern.getKind()==EQUAL || d_match_pattern.getKind()==IFF ) &&
+ d_match_pattern[0].getKind()==INST_CONSTANT && d_match_pattern[1].getKind()==INST_CONSTANT ){
//we will be producing candidates via literal matching heuristics
if( d_pattern.getKind()!=NOT ){
//candidates will be all equalities
@@ -148,26 +149,6 @@ void InstMatchGenerator::initialize( Node q, QuantifiersEngine* qe, std::vector<
//candidates will be all disequalities
d_cg = new inst::CandidateGeneratorQELitDeq( qe, d_match_pattern );
}
- }else if( d_pattern.getKind()==EQUAL || d_pattern.getKind()==IFF ||
- d_pattern.getKind()==GEQ || d_pattern.getKind()==GT || d_pattern.getKind()==NOT ){
- Assert( d_matchPolicy==MATCH_GEN_DEFAULT );
- if( d_pattern.getKind()==NOT ){
- if (d_pattern[0][1].getKind()!=INST_CONSTANT) {
- Unimplemented("Disequal generator unimplemented");
- }else{
- d_eq_class = d_pattern[0][1];
- }
- }else{
- //store the equivalence class that we will call d_cg->reset( ... ) on
- d_eq_class = d_pattern[1];
- }
- d_eq_class_rel = true;
- Assert( Trigger::isAtomicTrigger( d_match_pattern ) );
- //we are matching only in a particular equivalence class
- d_cg = new inst::CandidateGeneratorQE( qe, d_match_pattern_op );
- }else if( Trigger::isAtomicTrigger( d_match_pattern ) ){
- //we will be scanning lists trying to find d_match_pattern.getOperator()
- d_cg = new inst::CandidateGeneratorQE( qe, d_match_pattern_op );
}else{
d_cg = new CandidateGeneratorQueue;
Trace("inst-match-gen-warn") << "(?) Unknown matching pattern is " << d_match_pattern << std::endl;
@@ -197,7 +178,7 @@ bool InstMatchGenerator::getMatch( Node f, Node t, InstMatch& m, QuantifiersEngi
Assert( !Trigger::isAtomicTrigger( d_match_pattern ) || t.getOperator()==d_match_pattern.getOperator() );
//first, check if ground arguments are not equal, or a match is in conflict
Trace("matching-debug2") << "Setting immediate matches..." << std::endl;
- for( int i=0; i<(int)d_match_pattern.getNumChildren(); i++ ){
+ for( unsigned i=0; i<d_match_pattern.getNumChildren(); i++ ){
if( d_children_types[i]==0 ){
Trace("matching-debug2") << "Setting " << d_var_num[i] << " to " << t[i] << "..." << std::endl;
bool addToPrev = m.get( d_var_num[i] ).isNull();
@@ -231,8 +212,8 @@ bool InstMatchGenerator::getMatch( Node f, Node t, InstMatch& m, QuantifiersEngi
}
}
//for relational matching
- }else if( d_eq_class_rel && d_eq_class.getKind()==INST_CONSTANT ){
- int v = d_eq_class.getAttribute(InstVarNumAttribute());
+ }else if( !d_eq_class_rel.isNull() && d_eq_class_rel.getKind()==INST_CONSTANT ){
+ int v = d_eq_class_rel.getAttribute(InstVarNumAttribute());
//also must fit match to equivalence class
bool pol = d_pattern.getKind()!=NOT;
Node pat = d_pattern.getKind()==NOT ? d_pattern[0] : d_pattern;
@@ -289,7 +270,7 @@ bool InstMatchGenerator::continueNextMatch( Node f, InstMatch& m, QuantifiersEng
return d_next->getNextMatch( f, m, qe );
}else{
if( d_active_add ){
- return qe->addInstantiation( f, m, false );
+ return qe->addInstantiation( f, m );
}else{
return true;
}
@@ -313,20 +294,22 @@ void InstMatchGenerator::resetInstantiationRound( QuantifiersEngine* qe ){
void InstMatchGenerator::reset( Node eqc, QuantifiersEngine* qe ){
eqc = qe->getEqualityQuery()->getRepresentative( eqc );
Trace("matching-debug2") << this << " reset " << eqc << "." << std::endl;
- if( !eqc.isNull() ){
+ if( !d_eq_class_rel.isNull() && d_eq_class_rel.getKind()!=INST_CONSTANT ){
+ d_eq_class = d_eq_class_rel;
+ }else if( !eqc.isNull() ){
d_eq_class = eqc;
}
//we have a specific equivalence class in mind
//we are producing matches for f(E) ~ t, where E is a non-ground vector of terms, and t is a ground term
//just look in equivalence class of the RHS
- d_cg->reset( d_eq_class_rel ? Node::null() : d_eq_class );
+ d_cg->reset( d_eq_class );
d_needsReset = false;
}
bool InstMatchGenerator::getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe ){
if( d_needsReset ){
Trace("matching") << "Reset not done yet, must do the reset..." << std::endl;
- reset( d_eq_class_rel ? Node::null() : d_eq_class, qe );
+ reset( d_eq_class, qe );
}
m.d_matched = Node::null();
Trace("matching") << this << " " << d_match_pattern << " get next match " << m << " in eq class " << d_eq_class << std::endl;
@@ -346,7 +329,7 @@ bool InstMatchGenerator::getNextMatch( Node f, InstMatch& m, QuantifiersEngine*
if( !success ){
Trace("matching") << this << " failed, reset " << d_eq_class << std::endl;
//we failed, must reset
- reset( d_eq_class_rel ? Node::null() : d_eq_class, qe );
+ reset( d_eq_class, qe );
}
return success;
}
@@ -360,11 +343,17 @@ int InstMatchGenerator::addInstantiations( Node f, InstMatch& baseMatch, Quantif
while( getNextMatch( f, m, qe ) ){
if( !d_active_add ){
m.add( baseMatch );
- if( qe->addInstantiation( f, m, false ) ){
+ if( qe->addInstantiation( f, m ) ){
addedLemmas++;
+ if( qe->inConflict() ){
+ break;
+ }
}
}else{
addedLemmas++;
+ if( qe->inConflict() ){
+ break;
+ }
}
m.clear();
}
@@ -377,12 +366,12 @@ int InstMatchGenerator::addTerm( Node f, Node t, QuantifiersEngine* qe ){
if( !d_match_pattern.isNull() ){
InstMatch m( f );
if( getMatch( f, t, m, qe ) ){
- if( qe->addInstantiation( f, m, false ) ){
+ if( qe->addInstantiation( f, m ) ){
return 1;
}
}
}else{
- for( int i=0; i<(int)d_children.size(); i++ ){
+ for( unsigned i=0; i<d_children.size(); i++ ){
d_children[i]->addTerm( f, t, qe );
}
}
@@ -544,14 +533,14 @@ d_f( q ){
/** reset instantiation round (call this whenever equivalence classes have changed) */
void InstMatchGeneratorMulti::resetInstantiationRound( QuantifiersEngine* qe ){
- for( int i=0; i<(int)d_children.size(); i++ ){
+ for( unsigned i=0; i<d_children.size(); i++ ){
d_children[i]->resetInstantiationRound( qe );
}
}
/** reset, eqc is the equivalence class to search in (any if eqc=null) */
void InstMatchGeneratorMulti::reset( Node eqc, QuantifiersEngine* qe ){
- for( int i=0; i<(int)d_children.size(); i++ ){
+ for( unsigned i=0; i<d_children.size(); i++ ){
d_children[i]->reset( eqc, qe );
}
}
@@ -559,7 +548,7 @@ void InstMatchGeneratorMulti::reset( Node eqc, QuantifiersEngine* qe ){
int InstMatchGeneratorMulti::addInstantiations( Node q, InstMatch& baseMatch, QuantifiersEngine* qe ){
int addedLemmas = 0;
Debug("smart-multi-trigger") << "Process smart multi trigger" << std::endl;
- for( int i=0; i<(int)d_children.size(); i++ ){
+ for( unsigned i=0; i<d_children.size(); i++ ){
Debug("smart-multi-trigger") << "Calculate matches " << i << std::endl;
std::vector< InstMatch > newMatches;
InstMatch m( q );
@@ -569,8 +558,11 @@ int InstMatchGeneratorMulti::addInstantiations( Node q, InstMatch& baseMatch, Qu
m.clear();
}
Debug("smart-multi-trigger") << "Made " << newMatches.size() << " new matches for index " << i << std::endl;
- for( int j=0; j<(int)newMatches.size(); j++ ){
+ for( unsigned j=0; j<newMatches.size(); j++ ){
processNewMatch( qe, newMatches[j], i, addedLemmas );
+ if( qe->inConflict() ){
+ return addedLemmas;
+ }
}
}
return addedLemmas;
@@ -593,6 +585,7 @@ void InstMatchGeneratorMulti::processNewMatch( QuantifiersEngine* qe, InstMatch&
void InstMatchGeneratorMulti::processNewInstantiations( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas, InstMatchTrie* tr,
std::vector< IndexedTrie >& unique_var_tries,
int trieIndex, int childIndex, int endChildIndex, bool modEq ){
+ Assert( !qe->inConflict() );
if( childIndex==endChildIndex ){
//now, process unique variables
processNewInstantiations2( qe, m, addedLemmas, unique_var_tries, 0 );
@@ -614,6 +607,9 @@ void InstMatchGeneratorMulti::processNewInstantiations( QuantifiersEngine* qe, I
mn.setValue( curr_index, it->first);
processNewInstantiations( qe, mn, addedLemmas, &(it->second), unique_var_tries,
trieIndex+1, childIndex, endChildIndex, modEq );
+ if( qe->inConflict() ){
+ break;
+ }
}
//}
}else{
@@ -635,6 +631,9 @@ void InstMatchGeneratorMulti::processNewInstantiations( QuantifiersEngine* qe, I
if( itc!=tr->d_data.end() ){
processNewInstantiations( qe, m, addedLemmas, &(itc->second), unique_var_tries,
trieIndex+1, childIndex, endChildIndex, modEq );
+ if( qe->inConflict() ){
+ break;
+ }
}
}
++eqc;
@@ -666,13 +665,16 @@ void InstMatchGeneratorMulti::processNewInstantiations2( QuantifiersEngine* qe,
InstMatch mn( &m );
mn.setValue( curr_index, it->first);
processNewInstantiations2( qe, mn, addedLemmas, unique_var_tries, uvtIndex, &(it->second), trieIndex+1 );
+ if( qe->inConflict() ){
+ break;
+ }
}
}else{
processNewInstantiations2( qe, m, addedLemmas, unique_var_tries, uvtIndex+1 );
}
}else{
//m is an instantiation
- if( qe->addInstantiation( d_f, m, false ) ){
+ if( qe->addInstantiation( d_f, m ) ){
addedLemmas++;
Debug("smart-multi-trigger") << "-> Produced instantiation " << m << std::endl;
}
@@ -683,7 +685,7 @@ int InstMatchGeneratorMulti::addTerm( Node q, Node t, QuantifiersEngine* qe ){
Assert( options::eagerInstQuant() );
int addedLemmas = 0;
for( int i=0; i<(int)d_children.size(); i++ ){
- Node t_op = qe->getTermDatabase()->getOperator( t );
+ Node t_op = qe->getTermDatabase()->getMatchOperator( t );
if( ((InstMatchGenerator*)d_children[i])->d_match_pattern_op==t_op ){
InstMatch m( q );
//if it produces a match, then process it with the rest
@@ -696,6 +698,18 @@ int InstMatchGeneratorMulti::addTerm( Node q, Node t, QuantifiersEngine* qe ){
}
InstMatchGeneratorSimple::InstMatchGeneratorSimple( Node q, Node pat ) : d_f( q ), d_match_pattern( pat ) {
+ if( d_match_pattern.getKind()==NOT ){
+ d_match_pattern = d_match_pattern[0];
+ d_pol = false;
+ }else{
+ d_pol = true;
+ }
+ if( d_match_pattern.getKind()==EQUAL || d_match_pattern.getKind()==IFF ){
+ d_eqc = d_match_pattern[1];
+ d_match_pattern = d_match_pattern[0];
+ Assert( !quantifiers::TermDb::hasInstConstAttr( d_eqc ) );
+ }
+ Assert( Trigger::isSimpleTrigger( d_match_pattern ) );
for( unsigned i=0; i<d_match_pattern.getNumChildren(); i++ ){
if( d_match_pattern[i].getKind()==INST_CONSTANT ){
if( !options::cbqi() || quantifiers::TermDb::getInstConstAttr(d_match_pattern[i])==q ){
@@ -709,15 +723,39 @@ InstMatchGeneratorSimple::InstMatchGeneratorSimple( Node q, Node pat ) : d_f( q
}
void InstMatchGeneratorSimple::resetInstantiationRound( QuantifiersEngine* qe ) {
- d_op = qe->getTermDatabase()->getOperator( d_match_pattern );
+ d_op = qe->getTermDatabase()->getMatchOperator( d_match_pattern );
}
int InstMatchGeneratorSimple::addInstantiations( Node q, InstMatch& baseMatch, QuantifiersEngine* qe ){
- InstMatch m( q );
- m.add( baseMatch );
int addedLemmas = 0;
-
- addInstantiations( m, qe, addedLemmas, 0, &(qe->getTermDatabase()->d_func_map_trie[ d_op ]) );
+ quantifiers::TermArgTrie* tat;
+ if( d_eqc.isNull() ){
+ tat = qe->getTermDatabase()->getTermArgTrie( d_op );
+ }else{
+ if( d_pol ){
+ tat = qe->getTermDatabase()->getTermArgTrie( d_eqc, d_op );
+ }else{
+ Node r = qe->getEqualityQuery()->getRepresentative( d_eqc );
+ //iterate over all classes except r
+ tat = qe->getTermDatabase()->getTermArgTrie( Node::null(), d_op );
+ for( std::map< TNode, quantifiers::TermArgTrie >::iterator it = tat->d_data.begin(); it != tat->d_data.end(); ++it ){
+ if( it->first!=r ){
+ InstMatch m( q );
+ m.add( baseMatch );
+ addInstantiations( m, qe, addedLemmas, 0, &(it->second) );
+ if( qe->inConflict() ){
+ break;
+ }
+ }
+ }
+ tat = NULL;
+ }
+ }
+ if( tat ){
+ InstMatch m( q );
+ m.add( baseMatch );
+ addInstantiations( m, qe, addedLemmas, 0, tat );
+ }
return addedLemmas;
}
@@ -725,14 +763,14 @@ void InstMatchGeneratorSimple::addInstantiations( InstMatch& m, QuantifiersEngin
Debug("simple-trigger-debug") << "Add inst " << argIndex << " " << d_match_pattern << std::endl;
if( argIndex==(int)d_match_pattern.getNumChildren() ){
Assert( !tat->d_data.empty() );
- Node t = tat->d_data.begin()->first;
+ TNode t = tat->getNodeData();
Debug("simple-trigger") << "Actual term is " << t << std::endl;
//convert to actual used terms
for( std::map< int, int >::iterator it = d_var_num.begin(); it != d_var_num.end(); ++it ){
Debug("simple-trigger") << "...set " << it->second << " " << t[it->first] << std::endl;
m.setValue( it->second, t[it->first] );
}
- if( qe->addInstantiation( d_f, m, false ) ){
+ if( qe->addInstantiation( d_f, m ) ){
addedLemmas++;
Debug("simple-trigger") << "-> Produced instantiation " << m << std::endl;
}
@@ -749,10 +787,14 @@ void InstMatchGeneratorSimple::addInstantiations( InstMatch& m, QuantifiersEngin
m.setValue( v, t);
addInstantiations( m, qe, addedLemmas, argIndex+1, &(it->second) );
m.setValue( v, prev);
+ if( qe->inConflict() ){
+ break;
+ }
}
}
return;
}
+ //inst constant from another quantified formula, treat as ground term TODO: remove this?
}
Node r = qe->getEqualityQuery()->getRepresentative( d_match_pattern[argIndex] );
std::map< TNode, quantifiers::TermArgTrie >::iterator it = tat->d_data.find( r );
@@ -763,16 +805,17 @@ void InstMatchGeneratorSimple::addInstantiations( InstMatch& m, QuantifiersEngin
}
int InstMatchGeneratorSimple::addTerm( Node q, Node t, QuantifiersEngine* qe ){
+ //for eager instantiation only
Assert( options::eagerInstQuant() );
InstMatch m( q );
- for( int i=0; i<(int)t.getNumChildren(); i++ ){
+ for( unsigned i=0; i<t.getNumChildren(); i++ ){
if( d_match_pattern[i].getKind()==INST_CONSTANT ){
m.setValue(d_var_num[i], t[i]);
}else if( !qe->getEqualityQuery()->areEqual( d_match_pattern[i], t[i] ) ){
return 0;
}
}
- return qe->addInstantiation( q, m, false ) ? 1 : 0;
+ return qe->addInstantiation( q, m ) ? 1 : 0;
}
}/* CVC4::theory::inst namespace */
diff --git a/src/theory/quantifiers/inst_match_generator.h b/src/theory/quantifiers/inst_match_generator.h
index 75adeb2d8..a1d907001 100644
--- a/src/theory/quantifiers/inst_match_generator.h
+++ b/src/theory/quantifiers/inst_match_generator.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file inst_match_generator.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Andrew Reynolds, Clark Barrett
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief inst match generator class
**/
@@ -64,7 +64,7 @@ protected:
InstMatchGenerator* d_next;
/** eq class */
Node d_eq_class;
- bool d_eq_class_rel;
+ Node d_eq_class_rel;
/** variable numbers */
std::map< int, int > d_var_num;
/** initialize pattern */
@@ -211,6 +211,9 @@ private:
Node d_f;
/** match term */
Node d_match_pattern;
+ /** equivalence class */
+ bool d_pol;
+ Node d_eqc;
/** match pattern arg types */
std::vector< TypeNode > d_match_pattern_arg_types;
/** operator */
diff --git a/src/theory/quantifiers/inst_propagator.cpp b/src/theory/quantifiers/inst_propagator.cpp
new file mode 100644
index 000000000..d4be58636
--- /dev/null
+++ b/src/theory/quantifiers/inst_propagator.cpp
@@ -0,0 +1,761 @@
+/********************* */
+/*! \file inst_propagator.cpp
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Andrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2016 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.\endverbatim
+ **
+ ** Propagate mechanism for instantiations
+ **/
+
+#include <vector>
+
+#include "theory/quantifiers/inst_propagator.h"
+#include "theory/rewriter.h"
+#include "theory/quantifiers/term_database.h"
+
+using namespace CVC4;
+using namespace std;
+using namespace CVC4::theory;
+using namespace CVC4::theory::quantifiers;
+using namespace CVC4::kind;
+
+
+EqualityQueryInstProp::EqualityQueryInstProp( QuantifiersEngine* qe ) : d_qe( qe ){
+ d_true = NodeManager::currentNM()->mkConst( true );
+ d_false = NodeManager::currentNM()->mkConst( false );
+}
+
+bool EqualityQueryInstProp::reset( Theory::Effort e ) {
+ d_uf.clear();
+ d_uf_exp.clear();
+ d_diseq_list.clear();
+ return true;
+}
+
+/** contains term */
+bool EqualityQueryInstProp::hasTerm( Node a ) {
+ if( getEngine()->hasTerm( a ) ){
+ return true;
+ }else{
+ std::vector< Node > exp;
+ Node ar = getUfRepresentative( a, exp );
+ return !ar.isNull() && getEngine()->hasTerm( ar );
+ }
+}
+
+/** get the representative of the equivalence class of a */
+Node EqualityQueryInstProp::getRepresentative( Node a ) {
+ if( getEngine()->hasTerm( a ) ){
+ a = getEngine()->getRepresentative( a );
+ }
+ std::vector< Node > exp;
+ Node ar = getUfRepresentative( a, exp );
+ return ar.isNull() ? a : ar;
+}
+
+/** returns true if a and b are equal in the current context */
+bool EqualityQueryInstProp::areEqual( Node a, Node b ) {
+ if( a==b ){
+ return true;
+ }else{
+ eq::EqualityEngine* ee = getEngine();
+ if( ee->hasTerm( a ) && ee->hasTerm( b ) ){
+ if( ee->areEqual( a, b ) ){
+ return true;
+ }
+ }
+ return false;
+ }
+}
+
+/** returns true is a and b are disequal in the current context */
+bool EqualityQueryInstProp::areDisequal( Node a, Node b ) {
+ if( a==b ){
+ return false;
+ }else{
+ eq::EqualityEngine* ee = getEngine();
+ if( ee->hasTerm( a ) && ee->hasTerm( b ) ){
+ if( ee->areDisequal( a, b, false ) ){
+ return true;
+ }
+ }
+ return false;
+ }
+}
+
+/** get the equality engine associated with this query */
+eq::EqualityEngine* EqualityQueryInstProp::getEngine() {
+ return d_qe->getMasterEqualityEngine();
+}
+
+/** get the equivalence class of a */
+void EqualityQueryInstProp::getEquivalenceClass( Node a, std::vector< Node >& eqc ) {
+ //TODO?
+}
+
+TNode EqualityQueryInstProp::getCongruentTerm( Node f, std::vector< TNode >& args ) {
+ TNode t = d_qe->getTermDatabase()->getCongruentTerm( f, args );
+ if( !t.isNull() ){
+ return t;
+ }else{
+ //TODO?
+ return TNode::null();
+ }
+}
+
+Node EqualityQueryInstProp::getRepresentativeExp( Node a, std::vector< Node >& exp ) {
+ bool engine_has_a = getEngine()->hasTerm( a );
+ if( engine_has_a ){
+ a = getEngine()->getRepresentative( a );
+ }
+ //get union find representative, if this occurs in the equality engine, return it
+ unsigned prev_size = exp.size();
+ Node ar = getUfRepresentative( a, exp );
+ if( !ar.isNull() ){
+ if( engine_has_a || getEngine()->hasTerm( ar ) ){
+ Assert( getEngine()->hasTerm( ar ) );
+ Assert( getEngine()->getRepresentative( ar )==ar );
+ return ar;
+ }
+ }else{
+ if( engine_has_a ){
+ return a;
+ }
+ }
+ //retract explanation
+ while( exp.size()>prev_size ){
+ exp.pop_back();
+ }
+ return Node::null();
+}
+
+bool EqualityQueryInstProp::areEqualExp( Node a, Node b, std::vector< Node >& exp ) {
+ if( areEqual( a, b ) ){
+ return true;
+ }else{
+ std::vector< Node > exp_a;
+ Node ar = getUfRepresentative( a, exp_a );
+ if( !ar.isNull() ){
+ std::vector< Node > exp_b;
+ if( ar==getUfRepresentative( b, exp_b ) ){
+ merge_exp( exp, exp_a );
+ merge_exp( exp, exp_b );
+ return true;
+ }
+ }
+ return false;
+ }
+}
+
+bool EqualityQueryInstProp::areDisequalExp( Node a, Node b, std::vector< Node >& exp ) {
+ if( areDisequal( a, b ) ){
+ return true;
+ }else{
+ //Assert( getRepresentative( a )==a );
+ //Assert( getRepresentative( b )==b );
+ std::map< Node, std::vector< Node > >::iterator itd = d_diseq_list[a].find( b );
+ if( itd!=d_diseq_list[a].end() ){
+ exp.insert( exp.end(), itd->second.begin(), itd->second.end() );
+ return true;
+ }else{
+ return false;
+ }
+ }
+}
+
+Node EqualityQueryInstProp::getUfRepresentative( Node a, std::vector< Node >& exp ) {
+ Assert( exp.empty() );
+ std::map< Node, Node >::iterator it = d_uf.find( a );
+ if( it!=d_uf.end() ){
+ if( it->second==a ){
+ Assert( d_uf_exp[ a ].empty() );
+ return it->second;
+ }else{
+ Node m = getUfRepresentative( it->second, exp );
+ Assert( !m.isNull() );
+ if( m!=it->second ){
+ //update union find
+ d_uf[ a ] = m;
+ //update explanation : merge the explanation of the parent
+ merge_exp( d_uf_exp[ a ], exp );
+ Trace("qip-eq") << "EqualityQueryInstProp::getUfRepresentative : merge " << a << " -> " << m << ", exp size=" << d_uf_exp[ a ].size() << std::endl;
+ }
+ //add current explanation to exp: note that exp is a subset of d_uf_exp[ a ], reset
+ exp.clear();
+ exp.insert( exp.end(), d_uf_exp[ a ].begin(), d_uf_exp[ a ].end() );
+ return m;
+ }
+ }else{
+ return Node::null();
+ }
+}
+
+// set a == b with reason, return status, modify a and b to representatives pre-merge
+int EqualityQueryInstProp::setEqual( Node& a, Node& b, bool pol, std::vector< Node >& reason ) {
+ if( a==b ){
+ return pol ? STATUS_NONE : STATUS_CONFLICT;
+ }
+ int status = pol ? STATUS_MERGED_UNKNOWN : STATUS_NONE;
+ Trace("qip-eq") << "EqualityQueryInstProp::setEqual " << a << ", " << b << ", pol = " << pol << ", reason size = " << reason.size() << std::endl;
+ //get the representative for a
+ std::vector< Node > exp_a;
+ Node ar = getUfRepresentative( a, exp_a );
+ if( ar.isNull() ){
+ Assert( exp_a.empty() );
+ ar = a;
+ }
+ if( ar==b ){
+ Trace("qip-eq") << "EqualityQueryInstProp::setEqual : already equal" << std::endl;
+ if( pol ){
+ return STATUS_NONE;
+ }else{
+ merge_exp( reason, exp_a );
+ return STATUS_CONFLICT;
+ }
+ }
+ bool swap = false;
+ //get the representative for b
+ std::vector< Node > exp_b;
+ Node br = getUfRepresentative( b, exp_b );
+ if( br.isNull() ){
+ Assert( exp_b.empty() );
+ br = b;
+ if( !getEngine()->hasTerm( br ) ){
+ if( ar!=a || getEngine()->hasTerm( ar ) ){
+ swap = true;
+ }
+ }else{
+ if( getEngine()->hasTerm( ar ) ){
+ status = STATUS_MERGED_KNOWN;
+ }
+ }
+ }else{
+ if( ar==br ){
+ Trace("qip-eq") << "EqualityQueryInstProp::setEqual : already equal" << std::endl;
+ if( pol ){
+ return STATUS_NONE;
+ }else{
+ merge_exp( reason, exp_a );
+ merge_exp( reason, exp_b );
+ return STATUS_CONFLICT;
+ }
+ }else if( getEngine()->hasTerm( ar ) ){
+ if( getEngine()->hasTerm( br ) ){
+ status = STATUS_MERGED_KNOWN;
+ }else{
+ swap = true;
+ }
+ }
+ }
+
+ if( swap ){
+ //swap
+ Node temp_r = ar;
+ ar = br;
+ br = temp_r;
+ }
+
+ Assert( !getEngine()->hasTerm( ar ) || getEngine()->hasTerm( br ) );
+ Assert( ar!=br );
+
+ std::vector< Node > exp_d;
+ if( areDisequalExp( ar, br, exp_d ) ){
+ if( pol ){
+ merge_exp( reason, exp_b );
+ merge_exp( reason, exp_b );
+ merge_exp( reason, exp_d );
+ return STATUS_CONFLICT;
+ }else{
+ return STATUS_NONE;
+ }
+ }else{
+ if( pol ){
+ //update the union find
+ Assert( d_uf_exp[ar].empty() );
+ Assert( d_uf_exp[br].empty() );
+
+ d_uf[ar] = br;
+ merge_exp( d_uf_exp[ar], exp_a );
+ merge_exp( d_uf_exp[ar], exp_b );
+ merge_exp( d_uf_exp[ar], reason );
+
+ d_uf[br] = br;
+ d_uf_exp[br].clear();
+
+ Trace("qip-eq") << "EqualityQueryInstProp::setEqual : merge " << ar << " -> " << br << ", exp size = " << d_uf_exp[ar].size() << ", status = " << status << std::endl;
+ a = ar;
+ b = br;
+
+ //carry disequality list
+ std::map< Node, std::map< Node, std::vector< Node > > >::iterator itd = d_diseq_list.find( ar );
+ if( itd!=d_diseq_list.end() ){
+ for( std::map< Node, std::vector< Node > >::iterator itdd = itd->second.begin(); itdd != itd->second.end(); ++itdd ){
+ Node d = itdd->first;
+ if( d_diseq_list[br].find( d )==d_diseq_list[br].end() ){
+ merge_exp( d_diseq_list[br][d], itdd->second );
+ merge_exp( d_diseq_list[br][d], d_uf_exp[ar] );
+ }
+ }
+ }
+
+ return status;
+ }else{
+ Trace("qip-eq") << "EqualityQueryInstProp::setEqual : disequal " << ar << " <> " << br << std::endl;
+ Assert( d_diseq_list[ar].find( br )==d_diseq_list[ar].end() );
+ Assert( d_diseq_list[br].find( ar )==d_diseq_list[br].end() );
+
+ merge_exp( d_diseq_list[ar][br], reason );
+ merge_exp( d_diseq_list[br][ar], reason );
+ return STATUS_NONE;
+ }
+ }
+}
+
+void EqualityQueryInstProp::addArgument( std::vector< Node >& args, std::vector< Node >& props, Node n, bool is_prop, bool pol ) {
+ if( is_prop ){
+ if( isLiteral( n ) ){
+ props.push_back( pol ? n : n.negate() );
+ return;
+ }
+ }
+ args.push_back( n );
+}
+
+bool EqualityQueryInstProp::isLiteral( Node n ) {
+ Kind ak = n.getKind()==NOT ? n[0].getKind() : n.getKind();
+ Assert( ak!=NOT );
+ return ak!=AND && ak!=OR && ak!=IFF && ak!=ITE;
+}
+
+//this is identical to TermDb::evaluateTerm2, but tracks more information
+Node EqualityQueryInstProp::evaluateTermExp( Node n, std::vector< Node >& exp, std::map< Node, Node >& visited, bool hasPol, bool pol,
+ std::map< Node, bool >& watch_list_out, std::vector< Node >& props ) {
+ std::map< Node, Node >::iterator itv = visited.find( n );
+ if( itv != visited.end() ){
+ return itv->second;
+ }else{
+ visited[n] = n;
+ Trace("qip-eval") << "evaluate term : " << n << std::endl;
+ std::vector< Node > exp_n;
+ Node ret = getRepresentativeExp( n, exp_n );
+ if( ret.isNull() ){
+ //term is not known to be equal to a representative in equality engine, evaluate it
+ Kind k = n.getKind();
+ if( k==FORALL ){
+ ret = Node::null();
+ }else{
+ std::map< Node, bool > watch_list_out_curr;
+ TNode f = d_qe->getTermDatabase()->getMatchOperator( n );
+ std::vector< Node > args;
+ bool ret_set = false;
+ bool childChanged = false;
+ int abort_i = -1;
+ //get the child entailed polarity
+ Assert( n.getKind()!=IMPLIES );
+ bool newHasPol, newPol;
+ QuantPhaseReq::getEntailPolarity( n, 0, hasPol, pol, newHasPol, newPol );
+ //for each child
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ Node c = evaluateTermExp( n[i], exp, visited, newHasPol, newPol, watch_list_out_curr, props );
+ if( c.isNull() ){
+ ret = Node::null();
+ ret_set = true;
+ break;
+ }else if( c==d_true || c==d_false ){
+ //short-circuiting
+ if( k==kind::AND || k==kind::OR ){
+ if( (k==kind::AND)==(c==d_false) ){
+ ret = c;
+ ret_set = true;
+ break;
+ }else{
+ //redundant
+ c = Node::null();
+ childChanged = true;
+ }
+ }else if( k==kind::ITE && i==0 ){
+ Assert( watch_list_out_curr.empty() );
+ ret = evaluateTermExp( n[ c==d_true ? 1 : 2], exp, visited, hasPol, pol, watch_list_out_curr, props );
+ ret_set = true;
+ break;
+ }else if( k==kind::NOT ){
+ ret = c==d_true ? d_false : d_true;
+ ret_set = true;
+ break;
+ }
+ }
+ if( !c.isNull() ){
+ childChanged = childChanged || n[i]!=c;
+ if( !f.isNull() && !watch_list_out_curr.empty() ){
+ // we are done if this is an UF application and an argument is unevaluated
+ args.push_back( c );
+ abort_i = i;
+ break;
+ }else if( ( k==kind::AND || k==kind::OR ) ){
+ if( c.getKind()==k ){
+ //flatten
+ for( unsigned j=0; j<c.getNumChildren(); j++ ){
+ addArgument( args, props, c[j], newHasPol, newPol );
+ }
+ }else{
+ addArgument( args, props, c, newHasPol, newPol );
+ }
+ //if we are in a branching position
+ if( hasPol && !newHasPol && args.size()>=2 ){
+ //we are done if at least two args are unevaluated
+ abort_i = i;
+ break;
+ }
+ }else if( k==kind::ITE ){
+ //we are done if we are ITE and condition is unevaluated
+ Assert( i==0 );
+ args.push_back( c );
+ abort_i = i;
+ break;
+ }else{
+ args.push_back( c );
+ }
+ }
+ }
+ //add remaining children if we aborted
+ if( abort_i!=-1 ){
+ for( int i=(abort_i+1); i<(int)n.getNumChildren(); i++ ){
+ args.push_back( n[i] );
+ }
+ }
+ //copy over the watch list
+ for( std::map< Node, bool >::iterator itc = watch_list_out_curr.begin(); itc != watch_list_out_curr.end(); ++itc ){
+ watch_list_out[itc->first] = itc->second;
+ }
+
+ //if we have not short-circuited evaluation
+ if( !ret_set ){
+ //if it is an indexed term, return the congruent term
+ if( !f.isNull() && watch_list_out.empty() ){
+ std::vector< TNode > t_args;
+ for( unsigned i=0; i<args.size(); i++ ) {
+ t_args.push_back( args[i] );
+ }
+ Assert( args.size()==n.getNumChildren() );
+ //args contains terms known by the equality engine
+ TNode nn = getCongruentTerm( f, t_args );
+ Trace("qip-eval") << " got congruent term " << nn << " from DB for " << n << std::endl;
+ if( !nn.isNull() ){
+ //successfully constructed representative in EE
+ Assert( exp_n.empty() );
+ ret = getRepresentativeExp( nn, exp_n );
+ Trace("qip-eval") << "return rep, exp size = " << exp_n.size() << std::endl;
+ merge_exp( exp, exp_n );
+ ret_set = true;
+ Assert( !ret.isNull() );
+ }
+ }
+ if( !ret_set ){
+ if( childChanged ){
+ Trace("qip-eval") << "return rewrite" << std::endl;
+ if( ( k==kind::AND || k==kind::OR ) ){
+ if( args.empty() ){
+ ret = k==kind::AND ? d_true : d_false;
+ ret_set = true;
+ }else if( args.size()==1 ){
+ ret = args[0];
+ ret_set = true;
+ }
+ }else{
+ Assert( args.size()==n.getNumChildren() );
+ }
+ if( !ret_set ){
+ if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){
+ args.insert( args.begin(), n.getOperator() );
+ }
+ ret = NodeManager::currentNM()->mkNode( k, args );
+ ret = Rewriter::rewrite( ret );
+ //re-evaluate
+ Node ret_eval = getRepresentativeExp( ret, exp_n );
+ if( !ret_eval.isNull() ){
+ ret = ret_eval;
+ watch_list_out.clear();
+ }else{
+ watch_list_out[ret] = true;
+ }
+ }
+ }else{
+ ret = n;
+ watch_list_out[ret] = true;
+ }
+ }
+ }
+ }
+ }else{
+ Trace("qip-eval") << "...exists in ee, return rep, exp size = " << exp_n.size() << std::endl;
+ merge_exp( exp, exp_n );
+ }
+ Trace("qip-eval") << "evaluated term : " << n << ", got : " << ret << ", exp size = " << exp.size() << std::endl;
+ visited[n] = ret;
+ return ret;
+ }
+}
+
+void EqualityQueryInstProp::merge_exp( std::vector< Node >& v, std::vector< Node >& v_to_merge, int up_to_size ) {
+ //TODO : optimize
+ if( v.empty() ){
+ Assert( up_to_size==-1 || up_to_size==(int)v_to_merge.size() );
+ v.insert( v.end(), v_to_merge.begin(), v_to_merge.end() );
+ }else{
+ //std::vector< Node >::iterator v_end = v.end();
+ up_to_size = up_to_size==-1 ? (int)v_to_merge.size() : up_to_size;
+ for( int j=0; j<up_to_size; j++ ){
+ if( std::find( v.begin(), v.end(), v_to_merge[j] )==v.end() ){
+ v.push_back( v_to_merge[j] );
+ }
+ }
+ }
+}
+
+
+void InstPropagator::InstInfo::init( Node q, Node lem, std::vector< Node >& terms, Node body ) {
+ d_active = true;
+ //information about the instance
+ d_q = q;
+ d_lem = lem;
+ Assert( d_terms.empty() );
+ d_terms.insert( d_terms.end(), terms.begin(), terms.end() );
+ //the current lemma
+ d_curr = body;
+ d_curr_exp.push_back( body );
+}
+
+InstPropagator::InstPropagator( QuantifiersEngine* qe ) :
+d_qe( qe ), d_notify(*this), d_qy( qe ){
+}
+
+bool InstPropagator::reset( Theory::Effort e ) {
+ d_icount = 1;
+ d_ii.clear();
+ for( unsigned i=0; i<2; i++ ){
+ d_conc_to_id[i].clear();
+ d_conc_to_id[i][d_qy.d_true] = 0;
+ }
+ d_conflict = false;
+ d_watch_list.clear();
+ d_update_list.clear();
+ d_relevant_inst.clear();
+ return d_qy.reset( e );
+}
+
+bool InstPropagator::notifyInstantiation( unsigned quant_e, Node q, Node lem, std::vector< Node >& terms, Node body ) {
+ if( !d_conflict ){
+ if( Trace.isOn("qip-prop") ){
+ Trace("qip-prop") << "InstPropagator:: Notify instantiation " << q << " : " << std::endl;
+ for( unsigned i=0; i<terms.size(); i++ ){
+ Trace("qip-prop") << " " << terms[i] << std::endl;
+ }
+ }
+ unsigned id = d_icount;
+ d_icount++;
+ Trace("qip-prop") << "...assign id=" << id << std::endl;
+ d_ii[id].init( q, lem, terms, body );
+ //initialize the information
+ if( cacheConclusion( id, body ) ){
+ Assert( d_update_list.empty() );
+ d_update_list.push_back( id );
+ bool firstTime = true;
+ //update infos in the update list until empty
+ do {
+ unsigned uid = d_update_list.back();
+ d_update_list.pop_back();
+ if( d_ii[uid].d_active ){
+ update( uid, d_ii[uid], firstTime );
+ }
+ firstTime = false;
+ }while( !d_conflict && !d_update_list.empty() );
+ }else{
+ d_ii[id].d_active = false;
+ Trace("qip-prop") << "...duplicate." << std::endl;
+ }
+ Trace("qip-prop") << "...finished notify instantiation." << std::endl;
+ return !d_conflict;
+ }else{
+ Assert( false );
+ return true;
+ }
+}
+
+bool InstPropagator::update( unsigned id, InstInfo& ii, bool firstTime ) {
+ Assert( !d_conflict );
+ Assert( ii.d_active );
+ Trace("qip-prop-debug") << "Update info [" << id << "]..." << std::endl;
+ //update the evaluation of the current lemma
+ std::map< Node, Node > visited;
+ std::map< Node, bool > watch_list;
+ std::vector< Node > props;
+ Node eval = d_qy.evaluateTermExp( ii.d_curr, ii.d_curr_exp, visited, true, true, watch_list, props );
+ if( eval.isNull() ){
+ ii.d_active = false;
+ }else if( firstTime || eval!=ii.d_curr ){
+ if( EqualityQueryInstProp::isLiteral( eval ) ){
+ props.push_back( eval );
+ eval = d_qy.d_true;
+ watch_list.clear();
+ }
+ if( Trace.isOn("qip-prop") ){
+ Trace("qip-prop") << "Update info [" << id << "]..." << std::endl;
+ Trace("qip-prop") << "...updated lemma " << ii.d_curr << " -> " << eval << ", exp = ";
+ debugPrintExplanation( ii.d_curr_exp, "qip-prop" );
+ Trace("qip-prop") << std::endl;
+ Trace("qip-prop") << "...watch list: " << std::endl;
+ for( std::map< Node, bool >::iterator itw = watch_list.begin(); itw!=watch_list.end(); ++itw ){
+ Trace("qip-prop") << " " << itw->first << std::endl;
+ }
+ Trace("qip-prop") << "...new propagations: " << std::endl;
+ for( unsigned i=0; i<props.size(); i++ ){
+ Trace("qip-prop") << " " << props[i] << std::endl;
+ }
+ Trace("qip-prop") << std::endl;
+ }
+ //determine the status of eval
+ if( eval==d_qy.d_false ){
+ Assert( props.empty() );
+ //we have inferred a conflict
+ conflict( ii.d_curr_exp );
+ return false;
+ }else{
+ for( unsigned i=0; i<props.size(); i++ ){
+ Trace("qip-prop-debug2") << "Process propagation " << props[i] << std::endl;
+ //if we haven't propagated this literal yet
+ if( cacheConclusion( id, props[i], 1 ) ){
+ Node lit = props[i].getKind()==NOT ? props[i][0] : props[i];
+ bool pol = props[i].getKind()!=NOT;
+ if( lit.getKind()==EQUAL ){
+ propagate( lit[0], lit[1], pol, ii.d_curr_exp );
+ }else{
+ propagate( lit, pol ? d_qy.d_true : d_qy.d_false, true, ii.d_curr_exp );
+ }
+ if( d_conflict ){
+ return false;
+ }
+ }
+ Trace("qip-prop-debug2") << "Done process propagation " << props[i] << std::endl;
+ }
+ //if we have not inferred this conclusion yet
+ if( cacheConclusion( id, eval ) ){
+ ii.d_curr = eval;
+ //update the watch list
+ Trace("qip-prop-debug") << "...updating watch list for [" << id << "], curr is " << ii.d_curr << std::endl;
+ //Here, we need to be notified of enough terms such that if we are not notified, then update( ii ) will return no propagations.
+ // Similar to two-watched literals, but since we are in UF, we need to watch all terms on a complete path of two terms.
+ for( std::map< Node, bool >::iterator itw = watch_list.begin(); itw != watch_list.end(); ++itw ){
+ d_watch_list[ itw->first ][ id ] = true;
+ }
+ }else{
+ Trace("qip-prop-debug") << "...conclusion " << eval << " is duplicate." << std::endl;
+ ii.d_active = false;
+ }
+ }
+ }else{
+ Trace("qip-prop-debug") << "...did not update." << std::endl;
+ }
+ Assert( !d_conflict );
+ return true;
+}
+
+void InstPropagator::propagate( Node a, Node b, bool pol, std::vector< Node >& exp ) {
+ if( Trace.isOn("qip-propagate") ){
+ Trace("qip-propagate") << "* Propagate " << a << ( pol ? " == " : " != " ) << b << ", exp = ";
+ debugPrintExplanation( exp, "qip-propagate" );
+ Trace("qip-propagate") << "..." << std::endl;
+ }
+ //set equal
+ int status = d_qy.setEqual( a, b, pol, exp );
+ if( status==EqualityQueryInstProp::STATUS_NONE ){
+ Trace("qip-prop-debug") << "...already equal/no conflict." << std::endl;
+ return;
+ }else if( status==EqualityQueryInstProp::STATUS_CONFLICT ){
+ Trace("qip-prop-debug") << "...conflict." << std::endl;
+ conflict( exp );
+ return;
+ }
+ if( pol ){
+ if( status==EqualityQueryInstProp::STATUS_MERGED_KNOWN ){
+ Assert( d_qy.getEngine()->hasTerm( a ) );
+ Assert( d_qy.getEngine()->hasTerm( b ) );
+ Trace("qip-prop-debug") << "...equality between known terms." << std::endl;
+ addRelevantInstances( exp, "qip-propagate" );
+ }
+ Trace("qip-prop-debug") << "...merged representatives " << a << " and " << b << std::endl;
+ for( unsigned i=0; i<2; i++ ){
+ //update terms from watched lists
+ Node c = i==0 ? a : b;
+ std::map< Node, std::map< unsigned, bool > >::iterator it = d_watch_list.find( c );
+ if( it!=d_watch_list.end() ){
+ Trace("qip-prop-debug") << "...update ids from watch list of " << c << ", size=" << it->second.size() << "..." << std::endl;
+ for( std::map< unsigned, bool >::iterator itw = it->second.begin(); itw != it->second.end(); ++itw ){
+ unsigned idw = itw->first;
+ if( std::find( d_update_list.begin(), d_update_list.end(), idw )==d_update_list.end() ){
+ Trace("qip-prop-debug") << "...will update " << idw << std::endl;
+ d_update_list.push_back( idw );
+ }
+ }
+ d_watch_list.erase( c );
+ }
+ }
+ }
+}
+
+void InstPropagator::conflict( std::vector< Node >& exp ) {
+ Trace("qip-propagate") << "Conflict, exp size =" << exp.size() << std::endl;
+ d_conflict = true;
+ d_relevant_inst.clear();
+ addRelevantInstances( exp, "qip-propagate" );
+
+ //now, inform quantifiers engine which instances should be retracted
+ Trace("qip-prop-debug") << "...remove instantiation ids : ";
+ for( std::map< unsigned, InstInfo >::iterator it = d_ii.begin(); it != d_ii.end(); ++it ){
+ if( d_relevant_inst.find( it->first )==d_relevant_inst.end() ){
+ if( !d_qe->removeInstantiation( it->second.d_q, it->second.d_lem, it->second.d_terms ) ){
+ Trace("qip-warn") << "WARNING : did not remove instantiation id " << it->first << std::endl;
+ Assert( false );
+ }else{
+ Trace("qip-prop-debug") << it->first << " ";
+ }
+ }else{
+ //mark the quantified formula as relevant
+ d_qe->markRelevant( it->second.d_q );
+ }
+ }
+ Trace("qip-prop-debug") << std::endl;
+ //will interupt the quantifiers engine
+ Trace("quant-engine-conflict") << "-----> InstPropagator::conflict with " << exp.size() << " instances." << std::endl;
+}
+
+bool InstPropagator::cacheConclusion( unsigned id, Node body, int prop_index ) {
+ Assert( prop_index==0 || prop_index==1 );
+ //check if the conclusion is non-redundant
+ if( d_conc_to_id[prop_index].find( body )==d_conc_to_id[prop_index].end() ){
+ d_conc_to_id[prop_index][body] = id;
+ return true;
+ }else{
+ return false;
+ }
+}
+
+void InstPropagator::addRelevantInstances( std::vector< Node >& exp, const char * c ) {
+ for( unsigned i=0; i<exp.size(); i++ ){
+ Assert( d_conc_to_id[0].find( exp[i] )!=d_conc_to_id[0].end() );
+ Trace(c) << " relevant instance id : " << d_conc_to_id[0][ exp[i] ] << std::endl;
+ d_relevant_inst[ d_conc_to_id[0][ exp[i] ] ] = true;
+ }
+}
+
+void InstPropagator::debugPrintExplanation( std::vector< Node >& exp, const char * c ) {
+ for( unsigned i=0; i<exp.size(); i++ ){
+ Assert( d_conc_to_id[0].find( exp[i] )!=d_conc_to_id[0].end() );
+ Trace(c) << d_conc_to_id[0][ exp[i] ] << " ";
+ }
+}
+
diff --git a/src/theory/quantifiers/inst_propagator.h b/src/theory/quantifiers/inst_propagator.h
new file mode 100644
index 000000000..0c02c7f95
--- /dev/null
+++ b/src/theory/quantifiers/inst_propagator.h
@@ -0,0 +1,163 @@
+/********************* */
+/*! \file inst_propagator.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Andrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2016 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.\endverbatim
+ **
+ ** \brief Propagate mechanism for instantiations
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__QUANTIFIERS_INST_PROPAGATOR_H
+#define __CVC4__QUANTIFIERS_INST_PROPAGATOR_H
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <map>
+#include "expr/node.h"
+#include "expr/type_node.h"
+#include "theory/quantifiers_engine.h"
+#include "theory/quantifiers/term_database.h"
+
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
+
+class EqualityQueryInstProp : public EqualityQuery {
+private:
+ /** pointer to quantifiers engine */
+ QuantifiersEngine* d_qe;
+public:
+ EqualityQueryInstProp( QuantifiersEngine* qe );
+ ~EqualityQueryInstProp(){};
+ /** reset */
+ bool reset( Theory::Effort e );
+ /** identify */
+ std::string identify() const { return "EqualityQueryInstProp"; }
+ /** extends engine */
+ bool extendsEngine() { return true; }
+ /** contains term */
+ bool hasTerm( Node a );
+ /** get the representative of the equivalence class of a */
+ Node getRepresentative( Node a );
+ /** returns true if a and b are equal in the current context */
+ bool areEqual( Node a, Node b );
+ /** returns true is a and b are disequal in the current context */
+ bool areDisequal( Node a, Node b );
+ /** get the equality engine associated with this query */
+ eq::EqualityEngine* getEngine();
+ /** get the equivalence class of a */
+ void getEquivalenceClass( Node a, std::vector< Node >& eqc );
+ /** get congruent term */
+ TNode getCongruentTerm( Node f, std::vector< TNode >& args );
+public:
+ /** get the representative of the equivalence class of a, with explanation */
+ Node getRepresentativeExp( Node a, std::vector< Node >& exp );
+ /** returns true if a and b are equal in the current context */
+ bool areEqualExp( Node a, Node b, std::vector< Node >& exp );
+ /** returns true is a and b are disequal in the current context */
+ bool areDisequalExp( Node a, Node b, std::vector< Node >& exp );
+private:
+ /** term index */
+ std::map< Node, TermArgTrie > d_func_map_trie;
+ /** union find for terms beyond what is stored in equality engine */
+ std::map< Node, Node > d_uf;
+ std::map< Node, std::vector< Node > > d_uf_exp;
+ Node getUfRepresentative( Node a, std::vector< Node >& exp );
+ /** disequality list, stores explanations */
+ std::map< Node, std::map< Node, std::vector< Node > > > d_diseq_list;
+ /** add arg */
+ void addArgument( std::vector< Node >& args, std::vector< Node >& props, Node n, bool is_prop, bool pol );
+public:
+ enum {
+ STATUS_CONFLICT,
+ STATUS_MERGED_KNOWN,
+ STATUS_MERGED_UNKNOWN,
+ STATUS_NONE,
+ };
+ /** set equal */
+ int setEqual( Node& a, Node& b, bool pol, std::vector< Node >& reason );
+ Node d_true;
+ Node d_false;
+public:
+ //for explanations
+ static void merge_exp( std::vector< Node >& v, std::vector< Node >& v_to_merge, int up_to_size = -1 );
+
+ Node evaluateTermExp( Node n, std::vector< Node >& exp, std::map< Node, Node >& visited, bool hasPol, bool pol,
+ std::map< Node, bool >& watch_list_out, std::vector< Node >& props );
+ static bool isLiteral( Node n );
+};
+
+class InstPropagator : public QuantifiersUtil {
+private:
+ /** pointer to quantifiers engine */
+ QuantifiersEngine* d_qe;
+ /** notify class */
+ class InstantiationNotifyInstPropagator : public InstantiationNotify {
+ InstPropagator& d_ip;
+ public:
+ InstantiationNotifyInstPropagator(InstPropagator& ip): d_ip(ip) {}
+ virtual bool notifyInstantiation( unsigned quant_e, Node q, Node lem, std::vector< Node >& terms, Node body ) {
+ return d_ip.notifyInstantiation( quant_e, q, lem, terms, body );
+ }
+ };
+ InstantiationNotifyInstPropagator d_notify;
+ /** notify instantiation method */
+ bool notifyInstantiation( unsigned quant_e, Node q, Node lem, std::vector< Node >& terms, Node body );
+ /** equality query */
+ EqualityQueryInstProp d_qy;
+ class InstInfo {
+ public:
+ bool d_active;
+ Node d_q;
+ Node d_lem;
+ std::vector< Node > d_terms;
+ // the current entailed body
+ Node d_curr;
+ //explanation for current entailed body
+ std::vector< Node > d_curr_exp;
+ void init( Node q, Node lem, std::vector< Node >& terms, Node body );
+ };
+ /** instantiation count/info */
+ unsigned d_icount;
+ std::map< unsigned, InstInfo > d_ii;
+ std::map< Node, unsigned > d_conc_to_id[2];
+ /** are we in conflict */
+ bool d_conflict;
+ /** watch list */
+ std::map< Node, std::map< unsigned, bool > > d_watch_list;
+ /** update list */
+ std::vector< unsigned > d_update_list;
+ /** relevant instances */
+ std::map< unsigned, bool > d_relevant_inst;
+private:
+ bool update( unsigned id, InstInfo& i, bool firstTime = false );
+ void propagate( Node a, Node b, bool pol, std::vector< Node >& exp );
+ void conflict( std::vector< Node >& exp );
+ bool cacheConclusion( unsigned id, Node body, int prop_index = 0 );
+ void addRelevantInstances( std::vector< Node >& exp, const char * c );
+
+ void debugPrintExplanation( std::vector< Node >& exp, const char * c );
+public:
+ InstPropagator( QuantifiersEngine* qe );
+ ~InstPropagator(){}
+ /** reset */
+ bool reset( Theory::Effort e );
+ /** identify */
+ std::string identify() const { return "InstPropagator"; }
+ /** get the notify mechanism */
+ InstantiationNotify* getInstantiationNotify() { return &d_notify; }
+};
+
+}
+}
+}
+
+#endif
diff --git a/src/theory/quantifiers/inst_strategy_cbqi.cpp b/src/theory/quantifiers/inst_strategy_cbqi.cpp
index d5ef2e290..149330c61 100644
--- a/src/theory/quantifiers/inst_strategy_cbqi.cpp
+++ b/src/theory/quantifiers/inst_strategy_cbqi.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file inst_strategy_cbqi.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): Tim King
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of counterexample-guided quantifier instantiation strategies
**/
@@ -34,8 +34,9 @@ using namespace CVC4::theory::arith;
#define ARITH_INSTANTIATOR_USE_MINUS_DELTA
InstStrategyCbqi::InstStrategyCbqi( QuantifiersEngine * qe )
- : QuantifiersModule( qe )
- , d_added_cbqi_lemma( qe->getUserContext() ){
+ : QuantifiersModule( qe ), d_added_cbqi_lemma( qe->getUserContext() )
+//, d_added_inst( qe->getUserContext() )
+{
}
InstStrategyCbqi::~InstStrategyCbqi() throw(){}
@@ -45,7 +46,7 @@ bool InstStrategyCbqi::needsCheck( Theory::Effort e ) {
}
unsigned InstStrategyCbqi::needsModel( Theory::Effort e ) {
- for( int i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+ for( unsigned i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
Node q = d_quantEngine->getModel()->getAssertedQuantifier( i );
if( doCbqi( q ) && d_quantEngine->getModel()->isQuantifierActive( q ) ){
return QuantifiersEngine::QEFFORT_STANDARD;
@@ -58,7 +59,7 @@ void InstStrategyCbqi::reset_round( Theory::Effort effort ) {
d_cbqi_set_quant_inactive = false;
d_incomplete_check = false;
//check if any cbqi lemma has not been added yet
- for( int i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+ for( unsigned i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
Node q = d_quantEngine->getModel()->getAssertedQuantifier( i );
//it is not active if it corresponds to a rewrite rule: we will process in rewrite engine
if( doCbqi( q ) ){
@@ -106,6 +107,7 @@ void InstStrategyCbqi::reset_round( Theory::Effort effort ) {
void InstStrategyCbqi::check( Theory::Effort e, unsigned quant_e ) {
if( quant_e==QuantifiersEngine::QEFFORT_STANDARD ){
+ Assert( !d_quantEngine->inConflict() );
double clSet = 0;
if( Trace.isOn("cbqi-engine") ){
clSet = double(clock())/double(CLOCKS_PER_SEC);
@@ -113,13 +115,16 @@ void InstStrategyCbqi::check( Theory::Effort e, unsigned quant_e ) {
}
unsigned lastWaiting = d_quantEngine->getNumLemmasWaiting();
for( int ee=0; ee<=1; ee++ ){
- for( int i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+ for( unsigned i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
Node q = d_quantEngine->getModel()->getAssertedQuantifier( i );
if( doCbqi( q ) && d_quantEngine->getModel()->isQuantifierActive( q ) ){
process( q, e, ee );
+ if( d_quantEngine->inConflict() ){
+ break;
+ }
}
}
- if( d_quantEngine->getNumLemmasWaiting()>lastWaiting ){
+ if( d_quantEngine->inConflict() || d_quantEngine->getNumLemmasWaiting()>lastWaiting ){
break;
}
}
@@ -162,13 +167,15 @@ void InstStrategyCbqi::registerCounterexampleLemma( Node q, Node lem ){
bool InstStrategyCbqi::hasNonCbqiOperator( Node n, std::map< Node, bool >& visited ){
if( visited.find( n )==visited.end() ){
visited[n] = true;
- if( n.getKind()!=INST_CONSTANT && TermDb::hasInstConstAttr( n ) ){
+ if( n.getKind()!=BOUND_VARIABLE && TermDb::hasBoundVarAttr( n ) ){
if( !inst::Trigger::isCbqiKind( n.getKind() ) ){
Trace("cbqi-debug2") << "Non-cbqi kind : " << n.getKind() << " in " << n << std::endl;
return true;
}else if( n.getKind()==MULT && ( n.getNumChildren()!=2 || !n[0].isConst() ) ){
Trace("cbqi-debug2") << "Non-linear arithmetic : " << n << std::endl;
return true;
+ }else if( n.getKind()==FORALL ){
+ return hasNonCbqiOperator( n[1], visited );
}else{
for( unsigned i=0; i<n.getNumChildren(); i++ ){
if( hasNonCbqiOperator( n[i], visited ) ){
@@ -201,20 +208,25 @@ bool InstStrategyCbqi::doCbqi( Node q ){
std::map< Node, bool >::iterator it = d_do_cbqi.find( q );
if( it==d_do_cbqi.end() ){
bool ret = false;
- //if has an instantiation pattern, don't do it
- if( q.getNumChildren()==3 && options::eMatching() && options::userPatternsQuant()!=USER_PAT_MODE_IGNORE ){
- ret = false;
+ if( d_quantEngine->getTermDatabase()->isQAttrQuantElim( q ) ){
+ ret = true;
}else{
- if( options::cbqiAll() ){
- ret = true;
+ //if has an instantiation pattern, don't do it
+ if( q.getNumChildren()==3 && options::eMatching() && options::userPatternsQuant()!=USER_PAT_MODE_IGNORE ){
+ ret = false;
}else{
- //if quantifier has a non-arithmetic variable, then do not use cbqi
- //if quantifier has an APPLY_UF term, then do not use cbqi
- Node cb = d_quantEngine->getTermDatabase()->getInstConstantBody( q );
- std::map< Node, bool > visited;
- ret = !hasNonCbqiVariable( q ) && !hasNonCbqiOperator( cb, visited );
+ if( options::cbqiAll() ){
+ ret = true;
+ }else{
+ //if quantifier has a non-arithmetic variable, then do not use cbqi
+ //if quantifier has an APPLY_UF term, then do not use cbqi
+ //Node cb = d_quantEngine->getTermDatabase()->getInstConstantBody( q );
+ std::map< Node, bool > visited;
+ ret = !hasNonCbqiVariable( q ) && !hasNonCbqiOperator( q[1], visited );
+ }
}
}
+ Trace("cbqi") << "doCbqi " << q << " returned " << ret << std::endl;
d_do_cbqi[q] = ret;
return ret;
}else{
@@ -224,7 +236,7 @@ bool InstStrategyCbqi::doCbqi( Node q ){
Node InstStrategyCbqi::getNextDecisionRequest(){
// all counterexample literals that are not asserted
- for( int i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+ for( unsigned i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
Node q = d_quantEngine->getModel()->getAssertedQuantifier( i );
if( hasAddedCbqiLemma( q ) ){
Node cel = d_quantEngine->getTermDatabase()->getCounterexampleLiteral( q );
@@ -304,8 +316,10 @@ void InstStrategySimplex::processResetInstantiationRound( Theory::Effort effort
}
}
//print debug
- Debug("quant-arith-debug") << std::endl;
- debugPrint( "quant-arith-debug" );
+ if( Debug.isOn("quant-arith-debug") ){
+ Debug("quant-arith-debug") << std::endl;
+ debugPrint( "quant-arith-debug" );
+ }
d_counter++;
}
@@ -343,10 +357,10 @@ void InstStrategySimplex::process( Node f, Theory::Effort effort, int e ){
bool m_point_valid = true;
int lem = 0;
//scan over all instantiation rows
- for( int i=0; i<d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); i++ ){
+ for( unsigned i=0; i<d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); i++ ){
Node ic = d_quantEngine->getTermDatabase()->getInstantiationConstant( f, i );
Debug("quant-arith-simplex") << "InstStrategySimplex check " << ic << ", rows = " << d_instRows[ic].size() << std::endl;
- for( int j=0; j<(int)d_instRows[ic].size(); j++ ){
+ for( unsigned j=0; j<d_instRows[ic].size(); j++ ){
ArithVar x = d_instRows[ic][j];
if( !d_ceTableaux[ic][x].empty() ){
if( Debug.isOn("quant-arith-simplex") ){
@@ -462,25 +476,25 @@ void InstStrategySimplex::debugPrint( const char* c ){
}
Debug(c) << std::endl;
- for( int i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+ for( unsigned i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
Node f = d_quantEngine->getModel()->getAssertedQuantifier( i );
Debug(c) << f << std::endl;
Debug(c) << " Inst constants: ";
- for( int i=0; i<(int)d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); i++ ){
- if( i>0 ){
+ for( unsigned j=0; j<d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); i++ ){
+ if( j>0 ){
Debug( c ) << ", ";
}
Debug( c ) << d_quantEngine->getTermDatabase()->getInstantiationConstant( f, i );
}
Debug(c) << std::endl;
- for( int j=0; j<d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); j++ ){
+ for( unsigned j=0; j<d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); j++ ){
Node ic = d_quantEngine->getTermDatabase()->getInstantiationConstant( f, j );
Debug(c) << " Instantiation rows for " << ic << " : ";
- for( int i=0; i<(int)d_instRows[ic].size(); i++ ){
- if( i>0 ){
+ for( unsigned k=0; k<d_instRows[ic].size(); k++ ){
+ if( k>0 ){
Debug(c) << ", ";
}
- Debug(c) << d_instRows[ic][i];
+ Debug(c) << d_instRows[ic][k];
}
Debug(c) << std::endl;
}
@@ -559,8 +573,8 @@ Node InstStrategySimplex::getTableauxValue( ArithVar v, bool minus_delta ){
//new implementation
-bool CegqiOutputInstStrategy::addInstantiation( std::vector< Node >& subs ) {
- return d_out->addInstantiation( subs );
+bool CegqiOutputInstStrategy::doAddInstantiation( std::vector< Node >& subs ) {
+ return d_out->doAddInstantiation( subs );
}
bool CegqiOutputInstStrategy::isEligibleForInstantiation( Node n ) {
@@ -580,24 +594,33 @@ InstStrategyCegqi::InstStrategyCegqi( QuantifiersEngine * qe )
InstStrategyCegqi::~InstStrategyCegqi() throw () {
delete d_out;
+
+ for(std::map< Node, CegInstantiator * >::iterator i = d_cinst.begin(),
+ iend = d_cinst.end(); i != iend; ++i) {
+ CegInstantiator * instantiator = (*i).second;
+ delete instantiator;
+ }
+ d_cinst.clear();
}
void InstStrategyCegqi::processResetInstantiationRound( Theory::Effort effort ) {
- d_check_vts_lemma_lc = true;
+ d_check_vts_lemma_lc = false;
}
-void InstStrategyCegqi::process( Node f, Theory::Effort effort, int e ) {
+void InstStrategyCegqi::process( Node q, Theory::Effort effort, int e ) {
if( e==0 ){
- CegInstantiator * cinst = getInstantiator( f );
- Trace("inst-alg") << "-> Run cegqi for " << f << std::endl;
- d_curr_quant = f;
+ CegInstantiator * cinst = getInstantiator( q );
+ Trace("inst-alg") << "-> Run cegqi for " << q << std::endl;
+ d_curr_quant = q;
if( !cinst->check() ){
d_incomplete_check = true;
+ d_check_vts_lemma_lc = true;
}
d_curr_quant = Node::null();
}else if( e==1 ){
//minimize the free delta heuristically on demand
if( d_check_vts_lemma_lc ){
+ Trace("inst-alg") << "-> Minimize delta heuristic, for " << q << std::endl;
d_check_vts_lemma_lc = false;
d_small_const = NodeManager::currentNM()->mkNode( MULT, d_small_const, d_small_const );
d_small_const = Rewriter::rewrite( d_small_const );
@@ -619,11 +642,24 @@ void InstStrategyCegqi::process( Node f, Theory::Effort effort, int e ) {
}
}
-bool InstStrategyCegqi::addInstantiation( std::vector< Node >& subs ) {
+bool InstStrategyCegqi::doAddInstantiation( std::vector< Node >& subs ) {
Assert( !d_curr_quant.isNull() );
- //check if we need virtual term substitution (if used delta or infinity)
- bool used_vts = d_quantEngine->getTermDatabase()->containsVtsTerm( subs, false );
- return d_quantEngine->addInstantiation( d_curr_quant, subs, false, false, false, used_vts );
+ //if doing partial quantifier elimination, record the instantiation and set the incomplete flag instead of sending instantiation lemma
+ if( d_quantEngine->getTermDatabase()->isQAttrQuantElimPartial( d_curr_quant ) ){
+ d_cbqi_set_quant_inactive = true;
+ d_incomplete_check = true;
+ d_quantEngine->recordInstantiationInternal( d_curr_quant, subs, false, false );
+ return true;
+ }else{
+ //check if we need virtual term substitution (if used delta or infinity)
+ bool used_vts = d_quantEngine->getTermDatabase()->containsVtsTerm( subs, false );
+ if( d_quantEngine->addInstantiation( d_curr_quant, subs, false, false, used_vts ) ){
+ //d_added_inst.insert( d_curr_quant );
+ return true;
+ }else{
+ return false;
+ }
+ }
}
bool InstStrategyCegqi::addLemma( Node lem ) {
@@ -665,7 +701,7 @@ void InstStrategyCegqi::registerCounterexampleLemma( Node q, Node lem ) {
//must register with the instantiator
//must explicitly remove ITEs so that we record dependencies
std::vector< Node > ce_vars;
- for( int i=0; i<d_quantEngine->getTermDatabase()->getNumInstantiationConstants( q ); i++ ){
+ for( unsigned i=0; i<d_quantEngine->getTermDatabase()->getNumInstantiationConstants( q ); i++ ){
ce_vars.push_back( d_quantEngine->getTermDatabase()->getInstantiationConstant( q, i ) );
}
std::vector< Node > lems;
diff --git a/src/theory/quantifiers/inst_strategy_cbqi.h b/src/theory/quantifiers/inst_strategy_cbqi.h
index 5511af209..8ed59778b 100644
--- a/src/theory/quantifiers/inst_strategy_cbqi.h
+++ b/src/theory/quantifiers/inst_strategy_cbqi.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file inst_strategy_cbqi.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): Tim King
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief counterexample-guided quantifier instantiation
**/
@@ -39,6 +39,8 @@ protected:
bool d_incomplete_check;
/** whether we have added cbqi lemma */
NodeSet d_added_cbqi_lemma;
+ /** whether we have instantiated quantified formulas */
+ //NodeSet d_added_inst;
/** whether to do cbqi for this quantified formula */
std::map< Node, bool > d_do_cbqi;
/** register ce lemma */
@@ -120,7 +122,7 @@ class CegqiOutputInstStrategy : public CegqiOutput {
public:
CegqiOutputInstStrategy( InstStrategyCegqi * out ) : d_out( out ){}
InstStrategyCegqi * d_out;
- bool addInstantiation( std::vector< Node >& subs );
+ bool doAddInstantiation( std::vector< Node >& subs );
bool isEligibleForInstantiation( Node n );
bool addLemma( Node lem );
};
@@ -141,7 +143,7 @@ public:
InstStrategyCegqi( QuantifiersEngine * qe );
~InstStrategyCegqi() throw();
- bool addInstantiation( std::vector< Node >& subs );
+ bool doAddInstantiation( std::vector< Node >& subs );
bool isEligibleForInstantiation( Node n );
bool addLemma( Node lem );
/** identify */
diff --git a/src/theory/quantifiers/inst_strategy_e_matching.cpp b/src/theory/quantifiers/inst_strategy_e_matching.cpp
index 299eb51fd..630880690 100644
--- a/src/theory/quantifiers/inst_strategy_e_matching.cpp
+++ b/src/theory/quantifiers/inst_strategy_e_matching.cpp
@@ -1,20 +1,18 @@
/********************* */
/*! \file inst_strategy_e_matching.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of e matching instantiation strategies
**/
#include "theory/quantifiers/inst_strategy_e_matching.h"
-
-#include "options/quantifiers_options.h"
#include "theory/quantifiers/inst_match_generator.h"
#include "theory/quantifiers/relevant_domain.h"
#include "theory/quantifiers/term_database.h"
@@ -51,15 +49,18 @@ struct sortQuantifiersForSymbol {
struct sortTriggers {
bool operator() (Node i, Node j) {
- if( Trigger::isAtomicTrigger( i ) ){
- return i<j || !Trigger::isAtomicTrigger( j );
+ int wi = Trigger::getTriggerWeight( i );
+ int wj = Trigger::getTriggerWeight( j );
+ if( wi==wj ){
+ return i<j;
}else{
- return i<j && !Trigger::isAtomicTrigger( j );
+ return wi<wj;
}
}
};
void InstStrategyUserPatterns::processResetInstantiationRound( Theory::Effort effort ){
+ Trace("inst-alg-debug") << "reset user triggers" << std::endl;
//reset triggers
for( std::map< Node, std::vector< Trigger* > >::iterator it = d_user_gen.begin(); it != d_user_gen.end(); ++it ){
for( unsigned i=0; i<it->second.size(); i++ ){
@@ -67,6 +68,7 @@ void InstStrategyUserPatterns::processResetInstantiationRound( Theory::Effort ef
it->second[i]->reset( Node::null() );
}
}
+ Trace("inst-alg-debug") << "done reset user triggers" << std::endl;
}
int InstStrategyUserPatterns::process( Node f, Theory::Effort effort, int e ){
@@ -83,7 +85,7 @@ int InstStrategyUserPatterns::process( Node f, Theory::Effort effort, int e ){
if( d_quantEngine->getInstUserPatMode()==USER_PAT_MODE_RESORT ){
int matchOption = 0;
for( unsigned i=0; i<d_user_gen_wait[f].size(); i++ ){
- Trigger * t = Trigger::mkTrigger( d_quantEngine, f, d_user_gen_wait[f][i], matchOption, true, Trigger::TR_RETURN_NULL, options::smartTriggers() );
+ Trigger * t = Trigger::mkTrigger( d_quantEngine, f, d_user_gen_wait[f][i], matchOption, true, Trigger::TR_RETURN_NULL );
if( t ){
d_user_gen[f].push_back( t );
}
@@ -104,7 +106,9 @@ int InstStrategyUserPatterns::process( Node f, Theory::Effort effort, int e ){
if( d_user_gen[f][i]->isMultiTrigger() ){
d_quantEngine->d_statistics.d_multi_trigger_instantiations += numInst;
}
- //d_quantEngine->d_hasInstantiated[f] = true;
+ if( d_quantEngine->inConflict() ){
+ break;
+ }
}
}
}
@@ -118,11 +122,13 @@ void InstStrategyUserPatterns::addUserPattern( Node q, Node pat ){
bool usable = true;
std::vector< Node > nodes;
for( unsigned i=0; i<pat.getNumChildren(); i++ ){
- nodes.push_back( pat[i] );
- if( pat[i].getKind()!=INST_CONSTANT && !Trigger::isUsableTrigger( pat[i], q ) ){
+ Node pat_use = Trigger::getIsUsableTrigger( pat[i], q );
+ if( pat_use.isNull() ){
Trace("trigger-warn") << "User-provided trigger is not usable : " << pat << " because of " << pat[i] << std::endl;
usable = false;
break;
+ }else{
+ nodes.push_back( pat_use );
}
}
if( usable ){
@@ -132,19 +138,22 @@ void InstStrategyUserPatterns::addUserPattern( Node q, Node pat ){
if( d_quantEngine->getInstUserPatMode()==USER_PAT_MODE_RESORT ){
d_user_gen_wait[q].push_back( nodes );
}else{
- d_user_gen[q].push_back( Trigger::mkTrigger( d_quantEngine, q, nodes, matchOption, true, Trigger::TR_MAKE_NEW, options::smartTriggers() ) );
+ Trigger * t = Trigger::mkTrigger( d_quantEngine, q, nodes, matchOption, true, Trigger::TR_MAKE_NEW );
+ if( t ){
+ d_user_gen[q].push_back( t );
+ }else{
+ Trace("trigger-warn") << "Failed to construct trigger : " << pat << " due to variable mismatch" << std::endl;
+ }
}
}
}
InstStrategyAutoGenTriggers::InstStrategyAutoGenTriggers( QuantifiersEngine* qe ) : InstStrategy( qe ){
//how to select trigger terms
- if( options::triggerSelMode()==TRIGGER_SEL_MIN ){
- d_tr_strategy = Trigger::TS_MIN_TRIGGER;
- }else if( options::triggerSelMode()==TRIGGER_SEL_MAX ){
- d_tr_strategy = Trigger::TS_MAX_TRIGGER;
+ if( options::triggerSelMode()==quantifiers::TRIGGER_SEL_DEFAULT ){
+ d_tr_strategy = quantifiers::TRIGGER_SEL_MIN;
}else{
- d_tr_strategy = Trigger::TS_ALL;
+ d_tr_strategy = options::triggerSelMode();
}
//whether to select new triggers during the search
if( options::incrementTriggers() ){
@@ -156,6 +165,7 @@ InstStrategyAutoGenTriggers::InstStrategyAutoGenTriggers( QuantifiersEngine* qe
}
void InstStrategyAutoGenTriggers::processResetInstantiationRound( Theory::Effort effort ){
+ Trace("inst-alg-debug") << "reset auto-gen triggers" << std::endl;
//reset triggers
for( unsigned r=0; r<2; r++ ){
for( std::map< Node, std::map< Trigger*, bool > >::iterator it = d_auto_gen_trigger[r].begin(); it != d_auto_gen_trigger[r].end(); ++it ){
@@ -166,6 +176,7 @@ void InstStrategyAutoGenTriggers::processResetInstantiationRound( Theory::Effort
}
}
d_processed_trigger.clear();
+ Trace("inst-alg-debug") << "done reset auto-gen triggers" << std::endl;
}
int InstStrategyAutoGenTriggers::process( Node f, Theory::Effort effort, int e ){
@@ -220,11 +231,13 @@ int InstStrategyAutoGenTriggers::process( Node f, Theory::Effort effort, int e )
if( r==1 ){
d_quantEngine->d_statistics.d_multi_trigger_instantiations += numInst;
}
- //d_quantEngine->d_hasInstantiated[f] = true;
+ if( d_quantEngine->inConflict() ){
+ break;
+ }
}
}
}
- if( hasInst && options::multiTriggerPriority() ){
+ if( d_quantEngine->inConflict() || ( hasInst && options::multiTriggerPriority() ) ){
break;
}
}
@@ -237,67 +250,102 @@ int InstStrategyAutoGenTriggers::process( Node f, Theory::Effort effort, int e )
}
void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
- Trace("auto-gen-trigger-debug") << "Generate triggers for " << f << std::endl;
+ Trace("auto-gen-trigger-debug") << "Generate triggers for " << f << ", #var=" << f[0].getNumChildren() << "..." << std::endl;
if( d_patTerms[0].find( f )==d_patTerms[0].end() ){
//determine all possible pattern terms based on trigger term selection strategy d_tr_strategy
d_patTerms[0][f].clear();
d_patTerms[1][f].clear();
bool ntrivTriggers = options::relationalTriggers();
std::vector< Node > patTermsF;
+ std::map< Node, inst::TriggerTermInfo > tinfo;
//well-defined function: can assume LHS is only trigger
if( options::quantFunWellDefined() ){
Node hd = TermDb::getFunDefHead( f );
if( !hd.isNull() ){
hd = d_quantEngine->getTermDatabase()->getInstConstantNode( hd, f );
patTermsF.push_back( hd );
+ tinfo[hd].init( f, hd );
}
}
//otherwise, use algorithm for collecting pattern terms
if( patTermsF.empty() ){
Node bd = d_quantEngine->getTermDatabase()->getInstConstantBody( f );
- Trigger::collectPatTerms( d_quantEngine, f, bd, patTermsF, d_tr_strategy, d_user_no_gen[f], true );
- Trace("auto-gen-trigger-debug") << "Collected pat terms for " << bd << ", no-patterns : " << d_user_no_gen[f].size() << std::endl;
- Trace("auto-gen-trigger-debug") << " ";
- for( int i=0; i<(int)patTermsF.size(); i++ ){
- Trace("auto-gen-trigger-debug") << patTermsF[i] << " ";
- }
- Trace("auto-gen-trigger-debug") << std::endl;
+ Trigger::collectPatTerms( f, bd, patTermsF, d_tr_strategy, d_user_no_gen[f], tinfo, true );
if( ntrivTriggers ){
sortTriggers st;
std::sort( patTermsF.begin(), patTermsF.end(), st );
}
+ if( Trace.isOn("auto-gen-trigger-debug") ){
+ Trace("auto-gen-trigger-debug") << "Collected pat terms for " << bd << ", no-patterns : " << d_user_no_gen[f].size() << std::endl;
+ for( unsigned i=0; i<patTermsF.size(); i++ ){
+ Assert( tinfo.find( patTermsF[i] )!=tinfo.end() );
+ Trace("auto-gen-trigger-debug") << " " << patTermsF[i];
+ Trace("auto-gen-trigger-debug") << " info[" << tinfo[patTermsF[i]].d_reqPol << ", " << tinfo[patTermsF[i]].d_reqPolEq << ", " << tinfo[patTermsF[i]].d_fv.size() << "]" << std::endl;
+ }
+ Trace("auto-gen-trigger-debug") << std::endl;
+ }
}
- //sort into single/multi triggers
- std::map< Node, std::vector< Node > > varContains;
+ //sort into single/multi triggers, calculate which terms should not be considered
std::map< Node, bool > vcMap;
std::map< Node, bool > rmPatTermsF;
+ int last_weight = -1;
for( unsigned i=0; i<patTermsF.size(); i++ ){
- d_quantEngine->getTermDatabase()->getVarContainsNode( f, patTermsF[i], varContains[ patTermsF[i] ] );
+ Assert( patTermsF[i].getKind()!=NOT );
bool newVar = false;
- for( unsigned j=0; j<varContains[ patTermsF[i] ].size(); j++ ){
- if( vcMap.find( varContains[ patTermsF[i] ][j] )==vcMap.end() ){
- vcMap[varContains[ patTermsF[i] ][j]] = true;
+ for( unsigned j=0; j<tinfo[ patTermsF[i] ].d_fv.size(); j++ ){
+ if( vcMap.find( tinfo[ patTermsF[i] ].d_fv[j] )==vcMap.end() ){
+ vcMap[tinfo[ patTermsF[i] ].d_fv[j]] = true;
newVar = true;
}
}
- if( ntrivTriggers && !newVar && !Trigger::isAtomicTrigger( patTermsF[i] ) ){
- Trace("auto-gen-trigger-debug") << "Exclude expendible non-trivial trigger : " << patTermsF[i] << std::endl;
+ int curr_w = Trigger::getTriggerWeight( patTermsF[i] );
+ if( ntrivTriggers && !newVar && last_weight!=-1 && curr_w>last_weight ){
+ Trace("auto-gen-trigger-debug") << "...exclude expendible non-trivial trigger : " << patTermsF[i] << std::endl;
rmPatTermsF[patTermsF[i]] = true;
+ }else{
+ last_weight = curr_w;
}
}
- for( std::map< Node, std::vector< Node > >::iterator it = varContains.begin(); it != varContains.end(); ++it ){
- if( rmPatTermsF.find( it->first )==rmPatTermsF.end() ){
- if( it->second.size()==f[0].getNumChildren() && ( options::pureThTriggers() || !Trigger::isPureTheoryTrigger( it->first ) ) ){
- d_patTerms[0][f].push_back( it->first );
- d_is_single_trigger[ it->first ] = true;
+ for( unsigned i=0; i<patTermsF.size(); i++ ){
+ Node pat = patTermsF[i];
+ if( rmPatTermsF.find( pat )==rmPatTermsF.end() ){
+ Trace("auto-gen-trigger-debug") << "...processing pattern " << pat << std::endl;
+ //process the pattern: if it has a required polarity, consider it
+ Assert( tinfo.find( pat )!=tinfo.end() );
+ int rpol = tinfo[pat].d_reqPol;
+ Node rpoleq = tinfo[pat].d_reqPolEq;
+ unsigned num_fv = tinfo[pat].d_fv.size();
+ Trace("auto-gen-trigger-debug") << "...required polarity for " << pat << " is " << rpol << ", eq=" << rpoleq << std::endl;
+ if( rpol!=0 ){
+ if( Trigger::isRelationalTrigger( pat ) ){
+ pat = rpol==-1 ? pat.negate() : pat;
+ }else{
+ Assert( Trigger::isAtomicTrigger( pat ) );
+ if( pat.getType().isBoolean() && rpoleq.isNull() ){
+ pat = NodeManager::currentNM()->mkNode( IFF, pat, NodeManager::currentNM()->mkConst( rpol==-1 ) ).negate();
+ }else{
+ Assert( !rpoleq.isNull() );
+ if( rpol==-1 ){
+ //all equivalence classes except rpoleq
+ pat = NodeManager::currentNM()->mkNode( EQUAL, pat, rpoleq ).negate();
+ }else if( rpol==1 ){
+ //all equivalence classes that are not disequal to rpoleq TODO
+ }
+ }
+ }
+ Trace("auto-gen-trigger-debug") << "...got : " << pat << std::endl;
}else{
- d_patTerms[1][f].push_back( it->first );
- d_is_single_trigger[ it->first ] = false;
+ if( Trigger::isRelationalTrigger( pat ) ){
+ //consider both polarities
+ addPatternToPool( f, pat.negate(), num_fv );
+ }
}
+ addPatternToPool( f, pat, num_fv );
}
}
+ //tinfo not used below this point
d_made_multi_trigger[f] = false;
- Trace("auto-gen-trigger") << "Single triggers for " << f << " : " << std::endl;
+ Trace("auto-gen-trigger") << "Single trigger pool for " << f << " : " << std::endl;
for( unsigned i=0; i<d_patTerms[0][f].size(); i++ ){
Trace("auto-gen-trigger") << " " << d_patTerms[0][f][i] << std::endl;
}
@@ -327,7 +375,7 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
//sort based on # occurrences (this will cause Trigger to select rarer symbols)
std::sort( patTerms.begin(), patTerms.end(), sqfs );
Debug("relevant-trigger") << "Terms based on relevance: " << std::endl;
- for( int i=0; i<(int)patTerms.size(); i++ ){
+ for( unsigned i=0; i<patTerms.size(); i++ ){
Debug("relevant-trigger") << " " << patTerms[i] << " (";
Debug("relevant-trigger") << d_quantEngine->getQuantifierRelevance()->getNumQuantifiersForSymbol( patTerms[i].getOperator() ) << ")" << std::endl;
}
@@ -336,7 +384,7 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
int matchOption = 0;
Trigger* tr = NULL;
if( d_is_single_trigger[ patTerms[0] ] ){
- tr = Trigger::mkTrigger( d_quantEngine, f, patTerms[0], matchOption, false, Trigger::TR_RETURN_NULL, options::smartTriggers() );
+ tr = Trigger::mkTrigger( d_quantEngine, f, patTerms[0], matchOption, false, Trigger::TR_RETURN_NULL );
d_single_trigger_gen[ patTerms[0] ] = true;
}else{
//only generate multi trigger if option set, or if no single triggers exist
@@ -354,7 +402,7 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
d_made_multi_trigger[f] = true;
}
//will possibly want to get an old trigger
- tr = Trigger::mkTrigger( d_quantEngine, f, patTerms, matchOption, false, Trigger::TR_GET_OLD, options::smartTriggers() );
+ tr = Trigger::mkTrigger( d_quantEngine, f, patTerms, matchOption, false, Trigger::TR_GET_OLD );
}
if( tr ){
unsigned tindex;
@@ -390,7 +438,7 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
if( !options::relevantTriggers() ||
d_quantEngine->getQuantifierRelevance()->getNumQuantifiersForSymbol( patTerms[index].getOperator() )<=nqfs_curr ){
d_single_trigger_gen[ patTerms[index] ] = true;
- Trigger* tr2 = Trigger::mkTrigger( d_quantEngine, f, patTerms[index], matchOption, false, Trigger::TR_RETURN_NULL, options::smartTriggers() );
+ Trigger* tr2 = Trigger::mkTrigger( d_quantEngine, f, patTerms[index], matchOption, false, Trigger::TR_RETURN_NULL );
if( tr2 ){
//Notice() << "Add additional trigger " << patTerms[index] << std::endl;
tr2->resetInstantiationRound();
@@ -409,6 +457,16 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
}
}
+void InstStrategyAutoGenTriggers::addPatternToPool( Node q, Node pat, unsigned num_fv ) {
+ if( num_fv==q[0].getNumChildren() && ( options::pureThTriggers() || !Trigger::isPureTheoryTrigger( pat ) ) ){
+ d_patTerms[0][q].push_back( pat );
+ d_is_single_trigger[ pat ] = true;
+ }else{
+ d_patTerms[1][q].push_back( pat );
+ d_is_single_trigger[ pat ] = false;
+ }
+}
+
bool InstStrategyAutoGenTriggers::hasUserPatterns( Node q ) {
if( q.getNumChildren()==3 ){
std::map< Node, bool >::iterator it = d_hasUserPatterns.find( q );
@@ -462,7 +520,7 @@ bool InstStrategyLocalTheoryExt::isLocalTheoryExt( Node f ) {
}
Trace("local-t-ext") << std::endl;
int matchOption = 0;
- Trigger * tr = Trigger::mkTrigger( d_quantEngine, f, patTerms, matchOption, true, Trigger::TR_GET_OLD, options::smartTriggers() );
+ Trigger * tr = Trigger::mkTrigger( d_quantEngine, f, patTerms, matchOption, true, Trigger::TR_GET_OLD );
d_lte_trigger[f] = tr;
}else{
Trace("local-t-ext") << "No local theory extensions trigger for " << f << "." << std::endl;
@@ -515,12 +573,15 @@ void FullSaturation::check( Theory::Effort e, unsigned quant_e ) {
Trace("fs-engine") << "---Full Saturation Round, effort = " << e << "---" << std::endl;
}
int addedLemmas = 0;
- for( int i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
- Node q = d_quantEngine->getModel()->getAssertedQuantifier( i );
+ for( unsigned i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+ Node q = d_quantEngine->getModel()->getAssertedQuantifier( i, true );
if( d_quantEngine->hasOwnership( q, this ) && d_quantEngine->getModel()->isQuantifierActive( q ) ){
if( process( q, fullEffort ) ){
//added lemma
addedLemmas++;
+ if( d_quantEngine->inConflict() ){
+ break;
+ }
}
}
}
@@ -538,18 +599,6 @@ bool FullSaturation::process( Node f, bool fullEffort ){
unsigned rstart = options::fullSaturateQuantRd() ? 0 : 1;
unsigned rend = fullEffort ? 1 : rstart;
for( unsigned r=rstart; r<=rend; r++ ){
- /*
- //complete guess
- if( d_guessed.find( f )==d_guessed.end() ){
- Trace("inst-alg") << "-> Guess instantiate " << f << "..." << std::endl;
- d_guessed[f] = true;
- InstMatch m( f );
- if( d_quantEngine->addInstantiation( f, m ) ){
- ++(d_quantEngine->d_statistics.d_instantiations_guess);
- return true;
- }
- }
- */
if( rd || r>0 ){
if( r==0 ){
Trace("inst-alg") << "-> Relevant domain instantiate " << f << "..." << std::endl;
@@ -566,7 +615,7 @@ bool FullSaturation::process( Node f, bool fullEffort ){
if( r==0 ){
ts = rd->getRDomain( f, i )->d_terms.size();
}else{
- ts = d_quantEngine->getTermDatabase()->d_type_map[f[0][i].getType()].size();
+ ts = d_quantEngine->getTermDatabase()->getNumTypeGroundTerms( f[0][i].getType() );
}
max_zero.push_back( fullEffort && ts==0 );
ts = ( fullEffort && ts==0 ) ? 1 : ts;
@@ -582,6 +631,11 @@ bool FullSaturation::process( Node f, bool fullEffort ){
}
}
if( !has_zero ){
+ std::vector< TypeNode > ftypes;
+ for( unsigned i=0; i<f[0].getNumChildren(); i++ ){
+ ftypes.push_back( f[0][i].getType() );
+ }
+
Trace("inst-alg-rd") << "Will do " << final_max_i << " stages of instantiation." << std::endl;
unsigned max_i = 0;
bool success;
@@ -599,7 +653,7 @@ bool FullSaturation::process( Node f, bool fullEffort ){
if( options::cbqi() && r==1 && !max_zero[index] ){
//skip inst constant nodes
while( nv<maxs[index] && nv<=max_i &&
- quantifiers::TermDb::hasInstConstAttr( d_quantEngine->getTermDatabase()->d_type_map[f[0][index].getType()][nv] ) ){
+ quantifiers::TermDb::hasInstConstAttr( d_quantEngine->getTermDatabase()->getTypeGroundTerm( ftypes[index], nv ) ) ){
nv++;
}
}
@@ -625,13 +679,16 @@ bool FullSaturation::process( Node f, bool fullEffort ){
if( max_zero[i] ){
//no terms available, will report incomplete instantiation
terms.push_back( Node::null() );
+ Trace("inst-alg-rd") << " null" << std::endl;
}else if( r==0 ){
terms.push_back( rd->getRDomain( f, i )->d_terms[childIndex[i]] );
+ Trace("inst-alg-rd") << " " << rd->getRDomain( f, i )->d_terms[childIndex[i]] << std::endl;
}else{
- terms.push_back( d_quantEngine->getTermDatabase()->d_type_map[f[0][i].getType()][childIndex[i]] );
+ terms.push_back( d_quantEngine->getTermDatabase()->getTypeGroundTerm( ftypes[i], childIndex[i] ) );
+ Trace("inst-alg-rd") << " " << d_quantEngine->getTermDatabase()->getTypeGroundTerm( ftypes[i], childIndex[i] ) << std::endl;
}
}
- if( d_quantEngine->addInstantiation( f, terms, false ) ){
+ if( d_quantEngine->addInstantiation( f, terms ) ){
Trace("inst-alg-rd") << "Success!" << std::endl;
++(d_quantEngine->d_statistics.d_instantiations_guess);
return true;
diff --git a/src/theory/quantifiers/inst_strategy_e_matching.h b/src/theory/quantifiers/inst_strategy_e_matching.h
index 4e7afad5d..028f24b27 100644
--- a/src/theory/quantifiers/inst_strategy_e_matching.h
+++ b/src/theory/quantifiers/inst_strategy_e_matching.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file inst_strategy_e_matching.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief E matching instantiation strategies
**/
@@ -23,6 +23,7 @@
#include "theory/quantifiers/trigger.h"
#include "theory/quantifiers_engine.h"
#include "util/statistics_registry.h"
+#include "options/quantifiers_options.h"
namespace CVC4 {
namespace theory {
@@ -64,7 +65,7 @@ public:
};
private:
/** trigger generation strategy */
- int d_tr_strategy;
+ TriggerSelMode d_tr_strategy;
/** regeneration */
bool d_regenerate;
int d_regenerate_frequency;
@@ -73,6 +74,8 @@ private:
std::map< Node, int > d_counter;
/** single, multi triggers for each quantifier */
std::map< Node, std::vector< Node > > d_patTerms[2];
+ std::map< Node, std::map< Node, bool > > d_patReqPol;
+ /** information about triggers */
std::map< Node, bool > d_is_single_trigger;
std::map< Node, bool > d_single_trigger_gen;
std::map< Node, bool > d_made_multi_trigger;
@@ -86,6 +89,7 @@ private:
int process( Node q, Theory::Effort effort, int e );
/** generate triggers */
void generateTriggers( Node q );
+ void addPatternToPool( Node q, Node pat, unsigned num_fv );
//bool addTrigger( inst::Trigger * tr, Node f, unsigned r );
/** has user patterns */
bool hasUserPatterns( Node q );
diff --git a/src/theory/quantifiers/instantiation_engine.cpp b/src/theory/quantifiers/instantiation_engine.cpp
index 88a67e3c8..955dc5d86 100644
--- a/src/theory/quantifiers/instantiation_engine.cpp
+++ b/src/theory/quantifiers/instantiation_engine.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file instantiation_engine.cpp
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): Tim King
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of instantiation engine class
**/
@@ -60,7 +60,7 @@ void InstantiationEngine::presolve() {
}
}
-bool InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
+void InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
unsigned lastWaiting = d_quantEngine->getNumLemmasWaiting();
//iterate over an internal effort level e
int e = 0;
@@ -83,8 +83,10 @@ bool InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
InstStrategy* is = d_instStrategies[j];
Trace("inst-engine-debug") << "Do " << is->identify() << " " << e_use << std::endl;
int quantStatus = is->process( q, effort, e_use );
- Trace("inst-engine-debug") << " -> status is " << quantStatus << std::endl;
- if( quantStatus==InstStrategy::STATUS_UNFINISHED ){
+ Trace("inst-engine-debug") << " -> status is " << quantStatus << ", conflict=" << d_quantEngine->inConflict() << std::endl;
+ if( d_quantEngine->inConflict() ){
+ return;
+ }else if( quantStatus==InstStrategy::STATUS_UNFINISHED ){
finished = false;
}
}
@@ -96,13 +98,6 @@ bool InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
}
e++;
}
- //Notice() << "All instantiators finished, # added lemmas = " << (int)d_lemmas_waiting.size() << std::endl;
- if( !d_quantEngine->hasAddedLemma() ){
- return false;
- }else{
- Trace("inst-engine") << "Added lemmas = " << (int)(d_quantEngine->getNumLemmasWaiting()-lastWaiting) << std::endl;
- return true;
- }
}
bool InstantiationEngine::needsCheck( Theory::Effort e ){
@@ -128,8 +123,8 @@ void InstantiationEngine::check( Theory::Effort e, unsigned quant_e ){
//collect all active quantified formulas belonging to this
bool quantActive = false;
d_quants.clear();
- for( int i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
- Node q = d_quantEngine->getModel()->getAssertedQuantifier( i );
+ for( unsigned i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+ Node q = d_quantEngine->getModel()->getAssertedQuantifier( i, true );
if( d_quantEngine->hasOwnership( q, this ) && d_quantEngine->getModel()->isQuantifierActive( q ) ){
quantActive = true;
d_quants.push_back( q );
@@ -138,8 +133,18 @@ void InstantiationEngine::check( Theory::Effort e, unsigned quant_e ){
Trace("inst-engine-debug") << "InstEngine: check: # asserted quantifiers " << d_quants.size() << "/";
Trace("inst-engine-debug") << d_quantEngine->getModel()->getNumAssertedQuantifiers() << " " << quantActive << std::endl;
if( quantActive ){
- bool addedLemmas = doInstantiationRound( e );
- Trace("inst-engine-debug") << "Add lemmas = " << addedLemmas << std::endl;
+ unsigned lastWaiting = d_quantEngine->getNumLemmasWaiting();
+ doInstantiationRound( e );
+ if( d_quantEngine->inConflict() ){
+ Assert( d_quantEngine->getNumLemmasWaiting()>lastWaiting );
+ Trace("inst-engine") << "Conflict = " << d_quantEngine->getNumLemmasWaiting() << " / " << d_quantEngine->getNumLemmasAddedThisRound();
+ if( lastWaiting>0 ){
+ Trace("inst-engine") << " (prev " << lastWaiting << ")";
+ }
+ Trace("inst-engine") << std::endl;
+ }else if( d_quantEngine->hasAddedLemma() ){
+ Trace("inst-engine") << "Added lemmas = " << (d_quantEngine->getNumLemmasWaiting()-lastWaiting) << std::endl;
+ }
}else{
d_quants.clear();
}
@@ -165,6 +170,22 @@ bool InstantiationEngine::isIncomplete( Node q ) {
return true;
}
+void InstantiationEngine::preRegisterQuantifier( Node q ) {
+ if( options::strictTriggers() && q.getNumChildren()==3 ){
+ //if strict triggers, take ownership of this quantified formula
+ bool hasPat = false;
+ for( unsigned i=0; i<q[2].getNumChildren(); i++ ){
+ if( q[2][i].getKind()==INST_PATTERN || q[2][i].getKind()==INST_NO_PATTERN ){
+ hasPat = true;
+ break;
+ }
+ }
+ if( hasPat ){
+ d_quantEngine->setOwner( q, this, 1 );
+ }
+ }
+}
+
void InstantiationEngine::registerQuantifier( Node f ){
if( d_quantEngine->hasOwnership( f, this ) ){
//for( unsigned i=0; i<d_instStrategies.size(); ++i ){
diff --git a/src/theory/quantifiers/instantiation_engine.h b/src/theory/quantifiers/instantiation_engine.h
index bfa610369..d2b3740a1 100644
--- a/src/theory/quantifiers/instantiation_engine.h
+++ b/src/theory/quantifiers/instantiation_engine.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file instantiation_engine.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): Tim King
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Instantiation Engine classes
**/
@@ -70,7 +70,7 @@ private:
/** is the engine incomplete for this quantifier */
bool isIncomplete( Node q );
/** do instantiation round */
- bool doInstantiationRound( Theory::Effort effort );
+ void doInstantiationRound( Theory::Effort effort );
public:
InstantiationEngine( QuantifiersEngine* qe );
~InstantiationEngine();
@@ -79,6 +79,7 @@ public:
void reset_round( Theory::Effort e );
void check( Theory::Effort e, unsigned quant_e );
bool checkComplete();
+ void preRegisterQuantifier( Node q );
void registerQuantifier( Node q );
Node explain(TNode n){ return Node::null(); }
/** add user pattern */
diff --git a/src/theory/quantifiers/local_theory_ext.cpp b/src/theory/quantifiers/local_theory_ext.cpp
index 794032c87..ada28c084 100644
--- a/src/theory/quantifiers/local_theory_ext.cpp
+++ b/src/theory/quantifiers/local_theory_ext.cpp
@@ -1,13 +1,13 @@
/********************* */
-/*! \file quant_util.cpp
+/*! \file local_theory_ext.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of local theory ext utilities
**/
@@ -31,69 +31,69 @@ QuantifiersModule( qe ), d_wasInvoked( false ), d_needsCheck( false ){
}
/** add quantifier */
-bool LtePartialInst::addQuantifier( Node q ) {
- if( d_do_inst.find( q )!=d_do_inst.end() ){
- if( d_do_inst[q] ){
- d_lte_asserts.push_back( q );
- return true;
+void LtePartialInst::preRegisterQuantifier( Node q ) {
+ if( !q.getAttribute(LtePartialInstAttribute()) ){
+ if( d_do_inst.find( q )!=d_do_inst.end() ){
+ if( d_do_inst[q] ){
+ d_lte_asserts.push_back( q );
+ d_quantEngine->setOwner( q, this );
+ }
}else{
- return false;
- }
- }else{
- d_vars[q].clear();
- d_pat_var_order[q].clear();
- //check if this quantified formula is eligible for partial instantiation
- std::map< Node, bool > vars;
- for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
- vars[q[0][i]] = false;
- }
- getEligibleInstVars( q[1], vars );
-
- //instantiate only if we would force ground instances
- std::map< Node, int > var_order;
- bool doInst = true;
- for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
- if( vars[q[0][i]] ){
- d_vars[q].push_back( q[0][i] );
- var_order[q[0][i]] = i;
- }else{
- Trace("lte-partial-inst-debug") << "...do not consider, variable " << q[0][i] << " was not found in correct position in body." << std::endl;
- doInst = false;
- break;
+ d_vars[q].clear();
+ d_pat_var_order[q].clear();
+ //check if this quantified formula is eligible for partial instantiation
+ std::map< Node, bool > vars;
+ for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
+ vars[q[0][i]] = false;
}
- }
- if( doInst ){
- //also needs patterns
- if( q.getNumChildren()==3 && q[2].getNumChildren()==1 ){
- for( unsigned i=0; i<q[2][0].getNumChildren(); i++ ){
- Node pat = q[2][0][i];
- if( pat.getKind()==APPLY_UF ){
- for( unsigned j=0; j<pat.getNumChildren(); j++ ){
- if( !addVariableToPatternList( pat[j], d_pat_var_order[q], var_order ) ){
- doInst = false;
+ getEligibleInstVars( q[1], vars );
+
+ //instantiate only if we would force ground instances
+ std::map< Node, int > var_order;
+ bool doInst = true;
+ for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
+ if( vars[q[0][i]] ){
+ d_vars[q].push_back( q[0][i] );
+ var_order[q[0][i]] = i;
+ }else{
+ Trace("lte-partial-inst-debug") << "...do not consider, variable " << q[0][i] << " was not found in correct position in body." << std::endl;
+ doInst = false;
+ break;
+ }
+ }
+ if( doInst ){
+ //also needs patterns
+ if( q.getNumChildren()==3 && q[2].getNumChildren()==1 ){
+ for( unsigned i=0; i<q[2][0].getNumChildren(); i++ ){
+ Node pat = q[2][0][i];
+ if( pat.getKind()==APPLY_UF ){
+ for( unsigned j=0; j<pat.getNumChildren(); j++ ){
+ if( !addVariableToPatternList( pat[j], d_pat_var_order[q], var_order ) ){
+ doInst = false;
+ }
}
+ }else if( !addVariableToPatternList( pat, d_pat_var_order[q], var_order ) ){
+ doInst = false;
+ }
+ if( !doInst ){
+ Trace("lte-partial-inst-debug") << "...do not consider, cannot resolve pattern : " << pat << std::endl;
+ break;
}
- }else if( !addVariableToPatternList( pat, d_pat_var_order[q], var_order ) ){
- doInst = false;
- }
- if( !doInst ){
- Trace("lte-partial-inst-debug") << "...do not consider, cannot resolve pattern : " << pat << std::endl;
- break;
}
+ }else{
+ Trace("lte-partial-inst-debug") << "...do not consider (must have exactly one pattern)." << std::endl;
}
- }else{
- Trace("lte-partial-inst-debug") << "...do not consider (must have exactly one pattern)." << std::endl;
+ }
+
+
+ Trace("lte-partial-inst") << "LTE: ...will " << ( doInst ? "" : "not ") << "instantiate " << q << std::endl;
+ d_do_inst[q] = doInst;
+ if( doInst ){
+ d_lte_asserts.push_back( q );
+ d_needsCheck = true;
+ d_quantEngine->setOwner( q, this );
}
}
-
-
- Trace("lte-partial-inst") << "LTE: ...will " << ( doInst ? "" : "not ") << "instantiate " << q << std::endl;
- d_do_inst[q] = doInst;
- if( doInst ){
- d_lte_asserts.push_back( q );
- d_needsCheck = true;
- }
- return doInst;
}
}
@@ -188,7 +188,6 @@ void LtePartialInst::getInstantiations( std::vector< Node >& lemmas ) {
Assert( !conj.empty() );
lemmas.push_back( NodeManager::currentNM()->mkNode( OR, q.negate(), conj.size()==1 ? conj[0] : NodeManager::currentNM()->mkNode( AND, conj ) ) );
d_wasInvoked = true;
- d_quantEngine->getModel()->markQuantifierReduced( q );
}
}
}
diff --git a/src/theory/quantifiers/local_theory_ext.h b/src/theory/quantifiers/local_theory_ext.h
index 6e2ee34af..94abf3c90 100644
--- a/src/theory/quantifiers/local_theory_ext.h
+++ b/src/theory/quantifiers/local_theory_ext.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file local_theory_ext.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief local theory extensions util
**/
@@ -55,8 +55,8 @@ private:
bool addVariableToPatternList( Node v, std::vector< int >& pat_var_order, std::map< Node, int >& var_order );
public:
LtePartialInst( QuantifiersEngine * qe, context::Context* c );
- /** add quantifier : special form of registration */
- bool addQuantifier( Node q );
+ /** determine whether this quantified formula will be reduced */
+ void preRegisterQuantifier( Node q );
/** was invoked */
bool wasInvoked() { return d_wasInvoked; }
diff --git a/src/theory/quantifiers/macros.cpp b/src/theory/quantifiers/macros.cpp
index a5e3dada8..582599680 100644
--- a/src/theory/quantifiers/macros.cpp
+++ b/src/theory/quantifiers/macros.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file macros.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): Kshitij Bansal
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Sort inference module
**
@@ -39,9 +39,15 @@ bool QuantifierMacros::simplify( std::vector< Node >& assertions, bool doRewrite
d_ground_macros = (r==0);
Trace("macros") << "Find macros, ground=" << d_ground_macros << "..." << std::endl;
//first, collect macro definitions
- for( int i=0; i<(int)assertions.size(); i++ ){
+ std::vector< Node > macro_assertions;
+ for( unsigned i=0; i<assertions.size(); i++ ){
Trace("macros-debug") << " process assertion " << assertions[i] << std::endl;
if( processAssertion( assertions[i] ) ){
+ PROOF(
+ if( std::find( macro_assertions.begin(), macro_assertions.end(), assertions[i] )==macro_assertions.end() ){
+ macro_assertions.push_back( assertions[i] );
+ }
+ );
//process this assertion again
i--;
}
@@ -56,7 +62,17 @@ bool QuantifierMacros::simplify( std::vector< Node >& assertions, bool doRewrite
if( curr!=assertions[i] ){
curr = Rewriter::rewrite( curr );
Trace("macros-rewrite") << "Rewrite " << assertions[i] << " to " << curr << std::endl;
- PROOF( ProofManager::currentPM()->addDependence(curr, assertions[i]); );
+ //for now, it is dependent upon all assertions involving macros, this is an over-approximation.
+ //a more fine-grained unsat core computation would require caching dependencies for each subterm of the formula,
+ // which is expensive.
+ PROOF(
+ ProofManager::currentPM()->addDependence(curr, assertions[i]);
+ for( unsigned j=0; j<macro_assertions.size(); j++ ){
+ if( macro_assertions[j]!=assertions[i] ){
+ ProofManager::currentPM()->addDependence(curr,macro_assertions[j]);
+ }
+ }
+ );
assertions[i] = curr;
retVal = true;
}
@@ -68,7 +84,7 @@ bool QuantifierMacros::simplify( std::vector< Node >& assertions, bool doRewrite
}
}
if( Trace.isOn("macros-warn") ){
- for( int i=0; i<(int)assertions.size(); i++ ){
+ for( unsigned i=0; i<assertions.size(); i++ ){
debugMacroDefinition( assertions[i], assertions[i] );
}
}
@@ -137,7 +153,7 @@ bool QuantifierMacros::isGroundUfTerm( Node f, Node n ) {
d_qe->getTermDatabase()->getVarContainsNode( f, icn, var );
Trace("macros-debug2") << "Get trigger variables for " << icn << std::endl;
std::vector< Node > trigger_var;
- inst::Trigger::getTriggerVariables( d_qe, icn, f, trigger_var );
+ inst::Trigger::getTriggerVariables( icn, f, trigger_var );
Trace("macros-debug2") << "Done." << std::endl;
//only if all variables are also trigger variables
return trigger_var.size()>=var.size();
@@ -145,18 +161,24 @@ bool QuantifierMacros::isGroundUfTerm( Node f, Node n ) {
bool QuantifierMacros::isBoundVarApplyUf( Node n ) {
Assert( n.getKind()==APPLY_UF );
- TypeNode tn = n.getOperator().getType();
+ TypeNode tno = n.getOperator().getType();
+ std::map< Node, bool > vars;
for( unsigned i=0; i<n.getNumChildren(); i++ ){
if( n[i].getKind()!=BOUND_VARIABLE ){
return false;
}
- if( n[i].getType()!=tn[i] ){
+ if( n[i].getType()!=tno[i] ){
return false;
}
- for( unsigned j=0; j<i; j++ ){
- if( n[j]==n[i] ){
- return false;
- }
+ if( !tno[i].isSort() && !tno[i].isReal() && ( !tno[i].isDatatype() || tno[i].isParametricDatatype() ) &&
+ !tno[i].isBitVector() && !tno[i].isString() && !tno[i].isFloatingPoint() ){
+ //only non-parametric types are supported
+ return false;
+ }
+ if( vars.find( n[i] )==vars.end() ){
+ vars[n[i]] = true;
+ }else{
+ return false;
}
}
return true;
@@ -388,13 +410,33 @@ Node QuantifierMacros::simplify( Node n ){
Node op = n.getOperator();
std::map< Node, Node >::iterator it = d_macro_defs.find( op );
if( it!=d_macro_defs.end() && !it->second.isNull() ){
- //do substitution if necessary
- ret = it->second;
- std::map< Node, std::vector< Node > >::iterator itb = d_macro_basis.find( op );
- if( itb!=d_macro_basis.end() ){
- ret = ret.substitute( itb->second.begin(), itb->second.end(), children.begin(), children.end() );
+ //only apply if children are subtypes of arguments
+ bool success = true;
+ std::vector< Node > cond;
+ TypeNode tno = op.getType();
+ for( unsigned i=0; i<children.size(); i++ ){
+ if( !TermDb::getEnsureTypeCondition( children[i], tno[i], cond ) ){
+ //if this does fail, we are incomplete, since we are eliminating quantified formula corresponding to op,
+ // and not ensuring it applies to n when its types are correct.
+ //however, this should never fail: we never process types for which we cannot constuct conditions that ensure correct types, e.g. (is-int t).
+ Assert( false );
+ success = false;
+ break;
+ }
+ }
+ if( success ){
+ //do substitution if necessary
+ ret = it->second;
+ std::map< Node, std::vector< Node > >::iterator itb = d_macro_basis.find( op );
+ if( itb!=d_macro_basis.end() ){
+ ret = ret.substitute( itb->second.begin(), itb->second.end(), children.begin(), children.end() );
+ }
+ if( !cond.empty() ){
+ Node cc = cond.size()==1 ? cond[0] : NodeManager::currentNM()->mkNode( kind::AND, cond );
+ ret = NodeManager::currentNM()->mkNode( kind::ITE, cc, ret, n );
+ }
+ retSet = true;
}
- retSet = true;
}
}
if( !retSet && childChanged ){
diff --git a/src/theory/quantifiers/macros.h b/src/theory/quantifiers/macros.h
index 06e2d652a..39ec2f0a1 100644
--- a/src/theory/quantifiers/macros.h
+++ b/src/theory/quantifiers/macros.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file macros.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Pre-process step for detecting quantifier macro definitions
**/
diff --git a/src/theory/quantifiers/model_builder.cpp b/src/theory/quantifiers/model_builder.cpp
index 95b674cca..3ae36b1d4 100644
--- a/src/theory/quantifiers/model_builder.cpp
+++ b/src/theory/quantifiers/model_builder.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file model_builder.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): Kshitij Bansal, Morgan Deters
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of model builder class
**/
@@ -50,14 +50,14 @@ bool QModelBuilder::optUseModel() {
void QModelBuilder::debugModel( FirstOrderModel* fm ){
//debug the model: cycle through all instantiations for all quantifiers, report ones that are not true
- if( Trace.isOn("quant-model-warn") ){
- Trace("quant-model-warn") << "Testing quantifier instantiations..." << std::endl;
+ if( Trace.isOn("quant-check-model") ){
+ Trace("quant-check-model") << "Testing quantifier instantiations..." << std::endl;
int tests = 0;
int bad = 0;
- for( int i=0; i<fm->getNumAssertedQuantifiers(); i++ ){
+ for( unsigned i=0; i<fm->getNumAssertedQuantifiers(); i++ ){
Node f = fm->getAssertedQuantifier( i );
std::vector< Node > vars;
- for( int j=0; j<(int)f[0].getNumChildren(); j++ ){
+ for( unsigned j=0; j<f[0].getNumChildren(); j++ ){
vars.push_back( f[0][j] );
}
RepSetIterator riter( d_qe, &(fm->d_rep_set) );
@@ -65,26 +65,26 @@ void QModelBuilder::debugModel( FirstOrderModel* fm ){
while( !riter.isFinished() ){
tests++;
std::vector< Node > terms;
- for( int i=0; i<riter.getNumTerms(); i++ ){
- terms.push_back( riter.getTerm( i ) );
+ for( int k=0; k<riter.getNumTerms(); k++ ){
+ terms.push_back( riter.getTerm( k ) );
}
Node n = d_qe->getInstantiation( f, vars, terms );
Node val = fm->getValue( n );
if( val!=fm->d_true ){
- Trace("quant-model-warn") << "******* Instantiation " << n << " for " << std::endl;
- Trace("quant-model-warn") << " " << f << std::endl;
- Trace("quant-model-warn") << " Evaluates to " << val << std::endl;
+ Trace("quant-check-model") << "******* Instantiation " << n << " for " << std::endl;
+ Trace("quant-check-model") << " " << f << std::endl;
+ Trace("quant-check-model") << " Evaluates to " << val << std::endl;
bad++;
}
riter.increment();
}
- Trace("quant-model-warn") << "Tested " << tests << " instantiations";
+ Trace("quant-check-model") << "Tested " << tests << " instantiations";
if( bad>0 ){
- Trace("quant-model-warn") << ", " << bad << " failed" << std::endl;
+ Trace("quant-check-model") << ", " << bad << " failed" << std::endl;
}
- Trace("quant-model-warn") << "." << std::endl;
+ Trace("quant-check-model") << "." << std::endl;
}else{
- Trace("quant-model-warn") << "Warning: Could not test quantifier " << f << std::endl;
+ Trace("quant-check-model") << "Warning: Could not test quantifier " << f << std::endl;
}
}
}
@@ -149,17 +149,21 @@ void QModelBuilderIG::processBuildModel( TheoryModel* m, bool fullModel ) {
if( optUseModel() ){
Trace("model-engine-debug") << "Initializing " << fm->getNumAssertedQuantifiers() << " quantifiers..." << std::endl;
//check if any quantifiers are un-initialized
- for( int i=0; i<fm->getNumAssertedQuantifiers(); i++ ){
+ for( unsigned i=0; i<fm->getNumAssertedQuantifiers(); i++ ){
Node f = fm->getAssertedQuantifier( i );
if( isQuantifierActive( f ) ){
int lems = initializeQuantifier( f, f );
d_statistics.d_init_inst_gen_lemmas += lems;
d_addedLemmas += lems;
+ if( d_qe->inConflict() ){
+ break;
+ }
}
}
if( d_addedLemmas>0 ){
Trace("model-engine") << "Initialize, Added Lemmas = " << d_addedLemmas << std::endl;
}else{
+ Assert( !d_qe->inConflict() );
//initialize model
fm->initialize();
//analyze the functions
@@ -169,7 +173,7 @@ void QModelBuilderIG::processBuildModel( TheoryModel* m, bool fullModel ) {
Trace("model-engine-debug") << "Analyzing quantifiers..." << std::endl;
d_quant_sat.clear();
d_uf_prefs.clear();
- for( int i=0; i<fm->getNumAssertedQuantifiers(); i++ ){
+ for( unsigned i=0; i<fm->getNumAssertedQuantifiers(); i++ ){
Node f = fm->getAssertedQuantifier( i );
if( isQuantifierActive( f ) ){
analyzeQuantifier( fm, f );
@@ -186,7 +190,7 @@ void QModelBuilderIG::processBuildModel( TheoryModel* m, bool fullModel ) {
d_numQuantNoSelForm = 0;
//now, see if we know that any exceptions via InstGen exist
Trace("model-engine-debug") << "Perform InstGen techniques for quantifiers..." << std::endl;
- for( int i=0; i<fm->getNumAssertedQuantifiers(); i++ ){
+ for( unsigned i=0; i<fm->getNumAssertedQuantifiers(); i++ ){
Node f = fm->getAssertedQuantifier( i );
if( isQuantifierActive( f ) ){
int lems = doInstGen( fm, f );
@@ -202,7 +206,7 @@ void QModelBuilderIG::processBuildModel( TheoryModel* m, bool fullModel ) {
}else{
d_numQuantNoSelForm++;
}
- if( options::fmfInstGenOneQuantPerRound() && lems>0 ){
+ if( d_qe->inConflict() || ( options::fmfInstGenOneQuantPerRound() && lems>0 ) ){
break;
}
}else if( d_quant_sat.find( f )!=d_quant_sat.end() ){
@@ -276,7 +280,7 @@ int QModelBuilderIG::initializeQuantifier( Node f, Node fp ){
//try to add it
Trace("inst-fmf-init") << "Init: try to add match " << d_quant_basis_match[f] << std::endl;
//add model basis instantiation
- if( d_qe->addInstantiation( fp, d_quant_basis_match[f], false ) ){
+ if( d_qe->addInstantiation( fp, d_quant_basis_match[f] ) ){
d_quant_basis_match_added[f] = true;
return 1;
}else{
@@ -426,8 +430,11 @@ bool QModelBuilderIG::doExhaustiveInstantiation( FirstOrderModel * fm, Node f, i
}
Debug("fmf-model-eval") << "* Add instantiation " << m << std::endl;
//add as instantiation
- if( d_qe->addInstantiation( f, m ) ){
+ if( d_qe->addInstantiation( f, m, true ) ){
d_addedLemmas++;
+ if( d_qe->inConflict() ){
+ break;
+ }
//if the instantiation is show to be false, and we wish to skip multiple instantiations at once
if( eval==-1 ){
riter.increment2( depIndex );
@@ -660,7 +667,7 @@ int QModelBuilderDefault::doInstGen( FirstOrderModel* fm, Node f ){
//if applicable, try to add exceptions here
if( !tr_terms.empty() ){
//make a trigger for these terms, add instantiations
- inst::Trigger* tr = inst::Trigger::mkTrigger( d_qe, f, tr_terms, 0, true, inst::Trigger::TR_MAKE_NEW, options::smartTriggers() );
+ inst::Trigger* tr = inst::Trigger::mkTrigger( d_qe, f, tr_terms, 0, true, inst::Trigger::TR_MAKE_NEW );
//Notice() << "Trigger = " << (*tr) << std::endl;
tr->resetInstantiationRound();
tr->reset( Node::null() );
diff --git a/src/theory/quantifiers/model_builder.h b/src/theory/quantifiers/model_builder.h
index b45aa0ff0..906673903 100644
--- a/src/theory/quantifiers/model_builder.h
+++ b/src/theory/quantifiers/model_builder.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file model_builder.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Model Builder class
**/
diff --git a/src/theory/quantifiers/model_engine.cpp b/src/theory/quantifiers/model_engine.cpp
index 4b173c833..0bbca88eb 100644
--- a/src/theory/quantifiers/model_engine.cpp
+++ b/src/theory/quantifiers/model_engine.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file model_engine.cpp
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): Francois Bobot
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of model engine class
**/
@@ -62,6 +62,7 @@ void ModelEngine::reset_round( Theory::Effort e ) {
void ModelEngine::check( Theory::Effort e, unsigned quant_e ){
if( quant_e==QuantifiersEngine::QEFFORT_MODEL ){
+ Assert( !d_quantEngine->inConflict() );
int addedLemmas = 0;
FirstOrderModel* fm = d_quantEngine->getModel();
@@ -82,8 +83,10 @@ void ModelEngine::check( Theory::Effort e, unsigned quant_e ){
Trace("model-engine-debug") << "Check model..." << std::endl;
d_incomplete_check = false;
//print debug
- Trace("fmf-model-complete") << std::endl;
- debugPrint("fmf-model-complete");
+ if( Trace.isOn("fmf-model-complete") ){
+ Trace("fmf-model-complete") << std::endl;
+ debugPrint("fmf-model-complete");
+ }
//successfully built an acceptable model, now check it
addedLemmas += checkModel();
}else{
@@ -98,10 +101,10 @@ void ModelEngine::check( Theory::Effort e, unsigned quant_e ){
if( addedLemmas==0 ){
Trace("model-engine-debug") << "No lemmas added, incomplete = " << d_incomplete_check << std::endl;
//CVC4 will answer SAT or unknown
- Trace("fmf-consistent") << std::endl;
- debugPrint("fmf-consistent");
- }else{
- //otherwise, the search will continue
+ if( Trace.isOn("fmf-consistent") ){
+ Trace("fmf-consistent") << std::endl;
+ debugPrint("fmf-consistent");
+ }
}
}
}
@@ -178,49 +181,51 @@ int ModelEngine::checkModel(){
d_addedLemmas = 0;
d_totalLemmas = 0;
//for statistics
- for( int i=0; i<fm->getNumAssertedQuantifiers(); i++ ){
- Node f = fm->getAssertedQuantifier( i );
- int totalInst = 1;
- for( size_t i=0; i<f[0].getNumChildren(); i++ ){
- TypeNode tn = f[0][i].getType();
- if( fm->d_rep_set.hasType( tn ) ){
- totalInst = totalInst * (int)fm->d_rep_set.d_type_reps[ tn ].size();
+ if( Trace.isOn("model-engine") ){
+ for( unsigned i=0; i<fm->getNumAssertedQuantifiers(); i++ ){
+ Node f = fm->getAssertedQuantifier( i );
+ int totalInst = 1;
+ for( unsigned j=0; j<f[0].getNumChildren(); j++ ){
+ TypeNode tn = f[0][j].getType();
+ if( fm->d_rep_set.hasType( tn ) ){
+ totalInst = totalInst * (int)fm->d_rep_set.d_type_reps[ tn ].size();
+ }
}
+ d_totalLemmas += totalInst;
}
- d_totalLemmas += totalInst;
}
Trace("model-engine-debug") << "Do exhaustive instantiation..." << std::endl;
// FMC uses two sub-effort levels
int e_max = options::mbqiMode()==MBQI_FMC || options::mbqiMode()==MBQI_FMC_INTERVAL ? 2 : ( options::mbqiMode()==MBQI_TRUST ? 0 : 1 );
for( int e=0; e<e_max; e++) {
- if (d_addedLemmas==0) {
- for( int i=0; i<fm->getNumAssertedQuantifiers(); i++ ){
- Node f = fm->getAssertedQuantifier( i );
- Trace("fmf-exh-inst") << "-> Exhaustive instantiate " << f << ", effort = " << e << "..." << std::endl;
- //determine if we should check this quantifier
- if( considerQuantifiedFormula( f ) ){
- exhaustiveInstantiate( f, e );
- if( Trace.isOn("model-engine-warn") ){
- if( d_addedLemmas>10000 ){
- Debug("fmf-exit") << std::endl;
- debugPrint("fmf-exit");
- exit( 0 );
- }
- }
- if( optOneQuantPerRound() && d_addedLemmas>0 ){
- break;
- }
- }else{
- Trace("fmf-exh-inst") << "-> Inactive : " << f << std::endl;
+ for( unsigned i=0; i<fm->getNumAssertedQuantifiers(); i++ ){
+ Node f = fm->getAssertedQuantifier( i, true );
+ Trace("fmf-exh-inst") << "-> Exhaustive instantiate " << f << ", effort = " << e << "..." << std::endl;
+ //determine if we should check this quantifier
+ if( considerQuantifiedFormula( f ) ){
+ exhaustiveInstantiate( f, e );
+ if( d_quantEngine->inConflict() || ( optOneQuantPerRound() && d_addedLemmas>0 ) ){
+ break;
}
+ }else{
+ Trace("fmf-exh-inst") << "-> Inactive : " << f << std::endl;
}
}
+ if( d_addedLemmas>0 ){
+ break;
+ }else{
+ Assert( !d_quantEngine->inConflict() );
+ }
}
//print debug information
- Trace("model-engine") << "Added Lemmas = " << d_addedLemmas << " / " << d_triedLemmas << " / ";
- Trace("model-engine") << d_totalLemmas << std::endl;
+ if( d_quantEngine->inConflict() ){
+ Trace("model-engine") << "Conflict = " << d_quantEngine->getNumLemmasWaiting() << " / " << d_quantEngine->getNumLemmasAddedThisRound() << std::endl;
+ }else{
+ Trace("model-engine") << "Added Lemmas = " << d_addedLemmas << " / " << d_triedLemmas << " / ";
+ Trace("model-engine") << d_totalLemmas << std::endl;
+ }
return d_addedLemmas;
}
@@ -266,15 +271,17 @@ void ModelEngine::exhaustiveInstantiate( Node f, int effort ){
d_incomplete_check = d_incomplete_check || mb->d_incomplete_check;
d_statistics.d_mbqi_inst_lemmas += mb->d_addedLemmas;
}else{
- Trace("fmf-exh-inst-debug") << " Instantiation Constants: ";
- for( size_t i=0; i<f[0].getNumChildren(); i++ ){
- Trace("fmf-exh-inst-debug") << d_quantEngine->getTermDatabase()->getInstantiationConstant( f, i ) << " ";
+ if( Trace.isOn("fmf-exh-inst-debug") ){
+ Trace("fmf-exh-inst-debug") << " Instantiation Constants: ";
+ for( size_t i=0; i<f[0].getNumChildren(); i++ ){
+ Trace("fmf-exh-inst-debug") << d_quantEngine->getTermDatabase()->getInstantiationConstant( f, i ) << " ";
+ }
+ Trace("fmf-exh-inst-debug") << std::endl;
}
- Trace("fmf-exh-inst-debug") << std::endl;
//create a rep set iterator and iterate over the (relevant) domain of the quantifier
RepSetIterator riter( d_quantEngine, &(d_quantEngine->getModel()->d_rep_set) );
if( riter.setQuantifier( f ) ){
- Trace("fmf-exh-inst") << "...exhaustive instantiation incomplete=" << riter.d_incomplete << "..." << std::endl;
+ Trace("fmf-exh-inst") << "...exhaustive instantiation set, incomplete=" << riter.d_incomplete << "..." << std::endl;
if( !riter.d_incomplete ){
int triedLemmas = 0;
int addedLemmas = 0;
@@ -287,8 +294,11 @@ void ModelEngine::exhaustiveInstantiate( Node f, int effort ){
Debug("fmf-model-eval") << "* Add instantiation " << m << std::endl;
triedLemmas++;
//add as instantiation
- if( d_quantEngine->addInstantiation( f, m ) ){
+ if( d_quantEngine->addInstantiation( f, m, true ) ){
addedLemmas++;
+ if( d_quantEngine->inConflict() ){
+ break;
+ }
}else{
Debug("fmf-model-eval") << "* Failed Add instantiation " << m << std::endl;
}
@@ -299,6 +309,7 @@ void ModelEngine::exhaustiveInstantiate( Node f, int effort ){
d_statistics.d_exh_inst_lemmas += addedLemmas;
}
}else{
+ Trace("fmf-exh-inst") << "...exhaustive instantiation failed to set, incomplete=" << riter.d_incomplete << "..." << std::endl;
Assert( riter.d_incomplete );
}
//if the iterator is incomplete, we will return unknown instead of sat if no instantiations are added this round
@@ -308,15 +319,15 @@ void ModelEngine::exhaustiveInstantiate( Node f, int effort ){
void ModelEngine::debugPrint( const char* c ){
Trace( c ) << "Quantifiers: " << std::endl;
- for( int i=0; i<(int)d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
- Node f = d_quantEngine->getModel()->getAssertedQuantifier( i );
+ for( unsigned i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+ Node q = d_quantEngine->getModel()->getAssertedQuantifier( i );
Trace( c ) << " ";
- if( !d_quantEngine->getModelBuilder()->isQuantifierActive( f ) ){
+ if( !d_quantEngine->getModelBuilder()->isQuantifierActive( q ) ){
Trace( c ) << "*Inactive* ";
}else{
Trace( c ) << " ";
}
- Trace( c ) << f << std::endl;
+ Trace( c ) << q << std::endl;
}
//d_quantEngine->getModel()->debugPrint( c );
}
diff --git a/src/theory/quantifiers/model_engine.h b/src/theory/quantifiers/model_engine.h
index 1fb4255b2..12f18aa08 100644
--- a/src/theory/quantifiers/model_engine.h
+++ b/src/theory/quantifiers/model_engine.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file model_engine.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Model Engine class
**/
diff --git a/src/theory/quantifiers/quant_conflict_find.cpp b/src/theory/quantifiers/quant_conflict_find.cpp
index a890276f7..ca87a607d 100644
--- a/src/theory/quantifiers/quant_conflict_find.cpp
+++ b/src/theory/quantifiers/quant_conflict_find.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file quant_conflict_find.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Clark Barrett, Tim King, Andrew Reynolds
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief quant conflict find class
**
@@ -22,19 +22,32 @@
#include "theory/quantifiers/quant_util.h"
#include "theory/quantifiers/term_database.h"
#include "theory/quantifiers/trigger.h"
+#include "theory/quantifiers/first_order_model.h"
#include "theory/theory_engine.h"
-using namespace CVC4;
using namespace CVC4::kind;
-using namespace CVC4::theory;
-using namespace CVC4::theory::quantifiers;
using namespace std;
namespace CVC4 {
+namespace theory {
+namespace quantifiers {
+QuantInfo::QuantInfo()
+ : d_mg( NULL )
+{}
+
+QuantInfo::~QuantInfo() {
+ delete d_mg;
+ for(std::map< int, MatchGen * >::iterator i = d_var_mg.begin(),
+ iend=d_var_mg.end(); i != iend; ++i) {
+ MatchGen* currentMatchGenerator = (*i).second;
+ delete currentMatchGenerator;
+ }
+ d_var_mg.clear();
+}
-void QuantInfo::initialize( Node q, Node qn ) {
+void QuantInfo::initialize( QuantConflictFind * p, Node q, Node qn ) {
d_q = q;
for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
d_match.push_back( TNode::null() );
@@ -95,6 +108,59 @@ void QuantInfo::initialize( Node q, Node qn ) {
Trace("qcf-invalid") << "QCF invalid : body of formula cannot be processed." << std::endl;
}
Trace("qcf-qregister-summary") << "QCF register : " << ( d_mg->isValid() ? "VALID " : "INVALID" ) << " : " << q << std::endl;
+
+ if( d_mg->isValid() ){
+ //optimization : record variable argument positions for terms that must be matched
+ std::vector< TNode > vars;
+ //TODO: revisit this, makes QCF faster, but misses conflicts due to caring about paths that may not be relevant (starExec jobs 14136/14137)
+ //if( options::qcfSkipRd() ){
+ // for( unsigned j=q[0].getNumChildren(); j<d_vars.size(); j++ ){
+ // vars.push_back( d_vars[j] );
+ // }
+ //}
+ //get all variables that are always relevant
+ std::map< TNode, bool > visited;
+ getPropagateVars( vars, q[1], false, visited );
+ for( unsigned j=0; j<vars.size(); j++ ){
+ Node v = vars[j];
+ TNode f = p->getTermDatabase()->getMatchOperator( v );
+ if( !f.isNull() ){
+ Trace("qcf-opt") << "Record variable argument positions in " << v << ", op=" << f << "..." << std::endl;
+ for( unsigned k=0; k<v.getNumChildren(); k++ ){
+ Node n = v[k];
+ std::map< TNode, int >::iterator itv = d_var_num.find( n );
+ if( itv!=d_var_num.end() ){
+ Trace("qcf-opt") << " arg " << k << " is var #" << itv->second << std::endl;
+ if( std::find( d_var_rel_dom[itv->second][f].begin(), d_var_rel_dom[itv->second][f].end(), k )==d_var_rel_dom[itv->second][f].end() ){
+ d_var_rel_dom[itv->second][f].push_back( k );
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void QuantInfo::getPropagateVars( std::vector< TNode >& vars, TNode n, bool pol, std::map< TNode, bool >& visited ){
+ std::map< TNode, bool >::iterator itv = visited.find( n );
+ if( itv==visited.end() ){
+ visited[n] = true;
+ bool rec = true;
+ bool newPol = pol;
+ if( d_var_num.find( n )!=d_var_num.end() ){
+ Assert( std::find( vars.begin(), vars.end(), n )==vars.end() );
+ vars.push_back( n );
+ }else if( MatchGen::isHandledBoolConnective( n ) ){
+ Assert( n.getKind()!=IMPLIES );
+ QuantPhaseReq::getEntailPolarity( n, 0, true, pol, rec, newPol );
+ }
+ Trace("qcf-opt-debug") << "getPropagateVars " << n << ", pol = " << pol << ", rec = " << rec << std::endl;
+ if( rec ){
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ getPropagateVars( vars, n[i], pol, visited );
+ }
+ }
+ }
}
void QuantInfo::registerNode( Node n, bool hasPol, bool pol, bool beneathQuant ) {
@@ -315,7 +381,7 @@ int QuantInfo::addConstraint( QuantConflictFind * p, int v, TNode n, int vn, boo
return 1;
}else{
//std::map< int, TNode >::iterator itm = d_match.find( v );
-
+ bool isGroundRep = false;
if( vn!=-1 ){
Debug("qcf-match-debug") << " ...Variable bound to variable" << std::endl;
//std::map< int, TNode >::iterator itmn = d_match.find( vn );
@@ -361,13 +427,14 @@ int QuantInfo::addConstraint( QuantConflictFind * p, int v, TNode n, int vn, boo
}else{
Debug("qcf-match-debug") << " ...Variable bound to ground" << std::endl;
if( d_match[v].isNull() ){
+ //isGroundRep = true; ??
}else{
//compare ground values
Debug("qcf-match-debug") << " -> Ground value, compare " << d_match[v] << " "<< n << std::endl;
return p->areMatchEqual( d_match[v], n ) ? 0 : -1;
}
}
- if( setMatch( p, v, n ) ){
+ if( setMatch( p, v, n, isGroundRep ) ){
Debug("qcf-match-debug") << " -> success" << std::endl;
return 1;
}else{
@@ -433,8 +500,23 @@ bool QuantInfo::isConstrainedVar( int v ) {
}
}
-bool QuantInfo::setMatch( QuantConflictFind * p, int v, TNode n ) {
+bool QuantInfo::setMatch( QuantConflictFind * p, int v, TNode n, bool isGroundRep ) {
if( getCurrentCanBeEqual( p, v, n ) ){
+ if( isGroundRep ){
+ //fail if n does not exist in the relevant domain of each of the argument positions
+ std::map< int, std::map< TNode, std::vector< unsigned > > >::iterator it = d_var_rel_dom.find( v );
+ if( it!=d_var_rel_dom.end() ){
+ for( std::map< TNode, std::vector< unsigned > >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
+ for( unsigned j=0; j<it2->second.size(); j++ ){
+ Debug("qcf-match-debug2") << n << " in relevant domain " << it2->first << "." << it2->second[j] << "?" << std::endl;
+ if( !p->getTermDatabase()->inRelevantDomain( it2->first, it2->second[j], n ) ){
+ Debug("qcf-match-debug") << " -> fail, since " << n << " is not in relevant domain of " << it2->first << "." << it2->second[j] << std::endl;
+ return false;
+ }
+ }
+ }
+ }
+ }
Debug("qcf-match-debug") << "-- bind : " << v << " -> " << n << ", checked " << d_curr_var_deq[v].size() << " disequalities" << std::endl;
d_match[v] = n;
return true;
@@ -477,7 +559,22 @@ bool QuantInfo::entailmentTest( QuantConflictFind * p, Node lit, bool chEnt ) {
Trace("qcf-tconstraint-debug") << "...constraint " << lit << " is disentailed (rewrites to false)." << std::endl;
return false;
}else if( rew!=p->d_true ){
- //if checking for conflicts, we must be sure that the constraint is entailed
+ //if checking for conflicts, we must be sure that the (negation of) constraint is (not) entailed
+ if( !chEnt ){
+ rew = Rewriter::rewrite( rew.negate() );
+ }
+ //check if it is entailed
+ Trace("qcf-tconstraint-debug") << "Check entailment of " << rew << "..." << std::endl;
+ std::pair<bool, Node> et = p->getQuantifiersEngine()->getTheoryEngine()->entailmentCheck(THEORY_OF_TYPE_BASED, rew );
+ ++(p->d_statistics.d_entailment_checks);
+ Trace("qcf-tconstraint-debug") << "ET result : " << et.first << " " << et.second << std::endl;
+ if( !et.first ){
+ Trace("qcf-tconstraint-debug") << "...cannot show entailment of " << rew << "." << std::endl;
+ return !chEnt;
+ }else{
+ return chEnt;
+ }
+/*
if( chEnt ){
//check if it is entailed
Trace("qcf-tconstraint-debug") << "Check entailment of " << rew << "..." << std::endl;
@@ -494,6 +591,7 @@ bool QuantInfo::entailmentTest( QuantConflictFind * p, Node lit, bool chEnt ) {
Trace("qcf-tconstraint-debug") << "...does not need to be entailed." << std::endl;
return true;
}
+*/
}else{
Trace("qcf-tconstraint-debug") << "...rewrites to true." << std::endl;
return true;
@@ -538,7 +636,7 @@ bool QuantInfo::completeMatch( QuantConflictFind * p, std::vector< int >& assign
if( !z.isNull() ){
Trace("qcf-tconstraint-debug") << "...set " << d_vars[vn] << " = " << z << std::endl;
assigned.push_back( vn );
- if( !setMatch( p, vn, z ) ){
+ if( !setMatch( p, vn, z, false ) ){
success = false;
break;
}
@@ -580,7 +678,7 @@ bool QuantInfo::completeMatch( QuantConflictFind * p, std::vector< int >& assign
if( !sum.isNull() ){
assigned.push_back( slv_v );
Trace("qcf-tconstraint-debug") << "...set " << d_vars[slv_v] << " = " << sum << std::endl;
- if( !setMatch( p, slv_v, sum ) ){
+ if( !setMatch( p, slv_v, sum, false ) ){
success = false;
}
p->d_tempCache.push_back( sum );
@@ -666,7 +764,7 @@ bool QuantInfo::completeMatch( QuantConflictFind * p, std::vector< int >& assign
int currIndex = d_una_eqc_count[d_una_index];
d_una_eqc_count[d_una_index]++;
Trace("qcf-check-unassign") << d_unassigned[d_una_index] << "->" << p->d_eqcs[d_unassigned_tn[d_una_index]][currIndex] << std::endl;
- if( setMatch( p, d_unassigned[d_una_index], p->d_eqcs[d_unassigned_tn[d_una_index]][currIndex] ) ){
+ if( setMatch( p, d_unassigned[d_una_index], p->d_eqcs[d_unassigned_tn[d_una_index]][currIndex], true ) ){
d_match_term[d_unassigned[d_una_index]] = TNode::null();
Trace("qcf-check-unassign") << "Succeeded match " << d_una_index << std::endl;
d_una_index++;
@@ -801,6 +899,7 @@ MatchGen::MatchGen( QuantInfo * qi, Node n, bool isVar )
if( isVar ){
Assert( qi->d_var_num.find( n )!=qi->d_var_num.end() );
if( n.getKind()==ITE ){
+ /*
d_type = typ_ite_var;
d_type_not = false;
d_n = n;
@@ -817,15 +916,16 @@ MatchGen::MatchGen( QuantInfo * qi, Node n, bool isVar )
}
}
}else{
+*/
d_type = typ_invalid;
- }
+ //}
}else{
d_type = isHandledUfTerm( n ) ? typ_var : typ_tsym;
d_qni_var_num[0] = qi->getVarNum( n );
d_qni_size++;
d_type_not = false;
d_n = n;
- //Node f = getOperator( n );
+ //Node f = getMatchOperator( n );
for( unsigned j=0; j<d_n.getNumChildren(); j++ ){
Node nn = d_n[j];
Trace("qcf-qregister-debug") << " " << d_qni_size;
@@ -1031,16 +1131,27 @@ void MatchGen::reset_round( QuantConflictFind * p ) {
d_qni_gterm_rep[it->first] = p->getRepresentative( it->second );
}
if( d_type==typ_ground ){
- int e = p->evaluate( d_n );
- if( e==1 ){
- d_ground_eval[0] = p->d_true;
- }else if( e==-1 ){
- d_ground_eval[0] = p->d_false;
+ //int e = p->evaluate( d_n );
+ //if( e==1 ){
+ // d_ground_eval[0] = p->d_true;
+ //}else if( e==-1 ){
+ // d_ground_eval[0] = p->d_false;
+ //}
+ //modified
+ for( unsigned i=0; i<2; i++ ){
+ if( p->getTermDatabase()->isEntailed( d_n, i==0 ) ){
+ d_ground_eval[0] = i==0 ? p->d_true : p->d_false;
+ }
}
}else if( d_type==typ_eq ){
for( unsigned i=0; i<d_n.getNumChildren(); i++ ){
if( !d_n[i].hasBoundVar() ){
- d_ground_eval[i] = p->evaluateTerm( d_n[i] );
+ TNode t = p->getTermDatabase()->getEntailedTerm( d_n[i] );
+ if( t.isNull() ){
+ d_ground_eval[i] = d_n[i];
+ }else{
+ d_ground_eval[i] = t;
+ }
}
}
}
@@ -1073,14 +1184,18 @@ void MatchGen::reset( QuantConflictFind * p, bool tgt, QuantInfo * qi ) {
int vn = qi->getCurrentRepVar( qi->getVarNum( n ) );
if( vn==-1 ){
//evaluate the value, see if it is compatible
- int e = p->evaluate( n );
- if( ( e==1 && d_tgt ) || ( e==0 && !d_tgt ) ){
+ //int e = p->evaluate( n );
+ //if( ( e==1 && d_tgt ) || ( e==0 && !d_tgt ) ){
+ // d_child_counter = 0;
+ //}
+ //modified
+ if( p->getTermDatabase()->isEntailed( n, d_tgt ) ){
d_child_counter = 0;
}
}else{
//unassigned, set match to true/false
d_qni_bound[0] = vn;
- qi->setMatch( p, vn, d_tgt ? p->d_true : p->d_false );
+ qi->setMatch( p, vn, d_tgt ? p->d_true : p->d_false, false );
d_child_counter = 0;
}
if( d_child_counter==0 ){
@@ -1088,7 +1203,7 @@ void MatchGen::reset( QuantConflictFind * p, bool tgt, QuantInfo * qi ) {
}
}else if( d_type==typ_var ){
Assert( isHandledUfTerm( d_n ) );
- Node f = getOperator( p, d_n );
+ Node f = getMatchOperator( p, d_n );
Debug("qcf-match-debug") << " reset: Var will match operators of " << f << std::endl;
TermArgTrie * qni = p->getTermDatabase()->getTermArgTrie( Node::null(), f );
if( qni!=NULL ){
@@ -1242,12 +1357,12 @@ bool MatchGen::getNextMatch( QuantConflictFind * p, QuantInfo * qi ) {
Debug("qcf-match-debug") << "..." << std::endl;
while( ( success && d_binding_it!=d_qni_bound.end() ) || doFail ){
- std::map< int, MatchGen * >::iterator itm;
+ QuantInfo::VarMgMap::const_iterator itm;
if( !doFail ){
Debug("qcf-match-debug") << " check variable " << d_binding_it->second << std::endl;
- itm = qi->d_var_mg.find( d_binding_it->second );
+ itm = qi->var_mg_find( d_binding_it->second );
}
- if( doFail || ( d_binding_it->first!=0 && itm!=qi->d_var_mg.end() ) ){
+ if( doFail || ( d_binding_it->first!=0 && itm != qi->var_mg_end() ) ){
Debug("qcf-match-debug") << " we had bound variable " << d_binding_it->second << ", reset = " << doReset << std::endl;
if( doReset ){
itm->second->reset( p, true, qi );
@@ -1261,7 +1376,9 @@ bool MatchGen::getNextMatch( QuantConflictFind * p, QuantInfo * qi ) {
--d_binding_it;
Debug("qcf-match-debug") << " decrement..." << std::endl;
}
- }while( success && ( d_binding_it->first==0 || qi->d_var_mg.find( d_binding_it->second )==qi->d_var_mg.end() ) );
+ }while( success &&
+ ( d_binding_it->first==0 ||
+ (!qi->containsVarMg(d_binding_it->second))));
doReset = false;
doFail = false;
}else{
@@ -1318,17 +1435,6 @@ bool MatchGen::getNextMatch( QuantConflictFind * p, QuantInfo * qi ) {
d_qni_bound_cons.clear();
}
}
- /*
- if( d_type==typ_var && p->d_effort==QuantConflictFind::effort_mc && !d_matched_basis ){
- d_matched_basis = true;
- Node f = getOperator( d_n );
- TNode mbo = p->getTermDatabase()->getModelBasisOpTerm( f );
- if( qi->setMatch( p, d_qni_var_num[0], mbo ) ){
- success = true;
- d_qni_bound[0] = d_qni_var_num[0];
- }
- }
- */
}
Debug("qcf-match") << " ...finished matching for " << d_n << ", success = " << success << std::endl;
d_wasSet = success;
@@ -1548,7 +1654,7 @@ bool MatchGen::doMatching( QuantConflictFind * p, QuantInfo * qi ) {
if( it != d_qn[index]->d_data.end() ) {
d_qni.push_back( it );
//set the match
- if( it->first.getType().isComparableTo( qi->d_var_types[repVar] ) && qi->setMatch( p, d_qni_bound[index], it->first ) ){
+ if( it->first.getType().isComparableTo( qi->d_var_types[repVar] ) && qi->setMatch( p, d_qni_bound[index], it->first, true ) ){
Debug("qcf-match-debug") << " Binding variable" << std::endl;
if( d_qn.size()<d_qni_size ){
d_qn.push_back( &it->second );
@@ -1593,7 +1699,7 @@ bool MatchGen::doMatching( QuantConflictFind * p, QuantInfo * qi ) {
d_qni[index]++;
if( d_qni[index]!=d_qn[index]->d_data.end() ){
success = true;
- if( qi->setMatch( p, itb->second, d_qni[index]->first ) ){
+ if( qi->setMatch( p, itb->second, d_qni[index]->first, true ) ){
Debug("qcf-match-debug") << " Bind next variable" << std::endl;
if( d_qn.size()<d_qni_size ){
d_qn.push_back( &d_qni[index]->second );
@@ -1679,12 +1785,14 @@ bool MatchGen::isHandledBoolConnective( TNode n ) {
bool MatchGen::isHandledUfTerm( TNode n ) {
//return n.getKind()==APPLY_UF || n.getKind()==STORE || n.getKind()==SELECT ||
// n.getKind()==APPLY_CONSTRUCTOR || n.getKind()==APPLY_SELECTOR_TOTAL || n.getKind()==APPLY_TESTER;
+ //TODO : treat APPLY_TESTER as a T-constraint instead of matching (currently leads to overabundance of instantiations)
+ //return inst::Trigger::isAtomicTriggerKind( n.getKind() ) && ( !options::qcfTConstraint() || n.getKind()!=APPLY_TESTER );
return inst::Trigger::isAtomicTriggerKind( n.getKind() );
}
-Node MatchGen::getOperator( QuantConflictFind * p, Node n ) {
+Node MatchGen::getMatchOperator( QuantConflictFind * p, Node n ) {
if( isHandledUfTerm( n ) ){
- return p->getTermDatabase()->getOperator( n );
+ return p->getTermDatabase()->getMatchOperator( n );
}else{
return Node::null();
}
@@ -1707,8 +1815,7 @@ bool MatchGen::isHandled( TNode n ) {
QuantConflictFind::QuantConflictFind( QuantifiersEngine * qe, context::Context* c ) :
QuantifiersModule( qe ),
-d_conflict( c, false ),
-d_qassert( c ) {
+d_conflict( c, false ) {
d_fid_count = 0;
d_true = NodeManager::currentNM()->mkConst<bool>(true);
d_false = NodeManager::currentNM()->mkConst<bool>(false);
@@ -1733,7 +1840,7 @@ void QuantConflictFind::registerQuantifier( Node q ) {
Trace("qcf-qregister") << " : " << q << std::endl;
//make QcfNode structure
Trace("qcf-qregister") << "- Get relevant equality/disequality pairs, calculate flattening..." << std::endl;
- d_qinfo[q].initialize( q, q[1] );
+ d_qinfo[q].initialize( this, q, q[1] );
//debug print
Trace("qcf-qregister") << "- Flattened structure is :" << std::endl;
@@ -1748,96 +1855,16 @@ void QuantConflictFind::registerQuantifier( Node q ) {
Trace("qcf-qregister") << std::endl;
}
}
-
+
Trace("qcf-qregister") << "Done registering quantifier." << std::endl;
}
}
-int QuantConflictFind::evaluate( Node n, bool pref, bool hasPref ) {
- int ret = 0;
- if( n.getKind()==EQUAL ){
- Node n1 = evaluateTerm( n[0] );
- Node n2 = evaluateTerm( n[1] );
- Debug("qcf-eval") << "Evaluate : Normalize " << n << " to " << n1 << " = " << n2 << std::endl;
- if( areEqual( n1, n2 ) ){
- ret = 1;
- }else if( areDisequal( n1, n2 ) ){
- ret = -1;
- }
- //else if( d_effort>QuantConflictFind::effort_conflict ){
- // ret = -1;
- //}
- }else if( MatchGen::isHandledUfTerm( n ) ){ //predicate
- Node nn = evaluateTerm( n );
- Debug("qcf-eval") << "Evaluate : Normalize " << nn << " to " << n << std::endl;
- if( areEqual( nn, d_true ) ){
- ret = 1;
- }else if( areEqual( nn, d_false ) ){
- ret = -1;
- }
- //else if( d_effort>QuantConflictFind::effort_conflict ){
- // ret = -1;
- //}
- }else if( n.getKind()==NOT ){
- return -evaluate( n[0] );
- }else if( n.getKind()==ITE ){
- int cev1 = evaluate( n[0] );
- int cevc[2] = { 0, 0 };
- for( unsigned i=0; i<2; i++ ){
- if( ( i==0 && cev1!=-1 ) || ( i==1 && cev1!=1 ) ){
- cevc[i] = evaluate( n[i+1] );
- if( cev1!=0 ){
- ret = cevc[i];
- break;
- }else if( cevc[i]==0 ){
- break;
- }
- }
- }
- if( ret==0 && cevc[0]!=0 && cevc[0]==cevc[1] ){
- ret = cevc[0];
- }
- }else if( n.getKind()==IFF ){
- int cev1 = evaluate( n[0] );
- if( cev1!=0 ){
- int cev2 = evaluate( n[1] );
- if( cev2!=0 ){
- ret = cev1==cev2 ? 1 : -1;
- }
- }
-
- }else{
- int ssval = 0;
- if( n.getKind()==OR ){
- ssval = 1;
- }else if( n.getKind()==AND ){
- ssval = -1;
- }
- bool isUnk = false;
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- int cev = evaluate( n[i] );
- if( cev==ssval ){
- ret = ssval;
- break;
- }else if( cev==0 ){
- isUnk = true;
- }
- }
- if( ret==0 && !isUnk ){
- ret = -ssval;
- }
- }
- Debug("qcf-eval") << "Evaluate " << n << " to " << ret << std::endl;
- return ret;
-}
-
short QuantConflictFind::getMaxQcfEffort() {
if( options::qcfMode()==QCF_CONFLICT_ONLY ){
return effort_conflict;
- }else if( options::qcfMode()==QCF_PROP_EQ ){
+ }else if( options::qcfMode()==QCF_PROP_EQ || options::qcfMode()==QCF_PARTIAL ){
return effort_prop_eq;
- }else if( options::qcfMode()==QCF_MC ){
- return effort_mc;
}else{
return 0;
}
@@ -1862,48 +1889,13 @@ bool QuantConflictFind::areMatchDisequal( TNode n1, TNode n2 ) {
//-------------------------------------------------- handling assertions / eqc
void QuantConflictFind::assertNode( Node q ) {
+ /*
if( d_quantEngine->hasOwnership( q, this ) ){
Trace("qcf-proc") << "QCF : assertQuantifier : ";
debugPrintQuant("qcf-proc", q);
Trace("qcf-proc") << std::endl;
- d_qassert.push_back( q );
- //set the eqRegistries that this depends on to true
- //for( std::map< EqRegistry *, bool >::iterator it = d_qinfo[q].d_rel_eqr.begin(); it != d_qinfo[q].d_rel_eqr.end(); ++it ){
- // it->first->d_active.set( true );
- //}
}
-}
-
-Node QuantConflictFind::evaluateTerm( Node n ) {
- if( MatchGen::isHandledUfTerm( n ) ){
- Node f = MatchGen::getOperator( this, n );
- Node nn;
- if( getEqualityEngine()->hasTerm( n ) ){
- nn = getTermDatabase()->existsTerm( f, n );
- }else{
- std::vector< TNode > args;
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- Node c = evaluateTerm( n[i] );
- args.push_back( c );
- }
- nn = getTermDatabase()->d_func_map_trie[f].existsTerm( args );
- }
- if( !nn.isNull() ){
- Debug("qcf-eval") << "GT: Term " << nn << " for " << n << " hasTerm = " << getEqualityEngine()->hasTerm( n ) << std::endl;
- return getRepresentative( nn );
- }else{
- Debug("qcf-eval") << "GT: No term for " << n << " hasTerm = " << getEqualityEngine()->hasTerm( n ) << std::endl;
- return n;
- }
- }else if( n.getKind()==ITE ){
- int v = evaluate( n[0], false, false );
- if( v==1 ){
- return evaluateTerm( n[1] );
- }else if( v==-1 ){
- return evaluateTerm( n[2] );
- }
- }
- return getRepresentative( n );
+ */
}
/** new node */
@@ -1965,28 +1957,12 @@ void QuantConflictFind::check( Theory::Effort level, unsigned quant_e ) {
//determine order for quantified formulas
std::vector< Node > qorder;
- std::map< Node, bool > qassert;
- //mark which are asserted
- for( unsigned i=0; i<d_qassert.size(); i++ ){
- qassert[d_qassert[i]] = true;
- }
- //add which ones are specified in the order
- for( unsigned i=0; i<d_quant_order.size(); i++ ){
- Node n = d_quant_order[i];
- if( std::find( qorder.begin(), qorder.end(), n )==qorder.end() && qassert.find( n )!=qassert.end() ){
- qorder.push_back( n );
- }
- }
- d_quant_order.clear();
- d_quant_order.insert( d_quant_order.begin(), qorder.begin(), qorder.end() );
- //add remaining
- for( unsigned i=0; i<d_qassert.size(); i++ ){
- Node n = d_qassert[i];
- if( std::find( qorder.begin(), qorder.end(), n )==qorder.end() ){
- qorder.push_back( n );
+ for( unsigned i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+ Node q = d_quantEngine->getModel()->getAssertedQuantifier( i, true );
+ if( d_quantEngine->hasOwnership( q, this ) ){
+ qorder.push_back( q );
}
}
-
if( Trace.isOn("qcf-debug") ){
Trace("qcf-debug") << std::endl;
debugPrint("qcf-debug");
@@ -2002,7 +1978,7 @@ void QuantConflictFind::check( Theory::Effort level, unsigned quant_e ) {
QuantInfo * qi = &d_qinfo[q];
Assert( d_qinfo.find( q )!=d_qinfo.end() );
- if( qi->d_mg->isValid() ){
+ if( qi->matchGeneratorIsValid() ){
Trace("qcf-check") << "Check quantified formula ";
debugPrintQuant("qcf-check", q);
Trace("qcf-check") << " : " << q << "..." << std::endl;
@@ -2011,7 +1987,7 @@ void QuantConflictFind::check( Theory::Effort level, unsigned quant_e ) {
qi->reset_round( this );
//try to make a matches making the body false
Trace("qcf-check-debug") << "Get next match..." << std::endl;
- while( qi->d_mg->getNextMatch( this, qi ) ){
+ while( qi->getNextMatch( this ) ){
Trace("qcf-inst") << "*** Produced match at effort " << e << " : " << std::endl;
qi->debugPrintMatch("qcf-inst");
Trace("qcf-inst") << std::endl;
@@ -2021,22 +1997,21 @@ void QuantConflictFind::check( Theory::Effort level, unsigned quant_e ) {
std::vector< Node > terms;
qi->getMatch( terms );
if( !qi->isTConstraintSpurious( this, terms ) ){
+ //for debugging
if( Debug.isOn("qcf-check-inst") ){
- //if( e==effort_conflict ){
Node inst = d_quantEngine->getInstantiation( q, terms );
Debug("qcf-check-inst") << "Check instantiation " << inst << "..." << std::endl;
- Assert( evaluate( inst )!=1 );
- Assert( evaluate( inst )==-1 || e>effort_conflict );
- //}
+ Assert( !getTermDatabase()->isEntailed( inst, true ) );
+ Assert( getTermDatabase()->isEntailed( inst, false ) || e>effort_conflict );
}
- if( d_quantEngine->addInstantiation( q, terms, false ) ){
+ if( d_quantEngine->addInstantiation( q, terms ) ){
Trace("qcf-check") << " ... Added instantiation" << std::endl;
Trace("qcf-inst") << "*** Was from effort " << e << " : " << std::endl;
qi->debugPrintMatch("qcf-inst");
Trace("qcf-inst") << std::endl;
++addedLemmas;
if( e==effort_conflict ){
- d_quant_order.insert( d_quant_order.begin(), q );
+ d_quantEngine->markRelevant( q );
++(d_statistics.d_conflict_inst);
if( options::qcfAllConflict() ){
isConflict = true;
@@ -2045,11 +2020,14 @@ void QuantConflictFind::check( Theory::Effort level, unsigned quant_e ) {
}
break;
}else if( e==effort_prop_eq ){
+ d_quantEngine->markRelevant( q );
++(d_statistics.d_prop_inst);
}
}else{
Trace("qcf-inst") << " ... Failed to add instantiation" << std::endl;
- //Assert( false );
+ //this should only happen if the algorithm generates the same propagating instance twice this round
+ //in this case, break to avoid exponential behavior
+ break;
}
}
//clean up assigned
@@ -2062,6 +2040,7 @@ void QuantConflictFind::check( Theory::Effort level, unsigned quant_e ) {
Trace("qcf-inst") << " ... Spurious instantiation (match is inconsistent)" << std::endl;
}
}
+ Trace("qcf-check") << "Done, conflict = " << d_conflict << std::endl;
if( d_conflict ){
break;
}
@@ -2099,60 +2078,24 @@ void QuantConflictFind::computeRelevantEqr() {
//d_uf_terms.clear();
//d_eqc_uf_terms.clear();
d_eqcs.clear();
- d_model_basis.clear();
//d_arg_reps.clear();
//double clSet = 0;
//if( Trace.isOn("qcf-opt") ){
// clSet = double(clock())/double(CLOCKS_PER_SEC);
//}
- //long nTermst = 0;
- //long nTerms = 0;
- //long nEqc = 0;
-
- //which nodes are irrelevant for disequality matches
- std::map< TNode, bool > irrelevant_dnode;
//now, store matches
eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( getEqualityEngine() );
while( !eqcs_i.isFinished() ){
- //nEqc++;
Node r = (*eqcs_i);
if( getTermDatabase()->hasTermCurrent( r ) ){
TypeNode rtn = r.getType();
- if( options::qcfMode()==QCF_MC ){
- std::map< TypeNode, std::vector< TNode > >::iterator itt = d_eqcs.find( rtn );
- if( itt==d_eqcs.end() ){
- Node mb = getTermDatabase()->getModelBasisTerm( rtn );
- if( !getEqualityEngine()->hasTerm( mb ) ){
- Trace("qcf-warn") << "WARNING: Model basis term does not exist!" << std::endl;
- Assert( false );
- }
- Node mbr = getRepresentative( mb );
- if( mbr!=r ){
- d_eqcs[rtn].push_back( mbr );
- }
- d_eqcs[rtn].push_back( r );
- d_model_basis[rtn] = mb;
- }else{
- itt->second.push_back( r );
- }
- }else{
- if( !options::cbqi() || !TermDb::hasInstConstAttr( r ) ){
- d_eqcs[rtn].push_back( r );
- }
+ if( !options::cbqi() || !TermDb::hasInstConstAttr( r ) ){
+ d_eqcs[rtn].push_back( r );
}
}
++eqcs_i;
}
- /*
- if( Trace.isOn("qcf-opt") ){
- double clSet2 = double(clock())/double(CLOCKS_PER_SEC);
- Trace("qcf-opt") << "Compute rel eqc : " << std::endl;
- Trace("qcf-opt") << " " << nEqc << " equivalence classes. " << std::endl;
- Trace("qcf-opt") << " " << nTerms << " / " << nTermst << " terms." << std::endl;
- Trace("qcf-opt") << " Time : " << (clSet2-clSet) << std::endl;
- }
- */
}
}
@@ -2179,21 +2122,6 @@ void QuantConflictFind::debugPrint( const char * c ) {
++eqc_i;
}
Trace(c) << (pr ? " " : "" ) << "}" << std::endl;
- /*
- EqcInfo * eqcn = getEqcInfo( n, false );
- if( eqcn ){
- Trace(c) << " DEQ : {";
- pr = false;
- for( NodeBoolMap::iterator it = eqcn->d_diseq.begin(); it != eqcn->d_diseq.end(); ++it ){
- if( (*it).second ){
- Trace(c) << (pr ? "," : "" ) << " " << (*it).first;
- pr = true;
- }
- }
- Trace(c) << (pr ? " " : "" ) << "}" << std::endl;
- }
- //}
- */
++eqcs_i;
}
}
@@ -2255,5 +2183,6 @@ TNode QuantConflictFind::getZero( Kind k ) {
}
}
-
-}
+} /* namespace CVC4::theory::quantifiers */
+} /* namespace CVC4::theory */
+} /* namespace CVC4 */
diff --git a/src/theory/quantifiers/quant_conflict_find.h b/src/theory/quantifiers/quant_conflict_find.h
index 11299b532..8b42b0916 100644
--- a/src/theory/quantifiers/quant_conflict_find.h
+++ b/src/theory/quantifiers/quant_conflict_find.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file quant_conflict_find.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Clark Barrett, Tim King, Andrew Reynolds
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief quantifiers conflict find class
**/
@@ -98,7 +98,7 @@ public:
// is this term treated as UF application?
static bool isHandledBoolConnective( TNode n );
static bool isHandledUfTerm( TNode n );
- static Node getOperator( QuantConflictFind * p, Node n );
+ static Node getMatchOperator( QuantConflictFind * p, Node n );
//can this node be handled by the algorithm
static bool isHandled( TNode n );
};
@@ -114,9 +114,12 @@ private: //for completing match
int d_unassigned_nvar;
int d_una_index;
std::vector< int > d_una_eqc_count;
+ //optimization: track which arguments variables appear under UF terms in
+ std::map< int, std::map< TNode, std::vector< unsigned > > > d_var_rel_dom;
+ void getPropagateVars( std::vector< TNode >& vars, TNode n, bool pol, std::map< TNode, bool >& visited );
public:
- QuantInfo() : d_mg( NULL ) {}
- ~QuantInfo() { delete d_mg; }
+ QuantInfo();
+ ~QuantInfo();
std::vector< TNode > d_vars;
std::vector< TypeNode > d_var_types;
std::map< TNode, int > d_var_num;
@@ -128,13 +131,25 @@ public:
int getNumVars() { return (int)d_vars.size(); }
TNode getVar( int i ) { return d_vars[i]; }
+ typedef std::map< int, MatchGen * > VarMgMap;
+ private:
MatchGen * d_mg;
+ VarMgMap d_var_mg;
+ public:
+ VarMgMap::const_iterator var_mg_find(int i) const { return d_var_mg.find(i); }
+ VarMgMap::const_iterator var_mg_end() const { return d_var_mg.end(); }
+ bool containsVarMg(int i) const { return var_mg_find(i) != var_mg_end(); }
+
+ bool matchGeneratorIsValid() const { return d_mg->isValid(); }
+ bool getNextMatch( QuantConflictFind * p ) {
+ return d_mg->getNextMatch(p, this);
+ }
+
Node d_q;
- std::map< int, MatchGen * > d_var_mg;
void reset_round( QuantConflictFind * p );
public:
//initialize
- void initialize( Node q, Node qn );
+ void initialize( QuantConflictFind * p, Node q, Node qn );
//current constraints
std::vector< TNode > d_match;
std::vector< TNode > d_match_term;
@@ -146,7 +161,7 @@ public:
bool getCurrentCanBeEqual( QuantConflictFind * p, int v, TNode n, bool chDiseq = false );
int addConstraint( QuantConflictFind * p, int v, TNode n, bool polarity );
int addConstraint( QuantConflictFind * p, int v, TNode n, int vn, bool polarity, bool doRemove );
- bool setMatch( QuantConflictFind * p, int v, TNode n );
+ bool setMatch( QuantConflictFind * p, int v, TNode n, bool isGroundRep );
bool isMatchSpurious( QuantConflictFind * p );
bool isTConstraintSpurious( QuantConflictFind * p, std::vector< Node >& terms );
bool entailmentTest( QuantConflictFind * p, Node lit, bool chEnt = true );
@@ -166,7 +181,6 @@ class QuantConflictFind : public QuantifiersModule
typedef context::CDHashMap<Node, bool, NodeHashFunction> NodeBoolMap;
private:
context::CDO< bool > d_conflict;
- std::vector< Node > d_quant_order;
std::map< Kind, Node > d_zero;
//for storing nodes created during t-constraint solving (prevents memory leaks)
std::vector< Node > d_tempCache;
@@ -180,21 +194,14 @@ public: //for ground terms
Node d_false;
TNode getZero( Kind k );
private:
- Node evaluateTerm( Node n );
- int evaluate( Node n, bool pref = false, bool hasPref = false );
-private:
- //currently asserted quantifiers
- NodeList d_qassert;
std::map< Node, QuantInfo > d_qinfo;
private: //for equivalence classes
// type -> list(eqc)
std::map< TypeNode, std::vector< TNode > > d_eqcs;
- std::map< TypeNode, Node > d_model_basis;
public:
enum {
effort_conflict,
effort_prop_eq,
- effort_mc,
};
short d_effort;
void setEffort( int e ) { d_effort = e; }
@@ -248,8 +255,8 @@ public:
std::string identify() const { return "QcfEngine"; }
};
-}
-}
-}
+} /* namespace CVC4::theory::quantifiers */
+} /* namespace CVC4::theory */
+} /* namespace CVC4 */
#endif
diff --git a/src/theory/quantifiers/quant_equality_engine.cpp b/src/theory/quantifiers/quant_equality_engine.cpp
index 54a931196..3f89a799c 100644
--- a/src/theory/quantifiers/quant_equality_engine.cpp
+++ b/src/theory/quantifiers/quant_equality_engine.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file quant_equality_engine.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** Congruence closure with free variables
**/
@@ -32,6 +32,7 @@ d_conflict(c, false),
d_quant_red(c),
d_quant_unproc(c){
d_uequalityEngine.addFunctionKind( kind::APPLY_UF );
+ d_intType = NodeManager::currentNM()->integerType();
}
void QuantEqualityEngine::conflict(TNode t1, TNode t2) {
@@ -86,56 +87,130 @@ void QuantEqualityEngine::registerQuantifier( Node q ) {
void QuantEqualityEngine::assertNode( Node n ) {
Assert( n.getKind()==FORALL );
Trace("qee-debug") << "QEE assert : " << n << std::endl;
- Node lit = n[1].getKind()==NOT ? n[1][0] : n[1];
- bool pol = n[1].getKind()!=NOT;
- if( lit.getKind()==APPLY_UF || lit.getKind()==EQUAL ){
- lit = getTermDatabase()->getCanonicalTerm( lit );
- Trace("qee-debug") << "Canonical : " << lit << ", pol = " << pol << std::endl;
- Node t1 = lit.getKind()==APPLY_UF ? lit : lit[0];
+ if( !d_conflict ){
+ Node lit = n[1].getKind()==NOT ? n[1][0] : n[1];
+ bool pol = n[1].getKind()!=NOT;
+ bool success = true;
+ Node t1;
Node t2;
- if( lit.getKind()==APPLY_UF ){
- t2 = pol ? getTermDatabase()->d_true : getTermDatabase()->d_false;
- pol = true;
+ if( lit.getKind()==APPLY_UF || lit.getKind()==EQUAL || lit.getKind()==IFF ){
+ lit = getTermDatabase()->getCanonicalTerm( lit );
+ Trace("qee-debug") << "Canonical : " << lit << ", pol = " << pol << std::endl;
+ if( lit.getKind()==APPLY_UF ){
+ t1 = getFunctionAppForPredicateApp( lit );
+ t2 = pol ? getTermDatabase()->d_one : getTermDatabase()->d_zero;
+ pol = true;
+ lit = NodeManager::currentNM()->mkNode( EQUAL, t1, t2 );
+ }else if( lit.getKind()==EQUAL ){
+ t1 = lit[0];
+ t2 = lit[1];
+ }else if( lit.getKind()==IFF ){
+ if( lit[0].getKind()==NOT ){
+ t1 = lit[0][0];
+ pol = !pol;
+ }else{
+ t1 = lit[0];
+ }
+ if( lit[1].getKind()==NOT ){
+ t2 = lit[1][0];
+ pol = !pol;
+ }else{
+ t2 = lit[1];
+ }
+ if( t1.getKind()==APPLY_UF && t2.getKind()==APPLY_UF ){
+ t1 = getFunctionAppForPredicateApp( t1 );
+ t2 = getFunctionAppForPredicateApp( t2 );
+ lit = NodeManager::currentNM()->mkNode( EQUAL, t1, t2 );
+ }else{
+ success = false;
+ }
+ }
}else{
- t2 = lit[1];
- }
- bool alreadyHolds = false;
- if( pol && areUnivEqual( t1, t2 ) ){
- alreadyHolds = true;
- }else if( !pol && areUnivDisequal( t1, t2 ) ){
- alreadyHolds = true;
+ success = false;
}
+ if( success ){
+ bool alreadyHolds = false;
+ if( pol && areUnivEqualInternal( t1, t2 ) ){
+ alreadyHolds = true;
+ }else if( !pol && areUnivDisequalInternal( t1, t2 ) ){
+ alreadyHolds = true;
+ }
- if( alreadyHolds ){
- d_quant_red.push_back( n );
- Trace("qee-debug") << "...add to redundant" << std::endl;
- }else{
- Trace("qee-debug") << "...assert" << std::endl;
- Trace("qee-assert") << "QEE : assert : " << lit << ", pol = " << pol << ", kind = " << lit.getKind() << std::endl;
- if( lit.getKind()==APPLY_UF ){
- d_uequalityEngine.assertPredicate(lit, pol, n);
+ if( alreadyHolds ){
+ d_quant_red.push_back( n );
+ Trace("qee-debug") << "...add to redundant" << std::endl;
}else{
- d_uequalityEngine.assertEquality(lit, pol, n);
+ Trace("qee-debug") << "...assert" << std::endl;
+ Trace("qee-assert") << "QEE : assert : " << lit << ", pol = " << pol << ", kind = " << lit.getKind() << std::endl;
+ if( lit.getKind()==APPLY_UF ){
+ d_uequalityEngine.assertPredicate(lit, pol, n);
+ }else{
+ d_uequalityEngine.assertEquality(lit, pol, n);
+ }
}
+ }else{
+ d_quant_unproc[n] = true;
+ Trace("qee-debug") << "...add to unprocessed (" << lit.getKind() << ")" << std::endl;
}
- }else{
- d_quant_unproc[n] = true;
- Trace("qee-debug") << "...add to unprocessed (" << lit.getKind() << ")" << std::endl;
}
}
-bool QuantEqualityEngine::areUnivDisequal( TNode n1, TNode n2 ) {
+bool QuantEqualityEngine::areUnivDisequalInternal( TNode n1, TNode n2 ) {
return n1!=n2 && d_uequalityEngine.hasTerm( n1 ) && d_uequalityEngine.hasTerm( n2 ) && d_uequalityEngine.areDisequal( n1, n2, false );
}
-bool QuantEqualityEngine::areUnivEqual( TNode n1, TNode n2 ) {
+bool QuantEqualityEngine::areUnivEqualInternal( TNode n1, TNode n2 ) {
return n1==n2 || ( d_uequalityEngine.hasTerm( n1 ) && d_uequalityEngine.hasTerm( n2 ) && d_uequalityEngine.areEqual( n1, n2 ) );
}
-TNode QuantEqualityEngine::getUnivRepresentative( TNode n ) {
+TNode QuantEqualityEngine::getUnivRepresentativeInternal( TNode n ) {
if( d_uequalityEngine.hasTerm( n ) ){
return d_uequalityEngine.getRepresentative( n );
}else{
return n;
}
-} \ No newline at end of file
+}
+bool QuantEqualityEngine::areUnivDisequal( TNode n1, TNode n2 ) {
+ //TODO: must convert to internal representation
+ return areUnivDisequalInternal( n1, n2 );
+}
+
+bool QuantEqualityEngine::areUnivEqual( TNode n1, TNode n2 ) {
+ //TODO: must convert to internal representation
+ return areUnivEqualInternal( n1, n2 );
+}
+
+TNode QuantEqualityEngine::getUnivRepresentative( TNode n ) {
+ //TODO: must convert to internal representation
+ return getUnivRepresentativeInternal( n );
+}
+
+Node QuantEqualityEngine::getFunctionForPredicate( Node f ) {
+ std::map< Node, Node >::iterator it = d_pred_to_func.find( f );
+ if( it==d_pred_to_func.end() ){
+ std::vector< TypeNode > argTypes;
+ TypeNode tn = f.getType();
+ for( unsigned i=0; i<(tn.getNumChildren()-1); i++ ){
+ argTypes.push_back( tn[i] );
+ }
+ TypeNode ftn = NodeManager::currentNM()->mkFunctionType( argTypes, d_intType );
+ std::stringstream ss;
+ ss << "ee_" << f;
+ Node op = NodeManager::currentNM()->mkSkolem( ss.str(), ftn, "op created for internal ee" );
+ d_pred_to_func[f] = op;
+ return op;
+ }else{
+ return it->second;
+ }
+}
+
+Node QuantEqualityEngine::getFunctionAppForPredicateApp( Node n ) {
+ Assert( n.getKind()==APPLY_UF );
+ std::vector< Node > children;
+ children.push_back( getFunctionForPredicate( n.getOperator() ) );
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ children.push_back( n[i] );
+ }
+ return NodeManager::currentNM()->mkNode( APPLY_UF, children );
+}
+
diff --git a/src/theory/quantifiers/quant_equality_engine.h b/src/theory/quantifiers/quant_equality_engine.h
index 35a328147..26654de4d 100644
--- a/src/theory/quantifiers/quant_equality_engine.h
+++ b/src/theory/quantifiers/quant_equality_engine.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file quant_equality_engine.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Congruence closure with free variables
**/
@@ -56,12 +56,21 @@ private:
context::CDList<Node> d_quant_red;
/** unprocessed quantifiers in current context */
NodeBoolMap d_quant_unproc;
+ // map predicates to functions over int
+ TypeNode d_intType;
+ std::map< Node, Node > d_pred_to_func;
+ Node getFunctionForPredicate( Node f );
+ Node getFunctionAppForPredicateApp( Node n );
private:
void conflict(TNode t1, TNode t2);
void eqNotifyNewClass(TNode t);
void eqNotifyPreMerge(TNode t1, TNode t2);
void eqNotifyPostMerge(TNode t1, TNode t2);
void eqNotifyDisequal(TNode t1, TNode t2, TNode reason);
+ //queries
+ bool areUnivDisequalInternal( TNode n1, TNode n2 );
+ bool areUnivEqualInternal( TNode n1, TNode n2 );
+ TNode getUnivRepresentativeInternal( TNode n );
public:
QuantEqualityEngine( QuantifiersEngine * qe, context::Context* c );
virtual ~QuantEqualityEngine() throw (){}
diff --git a/src/theory/quantifiers/quant_split.cpp b/src/theory/quantifiers/quant_split.cpp
new file mode 100644
index 000000000..9fb943e5e
--- /dev/null
+++ b/src/theory/quantifiers/quant_split.cpp
@@ -0,0 +1,134 @@
+/********************* */
+/*! \file quant_split.cpp
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2016 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.\endverbatim
+ **
+ ** \brief Implementation of dynamic quantifiers splitting
+ **/
+
+#include "theory/quantifiers/quant_split.h"
+#include "theory/quantifiers/term_database.h"
+#include "theory/quantifiers_engine.h"
+#include "theory/quantifiers/first_order_model.h"
+#include "options/quantifiers_options.h"
+
+using namespace std;
+using namespace CVC4;
+using namespace CVC4::kind;
+using namespace CVC4::context;
+using namespace CVC4::theory;
+using namespace CVC4::theory::quantifiers;
+
+
+QuantDSplit::QuantDSplit( QuantifiersEngine * qe, context::Context* c ) :
+QuantifiersModule( qe ), d_added_split( qe->getUserContext() ){
+
+}
+
+/** pre register quantifier */
+void QuantDSplit::preRegisterQuantifier( Node q ) {
+ int max_index = -1;
+ int max_score = -1;
+ if( q.getNumChildren()==3 ){
+ return;
+ }
+ Trace("quant-dsplit-debug") << "Check split quantified formula : " << q << std::endl;
+ for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
+ TypeNode tn = q[0][i].getType();
+ if( tn.isDatatype() ){
+ const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
+ if( dt.isRecursiveSingleton() ){
+ Trace("quant-dsplit-debug") << "Datatype " << dt.getName() << " is recursive singleton." << std::endl;
+ }else{
+ int score = -1;
+ if( options::quantDynamicSplit()==quantifiers::QUANT_DSPLIT_MODE_AGG ){
+ score = dt.isUFinite() ? 1 : -1;
+ }else if( options::quantDynamicSplit()==quantifiers::QUANT_DSPLIT_MODE_DEFAULT ){
+ score = dt.isUFinite() ? 1 : -1;
+ }
+ Trace("quant-dsplit-debug") << "Datatype " << dt.getName() << " is score " << score << " (" << dt.isUFinite() << " " << dt.isFinite() << ")" << std::endl;
+ if( score>max_score ){
+ max_index = i;
+ max_score = score;
+ }
+ }
+ }
+ }
+
+ if( max_index!=-1 ){
+ Trace("quant-dsplit-debug") << "Will split at index " << max_index << "." << std::endl;
+ d_quant_to_reduce[q] = max_index;
+ d_quantEngine->setOwner( q, this );
+ }
+}
+
+/* whether this module needs to check this round */
+bool QuantDSplit::needsCheck( Theory::Effort e ) {
+ return e>=Theory::EFFORT_FULL && !d_quant_to_reduce.empty();
+}
+
+/* Call during quantifier engine's check */
+void QuantDSplit::check( Theory::Effort e, unsigned quant_e ) {
+ //add lemmas ASAP (they are a reduction)
+ if( quant_e==QuantifiersEngine::QEFFORT_CONFLICT ){
+ std::vector< Node > lemmas;
+ for(std::map< Node, int >::iterator it = d_quant_to_reduce.begin(); it != d_quant_to_reduce.end(); ++it) {
+ Node q = it->first;
+ if( d_added_split.find( q )==d_added_split.end() ){
+ d_added_split.insert( q );
+ std::vector< Node > bvs;
+ for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
+ if( (int)i!=it->second ){
+ bvs.push_back( q[0][i] );
+ }
+ }
+ std::vector< Node > disj;
+ disj.push_back( q.negate() );
+ TNode svar = q[0][it->second];
+ TypeNode tn = svar.getType();
+ if( tn.isDatatype() ){
+ std::vector< Node > cons;
+ const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
+ for( unsigned j=0; j<dt.getNumConstructors(); j++ ){
+ std::vector< Node > vars;
+ for( unsigned k=0; k<dt[j].getNumArgs(); k++ ){
+ TypeNode tns = TypeNode::fromType( dt[j][k].getRangeType() );
+ Node v = NodeManager::currentNM()->mkBoundVar( tns );
+ vars.push_back( v );
+ }
+ std::vector< Node > bvs_cmb;
+ bvs_cmb.insert( bvs_cmb.end(), bvs.begin(), bvs.end() );
+ bvs_cmb.insert( bvs_cmb.end(), vars.begin(), vars.end() );
+ vars.insert( vars.begin(), Node::fromExpr( dt[j].getConstructor() ) );
+ Node c = NodeManager::currentNM()->mkNode( kind::APPLY_CONSTRUCTOR, vars );
+ TNode ct = c;
+ Node body = q[1].substitute( svar, ct );
+ if( !bvs_cmb.empty() ){
+ body = NodeManager::currentNM()->mkNode( kind::FORALL, NodeManager::currentNM()->mkNode( kind::BOUND_VAR_LIST, bvs_cmb ), body );
+ }
+ cons.push_back( body );
+ }
+ Node conc = cons.size()==1 ? cons[0] : NodeManager::currentNM()->mkNode( kind::AND, cons );
+ disj.push_back( conc );
+ }else{
+ Assert( false );
+ }
+ lemmas.push_back( disj.size()==1 ? disj[0] : NodeManager::currentNM()->mkNode( kind::OR, disj ) );
+ }
+ }
+
+ //add lemmas to quantifiers engine
+ for( unsigned i=0; i<lemmas.size(); i++ ){
+ Trace("quant-dsplit") << "QuantDSplit lemma : " << lemmas[i] << std::endl;
+ d_quantEngine->addLemma( lemmas[i], false );
+ }
+ d_quant_to_reduce.clear();
+ }
+}
+
diff --git a/src/theory/quantifiers/quant_split.h b/src/theory/quantifiers/quant_split.h
new file mode 100644
index 000000000..d36824998
--- /dev/null
+++ b/src/theory/quantifiers/quant_split.h
@@ -0,0 +1,54 @@
+/********************* */
+/*! \file quant_split.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2016 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.\endverbatim
+ **
+ ** \brief dynamic quantifiers splitting
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__THEORY__QUANT_SPLIT_H
+#define __CVC4__THEORY__QUANT_SPLIT_H
+
+#include "theory/quantifiers_engine.h"
+#include "context/cdo.h"
+
+namespace CVC4 {
+namespace theory {
+namespace quantifiers {
+
+class QuantDSplit : public QuantifiersModule {
+ typedef context::CDHashSet<Node, NodeHashFunction> NodeSet;
+private:
+ /** list of relevant quantifiers asserted in the current context */
+ std::map< Node, int > d_quant_to_reduce;
+ /** whether we have instantiated quantified formulas */
+ NodeSet d_added_split;
+public:
+ QuantDSplit( QuantifiersEngine * qe, context::Context* c );
+ /** determine whether this quantified formula will be reduced */
+ void preRegisterQuantifier( Node q );
+
+ /* whether this module needs to check this round */
+ bool needsCheck( Theory::Effort e );
+ /* Call during quantifier engine's check */
+ void check( Theory::Effort e, unsigned quant_e );
+ /* Called for new quantifiers */
+ void registerQuantifier( Node q ) {}
+ void assertNode( Node n ) {}
+ /** Identify this module (for debugging, dynamic configuration, etc..) */
+ std::string identify() const { return "QuantDSplit"; }
+};
+
+}
+}
+}
+
+#endif
diff --git a/src/theory/quantifiers/quant_util.cpp b/src/theory/quantifiers/quant_util.cpp
index bf91f74c6..3b7787a20 100644
--- a/src/theory/quantifiers/quant_util.cpp
+++ b/src/theory/quantifiers/quant_util.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file quant_util.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of quantifier utilities
**/
@@ -23,6 +23,38 @@ using namespace CVC4::kind;
using namespace CVC4::context;
using namespace CVC4::theory;
+
+unsigned QuantifiersModule::needsModel( Theory::Effort e ) {
+ return QuantifiersEngine::QEFFORT_NONE;
+}
+
+eq::EqualityEngine * QuantifiersModule::getEqualityEngine() {
+ return d_quantEngine->getMasterEqualityEngine();
+}
+
+bool QuantifiersModule::areEqual( TNode n1, TNode n2 ) {
+ eq::EqualityEngine * ee = getEqualityEngine();
+ return n1==n2 || ( ee->hasTerm( n1 ) && ee->hasTerm( n2 ) && ee->areEqual( n1, n2 ) );
+}
+
+bool QuantifiersModule::areDisequal( TNode n1, TNode n2 ) {
+ eq::EqualityEngine * ee = getEqualityEngine();
+ return n1!=n2 && ee->hasTerm( n1 ) && ee->hasTerm( n2 ) && ee->areDisequal( n1, n2, false );
+}
+
+TNode QuantifiersModule::getRepresentative( TNode n ) {
+ eq::EqualityEngine * ee = getEqualityEngine();
+ if( ee->hasTerm( n ) ){
+ return ee->getRepresentative( n );
+ }else{
+ return n;
+ }
+}
+
+quantifiers::TermDb * QuantifiersModule::getTermDatabase() {
+ return d_quantEngine->getTermDatabase();
+}
+
bool QuantArith::getMonomial( Node n, Node& c, Node& v ){
if( n.getKind()==MULT && n.getNumChildren()==2 && n[0].isConst() ){
c = n[0];
@@ -33,8 +65,13 @@ bool QuantArith::getMonomial( Node n, Node& c, Node& v ){
}
}
bool QuantArith::getMonomial( Node n, std::map< Node, Node >& msum ) {
- if ( n.getKind()==MULT ){
- if( n.getNumChildren()==2 && msum.find(n[1])==msum.end() && n[0].isConst() ){
+ if( n.isConst() ){
+ if( msum.find(Node::null())==msum.end() ){
+ msum[Node::null()] = n;
+ return true;
+ }
+ }else if( n.getKind()==MULT && n.getNumChildren()==2 && n[0].isConst() ){
+ if( msum.find(n[1])==msum.end() ){
msum[n[1]] = n[0];
return true;
}
@@ -63,10 +100,7 @@ bool QuantArith::getMonomialSum( Node n, std::map< Node, Node >& msum ) {
bool QuantArith::getMonomialSumLit( Node lit, std::map< Node, Node >& msum ) {
if( lit.getKind()==GEQ || lit.getKind()==EQUAL ){
if( getMonomialSum( lit[0], msum ) ){
- if( lit[1].isConst() ){
- if( !lit[1].getConst<Rational>().isZero() ){
- msum[Node::null()] = negate( lit[1] );
- }
+ if( lit[1].isConst() && lit[1].getConst<Rational>().isZero() ){
return true;
}else{
//subtract the other side
@@ -90,7 +124,29 @@ bool QuantArith::getMonomialSumLit( Node lit, std::map< Node, Node >& msum ) {
return false;
}
-int QuantArith::isolate( Node v, std::map< Node, Node >& msum, Node & veq, Kind k, bool doCoeff ) {
+Node QuantArith::mkNode( std::map< Node, Node >& msum ) {
+ std::vector< Node > children;
+ for( std::map< Node, Node >::iterator it = msum.begin(); it != msum.end(); ++it ){
+ Node m;
+ if( !it->first.isNull() ){
+ if( !it->second.isNull() ){
+ m = NodeManager::currentNM()->mkNode( MULT, it->second, it->first );
+ }else{
+ m = it->first;
+ }
+ }else{
+ Assert( !it->second.isNull() );
+ m = it->second;
+ }
+ children.push_back(m);
+ }
+ return children.size()>1 ? NodeManager::currentNM()->mkNode( PLUS, children ) : (children.size()==1 ? children[0] : NodeManager::currentNM()->mkConst( Rational(0) ));
+}
+
+// given (msum <k> 0), solve (veq_c * v <k> val) or (val <k> veq_c * v), where:
+// veq_c is either null (meaning 1), or positive.
+// return value 1: veq_c*v is RHS, -1: veq_c*v is LHS, 0: failed.
+int QuantArith::isolate( Node v, std::map< Node, Node >& msum, Node & veq_c, Node & val, Kind k ) {
std::map< Node, Node >::iterator itv = msum.find( v );
if( itv!=msum.end() ){
std::vector< Node > children;
@@ -111,46 +167,42 @@ int QuantArith::isolate( Node v, std::map< Node, Node >& msum, Node & veq, Kind
children.push_back(m);
}
}
- veq = children.size()>1 ? NodeManager::currentNM()->mkNode( PLUS, children ) :
+ val = children.size()>1 ? NodeManager::currentNM()->mkNode( PLUS, children ) :
(children.size()==1 ? children[0] : NodeManager::currentNM()->mkConst( Rational(0) ));
- Node vc = v;
if( !r.isOne() && !r.isNegativeOne() ){
- if( vc.getType().isInteger() ){
- if( doCoeff ){
- vc = NodeManager::currentNM()->mkNode( MULT, NodeManager::currentNM()->mkConst( r.abs() ), vc );
- }else{
- return 0;
- }
+ if( v.getType().isInteger() ){
+ veq_c = NodeManager::currentNM()->mkConst( r.abs() );
}else{
- veq = NodeManager::currentNM()->mkNode( MULT, veq, NodeManager::currentNM()->mkConst( Rational(1) / r.abs() ) );
+ val = NodeManager::currentNM()->mkNode( MULT, val, NodeManager::currentNM()->mkConst( Rational(1) / r.abs() ) );
}
}
if( r.sgn()==1 ){
- veq = negate(veq);
+ val = negate(val);
+ }else{
+ val = Rewriter::rewrite( val );
}
- veq = Rewriter::rewrite( veq );
- bool inOrder = r.sgn()==1 || k==EQUAL;
- veq = NodeManager::currentNM()->mkNode( k, inOrder ? vc : veq, inOrder ? veq : vc );
- return inOrder ? 1 : -1;
+ return ( r.sgn()==1 || k==EQUAL ) ? 1 : -1;
}
}
return 0;
}
-int QuantArith::isolate( Node v, std::map< Node, Node >& msum, Node & veq_c, Node & val, Kind k ) {
- Node vatom;
- //isolate pv in the inequality
- int ires = isolate( v, msum, vatom, k, true );
+int QuantArith::isolate( Node v, std::map< Node, Node >& msum, Node & veq, Kind k, bool doCoeff ) {
+ Node veq_c;
+ Node val;
+ //isolate v in the (in)equality
+ int ires = isolate( v, msum, veq_c, val, k );
if( ires!=0 ){
- val = vatom[ ires==1 ? 1 : 0 ];
- Node pvm = vatom[ ires==1 ? 0 : 1 ];
- //get monomial
- if( pvm!=v ){
- Node veq_v;
- if( QuantArith::getMonomial( pvm, veq_c, veq_v ) ){
- Assert( veq_v==v );
+ Node vc = v;
+ if( !veq_c.isNull() ){
+ if( doCoeff ){
+ vc = NodeManager::currentNM()->mkNode( MULT, veq_c, vc );
+ }else{
+ return 0;
}
}
+ bool inOrder = ires==1;
+ veq = NodeManager::currentNM()->mkNode( k, inOrder ? vc : val, inOrder ? val : vc );
}
return ires;
}
@@ -164,7 +216,7 @@ Node QuantArith::solveEqualityFor( Node lit, Node v ) {
return lit[1-r];
}
}
- if( tn.isInteger() || tn.isReal() ){
+ if( tn.isReal() ){
if( quantifiers::TermDb::containsTerm( lit, v ) ){
std::map< Node, Node > msum;
if( QuantArith::getMonomialSumLit( lit, msum ) ){
@@ -357,3 +409,20 @@ void QuantPhaseReq::getPolarity( Node n, int child, bool hasPol, bool pol, bool&
newPol = pol;
}
}
+
+void QuantPhaseReq::getEntailPolarity( Node n, int child, bool hasPol, bool pol, bool& newHasPol, bool& newPol ) {
+ if( n.getKind()==AND || n.getKind()==OR ){
+ newHasPol = hasPol && pol==( n.getKind()==AND );
+ newPol = pol;
+ }else if( n.getKind()==IMPLIES ){
+ newHasPol = hasPol && !pol;
+ newPol = child==0 ? !pol : pol;
+ }else if( n.getKind()==NOT ){
+ newHasPol = hasPol;
+ newPol = !pol;
+ }else{
+ newHasPol = false;
+ newPol = pol;
+ }
+}
+
diff --git a/src/theory/quantifiers/quant_util.h b/src/theory/quantifiers/quant_util.h
index 566a09923..79cdae437 100644
--- a/src/theory/quantifiers/quant_util.h
+++ b/src/theory/quantifiers/quant_util.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file quant_util.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief quantifier util
**/
@@ -29,6 +29,58 @@ namespace theory {
class QuantifiersEngine;
+namespace quantifiers {
+ class TermDb;
+}
+
+class QuantifiersModule {
+protected:
+ QuantifiersEngine* d_quantEngine;
+public:
+ QuantifiersModule( QuantifiersEngine* qe ) : d_quantEngine( qe ){}
+ virtual ~QuantifiersModule(){}
+ //get quantifiers engine
+ QuantifiersEngine* getQuantifiersEngine() { return d_quantEngine; }
+ /** presolve */
+ virtual void presolve() {}
+ /* whether this module needs to check this round */
+ virtual bool needsCheck( Theory::Effort e ) { return e>=Theory::EFFORT_LAST_CALL; }
+ /* whether this module needs a model built */
+ virtual unsigned needsModel( Theory::Effort e );
+ /* reset at a round */
+ virtual void reset_round( Theory::Effort e ){}
+ /* Call during quantifier engine's check */
+ virtual void check( Theory::Effort e, unsigned quant_e ) = 0;
+ /* check was complete (e.g. no lemmas implies a model) */
+ virtual bool checkComplete() { return true; }
+ /* Called for new quantified formulas */
+ virtual void preRegisterQuantifier( Node q ) { }
+ /* Called for new quantifiers after owners are finalized */
+ virtual void registerQuantifier( Node q ) = 0;
+ virtual void assertNode( Node n ) {}
+ virtual void propagate( Theory::Effort level ){}
+ virtual Node getNextDecisionRequest() { return TNode::null(); }
+ /** Identify this module (for debugging, dynamic configuration, etc..) */
+ virtual std::string identify() const = 0;
+public:
+ eq::EqualityEngine * getEqualityEngine();
+ bool areDisequal( TNode n1, TNode n2 );
+ bool areEqual( TNode n1, TNode n2 );
+ TNode getRepresentative( TNode n );
+ quantifiers::TermDb * getTermDatabase();
+};/* class QuantifiersModule */
+
+class QuantifiersUtil {
+public:
+ QuantifiersUtil(){}
+ virtual ~QuantifiersUtil(){}
+ /* reset at a round */
+ virtual bool reset( Theory::Effort e ) = 0;
+ /** Identify this module (for debugging, dynamic configuration, etc..) */
+ virtual std::string identify() const = 0;
+};
+
+
class QuantArith
{
public:
@@ -36,9 +88,10 @@ public:
static bool getMonomial( Node n, std::map< Node, Node >& msum );
static bool getMonomialSum( Node n, std::map< Node, Node >& msum );
static bool getMonomialSumLit( Node lit, std::map< Node, Node >& msum );
+ static Node mkNode( std::map< Node, Node >& msum );
//return 1 : solved on LHS, return -1 : solved on RHS, return 0: failed
- static int isolate( Node v, std::map< Node, Node >& msum, Node & veq, Kind k, bool doCoeff = false );
static int isolate( Node v, std::map< Node, Node >& msum, Node & veq_c, Node & val, Kind k );
+ static int isolate( Node v, std::map< Node, Node >& msum, Node & veq, Kind k, bool doCoeff = false );
static Node solveEqualityFor( Node lit, Node v );
static Node negate( Node t );
static Node offset( Node t, int i );
@@ -92,15 +145,16 @@ public:
std::map< Node, Node > d_phase_reqs_equality_term;
static void getPolarity( Node n, int child, bool hasPol, bool pol, bool& newHasPol, bool& newPol );
+ static void getEntailPolarity( Node n, int child, bool hasPol, bool pol, bool& newHasPol, bool& newPol );
};
-class EqualityQuery {
+class EqualityQuery : public QuantifiersUtil{
public:
EqualityQuery(){}
virtual ~EqualityQuery(){};
- /** reset */
- virtual void reset() = 0;
+ /** extends engine */
+ virtual bool extendsEngine() { return false; }
/** contains term */
virtual bool hasTerm( Node a ) = 0;
/** get the representative of the equivalence class of a */
@@ -113,6 +167,8 @@ public:
virtual eq::EqualityEngine* getEngine() = 0;
/** get the equivalence class of a */
virtual void getEquivalenceClass( Node a, std::vector< Node >& eqc ) = 0;
+ /** get the term that exists in EE that is congruent to f with args (f is returned by TermDb::getMatchOperator(...) */
+ virtual TNode getCongruentTerm( Node f, std::vector< TNode >& args ) = 0;
};/* class EqualityQuery */
diff --git a/src/theory/quantifiers/quantifiers_attributes.cpp b/src/theory/quantifiers/quantifiers_attributes.cpp
index 8c6b30124..b797f4ce9 100644
--- a/src/theory/quantifiers/quantifiers_attributes.cpp
+++ b/src/theory/quantifiers/quantifiers_attributes.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file quantifiers_attributes.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of QuantifiersAttributes class
**/
@@ -24,7 +24,7 @@ using namespace CVC4::context;
using namespace CVC4::theory;
using namespace CVC4::theory::quantifiers;
-void QuantifiersAttributes::setUserAttribute( const std::string& attr, Node n, std::vector<Node> node_values, std::string str_value ){
+void QuantifiersAttributes::setUserAttribute( const std::string& attr, Node n, std::vector< Node >& node_values, std::string str_value ){
Trace("quant-attr-debug") << "Set " << attr << " " << n << std::endl;
if( attr=="axiom" ){
Trace("quant-attr-debug") << "Set axiom " << n << std::endl;
@@ -58,5 +58,13 @@ void QuantifiersAttributes::setUserAttribute( const std::string& attr, Node n, s
Trace("quant-attr-debug") << "Set rewrite rule priority " << n << " to " << lvl << std::endl;
RrPriorityAttribute rrpa;
n.setAttribute( rrpa, lvl );
+ }else if( attr=="quant-elim" ){
+ Trace("quant-attr-debug") << "Set quantifier elimination " << n << std::endl;
+ QuantElimAttribute qea;
+ n.setAttribute( qea, true );
+ }else if( attr=="quant-elim-partial" ){
+ Trace("quant-attr-debug") << "Set partial quantifier elimination " << n << std::endl;
+ QuantElimPartialAttribute qepa;
+ n.setAttribute( qepa, true );
}
}
diff --git a/src/theory/quantifiers/quantifiers_attributes.h b/src/theory/quantifiers/quantifiers_attributes.h
index bad58eef8..53cef796a 100644
--- a/src/theory/quantifiers/quantifiers_attributes.h
+++ b/src/theory/quantifiers/quantifiers_attributes.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file quantifiers_attributes.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Attributes for the theory quantifiers
**
@@ -36,7 +36,7 @@ struct QuantifiersAttributes
* This function will apply a custom set of attributes to all top-level universal
* quantifiers contained in n
*/
- static void setUserAttribute( const std::string& attr, Node n, std::vector<Node> node_values, std::string str_value );
+ static void setUserAttribute( const std::string& attr, Node n, std::vector< Node >& node_values, std::string str_value );
};
diff --git a/src/theory/quantifiers/quantifiers_rewriter.cpp b/src/theory/quantifiers/quantifiers_rewriter.cpp
index afe8cd598..5aae4d640 100644
--- a/src/theory/quantifiers/quantifiers_rewriter.cpp
+++ b/src/theory/quantifiers/quantifiers_rewriter.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file quantifiers_rewriter.cpp
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): Tim King
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of QuantifiersRewriter class
**/
@@ -229,52 +229,48 @@ RewriteResponse QuantifiersRewriter::preRewrite(TNode in) {
RewriteResponse QuantifiersRewriter::postRewrite(TNode in) {
Trace("quantifiers-rewrite-debug") << "post-rewriting " << in << std::endl;
- if( !options::quantRewriteRules() || !TermDb::isRewriteRule( in ) ){
- RewriteStatus status = REWRITE_DONE;
- Node ret = in;
- //get the arguments
- std::vector< Node > args;
- for( int i=0; i<(int)in[0].getNumChildren(); i++ ){
- args.push_back( in[0][i] );
- }
- //get the instantiation pattern list
- Node ipl;
+ RewriteStatus status = REWRITE_DONE;
+ Node ret = in;
+ int rew_op = -1;
+ //get the body
+ if( in.getKind()==EXISTS ){
+ std::vector< Node > children;
+ children.push_back( in[0] );
+ children.push_back( in[1].negate() );
if( in.getNumChildren()==3 ){
- ipl = in[2];
- }
- //get the body
- if( in.getKind()==EXISTS ){
- std::vector< Node > children;
- children.push_back( in[0] );
- children.push_back( in[1].negate() );
- if( in.getNumChildren()==3 ){
- children.push_back( in[2] );
- }
- ret = NodeManager::currentNM()->mkNode( FORALL, children );
- ret = ret.negate();
- status = REWRITE_AGAIN_FULL;
+ children.push_back( in[2] );
+ }
+ ret = NodeManager::currentNM()->mkNode( FORALL, children );
+ ret = ret.negate();
+ status = REWRITE_AGAIN_FULL;
+ }else if( in.getKind()==FORALL ){
+ if( in[1].isConst() ){
+ return RewriteResponse( status, in[1] );
}else{
- for( int op=0; op<COMPUTE_LAST; op++ ){
- //TODO : compute isNested (necessary?)
- bool isNested = false;
- if( doOperation( in, isNested, op ) ){
- ret = computeOperation( in, isNested, op );
- if( ret!=in ){
- status = REWRITE_AGAIN_FULL;
- break;
+ //compute attributes
+ QAttributes qa;
+ TermDb::computeQuantAttributes( in, qa );
+ if( !qa.isRewriteRule() ){
+ for( int op=0; op<COMPUTE_LAST; op++ ){
+ if( doOperation( in, op, qa ) ){
+ ret = computeOperation( in, op, qa );
+ if( ret!=in ){
+ rew_op = op;
+ status = REWRITE_AGAIN_FULL;
+ break;
+ }
}
}
}
}
- //print if changed
- if( in!=ret ){
- Trace("quantifiers-rewrite") << "*** rewrite " << in << std::endl;
- Trace("quantifiers-rewrite") << " to " << std::endl;
- Trace("quantifiers-rewrite") << ret << std::endl;
- }
- return RewriteResponse( status, ret );
}
- return RewriteResponse(REWRITE_DONE, in);
+ //print if changed
+ if( in!=ret ){
+ Trace("quantifiers-rewrite") << "*** rewrite (op=" << rew_op << ") " << in << std::endl;
+ Trace("quantifiers-rewrite") << " to " << std::endl;
+ Trace("quantifiers-rewrite") << ret << std::endl;
+ }
+ return RewriteResponse( status, ret );
}
Node QuantifiersRewriter::computeElimSymbols( Node body ) {
@@ -315,6 +311,10 @@ Node QuantifiersRewriter::computeElimSymbols( Node body ) {
}
childrenChanged = childrenChanged || c!=body[i];
}
+ //if( body.getKind()==ITE && isLiteral( body[0] ) ){
+ // ret = NodeManager::currentNM()->mkNode( AND, NodeManager::currentNM()->mkNode( OR, body[0].negate(), body[1] ),
+ // NodeManager::currentNM()->mkNode( OR, body[0], body[2] ) );
+ //}
if( childrenChanged ){
return ( children.size()==1 && k!=NOT ) ? children[0] : NodeManager::currentNM()->mkNode( k, children );
}else{
@@ -330,7 +330,7 @@ Node QuantifiersRewriter::computeNNF( Node body ){
}else if( isLiteral( body[0] ) ){
return body;
}else{
- std::vector< Node > children;
+ std::vector< Node > children;
Kind k = body[0].getKind();
if( body[0].getKind()==OR || body[0].getKind()==AND ){
@@ -564,12 +564,23 @@ void setEntailedCond( Node n, bool pol, std::map< Node, bool >& currCond, std::v
}
}
-Node QuantifiersRewriter::computeProcessTerms( Node body, std::vector< Node >& new_vars, std::vector< Node >& new_conds, Node q ){
+void removeEntailedCond( std::map< Node, bool >& currCond, std::vector< Node >& new_cond, std::map< Node, Node >& cache ) {
+ if( !new_cond.empty() ){
+ for( unsigned j=0; j<new_cond.size(); j++ ){
+ currCond.erase( new_cond[j] );
+ }
+ new_cond.clear();
+ cache.clear();
+ }
+}
+
+Node QuantifiersRewriter::computeProcessTerms( Node body, std::vector< Node >& new_vars, std::vector< Node >& new_conds, Node q, QAttributes& qa ){
std::map< Node, bool > curr_cond;
std::map< Node, Node > cache;
std::map< Node, Node > icache;
- Node h = TermDb::getFunDefHead( q );
- if( !h.isNull() ){
+ if( qa.isFunDef() ){
+ Node h = TermDb::getFunDefHead( q );
+ Assert( !h.isNull() );
// if it is a function definition, rewrite the body independently
Node fbody = TermDb::getFunDefBody( q );
Assert( !body.isNull() );
@@ -591,96 +602,119 @@ Node QuantifiersRewriter::computeProcessTerms2( Node body, bool hasPol, bool pol
ret = iti->second;
Trace("quantifiers-rewrite-term-debug2") << "Return (cached) " << ret << " for " << body << std::endl;
}else{
- bool firstTimeCD = true;
+ //only do context dependent processing up to depth 8
+ bool doCD = nCurrCond<8;
bool changed = false;
std::vector< Node > children;
- for( size_t i=0; i<body.getNumChildren(); i++ ){
- std::vector< Node > new_cond;
+ //set entailed conditions based on OR/AND
+ std::map< int, std::vector< Node > > new_cond_children;
+ if( doCD && ( body.getKind()==OR || body.getKind()==AND ) ){
+ nCurrCond = nCurrCond + 1;
bool conflict = false;
- //only do context dependent processing up to depth 8
- if( nCurrCond<8 ){
- if( firstTimeCD ){
- firstTimeCD = false;
- nCurrCond = nCurrCond + 1;
- }
- if( Trace.isOn("quantifiers-rewrite-term-debug") ){
- //if( ( body.getKind()==ITE && i>0 ) || ( hasPol && ( ( body.getKind()==OR && pol ) || (body.getKind()==AND && !pol ) ) ) ){
- if( ( body.getKind()==ITE && i>0 ) || body.getKind()==OR || body.getKind()==AND ){
- Trace("quantifiers-rewrite-term-debug") << "---rewrite " << body[i] << " under conditions:----" << std::endl;
+ bool use_pol = body.getKind()==AND;
+ for( unsigned j=0; j<body.getNumChildren(); j++ ){
+ setEntailedCond( body[j], use_pol, currCond, new_cond_children[j], conflict );
+ }
+ if( conflict ){
+ Trace("quantifiers-rewrite-term-debug") << "-------conflict, return " << !use_pol << std::endl;
+ ret = NodeManager::currentNM()->mkConst( !use_pol );
+ }
+ }
+ if( ret.isNull() ){
+ for( size_t i=0; i<body.getNumChildren(); i++ ){
+
+ //set/update entailed conditions
+ std::vector< Node > new_cond;
+ bool conflict = false;
+ if( doCD ){
+ if( Trace.isOn("quantifiers-rewrite-term-debug") ){
+ if( ( body.getKind()==ITE && i>0 ) || body.getKind()==OR || body.getKind()==AND ){
+ Trace("quantifiers-rewrite-term-debug") << "---rewrite " << body[i] << " under conditions:----" << std::endl;
+ }
}
- }
- if( body.getKind()==ITE && i>0 ){
- setEntailedCond( children[0], i==1, currCond, new_cond, conflict );
- //should not conflict (entailment check failed)
- Assert( !conflict );
- }
- //if( hasPol && ( ( body.getKind()==OR && pol ) || ( body.getKind()==AND && !pol ) ) ){
- // bool use_pol = !pol;
- if( body.getKind()==OR || body.getKind()==AND ){
- bool use_pol = body.getKind()==AND;
- for( unsigned j=0; j<body.getNumChildren(); j++ ){
- if( j<i ){
- setEntailedCond( children[j], use_pol, currCond, new_cond, conflict );
- }else if( j>i ){
- setEntailedCond( body[j], use_pol, currCond, new_cond, conflict );
+ if( body.getKind()==ITE && i>0 ){
+ if( i==1 ){
+ nCurrCond = nCurrCond + 1;
}
+ setEntailedCond( children[0], i==1, currCond, new_cond, conflict );
+ //should not conflict (entailment check failed)
+ Assert( !conflict );
}
- if( conflict ){
- Trace("quantifiers-rewrite-term-debug") << "-------conflict, return " << !use_pol << std::endl;
- ret = NodeManager::currentNM()->mkConst( !use_pol );
+ if( body.getKind()==OR || body.getKind()==AND ){
+ bool use_pol = body.getKind()==AND;
+ //remove the current condition
+ removeEntailedCond( currCond, new_cond_children[i], cache );
+ if( i>0 ){
+ //add the previous condition
+ setEntailedCond( children[i-1], use_pol, currCond, new_cond_children[i-1], conflict );
+ }
+ if( conflict ){
+ Trace("quantifiers-rewrite-term-debug") << "-------conflict, return " << !use_pol << std::endl;
+ ret = NodeManager::currentNM()->mkConst( !use_pol );
+ }
}
- }
- if( !new_cond.empty() ){
- cache.clear();
- }
- if( Trace.isOn("quantifiers-rewrite-term-debug") ){
- //if( ( body.getKind()==ITE && i>0 ) || ( hasPol && ( ( body.getKind()==OR && pol ) || (body.getKind()==AND && !pol ) ) ) ){
- if( ( body.getKind()==ITE && i>0 ) || body.getKind()==OR || body.getKind()==AND ){
- Trace("quantifiers-rewrite-term-debug") << "-------" << std::endl;
+ if( !new_cond.empty() ){
+ cache.clear();
+ }
+ if( Trace.isOn("quantifiers-rewrite-term-debug") ){
+ if( ( body.getKind()==ITE && i>0 ) || body.getKind()==OR || body.getKind()==AND ){
+ Trace("quantifiers-rewrite-term-debug") << "-------" << std::endl;
+ }
}
}
- }
- if( !conflict ){
- bool newHasPol;
- bool newPol;
- QuantPhaseReq::getPolarity( body, i, hasPol, pol, newHasPol, newPol );
- Node nn = computeProcessTerms2( body[i], newHasPol, newPol, currCond, nCurrCond, cache, icache, new_vars, new_conds );
- if( body.getKind()==ITE && i==0 ){
- int res = getEntailedCond( nn, currCond );
- Trace("quantifiers-rewrite-term-debug") << "Condition for " << body << " is " << nn << ", entailment check=" << res << std::endl;
- if( res==1 ){
- ret = computeProcessTerms2( body[1], hasPol, pol, currCond, nCurrCond, cache, icache, new_vars, new_conds );
- }else if( res==-1 ){
- ret = computeProcessTerms2( body[2], hasPol, pol, currCond, nCurrCond, cache, icache, new_vars, new_conds );
+
+ //do the recursive call on children
+ if( !conflict ){
+ bool newHasPol;
+ bool newPol;
+ QuantPhaseReq::getPolarity( body, i, hasPol, pol, newHasPol, newPol );
+ Node nn = computeProcessTerms2( body[i], newHasPol, newPol, currCond, nCurrCond, cache, icache, new_vars, new_conds );
+ if( body.getKind()==ITE && i==0 ){
+ int res = getEntailedCond( nn, currCond );
+ Trace("quantifiers-rewrite-term-debug") << "Condition for " << body << " is " << nn << ", entailment check=" << res << std::endl;
+ if( res==1 ){
+ ret = computeProcessTerms2( body[1], hasPol, pol, currCond, nCurrCond, cache, icache, new_vars, new_conds );
+ }else if( res==-1 ){
+ ret = computeProcessTerms2( body[2], hasPol, pol, currCond, nCurrCond, cache, icache, new_vars, new_conds );
+ }
}
+ children.push_back( nn );
+ changed = changed || nn!=body[i];
+ }
+
+ //clean up entailed conditions
+ removeEntailedCond( currCond, new_cond, cache );
+
+ if( !ret.isNull() ){
+ break;
}
- children.push_back( nn );
- changed = changed || nn!=body[i];
}
- if( !new_cond.empty() ){
- for( unsigned j=0; j<new_cond.size(); j++ ){
- currCond.erase( new_cond[j] );
+
+ //make return value
+ if( ret.isNull() ){
+ if( changed ){
+ if( body.getMetaKind() == kind::metakind::PARAMETERIZED ){
+ children.insert( children.begin(), body.getOperator() );
+ }
+ ret = NodeManager::currentNM()->mkNode( body.getKind(), children );
+ }else{
+ ret = body;
}
- cache.clear();
- }
- if( !ret.isNull() ){
- break;
}
}
- if( ret.isNull() ){
- if( changed ){
- if( body.getMetaKind() == kind::metakind::PARAMETERIZED ){
- children.insert( children.begin(), body.getOperator() );
- }
- ret = NodeManager::currentNM()->mkNode( body.getKind(), children );
- }else{
- ret = body;
+
+ //clean up entailed conditions
+ if( body.getKind()==OR || body.getKind()==AND ){
+ for( unsigned j=0; j<body.getNumChildren(); j++ ){
+ removeEntailedCond( currCond, new_cond_children[j], cache );
}
}
+
Trace("quantifiers-rewrite-term-debug2") << "Returning " << ret << " for " << body << std::endl;
cache[body] = ret;
}
+ //do context-independent rewriting
iti = icache.find( ret );
if( iti!=icache.end() ){
return iti->second;
@@ -710,46 +744,60 @@ Node QuantifiersRewriter::computeProcessTerms2( Node body, bool hasPol, bool pol
}
}
}
- }else if( ret.getKind()==INTS_DIVISION_TOTAL || ret.getKind()==INTS_MODULUS_TOTAL ){
- Node num = ret[0];
- Node den = ret[1];
- if(den.isConst()) {
- const Rational& rat = den.getConst<Rational>();
- Assert(!num.isConst());
- if(rat != 0) {
- Node intVar = NodeManager::currentNM()->mkBoundVar(NodeManager::currentNM()->integerType());
- new_vars.push_back( intVar );
- Node cond;
- if(rat > 0) {
- cond = NodeManager::currentNM()->mkNode(kind::AND,
- NodeManager::currentNM()->mkNode(kind::LEQ, NodeManager::currentNM()->mkNode(kind::MULT, den, intVar), num),
- NodeManager::currentNM()->mkNode(kind::LT, num,
- NodeManager::currentNM()->mkNode(kind::MULT, den, NodeManager::currentNM()->mkNode(kind::PLUS, intVar, NodeManager::currentNM()->mkConst(Rational(1))))));
- } else {
- cond = NodeManager::currentNM()->mkNode(kind::AND,
- NodeManager::currentNM()->mkNode(kind::LEQ, NodeManager::currentNM()->mkNode(kind::MULT, den, intVar), num),
- NodeManager::currentNM()->mkNode(kind::LT, num,
- NodeManager::currentNM()->mkNode(kind::MULT, den, NodeManager::currentNM()->mkNode(kind::PLUS, intVar, NodeManager::currentNM()->mkConst(Rational(-1))))));
- }
- new_conds.push_back( cond.negate() );
- if( ret.getKind()==INTS_DIVISION_TOTAL ){
- ret = intVar;
- }else{
- ret = NodeManager::currentNM()->mkNode(kind::MINUS, num, NodeManager::currentNM()->mkNode(kind::MULT, den, intVar));
+ /* ITE lifting
+ if( ret.getKind()==ITE ){
+ TypeNode ite_t = ret[1].getType();
+ if( !ite_t.isBoolean() ){
+ ite_t = TypeNode::leastCommonTypeNode( ite_t, ret[2].getType() );
+ Node ite_v = NodeManager::currentNM()->mkBoundVar(ite_t);
+ new_vars.push_back( ite_v );
+ Node cond = NodeManager::currentNM()->mkNode(kind::ITE, ret[0], ite_v.eqNode( ret[1] ), ite_v.eqNode( ret[2] ) );
+ new_conds.push_back( cond.negate() );
+ ret = ite_v;
+ }
+ */
+ }else if( options::elimExtArithQuant() ){
+ if( ret.getKind()==INTS_DIVISION_TOTAL || ret.getKind()==INTS_MODULUS_TOTAL ){
+ Node num = ret[0];
+ Node den = ret[1];
+ if(den.isConst()) {
+ const Rational& rat = den.getConst<Rational>();
+ Assert(!num.isConst());
+ if(rat != 0) {
+ Node intVar = NodeManager::currentNM()->mkBoundVar(NodeManager::currentNM()->integerType());
+ new_vars.push_back( intVar );
+ Node cond;
+ if(rat > 0) {
+ cond = NodeManager::currentNM()->mkNode(kind::AND,
+ NodeManager::currentNM()->mkNode(kind::LEQ, NodeManager::currentNM()->mkNode(kind::MULT, den, intVar), num),
+ NodeManager::currentNM()->mkNode(kind::LT, num,
+ NodeManager::currentNM()->mkNode(kind::MULT, den, NodeManager::currentNM()->mkNode(kind::PLUS, intVar, NodeManager::currentNM()->mkConst(Rational(1))))));
+ } else {
+ cond = NodeManager::currentNM()->mkNode(kind::AND,
+ NodeManager::currentNM()->mkNode(kind::LEQ, NodeManager::currentNM()->mkNode(kind::MULT, den, intVar), num),
+ NodeManager::currentNM()->mkNode(kind::LT, num,
+ NodeManager::currentNM()->mkNode(kind::MULT, den, NodeManager::currentNM()->mkNode(kind::PLUS, intVar, NodeManager::currentNM()->mkConst(Rational(-1))))));
+ }
+ new_conds.push_back( cond.negate() );
+ if( ret.getKind()==INTS_DIVISION_TOTAL ){
+ ret = intVar;
+ }else{
+ ret = NodeManager::currentNM()->mkNode(kind::MINUS, num, NodeManager::currentNM()->mkNode(kind::MULT, den, intVar));
+ }
}
}
- }
- }else if( ret.getKind()==TO_INTEGER || ret.getKind()==IS_INTEGER ){
- Node intVar = NodeManager::currentNM()->mkBoundVar(NodeManager::currentNM()->integerType());
- new_vars.push_back( intVar );
- new_conds.push_back(NodeManager::currentNM()->mkNode(kind::AND,
- NodeManager::currentNM()->mkNode(kind::LT,
- NodeManager::currentNM()->mkNode(kind::MINUS, ret[0], NodeManager::currentNM()->mkConst(Rational(1))), intVar),
- NodeManager::currentNM()->mkNode(kind::LEQ, intVar, ret[0])).negate());
- if( ret.getKind()==TO_INTEGER ){
- ret = intVar;
- }else{
- ret = ret[0].eqNode( intVar );
+ }else if( ret.getKind()==TO_INTEGER || ret.getKind()==IS_INTEGER ){
+ Node intVar = NodeManager::currentNM()->mkBoundVar(NodeManager::currentNM()->integerType());
+ new_vars.push_back( intVar );
+ new_conds.push_back(NodeManager::currentNM()->mkNode(kind::AND,
+ NodeManager::currentNM()->mkNode(kind::LT,
+ NodeManager::currentNM()->mkNode(kind::MINUS, ret[0], NodeManager::currentNM()->mkConst(Rational(1))), intVar),
+ NodeManager::currentNM()->mkNode(kind::LEQ, intVar, ret[0])).negate());
+ if( ret.getKind()==TO_INTEGER ){
+ ret = intVar;
+ }else{
+ ret = ret[0].eqNode( intVar );
+ }
}
}
icache[prev] = ret;
@@ -782,7 +830,7 @@ bool QuantifiersRewriter::isConditionalVariableElim( Node n, int pol ){
return false;
}
-Node QuantifiersRewriter::computeCondSplit( Node body, Node ipl ){
+Node QuantifiersRewriter::computeCondSplit( Node body, QAttributes& qa ){
if( options::iteDtTesterSplitQuant() && body.getKind()==ITE ){
Trace("quantifiers-rewrite-ite-debug") << "DTT split : " << body << std::endl;
std::map< Node, Node > pcons;
@@ -799,7 +847,8 @@ Node QuantifiersRewriter::computeCondSplit( Node body, Node ipl ){
}
}
if( options::condVarSplitQuant() ){
- if( body.getKind()==ITE || ( body.getKind()==IFF && options::condVarSplitQuantAgg() && !TermDb::isFunDefAnnotation( ipl ) ) ){
+ if( body.getKind()==ITE || ( body.getKind()==IFF && options::condVarSplitQuantAgg() ) ){
+ Assert( !qa.isFunDef() );
Trace("quantifiers-rewrite-debug") << "Conditional var elim split " << body << "?" << std::endl;
bool do_split = false;
unsigned index_max = body.getKind()==ITE ? 0 : 1;
@@ -932,8 +981,7 @@ bool QuantifiersRewriter::computeVariableElimLit( Node lit, bool pol, std::vecto
newChildren.push_back( Node::fromExpr( c.getConstructor() ) );
std::vector< Node > newVars;
for( unsigned j=0; j<c.getNumArgs(); j++ ){
- TypeNode tn = TypeNode::fromType( c[j].getSelector().getType() );
- tn = tn[1];
+ TypeNode tn = TypeNode::fromType( c[j].getRangeType() );
Node v = NodeManager::currentNM()->mkBoundVar( tn );
newChildren.push_back( v );
newVars.push_back( v );
@@ -957,7 +1005,7 @@ bool QuantifiersRewriter::computeVariableElimLit( Node lit, bool pol, std::vecto
return false;
}
-Node QuantifiersRewriter::computeVarElimination2( Node body, std::vector< Node >& args, Node& ipl, std::map< Node, std::vector< int > >& var_parent ){
+Node QuantifiersRewriter::computeVarElimination2( Node body, std::vector< Node >& args, QAttributes& qa, std::map< Node, std::vector< int > >& var_parent ){
Trace("var-elim-quant-debug") << "Compute var elimination for " << body << std::endl;
QuantPhaseReq qpr( body );
std::vector< Node > vars;
@@ -977,15 +1025,15 @@ Node QuantifiersRewriter::computeVarElimination2( Node body, std::vector< Node >
//remake with eliminated nodes
body = body.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
body = Rewriter::rewrite( body );
- if( !ipl.isNull() ){
- ipl = ipl.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
+ if( !qa.d_ipl.isNull() ){
+ qa.d_ipl = qa.d_ipl.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
}
Trace("var-elim-quant") << "Return " << body << std::endl;
}
return body;
}
-Node QuantifiersRewriter::computeVarElimination( Node body, std::vector< Node >& args, Node& ipl ){
+Node QuantifiersRewriter::computeVarElimination( Node body, std::vector< Node >& args, QAttributes& qa ){
//the parent id's for each variable, if using purifyQuant
std::map< Node, std::vector< int > > var_parent;
if( options::purifyQuant() ){
@@ -995,7 +1043,7 @@ Node QuantifiersRewriter::computeVarElimination( Node body, std::vector< Node >&
Node prev;
do{
prev = body;
- body = computeVarElimination2( body, args, ipl, var_parent );
+ body = computeVarElimination2( body, args, qa, var_parent );
}while( prev!=body && !args.empty() );
}
return body;
@@ -1290,13 +1338,13 @@ Node QuantifiersRewriter::computeSplit( Node f, std::vector< Node >& args, Node
return f;
}
-Node QuantifiersRewriter::mkForAll( std::vector< Node >& args, Node body, Node ipl ){
+Node QuantifiersRewriter::mkForAll( std::vector< Node >& args, Node body, QAttributes& qa ){
std::vector< Node > activeArgs;
//if cegqi is on, may be synthesis conjecture, in which case we want to keep all variables
- if( options::ceGuidedInst() && TermDb::isSygusConjectureAnnotation( ipl ) ){
+ if( options::ceGuidedInst() && qa.d_sygus ){
activeArgs.insert( activeArgs.end(), args.begin(), args.end() );
}else{
- computeArgVec2( args, activeArgs, body, ipl );
+ computeArgVec2( args, activeArgs, body, qa.d_ipl );
}
if( activeArgs.empty() ){
return body;
@@ -1304,14 +1352,14 @@ Node QuantifiersRewriter::mkForAll( std::vector< Node >& args, Node body, Node i
std::vector< Node > children;
children.push_back( NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST, activeArgs ) );
children.push_back( body );
- if( !ipl.isNull() ){
- children.push_back( ipl );
+ if( !qa.d_ipl.isNull() ){
+ children.push_back( qa.d_ipl );
}
return NodeManager::currentNM()->mkNode( kind::FORALL, children );
}
}
-Node QuantifiersRewriter::computeMiniscoping( Node f, std::vector< Node >& args, Node body, Node ipl ){
+Node QuantifiersRewriter::computeMiniscoping( Node f, std::vector< Node >& args, Node body, QAttributes& qa ){
if( body.getKind()==FORALL ){
//combine arguments
std::vector< Node > newArgs;
@@ -1319,26 +1367,26 @@ Node QuantifiersRewriter::computeMiniscoping( Node f, std::vector< Node >& args,
newArgs.push_back( body[0][i] );
}
newArgs.insert( newArgs.end(), args.begin(), args.end() );
- return mkForAll( newArgs, body[ 1 ], ipl );
+ return mkForAll( newArgs, body[ 1 ], qa );
}else{
if( body.getKind()==NOT ){
//push not downwards
if( body[0].getKind()==NOT ){
- return computeMiniscoping( f, args, body[0][0], ipl );
+ return computeMiniscoping( f, args, body[0][0], qa );
}else if( body[0].getKind()==AND ){
if( options::miniscopeQuantFreeVar() ){
NodeBuilder<> t(kind::OR);
for( int i=0; i<(int)body[0].getNumChildren(); i++ ){
t << ( body[0][i].getKind()==NOT ? body[0][i][0] : body[0][i].notNode() );
}
- return computeMiniscoping( f, args, t.constructNode(), ipl );
+ return computeMiniscoping( f, args, t.constructNode(), qa );
}
}else if( body[0].getKind()==OR ){
if( options::miniscopeQuant() ){
NodeBuilder<> t(kind::AND);
for( int i=0; i<(int)body[0].getNumChildren(); i++ ){
Node trm = body[0][i].negate();
- t << computeMiniscoping( f, args, trm, ipl );
+ t << computeMiniscoping( f, args, trm, qa );
}
return t.constructNode();
}
@@ -1348,7 +1396,7 @@ Node QuantifiersRewriter::computeMiniscoping( Node f, std::vector< Node >& args,
//break apart
NodeBuilder<> t(kind::AND);
for( unsigned i=0; i<body.getNumChildren(); i++ ){
- t << computeMiniscoping( f, args, body[i], ipl );
+ t << computeMiniscoping( f, args, body[i], qa );
}
Node retVal = t;
return retVal;
@@ -1376,7 +1424,7 @@ Node QuantifiersRewriter::computeMiniscoping( Node f, std::vector< Node >& args,
return body_split;
}else if( body_split.getNumChildren()>0 ){
newBody = tb.getNumChildren()==1 ? tb.getChild( 0 ) : tb;
- body_split << mkForAll( args, newBody, ipl );
+ body_split << mkForAll( args, newBody, qa );
return body_split.getNumChildren()==1 ? body_split.getChild( 0 ) : body_split;
}
}
@@ -1385,7 +1433,7 @@ Node QuantifiersRewriter::computeMiniscoping( Node f, std::vector< Node >& args,
//if( body==f[1] ){
// return f;
//}else{
- return mkForAll( args, body, ipl );
+ return mkForAll( args, body, qa );
//}
}
@@ -1491,101 +1539,96 @@ Node QuantifiersRewriter::computeAggressiveMiniscoping( std::vector< Node >& arg
return n;
}
}
- return mkForAll( args, body, Node::null() );
+ QAttributes qa;
+ return mkForAll( args, body, qa );
}
-bool QuantifiersRewriter::doOperation( Node f, bool isNested, int computeOption ){
+bool QuantifiersRewriter::doOperation( Node q, int computeOption, QAttributes& qa ){
+ bool is_strict_trigger = qa.d_hasPattern && options::userPatternsQuant()==USER_PAT_MODE_TRUST;
+ bool is_std = !qa.d_sygus && !qa.d_quant_elim && !qa.isFunDef() && !is_strict_trigger;
if( computeOption==COMPUTE_ELIM_SYMBOLS ){
return true;
}else if( computeOption==COMPUTE_MINISCOPING ){
- return true;
+ return is_std;
}else if( computeOption==COMPUTE_AGGRESSIVE_MINISCOPING ){
- return options::aggressiveMiniscopeQuant();
+ return options::aggressiveMiniscopeQuant() && is_std;
}else if( computeOption==COMPUTE_NNF ){
- return options::nnfQuant();
+ return true;
}else if( computeOption==COMPUTE_PROCESS_TERMS ){
return true;
//return options::iteLiftQuant()!=ITE_LIFT_QUANT_MODE_NONE || options::iteCondVarSplitQuant();
}else if( computeOption==COMPUTE_COND_SPLIT ){
- return options::iteDtTesterSplitQuant() || options::condVarSplitQuant();
+ return ( options::iteDtTesterSplitQuant() || options::condVarSplitQuant() ) && !is_strict_trigger;
}else if( computeOption==COMPUTE_PRENEX ){
- return options::prenexQuant()!=PRENEX_NONE && !options::aggressiveMiniscopeQuant();
+ return options::prenexQuant()!=PRENEX_NONE && !options::aggressiveMiniscopeQuant() && is_std;
}else if( computeOption==COMPUTE_VAR_ELIMINATION ){
- return options::varElimQuant() || options::dtVarExpandQuant() || options::purifyQuant();
+ return ( options::varElimQuant() || options::dtVarExpandQuant() || options::purifyQuant() ) && is_std;
//}else if( computeOption==COMPUTE_CNF ){
// return options::cnfQuant();
}else if( computeOption==COMPUTE_PURIFY_EXPAND ){
- return options::purifyQuant();
+ return options::purifyQuant() && is_std;
}else{
return false;
}
}
//general method for computing various rewrites
-Node QuantifiersRewriter::computeOperation( Node f, bool isNested, int computeOption ){
- if( f.getKind()==FORALL ){
- Trace("quantifiers-rewrite-debug") << "Compute operation " << computeOption << " on " << f << ", nested = " << isNested << std::endl;
- std::vector< Node > args;
- for( unsigned i=0; i<f[0].getNumChildren(); i++ ){
- args.push_back( f[0][i] );
- }
- Node n = f[1];
- Node ipl;
- if( f.getNumChildren()==3 ){
- ipl = f[2];
- }
- if( computeOption==COMPUTE_ELIM_SYMBOLS ){
- n = computeElimSymbols( n );
- }else if( computeOption==COMPUTE_MINISCOPING ){
- //return directly
- return computeMiniscoping( f, args, n, ipl );
- }else if( computeOption==COMPUTE_AGGRESSIVE_MINISCOPING ){
- return computeAggressiveMiniscoping( args, n );
- }else if( computeOption==COMPUTE_NNF ){
- n = computeNNF( n );
- }else if( computeOption==COMPUTE_PROCESS_TERMS ){
- std::vector< Node > new_conds;
- n = computeProcessTerms( n, args, new_conds, f );
- if( !new_conds.empty() ){
- new_conds.push_back( n );
- n = NodeManager::currentNM()->mkNode( OR, new_conds );
- }
- }else if( computeOption==COMPUTE_COND_SPLIT ){
- n = computeCondSplit( n, ipl );
- }else if( computeOption==COMPUTE_PRENEX ){
- n = computePrenex( n, args, true );
- }else if( computeOption==COMPUTE_VAR_ELIMINATION ){
- n = computeVarElimination( n, args, ipl );
- //}else if( computeOption==COMPUTE_CNF ){
- //n = computeCNF( n, args, defs, false );
- //ipl = Node::null();
- }else if( computeOption==COMPUTE_PURIFY_EXPAND ){
- std::vector< Node > conj;
- computePurifyExpand( n, conj, args, ipl );
- if( !conj.empty() ){
- return conj.size()==1 ? conj[0] : NodeManager::currentNM()->mkNode( AND, conj );
- }else{
- return f;
- }
+Node QuantifiersRewriter::computeOperation( Node f, int computeOption, QAttributes& qa ){
+ Trace("quantifiers-rewrite-debug") << "Compute operation " << computeOption << " on " << f << std::endl;
+ std::vector< Node > args;
+ for( unsigned i=0; i<f[0].getNumChildren(); i++ ){
+ args.push_back( f[0][i] );
+ }
+ Node n = f[1];
+ if( computeOption==COMPUTE_ELIM_SYMBOLS ){
+ n = computeElimSymbols( n );
+ }else if( computeOption==COMPUTE_MINISCOPING ){
+ //return directly
+ return computeMiniscoping( f, args, n, qa );
+ }else if( computeOption==COMPUTE_AGGRESSIVE_MINISCOPING ){
+ return computeAggressiveMiniscoping( args, n );
+ }else if( computeOption==COMPUTE_NNF ){
+ n = computeNNF( n );
+ }else if( computeOption==COMPUTE_PROCESS_TERMS ){
+ std::vector< Node > new_conds;
+ n = computeProcessTerms( n, args, new_conds, f, qa );
+ if( !new_conds.empty() ){
+ new_conds.push_back( n );
+ n = NodeManager::currentNM()->mkNode( OR, new_conds );
}
- Trace("quantifiers-rewrite-debug") << "Compute Operation: return " << n << ", " << args.size() << std::endl;
- if( f[1]==n && args.size()==f[0].getNumChildren() ){
+ }else if( computeOption==COMPUTE_COND_SPLIT ){
+ n = computeCondSplit( n, qa );
+ }else if( computeOption==COMPUTE_PRENEX ){
+ n = computePrenex( n, args, true );
+ }else if( computeOption==COMPUTE_VAR_ELIMINATION ){
+ n = computeVarElimination( n, args, qa );
+ //}else if( computeOption==COMPUTE_CNF ){
+ //n = computeCNF( n, args, defs, false );
+ //ipl = Node::null();
+ }else if( computeOption==COMPUTE_PURIFY_EXPAND ){
+ std::vector< Node > conj;
+ computePurifyExpand( n, conj, args, qa );
+ if( !conj.empty() ){
+ return conj.size()==1 ? conj[0] : NodeManager::currentNM()->mkNode( AND, conj );
+ }else{
return f;
+ }
+ }
+ Trace("quantifiers-rewrite-debug") << "Compute Operation: return " << n << ", " << args.size() << std::endl;
+ if( f[1]==n && args.size()==f[0].getNumChildren() ){
+ return f;
+ }else{
+ if( args.empty() ){
+ return n;
}else{
- if( args.empty() ){
- return n;
- }else{
- std::vector< Node > children;
- children.push_back( NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST, args ) );
- children.push_back( n );
- if( !ipl.isNull() ){
- children.push_back( ipl );
- }
- return NodeManager::currentNM()->mkNode(kind::FORALL, children );
+ std::vector< Node > children;
+ children.push_back( NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST, args ) );
+ children.push_back( n );
+ if( !qa.d_ipl.isNull() && args.size()==f[0].getNumChildren() ){
+ children.push_back( qa.d_ipl );
}
+ return NodeManager::currentNM()->mkNode(kind::FORALL, children );
}
- }else{
- return f;
}
}
@@ -1754,31 +1797,29 @@ Node QuantifiersRewriter::preSkolemizeQuantifiers( Node n, bool polarity, std::v
//check if it contains a quantifier as a subterm
//if so, we will write this node
if( containsQuantifiers( n ) ){
- if( n.getType().isBoolean() ){
- if( n.getKind()==kind::ITE || n.getKind()==kind::IFF || n.getKind()==kind::XOR || n.getKind()==kind::IMPLIES ){
- if( options::preSkolemQuantAgg() ){
- Node nn;
- //must remove structure
- if( n.getKind()==kind::ITE ){
- nn = NodeManager::currentNM()->mkNode( kind::AND,
- NodeManager::currentNM()->mkNode( kind::OR, n[0].notNode(), n[1] ),
- NodeManager::currentNM()->mkNode( kind::OR, n[0], n[2] ) );
- }else if( n.getKind()==kind::IFF || n.getKind()==kind::XOR ){
- nn = NodeManager::currentNM()->mkNode( kind::AND,
- NodeManager::currentNM()->mkNode( kind::OR, n[0].notNode(), n.getKind()==kind::XOR ? n[1].notNode() : n[1] ),
- NodeManager::currentNM()->mkNode( kind::OR, n[0], n.getKind()==kind::XOR ? n[1] : n[1].notNode() ) );
- }else if( n.getKind()==kind::IMPLIES ){
- nn = NodeManager::currentNM()->mkNode( kind::OR, n[0].notNode(), n[1] );
- }
- return preSkolemizeQuantifiers( nn, polarity, fvTypes, fvs );
- }
- }else if( n.getKind()==kind::AND || n.getKind()==kind::OR ){
- vector< Node > children;
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- children.push_back( preSkolemizeQuantifiers( n[i], polarity, fvTypes, fvs ) );
+ if( ( n.getKind()==kind::ITE && n.getType().isBoolean() ) || n.getKind()==kind::IFF ){
+ if( options::preSkolemQuantAgg() ){
+ Node nn;
+ //must remove structure
+ if( n.getKind()==kind::ITE ){
+ nn = NodeManager::currentNM()->mkNode( kind::AND,
+ NodeManager::currentNM()->mkNode( kind::OR, n[0].notNode(), n[1] ),
+ NodeManager::currentNM()->mkNode( kind::OR, n[0], n[2] ) );
+ }else if( n.getKind()==kind::IFF || n.getKind()==kind::XOR ){
+ nn = NodeManager::currentNM()->mkNode( kind::AND,
+ NodeManager::currentNM()->mkNode( kind::OR, n[0].notNode(), n.getKind()==kind::XOR ? n[1].notNode() : n[1] ),
+ NodeManager::currentNM()->mkNode( kind::OR, n[0], n.getKind()==kind::XOR ? n[1] : n[1].notNode() ) );
+ }else if( n.getKind()==kind::IMPLIES ){
+ nn = NodeManager::currentNM()->mkNode( kind::OR, n[0].notNode(), n[1] );
}
- return NodeManager::currentNM()->mkNode( n.getKind(), children );
+ return preSkolemizeQuantifiers( nn, polarity, fvTypes, fvs );
}
+ }else if( n.getKind()==kind::AND || n.getKind()==kind::OR ){
+ vector< Node > children;
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ children.push_back( preSkolemizeQuantifiers( n[i], polarity, fvTypes, fvs ) );
+ }
+ return NodeManager::currentNM()->mkNode( n.getKind(), children );
}
}
}
@@ -1786,15 +1827,20 @@ Node QuantifiersRewriter::preSkolemizeQuantifiers( Node n, bool polarity, std::v
}
Node QuantifiersRewriter::preprocess( Node n, bool isInst ) {
+ Node prev = n;
if( options::preSkolemQuant() ){
if( !isInst || !options::preSkolemQuantNested() ){
- //apply pre-skolemization to existential quantifiers
Trace("quantifiers-preprocess-debug") << "Pre-skolemize " << n << "..." << std::endl;
+ //apply pre-skolemization to existential quantifiers
std::vector< TypeNode > fvTypes;
std::vector< TNode > fvs;
- n = quantifiers::QuantifiersRewriter::preSkolemizeQuantifiers( n, true, fvTypes, fvs );
+ n = quantifiers::QuantifiersRewriter::preSkolemizeQuantifiers( prev, true, fvTypes, fvs );
}
}
+ if( n!=prev ){
+ Trace("quantifiers-preprocess") << "Preprocess " << prev<< std::endl;
+ Trace("quantifiers-preprocess") << "..returned " << n << std::endl;
+ }
return n;
}
@@ -1886,7 +1932,7 @@ Node QuantifiersRewriter::computePurify( Node body, std::vector< Node >& args, s
}
}
-void QuantifiersRewriter::computePurifyExpand( Node body, std::vector< Node >& conj, std::vector< Node >& args, Node ipl ) {
+void QuantifiersRewriter::computePurifyExpand( Node body, std::vector< Node >& conj, std::vector< Node >& args, QAttributes& qa ) {
if( body.getKind()==OR ){
Trace("quantifiers-rewrite-purify-exp") << "Purify expansion : " << body << std::endl;
std::map< int, std::vector< Node > > disj;
diff --git a/src/theory/quantifiers/quantifiers_rewriter.h b/src/theory/quantifiers/quantifiers_rewriter.h
index 47997f9a7..2071d1793 100644
--- a/src/theory/quantifiers/quantifiers_rewriter.h
+++ b/src/theory/quantifiers/quantifiers_rewriter.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file quantifiers_rewriter.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Rewriter for the theory of inductive quantifiers
**
@@ -26,6 +26,8 @@ namespace CVC4 {
namespace theory {
namespace quantifiers {
+class QAttributes;
+
class QuantifiersRewriter {
private:
static int getPurifyIdLit2( Node n, std::map< Node, int >& visited );
@@ -37,7 +39,7 @@ public:
static int getPurifyIdLit( Node n );
private:
static void addNodeToOrBuilder( Node n, NodeBuilder<>& t );
- static Node mkForAll( std::vector< Node >& args, Node body, Node ipl );
+ static Node mkForAll( std::vector< Node >& args, Node body, QAttributes& qa );
static void computeArgs( std::vector< Node >& args, std::map< Node, bool >& activeMap, Node n, std::map< Node, bool >& visited );
static void computeArgVec( std::vector< Node >& args, std::vector< Node >& activeArgs, Node n );
static void computeArgVec2( std::vector< Node >& args, std::vector< Node >& activeArgs, Node n, Node ipl );
@@ -52,21 +54,21 @@ private:
std::map< Node, std::vector< int > >& var_parent );
static Node computePurify2( Node body, std::vector< Node >& args, std::map< Node, Node >& visited, std::map< Node, Node >& var_to_term,
std::map< Node, std::vector< int > >& var_parent, int parentId );
- static Node computeVarElimination2( Node body, std::vector< Node >& args, Node& ipl, std::map< Node, std::vector< int > >& var_parent );
+ static Node computeVarElimination2( Node body, std::vector< Node >& args, QAttributes& qa, std::map< Node, std::vector< int > >& var_parent );
private:
static Node computeElimSymbols( Node body );
- static Node computeMiniscoping( Node f, std::vector< Node >& args, Node body, Node ipl );
+ static Node computeMiniscoping( Node f, std::vector< Node >& args, Node body, QAttributes& qa );
static Node computeAggressiveMiniscoping( std::vector< Node >& args, Node body );
static Node computeNNF( Node body );
//cache is dependent upon currCond, icache is not, new_conds are negated conditions
- static Node computeProcessTerms( Node body, std::vector< Node >& new_vars, std::vector< Node >& new_conds, Node q );
- static Node computeCondSplit( Node body, Node ipl );
+ static Node computeProcessTerms( Node body, std::vector< Node >& new_vars, std::vector< Node >& new_conds, Node q, QAttributes& qa );
+ static Node computeCondSplit( Node body, QAttributes& qa );
static Node computeCNF( Node body, std::vector< Node >& args, NodeBuilder<>& defs, bool forcePred );
static Node computePrenex( Node body, std::vector< Node >& args, bool pol );
static Node computeSplit( Node f, std::vector< Node >& args, Node body );
- static Node computeVarElimination( Node body, std::vector< Node >& args, Node& ipl );
+ static Node computeVarElimination( Node body, std::vector< Node >& args, QAttributes& qa );
static Node computePurify( Node body, std::vector< Node >& args, std::map< Node, std::vector< int > >& var_parent );
- static void computePurifyExpand( Node body, std::vector< Node >& conj, std::vector< Node >& args, Node ipl );
+ static void computePurifyExpand( Node body, std::vector< Node >& conj, std::vector< Node >& args, QAttributes& qa );
private:
enum{
COMPUTE_ELIM_SYMBOLS = 0,
@@ -82,7 +84,7 @@ private:
//COMPUTE_CNF,
COMPUTE_LAST
};
- static Node computeOperation( Node f, bool isNested, int computeOption );
+ static Node computeOperation( Node f, int computeOption, QAttributes& qa );
public:
static RewriteResponse preRewrite(TNode in);
static RewriteResponse postRewrite(TNode in);
@@ -90,7 +92,7 @@ public:
static inline void shutdown() {}
private:
/** options */
- static bool doOperation( Node f, bool isNested, int computeOption );
+ static bool doOperation( Node f, int computeOption, QAttributes& qa );
private:
static Node preSkolemizeQuantifiers(Node n, bool polarity, std::vector< TypeNode >& fvTypes, std::vector<TNode>& fvs);
public:
diff --git a/src/theory/quantifiers/relevant_domain.cpp b/src/theory/quantifiers/relevant_domain.cpp
index 88793358e..b353fce2f 100644
--- a/src/theory/quantifiers/relevant_domain.cpp
+++ b/src/theory/quantifiers/relevant_domain.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file relevant_domain.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of relevant domain class
**/
@@ -82,8 +82,9 @@ RelevantDomain::RDomain * RelevantDomain::getRDomain( Node n, int i, bool getPar
return getParent ? d_rel_doms[n][i]->getParent() : d_rel_doms[n][i];
}
-void RelevantDomain::reset(){
+bool RelevantDomain::reset( Theory::Effort e ) {
d_is_computed = false;
+ return true;
}
void RelevantDomain::compute(){
@@ -94,7 +95,7 @@ void RelevantDomain::compute(){
it2->second->reset();
}
}
- for( int i=0; i<d_model->getNumAssertedQuantifiers(); i++ ){
+ for( unsigned i=0; i<d_model->getNumAssertedQuantifiers(); i++ ){
Node q = d_model->getAssertedQuantifier( i );
Node icf = d_qe->getTermDatabase()->getInstConstantBody( q );
Trace("rel-dom-debug") << "compute relevant domain for " << icf << std::endl;
@@ -140,7 +141,7 @@ void RelevantDomain::compute(){
}
void RelevantDomain::computeRelevantDomain( Node q, Node n, bool hasPol, bool pol ) {
- Node op = d_qe->getTermDatabase()->getOperator( n );
+ Node op = d_qe->getTermDatabase()->getMatchOperator( n );
for( unsigned i=0; i<n.getNumChildren(); i++ ){
if( !op.isNull() ){
RDomain * rf = getRDomain( op, i );
diff --git a/src/theory/quantifiers/relevant_domain.h b/src/theory/quantifiers/relevant_domain.h
index 3ce285bc8..2b90520fd 100644
--- a/src/theory/quantifiers/relevant_domain.h
+++ b/src/theory/quantifiers/relevant_domain.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file relevant_domain.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief relevant domain class
**/
@@ -23,7 +23,7 @@ namespace CVC4 {
namespace theory {
namespace quantifiers {
-class RelevantDomain
+class RelevantDomain : public QuantifiersUtil
{
private:
class RDomain
@@ -62,7 +62,10 @@ private:
public:
RelevantDomain( QuantifiersEngine* qe, FirstOrderModel* m );
virtual ~RelevantDomain(){}
- void reset();
+ /* reset */
+ bool reset( Theory::Effort e );
+ /** identify */
+ std::string identify() const { return "RelevantDomain"; }
//compute the relevant domain
void compute();
diff --git a/src/theory/quantifiers/rewrite_engine.cpp b/src/theory/quantifiers/rewrite_engine.cpp
index 4c8050239..5365dbcfa 100644
--- a/src/theory/quantifiers/rewrite_engine.cpp
+++ b/src/theory/quantifiers/rewrite_engine.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file rewrite_engine.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Rewrite engine module
**
@@ -68,7 +68,7 @@ bool RewriteEngine::needsCheck( Theory::Effort e ){
void RewriteEngine::check( Theory::Effort e, unsigned quant_e ) {
if( quant_e==QuantifiersEngine::QEFFORT_STANDARD ){
- //if( e==Theory::EFFORT_FULL ){
+ Assert( !d_quantEngine->inConflict() );
Trace("rewrite-engine") << "---Rewrite Engine Round, effort = " << e << "---" << std::endl;
//if( e==Theory::EFFORT_LAST_CALL ){
// if( !d_quantEngine->getModel()->isModelSet() ){
@@ -95,7 +95,7 @@ void RewriteEngine::check( Theory::Effort e, unsigned quant_e ) {
//per priority level
int index = 0;
bool success = true;
- while( success && index<(int)d_priority_order.size() ) {
+ while( !d_quantEngine->inConflict() && success && index<(int)d_priority_order.size() ) {
addedLemmas += checkRewriteRule( d_priority_order[index], e );
index++;
if( index<(int)d_priority_order.size() ){
@@ -104,11 +104,6 @@ void RewriteEngine::check( Theory::Effort e, unsigned quant_e ) {
}
Trace("rewrite-engine") << "Finished rewrite engine, added " << addedLemmas << " lemmas." << std::endl;
- if (addedLemmas==0) {
-
- }else{
- //otherwise, the search will continue
- }
}
}
@@ -124,12 +119,13 @@ int RewriteEngine::checkRewriteRule( Node f, Theory::Effort e ) {
std::map< Node, QuantInfo >::iterator it = d_qinfo.find( f );
if( it!=d_qinfo.end() ){
QuantInfo * qi = &it->second;
- if( qi->d_mg->isValid() ){
+ if( qi->matchGeneratorIsValid() ){
Node rr = TermDb::getRewriteRule( f );
Trace("rewrite-engine-inst-debug") << " Reset round..." << std::endl;
qi->reset_round( qcf );
Trace("rewrite-engine-inst-debug") << " Get matches..." << std::endl;
- while( qi->d_mg->getNextMatch( qcf, qi ) && ( addedLemmas==0 || !options::rrOneInstPerRound() ) ){
+ while( !d_quantEngine->inConflict() && qi->getNextMatch( qcf ) &&
+ ( addedLemmas==0 || !options::rrOneInstPerRound() ) ){
Trace("rewrite-engine-inst-debug") << " Got match to complete..." << std::endl;
qi->debugPrintMatch( "rewrite-engine-inst-debug" );
std::vector< int > assigned;
@@ -137,7 +133,7 @@ int RewriteEngine::checkRewriteRule( Node f, Theory::Effort e ) {
bool doContinue = false;
bool success = true;
int tempAddedLemmas = 0;
- while( tempAddedLemmas==0 && success && ( addedLemmas==0 || !options::rrOneInstPerRound() ) ){
+ while( !d_quantEngine->inConflict() && tempAddedLemmas==0 && success && ( addedLemmas==0 || !options::rrOneInstPerRound() ) ){
success = qi->completeMatch( qcf, assigned, doContinue );
doContinue = true;
if( success ){
@@ -158,7 +154,7 @@ int RewriteEngine::checkRewriteRule( Node f, Theory::Effort e ) {
if( inst.size()>f[0].getNumChildren() ){
inst.resize( f[0].getNumChildren() );
}
- if( d_quantEngine->addInstantiation( f, inst, false ) ){
+ if( d_quantEngine->addInstantiation( f, inst ) ){
addedLemmas++;
tempAddedLemmas++;
/*
@@ -289,7 +285,7 @@ void RewriteEngine::registerQuantifier( Node f ) {
//make the quantified formula
d_qinfo_n[f] = NodeManager::currentNM()->mkNode( FORALL, qcfn_c );
Trace("rr-register") << " qcf formula is : " << d_qinfo_n[f] << std::endl;
- d_qinfo[f].initialize( d_qinfo_n[f], d_qinfo_n[f][1] );
+ d_qinfo[f].initialize( qcf, d_qinfo_n[f], d_qinfo_n[f][1] );
}
}
}
diff --git a/src/theory/quantifiers/rewrite_engine.h b/src/theory/quantifiers/rewrite_engine.h
index 6ad76c541..424530696 100644
--- a/src/theory/quantifiers/rewrite_engine.h
+++ b/src/theory/quantifiers/rewrite_engine.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file rewrite_engine.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** [[ Add lengthier description here ]]
** \todo document this file
diff --git a/src/theory/quantifiers/symmetry_breaking.cpp b/src/theory/quantifiers/symmetry_breaking.cpp
index 4c8e24d08..2a2b13583 100644
--- a/src/theory/quantifiers/symmetry_breaking.cpp
+++ b/src/theory/quantifiers/symmetry_breaking.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file symmetry_breaking.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief symmetry breaking module
**
diff --git a/src/theory/quantifiers/symmetry_breaking.h b/src/theory/quantifiers/symmetry_breaking.h
index 43e5ec765..38fea4f45 100644
--- a/src/theory/quantifiers/symmetry_breaking.h
+++ b/src/theory/quantifiers/symmetry_breaking.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file symmetry_breaking.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Pre-process step for first-order reasoning
**/
diff --git a/src/theory/quantifiers/term_database.cpp b/src/theory/quantifiers/term_database.cpp
index 560f68810..8b09d8e5d 100644
--- a/src/theory/quantifiers/term_database.cpp
+++ b/src/theory/quantifiers/term_database.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file term_database.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Francois Bobot
- ** Minor contributors (to current version): Kshitij Bansal, Morgan Deters
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Francois Bobot, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of term databse class
**/
@@ -59,23 +59,27 @@ TNode TermArgTrie::existsTerm( std::vector< TNode >& reps, int argIndex ) {
}
bool TermArgTrie::addTerm( TNode n, std::vector< TNode >& reps, int argIndex ){
+ return addOrGetTerm( n, reps, argIndex )==n;
+}
+
+TNode TermArgTrie::addOrGetTerm( TNode n, std::vector< TNode >& reps, int argIndex ) {
if( argIndex==(int)reps.size() ){
if( d_data.empty() ){
//store n in d_data (this should be interpretted as the "data" and not as a reference to a child)
d_data[n].clear();
- return true;
+ return n;
}else{
- return false;
+ return d_data.begin()->first;
}
}else{
- return d_data[reps[argIndex]].addTerm( n, reps, argIndex+1 );
+ return d_data[reps[argIndex]].addOrGetTerm( n, reps, argIndex+1 );
}
}
void TermArgTrie::debugPrint( const char * c, Node n, unsigned depth ) {
for( std::map< TNode, TermArgTrie >::iterator it = d_data.begin(); it != d_data.end(); ++it ){
- for( unsigned i=0; i<depth; i++ ){ Debug(c) << " "; }
- Debug(c) << it->first << std::endl;
+ for( unsigned i=0; i<depth; i++ ){ Trace(c) << " "; }
+ Trace(c) << it->first << std::endl;
it->second.debugPrint( c, n, depth+1 );
}
}
@@ -107,10 +111,25 @@ Node TermDb::getGroundTerm( Node f, unsigned i ) {
return d_op_map[f][i];
}
-Node TermDb::getOperator( Node n ) {
- //return n.getOperator();
+unsigned TermDb::getNumTypeGroundTerms( TypeNode tn ) {
+ std::map< TypeNode, std::vector< Node > >::iterator it = d_type_map.find( tn );
+ if( it!=d_type_map.end() ){
+ return it->second.size();
+ }else{
+ return 0;
+ }
+}
+
+Node TermDb::getTypeGroundTerm( TypeNode tn, unsigned i ) {
+ Assert( i<d_type_map[tn].size() );
+ return d_type_map[tn][i];
+}
+
+Node TermDb::getMatchOperator( Node n ) {
Kind k = n.getKind();
- if( k==SELECT || k==STORE || k==UNION || k==INTERSECTION || k==SUBSET || k==SETMINUS || k==MEMBER || k==SINGLETON ){
+ //datatype operators may be parametric, always assume they are
+ if( k==SELECT || k==STORE || k==UNION || k==INTERSECTION || k==SUBSET || k==SETMINUS || k==MEMBER || k==SINGLETON ||
+ k==APPLY_SELECTOR_TOTAL || k==APPLY_TESTER ){
//since it is parametric, use a particular one as op
TypeNode tn = n[0].getType();
Node op = n.getOperator();
@@ -144,7 +163,7 @@ void TermDb::addTerm( Node n, std::set< Node >& added, bool withinQuant, bool wi
//if this is an atomic trigger, consider adding it
if( inst::Trigger::isAtomicTrigger( n ) ){
Trace("term-db") << "register term in db " << n << std::endl;
- Node op = getOperator( n );
+ Node op = getMatchOperator( n );
d_op_map[op].push_back( n );
added.insert( n );
@@ -201,116 +220,192 @@ void TermDb::computeUfEqcTerms( TNode f ) {
}
}
-TNode TermDb::evaluateTerm( TNode n, std::map< TNode, TNode >& subs, bool subsRep ) {
- Trace("term-db-eval") << "evaluate term : " << n << std::endl;
- eq::EqualityEngine * ee = d_quantEngine->getTheoryEngine()->getMasterEqualityEngine();
- if( ee->hasTerm( n ) ){
- Trace("term-db-eval") << "...exists in ee, return rep " << std::endl;
- return ee->getRepresentative( n );
- }else if( n.getKind()==BOUND_VARIABLE ){
- Assert( subs.find( n )!=subs.end() );
- Trace("term-db-eval") << "...substitution is : " << subs[n] << std::endl;
- if( subsRep ){
- Assert( ee->hasTerm( subs[n] ) );
- Assert( ee->getRepresentative( subs[n] )==subs[n] );
- return subs[n];
+bool TermDb::inRelevantDomain( TNode f, unsigned i, TNode r ) {
+ Assert( d_quantEngine->getTheoryEngine()->getMasterEqualityEngine()->getRepresentative( r )==r );
+ std::map< Node, std::map< unsigned, std::vector< Node > > >::iterator it = d_func_map_rel_dom.find( f );
+ if( it != d_func_map_rel_dom.end() ){
+ std::map< unsigned, std::vector< Node > >::iterator it2 = it->second.find( i );
+ if( it2!=it->second.end() ){
+ return std::find( it2->second.begin(), it2->second.end(), r )!=it2->second.end();
}else{
- return evaluateTerm( subs[n], subs, subsRep );
+ return false;
}
}else{
- if( n.hasOperator() ){
- TNode f = getOperator( n );
- if( !f.isNull() ){
- std::vector< TNode > args;
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- TNode c = evaluateTerm( n[i], subs, subsRep );
- if( c.isNull() ){
- return TNode::null();
+ return false;
+ }
+}
+
+//return a term n' equivalent to n
+// maximal subterms of n' are representatives in the equality engine qy
+Node TermDb::evaluateTerm2( TNode n, std::map< TNode, Node >& visited, EqualityQuery * qy ) {
+ std::map< TNode, Node >::iterator itv = visited.find( n );
+ if( itv != visited.end() ){
+ return itv->second;
+ }
+ Trace("term-db-eval") << "evaluate term : " << n << std::endl;
+ Node ret;
+ if( n.getKind()==BOUND_VARIABLE ){
+ return n;
+ }else if( !qy->hasTerm( n ) ){
+ //term is not known to be equal to a representative in equality engine, evaluate it
+ if( n.getKind()==FORALL ){
+ ret = Node::null();
+ }else if( n.hasOperator() ){
+ TNode f = getMatchOperator( n );
+ std::vector< TNode > args;
+ bool ret_set = false;
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ TNode c = evaluateTerm2( n[i], visited, qy );
+ if( c.isNull() ){
+ ret = Node::null();
+ ret_set = true;
+ break;
+ }else if( c==d_true || c==d_false ){
+ //short-circuiting
+ if( ( n.getKind()==kind::AND && c==d_false ) || ( n.getKind()==kind::OR && c==d_true ) ){
+ ret = c;
+ ret_set = true;
+ break;
+ }else if( n.getKind()==kind::ITE && i==0 ){
+ ret = evaluateTerm2( n[ c==d_true ? 1 : 2], visited, qy );
+ ret_set = true;
+ break;
}
- Trace("term-db-eval") << "Got child : " << c << std::endl;
- args.push_back( c );
}
- Trace("term-db-eval") << "Get term from DB" << std::endl;
- TNode nn = d_func_map_trie[f].existsTerm( args );
- Trace("term-db-eval") << "Got term " << nn << std::endl;
- if( !nn.isNull() ){
- if( ee->hasTerm( nn ) ){
- Trace("term-db-eval") << "return rep " << std::endl;
- return ee->getRepresentative( nn );
- }else{
- //Assert( false );
+ Trace("term-db-eval") << " child " << i << " : " << c << std::endl;
+ args.push_back( c );
+ }
+ if( !ret_set ){
+ //if it is an indexed term, return the congruent term
+ if( !f.isNull() ){
+ TNode nn = qy->getCongruentTerm( f, args );
+ Trace("term-db-eval") << " got congruent term " << nn << " from DB for " << n << std::endl;
+ if( !nn.isNull() ){
+ ret = qy->getRepresentative( nn );
+ Trace("term-db-eval") << "return rep" << std::endl;
+ ret_set = true;
+ Assert( !ret.isNull() );
}
}
+ if( !ret_set ){
+ Trace("term-db-eval") << "return rewrite" << std::endl;
+ //a theory symbol or a new UF term
+ if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){
+ args.insert( args.begin(), n.getOperator() );
+ }
+ ret = NodeManager::currentNM()->mkNode( n.getKind(), args );
+ ret = Rewriter::rewrite( ret );
+ }
}
}
- return TNode::null();
+ }else{
+ Trace("term-db-eval") << "...exists in ee, return rep" << std::endl;
+ ret = qy->getRepresentative( n );
}
+ Trace("term-db-eval") << "evaluated term : " << n << ", got : " << ret << std::endl;
+ visited[n] = ret;
+ return ret;
}
-TNode TermDb::evaluateTerm( TNode n ) {
- eq::EqualityEngine * ee = d_quantEngine->getTheoryEngine()->getMasterEqualityEngine();
- if( ee->hasTerm( n ) ){
- return ee->getRepresentative( n );
- }else if( n.getKind()!=BOUND_VARIABLE ){
+
+TNode TermDb::getEntailedTerm2( TNode n, std::map< TNode, TNode >& subs, bool subsRep, bool hasSubs, EqualityQuery * qy ) {
+ Assert( !qy->extendsEngine() );
+ Trace("term-db-entail") << "get entailed term : " << n << std::endl;
+ if( qy->getEngine()->hasTerm( n ) ){
+ Trace("term-db-entail") << "...exists in ee, return rep " << std::endl;
+ return n;
+ }else if( n.getKind()==BOUND_VARIABLE ){
+ if( hasSubs ){
+ Assert( subs.find( n )!=subs.end() );
+ Trace("term-db-entail") << "...substitution is : " << subs[n] << std::endl;
+ if( subsRep ){
+ Assert( qy->getEngine()->hasTerm( subs[n] ) );
+ Assert( qy->getEngine()->getRepresentative( subs[n] )==subs[n] );
+ return subs[n];
+ }else{
+ return getEntailedTerm2( subs[n], subs, subsRep, hasSubs, qy );
+ }
+ }
+ }else if( n.getKind()==ITE ){
+ for( unsigned i=0; i<2; i++ ){
+ if( isEntailed2( n[0], subs, subsRep, hasSubs, i==0, qy ) ){
+ return getEntailedTerm2( n[ i==0 ? 1 : 2 ], subs, subsRep, hasSubs, qy );
+ }
+ }
+ }else{
if( n.hasOperator() ){
- TNode f = getOperator( n );
+ TNode f = getMatchOperator( n );
if( !f.isNull() ){
std::vector< TNode > args;
for( unsigned i=0; i<n.getNumChildren(); i++ ){
- TNode c = evaluateTerm( n[i] );
+ TNode c = getEntailedTerm2( n[i], subs, subsRep, hasSubs, qy );
if( c.isNull() ){
return TNode::null();
}
+ c = qy->getEngine()->getRepresentative( c );
+ Trace("term-db-entail") << " child " << i << " : " << c << std::endl;
args.push_back( c );
}
- TNode nn = d_func_map_trie[f].existsTerm( args );
- if( !nn.isNull() ){
- if( ee->hasTerm( nn ) ){
- return ee->getRepresentative( nn );
- }else{
- //Assert( false );
- }
- }
+ TNode nn = qy->getCongruentTerm( f, args );
+ Trace("term-db-entail") << " got congruent term " << nn << " for " << n << std::endl;
+ return nn;
}
}
}
return TNode::null();
}
-bool TermDb::isEntailed( TNode n, std::map< TNode, TNode >& subs, bool subsRep, bool pol ) {
- Trace("term-db-eval") << "Check entailed : " << n << ", pol = " << pol << std::endl;
+Node TermDb::evaluateTerm( TNode n, EqualityQuery * qy ) {
+ if( qy==NULL ){
+ qy = d_quantEngine->getEqualityQuery();
+ }
+ std::map< TNode, Node > visited;
+ return evaluateTerm2( n, visited, qy );
+}
+
+TNode TermDb::getEntailedTerm( TNode n, std::map< TNode, TNode >& subs, bool subsRep, EqualityQuery * qy ) {
+ if( qy==NULL ){
+ qy = d_quantEngine->getEqualityQuery();
+ }
+ return getEntailedTerm2( n, subs, subsRep, true, qy );
+}
+
+TNode TermDb::getEntailedTerm( TNode n, EqualityQuery * qy ) {
+ if( qy==NULL ){
+ qy = d_quantEngine->getEqualityQuery();
+ }
+ std::map< TNode, TNode > subs;
+ return getEntailedTerm2( n, subs, false, false, qy );
+}
+
+bool TermDb::isEntailed2( TNode n, std::map< TNode, TNode >& subs, bool subsRep, bool hasSubs, bool pol, EqualityQuery * qy ) {
+ Assert( !qy->extendsEngine() );
+ Trace("term-db-entail") << "Check entailed : " << n << ", pol = " << pol << std::endl;
Assert( n.getType().isBoolean() );
if( n.getKind()==EQUAL ){
- TNode n1 = evaluateTerm( n[0], subs, subsRep );
+ TNode n1 = getEntailedTerm2( n[0], subs, subsRep, hasSubs, qy );
if( !n1.isNull() ){
- TNode n2 = evaluateTerm( n[1], subs, subsRep );
+ TNode n2 = getEntailedTerm2( n[1], subs, subsRep, hasSubs, qy );
if( !n2.isNull() ){
- eq::EqualityEngine * ee = d_quantEngine->getTheoryEngine()->getMasterEqualityEngine();
- Assert( ee->hasTerm( n1 ) );
- Assert( ee->hasTerm( n2 ) );
- if( pol ){
- return n1==n2 || ee->areEqual( n1, n2 );
+ if( n1==n2 ){
+ return pol;
}else{
- return n1!=n2 && ee->areDisequal( n1, n2, false );
+ Assert( qy->getEngine()->hasTerm( n1 ) );
+ Assert( qy->getEngine()->hasTerm( n2 ) );
+ if( pol ){
+ return qy->getEngine()->areEqual( n1, n2 );
+ }else{
+ return qy->getEngine()->areDisequal( n1, n2, false );
+ }
}
}
}
- }else if( n.getKind()==APPLY_UF ){
- TNode n1 = evaluateTerm( n, subs, subsRep );
- if( !n1.isNull() ){
- eq::EqualityEngine * ee = d_quantEngine->getTheoryEngine()->getMasterEqualityEngine();
- Assert( ee->hasTerm( n1 ) );
- TNode n2 = pol ? d_true : d_false;
- if( ee->hasTerm( n2 ) ){
- return ee->areEqual( n1, n2 );
- }
- }
}else if( n.getKind()==NOT ){
- return isEntailed( n[0], subs, subsRep, !pol );
+ return isEntailed2( n[0], subs, subsRep, hasSubs, !pol, qy );
}else if( n.getKind()==OR || n.getKind()==AND ){
bool simPol = ( pol && n.getKind()==OR ) || ( !pol && n.getKind()==AND );
for( unsigned i=0; i<n.getNumChildren(); i++ ){
- if( isEntailed( n[i], subs, subsRep, pol ) ){
+ if( isEntailed2( n[i], subs, subsRep, hasSubs, pol, qy ) ){
if( simPol ){
return true;
}
@@ -323,16 +418,45 @@ bool TermDb::isEntailed( TNode n, std::map< TNode, TNode >& subs, bool subsRep,
return !simPol;
}else if( n.getKind()==IFF || n.getKind()==ITE ){
for( unsigned i=0; i<2; i++ ){
- if( isEntailed( n[0], subs, subsRep, i==0 ) ){
+ if( isEntailed2( n[0], subs, subsRep, hasSubs, i==0, qy ) ){
unsigned ch = ( n.getKind()==IFF || i==0 ) ? 1 : 2;
bool reqPol = ( n.getKind()==ITE || i==0 ) ? pol : !pol;
- return isEntailed( n[ch], subs, subsRep, reqPol );
+ return isEntailed2( n[ch], subs, subsRep, hasSubs, reqPol, qy );
+ }
+ }
+ }else if( n.getKind()==APPLY_UF ){
+ TNode n1 = getEntailedTerm2( n, subs, subsRep, hasSubs, qy );
+ if( !n1.isNull() ){
+ Assert( qy->hasTerm( n1 ) );
+ if( n1==d_true ){
+ return pol;
+ }else if( n1==d_false ){
+ return !pol;
+ }else{
+ return qy->getEngine()->getRepresentative( n1 ) == ( pol ? d_true : d_false );
}
}
}
return false;
}
+bool TermDb::isEntailed( TNode n, bool pol, EqualityQuery * qy ) {
+ if( qy==NULL ){
+ Assert( d_consistent_ee );
+ qy = d_quantEngine->getEqualityQuery();
+ }
+ std::map< TNode, TNode > subs;
+ return isEntailed2( n, subs, false, false, pol, qy );
+}
+
+bool TermDb::isEntailed( TNode n, std::map< TNode, TNode >& subs, bool subsRep, bool pol, EqualityQuery * qy ) {
+ if( qy==NULL ){
+ Assert( d_consistent_ee );
+ qy = d_quantEngine->getEqualityQuery();
+ }
+ return isEntailed2( n, subs, subsRep, true, pol, qy );
+}
+
bool TermDb::hasTermCurrent( Node n, bool useMode ) {
if( !useMode ){
return d_has_map.find( n )!=d_has_map.end();
@@ -431,7 +555,7 @@ void TermDb::presolve() {
}
}
-void TermDb::reset( Theory::Effort effort ){
+bool TermDb::reset( Theory::Effort effort ){
int nonCongruentCount = 0;
int congruentCount = 0;
int alreadyCongruentCount = 0;
@@ -440,6 +564,8 @@ void TermDb::reset( Theory::Effort effort ){
d_arg_reps.clear();
d_func_map_trie.clear();
d_func_map_eqc_trie.clear();
+ d_func_map_rel_dom.clear();
+ d_consistent_ee = true;
eq::EqualityEngine* ee = d_quantEngine->getMasterEqualityEngine();
//compute has map
@@ -480,7 +606,13 @@ void TermDb::reset( Theory::Effort effort ){
}
}
}
-
+ //explicitly add inst closure terms to the equality engine to ensure only EE terms are indexed
+ for( std::hash_set< Node, NodeHashFunction >::iterator it = d_iclosure_processed.begin(); it !=d_iclosure_processed.end(); ++it ){
+ Node n = *it;
+ if( !ee->hasTerm( n ) ){
+ ee->addTerm( n );
+ }
+ }
//rebuild d_func/pred_map_trie for each operation, this will calculate all congruent terms
for( std::map< Node, std::vector< Node > >::iterator it = d_op_map.begin(); it != d_op_map.end(); ++it ){
@@ -488,32 +620,58 @@ void TermDb::reset( Theory::Effort effort ){
Trace("term-db-debug") << "Adding terms for operator " << it->first << std::endl;
for( unsigned i=0; i<it->second.size(); i++ ){
Node n = it->second[i];
- //to be added to term index, term must be relevant, and either exist in EE or be an inst closure term
- if( hasTermCurrent( n ) && ( ee->hasTerm( n ) || d_iclosure_processed.find( n )!=d_iclosure_processed.end() ) ){
+ //to be added to term index, term must be relevant, and exist in EE
+ if( hasTermCurrent( n ) && ee->hasTerm( n ) ){
if( !n.getAttribute(NoMatchAttribute()) ){
if( options::finiteModelFind() ){
computeModelBasisArgAttribute( n );
}
computeArgReps( n );
- if( Trace.isOn("term-db-debug") ){
- Trace("term-db-debug") << "Adding term " << n << " with arg reps : ";
- for( unsigned i=0; i<d_arg_reps[n].size(); i++ ){
- Trace("term-db-debug") << d_arg_reps[n] << " ";
+ Trace("term-db-debug") << "Adding term " << n << " with arg reps : ";
+ for( unsigned i=0; i<d_arg_reps[n].size(); i++ ){
+ Trace("term-db-debug") << d_arg_reps[n][i] << " ";
+ if( std::find( d_func_map_rel_dom[it->first][i].begin(),
+ d_func_map_rel_dom[it->first][i].end(), d_arg_reps[n][i] ) == d_func_map_rel_dom[it->first][i].end() ){
+ d_func_map_rel_dom[it->first][i].push_back( d_arg_reps[n][i] );
}
- Trace("term-db-debug") << std::endl;
}
-
- if( !d_func_map_trie[ it->first ].addTerm( n, d_arg_reps[n] ) ){
+ Trace("term-db-debug") << std::endl;
+ if( ee->hasTerm( n ) ){
+ Trace("term-db-debug") << " and value : " << ee->getRepresentative( n ) << std::endl;
+ }
+ Node at = d_func_map_trie[ it->first ].addOrGetTerm( n, d_arg_reps[n] );
+ if( at!=n && ee->areEqual( at, n ) ){
NoMatchAttribute nma;
n.setAttribute(nma,true);
Trace("term-db-debug") << n << " is redundant." << std::endl;
congruentCount++;
}else{
+ if( at!=n && ee->areDisequal( at, n, false ) ){
+ std::vector< Node > lits;
+ lits.push_back( NodeManager::currentNM()->mkNode( at.getType().isBoolean() ? IFF : EQUAL, at, n ) );
+ for( unsigned i=0; i<at.getNumChildren(); i++ ){
+ if( at[i]!=n[i] ){
+ lits.push_back( NodeManager::currentNM()->mkNode( at[i].getType().isBoolean() ? IFF : EQUAL, at[i], n[i] ).negate() );
+ }
+ }
+ Node lem = lits.size()==1 ? lits[0] : NodeManager::currentNM()->mkNode( OR, lits );
+ if( Trace.isOn("term-db-lemma") ){
+ Trace("term-db-lemma") << "Disequal congruent terms : " << at << " " << n << "!!!!" << std::endl;
+ if( !d_quantEngine->getTheoryEngine()->needCheck() ){
+ Trace("term-db-lemma") << " all theories passed with no lemmas." << std::endl;
+ }
+ Trace("term-db-lemma") << " add lemma : " << lem << std::endl;
+ }
+ d_quantEngine->addLemma( lem );
+ d_consistent_ee = false;
+ return false;
+ }
nonCongruentCount++;
d_op_nonred_count[ it->first ]++;
}
}else{
+ Trace("term-db-debug") << n << " is already redundant." << std::endl;
congruentCount++;
alreadyCongruentCount++;
}
@@ -526,15 +684,16 @@ void TermDb::reset( Theory::Effort effort ){
Trace("term-db-stats") << "TermDb: Reset" << std::endl;
Trace("term-db-stats") << "Non-Congruent/Congruent/Non-Relevant = ";
Trace("term-db-stats") << nonCongruentCount << " / " << congruentCount << " (" << alreadyCongruentCount << ") / " << nonRelevantCount << std::endl;
- if( Debug.isOn("term-db") ){
- Debug("term-db") << "functions : " << std::endl;
+ if( Trace.isOn("term-db-index") ){
+ Trace("term-db-index") << "functions : " << std::endl;
for( std::map< Node, std::vector< Node > >::iterator it = d_op_map.begin(); it != d_op_map.end(); ++it ){
if( it->second.size()>0 ){
- Debug("term-db") << "- " << it->first << std::endl;
- d_func_map_trie[ it->first ].debugPrint("term-db", it->second[0]);
+ Trace("term-db-index") << "- " << it->first << std::endl;
+ d_func_map_trie[ it->first ].debugPrint("term-db-index", it->second[0]);
}
}
}
+ return true;
}
TermArgTrie * TermDb::getTermArgTrie( Node f ) {
@@ -565,11 +724,15 @@ TermArgTrie * TermDb::getTermArgTrie( Node eqc, Node f ) {
}
}
-TNode TermDb::existsTerm( Node f, Node n ) {
+TNode TermDb::getCongruentTerm( Node f, Node n ) {
computeArgReps( n );
return d_func_map_trie[f].existsTerm( d_arg_reps[n] );
}
+TNode TermDb::getCongruentTerm( Node f, std::vector< TNode >& args ) {
+ return d_func_map_trie[f].existsTerm( args );
+}
+
Node TermDb::getModelBasisTerm( TypeNode tn, int i ){
if( d_model_basis_term.find( tn )==d_model_basis_term.end() ){
Node mbt;
@@ -800,10 +963,10 @@ Node TermDb::getInstantiationConstant( Node q, int i ) const {
}
/** get number of instantiation constants for q */
-int TermDb::getNumInstantiationConstants( Node q ) const {
+unsigned TermDb::getNumInstantiationConstants( Node q ) const {
std::map< Node, std::vector< Node > >::const_iterator it = d_inst_constants.find( q );
if( it!=d_inst_constants.end() ){
- return (int)it->second.size();
+ return it->second.size();
}else{
return 0;
}
@@ -853,14 +1016,29 @@ Node TermDb::getInstantiatedNode( Node n, Node q, std::vector< Node >& terms ) {
}
-void getSelfSel( const DatatypeConstructor& dc, Node n, TypeNode ntn, std::vector< Node >& selfSel ){
+void getSelfSel( const Datatype& dt, const DatatypeConstructor& dc, Node n, TypeNode ntn, std::vector< Node >& selfSel ){
+ TypeNode tspec;
+ if( dt.isParametric() ){
+ tspec = TypeNode::fromType( dc.getSpecializedConstructorType(n.getType().toType()) );
+ Trace("sk-ind-debug") << "Specialized constructor type : " << tspec << std::endl;
+ Assert( tspec.getNumChildren()==dc.getNumArgs() );
+ }
+ Trace("sk-ind-debug") << "Check self sel " << dc.getName() << " " << dt.getName() << std::endl;
for( unsigned j=0; j<dc.getNumArgs(); j++ ){
- TypeNode tn = TypeNode::fromType( ((SelectorType)dc[j].getSelector().getType()).getRangeType() );
std::vector< Node > ssc;
- if( tn==ntn ){
- ssc.push_back( n );
+ if( dt.isParametric() ){
+ Trace("sk-ind-debug") << "Compare " << tspec[j] << " " << ntn << std::endl;
+ if( tspec[j]==ntn ){
+ ssc.push_back( n );
+ }
+ }else{
+ TypeNode tn = TypeNode::fromType( dc[j].getRangeType() );
+ Trace("sk-ind-debug") << "Compare " << tn << " " << ntn << std::endl;
+ if( tn==ntn ){
+ ssc.push_back( n );
+ }
}
- /* TODO
+ /* TODO: more than weak structural induction
else if( datatypes::DatatypesRewriter::isTypeDatatype( tn ) && std::find( visited.begin(), visited.end(), tn )==visited.end() ){
visited.push_back( tn );
const Datatype& dt = ((DatatypeType)(subs[0].getType()).toType()).getDatatype();
@@ -938,7 +1116,7 @@ Node TermDb::mkSkolemizedBody( Node f, Node n, std::vector< TypeNode >& argTypes
std::vector< Node > disj;
for( unsigned i=0; i<dt.getNumConstructors(); i++ ){
std::vector< Node > selfSel;
- getSelfSel( dt[i], k, tn, selfSel );
+ getSelfSel( dt, dt[i], k, tn, selfSel );
std::vector< Node > conj;
conj.push_back( NodeManager::currentNM()->mkNode( APPLY_TESTER, Node::fromExpr( dt[i].getTester() ), k ).negate() );
for( unsigned j=0; j<selfSel.size(); j++ ){
@@ -1050,7 +1228,7 @@ bool TermDb::isClosedEnumerableType( TypeNode tn ) {
const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
for( unsigned i=0; i<dt.getNumConstructors(); i++ ){
for( unsigned j=0; j<dt[i].getNumArgs(); j++ ){
- TypeNode ctn = TypeNode::fromType( ((SelectorType)dt[i][j].getSelector().getType()).getRangeType() );
+ TypeNode ctn = TypeNode::fromType( dt[i][j].getRangeType() );
if( tn!=ctn && !isClosedEnumerableType( ctn ) ){
ret = false;
break;
@@ -1585,7 +1763,7 @@ bool TermDb::containsVtsInfinity( Node n, bool isFree ) {
return containsTerms( n, t );
}
-Node TermDb::mkNodeType( Node n, TypeNode tn ) {
+Node TermDb::ensureType( Node n, TypeNode tn ) {
TypeNode ntn = n.getType();
Assert( ntn.isComparableTo( tn ) );
if( ntn.isSubtypeOf( tn ) ){
@@ -1598,6 +1776,20 @@ Node TermDb::mkNodeType( Node n, TypeNode tn ) {
}
}
+bool TermDb::getEnsureTypeCondition( Node n, TypeNode tn, std::vector< Node >& cond ) {
+ TypeNode ntn = n.getType();
+ Assert( ntn.isComparableTo( tn ) );
+ if( !ntn.isSubtypeOf( tn ) ){
+ if( tn.isInteger() ){
+ cond.push_back( NodeManager::currentNM()->mkNode( IS_INTEGER, n ) );
+ return true;
+ }
+ return false;
+ }else{
+ return true;
+ }
+}
+
bool TermDb::containsTerm2( Node n, Node t, std::map< Node, bool >& visited ) {
if( n==t ){
return true;
@@ -1630,20 +1822,6 @@ bool TermDb::containsTerms2( Node n, std::vector< Node >& t, std::map< Node, boo
return false;
}
-bool TermDb::containsUninterpretedConstant2( Node n, std::map< Node, bool >& visited ) {
- if( n.getKind()==UNINTERPRETED_CONSTANT ){
- return true;
- }else if( visited.find( n )==visited.end() ){
- visited[n] = true;
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- if( containsUninterpretedConstant2( n[i], visited ) ){
- return true;
- }
- }
- }
- return false;
-}
-
bool TermDb::containsTerm( Node n, Node t ) {
std::map< Node, bool > visited;
return containsTerm2( n, t, visited );
@@ -1658,9 +1836,38 @@ bool TermDb::containsTerms( Node n, std::vector< Node >& t ) {
}
}
+int TermDb::getTermDepth( Node n ) {
+ if (!n.hasAttribute(TermDepthAttribute()) ){
+ int maxDepth = -1;
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ int depth = getTermDepth( n[i] );
+ if( depth>maxDepth ){
+ maxDepth = depth;
+ }
+ }
+ TermDepthAttribute tda;
+ n.setAttribute(tda,1+maxDepth);
+ }
+ return n.getAttribute(TermDepthAttribute());
+}
+
bool TermDb::containsUninterpretedConstant( Node n ) {
- std::map< Node, bool > visited;
- return containsUninterpretedConstant2( n, visited );
+ if (!n.hasAttribute(ContainsUConstAttribute()) ){
+ bool ret = false;
+ if( n.getKind()==UNINTERPRETED_CONSTANT ){
+ ret = true;
+ }else{
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ if( containsUninterpretedConstant( n[i] ) ){
+ ret = true;
+ break;
+ }
+ }
+ }
+ ContainsUConstAttribute cuca;
+ n.setAttribute(cuca, ret ? 1 : 0);
+ }
+ return n.getAttribute(ContainsUConstAttribute())!=0;
}
Node TermDb::simpleNegate( Node n ){
@@ -1787,69 +1994,109 @@ bool TermDb::isSygusConjectureAnnotation( Node ipl ){
return false;
}
+bool TermDb::isQuantElimAnnotation( Node ipl ) {
+ if( !ipl.isNull() ){
+ for( unsigned i=0; i<ipl.getNumChildren(); i++ ){
+ if( ipl[i].getKind()==INST_ATTRIBUTE ){
+ Node avar = ipl[i][0];
+ if( avar.getAttribute(QuantElimAttribute()) ){
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
void TermDb::computeAttributes( Node q ) {
+ computeQuantAttributes( q, d_qattr[q] );
+ if( !d_qattr[q].d_rr.isNull() ){
+ if( d_quantEngine->getRewriteEngine()==NULL ){
+ Trace("quant-warn") << "WARNING : rewrite engine is null, and we have : " << q << std::endl;
+ }
+ //set rewrite engine as owner
+ d_quantEngine->setOwner( q, d_quantEngine->getRewriteEngine(), 2 );
+ }
+ if( d_qattr[q].isFunDef() ){
+ Node f = d_qattr[q].d_fundef_f;
+ if( d_fun_defs.find( f )!=d_fun_defs.end() ){
+ Message() << "Cannot define function " << f << " more than once." << std::endl;
+ exit( 1 );
+ }
+ d_fun_defs[f] = true;
+ d_quantEngine->setOwner( q, d_quantEngine->getFunDefEngine(), 2 );
+ }
+ if( d_qattr[q].d_sygus ){
+ if( d_quantEngine->getCegInstantiation()==NULL ){
+ Trace("quant-warn") << "WARNING : ceg instantiation is null, and we have : " << q << std::endl;
+ }
+ d_quantEngine->setOwner( q, d_quantEngine->getCegInstantiation(), 2 );
+ }
+ if( d_qattr[q].d_synthesis ){
+ if( d_quantEngine->getCegInstantiation()==NULL ){
+ Trace("quant-warn") << "WARNING : ceg instantiation is null, and we have : " << q << std::endl;
+ }
+ d_quantEngine->setOwner( q, d_quantEngine->getCegInstantiation(), 2 );
+ }
+}
+
+void TermDb::computeQuantAttributes( Node q, QAttributes& qa ){
Trace("quant-attr-debug") << "Compute attributes for " << q << std::endl;
if( q.getNumChildren()==3 ){
+ qa.d_ipl = q[2];
for( unsigned i=0; i<q[2].getNumChildren(); i++ ){
Trace("quant-attr-debug") << "Check : " << q[2][i] << " " << q[2][i].getKind() << std::endl;
- if( q[2][i].getKind()==INST_ATTRIBUTE ){
+ if( q[2][i].getKind()==INST_PATTERN || q[2][i].getKind()==INST_NO_PATTERN ){
+ qa.d_hasPattern = true;
+ }else if( q[2][i].getKind()==INST_ATTRIBUTE ){
Node avar = q[2][i][0];
if( avar.getAttribute(AxiomAttribute()) ){
Trace("quant-attr") << "Attribute : axiom : " << q << std::endl;
- d_qattr_axiom[q] = true;
+ qa.d_axiom = true;
}
if( avar.getAttribute(ConjectureAttribute()) ){
Trace("quant-attr") << "Attribute : conjecture : " << q << std::endl;
- d_qattr_conjecture[q] = true;
+ qa.d_conjecture = true;
}
if( avar.getAttribute(FunDefAttribute()) ){
Trace("quant-attr") << "Attribute : function definition : " << q << std::endl;
- d_qattr_fundef[q] = true;
//get operator directly from pattern
- Node f = q[2][i][0].getOperator();
- if( d_fun_defs.find( f )!=d_fun_defs.end() ){
- Message() << "Cannot define function " << f << " more than once." << std::endl;
- exit( 0 );
- }
- d_fun_defs[f] = true;
- d_quantEngine->setOwner( q, d_quantEngine->getFunDefEngine() );
+ qa.d_fundef_f = q[2][i][0].getOperator();
}
if( avar.getAttribute(SygusAttribute()) ){
//not necessarily nested existential
//Assert( q[1].getKind()==NOT );
//Assert( q[1][0].getKind()==FORALL );
-
Trace("quant-attr") << "Attribute : sygus : " << q << std::endl;
- d_qattr_sygus[q] = true;
- if( d_quantEngine->getCegInstantiation()==NULL ){
- Trace("quant-warn") << "WARNING : ceg instantiation is null, and we have : " << q << std::endl;
- }
- d_quantEngine->setOwner( q, d_quantEngine->getCegInstantiation() );
+ qa.d_sygus = true;
}
if( avar.getAttribute(SynthesisAttribute()) ){
Trace("quant-attr") << "Attribute : synthesis : " << q << std::endl;
- d_qattr_synthesis[q] = true;
- if( d_quantEngine->getCegInstantiation()==NULL ){
- Trace("quant-warn") << "WARNING : ceg instantiation is null, and we have : " << q << std::endl;
- }
- d_quantEngine->setOwner( q, d_quantEngine->getCegInstantiation() );
+ qa.d_synthesis = true;
}
if( avar.hasAttribute(QuantInstLevelAttribute()) ){
- d_qattr_qinstLevel[q] = avar.getAttribute(QuantInstLevelAttribute());
- Trace("quant-attr") << "Attribute : quant inst level " << d_qattr_qinstLevel[q] << " : " << q << std::endl;
+ qa.d_qinstLevel = avar.getAttribute(QuantInstLevelAttribute());
+ Trace("quant-attr") << "Attribute : quant inst level " << qa.d_qinstLevel << " : " << q << std::endl;
}
if( avar.hasAttribute(RrPriorityAttribute()) ){
- d_qattr_rr_priority[q] = avar.getAttribute(RrPriorityAttribute());
- Trace("quant-attr") << "Attribute : rr priority " << d_qattr_rr_priority[q] << " : " << q << std::endl;
+ qa.d_rr_priority = avar.getAttribute(RrPriorityAttribute());
+ Trace("quant-attr") << "Attribute : rr priority " << qa.d_rr_priority << " : " << q << std::endl;
+ }
+ if( avar.getAttribute(QuantElimAttribute()) ){
+ Trace("quant-attr") << "Attribute : quantifier elimination : " << q << std::endl;
+ qa.d_quant_elim = true;
+ //don't set owner, should happen naturally
+ }
+ if( avar.getAttribute(QuantElimPartialAttribute()) ){
+ Trace("quant-attr") << "Attribute : quantifier elimination partial : " << q << std::endl;
+ qa.d_quant_elim = true;
+ qa.d_quant_elim_partial = true;
+ //don't set owner, should happen naturally
}
if( avar.getKind()==REWRITE_RULE ){
Trace("quant-attr") << "Attribute : rewrite rule : " << q << std::endl;
Assert( i==0 );
- if( d_quantEngine->getRewriteEngine()==NULL ){
- Trace("quant-warn") << "WARNING : rewrite engine is null, and we have : " << q << std::endl;
- }
- //set rewrite engine as owner
- d_quantEngine->setOwner( q, d_quantEngine->getRewriteEngine() );
+ qa.d_rr = avar;
}
}
}
@@ -1857,69 +2104,85 @@ void TermDb::computeAttributes( Node q ) {
}
bool TermDb::isQAttrConjecture( Node q ) {
- std::map< Node, bool >::iterator it = d_qattr_conjecture.find( q );
- if( it==d_qattr_conjecture.end() ){
+ std::map< Node, QAttributes >::iterator it = d_qattr.find( q );
+ if( it==d_qattr.end() ){
return false;
}else{
- return it->second;
+ return it->second.d_conjecture;
}
}
bool TermDb::isQAttrAxiom( Node q ) {
- std::map< Node, bool >::iterator it = d_qattr_axiom.find( q );
- if( it==d_qattr_axiom.end() ){
+ std::map< Node, QAttributes >::iterator it = d_qattr.find( q );
+ if( it==d_qattr.end() ){
return false;
}else{
- return it->second;
+ return it->second.d_axiom;
}
}
bool TermDb::isQAttrFunDef( Node q ) {
- std::map< Node, bool >::iterator it = d_qattr_fundef.find( q );
- if( it==d_qattr_fundef.end() ){
+ std::map< Node, QAttributes >::iterator it = d_qattr.find( q );
+ if( it==d_qattr.end() ){
return false;
}else{
- return it->second;
+ return it->second.isFunDef();
}
}
bool TermDb::isQAttrSygus( Node q ) {
- std::map< Node, bool >::iterator it = d_qattr_sygus.find( q );
- if( it==d_qattr_sygus.end() ){
+ std::map< Node, QAttributes >::iterator it = d_qattr.find( q );
+ if( it==d_qattr.end() ){
return false;
}else{
- return it->second;
+ return it->second.d_sygus;
}
}
bool TermDb::isQAttrSynthesis( Node q ) {
- std::map< Node, bool >::iterator it = d_qattr_synthesis.find( q );
- if( it==d_qattr_synthesis.end() ){
+ std::map< Node, QAttributes >::iterator it = d_qattr.find( q );
+ if( it==d_qattr.end() ){
return false;
}else{
- return it->second;
+ return it->second.d_synthesis;
}
}
int TermDb::getQAttrQuantInstLevel( Node q ) {
- std::map< Node, int >::iterator it = d_qattr_qinstLevel.find( q );
- if( it==d_qattr_qinstLevel.end() ){
+ std::map< Node, QAttributes >::iterator it = d_qattr.find( q );
+ if( it==d_qattr.end() ){
return -1;
}else{
- return it->second;
+ return it->second.d_qinstLevel;
}
}
int TermDb::getQAttrRewriteRulePriority( Node q ) {
- std::map< Node, int >::iterator it = d_qattr_rr_priority.find( q );
- if( it==d_qattr_rr_priority.end() ){
+ std::map< Node, QAttributes >::iterator it = d_qattr.find( q );
+ if( it==d_qattr.end() ){
return -1;
}else{
- return it->second;
+ return it->second.d_rr_priority;
}
}
+bool TermDb::isQAttrQuantElim( Node q ) {
+ std::map< Node, QAttributes >::iterator it = d_qattr.find( q );
+ if( it==d_qattr.end() ){
+ return false;
+ }else{
+ return it->second.d_quant_elim;
+ }
+}
+bool TermDb::isQAttrQuantElimPartial( Node q ) {
+ std::map< Node, QAttributes >::iterator it = d_qattr.find( q );
+ if( it==d_qattr.end() ){
+ return false;
+ }else{
+ return it->second.d_quant_elim_partial;
+ }
+}
TermDbSygus::TermDbSygus(){
d_true = NodeManager::currentNM()->mkConst( true );
diff --git a/src/theory/quantifiers/term_database.h b/src/theory/quantifiers/term_database.h
index 0c4e94517..a62b343a2 100644
--- a/src/theory/quantifiers/term_database.h
+++ b/src/theory/quantifiers/term_database.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file term_database.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): Tim King
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief term database class
**/
@@ -20,6 +20,7 @@
#include "expr/attribute.h"
#include "theory/theory.h"
#include "theory/type_enumerator.h"
+#include "theory/quantifiers/quant_util.h"
#include <map>
@@ -68,6 +69,12 @@ typedef expr::Attribute<InstLevelAttributeId, uint64_t> InstLevelAttribute;
struct InstVarNumAttributeId {};
typedef expr::Attribute<InstVarNumAttributeId, uint64_t> InstVarNumAttribute;
+struct TermDepthAttributeId {};
+typedef expr::Attribute<TermDepthAttributeId, uint64_t> TermDepthAttribute;
+
+struct ContainsUConstAttributeId {};
+typedef expr::Attribute<ContainsUConstAttributeId, uint64_t> ContainsUConstAttribute;
+
struct ModelBasisAttributeId {};
typedef expr::Attribute<ModelBasisAttributeId, bool> ModelBasisAttribute;
//for APPLY_UF terms, 1 : term has direct child with model basis attribute,
@@ -99,6 +106,14 @@ typedef expr::Attribute<SygusProxyAttributeId, Node> SygusProxyAttribute;
struct AbsTypeFunDefAttributeId {};
typedef expr::Attribute<AbsTypeFunDefAttributeId, bool> AbsTypeFunDefAttribute;
+/** Attribute true for quantifiers that we are doing quantifier elimination on */
+struct QuantElimAttributeId {};
+typedef expr::Attribute< QuantElimAttributeId, bool > QuantElimAttribute;
+
+/** Attribute true for quantifiers that we are doing partial quantifier elimination on */
+struct QuantElimPartialAttributeId {};
+typedef expr::Attribute< QuantElimPartialAttributeId, bool > QuantElimPartialAttribute;
+
class QuantifiersEngine;
namespace inst{
@@ -112,23 +127,57 @@ public:
/** the data */
std::map< TNode, TermArgTrie > d_data;
public:
+ bool hasNodeData() { return !d_data.empty(); }
+ TNode getNodeData() { return d_data.begin()->first; }
TNode existsTerm( std::vector< TNode >& reps, int argIndex = 0 );
+ TNode addOrGetTerm( TNode n, std::vector< TNode >& reps, int argIndex = 0 );
bool addTerm( TNode n, std::vector< TNode >& reps, int argIndex = 0 );
void debugPrint( const char * c, Node n, unsigned depth = 0 );
void clear() { d_data.clear(); }
};/* class TermArgTrie */
+class QAttributes{
+public:
+ QAttributes() : d_hasPattern(false), d_conjecture(false), d_axiom(false), d_sygus(false),
+ d_synthesis(false), d_rr_priority(-1), d_qinstLevel(-1), d_quant_elim(false), d_quant_elim_partial(false){}
+ ~QAttributes(){}
+ bool d_hasPattern;
+ Node d_rr;
+ bool d_conjecture;
+ bool d_axiom;
+ Node d_fundef_f;
+ bool d_sygus;
+ bool d_synthesis;
+ int d_rr_priority;
+ int d_qinstLevel;
+ bool d_quant_elim;
+ bool d_quant_elim_partial;
+ Node d_ipl;
+ bool isRewriteRule() { return !d_rr.isNull(); }
+ bool isFunDef() { return !d_fundef_f.isNull(); }
+};
+
namespace fmcheck {
class FullModelChecker;
}
class TermDbSygus;
+class QuantConflictFind;
+class RelevantDomain;
+class ConjectureGenerator;
+class TermGenerator;
+class TermGenEnv;
-class TermDb {
+class TermDb : public QuantifiersUtil {
friend class ::CVC4::theory::QuantifiersEngine;
+ //TODO: eliminate most of these
friend class ::CVC4::theory::inst::Trigger;
friend class ::CVC4::theory::quantifiers::fmcheck::FullModelChecker;
+ friend class ::CVC4::theory::quantifiers::QuantConflictFind;
+ friend class ::CVC4::theory::quantifiers::RelevantDomain;
+ friend class ::CVC4::theory::quantifiers::ConjectureGenerator;
+ friend class ::CVC4::theory::quantifiers::TermGenEnv;
typedef context::CDHashMap<Node, int, NodeHashFunction> NodeIntMap;
private:
/** reference to the quantifiers engine */
@@ -139,8 +188,8 @@ private:
std::hash_set< Node, NodeHashFunction > d_iclosure_processed;
/** select op map */
std::map< Node, std::map< TypeNode, Node > > d_par_op_map;
- /** set has term */
- void setHasTerm( Node n );
+ /** whether master equality engine is UF-inconsistent */
+ bool d_consistent_ee;
public:
TermDb( context::Context* c, context::UserContext* u, QuantifiersEngine* qe );
~TermDb(){}
@@ -150,13 +199,19 @@ public:
/** constants */
Node d_zero;
Node d_one;
-
+public:
+ /** presolve (called once per user check-sat) */
+ void presolve();
+ /** reset (calculate which terms are active) */
+ bool reset( Theory::Effort effort );
+ /** identify */
+ std::string identify() const { return "TermDb"; }
+private:
/** map from operators to ground terms for that operator */
std::map< Node, std::vector< Node > > d_op_map;
/** map from type nodes to terms of that type */
std::map< TypeNode, std::vector< Node > > d_type_map;
-
/** count number of non-redundant ground terms per operator */
std::map< Node, int > d_op_nonred_count;
/**mapping from UF terms to representatives of their arguments */
@@ -164,41 +219,53 @@ public:
/** map from operators to trie */
std::map< Node, TermArgTrie > d_func_map_trie;
std::map< Node, TermArgTrie > d_func_map_eqc_trie;
+ /** mapping from operators to their representative relevant domains */
+ std::map< Node, std::map< unsigned, std::vector< Node > > > d_func_map_rel_dom;
/** has map */
std::map< Node, bool > d_has_map;
/** map from reps to a term in eqc in d_has_map */
- std::map< Node, Node > d_term_elig_eqc;
-
+ std::map< Node, Node > d_term_elig_eqc;
+ /** set has term */
+ void setHasTerm( Node n );
+ /** evaluate term */
+ Node evaluateTerm2( TNode n, std::map< TNode, Node >& visited, EqualityQuery * qy );
+ TNode getEntailedTerm2( TNode n, std::map< TNode, TNode >& subs, bool subsRep, bool hasSubs, EqualityQuery * qy );
+ bool isEntailed2( TNode n, std::map< TNode, TNode >& subs, bool subsRep, bool hasSubs, bool pol, EqualityQuery * qy );
public:
/** ground terms for operator */
unsigned getNumGroundTerms( Node f );
/** get ground term for operator */
Node getGroundTerm( Node f, unsigned i );
+ /** get num type terms */
+ unsigned getNumTypeGroundTerms( TypeNode tn );
+ /** get type ground term */
+ Node getTypeGroundTerm( TypeNode tn, unsigned i );
/** add a term to the database */
void addTerm( Node n, std::set< Node >& added, bool withinQuant = false, bool withinInstClosure = false );
- /** presolve (called once per user check-sat) */
- void presolve();
- /** reset (calculate which terms are active) */
- void reset( Theory::Effort effort );
- /** get operator*/
- Node getOperator( Node n );
+ /** get match operator */
+ Node getMatchOperator( Node n );
/** get term arg index */
TermArgTrie * getTermArgTrie( Node f );
TermArgTrie * getTermArgTrie( Node eqc, Node f );
/** exists term */
- TNode existsTerm( Node f, Node n );
+ TNode getCongruentTerm( Node f, Node n );
+ TNode getCongruentTerm( Node f, std::vector< TNode >& args );
/** compute arg reps */
void computeArgReps( TNode n );
/** compute uf eqc terms */
void computeUfEqcTerms( TNode f );
+ /** in relevant domain */
+ bool inRelevantDomain( TNode f, unsigned i, TNode r );
/** evaluate a term under a substitution. Return representative in EE if possible.
* subsRep is whether subs contains only representatives
*/
- TNode evaluateTerm( TNode n, std::map< TNode, TNode >& subs, bool subsRep );
- /** same as above, but without substitution */
- TNode evaluateTerm( TNode n );
+ Node evaluateTerm( TNode n, EqualityQuery * qy = NULL );
+ /** get entailed term, does not construct new terms, less aggressive */
+ TNode getEntailedTerm( TNode n, EqualityQuery * qy = NULL );
+ TNode getEntailedTerm( TNode n, std::map< TNode, TNode >& subs, bool subsRep, EqualityQuery * qy = NULL );
/** is entailed (incomplete check) */
- bool isEntailed( TNode n, std::map< TNode, TNode >& subs, bool subsRep, bool pol );
+ bool isEntailed( TNode n, bool pol, EqualityQuery * qy = NULL );
+ bool isEntailed( TNode n, std::map< TNode, TNode >& subs, bool subsRep, bool pol, EqualityQuery * qy = NULL );
/** has term */
bool hasTermCurrent( Node n, bool useMode = true );
/** is term eligble for instantiation? */
@@ -248,7 +315,7 @@ public:
/** get the i^th instantiation constant of q */
Node getInstantiationConstant( Node q, int i ) const;
/** get number of instantiation constants for q */
- int getNumInstantiationConstants( Node q ) const;
+ unsigned getNumInstantiationConstants( Node q ) const;
/** get the ce body q[e/x] */
Node getInstConstantBody( Node q );
/** get counterexample literal (for cbqi) */
@@ -318,26 +385,26 @@ public:
//for triggers
private:
/** helper function for compute var contains */
- void computeVarContains2( Node n, std::vector< Node >& varContains, std::map< Node, bool >& visited );
+ static void computeVarContains2( Node n, std::vector< Node >& varContains, std::map< Node, bool >& visited );
/** triggers for each operator */
std::map< Node, std::vector< inst::Trigger* > > d_op_triggers;
/** helper for is instance of */
- bool isUnifiableInstanceOf( Node n1, Node n2, std::map< Node, Node >& subs );
+ static bool isUnifiableInstanceOf( Node n1, Node n2, std::map< Node, Node >& subs );
/** -1: n1 is an instance of n2, 1: n1 is an instance of n2 */
- int isInstanceOf2( Node n1, Node n2, std::vector< Node >& varContains1, std::vector< Node >& varContains2 );
+ static int isInstanceOf2( Node n1, Node n2, std::vector< Node >& varContains1, std::vector< Node >& varContains2 );
public:
/** compute var contains */
- void computeVarContains( Node n, std::vector< Node >& varContains );
+ static void computeVarContains( Node n, std::vector< Node >& varContains );
/** get var contains for each of the patterns in pats */
- void getVarContains( Node f, std::vector< Node >& pats, std::map< Node, std::vector< Node > >& varContains );
+ static void getVarContains( Node f, std::vector< Node >& pats, std::map< Node, std::vector< Node > >& varContains );
/** get var contains for node n */
- void getVarContainsNode( Node f, Node n, std::vector< Node >& varContains );
- /** register trigger (for eager quantifier instantiation) */
- void registerTrigger( inst::Trigger* tr, Node op );
+ static void getVarContainsNode( Node f, Node n, std::vector< Node >& varContains );
/** -1: n1 is an instance of n2, 1: n1 is an instance of n2 */
- int isInstanceOf( Node n1, Node n2 );
+ static int isInstanceOf( Node n1, Node n2 );
/** filter all nodes that have instances */
- void filterInstances( std::vector< Node >& nodes );
+ static void filterInstances( std::vector< Node >& nodes );
+ /** register trigger (for eager quantifier instantiation) */
+ void registerTrigger( inst::Trigger* tr, Node op );
//for term ordering
private:
@@ -390,14 +457,14 @@ public:
bool containsVtsTerm( std::vector< Node >& n, bool isFree = false );
/** simple check for contains term */
bool containsVtsInfinity( Node n, bool isFree = false );
- /** make type */
- static Node mkNodeType( Node n, TypeNode tn );
-
+ /** ensure type */
+ static Node ensureType( Node n, TypeNode tn );
+ /** get ensure type condition */
+ static bool getEnsureTypeCondition( Node n, TypeNode tn, std::vector< Node >& cond );
private:
//helper for contains term
static bool containsTerm2( Node n, Node t, std::map< Node, bool >& visited );
static bool containsTerms2( Node n, std::vector< Node >& t, std::map< Node, bool >& visited );
- static bool containsUninterpretedConstant2( Node n, std::map< Node, bool >& visited );
//general utilities
public:
/** simple check for whether n contains t as subterm */
@@ -406,6 +473,8 @@ public:
static bool containsTerms( Node n, std::vector< Node >& t );
/** contains uninterpreted constant */
static bool containsUninterpretedConstant( Node n );
+ /** get the term depth of n */
+ static int getTermDepth( Node n );
/** simple negate */
static Node simpleNegate( Node n );
/** is assoc */
@@ -440,15 +509,11 @@ public: //general queries concerning quantified formulas wrt modules
static Node getFunDefHead( Node q );
/** get fun def body */
static Node getFunDefBody( Node q );
+ /** is quant elim annotation */
+ static bool isQuantElimAnnotation( Node ipl );
//attributes
private:
- std::map< Node, bool > d_qattr_conjecture;
- std::map< Node, bool > d_qattr_axiom;
- std::map< Node, bool > d_qattr_fundef;
- std::map< Node, bool > d_qattr_sygus;
- std::map< Node, bool > d_qattr_synthesis;
- std::map< Node, int > d_qattr_rr_priority;
- std::map< Node, int > d_qattr_qinstLevel;
+ std::map< Node, QAttributes > d_qattr;
//record attributes
void computeAttributes( Node q );
public:
@@ -466,7 +531,12 @@ public:
int getQAttrQuantInstLevel( Node q );
/** get rewrite rule priority */
int getQAttrRewriteRulePriority( Node q );
-
+ /** is quant elim */
+ bool isQAttrQuantElim( Node q );
+ /** is quant elim partial */
+ bool isQAttrQuantElimPartial( Node q );
+ /** compute quantifier attributes */
+ static void computeQuantAttributes( Node q, QAttributes& qa );
};/* class TermDb */
class TermDbSygus {
diff --git a/src/theory/quantifiers/theory_quantifiers.cpp b/src/theory/quantifiers/theory_quantifiers.cpp
index 86fc057ea..efe40aaa8 100644
--- a/src/theory/quantifiers/theory_quantifiers.cpp
+++ b/src/theory/quantifiers/theory_quantifiers.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_quantifiers.cpp
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): Dejan Jovanovic
+ ** Top contributors (to current version):
+ ** Morgan Deters, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of the theory of quantifiers
**
@@ -47,6 +47,8 @@ TheoryQuantifiers::TheoryQuantifiers(Context* c, context::UserContext* u, Output
out.handleUserAttribute( "synthesis", this );
out.handleUserAttribute( "quant-inst-max-level", this );
out.handleUserAttribute( "rr-priority", this );
+ out.handleUserAttribute( "quant-elim", this );
+ out.handleUserAttribute( "quant-elim-partial", this );
}
TheoryQuantifiers::~TheoryQuantifiers() {
diff --git a/src/theory/quantifiers/theory_quantifiers.h b/src/theory/quantifiers/theory_quantifiers.h
index 6335349b1..6775e0536 100644
--- a/src/theory/quantifiers/theory_quantifiers.h
+++ b/src/theory/quantifiers/theory_quantifiers.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_quantifiers.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: none
- ** Minor contributors (to current version): Francois Bobot, Dejan Jovanovic, Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Morgan Deters, Tim King, Andrew Reynolds
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Theory of quantifiers.
**
diff --git a/src/theory/quantifiers/theory_quantifiers_type_rules.h b/src/theory/quantifiers/theory_quantifiers_type_rules.h
index 1fb8ddaf9..6ba57afb4 100644
--- a/src/theory/quantifiers/theory_quantifiers_type_rules.h
+++ b/src/theory/quantifiers/theory_quantifiers_type_rules.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_quantifiers_type_rules.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Theory of quantifiers
**
diff --git a/src/theory/quantifiers/trigger.cpp b/src/theory/quantifiers/trigger.cpp
index 9aee18317..38635b37b 100644
--- a/src/theory/quantifiers/trigger.cpp
+++ b/src/theory/quantifiers/trigger.cpp
@@ -1,60 +1,67 @@
/********************* */
/*! \file trigger.cpp
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): Francois Bobot, Kshitij Bansal
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of trigger class
**/
#include "theory/quantifiers/trigger.h"
-
-#include "options/quantifiers_options.h"
#include "theory/quantifiers/candidate_generator.h"
#include "theory/quantifiers/inst_match_generator.h"
#include "theory/quantifiers/term_database.h"
#include "theory/quantifiers_engine.h"
#include "theory/theory_engine.h"
#include "theory/uf/equality_engine.h"
+#include "util/hash.h"
+
using namespace std;
-using namespace CVC4;
using namespace CVC4::kind;
using namespace CVC4::context;
-using namespace CVC4::theory;
-using namespace CVC4::theory::inst;
+
+namespace CVC4 {
+namespace theory {
+namespace inst {
+
+void TriggerTermInfo::init( Node q, Node n, int reqPol, Node reqPolEq ){
+ if( d_fv.empty() ){
+ quantifiers::TermDb::getVarContainsNode( q, n, d_fv );
+ }
+ if( d_reqPol==0 ){
+ d_reqPol = reqPol;
+ d_reqPolEq = reqPolEq;
+ }else{
+ //determined a ground (dis)equality must hold or else q is a tautology?
+ }
+}
/** trigger class constructor */
-Trigger::Trigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes, int matchOption, bool smartTriggers ) :
-d_quantEngine( qe ), d_f( f ){
+Trigger::Trigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes, int matchOption )
+ : d_quantEngine( qe ), d_f( f )
+{
d_nodes.insert( d_nodes.begin(), nodes.begin(), nodes.end() );
Trace("trigger") << "Trigger for " << f << ": " << std::endl;
- for( int i=0; i<(int)d_nodes.size(); i++ ){
+ for( unsigned i=0; i<d_nodes.size(); i++ ){
Trace("trigger") << " " << d_nodes[i] << std::endl;
}
- Trace("trigger-debug") << ", smart triggers = " << smartTriggers;
- Trace("trigger") << std::endl;
- if( smartTriggers ){
- if( d_nodes.size()==1 ){
- if( isSimpleTrigger( d_nodes[0] ) ){
- d_mg = new InstMatchGeneratorSimple( f, d_nodes[0] );
- }else{
- d_mg = InstMatchGenerator::mkInstMatchGenerator( f, d_nodes[0], qe );
- d_mg->setActiveAdd(true);
- }
+ if( d_nodes.size()==1 ){
+ if( isSimpleTrigger( d_nodes[0] ) ){
+ d_mg = new InstMatchGeneratorSimple( f, d_nodes[0] );
}else{
- d_mg = new InstMatchGeneratorMulti( f, d_nodes, qe );
- //d_mg = InstMatchGenerator::mkInstMatchGenerator( d_nodes, qe );
- //d_mg->setActiveAdd();
+ d_mg = InstMatchGenerator::mkInstMatchGenerator( f, d_nodes[0], qe );
+ d_mg->setActiveAdd(true);
}
}else{
- d_mg = InstMatchGenerator::mkInstMatchGenerator( f, d_nodes, qe );
- d_mg->setActiveAdd(true);
+ d_mg = new InstMatchGeneratorMulti( f, d_nodes, qe );
+ //d_mg = InstMatchGenerator::mkInstMatchGenerator( d_nodes, qe );
+ //d_mg->setActiveAdd();
}
if( d_nodes.size()==1 ){
if( isSimpleTrigger( d_nodes[0] ) ){
@@ -63,23 +70,26 @@ d_quantEngine( qe ), d_f( f ){
++(qe->d_statistics.d_simple_triggers);
}
}else{
- Trace("multi-trigger") << "Multi-trigger ";
- debugPrint("multi-trigger");
- Trace("multi-trigger") << " for " << f << std::endl;
- //Notice() << "Multi-trigger for " << f << " : " << std::endl;
- //Notice() << " " << (*this) << std::endl;
+ Trace("multi-trigger") << "Trigger for " << f << ": " << std::endl;
+ for( unsigned i=0; i<d_nodes.size(); i++ ){
+ Trace("multi-trigger") << " " << d_nodes[i] << std::endl;
+ }
++(qe->d_statistics.d_multi_triggers);
}
//Notice() << "Trigger : " << (*this) << " for " << f << std::endl;
if( options::eagerInstQuant() ){
for( int i=0; i<(int)d_nodes.size(); i++ ){
- Node op = qe->getTermDatabase()->getOperator( d_nodes[i] );
+ Node op = qe->getTermDatabase()->getMatchOperator( d_nodes[i] );
qe->getTermDatabase()->registerTrigger( this, op );
}
}
Trace("trigger-debug") << "Finished making trigger." << std::endl;
}
+Trigger::~Trigger() {
+ if(d_mg != NULL) { delete d_mg; }
+}
+
void Trigger::resetInstantiationRound(){
d_mg->resetInstantiationRound( d_quantEngine );
}
@@ -114,8 +124,7 @@ int Trigger::addInstantiations( InstMatch& baseMatch ){
return addedLemmas;
}
-Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes, int matchOption, bool keepAll, int trOption,
- bool smartTriggers ){
+Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes, int matchOption, bool keepAll, int trOption ){
std::vector< Node > trNodes;
if( !keepAll ){
//only take nodes that contribute variables to the trigger when added
@@ -125,7 +134,7 @@ Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >&
std::map< Node, std::vector< Node > > patterns;
size_t varCount = 0;
std::map< Node, std::vector< Node > > varContains;
- qe->getTermDatabase()->getVarContains( f, temp, varContains );
+ quantifiers::TermDb::getVarContains( f, temp, varContains );
for( unsigned i=0; i<temp.size(); i++ ){
bool foundVar = false;
for( unsigned j=0; j<varContains[ temp[i] ].size(); j++ ){
@@ -202,21 +211,21 @@ Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >&
}
}
}
- Trigger* t = new Trigger( qe, f, trNodes, matchOption, smartTriggers );
+ Trigger* t = new Trigger( qe, f, trNodes, matchOption );
qe->getTriggerDatabase()->addTrigger( trNodes, t );
return t;
}
-Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, Node n, int matchOption, bool keepAll, int trOption, bool smartTriggers ){
+Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, Node n, int matchOption, bool keepAll, int trOption ){
std::vector< Node > nodes;
nodes.push_back( n );
- return mkTrigger( qe, f, nodes, matchOption, keepAll, trOption, smartTriggers );
+ return mkTrigger( qe, f, nodes, matchOption, keepAll, trOption );
}
bool Trigger::isUsable( Node n, Node q ){
if( quantifiers::TermDb::getInstConstAttr(n)==q ){
if( isAtomicTrigger( n ) ){
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
if( !isUsable( n[i], q ) ){
return false;
}
@@ -241,67 +250,91 @@ bool Trigger::isUsable( Node n, Node q ){
}
}
-Node Trigger::getIsUsableTrigger( Node n, Node f, bool pol, bool hasPol ) {
+Node Trigger::getIsUsableEq( Node q, Node n ) {
+ Assert( isRelationalTrigger( n ) );
+ for( unsigned i=0; i<2; i++) {
+ if( isUsableEqTerms( q, n[i], n[1-i] ) ){
+ if( i==1 && ( n.getKind()==EQUAL || n.getKind()==IFF ) && !quantifiers::TermDb::hasInstConstAttr(n[0]) ){
+ return NodeManager::currentNM()->mkNode( n.getKind(), n[1], n[0] );
+ }else{
+ return n;
+ }
+ }
+ }
+ return Node::null();
+}
+
+bool Trigger::isUsableEqTerms( Node q, Node n1, Node n2 ) {
+ if( n1.getKind()==INST_CONSTANT ){
+ if( options::relationalTriggers() ){
+ if( !quantifiers::TermDb::hasInstConstAttr(n2) ){
+ return true;
+ }else if( n2.getKind()==INST_CONSTANT ){
+ return true;
+ }
+ }
+ }else if( isAtomicTrigger( n1 ) && isUsable( n1, q ) ){
+ if( options::relationalTriggers() && n2.getKind()==INST_CONSTANT && !quantifiers::TermDb::containsTerm( n1, n2 ) ){
+ return true;
+ }else if( !quantifiers::TermDb::hasInstConstAttr(n2) ){
+ return true;
+ }
+ }
+ return false;
+}
+
+Node Trigger::getIsUsableTrigger( Node n, Node q ) {
+ bool pol = true;
Trace("trigger-debug") << "Is " << n << " a usable trigger?" << std::endl;
if( n.getKind()==NOT ){
pol = !pol;
n = n[0];
}
- if( options::relationalTriggers() ){
- if( n.getKind()==EQUAL || n.getKind()==IFF || n.getKind()==GEQ ){
- Node rtr;
- bool do_negate = hasPol && pol;
- bool is_arith = n[0].getType().isReal();
- for( unsigned i=0; i<2; i++) {
- if( n[1-i].getKind()==INST_CONSTANT ){
- if( isUsableTrigger( n[i], f ) && !quantifiers::TermDb::containsTerm( n[i], n[1-i] ) && ( !do_negate || is_arith ) ){
- rtr = n;
- break;
- }
- if( n[i].getKind()==INST_CONSTANT && ( !hasPol || pol ) ){
- do_negate = true;
- rtr = n;
- break;
+ if( n.getKind()==INST_CONSTANT ){
+ return pol ? n : NodeManager::currentNM()->mkNode( IFF, n, NodeManager::currentNM()->mkConst( true ) ).notNode();
+ }else if( isRelationalTrigger( n ) ){
+ Node rtr = getIsUsableEq( q, n );
+ if( rtr.isNull() && n[0].getType().isReal() ){
+ //try to solve relation
+ std::map< Node, Node > m;
+ if( QuantArith::getMonomialSumLit(n, m) ){
+ for( std::map< Node, Node >::iterator it = m.begin(); it!=m.end(); ++it ){
+ bool trySolve = false;
+ if( !it->first.isNull() ){
+ if( it->first.getKind()==INST_CONSTANT ){
+ trySolve = options::relationalTriggers();
+ }else if( isUsableTrigger( it->first, q ) ){
+ trySolve = true;
+ }
}
- }
- }
- if( is_arith ){
- //try to rearrange?
- std::map< Node, Node > m;
- if( QuantArith::getMonomialSumLit(n, m) ){
- for( std::map< Node, Node >::iterator it = m.begin(); it!=m.end(); ++it ){
- if( !it->first.isNull() && it->first.getKind()==INST_CONSTANT ){
- Node veq;
- if( QuantArith::isolate( it->first, m, veq, n.getKind() )!=0 ){
- int vti = veq[0]==it->first ? 1 : 0;
- if( isUsableTrigger( veq[vti], f ) && !quantifiers::TermDb::containsTerm( veq[vti], veq[1-vti] ) ){
- rtr = veq;
- }
- }
+ if( trySolve ){
+ Trace("trigger-debug") << "Try to solve for " << it->first << std::endl;
+ Node veq;
+ if( QuantArith::isolate( it->first, m, veq, n.getKind() )!=0 ){
+ rtr = getIsUsableEq( q, veq );
}
+ //either all solves will succeed or all solves will fail
+ break;
}
}
}
- if( !rtr.isNull() ){
- Trace("relational-trigger") << "Relational trigger : " << std::endl;
- Trace("relational-trigger") << " " << rtr << " (from " << n << ")" << std::endl;
- Trace("relational-trigger") << " in quantifier " << f << std::endl;
- if( hasPol ){
- Trace("relational-trigger") << " polarity : " << pol << std::endl;
- }
- Node rtr2 = do_negate ? rtr.negate() : rtr;
- Trace("relational-trigger") << " return : " << rtr2 << std::endl;
- return rtr2;
- }
}
- }
- bool usable = quantifiers::TermDb::getInstConstAttr(n)==f && isAtomicTrigger( n ) && isUsable( n, f );
- Trace("trigger-debug") << n << " usable : " << (quantifiers::TermDb::getInstConstAttr(n)==f) << " " << isAtomicTrigger( n ) << " " << isUsable( n, f ) << std::endl;
- if( usable ){
- return n;
+ if( !rtr.isNull() ){
+ Trace("relational-trigger") << "Relational trigger : " << std::endl;
+ Trace("relational-trigger") << " " << rtr << " (from " << n << ")" << std::endl;
+ Trace("relational-trigger") << " in quantifier " << q << std::endl;
+ Node rtr2 = pol ? rtr : rtr.negate();
+ Trace("relational-trigger") << " return : " << rtr2 << std::endl;
+ return rtr2;
+ }
}else{
- return Node::null();
+ bool usable = quantifiers::TermDb::getInstConstAttr(n)==q && isAtomicTrigger( n ) && isUsable( n, q );
+ Trace("trigger-debug") << n << " usable : " << (quantifiers::TermDb::getInstConstAttr(n)==q) << " " << isAtomicTrigger( n ) << " " << isUsable( n, q ) << std::endl;
+ if( usable ){
+ return pol ? n : NodeManager::currentNM()->mkNode( IFF, n, NodeManager::currentNM()->mkConst( true ) ).notNode();
+ }
}
+ return Node::null();
}
bool Trigger::isUsableTrigger( Node n, Node q ){
@@ -321,19 +354,33 @@ bool Trigger::isAtomicTriggerKind( Kind k ) {
k==UNION || k==INTERSECTION || k==SUBSET || k==SETMINUS || k==MEMBER || k==SINGLETON;
}
+bool Trigger::isRelationalTrigger( Node n ) {
+ return isRelationalTriggerKind( n.getKind() );
+}
+
+bool Trigger::isRelationalTriggerKind( Kind k ) {
+ return k==EQUAL || k==IFF || k==GEQ;
+}
+
bool Trigger::isCbqiKind( Kind k ) {
return quantifiers::TermDb::isBoolConnective( k ) || k==PLUS || k==GEQ || k==EQUAL || k==MULT ||
k==APPLY_CONSTRUCTOR || k==APPLY_SELECTOR_TOTAL || k==APPLY_TESTER;
}
bool Trigger::isSimpleTrigger( Node n ){
- if( isAtomicTrigger( n ) ){
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- if( n[i].getKind()!=INST_CONSTANT && quantifiers::TermDb::hasInstConstAttr(n[i]) ){
+ Node t = n.getKind()==NOT ? n[0] : n;
+ if( n.getKind()==IFF || n.getKind()==EQUAL ){
+ if( !quantifiers::TermDb::hasInstConstAttr( n[1] ) ){
+ t = n[0];
+ }
+ }
+ if( isAtomicTrigger( t ) ){
+ for( unsigned i=0; i<t.getNumChildren(); i++ ){
+ if( t[i].getKind()!=INST_CONSTANT && quantifiers::TermDb::hasInstConstAttr(t[i]) ){
return false;
}
}
- if( options::purifyDtTriggers() && n.getKind()==APPLY_SELECTOR_TOTAL ){
+ if( options::purifyDtTriggers() && t.getKind()==APPLY_SELECTOR_TOTAL ){
return false;
}
return true;
@@ -342,69 +389,101 @@ bool Trigger::isSimpleTrigger( Node n ){
}
}
-
-bool Trigger::collectPatTerms2( Node f, Node n, std::map< Node, bool >& patMap, int tstrt, std::vector< Node >& exclude, bool pol, bool hasPol ){
- if( patMap.find( n )==patMap.end() ){
- patMap[ n ] = false;
- if( tstrt==TS_MIN_TRIGGER ){
- if( n.getKind()==FORALL ){
- return false;
- }else{
- bool retVal = false;
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- bool newHasPol, newPol;
- QuantPhaseReq::getPolarity( n, i, hasPol, pol, newHasPol, newPol );
- if( collectPatTerms2( f, n[i], patMap, tstrt, exclude, newPol, newHasPol ) ){
- retVal = true;
+//store triggers in reqPol, indicating their polarity (if any) they must appear to falsify the quantified formula
+bool Trigger::collectPatTerms2( Node q, Node n, std::map< Node, Node >& visited, std::map< Node, TriggerTermInfo >& tinfo,
+ quantifiers::TriggerSelMode tstrt, std::vector< Node >& exclude, std::vector< Node >& added,
+ bool pol, bool hasPol, bool epol, bool hasEPol ){
+ std::map< Node, Node >::iterator itv = visited.find( n );
+ if( itv==visited.end() ){
+ visited[ n ] = Node::null();
+ Trace("auto-gen-trigger-debug2") << "Collect pat terms " << n << " " << pol << " " << hasPol << " " << epol << " " << hasEPol << std::endl;
+ bool retVal = false;
+ if( n.getKind()!=FORALL && n.getKind()!=INST_CONSTANT ){
+ bool rec = true;
+ Node nu;
+ bool nu_single = false;
+ if( n.getKind()!=NOT && std::find( exclude.begin(), exclude.end(), n )==exclude.end() ){
+ nu = getIsUsableTrigger( n, q );
+ if( !nu.isNull() ){
+ Assert( nu.getKind()!=NOT );
+ Trace("auto-gen-trigger-debug2") << "...found usable trigger : " << nu << std::endl;
+ Node reqEq;
+ if( nu.getKind()==IFF || nu.getKind()==EQUAL ){
+ if( isAtomicTrigger( nu[0] ) && !quantifiers::TermDb::hasInstConstAttr(nu[1]) ){
+ if( hasPol ){
+ reqEq = nu[1];
+ }
+ nu = nu[0];
+ }
}
- }
- if( retVal ){
- return true;
- }else{
- Node nu;
- if( std::find( exclude.begin(), exclude.end(), n )==exclude.end() ){
- nu = getIsUsableTrigger( n, f, pol, hasPol );
+ Assert( reqEq.isNull() || !quantifiers::TermDb::hasInstConstAttr( reqEq ) );
+ Assert( isUsableTrigger( nu, q ) );
+ //do not add if already excluded
+ bool add = true;
+ if( n!=nu ){
+ std::map< Node, Node >::iterator itvu = visited.find( nu );
+ if( itvu!=visited.end() && itvu->second.isNull() ){
+ add = false;
+ }
}
- if( !nu.isNull() ){
- patMap[ nu ] = true;
- return true;
- }else{
- return false;
+ if( add ){
+ Trace("auto-gen-trigger-debug2") << "...add usable trigger : " << nu << std::endl;
+ visited[ nu ] = nu;
+ tinfo[ nu ].init( q, nu, hasEPol ? ( epol ? 1 : -1 ) : 0, reqEq );
+ nu_single = tinfo[ nu ].d_fv.size()==q[0].getNumChildren();
+ retVal = true;
+ if( tstrt==quantifiers::TRIGGER_SEL_MAX || ( tstrt==quantifiers::TRIGGER_SEL_MIN_SINGLE_MAX && !nu_single ) ){
+ rec = false;
+ }
}
}
}
- }else{
- bool retVal = false;
- Node nu;
- if( std::find( exclude.begin(), exclude.end(), n )==exclude.end() ){
- nu = getIsUsableTrigger( n, f, pol, hasPol );
- }
- if( !nu.isNull() ){
- patMap[ nu ] = true;
- if( tstrt==TS_MAX_TRIGGER ){
- return true;
- }else{
- retVal = true;
- }
- }
- if( n.getKind()!=FORALL ){
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ if( rec ){
+ Node nrec = nu.isNull() ? n : nu;
+ std::vector< Node > added2;
+ for( unsigned i=0; i<nrec.getNumChildren(); i++ ){
bool newHasPol, newPol;
- QuantPhaseReq::getPolarity( n, i, hasPol, pol, newHasPol, newPol );
- if( collectPatTerms2( f, n[i], patMap, tstrt, exclude, newPol, newHasPol ) ){
+ bool newHasEPol, newEPol;
+ QuantPhaseReq::getPolarity( nrec, i, hasPol, pol, newHasPol, newPol );
+ QuantPhaseReq::getEntailPolarity( nrec, i, hasEPol, epol, newHasEPol, newEPol );
+ if( collectPatTerms2( q, nrec[i], visited, tinfo, tstrt, exclude, added2, newPol, newHasPol, newEPol, newHasEPol ) ){
retVal = true;
}
}
+ if( !nu.isNull() ){
+ bool rm_nu = false;
+ //discard if we added a subterm as a trigger with all variables that nu has
+ for( unsigned i=0; i<added2.size(); i++ ){
+ Assert( tinfo.find( added2[i] )!=tinfo.end() );
+ if( added2[i]!=nu ){
+ if( tinfo[ nu ].d_fv.size()==tinfo[ added2[i] ].d_fv.size() ){
+ rm_nu = true;
+ }
+ added.push_back( added2[i] );
+ }else{
+ Assert( false );
+ }
+ }
+ if( rm_nu && ( tstrt==quantifiers::TRIGGER_SEL_MIN || ( tstrt==quantifiers::TRIGGER_SEL_MIN_SINGLE_ALL && nu_single ) ) ){
+ visited[nu] = Node::null();
+ tinfo.erase( nu );
+ }else{
+ added.push_back( nu );
+ }
+ }
}
- return retVal;
}
+ return retVal;
}else{
- return patMap[ n ];
+ if( itv->second.isNull() ){
+ return false;
+ }else{
+ added.push_back( itv->second );
+ return true;
+ }
}
}
-
-
bool Trigger::isBooleanTermTrigger( Node n ) {
if( n.getKind()==ITE ){
//check for boolean term converted to ITE
@@ -434,6 +513,23 @@ bool Trigger::isPureTheoryTrigger( Node n ) {
}
}
+int Trigger::getTriggerWeight( Node n ) {
+ if( isAtomicTrigger( n ) ){
+ return 0;
+ }else{
+ if( options::relationalTriggers() ){
+ if( isRelationalTrigger( n ) ){
+ for( unsigned i=0; i<2; i++ ){
+ if( n[i].getKind()==INST_CONSTANT && !quantifiers::TermDb::hasInstConstAttr( n[1-i] ) ){
+ return 0;
+ }
+ }
+ }
+ }
+ return 1;
+ }
+}
+
bool Trigger::isLocalTheoryExt( Node n, std::vector< Node >& vars, std::vector< Node >& patTerms ) {
if( !n.getType().isBoolean() && n.getKind()==APPLY_UF ){
if( std::find( patTerms.begin(), patTerms.end(), n )==patTerms.end() ){
@@ -466,42 +562,51 @@ bool Trigger::isLocalTheoryExt( Node n, std::vector< Node >& vars, std::vector<
return true;
}
-void Trigger::collectPatTerms( QuantifiersEngine* qe, Node f, Node n, std::vector< Node >& patTerms, int tstrt, std::vector< Node >& exclude, bool filterInst ){
- std::map< Node, bool > patMap;
+void Trigger::collectPatTerms( Node q, Node n, std::vector< Node >& patTerms, quantifiers::TriggerSelMode tstrt, std::vector< Node >& exclude,
+ std::map< Node, TriggerTermInfo >& tinfo, bool filterInst ){
+ std::map< Node, Node > visited;
if( filterInst ){
//immediately do not consider any term t for which another term is an instance of t
std::vector< Node > patTerms2;
- collectPatTerms( qe, f, n, patTerms2, TS_ALL, exclude, false );
+ std::map< Node, TriggerTermInfo > tinfo2;
+ collectPatTerms( q, n, patTerms2, quantifiers::TRIGGER_SEL_ALL, exclude, tinfo2, false );
std::vector< Node > temp;
temp.insert( temp.begin(), patTerms2.begin(), patTerms2.end() );
- qe->getTermDatabase()->filterInstances( temp );
+ quantifiers::TermDb::filterInstances( temp );
if( temp.size()!=patTerms2.size() ){
Trace("trigger-filter-instance") << "Filtered an instance: " << std::endl;
Trace("trigger-filter-instance") << "Old: ";
- for( int i=0; i<(int)patTerms2.size(); i++ ){
+ for( unsigned i=0; i<patTerms2.size(); i++ ){
Trace("trigger-filter-instance") << patTerms2[i] << " ";
}
Trace("trigger-filter-instance") << std::endl << "New: ";
- for( int i=0; i<(int)temp.size(); i++ ){
+ for( unsigned i=0; i<temp.size(); i++ ){
Trace("trigger-filter-instance") << temp[i] << " ";
}
Trace("trigger-filter-instance") << std::endl;
}
- if( tstrt==TS_ALL ){
- patTerms.insert( patTerms.begin(), temp.begin(), temp.end() );
+ if( tstrt==quantifiers::TRIGGER_SEL_ALL ){
+ for( unsigned i=0; i<temp.size(); i++ ){
+ //copy information
+ tinfo[temp[i]].d_fv.insert( tinfo[temp[i]].d_fv.end(), tinfo2[temp[i]].d_fv.begin(), tinfo2[temp[i]].d_fv.end() );
+ tinfo[temp[i]].d_reqPol = tinfo2[temp[i]].d_reqPol;
+ tinfo[temp[i]].d_reqPolEq = tinfo2[temp[i]].d_reqPolEq;
+ patTerms.push_back( temp[i] );
+ }
return;
}else{
//do not consider terms that have instances
- for( int i=0; i<(int)patTerms2.size(); i++ ){
+ for( unsigned i=0; i<patTerms2.size(); i++ ){
if( std::find( temp.begin(), temp.end(), patTerms2[i] )==temp.end() ){
- patMap[ patTerms2[i] ] = false;
+ visited[ patTerms2[i] ] = Node::null();
}
}
}
}
- collectPatTerms2( f, n, patMap, tstrt, exclude, true, true );
- for( std::map< Node, bool >::iterator it = patMap.begin(); it != patMap.end(); ++it ){
- if( it->second ){
+ std::vector< Node > added;
+ collectPatTerms2( q, n, visited, tinfo, tstrt, exclude, added, true, true, false, true );
+ for( std::map< Node, TriggerTermInfo >::iterator it = tinfo.begin(); it != tinfo.end(); ++it ){
+ if( !visited[it->first].isNull() ){
patTerms.push_back( it->first );
}
}
@@ -582,14 +687,15 @@ Node Trigger::getInversion( Node n, Node x ) {
return Node::null();
}
-void Trigger::getTriggerVariables( QuantifiersEngine* qe, Node icn, Node f, std::vector< Node >& t_vars ) {
+void Trigger::getTriggerVariables( Node icn, Node q, std::vector< Node >& t_vars ) {
std::vector< Node > patTerms;
+ std::map< Node, TriggerTermInfo > tinfo;
//collect all patterns from icn
std::vector< Node > exclude;
- collectPatTerms( qe, f, icn, patTerms, TS_ALL, exclude );
+ collectPatTerms( q, icn, patTerms, quantifiers::TRIGGER_SEL_ALL, exclude, tinfo );
//collect all variables from all patterns in patTerms, add to t_vars
for( unsigned i=0; i<patTerms.size(); i++ ){
- qe->getTermDatabase()->getVarContainsNode( f, patTerms[i], t_vars );
+ quantifiers::TermDb::getVarContainsNode( q, patTerms[i], t_vars );
}
}
@@ -621,7 +727,7 @@ InstMatchGenerator* Trigger::getInstMatchGenerator( Node q, Node n ) {
Trigger* TriggerTrie::getTrigger2( std::vector< Node >& nodes ){
if( nodes.empty() ){
- return d_tr;
+ return d_tr.empty() ? NULL : d_tr[0];
}else{
Node n = nodes.back();
nodes.pop_back();
@@ -635,7 +741,7 @@ Trigger* TriggerTrie::getTrigger2( std::vector< Node >& nodes ){
void TriggerTrie::addTrigger2( std::vector< Node >& nodes, Trigger* t ){
if( nodes.empty() ){
- d_tr = t;
+ d_tr.push_back( t );
}else{
Node n = nodes.back();
nodes.pop_back();
@@ -645,3 +751,24 @@ void TriggerTrie::addTrigger2( std::vector< Node >& nodes, Trigger* t ){
d_children[n]->addTrigger2( nodes, t );
}
}
+
+
+TriggerTrie::TriggerTrie()
+{}
+
+TriggerTrie::~TriggerTrie() {
+ for(std::map< TNode, TriggerTrie* >::iterator i = d_children.begin(), iend = d_children.end();
+ i != iend; ++i) {
+ TriggerTrie* current = (*i).second;
+ delete current;
+ }
+ d_children.clear();
+
+ for( unsigned i=0; i<d_tr.size(); i++ ){
+ delete d_tr[i];
+ }
+}
+
+}/* CVC4::theory::inst namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
diff --git a/src/theory/quantifiers/trigger.h b/src/theory/quantifiers/trigger.h
index 11962008e..41f2a1c38 100644
--- a/src/theory/quantifiers/trigger.h
+++ b/src/theory/quantifiers/trigger.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file trigger.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): Francois Bobot
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters, Andrew Reynolds
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief trigger class
**/
@@ -17,11 +17,13 @@
#ifndef __CVC4__THEORY__QUANTIFIERS__TRIGGER_H
#define __CVC4__THEORY__QUANTIFIERS__TRIGGER_H
-#include "theory/quantifiers/inst_match.h"
-#include "expr/node.h"
-#include "util/hash.h"
#include <map>
+#include "expr/node.h"
+#include "theory/quantifiers/inst_match.h"
+#include "options/quantifiers_options.h"
+
+// Forward declarations for defining the Trigger and TriggerTrie.
namespace CVC4 {
namespace theory {
@@ -31,29 +33,37 @@ namespace inst {
class IMGenerator;
class InstMatchGenerator;
+}/* CVC4::theory::inst namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
-//a collect of nodes representing a trigger
-class Trigger {
-private:
- /** the quantifiers engine */
- QuantifiersEngine* d_quantEngine;
- /** the quantifier this trigger is for */
- Node d_f;
- /** match generators */
- IMGenerator* d_mg;
-private:
- /** trigger constructor */
- Trigger( QuantifiersEngine* ie, Node f, std::vector< Node >& nodes, int matchOption = 0, bool smartTriggers = false );
-public:
- ~Trigger(){}
-public:
- std::vector< Node > d_nodes;
+
+namespace CVC4 {
+namespace theory {
+namespace inst {
+
+class TriggerTermInfo {
public:
+ TriggerTermInfo() : d_reqPol(0){}
+ ~TriggerTermInfo(){}
+ std::vector< Node > d_fv;
+ int d_reqPol;
+ Node d_reqPolEq;
+ void init( Node q, Node n, int reqPol = 0, Node reqPolEq = Node::null() );
+};
+
+/** A collect of nodes representing a trigger. */
+class Trigger {
+ public:
+ ~Trigger();
+
IMGenerator* getGenerator() { return d_mg; }
-public:
- /** reset instantiation round (call this whenever equivalence classes have changed) */
+
+ /** reset instantiation round (call this whenever equivalence
+ * classes have changed) */
void resetInstantiationRound();
- /** reset, eqc is the equivalence class to search in (search in any if eqc=null) */
+ /** reset, eqc is the equivalence class to search in (search in any
+ * if eqc=null) */
void reset( Node eqc );
/** get next match. must call reset( eqc ) once before this function. */
bool getNextMatch( Node f, InstMatch& m );
@@ -66,7 +76,7 @@ public:
int addTerm( Node t );
/** return whether this is a multi-trigger */
bool isMultiTrigger() { return d_nodes.size()>1; }
-public:
+
/** add all available instantiations exhaustively, in any equivalence class
if limitInst>0, limitInst is the max # of instantiations to try */
int addInstantiations( InstMatch& baseMatch );
@@ -74,51 +84,46 @@ public:
ie : quantifier engine;
f : forall something ....
nodes : (multi-)trigger
- matchOption : which policy to use for creating matches (one of InstMatchGenerator::MATCH_GEN_* )
+ matchOption : which policy to use for creating matches
+ (one of InstMatchGenerator::MATCH_GEN_* )
keepAll: don't remove unneeded patterns;
- trOption : policy for dealing with triggers that already existed (see below)
+ trOption : policy for dealing with triggers that already existed
+ (see below)
*/
enum{
TR_MAKE_NEW, //make new trigger even if it already may exist
TR_GET_OLD, //return a previous trigger if it had already been created
TR_RETURN_NULL //return null if a duplicate is found
};
- static Trigger* mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes,
- int matchOption = 0, bool keepAll = true, int trOption = TR_MAKE_NEW,
- bool smartTriggers = false );
+ static Trigger* mkTrigger( QuantifiersEngine* qe, Node f,
+ std::vector< Node >& nodes, int matchOption = 0,
+ bool keepAll = true, int trOption = TR_MAKE_NEW );
static Trigger* mkTrigger( QuantifiersEngine* qe, Node f, Node n,
- int matchOption = 0, bool keepAll = true, int trOption = TR_MAKE_NEW,
- bool smartTriggers = false );
-private:
- /** is subterm of trigger usable */
- static bool isUsable( Node n, Node q );
- static Node getIsUsableTrigger( Node n, Node f, bool pol = true, bool hasPol = false );
- /** collect all APPLY_UF pattern terms for f in n */
- static bool collectPatTerms2( Node f, Node n, std::map< Node, bool >& patMap, int tstrt, std::vector< Node >& exclude, bool pol, bool hasPol );
-public:
- //different strategies for choosing trigger terms
- enum {
- TS_MAX_TRIGGER = 0,
- TS_MIN_TRIGGER,
- TS_ALL,
- };
- static void collectPatTerms( QuantifiersEngine* qe, Node f, Node n, std::vector< Node >& patTerms, int tstrt, std::vector< Node >& exclude, bool filterInst = false );
-public:
+ int matchOption = 0, bool keepAll = true,
+ int trOption = TR_MAKE_NEW );
+ static void collectPatTerms( Node q, Node n, std::vector< Node >& patTerms, quantifiers::TriggerSelMode tstrt,
+ std::vector< Node >& exclude, std::map< Node, TriggerTermInfo >& tinfo,
+ bool filterInst = false );
/** is usable trigger */
static bool isUsableTrigger( Node n, Node q );
+ static Node getIsUsableTrigger( Node n, Node q );
static bool isAtomicTrigger( Node n );
static bool isAtomicTriggerKind( Kind k );
+ static bool isRelationalTrigger( Node n );
+ static bool isRelationalTriggerKind( Kind k );
static bool isCbqiKind( Kind k );
static bool isSimpleTrigger( Node n );
static bool isBooleanTermTrigger( Node n );
static bool isPureTheoryTrigger( Node n );
- static bool isLocalTheoryExt( Node n, std::vector< Node >& vars, std::vector< Node >& patTerms );
+ static int getTriggerWeight( Node n );
+ static bool isLocalTheoryExt( Node n, std::vector< Node >& vars,
+ std::vector< Node >& patTerms );
/** return data structure for producing matches for this trigger. */
static InstMatchGenerator* getInstMatchGenerator( Node q, Node n );
static Node getInversionVariable( Node n );
static Node getInversion( Node n, Node x );
/** get all variables that E-matching can possibly handle */
- static void getTriggerVariables( QuantifiersEngine* qe, Node icn, Node f, std::vector< Node >& t_vars );
+ static void getTriggerVariables( Node icn, Node f, std::vector< Node >& t_vars );
void debugPrint( const char * c ) {
Trace(c) << "TRIGGER( ";
@@ -128,17 +133,35 @@ public:
}
Trace(c) << " )";
}
-};
+private:
+ /** trigger constructor */
+ Trigger( QuantifiersEngine* ie, Node f, std::vector< Node >& nodes, int matchOption = 0 );
+
+ /** is subterm of trigger usable */
+ static bool isUsable( Node n, Node q );
+ static Node getIsUsableEq( Node q, Node eq );
+ static bool isUsableEqTerms( Node q, Node n1, Node n2 );
+ /** collect all APPLY_UF pattern terms for f in n */
+ static bool collectPatTerms2( Node q, Node n, std::map< Node, Node >& visited, std::map< Node, TriggerTermInfo >& tinfo,
+ quantifiers::TriggerSelMode tstrt, std::vector< Node >& exclude, std::vector< Node >& added,
+ bool pol, bool hasPol, bool epol, bool hasEPol );
+
+ std::vector< Node > d_nodes;
+
+ /** the quantifiers engine */
+ QuantifiersEngine* d_quantEngine;
+ /** the quantifier this trigger is for */
+ Node d_f;
+ /** match generators */
+ IMGenerator* d_mg;
+}; /* class Trigger */
/** a trie of triggers */
class TriggerTrie {
-private:
- inst::Trigger* getTrigger2( std::vector< Node >& nodes );
- void addTrigger2( std::vector< Node >& nodes, inst::Trigger* t );
public:
- TriggerTrie() : d_tr( NULL ){}
- inst::Trigger* d_tr;
- std::map< TNode, TriggerTrie* > d_children;
+ TriggerTrie();
+ ~TriggerTrie();
+
inst::Trigger* getTrigger( std::vector< Node >& nodes ){
std::vector< Node > temp;
temp.insert( temp.begin(), nodes.begin(), nodes.end() );
@@ -151,7 +174,13 @@ public:
std::sort( temp.begin(), temp.end() );
return addTrigger2( temp, t );
}
-};/* class inst::Trigger::Trigger */
+private:
+ inst::Trigger* getTrigger2( std::vector< Node >& nodes );
+ void addTrigger2( std::vector< Node >& nodes, inst::Trigger* t );
+
+ std::vector< inst::Trigger* > d_tr;
+ std::map< TNode, TriggerTrie* > d_children;
+};/* class inst::Trigger::TriggerTrie */
}/* CVC4::theory::inst namespace */
}/* CVC4::theory namespace */
diff --git a/src/theory/quantifiers_engine.cpp b/src/theory/quantifiers_engine.cpp
index 6fedc14f0..6d3b17254 100644
--- a/src/theory/quantifiers_engine.cpp
+++ b/src/theory/quantifiers_engine.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file quantifiers_engine.cpp
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): Francois Bobot
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of quantifiers engine class
**/
@@ -39,6 +39,10 @@
#include "theory/quantifiers/rewrite_engine.h"
#include "theory/quantifiers/term_database.h"
#include "theory/quantifiers/trigger.h"
+#include "theory/quantifiers/quant_split.h"
+#include "theory/quantifiers/anti_skolem.h"
+#include "theory/quantifiers/equality_infer.h"
+#include "theory/quantifiers/inst_propagator.h"
#include "theory/theory_engine.h"
#include "theory/uf/equality_engine.h"
#include "theory/uf/theory_uf.h"
@@ -51,49 +55,40 @@ using namespace CVC4::context;
using namespace CVC4::theory;
using namespace CVC4::theory::inst;
-unsigned QuantifiersModule::needsModel( Theory::Effort e ) {
- return QuantifiersEngine::QEFFORT_NONE;
-}
-
-eq::EqualityEngine * QuantifiersModule::getEqualityEngine() {
- return d_quantEngine->getMasterEqualityEngine();
-}
-
-bool QuantifiersModule::areEqual( TNode n1, TNode n2 ) {
- eq::EqualityEngine * ee = getEqualityEngine();
- return n1==n2 || ( ee->hasTerm( n1 ) && ee->hasTerm( n2 ) && ee->areEqual( n1, n2 ) );
-}
-
-bool QuantifiersModule::areDisequal( TNode n1, TNode n2 ) {
- eq::EqualityEngine * ee = getEqualityEngine();
- return n1!=n2 && ee->hasTerm( n1 ) && ee->hasTerm( n2 ) && ee->areDisequal( n1, n2, false );
-}
-
-TNode QuantifiersModule::getRepresentative( TNode n ) {
- eq::EqualityEngine * ee = getEqualityEngine();
- if( ee->hasTerm( n ) ){
- return ee->getRepresentative( n );
- }else{
- return n;
- }
-}
-
-quantifiers::TermDb * QuantifiersModule::getTermDatabase() {
- return d_quantEngine->getTermDatabase();
-}
-
QuantifiersEngine::QuantifiersEngine(context::Context* c, context::UserContext* u, TheoryEngine* te):
d_te( te ),
+ //d_quants(u),
+ d_quants_red(u),
d_lemmas_produced_c(u),
d_skolemized(u),
+ d_ierCounter_c(c),
+ //d_ierCounter(c),
+ //d_ierCounter_lc(c),
+ //d_ierCounterLastLc(c),
d_presolve(u, true),
d_presolve_in(u),
d_presolve_cache(u),
d_presolve_cache_wq(u),
d_presolve_cache_wic(u){
- d_eq_query = new EqualityQueryQuantifiersEngine( this );
+ //utilities
+ d_eq_query = new EqualityQueryQuantifiersEngine( c, this );
+ d_util.push_back( d_eq_query );
+
d_term_db = new quantifiers::TermDb( c, u, this );
+ d_util.push_back( d_term_db );
+
+ if( options::instPropagate() ){
+ d_inst_prop = new quantifiers::InstPropagator( this );
+ d_util.push_back( d_inst_prop );
+ d_inst_notify.push_back( d_inst_prop->getInstantiationNotify() );
+ }else{
+ d_inst_prop = NULL;
+ }
+
d_tr_trie = new inst::TriggerTrie;
+ d_curr_effort_level = QEFFORT_NONE;
+ d_conflict = false;
+ d_num_added_lemmas_round = 0;
d_hasAddedLemma = false;
//don't add true lemma
d_lemmas_produced_c[d_term_db->d_true] = true;
@@ -121,6 +116,8 @@ QuantifiersEngine::QuantifiersEngine(context::Context* c, context::UserContext*
d_sg_gen = NULL;
d_inst_engine = NULL;
d_i_cbqi = NULL;
+ d_qsplit = NULL;
+ d_anti_skolem = NULL;
d_model_engine = NULL;
d_bint = NULL;
d_rr_engine = NULL;
@@ -134,13 +131,23 @@ QuantifiersEngine::QuantifiersEngine(context::Context* c, context::UserContext*
d_builder = NULL;
d_total_inst_count_debug = 0;
- d_ierCounter = 0;
+ //allow theory combination to go first, once initially
+ d_ierCounter = options::instWhenTcFirst() ? 0 : 1;
+ d_ierCounter_c = d_ierCounter;
d_ierCounter_lc = 0;
- //if any strategy called only on last call, use phase 3
- d_inst_when_phase = options::cbqi() ? 3 : 2;
+ d_ierCounterLastLc = 0;
+ d_inst_when_phase = 1 + ( options::instWhenPhase()<1 ? 1 : options::instWhenPhase() );
}
QuantifiersEngine::~QuantifiersEngine(){
+ for(std::map< Node, inst::CDInstMatchTrie* >::iterator
+ i = d_c_inst_match_trie.begin(), iend = d_c_inst_match_trie.end();
+ i != iend; ++i)
+ {
+ delete (*i).second;
+ }
+ d_c_inst_match_trie.clear();
+
delete d_alpha_equiv;
delete d_builder;
delete d_rr_engine;
@@ -161,6 +168,9 @@ QuantifiersEngine::~QuantifiersEngine(){
delete d_uee;
delete d_fs;
delete d_i_cbqi;
+ delete d_qsplit;
+ delete d_anti_skolem;
+ delete d_inst_prop;
}
EqualityQueryQuantifiersEngine* QuantifiersEngine::getEqualityQuery() {
@@ -237,6 +247,15 @@ void QuantifiersEngine::finishInit(){
d_lte_part_inst = new quantifiers::LtePartialInst( this, c );
d_modules.push_back( d_lte_part_inst );
}
+ if( ( options::finiteModelFind() && options::quantDynamicSplit()!=quantifiers::QUANT_DSPLIT_MODE_NONE ) ||
+ options::quantDynamicSplit()==quantifiers::QUANT_DSPLIT_MODE_AGG ){
+ d_qsplit = new quantifiers::QuantDSplit( this, c );
+ d_modules.push_back( d_qsplit );
+ }
+ if( options::quantAntiSkolem() ){
+ d_anti_skolem = new quantifiers::QuantAntiSkolem( this );
+ d_modules.push_back( d_anti_skolem );
+ }
if( options::quantAlphaEquiv() ){
d_alpha_equiv = new quantifiers::AlphaEquivalence( this );
}
@@ -257,6 +276,7 @@ void QuantifiersEngine::finishInit(){
if( needsRelDom ){
d_rel_dom = new quantifiers::RelevantDomain( this, d_model );
+ d_util.push_back( d_rel_dom );
}
if( needsBuilder ){
@@ -285,13 +305,17 @@ QuantifiersModule * QuantifiersEngine::getOwner( Node q ) {
}
}
-void QuantifiersEngine::setOwner( Node q, QuantifiersModule * m ) {
+void QuantifiersEngine::setOwner( Node q, QuantifiersModule * m, int priority ) {
QuantifiersModule * mo = getOwner( q );
if( mo!=m ){
if( mo!=NULL ){
- Trace("quant-warn") << "WARNING: setting owner of " << q << " to " << ( m ? m->identify() : "null" ) << ", but already has owner " << mo->identify() << "!" << std::endl;
+ if( priority<=d_owner_priority[q] ){
+ Trace("quant-warn") << "WARNING: setting owner of " << q << " to " << ( m ? m->identify() : "null" ) << ", but already has owner " << mo->identify() << " with higher priority!" << std::endl;
+ return;
+ }
}
d_owner[q] = m;
+ d_owner_priority[q] = priority;
}
}
@@ -323,11 +347,6 @@ void QuantifiersEngine::check( Theory::Effort e ){
Trace("quant-engine-debug") << "Master equality engine not consistent, return." << std::endl;
return;
}
- if( e==Theory::EFFORT_FULL ){
- d_ierCounter++;
- }else if( e==Theory::EFFORT_LAST_CALL ){
- d_ierCounter_lc++;
- }
bool needsCheck = !d_lemmas_waiting.empty();
unsigned needsModelE = QEFFORT_NONE;
std::vector< QuantifiersModule* > qm;
@@ -346,6 +365,8 @@ void QuantifiersEngine::check( Theory::Effort e ){
}
}
+ d_conflict = false;
+ d_num_added_lemmas_round = 0;
d_hasAddedLemma = false;
bool setIncomplete = false;
if( e==Theory::EFFORT_LAST_CALL ){
@@ -357,50 +378,72 @@ void QuantifiersEngine::check( Theory::Effort e ){
}
bool usedModelBuilder = false;
- Trace("quant-engine-debug") << "Quantifiers Engine call to check, level = " << e << std::endl;
+ Trace("quant-engine-debug2") << "Quantifiers Engine call to check, level = " << e << ", needsCheck=" << needsCheck << std::endl;
if( needsCheck ){
- Trace("quant-engine") << "Quantifiers Engine check, level = " << e << std::endl;
+ //flush previous lemmas (for instance, if was interupted), or other lemmas to process
+ flushLemmas();
+ if( d_hasAddedLemma ){
+ return;
+ }
+ if( !d_recorded_inst.empty() ){
+ Trace("quant-engine-debug") << "Removing " << d_recorded_inst.size() << " instantiations..." << std::endl;
+ //remove explicitly recorded instantiations
+ for( unsigned i=0; i<d_recorded_inst.size(); i++ ){
+ removeInstantiationInternal( d_recorded_inst[i].first, d_recorded_inst[i].second );
+ }
+ d_recorded_inst.clear();
+ }
+
if( Trace.isOn("quant-engine-debug") ){
+ Trace("quant-engine-debug") << "Quantifiers Engine check, level = " << e << std::endl;
+ Trace("quant-engine-debug") << " depth : " << d_ierCounter_c << std::endl;
Trace("quant-engine-debug") << " modules to check : ";
for( unsigned i=0; i<qm.size(); i++ ){
Trace("quant-engine-debug") << qm[i]->identify() << " ";
}
Trace("quant-engine-debug") << std::endl;
Trace("quant-engine-debug") << " # quantified formulas = " << d_model->getNumAssertedQuantifiers() << std::endl;
- if( d_model->getNumToReduceQuantifiers()>0 ){
- Trace("quant-engine-debug") << " # quantified formulas to reduce = " << d_model->getNumToReduceQuantifiers() << std::endl;
- }
if( !d_lemmas_waiting.empty() ){
Trace("quant-engine-debug") << " lemmas waiting = " << d_lemmas_waiting.size() << std::endl;
}
Trace("quant-engine-debug") << " Theory engine finished : " << !d_te->needCheck() << std::endl;
Trace("quant-engine-debug") << " Needs model effort : " << needsModelE << std::endl;
- Trace("quant-engine-debug") << "Resetting all modules..." << std::endl;
}
- if( Trace.isOn("quant-engine-ee") ){
- Trace("quant-engine-ee") << "Equality engine : " << std::endl;
- debugPrintEqualityEngine( "quant-engine-ee" );
+ if( Trace.isOn("quant-engine-ee-pre") ){
+ Trace("quant-engine-ee-pre") << "Equality engine (pre-inference): " << std::endl;
+ debugPrintEqualityEngine( "quant-engine-ee-pre" );
}
if( Trace.isOn("quant-engine-assert") ){
Trace("quant-engine-assert") << "Assertions : " << std::endl;
getTheoryEngine()->printAssertions("quant-engine-assert");
}
- //reset relevant information
-
- //flush previous lemmas (for instance, if was interupted), or other lemmas to process
- flushLemmas();
- if( d_hasAddedLemma ){
- return;
+ //reset utilities
+ Trace("quant-engine-debug") << "Resetting all utilities..." << std::endl;
+ for( unsigned i=0; i<d_util.size(); i++ ){
+ Trace("quant-engine-debug2") << "Reset " << d_util[i]->identify().c_str() << "..." << std::endl;
+ if( !d_util[i]->reset( e ) ){
+ flushLemmas();
+ if( d_hasAddedLemma ){
+ return;
+ }else{
+ //should only fail reset if added a lemma
+ Assert( false );
+ }
+ }
}
- Trace("quant-engine-debug2") << "Reset term db..." << std::endl;
- d_term_db->reset( e );
- d_eq_query->reset();
- if( d_rel_dom ){
- d_rel_dom->reset();
+ if( Trace.isOn("quant-engine-ee") ){
+ Trace("quant-engine-ee") << "Equality engine : " << std::endl;
+ debugPrintEqualityEngine( "quant-engine-ee" );
}
+
+ //reset the model
+ Trace("quant-engine-debug") << "Reset model..." << std::endl;
d_model->reset_round();
+
+ //reset the modules
+ Trace("quant-engine-debug") << "Resetting all modules..." << std::endl;
for( unsigned i=0; i<d_modules.size(); i++ ){
Trace("quant-engine-debug2") << "Reset " << d_modules[i]->identify().c_str() << std::endl;
d_modules[i]->reset_round( e );
@@ -410,6 +453,7 @@ void QuantifiersEngine::check( Theory::Effort e ){
flushLemmas();
if( d_hasAddedLemma ){
return;
+
}
if( e==Theory::EFFORT_LAST_CALL ){
@@ -422,6 +466,7 @@ void QuantifiersEngine::check( Theory::Effort e ){
}
Trace("quant-engine-debug") << "Check modules that needed check..." << std::endl;
for( unsigned quant_e = QEFFORT_CONFLICT; quant_e<=QEFFORT_LAST_CALL; quant_e++ ){
+ d_curr_effort_level = quant_e;
bool success = true;
//build the model if any module requested it
if( needsModelE==quant_e ){
@@ -440,6 +485,10 @@ void QuantifiersEngine::check( Theory::Effort e ){
for( unsigned i=0; i<qm.size(); i++ ){
Trace("quant-engine-debug") << "Check " << qm[i]->identify().c_str() << " at effort " << quant_e << "..." << std::endl;
qm[i]->check( e, quant_e );
+ if( d_conflict ){
+ Trace("quant-engine-debug") << "...conflict!" << std::endl;
+ break;
+ }
}
}
//flush all current lemmas
@@ -447,25 +496,45 @@ void QuantifiersEngine::check( Theory::Effort e ){
//if we have added one, stop
if( d_hasAddedLemma ){
break;
- }else if( e==Theory::EFFORT_LAST_CALL && quant_e==QEFFORT_MODEL ){
- //if we have a chance not to set incomplete
- if( !setIncomplete ){
- setIncomplete = false;
- //check if we should set the incomplete flag
- for( unsigned i=0; i<qm.size(); i++ ){
- if( !qm[i]->checkComplete() ){
- Trace("quant-engine-debug") << "Set incomplete because " << qm[i]->identify().c_str() << " was incomplete." << std::endl;
+ }else{
+ Assert( !d_conflict );
+ if( quant_e==QEFFORT_CONFLICT ){
+ if( e==Theory::EFFORT_FULL ){
+ //increment if a last call happened, we are not strictly enforcing interleaving, or already were in phase
+ if( d_ierCounterLastLc!=d_ierCounter_lc || !options::instWhenStrictInterleave() || d_ierCounter%d_inst_when_phase!=0 ){
+ d_ierCounter = d_ierCounter + 1;
+ d_ierCounterLastLc = d_ierCounter_lc;
+ d_ierCounter_c = d_ierCounter_c.get() + 1;
+ }
+ }else if( e==Theory::EFFORT_LAST_CALL ){
+ d_ierCounter_lc = d_ierCounter_lc + 1;
+ }
+ }else if( quant_e==QEFFORT_MODEL ){
+ if( e==Theory::EFFORT_LAST_CALL ){
+ if( !d_recorded_inst.empty() ){
setIncomplete = true;
+ }
+ //if we have a chance not to set incomplete
+ if( !setIncomplete ){
+ setIncomplete = false;
+ //check if we should set the incomplete flag
+ for( unsigned i=0; i<qm.size(); i++ ){
+ if( !qm[i]->checkComplete() ){
+ Trace("quant-engine-debug") << "Set incomplete because " << qm[i]->identify().c_str() << " was incomplete." << std::endl;
+ setIncomplete = true;
+ break;
+ }
+ }
+ }
+ //if setIncomplete = false, we will answer SAT, otherwise we will run at quant_e QEFFORT_LAST_CALL
+ if( !setIncomplete ){
break;
}
}
}
- //if setIncomplete = false, we will answer SAT, otherwise we will run at quant_e QEFFORT_LAST_CALL
- if( !setIncomplete ){
- break;
- }
}
}
+ d_curr_effort_level = QEFFORT_NONE;
Trace("quant-engine-debug") << "Done check modules that needed check." << std::endl;
if( d_hasAddedLemma ){
//debug information
@@ -476,9 +545,9 @@ void QuantifiersEngine::check( Theory::Effort e ){
}
}
}
- Trace("quant-engine") << "Finished quantifiers engine check." << std::endl;
+ Trace("quant-engine-debug2") << "Finished quantifiers engine check." << std::endl;
}else{
- Trace("quant-engine") << "Quantifiers Engine does not need check." << std::endl;
+ Trace("quant-engine-debug2") << "Quantifiers Engine does not need check." << std::endl;
}
//SAT case
@@ -507,35 +576,38 @@ void QuantifiersEngine::check( Theory::Effort e ){
}
}
+void QuantifiersEngine::notifyCombineTheories() {
+ //if allowing theory combination to happen at most once between instantiation rounds
+ //d_ierCounter = 1;
+ //d_ierCounterLastLc = -1;
+}
+
bool QuantifiersEngine::reduceQuantifier( Node q ) {
- std::map< Node, bool >::iterator it = d_quants_red.find( q );
+ BoolMap::const_iterator it = d_quants_red.find( q );
if( it==d_quants_red.end() ){
- if( d_alpha_equiv ){
- Trace("quant-engine-red") << "Alpha equivalence " << q << "?" << std::endl;
- //add equivalence with another quantified formula
- if( !d_alpha_equiv->registerQuantifier( q ) ){
- Trace("quant-engine-red") << "...alpha equivalence success." << std::endl;
- ++(d_statistics.d_red_alpha_equiv);
- d_quants_red[q] = true;
- return true;
+ Node lem;
+ std::map< Node, Node >::iterator itr = d_quants_red_lem.find( q );
+ if( itr==d_quants_red_lem.end() ){
+ if( d_alpha_equiv ){
+ Trace("quant-engine-red") << "Alpha equivalence " << q << "?" << std::endl;
+ //add equivalence with another quantified formula
+ lem = d_alpha_equiv->reduceQuantifier( q );
+ if( !lem.isNull() ){
+ Trace("quant-engine-red") << "...alpha equivalence success." << std::endl;
+ ++(d_statistics.d_red_alpha_equiv);
+ }
}
+ d_quants_red_lem[q] = lem;
+ }else{
+ lem = itr->second;
}
- if( d_lte_part_inst && !q.getAttribute(LtePartialInstAttribute()) ){
- //will partially instantiate
- Trace("quant-engine-red") << "LTE: Partially instantiate " << q << "?" << std::endl;
- if( d_lte_part_inst->addQuantifier( q ) ){
- Trace("quant-engine-red") << "...LTE partially instantiate success." << std::endl;
- //delayed reduction : assert to model
- d_model->assertQuantifier( q, true );
- ++(d_statistics.d_red_lte_partial_inst);
- d_quants_red[q] = true;
- return true;
- }
+ if( !lem.isNull() ){
+ getOutputChannel().lemma( lem );
}
- d_quants_red[q] = false;
- return false;
+ d_quants_red[q] = !lem.isNull();
+ return !lem.isNull();
}else{
- return it->second;
+ return (*it).second;
}
}
@@ -581,7 +653,7 @@ bool QuantifiersEngine::registerQuantifier( Node f ){
return true;
}
}else{
- return it->second;
+ return (*it).second;
}
}
@@ -673,6 +745,29 @@ void QuantifiersEngine::addTermToDatabase( Node n, bool withinQuant, bool within
}
}
+void QuantifiersEngine::eqNotifyNewClass(TNode t) {
+ addTermToDatabase( t );
+ if( d_eq_query->getEqualityInference() ){
+ d_eq_query->getEqualityInference()->eqNotifyNewClass( t );
+ }
+}
+
+void QuantifiersEngine::eqNotifyPreMerge(TNode t1, TNode t2) {
+ if( d_eq_query->getEqualityInference() ){
+ d_eq_query->getEqualityInference()->eqNotifyMerge( t1, t2 );
+ }
+}
+
+void QuantifiersEngine::eqNotifyPostMerge(TNode t1, TNode t2) {
+
+}
+
+void QuantifiersEngine::eqNotifyDisequal(TNode t1, TNode t2, TNode reason) {
+ //if( d_qcf ){
+ // d_qcf->assertDisequal( t1, t2 );
+ //}
+}
+
void QuantifiersEngine::computeTermVector( Node f, InstMatch& m, std::vector< Node >& vars, std::vector< Node >& terms ){
for( size_t i=0; i<f[0].getNumChildren(); i++ ){
Node n = m.get( i );
@@ -683,73 +778,39 @@ void QuantifiersEngine::computeTermVector( Node f, InstMatch& m, std::vector< No
}
}
-bool QuantifiersEngine::addInstantiationInternal( Node f, std::vector< Node >& vars, std::vector< Node >& terms, bool doVts ){
- Assert( f.getKind()==FORALL );
- Assert( vars.size()==terms.size() );
- Node body = getInstantiation( f, vars, terms );
- //do virtual term substitution
- if( doVts ){
- body = Rewriter::rewrite( body );
- Trace("quant-vts-debug") << "Rewrite vts symbols in " << body << std::endl;
- Node body_r = d_term_db->rewriteVtsSymbols( body );
- Trace("quant-vts-debug") << " ...result: " << body_r << std::endl;
- body = body_r;
+
+bool QuantifiersEngine::recordInstantiationInternal( Node q, std::vector< Node >& terms, bool modEq, bool addedLem ) {
+ if( !addedLem ){
+ //record the instantiation for deletion later
+ d_recorded_inst.push_back( std::pair< Node, std::vector< Node > >( q, terms ) );
}
- body = quantifiers::QuantifiersRewriter::preprocess( body, true );
- Trace("inst-debug") << "...preprocess to " << body << std::endl;
- Trace("inst-assert") << "(assert " << body << ")" << std::endl;
- //make the lemma
- Node lem = NodeManager::currentNM()->mkNode( kind::OR, f.negate(), body );
- //check for duplication
- if( addLemma( lem ) ){
- d_total_inst_debug[f]++;
- d_temp_inst_debug[f]++;
- d_total_inst_count_debug++;
- Trace("inst") << "*** Instantiate " << f << " with " << std::endl;
- for( unsigned i=0; i<terms.size(); i++ ){
- if( Trace.isOn("inst") ){
- Trace("inst") << " " << terms[i];
- if( Trace.isOn("inst-debug") ){
- Trace("inst-debug") << ", type=" << terms[i].getType() << ", var_type=" << f[0][i].getType();
- }
- Trace("inst") << std::endl;
- }
- if( options::cbqi() ){
- Node icf = quantifiers::TermDb::getInstConstAttr(terms[i]);
- bool bad_inst = false;
- if( !icf.isNull() ){
- if( icf==f ){
- bad_inst = true;
- }else{
- bad_inst = quantifiers::TermDb::containsTerms( terms[i], d_term_db->d_inst_constants[f] );
- }
- }
- if( bad_inst ){
- Trace("inst")<< "***& Bad Instantiate " << f << " with " << std::endl;
- for( unsigned i=0; i<terms.size(); i++ ){
- Trace("inst") << " " << terms[i] << std::endl;
- }
- Unreachable("Bad instantiation");
- }
- }
- Assert( terms[i].getType().isSubtypeOf( f[0][i].getType() ) );
+ if( options::incrementalSolving() ){
+ Trace("inst-add-debug") << "Adding into context-dependent inst trie, modEq = " << modEq << std::endl;
+ inst::CDInstMatchTrie* imt;
+ std::map< Node, inst::CDInstMatchTrie* >::iterator it = d_c_inst_match_trie.find( q );
+ if( it!=d_c_inst_match_trie.end() ){
+ imt = it->second;
+ }else{
+ imt = new CDInstMatchTrie( getUserContext() );
+ d_c_inst_match_trie[q] = imt;
}
- if( options::instMaxLevel()!=-1 ){
- uint64_t maxInstLevel = 0;
- for( unsigned i=0; i<terms.size(); i++ ){
- if( terms[i].hasAttribute(InstLevelAttribute()) ){
- if( terms[i].getAttribute(InstLevelAttribute())>maxInstLevel ){
- maxInstLevel = terms[i].getAttribute(InstLevelAttribute());
- }
- }
- }
- setInstantiationLevelAttr( body, f[1], maxInstLevel+1 );
+ return imt->addInstMatch( this, q, terms, getUserContext(), modEq );
+ }else{
+ Trace("inst-add-debug") << "Adding into inst trie" << std::endl;
+ return d_inst_match_trie[q].addInstMatch( this, q, terms, modEq );
+ }
+}
+
+bool QuantifiersEngine::removeInstantiationInternal( Node q, std::vector< Node >& terms ) {
+ if( options::incrementalSolving() ){
+ std::map< Node, inst::CDInstMatchTrie* >::iterator it = d_c_inst_match_trie.find( q );
+ if( it!=d_c_inst_match_trie.end() ){
+ return it->second->removeInstMatch( this, q, terms );
+ }else{
+ return false;
}
- ++(d_statistics.d_instantiations);
- return true;
}else{
- ++(d_statistics.d_inst_duplicate);
- return false;
+ return d_inst_match_trie[q].removeInstMatch( this, q, terms );
}
}
@@ -764,7 +825,7 @@ void QuantifiersEngine::setInstantiationLevelAttr( Node n, Node qn, uint64_t lev
Trace("inst-level-debug") << "Set instantiation level " << n << " to " << level << std::endl;
}
Assert( n.getNumChildren()==qn.getNumChildren() );
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
setInstantiationLevelAttr( n[i], qn[i], level );
}
}
@@ -776,7 +837,7 @@ void QuantifiersEngine::setInstantiationLevelAttr( Node n, uint64_t level ){
n.setAttribute(ila,level);
Trace("inst-level-debug") << "Set instantiation level " << n << " to " << level << std::endl;
}
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
setInstantiationLevelAttr( n[i], level );
}
}
@@ -811,7 +872,7 @@ Node QuantifiersEngine::getSubstitute( Node n, std::vector< Node >& terms ){
}
-Node QuantifiersEngine::getInstantiation( Node q, std::vector< Node >& vars, std::vector< Node >& terms ){
+Node QuantifiersEngine::getInstantiation( Node q, std::vector< Node >& vars, std::vector< Node >& terms, bool doVts ){
Node body;
//process partial instantiation if necessary
if( d_term_db->d_vars[q].size()!=vars.size() ){
@@ -842,60 +903,81 @@ Node QuantifiersEngine::getInstantiation( Node q, std::vector< Node >& vars, std
}
}
}
+ if( doVts ){
+ //do virtual term substitution
+ body = Rewriter::rewrite( body );
+ Trace("quant-vts-debug") << "Rewrite vts symbols in " << body << std::endl;
+ Node body_r = d_term_db->rewriteVtsSymbols( body );
+ Trace("quant-vts-debug") << " ...result: " << body_r << std::endl;
+ body = body_r;
+ }
return body;
}
-Node QuantifiersEngine::getInstantiation( Node q, InstMatch& m ){
+Node QuantifiersEngine::getInstantiation( Node q, InstMatch& m, bool doVts ){
std::vector< Node > vars;
std::vector< Node > terms;
computeTermVector( q, m, vars, terms );
- return getInstantiation( q, vars, terms );
+ return getInstantiation( q, vars, terms, doVts );
}
-Node QuantifiersEngine::getInstantiation( Node q, std::vector< Node >& terms ) {
- return getInstantiation( q, d_term_db->d_vars[q], terms );
+Node QuantifiersEngine::getInstantiation( Node q, std::vector< Node >& terms, bool doVts ) {
+ return getInstantiation( q, d_term_db->d_vars[q], terms, doVts );
}
/*
-bool QuantifiersEngine::existsInstantiation( Node f, InstMatch& m, bool modEq, bool modInst ){
+bool QuantifiersEngine::existsInstantiation( Node f, InstMatch& m, bool modEq ){
if( options::incrementalSolving() ){
if( d_c_inst_match_trie.find( f )!=d_c_inst_match_trie.end() ){
- if( d_c_inst_match_trie[f]->existsInstMatch( this, f, m, getUserContext(), modEq, modInst ) ){
+ if( d_c_inst_match_trie[f]->existsInstMatch( this, f, m, getUserContext(), modEq ) ){
return true;
}
}
}else{
if( d_inst_match_trie.find( f )!=d_inst_match_trie.end() ){
- if( d_inst_match_trie[f].existsInstMatch( this, f, m, modEq, modInst ) ){
+ if( d_inst_match_trie[f].existsInstMatch( this, f, m, modEq ) ){
return true;
}
}
}
- //also check model builder (it may contain instantiations internally)
- if( d_builder && d_builder->existsInstantiation( f, m, modEq, modInst ) ){
- return true;
- }
return false;
}
*/
-bool QuantifiersEngine::addLemma( Node lem, bool doCache ){
+bool QuantifiersEngine::addLemma( Node lem, bool doCache, bool doRewrite ){
if( doCache ){
- lem = Rewriter::rewrite(lem);
+ if( doRewrite ){
+ lem = Rewriter::rewrite(lem);
+ }
Trace("inst-add-debug") << "Adding lemma : " << lem << std::endl;
- if( d_lemmas_produced_c.find( lem )==d_lemmas_produced_c.end() ){
+ BoolMap::const_iterator itp = d_lemmas_produced_c.find( lem );
+ if( itp==d_lemmas_produced_c.end() || !(*itp).second ){
//d_curr_out->lemma( lem, false, true );
d_lemmas_produced_c[ lem ] = true;
d_lemmas_waiting.push_back( lem );
Trace("inst-add-debug") << "Added lemma" << std::endl;
+ d_num_added_lemmas_round++;
return true;
}else{
Trace("inst-add-debug") << "Duplicate." << std::endl;
return false;
}
}else{
+ //do not need to rewrite, will be rewritten after sending
d_lemmas_waiting.push_back( lem );
+ d_num_added_lemmas_round++;
+ return true;
+ }
+}
+
+bool QuantifiersEngine::removeLemma( Node lem ) {
+ std::vector< Node >::iterator it = std::find( d_lemmas_waiting.begin(), d_lemmas_waiting.end(), lem );
+ if( it!=d_lemmas_waiting.end() ){
+ d_lemmas_waiting.erase( it, it + 1 );
+ d_lemmas_produced_c[ lem ] = false;
return true;
+ }else{
+ return false;
}
}
@@ -903,16 +985,16 @@ void QuantifiersEngine::addRequirePhase( Node lit, bool req ){
d_phase_req_waiting[lit] = req;
}
-bool QuantifiersEngine::addInstantiation( Node q, InstMatch& m, bool mkRep, bool modEq, bool modInst, bool doVts ){
+bool QuantifiersEngine::addInstantiation( Node q, InstMatch& m, bool mkRep, bool modEq, bool doVts ){
std::vector< Node > terms;
m.getTerms( q, terms );
- return addInstantiation( q, terms, mkRep, modEq, modInst, doVts );
+ return addInstantiation( q, terms, mkRep, modEq, doVts );
}
-bool QuantifiersEngine::addInstantiation( Node q, std::vector< Node >& terms, bool mkRep, bool modEq, bool modInst, bool doVts ) {
+bool QuantifiersEngine::addInstantiation( Node q, std::vector< Node >& terms, bool mkRep, bool modEq, bool doVts ) {
// For resource-limiting (also does a time check).
getOutputChannel().safePoint(options::quantifierStep());
-
+ Assert( !d_conflict );
Assert( terms.size()==q[0].getNumChildren() );
Trace("inst-add-debug") << "For quantified formula " << q << ", add instantiation: " << std::endl;
for( unsigned i=0; i<terms.size(); i++ ){
@@ -921,18 +1003,42 @@ bool QuantifiersEngine::addInstantiation( Node q, std::vector< Node >& terms, bo
if( terms[i].isNull() ){
terms[i] = d_term_db->getModelBasisTerm( q[0][i].getType() );
}
- //make it representative, this is helpful for recognizing duplication
if( mkRep ){
//pick the best possible representative for instantiation, based on past use and simplicity of term
terms[i] = d_eq_query->getInternalRepresentative( terms[i], q, i );
}else{
//ensure the type is correct
- terms[i] = quantifiers::TermDb::mkNodeType( terms[i], q[0][i].getType() );
+ terms[i] = quantifiers::TermDb::ensureType( terms[i], q[0][i].getType() );
}
Trace("inst-add-debug") << " -> " << terms[i] << std::endl;
- Assert( !terms[i].isNull() );
+ if( terms[i].isNull() ){
+ Trace("inst-add-debug") << " --> Failed to make term vector, due to term/type restrictions." << std::endl;
+ return false;
+ }
#ifdef CVC4_ASSERTIONS
- Assert( !quantifiers::TermDb::containsUninterpretedConstant( terms[i] ) );
+ bool bad_inst = false;
+ if( quantifiers::TermDb::containsUninterpretedConstant( terms[i] ) ){
+ bad_inst = true;
+ }else if( !terms[i].getType().isSubtypeOf( q[0][i].getType() ) ){
+ bad_inst = true;
+ }else if( options::cbqi() ){
+ Node icf = quantifiers::TermDb::getInstConstAttr(terms[i]);
+ if( !icf.isNull() ){
+ if( icf==q ){
+ bad_inst = true;
+ }else{
+ bad_inst = quantifiers::TermDb::containsTerms( terms[i], d_term_db->d_inst_constants[q] );
+ }
+ }
+ }
+ //this assertion is critical to soundness
+ if( bad_inst ){
+ Trace("inst")<< "***& Bad Instantiate " << q << " with " << std::endl;
+ for( unsigned j=0; j<terms.size(); j++ ){
+ Trace("inst") << " " << terms[j] << std::endl;
+ }
+ Assert( false );
+ }
#endif
}
@@ -944,55 +1050,101 @@ bool QuantifiersEngine::addInstantiation( Node q, std::vector< Node >& terms, bo
}
}
}
- //check for entailment
+
+ //check for positive entailment
if( options::instNoEntail() ){
+ //TODO: check consistency of equality engine (if not aborting on utility's reset)
std::map< TNode, TNode > subs;
for( unsigned i=0; i<terms.size(); i++ ){
subs[q[0][i]] = terms[i];
}
if( d_term_db->isEntailed( q[1], subs, false, true ) ){
- Trace("inst-add-debug") << " -> Currently entailed." << std::endl;
+ Trace("inst-add-debug") << " --> Currently entailed." << std::endl;
return false;
}
+ //Node eval = d_term_db->evaluateTerm( q[1], subs, false, true );
+ //Trace("ajr-temp") << "Instantiation evaluates to : " << std::endl;
+ //Trace("ajr-temp") << " " << eval << std::endl;
}
- //check for duplication
- bool alreadyExists = false;
- if( options::incrementalSolving() ){
- Trace("inst-add-debug") << "Adding into context-dependent inst trie, modEq = " << modEq << ", modInst = " << modInst << std::endl;
- inst::CDInstMatchTrie* imt;
- std::map< Node, inst::CDInstMatchTrie* >::iterator it = d_c_inst_match_trie.find( q );
- if( it!=d_c_inst_match_trie.end() ){
- imt = it->second;
- }else{
- imt = new CDInstMatchTrie( getUserContext() );
- d_c_inst_match_trie[q] = imt;
- }
- alreadyExists = !imt->addInstMatch( this, q, terms, getUserContext(), modEq, modInst );
- }else{
- Trace("inst-add-debug") << "Adding into inst trie" << std::endl;
- alreadyExists = !d_inst_match_trie[q].addInstMatch( this, q, terms, modEq, modInst );
- }
+ //check for term vector duplication
+ bool alreadyExists = !recordInstantiationInternal( q, terms, modEq );
if( alreadyExists ){
- Trace("inst-add-debug") << " -> Already exists." << std::endl;
+ Trace("inst-add-debug") << " --> Already exists." << std::endl;
++(d_statistics.d_inst_duplicate_eq);
return false;
}
-
- //add the instantiation
+ //construct the instantiation
Trace("inst-add-debug") << "Constructing instantiation..." << std::endl;
- bool addedInst = addInstantiationInternal( q, d_term_db->d_vars[q], terms, doVts );
- //report the result
- if( addedInst ){
- Trace("inst-add-debug") << " -> Success." << std::endl;
+ Assert( d_term_db->d_vars[q].size()==terms.size() );
+ Node body = getInstantiation( q, d_term_db->d_vars[q], terms, doVts ); //do virtual term substitution
+ body = quantifiers::QuantifiersRewriter::preprocess( body, true );
+ Trace("inst-debug") << "...preprocess to " << body << std::endl;
+
+ //construct the lemma
+ Trace("inst-assert") << "(assert " << body << ")" << std::endl;
+ body = Rewriter::rewrite(body);
+ Node lem = NodeManager::currentNM()->mkNode( kind::OR, q.negate(), body );
+ lem = Rewriter::rewrite(lem);
+
+ //check for lemma duplication
+ if( addLemma( lem, true, false ) ){
+ d_total_inst_debug[q]++;
+ d_temp_inst_debug[q]++;
+ d_total_inst_count_debug++;
+ if( Trace.isOn("inst") ){
+ Trace("inst") << "*** Instantiate " << q << " with " << std::endl;
+ for( unsigned i=0; i<terms.size(); i++ ){
+ if( Trace.isOn("inst") ){
+ Trace("inst") << " " << terms[i];
+ if( Trace.isOn("inst-debug") ){
+ Trace("inst-debug") << ", type=" << terms[i].getType() << ", var_type=" << q[0][i].getType();
+ }
+ Trace("inst") << std::endl;
+ }
+ }
+ }
+ if( options::instMaxLevel()!=-1 ){
+ uint64_t maxInstLevel = 0;
+ for( unsigned i=0; i<terms.size(); i++ ){
+ if( terms[i].hasAttribute(InstLevelAttribute()) ){
+ if( terms[i].getAttribute(InstLevelAttribute())>maxInstLevel ){
+ maxInstLevel = terms[i].getAttribute(InstLevelAttribute());
+ }
+ }
+ }
+ setInstantiationLevelAttr( body, q[1], maxInstLevel+1 );
+ }
+ if( d_curr_effort_level>QEFFORT_CONFLICT && d_curr_effort_level<QEFFORT_NONE ){
+ //notify listeners
+ for( unsigned j=0; j<d_inst_notify.size(); j++ ){
+ if( !d_inst_notify[j]->notifyInstantiation( d_curr_effort_level, q, lem, terms, body ) ){
+ Trace("inst-add-debug") << "...we are in conflict." << std::endl;
+ d_conflict = true;
+ Assert( !d_lemmas_waiting.empty() );
+ break;
+ }
+ }
+ }
+ Trace("inst-add-debug") << " --> Success." << std::endl;
+ ++(d_statistics.d_instantiations);
return true;
}else{
- Trace("inst-add-debug") << " -> Lemma already exists." << std::endl;
+ Trace("inst-add-debug") << " --> Lemma already exists." << std::endl;
+ ++(d_statistics.d_inst_duplicate);
return false;
}
}
+bool QuantifiersEngine::removeInstantiation( Node q, Node lem, std::vector< Node >& terms ) {
+ //lem must occur in d_waiting_lemmas
+ if( removeLemma( lem ) ){
+ return removeInstantiationInternal( q, terms );
+ }else{
+ return false;
+ }
+}
bool QuantifiersEngine::addSplit( Node n, bool reqPhase, bool reqPhasePol ){
n = Rewriter::rewrite( n );
@@ -1012,7 +1164,12 @@ bool QuantifiersEngine::addSplitEquality( Node n1, Node n2, bool reqPhase, bool
return addSplit( fm );
}
+void QuantifiersEngine::markRelevant( Node q ) {
+ d_model->markRelevant( q );
+}
+
bool QuantifiersEngine::getInstWhenNeedsCheck( Theory::Effort e ) {
+ Trace("quant-engine-debug2") << "Get inst when needs check, counts=" << d_ierCounter << ", " << d_ierCounter_lc << std::endl;
//determine if we should perform check, based on instWhenMode
bool performCheck = false;
if( options::instWhenMode()==quantifiers::INST_WHEN_FULL ){
@@ -1020,9 +1177,9 @@ bool QuantifiersEngine::getInstWhenNeedsCheck( Theory::Effort e ) {
}else if( options::instWhenMode()==quantifiers::INST_WHEN_FULL_DELAY ){
performCheck = ( e >= Theory::EFFORT_FULL ) && !getTheoryEngine()->needCheck();
}else if( options::instWhenMode()==quantifiers::INST_WHEN_FULL_LAST_CALL ){
- performCheck = ( ( e==Theory::EFFORT_FULL && d_ierCounter%d_inst_when_phase==0 ) || e==Theory::EFFORT_LAST_CALL );
+ performCheck = ( ( e==Theory::EFFORT_FULL && d_ierCounter%d_inst_when_phase!=0 ) || e==Theory::EFFORT_LAST_CALL );
}else if( options::instWhenMode()==quantifiers::INST_WHEN_FULL_DELAY_LAST_CALL ){
- performCheck = ( ( e==Theory::EFFORT_FULL && !getTheoryEngine()->needCheck() && d_ierCounter%d_inst_when_phase==0 ) || e==Theory::EFFORT_LAST_CALL );
+ performCheck = ( ( e==Theory::EFFORT_FULL && !getTheoryEngine()->needCheck() && d_ierCounter%d_inst_when_phase!=0 ) || e==Theory::EFFORT_LAST_CALL );
}else if( options::instWhenMode()==quantifiers::INST_WHEN_LAST_CALL ){
performCheck = ( e >= Theory::EFFORT_LAST_CALL );
}else{
@@ -1106,6 +1263,18 @@ void QuantifiersEngine::printSynthSolution( std::ostream& out ) {
}
}
+void QuantifiersEngine::getInstantiations( std::map< Node, std::vector< Node > >& insts ) {
+ if( options::incrementalSolving() ){
+ for( std::map< Node, inst::CDInstMatchTrie* >::iterator it = d_c_inst_match_trie.begin(); it != d_c_inst_match_trie.end(); ++it ){
+ it->second->getInstantiations( insts[it->first], it->first, this );
+ }
+ }else{
+ for( std::map< Node, inst::InstMatchTrie >::iterator it = d_inst_match_trie.begin(); it != d_inst_match_trie.end(); ++it ){
+ it->second.getInstantiations( insts[it->first], it->first, this );
+ }
+ }
+}
+
QuantifiersEngine::Statistics::Statistics()
: d_time("theory::QuantifiersEngine::time"),
d_num_quant("QuantifiersEngine::Num_Quantifiers", 0),
@@ -1204,9 +1373,57 @@ void QuantifiersEngine::debugPrintEqualityEngine( const char * c ) {
}
}
-void EqualityQueryQuantifiersEngine::reset(){
+
+EqualityQueryQuantifiersEngine::EqualityQueryQuantifiersEngine( context::Context* c, QuantifiersEngine* qe ) : d_qe( qe ), d_eqi_counter( c ), d_reset_count( 0 ){
+ if( options::inferArithTriggerEq() ){
+ d_eq_inference = new quantifiers::EqualityInference( c, options::inferArithTriggerEqExp() );
+ }else{
+ d_eq_inference = NULL;
+ }
+}
+
+EqualityQueryQuantifiersEngine::~EqualityQueryQuantifiersEngine(){
+ delete d_eq_inference;
+}
+
+bool EqualityQueryQuantifiersEngine::reset( Theory::Effort e ){
d_int_rep.clear();
d_reset_count++;
+ return processInferences( e );
+}
+
+bool EqualityQueryQuantifiersEngine::processInferences( Theory::Effort e ) {
+ if( options::inferArithTriggerEq() ){
+ eq::EqualityEngine* ee = getEngine();
+ //updated implementation
+ while( d_eqi_counter.get()<d_eq_inference->getNumPendingMerges() ){
+ Node eq = d_eq_inference->getPendingMerge( d_eqi_counter.get() );
+ Node eq_exp = d_eq_inference->getPendingMergeExplanation( d_eqi_counter.get() );
+ Trace("quant-engine-ee-proc") << "processInferences : Infer : " << eq << std::endl;
+ Trace("quant-engine-ee-proc") << " explanation : " << eq_exp << std::endl;
+ Assert( ee->hasTerm( eq[0] ) );
+ Assert( ee->hasTerm( eq[1] ) );
+ if( ee->areDisequal( eq[0], eq[1], false ) ){
+ Trace("quant-engine-ee-proc") << "processInferences : Conflict : " << eq << std::endl;
+ if( Trace.isOn("term-db-lemma") ){
+ Trace("term-db-lemma") << "Disequal terms, equal by normalization : " << eq[0] << " " << eq[1] << "!!!!" << std::endl;
+ if( !d_qe->getTheoryEngine()->needCheck() ){
+ Trace("term-db-lemma") << " all theories passed with no lemmas." << std::endl;
+ //this should really never happen (implies arithmetic is incomplete when sharing is enabled)
+ Assert( false );
+ }
+ Trace("term-db-lemma") << " add split on : " << eq << std::endl;
+ }
+ d_qe->addSplit( eq );
+ return false;
+ }else{
+ ee->assertEquality( eq, true, eq_exp );
+ d_eqi_counter = d_eqi_counter.get() + 1;
+ }
+ }
+ Assert( ee->consistent() );
+ }
+ return true;
}
bool EqualityQueryQuantifiersEngine::hasTerm( Node a ){
@@ -1237,39 +1454,43 @@ bool EqualityQueryQuantifiersEngine::areEqual( Node a, Node b ){
}
bool EqualityQueryQuantifiersEngine::areDisequal( Node a, Node b ){
- eq::EqualityEngine* ee = getEngine();
- if( ee->hasTerm( a ) && ee->hasTerm( b ) ){
- if( ee->areDisequal( a, b, false ) ){
- return true;
+ if( a==b ){
+ return false;
+ }else{
+ eq::EqualityEngine* ee = getEngine();
+ if( ee->hasTerm( a ) && ee->hasTerm( b ) ){
+ if( ee->areDisequal( a, b, false ) ){
+ return true;
+ }
}
+ return false;
}
- return false;
}
Node EqualityQueryQuantifiersEngine::getInternalRepresentative( Node a, Node f, int index ){
Assert( f.isNull() || f.getKind()==FORALL );
Node r = getRepresentative( a );
- if( !options::internalReps() ){
- return r;
- }else{
- if( options::finiteModelFind() ){
- if( r.isConst() ){
- //map back from values assigned by model, if any
- if( d_qe->getModel() ){
- std::map< Node, Node >::iterator it = d_qe->getModel()->d_rep_set.d_values_to_terms.find( r );
- if( it!=d_qe->getModel()->d_rep_set.d_values_to_terms.end() ){
- r = it->second;
- r = getRepresentative( r );
- }else{
- if( r.getType().isSort() ){
- Trace("internal-rep-warn") << "No representative for UF constant." << std::endl;
- //should never happen : UF constants should never escape model
- Assert( false );
- }
+ if( options::finiteModelFind() ){
+ if( r.isConst() && quantifiers::TermDb::containsUninterpretedConstant( r ) ){
+ //map back from values assigned by model, if any
+ if( d_qe->getModel() ){
+ std::map< Node, Node >::iterator it = d_qe->getModel()->d_rep_set.d_values_to_terms.find( r );
+ if( it!=d_qe->getModel()->d_rep_set.d_values_to_terms.end() ){
+ r = it->second;
+ r = getRepresentative( r );
+ }else{
+ if( r.getType().isSort() ){
+ Trace("internal-rep-warn") << "No representative for UF constant." << std::endl;
+ //should never happen : UF constants should never escape model
+ Assert( false );
}
}
}
}
+ }
+ if( options::quantRepMode()==quantifiers::QUANT_REP_MODE_EE ){
+ return r;
+ }else{
TypeNode v_tn = f.isNull() ? a.getType() : f[0][index].getType();
std::map< Node, Node >::iterator itir = d_int_rep[v_tn].find( r );
if( itir==d_int_rep[v_tn].end() ){
@@ -1309,7 +1530,7 @@ Node EqualityQueryQuantifiersEngine::getInternalRepresentative( Node a, Node f,
if( d_rep_score.find( r_best )==d_rep_score.end() ){
d_rep_score[ r_best ] = d_reset_count;
}
- Trace("internal-rep-select") << "...Choose " << r_best << std::endl;
+ Trace("internal-rep-select") << "...Choose " << r_best << " with score " << r_best_score << std::endl;
Assert( r_best.getType().isSubtypeOf( v_tn ) );
d_int_rep[v_tn][r] = r_best;
if( r_best!=a ){
@@ -1416,6 +1637,10 @@ void EqualityQueryQuantifiersEngine::getEquivalenceClass( Node a, std::vector< N
Assert( std::find( eqc.begin(), eqc.end(), a )!=eqc.end() );
}
+TNode EqualityQueryQuantifiersEngine::getCongruentTerm( Node f, std::vector< TNode >& args ) {
+ return d_qe->getTermDatabase()->getCongruentTerm( f, args );
+}
+
//helper functions
Node EqualityQueryQuantifiersEngine::getInstance( Node n, const std::vector< Node >& eqc, std::hash_map<TNode, Node, TNodeHashFunction>& cache ){
@@ -1435,23 +1660,6 @@ Node EqualityQueryQuantifiersEngine::getInstance( Node n, const std::vector< Nod
}
}
-/*
-int getDepth( Node n ){
- if( n.getNumChildren()==0 ){
- return 0;
- }else{
- int maxDepth = -1;
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- int depth = getDepth( n[i] );
- if( depth>maxDepth ){
- maxDepth = depth;
- }
- }
- return maxDepth;
- }
-}
-*/
-
//-2 : invalid, -1 : undesired, otherwise : smaller the score, the better
int EqualityQueryQuantifiersEngine::getRepScore( Node n, Node f, int index, TypeNode v_tn ){
if( options::cbqi() && quantifiers::TermDb::hasInstConstAttr(n) ){ //reject
@@ -1468,8 +1676,12 @@ int EqualityQueryQuantifiersEngine::getRepScore( Node n, Node f, int index, Type
return options::instLevelInputOnly() ? -1 : 0;
}
}else{
- //score prefers earliest use of this term as a representative
- return d_rep_score.find( n )==d_rep_score.end() ? -1 : d_rep_score[n];
+ if( options::quantRepMode()==quantifiers::QUANT_REP_MODE_FIRST ){
+ //score prefers earliest use of this term as a representative
+ return d_rep_score.find( n )==d_rep_score.end() ? -1 : d_rep_score[n];
+ }else{
+ Assert( options::quantRepMode()==quantifiers::QUANT_REP_MODE_DEPTH );
+ return quantifiers::TermDb::getTermDepth( n );
+ }
}
- //return ( d_rep_score.find( n )==d_rep_score.end() ? 100 : 0 ) + getDepth( n ); //term depth
}
diff --git a/src/theory/quantifiers_engine.h b/src/theory/quantifiers_engine.h
index aa770ad67..4ee66f9e7 100644
--- a/src/theory/quantifiers_engine.h
+++ b/src/theory/quantifiers_engine.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file quantifiers_engine.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): Francois Bobot
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Theory instantiator, Instantiation Engine classes
**/
@@ -44,42 +44,11 @@ namespace quantifiers {
class TermDbSygus;
}
-class QuantifiersModule {
-protected:
- QuantifiersEngine* d_quantEngine;
+class InstantiationNotify {
public:
- QuantifiersModule( QuantifiersEngine* qe ) : d_quantEngine( qe ){}
- virtual ~QuantifiersModule(){}
- //get quantifiers engine
- QuantifiersEngine* getQuantifiersEngine() { return d_quantEngine; }
- /** presolve */
- virtual void presolve() {}
- /* whether this module needs to check this round */
- virtual bool needsCheck( Theory::Effort e ) { return e>=Theory::EFFORT_LAST_CALL; }
- /* whether this module needs a model built */
- virtual unsigned needsModel( Theory::Effort e );
- /* reset at a round */
- virtual void reset_round( Theory::Effort e ){}
- /* Call during quantifier engine's check */
- virtual void check( Theory::Effort e, unsigned quant_e ) = 0;
- /* check was complete (e.g. no lemmas implies a model) */
- virtual bool checkComplete() { return true; }
- /* Called for new quantifiers */
- virtual void preRegisterQuantifier( Node q ) {}
- /* Called for new quantifiers after owners are finalized */
- virtual void registerQuantifier( Node q ) = 0;
- virtual void assertNode( Node n ) {}
- virtual void propagate( Theory::Effort level ){}
- virtual Node getNextDecisionRequest() { return TNode::null(); }
- /** Identify this module (for debugging, dynamic configuration, etc..) */
- virtual std::string identify() const = 0;
-public:
- eq::EqualityEngine * getEqualityEngine();
- bool areDisequal( TNode n1, TNode n2 );
- bool areEqual( TNode n1, TNode n2 );
- TNode getRepresentative( TNode n );
- quantifiers::TermDb * getTermDatabase();
-};/* class QuantifiersModule */
+ InstantiationNotify(){}
+ virtual bool notifyInstantiation( unsigned quant_e, Node q, Node lem, std::vector< Node >& terms, Node body ) = 0;
+};
namespace quantifiers {
class FirstOrderModel;
@@ -99,6 +68,11 @@ namespace quantifiers {
class QuantEqualityEngine;
class FullSaturation;
class InstStrategyCbqi;
+ class InstStrategyCegqi;
+ class QuantDSplit;
+ class QuantAntiSkolem;
+ class EqualityInference;
+ class InstPropagator;
}/* CVC4::theory::quantifiers */
namespace inst {
@@ -110,6 +84,7 @@ class EqualityQueryQuantifiersEngine;
class QuantifiersEngine {
friend class quantifiers::InstantiationEngine;
+ friend class quantifiers::InstStrategyCegqi;
friend class quantifiers::ModelEngine;
friend class quantifiers::RewriteEngine;
friend class quantifiers::QuantConflictFind;
@@ -121,8 +96,12 @@ class QuantifiersEngine {
private:
/** reference to theory engine object */
TheoryEngine* d_te;
+ /** vector of utilities for quantifiers */
+ std::vector< QuantifiersUtil* > d_util;
/** vector of modules for quantifiers */
std::vector< QuantifiersModule* > d_modules;
+ /** instantiation notify */
+ std::vector< InstantiationNotify* > d_inst_notify;
/** equality query class */
EqualityQueryQuantifiersEngine* d_eq_query;
/** for computing relevance of quantifiers */
@@ -157,6 +136,12 @@ private:
quantifiers::FullSaturation * d_fs;
/** counterexample-based quantifier instantiation */
quantifiers::InstStrategyCbqi * d_i_cbqi;
+ /** quantifiers splitting */
+ quantifiers::QuantDSplit * d_qsplit;
+ /** quantifiers anti-skolemization */
+ quantifiers::QuantAntiSkolem * d_anti_skolem;
+ /** quantifiers instantiation propagtor */
+ quantifiers::InstPropagator * d_inst_prop;
public: //effort levels
enum {
QEFFORT_CONFLICT,
@@ -166,11 +151,21 @@ public: //effort levels
//none
QEFFORT_NONE,
};
+private: //this information is reset during check
+ /** current effort level */
+ unsigned d_curr_effort_level;
+ /** are we in conflict */
+ bool d_conflict;
+ /** number of lemmas we actually added this round (for debugging) */
+ unsigned d_num_added_lemmas_round;
+ /** has added lemma this round */
+ bool d_hasAddedLemma;
private:
/** list of all quantifiers seen */
std::map< Node, bool > d_quants;
/** quantifiers reduced */
- std::map< Node, bool > d_quants_red;
+ BoolMap d_quants_red;
+ std::map< Node, Node > d_quants_red_lem;
/** list of all lemmas produced */
//std::map< Node, bool > d_lemmas_produced;
BoolMap d_lemmas_produced_c;
@@ -178,11 +173,11 @@ private:
std::vector< Node > d_lemmas_waiting;
/** phase requirements waiting */
std::map< Node, bool > d_phase_req_waiting;
- /** has added lemma this round */
- bool d_hasAddedLemma;
/** list of all instantiations produced for each quantifier */
std::map< Node, inst::InstMatchTrie > d_inst_match_trie;
std::map< Node, inst::CDInstMatchTrie* > d_c_inst_match_trie;
+ /** recorded instantiations */
+ std::vector< std::pair< Node, std::vector< Node > > > d_recorded_inst;
/** quantifiers that have been skolemized */
BoolMap d_skolemized;
/** term database */
@@ -195,9 +190,11 @@ private:
std::map< Node, int > d_total_inst_debug;
std::map< Node, int > d_temp_inst_debug;
int d_total_inst_count_debug;
- /** inst round counters */
+ /** inst round counters TODO: make context-dependent? */
+ context::CDO< int > d_ierCounter_c;
int d_ierCounter;
int d_ierCounter_lc;
+ int d_ierCounterLastLc;
int d_inst_when_phase;
/** has presolve been called */
context::CDO< bool > d_presolve;
@@ -253,14 +250,19 @@ public: //modules
quantifiers::FullSaturation * getFullSaturation() { return d_fs; }
/** get inst strategy cbqi */
quantifiers::InstStrategyCbqi * getInstStrategyCbqi() { return d_i_cbqi; }
+ /** get quantifiers splitting */
+ quantifiers::QuantDSplit * getQuantDSplit() { return d_qsplit; }
+ /** get quantifiers anti-skolemization */
+ quantifiers::QuantAntiSkolem * getQuantAntiSkolem() { return d_anti_skolem; }
private:
/** owner of quantified formulas */
std::map< Node, QuantifiersModule * > d_owner;
+ std::map< Node, int > d_owner_priority;
public:
/** get owner */
QuantifiersModule * getOwner( Node q );
/** set owner */
- void setOwner( Node q, QuantifiersModule * m );
+ void setOwner( Node q, QuantifiersModule * m, int priority = 0 );
/** considers */
bool hasOwnership( Node q, QuantifiersModule * m = NULL );
public:
@@ -270,6 +272,8 @@ public:
void presolve();
/** check at level */
void check( Theory::Effort e );
+ /** notify that theories were combined */
+ void notifyCombineTheories();
/** register quantifier */
bool registerQuantifier( Node f );
/** register quantifier */
@@ -281,41 +285,53 @@ public:
/** get next decision request */
Node getNextDecisionRequest();
private:
- /** reduce quantifier */
+ /** reduceQuantifier, return true if reduced */
bool reduceQuantifier( Node q );
/** compute term vector */
void computeTermVector( Node f, InstMatch& m, std::vector< Node >& vars, std::vector< Node >& terms );
- /** instantiate f with arguments terms */
- bool addInstantiationInternal( Node f, std::vector< Node >& vars, std::vector< Node >& terms, bool doVts = false );
+ /** record instantiation, return true if it was non-duplicate */
+ bool recordInstantiationInternal( Node q, std::vector< Node >& terms, bool modEq = false, bool addedLem = true );
+ /** remove instantiation */
+ bool removeInstantiationInternal( Node q, std::vector< Node >& terms );
/** set instantiation level attr */
static void setInstantiationLevelAttr( Node n, Node qn, uint64_t level );
/** flush lemmas */
void flushLemmas();
public:
/** get instantiation */
- Node getInstantiation( Node q, std::vector< Node >& vars, std::vector< Node >& terms );
+ Node getInstantiation( Node q, std::vector< Node >& vars, std::vector< Node >& terms, bool doVts = false );
/** get instantiation */
- Node getInstantiation( Node q, InstMatch& m );
+ Node getInstantiation( Node q, InstMatch& m, bool doVts = false );
/** get instantiation */
- Node getInstantiation( Node q, std::vector< Node >& terms );
+ Node getInstantiation( Node q, std::vector< Node >& terms, bool doVts = false );
/** do substitution */
Node getSubstitute( Node n, std::vector< Node >& terms );
/** add lemma lem */
- bool addLemma( Node lem, bool doCache = true );
+ bool addLemma( Node lem, bool doCache = true, bool doRewrite = true );
+ /** remove pending lemma */
+ bool removeLemma( Node lem );
/** add require phase */
void addRequirePhase( Node lit, bool req );
/** do instantiation specified by m */
- bool addInstantiation( Node q, InstMatch& m, bool mkRep = true, bool modEq = false, bool modInst = false, bool doVts = false );
+ bool addInstantiation( Node q, InstMatch& m, bool mkRep = false, bool modEq = false, bool doVts = false );
/** add instantiation */
- bool addInstantiation( Node q, std::vector< Node >& terms, bool mkRep = true, bool modEq = false, bool modInst = false, bool doVts = false );
+ bool addInstantiation( Node q, std::vector< Node >& terms, bool mkRep = false, bool modEq = false, bool doVts = false );
+ /** remove pending instantiation */
+ bool removeInstantiation( Node q, Node lem, std::vector< Node >& terms );
/** split on node n */
bool addSplit( Node n, bool reqPhase = false, bool reqPhasePol = true );
/** add split equality */
bool addSplitEquality( Node n1, Node n2, bool reqPhase = false, bool reqPhasePol = true );
+ /** mark relevant quantified formula, this will indicate it should be checked before the others */
+ void markRelevant( Node q );
/** has added lemma */
bool hasAddedLemma() { return !d_lemmas_waiting.empty() || d_hasAddedLemma; }
+ /** is in conflict */
+ bool inConflict() { return d_conflict; }
/** get number of waiting lemmas */
unsigned getNumLemmasWaiting() { return d_lemmas_waiting.size(); }
+ /** get number of waiting lemmas */
+ unsigned getNumLemmasAddedThisRound() { return d_num_added_lemmas_round; }
/** get needs check */
bool getInstWhenNeedsCheck( Theory::Effort e );
/** get user pat mode */
@@ -333,6 +349,11 @@ public:
inst::TriggerTrie* getTriggerDatabase() { return d_tr_trie; }
/** add term to database */
void addTermToDatabase( Node n, bool withinQuant = false, bool withinInstClosure = false );
+ /** notification when master equality engine is updated */
+ void eqNotifyNewClass(TNode t);
+ void eqNotifyPreMerge(TNode t1, TNode t2);
+ void eqNotifyPostMerge(TNode t1, TNode t2);
+ void eqNotifyDisequal(TNode t1, TNode t2, TNode reason);
/** get the master equality engine */
eq::EqualityEngine* getMasterEqualityEngine() ;
/** debug print equality engine */
@@ -342,6 +363,8 @@ public:
void printInstantiations( std::ostream& out );
/** print solution for synthesis conjectures */
void printSynthSolution( std::ostream& out );
+ /** get instantiations */
+ void getInstantiations( std::map< Node, std::vector< Node > >& insts );
/** statistics class */
class Statistics {
public:
@@ -376,6 +399,9 @@ class EqualityQueryQuantifiersEngine : public EqualityQuery
private:
/** pointer to theory engine */
QuantifiersEngine* d_qe;
+ /** quantifiers equality inference */
+ quantifiers::EqualityInference * d_eq_inference;
+ context::CDO< unsigned > d_eqi_counter;
/** internal representatives */
std::map< TypeNode, std::map< Node, Node > > d_int_rep;
/** rep score */
@@ -383,15 +409,21 @@ private:
/** reset count */
int d_reset_count;
+ /** processInferences : will merge equivalence classes in master equality engine, if possible */
+ bool processInferences( Theory::Effort e );
/** node contains */
Node getInstance( Node n, const std::vector< Node >& eqc, std::hash_map<TNode, Node, TNodeHashFunction>& cache );
/** get score */
int getRepScore( Node n, Node f, int index, TypeNode v_tn );
+ /** flatten representatives */
+ void flattenRepresentatives( std::map< TypeNode, std::vector< Node > >& reps );
public:
- EqualityQueryQuantifiersEngine( QuantifiersEngine* qe ) : d_qe( qe ), d_reset_count( 0 ){}
- ~EqualityQueryQuantifiersEngine(){}
+ EqualityQueryQuantifiersEngine( context::Context* c, QuantifiersEngine* qe );
+ virtual ~EqualityQueryQuantifiersEngine();
/** reset */
- void reset();
+ bool reset( Theory::Effort e );
+ /** identify */
+ std::string identify() const { return "EqualityQueryQE"; }
/** general queries about equality */
bool hasTerm( Node a );
Node getRepresentative( Node a );
@@ -399,13 +431,14 @@ public:
bool areDisequal( Node a, Node b );
eq::EqualityEngine* getEngine();
void getEquivalenceClass( Node a, std::vector< Node >& eqc );
+ TNode getCongruentTerm( Node f, std::vector< TNode >& args );
/** getInternalRepresentative gets the current best representative in the equivalence class of a, based on some criteria.
If cbqi is active, this will return a term in the equivalence class of "a" that does
not contain instantiation constants, if such a term exists.
*/
Node getInternalRepresentative( Node a, Node f, int index );
- /** flatten representatives */
- void flattenRepresentatives( std::map< TypeNode, std::vector< Node > >& reps );
+ /** get quantifiers equality inference */
+ quantifiers::EqualityInference * getEqualityInference() { return d_eq_inference; }
}; /* EqualityQueryQuantifiersEngine */
}/* CVC4::theory namespace */
diff --git a/src/theory/rep_set.cpp b/src/theory/rep_set.cpp
index a90a4cf17..d7178a8c1 100644
--- a/src/theory/rep_set.cpp
+++ b/src/theory/rep_set.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file rep_set.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): Kshitij Bansal
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of representative set
**/
diff --git a/src/theory/rep_set.h b/src/theory/rep_set.h
index 2df824b5d..08fc7dd52 100644
--- a/src/theory/rep_set.h
+++ b/src/theory/rep_set.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file rep_set.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Representative set class and utilities
**/
diff --git a/src/theory/rewriter.cpp b/src/theory/rewriter.cpp
index d89724cbd..18ded60a8 100644
--- a/src/theory/rewriter.cpp
+++ b/src/theory/rewriter.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file rewriter.cpp
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): Liana Hadarean, Clark Barrett
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Morgan Deters, Liana Hadarean
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/rewriter.h b/src/theory/rewriter.h
index 5ad6adca8..fc53121e4 100644
--- a/src/theory/rewriter.h
+++ b/src/theory/rewriter.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file rewriter.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): Tim King
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief The Rewriter class
**
diff --git a/src/theory/rewriter_attributes.h b/src/theory/rewriter_attributes.h
index d2bbd44ae..5f709de6a 100644
--- a/src/theory/rewriter_attributes.h
+++ b/src/theory/rewriter_attributes.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file rewriter_attributes.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Rewriter attributes
**
diff --git a/src/theory/rewriter_tables_template.h b/src/theory/rewriter_tables_template.h
index d79f464b5..4d41c023d 100644
--- a/src/theory/rewriter_tables_template.h
+++ b/src/theory/rewriter_tables_template.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file rewriter_tables_template.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Morgan Deters, Tim King
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Rewriter tables for various theories
**
diff --git a/src/theory/sets/card_unused_implementation.cpp b/src/theory/sets/card_unused_implementation.cpp
new file mode 100644
index 000000000..488ee1026
--- /dev/null
+++ b/src/theory/sets/card_unused_implementation.cpp
@@ -0,0 +1,312 @@
+// Removing old cardinality implementation, dumping it here.
+
+///////////////////////////////////////////////////////////////
+// Commenting out processCard, creates confusion when writing
+// processCard2
+///////////////////////////////////////////////////////////////
+
+
+// void TheorySetsPrivate::processCard(Theory::Effort level) {
+// if(level != Theory::EFFORT_FULL) return;
+
+
+// Trace("sets-card") << "[sets-card] processCard( " << level << ")" << std::endl;
+// Trace("sets-card") << "[sets-card] # processed terms = " << d_processedCardTerms.size() << std::endl;
+// Trace("sets-card") << "[sets-card] # processed pairs = " << d_processedCardPairs.size() << std::endl;
+// NodeManager* nm = NodeManager::currentNM();
+
+// bool newLemmaGenerated = false;
+
+// // Introduce lemma
+// for(typeof(d_cardTerms.begin()) it = d_cardTerms.begin();
+// it != d_cardTerms.end(); ++it) {
+
+// for(eq::EqClassIterator j(d_equalityEngine.getRepresentative((*it)[0]), &d_equalityEngine);
+// !j.isFinished(); ++j) {
+
+// Node n = nm->mkNode(kind::CARD, (*j));
+
+// if(d_processedCardTerms.find(n) != d_processedCardTerms.end()) {
+// continue;
+// }
+
+// Trace("sets-card") << "[sets-card] Processing " << n << " in eq cl of " << (*it) << std::endl;
+
+// newLemmaGenerated = true;
+// d_processedCardTerms.insert(n);
+
+// Kind k = n[0].getKind();
+
+// if(k == kind::SINGLETON) {
+// d_external.d_out->lemma(nm->mkNode(kind::EQUAL,
+// n,
+// nm->mkConst(Rational(1))));
+// continue;
+// } else {
+// d_external.d_out->lemma(nm->mkNode(kind::GEQ,
+// n,
+// nm->mkConst(Rational(0))));
+// }
+
+// // rest of the processing is for compound terms
+// if(k != kind::UNION && k != kind::INTERSECTION && k != kind::SETMINUS) {
+// continue;
+// }
+
+// Node s = min(n[0][0], n[0][1]);
+// Node t = max(n[0][0], n[0][1]);
+// bool isUnion = (k == kind::UNION);
+// Assert(Rewriter::rewrite(s) == s);
+// Assert(Rewriter::rewrite(t) == t);
+
+// typeof(d_processedCardPairs.begin()) processedInfo = d_processedCardPairs.find(make_pair(s, t));
+
+// if(processedInfo == d_processedCardPairs.end()) {
+
+// Node sNt = nm->mkNode(kind::INTERSECTION, s, t);
+// sNt = Rewriter::rewrite(sNt);
+// Node sMt = nm->mkNode(kind::SETMINUS, s, t);
+// sMt = Rewriter::rewrite(sMt);
+// Node tMs = nm->mkNode(kind::SETMINUS, t, s);
+// tMs = Rewriter::rewrite(tMs);
+
+// Node card_s = nm->mkNode(kind::CARD, s);
+// Node card_t = nm->mkNode(kind::CARD, t);
+// Node card_sNt = nm->mkNode(kind::CARD, sNt);
+// Node card_sMt = nm->mkNode(kind::CARD, sMt);
+// Node card_tMs = nm->mkNode(kind::CARD, tMs);
+
+// Node lem;
+
+// // for s
+// lem = nm->mkNode(kind::EQUAL,
+// card_s,
+// nm->mkNode(kind::PLUS, card_sNt, card_sMt));
+// d_external.d_out->lemma(lem);
+
+// // for t
+// lem = nm->mkNode(kind::EQUAL,
+// card_t,
+// nm->mkNode(kind::PLUS, card_sNt, card_tMs));
+
+// d_external.d_out->lemma(lem);
+
+// // for union
+// if(isUnion) {
+// lem = nm->mkNode(kind::EQUAL,
+// n, // card(s union t)
+// nm->mkNode(kind::PLUS, card_sNt, card_sMt, card_tMs));
+// d_external.d_out->lemma(lem);
+// }
+
+// d_processedCardPairs.insert(make_pair(make_pair(s, t), isUnion));
+
+// } else if(isUnion && processedInfo->second == false) {
+
+// Node sNt = nm->mkNode(kind::INTERSECTION, s, t);
+// sNt = Rewriter::rewrite(sNt);
+// Node sMt = nm->mkNode(kind::SETMINUS, s, t);
+// sMt = Rewriter::rewrite(sMt);
+// Node tMs = nm->mkNode(kind::SETMINUS, t, s);
+// tMs = Rewriter::rewrite(tMs);
+
+// Node card_s = nm->mkNode(kind::CARD, s);
+// Node card_t = nm->mkNode(kind::CARD, t);
+// Node card_sNt = nm->mkNode(kind::CARD, sNt);
+// Node card_sMt = nm->mkNode(kind::CARD, sMt);
+// Node card_tMs = nm->mkNode(kind::CARD, tMs);
+
+// Assert(Rewriter::rewrite(n[0]) == n[0]);
+
+// Node lem = nm->mkNode(kind::EQUAL,
+// n, // card(s union t)
+// nm->mkNode(kind::PLUS, card_sNt, card_sMt, card_tMs));
+// d_external.d_out->lemma(lem);
+
+// processedInfo->second = true;
+// }
+
+// }//equivalence class loop
+
+// }//d_cardTerms loop
+
+// if(newLemmaGenerated) {
+// Trace("sets-card") << "[sets-card] New introduce done. Returning." << std::endl;
+// return;
+// }
+
+
+
+// // Leaves disjoint lemmas
+// buildGraph();
+
+// // Leaves disjoint lemmas
+// for(typeof(leaves.begin()) it = leaves.begin(); it != leaves.end(); ++it) {
+// TNode l1 = (*it);
+// if(d_equalityEngine.getRepresentative(l1).getKind() == kind::EMPTYSET) continue;
+// for(typeof(leaves.begin()) jt = leaves.begin(); jt != leaves.end(); ++jt) {
+// TNode l2 = (*jt);
+
+// if(d_equalityEngine.getRepresentative(l2).getKind() == kind::EMPTYSET) continue;
+
+// if( l1 == l2 ) continue;
+
+// Node l1_inter_l2 = nm->mkNode(kind::INTERSECTION, min(l1, l2), max(l1, l2));
+// l1_inter_l2 = Rewriter::rewrite(l1_inter_l2);
+// Node emptySet = nm->mkConst<EmptySet>(EmptySet(nm->toType(l1_inter_l2.getType())));
+// if(d_equalityEngine.hasTerm(l1_inter_l2) &&
+// d_equalityEngine.hasTerm(emptySet) &&
+// d_equalityEngine.areEqual(l1_inter_l2, emptySet)) {
+// Debug("sets-card-graph") << "[sets-card-graph] Disjoint (asserted): " << l1 << " and " << l2 << std::endl;
+// continue; // known to be disjoint
+// }
+
+// std::set<TNode> l1_ancestors = getReachable(edgesBk, l1);
+// std::set<TNode> l2_ancestors = getReachable(edgesBk, l2);
+
+// // have a disjoint edge
+// bool loop = true;
+// bool equality = false;
+// for(typeof(l1_ancestors.begin()) l1_it = l1_ancestors.begin();
+// l1_it != l1_ancestors.end() && loop; ++l1_it) {
+// for(typeof(l2_ancestors.begin()) l2_it = l2_ancestors.begin();
+// l2_it != l2_ancestors.end() && loop; ++l2_it) {
+// TNode n1 = (*l1_it);
+// TNode n2 = (*l2_it);
+// if(disjoint.find(make_pair(n1, n2)) != disjoint.find(make_pair(n2, n1))) {
+// loop = false;
+// }
+// if(n1 == n2) {
+// equality = true;
+// }
+// if(d_equalityEngine.hasTerm(n1) && d_equalityEngine.hasTerm(n2) &&
+// d_equalityEngine.areEqual(n1, n2)) {
+// equality = true;
+// }
+// }
+// }
+// if(loop == false) {
+// Debug("sets-card-graph") << "[sets-card-graph] Disjoint (always): " << l1 << " and " << l2 << std::endl;
+// continue;
+// }
+// if(equality == false) {
+// Debug("sets-card-graph") << "[sets-card-graph] No equality found: " << l1 << " and " << l2 << std::endl;
+// continue;
+// }
+
+// Node lem = nm->mkNode(kind::OR,
+// nm->mkNode(kind::EQUAL, l1_inter_l2, emptySet),
+// nm->mkNode(kind::LT, nm->mkConst(Rational(0)),
+// nm->mkNode(kind::CARD, l1_inter_l2)));
+
+// d_external.d_out->lemma(lem);
+// Trace("sets-card") << "[sets-card] Guessing disjointness of : " << l1 << " and " << l2 << std::endl;
+// if(Debug.isOn("sets-card-disjoint")) {
+// Debug("sets-card-disjoint") << "[sets-card-disjoint] Lemma for " << l1 << " and " << l2 << " generated because:" << std::endl;
+// for(typeof(disjoint.begin()) it = disjoint.begin(); it != disjoint.end(); ++it) {
+// Debug("sets-card-disjoint") << "[sets-card-disjoint] " << it->first << " " << it->second << std::endl;
+// }
+// }
+// newLemmaGenerated = true;
+// Trace("sets-card") << "[sets-card] New intersection being empty lemma generated. Returning." << std::endl;
+// return;
+// }
+// }
+
+// Assert(!newLemmaGenerated);
+
+
+
+// // Elements being either equal or disequal
+
+// for(typeof(leaves.begin()) it = leaves.begin();
+// it != leaves.end(); ++it) {
+// Assert(d_equalityEngine.hasTerm(*it));
+// Node n = d_equalityEngine.getRepresentative(*it);
+// Assert(n.getKind() == kind::EMPTYSET || leaves.find(n) != leaves.end());
+// if(n != *it) continue;
+// const CDTNodeList* l = d_termInfoManager->getMembers(*it);
+// std::set<TNode> elems;
+// for(typeof(l->begin()) l_it = l->begin(); l_it != l->end(); ++l_it) {
+// elems.insert(d_equalityEngine.getRepresentative(*l_it));
+// }
+// for(typeof(elems.begin()) e1_it = elems.begin(); e1_it != elems.end(); ++e1_it) {
+// for(typeof(elems.begin()) e2_it = elems.begin(); e2_it != elems.end(); ++e2_it) {
+// if(*e1_it == *e2_it) continue;
+// if(!d_equalityEngine.areDisequal(*e1_it, *e2_it, false)) {
+// Node lem = nm->mkNode(kind::EQUAL, *e1_it, *e2_it);
+// lem = nm->mkNode(kind::OR, lem, nm->mkNode(kind::NOT, lem));
+// d_external.d_out->lemma(lem);
+// newLemmaGenerated = true;
+// }
+// }
+// }
+// }
+
+// if(newLemmaGenerated) {
+// Trace("sets-card") << "[sets-card] Members arrangments lemmas. Returning." << std::endl;
+// return;
+// }
+
+
+// // Guess leaf nodes being empty or non-empty
+// for(typeof(leaves.begin()) it = leaves.begin(); it != leaves.end(); ++it) {
+// Node n = d_equalityEngine.getRepresentative(*it);
+// if(n.getKind() == kind::EMPTYSET) continue;
+// if(d_termInfoManager->getMembers(n)->size() > 0) continue;
+// Node emptySet = nm->mkConst<EmptySet>(EmptySet(nm->toType(n.getType())));
+// if(!d_equalityEngine.hasTerm(emptySet)) {
+// d_equalityEngine.addTerm(emptySet);
+// }
+// if(!d_equalityEngine.areDisequal(n, emptySet, false)) {
+// Node lem = nm->mkNode(kind::EQUAL, n, emptySet);
+// lem = nm->mkNode(kind::OR, lem, nm->mkNode(kind::NOT, lem));
+// Assert(d_cardLowerLemmaCache.find(lem) == d_cardLowerLemmaCache.end());
+// d_cardLowerLemmaCache.insert(lem);
+// d_external.d_out->lemma(lem);
+// newLemmaGenerated = true;
+// break;
+// }
+// }
+
+// if(newLemmaGenerated) {
+// Trace("sets-card") << "[sets-card] New guessing leaves being empty done." << std::endl;
+// return;
+// }
+
+// // Assert Lower bound
+// for(typeof(leaves.begin()) it = leaves.begin();
+// it != leaves.end(); ++it) {
+// Assert(d_equalityEngine.hasTerm(*it));
+// Node n = d_equalityEngine.getRepresentative(*it);
+// Assert(n.getKind() == kind::EMPTYSET || leaves.find(n) != leaves.end());
+// if(n != *it) continue;
+// const CDTNodeList* l = d_termInfoManager->getMembers(n);
+// std::set<TNode> elems;
+// for(typeof(l->begin()) l_it = l->begin(); l_it != l->end(); ++l_it) {
+// elems.insert(d_equalityEngine.getRepresentative(*l_it));
+// }
+// if(elems.size() == 0) continue;
+// NodeBuilder<> nb(kind::OR);
+// nb << ( nm->mkNode(kind::LEQ, nm->mkConst(Rational(elems.size())), nm->mkNode(kind::CARD, n)) );
+// if(elems.size() > 1) {
+// for(typeof(elems.begin()) e1_it = elems.begin(); e1_it != elems.end(); ++e1_it) {
+// for(typeof(elems.begin()) e2_it = elems.begin(); e2_it != elems.end(); ++e2_it) {
+// if(*e1_it == *e2_it) continue;
+// nb << (nm->mkNode(kind::EQUAL, *e1_it, *e2_it));
+// }
+// }
+// }
+// for(typeof(elems.begin()) e_it = elems.begin(); e_it != elems.end(); ++e_it) {
+// nb << nm->mkNode(kind::NOT, nm->mkNode(kind::MEMBER, *e_it, n));
+// }
+// Node lem = Node(nb);
+// if(d_cardLowerLemmaCache.find(lem) == d_cardLowerLemmaCache.end()) {
+// Trace("sets-card") << "[sets-card] Card Lower: " << lem << std::endl;
+// d_external.d_out->lemma(lem);
+// d_cardLowerLemmaCache.insert(lem);
+// newLemmaGenerated = true;
+// }
+// }
+// }
+
diff --git a/src/theory/sets/expr_patterns.h b/src/theory/sets/expr_patterns.h
index f293d0714..32e77d8b8 100644
--- a/src/theory/sets/expr_patterns.h
+++ b/src/theory/sets/expr_patterns.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file expr_patterns.h
** \verbatim
- ** Original author: Kshitij Bansal
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Kshitij Bansal, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Expr patterns.
**
@@ -54,6 +54,10 @@ static Node EQUAL(TNode a, TNode b) {
return NodeManager::currentNM()->mkNode(kind::EQUAL, a, b);
}
+static Node CARD(TNode a) {
+ return NodeManager::currentNM()->mkNode(kind::CARD, a);
+}
+
}/* CVC4::expr::pattern namespace */
}/* CVC4::expr namespace */
}/* CVC4 namespace */
diff --git a/src/theory/sets/kinds b/src/theory/sets/kinds
index efd00093a..3fb73749d 100644
--- a/src/theory/sets/kinds
+++ b/src/theory/sets/kinds
@@ -12,7 +12,7 @@ rewriter ::CVC4::theory::sets::TheorySetsRewriter \
"theory/sets/theory_sets_rewriter.h"
properties parametric
-properties check propagate
+properties check propagate presolve
# constants
constant EMPTYSET \
@@ -42,6 +42,7 @@ operator SUBSET 2 "subset predicate; first parameter a subset of second"
operator MEMBER 2 "set membership predicate; first parameter a member of second"
operator SINGLETON 1 "the set of the single element given as a parameter"
operator INSERT 2: "set obtained by inserting elements (first N-1 parameters) into a set (the last parameter)"
+operator CARD 1 "set cardinality operator"
operator JOIN 2 "set join"
operator PRODUCT 2 "set cartesian product"
@@ -56,6 +57,7 @@ typerule MEMBER ::CVC4::theory::sets::MemberTypeRule
typerule SINGLETON ::CVC4::theory::sets::SingletonTypeRule
typerule EMPTYSET ::CVC4::theory::sets::EmptySetTypeRule
typerule INSERT ::CVC4::theory::sets::InsertTypeRule
+typerule CARD ::CVC4::theory::sets::CardTypeRule
typerule JOIN ::CVC4::theory::sets::RelBinaryOperatorTypeRule
typerule PRODUCT ::CVC4::theory::sets::RelBinaryOperatorTypeRule
@@ -67,6 +69,7 @@ construle INTERSECTION ::CVC4::theory::sets::SetsBinaryOperatorTypeRule
construle SETMINUS ::CVC4::theory::sets::SetsBinaryOperatorTypeRule
construle SINGLETON ::CVC4::theory::sets::SingletonTypeRule
construle INSERT ::CVC4::theory::sets::InsertTypeRule
+construle CARD ::CVC4::theory::sets::CardTypeRule
construle JOIN ::CVC4::theory::sets::RelBinaryOperatorTypeRule
construle PRODUCT ::CVC4::theory::sets::RelBinaryOperatorTypeRule
diff --git a/src/theory/sets/normal_form.h b/src/theory/sets/normal_form.h
index 13da6d57e..6da7e9f8f 100644
--- a/src/theory/sets/normal_form.h
+++ b/src/theory/sets/normal_form.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file normal_form.h
** \verbatim
- ** Original author: Kshitij Bansal
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Kshitij Bansal, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Normal form for set constants.
**
diff --git a/src/theory/sets/scrutinize.h b/src/theory/sets/scrutinize.h
index dc5feecda..2ada4a3ce 100644
--- a/src/theory/sets/scrutinize.h
+++ b/src/theory/sets/scrutinize.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file scrutinize.h
** \verbatim
- ** Original author: Kshitij Bansal
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Kshitij Bansal, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Check consistency of internal data structures.
**
diff --git a/src/theory/sets/term_info.h b/src/theory/sets/term_info.h
index 3168817e2..c7d4b38bc 100644
--- a/src/theory/sets/term_info.h
+++ b/src/theory/sets/term_info.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file term_info.h
** \verbatim
- ** Original author: Kshitij Bansal
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Kshitij Bansal, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Term info.
**
diff --git a/src/theory/sets/theory_sets.cpp b/src/theory/sets/theory_sets.cpp
index 1280ad58d..bdbc964c6 100644
--- a/src/theory/sets/theory_sets.cpp
+++ b/src/theory/sets/theory_sets.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_sets.cpp
** \verbatim
- ** Original author: Kshitij Bansal
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Kshitij Bansal, Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Sets theory.
**
@@ -70,6 +70,10 @@ void TheorySets::preRegisterTerm(TNode node) {
d_internal->preRegisterTerm(node);
}
+void TheorySets::presolve() {
+ d_internal->presolve();
+}
+
void TheorySets::propagate(Effort e) {
d_internal->propagate(e);
}
diff --git a/src/theory/sets/theory_sets.h b/src/theory/sets/theory_sets.h
index 9e08b597d..840135937 100644
--- a/src/theory/sets/theory_sets.h
+++ b/src/theory/sets/theory_sets.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_sets.h
** \verbatim
- ** Original author: Kshitij Bansal
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Kshitij Bansal, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Sets theory.
**
@@ -64,6 +64,8 @@ public:
void preRegisterTerm(TNode node);
+ void presolve();
+
void propagate(Effort);
void setMasterEqualityEngine(eq::EqualityEngine* eq);
diff --git a/src/theory/sets/theory_sets_private.cpp b/src/theory/sets/theory_sets_private.cpp
index fee47e3cb..bc9227e54 100644
--- a/src/theory/sets/theory_sets_private.cpp
+++ b/src/theory/sets/theory_sets_private.cpp
@@ -1,19 +1,20 @@
/********************* */
/*! \file theory_sets_private.cpp
** \verbatim
- ** Original author: Kshitij Bansal
- ** Major contributors: none
- ** Minor contributors (to current version): Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Kshitij Bansal, Tim King, Andrew Reynolds
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Sets theory implementation.
**
** Sets theory implementation.
**/
+#include <algorithm>
#include "theory/sets/theory_sets_private.h"
#include <boost/foreach.hpp>
@@ -36,12 +37,15 @@ namespace sets {
const char* element_of_str = " \u2208 ";
+// Declaration of functions defined later in this CPP file
+const std::set<TNode> getLeaves(map<TNode, set<TNode> >& edges, TNode node);
+
/**************************** TheorySetsPrivate *****************************/
/**************************** TheorySetsPrivate *****************************/
/**************************** TheorySetsPrivate *****************************/
void TheorySetsPrivate::check(Theory::Effort level) {
-
+ d_newLemmaGenerated = false;
while(!d_external.done() && !d_conflict) {
// Get all the assertions
Assertion assertion = d_external.get();
@@ -100,13 +104,17 @@ void TheorySetsPrivate::check(Theory::Effort level) {
d_rels->check(level);
if( (level == Theory::EFFORT_FULL || options::setsEagerLemmas() ) && !isComplete()) {
- d_external.d_out->lemma(getLemma());
+ lemma(getLemma(), SETS_LEMMA_OTHER);
return;
}
+
+ //processCard(level);
+ processCard2(level);
+
// if we are here, there is no conflict and we are complete
if(Debug.isOn("sets-scrutinize")) { d_scrutinize->postCheckInvariants(); }
-
+
return;
}/* TheorySetsPrivate::check() */
@@ -119,31 +127,39 @@ void TheorySetsPrivate::assertEquality(TNode fact, TNode reason, bool learnt)
bool polarity = fact.getKind() != kind::NOT;
TNode atom = polarity ? fact : fact[0];
- Debug("sets-assert") << "\n finish assert equality!!!!!!!*************** 0" <<std::endl;
// fact already holds
if( holds(atom, polarity) ) {
Debug("sets-assert") << "[sets-assert] already present, skipping" << std::endl;
return;
}
- Debug("sets-assert") << "\n finish assert equality!!!!!!!*************** 1" <<std::endl;
// assert fact & check for conflict
if(learnt) {
- Debug("sets-assert") << "\n finish assert equality!!!!!!!*************** 5" <<std::endl;
registerReason(reason, /*save=*/ true);
}
- Debug("sets-assert") << "\n finish assert equality!!!!!!!*************** 4" <<std::endl;
d_equalityEngine.assertEquality(atom, polarity, reason);
- Debug("sets-assert") << "\n finish assert equality!!!!!!!*************** 2" <<std::endl;
if(!d_equalityEngine.consistent()) {
Debug("sets-assert") << "[sets-assert] running into a conflict" << std::endl;
d_conflict = true;
return;
}
- Debug("sets-assert") << "\n finish assert equality!!!!!!!*************** 3" <<std::endl;
+
+ if(atom[0].getKind() == kind::CARD && isCardVar(atom[0])) {
+ NodeManager* nm = NodeManager::currentNM();
+ Node emptySet = nm->mkConst<EmptySet>(EmptySet(nm->toType(atom[0].getType())));
+ Node newFact = nm->mkNode(kind::EQUAL, getCardVar(atom[0]), emptySet);
+ if(!polarity) newFact = nm->mkNode(kind::NOT, newFact);
+ learnLiteral(newFact, fact);
+ }
+
+ // disequality lemma
if(!polarity && atom[0].getType().isSet()) {
addToPending(atom);
}
- Debug("sets-assert") << "\n finish assert equality!!!!!!!*************** " <<std::endl;
+
+ // for cardinality
+ if(polarity && atom[0].getType().isSet()) {
+ d_graphMergesPending.push(make_pair(atom[0], atom[1]));
+ }
}/* TheorySetsPrivate::assertEquality() */
@@ -371,11 +387,12 @@ void TheorySetsPrivate::doSettermPropagation(TNode x, TNode S)
addToPending( MEMBER(x, S[0]) );
break;
case kind::SETMINUS: // intentional fallthrough
- case kind::INTERSECTION:
if( holds(MEMBER(x, S[0])) &&
!present( MEMBER(x, S[1]) ))
addToPending( MEMBER(x, S[1]) );
break;
+ case kind::INTERSECTION:
+ return;
default:
Assert(false, "MembershipEngine::doSettermPropagation");
}
@@ -412,6 +429,33 @@ void TheorySetsPrivate::learnLiteral(TNode atom, bool polarity, Node reason) {
}/*TheorySetsPrivate::learnLiteral(...)*/
+/************************ CardVar ************************/
+
+Node TheorySetsPrivate::getCardVar(TNode n) {
+ NodeNodeHashMap::iterator it = d_setTermToCardVar.find(n);
+ if(it == d_setTermToCardVar.end()) {
+ return it->second;
+ } else {
+ NodeManager* nm = NodeManager::currentNM();
+ Node cardVar = nm->mkSkolem("scv_", n.getType());
+ d_setTermToCardVar[n] = cardVar;
+ d_cardVarToSetTerm[cardVar] = n;
+ return cardVar;
+ }
+}
+
+Node TheorySetsPrivate::newCardVar(TNode n) {
+ NodeNodeHashMap::iterator it = d_cardVarToSetTerm.find(n);
+ Assert(it != d_cardVarToSetTerm.end());
+ return it->second;
+}
+
+bool TheorySetsPrivate::isCardVar(TNode n) {
+ NodeNodeHashMap::iterator it = d_cardVarToSetTerm.find(n);
+ return it != d_cardVarToSetTerm.end();
+}
+
+
/************************ Sharing ************************/
/************************ Sharing ************************/
/************************ Sharing ************************/
@@ -840,11 +884,23 @@ Node TheorySetsPrivate::elementsToShape(set<Node> elements, TypeNode setType) co
void TheorySetsPrivate::collectModelInfo(TheoryModel* m, bool fullModel)
{
- Debug("sets-model") << "[sets-model] collectModelInfo(..., fullModel="
+ Trace("sets-model") << "[sets-model] collectModelInfo(..., fullModel="
<< (fullModel ? "true)" : "false)") << std::endl;
set<Node> terms;
+ NodeManager* nm = NodeManager::currentNM();
+
+ // // this is for processCard -- commenting out for now
+ // if(Debug.isOn("sets-card")) {
+ // for(typeof(d_cardTerms.begin()) it = d_cardTerms.begin();
+ // it != d_cardTerms.end(); ++it) {
+ // Debug("sets-card") << "[sets-card] " << *it << " = "
+ // << d_external.d_valuation.getModelValue(*it)
+ // << std::endl;
+ // }
+ // }
+
if(Trace.isOn("sets-assertions")) {
dumpAssertionsHumanified();
}
@@ -852,6 +908,23 @@ void TheorySetsPrivate::collectModelInfo(TheoryModel* m, bool fullModel)
// Compute terms appearing assertions and shared terms
d_external.computeRelevantTerms(terms);
+ //processCard2 begin
+ if(Debug.isOn("sets-card")) {
+ for(typeof(d_V.begin()) it = d_V.begin(); it != d_V.end(); ++it) {
+ Node n = nm->mkNode(kind::CARD, *it);
+ Debug("sets-card") << "[sets-card] " << n << " = ";
+ // if(d_external.d_sharedTerms.find(n) == d_external.d_sharedTerms.end()) continue;
+ if((Rewriter::rewrite(n)).isConst()) {
+ Debug("sets-card") << (Rewriter::rewrite(n))
+ << std::endl;
+ } else {
+ Debug("sets-card") << d_external.d_valuation.getModelValue(n)
+ << std::endl;
+ }
+ }
+ }
+ //processCard2 end
+
// Compute for each setterm elements that it contains
SettermElementsMap settermElementsMap;
for(eq::EqClassIterator it_eqclasses(d_trueNode, &d_equalityEngine);
@@ -864,10 +937,10 @@ void TheorySetsPrivate::collectModelInfo(TheoryModel* m, bool fullModel)
settermElementsMap[S].insert(x);
}
if(Debug.isOn("sets-model-details")) {
- vector<TNode> explanation;
- d_equalityEngine.explainPredicate(n, true, explanation);
Debug("sets-model-details")
<< "[sets-model-details] > node: " << n << ", explanation:" << std::endl;
+ vector<TNode> explanation;
+ d_equalityEngine.explainPredicate(n, true, explanation);
BOOST_FOREACH(TNode m, explanation) {
Debug("sets-model-details") << "[sets-model-details] >> " << m << std::endl;
}
@@ -879,9 +952,9 @@ void TheorySetsPrivate::collectModelInfo(TheoryModel* m, bool fullModel)
! it_eqclasses.isFinished() ; ++it_eqclasses) {
TNode n = (*it_eqclasses);
vector<TNode> explanation;
- d_equalityEngine.explainPredicate(n, false, explanation);
Debug("sets-model-details")
<< "[sets-model-details] > node: not: " << n << ", explanation:" << std::endl;
+ d_equalityEngine.explainPredicate(n, false, explanation);
BOOST_FOREACH(TNode m, explanation) {
Debug("sets-model-details") << "[sets-model-details] >> " << m << std::endl;
}
@@ -913,16 +986,74 @@ void TheorySetsPrivate::collectModelInfo(TheoryModel* m, bool fullModel)
}
}
- BOOST_FOREACH( SettermElementsMap::value_type &it, settermElementsMap ) {
- BOOST_FOREACH( TNode element, it.second /* elements */ ) {
- Debug("sets-model-details") << "[sets-model-details] > " <<
- (it.first /* setterm */) << ": " << element << std::endl;
+ if(Debug.isOn("sets-model-details")) {
+ BOOST_FOREACH( SettermElementsMap::value_type &it, settermElementsMap ) {
+ BOOST_FOREACH( TNode element, it.second /* elements */ ) {
+ Debug("sets-model-details") << "[sets-model-details] > " <<
+ (it.first /* setterm */) << ": " << element << std::endl;
+ }
+ }
+ }
+
+ // build graph, and create sufficient number of skolems
+ // buildGraph(); // this is for processCard
+
+ //processCard2 begin
+ leaves.clear();
+ for(typeof(d_V.begin()) it = d_V.begin(); it != d_V.end(); ++it)
+ if(d_E.find(*it) == d_E.end())
+ leaves.insert(*it);
+ d_statistics.d_numLeaves.setData(leaves.size());
+ d_statistics.d_numLeavesMax.maxAssign(leaves.size());
+ //processCard2 end
+
+ std::hash_map<TNode, std::vector<TNode>, TNodeHashFunction> slackElements;
+ BOOST_FOREACH( TNode setterm, leaves ) {
+ if(setterm.getKind() == kind::EMPTYSET) { continue; }
+ // Assert(d_cardTerms.find(nm->mkNode(kind::CARD,setterm)) != d_cardTerms.end()); // for processCard
+ Assert(d_V.find(setterm) != d_V.end());
+ Node cardValNode = d_external.d_valuation.getModelValue(nm->mkNode(kind::CARD,setterm));
+ Rational cardValRational = cardValNode.getConst<Rational>();
+ Assert(cardValRational.isIntegral());
+ Integer cardValInteger = cardValRational.getNumerator();
+ Assert(cardValInteger.fitsSignedInt(), "Can't build models that big.");
+ int cardValInt = cardValInteger.getSignedInt();
+ Assert(cardValInt >= 0);
+ int numElems = getElements(setterm, settermElementsMap).size();
+ Trace("sets-model-card") << "[sets-model-card] cardValInt = " << cardValInt << std::endl
+ << " numElems = " << numElems << std::endl;
+ Trace("sets-model-card") << "[sets-model-card] Creating " << cardValInt-numElems
+ << " slack variables for " << setterm << std::endl;
+ Assert(cardValInt >= numElems, "Run with -d sets-model-card for details");
+
+ TypeNode elementType = setterm.getType().getSetElementType();
+ std::vector<TNode>& cur = slackElements[setterm];
+ for(int i = numElems; i < cardValInt; ++i) {
+ // slk = slack
+ cur.push_back(nm->mkSkolem("slk_", elementType));
}
}
// assign representatives to equivalence class
BOOST_FOREACH( TNode setterm, settermsModEq ) {
Elements elements = getElements(setterm, settermElementsMap);
+ if(d_E.find(setterm) != d_E.end()) {
+ Trace("sets-model-card") << "[sets-model-card] " << setterm << " (before slacks): " << elements.size() << std::endl;
+ std::set<TNode> leafChildren = get_leaves(setterm);
+ BOOST_FOREACH( TNode leafChild, leafChildren ) {
+ if(leaves.find(leafChild) == leaves.end()) { continue; }
+ BOOST_FOREACH( TNode slackVar, slackElements[leafChild] ) {
+ elements.insert(slackVar);
+ }
+ }
+ Trace("sets-model-card") << "[sets-model-card] " << setterm << " (after slacks): " << elements.size() << std::endl;
+ } else if(d_V.find(setterm) != d_V.end()) {
+ Trace("sets-model-card") << "[sets-model-card] " << setterm << " (before slacks): " << elements.size() << std::endl;
+ BOOST_FOREACH( TNode slackVar, slackElements[setterm] ) {
+ elements.insert(slackVar);
+ }
+ Trace("sets-model-card") << "[sets-model-card] " << setterm << " (after slacks): " << elements.size() << std::endl;
+ }
Node shape = elementsToShape(elements, setterm.getType());
shape = theory::Rewriter::rewrite(shape);
m->assertEquality(shape, setterm, true);
@@ -996,20 +1127,44 @@ Node mkAnd(const std::vector<TNode>& conjunctions) {
TheorySetsPrivate::Statistics::Statistics() :
- d_getModelValueTime("theory::sets::getModelValueTime")
+ d_getModelValueTime("theory::sets::getModelValueTime")
+ , d_mergeTime("theory::sets::merge_nodes::time")
+ , d_processCard2Time("theory::sets::processCard2::time")
, d_memberLemmas("theory::sets::lemmas::member", 0)
, d_disequalityLemmas("theory::sets::lemmas::disequality", 0)
+ , d_numVertices("theory::sets::vertices", 0)
+ , d_numVerticesMax("theory::sets::vertices-max", 0)
+ , d_numMergeEq1or2("theory::sets::merge1or2", 0)
+ , d_numMergeEq3("theory::sets::merge3", 0)
+ , d_numLeaves("theory::sets::leaves", 0)
+ , d_numLeavesMax("theory::sets::leaves-max", 0)
{
smtStatisticsRegistry()->registerStat(&d_getModelValueTime);
+ smtStatisticsRegistry()->registerStat(&d_mergeTime);
+ smtStatisticsRegistry()->registerStat(&d_processCard2Time);
smtStatisticsRegistry()->registerStat(&d_memberLemmas);
smtStatisticsRegistry()->registerStat(&d_disequalityLemmas);
+ smtStatisticsRegistry()->registerStat(&d_numVertices);
+ smtStatisticsRegistry()->registerStat(&d_numVerticesMax);
+ smtStatisticsRegistry()->registerStat(&d_numMergeEq1or2);
+ smtStatisticsRegistry()->registerStat(&d_numMergeEq3);
+ smtStatisticsRegistry()->registerStat(&d_numLeaves);
+ smtStatisticsRegistry()->registerStat(&d_numLeavesMax);
}
TheorySetsPrivate::Statistics::~Statistics() {
smtStatisticsRegistry()->unregisterStat(&d_getModelValueTime);
+ smtStatisticsRegistry()->unregisterStat(&d_mergeTime);
+ smtStatisticsRegistry()->unregisterStat(&d_processCard2Time);
smtStatisticsRegistry()->unregisterStat(&d_memberLemmas);
smtStatisticsRegistry()->unregisterStat(&d_disequalityLemmas);
+ smtStatisticsRegistry()->unregisterStat(&d_numVertices);
+ smtStatisticsRegistry()->unregisterStat(&d_numVerticesMax);
+ smtStatisticsRegistry()->unregisterStat(&d_numMergeEq1or2);
+ smtStatisticsRegistry()->unregisterStat(&d_numMergeEq3);
+ smtStatisticsRegistry()->unregisterStat(&d_numLeaves);
+ smtStatisticsRegistry()->unregisterStat(&d_numLeavesMax);
}
@@ -1036,9 +1191,10 @@ void TheorySetsPrivate::registerReason(TNode reason, bool save)
if(save) d_nodeSaver.insert(reason);
if(reason.getKind() == kind::AND) {
- Assert(reason.getNumChildren() == 2);
- registerReason(reason[0], false);
- registerReason(reason[1], false);
+ //Assert(reason.getNumChildren() == 2);
+ for(unsigned i = 0; i < reason.getNumChildren(); ++i) {
+ registerReason(reason[i], false);
+ }
} else if(reason.getKind() == kind::NOT) {
registerReason(reason[0], false);
} else if(reason.getKind() == kind::MEMBER) {
@@ -1100,7 +1256,8 @@ void TheorySetsPrivate::addToPending(Node n) {
<< std::endl;
++d_statistics.d_memberLemmas;
d_pending.push(n);
- d_external.d_out->splitLemma(getLemma());
+ lemma(getLemma(), SETS_LEMMA_MEMBER);
+ // d_external.d_out->splitLemma();
Assert(isComplete());
} else {
@@ -1110,7 +1267,8 @@ void TheorySetsPrivate::addToPending(Node n) {
Assert(n.getKind() == kind::EQUAL);
++d_statistics.d_disequalityLemmas;
d_pendingDisequal.push(n);
- d_external.d_out->splitLemma(getLemma());
+ lemma(getLemma(), SETS_LEMMA_DISEQUAL);
+ // d_external.d_out->splitLemma();
Assert(isComplete());
}
@@ -1151,7 +1309,13 @@ Node TheorySetsPrivate::getLemma() {
Node x = NodeManager::currentNM()->mkSkolem("sde_", elementType);
Node l1 = MEMBER(x, n[0]), l2 = MEMBER(x, n[1]);
- lemma = OR(n, AND(l1, NOT(l2)), AND(NOT(l1), l2));
+ if(n[0].getKind() == kind::EMPTYSET) {
+ lemma = OR(n, l2);
+ } else if(n[1].getKind() == kind::EMPTYSET) {
+ lemma = OR(n, l1);
+ } else {
+ lemma = OR(n, AND(l1, NOT(l2)), AND(NOT(l1), l2));
+ }
}
Debug("sets-lemma") << "[sets-lemma] Generating for " << n
@@ -1171,6 +1335,8 @@ TheorySetsPrivate::TheorySetsPrivate(TheorySets& external,
d_falseNode(NodeManager::currentNM()->mkConst<bool>(false)),
d_conflict(c),
d_termInfoManager(NULL),
+ d_setTermToCardVar(),
+ d_cardVarToSetTerm(),
d_propagationQueue(c),
d_settermPropagationQueue(c),
d_nodeSaver(c),
@@ -1181,7 +1347,24 @@ TheorySetsPrivate::TheorySetsPrivate(TheorySets& external,
d_ccg_i(c),
d_ccg_j(c),
d_scrutinize(NULL),
- d_rels(NULL)
+ d_rels(NULL),
+ d_cardEnabled(false),
+ d_cardTerms(c),
+ d_typesAdded(),
+ d_processedCardTerms(c),
+ d_processedCardPairs(),
+ d_cardLowerLemmaCache(u),
+ edgesFd(),
+ edgesBk(),
+ disjoint(),
+ leaves(),
+ d_V(c),
+ d_E(c),
+ d_graphMergesPending(c),
+ d_allSetEqualitiesSoFar(c),
+ d_lemmasGenerated(u),
+ d_newLemmaGenerated(false),
+ d_relTerms(u)
{
d_termInfoManager = new TermInfoManager(*this, c, &d_equalityEngine);
d_rels = new TheorySetsRels(c, u, &d_equalityEngine, &d_conflict, external);
@@ -1193,6 +1376,9 @@ TheorySetsPrivate::TheorySetsPrivate(TheorySets& external,
d_equalityEngine.addFunctionKind(kind::MEMBER);
d_equalityEngine.addFunctionKind(kind::SUBSET);
+ // If cardinality is on.
+ d_equalityEngine.addFunctionKind(kind::CARD);
+
if( Debug.isOn("sets-scrutinize") ) {
d_scrutinize = new TheorySetsScrutinize(this);
}
@@ -1308,6 +1494,30 @@ Node TheorySetsPrivate::explain(TNode literal)
return mkAnd(assumptions);
}
+bool TheorySetsPrivate::lemma(Node n, SetsLemmaTag t)
+{
+ if(d_lemmasGenerated.find(n) != d_lemmasGenerated.end()) {
+ return false;
+ }
+ d_lemmasGenerated.insert(n);
+ d_newLemmaGenerated = true;
+ switch(t) {
+ case SETS_LEMMA_DISEQUAL:
+ case SETS_LEMMA_MEMBER: {
+ d_external.d_out->splitLemma(n);
+ break;
+ }
+ case SETS_LEMMA_GRAPH:// {
+ // d_external.d_out->preservedLemma(n, false, false);
+ // break;
+ // }
+ case SETS_LEMMA_OTHER: {
+ d_external.d_out->lemma(n);
+ break;
+ }
+ }
+ return true;
+}
void TheorySetsPrivate::preRegisterTerm(TNode node)
{
@@ -1323,6 +1533,11 @@ void TheorySetsPrivate::preRegisterTerm(TNode node)
// TODO: what's the point of this
d_equalityEngine.addTriggerPredicate(node);
break;
+ case kind::CARD:
+ if(!d_cardEnabled) { enableCard(); }
+ registerCard(node);
+ d_equalityEngine.addTriggerTerm(node, THEORY_SETS);
+ break;
default:
d_termInfoManager->addTerm(node);
d_equalityEngine.addTriggerTerm(node, THEORY_SETS);
@@ -1331,9 +1546,38 @@ void TheorySetsPrivate::preRegisterTerm(TNode node)
if(node.getKind() == kind::SINGLETON) {
learnLiteral(MEMBER(node[0], node), true, d_trueNode);
}
+
+ // ** For cardinality reasoning **
+ if(node.getType().isSet() && d_typesAdded.find(node.getType()) == d_typesAdded.end()) {
+ d_typesAdded.insert(node.getType());
+
+ if(d_cardEnabled) {
+ cardCreateEmptysetSkolem(node.getType());
+ }
+ }
+ if(d_cardEnabled && node.getKind() == kind::SINGLETON) {
+ registerCard(NodeManager::currentNM()->mkNode(kind::CARD, node));
+ }
}
+void TheorySetsPrivate::presolve() {
+
+ for(typeof(d_termInfoManager->d_terms.begin()) it = d_termInfoManager->d_terms.begin();
+ it != d_termInfoManager->d_terms.end(); ++it) {
+ d_relTerms.insert(*it);
+ }
+
+ if(Trace.isOn("sets-relterms")) {
+ Trace("sets-relterms") << "[sets-relterms] ";
+ for(typeof(d_relTerms.begin()) it = d_relTerms.begin();
+ it != d_relTerms.end(); ++it ) {
+ Trace("sets-relterms") << (*it) << ", ";
+ }
+ Trace("sets-relterms") << "\n";
+ }
+
+}
/**************************** eq::NotifyClass *****************************/
/**************************** eq::NotifyClass *****************************/
@@ -1367,7 +1611,7 @@ bool TheorySetsPrivate::NotifyClass::eqNotifyTriggerTermEquality(TheoryId tag, T
{
Debug("sets-eq") << "[sets-eq] eqNotifyTriggerTermEquality: tag = " << tag
<< " t1 = " << t1 << " t2 = " << t2 << " value = " << value << std::endl;
- if(value) {
+ if(value && t1.getKind() != kind::CARD && t2.getKind() != kind::CARD) {
d_theory.d_termInfoManager->mergeTerms(t1, t2);
}
d_theory.propagate( value ? EQUAL(t1, t2) : NOT(EQUAL(t1, t2)) );
@@ -1488,7 +1732,12 @@ void TheorySetsPrivate::TermInfoManager::addTerm(TNode n) {
if(d_terms.contains(n[i])) {
Debug("sets-parent") << "Adding " << n << " to parent list of "
<< n[i] << std::endl;
+
+ // introduce cardinality of this set if a child's cardinality appears
d_info[n[i]]->parents->push_back(n);
+ if(d_theory.d_cardTerms.find(CARD(n[i])) != d_theory.d_cardTerms.end()) {
+ d_theory.registerCard(CARD(n));
+ }
typeof(d_info.begin()) ita = d_info.find(d_eqEngine->getRepresentative(n[i]));
Assert(ita != d_info.end());
@@ -1656,6 +1905,907 @@ Node TheorySetsPrivate::TermInfoManager::getModelValue(TNode n)
return v;
}
+
+
+
+/********************** Cardinality ***************************/
+/********************** Cardinality ***************************/
+/********************** Cardinality ***************************/
+
+void TheorySetsPrivate::enableCard()
+{
+ Assert(!d_cardEnabled);
+ Trace("sets-card") << "[sets-card] Enabling cardinality reasoning" << std::endl;
+ d_cardEnabled = true;
+
+ BOOST_FOREACH( TypeNode t, d_typesAdded ) {
+ cardCreateEmptysetSkolem(t);
+ }
+
+ for(typeof(d_termInfoManager->d_terms.begin()) it = d_termInfoManager->d_terms.begin();
+ it != d_termInfoManager->d_terms.end(); ++it) {
+ Node n = (*it);
+ if(n.getKind() == kind::SINGLETON) {
+ registerCard(NodeManager::currentNM()->mkNode(kind::CARD, n));
+ }
+ }
+}
+
+void TheorySetsPrivate::registerCard(TNode node) {
+ Trace("sets-card") << "[sets-card] registerCard( " << node << ")" << std::endl;
+ if(d_cardTerms.find(node) == d_cardTerms.end()) {
+ d_cardTerms.insert(node);
+
+ // introduce cardinality of any set-term containing this term
+ NodeManager* nm = NodeManager::currentNM();
+ const CDTNodeList* parentList = d_termInfoManager->getParents(node[0]);
+ for(typeof(parentList->begin()) it = parentList->begin();
+ it != parentList->end(); ++it) {
+ registerCard(nm->mkNode(kind::CARD, *it));
+ }
+ }
+}
+
+
+void TheorySetsPrivate::cardCreateEmptysetSkolem(TypeNode t) {
+ // set cardinality zero
+ NodeManager* nm = NodeManager::currentNM();
+ Debug("sets-card") << "Creating skolem for emptyset for type "
+ << t << std::endl;
+ Node emptySet = nm->mkConst<EmptySet>(EmptySet(nm->toType(t)));
+ Node sk = nm->mkSkolem("scz_", t);
+ lemma(nm->mkNode(kind::EQUAL, sk, emptySet), SETS_LEMMA_OTHER);
+ lemma(nm->mkNode(kind::EQUAL, nm->mkConst(Rational(0)), nm->mkNode(kind::CARD, sk)), SETS_LEMMA_OTHER);
+}
+
+
+void TheorySetsPrivate::buildGraph() {
+
+ NodeManager* nm = NodeManager::currentNM();
+
+ edgesFd.clear();
+ edgesBk.clear();
+ disjoint.clear();
+
+ for(typeof(d_processedCardPairs.begin()) it = d_processedCardPairs.begin();
+ it != d_processedCardPairs.end(); ++it) {
+ Node s = (it->first).first;
+ Assert(Rewriter::rewrite(s) == s);
+ Node t = (it->first).second;
+ Assert(Rewriter::rewrite(t) == t);
+ bool hasUnion = (it->second);
+
+ Node sNt = nm->mkNode(kind::INTERSECTION, s, t);
+ sNt = Rewriter::rewrite(sNt);
+ Node sMt = nm->mkNode(kind::SETMINUS, s, t);
+ sMt = Rewriter::rewrite(sMt);
+ Node tMs = nm->mkNode(kind::SETMINUS, t, s);
+ tMs = Rewriter::rewrite(tMs);
+
+ edgesFd[s].insert(sNt);
+ edgesFd[s].insert(sMt);
+ edgesBk[sNt].insert(s);
+ edgesBk[sMt].insert(s);
+
+ edgesFd[t].insert(sNt);
+ edgesFd[t].insert(tMs);
+ edgesBk[sNt].insert(t);
+ edgesBk[tMs].insert(t);
+
+ if(hasUnion) {
+ Node sUt = nm->mkNode(kind::UNION, s, t);
+ sUt = Rewriter::rewrite(sUt);
+
+ edgesFd[sUt].insert(sNt);
+ edgesFd[sUt].insert(sMt);
+ edgesFd[sUt].insert(tMs);
+ edgesBk[sNt].insert(sUt);
+ edgesBk[sMt].insert(sUt);
+ edgesBk[tMs].insert(sUt);
+ }
+
+ disjoint.insert(make_pair(sNt, sMt));
+ disjoint.insert(make_pair(sMt, sNt));
+ disjoint.insert(make_pair(sNt, tMs));
+ disjoint.insert(make_pair(tMs, sNt));
+ disjoint.insert(make_pair(tMs, sMt));
+ disjoint.insert(make_pair(sMt, tMs));
+ }
+
+ if(Debug.isOn("sets-card-graph")) {
+ Debug("sets-card-graph") << "[sets-card-graph] Fd:" << std::endl;
+ for(typeof(edgesFd.begin()) it = edgesFd.begin();
+ it != edgesFd.end(); ++it) {
+ Debug("sets-card-graph") << "[sets-card-graph] " << (it->first) << std::endl;
+ for(typeof( (it->second).begin()) jt = (it->second).begin();
+ jt != (it->second).end(); ++jt) {
+ Debug("sets-card-graph") << "[sets-card-graph] " << (*jt) << std::endl;
+ }
+ }
+ Debug("sets-card-graph") << "[sets-card-graph] Bk:" << std::endl;
+ for(typeof(edgesBk.begin()) it = edgesBk.begin();
+ it != edgesBk.end(); ++it) {
+ Debug("sets-card-graph") << "[sets-card-graph] " << (it->first) << std::endl;
+ for(typeof( (it->second).begin()) jt = (it->second).begin();
+ jt != (it->second).end(); ++jt) {
+ Debug("sets-card-graph") << "[sets-card-graph] " << (*jt) << std::endl;
+ }
+ }
+ }
+
+
+
+ leaves.clear();
+
+ for(typeof(d_processedCardTerms.begin()) it = d_processedCardTerms.begin();
+ it != d_processedCardTerms.end(); ++it) {
+ Node n = (*it)[0];
+ if( edgesFd.find(n) == edgesFd.end() ) {
+ leaves.insert(n);
+ Debug("sets-card-graph") << "[sets-card-graph] Leaf: " << n << std::endl;
+ }
+ // if( edgesBk.find(n) != edgesBk.end() ) {
+ // Assert(n.getKind() == kind::INTERSECTION ||
+ // n.getKind() == kind::SETMINUS);
+ // }
+ }
+
+}
+
+const std::set<TNode> getReachable(map<TNode, set<TNode> >& edges, TNode node) {
+ Debug("sets-getreachable-debug") << "[sets-getreachable-debug] " << node << ":" << std::endl;
+ queue<TNode> Q;
+ std::set<TNode> ret;
+ ret.insert(node);
+ if(edges.find(node) != edges.end()) {
+ Debug("sets-getreachable-debug") << "[sets-getreachable-debug] " << node << ":" << std::endl;
+ Q.push(node);
+ }
+ while(!Q.empty()) {
+ TNode n = Q.front();
+ Q.pop();
+ for(set<TNode>::iterator it = edges[n].begin();
+ it != edges[n].end(); ++it) {
+ if(ret.find(*it) == ret.end()) {
+ if(edges.find(*it) != edges.end()) {
+ Debug("sets-getreachable-debug") << "[sets-getreachable-debug] " << *it << ":" << std::endl;
+ Q.push(*it);
+ }
+ ret.insert(*it);
+ }
+ }
+ }
+ return ret;
+}
+
+const std::set<TNode> getLeaves(map<TNode, set<TNode> >& edges, TNode node) {
+ Debug("sets-getreachable-debug") << "[sets-getreachable-debug] " << node << ":" << std::endl;
+ queue<TNode> Q;
+ std::set<TNode> ret;
+ std::set<TNode> visited;
+ visited.insert(node);
+ if(edges.find(node) != edges.end()) {
+ Q.push(node);
+ } else {
+ Debug("sets-getreachable-debug") << "[sets-getreachable-debug] " << node << std::endl;
+ ret.insert(node);
+ }
+ while(!Q.empty()) {
+ TNode n = Q.front();
+ Q.pop();
+ for(set<TNode>::iterator it = edges[n].begin();
+ it != edges[n].end(); ++it) {
+ if(visited.find(*it) == visited.end()) {
+ if(edges.find(*it) != edges.end()) {
+ Q.push(*it);
+ } else {
+ Debug("sets-getreachable-debug") << "[sets-getreachable-debug] " << *it << std::endl;
+ ret.insert(*it);
+ }
+ visited.insert(*it);
+ }
+ }
+ }
+ return ret;
+}
+
+/************ New cardinality implementation **************/
+
+
+/***
+ * Data structures:
+ * d_V : vertices in the graph (context dependent data structure)
+ * d_E : edges between vertices in the graph
+ *
+ * Methods:
+ *
+ * merge(vector<int> a, vector<int> b)
+ * get non empty leaves
+ * of a & b, for each internal node, there will be two parent nodes
+ *
+ * Introduce
+ * <If a node already exists, merge with it>
+ */
+
+void TheorySetsPrivate::add_edges(TNode source, TNode dest) {
+ vector<TNode> V;
+ V.push_back(dest);
+ add_edges(source, V);
+}
+
+void TheorySetsPrivate::add_edges(TNode source, TNode dest1, TNode dest2) {
+ vector<TNode> V;
+ V.push_back(dest1);
+ V.push_back(dest2);
+ add_edges(source, V);
+}
+
+void TheorySetsPrivate::add_edges(TNode source, TNode dest1, TNode dest2, TNode dest3) {
+ vector<TNode> V;
+ V.push_back(dest1);
+ V.push_back(dest2);
+ V.push_back(dest3);
+ add_edges(source, V);
+}
+
+void TheorySetsPrivate::add_edges(TNode source, const std::vector<TNode>& dests) {
+
+ if(Debug.isOn("sets-graph-details")) {
+ Debug("sets-graph-details") << "[sets-graph-details] add_edges " << source
+ << " [";
+ BOOST_FOREACH(TNode v, dests) {
+ Debug("sets-graph-details") << v << ", ";
+ Assert(d_V.find(v) != d_V.end());
+ }
+ Debug("sets-graph-details") << "]" << std::endl;
+ }
+
+ Assert(d_E.find(source) == d_E.end());
+ if(dests.size() == 1 && dests[0] == source) {
+ return;
+ }
+ d_E.insert(source, dests);
+}
+
+
+void TheorySetsPrivate::add_node(TNode vertex) {
+ NodeManager* nm = NodeManager::currentNM();
+ Debug("sets-graph-details") << "[sets-graph-details] add_node " << vertex << std::endl;
+ if(d_V.find(vertex) == d_V.end()) {
+ d_V.insert(vertex);
+ Kind k = vertex.getKind();
+ if(k == kind::SINGLETON) {
+ // newLemmaGenerated = true;
+ lemma(nm->mkNode(kind::EQUAL,
+ nm->mkNode(kind::CARD, vertex),
+ nm->mkConst(Rational(1))),
+ SETS_LEMMA_OTHER);
+ } else if(k != kind::EMPTYSET) {
+ // newLemmaGenerated = true;
+ lemma(nm->mkNode(kind::GEQ,
+ nm->mkNode(kind::CARD, vertex),
+ nm->mkConst(Rational(0))),
+ SETS_LEMMA_OTHER);
+ }
+ d_statistics.d_numVerticesMax.maxAssign(d_V.size());
+ }
+ d_equalityEngine.addTerm(vertex);
+ d_termInfoManager->addTerm(vertex);
+}
+
+std::set<TNode> TheorySetsPrivate::non_empty(std::set<TNode> vertices)
+{
+ std::set<TNode> ret;
+ NodeManager* nm = NodeManager::currentNM();
+ BOOST_FOREACH(TNode vertex, vertices) {
+ Node emptySet = nm->mkConst<EmptySet>(EmptySet(nm->toType(vertex.getType())));
+ if(!d_equalityEngine.areEqual(vertex, emptySet)) {
+ ret.insert(vertex);
+ }
+ }
+ return ret;
+}
+
+std::set<TNode> TheorySetsPrivate::get_leaves(Node vertex) {
+ Debug("sets-graph-details") << "[sets-graph-details] get_leaves " << vertex << std::endl;
+ std::set<TNode> a;
+ Assert(d_V.find(vertex) != d_V.end());
+ if(d_E.find(vertex) != d_E.end()) {
+ Assert(d_E[vertex].get().size() > 0);
+ BOOST_FOREACH(TNode v , d_E[vertex].get()) {
+ std::set<TNode> s = get_leaves(v);
+ a.insert(s.begin(), s.end());
+ }
+ } else {
+ a.insert(vertex);
+ }
+ // a = non_empty(a);
+ return a;
+}
+
+std::set<TNode> TheorySetsPrivate::get_leaves(Node vertex1, Node vertex2) {
+ std::set<TNode> s = get_leaves(vertex1);
+ std::set<TNode> t = get_leaves(vertex2);
+ t.insert(s.begin(), s.end());
+ return t;
+}
+
+std::set<TNode> TheorySetsPrivate::get_leaves(Node vertex1, Node vertex2, Node vertex3) {
+ std::set<TNode> s = get_leaves(vertex1);
+ std::set<TNode> t = get_leaves(vertex2);
+ std::set<TNode> u = get_leaves(vertex3);
+ t.insert(s.begin(), s.end());
+ t.insert(u.begin(), u.end());
+ return t;
+}
+
+Node TheorySetsPrivate::eqemptySoFar() {
+ std::vector<Node> V;
+
+ for(typeof(d_V.begin()) it = d_V.begin(); it != d_V.end(); ++it) {
+ Node rep = d_equalityEngine.getRepresentative(*it);
+ if(rep.getKind() == kind::EMPTYSET) {
+ V.push_back(EQUAL(rep, (*it)));
+ }
+ }
+
+ if(V.size() == 0) {
+ return d_trueNode;
+ } else if(V.size() == 1) {
+ return V[0];
+ } else {
+ NodeManager* nm = NodeManager::currentNM();
+ return nm->mkNode(kind::AND, V);
+ }
+}
+
+
+void TheorySetsPrivate::merge_nodes(std::set<TNode> leaves1, std::set<TNode> leaves2, Node reason) {
+ CodeTimer codeTimer(d_statistics.d_mergeTime);
+
+ NodeManager* nm = NodeManager::currentNM();
+
+ // do non-empty reasoning stuff
+ std::vector<TNode> leaves1_nonempty, leaves2_nonempty;
+ BOOST_FOREACH(TNode l, leaves1) {
+ Node emptySet = nm->mkConst<EmptySet>(EmptySet(nm->toType(l.getType())));
+ if(d_equalityEngine.getRepresentative(l).getKind() != kind::EMPTYSET) {
+ leaves1_nonempty.push_back(l);
+ } else {
+ // reason = nm->mkNode(kind::AND, reason, EQUAL(l, emptySet));
+ }
+ }
+ BOOST_FOREACH(TNode l, leaves2) {
+ Node emptySet = nm->mkConst<EmptySet>(EmptySet(nm->toType(l.getType())));
+ if(d_equalityEngine.getRepresentative(l).getKind() != kind::EMPTYSET) {
+ leaves2_nonempty.push_back(l);
+ } else {
+ // reason = nm->mkNode(kind::AND, reason, EQUAL(l, emptySet));
+ }
+ }
+
+ // last minute stuff
+ reason = nm->mkNode(kind::AND, reason, eqemptySoFar());
+
+ Trace("sets-graph-merge") << "[sets-graph-merge] merge_nodes(..,.., " << reason << ")"
+ << std::endl;
+ print_graph();
+ Trace("sets-graph") << std::endl;
+
+ std::set<TNode> leaves3, leaves4;
+ std::set_difference(leaves1_nonempty.begin(), leaves1_nonempty.end(),
+ leaves2_nonempty.begin(), leaves2_nonempty.end(),
+ std::inserter(leaves3, leaves3.begin()));
+ std::set_difference(leaves2_nonempty.begin(), leaves2_nonempty.end(),
+ leaves1_nonempty.begin(), leaves1_nonempty.end(),
+ std::inserter(leaves4, leaves4.begin()));
+
+ if(leaves3.size() == 0) {
+ Trace("sets-graph-merge") << "[sets-graph-merge] Merge Equality 1" << std::endl;
+ // make everything in leaves4 empty
+ BOOST_FOREACH(TNode v , leaves4) {
+ Node zero = nm->mkConst(Rational(0));
+ if(!d_equalityEngine.hasTerm(zero)) {
+ d_equalityEngine.addTerm(zero);
+ d_termInfoManager->addTerm(zero);
+ }
+ learnLiteral( /* atom = */ EQUAL(nm->mkNode(kind::CARD, v), zero),
+ /* polarity = */ true,
+ /* reason = */ reason);
+ }
+ ++d_statistics.d_numMergeEq1or2;
+ } else if(leaves4.size() == 0) {
+ Trace("sets-graph-merge") << "[sets-graph-merge] Merge Equality 2" << std::endl;
+ // make everything in leaves3 empty
+ BOOST_FOREACH(TNode v , leaves3) {
+ Node zero = nm->mkConst(Rational(0));
+ if(!d_equalityEngine.hasTerm(zero)) {
+ d_equalityEngine.addTerm(zero);
+ d_termInfoManager->addTerm(zero);
+ }
+ learnLiteral( /* atom = */ EQUAL(nm->mkNode(kind::CARD, v), zero),
+ /* polarity = */ true,
+ /* reason = */ reason);
+ }
+ ++d_statistics.d_numMergeEq1or2;
+ } else {
+ Trace("sets-graph-merge") << "[sets-graph-merge] Merge Equality 3" << std::endl;
+ Trace("sets-graph-merge") << "[sets-graph-merge] #left= " << leaves1.size()
+ << " #right= " << leaves2.size()
+ << " #left non-empty= " << leaves1_nonempty.size()
+ << " #right non-empty= " << leaves2_nonempty.size()
+ << " #left-right= " << leaves3.size()
+ << " #right-left= " << leaves4.size() << std::endl;
+
+ std::map<TNode, vector<TNode> > children;
+
+ // Merge Equality 3
+ BOOST_FOREACH(TNode l1 , leaves3) {
+ BOOST_FOREACH(TNode l2 , leaves4) {
+ Node l1_inter_l2 = nm->mkNode(kind::INTERSECTION, min(l1, l2), max(l1, l2));
+ l1_inter_l2 = Rewriter::rewrite(l1_inter_l2);
+ add_node(l1_inter_l2);
+ children[l1].push_back(l1_inter_l2);
+ children[l2].push_back(l1_inter_l2);
+ // if(d_V.find(l1_inter_l2) != d_V.end()) {
+ // // This case needs to be handled, currently not
+ // Warning() << "This might create a loop. We need to handle this case. Probably merge the two nodes?" << std::endl;
+ // Unhandled();
+ // }
+ }
+ ++d_statistics.d_numMergeEq3;
+ }
+
+ for(std::map<TNode, vector<TNode> >::iterator it = children.begin();
+ it != children.end(); ++it) {
+ add_edges(it->first, it->second);
+ Node rhs;
+ if(it->second.size() == 1) {
+ rhs = nm->mkNode(kind::CARD, it->second[0]);
+ } else {
+ NodeBuilder<> nb(kind::PLUS);
+ BOOST_FOREACH(TNode n , it->second) {
+ Node card_n = nm->mkNode(kind::CARD, n);
+ nb << card_n;
+ }
+ rhs = Node(nb);
+ }
+ Node lem;
+ lem = nm->mkNode(kind::EQUAL,
+ nm->mkNode(kind::CARD, it->first),
+ rhs);
+ lem = nm->mkNode(kind::IMPLIES, reason, lem);
+ lem = Rewriter::rewrite(lem);
+ d_external.d_out->lemma(lem);
+ }
+ }
+
+ Trace("sets-graph") << std::endl;
+ print_graph();
+ Trace("sets-graph") << std::endl;
+
+}
+
+void TheorySetsPrivate::print_graph() {
+ std::string tag = "sets-graph";
+ if(Trace.isOn("sets-graph")) {
+ Trace(tag) << "[sets-graph] Graph : " << std::endl;
+ for(typeof(d_V.begin()) it = d_V.begin(); it != d_V.end(); ++it) {
+ TNode v = *it;
+ // BOOST_FOREACH(TNode v, d_V) {
+ Trace(tag) << "[" << tag << "] " << v << " : ";
+ // BOOST_FOREACH(TNode w, d_E[v].get()) {
+ if(d_E.find(v) != d_E.end()) {
+ BOOST_FOREACH(TNode w, d_E[v].get()) {
+ Trace(tag) << w << ", ";
+ }
+ } else {
+ Trace(tag) << " leaf. " ;
+ }
+ Trace(tag) << std::endl;
+ }
+ }
+
+ if(Trace.isOn("sets-graph-dot")) {
+ std::ostringstream oss;
+ oss << "digraph G { ";
+ for(typeof(d_V.begin()) it = d_V.begin(); it != d_V.end(); ++it) {
+ TNode v = *it;
+ if(d_E.find(v) != d_E.end()) {
+ BOOST_FOREACH(TNode w, d_E[v].get()) {
+ //oss << v.getId() << " -> " << w.getId() << "; ";
+ oss << "\"" << v << "\" -> \"" << w << "\"; ";
+ }
+ } else {
+ oss << "\"" << v << "\";";
+ }
+ }
+ oss << "}";
+ Trace("sets-graph-dot") << "[sets-graph-dot] " << oss.str() << std::endl;
+ }
+}
+
+Node TheorySetsPrivate::eqSoFar() {
+ std::vector<Node> V(d_allSetEqualitiesSoFar.begin(), d_allSetEqualitiesSoFar.end());
+ if(V.size() == 0) {
+ return d_trueNode;
+ } else if(V.size() == 1) {
+ return V[0];
+ } else {
+ NodeManager* nm = NodeManager::currentNM();
+ return nm->mkNode(kind::AND, V);
+ }
+}
+
+
+void TheorySetsPrivate::guessLeavesEmptyLemmas() {
+
+ // Guess leaf nodes being empty or non-empty
+ NodeManager* nm = NodeManager::currentNM();
+ leaves.clear();
+ for(typeof(d_V.begin()) it = d_V.begin(); it != d_V.end(); ++it) {
+ TNode v = *it;
+ if(d_E.find(v) == d_E.end()) {
+ leaves.insert(v);
+ }
+ }
+ d_statistics.d_numLeaves.setData(leaves.size());
+ d_statistics.d_numLeavesMax.maxAssign(leaves.size());
+
+ int
+ numLeaves = leaves.size(),
+ numLemmasGenerated = 0,
+ numLeavesIsEmpty = 0,
+ numLeavesIsNonEmpty = 0,
+ numLeavesCurrentlyNonEmpty = 0,
+ numLemmaAlreadyExisted = 0;
+
+ for(typeof(leaves.begin()) it = leaves.begin(); it != leaves.end(); ++it) {
+ bool generateLemma = true;
+ Node emptySet = nm->mkConst<EmptySet>(EmptySet(nm->toType((*it).getType())));
+
+ if(d_equalityEngine.hasTerm(*it)) {
+ Node n = d_equalityEngine.getRepresentative(*it);
+ if(n.getKind() == kind::EMPTYSET) {
+ ++numLeavesIsEmpty;
+ continue;
+ }
+ if(d_termInfoManager->getMembers(n)->size() > 0) {
+ ++numLeavesCurrentlyNonEmpty;
+ continue;
+ }
+ if(!d_equalityEngine.hasTerm(emptySet)) {
+ d_equalityEngine.addTerm(emptySet);
+ }
+ if(d_equalityEngine.areDisequal(n, emptySet, false)) {
+ ++numLeavesIsNonEmpty;
+ generateLemma = false;
+ }
+ }
+
+ if(generateLemma) {
+ Node n = nm->mkNode(kind::EQUAL, (*it), emptySet);
+ Node lem = nm->mkNode(kind::OR, n, nm->mkNode(kind::NOT, n));
+ bool lemmaGenerated =
+ lemma(lem, SETS_LEMMA_GRAPH);
+ if(lemmaGenerated) {
+ ++numLemmasGenerated;
+ } else {
+ ++numLemmaAlreadyExisted;
+ }
+ n = d_external.d_valuation.ensureLiteral(n);
+ d_external.d_out->requirePhase(n, true);
+ }
+
+ }
+ Trace("sets-guess-empty")
+ << "[sets-guess-empty] numLeaves = " << numLeaves << std::endl
+ << " numLemmasGenerated = " << numLemmasGenerated << std::endl
+ << " numLeavesIsEmpty = " << numLeavesIsEmpty << std::endl
+ << " numLeavesIsNonEmpty = " << numLeavesIsNonEmpty << std::endl
+ << " numLeavesCurrentlyNonEmpty = " << numLeavesCurrentlyNonEmpty << std::endl
+ << " numLemmaAlreadyExisted = " << numLemmaAlreadyExisted << std::endl;
+
+}
+
+void TheorySetsPrivate::processCard2(Theory::Effort level) {
+ CodeTimer codeTimer(d_statistics.d_processCard2Time);
+
+ if(level != Theory::EFFORT_FULL) return;
+
+ d_statistics.d_numVertices.setData(d_V.size());
+ d_statistics.d_numVerticesMax.maxAssign(d_V.size());
+
+ Trace("sets-card") << "[sets-card] processCard( " << level << ")" << std::endl;
+ Trace("sets-card") << "[sets-card] # vertices = " << d_V.size() << std::endl;
+
+ NodeManager* nm = NodeManager::currentNM();
+
+ // Introduce
+ for(typeof(d_cardTerms.begin()) it = d_cardTerms.begin();
+ it != d_cardTerms.end(); ++it) {
+
+ for(eq::EqClassIterator j(d_equalityEngine.getRepresentative((*it)[0]), &d_equalityEngine);
+ !j.isFinished(); ++j) {
+
+ Node n = nm->mkNode(kind::CARD, (*j));
+
+ if(d_processedCardTerms.find(n) != d_processedCardTerms.end()) {
+ continue;
+ }
+
+ if(d_relTerms.find(n[0]) == d_relTerms.end()) {
+ // not relevant, skip
+ continue;
+ }
+
+ Trace("sets-graph") << std::endl;
+ print_graph();
+ Trace("sets-graph") << std::endl;
+
+ add_node(n[0]);
+
+ Trace("sets-card") << "[sets-card] Processing " << n << " in eq cl of " << (*it) << std::endl;
+
+ d_processedCardTerms.insert(n);
+
+ Kind k = n[0].getKind();
+
+ if(k == kind::SINGLETON) {
+ Trace("sets-card") << "[sets-card] Introduce Singleton " << n[0] << std::endl;
+ continue;
+ }
+
+ // rest of the processing is for compound terms
+ if(k != kind::UNION && k != kind::INTERSECTION && k != kind::SETMINUS) {
+ continue;
+ }
+
+ Trace("sets-card") << "[sets-card] Introduce Term " << n[0] << std::endl;
+
+ Node s = min(n[0][0], n[0][1]);
+ Node t = max(n[0][0], n[0][1]);
+ bool isUnion = (k == kind::UNION);
+ Assert(Rewriter::rewrite(s) == s);
+ Assert(Rewriter::rewrite(t) == t);
+
+ Node sNt = nm->mkNode(kind::INTERSECTION, s, t);
+ sNt = Rewriter::rewrite(sNt);
+ Node sMt = nm->mkNode(kind::SETMINUS, s, t);
+ sMt = Rewriter::rewrite(sMt);
+ Node tMs = nm->mkNode(kind::SETMINUS, t, s);
+ tMs = Rewriter::rewrite(tMs);
+
+ Node card_s = nm->mkNode(kind::CARD, s);
+ Node card_t = nm->mkNode(kind::CARD, t);
+ Node card_sNt = nm->mkNode(kind::CARD, sNt);
+ Node card_sMt = nm->mkNode(kind::CARD, sMt);
+ Node card_tMs = nm->mkNode(kind::CARD, tMs);
+
+ Node lem;
+
+ add_node(sMt);
+ add_node(sNt);
+ add_node(tMs);
+
+
+ // for union
+ if(isUnion) {
+ if(d_E.find(n[0]) != d_E.end()) {
+ // do a merge of current leaves of d_E with
+ // sNT sMT tMs
+ Trace("sets-card") << "[sets-card] Already found in the graph, merging " << n[0] << std::endl;
+ merge_nodes(get_leaves(n[0]), get_leaves(sMt, sNt, tMs), eqSoFar());
+ } else {
+ add_node(n[0]);
+
+ lem = nm->mkNode(kind::EQUAL,
+ n, // card(s union t)
+ nm->mkNode(kind::PLUS, card_sNt, card_sMt, card_tMs));
+ lemma(lem, SETS_LEMMA_GRAPH);
+
+ Assert(d_E.find(n[0]) == d_E.end());
+ add_edges(n[0], sMt, sNt, tMs);
+ }
+ }
+
+ // for s
+ if(d_E.find(s) == d_E.end()) {
+ add_node(s);
+ add_edges(s, sMt, sNt);
+
+ lem = nm->mkNode(kind::EQUAL,
+ card_s,
+ nm->mkNode(kind::PLUS, card_sNt, card_sMt));
+ lemma(lem, SETS_LEMMA_GRAPH);
+ } else {
+ if(find(d_E[s].get().begin(), d_E[s].get().end(), sMt) != d_E[s].get().end()) {
+ Assert( find(d_E[s].get().begin(), d_E[s].get().end(), sMt) != d_E[s].get().end() );
+ Assert( find(d_E[s].get().begin(), d_E[s].get().end(), sNt) != d_E[s].get().end() );
+ Assert( find(d_E[t].get().begin(), d_E[t].get().end(), tMs) != d_E[t].get().end() );
+ Assert( find(d_E[t].get().begin(), d_E[t].get().end(), sNt) != d_E[t].get().end() );
+ continue;
+ }
+
+ Trace("sets-card") << "[sets-card] Already found in the graph, merging " << s << std::endl;
+ merge_nodes(get_leaves(s), get_leaves(sMt, sNt), eqSoFar());
+ }
+
+ // for t
+ if(d_E.find(t) == d_E.end()) {
+ Assert(d_E.find(t) == d_E.end());
+ add_node(t);
+ add_edges(t, sNt, tMs);
+
+ lem = nm->mkNode(kind::EQUAL,
+ card_t,
+ nm->mkNode(kind::PLUS, card_sNt, card_tMs));
+ lemma(lem, SETS_LEMMA_GRAPH);
+ } else {
+ // Assert( find(d_E[s].get().begin(), d_E[s].get().end(), sMt) == d_E[s].get().end() );
+ // Assert( find(d_E[s].get().begin(), d_E[s].get().end(), sNt) == d_E[s].get().end() );
+ // Assert( find(d_E[t].get().begin(), d_E[t].get().end(), tMs) == d_E[t].get().end() );
+ // Assert( find(d_E[t].get().begin(), d_E[t].get().end(), sNt) == d_E[t].get().end() );
+
+ Trace("sets-card") << "[sets-card] Already found in the graph, merging " << t << std::endl;
+ merge_nodes(get_leaves(t), get_leaves(sNt, tMs), eqSoFar());
+ }
+
+ if(options::setsSlowLemmas()) {
+ if(d_newLemmaGenerated) {
+ break;
+ } else if(options::setsGuessEmpty() == 0) {
+ guessLeavesEmptyLemmas();
+ if(d_newLemmaGenerated) {
+ return;
+ }
+ }
+ }
+
+ }//equivalence class loop
+
+ if(options::setsSlowLemmas() && d_newLemmaGenerated) {
+ break;
+ }
+
+ }//d_cardTerms loop
+
+ print_graph();
+
+ if(d_newLemmaGenerated) {
+ Trace("sets-card") << "[sets-card] New introduce done. Returning." << std::endl;
+ return;
+ }
+
+ if(options::setsGuessEmpty() == 1) {
+ guessLeavesEmptyLemmas();
+ if(d_newLemmaGenerated) {
+ return;
+ }
+ }
+
+ // Merge equalities from input assertions
+
+ while(!d_graphMergesPending.empty()) {
+ std::pair<TNode,TNode> np = d_graphMergesPending.front();
+ d_graphMergesPending.pop();
+
+ Debug("sets-card") << "[sets-card] Equality " << np.first << " " << np.second << std::endl;
+ if(np.first.getKind() == kind::EMPTYSET || np.second.getKind() == kind::EMPTYSET) {
+ Debug("sets-card") << "[sets-card] skipping merge as one side is empty set" << std::endl;
+ continue;
+ }
+
+ if(d_V.find(np.first) == d_V.end() || d_V.find(np.second) == d_V.end()) {
+ Assert((d_V.find(np.first) == d_V.end()));
+ Assert((d_V.find(np.second) == d_V.end()));
+ continue;
+ }
+ d_allSetEqualitiesSoFar.push_back(EQUAL(np.first, np.second));
+ // merge_nodes(get_leaves(np.first), get_leaves(np.second), EQUAL(np.first, np.second));
+ merge_nodes(get_leaves(np.first), get_leaves(np.second), eqSoFar());
+ }
+
+ if(d_newLemmaGenerated) {
+ Trace("sets-card") << "[sets-card] New merge done. Returning." << std::endl;
+ return;
+ }
+
+ leaves.clear();
+ for(typeof(d_V.begin()) it = d_V.begin(); it != d_V.end(); ++it) {
+ TNode v = *it;
+ if(d_E.find(v) == d_E.end()) {
+ leaves.insert(v);
+ }
+ }
+ Trace("sets-card") << "[sets-card] # leaves = " << leaves.size() << std::endl;
+ d_statistics.d_numLeaves.setData(leaves.size());
+ d_statistics.d_numLeavesMax.maxAssign(leaves.size());
+
+ Assert(!d_newLemmaGenerated);
+
+
+ if(options::setsGuessEmpty() == 2) {
+ guessLeavesEmptyLemmas();
+ if(d_newLemmaGenerated) {
+ return;
+ }
+ }
+
+ // Elements being either equal or disequal [Members Arrangement rule]
+ Trace("sets-card") << "[sets-card] Processing elements equality/disequal to each other" << std::endl;
+ for(typeof(leaves.begin()) it = leaves.begin();
+ it != leaves.end(); ++it) {
+ if(!d_equalityEngine.hasTerm(*it)) continue;
+ Node n = d_equalityEngine.getRepresentative(*it);
+ Assert(n.getKind() == kind::EMPTYSET || leaves.find(n) != leaves.end());
+ if(n != *it) continue;
+ const CDTNodeList* l = d_termInfoManager->getMembers(*it);
+ std::set<TNode> elems;
+ for(typeof(l->begin()) l_it = l->begin(); l_it != l->end(); ++l_it) {
+ elems.insert(d_equalityEngine.getRepresentative(*l_it));
+ }
+ for(typeof(elems.begin()) e1_it = elems.begin(); e1_it != elems.end(); ++e1_it) {
+ for(typeof(elems.begin()) e2_it = elems.begin(); e2_it != elems.end(); ++e2_it) {
+ if(*e1_it == *e2_it) continue;
+ if(!d_equalityEngine.areDisequal(*e1_it, *e2_it, false)) {
+ Node lem = nm->mkNode(kind::EQUAL, *e1_it, *e2_it);
+ lem = nm->mkNode(kind::OR, lem, nm->mkNode(kind::NOT, lem));
+ lemma(lem, SETS_LEMMA_GRAPH);
+ }
+ }
+ }
+ }
+
+ if(d_newLemmaGenerated) {
+ Trace("sets-card") << "[sets-card] Members arrangments lemmas. Returning." << std::endl;
+ return;
+ }
+
+ // Assert Lower bound
+ Trace("sets-card") << "[sets-card] Processing assert lower bound" << std::endl;
+ for(typeof(leaves.begin()) it = leaves.begin();
+ it != leaves.end(); ++it) {
+ Trace("sets-cardlower") << "[sets-cardlower] Card Lower: " << *it << std::endl;
+ Assert(d_equalityEngine.hasTerm(*it));
+ Node n = d_equalityEngine.getRepresentative(*it);
+ // Node n = (*it);
+ // if(!d_equalityEngine.hasTerm(n)) {
+ // Trace("sets-cardlower") << "[sets-cardlower] not in EE" << std::endl;
+ // continue;
+ // }
+ // Assert(n.getKind() == kind::EMPTYSET || leaves.find(n) != leaves.end()); // ????
+ // if(n != *it) continue;
+ const CDTNodeList* l = d_termInfoManager->getMembers(n);
+ std::set<TNode> elems;
+ for(typeof(l->begin()) l_it = l->begin(); l_it != l->end(); ++l_it) {
+ elems.insert(d_equalityEngine.getRepresentative(*l_it));
+ }
+ if(elems.size() == 0) continue;
+ NodeBuilder<> nb(kind::OR);
+ nb << ( nm->mkNode(kind::LEQ, nm->mkConst(Rational(elems.size())), nm->mkNode(kind::CARD, *it)) );
+ if(elems.size() > 1) {
+ for(typeof(elems.begin()) e1_it = elems.begin(); e1_it != elems.end(); ++e1_it) {
+ for(typeof(elems.begin()) e2_it = elems.begin(); e2_it != elems.end(); ++e2_it) {
+ if(*e1_it == *e2_it) continue;
+ nb << (nm->mkNode(kind::EQUAL, *e1_it, *e2_it));
+ }
+ }
+ }
+ for(typeof(elems.begin()) e_it = elems.begin(); e_it != elems.end(); ++e_it) {
+ nb << nm->mkNode(kind::NOT, nm->mkNode(kind::MEMBER, *e_it, *it));
+ }
+ Node lem = Node(nb);
+ // if(d_cardLowerLemmaCache.find(lem) == d_cardLowerLemmaCache.end()) {
+ Trace("sets-card") << "[sets-card] Card Lower: " << lem << std::endl;
+ lemma(lem, SETS_LEMMA_GRAPH);
+ // d_cardLowerLemmaCache.insert(lem);
+ // }
+ }
+}
+
+
+
}/* CVC4::theory::sets namespace */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
diff --git a/src/theory/sets/theory_sets_private.h b/src/theory/sets/theory_sets_private.h
index a01e9a168..217432670 100644
--- a/src/theory/sets/theory_sets_private.h
+++ b/src/theory/sets/theory_sets_private.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_sets_private.h
** \verbatim
- ** Original author: Kshitij Bansal
- ** Major contributors: none
- ** Minor contributors (to current version): Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Kshitij Bansal, Tim King, Andrew Reynolds
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Sets theory implementation.
**
@@ -68,6 +68,8 @@ public:
void preRegisterTerm(TNode node);
+ void presolve();
+
void propagate(Theory::Effort);
private:
@@ -76,8 +78,16 @@ private:
class Statistics {
public:
TimerStat d_getModelValueTime;
+ TimerStat d_mergeTime;
+ TimerStat d_processCard2Time;
IntStat d_memberLemmas;
IntStat d_disequalityLemmas;
+ IntStat d_numVertices;
+ IntStat d_numVerticesMax;
+ IntStat d_numMergeEq1or2;
+ IntStat d_numMergeEq3;
+ IntStat d_numLeaves;
+ IntStat d_numLeavesMax;
Statistics();
~Statistics();
@@ -115,6 +125,20 @@ private:
/** generate and send out conflict node */
void conflict(TNode, TNode);
+ /** send out a lemma */
+ enum SetsLemmaTag {
+ SETS_LEMMA_DISEQUAL,
+ SETS_LEMMA_MEMBER,
+ SETS_LEMMA_GRAPH,
+ SETS_LEMMA_OTHER
+ };
+
+ /**
+ * returns true if a lemmas was generated
+ * returns false otherwise (found in cache)
+ */
+ bool lemma(Node n, SetsLemmaTag t);
+
class TermInfoManager {
TheorySetsPrivate& d_theory;
context::Context* d_context;
@@ -143,6 +167,25 @@ private:
};
TermInfoManager* d_termInfoManager;
+ /******
+ * Card Vars :
+ *
+ * mapping from set terms to correpsonding cardinality variable
+ *
+ * in the ::check function, when we get one of those cardinality
+ * variables to be assigned to 0, we will assert in equality engine
+ * to be equal to empty set.
+ *
+ * if required, we will add more filters so it doesn't leak to
+ * outside world
+ */
+ Node getCardVar(TNode n);
+ Node newCardVar(TNode n);
+ bool isCardVar(TNode n);
+ typedef std::hash_map <Node, Node, NodeHashFunction> NodeNodeHashMap;
+ NodeNodeHashMap d_setTermToCardVar;
+ NodeNodeHashMap d_cardVarToSetTerm;
+
/** Assertions and helper functions */
bool present(TNode atom);
bool holds(TNode lit) {
@@ -205,6 +248,55 @@ private:
// relational solver
TheorySetsRels* d_rels;
+ /***** Cardinality handling *****/
+ bool d_cardEnabled;
+ void enableCard();
+ void cardCreateEmptysetSkolem(TypeNode t);
+
+ CDNodeSet d_cardTerms;
+ std::set<TypeNode> d_typesAdded;
+ CDNodeSet d_processedCardTerms;
+ std::map<std::pair<Node, Node>, bool> d_processedCardPairs;
+ CDNodeSet d_cardLowerLemmaCache;
+ void registerCard(TNode);
+ void processCard(Theory::Effort level);
+
+ /* Graph handling */
+ std::map<TNode, std::set<TNode> > edgesFd;
+ std::map<TNode, std::set<TNode> > edgesBk;
+ std::set< std::pair<TNode, TNode> > disjoint;
+ std::set<TNode> leaves;
+ void buildGraph();
+
+ /* For calculus as in paper */
+ void processCard2(Theory::Effort level);
+ CDNodeSet d_V;
+ context::CDHashMap <TNode, std::vector<TNode>, TNodeHashFunction > d_E;
+ void add_edges(TNode source, TNode dest);
+ void add_edges(TNode source, TNode dest1, TNode dest2);
+ void add_edges(TNode source, TNode dest1, TNode dest2, TNode dest3);
+ void add_edges(TNode source, const std::vector<TNode>& dests);
+ void add_node(TNode vertex);
+ void merge_nodes(std::set<TNode> a, std::set<TNode> b, Node reason);
+ std::set<TNode> get_leaves(Node vertex);
+ std::set<TNode> get_leaves(Node vertex1, Node vertex2);
+ std::set<TNode> get_leaves(Node vertex1, Node vertex2, Node vertex3);
+ std::set<TNode> non_empty(std::set<TNode> vertices);
+ void print_graph();
+ context::CDQueue < std::pair<TNode, TNode> > d_graphMergesPending;
+ context::CDList<Node> d_allSetEqualitiesSoFar;
+ Node eqSoFar();
+ Node eqemptySoFar();
+
+ std::set<TNode> getNonEmptyLeaves(TNode);
+ CDNodeSet d_lemmasGenerated;
+ bool d_newLemmaGenerated;
+
+ void guessLeavesEmptyLemmas();
+
+
+ /** relevant terms */
+ CDNodeSet d_relTerms;
};/* class TheorySetsPrivate */
diff --git a/src/theory/sets/theory_sets_rewriter.cpp b/src/theory/sets/theory_sets_rewriter.cpp
index 9156e3a75..5204dcaed 100644
--- a/src/theory/sets/theory_sets_rewriter.cpp
+++ b/src/theory/sets/theory_sets_rewriter.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_sets_rewriter.cpp
** \verbatim
- ** Original author: Kshitij Bansal
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Kshitij Bansal, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Sets theory rewriter.
**
@@ -18,6 +18,8 @@
#include "theory/sets/normal_form.h"
#include "theory/sets/theory_sets_rels.h"
#include "theory/sets/rels_utils.h"
+#include "expr/attribute.h"
+#include "options/sets_options.h"
namespace CVC4 {
namespace theory {
@@ -26,6 +28,101 @@ namespace sets {
typedef std::set<TNode> Elements;
typedef std::hash_map<TNode, Elements, TNodeHashFunction> SettermElementsMap;
+struct FlattenedNodeTag {};
+typedef expr::Attribute<FlattenedNodeTag, bool> flattened;
+
+
+/**
+ * flattenNode looks for children of same kind, and if found merges
+ * them into the parent.
+ *
+ * It simultaneously handles a couple of other optimizations:
+ * - trivialNode - if found during exploration, return that node itself
+ * (like in case of OR, if "true" is found, makes sense to replace
+ * whole formula with "true")
+ * - skipNode - as name suggests, skip them
+ * (like in case of OR, you may want to skip any "false" nodes found)
+ *
+ * Use a null node if you want to ignore any of the optimizations.
+ */
+RewriteResponse flattenNode(TNode n, TNode trivialNode, TNode skipNode)
+{
+ if(n.hasAttribute(flattened()) && n.getAttribute(flattened())) {
+ return RewriteResponse(REWRITE_DONE, n);
+ }
+
+ typedef std::hash_set<TNode, TNodeHashFunction> node_set;
+
+ node_set visited;
+ visited.insert(skipNode);
+
+ std::vector<TNode> toProcess;
+ toProcess.push_back(n);
+
+ Kind k = n.getKind();
+ typedef std::vector<TNode> ChildList;
+ ChildList childList; //TNode should be fine, since 'n' is still there
+
+ Debug("sets-rewrite-flatten") << "[sets-rewrite-flatten] " << n << std::endl;
+ for (unsigned i = 0; i < toProcess.size(); ++ i) {
+ TNode current = toProcess[i];
+ Debug("sets-rewrite-flatten") << "[sets-rewrite-flatten] > Processing " << current << std::endl;
+ for(unsigned j = 0, j_end = current.getNumChildren(); j < j_end; ++ j) {
+ TNode child = current[j];
+ if(visited.find(child) != visited.end()) {
+ continue;
+ } else if(child == trivialNode) {
+ return RewriteResponse(REWRITE_DONE, trivialNode);
+ } else {
+ visited.insert(child);
+ if(child.getKind() == k) {
+ toProcess.push_back(child);
+ } else {
+ childList.push_back(child);
+ }
+ }
+ }
+ }
+ if (childList.size() == 0) return RewriteResponse(REWRITE_DONE, skipNode);
+ if (childList.size() == 1) return RewriteResponse(REWRITE_AGAIN, childList[0]);
+
+ sort(childList.begin(), childList.end());
+
+ /* Make sure we are under number of children possible in a node */
+ NodeManager* nodeManager = NodeManager::currentNM();
+ static const unsigned MAX_CHILDREN = (1u << __CVC4__EXPR__NODE_VALUE__NBITS__NCHILDREN ) - 1;
+ AlwaysAssert(childList.size() < MAX_CHILDREN, "do not support formulas this big");
+
+ ChildList::iterator cur = childList.begin(), next, en = childList.end();
+ Node ret = (*cur);
+ ++cur;
+ while( cur != en ) {
+ ret = nodeManager->mkNode(k, ret, *cur);
+ ret.setAttribute(flattened(), true);
+ ++cur;
+ }
+ Trace("sets-postrewrite") << "flatten Sets::postRewrite returning " << ret << std::endl;
+ if(ret != n) {
+ return RewriteResponse(REWRITE_AGAIN, ret); // again for constants
+ } else {
+ return RewriteResponse(REWRITE_DONE, ret);
+ }
+ // if (childList.size() < MAX_CHILDREN) {
+ // Node retNode = nodeManager->mkNode(k, childList);
+ // return RewriteResponse(REWRITE_DONE, retNode);
+ // } else {
+ // Assert(childList.size() < size_t(MAX_CHILDREN) * size_t(MAX_CHILDREN) );
+ // NodeBuilder<> nb(k);
+ // ChildList::iterator cur = childList.begin(), next, en = childList.end();
+ // while( cur != en ) {
+ // next = min(cur + MAX_CHILDREN, en);
+ // nb << (nodeManager->mkNode(k, ChildList(cur, next) ));
+ // cur = next;
+ // }
+ // return RewriteResponse(REWRITE_DONE, nb.constructNode());
+ // }
+}
+
bool checkConstantMembership(TNode elementTerm, TNode setTerm)
{
if(setTerm.getKind() == kind::EMPTYSET) {
@@ -103,57 +200,92 @@ RewriteResponse TheorySetsRewriter::postRewrite(TNode node) {
}//kind::IFF
case kind::SETMINUS: {
- if(node[0] == node[1]) {
- Node newNode = nm->mkConst(EmptySet(nm->toType(node[0].getType())));
- Trace("sets-postrewrite") << "Sets::postRewrite returning " << newNode << std::endl;
- return RewriteResponse(REWRITE_DONE, newNode);
- } else if(node[0].getKind() == kind::EMPTYSET ||
- node[1].getKind() == kind::EMPTYSET) {
- Trace("sets-postrewrite") << "Sets::postRewrite returning " << node[0] << std::endl;
- return RewriteResponse(REWRITE_DONE, node[0]);
- } else if(node[0].isConst() && node[1].isConst()) {
- std::set<Node> left = NormalForm::getElementsFromNormalConstant(node[0]);
- std::set<Node> right = NormalForm::getElementsFromNormalConstant(node[1]);
- std::set<Node> newSet;
- std::set_difference(left.begin(), left.end(), right.begin(), right.end(),
- std::inserter(newSet, newSet.begin()));
- Node newNode = NormalForm::elementsToSet(newSet, node.getType());
- Assert(newNode.isConst());
- Trace("sets-postrewrite") << "Sets::postRewrite returning " << newNode << std::endl;
- return RewriteResponse(REWRITE_DONE, newNode);
+ if( options::setsAggRewrite() ){
+ Node newNode = rewriteSet( node );
+ if( newNode!=node ){
+ return RewriteResponse(REWRITE_DONE, newNode);
+ }
+ }else{
+ if(node[0] == node[1]) {
+ Node newNode = nm->mkConst(EmptySet(nm->toType(node[0].getType())));
+ Trace("sets-postrewrite") << "Sets::postRewrite returning " << newNode << std::endl;
+ return RewriteResponse(REWRITE_DONE, newNode);
+ } else if(node[0].getKind() == kind::EMPTYSET ||
+ node[1].getKind() == kind::EMPTYSET) {
+ Trace("sets-postrewrite") << "Sets::postRewrite returning " << node[0] << std::endl;
+ return RewriteResponse(REWRITE_DONE, node[0]);
+ } else if(node[0].isConst() && node[1].isConst()) {
+ std::set<Node> left = NormalForm::getElementsFromNormalConstant(node[0]);
+ std::set<Node> right = NormalForm::getElementsFromNormalConstant(node[1]);
+ std::set<Node> newSet;
+ std::set_difference(left.begin(), left.end(), right.begin(), right.end(),
+ std::inserter(newSet, newSet.begin()));
+ Node newNode = NormalForm::elementsToSet(newSet, node.getType());
+ Assert(newNode.isConst());
+ Trace("sets-postrewrite") << "Sets::postRewrite returning " << newNode << std::endl;
+ return RewriteResponse(REWRITE_DONE, newNode);
+ }
}
break;
- }//kind::INTERSECION
+ }//kind::SETMINUS
case kind::INTERSECTION: {
- if(node[0] == node[1]) {
- Trace("sets-postrewrite") << "Sets::postRewrite returning " << node[0] << std::endl;
- return RewriteResponse(REWRITE_DONE, node[0]);
- } else if(node[0].getKind() == kind::EMPTYSET) {
- return RewriteResponse(REWRITE_DONE, node[0]);
- } else if(node[1].getKind() == kind::EMPTYSET) {
- return RewriteResponse(REWRITE_DONE, node[1]);
- } else if(node[0].isConst() && node[1].isConst()) {
- std::set<Node> left = NormalForm::getElementsFromNormalConstant(node[0]);
- std::set<Node> right = NormalForm::getElementsFromNormalConstant(node[1]);
- std::set<Node> newSet;
- std::set_intersection(left.begin(), left.end(), right.begin(), right.end(),
- std::inserter(newSet, newSet.begin()));
- Node newNode = NormalForm::elementsToSet(newSet, node.getType());
- Assert(newNode.isConst());
- Trace("sets-postrewrite") << "Sets::postRewrite returning " << newNode << std::endl;
- return RewriteResponse(REWRITE_DONE, newNode);
- } else if (node[0] > node[1]) {
- Node newNode = nm->mkNode(node.getKind(), node[1], node[0]);
- Trace("sets-postrewrite") << "Sets::postRewrite returning " << newNode << std::endl;
- return RewriteResponse(REWRITE_DONE, newNode);
+ if( options::setsAggRewrite() ){
+ Node newNode = rewriteSet( node );
+ if( newNode!=node ){
+ return RewriteResponse(REWRITE_DONE, newNode);
+ }
+ // }else{
+ // Node emptySet = nm->mkConst(EmptySet(nm->toType(node[0].getType())));
+ // if(node[0].isConst() && node[1].isConst()) {
+ // std::set<Node> left = NormalForm::getElementsFromNormalConstant(node[0]);
+ // std::set<Node> right = NormalForm::getElementsFromNormalConstant(node[1]);
+ // std::set<Node> newSet;
+ // std::set_intersection(left.begin(), left.end(), right.begin(), right.end(),
+ // std::inserter(newSet, newSet.begin()));
+ // Node newNode = NormalForm::elementsToSet(newSet, node.getType());
+ // Assert(newNode.isConst());
+ // Trace("sets-postrewrite") << "Sets::postRewrite returning " << newNode << std::endl;
+ // return RewriteResponse(REWRITE_DONE, newNode);
+ // } else {
+ // return flattenNode(node, /* trivialNode = */ emptySet, /* skipNode = */ Node());
+ // }
+ // }
+ }else{
+ if(node[0] == node[1]) {
+ Trace("sets-postrewrite") << "Sets::postRewrite returning " << node[0] << std::endl;
+ return RewriteResponse(REWRITE_DONE, node[0]);
+ } else if(node[0].getKind() == kind::EMPTYSET) {
+ return RewriteResponse(REWRITE_DONE, node[0]);
+ } else if(node[1].getKind() == kind::EMPTYSET) {
+ return RewriteResponse(REWRITE_DONE, node[1]);
+ } else if(node[0].isConst() && node[1].isConst()) {
+ std::set<Node> left = NormalForm::getElementsFromNormalConstant(node[0]);
+ std::set<Node> right = NormalForm::getElementsFromNormalConstant(node[1]);
+ std::set<Node> newSet;
+ std::set_intersection(left.begin(), left.end(), right.begin(), right.end(),
+ std::inserter(newSet, newSet.begin()));
+ Node newNode = NormalForm::elementsToSet(newSet, node.getType());
+ Assert(newNode.isConst());
+ Trace("sets-postrewrite") << "Sets::postRewrite returning " << newNode << std::endl;
+ return RewriteResponse(REWRITE_DONE, newNode);
+ } else if (node[0] > node[1]) {
+ Node newNode = nm->mkNode(node.getKind(), node[1], node[0]);
+ Trace("sets-postrewrite") << "Sets::postRewrite returning " << newNode << std::endl;
+ return RewriteResponse(REWRITE_DONE, newNode);
+ }
}
break;
}//kind::INTERSECION
case kind::UNION: {
// NOTE: case where it is CONST is taken care of at the top
- if(node[0] == node[1]) {
+ if( options::setsAggRewrite() ){
+ Node newNode = rewriteSet( node );
+ if( newNode!=node ){
+ return RewriteResponse(REWRITE_DONE, newNode);
+ }
+ }else if(node[0] == node[1]) {
Trace("sets-postrewrite") << "Sets::postRewrite returning " << node[0] << std::endl;
return RewriteResponse(REWRITE_DONE, node[0]);
} else if(node[0].getKind() == kind::EMPTYSET) {
@@ -170,7 +302,7 @@ RewriteResponse TheorySetsRewriter::postRewrite(TNode node) {
Assert(newNode.isConst());
Trace("sets-postrewrite") << "Sets::postRewrite returning " << newNode << std::endl;
return RewriteResponse(REWRITE_DONE, newNode);
- } else if (node[0] > node[1]) {
+ }else if (node[0] > node[1]) {
Node newNode = nm->mkNode(node.getKind(), node[1], node[0]);
Trace("sets-postrewrite") << "Sets::postRewrite returning " << newNode << std::endl;
return RewriteResponse(REWRITE_DONE, newNode);
@@ -178,6 +310,13 @@ RewriteResponse TheorySetsRewriter::postRewrite(TNode node) {
break;
}//kind::UNION
+ case kind::CARD: {
+ if(node[0].isConst()) {
+ std::set<Node> elements = NormalForm::getElementsFromNormalConstant(node[0]);
+ return RewriteResponse(REWRITE_DONE, nm->mkConst(Rational(elements.size())));
+ }
+ }
+
case kind::TRANSPOSE: {
if(node[0].getKind() == kind::TRANSPOSE) {
return RewriteResponse(REWRITE_AGAIN, node[0][0]);
@@ -365,6 +504,180 @@ RewriteResponse TheorySetsRewriter::preRewrite(TNode node) {
return RewriteResponse(REWRITE_DONE, node);
}
+Node TheorySetsRewriter::rewriteSet( Node s ) {
+ Trace("sets-rewrite-debug") << "Rewrite set : " << s << std::endl;
+ Node empSet = NodeManager::currentNM()->mkConst(EmptySet(NodeManager::currentNM()->toType(s.getType())));
+ bool success;
+ do{
+ success = false;
+ std::map< Node, bool > ca;
+ Node ss = rewriteSet( s, ca, empSet );
+ if( ss!=s ){
+ Assert( !ss.isNull() );
+ Trace("sets-rewrite") << "Rewrite set : " << s << std::endl;
+ Trace("sets-rewrite") << "........got : " << ss << std::endl;
+ success = true;
+ s = ss;
+ }
+ }while( success );
+ return s;
+}
+
+Node TheorySetsRewriter::rewriteSet( Node s, std::map< Node, bool >& ca, Node empSet ) {
+ if( s.getKind()!=kind::UNION && s.getKind()!=kind::INTERSECTION && s.getKind()!=kind::SETMINUS ){
+ std::map< Node, bool >::iterator it = ca.find( s );
+ if( it==ca.end() ){
+ return s;
+ }else if( it->second ){
+ return Node::null();
+ }else{
+ return empSet;
+ }
+ }else{
+ Trace("sets-rewrite-debug") << "Get components : " << s << std::endl;
+ std::map< Node, bool > c;
+ bool pol = s.getKind()!=kind::UNION;
+ if( pol ){
+ //copy current components
+ for( std::map< Node, bool >::iterator it = ca.begin(); it != ca.end(); ++it ){
+ c[it->first] = it->second;
+ }
+ }
+ if( collectSetComponents( s, c, pol ) ){
+ if( Trace.isOn("sets-rewrite-debug") ){
+ Trace("sets-rewrite-debug") << " got components : " << std::endl;
+ for( std::map< Node, bool >::iterator it = c.begin(); it != c.end(); ++it ){
+ Trace("sets-rewrite-debug") << " " << it->first << " -> " << it->second << std::endl;
+ }
+ }
+
+ //simplify components based on what is asserted in ca, recursively
+ std::map< Node, bool > nc;
+ if( pol ){
+ //copy map
+ for( std::map< Node, bool >::iterator it = c.begin(); it != c.end(); ++it ){
+ nc[it->first] = it->second;
+ }
+ //rewrite each new component based on current assertions
+ for( std::map< Node, bool >::iterator it = c.begin(); it != c.end(); ++it ){
+ if( ca.find( it->first )==ca.end() ){
+ nc.erase( it->first );
+ Node prev = it->first;
+ //only rewrite positive components here
+ Node ss = it->second ? rewriteSet( it->first, nc, empSet ) : it->first;
+ if( prev!=ss ){
+ Trace("sets-rewrite-debug") << " simplify component : " << prev << "..." << ss << std::endl;
+ }
+ if( ss==empSet ){
+ Trace("sets-rewrite-debug") << " return singularity " << ss << std::endl;
+ return ss;
+ }else if( !ss.isNull() ){
+ std::map< Node, bool >::iterator itc = nc.find( ss );
+ if( itc==nc.end() ){
+ nc[ss] = it->second;
+ }else if( it->second!=itc->second ){
+ Trace("sets-rewrite-debug") << "...conflict, return empty set." << std::endl;
+ return empSet;
+ }
+ }
+ }
+ }
+ }else{
+ for( std::map< Node, bool >::iterator it = c.begin(); it != c.end(); ++it ){
+ Node prev = it->first;
+ Node ss = rewriteSet( it->first, ca, empSet );
+ if( prev!=ss ){
+ Trace("sets-rewrite-debug") << " simplify component : " << prev << "..." << ss << std::endl;
+ }
+ if( ss.isNull() ){
+ Trace("sets-rewrite-debug") << " return singularity " << ss << std::endl;
+ return ss;
+ }else if( ss!=empSet ){
+ std::map< Node, bool >::iterator itc = nc.find( ss );
+ if( itc==nc.end() ){
+ nc[ss] = it->second;
+ }else if( it->second!=itc->second ){
+ Trace("sets-rewrite-debug") << "...conflict, return complete set." << std::endl;
+ return Node::null();
+ }
+ }
+ }
+ }
+
+
+ //construct sorted lists of positive, negative components
+ std::vector< Node > comp[2];
+ for( std::map< Node, bool >::iterator it = nc.begin(); it != nc.end(); ++it ){
+ if( !pol || ca.find( it->first )==ca.end() ){
+ comp[ ( it->second==pol ) ? 0 : 1 ].push_back( it->first );
+ }
+ }
+ //construct normalized set
+ Node curr;
+ for( unsigned i=0; i<2; i++ ){
+ if( comp[i].size()>1 ){
+ std::sort( comp[i].begin(), comp[i].end() );
+ }
+ if( i==0 ){
+ if( comp[i].empty() ){
+ Trace("sets-rewrite-debug") << "...return trivial set (no components)." << std::endl;
+ if( pol ){
+ return Node::null();
+ }else{
+ return empSet;
+ }
+ }else{
+ curr = comp[i][0];
+ for( unsigned j=1; j<comp[i].size(); j++ ){
+ curr = NodeManager::currentNM()->mkNode( pol ? kind::INTERSECTION : kind::UNION, curr, comp[i][j] );
+ }
+ }
+ }else if( i==1 ){
+ if( !comp[i].empty() ){
+ Assert( pol );
+ Node rem = comp[i][0];
+ for( unsigned j=1; j<comp[i].size(); j++ ){
+ rem = NodeManager::currentNM()->mkNode( kind::UNION, rem, comp[i][j] );
+ }
+ curr = NodeManager::currentNM()->mkNode( kind::SETMINUS, curr, rem );
+ }
+ }
+ }
+ Trace("sets-rewrite-debug") << "...return " << curr << std::endl;
+ return curr;
+ }else{
+ if( pol ){
+ Trace("sets-rewrite-debug") << "...return empty set." << std::endl;
+ return NodeManager::currentNM()->mkConst(EmptySet(NodeManager::currentNM()->toType(s.getType())));
+ }else{
+ Trace("sets-rewrite-debug") << "...return complete set." << std::endl;
+ return Node::null();
+ }
+ }
+ }
+}
+
+bool TheorySetsRewriter::collectSetComponents( Node n, std::map< Node, bool >& c, bool pol ) {
+ std::map< Node, bool >::iterator itc = c.find( n );
+ if( itc!=c.end() ){
+ if( itc->second!=pol ){
+ return false;
+ }
+ }else{
+ if( ( pol && ( n.getKind()==kind::INTERSECTION || n.getKind()==kind::SETMINUS ) ) || ( !pol && n.getKind()==kind::UNION ) ){
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ bool newPol = ( i==1 && n.getKind()==kind::SETMINUS ) ? !pol : pol;
+ if( !collectSetComponents( n[i], c, newPol ) ){
+ return false;
+ }
+ }
+ }else{
+ c[n] = pol;
+ }
+ }
+ return true;
+}
+
}/* CVC4::theory::sets namespace */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
diff --git a/src/theory/sets/theory_sets_rewriter.h b/src/theory/sets/theory_sets_rewriter.h
index 58ee8bfb0..97c89520a 100644
--- a/src/theory/sets/theory_sets_rewriter.h
+++ b/src/theory/sets/theory_sets_rewriter.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_sets_rewriter.h
** \verbatim
- ** Original author: Kshitij Bansal
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Kshitij Bansal, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Sets theory rewriter.
**
@@ -26,6 +26,10 @@ namespace theory {
namespace sets {
class TheorySetsRewriter {
+private:
+ static bool collectSetComponents( Node n, std::map< Node, bool >& c, bool pol );
+ static Node rewriteSet( Node s, std::map< Node, bool >& ca, Node empSet );
+ static Node rewriteSet( Node s );
public:
/**
diff --git a/src/theory/sets/theory_sets_type_enumerator.h b/src/theory/sets/theory_sets_type_enumerator.h
index bb0e1794c..40863b0f2 100644
--- a/src/theory/sets/theory_sets_type_enumerator.h
+++ b/src/theory/sets/theory_sets_type_enumerator.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_sets_type_enumerator.h
** \verbatim
- ** Original author: Kshitij Bansal
- ** Major contributors: none
- ** Minor contributors (to current version): Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Kshitij Bansal, Morgan Deters, Andrew Reynolds
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/sets/theory_sets_type_rules.h b/src/theory/sets/theory_sets_type_rules.h
index fdcb094fc..92d6c9b6d 100644
--- a/src/theory/sets/theory_sets_type_rules.h
+++ b/src/theory/sets/theory_sets_type_rules.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_sets_type_rules.h
** \verbatim
- ** Original author: Kshitij Bansal
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Kshitij Bansal, Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Sets theory type rules.
**
@@ -136,6 +136,25 @@ struct EmptySetTypeRule {
}
};/* struct EmptySetTypeRule */
+struct CardTypeRule {
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
+ throw (TypeCheckingExceptionPrivate, AssertionException) {
+ Assert(n.getKind() == kind::CARD);
+ TypeNode setType = n[0].getType(check);
+ if( check ) {
+ if(!setType.isSet()) {
+ throw TypeCheckingExceptionPrivate(n, "cardinality operates on a set, non-set object found");
+ }
+ }
+ return nodeManager->integerType();
+ }
+
+ inline static bool computeIsConst(NodeManager* nodeManager, TNode n) {
+ Assert(n.getKind() == kind::CARD);
+ return false;
+ }
+};/* struct CardTypeRule */
+
struct InsertTypeRule {
inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
throw (TypeCheckingExceptionPrivate, AssertionException) {
@@ -256,7 +275,6 @@ struct RelTransClosureTypeRule {
}
};/* struct RelTransClosureTypeRule */
-
struct SetsProperties {
inline static Cardinality computeCardinality(TypeNode type) {
Assert(type.getKind() == kind::SET_TYPE);
diff --git a/src/theory/shared_terms_database.cpp b/src/theory/shared_terms_database.cpp
index 89cba3ae4..0dc6cc7a1 100644
--- a/src/theory/shared_terms_database.cpp
+++ b/src/theory/shared_terms_database.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file shared_terms_database.cpp
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): Andrew Reynolds, Clark Barrett
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Morgan Deters, Clark Barrett
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** [[ Add lengthier description here ]]
** \todo document this file
@@ -122,7 +122,7 @@ Theory::Set SharedTermsDatabase::getNotifiedTheories(TNode term) const {
bool SharedTermsDatabase::propagateSharedEquality(TheoryId theory, TNode a, TNode b, bool value)
{
- Debug("shared-terms-database") << "SharedTermsDatabase::newEquality(" << theory << a << "," << b << ", " << (value ? "true" : "false") << ")" << endl;
+ Debug("shared-terms-database") << "SharedTermsDatabase::newEquality(" << theory << "," << a << "," << b << ", " << (value ? "true" : "false") << ")" << endl;
if (d_inConflict) {
return false;
diff --git a/src/theory/shared_terms_database.h b/src/theory/shared_terms_database.h
index c15336e29..c108122ef 100644
--- a/src/theory/shared_terms_database.h
+++ b/src/theory/shared_terms_database.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file shared_terms_database.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): Tim King, Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Morgan Deters, Andrew Reynolds
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** [[ Add lengthier description here ]]
** \todo document this file
diff --git a/src/theory/sort_inference.cpp b/src/theory/sort_inference.cpp
index 060584fcf..1f8ec7ee4 100644
--- a/src/theory/sort_inference.cpp
+++ b/src/theory/sort_inference.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file sort_inference.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): Kshitij Bansal
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Sort inference module
**
@@ -118,10 +118,11 @@ void SortInference::simplify( std::vector< Node >& assertions, bool doSortInfere
if( doSortInference ){
Trace("sort-inference-proc") << "Calculating sort inference..." << std::endl;
//process all assertions
+ std::map< Node, int > visited;
for( unsigned i=0; i<assertions.size(); i++ ){
Trace("sort-inference-debug") << "Process " << assertions[i] << std::endl;
std::map< Node, Node > var_bound;
- process( assertions[i], var_bound );
+ process( assertions[i], var_bound, visited );
}
Trace("sort-inference-proc") << "...done" << std::endl;
for( std::map< Node, int >::iterator it = d_op_return_types.begin(); it != d_op_return_types.end(); ++it ){
@@ -155,10 +156,11 @@ void SortInference::simplify( std::vector< Node >& assertions, bool doSortInfere
bool rewritten = false;
//determine monotonicity of sorts
Trace("sort-inference-proc") << "Calculating monotonicty for subsorts..." << std::endl;
+ std::map< Node, std::map< int, bool > > visited;
for( unsigned i=0; i<assertions.size(); i++ ){
Trace("sort-inference-debug") << "Process monotonicity for " << assertions[i] << std::endl;
std::map< Node, Node > var_bound;
- processMonotonic( assertions[i], true, true, var_bound );
+ processMonotonic( assertions[i], true, true, var_bound, visited );
}
Trace("sort-inference-proc") << "...done" << std::endl;
@@ -176,13 +178,16 @@ void SortInference::simplify( std::vector< Node >& assertions, bool doSortInfere
//simplify all assertions by introducing new symbols wherever necessary
Trace("sort-inference-proc") << "Perform simplification..." << std::endl;
+ std::map< Node, std::map< TypeNode, Node > > visited2;
for( unsigned i=0; i<assertions.size(); i++ ){
Node prev = assertions[i];
std::map< Node, Node > var_bound;
- Trace("sort-inference-debug") << "Rewrite " << assertions[i] << std::endl;
- Node curr = simplify( assertions[i], var_bound );
+ Trace("sort-inference-debug") << "Simplify " << assertions[i] << std::endl;
+ TypeNode tnn;
+ Node curr = simplifyNode( assertions[i], var_bound, tnn, visited2 );
Trace("sort-inference-debug") << "Done." << std::endl;
if( curr!=assertions[i] ){
+ Trace("sort-inference-debug") << "Rewrite " << curr << std::endl;
curr = theory::Rewriter::rewrite( curr );
rewritten = true;
Trace("sort-inference-rewrite") << assertions << std::endl;
@@ -196,9 +201,17 @@ void SortInference::simplify( std::vector< Node >& assertions, bool doSortInfere
for( std::map< TypeNode, std::map< Node, Node > >::iterator it = d_const_map.begin(); it != d_const_map.end(); ++it ){
std::vector< Node > consts;
for( std::map< Node, Node >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
+ Assert( it2->first.isConst() );
consts.push_back( it2->second );
}
- //TODO: add lemma enforcing introduced constants to be distinct
+ //add lemma enforcing introduced constants to be distinct
+ if( consts.size()>1 ){
+ Node distinct_const = NodeManager::currentNM()->mkNode( kind::DISTINCT, consts );
+ Trace("sort-inference-rewrite") << "Add the constant distinctness lemma: " << std::endl;
+ Trace("sort-inference-rewrite") << " " << distinct_const << std::endl;
+ assertions.push_back( distinct_const );
+ rewritten = true;
+ }
}
//enforce constraints based on monotonicity
@@ -242,43 +255,15 @@ void SortInference::simplify( std::vector< Node >& assertions, bool doSortInfere
reset();
Trace("sort-inference-debug") << "Finished sort inference, rewritten = " << rewritten << std::endl;
}
- /*
- else if( !options::ufssSymBreak() ){
- //just add the unit lemmas between constants
- std::map< TypeNode, std::map< int, Node > > constants;
- for( std::map< Node, int >::iterator it = d_op_return_types.begin(); it != d_op_return_types.end(); ++it ){
- int rt = d_type_union_find.getRepresentative( it->second );
- if( d_op_arg_types[ it->first ].empty() ){
- TypeNode tn = it->first.getType();
- if( constants[ tn ].find( rt )==constants[ tn ].end() ){
- constants[ tn ][ rt ] = it->first;
- }
- }
- }
- //add unit lemmas for each constant
- for( std::map< TypeNode, std::map< int, Node > >::iterator it = constants.begin(); it != constants.end(); ++it ){
- Node first_const;
- for( std::map< int, Node >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
- if( first_const.isNull() ){
- first_const = it2->second;
- }else{
- Node eq = first_const.eqNode( it2->second );
- //eq = Rewriter::rewrite( eq );
- Trace("sort-inference-lemma") << "Sort inference lemma : " << eq << std::endl;
- assertions.push_back( eq );
- }
- }
- }
- }
- */
initialSortCount = sortCount;
}
if( doMonotonicyInference ){
+ std::map< Node, std::map< int, bool > > visited;
Trace("sort-inference-proc") << "Calculating monotonicty for types..." << std::endl;
for( unsigned i=0; i<assertions.size(); i++ ){
Trace("sort-inference-debug") << "Process type monotonicity for " << assertions[i] << std::endl;
std::map< Node, Node > var_bound;
- processMonotonic( assertions[i], true, true, var_bound, true );
+ processMonotonic( assertions[i], true, true, var_bound, visited, true );
}
Trace("sort-inference-proc") << "...done" << std::endl;
}
@@ -338,174 +323,185 @@ int SortInference::getIdForType( TypeNode tn ){
}
}
-int SortInference::process( Node n, std::map< Node, Node >& var_bound ){
- //add to variable bindings
- if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
- if( d_var_types.find( n )!=d_var_types.end() ){
- return getIdForType( n.getType() );
- }else{
- for( size_t i=0; i<n[0].getNumChildren(); i++ ){
- //apply sort inference to quantified variables
- d_var_types[n][ n[0][i] ] = sortCount;
- sortCount++;
+int SortInference::process( Node n, std::map< Node, Node >& var_bound, std::map< Node, int >& visited ){
+ std::map< Node, int >::iterator itv = visited.find( n );
+ if( itv!=visited.end() ){
+ return itv->second;
+ }else{
+ //add to variable bindings
+ bool use_new_visited = false;
+ std::map< Node, int > new_visited;
+ if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
+ if( d_var_types.find( n )!=d_var_types.end() ){
+ return getIdForType( n.getType() );
+ }else{
+ for( size_t i=0; i<n[0].getNumChildren(); i++ ){
+ //apply sort inference to quantified variables
+ d_var_types[n][ n[0][i] ] = sortCount;
+ sortCount++;
- //type of the quantified variable must be the same
- var_bound[ n[0][i] ] = n;
+ //type of the quantified variable must be the same
+ var_bound[ n[0][i] ] = n;
+ }
}
+ use_new_visited = true;
}
- }
- //process children
- std::vector< Node > children;
- std::vector< int > child_types;
- for( size_t i=0; i<n.getNumChildren(); i++ ){
- bool processChild = true;
- if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
- processChild = options::userPatternsQuant()==theory::quantifiers::USER_PAT_MODE_IGNORE ? i==1 : i>=1;
- }
- if( processChild ){
- children.push_back( n[i] );
- child_types.push_back( process( n[i], var_bound ) );
+ //process children
+ std::vector< Node > children;
+ std::vector< int > child_types;
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ bool processChild = true;
+ if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
+ processChild = options::userPatternsQuant()==theory::quantifiers::USER_PAT_MODE_IGNORE ? i==1 : i>=1;
+ }
+ if( processChild ){
+ children.push_back( n[i] );
+ child_types.push_back( process( n[i], var_bound, use_new_visited ? new_visited : visited ) );
+ }
}
- }
- //remove from variable bindings
- if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
- //erase from variable bound
- for( size_t i=0; i<n[0].getNumChildren(); i++ ){
- var_bound.erase( n[0][i] );
- }
- }
- Trace("sort-inference-debug") << "...Process " << n << std::endl;
-
- int retType;
- if( n.getKind()==kind::EQUAL ){
- Trace("sort-inference-debug") << "For equality " << n << ", set equal types from : " << n[0].getType() << " " << n[1].getType() << std::endl;
- //if original types are mixed (e.g. Int/Real), don't commit type equality in either direction
- if( n[0].getType()!=n[1].getType() ){
- //for now, assume the original types
- for( unsigned i=0; i<2; i++ ){
- int ct = getIdForType( n[i].getType() );
- setEqual( child_types[i], ct );
+ //remove from variable bindings
+ if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
+ //erase from variable bound
+ for( size_t i=0; i<n[0].getNumChildren(); i++ ){
+ var_bound.erase( n[0][i] );
}
- }else{
- //we only require that the left and right hand side must be equal
- setEqual( child_types[0], child_types[1] );
}
- //int eqType = getIdForType( n[0].getType() );
- //setEqual( child_types[0], eqType );
- //setEqual( child_types[1], eqType );
- retType = getIdForType( n.getType() );
- }else if( n.getKind()==kind::APPLY_UF ){
- Node op = n.getOperator();
- TypeNode tn_op = op.getType();
- if( d_op_return_types.find( op )==d_op_return_types.end() ){
- if( n.getType().isBoolean() ){
- //use booleans
- d_op_return_types[op] = getIdForType( n.getType() );
+ Trace("sort-inference-debug") << "...Process " << n << std::endl;
+
+ int retType;
+ if( n.getKind()==kind::EQUAL ){
+ Trace("sort-inference-debug") << "For equality " << n << ", set equal types from : " << n[0].getType() << " " << n[1].getType() << std::endl;
+ //if original types are mixed (e.g. Int/Real), don't commit type equality in either direction
+ if( n[0].getType()!=n[1].getType() ){
+ //for now, assume the original types
+ for( unsigned i=0; i<2; i++ ){
+ int ct = getIdForType( n[i].getType() );
+ setEqual( child_types[i], ct );
+ }
}else{
- //assign arbitrary sort for return type
- d_op_return_types[op] = sortCount;
- sortCount++;
+ //we only require that the left and right hand side must be equal
+ setEqual( child_types[0], child_types[1] );
}
- //d_type_eq_class[sortCount].push_back( op );
- //assign arbitrary sort for argument types
- for( size_t i=0; i<n.getNumChildren(); i++ ){
- d_op_arg_types[op].push_back( sortCount );
- sortCount++;
- }
- }
- for( size_t i=0; i<n.getNumChildren(); i++ ){
- //the argument of the operator must match the return type of the subterm
- if( n[i].getType()!=tn_op[i] ){
- //if type mismatch, assume original types
- Trace("sort-inference-debug") << "Argument " << i << " of " << op << " " << n[i] << " has type " << n[i].getType();
- Trace("sort-inference-debug") << ", while operator arg has type " << tn_op[i] << std::endl;
- int ct1 = getIdForType( n[i].getType() );
- setEqual( child_types[i], ct1 );
- int ct2 = getIdForType( tn_op[i] );
- setEqual( d_op_arg_types[op][i], ct2 );
- }else{
- setEqual( child_types[i], d_op_arg_types[op][i] );
+ d_equality_types[n] = child_types[0];
+ retType = getIdForType( n.getType() );
+ }else if( n.getKind()==kind::APPLY_UF ){
+ Node op = n.getOperator();
+ TypeNode tn_op = op.getType();
+ if( d_op_return_types.find( op )==d_op_return_types.end() ){
+ if( n.getType().isBoolean() ){
+ //use booleans
+ d_op_return_types[op] = getIdForType( n.getType() );
+ }else{
+ //assign arbitrary sort for return type
+ d_op_return_types[op] = sortCount;
+ sortCount++;
+ }
+ //d_type_eq_class[sortCount].push_back( op );
+ //assign arbitrary sort for argument types
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ d_op_arg_types[op].push_back( sortCount );
+ sortCount++;
+ }
}
- }
- //return type is the return type
- retType = d_op_return_types[op];
- }else{
- std::map< Node, Node >::iterator it = var_bound.find( n );
- if( it!=var_bound.end() ){
- Trace("sort-inference-debug") << n << " is a bound variable." << std::endl;
- //the return type was specified while binding
- retType = d_var_types[it->second][n];
- }else if( n.getKind() == kind::VARIABLE || n.getKind()==kind::SKOLEM ){
- Trace("sort-inference-debug") << n << " is a variable." << std::endl;
- if( d_op_return_types.find( n )==d_op_return_types.end() ){
- //assign arbitrary sort
- d_op_return_types[n] = sortCount;
- sortCount++;
- //d_type_eq_class[sortCount].push_back( n );
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ //the argument of the operator must match the return type of the subterm
+ if( n[i].getType()!=tn_op[i] ){
+ //if type mismatch, assume original types
+ Trace("sort-inference-debug") << "Argument " << i << " of " << op << " " << n[i] << " has type " << n[i].getType();
+ Trace("sort-inference-debug") << ", while operator arg has type " << tn_op[i] << std::endl;
+ int ct1 = getIdForType( n[i].getType() );
+ setEqual( child_types[i], ct1 );
+ int ct2 = getIdForType( tn_op[i] );
+ setEqual( d_op_arg_types[op][i], ct2 );
+ }else{
+ setEqual( child_types[i], d_op_arg_types[op][i] );
+ }
}
- retType = d_op_return_types[n];
- //}else if( n.isConst() ){
- // Trace("sort-inference-debug") << n << " is a constant." << std::endl;
- //can be any type we want
- // retType = sortCount;
- // sortCount++;
+ //return type is the return type
+ retType = d_op_return_types[op];
}else{
- Trace("sort-inference-debug") << n << " is a interpreted symbol." << std::endl;
- //it is an interpretted term
- for( size_t i=0; i<children.size(); i++ ){
- Trace("sort-inference-debug") << children[i] << " forced to have " << children[i].getType() << std::endl;
- //must enforce the actual type of the operator on the children
- int ct = getIdForType( children[i].getType() );
- setEqual( child_types[i], ct );
+ std::map< Node, Node >::iterator it = var_bound.find( n );
+ if( it!=var_bound.end() ){
+ Trace("sort-inference-debug") << n << " is a bound variable." << std::endl;
+ //the return type was specified while binding
+ retType = d_var_types[it->second][n];
+ }else if( n.getKind() == kind::VARIABLE || n.getKind()==kind::SKOLEM ){
+ Trace("sort-inference-debug") << n << " is a variable." << std::endl;
+ if( d_op_return_types.find( n )==d_op_return_types.end() ){
+ //assign arbitrary sort
+ d_op_return_types[n] = sortCount;
+ sortCount++;
+ //d_type_eq_class[sortCount].push_back( n );
+ }
+ retType = d_op_return_types[n];
+ }else if( n.isConst() ){
+ Trace("sort-inference-debug") << n << " is a constant." << std::endl;
+ //can be any type we want
+ retType = sortCount;
+ sortCount++;
+ }else{
+ Trace("sort-inference-debug") << n << " is a interpreted symbol." << std::endl;
+ //it is an interpreted term
+ for( size_t i=0; i<children.size(); i++ ){
+ Trace("sort-inference-debug") << children[i] << " forced to have " << children[i].getType() << std::endl;
+ //must enforce the actual type of the operator on the children
+ int ct = getIdForType( children[i].getType() );
+ setEqual( child_types[i], ct );
+ }
+ //return type must be the actual return type
+ retType = getIdForType( n.getType() );
}
- //return type must be the actual return type
- retType = getIdForType( n.getType() );
}
+ Trace("sort-inference-debug") << "...Type( " << n << " ) = ";
+ printSort("sort-inference-debug", retType );
+ Trace("sort-inference-debug") << std::endl;
+ visited[n] = retType;
+ return retType;
}
- Trace("sort-inference-debug") << "...Type( " << n << " ) = ";
- printSort("sort-inference-debug", retType );
- Trace("sort-inference-debug") << std::endl;
- return retType;
}
-void SortInference::processMonotonic( Node n, bool pol, bool hasPol, std::map< Node, Node >& var_bound, bool typeMode ) {
- Trace("sort-inference-debug") << "...Process monotonic " << pol << " " << hasPol << " " << n << std::endl;
- if( n.getKind()==kind::FORALL ){
- //only consider variables universally if it is possible this quantified formula is asserted positively
- if( !hasPol || pol ){
- for( unsigned i=0; i<n[0].getNumChildren(); i++ ){
- var_bound[n[0][i]] = n;
+void SortInference::processMonotonic( Node n, bool pol, bool hasPol, std::map< Node, Node >& var_bound, std::map< Node, std::map< int, bool > >& visited, bool typeMode ) {
+ int pindex = hasPol ? ( pol ? 1 : -1 ) : 0;
+ if( visited[n].find( pindex )==visited[n].end() ){
+ visited[n][pindex] = true;
+ Trace("sort-inference-debug") << "...Process monotonic " << pol << " " << hasPol << " " << n << std::endl;
+ if( n.getKind()==kind::FORALL ){
+ //only consider variables universally if it is possible this quantified formula is asserted positively
+ if( !hasPol || pol ){
+ for( unsigned i=0; i<n[0].getNumChildren(); i++ ){
+ var_bound[n[0][i]] = n;
+ }
}
- }
- processMonotonic( n[1], pol, hasPol, var_bound, typeMode );
- if( !hasPol || pol ){
- for( unsigned i=0; i<n[0].getNumChildren(); i++ ){
- var_bound.erase( n[0][i] );
+ processMonotonic( n[1], pol, hasPol, var_bound, visited, typeMode );
+ if( !hasPol || pol ){
+ for( unsigned i=0; i<n[0].getNumChildren(); i++ ){
+ var_bound.erase( n[0][i] );
+ }
}
- }
- return;
- }else if( n.getKind()==kind::EQUAL ){
- if( !hasPol || pol ){
- for( unsigned i=0; i<2; i++ ){
- if( var_bound.find( n[i] )!=var_bound.end() ){
- if( !typeMode ){
- int sid = getSortId( var_bound[n[i]], n[i] );
- d_non_monotonic_sorts[sid] = true;
- }else{
- d_non_monotonic_sorts_orig[n[i].getType()] = true;
+ return;
+ }else if( n.getKind()==kind::EQUAL ){
+ if( !hasPol || pol ){
+ for( unsigned i=0; i<2; i++ ){
+ if( var_bound.find( n[i] )!=var_bound.end() ){
+ if( !typeMode ){
+ int sid = getSortId( var_bound[n[i]], n[i] );
+ d_non_monotonic_sorts[sid] = true;
+ }else{
+ d_non_monotonic_sorts_orig[n[i].getType()] = true;
+ }
+ break;
}
- break;
}
}
}
- }
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- bool npol;
- bool nhasPol;
- theory::QuantPhaseReq::getPolarity( n, i, hasPol, pol, nhasPol, npol );
- processMonotonic( n[i], npol, nhasPol, var_bound, typeMode );
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ bool npol;
+ bool nhasPol;
+ theory::QuantPhaseReq::getPolarity( n, i, hasPol, pol, nhasPol, npol );
+ processMonotonic( n[i], npol, nhasPol, var_bound, visited, typeMode );
+ }
}
}
@@ -544,7 +540,7 @@ TypeNode SortInference::getTypeForId( int t ){
}
Node SortInference::getNewSymbol( Node old, TypeNode tn ){
- if( tn==old.getType() ){
+ if( tn.isNull() || tn==old.getType() ){
return old;
}else if( old.isConst() ){
//must make constant of type tn
@@ -565,128 +561,139 @@ Node SortInference::getNewSymbol( Node old, TypeNode tn ){
}
}
-Node SortInference::simplify( Node n, std::map< Node, Node >& var_bound ){
- Trace("sort-inference-debug2") << "Simplify " << n << std::endl;
- std::vector< Node > children;
- if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
- //recreate based on types of variables
- std::vector< Node > new_children;
- for( size_t i=0; i<n[0].getNumChildren(); i++ ){
- TypeNode tn = getOrCreateTypeForId( d_var_types[n][ n[0][i] ], n[0][i].getType() );
- Node v = getNewSymbol( n[0][i], tn );
- Trace("sort-inference-debug2") << "Map variable " << n[0][i] << " to " << v << std::endl;
- new_children.push_back( v );
- var_bound[ n[0][i] ] = v;
+Node SortInference::simplifyNode( Node n, std::map< Node, Node >& var_bound, TypeNode tnn, std::map< Node, std::map< TypeNode, Node > >& visited ){
+ std::map< TypeNode, Node >::iterator itv = visited[n].find( tnn );
+ if( itv!=visited[n].end() ){
+ return itv->second;
+ }else{
+ Trace("sort-inference-debug2") << "Simplify " << n << ", type context=" << tnn << std::endl;
+ std::vector< Node > children;
+ std::map< Node, std::map< TypeNode, Node > > new_visited;
+ bool use_new_visited = false;
+ if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
+ //recreate based on types of variables
+ std::vector< Node > new_children;
+ for( size_t i=0; i<n[0].getNumChildren(); i++ ){
+ TypeNode tn = getOrCreateTypeForId( d_var_types[n][ n[0][i] ], n[0][i].getType() );
+ Node v = getNewSymbol( n[0][i], tn );
+ Trace("sort-inference-debug2") << "Map variable " << n[0][i] << " to " << v << std::endl;
+ new_children.push_back( v );
+ var_bound[ n[0][i] ] = v;
+ }
+ children.push_back( NodeManager::currentNM()->mkNode( n[0].getKind(), new_children ) );
+ use_new_visited = true;
}
- children.push_back( NodeManager::currentNM()->mkNode( n[0].getKind(), new_children ) );
- }
- //process children
- if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){
- children.push_back( n.getOperator() );
- }
- bool childChanged = false;
- for( size_t i=0; i<n.getNumChildren(); i++ ){
- bool processChild = true;
- if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
- processChild = options::userPatternsQuant()==theory::quantifiers::USER_PAT_MODE_IGNORE ? i==1 : i>=1;
+ //process children
+ if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){
+ children.push_back( n.getOperator() );
}
- if( processChild ){
- Node nc = simplify( n[i], var_bound );
- Trace("sort-inference-debug2") << "Simplify " << i << " " << n[i] << " returned " << nc << std::endl;
- children.push_back( nc );
- childChanged = childChanged || nc!=n[i];
+ Node op;
+ if( n.hasOperator() ){
+ op = n.getOperator();
}
- }
-
- //remove from variable bindings
- if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
- //erase from variable bound
- for( size_t i=0; i<n[0].getNumChildren(); i++ ){
- Trace("sort-inference-debug2") << "Remove bound for " << n[0][i] << std::endl;
- var_bound.erase( n[0][i] );
+ bool childChanged = false;
+ TypeNode tnnc;
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ bool processChild = true;
+ if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
+ processChild = options::userPatternsQuant()==theory::quantifiers::USER_PAT_MODE_IGNORE ? i==1 : i>=1;
+ }
+ if( processChild ){
+ if( n.getKind()==kind::APPLY_UF ){
+ Assert( d_op_arg_types.find( op )!=d_op_arg_types.end() );
+ tnnc = getOrCreateTypeForId( d_op_arg_types[op][i], n[i].getType() );
+ Assert( !tnnc.isNull() );
+ }else if( n.getKind()==kind::EQUAL && i==0 ){
+ Assert( d_equality_types.find( n )!=d_equality_types.end() );
+ tnnc = getOrCreateTypeForId( d_equality_types[n], n[0].getType() );
+ Assert( !tnnc.isNull() );
+ }
+ Node nc = simplifyNode( n[i], var_bound, tnnc, use_new_visited ? new_visited : visited );
+ Trace("sort-inference-debug2") << "Simplify " << i << " " << n[i] << " returned " << nc << std::endl;
+ children.push_back( nc );
+ childChanged = childChanged || nc!=n[i];
+ }
}
- return NodeManager::currentNM()->mkNode( n.getKind(), children );
- }else if( n.getKind()==kind::EQUAL ){
- TypeNode tn1 = children[0].getType();
- TypeNode tn2 = children[1].getType();
- if( !tn1.isSubtypeOf( tn2 ) && !tn2.isSubtypeOf( tn1 ) ){
- if( children[0].isConst() ){
- children[0] = getNewSymbol( children[0], children[1].getType() );
- }else if( children[1].isConst() ){
- children[1] = getNewSymbol( children[1], children[0].getType() );
- }else{
+
+ //remove from variable bindings
+ Node ret;
+ if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
+ //erase from variable bound
+ for( size_t i=0; i<n[0].getNumChildren(); i++ ){
+ Trace("sort-inference-debug2") << "Remove bound for " << n[0][i] << std::endl;
+ var_bound.erase( n[0][i] );
+ }
+ ret = NodeManager::currentNM()->mkNode( n.getKind(), children );
+ }else if( n.getKind()==kind::EQUAL ){
+ TypeNode tn1 = children[0].getType();
+ TypeNode tn2 = children[1].getType();
+ if( !tn1.isSubtypeOf( tn2 ) && !tn2.isSubtypeOf( tn1 ) ){
Trace("sort-inference-warn") << "Sort inference created bad equality: " << children[0] << " = " << children[1] << std::endl;
Trace("sort-inference-warn") << " Types : " << children[0].getType() << " " << children[1].getType() << std::endl;
Assert( false );
}
- }
- return NodeManager::currentNM()->mkNode( kind::EQUAL, children );
- }else if( n.getKind()==kind::APPLY_UF ){
- Node op = n.getOperator();
- if( d_symbol_map.find( op )==d_symbol_map.end() ){
- //make the new operator if necessary
- bool opChanged = false;
- std::vector< TypeNode > argTypes;
- for( size_t i=0; i<n.getNumChildren(); i++ ){
- TypeNode tn = getOrCreateTypeForId( d_op_arg_types[op][i], n[i].getType() );
- argTypes.push_back( tn );
- if( tn!=n[i].getType() ){
+ ret = NodeManager::currentNM()->mkNode( kind::EQUAL, children );
+ }else if( n.getKind()==kind::APPLY_UF ){
+ if( d_symbol_map.find( op )==d_symbol_map.end() ){
+ //make the new operator if necessary
+ bool opChanged = false;
+ std::vector< TypeNode > argTypes;
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ TypeNode tn = getOrCreateTypeForId( d_op_arg_types[op][i], n[i].getType() );
+ argTypes.push_back( tn );
+ if( tn!=n[i].getType() ){
+ opChanged = true;
+ }
+ }
+ TypeNode retType = getOrCreateTypeForId( d_op_return_types[op], n.getType() );
+ if( retType!=n.getType() ){
opChanged = true;
}
- }
- TypeNode retType = getOrCreateTypeForId( d_op_return_types[op], n.getType() );
- if( retType!=n.getType() ){
- opChanged = true;
- }
- if( opChanged ){
- std::stringstream ss;
- ss << "io_" << op;
- TypeNode typ = NodeManager::currentNM()->mkFunctionType( argTypes, retType );
- d_symbol_map[op] = NodeManager::currentNM()->mkSkolem( ss.str(), typ, "op created during sort inference" );
- Trace("setp-model") << "Function " << op << " is replaced with " << d_symbol_map[op] << std::endl;
- d_model_replace_f[op] = d_symbol_map[op];
- }else{
- d_symbol_map[op] = op;
- }
- }
- children[0] = d_symbol_map[op];
- //make sure all children have been taken care of
- for( size_t i=0; i<n.getNumChildren(); i++ ){
- TypeNode tn = children[i+1].getType();
- TypeNode tna = getTypeForId( d_op_arg_types[op][i] );
- if( tn!=tna ){
- if( n[i].isConst() ){
- children[i+1] = getNewSymbol( n[i], tna );
+ if( opChanged ){
+ std::stringstream ss;
+ ss << "io_" << op;
+ TypeNode typ = NodeManager::currentNM()->mkFunctionType( argTypes, retType );
+ d_symbol_map[op] = NodeManager::currentNM()->mkSkolem( ss.str(), typ, "op created during sort inference" );
+ Trace("setp-model") << "Function " << op << " is replaced with " << d_symbol_map[op] << std::endl;
+ d_model_replace_f[op] = d_symbol_map[op];
}else{
+ d_symbol_map[op] = op;
+ }
+ }
+ children[0] = d_symbol_map[op];
+ //make sure all children have been taken care of
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ TypeNode tn = children[i+1].getType();
+ TypeNode tna = getTypeForId( d_op_arg_types[op][i] );
+ if( tn!=tna ){
Trace("sort-inference-warn") << "Sort inference created bad child: " << n << " " << n[i] << " " << tn << " " << tna << std::endl;
Assert( false );
}
}
- }
- return NodeManager::currentNM()->mkNode( kind::APPLY_UF, children );
- }else{
- std::map< Node, Node >::iterator it = var_bound.find( n );
- if( it!=var_bound.end() ){
- return it->second;
- }else if( n.getKind() == kind::VARIABLE || n.getKind() == kind::SKOLEM ){
- if( d_symbol_map.find( n )==d_symbol_map.end() ){
- TypeNode tn = getOrCreateTypeForId( d_op_return_types[n], n.getType() );
- d_symbol_map[n] = getNewSymbol( n, tn );
- }
- return d_symbol_map[n];
- }else if( n.isConst() ){
- //just return n, we will fix at higher scope
- return n;
+ ret = NodeManager::currentNM()->mkNode( kind::APPLY_UF, children );
}else{
- if( childChanged ){
- return NodeManager::currentNM()->mkNode( n.getKind(), children );
+ std::map< Node, Node >::iterator it = var_bound.find( n );
+ if( it!=var_bound.end() ){
+ ret = it->second;
+ }else if( n.getKind() == kind::VARIABLE || n.getKind() == kind::SKOLEM ){
+ if( d_symbol_map.find( n )==d_symbol_map.end() ){
+ TypeNode tn = getOrCreateTypeForId( d_op_return_types[n], n.getType() );
+ d_symbol_map[n] = getNewSymbol( n, tn );
+ }
+ ret = d_symbol_map[n];
+ }else if( n.isConst() ){
+ //type is determined by context
+ ret = getNewSymbol( n, tnn );
+ }else if( childChanged ){
+ ret = NodeManager::currentNM()->mkNode( n.getKind(), children );
}else{
- return n;
+ ret = n;
}
}
+ visited[n][tnn] = ret;
+ return ret;
}
-
}
Node SortInference::mkInjection( TypeNode tn1, TypeNode tn2 ) {
@@ -728,7 +735,8 @@ void SortInference::setSkolemVar( Node f, Node v, Node sk ){
if( isWellSortedFormula( f ) && d_var_types.find( f )==d_var_types.end() ){
//calculate the sort for variables if not done so already
std::map< Node, Node > var_bound;
- process( f, var_bound );
+ std::map< Node, int > visited;
+ process( f, var_bound, visited );
}
d_op_return_types[sk] = getSortId( f, v );
Trace("sort-inference-temp") << "Set skolem sort id for " << sk << " to " << d_op_return_types[sk] << std::endl;
diff --git a/src/theory/sort_inference.h b/src/theory/sort_inference.h
index f926776de..ae3342f92 100644
--- a/src/theory/sort_inference.h
+++ b/src/theory/sort_inference.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file sort_inference.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Pre-process step for performing sort inference
**/
@@ -61,6 +61,7 @@ private:
//for apply uf operators
std::map< Node, int > d_op_return_types;
std::map< Node, std::vector< int > > d_op_arg_types;
+ std::map< Node, int > d_equality_types;
//for bound variables
std::map< Node, std::map< Node, int > > d_var_types;
//get representative
@@ -68,10 +69,10 @@ private:
int getIdForType( TypeNode tn );
void printSort( const char* c, int t );
//process
- int process( Node n, std::map< Node, Node >& var_bound );
+ int process( Node n, std::map< Node, Node >& var_bound, std::map< Node, int >& visited );
//for monotonicity inference
private:
- void processMonotonic( Node n, bool pol, bool hasPol, std::map< Node, Node >& var_bound, bool typeMode = false );
+ void processMonotonic( Node n, bool pol, bool hasPol, std::map< Node, Node >& var_bound, std::map< Node, std::map< int, bool > >& visited, bool typeMode = false );
//for rewriting
private:
@@ -84,7 +85,7 @@ private:
TypeNode getTypeForId( int t );
Node getNewSymbol( Node old, TypeNode tn );
//simplify
- Node simplify( Node n, std::map< Node, Node >& var_bound );
+ Node simplifyNode( Node n, std::map< Node, Node >& var_bound, TypeNode tnn, std::map< Node, std::map< TypeNode, Node > >& visited );
//make injection
Node mkInjection( TypeNode tn1, TypeNode tn2 );
//reset
diff --git a/src/theory/strings/regexp_operation.cpp b/src/theory/strings/regexp_operation.cpp
index 98f03327a..53344dd6c 100644
--- a/src/theory/strings/regexp_operation.cpp
+++ b/src/theory/strings/regexp_operation.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file regexp_operation.cpp
** \verbatim
- ** Original author: Tianyi Liang
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Tianyi Liang, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Symbolic Regular Expresion Operations
**
diff --git a/src/theory/strings/regexp_operation.h b/src/theory/strings/regexp_operation.h
index 012a573c1..c537553f2 100644
--- a/src/theory/strings/regexp_operation.h
+++ b/src/theory/strings/regexp_operation.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file regexp_operation.h
** \verbatim
- ** Original author: Tianyi Liang
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Tianyi Liang, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Symbolic Regular Expresion Operations
**
diff --git a/src/theory/strings/theory_strings.cpp b/src/theory/strings/theory_strings.cpp
index 529e69e82..b3e1925ae 100644
--- a/src/theory/strings/theory_strings.cpp
+++ b/src/theory/strings/theory_strings.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_strings.cpp
** \verbatim
- ** Original author: Tianyi Liang
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): Martin Brain <>, Morgan Deters
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tianyi Liang, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of the theory of strings.
**
@@ -653,7 +653,9 @@ void TheoryStrings::checkReduction( Node atom, int pol, int effort ) {
if( atom.getKind()==kind::STRING_IN_REGEXP ){
if( atom[1].getKind()==kind::REGEXP_RANGE ){
Node eq = d_one.eqNode(NodeManager::currentNM()->mkNode(kind::STRING_LENGTH, atom[0]));
- sendLemma( atom, eq, "RE-Range-Len" );
+ std::vector< Node > exp_vec;
+ exp_vec.push_back( atom );
+ sendInference( d_empty_vec, exp_vec, eq, "RE-Range-Len", true );
}
}else if( atom.getKind()==kind::STRING_STRCTN ){
Node x = atom[0];
@@ -663,7 +665,9 @@ void TheoryStrings::checkReduction( Node atom, int pol, int effort ) {
Node sk1 = mkSkolemCached( x, s, sk_id_ctn_pre, "sc1" );
Node sk2 = mkSkolemCached( x, s, sk_id_ctn_post, "sc2" );
Node eq = Rewriter::rewrite( x.eqNode( mkConcat( sk1, s, sk2 ) ) );
- sendLemma( atom, eq, "POS-CTN" );
+ std::vector< Node > exp_vec;
+ exp_vec.push_back( atom );
+ sendInference( d_empty_vec, exp_vec, eq, "POS-CTN", true );
}else{
// for STRING_SUBSTR,
// STRING_STRIDOF, STRING_ITOS, STRING_U16TOS, STRING_U32TOS, STRING_STOI, STRING_STOU16, STRING_STOU32, STRING_STRREPL
@@ -675,7 +679,7 @@ void TheoryStrings::checkReduction( Node atom, int pol, int effort ) {
nnlem = Rewriter::rewrite( nnlem );
Trace("strings-red-lemma") << "Reduction_" << effort << " lemma : " << nnlem << std::endl;
Trace("strings-red-lemma") << "...from " << atom << std::endl;
- sendLemma( d_true, nnlem, "Reduction" );
+ sendInference( d_empty_vec, nnlem, "Reduction", true );
}
}
}
@@ -950,7 +954,7 @@ void TheoryStrings::checkInit() {
}
}
//infer the equality
- sendInfer( mkAnd( exp ), n.eqNode( nc ), "I_Norm" );
+ sendInference( exp, n.eqNode( nc ), "I_Norm" );
}else{
//update the extf map : only process if neither has been reduced
NodeBoolMap::const_iterator it = d_ext_func_terms.find( n );
@@ -989,7 +993,7 @@ void TheoryStrings::checkInit() {
}
AlwaysAssert( foundNEmpty );
//infer the equality
- sendInfer( mkAnd( exp ), n.eqNode( c[0] ), "I_Norm_S" );
+ sendInference( exp, n.eqNode( c[0] ), "I_Norm_S" );
}
d_congruent.insert( n );
congruent[k]++;
@@ -1141,11 +1145,7 @@ void TheoryStrings::checkExtendedFuncsEval( int effort ) {
}
if( !conc.isNull() ){
Trace("strings-extf") << " resolve extf : " << nr << " -> " << nrc << std::endl;
- if( n.getType().isInteger() || d_extf_exp[n].empty() ){
- sendLemma( mkExplain( d_extf_exp[n] ), conc, effort==0 ? "EXTF" : "EXTF-N" );
- }else{
- sendInfer( mkAnd( d_extf_exp[n] ), conc, effort==0 ? "EXTF" : "EXTF-N" );
- }
+ sendInference( d_extf_exp[n], conc, effort==0 ? "EXTF" : "EXTF-N", n.getType().isInteger() || d_extf_exp[n].empty() );
if( d_conflict ){
Trace("strings-extf-debug") << " conflict, return." << std::endl;
return;
@@ -1158,7 +1158,7 @@ void TheoryStrings::checkExtendedFuncsEval( int effort ) {
Trace("strings-extf-debug") << " decomposable..." << std::endl;
Trace("strings-extf") << " resolve extf : " << nr << " -> " << nrc << ", pol = " << d_extf_pol[n] << std::endl;
for( unsigned i=0; i<nrc.getNumChildren(); i++ ){
- sendInfer( mkAnd( d_extf_exp[n] ), d_extf_pol[n]==-1 ? nrc[i].negate() : nrc[i], effort==0 ? "EXTF_d" : "EXTF_d-N" );
+ sendInference( d_extf_exp[n], d_extf_pol[n]==-1 ? nrc[i].negate() : nrc[i], effort==0 ? "EXTF_d" : "EXTF_d-N" );
}
}else{
to_reduce = nrc;
@@ -1202,13 +1202,13 @@ void TheoryStrings::checkExtfInference( Node n, Node nr, int effort ){
std::vector< Node > children;
children.push_back( nr[0] );
children.push_back( nr[1] );
- Node exp_n = mkAnd( d_extf_exp[n] );
+ //Node exp_n = mkAnd( d_extf_exp[n] );
for( unsigned i=0; i<nr[index].getNumChildren(); i++ ){
children[index] = nr[index][i];
Node conc = NodeManager::currentNM()->mkNode( kind::STRING_STRCTN, children );
//can mark as reduced, since model for n => model for conc
d_ext_func_terms[conc] = false;
- sendInfer( exp_n, n_pol==1 ? conc : conc.negate(), "CTN_Decompose" );
+ sendInference( d_extf_exp[n], n_pol==1 ? conc : conc.negate(), "CTN_Decompose" );
}
}
}else{
@@ -1238,7 +1238,7 @@ void TheoryStrings::checkExtfInference( Node n, Node nr, int effort ){
Node ofrom = d_extf_info[nr[0]].d_ctn_from[opol][i];
Assert( d_extf_exp.find( ofrom )!=d_extf_exp.end() );
exp.insert( exp.end(), d_extf_exp[ofrom].begin(), d_extf_exp[ofrom].end() );
- sendInfer( mkAnd( exp ), conc, "CTN_Trans" );
+ sendInference( exp, conc, "CTN_Trans" );
}
}
}else{
@@ -1417,8 +1417,9 @@ void TheoryStrings::checkFlatForms() {
}else{
Node curr = d_flat_form[a][count];
Node curr_c = d_eqc_to_const[curr];
+ Node ac = a[d_flat_form_index[a][count]];
std::vector< Node > lexp;
- Node lcurr = getLength( curr, lexp );
+ Node lcurr = getLength( ac, lexp );
for( unsigned i=1; i<it->second.size(); i++ ){
b = it->second[i];
if( std::find( inelig.begin(), inelig.end(), b )==inelig.end() ){
@@ -1438,7 +1439,6 @@ void TheoryStrings::checkFlatForms() {
}else{
Node cc = d_flat_form[b][count];
if( cc!=curr ){
- Node ac = a[d_flat_form_index[a][count]];
Node bc = b[d_flat_form_index[b][count]];
inelig.push_back( b );
Assert( !areEqual( curr, cc ) );
@@ -1462,11 +1462,17 @@ void TheoryStrings::checkFlatForms() {
break;
}else{
//if lengths are the same, apply LengthEq
- Node lcc = getLength( cc, lexp );
+ std::vector< Node > lexp2;
+ Node lcc = getLength( bc, lexp2 );
if( areEqual( lcurr, lcc ) ){
Trace("strings-ff-debug") << "Infer " << ac << " == " << bc << " since " << lcurr << " == " << lcc << std::endl;
//exp_n.push_back( getLength( curr, true ).eqNode( getLength( cc, true ) ) );
+ Trace("strings-ff-debug") << "Explanation for " << lcurr << " is ";
+ for( unsigned j=0; j<lexp.size(); j++ ) { Trace("strings-ff-debug") << lexp[j] << std::endl; }
+ Trace("strings-ff-debug") << "Explanation for " << lcc << " is ";
+ for( unsigned j=0; j<lexp2.size(); j++ ) { Trace("strings-ff-debug") << lexp2[j] << std::endl; }
exp.insert( exp.end(), lexp.begin(), lexp.end() );
+ exp.insert( exp.end(), lexp2.begin(), lexp2.end() );
addToExplanation( lcurr, lcc, exp );
conc = ac.eqNode( bc );
inf_type = 1;
@@ -1505,7 +1511,7 @@ void TheoryStrings::checkFlatForms() {
}
}
//if( exp_n.empty() ){
- sendInfer( mkAnd( exp ), conc, inf_type==0? "F_Const" : ( inf_type==1 ? "F_LengthEq" : ( inf_type==2 ? "F_Endpoint" : "F_EndpointEq" ) ) );
+ sendInference( exp, conc, inf_type==0? "F_Const" : ( inf_type==1 ? "F_LengthEq" : ( inf_type==2 ? "F_Endpoint" : "F_EndpointEq" ) ) );
//}else{
//}
if( d_conflict ){
@@ -1555,7 +1561,9 @@ Node TheoryStrings::checkCycles( Node eqc, std::vector< Node >& curr, std::vecto
if( eqc==d_emptyString_r ){
//for empty eqc, ensure all components are empty
if( nr!=d_emptyString_r ){
- sendInfer( n.eqNode( d_emptyString ), n[i].eqNode( d_emptyString ), "I_CYCLE_E" );
+ std::vector< Node > exp;
+ exp.push_back( n.eqNode( d_emptyString ) );
+ sendInference( exp, n[i].eqNode( d_emptyString ), "I_CYCLE_E" );
return Node::null();
}
}else{
@@ -1574,7 +1582,7 @@ Node TheoryStrings::checkCycles( Node eqc, std::vector< Node >& curr, std::vecto
for( unsigned j=0; j<n.getNumChildren(); j++ ){
//take first non-empty
if( j!=i && !areEqual( n[j], d_emptyString ) ){
- sendInfer( mkAnd( exp ), n[j].eqNode( d_emptyString ), "I_CYCLE" );
+ sendInference( exp, n[j].eqNode( d_emptyString ), "I_CYCLE" );
return Node::null();
}
}
@@ -1642,7 +1650,7 @@ void TheoryStrings::checkNormalForms(){
//two equivalence classes have same normal form, merge
nf_exp.push_back( eqc_to_exp[nf_to_eqc[nf_term]] );
Node eq = eqc.eqNode( nf_to_eqc[nf_term] );
- sendInfer( mkAnd( nf_exp ), eq, "Normal_Form" );
+ sendInference( nf_exp, eq, "Normal_Form" );
} else {
nf_to_eqc[nf_term] = eqc;
eqc_to_exp[eqc] = mkAnd( nf_exp );
@@ -1701,14 +1709,16 @@ bool TheoryStrings::normalizeEquivalenceClass( Node eqc, std::vector< Node > & n
std::vector< std::vector< Node > > normal_forms;
// explanation for each normal form (phi)
std::vector< std::vector< Node > > normal_forms_exp;
+ // dependency information
+ std::vector< std::map< Node, std::map< bool, int > > > normal_forms_exp_depend;
// record terms for each normal form (t)
std::vector< Node > normal_form_src;
//Get Normal Forms
- result = getNormalForms(eqc, nf, normal_forms, normal_forms_exp, normal_form_src);
+ result = getNormalForms(eqc, normal_forms, normal_form_src, normal_forms_exp, normal_forms_exp_depend);
if( hasProcessed() ){
- return true;
+ return true;
}else if( result ){
- if( processNEqc(normal_forms, normal_forms_exp, normal_form_src) ){
+ if( processNEqc(normal_forms, normal_form_src, normal_forms_exp, normal_forms_exp_depend) ){
return true;
}
}
@@ -1716,20 +1726,43 @@ bool TheoryStrings::normalizeEquivalenceClass( Node eqc, std::vector< Node > & n
if( normal_forms.empty() ){
Trace("strings-solve-debug2") << "construct the normal form" << std::endl;
getConcatVec( eqc, nf );
+ d_normal_forms_base[eqc] = eqc;
}else{
- Trace("strings-solve-debug2") << "just take the first normal form" << std::endl;
- //just take the first normal form
- nf.insert( nf.end(), normal_forms[0].begin(), normal_forms[0].end() );
- nf_exp.insert( nf_exp.end(), normal_forms_exp[0].begin(), normal_forms_exp[0].end() );
- if( eqc!=normal_form_src[0] ){
- nf_exp.push_back( eqc.eqNode( normal_form_src[0] ) );
+ int nf_index = 0;
+ //nf.insert( nf.end(), normal_forms[nf_index].begin(), normal_forms[nf_index].end() );
+ //nf_exp.insert( nf_exp.end(), normal_forms_exp[nf_index].begin(), normal_forms_exp[nf_index].end() );
+ //Trace("strings-solve-debug2") << "take normal form ... done" << std::endl;
+ //d_normal_forms_base[eqc] = normal_form_src[nf_index];
+ ///*
+ std::vector< Node >::iterator itn = std::find( normal_form_src.begin(), normal_form_src.end(), eqc );
+ if( itn!=normal_form_src.end() ){
+ nf_index = itn - normal_form_src.begin();
+ Trace("strings-solve-debug2") << "take normal form " << nf_index << std::endl;
+ Assert( normal_form_src[nf_index]==eqc );
+ }else{
+ //just take the first normal form
+ Trace("strings-solve-debug2") << "take the first normal form" << std::endl;
+ }
+ nf.insert( nf.end(), normal_forms[nf_index].begin(), normal_forms[nf_index].end() );
+ nf_exp.insert( nf_exp.end(), normal_forms_exp[nf_index].begin(), normal_forms_exp[nf_index].end() );
+ //if( eqc!=normal_form_src[nf_index] ){
+ // nf_exp.push_back( eqc.eqNode( normal_form_src[nf_index] ) );
+ //}
+ Trace("strings-solve-debug2") << "take normal form ... done" << std::endl;
+ d_normal_forms_base[eqc] = normal_form_src[nf_index];
+ //*/
+ //track dependencies
+ for( unsigned i=0; i<normal_forms_exp[nf_index].size(); i++ ){
+ Node exp = normal_forms_exp[nf_index][i];
+ for( unsigned r=0; r<2; r++ ){
+ d_normal_forms_exp_depend[eqc][exp][r==0] = normal_forms_exp_depend[nf_index][exp][r==0];
+ }
}
- Trace("strings-solve-debug2") << "just take the first normal form ... done" << std::endl;
}
- d_normal_forms_base[eqc] = normal_form_src.empty() ? eqc : normal_form_src[0];
d_normal_forms[eqc].insert( d_normal_forms[eqc].end(), nf.begin(), nf.end() );
d_normal_forms_exp[eqc].insert( d_normal_forms_exp[eqc].end(), nf_exp.begin(), nf_exp.end() );
+
Trace("strings-process-debug") << "Return process equivalence class " << eqc << " : returned, size = " << nf.size() << std::endl;
}else{
Trace("strings-process-debug") << "Return process equivalence class " << eqc << " : already computed, size = " << d_normal_forms[eqc].size() << std::endl;
@@ -1741,9 +1774,8 @@ bool TheoryStrings::normalizeEquivalenceClass( Node eqc, std::vector< Node > & n
}
}
-bool TheoryStrings::getNormalForms( Node &eqc, std::vector< Node > & nf,
- std::vector< std::vector< Node > > &normal_forms, std::vector< std::vector< Node > > &normal_forms_exp,
- std::vector< Node > &normal_form_src) {
+bool TheoryStrings::getNormalForms( Node &eqc, std::vector< std::vector< Node > > &normal_forms, std::vector< Node > &normal_form_src,
+ std::vector< std::vector< Node > > &normal_forms_exp, std::vector< std::map< Node, std::map< bool, int > > >& normal_forms_exp_depend ) {
Trace("strings-process-debug") << "Get normal forms " << eqc << std::endl;
eq::EqClassIterator eqc_i = eq::EqClassIterator( eqc, &d_equalityEngine );
while( !eqc_i.isFinished() ){
@@ -1751,8 +1783,9 @@ bool TheoryStrings::getNormalForms( Node &eqc, std::vector< Node > & nf,
if( d_congruent.find( n )==d_congruent.end() ){
if( n.getKind() == kind::CONST_STRING || n.getKind() == kind::STRING_CONCAT ){
Trace("strings-process-debug") << "Get Normal Form : Process term " << n << " in eqc " << eqc << std::endl;
- std::vector<Node> nf_n;
- std::vector<Node> nf_exp_n;
+ std::vector< Node > nf_n;
+ std::vector< Node > nf_exp_n;
+ std::map< Node, std::map< bool, int > > nf_exp_depend_n;
if( n.getKind()==kind::CONST_STRING ){
if( n!=d_emptyString ) {
nf_n.push_back( n );
@@ -1760,33 +1793,55 @@ bool TheoryStrings::getNormalForms( Node &eqc, std::vector< Node > & nf,
}else if( n.getKind()==kind::STRING_CONCAT ){
for( unsigned i=0; i<n.getNumChildren(); i++ ) {
Node nr = d_equalityEngine.getRepresentative( n[i] );
- std::vector< Node > nf_temp;
- std::vector< Node > nf_exp_temp;
Trace("strings-process-debug") << "Normalizing subterm " << n[i] << " = " << nr << std::endl;
Assert( d_normal_forms.find( nr )!=d_normal_forms.end() );
- nf_temp.insert( nf_temp.end(), d_normal_forms[nr].begin(), d_normal_forms[nr].end() );
- nf_exp_temp.insert( nf_exp_temp.end(), d_normal_forms_exp[nr].begin(), d_normal_forms_exp[nr].end() );
+ unsigned orig_size = nf_n.size();
+ unsigned add_size = d_normal_forms[nr].size();
//if not the empty string, add to current normal form
- if( nf.size()!=1 || nf[0]!=d_emptyString ){
- for( unsigned r=0; r<nf_temp.size(); r++ ) {
+ if( !d_normal_forms[nr].empty() ){
+ for( unsigned r=0; r<d_normal_forms[nr].size(); r++ ) {
if( Trace.isOn("strings-error") ) {
- if( nf_temp[r].getKind()==kind::STRING_CONCAT ){
+ if( d_normal_forms[nr][r].getKind()==kind::STRING_CONCAT ){
Trace("strings-error") << "Strings::Error: From eqc = " << eqc << ", " << n << " index " << i << ", bad normal form : ";
- for( unsigned rr=0; rr<nf_temp.size(); rr++ ) {
- Trace("strings-error") << nf_temp[rr] << " ";
+ for( unsigned rr=0; rr<d_normal_forms[nr].size(); rr++ ) {
+ Trace("strings-error") << d_normal_forms[nr][rr] << " ";
}
Trace("strings-error") << std::endl;
}
}
- Assert( nf_temp[r].getKind()!=kind::STRING_CONCAT );
+ Assert( d_normal_forms[nr][r].getKind()!=kind::STRING_CONCAT );
+ }
+ nf_n.insert( nf_n.end(), d_normal_forms[nr].begin(), d_normal_forms[nr].end() );
+ }
+
+ for( unsigned j=0; j<d_normal_forms_exp[nr].size(); j++ ){
+ Node exp = d_normal_forms_exp[nr][j];
+ nf_exp_n.push_back( exp );
+ //track depends
+ for( unsigned k=0; k<2; k++ ){
+ int prev_dep = d_normal_forms_exp_depend[nr][exp][k==1];
+ if( k==0 ){
+ nf_exp_depend_n[exp][false] = orig_size + prev_dep;
+ }else if( k==1 ){
+ //store forward index (converted back to reverse index below)
+ nf_exp_depend_n[exp][true] = orig_size + ( add_size - prev_dep );
+ }
}
- nf_n.insert( nf_n.end(), nf_temp.begin(), nf_temp.end() );
}
- nf_exp_n.insert( nf_exp_n.end(), nf_exp_temp.begin(), nf_exp_temp.end() );
if( nr!=n[i] ){
- nf_exp_n.push_back( n[i].eqNode( nr ) );
+ Node eq = n[i].eqNode( nr );
+ nf_exp_n.push_back( eq );
+ //track depends
+ nf_exp_depend_n[eq][false] = orig_size;
+ nf_exp_depend_n[eq][true] = orig_size + add_size;
}
}
+ //convert forward indices to reverse indices
+ int total_size = nf_n.size();
+ for( std::map< Node, std::map< bool, int > >::iterator it = nf_exp_depend_n.begin(); it != nf_exp_depend_n.end(); ++it ){
+ it->second[true] = total_size - it->second[true];
+ Assert( it->second[true]>=0 );
+ }
}
//if not equal to self
if( nf_n.size()>1 || ( nf_n.size()==1 && nf_n[0].getKind()==kind::CONST_STRING ) ){
@@ -1801,8 +1856,9 @@ bool TheoryStrings::getNormalForms( Node &eqc, std::vector< Node > & nf,
}
}
normal_forms.push_back(nf_n);
- normal_forms_exp.push_back(nf_exp_n);
normal_form_src.push_back(n);
+ normal_forms_exp.push_back(nf_exp_n);
+ normal_forms_exp_depend.push_back(nf_exp_depend_n);
}else{
//this was redundant: combination of self + empty string(s)
Node nn = nf_n.size()==0 ? d_emptyString : nf_n[0];
@@ -1814,7 +1870,7 @@ bool TheoryStrings::getNormalForms( Node &eqc, std::vector< Node > & nf,
ant.insert( ant.end(), nf_exp_n.begin(), nf_exp_n.end() );
ant.push_back( n.eqNode( eqc ) );
Node conc = Rewriter::rewrite( nn.eqNode( eqc ) );
- sendInfer( mkAnd( ant ), conc, "CYCLE-T" );
+ sendInference( ant, conc, "CYCLE-T" );
return true;
}
*/
@@ -1846,72 +1902,92 @@ bool TheoryStrings::getNormalForms( Node &eqc, std::vector< Node > & nf,
}
Trace("strings-solve") << normal_forms_exp[i][j];
}
+ Trace("strings-solve") << std::endl;
+ Trace("strings-solve") << "WITH DEPENDENCIES : " << std::endl;
+ for( unsigned j=0; j<normal_forms_exp[i].size(); j++ ) {
+ Trace("strings-solve") << " " << normal_forms_exp[i][j] << " -> ";
+ Trace("strings-solve") << normal_forms_exp_depend[i][normal_forms_exp[i][j]][false] << ",";
+ Trace("strings-solve") << normal_forms_exp_depend[i][normal_forms_exp[i][j]][true] << std::endl;
+ }
}
Trace("strings-solve") << std::endl;
+
}
} else {
- //std::vector< Node > nf;
- //nf.push_back( eqc );
- //normal_forms.push_back(nf);
- //std::vector< Node > nf_exp_def;
- //normal_forms_exp.push_back(nf_exp_def);
- //normal_form_src.push_back(eqc);
Trace("strings-solve") << "--- Single normal form for equivalence class " << eqc << std::endl;
}
}
return true;
}
+void TheoryStrings::getExplanationVectorForPrefix( std::vector< std::vector< Node > > &normal_forms, std::vector< Node > &normal_form_src,
+ std::vector< std::vector< Node > > &normal_forms_exp, std::vector< std::map< Node, std::map< bool, int > > >& normal_forms_exp_depend,
+ unsigned i, unsigned j, int index, bool isRev, std::vector< Node >& curr_exp ) {
+ if( index==-1 || !options::stringMinPrefixExplain() ){
+ curr_exp.insert(curr_exp.end(), normal_forms_exp[i].begin(), normal_forms_exp[i].end() );
+ curr_exp.insert(curr_exp.end(), normal_forms_exp[j].begin(), normal_forms_exp[j].end() );
+ }else{
+ Trace("strings-explain-prefix") << "Get explanation for prefix " << index << " of normal forms " << i << " and " << j << ", reverse = " << isRev << std::endl;
+ for( unsigned r=0; r<2; r++ ){
+ int tindex = r==0 ? i : j;
+ for( unsigned k=0; k<normal_forms_exp[tindex].size(); k++ ){
+ Node exp = normal_forms_exp[tindex][k];
+ int dep = normal_forms_exp_depend[tindex][exp][isRev];
+ if( dep<=index ){
+ curr_exp.push_back( exp );
+ Trace("strings-explain-prefix-debug") << " include : " << exp << std::endl;
+ }else{
+ Trace("strings-explain-prefix-debug") << " exclude : " << exp << std::endl;
+ }
+ }
+ }
+ Trace("strings-explain-prefix") << "Included " << curr_exp.size() << " / " << ( normal_forms_exp[i].size() + normal_forms_exp[j].size() ) << std::endl;
+ }
+ if( normal_form_src[i]!=normal_form_src[j] ){
+ curr_exp.push_back( normal_form_src[i].eqNode( normal_form_src[j] ) );
+ }
+}
-bool TheoryStrings::processNEqc( std::vector< std::vector< Node > > &normal_forms, std::vector< std::vector< Node > > &normal_forms_exp,
- std::vector< Node > &normal_form_src) {
+bool TheoryStrings::processNEqc( std::vector< std::vector< Node > > &normal_forms, std::vector< Node > &normal_form_src,
+ std::vector< std::vector< Node > > &normal_forms_exp, std::vector< std::map< Node, std::map< bool, int > > >& normal_forms_exp_depend ) {
bool flag_lb = false;
std::vector< Node > c_lb_exp;
- int c_i, c_j, c_loop_n_index, c_other_n_index, c_loop_index, c_index, c_other_index;
+ int c_i, c_j, c_loop_n_index, c_other_n_index, c_loop_index, c_index;
for(unsigned i=0; i<normal_forms.size()-1; i++) {
//unify each normalform[j] with normal_forms[i]
for(unsigned j=i+1; j<normal_forms.size(); j++ ) {
Trace("strings-solve") << "Strings: Process normal form #" << i << " against #" << j << "..." << std::endl;
if( isNormalFormPair( normal_form_src[i], normal_form_src[j] ) ) {
Trace("strings-solve") << "Strings: Already cached." << std::endl;
- } else {
- //the current explanation for why the prefix is equal
- std::vector< Node > curr_exp;
- curr_exp.insert(curr_exp.end(), normal_forms_exp[i].begin(), normal_forms_exp[i].end() );
- curr_exp.insert(curr_exp.end(), normal_forms_exp[j].begin(), normal_forms_exp[j].end() );
- if( normal_form_src[i]!=normal_form_src[j] ){
- curr_exp.push_back( normal_form_src[i].eqNode( normal_form_src[j] ) );
- }
-
+ }else{
//process the reverse direction first (check for easy conflicts and inferences)
- if( processReverseNEq( normal_forms, normal_form_src, curr_exp, i, j ) ){
+ if( processReverseNEq( normal_forms, normal_form_src, normal_forms_exp, normal_forms_exp_depend, i, j ) ){
return true;
}
//ensure that normal_forms[i] and normal_forms[j] are the same modulo equality
- unsigned index_i = 0;
- unsigned index_j = 0;
+ unsigned index = 0;
bool success;
do{
//simple check
- if( processSimpleNEq( normal_forms, normal_form_src, curr_exp, i, j, index_i, index_j, false ) ){
+ if( processSimpleNEq( normal_forms, normal_form_src, normal_forms_exp, normal_forms_exp_depend, i, j, index, false ) ){
//added a lemma, return
return true;
}
success = false;
//if we are at the end
- if(index_i==normal_forms[i].size() || index_j==normal_forms[j].size() ) {
- Assert( index_i==normal_forms[i].size() && index_j==normal_forms[j].size() );
+ if(index==normal_forms[i].size() || index==normal_forms[j].size() ) {
+ Assert( index==normal_forms[i].size() && index==normal_forms[j].size() );
//we're done
//addNormalFormPair( normal_form_src[i], normal_form_src[j] );
} else {
std::vector< Node > lexp;
- Node length_term_i = getLength( normal_forms[i][index_i], lexp );
- Node length_term_j = getLength( normal_forms[j][index_j], lexp );
+ Node length_term_i = getLength( normal_forms[i][index], lexp );
+ Node length_term_j = getLength( normal_forms[j][index], lexp );
//check length(normal_forms[i][index]) == length(normal_forms[j][index])
if( !areDisequal(length_term_i, length_term_j) && !areEqual(length_term_i, length_term_j) &&
- normal_forms[i][index_i].getKind()!=kind::CONST_STRING && normal_forms[j][index_j].getKind()!=kind::CONST_STRING ) {
+ normal_forms[i][index].getKind()!=kind::CONST_STRING && normal_forms[j][index].getKind()!=kind::CONST_STRING ) {
//length terms are equal, merge equivalence classes if not already done so
Node length_eq = NodeManager::currentNM()->mkNode( kind::EQUAL, length_term_i, length_term_j );
Trace("strings-solve-debug") << "Non-simple Case 1 : string lengths neither equal nor disequal" << std::endl;
@@ -1924,23 +2000,21 @@ bool TheoryStrings::processNEqc( std::vector< std::vector< Node > > &normal_form
Trace("strings-solve-debug") << "Non-simple Case 2 : must compare strings" << std::endl;
int loop_in_i = -1;
int loop_in_j = -1;
- if( detectLoop(normal_forms, i, j, index_i, index_j, loop_in_i, loop_in_j) ){
+ if( detectLoop(normal_forms, i, j, index, loop_in_i, loop_in_j) ){
if( !flag_lb ){
c_i = i;
c_j = j;
c_loop_n_index = loop_in_i!=-1 ? i : j;
c_other_n_index = loop_in_i!=-1 ? j : i;
c_loop_index = loop_in_i!=-1 ? loop_in_i : loop_in_j;
- c_index = loop_in_i!=-1 ? index_i : index_j;
- c_other_index = loop_in_i!=-1 ? index_j : index_i;
-
- c_lb_exp = curr_exp;
+ c_index = index;
+
+ getExplanationVectorForPrefix( normal_forms, normal_form_src, normal_forms_exp, normal_forms_exp_depend, i, j, -1, false, c_lb_exp );
if(options::stringLB() == 0) {
flag_lb = true;
} else {
- if(processLoop(c_lb_exp, normal_forms, normal_form_src,
- c_i, c_j, c_loop_n_index, c_other_n_index, c_loop_index, c_index, c_other_index)) {
+ if(processLoop(c_lb_exp, normal_forms, normal_form_src, c_i, c_j, c_loop_n_index, c_other_n_index, c_loop_index, c_index)) {
return true;
}
}
@@ -1949,26 +2023,24 @@ bool TheoryStrings::processNEqc( std::vector< std::vector< Node > > &normal_form
Node conc;
std::vector< Node > antec;
Trace("strings-solve-debug") << "No loops detected." << std::endl;
- if( normal_forms[i][index_i].getKind() == kind::CONST_STRING || normal_forms[j][index_j].getKind() == kind::CONST_STRING) {
- unsigned const_k = normal_forms[i][index_i].getKind() == kind::CONST_STRING ? i : j;
- unsigned const_index_k = normal_forms[i][index_i].getKind() == kind::CONST_STRING ? index_i : index_j;
- unsigned nconst_k = normal_forms[i][index_i].getKind() == kind::CONST_STRING ? j : i;
- unsigned nconst_index_k = normal_forms[i][index_i].getKind() == kind::CONST_STRING ? index_j : index_i;
- Node const_str = normal_forms[const_k][const_index_k];
- Node other_str = normal_forms[nconst_k][nconst_index_k];
+ if( normal_forms[i][index].getKind() == kind::CONST_STRING || normal_forms[j][index].getKind() == kind::CONST_STRING) {
+ unsigned const_k = normal_forms[i][index].getKind() == kind::CONST_STRING ? i : j;
+ unsigned nconst_k = normal_forms[i][index].getKind() == kind::CONST_STRING ? j : i;
+ Node const_str = normal_forms[const_k][index];
+ Node other_str = normal_forms[nconst_k][index];
Assert( other_str.getKind()!=kind::CONST_STRING, "Other string is not constant." );
Assert( other_str.getKind()!=kind::STRING_CONCAT, "Other string is not CONCAT." );
- if( !areDisequal(other_str, d_emptyString) ) {
+ if( !d_equalityEngine.areDisequal(other_str, d_emptyString, true) ) {
sendSplit( other_str, d_emptyString, "Len-Split(CST)" );
} else {
Assert(areDisequal(other_str, d_emptyString), "CST Split on empty Var");
- antec.insert( antec.end(), curr_exp.begin(), curr_exp.end() );
+ getExplanationVectorForPrefix( normal_forms, normal_form_src, normal_forms_exp, normal_forms_exp_depend, i, j, index, false, antec );
Node xnz = other_str.eqNode(d_emptyString).negate();
antec.push_back( xnz );
Node conc;
- if( normal_forms[nconst_k].size() > nconst_index_k + 1 && normal_forms[nconst_k][nconst_index_k + 1].isConst() ) {
+ if( normal_forms[nconst_k].size() > index + 1 && normal_forms[nconst_k][index + 1].isConst() ) {
CVC4::String stra = const_str.getConst<String>();
- CVC4::String strb = normal_forms[nconst_k][nconst_index_k + 1].getConst<String>();
+ CVC4::String strb = normal_forms[nconst_k][index + 1].getConst<String>();
CVC4::String stra1 = stra.substr(1);
size_t p = stra.size() - stra1.overlap(strb);
size_t p2 = stra1.find(strb);
@@ -1987,13 +2059,12 @@ bool TheoryStrings::processNEqc( std::vector< std::vector< Node > > &normal_form
}
conc = Rewriter::rewrite( conc );
- sendLemma( mkExplain( antec ), conc, "S-Split(CST-P)" );
- //sendInfer(mkAnd( antec ), conc, "S-Split(CST-P)");
+ sendInference( antec, conc, "S-Split(CST-P)", true );
}
return true;
} else {
std::vector< Node > antec_new_lits;
- antec.insert(antec.end(), curr_exp.begin(), curr_exp.end() );
+ getExplanationVectorForPrefix( normal_forms, normal_form_src, normal_forms_exp, normal_forms_exp_depend, i, j, index, false, antec );
Node ldeq = NodeManager::currentNM()->mkNode( kind::EQUAL, length_term_i, length_term_j ).negate();
if( d_equalityEngine.areDisequal( length_term_i, length_term_j, true ) ){
@@ -2004,7 +2075,7 @@ bool TheoryStrings::processNEqc( std::vector< std::vector< Node > > &normal_form
//x!=e /\ y!=e
for(unsigned xory=0; xory<2; xory++) {
- Node x = xory==0 ? normal_forms[i][index_i] : normal_forms[j][index_j];
+ Node x = xory==0 ? normal_forms[i][index] : normal_forms[j][index];
Node xgtz = x.eqNode( d_emptyString ).negate();
if( d_equalityEngine.areDisequal( x, d_emptyString, true ) ) {
antec.push_back( xgtz );
@@ -2012,15 +2083,31 @@ bool TheoryStrings::processNEqc( std::vector< std::vector< Node > > &normal_form
antec_new_lits.push_back( xgtz );
}
}
+ Node sk = mkSkolemCached( normal_forms[i][index], normal_forms[j][index], sk_id_v_spt, "v_spt", 1 );
+ Node eq1 = normal_forms[i][index].eqNode( mkConcat(normal_forms[j][index], sk) );
+ Node eq2 = normal_forms[j][index].eqNode( mkConcat(normal_forms[i][index], sk) );
+ if( options::stringCheckEntailLen() ){
+ //check entailment
+ for( unsigned e=0; e<2; e++ ){
+ Node lt1 = e==0 ? length_term_i : length_term_j;
+ Node lt2 = e==0 ? length_term_j : length_term_i;
+ Node ent_lit = Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::GT, lt1, lt2 ) );
+ std::pair<bool, Node> et = d_valuation.entailmentCheck(THEORY_OF_TYPE_BASED, ent_lit );
+ if( et.first ){
+ Trace("strings-entail") << "Strings entailment : " << ent_lit << " is entailed in the current context." << std::endl;
+ Trace("strings-entail") << " explanation was : " << et.second << std::endl;
+ conc = e==0 ? eq1 : eq2;
+ antec_new_lits.push_back( et.second );
+ break;
+ }
+ }
+ }
+ if( conc.isNull() ){
+ conc = Rewriter::rewrite(NodeManager::currentNM()->mkNode( kind::OR, eq1, eq2 ));
+ }
- Node sk = mkSkolemCached( normal_forms[i][index_i], normal_forms[j][index_j], sk_id_v_spt, "v_spt", 1 );
- Node eq1 = normal_forms[i][index_i].eqNode( mkConcat(normal_forms[j][index_j], sk) );
- Node eq2 = normal_forms[j][index_j].eqNode( mkConcat(normal_forms[i][index_i], sk) );
- conc = Rewriter::rewrite(NodeManager::currentNM()->mkNode( kind::OR, eq1, eq2 ));
- Node ant = mkExplain( antec, antec_new_lits );
- sendLemma( ant, conc, "S-Split(VAR)" );
- //sendInfer( ant, conc, "S-Split(VAR)" );
+ sendInference( antec, antec_new_lits, conc, "S-Split(VAR)", true );
//++(d_statistics.d_eq_splits);
return true;
}
@@ -2035,8 +2122,7 @@ bool TheoryStrings::processNEqc( std::vector< std::vector< Node > > &normal_form
}
}
if(flag_lb) {
- if(processLoop(c_lb_exp, normal_forms, normal_form_src,
- c_i, c_j, c_loop_n_index, c_other_n_index, c_loop_index, c_index, c_other_index)) {
+ if(processLoop(c_lb_exp, normal_forms, normal_form_src, c_i, c_j, c_loop_n_index, c_other_n_index, c_loop_index, c_index)) {
return true;
}
}
@@ -2045,16 +2131,14 @@ bool TheoryStrings::processNEqc( std::vector< std::vector< Node > > &normal_form
}
bool TheoryStrings::processReverseNEq( std::vector< std::vector< Node > > &normal_forms, std::vector< Node > &normal_form_src,
- std::vector< Node > &curr_exp, unsigned i, unsigned j ) {
+ std::vector< std::vector< Node > > &normal_forms_exp, std::vector< std::map< Node, std::map< bool, int > > >& normal_forms_exp_depend,
+ unsigned i, unsigned j ) {
//reverse normal form of i, j
std::reverse( normal_forms[i].begin(), normal_forms[i].end() );
std::reverse( normal_forms[j].begin(), normal_forms[j].end() );
- std::vector< Node > t_curr_exp;
- t_curr_exp.insert( t_curr_exp.begin(), curr_exp.begin(), curr_exp.end() );
- unsigned index_i = 0;
- unsigned index_j = 0;
- bool ret = processSimpleNEq( normal_forms, normal_form_src, t_curr_exp, i, j, index_i, index_j, true );
+ unsigned index = 0;
+ bool ret = processSimpleNEq( normal_forms, normal_form_src, normal_forms_exp, normal_forms_exp_depend, i, j, index, true );
//reverse normal form of i, j
std::reverse( normal_forms[i].begin(), normal_forms[i].end() );
@@ -2063,66 +2147,65 @@ bool TheoryStrings::processReverseNEq( std::vector< std::vector< Node > > &norma
return ret;
}
-bool TheoryStrings::processSimpleNEq( std::vector< std::vector< Node > > &normal_forms, std::vector< Node > &normal_form_src, std::vector< Node > &curr_exp,
- unsigned i, unsigned j, unsigned& index_i, unsigned& index_j, bool isRev ) {
+bool TheoryStrings::processSimpleNEq( std::vector< std::vector< Node > > &normal_forms, std::vector< Node > &normal_form_src,
+ std::vector< std::vector< Node > > &normal_forms_exp, std::vector< std::map< Node, std::map< bool, int > > >& normal_forms_exp_depend,
+ unsigned i, unsigned j, unsigned& index, bool isRev ) {
bool success;
do {
success = false;
//if we are at the end
- if(index_i==normal_forms[i].size() || index_j==normal_forms[j].size() ) {
- if( index_i==normal_forms[i].size() && index_j==normal_forms[j].size() ) {
+ if(index==normal_forms[i].size() || index==normal_forms[j].size() ) {
+ if( index==normal_forms[i].size() && index==normal_forms[j].size() ) {
//we're done
} else {
//the remainder must be empty
- unsigned k = index_i==normal_forms[i].size() ? j : i;
- unsigned index_k = index_i==normal_forms[i].size() ? index_j : index_i;
- Node eq_exp = mkAnd( curr_exp );
+ unsigned k = index==normal_forms[i].size() ? j : i;
+ unsigned index_k = index;
+ //Node eq_exp = mkAnd( curr_exp );
+ std::vector< Node > curr_exp;
+ getExplanationVectorForPrefix( normal_forms, normal_form_src, normal_forms_exp, normal_forms_exp_depend, i, j, -1, isRev, curr_exp );
while(!d_conflict && index_k<normal_forms[k].size()) {
//can infer that this string must be empty
Node eq = normal_forms[k][index_k].eqNode( d_emptyString );
//Trace("strings-lemma") << "Strings: Infer " << eq << " from " << eq_exp << std::endl;
Assert( !areEqual( d_emptyString, normal_forms[k][index_k] ) );
- sendInfer( eq_exp, eq, "EQ_Endpoint" );
+ sendInference( curr_exp, eq, "EQ_Endpoint" );
index_k++;
}
return true;
}
}else{
- Trace("strings-solve-debug") << "Process " << normal_forms[i][index_i] << " ... " << normal_forms[j][index_j] << std::endl;
- if(areEqual(normal_forms[i][index_i], normal_forms[j][index_j])) {
+ Trace("strings-solve-debug") << "Process " << normal_forms[i][index] << " ... " << normal_forms[j][index] << std::endl;
+ if( normal_forms[i][index]==normal_forms[j][index] ){
Trace("strings-solve-debug") << "Simple Case 1 : strings are equal" << std::endl;
- //terms are equal, continue
- if( normal_forms[i][index_i]!=normal_forms[j][index_j] ){
- Node eq = normal_forms[i][index_i].eqNode(normal_forms[j][index_j]);
- Trace("strings-solve-debug") << "Add to explanation : " << eq << std::endl;
- curr_exp.push_back(eq);
- }
- index_j++;
- index_i++;
+ index++;
success = true;
- } else {
+ }else{
+ Assert( !areEqual(normal_forms[i][index], normal_forms[j][index]) );
std::vector< Node > temp_exp;
- Node length_term_i = getLength( normal_forms[i][index_i], temp_exp );
- Node length_term_j = getLength( normal_forms[j][index_j], temp_exp );
+ Node length_term_i = getLength( normal_forms[i][index], temp_exp );
+ Node length_term_j = getLength( normal_forms[j][index], temp_exp );
//check length(normal_forms[i][index]) == length(normal_forms[j][index])
if( areEqual( length_term_i, length_term_j ) ){
Trace("strings-solve-debug") << "Simple Case 2 : string lengths are equal" << std::endl;
- Node eq = normal_forms[i][index_i].eqNode( normal_forms[j][index_j] );
+ Node eq = normal_forms[i][index].eqNode( normal_forms[j][index] );
//eq = Rewriter::rewrite( eq );
Node length_eq = length_term_i.eqNode( length_term_j );
- temp_exp.insert(temp_exp.end(), curr_exp.begin(), curr_exp.end() );
+ //temp_exp.insert(temp_exp.end(), curr_exp.begin(), curr_exp.end() );
+ getExplanationVectorForPrefix( normal_forms, normal_form_src, normal_forms_exp, normal_forms_exp_depend, i, j, index, isRev, temp_exp );
temp_exp.push_back(length_eq);
- sendInfer( mkAnd( temp_exp ), eq, "LengthEq" );
+ sendInference( temp_exp, eq, "LengthEq" );
return true;
- }else if( ( normal_forms[i][index_i].getKind()!=kind::CONST_STRING && index_i==normal_forms[i].size()-1 ) ||
- ( normal_forms[j][index_j].getKind()!=kind::CONST_STRING && index_j==normal_forms[j].size()-1 ) ){
+ }else if( ( normal_forms[i][index].getKind()!=kind::CONST_STRING && index==normal_forms[i].size()-1 ) ||
+ ( normal_forms[j][index].getKind()!=kind::CONST_STRING && index==normal_forms[j].size()-1 ) ){
Trace("strings-solve-debug") << "Simple Case 3 : at endpoint" << std::endl;
Node conc;
std::vector< Node > antec;
- antec.insert(antec.end(), curr_exp.begin(), curr_exp.end() );
+ //antec.insert(antec.end(), curr_exp.begin(), curr_exp.end() );
+ getExplanationVectorForPrefix( normal_forms, normal_form_src, normal_forms_exp, normal_forms_exp_depend, i, j, -1, isRev, antec );
std::vector< Node > eqn;
for( unsigned r=0; r<2; r++ ) {
- int index_k = r==0 ? index_i : index_j;
+ int index_k = index;
int k = r==0 ? i : j;
std::vector< Node > eqnc;
for( unsigned index_l=index_k; index_l<normal_forms[k].size(); index_l++ ) {
@@ -2136,16 +2219,15 @@ bool TheoryStrings::processSimpleNEq( std::vector< std::vector< Node > > &normal
}
if( !areEqual( eqn[0], eqn[1] ) ) {
conc = eqn[0].eqNode( eqn[1] );
- sendLemma( mkExplain( antec ), conc, "ENDPOINT" );
- //sendInfer( mkAnd( antec ), conc, "ENDPOINT" );
+ sendInference( antec, conc, "ENDPOINT", true );
return true;
}else{
- index_i = normal_forms[i].size();
- index_j = normal_forms[j].size();
+ Assert( normal_forms[i].size()==normal_forms[j].size() );
+ index = normal_forms[i].size();
}
- } else if(normal_forms[i][index_i].isConst() && normal_forms[j][index_j].isConst()) {
- Node const_str = normal_forms[i][index_i];
- Node other_str = normal_forms[j][index_j];
+ } else if( normal_forms[i][index].isConst() && normal_forms[j][index].isConst() ){
+ Node const_str = normal_forms[i][index];
+ Node other_str = normal_forms[j][index];
Trace("strings-solve-debug") << "Simple Case 3 : Const Split : " << const_str << " vs " << other_str << std::endl;
unsigned len_short = const_str.getConst<String>().size() <= other_str.getConst<String>().size() ? const_str.getConst<String>().size() : other_str.getConst<String>().size();
bool isSameFix = isRev ? const_str.getConst<String>().rstrncmp(other_str.getConst<String>(), len_short): const_str.getConst<String>().strncmp(other_str.getConst<String>(), len_short);
@@ -2153,29 +2235,26 @@ bool TheoryStrings::processSimpleNEq( std::vector< std::vector< Node > > &normal
//same prefix/suffix
//k is the index of the string that is shorter
int k = const_str.getConst<String>().size()<other_str.getConst<String>().size() ? i : j;
- int index_k = const_str.getConst<String>().size()<other_str.getConst<String>().size() ? index_i : index_j;
int l = const_str.getConst<String>().size()<other_str.getConst<String>().size() ? j : i;
- int index_l = const_str.getConst<String>().size()<other_str.getConst<String>().size() ? index_j : index_i;
if(isRev) {
- int new_len = normal_forms[l][index_l].getConst<String>().size() - len_short;
- Node remainderStr = NodeManager::currentNM()->mkConst( normal_forms[l][index_l].getConst<String>().substr(0, new_len) );
- Trace("strings-solve-debug-test") << "Break normal form of " << normal_forms[l][index_l] << " into " << normal_forms[k][index_k] << ", " << remainderStr << std::endl;
- normal_forms[l].insert( normal_forms[l].begin()+index_l + 1, remainderStr );
+ int new_len = normal_forms[l][index].getConst<String>().size() - len_short;
+ Node remainderStr = NodeManager::currentNM()->mkConst( normal_forms[l][index].getConst<String>().substr(0, new_len) );
+ Trace("strings-solve-debug-test") << "Break normal form of " << normal_forms[l][index] << " into " << normal_forms[k][index] << ", " << remainderStr << std::endl;
+ normal_forms[l].insert( normal_forms[l].begin()+index + 1, remainderStr );
} else {
- Node remainderStr = NodeManager::currentNM()->mkConst(normal_forms[l][index_l].getConst<String>().substr(len_short));
- Trace("strings-solve-debug-test") << "Break normal form of " << normal_forms[l][index_l] << " into " << normal_forms[k][index_k] << ", " << remainderStr << std::endl;
- normal_forms[l].insert( normal_forms[l].begin()+index_l + 1, remainderStr );
+ Node remainderStr = NodeManager::currentNM()->mkConst(normal_forms[l][index].getConst<String>().substr(len_short));
+ Trace("strings-solve-debug-test") << "Break normal form of " << normal_forms[l][index] << " into " << normal_forms[k][index] << ", " << remainderStr << std::endl;
+ normal_forms[l].insert( normal_forms[l].begin()+index + 1, remainderStr );
}
- normal_forms[l][index_l] = normal_forms[k][index_k];
- index_i++;
- index_j++;
+ normal_forms[l][index] = normal_forms[k][index];
+ index++;
success = true;
} else {
std::vector< Node > antec;
//curr_exp is conflict
- antec.insert(antec.end(), curr_exp.begin(), curr_exp.end() );
- Node ant = mkExplain( antec );
- sendLemma( ant, d_false, "Const Conflict" );
+ //antec.insert(antec.end(), curr_exp.begin(), curr_exp.end() );
+ getExplanationVectorForPrefix( normal_forms, normal_form_src, normal_forms_exp, normal_forms_exp_depend, i, j, index, isRev, antec );
+ sendInference( antec, d_false, "Const Conflict", true );
return true;
}
}
@@ -2185,18 +2264,15 @@ bool TheoryStrings::processSimpleNEq( std::vector< std::vector< Node > > &normal
return false;
}
-bool TheoryStrings::detectLoop( std::vector< std::vector< Node > > &normal_forms, int i, int j,
- int index_i, int index_j, int &loop_in_i, int &loop_in_j) {
+bool TheoryStrings::detectLoop( std::vector< std::vector< Node > > &normal_forms, int i, int j, int index, int &loop_in_i, int &loop_in_j) {
int has_loop[2] = { -1, -1 };
if( options::stringLB() != 2 ) {
for( unsigned r=0; r<2; r++ ) {
- int index = (r==0 ? index_i : index_j);
- int other_index = (r==0 ? index_j : index_i );
int n_index = (r==0 ? i : j);
int other_n_index = (r==0 ? j : i);
- if( normal_forms[other_n_index][other_index].getKind() != kind::CONST_STRING ) {
+ if( normal_forms[other_n_index][index].getKind() != kind::CONST_STRING ) {
for( unsigned lp = index+1; lp<normal_forms[n_index].size(); lp++ ){
- if( normal_forms[n_index][lp]==normal_forms[other_n_index][other_index] ){
+ if( normal_forms[n_index][lp]==normal_forms[other_n_index][index] ){
has_loop[r] = lp;
break;
}
@@ -2215,163 +2291,173 @@ bool TheoryStrings::detectLoop( std::vector< std::vector< Node > > &normal_forms
//xs(zy)=t(yz)xr
bool TheoryStrings::processLoop( std::vector< Node > &antec, std::vector< std::vector< Node > > &normal_forms, std::vector< Node > &normal_form_src,
- int i, int j, int loop_n_index, int other_n_index, int loop_index, int index, int other_index) {
- Node conc;
- Trace("strings-loop") << "Detected possible loop for " << normal_forms[loop_n_index][loop_index] << std::endl;
- Trace("strings-loop") << " ... (X)= " << normal_forms[other_n_index][other_index] << std::endl;
-
- Trace("strings-loop") << " ... T(Y.Z)= ";
- std::vector< Node > vec_t;
- for(int lp=index; lp<loop_index; ++lp) {
- if(lp != index) Trace("strings-loop") << " ++ ";
- Trace("strings-loop") << normal_forms[loop_n_index][lp];
- vec_t.push_back( normal_forms[loop_n_index][lp] );
- }
- Node t_yz = mkConcat( vec_t );
- Trace("strings-loop") << " (" << t_yz << ")" << std::endl;
- Trace("strings-loop") << " ... S(Z.Y)= ";
- std::vector< Node > vec_s;
- for(int lp=other_index+1; lp<(int)normal_forms[other_n_index].size(); ++lp) {
- if(lp != other_index+1) Trace("strings-loop") << " ++ ";
- Trace("strings-loop") << normal_forms[other_n_index][lp];
- vec_s.push_back( normal_forms[other_n_index][lp] );
- }
- Node s_zy = mkConcat( vec_s );
- Trace("strings-loop") << " (" << s_zy << ")" << std::endl;
- Trace("strings-loop") << " ... R= ";
- std::vector< Node > vec_r;
- for(int lp=loop_index+1; lp<(int)normal_forms[loop_n_index].size(); ++lp) {
- if(lp != loop_index+1) Trace("strings-loop") << " ++ ";
- Trace("strings-loop") << normal_forms[loop_n_index][lp];
- vec_r.push_back( normal_forms[loop_n_index][lp] );
- }
- Node r = mkConcat( vec_r );
- Trace("strings-loop") << " (" << r << ")" << std::endl;
-
- //Trace("strings-loop") << "Lemma Cache: " << normal_form_src[i] << " vs " << normal_form_src[j] << std::endl;
- //TODO: can be more general
- if( s_zy.isConst() && r.isConst() && r != d_emptyString) {
- int c;
- bool flag = true;
- if(s_zy.getConst<String>().tailcmp( r.getConst<String>(), c ) ) {
- if(c >= 0) {
- s_zy = NodeManager::currentNM()->mkConst( s_zy.getConst<String>().substr(0, c) );
- r = d_emptyString;
- vec_r.clear();
- Trace("strings-loop") << "Strings::Loop: Refactor S(Z.Y)= " << s_zy << ", c=" << c << std::endl;
- flag = false;
- }
+ int i, int j, int loop_n_index, int other_n_index, int loop_index, int index) {
+ if( options::stringAbortLoop() ){
+ Message() << "Looping word equation encountered." << std::endl;
+ exit( 1 );
+ }else{
+ Node conc;
+ Trace("strings-loop") << "Detected possible loop for " << normal_forms[loop_n_index][loop_index] << std::endl;
+ Trace("strings-loop") << " ... (X)= " << normal_forms[other_n_index][index] << std::endl;
+
+ Trace("strings-loop") << " ... T(Y.Z)= ";
+ std::vector< Node > vec_t;
+ for(int lp=index; lp<loop_index; ++lp) {
+ if(lp != index) Trace("strings-loop") << " ++ ";
+ Trace("strings-loop") << normal_forms[loop_n_index][lp];
+ vec_t.push_back( normal_forms[loop_n_index][lp] );
}
- if(flag) {
- Trace("strings-loop") << "Strings::Loop: tails are different." << std::endl;
- sendLemma( mkExplain( antec ), conc, "Loop Conflict" );
- return true;
+ Node t_yz = mkConcat( vec_t );
+ Trace("strings-loop") << " (" << t_yz << ")" << std::endl;
+ Trace("strings-loop") << " ... S(Z.Y)= ";
+ std::vector< Node > vec_s;
+ for(int lp=index+1; lp<(int)normal_forms[other_n_index].size(); ++lp) {
+ if(lp != index+1) Trace("strings-loop") << " ++ ";
+ Trace("strings-loop") << normal_forms[other_n_index][lp];
+ vec_s.push_back( normal_forms[other_n_index][lp] );
+ }
+ Node s_zy = mkConcat( vec_s );
+ Trace("strings-loop") << " (" << s_zy << ")" << std::endl;
+ Trace("strings-loop") << " ... R= ";
+ std::vector< Node > vec_r;
+ for(int lp=loop_index+1; lp<(int)normal_forms[loop_n_index].size(); ++lp) {
+ if(lp != loop_index+1) Trace("strings-loop") << " ++ ";
+ Trace("strings-loop") << normal_forms[loop_n_index][lp];
+ vec_r.push_back( normal_forms[loop_n_index][lp] );
+ }
+ Node r = mkConcat( vec_r );
+ Trace("strings-loop") << " (" << r << ")" << std::endl;
+
+ //Trace("strings-loop") << "Lemma Cache: " << normal_form_src[i] << " vs " << normal_form_src[j] << std::endl;
+ //TODO: can be more general
+ if( s_zy.isConst() && r.isConst() && r != d_emptyString) {
+ int c;
+ bool flag = true;
+ if(s_zy.getConst<String>().tailcmp( r.getConst<String>(), c ) ) {
+ if(c >= 0) {
+ s_zy = NodeManager::currentNM()->mkConst( s_zy.getConst<String>().substr(0, c) );
+ r = d_emptyString;
+ vec_r.clear();
+ Trace("strings-loop") << "Strings::Loop: Refactor S(Z.Y)= " << s_zy << ", c=" << c << std::endl;
+ flag = false;
+ }
+ }
+ if(flag) {
+ Trace("strings-loop") << "Strings::Loop: tails are different." << std::endl;
+ sendInference( antec, conc, "Loop Conflict", true );
+ return true;
+ }
}
- }
- //require that x is non-empty
- if( !areDisequal( normal_forms[loop_n_index][loop_index], d_emptyString ) ){
- //try to make normal_forms[loop_n_index][loop_index] equal to empty to avoid loop
- sendSplit( normal_forms[loop_n_index][loop_index], d_emptyString, "Len-Split(Loop-X)" );
- } else if( !areDisequal( t_yz, d_emptyString ) && t_yz.getKind()!=kind::CONST_STRING ) {
- //try to make normal_forms[loop_n_index][loop_index] equal to empty to avoid loop
- sendSplit( t_yz, d_emptyString, "Len-Split(Loop-YZ)" );
- } else {
- //need to break
- antec.push_back( normal_forms[loop_n_index][loop_index].eqNode( d_emptyString ).negate() );
- if( t_yz.getKind()!=kind::CONST_STRING ) {
- antec.push_back( t_yz.eqNode( d_emptyString ).negate() );
- }
- Node ant = mkExplain( antec );
- if(d_loop_antec.find(ant) == d_loop_antec.end()) {
- d_loop_antec.insert(ant);
-
- Node str_in_re;
- if( s_zy == t_yz &&
- r == d_emptyString &&
- s_zy.isConst() &&
- s_zy.getConst<String>().isRepeated()
- ) {
- Node rep_c = NodeManager::currentNM()->mkConst( s_zy.getConst<String>().substr(0, 1) );
- Trace("strings-loop") << "Special case (X)=" << normal_forms[other_n_index][other_index] << " " << std::endl;
- Trace("strings-loop") << "... (C)=" << rep_c << " " << std::endl;
- //special case
- str_in_re = NodeManager::currentNM()->mkNode( kind::STRING_IN_REGEXP, normal_forms[other_n_index][other_index],
- NodeManager::currentNM()->mkNode( kind::REGEXP_STAR,
- NodeManager::currentNM()->mkNode( kind::STRING_TO_REGEXP, rep_c ) ) );
- conc = str_in_re;
- } else if(t_yz.isConst()) {
- Trace("strings-loop") << "Strings::Loop: Const Normal Breaking." << std::endl;
- CVC4::String s = t_yz.getConst< CVC4::String >();
- unsigned size = s.size();
- std::vector< Node > vconc;
- for(unsigned len=1; len<=size; len++) {
- Node y = NodeManager::currentNM()->mkConst(s.substr(0, len));
- Node z = NodeManager::currentNM()->mkConst(s.substr(len, size - len));
- Node restr = s_zy;
- Node cc;
- if(r != d_emptyString) {
- std::vector< Node > v2(vec_r);
- v2.insert(v2.begin(), y);
- v2.insert(v2.begin(), z);
- restr = mkConcat( z, y );
- cc = Rewriter::rewrite(s_zy.eqNode( mkConcat( v2 ) ));
- } else {
- cc = Rewriter::rewrite(s_zy.eqNode( mkConcat( z, y) ));
- }
- if(cc == d_false) {
- continue;
+ //require that x is non-empty
+ if( !areDisequal( normal_forms[loop_n_index][loop_index], d_emptyString ) ){
+ //try to make normal_forms[loop_n_index][loop_index] equal to empty to avoid loop
+ sendSplit( normal_forms[loop_n_index][loop_index], d_emptyString, "Len-Split(Loop-X)" );
+ } else if( !areDisequal( t_yz, d_emptyString ) && t_yz.getKind()!=kind::CONST_STRING ) {
+ //try to make normal_forms[loop_n_index][loop_index] equal to empty to avoid loop
+ sendSplit( t_yz, d_emptyString, "Len-Split(Loop-YZ)" );
+ } else {
+ //need to break
+ antec.push_back( normal_forms[loop_n_index][loop_index].eqNode( d_emptyString ).negate() );
+ if( t_yz.getKind()!=kind::CONST_STRING ) {
+ antec.push_back( t_yz.eqNode( d_emptyString ).negate() );
+ }
+ Node ant = mkExplain( antec );
+ if(d_loop_antec.find(ant) == d_loop_antec.end()) {
+ d_loop_antec.insert(ant);
+
+ Node str_in_re;
+ if( s_zy == t_yz &&
+ r == d_emptyString &&
+ s_zy.isConst() &&
+ s_zy.getConst<String>().isRepeated()
+ ) {
+ Node rep_c = NodeManager::currentNM()->mkConst( s_zy.getConst<String>().substr(0, 1) );
+ Trace("strings-loop") << "Special case (X)=" << normal_forms[other_n_index][index] << " " << std::endl;
+ Trace("strings-loop") << "... (C)=" << rep_c << " " << std::endl;
+ //special case
+ str_in_re = NodeManager::currentNM()->mkNode( kind::STRING_IN_REGEXP, normal_forms[other_n_index][index],
+ NodeManager::currentNM()->mkNode( kind::REGEXP_STAR,
+ NodeManager::currentNM()->mkNode( kind::STRING_TO_REGEXP, rep_c ) ) );
+ conc = str_in_re;
+ } else if(t_yz.isConst()) {
+ Trace("strings-loop") << "Strings::Loop: Const Normal Breaking." << std::endl;
+ CVC4::String s = t_yz.getConst< CVC4::String >();
+ unsigned size = s.size();
+ std::vector< Node > vconc;
+ for(unsigned len=1; len<=size; len++) {
+ Node y = NodeManager::currentNM()->mkConst(s.substr(0, len));
+ Node z = NodeManager::currentNM()->mkConst(s.substr(len, size - len));
+ Node restr = s_zy;
+ Node cc;
+ if(r != d_emptyString) {
+ std::vector< Node > v2(vec_r);
+ v2.insert(v2.begin(), y);
+ v2.insert(v2.begin(), z);
+ restr = mkConcat( z, y );
+ cc = Rewriter::rewrite(s_zy.eqNode( mkConcat( v2 ) ));
+ } else {
+ cc = Rewriter::rewrite(s_zy.eqNode( mkConcat( z, y) ));
+ }
+ if(cc == d_false) {
+ continue;
+ }
+ Node conc2 = NodeManager::currentNM()->mkNode(kind::STRING_IN_REGEXP, normal_forms[other_n_index][index],
+ NodeManager::currentNM()->mkNode(kind::REGEXP_CONCAT,
+ NodeManager::currentNM()->mkNode(kind::STRING_TO_REGEXP, y),
+ NodeManager::currentNM()->mkNode(kind::REGEXP_STAR,
+ NodeManager::currentNM()->mkNode(kind::STRING_TO_REGEXP, restr))));
+ cc = cc==d_true ? conc2 : NodeManager::currentNM()->mkNode( kind::AND, cc, conc2 );
+ d_regexp_ant[conc2] = ant;
+ vconc.push_back(cc);
}
- Node conc2 = NodeManager::currentNM()->mkNode(kind::STRING_IN_REGEXP, normal_forms[other_n_index][other_index],
- NodeManager::currentNM()->mkNode(kind::REGEXP_CONCAT,
- NodeManager::currentNM()->mkNode(kind::STRING_TO_REGEXP, y),
- NodeManager::currentNM()->mkNode(kind::REGEXP_STAR,
- NodeManager::currentNM()->mkNode(kind::STRING_TO_REGEXP, restr))));
- cc = cc==d_true ? conc2 : NodeManager::currentNM()->mkNode( kind::AND, cc, conc2 );
- d_regexp_ant[conc2] = ant;
- vconc.push_back(cc);
+ conc = vconc.size()==0 ? Node::null() : vconc.size()==1 ? vconc[0] : NodeManager::currentNM()->mkNode(kind::OR, vconc);
+ } else {
+ Trace("strings-loop") << "Strings::Loop: Normal Loop Breaking." << std::endl;
+ //right
+ Node sk_w= mkSkolemS( "w_loop" );
+ Node sk_y= mkSkolemS( "y_loop", 1 );
+ Node sk_z= mkSkolemS( "z_loop" );
+ //t1 * ... * tn = y * z
+ Node conc1 = t_yz.eqNode( mkConcat( sk_y, sk_z ) );
+ // s1 * ... * sk = z * y * r
+ vec_r.insert(vec_r.begin(), sk_y);
+ vec_r.insert(vec_r.begin(), sk_z);
+ Node conc2 = s_zy.eqNode( mkConcat( vec_r ) );
+ Node conc3 = normal_forms[other_n_index][index].eqNode( mkConcat( sk_y, sk_w ) );
+ Node restr = r == d_emptyString ? s_zy : mkConcat( sk_z, sk_y );
+ str_in_re = NodeManager::currentNM()->mkNode( kind::STRING_IN_REGEXP, sk_w,
+ NodeManager::currentNM()->mkNode( kind::REGEXP_STAR,
+ NodeManager::currentNM()->mkNode( kind::STRING_TO_REGEXP, restr ) ) );
+
+ std::vector< Node > vec_conc;
+ vec_conc.push_back(conc1); vec_conc.push_back(conc2); vec_conc.push_back(conc3);
+ vec_conc.push_back(str_in_re);
+ //vec_conc.push_back(sk_y.eqNode(d_emptyString).negate());//by mkskolems
+ conc = NodeManager::currentNM()->mkNode( kind::AND, vec_conc );
+ } // normal case
+
+ //set its antecedant to ant, to say when it is relevant
+ if(!str_in_re.isNull()) {
+ d_regexp_ant[str_in_re] = ant;
+ }
+ //we will be done
+ addNormalFormPair( normal_form_src[i], normal_form_src[j] );
+ if( options::stringProcessLoop() ){
+ sendLemma( ant, conc, "F-LOOP" );
+ ++(d_statistics.d_loop_lemmas);
+ }else{
+ d_out->setIncomplete();
+ return false;
}
- conc = vconc.size()==0 ? Node::null() : vconc.size()==1 ? vconc[0] : NodeManager::currentNM()->mkNode(kind::OR, vconc);
+
} else {
- Trace("strings-loop") << "Strings::Loop: Normal Loop Breaking." << std::endl;
- //right
- Node sk_w= mkSkolemS( "w_loop" );
- Node sk_y= mkSkolemS( "y_loop", 1 );
- Node sk_z= mkSkolemS( "z_loop" );
- //t1 * ... * tn = y * z
- Node conc1 = t_yz.eqNode( mkConcat( sk_y, sk_z ) );
- // s1 * ... * sk = z * y * r
- vec_r.insert(vec_r.begin(), sk_y);
- vec_r.insert(vec_r.begin(), sk_z);
- Node conc2 = s_zy.eqNode( mkConcat( vec_r ) );
- Node conc3 = normal_forms[other_n_index][other_index].eqNode( mkConcat( sk_y, sk_w ) );
- Node restr = r == d_emptyString ? s_zy : mkConcat( sk_z, sk_y );
- str_in_re = NodeManager::currentNM()->mkNode( kind::STRING_IN_REGEXP, sk_w,
- NodeManager::currentNM()->mkNode( kind::REGEXP_STAR,
- NodeManager::currentNM()->mkNode( kind::STRING_TO_REGEXP, restr ) ) );
-
- std::vector< Node > vec_conc;
- vec_conc.push_back(conc1); vec_conc.push_back(conc2); vec_conc.push_back(conc3);
- vec_conc.push_back(str_in_re);
- //vec_conc.push_back(sk_y.eqNode(d_emptyString).negate());//by mkskolems
- conc = NodeManager::currentNM()->mkNode( kind::AND, vec_conc );
- } // normal case
-
- //set its antecedant to ant, to say when it is relevant
- if(!str_in_re.isNull()) {
- d_regexp_ant[str_in_re] = ant;
+ Trace("strings-loop") << "Strings::Loop: loop lemma for " << ant << " has already added." << std::endl;
+ addNormalFormPair( normal_form_src[i], normal_form_src[j] );
+ return false;
}
-
- sendLemma( ant, conc, "F-LOOP" );
- ++(d_statistics.d_loop_lemmas);
-
- //we will be done
- addNormalFormPair( normal_form_src[i], normal_form_src[j] );
- } else {
- Trace("strings-loop") << "Strings::Loop: loop lemma for " << ant << " has already added." << std::endl;
- addNormalFormPair( normal_form_src[i], normal_form_src[j] );
- return false;
}
+ return true;
}
return true;
}
@@ -2437,7 +2523,7 @@ bool TheoryStrings::processDeq( Node ni, Node nj ) {
Node lsk2 = mkLength( sk2 );
conc.push_back( lsk2.eqNode( lj ) );
conc.push_back( NodeManager::currentNM()->mkNode( kind::OR, j.eqNode( mkConcat( sk1, sk3 ) ), i.eqNode( mkConcat( sk2, sk3 ) ) ) );
- sendLemma( mkExplain( antec, antec_new_lits ), NodeManager::currentNM()->mkNode( kind::AND, conc ), "D-DISL-Split" );
+ sendInference( antec, antec_new_lits, NodeManager::currentNM()->mkNode( kind::AND, conc ), "D-DISL-Split" );
++(d_statistics.d_deq_splits);
return true;
}else if( areEqual( li, lj ) ){
@@ -2498,8 +2584,7 @@ int TheoryStrings::processSimpleDeq( std::vector< Node >& nfi, std::vector< Node
}
Node conc = cc.size()==1 ? cc[0] : NodeManager::currentNM()->mkNode( kind::AND, cc );
conc = Rewriter::rewrite( conc );
- sendLemma(mkExplain( ant ), conc, "Disequality Normalize Empty");
- //sendInfer(mkAnd( ant ), conc, "Disequality Normalize Empty");
+ sendInference( ant, conc, "Disequality Normalize Empty", true);
return -1;
} else {
Node i = nfi[index];
@@ -2663,6 +2748,49 @@ void TheoryStrings::registerTerm( Node n, int effort ) {
}
}
+void TheoryStrings::sendInference( std::vector< Node >& exp, std::vector< Node >& exp_n, Node eq, const char * c, bool asLemma ) {
+ eq = eq.isNull() ? d_false : Rewriter::rewrite( eq );
+ if( eq!=d_true ){
+ if( Trace.isOn("strings-infer-debug") ){
+ Trace("strings-infer-debug") << "infer : " << eq << " from: " << std::endl;
+ for( unsigned i=0; i<exp.size(); i++ ){
+ Trace("strings-infer-debug") << " " << exp[i] << std::endl;
+ }
+ for( unsigned i=0; i<exp_n.size(); i++ ){
+ Trace("strings-infer-debug") << " N:" << exp_n[i] << std::endl;
+ }
+ //Trace("strings-infer-debug") << "as lemma : " << asLemma << std::endl;
+ }
+ bool doSendLemma = ( asLemma || eq==d_false || eq.getKind()==kind::OR || options::stringInferAsLemmas() );
+ if( doSendLemma ){
+ Node eq_exp;
+ if( options::stringRExplainLemmas() ){
+ eq_exp = mkExplain( exp, exp_n );
+ }else{
+ if( exp.empty() ){
+ eq_exp = mkAnd( exp_n );
+ }else if( exp_n.empty() ){
+ eq_exp = mkAnd( exp );
+ }else{
+ std::vector< Node > ev;
+ ev.insert( ev.end(), exp.begin(), exp.end() );
+ ev.insert( ev.end(), exp_n.begin(), exp_n.end() );
+ eq_exp = NodeManager::currentNM()->mkNode( kind::AND, ev );
+ }
+ }
+ sendLemma( eq_exp, eq, c );
+ }else{
+ Assert( exp_n.empty() );
+ sendInfer( mkAnd( exp ), eq, c );
+ }
+ }
+}
+
+void TheoryStrings::sendInference( std::vector< Node >& exp, Node eq, const char * c, bool asLemma ) {
+ std::vector< Node > exp_n;
+ sendInference( exp, exp_n, eq, c, asLemma );
+}
+
void TheoryStrings::sendLemma( Node ant, Node conc, const char * c ) {
if( conc.isNull() || conc == d_false ) {
d_out->conflict(ant);
@@ -2684,38 +2812,33 @@ void TheoryStrings::sendLemma( Node ant, Node conc, const char * c ) {
}
void TheoryStrings::sendInfer( Node eq_exp, Node eq, const char * c ) {
- Trace("strings-infer-debug") << "infer : " << eq << " from " << eq_exp << std::endl;
- eq = Rewriter::rewrite( eq );
- if( eq==d_false || eq.getKind()==kind::OR ) {
- sendLemma( eq_exp, eq, c );
- }else if( eq!=d_true ){
- if( options::stringInferSym() ){
- std::vector< Node > vars;
- std::vector< Node > subs;
- std::vector< Node > unproc;
- inferSubstitutionProxyVars( eq_exp, vars, subs, unproc );
- if( unproc.empty() ){
- Trace("strings-lemma-debug") << "Strings::Infer " << eq << " from " << eq_exp << " by " << c << std::endl;
- Node eqs = eq.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
- Trace("strings-lemma-debug") << "Strings::Infer Alternate : " << eqs << std::endl;
- for( unsigned i=0; i<vars.size(); i++ ){
- Trace("strings-lemma-debug") << " " << vars[i] << " -> " << subs[i] << std::endl;
- }
- sendLemma( d_true, eqs, c );
- return;
- }else{
- for( unsigned i=0; i<unproc.size(); i++ ){
- Trace("strings-lemma-debug") << " non-trivial exp : " << unproc[i] << std::endl;
- }
+ if( options::stringInferSym() ){
+ std::vector< Node > vars;
+ std::vector< Node > subs;
+ std::vector< Node > unproc;
+ inferSubstitutionProxyVars( eq_exp, vars, subs, unproc );
+ if( unproc.empty() ){
+ Trace("strings-lemma-debug") << "Strings::Infer " << eq << " from " << eq_exp << " by " << c << std::endl;
+ Node eqs = eq.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
+ Trace("strings-lemma-debug") << "Strings::Infer Alternate : " << eqs << std::endl;
+ for( unsigned i=0; i<vars.size(); i++ ){
+ Trace("strings-lemma-debug") << " " << vars[i] << " -> " << subs[i] << std::endl;
+ }
+ sendLemma( d_true, eqs, c );
+ return;
+ }else{
+ for( unsigned i=0; i<unproc.size(); i++ ){
+ Trace("strings-lemma-debug") << " non-trivial exp : " << unproc[i] << std::endl;
}
}
- Trace("strings-lemma") << "Strings::Infer " << eq << " from " << eq_exp << " by " << c << std::endl;
- Trace("strings-assert") << "(assert (=> " << eq_exp << " " << eq << ")) ; infer " << c << std::endl;
- d_pending.push_back( eq );
- d_pending_exp[eq] = eq_exp;
- d_infer.push_back( eq );
- d_infer_exp.push_back( eq_exp );
}
+ Trace("strings-lemma") << "Strings::Infer " << eq << " from " << eq_exp << " by " << c << std::endl;
+ Trace("strings-assert") << "(assert (=> " << eq_exp << " " << eq << ")) ; infer " << c << std::endl;
+ d_pending.push_back( eq );
+ d_pending_exp[eq] = eq_exp;
+ d_infer.push_back( eq );
+ d_infer_exp.push_back( eq_exp );
+
}
void TheoryStrings::sendSplit( Node a, Node b, const char * c, bool preq ) {
@@ -2993,7 +3116,7 @@ void TheoryStrings::checkLengthsEqc() {
Node eq = llt.eqNode( lc );
if( llt!=lc ){
ei->d_normalized_length.set( eq );
- sendLemma( mkExplain( ant ), eq, "LEN-NORM" );
+ sendInference( ant, eq, "LEN-NORM", true );
}
}
}else{
@@ -3009,7 +3132,7 @@ void TheoryStrings::checkLengthsEqc() {
Assert( d_proxy_var_to_length.find( pv )!=d_proxy_var_to_length.end() );
Node pvl = d_proxy_var_to_length[pv];
Node ceq = Rewriter::rewrite( mkLength( pv ).eqNode( pvl ) );
- sendLemma( d_true, ceq, "LEN-NORM-I" );
+ sendInference( d_empty_vec, ceq, "LEN-NORM-I", true );
}
}
*/
@@ -3075,13 +3198,12 @@ void TheoryStrings::checkCardinality() {
vec_node.push_back( len_eq_lr );
}
}
- Node antc = NodeManager::currentNM()->mkNode( kind::AND, vec_node );
Node len = NodeManager::currentNM()->mkNode( kind::STRING_LENGTH, cols[i][0] );
Node cons = NodeManager::currentNM()->mkNode( kind::GEQ, len, k_node );
cons = Rewriter::rewrite( cons );
ei->d_cardinality_lem_k.set( int_k+1 );
if( cons!=d_true ){
- sendLemma( antc, cons, "CARDINALITY" );
+ sendInference( d_empty_vec, vec_node, cons, "CARDINALITY", true );
return;
}
}
@@ -3344,9 +3466,8 @@ bool TheoryStrings::normalizePosMemberships(std::map< Node, std::vector< Node >
inter_r = d_regexp_opr.intersect(inter_r, inter_r2, spflag);
if(inter_r == d_emptyRegexp) {
//conflict
- Node antec = exp.size() == 1? exp[0] : NodeManager::currentNM()->mkNode(kind::AND, exp);
Node conc;
- sendLemma(antec, conc, "INTERSECT CONFLICT");
+ sendInference( d_empty_vec, exp, conc, "INTERSECT CONFLICT", true );
addLemma = true;
break;
}
@@ -3417,17 +3538,15 @@ bool TheoryStrings::applyRLen(std::map< Node, std::vector< Node > > &XinR_with_e
bool TheoryStrings::checkMembershipsWithoutLength(
std::map< Node, std::vector< Node > > &memb_with_exps,
std::map< Node, std::vector< Node > > &XinR_with_exps) {
- for(std::map< Node, std::vector< Node > >::const_iterator itr = memb_with_exps.begin();
- itr != memb_with_exps.end(); ++itr) {
+ for(std::map< Node, std::vector< Node > >::iterator itr = memb_with_exps.begin(); itr != memb_with_exps.end(); ++itr) {
Node memb = itr->first;
Node s = memb[0];
Node r = memb[1];
if(s.isConst()) {
memb = Rewriter::rewrite( memb );
if(memb == d_false) {
- Node antec = itr->second.size() == 1? itr->second[0] : NodeManager::currentNM()->mkNode(kind::AND, itr->second);
Node conc;
- sendLemma(antec, conc, "MEMBERSHIP CONFLICT");
+ sendInference(d_empty_vec, itr->second, conc, "MEMBERSHIP CONFLICT", true);
//addLemma = true;
return true;
} else {
@@ -3438,14 +3557,13 @@ bool TheoryStrings::checkMembershipsWithoutLength(
XinR_with_exps[itr->first] = itr->second;
} else {
Assert(s.getKind() == kind::STRING_CONCAT);
- Node antec = itr->second.size() == 1? itr->second[0] : NodeManager::currentNM()->mkNode(kind::AND, itr->second);
Node conc;
for( unsigned i=0; i<s.getNumChildren(); i++ ) {
if(s[i].isConst()) {
CVC4::String str( s[0].getConst< String >() );
//R-Consume, see Tianyi's thesis
if(!applyRConsume(str, r)) {
- sendLemma(antec, conc, "R-Consume CONFLICT");
+ sendInference(d_empty_vec, itr->second, conc, "R-Consume CONFLICT", true);
//addLemma = true;
return true;
}
@@ -3467,11 +3585,11 @@ bool TheoryStrings::checkMembershipsWithoutLength(
break;
} else if(conc.isNull() || conc == d_false) {
conc = Node::null();
- sendLemma(antec, conc, "R-Split Conflict");
+ sendInference(d_empty_vec, itr->second, conc, "R-Split Conflict", true);
//addLemma = true;
return true;
} else {
- sendLemma(antec, conc, "R-Split");
+ sendInference(d_empty_vec, itr->second, conc, "R-Split", true);
//addLemma = true;
return true;
}
@@ -3569,9 +3687,8 @@ void TheoryStrings::checkMemberships() {
Node n = NodeManager::currentNM()->mkNode(kind::STRING_IN_REGEXP, x, *itr2);
vec_nodes.push_back( n );
}
- Node antec = vec_nodes.size() == 1? vec_nodes[0] : NodeManager::currentNM()->mkNode(kind::AND, vec_nodes);
Node conc;
- sendLemma(antec, conc, "INTERSECT CONFLICT");
+ sendInference(vec_nodes, conc, "INTERSECT CONFLICT", true);
addedLemma = true;
break;
}
@@ -3661,9 +3778,6 @@ void TheoryStrings::checkMemberships() {
} else {
processed.push_back( assertion );
}
- } else if(conc == d_false) {
- conc = Node::null();
- sendLemma(antec, conc, "RegExp CST-SP Conflict");
} else {
sendLemma(antec, conc, "RegExp-CST-SP");
}
@@ -3712,8 +3826,7 @@ void TheoryStrings::checkMemberships() {
}
}
antec = Rewriter::rewrite( NodeManager::currentNM()->mkNode(kind::AND, antec, mkExplain(rnfexp)) );
- Node conc = nvec.size()==1 ? nvec[0] :
- NodeManager::currentNM()->mkNode(kind::AND, nvec);
+ Node conc = nvec.size()==1 ? nvec[0] : NodeManager::currentNM()->mkNode(kind::AND, nvec);
conc = Rewriter::rewrite(conc);
sendLemma( antec, conc, "REGEXP" );
addedLemma = true;
@@ -3946,7 +4059,7 @@ void TheoryStrings::checkConstantEquivalenceClasses( TermIndex* ti, std::vector<
//exp contains an explanation of n==c
Assert( countc==vecc.size() );
if( hasTerm( c ) ){
- sendInfer( mkAnd( exp ), n.eqNode( c ), "I_CONST_MERGE" );
+ sendInference( exp, n.eqNode( c ), "I_CONST_MERGE" );
return;
}else if( !hasProcessed() ){
Node nr = getRepresentative( n );
@@ -3967,7 +4080,7 @@ void TheoryStrings::checkConstantEquivalenceClasses( TermIndex* ti, std::vector<
exp.push_back( d_eqc_to_const_exp[nr] );
addToExplanation( n, d_eqc_to_const_base[nr], exp );
}
- sendLemma( mkExplain( exp ), d_false, "I_CONST_CONFLICT" );
+ sendInference( exp, d_false, "I_CONST_CONFLICT" );
return;
}else{
Trace("strings-debug") << "Duplicate constant." << std::endl;
@@ -4053,7 +4166,7 @@ void TheoryStrings::checkNegContains( std::vector< Node >& negContains ) {
lexp.push_back( atom.negate() );
Node xneqs = x.eqNode(s).negate();
d_neg_ctn_eqlen.insert( atom );
- sendLemma( mkExplain( lexp ), xneqs, "NEG-CTN-EQL" );
+ sendInference( lexp, xneqs, "NEG-CTN-EQL", true );
}
}else if( !areDisequal( lenx, lens ) ){
if(d_neg_ctn_ulen.find(atom) == d_neg_ctn_ulen.end()) {
@@ -4093,7 +4206,9 @@ void TheoryStrings::checkNegContains( std::vector< Node >& negContains ) {
conc = Rewriter::rewrite( NodeManager::currentNM()->mkNode( kind::OR, xlss, conc ) );
d_neg_ctn_cached.insert( atom );
- sendLemma( atom.negate(), conc, "NEG-CTN-BRK" );
+ std::vector< Node > exp;
+ exp.push_back( atom.negate() );
+ sendInference( d_empty_vec, exp, conc, "NEG-CTN-BRK", true );
//d_pending_req_phase[xlss] = true;
}
}
diff --git a/src/theory/strings/theory_strings.h b/src/theory/strings/theory_strings.h
index fef2983fd..b9da524de 100644
--- a/src/theory/strings/theory_strings.h
+++ b/src/theory/strings/theory_strings.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_strings.h
** \verbatim
- ** Original author: Tianyi Liang
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): Martin Brain <>, Morgan Deters
+ ** Top contributors (to current version):
+ ** Tianyi Liang, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Theory of strings
**
@@ -158,6 +158,7 @@ private:
std::map< Node, Node > d_normal_forms_base;
std::map< Node, std::vector< Node > > d_normal_forms;
std::map< Node, std::vector< Node > > d_normal_forms_exp;
+ std::map< Node, std::map< Node, std::map< bool, int > > > d_normal_forms_exp_depend;
//map of pairs of terms that have the same normal form
NodeListMap d_nf_pairs;
void addNormalFormPair( Node n1, Node n2 );
@@ -174,7 +175,7 @@ private:
NodeBoolMap d_preproc_cache;
// extended functions inferences cache
NodeSet d_extf_infer_cache;
-
+ std::vector< Node > d_empty_vec;
private:
NodeSet d_congruent;
std::map< Node, Node > d_eqc_to_const;
@@ -236,7 +237,6 @@ private:
NodeNodeMap d_proxy_var;
NodeNodeMap d_proxy_var_to_length;
private:
-
//initial check
void checkInit();
void checkConstantEquivalenceClasses( TermIndex* ti, std::vector< Node >& vecc );
@@ -254,30 +254,31 @@ private:
//normal forms check
void checkNormalForms();
bool normalizeEquivalenceClass( Node n, std::vector< Node > & nf, std::vector< Node > & nf_exp );
- bool getNormalForms( Node &eqc, std::vector< Node > & nf,
- std::vector< std::vector< Node > > &normal_forms,
- std::vector< std::vector< Node > > &normal_forms_exp,
- std::vector< Node > &normal_form_src);
+ bool getNormalForms( Node &eqc, std::vector< std::vector< Node > > &normal_forms, std::vector< Node > &normal_form_src,
+ std::vector< std::vector< Node > > &normal_forms_exp, std::vector< std::map< Node, std::map< bool, int > > >& normal_forms_exp_depend);
bool detectLoop(std::vector< std::vector< Node > > &normal_forms,
- int i, int j, int index_i, int index_j,
- int &loop_in_i, int &loop_in_j);
+ int i, int j, int index, int &loop_in_i, int &loop_in_j);
bool processLoop(std::vector< Node > &antec,
std::vector< std::vector< Node > > &normal_forms,
std::vector< Node > &normal_form_src,
int i, int j, int loop_n_index, int other_n_index,
- int loop_index, int index, int other_index);
- bool processNEqc(std::vector< std::vector< Node > > &normal_forms,
- std::vector< std::vector< Node > > &normal_forms_exp,
- std::vector< Node > &normal_form_src);
- bool processReverseNEq(std::vector< std::vector< Node > > &normal_forms,
- std::vector< Node > &normal_form_src, std::vector< Node > &curr_exp, unsigned i, unsigned j );
- bool processSimpleNEq( std::vector< std::vector< Node > > &normal_forms,
- std::vector< Node > &normal_form_src, std::vector< Node > &curr_exp, unsigned i, unsigned j,
- unsigned& index_i, unsigned& index_j, bool isRev );
+ int loop_index, int index);
+ bool processNEqc( std::vector< std::vector< Node > > &normal_forms, std::vector< Node > &normal_form_src,
+ std::vector< std::vector< Node > > &normal_forms_exp, std::vector< std::map< Node, std::map< bool, int > > >& normal_forms_exp_depend );
+ bool processReverseNEq( std::vector< std::vector< Node > > &normal_forms, std::vector< Node > &normal_form_src,
+ std::vector< std::vector< Node > > &normal_forms_exp, std::vector< std::map< Node, std::map< bool, int > > >& normal_forms_exp_depend,
+ unsigned i, unsigned j );
+ bool processSimpleNEq( std::vector< std::vector< Node > > &normal_forms, std::vector< Node > &normal_form_src,
+ std::vector< std::vector< Node > > &normal_forms_exp, std::vector< std::map< Node, std::map< bool, int > > >& normal_forms_exp_depend,
+ unsigned i, unsigned j, unsigned& index, bool isRev );
bool processDeq( Node n1, Node n2 );
int processReverseDeq( std::vector< Node >& nfi, std::vector< Node >& nfj, Node ni, Node nj );
int processSimpleDeq( std::vector< Node >& nfi, std::vector< Node >& nfj, Node ni, Node nj, unsigned& index, bool isRev );
void checkDeqNF();
+
+ void getExplanationVectorForPrefix( std::vector< std::vector< Node > > &normal_forms, std::vector< Node > &normal_form_src,
+ std::vector< std::vector< Node > > &normal_forms_exp, std::vector< std::map< Node, std::map< bool, int > > >& normal_forms_exp_depend,
+ unsigned i, unsigned j, int index, bool isRev, std::vector< Node >& curr_exp );
//check for extended functions
void checkExtendedFuncs();
@@ -337,6 +338,8 @@ protected:
//register term
void registerTerm( Node n, int effort );
//send lemma
+ void sendInference( std::vector< Node >& exp, std::vector< Node >& exp_n, Node eq, const char * c, bool asLemma = false );
+ void sendInference( std::vector< Node >& exp, Node eq, const char * c, bool asLemma = false );
void sendLemma( Node ant, Node conc, const char * c );
void sendInfer( Node eq_exp, Node eq, const char * c );
void sendSplit( Node a, Node b, const char * c, bool preq = true );
diff --git a/src/theory/strings/theory_strings_preprocess.cpp b/src/theory/strings/theory_strings_preprocess.cpp
index a1c93a369..a4f42bddd 100644
--- a/src/theory/strings/theory_strings_preprocess.cpp
+++ b/src/theory/strings/theory_strings_preprocess.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_strings_preprocess.cpp
** \verbatim
- ** Original author: Tianyi Liang
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tianyi Liang, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Strings Preprocess
**
diff --git a/src/theory/strings/theory_strings_preprocess.h b/src/theory/strings/theory_strings_preprocess.h
index 08805fddc..5bc9667ea 100644
--- a/src/theory/strings/theory_strings_preprocess.h
+++ b/src/theory/strings/theory_strings_preprocess.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_strings_preprocess.h
** \verbatim
- ** Original author: Tianyi Liang
- ** Major contributors: Morgan Deters, Andrew Reynolds
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Strings Preprocess
**
diff --git a/src/theory/strings/theory_strings_rewriter.cpp b/src/theory/strings/theory_strings_rewriter.cpp
index 733471288..75243b84d 100644
--- a/src/theory/strings/theory_strings_rewriter.cpp
+++ b/src/theory/strings/theory_strings_rewriter.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_strings_rewriter.cpp
** \verbatim
- ** Original author: Tianyi Liang
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Tianyi Liang, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of the theory of strings.
**
diff --git a/src/theory/strings/theory_strings_rewriter.h b/src/theory/strings/theory_strings_rewriter.h
index f8b420904..59588eda2 100644
--- a/src/theory/strings/theory_strings_rewriter.h
+++ b/src/theory/strings/theory_strings_rewriter.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_strings_rewriter.h
** \verbatim
- ** Original author: Tianyi Liang
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Tianyi Liang, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/strings/theory_strings_type_rules.h b/src/theory/strings/theory_strings_type_rules.h
index aff033338..eae993545 100644
--- a/src/theory/strings/theory_strings_type_rules.h
+++ b/src/theory/strings/theory_strings_type_rules.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_strings_type_rules.h
** \verbatim
- ** Original author: Tianyi Liang
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Tianyi Liang, Tim King, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Typing and cardinality rules for the theory of arrays
**
@@ -239,7 +239,7 @@ class RegExpConstantTypeRule {
public:
inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
throw (TypeCheckingExceptionPrivate, AssertionException) {
- return nodeManager->regexpType();
+ return nodeManager->regExpType();
}
};
@@ -262,7 +262,7 @@ public:
throw TypeCheckingExceptionPrivate(n, "expecting at least 2 terms in regexp concat");
}
}
- return nodeManager->regexpType();
+ return nodeManager->regExpType();
}
};
@@ -280,7 +280,7 @@ public:
}
}
}
- return nodeManager->regexpType();
+ return nodeManager->regExpType();
}
};
@@ -298,7 +298,7 @@ public:
}
}
}
- return nodeManager->regexpType();
+ return nodeManager->regExpType();
}
};
@@ -312,7 +312,7 @@ public:
throw TypeCheckingExceptionPrivate(n, "expecting regexp terms");
}
}
- return nodeManager->regexpType();
+ return nodeManager->regExpType();
}
};
@@ -326,7 +326,7 @@ public:
throw TypeCheckingExceptionPrivate(n, "expecting regexp terms");
}
}
- return nodeManager->regexpType();
+ return nodeManager->regExpType();
}
};
@@ -340,7 +340,7 @@ public:
throw TypeCheckingExceptionPrivate(n, "expecting regexp terms");
}
}
- return nodeManager->regexpType();
+ return nodeManager->regExpType();
}
};
@@ -373,7 +373,7 @@ public:
throw TypeCheckingExceptionPrivate(n, "expecting standard ASCII characters in regexp range, or please set the option strings-std-ascii to be false");
}
}
- return nodeManager->regexpType();
+ return nodeManager->regExpType();
}
};
@@ -409,7 +409,7 @@ public:
//}
}
}
- return nodeManager->regexpType();
+ return nodeManager->regExpType();
}
};
@@ -426,7 +426,7 @@ public:
// throw TypeCheckingExceptionPrivate(n, "expecting constant string terms");
//}
}
- return nodeManager->regexpType();
+ return nodeManager->regExpType();
}
};
@@ -456,7 +456,7 @@ public:
throw (TypeCheckingExceptionPrivate, AssertionException) {
Assert(n.getKind() == kind::REGEXP_EMPTY);
- return nodeManager->regexpType();
+ return nodeManager->regExpType();
}
};
@@ -466,7 +466,7 @@ public:
throw (TypeCheckingExceptionPrivate, AssertionException) {
Assert(n.getKind() == kind::REGEXP_SIGMA);
- return nodeManager->regexpType();
+ return nodeManager->regExpType();
}
};
@@ -480,7 +480,7 @@ public:
throw TypeCheckingExceptionPrivate(n, "expecting an integer term in RV");
}
}
- return nodeManager->regexpType();
+ return nodeManager->regExpType();
}
};
diff --git a/src/theory/strings/type_enumerator.h b/src/theory/strings/type_enumerator.h
index bdaa683c1..1fe3d79f6 100644
--- a/src/theory/strings/type_enumerator.h
+++ b/src/theory/strings/type_enumerator.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file type_enumerator.h
** \verbatim
- ** Original author: Tianyi Liang
- ** Major contributors: none
- ** Minor contributors (to current version): Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Tianyi Liang, Tim King, Andrew Reynolds
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Enumerators for strings
**
diff --git a/src/theory/substitutions.cpp b/src/theory/substitutions.cpp
index af517dcf3..7dbfb2678 100644
--- a/src/theory/substitutions.cpp
+++ b/src/theory/substitutions.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file substitutions.cpp
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Morgan Deters, Clark Barrett
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Clark Barrett, Dejan Jovanovic, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief A substitution mapping for theory simplification
**
diff --git a/src/theory/substitutions.h b/src/theory/substitutions.h
index a4fd490c2..019fbd17e 100644
--- a/src/theory/substitutions.h
+++ b/src/theory/substitutions.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file substitutions.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Clark Barrett, Dejan Jovanovic
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Dejan Jovanovic, Clark Barrett
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief A substitution mapping for theory simplification
**
diff --git a/src/theory/term_registration_visitor.cpp b/src/theory/term_registration_visitor.cpp
index 2aa00a177..830e7f809 100644
--- a/src/theory/term_registration_visitor.cpp
+++ b/src/theory/term_registration_visitor.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file term_registration_visitor.cpp
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): Tim King, Clark Barrett, Morgan Deters
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Andrew Reynolds, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** [[ Add lengthier description here ]]
** \todo document this file
diff --git a/src/theory/term_registration_visitor.h b/src/theory/term_registration_visitor.h
index a14b7a1ba..6d04910f6 100644
--- a/src/theory/term_registration_visitor.h
+++ b/src/theory/term_registration_visitor.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file term_registration_visitor.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** [[ Add lengthier description here ]]
** \todo document this file
diff --git a/src/theory/theory.cpp b/src/theory/theory.cpp
index ee5efc8db..7e2b6df55 100644
--- a/src/theory/theory.cpp
+++ b/src/theory/theory.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory.cpp
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Clark Barrett, Dejan Jovanovic, Tim King
- ** Minor contributors (to current version): Kshitij Bansal, Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Tim King, Dejan Jovanovic, Clark Barrett
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Base for theory interface.
**
@@ -231,7 +231,7 @@ void Theory::collectTerms(TNode n, set<Node>& termSet) const
}
-void Theory::computeRelevantTerms(set<Node>& termSet) const
+void Theory::computeRelevantTerms(set<Node>& termSet, bool includeShared) const
{
// Collect all terms appearing in assertions
context::CDList<Assertion>::const_iterator assert_it = facts_begin(), assert_it_end = facts_end();
@@ -239,6 +239,8 @@ void Theory::computeRelevantTerms(set<Node>& termSet) const
collectTerms(*assert_it, termSet);
}
+ if (!includeShared) return;
+
// Add terms that are shared terms
context::CDList<TNode>::const_iterator shared_it = shared_terms_begin(), shared_it_end = shared_terms_end();
for (; shared_it != shared_it_end; ++shared_it) {
diff --git a/src/theory/theory.h b/src/theory/theory.h
index c988c9120..382d4cf65 100644
--- a/src/theory/theory.h
+++ b/src/theory/theory.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Tim King, Dejan Jovanovic
- ** Minor contributors (to current version): Francois Bobot, Kshitij Bansal, Martin Brain <>, Clark Barrett, Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Base of the theory interface.
**
@@ -237,7 +237,7 @@ protected:
* termSet. This is used by collectModelInfo to delimit the set of
* terms that should be used when constructing a model
*/
- void computeRelevantTerms(std::set<Node>& termSet) const;
+ void computeRelevantTerms(std::set<Node>& termSet, bool includeShared = true) const;
/**
* Construct a Theory.
@@ -277,7 +277,7 @@ protected:
*
*/
bool d_proofsEnabled;
-
+
/**
* Returns the next assertion in the assertFact() queue.
*
diff --git a/src/theory/theory_engine.cpp b/src/theory/theory_engine.cpp
index 45f7506de..f2231ff7a 100644
--- a/src/theory/theory_engine.cpp
+++ b/src/theory/theory_engine.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_engine.cpp
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Dejan Jovanovic
- ** Minor contributors (to current version): Christopher L. Conway, Tianyi Liang, Kshitij Bansal, Clark Barrett, Liana Hadarean, Andrew Reynolds, Tim King
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief The theory engine
**
@@ -78,24 +78,26 @@ void TheoryEngine::finishInit() {
}
void TheoryEngine::eqNotifyNewClass(TNode t){
- if( d_logicInfo.isQuantified() ){
- d_quantEngine->addTermToDatabase( t );
+ if (d_logicInfo.isQuantified()) {
+ d_quantEngine->eqNotifyNewClass( t );
}
}
void TheoryEngine::eqNotifyPreMerge(TNode t1, TNode t2){
-
+ if (d_logicInfo.isQuantified()) {
+ d_quantEngine->eqNotifyPreMerge( t1, t2 );
+ }
}
void TheoryEngine::eqNotifyPostMerge(TNode t1, TNode t2){
-
+ if (d_logicInfo.isQuantified()) {
+ d_quantEngine->eqNotifyPostMerge( t1, t2 );
+ }
}
void TheoryEngine::eqNotifyDisequal(TNode t1, TNode t2, TNode reason){
- if( d_logicInfo.isQuantified() ){
- if( options::quantConflictFind() ){
- d_quantEngine->getConflictFind()->assertDisequal( t1, t2 );
- }
+ if (d_logicInfo.isQuantified()) {
+ d_quantEngine->eqNotifyDisequal( t1, t2, reason );
}
}
@@ -198,6 +200,7 @@ void TheoryEngine::interrupt() throw(ModalException) {
void TheoryEngine::preRegister(TNode preprocessed) {
+ Debug("theory") << "TheoryEngine::preRegister( " << preprocessed << ")" << std::endl;
if(Dump.isOn("missed-t-propagations")) {
d_possiblePropagations.push_back(preprocessed);
}
@@ -344,6 +347,7 @@ void TheoryEngine::check(Theory::Effort effort) {
if (theory::TheoryTraits<THEORY>::hasCheck && d_logicInfo.isTheoryEnabled(THEORY)) { \
theoryOf(THEORY)->check(effort); \
if (d_inConflict) { \
+ Debug("conflict") << THEORY << " in conflict. " << std::endl; \
break; \
} \
}
@@ -404,6 +408,9 @@ void TheoryEngine::check(Theory::Effort effort) {
// Do the combination
Debug("theory") << "TheoryEngine::check(" << effort << "): running combination" << endl;
combineTheories();
+ if(d_logicInfo.isQuantified()){
+ d_quantEngine->notifyCombineTheories();
+ }
}
}
@@ -418,14 +425,14 @@ void TheoryEngine::check(Theory::Effort effort) {
// must build model at this point
d_curr_model_builder->buildModel(d_curr_model, true);
}
- Trace("theory::assertions-model") << endl;
+ Trace("theory::assertions-model") << endl;
if (Trace.isOn("theory::assertions-model")) {
printAssertions("theory::assertions-model");
}
}
Debug("theory") << "TheoryEngine::check(" << effort << "): done, we are " << (d_inConflict ? "unsat" : "sat") << (d_lemmasAdded ? " with new lemmas" : " with no new lemmas");
- Debug("theory") << ", need check = " << needCheck() << endl;
+ Debug("theory") << ", need check = " << (needCheck() ? "YES" : "NO") << endl;
if(!d_inConflict && Theory::fullEffort(effort) && d_masterEqualityEngine != NULL && !d_lemmasAdded) {
AlwaysAssert(d_masterEqualityEngine->consistent());
@@ -490,7 +497,7 @@ void TheoryEngine::combineTheories() {
// We need to split on it
Debug("combineTheories") << "TheoryEngine::combineTheories(): requesting a split " << endl;
- lemma(equality.orNode(equality.notNode()), RULE_INVALID, false, false, false, carePair.theory);
+ lemma(equality.orNode(equality.notNode()), RULE_INVALID, false, false, false, carePair.theory, carePair.theory);
// This code is supposed to force preference to follow what the theory models already have
// but it doesn't seem to make a big difference - need to explore more -Clark
// if (true) {
@@ -1212,6 +1219,8 @@ Node TheoryEngine::ensureLiteral(TNode n) {
void TheoryEngine::printInstantiations( std::ostream& out ) {
if( d_quantEngine ){
d_quantEngine->printInstantiations( out );
+ }else{
+ out << "Internal error : instantiations not available when quantifiers are not present." << std::endl;
}
}
@@ -1223,6 +1232,15 @@ void TheoryEngine::printSynthSolution( std::ostream& out ) {
}
}
+void TheoryEngine::getInstantiations( std::map< Node, std::vector< Node > >& insts ) {
+ if( d_quantEngine ){
+ d_quantEngine->getInstantiations( insts );
+ }else{
+ Assert( false );
+ }
+}
+
+
static Node mkExplanation(const std::vector<NodeTheoryPair>& explanation) {
std::set<TNode> all;
@@ -1252,8 +1270,7 @@ static Node mkExplanation(const std::vector<NodeTheoryPair>& explanation) {
return conjunction;
}
-
-Node TheoryEngine::getExplanation(TNode node) {
+NodeTheoryPair TheoryEngine::getExplanationAndExplainer(TNode node) {
Debug("theory::explain") << "TheoryEngine::getExplanation(" << node << "): current propagation index = " << d_propagationMapTimestamp << endl;
bool polarity = node.getKind() != kind::NOT;
@@ -1263,12 +1280,16 @@ Node TheoryEngine::getExplanation(TNode node) {
if (!d_logicInfo.isSharingEnabled()) {
Node explanation = theoryOf(atom)->explain(node);
Debug("theory::explain") << "TheoryEngine::getExplanation(" << node << ") => " << explanation << endl;
- return explanation;
+ return NodeTheoryPair(explanation, theoryOf(atom)->getId());
}
// Initial thing to explain
NodeTheoryPair toExplain(node, THEORY_SAT_SOLVER, d_propagationMapTimestamp);
Assert(d_propagationMap.find(toExplain) != d_propagationMap.end());
+
+ NodeTheoryPair nodeExplainerPair = d_propagationMap[toExplain];
+ TheoryId explainer = nodeExplainerPair.theory;
+
// Create the workplace for explanations
std::vector<NodeTheoryPair> explanationVector;
explanationVector.push_back(d_propagationMap[toExplain]);
@@ -1278,7 +1299,11 @@ Node TheoryEngine::getExplanation(TNode node) {
Debug("theory::explain") << "TheoryEngine::getExplanation(" << node << ") => " << explanation << endl;
- return explanation;
+ return NodeTheoryPair(explanation, explainer);
+}
+
+Node TheoryEngine::getExplanation(TNode node) {
+ return getExplanationAndExplainer(node).node;
}
struct AtomsCollect {
@@ -1380,7 +1405,8 @@ theory::LemmaStatus TheoryEngine::lemma(TNode node,
bool negated,
bool removable,
bool preprocess,
- theory::TheoryId atomsTo) {
+ theory::TheoryId atomsTo,
+ theory::TheoryId ownerTheory) {
// For resource-limiting (also does a time check).
// spendResource();
@@ -1406,12 +1432,13 @@ theory::LemmaStatus TheoryEngine::lemma(TNode node,
d_channels->getLemmaOutputChannel()->notifyNewLemma(node.toExpr());
}
+ std::vector<Node> additionalLemmas;
+ IteSkolemMap iteSkolemMap;
+
// Run theory preprocessing, maybe
Node ppNode = preprocess ? this->preprocess(node) : Node(node);
// Remove the ITEs
- std::vector<Node> additionalLemmas;
- IteSkolemMap iteSkolemMap;
additionalLemmas.push_back(ppNode);
d_iteRemover.run(additionalLemmas, iteSkolemMap);
additionalLemmas[0] = theory::Rewriter::rewrite(additionalLemmas[0]);
@@ -1429,10 +1456,10 @@ theory::LemmaStatus TheoryEngine::lemma(TNode node,
}
// assert to prop engine
- d_propEngine->assertLemma(additionalLemmas[0], negated, removable, rule, node);
+ d_propEngine->assertLemma(additionalLemmas[0], negated, removable, rule, ownerTheory, node);
for (unsigned i = 1; i < additionalLemmas.size(); ++ i) {
additionalLemmas[i] = theory::Rewriter::rewrite(additionalLemmas[i]);
- d_propEngine->assertLemma(additionalLemmas[i], false, removable, rule, node);
+ d_propEngine->assertLemma(additionalLemmas[i], false, removable, rule, ownerTheory, node);
}
// WARNING: Below this point don't assume additionalLemmas[0] to be not negated.
@@ -1476,11 +1503,11 @@ void TheoryEngine::conflict(TNode conflict, TheoryId theoryId) {
Node fullConflict = mkExplanation(explanationVector);
Debug("theory::conflict") << "TheoryEngine::conflict(" << conflict << ", " << theoryId << "): full = " << fullConflict << endl;
Assert(properConflict(fullConflict));
- lemma(fullConflict, RULE_CONFLICT, true, true, false, THEORY_LAST);
+ lemma(fullConflict, RULE_CONFLICT, true, true, false, THEORY_LAST, theoryId);
} else {
// When only one theory, the conflict should need no processing
Assert(properConflict(conflict));
- lemma(conflict, RULE_CONFLICT, true, true, false, THEORY_LAST);
+ lemma(conflict, RULE_CONFLICT, true, true, false, THEORY_LAST, theoryId);
}
}
@@ -1718,7 +1745,7 @@ void TheoryEngine::ppUnconstrainedSimp(vector<Node>& assertions)
}
-void TheoryEngine::setUserAttribute(const std::string& attr, Node n, std::vector<Node> node_values, std::string str_value) {
+void TheoryEngine::setUserAttribute(const std::string& attr, Node n, std::vector<Node>& node_values, std::string str_value) {
Trace("te-attr") << "set user attribute " << attr << " " << n << endl;
if( d_attr_handle.find( attr )!=d_attr_handle.end() ){
for( size_t i=0; i<d_attr_handle[attr].size(); i++ ){
diff --git a/src/theory/theory_engine.h b/src/theory/theory_engine.h
index 886aa6863..db94edd7c 100644
--- a/src/theory/theory_engine.h
+++ b/src/theory/theory_engine.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_engine.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Andrew Reynolds, Dejan Jovanovic
- ** Minor contributors (to current version): Christopher L. Conway, Francois Bobot, Kshitij Bansal, Clark Barrett, Liana Hadarean, Tim King
+ ** Top contributors (to current version):
+ ** Morgan Deters, Dejan Jovanovic, Andrew Reynolds
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief The theory engine
**
@@ -59,7 +59,7 @@ struct NodeTheoryPair {
Node node;
theory::TheoryId theory;
size_t timestamp;
- NodeTheoryPair(TNode node, theory::TheoryId theory, size_t timestamp)
+ NodeTheoryPair(TNode node, theory::TheoryId theory, size_t timestamp = 0)
: node(node), theory(theory), timestamp(timestamp) {}
NodeTheoryPair()
: theory(theory::THEORY_LAST) {}
@@ -263,7 +263,7 @@ class TheoryEngine {
{
}
- void safePoint(uint64_t ammount) throw(theory::Interrupted, UnsafeInterruptException, AssertionException) {
+ void safePoint(uint64_t ammount) throw(theory::Interrupted, UnsafeInterruptException, AssertionException) {
spendResource(ammount);
if (d_engine->d_interrupted) {
throw theory::Interrupted();
@@ -294,14 +294,21 @@ class TheoryEngine {
Trace("theory::lemma") << "EngineOutputChannel<" << d_theory << ">::lemma(" << lemma << ")" << std::endl;
++ d_statistics.lemmas;
d_engine->d_outputChannelUsed = true;
- return d_engine->lemma(lemma, rule, false, removable, preprocess, sendAtoms ? d_theory: theory::THEORY_LAST);
+ return d_engine->lemma(lemma, rule, false, removable, preprocess, sendAtoms ? d_theory : theory::THEORY_LAST, d_theory);
}
+ /*theory::LemmaStatus preservedLemma(TNode lemma, bool removable = false, bool preprocess = false) throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException, LogicException) {
+ Trace("theory::lemma") << "EngineOutputChannel<" << d_theory << ">::preservedLemma(" << lemma << ")" << std::endl;
+ ++ d_statistics.lemmas;
+ d_engine->d_outputChannelUsed = true;
+ return d_engine->lemma(lemma, false, removable, preprocess, d_theory);
+ }*/
+
theory::LemmaStatus splitLemma(TNode lemma, bool removable = false) throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException) {
- Trace("theory::lemma") << "EngineOutputChannel<" << d_theory << ">::lemma(" << lemma << ")" << std::endl;
+ Trace("theory::lemma") << "EngineOutputChannel<" << d_theory << ">::splitLemma(" << lemma << ")" << std::endl;
++ d_statistics.lemmas;
d_engine->d_outputChannelUsed = true;
- return d_engine->lemma(lemma, RULE_SPLIT, false, removable, false, d_theory);
+ return d_engine->lemma(lemma, RULE_SPLIT, false, removable, false, d_theory, d_theory);
}
void demandRestart() throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException) {
@@ -448,7 +455,8 @@ class TheoryEngine {
bool negated,
bool removable,
bool preprocess,
- theory::TheoryId atomsTo);
+ theory::TheoryId atomsTo,
+ theory::TheoryId ownerTheory);
/** Enusre that the given atoms are send to the given theory */
void ensureLemmaAtoms(const std::vector<TNode>& atoms, theory::TheoryId theory);
@@ -719,6 +727,12 @@ public:
Node getExplanation(TNode node);
/**
+ * Returns an explanation of the node propagated to the SAT solver and the theory
+ * that propagated it.
+ */
+ NodeTheoryPair getExplanationAndExplainer(TNode node);
+
+ /**
* collect model info
*/
void collectModelInfo( theory::TheoryModel* m, bool fullModel );
@@ -784,6 +798,11 @@ public:
void printSynthSolution( std::ostream& out );
/**
+ * Get instantiations
+ */
+ void getInstantiations( std::map< Node, std::vector< Node > >& insts );
+
+ /**
* Forwards an entailment check according to the given theoryOfMode.
* See theory.h for documentation on entailmentCheck().
*/
@@ -851,7 +870,7 @@ public:
* This function is called when an attribute is set by a user. In SMT-LIBv2 this is done
* via the syntax (! n :attr)
*/
- void setUserAttribute(const std::string& attr, Node n, std::vector<Node> node_values, std::string str_value);
+ void setUserAttribute(const std::string& attr, Node n, std::vector<Node>& node_values, std::string str_value);
/**
* Handle user attribute.
diff --git a/src/theory/theory_model.cpp b/src/theory/theory_model.cpp
index 0eff9bd5d..fa7e497e2 100644
--- a/src/theory/theory_model.cpp
+++ b/src/theory/theory_model.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_model.cpp
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Andrew Reynolds, Clark Barrett
- ** Minor contributors (to current version): Kshitij Bansal, Liana Hadarean, Tim King
+ ** Top contributors (to current version):
+ ** Clark Barrett, Andrew Reynolds, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of model class
**/
@@ -631,7 +631,9 @@ void TheoryEngineModelBuilder::buildModel(Model* m, bool fullModel)
Trace("model-builder") << " Processing Term: " << n << endl;
// Record as rep if this node was specified as a representative
if (tm->d_reps.find(n) != tm->d_reps.end()){
- Assert(rep.isNull());
+ //AJR: I believe this assertion is too strict,
+ // e.g. datatypes may assert representative for two constructor terms that are not in the care graph and are merged during collectModelInfo.
+ //Assert(rep.isNull());
rep = tm->d_reps[n];
Assert(!rep.isNull() );
Trace("model-builder") << " Rep( " << eqc << " ) = " << rep << std::endl;
diff --git a/src/theory/theory_model.h b/src/theory/theory_model.h
index b0952538a..6e4f77336 100644
--- a/src/theory/theory_model.h
+++ b/src/theory/theory_model.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_model.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Andrew Reynolds, Clark Barrett
- ** Minor contributors (to current version): Tim King
+ ** Top contributors (to current version):
+ ** Clark Barrett, Morgan Deters, Andrew Reynolds
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Model class
**/
diff --git a/src/theory/theory_registrar.h b/src/theory/theory_registrar.h
index d04251585..d0e3a5b0d 100644
--- a/src/theory/theory_registrar.h
+++ b/src/theory/theory_registrar.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_registrar.h
** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: Morgan Deters, Tim King
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters, Liana Hadarean
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Class to encapsulate preregistration duties
**
diff --git a/src/theory/theory_test_utils.h b/src/theory/theory_test_utils.h
index 6247833f8..031c51d22 100644
--- a/src/theory/theory_test_utils.h
+++ b/src/theory/theory_test_utils.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_test_utils.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): Andrew Reynolds, Dejan Jovanovic
+ ** Top contributors (to current version):
+ ** Tim King, Morgan Deters, Liana Hadarean
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Common utilities for testing theories
**
diff --git a/src/theory/theory_traits_template.h b/src/theory/theory_traits_template.h
index b0e7010b7..0d2d0b8e2 100644
--- a/src/theory/theory_traits_template.h
+++ b/src/theory/theory_traits_template.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_traits_template.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Dejan Jovanovic, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief A template for the theory_traits.h header, defining various
** (static) aspects of theories
diff --git a/src/theory/type_enumerator.h b/src/theory/type_enumerator.h
index 951967f50..d1318aaa8 100644
--- a/src/theory/type_enumerator.h
+++ b/src/theory/type_enumerator.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file type_enumerator.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: none
- ** Minor contributors (to current version): Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Morgan Deters, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Enumerators for types
**
diff --git a/src/theory/type_enumerator_template.cpp b/src/theory/type_enumerator_template.cpp
index 6f9b565bf..2dfefa1a8 100644
--- a/src/theory/type_enumerator_template.cpp
+++ b/src/theory/type_enumerator_template.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file type_enumerator_template.cpp
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: none
- ** Minor contributors (to current version): Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Morgan Deters, Tim King, Andrew Reynolds
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Enumerators for types
**
diff --git a/src/theory/uf/equality_engine.cpp b/src/theory/uf/equality_engine.cpp
index 0ac5096d2..9b429765e 100644
--- a/src/theory/uf/equality_engine.cpp
+++ b/src/theory/uf/equality_engine.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file equality_engine.cpp
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: none
- ** Minor contributors (to current version): Dejan Jovanovic, Tianyi Liang, Tim King, Francois Bobot, Morgan Deters, Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Guy Katz, Andrew Reynolds
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
@@ -42,7 +42,6 @@ EqualityEngine::Statistics::~Statistics() {
smtStatisticsRegistry()->unregisterStat(&constantTermsCount);
}
-
/**
* Data used in the BFS search through the equality graph.
*/
@@ -94,6 +93,8 @@ void EqualityEngine::init() {
d_trueId = getNodeId(d_true);
d_falseId = getNodeId(d_false);
+
+ d_freshMergeReasonType = eq::NUMBER_OF_MERGE_REASONS;
}
EqualityEngine::~EqualityEngine() throw(AssertionException) {
@@ -157,7 +158,7 @@ void EqualityEngine::setMasterEqualityEngine(EqualityEngine* master) {
}
void EqualityEngine::enqueue(const MergeCandidate& candidate, bool back) {
- Debug("equality") << d_name << "::eq::enqueue(" << d_nodes[candidate.t1Id] << ", " << d_nodes[candidate.t2Id] << ", " << candidate.type << ")" << std::endl;
+ Debug("equality") << d_name << "::eq::enqueue(" << d_nodes[candidate.t1Id] << ", " << d_nodes[candidate.t2Id] << ", " << candidate.type << "). reason: " << candidate.reason << std::endl;
if (back) {
d_propagationQueue.push_back(candidate);
} else {
@@ -390,7 +391,7 @@ const EqualityNode& EqualityEngine::getEqualityNode(EqualityNodeId nodeId) const
return d_equalityNodes[nodeId];
}
-void EqualityEngine::assertEqualityInternal(TNode t1, TNode t2, TNode reason, MergeReasonType pid) {
+void EqualityEngine::assertEqualityInternal(TNode t1, TNode t2, TNode reason, unsigned pid) {
Debug("equality") << d_name << "::eq::addEqualityInternal(" << t1 << "," << t2 << "), pid = " << pid << std::endl;
@@ -408,7 +409,7 @@ void EqualityEngine::assertEqualityInternal(TNode t1, TNode t2, TNode reason, Me
enqueue(MergeCandidate(t1Id, t2Id, pid, reason));
}
-void EqualityEngine::assertPredicate(TNode t, bool polarity, TNode reason, MergeReasonType pid) {
+void EqualityEngine::assertPredicate(TNode t, bool polarity, TNode reason, unsigned pid) {
Debug("equality") << d_name << "::eq::addPredicate(" << t << "," << (polarity ? "true" : "false") << ")" << std::endl;
Assert(t.getKind() != kind::EQUAL, "Use assertEquality instead");
assertEqualityInternal(t, polarity ? d_true : d_false, reason, pid);
@@ -421,7 +422,7 @@ void EqualityEngine::mergePredicates(TNode p, TNode q, TNode reason) {
propagate();
}
-void EqualityEngine::assertEquality(TNode eq, bool polarity, TNode reason, MergeReasonType pid) {
+void EqualityEngine::assertEquality(TNode eq, bool polarity, TNode reason, unsigned pid) {
Debug("equality") << d_name << "::eq::addEquality(" << eq << "," << (polarity ? "true" : "false") << ")" << std::endl;
if (polarity) {
// If two terms are already equal, don't assert anything
@@ -889,7 +890,7 @@ void EqualityEngine::backtrack() {
}
-void EqualityEngine::addGraphEdge(EqualityNodeId t1, EqualityNodeId t2, MergeReasonType type, TNode reason) {
+void EqualityEngine::addGraphEdge(EqualityNodeId t1, EqualityNodeId t2, unsigned type, TNode reason) {
Debug("equality") << d_name << "::eq::addGraphEdge(" << d_nodes[t1] << "," << d_nodes[t2] << "," << reason << ")" << std::endl;
EqualityEdgeId edge = d_equalityEdges.size();
d_equalityEdges.push_back(EqualityEdge(t2, d_equalityGraph[t1], type, reason));
@@ -920,7 +921,7 @@ std::string EqualityEngine::edgesToString(EqualityEdgeId edgeId) const {
}
void EqualityEngine::explainEquality(TNode t1, TNode t2, bool polarity, std::vector<TNode>& equalities, EqProof * eqp) const {
- Debug("equality") << d_name << "::eq::explainEquality(" << t1 << ", " << t2 << ", " << (polarity ? "true" : "false") << ")" << std::endl;
+ Debug("equality") << d_name << "::eq::explainEquality(" << t1 << ", " << t2 << ", " << (polarity ? "true" : "false") << ")" << ", proof = " << (eqp ? "ON" : "OFF") << std::endl;
// The terms must be there already
Assert(hasTerm(t1) && hasTerm(t2));;
@@ -933,13 +934,72 @@ void EqualityEngine::explainEquality(TNode t1, TNode t2, bool polarity, std::vec
// Get the explanation
getExplanation(t1Id, t2Id, equalities, eqp);
} else {
+ if (eqp) {
+ eqp->d_id = eq::MERGED_THROUGH_TRANS;
+ eqp->d_node = d_nodes[t1Id].eqNode(d_nodes[t2Id]).notNode();
+ }
+
// Get the reason for this disequality
EqualityPair pair(t1Id, t2Id);
Assert(d_disequalityReasonsMap.find(pair) != d_disequalityReasonsMap.end(), "Don't ask for stuff I didn't notify you about");
DisequalityReasonRef reasonRef = d_disequalityReasonsMap.find(pair)->second;
+
for (unsigned i = reasonRef.mergesStart; i < reasonRef.mergesEnd; ++ i) {
+
EqualityPair toExplain = d_deducedDisequalityReasons[i];
- getExplanation(toExplain.first, toExplain.second, equalities, eqp);
+ EqProof* eqpc = NULL;
+
+ // If we're constructing a (transitivity) proof, we don't need to include an explanation for x=x.
+ if (eqp && toExplain.first != toExplain.second) {
+ eqpc = new EqProof;
+ }
+
+ getExplanation(toExplain.first, toExplain.second, equalities, eqpc);
+
+ if (eqpc) {
+ Debug("pf::ee") << "Child proof is:" << std::endl;
+ eqpc->debug_print("pf::ee", 1);
+
+ if (eqpc->d_id == eq::MERGED_THROUGH_TRANS) {
+ std::vector<EqProof *> orderedChildren;
+ bool nullCongruenceFound = false;
+ for (unsigned i = 0; i < eqpc->d_children.size(); ++i) {
+ if (eqpc->d_children[i]->d_id==eq::MERGED_THROUGH_CONGRUENCE && eqpc->d_children[i]->d_node.isNull()) {
+
+ // For now, assume there can only be one null congruence child
+ Assert(!nullCongruenceFound);
+ nullCongruenceFound = true;
+
+ Debug("pf::ee") << "Have congruence with empty d_node. Splitting..." << std::endl;
+ orderedChildren.insert(orderedChildren.begin(), eqpc->d_children[i]->d_children[0]);
+ orderedChildren.push_back(eqpc->d_children[i]->d_children[1]);
+ } else {
+ orderedChildren.push_back(eqpc->d_children[i]);
+ }
+ }
+
+ if (nullCongruenceFound) {
+ eqpc->d_children = orderedChildren;
+ Debug("pf::ee") << "Child proof's children have been reordered. It is now:" << std::endl;
+ eqpc->debug_print("pf::ee", 1);
+ }
+ }
+
+ eqp->d_children.push_back(eqpc);
+ }
+ }
+
+ if (eqp) {
+ if(eqp->d_children.size() == 1) {
+ // The transitivity proof has just one child. Simplify.
+ EqProof* temp = eqp->d_children[0];
+ eqp->d_children.clear();
+ *eqp = *temp;
+ delete temp;
+ }
+
+ Debug("pf::ee") << "Disequality explanation final proof: " << std::endl;
+ eqp->debug_print("pf::ee", 1);
}
}
}
@@ -972,7 +1032,12 @@ void EqualityEngine::getExplanation(EqualityNodeId t1Id, EqualityNodeId t2Id, st
// If the nodes are the same, we're done
if (t1Id == t2Id){
if( eqp ) {
- eqp->d_node = ProofManager::currentPM()->mkOp(d_nodes[t1Id]);
+ if ((d_nodes[t1Id].getKind() == kind::BUILTIN) && (d_nodes[t1Id].getConst<Kind>() == kind::SELECT)) {
+ std::vector<Node> no_children;
+ eqp->d_node = NodeManager::currentNM()->mkNode(kind::PARTIAL_SELECT_0, no_children);
+ } else {
+ eqp->d_node = ProofManager::currentPM()->mkOp(d_nodes[t1Id]);
+ }
}
return;
}
@@ -1019,24 +1084,28 @@ void EqualityEngine::getExplanation(EqualityNodeId t1Id, EqualityNodeId t2Id, st
Debug("equality") << d_name << "::eq::getExplanation(): path found: " << std::endl;
- std::vector< EqProof * > eqp_trans;
+ std::vector<EqProof *> eqp_trans;
// Reconstruct the path
do {
// The current node
currentNode = bfsQueue[currentIndex].nodeId;
EqualityNodeId edgeNode = d_equalityEdges[currentEdge].getNodeId();
- MergeReasonType reasonType = d_equalityEdges[currentEdge].getReasonType();
+ unsigned reasonType = d_equalityEdges[currentEdge].getReasonType();
+ Node reason = d_equalityEdges[currentEdge].getReason();
Debug("equality") << d_name << "::eq::getExplanation(): currentEdge = " << currentEdge << ", currentNode = " << currentNode << std::endl;
+ Debug("equality") << d_name << " targetNode = " << d_nodes[edgeNode] << std::endl;
Debug("equality") << d_name << " in currentEdge = (" << d_nodes[currentNode] << "," << d_nodes[edge.getNodeId()] << ")" << std::endl;
+ Debug("equality") << d_name << " reason type = " << reasonType << std::endl;
- EqProof * eqpc = NULL;
- //make child proof if a proof is being constructed
- if( eqp ){
+ EqProof* eqpc = NULL;
+ // Make child proof if a proof is being constructed
+ if (eqp) {
eqpc = new EqProof;
eqpc->d_id = reasonType;
}
+
// Add the actual equality to the vector
switch (reasonType) {
case MERGED_THROUGH_CONGRUENCE: {
@@ -1044,32 +1113,47 @@ void EqualityEngine::getExplanation(EqualityNodeId t1Id, EqualityNodeId t2Id, st
Debug("equality") << d_name << "::eq::getExplanation(): due to congruence, going deeper" << std::endl;
const FunctionApplication& f1 = d_applications[currentNode].original;
const FunctionApplication& f2 = d_applications[edgeNode].original;
+
Debug("equality") << push;
+ Debug("equality") << "Explaining left hand side equalities" << std::endl;
EqProof * eqpc1 = eqpc ? new EqProof : NULL;
getExplanation(f1.a, f2.a, equalities, eqpc1);
+ Debug("equality") << "Explaining right hand side equalities" << std::endl;
EqProof * eqpc2 = eqpc ? new EqProof : NULL;
getExplanation(f1.b, f2.b, equalities, eqpc2);
if( eqpc ){
eqpc->d_children.push_back( eqpc1 );
eqpc->d_children.push_back( eqpc2 );
- Debug("equality-pf") << "Congruence : " << d_nodes[currentNode] << " " << d_nodes[edgeNode] << std::endl;
if( d_nodes[currentNode].getKind()==kind::EQUAL ){
//leave node null for now
eqpc->d_node = Node::null();
- }else{
- Debug("equality-pf") << d_nodes[f1.a] << " / " << d_nodes[f2.a] << ", " << d_nodes[f1.b] << " / " << d_nodes[f2.b] << std::endl;
+ } else {
if(d_nodes[f1.a].getKind() == kind::APPLY_UF ||
d_nodes[f1.a].getKind() == kind::SELECT ||
d_nodes[f1.a].getKind() == kind::STORE) {
eqpc->d_node = d_nodes[f1.a];
} else {
- eqpc->d_node = NodeManager::currentNM()->mkNode(kind::PARTIAL_APPLY_UF, ProofManager::currentPM()->mkOp(d_nodes[f1.a]), d_nodes[f1.b]);
+ if (d_nodes[f1.a].getKind() == kind::BUILTIN && d_nodes[f1.a].getConst<Kind>() == kind::SELECT) {
+ eqpc->d_node = NodeManager::currentNM()->mkNode(kind::PARTIAL_SELECT_1, d_nodes[f1.b]);
+ // The first child is a PARTIAL_SELECT_0.
+ // Give it a child so that we know what kind of (read) it is, when we dump to LFSC.
+ Assert(eqpc->d_children[0]->d_node.getKind() == kind::PARTIAL_SELECT_0);
+ Assert(eqpc->d_children[0]->d_children.size() == 0);
+
+ eqpc->d_children[0]->d_node = NodeManager::currentNM()->mkNode(kind::PARTIAL_SELECT_0,
+ d_nodes[f1.b]);
+ } else {
+ eqpc->d_node = NodeManager::currentNM()->mkNode(kind::PARTIAL_APPLY_UF,
+ ProofManager::currentPM()->mkOp(d_nodes[f1.a]),
+ d_nodes[f1.b]);
+ }
}
}
}
Debug("equality") << pop;
break;
}
+
case MERGED_THROUGH_REFLEXIVITY: {
// x1 == x1
Debug("equality") << d_name << "::eq::getExplanation(): due to reflexivity, going deeper" << std::endl;
@@ -1088,6 +1172,7 @@ void EqualityEngine::getExplanation(EqualityNodeId t1Id, EqualityNodeId t2Id, st
break;
}
+
case MERGED_THROUGH_CONSTANTS: {
// f(c1, ..., cn) = c semantically, we can just ignore it
Debug("equality") << d_name << "::eq::getExplanation(): due to constants, explain the constants" << std::endl;
@@ -1111,23 +1196,41 @@ void EqualityEngine::getExplanation(EqualityNodeId t1Id, EqualityNodeId t2Id, st
}
Debug("equality") << pop;
-
break;
}
+
default: {
// Construct the equality
- Debug("equality") << d_name << "::eq::getExplanation(): adding: " << d_equalityEdges[currentEdge].getReason() << std::endl;
- if( eqpc ){
- if(reasonType == MERGED_THROUGH_EQUALITY) {
- eqpc->d_node = d_equalityEdges[currentEdge].getReason();
+ Debug("equality") << d_name << "::eq::getExplanation(): adding: "
+ << reason << std::endl;
+ Debug("equality") << d_name << "::eq::getExplanation(): reason type = " << reasonType << std::endl;
+
+ Node a = d_nodes[currentNode];
+ Node b = d_nodes[d_equalityEdges[currentEdge].getNodeId()];
+
+ if (eqpc) {
+ //apply proof reconstruction processing (when eqpc is non-null)
+ if (d_pathReconstructionTriggers.find(reasonType) != d_pathReconstructionTriggers.end()) {
+ d_pathReconstructionTriggers.find(reasonType)->second->notify(reasonType, reason, a, b,
+ equalities, eqpc);
+ }
+ if (reasonType == MERGED_THROUGH_EQUALITY) {
+ eqpc->d_node = reason;
} else {
- // theory-specific proof rule
- eqpc->d_node = d_nodes[d_equalityEdges[currentEdge].getNodeId()].eqNode(d_nodes[currentNode]);
- Debug("equality-pf") << "theory eq : " << eqpc->d_node << std::endl;
+ // The LFSC translator prefers (not (= a b)) over (= (= a b) false)
+
+ if (a == NodeManager::currentNM()->mkConst(false)) {
+ eqpc->d_node = b.notNode();
+ } else if (b == NodeManager::currentNM()->mkConst(false)) {
+ eqpc->d_node = a.notNode();
+ } else {
+ eqpc->d_node = b.eqNode(a);
+ }
}
eqpc->d_id = reasonType;
}
- equalities.push_back(d_equalityEdges[currentEdge].getReason());
+
+ equalities.push_back(reason);
break;
}
}
@@ -1137,7 +1240,7 @@ void EqualityEngine::getExplanation(EqualityNodeId t1Id, EqualityNodeId t2Id, st
currentIndex = bfsQueue[currentIndex].previousIndex;
//---from Morgan---
- if(eqpc != NULL && eqpc->d_id == MERGED_THROUGH_REFLEXIVITY) {
+ if (eqpc != NULL && eqpc->d_id == MERGED_THROUGH_REFLEXIVITY) {
if(eqpc->d_node.isNull()) {
Assert(eqpc->d_children.size() == 1);
EqProof *p = eqpc;
@@ -1149,11 +1252,10 @@ void EqualityEngine::getExplanation(EqualityNodeId t1Id, EqualityNodeId t2Id, st
}
//---end from Morgan---
- eqp_trans.push_back( eqpc );
-
+ eqp_trans.push_back(eqpc);
} while (currentEdge != null_id);
- if(eqp) {
+ if (eqp) {
if(eqp_trans.size() == 1) {
*eqp = *eqp_trans[0];
delete eqp_trans[0];
@@ -1162,6 +1264,8 @@ void EqualityEngine::getExplanation(EqualityNodeId t1Id, EqualityNodeId t2Id, st
eqp->d_children.insert( eqp->d_children.end(), eqp_trans.begin(), eqp_trans.end() );
eqp->d_node = NodeManager::currentNM()->mkNode(d_nodes[t1Id].getType().isBoolean() ? kind::IFF : kind::EQUAL, d_nodes[t1Id], d_nodes[t2Id]);
}
+
+ eqp->debug_print("pf::ee", 1);
}
// Done
@@ -1508,7 +1612,7 @@ void EqualityEngine::debugPrintGraph() const {
EqualityEdgeId edgeId = d_equalityGraph[nodeId];
while (edgeId != null_edge) {
const EqualityEdge& edge = d_equalityEdges[edgeId];
- Debug("equality::graph") << " " << d_nodes[edge.getNodeId()] << ":" << edge.getReason();
+ Debug("equality::graph") << " [" << edge.getNodeId() << "] " << d_nodes[edge.getNodeId()] << ":" << edge.getReason();
edgeId = edge.getNext();
}
@@ -1517,17 +1621,19 @@ void EqualityEngine::debugPrintGraph() const {
}
bool EqualityEngine::areEqual(TNode t1, TNode t2) const {
- Debug("equality") << d_name << "::eq::areEqual(" << t1 << "," << t2 << ")" << std::endl;
+ Debug("equality") << d_name << "::eq::areEqual(" << t1 << "," << t2 << ")";
Assert(hasTerm(t1));
Assert(hasTerm(t2));
- return getEqualityNode(t1).getFind() == getEqualityNode(t2).getFind();
+ bool result = getEqualityNode(t1).getFind() == getEqualityNode(t2).getFind();
+ Debug("equality") << (result ? "\t(YES)" : "\t(NO)") << std::endl;
+ return result;
}
bool EqualityEngine::areDisequal(TNode t1, TNode t2, bool ensureProof) const
{
- Debug("equality") << d_name << "::eq::areDisequal(" << t1 << "," << t2 << ")" << std::endl;
+ Debug("equality") << d_name << "::eq::areDisequal(" << t1 << "," << t2 << ")";
// Add the terms
Assert(hasTerm(t1));
@@ -1539,6 +1645,7 @@ bool EqualityEngine::areDisequal(TNode t1, TNode t2, bool ensureProof) const
// If we propagated this disequality we're true
if (hasPropagatedDisequality(t1Id, t2Id)) {
+ Debug("equality") << "\t(YES)" << std::endl;
return true;
}
@@ -1556,6 +1663,7 @@ bool EqualityEngine::areDisequal(TNode t1, TNode t2, bool ensureProof) const
nonConst->d_deducedDisequalityReasons.push_back(EqualityPair(t2Id, t2ClassId));
nonConst->storePropagatedDisequality(THEORY_LAST, t1Id, t2Id);
}
+ Debug("equality") << "\t(YES)" << std::endl;
return true;
}
@@ -1571,6 +1679,7 @@ bool EqualityEngine::areDisequal(TNode t1, TNode t2, bool ensureProof) const
nonConst->d_deducedDisequalityReasons.push_back(EqualityPair(t2Id, original.b));
nonConst->storePropagatedDisequality(THEORY_LAST, t1Id, t2Id);
}
+ Debug("equality") << "\t(YES)" << std::endl;
return true;
}
}
@@ -1587,21 +1696,33 @@ bool EqualityEngine::areDisequal(TNode t1, TNode t2, bool ensureProof) const
nonConst->d_deducedDisequalityReasons.push_back(EqualityPair(t1Id, original.b));
nonConst->storePropagatedDisequality(THEORY_LAST, t1Id, t2Id);
}
+ Debug("equality") << "\t(YES)" << std::endl;
return true;
}
}
// Couldn't deduce dis-equalityReturn whether the terms are disequal
+ Debug("equality") << "\t(NO)" << std::endl;
return false;
}
-size_t EqualityEngine::getSize(TNode t)
-{
+size_t EqualityEngine::getSize(TNode t) {
// Add the term
addTermInternal(t);
return getEqualityNode(getEqualityNode(t).getFind()).getSize();
}
+
+void EqualityEngine::addPathReconstructionTrigger(unsigned trigger, const PathReconstructionNotify* notify) {
+ // Currently we can only inform one callback per trigger
+ Assert(d_pathReconstructionTriggers.find(trigger) == d_pathReconstructionTriggers.end());
+ d_pathReconstructionTriggers[trigger] = notify;
+}
+
+unsigned EqualityEngine::getFreshMergeReasonType() {
+ return d_freshMergeReasonType++;
+}
+
void EqualityEngine::addTriggerTerm(TNode t, TheoryId tag)
{
Debug("equality::trigger") << d_name << "::eq::addTriggerTerm(" << t << ", " << tag << ")" << std::endl;
@@ -2103,10 +2224,9 @@ void EqProof::debug_print( const char * c, unsigned tb ) const{
d_children[i]->debug_print( c, tb+1 );
}
}
- Debug( c ) << ")";
+ Debug( c ) << ")" << std::endl;
}
-
} // Namespace uf
} // Namespace theory
} // Namespace CVC4
diff --git a/src/theory/uf/equality_engine.h b/src/theory/uf/equality_engine.h
index 9cfa16adf..f30f1e8a0 100644
--- a/src/theory/uf/equality_engine.h
+++ b/src/theory/uf/equality_engine.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file equality_engine.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): Tim King, Kshitij Bansal, Dejan Jovanovic, Liana Hadarean, Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Morgan Deters, Guy Katz
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
@@ -140,6 +140,18 @@ public:
void eqNotifyDisequal(TNode t1, TNode t2, TNode reason) { }
};/* class EqualityEngineNotifyNone */
+/**
+ * An interface for equality engine notifications during equality path reconstruction.
+ * Can be used to add theory-specific logic for, e.g., proof construction.
+ */
+class PathReconstructionNotify {
+public:
+
+ virtual ~PathReconstructionNotify() {}
+
+ virtual void notify(unsigned reasonType, Node reason, Node a, Node b,
+ std::vector<TNode>& equalities, EqProof* proof) const = 0;
+};
/**
* Class for keeping an incremental congruence closure over a set of terms. It provides
@@ -218,6 +230,9 @@ private:
/** The map of kinds to be treated as interpreted function applications (for evaluation of constants) */
KindMap d_congruenceKindsInterpreted;
+ /** Objects that need to be notified during equality path reconstruction */
+ std::map<unsigned, const PathReconstructionNotify*> d_pathReconstructionTriggers;
+
/** Map from nodes to their ids */
__gnu_cxx::hash_map<TNode, EqualityNodeId, TNodeHashFunction> d_nodeIds;
@@ -259,6 +274,9 @@ private:
/** Memory for the use-list nodes */
std::vector<UseListNode> d_useListNodes;
+ /** A fresh merge reason type to return upon request */
+ unsigned d_freshMergeReasonType;
+
/**
* We keep a list of asserted equalities. Not among original terms, but
* among the class representatives.
@@ -289,7 +307,7 @@ private:
// The next edge
EqualityEdgeId d_nextId;
// Type of reason for this equality
- MergeReasonType d_mergeType;
+ unsigned d_mergeType;
// Reason of this equality
TNode d_reason;
@@ -298,7 +316,7 @@ private:
EqualityEdge():
d_nodeId(null_edge), d_nextId(null_edge), d_mergeType(MERGED_THROUGH_CONGRUENCE) {}
- EqualityEdge(EqualityNodeId nodeId, EqualityNodeId nextId, MergeReasonType type, TNode reason):
+ EqualityEdge(EqualityNodeId nodeId, EqualityNodeId nextId, unsigned type, TNode reason):
d_nodeId(nodeId), d_nextId(nextId), d_mergeType(type), d_reason(reason) {}
/** Returns the id of the next edge */
@@ -308,7 +326,7 @@ private:
EqualityNodeId getNodeId() const { return d_nodeId; }
/** The reason of this edge */
- MergeReasonType getReasonType() const { return d_mergeType; }
+ unsigned getReasonType() const { return d_mergeType; }
/** The reason of this edge */
TNode getReason() const { return d_reason; }
@@ -333,7 +351,7 @@ private:
std::vector<EqualityEdgeId> d_equalityGraph;
/** Add an edge to the equality graph */
- void addGraphEdge(EqualityNodeId t1, EqualityNodeId t2, MergeReasonType type, TNode reason);
+ void addGraphEdge(EqualityNodeId t1, EqualityNodeId t2, unsigned type, TNode reason);
/** Returns the equality node of the given node */
EqualityNode& getEqualityNode(TNode node);
@@ -505,7 +523,7 @@ private:
/**
* Adds an equality of terms t1 and t2 to the database.
*/
- void assertEqualityInternal(TNode t1, TNode t2, TNode reason, MergeReasonType pid = MERGED_THROUGH_EQUALITY);
+ void assertEqualityInternal(TNode t1, TNode t2, TNode reason, unsigned pid = MERGED_THROUGH_EQUALITY);
/**
* Adds a trigger equality to the database with the trigger node and polarity for notification.
@@ -729,7 +747,7 @@ public:
* asserting the negated predicate
* @param reason the reason to keep for building explanations
*/
- void assertPredicate(TNode p, bool polarity, TNode reason, MergeReasonType pid = MERGED_THROUGH_EQUALITY);
+ void assertPredicate(TNode p, bool polarity, TNode reason, unsigned pid = MERGED_THROUGH_EQUALITY);
/**
* Adds predicate p and q and makes them equal.
@@ -744,7 +762,7 @@ public:
* asserting the negated equality
* @param reason the reason to keep for building explanations
*/
- void assertEquality(TNode eq, bool polarity, TNode reason, MergeReasonType pid = MERGED_THROUGH_EQUALITY);
+ void assertEquality(TNode eq, bool polarity, TNode reason, unsigned pid = MERGED_THROUGH_EQUALITY);
/**
* Returns the current representative of the term t.
@@ -833,6 +851,15 @@ public:
*/
bool consistent() const { return !d_done; }
+ /**
+ * Marks an object for merge type based notification during equality path reconstruction.
+ */
+ void addPathReconstructionTrigger(unsigned trigger, const PathReconstructionNotify* notify);
+
+ /**
+ * Returns a fresh merge reason type tag for the client to use.
+ */
+ unsigned getFreshMergeReasonType();
};
/**
@@ -876,7 +903,7 @@ class EqProof
{
public:
EqProof() : d_id(MERGED_THROUGH_REFLEXIVITY){}
- MergeReasonType d_id;
+ unsigned d_id;
Node d_node;
std::vector< EqProof * > d_children;
void debug_print( const char * c, unsigned tb = 0 ) const;
diff --git a/src/theory/uf/equality_engine_types.h b/src/theory/uf/equality_engine_types.h
index fb1e73575..346aebca7 100644
--- a/src/theory/uf/equality_engine_types.h
+++ b/src/theory/uf/equality_engine_types.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file equality_engine_types.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: none
- ** Minor contributors (to current version): Morgan Deters, Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Andrew Reynolds, Guy Katz
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
@@ -67,14 +67,11 @@ enum MergeReasonType {
MERGED_THROUGH_REFLEXIVITY,
/** Equality was merged to false, due to both sides of equality being a constant */
MERGED_THROUGH_CONSTANTS,
-
/** (for proofs only) Equality was merged due to transitivity */
MERGED_THROUGH_TRANS,
- /** Theory specific proof rules */
- MERGED_ARRAYS_ROW,
- MERGED_ARRAYS_ROW1,
- MERGED_ARRAYS_EXT
+ /** Reason types beyond this constant are theory specific reasons */
+ NUMBER_OF_MERGE_REASONS
};
inline std::ostream& operator << (std::ostream& out, MergeReasonType reason) {
@@ -91,10 +88,10 @@ inline std::ostream& operator << (std::ostream& out, MergeReasonType reason) {
case MERGED_THROUGH_CONSTANTS:
out << "constants disequal";
break;
- // (for proofs only)
case MERGED_THROUGH_TRANS:
out << "transitivity";
break;
+
default:
out << "[theory]";
break;
@@ -108,9 +105,9 @@ inline std::ostream& operator << (std::ostream& out, MergeReasonType reason) {
*/
struct MergeCandidate {
EqualityNodeId t1Id, t2Id;
- MergeReasonType type;
+ unsigned type;
TNode reason;
- MergeCandidate(EqualityNodeId x, EqualityNodeId y, MergeReasonType type, TNode reason)
+ MergeCandidate(EqualityNodeId x, EqualityNodeId y, unsigned type, TNode reason)
: t1Id(x), t2Id(y), type(type), reason(reason)
{}
};
@@ -365,4 +362,3 @@ struct TriggerInfo {
} // namespace eq
} // namespace theory
} // namespace CVC4
-
diff --git a/src/theory/uf/symmetry_breaker.cpp b/src/theory/uf/symmetry_breaker.cpp
index 4f7a2667c..ed5d99bdf 100644
--- a/src/theory/uf/symmetry_breaker.cpp
+++ b/src/theory/uf/symmetry_breaker.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file symmetry_breaker.cpp
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Liana Hadarean, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of algorithm suggested by Deharbe, Fontaine,
** Merz, and Paleo, "Exploiting symmetry in SMT problems," CADE 2011
diff --git a/src/theory/uf/symmetry_breaker.h b/src/theory/uf/symmetry_breaker.h
index 5523c1c0d..b706f340f 100644
--- a/src/theory/uf/symmetry_breaker.h
+++ b/src/theory/uf/symmetry_breaker.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file symmetry_breaker.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: none
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Liana Hadarean, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of algorithm suggested by Deharbe, Fontaine,
** Merz, and Paleo, "Exploiting symmetry in SMT problems," CADE 2011
diff --git a/src/theory/uf/theory_uf.cpp b/src/theory/uf/theory_uf.cpp
index ffb537734..0c7bed773 100644
--- a/src/theory/uf/theory_uf.cpp
+++ b/src/theory/uf/theory_uf.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_uf.cpp
** \verbatim
- ** Original author: Tim King
- ** Major contributors: Morgan Deters, Dejan Jovanovic
- ** Minor contributors (to current version): Clark Barrett, Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Morgan Deters, Andrew Reynolds
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief This is the interface to TheoryUF implementations
**
@@ -105,6 +105,8 @@ void TheoryUF::check(Effort level) {
TNode fact = assertion.assertion;
Debug("uf") << "TheoryUF::check(): processing " << fact << std::endl;
+ Debug("uf") << "Term's theory: " << theory::Theory::theoryOf(fact.toExpr()) << std::endl;
+
if (d_thss != NULL) {
bool isDecision = d_valuation.isSatLiteral(fact) && d_valuation.isDecision(fact);
d_thss->assertNode(fact, isDecision);
@@ -219,9 +221,15 @@ void TheoryUF::explain(TNode literal, std::vector<TNode>& assumptions, eq::EqPro
d_equalityEngine.explainPredicate(atom, polarity, assumptions, pf);
}
if( pf ){
- Debug("uf-pf") << std::endl;
- pf->debug_print("uf-pf");
+ Debug("pf::uf") << std::endl;
+ pf->debug_print("pf::uf");
+ }
+
+ Debug("pf::uf") << "UF: explain( " << literal << " ):" << std::endl << "\t";
+ for (unsigned i = 0; i < assumptions.size(); ++i) {
+ Debug("pf::uf") << assumptions[i] << " ";
}
+ Debug("pf::uf") << std::endl;
}
Node TheoryUF::explain(TNode literal) {
@@ -270,6 +278,7 @@ void TheoryUF::presolve() {
for(vector<Node>::const_iterator i = newClauses.begin();
i != newClauses.end();
++i) {
+ Debug("uf") << "uf: generating a lemma: " << *i << std::endl;
d_out->lemma(*i);
}
}
@@ -521,7 +530,7 @@ void TheoryUF::conflict(TNode a, TNode b) {
} else {
d_conflictNode = explain(a.eqNode(b),pf);
}
- ProofUF * puf = d_proofsEnabled ? new ProofUF( pf ) : NULL;
+ ProofUF* puf = d_proofsEnabled ? new ProofUF( pf ) : NULL;
d_out->conflict(d_conflictNode, puf);
d_conflict = true;
}
diff --git a/src/theory/uf/theory_uf.h b/src/theory/uf/theory_uf.h
index e29b923f9..42a804c09 100644
--- a/src/theory/uf/theory_uf.h
+++ b/src/theory/uf/theory_uf.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_uf.h
** \verbatim
- ** Original author: Tim King
- ** Major contributors: Dejan Jovanovic, Morgan Deters
- ** Minor contributors (to current version): Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Dejan Jovanovic, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief This is the interface to TheoryUF implementations
**
@@ -136,7 +136,7 @@ private:
* Explain a literal, with proof (if "pf" is non-NULL).
*/
Node explain(TNode literal, eq::EqProof* pf);
-
+
/** Literals to propagate */
context::CDList<Node> d_literalsToPropagate;
diff --git a/src/theory/uf/theory_uf_model.cpp b/src/theory/uf/theory_uf_model.cpp
index 6d0123a19..f6568ad7f 100644
--- a/src/theory/uf/theory_uf_model.cpp
+++ b/src/theory/uf/theory_uf_model.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_uf_model.cpp
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of Theory UF Model
**/
diff --git a/src/theory/uf/theory_uf_model.h b/src/theory/uf/theory_uf_model.h
index 970a7d6b3..39e7ee6f0 100644
--- a/src/theory/uf/theory_uf_model.h
+++ b/src/theory/uf/theory_uf_model.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_uf_model.h
** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Morgan Deters, Andrew Reynolds, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Model for Theory UF
**/
diff --git a/src/theory/uf/theory_uf_rewriter.h b/src/theory/uf/theory_uf_rewriter.h
index 82dacb6c2..166d11451 100644
--- a/src/theory/uf/theory_uf_rewriter.h
+++ b/src/theory/uf/theory_uf_rewriter.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_uf_rewriter.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): Clark Barrett
+ ** Top contributors (to current version):
+ ** Morgan Deters, Dejan Jovanovic, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add one-line brief description here ]]
**
diff --git a/src/theory/uf/theory_uf_strong_solver.cpp b/src/theory/uf/theory_uf_strong_solver.cpp
index 3ed1c4d40..ed28cc2fc 100644
--- a/src/theory/uf/theory_uf_strong_solver.cpp
+++ b/src/theory/uf/theory_uf_strong_solver.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_uf_strong_solver.cpp
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): Clark Barrett
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Implementation of theory uf strong solver class
**/
@@ -29,17 +29,44 @@
//#define LAZY_REL_EQC
using namespace std;
-using namespace CVC4;
using namespace CVC4::kind;
using namespace CVC4::context;
-using namespace CVC4::theory;
-using namespace CVC4::theory::uf;
-void StrongSolverTheoryUF::SortModel::Region::addRep( Node n ) {
+
+namespace CVC4 {
+namespace theory {
+namespace uf {
+
+/* These are names are unambigious are we use abbreviations. */
+typedef StrongSolverTheoryUF::SortModel SortModel;
+typedef SortModel::Region Region;
+typedef Region::RegionNodeInfo RegionNodeInfo;
+typedef RegionNodeInfo::DiseqList DiseqList;
+
+Region::Region(SortModel* cf, context::Context* c)
+ : d_cf( cf )
+ , d_testCliqueSize( c, 0 )
+ , d_splitsSize( c, 0 )
+ , d_testClique( c )
+ , d_splits( c )
+ , d_reps_size( c, 0 )
+ , d_total_diseq_external( c, 0 )
+ , d_total_diseq_internal( c, 0 )
+ , d_valid( c, true ) {}
+
+Region::~Region() {
+ for(iterator i = begin(), iend = end(); i != iend; ++i) {
+ RegionNodeInfo* regionNodeInfo = (*i).second;
+ delete regionNodeInfo;
+ }
+ d_nodes.clear();
+}
+
+void Region::addRep( Node n ) {
setRep( n, true );
}
-void StrongSolverTheoryUF::SortModel::Region::takeNode( StrongSolverTheoryUF::SortModel::Region* r, Node n ){
+void Region::takeNode( Region* r, Node n ){
Assert( !hasRep( n ) );
Assert( r->hasRep( n ) );
//add representative
@@ -47,8 +74,8 @@ void StrongSolverTheoryUF::SortModel::Region::takeNode( StrongSolverTheoryUF::So
//take disequalities from r
RegionNodeInfo* rni = r->d_nodes[n];
for( int t=0; t<2; t++ ){
- RegionNodeInfo::DiseqList* del = rni->d_disequalities[t];
- for( NodeBoolMap::iterator it = del->d_disequalities.begin(); it != del->d_disequalities.end(); ++it ){
+ DiseqList* del = rni->get(t);
+ for(DiseqList::iterator it = del->begin(); it != del->end(); ++it ){
if( (*it).second ){
r->setDisequal( n, (*it).first, t, false );
if( t==0 ){
@@ -71,21 +98,22 @@ void StrongSolverTheoryUF::SortModel::Region::takeNode( StrongSolverTheoryUF::So
r->setRep( n, false );
}
-void StrongSolverTheoryUF::SortModel::Region::combine( StrongSolverTheoryUF::SortModel::Region* r ){
+void Region::combine( Region* r ){
//take all nodes from r
- for( std::map< Node, RegionNodeInfo* >::iterator it = r->d_nodes.begin(); it != r->d_nodes.end(); ++it ){
- if( it->second->d_valid ){
+ for(Region::iterator it = r->d_nodes.begin(); it != r->d_nodes.end(); ++it) {
+ if( it->second->valid() ){
setRep( it->first, true );
}
}
- for( std::map< Node, RegionNodeInfo* >::iterator it = r->d_nodes.begin(); it != r->d_nodes.end(); ++it ){
- if( it->second->d_valid ){
+ for(Region::iterator it = r->d_nodes.begin(); it != r->d_nodes.end(); ++it){
+ if( it->second->valid() ){
//take disequalities from r
Node n = it->first;
RegionNodeInfo* rni = it->second;
for( int t=0; t<2; t++ ){
- RegionNodeInfo::DiseqList* del = rni->d_disequalities[t];
- for( NodeBoolMap::iterator it2 = del->d_disequalities.begin(); it2 != del->d_disequalities.end(); ++it2 ){
+ RegionNodeInfo::DiseqList* del = rni->get(t);
+ for( RegionNodeInfo::DiseqList::iterator it2 = del->begin(),
+ it2end = del->end(); it2 != it2end; ++it2 ){
if( (*it2).second ){
if( t==0 && hasRep( (*it2).first ) ){
setDisequal( (*it2).first, n, 0, false );
@@ -103,12 +131,12 @@ void StrongSolverTheoryUF::SortModel::Region::combine( StrongSolverTheoryUF::Sor
}
/** setEqual */
-void StrongSolverTheoryUF::SortModel::Region::setEqual( Node a, Node b ){
+void Region::setEqual( Node a, Node b ){
Assert( hasRep( a ) && hasRep( b ) );
//move disequalities of b over to a
for( int t=0; t<2; t++ ){
- RegionNodeInfo::DiseqList* del = d_nodes[b]->d_disequalities[t];
- for( NodeBoolMap::iterator it = del->d_disequalities.begin(); it != del->d_disequalities.end(); ++it ){
+ DiseqList* del = d_nodes[b]->get(t);
+ for( DiseqList::iterator it = del->begin(); it != del->end(); ++it ){
if( (*it).second ){
Node n = (*it).first;
//get the region that contains the endpoint of the disequality b != ...
@@ -133,12 +161,13 @@ void StrongSolverTheoryUF::SortModel::Region::setEqual( Node a, Node b ){
setRep( b, false );
}
-void StrongSolverTheoryUF::SortModel::Region::setDisequal( Node n1, Node n2, int type, bool valid ){
- //Debug("uf-ss-region-debug") << "set disequal " << n1 << " " << n2 << " " << type << " " << valid << std::endl;
+void Region::setDisequal( Node n1, Node n2, int type, bool valid ){
+ //Debug("uf-ss-region-debug") << "set disequal " << n1 << " " << n2 << " "
+ // << type << " " << valid << std::endl;
//debugPrint("uf-ss-region-debug");
//Assert( isDisequal( n1, n2, type )!=valid );
if( isDisequal( n1, n2, type )!=valid ){ //DO_THIS: make assertion
- d_nodes[ n1 ]->d_disequalities[type]->setDisequal( n2, valid );
+ d_nodes[ n1 ]->get(type)->setDisequal( n2, valid );
if( type==0 ){
d_total_diseq_external = d_total_diseq_external + ( valid ? 1 : -1 );
}else{
@@ -149,7 +178,8 @@ void StrongSolverTheoryUF::SortModel::Region::setDisequal( Node n1, Node n2, int
d_testClique.find( n2 )!=d_testClique.end() && d_testClique[n2] ){
Node eq = NodeManager::currentNM()->mkNode( EQUAL, n1, n2 );
if( d_splits.find( eq )!=d_splits.end() && d_splits[ eq ] ){
- Debug("uf-ss-debug") << "removing split for " << n1 << " " << n2 << std::endl;
+ Debug("uf-ss-debug") << "removing split for " << n1 << " " << n2
+ << std::endl;
d_splits[ eq ] = false;
d_splitsSize = d_splitsSize - 1;
}
@@ -159,20 +189,20 @@ void StrongSolverTheoryUF::SortModel::Region::setDisequal( Node n1, Node n2, int
}
}
-void StrongSolverTheoryUF::SortModel::Region::setRep( Node n, bool valid ){
+void Region::setRep( Node n, bool valid ) {
Assert( hasRep( n )!=valid );
if( valid && d_nodes.find( n )==d_nodes.end() ){
d_nodes[n] = new RegionNodeInfo( d_cf->d_thss->getSatContext() );
}
- d_nodes[n]->d_valid = valid;
+ d_nodes[n]->setValid(valid);
d_reps_size = d_reps_size + ( valid ? 1 : -1 );
//removing a member of the test clique from this region
- if( d_testClique.find( n )!=d_testClique.end() && d_testClique[n] ){
+ if( d_testClique.find( n ) != d_testClique.end() && d_testClique[n] ){
Assert( !valid );
d_testClique[n] = false;
d_testCliqueSize = d_testCliqueSize - 1;
//remove all splits involving n
- for( NodeBoolMap::iterator it = d_splits.begin(); it != d_splits.end(); ++it ){
+ for( split_iterator it = begin_splits(); it != end_splits(); ++it ){
if( (*it).second ){
if( (*it).first[0]==n || (*it).first[1]==n ){
d_splits[ (*it).first ] = false;
@@ -183,33 +213,41 @@ void StrongSolverTheoryUF::SortModel::Region::setRep( Node n, bool valid ){
}
}
-bool StrongSolverTheoryUF::SortModel::Region::isDisequal( Node n1, Node n2, int type ){
- RegionNodeInfo::DiseqList* del = d_nodes[ n1 ]->d_disequalities[type];
- return del->d_disequalities.find( n2 )!=del->d_disequalities.end() && del->d_disequalities[n2];
+bool Region::isDisequal( Node n1, Node n2, int type ) {
+ RegionNodeInfo::DiseqList* del = d_nodes[ n1 ]->get(type);
+ return del->isSet(n2) && del->getDisequalityValue(n2);
}
struct sortInternalDegree {
- StrongSolverTheoryUF::SortModel::Region* r;
- bool operator() (Node i,Node j) { return (r->d_nodes[i]->getNumInternalDisequalities()>r->d_nodes[j]->getNumInternalDisequalities());}
+ Region* r;
+ bool operator() (Node i, Node j) {
+ return (r->getRegionInfo(i)->getNumInternalDisequalities() >
+ r->getRegionInfo(j)->getNumInternalDisequalities());
+ }
};
struct sortExternalDegree {
- StrongSolverTheoryUF::SortModel::Region* r;
- bool operator() (Node i,Node j) { return (r->d_nodes[i]->getNumExternalDisequalities()>r->d_nodes[j]->getNumExternalDisequalities());}
+ Region* r;
+ bool operator() (Node i,Node j) {
+ return (r->getRegionInfo(i)->getNumExternalDisequalities() >
+ r->getRegionInfo(j)->getNumExternalDisequalities());
+ }
};
int gmcCount = 0;
-bool StrongSolverTheoryUF::SortModel::Region::getMustCombine( int cardinality ){
+bool Region::getMustCombine( int cardinality ){
if( options::ufssRegions() && d_total_diseq_external>=unsigned(cardinality) ){
- //The number of external disequalities is greater than or equal to cardinality.
- //Thus, a clique of size cardinality+1 may exist between nodes in d_regions[i] and other regions
- //Check if this is actually the case: must have n nodes with outgoing degree (cardinality+1-n) for some n>0
+ //The number of external disequalities is greater than or equal to
+ //cardinality. Thus, a clique of size cardinality+1 may exist
+ //between nodes in d_regions[i] and other regions Check if this is
+ //actually the case: must have n nodes with outgoing degree
+ //(cardinality+1-n) for some n>0
std::vector< int > degrees;
- for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
+ for( Region::iterator it = begin(); it != end(); ++it ){
RegionNodeInfo* rni = it->second;
- if( rni->d_valid ){
- if( rni->getNumDisequalities()>=cardinality ){
+ if( rni->valid() ){
+ if( rni->getNumDisequalities() >= cardinality ){
int outDeg = rni->getNumExternalDisequalities();
if( outDeg>=cardinality ){
//we have 1 node of degree greater than (cardinality)
@@ -226,7 +264,8 @@ bool StrongSolverTheoryUF::SortModel::Region::getMustCombine( int cardinality ){
}
gmcCount++;
if( gmcCount%100==0 ){
- Trace("gmc-count") << gmcCount << " " << cardinality << " sample : " << degrees.size() << std::endl;
+ Trace("gmc-count") << gmcCount << " " << cardinality
+ << " sample : " << degrees.size() << std::endl;
}
//this should happen relatively infrequently....
std::sort( degrees.begin(), degrees.end() );
@@ -239,13 +278,14 @@ bool StrongSolverTheoryUF::SortModel::Region::getMustCombine( int cardinality ){
return false;
}
-bool StrongSolverTheoryUF::SortModel::Region::check( Theory::Effort level, int cardinality, std::vector< Node >& clique ){
+bool Region::check( Theory::Effort level, int cardinality,
+ std::vector< Node >& clique ) {
if( d_reps_size>unsigned(cardinality) ){
if( d_total_diseq_internal==d_reps_size*( d_reps_size - 1 ) ){
if( d_reps_size>1 ){
//quick clique check, all reps form a clique
- for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
- if( it->second->d_valid ){
+ for( iterator it = begin(); it != end(); ++it ){
+ if( it->second->valid() ){
clique.push_back( it->first );
}
}
@@ -254,15 +294,19 @@ bool StrongSolverTheoryUF::SortModel::Region::check( Theory::Effort level, int c
}else{
return false;
}
- }else if( options::ufssRegions() || options::ufssEagerSplits() || level==Theory::EFFORT_FULL ){
+ }else if( options::ufssRegions() || options::ufssEagerSplits() ||
+ level==Theory::EFFORT_FULL ) {
//build test clique, up to size cardinality+1
if( d_testCliqueSize<=unsigned(cardinality) ){
std::vector< Node > newClique;
if( d_testCliqueSize<unsigned(cardinality) ){
- for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
+ for( iterator it = begin(); it != end(); ++it ){
//if not in the test clique, add it to the set of new members
- if( it->second->d_valid && ( d_testClique.find( it->first )==d_testClique.end() || !d_testClique[ it->first ] ) ){
- //if( it->second->getNumInternalDisequalities()>cardinality || level==Theory::EFFORT_FULL ){
+ if( it->second->valid() &&
+ ( d_testClique.find( it->first ) == d_testClique.end() ||
+ !d_testClique[ it->first ] ) ){
+ //if( it->second->getNumInternalDisequalities()>cardinality ||
+ // level==Theory::EFFORT_FULL ){
newClique.push_back( it->first );
//}
}
@@ -271,14 +315,18 @@ bool StrongSolverTheoryUF::SortModel::Region::check( Theory::Effort level, int c
sortInternalDegree sidObj;
sidObj.r = this;
std::sort( newClique.begin(), newClique.end(), sidObj );
- newClique.erase( newClique.begin() + ( cardinality - d_testCliqueSize ) + 1, newClique.end() );
+ int offset = ( cardinality - d_testCliqueSize ) + 1;
+ newClique.erase( newClique.begin() + offset, newClique.end() );
}else{
//scan for the highest degree
int maxDeg = -1;
Node maxNode;
- for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
+ for( std::map< Node, RegionNodeInfo* >::iterator
+ it = d_nodes.begin(); it != d_nodes.end(); ++it ){
//if not in the test clique, add it to the set of new members
- if( it->second->d_valid && ( d_testClique.find( it->first )==d_testClique.end() || !d_testClique[ it->first ] ) ){
+ if( it->second->valid() &&
+ ( d_testClique.find( it->first )==d_testClique.end() ||
+ !d_testClique[ it->first ] ) ){
if( it->second->getNumInternalDisequalities()>maxDeg ){
maxDeg = it->second->getNumInternalDisequalities();
maxNode = it->first;
@@ -290,18 +338,27 @@ bool StrongSolverTheoryUF::SortModel::Region::check( Theory::Effort level, int c
}
//check splits internal to new members
for( int j=0; j<(int)newClique.size(); j++ ){
- Debug("uf-ss-debug") << "Choose to add clique member " << newClique[j] << std::endl;
+ Debug("uf-ss-debug") << "Choose to add clique member "
+ << newClique[j] << std::endl;
for( int k=(j+1); k<(int)newClique.size(); k++ ){
if( !isDisequal( newClique[j], newClique[k], 1 ) ){
- d_splits[ NodeManager::currentNM()->mkNode( EQUAL, newClique[j], newClique[k] ) ] = true;
+ Node at_j = newClique[j];
+ Node at_k = newClique[k];
+ Node j_eq_k =
+ NodeManager::currentNM()->mkNode( EQUAL, at_j, at_k );
+ d_splits[ j_eq_k ] = true;
d_splitsSize = d_splitsSize + 1;
}
}
//check disequalities with old members
- for( NodeBoolMap::iterator it = d_testClique.begin(); it != d_testClique.end(); ++it ){
+ for( NodeBoolMap::iterator it = d_testClique.begin();
+ it != d_testClique.end(); ++it ){
if( (*it).second ){
if( !isDisequal( (*it).first, newClique[j], 1 ) ){
- d_splits[ NodeManager::currentNM()->mkNode( EQUAL, (*it).first, newClique[j] ) ] = true;
+ Node at_it = (*it).first;
+ Node at_j = newClique[j];
+ Node it_eq_j = at_it.eqNode(at_j);
+ d_splits[ it_eq_j ] = true;
d_splitsSize = d_splitsSize + 1;
}
}
@@ -313,10 +370,12 @@ bool StrongSolverTheoryUF::SortModel::Region::check( Theory::Effort level, int c
d_testCliqueSize = d_testCliqueSize + 1;
}
}
- //check if test clique has larger size than cardinality, and forms a clique
- if( d_testCliqueSize>=unsigned(cardinality+1) && d_splitsSize==0 ){
+ // Check if test clique has larger size than cardinality, and
+ // forms a clique.
+ if( d_testCliqueSize >= unsigned(cardinality+1) && d_splitsSize==0 ){
//test clique is a clique
- for( NodeBoolMap::iterator it = d_testClique.begin(); it != d_testClique.end(); ++it ){
+ for( NodeBoolMap::iterator it = d_testClique.begin();
+ it != d_testClique.end(); ++it ){
if( (*it).second ){
clique.push_back( (*it).first );
}
@@ -328,10 +387,12 @@ bool StrongSolverTheoryUF::SortModel::Region::check( Theory::Effort level, int c
return false;
}
-bool StrongSolverTheoryUF::SortModel::Region::getCandidateClique( int cardinality, std::vector< Node >& clique ) {
+bool Region::getCandidateClique( int cardinality, std::vector< Node >& clique )
+{
if( d_testCliqueSize>=unsigned(cardinality+1) ){
//test clique is a clique
- for( NodeBoolMap::iterator it = d_testClique.begin(); it != d_testClique.end(); ++it ){
+ for( NodeBoolMap::iterator it = d_testClique.begin();
+ it != d_testClique.end(); ++it ){
if( (*it).second ){
clique.push_back( (*it).first );
}
@@ -341,12 +402,13 @@ bool StrongSolverTheoryUF::SortModel::Region::getCandidateClique( int cardinalit
return false;
}
-void StrongSolverTheoryUF::SortModel::Region::getNumExternalDisequalities( std::map< Node, int >& num_ext_disequalities ){
- for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
+void Region::getNumExternalDisequalities(
+ std::map< Node, int >& num_ext_disequalities ){
+ for( Region::iterator it = begin(); it != end(); ++it ){
RegionNodeInfo* rni = it->second;
- if( rni->d_valid ){
- RegionNodeInfo::DiseqList* del = rni->d_disequalities[0];
- for( NodeBoolMap::iterator it2 = del->d_disequalities.begin(); it2 != del->d_disequalities.end(); ++it2 ){
+ if( rni->valid() ){
+ DiseqList* del = rni->get(0);
+ for( DiseqList::iterator it2 = del->begin(); it2 != del->end(); ++it2 ){
if( (*it2).second ){
num_ext_disequalities[ (*it2).first ]++;
}
@@ -355,32 +417,35 @@ void StrongSolverTheoryUF::SortModel::Region::getNumExternalDisequalities( std::
}
}
-void StrongSolverTheoryUF::SortModel::Region::debugPrint( const char* c, bool incClique ){
+void Region::debugPrint( const char* c, bool incClique ) {
Debug( c ) << "Num reps: " << d_reps_size << std::endl;
- for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
+ for( Region::iterator it = begin(); it != end(); ++it ){
RegionNodeInfo* rni = it->second;
- if( rni->d_valid ){
+ if( rni->valid() ){
Node n = it->first;
Debug( c ) << " " << n << std::endl;
for( int i=0; i<2; i++ ){
Debug( c ) << " " << ( i==0 ? "Ext" : "Int" ) << " disequal:";
- RegionNodeInfo::DiseqList* del = rni->d_disequalities[i];
- for( NodeBoolMap::iterator it2 = del->d_disequalities.begin(); it2 != del->d_disequalities.end(); ++it2 ){
+ DiseqList* del = rni->get(i);
+ for( DiseqList::iterator it2 = del->begin(); it2 != del->end(); ++it2 ){
if( (*it2).second ){
Debug( c ) << " " << (*it2).first;
}
}
- Debug( c ) << ", total = " << del->d_size << std::endl;
+ Debug( c ) << ", total = " << del->size() << std::endl;
}
}
}
- Debug( c ) << "Total disequal: " << d_total_diseq_external << " external," << std::endl;
- Debug( c ) << " " << d_total_diseq_internal<< " internal." << std::endl;
+ Debug( c ) << "Total disequal: " << d_total_diseq_external << " external,"
+ << std::endl;
+ Debug( c ) << " " << d_total_diseq_internal << " internal."
+ << std::endl;
if( incClique ){
Debug( c ) << "Candidate clique members: " << std::endl;
Debug( c ) << " ";
- for( NodeBoolMap::iterator it = d_testClique.begin(); it != d_testClique.end(); ++ it ){
+ for( NodeBoolMap::iterator it = d_testClique.begin();
+ it != d_testClique.end(); ++ it ){
if( (*it).second ){
Debug( c ) << (*it).first << " ";
}
@@ -388,7 +453,8 @@ void StrongSolverTheoryUF::SortModel::Region::debugPrint( const char* c, bool in
Debug( c ) << ", size = " << d_testCliqueSize << std::endl;
Debug( c ) << "Required splits: " << std::endl;
Debug( c ) << " ";
- for( NodeBoolMap::iterator it = d_splits.begin(); it != d_splits.end(); ++ it ){
+ for( NodeBoolMap::iterator it = d_splits.begin(); it != d_splits.end();
+ ++ it ){
if( (*it).second ){
Debug( c ) << (*it).first << " ";
}
@@ -397,17 +463,25 @@ void StrongSolverTheoryUF::SortModel::Region::debugPrint( const char* c, bool in
}
}
-
-
-
-
-
-
-
-StrongSolverTheoryUF::SortModel::SortModel( Node n, context::Context* c, context::UserContext* u, StrongSolverTheoryUF* thss ) : d_type( n.getType() ),
- d_thss( thss ), d_regions_index( c, 0 ), d_regions_map( c ), d_split_score( c ), d_disequalities_index( c, 0 ),
- d_reps( c, 0 ), d_conflict( c, false ), d_cardinality( c, 1 ), d_aloc_cardinality( u, 0 ),
- d_cardinality_assertions( c ), d_hasCard( c, false ), d_maxNegCard( c, 0 ), d_initialized( u, false ), d_lemma_cache( u ){
+SortModel::SortModel( Node n,
+ context::Context* c,
+ context::UserContext* u,
+ StrongSolverTheoryUF* thss )
+ : d_type( n.getType() )
+ , d_thss( thss )
+ , d_regions_index( c, 0 )
+ , d_regions_map( c )
+ , d_split_score( c )
+ , d_disequalities_index( c, 0 )
+ , d_reps( c, 0 )
+ , d_conflict( c, false )
+ , d_cardinality( c, 1 )
+ , d_aloc_cardinality( u, 0 )
+ , d_hasCard( c, false )
+ , d_maxNegCard( c, 0 )
+ , d_initialized( u, false )
+ , d_lemma_cache( u )
+{
d_cardinality_term = n;
//if( d_type.isSort() ){
// TypeEnumerator te(tn);
@@ -417,8 +491,17 @@ StrongSolverTheoryUF::SortModel::SortModel( Node n, context::Context* c, context
//}
}
+SortModel::~SortModel() {
+ for(std::vector<Region*>::iterator i = d_regions.begin();
+ i != d_regions.end(); ++i) {
+ Region* region = *i;
+ delete region;
+ }
+ d_regions.clear();
+}
+
/** initialize */
-void StrongSolverTheoryUF::SortModel::initialize( OutputChannel* out ){
+void SortModel::initialize( OutputChannel* out ){
if( !d_initialized ){
d_initialized = true;
allocateCardinality( out );
@@ -426,17 +509,20 @@ void StrongSolverTheoryUF::SortModel::initialize( OutputChannel* out ){
}
/** new node */
-void StrongSolverTheoryUF::SortModel::newEqClass( Node n ){
+void SortModel::newEqClass( Node n ){
if( !d_conflict ){
if( d_regions_map.find( n )==d_regions_map.end() ){
- //must generate totality axioms for every cardinality we have allocated thus far
- for( std::map< int, Node >::iterator it = d_cardinality_literal.begin(); it != d_cardinality_literal.end(); ++it ){
+ // Must generate totality axioms for every cardinality we have
+ // allocated thus far.
+ for( std::map< int, Node >::iterator it = d_cardinality_literal.begin();
+ it != d_cardinality_literal.end(); ++it ){
if( applyTotality( it->first ) ){
addTotalityAxiom( n, it->first, &d_thss->getOutputChannel() );
}
}
if( options::ufssTotality() ){
- //regions map will store whether we need to equate this term with a constant equivalence class
+ // Regions map will store whether we need to equate this term
+ // with a constant equivalence class.
if( std::find( d_totality_terms[0].begin(), d_totality_terms[0].end(), n )==d_totality_terms[0].end() ){
d_regions_map[n] = 0;
}else{
@@ -444,16 +530,20 @@ void StrongSolverTheoryUF::SortModel::newEqClass( Node n ){
}
}else{
if( !options::ufssRegions() ){
- //if not using regions, always add new equivalence classes to region index = 0
+ // If not using regions, always add new equivalence classes
+ // to region index = 0.
d_regions_index = 0;
}
d_regions_map[n] = d_regions_index;
- Debug("uf-ss") << "StrongSolverTheoryUF: New Eq Class " << n << std::endl;
- Debug("uf-ss-debug") << d_regions_index << " " << (int)d_regions.size() << std::endl;
+ Debug("uf-ss") << "StrongSolverTheoryUF: New Eq Class " << n
+ << std::endl;
+ Debug("uf-ss-debug") << d_regions_index << " "
+ << (int)d_regions.size() << std::endl;
if( d_regions_index<d_regions.size() ){
d_regions[ d_regions_index ]->debugPrint("uf-ss-debug",true);
- d_regions[ d_regions_index ]->d_valid = true;
- Assert( !options::ufssRegions() || d_regions[ d_regions_index ]->getNumReps()==0 );
+ d_regions[ d_regions_index ]->setValid(true);
+ Assert( !options::ufssRegions() ||
+ d_regions[ d_regions_index ]->getNumReps()==0 );
}else{
d_regions.push_back( new Region( this, d_thss->getSatContext() ) );
}
@@ -466,7 +556,7 @@ void StrongSolverTheoryUF::SortModel::newEqClass( Node n ){
}
/** merge */
-void StrongSolverTheoryUF::SortModel::merge( Node a, Node b ){
+void SortModel::merge( Node a, Node b ){
if( !d_conflict ){
if( options::ufssTotality() ){
if( d_regions_map[b]==-1 ){
@@ -476,7 +566,8 @@ void StrongSolverTheoryUF::SortModel::merge( Node a, Node b ){
}else{
//Assert( a==d_th->d_equalityEngine.getRepresentative( a ) );
//Assert( b==d_th->d_equalityEngine.getRepresentative( b ) );
- Debug("uf-ss") << "StrongSolverTheoryUF: Merging " << a << " = " << b << "..." << std::endl;
+ Debug("uf-ss") << "StrongSolverTheoryUF: Merging "
+ << a << " = " << b << "..." << std::endl;
if( a!=b ){
Assert( d_regions_map.find( a )!=d_regions_map.end() );
Assert( d_regions_map.find( b )!=d_regions_map.end() );
@@ -493,10 +584,15 @@ void StrongSolverTheoryUF::SortModel::merge( Node a, Node b ){
d_regions[ri]->setEqual( a, b );
checkRegion( ri );
}else{
- // either move a to d_regions[bi], or b to d_regions[ai]
- int aex = d_regions[ai]->d_nodes[a]->getNumInternalDisequalities() - getNumDisequalitiesToRegion( a, bi );
- int bex = d_regions[bi]->d_nodes[b]->getNumInternalDisequalities() - getNumDisequalitiesToRegion( b, ai );
- //based on which would produce the fewest number of external disequalities
+ // Either move a to d_regions[bi], or b to d_regions[ai].
+ RegionNodeInfo* a_region_info = d_regions[ai]->getRegionInfo(a);
+ RegionNodeInfo* b_region_info = d_regions[bi]->getRegionInfo(b);
+ int aex = ( a_region_info->getNumInternalDisequalities() -
+ getNumDisequalitiesToRegion( a, bi ) );
+ int bex = ( b_region_info->getNumInternalDisequalities() -
+ getNumDisequalitiesToRegion( b, ai ) );
+ // Based on which would produce the fewest number of
+ // external disequalities.
if( aex<bex ){
moveNode( a, bi );
d_regions[bi]->setEqual( a, b );
@@ -529,7 +625,7 @@ void StrongSolverTheoryUF::SortModel::merge( Node a, Node b ){
}
/** assert terms are disequal */
-void StrongSolverTheoryUF::SortModel::assertDisequal( Node a, Node b, Node reason ){
+void SortModel::assertDisequal( Node a, Node b, Node reason ){
if( !d_conflict ){
if( options::ufssTotality() ){
//do nothing
@@ -584,7 +680,7 @@ void StrongSolverTheoryUF::SortModel::assertDisequal( Node a, Node b, Node reaso
}
}
-bool StrongSolverTheoryUF::SortModel::areDisequal( Node a, Node b ) {
+bool SortModel::areDisequal( Node a, Node b ) {
Assert( a == d_thss->getTheory()->d_equalityEngine.getRepresentative( a ) );
Assert( b == d_thss->getTheory()->d_equalityEngine.getRepresentative( b ) );
if( d_regions_map.find( a )!=d_regions_map.end() &&
@@ -598,7 +694,7 @@ bool StrongSolverTheoryUF::SortModel::areDisequal( Node a, Node b ) {
}
/** check */
-void StrongSolverTheoryUF::SortModel::check( Theory::Effort level, OutputChannel* out ){
+void SortModel::check( Theory::Effort level, OutputChannel* out ){
if( level>=Theory::EFFORT_STANDARD && d_hasCard && !d_conflict ){
Debug("uf-ss") << "StrongSolverTheoryUF: Check " << level << " " << d_type << std::endl;
//Notice() << "StrongSolverTheoryUF: Check " << level << std::endl;
@@ -616,7 +712,7 @@ void StrongSolverTheoryUF::SortModel::check( Theory::Effort level, OutputChannel
if( !options::ufssTotality() ){
//do a check within each region
for( int i=0; i<(int)d_regions_index; i++ ){
- if( d_regions[i]->d_valid ){
+ if( d_regions[i]->valid() ){
std::vector< Node > clique;
if( d_regions[i]->check( level, d_cardinality, clique ) ){
if( options::ufssMode()==UF_SS_FULL ){
@@ -637,7 +733,7 @@ void StrongSolverTheoryUF::SortModel::check( Theory::Effort level, OutputChannel
Trace("uf-ss-debug") << "Add splits?" << std::endl;
//see if we have any recommended splits from large regions
for( int i=0; i<(int)d_regions_index; i++ ){
- if( d_regions[i]->d_valid && d_regions[i]->getNumReps()>d_cardinality ){
+ if( d_regions[i]->valid() && d_regions[i]->getNumReps()>d_cardinality ){
//just add the clique lemma
if( level==Theory::EFFORT_FULL && options::ufssCliqueSplits() ){
std::vector< Node > clique;
@@ -661,18 +757,19 @@ void StrongSolverTheoryUF::SortModel::check( Theory::Effort level, OutputChannel
}
}
}
- //if no added lemmas, force continuation via combination of regions
+ //If no added lemmas, force continuation via combination of regions.
if( level==Theory::EFFORT_FULL ){
if( !addedLemma ){
- Trace("uf-ss-debug") << "No splits added. " << d_cardinality << std::endl;
+ Trace("uf-ss-debug") << "No splits added. " << d_cardinality
+ << std::endl;
Trace("uf-ss-si") << "Must combine region" << std::endl;
bool recheck = false;
if( options::sortInference()){
- //if sort inference is enabled, search for regions with same sort
+ //If sort inference is enabled, search for regions with same sort.
std::map< int, int > sortsFound;
for( int i=0; i<(int)d_regions_index; i++ ){
- if( d_regions[i]->d_valid ){
- Node op = d_regions[i]->d_nodes.begin()->first;
+ if( d_regions[i]->valid() ){
+ Node op = d_regions[i]->frontKey();
int sort_id = d_thss->getSortInference()->getSortId(op);
if( sortsFound.find( sort_id )!=sortsFound.end() ){
combineRegions( sortsFound[sort_id], i );
@@ -687,7 +784,7 @@ void StrongSolverTheoryUF::SortModel::check( Theory::Effort level, OutputChannel
if( !recheck ) {
//naive strategy, force region combination involving the first valid region
for( int i=0; i<(int)d_regions_index; i++ ){
- if( d_regions[i]->d_valid ){
+ if( d_regions[i]->valid() ){
int fcr = forceCombineRegion( i, false );
Trace("uf-ss-debug") << "Combined regions " << i << " " << fcr << std::endl;
if( options::ufssMode()==UF_SS_FULL || fcr!=-1 ){
@@ -708,26 +805,28 @@ void StrongSolverTheoryUF::SortModel::check( Theory::Effort level, OutputChannel
}
}
-void StrongSolverTheoryUF::SortModel::presolve() {
+void SortModel::presolve() {
d_initialized = false;
d_aloc_cardinality = 0;
}
-void StrongSolverTheoryUF::SortModel::propagate( Theory::Effort level, OutputChannel* out ){
+void SortModel::propagate( Theory::Effort level, OutputChannel* out ){
}
-Node StrongSolverTheoryUF::SortModel::getNextDecisionRequest(){
+Node SortModel::getNextDecisionRequest(){
//request the current cardinality as a decision literal, if not already asserted
for( int i=1; i<=d_aloc_cardinality; i++ ){
if( !d_hasCard || i<d_cardinality ){
Node cn = d_cardinality_literal[ i ];
Assert( !cn.isNull() );
- if( d_cardinality_assertions.find( cn )==d_cardinality_assertions.end() ){
+ bool value;
+ if( !d_thss->getTheory()->d_valuation.hasSatValue( cn, value ) ){
Trace("uf-ss-dec") << "UFSS : Get next decision " << d_type << " " << i << std::endl;
return cn;
}else{
- Trace("uf-ss-dec-debug") << " dec : " << cn << " already asserted " << d_cardinality_assertions[cn].get() << std::endl;
+ Trace("uf-ss-dec-debug") << " dec : " << cn << " already asserted " << value << std::endl;
+ Assert( !value );
}
}
}
@@ -737,7 +836,7 @@ Node StrongSolverTheoryUF::SortModel::getNextDecisionRequest(){
return Node::null();
}
-bool StrongSolverTheoryUF::SortModel::minimize( OutputChannel* out, TheoryModel* m ){
+bool SortModel::minimize( OutputChannel* out, TheoryModel* m ){
if( options::ufssTotality() ){
//do nothing
}else{
@@ -774,7 +873,7 @@ bool StrongSolverTheoryUF::SortModel::minimize( OutputChannel* out, TheoryModel*
// if two equivalence classes are neither equal nor disequal, add a split
int validRegionIndex = -1;
for( int i=0; i<(int)d_regions_index; i++ ){
- if( d_regions[i]->d_valid ){
+ if( d_regions[i]->valid() ){
if( validRegionIndex!=-1 ){
combineRegions( validRegionIndex, i );
if( addSplit( d_regions[validRegionIndex], out )!=0 ){
@@ -798,11 +897,11 @@ bool StrongSolverTheoryUF::SortModel::minimize( OutputChannel* out, TheoryModel*
}
-int StrongSolverTheoryUF::SortModel::getNumDisequalitiesToRegion( Node n, int ri ){
+int SortModel::getNumDisequalitiesToRegion( Node n, int ri ){
int ni = d_regions_map[n];
int counter = 0;
- Region::RegionNodeInfo::DiseqList* del = d_regions[ni]->d_nodes[n]->d_disequalities[0];
- for( NodeBoolMap::iterator it = del->d_disequalities.begin(); it != del->d_disequalities.end(); ++it ){
+ DiseqList* del = d_regions[ni]->getRegionInfo(n)->get(0);
+ for( DiseqList::iterator it = del->begin(); it != del->end(); ++it ){
if( (*it).second ){
if( d_regions_map[ (*it).first ]==ri ){
counter++;
@@ -812,12 +911,14 @@ int StrongSolverTheoryUF::SortModel::getNumDisequalitiesToRegion( Node n, int ri
return counter;
}
-void StrongSolverTheoryUF::SortModel::getDisequalitiesToRegions( int ri, std::map< int, int >& regions_diseq ){
- for( std::map< Node, Region::RegionNodeInfo* >::iterator it = d_regions[ri]->d_nodes.begin();
- it != d_regions[ri]->d_nodes.end(); ++it ){
- if( it->second->d_valid ){
- Region::RegionNodeInfo::DiseqList* del = it->second->d_disequalities[0];
- for( NodeBoolMap::iterator it2 = del->d_disequalities.begin(); it2 != del->d_disequalities.end(); ++it2 ){
+void SortModel::getDisequalitiesToRegions(int ri,
+ std::map< int, int >& regions_diseq)
+{
+ Region* region = d_regions[ri];
+ for(Region::iterator it = region->begin(); it != region->end(); ++it ){
+ if( it->second->valid() ){
+ DiseqList* del = it->second->get(0);
+ for( DiseqList::iterator it2 = del->begin(); it2 != del->end(); ++it2 ){
if( (*it2).second ){
Assert( isValid( d_regions_map[ (*it2).first ] ) );
//Notice() << "Found disequality with " << (*it2).first << ", region = " << d_regions_map[ (*it2).first ] << std::endl;
@@ -828,7 +929,7 @@ void StrongSolverTheoryUF::SortModel::getDisequalitiesToRegions( int ri, std::ma
}
}
-void StrongSolverTheoryUF::SortModel::setSplitScore( Node n, int s ){
+void SortModel::setSplitScore( Node n, int s ){
if( d_split_score.find( n )!=d_split_score.end() ){
int ss = d_split_score[ n ];
d_split_score[ n ] = s>ss ? s : ss;
@@ -840,13 +941,13 @@ void StrongSolverTheoryUF::SortModel::setSplitScore( Node n, int s ){
}
}
-void StrongSolverTheoryUF::SortModel::assertCardinality( OutputChannel* out, int c, bool val ){
+void SortModel::assertCardinality( OutputChannel* out, int c, bool val ){
if( !d_conflict ){
- Trace("uf-ss-assert") << "Assert cardinality " << d_type << " " << c << " " << val << " level = ";
- Trace("uf-ss-assert") << d_thss->getTheory()->d_valuation.getAssertionLevel() << std::endl;
+ Trace("uf-ss-assert")
+ << "Assert cardinality "<< d_type << " " << c << " " << val << " level = "
+ << d_thss->getTheory()->d_valuation.getAssertionLevel() << std::endl;
Assert( c>0 );
Node cl = getCardinalityLiteral( c );
- d_cardinality_assertions[ cl ] = val;
if( val ){
bool doCheckRegions = !d_hasCard;
bool prevHasCard = d_hasCard;
@@ -861,7 +962,7 @@ void StrongSolverTheoryUF::SortModel::assertCardinality( OutputChannel* out, int
//should check all regions now
if( doCheckRegions ){
for( int i=0; i<(int)d_regions_index; i++ ){
- if( d_regions[i]->d_valid ){
+ if( d_regions[i]->valid() ){
checkRegion( i );
if( d_conflict ){
return;
@@ -890,8 +991,9 @@ void StrongSolverTheoryUF::SortModel::assertCardinality( OutputChannel* out, int
bool needsCard = true;
for( std::map< int, Node >::iterator it = d_cardinality_literal.begin(); it!=d_cardinality_literal.end(); ++it ){
if( it->first<=d_aloc_cardinality.get() ){
- if( d_cardinality_assertions.find( it->second )==d_cardinality_assertions.end() ){
- Debug("fmf-card-debug") << "..does not need allocate because of " << it->second << std::endl;
+ bool value;
+ if( !d_thss->getTheory()->d_valuation.hasSatValue( it->second, value ) ){
+ Debug("fmf-card-debug") << "..does not need allocate because we are waiting for " << it->second << std::endl;
needsCard = false;
break;
}
@@ -912,7 +1014,7 @@ void StrongSolverTheoryUF::SortModel::assertCardinality( OutputChannel* out, int
}
}
-void StrongSolverTheoryUF::SortModel::checkRegion( int ri, bool checkCombine ){
+void SortModel::checkRegion( int ri, bool checkCombine ){
if( isValid(ri) && d_hasCard ){
Assert( d_cardinality>0 );
if( checkCombine && d_regions[ri]->getMustCombine( d_cardinality ) ){
@@ -941,10 +1043,10 @@ void StrongSolverTheoryUF::SortModel::checkRegion( int ri, bool checkCombine ){
}
}
-int StrongSolverTheoryUF::SortModel::forceCombineRegion( int ri, bool useDensity ){
+int SortModel::forceCombineRegion( int ri, bool useDensity ){
if( !useDensity ){
for( int i=0; i<(int)d_regions_index; i++ ){
- if( ri!=i && d_regions[i]->d_valid ){
+ if( ri!=i && d_regions[i]->valid() ){
return combineRegions( ri, i );
}
}
@@ -981,7 +1083,7 @@ int StrongSolverTheoryUF::SortModel::forceCombineRegion( int ri, bool useDensity
}
-int StrongSolverTheoryUF::SortModel::combineRegions( int ai, int bi ){
+int SortModel::combineRegions( int ai, int bi ){
#ifdef COMBINE_REGIONS_SMALL_INTO_LARGE
if( d_regions[ai]->getNumReps()<d_regions[bi]->getNumReps() ){
return combineRegions( bi, ai );
@@ -989,19 +1091,20 @@ int StrongSolverTheoryUF::SortModel::combineRegions( int ai, int bi ){
#endif
Debug("uf-ss-region") << "uf-ss: Combine Region #" << bi << " with Region #" << ai << std::endl;
Assert( isValid( ai ) && isValid( bi ) );
- for( std::map< Node, Region::RegionNodeInfo* >::iterator it = d_regions[bi]->d_nodes.begin(); it != d_regions[bi]->d_nodes.end(); ++it ){
+ Region* region_bi = d_regions[bi];
+ for(Region::iterator it = region_bi->begin(); it != region_bi->end(); ++it){
Region::RegionNodeInfo* rni = it->second;
- if( rni->d_valid ){
+ if( rni->valid() ){
d_regions_map[ it->first ] = ai;
}
}
//update regions disequal DO_THIS?
d_regions[ai]->combine( d_regions[bi] );
- d_regions[bi]->d_valid = false;
+ d_regions[bi]->setValid( false );
return ai;
}
-void StrongSolverTheoryUF::SortModel::moveNode( Node n, int ri ){
+void SortModel::moveNode( Node n, int ri ){
Debug("uf-ss-region") << "uf-ss: Move node " << n << " to Region #" << ri << std::endl;
Assert( isValid( d_regions_map[ n ] ) );
Assert( isValid( ri ) );
@@ -1010,7 +1113,7 @@ void StrongSolverTheoryUF::SortModel::moveNode( Node n, int ri ){
d_regions_map[n] = ri;
}
-void StrongSolverTheoryUF::SortModel::allocateCardinality( OutputChannel* out ){
+void SortModel::allocateCardinality( OutputChannel* out ){
if( d_aloc_cardinality>0 ){
Trace("uf-ss-fmf") << "No model of size " << d_aloc_cardinality << " exists for type " << d_type << " in this branch" << std::endl;
}
@@ -1028,20 +1131,26 @@ void StrongSolverTheoryUF::SortModel::allocateCardinality( OutputChannel* out ){
//allocate the lowest such that it is not asserted
Node cl;
+ bool increment;
do {
+ increment = false;
d_aloc_cardinality = d_aloc_cardinality + 1;
cl = getCardinalityLiteral( d_aloc_cardinality );
- }while( d_cardinality_assertions.find( cl )!=d_cardinality_assertions.end() && !d_cardinality_assertions[cl] );
- //if one is already asserted postively, abort
- if( d_cardinality_assertions.find( cl )!=d_cardinality_assertions.end() ){
- return;
- }
+ bool value;
+ if( d_thss->getTheory()->d_valuation.hasSatValue( cl, value ) ){
+ if( value ){
+ //if one is already asserted postively, abort
+ return;
+ }else{
+ increment = true;
+ }
+ }
+ }while( increment );
//check for abort case
if( options::ufssAbortCardinality()==d_aloc_cardinality ){
- //abort here DO_THIS
Message() << "Maximum cardinality reached." << std::endl;
- exit( 0 );
+ exit( 1 );
}else{
if( applyTotality( d_aloc_cardinality ) ){
//must generate new cardinality lemma term
@@ -1093,11 +1202,12 @@ void StrongSolverTheoryUF::SortModel::allocateCardinality( OutputChannel* out ){
}
}
-int StrongSolverTheoryUF::SortModel::addSplit( Region* r, OutputChannel* out ){
+int SortModel::addSplit( Region* r, OutputChannel* out ){
Node s;
if( r->hasSplits() ){
//take the first split you find
- for( NodeBoolMap::iterator it = r->d_splits.begin(); it != r->d_splits.end(); ++it ){
+ for( Region::split_iterator it = r->begin_splits();
+ it != r->end_splits(); ++it ){
if( (*it).second ){
s = (*it).first;
break;
@@ -1106,13 +1216,16 @@ int StrongSolverTheoryUF::SortModel::addSplit( Region* r, OutputChannel* out ){
Assert( s!=Node::null() );
}else{
if( options::ufssMode()!=UF_SS_FULL ){
- //since candidate clique is not reported, we may need to find splits manually
- for ( std::map< Node, Region::RegionNodeInfo* >::iterator it = r->d_nodes.begin(); it != r->d_nodes.end(); ++it ){
- if ( it->second->d_valid ){
- for ( std::map< Node, Region::RegionNodeInfo* >::iterator it2 = r->d_nodes.begin(); it2 != r->d_nodes.end(); ++it2 ){
- if ( it->second!=it2->second && it2->second->d_valid ){
+ // Since candidate clique is not reported, we may need to find
+ // splits manually.
+ for ( Region::iterator it = r->begin(); it != r->end(); ++it ){
+ if ( it->second->valid() ){
+ for ( Region::iterator it2 = r->begin(); it2 != r->end(); ++it2 ){
+ if ( it->second!=it2->second && it2->second->valid() ){
if( !r->isDisequal( it->first, it2->first, 1 ) ){
- s = NodeManager::currentNM()->mkNode( EQUAL, it->first, it2->first );
+ Node it_node = it->first;
+ Node it2_node = it2->first;
+ s = it_node.eqNode(it2_node);
}
}
}
@@ -1128,7 +1241,8 @@ int StrongSolverTheoryUF::SortModel::addSplit( Region* r, OutputChannel* out ){
Node b_t = NodeManager::currentNM()->mkConst( true );
Node b_f = NodeManager::currentNM()->mkConst( false );
if( ss==b_f ){
- Trace("uf-ss-lemma") << "....Assert disequal directly : " << s[0] << " " << s[1] << std::endl;
+ Trace("uf-ss-lemma") << "....Assert disequal directly : "
+ << s[0] << " " << s[1] << std::endl;
assertDisequal( s[0], s[1], b_t );
return -1;
}else{
@@ -1165,7 +1279,7 @@ int StrongSolverTheoryUF::SortModel::addSplit( Region* r, OutputChannel* out ){
}
-void StrongSolverTheoryUF::SortModel::addCliqueLemma( std::vector< Node >& clique, OutputChannel* out ){
+void SortModel::addCliqueLemma( std::vector< Node >& clique, OutputChannel* out ){
Assert( d_hasCard );
Assert( d_cardinality>0 );
while( clique.size()>size_t(d_cardinality+1) ){
@@ -1318,7 +1432,7 @@ void StrongSolverTheoryUF::SortModel::addCliqueLemma( std::vector< Node >& cliqu
}
}
-void StrongSolverTheoryUF::SortModel::addTotalityAxiom( Node n, int cardinality, OutputChannel* out ){
+void SortModel::addTotalityAxiom( Node n, int cardinality, OutputChannel* out ){
if( std::find( d_totality_terms[0].begin(), d_totality_terms[0].end(), n )==d_totality_terms[0].end() ){
if( std::find( d_totality_lems[n].begin(), d_totality_lems[n].end(), cardinality ) == d_totality_lems[n].end() ){
d_totality_lems[n].push_back( cardinality );
@@ -1346,7 +1460,7 @@ void StrongSolverTheoryUF::SortModel::addTotalityAxiom( Node n, int cardinality,
for( unsigned j=0; j<(d_sym_break_terms[n.getType()][sort_id].size()-1); j++ ){
eqs.push_back( d_sym_break_terms[n.getType()][sort_id][j].eqNode( getTotalityLemmaTerm( cardinality, i-1 ) ) );
}
- Node ax = NodeManager::currentNM()->mkNode( OR, eqs );
+ Node ax = eqs.size()==1 ? eqs[0] : NodeManager::currentNM()->mkNode( OR, eqs );
Node lem = NodeManager::currentNM()->mkNode( IMPLIES, eq, ax );
Trace("uf-ss-lemma") << "*** Add (canonicity) totality axiom " << lem << std::endl;
d_thss->getOutputChannel().lemma( lem );
@@ -1369,7 +1483,7 @@ void StrongSolverTheoryUF::SortModel::addTotalityAxiom( Node n, int cardinality,
}
}
-void StrongSolverTheoryUF::SortModel::addClique( int c, std::vector< Node >& clique ) {
+void SortModel::addClique( int c, std::vector< Node >& clique ) {
//if( d_clique_trie[c].add( clique ) ){
// d_cliques[ c ].push_back( clique );
//}
@@ -1377,20 +1491,20 @@ void StrongSolverTheoryUF::SortModel::addClique( int c, std::vector< Node >& cli
/** apply totality */
-bool StrongSolverTheoryUF::SortModel::applyTotality( int cardinality ){
+bool SortModel::applyTotality( int cardinality ){
return options::ufssTotality() || cardinality<=options::ufssTotalityLimited();
// || ( options::ufssModelInference() && !d_totality_terms[cardinality].empty() );
}
/** get totality lemma terms */
-Node StrongSolverTheoryUF::SortModel::getTotalityLemmaTerm( int cardinality, int i ){
+Node SortModel::getTotalityLemmaTerm( int cardinality, int i ){
return d_totality_terms[0][i];
//}else{
// return d_totality_terms[cardinality][i];
//}
}
-void StrongSolverTheoryUF::SortModel::simpleCheckCardinality() {
+void SortModel::simpleCheckCardinality() {
if( d_maxNegCard.get()!=0 && d_hasCard.get() && d_cardinality.get()<d_maxNegCard.get() ){
Node lem = NodeManager::currentNM()->mkNode( AND, getCardinalityLiteral( d_cardinality.get() ),
getCardinalityLiteral( d_maxNegCard.get() ).negate() );
@@ -1400,7 +1514,7 @@ void StrongSolverTheoryUF::SortModel::simpleCheckCardinality() {
}
}
-bool StrongSolverTheoryUF::SortModel::doSendLemma( Node lem ) {
+bool SortModel::doSendLemma( Node lem ) {
if( d_lemma_cache.find( lem )==d_lemma_cache.end() ){
d_lemma_cache[lem] = true;
d_thss->getOutputChannel().lemma( lem );
@@ -1410,32 +1524,36 @@ bool StrongSolverTheoryUF::SortModel::doSendLemma( Node lem ) {
}
}
-void StrongSolverTheoryUF::SortModel::debugPrint( const char* c ){
+void SortModel::debugPrint( const char* c ){
Debug( c ) << "-- Conflict Find:" << std::endl;
Debug( c ) << "Number of reps = " << d_reps << std::endl;
Debug( c ) << "Cardinality req = " << d_cardinality << std::endl;
unsigned debugReps = 0;
for( int i=0; i<(int)d_regions_index; i++ ){
- if( d_regions[i]->d_valid ){
+ Region* region = d_regions[i];
+ if( region->valid() ){
Debug( c ) << "Region #" << i << ": " << std::endl;
- d_regions[i]->debugPrint( c, true );
+ region->debugPrint( c, true );
Debug( c ) << std::endl;
- for( std::map< Node, Region::RegionNodeInfo* >::iterator it = d_regions[i]->d_nodes.begin(); it != d_regions[i]->d_nodes.end(); ++it ){
- if( it->second->d_valid ){
+ for( Region::iterator it = region->begin(); it != region->end(); ++it ){
+ if( it->second->valid() ){
if( d_regions_map[ it->first ]!=i ){
- Debug( c ) << "***Bad regions map : " << it->first << " " << d_regions_map[ it->first ].get() << std::endl;
+ Debug( c ) << "***Bad regions map : " << it->first
+ << " " << d_regions_map[ it->first ].get() << std::endl;
}
}
}
- debugReps += d_regions[i]->getNumReps();
+ debugReps += region->getNumReps();
}
}
+
if( debugReps!=d_reps ){
- Debug( c ) << "***Bad reps: " << d_reps << ", actual = " << debugReps << std::endl;
+ Debug( c ) << "***Bad reps: " << d_reps << ", "
+ << "actual = " << debugReps << std::endl;
}
}
-bool StrongSolverTheoryUF::SortModel::debugModel( TheoryModel* m ){
+bool SortModel::debugModel( TheoryModel* m ){
if( Trace.isOn("uf-ss-warn") ){
std::vector< Node > eqcs;
eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( m->d_equalityEngine );
@@ -1503,27 +1621,42 @@ bool StrongSolverTheoryUF::SortModel::debugModel( TheoryModel* m ){
return true;
}
-int StrongSolverTheoryUF::SortModel::getNumRegions(){
+int SortModel::getNumRegions(){
int count = 0;
for( int i=0; i<(int)d_regions_index; i++ ){
- if( d_regions[i]->d_valid ){
+ if( d_regions[i]->valid() ){
count++;
}
}
return count;
}
-Node StrongSolverTheoryUF::SortModel::getCardinalityLiteral( int c ) {
- if( d_cardinality_literal.find( c )==d_cardinality_literal.end() ){
- d_cardinality_literal[c] = NodeManager::currentNM()->mkNode( CARDINALITY_CONSTRAINT, d_cardinality_term,
- NodeManager::currentNM()->mkConst( Rational( c ) ) );
+Node SortModel::getCardinalityLiteral( int c ) {
+ if( d_cardinality_literal.find(c) == d_cardinality_literal.end() ){
+ Node c_as_rational = NodeManager::currentNM()->mkConst(Rational(c));
+ d_cardinality_literal[c] =
+ NodeManager::currentNM()->mkNode(CARDINALITY_CONSTRAINT,
+ d_cardinality_term,
+ c_as_rational);
+
}
return d_cardinality_literal[c];
}
-StrongSolverTheoryUF::StrongSolverTheoryUF(context::Context* c, context::UserContext* u, OutputChannel& out, TheoryUF* th) :
-d_out( &out ), d_th( th ), d_conflict( c, false ), d_rep_model(), d_aloc_com_card( u, 0 ), d_com_card_assertions( c ), d_min_pos_com_card( c, -1 ),
-d_card_assertions_eqv_lemma( u ), d_min_pos_tn_master_card( c, -1 ), d_rel_eqc( c )
+StrongSolverTheoryUF::StrongSolverTheoryUF(context::Context* c,
+ context::UserContext* u,
+ OutputChannel& out,
+ TheoryUF* th)
+ : d_out( &out )
+ , d_th( th )
+ , d_conflict( c, false )
+ , d_rep_model()
+ , d_aloc_com_card( u, 0 )
+ , d_com_card_assertions( c )
+ , d_min_pos_com_card( c, -1 )
+ , d_card_assertions_eqv_lemma( u )
+ , d_min_pos_tn_master_card( c, -1 )
+ , d_rel_eqc( c )
{
if( options::ufssDiseqPropagation() ){
d_deq_prop = new DisequalityPropagator( th->getQuantifiersEngine(), this );
@@ -1899,7 +2032,7 @@ void StrongSolverTheoryUF::preRegisterTerm( TNode n ){
//}
-StrongSolverTheoryUF::SortModel* StrongSolverTheoryUF::getSortModel( Node n ){
+SortModel* StrongSolverTheoryUF::getSortModel( Node n ){
TypeNode tn = n.getType();
std::map< TypeNode, SortModel* >::iterator it = d_rep_model.find( tn );
//pre-register the type if not done already
@@ -1914,9 +2047,7 @@ StrongSolverTheoryUF::SortModel* StrongSolverTheoryUF::getSortModel( Node n ){
}
}
-void StrongSolverTheoryUF::notifyRestart(){
-
-}
+void StrongSolverTheoryUF::notifyRestart(){}
/** get cardinality for sort */
int StrongSolverTheoryUF::getCardinality( Node n ) {
@@ -2021,27 +2152,31 @@ void StrongSolverTheoryUF::checkCombinedCardinality() {
conf.push_back( d_rep_model[d_tn_mono_master]->getCardinalityLiteral( mc ) );
conf.push_back( d_rep_model[maxSlaveType]->getCardinalityLiteral( maxMonoSlave ).negate() );
Node cf = NodeManager::currentNM()->mkNode( AND, conf );
- Trace("uf-ss-lemma") << "*** Combined monotone cardinality conflict : " << cf << std::endl;
- Trace("uf-ss-com-card") << "*** Combined monotone cardinality conflict : " << cf << std::endl;
+ Trace("uf-ss-lemma") << "*** Combined monotone cardinality conflict"
+ << " : " << cf << std::endl;
+ Trace("uf-ss-com-card") << "*** Combined monotone cardinality conflict"
+ << " : " << cf << std::endl;
getOutputChannel().conflict( cf );
d_conflict.set( true );
return;
}
}
- if( d_min_pos_com_card.get()!=-1 && totalCombinedCard>d_min_pos_com_card.get() ){
+ int cc = d_min_pos_com_card.get();
+ if( cc !=-1 && totalCombinedCard > cc ){
//conflict
- int cc = d_min_pos_com_card.get();
- Assert( d_com_card_literal.find( cc )!=d_com_card_literal.end() );
+ Assert( d_com_card_literal.find( cc ) != d_com_card_literal.end() );
Node com_lit = d_com_card_literal[cc];
- Assert( d_com_card_assertions.find( com_lit )!=d_com_card_assertions.end() );
+ Assert(d_com_card_assertions.find(com_lit)!=d_com_card_assertions.end());
Assert( d_com_card_assertions[com_lit] );
std::vector< Node > conf;
conf.push_back( com_lit );
int totalAdded = 0;
- for( std::map< TypeNode, SortModel* >::iterator it = d_rep_model.begin(); it != d_rep_model.end(); ++it ){
+ for( std::map< TypeNode, SortModel* >::iterator it = d_rep_model.begin();
+ it != d_rep_model.end(); ++it ){
bool doAdd = true;
if( options::ufssFairnessMonotone() ){
- std::map< TypeNode, bool >::iterator its = d_tn_mono_slave.find( it->first );
+ std::map< TypeNode, bool >::iterator its =
+ d_tn_mono_slave.find( it->first );
if( its!=d_tn_mono_slave.end() && its->second ){
doAdd = false;
}
@@ -2058,8 +2193,10 @@ void StrongSolverTheoryUF::checkCombinedCardinality() {
}
}
Node cf = NodeManager::currentNM()->mkNode( AND, conf );
- Trace("uf-ss-lemma") << "*** Combined cardinality conflict : " << cf << std::endl;
- Trace("uf-ss-com-card") << "*** Combined cardinality conflict : " << cf << std::endl;
+ Trace("uf-ss-lemma") << "*** Combined cardinality conflict : " << cf
+ << std::endl;
+ Trace("uf-ss-com-card") << "*** Combined cardinality conflict : " << cf
+ << std::endl;
getOutputChannel().conflict( cf );
d_conflict.set( true );
}
@@ -2113,8 +2250,10 @@ StrongSolverTheoryUF::Statistics::~Statistics(){
}
-DisequalityPropagator::DisequalityPropagator(QuantifiersEngine* qe, StrongSolverTheoryUF* ufss) :
- d_qe(qe), d_ufss(ufss){
+DisequalityPropagator::DisequalityPropagator(QuantifiersEngine* qe,
+ StrongSolverTheoryUF* ufss)
+ : d_qe(qe), d_ufss(ufss)
+{
d_true = NodeManager::currentNM()->mkConst( true );
d_false = NodeManager::currentNM()->mkConst( false );
}
@@ -2182,3 +2321,7 @@ DisequalityPropagator::Statistics::Statistics():
DisequalityPropagator::Statistics::~Statistics(){
smtStatisticsRegistry()->unregisterStat(& d_propagations);
}
+
+}/* CVC4::theory namespace::uf */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
diff --git a/src/theory/uf/theory_uf_strong_solver.h b/src/theory/uf/theory_uf_strong_solver.h
index db4c50423..11f0664f3 100644
--- a/src/theory/uf/theory_uf_strong_solver.h
+++ b/src/theory/uf/theory_uf_strong_solver.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_uf_strong_solver.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Andrew Reynolds
- ** Minor contributors (to current version): none
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Theory uf strong solver
**/
@@ -25,17 +25,19 @@
#include "util/statistics_registry.h"
namespace CVC4 {
-
class SortInference;
-
namespace theory {
-
class SubsortSymmetryBreaker;
-
namespace uf {
-
class TheoryUF;
class DisequalityPropagator;
+} /* namespace CVC4::theory::uf */
+} /* namespace CVC4::theory */
+} /* namespace CVC4 */
+
+namespace CVC4 {
+namespace theory {
+namespace uf {
class StrongSolverTheoryUF{
protected:
@@ -44,83 +46,135 @@ protected:
typedef context::CDHashMap<Node, Node, NodeHashFunction> NodeNodeMap;
typedef context::CDHashMap<TypeNode, bool, TypeNodeHashFunction> TypeNodeBoolMap;
public:
- /** information for incremental conflict/clique finding for a particular sort */
+ /**
+ * Information for incremental conflict/clique finding for a
+ * particular sort.
+ */
class SortModel {
private:
std::map< Node, std::vector< int > > d_totality_lems;
std::map< TypeNode, std::map< int, std::vector< Node > > > d_sym_break_terms;
std::map< Node, int > d_sym_break_index;
public:
- /** a partition of the current equality graph for which cliques can occur internally */
+
+ /**
+ * A partition of the current equality graph for which cliques
+ * can occur internally.
+ */
class Region {
public:
- /** conflict find pointer */
- SortModel* d_cf;
/** information stored about each node in region */
class RegionNodeInfo {
public:
/** disequality list for node */
class DiseqList {
public:
- DiseqList( context::Context* c ) : d_size( c, 0 ), d_disequalities( c ){}
+ DiseqList( context::Context* c )
+ : d_size( c, 0 ), d_disequalities( c ) {}
~DiseqList(){}
- context::CDO< unsigned > d_size;
- NodeBoolMap d_disequalities;
+
void setDisequal( Node n, bool valid ){
- Assert( d_disequalities.find( n )==d_disequalities.end() || d_disequalities[n]!=valid );
+ Assert( (!isSet(n)) || getDisequalityValue(n) != valid );
d_disequalities[ n ] = valid;
d_size = d_size + ( valid ? 1 : -1 );
}
- };
- private:
- DiseqList d_internal;
- DiseqList d_external;
+ bool isSet(Node n) const {
+ return d_disequalities.find(n) != d_disequalities.end();
+ }
+ bool getDisequalityValue(Node n) const {
+ Assert(isSet(n));
+ return (*(d_disequalities.find(n))).second;
+ }
+
+ int size() const { return d_size; }
+
+ typedef NodeBoolMap::iterator iterator;
+ iterator begin() { return d_disequalities.begin(); }
+ iterator end() { return d_disequalities.end(); }
+
+ private:
+ context::CDO< int > d_size;
+ NodeBoolMap d_disequalities;
+ }; /* class DiseqList */
public:
/** constructor */
- RegionNodeInfo( context::Context* c ) :
- d_internal( c ), d_external( c ), d_valid( c, true ){
+ RegionNodeInfo( context::Context* c )
+ : d_internal(c), d_external(c), d_valid(c, true) {
d_disequalities[0] = &d_internal;
d_disequalities[1] = &d_external;
}
~RegionNodeInfo(){}
+
+ int getNumDisequalities() const {
+ return d_disequalities[0]->size() + d_disequalities[1]->size();
+ }
+ int getNumExternalDisequalities() const {
+ return d_disequalities[0]->size();
+ }
+ int getNumInternalDisequalities() const {
+ return d_disequalities[1]->size();
+ }
+
+ bool valid() const { return d_valid; }
+ void setValid(bool valid) { d_valid = valid; }
+
+ DiseqList* get(unsigned i) { return d_disequalities[i]; }
+
+ private:
+ DiseqList d_internal;
+ DiseqList d_external;
context::CDO< bool > d_valid;
DiseqList* d_disequalities[2];
+ }; /* class RegionNodeInfo */
- int getNumDisequalities() { return d_disequalities[0]->d_size + d_disequalities[1]->d_size; }
- int getNumExternalDisequalities() { return d_disequalities[0]->d_size; }
- int getNumInternalDisequalities() { return d_disequalities[1]->d_size; }
- };
- ///** end class RegionNodeInfo */
private:
+ /** conflict find pointer */
+ SortModel* d_cf;
+
context::CDO< unsigned > d_testCliqueSize;
context::CDO< unsigned > d_splitsSize;
- public:
//a postulated clique
NodeBoolMap d_testClique;
//disequalities needed for this clique to happen
NodeBoolMap d_splits;
- private:
//number of valid representatives in this region
context::CDO< unsigned > d_reps_size;
//total disequality size (external)
context::CDO< unsigned > d_total_diseq_external;
//total disequality size (internal)
context::CDO< unsigned > d_total_diseq_internal;
- private:
/** set rep */
void setRep( Node n, bool valid );
- public:
- //constructor
- Region( SortModel* cf, context::Context* c ) : d_cf( cf ), d_testCliqueSize( c, 0 ),
- d_splitsSize( c, 0 ), d_testClique( c ), d_splits( c ), d_reps_size( c, 0 ),
- d_total_diseq_external( c, 0 ), d_total_diseq_internal( c, 0 ), d_valid( c, true ) {
- }
- virtual ~Region(){}
//region node infomation
std::map< Node, RegionNodeInfo* > d_nodes;
//whether region is valid
context::CDO< bool > d_valid;
+
public:
+ //constructor
+ Region( SortModel* cf, context::Context* c );
+ virtual ~Region();
+
+ typedef std::map< Node, RegionNodeInfo* >::iterator iterator;
+ iterator begin() { return d_nodes.begin(); }
+ iterator end() { return d_nodes.end(); }
+
+ typedef NodeBoolMap::iterator split_iterator;
+ split_iterator begin_splits() { return d_splits.begin(); }
+ split_iterator end_splits() { return d_splits.end(); }
+
+ /** Returns a RegionInfo. */
+ RegionNodeInfo* getRegionInfo(Node n) {
+ Assert(d_nodes.find(n) != d_nodes.end());
+ return (* (d_nodes.find(n))).second;
+ }
+
+ /** Returns whether or not d_valid is set in current context. */
+ bool valid() const { return d_valid; }
+
+ /** Sets d_valid to the value valid in the current context.*/
+ void setValid(bool valid) { d_valid = valid; }
+
/** add rep */
void addRep( Node n );
//take node from region
@@ -131,13 +185,14 @@ public:
void setEqual( Node a, Node b );
//set n1 != n2 to value 'valid', type is whether it is internal/external
void setDisequal( Node n1, Node n2, int type, bool valid );
- public:
//get num reps
int getNumReps() { return d_reps_size; }
//get test clique size
int getTestCliqueSize() { return d_testCliqueSize; }
// has representative
- bool hasRep( Node n ) { return d_nodes.find( n )!=d_nodes.end() && d_nodes[n]->d_valid; }
+ bool hasRep( Node n ) {
+ return d_nodes.find(n) != d_nodes.end() && d_nodes[n]->valid();
+ }
// is disequal
bool isDisequal( Node n1, Node n2, int type );
/** get must merge */
@@ -145,15 +200,18 @@ public:
/** has splits */
bool hasSplits() { return d_splitsSize>0; }
/** get external disequalities */
- void getNumExternalDisequalities( std::map< Node, int >& num_ext_disequalities );
- public:
+ void getNumExternalDisequalities(std::map< Node, int >& num_ext_disequalities );
/** check for cliques */
bool check( Theory::Effort level, int cardinality, std::vector< Node >& clique );
/** get candidate clique */
bool getCandidateClique( int cardinality, std::vector< Node >& clique );
//print debug
void debugPrint( const char* c, bool incClique = false );
- };
+
+ // Returns the first key in d_nodes.
+ Node frontKey() const { return d_nodes.begin()->first; }
+ }; /* class Region */
+
private:
/** the type this model is for */
TypeNode d_type;
@@ -173,16 +231,17 @@ public:
std::vector< Node > d_disequalities;
/** number of representatives in all regions */
context::CDO< unsigned > d_reps;
- private:
+
/** get number of disequalities from node n to region ri */
int getNumDisequalitiesToRegion( Node n, int ri );
/** get number of disequalities from Region r to other regions */
void getDisequalitiesToRegions( int ri, std::map< int, int >& regions_diseq );
/** is valid */
- bool isValid( int ri ) { return ri>=0 && ri<(int)d_regions_index && d_regions[ ri ]->d_valid; }
+ bool isValid( int ri ) {
+ return ri>=0 && ri<(int)d_regions_index && d_regions[ ri ]->valid();
+ }
/** set split score */
void setSplitScore( Node n, int s );
- private:
/** check if we need to combine region ri */
void checkRegion( int ri, bool checkCombine = true );
/** force combine region */
@@ -191,18 +250,21 @@ public:
int combineRegions( int ai, int bi );
/** move node n to region ri */
void moveNode( Node n, int ri );
- private:
/** allocate cardinality */
void allocateCardinality( OutputChannel* out );
- /** add split 0 = no split, -1 = entailed disequality added, 1 = split added */
+ /**
+ * Add splits. Returns
+ * 0 = no split,
+ * -1 = entailed disequality added, or
+ * 1 = split added.
+ */
int addSplit( Region* r, OutputChannel* out );
/** add clique lemma */
void addCliqueLemma( std::vector< Node >& clique, OutputChannel* out );
/** add totality axiom */
void addTotalityAxiom( Node n, int cardinality, OutputChannel* out );
- private:
+
class NodeTrie {
- std::map< Node, NodeTrie > d_children;
public:
bool add( std::vector< Node >& n, unsigned i = 0 ){
Assert( i<n.size() );
@@ -214,10 +276,13 @@ public:
return d_children[n[i]].add( n, i+1 );
}
}
- };
+ private:
+ std::map< Node, NodeTrie > d_children;
+ }; /* class NodeTrie */
+
std::map< int, NodeTrie > d_clique_trie;
void addClique( int c, std::vector< Node >& clique );
- private:
+
/** Are we in conflict */
context::CDO<bool> d_conflict;
/** cardinality */
@@ -232,8 +297,6 @@ public:
std::map< int, Node > d_cardinality_literal;
/** cardinality lemmas */
std::map< int, Node > d_cardinality_lemma;
- /** cardinality assertions (indexed by cardinality literals ) */
- NodeBoolMap d_cardinality_assertions;
/** whether a positive cardinality constraint has been asserted */
context::CDO< bool > d_hasCard;
/** clique lemmas that have been asserted */
@@ -246,18 +309,20 @@ public:
context::CDO< bool > d_initialized;
/** cache for lemmas */
NodeBoolMap d_lemma_cache;
- private:
+
/** apply totality */
bool applyTotality( int cardinality );
/** get totality lemma terms */
Node getTotalityLemmaTerm( int cardinality, int i );
/** simple check cardinality */
void simpleCheckCardinality();
- private:
+
bool doSendLemma( Node lem );
+
public:
- SortModel( Node n, context::Context* c, context::UserContext* u, StrongSolverTheoryUF* thss );
- virtual ~SortModel(){}
+ SortModel( Node n, context::Context* c, context::UserContext* u,
+ StrongSolverTheoryUF* thss );
+ virtual ~SortModel();
/** initialize */
void initialize( OutputChannel* out );
/** new node */
@@ -420,18 +485,7 @@ public:
Statistics d_statistics;
};/* class StrongSolverTheoryUF */
-class DisequalityPropagator
-{
-private:
- /** quantifiers engine */
- QuantifiersEngine* d_qe;
- /** strong solver */
- StrongSolverTheoryUF* d_ufss;
- /** true,false */
- Node d_true;
- Node d_false;
- /** check term t against equivalence class that t is disequal from */
- void checkEquivalenceClass( Node t, Node eqc );
+class DisequalityPropagator {
public:
DisequalityPropagator(QuantifiersEngine* qe, StrongSolverTheoryUF* ufss);
/** merge */
@@ -440,7 +494,7 @@ public:
void assertDisequal( Node a, Node b, Node reason );
/** assert predicate */
void assertPredicate( Node p, bool polarity );
-public:
+
class Statistics {
public:
IntStat d_propagations;
@@ -449,9 +503,20 @@ public:
};
/** statistics class */
Statistics d_statistics;
-};
-}
+private:
+ /** quantifiers engine */
+ QuantifiersEngine* d_qe;
+ /** strong solver */
+ StrongSolverTheoryUF* d_ufss;
+ /** true,false */
+ Node d_true;
+ Node d_false;
+ /** check term t against equivalence class that t is disequal from */
+ void checkEquivalenceClass( Node t, Node eqc );
+}; /* class DisequalityPropagator */
+
+}/* CVC4::theory namespace::uf */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
diff --git a/src/theory/uf/theory_uf_type_rules.h b/src/theory/uf/theory_uf_type_rules.h
index 05b95e9e1..ab42aaf15 100644
--- a/src/theory/uf/theory_uf_type_rules.h
+++ b/src/theory/uf/theory_uf_type_rules.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file theory_uf_type_rules.h
** \verbatim
- ** Original author: Dejan Jovanovic
- ** Major contributors: Christopher L. Conway, Andrew Reynolds, Morgan Deters
- ** Minor contributors (to current version): Tim King
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Morgan Deters, Dejan Jovanovic
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief [[ Add brief comments here ]]
**
diff --git a/src/theory/unconstrained_simplifier.cpp b/src/theory/unconstrained_simplifier.cpp
index dda73c1d9..6a33adc56 100644
--- a/src/theory/unconstrained_simplifier.cpp
+++ b/src/theory/unconstrained_simplifier.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file unconstrained_simplifier.cpp
** \verbatim
- ** Original author: Clark Barrett
- ** Major contributors: none
- ** Minor contributors (to current version): Kshitij Bansal, Morgan Deters, Tim King, Liana Hadarean, Peter Collingbourne, Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Clark Barrett, Peter Collingbourne, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Simplifications based on unconstrained variables
**
diff --git a/src/theory/unconstrained_simplifier.h b/src/theory/unconstrained_simplifier.h
index e23c4853d..e10be1a8f 100644
--- a/src/theory/unconstrained_simplifier.h
+++ b/src/theory/unconstrained_simplifier.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file unconstrained_simplifier.h
** \verbatim
- ** Original author: Clark Barrett
- ** Major contributors: none
- ** Minor contributors (to current version): Tim King
+ ** Top contributors (to current version):
+ ** Clark Barrett, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief Simplifications based on unconstrained variables
**
diff --git a/src/theory/valuation.cpp b/src/theory/valuation.cpp
index 7407086c2..165937c13 100644
--- a/src/theory/valuation.cpp
+++ b/src/theory/valuation.cpp
@@ -1,13 +1,13 @@
/********************* */
/*! \file valuation.cpp
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Dejan Jovanovic
- ** Minor contributors (to current version): Andrew Reynolds, Clark Barrett, Tim King
+ ** Top contributors (to current version):
+ ** Morgan Deters, Dejan Jovanovic, Tim King
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief A "valuation" proxy for TheoryEngine
**
diff --git a/src/theory/valuation.h b/src/theory/valuation.h
index c9bff14a4..4ecdecad0 100644
--- a/src/theory/valuation.h
+++ b/src/theory/valuation.h
@@ -1,13 +1,13 @@
/********************* */
/*! \file valuation.h
** \verbatim
- ** Original author: Morgan Deters
- ** Major contributors: Dejan Jovanovic
- ** Minor contributors (to current version): Tim King, Clark Barrett, Andrew Reynolds
+ ** Top contributors (to current version):
+ ** Morgan Deters, Dejan Jovanovic, Andrew Reynolds
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
+ ** Copyright (c) 2009-2016 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.\endverbatim
**
** \brief A "valuation" proxy for TheoryEngine
**
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback