return false;
}
-NlSolver::NlSolver(TheoryArith& containing, NlModel& model)
- : d_containing(containing),
+NlSolver::NlSolver(InferenceManager& im, ArithState& astate, NlModel& model)
+ : d_im(im),
+ d_astate(astate),
d_model(model),
d_cdb(d_mdb),
- d_zero_split(containing.getUserContext())
+ d_zero_split(d_astate.getUserContext())
{
NodeManager* nm = NodeManager::currentNM();
d_true = nm->mkConst(true);
}
}
-std::vector<NlLemma> NlSolver::checkSplitZero()
+void NlSolver::checkSplitZero()
{
- std::vector<NlLemma> lemmas;
for (unsigned i = 0; i < d_ms_vars.size(); i++)
{
Node v = d_ms_vars[i];
{
Node eq = v.eqNode(d_zero);
eq = Rewriter::rewrite(eq);
- Node literal = d_containing.getValuation().ensureLiteral(eq);
- d_containing.getOutputChannel().requirePhase(literal, true);
- lemmas.emplace_back(literal.orNode(literal.negate()),
- InferenceId::NL_SPLIT_ZERO);
+ d_im.addPendingPhaseRequirement(eq, true);
+ Node lem = eq.orNode(eq.negate());
+ d_im.addPendingArithLemma(lem, InferenceId::NL_SPLIT_ZERO);
}
}
- return lemmas;
}
void NlSolver::assignOrderIds(std::vector<Node>& vars,
Node a,
unsigned a_index,
int status,
- std::vector<Node>& exp,
- std::vector<NlLemma>& lem)
+ std::vector<Node>& exp)
{
Trace("nl-ext-debug") << "Process " << a << " at index " << a_index
<< ", status is " << status << std::endl;
{
Node lemma =
safeConstructNary(AND, exp).impNode(mkLit(oa, d_zero, status * 2));
- lem.emplace_back(lemma, InferenceId::NL_SIGN);
+ d_im.addPendingArithLemma(lemma, InferenceId::NL_SIGN);
}
return status;
}
if (mvaoa.getConst<Rational>().sgn() != 0)
{
Node lemma = av.eqNode(d_zero).impNode(oa.eqNode(d_zero));
- lem.emplace_back(lemma, InferenceId::NL_SIGN);
+ d_im.addPendingArithLemma(lemma, InferenceId::NL_SIGN);
}
return 0;
}
if (aexp % 2 == 0)
{
exp.push_back(av.eqNode(d_zero).negate());
- return compareSign(oa, a, a_index + 1, status, exp, lem);
+ return compareSign(oa, a, a_index + 1, status, exp);
}
exp.push_back(nm->mkNode(sgn == 1 ? GT : LT, av, d_zero));
- return compareSign(oa, a, a_index + 1, status * sgn, exp, lem);
+ return compareSign(oa, a, a_index + 1, status * sgn, exp);
}
bool NlSolver::compareMonomial(
Node b,
NodeMultiset& b_exp_proc,
std::vector<Node>& exp,
- std::vector<NlLemma>& lem,
+ std::vector<ArithLemma>& lem,
std::map<int, std::map<Node, std::map<Node, Node> > >& cmp_infers)
{
Trace("nl-ext-comp-debug")
NodeMultiset& b_exp_proc,
int status,
std::vector<Node>& exp,
- std::vector<NlLemma>& lem,
+ std::vector<ArithLemma>& lem,
std::map<int, std::map<Node, std::map<Node, Node> > >& cmp_infers)
{
Trace("nl-ext-comp-debug")
Node clem = nm->mkNode(
IMPLIES, safeConstructNary(AND, exp), mkLit(oa, ob, status, true));
Trace("nl-ext-comp-lemma") << "comparison lemma : " << clem << std::endl;
- lem.emplace_back(clem, InferenceId::NL_COMPARISON);
+ lem.emplace_back(clem, LemmaProperty::NONE, nullptr, InferenceId::NL_COMPARISON);
cmp_infers[status][oa][ob] = clem;
}
return true;
return false;
}
-std::vector<NlLemma> NlSolver::checkMonomialSign()
+void NlSolver::checkMonomialSign()
{
- std::vector<NlLemma> lemmas;
std::map<Node, int> signs;
Trace("nl-ext") << "Get monomial sign lemmas..." << std::endl;
for (unsigned j = 0; j < d_ms.size(); j++)
}
if (d_m_nconst_factor.find(a) == d_m_nconst_factor.end())
{
- signs[a] = compareSign(a, a, 0, 1, exp, lemmas);
+ signs[a] = compareSign(a, a, 0, 1, exp);
if (signs[a] == 0)
{
d_ms_proc[a] = true;
}
}
}
- return lemmas;
}
-std::vector<NlLemma> NlSolver::checkMonomialMagnitude(unsigned c)
+void NlSolver::checkMonomialMagnitude(unsigned c)
{
// ensure information is setup
if (c == 0)
}
unsigned r = 1;
- std::vector<NlLemma> lemmas;
+ std::vector<ArithLemma> lemmas;
// if (x,y,L) in cmp_infers, then x > y inferred as conclusion of L
// in lemmas
std::map<int, std::map<Node, std::map<Node, Node> > > cmp_infers;
}
}
}
- std::vector<NlLemma> nr_lemmas;
for (unsigned i = 0; i < lemmas.size(); i++)
{
if (r_lemmas.find(lemmas[i].d_node) == r_lemmas.end())
{
- nr_lemmas.push_back(lemmas[i]);
+ d_im.addPendingArithLemma(lemmas[i]);
}
}
// could only take maximal lower/minimial lower bounds?
-
- Trace("nl-ext-comp") << nr_lemmas.size() << " / " << lemmas.size()
- << " were non-redundant." << std::endl;
- return nr_lemmas;
}
-std::vector<NlLemma> NlSolver::checkTangentPlanes()
+void NlSolver::checkTangentPlanes(bool asWaitingLemmas)
{
- std::vector<NlLemma> lemmas;
Trace("nl-ext") << "Get monomial tangent plane lemmas..." << std::endl;
NodeManager* nm = NodeManager::currentNM();
const std::map<Node, std::vector<Node> >& ccMap =
tplaneConj.push_back(lb_reverse2);
Node tlem = nm->mkNode(AND, tplaneConj);
- lemmas.emplace_back(tlem, InferenceId::NL_TANGENT_PLANE);
+ d_im.addPendingArithLemma(
+ tlem, InferenceId::NL_TANGENT_PLANE, asWaitingLemmas);
}
}
}
}
}
- Trace("nl-ext") << "...trying " << lemmas.size() << " tangent plane lemmas..."
- << std::endl;
- return lemmas;
}
-std::vector<NlLemma> NlSolver::checkMonomialInferBounds(
- std::vector<NlLemma>& nt_lemmas,
+void NlSolver::checkMonomialInferBounds(
const std::vector<Node>& asserts,
const std::vector<Node>& false_asserts)
{
const std::map<Node, std::map<Node, ConstraintInfo> >& cim =
d_cdb.getConstraints();
- std::vector<NlLemma> lemmas;
NodeManager* nm = NodeManager::currentNM();
// register constraints
Trace("nl-ext-debug") << "Register bound constraints..." << std::endl;
<< " (pre-rewrite : " << pr_iblem << ")" << std::endl;
// Trace("nl-ext-bound-lemma") << " intro new
// monomials = " << introNewTerms << std::endl;
- if (!introNewTerms)
- {
- lemmas.emplace_back(iblem, InferenceId::NL_INFER_BOUNDS);
- }
- else
- {
- nt_lemmas.emplace_back(iblem, InferenceId::NL_INFER_BOUNDS_NT);
- }
+ d_im.addPendingArithLemma(iblem, InferenceId::NL_INFER_BOUNDS_NT, introNewTerms);
}
}
}
}
}
- return lemmas;
}
-std::vector<NlLemma> NlSolver::checkFactoring(
- const std::vector<Node>& asserts, const std::vector<Node>& false_asserts)
+void NlSolver::checkFactoring(const std::vector<Node>& asserts, const std::vector<Node>& false_asserts)
{
- std::vector<NlLemma> lemmas;
NodeManager* nm = NodeManager::currentNM();
Trace("nl-ext") << "Get factoring lemmas..." << std::endl;
for (const Node& lit : asserts)
sum = Rewriter::rewrite(sum);
Trace("nl-ext-factor")
<< "* Factored sum for " << x << " : " << sum << std::endl;
- Node kf = getFactorSkolem(sum, lemmas);
+ Node kf = getFactorSkolem(sum);
std::vector<Node> poly;
poly.push_back(nm->mkNode(MULT, x, kf));
std::map<Node, std::vector<Node> >::iterator itfo =
lemma_disj.push_back(conc_lit);
Node flem = nm->mkNode(OR, lemma_disj);
Trace("nl-ext-factor") << "...lemma is " << flem << std::endl;
- lemmas.emplace_back(flem, InferenceId::NL_FACTOR);
+ d_im.addPendingArithLemma(flem, InferenceId::NL_FACTOR);
}
}
}
}
- return lemmas;
}
-Node NlSolver::getFactorSkolem(Node n, std::vector<NlLemma>& lemmas)
+Node NlSolver::getFactorSkolem(Node n)
{
std::map<Node, Node>::iterator itf = d_factor_skolem.find(n);
if (itf == d_factor_skolem.end())
NodeManager* nm = NodeManager::currentNM();
Node k = nm->mkSkolem("kf", n.getType());
Node k_eq = Rewriter::rewrite(k.eqNode(n));
- lemmas.push_back(k_eq);
+ d_im.addPendingArithLemma(k_eq, InferenceId::NL_FACTOR);
d_factor_skolem[n] = k;
return k;
}
return itf->second;
}
-std::vector<NlLemma> NlSolver::checkMonomialInferResBounds()
+void NlSolver::checkMonomialInferResBounds()
{
- std::vector<NlLemma> lemmas;
NodeManager* nm = NodeManager::currentNM();
Trace("nl-ext") << "Get monomial resolution inferred bound lemmas..."
<< std::endl;
rblem = Rewriter::rewrite(rblem);
Trace("nl-ext-rbound-lemma")
<< "Resolution bound lemma : " << rblem << std::endl;
- lemmas.emplace_back(rblem, InferenceId::NL_RES_INFER_BOUNDS);
+ d_im.addPendingArithLemma(rblem, InferenceId::NL_RES_INFER_BOUNDS);
}
}
exp.pop_back();
}
}
}
- return lemmas;
}
} // namespace nl
typedef context::CDHashSet<Node, NodeHashFunction> NodeSet;
public:
- NlSolver(TheoryArith& containing, NlModel& model);
+ NlSolver(InferenceManager& im, ArithState& astate, NlModel& model);
~NlSolver();
/** init last call
* t = 0 V t != 0
* where t is a term that exists in the current context.
*/
- std::vector<NlLemma> checkSplitZero();
+ void checkSplitZero();
/** check monomial sign
*
* x < 0 => x*y*y < 0
* x = 0 => x*y*z = 0
*/
- std::vector<NlLemma> checkMonomialSign();
+ void checkMonomialSign();
/** check monomial magnitude
*
* against 1, 1 : compare non-linear monomials against variables, 2 : compare
* non-linear monomials against other non-linear monomials.
*/
- std::vector<NlLemma> checkMonomialMagnitude(unsigned c);
+ void checkMonomialMagnitude(unsigned c);
/** check monomial inferred bounds
*
* ...where (y > z + w) and x*y are a constraint and term
* that occur in the current context.
*/
- std::vector<NlLemma> checkMonomialInferBounds(
- std::vector<NlLemma>& nt_lemmas,
+ void checkMonomialInferBounds(
const std::vector<Node>& asserts,
const std::vector<Node>& false_asserts);
* ...where k is fresh and x*z + y*z > t is a
* constraint that occurs in the current context.
*/
- std::vector<NlLemma> checkFactoring(const std::vector<Node>& asserts,
+ void checkFactoring(const std::vector<Node>& asserts,
const std::vector<Node>& false_asserts);
/** check monomial infer resolution bounds
* ...where s <= x*z and x*y <= t are constraints
* that occur in the current context.
*/
- std::vector<NlLemma> checkMonomialInferResBounds();
+ void checkMonomialInferResBounds();
/** check tangent planes
*
* ( ( x>2 ^ y>5) ^ (x<2 ^ y<5) ) => x*y > 5*x + 2*y - 10
* ( ( x>2 ^ y<5) ^ (x<2 ^ y>5) ) => x*y < 5*x + 2*y - 10
*/
- std::vector<NlLemma> checkTangentPlanes();
+ void checkTangentPlanes(bool asWaitingLemmas);
//-------------------------------------------- end lemma schemas
private:
- // The theory of arithmetic containing this extension.
- TheoryArith& d_containing;
+ /** The inference manager that we push conflicts and lemmas to. */
+ InferenceManager& d_im;
+ /** Reference to the state. */
+ ArithState& d_astate;
/** Reference to the non-linear model object */
NlModel& d_model;
/** commonly used terms */
Node a,
unsigned a_index,
int status,
- std::vector<Node>& exp,
- std::vector<NlLemma>& lem);
+ std::vector<Node>& exp);
/** compare monomials a and b
*
* Initially, a call to this function is such that :
Node b,
NodeMultiset& b_exp_proc,
std::vector<Node>& exp,
- std::vector<NlLemma>& lem,
+ std::vector<ArithLemma>& lem,
std::map<int, std::map<Node, std::map<Node, Node> > >& cmp_infers);
/** helper function for above
*
NodeMultiset& b_exp_proc,
int status,
std::vector<Node>& exp,
- std::vector<NlLemma>& lem,
+ std::vector<ArithLemma>& lem,
std::map<int, std::map<Node, std::map<Node, Node> > >& cmp_infers);
/** Get factor skolem for n, add resulting lemmas to lemmas */
- Node getFactorSkolem(Node n, std::vector<NlLemma>& lemmas);
+ Node getFactorSkolem(Node n);
}; /* class NlSolver */
} // namespace nl
containing.getOutputChannel()),
d_model(containing.getSatContext()),
d_trSlv(d_im, d_model),
- d_nlSlv(containing, d_model),
+ d_nlSlv(d_im, state, d_model),
d_cadSlv(d_im, d_model),
d_icpSlv(d_im),
d_iandSlv(d_im, state, d_model),
if (options::nlExt() && options::nlExtSplitZero())
{
Trace("nl-ext") << "Get zero split lemmas..." << std::endl;
- lemmas = d_nlSlv.checkSplitZero();
- filterLemmas(lemmas, lems);
- if (!lems.empty())
+ d_nlSlv.checkSplitZero();
+ if (d_im.hasUsed())
{
- Trace("nl-ext") << " ...finished with " << lems.size() << " new lemmas."
+ Trace("nl-ext") << " ...finished with " << d_im.numPendingLemmas() << " new lemmas."
<< std::endl;
- return lems.size();
+ return d_im.numPendingLemmas();
}
}
if (options::nlExt())
{
//---------------------------------lemmas based on sign (comparison to zero)
- lemmas = d_nlSlv.checkMonomialSign();
- filterLemmas(lemmas, lems);
- if (!lems.empty())
+ d_nlSlv.checkMonomialSign();
+ if (d_im.hasUsed())
{
- Trace("nl-ext") << " ...finished with " << lems.size() << " new lemmas."
+ Trace("nl-ext") << " ...finished with " << d_im.numPendingLemmas() << " new lemmas."
<< std::endl;
- return lems.size();
+ return d_im.numPendingLemmas();
}
//-----------------------------------monotonicity of transdental functions
for (unsigned c = 0; c < 3; c++)
{
// c is effort level
- lemmas = d_nlSlv.checkMonomialMagnitude(c);
- unsigned nlem = lemmas.size();
- filterLemmas(lemmas, lems);
- if (!lems.empty())
+ d_nlSlv.checkMonomialMagnitude(c);
+ if (d_im.hasUsed())
{
- Trace("nl-ext") << " ...finished with " << lems.size()
- << " new lemmas (out of possible " << nlem << ")."
- << std::endl;
- return lems.size();
+ Trace("nl-ext") << " ...finished with " << d_im.numPendingLemmas()
+ << " new lemmas." << std::endl;
+ return d_im.numPendingLemmas();
}
}
//-----------------------------------inferred bounds lemmas
// e.g. x >= t => y*x >= y*t
- std::vector<NlLemma> nt_lemmas;
- lemmas =
- d_nlSlv.checkMonomialInferBounds(nt_lemmas, assertions, false_asserts);
- // Trace("nl-ext") << "Bound lemmas : " << lemmas.size() << ", " <<
- // nt_lemmas.size() << std::endl; prioritize lemmas that do not
- // introduce new monomials
- filterLemmas(lemmas, lems);
+ d_nlSlv.checkMonomialInferBounds(assertions, false_asserts);
+ Trace("nl-ext") << "Bound lemmas : " << d_im.numPendingLemmas() << ", " << d_im.numWaitingLemmas() << std::endl;
+ // prioritize lemmas that do not introduce new monomials
if (options::nlExtTangentPlanes()
&& options::nlExtTangentPlanesInterleave())
{
- lemmas = d_nlSlv.checkTangentPlanes();
- filterLemmas(lemmas, lems);
+ d_nlSlv.checkTangentPlanes(false);
}
- if (!lems.empty())
+ if (d_im.hasUsed())
{
- Trace("nl-ext") << " ...finished with " << lems.size() << " new lemmas."
+ Trace("nl-ext") << " ...finished with " << d_im.numPendingLemmas() << " new lemmas."
<< std::endl;
- return lems.size();
+ return d_im.numPendingLemmas();
}
// from inferred bound inferences : now do ones that introduce new terms
- filterLemmas(nt_lemmas, lems);
- if (!lems.empty())
+ d_im.flushWaitingLemmas();
+ if (d_im.hasUsed())
{
- Trace("nl-ext") << " ...finished with " << lems.size()
+ Trace("nl-ext") << " ...finished with " << d_im.numPendingLemmas()
<< " new (monomial-introducing) lemmas." << std::endl;
- return lems.size();
+ return d_im.numPendingLemmas();
}
//------------------------------------factoring lemmas
// x*y + x*z >= t => exists k. k = y + z ^ x*k >= t
if (options::nlExtFactor())
{
- lemmas = d_nlSlv.checkFactoring(assertions, false_asserts);
- filterLemmas(lemmas, lems);
- if (!lems.empty())
+ d_nlSlv.checkFactoring(assertions, false_asserts);
+ if (d_im.hasUsed())
{
- Trace("nl-ext") << " ...finished with " << lems.size()
+ Trace("nl-ext") << " ...finished with " << d_im.numPendingLemmas()
<< " new lemmas." << std::endl;
- return lems.size();
+ return d_im.numPendingLemmas();
}
}
// e.g. ( y>=0 ^ s <= x*z ^ x*y <= t ) => y*s <= z*t
if (options::nlExtResBound())
{
- lemmas = d_nlSlv.checkMonomialInferResBounds();
- filterLemmas(lemmas, lems);
- if (!lems.empty())
+ d_nlSlv.checkMonomialInferResBounds();
+ if (d_im.hasUsed())
{
- Trace("nl-ext") << " ...finished with " << lems.size()
+ Trace("nl-ext") << " ...finished with " << d_im.numPendingLemmas()
<< " new lemmas." << std::endl;
- return lems.size();
+ return d_im.numPendingLemmas();
}
}
if (options::nlExtTangentPlanes()
&& !options::nlExtTangentPlanesInterleave())
{
- lemmas = d_nlSlv.checkTangentPlanes();
- filterLemmas(lemmas, wlems);
+ d_nlSlv.checkTangentPlanes(true);
}
if (options::nlExtTfTangentPlanes())
{
checkLastCall(assertions, false_asserts, xts, mlems, wlems);
if (!mlems.empty() || d_im.hasSentLemma() || d_im.hasPendingLemma())
{
+ d_im.clearWaitingLemmas();
return true;
}
}
filterLemmas(lemmas, mlems);
if (!mlems.empty() || d_im.hasPendingLemma())
{
+ d_im.clearWaitingLemmas();
return true;
}
}
d_containing.getOutputChannel().setIncomplete();
}
}
+ d_im.clearWaitingLemmas();
} while (needsRecheck);
// did not add lemmas