(proof-new) Improve robustness of CONG rule (#4882)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Wed, 12 Aug 2020 21:34:47 +0000 (16:34 -0500)
committerGitHub <noreply@github.com>
Wed, 12 Aug 2020 21:34:47 +0000 (18:34 -0300)
This makes it so that the explicit Kind is wrapped in a Node as an argument to the CONG proof rule. This allows us to distinguish applications with the same parameterized operator but different kinds (e.g. APPLY_SELECTOR vs APPLY_SELECTOR_TOTAL).

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

index beff92bd4f5d4e873507364ca9ac34fde25d1304..364598cf44788643af7e6e5a745d24cf26bd6bf0 100644 (file)
@@ -481,11 +481,14 @@ enum class PfRule : uint32_t
   // -----------------------
   // Conclusion: (= t1 tn)
   TRANS,
-  // ======== Congruence  (subsumed by Substitute?)
+  // ======== Congruence
   // Children: (P1:(= t1 s1), ..., Pn:(= tn sn))
-  // Arguments: (f)
+  // Arguments: (<kind> f?)
   // ---------------------------------------------
-  // Conclusion: (= (f t1 ... tn) (f s1 ... sn))
+  // Conclusion: (= (<kind> f? t1 ... tn) (<kind> f? s1 ... sn))
+  // Notice that f must be provided iff <kind> is a parameterized kind, e.g.
+  // APPLY_UF. The actual node for <kind> is constructible via
+  // ProofRuleChecker::mkKindNode.
   CONG,
   // ======== True intro
   // Children: (P:F)
index f866e77dd7f305e2cefad25857a549441effbdd3..b010b6d17c61f81de9fd84336ca00c381a2fcf54 100644 (file)
@@ -86,15 +86,15 @@ Node UfProofRuleChecker::checkInternal(PfRule id,
   else if (id == PfRule::CONG)
   {
     Assert(children.size() > 0);
-    Assert(args.size() == 1);
+    Assert(args.size() >= 1 && args.size() <= 2);
     // We do congruence over builtin kinds using operatorToKind
     std::vector<Node> lchildren;
     std::vector<Node> rchildren;
-    // get the expected kind for args[0]
-    Kind k = NodeManager::getKindForFunction(args[0]);
-    if (k == kind::UNDEFINED_KIND)
+    // get the kind encoded as args[0]
+    Kind k;
+    if (!getKind(args[0], k))
     {
-      k = NodeManager::operatorToKind(args[0]);
+      return Node::null();
     }
     if (k == kind::UNDEFINED_KIND)
     {
@@ -104,9 +104,17 @@ Node UfProofRuleChecker::checkInternal(PfRule id,
                         << ", metakind=" << kind::metaKindOf(k) << std::endl;
     if (kind::metaKindOf(k) == kind::metakind::PARAMETERIZED)
     {
+      if (args.size() <= 1)
+      {
+        return Node::null();
+      }
       // parameterized kinds require the operator
-      lchildren.push_back(args[0]);
-      rchildren.push_back(args[0]);
+      lchildren.push_back(args[1]);
+      rchildren.push_back(args[1]);
+    }
+    else if (args.size() > 1)
+    {
+      return Node::null();
     }
     for (size_t i = 0, nchild = children.size(); i < nchild; i++)
     {