/********************* */ /*! \file abstraction.h ** \verbatim ** Top contributors (to current version): ** Liana Hadarean, Tim King, Mathias Preiner ** This file is part of the CVC4 project. ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS ** in the top-level 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. ** ** Bitvector theory. **/ #include "cvc4_private.h" #ifndef CVC4__THEORY__BV__ABSTRACTION_H #define CVC4__THEORY__BV__ABSTRACTION_H #include #include #include "expr/node.h" #include "theory/substitutions.h" #include "util/statistics_registry.h" namespace CVC4 { namespace theory { namespace bv { typedef std::vector ArgsVec; class AbstractionModule { struct Statistics { IntStat d_numFunctionsAbstracted; IntStat d_numArgsSkolemized; TimerStat d_abstractionTime; Statistics(const std::string& name); ~Statistics(); }; class ArgsTableEntry { std::vector d_data; unsigned d_arity; public: ArgsTableEntry(unsigned n) : d_arity(n) {} ArgsTableEntry() : d_arity(0) {} void addArguments(const ArgsVec& args); typedef std::vector::iterator iterator; iterator begin() { return d_data.begin(); } iterator end() { return d_data.end(); } unsigned getArity() { return d_arity; } unsigned getNumEntries() { return d_data.size(); } ArgsVec& getEntry(unsigned i) { Assert(i < d_data.size()); return d_data[i]; } }; class ArgsTable { std::unordered_map d_data; bool hasEntry(TNode signature) const; public: typedef std::unordered_map::iterator iterator; ArgsTable() {} void addEntry(TNode signature, const ArgsVec& args); ArgsTableEntry& getEntry(TNode signature); iterator begin() { return d_data.begin(); } iterator end() { return d_data.end(); } }; /** * Checks if one pattern is a generalization of the other * * @param s * @param t * * @return 1 if s :> t, 2 if s <: t, 0 if they equivalent and -1 if they are incomparable */ static int comparePatterns(TNode s, TNode t); class LemmaInstantiatior { std::vector d_functions; std::vector d_maxMatch; ArgsTable& d_argsTable; context::Context* d_ctx; theory::SubstitutionMap d_subst; TNode d_conflict; std::vector d_lemmas; void backtrack(std::vector& stack); int next(int val, int index); bool isConsistent(const std::vector& stack); bool accept(const std::vector& stack); void mkLemma(); public: LemmaInstantiatior(const std::vector& functions, ArgsTable& table, TNode conflict) : d_functions(functions) , d_argsTable(table) , d_ctx(new context::Context()) , d_subst(d_ctx) , d_conflict(conflict) , d_lemmas() { Debug("bv-abstraction-gen") << "LemmaInstantiator conflict:" << conflict << "\n"; // initializing the search space for (unsigned i = 0; i < functions.size(); ++i) { TNode func_op = functions[i].getOperator(); // number of matches for this function unsigned maxCount = table.getEntry(func_op).getNumEntries(); d_maxMatch.push_back(maxCount); } } void generateInstantiations(std::vector& lemmas); }; typedef std::unordered_map, NodeHashFunction> NodeVecMap; typedef std::unordered_map NodeTNodeMap; typedef std::unordered_map TNodeTNodeMap; typedef std::unordered_map NodeNodeMap; typedef std::unordered_map TNodeNodeMap; typedef std::unordered_set TNodeSet; typedef std::unordered_map IntNodeMap; typedef std::unordered_map IndexMap; typedef std::unordered_map > SkolemMap; typedef std::unordered_map SignatureMap; ArgsTable d_argsTable; // mapping between signature and uninterpreted function symbol used to // abstract the signature NodeNodeMap d_signatureToFunc; NodeNodeMap d_funcToSignature; NodeNodeMap d_assertionToSignature; SignatureMap d_signatures; NodeNodeMap d_sigToGeneralization; TNodeSet d_skolems; // skolems maps IndexMap d_signatureIndices; SkolemMap d_signatureSkolems; void collectArgumentTypes(TNode sig, std::vector& types, TNodeSet& seen); void collectArguments(TNode node, TNode sig, std::vector& args, TNodeSet& seen); void finalizeSignatures(); Node abstractSignatures(TNode assertion); Node computeSignature(TNode node); bool isConjunctionOfAtoms(TNode node, TNodeSet& seen); TNode getGeneralization(TNode term); void storeGeneralization(TNode s, TNode t); // signature skolem stuff Node getGeneralizedSignature(Node node); Node getSignatureSkolem(TNode node); unsigned getBitwidthIndex(unsigned bitwidth); void resetSignatureIndex(); Node computeSignatureRec(TNode, NodeNodeMap&); void storeSignature(Node signature, TNode assertion); bool hasSignature(Node node); Node substituteArguments(TNode signature, TNode apply, unsigned& i, TNodeTNodeMap& seen); // crazy instantiation methods void generateInstantiations(unsigned current, std::vector& matches, std::vector >& instantiations, std::vector >& new_instantiations); Node tryMatching(const std::vector& ss, const std::vector& tt, TNode conflict); void makeFreshArgs(TNode func, std::vector& fresh_args); void makeFreshSkolems(TNode node, SubstitutionMap& map, SubstitutionMap& reverse_map); void skolemizeArguments(std::vector& assertions); Node reverseAbstraction(Node assertion, NodeNodeMap& seen); TNodeSet d_addedLemmas; TNodeSet d_lemmaAtoms; TNodeSet d_inputAtoms; void storeLemma(TNode lemma); Statistics d_statistics; public: AbstractionModule(const std::string& name) : d_argsTable() , d_signatureToFunc() , d_funcToSignature() , d_assertionToSignature() , d_signatures() , d_sigToGeneralization() , d_skolems() , d_signatureIndices() , d_signatureSkolems() , d_addedLemmas() , d_lemmaAtoms() , d_inputAtoms() , d_statistics(name) {} /** * returns true if there are new uninterepreted functions symbols in the output * * @param assertions * @param new_assertions * * @return */ bool applyAbstraction(const std::vector& assertions, std::vector& new_assertions); /** * Returns true if the node represents an abstraction predicate. * * @param node * * @return */ bool isAbstraction(TNode node); /** * Returns the interpretation of the abstraction predicate. * * @param node * * @return */ Node getInterpretation(TNode node); Node simplifyConflict(TNode conflict); void generalizeConflict(TNode conflict, std::vector& lemmas); void addInputAtom(TNode atom); bool isLemmaAtom(TNode node) const; }; } } } #endif