[proofs] Cancel SYMM in CDProof, throw an error for cyclic proofs during double SYMM...
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Fri, 12 Nov 2021 21:09:11 +0000 (15:09 -0600)
committerGitHub <noreply@github.com>
Fri, 12 Nov 2021 21:09:11 +0000 (21:09 +0000)
This fixes the potential for cyclic proofs in CDProof when P and (SYMM P) are added as proofs to a CDProof with automatic managing of symmetry.

This manifested as non-termination on the seqArray branch with proofs enabled, instead, if this were to occur, we should throw an error, which is easy to catch.

src/proof/proof.cpp
src/proof/proof_node_manager.cpp

index dc370a04dd9c6ab98f6c1fe8310b5353b48eb054..ffccd42ba4d37b2080a31a06ec07aa70f9329f18 100644 (file)
@@ -287,6 +287,24 @@ bool CDProof::addProof(std::shared_ptr<ProofNode> pn,
 {
   if (!doCopy)
   {
+    // If we are automatically managing symmetry, we strip off SYMM steps.
+    // This avoids cyclic proofs in cases where P and (SYMM P) are added as
+    // proofs to the same CDProof.
+    if (d_autoSymm)
+    {
+      std::vector<std::shared_ptr<ProofNode>> processed;
+      while (pn->getRule() == PfRule::SYMM)
+      {
+        pn = pn->getChildren()[0];
+        if (std::find(processed.begin(), processed.end(), pn)
+            != processed.end())
+        {
+          Unreachable() << "Cyclic proof encountered when cancelling symmetry "
+                           "steps during addProof";
+        }
+        processed.push_back(pn);
+      }
+    }
     // If we aren't doing a deep copy, we either store pn or link its top
     // node into the existing pointer
     Node curFact = pn->getResult();
index 72c39c59fc25893ea7328f46e7931932faaf9a48..e0a7f81c077db448e6de3d51a29ee28d8b9161ae 100644 (file)
@@ -403,12 +403,20 @@ std::shared_ptr<ProofNode> ProofNodeManager::clone(
 
 ProofNode* ProofNodeManager::cancelDoubleSymm(ProofNode* pn)
 {
+  // processed is almost always size <= 1
+  std::vector<ProofNode*> processed;
   while (pn->getRule() == PfRule::SYMM)
   {
     std::shared_ptr<ProofNode> pnc = pn->getChildren()[0];
     if (pnc->getRule() == PfRule::SYMM)
     {
       pn = pnc->getChildren()[0].get();
+      if (std::find(processed.begin(), processed.end(), pn) != processed.end())
+      {
+        Unreachable()
+            << "Cyclic proof encountered when cancelling double symmetry";
+      }
+      processed.push_back(pn);
     }
     else
     {