LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/proof - proof_node_manager.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 181 217 83.4 %
Date: 2026-02-26 11:40:56 Functions: 14 14 100.0 %
Branches: 120 206 58.3 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * This file is part of the cvc5 project.
       3                 :            :  *
       4                 :            :  * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS
       5                 :            :  * in the top-level source directory and their institutional affiliations.
       6                 :            :  * All rights reserved.  See the file COPYING in the top-level source
       7                 :            :  * directory for licensing information.
       8                 :            :  * ****************************************************************************
       9                 :            :  *
      10                 :            :  * Implementation of proof node manager.
      11                 :            :  */
      12                 :            : 
      13                 :            : #include "proof/proof_node_manager.h"
      14                 :            : 
      15                 :            : #include <sstream>
      16                 :            : 
      17                 :            : #include "options/proof_options.h"
      18                 :            : #include "proof/proof.h"
      19                 :            : #include "proof/proof_checker.h"
      20                 :            : #include "proof/proof_node.h"
      21                 :            : #include "proof/proof_node_algorithm.h"
      22                 :            : #include "theory/rewriter.h"
      23                 :            : 
      24                 :            : using namespace cvc5::internal::kind;
      25                 :            : 
      26                 :            : namespace cvc5::internal {
      27                 :            : 
      28                 :      18896 : ProofNodeManager::ProofNodeManager(NodeManager* nm,
      29                 :            :                                    const Options& opts,
      30                 :            :                                    theory::Rewriter* rr,
      31                 :      18896 :                                    ProofChecker* pc)
      32                 :      18896 :     : d_opts(opts), d_rewriter(rr), d_checker(pc)
      33                 :            : {
      34                 :      18896 :   d_true = nm->mkConst(true);
      35                 :            :   // we always allocate a proof checker, regardless of the proof checking mode
      36 [ -  + ][ -  + ]:      18896 :   Assert(d_checker != nullptr);
                 [ -  - ]
      37                 :      18896 : }
      38                 :            : 
      39                 :   66238054 : std::shared_ptr<ProofNode> ProofNodeManager::mkNode(
      40                 :            :     ProofRule id,
      41                 :            :     const std::vector<std::shared_ptr<ProofNode>>& children,
      42                 :            :     const std::vector<Node>& args,
      43                 :            :     Node expected)
      44                 :            : {
      45         [ +  - ]:  132476108 :   Trace("pnm") << "ProofNodeManager::mkNode " << id << " {" << expected.getId()
      46                 :   66238054 :                << "} " << expected << "\n";
      47                 :   66238054 :   bool didCheck = false;
      48                 :   66238054 :   Node res = checkInternal(id, children, args, expected, didCheck);
      49         [ -  + ]:   66238054 :   if (res.isNull())
      50                 :            :   {
      51                 :            :     // if it was invalid, then we return the null node
      52                 :          0 :     return nullptr;
      53                 :            :   }
      54                 :            :   // otherwise construct the proof node and set its proven field
      55                 :            :   std::shared_ptr<ProofNode> pn =
      56                 :   66238054 :       std::make_shared<ProofNode>(id, children, args);
      57                 :   66238054 :   pn->d_proven = res;
      58                 :   66238054 :   pn->d_provenChecked = didCheck;
      59                 :   66238054 :   return pn;
      60                 :   66238054 : }
      61                 :            : 
      62                 :      22786 : std::shared_ptr<ProofNode> ProofNodeManager::mkTrustedNode(
      63                 :            :     TrustId id,
      64                 :            :     const std::vector<std::shared_ptr<ProofNode>>& children,
      65                 :            :     const std::vector<Node>& args,
      66                 :            :     const Node& conc)
      67                 :            : {
      68                 :      22786 :   std::vector<Node> sargs;
      69                 :      22786 :   sargs.push_back(mkTrustId(conc.getNodeManager(), id));
      70                 :      22786 :   sargs.push_back(conc);
      71                 :      22786 :   sargs.insert(sargs.end(), args.begin(), args.end());
      72                 :      45572 :   return mkNode(ProofRule::TRUST, children, sargs);
      73                 :      22786 : }
      74                 :            : 
      75                 :   19465068 : std::shared_ptr<ProofNode> ProofNodeManager::mkAssume(Node fact)
      76                 :            : {
      77 [ -  + ][ -  + ]:   19465068 :   Assert(!fact.isNull());
                 [ -  - ]
      78 [ -  + ][ -  + ]:   19465068 :   Assert(fact.getType().isBoolean());
                 [ -  - ]
      79                 :   38930136 :   return mkNode(ProofRule::ASSUME, {}, {fact}, fact);
      80                 :            : }
      81                 :            : 
      82                 :    2351839 : std::shared_ptr<ProofNode> ProofNodeManager::mkSymm(
      83                 :            :     std::shared_ptr<ProofNode> child, Node expected)
      84                 :            : {
      85         [ +  + ]:    2351839 :   if (child->getRule() == ProofRule::SYMM)
      86                 :            :   {
      87                 :       2030 :     Assert(expected.isNull()
      88                 :            :            || child->getChildren()[0]->getResult() == expected);
      89                 :       2030 :     return child->getChildren()[0];
      90                 :            :   }
      91                 :    4699618 :   return mkNode(ProofRule::SYMM, {child}, {}, expected);
      92                 :            : }
      93                 :            : 
      94                 :       2555 : std::shared_ptr<ProofNode> ProofNodeManager::mkTrans(
      95                 :            :     const std::vector<std::shared_ptr<ProofNode>>& children, Node expected)
      96                 :            : {
      97 [ -  + ][ -  + ]:       2555 :   Assert(!children.empty());
                 [ -  - ]
      98         [ -  + ]:       2555 :   if (children.size() == 1)
      99                 :            :   {
     100                 :          0 :     Assert(expected.isNull() || children[0]->getResult() == expected);
     101                 :          0 :     return children[0];
     102                 :            :   }
     103                 :       2555 :   return mkNode(ProofRule::TRANS, children, {}, expected);
     104                 :            : }
     105                 :            : 
     106                 :    1313861 : std::shared_ptr<ProofNode> ProofNodeManager::mkScope(
     107                 :            :     std::shared_ptr<ProofNode> pf,
     108                 :            :     std::vector<Node>& assumps,
     109                 :            :     bool ensureClosed,
     110                 :            :     bool doMinimize,
     111                 :            :     Node expected)
     112                 :            : {
     113 [ +  + ][ +  - ]:    1313861 :   if (!ensureClosed && !doMinimize)
     114                 :            :   {
     115                 :    1159562 :     return mkNode(ProofRule::SCOPE, {pf}, assumps, expected);
     116                 :            :   }
     117         [ +  - ]:     734080 :   Trace("pnm-scope") << "ProofNodeManager::mkScope " << assumps << std::endl;
     118                 :            :   // we first ensure the assumptions are flattened
     119                 :     734080 :   std::unordered_set<Node> ac{assumps.begin(), assumps.end()};
     120                 :            :   // map from the rewritten form of assumptions to the original. This is only
     121                 :            :   // computed in the rare case when we need rewriting to match the
     122                 :            :   // assumptions. An example of this is for Boolean constant equalities in
     123                 :            :   // scoped proofs from the proof equality engine.
     124                 :     734080 :   std::unordered_map<Node, Node> acr;
     125                 :            :   // whether we have compute the map above
     126                 :     734080 :   bool computedAcr = false;
     127                 :            : 
     128                 :            :   // The free assumptions of the proof
     129                 :     734080 :   std::map<Node, std::vector<std::shared_ptr<ProofNode>>> famap;
     130                 :     734080 :   expr::getFreeAssumptionsMap(pf, famap);
     131                 :     734080 :   std::unordered_set<Node> acu;
     132                 :     734080 :   for (const std::pair<const Node, std::vector<std::shared_ptr<ProofNode>>>&
     133         [ +  + ]:    5505152 :            fa : famap)
     134                 :            :   {
     135                 :    4036992 :     Node a = fa.first;
     136         [ +  + ]:    4036992 :     if (ac.find(a) != ac.end())
     137                 :            :     {
     138                 :            :       // already covered by an assumption
     139                 :    3107192 :       acu.insert(a);
     140                 :    3107192 :       continue;
     141                 :            :     }
     142         [ +  - ]:     929800 :     Trace("pnm-scope") << "- try matching free assumption " << a << "\n";
     143                 :            :     // otherwise it may be due to symmetry?
     144                 :     929800 :     Node aeqSym = CDProof::getSymmFact(a);
     145         [ +  - ]:     929800 :     Trace("pnm-scope") << "  - try sym " << aeqSym << "\n";
     146                 :     929800 :     Node aMatch;
     147 [ +  + ][ +  - ]:     929800 :     if (!aeqSym.isNull() && ac.count(aeqSym))
                 [ +  + ]
     148                 :            :     {
     149         [ +  - ]:    1857816 :       Trace("pnm-scope") << "- reorient assumption " << aeqSym << " via " << a
     150                 :     928908 :                          << " for " << fa.second.size() << " proof nodes"
     151                 :     928908 :                          << std::endl;
     152                 :     928908 :       aMatch = aeqSym;
     153                 :            :     }
     154                 :            :     else
     155                 :            :     {
     156                 :            :       // trivial assumption (by rewriting)
     157                 :        892 :       Node ar = d_rewriter->rewrite(a);
     158         [ +  + ]:        892 :       if (ar == d_true)
     159                 :            :       {
     160         [ +  - ]:         20 :         Trace("pnm-scope") << "- justify trivial True assumption\n";
     161         [ +  + ]:         40 :         for (std::shared_ptr<ProofNode> pfs : fa.second)
     162                 :            :         {
     163 [ -  + ][ -  + ]:         20 :           Assert(pfs->getResult() == a);
                 [ -  - ]
     164                 :         40 :           updateNode(pfs.get(), ProofRule::MACRO_SR_PRED_INTRO, {}, {a});
     165                 :         20 :         }
     166         [ +  - ]:         20 :         Trace("pnm-scope") << "...finished" << std::endl;
     167                 :         20 :         acu.insert(a);
     168                 :         20 :         continue;
     169                 :         20 :       }
     170                 :            :       // Otherwise, may be derivable by rewriting. Note this is used in
     171                 :            :       // ensuring that proofs from the proof equality engine that involve
     172                 :            :       // equality with Boolean constants are closed.
     173         [ +  + ]:        872 :       if (!computedAcr)
     174                 :            :       {
     175                 :        395 :         computedAcr = true;
     176         [ +  + ]:       2884 :         for (const Node& acc : ac)
     177                 :            :         {
     178                 :       2489 :           Node accr = d_rewriter->rewrite(acc);
     179                 :       2489 :           acr[accr] = acc;
     180                 :       2489 :         }
     181                 :            :       }
     182         [ +  - ]:        872 :       Trace("pnm-scope") << "- rewritten: " << ar << std::endl;
     183                 :        872 :       std::unordered_map<Node, Node>::iterator itr = acr.find(ar);
     184         [ +  - ]:        872 :       if (itr != acr.end())
     185                 :            :       {
     186                 :        872 :         aMatch = itr->second;
     187                 :            :       }
     188         [ +  + ]:        892 :     }
     189                 :            : 
     190                 :            :     // if we found a match either by symmetry or rewriting, then we connect
     191                 :            :     // the assumption here.
     192         [ +  - ]:     929780 :     if (!aMatch.isNull())
     193                 :            :     {
     194                 :     929780 :       std::shared_ptr<ProofNode> pfaa = mkAssume(aMatch);
     195                 :            :       // must correct the orientation on this leaf
     196                 :     929780 :       std::vector<std::shared_ptr<ProofNode>> children;
     197                 :     929780 :       children.push_back(pfaa);
     198         [ +  + ]:    1859648 :       for (std::shared_ptr<ProofNode> pfs : fa.second)
     199                 :            :       {
     200 [ -  + ][ -  + ]:     929868 :         Assert(pfs->getResult() == a);
                 [ -  - ]
     201                 :            :         // use SYMM if possible
     202         [ +  + ]:     929868 :         if (aMatch == aeqSym)
     203                 :            :         {
     204         [ -  + ]:     928996 :           if (pfaa->getRule() == ProofRule::SYMM)
     205                 :            :           {
     206                 :          0 :             updateNode(pfs.get(), pfaa->getChildren()[0].get());
     207                 :            :           }
     208                 :            :           else
     209                 :            :           {
     210                 :     928996 :             updateNode(pfs.get(), ProofRule::SYMM, children, {});
     211                 :            :           }
     212                 :            :         }
     213                 :            :         else
     214                 :            :         {
     215                 :       1744 :           updateNode(
     216                 :            :               pfs.get(), ProofRule::MACRO_SR_PRED_TRANSFORM, children, {a});
     217                 :            :         }
     218                 :     929868 :       }
     219         [ +  - ]:     929780 :       Trace("pnm-scope") << "...finished" << std::endl;
     220                 :     929780 :       acu.insert(aMatch);
     221                 :     929780 :       continue;
     222                 :     929780 :     }
     223         [ -  - ]:          0 :     if (!ensureClosed)
     224                 :            :     {
     225                 :          0 :       continue;
     226                 :            :     }
     227                 :            :     // If we did not find a match, it is an error, since all free assumptions
     228                 :            :     // should be arguments to SCOPE.
     229                 :          0 :     std::stringstream ss;
     230                 :            : 
     231                 :          0 :     bool dumpProofTraceOn = TraceIsOn("dump-proof-error");
     232         [ -  - ]:          0 :     if (dumpProofTraceOn)
     233                 :            :     {
     234                 :          0 :       ss << "The proof : " << *pf << std::endl;
     235                 :            :     }
     236                 :          0 :     ss << std::endl << "Free assumption: " << a << std::endl;
     237         [ -  - ]:          0 :     for (const Node& aprint : ac)
     238                 :            :     {
     239                 :          0 :       ss << "- assumption: " << aprint << std::endl;
     240                 :            :     }
     241         [ -  - ]:          0 :     if (!dumpProofTraceOn)
     242                 :            :     {
     243                 :          0 :       ss << "Use -t dump-proof-error for details on proof" << std::endl;
     244                 :            :     }
     245                 :          0 :     Unreachable() << "Generated a proof that is not closed by the scope: "
     246                 :          0 :                   << ss.str() << std::endl;
     247                 :    4036992 :   }
     248         [ +  + ]:     734080 :   if (acu.size() < ac.size())
     249                 :            :   {
     250                 :            :     // All assumptions should match a free assumption; if one does not, then
     251                 :            :     // the explanation could have been smaller.
     252         [ +  + ]:     824619 :     for (const Node& a : ac)
     253                 :            :     {
     254         [ +  + ]:     777816 :       if (acu.find(a) == acu.end())
     255                 :            :       {
     256         [ +  - ]:     206042 :         Trace("pnm") << "ProofNodeManager::mkScope: assumption " << a
     257                 :          0 :                      << " does not match a free assumption in proof"
     258                 :     103021 :                      << std::endl;
     259                 :            :       }
     260                 :            :     }
     261                 :            :   }
     262 [ +  + ][ +  + ]:     734080 :   if (doMinimize && acu.size() < ac.size())
                 [ +  + ]
     263                 :            :   {
     264                 :      42314 :     assumps.clear();
     265                 :      42314 :     assumps.insert(assumps.end(), acu.begin(), acu.end());
     266                 :            :   }
     267         [ +  + ]:     691766 :   else if (ac.size() < assumps.size())
     268                 :            :   {
     269                 :            :     // remove duplicates to avoid redundant literals in clauses
     270                 :       1567 :     assumps.clear();
     271                 :       1567 :     assumps.insert(assumps.end(), ac.begin(), ac.end());
     272                 :            :   }
     273                 :     734080 :   Node minExpected;
     274                 :     734080 :   Node exp;
     275         [ +  + ]:     734080 :   if (assumps.empty())
     276                 :            :   {
     277                 :            :     // SCOPE with no arguments is a no-op, just return original
     278                 :       9303 :     return pf;
     279                 :            :   }
     280                 :     724777 :   Node conc = pf->getResult();
     281                 :     724777 :   NodeManager* nm = conc.getNodeManager();
     282         [ +  + ]:     724777 :   exp = assumps.size() == 1 ? assumps[0] : nm->mkNode(Kind::AND, assumps);
     283 [ +  + ][ +  + ]:     724777 :   if (conc.isConst() && !conc.getConst<bool>())
                 [ +  + ]
     284                 :            :   {
     285                 :     206380 :     minExpected = exp.notNode();
     286                 :            :   }
     287                 :            :   else
     288                 :            :   {
     289                 :     518397 :     minExpected = nm->mkNode(Kind::IMPLIES, exp, conc);
     290                 :            :   }
     291                 :    1449554 :   return mkNode(ProofRule::SCOPE, {pf}, assumps, minExpected);
     292                 :     734080 : }
     293                 :            : 
     294                 :    2171831 : bool ProofNodeManager::updateNode(
     295                 :            :     ProofNode* pn,
     296                 :            :     ProofRule id,
     297                 :            :     const std::vector<std::shared_ptr<ProofNode>>& children,
     298                 :            :     const std::vector<Node>& args)
     299                 :            : {
     300                 :    2171831 :   return updateNodeInternal(pn, id, children, args, true);
     301                 :            : }
     302                 :            : 
     303                 :    9793996 : bool ProofNodeManager::updateNode(ProofNode* pn, ProofNode* pnr)
     304                 :            : {
     305 [ -  + ][ -  + ]:    9793996 :   Assert(pn != nullptr);
                 [ -  - ]
     306 [ -  + ][ -  + ]:    9793996 :   Assert(pnr != nullptr);
                 [ -  - ]
     307         [ +  + ]:    9793996 :   if (pn == pnr)
     308                 :            :   {
     309                 :            :     // same node, no update necessary
     310                 :      20626 :     return true;
     311                 :            :   }
     312         [ -  + ]:    9773370 :   if (pn->getResult() != pnr->getResult())
     313                 :            :   {
     314                 :          0 :     return false;
     315                 :            :   }
     316                 :            :   // copy whether we did the check
     317                 :    9773370 :   pn->d_provenChecked = pnr->d_provenChecked;
     318                 :            :   // can shortcut re-check of rule
     319                 :    9773370 :   return updateNodeInternal(
     320                 :    9773370 :       pn, pnr->getRule(), pnr->getChildren(), pnr->getArguments(), false);
     321                 :            : }
     322                 :            : 
     323                 :    2211702 : void ProofNodeManager::ensureChecked(ProofNode* pn)
     324                 :            : {
     325         [ +  + ]:    2211702 :   if (pn->d_provenChecked)
     326                 :            :   {
     327                 :            :     // already checked
     328                 :      32380 :     return;
     329                 :            :   }
     330                 :            :   // directly call the proof checker
     331                 :    2179322 :   Node res = d_checker->check(pn, pn->getResult());
     332                 :    2179322 :   pn->d_provenChecked = true;
     333                 :            :   // should have the correct result
     334 [ -  + ][ -  + ]:    2179322 :   Assert(res == pn->d_proven);
                 [ -  - ]
     335                 :    2179322 : }
     336                 :            : 
     337                 :   68409885 : Node ProofNodeManager::checkInternal(
     338                 :            :     ProofRule id,
     339                 :            :     const std::vector<std::shared_ptr<ProofNode>>& children,
     340                 :            :     const std::vector<Node>& args,
     341                 :            :     Node expected,
     342                 :            :     bool& didCheck)
     343                 :            : {
     344                 :            :   // if the user supplied an expected result, then we trust it if we are in
     345                 :            :   // a proof checking mode that does not eagerly check rule applications
     346         [ +  + ]:   68409885 :   if (!expected.isNull())
     347                 :            :   {
     348         [ +  + ]:   65662059 :     if (d_opts.proof.proofCheck == options::ProofCheckMode::LAZY
     349         [ +  + ]:   37516324 :         || d_opts.proof.proofCheck == options::ProofCheckMode::NONE)
     350                 :            :     {
     351                 :   65554273 :       return expected;
     352                 :            :     }
     353                 :            :   }
     354                 :            :   // check with the checker, which takes expected as argument
     355                 :    2855612 :   Node res = d_checker->check(id, children, args, expected);
     356                 :    2855612 :   didCheck = true;
     357 [ -  + ][ -  + ]:    2855612 :   Assert(!res.isNull())
                 [ -  - ]
     358                 :          0 :       << "ProofNodeManager::checkInternal: failed to check proof";
     359                 :    2855612 :   return res;
     360                 :    2855612 : }
     361                 :            : 
     362                 :   44245927 : ProofChecker* ProofNodeManager::getChecker() const { return d_checker; }
     363                 :            : 
     364                 :    1473053 : ProofNode* ProofNodeManager::cancelDoubleSymm(ProofNode* pn)
     365                 :            : {
     366                 :            :   // processed is almost always size <= 1
     367                 :    1473053 :   std::vector<ProofNode*> processed;
     368         [ +  + ]:    1473128 :   while (pn->getRule() == ProofRule::SYMM)
     369                 :            :   {
     370                 :    1473053 :     std::shared_ptr<ProofNode> pnc = pn->getChildren()[0];
     371         [ +  + ]:    1473053 :     if (pnc->getRule() == ProofRule::SYMM)
     372                 :            :     {
     373                 :         75 :       pn = pnc->getChildren()[0].get();
     374         [ -  + ]:         75 :       if (std::find(processed.begin(), processed.end(), pn) != processed.end())
     375                 :            :       {
     376                 :          0 :         Unreachable()
     377                 :          0 :             << "Cyclic proof encountered when cancelling double symmetry";
     378                 :            :       }
     379                 :         75 :       processed.push_back(pn);
     380                 :            :     }
     381                 :            :     else
     382                 :            :     {
     383                 :    1472978 :       break;
     384                 :            :     }
     385         [ +  + ]:    1473053 :   }
     386                 :    1473053 :   return pn;
     387                 :    1473053 : }
     388                 :            : 
     389                 :   11945201 : bool ProofNodeManager::updateNodeInternal(
     390                 :            :     ProofNode* pn,
     391                 :            :     ProofRule id,
     392                 :            :     const std::vector<std::shared_ptr<ProofNode>>& children,
     393                 :            :     const std::vector<Node>& args,
     394                 :            :     bool needsCheck)
     395                 :            : {
     396 [ -  + ][ -  + ]:   11945201 :   Assert(pn != nullptr);
                 [ -  - ]
     397                 :            :   // ---------------- check for cyclic
     398         [ +  + ]:   11945201 :   if (d_opts.proof.proofCheck == options::ProofCheckMode::EAGER)
     399                 :            :   {
     400                 :      17519 :     std::unordered_set<const ProofNode*> visited;
     401         [ +  + ]:      29415 :     for (const std::shared_ptr<ProofNode>& cpc : children)
     402                 :            :     {
     403         [ -  + ]:      11896 :       if (expr::containsSubproof(cpc.get(), pn, visited))
     404                 :            :       {
     405                 :          0 :         std::stringstream ss;
     406                 :          0 :         ss << "ProofNodeManager::updateNode: attempting to make cyclic proof! "
     407                 :          0 :            << id << " " << pn->getResult() << ", children = " << std::endl;
     408         [ -  - ]:          0 :         for (const std::shared_ptr<ProofNode>& cp : children)
     409                 :            :         {
     410                 :          0 :           ss << "  " << cp->getRule() << " " << cp->getResult() << std::endl;
     411                 :            :         }
     412                 :          0 :         ss << "Full children:" << std::endl;
     413         [ -  - ]:          0 :         for (const std::shared_ptr<ProofNode>& cp : children)
     414                 :            :         {
     415                 :          0 :           ss << "  - ";
     416                 :          0 :           cp->printDebug(ss);
     417                 :          0 :           ss << std::endl;
     418                 :            :         }
     419                 :          0 :         Unreachable() << ss.str();
     420                 :          0 :       }
     421                 :            :     }
     422                 :      17519 :   }
     423                 :            :   // ---------------- end check for cyclic
     424                 :            : 
     425                 :            :   // should have already computed what is proven
     426 [ -  + ][ -  + ]:   11945201 :   Assert(!pn->d_proven.isNull())
                 [ -  - ]
     427                 :          0 :       << "ProofNodeManager::updateProofNode: invalid proof provided";
     428         [ +  + ]:   11945201 :   if (needsCheck)
     429                 :            :   {
     430                 :            :     // We expect to prove the same thing as before
     431                 :    2171831 :     bool didCheck = false;
     432                 :    2171831 :     Node res = checkInternal(id, children, args, pn->d_proven, didCheck);
     433         [ -  + ]:    2171831 :     if (res.isNull())
     434                 :            :     {
     435                 :            :       // if it was invalid, then we do not update
     436                 :          0 :       return false;
     437                 :            :     }
     438                 :            :     // proven field should already be the same as the result
     439 [ -  + ][ -  + ]:    2171831 :     Assert(res == pn->d_proven);
                 [ -  - ]
     440                 :    2171831 :     pn->d_provenChecked = didCheck;
     441         [ +  - ]:    2171831 :   }
     442                 :            : 
     443                 :            :   // we update its value
     444                 :   11945201 :   pn->setValue(id, children, args);
     445                 :   11945201 :   return true;
     446                 :            : }
     447                 :            : 
     448                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14