LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/smt - env.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 169 177 95.5 %
Date: 2026-02-15 11:43:36 Functions: 47 47 100.0 %
Branches: 68 100 68.0 %

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

Generated by: LCOV version 1.14