(proof-new) Clean up uses of witness with skolem lemmas (#6109)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Thu, 11 Mar 2021 09:21:06 +0000 (03:21 -0600)
committerGitHub <noreply@github.com>
Thu, 11 Mar 2021 09:21:06 +0000 (09:21 +0000)
This ensures we do not return WITNESS terms in response to ppRewrite. This makes standard utility methods in SkolemLemma to help make this easy.

It also removes TheorySetsPrivate::expandDefinitions, which was returning WITNESS in response to expandDefinitions, which is no longer permitted.

src/CMakeLists.txt
src/theory/arith/operator_elim.cpp
src/theory/sets/theory_sets.cpp
src/theory/sets/theory_sets_private.cpp
src/theory/sets/theory_sets_private.h
src/theory/skolem_lemma.cpp [new file with mode: 0644]
src/theory/skolem_lemma.h
src/theory/strings/theory_strings.cpp
src/theory/theory_preprocessor.cpp

index 3fc12c5850bc5017b6d84183ad748820fc68116f..a086d4224c8d8f661fc9892e4c7208def026f2ae 100644 (file)
@@ -900,6 +900,7 @@ libcvc4_add_sources(
   theory/shared_solver_distributed.h
   theory/shared_terms_database.cpp
   theory/shared_terms_database.h
+  theory/skolem_lemma.cpp
   theory/skolem_lemma.h
   theory/smt_engine_subsolver.cpp
   theory/smt_engine_subsolver.h
index 100116fd7d1f6226aa36448570d449ac7b511f19..ab01960dd04c607dca80a175363260641d584d33 100644 (file)
@@ -481,18 +481,16 @@ Node OperatorElim::mkWitnessTerm(Node v,
   // we mark that we should send a lemma
   Node k =
       sm->mkSkolem(v, pred, prefix, comment, NodeManager::SKOLEM_DEFAULT, this);
-  TNode tv = v;
-  TNode tk = k;
-  Node lem = pred.substitute(tv, tk);
   if (d_pnm != nullptr)
   {
+    Node lem = SkolemLemma::getSkolemLemmaFor(k);
     TrustNode tlem =
         mkTrustNode(lem, PfRule::THEORY_PREPROCESS_LEMMA, {}, {lem});
     lems.push_back(SkolemLemma(tlem, k));
   }
   else
   {
-    lems.push_back(SkolemLemma(TrustNode::mkTrustLemma(lem), k));
+    lems.push_back(SkolemLemma(k, nullptr));
   }
   return k;
 }
index ee23aae499af0956c8410d7df0b4bc970da5bb5c..f3ad57535ca2e54fcc28ce3bc2050118a3d3acfb 100644 (file)
@@ -132,7 +132,8 @@ void TheorySets::preRegisterTerm(TNode node)
 
 TrustNode TheorySets::expandDefinition(Node n)
 {
-  return d_internal->expandDefinition(n);
+  // we currently do not expand any set operators
+  return TrustNode::null();
 }
 
 TrustNode TheorySets::ppRewrite(TNode n, std::vector<SkolemLemma>& lems)
index c15ea6f654e53ba7fed2c0c36aecc925f7d56a5f..da2958c5ceed296ad1d28dc698facdf813e158a8 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "expr/emptyset.h"
 #include "expr/node_algorithm.h"
+#include "expr/skolem_manager.h"
 #include "options/sets_options.h"
 #include "smt/smt_statistics_registry.h"
 #include "theory/sets/normal_form.h"
@@ -1265,17 +1266,6 @@ void TheorySetsPrivate::preRegisterTerm(TNode node)
   }
 }
 
