LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/theory/quantifiers - inst_strategy_pool.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 106 120 88.3 %
Date: 2025-02-08 13:33:28 Functions: 11 12 91.7 %
Branches: 76 134 56.7 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * Top contributors (to current version):
       3                 :            :  *   Andrew Reynolds, Aina Niemetz, Andres Noetzli
       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                 :            :  * Pool-based instantiation strategy
      14                 :            :  */
      15                 :            : 
      16                 :            : #include "theory/quantifiers/inst_strategy_pool.h"
      17                 :            : 
      18                 :            : #include "options/quantifiers_options.h"
      19                 :            : #include "theory/quantifiers/first_order_model.h"
      20                 :            : #include "theory/quantifiers/instantiate.h"
      21                 :            : #include "theory/quantifiers/quantifiers_inference_manager.h"
      22                 :            : #include "theory/quantifiers/term_pools.h"
      23                 :            : #include "theory/quantifiers/term_registry.h"
      24                 :            : #include "theory/quantifiers/term_tuple_enumerator.h"
      25                 :            : 
      26                 :            : using namespace cvc5::internal::kind;
      27                 :            : using namespace cvc5::context;
      28                 :            : 
      29                 :            : namespace cvc5::internal {
      30                 :            : namespace theory {
      31                 :            : namespace quantifiers {
      32                 :            : 
      33                 :      43589 : InstStrategyPool::InstStrategyPool(Env& env,
      34                 :            :                                    QuantifiersState& qs,
      35                 :            :                                    QuantifiersInferenceManager& qim,
      36                 :            :                                    QuantifiersRegistry& qr,
      37                 :      43589 :                                    TermRegistry& tr)
      38                 :      43589 :     : QuantifiersModule(env, qs, qim, qr, tr)
      39                 :            : {
      40                 :      43589 : }
      41                 :            : 
      42                 :      38961 : void InstStrategyPool::presolve() {}
      43                 :            : 
      44                 :     146219 : bool InstStrategyPool::needsCheck(Theory::Effort e)
      45                 :            : {
      46                 :     146219 :   return d_qstate.getInstWhenNeedsCheck(e);
      47                 :            : }
      48                 :            : 
      49                 :      61440 : void InstStrategyPool::reset_round(Theory::Effort e) {}
      50                 :            : 
      51                 :      59521 : void InstStrategyPool::registerQuantifier(Node q)
      52                 :            : {
      53         [ -  + ]:      59521 :   if (options().quantifiers.userPoolQuant == options::UserPoolMode::IGNORE)
      54                 :            :   {
      55                 :          0 :     return;
      56                 :            :   }
      57                 :            :   // take into account user pools
      58         [ +  + ]:      59521 :   if (q.getNumChildren() == 3)
      59                 :            :   {
      60                 :      36669 :     Node subsPat = d_qreg.substituteBoundVariablesToInstConstants(q[2], q);
      61                 :            :     // add patterns
      62         [ +  + ]:      25558 :     for (const Node& p : subsPat)
      63                 :            :     {
      64         [ +  + ]:      13335 :       if (p.getKind() == Kind::INST_POOL)
      65                 :            :       {
      66                 :         64 :         if (hasTupleSemantics(q, p) || hasProductSemantics(q, p))
      67                 :            :         {
      68                 :         64 :           d_userPools[q].push_back(p);
      69                 :            :         }
      70                 :            :         else
      71                 :            :         {
      72         [ -  - ]:          0 :           Warning() << "Cannot find semantics of pool " << p << " in " << q
      73                 :          0 :                     << std::endl;
      74                 :            :         }
      75                 :            :       }
      76                 :            :     }
      77                 :            :   }
      78                 :            : }
      79                 :            : 
      80                 :      59521 : void InstStrategyPool::checkOwnership(Node q)
      81                 :            : {
      82                 :      59521 :   if (options().quantifiers.userPoolQuant == options::UserPoolMode::TRUST
      83 [ +  - ][ +  + ]:      59521 :       && q.getNumChildren() == 3)
                 [ +  + ]
      84                 :            :   {
      85                 :            :     // if only using pools for instantiation, take ownership of this quantified
      86                 :            :     // formula
      87         [ +  + ]:      25488 :     for (const Node& p : q[2])
      88                 :            :     {
      89         [ +  + ]:      13329 :       if (p.getKind() == Kind::INST_POOL)
      90                 :            :       {
      91                 :         64 :         d_qreg.setOwner(q, this, 1);
      92                 :         64 :         return;
      93                 :            :       }
      94                 :            :     }
      95                 :            :   }
      96                 :            : }
      97                 :            : 
      98                 :        349 : bool InstStrategyPool::hasProductSemantics(Node q, Node p)
      99                 :            : {
     100 [ +  - ][ -  + ]:        349 :   Assert(q.getKind() == Kind::EXISTS || q.getKind() == Kind::FORALL);
         [ -  + ][ -  - ]
     101 [ -  + ][ -  + ]:        349 :   Assert(p.getKind() == Kind::INST_POOL);
                 [ -  - ]
     102                 :        349 :   size_t nchild = p.getNumChildren();
     103         [ +  + ]:        349 :   if (nchild != q[0].getNumChildren())
     104                 :            :   {
     105                 :         10 :     return false;
     106                 :            :   }
     107         [ +  + ]:        796 :   for (size_t i = 0; i < nchild; i++)
     108                 :            :   {
     109 [ -  + ][ -  + ]:        457 :     Assert(p[i].getType().isSet());
                 [ -  - ]
     110                 :        914 :     TypeNode tn = p[i].getType().getSetElementType();
     111         [ -  + ]:        457 :     if (tn != q[0][i].getType())
     112                 :            :     {
     113                 :            :       // the i^th pool in the annotation does not match the i^th variable
     114                 :          0 :       return false;
     115                 :            :     }
     116                 :            :   }
     117                 :        339 :   return true;
     118                 :            : }
     119                 :            : 
     120                 :        174 : bool InstStrategyPool::hasTupleSemantics(Node q, Node p)
     121                 :            : {
     122 [ +  - ][ -  + ]:        174 :   Assert(q.getKind() == Kind::EXISTS || q.getKind() == Kind::FORALL);
         [ -  + ][ -  - ]
     123 [ -  + ][ -  + ]:        174 :   Assert(p.getKind() == Kind::INST_POOL);
                 [ -  - ]
     124         [ +  + ]:        174 :   if (p.getNumChildren() != 1)
     125                 :            :   {
     126                 :         60 :     return false;
     127                 :            :   }
     128 [ -  + ][ -  + ]:        114 :   Assert(p[0].getType().isSet());
                 [ -  - ]
     129                 :        342 :   TypeNode ptn = p[0].getType().getSetElementType();
     130         [ +  + ]:        114 :   if (!ptn.isTuple())
     131                 :            :   {
     132                 :         92 :     return false;
     133                 :            :   }
     134                 :         44 :   std::vector<TypeNode> targs = ptn.getTupleTypes();
     135                 :         22 :   size_t nchild = targs.size();
     136         [ -  + ]:         22 :   if (nchild != q[0].getNumChildren())
     137                 :            :   {
     138                 :          0 :     return false;
     139                 :            :   }
     140         [ +  + ]:         66 :   for (size_t i = 0; i < nchild; i++)
     141                 :            :   {
     142         [ -  + ]:         44 :     if (targs[i] != q[0][i].getType())
     143                 :            :     {
     144                 :            :       // the i^th component type of the pool in the annotation does not match
     145                 :            :       // the i^th variable
     146                 :          0 :       return false;
     147                 :            :     }
     148                 :            :   }
     149                 :         22 :   return true;
     150                 :            : }
     151                 :            : 
     152                 :     108800 : void InstStrategyPool::check(Theory::Effort e, QEffort quant_e)
     153                 :            : {
     154         [ +  + ]:     108800 :   if (d_userPools.empty())
     155                 :            :   {
     156                 :     108754 :     return;
     157                 :            :   }
     158                 :         46 :   beginCallDebug();
     159                 :         46 :   FirstOrderModel* fm = d_treg.getModel();
     160                 :         46 :   bool inConflict = false;
     161                 :         46 :   uint64_t addedLemmas = 0;
     162                 :         46 :   size_t nquant = fm->getNumAssertedQuantifiers();
     163                 :         46 :   std::map<Node, std::vector<Node> >::iterator uit;
     164         [ +  + ]:        170 :   for (size_t i = 0; i < nquant; i++)
     165                 :            :   {
     166                 :        124 :     Node q = fm->getAssertedQuantifier(i, true);
     167                 :        124 :     uit = d_userPools.find(q);
     168         [ +  + ]:        124 :     if (uit == d_userPools.end())
     169                 :            :     {
     170                 :            :       // no user pools for this
     171                 :         24 :       continue;
     172                 :            :     }
     173         [ -  + ]:        100 :     if (!d_qreg.hasOwnership(q, this))
     174                 :            :     {
     175                 :            :       // quantified formula is not owned by this
     176                 :          0 :       continue;
     177                 :            :     }
     178                 :            :     // process with each user pool
     179         [ +  + ]:        200 :     for (const Node& p : uit->second)
     180                 :            :     {
     181                 :        100 :       inConflict = process(q, p, addedLemmas);
     182         [ -  + ]:        100 :       if (inConflict)
     183                 :            :       {
     184                 :          0 :         break;
     185                 :            :       }
     186                 :            :     }
     187         [ -  + ]:        100 :     if (inConflict)
     188                 :            :     {
     189                 :          0 :       break;
     190                 :            :     }
     191                 :            :   }
     192                 :         46 :   endCallDebug();
     193                 :            : }
     194                 :            : 
     195                 :          0 : std::string InstStrategyPool::identify() const { return "pool-inst"; }
     196                 :            : 
     197                 :        100 : bool InstStrategyPool::process(Node q, Node p, uint64_t& addedLemmas)
     198                 :            : {
     199 [ +  - ][ +  - ]:        200 :   Assert(q.getKind() == Kind::FORALL && p.getKind() == Kind::INST_POOL);
         [ -  + ][ -  - ]
     200                 :            :   // maybe has tuple semantics?
     201         [ +  + ]:        100 :   if (hasTupleSemantics(q, p))
     202                 :            :   {
     203                 :          6 :     return processTuple(q, p, addedLemmas);
     204                 :            :   }
     205 [ -  + ][ -  + ]:         94 :   Assert(hasProductSemantics(q, p));
                 [ -  - ]
     206                 :            :   // otherwise, process standard
     207                 :         94 :   Instantiate* ie = d_qim.getInstantiate();
     208                 :            :   TermTupleEnumeratorEnv ttec;
     209                 :         94 :   ttec.d_fullEffort = true;
     210                 :         94 :   ttec.d_increaseSum = options().quantifiers.enumInstSum;
     211                 :         94 :   ttec.d_tr = &d_treg;
     212                 :            :   std::shared_ptr<TermTupleEnumeratorInterface> enumerator(
     213                 :        282 :       mkTermTupleEnumeratorPool(q, &ttec, p));
     214                 :        188 :   std::vector<Node> terms;
     215                 :        188 :   std::vector<bool> failMask;
     216                 :            :   // we instantiate exhaustively
     217                 :         94 :   enumerator->init();
     218         [ +  + ]:        904 :   while (enumerator->hasNext())
     219                 :            :   {
     220         [ -  + ]:        810 :     if (d_qstate.isInConflict())
     221                 :            :     {
     222                 :            :       // could be conflicting for an internal reason
     223                 :          0 :       return true;
     224                 :            :     }
     225                 :        810 :     enumerator->next(terms);
     226                 :            :     // try instantiation
     227                 :        810 :     failMask.clear();
     228         [ +  + ]:        810 :     if (ie->addInstantiationExpFail(
     229                 :            :             q, terms, failMask, InferenceId::QUANTIFIERS_INST_POOL))
     230                 :            :     {
     231         [ +  - ]:        588 :       Trace("pool-inst") << "Success with " << terms << std::endl;
     232                 :        588 :       addedLemmas++;
     233                 :            :     }
     234                 :            :     else
     235                 :            :     {
     236         [ +  - ]:        222 :       Trace("pool-inst") << "Fail with " << terms << std::endl;
     237                 :            :       // notify the enumerator of the failure
     238                 :        222 :       enumerator->failureReason(failMask);
     239                 :            :     }
     240                 :            :   }
     241                 :         94 :   return false;
     242                 :            : }
     243                 :            : 
     244                 :          6 : bool InstStrategyPool::processTuple(Node q, Node p, uint64_t& addedLemmas)
     245                 :            : {
     246                 :          6 :   Instantiate* ie = d_qim.getInstantiate();
     247                 :          6 :   TermPools* tp = d_treg.getTermPools();
     248                 :            :   // get the terms
     249                 :         12 :   std::vector<Node> terms;
     250                 :          6 :   tp->getTermsForPool(p[0], terms);
     251                 :            :   // instantiation for each term in pool
     252         [ +  + ]:         24 :   for (const Node& t : terms)
     253                 :            :   {
     254         [ -  + ]:         18 :     if (d_qstate.isInConflict())
     255                 :            :     {
     256                 :          0 :       return true;
     257                 :            :     }
     258         [ -  + ]:         18 :     if (t.getKind() != Kind::APPLY_CONSTRUCTOR)
     259                 :            :     {
     260                 :            :       // a symbolic tuple is in the pool, we ignore it.
     261                 :          0 :       continue;
     262                 :            :     }
     263                 :         36 :     std::vector<Node> inst(t.begin(), t.end());
     264 [ -  + ][ -  + ]:         18 :     Assert(inst.size() == q[0].getNumChildren());
                 [ -  - ]
     265         [ +  - ]:         18 :     if (ie->addInstantiation(q, inst, InferenceId::QUANTIFIERS_INST_POOL_TUPLE))
     266                 :            :     {
     267         [ +  - ]:         18 :       Trace("pool-inst") << "Success (tuple) with " << inst << std::endl;
     268                 :         18 :       addedLemmas++;
     269                 :            :     }
     270                 :            :     else
     271                 :            :     {
     272         [ -  - ]:          0 :       Trace("pool-inst") << "Fail (tuple) with " << inst << std::endl;
     273                 :            :     }
     274                 :            :   }
     275                 :          6 :   return false;
     276                 :            : }
     277                 :            : 
     278                 :            : }  // namespace quantifiers
     279                 :            : }  // namespace theory
     280                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14