diff options
author | PaulMeng <baolmeng@gmail.com> | 2016-04-20 14:43:18 -0500 |
---|---|---|
committer | PaulMeng <baolmeng@gmail.com> | 2016-04-20 14:43:18 -0500 |
commit | 904ffb6e73402bae537aa89e7fd8f0ab2e9d60e2 (patch) | |
tree | d96bb0c974bdea6170957d3e39d47a98f5c85ca0 /src | |
parent | a0054e9cc78822416d745e955c30f69cbb2a3aa7 (diff) |
update from the master
Diffstat (limited to 'src')
691 files changed, 18931 insertions, 9004 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 26a677d90..3ffda9f28 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -76,35 +76,41 @@ libcvc4_la_SOURCES = \ printer/cvc/cvc_printer.cpp \ printer/tptp/tptp_printer.h \ printer/tptp/tptp_printer.cpp \ + proof/arith_proof.cpp \ + proof/arith_proof.h \ + proof/array_proof.cpp \ + proof/array_proof.h \ + proof/bitvector_proof.cpp \ + proof/bitvector_proof.h \ + proof/clause_id.h \ + proof/cnf_proof.cpp \ + proof/cnf_proof.h \ proof/proof.h \ + proof/proof_manager.cpp \ + proof/proof_manager.h \ + proof/proof_utils.cpp \ + proof/proof_utils.h \ proof/sat_proof.h \ proof/sat_proof_implementation.h \ - proof/cnf_proof.h \ - proof/cnf_proof.cpp \ - proof/theory_proof.h \ + proof/skolemization_manager.cpp \ + proof/skolemization_manager.h \ proof/theory_proof.cpp \ - proof/uf_proof.h \ + proof/theory_proof.h \ proof/uf_proof.cpp \ - proof/array_proof.h \ - proof/bitvector_proof.h \ - proof/bitvector_proof.cpp \ - proof/proof_manager.h \ - proof/proof_manager.cpp \ - proof/proof_utils.h \ - proof/proof_utils.cpp \ + proof/uf_proof.h \ proof/unsat_core.cpp \ proof/unsat_core.h \ - prop/registrar.h \ + prop/cnf_stream.cpp \ + prop/cnf_stream.h \ prop/prop_engine.cpp \ prop/prop_engine.h \ - prop/theory_proxy.h \ - prop/theory_proxy.cpp \ - prop/cnf_stream.h \ - prop/cnf_stream.cpp \ + prop/registrar.h \ prop/sat_solver.h \ - prop/sat_solver_types.h \ - prop/sat_solver_factory.h \ prop/sat_solver_factory.cpp \ + prop/sat_solver_factory.h \ + prop/sat_solver_types.h \ + prop/theory_proxy.cpp \ + prop/theory_proxy.h \ smt/boolean_terms.cpp \ smt/boolean_terms.h \ smt/command.cpp \ @@ -284,6 +290,8 @@ libcvc4_la_SOURCES = \ theory/arrays/array_info.cpp \ theory/arrays/static_fact_manager.h \ theory/arrays/static_fact_manager.cpp \ + theory/arrays/array_proof_reconstruction.cpp \ + theory/arrays/array_proof_reconstruction.h \ theory/quantifiers/theory_quantifiers_type_rules.h \ theory/quantifiers/theory_quantifiers.h \ theory/quantifiers/quantifiers_rewriter.h \ @@ -353,6 +361,14 @@ libcvc4_la_SOURCES = \ theory/quantifiers/quant_equality_engine.cpp \ theory/quantifiers/ceg_instantiator.h \ theory/quantifiers/ceg_instantiator.cpp \ + theory/quantifiers/quant_split.h \ + theory/quantifiers/quant_split.cpp \ + theory/quantifiers/anti_skolem.h \ + theory/quantifiers/anti_skolem.cpp \ + theory/quantifiers/equality_infer.h \ + theory/quantifiers/equality_infer.cpp \ + theory/quantifiers/inst_propagator.h \ + theory/quantifiers/inst_propagator.cpp \ theory/arith/theory_arith_type_rules.h \ theory/arith/type_enumerator.h \ theory/arith/arithvar.h \ diff --git a/src/base/configuration.cpp b/src/base/configuration.cpp index c3ba39075..ce8967a18 100644 --- a/src/base/configuration.cpp +++ b/src/base/configuration.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file configuration.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Liana Hadarean, Tim King, ACSYS, Christopher L. Conway, Dejan Jovanovic, Francois Bobot + ** Top contributors (to current version): + ** Morgan Deters, 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 Configuration class, which provides compile-time ** configuration information about the CVC4 library diff --git a/src/base/configuration.h b/src/base/configuration.h index 818652db0..498337c4c 100644 --- a/src/base/configuration.h +++ b/src/base/configuration.h @@ -1,13 +1,13 @@ /********************* */ /*! \file configuration.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): ACSYS, Liana Hadarean, Tim King, Francois Bobot + ** Top contributors (to current version): + ** Morgan Deters, Tim King, Francois Bobot ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2014 New York University and The University of Iowa - ** See the file COPYING in the top-level source directory for licensing - ** information.\endverbatim + ** Copyright (c) 2009-2016 by the authors listed in the file AUTHORS + ** in the top-level 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 to a public class that provides compile-time information ** about the CVC4 library. diff --git a/src/base/configuration_private.h b/src/base/configuration_private.h index 902fdad09..74ce00bdf 100644 --- a/src/base/configuration_private.h +++ b/src/base/configuration_private.h @@ -1,13 +1,13 @@ /********************* */ /*! \file configuration_private.h ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: ACSYS, Morgan Deters - ** Minor contributors (to current version): Liana Hadarean, Tim King + ** Top contributors (to current version): + ** Morgan Deters, Christopher L. Conway, ACSYS ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2014 New York University and The University of Iowa - ** See the file COPYING in the top-level source directory for licensing - ** information.\endverbatim + ** Copyright (c) 2009-2016 by the authors listed in the file AUTHORS + ** in the top-level source directory) and their institutional affiliations. + ** All rights reserved. See the file COPYING in the top-level source + ** directory for licensing information.\endverbatim ** ** \brief Provides compile-time configuration information about the ** CVC4 library. diff --git a/src/base/cvc4_assert.cpp b/src/base/cvc4_assert.cpp index efc71c986..8d5b9e508 100644 --- a/src/base/cvc4_assert.cpp +++ b/src/base/cvc4_assert.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file cvc4_assert.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 Assertion utility classes, functions, and exceptions. ** diff --git a/src/base/cvc4_assert.h b/src/base/cvc4_assert.h index 63ed6d53e..5f67ba57d 100644 --- a/src/base/cvc4_assert.h +++ b/src/base/cvc4_assert.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cvc4_assert.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): ACSYS + ** 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 Assertion utility classes, functions, exceptions, and macros. ** diff --git a/src/base/exception.cpp b/src/base/exception.cpp index cdad92d5d..4f62f68db 100644 --- a/src/base/exception.cpp +++ b/src/base/exception.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file exception.cpp ** \verbatim - ** Original author: Morgan Deters - ** 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 CVC4's exception base class and some associated utilities ** diff --git a/src/base/exception.h b/src/base/exception.h index 38bbe47a4..8f3016e4e 100644 --- a/src/base/exception.h +++ b/src/base/exception.h @@ -1,13 +1,13 @@ /********************* */ /*! \file exception.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 CVC4's exception base class and some associated utilities ** diff --git a/src/base/listener.cpp b/src/base/listener.cpp index 2daced1f5..1f7c6158b 100644 --- a/src/base/listener.cpp +++ b/src/base/listener.cpp @@ -1,13 +1,13 @@ /********************* */ -/*! \file managed_listener.h +/*! \file listener.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-2016 New York University and The University of Iowa - ** See the file COPYING in the top-level source directory for licensing - ** information.\endverbatim + ** Copyright (c) 2009-2016 by the authors listed in the file AUTHORS + ** in the top-level source directory) and their institutional affiliations. + ** All rights reserved. See the file COPYING in the top-level source + ** directory for licensing information.\endverbatim ** ** \brief Output utility classes and functions ** diff --git a/src/base/listener.h b/src/base/listener.h index 8094c634d..724935ae7 100644 --- a/src/base/listener.h +++ b/src/base/listener.h @@ -1,13 +1,13 @@ /********************* */ /*! \file listener.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-2016 New York University and The University of Iowa - ** See the file COPYING in the top-level source directory for licensing - ** information.\endverbatim + ** Copyright (c) 2009-2016 by the authors listed in the file AUTHORS + ** in the top-level 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 classes for listeners and collections of listeners. ** diff --git a/src/base/modal_exception.h b/src/base/modal_exception.h index 44f133372..c662da2c8 100644 --- a/src/base/modal_exception.h +++ b/src/base/modal_exception.h @@ -1,13 +1,13 @@ /********************* */ /*! \file modal_exception.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 that is thrown when an interactive-only ** feature while CVC4 is being used in a non-interactive setting diff --git a/src/base/output.cpp b/src/base/output.cpp index be0f10fda..1d4525701 100644 --- a/src/base/output.cpp +++ b/src/base/output.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file output.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 Output utility classes and functions ** diff --git a/src/base/output.h b/src/base/output.h index 9d1ab03ae..30b5c8ea5 100644 --- a/src/base/output.h +++ b/src/base/output.h @@ -1,13 +1,13 @@ /********************* */ /*! \file output.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Tim King, 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 Output utility classes and functions ** diff --git a/src/base/tls.h.in b/src/base/tls.h.in index 88969e250..a61eb79be 100644 --- a/src/base/tls.h.in +++ b/src/base/tls.h.in @@ -1,13 +1,13 @@ /********************* */ /*! \file tls.h.in ** \verbatim - ** Original author: ACSYS - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Morgan Deters, ACSYS, 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 Header to define CVC4_THREAD whether or not TLS is ** supported by the compiler/runtime platform diff --git a/src/bindings/java_iterator_adapter.h b/src/bindings/java_iterator_adapter.h index 473e056f9..2688f9520 100644 --- a/src/bindings/java_iterator_adapter.h +++ b/src/bindings/java_iterator_adapter.h @@ -1,13 +1,13 @@ /********************* */ /*! \file java_iterator_adapter.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 iterator adapter for the Java bindings, giving Java iterators ** the ability to access elements from STL iterators. diff --git a/src/bindings/java_stream_adapters.h b/src/bindings/java_stream_adapters.h index c198b95aa..12f8713a3 100644 --- a/src/bindings/java_stream_adapters.h +++ b/src/bindings/java_stream_adapters.h @@ -1,13 +1,13 @@ /********************* */ /*! \file java_stream_adapters.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 OutputStream adapter for the Java bindings ** diff --git a/src/bindings/swig.h b/src/bindings/swig.h index 9bece4ecd..7d8f7494e 100644 --- a/src/bindings/swig.h +++ b/src/bindings/swig.h @@ -1,13 +1,13 @@ /********************* */ /*! \file swig.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 Common swig checks and definitions ** diff --git a/src/compat/cvc3_compat.cpp b/src/compat/cvc3_compat.cpp index 52174dce0..50da4e412 100644 --- a/src/compat/cvc3_compat.cpp +++ b/src/compat/cvc3_compat.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file cvc3_compat.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Andrew Reynolds, Tim King, Dejan Jovanovic, Tianyi Liang + ** 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 CVC3 compatibility layer for CVC4 ** @@ -1818,8 +1818,7 @@ Expr ValidityChecker::recordExpr(const std::vector<std::string>& fields, Expr ValidityChecker::recSelectExpr(const Expr& record, const std::string& field) { Type t = record.getType(); const CVC4::Datatype& dt = ((CVC4::DatatypeType)t).getDatatype(); - const CVC4::Record& rec = ((CVC4::DatatypeType)t).getRecord(); - unsigned index = rec.getIndex(field); + unsigned index = CVC4::Datatype::indexOf( dt[0].getSelector(field) ); return d_em->mkExpr(CVC4::kind::APPLY_SELECTOR_TOTAL, dt[0][index].getSelector(), record); } diff --git a/src/compat/cvc3_compat.h b/src/compat/cvc3_compat.h index 5fefa6871..d51670985 100644 --- a/src/compat/cvc3_compat.h +++ b/src/compat/cvc3_compat.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cvc3_compat.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Francois Bobot + ** Top contributors (to current version): + ** Morgan Deters, Tim King, Francois Bobot ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2014 New York University and The University of Iowa - ** See the file COPYING in the top-level source directory for licensing - ** information.\endverbatim + ** Copyright (c) 2009-2016 by the authors listed in the file AUTHORS + ** in the top-level source directory) and their institutional affiliations. + ** All rights reserved. See the file COPYING in the top-level source + ** directory for licensing information.\endverbatim ** ** \brief CVC3 compatibility layer for CVC4 ** diff --git a/src/context/backtrackable.h b/src/context/backtrackable.h index 5492dd8b5..131fabd7c 100644 --- a/src/context/backtrackable.h +++ b/src/context/backtrackable.h @@ -1,13 +1,13 @@ /********************* */ /*! \file backtrackable.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 Contains a backtrackable list ** diff --git a/src/context/cdchunk_list.h b/src/context/cdchunk_list.h index 62a87ffcc..3fa3c6b5d 100644 --- a/src/context/cdchunk_list.h +++ b/src/context/cdchunk_list.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cdchunk_list.h ** \verbatim - ** Original author: Tim King - ** 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 Context-dependent list class designed for use with a ** context memory allocator. diff --git a/src/context/cddense_set.h b/src/context/cddense_set.h index e717adaee..edc5ea558 100644 --- a/src/context/cddense_set.h +++ b/src/context/cddense_set.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cddense_set.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 This is an abstraction of a set of unsigned integers. ** diff --git a/src/context/cdhashmap.h b/src/context/cdhashmap.h index 0eb1d03c9..d080da333 100644 --- a/src/context/cdhashmap.h +++ b/src/context/cdhashmap.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cdhashmap.h ** \verbatim - ** Original author: Dejan Jovanovic - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): Kshitij Bansal, 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 Context-dependent map class. ** diff --git a/src/context/cdhashmap_forward.h b/src/context/cdhashmap_forward.h index 23346435a..b8a361dbb 100644 --- a/src/context/cdhashmap_forward.h +++ b/src/context/cdhashmap_forward.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cdhashmap_forward.h ** \verbatim - ** Original author: Dejan Jovanovic - ** Major contributors: Tim King, Morgan Deters - ** Minor contributors (to current version): none + ** 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 This is a forward declaration header to declare the CDHashMap<> ** template diff --git a/src/context/cdhashset.h b/src/context/cdhashset.h index 533a09a0a..8c450f1ab 100644 --- a/src/context/cdhashset.h +++ b/src/context/cdhashset.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cdhashset.h ** \verbatim - ** Original author: Dejan Jovanovic - ** Major contributors: Tim King, Morgan Deters - ** Minor contributors (to current version): Francois Bobot, Kshitij Bansal + ** Top contributors (to current version): + ** Morgan Deters, Tim King, 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 Context-dependent set class. ** diff --git a/src/context/cdhashset_forward.h b/src/context/cdhashset_forward.h index e96387c06..06ea9c471 100644 --- a/src/context/cdhashset_forward.h +++ b/src/context/cdhashset_forward.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cdhashset_forward.h ** \verbatim - ** Original author: Dejan Jovanovic - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): none + ** 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 This is a forward declaration header to declare the CDSet<> ** template diff --git a/src/context/cdinsert_hashmap.h b/src/context/cdinsert_hashmap.h index b65784ddf..6e772068b 100644 --- a/src/context/cdinsert_hashmap.h +++ b/src/context/cdinsert_hashmap.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cdinsert_hashmap.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 Context-dependent insert only hashmap built using trail of edits ** diff --git a/src/context/cdinsert_hashmap_forward.h b/src/context/cdinsert_hashmap_forward.h index 184b27a3d..5bc6e8fda 100644 --- a/src/context/cdinsert_hashmap_forward.h +++ b/src/context/cdinsert_hashmap_forward.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cdinsert_hashmap_forward.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 This is a forward declaration header to declare the CDInsertHashMap<> ** template diff --git a/src/context/cdlist.h b/src/context/cdlist.h index dbc00bd69..4e42c4688 100644 --- a/src/context/cdlist.h +++ b/src/context/cdlist.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cdlist.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Tim King - ** Minor contributors (to current version): Kshitij Bansal, Francois Bobot + ** Top contributors (to current version): + ** Morgan Deters, Tim King, Francois Bobot ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2014 New York University and The University of Iowa - ** See the file COPYING in the top-level source directory for licensing - ** information.\endverbatim + ** Copyright (c) 2009-2016 by the authors listed in the file AUTHORS + ** in the top-level 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 list class (only supports append) ** diff --git a/src/context/cdlist_forward.h b/src/context/cdlist_forward.h index dd4213f64..101117c23 100644 --- a/src/context/cdlist_forward.h +++ b/src/context/cdlist_forward.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cdlist_forward.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Tim King - ** 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 forward declaration header to declare the ** CDList<> template diff --git a/src/context/cdmaybe.h b/src/context/cdmaybe.h index d47f617a9..458a124ad 100644 --- a/src/context/cdmaybe.h +++ b/src/context/cdmaybe.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cdmaybe.h ** \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 A context-dependent "maybe" template type ** diff --git a/src/context/cdo.h b/src/context/cdo.h index 860648b27..e2fdcf9bd 100644 --- a/src/context/cdo.h +++ b/src/context/cdo.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cdo.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Clark Barrett, Francois Bobot + ** Top contributors (to current version): + ** Morgan Deters, Tim King, Francois Bobot ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2014 New York University and The University of Iowa - ** See the file COPYING in the top-level source directory for licensing - ** information.\endverbatim + ** Copyright (c) 2009-2016 by the authors listed in the file AUTHORS + ** in the top-level 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 context-dependent object. ** diff --git a/src/context/cdqueue.h b/src/context/cdqueue.h index 0e57a7cdb..5aa890d53 100644 --- a/src/context/cdqueue.h +++ b/src/context/cdqueue.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cdqueue.h ** \verbatim - ** Original author: Tim King - ** Major contributors: none - ** Minor contributors (to current version): Francois Bobot, Morgan Deters + ** Top contributors (to current version): + ** Tim King, Francois Bobot, 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 Context-dependent queue class ** diff --git a/src/context/cdtrail_hashmap.h b/src/context/cdtrail_hashmap.h index befd396a9..e89c1b528 100644 --- a/src/context/cdtrail_hashmap.h +++ b/src/context/cdtrail_hashmap.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cdtrail_hashmap.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 Context-dependent hashmap built using trail of elements ** diff --git a/src/context/cdtrail_hashmap_forward.h b/src/context/cdtrail_hashmap_forward.h index 2bfb32539..926c85872 100644 --- a/src/context/cdtrail_hashmap_forward.h +++ b/src/context/cdtrail_hashmap_forward.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cdtrail_hashmap_forward.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 This is a forward declaration header to declare the ** CDTrailHashMap<> template diff --git a/src/context/cdtrail_queue.h b/src/context/cdtrail_queue.h index dff68a161..825557f36 100644 --- a/src/context/cdtrail_queue.h +++ b/src/context/cdtrail_queue.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cdtrail_queue.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 Context-dependent queue class with an explicit trail of elements ** diff --git a/src/context/cdvector.h b/src/context/cdvector.h index fe8f77c6d..2449d78b0 100644 --- a/src/context/cdvector.h +++ b/src/context/cdvector.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cdvector.h ** \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/context/context.cpp b/src/context/context.cpp index 99a98e63f..9c0416ce8 100644 --- a/src/context/context.cpp +++ b/src/context/context.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file context.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 Implementation of base context operations. ** diff --git a/src/context/context.h b/src/context/context.h index b88f36786..4f45e8954 100644 --- a/src/context/context.h +++ b/src/context/context.h @@ -1,13 +1,13 @@ /********************* */ /*! \file context.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Clark Barrett - ** Minor contributors (to current version): Tim King, Dejan Jovanovic + ** 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 Context class and context manager. ** diff --git a/src/context/context_mm.cpp b/src/context/context_mm.cpp index f30413650..0a6b08b6a 100644 --- a/src/context/context_mm.cpp +++ b/src/context/context_mm.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file context_mm.cpp ** \verbatim - ** Original author: Clark Barrett - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Clark Barrett, 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 Context Memory Manager. ** diff --git a/src/context/context_mm.h b/src/context/context_mm.h index 4594ac253..99b448cf2 100644 --- a/src/context/context_mm.h +++ b/src/context/context_mm.h @@ -1,13 +1,13 @@ /********************* */ /*! \file context_mm.h ** \verbatim - ** Original author: Clark Barrett - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Clark Barrett, 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 Region-based memory manager with stack-based push and pop. ** diff --git a/src/context/stacking_vector.h b/src/context/stacking_vector.h index 578a2e3ae..b737c40ae 100644 --- a/src/context/stacking_vector.h +++ b/src/context/stacking_vector.h @@ -1,13 +1,13 @@ /********************* */ /*! \file stacking_vector.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 Backtrackable vector using an undo stack ** diff --git a/src/decision/decision_attributes.h b/src/decision/decision_attributes.h index 03229ac84..cc2c766e3 100644 --- a/src/decision/decision_attributes.h +++ b/src/decision/decision_attributes.h @@ -1,13 +1,13 @@ /********************* */ /*! \file decision_attributes.h ** \verbatim - ** Original author: Kshitij Bansal - ** Major contributors: Morgan Deters - ** 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 Rewriter attributes ** diff --git a/src/decision/decision_engine.cpp b/src/decision/decision_engine.cpp index 12400a3b1..71e4f4ec3 100644 --- a/src/decision/decision_engine.cpp +++ b/src/decision/decision_engine.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file decision_engine.cpp ** \verbatim - ** Original author: Kshitij Bansal - ** Major contributors: none - ** Minor contributors (to current version): Tim King, 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 Decision engine ** diff --git a/src/decision/decision_engine.h b/src/decision/decision_engine.h index de8a67413..92d203cb3 100644 --- a/src/decision/decision_engine.h +++ b/src/decision/decision_engine.h @@ -1,13 +1,13 @@ /********************* */ /*! \file decision_engine.h ** \verbatim - ** Original author: Kshitij Bansal - ** Major contributors: none - ** Minor contributors (to current version): Clark Barrett, Dejan Jovanovic, Morgan Deters, Tim King + ** 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 Decision engine ** diff --git a/src/decision/decision_strategy.h b/src/decision/decision_strategy.h index fca48ced1..591f018d8 100644 --- a/src/decision/decision_strategy.h +++ b/src/decision/decision_strategy.h @@ -1,13 +1,13 @@ /********************* */ /*! \file decision_strategy.h ** \verbatim - ** Original author: Kshitij Bansal - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Kshitij Bansal, 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 Decision strategy ** diff --git a/src/decision/justification_heuristic.cpp b/src/decision/justification_heuristic.cpp index bdde41b52..cfa478c7d 100644 --- a/src/decision/justification_heuristic.cpp +++ b/src/decision/justification_heuristic.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file justification_heuristic.cpp ** \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 Justification heuristic for decision making ** diff --git a/src/decision/justification_heuristic.h b/src/decision/justification_heuristic.h index 5b0deca1b..c03bba0c0 100644 --- a/src/decision/justification_heuristic.h +++ b/src/decision/justification_heuristic.h @@ -1,13 +1,13 @@ /********************* */ /*! \file justification_heuristic.h ** \verbatim - ** Original author: Kshitij Bansal - ** Major contributors: none - ** Minor contributors (to current version): Tim King, 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 Justification heuristic for decision making ** diff --git a/src/expr/array.h b/src/expr/array.h index ab554171f..cf050e077 100644 --- a/src/expr/array.h +++ b/src/expr/array.h @@ -1,13 +1,13 @@ /********************* */ /*! \file array.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 Array types. ** diff --git a/src/expr/array_store_all.cpp b/src/expr/array_store_all.cpp index 6ac07c81d..c8e346e48 100644 --- a/src/expr/array_store_all.cpp +++ b/src/expr/array_store_all.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file array_store_all.cpp ** \verbatim - ** Original author: Morgan Deters - ** 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 Representation of a constant array (an array in which the ** element is the same for all indices) diff --git a/src/expr/array_store_all.h b/src/expr/array_store_all.h index 293b785a9..0a9c8344a 100644 --- a/src/expr/array_store_all.h +++ b/src/expr/array_store_all.h @@ -1,13 +1,13 @@ /********************* */ /*! \file array_store_all.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 Representation of a constant array (an array in which the ** element is the same for all indices) diff --git a/src/expr/ascription_type.h b/src/expr/ascription_type.h index 42906e557..46d2871ff 100644 --- a/src/expr/ascription_type.h +++ b/src/expr/ascription_type.h @@ -1,13 +1,13 @@ /********************* */ /*! \file ascription_type.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 A class representing a type ascription ** diff --git a/src/expr/attribute.cpp b/src/expr/attribute.cpp index cd5b35384..3cf242988 100644 --- a/src/expr/attribute.cpp +++ b/src/expr/attribute.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file attribute.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Dejan Jovanovic, Tim King - ** Minor contributors (to current version): none + ** 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 AttributeManager implementation. ** diff --git a/src/expr/attribute.h b/src/expr/attribute.h index 432fbbac9..13bedeaf8 100644 --- a/src/expr/attribute.h +++ b/src/expr/attribute.h @@ -1,13 +1,13 @@ /********************* */ /*! \file attribute.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Tim King - ** Minor contributors (to current version): Christopher L. Conway, 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 Node attributes. ** diff --git a/src/expr/attribute_internals.h b/src/expr/attribute_internals.h index dae11fd74..60d2069e7 100644 --- a/src/expr/attribute_internals.h +++ b/src/expr/attribute_internals.h @@ -1,13 +1,13 @@ /********************* */ /*! \file attribute_internals.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Dejan Jovanovic, Tim King + ** 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 Node attributes' internals. ** diff --git a/src/expr/attribute_unique_id.h b/src/expr/attribute_unique_id.h index 45dc368a5..4875bdf50 100644 --- a/src/expr/attribute_unique_id.h +++ b/src/expr/attribute_unique_id.h @@ -1,13 +1,13 @@ /********************* */ /*! \file attribute_unique_id.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/expr/chain.h b/src/expr/chain.h index e052a2ed8..703aa76ed 100644 --- a/src/expr/chain.h +++ b/src/expr/chain.h @@ -1,13 +1,13 @@ /********************* */ /*! \file chain.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 [[ Add one-line brief description here ]] ** diff --git a/src/expr/convenience_node_builders.h b/src/expr/convenience_node_builders.h index 0c3b690b2..611a88e6f 100644 --- a/src/expr/convenience_node_builders.h +++ b/src/expr/convenience_node_builders.h @@ -1,13 +1,13 @@ /********************* */ /*! \file convenience_node_builders.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 Convenience node builders. ** diff --git a/src/expr/datatype.cpp b/src/expr/datatype.cpp index 32c0bb6dd..d14ac26d4 100644 --- a/src/expr/datatype.cpp +++ b/src/expr/datatype.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file datatype.cpp ** \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 A class representing a Datatype definition ** @@ -51,6 +51,10 @@ typedef expr::Attribute<expr::attr::DatatypeFiniteComputedTag, bool> DatatypeFin typedef expr::Attribute<expr::attr::DatatypeUFiniteTag, bool> DatatypeUFiniteAttr; typedef expr::Attribute<expr::attr::DatatypeUFiniteComputedTag, bool> DatatypeUFiniteComputedAttr; +Datatype::~Datatype(){ + delete d_record; +} + const Datatype& Datatype::datatypeOf(Expr item) { ExprManagerScope ems(item); TypeNode t = Node::fromExpr(item).getType(); @@ -133,6 +137,14 @@ void Datatype::resolve(ExprManager* em, d_involvesUt = true; } } + + if( d_isRecord ){ + std::vector< std::pair<std::string, Type> > fields; + for( unsigned i=0; i<(*this)[0].getNumArgs(); i++ ){ + fields.push_back( std::pair<std::string, Type>( (*this)[0][i].getName(), (*this)[0][i].getRangeType() ) ); + } + d_record = new Record(fields); + } } void Datatype::addConstructor(const DatatypeConstructor& c) { @@ -152,10 +164,12 @@ void Datatype::setSygus( Type st, Expr bvl, bool allow_const, bool allow_all ){ } void Datatype::setTuple() { + PrettyCheckArgument(!d_resolved, this, "cannot set tuple to a finalized Datatype"); d_isTuple = true; } void Datatype::setRecord() { + PrettyCheckArgument(!d_resolved, this, "cannot set record to a finalized Datatype"); d_isRecord = true; } @@ -185,20 +199,24 @@ Cardinality Datatype::computeCardinality( std::vector< Type >& processing ) cons bool Datatype::isRecursiveSingleton() const throw(IllegalArgumentException) { PrettyCheckArgument(isResolved(), this, "this datatype is not yet resolved"); if( d_card_rec_singleton==0 ){ - Assert( d_card_u_assume.empty() ); - std::vector< Type > processing; - if( computeCardinalityRecSingleton( processing, d_card_u_assume ) ){ - d_card_rec_singleton = 1; + if( isCodatatype() ){ + Assert( d_card_u_assume.empty() ); + std::vector< Type > processing; + if( computeCardinalityRecSingleton( processing, d_card_u_assume ) ){ + d_card_rec_singleton = 1; + }else{ + d_card_rec_singleton = -1; + } + if( d_card_rec_singleton==1 ){ + Trace("dt-card") << "Datatype " << getName() << " is recursive singleton, dependent upon " << d_card_u_assume.size() << " uninterpreted sorts: " << std::endl; + for( unsigned i=0; i<d_card_u_assume.size(); i++ ){ + Trace("dt-card") << " " << d_card_u_assume [i] << std::endl; + } + Trace("dt-card") << std::endl; + } }else{ d_card_rec_singleton = -1; } - if( d_card_rec_singleton==1 ){ - Trace("dt-card") << "Datatype " << getName() << " is recursive singleton, dependent upon " << d_card_u_assume.size() << " uninterpreted sorts: " << std::endl; - for( unsigned i=0; i<d_card_u_assume.size(); i++ ){ - Trace("dt-card") << " " << d_card_u_assume [i] << std::endl; - } - Trace("dt-card") << std::endl; - } } return d_card_rec_singleton==1; } @@ -288,10 +306,11 @@ bool Datatype::isUFinite() const throw(IllegalArgumentException) { if(self.getAttribute(DatatypeUFiniteComputedAttr())) { return self.getAttribute(DatatypeUFiniteAttr()); } + //start by assuming it is not + self.setAttribute(DatatypeUFiniteComputedAttr(), true); + self.setAttribute(DatatypeUFiniteAttr(), false); for(const_iterator i = begin(), i_end = end(); i != i_end; ++i) { if(! (*i).isUFinite()) { - self.setAttribute(DatatypeUFiniteComputedAttr(), true); - self.setAttribute(DatatypeUFiniteAttr(), false); return false; } } @@ -820,7 +839,7 @@ bool DatatypeConstructor::isFinite() const throw(IllegalArgumentException) { return self.getAttribute(DatatypeFiniteAttr()); } for(const_iterator i = begin(), i_end = end(); i != i_end; ++i) { - if(! SelectorType((*i).getSelector().getType()).getRangeType().getCardinality().isFinite()) { + if(! (*i).getRangeType().getCardinality().isFinite()) { self.setAttribute(DatatypeFiniteComputedAttr(), true); self.setAttribute(DatatypeFiniteAttr(), false); return false; @@ -840,9 +859,18 @@ bool DatatypeConstructor::isUFinite() const throw(IllegalArgumentException) { if(self.getAttribute(DatatypeUFiniteComputedAttr())) { return self.getAttribute(DatatypeUFiniteAttr()); } + bool success = true; for(const_iterator i = begin(), i_end = end(); i != i_end; ++i) { - Type t = SelectorType((*i).getSelector().getType()).getRangeType(); - if(!t.isSort() && !t.getCardinality().isFinite()) { + Type t = (*i).getRangeType(); + if( t.isDatatype() ){ + const Datatype& dt = ((DatatypeType)t).getDatatype(); + if( !dt.isUFinite() ){ + success = false; + } + }else if(!t.isSort() && !t.getCardinality().isFinite()) { + success = false; + } + if(!success ){ self.setAttribute(DatatypeUFiniteComputedAttr(), true); self.setAttribute(DatatypeUFiniteAttr(), false); return false; @@ -974,6 +1002,10 @@ SelectorType DatatypeConstructorArg::getType() const { return getSelector().getType(); } +Type DatatypeConstructorArg::getRangeType() const { + return getType().getRangeType(); +} + bool DatatypeConstructorArg::isUnresolvedSelf() const throw() { return d_selector.isNull() && d_name.size() == d_name.find('\0') + 1; } diff --git a/src/expr/datatype.h b/src/expr/datatype.h index 625fbb5d4..1197b4a3b 100644 --- a/src/expr/datatype.h +++ b/src/expr/datatype.h @@ -1,13 +1,13 @@ /********************* */ /*! \file datatype.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 A class representing a Datatype definition ** @@ -155,6 +155,11 @@ public: SelectorType getType() const; /** + * Get the range type of this argument. + */ + Type getRangeType() const; + + /** * Get the name of the type of this constructor argument * (Datatype field). Can be used for not-yet-resolved Datatypes * (in which case the name of the unresolved type, or "[self]" @@ -474,6 +479,7 @@ private: bool d_isCo; bool d_isTuple; bool d_isRecord; + Record * d_record; std::vector<DatatypeConstructor> d_constructors; bool d_resolved; Type d_self; @@ -553,6 +559,8 @@ public: */ inline Datatype(std::string name, const std::vector<Type>& params, bool isCo = false); + ~Datatype(); + /** * Add a constructor to this Datatype. Constructor names need not * be unique; they are for convenience and pretty-printing only. @@ -602,6 +610,9 @@ public: /** is this a record datatype? */ inline bool isRecord() const; + /** get the record representation for this datatype */ + inline Record * getRecord() const; + /** * Return the cardinality of this datatype (the sum of the * cardinalities of its constructors). The Datatype must be @@ -772,6 +783,7 @@ inline Datatype::Datatype(std::string name, bool isCo) : d_isCo(isCo), d_isTuple(false), d_isRecord(false), + d_record(NULL), d_constructors(), d_resolved(false), d_self(), @@ -788,6 +800,7 @@ inline Datatype::Datatype(std::string name, const std::vector<Type>& params, boo d_isCo(isCo), d_isTuple(false), d_isRecord(false), + d_record(NULL), d_constructors(), d_resolved(false), d_self(), @@ -844,6 +857,10 @@ inline bool Datatype::isRecord() const { return d_isRecord; } +inline Record * Datatype::getRecord() const { + return d_record; +} + inline bool Datatype::operator!=(const Datatype& other) const throw() { return !(*this == other); } diff --git a/src/expr/emptyset.cpp b/src/expr/emptyset.cpp index a6e2c1ece..23e6df7dc 100644 --- a/src/expr/emptyset.cpp +++ b/src/expr/emptyset.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file emptyset.cpp ** \verbatim - ** Original author: Kshitij Bansal - ** Major contributors: none - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Tim King, Kshitij Bansal, 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/expr/emptyset.h b/src/expr/emptyset.h index cf9d050f8..a606951f0 100644 --- a/src/expr/emptyset.h +++ b/src/expr/emptyset.h @@ -1,13 +1,13 @@ /********************* */ /*! \file emptyset.h ** \verbatim - ** Original author: Kshitij Bansal - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Tim King, Kshitij Bansal, 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/expr/expr.i b/src/expr/expr.i index b50686f52..354cacdc0 100644 --- a/src/expr/expr.i +++ b/src/expr/expr.i @@ -130,7 +130,13 @@ namespace CVC4 { %include "expr/expr.h" +#ifdef SWIGPYTHON +/* The python bindings on Mac OS X have trouble with this one - leave it + * out for now. */ +//%template(getConstTypeConstant) CVC4::Expr::getConst<CVC4::TypeConstant>; +#else %template(getConstTypeConstant) CVC4::Expr::getConst<CVC4::TypeConstant>; +#endif %template(getConstArrayStoreAll) CVC4::Expr::getConst<CVC4::ArrayStoreAll>; %template(getConstBitVectorSize) CVC4::Expr::getConst<CVC4::BitVectorSize>; %template(getConstAscriptionType) CVC4::Expr::getConst<CVC4::AscriptionType>; diff --git a/src/expr/expr_iomanip.cpp b/src/expr/expr_iomanip.cpp index 4c7ab3c8b..1d6df2a4e 100644 --- a/src/expr/expr_iomanip.cpp +++ b/src/expr/expr_iomanip.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file expr_iomanip.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) 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 Expr IO manipulation classes. ** diff --git a/src/expr/expr_iomanip.h b/src/expr/expr_iomanip.h index b3370e75a..94e2b46ea 100644 --- a/src/expr/expr_iomanip.h +++ b/src/expr/expr_iomanip.h @@ -1,13 +1,13 @@ /********************* */ /*! \file expr_iomanip.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) 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 Expr IO manipulation classes. ** diff --git a/src/expr/expr_manager.i b/src/expr/expr_manager.i index 66930cf55..11c1e284d 100644 --- a/src/expr/expr_manager.i +++ b/src/expr/expr_manager.i @@ -40,7 +40,6 @@ %include "expr/expr_manager.h" -%template(mkConst) CVC4::ExprManager::mkConst<CVC4::TypeConstant>; %template(mkConst) CVC4::ExprManager::mkConst<CVC4::ArrayStoreAll>; %template(mkConst) CVC4::ExprManager::mkConst<CVC4::BitVectorSize>; %template(mkConst) CVC4::ExprManager::mkConst<CVC4::AscriptionType>; @@ -67,10 +66,7 @@ %template(mkConst) CVC4::ExprManager::mkConst<CVC4::UninterpretedConstant>; %template(mkConst) CVC4::ExprManager::mkConst<CVC4::kind::Kind_t>; %template(mkConst) CVC4::ExprManager::mkConst<CVC4::Datatype>; -%template(mkConst) CVC4::ExprManager::mkConst<CVC4::TupleSelect>; %template(mkConst) CVC4::ExprManager::mkConst<CVC4::TupleUpdate>; -%template(mkConst) CVC4::ExprManager::mkConst<CVC4::Record>; -%template(mkConst) CVC4::ExprManager::mkConst<CVC4::RecordSelect>; %template(mkConst) CVC4::ExprManager::mkConst<CVC4::RecordUpdate>; %template(mkConst) CVC4::ExprManager::mkConst<CVC4::Rational>; %template(mkConst) CVC4::ExprManager::mkConst<CVC4::BitVector>; @@ -78,6 +74,25 @@ %template(mkConst) CVC4::ExprManager::mkConst<CVC4::EmptySet>; %template(mkConst) CVC4::ExprManager::mkConst<CVC4::String>; %template(mkConst) CVC4::ExprManager::mkConst<CVC4::RegExp>; +#ifdef SWIGPYTHON +/* The python bindings cannot differentiate between bool and other basic + * types like enum and int. Therefore, we rename mkConst for the bool + * case into mkBoolConst. +*/ +%template(mkBoolConst) CVC4::ExprManager::mkConst<bool>; + +// These cases have trouble too. Remove them for now. +//%template(mkConst) CVC4::ExprManager::mkConst<CVC4::TypeConstant>; +//%template(mkConst) CVC4::ExprManager::mkConst<CVC4::TupleSelect>; +//%template(mkConst) CVC4::ExprManager::mkConst<CVC4::Record>; +//%template(mkConst) CVC4::ExprManager::mkConst<CVC4::RecordSelect>; + +#else +%template(mkConst) CVC4::ExprManager::mkConst<CVC4::TypeConstant>; +%template(mkConst) CVC4::ExprManager::mkConst<CVC4::TupleSelect>; +%template(mkConst) CVC4::ExprManager::mkConst<CVC4::Record>; +%template(mkConst) CVC4::ExprManager::mkConst<CVC4::RecordSelect>; %template(mkConst) CVC4::ExprManager::mkConst<bool>; +#endif %include "expr/expr_manager.h" diff --git a/src/expr/expr_manager_scope.h b/src/expr/expr_manager_scope.h index a8e8f04be..cd4c274e5 100644 --- a/src/expr/expr_manager_scope.h +++ b/src/expr/expr_manager_scope.h @@ -1,13 +1,13 @@ /********************* */ /*! \file expr_manager_scope.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/expr/expr_manager_template.cpp b/src/expr/expr_manager_template.cpp index ce7a92b48..84f674d2b 100644 --- a/src/expr/expr_manager_template.cpp +++ b/src/expr/expr_manager_template.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file expr_manager_template.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Dejan Jovanovic, Christopher L. Conway - ** Minor contributors (to current version): Kshitij Bansal, Andrew Reynolds + ** Top contributors (to current version): + ** Morgan Deters, Tim King, 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 Public-facing expression manager interface, implementation ** @@ -142,6 +142,11 @@ StringType ExprManager::stringType() const { return StringType(Type(d_nodeManager, new TypeNode(d_nodeManager->stringType()))); } +RegExpType ExprManager::regExpType() const { + NodeManagerScope nms(d_nodeManager); + return StringType(Type(d_nodeManager, new TypeNode(d_nodeManager->regExpType()))); +} + RealType ExprManager::realType() const { NodeManagerScope nms(d_nodeManager); return RealType(Type(d_nodeManager, new TypeNode(d_nodeManager->realType()))); @@ -791,7 +796,7 @@ void ExprManager::checkResolvedDatatype(DatatypeType dtt) const { j != j_end; ++j) { const DatatypeConstructorArg& a = *j; - Type selectorType = a.getSelector().getType(); + Type selectorType = a.getType(); Assert(a.isResolved() && selectorType.isSelector() && SelectorType(selectorType).getDomain() == dtt, diff --git a/src/expr/expr_manager_template.h b/src/expr/expr_manager_template.h index 37ef128f4..04f2f4289 100644 --- a/src/expr/expr_manager_template.h +++ b/src/expr/expr_manager_template.h @@ -1,13 +1,13 @@ /********************* */ /*! \file expr_manager_template.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Dejan Jovanovic - ** Minor contributors (to current version): Andrew Reynolds, Kshitij Bansal, Tim King, Christopher L. Conway + ** 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 Public-facing expression manager interface ** @@ -121,6 +121,9 @@ public: /** Get the type for strings. */ StringType stringType() const; + /** Get the type for regular expressions. */ + RegExpType regExpType() const; + /** Get the type for reals. */ RealType realType() const; diff --git a/src/expr/expr_stream.h b/src/expr/expr_stream.h index 20977011c..d3dbd2902 100644 --- a/src/expr/expr_stream.h +++ b/src/expr/expr_stream.h @@ -1,13 +1,13 @@ /********************* */ /*! \file expr_stream.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 A stream interface for expressions ** diff --git a/src/expr/expr_template.cpp b/src/expr/expr_template.cpp index a6cdedd00..43e4a7b76 100644 --- a/src/expr/expr_template.cpp +++ b/src/expr/expr_template.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file expr_template.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Dejan Jovanovic, Kshitij Bansal - ** Minor contributors (to current version): Tim King, Christopher L. Conway + ** Top contributors (to current version): + ** Morgan Deters, Kshitij Bansal, 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 Public-facing expression interface, implementation. ** diff --git a/src/expr/expr_template.h b/src/expr/expr_template.h index d037a6bb9..5c3f89e9c 100644 --- a/src/expr/expr_template.h +++ b/src/expr/expr_template.h @@ -1,13 +1,13 @@ /********************* */ /*! \file expr_template.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Dejan Jovanovic - ** Minor contributors (to current version): Liana Hadarean, Kshitij Bansal, Tim King, Christopher L. Conway + ** 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 Public-facing expression interface. ** diff --git a/src/expr/kind_map.h b/src/expr/kind_map.h index 02e9728f0..6858f8ab9 100644 --- a/src/expr/kind_map.h +++ b/src/expr/kind_map.h @@ -1,13 +1,13 @@ /********************* */ /*! \file kind_map.h ** \verbatim - ** Original author: Dejan Jovanovic - ** Major contributors: none - ** Minor contributors (to current version): Morgan Deters + ** Top contributors (to current version): + ** 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 bitmap of Kinds ** diff --git a/src/expr/kind_template.h b/src/expr/kind_template.h index 799d1ac33..440d6b586 100644 --- a/src/expr/kind_template.h +++ b/src/expr/kind_template.h @@ -1,13 +1,13 @@ /********************* */ /*! \file kind_template.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Dejan Jovanovic - ** 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 Template for the Node kind header ** diff --git a/src/expr/matcher.h b/src/expr/matcher.h index 8cb092a64..308ad06df 100644 --- a/src/expr/matcher.h +++ b/src/expr/matcher.h @@ -1,13 +1,13 @@ /********************* */ /*! \file matcher.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 A class representing a type matcher ** diff --git a/src/expr/metakind_template.h b/src/expr/metakind_template.h index 539db1c91..9025aa02a 100644 --- a/src/expr/metakind_template.h +++ b/src/expr/metakind_template.h @@ -1,13 +1,13 @@ /********************* */ /*! \file metakind_template.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Tim King + ** 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 Template for the metakind header. ** diff --git a/src/expr/node.cpp b/src/expr/node.cpp index cf9a772b7..793b6af97 100644 --- a/src/expr/node.cpp +++ b/src/expr/node.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file node.cpp ** \verbatim - ** Original author: Dejan Jovanovic - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): Tim King + ** 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 Reference-counted encapsulation of a pointer to node information. ** diff --git a/src/expr/node.h b/src/expr/node.h index a51de6d66..998294da3 100644 --- a/src/expr/node.h +++ b/src/expr/node.h @@ -1,13 +1,13 @@ /********************* */ /*! \file node.h ** \verbatim - ** Original author: Dejan Jovanovic - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): Kshitij Bansal, Francois Bobot, Clark Barrett, Tim King, Christopher L. Conway + ** 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 Reference-counted encapsulation of a pointer to node information ** diff --git a/src/expr/node_builder.h b/src/expr/node_builder.h index e1a083a78..0dd4e44e8 100644 --- a/src/expr/node_builder.h +++ b/src/expr/node_builder.h @@ -1,13 +1,13 @@ /********************* */ /*! \file node_builder.h ** \verbatim - ** Original author: Dejan Jovanovic - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): Tim King, Christopher L. Conway + ** 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 A builder interface for Nodes. ** diff --git a/src/expr/node_manager.cpp b/src/expr/node_manager.cpp index e6e44928d..0809a0331 100644 --- a/src/expr/node_manager.cpp +++ b/src/expr/node_manager.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file node_manager.cpp ** \verbatim - ** Original author: Dejan Jovanovic - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): ACSYS, Kshitij Bansal, Tim King, Christopher L. Conway + ** 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 Expression manager implementation. ** @@ -170,7 +170,9 @@ NodeManager::~NodeManager() { d_operators[i] = Node::null(); } - d_tupleAndRecordTypes.clear(); + //d_tupleAndRecordTypes.clear(); + d_tt_cache.d_children.clear(); + d_rt_cache.d_children.clear(); Assert(!d_attrManager->inGarbageCollection() ); while(!d_zombies.empty()) { @@ -461,6 +463,47 @@ TypeNode NodeManager::mkSubrangeType(const SubrangeBounds& bounds) return TypeNode(mkTypeConst(bounds)); } +TypeNode NodeManager::TupleTypeCache::getTupleType( NodeManager * nm, std::vector< TypeNode >& types, unsigned index ) { + if( index==types.size() ){ + if( d_data.isNull() ){ + Datatype dt("__cvc4_tuple"); + dt.setTuple(); + DatatypeConstructor c("__cvc4_tuple_ctor"); + for (unsigned i = 0; i < types.size(); ++ i) { + std::stringstream ss; + ss << "__cvc4_tuple_stor_" << i; + c.addArg(ss.str().c_str(), types[i].toType()); + } + dt.addConstructor(c); + d_data = TypeNode::fromType(nm->toExprManager()->mkDatatypeType(dt)); + Debug("tuprec-debug") << "Return type : " << d_data << std::endl; + } + return d_data; + }else{ + return d_children[types[index]].getTupleType( nm, types, index+1 ); + } +} + +TypeNode NodeManager::RecTypeCache::getRecordType( NodeManager * nm, const Record& rec, unsigned index ) { + if( index==rec.getNumFields() ){ + if( d_data.isNull() ){ + const Record::FieldVector& fields = rec.getFields(); + Datatype dt("__cvc4_record"); + dt.setRecord(); + DatatypeConstructor c("__cvc4_record_ctor"); + for(Record::FieldVector::const_iterator i = fields.begin(); i != fields.end(); ++i) { + c.addArg((*i).first, (*i).second); + } + dt.addConstructor(c); + d_data = TypeNode::fromType(nm->toExprManager()->mkDatatypeType(dt)); + Debug("tuprec-debug") << "Return type : " << d_data << std::endl; + } + return d_data; + }else{ + return d_children[TypeNode::fromType( rec[index].second )][rec[index].first].getRecordType( nm, rec, index+1 ); + } +} + TypeNode NodeManager::mkTupleType(const std::vector<TypeNode>& types) { std::vector< TypeNode > ts; Debug("tuprec-debug") << "Make tuple type : "; @@ -470,60 +513,11 @@ TypeNode NodeManager::mkTupleType(const std::vector<TypeNode>& types) { Debug("tuprec-debug") << types[i] << " "; } Debug("tuprec-debug") << std::endl; - //index based on function type - TypeNode tindex; - if( types.empty() ){ - //do nothing (will index on null type) - }else if( types.size()==1 ){ - tindex = types[0]; - }else{ - TypeNode tt = ts.back(); - ts.pop_back(); - tindex = mkFunctionType( ts, tt ); - ts.push_back( tt ); - } - TypeNode& dtt = d_tupleAndRecordTypes[tindex]; - if(dtt.isNull()) { - Datatype dt("__cvc4_tuple"); - dt.setTuple(); - DatatypeConstructor c("__cvc4_tuple_ctor"); - for (unsigned i = 0; i < ts.size(); ++ i) { - std::stringstream ss; - ss << "__cvc4_tuple_stor_" << i; - c.addArg(ss.str().c_str(), ts[i].toType()); - } - dt.addConstructor(c); - dtt = TypeNode::fromType(toExprManager()->mkDatatypeType(dt)); - dtt.setAttribute(DatatypeTupleAttr(), tindex); - Debug("tuprec-debug") << "Return type : " << dtt << std::endl; - }else{ - Debug("tuprec-debug") << "Return cached type : " << dtt << std::endl; - } - Assert(!dtt.isNull()); - return dtt; + return d_tt_cache.getTupleType( this, ts ); } TypeNode NodeManager::mkRecordType(const Record& rec) { - //index based on type constant - TypeNode tindex = mkTypeConst(rec); - TypeNode& dtt = d_tupleAndRecordTypes[tindex]; - if(dtt.isNull()) { - const Record::FieldVector& fields = rec.getFields(); - Datatype dt("__cvc4_record"); - dt.setRecord(); - DatatypeConstructor c("__cvc4_record_ctor"); - for(Record::FieldVector::const_iterator i = fields.begin(); i != fields.end(); ++i) { - c.addArg((*i).first, (*i).second); - } - dt.addConstructor(c); - dtt = TypeNode::fromType(toExprManager()->mkDatatypeType(dt)); - dtt.setAttribute(DatatypeRecordAttr(), tindex); - Debug("tuprec-debug") << "Return type : " << dtt << std::endl; - }else{ - Debug("tuprec-debug") << "Return cached type : " << dtt << std::endl; - } - Assert(!dtt.isNull()); - return dtt; + return d_rt_cache.getRecordType( this, rec ); } void NodeManager::reclaimAllZombies(){ diff --git a/src/expr/node_manager.h b/src/expr/node_manager.h index 45c9afbde..7d2b13e4c 100644 --- a/src/expr/node_manager.h +++ b/src/expr/node_manager.h @@ -1,13 +1,13 @@ /********************* */ /*! \file node_manager.h ** \verbatim - ** Original author: Dejan Jovanovic - ** Major contributors: Christopher L. Conway, Morgan Deters - ** Minor contributors (to current version): ACSYS, Tianyi Liang, Kshitij Bansal, Tim King + ** Top contributors (to current version): + ** Morgan Deters, Christopher L. Conway, 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 manager for Nodes ** @@ -166,7 +166,20 @@ class NodeManager { /** * A map of tuple and record types to their corresponding datatype. */ - std::hash_map<TypeNode, TypeNode, TypeNodeHashFunction> d_tupleAndRecordTypes; + class TupleTypeCache { + public: + std::map< TypeNode, TupleTypeCache > d_children; + TypeNode d_data; + TypeNode getTupleType( NodeManager * nm, std::vector< TypeNode >& types, unsigned index = 0 ); + }; + class RecTypeCache { + public: + std::map< TypeNode, std::map< std::string, RecTypeCache > > d_children; + TypeNode d_data; + TypeNode getRecordType( NodeManager * nm, const Record& rec, unsigned index = 0 ); + }; + TupleTypeCache d_tt_cache; + RecTypeCache d_rt_cache; /** * Keep a count of all abstract values produced by this NodeManager. @@ -692,7 +705,7 @@ public: inline TypeNode stringType(); /** Get the (singleton) type for RegExp. */ - inline TypeNode regexpType(); + inline TypeNode regExpType(); /** Get the (singleton) type for rounding modes. */ inline TypeNode roundingModeType(); @@ -988,7 +1001,7 @@ inline TypeNode NodeManager::stringType() { } /** Get the (singleton) type for regexps. */ -inline TypeNode NodeManager::regexpType() { +inline TypeNode NodeManager::regExpType() { return TypeNode(mkTypeConst<TypeConstant>(REGEXP_TYPE)); } diff --git a/src/expr/node_manager_attributes.h b/src/expr/node_manager_attributes.h index 41086ac21..20e1c6c50 100644 --- a/src/expr/node_manager_attributes.h +++ b/src/expr/node_manager_attributes.h @@ -1,13 +1,13 @@ /********************* */ /*! \file node_manager_attributes.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 [[ Add one-line brief description here ]] ** @@ -28,8 +28,6 @@ namespace attr { struct VarNameTag { }; struct GlobalVarTag { }; struct SortArityTag { }; - struct DatatypeTupleTag { }; - struct DatatypeRecordTag { }; struct TypeTag { }; struct TypeCheckedTag { }; }/* CVC4::expr::attr namespace */ @@ -37,10 +35,6 @@ namespace attr { typedef Attribute<attr::VarNameTag, std::string> VarNameAttr; typedef Attribute<attr::GlobalVarTag(), bool> GlobalVarAttr; typedef Attribute<attr::SortArityTag, uint64_t> SortArityAttr; -/** Attribute true for datatype types that are replacements for tuple types */ -typedef expr::Attribute<expr::attr::DatatypeTupleTag, TypeNode> DatatypeTupleAttr; -/** Attribute true for datatype types that are replacements for record types */ -typedef expr::Attribute<expr::attr::DatatypeRecordTag, TypeNode> DatatypeRecordAttr; typedef expr::Attribute<expr::attr::TypeTag, TypeNode> TypeAttr; typedef expr::Attribute<expr::attr::TypeCheckedTag, bool> TypeCheckedAttr; diff --git a/src/expr/node_manager_listeners.cpp b/src/expr/node_manager_listeners.cpp index ec2de105a..3915aa9bd 100644 --- a/src/expr/node_manager_listeners.cpp +++ b/src/expr/node_manager_listeners.cpp @@ -1,13 +1,13 @@ /********************* */ -/*! \file node_manager_listeners.h +/*! \file node_manager_listeners.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 Listeners that NodeManager registers to its Options object. ** diff --git a/src/expr/node_manager_listeners.h b/src/expr/node_manager_listeners.h index fc7c2f65f..caff3a545 100644 --- a/src/expr/node_manager_listeners.h +++ b/src/expr/node_manager_listeners.h @@ -1,13 +1,13 @@ /********************* */ /*! \file node_manager_listeners.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 Listeners that NodeManager registers to its Options object. ** diff --git a/src/expr/node_self_iterator.h b/src/expr/node_self_iterator.h index 77fc05e3b..9d37f6e6e 100644 --- a/src/expr/node_self_iterator.h +++ b/src/expr/node_self_iterator.h @@ -1,13 +1,13 @@ /********************* */ /*! \file node_self_iterator.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 Iterator supporting Node "self-iteration" ** diff --git a/src/expr/node_value.cpp b/src/expr/node_value.cpp index ab18973cb..a40075ca9 100644 --- a/src/expr/node_value.cpp +++ b/src/expr/node_value.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file node_value.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Dejan Jovanovic + ** 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 An expression node. ** diff --git a/src/expr/node_value.h b/src/expr/node_value.h index c39c14604..fbf3ff76e 100644 --- a/src/expr/node_value.h +++ b/src/expr/node_value.h @@ -1,13 +1,13 @@ /********************* */ /*! \file node_value.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Christopher L. Conway, Tim King, Dejan Jovanovic + ** 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 An expression node. ** diff --git a/src/expr/pickle_data.cpp b/src/expr/pickle_data.cpp index e273bcece..2050d2d15 100644 --- a/src/expr/pickle_data.cpp +++ b/src/expr/pickle_data.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file pickle_data.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 This is a "pickle" for expressions, CVC4-internal view ** diff --git a/src/expr/pickle_data.h b/src/expr/pickle_data.h index acf0dccdd..6c283719a 100644 --- a/src/expr/pickle_data.h +++ b/src/expr/pickle_data.h @@ -1,13 +1,13 @@ /********************* */ /*! \file pickle_data.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Tim King + ** 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 "pickle" for expressions, CVC4-internal view ** diff --git a/src/expr/pickler.cpp b/src/expr/pickler.cpp index d0501ca2b..ab8037a9a 100644 --- a/src/expr/pickler.cpp +++ b/src/expr/pickler.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file pickler.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Tim King, Kshitij Bansal + ** Top contributors (to current version): + ** Morgan Deters, 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 This is a "pickler" for expressions ** diff --git a/src/expr/pickler.h b/src/expr/pickler.h index cf1754d93..abd927788 100644 --- a/src/expr/pickler.h +++ b/src/expr/pickler.h @@ -1,13 +1,13 @@ /********************* */ /*! \file pickler.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Kshitij Bansal + ** Top contributors (to current version): + ** Morgan Deters, Tim King, 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 This is a "pickler" for expressions ** diff --git a/src/expr/predicate.cpp b/src/expr/predicate.cpp index 5ccc3484a..52b580148 100644 --- a/src/expr/predicate.cpp +++ b/src/expr/predicate.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file predicate.cpp ** \verbatim - ** Original author: Morgan Deters - ** 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 Representation of predicates for predicate subtyping ** diff --git a/src/expr/predicate.h b/src/expr/predicate.h index 669ecc29f..a7003fbd1 100644 --- a/src/expr/predicate.h +++ b/src/expr/predicate.h @@ -1,13 +1,13 @@ /********************* */ /*! \file predicate.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 Representation of predicates for predicate subtyping ** diff --git a/src/expr/record.cpp b/src/expr/record.cpp index ec5ef96f1..0d2fd6527 100644 --- a/src/expr/record.cpp +++ b/src/expr/record.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file record.cpp ** \verbatim - ** Original author: Morgan Deters - ** 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 A class representing a record definition ** diff --git a/src/expr/record.h b/src/expr/record.h index d30536fb0..84feb7e1d 100644 --- a/src/expr/record.h +++ b/src/expr/record.h @@ -1,13 +1,13 @@ /********************* */ /*! \file record.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 A class representing a Record definition ** diff --git a/src/expr/symbol_table.cpp b/src/expr/symbol_table.cpp index c0a80b7ce..185006e73 100644 --- a/src/expr/symbol_table.cpp +++ b/src/expr/symbol_table.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file symbol_table.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Christopher L. Conway - ** Minor contributors (to current version): Andrew Reynolds, Dejan Jovanovic, Francois Bobot + ** Top contributors (to current version): + ** Morgan Deters, Christopher L. Conway, 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 Convenience class for scoping variable and type ** declarations (implementation) diff --git a/src/expr/symbol_table.h b/src/expr/symbol_table.h index 451a482dc..efd0f1a13 100644 --- a/src/expr/symbol_table.h +++ b/src/expr/symbol_table.h @@ -1,13 +1,13 @@ /********************* */ /*! \file symbol_table.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Christopher L. Conway - ** Minor contributors (to current version): Andrew Reynolds, Dejan Jovanovic, Francois Bobot + ** Top contributors (to current version): + ** Morgan Deters, Christopher L. Conway, Francois Bobot ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2014 New York University and The University of Iowa - ** See the file COPYING in the top-level source directory for licensing - ** information.\endverbatim + ** Copyright (c) 2009-2016 by the authors listed in the file AUTHORS + ** in the top-level source directory) and their institutional affiliations. + ** All rights reserved. See the file COPYING in the top-level source + ** directory for licensing information.\endverbatim ** ** \brief Convenience class for scoping variable and type declarations. ** diff --git a/src/expr/type.cpp b/src/expr/type.cpp index 6b5bdf07c..0c4d554ef 100644 --- a/src/expr/type.cpp +++ b/src/expr/type.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file type.cpp ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: Dejan Jovanovic, Morgan Deters - ** Minor contributors (to current version): Kshitij Bansal, 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 Implementation of expression types ** @@ -223,6 +223,12 @@ bool Type::isString() const { return d_typeNode->isString(); } +/** Is this the regexp type? */ +bool Type::isRegExp() const { + NodeManagerScope nms(d_nodeManager); + return d_typeNode->isRegExp(); +} + /** Is this the rounding mode type? */ bool Type::isRoundingMode() const { NodeManagerScope nms(d_nodeManager); @@ -427,6 +433,11 @@ StringType::StringType(const Type& t) throw(IllegalArgumentException) : PrettyCheckArgument(isNull() || isString(), this); } +RegExpType::RegExpType(const Type& t) throw(IllegalArgumentException) : + Type(t) { + PrettyCheckArgument(isNull() || isRegExp(), this); +} + RoundingModeType::RoundingModeType(const Type& t) throw(IllegalArgumentException) : Type(t) { PrettyCheckArgument(isNull() || isRoundingMode(), this); diff --git a/src/expr/type.h b/src/expr/type.h index 67d259fec..43cb3ffbf 100644 --- a/src/expr/type.h +++ b/src/expr/type.h @@ -1,13 +1,13 @@ /********************* */ /*! \file type.h ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: Dejan Jovanovic, Morgan Deters - ** Minor contributors (to current version): Andrew Reynolds, Kshitij Bansal + ** Top contributors (to current version): + ** Morgan Deters, Dejan Jovanovic, 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 Interface for expression types. ** @@ -47,6 +47,7 @@ class BooleanType; class IntegerType; class RealType; class StringType; +class RegExpType; class RoundingModeType; class BitVectorType; class ArrayType; @@ -258,6 +259,12 @@ public: bool isString() const; /** + * Is this the regexp type? + * @return true if the type is the regexp type + */ + bool isRegExp() const; + + /** * Is this the rounding mode type? * @return true if the type is the rounding mode type */ @@ -424,6 +431,18 @@ public: };/* class StringType */ /** + * Singleton class encapsulating the string type. + */ +class CVC4_PUBLIC RegExpType : public Type { + +public: + + /** Construct from the base type */ + RegExpType(const Type& type) throw(IllegalArgumentException); +};/* class RegExpType */ + + +/** * Singleton class encapsulating the rounding mode type. */ class CVC4_PUBLIC RoundingModeType : public Type { diff --git a/src/expr/type_checker.h b/src/expr/type_checker.h index 4b04adfc9..3df73b268 100644 --- a/src/expr/type_checker.h +++ b/src/expr/type_checker.h @@ -1,13 +1,13 @@ /********************* */ /*! \file type_checker.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Tim King + ** 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 A type checker ** diff --git a/src/expr/type_checker_template.cpp b/src/expr/type_checker_template.cpp index 061e1b4e0..8ed894a22 100644 --- a/src/expr/type_checker_template.cpp +++ b/src/expr/type_checker_template.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file type_checker_template.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Tim King - ** 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 TypeChecker implementation ** diff --git a/src/expr/type_node.cpp b/src/expr/type_node.cpp index 755b16e46..5d672e6ac 100644 --- a/src/expr/type_node.cpp +++ b/src/expr/type_node.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file type_node.cpp ** \verbatim - ** Original author: Dejan Jovanovic - ** Major contributors: Kshitij Bansal, Morgan Deters - ** Minor contributors (to current version): Andrew Reynolds, Clark Barrett, Tim King + ** Top contributors (to current version): + ** Morgan Deters, Andrew Reynolds, 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 Reference-counted encapsulation of a pointer to node information. ** @@ -93,46 +93,28 @@ bool TypeNode::isSubtypeOf(TypeNode t) const { t.getConst<TypeConstant>() == REAL_TYPE ); } } - if(isTuple() || isRecord()) { - if(isTuple() != t.isTuple() || isRecord() != t.isRecord()) { + if(isTuple() && t.isTuple()) { + const Datatype& dt1 = getDatatype(); + const Datatype& dt2 = t.getDatatype(); + if( dt1[0].getNumArgs()!=dt2[0].getNumArgs() ){ return false; } - if(isTuple()) { - if(getNumChildren() != t.getNumChildren()) { + // r1's fields must be subtypes of r2's, in order + for( unsigned i=0; i<dt1[0].getNumArgs(); i++ ){ + if( !dt1[0][i].getRangeType().isSubtypeOf( dt2[0][i].getRangeType() ) ){ return false; } - // children must be subtypes of t's, in order - for(const_iterator i = begin(), j = t.begin(); i != end(); ++i, ++j) { - if(!(*i).isSubtypeOf(*j)) { - return false; - } - } - } else { - const Record& r1 = getRecord(); - const Record& r2 = t.getRecord(); - if(r1.getNumFields() != r2.getNumFields()) { - return false; - } - const Record::FieldVector& fields1 = r1.getFields(); - const Record::FieldVector& fields2 = r2.getFields(); - // r1's fields must be subtypes of r2's, in order - // names must match also - for(Record::FieldVector::const_iterator i = fields1.begin(), j = fields2.begin(); i != fields1.end(); ++i, ++j) { - if((*i).first != (*j).first || !(*i).second.isSubtypeOf((*j).second)) { - return false; - } - } } return true; + }else if( t.isRecord() && t.isRecord() ){ + //records are not subtypes of each other in current implementation } if(isFunction()) { // A function is a subtype of another if the args are the same type, and // the return type is a subtype of the other's. This is enough for now // (and it's necessary for model generation, since a Real-valued function // might return a constant Int and thus the model value is typed differently). - return t.isFunction() && - getArgTypes() == t.getArgTypes() && - getRangeType().isSubtypeOf(t.getRangeType()); + return t.isFunction() && getArgTypes() == t.getArgTypes() && getRangeType().isSubtypeOf(t.getRangeType()); } if(isParametricDatatype() && t.isParametricDatatype()) { Assert(getKind() == kind::PARAMETRIC_DATATYPE); @@ -153,6 +135,11 @@ bool TypeNode::isSubtypeOf(TypeNode t) const { if(isSet() && t.isSet()) { return getSetElementType().isSubtypeOf(t.getSetElementType()); } + if(isArray() && t.isArray()) { + //reverse for index type + return t.getArrayIndexType().isSubtypeOf(getArrayIndexType()) && + getArrayConstituentType().isSubtypeOf(t.getArrayConstituentType()); + } return false; } @@ -163,39 +150,21 @@ bool TypeNode::isComparableTo(TypeNode t) const { if(isSubtypeOf(NodeManager::currentNM()->realType())) { return t.isSubtypeOf(NodeManager::currentNM()->realType()); } - if(isTuple() || isRecord()) { - if(t.isTuple() || t.isRecord()) { - if(isTuple() != t.isTuple() || isRecord() != t.isRecord()) { + if(isTuple() && t.isTuple()) { + const Datatype& dt1 = getDatatype(); + const Datatype& dt2 = t.getDatatype(); + if( dt1[0].getNumArgs()!=dt2[0].getNumArgs() ){ + return false; + } + // r1's fields must be subtypes of r2's, in order + for( unsigned i=0; i<dt1[0].getNumArgs(); i++ ){ + if( !dt1[0][i].getRangeType().isComparableTo( dt2[0][i].getRangeType() ) ){ return false; } - if(isTuple()) { - if(getNumChildren() != t.getNumChildren()) { - return false; - } - // children must be comparable to t's, in order - for(const_iterator i = begin(), j = t.begin(); i != end(); ++i, ++j) { - if(!(*i).isComparableTo(*j)) { - return false; - } - } - } else { - const Record& r1 = getRecord(); - const Record& r2 = t.getRecord(); - if(r1.getNumFields() != r2.getNumFields()) { - return false; - } - // r1's fields must be comparable to r2's, in order - // names must match also - const Record::FieldVector& fields1 = r1.getFields(); - const Record::FieldVector& fields2 = r2.getFields(); - for(Record::FieldVector::const_iterator i = fields1.begin(), j = fields2.begin(); i != fields1.end(); ++i, ++j) { - if((*i).first != (*j).first || !(*i).second.isComparableTo((*j).second)) { - return false; - } - } - } - return true; } + return true; + //}else if( isRecord() && t.isRecord() ){ + //record types are incomparable in current implementation } else if(isParametricDatatype() && t.isParametricDatatype()) { Assert(getKind() == kind::PARAMETRIC_DATATYPE); Assert(t.getKind() == kind::PARAMETRIC_DATATYPE); @@ -211,10 +180,12 @@ bool TypeNode::isComparableTo(TypeNode t) const { } else if(isSet() && t.isSet()) { return getSetElementType().isComparableTo(t.getSetElementType()); } - - if(isPredicateSubtype()) { - return t.isComparableTo(getSubtypeParentType()); + if(isArray() && t.isArray()) { + return getArrayIndexType().isComparableTo(t.getArrayIndexType()) && getArrayConstituentType().isComparableTo(t.getArrayConstituentType()); } + //if(isPredicateSubtype()) { + // return t.isComparableTo(getSubtypeParentType()); + //} return false; } @@ -271,13 +242,13 @@ std::vector<TypeNode> TypeNode::getParamTypes() const { /** Is this a tuple type? */ bool TypeNode::isTuple() const { - return ( getKind() == kind::DATATYPE_TYPE && hasAttribute(expr::DatatypeTupleAttr()) ) || + return ( getKind() == kind::DATATYPE_TYPE && getDatatype().isTuple() ) || ( isPredicateSubtype() && getSubtypeParentType().isTuple() ); } /** Is this a record type? */ bool TypeNode::isRecord() const { - return ( getKind() == kind::DATATYPE_TYPE && hasAttribute(expr::DatatypeRecordAttr()) ) || + return ( getKind() == kind::DATATYPE_TYPE && getDatatype().isRecord() ) || ( isPredicateSubtype() && getSubtypeParentType().isRecord() ); } @@ -294,14 +265,16 @@ vector<TypeNode> TypeNode::getTupleTypes() const { Assert(dt.getNumConstructors()==1); vector<TypeNode> types; for(unsigned i = 0; i < dt[0].getNumArgs(); ++i) { - types.push_back(TypeNode::fromType(((SelectorType)dt[0][i].getSelector().getType()).getRangeType())); + types.push_back(TypeNode::fromType(dt[0][i].getRangeType())); } return types; } const Record& TypeNode::getRecord() const { Assert(isRecord()); - return getAttribute(expr::DatatypeRecordAttr()).getConst<Record>(); + const Datatype & dt = getDatatype(); + return *(dt.getRecord()); + //return getAttribute(expr::DatatypeRecordAttr()).getConst<Record>(); } vector<TypeNode> TypeNode::getSExprTypes() const { @@ -341,6 +314,14 @@ bool TypeNode::isParameterInstantiatedDatatype(unsigned n) const { } TypeNode TypeNode::leastCommonTypeNode(TypeNode t0, TypeNode t1){ + return commonTypeNode( t0, t1, true ); +} + +TypeNode TypeNode::mostCommonTypeNode(TypeNode t0, TypeNode t1){ + return commonTypeNode( t0, t1, false ); +} + +TypeNode TypeNode::commonTypeNode(TypeNode t0, TypeNode t1, bool isLeast) { Assert( NodeManager::currentNM() != NULL, "There is no current CVC4::NodeManager associated to this thread.\n" "Perhaps a public-facing function is missing a NodeManagerScope ?" ); @@ -361,65 +342,75 @@ TypeNode TypeNode::leastCommonTypeNode(TypeNode t0, TypeNode t1){ return t0; //IntegerType } else if(t1.isReal()) { // t0 == IntegerType && t1.isReal() && !t1.isInteger() - return NodeManager::currentNM()->realType(); // RealType + return isLeast ? t1 : t0; // RealType } else { return TypeNode(); // null type } case REAL_TYPE: if(t1.isReal()) { - return t0; // RealType + return isLeast ? t0 : t1; // RealType } else { return TypeNode(); // null type } default: - if(t1.isPredicateSubtype() && t1.getSubtypeParentType().isSubtypeOf(t0)) { - return t0; // t0 is a constant type - } else { + //if(t1.isPredicateSubtype() && t1.getSubtypeParentType().isSubtypeOf(t0)) { + // return t0; // t0 is a constant type + //} else { return TypeNode(); // null type - } + //} } } else if(t1.getKind() == kind::TYPE_CONSTANT) { - return leastCommonTypeNode(t1, t0); // decrease the number of special cases + return commonTypeNode(t1, t0, isLeast); // decrease the number of special cases } // t0 != t1 && // t0.getKind() == kind::TYPE_CONSTANT && // t1.getKind() == kind::TYPE_CONSTANT switch(t0.getKind()) { - case kind::ARRAY_TYPE: case kind::BITVECTOR_TYPE: case kind::SORT_TYPE: case kind::CONSTRUCTOR_TYPE: case kind::SELECTOR_TYPE: case kind::TESTER_TYPE: - if(t1.isPredicateSubtype() && t1.getSubtypeParentType().isSubtypeOf(t0)) { - return t0; - } else { + //if( t1.isPredicateSubtype() && t1.getSubtypeParentType().isSubtypeOf(t0)) { + // return t0; + //} else { return TypeNode(); - } + //} case kind::FUNCTION_TYPE: return TypeNode(); // Not sure if this is right case kind::SET_TYPE: { // take the least common subtype of element types TypeNode elementType; - if(t1.isSet() && - ! (elementType = leastCommonTypeNode(t0[0], t1[0])).isNull() ) { + if(t1.isSet() && !(elementType = commonTypeNode(t0[0], t1[0], isLeast)).isNull() ) { return NodeManager::currentNM()->mkSetType(elementType); } else { return TypeNode(); } } + case kind::ARRAY_TYPE: { + TypeNode indexType, elementType; + if(t1.isArray() && + ! (indexType = commonTypeNode(t0[0], t1[0], !isLeast)).isNull() && + ! (elementType = commonTypeNode(t0[1], t1[1], isLeast)).isNull() ) { + return NodeManager::currentNM()->mkArrayType(indexType, elementType); + } else { + return TypeNode(); + } + } case kind::SEXPR_TYPE: Unimplemented("haven't implemented leastCommonType for symbolic expressions yet"); return TypeNode(); case kind::SUBTYPE_TYPE: - if(t1.isPredicateSubtype()){ - // This is the case where both t0 and t1 are predicate subtypes. - return leastCommonPredicateSubtype(t0, t1); - }else{ // t0 is a predicate subtype and t1 is not - return leastCommonTypeNode(t1, t0); //decrease the number of special cases - } + //if(t1.isPredicateSubtype()){ + // // This is the case where both t0 and t1 are predicate subtypes. + // return leastCommonPredicateSubtype(t0, t1); + //}else{ // t0 is a predicate subtype and t1 is not + // return commonTypeNode(t1, t0, isLeast); //decrease the number of special cases + //} + return TypeNode(); case kind::SUBRANGE_TYPE: + /* if(t1.isSubrange()) { const SubrangeBounds& t0SR = t0.getSubrangeBounds(); const SubrangeBounds& t1SR = t1.getSubrangeBounds(); @@ -449,62 +440,28 @@ TypeNode TypeNode::leastCommonTypeNode(TypeNode t0, TypeNode t1){ Assert(t1.isInteger()); return TypeNode(); } -/* - case kind::TUPLE_TYPE: { - // if the other == this one, we returned already, above - if(t0.getBaseType() == t1) { - return t1; - } - if(!t1.isTuple() || t0.getNumChildren() != t1.getNumChildren()) { - // no compatibility between t0, t1 - return TypeNode(); - } - std::vector<TypeNode> types; - // construct childwise leastCommonType, if one exists - for(const_iterator i = t0.begin(), j = t1.begin(); i != t0.end(); ++i, ++j) { - TypeNode kid = leastCommonTypeNode(*i, *j); - if(kid.isNull()) { - // no common supertype: types t0, t1 not compatible - return TypeNode(); - } - types.push_back(kid); - } - // if we make it here, we constructed the least common type - return NodeManager::currentNM()->mkTupleType(types); - } - case kind::RECORD_TYPE: { - // if the other == this one, we returned already, above - if(t0.getBaseType() == t1) { - return t1; - } - const Record& r0 = t0.getConst<Record>(); - if(!t1.isRecord() || r0.getNumFields() != t1.getConst<Record>().getNumFields()) { - // no compatibility between t0, t1 - return TypeNode(); - } - std::vector< std::pair<std::string, Type> > fields; - const Record& r1 = t1.getConst<Record>(); - const Record::FieldVector& fields0 = r0.getFields(); - const Record::FieldVector& fields1 = r1.getFields(); - // construct childwise leastCommonType, if one exists - for(Record::FieldVector::const_iterator i = fields0.begin(), j = fields1.begin(); i != fields0.end(); ++i, ++j) { - TypeNode kid = leastCommonTypeNode(TypeNode::fromType((*i).second), TypeNode::fromType((*j).second)); - if((*i).first != (*j).first || kid.isNull()) { - // if field names differ, or no common supertype, then - // types t0, t1 not compatible - return TypeNode(); - } - fields.push_back(std::make_pair((*i).first, kid.toType())); - } - // if we make it here, we constructed the least common type - return NodeManager::currentNM()->mkRecordType(Record(fields)); - } */ + return TypeNode(); case kind::DATATYPE_TYPE: - // t1 might be a subtype tuple or record - if(t1.getBaseType() == t0) { - return t0; + if( t0.isTuple() && t1.isTuple() ){ + const Datatype& dt1 = t0.getDatatype(); + const Datatype& dt2 = t1.getDatatype(); + if( dt1[0].getNumArgs()==dt2[0].getNumArgs() ){ + std::vector< TypeNode > lc_types; + for( unsigned i=0; i<dt1[0].getNumArgs(); i++ ){ + TypeNode tc = commonTypeNode( TypeNode::fromType( dt1[0][i].getRangeType() ), TypeNode::fromType( dt2[0][i].getRangeType() ), isLeast ); + if( tc.isNull() ){ + return tc; + }else{ + lc_types.push_back( tc ); + } + } + return NodeManager::currentNM()->mkTupleType( lc_types ); + } } + //else if( t0.isRecord() && t1.isRecord() ){ + //record types are not related in current implementation + //} // otherwise no common ancestor return TypeNode(); case kind::PARAMETRIC_DATATYPE: { @@ -519,12 +476,12 @@ TypeNode TypeNode::leastCommonTypeNode(TypeNode t0, TypeNode t1){ } vector<Type> v; for(size_t i = 1; i < t0.getNumChildren(); ++i) { - v.push_back(leastCommonTypeNode(t0[i], t1[i]).toType()); + v.push_back(commonTypeNode(t0[i], t1[i], isLeast).toType()); } return TypeNode::fromType(t0[0].getDatatype().getDatatypeType(v)); } default: - Unimplemented("don't have a leastCommonType for types `%s' and `%s'", t0.toString().c_str(), t1.toString().c_str()); + Unimplemented("don't have a commonType for types `%s' and `%s'", t0.toString().c_str(), t1.toString().c_str()); return TypeNode(); } } diff --git a/src/expr/type_node.h b/src/expr/type_node.h index 4c48cc3ca..cfb61a085 100644 --- a/src/expr/type_node.h +++ b/src/expr/type_node.h @@ -1,13 +1,13 @@ /********************* */ /*! \file type_node.h ** \verbatim - ** Original author: Dejan Jovanovic - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): Clark Barrett, Andrew Reynolds, Tianyi Liang, Kshitij Bansal, Tim King + ** Top contributors (to current version): + ** Morgan Deters, Dejan Jovanovic, 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 Reference-counted encapsulation of a pointer to node information. ** @@ -642,8 +642,10 @@ public: * For more information see: http://cvc4.cs.nyu.edu/wiki/Cvc4_Type_Lattice */ static TypeNode leastCommonTypeNode(TypeNode t0, TypeNode t1); + static TypeNode mostCommonTypeNode(TypeNode t0, TypeNode t1); private: + static TypeNode commonTypeNode(TypeNode t0, TypeNode t1, bool isLeast); /** * Returns the leastUpperBound in the extended type lattice of two diff --git a/src/expr/type_properties_template.h b/src/expr/type_properties_template.h index bc780a7e5..4874a84b8 100644 --- a/src/expr/type_properties_template.h +++ b/src/expr/type_properties_template.h @@ -1,13 +1,13 @@ /********************* */ /*! \file type_properties_template.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 Template for the Type properties header ** diff --git a/src/expr/uninterpreted_constant.cpp b/src/expr/uninterpreted_constant.cpp index 97bc3ae4b..c88c3b591 100644 --- a/src/expr/uninterpreted_constant.cpp +++ b/src/expr/uninterpreted_constant.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file uninterpreted_constant.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 Representation of constants of uninterpreted sorts ** diff --git a/src/expr/uninterpreted_constant.h b/src/expr/uninterpreted_constant.h index 5b2293df6..7d7a3759b 100644 --- a/src/expr/uninterpreted_constant.h +++ b/src/expr/uninterpreted_constant.h @@ -1,13 +1,13 @@ /********************* */ /*! \file uninterpreted_constant.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 Representation of constants of uninterpreted sorts ** diff --git a/src/expr/variable_type_map.h b/src/expr/variable_type_map.h index 59ce5c606..00d2c3eac 100644 --- a/src/expr/variable_type_map.h +++ b/src/expr/variable_type_map.h @@ -1,13 +1,13 @@ /********************* */ /*! \file variable_type_map.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 [[ Add one-line brief description here ]] ** diff --git a/src/include/cvc4.h b/src/include/cvc4.h index 90088de40..6e6204c58 100644 --- a/src/include/cvc4.h +++ b/src/include/cvc4.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cvc4.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 Main header file for CVC4 library functionality ** diff --git a/src/include/cvc4_private.h b/src/include/cvc4_private.h index ccc850787..56be6ff71 100644 --- a/src/include/cvc4_private.h +++ b/src/include/cvc4_private.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cvc4_private.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 #-inclusion of this file marks a header as private and generates a ** warning when the file is included improperly diff --git a/src/include/cvc4_private_library.h b/src/include/cvc4_private_library.h index e0127946d..c536d0586 100644 --- a/src/include/cvc4_private_library.h +++ b/src/include/cvc4_private_library.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cvc4_private_library.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 #-inclusion of this file marks a header as private and generates a ** warning when the file is included improperly diff --git a/src/include/cvc4_public.h b/src/include/cvc4_public.h index f299c7237..1308b3d96 100644 --- a/src/include/cvc4_public.h +++ b/src/include/cvc4_public.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cvc4_public.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 Macros that should be defined everywhere during the building of ** the libraries and driver binary, and also exported to the user. diff --git a/src/include/cvc4parser_private.h b/src/include/cvc4parser_private.h index c107c4f56..366877c96 100644 --- a/src/include/cvc4parser_private.h +++ b/src/include/cvc4parser_private.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cvc4parser_private.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 #-inclusion of this file marks a header as private and generates a ** warning when the file is included improperly. diff --git a/src/include/cvc4parser_public.h b/src/include/cvc4parser_public.h index edb189c19..ccbd09066 100644 --- a/src/include/cvc4parser_public.h +++ b/src/include/cvc4parser_public.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cvc4parser_public.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 Macros that should be defined everywhere during the building of ** the libraries and driver binary, and also exported to the user. diff --git a/src/lib/clock_gettime.c b/src/lib/clock_gettime.c index 3f1d36f0f..9bd4eafe8 100644 --- a/src/lib/clock_gettime.c +++ b/src/lib/clock_gettime.c @@ -1,13 +1,13 @@ /********************* */ /*! \file clock_gettime.c ** \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 Replacement for clock_gettime() for systems without it (like ** Mac OS X) @@ -16,7 +16,7 @@ ** OS X). **/ -#warning "TODO(taking): Make lib/clock_gettime.h cvc4_private.h again." +// #warning "TODO(taking): Make lib/clock_gettime.h cvc4_private.h again." #include "lib/clock_gettime.h" diff --git a/src/lib/clock_gettime.h b/src/lib/clock_gettime.h index 3a181bef5..74c9f5088 100644 --- a/src/lib/clock_gettime.h +++ b/src/lib/clock_gettime.h @@ -1,13 +1,13 @@ /********************* */ /*! \file clock_gettime.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 Replacement for clock_gettime() for systems without it (like Mac OS X) ** diff --git a/src/lib/ffs.c b/src/lib/ffs.c index d4481d2ca..81228be63 100644 --- a/src/lib/ffs.c +++ b/src/lib/ffs.c @@ -1,13 +1,13 @@ /********************* */ /*! \file ffs.c ** \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 Replacement for ffs() for systems without it (like Win32) ** diff --git a/src/lib/ffs.h b/src/lib/ffs.h index 44fb40674..878c8f7cf 100644 --- a/src/lib/ffs.h +++ b/src/lib/ffs.h @@ -1,13 +1,13 @@ /********************* */ /*! \file ffs.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 Replacement for ffs() for systems without it (like Win32) ** diff --git a/src/lib/replacements.h b/src/lib/replacements.h index b6acc1c7d..d2f7d9f4f 100644 --- a/src/lib/replacements.h +++ b/src/lib/replacements.h @@ -1,13 +1,13 @@ /********************* */ /*! \file replacements.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 Common header for replacement function sources ** diff --git a/src/lib/strtok_r.c b/src/lib/strtok_r.c index da49aaada..9173596a3 100644 --- a/src/lib/strtok_r.c +++ b/src/lib/strtok_r.c @@ -1,13 +1,13 @@ /********************* */ /*! \file strtok_r.c ** \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 Replacement for strtok_r() for systems without it (like Win32) ** diff --git a/src/lib/strtok_r.h b/src/lib/strtok_r.h index cc737043b..e3803b0c1 100644 --- a/src/lib/strtok_r.h +++ b/src/lib/strtok_r.h @@ -1,13 +1,13 @@ /********************* */ /*! \file strtok_r.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 Replacement for strtok_r() for systems without it (like Win32) ** diff --git a/src/main/command_executor.cpp b/src/main/command_executor.cpp index 672dedc50..320be701d 100644 --- a/src/main/command_executor.cpp +++ b/src/main/command_executor.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file command_executor.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Andrew Reynolds, Kshitij Bansal - ** 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 An additional layer between commands and invoking them. **/ @@ -115,6 +115,10 @@ bool CommandExecutor::doCommandSingleton(Command* cmd) if(q != NULL) { d_result = res = q->getResult(); } + CheckSynthCommand* csy = dynamic_cast<CheckSynthCommand*>(cmd); + if(csy != NULL) { + d_result = res = csy->getResult(); + } if((cs != NULL || q != NULL) && d_options.getStatsEveryQuery()) { std::ostringstream ossCurStats; diff --git a/src/main/command_executor.h b/src/main/command_executor.h index d8294212a..4018aeda1 100644 --- a/src/main/command_executor.h +++ b/src/main/command_executor.h @@ -1,13 +1,13 @@ /********************* */ /*! \file command_executor.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Kshitij Bansal - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Kshitij Bansal, 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 additional layer between commands and invoking them. **/ diff --git a/src/main/command_executor_portfolio.cpp b/src/main/command_executor_portfolio.cpp index 15165e82c..1902e1817 100644 --- a/src/main/command_executor_portfolio.cpp +++ b/src/main/command_executor_portfolio.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file command_executor_portfolio.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Kshitij Bansal - ** Minor contributors (to current version): Andrew Reynolds + ** 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 An additional layer between commands and invoking them. ** @@ -198,7 +198,8 @@ bool CommandExecutorPortfolio::doCommandSingleton(Command* cmd) // command if(dynamic_cast<CheckSatCommand*>(cmd) != NULL || - dynamic_cast<QueryCommand*>(cmd) != NULL) { + dynamic_cast<QueryCommand*>(cmd) != NULL || + dynamic_cast<CheckSynthCommand*>(cmd) != NULL) { mode = 1; } else if(dynamic_cast<GetValueCommand*>(cmd) != NULL || dynamic_cast<GetAssignmentCommand*>(cmd) != NULL || diff --git a/src/main/command_executor_portfolio.h b/src/main/command_executor_portfolio.h index ce9a80a4e..be980a01b 100644 --- a/src/main/command_executor_portfolio.h +++ b/src/main/command_executor_portfolio.h @@ -1,13 +1,13 @@ /********************* */ /*! \file command_executor_portfolio.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Kshitij Bansal - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Kshitij Bansal, 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 additional layer between commands and invoking them. ** diff --git a/src/main/driver_unified.cpp b/src/main/driver_unified.cpp index b83907bd3..bab70e98f 100644 --- a/src/main/driver_unified.cpp +++ b/src/main/driver_unified.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file driver_unified.cpp ** \verbatim - ** Original author: Kshitij Bansal - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): Francois Bobot + ** Top contributors (to current version): + ** Morgan Deters, Tim King, 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 Driver for CVC4 executable (cvc4) unified for both ** sequential and portfolio versions @@ -101,7 +101,7 @@ int runCvc4(int argc, char* argv[], Options& opts) { progPath = argv[0]; // Parse the options - vector<string> filenames = opts.parseOptions(argc, argv); + vector<string> filenames = Options::parseOptions(&opts, argc, argv); # ifndef PORTFOLIO_BUILD if( opts.wasSetByUserThreads() || diff --git a/src/main/interactive_shell.cpp b/src/main/interactive_shell.cpp index 4982cb2bb..e11f82a40 100644 --- a/src/main/interactive_shell.cpp +++ b/src/main/interactive_shell.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file interactive_shell.cpp ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): Kshitij Bansal, Francois Bobot + ** Top contributors (to current version): + ** Morgan Deters, Christopher L. Conway, 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 Interactive shell for CVC4 ** diff --git a/src/main/interactive_shell.h b/src/main/interactive_shell.h index 844fddf45..18e42f1e5 100644 --- a/src/main/interactive_shell.h +++ b/src/main/interactive_shell.h @@ -1,13 +1,13 @@ /********************* */ /*! \file interactive_shell.h ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Morgan Deters, Christopher L. Conway, 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 Interactive shell for CVC4 **/ diff --git a/src/main/main.cpp b/src/main/main.cpp index 56fc3ef40..7b6b9ad86 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file main.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Christopher L. Conway - ** Minor contributors (to current version): Clark Barrett, Dejan Jovanovic + ** Top contributors (to current version): + ** Morgan Deters, Tim King, 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 Main driver for CVC4 executable ** diff --git a/src/main/main.h b/src/main/main.h index 2ba688a98..8277d366a 100644 --- a/src/main/main.h +++ b/src/main/main.h @@ -1,13 +1,13 @@ /********************* */ /*! \file main.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 Header for main CVC4 driver ** diff --git a/src/main/portfolio.cpp b/src/main/portfolio.cpp index 22f3a67ae..1e1b41bea 100644 --- a/src/main/portfolio.cpp +++ b/src/main/portfolio.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file portfolio.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Kshitij Bansal - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Morgan Deters, 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 Provides (somewhat) generic functionality to simulate a ** (potentially cooperative) race diff --git a/src/main/portfolio.h b/src/main/portfolio.h index a7f15a04d..b96efda51 100644 --- a/src/main/portfolio.h +++ b/src/main/portfolio.h @@ -1,13 +1,13 @@ /********************* */ /*! \file portfolio.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Kshitij Bansal - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Morgan Deters, Tim King, 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 Provides (somewhat) generic functionality to simulate a ** (potentially cooperative) race diff --git a/src/main/portfolio_util.cpp b/src/main/portfolio_util.cpp index e42787fea..03827a917 100644 --- a/src/main/portfolio_util.cpp +++ b/src/main/portfolio_util.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file portfolio_util.cpp ** \verbatim - ** Original author: Kshitij Bansal - ** Major contributors: none - ** Minor contributors (to current version): Morgan Deters + ** Top contributors (to current version): + ** Tim King, 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 Code relevant only for portfolio builds **/ @@ -92,7 +92,7 @@ void parseThreadSpecificOptions(OptionsList& threadOptions, const Options& opts) *vp++ = NULL; if(targc > 1) { // this is necessary in case you do e.g. --thread0=" " try { - tOpts.parseOptions(targc, targv); + Options::parseOptions(&tOpts, targc, targv); } catch(OptionException& e) { stringstream ss; ss << optid << ": " << e.getMessage(); diff --git a/src/main/portfolio_util.h b/src/main/portfolio_util.h index 50cf0060a..32cc04540 100644 --- a/src/main/portfolio_util.h +++ b/src/main/portfolio_util.h @@ -1,13 +1,13 @@ /********************* */ /*! \file portfolio_util.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 Code relevant only for portfolio builds **/ diff --git a/src/main/util.cpp b/src/main/util.cpp index 71b46e67a..e14b508de 100644 --- a/src/main/util.cpp +++ b/src/main/util.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file util.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Christopher L. Conway, Tim King, ACSYS + ** Top contributors (to current version): + ** Morgan Deters, Tim King, 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 Utilities for the main driver. ** diff --git a/src/options/Makefile.am b/src/options/Makefile.am index 8a465c522..643932781 100644 --- a/src/options/Makefile.am +++ b/src/options/Makefile.am @@ -206,7 +206,8 @@ liboptions_la_SOURCES = \ arith_propagation_mode.h \ arith_unate_lemma_mode.cpp \ arith_unate_lemma_mode.h \ - argument_extender.cpp \ + argument_extender_implementation.cpp \ + argument_extender_implementation.h \ argument_extender.h \ base_handlers.h \ boolean_term_conversion_mode.cpp \ diff --git a/src/options/argument_extender.cpp b/src/options/argument_extender.cpp deleted file mode 100644 index d55610590..000000000 --- a/src/options/argument_extender.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/********************* */ -/*! \file preempt_get_option.h - ** \verbatim - ** Original author: Tim King - ** Major contributors: none - ** Minor contributors (to current version): none - ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2014 New York University and The University of Iowa - ** See the file COPYING in the top-level source directory for licensing - ** information.\endverbatim - ** - ** \brief Utility function for parsing commandline options. - ** - ** Utility function for parsing commandline options. - **/ - -#include "options/argument_extender.h" - -#include <cstdlib> -#include <cstring> -#include <vector> - -#include "base/cvc4_assert.h" -#include "base/output.h" - -namespace CVC4 { -namespace options { - -ArgumentExtender::ArgumentExtender(unsigned additional, size_t length) - : d_additional(additional) - , d_length(length) -{ - AlwaysAssert(d_additional >= 1); - AlwaysAssert(d_length >= 1); -} - -ArgumentExtender::~ArgumentExtender(){} - -unsigned ArgumentExtender::getIncrease() const { return d_additional; } -size_t ArgumentExtender::getLength() const { return d_length; } - -void ArgumentExtender::extend(int& argc, char**& argv, const char* opt, - std::vector<char*>& allocated) -{ - - Debug("preemptGetopt") << "preempting getopt() with " << opt << std::endl; - - AlwaysAssert(opt != NULL && *opt != '\0'); - AlwaysAssert(strlen(opt) <= getLength()); - - ++argc; - unsigned i = 1; - while(argv[i] != NULL && argv[i][0] != '\0') { - ++i; - } - - if(argv[i] == NULL) { - unsigned newSize = i + getIncrease(); - argv = (char**) realloc(argv, newSize * sizeof(char*)); - for(unsigned j = i; j < newSize-1; ++j) { - char* newString = (char*) malloc(sizeof(char) * getLength()); - newString[0] = '\0'; - argv[j] = newString; - allocated.push_back(newString); - } - argv[newSize - 1] = NULL; - } - - strncpy(argv[i], opt, getLength() - 1); - argv[i][getLength() - 1] = '\0'; // ensure NULL-termination even on overflow -} - -}/* CVC4::options namespace */ -}/* CVC4 namespace */ diff --git a/src/options/argument_extender.h b/src/options/argument_extender.h index 1f7e3c1dd..6be41fe8e 100644 --- a/src/options/argument_extender.h +++ b/src/options/argument_extender.h @@ -1,79 +1,85 @@ /********************* */ -/*! \file preempt_get_option.h +/*! \file argument_extender.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 Utility function for extending commandline options. + ** \brief Abstract utility class for extending commandline options. ** - ** Utility function for extending commandline options. + ** Abstract utility class for extending commandline options. **/ -#include "cvc4_private.h" +#include "cvc4_public.h" -#ifndef __CVC4__OPTIONS__PREMPT_GET_OPTION_H -#define __CVC4__OPTIONS__PREMPT_GET_OPTION_H +#ifndef __CVC4__OPTIONS__ARGUMENT_EXTENDER_H +#define __CVC4__OPTIONS__ARGUMENT_EXTENDER_H #include <cstddef> -#include <vector> namespace CVC4 { namespace options { - +/** + * Abstract utility class for implementing command line options + * parsing for the Options class. This allows for adding preemption + * arguments. A preemption is effectivly adding a new argument into + * the commandline arguments and must be processed immediately. + */ class ArgumentExtender { - public: +public: + ArgumentExtender(){} + virtual ~ArgumentExtender(){} + /** + * This creates a copy of the current arguments list as a new array. + * The new array is stored in argv. The user of this function is + * expected to own the memory of the string array, but not the + * strings themselves. The length of the new array is + * numArguments() and is stored in argc. + * * Preconditions: - * additional >= 1 - * length >= 1 + * - argc and argv are non-null. */ - ArgumentExtender(unsigned additional, size_t length); - ~ArgumentExtender(); + virtual void getArguments(int* argc, char*** argv) const = 0; + + /** Returns the number of arguments that are . */ + virtual size_t numArguments() const = 0; /** - * This purpose of this function is to massage argc and argv upon the event - * of parsing during Options::parseOptions of an option with the :link or - * :link-alternative attributes. The purpose of the function is to extend argv - * with another commandline argument. - * - * Preconditions: - * opt is '\0' terminated, non-null and non-empty c-string. - * strlen(opt) <= getLength() - * - * Let P be the first position in argv that is >= 1 and is either NULL or - * empty: - * argv[P] == NULL || argv[P] == '\0' - * - * This has a very specific set of side effects: - * - argc is incremented by one. - * - If argv[P] == NULL, this reallocates argv to have (P+additional) - * elements. - * - The 0 through P-1 elements of argv are the same. - * - The P element of argv is a copy of the first len-1 characters of opt. - * This is a newly allocated '\0' terminated c string of length len. - * - The P+1 through (P+additional-2) elements of argv are newly allocated - * empty '\0' terminated c strings of size len. - * - The last element at (P+additional-1) of argv is NULL. - * - All allocations are pushed back onto allocated. + * Inserts a copy of element into the front of the arguments list. + * Preconditions: element is non-null and 0 terminated. + */ + virtual void pushFrontArgument(const char* element) = 0; + + /** + * Inserts a copy of element into the back of the arguments list. + * Preconditions: element is non-null and 0 terminated. + */ + virtual void pushBackArgument(const char* element) = 0; + + /** Removes the front of the arguments list.*/ + virtual void popFrontArgument() = 0; + + /** Adds a new preemption to the arguments list. */ + virtual void pushBackPreemption(const char* element) = 0; + + /** + * Moves all of the preemptions into the front of the arguments + * list. */ - void extend(int& argc, char**& argv, const char* opt, - std::vector<char*>& allocated); + virtual void movePreemptionsToArguments() = 0; - unsigned getIncrease() const; - size_t getLength() const; + /** Returns true iff there is a pending preemption.*/ + virtual bool hasPreemptions() const = 0; - private: - unsigned d_additional; - size_t d_length; -}; +};/* class ArgumentExtender */ }/* CVC4::options namespace */ }/* CVC4 namespace */ -#endif /* __CVC4__OPTIONS__PREMPT_GET_OPTION_H */ +#endif /* __CVC4__OPTIONS__ARGUMENT_EXTENDER_H */ diff --git a/src/options/argument_extender_implementation.cpp b/src/options/argument_extender_implementation.cpp new file mode 100644 index 000000000..0c23434c4 --- /dev/null +++ b/src/options/argument_extender_implementation.cpp @@ -0,0 +1,114 @@ +/********************* */ +/*! \file argument_extender_implementation.cpp + ** \verbatim + ** Top contributors (to current version): + ** 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 Utility class for parsing commandline options. + ** + ** Utility class for parsing commandline options. + **/ + +#include "options/argument_extender_implementation.h" + +#include <cstdlib> +#include <cstring> +#include <list> + +#include "base/cvc4_assert.h" +#include "base/output.h" +#include "options/argument_extender.h" + +namespace CVC4 { +namespace options { + +ArgumentExtenderImplementation::ArgumentExtenderImplementation() + : d_allocated() + , d_preemptions() + , d_arguments() +{ +} + +ArgumentExtenderImplementation::~ArgumentExtenderImplementation(){ + for(CharPointerList::iterator i = d_allocated.begin(), + iend = d_allocated.end(); i != iend; ++i) { + char* current = *i; + Debug("options") << "~ArgumentExtenderImplementation " << current + << std::endl; + free(current); + } + d_allocated.clear(); +} + +size_t ArgumentExtenderImplementation::numArguments() const { + return d_arguments.size(); +} + +char* ArgumentExtenderImplementation::allocateCopy(const char* element) { + Assert(element != NULL); + + char* duplicate = strdup(element); + Assert(duplicate != NULL); + d_allocated.push_back(duplicate); + return duplicate; +} + +bool ArgumentExtenderImplementation::hasPreemptions() const { + return !d_preemptions.empty(); +} + +void ArgumentExtenderImplementation::pushBackPreemption(const char* element) { + d_preemptions.push_back(allocateCopy(element)); +} + +void ArgumentExtenderImplementation::movePreemptionsToArguments() { + d_arguments.splice(d_arguments.begin(), d_preemptions); +} + +void ArgumentExtenderImplementation::popFrontArgument() { + Assert(!d_arguments.empty()); + Debug("options") << "ArgumentExtenderImplementation::popFrontArgument " + << d_arguments.front() << std::endl; + d_arguments.pop_front(); +} + +void ArgumentExtenderImplementation::pushFrontArgument(const char* element) { + d_arguments.push_front(allocateCopy(element)); +} + +void ArgumentExtenderImplementation::pushBackArgument(const char* element) { + d_arguments.push_back(allocateCopy(element)); +} + +void ArgumentExtenderImplementation::getArguments(int* argc, char*** argv) + const { + Assert(argc != NULL); + Assert(argv != NULL); + + *argc = numArguments(); + *argv = copyArguments(); +} + +char** ArgumentExtenderImplementation::copyArguments() const { + int size = numArguments(); + Assert(size >= 0); + + char** array = (char**) malloc( sizeof(char*) * size ); + Assert(array != NULL); + int position = 0; + for(std::list< char* >::const_iterator i = d_arguments.begin(), + iend = d_arguments.end(); i != iend; ++i, ++position) { + char* at_position = *i; + array[position] = at_position; + } + + return array; +} + +}/* CVC4::options namespace */ +}/* CVC4 namespace */ diff --git a/src/options/argument_extender_implementation.h b/src/options/argument_extender_implementation.h new file mode 100644 index 000000000..e948132d7 --- /dev/null +++ b/src/options/argument_extender_implementation.h @@ -0,0 +1,115 @@ +/********************* */ +/*! \file argument_extender_implementation.h + ** \verbatim + ** Top contributors (to current version): + ** 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 Utility class for extending commandline options. + ** + ** Utility class for extending commandline options. + **/ + +#include "cvc4_private.h" + +#ifndef __CVC4__OPTIONS__ARGUMENT_EXTENDER_IMPLEMENTATION_H +#define __CVC4__OPTIONS__ARGUMENT_EXTENDER_IMPLEMENTATION_H + +#include <cstddef> +#include <list> + +#include "options/argument_extender.h" + +namespace CVC4 { +namespace options { + +/** + * Utility class for implementing command line options parsing for the + * Options class. This allows for adding preemption arguments. + * Preemptions are processed immediately after the current argument. + */ +class ArgumentExtenderImplementation : public ArgumentExtender { + public: + /** Constructs a new empty ArgumentExtender.*/ + ArgumentExtenderImplementation(); + + /** Destroys an ArgumentExtender and frees its associated memory.*/ + ~ArgumentExtenderImplementation(); + + /** + * This creates a copy of the current arguments list as a new array. + * The new array is stored in argv. The user of this function is + * expected to own the memory of the string array, but not the + * strings themselves. The length of the new array is + * numArguments() and is stored in argc. + * + * Preconditions: + * - argc and argv are non-null. + */ + void getArguments(int* argc, char*** argv) const; + + /** Returns the number of arguments that are . */ + size_t numArguments() const; + + /** + * Inserts a copy of element into the front of the arguments list. + * Preconditions: element is non-null and 0 terminated. + */ + void pushFrontArgument(const char* element); + + /** + * Inserts a copy of element into the back of the arguments list. + * Preconditions: element is non-null and 0 terminated. + */ + void pushBackArgument(const char* element); + + /** Removes the front of the arguments list.*/ + void popFrontArgument(); + + /** Adds a new preemption to the arguments list. */ + void pushBackPreemption(const char* element); + + /** + * Moves all of the preemptions into the front of the arguments + * list. + */ + void movePreemptionsToArguments(); + + /** Returns true iff there is a pending preemption.*/ + bool hasPreemptions() const; + +private: + + typedef std::list< char* > CharPointerList; + + /** Creates of copy of the arugments list.*/ + char** copyArguments() const; + + /** Allocates a copy and stores a copy in d_allocated.*/ + char* allocateCopy(const char* element); + + /** Contains a copy of the allocated strings.*/ + CharPointerList d_allocated; + + /** + * A list of all of the preempted arguments. All of these pointers + * in this list should be contained in d_allocated. + */ + CharPointerList d_preemptions; + + /** + * A list of all of the arguments. All of these pointers in this + * list should be contained in d_allocated. + */ + CharPointerList d_arguments; + +};/* class ArgumentExtenderImplementation */ + +}/* CVC4::options namespace */ +}/* CVC4 namespace */ + +#endif /* __CVC4__OPTIONS__ARGUMENT_EXTENDER_IMPLEMENTATION_H */ diff --git a/src/options/arith_heuristic_pivot_rule.cpp b/src/options/arith_heuristic_pivot_rule.cpp index ff5f2102a..15c340aa8 100644 --- a/src/options/arith_heuristic_pivot_rule.cpp +++ b/src/options/arith_heuristic_pivot_rule.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file arith_heuristic_pivot_rule.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Tim King - ** 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/options/arith_heuristic_pivot_rule.h b/src/options/arith_heuristic_pivot_rule.h index e44b8105b..9048cb92e 100644 --- a/src/options/arith_heuristic_pivot_rule.h +++ b/src/options/arith_heuristic_pivot_rule.h @@ -1,13 +1,13 @@ /********************* */ /*! \file arith_heuristic_pivot_rule.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Tim King - ** 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/options/arith_options b/src/options/arith_options index 9f4003004..f38e377ba 100644 --- a/src/options/arith_options +++ b/src/options/arith_options @@ -162,4 +162,7 @@ option pbRewrites --pb-rewrites bool :default false option pbRewriteThreshold --pb-rewrite-threshold int :default 256 threshold of number of pseudoboolean variables to have before doing rewrites +option sNormInferEq --snorm-infer-eq bool :default false + infer equalities based on Shostak normalization + endmodule diff --git a/src/options/arith_propagation_mode.cpp b/src/options/arith_propagation_mode.cpp index 7f18a0356..5baf0b832 100644 --- a/src/options/arith_propagation_mode.cpp +++ b/src/options/arith_propagation_mode.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file arith_propagation_mode.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/options/arith_propagation_mode.h b/src/options/arith_propagation_mode.h index fa89496f0..dc4b80372 100644 --- a/src/options/arith_propagation_mode.h +++ b/src/options/arith_propagation_mode.h @@ -1,13 +1,13 @@ /********************* */ /*! \file arith_propagation_mode.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 [[ Add one-line brief description here ]] ** diff --git a/src/options/arith_unate_lemma_mode.cpp b/src/options/arith_unate_lemma_mode.cpp index 55fd8a01f..9b683f4c1 100644 --- a/src/options/arith_unate_lemma_mode.cpp +++ b/src/options/arith_unate_lemma_mode.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file arith_unate_lemma_mode.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/options/arith_unate_lemma_mode.h b/src/options/arith_unate_lemma_mode.h index 5e1362bcb..39664d3aa 100644 --- a/src/options/arith_unate_lemma_mode.h +++ b/src/options/arith_unate_lemma_mode.h @@ -1,13 +1,13 @@ /********************* */ /*! \file arith_unate_lemma_mode.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 [[ Add one-line brief description here ]] ** diff --git a/src/options/base_handlers.h b/src/options/base_handlers.h index d4137255e..0345f9e10 100644 --- a/src/options/base_handlers.h +++ b/src/options/base_handlers.h @@ -1,13 +1,13 @@ /********************* */ /*! \file base_handlers.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Kshitij Bansal - ** 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/options/base_options_template.cpp b/src/options/base_options_template.cpp index 2c3d717fa..bdcef6029 100644 --- a/src/options/base_options_template.cpp +++ b/src/options/base_options_template.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file base_options_template.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 Contains code for handling command-line options. ** diff --git a/src/options/base_options_template.h b/src/options/base_options_template.h index c8c02ecaa..486b793d0 100644 --- a/src/options/base_options_template.h +++ b/src/options/base_options_template.h @@ -1,13 +1,13 @@ /********************* */ /*! \file base_options_template.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 Contains code for handling command-line options. ** diff --git a/src/options/boolean_term_conversion_mode.cpp b/src/options/boolean_term_conversion_mode.cpp index d1466ae14..0673718bb 100644 --- a/src/options/boolean_term_conversion_mode.cpp +++ b/src/options/boolean_term_conversion_mode.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file boolean_term_conversion_mode.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/options/boolean_term_conversion_mode.h b/src/options/boolean_term_conversion_mode.h index 81a0c661a..f2f4a51af 100644 --- a/src/options/boolean_term_conversion_mode.h +++ b/src/options/boolean_term_conversion_mode.h @@ -1,13 +1,13 @@ /********************* */ /*! \file boolean_term_conversion_mode.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 [[ Add one-line brief description here ]] ** diff --git a/src/options/bv_bitblast_mode.cpp b/src/options/bv_bitblast_mode.cpp index 99ceb41ee..9cf47fe33 100644 --- a/src/options/bv_bitblast_mode.cpp +++ b/src/options/bv_bitblast_mode.cpp @@ -1,13 +1,13 @@ /********************* */ -/*! \file bitblast_mode.cpp +/*! \file bv_bitblast_mode.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 Bitblast modes for bit-vector solver. ** diff --git a/src/options/bv_bitblast_mode.h b/src/options/bv_bitblast_mode.h index f36021478..4c8c4f626 100644 --- a/src/options/bv_bitblast_mode.h +++ b/src/options/bv_bitblast_mode.h @@ -1,13 +1,13 @@ /********************* */ -/*! \file bitblast_mode.h +/*! \file bv_bitblast_mode.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 Bitblasting modes for bit-vector solver. ** diff --git a/src/options/bv_options b/src/options/bv_options index c1180dba3..8edc809e3 100644 --- a/src/options/bv_options +++ b/src/options/bv_options @@ -11,14 +11,14 @@ option bitblastMode bitblast --bitblast=MODE CVC4::theory::bv::BitblastMode :han choose bitblasting mode, see --bitblast=help # Options for eager bit-blasting - + option bitvectorAig --bitblast-aig bool :default false :predicate abcEnabledBuild setBitblastAig :read-write bitblast by first converting to AIG (implies --bitblast=eager) expert-option bitvectorAigSimplifications --bv-aig-simp=COMMAND std::string :default "" :predicate abcEnabledBuild :read-write :link --bitblast-aig :link-smt bitblast-aig abc command to run AIG simplifications (implies --bitblast-aig, default is "balance;drw") # Options for lazy bit-blasting -option bitvectorPropagate --bv-propagate bool :default true :read-write +option bitvectorPropagate --bv-propagate bool :default true :read-write use bit-vector propagation in the bit-blaster option bitvectorEqualitySolver --bv-eq-solver bool :default true :read-write @@ -28,18 +28,18 @@ option bitvectorEqualitySlicer --bv-eq-slicer=MODE CVC4::theory::bv::BvSlicerMod turn on the slicing equality solver for the bit-vector theory (only if --bitblast=lazy) -option bitvectorInequalitySolver --bv-inequality-solver bool :default true :read-write +option bitvectorInequalitySolver --bv-inequality-solver bool :default true :read-write turn on the inequality solver for the bit-vector theory (only if --bitblast=lazy) option bitvectorAlgebraicSolver --bv-algebraic-solver bool :default true :read-write turn on the algebraic solver for the bit-vector theory (only if --bitblast=lazy) - + expert-option bitvectorAlgebraicBudget --bv-algebraic-budget unsigned :default 1500 :read-write :link --bv-algebraic-solver :link-smt bv-algebraic-solver the budget allowed for the algebraic solver in number of SAT conflicts # General options -option bitvectorToBool --bv-to-bool bool :default false :read-write +option bitvectorToBool --bv-to-bool bool :default false :read-write lift bit-vectors of size 1 to booleans when possible option bitvectorDivByZeroConst --bv-div-zero-const bool :default false :read-write @@ -47,11 +47,11 @@ option bitvectorDivByZeroConst --bv-div-zero-const bool :default false :read-wri expert-option bvExtractArithRewrite --bv-extract-arith bool :default false :read-write enable rewrite pushing extract [i:0] over arithmetic operations (can blow up) - + expert-option bvAbstraction --bv-abstraction bool :default false :read-write - mcm benchmark abstraction + mcm benchmark abstraction -expert-option skolemizeArguments --bv-skolemize bool :default false :read-write +expert-option skolemizeArguments --bv-skolemize bool :default false :read-write skolemize arguments for bv abstraction (only does something if --bv-abstraction is on) expert-option bvNumFunc --bv-num-func=NUM unsigned :default 1 @@ -62,8 +62,8 @@ expert-option bvEagerExplanations --bv-eager-explanations bool :default false :r expert-option bitvectorQuickXplain --bv-quick-xplain bool :default false minimize bv conflicts using the QuickXplain algorithm - + expert-option bvIntroducePow2 --bv-intro-pow2 bool :default false introduce bitvector powers of two as a preprocessing pass - + endmodule diff --git a/src/options/datatypes_options b/src/options/datatypes_options index b44a36e2a..e9578f8d7 100644 --- a/src/options/datatypes_options +++ b/src/options/datatypes_options @@ -23,5 +23,9 @@ option cdtBisimilar --cdt-bisimilar bool :default true do bisimilarity check for co-datatypes option dtCyclic --dt-cyclic bool :default true do cyclicity check for datatypes +option dtInferAsLemmas --dt-infer-as-lemmas bool :default false + always send lemmas out instead of making internal inferences +#option dtRExplainLemmas --dt-rexplain-lemmas bool :default true +# regression explanations for datatype lemmas endmodule diff --git a/src/options/decision_mode.cpp b/src/options/decision_mode.cpp index 0aeae1baa..3a93b0274 100644 --- a/src/options/decision_mode.cpp +++ b/src/options/decision_mode.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file decision_mode.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/options/decision_mode.h b/src/options/decision_mode.h index 420d00b4c..efc6ca213 100644 --- a/src/options/decision_mode.h +++ b/src/options/decision_mode.h @@ -1,13 +1,13 @@ /********************* */ /*! \file decision_mode.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Kshitij Bansal - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Morgan Deters, 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 [[ Add one-line brief description here ]] ** diff --git a/src/options/decision_weight.h b/src/options/decision_weight.h index 89ebe8a21..6d01b18cb 100644 --- a/src/options/decision_weight.h +++ b/src/options/decision_weight.h @@ -1,13 +1,13 @@ /********************* */ /*! \file decision_weight.h ** \verbatim - ** Original author: Kshitij Bansal - ** Major contributors: Morgan Deters - ** 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 Rewriter attributes ** diff --git a/src/options/didyoumean.cpp b/src/options/didyoumean.cpp index 1066c7a1f..d874c7bc7 100644 --- a/src/options/didyoumean.cpp +++ b/src/options/didyoumean.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file didyoumean.cpp ** \verbatim - ** Original author: Kshitij Bansal - ** Major contributors: none - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Kshitij Bansal, 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 did-you-mean style suggestions ** diff --git a/src/options/didyoumean.h b/src/options/didyoumean.h index 2615f4d0a..71a12e6fc 100644 --- a/src/options/didyoumean.h +++ b/src/options/didyoumean.h @@ -1,13 +1,13 @@ /********************* */ /*! \file didyoumean.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 did-you-mean style suggestions. ** diff --git a/src/options/didyoumean_test.cpp b/src/options/didyoumean_test.cpp index af3daa689..8117b57ac 100644 --- a/src/options/didyoumean_test.cpp +++ b/src/options/didyoumean_test.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file didyoumean_test.cpp ** \verbatim - ** Original author: Kshitij Bansal - ** Major contributors: none - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Kshitij Bansal, 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/options/language.cpp b/src/options/language.cpp index 7558c6927..665089e45 100644 --- a/src/options/language.cpp +++ b/src/options/language.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file language.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Francois Bobot, 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 Definition of input and output languages ** diff --git a/src/options/language.h b/src/options/language.h index 9191a1d59..00328e4ab 100644 --- a/src/options/language.h +++ b/src/options/language.h @@ -1,13 +1,13 @@ /********************* */ /*! \file language.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Francois Bobot, Andrew Reynolds + ** Top contributors (to current version): + ** Morgan Deters, Francois Bobot, 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 Definition of input and output languages ** diff --git a/src/options/main_options b/src/options/main_options index 7ec4fedb3..0fa799df2 100644 --- a/src/options/main_options +++ b/src/options/main_options @@ -54,8 +54,8 @@ option segvSpin --segv-spin bool :default false spin on segfault/other crash waiting for gdb undocumented-alias --segv-nospin = --no-segv-spin -expert-option tearDownIncremental : --tear-down-incremental int :default 0 - implement PUSH/POP/multi-query by destroying and recreating SmtEngine +expert-option tearDownIncremental : --tear-down-incremental=N int :default 0 + implement PUSH/POP/multi-query by destroying and recreating SmtEngine every N queries expert-option waitToJoin --wait-to-join bool :default true wait for other threads to join before quitting diff --git a/src/options/mkoptions b/src/options/mkoptions index ad8d7033f..dd5575644 100755 --- a/src/options/mkoptions +++ b/src/options/mkoptions @@ -604,7 +604,7 @@ template <> bool Options::wasSetByUser(options::${internal}__option_t) const { r for link in $links; do run_links="$run_links #line $lineno \"$kf\" - argumentExtender.extend(extra_argc, extra_argv, \"$link\", allocated);" + extender->pushBackPreemption(\"$link\");" done fi if [ -n "$smt_links" ]; then @@ -623,7 +623,7 @@ template <> bool Options::wasSetByUser(options::${internal}__option_t) const { r for link in $links_alternate; do run_links_alternate="$run_links_alternate #line $lineno \"$kf\" - argumentExtender.extend(extra_argc, extra_argv, \"$link\", allocated);" + extender->pushBackPreemption(\"$link\");" done fi if [ -n "$notifications" ]; then @@ -657,7 +657,7 @@ template <> void runBoolPredicates(options::${internal}__option_t, std::string o if [ "$type" = bool ]; then all_modules_option_handlers="${all_modules_option_handlers}${cases} #line $lineno \"$kf\" - assignBool(options::$internal, option, true);$run_links + options->assignBool(options::$internal, option, true);$run_links break; " elif [ -n "$expect_arg" -a "$internal" != - ]; then @@ -690,7 +690,7 @@ template <> options::${internal}__option_t::type runHandlerAndPredicates(options }" all_modules_option_handlers="${all_modules_option_handlers}${cases} #line $lineno \"$kf\" - assign(options::$internal, option, optionarg);$run_links + options->assign(options::$internal, option, optionarg);$run_links break; " elif [ -n "$expect_arg" ]; then @@ -733,7 +733,7 @@ template <> options::${internal}__option_t::type runHandlerAndPredicates(options if [ "$type" = bool ]; then all_modules_option_handlers="${all_modules_option_handlers}${cases_alternate} #line $lineno \"$kf\" - assignBool(options::$internal, option, false);$run_links_alternate + options->assignBool(options::$internal, option, false);$run_links_alternate break; " else @@ -1013,12 +1013,12 @@ function handle_alias { fi links="$links #line $lineno \"$kf\" - argumentExtender.extend(extra_argc, extra_argv, \"$linkopt\", allocated);" + extender->pushBackPreemption(\"$linkopt\");" if [ "$linkarg" ]; then # include also the arg links="$links #line $lineno \"$kf\" - argumentExtender.extend(extra_argc, extra_argv, optionarg.c_str(), allocated);" + extender->pushBackPreemption(optionarg.c_str());" fi shift done diff --git a/src/options/open_ostream.cpp b/src/options/open_ostream.cpp index 4c92d056b..214f148aa 100644 --- a/src/options/open_ostream.cpp +++ b/src/options/open_ostream.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file open_ostream.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/options/open_ostream.h b/src/options/open_ostream.h index ab83427a9..6c00e7dd1 100644 --- a/src/options/open_ostream.h +++ b/src/options/open_ostream.h @@ -1,13 +1,13 @@ /********************* */ -/*! \file open_stream.h +/*! \file open_ostream.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-2016 New York University and The University of Iowa - ** See the file COPYING in the top-level source directory for licensing - ** information.\endverbatim + ** Copyright (c) 2009-2016 by the authors listed in the file AUTHORS + ** in the top-level 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/options/option_exception.h b/src/options/option_exception.h index c57414026..450eda988 100644 --- a/src/options/option_exception.h +++ b/src/options/option_exception.h @@ -1,13 +1,13 @@ /********************* */ /*! \file option_exception.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 Options-related exceptions ** diff --git a/src/options/options.h b/src/options/options.h index 8fb52146f..33bd94e46 100644 --- a/src/options/options.h +++ b/src/options/options.h @@ -1,13 +1,13 @@ /********************* */ /*! \file options.h ** \verbatim - ** Original author: Morgan Deters - ** 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 Global (command-line, set-option, ...) parameters for SMT. ** @@ -27,6 +27,7 @@ #include "base/listener.h" #include "base/modal_exception.h" #include "base/tls.h" +#include "options/argument_extender.h" #include "options/language.h" #include "options/printer_modes.h" #include "options/option_exception.h" @@ -314,12 +315,18 @@ public: static std::vector<std::string> suggestSmtOptions(const std::string& optionName) throw(); /** - * Initialize the options based on the given command-line arguments. - * The return value is what's left of the command line (that is, the - * non-option arguments). + * Initialize the Options object options based on the given + * command-line arguments given in argc and argv. The return value + * is what's left of the command line (that is, the non-option + * arguments). + * + * This function uses getopt_long() and is not thread safe. + * + * Preconditions: options and argv must be non-null. */ - std::vector<std::string> parseOptions(int argc, char* argv[]) - throw(OptionException); + static std::vector<std::string> parseOptions(Options* options, + int argc, char* argv[]) + throw(OptionException); /** * Get the setting for all options. @@ -528,6 +535,22 @@ public: /** Sends a std::flush to getOut(). */ void flushOut(); + private: + + /** + * Internal procedure for implementing the parseOptions function. + * Initializes the options object based on the given command-line + * arguments. This uses an ArgumentExtender containing the + * command-line arguments. Nonoptions are stored into nonoptions. + * + * This is not thread safe. + * + * Preconditions: options, extender and nonoptions are non-null. + */ + static void parseOptionsRecursive(Options* options, + options::ArgumentExtender* extender, + std::vector<std::string>* nonoptions) + throw(OptionException); };/* class Options */ }/* CVC4 namespace */ diff --git a/src/options/options_get_option_template.cpp b/src/options/options_get_option_template.cpp index b7e5433ee..d50644a5d 100644 --- a/src/options/options_get_option_template.cpp +++ b/src/options/options_get_option_template.cpp @@ -1,13 +1,13 @@ /********************* */ -/*! \file option_handler_get_option_template.cpp +/*! \file options_get_option_template.cpp ** \verbatim - ** Original author: Morgan Deters - ** 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 Implementation of OptionsHandler::getOption. ** diff --git a/src/options/options_handler.cpp b/src/options/options_handler.cpp index 1c48f4bb1..a2809bd67 100644 --- a/src/options/options_handler.cpp +++ b/src/options/options_handler.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file options_handler.cpp ** \verbatim - ** Original author: Tim King - ** Major contributors: none - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Tim King, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2014 New York University and The University of Iowa - ** See the file COPYING in the top-level source directory for licensing - ** information.\endverbatim + ** Copyright (c) 2009-2016 by the authors listed in the file AUTHORS + ** in the top-level 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 custom handlers and predicates options. ** @@ -347,15 +347,21 @@ interleave \n\ const std::string OptionsHandler::s_triggerSelModeHelp = "\ Trigger selection modes currently supported by the --trigger-sel option:\n\ \n\ -default \n\ -+ Default, consider all subterms of quantified formulas for trigger selection.\n\ -\n\ -min \n\ +min | default \n\ + Consider only minimal subterms that meet criteria for triggers.\n\ \n\ max \n\ + Consider only maximal subterms that meet criteria for triggers. \n\ \n\ +all \n\ ++ Consider all subterms that meet criteria for triggers. \n\ +\n\ +min-s-max \n\ ++ Consider only minimal subterms that meet criteria for single triggers, maximal otherwise. \n\ +\n\ +min-s-all \n\ ++ Consider only minimal subterms that meet criteria for single triggers, all otherwise. \n\ +\n\ "; const std::string OptionsHandler::s_prenexQuantModeHelp = "\ Prenex quantifiers modes currently supported by the --prenex-quant option:\n\ @@ -428,7 +434,7 @@ post \n\ "; const std::string OptionsHandler::s_macrosQuantHelp = "\ -Template modes for quantifiers macro expansion, supported by --macros-quant-mode:\n\ +Modes for quantifiers macro expansion, supported by --macros-quant-mode:\n\ \n\ all \n\ + Infer definitions for functions, including those containing quantified formulas.\n\ @@ -441,6 +447,34 @@ ground-uf \n\ \n\ "; +const std::string OptionsHandler::s_quantDSplitHelp = "\ +Modes for quantifiers splitting, supported by --quant-dsplit-mode:\n\ +\n\ +none \n\ ++ Never split quantified formulas.\n\ +\n\ +default \n\ ++ Split quantified formulas over some finite datatypes when finite model finding is enabled.\n\ +\n\ +agg \n\ ++ Aggressively split quantified formulas.\n\ +\n\ +"; + +const std::string OptionsHandler::s_quantRepHelp = "\ +Modes for quantifiers representative selection, supported by --quant-rep-mode:\n\ +\n\ +ee \n\ ++ Let equality engine choose representatives.\n\ +\n\ +first (default) \n\ ++ Choose terms that appear first.\n\ +\n\ +depth \n\ ++ Choose terms that are of minimal depth.\n\ +\n\ +"; + theory::quantifiers::InstWhenMode OptionsHandler::stringToInstWhenMode(std::string option, std::string optarg) throw(OptionException) { if(optarg == "pre-full") { return theory::quantifiers::INST_WHEN_PRE_FULL; @@ -542,8 +576,6 @@ theory::quantifiers::QcfMode OptionsHandler::stringToQcfMode(std::string option, return theory::quantifiers::QCF_PROP_EQ; } else if(optarg == "partial") { return theory::quantifiers::QCF_PARTIAL; - } else if(optarg == "mc" ) { - return theory::quantifiers::QCF_MC; } else if(optarg == "help") { puts(s_qcfModeHelp.c_str()); exit(1); @@ -574,12 +606,18 @@ theory::quantifiers::UserPatMode OptionsHandler::stringToUserPatMode(std::string } theory::quantifiers::TriggerSelMode OptionsHandler::stringToTriggerSelMode(std::string option, std::string optarg) throw(OptionException) { - if(optarg == "default" || optarg == "all" ) { + if(optarg == "default") { return theory::quantifiers::TRIGGER_SEL_DEFAULT; } else if(optarg == "min") { return theory::quantifiers::TRIGGER_SEL_MIN; } else if(optarg == "max") { return theory::quantifiers::TRIGGER_SEL_MAX; + } else if(optarg == "min-s-max") { + return theory::quantifiers::TRIGGER_SEL_MIN_SINGLE_MAX; + } else if(optarg == "min-s-all") { + return theory::quantifiers::TRIGGER_SEL_MIN_SINGLE_ALL; + } else if(optarg == "all") { + return theory::quantifiers::TRIGGER_SEL_ALL; } else if(optarg == "help") { puts(s_triggerSelModeHelp.c_str()); exit(1); @@ -686,6 +724,37 @@ theory::quantifiers::MacrosQuantMode OptionsHandler::stringToMacrosQuantMode(std } } +theory::quantifiers::QuantDSplitMode OptionsHandler::stringToQuantDSplitMode(std::string option, std::string optarg) throw(OptionException) { + if(optarg == "none" ) { + return theory::quantifiers::QUANT_DSPLIT_MODE_NONE; + } else if(optarg == "default") { + return theory::quantifiers::QUANT_DSPLIT_MODE_DEFAULT; + } else if(optarg == "agg") { + return theory::quantifiers::QUANT_DSPLIT_MODE_AGG; + } else if(optarg == "help") { + puts(s_quantDSplitHelp.c_str()); + exit(1); + } else { + throw OptionException(std::string("unknown option for --quant-dsplit-mode: `") + + optarg + "'. Try --quant-dsplit-mode help."); + } +} + +theory::quantifiers::QuantRepMode OptionsHandler::stringToQuantRepMode(std::string option, std::string optarg) throw(OptionException) { + if(optarg == "none" ) { + return theory::quantifiers::QUANT_REP_MODE_EE; + } else if(optarg == "first" || optarg == "default") { + return theory::quantifiers::QUANT_REP_MODE_FIRST; + } else if(optarg == "depth") { + return theory::quantifiers::QUANT_REP_MODE_DEPTH; + } else if(optarg == "help") { + puts(s_quantRepHelp.c_str()); + exit(1); + } else { + throw OptionException(std::string("unknown option for --quant-rep-mode: `") + + optarg + "'. Try --quant-rep-mode help."); + } +} // theory/bv/options_handlers.h void OptionsHandler::abcEnabledBuild(std::string option, bool value) throw(OptionException) { diff --git a/src/options/options_handler.h b/src/options/options_handler.h index 9aa037004..baa6cea96 100644 --- a/src/options/options_handler.h +++ b/src/options/options_handler.h @@ -1,13 +1,13 @@ /********************* */ /*! \file options_handler.h ** \verbatim - ** Original author: Tim King - ** Major contributors: none - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Tim King, Andrew Reynolds ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2014 New York University and The University of Iowa - ** See the file COPYING in the top-level source directory for licensing - ** information.\endverbatim + ** Copyright (c) 2009-2016 by the authors listed in the file AUTHORS + ** in the top-level 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 custom handlers and predicates options. ** @@ -100,6 +100,8 @@ public: theory::quantifiers::IteLiftQuantMode stringToIteLiftQuantMode(std::string option, std::string optarg) throw(OptionException); theory::quantifiers::SygusInvTemplMode stringToSygusInvTemplMode(std::string option, std::string optarg) throw(OptionException); theory::quantifiers::MacrosQuantMode stringToMacrosQuantMode(std::string option, std::string optarg) throw(OptionException); + theory::quantifiers::QuantDSplitMode stringToQuantDSplitMode(std::string option, std::string optarg) throw(OptionException); + theory::quantifiers::QuantRepMode stringToQuantRepMode(std::string option, std::string optarg) throw(OptionException); // theory/bv/options_handlers.h void abcEnabledBuild(std::string option, bool value) throw(OptionException); @@ -199,6 +201,8 @@ public: static const std::string s_iteLiftQuantHelp; static const std::string s_literalMatchHelp; static const std::string s_macrosQuantHelp; + static const std::string s_quantDSplitHelp; + static const std::string s_quantRepHelp; static const std::string s_mbqiModeHelp; static const std::string s_modelFormatHelp; static const std::string s_prenexQuantModeHelp; diff --git a/src/options/options_holder_template.h b/src/options/options_holder_template.h index f033fd5ad..f33656eb1 100644 --- a/src/options/options_holder_template.h +++ b/src/options/options_holder_template.h @@ -1,13 +1,13 @@ /********************* */ /*! \file options_holder_template.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 Global (command-line, set-option, ...) parameters for SMT ** diff --git a/src/options/options_public_functions.cpp b/src/options/options_public_functions.cpp index 2e86c732e..8f3a63175 100644 --- a/src/options/options_public_functions.cpp +++ b/src/options/options_public_functions.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file options_public_functions.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Kshitij Bansal + ** 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 Definitions of public facing interface functions for Options. ** @@ -204,7 +204,7 @@ std::ostream* Options::getOut(){ } std::ostream* Options::getOutConst() const{ -#warning "Remove Options::getOutConst" + // #warning "Remove Options::getOutConst" return (*this)[options::out]; } diff --git a/src/options/options_set_option_template.cpp b/src/options/options_set_option_template.cpp index 04f3800f7..cc068f4e6 100644 --- a/src/options/options_set_option_template.cpp +++ b/src/options/options_set_option_template.cpp @@ -1,13 +1,13 @@ /********************* */ -/*! \file option_handler_set_option_template.cpp +/*! \file options_set_option_template.cpp ** \verbatim - ** Original author: Morgan Deters - ** 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 Implementation of OptionsHandler::setOption. ** diff --git a/src/options/options_template.cpp b/src/options/options_template.cpp index 51b2bea5e..f029dfd17 100644 --- a/src/options/options_template.cpp +++ b/src/options/options_template.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file options_template.cpp ** \verbatim - ** Original author: Morgan Deters - ** 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 Contains code for handling command-line options. ** @@ -53,13 +53,14 @@ extern int optreset; #include "base/output.h" #include "base/tls.h" #include "options/argument_extender.h" +#include "options/argument_extender_implementation.h" #include "options/didyoumean.h" #include "options/language.h" #include "options/options_handler.h" ${include_all_option_headers} -#line 63 "${template}" +#line 64 "${template}" #include "options/options_holder.h" #include "cvc4autoconfig.h" @@ -67,7 +68,7 @@ ${include_all_option_headers} ${option_handler_includes} -#line 71 "${template}" +#line 72 "${template}" using namespace CVC4; using namespace CVC4::options; @@ -389,7 +390,7 @@ Options::registerSetReplayLogFilename( ${all_custom_handlers} -#line 393 "${template}" +#line 394 "${template}" #ifdef CVC4_DEBUG # define USE_EARLY_TYPE_CHECKING_BY_DEFAULT true @@ -407,18 +408,18 @@ options::OptionsHolder::OptionsHolder() : ${all_modules_defaults} { } -#line 411 "${template}" +#line 412 "${template}" static const std::string mostCommonOptionsDescription = "\ Most commonly-used CVC4 options:${common_documentation}"; -#line 416 "${template}" +#line 417 "${template}" static const std::string optionsDescription = mostCommonOptionsDescription + "\n\ \n\ Additional CVC4 options:${remaining_documentation}"; -#line 422 "${template}" +#line 423 "${template}" static const std::string optionsFootnote = "\n\ [*] Each of these options has a --no-OPTIONNAME variant, which reverses the\n\ @@ -431,7 +432,7 @@ Languages currently supported as arguments to the -L / --lang option:\n\ cvc4 | presentation | pl CVC4 presentation language\n\ smt1 | smtlib1 SMT-LIB format 1.2\n\ smt | smtlib | smt2 |\n\ - smt2.0 | smtlib2 | smtlib2.0 SMT-LIB format 2.0\n\ + smt2.0 | smtlib2 | smtlib2.0 SMT-LIB format 2.0\n\ smt2.5 | smtlib2.5 SMT-LIB format 2.5\n\ tptp TPTP format (cnf and fof)\n\ sygus SyGuS format\n\ @@ -442,7 +443,7 @@ Languages currently supported as arguments to the --output-lang option:\n\ cvc3 CVC3 presentation language\n\ smt1 | smtlib1 SMT-LIB format 1.2\n\ smt | smtlib | smt2 |\n\ - smt2.0 | smtlib2.0 | smtlib2 SMT-LIB format 2.0\n\ + smt2.0 | smtlib2.0 | smtlib2 SMT-LIB format 2.0\n\ smt2.5 | smtlib2.5 SMT-LIB format 2.5\n\ tptp TPTP format\n\ z3str SMT-LIB 2.0 with Z3-str string constraints\n\ @@ -497,7 +498,7 @@ static struct option cmdlineOptions[] = {${all_modules_long_options} { NULL, no_argument, NULL, '\0' } };/* cmdlineOptions */ -#line 501 "${template}" +#line 502 "${template}" // static void preemptGetopt(int& argc, char**& argv, const char* opt) { @@ -549,178 +550,196 @@ public: * The return value is what's left of the command line (that is, the * non-option arguments). */ -std::vector<std::string> Options::parseOptions(int argc, char* main_argv[]) throw(OptionException) { - options::OptionsGuard guard(&s_current, this); +std::vector<std::string> Options::parseOptions(Options* options, + int argc, char* argv[]) + throw(OptionException) { - // Having this synonym simplifies the generation code in mkoptions. - options::OptionsHandler* handler = d_handler; + Assert(options != NULL); + Assert(argv != NULL); - const char *progName = main_argv[0]; + options::OptionsGuard guard(&s_current, options); - ArgumentExtender argumentExtender(s_preemptAdditional, s_maxoptlen); - std::vector<char*> allocated; + const char *progName = argv[0]; - Debug("options") << "main_argv == " << main_argv << std::endl; + // To debug options parsing, you may prefer to simply uncomment this + // and recompile. Debug flags have not been parsed yet so these have + // not been set. + //DebugChannel.on("options"); - // Reset getopt(), in the case of multiple calls to parseOptions(). - // This can be = 1 in newer GNU getopt, but older (< 2007) require = 0. - optind = 0; -#if HAVE_DECL_OPTRESET - optreset = 1; // on BSD getopt() (e.g. Mac OS), might need this -#endif /* HAVE_DECL_OPTRESET */ + Debug("options") << "Options::parseOptions == " << options << std::endl; + Debug("options") << "argv == " << argv << std::endl; - // find the base name of the program + // Find the base name of the program. const char *x = strrchr(progName, '/'); if(x != NULL) { progName = x + 1; } - d_holder->binary_name = std::string(progName); + options->d_holder->binary_name = std::string(progName); + + ArgumentExtender* argumentExtender = new ArgumentExtenderImplementation(); + for(int position = 1; position < argc; position++) { + argumentExtender->pushBackArgument(argv[position]); + } + + std::vector<std::string> nonoptions; + parseOptionsRecursive(options, argumentExtender, &nonoptions); + if(Debug.isOn("options")){ + for(std::vector<std::string>::const_iterator i = nonoptions.begin(), + iend = nonoptions.end(); i != iend; ++i){ + Debug("options") << "nonoptions " << *i << std::endl; + } + } + + delete argumentExtender; + return nonoptions; +} + +void Options::parseOptionsRecursive(Options* options, + ArgumentExtender* extender, + std::vector<std::string>* nonoptions) + throw(OptionException) { + + int argc; + char** argv; + + extender->movePreemptionsToArguments(); + extender->pushFrontArgument(""); + extender->getArguments(&argc, &argv); + + if(Debug.isOn("options")) { + Debug("options") << "starting a new parseOptionsRecursive with " + << argc << " arguments" << std::endl; + for( int i = 0; i < argc ; i++ ){ + Assert(argv[i] != NULL); + Debug("options") << " argv[" << i << "] = " << argv[i] << std::endl; + } + } - int extra_argc = 1; - char **extra_argv = (char**) malloc(2 * sizeof(char*)); - extra_argv[0] = NULL; - extra_argv[1] = NULL; + // Having this synonym simplifies the generation code in mkoptions. + options::OptionsHandler* handler = options->d_handler; + options::OptionsHolder* holder = options->d_holder; - int extra_optind = 0, main_optind = 0; + // Reset getopt(), in the case of multiple calls to parseOptions(). + // This can be = 1 in newer GNU getopt, but older (< 2007) require = 0. + optind = 0; +#if HAVE_DECL_OPTRESET + optreset = 1; // on BSD getopt() (e.g. Mac OS), might need this +#endif /* HAVE_DECL_OPTRESET */ + + + int main_optind = 0; int old_optind; - int *optind_ref = &main_optind; - char** argv = main_argv; - std::vector<std::string> nonOptions; + while(true) { // Repeat Forever + + if(extender->hasPreemptions()){ + // Stop this round of parsing. We now parse recursively + // to start on a new character array for argv. + parseOptionsRecursive(options, extender, nonoptions); + break; + } - for(;;) { - int c = -1; optopt = 0; std::string option, optionarg; - Debug("preemptGetopt") << "top of loop, extra_optind == " << extra_optind - << ", extra_argc == " << extra_argc << std::endl; - if((extra_optind == 0 ? 1 : extra_optind) < extra_argc) { -#if HAVE_DECL_OPTRESET - if(optind_ref != &extra_optind) { - optreset = 1; // on BSD getopt() (e.g. Mac OS), might need this - } -#endif /* HAVE_DECL_OPTRESET */ - old_optind = optind = extra_optind; - optind_ref = &extra_optind; - argv = extra_argv; - Debug("preemptGetopt") << "in preempt code, next arg is " - << extra_argv[optind == 0 ? 1 : optind] - << std::endl; - if(extra_argv[extra_optind == 0 ? 1 : extra_optind][0] != '-') { - InternalError( - "preempted args cannot give non-options command-line args (found `%s')", - extra_argv[extra_optind == 0 ? 1 : extra_optind]); - } - c = getopt_long(extra_argc, extra_argv, - "+:${all_modules_short_options}", - cmdlineOptions, NULL); - Debug("preemptGetopt") << "in preempt code" - << ", c == " << c << " (`" << char(c) << "')" - << " optind == " << optind << std::endl; - if(optopt == 0 || - ( optopt >= ${long_option_value_begin} && optopt <= ${long_option_value_end} )) { - // long option - option = argv[old_optind == 0 ? 1 : old_optind]; - optionarg = (optarg == NULL) ? "" : optarg; - } else { - // short option - option = std::string("-") + char(optopt); - optionarg = (optarg == NULL) ? "" : optarg; - } - if(optind >= extra_argc) { - Debug("preemptGetopt") << "-- no more preempt args" << std::endl; - unsigned i = 1; - while(extra_argv[i] != NULL && extra_argv[i][0] != '\0') { - extra_argv[i][0] = '\0'; - ++i; - } - extra_argc = 1; - extra_optind = 0; - } else { - Debug("preemptGetopt") << "-- more preempt args" << std::endl; - extra_optind = optind; - } + + optind = main_optind; + old_optind = main_optind; + //optind_ref = &main_optind; + //argv = main_argv; + + // If we encounter an element that is not at zero and does not start + // with a "-", this is a non-option. We consume this element as a + // non-option. + if (main_optind > 0 && main_optind < argc && + argv[main_optind][0] != '-') { + Debug("options") << "enqueueing " << argv[main_optind] + << " as a non-option." << std::endl; + nonoptions->push_back(argv[main_optind]); + ++main_optind; + extender->popFrontArgument(); + continue; } - if(c == -1) { -#if HAVE_DECL_OPTRESET - if(optind_ref != &main_optind) { - optreset = 1; // on BSD getopt() (e.g. Mac OS), might need this - } -#endif /* HAVE_DECL_OPTRESET */ - old_optind = optind = main_optind; - optind_ref = &main_optind; - argv = main_argv; - if(main_optind < argc && main_argv[main_optind][0] != '-') { - do { - if(main_optind != 0) { - nonOptions.push_back(main_argv[main_optind]); - } - ++main_optind; - } while(main_optind < argc && main_argv[main_optind][0] != '-'); - continue; - } - Debug("options") << "[ before, optind == " << optind << " ]" << std::endl; -#if defined(__MINGW32__) || defined(__MINGW64__) - if(optreset == 1 && optind > 1) { - // on mingw, optreset will reset the optind, so we have to - // manually advance argc, argv - main_argv[optind - 1] = main_argv[0]; - argv = main_argv += optind - 1; - argc -= optind - 1; - old_optind = optind = main_optind = 1; - if(argc > 0) { - Debug("options") << "looking at : " << argv[0] << std::endl; - } - /*c = getopt_long(argc, main_argv, + + + Debug("options") << "[ before, main_optind == " << main_optind << " ]" + << std::endl; + Debug("options") << "[ before, optind == " << optind << " ]" << std::endl; + Debug("options") << "[ argc == " << argc << ", argv == " << argv << " ]" + << std::endl; + int c = getopt_long(argc, argv, "+:${all_modules_short_options}", cmdlineOptions, NULL); - Debug("options") << "pre-emptory c is " << c << " (" << char(c) << ")" << std::endl; - Debug("options") << "optind was reset to " << optind << std::endl; - optind = main_optind; - Debug("options") << "I restored optind to " << optind << std::endl;*/ - } -#endif /* __MINGW32__ || __MINGW64__ */ - Debug("options") << "[ argc == " << argc - << ", main_argv == " << main_argv << " ]" << std::endl; - c = getopt_long(argc, main_argv, - "+:${all_modules_short_options}", - cmdlineOptions, NULL); - main_optind = optind; - Debug("options") << "[ got " << int(c) << " (" << char(c) << ") ]" - << std::endl; - Debug("options") << "[ next option will be at pos: " << optind << " ]" - << std::endl; - if(c == -1) { + + while(main_optind < optind) { + main_optind++; + extender->popFrontArgument(); + } + + Debug("options") << "[ got " << int(c) << " (" << char(c) << ") ]" + << "[ next option will be at pos: " << optind << " ]" + << std::endl; + + // The initial getopt_long call should always determine that argv[0] + // is not an option and returns -1. We always manually advance beyond + // this element. + // + // We have to reinitialize optind to 0 instead of 1 as we need to support + // changing the argv array passed to getopt. + // This is needed as are using GNU extensions. + // From: http://man7.org/linux/man-pages/man3/getopt.3.html + // A program that scans multiple argument vectors, or rescans the same + // vector more than once, and wants to make use of GNU extensions such + // as '+' and '-' at the start of optstring, or changes the value of + // POSIXLY_CORRECT between scans, must reinitialize getopt() by + // resetting optind to 0, rather than the traditional value of 1. + // (Resetting to 0 forces the invocation of an internal initialization + // routine that rechecks POSIXLY_CORRECT and checks for GNU extensions + // in optstring.) + if ( old_optind == 0 && c == -1 ) { + Assert(main_optind > 0); + continue; + } + + if ( c == -1 ) { + if(Debug.isOn("options")) { Debug("options") << "done with option parsing" << std::endl; - break; + for(int index = optind; index < argc; ++index) { + Debug("options") << "remaining " << argv[index] << std::endl; + } } - option = argv[old_optind == 0 ? 1 : old_optind]; - optionarg = (optarg == NULL) ? "" : optarg; + break; } + option = argv[old_optind == 0 ? 1 : old_optind]; + optionarg = (optarg == NULL) ? "" : optarg; + Debug("preemptGetopt") << "processing option " << c << " (`" << char(c) << "'), " << option << std::endl; switch(c) { ${all_modules_option_handlers} -#line 709 "${template}" +#line 722 "${template}" case ':': // This can be a long or short option, and the way to get at the // name of it is different. - throw OptionException(std::string("option `") + option + "' missing its required argument"); + throw OptionException(std::string("option `") + option + + "' missing its required argument"); case '?': default: - if( ( optopt == 0 || ( optopt >= ${long_option_value_begin} && optopt <= ${long_option_value_end} ) ) && - !strncmp(argv[optind - 1], "--thread", 8) && - strlen(argv[optind - 1]) > 8 ) { + if( ( optopt == 0 || + ( optopt >= ${long_option_value_begin} && + optopt <= ${long_option_value_end} ) + ) && !strncmp(argv[optind - 1], "--thread", 8) && + strlen(argv[optind - 1]) > 8 ) + { if(! isdigit(argv[optind - 1][8])) { throw OptionException(formatThreadOptionException(option)); } - std::vector<std::string>& threadArgv = d_holder->threadArgv; + std::vector<std::string>& threadArgv = holder->threadArgv; char *end; long tnum = strtol(argv[optind - 1] + 8, &end, 10); if(tnum < 0 || (*end != '\0' && *end != '=')) { @@ -734,23 +753,24 @@ ${all_modules_option_handlers} } if(*end == '\0') { // e.g., we have --thread0 "foo" if(argc <= optind) { - throw OptionException(std::string("option `") + option - + "' missing its required argument"); + throw OptionException(std::string("option `") + option + + "' missing its required argument"); } Debug("options") << "thread " << tnum << " gets option " << argv[optind] << std::endl; - threadArgv[tnum] += argv[(*optind_ref)++]; + threadArgv[tnum] += argv[main_optind]; + main_optind++; } else { // e.g., we have --thread0="foo" if(end[1] == '\0') { throw OptionException(std::string("option `") + option + "' missing its required argument"); } - Debug("options") << "thread " << tnum << " gets option " << (end + 1) - << std::endl; + Debug("options") << "thread " << tnum << " gets option " + << (end + 1) << std::endl; threadArgv[tnum] += end + 1; } - Debug("options") << "thread " << tnum << " now has " << threadArgv[tnum] - << std::endl; + Debug("options") << "thread " << tnum << " now has " + << threadArgv[tnum] << std::endl; break; } @@ -759,19 +779,10 @@ ${all_modules_option_handlers} } } - Debug("options") << "returning " << nonOptions.size() << " non-option arguments." << std::endl; - - free(extra_argv); - for(std::vector<char*>::iterator i = allocated.begin(), iend = allocated.end(); - i != iend; ++i) - { - char* current = *i; - #warning "TODO: Unit tests fail if garbage collection is done here." - //free(current); - } - allocated.clear(); + Debug("options") << "got " << nonoptions->size() + << " non-option arguments." << std::endl; - return nonOptions; + free(argv); } std::string Options::suggestCommandLineOptions(const std::string& optionName) throw() { @@ -787,7 +798,7 @@ std::string Options::suggestCommandLineOptions(const std::string& optionName) th static const char* smtOptions[] = { ${all_modules_smt_options}, -#line 790 "${template}" +#line 800 "${template}" NULL };/* smtOptions[] */ @@ -809,7 +820,7 @@ std::vector< std::vector<std::string> > Options::getOptions() const throw() { ${all_modules_get_options} -#line 813 "${template}" +#line 762 "${template}" return opts; } diff --git a/src/options/printer_modes.cpp b/src/options/printer_modes.cpp index b698ed07d..3ca311a96 100644 --- a/src/options/printer_modes.cpp +++ b/src/options/printer_modes.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file printer_modes.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 [[ Add one-line brief description here ]] ** diff --git a/src/options/printer_modes.h b/src/options/printer_modes.h index 8ccceb13f..a05ca2470 100644 --- a/src/options/printer_modes.h +++ b/src/options/printer_modes.h @@ -1,13 +1,13 @@ /********************* */ /*! \file printer_modes.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 [[ Add one-line brief description here ]] ** diff --git a/src/options/quantifiers_modes.cpp b/src/options/quantifiers_modes.cpp index e87f00d65..a58120974 100644 --- a/src/options/quantifiers_modes.cpp +++ b/src/options/quantifiers_modes.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file quantifiers_modes.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 [[ Add one-line brief description here ]] ** diff --git a/src/options/quantifiers_modes.h b/src/options/quantifiers_modes.h index 540db38ec..5749da972 100644 --- a/src/options/quantifiers_modes.h +++ b/src/options/quantifiers_modes.h @@ -1,13 +1,13 @@ /********************* */ /*! \file quantifiers_modes.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, 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 ]] ** @@ -83,8 +83,6 @@ enum QcfMode { QCF_PROP_EQ, /** use qcf for conflicts, propagations and heuristic instantiations */ QCF_PARTIAL, - /** use qcf for model checking */ - QCF_MC, }; enum UserPatMode { @@ -107,6 +105,12 @@ enum TriggerSelMode { TRIGGER_SEL_MIN, /** only consider maximal terms for triggers */ TRIGGER_SEL_MAX, + /** consider minimal terms for single triggers, maximal for non-single */ + TRIGGER_SEL_MIN_SINGLE_MAX, + /** consider minimal terms for single triggers, all for non-single */ + TRIGGER_SEL_MIN_SINGLE_ALL, + /** consider all terms for triggers */ + TRIGGER_SEL_ALL, }; enum CVC4_PUBLIC PrenexQuantMode { @@ -163,6 +167,24 @@ enum MacrosQuantMode { MACROS_QUANT_MODE_GROUND_UF, }; +enum QuantDSplitMode { + /** never do quantifiers splitting */ + QUANT_DSPLIT_MODE_NONE, + /** default */ + QUANT_DSPLIT_MODE_DEFAULT, + /** do quantifiers splitting aggressively */ + QUANT_DSPLIT_MODE_AGG, +}; + +enum QuantRepMode { + /** let equality engine choose representatives */ + QUANT_REP_MODE_EE, + /** default, choose representatives that appear first */ + QUANT_REP_MODE_FIRST, + /** choose representatives that have minimal depth */ + QUANT_REP_MODE_DEPTH, +}; + }/* CVC4::theory::quantifiers namespace */ }/* CVC4::theory namespace */ diff --git a/src/options/quantifiers_options b/src/options/quantifiers_options index f5a6ee843..74b3011a6 100644 --- a/src/options/quantifiers_options +++ b/src/options/quantifiers_options @@ -37,11 +37,6 @@ option condVarSplitQuantAgg --cond-var-split-agg-quant bool :default false aggressive split quantified formulas that lead to variable eliminations option iteDtTesterSplitQuant --ite-dtt-split-quant bool :read-write :default false split ites with dt testers as conditions -# Whether to CNF quantifier bodies -# option cnfQuant --cnf-quant bool :default false -# apply CNF conversion to quantified formulas -option nnfQuant --nnf-quant bool :default true - apply NNF conversion to quantified formulas # Whether to pre-skolemize quantifier bodies. # For example, forall x. ( P( x ) => (exists y. f( y ) = x) ) will be rewritten to # forall x. P( x ) => f( S( x ) ) = x @@ -57,6 +52,8 @@ option elimTautQuant --elim-taut-quant bool :default true eliminate tautological disjuncts of quantified formulas option purifyQuant --purify-quant bool :default false purify quantified formulas +option elimExtArithQuant --elim-ext-arith-quant bool :default true + eliminate extended arithmetic symbols in quantified formulas #### E-matching options @@ -67,9 +64,13 @@ option termDbMode --term-db-mode CVC4::theory::quantifiers::TermDbMode :default which ground terms to consider for instantiation option registerQuantBodyTerms --register-quant-body-terms bool :default false consider ground terms within bodies of quantified formulas for matching +option inferArithTriggerEq --infer-arith-trigger-eq bool :default false + infer equalities for trigger terms based on solving arithmetic equalities +option inferArithTriggerEqExp --infer-arith-trigger-eq-exp bool :default false + record explanations for inferArithTriggerEq -option smartTriggers --smart-triggers bool :default true - enable smart triggers +option strictTriggers --strict-triggers bool :default false + only instantiate quantifiers with user patterns based on triggers option relevantTriggers --relevant-triggers bool :default false prefer triggers that are more relevant based on SInE style analysis option relationalTriggers --relational-triggers bool :default false @@ -88,20 +89,26 @@ option multiTriggerPriority --multi-trigger-priority bool :default false only try multi triggers if single triggers give no instantiations option triggerSelMode --trigger-sel CVC4::theory::quantifiers::TriggerSelMode :default CVC4::theory::quantifiers::TRIGGER_SEL_DEFAULT :read-write :include "options/quantifiers_modes.h" :handler stringToTriggerSelMode selection mode for triggers -option userPatternsQuant --user-pat=MODE CVC4::theory::quantifiers::UserPatMode :default CVC4::theory::quantifiers::USER_PAT_MODE_TRUST :include "options/quantifiers_modes.h" :handler stringToUserPatMode +option userPatternsQuant --user-pat=MODE CVC4::theory::quantifiers::UserPatMode :default CVC4::theory::quantifiers::USER_PAT_MODE_TRUST :read-write :include "options/quantifiers_modes.h" :handler stringToUserPatMode policy for handling user-provided patterns for quantifier instantiation option incrementTriggers --increment-triggers bool :default true generate additional triggers as needed during search option instWhenMode --inst-when=MODE CVC4::theory::quantifiers::InstWhenMode :default CVC4::theory::quantifiers::INST_WHEN_FULL_LAST_CALL :read-write :include "options/quantifiers_modes.h" :handler stringToInstWhenMode :predicate checkInstWhenMode when to apply instantiation +option instWhenStrictInterleave --inst-when-strict-interleave bool :default true :read-write + ensure theory combination and standard quantifier effort strategies take turns +option instWhenPhase --inst-when-phase=N int :read-write :default 2 :read-write + instantiation rounds quantifiers takes (>=1) before allowing theory combination to happen +option instWhenTcFirst --inst-when-tc-first bool :default true :read-write + allow theory combination to happen once initially, before quantifier strategies are run option instMaxLevel --inst-max-level=N int :read-write :default -1 maximum inst level of terms used to instantiate quantified formulas with (-1 == no limit, default) option instLevelInputOnly --inst-level-input-only bool :default true only input terms are assigned instantiation level zero -option internalReps --quant-internal-reps bool :default true - instantiate with representatives chosen by quantifiers engine +option quantRepMode --quant-rep-mode=MODE CVC4::theory::quantifiers::QuantRepMode :default CVC4::theory::quantifiers::QUANT_REP_MODE_FIRST :read-write :include "options/quantifiers_modes.h" :handler stringToQuantRepMode + selection mode for representatives in quantifiers engine option eagerInstQuant --eager-inst-quant bool :default false apply quantifier instantiation eagerly @@ -167,6 +174,9 @@ option qcfAllConflict --qcf-all-conflict bool :read-write :default false option instNoEntail --inst-no-entail bool :read-write :default true do not consider instances of quantified formulas that are currently entailed + +option instPropagate --inst-propagate bool :read-write :default false + internal propagation for instantiations for selecting relevant instances ### rewrite rules options @@ -200,6 +210,8 @@ option conjectureGenGtEnum --conjecture-gen-gt-enum=N int :default 50 number of ground terms to generate for model filtering option conjectureUeeIntro --conjecture-gen-uee-intro bool :default false more aggressive merging for universal equality engine, introduces terms +option conjectureGenMaxDepth --conjecture-gen-max-depth=N int :default 3 + maximum depth of terms to consider for conjectures ### synthesis options @@ -283,6 +295,10 @@ option macrosQuant --macros-quant bool :read-write :default false perform quantifiers macro expansion option macrosQuantMode --macros-quant-mode=MODE CVC4::theory::quantifiers::MacrosQuantMode :default CVC4::theory::quantifiers::MACROS_QUANT_MODE_GROUND_UF :include "options/quantifiers_modes.h" :handler stringToMacrosQuantMode mode for quantifiers macro expansion +option quantDynamicSplit --quant-dsplit-mode=MODE CVC4::theory::quantifiers::QuantDSplitMode :read-write :default CVC4::theory::quantifiers::QUANT_DSPLIT_MODE_DEFAULT :include "options/quantifiers_modes.h" :handler stringToQuantDSplitMode + mode for dynamic quantifiers splitting +option quantAntiSkolem --quant-anti-skolem bool :read-write :default false + perform anti-skolemization for quantified formulas ### recursive function options diff --git a/src/options/set_language.cpp b/src/options/set_language.cpp index f68adbb45..32d3d73ae 100644 --- a/src/options/set_language.cpp +++ b/src/options/set_language.cpp @@ -1,13 +1,13 @@ /********************* */ -/*! \file language.h +/*! \file set_language.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Francois Bobot, Andrew Reynolds + ** 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 Definition of input and output languages ** diff --git a/src/options/set_language.h b/src/options/set_language.h index 53b0a6a63..c27bb5184 100644 --- a/src/options/set_language.h +++ b/src/options/set_language.h @@ -1,13 +1,13 @@ /********************* */ -/*! \file language.h +/*! \file set_language.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Francois Bobot, Andrew Reynolds + ** 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 Definition of input and output languages ** diff --git a/src/options/sets_options b/src/options/sets_options index 67bed5fe7..be945e4c9 100644 --- a/src/options/sets_options +++ b/src/options/sets_options @@ -17,4 +17,12 @@ expert-option setsCare1 --sets-care1 bool :default false option setsPropFull --sets-prop-full bool :default true additional propagation at full effort +option setsAggRewrite --sets-agg-rewrite bool :default false + aggressive sets rewriting + +option setsGuessEmpty --sets-guess-empty int :default 0 + when to guess leaf nodes being empty (0...2 : most aggressive..least aggressive) + +option setsSlowLemmas --sets-slow-lemmas bool :default true + endmodule diff --git a/src/options/simplification_mode.cpp b/src/options/simplification_mode.cpp index ab7851ef9..7189dacd1 100644 --- a/src/options/simplification_mode.cpp +++ b/src/options/simplification_mode.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file simplification_mode.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/options/simplification_mode.h b/src/options/simplification_mode.h index dd02ada5c..d1170f9ad 100644 --- a/src/options/simplification_mode.h +++ b/src/options/simplification_mode.h @@ -1,13 +1,13 @@ /********************* */ /*! \file simplification_mode.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 [[ Add one-line brief description here ]] ** diff --git a/src/options/strings_options b/src/options/strings_options index 65c293dbc..5c991a1bb 100644 --- a/src/options/strings_options +++ b/src/options/strings_options @@ -53,6 +53,18 @@ option stringInferSym strings-infer-sym --strings-infer-sym bool :default true strings split on empty string option stringEagerLen strings-eager-len --strings-eager-len bool :default true strings eager length lemmas +option stringCheckEntailLen strings-check-entail-len --strings-check-entail-len bool :default true + check entailment between length terms to reduce splitting +option stringProcessLoop strings-process-loop --strings-process-loop bool :default true + reduce looping word equations to regular expressions +option stringAbortLoop strings-abort-loop --strings-abort-loop bool :default false + abort when a looping word equation is encountered +option stringInferAsLemmas strings-infer-as-lemmas --strings-infer-as-lemmas bool :default false + always send lemmas out instead of making internal inferences +option stringRExplainLemmas strings-rexplain-lemmas --strings-rexplain-lemmas bool :default true + regression explanations for string lemmas +option stringMinPrefixExplain strings-min-prefix-explain --strings-min-prefix-explain bool :default true + minimize explanations for prefix of normal forms in strings endmodule diff --git a/src/options/theoryof_mode.cpp b/src/options/theoryof_mode.cpp index c05f97ede..cf7178042 100644 --- a/src/options/theoryof_mode.cpp +++ b/src/options/theoryof_mode.cpp @@ -1,3 +1,20 @@ +/********************* */ +/*! \file theoryof_mode.cpp + ** \verbatim + ** Top contributors (to current version): + ** 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 "options/theoryof_mode.h" diff --git a/src/options/theoryof_mode.h b/src/options/theoryof_mode.h index 5a8723738..98f05a131 100644 --- a/src/options/theoryof_mode.h +++ b/src/options/theoryof_mode.h @@ -1,13 +1,13 @@ /********************* */ /*! \file theoryof_mode.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 Option selection for theoryOf() operation ** diff --git a/src/options/ufss_mode.h b/src/options/ufss_mode.h index 6ce05d46a..4a4b8b4c1 100644 --- a/src/options/ufss_mode.h +++ b/src/options/ufss_mode.h @@ -1,13 +1,13 @@ /********************* */ /*! \file ufss_mode.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 Custom handlers and predicates for TheoryUF options ** diff --git a/src/parser/antlr_input.cpp b/src/parser/antlr_input.cpp index a1f74d694..6edb23a23 100644 --- a/src/parser/antlr_input.cpp +++ b/src/parser/antlr_input.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file antlr_input.cpp ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: Morgan Deters, Kshitij Bansal - ** Minor contributors (to current version): Francois Bobot + ** Top contributors (to current version): + ** Christopher L. Conway, 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 A super-class for ANTLR-generated input language parsers. ** diff --git a/src/parser/antlr_input.h b/src/parser/antlr_input.h index 241d1bc83..8e5e82811 100644 --- a/src/parser/antlr_input.h +++ b/src/parser/antlr_input.h @@ -1,13 +1,13 @@ /********************* */ /*! \file antlr_input.h ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): Tim King, Francois Bobot, Dejan Jovanovic + ** Top contributors (to current version): + ** Christopher L. Conway, 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 for ANTLR parser classes. ** diff --git a/src/parser/antlr_line_buffered_input.cpp b/src/parser/antlr_line_buffered_input.cpp index 99b4a3068..22bbaf1db 100644 --- a/src/parser/antlr_line_buffered_input.cpp +++ b/src/parser/antlr_line_buffered_input.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file antlr_line_buffered_input.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/parser/antlr_line_buffered_input.h b/src/parser/antlr_line_buffered_input.h index c47ab324f..2c01a9bde 100644 --- a/src/parser/antlr_line_buffered_input.h +++ b/src/parser/antlr_line_buffered_input.h @@ -1,13 +1,13 @@ /********************* */ /*! \file antlr_line_buffered_input.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 [[ Add one-line brief description here ]] ** diff --git a/src/parser/antlr_tracing.h b/src/parser/antlr_tracing.h index 1709e99a2..93a781796 100644 --- a/src/parser/antlr_tracing.h +++ b/src/parser/antlr_tracing.h @@ -1,13 +1,13 @@ /********************* */ /*! \file antlr_tracing.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 [[ Add one-line brief description here ]] ** diff --git a/src/parser/antlr_undefines.h b/src/parser/antlr_undefines.h index 35a6c7e12..edf64c8a6 100644 --- a/src/parser/antlr_undefines.h +++ b/src/parser/antlr_undefines.h @@ -1,13 +1,13 @@ /********************* */ /*! \file antlr_undefines.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-2016 New York University and The University of Iowa - ** See the file COPYING in the top-level source directory for licensing - ** information.\endverbatim + ** Copyright (c) 2009-2016 by the authors listed in the file AUTHORS + ** in the top-level source directory) and their institutional affiliations. + ** All rights reserved. See the file COPYING in the top-level source + ** directory for licensing information.\endverbatim ** ** \brief Every usage undefines standard autotools macro names. ** diff --git a/src/parser/bounded_token_buffer.cpp b/src/parser/bounded_token_buffer.cpp index 716639665..c89005941 100644 --- a/src/parser/bounded_token_buffer.cpp +++ b/src/parser/bounded_token_buffer.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file bounded_token_buffer.cpp ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: none - ** Minor contributors (to current version): Morgan Deters + ** Top contributors (to current version): + ** Christopher L. Conway, 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 ANTLR3 bounded token stream implementation. ** diff --git a/src/parser/bounded_token_buffer.h b/src/parser/bounded_token_buffer.h index d11986754..947b33f69 100644 --- a/src/parser/bounded_token_buffer.h +++ b/src/parser/bounded_token_buffer.h @@ -1,13 +1,13 @@ /********************* */ /*! \file bounded_token_buffer.h ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Christopher L. Conway, 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 ANTLR3 bounded token stream. ** diff --git a/src/parser/bounded_token_factory.cpp b/src/parser/bounded_token_factory.cpp index 7d130146f..1c5a00958 100644 --- a/src/parser/bounded_token_factory.cpp +++ b/src/parser/bounded_token_factory.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file bounded_token_factory.cpp ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: none - ** Minor contributors (to current version): Morgan Deters + ** Top contributors (to current version): + ** Christopher L. Conway, 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 ANTLR3 bounded token factory implementation. ** diff --git a/src/parser/bounded_token_factory.h b/src/parser/bounded_token_factory.h index 5e5e48fab..8535d49cf 100644 --- a/src/parser/bounded_token_factory.h +++ b/src/parser/bounded_token_factory.h @@ -1,13 +1,13 @@ /********************* */ /*! \file bounded_token_factory.h ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Christopher L. Conway, 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 ANTLR3 bounded token factory. ** diff --git a/src/parser/cvc/Cvc.g b/src/parser/cvc/Cvc.g index 967503074..c497fcd0d 100644 --- a/src/parser/cvc/Cvc.g +++ b/src/parser/cvc/Cvc.g @@ -1,13 +1,13 @@ /* ******************* */ /*! \file Cvc.g ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): Tim King, Dejan Jovanovic, Tianyi Liang, Andrew Reynolds + ** Top contributors (to current version): + ** Morgan Deters, Christopher L. Conway, 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 Parser for CVC presentation input language ** @@ -213,16 +213,35 @@ tokens { // Strings STRING_TOK = 'STRING'; - SCONCAT_TOK = 'SCONCAT'; - SCONTAINS_TOK = 'CONTAINS'; - SSUBSTR_TOK = 'SUBSTR'; - SINDEXOF_TOK = 'INDEXOF'; - SREPLACE_TOK = 'REPLACE'; - SPREFIXOF_TOK = 'PREFIXOF'; - SSUFFIXOF_TOK = 'SUFFIXOF'; - STOINTEGER_TOK = 'TO_INTEGER'; - STOSTRING_TOK = 'TO_STRING'; - STORE_TOK = 'TO_RE'; + STRING_CONCAT_TOK = 'CONCAT'; + STRING_LENGTH_TOK = 'LENGTH'; + STRING_CONTAINS_TOK = 'CONTAINS'; + STRING_SUBSTR_TOK = 'SUBSTR'; + STRING_CHARAT_TOK = 'CHARAT'; + STRING_INDEXOF_TOK = 'INDEXOF'; + STRING_REPLACE_TOK = 'REPLACE'; + STRING_PREFIXOF_TOK = 'PREFIXOF'; + STRING_SUFFIXOF_TOK = 'SUFFIXOF'; + STRING_STOI_TOK = 'STRING_TO_INTEGER'; + STRING_ITOS_TOK = 'INTEGER_TO_STRING'; + STRING_U16TOS_TOK = 'UINT16_TO_STRING'; + STRING_STOU16_TOK = 'STRING_TO_UINT16'; + STRING_U32TOS_TOK = 'UINT32_TO_STRING'; + STRING_STOU32_TOK = 'STRING_TO_UINT32'; + //Regular expressions (TODO) + //STRING_IN_REGEXP_TOK + //STRING_TO_REGEXP_TOK + //REGEXP_CONCAT_TOK + //REGEXP_UNION_TOK + //REGEXP_INTER_TOK + //REGEXP_STAR_TOK + //REGEXP_PLUS_TOK + //REGEXP_OPT_TOK + //REGEXP_RANGE_TOK + //REGEXP_LOOP_TOK + //REGEXP_EMPTY_TOK + //REGEXP_SIGMA_TOK + FMF_CARD_TOK = 'HAS_CARD'; @@ -367,6 +386,7 @@ Kind getOperatorKind(int type, bool& negate) { case CONCAT_TOK: return kind::BITVECTOR_CONCAT; case BAR: return kind::BITVECTOR_OR; case BVAND_TOK: return kind::BITVECTOR_AND; + } std::stringstream ss; @@ -1694,7 +1714,6 @@ postfixTerm[CVC4::Expr& f] f = MK_EXPR(CVC4::kind::SELECT, f, f2); } } - /* left- or right-shift */ | ( LEFTSHIFT_TOK { left = true; } | RIGHTSHIFT_TOK { left = false; } ) k=numeral @@ -1920,7 +1939,6 @@ bvTerm[CVC4::Expr& f] { f = MK_EXPR(CVC4::kind::BITVECTOR_SGT, f, f2); } | BVSGE_TOK LPAREN formula[f] COMMA formula[f2] RPAREN { f = MK_EXPR(CVC4::kind::BITVECTOR_SGE, f, f2); } - | stringTerm[f] ; @@ -1932,27 +1950,35 @@ stringTerm[CVC4::Expr& f] std::vector<Expr> args; } /* String prefix operators */ - : SCONCAT_TOK LPAREN formula[f] { args.push_back(f); } + : STRING_CONCAT_TOK LPAREN formula[f] { args.push_back(f); } ( COMMA formula[f2] { args.push_back(f2); } )+ RPAREN { f = MK_EXPR(CVC4::kind::STRING_CONCAT, args); } - | SCONTAINS_TOK LPAREN formula[f] COMMA formula[f2] RPAREN + | STRING_LENGTH_TOK LPAREN formula[f] RPAREN + { f = MK_EXPR(CVC4::kind::STRING_LENGTH, f); } + | STRING_CONTAINS_TOK LPAREN formula[f] COMMA formula[f2] RPAREN { f = MK_EXPR(CVC4::kind::STRING_STRCTN, f, f2); } - | SSUBSTR_TOK LPAREN formula[f] COMMA formula[f2] COMMA formula[f3] RPAREN + | STRING_SUBSTR_TOK LPAREN formula[f] COMMA formula[f2] COMMA formula[f3] RPAREN { f = MK_EXPR(CVC4::kind::STRING_SUBSTR, f, f2, f3); } - | SINDEXOF_TOK LPAREN formula[f] COMMA formula[f2] COMMA formula[f3] RPAREN + | STRING_INDEXOF_TOK LPAREN formula[f] COMMA formula[f2] COMMA formula[f3] RPAREN { f = MK_EXPR(CVC4::kind::STRING_STRIDOF, f, f2, f3); } - | SREPLACE_TOK LPAREN formula[f] COMMA formula[f2] COMMA formula[f3] RPAREN + | STRING_REPLACE_TOK LPAREN formula[f] COMMA formula[f2] COMMA formula[f3] RPAREN { f = MK_EXPR(CVC4::kind::STRING_STRREPL, f, f2, f3); } - | SPREFIXOF_TOK LPAREN formula[f] COMMA formula[f2] RPAREN + | STRING_PREFIXOF_TOK LPAREN formula[f] COMMA formula[f2] RPAREN { f = MK_EXPR(CVC4::kind::STRING_PREFIX, f, f2); } - | SSUFFIXOF_TOK LPAREN formula[f] COMMA formula[f2] RPAREN + | STRING_SUFFIXOF_TOK LPAREN formula[f] COMMA formula[f2] RPAREN { f = MK_EXPR(CVC4::kind::STRING_SUFFIX, f, f2); } - | STOINTEGER_TOK LPAREN formula[f] RPAREN + | STRING_STOI_TOK LPAREN formula[f] RPAREN { f = MK_EXPR(CVC4::kind::STRING_STOI, f); } - | STOSTRING_TOK LPAREN formula[f] RPAREN + | STRING_ITOS_TOK LPAREN formula[f] RPAREN { f = MK_EXPR(CVC4::kind::STRING_ITOS, f); } - | STORE_TOK LPAREN formula[f] RPAREN - { f = MK_EXPR(CVC4::kind::STRING_TO_REGEXP, f); } + | STRING_U16TOS_TOK LPAREN formula[f] RPAREN + { f = MK_EXPR(CVC4::kind::STRING_U16TOS, f); } + | STRING_STOU16_TOK LPAREN formula[f] RPAREN + { f = MK_EXPR(CVC4::kind::STRING_STOU16, f); } + | STRING_U32TOS_TOK LPAREN formula[f] RPAREN + { f = MK_EXPR(CVC4::kind::STRING_U32TOS, f); } + | STRING_STOU32_TOK LPAREN formula[f] RPAREN + { f = MK_EXPR(CVC4::kind::STRING_STOU32, f); } /* string literal */ | str[s] @@ -2018,6 +2044,11 @@ simpleTerm[CVC4::Expr& f] } } + /* set cardinality literal */ + | BAR BAR formula[f] { args.push_back(f); } BAR BAR + { f = MK_EXPR(kind::CARD, args[0]); + } + /* array literals */ | ARRAY_TOK /* { PARSER_STATE->pushScope(); } */ LPAREN restrictedType[t, CHECK_DECLARED] OF_TOK restrictedType[t2, CHECK_DECLARED] diff --git a/src/parser/cvc/cvc_input.cpp b/src/parser/cvc/cvc_input.cpp index 2370109ef..9e00567fe 100644 --- a/src/parser/cvc/cvc_input.cpp +++ b/src/parser/cvc/cvc_input.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file cvc_input.cpp ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Christopher L. Conway, 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 file-specific comments here ]]. ** diff --git a/src/parser/cvc/cvc_input.h b/src/parser/cvc/cvc_input.h index a88fd7223..aff3698fc 100644 --- a/src/parser/cvc/cvc_input.h +++ b/src/parser/cvc/cvc_input.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cvc_input.h ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): Dejan Jovanovic + ** Top contributors (to current version): + ** Christopher L. Conway, 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 file-specific comments here ]]. ** diff --git a/src/parser/input.cpp b/src/parser/input.cpp index 896e8bc74..5fadbcc54 100644 --- a/src/parser/input.cpp +++ b/src/parser/input.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file input.cpp ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): Dejan Jovanovic + ** Top contributors (to current version): + ** Christopher L. Conway, 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 super-class for input language parsers. ** diff --git a/src/parser/input.h b/src/parser/input.h index 4ff37409c..7dce369c5 100644 --- a/src/parser/input.h +++ b/src/parser/input.h @@ -1,13 +1,13 @@ /********************* */ /*! \file input.h ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): Francois Bobot + ** Top contributors (to current version): + ** Christopher L. Conway, 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 for parser inputs. ** diff --git a/src/parser/memory_mapped_input_buffer.cpp b/src/parser/memory_mapped_input_buffer.cpp index 7be1c9aba..c9515aa92 100644 --- a/src/parser/memory_mapped_input_buffer.cpp +++ b/src/parser/memory_mapped_input_buffer.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file memory_mapped_input_buffer.cpp ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): Tim King + ** Top contributors (to current version): + ** Christopher L. Conway, 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 file-specific comments here ]]. ** diff --git a/src/parser/memory_mapped_input_buffer.h b/src/parser/memory_mapped_input_buffer.h index bacd9cb0f..2a34d1197 100644 --- a/src/parser/memory_mapped_input_buffer.h +++ b/src/parser/memory_mapped_input_buffer.h @@ -1,13 +1,13 @@ /********************* */ /*! \file memory_mapped_input_buffer.h ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Christopher L. Conway, 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 ANTLR input buffer from a memory-mapped file. ** diff --git a/src/parser/parser.cpp b/src/parser/parser.cpp index b9531e8d9..712494805 100644 --- a/src/parser/parser.cpp +++ b/src/parser/parser.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file parser.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Christopher L. Conway - ** Minor contributors (to current version): Tim King, Dejan Jovanovic, Kshitij Bansal, Andrew Reynolds + ** Top contributors (to current version): + ** Morgan Deters, Christopher L. Conway, 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 Parser state implementation. ** diff --git a/src/parser/parser.h b/src/parser/parser.h index 9c2c7f7be..54f25ae74 100644 --- a/src/parser/parser.h +++ b/src/parser/parser.h @@ -1,13 +1,13 @@ /********************* */ /*! \file parser.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Christopher L. Conway - ** Minor contributors (to current version): Dejan Jovanovic, Kshitij Bansal, Francois Bobot, Andrew Reynolds + ** Top contributors (to current version): + ** Morgan Deters, Christopher L. Conway, 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 collection of state for use by parser implementations. ** diff --git a/src/parser/parser_builder.cpp b/src/parser/parser_builder.cpp index e095d208b..8580d5672 100644 --- a/src/parser/parser_builder.cpp +++ b/src/parser/parser_builder.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file parser_builder.cpp ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): Dejan Jovanovic, Francois Bobot + ** Top contributors (to current version): + ** Christopher L. Conway, 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 builder for parsers. ** diff --git a/src/parser/parser_builder.h b/src/parser/parser_builder.h index fe652286b..68dd684c1 100644 --- a/src/parser/parser_builder.h +++ b/src/parser/parser_builder.h @@ -1,13 +1,13 @@ /********************* */ /*! \file parser_builder.h ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Christopher L. Conway, 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 builder for parsers. ** diff --git a/src/parser/parser_exception.h b/src/parser/parser_exception.h index de47767c9..d83aab299 100644 --- a/src/parser/parser_exception.h +++ b/src/parser/parser_exception.h @@ -1,13 +1,13 @@ /********************* */ /*! \file parser_exception.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Christopher L. Conway - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Morgan Deters, Christopher L. Conway, 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 Exception class for parse errors. ** diff --git a/src/parser/smt1/Smt1.g b/src/parser/smt1/Smt1.g index a8e797470..824e6db8b 100644 --- a/src/parser/smt1/Smt1.g +++ b/src/parser/smt1/Smt1.g @@ -1,13 +1,13 @@ /* ******************* */ /*! \file Smt1.g ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Dejan Jovanovic, Christopher L. Conway - ** Minor contributors (to current version): Andrew Reynolds, Tim King + ** Top contributors (to current version): + ** Christopher L. Conway, 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 Parser for SMT-LIB input language. ** diff --git a/src/parser/smt1/smt1.cpp b/src/parser/smt1/smt1.cpp index a2abee2e7..50f62009a 100644 --- a/src/parser/smt1/smt1.cpp +++ b/src/parser/smt1/smt1.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file smt1.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Christopher L. Conway - ** Minor contributors (to current version): Tim King, Tianyi Liang, Dejan Jovanovic, Clark Barrett + ** Top contributors (to current version): + ** Morgan Deters, Christopher L. Conway, 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 ** ** Definitions of SMT-LIB (v1) constants. **/ diff --git a/src/parser/smt1/smt1.h b/src/parser/smt1/smt1.h index 20ba0401c..45de222ac 100644 --- a/src/parser/smt1/smt1.h +++ b/src/parser/smt1/smt1.h @@ -1,13 +1,13 @@ /********************* */ /*! \file smt1.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Christopher L. Conway - ** Minor contributors (to current version): Andrew Reynolds, Clark Barrett, Tianyi Liang + ** Top contributors (to current version): + ** Christopher L. Conway, 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 ** ** Definitions of SMT constants. **/ diff --git a/src/parser/smt1/smt1_input.cpp b/src/parser/smt1/smt1_input.cpp index 8a8aa577e..69801e8b4 100644 --- a/src/parser/smt1/smt1_input.cpp +++ b/src/parser/smt1/smt1_input.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file smt1_input.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Christopher L. Conway - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Christopher L. Conway, 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 file-specific comments here ]]. ** diff --git a/src/parser/smt1/smt1_input.h b/src/parser/smt1/smt1_input.h index de21036c0..0e719f519 100644 --- a/src/parser/smt1/smt1_input.h +++ b/src/parser/smt1/smt1_input.h @@ -1,13 +1,13 @@ /********************* */ /*! \file smt1_input.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Christopher L. Conway - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Christopher L. Conway, 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 file-specific comments here ]]. ** diff --git a/src/parser/smt2/Smt2.g b/src/parser/smt2/Smt2.g index fb3b5ec5e..38163c579 100644 --- a/src/parser/smt2/Smt2.g +++ b/src/parser/smt2/Smt2.g @@ -1,13 +1,13 @@ /* ******************* */ /*! \file Smt2.g ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): Dejan Jovanovic, Kshitij Bansal, Tianyi Liang, Francois Bobot, Andrew Reynolds + ** Top contributors (to current version): + ** Morgan Deters, Andrew Reynolds, 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 Parser for SMT-LIB v2 input language ** @@ -765,9 +765,7 @@ sygusCommand returns [CVC4::Command* cmd = NULL] Command* c = new SetUserAttributeCommand("sygus", sygusVar); c->setMuted(true); PARSER_STATE->preemptCommand(c); - c = new AssertCommand(body); - PARSER_STATE->preemptCommand(c); - $cmd = new CheckSatCommand(); + $cmd = new CheckSynthCommand(body); } | c = command { $cmd = c; } // /* error handling */ @@ -1302,6 +1300,12 @@ extendedCommand[CVC4::Command*& cmd] | SIMPLIFY_TOK { PARSER_STATE->checkThatLogicIsSet(); } term[e,e2] { cmd = new SimplifyCommand(e); } + | GET_QE_TOK { PARSER_STATE->checkThatLogicIsSet(); } + term[e,e2] + { cmd = new GetQuantifierEliminationCommand(e, true); } + | GET_QE_DISJUNCT_TOK { PARSER_STATE->checkThatLogicIsSet(); } + term[e,e2] + { cmd = new GetQuantifierEliminationCommand(e, false); } ; @@ -2562,6 +2566,8 @@ DECLARE_CONST_TOK : 'declare-const'; DEFINE_CONST_TOK : 'define-const'; SIMPLIFY_TOK : 'simplify'; INCLUDE_TOK : 'include'; +GET_QE_TOK : 'get-qe'; +GET_QE_DISJUNCT_TOK : 'get-qe-disjunct'; // SyGuS commands SYNTH_FUN_TOK : 'synth-fun'; diff --git a/src/parser/smt2/smt2.cpp b/src/parser/smt2/smt2.cpp index ff22dd9c7..463adcb54 100644 --- a/src/parser/smt2/smt2.cpp +++ b/src/parser/smt2/smt2.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file smt2.cpp ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: Kshitij Bansal, Morgan Deters - ** Minor contributors (to current version): Andrew Reynolds, Clark Barrett, Tianyi Liang + ** Top contributors (to current version): + ** Andrew Reynolds, Kshitij Bansal, 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 Definitions of SMT2 constants. ** @@ -230,6 +230,7 @@ void Smt2::addTheory(Theory theory) { addOperator(kind::PRODUCT, "product"); addOperator(kind::SINGLETON, "singleton"); addOperator(kind::INSERT, "insert"); + addOperator(kind::CARD, "card"); break; case THEORY_DATATYPES: diff --git a/src/parser/smt2/smt2.h b/src/parser/smt2/smt2.h index 7cf92f008..1ae2c9dd7 100644 --- a/src/parser/smt2/smt2.h +++ b/src/parser/smt2/smt2.h @@ -1,13 +1,13 @@ /********************* */ /*! \file smt2.h ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): Tianyi Liang, Kshitij Bansal + ** Top contributors (to current version): + ** Morgan Deters, Andrew Reynolds, 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 Definitions of SMT2 constants. ** diff --git a/src/parser/smt2/smt2_input.cpp b/src/parser/smt2/smt2_input.cpp index cea6db278..7aa4c3441 100644 --- a/src/parser/smt2/smt2_input.cpp +++ b/src/parser/smt2/smt2_input.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file smt2_input.cpp ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Christopher L. Conway, 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 file-specific comments here ]]. ** diff --git a/src/parser/smt2/smt2_input.h b/src/parser/smt2/smt2_input.h index 9a07ddc08..0ed88393f 100644 --- a/src/parser/smt2/smt2_input.h +++ b/src/parser/smt2/smt2_input.h @@ -1,13 +1,13 @@ /********************* */ /*! \file smt2_input.h ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Christopher L. Conway, 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 file-specific comments here ]]. ** diff --git a/src/parser/smt2/sygus_input.cpp b/src/parser/smt2/sygus_input.cpp index e4f36b3df..5b20e0a9a 100644 --- a/src/parser/smt2/sygus_input.cpp +++ b/src/parser/smt2/sygus_input.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file sygus_input.cpp ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: Morgan Deters - ** 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 file-specific comments here ]]. ** diff --git a/src/parser/smt2/sygus_input.h b/src/parser/smt2/sygus_input.h index 1f0078076..50bc973e9 100644 --- a/src/parser/smt2/sygus_input.h +++ b/src/parser/smt2/sygus_input.h @@ -1,13 +1,13 @@ /********************* */ /*! \file sygus_input.h ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: Morgan Deters - ** 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 file-specific comments here ]]. ** diff --git a/src/parser/tptp/Tptp.g b/src/parser/tptp/Tptp.g index d57aea376..73dcfa6cb 100644 --- a/src/parser/tptp/Tptp.g +++ b/src/parser/tptp/Tptp.g @@ -1,13 +1,13 @@ /* ******************* */ /*! \file Tptp.g ** \verbatim - ** Original author: Francois Bobot - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Morgan Deters, 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 Parser for TPTP input language. ** diff --git a/src/parser/tptp/tptp.cpp b/src/parser/tptp/tptp.cpp index 9d3bd4b1c..193c27e11 100644 --- a/src/parser/tptp/tptp.cpp +++ b/src/parser/tptp/tptp.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file tptp.cpp ** \verbatim - ** Original author: Francois Bobot - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Francois Bobot, 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 Definitions of TPTP constants. ** diff --git a/src/parser/tptp/tptp.h b/src/parser/tptp/tptp.h index 0937a11bf..06b7fac3c 100644 --- a/src/parser/tptp/tptp.h +++ b/src/parser/tptp/tptp.h @@ -1,13 +1,13 @@ /********************* */ /*! \file tptp.h ** \verbatim - ** Original author: Francois Bobot - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): Andrew Reynolds + ** Top contributors (to current version): + ** Francois Bobot, 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 Definitions of TPTP constants. ** diff --git a/src/parser/tptp/tptp_input.cpp b/src/parser/tptp/tptp_input.cpp index 5a393a58c..42337b42b 100644 --- a/src/parser/tptp/tptp_input.cpp +++ b/src/parser/tptp/tptp_input.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file tptp_input.cpp ** \verbatim - ** Original author: Francois Bobot - ** Major contributors: none - ** Minor contributors (to current version): Morgan Deters + ** Top contributors (to current version): + ** Francois Bobot, 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 file-specific comments here ]]. ** diff --git a/src/parser/tptp/tptp_input.h b/src/parser/tptp/tptp_input.h index 6357beae1..28bf1828a 100644 --- a/src/parser/tptp/tptp_input.h +++ b/src/parser/tptp/tptp_input.h @@ -1,13 +1,13 @@ /********************* */ /*! \file tptp_input.h ** \verbatim - ** Original author: Francois Bobot - ** Major contributors: none - ** Minor contributors (to current version): Morgan Deters + ** Top contributors (to current version): + ** Francois Bobot, 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 file-specific comments here ]]. ** diff --git a/src/printer/ast/ast_printer.cpp b/src/printer/ast/ast_printer.cpp index d05309ef7..e15d8766f 100644 --- a/src/printer/ast/ast_printer.cpp +++ b/src/printer/ast/ast_printer.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file ast_printer.cpp ** \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, 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 The pretty-printer interface for the AST output language ** diff --git a/src/printer/ast/ast_printer.h b/src/printer/ast/ast_printer.h index ea425a16f..ef123d1d4 100644 --- a/src/printer/ast/ast_printer.h +++ b/src/printer/ast/ast_printer.h @@ -1,13 +1,13 @@ /********************* */ /*! \file ast_printer.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 The pretty-printer interface for the AST output language ** diff --git a/src/printer/cvc/cvc_printer.cpp b/src/printer/cvc/cvc_printer.cpp index 9de790d7b..8bd222ca7 100644 --- a/src/printer/cvc/cvc_printer.cpp +++ b/src/printer/cvc/cvc_printer.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file cvc_printer.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Dejan Jovanovic - ** Minor contributors (to current version): Francois Bobot, Liana Hadarean, Clark Barrett, Tim King, 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 The pretty-printer interface for the CVC output language ** @@ -809,6 +809,13 @@ void CvcPrinter::toStream(std::ostream& out, TNode n, int depth, bool types, boo return; break; } + case kind::CARD: { + out << "||"; + toStream(out, n[0], depth, types, false); + out << "||"; + return; + break; + } // Quantifiers case kind::FORALL: diff --git a/src/printer/cvc/cvc_printer.h b/src/printer/cvc/cvc_printer.h index 0809696c4..fd250132b 100644 --- a/src/printer/cvc/cvc_printer.h +++ b/src/printer/cvc/cvc_printer.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cvc_printer.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 pretty-printer interface for the CVC output language ** diff --git a/src/printer/dagification_visitor.cpp b/src/printer/dagification_visitor.cpp index 5bb4af436..c52f0ed08 100644 --- a/src/printer/dagification_visitor.cpp +++ b/src/printer/dagification_visitor.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file dagification_visitor.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 Implementation of a dagifier for CVC4 expressions ** diff --git a/src/printer/dagification_visitor.h b/src/printer/dagification_visitor.h index 99fa7db64..c79ec514f 100644 --- a/src/printer/dagification_visitor.h +++ b/src/printer/dagification_visitor.h @@ -1,13 +1,13 @@ /********************* */ /*! \file dagification_visitor.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 A dagifier for CVC4 expressions ** diff --git a/src/printer/printer.cpp b/src/printer/printer.cpp index a2734160f..c715312c1 100644 --- a/src/printer/printer.cpp +++ b/src/printer/printer.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file printer.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Francois Bobot, Andrew Reynolds + ** 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 Base of the pretty-printer interface ** diff --git a/src/printer/printer.h b/src/printer/printer.h index f4cd4635c..a6156ad16 100644 --- a/src/printer/printer.h +++ b/src/printer/printer.h @@ -1,13 +1,13 @@ /********************* */ /*! \file printer.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 Base of the pretty-printer interface ** diff --git a/src/printer/smt1/smt1_printer.cpp b/src/printer/smt1/smt1_printer.cpp index bcd6faa83..7fde0749b 100644 --- a/src/printer/smt1/smt1_printer.cpp +++ b/src/printer/smt1/smt1_printer.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file smt1_printer.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 The pretty-printer interface for the SMT output language ** diff --git a/src/printer/smt1/smt1_printer.h b/src/printer/smt1/smt1_printer.h index b13b894f0..d8101d916 100644 --- a/src/printer/smt1/smt1_printer.h +++ b/src/printer/smt1/smt1_printer.h @@ -1,13 +1,13 @@ /********************* */ /*! \file smt1_printer.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 The pretty-printer interface for the SMT output language ** diff --git a/src/printer/smt2/smt2_printer.cpp b/src/printer/smt2/smt2_printer.cpp index 7c501ffec..9d61e5ef8 100644 --- a/src/printer/smt2/smt2_printer.cpp +++ b/src/printer/smt2/smt2_printer.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file smt2_printer.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Dejan Jovanovic, Tim King, Liana Hadarean, Kshitij Bansal, Tianyi Liang, Francois Bobot, Andrew Reynolds + ** Top contributors (to current version): + ** Morgan Deters, Andrew Reynolds, 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 The pretty-printer interface for the SMT2 output language ** @@ -385,6 +385,8 @@ void Smt2Printer::toStream(std::ostream& out, TNode n, // arrays theory case kind::SELECT: case kind::STORE: + case kind::PARTIAL_SELECT_0: + case kind::PARTIAL_SELECT_1: case kind::ARRAY_TYPE: out << smtKindString(k) << " "; break; // string theory @@ -449,7 +451,7 @@ void Smt2Printer::toStream(std::ostream& out, TNode n, case kind::CARDINALITY_CONSTRAINT: out << "fmf.card "; break; case kind::CARDINALITY_VALUE: out << "fmf.card.val "; break; - + // bv theory case kind::BITVECTOR_CONCAT: out << "concat "; forceBinary = true; break; case kind::BITVECTOR_AND: out << "bvand "; forceBinary = true; break; @@ -736,6 +738,8 @@ static string smtKindString(Kind k) throw() { case kind::SELECT: return "select"; case kind::STORE: return "store"; case kind::ARRAY_TYPE: return "Array"; + case kind::PARTIAL_SELECT_0: return "partial_select_0"; + case kind::PARTIAL_SELECT_1: return "partial_select_1"; // bv theory case kind::BITVECTOR_CONCAT: return "concat"; @@ -981,7 +985,7 @@ void Smt2Printer::toStream(std::ostream& out, const Command* c, static std::string quoteSymbol(TNode n) { -#warning "check the old implementation. It seems off." + // #warning "check the old implementation. It seems off." std::stringstream ss; ss << language::SetLanguage(language::output::LANG_SMTLIB_V2_5); return CVC4::quoteSymbol(ss.str()); diff --git a/src/printer/smt2/smt2_printer.h b/src/printer/smt2/smt2_printer.h index a57c4f8dc..0354a5738 100644 --- a/src/printer/smt2/smt2_printer.h +++ b/src/printer/smt2/smt2_printer.h @@ -1,13 +1,13 @@ /********************* */ /*! \file smt2_printer.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** 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 The pretty-printer interface for the SMT2 output language ** diff --git a/src/printer/tptp/tptp_printer.cpp b/src/printer/tptp/tptp_printer.cpp index 46ae47ba4..1be98ffad 100644 --- a/src/printer/tptp/tptp_printer.cpp +++ b/src/printer/tptp/tptp_printer.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file tptp_printer.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 The pretty-printer interface for the TPTP output language ** diff --git a/src/printer/tptp/tptp_printer.h b/src/printer/tptp/tptp_printer.h index 90a682bcc..aac69d046 100644 --- a/src/printer/tptp/tptp_printer.h +++ b/src/printer/tptp/tptp_printer.h @@ -1,13 +1,13 @@ /********************* */ /*! \file tptp_printer.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 The pretty-printer interface for the TPTP output language ** diff --git a/src/proof/arith_proof.cpp b/src/proof/arith_proof.cpp new file mode 100644 index 000000000..a1287b667 --- /dev/null +++ b/src/proof/arith_proof.cpp @@ -0,0 +1,833 @@ +/********************* */ +/*! \file arith_proof.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 "proof/theory_proof.h" +#include "proof/proof_manager.h" +#include "proof/arith_proof.h" +#include "theory/arith/theory_arith.h" +#include <stack> + +namespace CVC4 { + +inline static Node eqNode(TNode n1, TNode n2) { + return NodeManager::currentNM()->mkNode(n1.getType().isBoolean() ? kind::IFF : kind::EQUAL, n1, n2); +} + +// congrence matching term helper +inline static bool match(TNode n1, TNode n2) { + Debug("pf::arith") << "match " << n1 << " " << n2 << std::endl; + if(ProofManager::currentPM()->hasOp(n1)) { + n1 = ProofManager::currentPM()->lookupOp(n1); + } + if(ProofManager::currentPM()->hasOp(n2)) { + n2 = ProofManager::currentPM()->lookupOp(n2); + } + Debug("pf::arith") << "+ match " << n1 << " " << n2 << std::endl; + if(n1 == n2) { + return true; + } + if(n1.getType().isFunction() && n2.hasOperator()) { + if(ProofManager::currentPM()->hasOp(n2.getOperator())) { + return n1 == ProofManager::currentPM()->lookupOp(n2.getOperator()); + } else { + return n1 == n2.getOperator(); + } + } + if(n2.getType().isFunction() && n1.hasOperator()) { + if(ProofManager::currentPM()->hasOp(n1.getOperator())) { + return n2 == ProofManager::currentPM()->lookupOp(n1.getOperator()); + } else { + return n2 == n1.getOperator(); + } + } + if(n1.hasOperator() && n2.hasOperator() && n1.getOperator() != n2.getOperator()) { + return false; + } + for(size_t i = 0; i < n1.getNumChildren() && i < n2.getNumChildren(); ++i) { + if(n1[i] != n2[i]) { + return false; + } + } + return true; +} + + +void ProofArith::toStream(std::ostream& out) { + Trace("theory-proof-debug") << "; Print Arith proof..." << std::endl; + //AJR : carry this further? + LetMap map; + toStreamLFSC(out, ProofManager::getArithProof(), d_proof, map); +} + +void ProofArith::toStreamLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, const LetMap& map) { + Debug("lfsc-arith") << "Printing arith proof in LFSC : " << std::endl; + pf->debug_print("lfsc-arith"); + Debug("lfsc-arith") << std::endl; + toStreamRecLFSC( out, tp, pf, 0, map ); +} + +Node ProofArith::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, unsigned tb, const LetMap& map) { + Debug("pf::arith") << std::endl << std::endl << "toStreamRecLFSC called. tb = " << tb << " . proof:" << std::endl; + pf->debug_print("pf::arith"); + Debug("pf::arith") << std::endl; + + if(tb == 0) { + Assert(pf->d_id == theory::eq::MERGED_THROUGH_TRANS); + Assert(!pf->d_node.isNull()); + Assert(pf->d_children.size() >= 2); + + int neg = -1; + theory::eq::EqProof subTrans; + subTrans.d_id = theory::eq::MERGED_THROUGH_TRANS; + subTrans.d_node = pf->d_node; + + size_t i = 0; + while (i < pf->d_children.size()) { + // Look for the negative clause, with which we will form a contradiction. + if(!pf->d_children[i]->d_node.isNull() && pf->d_children[i]->d_node.getKind() == kind::NOT) { + Assert(neg < 0); + neg = i; + ++i; + } + + // Handle congruence closures over equalities. + else if (pf->d_children[i]->d_id==theory::eq::MERGED_THROUGH_CONGRUENCE && pf->d_children[i]->d_node.isNull()) { + Debug("pf::arith") << "Handling congruence over equalities" << std::endl; + + // Gather the sequence of consecutive congruence closures. + std::vector<const theory::eq::EqProof *> congruenceClosures; + unsigned count; + Debug("pf::arith") << "Collecting congruence sequence" << std::endl; + for (count = 0; + i + count < pf->d_children.size() && + pf->d_children[i + count]->d_id==theory::eq::MERGED_THROUGH_CONGRUENCE && + pf->d_children[i + count]->d_node.isNull(); + ++count) { + Debug("pf::arith") << "Found a congruence: " << std::endl; + pf->d_children[i+count]->debug_print("pf::arith"); + congruenceClosures.push_back(pf->d_children[i+count]); + } + + Debug("pf::arith") << "Total number of congruences found: " << congruenceClosures.size() << std::endl; + + // Determine if the "target" of the congruence sequence appears right before or right after the sequence. + bool targetAppearsBefore = true; + bool targetAppearsAfter = true; + + if ((i == 0) || (i == 1 && neg == 0)) { + Debug("pf::arith") << "Target does not appear before" << std::endl; + targetAppearsBefore = false; + } + + if ((i + count >= pf->d_children.size()) || + (!pf->d_children[i + count]->d_node.isNull() && + pf->d_children[i + count]->d_node.getKind() == kind::NOT)) { + Debug("pf::arith") << "Target does not appear after" << std::endl; + targetAppearsAfter = false; + } + + // Assert that we have precisely one target clause. + Assert(targetAppearsBefore != targetAppearsAfter); + + // Begin breaking up the congruences and ordering the equalities correctly. + std::vector<theory::eq::EqProof *> orderedEqualities; + + + // Insert target clause first. + if (targetAppearsBefore) { + orderedEqualities.push_back(pf->d_children[i - 1]); + // The target has already been added to subTrans; remove it. + subTrans.d_children.pop_back(); + } else { + orderedEqualities.push_back(pf->d_children[i + count]); + } + + // Start with the congruence closure closest to the target clause, and work our way back/forward. + if (targetAppearsBefore) { + for (unsigned j = 0; j < count; ++j) { + if (pf->d_children[i + j]->d_children[0]->d_id != theory::eq::MERGED_THROUGH_REFLEXIVITY) + orderedEqualities.insert(orderedEqualities.begin(), pf->d_children[i + j]->d_children[0]); + if (pf->d_children[i + j]->d_children[1]->d_id != theory::eq::MERGED_THROUGH_REFLEXIVITY) + orderedEqualities.insert(orderedEqualities.end(), pf->d_children[i + j]->d_children[1]); + } + } else { + for (unsigned j = 0; j < count; ++j) { + if (pf->d_children[i + count - 1 - j]->d_children[0]->d_id != theory::eq::MERGED_THROUGH_REFLEXIVITY) + orderedEqualities.insert(orderedEqualities.begin(), pf->d_children[i + count - 1 - j]->d_children[0]); + if (pf->d_children[i + count - 1 - j]->d_children[1]->d_id != theory::eq::MERGED_THROUGH_REFLEXIVITY) + orderedEqualities.insert(orderedEqualities.end(), pf->d_children[i + count - 1 - j]->d_children[1]); + } + } + + // Copy the result into the main transitivity proof. + subTrans.d_children.insert(subTrans.d_children.end(), orderedEqualities.begin(), orderedEqualities.end()); + + // Increase i to skip over the children that have been processed. + i += count; + if (targetAppearsAfter) { + ++i; + } + } + + // Else, just copy the child proof as is + else { + subTrans.d_children.push_back(pf->d_children[i]); + ++i; + } + } + Assert(neg >= 0); + + Node n1; + std::stringstream ss; + //Assert(subTrans.d_children.size() == pf->d_children.size() - 1); + Debug("pf::arith") << "\nsubtrans has " << subTrans.d_children.size() << " children\n"; + if(pf->d_children.size() > 2) { + n1 = toStreamRecLFSC(ss, tp, &subTrans, 1, map); + } else { + n1 = toStreamRecLFSC(ss, tp, subTrans.d_children[0], 1, map); + Debug("pf::arith") << "\nsubTrans unique child " << subTrans.d_children[0]->d_id << " was proven\ngot: " << n1 << std::endl; + } + + Node n2 = pf->d_children[neg]->d_node; + Assert(n2.getKind() == kind::NOT); + out << "(clausify_false (contra _ "; + Debug("pf::arith") << "\nhave proven: " << n1 << std::endl; + Debug("pf::arith") << "n2 is " << n2[0] << std::endl; + + if (n2[0].getNumChildren() > 0) { Debug("pf::arith") << "\nn2[0]: " << n2[0][0] << std::endl; } + if (n1.getNumChildren() > 1) { Debug("pf::arith") << "n1[1]: " << n1[1] << std::endl; } + + if(n2[0].getKind() == kind::APPLY_UF) { + out << "(trans _ _ _ _ "; + out << "(symm _ _ _ "; + out << ss.str(); + out << ") (pred_eq_f _ " << ProofManager::getLitName(n2[0]) << ")) t_t_neq_f))" << std::endl; + } else { + Assert((n1[0] == n2[0][0] && n1[1] == n2[0][1]) || (n1[1] == n2[0][0] && n1[0] == n2[0][1])); + if(n1[1] == n2[0][0]) { + out << "(symm _ _ _ " << ss.str() << ")"; + } else { + out << ss.str(); + } + out << " " << ProofManager::getLitName(n2[0]) << "))" << std::endl; + } + return Node(); + } + + switch(pf->d_id) { + case theory::eq::MERGED_THROUGH_CONGRUENCE: { + Debug("pf::arith") << "\nok, looking at congruence:\n"; + pf->debug_print("pf::arith"); + std::stack<const theory::eq::EqProof*> stk; + for(const theory::eq::EqProof* pf2 = pf; pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE; pf2 = pf2->d_children[0]) { + Assert(!pf2->d_node.isNull()); + Assert(pf2->d_node.getKind() == kind::PARTIAL_APPLY_UF || pf2->d_node.getKind() == kind::BUILTIN || pf2->d_node.getKind() == kind::APPLY_UF || pf2->d_node.getKind() == kind::SELECT || pf2->d_node.getKind() == kind::STORE); + Assert(pf2->d_children.size() == 2); + out << "(cong _ _ _ _ _ _ "; + stk.push(pf2); + } + Assert(stk.top()->d_children[0]->d_id != theory::eq::MERGED_THROUGH_CONGRUENCE); + NodeBuilder<> b1(kind::PARTIAL_APPLY_UF), b2(kind::PARTIAL_APPLY_UF); + const theory::eq::EqProof* pf2 = stk.top(); + stk.pop(); + Assert(pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE); + Node n1 = toStreamRecLFSC(out, tp, pf2->d_children[0], tb + 1, map); + out << " "; + std::stringstream ss; + Node n2 = toStreamRecLFSC(ss, tp, pf2->d_children[1], tb + 1, map); + Debug("pf::arith") << "\nok, in FIRST cong[" << stk.size() << "]" << "\n"; + pf2->debug_print("pf::arith"); + Debug("pf::arith") << "looking at " << pf2->d_node << "\n"; + Debug("pf::arith") << " " << n1 << "\n"; + Debug("pf::arith") << " " << n2 << "\n"; + int side = 0; + if(match(pf2->d_node, n1[0])) { + //if(tb == 1) { + Debug("pf::arith") << "SIDE IS 0\n"; + //} + side = 0; + } else { + //if(tb == 1) { + Debug("pf::arith") << "SIDE IS 1\n"; + //} + if(!match(pf2->d_node, n1[1])) { + Debug("pf::arith") << "IN BAD CASE, our first subproof is\n"; + pf2->d_children[0]->debug_print("pf::arith"); + } + Assert(match(pf2->d_node, n1[1])); + side = 1; + } + if(n1[side].getKind() == kind::APPLY_UF || n1[side].getKind() == kind::PARTIAL_APPLY_UF || n1[side].getKind() == kind::SELECT || n1[side].getKind() == kind::STORE) { + if(n1[side].getKind() == kind::APPLY_UF || n1[side].getKind() == kind::PARTIAL_APPLY_UF) { + b1 << n1[side].getOperator(); + } else { + b1 << ProofManager::currentPM()->mkOp(n1[side].getOperator()); + } + b1.append(n1[side].begin(), n1[side].end()); + } else { + b1 << n1[side]; + } + if(n1[1-side].getKind() == kind::PARTIAL_APPLY_UF || n1[1-side].getKind() == kind::APPLY_UF || n1[side].getKind() == kind::SELECT || n1[side].getKind() == kind::STORE) { + if(n1[1-side].getKind() == kind::PARTIAL_APPLY_UF || n1[1-side].getKind() == kind::APPLY_UF) { + b2 << n1[1-side].getOperator(); + } else { + b2 << ProofManager::currentPM()->mkOp(n1[1-side].getOperator()); + } + b2.append(n1[1-side].begin(), n1[1-side].end()); + } else { + b2 << n1[1-side]; + } + Debug("pf::arith") << "pf2->d_node " << pf2->d_node << std::endl; + Debug("pf::arith") << "b1.getNumChildren() " << b1.getNumChildren() << std::endl; + Debug("pf::arith") << "n1 " << n1 << std::endl; + Debug("pf::arith") << "n2 " << n2 << std::endl; + Debug("pf::arith") << "side " << side << std::endl; + if(pf2->d_node[b1.getNumChildren() - (pf2->d_node.getMetaKind() == kind::metakind::PARAMETERIZED ? 0 : 1)] == n2[side]) { + b1 << n2[side]; + b2 << n2[1-side]; + out << ss.str(); + } else { + Assert(pf2->d_node[b1.getNumChildren() - (pf2->d_node.getMetaKind() == kind::metakind::PARAMETERIZED ? 0 : 1)] == n2[1-side]); + b1 << n2[1-side]; + b2 << n2[side]; + out << "(symm _ _ _ " << ss.str() << ")"; + } + out << ")"; + while(!stk.empty()) { + if(tb == 1) { + Debug("pf::arith") << "\nMORE TO DO\n"; + } + pf2 = stk.top(); + stk.pop(); + Assert(pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE); + out << " "; + ss.str(""); + n2 = toStreamRecLFSC(ss, tp, pf2->d_children[1], tb + 1, map); + Debug("pf::arith") << "\nok, in cong[" << stk.size() << "]" << "\n"; + Debug("pf::arith") << "looking at " << pf2->d_node << "\n"; + Debug("pf::arith") << " " << n1 << "\n"; + Debug("pf::arith") << " " << n2 << "\n"; + Debug("pf::arith") << " " << b1 << "\n"; + Debug("pf::arith") << " " << b2 << "\n"; + if(pf2->d_node[b1.getNumChildren()] == n2[side]) { + b1 << n2[side]; + b2 << n2[1-side]; + out << ss.str(); + } else { + Assert(pf2->d_node[b1.getNumChildren()] == n2[1-side]); + b1 << n2[1-side]; + b2 << n2[side]; + out << "(symm _ _ _ " << ss.str() << ")"; + } + out << ")"; + } + n1 = b1; + n2 = b2; + Debug("pf::arith") << "at end assert, got " << pf2->d_node << " and " << n1 << std::endl; + if(pf2->d_node.getKind() == kind::PARTIAL_APPLY_UF) { + Assert(n1 == pf2->d_node); + } + if(n1.getOperator().getType().getNumChildren() == n1.getNumChildren() + 1) { + if(ProofManager::currentPM()->hasOp(n1.getOperator())) { + b1.clear(ProofManager::currentPM()->lookupOp(n2.getOperator()).getConst<Kind>()); + } else { + b1.clear(kind::APPLY_UF); + b1 << n1.getOperator(); + } + b1.append(n1.begin(), n1.end()); + n1 = b1; + Debug("pf::arith") << "at[2] end assert, got " << pf2->d_node << " and " << n1 << std::endl; + if(pf2->d_node.getKind() == kind::APPLY_UF) { + Assert(n1 == pf2->d_node); + } + } + if(n2.getOperator().getType().getNumChildren() == n2.getNumChildren() + 1) { + if(ProofManager::currentPM()->hasOp(n2.getOperator())) { + b2.clear(ProofManager::currentPM()->lookupOp(n2.getOperator()).getConst<Kind>()); + } else { + b2.clear(kind::APPLY_UF); + b2 << n2.getOperator(); + } + b2.append(n2.begin(), n2.end()); + n2 = b2; + } + Node n = (side == 0 ? eqNode(n1, n2) : eqNode(n2, n1)); + if(tb == 1) { + Debug("pf::arith") << "\ncong proved: " << n << "\n"; + } + return n; + } + + case theory::eq::MERGED_THROUGH_REFLEXIVITY: + Assert(!pf->d_node.isNull()); + Assert(pf->d_children.empty()); + out << "(refl _ "; + tp->printTerm(NodeManager::currentNM()->toExpr(pf->d_node), out, map); + out << ")"; + return eqNode(pf->d_node, pf->d_node); + + case theory::eq::MERGED_THROUGH_EQUALITY: + Assert(!pf->d_node.isNull()); + Assert(pf->d_children.empty()); + out << ProofManager::getLitName(pf->d_node.negate()); + return pf->d_node; + + case theory::eq::MERGED_THROUGH_TRANS: { + Assert(!pf->d_node.isNull()); + Assert(pf->d_children.size() >= 2); + std::stringstream ss; + Debug("pf::arith") << "\ndoing trans proof[[\n"; + pf->debug_print("pf::arith"); + Debug("pf::arith") << "\n"; + Node n1 = toStreamRecLFSC(ss, tp, pf->d_children[0], tb + 1, map); + Debug("pf::arith") << "\ndoing trans proof, got n1 " << n1 << "\n"; + if(tb == 1) { + Debug("pf::arith") << "\ntrans proof[0], got n1 " << n1 << "\n"; + } + + bool identicalEqualities = false; + bool evenLengthSequence; + Node nodeAfterEqualitySequence; + + std::map<size_t, Node> childToStream; + + for(size_t i = 1; i < pf->d_children.size(); ++i) { + std::stringstream ss1(ss.str()), ss2; + ss.str(""); + + // It is possible that we've already converted the i'th child to stream. If so, + // use previously stored result. Otherwise, convert and store. + Node n2; + if (childToStream.find(i) != childToStream.end()) + n2 = childToStream[i]; + else { + n2 = toStreamRecLFSC(ss2, tp, pf->d_children[i], tb + 1, map); + childToStream[i] = n2; + } + + // The following branch is dedicated to handling sequences of identical equalities, + // i.e. trans[ a=b, a=b, a=b ]. + // + // There are two cases: + // 1. The number of equalities is odd. Then, the sequence can be collapsed to just one equality, + // i.e. a=b. + // 2. The number of equalities is even. Now, we have two options: a=a or b=b. To determine this, + // we look at the node after the equality sequence. If it needs a, we go for a=a; and if it needs + // b, we go for b=b. If there is no following node, we look at the goal of the transitivity proof, + // and use it to determine which option we need. + if(n2.getKind() == kind::EQUAL || n2.getKind() == kind::IFF) { + if (((n1[0] == n2[0]) && (n1[1] == n2[1])) || ((n1[0] == n2[1]) && (n1[1] == n2[0]))) { + // We are in a sequence of identical equalities + + Debug("pf::arith") << "Detected identical equalities: " << std::endl << "\t" << n1 << std::endl; + + if (!identicalEqualities) { + // The sequence of identical equalities has started just now + identicalEqualities = true; + + Debug("pf::arith") << "The sequence is just beginning. Determining length..." << std::endl; + + // Determine whether the length of this sequence is odd or even. + evenLengthSequence = true; + bool sequenceOver = false; + size_t j = i + 1; + + while (j < pf->d_children.size() && !sequenceOver) { + std::stringstream dontCare; + nodeAfterEqualitySequence = toStreamRecLFSC(dontCare, tp, pf->d_children[j], tb + 1, map ); + + if (((nodeAfterEqualitySequence[0] == n1[0]) && (nodeAfterEqualitySequence[1] == n1[1])) || + ((nodeAfterEqualitySequence[0] == n1[1]) && (nodeAfterEqualitySequence[1] == n1[0]))) { + evenLengthSequence = !evenLengthSequence; + } else { + sequenceOver = true; + } + + ++j; + } + + if (evenLengthSequence) { + // If the length is even, we need to apply transitivity for the "correct" hand of the equality. + + Debug("pf::arith") << "Equality sequence of even length" << std::endl; + Debug("pf::arith") << "n1 is: " << n1 << std::endl; + Debug("pf::arith") << "n2 is: " << n2 << std::endl; + Debug("pf::arith") << "pf-d_node is: " << pf->d_node << std::endl; + Debug("pf::arith") << "Next node is: " << nodeAfterEqualitySequence << std::endl; + + ss << "(trans _ _ _ _ "; + + // If the sequence is at the very end of the transitivity proof, use pf->d_node to guide us. + if (!sequenceOver) { + if (match(n1[0], pf->d_node[0])) { + n1 = eqNode(n1[0], n1[0]); + ss << ss1.str() << " (symm _ _ _ " << ss1.str() << ")"; + } else if (match(n1[1], pf->d_node[1])) { + n1 = eqNode(n1[1], n1[1]); + ss << " (symm _ _ _ " << ss1.str() << ")" << ss1.str(); + } else { + Debug("pf::arith") << "Error: identical equalities over, but hands don't match what we're proving." + << std::endl; + Assert(false); + } + } else { + // We have a "next node". Use it to guide us. + + Assert(nodeAfterEqualitySequence.getKind() == kind::EQUAL || + nodeAfterEqualitySequence.getKind() == kind::IFF); + + if ((n1[0] == nodeAfterEqualitySequence[0]) || (n1[0] == nodeAfterEqualitySequence[1])) { + + // Eliminate n1[1] + ss << ss1.str() << " (symm _ _ _ " << ss1.str() << ")"; + n1 = eqNode(n1[0], n1[0]); + + } else if ((n1[1] == nodeAfterEqualitySequence[0]) || (n1[1] == nodeAfterEqualitySequence[1])) { + + // Eliminate n1[0] + ss << " (symm _ _ _ " << ss1.str() << ")" << ss1.str(); + n1 = eqNode(n1[1], n1[1]); + + } else { + Debug("pf::arith") << "Error: even length sequence, but I don't know which hand to keep!" << std::endl; + Assert(false); + } + } + + ss << ")"; + + } else { + Debug("pf::arith") << "Equality sequence length is odd!" << std::endl; + ss.str(ss1.str()); + } + + Debug("pf::arith") << "Have proven: " << n1 << std::endl; + } else { + ss.str(ss1.str()); + } + + // Ignore the redundancy. + continue; + } + } + + if (identicalEqualities) { + // We were in a sequence of identical equalities, but it has now ended. Resume normal operation. + identicalEqualities = false; + } + + Debug("pf::arith") << "\ndoing trans proof, got n2 " << n2 << "\n"; + if(tb == 1) { + Debug("pf::arith") << "\ntrans proof[" << i << "], got n2 " << n2 << "\n"; + Debug("pf::arith") << (n2.getKind() == kind::EQUAL || n2.getKind() == kind::IFF) << "\n"; + + if ((n1.getNumChildren() >= 2) && (n2.getNumChildren() >= 2)) { + Debug("pf::arith") << n1[0].getId() << " " << n1[1].getId() << " / " << n2[0].getId() << " " << n2[1].getId() << "\n"; + Debug("pf::arith") << n1[0].getId() << " " << n1[0] << "\n"; + Debug("pf::arith") << n1[1].getId() << " " << n1[1] << "\n"; + Debug("pf::arith") << n2[0].getId() << " " << n2[0] << "\n"; + Debug("pf::arith") << n2[1].getId() << " " << n2[1] << "\n"; + Debug("pf::arith") << (n1[0] == n2[0]) << "\n"; + Debug("pf::arith") << (n1[1] == n2[1]) << "\n"; + Debug("pf::arith") << (n1[0] == n2[1]) << "\n"; + Debug("pf::arith") << (n1[1] == n2[0]) << "\n"; + } + } + ss << "(trans _ _ _ _ "; + + if((n2.getKind() == kind::EQUAL || n2.getKind() == kind::IFF) && + (n1.getKind() == kind::EQUAL || n1.getKind() == kind::IFF)) + // Both elements of the transitivity rule are equalities/iffs + { + if(n1[0] == n2[0]) { + if(tb == 1) { Debug("pf::arith") << "case 1\n"; } + n1 = eqNode(n1[1], n2[1]); + ss << "(symm _ _ _ " << ss1.str() << ") " << ss2.str(); + } else if(n1[1] == n2[1]) { + if(tb == 1) { Debug("pf::arith") << "case 2\n"; } + n1 = eqNode(n1[0], n2[0]); + ss << ss1.str() << " (symm _ _ _ " << ss2.str() << ")"; + } else if(n1[0] == n2[1]) { + if(tb == 1) { Debug("pf::arith") << "case 3\n"; } + n1 = eqNode(n2[0], n1[1]); + ss << ss2.str() << " " << ss1.str(); + if(tb == 1) { Debug("pf::arith") << "++ proved " << n1 << "\n"; } + } else if(n1[1] == n2[0]) { + if(tb == 1) { Debug("pf::arith") << "case 4\n"; } + n1 = eqNode(n1[0], n2[1]); + ss << ss1.str() << " " << ss2.str(); + } else { + Warning() << "\n\ntrans proof failure at step " << i << "\n\n"; + Warning() << "0 proves " << n1 << "\n"; + Warning() << "1 proves " << n2 << "\n\n"; + pf->debug_print("pf::arith",0); + //toStreamRec(Warning.getStream(), pf, 0); + Warning() << "\n\n"; + Unreachable(); + } + Debug("pf::arith") << "++ trans proof[" << i << "], now have " << n1 << std::endl; + } else if(n1.getKind() == kind::EQUAL || n1.getKind() == kind::IFF) { + // n1 is an equality/iff, but n2 is a predicate + if(n1[0] == n2) { + n1 = n1[1]; + ss << "(symm _ _ _ " << ss1.str() << ") (pred_eq_t _ " << ss2.str() << ")"; + } else if(n1[1] == n2) { + n1 = n1[0]; + ss << ss1.str() << " (pred_eq_t _ " << ss2.str() << ")"; + } else { + Unreachable(); + } + } else if(n2.getKind() == kind::EQUAL || n2.getKind() == kind::IFF) { + // n2 is an equality/iff, but n1 is a predicate + if(n2[0] == n1) { + n1 = n2[1]; + ss << "(symm _ _ _ " << ss2.str() << ") (pred_eq_t _ " << ss1.str() << ")"; + } else if(n2[1] == n1) { + n1 = n2[0]; + ss << ss2.str() << " (pred_eq_t _ " << ss1.str() << ")"; + } else { + Unreachable(); + } + } else { + // Both n1 and n2 are prediacates. Don't know what to do... + Unreachable(); + } + + ss << ")"; + } + out << ss.str(); + Debug("pf::arith") << "\n++ trans proof done, have proven " << n1 << std::endl; + return n1; + } + + default: + Assert(!pf->d_node.isNull()); + Assert(pf->d_children.empty()); + Debug("pf::arith") << "theory proof: " << pf->d_node << " by rule " << int(pf->d_id) << std::endl; + AlwaysAssert(false); + return pf->d_node; + } +} + +ArithProof::ArithProof(theory::arith::TheoryArith* arith, TheoryProofEngine* pe) + : TheoryProof(arith, pe), d_realMode(false) +{} + +void ArithProof::registerTerm(Expr term) { + Debug("pf::arith") << "Arith register term: " << term << ". Kind: " << term.getKind() + << ". Type: " << term.getType() << std::endl; + + if (term.getType().isReal() && !term.getType().isInteger()) { + Debug("pf::arith") << "Entering real mode" << std::endl; + d_realMode = true; + } + + // recursively declare all other terms + for (unsigned i = 0; i < term.getNumChildren(); ++i) { + // could belong to other theories + d_proofEngine->registerTerm(term[i]); + } +} + +void LFSCArithProof::printOwnedTerm(Expr term, std::ostream& os, const LetMap& map) { + Debug("pf::arith") << "Arith print term: " << term << ". Kind: " << term.getKind() + << ". Type: " << term.getType() + << ". Number of children: " << term.getNumChildren() << std::endl; + + // !d_realMode <--> term.getType().isInteger() + + Assert (theory::Theory::theoryOf(term) == theory::THEORY_ARITH); + switch (term.getKind()) { + + case kind::CONST_RATIONAL: { + Assert (term.getNumChildren() == 0); + Assert (term.getType().isInteger() || term.getType().isReal()); + + const Rational& r = term.getConst<Rational>(); + bool neg = (r < 0); + + os << (!d_realMode ? "(a_int " : "(a_real "); + + if (neg) { + os << "(~ "; + } + + if (!d_realMode) { + os << r.abs(); + } else { + os << r.abs().getNumerator(); + os << "/"; + os << r.getDenominator(); + } + + if (neg) { + os << ") "; + } + + os << ") "; + return; + } + + case kind::UMINUS: { + Assert (term.getNumChildren() == 1); + Assert (term.getType().isInteger() || term.getType().isReal()); + os << (!d_realMode ? "(u-_Int " : "(u-_Real "); + d_proofEngine->printBoundTerm(term[0], os, map); + os << ") "; + return; + } + + case kind::PLUS: { + Assert (term.getNumChildren() >= 2); + + std::stringstream paren; + for (unsigned i = 0; i < term.getNumChildren() - 1; ++i) { + os << (!d_realMode ? "(+_Int " : "(+_Real "); + d_proofEngine->printBoundTerm(term[i], os, map); + os << " "; + paren << ") "; + } + + d_proofEngine->printBoundTerm(term[term.getNumChildren() - 1], os, map); + os << paren.str(); + return; + } + + case kind::MINUS: { + Assert (term.getNumChildren() >= 2); + + std::stringstream paren; + for (unsigned i = 0; i < term.getNumChildren() - 1; ++i) { + os << (!d_realMode ? "(-_Int " : "(-_Real "); + d_proofEngine->printBoundTerm(term[i], os, map); + os << " "; + paren << ") "; + } + + d_proofEngine->printBoundTerm(term[term.getNumChildren() - 1], os, map); + os << paren.str(); + return; + } + + case kind::MULT: { + Assert (term.getNumChildren() >= 2); + + std::stringstream paren; + for (unsigned i = 0; i < term.getNumChildren() - 1; ++i) { + os << (!d_realMode ? "(*_Int " : "(*_Real "); + d_proofEngine->printBoundTerm(term[i], os, map); + os << " "; + paren << ") "; + } + + d_proofEngine->printBoundTerm(term[term.getNumChildren() - 1], os, map); + os << paren.str(); + return; + } + + case kind::DIVISION: + case kind::DIVISION_TOTAL: { + Assert (term.getNumChildren() >= 2); + + std::stringstream paren; + for (unsigned i = 0; i < term.getNumChildren() - 1; ++i) { + os << (!d_realMode ? "(/_Int " : "(/_Real "); + d_proofEngine->printBoundTerm(term[i], os, map); + os << " "; + paren << ") "; + } + + d_proofEngine->printBoundTerm(term[term.getNumChildren() - 1], os, map); + os << paren.str(); + return; + } + + case kind::GT: + Assert (term.getNumChildren() == 2); + os << (!d_realMode ? "(>_Int " : "(>_Real "); + d_proofEngine->printBoundTerm(term[0], os, map); + os << " "; + d_proofEngine->printBoundTerm(term[1], os, map); + os << ") "; + return; + + case kind::GEQ: + Assert (term.getNumChildren() == 2); + os << (!d_realMode ? "(>=_Int " : "(>=_Real "); + d_proofEngine->printBoundTerm(term[0], os, map); + os << " "; + d_proofEngine->printBoundTerm(term[1], os, map); + os << ") "; + return; + + case kind::LT: + Assert (term.getNumChildren() == 2); + os << (!d_realMode ? "(<_Int " : "(<_Real "); + d_proofEngine->printBoundTerm(term[0], os, map); + os << " "; + d_proofEngine->printBoundTerm(term[1], os, map); + os << ") "; + return; + + case kind::LEQ: + Assert (term.getNumChildren() == 2); + os << (!d_realMode ? "(<=_Int " : "(<=_Real "); + d_proofEngine->printBoundTerm(term[0], os, map); + os << " "; + d_proofEngine->printBoundTerm(term[1], os, map); + os << ") "; + return; + + default: + Debug("pf::arith") << "Default printing of term: " << term << std::endl; + os << term; + return; + } +} + +void LFSCArithProof::printOwnedSort(Type type, std::ostream& os) { + Debug("pf::arith") << "Arith print sort: " << type << std::endl; + + if (type.isInteger() && d_realMode) { + // If in "real mode", don't use type Int for, e.g., equality. + os << "Real "; + } else { + os << type << " "; + } +} + +void LFSCArithProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren) { + os << " ;; Arith Theory Lemma \n;;"; + for (unsigned i = 0; i < lemma.size(); ++i) { + os << lemma[i] <<" "; + } + os <<"\n"; + //os << " (clausify_false trust)"; + ArithProof::printTheoryLemmaProof( lemma, os, paren ); +} + +void LFSCArithProof::printSortDeclarations(std::ostream& os, std::ostream& paren) { +} + +void LFSCArithProof::printTermDeclarations(std::ostream& os, std::ostream& paren) { +} + +void LFSCArithProof::printDeferredDeclarations(std::ostream& os, std::ostream& paren) { + // Nothing to do here at this point. +} + +} /* CVC4 namespace */ diff --git a/src/proof/arith_proof.h b/src/proof/arith_proof.h new file mode 100644 index 000000000..788e4bd86 --- /dev/null +++ b/src/proof/arith_proof.h @@ -0,0 +1,82 @@ +/********************* */ +/*! \file arith_proof.h + ** \verbatim + ** Top contributors (to current version): + ** Guy Katz, 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 Arith proof + ** + ** Arith proof + **/ + +#include "cvc4_private.h" + +#ifndef __CVC4__ARITH__PROOF_H +#define __CVC4__ARITH__PROOF_H + +#include "expr/expr.h" +#include "proof/proof_manager.h" +#include "proof/theory_proof.h" +#include "theory/uf/equality_engine.h" + +namespace CVC4 { + +//proof object outputted by TheoryArith +class ProofArith : public Proof { +private: + static Node toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, unsigned tb, const LetMap& map); +public: + ProofArith( theory::eq::EqProof * pf ) : d_proof( pf ) {} + //it is simply an equality engine proof + theory::eq::EqProof * d_proof; + void toStream(std::ostream& out); + static void toStreamLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, const LetMap& map); +}; + + +namespace theory { +namespace arith { +class TheoryArith; +} +} + +typedef __gnu_cxx::hash_set<Type, TypeHashFunction > TypeSet; + + +class ArithProof : public TheoryProof { +protected: + // std::map<Expr, std::string> d_constRationalString; // all the variable/function declarations + + // TypeSet d_sorts; // all the uninterpreted sorts in this theory + // ExprSet d_declarations; // all the variable/function declarations + + bool d_realMode; + +public: + ArithProof(theory::arith::TheoryArith* arith, TheoryProofEngine* proofEngine); + + virtual void registerTerm(Expr term); +}; + +class LFSCArithProof : public ArithProof { +public: + LFSCArithProof(theory::arith::TheoryArith* arith, TheoryProofEngine* proofEngine) + : ArithProof(arith, proofEngine) + {} + virtual void printOwnedTerm(Expr term, std::ostream& os, const LetMap& map); + virtual void printOwnedSort(Type type, std::ostream& os); + virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren); + virtual void printSortDeclarations(std::ostream& os, std::ostream& paren); + virtual void printTermDeclarations(std::ostream& os, std::ostream& paren); + virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren); +}; + + +}/* CVC4 namespace */ + +#endif /* __CVC4__ARITH__PROOF_H */ diff --git a/src/proof/array_proof.cpp b/src/proof/array_proof.cpp new file mode 100644 index 000000000..8aba8dce9 --- /dev/null +++ b/src/proof/array_proof.cpp @@ -0,0 +1,1269 @@ +/********************* */ +/*! \file array_proof.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 "proof/theory_proof.h" +#include "proof/proof_manager.h" +#include "proof/array_proof.h" +#include "theory/arrays/theory_arrays.h" +#include <stack> + +namespace CVC4 { + +inline static Node eqNode(TNode n1, TNode n2) { + return NodeManager::currentNM()->mkNode(n1.getType().isBoolean() ? kind::IFF : kind::EQUAL, n1, n2); +} + +// congrence matching term helper +inline static bool match(TNode n1, TNode n2) { + Debug("mgd") << "match " << n1 << " " << n2 << std::endl; + if(ProofManager::currentPM()->hasOp(n1)) { + n1 = ProofManager::currentPM()->lookupOp(n1); + } + if(ProofManager::currentPM()->hasOp(n2)) { + n2 = ProofManager::currentPM()->lookupOp(n2); + } + Debug("mgd") << "+ match " << n1 << " " << n2 << std::endl; + Debug("pf::array") << "+ match: step 1" << std::endl; + if(n1 == n2) { + return true; + } + + if(n1.getType().isFunction() && n2.hasOperator()) { + if(ProofManager::currentPM()->hasOp(n2.getOperator())) { + return n1 == ProofManager::currentPM()->lookupOp(n2.getOperator()); + } else { + return n1 == n2.getOperator(); + } + } + + if(n2.getType().isFunction() && n1.hasOperator()) { + if(ProofManager::currentPM()->hasOp(n1.getOperator())) { + return n2 == ProofManager::currentPM()->lookupOp(n1.getOperator()); + } else { + return n2 == n1.getOperator(); + } + } + + if(n1.hasOperator() && n2.hasOperator() && n1.getOperator() != n2.getOperator()) { + if (!((n1.getKind() == kind::SELECT && n2.getKind() == kind::PARTIAL_SELECT_0) || + (n1.getKind() == kind::SELECT && n2.getKind() == kind::PARTIAL_SELECT_1) || + (n1.getKind() == kind::PARTIAL_SELECT_1 && n2.getKind() == kind::SELECT) || + (n1.getKind() == kind::PARTIAL_SELECT_1 && n2.getKind() == kind::PARTIAL_SELECT_0) || + (n1.getKind() == kind::PARTIAL_SELECT_0 && n2.getKind() == kind::SELECT) || + (n1.getKind() == kind::PARTIAL_SELECT_0 && n2.getKind() == kind::PARTIAL_SELECT_1) + )) { + return false; + } + } + + for(size_t i = 0; i < n1.getNumChildren() && i < n2.getNumChildren(); ++i) { + if(n1[i] != n2[i]) { + return false; + } + } + + return true; +} + +void ProofArray::setRowMergeTag(unsigned tag) { + d_reasonRow = tag; +} + +void ProofArray::setRow1MergeTag(unsigned tag) { + d_reasonRow1 = tag; +} + +void ProofArray::setExtMergeTag(unsigned tag) { + d_reasonExt = tag; +} + +void ProofArray::toStream(std::ostream& out) { + Trace("pf::array") << "; Print Array proof..." << std::endl; + //AJR : carry this further? + LetMap map; + toStreamLFSC(out, ProofManager::getArrayProof(), d_proof, map); + Debug("pf::array") << "; Print Array proof done!" << std::endl; +} + +void ProofArray::toStreamLFSC(std::ostream& out, TheoryProof* tp, theory::eq::EqProof* pf, const LetMap& map) { + Debug("pf::array") << "Printing array proof in LFSC : " << std::endl; + pf->debug_print("pf::array"); + Debug("pf::array") << std::endl; + toStreamRecLFSC( out, tp, pf, 0, map ); + Debug("pf::array") << "Printing array proof in LFSC DONE" << std::endl; +} + +Node ProofArray::toStreamRecLFSC(std::ostream& out, + TheoryProof* tp, + theory::eq::EqProof* pf, + unsigned tb, + const LetMap& map) { + + Debug("pf::array") << std::endl << std::endl << "toStreamRecLFSC called. tb = " << tb << " . proof:" << std::endl; + pf->debug_print("pf::array"); + Debug("pf::array") << std::endl; + + if(tb == 0) { + Assert(pf->d_id == theory::eq::MERGED_THROUGH_TRANS); + Assert(!pf->d_node.isNull()); + Assert(pf->d_children.size() >= 2); + + int neg = -1; + theory::eq::EqProof subTrans; + subTrans.d_id = theory::eq::MERGED_THROUGH_TRANS; + subTrans.d_node = pf->d_node; + + size_t i = 0; + while (i < pf->d_children.size()) { + // Look for the negative clause, with which we will form a contradiction. + if(!pf->d_children[i]->d_node.isNull() && pf->d_children[i]->d_node.getKind() == kind::NOT) { + Assert(neg < 0); + neg = i; + ++i; + } + + // Handle congruence closures over equalities. + else if (pf->d_children[i]->d_id==theory::eq::MERGED_THROUGH_CONGRUENCE && pf->d_children[i]->d_node.isNull()) { + Debug("pf::array") << "Handling congruence over equalities" << std::endl; + + // Gather the sequence of consecutive congruence closures. + std::vector<const theory::eq::EqProof *> congruenceClosures; + unsigned count; + Debug("pf::array") << "Collecting congruence sequence" << std::endl; + for (count = 0; + i + count < pf->d_children.size() && + pf->d_children[i + count]->d_id==theory::eq::MERGED_THROUGH_CONGRUENCE && + pf->d_children[i + count]->d_node.isNull(); + ++count) { + Debug("pf::array") << "Found a congruence: " << std::endl; + pf->d_children[i+count]->debug_print("pf::array"); + congruenceClosures.push_back(pf->d_children[i+count]); + } + + Debug("pf::array") << "Total number of congruences found: " << congruenceClosures.size() << std::endl; + + // Determine if the "target" of the congruence sequence appears right before or right after the sequence. + bool targetAppearsBefore = true; + bool targetAppearsAfter = true; + + if ((i == 0) || (i == 1 && neg == 0)) { + Debug("pf::array") << "Target does not appear before" << std::endl; + targetAppearsBefore = false; + } + + if ((i + count >= pf->d_children.size()) || + (!pf->d_children[i + count]->d_node.isNull() && + pf->d_children[i + count]->d_node.getKind() == kind::NOT)) { + Debug("pf::array") << "Target does not appear after" << std::endl; + targetAppearsAfter = false; + } + + // Assert that we have precisely one target clause. + Assert(targetAppearsBefore != targetAppearsAfter); + + // Begin breaking up the congruences and ordering the equalities correctly. + std::vector<theory::eq::EqProof *> orderedEqualities; + + // Insert target clause first. + if (targetAppearsBefore) { + orderedEqualities.push_back(pf->d_children[i - 1]); + // The target has already been added to subTrans; remove it. + subTrans.d_children.pop_back(); + } else { + orderedEqualities.push_back(pf->d_children[i + count]); + } + + // Start with the congruence closure closest to the target clause, and work our way back/forward. + if (targetAppearsBefore) { + for (unsigned j = 0; j < count; ++j) { + if (pf->d_children[i + j]->d_children[0]->d_id != theory::eq::MERGED_THROUGH_REFLEXIVITY) + orderedEqualities.insert(orderedEqualities.begin(), pf->d_children[i + j]->d_children[0]); + if (pf->d_children[i + j]->d_children[1]->d_id != theory::eq::MERGED_THROUGH_REFLEXIVITY) + orderedEqualities.insert(orderedEqualities.end(), pf->d_children[i + j]->d_children[1]); + } + } else { + for (unsigned j = 0; j < count; ++j) { + if (pf->d_children[i + count - 1 - j]->d_children[0]->d_id != theory::eq::MERGED_THROUGH_REFLEXIVITY) + orderedEqualities.insert(orderedEqualities.begin(), pf->d_children[i + count - 1 - j]->d_children[0]); + if (pf->d_children[i + count - 1 - j]->d_children[1]->d_id != theory::eq::MERGED_THROUGH_REFLEXIVITY) + orderedEqualities.insert(orderedEqualities.end(), pf->d_children[i + count - 1 - j]->d_children[1]); + } + } + + // Copy the result into the main transitivity proof. + subTrans.d_children.insert(subTrans.d_children.end(), orderedEqualities.begin(), orderedEqualities.end()); + + // Increase i to skip over the children that have been processed. + i += count; + if (targetAppearsAfter) { + ++i; + } + } + + // Else, just copy the child proof as is + else { + subTrans.d_children.push_back(pf->d_children[i]); + ++i; + } + } + Assert(neg >= 0); + + Node n1; + std::stringstream ss, ss2; + //Assert(subTrans.d_children.size() == pf->d_children.size() - 1); + Debug("mgdx") << "\nsubtrans has " << subTrans.d_children.size() << " children\n"; + if(pf->d_children.size() > 2) { + n1 = toStreamRecLFSC(ss, tp, &subTrans, 1, map); + } else { + n1 = toStreamRecLFSC(ss, tp, subTrans.d_children[0], 1, map); + Debug("mgdx") << "\nsubTrans unique child " << subTrans.d_children[0]->d_id << " was proven\ngot: " << n1 << std::endl; + } + + Node n2 = pf->d_children[neg]->d_node; + Assert(n2.getKind() == kind::NOT); + Debug("mgdx") << "\nhave proven: " << n1 << std::endl; + Debug("mgdx") << "n2 is " << n2 << std::endl; + Debug("mgdx") << "n2->d_id is " << pf->d_children[neg]->d_id << std::endl; + Debug("mgdx") << "n2[0] is " << n2[0] << std::endl; + + if (n2[0].getNumChildren() > 0) { Debug("mgdx") << "\nn2[0]: " << n2[0][0] << std::endl; } + if (n1.getNumChildren() > 1) { Debug("mgdx") << "n1[1]: " << n1[1] << std::endl; } + + if (pf->d_children[neg]->d_id == d_reasonExt) { + // The negative node was created by an EXT rule; e.g. it is a[k]!=b[k], due to a!=b. + + // (clausify_false (contra _ .gl2 (or_elim_1 _ _ .gl1 FIXME))))))) (\ .glemc6 + + out << "(clausify_false (contra _ "; + out << ss.str(); + + toStreamRecLFSC(ss2, tp, pf->d_children[neg], 1, map); + + out << " "; + out << ss2.str(); + out << "))"; + + } else { + // The negative node is, e.g., a pure equality + out << "(clausify_false (contra _ "; + + if(n2[0].getKind() == kind::APPLY_UF) { + out << "(trans _ _ _ _ "; + out << "(symm _ _ _ "; + out << ss.str(); + out << ") (pred_eq_f _ " << ProofManager::getLitName(n2[0]) << ")) t_t_neq_f))" << std::endl; + } else { + Assert((n1[0] == n2[0][0] && n1[1] == n2[0][1]) || (n1[1] == n2[0][0] && n1[0] == n2[0][1])); + if(n1[1] == n2[0][0]) { + out << "(symm _ _ _ " << ss.str() << ")"; + } else { + out << ss.str(); + } + Debug("pf::array") << "ArrayProof::toStream: getLitName( " << n2[0] << " ) = " << + ProofManager::getLitName(n2[0]) << std::endl; + + out << " " << ProofManager::getLitName(n2[0]) << "))" << std::endl; + } + } + + return Node(); + } + + if (pf->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE) { + Debug("mgd") << "\nok, looking at congruence:\n"; + pf->debug_print("mgd"); + std::stack<const theory::eq::EqProof*> stk; + for(const theory::eq::EqProof* pf2 = pf; pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE; pf2 = pf2->d_children[0]) { + Assert(!pf2->d_node.isNull()); + Assert(pf2->d_node.getKind() == kind::PARTIAL_APPLY_UF || + pf2->d_node.getKind() == kind::BUILTIN || + pf2->d_node.getKind() == kind::APPLY_UF || + pf2->d_node.getKind() == kind::SELECT || + pf2->d_node.getKind() == kind::PARTIAL_SELECT_0 || + pf2->d_node.getKind() == kind::PARTIAL_SELECT_1 || + pf2->d_node.getKind() == kind::STORE); + + Assert(pf2->d_children.size() == 2); + out << "(cong _ _ _ _ _ _ "; + stk.push(pf2); + } + Assert(stk.top()->d_children[0]->d_id != theory::eq::MERGED_THROUGH_CONGRUENCE); + // NodeBuilder<> b1(kind::PARTIAL_APPLY_UF), b2(kind::PARTIAL_APPLY_UF); + NodeBuilder<> b1, b2; + + const theory::eq::EqProof* pf2 = stk.top(); + stk.pop(); + Assert(pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE); + Node n1 = toStreamRecLFSC(out, tp, pf2->d_children[0], tb + 1, map); + out << " "; + std::stringstream ss; + Node n2 = toStreamRecLFSC(ss, tp, pf2->d_children[1], tb + 1, map); + + + Debug("mgd") << "\nok, in FIRST cong[" << stk.size() << "]" << "\n"; + pf2->debug_print("mgd"); + // Temp + Debug("mgd") << "n1 is a proof for: " << pf2->d_children[0]->d_node << ". It is: " << n1 << std::endl; + Debug("mgd") << "n2 is a proof for: " << pf2->d_children[1]->d_node << ". It is: " << n2 << std::endl; + // + Debug("mgd") << "looking at " << pf2->d_node << "\n"; + Debug("mgd") << " " << n1 << "\n"; + Debug("mgd") << " " << n2 << "\n"; + + int side = 0; + if(match(pf2->d_node, n1[0])) { + Debug("mgd") << "SIDE IS 0\n"; + side = 0; + } else { + Debug("mgd") << "SIDE IS 1\n"; + if(!match(pf2->d_node, n1[1])) { + Debug("mgd") << "IN BAD CASE, our first subproof is\n"; + pf2->d_children[0]->debug_print("mgd"); + } + Assert(match(pf2->d_node, n1[1])); + side = 1; + } + + if(n1[side].getKind() == kind::APPLY_UF || + n1[side].getKind() == kind::PARTIAL_APPLY_UF || + n1[side].getKind() == kind::SELECT || + n1[side].getKind() == kind::PARTIAL_SELECT_1 || + n1[side].getKind() == kind::STORE) { + if(n1[side].getKind() == kind::APPLY_UF || n1[side].getKind() == kind::PARTIAL_APPLY_UF) { + b1 << kind::PARTIAL_APPLY_UF; + b1 << n1[side].getOperator(); + } else if (n1[side].getKind() == kind::SELECT || n1[side].getKind() == kind::PARTIAL_SELECT_1) { + // b1 << n1[side].getKind(); + b1 << kind::SELECT; + } else { + b1 << kind::PARTIAL_APPLY_UF; + b1 << ProofManager::currentPM()->mkOp(n1[side].getOperator()); + } + b1.append(n1[side].begin(), n1[side].end()); + } + else if (n1[side].getKind() == kind::PARTIAL_SELECT_0) { + b1 << kind::PARTIAL_SELECT_1; + } else { + b1 << n1[side]; + } + + if(n1[1-side].getKind() == kind::PARTIAL_APPLY_UF || + n1[1-side].getKind() == kind::APPLY_UF || + n1[1-side].getKind() == kind::SELECT || + n1[1-side].getKind() == kind::PARTIAL_SELECT_1 || + n1[1-side].getKind() == kind::STORE) { + if(n1[1-side].getKind() == kind::APPLY_UF || + n1[1-side].getKind() == kind::PARTIAL_APPLY_UF) { + b2 << kind::PARTIAL_APPLY_UF; + b2 << n1[1-side].getOperator(); + } else if (n1[1-side].getKind() == kind::SELECT || n1[1-side].getKind() == kind::PARTIAL_SELECT_1) { + // b2 << n1[1-side].getKind(); + b2 << kind::SELECT; + } else { + b2 << kind::PARTIAL_APPLY_UF; + b2 << ProofManager::currentPM()->mkOp(n1[1-side].getOperator()); + } + b2.append(n1[1-side].begin(), n1[1-side].end()); + } else if (n1[1-side].getKind() == kind::PARTIAL_SELECT_0) { + b2 << kind::PARTIAL_SELECT_1; + } else { + b2 << n1[1-side]; + } + Debug("mgd") << "pf2->d_node " << pf2->d_node << std::endl; + Debug("mgd") << "b1.getNumChildren() " << b1.getNumChildren() << std::endl; + Debug("mgd") << "n1 " << n1 << std::endl; + Debug("mgd") << "n2 " << n2 << std::endl; + // These debug prints can cause a problem if we're constructing a SELECT node and it doesn't have enough + // children yet. + // Debug("mgd") << "b1 " << b1 << std::endl; + // Debug("mgd") << "b2 " << b2 << std::endl; + Debug("mgd") << "side " << side << std::endl; + Debug("mgd") << "pf2->d_node's number of children: " << pf2->d_node.getNumChildren() << std::endl; + Debug("mgd") << "pf2->d_node's meta kind: " << pf2->d_node.getMetaKind() << std::endl; + Debug("mgd") << "Is this meta kind considered parameterized? " << (pf2->d_node.getMetaKind() == kind::metakind::PARAMETERIZED) << std::endl; + + if(pf2->d_node[b1.getNumChildren() + + (n1[side].getKind() == kind::PARTIAL_SELECT_0 ? 1 : 0) + + (n1[side].getKind() == kind::PARTIAL_SELECT_1 ? 1 : 0) - + (pf2->d_node.getMetaKind() == kind::metakind::PARAMETERIZED ? 0 : 1)] == n2[side]) { + b1 << n2[side]; + b2 << n2[1-side]; + out << ss.str(); + } else { + Assert(pf2->d_node[b1.getNumChildren() + + (n1[side].getKind() == kind::PARTIAL_SELECT_0 ? 1 : 0) + + (n1[side].getKind() == kind::PARTIAL_SELECT_1 ? 1 : 0) - + (pf2->d_node.getMetaKind() == kind::metakind::PARAMETERIZED ? 0 : 1)] == n2[1-side]); + b1 << n2[1-side]; + b2 << n2[side]; + out << "(symm _ _ _ " << ss.str() << ")"; + } + + Debug("mgd") << "After first insertion:" << std::endl; + Debug("mgd") << "b1 " << b1 << std::endl; + Debug("mgd") << "b2 " << b2 << std::endl; + + out << ")"; + while(!stk.empty()) { + + Debug("mgd") << "\nMORE TO DO\n"; + + pf2 = stk.top(); + stk.pop(); + Assert(pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE); + out << " "; + ss.str(""); + n2 = toStreamRecLFSC(ss, tp, pf2->d_children[1], tb + 1, map); + + Debug("mgd") << "\nok, in cong[" << stk.size() << "]" << "\n"; + Debug("mgd") << "looking at " << pf2->d_node << "\n"; + Debug("mgd") << " " << n1 << "\n"; + Debug("mgd") << " " << n2 << "\n"; + Debug("mgd") << " " << b1 << "\n"; + Debug("mgd") << " " << b2 << "\n"; + if(pf2->d_node[b1.getNumChildren()] == n2[side]) { + b1 << n2[side]; + b2 << n2[1-side]; + out << ss.str(); + } else { + Assert(pf2->d_node[b1.getNumChildren()] == n2[1-side]); + b1 << n2[1-side]; + b2 << n2[side]; + out << "(symm _ _ _ " << ss.str() << ")"; + } + out << ")"; + } + n1 = b1; + n2 = b2; + + Debug("mgd") << "at end assert!" << std::endl + << "pf2->d_node = " << pf2->d_node << std::endl + << "n1 (assigned from b1) = " << n1 << std::endl + << "n2 (assigned from b2) = " << n2 << std::endl; + + if(pf2->d_node.getKind() == kind::PARTIAL_APPLY_UF) { + Assert(n1 == pf2->d_node); + } + + Debug("mgd") << "n1.getOperator().getType().getNumChildren() = " + << n1.getOperator().getType().getNumChildren() << std::endl; + Debug("mgd") << "n1.getNumChildren() + 1 = " + << n1.getNumChildren() + 1 << std::endl; + + Assert(!((n1.getKind() == kind::PARTIAL_SELECT_0 && n1.getNumChildren() == 2))); + if (n1.getKind() == kind::PARTIAL_SELECT_1 && n1.getNumChildren() == 2) { + Debug("mgd") << "Finished a SELECT. Updating.." << std::endl; + b1.clear(kind::SELECT); + b1.append(n1.begin(), n1.end()); + n1 = b1; + Debug("mgd") << "New n1: " << n1 << std::endl; + // } else if (n1.getKind() == kind::PARTIAL_SELECT_0 && n1.getNumChildren() == 1) { + // Debug("mgd") << "Finished a PARTIAL_SELECT_1. Updating.." << std::endl; + // b1.clear(kind::PARTIAL_SELECT_1); + // b1.append(n1.begin(), n1.end()); + // n1 = b1; + // Debug("mgd") << "New n1: " << n1 << std::endl; + // } else + } else if(n1.getOperator().getType().getNumChildren() == n1.getNumChildren() + 1) { + if(ProofManager::currentPM()->hasOp(n1.getOperator())) { + b1.clear(ProofManager::currentPM()->lookupOp(n2.getOperator()).getConst<Kind>()); + } else { + b1.clear(kind::APPLY_UF); + b1 << n1.getOperator(); + } + b1.append(n1.begin(), n1.end()); + n1 = b1; + Debug("mgd") << "at[2] end assert, got " << pf2->d_node << " and " << n1 << std::endl; + if(pf2->d_node.getKind() == kind::APPLY_UF) { + Assert(n1 == pf2->d_node); + } + } + + Debug("mgd") << "n2.getOperator().getType().getNumChildren() = " + << n2.getOperator().getType().getNumChildren() << std::endl; + Debug("mgd") << "n2.getNumChildren() + 1 = " + << n2.getNumChildren() + 1 << std::endl; + + Assert(!((n2.getKind() == kind::PARTIAL_SELECT_0 && n2.getNumChildren() == 2))); + if (n2.getKind() == kind::PARTIAL_SELECT_1 && n2.getNumChildren() == 2) { + Debug("mgd") << "Finished a SELECT. Updating.." << std::endl; + b2.clear(kind::SELECT); + b2.append(n2.begin(), n2.end()); + n2 = b2; + Debug("mgd") << "New n2: " << n2 << std::endl; + // } else if (n2.getKind() == kind::PARTIAL_SELECT_0 && n2.getNumChildren() == 1) { + // Debug("mgd") << "Finished a PARTIAL_SELECT_1. Updating.." << std::endl; + // b2.clear(kind::PARTIAL_SELECT_1); + // b2.append(n2.begin(), n2.end()); + // n2 = b2; + // Debug("mgd") << "New n2: " << n2 << std::endl; + // } else + } else if(n2.getOperator().getType().getNumChildren() == n2.getNumChildren() + 1) { + if(ProofManager::currentPM()->hasOp(n2.getOperator())) { + b2.clear(ProofManager::currentPM()->lookupOp(n2.getOperator()).getConst<Kind>()); + } else { + b2.clear(kind::APPLY_UF); + b2 << n2.getOperator(); + } + b2.append(n2.begin(), n2.end()); + n2 = b2; + } + Node n = (side == 0 ? eqNode(n1, n2) : eqNode(n2, n1)); + + Debug("mgdx") << "\ncong proved: " << n << "\n"; + return n; + } + + else if (pf->d_id == theory::eq::MERGED_THROUGH_REFLEXIVITY) { + Assert(!pf->d_node.isNull()); + Assert(pf->d_children.empty()); + out << "(refl _ "; + tp->printTerm(NodeManager::currentNM()->toExpr(pf->d_node), out, map); + out << ")"; + return eqNode(pf->d_node, pf->d_node); + } + + else if (pf->d_id == theory::eq::MERGED_THROUGH_EQUALITY) { + Assert(!pf->d_node.isNull()); + Assert(pf->d_children.empty()); + Debug("pf::array") << "ArrayProof::toStream: getLitName( " << pf->d_node.negate() << " ) = " << + ProofManager::getLitName(pf->d_node.negate()) << std::endl; + out << ProofManager::getLitName(pf->d_node.negate()); + return pf->d_node; + } + + else if (pf->d_id == theory::eq::MERGED_THROUGH_TRANS) { + bool firstNeg = false; + bool secondNeg = false; + + Assert(!pf->d_node.isNull()); + Assert(pf->d_children.size() >= 2); + std::stringstream ss; + Debug("mgd") << "\ndoing trans proof[[\n"; + pf->debug_print("mgd"); + Debug("mgd") << "\n"; + Node n1 = toStreamRecLFSC(ss, tp, pf->d_children[0], tb + 1, map); + Debug("mgd") << "\ndoing trans proof, got n1 " << n1 << "\n"; + if(tb == 1) { + Debug("mgdx") << "\ntrans proof[0], got n1 " << n1 << "\n"; + } + + bool identicalEqualities = false; + bool evenLengthSequence; + Node nodeAfterEqualitySequence; + + std::map<size_t, Node> childToStream; + + for(size_t i = 1; i < pf->d_children.size(); ++i) { + std::stringstream ss1(ss.str()), ss2; + ss.str(""); + + // It is possible that we've already converted the i'th child to stream. If so, + // use previously stored result. Otherwise, convert and store. + Node n2; + if (childToStream.find(i) != childToStream.end()) + n2 = childToStream[i]; + else { + n2 = toStreamRecLFSC(ss2, tp, pf->d_children[i], tb + 1, map); + childToStream[i] = n2; + } + + Debug("mgd") << "\ndoing trans proof, got (first) n2 " << n2 << "\n"; + + // The following branch is dedicated to handling sequences of identical equalities, + // i.e. trans[ a=b, a=b, a=b ]. + // + // There are two cases: + // 1. The number of equalities is odd. Then, the sequence can be collapsed to just one equality, + // i.e. a=b. + // 2. The number of equalities is even. Now, we have two options: a=a or b=b. To determine this, + // we look at the node after the equality sequence. If it needs a, we go for a=a; and if it needs + // b, we go for b=b. If there is no following node, we look at the goal of the transitivity proof, + // and use it to determine which option we need. + if(n2.getKind() == kind::EQUAL || n2.getKind() == kind::IFF) { + if (((n1[0] == n2[0]) && (n1[1] == n2[1])) || ((n1[0] == n2[1]) && (n1[1] == n2[0]))) { + // We are in a sequence of identical equalities + + Debug("pf::array") << "Detected identical equalities: " << std::endl << "\t" << n1 << std::endl; + + if (!identicalEqualities) { + // The sequence of identical equalities has started just now + identicalEqualities = true; + + Debug("pf::array") << "The sequence is just beginning. Determining length..." << std::endl; + + // Determine whether the length of this sequence is odd or even. + evenLengthSequence = true; + bool sequenceOver = false; + size_t j = i + 1; + + while (j < pf->d_children.size() && !sequenceOver) { + std::stringstream dontCare; + nodeAfterEqualitySequence = toStreamRecLFSC(dontCare, tp, pf->d_children[j], tb + 1, map ); + + if (((nodeAfterEqualitySequence[0] == n1[0]) && (nodeAfterEqualitySequence[1] == n1[1])) || + ((nodeAfterEqualitySequence[0] == n1[1]) && (nodeAfterEqualitySequence[1] == n1[0]))) { + evenLengthSequence = !evenLengthSequence; + } else { + sequenceOver = true; + } + + ++j; + } + + if (evenLengthSequence) { + // If the length is even, we need to apply transitivity for the "correct" hand of the equality. + + Debug("pf::array") << "Equality sequence of even length" << std::endl; + Debug("pf::array") << "n1 is: " << n1 << std::endl; + Debug("pf::array") << "n2 is: " << n2 << std::endl; + Debug("pf::array") << "pf-d_node is: " << pf->d_node << std::endl; + Debug("pf::array") << "Next node is: " << nodeAfterEqualitySequence << std::endl; + + ss << "(trans _ _ _ _ "; + + // If the sequence is at the very end of the transitivity proof, use pf->d_node to guide us. + if (!sequenceOver) { + if (match(n1[0], pf->d_node[0])) { + n1 = eqNode(n1[0], n1[0]); + ss << ss1.str() << " (symm _ _ _ " << ss1.str() << ")"; + } else if (match(n1[1], pf->d_node[1])) { + n1 = eqNode(n1[1], n1[1]); + ss << " (symm _ _ _ " << ss1.str() << ")" << ss1.str(); + } else { + Debug("pf::array") << "Error: identical equalities over, but hands don't match what we're proving." + << std::endl; + Assert(false); + } + } else { + // We have a "next node". Use it to guide us. + if (nodeAfterEqualitySequence.getKind() == kind::NOT) { + nodeAfterEqualitySequence = nodeAfterEqualitySequence[0]; + } + + Assert(nodeAfterEqualitySequence.getKind() == kind::EQUAL || + nodeAfterEqualitySequence.getKind() == kind::IFF); + + if ((n1[0] == nodeAfterEqualitySequence[0]) || (n1[0] == nodeAfterEqualitySequence[1])) { + + // Eliminate n1[1] + ss << ss1.str() << " (symm _ _ _ " << ss1.str() << ")"; + n1 = eqNode(n1[0], n1[0]); + + } else if ((n1[1] == nodeAfterEqualitySequence[0]) || (n1[1] == nodeAfterEqualitySequence[1])) { + + // Eliminate n1[0] + ss << " (symm _ _ _ " << ss1.str() << ")" << ss1.str(); + n1 = eqNode(n1[1], n1[1]); + + } else { + Debug("pf::array") << "Error: even length sequence, but I don't know which hand to keep!" << std::endl; + Assert(false); + } + } + + ss << ")"; + + } else { + Debug("pf::array") << "Equality sequence length is odd!" << std::endl; + ss.str(ss1.str()); + } + + Debug("pf::array") << "Have proven: " << n1 << std::endl; + } else { + ss.str(ss1.str()); + } + + // Ignore the redundancy. + continue; + } + } + + if (identicalEqualities) { + // We were in a sequence of identical equalities, but it has now ended. Resume normal operation. + identicalEqualities = false; + } + + Debug("mgd") << "\ndoing trans proof, got n2 " << n2 << "\n"; + if(tb == 1) { + Debug("mgdx") << "\ntrans proof[" << i << "], got n2 " << n2 << "\n"; + Debug("mgdx") << (n2.getKind() == kind::EQUAL || n2.getKind() == kind::IFF) << "\n"; + + if ((n1.getNumChildren() >= 2) && (n2.getNumChildren() >= 2)) { + Debug("mgdx") << n1[0].getId() << " " << n1[1].getId() << " / " << n2[0].getId() << " " << n2[1].getId() << "\n"; + Debug("mgdx") << n1[0].getId() << " " << n1[0] << "\n"; + Debug("mgdx") << n1[1].getId() << " " << n1[1] << "\n"; + Debug("mgdx") << n2[0].getId() << " " << n2[0] << "\n"; + Debug("mgdx") << n2[1].getId() << " " << n2[1] << "\n"; + Debug("mgdx") << (n1[0] == n2[0]) << "\n"; + Debug("mgdx") << (n1[1] == n2[1]) << "\n"; + Debug("mgdx") << (n1[0] == n2[1]) << "\n"; + Debug("mgdx") << (n1[1] == n2[0]) << "\n"; + } + } + + // We can hadnle one of the equalities being negative, but not both + Assert((n1.getKind() != kind::NOT) || (n2.getKind() != kind::NOT)); + + firstNeg = false; + secondNeg = false; + + if (n1.getKind() == kind::NOT) { + Debug("mgdx") << "n1 is negative" << std::endl; + Debug("pf::array") << "n1 = " << n1 << ", n2 = " << n2 << std::endl; + firstNeg = true; + ss << "(negtrans1 _ _ _ _ "; + n1 = n1[0]; + } else if (n2.getKind() == kind::NOT) { + Debug("mgdx") << "n2 is negative" << std::endl; + Debug("pf::array") << "n1 = " << n1 << ", n2 = " << n2 << std::endl; + secondNeg = true; + ss << "(negtrans2 _ _ _ _ "; + n2 = n2[0]; + } else { + ss << "(trans _ _ _ _ "; + } + + if((n2.getKind() == kind::EQUAL || n2.getKind() == kind::IFF) && + (n1.getKind() == kind::EQUAL || n1.getKind() == kind::IFF)) + // Both elements of the transitivity rule are equalities/iffs + { + if(n1[0] == n2[0]) { + if(tb == 1) { Debug("mgdx") << "case 1\n"; } + n1 = eqNode(n1[1], n2[1]); + ss << (firstNeg ? "(negsymm _ _ _ " : "(symm _ _ _ ") << ss1.str() << ") " << ss2.str(); + } else if(n1[1] == n2[1]) { + if(tb == 1) { Debug("mgdx") << "case 2\n"; } + n1 = eqNode(n1[0], n2[0]); + ss << ss1.str() << (secondNeg ? " (negsymm _ _ _ " : " (symm _ _ _ " ) << ss2.str() << ")"; + } else if(n1[0] == n2[1]) { + if(tb == 1) { Debug("mgdx") << "case 3\n"; } + if(!firstNeg && !secondNeg) { + n1 = eqNode(n2[0], n1[1]); + ss << ss2.str() << " " << ss1.str(); + } else if (firstNeg) { + n1 = eqNode(n1[1], n2[0]); + ss << " (negsymm _ _ _ " << ss1.str() << ") (symm _ _ _ " << ss2.str() << ")"; + } else { + Assert(secondNeg); + n1 = eqNode(n1[1], n2[0]); + ss << " (symm _ _ _ " << ss1.str() << ") (negsymm _ _ _ " << ss2.str() << ")"; + } + if(tb == 1) { Debug("mgdx") << "++ proved " << n1 << "\n"; } + } else if(n1[1] == n2[0]) { + if(tb == 1) { Debug("mgdx") << "case 4\n"; } + n1 = eqNode(n1[0], n2[1]); + ss << ss1.str() << " " << ss2.str(); + } else { + Warning() << "\n\ntrans proof failure at step " << i << "\n\n"; + Warning() << "0 proves " << n1 << "\n"; + Warning() << "1 proves " << n2 << "\n\n"; + pf->debug_print("mgdx",0); + //toStreamRec(Warning.getStream(), pf, 0); + Warning() << "\n\n"; + Unreachable(); + } + Debug("mgd") << "++ trans proof[" << i << "], now have " << n1 << std::endl; + } else if(n1.getKind() == kind::EQUAL || n1.getKind() == kind::IFF) { + // n1 is an equality/iff, but n2 is a predicate + if(n1[0] == n2) { + n1 = n1[1]; + ss << (firstNeg ? "(negsymm _ _ _ " : "(symm _ _ _ ") + << ss1.str() << ") (pred_eq_t _ " << ss2.str() << ")"; + } else if(n1[1] == n2) { + n1 = n1[0]; + ss << ss1.str() << " (pred_eq_t _ " << ss2.str() << ")"; + } else { + Unreachable(); + } + } else if(n2.getKind() == kind::EQUAL || n2.getKind() == kind::IFF) { + // n2 is an equality/iff, but n1 is a predicate + if(n2[0] == n1) { + n1 = n2[1]; + ss << (secondNeg ? "(negsymm _ _ _ " : "(symm _ _ _ ") + << ss2.str() << ") (pred_eq_t _ " << ss1.str() << ")"; + } else if(n2[1] == n1) { + n1 = n2[0]; + ss << ss2.str() << " (pred_eq_t _ " << ss1.str() << ")"; + } else { + Unreachable(); + } + } else { + // Both n1 and n2 are prediacates. Don't know what to do... + Unreachable(); + } + + ss << ")"; + + if (firstNeg || secondNeg) { + n1 = (n1.getKind() == kind::NOT) ? n1[0] : n1.notNode(); + } + } + + out << ss.str(); + Debug("mgd") << "\n++ trans proof done, have proven " << n1 << std::endl; + //return (firstNeg || secondNeg) ? n1.notNode() : n1; + return n1; + } + + else if (pf->d_id == d_reasonRow) { + Debug("mgd") << "row lemma: " << pf->d_node << std::endl; + Assert(pf->d_node.getKind() == kind::EQUAL); + + + if (pf->d_node[1].getKind() == kind::SELECT) { + // This is the case where ((a[i]:=t)[k] == a[k]), and the sub-proof explains why (i != k). + TNode t1, t2, t3, t4; + Node ret; + if(pf->d_node[1].getKind() == kind::SELECT && + pf->d_node[1][0].getKind() == kind::STORE && + pf->d_node[0].getKind() == kind::SELECT && + pf->d_node[0][0] == pf->d_node[1][0][0] && + pf->d_node[0][1] == pf->d_node[1][1]) { + t2 = pf->d_node[1][0][1]; + t3 = pf->d_node[1][1]; + t1 = pf->d_node[0][0]; + t4 = pf->d_node[1][0][2]; + ret = pf->d_node[1].eqNode(pf->d_node[0]); + Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\nt4 " << t4 << "\n"; + } else { + Assert(pf->d_node[0].getKind() == kind::SELECT && + pf->d_node[0][0].getKind() == kind::STORE && + pf->d_node[1].getKind() == kind::SELECT && + pf->d_node[1][0] == pf->d_node[0][0][0] && + pf->d_node[1][1] == pf->d_node[0][1]); + t2 = pf->d_node[0][0][1]; + t3 = pf->d_node[0][1]; + t1 = pf->d_node[1][0]; + t4 = pf->d_node[0][0][2]; + ret = pf->d_node; + Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\nt4 " << t4 << "\n"; + } + + // inner index != outer index + // t3 is the outer index + + + Assert(pf->d_children.size() == 1); + std::stringstream ss; + Node subproof = toStreamRecLFSC(ss, tp, pf->d_children[0], tb + 1, map); + + out << "(row _ _ "; + tp->printTerm(t2.toExpr(), out, map); + out << " "; + tp->printTerm(t3.toExpr(), out, map); + out << " "; + tp->printTerm(t1.toExpr(), out, map); + out << " "; + tp->printTerm(t4.toExpr(), out, map); + out << " "; + + Debug("pf::array") << "pf->d_children[0]->d_node is: " << pf->d_children[0]->d_node + << ". t3 is: " << t3 << std::endl + << "subproof is: " << subproof << std::endl; + + Debug("pf::array") << "Subproof is: " << ss.str() << std::endl; + + if (subproof[0][1] == t3) { + Debug("pf::array") << "Dont need symmetry!" << std::endl; + out << ss.str(); + } else { + Debug("pf::array") << "Need symmetry!" << std::endl; + out << "(negsymm _ _ _ " << ss.str() << ")"; + } + + out << ")"; + + return ret; + } else { + Debug("pf::array") << "In the case of NEGATIVE ROW" << std::endl; + + Debug("pf::array") << "pf->d_children[0]->d_node is: " << pf->d_children[0]->d_node << std::endl; + + // This is the case where (i == k), and the sub-proof explains why ((a[i]:=t)[k] != a[k]) + + // If we wanted to remove the need for "negativerow", we would need to prove i==k using a new satlem. We would: + // 1. Create a new satlem. + // 2. Assume that i != k + // 3. Apply ROW to show that ((a[i]:=t)[k] == a[k]) + // 4. Contradict this with the fact that ((a[i]:=t)[k] != a[k]), obtaining our contradiction + + TNode t1, t2, t3, t4; + Node ret; + + // pf->d_node is an equality, i==k. + t1 = pf->d_node[0]; + t2 = pf->d_node[1]; + + // pf->d_children[0]->d_node will have the form: (not (= (select (store a_565 i7 e_566) i1) (select a_565 i1))), + // or its symmetrical version. + + unsigned side; + if (pf->d_children[0]->d_node[0][0].getKind() == kind::SELECT && + pf->d_children[0]->d_node[0][0][0].getKind() == kind::STORE) { + side = 0; + } else if (pf->d_children[0]->d_node[0][1].getKind() == kind::SELECT && + pf->d_children[0]->d_node[0][1][0].getKind() == kind::STORE) { + side = 1; + } + else { + Unreachable(); + } + + Debug("pf::array") << "Side is: " << side << std::endl; + + // The array's index and element types will come from the subproof... + t3 = pf->d_children[0]->d_node[0][side][0][0]; + t4 = pf->d_children[0]->d_node[0][side][0][2]; + ret = pf->d_node; + + Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\nt4 " << t4 << "\n"; + + Assert(pf->d_children.size() == 1); + std::stringstream ss; + Node subproof = toStreamRecLFSC(ss, tp, pf->d_children[0], tb + 1, map); + + Debug("pf::array") << "Subproof is: " << ss.str() << std::endl; + + out << "(negativerow _ _ "; + tp->printTerm(t1.toExpr(), out, map); + out << " "; + tp->printTerm(t2.toExpr(), out, map); + out << " "; + tp->printTerm(t3.toExpr(), out, map); + out << " "; + tp->printTerm(t4.toExpr(), out, map); + out << " "; + + + // if (subproof[0][1] == t3) { + Debug("pf::array") << "Dont need symmetry!" << std::endl; + out << ss.str(); + // } else { + // Debug("pf::array") << "Need symmetry!" << std::endl; + // out << "(negsymm _ _ _ " << ss.str() << ")"; + // } + + out << ")"; + + // Unreachable(); + + return ret; + } + } + + else if (pf->d_id == d_reasonRow1) { + Debug("mgd") << "row1 lemma: " << pf->d_node << std::endl; + Assert(pf->d_node.getKind() == kind::EQUAL); + TNode t1, t2, t3; + Node ret; + if(pf->d_node[1].getKind() == kind::SELECT && + pf->d_node[1][0].getKind() == kind::STORE && + pf->d_node[1][0][1] == pf->d_node[1][1] && + pf->d_node[1][0][2] == pf->d_node[0]) { + t1 = pf->d_node[1][0][0]; + t2 = pf->d_node[1][0][1]; + t3 = pf->d_node[0]; + ret = pf->d_node[1].eqNode(pf->d_node[0]); + Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\n"; + } else { + Assert(pf->d_node[0].getKind() == kind::SELECT && + pf->d_node[0][0].getKind() == kind::STORE && + pf->d_node[0][0][1] == pf->d_node[0][1] && + pf->d_node[0][0][2] == pf->d_node[1]); + t1 = pf->d_node[0][0][0]; + t2 = pf->d_node[0][0][1]; + t3 = pf->d_node[1]; + ret = pf->d_node; + Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\n"; + } + out << "(row1 _ _ "; + tp->printTerm(t1.toExpr(), out, map); + out << " "; + tp->printTerm(t2.toExpr(), out, map); + out << " "; + tp->printTerm(t3.toExpr(), out, map); + out << ")"; + return ret; + } + + else if (pf->d_id == d_reasonExt) { + theory::eq::EqProof *child_proof; + + Assert(pf->d_node.getKind() == kind::NOT); + Assert(pf->d_node[0].getKind() == kind::EQUAL); + Assert(pf->d_children.size() == 1); + + child_proof = pf->d_children[0]; + Assert(child_proof->d_node.getKind() == kind::NOT); + Assert(child_proof->d_node[0].getKind() == kind::EQUAL); + + Debug("mgd") << "EXT lemma: " << pf->d_node << std::endl; + + TNode t1, t2, t3; + t1 = child_proof->d_node[0][0]; + t2 = child_proof->d_node[0][1]; + t3 = pf->d_node[0][0][1]; + + Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\n"; + + out << "(or_elim_1 _ _ "; + out << ProofManager::getLitName(child_proof->d_node[0]); + out << " "; + out << ProofManager::getArrayProof()->skolemToLiteral(t3.toExpr()); + out << ")"; + + return pf->d_node; + } + + else { + Assert(!pf->d_node.isNull()); + Assert(pf->d_children.empty()); + Debug("mgd") << "theory proof: " << pf->d_node << " by rule " << int(pf->d_id) << std::endl; + AlwaysAssert(false); + return pf->d_node; + } +} + +ArrayProof::ArrayProof(theory::arrays::TheoryArrays* arrays, TheoryProofEngine* pe) + : TheoryProof(arrays, pe) +{} + +void ArrayProof::registerTerm(Expr term) { + // already registered + if (d_declarations.find(term) != d_declarations.end()) + return; + + Type type = term.getType(); + if (type.isSort()) { + // declare uninterpreted sorts + d_sorts.insert(type); + } + + if (term.getKind() == kind::APPLY_UF) { + Expr function = term.getOperator(); + d_declarations.insert(function); + } + + if (term.isVariable()) { + d_declarations.insert(term); + } + + // recursively declare all other terms + for (unsigned i = 0; i < term.getNumChildren(); ++i) { + // could belong to other theories + d_proofEngine->registerTerm(term[i]); + } +} + +std::string ArrayProof::skolemToLiteral(Expr skolem) { + Assert(d_skolemToLiteral.find(skolem) != d_skolemToLiteral.end()); + return d_skolemToLiteral[skolem]; +} + +void LFSCArrayProof::printOwnedTerm(Expr term, std::ostream& os, const LetMap& map) { + Debug("pf::array") << std::endl << "(pf::array) LFSCArrayProof::printOwnedTerm: term = " << term << std::endl; + + Assert (theory::Theory::theoryOf(term) == theory::THEORY_ARRAY); + + if (theory::Theory::theoryOf(term) != theory::THEORY_ARRAY) { + // We can get here, for instance, if there's a (select ite ...), e.g. a non-array term + // hiding as a subterm of an array term. In that case, send it back to the dispatcher. + d_proofEngine->printBoundTerm(term, os, map); + return; + } + + if (term.getKind() == kind::VARIABLE || term.getKind() == kind::SKOLEM) { + os << term; + return; + } + + Assert ((term.getKind() == kind::SELECT) || (term.getKind() == kind::PARTIAL_SELECT_0) || (term.getKind() == kind::PARTIAL_SELECT_1) || (term.getKind() == kind::STORE)); + + switch (term.getKind()) { + case kind::SELECT: + Assert(term.getNumChildren() == 2); + os << "(apply _ _ (apply _ _ (read "; + printSort(ArrayType(term[0].getType()).getIndexType(), os); + os << " "; + printSort(ArrayType(term[0].getType()).getConstituentType(), os); + os << ") "; + printTerm(term[0], os, map); + os << ") "; + printTerm(term[1], os, map); + os << ") "; + return; + + case kind::PARTIAL_SELECT_0: + Assert(term.getNumChildren() == 1); + os << "(read "; + printSort(ArrayType(term[0].getType()).getIndexType(), os); + os << " "; + printSort(ArrayType(term[0].getType()).getConstituentType(), os); + os << ") "; + return; + + case kind::PARTIAL_SELECT_1: + Debug("pf::array") << "This branch has not beed tested yet." << std::endl; + Unreachable(); + + Assert(term.getNumChildren() == 1); + os << "(apply _ _ (read "; + printSort(ArrayType(term[0].getType()).getIndexType(), os); + os << " "; + printSort(ArrayType(term[0].getType()).getConstituentType(), os); + os << ") "; + printTerm(term[0], os, map); + os << ") "; + return; + + case kind::STORE: + os << "(apply _ _ (apply _ _ (apply _ _ (write "; + printSort(ArrayType(term[0].getType()).getIndexType(), os); + os << " "; + printSort(ArrayType(term[0].getType()).getConstituentType(), os); + os << ") "; + printTerm(term[0], os, map); + os << ") "; + printTerm(term[1], os, map); + os << ") "; + printTerm(term[2], os, map); + os << ") "; + return; + + default: + Unreachable(); + return; + } +} + +void LFSCArrayProof::printOwnedSort(Type type, std::ostream& os) { + Debug("pf::array") << std::endl << "(pf::array) LFSCArrayProof::printOwnedSort: type is: " << type << std::endl; + Assert (type.isArray() || type.isSort()); + os << type <<" "; +} + +void LFSCArrayProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren) { + os << " ;; Array Theory Lemma \n;;"; + for (unsigned i = 0; i < lemma.size(); ++i) { + os << lemma[i] <<" "; + } + os <<"\n"; + //os << " (clausify_false trust)"; + ArrayProof::printTheoryLemmaProof(lemma, os, paren); +} + +void LFSCArrayProof::printSortDeclarations(std::ostream& os, std::ostream& paren) { + // declaring the sorts + Debug("pf::array") << "Arrays declaring sorts..." << std::endl; + + for (TypeSet::const_iterator it = d_sorts.begin(); it != d_sorts.end(); ++it) { + if (!ProofManager::currentPM()->wasPrinted(*it)) { + os << "(% " << *it << " sort\n"; + paren << ")"; + ProofManager::currentPM()->markPrinted(*it); + } + } +} + +void LFSCArrayProof::printTermDeclarations(std::ostream& os, std::ostream& paren) { + Debug("pf::array") << "Arrays declaring terms..." << std::endl; + + for (ExprSet::const_iterator it = d_declarations.begin(); it != d_declarations.end(); ++it) { + Expr term = *it; + + Assert(term.getType().isArray() || term.isVariable()); + + Debug("pf::array") << "LFSCArrayProof::printDeclarations: term is: " << term + << ". It's type is: " << term.getType() + << std::endl; + + if (term.getType().isArray()){ + ArrayType array_type(term.getType()); + + Debug("pf::array") << "LFSCArrayProof::printDeclarations: term is an array. Index type: " + << array_type.getIndexType() + << ", element type: " << array_type.getConstituentType() << std::endl; + + os << "(% " << ProofManager::sanitize(term) << " "; + os << "(term "; + os << "(Array "; + + printSort(array_type.getIndexType(), os); + os << " "; + printSort(array_type.getConstituentType(), os); + + os << "))\n"; + } else { + Assert(term.isVariable()); + if (ProofManager::getSkolemizationManager()->isSkolem(*it)) { + Debug("pf::array") << "This term is a skoelm!" << std::endl; + d_skolemDeclarations.insert(*it); + } else { + os << "(% " << ProofManager::sanitize(term) << " "; + os << "(term "; + os << term.getType() << ")\n"; + } + } + + paren << ")"; + } + + Debug("pf::array") << "Declaring terms done!" << std::endl; +} + +void LFSCArrayProof::printDeferredDeclarations(std::ostream& os, std::ostream& paren) { + Debug("pf::array") << "Array: print deferred declarations called" << std::endl; + + for (ExprSet::const_iterator it = d_skolemDeclarations.begin(); it != d_skolemDeclarations.end(); ++it) { + Expr term = *it; + Node equality = ProofManager::getSkolemizationManager()->getDisequality(*it); + + Debug("pf::array") << "LFSCArrayProof::printDeferredDeclarations: term is: " << *it << std::endl + << "It is a witness for: " << equality << std::endl; + + std::ostringstream newSkolemLiteral; + newSkolemLiteral << ".sl" << d_skolemToLiteral.size(); + std::string skolemLiteral = newSkolemLiteral.str(); + + d_skolemToLiteral[*it] = skolemLiteral; + + Debug("pf::array") << "LFSCArrayProof::printDeferredDeclarations: new skolem literal is: " << skolemLiteral << std::endl; + + Assert(equality.getKind() == kind::NOT); + Assert(equality[0].getKind() == kind::EQUAL); + + Node array_one = equality[0][0]; + Node array_two = equality[0][1]; + + LetMap map; + + os << "(ext _ _ "; + printTerm(array_one.toExpr(), os, map); + os << " "; + printTerm(array_two.toExpr(), os, map); + os << " (\\ "; + printTerm(*it, os, map); + os << " (\\ "; + os << skolemLiteral.c_str(); + os << "\n"; + + paren << ")))"; + } +} + +} /* CVC4 namespace */ diff --git a/src/proof/array_proof.h b/src/proof/array_proof.h index beaf5194c..fb25c9433 100644 --- a/src/proof/array_proof.h +++ b/src/proof/array_proof.h @@ -1,13 +1,13 @@ /********************* */ /*! \file array_proof.h ** \verbatim - ** Original author: Liana Hadarean - ** Major contributors: none - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Guy Katz, 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 Arrray proof ** @@ -23,53 +23,74 @@ #include "proof/proof_manager.h" #include "proof/theory_proof.h" #include "theory/arrays/theory_arrays.h" +#include "theory/uf/equality_engine.h" namespace CVC4 { +//proof object outputted by TheoryARRAY +class ProofArray : public Proof { +private: + Node toStreamRecLFSC(std::ostream& out, TheoryProof* tp, + theory::eq::EqProof* pf, + unsigned tb, + const LetMap& map); + + /** 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: + ProofArray(theory::eq::EqProof* pf) : d_proof(pf) {} + //it is simply an equality engine proof + theory::eq::EqProof *d_proof; + void toStream(std::ostream& out); + void toStreamLFSC(std::ostream& out, TheoryProof* tp, theory::eq::EqProof* pf, const LetMap& map); + + void registerSkolem(Node equality, Node skolem); + + void setRowMergeTag(unsigned tag); + void setRow1MergeTag(unsigned tag); + void setExtMergeTag(unsigned tag); +}; + namespace theory { namespace arrays{ class TheoryArrays; } /* namespace CVC4::theory::arrays */ } /* namespace CVC4::theory */ +typedef __gnu_cxx::hash_set<Type, TypeHashFunction > TypeSet; + class ArrayProof : public TheoryProof { // TODO: whatever goes in this theory +protected: + TypeSet d_sorts; // all the uninterpreted sorts in this theory + ExprSet d_declarations; // all the variable/function declarations + ExprSet d_skolemDeclarations; // all the skolem variable declarations + std::map<Expr, std::string> d_skolemToLiteral; + public: - ArrayProof(theory::arrays::TheoryArrays* arrays, TheoryProofEngine* proofEngine) - : TheoryProof(arrays, proofEngine) - {} - virtual void registerTerm(Expr term) {} - - virtual void printTerm(Expr term, std::ostream& os, const LetMap& map) = 0; - virtual void printSort(Type type, std::ostream& os) = 0; - /** - * Print a proof for the theory lemma. Must prove - * clause representing lemma to be used in resolution proof. - * - * @param lemma clausal form of lemma - * @param os output stream - */ - virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren) = 0; - /** - * Print the variable/sorts declarations for this theory. - * - * @param os - * @param paren - */ - virtual void printDeclarations(std::ostream& os, std::ostream& paren) = 0; + ArrayProof(theory::arrays::TheoryArrays* arrays, TheoryProofEngine* proofEngine); + + std::string skolemToLiteral(Expr skolem); + + virtual void registerTerm(Expr term); }; class LFSCArrayProof : public ArrayProof { public: - LFSCArrayProof(theory::arrays::TheoryArrays* uf, TheoryProofEngine* proofEngine) - : ArrayProof(uf, proofEngine) + LFSCArrayProof(theory::arrays::TheoryArrays* arrays, TheoryProofEngine* proofEngine) + : ArrayProof(arrays, proofEngine) {} - // TODO implement - virtual void printTerm(Expr term, std::ostream& os, const LetMap& map) {} - virtual void printSort(Type type, std::ostream& os) {} - virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren) {} - virtual void printDeclarations(std::ostream& os, std::ostream& paren) {} + virtual void printOwnedTerm(Expr term, std::ostream& os, const LetMap& map); + virtual void printOwnedSort(Type type, std::ostream& os); + virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren); + virtual void printSortDeclarations(std::ostream& os, std::ostream& paren); + virtual void printTermDeclarations(std::ostream& os, std::ostream& paren); + virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren); }; diff --git a/src/proof/bitvector_proof.cpp b/src/proof/bitvector_proof.cpp index e067f0bce..b63782226 100644 --- a/src/proof/bitvector_proof.cpp +++ b/src/proof/bitvector_proof.cpp @@ -1,23 +1,23 @@ /********************* */ /*! \file bitvector_proof.cpp -** \verbatim -** Original author: Liana Hadarean -** Major contributors: none -** Minor contributors (to current version): none -** This file is part of the CVC4 project. -** Copyright (c) 2009-2014 New York University and The University of Iowa -** See the file COPYING in the top-level source directory for licensing -** information.\endverbatim -** -** \brief [[ Add one-line brief description here ]] -** -** [[ Add lengthier description here ]] -** \todo document this file -**/ + ** \verbatim + ** Top contributors (to current version): + ** Liana Hadarean, Guy Katz, 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 + ** + ** [[ Add lengthier description here ]] + + ** \todo document this file +**/ -#include "proof/bitvector_proof.h" +#include "proof/bitvector_proof.h" #include "options/bv_options.h" +#include "proof/clause_id.h" #include "proof/proof_utils.h" #include "proof/sat_proof_implementation.h" #include "prop/bvminisat/bvminisat.h" @@ -130,10 +130,10 @@ void BitVectorProof::endBVConflict(const CVC4::BVMinisat::Solver::TLitVec& confl expr_confl.push_back(expr_lit); } Expr conflict = utils::mkSortedExpr(kind::OR, expr_confl); - Debug("bv-proof") << "Make conflict for " << conflict << std::endl; + Debug("pf::bv") << "Make conflict for " << conflict << std::endl; if (d_bbConflictMap.find(conflict) != d_bbConflictMap.end()) { - Debug("bv-proof") << "Abort...already conflict for " << conflict << std::endl; + Debug("pf::bv") << "Abort...already conflict for " << conflict << std::endl; // This can only happen when we have eager explanations in the bv solver // if we don't get to propagate p before ~p is already asserted d_resolutionProof->cancelResChain(); @@ -144,30 +144,33 @@ void BitVectorProof::endBVConflict(const CVC4::BVMinisat::Solver::TLitVec& confl ClauseId clause_id = d_resolutionProof->registerAssumptionConflict(confl); d_bbConflictMap[conflict] = clause_id; d_resolutionProof->endResChain(clause_id); - Debug("bv-proof") << "BitVectorProof::endBVConflict id"<<clause_id<< " => " << conflict << "\n"; + Debug("pf::bv") << "BitVectorProof::endBVConflict id"<<clause_id<< " => " << conflict << "\n"; d_isAssumptionConflict = false; } void BitVectorProof::finalizeConflicts(std::vector<Expr>& conflicts) { if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) { - Debug("bv-proof") << "Construct full proof." << std::endl; + Debug("pf::bv") << "Construct full proof." << std::endl; d_resolutionProof->constructProof(); return; } for(unsigned i = 0; i < conflicts.size(); ++i) { Expr confl = conflicts[i]; - Debug("bv-proof") << "Finalize conflict " << confl << std::endl; + Debug("pf::bv") << "Finalize conflict " << confl << std::endl; //Assert (d_bbConflictMap.find(confl) != d_bbConflictMap.end()); if(d_bbConflictMap.find(confl) != d_bbConflictMap.end()){ ClauseId id = d_bbConflictMap[confl]; d_resolutionProof->collectClauses(id); }else{ - Debug("bv-proof") << "Do not collect clauses for " << confl << std::endl; + Debug("pf::bv") << "Do not collect clauses for " << confl << std::endl; } } } -void LFSCBitVectorProof::printTerm(Expr term, std::ostream& os, const LetMap& map) { +void LFSCBitVectorProof::printOwnedTerm(Expr term, std::ostream& os, const LetMap& map) { + Debug("pf::bv") << std::endl << "(pf::bv) LFSCBitVectorProof::printOwnedTerm( " << term << " ), theory is: " + << Theory::theoryOf(term) << std::endl; + Assert (Theory::theoryOf(term) == THEORY_BV); // peel off eager bit-blasting trick @@ -232,7 +235,7 @@ void LFSCBitVectorProof::printTerm(Expr term, std::ostream& os, const LetMap& ma return; } case kind::BITVECTOR_BITOF : { - printBitOf(term, os); + printBitOf(term, os, map); return; } case kind::VARIABLE: @@ -245,13 +248,25 @@ void LFSCBitVectorProof::printTerm(Expr term, std::ostream& os, const LetMap& ma } } -void LFSCBitVectorProof::printBitOf(Expr term, std::ostream& os) { +void LFSCBitVectorProof::printBitOf(Expr term, std::ostream& os, const LetMap& map) { Assert (term.getKind() == kind::BITVECTOR_BITOF); unsigned bit = term.getOperator().getConst<BitVectorBitOf>().bitIndex; Expr var = term[0]; - Assert (var.getKind() == kind::VARIABLE || - var.getKind() == kind::SKOLEM); - os << "(bitof " << ProofManager::sanitize(var) <<" " << bit <<")"; + + Debug("pf::bv") << "LFSCBitVectorProof::printBitOf( " << term << " ), " + << "bit = " << bit + << ", var = " << var << std::endl; + + os << "(bitof "; + if (var.getKind() == kind::VARIABLE || var.getKind() == kind::SKOLEM) { + // If var is "simple", we can just sanitize and print + os << ProofManager::sanitize(var); + } else { + // If var is "complex", it can belong to another theory. Therefore, dispatch again. + d_proofEngine->printBoundTerm(var, os, map); + } + + os << " " << bit << ")"; } void LFSCBitVectorProof::printConstant(Expr term, std::ostream& os) { @@ -332,7 +347,9 @@ void LFSCBitVectorProof::printOperatorParametric(Expr term, std::ostream& os, co os <<")"; } -void LFSCBitVectorProof::printSort(Type type, std::ostream& os) { +void LFSCBitVectorProof::printOwnedSort(Type type, std::ostream& os) { + Debug("pf::bv") << std::endl << "(pf::bv) LFSCBitVectorProof::printOwnedSort( " << type << " )" << std::endl; + Assert (type.isBitVector()); unsigned width = utils::getSize(type); os << "(BitVec "<<width<<")"; @@ -368,12 +385,20 @@ void LFSCBitVectorProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::os ClauseId lemma_id = d_bbConflictMap[lem]; d_resolutionProof->printAssumptionsResolution(lemma_id, os, lemma_paren); os <<lemma_paren.str(); - }else{ - Debug("bv-proof") << std::endl << "; Print non-bitblast theory conflict " << conflict << std::endl; + } else { + Unreachable(); // If we were to reach here, we would crash because BV replay is currently not supported + // in TheoryProof::printTheoryLemmaProof() + + Debug("pf::bv") << std::endl << "; Print non-bitblast theory conflict " << conflict << std::endl; BitVectorProof::printTheoryLemmaProof( lemma, os, paren ); } } -void LFSCBitVectorProof::printDeclarations(std::ostream& os, std::ostream& paren) { + +void LFSCBitVectorProof::printSortDeclarations(std::ostream& os, std::ostream& paren) { + // Nothing to do here at this point. +} + +void LFSCBitVectorProof::printTermDeclarations(std::ostream& os, std::ostream& paren) { ExprSet::const_iterator it = d_declarations.begin(); ExprSet::const_iterator end = d_declarations.end(); for (; it != end; ++it) { @@ -382,6 +407,9 @@ void LFSCBitVectorProof::printDeclarations(std::ostream& os, std::ostream& paren } } +void LFSCBitVectorProof::printDeferredDeclarations(std::ostream& os, std::ostream& paren) { + // Nothing to do here at this point. +} void LFSCBitVectorProof::printTermBitblasting(Expr term, std::ostream& os) { // TODO: once we have the operator elimination rules remove those that we @@ -428,7 +456,7 @@ void LFSCBitVectorProof::printTermBitblasting(Expr term, std::ostream& os) { os <<" _ _ _ _ _ _ "; } os << getBBTermName(term[0]) <<" "; - + for (unsigned i = 1; i < term.getNumChildren(); ++i) { os << getBBTermName(term[i]); os << ") "; @@ -488,7 +516,7 @@ void LFSCBitVectorProof::printTermBitblasting(Expr term, std::ostream& os) { case kind::BITVECTOR_SHL : case kind::BITVECTOR_LSHR : case kind::BITVECTOR_ASHR : { - // these are terms for which bit-blasting is not supported yet + // these are terms for which bit-blasting is not supported yet std::ostringstream paren; os <<"(trust_bblast_term _ "; paren <<")"; diff --git a/src/proof/bitvector_proof.h b/src/proof/bitvector_proof.h index 80d567f7c..4a1f4015d 100644 --- a/src/proof/bitvector_proof.h +++ b/src/proof/bitvector_proof.h @@ -1,13 +1,13 @@ /********************* */ /*! \file bitvector_proof.h ** \verbatim - ** Original author: Liana Hadarean - ** Major contributors: none - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Liana Hadarean, Guy Katz, 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 proof ** @@ -19,7 +19,7 @@ #ifndef __CVC4__BITVECTOR__PROOF_H #define __CVC4__BITVECTOR__PROOF_H -//#include <cstdint> +//#include <cstdint> #include <ext/hash_map> #include <ext/hash_set> #include <iostream> @@ -45,7 +45,7 @@ template <class T> class TBitblaster; } /* namespace CVC4::theory::bv */ } /* namespace CVC4::theory */ -class CnfProof; +class CnfProof; } /* namespace CVC4 */ namespace CVC4 { @@ -109,7 +109,7 @@ public: virtual void printTermBitblasting(Expr term, std::ostream& os) = 0; virtual void printAtomBitblasting(Expr term, std::ostream& os) = 0; - + virtual void printBitblasting(std::ostream& os, std::ostream& paren) = 0; virtual void printResolutionProof(std::ostream& os, std::ostream& paren) = 0; @@ -122,17 +122,19 @@ class LFSCBitVectorProof: public BitVectorProof { void printOperatorUnary(Expr term, std::ostream& os, const LetMap& map); void printPredicate(Expr term, std::ostream& os, const LetMap& map); void printOperatorParametric(Expr term, std::ostream& os, const LetMap& map); - void printBitOf(Expr term, std::ostream& os); + void printBitOf(Expr term, std::ostream& os, const LetMap& map); public: LFSCBitVectorProof(theory::bv::TheoryBV* bv, TheoryProofEngine* proofEngine) :BitVectorProof(bv, proofEngine) {} - virtual void printTerm(Expr term, std::ostream& os, const LetMap& map); - virtual void printSort(Type type, std::ostream& os); + virtual void printOwnedTerm(Expr term, std::ostream& os, const LetMap& map); + virtual void printOwnedSort(Type type, std::ostream& os); virtual void printTermBitblasting(Expr term, std::ostream& os); virtual void printAtomBitblasting(Expr term, std::ostream& os); virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren); - virtual void printDeclarations(std::ostream& os, std::ostream& paren); + virtual void printSortDeclarations(std::ostream& os, std::ostream& paren); + virtual void printTermDeclarations(std::ostream& os, std::ostream& paren); + virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren); virtual void printBitblasting(std::ostream& os, std::ostream& paren); virtual void printResolutionProof(std::ostream& os, std::ostream& paren); }; diff --git a/src/proof/clause_id.h b/src/proof/clause_id.h new file mode 100644 index 000000000..c66f8c9f5 --- /dev/null +++ b/src/proof/clause_id.h @@ -0,0 +1,33 @@ +/********************* */ +/*! \file clause_id.h + ** \verbatim + ** Top contributors (to current version): + ** 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 Definition of ClauseId + ** + ** A ClauseId is a shared identifier between the proofs module and the sat + ** solver for a clause. + **/ + +#include "cvc4_private.h" + +#ifndef __CVC4__PROOF__CLAUSE_ID_H +#define __CVC4__PROOF__CLAUSE_ID_H + +namespace CVC4 { + +/** + * A ClauseId is a shared identifier between the proofs module and the sat + * solver for a clause. + */ +typedef unsigned ClauseId; + +}/* CVC4 namespace */ + +#endif /* __CVC4__PROOF__CLAUSE_ID_H */ diff --git a/src/proof/cnf_proof.cpp b/src/proof/cnf_proof.cpp index 884a67856..19e9cbac9 100644 --- a/src/proof/cnf_proof.cpp +++ b/src/proof/cnf_proof.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file cnf_proof.cpp ** \verbatim - ** Original author: Liana Hadarean - ** Major contributors: Morgan Deters, Andrew Reynolds - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Liana Hadarean, 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 ]] ** @@ -16,22 +16,23 @@ **/ #include "proof/cnf_proof.h" -#include "proof/theory_proof.h" + +#include "proof/clause_id.h" #include "proof/proof_manager.h" -#include "prop/sat_solver_types.h" -#include "prop/minisat/minisat.h" +#include "proof/theory_proof.h" #include "prop/cnf_stream.h" - -using namespace CVC4::prop; +#include "prop/minisat/minisat.h" +#include "prop/sat_solver_types.h" namespace CVC4 { -CnfProof::CnfProof(CnfStream* stream, +CnfProof::CnfProof(prop::CnfStream* stream, context::Context* ctx, const std::string& name) : d_cnfStream(stream) , d_clauseToAssertion(ctx) , d_assertionToProofRule(ctx) + , d_clauseIdToOwnerTheory(ctx) , d_currentAssertionStack() , d_currentDefinitionStack() , d_clauseToDefinition(ctx) @@ -54,12 +55,13 @@ bool CnfProof::isDefinition(Node node) { return d_definitions.find(node) != d_definitions.end(); } - + ProofRule CnfProof::getProofRule(Node node) { Assert (isAssertion(node)); NodeToProofRule::iterator it = d_assertionToProofRule.find(node); return (*it).second; } + ProofRule CnfProof::getProofRule(ClauseId clause) { TNode assertion = getAssertionForClause(clause); return getProofRule(assertion); @@ -94,13 +96,14 @@ void CnfProof::registerConvertedClause(ClauseId clause, bool explanation) { Node current_assertion = getCurrentAssertion(); Node current_expr = getCurrentDefinition(); - + Debug("proof:cnf") << "CnfProof::registerConvertedClause " << clause << " assertion = " << current_assertion << clause << " definition = " << current_expr << std::endl; setClauseAssertion(clause, current_assertion); setClauseDefinition(clause, current_expr); + registerExplanationLemma(clause); } void CnfProof::setClauseAssertion(ClauseId clause, Node expr) { @@ -112,7 +115,7 @@ void CnfProof::setClauseAssertion(ClauseId clause, Node expr) { // that since b is top level, it is not cached by the CnfStream) if (d_clauseToAssertion.find(clause) != d_clauseToAssertion.end()) return; - + d_clauseToAssertion.insert (clause, expr); } @@ -126,7 +129,7 @@ void CnfProof::setClauseDefinition(ClauseId clause, Node definition) { d_clauseToDefinition.insert(clause, definition); d_definitions.insert(definition); } - + void CnfProof::registerAssertion(Node assertion, ProofRule reason) { Debug("proof:cnf") << "CnfProof::registerAssertion " << assertion << " reason " << reason << std::endl; @@ -140,6 +143,16 @@ void CnfProof::registerAssertion(Node assertion, ProofRule reason) { d_assertionToProofRule.insert(assertion, reason); } +void CnfProof::registerExplanationLemma(ClauseId clauseId) { + d_clauseIdToOwnerTheory.insert(clauseId, getExplainerTheory()); +} + +theory::TheoryId CnfProof::getOwnerTheory(ClauseId clause) { + Assert(d_clauseIdToOwnerTheory.find(clause) != d_clauseIdToOwnerTheory.end()); + return d_clauseIdToOwnerTheory[clause]; +} + + void CnfProof::setCnfDependence(Node from, Node to) { Debug("proof:cnf") << "CnfProof::setCnfDependence " << "from " << from << std::endl @@ -158,10 +171,10 @@ void CnfProof::pushCurrentAssertion(Node assertion) { void CnfProof::popCurrentAssertion() { Assert (d_currentAssertionStack.size()); - + Debug("proof:cnf") << "CnfProof::popCurrentAssertion " << d_currentAssertionStack.back() << std::endl; - + d_currentAssertionStack.pop_back(); } @@ -170,6 +183,14 @@ Node CnfProof::getCurrentAssertion() { return d_currentAssertionStack.back(); } +void CnfProof::setExplainerTheory(theory::TheoryId theory) { + d_explainerTheory = theory; +} + +theory::TheoryId CnfProof::getExplainerTheory() { + return d_explainerTheory; +} + void CnfProof::pushCurrentDefinition(Node definition) { Debug("proof:cnf") << "CnfProof::pushCurrentDefinition " << definition << std::endl; @@ -179,10 +200,10 @@ void CnfProof::pushCurrentDefinition(Node definition) { void CnfProof::popCurrentDefinition() { Assert (d_currentDefinitionStack.size()); - + Debug("proof:cnf") << "CnfProof::popCurrentDefinition " << d_currentDefinitionStack.back() << std::endl; - + d_currentDefinitionStack.pop_back(); } @@ -202,8 +223,8 @@ Node CnfProof::getAtom(prop::SatVariable var) { void CnfProof::collectAtoms(const prop::SatClause* clause, NodeSet& atoms) { for (unsigned i = 0; i < clause->size(); ++i) { - SatLiteral lit = clause->operator[](i); - SatVariable var = lit.getSatVariable(); + prop::SatLiteral lit = clause->operator[](i); + prop::SatVariable var = lit.getSatVariable(); TNode atom = getAtom(var); if (atoms.find(atom) == atoms.end()) { Assert (atoms.find(atom) == atoms.end()); @@ -245,8 +266,8 @@ void CnfProof::collectAssertionsForClauses(const IdToSatClause& clauses, void LFSCCnfProof::printAtomMapping(const NodeSet& atoms, std::ostream& os, std::ostream& paren) { - NodeSet::const_iterator it = atoms.begin(); - NodeSet::const_iterator end = atoms.end(); + NodeSet::const_iterator it = atoms.begin(); + NodeSet::const_iterator end = atoms.end(); for (;it != end; ++it) { os << "(decl_atom "; @@ -255,7 +276,7 @@ void LFSCCnfProof::printAtomMapping(const NodeSet& atoms, //FIXME hideous LFSCTheoryProofEngine* pe = (LFSCTheoryProofEngine*)ProofManager::currentPM()->getTheoryProofEngine(); pe->printLetTerm(atom.toExpr(), os); - + os << " (\\ " << ProofManager::getVarName(var, d_name) << " (\\ " << ProofManager::getAtomName(var, d_name) << "\n"; paren << ")))"; @@ -295,9 +316,9 @@ void LFSCCnfProof::printCnfProofForClause(ClauseId id, // paren << "))"; // return; - + Assert( clause->size()>0 ); - + Node base_assertion = getDefinitionForClause(id); //get the assertion for the clause id @@ -357,19 +378,19 @@ void LFSCCnfProof::printCnfProofForClause(ClauseId id, std::stringstream os_paren; //eliminate each one for (int j = base_assertion.getNumChildren()-2; j >= 0; j--) { + Trace("cnf-pf-debug") << "; base_assertion[" << j << "] is: " << base_assertion[j] + << ", and its kind is: " << base_assertion[j].getKind() << std::endl ; + Node child_base = base_assertion[j].getKind()==kind::NOT ? base_assertion[j][0] : base_assertion[j]; bool child_pol = base_assertion[j].getKind()!=kind::NOT; - - if( j==0 && base_assertion.getKind()==kind::IMPLIES ){ - child_pol = !child_pol; - } - + Trace("cnf-pf-debug") << "; child " << j << " " - << child_base << " " - << child_pol << " " - << childPol[child_base] << std::endl; - + << ", child base: " << child_base + << ", child pol: " << child_pol + << ", childPol[child_base] " + << childPol[child_base] << ", base pol: " << base_pol << std::endl; + std::map< Node, unsigned >::iterator itcic = childIndex.find( child_base ); if( itcic!=childIndex.end() ){ @@ -377,7 +398,13 @@ void LFSCCnfProof::printCnfProofForClause(ClauseId id, os_main << "(or_elim_1 _ _ "; prop::SatLiteral lit = (*clause)[itcic->second]; // Should be if in the original formula it was negated - if( childPol[child_base] && base_pol ){ + // if( childPol[child_base] && base_pol ){ + + // Adding the below to catch a specific case where the first child of an IMPLIES is negative, + // in which case we need not_not introduction. + if (base_assertion.getKind() == kind::IMPLIES && !child_pol && base_pol) { + os_main << "(not_not_intro _ " << ProofManager::getLitName(lit, d_name) << ") "; + } else if (childPol[child_base] && base_pol) { os_main << ProofManager::getLitName(lit, d_name) << " "; }else{ os_main << "(not_not_intro _ " << ProofManager::getLitName(lit, d_name) << ") "; @@ -391,6 +418,7 @@ void LFSCCnfProof::printCnfProofForClause(ClauseId id, success = false; } } + if( success ){ if( base_assertion.getKind()==kind::IMPLIES ){ os_main << "(impl_elim _ _ "; @@ -420,7 +448,7 @@ void LFSCCnfProof::printCnfProofForClause(ClauseId id, }else if ((base_assertion.getKind()==kind::AND && base_pol) || ((base_assertion.getKind()==kind::OR || base_assertion.getKind()==kind::IMPLIES) && !base_pol)) { - + std::stringstream os_main; Node iatom; @@ -431,7 +459,7 @@ void LFSCCnfProof::printCnfProofForClause(ClauseId id, Assert( assertion.getNumChildren()==1 ); iatom = assertion[0]; } - + Trace("cnf-pf") << "; and/or case 2, iatom = " << iatom << std::endl; Node e_base = iatom.getKind()==kind::NOT ? iatom[0] : iatom; bool e_pol = iatom.getKind()!=kind::NOT; @@ -729,6 +757,4 @@ bool LFSCCnfProof::printProofTopLevel(Node e, std::ostream& out) { } } - - } /* CVC4 namespace */ diff --git a/src/proof/cnf_proof.h b/src/proof/cnf_proof.h index 675bd9b9d..a21cb1c0e 100644 --- a/src/proof/cnf_proof.h +++ b/src/proof/cnf_proof.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cnf_proof.h ** \verbatim - ** Original author: Liana Hadarean - ** Major contributors: Morgan Deters, Andrew Reynolds - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Liana Hadarean, Guy Katz, 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 manager for CnfProofs. ** @@ -21,14 +21,13 @@ #ifndef __CVC4__CNF_PROOF_H #define __CVC4__CNF_PROOF_H -#include <ext/hash_map> +#include <ext/hash_map> #include <ext/hash_set> #include <iosfwd> #include "context/cdhashmap.h" +#include "proof/clause_id.h" #include "proof/sat_proof.h" -#include "proof/sat_proof.h" -#include "util/proof.h" #include "util/proof.h" namespace CVC4 { @@ -44,6 +43,7 @@ typedef __gnu_cxx::hash_set<ClauseId> ClauseIdSet; typedef context::CDHashMap<ClauseId, Node> ClauseIdToNode; typedef context::CDHashMap<Node, ProofRule, NodeHashFunction> NodeToProofRule; +typedef context::CDHashMap<ClauseId, theory::TheoryId> ClauseIdToTheory; class CnfProof { protected: @@ -55,28 +55,33 @@ protected: /** Map from assertion to reason for adding assertion **/ NodeToProofRule d_assertionToProofRule; + /** Map from assertion to the theory that added this assertion **/ + ClauseIdToTheory d_clauseIdToOwnerTheory; + + /** The last theory to explain a lemma **/ + theory::TheoryId d_explainerTheory; + /** Top of stack is assertion currently being converted to CNF **/ std::vector<Node> d_currentAssertionStack; /** Top of stack is top-level fact currently being converted to CNF **/ std::vector<Node> d_currentDefinitionStack; - /** Map from ClauseId to the top-level fact that lead to adding this clause **/ ClauseIdToNode d_clauseToDefinition; /** Top-level facts that follow from assertions during convertAndAssert **/ NodeSet d_definitions; - + /** Map from top-level fact to facts/assertion that it follows from **/ NodeToNode d_cnfDeps; ClauseIdSet d_explanations; - + bool isDefinition(Node node); Node getDefinitionForClause(ClauseId clause); - + std::string d_name; public: CnfProof(CVC4::prop::CnfStream* cnfStream, @@ -104,10 +109,10 @@ public: /** Clause is one of the clauses defining top-level assertion node*/ void setClauseAssertion(ClauseId clause, Node node); - + void registerAssertion(Node assertion, ProofRule reason); void setCnfDependence(Node from, Node to); - + void pushCurrentAssertion(Node assertion); // the current assertion being converted void popCurrentAssertion(); Node getCurrentAssertion(); @@ -116,14 +121,18 @@ public: void popCurrentDefinition(); Node getCurrentDefinition(); - + void setExplainerTheory(theory::TheoryId theory); + theory::TheoryId getExplainerTheory(); + theory::TheoryId getOwnerTheory(ClauseId clause); + + void registerExplanationLemma(ClauseId clauseId); + // accessors for the leaf assertions that are being converted to CNF bool isAssertion(Node node); ProofRule getProofRule(Node assertion); ProofRule getProofRule(ClauseId clause); Node getAssertionForClause(ClauseId clause); - /** Virtual methods for printing things **/ virtual void printAtomMapping(const NodeSet& atoms, std::ostream& os, @@ -155,7 +164,7 @@ public: void printAtomMapping(const NodeSet& atoms, std::ostream& os, std::ostream& paren); - + void printClause(const prop::SatClause& clause, std::ostream& os, std::ostream& paren); diff --git a/src/proof/proof.h b/src/proof/proof.h index 97dad7150..af72ccfa8 100644 --- a/src/proof/proof.h +++ b/src/proof/proof.h @@ -1,13 +1,13 @@ /********************* */ /*! \file proof.h ** \verbatim - ** Original author: Liana Hadarean - ** Major contributors: Morgan Deters - ** 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 Proof macros ** diff --git a/src/proof/proof_manager.cpp b/src/proof/proof_manager.cpp index b90d589b8..a3689d746 100644 --- a/src/proof/proof_manager.cpp +++ b/src/proof/proof_manager.cpp @@ -1,34 +1,31 @@ /********************* */ /*! \file proof_manager.cpp ** \verbatim - ** Original author: Liana Hadarean - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): Andrew Reynolds + ** Top contributors (to current version): + ** Liana Hadarean, Guy Katz, 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 - ** - ** \brief [[ Add one-line brief description here ]] + ** Copyright (c) 2009-2016 by the authors listed in the file AUTHORS + ** in the top-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 "context/context.h" +**/ #include "proof/proof_manager.h" -#include "proof/cnf_proof.h" -#include "proof/theory_proof.h" + +#include "base/cvc4_assert.h" +#include "context/context.h" +#include "options/bv_options.h" #include "proof/bitvector_proof.h" +#include "proof/clause_id.h" +#include "proof/cnf_proof.h" #include "proof/proof_utils.h" #include "proof/sat_proof_implementation.h" -#include "options/bv_options.h" - -#include "util/proof.h" -#include "util/hash.h" - -#include "base/cvc4_assert.h" +#include "proof/theory_proof.h" #include "smt/smt_engine.h" #include "smt/smt_engine_scope.h" #include "smt_util/node_visitor.h" @@ -38,7 +35,8 @@ #include "theory/uf/equality_engine.h" #include "theory/uf/theory_uf.h" #include "theory/valuation.h" - +#include "util/hash.h" +#include "util/proof.h" namespace CVC4 { @@ -107,6 +105,7 @@ UFProof* ProofManager::getUfProof() { TheoryProof* pf = getTheoryProofEngine()->getTheoryProof(theory::THEORY_UF); return (UFProof*)pf; } + BitVectorProof* ProofManager::getBitVectorProof() { Assert (options::proof()); TheoryProof* pf = getTheoryProofEngine()->getTheoryProof(theory::THEORY_BV); @@ -119,6 +118,17 @@ ArrayProof* ProofManager::getArrayProof() { return (ArrayProof*)pf; } +ArithProof* ProofManager::getArithProof() { + Assert (options::proof()); + TheoryProof* pf = getTheoryProofEngine()->getTheoryProof(theory::THEORY_ARITH); + return (ArithProof*)pf; +} + +SkolemizationManager* ProofManager::getSkolemizationManager() { + Assert (options::proof()); + return &(currentPM()->d_skolemizationManager); +} + void ProofManager::initSatProof(Minisat::Solver* solver) { Assert (currentPM()->d_satProof == NULL); Assert(currentPM()->d_format == LFSC); @@ -212,14 +222,22 @@ std::string ProofManager::getLitName(TNode lit, return getLitName(currentPM()->d_cnfProof->getLiteral(lit), prefix); } -std::string ProofManager::sanitize(TNode var) { - Assert (var.isVar()); - std::string name = var.toString(); - std::replace(name.begin(), name.end(), ' ', '_'); +std::string ProofManager::sanitize(TNode node) { + Assert (node.isVar() || node.isConst()); + + std::string name = node.toString(); + if (node.isVar()) { + std::replace(name.begin(), name.end(), ' ', '_'); + } else if (node.isConst()) { + name.erase(std::remove(name.begin(), name.end(), '('), name.end()); + name.erase(std::remove(name.begin(), name.end(), ')'), name.end()); + name.erase(std::remove(name.begin(), name.end(), ' '), name.end()); + name = "const" + name; + } + return name; } - void ProofManager::traceDeps(TNode n) { Debug("cores") << "trace deps " << n << std::endl; if ((n.isConst() && n == NodeManager::currentNM()->mkConst<bool>(true)) || @@ -321,10 +339,51 @@ void LFSCProof::toStream(std::ostream& out) { d_satProof->collectClausesUsed(used_inputs, used_lemmas); + IdToSatClause::iterator it2; + Debug("pf::pm") << std::endl << "Used inputs: " << std::endl; + for (it2 = used_inputs.begin(); it2 != used_inputs.end(); ++it2) { + Debug("pf::pm") << "\t input = " << *(it2->second) << std::endl; + } + Debug("pf::pm") << std::endl; + + // Debug("pf::pm") << std::endl << "Used lemmas: " << std::endl; + // for (it2 = used_lemmas.begin(); it2 != used_lemmas.end(); ++it2) { + // Debug("pf::pm") << "\t lemma = " << *(it2->second) << std::endl; + // } + // Debug("pf::pm") << std::endl; + Debug("pf::pm") << std::endl << "Used lemmas: " << std::endl; + for (it2 = used_lemmas.begin(); it2 != used_lemmas.end(); ++it2) { + + std::vector<Expr> clause_expr; + for(unsigned i = 0; i < it2->second->size(); ++i) { + prop::SatLiteral lit = (*(it2->second))[i]; + Expr atom = d_cnfProof->getAtom(lit.getSatVariable()).toExpr(); + if (atom.isConst()) { + Assert (atom == utils::mkTrue()); + continue; + } + Expr expr_lit = lit.isNegated() ? atom.notExpr(): atom; + clause_expr.push_back(expr_lit); + } + + Debug("pf::pm") << "\t lemma " << it2->first << " = " << *(it2->second) << std::endl; + Debug("pf::pm") << "\t"; + for (unsigned i = 0; i < clause_expr.size(); ++i) { + Debug("pf::pm") << clause_expr[i] << " "; + } + Debug("pf::pm") << std::endl; + } + Debug("pf::pm") << std::endl; + // collecting assertions that lead to the clauses being asserted NodeSet used_assertions; d_cnfProof->collectAssertionsForClauses(used_inputs, used_assertions); + NodeSet::iterator it3; + Debug("pf::pm") << std::endl << "Used assertions: " << std::endl; + for (it3 = used_assertions.begin(); it3 != used_assertions.end(); ++it3) + Debug("pf::pm") << "\t assertion = " << *it3 << std::endl; + NodeSet atoms; // collects the atoms in the clauses d_cnfProof->collectAtomsForClauses(used_inputs, atoms); @@ -336,21 +395,25 @@ void LFSCProof::toStream(std::ostream& out) { utils::collectAtoms(*it, atoms); } - if (Debug.isOn("proof:pm")) { - // std::cout << NodeManager::currentNM(); - Debug("proof:pm") << "LFSCProof::Used assertions: "<< std::endl; - for(NodeSet::const_iterator it = used_assertions.begin(); it != used_assertions.end(); ++it) { - Debug("proof:pm") << " " << *it << std::endl; - } + NodeSet::iterator atomIt; + Debug("pf::pm") << std::endl << "Dumping atoms from lemmas, inputs and assertions: " << std::endl << std::endl; + for (atomIt = atoms.begin(); atomIt != atoms.end(); ++atomIt) { + Debug("pf::pm") << "\tAtom: " << *atomIt << std::endl; + + if (Debug.isOn("proof:pm")) { + // std::cout << NodeManager::currentNM(); + Debug("proof:pm") << "LFSCProof::Used assertions: "<< std::endl; + for(NodeSet::const_iterator it = used_assertions.begin(); it != used_assertions.end(); ++it) { + Debug("proof:pm") << " " << *it << std::endl; + } - Debug("proof:pm") << "LFSCProof::Used atoms: "<< std::endl; - for(NodeSet::const_iterator it = atoms.begin(); it != atoms.end(); ++it) { - Debug("proof:pm") << " " << *it << std::endl; + Debug("proof:pm") << "LFSCProof::Used atoms: "<< std::endl; + for(NodeSet::const_iterator it = atoms.begin(); it != atoms.end(); ++it) { + Debug("proof:pm") << " " << *it << std::endl; + } } } - - smt::SmtScope scope(d_smtEngine); std::ostringstream paren; out << "(check\n"; @@ -359,32 +422,55 @@ void LFSCProof::toStream(std::ostream& out) { // declare the theory atoms NodeSet::const_iterator it = atoms.begin(); NodeSet::const_iterator end = atoms.end(); + + Debug("pf::pm") << "LFSCProof::toStream: registering terms:" << std::endl; for(; it != end; ++it) { + Debug("pf::pm") << "\tTerm: " << (*it).toExpr() << std::endl; d_theoryProof->registerTerm((*it).toExpr()); } + + Debug("pf::pm") << std::endl << "Term registration done!" << std::endl << std::endl; + + Debug("pf::pm") << std::endl << "LFSCProof::toStream: starting to print assertions" << std::endl; + // print out all the original assertions + d_theoryProof->registerTermsFromAssertions(); + d_theoryProof->printSortDeclarations(out, paren); + d_theoryProof->printTermDeclarations(out, paren); d_theoryProof->printAssertions(out, paren); + Debug("pf::pm") << std::endl << "LFSCProof::toStream: print assertions DONE" << std::endl; - out << "(: (holds cln)\n"; + out << "(: (holds cln)\n\n"; + + // Have the theory proofs print deferred declarations, e.g. for skolem variables. + out << " ;; Printing deferred declarations \n"; + d_theoryProof->printDeferredDeclarations(out, paren); // print trust that input assertions are their preprocessed form printPreprocessedAssertions(used_assertions, out, paren); // print mapping between theory atoms and internal SAT variables + out << ";; Printing mapping from preprocessed assertions into atoms \n"; d_cnfProof->printAtomMapping(atoms, out, paren); + Debug("pf::pm") << std::endl << "Printing cnf proof for clauses" << std::endl; + IdToSatClause::const_iterator cl_it = used_inputs.begin(); // print CNF conversion proof for each clause for (; cl_it != used_inputs.end(); ++cl_it) { d_cnfProof->printCnfProofForClause(cl_it->first, cl_it->second, out, paren); } + Debug("pf::pm") << std::endl << "Printing cnf proof for clauses DONE" << std::endl; + // FIXME: for now assume all theory lemmas are in CNF form so // distinguish between them and inputs // print theory lemmas for resolution proof - d_theoryProof->printTheoryLemmas(used_lemmas, out, paren); + Debug("pf::pm") << "Proof manager: printing theory lemmas" << std::endl; + d_theoryProof->printTheoryLemmas(used_lemmas, out, paren); + Debug("pf::pm") << "Proof manager: printing theory lemmas DONE!" << std::endl; if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER && ProofManager::getBitVectorProof()) { // print actual resolution proof @@ -406,7 +492,7 @@ void LFSCProof::toStream(std::ostream& out) { void LFSCProof::printPreprocessedAssertions(const NodeSet& assertions, std::ostream& os, std::ostream& paren) { - os << " ;; Preprocessing \n"; + os << "\n ;; In the preprocessor we trust \n"; NodeSet::const_iterator it = assertions.begin(); NodeSet::const_iterator end = assertions.end(); @@ -422,11 +508,12 @@ void LFSCProof::printPreprocessedAssertions(const NodeSet& assertions, paren << "))"; } -} - + os << "\n"; +} //---from Morgan--- + bool ProofManager::hasOp(TNode n) const { return d_bops.find(n) != d_bops.end(); } @@ -438,16 +525,21 @@ Node ProofManager::lookupOp(TNode n) const { } Node ProofManager::mkOp(TNode n) { + Trace("mgd-pm-mkop") << "MkOp : " << n << " " << n.getKind() << std::endl; if(n.getKind() != kind::BUILTIN) { return n; } + Node& op = d_ops[n]; if(op.isNull()) { - Debug("mgd") << "making an op for " << n << "\n"; + Assert((n.getConst<Kind>() == kind::SELECT) || (n.getConst<Kind>() == kind::STORE)); + + Debug("mgd-pm-mkop") << "making an op for " << n << "\n"; + std::stringstream ss; ss << n; std::string s = ss.str(); - Debug("mgd") << " : " << s << std::endl; + Debug("mgd-pm-mkop") << " : " << s << std::endl; std::vector<TypeNode> v; v.push_back(NodeManager::currentNM()->integerType()); if(n.getConst<Kind>() == kind::SELECT) { @@ -459,44 +551,54 @@ Node ProofManager::mkOp(TNode n) { v.push_back(NodeManager::currentNM()->integerType()); } TypeNode type = NodeManager::currentNM()->mkFunctionType(v); + Debug("mgd-pm-mkop") << "typenode is: " << type << "\n"; op = NodeManager::currentNM()->mkSkolem(s, type, " ignore", NodeManager::SKOLEM_NO_NOTIFY); d_bops[op] = n; } + Debug("mgd-pm-mkop") << "returning the op: " << op << "\n"; return op; } //---end from Morgan--- +bool ProofManager::wasPrinted(const Type& type) const { + return d_printedTypes.find(type) != d_printedTypes.end(); +} + +void ProofManager::markPrinted(const Type& type) { + d_printedTypes.insert(type); +} + std::ostream& operator<<(std::ostream& out, CVC4::ProofRule k) { switch(k) { case RULE_GIVEN: - out << "RULE_GIVEN"; + out << "RULE_GIVEN"; break; case RULE_DERIVED: - out << "RULE_DERIVED"; + out << "RULE_DERIVED"; break; case RULE_RECONSTRUCT: - out << "RULE_RECONSTRUCT"; + out << "RULE_RECONSTRUCT"; break; case RULE_TRUST: - out << "RULE_TRUST"; + out << "RULE_TRUST"; break; case RULE_INVALID: - out << "RULE_INVALID"; + out << "RULE_INVALID"; break; case RULE_CONFLICT: - out << "RULE_CONFLICT"; + out << "RULE_CONFLICT"; break; case RULE_TSEITIN: - out << "RULE_TSEITIN"; + out << "RULE_TSEITIN"; break; case RULE_SPLIT: - out << "RULE_SPLIT"; + out << "RULE_SPLIT"; break; case RULE_ARRAYS_EXT: - out << "RULE_ARRAYS"; + out << "RULE_ARRAYS"; break; case RULE_ARRAYS_ROW: - out << "RULE_ARRAYS"; + out << "RULE_ARRAYS"; break; default: out << "ProofRule Unknown! [" << unsigned(k) << "]"; diff --git a/src/proof/proof_manager.h b/src/proof/proof_manager.h index 96c4e1d61..c74aac237 100644 --- a/src/proof/proof_manager.h +++ b/src/proof/proof_manager.h @@ -1,13 +1,13 @@ /********************* */ /*! \file proof_manager.h ** \verbatim - ** Original author: Liana Hadarean - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): Andrew Reynolds + ** Top contributors (to current version): + ** Liana Hadarean, 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 A manager for Proofs ** @@ -21,8 +21,11 @@ #include <iosfwd> #include <map> - +#include "proof/proof.h" +#include "proof/skolemization_manager.h" +#include "util/proof.h" #include "expr/node.h" +#include "proof/clause_id.h" #include "proof/proof.h" #include "theory/logic_info.h" #include "theory/substitutions.h" @@ -46,13 +49,12 @@ namespace prop { class SmtEngine; -typedef unsigned ClauseId; const ClauseId ClauseIdEmpty(-1); -const ClauseId ClauseIdUndef(-2); +const ClauseId ClauseIdUndef(-2); const ClauseId ClauseIdError(-3); class Proof; -template <class Solver> class TSatProof; +template <class Solver> class TSatProof; typedef TSatProof< CVC4::Minisat::Solver> CoreSatProof; class CnfProof; @@ -60,10 +62,11 @@ class RewriterProof; class TheoryProofEngine; class TheoryProof; class UFProof; +class ArithProof; class ArrayProof; class BitVectorProof; -template <class Solver> class LFSCSatProof; +template <class Solver> class LFSCSatProof; typedef LFSCSatProof< CVC4::Minisat::Solver> LFSCCoreSatProof; class LFSCCnfProof; @@ -74,7 +77,7 @@ class LFSCRewriterProof; template <class Solver> class ProofProxy; typedef ProofProxy< CVC4::Minisat::Solver> CoreProofProxy; -typedef ProofProxy< CVC4::BVMinisat::Solver> BVProofProxy; +typedef ProofProxy< CVC4::BVMinisat::Solver> BVProofProxy; namespace prop { typedef uint64_t SatVariable; @@ -96,8 +99,6 @@ typedef __gnu_cxx::hash_set<Node, NodeHashFunction > NodeSet; typedef __gnu_cxx::hash_map<Node, std::vector<Node>, NodeHashFunction > NodeToNodes; typedef std::hash_set<ClauseId> IdHashSet; -typedef unsigned ClauseId; - enum ProofRule { RULE_GIVEN, /* input assertion */ RULE_DERIVED, /* a "macro" rule */ @@ -107,7 +108,7 @@ enum ProofRule { RULE_CONFLICT, /* re-construct as a conflict */ RULE_TSEITIN, /* Tseitin CNF transformation */ RULE_SPLIT, /* A splitting lemma of the form a v ~ a*/ - + RULE_ARRAYS_EXT, /* arrays, extensional */ RULE_ARRAYS_ROW, /* arrays, read-over-write */ };/* enum ProofRules */ @@ -122,6 +123,8 @@ class ProofManager { ExprSet d_inputCoreFormulas; ExprSet d_outputCoreFormulas; + SkolemizationManager d_skolemizationManager; + int d_nextId; Proof* d_fullProof; @@ -131,6 +134,8 @@ class ProofManager { // trace dependences back to unsat core void traceDeps(TNode n); + std::set<Type> d_printedTypes; + protected: LogicInfo d_logic; @@ -155,6 +160,9 @@ public: static UFProof* getUfProof(); static BitVectorProof* getBitVectorProof(); static ArrayProof* getArrayProof(); + static ArithProof* getArithProof(); + + static SkolemizationManager *getSkolemizationManager(); // iterators over data shared by proofs typedef ExprSet::const_iterator assertions_iterator; @@ -165,17 +173,17 @@ public: } assertions_iterator end_assertions() const { return d_inputFormulas.end(); } size_t num_assertions() const { return d_inputFormulas.size(); } - + //---from Morgan--- Node mkOp(TNode n); Node lookupOp(TNode n) const; bool hasOp(TNode n) const; - + std::map<Node, Node> d_ops; std::map<Node, Node> d_bops; //---end from Morgan--- - - + + // variable prefixes static std::string getInputClauseName(ClauseId id, const std::string& prefix = ""); static std::string getLemmaClauseName(ClauseId id, const std::string& prefix = ""); @@ -183,7 +191,7 @@ public: static std::string getLearntClauseName(ClauseId id, const std::string& prefix = ""); static std::string getPreprocessedAssertionName(Node node, const std::string& prefix = ""); static std::string getAssertionName(Node node, const std::string& prefix = ""); - + static std::string getVarName(prop::SatVariable var, const std::string& prefix = ""); static std::string getAtomName(prop::SatVariable var, const std::string& prefix = ""); static std::string getAtomName(TNode atom, const std::string& prefix = ""); @@ -192,14 +200,13 @@ public: // for SMT variable names that have spaces and other things static std::string sanitize(TNode var); - - /** Add proof assertion - unlinke addCoreAssertion this is post definition expansion **/ + /** Add proof assertion - unlike addCoreAssertion this is post definition expansion **/ void addAssertion(Expr formula); - + /** Public unsat core methods **/ void addCoreAssertion(Expr formula); - + void addDependence(TNode n, TNode dep); void addUnsatCore(Expr formula); @@ -214,6 +221,9 @@ public: const std::string getLogic() const { return d_logic.getLogicString(); } LogicInfo & getLogicInfo() { return d_logic; } + void markPrinted(const Type& type); + bool wasPrinted(const Type& type) const; + };/* class ProofManager */ class LFSCProof : public Proof { diff --git a/src/proof/proof_utils.cpp b/src/proof/proof_utils.cpp index 47b8a235e..5b04c281d 100644 --- a/src/proof/proof_utils.cpp +++ b/src/proof/proof_utils.cpp @@ -1,18 +1,18 @@ /********************* */ /*! \file proof_utils.cpp -** \verbatim -** Original author: Liana Hadarean -** Major contributors: none -** Minor contributors (to current version): none -** This file is part of the CVC4 project. -** Copyright (c) 2009-2014 New York University and The University of Iowa -** See the file COPYING in the top-level source directory for licensing -** information.\endverbatim -** -** \brief [[ Add one-line brief description here ]] -** -** [[ Add lengthier description here ]] -** \todo document this file + ** \verbatim + ** Top contributors (to current version): + ** Liana Hadarean + ** 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 "proof/proof_utils.h" diff --git a/src/proof/proof_utils.h b/src/proof/proof_utils.h index c27fbe5c2..da10c33a0 100644 --- a/src/proof/proof_utils.h +++ b/src/proof/proof_utils.h @@ -1,18 +1,18 @@ /********************* */ /*! \file proof_utils.h -** \verbatim -** Original author: Liana Hadarean -** Major contributors: none -** Minor contributors (to current version): none -** This file is part of the CVC4 project. -** Copyright (c) 2009-2014 New York University and The University of Iowa -** See the file COPYING in the top-level source directory for licensing -** information.\endverbatim -** -** \brief [[ Add one-line brief description here ]] -** -** [[ Add lengthier description here ]] -** \todo document this file + ** \verbatim + ** Top contributors (to current version): + ** Liana Hadarean + ** 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 "cvc4_private.h" diff --git a/src/proof/sat_proof.h b/src/proof/sat_proof.h index cd42ab85b..d94b61bf3 100644 --- a/src/proof/sat_proof.h +++ b/src/proof/sat_proof.h @@ -1,13 +1,13 @@ /********************* */ /*! \file sat_proof.h ** \verbatim - ** Original author: Liana Hadarean - ** Major contributors: Morgan Deters - ** 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 Resolution proof ** @@ -20,21 +20,22 @@ #define __CVC4__SAT__PROOF_H #include <stdint.h> + #include <ext/hash_map> #include <ext/hash_set> #include <iosfwd> #include <set> #include <sstream> #include <vector> + #include "expr/expr.h" +#include "proof/clause_id.h" #include "proof/proof_manager.h" #include "util/proof.h" #include "util/statistics_registry.h" - namespace CVC4 { - class CnfProof; /** @@ -123,7 +124,7 @@ protected: VarSet d_assumptions; // assumption literals for bv solver IdHashSet d_assumptionConflicts; // assumption conflicts not actually added to SAT solver IdToConflicts d_assumptionConflictsDebug; - + // resolutions IdResMap d_resChains; ResStack d_resStack; @@ -240,13 +241,13 @@ public: ClauseId getTrueUnit() const; ClauseId getFalseUnit() const; - + void registerAssumption(const typename Solver::TVar var); ClauseId registerAssumptionConflict(const typename Solver::TLitVec& confl); - + ClauseId storeUnitConflict(typename Solver::TLit lit, ClauseKind kind); - + /** * Marks the deleted clauses as deleted. Note we may still use them in the final * resolution. @@ -296,12 +297,13 @@ public: virtual void printResolutionEmptyClause(std::ostream& out, std::ostream& paren) = 0; virtual void printAssumptionsResolution(ClauseId id, std::ostream& out, std::ostream& paren) = 0; - void collectClausesUsed(IdToSatClause& inputs, IdToSatClause& lemmas); void storeClauseGlue(ClauseId clause, int glue); + + private: __gnu_cxx::hash_map<ClauseId, int> d_glueMap; struct Statistics { @@ -320,7 +322,6 @@ private: Statistics d_statistics; };/* class TSatProof */ - template <class S> class ProofProxy { private: diff --git a/src/proof/sat_proof_implementation.h b/src/proof/sat_proof_implementation.h index 92645e105..e773e4b47 100644 --- a/src/proof/sat_proof_implementation.h +++ b/src/proof/sat_proof_implementation.h @@ -1,13 +1,13 @@ /********************* */ /*! \file sat_proof_implementation.h ** \verbatim - ** Original author: Liana Hadarean - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Liana Hadarean, Guy Katz, 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 Resolution proof ** @@ -19,30 +19,31 @@ #ifndef __CVC4__SAT__PROOF_IMPLEMENTATION_H #define __CVC4__SAT__PROOF_IMPLEMENTATION_H -#include "proof/sat_proof.h" +#include "proof/clause_id.h" #include "proof/cnf_proof.h" -#include "prop/minisat/minisat.h" +#include "proof/sat_proof.h" #include "prop/bvminisat/bvminisat.h" -#include "prop/minisat/core/Solver.h" #include "prop/bvminisat/core/Solver.h" +#include "prop/minisat/core/Solver.h" +#include "prop/minisat/minisat.h" #include "prop/sat_solver_types.h" #include "smt/smt_statistics_registry.h" namespace CVC4 { -template <class Solver> +template <class Solver> void printLit (typename Solver::TLit l) { Debug("proof:sat") << (sign(l) ? "-" : "") << var(l) + 1; } -template <class Solver> +template <class Solver> void printClause (typename Solver::TClause& c) { for (int i = 0; i < c.size(); i++) { Debug("proof:sat") << (sign(c[i]) ? "-" : "") << var(c[i]) + 1 << " "; } } -template <class Solver> +template <class Solver> void printClause (std::vector<typename Solver::TLit>& c) { for (unsigned i = 0; i < c.size(); i++) { Debug("proof:sat") << (sign(c[i]) ? "-" : "") << var(c[i]) + 1 << " "; @@ -50,7 +51,7 @@ void printClause (std::vector<typename Solver::TLit>& c) { } -template <class Solver> +template <class Solver> void printLitSet(const std::set<typename Solver::TLit>& s) { typename std::set < typename Solver::TLit>::const_iterator it = s.begin(); for(; it != s.end(); ++it) { @@ -61,11 +62,11 @@ void printLitSet(const std::set<typename Solver::TLit>& s) { } // purely debugging functions -template <class Solver> +template <class Solver> void printDebug (typename Solver::TLit l) { Debug("proof:sat") << (sign(l) ? "-" : "") << var(l) + 1 << std::endl; } -template <class Solver> +template <class Solver> void printDebug (typename Solver::TClause& c) { for (int i = 0; i < c.size(); i++) { Debug("proof:sat") << (sign(c[i]) ? "-" : "") << var(c[i]) + 1 << " "; @@ -80,7 +81,7 @@ void printDebug (typename Solver::TClause& c) { * @param id the clause id * @param set the clause converted to a set of literals */ -template <class Solver> +template <class Solver> void TSatProof<Solver>::createLitSet(ClauseId id, LitSet& set) { Assert(set.empty()); if(isUnit(id)) { @@ -94,11 +95,11 @@ void TSatProof<Solver>::createLitSet(ClauseId id, LitSet& set) { if (d_assumptionConflictsDebug.find(id) != d_assumptionConflictsDebug.end()) { LitVector* clause = d_assumptionConflictsDebug[id]; for (unsigned i = 0; i < clause->size(); ++i) { - set.insert(clause->operator[](i)); + set.insert(clause->operator[](i)); } return; } - + typename Solver::TCRef ref = getClauseRef(id); typename Solver::TClause& c = getClause(ref); for (int i = 0; i < c.size(); i++) { @@ -114,7 +115,7 @@ void TSatProof<Solver>::createLitSet(ClauseId id, LitSet& set) { * @param clause1 * @param clause2 */ -template <class Solver> +template <class Solver> bool resolve(const typename Solver::TLit v, std::set<typename Solver::TLit>& clause1, std::set<typename Solver::TLit>& clause2, bool s) { @@ -133,7 +134,7 @@ bool resolve(const typename Solver::TLit v, } clause1.erase(var); clause2.erase(~var); - typename std::set<typename Solver::TLit>::iterator it = clause2.begin(); + typename std::set<typename Solver::TLit>::iterator it = clause2.begin(); for (; it!= clause2.end(); ++it) { clause1.insert(*it); } @@ -149,7 +150,7 @@ bool resolve(const typename Solver::TLit v, } clause1.erase(~var); clause2.erase(var); - typename std::set<typename Solver::TLit>::iterator it = clause2.begin(); + typename std::set<typename Solver::TLit>::iterator it = clause2.begin(); for (; it!= clause2.end(); ++it) { clause1.insert(*it); } @@ -158,19 +159,19 @@ bool resolve(const typename Solver::TLit v, } /// ResChain -template <class Solver> +template <class Solver> ResChain<Solver>::ResChain(ClauseId start) : d_start(start), d_steps(), d_redundantLits(NULL) {} -template <class Solver> +template <class Solver> void ResChain<Solver>::addStep(typename Solver::TLit lit, ClauseId id, bool sign) { ResStep<Solver> step(lit, id, sign); d_steps.push_back(step); } -template <class Solver> +template <class Solver> void ResChain<Solver>::addRedundantLit(typename Solver::TLit lit) { if (d_redundantLits) { d_redundantLits->insert(lit); @@ -182,19 +183,19 @@ void ResChain<Solver>::addRedundantLit(typename Solver::TLit lit) { /// ProxyProof -template <class Solver> +template <class Solver> ProofProxy<Solver>::ProofProxy(TSatProof<Solver>* proof): d_proof(proof) {} -template <class Solver> +template <class Solver> void ProofProxy<Solver>::updateCRef(typename Solver::TCRef oldref, typename Solver::TCRef newref) { d_proof->updateCRef(oldref, newref); } /// SatProof -template <class Solver> +template <class Solver> TSatProof<Solver>::TSatProof(Solver* solver, const std::string& name, bool checkRes) : d_solver(solver) , d_cnfProof(NULL) @@ -217,7 +218,7 @@ TSatProof<Solver>::TSatProof(Solver* solver, const std::string& name, bool check , d_unitConflictId() , d_storedUnitConflict(false) , d_trueLit(ClauseIdUndef) - , d_falseLit(ClauseIdUndef) + , d_falseLit(ClauseIdUndef) , d_name(name) , d_seenLearnt() , d_seenInputs() @@ -227,10 +228,10 @@ TSatProof<Solver>::TSatProof(Solver* solver, const std::string& name, bool check d_proxy = new ProofProxy<Solver>(this); } -template <class Solver> +template <class Solver> TSatProof<Solver>::~TSatProof() { delete d_proxy; - + // FIXME: double free if deleted clause also appears in d_seenLemmas? IdToSatClause::iterator it = d_deletedTheoryLemmas.begin(); IdToSatClause::iterator end = d_deletedTheoryLemmas.end(); @@ -256,8 +257,8 @@ TSatProof<Solver>::~TSatProof() { delete seen_it->second; } } - -template <class Solver> + +template <class Solver> void TSatProof<Solver>::setCnfProof(CnfProof* cnf_proof) { Assert (d_cnfProof == NULL); d_cnfProof = cnf_proof; @@ -270,7 +271,7 @@ void TSatProof<Solver>::setCnfProof(CnfProof* cnf_proof) { * * @return */ -template <class Solver> +template <class Solver> bool TSatProof<Solver>::checkResolution(ClauseId id) { if(d_checkRes) { bool validRes = true; @@ -299,9 +300,9 @@ bool TSatProof<Solver>::checkResolution(ClauseId id) { if (id == d_emptyClauseId) { return clause1.empty(); } - + LitVector c; - getLitVec(id, c); + getLitVec(id, c); for (unsigned i = 0; i < c.size(); ++i) { int count = clause1.erase(c[i]); @@ -334,7 +335,7 @@ bool TSatProof<Solver>::checkResolution(ClauseId id) { /// helper methods -template <class Solver> +template <class Solver> ClauseId TSatProof<Solver>::getClauseId(typename Solver::TCRef ref) { if(d_clauseId.find(ref) == d_clauseId.end()) { Debug("proof:sat") << "Missing clause \n"; @@ -343,12 +344,12 @@ ClauseId TSatProof<Solver>::getClauseId(typename Solver::TCRef ref) { return d_clauseId[ref]; } -template <class Solver> +template <class Solver> ClauseId TSatProof<Solver>::getClauseId(typename Solver::TLit lit) { Assert(d_unitId.find(toInt(lit)) != d_unitId.end()); return d_unitId[toInt(lit)]; } -template <class Solver> +template <class Solver> typename Solver::TCRef TSatProof<Solver>::getClauseRef(ClauseId id) { if (d_idClause.find(id) == d_idClause.end()) { Debug("proof:sat") << "proof:getClauseRef cannot find clause "<<id<<" " @@ -359,19 +360,19 @@ typename Solver::TCRef TSatProof<Solver>::getClauseRef(ClauseId id) { return d_idClause[id]; } -template <class Solver> +template <class Solver> typename Solver::TClause& TSatProof<Solver>::getClause(typename Solver::TCRef ref) { Assert(ref != Solver::TCRef_Undef); Assert(ref >= 0 && ref < d_solver->ca.size()); return d_solver->ca[ref]; } -template <class Solver> +template <class Solver> void TSatProof<Solver>::getLitVec(ClauseId id, LitVector& vec) { if (isUnit(id)) { typename Solver::TLit lit = getUnit(id); vec.push_back(lit); - return; + return; } if (isAssumptionConflict(id)) { vec = *(d_assumptionConflictsDebug[id]); @@ -385,44 +386,44 @@ void TSatProof<Solver>::getLitVec(ClauseId id, LitVector& vec) { } -template <class Solver> +template <class Solver> typename Solver::TLit TSatProof<Solver>::getUnit(ClauseId id) { Assert(d_idUnit.find(id) != d_idUnit.end()); return d_idUnit[id]; } -template <class Solver> +template <class Solver> bool TSatProof<Solver>::isUnit(ClauseId id) { return d_idUnit.find(id) != d_idUnit.end(); } -template <class Solver> +template <class Solver> bool TSatProof<Solver>::isUnit(typename Solver::TLit lit) { return d_unitId.find(toInt(lit)) != d_unitId.end(); } -template <class Solver> +template <class Solver> ClauseId TSatProof<Solver>::getUnitId(typename Solver::TLit lit) { Assert(isUnit(lit)); return d_unitId[toInt(lit)]; } -template <class Solver> +template <class Solver> bool TSatProof<Solver>::hasResolution(ClauseId id) { return d_resChains.find(id) != d_resChains.end(); } -template <class Solver> +template <class Solver> bool TSatProof<Solver>::isInputClause(ClauseId id) { return (d_inputClauses.find(id) != d_inputClauses.end()); } -template <class Solver> +template <class Solver> bool TSatProof<Solver>::isLemmaClause(ClauseId id) { return (d_lemmaClauses.find(id) != d_lemmaClauses.end()); } -template <class Solver> +template <class Solver> bool TSatProof<Solver>::isAssumptionConflict(ClauseId id) { return d_assumptionConflicts.find(id) != d_assumptionConflicts.end(); } -template <class Solver> +template <class Solver> void TSatProof<Solver>::print(ClauseId id) { if (d_deleted.find(id) != d_deleted.end()) { Debug("proof:sat") << "del"<<id; @@ -436,13 +437,13 @@ void TSatProof<Solver>::print(ClauseId id) { printClause<Solver>(getClause(ref)); } } -template <class Solver> +template <class Solver> void TSatProof<Solver>::printRes(ClauseId id) { Assert(hasResolution(id)); Debug("proof:sat") << "id "<< id <<": "; printRes(d_resChains[id]); } -template <class Solver> +template <class Solver> void TSatProof<Solver>::printRes(ResChain<Solver>* res) { ClauseId start_id = res->getStart(); @@ -467,14 +468,14 @@ void TSatProof<Solver>::printRes(ResChain<Solver>* res) { } /// registration methods -template <class Solver> +template <class Solver> ClauseId TSatProof<Solver>::registerClause(typename Solver::TCRef clause, ClauseKind kind) { Assert(clause != Solver::TCRef_Undef); typename ClauseIdMap::iterator it = d_clauseId.find(clause); if (it == d_clauseId.end()) { ClauseId newId = ProofManager::currentPM()->nextId(); - d_clauseId.insert(std::make_pair(clause, newId)); + d_clauseId.insert(std::make_pair(clause, newId)); d_idClause.insert(std::make_pair(newId, clause)); if (kind == INPUT) { Assert(d_inputClauses.find(newId) == d_inputClauses.end()); @@ -483,6 +484,11 @@ template <class Solver> if (kind == THEORY_LEMMA) { Assert(d_lemmaClauses.find(newId) == d_lemmaClauses.end()); d_lemmaClauses.insert(newId); + Debug("pf::sat") << "TSatProof::registerClause registering a new lemma clause: " + << newId << " = " << *buildClause(newId) + << ". Explainer theory: " << d_cnfProof->getExplainerTheory() + << std::endl; + d_cnfProof->registerExplanationLemma(newId); } } @@ -496,7 +502,7 @@ template <class Solver> return id; } -template <class Solver> +template <class Solver> ClauseId TSatProof<Solver>::registerUnitClause(typename Solver::TLit lit, ClauseKind kind) { Debug("cores") << "registerUnitClause " << kind << std::endl; @@ -512,49 +518,54 @@ ClauseId TSatProof<Solver>::registerUnitClause(typename Solver::TLit lit, } if (kind == THEORY_LEMMA) { Assert(d_lemmaClauses.find(newId) == d_lemmaClauses.end()); + Debug("pf::sat") << "TSatProof::registerUnitClause: registering a new lemma (UNIT CLAUSE): " + << lit + << ". Explainer theory: " << d_cnfProof->getExplainerTheory() + << std::endl; d_lemmaClauses.insert(newId); + d_cnfProof->registerExplanationLemma(newId); } } ClauseId id = d_unitId[toInt(lit)]; Assert(kind != INPUT || d_inputClauses.count(id)); Assert(kind != THEORY_LEMMA || d_lemmaClauses.count(id)); - Debug("proof:sat:detailed") << "registerUnitClause id: " << id + Debug("proof:sat:detailed") << "registerUnitClause id: " << id <<" kind: " << kind << "\n"; // ProofManager::currentPM()->setRegisteredClauseId( d_unitId[toInt(lit)] ); return id; } -template <class Solver> +template <class Solver> void TSatProof<Solver>::registerTrueLit(const typename Solver::TLit lit) { Assert (d_trueLit == ClauseIdUndef); d_trueLit = registerUnitClause(lit, INPUT); } -template <class Solver> +template <class Solver> void TSatProof<Solver>::registerFalseLit(const typename Solver::TLit lit) { Assert (d_falseLit == ClauseIdUndef); d_falseLit = registerUnitClause(lit, INPUT); } -template <class Solver> +template <class Solver> ClauseId TSatProof<Solver>::getTrueUnit() const { Assert (d_trueLit != ClauseIdUndef); return d_trueLit; } -template <class Solver> +template <class Solver> ClauseId TSatProof<Solver>::getFalseUnit() const { Assert (d_falseLit != ClauseIdUndef); return d_falseLit; } -template <class Solver> +template <class Solver> void TSatProof<Solver>::registerAssumption(const typename Solver::TVar var) { Assert (d_assumptions.find(var) == d_assumptions.end()); d_assumptions.insert(var); } -template <class Solver> +template <class Solver> ClauseId TSatProof<Solver>::registerAssumptionConflict(const typename Solver::TLitVec& confl) { Debug("proof:sat:detailed") << "registerAssumptionConflict " << std::endl; // Uniqueness is checked in the bit-vector proof @@ -564,13 +575,13 @@ ClauseId TSatProof<Solver>::registerAssumptionConflict(const typename Solver::TL } ClauseId new_id = ProofManager::currentPM()->nextId(); d_assumptionConflicts.insert(new_id); - LitVector* vec_confl = new LitVector(confl.size()); + LitVector* vec_confl = new LitVector(confl.size()); for (int i = 0; i < confl.size(); ++i) { vec_confl->operator[](i) = confl[i]; } if (Debug.isOn("proof:sat:detailed")) { printClause<Solver>(*vec_confl); - Debug("proof:sat:detailed") << "\n"; + Debug("proof:sat:detailed") << "\n"; } d_assumptionConflictsDebug[new_id] = vec_confl; @@ -578,7 +589,7 @@ ClauseId TSatProof<Solver>::registerAssumptionConflict(const typename Solver::TL } -template <class Solver> +template <class Solver> void TSatProof<Solver>::removedDfs(typename Solver::TLit lit, LitSet* removedSet, LitVector& removeStack, LitSet& inClause, LitSet& seen) { // if we already added the literal return if (seen.count(lit)) { @@ -605,7 +616,7 @@ void TSatProof<Solver>::removedDfs(typename Solver::TLit lit, LitSet* removedSet } } -template <class Solver> +template <class Solver> void TSatProof<Solver>::removeRedundantFromRes(ResChain<Solver>* res, ClauseId id) { LitSet* removed = res->getRedundant(); if (removed == NULL) { @@ -636,8 +647,8 @@ void TSatProof<Solver>::removeRedundantFromRes(ResChain<Solver>* res, ClauseId i } removed->clear(); } - -template <class Solver> + +template <class Solver> void TSatProof<Solver>::registerResolution(ClauseId id, ResChain<Solver>* res) { Assert(res != NULL); @@ -661,14 +672,14 @@ void TSatProof<Solver>::registerResolution(ClauseId id, ResChain<Solver>* res) { /// recording resolutions -template <class Solver> +template <class Solver> void TSatProof<Solver>::startResChain(typename Solver::TCRef start) { ClauseId id = getClauseId(start); ResChain<Solver>* res = new ResChain<Solver>(id); d_resStack.push_back(res); } -template <class Solver> +template <class Solver> void TSatProof<Solver>::startResChain(typename Solver::TLit start) { ClauseId id = getUnitId(start); ResChain<Solver>* res = new ResChain<Solver>(id); @@ -676,7 +687,7 @@ void TSatProof<Solver>::startResChain(typename Solver::TLit start) { } -template <class Solver> +template <class Solver> void TSatProof<Solver>::addResolutionStep(typename Solver::TLit lit, typename Solver::TCRef clause, bool sign) { ClauseId id = registerClause(clause, LEARNT); @@ -684,7 +695,7 @@ void TSatProof<Solver>::addResolutionStep(typename Solver::TLit lit, res->addStep(lit, id, sign); } -template <class Solver> +template <class Solver> void TSatProof<Solver>::endResChain(ClauseId id) { Debug("proof:sat:detailed") <<"endResChain " << id << "\n"; Assert(d_resStack.size() > 0); @@ -694,7 +705,7 @@ void TSatProof<Solver>::endResChain(ClauseId id) { } -// template <class Solver> +// template <class Solver> // void TSatProof<Solver>::endResChain(typename Solver::TCRef clause) { // Assert(d_resStack.size() > 0); // ClauseId id = registerClause(clause, LEARNT); @@ -703,7 +714,7 @@ void TSatProof<Solver>::endResChain(ClauseId id) { // d_resStack.pop_back(); // } -template <class Solver> +template <class Solver> void TSatProof<Solver>::endResChain(typename Solver::TLit lit) { Assert(d_resStack.size() > 0); ClauseId id = registerUnitClause(lit, LEARNT); @@ -715,14 +726,14 @@ void TSatProof<Solver>::endResChain(typename Solver::TLit lit) { } -template <class Solver> +template <class Solver> void TSatProof<Solver>::cancelResChain() { Assert(d_resStack.size() > 0); d_resStack.pop_back(); } -template <class Solver> +template <class Solver> void TSatProof<Solver>::storeLitRedundant(typename Solver::TLit lit) { Assert(d_resStack.size() > 0); ResChain<Solver>* res = d_resStack.back(); @@ -730,18 +741,18 @@ void TSatProof<Solver>::storeLitRedundant(typename Solver::TLit lit) { } /// constructing resolutions -template <class Solver> +template <class Solver> void TSatProof<Solver>::resolveOutUnit(typename Solver::TLit lit) { ClauseId id = resolveUnit(~lit); ResChain<Solver>* res = d_resStack.back(); res->addStep(lit, id, !sign(lit)); } -template <class Solver> +template <class Solver> void TSatProof<Solver>::storeUnitResolution(typename Solver::TLit lit) { Debug("cores") << "STORE UNIT RESOLUTION" << std::endl; resolveUnit(lit); } -template <class Solver> +template <class Solver> ClauseId TSatProof<Solver>::resolveUnit(typename Solver::TLit lit) { // first check if we already have a resolution for lit if(isUnit(lit)) { @@ -771,12 +782,12 @@ ClauseId TSatProof<Solver>::resolveUnit(typename Solver::TLit lit) { registerResolution(unit_id, res); return unit_id; } -template <class Solver> +template <class Solver> void TSatProof<Solver>::toStream(std::ostream& out) { Debug("proof:sat") << "TSatProof<Solver>::printProof\n"; Unimplemented("native proof printing not supported yet"); } -template <class Solver> +template <class Solver> ClauseId TSatProof<Solver>::storeUnitConflict(typename Solver::TLit conflict_lit, ClauseKind kind) { Debug("cores") << "STORE UNIT CONFLICT" << std::endl; @@ -786,7 +797,7 @@ ClauseId TSatProof<Solver>::storeUnitConflict(typename Solver::TLit conflict_lit Debug("proof:sat:detailed") <<"storeUnitConflict " << d_unitConflictId << "\n"; return d_unitConflictId; } -template <class Solver> +template <class Solver> void TSatProof<Solver>::finalizeProof(typename Solver::TCRef conflict_ref) { Assert(d_resStack.size() == 0); Assert(conflict_ref != Solver::TCRef_Undef); @@ -828,7 +839,7 @@ void TSatProof<Solver>::finalizeProof(typename Solver::TCRef conflict_ref) { } /// CRef manager -template <class Solver> +template <class Solver> void TSatProof<Solver>::updateCRef(typename Solver::TCRef oldref, typename Solver::TCRef newref) { if (d_clauseId.find(oldref) == d_clauseId.end()) { @@ -840,7 +851,7 @@ void TSatProof<Solver>::updateCRef(typename Solver::TCRef oldref, d_temp_clauseId[newref] = id; d_temp_idClause[id] = newref; } -template <class Solver> +template <class Solver> void TSatProof<Solver>::finishUpdateCRef() { d_clauseId.swap(d_temp_clauseId); d_temp_clauseId.clear(); @@ -848,7 +859,7 @@ void TSatProof<Solver>::finishUpdateCRef() { d_idClause.swap(d_temp_idClause); d_temp_idClause.clear(); } -template <class Solver> +template <class Solver> void TSatProof<Solver>::markDeleted(typename Solver::TCRef clause) { if (d_clauseId.find(clause) != d_clauseId.end()) { ClauseId id = getClauseId(clause); @@ -866,18 +877,18 @@ void TSatProof<Solver>::markDeleted(typename Solver::TCRef clause) { // template<> // void toSatClause< ::BVMinisat::Solver> (const BVMinisat::Solver::TClause& minisat_cl, // prop::SatClause& sat_cl) { - + // prop::BVMinisatSatSolver::toSatClause(minisat_cl, sat_cl); // } -template <class Solver> +template <class Solver> void TSatProof<Solver>::constructProof(ClauseId conflict) { collectClauses(conflict); } -template <class Solver> +template <class Solver> std::string TSatProof<Solver>::clauseName(ClauseId id) { std::ostringstream os; if (isInputClause(id)) { @@ -893,7 +904,7 @@ std::string TSatProof<Solver>::clauseName(ClauseId id) { } } -template <class Solver> +template <class Solver> prop::SatClause* TSatProof<Solver>::buildClause(ClauseId id) { if (isUnit(id)) { typename Solver::TLit lit = getUnit(id); @@ -915,7 +926,7 @@ prop::SatClause* TSatProof<Solver>::buildClause(ClauseId id) { return clause; } -template <class Solver> +template <class Solver> void TSatProof<Solver>::collectClauses(ClauseId id) { if (d_seenInputs.find(id) != d_seenInputs.end() || d_seenLemmas.find(id) != d_seenLemmas.end() || @@ -948,7 +959,7 @@ void TSatProof<Solver>::collectClauses(ClauseId id) { } } -template <class Solver> +template <class Solver> void TSatProof<Solver>::collectClausesUsed(IdToSatClause& inputs, IdToSatClause& lemmas) { inputs = d_seenInputs; @@ -959,13 +970,13 @@ void TSatProof<Solver>::collectClausesUsed(IdToSatClause& inputs, ); } -template <class Solver> +template <class Solver> void TSatProof<Solver>::storeClauseGlue(ClauseId clause, int glue) { Assert (d_glueMap.find(clause) == d_glueMap.end()); d_glueMap.insert(std::make_pair(clause, glue)); } -template <class Solver> +template <class Solver> TSatProof<Solver>::Statistics::Statistics(const std::string& prefix) : d_numLearnedClauses("satproof::"+prefix+"::NumLearnedClauses", 0) , d_numLearnedInProof("satproof::"+prefix+"::NumLearnedInProof", 0) @@ -985,7 +996,7 @@ TSatProof<Solver>::Statistics::Statistics(const std::string& prefix) smtStatisticsRegistry()->registerStat(&d_usedClauseGlue); } -template <class Solver> +template <class Solver> TSatProof<Solver>::Statistics::~Statistics() { smtStatisticsRegistry()->unregisterStat(&d_numLearnedClauses); smtStatisticsRegistry()->unregisterStat(&d_numLearnedInProof); @@ -999,7 +1010,7 @@ TSatProof<Solver>::Statistics::~Statistics() { /// LFSCSatProof class -template <class Solver> +template <class Solver> void LFSCSatProof<Solver>::printResolution(ClauseId id, std::ostream& out, std::ostream& paren) { out << "(satlem_simplify _ _ _ "; @@ -1029,7 +1040,7 @@ void LFSCSatProof<Solver>::printResolution(ClauseId id, std::ostream& out, std:: } /// LFSCSatProof class -template <class Solver> +template <class Solver> void LFSCSatProof<Solver>::printAssumptionsResolution(ClauseId id, std::ostream& out, std::ostream& paren) { Assert (this->isAssumptionConflict(id)); // print the resolution proving the assumption conflict @@ -1037,7 +1048,7 @@ void LFSCSatProof<Solver>::printAssumptionsResolution(ClauseId id, std::ostream& // resolve out assumptions to prove empty clause out << "(satlem_simplify _ _ _ "; std::vector<typename Solver::TLit>& confl = *(this->d_assumptionConflictsDebug[id]); - + Assert (confl.size()); for (unsigned i = 0; i < confl.size(); ++i) { @@ -1045,8 +1056,8 @@ void LFSCSatProof<Solver>::printAssumptionsResolution(ClauseId id, std::ostream& out <<"("; out << (lit.isNegated() ? "Q" : "R") <<" _ _ "; } - - out << this->clauseName(id)<< " "; + + out << this->clauseName(id)<< " "; for (int i = confl.size() - 1; i >= 0; --i) { prop::SatLiteral lit = toSatLiteral<Solver>(confl[i]); prop::SatVariable v = lit.getSatVariable(); @@ -1073,20 +1084,20 @@ void LFSCSatProof<Solver>::printResolutions(std::ostream& out, std::ostream& par template <class Solver> void LFSCSatProof<Solver>::printResolutionEmptyClause(std::ostream& out, std::ostream& paren) { - printResolution(this->d_emptyClauseId, out, paren); + printResolution(this->d_emptyClauseId, out, paren); } inline std::ostream& operator<<(std::ostream& out, CVC4::ClauseKind k) { switch(k) { case CVC4::INPUT: - out << "INPUT"; + out << "INPUT"; break; case CVC4::THEORY_LEMMA: - out << "THEORY_LEMMA"; + out << "THEORY_LEMMA"; break; case CVC4::LEARNT: - out << "LEARNT"; + out << "LEARNT"; break; default: out << "ClauseKind Unknown! [" << unsigned(k) << "]"; diff --git a/src/proof/skolemization_manager.cpp b/src/proof/skolemization_manager.cpp new file mode 100644 index 000000000..12fea82ad --- /dev/null +++ b/src/proof/skolemization_manager.cpp @@ -0,0 +1,68 @@ +/********************* */ +/*! \file skolemization_manager.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 "proof/skolemization_manager.h" + +namespace CVC4 { + +void SkolemizationManager::registerSkolem(Node disequality, Node skolem) { + Debug("pf::pm") << "SkolemizationManager: registerSkolem: disequality = " << disequality << ", skolem = " << skolem << std::endl; + + if (isSkolem(skolem)) { + Assert(d_skolemToDisequality[skolem] == disequality); + return; + } + + d_disequalityToSkolem[disequality] = skolem; + d_skolemToDisequality[skolem] = disequality; +} + +bool SkolemizationManager::hasSkolem(Node disequality) { + return (d_disequalityToSkolem.find(disequality) != d_disequalityToSkolem.end()); +} + +Node SkolemizationManager::getSkolem(Node disequality) { + Debug("pf::pm") << "SkolemizationManager: getSkolem( "; + Assert (d_disequalityToSkolem.find(disequality) != d_disequalityToSkolem.end()); + Debug("pf::pm") << disequality << " ) = " << d_disequalityToSkolem[disequality] << std::endl; + return d_disequalityToSkolem[disequality]; +} + +Node SkolemizationManager::getDisequality(Node skolem) { + Assert (d_skolemToDisequality.find(skolem) != d_skolemToDisequality.end()); + return d_skolemToDisequality[skolem]; +} + +bool SkolemizationManager::isSkolem(Node skolem) { + return (d_skolemToDisequality.find(skolem) != d_skolemToDisequality.end()); +} + +void SkolemizationManager::clear() { + Debug("pf::pm") << "SkolemizationManager: clear" << std::endl; + d_disequalityToSkolem.clear(); + d_skolemToDisequality.clear(); +} + +std::hash_map<Node, Node, NodeHashFunction>::const_iterator SkolemizationManager::begin() { + return d_disequalityToSkolem.begin(); +} + +std::hash_map<Node, Node, NodeHashFunction>::const_iterator SkolemizationManager::end() { + return d_disequalityToSkolem.end(); +} + +} /* CVC4 namespace */ diff --git a/src/proof/skolemization_manager.h b/src/proof/skolemization_manager.h new file mode 100644 index 000000000..de510e514 --- /dev/null +++ b/src/proof/skolemization_manager.h @@ -0,0 +1,55 @@ +/********************* */ +/*! \file skolemization_manager.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 + ** + ** [[ Add lengthier description here ]] + + ** \todo document this file + + **/ + +#include "cvc4_private.h" + +#ifndef __CVC4__SKOLEMIZATION_MANAGER_H +#define __CVC4__SKOLEMIZATION_MANAGER_H + +#include <iostream> +#include <map> +#include "proof/proof.h" +#include "util/proof.h" +#include "expr/node.h" +#include "theory/logic_info.h" +#include "theory/substitutions.h" + +namespace CVC4 { + +class SkolemizationManager { +public: + void registerSkolem(Node disequality, Node skolem); + bool hasSkolem(Node disequality); + Node getSkolem(Node disequality); + Node getDisequality(Node skolem); + bool isSkolem(Node skolem); + + void clear(); + + std::hash_map<Node, Node, NodeHashFunction>::const_iterator begin(); + std::hash_map<Node, Node, NodeHashFunction>::const_iterator end(); + +private: + std::hash_map<Node, Node, NodeHashFunction> d_disequalityToSkolem; + std::hash_map<Node, Node, NodeHashFunction> d_skolemToDisequality; +}; + +}/* CVC4 namespace */ + + + +#endif /* __CVC4__SKOLEMIZATION_MANAGER_H */ diff --git a/src/proof/theory_proof.cpp b/src/proof/theory_proof.cpp index 6679cf896..088275b3f 100644 --- a/src/proof/theory_proof.cpp +++ b/src/proof/theory_proof.cpp @@ -1,31 +1,32 @@ /********************* */ /*! \file theory_proof.cpp ** \verbatim - ** Original author: Liana Hadarean - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Liana Hadarean, Guy Katz, 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 ]] ** ** [[ Add lengthier description here ]] ** \todo document this file **/ +#include "proof/theory_proof.h" #include "base/cvc4_assert.h" #include "context/context.h" #include "options/bv_options.h" +#include "proof/arith_proof.h" #include "proof/array_proof.h" #include "proof/bitvector_proof.h" -#include "proof/cnf_proof.h" +#include "proof/clause_id.h" #include "proof/cnf_proof.h" #include "proof/proof_manager.h" #include "proof/proof_utils.h" #include "proof/sat_proof.h" -#include "proof/theory_proof.h" #include "proof/uf_proof.h" #include "prop/sat_solver_types.h" #include "smt/smt_engine.h" @@ -79,13 +80,16 @@ public: return theory::LemmaStatus(TNode::null(), 0); } void requirePhase(TNode n, bool b) throw() { + Debug("theory-proof-debug") << "ProofOutputChannel::requirePhase called" << std::endl; Trace("theory-proof-debug") << "requirePhase " << n << " " << b << std::endl; } bool flipDecision() throw() { + Debug("theory-proof-debug") << "ProofOutputChannel::flipDecision called" << std::endl; AlwaysAssert(false); return false; } void setIncomplete() throw() { + Debug("theory-proof-debug") << "ProofOutputChannel::setIncomplete called" << std::endl; AlwaysAssert(false); } };/* class ProofOutputChannel */ @@ -146,11 +150,18 @@ void TheoryProofEngine::registerTheory(theory::Theory* th) { ((theory::bv::TheoryBV*)th)->setProofLog( bvp ); return; } + if (id == theory::THEORY_ARRAY) { d_theoryProofTable[id] = new LFSCArrayProof((theory::arrays::TheoryArrays*)th, this); return; } - // TODO other theories + + if (id == theory::THEORY_ARITH) { + d_theoryProofTable[id] = new LFSCArithProof((theory::arith::TheoryArith*)th, this); + return; + } + + // TODO other theories } } } @@ -164,9 +175,12 @@ void TheoryProofEngine::registerTerm(Expr term) { if (d_registrationCache.count(term)) { return; } + Debug("pf::tp") << "TheoryProofEngine::registerTerm: registering new term: " << term << std::endl; theory::TheoryId theory_id = theory::Theory::theoryOf(term); + Debug("pf::tp") << "Term's theory: " << theory_id << std::endl; + // don't need to register boolean terms if (theory_id == theory::THEORY_BUILTIN || term.getKind() == kind::ITE) { @@ -178,20 +192,33 @@ void TheoryProofEngine::registerTerm(Expr term) { } if (!supportedTheory(theory_id)) return; - + getTheoryProof(theory_id)->registerTerm(term); d_registrationCache.insert(term); } theory::TheoryId TheoryProofEngine::getTheoryForLemma(ClauseId id) { - // TODO: now CNF proof has a map from formula to proof rule - // that should be checked to figure out what theory is responsible for this ProofManager* pm = ProofManager::currentPM(); - if (pm->getLogic() == "QF_UF") return theory::THEORY_UF; - if (pm->getLogic() == "QF_BV") return theory::THEORY_BV; - if (pm->getLogic() == "ALL_SUPPORTED") return theory::THEORY_BV; - Unreachable(); + Debug("pf::tp") << "TheoryProofEngine::getTheoryForLemma( " << id << " )" + << " = " << pm->getCnfProof()->getOwnerTheory(id) << std::endl; + + if ((pm->getLogic() == "QF_UFLIA") || (pm->getLogic() == "QF_UFLRA")) { + Debug("pf::tp") << "TheoryProofEngine::getTheoryForLemma: special hack for Arithmetic-with-holes support. " + << "Returning THEORY_ARITH" << std::endl; + return theory::THEORY_ARITH; + } + + return pm->getCnfProof()->getOwnerTheory(id); + + // if (pm->getLogic() == "QF_UF") return theory::THEORY_UF; + // if (pm->getLogic() == "QF_BV") return theory::THEORY_BV; + // if (pm->getLogic() == "QF_AX") return theory::THEORY_ARRAY; + // if (pm->getLogic() == "ALL_SUPPORTED") return theory::THEORY_BV; + + // Debug("pf::tp") << "Unsupported logic (" << pm->getLogic() << ")" << std::endl; + + // Unreachable(); } void LFSCTheoryProofEngine::bind(Expr term, LetMap& map, Bindings& let_order) { @@ -245,6 +272,9 @@ void LFSCTheoryProofEngine::printLetTerm(Expr term, std::ostream& os) { void LFSCTheoryProofEngine::printTheoryTerm(Expr term, std::ostream& os, const LetMap& map) { theory::TheoryId theory_id = theory::Theory::theoryOf(term); + Debug("pf::tp") << std::endl << "LFSCTheoryProofEngine::printTheoryTerm: term = " << term + << ", theory_id = " << theory_id << std::endl; + // boolean terms and ITEs are special because they // are common to all theories if (theory_id == theory::THEORY_BUILTIN || @@ -254,39 +284,55 @@ void LFSCTheoryProofEngine::printTheoryTerm(Expr term, std::ostream& os, const L return; } // dispatch to proper theory - getTheoryProof(theory_id)->printTerm(term, os, map); + getTheoryProof(theory_id)->printOwnedTerm(term, os, map); } void LFSCTheoryProofEngine::printSort(Type type, std::ostream& os) { if (type.isSort()) { - getTheoryProof(theory::THEORY_UF)->printSort(type, os); + getTheoryProof(theory::THEORY_UF)->printOwnedSort(type, os); return; } if (type.isBitVector()) { - getTheoryProof(theory::THEORY_BV)->printSort(type, os); + getTheoryProof(theory::THEORY_BV)->printOwnedSort(type, os); return; } if (type.isArray()) { - getTheoryProof(theory::THEORY_ARRAY)->printSort(type, os); + getTheoryProof(theory::THEORY_ARRAY)->printOwnedSort(type, os); + return; + } + + if (type.isInteger() || type.isReal()) { + getTheoryProof(theory::THEORY_ARITH)->printOwnedSort(type, os); + return; + } + + if (type.isBoolean()) { + getTheoryProof(theory::THEORY_BOOL)->printOwnedSort(type, os); return; } + Unreachable(); } -void LFSCTheoryProofEngine::printAssertions(std::ostream& os, std::ostream& paren) { - unsigned counter = 0; +void LFSCTheoryProofEngine::registerTermsFromAssertions() { ProofManager::assertions_iterator it = ProofManager::currentPM()->begin_assertions(); ProofManager::assertions_iterator end = ProofManager::currentPM()->end_assertions(); - // collect declarations first for(; it != end; ++it) { registerTerm(*it); } - printDeclarations(os, paren); +} + +void LFSCTheoryProofEngine::printAssertions(std::ostream& os, std::ostream& paren) { + Debug("pf::tp") << "LFSCTheoryProofEngine::printAssertions called" << std::endl << std::endl; + + unsigned counter = 0; + ProofManager::assertions_iterator it = ProofManager::currentPM()->begin_assertions(); + ProofManager::assertions_iterator end = ProofManager::currentPM()->end_assertions(); - it = ProofManager::currentPM()->begin_assertions(); for (; it != end; ++it) { + Debug("pf::tp") << "printAssertions: assertion is: " << *it << std::endl; // FIXME: merge this with counter os << "(% A" << counter++ << " (th_holds "; printLetTerm(*it, os); @@ -295,13 +341,40 @@ void LFSCTheoryProofEngine::printAssertions(std::ostream& os, std::ostream& pare } //store map between assertion and counter // ProofManager::currentPM()->setAssertion( *it ); + Debug("pf::tp") << "LFSCTheoryProofEngine::printAssertions done" << std::endl << std::endl; +} + +void LFSCTheoryProofEngine::printSortDeclarations(std::ostream& os, std::ostream& paren) { + Debug("pf::tp") << "LFSCTheoryProofEngine::printSortDeclarations called" << std::endl << std::endl; + + TheoryProofTable::const_iterator it = d_theoryProofTable.begin(); + TheoryProofTable::const_iterator end = d_theoryProofTable.end(); + for (; it != end; ++it) { + it->second->printSortDeclarations(os, paren); + } + + Debug("pf::tp") << "LFSCTheoryProofEngine::printSortDeclarations done" << std::endl << std::endl; +} + +void LFSCTheoryProofEngine::printTermDeclarations(std::ostream& os, std::ostream& paren) { + Debug("pf::tp") << "LFSCTheoryProofEngine::printTermDeclarations called" << std::endl << std::endl; + + TheoryProofTable::const_iterator it = d_theoryProofTable.begin(); + TheoryProofTable::const_iterator end = d_theoryProofTable.end(); + for (; it != end; ++it) { + it->second->printTermDeclarations(os, paren); + } + + Debug("pf::tp") << "LFSCTheoryProofEngine::printTermDeclarations done" << std::endl << std::endl; } -void LFSCTheoryProofEngine::printDeclarations(std::ostream& os, std::ostream& paren) { +void LFSCTheoryProofEngine::printDeferredDeclarations(std::ostream& os, std::ostream& paren) { + Debug("pf::tp") << "LFSCTheoryProofEngine::printDeferredDeclarations called" << std::endl; + TheoryProofTable::const_iterator it = d_theoryProofTable.begin(); TheoryProofTable::const_iterator end = d_theoryProofTable.end(); for (; it != end; ++it) { - it->second->printDeclarations(os, paren); + it->second->printDeferredDeclarations(os, paren); } } @@ -313,6 +386,16 @@ void LFSCTheoryProofEngine::printTheoryLemmas(const IdToSatClause& lemmas, IdToSatClause::const_iterator it = lemmas.begin(); IdToSatClause::const_iterator end = lemmas.end(); + Debug("pf::tp") << "LFSCTheoryProofEngine::printTheoryLemmas: checking lemma owners..." << std::endl; + + for (; it != end; ++it) { + Debug("pf::tp") << "LFSCTheoryProofEngine::printTheoryLemmas: new lemma" << std::endl; + ClauseId id = it->first; + Debug("pf::tp") << "\tLemma = " << id + << ". Owner theory: " << pm->getCnfProof()->getOwnerTheory(id) << std::endl; + } + it = lemmas.begin(); + // BitVector theory is special case: must know all // conflicts needed ahead of time for resolution // proof lemmas @@ -353,13 +436,22 @@ void LFSCTheoryProofEngine::printTheoryLemmas(const IdToSatClause& lemmas, it = lemmas.begin(); + Debug("pf::tp") << "LFSCTheoryProofEngine::printTheoryLemmas: printing lemmas..." << std::endl; + for (; it != end; ++it) { + Debug("pf::tp") << "LFSCTheoryProofEngine::printTheoryLemmas: printing a new lemma!" << std::endl; + + // Debug("pf::tp") << "\tLemma = " << it->first << ", " << *(it->second) << std::endl; ClauseId id = it->first; + Debug("pf::tp") << "Owner theory:" << pm->getCnfProof()->getOwnerTheory(id) << std::endl; const prop::SatClause* clause = it->second; // printing clause as it appears in resolution proof os << "(satlem _ _ "; std::ostringstream clause_paren; + + Debug("pf::tp") << "CnfProof printing clause..." << std::endl; pm->getCnfProof()->printClause(*clause, os, clause_paren); + Debug("pf::tp") << "CnfProof printing clause - Done!" << std::endl; std::vector<Expr> clause_expr; for(unsigned i = 0; i < clause->size(); ++i) { @@ -373,10 +465,14 @@ void LFSCTheoryProofEngine::printTheoryLemmas(const IdToSatClause& lemmas, clause_expr.push_back(expr_lit); } + Debug("pf::tp") << "Expression printing done!" << std::endl; + // query appropriate theory for proof of clause theory::TheoryId theory_id = getTheoryForLemma(id); + Debug("pf::tp") << "Get theory lemma from " << theory_id << "..." << std::endl; Debug("theory-proof-debug") << ";; Get theory lemma from " << theory_id << "..." << std::endl; getTheoryProof(theory_id)->printTheoryLemmaProof(clause_expr, os, paren); + Debug("pf::tp") << "Get theory lemma from " << theory_id << "... DONE!" << std::endl; // os << " (clausify_false trust)"; os << clause_paren.str(); os << "( \\ " << pm->getLemmaClauseName(id) <<"\n"; @@ -385,15 +481,19 @@ void LFSCTheoryProofEngine::printTheoryLemmas(const IdToSatClause& lemmas, } void LFSCTheoryProofEngine::printBoundTerm(Expr term, std::ostream& os, const LetMap& map) { + // Debug("pf::tp") << "LFSCTheoryProofEngine::printBoundTerm( " << term << " ) " << std::endl; + LetMap::const_iterator it = map.find(term); - Assert (it != map.end()); - unsigned id = it->second.id; - unsigned count = it->second.count; - if (count > LET_COUNT) { - os <<"let"<<id; - return; + if (it != map.end()) { + unsigned id = it->second.id; + unsigned count = it->second.count; + if (count > LET_COUNT) { + os <<"let"<<id; + return; + } } - printTheoryTerm(term, os, map); + + printTheoryTerm(term, os, map); } void LFSCTheoryProofEngine::printCoreTerm(Expr term, std::ostream& os, const LetMap& map) { @@ -513,32 +613,83 @@ void TheoryProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& th = new theory::arrays::TheoryArrays(&fakeContext, &fakeContext, oc, v, ProofManager::currentPM()->getLogicInfo(), "replay::"); + } else if (d_theory->getId() == theory::THEORY_ARITH) { + Trace("theory-proof-debug") << "Arith proofs currently not supported. Use 'trust'" << std::endl; + os << " (clausify_false trust)"; + return; } else { InternalError(std::string("can't generate theory-proof for ") + ProofManager::currentPM()->getLogic()); } + + Debug("pf::tp") << "TheoryProof::printTheoryLemmaProof - calling th->ProduceProofs()" << std::endl; th->produceProofs(); + Debug("pf::tp") << "TheoryProof::printTheoryLemmaProof - th->ProduceProofs() DONE" << std::endl; + MyPreRegisterVisitor preRegVisitor(th); for( unsigned i=0; i<lemma.size(); i++ ){ Node lit = Node::fromExpr( lemma[i] ).negate(); - Trace("theory-proof-debug") << "; preregistering and asserting " << lit << std::endl; + Trace("pf::tp") << "; preregistering and asserting " << lit << std::endl; NodeVisitor<MyPreRegisterVisitor>::run(preRegVisitor, lit); th->assertFact(lit, false); } + + Debug("pf::tp") << "TheoryProof::printTheoryLemmaProof - calling th->check()" << std::endl; th->check(theory::Theory::EFFORT_FULL); + Debug("pf::tp") << "TheoryProof::printTheoryLemmaProof - th->check() DONE" << std::endl; + if(oc.d_conflict.isNull()) { - Trace("theory-proof-debug") << "; conflict is null" << std::endl; + Trace("pf::tp") << "; conflict is null" << std::endl; Assert(!oc.d_lemma.isNull()); - Trace("theory-proof-debug") << "; ++ but got lemma: " << oc.d_lemma << std::endl; - Trace("theory-proof-debug") << "; asserting " << oc.d_lemma[1].negate() << std::endl; - th->assertFact(oc.d_lemma[1].negate(), false); + Trace("pf::tp") << "; ++ but got lemma: " << oc.d_lemma << std::endl; + + // Original, as in Liana's branch + // Trace("pf::tp") << "; asserting " << oc.d_lemma[1].negate() << std::endl; + // th->assertFact(oc.d_lemma[1].negate(), false); + // th->check(theory::Theory::EFFORT_FULL); + + // Altered version, to handle OR lemmas + + if (oc.d_lemma.getKind() == kind::OR) { + Debug("pf::tp") << "OR lemma. Negating each child separately" << std::endl; + for (unsigned i = 0; i < oc.d_lemma.getNumChildren(); ++i) { + if (oc.d_lemma[i].getKind() == kind::NOT) { + Trace("pf::tp") << "; asserting fact: " << oc.d_lemma[i][0] << std::endl; + th->assertFact(oc.d_lemma[i][0], false); + } + else { + Trace("pf::tp") << "; asserting fact: " << oc.d_lemma[i].notNode() << std::endl; + th->assertFact(oc.d_lemma[i].notNode(), false); + } + } + } + else { + Unreachable(); + + Assert(oc.d_lemma.getKind() == kind::NOT); + Debug("pf::tp") << "NOT lemma" << std::endl; + Trace("pf::tp") << "; asserting fact: " << oc.d_lemma[0] << std::endl; + th->assertFact(oc.d_lemma[0], false); + } + + // Trace("pf::tp") << "; ++ but got lemma: " << oc.d_lemma << std::endl; + // Trace("pf::tp") << "; asserting " << oc.d_lemma[1].negate() << std::endl; + // th->assertFact(oc.d_lemma[1].negate(), false); + + // th->check(theory::Theory::EFFORT_FULL); } + Debug("pf::tp") << "Calling oc.d_proof->toStream(os)" << std::endl; oc.d_proof->toStream(os); + Debug("pf::tp") << "Calling oc.d_proof->toStream(os) -- DONE!" << std::endl; + + Debug("pf::tp") << "About to delete the theory solver used for proving the lemma... " << std::endl; delete th; + Debug("pf::tp") << "About to delete the theory solver used for proving the lemma: DONE! " << std::endl; } bool TheoryProofEngine::supportedTheory(theory::TheoryId id) { return (id == theory::THEORY_ARRAY || + id == theory::THEORY_ARITH || id == theory::THEORY_BV || id == theory::THEORY_UF || id == theory::THEORY_BOOL); @@ -560,7 +711,7 @@ void BooleanProof::registerTerm(Expr term) { } } -void LFSCBooleanProof::printTerm(Expr term, std::ostream& os, const LetMap& map) { +void LFSCBooleanProof::printOwnedTerm(Expr term, std::ostream& os, const LetMap& map) { Assert (term.getType().isBoolean()); if (term.isVariable()) { os << "(p_app " << ProofManager::sanitize(term) <<")"; @@ -611,11 +762,16 @@ void LFSCBooleanProof::printTerm(Expr term, std::ostream& os, const LetMap& map) } -void LFSCBooleanProof::printSort(Type type, std::ostream& os) { +void LFSCBooleanProof::printOwnedSort(Type type, std::ostream& os) { Assert (type.isBoolean()); os << "Bool"; } -void LFSCBooleanProof::printDeclarations(std::ostream& os, std::ostream& paren) { + +void LFSCBooleanProof::printSortDeclarations(std::ostream& os, std::ostream& paren) { + // Nothing to do here at this point. +} + +void LFSCBooleanProof::printTermDeclarations(std::ostream& os, std::ostream& paren) { for (ExprSet::const_iterator it = d_declarations.begin(); it != d_declarations.end(); ++it) { Expr term = *it; @@ -626,6 +782,10 @@ void LFSCBooleanProof::printDeclarations(std::ostream& os, std::ostream& paren) } } +void LFSCBooleanProof::printDeferredDeclarations(std::ostream& os, std::ostream& paren) { + // Nothing to do here at this point. +} + void LFSCBooleanProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren) { diff --git a/src/proof/theory_proof.h b/src/proof/theory_proof.h index d997d6e23..54c86f3f3 100644 --- a/src/proof/theory_proof.h +++ b/src/proof/theory_proof.h @@ -1,19 +1,18 @@ /********************* */ /*! \file theory_proof.h -** \verbatim -** Original author: Liana Hadarean -** Major contributors: Morgan Deters -** Minor contributors (to current version): none -** This file is part of the CVC4 project. -** Copyright (c) 2009-2014 New York University and The University of Iowa -** See the file COPYING in the top-level source directory for licensing -** information.\endverbatim -** -** \brief A manager for UfProofs. -** -** A manager for UfProofs. -** -** + ** \verbatim + ** Top contributors (to current version): + ** Liana Hadarean, Guy Katz, 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 + ** + ** [[ Add lengthier description here ]] + + ** \todo document this file + **/ #include "cvc4_private.h" @@ -21,33 +20,32 @@ #ifndef __CVC4__THEORY_PROOF_H #define __CVC4__THEORY_PROOF_H -#include "util/proof.h" -#include "expr/expr.h" -#include "prop/sat_solver_types.h" #include <ext/hash_set> #include <iosfwd> +#include "expr/expr.h" +#include "proof/clause_id.h" +#include "prop/sat_solver_types.h" +#include "util/proof.h" namespace CVC4 { namespace theory { class Theory; -} - -typedef unsigned ClauseId; +} /* namespace CVC4::theory */ struct LetCount { static unsigned counter; static void resetCounter() { counter = 0; } static unsigned newId() { return ++counter; } - + unsigned count; unsigned id; LetCount() : count(0) , id(-1) {} - + void increment() { ++count; } LetCount(unsigned i) : count(1) @@ -66,7 +64,7 @@ struct LetCount { count = rhs.count; return *this; } -}; +}; struct LetOrderElement { Expr expr; @@ -85,10 +83,9 @@ struct LetOrderElement { typedef __gnu_cxx::hash_map < ClauseId, prop::SatClause* > IdToSatClause; typedef __gnu_cxx::hash_map<Expr, LetCount, ExprHashFunction> LetMap; -typedef std::vector<LetOrderElement> Bindings; +typedef std::vector<LetOrderElement> Bindings; class TheoryProof; -typedef unsigned ClauseId; typedef __gnu_cxx::hash_set<Expr, ExprHashFunction > ExprSet; typedef std::map<theory::TheoryId, TheoryProof* > TheoryProofTable; @@ -126,6 +123,14 @@ public: virtual void printSort(Type type, std::ostream& os) = 0; /** + * Go over the assertions and register all terms with the theories. + * + * @param os + * @param paren closing parenthesis + */ + virtual void registerTermsFromAssertions() = 0; + + /** * Print the theory assertions (arbitrary formulas over * theory atoms) * @@ -133,6 +138,14 @@ public: * @param paren closing parenthesis */ virtual void printAssertions(std::ostream& os, std::ostream& paren) = 0; + /** + * Print variable declarations that need to appear within the proof, + * e.g. skolemized variables. + * + * @param os + * @param paren closing parenthesis + */ + virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren) = 0; /** * Print proofs of all the theory lemmas (must prove @@ -170,11 +183,14 @@ public: LFSCTheoryProofEngine() : TheoryProofEngine() {} - void printDeclarations(std::ostream& os, std::ostream& paren); + void registerTermsFromAssertions(); + void printSortDeclarations(std::ostream& os, std::ostream& paren); + void printTermDeclarations(std::ostream& os, std::ostream& paren); virtual void printCoreTerm(Expr term, std::ostream& os, const LetMap& map); virtual void printLetTerm(Expr term, std::ostream& os); virtual void printBoundTerm(Expr term, std::ostream& os, const LetMap& map); virtual void printAssertions(std::ostream& os, std::ostream& paren); + virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren); virtual void printTheoryLemmas(const IdToSatClause& lemmas, std::ostream& os, std::ostream& paren); @@ -191,41 +207,74 @@ public: : d_theory(th) , d_proofEngine(proofEngine) {} - virtual ~TheoryProof() {}; - /** - * Print a term belonging to this theory. - * + virtual ~TheoryProof() {}; + /** + * Print a term belonging some theory, not neccessarily this one. + * * @param term expresion representing term * @param os output stream */ - virtual void printTerm(Expr term, std::ostream& os, const LetMap& map) = 0; - /** - * Print the proof representation of the given type. - * - * @param type - * @param os + void printTerm(Expr term, std::ostream& os, const LetMap& map) { + d_proofEngine->printBoundTerm(term, os, map); + } + /** + * Print a term belonging to THIS theory. + * + * @param term expresion representing term + * @param os output stream */ - virtual void printSort(Type type, std::ostream& os) = 0; - /** + virtual void printOwnedTerm(Expr term, std::ostream& os, const LetMap& map) = 0; + /** + * Print the proof representation of the given type that belongs to some theory. + * + * @param type + * @param os + */ + void printSort(Type type, std::ostream& os) { + d_proofEngine->printSort(type, os); + } + /** + * Print the proof representation of the given type that belongs to THIS theory. + * + * @param type + * @param os + */ + virtual void printOwnedSort(Type type, std::ostream& os) = 0; + /** * Print a proof for the theory lemmas. Must prove * clause representing lemmas to be used in resolution proof. - * + * * @param os output stream */ virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren); - /** - * Print the variable/sorts declarations for this theory. - * - * @param os - * @param paren + /** + * Print the sorts declarations for this theory. + * + * @param os + * @param paren */ - virtual void printDeclarations(std::ostream& os, std::ostream& paren) = 0; - /** + virtual void printSortDeclarations(std::ostream& os, std::ostream& paren) = 0; + /** + * Print the term declarations for this theory. + * + * @param os + * @param paren + */ + virtual void printTermDeclarations(std::ostream& os, std::ostream& paren) = 0; + /** + * Print any deferred variable/sorts declarations for this theory + * (those that need to appear inside the actual proof). + * + * @param os + * @param paren + */ + virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren) = 0; + /** * Register a term of this theory that appears in the proof. - * - * @param term + * + * @param term */ - virtual void registerTerm(Expr term) = 0; + virtual void registerTerm(Expr term) = 0; }; class BooleanProof : public TheoryProof { @@ -235,12 +284,14 @@ public: BooleanProof(TheoryProofEngine* proofEngine); virtual void registerTerm(Expr term); - - virtual void printTerm(Expr term, std::ostream& os, const LetMap& map) = 0; - virtual void printSort(Type type, std::ostream& os) = 0; + virtual void printOwnedTerm(Expr term, std::ostream& os, const LetMap& map) = 0; + + virtual void printOwnedSort(Type type, std::ostream& os) = 0; virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren) = 0; - virtual void printDeclarations(std::ostream& os, std::ostream& paren) = 0; + virtual void printSortDeclarations(std::ostream& os, std::ostream& paren) = 0; + virtual void printTermDeclarations(std::ostream& os, std::ostream& paren) = 0; + virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren) = 0; }; class LFSCBooleanProof : public BooleanProof { @@ -248,13 +299,14 @@ public: LFSCBooleanProof(TheoryProofEngine* proofEngine) : BooleanProof(proofEngine) {} - virtual void printTerm(Expr term, std::ostream& os, const LetMap& map); - virtual void printSort(Type type, std::ostream& os); + virtual void printOwnedTerm(Expr term, std::ostream& os, const LetMap& map); + virtual void printOwnedSort(Type type, std::ostream& os); virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren); - virtual void printDeclarations(std::ostream& os, std::ostream& paren); + virtual void printSortDeclarations(std::ostream& os, std::ostream& paren); + virtual void printTermDeclarations(std::ostream& os, std::ostream& paren); + virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren); }; - } /* CVC4 namespace */ #endif /* __CVC4__THEORY_PROOF_H */ diff --git a/src/proof/uf_proof.cpp b/src/proof/uf_proof.cpp index ec0d90ae7..32ca122b0 100644 --- a/src/proof/uf_proof.cpp +++ b/src/proof/uf_proof.cpp @@ -1,18 +1,18 @@ /********************* */ /*! \file uf_proof.cpp -** \verbatim -** Original author: Liana Hadarean -** Major contributors: none -** Minor contributors (to current version): none -** This file is part of the CVC4 project. -** Copyright (c) 2009-2014 New York University and The University of Iowa -** See the file COPYING in the top-level source directory for licensing -** information.\endverbatim -** -** \brief [[ Add one-line brief description here ]] -** -** [[ Add lengthier description here ]] -** \todo document this file + ** \verbatim + ** Top contributors (to current version): + ** Liana Hadarean, 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 "proof/theory_proof.h" @@ -21,10 +21,7 @@ #include "theory/uf/theory_uf.h" #include <stack> -using namespace CVC4; -using namespace CVC4::theory; -using namespace CVC4::theory::uf; - +namespace CVC4 { inline static Node eqNode(TNode n1, TNode n2) { return NodeManager::currentNM()->mkNode(n1.getType().isBoolean() ? kind::IFF : kind::EQUAL, n1, n2); @@ -32,14 +29,14 @@ inline static Node eqNode(TNode n1, TNode n2) { // congrence matching term helper inline static bool match(TNode n1, TNode n2) { - Debug("mgd") << "match " << n1 << " " << n2 << std::endl; + Debug("pf::uf") << "match " << n1 << " " << n2 << std::endl; if(ProofManager::currentPM()->hasOp(n1)) { n1 = ProofManager::currentPM()->lookupOp(n1); } if(ProofManager::currentPM()->hasOp(n2)) { n2 = ProofManager::currentPM()->lookupOp(n2); } - Debug("mgd") << "+ match " << n1 << " " << n2 << std::endl; + Debug("pf::uf") << "+ match " << n1 << " " << n2 << std::endl; if(n1 == n2) { return true; } @@ -77,6 +74,7 @@ void ProofUF::toStream(std::ostream& out) { } void ProofUF::toStreamLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, const LetMap& map) { + Debug("pf::uf") << "ProofUF::toStreamLFSC starting" << std::endl; Debug("lfsc-uf") << "Printing uf proof in LFSC : " << std::endl; pf->debug_print("lfsc-uf"); Debug("lfsc-uf") << std::endl; @@ -84,18 +82,18 @@ void ProofUF::toStreamLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqPr } Node ProofUF::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, unsigned tb, const LetMap& map) { - Debug("gk::proof") << std::endl << std::endl << "toStreamRecLFSC called. tb = " << tb << " . proof:" << std::endl; - pf->debug_print("gk::proof"); - Debug("gk::proof") << std::endl; + Debug("pf::uf") << std::endl << std::endl << "toStreamRecLFSC called. tb = " << tb << " . proof:" << std::endl; + pf->debug_print("pf::uf"); + Debug("pf::uf") << std::endl; if(tb == 0) { - Assert(pf->d_id == eq::MERGED_THROUGH_TRANS); + Assert(pf->d_id == theory::eq::MERGED_THROUGH_TRANS); Assert(!pf->d_node.isNull()); Assert(pf->d_children.size() >= 2); int neg = -1; theory::eq::EqProof subTrans; - subTrans.d_id = eq::MERGED_THROUGH_TRANS; + subTrans.d_id = theory::eq::MERGED_THROUGH_TRANS; subTrans.d_node = pf->d_node; size_t i = 0; @@ -108,38 +106,38 @@ Node ProofUF::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::E } // Handle congruence closures over equalities. - else if (pf->d_children[i]->d_id==eq::MERGED_THROUGH_CONGRUENCE && pf->d_children[i]->d_node.isNull()) { - Debug("gk::proof") << "Handling congruence over equalities" << std::endl; + else if (pf->d_children[i]->d_id==theory::eq::MERGED_THROUGH_CONGRUENCE && pf->d_children[i]->d_node.isNull()) { + Debug("pf::uf") << "Handling congruence over equalities" << std::endl; // Gather the sequence of consecutive congruence closures. std::vector<const theory::eq::EqProof *> congruenceClosures; unsigned count; - Debug("gk::proof") << "Collecting congruence sequence" << std::endl; + Debug("pf::uf") << "Collecting congruence sequence" << std::endl; for (count = 0; i + count < pf->d_children.size() && - pf->d_children[i + count]->d_id==eq::MERGED_THROUGH_CONGRUENCE && + pf->d_children[i + count]->d_id==theory::eq::MERGED_THROUGH_CONGRUENCE && pf->d_children[i + count]->d_node.isNull(); ++count) { - Debug("gk::proof") << "Found a congruence: " << std::endl; - pf->d_children[i+count]->debug_print("gk::proof"); + Debug("pf::uf") << "Found a congruence: " << std::endl; + pf->d_children[i+count]->debug_print("pf::uf"); congruenceClosures.push_back(pf->d_children[i+count]); } - Debug("gk::proof") << "Total number of congruences found: " << congruenceClosures.size() << std::endl; + Debug("pf::uf") << "Total number of congruences found: " << congruenceClosures.size() << std::endl; // Determine if the "target" of the congruence sequence appears right before or right after the sequence. bool targetAppearsBefore = true; bool targetAppearsAfter = true; if ((i == 0) || (i == 1 && neg == 0)) { - Debug("gk::proof") << "Target does not appear before" << std::endl; + Debug("pf::uf") << "Target does not appear before" << std::endl; targetAppearsBefore = false; } if ((i + count >= pf->d_children.size()) || (!pf->d_children[i + count]->d_node.isNull() && pf->d_children[i + count]->d_node.getKind() == kind::NOT)) { - Debug("gk::proof") << "Target does not appear after" << std::endl; + Debug("pf::uf") << "Target does not appear after" << std::endl; targetAppearsAfter = false; } @@ -162,16 +160,16 @@ Node ProofUF::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::E // Start with the congruence closure closest to the target clause, and work our way back/forward. if (targetAppearsBefore) { for (unsigned j = 0; j < count; ++j) { - if (pf->d_children[i + j]->d_children[0]->d_id != eq::MERGED_THROUGH_REFLEXIVITY) + if (pf->d_children[i + j]->d_children[0]->d_id != theory::eq::MERGED_THROUGH_REFLEXIVITY) orderedEqualities.insert(orderedEqualities.begin(), pf->d_children[i + j]->d_children[0]); - if (pf->d_children[i + j]->d_children[1]->d_id != eq::MERGED_THROUGH_REFLEXIVITY) + if (pf->d_children[i + j]->d_children[1]->d_id != theory::eq::MERGED_THROUGH_REFLEXIVITY) orderedEqualities.insert(orderedEqualities.end(), pf->d_children[i + j]->d_children[1]); } } else { for (unsigned j = 0; j < count; ++j) { - if (pf->d_children[i + count - 1 - j]->d_children[0]->d_id != eq::MERGED_THROUGH_REFLEXIVITY) + if (pf->d_children[i + count - 1 - j]->d_children[0]->d_id != theory::eq::MERGED_THROUGH_REFLEXIVITY) orderedEqualities.insert(orderedEqualities.begin(), pf->d_children[i + count - 1 - j]->d_children[0]); - if (pf->d_children[i + count - 1 - j]->d_children[1]->d_id != eq::MERGED_THROUGH_REFLEXIVITY) + if (pf->d_children[i + count - 1 - j]->d_children[1]->d_id != theory::eq::MERGED_THROUGH_REFLEXIVITY) orderedEqualities.insert(orderedEqualities.end(), pf->d_children[i + count - 1 - j]->d_children[1]); } } @@ -197,22 +195,22 @@ Node ProofUF::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::E Node n1; std::stringstream ss; //Assert(subTrans.d_children.size() == pf->d_children.size() - 1); - Debug("mgdx") << "\nsubtrans has " << subTrans.d_children.size() << " children\n"; + Debug("pf::uf") << "\nsubtrans has " << subTrans.d_children.size() << " children\n"; if(pf->d_children.size() > 2) { n1 = toStreamRecLFSC(ss, tp, &subTrans, 1, map); } else { n1 = toStreamRecLFSC(ss, tp, subTrans.d_children[0], 1, map); - Debug("mgdx") << "\nsubTrans unique child " << subTrans.d_children[0]->d_id << " was proven\ngot: " << n1 << std::endl; + Debug("pf::uf") << "\nsubTrans unique child " << subTrans.d_children[0]->d_id << " was proven\ngot: " << n1 << std::endl; } Node n2 = pf->d_children[neg]->d_node; Assert(n2.getKind() == kind::NOT); out << "(clausify_false (contra _ "; - Debug("mgdx") << "\nhave proven: " << n1 << std::endl; - Debug("mgdx") << "n2 is " << n2[0] << std::endl; + Debug("pf::uf") << "\nhave proven: " << n1 << std::endl; + Debug("pf::uf") << "n2 is " << n2[0] << std::endl; - if (n2[0].getNumChildren() > 0) { Debug("mgdx") << "\nn2[0]: " << n2[0][0] << std::endl; } - if (n1.getNumChildren() > 1) { Debug("mgdx") << "n1[1]: " << n1[1] << std::endl; } + if (n2[0].getNumChildren() > 0) { Debug("pf::uf") << "\nn2[0]: " << n2[0][0] << std::endl; } + if (n1.getNumChildren() > 1) { Debug("pf::uf") << "n1[1]: " << n1[1] << std::endl; } if(n2[0].getKind() == kind::APPLY_UF) { out << "(trans _ _ _ _ "; @@ -232,44 +230,44 @@ Node ProofUF::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::E } switch(pf->d_id) { - case eq::MERGED_THROUGH_CONGRUENCE: { - Debug("mgd") << "\nok, looking at congruence:\n"; - pf->debug_print("mgd"); + case theory::eq::MERGED_THROUGH_CONGRUENCE: { + Debug("pf::uf") << "\nok, looking at congruence:\n"; + pf->debug_print("pf::uf"); std::stack<const theory::eq::EqProof*> stk; - for(const theory::eq::EqProof* pf2 = pf; pf2->d_id == eq::MERGED_THROUGH_CONGRUENCE; pf2 = pf2->d_children[0]) { + for(const theory::eq::EqProof* pf2 = pf; pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE; pf2 = pf2->d_children[0]) { Assert(!pf2->d_node.isNull()); Assert(pf2->d_node.getKind() == kind::PARTIAL_APPLY_UF || pf2->d_node.getKind() == kind::BUILTIN || pf2->d_node.getKind() == kind::APPLY_UF || pf2->d_node.getKind() == kind::SELECT || pf2->d_node.getKind() == kind::STORE); Assert(pf2->d_children.size() == 2); out << "(cong _ _ _ _ _ _ "; stk.push(pf2); } - Assert(stk.top()->d_children[0]->d_id != eq::MERGED_THROUGH_CONGRUENCE); + Assert(stk.top()->d_children[0]->d_id != theory::eq::MERGED_THROUGH_CONGRUENCE); NodeBuilder<> b1(kind::PARTIAL_APPLY_UF), b2(kind::PARTIAL_APPLY_UF); const theory::eq::EqProof* pf2 = stk.top(); stk.pop(); - Assert(pf2->d_id == eq::MERGED_THROUGH_CONGRUENCE); + Assert(pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE); Node n1 = toStreamRecLFSC(out, tp, pf2->d_children[0], tb + 1, map); out << " "; std::stringstream ss; Node n2 = toStreamRecLFSC(ss, tp, pf2->d_children[1], tb + 1, map); - Debug("mgd") << "\nok, in FIRST cong[" << stk.size() << "]" << "\n"; - pf2->debug_print("mgd"); - Debug("mgd") << "looking at " << pf2->d_node << "\n"; - Debug("mgd") << " " << n1 << "\n"; - Debug("mgd") << " " << n2 << "\n"; + Debug("pf::uf") << "\nok, in FIRST cong[" << stk.size() << "]" << "\n"; + pf2->debug_print("pf::uf"); + Debug("pf::uf") << "looking at " << pf2->d_node << "\n"; + Debug("pf::uf") << " " << n1 << "\n"; + Debug("pf::uf") << " " << n2 << "\n"; int side = 0; if(match(pf2->d_node, n1[0])) { //if(tb == 1) { - Debug("mgd") << "SIDE IS 0\n"; + Debug("pf::uf") << "SIDE IS 0\n"; //} side = 0; } else { //if(tb == 1) { - Debug("mgd") << "SIDE IS 1\n"; + Debug("pf::uf") << "SIDE IS 1\n"; //} if(!match(pf2->d_node, n1[1])) { - Debug("mgd") << "IN BAD CASE, our first subproof is\n"; - pf2->d_children[0]->debug_print("mgd"); + Debug("pf::uf") << "IN BAD CASE, our first subproof is\n"; + pf2->d_children[0]->debug_print("pf::uf"); } Assert(match(pf2->d_node, n1[1])); side = 1; @@ -294,11 +292,11 @@ Node ProofUF::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::E } else { b2 << n1[1-side]; } - Debug("mgd") << "pf2->d_node " << pf2->d_node << std::endl; - Debug("mgd") << "b1.getNumChildren() " << b1.getNumChildren() << std::endl; - Debug("mgd") << "n1 " << n1 << std::endl; - Debug("mgd") << "n2 " << n2 << std::endl; - Debug("mgd") << "side " << side << std::endl; + Debug("pf::uf") << "pf2->d_node " << pf2->d_node << std::endl; + Debug("pf::uf") << "b1.getNumChildren() " << b1.getNumChildren() << std::endl; + Debug("pf::uf") << "n1 " << n1 << std::endl; + Debug("pf::uf") << "n2 " << n2 << std::endl; + Debug("pf::uf") << "side " << side << std::endl; if(pf2->d_node[b1.getNumChildren() - (pf2->d_node.getMetaKind() == kind::metakind::PARAMETERIZED ? 0 : 1)] == n2[side]) { b1 << n2[side]; b2 << n2[1-side]; @@ -312,20 +310,20 @@ Node ProofUF::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::E out << ")"; while(!stk.empty()) { if(tb == 1) { - Debug("mgd") << "\nMORE TO DO\n"; + Debug("pf::uf") << "\nMORE TO DO\n"; } pf2 = stk.top(); stk.pop(); - Assert(pf2->d_id == eq::MERGED_THROUGH_CONGRUENCE); + Assert(pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE); out << " "; ss.str(""); n2 = toStreamRecLFSC(ss, tp, pf2->d_children[1], tb + 1, map); - Debug("mgd") << "\nok, in cong[" << stk.size() << "]" << "\n"; - Debug("mgd") << "looking at " << pf2->d_node << "\n"; - Debug("mgd") << " " << n1 << "\n"; - Debug("mgd") << " " << n2 << "\n"; - Debug("mgd") << " " << b1 << "\n"; - Debug("mgd") << " " << b2 << "\n"; + Debug("pf::uf") << "\nok, in cong[" << stk.size() << "]" << "\n"; + Debug("pf::uf") << "looking at " << pf2->d_node << "\n"; + Debug("pf::uf") << " " << n1 << "\n"; + Debug("pf::uf") << " " << n2 << "\n"; + Debug("pf::uf") << " " << b1 << "\n"; + Debug("pf::uf") << " " << b2 << "\n"; if(pf2->d_node[b1.getNumChildren()] == n2[side]) { b1 << n2[side]; b2 << n2[1-side]; @@ -340,7 +338,7 @@ Node ProofUF::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::E } n1 = b1; n2 = b2; - Debug("mgd") << "at end assert, got " << pf2->d_node << " and " << n1 << std::endl; + Debug("pf::uf") << "at end assert, got " << pf2->d_node << " and " << n1 << std::endl; if(pf2->d_node.getKind() == kind::PARTIAL_APPLY_UF) { Assert(n1 == pf2->d_node); } @@ -353,7 +351,7 @@ Node ProofUF::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::E } b1.append(n1.begin(), n1.end()); n1 = b1; - Debug("mgd") << "at[2] end assert, got " << pf2->d_node << " and " << n1 << std::endl; + Debug("pf::uf") << "at[2] end assert, got " << pf2->d_node << " and " << n1 << std::endl; if(pf2->d_node.getKind() == kind::APPLY_UF) { Assert(n1 == pf2->d_node); } @@ -370,12 +368,12 @@ Node ProofUF::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::E } Node n = (side == 0 ? eqNode(n1, n2) : eqNode(n2, n1)); if(tb == 1) { - Debug("mgdx") << "\ncong proved: " << n << "\n"; + Debug("pf::uf") << "\ncong proved: " << n << "\n"; } return n; } - case eq::MERGED_THROUGH_REFLEXIVITY: + case theory::eq::MERGED_THROUGH_REFLEXIVITY: Assert(!pf->d_node.isNull()); Assert(pf->d_children.empty()); out << "(refl _ "; @@ -383,33 +381,44 @@ Node ProofUF::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::E out << ")"; return eqNode(pf->d_node, pf->d_node); - case eq::MERGED_THROUGH_EQUALITY: + case theory::eq::MERGED_THROUGH_EQUALITY: Assert(!pf->d_node.isNull()); Assert(pf->d_children.empty()); out << ProofManager::getLitName(pf->d_node.negate()); return pf->d_node; - case eq::MERGED_THROUGH_TRANS: { + case theory::eq::MERGED_THROUGH_TRANS: { Assert(!pf->d_node.isNull()); Assert(pf->d_children.size() >= 2); std::stringstream ss; - Debug("mgd") << "\ndoing trans proof[[\n"; - pf->debug_print("mgd"); - Debug("mgd") << "\n"; + Debug("pf::uf") << "\ndoing trans proof[[\n"; + pf->debug_print("pf::uf"); + Debug("pf::uf") << "\n"; Node n1 = toStreamRecLFSC(ss, tp, pf->d_children[0], tb + 1, map); - Debug("mgd") << "\ndoing trans proof, got n1 " << n1 << "\n"; + Debug("pf::uf") << "\ndoing trans proof, got n1 " << n1 << "\n"; if(tb == 1) { - Debug("mgdx") << "\ntrans proof[0], got n1 " << n1 << "\n"; + Debug("pf::uf") << "\ntrans proof[0], got n1 " << n1 << "\n"; } bool identicalEqualities = false; bool evenLengthSequence; Node nodeAfterEqualitySequence; + std::map<size_t, Node> childToStream; + for(size_t i = 1; i < pf->d_children.size(); ++i) { std::stringstream ss1(ss.str()), ss2; ss.str(""); - Node n2 = toStreamRecLFSC(ss2, tp, pf->d_children[i], tb + 1, map); + + // It is possible that we've already converted the i'th child to stream. If so, + // use previously stored result. Otherwise, convert and store. + Node n2; + if (childToStream.find(i) != childToStream.end()) + n2 = childToStream[i]; + else { + n2 = toStreamRecLFSC(ss2, tp, pf->d_children[i], tb + 1, map); + childToStream[i] = n2; + } // The following branch is dedicated to handling sequences of identical equalities, // i.e. trans[ a=b, a=b, a=b ]. @@ -425,13 +434,13 @@ Node ProofUF::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::E if (((n1[0] == n2[0]) && (n1[1] == n2[1])) || ((n1[0] == n2[1]) && (n1[1] == n2[0]))) { // We are in a sequence of identical equalities - Debug("gk::proof") << "Detected identical equalities: " << std::endl << "\t" << n1 << std::endl; + Debug("pf::uf") << "Detected identical equalities: " << std::endl << "\t" << n1 << std::endl; if (!identicalEqualities) { // The sequence of identical equalities has started just now identicalEqualities = true; - Debug("gk::proof") << "The sequence is just beginning. Determining length..." << std::endl; + Debug("pf::uf") << "The sequence is just beginning. Determining length..." << std::endl; // Determine whether the length of this sequence is odd or even. evenLengthSequence = true; @@ -455,11 +464,11 @@ Node ProofUF::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::E if (evenLengthSequence) { // If the length is even, we need to apply transitivity for the "correct" hand of the equality. - Debug("gk::proof") << "Equality sequence of even length" << std::endl; - Debug("gk::proof") << "n1 is: " << n1 << std::endl; - Debug("gk::proof") << "n2 is: " << n2 << std::endl; - Debug("gk::proof") << "pf-d_node is: " << pf->d_node << std::endl; - Debug("gk::proof") << "Next node is: " << nodeAfterEqualitySequence << std::endl; + Debug("pf::uf") << "Equality sequence of even length" << std::endl; + Debug("pf::uf") << "n1 is: " << n1 << std::endl; + Debug("pf::uf") << "n2 is: " << n2 << std::endl; + Debug("pf::uf") << "pf-d_node is: " << pf->d_node << std::endl; + Debug("pf::uf") << "Next node is: " << nodeAfterEqualitySequence << std::endl; ss << "(trans _ _ _ _ "; @@ -472,7 +481,7 @@ Node ProofUF::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::E n1 = eqNode(n1[1], n1[1]); ss << " (symm _ _ _ " << ss1.str() << ")" << ss1.str(); } else { - Debug("gk::proof") << "Error: identical equalities over, but hands don't match what we're proving." + Debug("pf::uf") << "Error: identical equalities over, but hands don't match what we're proving." << std::endl; Assert(false); } @@ -495,7 +504,7 @@ Node ProofUF::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::E n1 = eqNode(n1[1], n1[1]); } else { - Debug("gk::proof") << "Error: even length sequence, but I don't know which hand to keep!" << std::endl; + Debug("pf::uf") << "Error: even length sequence, but I don't know which hand to keep!" << std::endl; Assert(false); } } @@ -503,11 +512,11 @@ Node ProofUF::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::E ss << ")"; } else { - Debug("gk::proof") << "Equality sequence length is odd!" << std::endl; + Debug("pf::uf") << "Equality sequence length is odd!" << std::endl; ss.str(ss1.str()); } - Debug("gk::proof") << "Have proven: " << n1 << std::endl; + Debug("pf::uf") << "Have proven: " << n1 << std::endl; } else { ss.str(ss1.str()); } @@ -522,21 +531,21 @@ Node ProofUF::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::E identicalEqualities = false; } - Debug("mgd") << "\ndoing trans proof, got n2 " << n2 << "\n"; + Debug("pf::uf") << "\ndoing trans proof, got n2 " << n2 << "\n"; if(tb == 1) { - Debug("mgdx") << "\ntrans proof[" << i << "], got n2 " << n2 << "\n"; - Debug("mgdx") << (n2.getKind() == kind::EQUAL || n2.getKind() == kind::IFF) << "\n"; + Debug("pf::uf") << "\ntrans proof[" << i << "], got n2 " << n2 << "\n"; + Debug("pf::uf") << (n2.getKind() == kind::EQUAL || n2.getKind() == kind::IFF) << "\n"; if ((n1.getNumChildren() >= 2) && (n2.getNumChildren() >= 2)) { - Debug("mgdx") << n1[0].getId() << " " << n1[1].getId() << " / " << n2[0].getId() << " " << n2[1].getId() << "\n"; - Debug("mgdx") << n1[0].getId() << " " << n1[0] << "\n"; - Debug("mgdx") << n1[1].getId() << " " << n1[1] << "\n"; - Debug("mgdx") << n2[0].getId() << " " << n2[0] << "\n"; - Debug("mgdx") << n2[1].getId() << " " << n2[1] << "\n"; - Debug("mgdx") << (n1[0] == n2[0]) << "\n"; - Debug("mgdx") << (n1[1] == n2[1]) << "\n"; - Debug("mgdx") << (n1[0] == n2[1]) << "\n"; - Debug("mgdx") << (n1[1] == n2[0]) << "\n"; + Debug("pf::uf") << n1[0].getId() << " " << n1[1].getId() << " / " << n2[0].getId() << " " << n2[1].getId() << "\n"; + Debug("pf::uf") << n1[0].getId() << " " << n1[0] << "\n"; + Debug("pf::uf") << n1[1].getId() << " " << n1[1] << "\n"; + Debug("pf::uf") << n2[0].getId() << " " << n2[0] << "\n"; + Debug("pf::uf") << n2[1].getId() << " " << n2[1] << "\n"; + Debug("pf::uf") << (n1[0] == n2[0]) << "\n"; + Debug("pf::uf") << (n1[1] == n2[1]) << "\n"; + Debug("pf::uf") << (n1[0] == n2[1]) << "\n"; + Debug("pf::uf") << (n1[1] == n2[0]) << "\n"; } } ss << "(trans _ _ _ _ "; @@ -546,32 +555,32 @@ Node ProofUF::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::E // Both elements of the transitivity rule are equalities/iffs { if(n1[0] == n2[0]) { - if(tb == 1) { Debug("mgdx") << "case 1\n"; } + if(tb == 1) { Debug("pf::uf") << "case 1\n"; } n1 = eqNode(n1[1], n2[1]); ss << "(symm _ _ _ " << ss1.str() << ") " << ss2.str(); } else if(n1[1] == n2[1]) { - if(tb == 1) { Debug("mgdx") << "case 2\n"; } + if(tb == 1) { Debug("pf::uf") << "case 2\n"; } n1 = eqNode(n1[0], n2[0]); ss << ss1.str() << " (symm _ _ _ " << ss2.str() << ")"; } else if(n1[0] == n2[1]) { - if(tb == 1) { Debug("mgdx") << "case 3\n"; } + if(tb == 1) { Debug("pf::uf") << "case 3\n"; } n1 = eqNode(n2[0], n1[1]); ss << ss2.str() << " " << ss1.str(); - if(tb == 1) { Debug("mgdx") << "++ proved " << n1 << "\n"; } + if(tb == 1) { Debug("pf::uf") << "++ proved " << n1 << "\n"; } } else if(n1[1] == n2[0]) { - if(tb == 1) { Debug("mgdx") << "case 4\n"; } + if(tb == 1) { Debug("pf::uf") << "case 4\n"; } n1 = eqNode(n1[0], n2[1]); ss << ss1.str() << " " << ss2.str(); } else { Warning() << "\n\ntrans proof failure at step " << i << "\n\n"; Warning() << "0 proves " << n1 << "\n"; Warning() << "1 proves " << n2 << "\n\n"; - pf->debug_print("mgdx",0); + pf->debug_print("pf::uf",0); //toStreamRec(Warning.getStream(), pf, 0); Warning() << "\n\n"; Unreachable(); } - Debug("mgd") << "++ trans proof[" << i << "], now have " << n1 << std::endl; + Debug("pf::uf") << "++ trans proof[" << i << "], now have " << n1 << std::endl; } else if(n1.getKind() == kind::EQUAL || n1.getKind() == kind::IFF) { // n1 is an equality/iff, but n2 is a predicate if(n1[0] == n2) { @@ -602,90 +611,14 @@ Node ProofUF::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::E ss << ")"; } out << ss.str(); - Debug("mgd") << "\n++ trans proof done, have proven " << n1 << std::endl; + Debug("pf::uf") << "\n++ trans proof done, have proven " << n1 << std::endl; return n1; } - case eq::MERGED_ARRAYS_ROW: { - Debug("mgd") << "row lemma: " << pf->d_node << std::endl; - Assert(pf->d_node.getKind() == kind::EQUAL); - TNode t1, t2, t3, t4; - Node ret; - if(pf->d_node[1].getKind() == kind::SELECT && - pf->d_node[1][0].getKind() == kind::STORE && - pf->d_node[0].getKind() == kind::SELECT && - pf->d_node[0][0] == pf->d_node[1][0][0] && - pf->d_node[0][1] == pf->d_node[1][1]) { - t2 = pf->d_node[1][0][1]; - t3 = pf->d_node[1][1]; - t1 = pf->d_node[0][0]; - t4 = pf->d_node[1][0][2]; - ret = pf->d_node[1].eqNode(pf->d_node[0]); - Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\nt4 " << t4 << "\n"; - } else { - Assert(pf->d_node[0].getKind() == kind::SELECT && - pf->d_node[0][0].getKind() == kind::STORE && - pf->d_node[1].getKind() == kind::SELECT && - pf->d_node[1][0] == pf->d_node[0][0][0] && - pf->d_node[1][1] == pf->d_node[0][1]); - t2 = pf->d_node[0][0][1]; - t3 = pf->d_node[0][1]; - t1 = pf->d_node[1][0]; - t4 = pf->d_node[0][0][2]; - ret = pf->d_node; - Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\nt4 " << t4 << "\n"; - } - out << "(row _ _ "; - tp->printTerm(t2.toExpr(), out, map); - out << " "; - tp->printTerm(t3.toExpr(), out, map); - out << " "; - tp->printTerm(t1.toExpr(), out, map); - out << " "; - tp->printTerm(t4.toExpr(), out, map); - out << " " << ProofManager::getLitName(t2.eqNode(t3)) << ")"; - return ret; - } - - case eq::MERGED_ARRAYS_ROW1: { - Debug("mgd") << "row1 lemma: " << pf->d_node << std::endl; - Assert(pf->d_node.getKind() == kind::EQUAL); - TNode t1, t2, t3; - Node ret; - if(pf->d_node[1].getKind() == kind::SELECT && - pf->d_node[1][0].getKind() == kind::STORE && - pf->d_node[1][0][1] == pf->d_node[1][1] && - pf->d_node[1][0][2] == pf->d_node[0]) { - t1 = pf->d_node[1][0][0]; - t2 = pf->d_node[1][0][1]; - t3 = pf->d_node[0]; - ret = pf->d_node[1].eqNode(pf->d_node[0]); - Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\n"; - } else { - Assert(pf->d_node[0].getKind() == kind::SELECT && - pf->d_node[0][0].getKind() == kind::STORE && - pf->d_node[0][0][1] == pf->d_node[0][1] && - pf->d_node[0][0][2] == pf->d_node[1]); - t1 = pf->d_node[0][0][0]; - t2 = pf->d_node[0][0][1]; - t3 = pf->d_node[1]; - ret = pf->d_node; - Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\n"; - } - out << "(row1 _ _ "; - tp->printTerm(t1.toExpr(), out, map); - out << " "; - tp->printTerm(t2.toExpr(), out, map); - out << " "; - tp->printTerm(t3.toExpr(), out, map); - out << ")"; - return ret; - } - default: Assert(!pf->d_node.isNull()); Assert(pf->d_children.empty()); - Debug("mgd") << "theory proof: " << pf->d_node << " by rule " << int(pf->d_id) << std::endl; + Debug("pf::uf") << "theory proof: " << pf->d_node << " by rule " << int(pf->d_id) << std::endl; AlwaysAssert(false); return pf->d_node; } @@ -722,8 +655,10 @@ void UFProof::registerTerm(Expr term) { } } -void LFSCUFProof::printTerm(Expr term, std::ostream& os, const LetMap& map) { - Assert (Theory::theoryOf(term) == THEORY_UF); +void LFSCUFProof::printOwnedTerm(Expr term, std::ostream& os, const LetMap& map) { + Debug("pf::uf") << std::endl << "(pf::uf) LFSCUfProof::printOwnedTerm: term = " << term << std::endl; + + Assert (theory::Theory::theoryOf(term) == theory::THEORY_UF); if (term.getKind() == kind::VARIABLE || term.getKind() == kind::SKOLEM) { @@ -742,7 +677,7 @@ void LFSCUFProof::printTerm(Expr term, std::ostream& os, const LetMap& map) { } os << func << " "; for (unsigned i = 0; i < term.getNumChildren(); ++i) { - printTerm(term[i], os, map); + d_proofEngine->printBoundTerm(term[i], os, map); os << ")"; } if(term.getType().isBoolean()) { @@ -750,7 +685,9 @@ void LFSCUFProof::printTerm(Expr term, std::ostream& os, const LetMap& map) { } } -void LFSCUFProof::printSort(Type type, std::ostream& os) { +void LFSCUFProof::printOwnedSort(Type type, std::ostream& os) { + Debug("pf::uf") << std::endl << "(pf::uf) LFSCArrayProof::printOwnedSort: type is: " << type << std::endl; + Assert (type.isSort()); os << type <<" "; } @@ -765,13 +702,17 @@ void LFSCUFProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& UFProof::printTheoryLemmaProof( lemma, os, paren ); } -void LFSCUFProof::printDeclarations(std::ostream& os, std::ostream& paren) { - // declaring the sorts +void LFSCUFProof::printSortDeclarations(std::ostream& os, std::ostream& paren) { for (TypeSet::const_iterator it = d_sorts.begin(); it != d_sorts.end(); ++it) { - os << "(% " << *it << " sort\n"; - paren << ")"; + if (!ProofManager::currentPM()->wasPrinted(*it)) { + os << "(% " << *it << " sort\n"; + paren << ")"; + ProofManager::currentPM()->markPrinted(*it); + } } +} +void LFSCUFProof::printTermDeclarations(std::ostream& os, std::ostream& paren) { // declaring the terms for (ExprSet::const_iterator it = d_declarations.begin(); it != d_declarations.end(); ++it) { Expr term = *it; @@ -802,3 +743,9 @@ void LFSCUFProof::printDeclarations(std::ostream& os, std::ostream& paren) { paren << ")"; } } + +void LFSCUFProof::printDeferredDeclarations(std::ostream& os, std::ostream& paren) { + // Nothing to do here at this point. +} + +} /* namespace CVC4 */ diff --git a/src/proof/uf_proof.h b/src/proof/uf_proof.h index 121db1fcd..e359eaebd 100644 --- a/src/proof/uf_proof.h +++ b/src/proof/uf_proof.h @@ -1,13 +1,13 @@ /********************* */ /*! \file uf_proof.h ** \verbatim - ** Original author: Liana Hadarean - ** Major contributors: none - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Liana Hadarean, Guy Katz, 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 UF proof ** @@ -37,7 +37,7 @@ public: static void toStreamLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, const LetMap& map); }; - + namespace theory { namespace uf { class TheoryUF; @@ -51,7 +51,7 @@ class UFProof : public TheoryProof { protected: TypeSet d_sorts; // all the uninterpreted sorts in this theory ExprSet d_declarations; // all the variable/function declarations - + public: UFProof(theory::uf::TheoryUF* uf, TheoryProofEngine* proofEngine); @@ -63,10 +63,12 @@ public: LFSCUFProof(theory::uf::TheoryUF* uf, TheoryProofEngine* proofEngine) : UFProof(uf, proofEngine) {} - virtual void printTerm(Expr term, std::ostream& os, const LetMap& map); - virtual void printSort(Type type, std::ostream& os); + virtual void printOwnedTerm(Expr term, std::ostream& os, const LetMap& map); + virtual void printOwnedSort(Type type, std::ostream& os); virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren); - virtual void printDeclarations(std::ostream& os, std::ostream& paren); + virtual void printSortDeclarations(std::ostream& os, std::ostream& paren); + virtual void printTermDeclarations(std::ostream& os, std::ostream& paren); + virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren); }; diff --git a/src/proof/unsat_core.cpp b/src/proof/unsat_core.cpp index 2b559d117..4c940e4be 100644 --- a/src/proof/unsat_core.cpp +++ b/src/proof/unsat_core.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file unsat_core.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** 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 Representation of unsat cores ** diff --git a/src/proof/unsat_core.h b/src/proof/unsat_core.h index 8e92fe3d1..a238f0a6a 100644 --- a/src/proof/unsat_core.h +++ b/src/proof/unsat_core.h @@ -1,13 +1,13 @@ /********************* */ /*! \file unsat_core.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Morgan Deters, Tim King, 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/prop/bvminisat/bvminisat.cpp b/src/prop/bvminisat/bvminisat.cpp index 936778e0d..54e3f2e8b 100644 --- a/src/prop/bvminisat/bvminisat.cpp +++ b/src/prop/bvminisat/bvminisat.cpp @@ -19,6 +19,7 @@ #include "prop/bvminisat/bvminisat.h" #include "prop/bvminisat/simp/SimpSolver.h" +#include "proof/clause_id.h" #include "proof/sat_proof.h" #include "util/statistics_registry.h" diff --git a/src/prop/bvminisat/bvminisat.h b/src/prop/bvminisat/bvminisat.h index ec8c3455a..20724efd2 100644 --- a/src/prop/bvminisat/bvminisat.h +++ b/src/prop/bvminisat/bvminisat.h @@ -21,6 +21,7 @@ #pragma once #include "context/cdo.h" +#include "proof/clause_id.h" #include "prop/bvminisat/simp/SimpSolver.h" #include "prop/sat_solver.h" #include "util/statistics_registry.h" diff --git a/src/prop/bvminisat/core/Solver.cc b/src/prop/bvminisat/core/Solver.cc index 2100160de..d626a5d15 100644 --- a/src/prop/bvminisat/core/Solver.cc +++ b/src/prop/bvminisat/core/Solver.cc @@ -30,11 +30,12 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "mtl/Sort.h" #include "options/bv_options.h" #include "options/smt_options.h" -#include "theory/interrupted.h" -#include "proof/proof_manager.h" #include "proof/bitvector_proof.h" +#include "proof/clause_id.h" +#include "proof/proof_manager.h" #include "proof/sat_proof.h" #include "proof/sat_proof_implementation.h" +#include "theory/interrupted.h" #include "util/utility.h" namespace CVC4 { diff --git a/src/prop/bvminisat/core/Solver.h b/src/prop/bvminisat/core/Solver.h index 019c09bcd..555495149 100644 --- a/src/prop/bvminisat/core/Solver.h +++ b/src/prop/bvminisat/core/Solver.h @@ -21,20 +21,21 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #ifndef BVMinisat_Solver_h #define BVMinisat_Solver_h +#include <ext/hash_set> +#include <vector> + +#include "context/context.h" +#include "proof/clause_id.h" +#include "proof/sat_proof.h" #include "prop/bvminisat/core/SolverTypes.h" -#include "prop/bvminisat/mtl/Vec.h" -#include "prop/bvminisat/mtl/Heap.h" #include "prop/bvminisat/mtl/Alg.h" +#include "prop/bvminisat/mtl/Heap.h" +#include "prop/bvminisat/mtl/Vec.h" #include "prop/bvminisat/utils/Options.h" -#include "context/cdhashmap.h" -#include "proof/sat_proof.h" -#include <ext/hash_set> -#include <vector> namespace CVC4 { -typedef unsigned ClauseId; namespace BVMinisat { class Solver; } diff --git a/src/prop/bvminisat/simp/SimpSolver.cc b/src/prop/bvminisat/simp/SimpSolver.cc index 311ed1dd1..cb5929320 100644 --- a/src/prop/bvminisat/simp/SimpSolver.cc +++ b/src/prop/bvminisat/simp/SimpSolver.cc @@ -23,8 +23,9 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "mtl/Sort.h" #include "options/bv_options.h" #include "options/smt_options.h" -#include "utils/System.h" +#include "proof/clause_id.h" #include "proof/proof.h" +#include "utils/System.h" namespace CVC4 { namespace BVMinisat { diff --git a/src/prop/bvminisat/simp/SimpSolver.h b/src/prop/bvminisat/simp/SimpSolver.h index 5f6f46b91..9854bf77d 100644 --- a/src/prop/bvminisat/simp/SimpSolver.h +++ b/src/prop/bvminisat/simp/SimpSolver.h @@ -22,6 +22,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #define BVMinisat_SimpSolver_h #include "context/context.h" +#include "proof/clause_id.h" #include "prop/bvminisat/core/Solver.h" #include "prop/bvminisat/mtl/Queue.h" #include "util/statistics_registry.h" diff --git a/src/prop/cnf_stream.cpp b/src/prop/cnf_stream.cpp index d54848d26..aa1fc9587 100644 --- a/src/prop/cnf_stream.cpp +++ b/src/prop/cnf_stream.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file cnf_stream.cpp ** \verbatim - ** Original author: Tim King - ** Major contributors: Morgan Deters, Dejan Jovanovic - ** Minor contributors (to current version): Kshitij Bansal, Liana Hadarean, Christopher L. Conway, Andrew Reynolds + ** 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 A CNF converter that takes in asserts and has the side effect ** of given an equisatisfiable stream of assertions to PropEngine. @@ -15,6 +15,8 @@ ** A CNF converter that takes in asserts and has the side effect ** of given an equisatisfiable stream of assertions to PropEngine. **/ +#include "prop/cnf_stream.h" + #include <queue> #include "base/cvc4_assert.h" @@ -22,10 +24,10 @@ #include "expr/expr.h" #include "expr/node.h" #include "options/bv_options.h" +#include "proof/clause_id.h" +#include "proof/cnf_proof.h" #include "proof/proof_manager.h" #include "proof/sat_proof.h" -#include "proof/cnf_proof.h" -#include "prop/cnf_stream.h" #include "prop/minisat/minisat.h" #include "prop/prop_engine.h" #include "prop/theory_proxy.h" @@ -672,7 +674,8 @@ void TseitinCnfStream::convertAndAssert(TNode node, bool removable, bool negated, ProofRule proof_id, - TNode from) { + TNode from, + theory::TheoryId ownerTheory) { Debug("cnf") << "convertAndAssert(" << node << ", removable = " << (removable ? "true" : "false") << ", negated = " << (negated ? "true" : "false") << ")" << endl; @@ -682,6 +685,7 @@ void TseitinCnfStream::convertAndAssert(TNode node, Node assertion = negated ? node.notNode() : (Node)node; Node from_assertion = negated? from.notNode() : (Node) from; + d_cnfProof->setExplainerTheory(ownerTheory); if (proof_id != RULE_INVALID) { d_cnfProof->pushCurrentAssertion(from.isNull() ? assertion : from_assertion); d_cnfProof->registerAssertion(from.isNull() ? assertion : from_assertion, proof_id); @@ -693,7 +697,10 @@ void TseitinCnfStream::convertAndAssert(TNode node, }); convertAndAssert(node, negated); - PROOF(if (d_cnfProof) d_cnfProof->popCurrentAssertion(); ); + PROOF + (if (d_cnfProof) { + d_cnfProof->popCurrentAssertion(); + }); } void TseitinCnfStream::convertAndAssert(TNode node, bool negated) { diff --git a/src/prop/cnf_stream.h b/src/prop/cnf_stream.h index a6b6781ca..cf9d519a7 100644 --- a/src/prop/cnf_stream.h +++ b/src/prop/cnf_stream.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cnf_stream.h ** \verbatim - ** Original author: Tim King - ** Major contributors: Morgan Deters, Dejan Jovanovic - ** Minor contributors (to current version): Clark Barrett, Liana Hadarean, Christopher L. Conway, 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 class transforms a sequence of formulas into clauses. ** @@ -207,9 +207,14 @@ public: * @param node node to convert and assert * @param removable whether the sat solver can choose to remove the clauses * @param negated whether we are asserting the node negated + * @param ownerTheory indicates the theory that should invoked to prove the formula. */ - virtual void convertAndAssert(TNode node, bool removable, bool negated, ProofRule proof_id, TNode from = TNode::null()) = 0; - + virtual void convertAndAssert(TNode node, + bool removable, + bool negated, + ProofRule proof_id, + TNode from = TNode::null(), + theory::TheoryId ownerTheory = theory::THEORY_LAST) = 0; /** * Get the node that is represented by the given SatLiteral. * @param literal the literal from the sat solver @@ -278,7 +283,8 @@ public: * @param negated true if negated */ void convertAndAssert(TNode node, bool removable, - bool negated, ProofRule rule, TNode from = TNode::null()); + bool negated, ProofRule rule, TNode from = TNode::null(), + theory::TheoryId ownerTheory = theory::THEORY_LAST); /** * Constructs the stream to use the given sat solver. diff --git a/src/prop/minisat/core/Solver.cc b/src/prop/minisat/core/Solver.cc index b7fb1603d..411b89514 100644 --- a/src/prop/minisat/core/Solver.cc +++ b/src/prop/minisat/core/Solver.cc @@ -18,21 +18,22 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************************************/ +#include "prop/minisat/core/Solver.h" + #include <math.h> #include <iostream> #include "base/output.h" #include "options/prop_options.h" +#include "proof/clause_id.h" #include "proof/proof_manager.h" #include "proof/sat_proof_implementation.h" #include "proof/sat_proof.h" -#include "prop/minisat/core/Solver.h" #include "prop/minisat/minisat.h" #include "prop/minisat/mtl/Sort.h" #include "prop/theory_proxy.h" - using namespace CVC4::prop; namespace CVC4 { @@ -229,7 +230,7 @@ CRef Solver::reason(Var x) { proxy->explainPropagation(MinisatSatSolver::toSatLiteral(l), explanation_cl); vec<Lit> explanation; - MinisatSatSolver::toMinisatClause(explanation_cl, explanation); + MinisatSatSolver::toMinisatClause(explanation_cl, explanation); // Sort the literals by trail index level lemma_lt lt(*this); @@ -602,20 +603,20 @@ Lit Solver::pickBranchLit() /*_________________________________________________________________________________________________ | | analyze : (confl : Clause*) (out_learnt : vec<Lit>&) (out_btlevel : int&) -> [void] -| +| | Description: | Analyze conflict and produce a reason clause. -| +| | Pre-conditions: | * 'out_learnt' is assumed to be cleared. | * Current decision level must be greater than root level. -| +| | Post-conditions: | * 'out_learnt[0]' is the asserting literal at level 'out_btlevel'. -| * If out_learnt.size() > 1 then 'out_learnt[1]' has the greatest decision level of the +| * If out_learnt.size() > 1 then 'out_learnt[1]' has the greatest decision level of the | rest of literals. There may be others from the same level though. | * returns the maximal level of the resolved clauses -| +| |________________________________________________________________________________________________@*/ int Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel) { @@ -661,14 +662,14 @@ int Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel) } } } - + // Select next clause to look at: while (!seen[var(trail[index--])]); p = trail[index+1]; confl = reason(var(p)); seen[var(p)] = 0; pathC--; - + if ( pathC > 0 && confl != CRef_Undef ) { PROOF( ProofManager::getSatProof()->addResolutionStep(p, confl, sign(p)); ) } @@ -694,13 +695,13 @@ int Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel) out_learnt[j++] = out_learnt[i]; } else { PROOF( ProofManager::getSatProof()->storeLitRedundant(out_learnt[i]); ) - // Literal is redundant, to be safe, mark the level as current assertion level + // Literal is redundant, to be safe, mark the level as current assertion level // TODO: maybe optimize max_resolution_level = std::max(max_resolution_level, user_level(var(out_learnt[i]))); } } } - + }else if (ccmin_mode == 1){ Unreachable(); for (i = j = 1; i < out_learnt.size(); i++){ @@ -786,7 +787,7 @@ bool Solver::litRedundant(Lit p, uint32_t abstract_levels) /*_________________________________________________________________________________________________ | | analyzeFinal : (p : Lit) -> [void] -| +| | Description: | Specialized analysis procedure to express the final conflict in terms of assumptions. | Calculates the (possibly empty) set of assumptions that led to the assignment of 'p', and @@ -865,7 +866,7 @@ CRef Solver::propagate(TheoryCheckType type) if (lemmas.size() > 0) { recheck = true; confl = updateLemmas(); - return confl; + return confl; } else { recheck = proxy->theoryNeedCheck(); return confl; @@ -921,7 +922,7 @@ void Solver::propagateTheory() { proxy->theoryPropagate(propagatedLiteralsClause); vec<Lit> propagatedLiterals; - MinisatSatSolver::toMinisatClause(propagatedLiteralsClause, propagatedLiterals); + MinisatSatSolver::toMinisatClause(propagatedLiteralsClause, propagatedLiterals); int oldTrailSize = trail.size(); Debug("minisat") << "old trail size is " << oldTrailSize << ", propagating " << propagatedLiterals.size() << " lits..." << std::endl; @@ -963,11 +964,11 @@ void Solver::theoryCheck(CVC4::theory::Theory::Effort effort) /*_________________________________________________________________________________________________ | | propagateBool : [void] -> [Clause*] -| +| | Description: | Propagates all enqueued facts. If a conflict arises, the conflicting clause is returned, | otherwise CRef_Undef. -| +| | Post-conditions: | * the propagation queue is empty, even if there was a conflict. |________________________________________________________________________________________________@*/ @@ -1037,16 +1038,16 @@ CRef Solver::propagateBool() /*_________________________________________________________________________________________________ | | reduceDB : () -> [void] -| +| | Description: | Remove half of the learnt clauses, minus the clauses locked by the current assignment. Locked | clauses are clauses that are reason to some assignment. Binary clauses are never removed. |________________________________________________________________________________________________@*/ -struct reduceDB_lt { +struct reduceDB_lt { ClauseAllocator& ca; reduceDB_lt(ClauseAllocator& ca_) : ca(ca_) {} - bool operator () (CRef x, CRef y) { - return ca[x].size() > 2 && (ca[y].size() == 2 || ca[x].activity() < ca[y].activity()); } + bool operator () (CRef x, CRef y) { + return ca[x].size() > 2 && (ca[y].size() == 2 || ca[x].activity() < ca[y].activity()); } }; void Solver::reduceDB() { @@ -1114,7 +1115,7 @@ void Solver::rebuildOrderHeap() /*_________________________________________________________________________________________________ | | simplify : [void] -> [bool] -| +| | Description: | Simplify the clause database according to the current top-level assigment. Currently, the only | thing done here is the removal of satisfied clauses, but more things can be put here. @@ -1146,11 +1147,11 @@ bool Solver::simplify() /*_________________________________________________________________________________________________ | | search : (nof_conflicts : int) (params : const SearchParams&) -> [lbool] -| +| | Description: -| Search for a model the specified number of conflicts. +| Search for a model the specified number of conflicts. | NOTE! Use negative value for 'nof_conflicts' indicate infinity. -| +| | Output: | 'l_True' if a partial assigment that is consistent with respect to the clauseset is found. If | all variables are decision variables, this means that the clause set is satisfiable. 'l_False' @@ -1219,9 +1220,9 @@ lbool Solver::search(int nof_conflicts) max_learnts *= learntsize_inc; if (verbosity >= 1) - printf("| %9d | %7d %8d %8d | %8d %8d %6.0f | %6.3f %% |\n", - (int)conflicts, - (int)dec_vars - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]), nClauses(), (int)clauses_literals, + printf("| %9d | %7d %8d %8d | %8d %8d %6.0f | %6.3f %% |\n", + (int)conflicts, + (int)dec_vars - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]), nClauses(), (int)clauses_literals, (int)max_learnts, nLearnts(), (double)learnts_literals/nLearnts(), progressEstimate()*100); } @@ -1417,7 +1418,7 @@ lbool Solver::solve_() //================================================================================================= // Writing CNF to DIMACS: -// +// // FIXME: this needs to be rewritten completely. static Var mapVar(Var x, vec<Var>& map, Var& max) @@ -1466,7 +1467,7 @@ void Solver::toDimacs(FILE* f, const vec<Lit>& assumps) for (int i = 0; i < clauses_persistent.size(); i++) if (!satisfied(ca[clauses_persistent[i]])) cnt++; - + for (int i = 0; i < clauses_persistent.size(); i++) if (!satisfied(ca[clauses_persistent[i]])){ Clause& c = ca[clauses_persistent[i]]; @@ -1537,11 +1538,11 @@ void Solver::garbageCollect() { // Initialize the next region to a size corresponding to the estimated utilization degree. This // is not precise but should avoid some unnecessary reallocations for the new region: - ClauseAllocator to(ca.size() - ca.wasted()); + ClauseAllocator to(ca.size() - ca.wasted()); relocAll(to); if (verbosity >= 2) - printf("| Garbage collection: %12d bytes => %12d bytes |\n", + printf("| Garbage collection: %12d bytes => %12d bytes |\n", ca.size()*ClauseAllocator::Unit_Size, to.size()*ClauseAllocator::Unit_Size); to.moveTo(ca); } @@ -1698,7 +1699,7 @@ CRef Solver::updateLemmas() { int backtrack_index = trail.size(); PROOF(Assert (lemmas.size() == (int)lemmas_cnf_assertion.size());); - + // Attach all the clauses and enqueue all the propagations for (int i = 0; i < lemmas.size(); ++ i) { @@ -1739,7 +1740,7 @@ CRef Solver::updateLemmas() { ( Node cnf_assertion = lemmas_cnf_assertion[i].first; Node cnf_def = lemmas_cnf_assertion[i].second; - + ClauseId id = ProofManager::getSatProof()->registerUnitClause(lemma[0], THEORY_LEMMA); ProofManager::getCnfProof()->setClauseAssertion(id, cnf_assertion); ProofManager::getCnfProof()->setClauseDefinition(id, cnf_def); @@ -1784,20 +1785,20 @@ CRef Solver::updateLemmas() { void ClauseAllocator::reloc(CRef& cr, ClauseAllocator& to, CVC4::CoreProofProxy* proxy) { - + // FIXME what is this CRef_lazy if (cr == CRef_Lazy) return; - + CRef old = cr; // save the old reference Clause& c = operator[](cr); if (c.reloced()) { cr = c.relocation(); return; } - + cr = to.alloc(c.level(), c, c.removable()); c.relocate(cr); if (proxy) { - proxy->updateCRef(old, cr); + proxy->updateCRef(old, cr); } - // Copy extra data-fields: + // Copy extra data-fields: // (This could be cleaned-up. Generalize Clause-constructor to be applicable here instead?) to[cr].mark(c.mark()); if (to[cr].removable()) to[cr].activity() = c.activity(); diff --git a/src/prop/minisat/core/Solver.h b/src/prop/minisat/core/Solver.h index 777fb1093..99c47e045 100644 --- a/src/prop/minisat/core/Solver.h +++ b/src/prop/minisat/core/Solver.h @@ -27,6 +27,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "base/output.h" #include "context/context.h" +#include "proof/clause_id.h" #include "prop/minisat/core/SolverTypes.h" #include "prop/minisat/mtl/Alg.h" #include "prop/minisat/mtl/Heap.h" @@ -43,7 +44,6 @@ namespace prop { }/* CVC4::prop namespace */ }/* CVC4 namespace */ -typedef unsigned ClauseId; namespace CVC4 { namespace Minisat { diff --git a/src/prop/minisat/minisat.cpp b/src/prop/minisat/minisat.cpp index 739d9087a..bfbf9da6f 100644 --- a/src/prop/minisat/minisat.cpp +++ b/src/prop/minisat/minisat.cpp @@ -23,6 +23,7 @@ #include "options/prop_options.h" #include "options/smt_options.h" #include "prop/minisat/simp/SimpSolver.h" +#include "proof/clause_id.h" #include "proof/sat_proof.h" #include "util/statistics_registry.h" diff --git a/src/prop/minisat/simp/SimpSolver.cc b/src/prop/minisat/simp/SimpSolver.cc index 5bdaea950..9b551fa70 100644 --- a/src/prop/minisat/simp/SimpSolver.cc +++ b/src/prop/minisat/simp/SimpSolver.cc @@ -18,10 +18,12 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************************************/ +#include "prop/minisat/simp/SimpSolver.h" + #include "options/prop_options.h" +#include "proof/clause_id.h" #include "proof/proof.h" #include "prop/minisat/mtl/Sort.h" -#include "prop/minisat/simp/SimpSolver.h" #include "prop/minisat/utils/System.h" using namespace CVC4; diff --git a/src/prop/minisat/simp/SimpSolver.h b/src/prop/minisat/simp/SimpSolver.h index a19bec1ef..a995c1357 100644 --- a/src/prop/minisat/simp/SimpSolver.h +++ b/src/prop/minisat/simp/SimpSolver.h @@ -23,6 +23,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "cvc4_private.h" +#include "proof/clause_id.h" #include "prop/minisat/mtl/Queue.h" #include "prop/minisat/core/Solver.h" diff --git a/src/prop/prop_engine.cpp b/src/prop/prop_engine.cpp index 583e9da18..54cf4c457 100644 --- a/src/prop/prop_engine.cpp +++ b/src/prop/prop_engine.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file prop_engine.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Dejan Jovanovic - ** Minor contributors (to current version): Clark Barrett, Liana Hadarean, Kshitij Bansal, Christopher L. Conway, 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 Implementation of the propositional engine of CVC4 ** @@ -132,12 +132,13 @@ void PropEngine::assertFormula(TNode node) { void PropEngine::assertLemma(TNode node, bool negated, bool removable, ProofRule rule, + theory::TheoryId ownerTheory, TNode from) { //Assert(d_inCheckSat, "Sat solver should be in solve()!"); Debug("prop::lemmas") << "assertLemma(" << node << ")" << endl; // Assert as (possibly) removable - d_cnfStream->convertAndAssert(node, removable, negated, rule, from); + d_cnfStream->convertAndAssert(node, removable, negated, rule, from, ownerTheory); } void PropEngine::requirePhase(TNode n, bool phase) { diff --git a/src/prop/prop_engine.h b/src/prop/prop_engine.h index a71d4832d..b9ce7ca7e 100644 --- a/src/prop/prop_engine.h +++ b/src/prop/prop_engine.h @@ -1,13 +1,13 @@ /********************* */ /*! \file prop_engine.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Dejan Jovanovic - ** Minor contributors (to current version): Clark Barrett, Liana Hadarean, Christopher L. Conway, Kshitij Bansal, 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 The PropEngine (propositional engine); main interface point ** between CVC4's SMT infrastructure and the SAT solver @@ -134,7 +134,7 @@ public: * @param removable whether this lemma can be quietly removed based * on an activity heuristic (or not) */ - void assertLemma(TNode node, bool negated, bool removable, ProofRule rule, TNode from = TNode::null()); + void assertLemma(TNode node, bool negated, bool removable, ProofRule rule, theory::TheoryId ownerTheory, TNode from = TNode::null()); /** * If ever n is decided upon, it must be in the given phase. This diff --git a/src/prop/registrar.h b/src/prop/registrar.h index b6dd021ab..bd8088921 100644 --- a/src/prop/registrar.h +++ b/src/prop/registrar.h @@ -1,13 +1,13 @@ /********************* */ /*! \file registrar.h ** \verbatim - ** Original author: Liana Hadarean - ** Major contributors: Tim King, Morgan Deters - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Morgan Deters, Tim King, 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/prop/sat_solver.h b/src/prop/sat_solver.h index 1383308a3..92696ae25 100644 --- a/src/prop/sat_solver.h +++ b/src/prop/sat_solver.h @@ -1,13 +1,13 @@ /********************* */ /*! \file sat_solver.h ** \verbatim - ** Original author: Dejan Jovanovic - ** Major contributors: Morgan Deters, Liana Hadarean - ** Minor contributors (to current version): none + ** 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 SAT Solver. ** @@ -26,6 +26,7 @@ #include "context/cdlist.h" #include "context/context.h" #include "expr/node.h" +#include "proof/clause_id.h" #include "prop/sat_solver_types.h" #include "util/statistics_registry.h" @@ -37,8 +38,6 @@ namespace prop { class TheoryProxy; -typedef unsigned ClauseId; - class SatSolver { public: diff --git a/src/prop/sat_solver_factory.cpp b/src/prop/sat_solver_factory.cpp index c131ca475..092ec72f2 100644 --- a/src/prop/sat_solver_factory.cpp +++ b/src/prop/sat_solver_factory.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file sat_solver_factory.cpp ** \verbatim - ** Original author: Dejan Jovanovic - ** Major contributors: Tim King - ** Minor contributors (to current version): Morgan Deters, Liana Hadarean + ** 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 SAT Solver creation facility. ** diff --git a/src/prop/sat_solver_factory.h b/src/prop/sat_solver_factory.h index 6a3053a18..7cc23a8e8 100644 --- a/src/prop/sat_solver_factory.h +++ b/src/prop/sat_solver_factory.h @@ -1,13 +1,13 @@ /********************* */ /*! \file sat_solver_factory.h ** \verbatim - ** Original author: Dejan Jovanovic - ** Major contributors: none - ** Minor contributors (to current version): Liana Hadarean, Morgan Deters + ** 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 SAT Solver. ** diff --git a/src/prop/sat_solver_types.h b/src/prop/sat_solver_types.h index c47c2b67b..557f9af65 100644 --- a/src/prop/sat_solver_types.h +++ b/src/prop/sat_solver_types.h @@ -1,13 +1,13 @@ /********************* */ /*! \file sat_solver_types.h ** \verbatim - ** Original author: Dejan Jovanovic - ** Major contributors: none - ** Minor contributors (to current version): Morgan Deters, Liana Hadarean, Kshitij Bansal + ** Top contributors (to current version): + ** Dejan Jovanovic, 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 This class transforms a sequence of formulas into clauses. ** diff --git a/src/prop/theory_proxy.cpp b/src/prop/theory_proxy.cpp index 63a09169f..4a4515eb9 100644 --- a/src/prop/theory_proxy.cpp +++ b/src/prop/theory_proxy.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file theory_proxy.cpp ** \verbatim - ** Original author: Dejan Jovanovic - ** Major contributors: Kshitij Bansal, Morgan Deters - ** Minor contributors (to current version): Clark Barrett, Christopher L. Conway, Tim King, Liana Hadarean + ** Top contributors (to current version): + ** Morgan Deters, Tim King, 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 ]] ** @@ -98,19 +98,30 @@ void TheoryProxy::theoryPropagate(std::vector<SatLiteral>& output) { void TheoryProxy::explainPropagation(SatLiteral l, SatClause& explanation) { TNode lNode = d_cnfStream->getNode(l); Debug("prop-explain") << "explainPropagation(" << lNode << ")" << std::endl; - Node theoryExplanation = d_theoryEngine->getExplanation(lNode); - PROOF(ProofManager::getCnfProof()->pushCurrentAssertion(theoryExplanation); ); - Debug("prop-explain") << "explainPropagation() => " << theoryExplanation << std::endl; - if (theoryExplanation.getKind() == kind::AND) { - Node::const_iterator it = theoryExplanation.begin(); - Node::const_iterator it_end = theoryExplanation.end(); + + NodeTheoryPair theoryExplanation = d_theoryEngine->getExplanationAndExplainer(lNode); + Node explanationNode = theoryExplanation.node; + theory::TheoryId explainerTheory = theoryExplanation.theory; + + PROOF({ + ProofManager::getCnfProof()->pushCurrentAssertion(explanationNode); + ProofManager::getCnfProof()->setExplainerTheory(explainerTheory); + + Debug("pf::sat") << "TheoryProxy::explainPropagation: setting explainer theory to: " + << explainerTheory << std::endl; + }); + + Debug("prop-explain") << "explainPropagation() => " << explanationNode << std::endl; + if (explanationNode.getKind() == kind::AND) { + Node::const_iterator it = explanationNode.begin(); + Node::const_iterator it_end = explanationNode.end(); explanation.push_back(l); for (; it != it_end; ++ it) { explanation.push_back(~d_cnfStream->getLiteral(*it)); } } else { explanation.push_back(l); - explanation.push_back(~d_cnfStream->getLiteral(theoryExplanation)); + explanation.push_back(~d_cnfStream->getLiteral(explanationNode)); } } @@ -164,7 +175,7 @@ void TheoryProxy::notifyRestart() { if(lemmaCount % 1 == 0) { Debug("shared") << "=) " << asNode << std::endl; } - d_propEngine->assertLemma(d_theoryEngine->preprocess(asNode), false, true, RULE_INVALID); + d_propEngine->assertLemma(d_theoryEngine->preprocess(asNode), false, true, RULE_INVALID, theory::THEORY_LAST); } else { Debug("shared") << "=(" << asNode << std::endl; } diff --git a/src/prop/theory_proxy.h b/src/prop/theory_proxy.h index 0e2b885d9..88c6ca94a 100644 --- a/src/prop/theory_proxy.h +++ b/src/prop/theory_proxy.h @@ -1,13 +1,13 @@ /********************* */ /*! \file theory_proxy.h ** \verbatim - ** Original author: Dejan Jovanovic - ** Major contributors: Liana Hadarean, Kshitij Bansal, Morgan Deters - ** Minor contributors (to current version): Christopher L. Conway, Tim King + ** 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 SAT Solver. ** diff --git a/src/smt/boolean_terms.cpp b/src/smt/boolean_terms.cpp index 07d78a6fd..40b757598 100644 --- a/src/smt/boolean_terms.cpp +++ b/src/smt/boolean_terms.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file boolean_terms.cpp ** \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 [[ Add one-line brief description here ]] ** @@ -137,26 +137,6 @@ Node BooleanTermConverter::rewriteAs(TNode in, TypeNode as, std::map< TypeNode, TypeNode in_t = in.getType(); if( processing.find( in_t )==processing.end() ){ processing[in_t] = true; - if(in.getType().isRecord()) { - Assert(as.isRecord()); - const Record& inRec = in.getType().getRecord(); - const Record& asRec = as.getRecord(); - Assert(inRec.getNumFields() == asRec.getNumFields()); - const Datatype & dt = ((DatatypeType)in.getType().toType()).getDatatype(); - NodeBuilder<> nb(kind::APPLY_CONSTRUCTOR); - nb << NodeManager::currentNM()->mkConst(asRec); - for(size_t i = 0; i < asRec.getNumFields(); ++i) { - Assert(inRec[i].first == asRec[i].first); - Node arg = NodeManager::currentNM()->mkNode(kind::APPLY_SELECTOR_TOTAL, dt[0][i].getSelector(), in); - if(inRec[i].second != asRec[i].second) { - arg = rewriteAs(arg, TypeNode::fromType(asRec[i].second), processing); - } - nb << arg; - } - Node out = nb; - processing.erase( in_t ); - return out; - } if(in.getType().isDatatype()) { if(as.isBoolean() && in.getType().hasAttribute(BooleanTermAttr())) { processing.erase( in_t ); diff --git a/src/smt/boolean_terms.h b/src/smt/boolean_terms.h index e1865f29f..0a63f7fd8 100644 --- a/src/smt/boolean_terms.h +++ b/src/smt/boolean_terms.h @@ -1,13 +1,13 @@ /********************* */ /*! \file boolean_terms.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** 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 [[ Add one-line brief description here ]] ** diff --git a/src/smt/command.cpp b/src/smt/command.cpp index d6ec0769a..bd514e2a8 100644 --- a/src/smt/command.cpp +++ b/src/smt/command.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file command.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Kshitij Bansal, Dejan Jovanovic, Andrew Reynolds, Francois Bobot + ** Top contributors (to current version): + ** Morgan Deters, Andrew Reynolds, Francois Bobot ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2014 New York University and The University of Iowa - ** See the file COPYING in the top-level source directory for licensing - ** information.\endverbatim + ** Copyright (c) 2009-2016 by the authors listed in the file AUTHORS + ** in the top-level 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 command objects. ** @@ -376,6 +376,59 @@ std::string QueryCommand::getCommandName() const throw() { return "query"; } + +/* class CheckSynthCommand */ + +CheckSynthCommand::CheckSynthCommand() throw() : + d_expr() { +} + +CheckSynthCommand::CheckSynthCommand(const Expr& expr, bool inUnsatCore) throw() : + d_expr(expr), d_inUnsatCore(inUnsatCore) { +} + +Expr CheckSynthCommand::getExpr() const throw() { + return d_expr; +} + +void CheckSynthCommand::invoke(SmtEngine* smtEngine) throw() { + try { + d_result = smtEngine->checkSynth(d_expr); + d_commandStatus = CommandSuccess::instance(); + } catch(exception& e) { + d_commandStatus = new CommandFailure(e.what()); + } +} + +Result CheckSynthCommand::getResult() const throw() { + return d_result; +} + +void CheckSynthCommand::printResult(std::ostream& out, uint32_t verbosity) const throw() { + if(! ok()) { + this->Command::printResult(out, verbosity); + } else { + out << d_result << endl; + } +} + +Command* CheckSynthCommand::exportTo(ExprManager* exprManager, ExprManagerMapCollection& variableMap) { + CheckSynthCommand* c = new CheckSynthCommand(d_expr.exportTo(exprManager, variableMap), d_inUnsatCore); + c->d_result = d_result; + return c; +} + +Command* CheckSynthCommand::clone() const { + CheckSynthCommand* c = new CheckSynthCommand(d_expr, d_inUnsatCore); + c->d_result = d_result; + return c; +} + +std::string CheckSynthCommand::getCommandName() const throw() { + return "check-synth"; +} + + /* class ResetCommand */ void ResetCommand::invoke(SmtEngine* smtEngine) throw() { @@ -1233,6 +1286,60 @@ std::string GetSynthSolutionCommand::getCommandName() const throw() { return "get-instantiations"; } +/* class GetQuantifierEliminationCommand */ + +GetQuantifierEliminationCommand::GetQuantifierEliminationCommand() throw() : + d_expr() { +} + +GetQuantifierEliminationCommand::GetQuantifierEliminationCommand(const Expr& expr, bool doFull) throw() : + d_expr(expr), d_doFull(doFull) { +} + +Expr GetQuantifierEliminationCommand::getExpr() const throw() { + return d_expr; +} +bool GetQuantifierEliminationCommand::getDoFull() const throw() { + return d_doFull; +} + +void GetQuantifierEliminationCommand::invoke(SmtEngine* smtEngine) throw() { + try { + d_result = smtEngine->doQuantifierElimination(d_expr, d_doFull); + d_commandStatus = CommandSuccess::instance(); + } catch(exception& e) { + d_commandStatus = new CommandFailure(e.what()); + } +} + +Expr GetQuantifierEliminationCommand::getResult() const throw() { + return d_result; +} + +void GetQuantifierEliminationCommand::printResult(std::ostream& out, uint32_t verbosity) const throw() { + if(! ok()) { + this->Command::printResult(out, verbosity); + } else { + out << d_result << endl; + } +} + +Command* GetQuantifierEliminationCommand::exportTo(ExprManager* exprManager, ExprManagerMapCollection& variableMap) { + GetQuantifierEliminationCommand* c = new GetQuantifierEliminationCommand(d_expr.exportTo(exprManager, variableMap), d_doFull); + c->d_result = d_result; + return c; +} + +Command* GetQuantifierEliminationCommand::clone() const { + GetQuantifierEliminationCommand* c = new GetQuantifierEliminationCommand(d_expr, d_doFull); + c->d_result = d_result; + return c; +} + +std::string GetQuantifierEliminationCommand::getCommandName() const throw() { + return d_doFull ? "get-qe" : "get-qe-disjunct"; +} + /* class GetUnsatCoreCommand */ GetUnsatCoreCommand::GetUnsatCoreCommand() throw() { diff --git a/src/smt/command.h b/src/smt/command.h index 248e69b0e..db4efd819 100644 --- a/src/smt/command.h +++ b/src/smt/command.h @@ -1,13 +1,13 @@ /********************* */ /*! \file command.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Kshitij Bansal, Christopher L. Conway, Dejan Jovanovic, Francois Bobot, Andrew Reynolds + ** Top contributors (to current version): + ** Morgan Deters, Andrew Reynolds, Francois Bobot ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2014 New York University and The University of Iowa - ** See the file COPYING in the top-level source directory for licensing - ** information.\endverbatim + ** Copyright (c) 2009-2016 by the authors listed in the file AUTHORS + ** in the top-level 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 command pattern on SmtEngines. ** @@ -501,6 +501,24 @@ public: std::string getCommandName() const throw(); };/* class QueryCommand */ +class CVC4_PUBLIC CheckSynthCommand : public Command { +protected: + Expr d_expr; + Result d_result; + bool d_inUnsatCore; +public: + CheckSynthCommand() throw(); + CheckSynthCommand(const Expr& expr, bool inUnsatCore = true) throw(); + ~CheckSynthCommand() throw() {} + Expr getExpr() const throw(); + void invoke(SmtEngine* smtEngine) throw(); + Result getResult() const throw(); + void printResult(std::ostream& out, uint32_t verbosity = 2) const throw(); + Command* exportTo(ExprManager* exprManager, ExprManagerMapCollection& variableMap); + Command* clone() const; + std::string getCommandName() const throw(); +};/* class CheckSynthCommand */ + // this is TRANSFORM in the CVC presentation language class CVC4_PUBLIC SimplifyCommand : public Command { protected: @@ -624,6 +642,25 @@ public: std::string getCommandName() const throw(); };/* class GetSynthSolutionCommand */ +class CVC4_PUBLIC GetQuantifierEliminationCommand : public Command { +protected: + Expr d_expr; + bool d_doFull; + Expr d_result; +public: + GetQuantifierEliminationCommand() throw(); + GetQuantifierEliminationCommand(const Expr& expr, bool doFull) throw(); + ~GetQuantifierEliminationCommand() throw() {} + Expr getExpr() const throw(); + bool getDoFull() const throw(); + void invoke(SmtEngine* smtEngine) throw(); + Expr getResult() const throw(); + void printResult(std::ostream& out, uint32_t verbosity = 2) const throw(); + Command* exportTo(ExprManager* exprManager, ExprManagerMapCollection& variableMap); + Command* clone() const; + std::string getCommandName() const throw(); +};/* class GetQuantifierEliminationCommand */ + class CVC4_PUBLIC GetUnsatCoreCommand : public Command { protected: UnsatCore d_result; diff --git a/src/smt/command_list.cpp b/src/smt/command_list.cpp index 2319d9539..78e5914aa 100644 --- a/src/smt/command_list.cpp +++ b/src/smt/command_list.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file command_list.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 A context-sensitive list of Commands, and their cleanup ** diff --git a/src/smt/command_list.h b/src/smt/command_list.h index 47185b365..ea6b64940 100644 --- a/src/smt/command_list.h +++ b/src/smt/command_list.h @@ -1,13 +1,13 @@ /********************* */ /*! \file command_list.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 A context-sensitive list of Commands, and their cleanup ** diff --git a/src/smt/dump.cpp b/src/smt/dump.cpp index 3b9ec3273..eee7b901a 100644 --- a/src/smt/dump.cpp +++ b/src/smt/dump.cpp @@ -1,20 +1,21 @@ /********************* */ /*! \file dump.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): none + ** 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 Dump utility classes and functions ** ** Dump utility classes and functions. **/ -#include "smt/dump.h" +#include "smt/dump.h" +#include "lib/strtok_r.h" #include "base/output.h" namespace CVC4 { diff --git a/src/smt/dump.h b/src/smt/dump.h index a6fa899da..2abfe5408 100644 --- a/src/smt/dump.h +++ b/src/smt/dump.h @@ -1,13 +1,13 @@ /********************* */ /*! \file dump.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 Dump utility classes and functions ** diff --git a/src/smt/ite_removal.cpp b/src/smt/ite_removal.cpp index c0c6ed02b..fcd0c3254 100644 --- a/src/smt/ite_removal.cpp +++ b/src/smt/ite_removal.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file ite_removal.cpp ** \verbatim - ** Original author: Dejan Jovanovic - ** Major contributors: Tim King, Morgan Deters - ** Minor contributors (to current version): Kshitij Bansal, Andrew Reynolds, 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 Removal of term ITEs ** diff --git a/src/smt/ite_removal.h b/src/smt/ite_removal.h index d6d820f89..c0a46c316 100644 --- a/src/smt/ite_removal.h +++ b/src/smt/ite_removal.h @@ -1,13 +1,13 @@ /********************* */ /*! \file ite_removal.h ** \verbatim - ** Original author: Dejan Jovanovic - ** Major contributors: Kshitij Bansal, Tim King, 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 Removal of term ITEs ** diff --git a/src/smt/logic_exception.h b/src/smt/logic_exception.h index a641f8d21..93db29a9b 100644 --- a/src/smt/logic_exception.h +++ b/src/smt/logic_exception.h @@ -1,13 +1,13 @@ /********************* */ /*! \file logic_exception.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 that is thrown when a feature is used outside ** the logic that CVC4 is currently using diff --git a/src/smt/logic_request.cpp b/src/smt/logic_request.cpp index 09559eb8d..dc6a2d6b7 100644 --- a/src/smt/logic_request.cpp +++ b/src/smt/logic_request.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file logic_request.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/smt/logic_request.h b/src/smt/logic_request.h index 94c6c2a5e..7b41886bd 100644 --- a/src/smt/logic_request.h +++ b/src/smt/logic_request.h @@ -1,13 +1,13 @@ /********************* */ /*! \file logic_request.h ** \verbatim - ** Original author: Martin Brain <> - ** Major contributors: none - ** Minor contributors (to current version): Tim King + ** Top contributors (to current version): + ** Martin Brain, 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 object to request logic widening in the running SmtEngine ** diff --git a/src/smt/managed_ostreams.cpp b/src/smt/managed_ostreams.cpp index 1901f731d..cae6ac67f 100644 --- a/src/smt/managed_ostreams.cpp +++ b/src/smt/managed_ostreams.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file managed_ostreams.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-2016 New York University and The University of Iowa - ** See the file COPYING in the top-level source directory for licensing - ** information.\endverbatim + ** Copyright (c) 2009-2016 by the authors listed in the file AUTHORS + ** in the top-level source directory) and their institutional affiliations. + ** All rights reserved. See the file COPYING in the top-level source + ** directory for licensing information.\endverbatim ** ** \brief Wrappers to handle memory management of ostreams. ** diff --git a/src/smt/managed_ostreams.h b/src/smt/managed_ostreams.h index 6dc785027..56c517a87 100644 --- a/src/smt/managed_ostreams.h +++ b/src/smt/managed_ostreams.h @@ -1,13 +1,13 @@ /********************* */ /*! \file managed_ostreams.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-2016 New York University and The University of Iowa - ** See the file COPYING in the top-level source directory for licensing - ** information.\endverbatim + ** Copyright (c) 2009-2016 by the authors listed in the file AUTHORS + ** in the top-level source directory) and their institutional affiliations. + ** All rights reserved. See the file COPYING in the top-level source + ** directory for licensing information.\endverbatim ** ** \brief Wrappers to handle memory management of ostreams. ** diff --git a/src/smt/model.cpp b/src/smt/model.cpp index 15ecbadfb..a38862307 100644 --- a/src/smt/model.cpp +++ b/src/smt/model.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file model.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 ** This file is part of the CVC4 project. - ** Copyright (c) 2009-2014 New York University and The University of Iowa - ** See the file COPYING in the top-level source directory for licensing - ** information.\endverbatim + ** Copyright (c) 2009-2016 by the authors listed in the file AUTHORS + ** in the top-level 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 **/ diff --git a/src/smt/model.h b/src/smt/model.h index 4bbcb5f7d..768cb3e6a 100644 --- a/src/smt/model.h +++ b/src/smt/model.h @@ -1,13 +1,13 @@ /********************* */ /*! \file model.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 class **/ diff --git a/src/smt/model_postprocessor.cpp b/src/smt/model_postprocessor.cpp index aa645954b..369c5d48f 100644 --- a/src/smt/model_postprocessor.cpp +++ b/src/smt/model_postprocessor.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file model_postprocessor.cpp ** \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 ** diff --git a/src/smt/model_postprocessor.h b/src/smt/model_postprocessor.h index 024f4f3a3..d9e749677 100644 --- a/src/smt/model_postprocessor.h +++ b/src/smt/model_postprocessor.h @@ -1,13 +1,13 @@ /********************* */ /*! \file model_postprocessor.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 ** diff --git a/src/smt/smt_engine.cpp b/src/smt/smt_engine.cpp index 007c5e049..5bd1cbdfc 100644 --- a/src/smt/smt_engine.cpp +++ b/src/smt/smt_engine.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file smt_engine.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Clark Barrett - ** Minor contributors (to current version): Christopher L. Conway, Tianyi Liang, Martin Brain <>, Kshitij Bansal, Liana Hadarean, Dejan Jovanovic, Tim King, Andrew Reynolds + ** 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 The main entry point into the CVC4 library's SMT interface ** @@ -110,9 +110,18 @@ using namespace CVC4::context; using namespace CVC4::theory; namespace CVC4 { - namespace smt { +struct DeleteCommandFunction : public std::unary_function<const Command*, void> +{ + void operator()(const Command* command) { delete command; } +}; + +void DeleteAndClearCommandVector(std::vector<Command*>& commands) { + std::for_each(commands.begin(), commands.end(), DeleteCommandFunction()); + commands.clear(); +} + /** Useful for counting the number of recursive calls. */ class ScopeCounter { private: @@ -543,6 +552,11 @@ class SmtEnginePrivate : public NodeManagerListener { */ unsigned d_simplifyAssertionsDepth; + /** whether certain preprocess steps are necessary */ + bool d_needsExpandDefs; + bool d_needsRewriteBoolTerms; + bool d_needsConstrainSubTypes; + public: /** * Map from skolem variables to index in d_assertions containing @@ -670,6 +684,9 @@ public: d_abstractValueMap(&d_fakeContext), d_abstractValues(), d_simplifyAssertionsDepth(0), + d_needsExpandDefs(true), + d_needsRewriteBoolTerms(true), + d_needsConstrainSubTypes(true), //TODO d_iteSkolemMap(), d_iteRemover(smt.d_userContext), d_pbsProcessor(smt.d_userContext), @@ -955,6 +972,45 @@ public: std::ostream* getReplayLog() const { return d_managedReplayLog.getReplayLog(); } + + Node replaceQuantifiersWithInstantiations( Node n, std::map< Node, std::vector< Node > >& insts, std::map< Node, Node >& visited ){ + std::map< Node, Node >::iterator itv = visited.find( n ); + if( itv!=visited.end() ){ + return itv->second; + }else{ + Node ret = n; + if( n.getKind()==kind::FORALL ){ + std::map< Node, std::vector< Node > >::iterator it = insts.find( n ); + if( it==insts.end() ){ + Trace("smt-qe-debug") << "* " << n << " has no instances" << std::endl; + ret = NodeManager::currentNM()->mkConst(true); + }else{ + Trace("smt-qe-debug") << "* " << n << " has " << it->second.size() << " instances" << std::endl; + Node reti = it->second.empty() ? NodeManager::currentNM()->mkConst(true) : ( it->second.size()==1 ? it->second[0] : NodeManager::currentNM()->mkNode( kind::AND, it->second ) ); + Trace("smt-qe-debug") << " return : " << ret << std::endl; + //recursive (for nested quantification) + ret = replaceQuantifiersWithInstantiations( reti, insts, visited ); + } + }else if( n.getNumChildren()>0 ){ + bool childChanged = false; + std::vector< Node > children; + if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){ + children.push_back( n.getOperator() ); + } + for( unsigned i=0; i<n.getNumChildren(); i++ ){ + Node r = replaceQuantifiersWithInstantiations( n[i], insts, visited ); + children.push_back( r ); + childChanged = childChanged || r!=n[i]; + } + if( childChanged ){ + ret = NodeManager::currentNM()->mkNode( n.getKind(), children ); + } + } + visited[n] = ret; + return ret; + } + } + };/* class SmtEnginePrivate */ }/* namespace CVC4::smt */ @@ -1007,7 +1063,9 @@ SmtEngine::SmtEngine(ExprManager* em) throw() : // SatProof and TheoryProofs. The TheoryProofEngine and the SatProof are // initialized in TheoryEngine and PropEngine respectively. Assert(d_proofManager == NULL); - PROOF( d_proofManager = new ProofManager(); ); +#ifdef CVC4_PROOF + d_proofManager = new ProofManager(); +#endif // We have mutual dependency here, so we add the prop engine to the theory // engine later (it is non-essential there) @@ -1039,20 +1097,27 @@ SmtEngine::SmtEngine(ExprManager* em) throw() : } void SmtEngine::finishInit() { + Trace("smt-debug") << "SmtEngine::finishInit" << std::endl; // ensure that our heuristics are properly set up setDefaults(); + + Trace("smt-debug") << "Making decision engine..." << std::endl; d_decisionEngine = new DecisionEngine(d_context, d_userContext); d_decisionEngine->init(); // enable appropriate strategies + Trace("smt-debug") << "Making prop engine..." << std::endl; d_propEngine = new PropEngine(d_theoryEngine, d_decisionEngine, d_context, d_userContext, d_private->getReplayLog(), d_replayStream, d_channels); + Trace("smt-debug") << "Setting up theory engine..." << std::endl; d_theoryEngine->setPropEngine(d_propEngine); d_theoryEngine->setDecisionEngine(d_decisionEngine); + Trace("smt-debug") << "Finishing init for theory engine..." << std::endl; d_theoryEngine->finishInit(); + Trace("smt-debug") << "Set up assertion list..." << std::endl; // [MGD 10/20/2011] keep around in incremental mode, due to a // cleanup ordering issue and Nodes/TNodes. If SAT is popped // first, some user-context-dependent TNodes might still exist @@ -1073,6 +1138,7 @@ void SmtEngine::finishInit() { << SetBenchmarkLogicCommand(everything.getLogicString()); } + Trace("smt-debug") << "Dump declaration commands..." << std::endl; // dump out any pending declaration commands for(unsigned i = 0; i < d_dumpCommands.size(); ++i) { Dump("declarations") << *d_dumpCommands[i]; @@ -1081,6 +1147,7 @@ void SmtEngine::finishInit() { d_dumpCommands.clear(); PROOF( ProofManager::currentPM()->setLogic(d_logic); ); + Trace("smt-debug") << "SmtEngine::finishInit done" << std::endl; } void SmtEngine::finalOptionsAreSet() { @@ -1155,6 +1222,8 @@ SmtEngine::~SmtEngine() throw() { } d_dumpCommands.clear(); + DeleteAndClearCommandVector(d_modelGlobalCommands); + if(d_modelCommands != NULL) { d_modelCommands->deleteSelf(); } @@ -1260,15 +1329,7 @@ void SmtEngine::setDefaults() { Trace("smt") << "turning on quantifier logic, for strings-exp" << std::endl; } - if(! options::finiteModelFind.wasSetByUser()) { - options::finiteModelFind.set( true ); - Trace("smt") << "turning on finite-model-find, for strings-exp" - << std::endl; - } if(! options::fmfBoundInt.wasSetByUser()) { - if(! options::fmfBoundIntLazy.wasSetByUser()) { - options::fmfBoundIntLazy.set( true ); - } options::fmfBoundInt.set( true ); Trace("smt") << "turning on fmf-bound-int, for strings-exp" << std::endl; } @@ -1644,16 +1705,25 @@ void SmtEngine::setDefaults() { options::sortInference.set( false ); options::ufssFairnessMonotone.set( false ); } + if( d_logic.hasCardinalityConstraints() ){ + //must have finite model finding on + options::finiteModelFind.set( true ); + } + + //if it contains a theory with non-termination, do not strictly enforce that quantifiers and theory combination must be interleaved + if( d_logic.isTheoryEnabled(THEORY_STRINGS) || (d_logic.isTheoryEnabled(THEORY_ARITH) && !d_logic.isLinear()) ){ + if( !options::instWhenStrictInterleave.wasSetByUser() ){ + options::instWhenStrictInterleave.set( false ); + } + } + //local theory extensions if( options::localTheoryExt() ){ if( !options::instMaxLevel.wasSetByUser() ){ options::instMaxLevel.set( 0 ); } } - if( d_logic.hasCardinalityConstraints() ){ - //must have finite model finding on - options::finiteModelFind.set( true ); - } + if(options::fmfBoundIntLazy.wasSetByUser() && options::fmfBoundIntLazy()) { options::fmfBoundInt.set( true ); } @@ -1752,26 +1822,25 @@ void SmtEngine::setDefaults() { if( !options::cbqiPreRegInst.wasSetByUser()) { options::cbqiPreRegInst.set( true ); } - }else{ - //counterexample-guided instantiation for non-sygus - // enable if any quantifiers with arithmetic or datatypes - if( ( d_logic.isQuantified() && ( d_logic.isTheoryEnabled(THEORY_ARITH) || d_logic.isTheoryEnabled(THEORY_DATATYPES) ) ) || - options::cbqiAll() ){ - if( !options::cbqi.wasSetByUser() ){ - options::cbqi.set( true ); - } - } - if( options::cbqiSplx() ){ - //implies more general option + } + //counterexample-guided instantiation for non-sygus + // enable if any quantifiers with arithmetic or datatypes + if( ( d_logic.isQuantified() && ( d_logic.isTheoryEnabled(THEORY_ARITH) || d_logic.isTheoryEnabled(THEORY_DATATYPES) ) ) || + options::cbqiAll() ){ + if( !options::cbqi.wasSetByUser() ){ options::cbqi.set( true ); } - if( options::cbqi() ){ - //must rewrite divk - if( !options::rewriteDivk.wasSetByUser()) { - options::rewriteDivk.set( true ); - } + } + if( options::cbqiSplx() ){ + //implies more general option + options::cbqi.set( true ); + } + if( options::cbqi() ){ + //must rewrite divk + if( !options::rewriteDivk.wasSetByUser()) { + options::rewriteDivk.set( true ); } - if( options::cbqi() && d_logic.isPure(THEORY_ARITH) ){ + if( d_logic.isPure(THEORY_ARITH) ){ options::cbqiAll.set( false ); if( !options::quantConflictFind.wasSetByUser() ){ options::quantConflictFind.set( false ); @@ -1787,8 +1856,12 @@ void SmtEngine::setDefaults() { } } } - //implied options... + if( options::strictTriggers() ){ + if( !options::userPatternsQuant.wasSetByUser() ){ + options::userPatternsQuant.set( quantifiers::USER_PAT_MODE_TRUST ); + } + } if( options::qcfMode.wasSetByUser() || options::qcfTConstraint() ){ options::quantConflictFind.set( true ); } @@ -1843,6 +1916,9 @@ void SmtEngine::setDefaults() { options::preSkolemQuantNested.set( false ); } } + if( !d_logic.isTheoryEnabled(THEORY_DATATYPES) ){ + options::quantDynamicSplit.set( quantifiers::QUANT_DSPLIT_MODE_NONE ); + } //until bugs 371,431 are fixed if( ! options::minisatUseElim.wasSetByUser()){ @@ -2063,6 +2139,8 @@ CVC4::SExpr SmtEngine::getInfo(const std::string& key) const void SmtEngine::defineFunction(Expr func, const std::vector<Expr>& formals, Expr formula) { + SmtScope smts(this); + doPendingPops(); Trace("smt") << "SMT defineFunction(" << func << ")" << endl; for(std::vector<Expr>::const_iterator i = formals.begin(); i != formals.end(); ++i) { if((*i).getKind() != kind::BOUND_VARIABLE) { @@ -2081,7 +2159,6 @@ void SmtEngine::defineFunction(Expr func, DefineFunctionCommand c(ss.str(), func, formals, formula); addToModelCommandAndDump(c, ExprManager::VAR_FLAG_DEFINED, true, "declarations"); - SmtScope smts(this); PROOF( if (options::checkUnsatCores()) { d_defineCommands.push_back(c.clone()); @@ -3572,6 +3649,7 @@ Result SmtEngine::check() { // Make sure the prop layer has all of the assertions Trace("smt") << "SmtEngine::check(): processing assertions" << endl; d_private->processAssertions(); + Trace("smt") << "SmtEngine::check(): done processing assertions" << endl; // Turn off stop only for QF_LRA // TODO: Bring up in a meeting where to put this @@ -3807,6 +3885,7 @@ void SmtEnginePrivate::processAssertions() { Debug("smt") << " d_assertions : " << d_assertions.size() << endl; + dumpAssertions("pre-constrain-subtypes", d_assertions); { // Any variables of subtype types need to be constrained properly. @@ -4141,6 +4220,7 @@ void SmtEnginePrivate::processAssertions() { Trace("smt-proc") << "SmtEnginePrivate::processAssertions() end" << endl; dumpAssertions("post-everything", d_assertions); + //set instantiation level of everything to zero if( options::instLevelInputOnly() && options::instMaxLevel()!=-1 ){ @@ -4210,13 +4290,22 @@ void SmtEngine::ensureBoolean(const Expr& e) throw(TypeCheckingException) { } Result SmtEngine::checkSat(const Expr& ex, bool inUnsatCore) throw(TypeCheckingException, ModalException, LogicException) { + return checkSatisfiability( ex, inUnsatCore, false ); +}/* SmtEngine::checkSat() */ + +Result SmtEngine::query(const Expr& ex, bool inUnsatCore) throw(TypeCheckingException, ModalException, LogicException) { + Assert(!ex.isNull()); + return checkSatisfiability( ex, inUnsatCore, true ); +}/* SmtEngine::query() */ + +Result SmtEngine::checkSatisfiability(const Expr& ex, bool inUnsatCore, bool isQuery) { try { Assert(ex.isNull() || ex.getExprManager() == d_exprManager); SmtScope smts(this); finalOptionsAreSet(); doPendingPops(); - Trace("smt") << "SmtEngine::checkSat(" << ex << ")" << endl; + Trace("smt") << "SmtEngine::" << (isQuery ? "query" : "checkSat") << "(" << ex << ")" << endl; if(d_queryMade && !options::incrementalSolving()) { throw ModalException("Cannot make multiple queries unless " @@ -4247,14 +4336,15 @@ Result SmtEngine::checkSat(const Expr& ex, bool inUnsatCore) throw(TypeCheckingE // Add the formula if(!e.isNull()) { d_problemExtended = true; + Expr ea = isQuery ? e.notExpr() : e; if(d_assertionList != NULL) { - d_assertionList->push_back(e); + d_assertionList->push_back(ea); } - d_private->addFormula(e.getNode(), inUnsatCore); + d_private->addFormula(ea.getNode(), inUnsatCore); } Result r(Result::SAT_UNKNOWN, Result::UNKNOWN_REASON); - r = check().asSatisfiabilityResult(); + r = isQuery ? check().asValidityResult() : check().asSatisfiabilityResult(); if (options::solveIntAsBV() > 0 &&r.asSatisfiabilityResult().isSat() == Result::UNSAT) { r = Result(Result::SAT_UNKNOWN, Result::UNKNOWN_REASON); @@ -4265,7 +4355,11 @@ Result SmtEngine::checkSat(const Expr& ex, bool inUnsatCore) throw(TypeCheckingE // Dump the query if requested if(Dump.isOn("benchmark")) { // the expr already got dumped out if assertion-dumping is on - Dump("benchmark") << CheckSatCommand(ex); + if( isQuery ){ + Dump("benchmark") << QueryCommand(ex); + }else{ + Dump("benchmark") << CheckSatCommand(ex); + } } // Pop the context @@ -4276,7 +4370,7 @@ Result SmtEngine::checkSat(const Expr& ex, bool inUnsatCore) throw(TypeCheckingE d_problemExtended = false; - Trace("smt") << "SmtEngine::checkSat(" << e << ") => " << r << endl; + Trace("smt") << "SmtEngine::" << (isQuery ? "query" : "checkSat") << "(" << e << ") => " << r << endl; // Check that SAT results generate a model correctly. if(options::checkModels()) { @@ -4307,98 +4401,85 @@ Result SmtEngine::checkSat(const Expr& ex, bool inUnsatCore) throw(TypeCheckingE Result::RESOURCEOUT : Result::TIMEOUT; return Result(Result::SAT_UNKNOWN, why, d_filename); } -}/* SmtEngine::checkSat() */ - -Result SmtEngine::query(const Expr& ex, bool inUnsatCore) throw(TypeCheckingException, ModalException, LogicException) { - Assert(!ex.isNull()); - Assert(ex.getExprManager() == d_exprManager); - SmtScope smts(this); - finalOptionsAreSet(); - doPendingPops(); - Trace("smt") << "SMT query(" << ex << ")" << endl; - - try { - if(d_queryMade && !options::incrementalSolving()) { - throw ModalException("Cannot make multiple queries unless " - "incremental solving is enabled " - "(try --incremental)"); - } - - // Substitute out any abstract values in ex - Expr e = d_private->substituteAbstractValues(Node::fromExpr(ex)).toExpr(); - // Ensure that the expression is type-checked at this point, and Boolean - ensureBoolean(e); - - // check to see if a postsolve() is pending - if(d_needPostsolve) { - d_theoryEngine->postsolve(); - d_needPostsolve = false; - } - - // Push the context - internalPush(); - - // Note that a query has been made - d_queryMade = true; - - // Add the formula - d_problemExtended = true; - if(d_assertionList != NULL) { - d_assertionList->push_back(e.notExpr()); - } - d_private->addFormula(e.getNode().notNode(), inUnsatCore); - - // Run the check - Result r(Result::SAT_UNKNOWN, Result::UNKNOWN_REASON); - r = check().asValidityResult(); - d_needPostsolve = true; - - // Dump the query if requested - if(Dump.isOn("benchmark")) { - // the expr already got dumped out if assertion-dumping is on - Dump("benchmark") << QueryCommand(ex); - } - - // Pop the context - internalPop(); - - // Remember the status - d_status = r; - - d_problemExtended = false; +} - Trace("smt") << "SMT query(" << e << ") ==> " << r << endl; - // Check that SAT results generate a model correctly. - if(options::checkModels()) { - if(r.asSatisfiabilityResult().isSat() == Result::SAT || - (r.isUnknown() && r.whyUnknown() == Result::INCOMPLETE) ){ - checkModel(/* hard failure iff */ ! r.isUnknown()); - } - } - // Check that UNSAT results generate a proof correctly. - if(options::checkProofs()) { - if(r.asSatisfiabilityResult().isSat() == Result::UNSAT) { - TimerStat::CodeTimer checkProofTimer(d_stats->d_checkProofTime); - checkProof(); - } - } - // Check that UNSAT results generate an unsat core correctly. - if(options::checkUnsatCores()) { - if(r.asSatisfiabilityResult().isSat() == Result::UNSAT) { - TimerStat::CodeTimer checkUnsatCoreTimer(d_stats->d_checkUnsatCoreTime); - checkUnsatCore(); +Result SmtEngine::checkSynth(const Expr& e) throw(TypeCheckingException, ModalException, LogicException) { + SmtScope smts(this); + Trace("smt") << "Check synth: " << e << std::endl; + Trace("smt-synth") << "Check synthesis conjecture: " << e << std::endl; + Expr e_check = e; + Node conj = Node::fromExpr( e ); + Assert( conj.getKind()==kind::FORALL ); + //possibly run quantifier elimination to make formula into single invocation + if( conj[1].getKind()==kind::EXISTS ){ + Node conj_se = conj[1][1]; + + Trace("smt-synth") << "Compute single invocation for " << conj_se << "..." << std::endl; + quantifiers::SingleInvocationPartition sip( kind::APPLY ); + sip.init( conj_se ); + Trace("smt-synth") << "...finished, got:" << std::endl; + sip.debugPrint("smt-synth"); + + if( !sip.isPurelySingleInvocation() && sip.isNonGroundSingleInvocation() ){ + //We are in the case where our synthesis conjecture is exists f. forall xy. P( f( x ), x, y ), P does not contain f. + //The following will run QE on (exists z x.) exists y. P( z, x, y ) to obtain Q( z, x ), + // and then constructs exists f. forall x. Q( f( x ), x ), where Q does not contain f. We invoke synthesis solver on this result. + + //create new smt engine to do quantifier elimination + SmtEngine smt_qe( d_exprManager ); + smt_qe.setLogic(getLogicInfo()); + Trace("smt-synth") << "Property is non-ground single invocation, run QE to obtain single invocation." << std::endl; + //partition variables + std::vector< Node > qe_vars; + std::vector< Node > nqe_vars; + for( unsigned i=0; i<sip.d_all_vars.size(); i++ ){ + Node v = sip.d_all_vars[i]; + if( std::find( sip.d_si_vars.begin(), sip.d_si_vars.end(), v )==sip.d_si_vars.end() ){ + qe_vars.push_back( v ); + }else{ + nqe_vars.push_back( v ); + } + } + std::vector< Node > orig; + std::vector< Node > subs; + //skolemize non-qe variables + for( unsigned i=0; i<nqe_vars.size(); i++ ){ + Node k = NodeManager::currentNM()->mkSkolem( "k", nqe_vars[i].getType(), "qe for non-ground single invocation" ); + orig.push_back( nqe_vars[i] ); + subs.push_back( k ); + Trace("smt-synth") << " subs : " << nqe_vars[i] << " -> " << k << std::endl; + } + for( std::map< Node, bool >::iterator it = sip.d_funcs.begin(); it != sip.d_funcs.end(); ++it ){ + orig.push_back( sip.d_func_inv[it->first] ); + Node k = NodeManager::currentNM()->mkSkolem( "k", sip.d_func_fo_var[it->first].getType(), "qe for function in non-ground single invocation" ); + subs.push_back( k ); + Trace("smt-synth") << " subs : " << sip.d_func_inv[it->first] << " -> " << k << std::endl; + } + Node conj_se_ngsi = sip.getFullSpecification(); + Node conj_se_ngsi_subs = conj_se_ngsi.substitute( orig.begin(), orig.end(), subs.begin(), subs.end() ); + Assert( !qe_vars.empty() ); + conj_se_ngsi_subs = NodeManager::currentNM()->mkNode( kind::EXISTS, NodeManager::currentNM()->mkNode( kind::BOUND_VAR_LIST, qe_vars ), conj_se_ngsi_subs ); + + Trace("smt-synth") << "Run quantifier elimination on " << conj_se_ngsi_subs << std::endl; + Expr qe_res = smt_qe.doQuantifierElimination( conj_se_ngsi_subs.toExpr(), true, false ); + Trace("smt-synth") << "Result : " << qe_res << std::endl; + + //create single invocation conjecture + Node qe_res_n = Node::fromExpr( qe_res ); + qe_res_n = qe_res_n.substitute( subs.begin(), subs.end(), orig.begin(), orig.end() ); + if( !nqe_vars.empty() ){ + qe_res_n = NodeManager::currentNM()->mkNode( kind::EXISTS, NodeManager::currentNM()->mkNode( kind::BOUND_VAR_LIST, nqe_vars ), qe_res_n ); + } + Assert( conj.getNumChildren()==3 ); + qe_res_n = NodeManager::currentNM()->mkNode( kind::FORALL, conj[0], qe_res_n, conj[2] ); + Trace("smt-synth") << "Converted conjecture after QE : " << qe_res_n << std::endl; + e_check = qe_res_n.toExpr(); } } - - return r; - } catch (UnsafeInterruptException& e) { - AlwaysAssert(d_private->getResourceManager()->out()); - Result::UnknownExplanation why = d_private->getResourceManager()->outOfResources() ? - Result::RESOURCEOUT : Result::TIMEOUT; - return Result(Result::VALIDITY_UNKNOWN, why, d_filename); - } -}/* SmtEngine::query() */ + + return checkSatisfiability( e_check, true, false ); +} Result SmtEngine::assertFormula(const Expr& ex, bool inUnsatCore) throw(TypeCheckingException, LogicException, UnsafeInterruptException) { Assert(ex.getExprManager() == d_exprManager); @@ -5017,6 +5098,77 @@ void SmtEngine::printSynthSolution( std::ostream& out ) { } } +Expr SmtEngine::doQuantifierElimination(const Expr& e, bool doFull, bool strict) throw(TypeCheckingException, ModalException, LogicException) { + SmtScope smts(this); + if(!d_logic.isPure(THEORY_ARITH) && strict){ + Warning() << "Unexpected logic for quantifier elimination " << d_logic << endl; + } + Trace("smt-qe") << "Do quantifier elimination " << e << std::endl; + Node n_e = Node::fromExpr( e ); + if( n_e.getKind()!=kind::EXISTS ){ + throw ModalException("Expecting an existentially quantified formula as argument to get-qe."); + } + //tag the quantified formula with the quant-elim attribute + TypeNode t = NodeManager::currentNM()->booleanType(); + Node n_attr = NodeManager::currentNM()->mkSkolem("qe", t, "Auxiliary variable for qe attr."); + std::vector< Node > node_values; + d_theoryEngine->setUserAttribute( doFull ? "quant-elim" : "quant-elim-partial", n_attr, node_values, ""); + n_attr = NodeManager::currentNM()->mkNode(kind::INST_ATTRIBUTE, n_attr); + n_attr = NodeManager::currentNM()->mkNode(kind::INST_PATTERN_LIST, n_attr); + std::vector< Node > e_children; + e_children.push_back( n_e[0] ); + e_children.push_back( n_e[1] ); + e_children.push_back( n_attr ); + Node nn_e = NodeManager::currentNM()->mkNode( kind::EXISTS, e_children ); + Trace("smt-qe-debug") << "Query for quantifier elimination : " << nn_e << std::endl; + Assert( nn_e.getNumChildren()==3 ); + Result r = checkSatisfiability(nn_e.toExpr(), true, true); + Trace("smt-qe") << "Query returned " << r << std::endl; + if(r.asSatisfiabilityResult().isSat() != Result::UNSAT ) { + if( r.asSatisfiabilityResult().isSat() != Result::SAT && doFull ){ + stringstream ss; + ss << "While performing quantifier elimination, unexpected result : " << r << " for query."; + InternalError(ss.str().c_str()); + } + //get the instantiations for all quantified formulas + std::map< Node, std::vector< Node > > insts; + d_theoryEngine->getInstantiations( insts ); + //find the quantified formula that corresponds to the input + Node top_q; + for( std::map< Node, std::vector< Node > >::iterator it = insts.begin(); it != insts.end(); ++it ){ + Trace("smt-qe-debug") << "* quantifier " << it->first << " had " << it->second.size() << " instances." << std::endl; + if( it->first.getNumChildren()==3 && it->first[2]==n_attr ){ + top_q = it->first; + } + } + std::map< Node, Node > visited; + Node ret_n; + if( top_q.isNull() ){ + //no instances needed + ret_n = NodeManager::currentNM()->mkConst(true); + visited[top_q] = ret_n; + }else{ + //replace by a conjunction of instances + ret_n = d_private->replaceQuantifiersWithInstantiations( top_q, insts, visited ); + } + + //ensure all instantiations were accounted for + for( std::map< Node, std::vector< Node > >::iterator it = insts.begin(); it != insts.end(); ++it ){ + if( !it->second.empty() && visited.find( it->first )==visited.end() ){ + stringstream ss; + ss << "While performing quantifier elimination, processed a quantified formula : " << it->first; + ss << " that was not related to the query. Try option --simplification=none."; + InternalError(ss.str().c_str()); + } + } + Trace("smt-qe") << "Returned : " << ret_n << std::endl; + ret_n = Rewriter::rewrite( ret_n.negate() ); + return ret_n.toExpr(); + }else { + return NodeManager::currentNM()->mkConst(true).toExpr(); + } +} + vector<Expr> SmtEngine::getAssertions() throw(ModalException) { SmtScope smts(this); finalOptionsAreSet(); @@ -5174,7 +5326,7 @@ void SmtEngine::resetAssertions() throw() { Assert(d_userLevels.size() == 0 && d_userContext->getLevel() == 1); d_context->popto(0); d_userContext->popto(0); - d_modelGlobalCommands.clear(); + DeleteAndClearCommandVector(d_modelGlobalCommands); d_userContext->push(); d_context->push(); } diff --git a/src/smt/smt_engine.h b/src/smt/smt_engine.h index 3616762bc..2741cea85 100644 --- a/src/smt/smt_engine.h +++ b/src/smt/smt_engine.h @@ -1,13 +1,13 @@ /********************* */ /*! \file smt_engine.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Martin Brain <>, Tim King, Clark Barrett, Christopher L. Conway, Andrew Reynolds, Kshitij Bansal, Dejan Jovanovic + ** 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 SmtEngine: the main public entry point of libcvc4. ** @@ -244,11 +244,11 @@ class CVC4_PUBLIC SmtEngine { bool d_needPostsolve; /* - * Whether to call theory preprocessing during simplification - on by default* but gets turned off if arithRewriteEq is on + * Whether to call theory preprocessing during simplification - on + * by default* but gets turned off if arithRewriteEq is on */ bool d_earlyTheoryPP; - /** * Most recent result of last checkSat/query or (set-info :status). */ @@ -401,6 +401,8 @@ class CVC4_PUBLIC SmtEngine { SmtEngine(const SmtEngine&) CVC4_UNDEFINED; SmtEngine& operator=(const SmtEngine&) CVC4_UNDEFINED; + //check satisfiability (for query and check-sat) + Result checkSatisfiability(const Expr& e, bool inUnsatCore, bool isQuery); public: /** @@ -494,6 +496,12 @@ public: Result checkSat(const Expr& e = Expr(), bool inUnsatCore = true) throw(TypeCheckingException, ModalException, LogicException); /** + * Assert a synthesis conjecture to the current context and call + * check(). Returns sat, unsat, or unknown result. + */ + Result checkSynth(const Expr& e) throw(TypeCheckingException, ModalException, LogicException); + + /** * Simplify a formula without doing "much" work. Does not involve * the SAT Engine in the simplification, but uses the current * definitions, assertions, and the current partial model, if one @@ -553,6 +561,11 @@ public: void printSynthSolution( std::ostream& out ); /** + * Do quantifier elimination, doFull false means just output one disjunct, strict is whether to output warnings. + */ + Expr doQuantifierElimination(const Expr& e, bool doFull, bool strict=true) throw(TypeCheckingException, ModalException, LogicException); + + /** * Get an unsatisfiable core (only if immediately preceded by an * UNSAT or VALID query). Only permitted if CVC4 was built with * unsat-core support and produce-unsat-cores is on. diff --git a/src/smt/smt_engine_check_proof.cpp b/src/smt/smt_engine_check_proof.cpp index 354a43cc8..5634a4651 100644 --- a/src/smt/smt_engine_check_proof.cpp +++ b/src/smt/smt_engine_check_proof.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file smt_engine_check_proof.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Morgan Deters, 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 [[ Add one-line brief description here ]] ** @@ -22,7 +22,7 @@ #include <fstream> #include <string> -#warning "TODO: Why is lfsc's check.h being included like this?" +// #warning "TODO: Why is lfsc's check.h being included like this?" #include "check.h" #include "base/configuration_private.h" @@ -63,17 +63,26 @@ void SmtEngine::checkProof() { Chat() << "checking proof..." << endl; - if( !(d_logic.isPure(theory::THEORY_BOOL) || - d_logic.isPure(theory::THEORY_BV) || - (d_logic.isPure(theory::THEORY_UF) && - ! d_logic.hasCardinalityConstraints())) || - d_logic.isQuantified()) { + if ( !(d_logic.isPure(theory::THEORY_BOOL) || + d_logic.isPure(theory::THEORY_BV) || + d_logic.isPure(theory::THEORY_ARRAY) || + (d_logic.isPure(theory::THEORY_UF) && + ! d_logic.hasCardinalityConstraints())) || + d_logic.isQuantified()) { // no checking for these yet Notice() << "Notice: no proof-checking for non-UF/Bool/BV proofs yet" << endl; return; } - char* pfFile = strdup("/tmp/cvc4_proof.XXXXXX"); + char const* tempDir = getenv("TMPDIR"); + if (!tempDir) { + tempDir = "/tmp"; + } + + stringstream pfPath; + pfPath << tempDir << "/cvc4_proof.XXXXXX"; + + char* pfFile = strdup(pfPath.str().c_str()); int fd = mkstemp(pfFile); // ensure this temp file is removed after diff --git a/src/smt/smt_engine_scope.cpp b/src/smt/smt_engine_scope.cpp index 25004c85e..c31ea5736 100644 --- a/src/smt/smt_engine_scope.cpp +++ b/src/smt/smt_engine_scope.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file smt_engine_scope.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/smt/smt_engine_scope.h b/src/smt/smt_engine_scope.h index 5a7e39849..e00be40d4 100644 --- a/src/smt/smt_engine_scope.h +++ b/src/smt/smt_engine_scope.h @@ -1,13 +1,13 @@ /********************* */ /*! \file smt_engine_scope.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Morgan Deters, Tim King, 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/smt/smt_statistics_registry.cpp b/src/smt/smt_statistics_registry.cpp index 5aa9085f5..d34498697 100644 --- a/src/smt/smt_statistics_registry.cpp +++ b/src/smt/smt_statistics_registry.cpp @@ -1,13 +1,13 @@ /********************* */ -/*! \file smt_statistic_registry.cpp +/*! \file smt_statistics_registry.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-2016 New York University and The University of Iowa - ** See the file COPYING in the top-level source directory for licensing - ** information.\endverbatim + ** Copyright (c) 2009-2016 by the authors listed in the file AUTHORS + ** in the top-level source directory) and their institutional affiliations. + ** All rights reserved. See the file COPYING in the top-level source + ** directory for licensing information.\endverbatim ** ** \brief Accessor for the SmtEngine's StatisticsRegistry. ** diff --git a/src/smt/smt_statistics_registry.h b/src/smt/smt_statistics_registry.h index 60a5e7c53..7483e8215 100644 --- a/src/smt/smt_statistics_registry.h +++ b/src/smt/smt_statistics_registry.h @@ -1,13 +1,13 @@ /********************* */ -/*! \file smt_statistic_registry.h +/*! \file smt_statistics_registry.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-2016 New York University and The University of Iowa - ** See the file COPYING in the top-level source directory for licensing - ** information.\endverbatim + ** Copyright (c) 2009-2016 by the authors listed in the file AUTHORS + ** in the top-level source directory) and their institutional affiliations. + ** All rights reserved. See the file COPYING in the top-level source + ** directory for licensing information.\endverbatim ** ** \brief Accessor for the SmtEngine's StatisticsRegistry. ** diff --git a/src/smt/update_ostream.h b/src/smt/update_ostream.h index b87ed69d2..9574c5460 100644 --- a/src/smt/update_ostream.h +++ b/src/smt/update_ostream.h @@ -1,13 +1,13 @@ /********************* */ /*! \file update_ostream.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-2016 New York University and The University of Iowa - ** See the file COPYING in the top-level source directory for licensing - ** information.\endverbatim + ** Copyright (c) 2009-2016 by the authors listed in the file AUTHORS + ** in the top-level 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/smt_util/boolean_simplification.cpp b/src/smt_util/boolean_simplification.cpp index fba431350..c5c169301 100644 --- a/src/smt_util/boolean_simplification.cpp +++ b/src/smt_util/boolean_simplification.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file boolean_simplification.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 Simple routines for Boolean simplification ** diff --git a/src/smt_util/boolean_simplification.h b/src/smt_util/boolean_simplification.h index 27fdc3d28..7207dc336 100644 --- a/src/smt_util/boolean_simplification.h +++ b/src/smt_util/boolean_simplification.h @@ -1,13 +1,13 @@ /********************* */ /*! \file boolean_simplification.h ** \verbatim - ** Original author: Tim King - ** Major contributors: Morgan Deters - ** 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 Simple routines for Boolean simplification ** diff --git a/src/smt_util/lemma_channels.cpp b/src/smt_util/lemma_channels.cpp index e75866c5e..083c4adfb 100644 --- a/src/smt_util/lemma_channels.cpp +++ b/src/smt_util/lemma_channels.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file lemma_channels.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-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 This class is a light container for globals that used to live ** in options. This is NOT a good long term solution, but is a reasonable diff --git a/src/smt_util/lemma_channels.h b/src/smt_util/lemma_channels.h index 6cd81795e..54a9db137 100644 --- a/src/smt_util/lemma_channels.h +++ b/src/smt_util/lemma_channels.h @@ -1,13 +1,13 @@ /********************* */ /*! \file lemma_channels.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-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 LemmaChannels is a light container for a pair of input and output ** lemma channels. diff --git a/src/smt_util/lemma_input_channel.h b/src/smt_util/lemma_input_channel.h index 44f0b87f5..5d2b092e1 100644 --- a/src/smt_util/lemma_input_channel.h +++ b/src/smt_util/lemma_input_channel.h @@ -1,13 +1,13 @@ /********************* */ /*! \file lemma_input_channel.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 [[ Add one-line brief description here ]] ** diff --git a/src/smt_util/lemma_output_channel.h b/src/smt_util/lemma_output_channel.h index df7abd1e9..6664b0d48 100644 --- a/src/smt_util/lemma_output_channel.h +++ b/src/smt_util/lemma_output_channel.h @@ -1,13 +1,13 @@ /********************* */ /*! \file lemma_output_channel.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 Mechanism for communication about new lemmas ** diff --git a/src/smt_util/nary_builder.cpp b/src/smt_util/nary_builder.cpp index ec012308f..686dcf506 100644 --- a/src/smt_util/nary_builder.cpp +++ b/src/smt_util/nary_builder.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file nary_builder.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/smt_util/nary_builder.h b/src/smt_util/nary_builder.h index c98e01b1b..d8201fbc5 100644 --- a/src/smt_util/nary_builder.h +++ b/src/smt_util/nary_builder.h @@ -1,13 +1,13 @@ /********************* */ /*! \file nary_builder.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/smt_util/node_visitor.h b/src/smt_util/node_visitor.h index c8958b7b5..1906124ab 100644 --- a/src/smt_util/node_visitor.h +++ b/src/smt_util/node_visitor.h @@ -1,13 +1,13 @@ /********************* */ /*! \file node_visitor.h ** \verbatim - ** Original author: Dejan Jovanovic - ** Major contributors: Liana Hadarean, Morgan Deters - ** Minor contributors (to current version): none + ** 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 A simple visitor for nodes ** 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 ** diff --git a/src/util/abstract_value.cpp b/src/util/abstract_value.cpp index c9dc0251d..c80569034 100644 --- a/src/util/abstract_value.cpp +++ b/src/util/abstract_value.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file abstract_value.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 Representation of abstract values ** diff --git a/src/util/abstract_value.h b/src/util/abstract_value.h index f02df2e66..d85a62c72 100644 --- a/src/util/abstract_value.h +++ b/src/util/abstract_value.h @@ -1,13 +1,13 @@ /********************* */ /*! \file abstract_value.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 Representation of abstract values ** diff --git a/src/util/bin_heap.h b/src/util/bin_heap.h index ed6192cf7..4f2b25c39 100644 --- a/src/util/bin_heap.h +++ b/src/util/bin_heap.h @@ -1,13 +1,13 @@ /********************* */ /*! \file bin_heap.h ** \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 An implementation of a binary heap ** diff --git a/src/util/bitvector.h b/src/util/bitvector.h index 041cae38e..a04cbb58f 100644 --- a/src/util/bitvector.h +++ b/src/util/bitvector.h @@ -1,13 +1,13 @@ /********************* */ /*! \file bitvector.h ** \verbatim - ** Original author: Dejan Jovanovic - ** Major contributors: Morgan Deters, Liana Hadarean - ** Minor contributors (to current version): Christopher L. Conway + ** 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/util/bool.h b/src/util/bool.h index 2d5e15777..99db6a4a6 100644 --- a/src/util/bool.h +++ b/src/util/bool.h @@ -1,13 +1,13 @@ /********************* */ /*! \file bool.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 A hash function for Boolean ** diff --git a/src/util/cache.h b/src/util/cache.h index 788c89d83..8dd3cd0ae 100644 --- a/src/util/cache.h +++ b/src/util/cache.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cache.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 A generic Cache<> template class for use by functions that ** walk the Node DAG and want to cache results for sub-DAGs diff --git a/src/util/cardinality.cpp b/src/util/cardinality.cpp index 07e094a38..2eea4c040 100644 --- a/src/util/cardinality.cpp +++ b/src/util/cardinality.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file cardinality.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Tim King + ** 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 Representation of cardinality ** diff --git a/src/util/cardinality.h b/src/util/cardinality.h index 8b0d85980..93b4ca618 100644 --- a/src/util/cardinality.h +++ b/src/util/cardinality.h @@ -1,13 +1,13 @@ /********************* */ /*! \file cardinality.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Tim King + ** 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 Representation of cardinality ** diff --git a/src/util/debug.h b/src/util/debug.h index 6ef196111..665fa99a2 100644 --- a/src/util/debug.h +++ b/src/util/debug.h @@ -1,13 +1,13 @@ /********************* */ /*! \file debug.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 Debugging things. ** diff --git a/src/util/dense_map.h b/src/util/dense_map.h index 86b9f2553..7fa3832ef 100644 --- a/src/util/dense_map.h +++ b/src/util/dense_map.h @@ -1,13 +1,13 @@ /********************* */ /*! \file dense_map.h ** \verbatim - ** Original author: Tim King - ** Major contributors: none - ** Minor contributors (to current version): Dejan Jovanovic + ** Top contributors (to current version): + ** 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 This is an abstraction of a Map from unsigned integers to elements of type T. ** diff --git a/src/util/divisible.cpp b/src/util/divisible.cpp index 85824a77f..4e0d9815d 100644 --- a/src/util/divisible.cpp +++ b/src/util/divisible.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file divisible.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/util/divisible.h b/src/util/divisible.h index 56178e604..d5651ae41 100644 --- a/src/util/divisible.h +++ b/src/util/divisible.h @@ -1,13 +1,13 @@ /********************* */ /*! \file divisible.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 [[ Add one-line brief description here ]] ** diff --git a/src/util/dynamic_array.h b/src/util/dynamic_array.h index 6938748a8..2ec85a025 100644 --- a/src/util/dynamic_array.h +++ b/src/util/dynamic_array.h @@ -1,13 +1,13 @@ /********************* */ /*! \file dynamic_array.h ** \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/util/floatingpoint.cpp b/src/util/floatingpoint.cpp index d1164133a..678d3a45a 100644 --- a/src/util/floatingpoint.cpp +++ b/src/util/floatingpoint.cpp @@ -1,13 +1,14 @@ /********************* */ /*! \file floatingpoint.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): + ** Tim King, Martin Brain ** 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 [[ Implementations of the utility functions for working with floating point theories. ]] ** diff --git a/src/util/floatingpoint.h b/src/util/floatingpoint.h index d8a3a65d9..7b18d542a 100644 --- a/src/util/floatingpoint.h +++ b/src/util/floatingpoint.h @@ -1,13 +1,14 @@ /********************* */ /*! \file floatingpoint.h ** \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 ** 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 [[ Utility functions for working with floating point theories. ]] ** diff --git a/src/util/gmp_util.h b/src/util/gmp_util.h index d3f0d09d4..776d8a38a 100644 --- a/src/util/gmp_util.h +++ b/src/util/gmp_util.h @@ -1,13 +1,13 @@ /********************* */ /*! \file gmp_util.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/util/hash.h b/src/util/hash.h index 218cf0aab..4797b5f02 100644 --- a/src/util/hash.h +++ b/src/util/hash.h @@ -1,13 +1,13 @@ /********************* */ /*! \file hash.h ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): Dejan Jovanovic + ** Top contributors (to current version): + ** Morgan Deters, Christopher L. Conway, 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/util/index.h b/src/util/index.h index ea0802b2d..6c11343b5 100644 --- a/src/util/index.h +++ b/src/util/index.h @@ -1,13 +1,13 @@ /********************* */ /*! \file index.h ** \verbatim - ** Original author: Tim King - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): Liana Hadarean + ** 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 [[ Add one-line brief description here ]] ** diff --git a/src/util/integer.h.in b/src/util/integer.h.in index 3db9998a7..13ae1392b 100644 --- a/src/util/integer.h.in +++ b/src/util/integer.h.in @@ -1,13 +1,13 @@ /********************* */ /*! \file integer.h.in ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Tim King - ** 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 A multi-precision integer constant ** diff --git a/src/util/integer_cln_imp.cpp b/src/util/integer_cln_imp.cpp index 27a4b7d06..0064f2904 100644 --- a/src/util/integer_cln_imp.cpp +++ b/src/util/integer_cln_imp.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file integer_cln_imp.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/util/integer_cln_imp.h b/src/util/integer_cln_imp.h index 9e5e6c2ae..177fc02cf 100644 --- a/src/util/integer_cln_imp.h +++ b/src/util/integer_cln_imp.h @@ -1,13 +1,13 @@ /********************* */ /*! \file integer_cln_imp.h ** \verbatim - ** Original author: Tim King - ** Major contributors: Morgan Deters - ** Minor contributors (to current version): Dejan Jovanovic, Liana Hadarean + ** 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 A multiprecision integer constant; wraps a CLN multiprecision ** integer. diff --git a/src/util/integer_gmp_imp.cpp b/src/util/integer_gmp_imp.cpp index df1bd297a..d165dbec3 100644 --- a/src/util/integer_gmp_imp.cpp +++ b/src/util/integer_gmp_imp.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file integer_gmp_imp.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 A multi-precision rational constant. ** diff --git a/src/util/integer_gmp_imp.h b/src/util/integer_gmp_imp.h index 9cae16222..0c5665e38 100644 --- a/src/util/integer_gmp_imp.h +++ b/src/util/integer_gmp_imp.h @@ -1,13 +1,13 @@ /********************* */ /*! \file integer_gmp_imp.h ** \verbatim - ** Original author: Tim King - ** Major contributors: Morgan Deters, Liana Hadarean - ** Minor contributors (to current version): 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 A multiprecision integer constant; wraps a GMP multiprecision ** integer. diff --git a/src/util/maybe.h b/src/util/maybe.h index 2fa7c2f11..7ede6f512 100644 --- a/src/util/maybe.h +++ b/src/util/maybe.h @@ -1,13 +1,13 @@ /********************* */ /*! \file maybe.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 This provides a templated Maybe construct. ** diff --git a/src/util/ntuple.h b/src/util/ntuple.h index b9e1100f1..21af4f423 100644 --- a/src/util/ntuple.h +++ b/src/util/ntuple.h @@ -1,13 +1,13 @@ /********************* */ /*! \file ntuple.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 Similar to std::pair<>, for triples and quadruples ** diff --git a/src/util/proof.h b/src/util/proof.h index 22d9f97d5..fc5f7f901 100644 --- a/src/util/proof.h +++ b/src/util/proof.h @@ -1,13 +1,13 @@ /********************* */ /*! \file proof.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 [[ Add one-line brief description here ]] ** diff --git a/src/util/rational.h.in b/src/util/rational.h.in index 6f9c29c19..08c4003e9 100644 --- a/src/util/rational.h.in +++ b/src/util/rational.h.in @@ -1,13 +1,13 @@ /********************* */ /*! \file rational.h.in ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Tim King - ** 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 A multi-precision rational constant ** diff --git a/src/util/rational_cln_imp.cpp b/src/util/rational_cln_imp.cpp index 608b33f2b..bee944531 100644 --- a/src/util/rational_cln_imp.cpp +++ b/src/util/rational_cln_imp.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file rational_cln_imp.cpp ** \verbatim - ** Original author: Tim King - ** Major contributors: Morgan Deters, Christopher L. Conway - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Tim King, Christopher L. Conway, 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 multi-precision rational constant. ** diff --git a/src/util/rational_cln_imp.h b/src/util/rational_cln_imp.h index df08770e8..9b4a8efa7 100644 --- a/src/util/rational_cln_imp.h +++ b/src/util/rational_cln_imp.h @@ -1,13 +1,13 @@ /********************* */ /*! \file rational_cln_imp.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 Multiprecision rational constants; wraps a CLN multiprecision ** rational. diff --git a/src/util/rational_gmp_imp.cpp b/src/util/rational_gmp_imp.cpp index 63fb8e05c..17bce0201 100644 --- a/src/util/rational_gmp_imp.cpp +++ b/src/util/rational_gmp_imp.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file rational_gmp_imp.cpp ** \verbatim - ** Original author: Tim King - ** Major contributors: Morgan Deters, Christopher L. Conway - ** Minor contributors (to current version): none + ** Top contributors (to current version): + ** Tim King, Christopher L. Conway, 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 multi-precision rational constant. ** diff --git a/src/util/rational_gmp_imp.h b/src/util/rational_gmp_imp.h index 59145d485..6a1c8b4b8 100644 --- a/src/util/rational_gmp_imp.h +++ b/src/util/rational_gmp_imp.h @@ -1,13 +1,13 @@ /********************* */ /*! \file rational_gmp_imp.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 Multiprecision rational constants; wraps a GMP multiprecision ** rational. diff --git a/src/util/regexp.cpp b/src/util/regexp.cpp index 25a595613..d211aaf1b 100644 --- a/src/util/regexp.cpp +++ b/src/util/regexp.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file regexp.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 [[ Add one-line brief description here ]] ** diff --git a/src/util/regexp.h b/src/util/regexp.h index 4b26b6e91..2cfcbc4e4 100644 --- a/src/util/regexp.h +++ b/src/util/regexp.h @@ -1,13 +1,13 @@ /********************* */ /*! \file regexp.h ** \verbatim - ** Original author: Tianyi Liang - ** Major contributors: none - ** Minor contributors (to current version): Morgan Deters, Andrew Reynolds + ** 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 [[ Add one-line brief description here ]] ** diff --git a/src/util/resource_manager.cpp b/src/util/resource_manager.cpp index 8d6e5e6d4..7a739a779 100644 --- a/src/util/resource_manager.cpp +++ b/src/util/resource_manager.cpp @@ -1,17 +1,18 @@ /********************* */ /*! \file resource_manager.cpp -** \verbatim -** Original author: Liana Hadarean -** Major contributors: none -** Minor contributors (to current version): none -** This file is part of the CVC4 project. -** Copyright (c) 2009-2014 New York University and The University of Iowa -** See the file COPYING in the top-level source directory for licensing -** information.\endverbatim -** -** \brief Manages and updates various resource and time limits. -** -** Manages and updates various resource and time limits. + ** \verbatim + ** Top contributors (to current version): + ** Liana Hadarean, Tim King, Morgan Deters + ** 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 "util/resource_manager.h" diff --git a/src/util/resource_manager.h b/src/util/resource_manager.h index f3bb42a08..d21122cae 100644 --- a/src/util/resource_manager.h +++ b/src/util/resource_manager.h @@ -1,17 +1,18 @@ /********************* */ /*! \file resource_manager.h -** \verbatim -** Original author: Liana Hadarean -** Major contributors: none -** Minor contributors (to current version): none -** This file is part of the CVC4 project. -** Copyright (c) 2009-2014 New York University and The University of Iowa -** See the file COPYING in the top-level source directory for licensing -** information.\endverbatim -** -** \brief Manages and updates various resource and time limits -** -** Manages and updates various resource and time limits. + ** \verbatim + ** Top contributors (to current version): + ** Liana Hadarean, Tim King, Morgan Deters + ** 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 "cvc4_public.h" diff --git a/src/util/result.cpp b/src/util/result.cpp index b981164a4..51b1a8de1 100644 --- a/src/util/result.cpp +++ b/src/util/result.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file result.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Tim King + ** 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 Encapsulation of the result of a query. ** diff --git a/src/util/result.h b/src/util/result.h index 8069f7ef9..8303ad0e8 100644 --- a/src/util/result.h +++ b/src/util/result.h @@ -1,13 +1,13 @@ /********************* */ /*! \file result.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Tim King + ** 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 Encapsulation of the result of a query. ** diff --git a/src/util/sexpr.cpp b/src/util/sexpr.cpp index 9837a7045..efb90302f 100644 --- a/src/util/sexpr.cpp +++ b/src/util/sexpr.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file sexpr.cpp ** \verbatim - ** Original author: Morgan Deters - ** 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 Simple representation of S-expressions ** diff --git a/src/util/sexpr.h b/src/util/sexpr.h index 40fd9dd56..9c80a1b1f 100644 --- a/src/util/sexpr.h +++ b/src/util/sexpr.h @@ -1,13 +1,13 @@ /********************* */ /*! \file sexpr.h ** \verbatim - ** Original author: Christopher L. Conway - ** Major contributors: Tim King, Morgan Deters - ** Minor contributors (to current version): Dejan Jovanovic + ** Top contributors (to current version): + ** Tim King, Morgan Deters, 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 Simple representation of S-expressions ** diff --git a/src/util/sexpr.i b/src/util/sexpr.i index 4c89c5019..3c865c097 100644 --- a/src/util/sexpr.i +++ b/src/util/sexpr.i @@ -4,6 +4,7 @@ %ignore CVC4::operator<<(std::ostream&, const SExpr&); %ignore CVC4::operator<<(std::ostream&, SExpr::SexprTypes); +%ignore CVC4::operator<<(std::ostream&, PrettySExprs); // for Java and the like %extend CVC4::SExpr { diff --git a/src/util/smt2_quote_string.cpp b/src/util/smt2_quote_string.cpp index 68551bc0f..578be99e5 100644 --- a/src/util/smt2_quote_string.cpp +++ b/src/util/smt2_quote_string.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file smt2_quote_string.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 Quotes a string if necessary for smt2. ** diff --git a/src/util/smt2_quote_string.h b/src/util/smt2_quote_string.h index 577f216e2..2d7f0b2f0 100644 --- a/src/util/smt2_quote_string.h +++ b/src/util/smt2_quote_string.h @@ -1,13 +1,13 @@ /********************* */ /*! \file smt2_quote_string.h ** \verbatim - ** Original author: Morgan Deters - ** 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 Quotes a string if necessary for smt2. ** diff --git a/src/util/statistics.cpp b/src/util/statistics.cpp index 371872454..8384a7bb1 100644 --- a/src/util/statistics.cpp +++ b/src/util/statistics.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file statistics.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/util/statistics.h b/src/util/statistics.h index a0b6ed083..663d2071b 100644 --- a/src/util/statistics.h +++ b/src/util/statistics.h @@ -1,13 +1,13 @@ /********************* */ /*! \file statistics.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 [[ Add one-line brief description here ]] ** diff --git a/src/util/statistics_registry.cpp b/src/util/statistics_registry.cpp index c9051cc0e..cb8e1ce90 100644 --- a/src/util/statistics_registry.cpp +++ b/src/util/statistics_registry.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file statistics_registry.cpp ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: none - ** Minor contributors (to current version): Kshitij Bansal, Tim King + ** 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/util/statistics_registry.h b/src/util/statistics_registry.h index f4f00e444..4f2c356e8 100644 --- a/src/util/statistics_registry.h +++ b/src/util/statistics_registry.h @@ -1,13 +1,13 @@ /********************* */ /*! \file statistics_registry.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Tim King - ** Minor contributors (to current version): Kshitij Bansal + ** Top contributors (to current version): + ** Morgan Deters, Tim King, 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 Statistics utility classes ** diff --git a/src/util/subrange_bound.cpp b/src/util/subrange_bound.cpp index 5d66b75ad..085ecb930 100644 --- a/src/util/subrange_bound.cpp +++ b/src/util/subrange_bound.cpp @@ -1,13 +1,13 @@ /********************* */ /*! \file subrange_bound.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) 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 Representation of subrange bounds ** diff --git a/src/util/subrange_bound.h b/src/util/subrange_bound.h index d5b50bf4c..86c88e187 100644 --- a/src/util/subrange_bound.h +++ b/src/util/subrange_bound.h @@ -1,13 +1,13 @@ /********************* */ /*! \file subrange_bound.h ** \verbatim - ** Original author: Morgan Deters - ** Major contributors: Tim King - ** 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 Representation of subrange bounds ** diff --git a/src/util/tuple.h b/src/util/tuple.h index fe016db2c..14763d2d5 100644 --- a/src/util/tuple.h +++ b/src/util/tuple.h @@ -1,13 +1,13 @@ /********************* */ /*! \file tuple.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 Tuple operators ** diff --git a/src/util/unsafe_interrupt_exception.h b/src/util/unsafe_interrupt_exception.h index d7c736d64..345daf674 100644 --- a/src/util/unsafe_interrupt_exception.h +++ b/src/util/unsafe_interrupt_exception.h @@ -1,13 +1,13 @@ /********************* */ /*! \file unsafe_interrupt_exception.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 An exception that is thrown when the solver is out of time/resources ** and is interrupted in an unsafe state diff --git a/src/util/utility.h b/src/util/utility.h index 59522901a..1d51d42ee 100644 --- a/src/util/utility.h +++ b/src/util/utility.h @@ -1,13 +1,13 @@ /********************* */ /*! \file utility.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 Some standard STL-related utility functions for CVC4 ** |