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-04-19 10:41:43 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                 :      75684 : Env::Env(NodeManager* nm, const Options* opts)
      43                 :      75684 :     : d_nm(nm),
      44                 :      75684 :       d_context(new context::Context()),
      45                 :      75684 :       d_userContext(new context::UserContext()),
      46                 :      75684 :       d_pfManager(nullptr),
      47                 :      75684 :       d_proofNodeManager(nullptr),
      48                 :      75684 :       d_rewriter(new theory::Rewriter(nm)),
      49                 :      75684 :       d_evalRew(nullptr),
      50                 :      75684 :       d_eval(nullptr),
      51                 :      75684 :       d_topLevelSubs(nullptr),
      52                 :      75684 :       d_logic(),
      53                 :      75684 :       d_options(),
      54                 :      75684 :       d_resourceManager(),
      55                 :      75684 :       d_uninterpretedSortOwner(theory::THEORY_UF),
      56                 :     151368 :       d_boolTermSkolems(d_userContext.get())
      57                 :            : {
      58         [ +  + ]:      75684 :   if (opts != nullptr)
      59                 :            :   {
      60                 :      75251 :     d_options.copyValues(*opts);
      61                 :            :   }
      62                 :      75684 :   d_statisticsRegistry.reset(new StatisticsRegistry(
      63                 :      75684 :       d_options.base.statisticsInternal, d_options.base.statisticsAll));
      64                 :            :   // make the evaluators, which depend on the alphabet of strings
      65                 :     151368 :   d_evalRew.reset(new theory::Evaluator(d_rewriter.get(),
      66                 :      75684 :                                         d_options.strings.stringsAlphaCard));
      67                 :      75684 :   d_eval.reset(
      68                 :      75684 :       new theory::Evaluator(nullptr, d_options.strings.stringsAlphaCard));
      69                 :      75684 :   d_statisticsRegistry->registerTimer("global::totalTime").start();
      70                 :            :   d_resourceManager =
      71                 :      75684 :       std::make_unique<ResourceManager>(*d_statisticsRegistry, d_options);
      72                 :      75684 :   d_rewriter->d_resourceManager = d_resourceManager.get();
      73                 :      75684 : }
      74                 :            : 
      75                 :      70656 : Env::~Env() {}
      76                 :            : 
      77                 :  104009843 : NodeManager* Env::getNodeManager() const { return d_nm; }
      78                 :            : 
      79                 :      50931 : void Env::finishInit(smt::PfManager* pm)
      80                 :            : {
      81         [ +  + ]:      50931 :   if (pm != nullptr)
      82                 :            :   {
      83                 :      19687 :     d_pfManager = pm;
      84 [ -  + ][ -  + ]:      19687 :     Assert(d_proofNodeManager == nullptr);
                 [ -  - ]
      85                 :      19687 :     d_proofNodeManager = pm->getProofNodeManager();
      86                 :      19687 :     d_rewriter->finishInit(*this);
      87                 :            :   }
      88                 :     101862 :   d_topLevelSubs.reset(
      89                 :     101862 :       new theory::TrustSubstitutionMap(*this, d_userContext.get()));
      90                 :            : 
      91         [ +  + ]:      50931 :   if (d_options.quantifiers.oracles)
      92                 :            :   {
      93                 :        535 :     d_ochecker.reset(new theory::quantifiers::OracleChecker(*this));
      94                 :            :   }
      95                 :      50931 :   d_statisticsRegistry->setStatsAll(d_options.base.statisticsAll);
      96                 :      50931 :   d_statisticsRegistry->setStatsInternal(d_options.base.statisticsInternal);
      97                 :      50931 : }
      98                 :            : 
      99                 :      70636 : void Env::shutdown()
     100                 :            : {
     101                 :      70636 :   d_rewriter.reset(nullptr);
     102                 :            :   // d_resourceManager must be destroyed before d_statisticsRegistry
     103                 :      70636 :   d_resourceManager.reset(nullptr);
     104                 :      70636 : }
     105                 :            : 
     106                 :   54522336 : context::Context* Env::getContext() { return d_context.get(); }
     107                 :            : 
     108                 :    8211810 : context::UserContext* Env::getUserContext() { return d_userContext.get(); }
     109                 :            : 
     110                 :      51624 : smt::PfManager* Env::getProofManager() { return d_pfManager; }
     111                 :            : 
     112                 :      26633 : ProofLogger* Env::getProofLogger()
     113                 :            : {
     114         [ +  - ]:      26633 :   return d_pfManager ? d_pfManager->getProofLogger() : nullptr;
     115                 :            : }
     116                 :            : 
     117                 :   88161284 : ProofNodeManager* Env::getProofNodeManager() { return d_proofNodeManager; }
     118                 :            : 
     119                 :     194284 : bool Env::isProofProducing() const { return d_proofNodeManager != nullptr; }
     120                 :            : 
     121                 :     970727 : bool Env::isSatProofProducing() const
     122                 :            : {
     123                 :     970727 :   return d_proofNodeManager != nullptr
     124 [ +  + ][ +  + ]:     970727 :          && d_options.smt.proofMode != options::ProofMode::PP_ONLY;
     125                 :            : }
     126                 :            : 
     127                 :   14903394 : bool Env::isTheoryProofProducing() const
     128                 :            : {
     129                 :   14903394 :   return d_proofNodeManager != nullptr
     130 [ +  + ][ +  + ]:   17114900 :          && (d_options.smt.proofMode == options::ProofMode::FULL
     131         [ -  + ]:   17114900 :              || d_options.smt.proofMode == options::ProofMode::FULL_STRICT);
     132                 :            : }
     133                 :            : 
     134                 :   89947678 : theory::Rewriter* Env::getRewriter() { return d_rewriter.get(); }
     135                 :            : 
     136                 :      50937 : theory::Evaluator* Env::getEvaluator(bool useRewriter)
     137                 :            : {
     138         [ -  + ]:      50937 :   return useRewriter ? d_evalRew.get() : d_eval.get();
     139                 :            : }
     140                 :            : 
     141                 :     869100 : theory::TrustSubstitutionMap& Env::getTopLevelSubstitutions()
     142                 :            : {
     143                 :     869100 :   return *d_topLevelSubs.get();
     144                 :            : }
     145                 :            : 
     146                 :  359670084 : const LogicInfo& Env::getLogicInfo() const { return d_logic; }
     147                 :            : 
     148                 :    9652017 : StatisticsRegistry& Env::getStatisticsRegistry()
     149                 :            : {
     150                 :    9652017 :   return *d_statisticsRegistry;
     151                 :            : }
     152                 :            : 
     153                 :  348567756 : const Options& Env::getOptions() const { return d_options; }
     154                 :            : 
     155                 :   43331844 : ResourceManager* Env::getResourceManager() const
     156                 :            : {
     157                 :   43331844 :   return d_resourceManager.get();
     158                 :            : }
     159                 :            : 
     160                 :    5170067 : bool Env::isOutputOn(OutputTag tag) const
     161                 :            : {
     162                 :    5170067 :   return d_options.base.outputTagHolder[static_cast<size_t>(tag)];
     163                 :            : }
     164                 :     674244 : bool Env::isOutputOn(const std::string& tag) const
     165                 :            : {
     166                 :     674244 :   return isOutputOn(options::stringToOutputTag(tag));
     167                 :            : }
     168                 :     138070 : std::ostream& Env::output(const std::string& tag) const
     169                 :            : {
     170                 :     138070 :   return output(options::stringToOutputTag(tag));
     171                 :            : }
     172                 :            : 
     173                 :     159630 : std::ostream& Env::output(OutputTag tag) const
     174                 :            : {
     175         [ +  + ]:     159630 :   if (isOutputOn(tag))
     176                 :            :   {
     177                 :     138281 :     return *d_options.base.out;
     178                 :            :   }
     179                 :      21349 :   return cvc5::internal::null_os;
     180                 :            : }
     181                 :            : 
     182                 :    1973706 : bool Env::isVerboseOn(int64_t level) const
     183                 :            : {
     184 [ +  - ][ +  + ]:    1973706 :   return !Configuration::isMuzzledBuild() && d_options.base.verbosity >= level;
     185                 :            : }
     186                 :            : 
     187                 :    1973049 : std::ostream& Env::verbose(int64_t level) const
     188                 :            : {
     189         [ +  + ]:    1973049 :   if (isVerboseOn(level))
     190                 :            :   {
     191                 :        399 :     return *d_options.base.err;
     192                 :            :   }
     193                 :    1972650 :   return cvc5::internal::null_os;
     194                 :            : }
     195                 :            : 
     196                 :        310 : std::ostream& Env::warning() const { return verbose(0); }
     197                 :            : 
     198                 :    1377518 : Node Env::evaluate(TNode n,
     199                 :            :                    const std::vector<Node>& args,
     200                 :            :                    const std::vector<Node>& vals,
     201                 :            :                    bool useRewriter) const
     202                 :            : {
     203                 :    1377518 :   std::unordered_map<Node, Node> visited;
     204                 :    2755036 :   return evaluate(n, args, vals, visited, useRewriter);
     205                 :    1377518 : }
     206                 :            : 
     207                 :    1438353 : 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         [ +  + ]:    1438353 :   if (useRewriter)
     214                 :            :   {
     215                 :     895891 :     return d_evalRew->eval(n, args, vals, visited);
     216                 :            :   }
     217                 :     542462 :   return d_eval->eval(n, args, vals, visited);
     218                 :            : }
     219                 :            : 
     220                 :    2034780 : Node Env::rewriteViaMethod(TNode n, MethodId idr)
     221                 :            : {
     222         [ +  + ]:    2034780 :   if (idr == MethodId::RW_REWRITE)
     223                 :            :   {
     224                 :    1482969 :     return d_rewriter->rewrite(n);
     225                 :            :   }
     226         [ +  + ]:     551811 :   if (idr == MethodId::RW_EXT_REWRITE)
     227                 :            :   {
     228                 :      10752 :     return d_rewriter->extendedRewrite(n, false);
     229                 :            :   }
     230         [ +  + ]:     541059 :   if (idr == MethodId::RW_EXT_REWRITE_AGG)
     231                 :            :   {
     232                 :        567 :     return d_rewriter->extendedRewrite(n, true);
     233                 :            :   }
     234         [ +  + ]:     540492 :   if (idr == MethodId::RW_REWRITE_EQ_EXT)
     235                 :            :   {
     236                 :       3034 :     return d_rewriter->rewriteEqualityExt(n);
     237                 :            :   }
     238         [ +  - ]:     537458 :   if (idr == MethodId::RW_EVALUATE)
     239                 :            :   {
     240                 :     537458 :     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                 :   17082335 : bool Env::isFiniteType(TypeNode tn) const
     253                 :            : {
     254                 :   17082335 :   return isCardinalityClassFinite(tn.getCardinalityClass(),
     255                 :   34164670 :                                   d_options.quantifiers.finiteModelFind);
     256                 :            : }
     257                 :            : 
     258                 :     261293 : bool Env::isFiniteCardinalityClass(CardinalityClass cc) const
     259                 :            : {
     260                 :     261293 :   return isCardinalityClassFinite(cc, d_options.quantifiers.finiteModelFind);
     261                 :            : }
     262                 :            : 
     263                 :     240124 : bool Env::isFirstClassType(TypeNode tn) const
     264                 :            : {
     265         [ +  + ]:     240124 :   if (tn.isRegExp())
     266                 :            :   {
     267                 :          8 :     return d_options.strings.regExpFirstClass;
     268                 :            :   }
     269                 :     240116 :   return tn.isFirstClass();
     270                 :            : }
     271                 :            : 
     272                 :      50933 : void Env::setUninterpretedSortOwner(theory::TheoryId theory)
     273                 :            : {
     274                 :      50933 :   d_uninterpretedSortOwner = theory;
     275                 :      50933 : }
     276                 :            : 
     277                 :    1984904 : theory::TheoryId Env::getUninterpretedSortOwner() const
     278                 :            : {
     279                 :    1984904 :   return d_uninterpretedSortOwner;
     280                 :            : }
     281                 :            : 
     282                 :    8146518 : theory::TheoryId Env::theoryOf(TypeNode typeNode) const
     283                 :            : {
     284                 :    8146518 :   return theory::Theory::theoryOf(typeNode, d_uninterpretedSortOwner);
     285                 :            : }
     286                 :            : 
     287                 :  145374535 : theory::TheoryId Env::theoryOf(TNode node) const
     288                 :            : {
     289                 :  145374535 :   theory::TheoryId tid = theory::Theory::theoryOf(
     290                 :  145374535 :       node, d_options.theory.theoryOfMode, d_uninterpretedSortOwner);
     291                 :            :   // Special case: Boolean term skolems belong to THEORY_UF.
     292 [ +  + ][ +  + ]:  145374535 :   if (tid == theory::TheoryId::THEORY_BOOL && isBooleanTermSkolem(node))
         [ +  + ][ +  + ]
                 [ -  - ]
     293                 :            :   {
     294                 :     219394 :     return theory::TheoryId::THEORY_UF;
     295                 :            :   }
     296                 :  145155141 :   return tid;
     297                 :            : }
     298                 :            : 
     299                 :     214648 : bool Env::hasSepHeap() const { return !d_sepLocType.isNull(); }
     300                 :            : 
     301                 :      16054 : TypeNode Env::getSepLocType() const { return d_sepLocType; }
     302                 :            : 
     303                 :      16054 : 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                 :     910861 : const std::vector<Plugin*>& Env::getPlugins() const { return d_plugins; }
     316                 :            : 
     317                 :      10291 : theory::quantifiers::OracleChecker* Env::getOracleChecker() const
     318                 :            : {
     319                 :      10291 :   return d_ochecker.get();
     320                 :            : }
     321                 :            : 
     322                 :       3482 : void Env::registerBooleanTermSkolem(const Node& k)
     323                 :            : {
     324 [ -  + ][ -  + ]:       3482 :   Assert(k.isVar());
                 [ -  - ]
     325                 :       3482 :   d_boolTermSkolems.insert(k);
     326                 :       3482 : }
     327                 :            : 
     328                 :   14171825 : bool Env::isBooleanTermSkolem(const Node& k) const
     329                 :            : {
     330                 :            :   // optimization: check whether k is a variable
     331         [ +  + ]:   14171825 :   if (!k.isVar())
     332                 :            :   {
     333                 :   13839020 :     return false;
     334                 :            :   }
     335                 :     332805 :   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