summaryrefslogtreecommitdiff
path: root/src/theory/bv/theory_bv_utils.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/theory/bv/theory_bv_utils.h')
-rw-r--r--src/theory/bv/theory_bv_utils.h661
1 files changed, 148 insertions, 513 deletions
diff --git a/src/theory/bv/theory_bv_utils.h b/src/theory/bv/theory_bv_utils.h
index e304e4801..f6784621f 100644
--- a/src/theory/bv/theory_bv_utils.h
+++ b/src/theory/bv/theory_bv_utils.h
@@ -2,17 +2,16 @@
/*! \file theory_bv_utils.h
** \verbatim
** Top contributors (to current version):
- ** Liana Hadarean, Dejan Jovanovic, Morgan Deters
+ ** Aina Niemetz, Dejan Jovanovic, Morgan Deters
** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2017 by the authors listed in the file AUTHORS
+ ** 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 [[ Add one-line brief description here ]]
+ ** \brief Util functions for theory BV.
**
- ** [[ Add lengthier description here ]]
- ** \todo document this file
+ ** Util functions for theory BV.
**/
#include "cvc4_private.h"
@@ -36,205 +35,153 @@ typedef std::unordered_set<TNode, TNodeHashFunction> TNodeSet;
namespace utils {
-inline uint32_t pow2(uint32_t power) {
- Assert (power < 32);
- uint32_t one = 1;
- return one << power;
-}
-
-inline unsigned getExtractHigh(TNode node) {
- return node.getOperator().getConst<BitVectorExtract>().high;
-}
-
-inline unsigned getExtractLow(TNode node) {
- return node.getOperator().getConst<BitVectorExtract>().low;
-}
+typedef std::unordered_map<TNode, bool, TNodeHashFunction> TNodeBoolMap;
+typedef std::unordered_set<Node, NodeHashFunction> NodeSet;
-inline unsigned getSize(TNode node) {
- return node.getType().getBitVectorSize();
-}
+/* Compute 2^n. */
+uint32_t pow2(uint32_t n);
-inline unsigned getSignExtendAmount(TNode node)
+/* Compute the greatest common divisor for two objects of Type T. */
+template <class T>
+T gcd(T a, T b)
{
- return node.getOperator().getConst<BitVectorSignExtend>().signExtendAmount;
-}
-
-inline const bool getBit(TNode node, unsigned i) {
- Assert (i < utils::getSize(node) &&
- node.getKind() == kind::CONST_BITVECTOR);
- Integer bit = node.getConst<BitVector>().extract(i, i).getValue();
- return (bit == 1u);
-}
-
-inline Node mkTrue() {
- return NodeManager::currentNM()->mkConst<bool>(true);
-}
-
-inline Node mkFalse() {
- return NodeManager::currentNM()->mkConst<bool>(false);
-}
-
-inline Node mkVar(unsigned size) {
- NodeManager* nm = NodeManager::currentNM();
-
- return nm->mkSkolem("BVSKOLEM$$", nm->mkBitVectorType(size), "is a variable created by the theory of bitvectors");
-}
-
-
-inline Node mkSortedNode(Kind kind, std::vector<Node>& children) {
- Assert (kind == kind::BITVECTOR_AND ||
- kind == kind::BITVECTOR_OR ||
- kind == kind::BITVECTOR_XOR);
- Assert(children.size() > 0);
- if (children.size() == 1) {
- return children[0];
- }
- std::sort(children.begin(), children.end());
- return NodeManager::currentNM()->mkNode(kind, children);
-}
-
-
-inline Node mkNode(Kind kind, std::vector<Node>& children) {
- Assert (children.size() > 0);
- if (children.size() == 1) {
- return children[0];
- }
- return NodeManager::currentNM()->mkNode(kind, children);
-}
-
-inline Node mkNode(Kind kind, TNode child) {
- return NodeManager::currentNM()->mkNode(kind, child);
-}
-
-inline Node mkNode(Kind kind, TNode child1, TNode child2) {
- return NodeManager::currentNM()->mkNode(kind, child1, child2);
-}
-
-
-inline Node mkSortedNode(Kind kind, TNode child1, TNode child2) {
- Assert (kind == kind::BITVECTOR_AND ||
- kind == kind::BITVECTOR_OR ||
- kind == kind::BITVECTOR_XOR);
-
- if (child1 < child2) {
- return NodeManager::currentNM()->mkNode(kind, child1, child2);
- } else {
- return NodeManager::currentNM()->mkNode(kind, child2, child1);
+ while (b != 0)
+ {
+ T t = b;
+ b = a % t;
+ a = t;
}
+ return a;
}
-inline Node mkNode(Kind kind, TNode child1, TNode child2, TNode child3) {
- return NodeManager::currentNM()->mkNode(kind, child1, child2, child3);
-}
-
-
-inline Node mkNot(Node child) {
- return NodeManager::currentNM()->mkNode(kind::NOT, child);
-}
-
-inline Node mkAnd(TNode node1, TNode node2) {
- return NodeManager::currentNM()->mkNode(kind::AND, node1, node2);
-}
-
-inline Node mkOr(TNode node1, TNode node2) {
- return NodeManager::currentNM()->mkNode(kind::OR, node1, node2);
-}
-
-inline Node mkXor(TNode node1, TNode node2) {
- return NodeManager::currentNM()->mkNode(kind::XOR, node1, node2);
-}
-
-inline Node mkSignExtend(TNode node, unsigned amount)
-{
- NodeManager* nm = NodeManager::currentNM();
- Node signExtendOp =
- nm->mkConst<BitVectorSignExtend>(BitVectorSignExtend(amount));
- return nm->mkNode(signExtendOp, node);
-}
-
-inline Node mkExtract(TNode node, unsigned high, unsigned low) {
- Node extractOp = NodeManager::currentNM()->mkConst<BitVectorExtract>(BitVectorExtract(high, low));
- std::vector<Node> children;
- children.push_back(node);
- return NodeManager::currentNM()->mkNode(extractOp, children);
-}
+/* Create bit-vector of ones of given size. */
+BitVector mkBitVectorOnes(unsigned size);
+/* Create bit-vector representing the minimum signed value of given size. */
+BitVector mkBitVectorMinSigned(unsigned size);
+/* Create bit-vector representing the maximum signed value of given size. */
+BitVector mkBitVectorMaxSigned(unsigned size);
-inline Node mkBitOf(TNode node, unsigned index) {
- Node bitOfOp = NodeManager::currentNM()->mkConst<BitVectorBitOf>(BitVectorBitOf(index));
- return NodeManager::currentNM()->mkNode(bitOfOp, node);
-}
+/* Get the bit-width of given node. */
+unsigned getSize(TNode node);
-Node mkSum(std::vector<Node>& children, unsigned width);
+/* Get bit at given index. */
+const bool getBit(TNode node, unsigned i);
-inline Node mkConcat(TNode node, unsigned repeat) {
- Assert (repeat);
- if(repeat == 1) {
- return node;
- }
- NodeBuilder<> result(kind::BITVECTOR_CONCAT);
- for (unsigned i = 0; i < repeat; ++i) {
- result << node;
- }
- Node resultNode = result;
- return resultNode;
-}
+/* Get the upper index of given extract node. */
+unsigned getExtractHigh(TNode node);
+/* Get the lower index of given extract node. */
+unsigned getExtractLow(TNode node);
-inline Node mkConcat(std::vector<Node>& children) {
- if (children.size() > 1)
- return NodeManager::currentNM()->mkNode(kind::BITVECTOR_CONCAT, children);
- else
- return children[0];
-}
+/* Get the number of bits by which a given node is extended. */
+unsigned getSignExtendAmount(TNode node);
-inline Node mkConcat(TNode t1, TNode t2) {
- return NodeManager::currentNM()->mkNode(kind::BITVECTOR_CONCAT, t1, t2);
-}
-
-
-inline BitVector mkBitVectorOnes(unsigned size) {
- Assert(size > 0);
- return BitVector(1, Integer(1)).signExtend(size - 1);
-}
-
-inline BitVector mkBitVectorMinSigned(unsigned size)
+/* Returns true if given node represents a zero bit-vector. */
+bool isZero(TNode node);
+/* If node is a constant of the form 2^c or -2^c, then this function returns
+ * c+1. Otherwise, this function returns 0. The flag isNeg is updated to
+ * indicate whether node is negative. */
+unsigned isPow2Const(TNode node, bool& isNeg);
+/* Returns true if node or all of its children is const. */
+bool isBvConstTerm(TNode node);
+/* Returns true if node is a predicate over bit-vector nodes. */
+bool isBVPredicate(TNode node);
+/* Returns true if given term is a THEORY_BV term. */
+bool isCoreTerm(TNode term, TNodeBoolMap& cache);
+/* Returns true if given term is a bv constant, variable or equality term. */
+bool isEqualityTerm(TNode term, TNodeBoolMap& cache);
+/* Returns true if given node is an atom that is bit-blasted. */
+bool isBitblastAtom(Node lit);
+
+/* Create Boolean node representing true. */
+Node mkTrue();
+/* Create Boolean node representing false. */
+Node mkFalse();
+/* Create bit-vector node representing a bit-vector of ones of given size. */
+Node mkOnes(unsigned size);
+/* Create bit-vector node representing a zero bit-vector of given size. */
+Node mkZero(unsigned size);
+/* Create bit-vector node representing a bit-vector value one of given size. */
+Node mkOne(unsigned size);
+
+/* Create bit-vector constant of given size and value. */
+Node mkConst(unsigned size, unsigned int value);
+Node mkConst(unsigned size, Integer& value);
+/* Create bit-vector constant from given bit-vector. */
+Node mkConst(const BitVector& value);
+
+/* Create bit-vector variable. */
+Node mkVar(unsigned size);
+
+/* Create n-ary node of given kind. */
+Node mkNode(Kind kind, TNode child);
+Node mkNode(Kind kind, TNode child1, TNode child2);
+Node mkNode(Kind kind, TNode child1, TNode child2, TNode child3);
+Node mkNode(Kind kind, std::vector<Node>& children);
+
+/* Create n-ary bit-vector node of kind BITVECTOR_AND, BITVECTOR_OR or
+ * BITVECTOR_XOR where its children are sorted */
+Node mkSortedNode(Kind kind, TNode child1, TNode child2);
+Node mkSortedNode(Kind kind, std::vector<Node>& children);
+
+/* Create node of kind NOT. */
+Node mkNot(Node child);
+/* Create node of kind AND. */
+Node mkAnd(TNode node1, TNode node2);
+/* Create n-ary node of kind AND. */
+template<bool ref_count>
+Node mkAnd(const std::vector<NodeTemplate<ref_count>>& conjunctions)
{
- Assert(size > 0);
- return BitVector(size).setBit(size - 1);
-}
+ std::set<TNode> all(conjunctions.begin(), conjunctions.end());
-inline BitVector mkBitVectorMaxSigned(unsigned size)
-{
- Assert(size > 0);
- return ~mkBitVectorMinSigned(size);
-}
+ if (all.size() == 0) { return mkTrue(); }
-inline Node mkOnes(unsigned size) {
- BitVector val = mkBitVectorOnes(size);
- return NodeManager::currentNM()->mkConst<BitVector>(val);
-}
+ /* All the same, or just one */
+ if (all.size() == 1) { return conjunctions[0]; }
-inline Node mkConst(unsigned size, unsigned int value) {
- BitVector val(size, value);
- return NodeManager::currentNM()->mkConst<BitVector>(val);
+ NodeBuilder<> conjunction(kind::AND);
+ for (const Node& n : all) { conjunction << n; }
+ return conjunction;
}
-
-inline Node mkConst(unsigned size, Integer& value)
+/* Create node of kind OR. */
+Node mkOr(TNode node1, TNode node2);
+/* Create n-ary node of kind OR. */
+template<bool ref_count>
+Node mkOr(const std::vector<NodeTemplate<ref_count>>& nodes)
{
- return NodeManager::currentNM()->mkConst<BitVector>(BitVector(size, value));
-}
+ std::set<TNode> all(nodes.begin(), nodes.end());
-inline Node mkConst(const BitVector& value) {
- return NodeManager::currentNM()->mkConst<BitVector>(value);
-}
+ if (all.size() == 0) { return mkTrue(); }
-inline Node mkZero(unsigned size) { return mkConst(size, 0u); }
+ /* All the same, or just one */
+ if (all.size() == 1) { return nodes[0]; }
-inline Node mkOne(unsigned size) { return mkConst(size, 1u); }
-
-/* Increment */
+ NodeBuilder<> disjunction(kind::OR);
+ for (const Node& n : all) { disjunction << n; }
+ return disjunction;
+}
+/* Create node of kind XOR. */
+Node mkXor(TNode node1, TNode node2);
+
+/* Create signed extension node where given node is extended by given amount. */
+Node mkSignExtend(TNode node, unsigned amount);
+
+/* Create extract node where bits from index high to index low are extracted
+ * from given node. */
+Node mkExtract(TNode node, unsigned high, unsigned low);
+/* Create extract node of bit-width 1 where the resulting node represents
+ * the bit at given index. */
+Node mkBitOf(TNode node, unsigned index);
+
+/* Create n-ary concat node of given children. */
+Node mkConcat(TNode t1, TNode t2);
+Node mkConcat(std::vector<Node>& children);
+/* Create concat by repeating given node n times.
+ * Returns given node if n = 1. */
+Node mkConcat(TNode node, unsigned repeat);
+
+/* Create bit-vector addition node representing the increment of given node. */
Node mkInc(TNode t);
-
-/* Decrement */
+/* Create bit-vector addition node representing the decrement of given node. */
Node mkDec(TNode t);
/* Unsigned multiplication overflow detection.
@@ -243,345 +190,33 @@ Node mkDec(TNode t);
* http://ieeexplore.ieee.org/document/987767 */
Node mkUmulo(TNode t1, TNode t2);
-inline void getConjuncts(TNode node, std::set<TNode>& conjuncts) {
- if (node.getKind() != kind::AND) {
- conjuncts.insert(node);
- } else {
- for (unsigned i = 0; i < node.getNumChildren(); ++ i) {
- getConjuncts(node[i], conjuncts);
- }
- }
-}
-
-inline void getConjuncts(std::vector<TNode>& nodes, std::set<TNode>& conjuncts) {
- for (unsigned i = 0, i_end = nodes.size(); i < i_end; ++ i) {
- getConjuncts(nodes[i], conjuncts);
- }
-}
+/* Create conjunction over a set of (dis)equalities. */
+Node mkConjunction(const std::set<TNode> nodes);
+Node mkConjunction(const std::vector<TNode>& nodes);
-inline Node mkConjunction(const std::set<TNode> nodes) {
- std::set<TNode> expandedNodes;
-
- std::set<TNode>::const_iterator it = nodes.begin();
- std::set<TNode>::const_iterator it_end = nodes.end();
- while (it != it_end) {
- TNode current = *it;
- if (current != mkTrue()) {
- Assert(current.getKind() == kind::EQUAL || (current.getKind() == kind::NOT && current[0].getKind() == kind::EQUAL));
- expandedNodes.insert(current);
- }
- ++ it;
- }
+/* Get a set of all operands of nested and nodes. */
+void getConjuncts(TNode node, std::set<TNode>& conjuncts);
+void getConjuncts(std::vector<TNode>& nodes, std::set<TNode>& conjuncts);
+/* Create a flattened and node. */
+Node flattenAnd(std::vector<TNode>& queue);
- Assert(expandedNodes.size() > 0);
- if (expandedNodes.size() == 1) {
- return *expandedNodes.begin();
- }
+/* Create a string representing a set of nodes. */
+std::string setToString(const std::set<TNode>& nodeSet);
- NodeBuilder<> conjunction(kind::AND);
+/* Create a string representing a vector of nodes. */
+std::string vectorToString(const std::vector<Node>& nodes);
- it = expandedNodes.begin();
- it_end = expandedNodes.end();
- while (it != it_end) {
- conjunction << *it;
- ++ it;
- }
-
- return conjunction;
-}
-
-/**
- * If node is a constant of the form 2^c or -2^c, then this function returns
- * c+1. Otherwise, this function returns 0. The flag isNeg is updated to
- * indicate whether node is negative.
- */
-inline unsigned isPow2Const(TNode node, bool& isNeg)
-{
- if (node.getKind() != kind::CONST_BITVECTOR) {
- return false;
- }
-
- BitVector bv = node.getConst<BitVector>();
- unsigned p = bv.isPow2();
- if (p != 0)
- {
- isNeg = false;
- return p;
- }
- BitVector nbv = -bv;
- p = nbv.isPow2();
- if (p != 0)
- {
- isNeg = true;
- return p;
- }
- return false;
-}
-
-inline Node mkOr(const std::vector<Node>& nodes) {
- std::set<TNode> all;
- all.insert(nodes.begin(), nodes.end());
-
- if (all.size() == 0) {
- return mkTrue();
- }
-
- if (all.size() == 1) {
- // All the same, or just one
- return nodes[0];
- }
-
-
- NodeBuilder<> disjunction(kind::OR);
- std::set<TNode>::const_iterator it = all.begin();
- std::set<TNode>::const_iterator it_end = all.end();
- while (it != it_end) {
- disjunction << *it;
- ++ it;
- }
-
- return disjunction;
-}/* mkOr() */
-
-
-inline Node mkAnd(const std::vector<TNode>& conjunctions) {
- std::set<TNode> all;
- all.insert(conjunctions.begin(), conjunctions.end());
-
- if (all.size() == 0) {
- return mkTrue();
- }
-
- if (all.size() == 1) {
- // All the same, or just one
- return conjunctions[0];
- }
-
-
- NodeBuilder<> conjunction(kind::AND);
- std::set<TNode>::const_iterator it = all.begin();
- std::set<TNode>::const_iterator it_end = all.end();
- while (it != it_end) {
- conjunction << *it;
- ++ it;
- }
-
- return conjunction;
-}/* mkAnd() */
-
-inline Node mkAnd(const std::vector<Node>& conjunctions) {
- std::set<TNode> all;
- all.insert(conjunctions.begin(), conjunctions.end());
-
- if (all.size() == 0) {
- return mkTrue();
- }
-
- if (all.size() == 1) {
- // All the same, or just one
- return conjunctions[0];
- }
-
-
- NodeBuilder<> conjunction(kind::AND);
- std::set<TNode>::const_iterator it = all.begin();
- std::set<TNode>::const_iterator it_end = all.end();
- while (it != it_end) {
- conjunction << *it;
- ++ it;
- }
-
- return conjunction;
-}/* mkAnd() */
-
-inline bool isZero(TNode node) {
- if (!node.isConst()) return false;
- return node == utils::mkConst(utils::getSize(node), 0u);
-}
-
-inline Node flattenAnd(std::vector<TNode>& queue) {
- TNodeSet nodes;
- while(!queue.empty()) {
- TNode current = queue.back();
- queue.pop_back();
- if (current.getKind() == kind::AND) {
- for (unsigned i = 0; i < current.getNumChildren(); ++i) {
- if (nodes.count(current[i]) == 0) {
- queue.push_back(current[i]);
- }
- }
- } else {
- nodes.insert(current);
- }
- }
- std::vector<TNode> children;
- for (TNodeSet::const_iterator it = nodes.begin(); it!= nodes.end(); ++it) {
- children.push_back(*it);
- }
- return mkAnd(children);
-}
-
-
-// need a better name, this is not technically a ground term
-inline bool isBVGroundTerm(TNode node) {
- if (node.getNumChildren() == 0) {
- return node.isConst();
- }
-
- for (size_t i = 0; i < node.getNumChildren(); ++i) {
- if(! node[i].isConst()) {
- return false;
- }
- }
- return true;
-}
-
-inline bool isBVPredicate(TNode node) {
- if (node.getKind() == kind::EQUAL ||
- node.getKind() == kind::BITVECTOR_ULT ||
- node.getKind() == kind::BITVECTOR_SLT ||
- node.getKind() == kind::BITVECTOR_UGT ||
- node.getKind() == kind::BITVECTOR_UGE ||
- node.getKind() == kind::BITVECTOR_SGT ||
- node.getKind() == kind::BITVECTOR_SGE ||
- node.getKind() == kind::BITVECTOR_ULE ||
- node.getKind() == kind::BITVECTOR_SLE ||
- node.getKind() == kind::BITVECTOR_REDOR ||
- node.getKind() == kind::BITVECTOR_REDAND ||
- ( node.getKind() == kind::NOT && (node[0].getKind() == kind::EQUAL ||
- node[0].getKind() == kind::BITVECTOR_ULT ||
- node[0].getKind() == kind::BITVECTOR_SLT ||
- node[0].getKind() == kind::BITVECTOR_UGT ||
- node[0].getKind() == kind::BITVECTOR_UGE ||
- node[0].getKind() == kind::BITVECTOR_SGT ||
- node[0].getKind() == kind::BITVECTOR_SGE ||
- node[0].getKind() == kind::BITVECTOR_ULE ||
- node[0].getKind() == kind::BITVECTOR_SLE ||
- node[0].getKind() == kind::BITVECTOR_REDOR ||
- node[0].getKind() == kind::BITVECTOR_REDAND)))
- {
- return true;
- }
- else
- {
- return false;
- }
-}
-
-inline Node mkConjunction(const std::vector<TNode>& nodes) {
- std::vector<TNode> expandedNodes;
-
- std::vector<TNode>::const_iterator it = nodes.begin();
- std::vector<TNode>::const_iterator it_end = nodes.end();
- while (it != it_end) {
- TNode current = *it;
-
- if (current != mkTrue()) {
- Assert(isBVPredicate(current));
- expandedNodes.push_back(current);
- }
- ++ it;
- }
-
- if (expandedNodes.size() == 0) {
- return mkTrue();
- }
-
- if (expandedNodes.size() == 1) {
- return *expandedNodes.begin();
- }
-
- NodeBuilder<> conjunction(kind::AND);
-
- it = expandedNodes.begin();
- it_end = expandedNodes.end();
- while (it != it_end) {
- conjunction << *it;
- ++ it;
- }
-
- return conjunction;
-}
-
-
-
-// Turn a set into a string
-inline std::string setToString(const std::set<TNode>& nodeSet) {
- std::stringstream out;
- out << "[";
- std::set<TNode>::const_iterator it = nodeSet.begin();
- std::set<TNode>::const_iterator it_end = nodeSet.end();
- bool first = true;
- while (it != it_end) {
- if (!first) {
- out << ",";
- }
- first = false;
- out << *it;
- ++ it;
- }
- out << "]";
- return out.str();
-}
-
-// Turn a vector into a string
-inline std::string vectorToString(const std::vector<Node>& nodes) {
- std::stringstream out;
- out << "[";
- for (unsigned i = 0; i < nodes.size(); ++ i) {
- if (i > 0) {
- out << ",";
- }
- out << nodes[i];
- }
- out << "]";
- return out.str();
-}
-
-// FIXME: dumb code
-inline void intersect(const std::vector<uint32_t>& v1,
- const std::vector<uint32_t>& v2,
- std::vector<uint32_t>& intersection) {
- for (unsigned i = 0; i < v1.size(); ++i) {
- bool found = false;
- for (unsigned j = 0; j < v2.size(); ++j) {
- if (v2[j] == v1[i]) {
- found = true;
- break;
- }
- }
- if (found) {
- intersection.push_back(v1[i]);
- }
- }
-}
-
-template <class T>
-inline T gcd(T a, T b) {
- while (b != 0) {
- T t = b;
- b = a % t;
- a = t;
- }
- return a;
-}
-
-typedef std::unordered_map<TNode, bool, TNodeHashFunction> TNodeBoolMap;
-
-bool isCoreTerm(TNode term, TNodeBoolMap& cache);
-bool isEqualityTerm(TNode term, TNodeBoolMap& cache);
-typedef std::unordered_set<Node, NodeHashFunction> NodeSet;
+/* Create the intersection of two vectors of uint32_t. */
+void intersect(const std::vector<uint32_t>& v1,
+ const std::vector<uint32_t>& v2,
+ std::vector<uint32_t>& intersection);
+/* Determine the total number of nodes that a given node consists of. */
uint64_t numNodes(TNode node, NodeSet& seen);
+/* Collect all variables under a given a node. */
void collectVariables(TNode node, NodeSet& vars);
-// is bitblast atom
-inline bool isBitblastAtom( Node lit ) {
- TNode atom = lit.getKind()==kind::NOT ? lit[0] : lit;
- return atom.getKind()!=kind::EQUAL || atom[0].getType().isBitVector();
-}
-
}
}
}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback