LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/expr - match_trie.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 113 115 98.3 %
Date: 2026-04-26 10:45:53 Functions: 4 4 100.0 %
Branches: 58 82 70.7 %

           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                 :            :  * Implements a match trie, also known as a discrimination tree.
      11                 :            :  */
      12                 :            : 
      13                 :            : #include "expr/match_trie.h"
      14                 :            : 
      15                 :            : using namespace cvc5::internal::kind;
      16                 :            : 
      17                 :            : namespace cvc5::internal {
      18                 :            : namespace expr {
      19                 :            : 
      20                 :       2283 : bool MatchTrie::getMatches(Node n, NotifyMatch* ntm)
      21                 :            : {
      22                 :       2283 :   std::vector<Node> vars;
      23                 :       2283 :   std::vector<Node> subs;
      24                 :       2283 :   std::map<Node, Node> smap;
      25                 :            : 
      26                 :       2283 :   std::vector<std::vector<Node> > visit;
      27                 :       2283 :   std::vector<MatchTrie*> visit_trie;
      28                 :       2283 :   std::vector<int> visit_var_index;
      29                 :       2283 :   std::vector<bool> visit_bound_var;
      30                 :            : 
      31                 :       4566 :   visit.push_back(std::vector<Node>{n});
      32                 :       2283 :   visit_trie.push_back(this);
      33                 :       2283 :   visit_var_index.push_back(-1);
      34                 :       2283 :   visit_bound_var.push_back(false);
      35         [ +  + ]:     260985 :   while (!visit.empty())
      36                 :            :   {
      37                 :     258702 :     std::vector<Node> cvisit = visit.back();
      38                 :     258702 :     MatchTrie* curr = visit_trie.back();
      39         [ +  + ]:     258702 :     if (cvisit.empty())
      40                 :            :     {
      41 [ -  + ][ -  + ]:      31480 :       Assert(n
                 [ -  - ]
      42                 :            :              == curr->d_data.substitute(
      43                 :            :                  vars.begin(), vars.end(), subs.begin(), subs.end()));
      44         [ +  - ]:      31480 :       Trace("match-debug") << "notify : " << curr->d_data << std::endl;
      45         [ -  + ]:      31480 :       if (!ntm->notify(n, curr->d_data, vars, subs))
      46                 :            :       {
      47                 :          0 :         return false;
      48                 :            :       }
      49                 :      31480 :       visit.pop_back();
      50                 :      31480 :       visit_trie.pop_back();
      51                 :      31480 :       visit_var_index.pop_back();
      52                 :      31480 :       visit_bound_var.pop_back();
      53                 :            :     }
      54                 :            :     else
      55                 :            :     {
      56                 :     227222 :       Node cn = cvisit.back();
      57         [ +  - ]:     454444 :       Trace("match-debug") << "traverse : " << cn << " at depth "
      58                 :     227222 :                            << visit.size() << std::endl;
      59                 :     227222 :       unsigned index = visit.size() - 1;
      60                 :     227222 :       int vindex = visit_var_index[index];
      61         [ +  + ]:     227222 :       if (vindex == -1)
      62                 :            :       {
      63         [ +  + ]:      70837 :         if (!cn.isVar())
      64                 :            :         {
      65         [ +  + ]:      24774 :           Node op = cn.hasOperator() ? cn.getOperator() : cn;
      66         [ +  + ]:      24774 :           unsigned nchild = cn.hasOperator() ? cn.getNumChildren() : 0;
      67                 :            :           std::map<unsigned, MatchTrie>::iterator itu =
      68                 :      24774 :               curr->d_children[op].find(nchild);
      69         [ +  + ]:      24774 :           if (itu != curr->d_children[op].end())
      70                 :            :           {
      71                 :            :             // recurse on the operator or self
      72                 :      18388 :             cvisit.pop_back();
      73         [ +  + ]:      18388 :             if (cn.hasOperator())
      74                 :            :             {
      75         [ +  + ]:      27424 :               for (const Node& cnc : cn)
      76                 :            :               {
      77                 :      19188 :                 cvisit.push_back(cnc);
      78                 :      19188 :               }
      79                 :            :             }
      80         [ +  - ]:      18388 :             Trace("match-debug") << "recurse op : " << op << std::endl;
      81                 :      18388 :             visit.push_back(cvisit);
      82                 :      18388 :             visit_trie.push_back(&itu->second);
      83                 :      18388 :             visit_var_index.push_back(-1);
      84                 :      18388 :             visit_bound_var.push_back(false);
      85                 :            :           }
      86                 :      24774 :         }
      87                 :      70837 :         visit_var_index[index]++;
      88                 :            :       }
      89                 :            :       else
      90                 :            :       {
      91                 :            :         // clean up if we previously bound a variable
      92         [ +  + ]:     156385 :         if (visit_bound_var[index])
      93                 :            :         {
      94 [ -  + ][ -  + ]:      81284 :           Assert(!vars.empty());
                 [ -  - ]
      95                 :      81284 :           smap.erase(vars.back());
      96                 :      81284 :           vars.pop_back();
      97                 :      81284 :           subs.pop_back();
      98                 :      81284 :           visit_bound_var[index] = false;
      99                 :            :         }
     100                 :            : 
     101         [ +  + ]:     156385 :         if (vindex == static_cast<int>(curr->d_vars.size()))
     102                 :            :         {
     103         [ +  - ]:     141674 :           Trace("match-debug")
     104                 :          0 :               << "finished checking " << curr->d_vars.size()
     105                 :      70837 :               << " variables at depth " << visit.size() << std::endl;
     106                 :            :           // finished
     107                 :      70837 :           visit.pop_back();
     108                 :      70837 :           visit_trie.pop_back();
     109                 :      70837 :           visit_var_index.pop_back();
     110                 :      70837 :           visit_bound_var.pop_back();
     111                 :            :         }
     112                 :            :         else
     113                 :            :         {
     114         [ +  - ]:     171096 :           Trace("match-debug") << "check variable #" << vindex << " at depth "
     115                 :      85548 :                                << visit.size() << std::endl;
     116 [ -  + ][ -  + ]:      85548 :           Assert(vindex < static_cast<int>(curr->d_vars.size()));
                 [ -  - ]
     117                 :            :           // recurse on variable?
     118                 :      85548 :           Node var = curr->d_vars[vindex];
     119                 :      85548 :           bool recurse = true;
     120                 :            :           // check if it is already bound
     121                 :      85548 :           std::map<Node, Node>::iterator its = smap.find(var);
     122         [ +  + ]:      85548 :           if (its != smap.end())
     123                 :            :           {
     124         [ +  + ]:       2274 :             if (its->second != cn)
     125                 :            :             {
     126                 :       1912 :               recurse = false;
     127                 :            :             }
     128                 :            :           }
     129         [ +  + ]:     249822 :           else if (!CVC5_EQUAL(var.getType(), cn.getType()))
     130                 :            :           {
     131                 :       1990 :             recurse = false;
     132                 :            :           }
     133                 :            :           else
     134                 :            :           {
     135                 :      81284 :             vars.push_back(var);
     136                 :      81284 :             subs.push_back(cn);
     137                 :      81284 :             smap[var] = cn;
     138                 :      81284 :             visit_bound_var[index] = true;
     139                 :            :           }
     140         [ +  + ]:      85548 :           if (recurse)
     141                 :            :           {
     142         [ +  - ]:      81646 :             Trace("match-debug") << "recurse var : " << var << std::endl;
     143                 :      81646 :             cvisit.pop_back();
     144                 :      81646 :             visit.push_back(cvisit);
     145                 :      81646 :             visit_trie.push_back(&curr->d_children[var][0]);
     146                 :      81646 :             visit_var_index.push_back(-1);
     147                 :      81646 :             visit_bound_var.push_back(false);
     148                 :            :           }
     149                 :      85548 :           visit_var_index[index]++;
     150                 :      85548 :         }
     151                 :            :       }
     152                 :     227222 :     }
     153         [ +  - ]:     258702 :   }
     154                 :       2283 :   return true;
     155                 :       2283 : }
     156                 :            : 
     157                 :       2288 : void MatchTrie::addTerm(Node n)
     158                 :            : {
     159 [ -  + ][ -  + ]:       2288 :   Assert(!n.isNull());
                 [ -  - ]
     160                 :       2288 :   std::vector<Node> visit;
     161                 :       2288 :   visit.push_back(n);
     162                 :       2288 :   MatchTrie* curr = this;
     163         [ +  + ]:      17178 :   while (!visit.empty())
     164                 :            :   {
     165                 :      14890 :     Node cn = visit.back();
     166                 :      14890 :     visit.pop_back();
     167         [ +  + ]:      14890 :     if (cn.hasOperator())
     168                 :            :     {
     169                 :       5349 :       curr = &(curr->d_children[cn.getOperator()][cn.getNumChildren()]);
     170         [ +  + ]:      17951 :       for (const Node& cnc : cn)
     171                 :            :       {
     172                 :      12602 :         visit.push_back(cnc);
     173                 :      12602 :       }
     174                 :            :     }
     175                 :            :     else
     176                 :            :     {
     177                 :       9541 :       if (cn.isVar()
     178 [ +  + ][ +  + ]:      22189 :           && std::find(curr->d_vars.begin(), curr->d_vars.end(), cn)
     179         [ +  + ]:      22189 :                  == curr->d_vars.end())
     180                 :            :       {
     181                 :       4364 :         curr->d_vars.push_back(cn);
     182                 :            :       }
     183                 :       9541 :       curr = &(curr->d_children[cn][0]);
     184                 :            :     }
     185                 :      14890 :   }
     186                 :       2288 :   curr->d_data = n;
     187                 :       2288 : }
     188                 :            : 
     189                 :         54 : void MatchTrie::clear()
     190                 :            : {
     191                 :         54 :   d_children.clear();
     192                 :         54 :   d_vars.clear();
     193                 :         54 :   d_data = Node::null();
     194                 :         54 : }
     195                 :            : 
     196                 :            : }  // namespace expr
     197                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14