LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/theory/quantifiers - quant_split.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 104 107 97.2 %
Date: 2024-11-10 12:40:22 Functions: 5 5 100.0 %
Branches: 66 98 67.3 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * Top contributors (to current version):
       3                 :            :  *   Andrew Reynolds, Mathias Preiner, Aina Niemetz
       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 dynamic quantifiers splitting.
      14                 :            :  */
      15                 :            : 
      16                 :            : #include "theory/quantifiers/quant_split.h"
      17                 :            : 
      18                 :            : #include "expr/dtype.h"
      19                 :            : #include "expr/dtype_cons.h"
      20                 :            : #include "options/quantifiers_options.h"
      21                 :            : #include "theory/datatypes/theory_datatypes_utils.h"
      22                 :            : #include "theory/quantifiers/first_order_model.h"
      23                 :            : #include "theory/quantifiers/term_database.h"
      24                 :            : 
      25                 :            : using namespace cvc5::internal::kind;
      26                 :            : 
      27                 :            : namespace cvc5::internal {
      28                 :            : namespace theory {
      29                 :            : namespace quantifiers {
      30                 :            : 
      31                 :      39621 : QuantDSplit::QuantDSplit(Env& env,
      32                 :            :                          QuantifiersState& qs,
      33                 :            :                          QuantifiersInferenceManager& qim,
      34                 :            :                          QuantifiersRegistry& qr,
      35                 :      39621 :                          TermRegistry& tr)
      36                 :            :     : QuantifiersModule(env, qs, qim, qr, tr),
      37                 :      79242 :       d_quant_to_reduce(userContext()),
      38                 :      39621 :       d_added_split(userContext())
      39                 :            : {
      40                 :      39621 : }
      41                 :            : 
      42                 :      32499 : void QuantDSplit::checkOwnership(Node q)
      43                 :            : {
      44                 :            :   // If q is non-standard (marked as sygus, quantifier elimination, etc.), then
      45                 :            :   // do no split it.
      46                 :      32499 :   QAttributes qa;
      47                 :      32499 :   QuantAttributes::computeQuantAttributes(q, qa);
      48         [ +  + ]:      32499 :   if (!qa.isStandard())
      49                 :            :   {
      50                 :       3536 :     return;
      51                 :            :   }
      52                 :            :   // do not split if there is a trigger
      53         [ +  + ]:      28963 :   if (qa.d_hasPattern)
      54                 :            :   {
      55                 :       2614 :     return;
      56                 :            :   }
      57                 :      26349 :   bool takeOwnership = false;
      58                 :      26349 :   bool doSplit = false;
      59                 :      26349 :   QuantifiersBoundInference& qbi = d_qreg.getQuantifiersBoundInference();
      60         [ +  - ]:      26349 :   Trace("quant-dsplit-debug") << "Check split quantified formula : " << q << std::endl;
      61         [ +  + ]:      86660 :   for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
      62                 :     124264 :     TypeNode tn = q[0][i].getType();
      63         [ +  + ]:      62132 :     if( tn.isDatatype() ){
      64                 :       7492 :       bool isFinite = d_env.isFiniteType(tn);
      65                 :       7492 :       const DType& dt = tn.getDType();
      66         [ +  + ]:       7492 :       if (dt.isRecursiveSingleton(tn))
      67                 :            :       {
      68 [ +  - ][ -  + ]:        450 :         Trace("quant-dsplit-debug") << "Datatype " << dt.getName() << " is recursive singleton." << std::endl;
                 [ -  - ]
      69                 :            :       }
      70                 :            :       else
      71                 :            :       {
      72                 :       7042 :         if (options().quantifiers.quantDynamicSplit
      73         [ -  + ]:       7042 :             == options::QuantDSplitMode::AGG)
      74                 :            :         {
      75                 :            :           // split if it is a finite datatype
      76                 :          0 :           doSplit = isFinite;
      77                 :            :         }
      78                 :       7042 :         else if (options().quantifiers.quantDynamicSplit
      79         [ +  - ]:       7042 :                  == options::QuantDSplitMode::DEFAULT)
      80                 :            :         {
      81         [ +  + ]:       7042 :           if (!qbi.isFiniteBound(q, q[0][i]))
      82                 :            :           {
      83         [ +  + ]:       6859 :             if (isFinite)
      84                 :            :             {
      85                 :            :               // split if goes from being unhandled -> handled by finite
      86                 :            :               // instantiation. An example is datatypes with uninterpreted sort
      87                 :            :               // fields which are "interpreted finite" but not "finite".
      88                 :         48 :               doSplit = true;
      89                 :            :               // we additionally take ownership of this formula, in other words,
      90                 :            :               // we mark it reduced.
      91                 :         48 :               takeOwnership = true;
      92                 :            :             }
      93 [ +  + ][ +  - ]:       6811 :             else if (dt.getNumConstructors() == 1 && !dt.isCodatatype())
                 [ +  + ]
      94                 :            :             {
      95                 :            :               // split if only one constructor
      96                 :       1773 :               doSplit = true;
      97                 :            :             }
      98                 :            :           }
      99                 :            :         }
     100         [ +  + ]:       7042 :         if (doSplit)
     101                 :            :         {
     102                 :            :           // store the index to split
     103                 :       1821 :           d_quant_to_reduce[q] = i;
     104         [ +  - ]:       3642 :           Trace("quant-dsplit-debug")
     105 [ -  + ][ -  - ]:       1821 :               << "Split at index " << i << " based on datatype " << dt.getName()
     106                 :       1821 :               << std::endl;
     107                 :       1821 :           break;
     108                 :            :         }
     109         [ +  - ]:      10442 :         Trace("quant-dsplit-debug")
     110 [ -  + ][ -  - ]:       5221 :             << "Do not split based on datatype " << dt.getName() << std::endl;
     111                 :            :       }
     112                 :            :     }
     113                 :            :   }
     114                 :            : 
     115         [ +  + ]:      26349 :   if (takeOwnership)
     116                 :            :   {
     117         [ +  - ]:         48 :     Trace("quant-dsplit-debug") << "Will take ownership." << std::endl;
     118                 :         48 :     d_qreg.setOwner(q, this);
     119                 :            :   }
     120                 :            :   // Notice we may not take ownership in some cases, meaning that both the
     121                 :            :   // original quantified formula and the split one are generated. This may
     122                 :            :   // increase our ability to answer "unsat", since quantifier instantiation
     123                 :            :   // heuristics may be more effective for one or the other (see issues #993
     124                 :            :   // and 3481).
     125                 :            : }
     126                 :            : 
     127                 :            : /* whether this module needs to check this round */
     128                 :     101164 : bool QuantDSplit::needsCheck( Theory::Effort e ) {
     129 [ +  + ][ +  + ]:     101164 :   return e>=Theory::EFFORT_FULL && !d_quant_to_reduce.empty();
     130                 :            : }
     131                 :            : 
     132                 :        743 : bool QuantDSplit::checkCompleteFor( Node q ) {
     133                 :            :   // true if we split q
     134                 :        743 :   return d_added_split.find( q )!=d_added_split.end();
     135                 :            : }
     136                 :            : 
     137                 :            : /* Call during quantifier engine's check */
     138                 :       3770 : void QuantDSplit::check(Theory::Effort e, QEffort quant_e)
     139                 :            : {
     140                 :            :   //add lemmas ASAP (they are a reduction)
     141         [ +  + ]:       3770 :   if (quant_e != QEFFORT_CONFLICT)
     142                 :            :   {
     143                 :       2414 :     return;
     144                 :            :   }
     145         [ +  - ]:       1356 :   Trace("quant-dsplit") << "QuantDSplit::check" << std::endl;
     146                 :       1356 :   NodeManager* nm = nodeManager();
     147                 :       1356 :   FirstOrderModel* m = d_treg.getModel();
     148                 :       1356 :   std::vector<Node> lemmas;
     149                 :      30162 :   for (NodeIntMap::iterator it = d_quant_to_reduce.begin();
     150         [ +  + ]:      30162 :        it != d_quant_to_reduce.end();
     151                 :      28806 :        ++it)
     152                 :            :   {
     153                 :      28806 :     Node q = it->first;
     154         [ +  - ]:      28806 :     Trace("quant-dsplit") << "- Split quantifier " << q << std::endl;
     155         [ +  + ]:      28806 :     if (d_added_split.find(q) != d_added_split.end())
     156                 :            :     {
     157                 :      26891 :       continue;
     158                 :            :     }
     159                 :       1915 :     if (m->isQuantifierAsserted(q) && m->isQuantifierActive(q))
     160                 :            :     {
     161                 :       1795 :       d_added_split.insert(q);
     162                 :       3590 :       std::vector<Node> bvs;
     163         [ +  + ]:       7376 :       for (unsigned i = 0, nvars = q[0].getNumChildren(); i < nvars; i++)
     164                 :            :       {
     165         [ +  + ]:       5581 :         if (static_cast<int>(i) != it->second)
     166                 :            :         {
     167                 :       3786 :           bvs.push_back(q[0][i]);
     168                 :            :         }
     169                 :            :       }
     170                 :       3590 :       std::vector<Node> disj;
     171                 :       1795 :       disj.push_back(q.negate());
     172                 :       5385 :       TNode svar = q[0][it->second];
     173                 :       3590 :       TypeNode tn = svar.getType();
     174 [ -  + ][ -  + ]:       1795 :       Assert(tn.isDatatype());
                 [ -  - ]
     175                 :       3590 :       std::vector<Node> cons;
     176                 :       1795 :       const DType& dt = tn.getDType();
     177         [ +  + ]:       3606 :       for (unsigned j = 0, ncons = dt.getNumConstructors(); j < ncons; j++)
     178                 :            :       {
     179                 :       3622 :         std::vector<Node> vars;
     180                 :       3622 :         TypeNode dtjtn = dt[j].getInstantiatedConstructorType(tn);
     181 [ -  + ][ -  + ]:       1811 :         Assert(dtjtn.getNumChildren() == dt[j].getNumArgs() + 1);
                 [ -  - ]
     182         [ +  + ]:       5372 :         for (unsigned k = 0, nargs = dt[j].getNumArgs(); k < nargs; k++)
     183                 :            :         {
     184                 :       7122 :           TypeNode tns = dtjtn[k];
     185                 :       7122 :           Node v = nm->mkBoundVar(tns);
     186                 :       3561 :           vars.push_back(v);
     187                 :            :         }
     188                 :       3622 :         std::vector<Node> bvs_cmb;
     189                 :       1811 :         bvs_cmb.insert(bvs_cmb.end(), bvs.begin(), bvs.end());
     190                 :       1811 :         bvs_cmb.insert(bvs_cmb.end(), vars.begin(), vars.end());
     191                 :       3622 :         Node c = datatypes::utils::mkApplyCons(tn, dt, j, vars);
     192                 :       3622 :         TNode ct = c;
     193                 :       5433 :         Node body = q[1].substitute(svar, ct);
     194         [ +  - ]:       1811 :         if (!bvs_cmb.empty())
     195                 :            :         {
     196                 :       3622 :           Node bvl = nm->mkNode(Kind::BOUND_VAR_LIST, bvs_cmb);
     197                 :       1811 :           std::vector<Node> children;
     198                 :       1811 :           children.push_back(bvl);
     199                 :       1811 :           children.push_back(body);
     200         [ -  + ]:       1811 :           if (q.getNumChildren() == 3)
     201                 :            :           {
     202                 :          0 :             Node ipls = q[2].substitute(svar, ct);
     203                 :          0 :             children.push_back(ipls);
     204                 :            :           }
     205                 :       1811 :           body = nm->mkNode(Kind::FORALL, children);
     206                 :            :         }
     207                 :       1811 :         cons.push_back(body);
     208                 :            :       }
     209         [ +  + ]:       1795 :       Node conc = cons.size() == 1 ? cons[0] : nm->mkNode(Kind::AND, cons);
     210                 :       1795 :       disj.push_back(conc);
     211         [ -  + ]:       1795 :       lemmas.push_back(disj.size() == 1 ? disj[0] : nm->mkNode(Kind::OR, disj));
     212                 :            :     }
     213                 :            :   }
     214                 :            : 
     215                 :            :   // add lemmas to quantifiers engine
     216         [ +  + ]:       3151 :   for (const Node& lem : lemmas)
     217                 :            :   {
     218         [ +  - ]:       1795 :     Trace("quant-dsplit") << "QuantDSplit lemma : " << lem << std::endl;
     219                 :       1795 :     d_qim.addPendingLemma(lem, InferenceId::QUANTIFIERS_DSPLIT);
     220                 :            :   }
     221         [ +  - ]:       1356 :   Trace("quant-dsplit") << "QuantDSplit::check finished" << std::endl;
     222                 :            : }
     223                 :            : 
     224                 :            : }  // namespace quantifiers
     225                 :            : }  // namespace theory
     226                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14