(proof-new) New rules for Booleans (#5243)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Tue, 13 Oct 2020 23:33:57 +0000 (18:33 -0500)
committerGitHub <noreply@github.com>
Tue, 13 Oct 2020 23:33:57 +0000 (18:33 -0500)
This adds 2 new rules for convenience to the Boolean checker.

src/expr/proof_rule.cpp
src/expr/proof_rule.h
src/theory/booleans/proof_checker.cpp

index a6ecd9bcb1417d70afc2d1b250de7f279dfccf6f..e4719ff30457201c19fbb55315bedf1f49c8d3ab 100644 (file)
@@ -50,6 +50,9 @@ const char* toString(PfRule id)
     case PfRule::REORDERING: return "REORDERING";
     case PfRule::SPLIT: return "SPLIT";
     case PfRule::EQ_RESOLVE: return "EQ_RESOLVE";
+    case PfRule::MODUS_PONENS: return "MODUS_PONENS";
+    case PfRule::NOT_NOT_ELIM: return "NOT_NOT_ELIM";
+    case PfRule::CONTRA: return "CONTRA";
     case PfRule::AND_ELIM: return "AND_ELIM";
     case PfRule::AND_INTRO: return "AND_INTRO";
     case PfRule::NOT_OR_ELIM: return "NOT_OR_ELIM";
@@ -68,7 +71,6 @@ const char* toString(PfRule id)
     case PfRule::ITE_ELIM2: return "ITE_ELIM2";
     case PfRule::NOT_ITE_ELIM1: return "NOT_ITE_ELIM1";
     case PfRule::NOT_ITE_ELIM2: return "NOT_ITE_ELIM2";
-    case PfRule::CONTRA: return "CONTRA";
     //================================================= De Morgan rules
     case PfRule::NOT_AND: return "NOT_AND";
     //================================================= CNF rules
index 1583bdc3dcccb1984d7c0f8eda44ecf3faf8d374..340b636ae44d92e9bdb48b0793d9d2d4c0ab7b8d 100644 (file)
@@ -280,6 +280,7 @@ enum class PfRule : uint32_t
   //  Set representations of C1 and C2 is the same but the number of literals in
   //  C2 is the same of that of C1
   REORDERING,
+
   // ======== Split
   // Children: none
   // Arguments: (F)
@@ -293,6 +294,25 @@ enum class PfRule : uint32_t
   // Conclusion: (F2)
   // Note this can optionally be seen as a macro for EQUIV_ELIM1+RESOLUTION.
   EQ_RESOLVE,
+  // ======== Modus ponens
+  // Children: (P1:F1, P2:(=> F1 F2))
+  // Arguments: none
+  // ---------------------
+  // Conclusion: (F2)
+  // Note this can optionally be seen as a macro for IMPLIES_ELIM+RESOLUTION.
+  MODUS_PONENS,
+  // ======== Double negation elimination
+  // Children: (P:(not (not F)))
+  // Arguments: none
+  // ---------------------
+  // Conclusion: (F)
+  NOT_NOT_ELIM,
+  // ======== Contradiction
+  // Children: (P1:F P2:(not F))
+  // Arguments: ()
+  // ---------------------
+  // Conclusion: false
+  CONTRA,
   // ======== And elimination
   // Children: (P:(and F1 ... Fn))
   // Arguments: (i)
@@ -401,12 +421,6 @@ enum class PfRule : uint32_t
   // ---------------------
   // Conclusion: (or C (not F2))
   NOT_ITE_ELIM2,
-  // ======== Not ITE elimination version 1
-  // Children: (P1:P P2:(not P))
-  // Arguments: ()
-  // ---------------------
-  // Conclusion: (false)
-  CONTRA,
 
   //================================================= De Morgan rules
   // ======== Not And
index eded6b9fa7305c0ebdfce0a9ea19ee801f89b836..2f06995e3ad6544eec743879d7954acfcc223c69 100644 (file)
@@ -13,6 +13,8 @@
  **/
 
 #include "theory/booleans/proof_checker.h"
+#include "expr/skolem_manager.h"
+#include "theory/rewriter.h"
 
 namespace CVC4 {
 namespace theory {
@@ -26,6 +28,9 @@ void BoolProofRuleChecker::registerTo(ProofChecker* pc)
   pc->registerChecker(PfRule::FACTORING, this);
   pc->registerChecker(PfRule::REORDERING, this);
   pc->registerChecker(PfRule::EQ_RESOLVE, this);
+  pc->registerChecker(PfRule::MODUS_PONENS, this);
+  pc->registerChecker(PfRule::NOT_NOT_ELIM, this);
+  pc->registerChecker(PfRule::CONTRA, this);
   pc->registerChecker(PfRule::AND_ELIM, this);
   pc->registerChecker(PfRule::AND_INTRO, this);
   pc->registerChecker(PfRule::NOT_OR_ELIM, this);
@@ -212,6 +217,15 @@ Node BoolProofRuleChecker::checkInternal(PfRule id,
     return NodeManager::currentNM()->mkNode(
         kind::OR, args[0], args[0].notNode());
   }
+  if (id == PfRule::CONTRA)
+  {
+    Assert(children.size() == 2);
+    if (children[1].getKind() == Kind::NOT && children[0] == children[1][0])
+    {
+      return NodeManager::currentNM()->mkConst(false);
+    }
+    return Node::null();
+  }
   if (id == PfRule::EQ_RESOLVE)
   {
     Assert(children.size() == 2);
@@ -222,6 +236,26 @@ Node BoolProofRuleChecker::checkInternal(PfRule id,
     }
     return children[1][1];
   }
+  if (id == PfRule::MODUS_PONENS)
+  {
+    Assert(children.size() == 2);
+    Assert(args.empty());
+    if (children[1].getKind() != kind::IMPLIES || children[0] != children[1][0])
+    {
+      return Node::null();
+    }
+    return children[1][1];
+  }
+  if (id == PfRule::NOT_NOT_ELIM)
+  {
+    Assert(children.size() == 1);
+    Assert(args.empty());
+    if (children[0].getKind() != kind::NOT || children[0][0].getKind() != kind::NOT)
+    {
+      return Node::null();
+    }
+    return children[0][0][0];
+  }
   // natural deduction rules
   if (id == PfRule::AND_ELIM)
   {