LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/theory/quantifiers/ematching - ho_trigger.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 228 254 89.8 %
Date: 2025-02-14 14:34:19 Functions: 9 10 90.0 %
Branches: 140 244 57.4 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * Top contributors (to current version):
       3                 :            :  *   Andrew Reynolds, Aina Niemetz, 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                 :            :  * Implementation of higher-order trigger class.
      14                 :            :  */
      15                 :            : 
      16                 :            : #include "theory/quantifiers/ematching/ho_trigger.h"
      17                 :            : 
      18                 :            : #include <stack>
      19                 :            : 
      20                 :            : #include "theory/quantifiers/ho_term_database.h"
      21                 :            : #include "theory/quantifiers/instantiate.h"
      22                 :            : #include "theory/quantifiers/quantifiers_inference_manager.h"
      23                 :            : #include "theory/quantifiers/quantifiers_registry.h"
      24                 :            : #include "theory/quantifiers/quantifiers_state.h"
      25                 :            : #include "theory/quantifiers/term_registry.h"
      26                 :            : #include "theory/quantifiers/term_util.h"
      27                 :            : #include "theory/uf/theory_uf_rewriter.h"
      28                 :            : #include "util/hash.h"
      29                 :            : 
      30                 :            : using namespace cvc5::internal::kind;
      31                 :            : 
      32                 :            : namespace cvc5::internal {
      33                 :            : namespace theory {
      34                 :            : namespace quantifiers {
      35                 :            : namespace inst {
      36                 :            : 
      37                 :        230 : HigherOrderTrigger::HigherOrderTrigger(
      38                 :            :     Env& env,
      39                 :            :     QuantifiersState& qs,
      40                 :            :     QuantifiersInferenceManager& qim,
      41                 :            :     QuantifiersRegistry& qr,
      42                 :            :     TermRegistry& tr,
      43                 :            :     Node q,
      44                 :            :     std::vector<Node>& nodes,
      45                 :            :     std::map<Node, std::vector<Node> >& ho_apps,
      46                 :        230 :     bool isUser)
      47                 :        230 :     : Trigger(env, qs, qim, qr, tr, q, nodes, isUser), d_ho_var_apps(ho_apps)
      48                 :            : {
      49                 :        230 :   NodeManager* nm = nodeManager();
      50                 :            :   // process the higher-order variable applications
      51         [ +  + ]:        468 :   for (std::pair<const Node, std::vector<Node> >& as : d_ho_var_apps)
      52                 :            :   {
      53                 :        476 :     Node n = as.first;
      54                 :        238 :     d_ho_var_list.push_back(n);
      55                 :        476 :     TypeNode tn = n.getType();
      56 [ -  + ][ -  + ]:        238 :     Assert(tn.isFunction());
                 [ -  - ]
      57         [ -  + ]:        238 :     if (TraceIsOn("ho-quant-trigger"))
      58                 :            :     {
      59         [ -  - ]:          0 :       Trace("ho-quant-trigger") << "  have " << as.second.size();
      60         [ -  - ]:          0 :       Trace("ho-quant-trigger") << " patterns with variable operator " << n
      61                 :          0 :                                 << ":" << std::endl;
      62         [ -  - ]:          0 :       for (unsigned j = 0; j < as.second.size(); j++)
      63                 :            :       {
      64         [ -  - ]:          0 :         Trace("ho-quant-trigger") << "  " << as.second[j] << std::endl;
      65                 :            :       }
      66                 :            :     }
      67         [ +  - ]:        238 :     if (d_ho_var_types.find(tn) == d_ho_var_types.end())
      68                 :            :     {
      69         [ +  - ]:        476 :       Trace("ho-quant-trigger") << "  type " << tn
      70                 :        238 :                                 << " needs higher-order matching." << std::endl;
      71                 :        238 :       d_ho_var_types.insert(tn);
      72                 :            :     }
      73                 :            :     // make the bound variable lists
      74                 :        238 :     d_ho_var_bvl[n] = nm->getBoundVarListForFunctionType(tn);
      75         [ +  + ]:        522 :     for (const Node& nc : d_ho_var_bvl[n])
      76                 :            :     {
      77                 :        284 :       d_ho_var_bvs[n].push_back(nc);
      78                 :            :     }
      79                 :            :   }
      80                 :        230 : }
      81                 :            : 
      82                 :        460 : HigherOrderTrigger::~HigherOrderTrigger() {}
      83                 :          0 : void HigherOrderTrigger::collectHoVarApplyTerms(
      84                 :            :     Node q, Node& n, std::map<Node, std::vector<Node> >& apps)
      85                 :            : {
      86                 :          0 :   std::vector<Node> ns;
      87                 :          0 :   ns.push_back(n);
      88                 :          0 :   collectHoVarApplyTerms(q, ns, apps);
      89                 :          0 :   Assert(ns.size() == 1);
      90                 :          0 :   n = ns[0];
      91                 :          0 : }
      92                 :            : 
      93                 :      42883 : void HigherOrderTrigger::collectHoVarApplyTerms(
      94                 :            :     Node q, std::vector<Node>& ns, std::map<Node, std::vector<Node> >& apps)
      95                 :            : {
      96                 :      85766 :   std::unordered_map<TNode, Node> visited;
      97                 :      42883 :   std::unordered_map<TNode, Node>::iterator it;
      98                 :            :   // whether the visited node is a child of a HO_APPLY chain
      99                 :      85766 :   std::unordered_map<TNode, bool> withinApply;
     100                 :      85766 :   std::vector<TNode> visit;
     101                 :      85766 :   TNode cur;
     102         [ +  + ]:      89607 :   for (unsigned i = 0, size = ns.size(); i < size; i++)
     103                 :            :   {
     104                 :      46724 :     visit.push_back(ns[i]);
     105                 :      46724 :     withinApply[ns[i]] = false;
     106                 :     484927 :     do
     107                 :            :     {
     108                 :     531651 :       cur = visit.back();
     109                 :     531651 :       visit.pop_back();
     110                 :            : 
     111                 :     531651 :       it = visited.find(cur);
     112         [ +  + ]:     531651 :       if (it == visited.end())
     113                 :            :       {
     114                 :            :         // do not look in nested quantifiers
     115         [ -  + ]:     261117 :         if (cur.getKind() == Kind::FORALL)
     116                 :            :         {
     117                 :          0 :           visited[cur] = cur;
     118                 :            :         }
     119                 :            :         else
     120                 :            :         {
     121                 :     261117 :           bool curWithinApply = withinApply[cur];
     122                 :     261117 :           visited[cur] = Node::null();
     123                 :     261117 :           visit.push_back(cur);
     124         [ +  + ]:     484927 :           for (unsigned j = 0, sizec = cur.getNumChildren(); j < sizec; j++)
     125                 :            :           {
     126 [ -  + ][ -  - ]:     223810 :             withinApply[cur[j]] = curWithinApply && j == 0;
     127                 :     223810 :             visit.push_back(cur[j]);
     128                 :            :           }
     129                 :            :         }
     130                 :            :       }
     131         [ +  + ]:     270534 :       else if (it->second.isNull())
     132                 :            :       {
     133                 :            :         // carry the conversion
     134                 :     522234 :         Node ret = cur;
     135                 :     261117 :         bool childChanged = false;
     136                 :     522234 :         std::vector<Node> children;
     137         [ +  + ]:     261117 :         if (cur.getMetaKind() == kind::metakind::PARAMETERIZED)
     138                 :            :         {
     139                 :     100519 :           children.push_back(cur.getOperator());
     140                 :            :         }
     141         [ +  + ]:     484927 :         for (const Node& nc : cur)
     142                 :            :         {
     143                 :     223810 :           it = visited.find(nc);
     144 [ -  + ][ -  + ]:     223810 :           Assert(it != visited.end());
                 [ -  - ]
     145 [ -  + ][ -  + ]:     223810 :           Assert(!it->second.isNull());
                 [ -  - ]
     146 [ +  + ][ +  + ]:     223810 :           childChanged = childChanged || nc != it->second;
     147                 :     223810 :           children.push_back(it->second);
     148                 :            :         }
     149         [ +  + ]:     261117 :         if (childChanged)
     150                 :            :         {
     151                 :        336 :           ret = NodeManager::currentNM()->mkNode(cur.getKind(), children);
     152                 :            :         }
     153                 :            :         // now, convert and store the application
     154         [ +  - ]:     261117 :         if (!withinApply[cur])
     155                 :            :         {
     156                 :     522234 :           TNode op;
     157         [ +  + ]:     261117 :           if (ret.getKind() == Kind::APPLY_UF)
     158                 :            :           {
     159                 :            :             // could be a fully applied function variable
     160                 :      92576 :             op = ret.getOperator();
     161                 :            :           }
     162         [ +  + ]:     168541 :           else if (ret.getKind() == Kind::HO_APPLY)
     163                 :            :           {
     164                 :        116 :             op = ret;
     165         [ +  + ]:        232 :             while (op.getKind() == Kind::HO_APPLY)
     166                 :            :             {
     167                 :        116 :               op = op[0];
     168                 :            :             }
     169                 :            :           }
     170         [ +  + ]:     261117 :           if (!op.isNull())
     171                 :            :           {
     172         [ +  + ]:      92692 :             if (op.getKind() == Kind::INST_CONSTANT)
     173                 :            :             {
     174 [ -  + ][ -  + ]:        238 :               Assert(TermUtil::getInstConstAttr(ret) == q);
                 [ -  - ]
     175         [ +  - ]:        476 :               Trace("ho-quant-trigger-debug")
     176                 :          0 :                   << "Ho variable apply term : " << ret << " with head " << op
     177                 :        238 :                   << std::endl;
     178         [ +  + ]:        238 :               if (ret.getKind() == Kind::APPLY_UF)
     179                 :            :               {
     180                 :        230 :                 Node prev = ret;
     181                 :            :                 // for consistency, convert to HO_APPLY if fully applied
     182                 :        230 :                 ret = uf::TheoryUfRewriter::getHoApplyForApplyUf(ret);
     183                 :            :               }
     184                 :        238 :               apps[op].push_back(ret);
     185                 :            :             }
     186                 :            :           }
     187                 :            :         }
     188                 :     261117 :         visited[cur] = ret;
     189                 :            :       }
     190         [ +  + ]:     531651 :     } while (!visit.empty());
     191                 :            : 
     192                 :            :     // store the conversion
     193 [ -  + ][ -  + ]:      46724 :     Assert(visited.find(ns[i]) != visited.end());
                 [ -  - ]
     194                 :      46724 :     ns[i] = visited[ns[i]];
     195                 :            :   }
     196                 :      42883 : }
     197                 :            : 
     198                 :        642 : uint64_t HigherOrderTrigger::addInstantiations()
     199                 :            : {
     200                 :            :   // call the base class implementation
     201                 :        642 :   uint64_t addedFoLemmas = Trigger::addInstantiations();
     202                 :            :   // also adds predicate lemms to force app completion
     203                 :        642 :   uint64_t addedHoLemmas = addHoTypeMatchPredicateLemmas();
     204                 :        642 :   return addedHoLemmas + addedFoLemmas;
     205                 :            : }
     206                 :            : 
     207                 :       1816 : bool HigherOrderTrigger::sendInstantiation(std::vector<Node>& m, InferenceId id)
     208                 :            : {
     209         [ +  + ]:       1816 :   if (options().quantifiers.hoMatching)
     210                 :            :   {
     211                 :            :     // get substitution corresponding to m
     212                 :       2976 :     std::vector<TNode> vars;
     213                 :       2976 :     std::vector<TNode> subs;
     214         [ +  + ]:       4740 :     for (unsigned i = 0, size = d_quant[0].getNumChildren(); i < size; i++)
     215                 :            :     {
     216                 :       3252 :       subs.push_back(m[i]);
     217                 :       3252 :       vars.push_back(d_qreg.getInstantiationConstant(d_quant, i));
     218                 :            :     }
     219                 :            : 
     220         [ +  - ]:       1488 :     Trace("ho-unif-debug") << "Run higher-order unification..." << std::endl;
     221                 :            : 
     222                 :            :     // get the substituted form of all variable-operator ho application terms
     223                 :       1488 :     std::map<TNode, std::vector<Node> > ho_var_apps_subs;
     224         [ +  + ]:       2984 :     for (std::pair<const Node, std::vector<Node> >& ha : d_ho_var_apps)
     225                 :            :     {
     226                 :       2992 :       TNode var = ha.first;
     227         [ +  + ]:       2992 :       for (unsigned j = 0, size = ha.second.size(); j < size; j++)
     228                 :            :       {
     229                 :       2992 :         TNode app = ha.second[j];
     230                 :            :         Node sapp =
     231                 :       1496 :             app.substitute(vars.begin(), vars.end(), subs.begin(), subs.end());
     232                 :       1496 :         ho_var_apps_subs[var].push_back(sapp);
     233         [ +  - ]:       2992 :         Trace("ho-unif-debug") << "  app[" << var << "] : " << app << " -> "
     234                 :       1496 :                                << sapp << std::endl;
     235                 :            :       }
     236                 :            :     }
     237                 :            : 
     238                 :            :     // compute argument vectors for each variable
     239                 :       1488 :     d_lchildren.clear();
     240                 :       1488 :     d_arg_to_arg_rep.clear();
     241                 :       1488 :     d_arg_vector.clear();
     242                 :       1488 :     EntailmentCheck* echeck = d_treg.getEntailmentCheck();
     243         [ +  + ]:       2984 :     for (std::pair<const TNode, std::vector<Node> >& ha : ho_var_apps_subs)
     244                 :            :     {
     245                 :       2992 :       TNode var = ha.first;
     246                 :       1496 :       unsigned vnum = var.getAttribute(InstVarNumAttribute());
     247                 :       2992 :       TNode value = m[vnum];
     248         [ +  - ]:       1496 :       Trace("ho-unif-debug") << "  val[" << var << "] = " << value << std::endl;
     249                 :            : 
     250         [ +  - ]:       2992 :       Trace("ho-unif-debug2") << "initialize lambda information..."
     251                 :       1496 :                               << std::endl;
     252                 :            :       // initialize the lambda children
     253                 :       1496 :       d_lchildren[vnum].push_back(value);
     254                 :            :       std::map<TNode, std::vector<Node> >::iterator ithb =
     255                 :       1496 :           d_ho_var_bvs.find(var);
     256 [ -  + ][ -  + ]:       1496 :       Assert(ithb != d_ho_var_bvs.end());
                 [ -  - ]
     257                 :       1496 :       d_lchildren[vnum].insert(
     258                 :       1496 :           d_lchildren[vnum].end(), ithb->second.begin(), ithb->second.end());
     259                 :            : 
     260         [ +  - ]:       1496 :       Trace("ho-unif-debug2") << "compute fixed arguments..." << std::endl;
     261                 :            :       // compute for each argument if it is only applied to a fixed value modulo
     262                 :            :       // equality
     263                 :       2992 :       std::map<unsigned, Node> fixed_vals;
     264         [ +  + ]:       2992 :       for (unsigned i = 0; i < ha.second.size(); i++)
     265                 :            :       {
     266                 :       2992 :         std::vector<TNode> args;
     267                 :            :         // must substitute the operator we matched with the original
     268                 :            :         // higher-order variable (var) that matched it. This ensures that the
     269                 :            :         // argument vector (args) below is of the proper length. This handles,
     270                 :            :         // for example, matches like:
     271                 :            :         //   (@ x y) with (@ (@ k1 k2) k3)
     272                 :            :         // where k3 but not k2 should be an argument of the match.
     273                 :       2992 :         Node hmatch = ha.second[i];
     274         [ +  - ]:       1496 :         Trace("ho-unif-debug2") << "Match is " << hmatch << std::endl;
     275                 :       1496 :         hmatch = hmatch.substitute(value, var);
     276         [ +  - ]:       1496 :         Trace("ho-unif-debug2") << "Pre-subs match is " << hmatch << std::endl;
     277                 :       2992 :         Node f = uf::TheoryUfRewriter::decomposeHoApply(hmatch, args);
     278                 :            :         // Assert( f==value );
     279         [ +  + ]:       3308 :         for (unsigned k = 0, size = args.size(); k < size; k++)
     280                 :            :         {
     281                 :            :           // must now subsitute back, to handle cases like
     282                 :            :           // (@ x y) matching (@ t (@ t s))
     283                 :            :           // where the above substitution would produce (@ x (@ x s)),
     284                 :            :           // but the argument should be (@ t s).
     285                 :       1812 :           args[k] = args[k].substitute(var, value);
     286                 :       3624 :           Node val = args[k];
     287                 :       1812 :           std::map<unsigned, Node>::iterator itf = fixed_vals.find(k);
     288         [ +  - ]:       1812 :           if (itf == fixed_vals.end())
     289                 :            :           {
     290                 :       1812 :             fixed_vals[k] = val;
     291                 :            :           }
     292         [ -  - ]:          0 :           else if (!itf->second.isNull())
     293                 :            :           {
     294         [ -  - ]:          0 :             if (!d_qstate.areEqual(itf->second, args[k]))
     295                 :            :             {
     296         [ -  - ]:          0 :               if (!echeck->isEntailed(itf->second.eqNode(args[k]), true))
     297                 :            :               {
     298                 :          0 :                 fixed_vals[k] = Node::null();
     299                 :            :               }
     300                 :            :             }
     301                 :            :           }
     302                 :            :         }
     303                 :            :       }
     304         [ -  + ]:       1496 :       if (TraceIsOn("ho-unif-debug"))
     305                 :            :       {
     306                 :          0 :         for (std::map<unsigned, Node>::iterator itf = fixed_vals.begin();
     307         [ -  - ]:          0 :              itf != fixed_vals.end();
     308                 :          0 :              ++itf)
     309                 :            :         {
     310         [ -  - ]:          0 :           Trace("ho-unif-debug") << "  arg[" << var << "][" << itf->first
     311                 :          0 :                                  << "] : " << itf->second << std::endl;
     312                 :            :         }
     313                 :            :       }
     314                 :            : 
     315                 :            :       // now construct argument vectors
     316         [ +  - ]:       1496 :       Trace("ho-unif-debug2") << "compute argument vectors..." << std::endl;
     317                 :       1496 :       std::map<Node, unsigned> arg_to_rep;
     318         [ +  + ]:       3316 :       for (unsigned index = 0, size = ithb->second.size(); index < size;
     319                 :            :            index++)
     320                 :            :       {
     321                 :       3640 :         Node bv_at_index = ithb->second[index];
     322                 :       1820 :         std::map<unsigned, Node>::iterator itf = fixed_vals.find(index);
     323         [ +  - ]:       1820 :         Trace("ho-unif-debug") << "  * arg[" << var << "][" << index << "]";
     324         [ +  + ]:       1820 :         if (itf != fixed_vals.end())
     325                 :            :         {
     326         [ +  - ]:       1812 :           if (!itf->second.isNull())
     327                 :            :           {
     328                 :       5436 :             Node r = d_qstate.getRepresentative(itf->second);
     329                 :       1812 :             std::map<Node, unsigned>::iterator itfr = arg_to_rep.find(r);
     330         [ +  + ]:       1812 :             if (itfr != arg_to_rep.end())
     331                 :            :             {
     332                 :        130 :               d_arg_to_arg_rep[vnum][index] = itfr->second;
     333                 :            :               // function applied to equivalent values at multiple arguments,
     334                 :            :               // can permute variables
     335                 :        130 :               d_arg_vector[vnum][itfr->second].push_back(bv_at_index);
     336         [ +  - ]:        260 :               Trace("ho-unif-debug") << " = { self } ++ arg[" << var << "]["
     337                 :        130 :                                      << itfr->second << "]" << std::endl;
     338                 :            :             }
     339                 :            :             else
     340                 :            :             {
     341                 :       1682 :               arg_to_rep[r] = index;
     342                 :            :               // function applied to single value, can either use variable or
     343                 :            :               // value at this argument position. We give priority to variables,
     344                 :            :               // although this order could be changed.
     345                 :       1682 :               d_arg_vector[vnum][index].push_back(bv_at_index);
     346                 :       1682 :               d_arg_vector[vnum][index].push_back(itf->second);
     347         [ +  - ]:       3364 :               Trace("ho-unif-debug") << " = { self, " << itf->second << " } "
     348                 :       1682 :                                      << std::endl;
     349                 :            :             }
     350                 :            :           }
     351                 :            :           else
     352                 :            :           {
     353                 :            :             // function is applied to disequal values, can only use variable at
     354                 :            :             // this argument position
     355                 :          0 :             d_arg_vector[vnum][index].push_back(bv_at_index);
     356         [ -  - ]:          0 :             Trace("ho-unif-debug") << " = { self } (disequal)" << std::endl;
     357                 :            :           }
     358                 :            :         }
     359                 :            :         else
     360                 :            :         {
     361                 :            :           // argument is irrelevant to matching, assume identity variable
     362                 :          8 :           d_arg_vector[vnum][index].push_back(bv_at_index);
     363         [ +  - ]:          8 :           Trace("ho-unif-debug") << " = { self } (irrelevant)" << std::endl;
     364                 :            :         }
     365                 :            :       }
     366         [ +  - ]:       1496 :       Trace("ho-unif-debug2") << "finished." << std::endl;
     367                 :            :     }
     368                 :            : 
     369                 :       1488 :     bool ret = sendInstantiation(m, 0);
     370         [ +  - ]:       1488 :     Trace("ho-unif-debug") << "Finished, success = " << ret << std::endl;
     371                 :       1488 :     return ret;
     372                 :            :   }
     373                 :            :   else
     374                 :            :   {
     375                 :            :     // do not run higher-order matching
     376                 :        328 :     return d_qim.getInstantiate()->addInstantiation(d_quant, m, id);
     377                 :            :   }
     378                 :            : }
     379                 :            : 
     380                 :            : // recursion depth limited by number of arguments of higher order variables
     381                 :            : // occurring as pattern operators (very small)
     382                 :       4082 : bool HigherOrderTrigger::sendInstantiation(std::vector<Node>& m,
     383                 :            :                                            size_t var_index)
     384                 :            : {
     385         [ +  - ]:       8164 :   Trace("ho-unif-debug2") << "send inst " << var_index << " / "
     386                 :       4082 :                           << d_ho_var_list.size() << std::endl;
     387         [ +  + ]:       4082 :   if (var_index == d_ho_var_list.size())
     388                 :            :   {
     389                 :            :     // we now have an instantiation to try
     390                 :       7758 :     return d_qim.getInstantiate()->addInstantiation(
     391                 :       5172 :         d_quant, m, InferenceId::QUANTIFIERS_INST_E_MATCHING_HO);
     392                 :            :   }
     393                 :            :   else
     394                 :            :   {
     395                 :       2992 :     Node var = d_ho_var_list[var_index];
     396                 :       1496 :     unsigned vnum = var.getAttribute(InstVarNumAttribute());
     397 [ -  + ][ -  + ]:       1496 :     Assert(vnum < m.size());
                 [ -  - ]
     398                 :       1496 :     Node value = m[vnum];
     399 [ -  + ][ -  + ]:       1496 :     Assert(d_lchildren[vnum][0] == value);
                 [ -  - ]
     400 [ -  + ][ -  + ]:       1496 :     Assert(d_ho_var_bvl.find(var) != d_ho_var_bvl.end());
                 [ -  - ]
     401                 :            : 
     402                 :            :     // now, recurse on arguments to enumerate equivalent matching lambda
     403                 :            :     // expressions
     404                 :            :     bool ret =
     405                 :       1496 :         sendInstantiationArg(m, var_index, vnum, 0, d_ho_var_bvl[var], false);
     406                 :            : 
     407                 :            :     // reset the value
     408                 :       1496 :     m[vnum] = value;
     409                 :            : 
     410                 :       1496 :     return ret;
     411                 :            :   }
     412                 :            : }
     413                 :            : 
     414                 :       4584 : bool HigherOrderTrigger::sendInstantiationArg(std::vector<Node>& m,
     415                 :            :                                               unsigned var_index,
     416                 :            :                                               unsigned vnum,
     417                 :            :                                               unsigned arg_index,
     418                 :            :                                               Node lbvl,
     419                 :            :                                               bool arg_changed)
     420                 :            : {
     421         [ +  - ]:       9168 :   Trace("ho-unif-debug2") << "send inst arg " << arg_index << " / "
     422                 :       4584 :                           << lbvl.getNumChildren() << std::endl;
     423         [ +  + ]:       4584 :   if (arg_index == lbvl.getNumChildren())
     424                 :            :   {
     425                 :            :     // construct the lambda
     426         [ +  + ]:       2594 :     if (arg_changed)
     427                 :            :     {
     428         [ +  - ]:       2344 :       Trace("ho-unif-debug2")
     429                 :       1172 :           << "  make lambda from children: " << d_lchildren[vnum] << std::endl;
     430                 :            :       Node body =
     431                 :       2344 :           NodeManager::currentNM()->mkNode(Kind::APPLY_UF, d_lchildren[vnum]);
     432         [ +  - ]:       1172 :       Trace("ho-unif-debug2") << "  got " << body << std::endl;
     433                 :       2344 :       Node lam = NodeManager::mkNode(Kind::LAMBDA, lbvl, body);
     434                 :       1172 :       m[vnum] = lam;
     435         [ +  - ]:       1172 :       Trace("ho-unif-debug2") << "  try " << vnum << " -> " << lam << std::endl;
     436                 :            :     }
     437                 :       2594 :     return sendInstantiation(m, var_index + 1);
     438                 :            :   }
     439                 :            :   else
     440                 :            :   {
     441                 :            :     std::map<unsigned, unsigned>::iterator itr =
     442                 :       1990 :         d_arg_to_arg_rep[vnum].find(arg_index);
     443                 :            :     unsigned rindex =
     444         [ +  + ]:       1990 :         itr != d_arg_to_arg_rep[vnum].end() ? itr->second : arg_index;
     445                 :            :     std::map<unsigned, std::vector<Node> >::iterator itv =
     446                 :       1990 :         d_arg_vector[vnum].find(rindex);
     447 [ -  + ][ -  + ]:       1990 :     Assert(itv != d_arg_vector[vnum].end());
                 [ -  - ]
     448                 :       1990 :     Node prev = lbvl[arg_index];
     449                 :       1990 :     bool ret = false;
     450                 :            :     // try each argument in the vector
     451         [ +  + ]:       3598 :     for (unsigned i = 0, size = itv->second.size(); i < size; i++)
     452                 :            :     {
     453 [ +  + ][ +  + ]:       3088 :       bool new_arg_changed = arg_changed || prev != itv->second[i];
     454                 :       3088 :       d_lchildren[vnum][arg_index + 1] = itv->second[i];
     455         [ +  + ]:       3088 :       if (sendInstantiationArg(
     456                 :            :               m, var_index, vnum, arg_index + 1, lbvl, new_arg_changed))
     457                 :            :       {
     458                 :       1480 :         ret = true;
     459                 :       1480 :         break;
     460                 :            :       }
     461                 :            :     }
     462                 :            :     // clean up
     463                 :       1990 :     d_lchildren[vnum][arg_index + 1] = prev;
     464                 :       1990 :     return ret;
     465                 :            :   }
     466                 :            : }
     467                 :            : 
     468                 :        642 : uint64_t HigherOrderTrigger::addHoTypeMatchPredicateLemmas()
     469                 :            : {
     470         [ -  + ]:        642 :   if (d_ho_var_types.empty())
     471                 :            :   {
     472                 :          0 :     return 0;
     473                 :            :   }
     474         [ +  - ]:        642 :   Trace("ho-quant-trigger") << "addHoTypeMatchPredicateLemmas..." << std::endl;
     475                 :        642 :   uint64_t numLemmas = 0;
     476                 :            :   // this forces expansion of APPLY_UF terms to curried HO_APPLY chains
     477                 :        642 :   TermDb* tdb = d_treg.getTermDatabase();
     478                 :        642 :   unsigned size = tdb->getNumOperators();
     479                 :        642 :   NodeManager* nm = NodeManager::currentNM();
     480         [ +  + ]:       6266 :   for (unsigned j = 0; j < size; j++)
     481                 :            :   {
     482                 :      11248 :     Node f = tdb->getOperator(j);
     483         [ +  + ]:       5624 :     if (f.isVar())
     484                 :            :     {
     485                 :       9312 :       TypeNode tn = f.getType();
     486         [ +  - ]:       4656 :       if (tn.isFunction())
     487                 :            :       {
     488                 :       9312 :         std::vector<TypeNode> argTypes = tn.getArgTypes();
     489 [ -  + ][ -  + ]:       4656 :         Assert(argTypes.size() > 0);
                 [ -  - ]
     490                 :       9312 :         TypeNode range = tn.getRangeType();
     491                 :            :         // for each function type suffix of the type of f, for example if
     492                 :            :         // f : (Int -> (Int -> Int))
     493                 :            :         // we iterate with stn = (Int -> (Int -> Int)) and (Int -> Int)
     494         [ +  + ]:       9800 :         for (unsigned a = 0, arg_size = argTypes.size(); a < arg_size; a++)
     495                 :            :         {
     496                 :      10288 :           std::vector<TypeNode> sargts;
     497                 :       5144 :           sargts.insert(sargts.begin(), argTypes.begin() + a, argTypes.end());
     498 [ -  + ][ -  + ]:       5144 :           Assert(sargts.size() > 0);
                 [ -  - ]
     499                 :      10288 :           TypeNode stn = nm->mkFunctionType(sargts, range);
     500         [ +  - ]:      10288 :           Trace("ho-quant-trigger-debug")
     501                 :       5144 :               << "For " << f << ", check " << stn << "..." << std::endl;
     502                 :            :           // if a variable of this type occurs in this trigger
     503         [ +  + ]:       5144 :           if (d_ho_var_types.find(stn) != d_ho_var_types.end())
     504                 :            :           {
     505                 :       6280 :             Node u = HoTermDb::getHoTypeMatchPredicate(tn);
     506                 :       9420 :             Node au = NodeManager::mkNode(Kind::APPLY_UF, u, f);
     507         [ +  + ]:       3140 :             if (d_qim.addPendingLemma(au,
     508                 :            :                                       InferenceId::QUANTIFIERS_HO_MATCH_PRED))
     509                 :            :             {
     510                 :            :               // this forces f to be a first-class member of the quantifier-free
     511                 :            :               // equality engine, which in turn forces the quantifier-free
     512                 :            :               // theory solver to expand it to an HO_APPLY chain.
     513         [ +  - ]:       1292 :               Trace("ho-quant")
     514                 :        646 :                   << "Added ho match predicate lemma : " << au << std::endl;
     515                 :        646 :               numLemmas++;
     516                 :            :             }
     517                 :            :           }
     518                 :            :         }
     519                 :            :       }
     520                 :            :     }
     521                 :            :   }
     522                 :            : 
     523                 :        642 :   return numLemmas;
     524                 :            : }
     525                 :            : 
     526                 :            : }  // namespace inst
     527                 :            : }  // namespace quantifiers
     528                 :            : }  // namespace theory
     529                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14