summaryrefslogtreecommitdiff
path: root/src/preprocessing/util/ite_utilities.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/preprocessing/util/ite_utilities.h')
-rw-r--r--src/preprocessing/util/ite_utilities.h420
1 files changed, 420 insertions, 0 deletions
diff --git a/src/preprocessing/util/ite_utilities.h b/src/preprocessing/util/ite_utilities.h
new file mode 100644
index 000000000..e137749db
--- /dev/null
+++ b/src/preprocessing/util/ite_utilities.h
@@ -0,0 +1,420 @@
+/********************* */
+/*! \file ite_utilities.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Tim King, Aina Niemetz, Paul Meng
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2018 by the authors listed in the file AUTHORS
+ ** in the top-level 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
+ **
+ ** This module implements preprocessing phases designed to simplify ITE
+ ** expressions. Based on:
+ ** Kim, Somenzi, Jin. Efficient Term-ITE Conversion for SMT. FMCAD 2009.
+ ** Burch, Jerry. Techniques for Verifying Superscalar Microprocessors. DAC
+ *'96
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__ITE_UTILITIES_H
+#define __CVC4__ITE_UTILITIES_H
+
+#include <unordered_map>
+#include <vector>
+
+#include "expr/node.h"
+#include "util/hash.h"
+#include "util/statistics_registry.h"
+
+namespace CVC4 {
+namespace preprocessing {
+namespace util {
+
+class IncomingArcCounter;
+class TermITEHeightCounter;
+class ITECompressor;
+class ITESimplifier;
+class ITECareSimplifier;
+
+/**
+ * A caching visitor that computes whether a node contains a term ite.
+ */
+class ContainsTermITEVisitor
+{
+ public:
+ ContainsTermITEVisitor();
+ ~ContainsTermITEVisitor();
+
+ /** returns true if a node contains a term ite. */
+ bool containsTermITE(TNode n);
+
+ /** Garbage collects the cache. */
+ void garbageCollect();
+
+ /** returns the size of the cache. */
+ size_t cache_size() const { return d_cache.size(); }
+
+ private:
+ typedef std::unordered_map<Node, bool, NodeHashFunction> NodeBoolMap;
+ NodeBoolMap d_cache;
+};
+
+class ITEUtilities
+{
+ public:
+ ITEUtilities();
+ ~ITEUtilities();
+
+ Node simpITE(TNode assertion);
+
+ bool simpIteDidALotOfWorkHeuristic() const;
+
+ /* returns false if an assertion is discovered to be equal to false. */
+ bool compress(std::vector<Node>& assertions);
+
+ Node simplifyWithCare(TNode e);
+
+ void clear();
+
+ ContainsTermITEVisitor* getContainsVisitor()
+ {
+ return d_containsVisitor.get();
+ }
+
+ bool containsTermITE(TNode n)
+ {
+ return d_containsVisitor->containsTermITE(n);
+ }
+
+ private:
+ std::unique_ptr<ContainsTermITEVisitor> d_containsVisitor;
+ ITECompressor* d_compressor;
+ ITESimplifier* d_simplifier;
+ ITECareSimplifier* d_careSimp;
+};
+
+class IncomingArcCounter
+{
+ public:
+ IncomingArcCounter(bool skipVars = false, bool skipConstants = false);
+ ~IncomingArcCounter();
+ void computeReachability(const std::vector<Node>& assertions);
+
+ inline uint32_t lookupIncoming(Node n) const
+ {
+ NodeCountMap::const_iterator it = d_reachCount.find(n);
+ if (it == d_reachCount.end())
+ {
+ return 0;
+ }
+ else
+ {
+ return (*it).second;
+ }
+ }
+ void clear();
+
+ private:
+ typedef std::unordered_map<Node, uint32_t, NodeHashFunction> NodeCountMap;
+ NodeCountMap d_reachCount;
+
+ bool d_skipVariables;
+ bool d_skipConstants;
+};
+
+class TermITEHeightCounter
+{
+ public:
+ TermITEHeightCounter();
+ ~TermITEHeightCounter();
+
+ /**
+ * Compute and [potentially] cache the termITEHeight() of e.
+ * The term ite height equals the maximum number of term ites
+ * encountered on any path from e to a leaf.
+ * Inductively:
+ * - termITEHeight(leaves) = 0
+ * - termITEHeight(e: term-ite(c, t, e) ) =
+ * 1 + max(termITEHeight(t), termITEHeight(e)) ; Don't include c
+ * - termITEHeight(e not term ite) = max_{c in children(e))
+ * (termITEHeight(c))
+ */
+ uint32_t termITEHeight(TNode e);
+
+ /** Clear the cache. */
+ void clear();
+
+ /** Size of the cache. */
+ size_t cache_size() const;
+
+ private:
+ typedef std::unordered_map<Node, uint32_t, NodeHashFunction> NodeCountMap;
+ NodeCountMap d_termITEHeight;
+}; /* class TermITEHeightCounter */
+
+/**
+ * A routine designed to undo the potentially large blow up
+ * due to expansion caused by the ite simplifier.
+ */
+class ITECompressor
+{
+ public:
+ ITECompressor(ContainsTermITEVisitor* contains);
+ ~ITECompressor();
+
+ /* returns false if an assertion is discovered to be equal to false. */
+ bool compress(std::vector<Node>& assertions);
+
+ /* garbage Collects the compressor. */
+ void garbageCollect();
+
+ private:
+ Node d_true; /* Copy of true. */
+ Node d_false; /* Copy of false. */
+ ContainsTermITEVisitor* d_contains;
+ std::vector<Node>* d_assertions;
+ IncomingArcCounter d_incoming;
+
+ typedef std::unordered_map<Node, Node, NodeHashFunction> NodeMap;
+ NodeMap d_compressed;
+
+ void reset();
+
+ Node push_back_boolean(Node original, Node compressed);
+ bool multipleParents(TNode c);
+ Node compressBooleanITEs(Node toCompress);
+ Node compressTerm(Node toCompress);
+ Node compressBoolean(Node toCompress);
+
+ class Statistics
+ {
+ public:
+ IntStat d_compressCalls;
+ IntStat d_skolemsAdded;
+ Statistics();
+ ~Statistics();
+ };
+ Statistics d_statistics;
+}; /* class ITECompressor */
+
+class ITESimplifier
+{
+ public:
+ ITESimplifier(ContainsTermITEVisitor* d_containsVisitor);
+ ~ITESimplifier();
+
+ Node simpITE(TNode assertion);
+
+ bool doneALotOfWorkHeuristic() const;
+ void clearSimpITECaches();
+
+ private:
+ Node d_true;
+ Node d_false;
+
+ ContainsTermITEVisitor* d_containsVisitor;
+ inline bool containsTermITE(TNode n)
+ {
+ return d_containsVisitor->containsTermITE(n);
+ }
+ TermITEHeightCounter d_termITEHeight;
+ inline uint32_t termITEHeight(TNode e)
+ {
+ return d_termITEHeight.termITEHeight(e);
+ }
+
+ // ConstantIte is a small inductive sublanguage:
+ // constant
+ // or termITE(cnd, ConstantIte, ConstantIte)
+ typedef std::vector<Node> NodeVec;
+ typedef std::unordered_map<Node, NodeVec*, NodeHashFunction>
+ ConstantLeavesMap;
+ ConstantLeavesMap d_constantLeaves;
+
+ // d_constantLeaves satisfies the following invariants:
+ // not containsTermITE(x) then !isKey(x)
+ // containsTermITE(x):
+ // - not isKey(x) then this value is uncomputed
+ // - d_constantLeaves[x] == NULL, then this contains a non-constant leaf
+ // - d_constantLeaves[x] != NULL, then this contains a sorted list of constant
+ // leaf
+ bool isConstantIte(TNode e);
+
+ /** If its not a constant and containsTermITE(ite),
+ * returns a sorted NodeVec of the leaves. */
+ NodeVec* computeConstantLeaves(TNode ite);
+
+ // Lists all of the vectors in d_constantLeaves for fast deletion.
+ std::vector<NodeVec*> d_allocatedConstantLeaves;
+
+ /* transforms */
+ Node transformAtom(TNode atom);
+ Node attemptConstantRemoval(TNode atom);
+ Node attemptLiftEquality(TNode atom);
+ Node attemptEagerRemoval(TNode atom);
+
+ // Given ConstantIte trees lcite and rcite,
+ // return a boolean expression equivalent to (= lcite rcite)
+ Node intersectConstantIte(TNode lcite, TNode rcite);
+
+ // Given ConstantIte tree cite and a constant c,
+ // return a boolean expression equivalent to (= lcite c)
+ Node constantIteEqualsConstant(TNode cite, TNode c);
+ uint32_t d_citeEqConstApplications;
+
+ typedef std::pair<Node, Node> NodePair;
+ using NodePairHashFunction =
+ PairHashFunction<Node, Node, NodeHashFunction, NodeHashFunction>;
+ typedef std::unordered_map<NodePair, Node, NodePairHashFunction> NodePairMap;
+ NodePairMap d_constantIteEqualsConstantCache;
+ NodePairMap d_replaceOverCache;
+ NodePairMap d_replaceOverTermIteCache;
+ Node replaceOver(Node n, Node replaceWith, Node simpVar);
+ Node replaceOverTermIte(Node term, Node simpAtom, Node simpVar);
+
+ std::unordered_map<Node, bool, NodeHashFunction> d_leavesConstCache;
+ bool leavesAreConst(TNode e, theory::TheoryId tid);
+ bool leavesAreConst(TNode e);
+
+ NodePairMap d_simpConstCache;
+ Node simpConstants(TNode simpContext, TNode iteNode, TNode simpVar);
+ std::unordered_map<TypeNode, Node, TypeNode::HashFunction> d_simpVars;
+ Node getSimpVar(TypeNode t);
+
+ typedef std::unordered_map<Node, Node, NodeHashFunction> NodeMap;
+ NodeMap d_simpContextCache;
+ Node createSimpContext(TNode c, Node& iteNode, Node& simpVar);
+
+ NodeMap d_simpITECache;
+ Node simpITEAtom(TNode atom);
+
+ private:
+ class Statistics
+ {
+ public:
+ IntStat d_maxNonConstantsFolded;
+ IntStat d_unexpected;
+ IntStat d_unsimplified;
+ IntStat d_exactMatchFold;
+ IntStat d_binaryPredFold;
+ IntStat d_specialEqualityFolds;
+ IntStat d_simpITEVisits;
+
+ HistogramStat<uint32_t> d_inSmaller;
+
+ Statistics();
+ ~Statistics();
+ };
+
+ Statistics d_statistics;
+};
+
+class ITECareSimplifier
+{
+ public:
+ ITECareSimplifier();
+ ~ITECareSimplifier();
+
+ Node simplifyWithCare(TNode e);
+
+ 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;
+
+ typedef std::unordered_map<TNode, Node, TNodeHashFunction> TNodeMap;
+
+ 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)
+ {
+ }
+ }; /* class ITECareSimplifier::CareSetPtrVal */
+
+ std::vector<CareSetPtrVal*> d_usedSets;
+ void careSetPtrGC(CareSetPtrVal* val) { d_usedSets.push_back(val); }
+
+ class CareSetPtr
+ {
+ CareSetPtrVal* d_val;
+ CareSetPtr(CareSetPtrVal* val) : d_val(val) {}
+
+ public:
+ CareSetPtr() : d_val(NULL) {}
+ CareSetPtr(const CareSetPtr& cs)
+ {
+ d_val = cs.d_val;
+ if (d_val != NULL)
+ {
+ ++(d_val->d_refCount);
+ }
+ }
+ ~CareSetPtr()
+ {
+ if (d_val != NULL && (--(d_val->d_refCount) == 0))
+ {
+ d_val->d_iteSimplifier.careSetPtrGC(d_val);
+ }
+ }
+ CareSetPtr& operator=(const CareSetPtr& cs)
+ {
+ if (d_val != cs.d_val)
+ {
+ if (d_val != NULL && (--(d_val->d_refCount) == 0))
+ {
+ d_val->d_iteSimplifier.careSetPtrGC(d_val);
+ }
+ d_val = cs.d_val;
+ if (d_val != NULL)
+ {
+ ++(d_val->d_refCount);
+ }
+ }
+ return *this;
+ }
+ std::set<Node>& getCareSet() { return d_val->d_careSet; }
+
+ 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();
+
+ typedef std::map<TNode, CareSetPtr> CareMap;
+ void updateQueue(CareMap& queue, TNode e, CareSetPtr& careSet);
+ Node substitute(TNode e, TNodeMap& substTable, TNodeMap& cache);
+};
+
+} // namespace util
+} // namespace preprocessing
+} // namespace CVC4
+
+#endif
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback