/********************* */ /*! \file arith_utilities.h ** \verbatim ** Original author: taking ** Major contributors: none ** Minor contributors (to current version): mdeters ** This file is part of the CVC4 prototype. ** Copyright (c) 2009, 2010 The Analysis of Computer Systems Group (ACSys) ** Courant Institute of Mathematical Sciences ** New York University ** 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__ARITH__ARITH_UTILITIES_H #define __CVC4__THEORY__ARITH__ARITH_UTILITIES_H #include "util/rational.h" #include "expr/node.h" #include "expr/attribute.h" #include #include #include #include namespace CVC4 { namespace theory { namespace arith { typedef uint32_t ArithVar; //static const ArithVar ARITHVAR_SENTINEL = std::numeric_limits::max(); #define ARITHVAR_SENTINEL std::numeric_limits::max() //Maps from Nodes -> ArithVars, and vice versa typedef __gnu_cxx::hash_map NodeToArithVarMap; typedef __gnu_cxx::hash_map ArithVarToNodeMap; inline Node mkRationalNode(const Rational& q){ return NodeManager::currentNM()->mkConst(q); } inline Node mkBoolNode(bool b){ return NodeManager::currentNM()->mkConst(b); } inline Rational coerceToRational(TNode constant){ switch(constant.getKind()){ case kind::CONST_INTEGER: { Rational q(constant.getConst()); return q; } case kind::CONST_RATIONAL: return constant.getConst(); default: Unreachable(); } Rational unreachable(0,0); return unreachable; } inline Node coerceToRationalNode(TNode constant){ switch(constant.getKind()){ case kind::CONST_INTEGER: { Rational q(constant.getConst()); Node n = mkRationalNode(q); return n; } case kind::CONST_RATIONAL: return constant; default: Unreachable(); } return Node::null(); } /** is k \in {LT, LEQ, EQ, GEQ, GT} */ inline bool isRelationOperator(Kind k){ using namespace kind; switch(k){ case LT: case LEQ: case EQUAL: case GEQ: case GT: return true; default: return false; } } /** * Given a relational kind, k, return the kind k' s.t. * swapping the lefthand and righthand side is equivalent. * * The following equivalence should hold, * (k l r) <=> (k' r l) */ inline Kind reverseRelationKind(Kind k){ using namespace kind; switch(k){ case LT: return GT; case LEQ: return GEQ; case EQUAL: return EQUAL; case GEQ: return LEQ; case GT: return LT; default: Unreachable(); } } inline bool evaluateConstantPredicate(Kind k, const Rational& left, const Rational& right){ using namespace kind; switch(k){ case LT: return left < right; case LEQ: return left <= right; case EQUAL: return left == right; case GEQ: return left >= right; case GT: return left > right; default: Unreachable(); return true; } } /** * Returns the appropraite coefficient for the infinitesimal given the kind * for an arithmetic atom inorder to represent strict inequalities as inequalities. * x < c becomes x <= c + (-1) * \delta * x > c becomes x >= x + ( 1) * \delta * Non-strict inequalities have a coefficient of zero. */ inline int deltaCoeff(Kind k){ switch(k){ case kind::LT: return -1; case kind::GT: return 1; default: return 0; } } /** * Given a literal to TheoryArith return a single kind to * to indicate its underlying structure. * The function returns the following in each case: * - (K left right) -> K where is a wildcard for EQUAL, LT, GT, LEQ, or GEQ: * - (NOT (EQUAL left right)) -> DISTINCT * - (NOT (LEQ left right)) -> GT * - (NOT (GEQ left right)) -> LT * - (NOT (LT left right)) -> GEQ * - (NOT (GT left right)) -> LEQ * If none of these match, it returns UNDEFINED_KIND. */ inline Kind simplifiedKind(TNode assertion){ switch(assertion.getKind()){ case kind::LT: case kind::GT: case kind::LEQ: case kind::GEQ: case kind::EQUAL: return assertion.getKind(); case kind::NOT: { TNode atom = assertion[0]; switch(atom.getKind()){ case kind::LEQ: //(not (LEQ x c)) <=> (GT x c) return kind::GT; case kind::GEQ: //(not (GEQ x c)) <=> (LT x c) return kind::LT; case kind::LT: //(not (LT x c)) <=> (GEQ x c) return kind::GEQ; case kind::GT: //(not (GT x c) <=> (LEQ x c) return kind::LEQ; case kind::EQUAL: return kind::DISTINCT; default: Unreachable(); return kind::UNDEFINED_KIND; } } default: Unreachable(); return kind::UNDEFINED_KIND; } } /** * Takes two nodes with exactly 2 children, * the second child of both are of kind CONST_RATIONAL, * and compares value of the two children. * This is for comparing inequality nodes. * RightHandRationalLT((<= x 50), (< x 75)) == true */ struct RightHandRationalLT { bool operator()(TNode s1, TNode s2) const { TNode rh1 = s1[1]; TNode rh2 = s2[1]; const Rational& c1 = rh1.getConst(); const Rational& c2 = rh2.getConst(); int cmpRes = c1.cmp(c2); return cmpRes < 0; } }; inline Node negateConjunctionAsClause(TNode conjunction){ Assert(conjunction.getKind() == kind::AND); NodeBuilder<> orBuilder(kind::OR); for(TNode::iterator i = conjunction.begin(), end=conjunction.end(); i != end; ++i){ TNode child = *i; Node negatedChild = NodeBuilder<1>(kind::NOT)<<(child); orBuilder << negatedChild; } return orBuilder; } }; /* namesapce arith */ }; /* namespace theory */ }; /* namespace CVC4 */ #endif /* __CVC4__THEORY__ARITH__ARITH_UTILITIES_H */