case kind::MULT:
case kind::NONLINEAR_MULT: return preRewriteMult(t);
case kind::IAND: return RewriteResponse(REWRITE_DONE, t);
+ case kind::POW2: return RewriteResponse(REWRITE_DONE, t);
case kind::EXPONENTIAL:
case kind::SINE:
case kind::COSINE:
case kind::MULT:
case kind::NONLINEAR_MULT: return postRewriteMult(t);
case kind::IAND: return postRewriteIAnd(t);
+ case kind::POW2: return postRewritePow2(t);
case kind::EXPONENTIAL:
case kind::SINE:
case kind::COSINE:
return RewriteResponse(REWRITE_DONE, res.getNode());
}
+RewriteResponse ArithRewriter::postRewritePow2(TNode t)
+{
+ Assert(t.getKind() == kind::POW2);
+ NodeManager* nm = NodeManager::currentNM();
+ // if constant, we eliminate
+ if (t[0].isConst())
+ {
+ // pow2 is only supported for integers
+ Assert(t[0].getType().isInteger());
+ Integer i = t[0].getConst<Rational>().getNumerator();
+ unsigned long k = i.getUnsignedLong();
+ Node ret = nm->mkConst<Rational>(Rational(Integer(2).pow(k), Integer(1)));
+ return RewriteResponse(REWRITE_DONE, ret);
+ }
+ return RewriteResponse(REWRITE_DONE, t);
+}
+
RewriteResponse ArithRewriter::postRewriteIAnd(TNode t)
{
Assert(t.getKind() == kind::IAND);
Trace("pow2") << "We have " << d_pow2s.size() << " pow2 terms." << std::endl;
}
-void Pow2Solver::checkInitialRefine() {}
+void Pow2Solver::checkInitialRefine()
+{
+ Trace("pow2-check") << "Pow2Solver::checkInitialRefine" << std::endl;
+ NodeManager* nm = NodeManager::currentNM();
+ for (const Node& i : d_pow2s)
+ {
+ if (d_initRefine.find(i) != d_initRefine.end())
+ {
+ // already sent initial axioms for i in this user context
+ continue;
+ }
+ d_initRefine.insert(i);
+ // initial refinement lemmas
+ std::vector<Node> conj;
+ // x>=0 -> x < pow2(x)
+ Node xgeq0 = nm->mkNode(LEQ, d_zero, i[0]);
+ Node xltpow2x = nm->mkNode(LT, i[0], i);
+ conj.push_back(nm->mkNode(IMPLIES, xgeq0, xltpow2x));
+ Node lem = nm->mkAnd(conj);
+ Trace("pow2-lemma") << "Pow2Solver::Lemma: " << lem << " ; INIT_REFINE"
+ << std::endl;
+ d_im.addPendingLemma(lem, InferenceId::ARITH_NL_POW2_INIT_REFINE);
+ }
+}
-void Pow2Solver::checkFullRefine() {}
+void Pow2Solver::checkFullRefine()
+{
+ Trace("pow2-check") << "Pow2Solver::checkFullRefine";
+ Trace("pow2-check") << "pow2 terms: " << std::endl;
+ for (const Node& i : d_pow2s)
+ {
+ Node valPow2x = d_model.computeAbstractModelValue(i);
+ Node valPow2xC = d_model.computeConcreteModelValue(i);
+ if (Trace.isOn("pow2-check"))
+ {
+ Node x = i[0];
+ Node valX = d_model.computeConcreteModelValue(x);
-Node Pow2Solver::valueBasedLemma(Node i) { return Node(); }
+ Trace("pow2-check") << "* " << i << ", value = " << valPow2x << std::endl;
+ Trace("pow2-check") << " actual (" << valX << ", "
+ << ") = " << valPow2xC << std::endl;
+ }
+ if (valPow2x == valPow2xC)
+ {
+ Trace("pow2-check") << "...already correct" << std::endl;
+ continue;
+ }
+
+ // Place holder for additional lemma schemas
+ //
+ // End of additional lemma schemas
+
+ // this is the most naive model-based schema based on model values
+ Node lem = valueBasedLemma(i);
+ Trace("pow2-lemma") << "Pow2Solver::Lemma: " << lem << " ; VALUE_REFINE"
+ << std::endl;
+ // send the value lemma
+ d_im.addPendingLemma(
+ lem, InferenceId::ARITH_NL_POW2_VALUE_REFINE, nullptr, true);
+ }
+}
+Node Pow2Solver::valueBasedLemma(Node i)
+{
+ Assert(i.getKind() == POW2);
+ Node x = i[0];
+
+ Node valX = d_model.computeConcreteModelValue(x);
+
+ NodeManager* nm = NodeManager::currentNM();
+ Node valC = nm->mkNode(POW2, valX);
+ valC = Rewriter::rewrite(valC);
+
+ Node lem = nm->mkNode(IMPLIES, x.eqNode(valX), i.eqNode(valC));
+ return lem;
+}
} // namespace nl
} // namespace arith