// integer constants. We must ensure numerator and denominator are
// constant and the denominator is non-zero. A similar issue happens for
// negative integers and reals, with unary minus.
+ // NOTE this should be applied more eagerly when UMINUS/DIVISION is
+ // constructed.
bool isNeg = false;
if (constVal.getKind() == api::UMINUS)
{
isNeg = true;
constVal = constVal[0];
}
- if (constVal.getKind() == api::DIVISION
- && constVal[0].getKind() == api::CONST_RATIONAL
- && constVal[1].getKind() == api::CONST_RATIONAL)
+ if (constVal.getKind() == api::DIVISION && isConstInt(constVal[0])
+ && isConstInt(constVal[1]))
{
std::stringstream sdiv;
sdiv << (isNeg ? "-" : "") << constVal[0] << "/" << constVal[1];
constVal = d_solver->mkReal(sdiv.str());
}
- else if (constVal.getKind() == api::CONST_RATIONAL && isNeg)
+ else if (isConstInt(constVal) && isNeg)
{
std::stringstream sneg;
sneg << "-" << constVal;
setLastNamedTerm(expr, name);
}
-api::Term Smt2::mkAnd(const std::vector<api::Term>& es)
+api::Term Smt2::mkAnd(const std::vector<api::Term>& es) const
{
if (es.size() == 0)
{
{
return es[0];
}
- else
- {
- return d_solver->mkTerm(api::AND, es);
- }
+ return d_solver->mkTerm(api::AND, es);
+}
+
+bool Smt2::isConstInt(const api::Term& t)
+{
+ api::Kind k = t.getKind();
+ // !!! Note when arithmetic subtyping is eliminated, this will update to
+ // CONST_INTEGER.
+ return k == api::CONST_RATIONAL;
}
} // namespace parser
* @return True if `es` is empty, `e` if `es` consists of a single element
* `e`, the conjunction of expressions otherwise.
*/
- api::Term mkAnd(const std::vector<api::Term>& es);
+ api::Term mkAnd(const std::vector<api::Term>& es) const;
+ /**
+ * Is term t a constant integer?
+ */
+ static bool isConstInt(const api::Term& t);
}; /* class Smt2 */
} // namespace parser
Node s;
if (c.isNull())
{
- c = cc.isNull() ? NodeManager::currentNM()->mkConst(
- CONST_RATIONAL, Rational(1))
- : cc;
+ c = cc.isNull()
+ ? NodeManager::currentNM()->mkConstInt(Rational(1))
+ : cc;
}
else
{
else
{
// TODO(#2377): could build ITE here
- Node test =
- other.eqNode(nm->mkConst(CONST_RATIONAL, Rational(0)));
+ Node test = other.eqNode(nm->mkConstReal(Rational(0)));
if (rewrite(test) != nm->mkConst<bool>(false))
{
break;
*/
void addMonomial(TNode x, const Rational& c, bool isNeg = false);
/**
- * Multiply this polynomial by the monomial x*c, where c is a CONST_RATIONAL.
+ * Multiply this polynomial by the monomial x*c, where c is a constant.
* If x is null, then x*c is treated as c.
*/
void multiplyMonomial(TNode x, const Rational& c);
}
}
+Node multConstants(const Node& c1, const Node& c2)
+{
+ Assert(!c1.isNull() && c1.isConst());
+ Assert(!c2.isNull() && c2.isConst());
+ NodeManager* nm = NodeManager::currentNM();
+ // real type if either has type real
+ TypeNode tn = c1.getType();
+ if (tn.isInteger())
+ {
+ tn = c2.getType();
+ }
+ Assert(tn.isRealOrInt());
+ return nm->mkConstRealOrInt(
+ tn, Rational(c1.getConst<Rational>() * c2.getConst<Rational>()));
+}
+
} // namespace arith
} // namespace theory
} // namespace cvc5
/** Negates a node in arithmetic proof normal form. */
Node negateProofLiteral(TNode n);
+/**
+ * Return the result of multiplying constant integer or real nodes c1 and c2.
+ * The returned type is real if either have type real.
+ */
+Node multConstants(const Node& c1, const Node& c2);
+
} // namespace arith
} // namespace theory
} // namespace cvc5
NodeManager* nm = NodeManager::currentNM();
SkolemManager* sm = nm->getSkolemManager();
Node A = node[0];
- Node zero = nm->mkConst(CONST_RATIONAL, Rational(0));
- Node one = nm->mkConst(CONST_RATIONAL, Rational(1));
+ Node zero = nm->mkConstInt(Rational(0));
+ Node one = nm->mkConstInt(Rational(1));
// types
TypeNode bagType = A.getType();
TypeNode elementType = A.getType().getBagElementType();
Node realValueOfAbstract =
rewrite(nm->mkNode(kind::FLOATINGPOINT_TO_REAL_TOTAL,
abstractValue,
- nm->mkConst(CONST_RATIONAL, Rational(0U))));
+ nm->mkConstReal(Rational(0U))));
Node bg = nm->mkNode(
kind::IMPLIES,
Node z = nm->mkNode(
kind::IMPLIES,
nm->mkNode(kind::FLOATINGPOINT_ISZ, node[0]),
- nm->mkNode(
- kind::EQUAL, node, nm->mkConst(CONST_RATIONAL, Rational(0U))));
+ nm->mkNode(kind::EQUAL, node, nm->mkConstReal(Rational(0U))));
handleLemma(z, InferenceId::FP_REGISTER_TERM);
return;
Node z = nm->mkNode(
kind::IMPLIES,
- nm->mkNode(
- kind::EQUAL, node[1], nm->mkConst(CONST_RATIONAL, Rational(0U))),
+ nm->mkNode(kind::EQUAL, node[1], nm->mkConstReal(Rational(0U))),
nm->mkNode(kind::EQUAL,
node,
nm->mkConst(FloatingPoint::makeZero(
FloatingPoint::PartialRational res(arg.convertToRational());
if (res.second) {
- Node lit = NodeManager::currentNM()->mkConst(CONST_RATIONAL, res.first);
+ Node lit = NodeManager::currentNM()->mkConstReal(res.first);
return RewriteResponse(REWRITE_DONE, lit);
} else {
// Can't constant fold the underspecified case
Rational partialValue(node[1].getConst<Rational>());
Rational folded(arg.convertToRationalTotal(partialValue));
- Node lit = NodeManager::currentNM()->mkConst(CONST_RATIONAL, folded);
+ Node lit = NodeManager::currentNM()->mkConstReal(folded);
return RewriteResponse(REWRITE_DONE, lit);
} else {
FloatingPoint::PartialRational res(arg.convertToRational());
if (res.second) {
- Node lit = NodeManager::currentNM()->mkConst(CONST_RATIONAL, res.first);
+ Node lit = NodeManager::currentNM()->mkConstReal(res.first);
return RewriteResponse(REWRITE_DONE, lit);
} else {
// Can't constant fold the underspecified case
ArithInstantiator::ArithInstantiator(Env& env, TypeNode tn, VtsTermCache* vtc)
: Instantiator(env, tn), d_vtc(vtc)
{
- d_zero = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(0));
- d_one = NodeManager::currentNM()->mkConst(CONST_RATIONAL, Rational(1));
+ d_zero = NodeManager::currentNM()->mkConstRealOrInt(tn, Rational(0));
+ d_one = NodeManager::currentNM()->mkConstRealOrInt(tn, Rational(1));
}
void ArithInstantiator::reset(CegInstantiator* ci,
uval = nm->mkNode(
PLUS,
val,
- nm->mkConst(CONST_RATIONAL,
- Rational(isUpperBoundCTT(uires) ? 1 : -1)));
+ nm->mkConstInt(Rational(isUpperBoundCTT(uires) ? 1 : -1)));
uval = rewrite(uval);
}
else
if (d_type.isInteger())
{
uires = is_upper ? CEG_TT_LOWER : CEG_TT_UPPER;
- uval =
- nm->mkNode(PLUS,
- val,
- nm->mkConst(CONST_RATIONAL,
- Rational(isUpperBoundCTT(uires) ? 1 : -1)));
+ uval = nm->mkNode(
+ PLUS,
+ val,
+ nm->mkConstInt(Rational(isUpperBoundCTT(uires) ? 1 : -1)));
uval = rewrite(uval);
}
else
{
if (options().quantifiers.cegqiModel)
{
- Node delta_coeff = nm->mkConst(
- CONST_RATIONAL, Rational(isUpperBoundCTT(uires) ? 1 : -1));
+ Node delta_coeff = nm->mkConstRealOrInt(
+ d_type, Rational(isUpperBoundCTT(uires) ? 1 : -1));
if (vts_coeff_delta.isNull())
{
vts_coeff_delta = delta_coeff;
Assert(d_mbp_coeff[rr][j].isConst());
value[t] = nm->mkNode(
MULT,
- nm->mkConst(
- CONST_RATIONAL,
- Rational(1) / d_mbp_coeff[rr][j].getConst<Rational>()),
+ nm->mkConstReal(Rational(1)
+ / d_mbp_coeff[rr][j].getConst<Rational>()),
value[t]);
value[t] = rewrite(value[t]);
}
}
else
{
- val =
- nm->mkNode(MULT,
- nm->mkNode(PLUS, vals[0], vals[1]),
- nm->mkConst(CONST_RATIONAL, Rational(1) / Rational(2)));
+ val = nm->mkNode(MULT,
+ nm->mkNode(PLUS, vals[0], vals[1]),
+ nm->mkConstReal(Rational(1) / Rational(2)));
val = rewrite(val);
}
}
vts_coeff[t] = itminf->second;
if (vts_coeff[t].isNull())
{
- vts_coeff[t] = nm->mkConst(CONST_RATIONAL, Rational(1));
+ vts_coeff[t] = nm->mkConstRealOrInt(d_type, Rational(1));
}
// negate if coefficient on variable is positive
std::map<Node, Node>::iterator itv = msum.find(pv);
{
vts_coeff[t] = nm->mkNode(
MULT,
- nm->mkConst(CONST_RATIONAL,
- Rational(-1) / itv->second.getConst<Rational>()),
+ nm->mkConstReal(Rational(-1)
+ / itv->second.getConst<Rational>()),
vts_coeff[t]);
vts_coeff[t] = rewrite(vts_coeff[t]);
}
}
}
// multiply everything by this coefficient
- Node rcoeff = nm->mkConst(CONST_RATIONAL, Rational(coeff));
+ Node rcoeff = nm->mkConstInt(Rational(coeff));
std::vector<Node> real_part;
for (std::map<Node, Node>::iterator it = msum.begin(); it != msum.end();
++it)
#include "expr/node_algorithm.h"
#include "options/quantifiers_options.h"
#include "theory/arith/arith_msum.h"
+#include "theory/arith/arith_utilities.h"
#include "theory/quantifiers/cegqi/ceg_arith_instantiator.h"
#include "theory/quantifiers/cegqi/ceg_bv_instantiator.h"
#include "theory/quantifiers/cegqi/ceg_dt_instantiator.h"
}
else
{
- NodeManager* nm = NodeManager::currentNM();
- d_coeff = nm->mkConst(CONST_RATIONAL,
- Rational(d_coeff.getConst<Rational>()
- * p.d_coeff.getConst<Rational>()));
+ d_coeff = arith::multConstants(d_coeff, p.d_coeff);
}
}
}
else
{
- Assert(new_theta.isConst());
- Assert(pv_prop.d_coeff.isConst());
- NodeManager* nm = NodeManager::currentNM();
- new_theta = nm->mkConst(CONST_RATIONAL,
- Rational(new_theta.getConst<Rational>()
- * pv_prop.d_coeff.getConst<Rational>()));
+ new_theta = arith::multConstants(new_theta, pv_prop.d_coeff);
}
d_theta.push_back(new_theta);
}
{
if (pat.getKind() == GT)
{
- t_match =
- nm->mkNode(MINUS, t, nm->mkConst(CONST_RATIONAL, Rational(1)));
+ t_match = nm->mkNode(
+ MINUS, t, nm->mkConstRealOrInt(t.getType(), Rational(1)));
}else{
t_match = t;
}
{
if (pat.getKind() == EQUAL)
{
- if (t.getType().isBoolean())
+ TypeNode tn = t.getType();
+ if (tn.isBoolean())
{
t_match = nm->mkConst(!d_qstate.areEqual(nm->mkConst(true), t));
}
else
{
- Assert(t.getType().isRealOrInt());
- t_match =
- nm->mkNode(PLUS, t, nm->mkConst(CONST_RATIONAL, Rational(1)));
+ Assert(tn.isRealOrInt());
+ t_match = nm->mkNode(PLUS, t, nm->mkConstRealOrInt(tn, Rational(1)));
}
}
else if (pat.getKind() == GEQ)
{
- t_match = nm->mkNode(PLUS, t, nm->mkConst(CONST_RATIONAL, Rational(1)));
+ t_match =
+ nm->mkNode(PLUS, t, nm->mkConstRealOrInt(t.getType(), Rational(1)));
}
else if (pat.getKind() == GT)
{
s = nm->mkNode(
PLUS,
s,
- nm->mkConst(CONST_RATIONAL, Rational(d_rel == GEQ ? -1 : 1)));
+ nm->mkConstRealOrInt(s.getType(), Rational(d_rel == GEQ ? -1 : 1)));
}
d_counter++;
Trace("relational-match-gen")