-TrustNode TheorySetsPrivate::expandDefinition(Node node)
-{
-  Debug("sets-proc") << "expandDefinition : " << node << std::endl;
-
-  if (node.getKind()==kind::CHOOSE)
-  {
-    return expandChooseOperator(node);
-  }
-  return TrustNode::null();
-}
-
 TrustNode TheorySetsPrivate::ppRewrite(Node node,
                                        std::vector<SkolemLemma>& lems)
 {
@@ -1283,24 +1273,17 @@ TrustNode TheorySetsPrivate::ppRewrite(Node node,
 
   switch (node.getKind())
   {
-    case kind::CHOOSE: return expandChooseOperator(node);
+    case kind::CHOOSE: return expandChooseOperator(node, lems);
     case kind::IS_SINGLETON: return expandIsSingletonOperator(node);
     default: return TrustNode::null();
   }
 }
 
-TrustNode TheorySetsPrivate::expandChooseOperator(const Node& node)
+TrustNode TheorySetsPrivate::expandChooseOperator(
+    const Node& node, std::vector<SkolemLemma>& lems)
 {
   Assert(node.getKind() == CHOOSE);
 
-  // we call the rewriter here to handle the pattern (choose (singleton x))
-  // because the rewriter is called after expansion
-  Node rewritten = Rewriter::rewrite(node);
-  if (rewritten.getKind() != CHOOSE)
-  {
-    return TrustNode::mkTrustRewrite(node, rewritten, nullptr);
-  }
-
   // (choose A) is expanded as
   // (witness ((x elementType))
   //    (ite
@@ -1309,7 +1292,7 @@ TrustNode TheorySetsPrivate::expandChooseOperator(const Node& node)
   //      (and (member x A) (= x chooseUf(A)))
 
   NodeManager* nm = NodeManager::currentNM();
-  Node set = rewritten[0];
+  Node set = node[0];
   TypeNode setType = set.getType();
   Node chooseSkolem = getChooseFunction(setType);
   Node apply = NodeManager::currentNM()->mkNode(APPLY_UF, chooseSkolem, set);
@@ -1322,9 +1305,10 @@ TrustNode TheorySetsPrivate::expandChooseOperator(const Node& node)
   Node member = nm->mkNode(MEMBER, witnessVariable, set);
   Node memberAndEqual = member.andNode(equal);
   Node ite = nm->mkNode(ITE, isEmpty, equal, memberAndEqual);
-  Node witnessVariables = nm->mkNode(BOUND_VAR_LIST, witnessVariable);
-  Node witness = nm->mkNode(WITNESS, witnessVariables, ite);
-  return TrustNode::mkTrustRewrite(node, witness, nullptr);
+  SkolemManager* sm = nm->getSkolemManager();
+  Node ret = sm->mkSkolem(witnessVariable, ite, "kSetChoose");
+  lems.push_back(SkolemLemma(ret, nullptr));
+  return TrustNode::mkTrustRewrite(node, ret, nullptr);
 }
 
 TrustNode TheorySetsPrivate::expandIsSingletonOperator(const Node& node)
index 262a4c5723f389f44ed9470452d0f24ce55274ec..329fbfc17ceaad0c8840046f4a2aa8d9a9dbc97f 100644 (file)
@@ -167,8 +167,6 @@ class TheorySetsPrivate {
 
   void preRegisterTerm(TNode node);
 
-  /** ppRewrite, which expands choose.  */
-  TrustNode expandDefinition(Node n);
   /** ppRewrite, which expands choose and is_singleton.  */
   TrustNode ppRewrite(Node n, std::vector<SkolemLemma>& lems);
 
@@ -204,7 +202,8 @@ class TheorySetsPrivate {
    */
   Node getChooseFunction(const TypeNode& setType);
   /** expand the definition of the choose operator */
-  TrustNode expandChooseOperator(const Node& node);
+  TrustNode expandChooseOperator(const Node& node,
+                                 std::vector<SkolemLemma>& lems);
   /** expand the definition of is_singleton operator */
   TrustNode expandIsSingletonOperator(const Node& node);
   /** subtheory solver for the theory of relations */
diff --git a/src/theory/skolem_lemma.cpp b/src/theory/skolem_lemma.cpp
new file mode 100644 (file)
index 0000000..7c8f00d
--- /dev/null
@@ -0,0 +1,43 @@
+/*********************                                                        */
+/*! \file skolem_lemma.cpp
+ ** \verbatim
+ ** Top contributors (to current version):
+ **   Andrew Reynolds
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+ ** in the top-level source directory and their institutional affiliations.
+ ** All rights reserved.  See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief The skolem lemma utility
+ **/
+
+#include "theory/skolem_lemma.h"
+
+#include "expr/skolem_manager.h"
+
+namespace CVC4 {
+namespace theory {
+
+SkolemLemma::SkolemLemma(TrustNode lem, Node k) : d_lemma(lem), d_skolem(k)
+{
+  Assert(lem.getKind() == TrustNodeKind::LEMMA);
+}
+
+SkolemLemma::SkolemLemma(Node k, ProofGenerator* pg) : d_lemma(), d_skolem(k)
+{
+  Node lem = getSkolemLemmaFor(k);
+  d_lemma = TrustNode::mkTrustLemma(lem, pg);
+}
+
+Node SkolemLemma::getSkolemLemmaFor(Node k)
+{
+  Node w = SkolemManager::getWitnessForm(k);
+  Assert(w.getKind() == kind::WITNESS);
+  TNode tx = w[0][0];
+  TNode tk = k;
+  return w[1].substitute(tx, tk);
+}
+
+}  // namespace theory
+}  // namespace CVC4
index a44d5a30d0cf4a676da0cf3b5642c91d4039dd85..c669b527d94d357dfab63834127e62a9a6bcb58f 100644 (file)
@@ -36,14 +36,26 @@ namespace theory {
 class SkolemLemma
 {
  public:
-  SkolemLemma(TrustNode lem, Node k) : d_lemma(lem), d_skolem(k)
-  {
-    Assert(lem.getKind() == TrustNodeKind::LEMMA);
-  }
+  /**
+   * Make skolem from trust node lem of kind LEMMA and skolem k.
+   */
+  SkolemLemma(TrustNode lem, Node k);
+  /**
+   * Make skolem lemma from witness form of skolem k. If non-null, pg is
+   * proof generator that can generator a proof for getSkolemLemmaFor(k).
+   */
+  SkolemLemma(Node k, ProofGenerator* pg);
+
   /** The lemma, a trust node of kind LEMMA */
   TrustNode d_lemma;
   /** The skolem associated with that lemma */
   Node d_skolem;
+
+  /**
+   * Get the lemma for skolem k based on its witness form. If k has witness
+   * form (witness ((x T)) (P x)), this is the formula (P k).
+   */
+  static Node getSkolemLemmaFor(Node k);
 };
 
 }  // namespace theory
index 7f838e411ea3d014bc1daa609d6935fe6be4d5eb..fbede89f091665776d92f036d88ae5169bd1cdbe 100644 (file)
@@ -998,15 +998,13 @@ TrustNode TheoryStrings::ppRewrite(TNode atom, std::vector<SkolemLemma>& lems)
     Node card = nm->mkConst(Rational(utils::getAlphabetCardinality()));
     Node cond =
         nm->mkNode(AND, nm->mkNode(LEQ, d_zero, t), nm->mkNode(LT, t, card));
-    Node k = nm->mkBoundVar(nm->stringType());
-    Node bvl = nm->mkNode(BOUND_VAR_LIST, k);
+    Node v = nm->mkBoundVar(nm->stringType());
     Node emp = Word::mkEmptyWord(atom.getType());
-    // TODO: use skolem manager
-    Node ret = nm->mkNode(
-        WITNESS,
-        bvl,
-        nm->mkNode(
-            ITE, cond, t.eqNode(nm->mkNode(STRING_TO_CODE, k)), k.eqNode(emp)));
+    Node pred = nm->mkNode(
+        ITE, cond, t.eqNode(nm->mkNode(STRING_TO_CODE, v)), v.eqNode(emp));
+    SkolemManager* sm = nm->getSkolemManager();
+    Node ret = sm->mkSkolem(v, pred, "kFromCode");
+    lems.push_back(SkolemLemma(ret, nullptr));
     return TrustNode::mkTrustRewrite(atom, ret, nullptr);
   }
   TrustNode ret;
index ea4b0f82f947e155d1df0e447f0cb64f29fba0bd..a9e16f48f14912fc2cdbf5a5b757b57daa7a9bd8 100644 (file)
@@ -204,13 +204,14 @@ TrustNode TheoryPreprocessor::preprocessLemmaInternal(
   {
     Assert(d_lp != nullptr);
     // add the original proof to the lazy proof
-    d_lp->addLazyStep(node.getProven(), node.getGenerator());
+    d_lp->addLazyStep(
+        node.getProven(), node.getGenerator(), PfRule::THEORY_PREPROCESS_LEMMA);
     // only need to do anything if lemmap changed in a non-trivial way
     if (!CDProof::isSame(lemmap, lemma))
     {
       d_lp->addLazyStep(tplemma.getProven(),
                         tplemma.getGenerator(),
-                        PfRule::PREPROCESS_LEMMA,
+                        PfRule::THEORY_PREPROCESS,
                         true,
                         "TheoryEngine::lemma_pp");
       // ---------- from node -------------- from theory preprocess