This PR fixes two issues with the (missing) handling of to_real.
The first is that equality substitution was not aware of to_real yet, possible introducing models for both x and (to_real x).
The second is that the conversion to libpoly polynomials would also not properly unpack to_real expressions.
Fixes #8835.
// reductions inference of the sine solver) may have introduced substitutions
// internally during check.
Node svalue = d_model.getSubstitutedForm(value);
+ if (var.getType().isInteger() && svalue.getKind() == Kind::TO_REAL)
+ {
+ svalue = svalue[0];
+ }
Trace("nl-cov") << "-> " << var << " = " << svalue << std::endl;
d_model.addSubstitution(var, svalue);
}
Assert(o.getNumChildren() == 2);
for (size_t i = 0; i < 2; ++i)
{
- const auto& l = o[i];
- const auto& r = o[1 - i];
+ const auto& l = (o[i].getKind() == Kind::TO_REAL ? o[i][0] : o[i]);
+ const auto& r = (o[1-i].getKind() == Kind::TO_REAL ? o[1-i][0] : o[1-i]);
// lhs can't be constant
if (l.isConst()) continue;
// types must match (otherwise we might have int/real issues)
return res;
}
-poly::UPolynomial as_poly_upolynomial_impl(const cvc5::internal::Node& n,
+poly::UPolynomial as_poly_upolynomial_impl(cvc5::internal::Node n,
poly::Integer& denominator,
const cvc5::internal::Node& var)
{
+ if (n.getKind() == Kind::TO_REAL) n = n[0];
denominator = poly::Integer(1);
if (n.isVar())
{
return as_poly_upolynomial_impl(n, denom, var);
}
-poly::Polynomial as_poly_polynomial_impl(const cvc5::internal::Node& n,
+poly::Polynomial as_poly_polynomial_impl(cvc5::internal::Node n,
poly::Integer& denominator,
VariableMapper& vm)
{
+ if (n.getKind() == Kind::TO_REAL) n = n[0];
denominator = poly::Integer(1);
if (n.isVar())
{
cvc5::internal::Node as_cvc_upolynomial(const poly::UPolynomial& p,
const cvc5::internal::Node& var);
-/** Convert a cvc5::internal::Node to a poly univariate polynomial. */
+/**
+ * Convert a cvc5::internal::Node to a poly univariate polynomial. Is robust to
+ * n being a `Kind::TO_REAL` wrapper node.
+ */
poly::UPolynomial as_poly_upolynomial(const cvc5::internal::Node& n,
const cvc5::internal::Node& var);
* (like in the context of coverings). If we need the actual polynomial (for example
* in the context of ICP) the second overload provides the denominator in the
* third argument.
+ * The method is robust to n being a `Kind::TO_REAL` wrapper node.
*/
poly::Polynomial as_poly_polynomial(const cvc5::internal::Node& n, VariableMapper& vm);
poly::Polynomial as_poly_polynomial(const cvc5::internal::Node& n,
regress0/nl/issue8744-real.smt2
regress0/nl/issue8744-real-cov.smt2
regress0/nl/issue8755-nl-logic-exception.smt2
+ regress0/nl/issue8835-int-second.smt2
regress0/nl/lazard-spurious-root.smt2
regress0/nl/magnitude-wrong-1020-m.smt2
regress0/nl/mult-po.smt2
--- /dev/null
+; EXPECT: sat
+; REQUIRES: poly
+(set-logic ALL)
+(set-option :nl-cov true)
+(set-option :check-models true)
+(declare-fun a () Int)
+(declare-fun b () Int)
+(declare-fun c () Real)
+(assert (= (* 1 (/ 1 69)) (+ b 1 (* b (* (* 2 c) a)) (- 1))))
+(check-sat)