Adds TypeNode::isArithmetic, NodeManager::mkConstReal and NodeManager::mkConstInt.
The first method (for now) is equivalent to TypeNode::isReal, and the latter 2 are equivalent to NodeManager::mkConst(CONST_RATIONAL, ...).
This furthermore distinguishes all uses of isReal: all that intend to be isArithmetic are changed in this PR. Redundant uses of isReal() || isInteger() are merged to isArithmetic().
Due to the above, there are no behavior changes in this PR.
#include "theory/sets/singleton_op.h"
#include "util/abstract_value.h"
#include "util/bitvector.h"
+#include "util/rational.h"
#include "util/resource_manager.h"
using namespace std;
return nb.constructNode();
}
+Node NodeManager::mkConstReal(const Rational& r)
+{
+ return mkConst(kind::CONST_RATIONAL, r);
+}
+
+Node NodeManager::mkConstInt(const Rational& r)
+{
+ // !!!! Note will update to CONST_INTEGER.
+ return mkConst(kind::CONST_RATIONAL, r);
+}
+
} // namespace cvc5
class BoundVarManager;
class DType;
+class Rational;
namespace expr {
namespace attr {
template <class NodeClass, class T>
NodeClass mkConstInternal(Kind k, const T&);
+ /**
+ * Make constant real. Returns constant of kind CONST_RATIONAL with Rational
+ * payload.
+ */
+ Node mkConstReal(const Rational& r);
+
+ /**
+ * Make constant real. Returns constant of kind CONST_INTEGER with Rational
+ * payload.
+ *
+ * !!! Note until subtypes are eliminated, this returns a constant of kind
+ * CONST_RATIONAL.
+ */
+ Node mkConstInt(const Rational& r);
+
/** Create a node with children. */
TypeNode mkTypeNode(Kind kind, TypeNode child1);
TypeNode mkTypeNode(Kind kind, TypeNode child1, TypeNode child2);
{
ret = CardinalityClass::FINITE;
}
- else if (isString() || isRegExp() || isSequence() || isReal() || isBag())
+ else if (isString() || isRegExp() || isSequence() || isRealOrInt() || isBag())
{
ret = CardinalityClass::INFINITE;
}
bool TypeNode::isStringLike() const { return isString() || isSequence(); }
+// !!! Note that this will change to isReal() || isInteger() when subtyping is
+// eliminated
+bool TypeNode::isRealOrInt() const { return isReal(); }
+
bool TypeNode::isSubtypeOf(TypeNode t) const {
if(*this == t) {
return true;
/** Is this a string-like type? (string or sequence) */
bool isStringLike() const;
+ /** Is this the integer or real type? */
+ bool isRealOrInt() const;
+
/** Is this the Rounding Mode type? */
bool isRoundingMode() const;
// could also do num + k*den checks
}
}
- else if (k == GEQ || (k == EQUAL && nr[0].getType().isReal()))
+ else if (k == GEQ || (k == EQUAL && nr[0].getType().isRealOrInt()))
{
std::map<Node, Node> msum;
if (ArithMSum::getMonomialSumLit(nr, msum))
}
if (!type_asc_arg.isNull())
{
- if (force_nt.isReal())
+ if (force_nt.isRealOrInt())
{
// we prefer using (/ x 1) instead of (to_real x) here.
// the reason is that (/ x 1) is SMT-LIB compliant when x is a constant
std::vector<Node> children;
for (size_t i = 0, size = n.getNumChildren(); i < size; ++i)
{
- if (!argTypes[i].isReal() || argTypes[i].isInteger() || !n[i].isConst()
- || !n[i].getType().isInteger())
+ if (!argTypes[i].isRealOrInt() || argTypes[i].isInteger()
+ || !n[i].isConst() || !n[i].getType().isInteger())
{
children.push_back(n[i]);
continue;
switch(n.getKind()){
case ITE:{
Node c = n[0], t = n[1], e = n[2];
- if(n.getType().isReal()){
+ if (n.getType().isRealOrInt())
+ {
Node rc = reduceVariablesInItes(c);
Node rt = reduceVariablesInItes(t);
Node re = reduceVariablesInItes(e);
d_varParts[n] = vpite;
return sum;
}
- }else{ // non-arith ite
+ }
+ else
+ { // non-arith ite
if(!d_contains.containsTermITE(n)){
// don't bother adding to d_reduceVar
return n;
}
}break;
default:
- if(n.getType().isReal() && Polynomial::isMember(n)){
+ if (n.getType().isRealOrInt() && Polynomial::isMember(n))
+ {
Node newn = Node::null();
if(!d_contains.containsTermITE(n)){
newn = n;
d_reduceVar[n] = newn;
return newn;
}
- }else{
+ }
+ else
+ {
if(!d_contains.containsTermITE(n)){
return n;
}
}else{
return d_one;
}
- }else if(n.getKind() == kind::ITE && n.getType().isReal()){
+ }
+ else if (n.getKind() == kind::ITE && n.getType().isRealOrInt())
+ {
const Integer& tgcd = gcdIte(n[1]);
if(tgcd.isOne()){
d_gcds[n] = d_one;
Node ArithIteUtils::reduceIteConstantIteByGCD(Node n){
Assert(n.getKind() == kind::ITE);
- Assert(n.getType().isReal());
+ Assert(n.getType().isRealOrInt());
const Integer& gcd = gcdIte(n);
if(gcd.isOne()){
Node newIte = reduceConstantIteByGCD(n[0]).iteNode(n[1],n[2]);
if(d_reduceGcd.find(n) != d_reduceGcd.end()){
return d_reduceGcd[n];
}
- if(n.getKind() == kind::ITE && n.getType().isReal()){
+ if (n.getKind() == kind::ITE && n.getType().isRealOrInt())
+ {
return reduceIteConstantIteByGCD(n);
}
return lit[1 - r];
}
}
- if (tn.isReal())
+ if (tn.isRealOrInt())
{
std::map<Node, Node> msum;
if (ArithMSum::getMonomialSumLit(lit, msum))
* (b) c is null.
*
* We say Node v is a {monomial variable} (or m-variable) if either:
- * (a) v.getType().isReal() and v is not a constant, or
+ * (a) v.getType().isRealOrInt() and v is not a constant, or
* (b) v is null.
*
* For m-constant or m-variable t, we write [t] to denote 1 if t.isNull() and
PolyNorm PolyNorm::mkPolyNorm(TNode n)
{
- Assert(n.getType().isReal());
+ Assert(n.getType().isRealOrInt());
Rational one(1);
Node null;
std::unordered_map<TNode, PolyNorm> visited;
"util/rational.h" \
"a multiple-precision rational constant; payload is an instance of the cvc5::Rational class"
+constant CONST_INTEGER \
+ class \
+ Rational \
+ ::cvc5::RationalHashFunction \
+ "util/rational.h" \
+ "a multiple-precision integer constant; payload is an instance of the cvc5::Rational class"
+
enumerator REAL_TYPE \
"::cvc5::theory::arith::RationalEnumerator" \
"theory/arith/type_enumerator.h"
typerule POW ::cvc5::theory::arith::ArithOperatorTypeRule
typerule CONST_RATIONAL ::cvc5::theory::arith::ArithConstantTypeRule
+typerule CONST_INTEGER ::cvc5::theory::arith::ArithConstantTypeRule
-typerule LT "SimpleTypeRule<RBool, AReal, AReal>"
-typerule LEQ "SimpleTypeRule<RBool, AReal, AReal>"
-typerule GT "SimpleTypeRule<RBool, AReal, AReal>"
-typerule GEQ "SimpleTypeRule<RBool, AReal, AReal>"
+typerule LT ::cvc5::theory::arith::ArithRelationTypeRule
+typerule LEQ ::cvc5::theory::arith::ArithRelationTypeRule
+typerule GT ::cvc5::theory::arith::ArithRelationTypeRule
+typerule GEQ ::cvc5::theory::arith::ArithRelationTypeRule
typerule INDEXED_ROOT_PREDICATE_OP "SimpleTypeRule<RBuiltinOperator>"
typerule INDEXED_ROOT_PREDICATE ::cvc5::theory::arith::IndexedRootPredicateTypeRule
{
Assert(children.empty());
Assert(args.size() == 6);
- Assert(args[0].getType().isReal());
- Assert(args[1].getType().isReal());
- Assert(args[2].getType().isReal());
- Assert(args[3].getType().isReal());
- Assert(args[4].getType().isReal());
+ Assert(args[0].getType().isRealOrInt());
+ Assert(args[1].getType().isRealOrInt());
+ Assert(args[2].getType().isRealOrInt());
+ Assert(args[3].getType().isRealOrInt());
+ Assert(args[4].getType().isRealOrInt());
Assert(args[5].isConst() && args[5].getKind() == Kind::CONST_RATIONAL
&& args[5].getConst<Rational>().isIntegral());
Node t = args[0];
if (visited.find(cur) == visited.end())
{
visited.insert(cur);
- if (cur.getType().isReal() && !cur.isConst())
+ if (cur.getType().isRealOrInt() && !cur.isConst())
{
Kind k = cur.getKind();
if (k != MULT && k != PLUS && k != NONLINEAR_MULT
{
return TrustNode::null();
}
- Assert(atom[0].getType().isReal());
+ Assert(atom[0].getType().isRealOrInt());
Node leq = NodeBuilder(kind::LEQ) << atom[0] << atom[1];
Node geq = NodeBuilder(kind::GEQ) << atom[0] << atom[1];
Node rewritten = rewrite(leq.andNode(geq));
throw LogicException(ss.str());
}
Assert(!d_partialModel.hasArithVar(x));
- Assert(x.getType().isReal()); // real or integer
+ Assert(x.getType().isRealOrInt()); // real or integer
ArithVar max = d_partialModel.getNumberOfVariables();
ArithVar varX = d_partialModel.allocate(x, aux);
case kind::LT:
return !isSatLiteral(n);
case kind::EQUAL:
- if(n[0].getType().isReal()){
+ if (n[0].getType().isRealOrInt())
+ {
return !isSatLiteral(n);
- }else if(n[0].getType().isBoolean()){
+ }
+ else if (n[0].getType().isBoolean())
+ {
return hasFreshArithLiteral(n[0]) ||
hasFreshArithLiteral(n[1]);
- }else{
+ }
+ else
+ {
return false;
}
case kind::IMPLIES:
}
if (check)
{
- if (!childType.isReal())
+ if (!childType.isRealOrInt())
{
throw TypeCheckingExceptionPrivate(n,
"expecting an arithmetic subterm");
}
}
+TypeNode ArithRelationTypeRule::computeType(NodeManager* nodeManager,
+ TNode n,
+ bool check)
+{
+ if (check)
+ {
+ Assert(n.getNumChildren() == 2);
+ TypeNode t1 = n[0].getType(check);
+ if (!t1.isRealOrInt())
+ {
+ throw TypeCheckingExceptionPrivate(
+ n, "expecting an arithmetic term for arithmetic relation");
+ }
+ TypeNode t2 = n[1].getType(check);
+ if (!t1.isComparableTo(t2))
+ {
+ throw TypeCheckingExceptionPrivate(
+ n, "expecting arithmetic terms of comparable type");
+ }
+ }
+ return nodeManager->booleanType();
+}
+
TypeNode RealNullaryOperatorTypeRule::computeType(NodeManager* nodeManager,
TNode n,
bool check)
n, "expecting boolean term as first argument");
}
TypeNode t2 = n[1].getType(check);
- if (!t2.isReal())
+ if (!t2.isRealOrInt())
{
throw TypeCheckingExceptionPrivate(
n, "expecting polynomial as second argument");
static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check);
};
+/**
+ * Type rule for arithmetic relations. Returns Boolean. Throws a type error
+ * if the types of the children are not arithmetic or not comparable.
+ */
+class ArithRelationTypeRule
+{
+ public:
+ static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check);
+};
+
/**
* Type rule for arithmetic operators.
* Takes care of mixed-integer operators, cases and (total) division.
{
kle = kind::FLOATINGPOINT_LEQ;
}
- else if (type.isInteger() || type.isReal())
+ else if (type.isRealOrInt())
{
kle = kind::LEQ;
}
n, "eqrange upper index type does not match array index type");
}
if (!indexType.isBitVector() && !indexType.isFloatingPoint()
- && !indexType.isInteger() && !indexType.isReal())
+ && !indexType.isRealOrInt())
{
throw TypeCheckingExceptionPrivate(
n,
Node atom = lit.getKind() == NOT ? lit[0] : lit;
// arithmetic inequalities and disequalities
if (atom.getKind() == GEQ
- || (atom.getKind() == EQUAL && atom[0].getType().isReal()))
+ || (atom.getKind() == EQUAL && atom[0].getType().isRealOrInt()))
{
return lit;
}
bool pol = lit.getKind() != NOT;
// arithmetic inequalities and disequalities
Assert(atom.getKind() == GEQ
- || (atom.getKind() == EQUAL && atom[0].getType().isReal()));
+ || (atom.getKind() == EQUAL && atom[0].getType().isRealOrInt()));
// get model value for pv
Node pv_value = ci->getModelValue(pv);
// cannot contain infinity?
return itv->second;
}
CegHandledStatus ret = CEG_UNHANDLED;
- if (tn.isInteger() || tn.isReal() || tn.isBoolean() || tn.isBitVector()
+ if (tn.isRealOrInt() || tn.isBoolean() || tn.isBitVector()
|| tn.isFloatingPoint())
{
ret = CEG_HANDLED;
if( d_instantiator.find( v )==d_instantiator.end() ){
TypeNode tn = v.getType();
Instantiator * vinst;
- if( tn.isReal() ){
+ if (tn.isRealOrInt())
+ {
vinst = new ArithInstantiator(d_env, tn, d_parent->getVtsTermCache());
- }else if( tn.isDatatype() ){
+ }
+ else if (tn.isDatatype())
+ {
vinst = new DtInstantiator(d_env, tn);
- }else if( tn.isBitVector() ){
+ }
+ else if (tn.isBitVector())
+ {
vinst = new BvInstantiator(d_env, tn, d_parent->getBvInverter());
- }else if( tn.isBoolean() ){
+ }
+ else if (tn.isBoolean())
+ {
vinst = new ModelValueInstantiator(d_env, tn);
- }else{
+ }
+ else
+ {
//default
vinst = new Instantiator(d_env, tn);
}
Node atom = lit.getKind()==NOT ? lit[0] : lit;
bool pol = lit.getKind()!=NOT;
//arithmetic inequalities and disequalities
- if( atom.getKind()==GEQ || ( atom.getKind()==EQUAL && !pol && atom[0].getType().isReal() ) ){
+ if (atom.getKind() == GEQ
+ || (atom.getKind() == EQUAL && !pol && atom[0].getType().isRealOrInt()))
+ {
NodeManager* nm = NodeManager::currentNM();
Assert(atom.getKind() != GEQ || atom[1].isConst());
Node atom_lhs;
}
}
}
- }else{
+ }
+ else
+ {
// don't know how to apply substitution to literal
}
}
TheoryId tid = Theory::theoryOf( rtn );
//if we care about the theory of this eqc
if( std::find( d_tids.begin(), d_tids.end(), tid )!=d_tids.end() ){
- if( rtn.isInteger() || rtn.isReal() ){
+ if (rtn.isRealOrInt())
+ {
rtn = rtn.getBaseType();
}
Trace("cegqi-proc-debug") << "...type eqc: " << r << std::endl;
}
else
{
- Assert(t.getType().isReal());
+ Assert(t.getType().isRealOrInt());
t_match =
nm->mkNode(PLUS, t, nm->mkConst(CONST_RATIONAL, Rational(1)));
}
else if (TriggerTermInfo::isRelationalTrigger(n))
{
Node rtr = getIsUsableEq(q, n);
- if (rtr.isNull() && n[0].getType().isReal())
+ if (rtr.isNull() && n[0].getType().isRealOrInt())
{
// try to solve relation
std::map<Node, Node> m;
d_pol(pol),
d_counter(0)
{
- Assert((rtrigger.getKind() == EQUAL && rtrigger[0].getType().isReal())
+ Assert((rtrigger.getKind() == EQUAL && rtrigger[0].getType().isRealOrInt())
|| rtrigger.getKind() == GEQ);
Trace("relational-match-gen")
<< "Relational trigger: " << rtrigger << ", hasPol/pol = " << hasPol
lit = lit[0];
}
// is it a relational trigger?
- if ((lit.getKind() == EQUAL && lit[0].getType().isReal())
+ if ((lit.getKind() == EQUAL && lit[0].getType().isRealOrInt())
|| lit.getKind() == GEQ)
{
// if one side of the relation is a variable and the other side is a ground
<< "Do aggressive rewrites on " << n << std::endl;
bool polarity = n.getKind() != NOT;
Node ret_atom = n.getKind() == NOT ? n[0] : n;
- if ((ret_atom.getKind() == EQUAL && ret_atom[0].getType().isReal())
+ if ((ret_atom.getKind() == EQUAL && ret_atom[0].getType().isRealOrInt())
|| ret_atom.getKind() == GEQ)
{
// ITE term removal in polynomials
}else if( q[1][1]==h ){
return q[1][0];
}
- else if (q[1][0].getType().isReal())
+ else if (q[1][0].getType().isRealOrInt())
{
// solve for h in the equality
std::map<Node, Node> msum;
Assert(lit.getKind() == EQUAL);
Node slv;
TypeNode tt = lit[0].getType();
- if (tt.isReal())
+ if (tt.isRealOrInt())
{
slv = getVarElimEqReal(lit, args, var);
}
<< ", pol = " << pol << "..." << std::endl;
bool canSolve =
lit.getKind() == GEQ
- || (lit.getKind() == EQUAL && lit[0].getType().isReal() && !pol);
+ || (lit.getKind() == EQUAL && lit[0].getType().isRealOrInt() && !pol);
if (!canSolve)
{
continue;
rdl.d_rd[1] = nullptr;
}else{
//solve the inequality for one/two variables, if possible
- if( n[0].getType().isReal() ){
+ if (n[0].getType().isRealOrInt())
+ {
std::map< Node, Node > msum;
if (ArithMSum::getMonomialSumLit(n, msum))
{
if( cur.isConst() ){
TypeNode tn = cur.getType();
Node c = cur;
- if( tn.isReal() ){
+ if (tn.isRealOrInt())
+ {
c = nm->mkConst(CONST_RATIONAL, c.getConst<Rational>().abs());
}
consts[tn].insert(c);
std::vector<Node>& ops)
{
NodeManager* nm = NodeManager::currentNM();
- if (type.isReal())
+ if (type.isRealOrInt())
{
ops.push_back(nm->mkConst(CONST_RATIONAL, Rational(0)));
ops.push_back(nm->mkConst(CONST_RATIONAL, Rational(1)));
opLArgs.push_back(nm->mkBoundVar(bArgType));
// build zarg
Node zarg;
- Assert(bArgType.isReal() || bArgType.isBitVector());
- if (bArgType.isReal())
+ Assert(bArgType.isRealOrInt() || bArgType.isBitVector());
+ if (bArgType.isRealOrInt())
{
zarg = nm->mkConst(CONST_RATIONAL, Rational(0));
}
// If the type does not support any term, we do any constant instead.
// We also fall back on any constant construction if the type has no
// constructors at this point (e.g. it simply encodes all constants).
- if (!types[i].isReal())
+ if (!types[i].isRealOrInt())
{
tsgcm = options::SygusGrammarConsMode::ANY_CONST;
}
}
}
- if (types[i].isReal())
+ if (types[i].isRealOrInt())
{
// Add PLUS, MINUS
Kind kinds[2] = {PLUS, MINUS};
<< "Build any-term datatype for " << types[i] << "..." << std::endl;
// for now, only real has any term construction
- Assert(types[i].isReal());
+ Assert(types[i].isRealOrInt());
// We have initialized the given type sdts[i], which should now contain
// a constructor for each relevant arithmetic term/variable. We now
// construct a sygus datatype of one of the following two forms.
}
// type specific predicates
std::stringstream ssop;
- if (types[i].isReal())
+ if (types[i].isRealOrInt())
{
Kind kind = LEQ;
Trace("sygus-grammar-def") << "...add for " << k << std::endl;
Node TermUtil::mkTypeValue(TypeNode tn, int32_t val)
{
Node n;
- if (tn.isInteger() || tn.isReal())
+ if (tn.isRealOrInt())
{
Rational c(val);
n = NodeManager::currentNM()->mkConst(CONST_RATIONAL, c);
status = -1;
if (!offset_val.isNull())
{
- if (tn.isInteger() || tn.isReal())
+ if (tn.isRealOrInt())
{
val_o = Rewriter::rewrite(
NodeManager::currentNM()->mkNode(PLUS, val, offset_val));
}
else
{
- if (n.getType().isReal() && n.getConst<Rational>().sgn() < 0)
+ if (n.getType().isInteger() && n.getConst<Rational>().sgn() < 0)
{
// negative arguments
if (ik == STRING_SUBSTR || ik == STRING_CHARAT)