LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/proof - proof_node_algorithm.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 129 140 92.1 %
Date: 2024-11-18 12:41:18 Functions: 7 10 70.0 %
Branches: 56 62 90.3 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * Top contributors (to current version):
       3                 :            :  *   Andrew Reynolds, Haniel Barbosa, Hans-Joerg Schurr
       4                 :            :  *
       5                 :            :  * This file is part of the cvc5 project.
       6                 :            :  *
       7                 :            :  * Copyright (c) 2009-2024 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                 :            :  * Implementation of proof node algorithm utilities.
      14                 :            :  */
      15                 :            : 
      16                 :            : #include "proof/proof_node_algorithm.h"
      17                 :            : 
      18                 :            : #include "proof/proof_node.h"
      19                 :            : #include "proof/proof_rule_checker.h"
      20                 :            : 
      21                 :            : namespace cvc5::internal {
      22                 :            : namespace expr {
      23                 :            : 
      24                 :     382505 : void getFreeAssumptions(ProofNode* pn, std::vector<Node>& assump)
      25                 :            : {
      26                 :     765010 :   std::map<Node, std::vector<std::shared_ptr<ProofNode>>> amap;
      27                 :            :   std::shared_ptr<ProofNode> spn = std::make_shared<ProofNode>(
      28                 :     765010 :       pn->getRule(), pn->getChildren(), pn->getArguments());
      29                 :     382505 :   getFreeAssumptionsMap(spn, amap);
      30                 :     768015 :   for (const std::pair<const Node, std::vector<std::shared_ptr<ProofNode>>>& p :
      31         [ +  + ]:    1918540 :        amap)
      32                 :            :   {
      33                 :     768015 :     assump.push_back(p.first);
      34                 :            :   }
      35                 :     382505 : }
      36                 :            : 
      37                 :    2392270 : void getFreeAssumptionsMap(
      38                 :            :     std::shared_ptr<ProofNode> pn,
      39                 :            :     std::map<Node, std::vector<std::shared_ptr<ProofNode>>>& amap)
      40                 :            : {
      41                 :            :   // proof should not be cyclic
      42                 :    4784550 :   std::unordered_set<ProofNode*> visited;
      43                 :    2392270 :   std::unordered_set<ProofNode*>::iterator it;
      44                 :    4784550 :   std::vector<std::shared_ptr<ProofNode>> visit;
      45                 :    2392270 :   std::shared_ptr<ProofNode> cur;
      46                 :    2392270 :   visit.push_back(pn);
      47                 :  174166000 :   do
      48                 :            :   {
      49                 :  176558000 :     cur = visit.back();
      50                 :  176558000 :     visit.pop_back();
      51                 :  176558000 :     it = visited.find(cur.get());
      52                 :  176558000 :     const std::vector<Node>& cargs = cur->getArguments();
      53         [ +  + ]:  176558000 :     if (it == visited.end())
      54                 :            :     {
      55                 :   66738200 :       visited.insert(cur.get());
      56                 :   66738200 :       ProofRule id = cur->getRule();
      57         [ +  + ]:   66738200 :       if (id == ProofRule::ASSUME)
      58                 :            :       {
      59 [ -  + ][ -  + ]:   17062600 :         Assert(cargs.size() == 1);
                 [ -  - ]
      60                 :   34125100 :         Node f = cargs[0];
      61                 :   17062600 :         amap[f].push_back(cur);
      62                 :            :       }
      63                 :            :       else
      64                 :            :       {
      65                 :   49675600 :         const std::vector<std::shared_ptr<ProofNode>>& cs = cur->getChildren();
      66         [ +  + ]:   49675600 :         if (id == ProofRule::SCOPE)
      67                 :            :         {
      68                 :            :           // make a recursive call, which is bound in depth by the number of
      69                 :            :           // nested SCOPE (never expected to be more than 1 or 2).
      70                 :    1857370 :           std::map<Node, std::vector<std::shared_ptr<ProofNode>>> amapTmp;
      71                 :     928686 :           expr::getFreeAssumptionsMap(cs[0], amapTmp);
      72                 :    4440640 :           for (std::pair<const Node, std::vector<std::shared_ptr<ProofNode>>>&
      73         [ +  + ]:    9809980 :                    a : amapTmp)
      74                 :            :           {
      75         [ +  + ]:    4440640 :             if (std::find(cargs.begin(), cargs.end(), a.first) == cargs.end())
      76                 :            :             {
      77                 :    1036640 :               std::vector<std::shared_ptr<ProofNode>>& pfs = amap[a.first];
      78                 :    1036640 :               pfs.insert(pfs.end(), a.second.begin(), a.second.end());
      79                 :            :             }
      80                 :            :           }
      81                 :     928686 :           continue;
      82                 :            :         }
      83                 :            :         // traverse on children
      84                 :   48746900 :         visit.insert(visit.end(), cs.begin(), cs.end());
      85                 :            :       }
      86                 :            :     }
      87         [ +  + ]:  176558000 :   } while (!visit.empty());
      88                 :    2392270 : }
      89                 :            : 
      90                 :       2334 : void getSubproofRule(std::shared_ptr<ProofNode> pn,
      91                 :            :                      ProofRule r,
      92                 :            :                      std::vector<std::shared_ptr<ProofNode>>& pfs)
      93                 :            : {
      94                 :       2334 :   std::unordered_set<ProofRule> rs{r};
      95                 :       2334 :   getSubproofRules(pn, rs, pfs);
      96                 :       2334 : }
      97                 :            : 
      98                 :       2340 : void getSubproofRules(std::shared_ptr<ProofNode> pn,
      99                 :            :                       std::unordered_set<ProofRule> rs,
     100                 :            :                       std::vector<std::shared_ptr<ProofNode>>& pfs)
     101                 :            : {
     102                 :            :   // proof should not be cyclic
     103                 :       4680 :   std::unordered_set<ProofNode*> visited;
     104                 :       2340 :   std::unordered_set<ProofNode*>::iterator it;
     105                 :       4680 :   std::vector<std::shared_ptr<ProofNode>> visit;
     106                 :       2340 :   std::shared_ptr<ProofNode> cur;
     107                 :       2340 :   visit.push_back(pn);
     108                 :      14735 :   do
     109                 :            :   {
     110                 :      17075 :     cur = visit.back();
     111                 :      17075 :     visit.pop_back();
     112                 :      17075 :     it = visited.find(cur.get());
     113         [ +  + ]:      17075 :     if (it == visited.end())
     114                 :            :     {
     115                 :      17024 :       visited.insert(cur.get());
     116         [ +  + ]:      17024 :       if (rs.find(cur->getRule()) != rs.end())
     117                 :            :       {
     118                 :       3025 :         pfs.push_back(cur);
     119                 :            :       }
     120                 :            :       else
     121                 :            :       {
     122                 :      13999 :         const std::vector<std::shared_ptr<ProofNode>>& cs = cur->getChildren();
     123                 :            :         // traverse on children
     124                 :      13999 :         visit.insert(visit.end(), cs.begin(), cs.end());
     125                 :            :       }
     126                 :            :     }
     127         [ +  + ]:      17075 :   } while (!visit.empty());
     128                 :       2340 : }
     129                 :            : 
     130                 :    8295940 : bool containsAssumption(const ProofNode* pn,
     131                 :            :                         std::unordered_map<const ProofNode*, bool>& caMap,
     132                 :            :                         const std::unordered_set<Node>& allowed)
     133                 :            : {
     134                 :   16591900 :   std::unordered_map<const ProofNode*, bool> visited;
     135                 :    8295940 :   std::unordered_map<const ProofNode*, bool>::iterator it;
     136                 :    8295940 :   std::vector<const ProofNode*> visit;
     137                 :    8295940 :   visit.push_back(pn);
     138                 :    8295940 :   bool foundAssumption = false;
     139                 :            :   const ProofNode* cur;
     140         [ +  + ]:   41902200 :   while (!visit.empty())
     141                 :            :   {
     142                 :   33606200 :     cur = visit.back();
     143                 :   33606200 :     visit.pop_back();
     144                 :            :     // have we already computed?
     145                 :   33606200 :     it = caMap.find(cur);
     146         [ +  + ]:   33606200 :     if (it != caMap.end())
     147                 :            :     {
     148                 :            :       // if cached, we set found assumption to true if applicable and continue
     149         [ +  + ]:   17043400 :       if (it->second)
     150                 :            :       {
     151                 :    4985250 :         foundAssumption = true;
     152                 :            :       }
     153                 :   17043400 :       continue;
     154                 :            :     }
     155                 :   16562800 :     it = visited.find(cur);
     156         [ +  + ]:   16562800 :     if (it == visited.end())
     157                 :            :     {
     158                 :    8636600 :       ProofRule r = cur->getRule();
     159         [ +  + ]:    8636600 :       if (r == ProofRule::ASSUME)
     160                 :            :       {
     161                 :     710054 :         bool ret = allowed.find(cur->getArguments()[0]) == allowed.end();
     162                 :     710054 :         visited[cur] = ret;
     163                 :     710054 :         caMap[cur] = ret;
     164                 :     710054 :         foundAssumption = ret;
     165                 :            :       }
     166         [ +  + ]:    7926540 :       else if (!foundAssumption)
     167                 :            :       {
     168                 :            :         // if we haven't found an assumption yet, recurse. Otherwise, we will
     169                 :            :         // not bother computing whether this subproof contains an assumption
     170                 :            :         // since we know its parent already contains one by another child.
     171                 :    7926240 :         visited[cur] = false;
     172                 :    7926240 :         visit.push_back(cur);
     173                 :            :         const std::vector<std::shared_ptr<ProofNode>>& children =
     174                 :    7926240 :             cur->getChildren();
     175         [ +  + ]:   25310300 :         for (const std::shared_ptr<ProofNode>& cp : children)
     176                 :            :         {
     177                 :   17384000 :           visit.push_back(cp.get());
     178                 :            :         }
     179                 :            :       }
     180                 :            :     }
     181         [ +  - ]:    7926240 :     else if (!it->second)
     182                 :            :     {
     183                 :    7926240 :       visited[cur] = true;
     184                 :            :       // we contain an assumption if we've found an assumption in a child
     185                 :    7926240 :       caMap[cur] = foundAssumption;
     186                 :            :     }
     187                 :            :   }
     188                 :   16591900 :   return caMap[cur];
     189                 :            : }
     190                 :          0 : bool containsAssumption(const ProofNode* pn,
     191                 :            :                         std::unordered_map<const ProofNode*, bool>& caMap)
     192                 :            : {
     193                 :          0 :   std::unordered_set<Node> allowed;
     194                 :          0 :   return containsAssumption(pn, caMap, allowed);
     195                 :            : }
     196                 :            : 
     197                 :          0 : bool containsAssumption(const ProofNode* pn)
     198                 :            : {
     199                 :          0 :   std::unordered_map<const ProofNode*, bool> caMap;
     200                 :          0 :   std::unordered_set<Node> allowed;
     201                 :          0 :   return containsAssumption(pn, caMap, allowed);
     202                 :            : }
     203                 :            : 
     204                 :          0 : bool containsSubproof(ProofNode* pn, ProofNode* pnc)
     205                 :            : {
     206                 :          0 :   std::unordered_set<const ProofNode*> visited;
     207                 :          0 :   return containsSubproof(pn, pnc, visited);
     208                 :            : }
     209                 :            : 
     210                 :      10486 : bool containsSubproof(ProofNode* pn,
     211                 :            :                       ProofNode* pnc,
     212                 :            :                       std::unordered_set<const ProofNode*>& visited)
     213                 :            : {
     214                 :      10486 :   std::unordered_map<const ProofNode*, bool>::iterator it;
     215                 :      20972 :   std::vector<const ProofNode*> visit;
     216                 :      10486 :   visit.push_back(pn);
     217                 :            :   const ProofNode* cur;
     218         [ +  + ]:     313355 :   while (!visit.empty())
     219                 :            :   {
     220                 :     302869 :     cur = visit.back();
     221                 :     302869 :     visit.pop_back();
     222         [ +  + ]:     302869 :     if (visited.find(cur) == visited.end())
     223                 :            :     {
     224                 :     263487 :       visited.insert(cur);
     225         [ -  + ]:     263487 :       if (cur == pnc)
     226                 :            :       {
     227                 :          0 :         return true;
     228                 :            :       }
     229                 :            :       const std::vector<std::shared_ptr<ProofNode>>& children =
     230                 :     263487 :           cur->getChildren();
     231         [ +  + ]:     555870 :       for (const std::shared_ptr<ProofNode>& cp : children)
     232                 :            :       {
     233                 :     292383 :         visit.push_back(cp.get());
     234                 :            :       }
     235                 :            :     }
     236                 :            :   }
     237                 :      10486 :   return false;
     238                 :            : }
     239                 :            : 
     240                 :    1962610 : ProofRule getCongRule(const Node& n, std::vector<Node>& args)
     241                 :            : {
     242                 :    1962610 :   Kind k = n.getKind();
     243                 :    1962610 :   ProofRule r = ProofRule::CONG;
     244 [ +  + ][ +  + ]:    1962610 :   switch (k)
     245                 :            :   {
     246                 :     604686 :     case Kind::APPLY_UF:
     247                 :            :     case Kind::DISTINCT:
     248                 :            :     case Kind::FLOATINGPOINT_LT:
     249                 :            :     case Kind::FLOATINGPOINT_LEQ:
     250                 :            :     case Kind::FLOATINGPOINT_GT:
     251                 :            :     case Kind::FLOATINGPOINT_GEQ:
     252                 :            :     case Kind::NULLABLE_LIFT:
     253                 :            :     case Kind::APPLY_INDEXED_SYMBOLIC:
     254                 :            :       // takes arbitrary but we use CONG
     255                 :     604686 :       break;
     256                 :       1048 :     case Kind::HO_APPLY:
     257                 :            :       // Use HO_CONG, since HO_APPLY is encoded as native function application.
     258                 :            :       // This requires no arguments so we return.
     259                 :       1048 :       r = ProofRule::HO_CONG;
     260                 :       1048 :       break;
     261                 :       7357 :     case Kind::APPLY_CONSTRUCTOR:
     262                 :            :       // tuples are n-ary, others are fixed
     263         [ +  + ]:       7357 :       r = n.getType().isTuple() ? ProofRule::NARY_CONG : ProofRule::CONG;
     264                 :       7357 :       break;
     265                 :    1349520 :     default:
     266         [ +  + ]:    1349520 :       if (NodeManager::isNAryKind(k))
     267                 :            :       {
     268                 :            :         // n-ary operators that are not handled as exceptions above use
     269                 :            :         // NARY_CONG
     270                 :     462876 :         r = ProofRule::NARY_CONG;
     271                 :            :       }
     272                 :    1349520 :       break;
     273                 :            :   }
     274                 :            :   // Add the arguments
     275                 :    1962610 :   args.push_back(ProofRuleChecker::mkKindNode(k));
     276         [ +  + ]:    1962610 :   if (kind::metaKindOf(k) == kind::metakind::PARAMETERIZED)
     277                 :            :   {
     278                 :     649936 :     args.push_back(n.getOperator());
     279                 :            :   }
     280         [ +  + ]:    1312670 :   else if (n.isClosure())
     281                 :            :   {
     282                 :            :     // bound variable list is an argument for closure over congruence
     283                 :      16173 :     args.push_back(n[0]);
     284                 :            :   }
     285                 :    1962610 :   return r;
     286                 :            : }
     287                 :            : 
     288                 :            : }  // namespace expr
     289                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14