LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/smt - env.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 179 186 96.2 %
Date: 2026-07-06 10:35:16 Functions: 47 47 100.0 %
Branches: 71 106 67.0 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * This file is part of the cvc5 project.
       3                 :            :  *
       4                 :            :  * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS
       5                 :            :  * in the top-level source directory and their institutional affiliations.
       6                 :            :  * All rights reserved.  See the file COPYING in the top-level source
       7                 :            :  * directory for licensing information.
       8                 :            :  * ****************************************************************************
       9                 :            :  *
      10                 :            :  * Smt Environment, main access to global utilities available to
      11                 :            :  * internal code.
      12                 :            :  */
      13                 :            : 
      14                 :            : #include "smt/env.h"
      15                 :            : 
      16                 :            : #include "context/context.h"
      17                 :            : #include "expr/node.h"
      18                 :            : #include "expr/node_algorithm.h"
      19                 :            : #include "expr/skolem_manager.h"
      20                 :            : #include "expr/subtype_elim_node_converter.h"
      21                 :            : #include "options/base_options.h"
      22                 :            : #include "options/printer_options.h"
      23                 :            : #include "options/quantifiers_options.h"
      24                 :            : #include "options/smt_options.h"
      25                 :            : #include "options/strings_options.h"
      26                 :            : #include "printer/printer.h"
      27                 :            : #include "proof/conv_proof_generator.h"
      28                 :            : #include "smt/proof_manager.h"
      29                 :            : #include "smt/solver_engine_stats.h"
      30                 :            : #include "theory/evaluator.h"
      31                 :            : #include "theory/quantifiers/oracle_checker.h"
      32                 :            : #include "theory/rewriter.h"
      33                 :            : #include "theory/theory.h"
      34                 :            : #include "theory/trust_substitutions.h"
      35                 :            : #include "util/resource_manager.h"
      36                 :            : #include "util/statistics_registry.h"
      37                 :            : 
      38                 :            : using namespace cvc5::internal::smt;
      39                 :            : 
      40                 :            : namespace cvc5::internal {
      41                 :            : 
      42                 :      76257 : Env::Env(NodeManager* nm, const Options* opts)
      43                 :      76257 :     : d_nm(nm),
      44                 :      76257 :       d_context(new context::Context()),
      45                 :      76257 :       d_userContext(new context::UserContext()),
      46                 :      76257 :       d_pfManager(nullptr),
      47                 :      76257 :       d_proofNodeManager(nullptr),
      48                 :      76257 :       d_rewriter(new theory::Rewriter(nm)),
      49                 :      76257 :       d_evalRew(nullptr),
      50                 :      76257 :       d_eval(nullptr),
      51                 :      76257 :       d_topLevelSubs(nullptr),
      52                 :      76257 :       d_logic(),
      53                 :      76257 :       d_options(),
      54                 :      76257 :       d_resourceManager(),
      55                 :      76257 :       d_uninterpretedSortOwner(theory::THEORY_UF),
      56                 :     152514 :       d_boolTermSkolems(d_userContext.get())
      57                 :            : {
      58         [ +  + ]:      76257 :   if (opts != nullptr)
      59                 :            :   {
      60                 :      75821 :     d_options.copyValues(*opts);
      61                 :            :   }
      62                 :      76257 :   d_statisticsRegistry.reset(new StatisticsRegistry(
      63                 :      76257 :       d_options.base.statisticsInternal, d_options.base.statisticsAll));
      64                 :            :   // make the evaluators, which depend on the alphabet of strings
      65                 :     152514 :   d_evalRew.reset(new theory::Evaluator(d_rewriter.get(),
      66                 :      76257 :                                         d_options.strings.stringsAlphaCard));
      67                 :      76257 :   d_eval.reset(
      68                 :      76257 :       new theory::Evaluator(nullptr, d_options.strings.stringsAlphaCard));
      69                 :      76257 :   d_statisticsRegistry->registerTimer("global::totalTime").start();
      70                 :            :   d_resourceManager =
      71                 :      76257 :       std::make_unique<ResourceManager>(*d_statisticsRegistry, d_options);
      72                 :      76257 :   d_rewriter->d_resourceManager = d_resourceManager.get();
      73                 :      76257 : }
      74                 :            : 
      75                 :      71170 : Env::~Env() {}
      76                 :            : 
      77                 :  102334436 : NodeManager* Env::getNodeManager() const { return d_nm; }
      78                 :            : 
      79                 :      51324 : void Env::finishInit(smt::PfManager* pm)
      80                 :            : {
      81         [ +  + ]:      51324 :   if (pm != nullptr)
      82                 :            :   {
      83                 :      20033 :     d_pfManager = pm;
      84 [ -  + ][ -  + ]:      20033 :     Assert(d_proofNodeManager == nullptr);
                 [ -  - ]
      85                 :      20033 :     d_proofNodeManager = pm->getProofNodeManager();
      86                 :      20033 :     d_rewriter->finishInit(*this);
      87                 :            :   }
      88                 :     102648 :   d_topLevelSubs.reset(
      89                 :     102648 :       new theory::TrustSubstitutionMap(*this, d_userContext.get()));
      90                 :            : 
      91         [ +  + ]:      51324 :   if (d_options.quantifiers.oracles)
      92                 :            :   {
      93                 :        535 :     d_ochecker.reset(new theory::quantifiers::OracleChecker(*this));
      94                 :            :   }
      95                 :      51324 :   d_statisticsRegistry->setStatsAll(d_options.base.statisticsAll);
      96                 :      51324 :   d_statisticsRegistry->setStatsInternal(d_options.base.statisticsInternal);
      97                 :      51324 : }
      98                 :            : 
      99                 :      71150 : void Env::shutdown()
     100                 :            : {
     101                 :      71150 :   d_rewriter.reset(nullptr);
     102                 :            :   // d_resourceManager must be destroyed before d_statisticsRegistry
     103                 :      71150 :   d_resourceManager.reset(nullptr);
     104                 :      71150 : }
     105                 :            : 
     106                 :   54373367 : context::Context* Env::getContext() { return d_context.get(); }
     107                 :            : 
     108                 :    8364802 : context::UserContext* Env::getUserContext() { return d_userContext.get(); }
     109                 :            : 
     110                 :      52019 : smt::PfManager* Env::getProofManager() { return d_pfManager; }
     111                 :            : 
     112                 :      26981 : ProofLogger* Env::getProofLogger()
     113                 :            : {
     114         [ +  - ]:      26981 :   return d_pfManager ? d_pfManager->getProofLogger() : nullptr;
     115                 :            : }
     116                 :            : 
     117                 :   86298452 : ProofNodeManager* Env::getProofNodeManager() { return d_proofNodeManager; }
     118                 :            : 
     119                 :     209646 : bool Env::isProofProducing() const { return d_proofNodeManager != nullptr; }
     120                 :            : 
     121                 :     978545 : bool Env::isSatProofProducing() const
     122                 :            : {
     123                 :     978545 :   return d_proofNodeManager != nullptr
     124 [ +  + ][ +  + ]:     978545 :          && d_options.smt.proofMode != options::ProofMode::PP_ONLY;
     125                 :            : }
     126                 :            : 
     127                 :   15087783 : bool Env::isTheoryProofProducing() const
     128                 :            : {
     129                 :   15087783 :   return d_proofNodeManager != nullptr
     130 [ +  + ][ +  + ]:   17313454 :          && (d_options.smt.proofMode == options::ProofMode::FULL
     131         [ -  + ]:   17313454 :              || d_options.smt.proofMode == options::ProofMode::FULL_STRICT);
     132                 :            : }
     133                 :            : 
     134                 :   93492867 : theory::Rewriter* Env::getRewriter() { return d_rewriter.get(); }
     135                 :            : 
     136                 :      51330 : theory::Evaluator* Env::getEvaluator(bool useRewriter)
     137                 :            : {
     138         [ -  + ]:      51330 :   return useRewriter ? d_evalRew.get() : d_eval.get();
     139                 :            : }
     140                 :            : 
     141                 :     855191 : theory::TrustSubstitutionMap& Env::getTopLevelSubstitutions()
     142                 :            : {
     143                 :     855191 :   return *d_topLevelSubs.get();
     144                 :            : }
     145                 :            : 
     146                 :  368025843 : const LogicInfo& Env::getLogicInfo() const { return d_logic; }
     147                 :            : 
     148                 :    9737420 : StatisticsRegistry& Env::getStatisticsRegistry()
     149                 :            : {
     150                 :    9737420 :   return *d_statisticsRegistry;
     151                 :            : }
     152                 :            : 
     153                 :  332745086 : const Options& Env::getOptions() const { return d_options; }
     154                 :            : 
     155                 :   44126273 : ResourceManager* Env::getResourceManager() const
     156                 :            : {
     157                 :   44126273 :   return d_resourceManager.get();
     158                 :            : }
     159                 :            : 
     160                 :    5222711 : bool Env::isOutputOn(OutputTag tag) const
     161                 :            : {
     162                 :    5222711 :   return d_options.base.outputTagHolder[static_cast<size_t>(tag)];
     163                 :            : }
     164                 :     676663 : bool Env::isOutputOn(const std::string& tag) const
     165                 :            : {
     166                 :     676663 :   return isOutputOn(options::stringToOutputTag(tag));
     167                 :            : }
     168                 :     138484 : std::ostream& Env::output(const std::string& tag) const
     169                 :            : {
     170                 :     138484 :   return output(options::stringToOutputTag(tag));
     171                 :            : }
     172                 :            : 
     173                 :     160039 : std::ostream& Env::output(OutputTag tag) const
     174                 :            : {
     175         [ +  + ]:     160039 :   if (isOutputOn(tag))
     176                 :            :   {
     177                 :     138695 :     return *d_options.base.out;
     178                 :            :   }
     179                 :      21344 :   return cvc5::internal::null_os;
     180                 :            : }
     181                 :            : 
     182                 :    1971117 : bool Env::isVerboseOn(int64_t level) const
     183                 :            : {
     184 [ +  - ][ +  + ]:    1971117 :   return !Configuration::isMuzzledBuild() && d_options.base.verbosity >= level;
     185                 :            : }
     186                 :            : 
     187                 :    1970466 : std::ostream& Env::verbose(int64_t level) const
     188                 :            : {
     189         [ +  + ]:    1970466 :   if (isVerboseOn(level))
     190                 :            :   {
     191                 :        396 :     return *d_options.base.err;
     192                 :            :   }
     193                 :    1970070 :   return cvc5::internal::null_os;
     194                 :            : }
     195                 :            : 
     196                 :        310 : std::ostream& Env::warning() const { return verbose(0); }
     197                 :            : 
     198                 :    1623777 : Node Env::evaluate(TNode n,
     199                 :            :                    const std::vector<Node>& args,
     200                 :            :                    const std::vector<Node>& vals,
     201                 :            :                    bool useRewriter) const
     202                 :            : {
     203                 :    1623777 :   std::unordered_map<Node, Node> visited;
     204                 :    3247554 :   return evaluate(n, args, vals, visited, useRewriter);
     205                 :    1623777 : }
     206                 :            : 
     207                 :    1684614 : Node Env::evaluate(TNode n,
     208                 :            :                    const std::vector<Node>& args,
     209                 :            :                    const std::vector<Node>& vals,
     210                 :            :                    const std::unordered_map<Node, Node>& visited,
     211                 :            :                    bool useRewriter) const
     212                 :            : {
     213         [ +  + ]:    1684614 :   if (useRewriter)
     214                 :            :   {
     215                 :     957102 :     return d_evalRew->eval(n, args, vals, visited);
     216                 :            :   }
     217                 :     727512 :   return d_eval->eval(n, args, vals, visited);
     218                 :            : }
     219                 :            : 
     220                 :    2273634 : Node Env::rewriteViaMethod(TNode n, MethodId idr)
     221                 :            : {
     222         [ +  + ]:    2273634 :   if (idr == MethodId::RW_REWRITE)
     223                 :            :   {
     224                 :    1536903 :     return d_rewriter->rewrite(n);
     225                 :            :   }
     226         [ +  + ]:     736731 :   if (idr == MethodId::RW_EXT_REWRITE)
     227                 :            :   {
     228                 :      10911 :     return d_rewriter->extendedRewrite(n, false);
     229                 :            :   }
     230         [ +  + ]:     725820 :   if (idr == MethodId::RW_EXT_REWRITE_AGG)
     231                 :            :   {
     232                 :        585 :     return d_rewriter->extendedRewrite(n, true);
     233                 :            :   }
     234         [ +  + ]:     725235 :   if (idr == MethodId::RW_REWRITE_EQ_EXT)
     235                 :            :   {
     236                 :       3046 :     return d_rewriter->rewriteEqualityExt(n);
     237                 :            :   }
     238         [ +  - ]:     722189 :   if (idr == MethodId::RW_EVALUATE)
     239                 :            :   {
     240                 :     722189 :     return evaluate(n, {}, {}, false);
     241                 :            :   }
     242         [ -  - ]:          0 :   if (idr == MethodId::RW_IDENTITY)
     243                 :            :   {
     244                 :            :     // does nothing
     245                 :          0 :     return n;
     246                 :            :   }
     247                 :            :   // unknown rewriter
     248                 :          0 :   Unhandled() << "Env::rewriteViaMethod: no rewriter for " << idr << std::endl;
     249                 :            :   return n;
     250                 :            : }
     251                 :            : 
     252                 :   17737894 : bool Env::isFiniteType(TypeNode tn) const
     253                 :            : {
     254                 :   17737894 :   return isCardinalityClassFinite(tn.getCardinalityClass(),
     255                 :   35475788 :                                   d_options.quantifiers.finiteModelFind);
     256                 :            : }
     257                 :            : 
     258                 :     264111 : bool Env::isFiniteCardinalityClass(CardinalityClass cc) const
     259                 :            : {
     260                 :     264111 :   return isCardinalityClassFinite(cc, d_options.quantifiers.finiteModelFind);
     261                 :            : }
     262                 :            : 
     263                 :     246758 : bool Env::isFirstClassType(TypeNode tn) const
     264                 :            : {
     265         [ +  + ]:     246758 :   if (tn.isRegExp())
     266                 :            :   {
     267                 :          8 :     return d_options.strings.regExpFirstClass;
     268                 :            :   }
     269                 :     246750 :   return tn.isFirstClass();
     270                 :            : }
     271                 :            : 
     272                 :      51326 : void Env::setUninterpretedSortOwner(theory::TheoryId theory)
     273                 :            : {
     274                 :      51326 :   d_uninterpretedSortOwner = theory;
     275                 :      51326 : }
     276                 :            : 
     277                 :    2089539 : theory::TheoryId Env::getUninterpretedSortOwner() const
     278                 :            : {
     279                 :    2089539 :   return d_uninterpretedSortOwner;
     280                 :            : }
     281                 :            : 
     282                 :    8439898 : theory::TheoryId Env::theoryOf(TypeNode typeNode) const
     283                 :            : {
     284                 :    8439898 :   return theory::Theory::theoryOf(typeNode, d_uninterpretedSortOwner);
     285                 :            : }
     286                 :            : 
     287                 :  148936103 : theory::TheoryId Env::theoryOf(TNode node) const
     288                 :            : {
     289                 :  148936103 :   theory::TheoryId tid = theory::Theory::theoryOf(
     290                 :  148936103 :       node, d_options.theory.theoryOfMode, d_uninterpretedSortOwner);
     291                 :            :   // Special case: Boolean term skolems belong to THEORY_UF.
     292 [ +  + ][ +  + ]:  148936103 :   if (tid == theory::TheoryId::THEORY_BOOL && isBooleanTermSkolem(node))
         [ +  + ][ +  + ]
                 [ -  - ]
     293                 :            :   {
     294                 :     255307 :     return theory::TheoryId::THEORY_UF;
     295                 :            :   }
     296                 :  148680796 :   return tid;
     297                 :            : }
     298                 :            : 
     299                 :     217313 : bool Env::hasSepHeap() const { return !d_sepLocType.isNull(); }
     300                 :            : 
     301                 :      16233 : TypeNode Env::getSepLocType() const { return d_sepLocType; }
     302                 :            : 
     303                 :      16233 : TypeNode Env::getSepDataType() const { return d_sepDataType; }
     304                 :            : 
     305                 :       1069 : void Env::declareSepHeap(TypeNode locT, TypeNode dataT)
     306                 :            : {
     307 [ -  + ][ -  + ]:       1069 :   Assert(!locT.isNull());
                 [ -  - ]
     308 [ -  + ][ -  + ]:       1069 :   Assert(!dataT.isNull());
                 [ -  - ]
     309                 :            :   // remember the types we have set
     310                 :       1069 :   d_sepLocType = locT;
     311                 :       1069 :   d_sepDataType = dataT;
     312                 :       1069 : }
     313                 :            : 
     314                 :         28 : void Env::addPlugin(Plugin* p) { d_plugins.push_back(p); }
     315                 :     905548 : const std::vector<Plugin*>& Env::getPlugins() const { return d_plugins; }
     316                 :            : 
     317                 :      10297 : theory::quantifiers::OracleChecker* Env::getOracleChecker() const
     318                 :            : {
     319                 :      10297 :   return d_ochecker.get();
     320                 :            : }
     321                 :            : 
     322                 :       3704 : void Env::registerBooleanTermSkolem(const Node& k)
     323                 :            : {
     324 [ -  + ][ -  + ]:       3704 :   Assert(k.isVar());
                 [ -  - ]
     325                 :       3704 :   d_boolTermSkolems.insert(k);
     326                 :       3704 : }
     327                 :            : 
     328                 :   14193189 : bool Env::isBooleanTermSkolem(const Node& k) const
     329                 :            : {
     330                 :            :   // optimization: check whether k is a variable
     331         [ +  + ]:   14193189 :   if (!k.isVar())
     332                 :            :   {
     333                 :   13825384 :     return false;
     334                 :            :   }
     335                 :     367805 :   return d_boolTermSkolems.find(k) != d_boolTermSkolems.end();
     336                 :            : }
     337                 :            : 
     338                 :        105 : Node Env::getSharableFormula(const Node& n) const
     339                 :            : {
     340                 :        105 :   Node on = n;
     341         [ -  + ]:        105 :   if (!d_options.base.pluginShareSkolems)
     342                 :            :   {
     343                 :            :     // note we only remove purify skolems if the above option is disabled
     344                 :          0 :     on = SkolemManager::getOriginalForm(n);
     345                 :            :   }
     346                 :        105 :   SkolemManager* skm = d_nm->getSkolemManager();
     347                 :        105 :   std::vector<Node> toProcess;
     348                 :        105 :   toProcess.push_back(on);
     349                 :            :   // The set of kinds that we never want to share. Any kind that can appear
     350                 :            :   // in lemmas but we don't have API support for should go in this list.
     351                 :            :   const std::unordered_set<Kind> excludeKinds = {
     352                 :            :       Kind::INST_CONSTANT,
     353                 :            :       Kind::DUMMY_SKOLEM,
     354                 :            :       Kind::CARDINALITY_CONSTRAINT,
     355                 :        105 :       Kind::COMBINED_CARDINALITY_CONSTRAINT};
     356                 :        105 :   size_t index = 0;
     357                 :            :   do
     358                 :            :   {
     359                 :        155 :     Node nn = toProcess[index];
     360                 :        155 :     index++;
     361                 :            :     // get the symbols contained in nn
     362                 :        155 :     std::unordered_set<Node> syms;
     363                 :        155 :     expr::getSymbols(nn, syms);
     364         [ +  + ]:        298 :     for (const Node& s : syms)
     365                 :            :     {
     366                 :        143 :       Kind sk = s.getKind();
     367         [ -  + ]:        143 :       if (excludeKinds.find(sk) != excludeKinds.end())
     368                 :            :       {
     369                 :            :         // these kinds are never sharable
     370                 :          0 :         return Node::null();
     371                 :            :       }
     372         [ +  + ]:        143 :       if (sk == Kind::SKOLEM)
     373                 :            :       {
     374         [ -  + ]:         50 :         if (!d_options.base.pluginShareSkolems)
     375                 :            :         {
     376                 :            :           // not shared if option is false
     377                 :          0 :           return Node::null();
     378                 :            :         }
     379                 :            :         // must ensure that the indices of the skolem are also legal
     380                 :            :         SkolemId id;
     381                 :         50 :         Node cacheVal;
     382         [ -  + ]:         50 :         if (!skm->isSkolemFunction(s, id, cacheVal))
     383                 :            :         {
     384                 :            :           // kind SKOLEM should imply that it is a skolem function
     385                 :          0 :           DebugUnhandled();
     386                 :            :           return Node::null();
     387                 :            :         }
     388                 :         50 :         if (!cacheVal.isNull()
     389 [ +  - ][ +  - ]:        150 :             && std::find(toProcess.begin(), toProcess.end(), cacheVal)
     390         [ +  - ]:        150 :                    == toProcess.end())
     391                 :            :         {
     392                 :            :           // if we have a cache value, add it to process vector
     393                 :         50 :           toProcess.push_back(cacheVal);
     394                 :            :         }
     395         [ +  - ]:         50 :       }
     396                 :            :     }
     397 [ +  - ][ +  - ]:        310 :   } while (index < toProcess.size());
                 [ +  + ]
     398                 :            :   // If we didn't encounter an illegal term, we now eliminate subtyping
     399                 :        105 :   SubtypeElimNodeConverter senc(d_nm);
     400                 :        105 :   on = senc.convert(on);
     401                 :        105 :   return on;
     402                 :        105 : }
     403                 :            : 
     404                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14