LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/theory - theory_preprocessor.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 204 213 95.8 %
Date: 2026-01-19 13:01:48 Functions: 12 13 92.3 %
Branches: 114 198 57.6 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * Top contributors (to current version):
       3                 :            :  *   Andrew Reynolds, Hans-Joerg Schurr, Mathias Preiner
       4                 :            :  *
       5                 :            :  * This file is part of the cvc5 project.
       6                 :            :  *
       7                 :            :  * Copyright (c) 2009-2025 by the authors listed in the file AUTHORS
       8                 :            :  * in the top-level source directory and their institutional affiliations.
       9                 :            :  * All rights reserved.  See the file COPYING in the top-level source
      10                 :            :  * directory for licensing information.
      11                 :            :  * ****************************************************************************
      12                 :            :  *
      13                 :            :  * The theory preprocessor.
      14                 :            :  */
      15                 :            : 
      16                 :            : #include "theory/theory_preprocessor.h"
      17                 :            : 
      18                 :            : #include "expr/skolem_manager.h"
      19                 :            : #include "expr/term_context_stack.h"
      20                 :            : #include "proof/lazy_proof.h"
      21                 :            : #include "smt/logic_exception.h"
      22                 :            : #include "theory/logic_info.h"
      23                 :            : #include "theory/rewriter.h"
      24                 :            : #include "theory/theory_engine.h"
      25                 :            : 
      26                 :            : using namespace std;
      27                 :            : 
      28                 :            : namespace cvc5::internal {
      29                 :            : namespace theory {
      30                 :            : 
      31                 :      50880 : TheoryPreprocessor::TheoryPreprocessor(Env& env, TheoryEngine& engine)
      32                 :            :     : EnvObj(env),
      33                 :            :       d_engine(engine),
      34                 :     101760 :       d_cache(userContext()),
      35                 :            :       d_tfr(env),
      36                 :            :       d_tpg(nullptr),
      37                 :            :       d_tpgRew(nullptr),
      38                 :            :       d_tspg(nullptr),
      39                 :      50880 :       d_lp(nullptr)
      40                 :            : {
      41                 :            :   // proofs are enabled in the theory preprocessor regardless of the proof mode
      42                 :      50880 :   ProofNodeManager* pnm = env.getProofNodeManager();
      43         [ +  + ]:      50880 :   if (pnm != nullptr)
      44                 :            :   {
      45                 :      18988 :     context::Context* u = userContext();
      46                 :      37976 :     d_tpg.reset(
      47                 :            :         new TConvProofGenerator(env,
      48                 :            :                                 u,
      49                 :            :                                 TConvPolicy::FIXPOINT,
      50                 :            :                                 TConvCachePolicy::NEVER,
      51                 :            :                                 "TheoryPreprocessor::preprocess_rewrite",
      52                 :      18988 :                                 &d_rtfc));
      53                 :      37976 :     d_tpgRew.reset(new TConvProofGenerator(env,
      54                 :            :                                            u,
      55                 :            :                                            TConvPolicy::ONCE,
      56                 :            :                                            TConvCachePolicy::NEVER,
      57                 :      18988 :                                            "TheoryPreprocessor::pprew"));
      58                 :      37976 :     d_lp.reset(
      59                 :      18988 :         new LazyCDProof(env, nullptr, u, "TheoryPreprocessor::LazyCDProof"));
      60                 :            :     // Make the main term conversion sequence generator, which tracks up to
      61                 :            :     // three conversions made in succession:
      62                 :            :     // (1) rewriting
      63                 :            :     // (2) (theory preprocessing+rewriting until fixed point)+term formula
      64                 :            :     // removal+rewriting.
      65                 :      18988 :     std::vector<ProofGenerator*> ts;
      66         [ +  - ]:      18988 :     ts.push_back(d_tpgRew.get());
      67         [ +  - ]:      18988 :     ts.push_back(d_tpg.get());
      68                 :      37976 :     d_tspg.reset(new TConvSeqProofGenerator(
      69                 :      37976 :         pnm, ts, userContext(), "TheoryPreprocessor::sequence"));
      70                 :            :   }
      71                 :      50880 : }
      72                 :            : 
      73                 :      50535 : TheoryPreprocessor::~TheoryPreprocessor() {}
      74                 :            : 
      75                 :     888711 : TrustNode TheoryPreprocessor::preprocess(TNode node,
      76                 :            :                                          std::vector<SkolemLemma>& newLemmas)
      77                 :            : {
      78                 :     888711 :   return preprocessInternal(node, newLemmas, true);
      79                 :            : }
      80                 :            : 
      81                 :    1829860 : TrustNode TheoryPreprocessor::preprocessInternal(
      82                 :            :     TNode node, std::vector<SkolemLemma>& newLemmas, bool procLemmas)
      83                 :            : {
      84                 :            :   // In this method, all rewriting steps of node are stored in d_tpg.
      85                 :            : 
      86         [ +  - ]:    1829860 :   Trace("tpp") << "TheoryPreprocessor::preprocess: start " << node << std::endl;
      87                 :            : 
      88                 :            :   // We must rewrite before preprocessing, because some terms when rewritten
      89                 :            :   // may introduce new terms that are not top-level and require preprocessing.
      90                 :            :   // An example of this is (forall ((x Int)) (and (tail L) (P x))) which
      91                 :            :   // rewrites to (and (tail L) (forall ((x Int)) (P x))). The subterm (tail L)
      92                 :            :   // must be preprocessed as a child here.
      93                 :    3659730 :   Node irNode = rewriteWithProof(node, d_tpgRew.get(), true, 0);
      94                 :            : 
      95                 :            :   // run theory preprocessing
      96                 :    3659730 :   TrustNode tpp = theoryPreprocess(irNode, newLemmas);
      97                 :    3659700 :   Node ppNode = tpp.getNode();
      98                 :            : 
      99         [ -  + ]:    1829850 :   if (TraceIsOn("tpp-debug"))
     100                 :            :   {
     101         [ -  - ]:          0 :     if (node != irNode)
     102                 :            :     {
     103         [ -  - ]:          0 :       Trace("tpp-debug") << "after initial rewriting : " << irNode << std::endl;
     104                 :            :     }
     105         [ -  - ]:          0 :     if (irNode != ppNode)
     106                 :            :     {
     107         [ -  - ]:          0 :       Trace("tpp-debug")
     108                 :          0 :           << "after preprocessing + rewriting and term formula removal : "
     109                 :          0 :           << ppNode << std::endl;
     110                 :            :     }
     111         [ -  - ]:          0 :     Trace("tpp-debug") << "TheoryPreprocessor::preprocess: finish" << std::endl;
     112                 :            :   }
     113                 :            : 
     114         [ +  + ]:    1829850 :   if (procLemmas)
     115                 :            :   {
     116                 :            :     // Also must preprocess the new lemmas. This is especially important for
     117                 :            :     // formulas containing witness terms whose bodies are not in preprocessed
     118                 :            :     // form, as term formula removal introduces new lemmas for these that
     119                 :            :     // require theory-preprocessing.
     120                 :    1769940 :     size_t i = 0;
     121         [ +  + ]:    1829850 :     while (i < newLemmas.size())
     122                 :            :     {
     123                 :      59917 :       TrustNode cur = newLemmas[i].d_lemma;
     124                 :      59917 :       newLemmas[i].d_lemma = preprocessLemmaInternal(cur, newLemmas, false);
     125 [ +  - ][ -  + ]:      59917 :       Trace("tpp") << "Final lemma : " << newLemmas[i].getProven() << std::endl;
                 [ -  - ]
     126                 :      59917 :       i++;
     127                 :            :     }
     128                 :            :   }
     129                 :            : 
     130         [ +  + ]:    1829850 :   if (node == ppNode)
     131                 :            :   {
     132         [ +  - ]:    2849920 :     Trace("tpp-debug") << "...TheoryPreprocessor::preprocess returned no change"
     133                 :    1424960 :                        << std::endl;
     134                 :            :     // no change
     135                 :    1424960 :     return TrustNode::null();
     136                 :            :   }
     137                 :            : 
     138                 :            :   // Now, sequence the conversion steps if proofs are enabled.
     139                 :     809786 :   TrustNode tret;
     140         [ +  + ]:     404893 :   if (isProofEnabled())
     141                 :            :   {
     142                 :     483064 :     std::vector<Node> cterms;
     143                 :     241532 :     cterms.push_back(node);
     144                 :     241532 :     cterms.push_back(irNode);
     145                 :     241532 :     cterms.push_back(ppNode);
     146                 :            :     // We have that:
     147                 :            :     // node -> irNode via rewriting
     148                 :            :     // irNode -> ppNode via theory-preprocessing + rewriting + tf removal
     149                 :     241532 :     tret = d_tspg->mkTrustRewriteSequence(cterms);
     150                 :     241532 :     tret.debugCheckClosed(
     151                 :            :         options(), "tpp-debug", "TheoryPreprocessor::lemma_ret");
     152                 :            :   }
     153                 :            :   else
     154                 :            :   {
     155                 :     163361 :     tret = TrustNode::mkTrustRewrite(node, ppNode, nullptr);
     156                 :            :   }
     157                 :            : 
     158         [ +  - ]:     809786 :   Trace("tpp-debug") << "...TheoryPreprocessor::preprocess returned "
     159 [ -  + ][ -  - ]:     404893 :                      << tret.getNode() << std::endl;
     160 [ +  - ][ -  - ]:     809786 :   Trace("tpp") << "TheoryPreprocessor::preprocess: return " << tret.getNode()
     161                 :          0 :                << ", procLemmas=" << procLemmas
     162         [ -  + ]:     404893 :                << ", # lemmas = " << newLemmas.size() << std::endl;
     163                 :     404893 :   return tret;
     164                 :            : }
     165                 :            : 
     166                 :     881235 : TrustNode TheoryPreprocessor::preprocessLemma(
     167                 :            :     TrustNode node, std::vector<SkolemLemma>& newLemmas)
     168                 :            : {
     169                 :     881235 :   return preprocessLemmaInternal(node, newLemmas, true);
     170                 :            : }
     171                 :            : 
     172                 :     941152 : TrustNode TheoryPreprocessor::preprocessLemmaInternal(
     173                 :            :     TrustNode node, std::vector<SkolemLemma>& newLemmas, bool procLemmas)
     174                 :            : {
     175                 :            :   // what was originally proven
     176                 :    1882300 :   Node lemma = node.getProven();
     177                 :    1882300 :   TrustNode tplemma = preprocessInternal(lemma, newLemmas, procLemmas);
     178         [ +  + ]:     941151 :   if (tplemma.isNull())
     179                 :            :   {
     180                 :            :     // no change needed
     181                 :     651633 :     return node;
     182                 :            :   }
     183 [ -  + ][ -  + ]:     289518 :   Assert(tplemma.getKind() == TrustNodeKind::REWRITE);
                 [ -  - ]
     184                 :            :   // what it was preprocessed to
     185                 :     289518 :   Node lemmap = tplemma.getNode();
     186 [ -  + ][ -  + ]:     289518 :   Assert(lemmap != node.getProven());
                 [ -  - ]
     187                 :            :   // process the preprocessing
     188         [ +  + ]:     289518 :   if (isProofEnabled())
     189                 :            :   {
     190 [ -  + ][ -  + ]:     154898 :     Assert(d_lp != nullptr);
                 [ -  - ]
     191                 :            :     // add the original proof to the lazy proof
     192                 :     154898 :     d_lp->addLazyStep(node.getProven(),
     193                 :            :                       node.getGenerator(),
     194                 :            :                       TrustId::THEORY_PREPROCESS_LEMMA);
     195                 :            :     // only need to do anything if lemmap changed in a non-trivial way
     196         [ +  + ]:     154898 :     if (!CDProof::isSame(lemmap, lemma))
     197                 :            :     {
     198                 :     145976 :       d_lp->addLazyStep(tplemma.getProven(),
     199                 :            :                         tplemma.getGenerator(),
     200                 :            :                         TrustId::THEORY_PREPROCESS,
     201                 :            :                         true,
     202                 :            :                         "TheoryEngine::lemma_pp");
     203                 :            :       // ---------- from node -------------- from theory preprocess
     204                 :            :       // lemma                lemma = lemmap
     205                 :            :       // ------------------------------------------ EQ_RESOLVE
     206                 :            :       // lemmap
     207                 :     145976 :       std::vector<Node> pfChildren;
     208                 :     145976 :       pfChildren.push_back(lemma);
     209                 :     145976 :       pfChildren.push_back(tplemma.getProven());
     210                 :     145976 :       d_lp->addStep(lemmap, ProofRule::EQ_RESOLVE, pfChildren, {});
     211                 :            :     }
     212                 :            :   }
     213         [ +  + ]:     289518 :   return TrustNode::mkTrustLemma(lemmap, d_lp.get());
     214                 :            : }
     215                 :            : 
     216                 :       1309 : RemoveTermFormulas& TheoryPreprocessor::getRemoveTermFormulas()
     217                 :            : {
     218                 :       1309 :   return d_tfr;
     219                 :            : }
     220                 :            : 
     221                 :    1829860 : TrustNode TheoryPreprocessor::theoryPreprocess(
     222                 :            :     TNode assertion, std::vector<SkolemLemma>& newLemmas)
     223                 :            : {
     224                 :            :   // Map from (term, term context identifier) to the term that it was
     225                 :            :   // theory-preprocessed to. This is used when the result of the current node
     226                 :            :   // should be set to the final result of converting its theory-preprocessed
     227                 :            :   // form.
     228                 :            :   std::unordered_map<std::pair<Node, uint32_t>,
     229                 :            :                      Node,
     230                 :            :                      PairHashFunction<Node, uint32_t, std::hash<Node>>>
     231                 :    3659730 :       wasPreprocessed;
     232                 :            :   std::unordered_map<
     233                 :            :       std::pair<Node, uint32_t>,
     234                 :            :       Node,
     235                 :    1829860 :       PairHashFunction<Node, uint32_t, std::hash<Node>>>::iterator itw;
     236                 :    1829860 :   NodeManager* nm = nodeManager();
     237                 :    3659730 :   TCtxStack ctx(&d_rtfc);
     238                 :    3659730 :   std::vector<bool> processedChildren;
     239                 :    1829860 :   ctx.pushInitial(assertion);
     240                 :    1829860 :   processedChildren.push_back(false);
     241                 :    3659730 :   std::pair<Node, uint32_t> initial = ctx.getCurrent();
     242                 :    3659730 :   std::pair<Node, uint32_t> curr;
     243                 :    1829870 :   Node node;
     244                 :            :   uint32_t nodeVal;
     245                 :    1829860 :   TppCache::const_iterator itc;
     246         [ +  + ]:   20772500 :   while (!ctx.empty())
     247                 :            :   {
     248                 :   18942700 :     curr = ctx.getCurrent();
     249                 :   18942700 :     itc = d_cache.find(curr);
     250                 :   18942700 :     node = curr.first;
     251                 :   18942700 :     nodeVal = curr.second;
     252         [ +  - ]:   18942700 :     Trace("tpp-debug") << "Visit " << node << ", " << nodeVal << std::endl;
     253         [ +  + ]:   18942700 :     if (itc != d_cache.end())
     254                 :            :     {
     255         [ +  - ]:    8849240 :       Trace("tpp-debug") << "...already computed" << std::endl;
     256                 :    8849240 :       ctx.pop();
     257                 :    8849240 :       processedChildren.pop_back();
     258                 :            :       // already computed
     259                 :   13675200 :       continue;
     260                 :            :     }
     261                 :            :     // if we have yet to process children
     262         [ +  + ]:   10093500 :     if (!processedChildren.back())
     263                 :            :     {
     264                 :            :       // check if we should replace the current node by a Skolem
     265                 :    5371680 :       TrustNode newLem;
     266                 :            :       bool inQuant, inTerm;
     267                 :    5371680 :       RtfTermContext::getFlags(nodeVal, inQuant, inTerm);
     268 [ -  + ][ -  + ]:    5371680 :       Assert(!inQuant);
                 [ -  - ]
     269                 :    5371680 :       TrustNode currTrn = d_tfr.runCurrent(node, inTerm, newLem);
     270                 :            :       // if we replaced by a skolem, we do not recurse
     271         [ +  + ]:    5371670 :       if (!currTrn.isNull())
     272                 :            :       {
     273                 :     103502 :         Node ret = currTrn.getNode();
     274                 :            :         // if this is the first time we've seen this term, we have a new lemma
     275                 :            :         // which we add to our vectors
     276         [ +  + ]:      51751 :         if (!newLem.isNull())
     277                 :            :         {
     278                 :      45859 :           newLemmas.push_back(theory::SkolemLemma(newLem, ret));
     279                 :            :         }
     280                 :            :         // register the rewrite into the proof generator
     281         [ +  + ]:      51751 :         if (isProofEnabled())
     282                 :            :         {
     283                 :      32435 :           registerTrustedRewrite(currTrn, d_tpg.get(), true, nodeVal);
     284                 :            :         }
     285         [ +  - ]:      51751 :         Trace("tpp-debug") << "...replace by skolem" << std::endl;
     286                 :      51751 :         d_cache.insert(curr, ret);
     287                 :      51751 :         continue;
     288                 :            :       }
     289                 :    5319920 :       size_t nchild = node.getNumChildren();
     290         [ +  + ]:    5319920 :       if (nchild > 0)
     291                 :            :       {
     292         [ +  + ]:    4729090 :         if (node.isClosure())
     293                 :            :         {
     294                 :            :           // currently, we never do any term formula removal in quantifier
     295                 :            :           // bodies
     296                 :            :         }
     297                 :            :         else
     298                 :            :         {
     299         [ +  - ]:    4669410 :           Trace("tpp-debug") << "...recurse to children" << std::endl;
     300                 :            :           // recurse if we have children
     301                 :    4669410 :           processedChildren[processedChildren.size() - 1] = true;
     302         [ +  + ]:   16956300 :           for (size_t i = 0; i < nchild; i++)
     303                 :            :           {
     304                 :   12286900 :             ctx.pushChild(node, nodeVal, i);
     305                 :   12286900 :             processedChildren.push_back(false);
     306                 :            :           }
     307                 :    4669410 :           continue;
     308                 :            :         }
     309                 :            :       }
     310                 :            :       else
     311                 :            :       {
     312         [ +  - ]:     590833 :         Trace("tpp-debug") << "...base case" << std::endl;
     313                 :            :       }
     314                 :            :     }
     315         [ +  - ]:    5372290 :     Trace("tpp-debug") << "...reconstruct" << std::endl;
     316                 :            :     // otherwise, we are now finished processing children, pop the current node
     317                 :            :     // and compute the result
     318                 :    5372290 :     ctx.pop();
     319                 :    5372290 :     processedChildren.pop_back();
     320                 :            :     // if this was preprocessed previously, we set our result to the final
     321                 :            :     // form of the preprocessed form of this.
     322                 :    5372290 :     itw = wasPreprocessed.find(curr);
     323         [ +  + ]:    5372290 :     if (itw != wasPreprocessed.end())
     324                 :            :     {
     325                 :            :       // we preprocessed it to something else, carry that
     326                 :     104782 :       std::pair<Node, uint32_t> key(itw->second, nodeVal);
     327                 :      52391 :       itc = d_cache.find(key);
     328 [ -  + ][ -  + ]:      52391 :       Assert(itc != d_cache.end());
                 [ -  - ]
     329                 :      52391 :       d_cache.insert(curr, itc->second);
     330                 :      52391 :       wasPreprocessed.erase(curr);
     331                 :      52391 :       continue;
     332                 :            :     }
     333                 :    5319910 :     Node ret = node;
     334                 :    5319910 :     Node pret = node;
     335 [ +  + ][ +  + ]:    5319900 :     if (!node.isClosure() && node.getNumChildren() > 0)
                 [ +  + ]
     336                 :            :     {
     337                 :            :       // if we have not already computed the result
     338                 :    9338780 :       std::vector<Node> newChildren;
     339                 :    4669390 :       bool childChanged = false;
     340         [ +  + ]:    4669390 :       if (node.getMetaKind() == kind::metakind::PARAMETERIZED)
     341                 :            :       {
     342                 :     463870 :         newChildren.push_back(node.getOperator());
     343                 :            :       }
     344                 :            :       // reconstruct from the children
     345                 :    4669390 :       std::pair<Node, uint32_t> currChild;
     346         [ +  + ]:   16956300 :       for (size_t i = 0, nchild = node.getNumChildren(); i < nchild; i++)
     347                 :            :       {
     348                 :            :         // recompute the value of the child
     349                 :   12286900 :         uint32_t val = d_rtfc.computeValue(node, nodeVal, i);
     350                 :   12286900 :         currChild = std::pair<Node, uint32_t>(node[i], val);
     351                 :   12286900 :         itc = d_cache.find(currChild);
     352 [ -  + ][ -  + ]:   12286900 :         Assert(itc != d_cache.end());
                 [ -  - ]
     353                 :   24573800 :         Node newChild = (*itc).second;
     354 [ -  + ][ -  + ]:   12286900 :         Assert(!newChild.isNull());
                 [ -  - ]
     355                 :   12286900 :         childChanged |= (newChild != node[i]);
     356                 :   12286900 :         newChildren.push_back(newChild);
     357                 :            :       }
     358                 :            :       // If changes, we reconstruct the node
     359         [ +  + ]:    4669390 :       if (childChanged)
     360                 :            :       {
     361                 :     318619 :         ret = nm->mkNode(node.getKind(), newChildren);
     362                 :            :       }
     363                 :            :       // Finish the conversion by rewriting. Notice that we must consider this a
     364                 :            :       // pre-rewrite since we do not recursively register the rewriting steps
     365                 :            :       // of subterms of rtfNode. For example, if this step rewrites
     366                 :            :       // (not A) ---> B, then if registered a pre-rewrite, it will apply when
     367                 :            :       // reconstructing proofs via d_tpg. However, if it is a post-rewrite
     368                 :            :       // it will fail to apply if another call to this class registers A -> C,
     369                 :            :       // in which case (not C) will be returned instead of B (see issue 6754).
     370                 :    4669390 :       pret = rewriteWithProof(ret, d_tpg.get(), false, nodeVal);
     371                 :            :     }
     372                 :            :     // if we did not rewrite above, we are ready to theory preprocess
     373         [ +  + ]:    5319900 :     if (pret == ret)
     374                 :            :     {
     375                 :    5289150 :       pret = preprocessWithProof(ret, newLemmas, nodeVal);
     376                 :            :     }
     377                 :            :     // if we changed due to rewriting or preprocessing, we traverse again
     378         [ +  + ]:    5319890 :     if (pret != ret)
     379                 :            :     {
     380                 :            :       // must restart
     381                 :      52391 :       ctx.push(node, nodeVal);
     382                 :      52391 :       processedChildren.push_back(true);
     383                 :      52391 :       ctx.push(pret, nodeVal);
     384                 :      52391 :       processedChildren.push_back(false);
     385                 :      52391 :       wasPreprocessed[curr] = pret;
     386                 :      52391 :       continue;
     387                 :            :     }
     388                 :            :     // cache
     389                 :    5267500 :     d_cache.insert(curr, ret);
     390                 :            :   }
     391                 :    1829850 :   itc = d_cache.find(initial);
     392 [ -  + ][ -  + ]:    1829850 :   Assert(itc != d_cache.end());
                 [ -  - ]
     393         [ +  + ]:    3659700 :   return TrustNode::mkTrustRewrite(assertion, (*itc).second, d_tpg.get());
     394                 :            : }
     395                 :            : 
     396                 :    6520880 : Node TheoryPreprocessor::rewriteWithProof(Node term,
     397                 :            :                                           TConvProofGenerator* pg,
     398                 :            :                                           bool isPre,
     399                 :            :                                           uint32_t tctx)
     400                 :            : {
     401                 :    6520880 :   Node termr = rewrite(term);
     402                 :            :   // store rewrite step if tracking proofs and it rewrites
     403         [ +  + ]:    6520880 :   if (isProofEnabled())
     404                 :            :   {
     405                 :            :     // may rewrite the same term more than once, thus check hasRewriteStep
     406         [ +  + ]:    3958710 :     if (termr != term)
     407                 :            :     {
     408         [ +  - ]:     448000 :       Trace("tpp-debug") << "TheoryPreprocessor: addRewriteStep (rewriting) "
     409                 :     224000 :                          << term << " -> " << termr << std::endl;
     410                 :     448000 :       pg->addRewriteStep(
     411                 :     224000 :           term, termr, ProofRule::MACRO_REWRITE, {}, {term}, isPre, tctx);
     412                 :            :     }
     413                 :            :   }
     414                 :    6520880 :   return termr;
     415                 :            : }
     416                 :            : 
     417                 :    5289140 : Node TheoryPreprocessor::preprocessWithProof(Node term,
     418                 :            :                                              std::vector<SkolemLemma>& lems,
     419                 :            :                                              uint32_t tctx)
     420                 :            : {
     421                 :            :   // Important that it is in rewritten form, to ensure that the rewrite steps
     422                 :            :   // recorded in d_tpg are functional. In other words, there should not
     423                 :            :   // be steps from the same term to multiple rewritten forms, which would be
     424                 :            :   // the case if we registered a preprocessing step for a non-rewritten term.
     425 [ -  + ][ -  + ]:    5289140 :   Assert(term == rewrite(term));
                 [ -  - ]
     426         [ +  - ]:   10578300 :   Trace("tpp-debug2") << "preprocessWithProof " << term
     427                 :    5289140 :                       << ", #lems = " << lems.size() << std::endl;
     428                 :            :   // We never call ppRewrite on equalities here, since equalities have a
     429                 :            :   // special status. In particular, notice that theory preprocessing can be
     430                 :            :   // called on all formulas asserted to theory engine, including those generated
     431                 :            :   // as new literals appearing in lemmas. Calling ppRewrite on equalities is
     432                 :            :   // incompatible with theory combination where a split on equality requested
     433                 :            :   // by a theory could be preprocessed to something else, thus making theory
     434                 :            :   // combination either non-terminating or result in solution soundness.
     435                 :            :   // Notice that an alternative solution is to ensure that certain lemmas
     436                 :            :   // (e.g. splits from theory combination) can never have theory preprocessing
     437                 :            :   // applied to them. However, it is more uniform to say that theory
     438                 :            :   // preprocessing is applied to all formulas. This makes it so that e.g.
     439                 :            :   // theory solvers do not need to specify whether they want their lemmas to
     440                 :            :   // be theory-preprocessed or not.
     441         [ +  + ]:    5289140 :   if (term.getKind() == Kind::EQUAL)
     442                 :            :   {
     443                 :     740133 :     return term;
     444                 :            :   }
     445                 :            :   // call ppRewrite for the given theory
     446                 :    9098010 :   std::vector<SkolemLemma> newLems;
     447                 :    9098010 :   TrustNode trn = d_engine.ppRewrite(term, newLems);
     448         [ +  - ]:    9097990 :   Trace("tpp-debug2") << "preprocessWithProof returned " << trn
     449                 :    4549000 :                       << ", #lems = " << newLems.size() << std::endl;
     450                 :    4549000 :   lems.insert(lems.end(), newLems.begin(), newLems.end());
     451         [ +  + ]:    4549000 :   if (trn.isNull())
     452                 :            :   {
     453                 :            :     // no change, return
     454                 :    4527370 :     return term;
     455                 :            :   }
     456                 :      21628 :   Node termr = trn.getNode();
     457 [ -  + ][ -  + ]:      21628 :   Assert(term != termr);
                 [ -  - ]
     458         [ +  + ]:      21628 :   if (isProofEnabled())
     459                 :            :   {
     460                 :       8808 :     registerTrustedRewrite(trn, d_tpg.get(), false, tctx);
     461                 :            :   }
     462                 :            :   // Rewrite again here, which notice is a *pre* rewrite.
     463                 :      21628 :   return rewriteWithProof(termr, d_tpg.get(), true, tctx);
     464                 :            : }
     465                 :            : 
     466                 :    7329910 : bool TheoryPreprocessor::isProofEnabled() const { return d_tpg != nullptr; }
     467                 :            : 
     468                 :      41243 : void TheoryPreprocessor::registerTrustedRewrite(TrustNode trn,
     469                 :            :                                                 TConvProofGenerator* pg,
     470                 :            :                                                 bool isPre,
     471                 :            :                                                 uint32_t tctx)
     472                 :            : {
     473 [ +  - ][ -  + ]:      41243 :   if (!isProofEnabled() || trn.isNull())
                 [ -  + ]
     474                 :            :   {
     475                 :          0 :     return;
     476                 :            :   }
     477 [ -  + ][ -  + ]:      41243 :   Assert(trn.getKind() == TrustNodeKind::REWRITE);
                 [ -  - ]
     478                 :      82486 :   Node eq = trn.getProven();
     479                 :      82486 :   Node term = eq[0];
     480                 :      41243 :   Node termr = eq[1];
     481         [ +  - ]:      82486 :   Trace("tpp-debug") << "TheoryPreprocessor: addRewriteStep (generator) "
     482                 :      41243 :                      << term << " -> " << termr << std::endl;
     483         [ +  + ]:      41243 :   if (trn.getGenerator() != nullptr)
     484                 :            :   {
     485                 :      36243 :     trn.debugCheckClosed(
     486                 :            :         options(), "tpp-debug", "TheoryPreprocessor::preprocessWithProof");
     487                 :            :   }
     488                 :            :   // always use term context hash 0 (default)
     489                 :      41243 :   pg->addRewriteStep(term,
     490                 :            :                      termr,
     491                 :            :                      trn.getGenerator(),
     492                 :            :                      isPre,
     493                 :            :                      TrustId::THEORY_PREPROCESS,
     494                 :            :                      true,
     495                 :            :                      tctx);
     496                 :            : }
     497                 :            : 
     498                 :            : }  // namespace theory
     499                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14