// we look at the node after the equality sequence. If it needs a, we go for a=a; and if it needs
// b, we go for b=b. If there is no following node, we look at the goal of the transitivity proof,
// and use it to determine which option we need.
+
if(n2.getKind() == kind::EQUAL || n2.getKind() == kind::IFF) {
if (((n1[0] == n2[0]) && (n1[1] == n2[1])) || ((n1[0] == n2[1]) && (n1[1] == n2[0]))) {
// We are in a sequence of identical equalities
// inner index != outer index
// t3 is the outer index
-
Assert(pf->d_children.size() == 1);
std::stringstream ss;
Node subproof = toStreamRecLFSC(ss, tp, pf->d_children[0], tb + 1, map);
tp->printTerm(t4.toExpr(), out, map);
out << " ";
+
Debug("pf::array") << "pf->d_children[0]->d_node is: " << pf->d_children[0]->d_node
<< ". t3 is: " << t3 << std::endl
<< "subproof is: " << subproof << std::endl;
Debug("pf::array") << "Subproof is: " << ss.str() << std::endl;
- if (subproof[0][1] == t3) {
- Debug("pf::array") << "Dont need symmetry!" << std::endl;
- out << ss.str();
+ // The subproof needs to show that t2 != t3. This can either be a direct disequality,
+ // or, if (wlog) t2 is constant, it can show that t3 is equal to another constant.
+ if (subproof.getKind() == kind::NOT) {
+ // The subproof is for t2 != t3 (or t3 != t2)
+ if (subproof[0][1] == t3) {
+ Debug("pf::array") << "Dont need symmetry!" << std::endl;
+ out << ss.str();
+ } else {
+ Debug("pf::array") << "Need symmetry!" << std::endl;
+ out << "(negsymm _ _ _ " << ss.str() << ")";
+ }
} else {
- Debug("pf::array") << "Need symmetry!" << std::endl;
- out << "(negsymm _ _ _ " << ss.str() << ")";
+ // Either t2 or t3 is a constant.
+ Assert(subproof.getKind() == kind::EQUAL);
+ Assert(subproof[0].isConst() || subproof[1].isConst());
+ Assert(t2.isConst() || t3.isConst());
+ Assert(!(t2.isConst() && t3.isConst()));
+
+ bool t2IsConst = t2.isConst();
+ if (subproof[0].isConst()) {
+ if (t2IsConst) {
+ // (t3 == subproof[1]) == subproof[0] != t2
+ // goal is t2 != t3
+ // subproof already shows constant = t3
+ Assert(t3 == subproof[1]);
+ out << "(negtrans _ _ _ _ ";
+ tp->printConstantDisequalityProof(out, t2.toExpr(), subproof[0].toExpr());
+ out << " ";
+ out << ss.str();
+ out << ")";
+ } else {
+ Assert(t2 == subproof[1]);
+ out << "(negsymm _ _ _ ";
+ out << "(negtrans _ _ _ _ ";
+ tp->printConstantDisequalityProof(out, t3.toExpr(), subproof[0].toExpr());
+ out << " ";
+ out << ss.str();
+ out << "))";
+ }
+ } else {
+ if (t2IsConst) {
+ // (t3 == subproof[0]) == subproof[1] != t2
+ // goal is t2 != t3
+ // subproof already shows constant = t3
+ Assert(t3 == subproof[0]);
+ out << "(negtrans _ _ _ _ ";
+ tp->printConstantDisequalityProof(out, t2.toExpr(), subproof[1].toExpr());
+ out << " ";
+ out << "(symm _ _ _ " << ss.str() << ")";
+ out << ")";
+ } else {
+ Assert(t2 == subproof[0]);
+ out << "(negsymm _ _ _ ";
+ out << "(negtrans _ _ _ _ ";
+ tp->printConstantDisequalityProof(out, t3.toExpr(), subproof[1].toExpr());
+ out << " ";
+ out << "(symm _ _ _ " << ss.str() << ")";
+ out << "))";
+ }
+ }
}
out << ")";
-
return ret;
} else {
Debug("pf::array") << "In the case of NEGATIVE ROW" << std::endl;
}
void TheoryProofEngine::registerTerm(Expr term) {
- Debug("pf::tp") << "TheoryProofEngine::registerTerm: registering term: " << term << std::endl;
+ Debug("pf::tp::register") << "TheoryProofEngine::registerTerm: registering term: " << term << std::endl;
if (d_registrationCache.count(term)) {
return;
}
- Debug("pf::tp") << "TheoryProofEngine::registerTerm: registering NEW term: " << term << std::endl;
+ Debug("pf::tp::register") << "TheoryProofEngine::registerTerm: registering NEW term: " << term << std::endl;
theory::TheoryId theory_id = theory::Theory::theoryOf(term);
- Debug("pf::tp") << "Term's theory( " << term << " ) = " << theory_id << std::endl;
+ Debug("pf::tp::register") << "Term's theory( " << term << " ) = " << theory_id << std::endl;
// don't need to register boolean terms
if (theory_id == theory::THEORY_BUILTIN ||
// A special case: the array theory needs to know of every skolem, even if
// it belongs to another theory (e.g., a BV skolem)
if (ProofManager::getSkolemizationManager()->isSkolem(term) && theory_id != theory::THEORY_ARRAY) {
- Debug("pf::tp") << "TheoryProofEngine::registerTerm: Special case: registering a non-array skolem: " << term << std::endl;
+ Debug("pf::tp::register") << "TheoryProofEngine::registerTerm: registering a non-array skolem: " << term << std::endl;
getTheoryProof(theory::THEORY_ARRAY)->registerTerm(term);
}
clause_expr[k] = missingAssertion->toExpr();
std::ostringstream rewritten;
- rewritten << "(or_elim_1 _ _ ";
- rewritten << "(not_not_intro _ ";
- rewritten << pm->getLitName(explanation);
- rewritten << ") (iff_elim_1 _ _ ";
- rewritten << d_assertionToRewrite[missingAssertion->negate()];
- rewritten << "))";
+
+ if (missingAssertion->getKind() == kind::NOT && (*missingAssertion)[0].toExpr() == utils::mkFalse()) {
+ rewritten << "(or_elim_2 _ _ ";
+ rewritten << "(not_not_intro _ ";
+ rewritten << pm->getLitName(explanation);
+ rewritten << ") (iff_elim_2 _ _ ";
+ rewritten << d_assertionToRewrite[missingAssertion->negate()];
+ rewritten << "))";
+ }
+ else {
+ rewritten << "(or_elim_1 _ _ ";
+ rewritten << "(not_not_intro _ ";
+ rewritten << pm->getLitName(explanation);
+ rewritten << ") (iff_elim_1 _ _ ";
+ rewritten << d_assertionToRewrite[missingAssertion->negate()];
+ rewritten << "))";
+ }
Debug("pf::tp") << "Setting a rewrite filter for this proof: " << std::endl
<< pm->getLitName(*missingAssertion) << " --> " << rewritten.str()
+ << ", explanation = " << explanation
<< std::endl << std::endl;
pm->addRewriteFilter(pm->getLitName(*missingAssertion), rewritten.str());
currentClauseExpr[k] = missingAssertion->toExpr();
std::ostringstream rewritten;
- rewritten << "(or_elim_1 _ _ ";
- rewritten << "(not_not_intro _ ";
- rewritten << pm->getLitName(explanation);
- rewritten << ") (iff_elim_1 _ _ ";
- rewritten << d_assertionToRewrite[missingAssertion->negate()];
- rewritten << "))";
+
+ if (missingAssertion->getKind() == kind::NOT && (*missingAssertion)[0].toExpr() == utils::mkFalse()) {
+ rewritten << "(or_elim_2 _ _ ";
+ rewritten << "(not_not_intro _ ";
+ rewritten << pm->getLitName(explanation);
+ rewritten << ") (iff_elim_2 _ _ ";
+ rewritten << d_assertionToRewrite[missingAssertion->negate()];
+ rewritten << "))";
+ }
+ else {
+ rewritten << "(or_elim_1 _ _ ";
+ rewritten << "(not_not_intro _ ";
+ rewritten << pm->getLitName(explanation);
+ rewritten << ") (iff_elim_1 _ _ ";
+ rewritten << d_assertionToRewrite[missingAssertion->negate()];
+ rewritten << "))";
+ }
Debug("pf::tp") << "Setting a rewrite filter for this proof: " << std::endl
<< pm->getLitName(*missingAssertion) << " --> " << rewritten.str()
+ << "explanation = " << explanation
<< std::endl << std::endl;
pm->addRewriteFilter(pm->getLitName(*missingAssertion), rewritten.str());
// or ((a[i]:=t)[k] == a[k]) because (i != k).
if (proof) {
- if (a.getNumChildren() == 2) {
+ if (a.getKind() == kind::SELECT) {
// This is the case of ((a[i]:=t)[k] == a[k]) because (i != k).
// The edge is ((a[i]:=t)[k], a[k]), or (a[k], (a[i]:=t)[k]). This flag should be
proof->d_children.push_back(childProof);
} else {
- // This is the case of (i == k) because ((a[i]:=t)[k] != a[k]),
+ // This is the case of (i == k) because ((a[i]:=t)[k] != a[k]),
Node indexOne = a;
Node indexTwo = b;
void EqualityEngine::assertEqualityInternal(TNode t1, TNode t2, TNode reason, unsigned pid) {
- Debug("equality") << d_name << "::eq::addEqualityInternal(" << t1 << "," << t2 << "), pid = " << pid << std::endl;
+ Debug("equality") << d_name << "::eq::addEqualityInternal(" << t1 << "," << t2 << "), reason = " << reason << ", pid = " << pid << std::endl;
if (d_done) {
return;
Debug("equality") << d_name << "::eq::getExplanation(): adding: "
<< reason << std::endl;
Debug("equality") << d_name << "::eq::getExplanation(): reason type = " << reasonType << std::endl;
-
Node a = d_nodes[currentNode];
Node b = d_nodes[d_equalityEdges[currentEdge].getNodeId()];