This PR eliminates all static calls to the rewriter from the transcendental solver. We now either use the rewriter from the Env object or the theory evaluator. For this to work, the evaluator is extended to support division. In some places, the rewriting was removed altogether.
#include "expr/sequence.h"
#include "theory/arith/arith_utilities.h"
#include "theory/arith/nl/transcendental/taylor_generator.h"
-#include "theory/rewriter.h"
+#include "theory/evaluator.h"
using namespace cvc5::kind;
/**
* Helper method to construct a secant plane:
- * ((evall - evalu) / (l - u)) * (t - l) + evall
+ * evall + ((evall - evalu) / (l - u)) * (t - l)
*/
Node mkSecant(TNode t, TNode l, TNode u, TNode evall, TNode evalu)
{
NodeManager* nm = NodeManager::currentNM();
return nm->mkNode(Kind::PLUS,
+ evall,
nm->mkNode(Kind::MULT,
nm->mkNode(Kind::DIVISION,
nm->mkNode(Kind::MINUS, evall, evalu),
nm->mkNode(Kind::MINUS, l, u)),
- nm->mkNode(Kind::MINUS, t, l)),
- evall);
+ nm->mkNode(Kind::MINUS, t, l)));
}
} // namespace
TaylorGenerator tg;
TaylorGenerator::ApproximationBounds bounds;
tg.getPolynomialApproximationBounds(Kind::EXPONENTIAL, d / 2, bounds);
- Node evall = Rewriter::rewrite(
- bounds.d_upperPos.substitute(tg.getTaylorVariable(), l));
- Node evalu = Rewriter::rewrite(
- bounds.d_upperPos.substitute(tg.getTaylorVariable(), u));
+ Evaluator eval(nullptr);
+ Node evall = eval.eval(bounds.d_upperPos, {tg.getTaylorVariable()}, {l});
+ Node evalu = eval.eval(bounds.d_upperPos, {tg.getTaylorVariable()}, {u});
Node evalsecant = mkSecant(t, l, u, evall, evalu);
Node lem = nm->mkNode(
Kind::IMPLIES,
mkBounds(t, l, u),
nm->mkNode(Kind::LEQ, nm->mkNode(Kind::EXPONENTIAL, t), evalsecant));
- return Rewriter::rewrite(lem);
+ return lem;
}
else if (id == PfRule::ARITH_TRANS_EXP_APPROX_ABOVE_NEG)
{
TaylorGenerator tg;
TaylorGenerator::ApproximationBounds bounds;
tg.getPolynomialApproximationBounds(Kind::EXPONENTIAL, d / 2, bounds);
- Node evall = Rewriter::rewrite(
- bounds.d_upperNeg.substitute(tg.getTaylorVariable(), l));
- Node evalu = Rewriter::rewrite(
- bounds.d_upperNeg.substitute(tg.getTaylorVariable(), u));
+ Evaluator eval(nullptr);
+ Node evall = eval.eval(bounds.d_upperNeg, {tg.getTaylorVariable()}, {l});
+ Node evalu = eval.eval(bounds.d_upperNeg, {tg.getTaylorVariable()}, {u});
Node evalsecant = mkSecant(t, l, u, evall, evalu);
Node lem = nm->mkNode(
Kind::IMPLIES,
mkBounds(t, l, u),
nm->mkNode(Kind::LEQ, nm->mkNode(Kind::EXPONENTIAL, t), evalsecant));
- return Rewriter::rewrite(lem);
+ return lem;
}
else if (id == PfRule::ARITH_TRANS_EXP_APPROX_BELOW)
{
TaylorGenerator tg;
TaylorGenerator::ApproximationBounds bounds;
tg.getPolynomialApproximationBounds(Kind::EXPONENTIAL, d, bounds);
- Node eval =
- Rewriter::rewrite(bounds.d_lower.substitute(tg.getTaylorVariable(), t));
+ Evaluator eval(nullptr);
+ Node evalt = eval.eval(bounds.d_lower, {tg.getTaylorVariable()}, {t});
return nm->mkNode(
- Kind::GEQ, std::vector<Node>{nm->mkNode(Kind::EXPONENTIAL, t), eval});
+ Kind::GEQ, std::vector<Node>{nm->mkNode(Kind::EXPONENTIAL, t), evalt});
}
else if (id == PfRule::ARITH_TRANS_SINE_BOUNDS)
{
Assert(args.size() == 1);
Assert(args[0].getType().isReal());
Node s1 = nm->mkNode(Kind::SINE, args[0]);
- Node s2 = nm->mkNode(
- Kind::SINE, Rewriter::rewrite(nm->mkNode(Kind::MULT, mone, args[0])));
+ Node s2 = nm->mkNode(Kind::SINE, nm->mkNode(Kind::MULT, mone, args[0]));
return nm->mkNode(PLUS, s1, s2).eqNode(zero);
}
else if (id == PfRule::ARITH_TRANS_SINE_TANGENT_ZERO)
TaylorGenerator tg;
TaylorGenerator::ApproximationBounds bounds;
tg.getPolynomialApproximationBounds(Kind::SINE, d / 2, bounds);
- Node evall = Rewriter::rewrite(
- bounds.d_upperNeg.substitute(tg.getTaylorVariable(), l));
- Node evalu = Rewriter::rewrite(
- bounds.d_upperNeg.substitute(tg.getTaylorVariable(), u));
+ Evaluator eval(nullptr);
+ Node evall = eval.eval(bounds.d_upperNeg, {tg.getTaylorVariable()}, {l});
+ Node evalu = eval.eval(bounds.d_upperNeg, {tg.getTaylorVariable()}, {u});
Node lem = nm->mkNode(
Kind::IMPLIES,
mkBounds(t, lb, ub),
nm->mkNode(
Kind::LEQ, nm->mkNode(Kind::SINE, t), mkSecant(t, lb, ub, l, u)));
- return Rewriter::rewrite(lem);
+ return lem;
}
else if (id == PfRule::ARITH_TRANS_SINE_APPROX_ABOVE_POS)
{
TaylorGenerator tg;
TaylorGenerator::ApproximationBounds bounds;
tg.getPolynomialApproximationBounds(Kind::SINE, d / 2, bounds);
- Node eval = Rewriter::rewrite(
- bounds.d_upperPos.substitute(tg.getTaylorVariable(), c));
- return Rewriter::rewrite(
- nm->mkNode(Kind::IMPLIES,
- mkBounds(t, lb, ub),
- nm->mkNode(Kind::LEQ, nm->mkNode(Kind::SINE, t), eval)));
+ Evaluator eval(nullptr);
+ Node evalc = eval.eval(bounds.d_upperPos, {tg.getTaylorVariable()}, {c});
+ return nm->mkNode(Kind::IMPLIES,
+ mkBounds(t, lb, ub),
+ nm->mkNode(Kind::LEQ, nm->mkNode(Kind::SINE, t), evalc));
}
else if (id == PfRule::ARITH_TRANS_SINE_APPROX_BELOW_POS)
{
TaylorGenerator tg;
TaylorGenerator::ApproximationBounds bounds;
tg.getPolynomialApproximationBounds(Kind::SINE, d / 2, bounds);
- Node evall =
- Rewriter::rewrite(bounds.d_lower.substitute(tg.getTaylorVariable(), l));
- Node evalu =
- Rewriter::rewrite(bounds.d_lower.substitute(tg.getTaylorVariable(), u));
+ Evaluator eval(nullptr);
+ Node evall = eval.eval(bounds.d_lower, {tg.getTaylorVariable()}, {l});
+ Node evalu = eval.eval(bounds.d_lower, {tg.getTaylorVariable()}, {u});
Node lem = nm->mkNode(
Kind::IMPLIES,
mkBounds(t, lb, ub),
nm->mkNode(
Kind::GEQ, nm->mkNode(Kind::SINE, t), mkSecant(t, lb, ub, l, u)));
- return Rewriter::rewrite(lem);
+ return lem;
}
else if (id == PfRule::ARITH_TRANS_SINE_APPROX_BELOW_NEG)
{
TaylorGenerator tg;
TaylorGenerator::ApproximationBounds bounds;
tg.getPolynomialApproximationBounds(Kind::SINE, d / 2, bounds);
- Node eval =
- Rewriter::rewrite(bounds.d_lower.substitute(tg.getTaylorVariable(), c));
- return Rewriter::rewrite(
- nm->mkNode(Kind::IMPLIES,
- mkBounds(t, lb, ub),
- nm->mkNode(Kind::GEQ, nm->mkNode(Kind::SINE, t), eval)));
+ Evaluator eval(nullptr);
+ Node evalc = eval.eval(bounds.d_lower, {tg.getTaylorVariable()}, {c});
+ return nm->mkNode(Kind::IMPLIES,
+ mkBounds(t, lb, ub),
+ nm->mkNode(Kind::GEQ, nm->mkNode(Kind::SINE, t), evalc));
}
return Node::null();
}
e,
poly_approx));
- Trace("nl-ext-sine") << "*** Tangent plane lemma (pre-rewrite): " << lem
- << std::endl;
- lem = rewrite(lem);
Trace("nl-ext-sine") << "*** Tangent plane lemma : " << lem << std::endl;
Assert(d_data->d_model.computeAbstractModelValue(lem) == d_data->d_false);
// Figure 3 : line 9
#include "theory/arith/arith_utilities.h"
#include "theory/arith/nl/nl_model.h"
+#include "theory/evaluator.h"
#include "theory/rewriter.h"
using namespace cvc5::kind;
namespace transcendental {
TaylorGenerator::TaylorGenerator()
- : d_nm(NodeManager::currentNM()),
- d_taylor_real_fv(d_nm->mkBoundVar("x", d_nm->realType()))
+ : d_taylor_real_fv(NodeManager::currentNM()->mkBoundVar(
+ "x", NodeManager::currentNM()->realType()))
{
}
}
}
factorial *= counter;
- varpow =
- Rewriter::rewrite(nm->mkNode(Kind::MULT, d_taylor_real_fv, varpow));
+ varpow = nm->mkNode(Kind::MULT, d_taylor_real_fv, varpow);
}
- Node taylor_sum =
- Rewriter::rewrite(sum.size() == 1 ? sum[0] : nm->mkNode(Kind::PLUS, sum));
- Node taylor_rem = Rewriter::rewrite(
- nm->mkNode(Kind::DIVISION,
- varpow,
- nm->mkConst<Rational>(CONST_RATIONAL, factorial)));
+ Node taylor_sum = (sum.size() == 1 ? sum[0] : nm->mkNode(Kind::PLUS, sum));
+ Node taylor_rem = nm->mkNode(
+ Kind::DIVISION, varpow, nm->mkConst<Rational>(CONST_RATIONAL, factorial));
auto res = std::make_pair(taylor_sum, taylor_rem);
if (k == Kind::EXPONENTIAL)
{
pbounds.d_lower = taylor_sum;
- pbounds.d_upperNeg =
- Rewriter::rewrite(nm->mkNode(Kind::PLUS, taylor_sum, ru));
- pbounds.d_upperPos = Rewriter::rewrite(nm->mkNode(
+ pbounds.d_upperNeg = nm->mkNode(Kind::PLUS, taylor_sum, ru);
+ pbounds.d_upperPos = nm->mkNode(
Kind::MULT,
taylor_sum,
- nm->mkNode(
- Kind::PLUS, nm->mkConst(CONST_RATIONAL, Rational(1)), ru)));
+ nm->mkNode(Kind::PLUS, nm->mkConst(CONST_RATIONAL, Rational(1)), ru));
}
else
{
Assert(k == Kind::SINE);
- Node l = Rewriter::rewrite(nm->mkNode(Kind::MINUS, taylor_sum, ru));
- Node u = Rewriter::rewrite(nm->mkNode(Kind::PLUS, taylor_sum, ru));
+ Node l = nm->mkNode(Kind::MINUS, taylor_sum, ru);
+ Node u = nm->mkNode(Kind::PLUS, taylor_sum, ru);
pbounds.d_lower = l;
pbounds.d_upperNeg = u;
pbounds.d_upperPos = u;
std::uint64_t ds = d;
TNode ttrf = getTaylorVariable();
TNode tc = c;
+ Evaluator eval(nullptr);
do
{
success = true;
std::pair<Node, Node> taylor = getTaylor(k, n);
// check that 1-c^{n+1}/(n+1)! > 0
Node ru = taylor.second;
- Node rus = ru.substitute(ttrf, tc);
- rus = Rewriter::rewrite(rus);
+ Node rus = eval.eval(ru, {ttrf}, {tc});
Assert(rus.isConst());
if (rus.getConst<Rational>() > 1)
{
std::vector<Node> bounds;
TNode tfv = getTaylorVariable();
TNode tfs = tf[0];
+ Evaluator eval(nullptr);
for (unsigned d2 = 0; d2 < 2; d2++)
{
Node pab = (d2 == 0 ? pbounds.d_lower
// M_A( x*x { x -> t } ) = M_A( t*t )
// where M_A denotes the abstract model.
Node mtfs = model.computeAbstractModelValue(tfs);
- pab = pab.substitute(tfv, mtfs);
- pab = Rewriter::rewrite(pab);
+ pab = eval.eval(pab, {tfv}, {mtfs});
Assert(pab.isConst());
bounds.push_back(pab);
}
NlModel& model);
private:
- NodeManager* d_nm;
const Node d_taylor_real_fv;
/**
InferenceManager& im,
NlModel& m)
: EnvObj(env),
- d_tstate(im, m, env),
+ d_tstate(env, im, m),
d_expSlv(env, &d_tstate),
d_sineSlv(env, &d_tstate)
{
- d_taylor_degree = d_tstate.d_env.getOptions().arith.nlExtTfTaylorDegree;
+ d_taylor_degree = options().arith.nlExtTfTaylorDegree;
}
TranscendentalSolver::~TranscendentalSolver() {}
auto it = secant_points.find(d);
if (it == secant_points.end())
{
- it = secant_points.emplace(d, d_tstate.d_env.getUserContext()).first;
+ it = secant_points.emplace(d, userContext()).first;
}
it->second.push_back(c);
}
namespace nl {
namespace transcendental {
-TranscendentalState::TranscendentalState(InferenceManager& im,
- NlModel& model,
- Env& env)
- : d_im(im), d_model(model), d_env(env)
+TranscendentalState::TranscendentalState(Env& env,
+ InferenceManager& im,
+ NlModel& model)
+ : EnvObj(env), d_im(im), d_model(model)
{
d_true = NodeManager::currentNM()->mkConst(true);
d_false = NodeManager::currentNM()->mkConst(false);
if (d_pi.isNull())
{
d_pi = nm->mkNullaryOperator(nm->realType(), Kind::PI);
- d_pi_2 = Rewriter::rewrite(
+ d_pi_2 = rewrite(
nm->mkNode(Kind::MULT,
d_pi,
nm->mkConst(CONST_RATIONAL, Rational(1) / Rational(2))));
- d_pi_neg_2 = Rewriter::rewrite(
+ d_pi_neg_2 = rewrite(
nm->mkNode(Kind::MULT,
d_pi,
nm->mkConst(CONST_RATIONAL, Rational(-1) / Rational(2))));
- d_pi_neg = Rewriter::rewrite(nm->mkNode(
+ d_pi_neg = rewrite(nm->mkNode(
Kind::MULT, d_pi, nm->mkConst(CONST_RATIONAL, Rational(-1))));
// initialize bounds
d_pi_bound[0] =
{
NodeManager* nm = NodeManager::currentNM();
// Figure 3: S_l( x ), S_u( x ) for s = 0,1
- Node rcoeff_n = Rewriter::rewrite(nm->mkNode(Kind::MINUS, lower, upper));
+ Node rcoeff_n = rewrite(nm->mkNode(Kind::MINUS, lower, upper));
Assert(rcoeff_n.isConst());
Rational rcoeff = rcoeff_n.getConst<Rational>();
Assert(rcoeff.sgn() != 0);
Trace("nl-trans") << "\tfrom ( " << lower << " ; " << lval << " ) to ( "
<< upper << " ; " << uval << " )" << std::endl;
Trace("nl-trans") << "\t" << res << std::endl;
- Trace("nl-trans") << "\trewritten: " << Rewriter::rewrite(res) << std::endl;
+ Trace("nl-trans") << "\trewritten: " << rewrite(res) << std::endl;
return res;
}
antec_n,
nm->mkNode(
convexity == Convexity::CONVEX ? Kind::LEQ : Kind::GEQ, tf, splane));
- Trace("nl-trans-lemma") << "*** Secant plane lemma (pre-rewrite) : " << lem
- << std::endl;
- lem = Rewriter::rewrite(lem);
Trace("nl-trans-lemma") << "*** Secant plane lemma : " << lem << std::endl;
Assert(d_model.computeAbstractModelValue(lem) == d_false);
CDProof* proof = nullptr;
if (lower != center)
{
// Figure 3 : P(l), P(u), for s = 0
- Node lval = Rewriter::rewrite(
- poly_approx.substitute(d_taylor.getTaylorVariable(), lower));
+ Node lval =
+ rewrite(poly_approx.substitute(d_taylor.getTaylorVariable(), lower));
Node splane = mkSecantPlane(tf[0], lower, center, lval, cval);
NlLemma nlem = mkSecantLemma(
lower, center, lval, cval, csign, convexity, tf, splane, actual_d);
if (center != upper)
{
// Figure 3 : P(l), P(u), for s = 1
- Node uval = Rewriter::rewrite(
- poly_approx.substitute(d_taylor.getTaylorVariable(), upper));
+ Node uval =
+ rewrite(poly_approx.substitute(d_taylor.getTaylorVariable(), upper));
Node splane = mkSecantPlane(tf[0], center, upper, cval, uval);
NlLemma nlem = mkSecantLemma(
center, upper, cval, uval, csign, convexity, tf, splane, actual_d);
* This includes common lookups and caches as well as generic utilities for
* secant plane lemmas and taylor approximations.
*/
-struct TranscendentalState
+struct TranscendentalState : protected EnvObj
{
- TranscendentalState(InferenceManager& im, NlModel& model, Env& env);
+ TranscendentalState(Env& env, InferenceManager& im, NlModel& model);
/**
* Checks whether proofs are enabled.
InferenceManager& d_im;
/** Reference to the non-linear model object */
NlModel& d_model;
- /** Reference to the environment */
- Env& d_env;
/** Utility to compute taylor approximations */
TaylorGenerator d_taylor;
/**
results[currNode] = EvalResult(res);
break;
}
+ case kind::DIVISION:
+ case kind::DIVISION_TOTAL:
+ {
+ Rational res = results[currNode[0]].d_rat;
+ bool divbyzero = false;
+ for (size_t i = 1, end = currNode.getNumChildren(); i < end; i++)
+ {
+ if (results[currNode[i]].d_rat.isZero())
+ {
+ Trace("evaluator")
+ << "Division by zero not supported" << std::endl;
+ divbyzero = true;
+ results[currNode] = EvalResult();
+ break;
+ }
+ res = res / results[currNode[i]].d_rat;
+ }
+ if (!divbyzero)
+ {
+ results[currNode] = EvalResult(res);
+ }
+ break;
+ }
case kind::GEQ:
{