LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/theory/quantifiers/sygus - sygus_interpol.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 170 205 82.9 %
Date: 2024-12-30 14:24:00 Functions: 10 10 100.0 %
Branches: 93 176 52.8 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * Top contributors (to current version):
       3                 :            :  *   Ying Sheng, Andrew Reynolds, Mathias Preiner
       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 sygus interpolation utility, which transforms an input of
      14                 :            :  * axioms and conjecture into an interpolation problem, and solve it.
      15                 :            :  */
      16                 :            : 
      17                 :            : #include "theory/quantifiers/sygus/sygus_interpol.h"
      18                 :            : 
      19                 :            : #include <sstream>
      20                 :            : 
      21                 :            : #include "base/modal_exception.h"
      22                 :            : #include "expr/dtype.h"
      23                 :            : #include "expr/node_algorithm.h"
      24                 :            : #include "options/quantifiers_options.h"
      25                 :            : #include "options/smt_options.h"
      26                 :            : #include "smt/env.h"
      27                 :            : #include "smt/set_defaults.h"
      28                 :            : #include "theory/datatypes/sygus_datatype_utils.h"
      29                 :            : #include "theory/quantifiers/quantifiers_attributes.h"
      30                 :            : #include "theory/quantifiers/sygus/sygus_grammar_cons.h"
      31                 :            : #include "theory/quantifiers/sygus/sygus_utils.h"
      32                 :            : #include "theory/smt_engine_subsolver.h"
      33                 :            : 
      34                 :            : namespace cvc5::internal {
      35                 :            : namespace theory {
      36                 :            : namespace quantifiers {
      37                 :            : 
      38                 :        616 : SygusInterpol::SygusInterpol(Env& env) : EnvObj(env) {}
      39                 :            : 
      40                 :        616 : void SygusInterpol::collectSymbols(const std::vector<Node>& axioms,
      41                 :            :                                    const Node& conj)
      42                 :            : {
      43         [ +  - ]:        616 :   Trace("sygus-interpol-debug") << "Collect symbols..." << std::endl;
      44                 :       1232 :   std::unordered_set<Node> symSetAxioms;
      45                 :        616 :   std::unordered_set<Node> symSetConj;
      46         [ +  + ]:       1234 :   for (size_t i = 0, size = axioms.size(); i < size; i++)
      47                 :            :   {
      48                 :        618 :     expr::getSymbols(axioms[i], symSetAxioms);
      49                 :            :   }
      50                 :        616 :   expr::getSymbols(conj, symSetConj);
      51                 :        616 :   d_syms.insert(d_syms.end(), symSetAxioms.begin(), symSetAxioms.end());
      52         [ +  + ]:        997 :   for (const Node& elem : symSetConj)
      53                 :            :   {
      54         [ +  + ]:        381 :     if (symSetAxioms.find(elem) != symSetAxioms.end())
      55                 :            :     {
      56                 :        193 :       d_symSetShared.insert(elem);
      57                 :            :     }
      58                 :            :     else
      59                 :            :     {
      60                 :        188 :       d_syms.push_back(elem);
      61                 :            :     }
      62                 :            :   }
      63         [ +  - ]:       1232 :   Trace("sygus-interpol-debug")
      64                 :          0 :       << "...finish, got " << d_syms.size() << " symbols in total. And "
      65                 :        616 :       << d_symSetShared.size() << " shared symbols." << std::endl;
      66                 :        616 : }
      67                 :            : 
      68                 :        616 : void SygusInterpol::createVariables(bool needsShared)
      69                 :            : {
      70                 :        616 :   NodeManager* nm = nodeManager();
      71         [ +  + ]:       1414 :   for (const Node& s : d_syms)
      72                 :            :   {
      73                 :        798 :     TypeNode tn = s.getType();
      74         [ +  - ]:       1596 :     if (tn.isDatatypeConstructor() || tn.isDatatypeSelector()
      75 [ +  - ][ +  - ]:       1596 :         || tn.isDatatypeTester() || tn.isDatatypeUpdater())
         [ -  + ][ -  + ]
      76                 :            :     {
      77                 :            :       // datatype symbols should be considered interpreted symbols here, not
      78                 :            :       // (higher-order) variables.
      79                 :          0 :       continue;
      80                 :            :     }
      81                 :            :     // Notice that we allow for non-first class (e.g. function) variables here.
      82                 :       1596 :     std::stringstream ss;
      83                 :        798 :     ss << s;
      84                 :       1596 :     Node var = NodeManager::mkBoundVar(tn);
      85                 :        798 :     d_vars.push_back(var);
      86                 :       1596 :     Node vlv = NodeManager::mkBoundVar(ss.str(), tn);
      87                 :            :     // set that this variable encodes the term s
      88                 :            :     SygusVarToTermAttribute sta;
      89                 :        798 :     vlv.setAttribute(sta, s);
      90                 :        798 :     d_vlvs.push_back(vlv);
      91 [ +  + ][ +  + ]:        798 :     if (!needsShared || d_symSetShared.find(s) != d_symSetShared.end())
                 [ +  + ]
      92                 :            :     {
      93                 :        373 :       d_varsShared.push_back(var);
      94                 :        373 :       d_vlvsShared.push_back(vlv);
      95                 :        373 :       d_varTypesShared.push_back(tn);
      96                 :            :     }
      97                 :            :   }
      98                 :            :   // make the sygus variable list
      99         [ +  + ]:        616 :   if (!d_vlvsShared.empty())
     100                 :            :   {
     101                 :        274 :     d_ibvlShared = nm->mkNode(Kind::BOUND_VAR_LIST, d_vlvsShared);
     102                 :            :   }
     103         [ +  - ]:        616 :   Trace("sygus-interpol-debug") << "...finish" << std::endl;
     104                 :        616 : }
     105                 :            : 
     106                 :          2 : void SygusInterpol::getIncludeCons(
     107                 :            :     const std::vector<Node>& axioms,
     108                 :            :     const Node& conj,
     109                 :            :     std::map<TypeNode, std::unordered_set<Node>>& result)
     110                 :            : {
     111                 :          2 :   NodeManager* nm = nodeManager();
     112 [ -  + ][ -  + ]:          2 :   Assert(options().smt.produceInterpolants);
                 [ -  - ]
     113                 :            :   // ASSUMPTIONS
     114         [ +  + ]:          2 :   if (options().smt.interpolantsMode == options::InterpolantsMode::ASSUMPTIONS)
     115                 :            :   {
     116                 :            :     Node tmpAssumptions =
     117         [ -  + ]:          1 :         (axioms.size() == 1 ? axioms[0] : nm->mkNode(Kind::AND, axioms));
     118                 :          1 :     expr::getOperatorsMap(tmpAssumptions, result);
     119                 :            :   }
     120                 :            :   // CONJECTURE
     121                 :          1 :   else if (options().smt.interpolantsMode
     122         [ +  - ]:          1 :            == options::InterpolantsMode::CONJECTURE)
     123                 :            :   {
     124                 :          1 :     expr::getOperatorsMap(conj, result);
     125                 :            :   }
     126                 :            :   // SHARED
     127         [ -  - ]:          0 :   else if (options().smt.interpolantsMode == options::InterpolantsMode::SHARED)
     128                 :            :   {
     129                 :            :     // Get operators from axioms
     130                 :          0 :     std::map<TypeNode, std::unordered_set<Node>> include_cons_axioms;
     131                 :            :     Node tmpAssumptions =
     132         [ -  - ]:          0 :         (axioms.size() == 1 ? axioms[0] : nm->mkNode(Kind::AND, axioms));
     133                 :          0 :     expr::getOperatorsMap(tmpAssumptions, include_cons_axioms);
     134                 :            : 
     135                 :            :     // Get operators from conj
     136                 :          0 :     std::map<TypeNode, std::unordered_set<Node>> include_cons_conj;
     137                 :          0 :     expr::getOperatorsMap(conj, include_cons_conj);
     138                 :            : 
     139                 :            :     // Compute intersection
     140                 :          0 :     for (std::map<TypeNode, std::unordered_set<Node>>::iterator it =
     141                 :          0 :              include_cons_axioms.begin();
     142         [ -  - ]:          0 :          it != include_cons_axioms.end();
     143                 :          0 :          it++)
     144                 :            :     {
     145                 :          0 :       TypeNode tn = it->first;
     146                 :          0 :       std::unordered_set<Node> axiomsOps = it->second;
     147                 :            :       std::map<TypeNode, std::unordered_set<Node>>::iterator concIter =
     148                 :          0 :           include_cons_conj.find(tn);
     149         [ -  - ]:          0 :       if (concIter != include_cons_conj.end())
     150                 :            :       {
     151                 :          0 :         std::unordered_set<Node> conjOps = concIter->second;
     152         [ -  - ]:          0 :         for (const Node& n : axiomsOps)
     153                 :            :         {
     154         [ -  - ]:          0 :           if (conjOps.find(n) != conjOps.end())
     155                 :            :           {
     156         [ -  - ]:          0 :             if (result.find(tn) == result.end())
     157                 :            :             {
     158                 :          0 :               result[tn] = std::unordered_set<Node>();
     159                 :            :             }
     160                 :          0 :             result[tn].insert(n);
     161                 :            :           }
     162                 :            :         }
     163                 :            :       }
     164                 :            :     }
     165                 :            :   }
     166                 :            :   // ALL
     167         [ -  - ]:          0 :   else if (options().smt.interpolantsMode == options::InterpolantsMode::ALL)
     168                 :            :   {
     169                 :            :     Node tmpAssumptions =
     170         [ -  - ]:          0 :         (axioms.size() == 1 ? axioms[0] : nm->mkNode(Kind::AND, axioms));
     171                 :          0 :     Node tmpAll = nm->mkNode(Kind::AND, tmpAssumptions, conj);
     172                 :          0 :     expr::getOperatorsMap(tmpAll, result);
     173                 :            :   }
     174                 :          2 : }
     175                 :            : 
     176                 :        616 : TypeNode SygusInterpol::setSynthGrammar(const TypeNode& itpGType,
     177                 :            :                                         const std::vector<Node>& axioms,
     178                 :            :                                         const Node& conj)
     179                 :            : {
     180         [ +  - ]:        616 :   Trace("sygus-interpol-debug") << "Setup grammar..." << std::endl;
     181                 :        616 :   TypeNode itpGTypeS;
     182         [ +  + ]:        616 :   if (!itpGType.isNull())
     183                 :            :   {
     184                 :            :     // set user-defined grammar
     185 [ +  - ][ +  - ]:        680 :     Assert(itpGType.isDatatype() && itpGType.getDType().isSygus());
         [ -  + ][ -  - ]
     186                 :        680 :     itpGTypeS = datatypes::utils::substituteAndGeneralizeSygusType(
     187                 :        680 :         itpGType, d_syms, d_vlvs);
     188 [ +  - ][ +  - ]:        680 :     Assert(itpGTypeS.isDatatype() && itpGTypeS.getDType().isSygus());
         [ -  + ][ -  - ]
     189                 :            :     // TODO(Ying Sheng) check if the vars in user-defined grammar, are
     190                 :            :     // consistent with the shared vars
     191                 :            :   }
     192         [ +  + ]:        276 :   else if (options().smt.interpolantsMode != options::InterpolantsMode::DEFAULT)
     193                 :            :   {
     194                 :            :     // set default grammar, unless in DEFAULT mode, in which case we will
     195                 :            :     // provide no grammar in this module.
     196                 :          4 :     TypeNode btype = nodeManager()->booleanType();
     197                 :            :     SygusGrammar g =
     198                 :          4 :         SygusGrammarCons::mkDefaultGrammar(d_env, btype, d_ibvlShared);
     199                 :            :     // exclude rules that don't appear in operators
     200                 :          2 :     std::map<TypeNode, std::unordered_set<Node>> include_cons;
     201                 :          2 :     getIncludeCons(axioms, conj, include_cons);
     202                 :          2 :     const std::vector<Node>& ntSyms = g.getNtSyms();
     203         [ +  + ]:          4 :     for (const Node& ntSym : ntSyms)
     204                 :            :     {
     205                 :          2 :       std::vector<Node> rules = g.getRulesFor(ntSym);
     206                 :          2 :       TypeNode stype = ntSym.getType();
     207         [ -  + ]:          2 :       if (include_cons.find(stype) == include_cons.end())
     208                 :            :       {
     209                 :          0 :         continue;
     210                 :            :       }
     211                 :          2 :       const std::unordered_set<Node>& icons = include_cons[stype];
     212         [ +  + ]:          6 :       for (const Node& r : rules)
     213                 :            :       {
     214 [ -  + ][ -  - ]:          4 :         if (r.hasOperator() && icons.find(r.getOperator()) == icons.end())
         [ -  + ][ -  + ]
                 [ -  - ]
     215                 :            :         {
     216                 :          0 :           g.removeRule(ntSym, r);
     217                 :            :         }
     218                 :            :       }
     219                 :            :     }
     220                 :          2 :     itpGTypeS = g.resolve(true);
     221                 :            :   }
     222         [ +  - ]:        616 :   Trace("sygus-interpol-debug") << "...finish setting up grammar" << std::endl;
     223                 :        616 :   return itpGTypeS;
     224                 :            : }
     225                 :            : 
     226                 :        616 : Node SygusInterpol::mkPredicate(const std::string& name)
     227                 :            : {
     228                 :        616 :   NodeManager* nm = nodeManager();
     229                 :            :   // make the interpolation predicate to synthesize
     230         [ +  - ]:       1232 :   Trace("sygus-interpol-debug")
     231                 :        616 :       << "Make interpolation predicate..." << std::endl;
     232                 :        616 :   TypeNode itpType = d_varTypesShared.empty()
     233                 :            :                          ? nm->booleanType()
     234         [ +  + ]:       1232 :                          : nm->mkPredicateType(d_varTypesShared);
     235                 :       1232 :   Node itp = NodeManager::mkBoundVar(name.c_str(), itpType);
     236         [ +  - ]:        616 :   Trace("sygus-interpol-debug") << "...finish" << std::endl;
     237                 :       1232 :   return itp;
     238                 :            : }
     239                 :            : 
     240                 :        616 : void SygusInterpol::mkSygusConjecture(Node itp,
     241                 :            :                                       const std::vector<Node>& axioms,
     242                 :            :                                       const Node& conj)
     243                 :            : {
     244                 :        616 :   NodeManager* nm = nodeManager();
     245                 :            :   // make the interpolation application to synthesize
     246         [ +  - ]:       1232 :   Trace("sygus-interpol-debug")
     247                 :        616 :       << "Make interpolation predicate app..." << std::endl;
     248                 :       1232 :   std::vector<Node> ichildren;
     249                 :        616 :   ichildren.push_back(itp);
     250                 :        616 :   ichildren.insert(ichildren.end(), d_varsShared.begin(), d_varsShared.end());
     251                 :            :   Node itpApp =
     252         [ +  + ]:       1232 :       d_varsShared.empty() ? itp : nm->mkNode(Kind::APPLY_UF, ichildren);
     253         [ +  - ]:       1232 :   Trace("sygus-interpol-debug") << "itpApp: " << itpApp << std::endl
     254                 :        616 :                                 << std::endl;
     255         [ +  - ]:        616 :   Trace("sygus-interpol-debug") << "...finish" << std::endl;
     256                 :            : 
     257                 :            :   // set the sygus bound variable list
     258         [ +  - ]:        616 :   Trace("sygus-interpol-debug") << "Set attributes..." << std::endl;
     259         [ +  + ]:        616 :   if (!d_ibvlShared.isNull())
     260                 :            :   {
     261                 :        274 :     SygusUtils::setSygusArgumentList(itp, d_ibvlShared);
     262                 :            :   }
     263         [ +  - ]:        616 :   Trace("sygus-interpol-debug") << "...finish" << std::endl;
     264                 :            : 
     265                 :            :   // Fa( x )
     266         [ +  - ]:        616 :   Trace("sygus-interpol-debug") << "Make conjecture body..." << std::endl;
     267                 :       1232 :   Node Fa = nm->mkAnd(axioms);
     268                 :            :   // Fa( x ) => A( x )
     269                 :       1848 :   Node firstImplication = nm->mkNode(Kind::IMPLIES, Fa, itpApp);
     270         [ +  - ]:       1232 :   Trace("sygus-interpol-debug")
     271                 :          0 :       << "first implication: " << firstImplication << std::endl
     272                 :        616 :       << std::endl;
     273                 :            :   // A( x ) => Fc( x )
     274                 :       1232 :   Node Fc = conj;
     275                 :       1848 :   Node secondImplication = nm->mkNode(Kind::IMPLIES, itpApp, Fc);
     276         [ +  - ]:       1232 :   Trace("sygus-interpol-debug")
     277                 :          0 :       << "second implication: " << secondImplication << std::endl
     278                 :        616 :       << std::endl;
     279                 :            :   // Fa( x ) => A( x ) ^ A( x ) => Fc( x )
     280                 :       1232 :   Node constraint = nm->mkNode(Kind::AND, firstImplication, secondImplication);
     281                 :       1232 :   constraint = constraint.substitute(
     282                 :        616 :       d_syms.begin(), d_syms.end(), d_vars.begin(), d_vars.end());
     283         [ +  - ]:        616 :   Trace("sygus-interpol-debug") << constraint << "...finish" << std::endl;
     284                 :        616 :   constraint = rewrite(constraint);
     285                 :            : 
     286                 :        616 :   d_sygusConj = constraint;
     287         [ +  - ]:        616 :   Trace("sygus-interpol") << "Generate: " << d_sygusConj << std::endl;
     288                 :        616 : }
     289                 :            : 
     290                 :        693 : bool SygusInterpol::findInterpol(SolverEngine* subSolver,
     291                 :            :                                  Node& interpol,
     292                 :            :                                  Node itp)
     293                 :            : {
     294                 :            :   // get the synthesis solution
     295                 :       1386 :   std::map<Node, Node> sols;
     296         [ +  + ]:        693 :   if (!subSolver->getSynthSolutions(sols))
     297                 :            :   {
     298                 :          1 :     return false;
     299                 :            :   }
     300 [ -  + ][ -  + ]:        692 :   Assert(sols.size() == 1);
                 [ -  - ]
     301                 :        692 :   std::map<Node, Node>::iterator its = sols.find(itp);
     302         [ -  + ]:        692 :   if (its == sols.end())
     303                 :            :   {
     304         [ -  - ]:          0 :     Trace("sygus-interpol")
     305                 :          0 :         << "SolverEngine::getInterpol: could not find solution!" << std::endl;
     306                 :            :     throw RecoverableModalException(
     307                 :          0 :         "Could not find solution for get-interpolant.");
     308                 :            :     return false;
     309                 :            :   }
     310         [ +  - ]:       1384 :   Trace("sygus-interpol") << "SolverEngine::getInterpol: solution is "
     311                 :        692 :                           << its->second << std::endl;
     312                 :        692 :   interpol = its->second;
     313                 :            :   // replace back the created variables to original symbols.
     314         [ +  + ]:        692 :   if (interpol.getKind() == Kind::LAMBDA)
     315                 :            :   {
     316                 :        357 :     interpol = interpol[1];
     317                 :            :   }
     318                 :            : 
     319                 :            :   // get the grammar type for the interpolant
     320                 :       1384 :   Node igdtbv = SygusUtils::getOrMkSygusArgumentList(itp);
     321                 :            :   // could have no variables, in which case there is nothing to do
     322         [ +  + ]:        692 :   if (igdtbv.isNull())
     323                 :            :   {
     324                 :        335 :     return true;
     325                 :            :   }
     326 [ -  + ][ -  + ]:        357 :   Assert(igdtbv.getKind() == Kind::BOUND_VAR_LIST);
                 [ -  - ]
     327                 :            :   // convert back to original
     328                 :            :   // must replace formal arguments of itp with the free variables in the
     329                 :            :   // input problem that they correspond to.
     330                 :        714 :   std::vector<Node> vars;
     331                 :        357 :   std::vector<Node> syms;
     332                 :            :   SygusVarToTermAttribute sta;
     333         [ +  + ]:        812 :   for (const Node& bv : igdtbv)
     334                 :            :   {
     335                 :        455 :     vars.push_back(bv);
     336         [ +  - ]:        455 :     syms.push_back(bv.hasAttribute(sta) ? bv.getAttribute(sta) : bv);
     337                 :            :   }
     338                 :            :   interpol =
     339                 :        357 :       interpol.substitute(vars.begin(), vars.end(), syms.begin(), syms.end());
     340                 :            : 
     341                 :        357 :   return true;
     342                 :            : }
     343                 :            : 
     344                 :        616 : bool SygusInterpol::solveInterpolation(const std::string& name,
     345                 :            :                                        const std::vector<Node>& axioms,
     346                 :            :                                        const Node& conj,
     347                 :            :                                        const TypeNode& itpGType,
     348                 :            :                                        Node& interpol)
     349                 :            : {
     350                 :            :   // Some instructions in setSynthGrammar and mkSygusConjecture need a fully
     351                 :            :   // initialized solver to work properly. Notice, however, that the sub-solver
     352                 :            :   // created below is not fully initialized by the time those two methods are
     353                 :            :   // needed. Therefore, we call them while the current parent solver is in scope
     354                 :            :   // (i.e., before creating the sub-solver).
     355                 :        616 :   collectSymbols(axioms, conj);
     356                 :        616 :   createVariables(itpGType.isNull());
     357                 :       1232 :   TypeNode grammarType = setSynthGrammar(itpGType, axioms, conj);
     358                 :            : 
     359                 :        616 :   d_itp = mkPredicate(name);
     360                 :        616 :   mkSygusConjecture(d_itp, axioms, conj);
     361                 :            : 
     362                 :       1232 :   Options subOptions;
     363                 :        616 :   subOptions.copyValues(d_env.getOptions());
     364                 :        616 :   subOptions.write_quantifiers().sygus = true;
     365                 :        616 :   smt::SetDefaults::disableChecking(subOptions);
     366                 :       1232 :   SubsolverSetupInfo ssi(d_env, subOptions);
     367                 :        616 :   initializeSubsolver(d_subSolver, ssi);
     368                 :            : 
     369         [ +  + ]:       1414 :   for (const Node& var : d_vars)
     370                 :            :   {
     371                 :        798 :     d_subSolver->declareSygusVar(var);
     372                 :            :   }
     373                 :       1232 :   std::vector<Node> vars_empty;
     374                 :        616 :   d_subSolver->declareSynthFun(d_itp, grammarType, false, vars_empty);
     375         [ +  - ]:       1232 :   Trace("sygus-interpol")
     376                 :          0 :       << "SygusInterpol::solveInterpolation: made conjecture : " << d_sygusConj
     377                 :        616 :       << std::endl;
     378                 :        616 :   d_subSolver->assertSygusConstraint(d_sygusConj);
     379                 :            : 
     380         [ +  - ]:       1232 :   Trace("sygus-interpol")
     381                 :        616 :       << "  SygusInterpol::solveInterpolation check synth..." << std::endl;
     382                 :        616 :   SynthResult r = d_subSolver->checkSynth();
     383         [ +  - ]:       1232 :   Trace("sygus-interpol") << "  SygusInterpol::solveInterpolation result: " << r
     384                 :        616 :                           << std::endl;
     385         [ +  + ]:        616 :   if (r.getStatus() == SynthResult::SOLUTION)
     386                 :            :   {
     387                 :        609 :     return findInterpol(d_subSolver.get(), interpol, d_itp);
     388                 :            :   }
     389                 :          7 :   return false;
     390                 :            : }
     391                 :            : 
     392                 :         84 : bool SygusInterpol::solveInterpolationNext(Node& interpol)
     393                 :            : {
     394         [ +  - ]:        168 :   Trace("sygus-interpol")
     395                 :         84 :       << "  SygusInterpol::solveInterpolationNext check synth..." << std::endl;
     396                 :            :   // invoke the check-synth with isNext = true.
     397                 :         84 :   SynthResult r = d_subSolver->checkSynth(true);
     398         [ +  - ]:        168 :   Trace("sygus-interpol") << "  SygusInterpol::solveInterpolationNext result: "
     399                 :         84 :                           << r << std::endl;
     400         [ +  - ]:         84 :   if (r.getStatus() == SynthResult::SOLUTION)
     401                 :            :   {
     402                 :         84 :     return findInterpol(d_subSolver.get(), interpol, d_itp);
     403                 :            :   }
     404                 :          0 :   return false;
     405                 :            : }
     406                 :            : 
     407                 :            : }  // namespace quantifiers
     408                 :            : }  // namespace theory
     409                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14