Arith has a normal form for literals, which the rewriter computes.
Nonetheless, arith sometimes gets (and ultimately propagates) non-normal
literals. It normalizes them internally and goes about its business.
However, when asked for an explanation, it must prove the non-normal
literal, rather than the normal one.
Also includes a regression for the bug, courtesy of Andy.
Co-authored-by: Andrew Reynolds andrew-reynolds@uiowa.edu
return externalExplain(b, AssertionOrderSentinel);
}
-TrustNode Constraint::externalExplainForPropagation() const
+TrustNode Constraint::externalExplainForPropagation(TNode lit) const
{
Assert(hasProof());
Assert(!isAssumption());
Node n = safeConstructNary(nb);
if (d_database->isProofEnabled())
{
+ // Check that the literal we're explaining via this constraint actually
+ // matches the constraint's canonical literal.
+ Assert(Rewriter::rewrite(lit) == getLiteral());
std::vector<Node> assumptions;
if (n.getKind() == Kind::AND)
{
{
assumptions.push_back(n);
}
- if (getProofLiteral() != getLiteral())
+ if (getProofLiteral() != lit)
{
pfFromAssumptions = d_database->d_pnm->mkNode(
- PfRule::MACRO_SR_PRED_TRANSFORM, {pfFromAssumptions}, {getLiteral()});
+ PfRule::MACRO_SR_PRED_TRANSFORM, {pfFromAssumptions}, {lit});
}
auto pf = d_database->d_pnm->mkScope(pfFromAssumptions, assumptions);
return d_database->d_pfGen->mkTrustedPropagation(
- getLiteral(), safeConstructNary(Kind::AND, assumptions), pf);
+ lit, safeConstructNary(Kind::AND, assumptions), pf);
}
else
{
- return TrustNode::mkTrustPropExp(getLiteral(), n);
+ return TrustNode::mkTrustPropExp(lit, n);
}
}
* hasEqualityEngineProof().
*
* All return conjuncts were asserted before this constraint.
+ *
+ * Requires the given node to rewrite to the canonical literal for this
+ * constraint.
+ *
+ * @params n the literal to prove
+ * n must rewrite to the constraint's canonical literal
+ *
+ * @returns a trust node of the form:
+ * (=> explanation n)
*/
- TrustNode externalExplainForPropagation() const;
+ TrustNode externalExplainForPropagation(TNode n) const;
/**
* Explain the constraint and its negation in terms of assertions.
TrustNode exp;
if(c != NullConstraint){
Assert(!c->isAssumption());
- exp = c->externalExplainForPropagation();
+ exp = c->externalExplainForPropagation(n);
Debug("arith::explain") << "constraint explanation" << n << ":" << exp << endl;
}else if(d_assertionsThatDoNotMatchTheirLiterals.find(n) != d_assertionsThatDoNotMatchTheirLiterals.end()){
c = d_assertionsThatDoNotMatchTheirLiterals[n];
if(!c->isAssumption()){
- exp = c->externalExplainForPropagation();
+ exp = c->externalExplainForPropagation(n);
Debug("arith::explain") << "assertions explanation" << n << ":" << exp << endl;
}else{
Debug("arith::explain") << "this is a strange mismatch" << n << endl;
regress0/arith/mod-simp.smt2
regress0/arith/mod.01.smt2
regress0/arith/mult.01.smt2
+ regress0/arith/non-normal.smt2
regress0/arr1.smt2
regress0/arr1.smtv1.smt2
regress0/arr2.smtv1.smt2
--- /dev/null
+; COMMAND-LINE: --proof-new-eager-checking
+; EXPECT: sat
+(set-logic QF_UFLRA)
+(declare-fun v1 () Real)
+(declare-fun v2 () Real)
+(declare-fun f1 (Real) Real)
+(declare-fun f0 (Real Real) Real)
+(declare-fun p0 (Real Real) Bool)
+(assert
+(ite
+ (or (= 0.0 v2) (> 1 (ite (< (- (- v1)) 1.0) 1.0 (ite (p0 0.0 v1) 0.0 1.0))))
+ (= 0.0 (ite (= 1.0 (f1 0.0)) 0.0 (f1 1.0)))
+ (and
+ (= 1.0 (ite (= 0.0 (f1 1.0)) v2 (- 1.0)))
+ (=> (not (p0 0.0 (- (- (- v2))))) (= 1.0 (ite (= 1.0 v2) (ite (= 0 (f0 0.0 1.0)) 1.0 (f0 0.0 (- v2 (- v1)))) 0.0))))))
+(check-sat)