This changes several places in arithmetic so that it never generates equalities between and an Int and a Real.
It also changes several uses of mkConstReal on integer values with mkConstInt whenever their type does not matter.
Since we do not construct CONST_INTEGER yet, this PR has no behavior change yet.
TNode scalar = args[i];
bool isPos = scalar.getConst<Rational>() > 0;
Node scalarCmp =
- nm->mkNode(isPos ? GT : LT,
- scalar,
- nm->mkConstRealOrInt(scalar.getType(), Rational(0)));
+ nm->mkNode(isPos ? GT : LT, scalar, nm->mkConstInt(Rational(0)));
// (= scalarCmp true)
Node scalarCmpOrTrue = steps.tryStep(PfRule::EVALUATE, {}, {scalarCmp});
Assert(!scalarCmpOrTrue.isNull());
children.push_back(m);
}
}
- val =
- children.size() > 1
- ? nm->mkNode(ADD, children)
- : (children.size() == 1 ? children[0]
- : nm->mkConstRealOrInt(vtn, Rational(0)));
+ val = children.size() > 1
+ ? nm->mkNode(ADD, children)
+ : (children.size() == 1 ? children[0]
+ : nm->mkConstInt(Rational(0)));
if (!r.isOne() && !r.isNegativeOne())
{
if (vtn.isInteger())
{
- veq_c = nm->mkConstReal(r.abs());
+ veq_c = nm->mkConstRealOrInt(r.abs());
}
else
{
- val = nm->mkNode(MULT, val, nm->mkConstReal(Rational(1) / r.abs()));
+ val = nm->mkNode(
+ MULT, val, nm->mkConstReal(Rational(1) / r.abs()));
}
}
val = r.sgn() == 1
- ? nm->mkNode(MULT, nm->mkConstRealOrInt(vtn, Rational(-1)), val)
+ ? nm->mkNode(MULT, nm->mkConstRealOrInt(Rational(-1)), val)
: val;
return (r.sgn() == 1 || k == EQUAL) ? 1 : -1;
}
tn, Rational(c1.getConst<Rational>() * c2.getConst<Rational>()));
}
+Node mkEquality(Node a, Node b)
+{
+ NodeManager* nm = NodeManager::currentNM();
+ Assert(a.getType().isRealOrInt());
+ Assert(b.getType().isRealOrInt());
+ // if they have the same type, just make them equal
+ if (a.getType() == b.getType())
+ {
+ return nm->mkNode(EQUAL, a, b);
+ }
+ // otherwise subtract and set equal to zero
+ Node diff = nm->mkNode(Kind::SUB, a, b);
+ return nm->mkNode(EQUAL, diff, mkZero(diff.getType()));
+}
+
} // namespace arith
} // namespace theory
} // namespace cvc5::internal
*/
Node multConstants(const Node& c1, const Node& c2);
+/**
+ * Make the equality (= a b) or (= (- a b) zero) if a and b have different
+ * types, where zero has the same type as (- a b).
+ * Use this utility to ensure an equality is properly typed.
+ */
+Node mkEquality(Node a, Node b);
+
} // namespace arith
} // namespace theory
} // namespace cvc5::internal
#include "theory/arith/bound_inference.h"
#include "smt/env.h"
+#include "theory/arith/arith_utilities.h"
#include "theory/arith/linear/normal_form.h"
#include "theory/rewriter.h"
const Node& value,
bool strict)
{
+ Assert(value.isConst());
// lhs > or >= value because of origin
Trace("bound-inf") << "\tNew bound " << lhs << (strict ? ">" : ">=") << value
<< " due to " << origin << std::endl;
if (!b.lower_strict && !b.upper_strict && b.lower_value == b.upper_value)
{
- b.lower_bound = b.upper_bound =
- rewrite(nm->mkNode(Kind::EQUAL, lhs, value));
+ Node eq = mkEquality(lhs, value);
+ b.lower_bound = b.upper_bound = rewrite(eq);
}
else
{
b.upper_origin = origin;
if (!b.lower_strict && !b.upper_strict && b.lower_value == b.upper_value)
{
- b.lower_bound = b.upper_bound =
- rewrite(nm->mkNode(Kind::EQUAL, lhs, value));
+ Node eq = mkEquality(lhs, value);
+ b.lower_bound = b.upper_bound = rewrite(eq);
}
else
{
Constant Constant::mkConstant(const Rational& rat)
{
NodeManager* nm = NodeManager::currentNM();
- return Constant(nm->mkConstReal(rat));
+ return Constant(nm->mkConstRealOrInt(rat));
}
size_t Variable::getComplexity() const{
}
}
- static Polynomial parsePolynomial(Node n) {
+ static Polynomial parsePolynomial(Node n)
+ {
+ // required to remove TO_REAL here since equalities may require casts
+ n = n.getKind() == kind::TO_REAL ? n[0] : n;
return Polynomial(n);
}
{
d_false = NodeManager::currentNM()->mkConst(false);
d_true = NodeManager::currentNM()->mkConst(true);
- d_zero = NodeManager::currentNM()->mkConstReal(Rational(0));
- d_one = NodeManager::currentNM()->mkConstReal(Rational(1));
- d_neg_one = NodeManager::currentNM()->mkConstReal(Rational(-1));
+ d_zero = NodeManager::currentNM()->mkConstInt(Rational(0));
+ d_one = NodeManager::currentNM()->mkConstInt(Rational(1));
+ d_neg_one = NodeManager::currentNM()->mkConstInt(Rational(-1));
if (d_env.isTheoryProofProducing())
{
d_proof.reset(new CDProofSet<CDProof>(
}
Node sum = nm->mkNode(Kind::ADD, itf->second);
sum = rewrite(sum);
+ // remove TO_REAL if necessary here
+ sum = sum.getKind() == TO_REAL ? sum[0] : sum;
Trace("nl-ext-factor")
<< "* Factored sum for " << x << " : " << sum << std::endl;
<< "compareMonomial " << oa << " and " << ob << ", indices = " << a_index
<< " " << b_index << std::endl;
Assert(status == 0 || status == 2);
+ NodeManager* nm = NodeManager::currentNM();
const std::vector<Node>& vla = d_data->d_mdb.getVariableList(a);
const std::vector<Node>& vlb = d_data->d_mdb.getVariableList(b);
if (a_index == vla.size() && b_index == vlb.size())
exp.push_back(v.eqNode(zero).negate());
}
}
- NodeManager* nm = NodeManager::currentNM();
Node clem = nm->mkNode(
Kind::IMPLIES, nm->mkAnd(exp), mkLit(oa, ob, status, true));
Trace("nl-ext-comp-lemma") << "comparison lemma : " << clem << std::endl;
{
Trace("nl-ext-comp-debug") << "...take leading " << bv << std::endl;
// can multiply b by <=1
- exp.push_back(mkLit(d_data->d_one, bv, bvo == ovo ? 0 : 2, true));
+ Node one = mkOne(bv.getType());
+ exp.push_back(mkLit(one, bv, bvo == ovo ? 0 : 2, true));
return compareMonomial(oa,
a,
a_index,
{
Trace("nl-ext-comp-debug") << "...take leading " << av << std::endl;
// can multiply a by >=1
- exp.push_back(mkLit(av, d_data->d_one, avo == ovo ? 0 : 2, true));
+ Node one = mkOne(av.getType());
+ exp.push_back(mkLit(av, one, avo == ovo ? 0 : 2, true));
return compareMonomial(oa,
a,
a_index + 1,
{
Trace("nl-ext-comp-debug") << "...take leading " << av << std::endl;
// do avo>=1 instead
- exp.push_back(mkLit(av, d_data->d_one, avo == ovo ? 0 : 2, true));
+ Node one = mkOne(av.getType());
+ exp.push_back(mkLit(av, one, avo == ovo ? 0 : 2, true));
return compareMonomial(oa,
a,
a_index + 1,
}
Node MonomialCheck::mkLit(Node a, Node b, int status, bool isAbsolute) const
{
+ NodeManager* nm = NodeManager::currentNM();
Assert(a.getType().isComparableTo(b.getType()));
if (status == 0)
{
- Node a_eq_b = a.eqNode(b);
+ Node a_eq_b = mkEquality(a, b);
if (!isAbsolute)
{
return a_eq_b;
}
- Node negate_b = NodeManager::currentNM()->mkNode(Kind::NEG, b);
- return a_eq_b.orNode(a.eqNode(negate_b));
+ Node negate_b = nm->mkNode(Kind::NEG, b);
+ return a_eq_b.orNode(mkEquality(a, negate_b));
}
else if (status < 0)
{
return mkLit(b, a, -status);
}
Assert(status == 1 || status == 2);
- NodeManager* nm = NodeManager::currentNM();
Kind greater_op = status == 1 ? Kind::GEQ : Kind::GT;
if (!isAbsolute)
{
d_extTheory.addFunctionKind(kind::IAND);
d_extTheory.addFunctionKind(kind::POW2);
d_true = NodeManager::currentNM()->mkConst(true);
- d_zero = NodeManager::currentNM()->mkConstReal(Rational(0));
- d_one = NodeManager::currentNM()->mkConstReal(Rational(1));
- d_neg_one = NodeManager::currentNM()->mkConstReal(Rational(-1));
if (d_env.isTheoryProofProducing())
{
const std::vector<Node>& xts);
/** commonly used terms */
- Node d_zero;
- Node d_one;
- Node d_neg_one;
Node d_true;
// The theory of arithmetic containing this extension.
TheoryArith& d_containing;
if (x < 0 && pow2x != 0)
{
Node assumption = nm->mkNode(LT, n[0], d_zero);
- Node conclusion = nm->mkNode(EQUAL, n, d_zero);
+ Node conclusion = nm->mkNode(EQUAL, n, mkZero(n.getType()));
Node lem = nm->mkNode(IMPLIES, assumption, conclusion);
d_im.addPendingLemma(
lem, InferenceId::ARITH_NL_POW2_TRIVIAL_CASE_REFINE, nullptr, true);
// initial refinements
if (d_tf_initial_refine.find(t) == d_tf_initial_refine.end())
{
+ Node zero = nm->mkConstInt(Rational(0));
+ Node one = nm->mkConstInt(Rational(1));
d_tf_initial_refine[t] = true;
{
// exp is always positive: exp(t) > 0
- Node lem = nm->mkNode(Kind::GT, t, d_data->d_zero);
+ Node lem = nm->mkNode(Kind::GT, t, zero);
CDProof* proof = nullptr;
if (d_data->isProofEnabled())
{
lem, InferenceId::ARITH_NL_T_INIT_REFINE, proof);
}
{
- // exp at zero: (t = 0) <=> (exp(t) = 1)
- Node lem = nm->mkNode(Kind::EQUAL,
- t[0].eqNode(d_data->d_zero),
- t.eqNode(d_data->d_one));
+ // must use real one/zero in equalities
+ Node rzero = nm->mkConstReal(Rational(0));
+ Node rone = nm->mkConstReal(Rational(1));
+ // exp at zero: (t = 0.0) <=> (exp(t) = 1.0)
+ Node lem =
+ nm->mkNode(Kind::EQUAL, t[0].eqNode(rzero), t.eqNode(rone));
CDProof* proof = nullptr;
if (d_data->isProofEnabled())
{
{
// exp on negative values: (t < 0) <=> (exp(t) < 1)
Node lem = nm->mkNode(Kind::EQUAL,
- nm->mkNode(Kind::LT, t[0], d_data->d_zero),
- nm->mkNode(Kind::LT, t, d_data->d_one));
+ nm->mkNode(Kind::LT, t[0], zero),
+ nm->mkNode(Kind::LT, t, one));
CDProof* proof = nullptr;
if (d_data->isProofEnabled())
{
// exp on positive values: (t <= 0) or (exp(t) > t+1)
Node lem = nm->mkNode(
Kind::OR,
- nm->mkNode(Kind::LEQ, t[0], d_data->d_zero),
- nm->mkNode(
- Kind::GT, t, nm->mkNode(Kind::ADD, t[0], d_data->d_one)));
+ nm->mkNode(Kind::LEQ, t[0], zero),
+ nm->mkNode(Kind::GT, t, nm->mkNode(Kind::ADD, t[0], one)));
CDProof* proof = nullptr;
if (d_data->isProofEnabled())
{
// Check if we already have neighboring secant points
if (bounds.first.isNull())
{
+ NodeManager* nm = NodeManager::currentNM();
+ Node one = nm->mkConstInt(Rational(1));
// pick c-1
- bounds.first = rewrite(
- NodeManager::currentNM()->mkNode(Kind::SUB, center, d_data->d_one));
+ bounds.first = rewrite(nm->mkNode(Kind::SUB, center, one));
}
if (bounds.second.isNull())
{
+ NodeManager* nm = NodeManager::currentNM();
+ Node one = nm->mkConstInt(Rational(1));
// pick c+1
- bounds.second = rewrite(
- NodeManager::currentNM()->mkNode(Kind::ADD, center, d_data->d_one));
+ bounds.second = rewrite(nm->mkNode(Kind::ADD, center, one));
}
return bounds;
}
PfRule id, const std::vector<Node>& children, const std::vector<Node>& args)
{
NodeManager* nm = NodeManager::currentNM();
- Node zero = nm->mkConstReal(Rational(0));
- Node one = nm->mkConstReal(Rational(1));
- Node mone = nm->mkConstReal(Rational(-1));
+ Node zero = nm->mkConstInt(Rational(0));
+ Node one = nm->mkConstInt(Rational(1));
+ Node mone = nm->mkConstInt(Rational(-1));
Node pi = nm->mkNullaryOperator(nm->realType(), Kind::PI);
Node mpi = nm->mkNode(Kind::MULT, mone, pi);
Trace("nl-trans-checker") << "Checking " << id << std::endl;
Assert(children.empty());
Assert(args.size() == 1);
Node e = nm->mkNode(Kind::EXPONENTIAL, args[0]);
- return nm->mkNode(EQUAL, args[0].eqNode(zero), e.eqNode(one));
+ Node rzero = nm->mkConstReal(Rational(0));
+ Node rone = nm->mkConstReal(Rational(1));
+ return nm->mkNode(EQUAL, args[0].eqNode(rzero), e.eqNode(rone));
}
else if (id == PfRule::ARITH_TRANS_EXP_APPROX_ABOVE_POS)
{
{
d_true = NodeManager::currentNM()->mkConst(true);
d_false = NodeManager::currentNM()->mkConst(false);
- d_zero = NodeManager::currentNM()->mkConstReal(Rational(0));
- d_one = NodeManager::currentNM()->mkConstReal(Rational(1));
- d_neg_one = NodeManager::currentNM()->mkConstReal(Rational(-1));
+ d_zero = NodeManager::currentNM()->mkConstInt(Rational(0));
+ d_one = NodeManager::currentNM()->mkConstInt(Rational(1));
+ d_neg_one = NodeManager::currentNM()->mkConstInt(Rational(-1));
if (d_env.isTheoryProofProducing())
{
d_proof.reset(new CDProofSet<CDProof>(
lems.push_back(mkSkolemLemma(lem, v));
if (k == IS_INTEGER)
{
- return nm->mkNode(EQUAL, node[0], v);
+ return mkEquality(node[0], v);
}
Assert(k == TO_INTEGER);
return v;
Node v = sm->mkPurifySkolem(
rw, "nonlinearDiv", "the result of a non-linear div term");
Node lem = nm->mkNode(IMPLIES,
- den.eqNode(nm->mkConstReal(Rational(0))).negate(),
+ den.eqNode(mkZero(den.getType())).negate(),
nm->mkNode(MULT, den, v).eqNode(num));
lems.push_back(mkSkolemLemma(lem, v));
return v;
{
checkNonLinearLogic(node);
Node divByZeroNum = getArithSkolemApp(num, SkolemFunId::DIV_BY_ZERO);
- Node denEq0 = nm->mkNode(EQUAL, den, nm->mkConstReal(Rational(0)));
+ Node denEq0 = nm->mkNode(EQUAL, den, mkZero(den.getType()));
ret = nm->mkNode(ITE, denEq0, divByZeroNum, ret);
}
return ret;
|| rel == Kind::LEQ || rel == Kind::GT || rel == Kind::GEQ);
Node lhs = args[1][0];
Node rhs = args[1][1];
- Node zero = nm->mkConstRealOrInt(mult.getType(), Rational(0));
+ Node zero = nm->mkConstInt(Rational(0));
return nm->mkNode(Kind::IMPLIES,
nm->mkAnd(std::vector<Node>{
nm->mkNode(Kind::GT, mult, zero), args[1]}),
Kind rel_inv = (rel == Kind::DISTINCT ? rel : reverseRelationKind(rel));
Node lhs = args[1][0];
Node rhs = args[1][1];
- Node zero = nm->mkConstRealOrInt(mult.getType(), Rational(0));
+ Node zero = nm->mkConstInt(Rational(0));
return nm->mkNode(Kind::IMPLIES,
nm->mkAnd(std::vector<Node>{
nm->mkNode(Kind::LT, mult, zero), args[1]}),
#include "expr/node_algorithm.h"
#include "options/quantifiers_options.h"
#include "theory/arith/arith_msum.h"
+#include "theory/arith/arith_utilities.h"
#include "theory/arith/linear/partial_model.h"
-#include "theory/arith/theory_arith.h"
#include "theory/arith/linear/theory_arith_private.h"
+#include "theory/arith/theory_arith.h"
#include "theory/quantifiers/term_util.h"
#include "theory/rewriter.h"
#include "util/random.h"
eq_rhs = nm->mkNode(MULT, lhs_coeff, eq_rhs);
}
}
- Node eq = eq_lhs.eqNode(eq_rhs);
+ Node eq = arith::mkEquality(eq_lhs, eq_rhs);
eq = rewrite(eq);
Node val;
TermProperties pv_prop;
// solve updated rewritten equality for vars[index], if coefficient is one,
// then we are successful
Node eq_rhs = sf.d_subs[index];
- Node eq = eq_lhs.eqNode(eq_rhs);
+ Node eq = arith::mkEquality(eq_lhs, eq_rhs);
eq = rewrite(eq);
Trace("cegqi-arith-debug") << "...equality is " << eq << std::endl;
std::map<Node, Node> msum;