LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/smt - solver_engine.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1003 1226 81.8 %
Date: 2026-03-31 10:41:31 Functions: 104 116 89.7 %
Branches: 438 720 60.8 %

           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                 :            :  * The main entry point into the cvc5 library's SMT interface.
      11                 :            :  */
      12                 :            : 
      13                 :            : #include "smt/solver_engine.h"
      14                 :            : 
      15                 :            : #include "base/check.h"
      16                 :            : #include "base/exception.h"
      17                 :            : #include "base/modal_exception.h"
      18                 :            : #include "base/output.h"
      19                 :            : #include "decision/decision_engine.h"
      20                 :            : #include "expr/bound_var_manager.h"
      21                 :            : #include "expr/node.h"
      22                 :            : #include "expr/node_algorithm.h"
      23                 :            : #include "expr/non_closed_node_converter.h"
      24                 :            : #include "expr/plugin.h"
      25                 :            : #include "expr/skolem_manager.h"
      26                 :            : #include "expr/subtype_elim_node_converter.h"
      27                 :            : #include "expr/sygus_term_enumerator.h"
      28                 :            : #include "options/base_options.h"
      29                 :            : #include "options/expr_options.h"
      30                 :            : #include "options/language.h"
      31                 :            : #include "options/main_options.h"
      32                 :            : #include "options/option_exception.h"
      33                 :            : #include "options/options_public.h"
      34                 :            : #include "options/parser_options.h"
      35                 :            : #include "options/printer_options.h"
      36                 :            : #include "options/proof_options.h"
      37                 :            : #include "options/quantifiers_options.h"
      38                 :            : #include "options/smt_options.h"
      39                 :            : #include "options/theory_options.h"
      40                 :            : #include "preprocessing/passes/synth_rew_rules.h"
      41                 :            : #include "printer/printer.h"
      42                 :            : #include "proof/unsat_core.h"
      43                 :            : #include "prop/prop_engine.h"
      44                 :            : #include "smt/abduction_solver.h"
      45                 :            : #include "smt/assertions.h"
      46                 :            : #include "smt/check_models.h"
      47                 :            : #include "smt/context_manager.h"
      48                 :            : #include "smt/env.h"
      49                 :            : #include "smt/expand_definitions.h"
      50                 :            : #include "smt/find_synth_solver.h"
      51                 :            : #include "smt/interpolation_solver.h"
      52                 :            : #include "smt/listeners.h"
      53                 :            : #include "smt/logic_exception.h"
      54                 :            : #include "smt/model.h"
      55                 :            : #include "smt/model_blocker.h"
      56                 :            : #include "smt/model_core_builder.h"
      57                 :            : #include "smt/preprocessor.h"
      58                 :            : #include "smt/proof_manager.h"
      59                 :            : #include "smt/quant_elim_solver.h"
      60                 :            : #include "smt/set_defaults.h"
      61                 :            : #include "smt/smt_driver.h"
      62                 :            : #include "smt/smt_driver_deep_restarts.h"
      63                 :            : #include "smt/smt_solver.h"
      64                 :            : #include "smt/solver_engine_state.h"
      65                 :            : #include "smt/solver_engine_stats.h"
      66                 :            : #include "smt/sygus_solver.h"
      67                 :            : #include "smt/timeout_core_manager.h"
      68                 :            : #include "smt/unsat_core_manager.h"
      69                 :            : #include "theory/datatypes/sygus_datatype_utils.h"
      70                 :            : #include "theory/quantifiers/candidate_rewrite_database.h"
      71                 :            : #include "theory/quantifiers/instantiation_list.h"
      72                 :            : #include "theory/quantifiers/oracle_engine.h"
      73                 :            : #include "theory/quantifiers/quantifiers_attributes.h"
      74                 :            : #include "theory/quantifiers/query_generator.h"
      75                 :            : #include "theory/quantifiers/rewrite_verifier.h"
      76                 :            : #include "theory/quantifiers/sygus/sygus_enumerator.h"
      77                 :            : #include "theory/quantifiers/sygus_sampler.h"
      78                 :            : #include "theory/quantifiers_engine.h"
      79                 :            : #include "theory/rewriter.h"
      80                 :            : #include "theory/smt_engine_subsolver.h"
      81                 :            : #include "theory/theory_engine.h"
      82                 :            : #include "util/random.h"
      83                 :            : #include "util/rational.h"
      84                 :            : #include "util/resource_manager.h"
      85                 :            : #include "util/sexpr.h"
      86                 :            : #include "util/statistics_registry.h"
      87                 :            : #include "util/string.h"
      88                 :            : 
      89                 :            : // required for hacks related to old proofs for unsat cores
      90                 :            : #include "base/configuration.h"
      91                 :            : #include "base/configuration_private.h"
      92                 :            : 
      93                 :            : using namespace std;
      94                 :            : using namespace cvc5::internal::smt;
      95                 :            : using namespace cvc5::internal::preprocessing;
      96                 :            : using namespace cvc5::internal::prop;
      97                 :            : using namespace cvc5::context;
      98                 :            : using namespace cvc5::internal::theory;
      99                 :            : 
     100                 :            : namespace cvc5::internal {
     101                 :            : 
     102                 :      75751 : SolverEngine::SolverEngine(NodeManager* nm, const Options* optr)
     103                 :      75751 :     : d_env(new Env(nm, optr)),
     104                 :      75751 :       d_state(new SolverEngineState(*d_env.get())),
     105                 :      75751 :       d_ctxManager(nullptr),
     106                 :      75751 :       d_routListener(new ResourceOutListener(*this)),
     107                 :      75751 :       d_smtSolver(nullptr),
     108                 :      75751 :       d_smtDriver(nullptr),
     109                 :      75751 :       d_checkModels(nullptr),
     110                 :      75751 :       d_pfManager(nullptr),
     111                 :      75751 :       d_ucManager(nullptr),
     112                 :      75751 :       d_sygusSolver(nullptr),
     113                 :      75751 :       d_abductSolver(nullptr),
     114                 :      75751 :       d_interpolSolver(nullptr),
     115                 :      75751 :       d_quantElimSolver(nullptr),
     116                 :      75751 :       d_userLogicSet(false),
     117                 :      75751 :       d_safeOptsSetRegularOption(false),
     118                 :      75751 :       d_safeOptsSetRegularOptionToDefault(false),
     119                 :      75751 :       d_isInternalSubsolver(false),
     120                 :     227253 :       d_stats(nullptr)
     121                 :            : {
     122                 :            :   // listen to resource out
     123                 :      75751 :   getResourceManager()->registerListener(d_routListener.get());
     124                 :            :   // make statistics
     125                 :      75751 :   d_stats.reset(new SolverEngineStatistics(d_env->getStatisticsRegistry()));
     126                 :            :   // make the SMT solver
     127                 :      75751 :   d_smtSolver.reset(new SmtSolver(*d_env, *d_stats));
     128                 :            :   // make the context manager
     129                 :      75751 :   d_ctxManager.reset(new ContextManager(*d_env.get(), *d_state));
     130                 :            :   // make the SyGuS solver
     131                 :      75751 :   d_sygusSolver.reset(new SygusSolver(*d_env.get(), *d_smtSolver));
     132                 :            :   // make the quantifier elimination solver
     133                 :      75751 :   d_quantElimSolver.reset(
     134                 :      75751 :       new QuantElimSolver(*d_env.get(), *d_smtSolver, d_ctxManager.get()));
     135                 :      75751 : }
     136                 :            : 
     137                 :     181345 : bool SolverEngine::isFullyInited() const { return d_state->isFullyInited(); }
     138                 :      34627 : bool SolverEngine::isQueryMade() const { return d_state->isQueryMade(); }
     139                 :       3657 : size_t SolverEngine::getNumUserLevels() const
     140                 :            : {
     141                 :       3657 :   return d_ctxManager->getNumUserLevels();
     142                 :            : }
     143                 :      14342 : SmtMode SolverEngine::getSmtMode() const { return d_state->getMode(); }
     144                 :       4697 : bool SolverEngine::isSmtModeSat() const
     145                 :            : {
     146                 :       4697 :   SmtMode mode = getSmtMode();
     147 [ +  + ][ +  + ]:       4697 :   return mode == SmtMode::SAT || mode == SmtMode::SAT_UNKNOWN;
     148                 :            : }
     149                 :          0 : Result SolverEngine::getStatusOfLastCommand() const
     150                 :            : {
     151                 :          0 :   return d_state->getStatus();
     152                 :            : }
     153                 :            : 
     154                 :     278153 : void SolverEngine::finishInit()
     155                 :            : {
     156         [ +  + ]:     278153 :   if (d_state->isFullyInited())
     157                 :            :   {
     158                 :            :     // already initialized, return
     159                 :     227108 :     return;
     160                 :            :   }
     161                 :            : 
     162                 :            :   // Notice that finishInit is called when options are finalized. If we are
     163                 :            :   // parsing smt2, this occurs at the moment we enter "Assert mode", page 52 of
     164                 :            :   // SMT-LIB 2.6 standard.
     165                 :            : 
     166                 :            :   // set the logic
     167                 :      51045 :   const LogicInfo& logic = getLogicInfo();
     168         [ +  + ]:      51045 :   if (!logic.isLocked())
     169                 :            :   {
     170                 :      16854 :     setLogicInternal();
     171                 :            :   }
     172                 :            : 
     173                 :            :   // set the random seed
     174                 :      51045 :   Random::getRandom().setSeed(d_env->getOptions().driver.seed);
     175                 :            : 
     176                 :            :   // Call finish init on the set defaults module. This inializes the logic
     177                 :            :   // and the best default options based on our heuristics.
     178                 :      51045 :   SetDefaults sdefaults(*d_env, d_isInternalSubsolver);
     179                 :      51045 :   sdefaults.setDefaults(d_env->d_logic, getOptions());
     180                 :            : 
     181         [ +  + ]:      51040 :   if (d_env->getOptions().smt.produceProofs)
     182                 :            :   {
     183                 :            :     // make the proof manager
     184                 :      19794 :     d_pfManager.reset(new PfManager(*d_env.get()));
     185                 :            :     // start the unsat core manager
     186                 :      19794 :     d_ucManager.reset(new UnsatCoreManager(
     187                 :      19794 :         *d_env.get(), *d_smtSolver.get(), *d_pfManager.get()));
     188                 :            :   }
     189                 :      51040 :   if (d_env->isOutputOn(OutputTag::RARE_DB)
     190 [ +  - ][ -  + ]:      51040 :       || d_env->isOutputOn(OutputTag::RARE_DB_EXPERT))
                 [ -  + ]
     191                 :            :   {
     192                 :          0 :     if (!d_env->getOptions().smt.produceProofs
     193                 :          0 :         || options().proof.proofGranularityMode
     194                 :            :                != options::ProofGranularityMode::DSL_REWRITE)
     195                 :            :     {
     196         [ -  - ]:          0 :       Warning() << "WARNING: -o rare-db requires --produce-proofs and "
     197                 :          0 :                    "--proof-granularity=dsl-rewrite" << std::endl;
     198                 :            :     }
     199                 :            :   }
     200                 :            :   // enable proof support in the environment/rewriter
     201                 :      51040 :   d_env->finishInit(d_pfManager.get());
     202                 :            : 
     203         [ +  - ]:      51040 :   Trace("smt-debug") << "SolverEngine::finishInit" << std::endl;
     204                 :      51040 :   d_smtSolver->finishInit();
     205                 :            : 
     206                 :            :   // make SMT solver driver based on options
     207         [ +  + ]:      51040 :   if (options().smt.deepRestartMode != options::DeepRestartMode::NONE)
     208                 :            :   {
     209                 :          8 :     d_smtDriver.reset(new SmtDriverDeepRestarts(
     210                 :          8 :         *d_env.get(), *d_smtSolver.get(), d_ctxManager.get()));
     211                 :            :   }
     212                 :            :   else
     213                 :            :   {
     214                 :      51032 :     ContextManager* ctx = d_ctxManager.get();
     215                 :            :     // deep restarts not enabled
     216                 :      51032 :     d_smtDriver.reset(
     217                 :      51032 :         new SmtDriverSingleCall(*d_env.get(), *d_smtSolver.get(), ctx));
     218                 :            :   }
     219                 :            : 
     220                 :            :   // global push/pop around everything, to ensure proper destruction
     221                 :            :   // of context-dependent data structures
     222                 :      51040 :   d_ctxManager->setup(d_smtDriver.get());
     223                 :            : 
     224                 :            :   // subsolvers
     225         [ +  + ]:      51040 :   if (d_env->getOptions().smt.produceAbducts)
     226                 :            :   {
     227                 :       6245 :     d_abductSolver.reset(new AbductionSolver(*d_env.get()));
     228                 :            :   }
     229         [ +  + ]:      51040 :   if (d_env->getOptions().smt.produceInterpolants)
     230                 :            :   {
     231                 :       1870 :     d_interpolSolver.reset(new InterpolationSolver(*d_env));
     232                 :            :   }
     233                 :            :   // check models utility
     234         [ +  + ]:      51040 :   if (d_env->getOptions().smt.checkModels)
     235                 :            :   {
     236                 :       2432 :     d_checkModels.reset(new CheckModels(*d_env.get()));
     237                 :            :   }
     238                 :            : 
     239 [ -  + ][ -  + ]:      51040 :   AlwaysAssert(d_smtSolver->getPropEngine()->getAssertionLevel() == 0)
                 [ -  - ]
     240                 :            :       << "The PropEngine has pushed but the SolverEngine "
     241                 :          0 :          "hasn't finished initializing!";
     242                 :            : 
     243 [ -  + ][ -  + ]:      51040 :   Assert(getLogicInfo().isLocked());
                 [ -  - ]
     244                 :            : 
     245                 :            :   // store that we are finished initializing
     246                 :      51040 :   d_state->markFinishInit();
     247         [ +  - ]:      51040 :   Trace("smt-debug") << "SolverEngine::finishInit done" << std::endl;
     248                 :      51045 : }
     249                 :            : 
     250                 :      70731 : void SolverEngine::shutdown()
     251                 :            : {
     252                 :      70731 :   d_ctxManager->shutdown();
     253                 :      70731 :   d_env->shutdown();
     254                 :      70731 : }
     255                 :            : 
     256                 :      70731 : SolverEngine::~SolverEngine()
     257                 :            : {
     258                 :            : 
     259                 :            :   try
     260                 :            :   {
     261                 :      70731 :     shutdown();
     262                 :            : 
     263                 :            :     // global push/pop around everything, to ensure proper destruction
     264                 :            :     // of context-dependent data structures
     265                 :      70731 :     d_ctxManager->cleanup();
     266                 :            : 
     267                 :            :     // destroy all passes before destroying things that they refer to
     268                 :      70731 :     d_smtSolver->getPreprocessor()->cleanup();
     269                 :            : 
     270                 :      70731 :     d_pfManager.reset(nullptr);
     271                 :      70731 :     d_ucManager.reset(nullptr);
     272                 :            : 
     273                 :      70731 :     d_abductSolver.reset(nullptr);
     274                 :      70731 :     d_interpolSolver.reset(nullptr);
     275                 :      70731 :     d_quantElimSolver.reset(nullptr);
     276                 :      70731 :     d_sygusSolver.reset(nullptr);
     277                 :      70731 :     d_smtDriver.reset(nullptr);
     278                 :      70731 :     d_smtSolver.reset(nullptr);
     279                 :            : 
     280                 :      70731 :     d_stats.reset(nullptr);
     281                 :      70731 :     d_routListener.reset(nullptr);
     282                 :            :     // destroy the state
     283                 :      70731 :     d_state.reset(nullptr);
     284                 :            :     // destroy the environment
     285                 :      70731 :     d_env.reset(nullptr);
     286                 :            :   }
     287         [ -  - ]:          0 :   catch (Exception& e)
     288                 :            :   {
     289                 :          0 :     d_env->warning() << "cvc5 threw an exception during cleanup." << std::endl << e << std::endl;
     290                 :          0 :   }
     291                 :      70731 : }
     292                 :            : 
     293                 :      43685 : void SolverEngine::setLogic(const LogicInfo& logic)
     294                 :            : {
     295         [ -  + ]:      43685 :   if (d_state->isFullyInited())
     296                 :            :   {
     297                 :          0 :     throw ModalException(
     298                 :            :         "Cannot set logic in SolverEngine after the engine has "
     299                 :          0 :         "finished initializing.");
     300                 :            :   }
     301                 :      43685 :   d_env->d_logic = logic;
     302                 :      43685 :   d_userLogic = logic;
     303                 :      43685 :   d_userLogicSet = true;
     304                 :      43685 :   setLogicInternal();
     305                 :      43685 : }
     306                 :            : 
     307                 :          0 : void SolverEngine::setLogic(const std::string& s)
     308                 :            : {
     309                 :            :   try
     310                 :            :   {
     311                 :          0 :     setLogic(LogicInfo(s));
     312                 :            :   }
     313         [ -  - ]:          0 :   catch (IllegalArgumentException& e)
     314                 :            :   {
     315                 :          0 :     throw LogicException(e.what());
     316                 :          0 :   }
     317                 :          0 : }
     318                 :            : 
     319                 :      53948 : bool SolverEngine::isLogicSet() const { return d_userLogicSet; }
     320                 :            : 
     321                 :     105297 : const LogicInfo& SolverEngine::getLogicInfo() const
     322                 :            : {
     323                 :     105297 :   return d_env->getLogicInfo();
     324                 :            : }
     325                 :            : 
     326                 :       7758 : LogicInfo SolverEngine::getUserLogicInfo() const
     327                 :            : {
     328                 :            :   // Lock the logic to make sure that this logic can be queried. We create a
     329                 :            :   // copy of the user logic here to keep this method const.
     330                 :       7758 :   LogicInfo res = d_userLogic;
     331                 :       7758 :   res.lock();
     332                 :       7758 :   return res;
     333                 :            : }
     334                 :            : 
     335                 :      60539 : void SolverEngine::setLogicInternal()
     336                 :            : {
     337 [ -  + ][ -  + ]:      60539 :   Assert(!d_state->isFullyInited())
                 [ -  - ]
     338                 :            :       << "setting logic in SolverEngine but the engine has already"
     339                 :          0 :          " finished initializing for this run";
     340                 :      60539 :   d_env->d_logic.lock();
     341                 :      60539 :   d_userLogic.lock();
     342                 :      60539 : }
     343                 :            : 
     344                 :      38834 : void SolverEngine::setInfo(const std::string& key, const std::string& value)
     345                 :            : {
     346         [ +  - ]:      38834 :   Trace("smt") << "SMT setInfo(" << key << ", " << value << ")" << endl;
     347                 :            : 
     348         [ +  + ]:      38834 :   if (key == "filename")
     349                 :            :   {
     350                 :      24420 :     d_env->d_options.write_driver().filename = value;
     351                 :      24420 :     d_env->getStatisticsRegistry().registerValue<std::string>(
     352                 :            :         "driver::filename", value);
     353                 :            :   }
     354         [ +  + ]:      14414 :   else if (key == "smt-lib-version")
     355                 :            :   {
     356 [ +  + ][ +  + ]:       2580 :     if (value != "2" && value != "2.6")
                 [ +  + ]
     357                 :            :     {
     358                 :        308 :       d_env->warning() << "SMT-LIB version " << value
     359                 :            :                 << " unsupported, defaulting to language (and semantics of) "
     360                 :        308 :                    "SMT-LIB 2.6\n";
     361                 :            :     }
     362                 :       2580 :     getOptions().write_base().inputLanguage = Language::LANG_SMTLIB_V2_6;
     363                 :            :     // also update the output language
     364         [ +  - ]:       2580 :     if (!getOptions().printer.outputLanguageWasSetByUser)
     365                 :            :     {
     366                 :       2580 :       setOption("output-language", "smtlib2.6");
     367                 :       2580 :       getOptions().write_printer().outputLanguageWasSetByUser = false;
     368                 :            :     }
     369                 :            :   }
     370         [ +  + ]:      11834 :   else if (key == "status")
     371                 :            :   {
     372                 :       8448 :     d_state->notifyExpectedStatus(value);
     373                 :            :   }
     374                 :      38834 : }
     375                 :            : 
     376                 :        284 : bool SolverEngine::isValidGetInfoFlag(const std::string& key) const
     377                 :            : {
     378 [ +  + ][ +  - ]:        566 :   if (key == "all-statistics" || key == "error-behavior" || key == "filename"
     379 [ +  + ][ +  + ]:        280 :       || key == "name" || key == "version" || key == "authors"
                 [ +  + ]
     380 [ +  + ][ +  - ]:         25 :       || key == "status" || key == "time" || key == "reason-unknown"
                 [ +  + ]
     381 [ +  + ][ +  - ]:        566 :       || key == "assertion-stack-levels" || key == "all-options")
         [ -  + ][ +  + ]
     382                 :            :   {
     383                 :        276 :     return true;
     384                 :            :   }
     385                 :          8 :   return false;
     386                 :            : }
     387                 :            : 
     388                 :        276 : std::string SolverEngine::getInfo(const std::string& key) const
     389                 :            : {
     390         [ +  - ]:        276 :   Trace("smt") << "SMT getInfo(" << key << ")" << endl;
     391         [ +  + ]:        276 :   if (key == "all-statistics")
     392                 :            :   {
     393                 :          2 :     return toSExpr(d_env->getStatisticsRegistry().begin(),
     394                 :          4 :                    d_env->getStatisticsRegistry().end());
     395                 :            :   }
     396         [ +  + ]:        274 :   if (key == "error-behavior")
     397                 :            :   {
     398                 :          2 :     return "immediate-exit";
     399                 :            :   }
     400         [ -  + ]:        272 :   if (key == "filename")
     401                 :            :   {
     402                 :          0 :     return d_env->getOptions().driver.filename;
     403                 :            :   }
     404         [ +  + ]:        272 :   if (key == "name")
     405                 :            :   {
     406                 :        502 :     return toSExpr(Configuration::getName());
     407                 :            :   }
     408         [ +  + ]:         21 :   if (key == "version")
     409                 :            :   {
     410                 :          4 :     return toSExpr(Configuration::getVersionString());
     411                 :            :   }
     412         [ +  + ]:         19 :   if (key == "authors")
     413                 :            :   {
     414                 :          4 :     return toSExpr("the " + Configuration::getName() + " authors");
     415                 :            :   }
     416         [ +  + ]:         17 :   if (key == "status")
     417                 :            :   {
     418                 :            :     // sat | unsat | unknown
     419                 :          3 :     Result status = d_state->getStatus();
     420    [ -  - ][ + ]:          3 :     switch (status.getStatus())
     421                 :            :     {
     422                 :          0 :       case Result::SAT: return "sat";
     423                 :          0 :       case Result::UNSAT: return "unsat";
     424                 :          3 :       default: return "unknown";
     425                 :            :     }
     426                 :          3 :   }
     427         [ -  + ]:         14 :   if (key == "time")
     428                 :            :   {
     429                 :          0 :     return toSExpr(std::clock());
     430                 :            :   }
     431         [ +  - ]:         14 :   if (key == "reason-unknown")
     432                 :            :   {
     433                 :         14 :     Result status = d_state->getStatus();
     434 [ +  + ][ +  - ]:         14 :     if (!status.isNull() && status.isUnknown())
                 [ +  + ]
     435                 :            :     {
     436                 :         10 :       std::stringstream ss;
     437                 :         10 :       ss << status.getUnknownExplanation();
     438                 :         10 :       std::string s = ss.str();
     439                 :         10 :       transform(s.begin(), s.end(), s.begin(), ::tolower);
     440                 :         10 :       return s;
     441                 :         10 :     }
     442                 :            :     else
     443                 :            :     {
     444                 :          4 :       throw RecoverableModalException(
     445                 :            :           "Can't get-info :reason-unknown when the "
     446                 :          8 :           "last result wasn't unknown!");
     447                 :            :     }
     448                 :         14 :   }
     449         [ -  - ]:          0 :   if (key == "assertion-stack-levels")
     450                 :            :   {
     451                 :          0 :     size_t ulevel = d_ctxManager->getNumUserLevels();
     452                 :          0 :     AlwaysAssert(ulevel <= std::numeric_limits<unsigned long int>::max());
     453                 :          0 :     return toSExpr(ulevel);
     454                 :            :   }
     455                 :          0 :   Assert(key == "all-options");
     456                 :            :   // get the options, like all-statistics
     457                 :          0 :   std::vector<std::vector<std::string>> res;
     458         [ -  - ]:          0 :   for (const auto& opt : options::getNames())
     459                 :            :   {
     460                 :          0 :     res.emplace_back(
     461                 :          0 :         std::vector<std::string>{opt, options::get(getOptions(), opt)});
     462                 :          0 :   }
     463                 :          0 :   return toSExpr(res);
     464                 :            : }
     465                 :            : 
     466                 :      13715 : void SolverEngine::debugCheckFormals(const std::vector<Node>& formals,
     467                 :            :                                      Node func)
     468                 :            : {
     469                 :      13715 :   std::unordered_set<Node> vars;
     470         [ +  + ]:      35433 :   for (const Node& v : formals)
     471                 :            :   {
     472         [ -  + ]:      21722 :     if (v.getKind() != Kind::BOUND_VARIABLE)
     473                 :            :     {
     474                 :          0 :       std::stringstream ss;
     475                 :            :       ss << "All formal arguments to defined functions must be "
     476                 :            :             "BOUND_VARIABLEs, but in the\n"
     477                 :          0 :          << "definition of function " << func << ", formal\n"
     478                 :          0 :          << "  " << v << "\n"
     479                 :          0 :          << "has kind " << v.getKind();
     480                 :          0 :       throw TypeCheckingExceptionPrivate(func, ss.str());
     481                 :          0 :     }
     482         [ +  + ]:      21722 :     if (!vars.insert(v).second)
     483                 :            :     {
     484                 :          4 :       std::stringstream ss;
     485                 :            :       ss << "All formal arguments to defined functions must be "
     486                 :            :             "unique, but a duplicate variable was used in the "
     487                 :          4 :          << "definition of function " << func;
     488                 :          4 :       throw TypeCheckingExceptionPrivate(func, ss.str());
     489                 :          4 :     }
     490                 :            :   }
     491                 :      13715 : }
     492                 :            : 
     493                 :      13711 : void SolverEngine::debugCheckFunctionBody(Node formula,
     494                 :            :                                           const std::vector<Node>& formals,
     495                 :            :                                           Node func)
     496                 :            : {
     497                 :      13711 :   TypeNode formulaType = formula.getType(d_env->getOptions().expr.typeChecking);
     498                 :      13711 :   TypeNode funcType = func.getType();
     499                 :            :   // We distinguish here between definitions of constants and functions,
     500                 :            :   // because the type checking for them is subtly different.  Perhaps we
     501                 :            :   // should instead have SolverEngine::defineFunction() and
     502                 :            :   // SolverEngine::defineConstant() for better clarity, although then that
     503                 :            :   // doesn't match the SMT-LIBv2 standard...
     504         [ +  + ]:      13711 :   if (formals.size() > 0)
     505                 :            :   {
     506                 :       9706 :     TypeNode rangeType = funcType.getRangeType();
     507         [ -  + ]:       9706 :     if (formulaType != rangeType)
     508                 :            :     {
     509                 :          0 :       stringstream ss;
     510                 :            :       ss << "Type of defined function does not match its declaration\n"
     511                 :          0 :          << "The function  : " << func << "\n"
     512                 :          0 :          << "Declared type : " << rangeType << "\n"
     513                 :          0 :          << "The body      : " << formula << "\n"
     514                 :          0 :          << "Body type     : " << formulaType;
     515                 :          0 :       throw TypeCheckingExceptionPrivate(func, ss.str());
     516                 :          0 :     }
     517                 :       9706 :   }
     518                 :            :   else
     519                 :            :   {
     520         [ -  + ]:       4005 :     if (formulaType != funcType)
     521                 :            :     {
     522                 :          0 :       stringstream ss;
     523                 :            :       ss << "Declared type of defined constant does not match its definition\n"
     524                 :          0 :          << "The constant   : " << func << "\n"
     525                 :          0 :          << "Declared type  : " << funcType << "\n"
     526                 :          0 :          << "The definition : " << formula << "\n"
     527                 :          0 :          << "Definition type: " << formulaType;
     528                 :          0 :       throw TypeCheckingExceptionPrivate(func, ss.str());
     529                 :          0 :     }
     530                 :            :   }
     531                 :      13711 : }
     532                 :            : 
     533                 :     335440 : void SolverEngine::declareConst(CVC5_UNUSED const Node& c)
     534                 :            : {
     535                 :     335440 :   d_state->notifyDeclaration();
     536                 :     335440 : }
     537                 :            : 
     538                 :      13904 : void SolverEngine::declareSort(CVC5_UNUSED const TypeNode& tn)
     539                 :            : {
     540                 :      13904 :   d_state->notifyDeclaration();
     541                 :      13904 : }
     542                 :            : 
     543                 :       9085 : void SolverEngine::defineFunction(Node func,
     544                 :            :                                   const std::vector<Node>& formals,
     545                 :            :                                   Node formula,
     546                 :            :                                   bool global)
     547                 :            : {
     548                 :       9085 :   beginCall();
     549         [ +  - ]:       9085 :   Trace("smt") << "SMT defineFunction(" << func << ")" << endl;
     550                 :       9088 :   debugCheckFormals(formals, func);
     551                 :            : 
     552                 :            :   // type check body
     553                 :       9082 :   debugCheckFunctionBody(formula, formals, func);
     554                 :            : 
     555                 :       9082 :   Node def = formula;
     556         [ +  + ]:       9082 :   if (!formals.empty())
     557                 :            :   {
     558                 :       5664 :     NodeManager* nm = d_env->getNodeManager();
     559                 :      22656 :     def = nm->mkNode(
     560                 :      16992 :         Kind::LAMBDA, nm->mkNode(Kind::BOUND_VAR_LIST, formals), def);
     561                 :            :   }
     562                 :       9082 :   Node feq = func.eqNode(def);
     563                 :       9082 :   d_smtSolver->getAssertions().addDefineFunDefinition(feq, global);
     564                 :       9082 : }
     565                 :            : 
     566                 :        629 : void SolverEngine::defineFunction(Node func, Node lambda, bool global)
     567                 :            : {
     568                 :        629 :   beginCall();
     569                 :            :   // A define-fun is treated as a (higher-order) assertion. It is provided
     570                 :            :   // to the assertions object. It will be added as a top-level substitution
     571                 :            :   // within this class, possibly multiple times if global is true.
     572                 :        629 :   Node feq = func.eqNode(lambda);
     573                 :        629 :   d_smtSolver->getAssertions().addDefineFunDefinition(feq, global);
     574                 :        629 : }
     575                 :            : 
     576                 :       3671 : void SolverEngine::defineFunctionsRec(
     577                 :            :     const std::vector<Node>& funcs,
     578                 :            :     const std::vector<std::vector<Node>>& formals,
     579                 :            :     const std::vector<Node>& formulas,
     580                 :            :     bool global)
     581                 :            : {
     582                 :       3671 :   beginCall();
     583         [ +  - ]:       3671 :   Trace("smt") << "SMT defineFunctionsRec(...)" << endl;
     584                 :            : 
     585 [ -  + ][ -  - ]:       3671 :   if (funcs.size() != formals.size() && funcs.size() != formulas.size())
                 [ -  + ]
     586                 :            :   {
     587                 :          0 :     stringstream ss;
     588                 :            :     ss << "Number of functions, formals, and function bodies passed to "
     589                 :            :           "defineFunctionsRec do not match:"
     590                 :            :        << "\n"
     591                 :          0 :        << "        #functions : " << funcs.size() << "\n"
     592                 :          0 :        << "        #arg lists : " << formals.size() << "\n"
     593                 :          0 :        << "  #function bodies : " << formulas.size() << "\n";
     594                 :          0 :     throw ModalException(ss.str());
     595                 :          0 :   }
     596         [ +  + ]:       8300 :   for (unsigned i = 0, size = funcs.size(); i < size; i++)
     597                 :            :   {
     598                 :            :     // check formal argument list
     599                 :       4631 :     debugCheckFormals(formals[i], funcs[i]);
     600                 :            :     // type check body
     601                 :       4629 :     debugCheckFunctionBody(formulas[i], formals[i], funcs[i]);
     602                 :            :   }
     603                 :            : 
     604                 :       3670 :   NodeManager* nm = d_env->getNodeManager();
     605         [ +  + ]:       8299 :   for (unsigned i = 0, size = funcs.size(); i < size; i++)
     606                 :            :   {
     607                 :            :     // we assert a quantified formula
     608                 :       4629 :     Node func_app;
     609                 :            :     // make the function application
     610         [ +  + ]:       4629 :     if (formals[i].empty())
     611                 :            :     {
     612                 :            :       // it has no arguments
     613                 :        587 :       func_app = funcs[i];
     614                 :            :     }
     615                 :            :     else
     616                 :            :     {
     617                 :       4042 :       std::vector<Node> children;
     618                 :       4042 :       children.push_back(funcs[i]);
     619                 :       4042 :       children.insert(children.end(), formals[i].begin(), formals[i].end());
     620                 :       4042 :       func_app = nm->mkNode(Kind::APPLY_UF, children);
     621                 :       4042 :     }
     622                 :       9258 :     Node lem = nm->mkNode(Kind::EQUAL, func_app, formulas[i]);
     623         [ +  + ]:       4629 :     if (!formals[i].empty())
     624                 :            :     {
     625                 :            :       // set the attribute to denote this is a function definition
     626                 :       4042 :       Node aexpr = nm->mkNode(Kind::INST_ATTRIBUTE, func_app);
     627                 :       4042 :       aexpr = nm->mkNode(Kind::INST_PATTERN_LIST, aexpr);
     628                 :            :       FunDefAttribute fda;
     629                 :       4042 :       func_app.setAttribute(fda, true);
     630                 :            :       // make the quantified formula
     631                 :       4042 :       Node boundVars = nm->mkNode(Kind::BOUND_VAR_LIST, formals[i]);
     632                 :       4042 :       lem = nm->mkNode(Kind::FORALL, boundVars, lem, aexpr);
     633                 :       4042 :     }
     634                 :            :     // Assert the quantified formula. Notice we don't call assertFormula
     635                 :            :     // directly, since we should call a private member method since we have
     636                 :            :     // already ensuring this SolverEngine is initialized above.
     637                 :            :     // add define recursive definition to the assertions
     638                 :       4629 :     d_smtSolver->getAssertions().addDefineFunDefinition(lem, global);
     639                 :       4629 :   }
     640                 :       3670 : }
     641                 :            : 
     642                 :       1941 : void SolverEngine::defineFunctionRec(Node func,
     643                 :            :                                      const std::vector<Node>& formals,
     644                 :            :                                      Node formula,
     645                 :            :                                      bool global)
     646                 :            : {
     647                 :       1941 :   std::vector<Node> funcs;
     648                 :       1941 :   funcs.push_back(func);
     649                 :       1941 :   std::vector<std::vector<Node>> formals_multi;
     650                 :       1941 :   formals_multi.push_back(formals);
     651                 :       1941 :   std::vector<Node> formulas;
     652                 :       1941 :   formulas.push_back(formula);
     653                 :       1941 :   defineFunctionsRec(funcs, formals_multi, formulas, global);
     654                 :       1941 : }
     655                 :            : 
     656                 :      25459 : TheoryModel* SolverEngine::getAvailableModel(const char* c) const
     657                 :            : {
     658         [ -  + ]:      25459 :   if (!d_env->getOptions().theory.assignFunctionValues)
     659                 :            :   {
     660                 :          0 :     std::stringstream ss;
     661                 :          0 :     ss << "Cannot " << c << " when --assign-function-values is false.";
     662                 :          0 :     throw RecoverableModalException(ss.str().c_str());
     663                 :          0 :   }
     664                 :            : 
     665                 :      25459 :   if (d_state->getMode() != SmtMode::SAT
     666 [ +  + ][ -  + ]:      25459 :       && d_state->getMode() != SmtMode::SAT_UNKNOWN)
                 [ -  + ]
     667                 :            :   {
     668                 :          0 :     std::stringstream ss;
     669                 :            :     ss << "Cannot " << c
     670                 :          0 :        << " unless immediately preceded by SAT or UNKNOWN response.";
     671                 :          0 :     throw RecoverableModalException(ss.str().c_str());
     672                 :          0 :   }
     673                 :            : 
     674         [ -  + ]:      25459 :   if (!d_env->getOptions().smt.produceModels)
     675                 :            :   {
     676                 :          0 :     std::stringstream ss;
     677                 :          0 :     ss << "Cannot " << c << " when produce-models options is off.";
     678                 :          0 :     throw ModalException(ss.str().c_str());
     679                 :          0 :   }
     680                 :            : 
     681                 :      25459 :   TheoryEngine* te = d_smtSolver->getTheoryEngine();
     682 [ -  + ][ -  + ]:      25459 :   Assert(te != nullptr);
                 [ -  - ]
     683                 :            :   // If the solver is in UNKNOWN mode, we use the latest available model (e.g.,
     684                 :            :   // one that was generated for a last call check). Note that the model is SAT
     685                 :            :   // context-independent internally, so this works even if the SAT solver has
     686                 :            :   // backtracked since the model was generated. We disable the resource manager
     687                 :            :   // while building or getting the model. In general, we should not be spending
     688                 :            :   // resources while building a model, but this ensures that we return a model
     689                 :            :   // if a problem was solved within the allocated resources.
     690                 :      25459 :   getResourceManager()->setEnabled(false);
     691                 :      25459 :   TheoryModel* m = d_state->getMode() == SmtMode::SAT_UNKNOWN
     692         [ +  + ]:      25459 :                        ? te->getModel()
     693                 :      24469 :                        : te->getBuiltModel();
     694                 :      25459 :   getResourceManager()->setEnabled(true);
     695                 :            : 
     696         [ -  + ]:      25459 :   if (m == nullptr)
     697                 :            :   {
     698                 :          0 :     std::stringstream ss;
     699                 :            :     ss << "Cannot " << c
     700                 :            :        << " since model is not available. Perhaps the most recent call to "
     701                 :          0 :           "check-sat was interrupted?";
     702                 :          0 :     throw RecoverableModalException(ss.str().c_str());
     703                 :          0 :   }
     704                 :            :   // compute the model core if necessary and not done so already
     705                 :      25459 :   const Options& opts = d_env->getOptions();
     706                 :      50918 :   if (opts.smt.modelCoresMode != options::ModelCoresMode::NONE
     707 [ +  + ][ +  + ]:      25459 :       && !m->isUsingModelCore())
                 [ +  + ]
     708                 :            :   {
     709                 :            :     // If we enabled model cores, we compute a model core for m based on our
     710                 :            :     // (expanded) assertions using the model core builder utility. Notice that
     711                 :            :     // we get the assertions using the getAssertionsInternal, which does not
     712                 :            :     // impact whether we are in "sat" mode
     713                 :        202 :     std::vector<Node> asserts = getAssertionsInternal();
     714                 :        202 :     d_smtSolver->getPreprocessor()->applySubstitutions(asserts);
     715                 :        202 :     ModelCoreBuilder mcb(*d_env.get());
     716                 :        202 :     mcb.setModelCore(asserts, m, opts.smt.modelCoresMode);
     717                 :        202 :   }
     718                 :            : 
     719                 :      25459 :   return m;
     720                 :            : }
     721                 :            : 
     722                 :       8569 : std::shared_ptr<ProofNode> SolverEngine::getAvailableSatProof()
     723                 :            : {
     724         [ -  + ]:       8569 :   if (d_state->getMode() != SmtMode::UNSAT)
     725                 :            :   {
     726                 :          0 :     std::stringstream ss;
     727                 :          0 :     ss << "Cannot get proof unless immediately preceded by UNSAT response.";
     728                 :          0 :     throw RecoverableModalException(ss.str().c_str());
     729                 :          0 :   }
     730                 :       8569 :   std::shared_ptr<ProofNode> pePfn;
     731         [ +  + ]:       8569 :   if (d_env->isSatProofProducing())
     732                 :            :   {
     733                 :            :     // get the proof from the prop engine
     734                 :       8560 :     PropEngine* pe = d_smtSolver->getPropEngine();
     735 [ -  + ][ -  + ]:       8560 :     Assert(pe != nullptr);
                 [ -  - ]
     736                 :       8560 :     pePfn = pe->getProof();
     737 [ -  + ][ -  + ]:       8560 :     Assert(pePfn != nullptr);
                 [ -  - ]
     738                 :            :   }
     739                 :            :   else
     740                 :            :   {
     741                 :            :     const context::CDList<Node>& assertions =
     742                 :          9 :         d_smtSolver->getPreprocessedAssertions();
     743                 :            :     // if not SAT proof producing, we construct a trusted step here
     744                 :          9 :     std::vector<std::shared_ptr<ProofNode>> ps;
     745                 :          9 :     ProofNodeManager* pnm = d_pfManager->getProofNodeManager();
     746         [ +  + ]:         18 :     for (const Node& a : assertions)
     747                 :            :     {
     748                 :            :       // skip true assertions
     749 [ +  - ][ +  - ]:          9 :       if (!a.isConst() || !a.getConst<bool>())
                 [ +  - ]
     750                 :            :       {
     751                 :          9 :         ps.push_back(pnm->mkAssume(a));
     752                 :            :       }
     753                 :            :     }
     754                 :            :     // since we do not have the theory lemmas, this is an SMT refutation trust
     755                 :            :     // step, not a SAT refutation.
     756                 :          9 :     NodeManager* nm = d_env->getNodeManager();
     757                 :          9 :     Node fn = nm->mkConst(false);
     758                 :          9 :     pePfn = pnm->mkTrustedNode(TrustId::SMT_REFUTATION, ps, {}, fn);
     759                 :          9 :   }
     760                 :       8569 :   return pePfn;
     761                 :          0 : }
     762                 :            : 
     763                 :       1013 : QuantifiersEngine* SolverEngine::getAvailableQuantifiersEngine(
     764                 :            :     const char* c) const
     765                 :            : {
     766                 :       1013 :   QuantifiersEngine* qe = d_smtSolver->getQuantifiersEngine();
     767         [ -  + ]:       1013 :   if (qe == nullptr)
     768                 :            :   {
     769                 :          0 :     std::stringstream ss;
     770                 :          0 :     ss << "Cannot " << c << " when quantifiers are not present.";
     771                 :          0 :     throw ModalException(ss.str().c_str());
     772                 :          0 :   }
     773                 :       1013 :   return qe;
     774                 :            : }
     775                 :            : 
     776                 :      43326 : Result SolverEngine::checkSat()
     777                 :            : {
     778                 :      43326 :   beginCall(true);
     779                 :      43373 :   Result res = checkSatInternal({});
     780                 :      43279 :   endCall();
     781                 :      43279 :   return res;
     782                 :          0 : }
     783                 :            : 
     784                 :        287 : Result SolverEngine::checkSat(const Node& assumption)
     785                 :            : {
     786                 :        287 :   beginCall(true);
     787                 :        286 :   std::vector<Node> assump;
     788         [ +  - ]:        286 :   if (!assumption.isNull())
     789                 :            :   {
     790                 :        286 :     assump.push_back(assumption);
     791                 :            :   }
     792                 :        286 :   Result res = checkSatInternal(assump);
     793                 :        284 :   endCall();
     794                 :        568 :   return res;
     795                 :        286 : }
     796                 :            : 
     797                 :       5741 : Result SolverEngine::checkSat(const std::vector<Node>& assumptions)
     798                 :            : {
     799                 :       5741 :   beginCall(true);
     800                 :       5741 :   Result res = checkSatInternal(assumptions);
     801                 :       5735 :   endCall();
     802                 :       5735 :   return res;
     803                 :          0 : }
     804                 :            : 
     805                 :      49353 : Result SolverEngine::checkSatInternal(const std::vector<Node>& assumptions)
     806                 :            : {
     807                 :      49353 :   ensureWellFormedTerms(assumptions, "checkSat");
     808                 :            : 
     809         [ +  - ]:      49353 :   Trace("smt") << "SolverEngine::checkSat(" << assumptions << ")" << endl;
     810                 :            :   // update the state to indicate we are about to run a check-sat
     811                 :      49353 :   d_state->notifyCheckSat();
     812                 :            : 
     813                 :            :   // Call the SMT solver driver to check for satisfiability. Note that in the
     814                 :            :   // case of options like e.g. deep restarts, this may invokve multiple calls
     815                 :            :   // to check satisfiability in the underlying SMT solver
     816                 :      49353 :   Result r = d_smtDriver->checkSat(assumptions);
     817                 :            : 
     818         [ +  - ]:      98604 :   Trace("smt") << "SolverEngine::checkSat(" << assumptions << ") => " << r
     819                 :      49302 :                << endl;
     820                 :            :   // notify our state of the check-sat result
     821                 :      49302 :   d_state->notifyCheckSatResult(r);
     822                 :            : 
     823                 :            :   // Check that SAT results generate a model correctly.
     824         [ +  + ]:      49298 :   if (d_env->getOptions().smt.checkModels)
     825                 :            :   {
     826         [ +  + ]:       3768 :     if (r.getStatus() == Result::SAT)
     827                 :            :     {
     828                 :       3096 :       checkModel();
     829                 :            :     }
     830                 :            :   }
     831                 :            :   // Check that UNSAT results generate a proof correctly.
     832         [ +  + ]:      49298 :   if (d_env->getOptions().smt.checkProofs)
     833                 :            :   {
     834         [ +  + ]:       3601 :     if (r.getStatus() == Result::UNSAT)
     835                 :            :     {
     836                 :       2433 :       checkProof();
     837                 :            :     }
     838                 :            :   }
     839                 :            :   // Check that UNSAT results generate an unsat core correctly.
     840         [ +  + ]:      49298 :   if (d_env->getOptions().smt.checkUnsatCores)
     841                 :            :   {
     842         [ +  + ]:       3136 :     if (r.getStatus() == Result::UNSAT)
     843                 :            :     {
     844                 :       2179 :       TimerStat::CodeTimer checkUnsatCoreTimer(d_stats->d_checkUnsatCoreTime);
     845                 :       2179 :       checkUnsatCore();
     846                 :       2179 :     }
     847                 :            :   }
     848                 :            : 
     849         [ -  + ]:      49298 :   if (d_env->getOptions().base.statisticsEveryQuery)
     850                 :            :   {
     851                 :          0 :     printStatisticsDiff();
     852                 :            :   }
     853                 :            : 
     854                 :            :   // set the filename on the result
     855                 :      49298 :   const std::string& filename = d_env->getOptions().driver.filename;
     856                 :      98596 :   return Result(r, filename);
     857                 :      49302 : }
     858                 :            : 
     859                 :        668 : std::pair<Result, std::vector<Node>> SolverEngine::getTimeoutCore(
     860                 :            :     const std::vector<Node>& assumptions)
     861                 :            : {
     862         [ +  - ]:        668 :   Trace("smt") << "SolverEngine::getTimeoutCore()" << std::endl;
     863                 :        668 :   beginCall(true);
     864                 :            :   // refresh the assertions, to ensure we have applied preprocessing to
     865                 :            :   // all current assertions
     866                 :        668 :   d_smtDriver->refreshAssertions();
     867                 :        668 :   TimeoutCoreManager tcm(*d_env.get());
     868                 :            :   // get the preprocessed assertions
     869                 :            :   const context::CDList<Node>& assertions =
     870                 :        668 :       d_smtSolver->getPreprocessedAssertions();
     871                 :        668 :   std::vector<Node> passerts(assertions.begin(), assertions.end());
     872                 :            :   const context::CDHashMap<size_t, Node>& ppsm =
     873                 :        668 :       d_smtSolver->getPreprocessedSkolemMap();
     874                 :        668 :   std::map<size_t, Node> ppSkolemMap;
     875         [ -  + ]:        668 :   for (auto& pk : ppsm)
     876                 :            :   {
     877                 :          0 :     ppSkolemMap[pk.first] = pk.second;
     878                 :            :   }
     879                 :            :   std::pair<Result, std::vector<Node>> ret =
     880                 :        668 :       tcm.getTimeoutCore(passerts, ppSkolemMap, assumptions);
     881                 :            :   // convert the preprocessed assertions to input assertions
     882                 :        668 :   std::vector<Node> core;
     883         [ +  + ]:        668 :   if (assumptions.empty())
     884                 :            :   {
     885         [ +  + ]:        442 :     if (!ret.second.empty())
     886                 :            :     {
     887                 :        440 :       core = d_ucManager->convertPreprocessedToInput(ret.second, true);
     888                 :            :     }
     889                 :            :   }
     890                 :            :   else
     891                 :            :   {
     892                 :            :     // not necessary to convert, since we computed the assumptions already
     893                 :        226 :     core = ret.second;
     894                 :            :   }
     895                 :        668 :   endCall();
     896                 :       1336 :   return std::pair<Result, std::vector<Node>>(ret.first, core);
     897                 :        668 : }
     898                 :            : 
     899                 :        250 : std::vector<Node> SolverEngine::getUnsatAssumptions(void)
     900                 :            : {
     901         [ +  - ]:        250 :   Trace("smt") << "SMT getUnsatAssumptions()" << endl;
     902         [ -  + ]:        250 :   if (!d_env->getOptions().smt.unsatAssumptions)
     903                 :            :   {
     904                 :          0 :     throw ModalException(
     905                 :            :         "Cannot get unsat assumptions when produce-unsat-assumptions option "
     906                 :          0 :         "is off.");
     907                 :            :   }
     908         [ -  + ]:        250 :   if (d_state->getMode() != SmtMode::UNSAT)
     909                 :            :   {
     910                 :          0 :     throw RecoverableModalException(
     911                 :            :         "Cannot get unsat assumptions unless immediately preceded by "
     912                 :          0 :         "UNSAT.");
     913                 :            :   }
     914                 :        250 :   UnsatCore core = getUnsatCoreInternal();
     915                 :        250 :   std::vector<Node> res;
     916                 :        250 :   std::vector<Node>& assumps = d_smtSolver->getAssertions().getAssumptions();
     917         [ +  + ]:        511 :   for (const Node& e : assumps)
     918                 :            :   {
     919         [ +  + ]:        261 :     if (std::find(core.begin(), core.end(), e) != core.end())
     920                 :            :     {
     921                 :        250 :       res.push_back(e);
     922                 :            :     }
     923                 :            :   }
     924                 :        500 :   return res;
     925                 :        250 : }
     926                 :            : 
     927                 :     182519 : void SolverEngine::assertFormula(const Node& formula)
     928                 :            : {
     929                 :     182519 :   beginCall();
     930                 :     182517 :   ensureWellFormedTerm(formula, "assertFormula");
     931                 :     182517 :   assertFormulaInternal(formula);
     932                 :     182517 : }
     933                 :            : 
     934                 :     182848 : void SolverEngine::assertFormulaInternal(const Node& formula)
     935                 :            : {
     936                 :            :   // as an optimization we do not check whether formula is well-formed here, and
     937                 :            :   // defer this check for certain cases within the assertions module.
     938         [ +  - ]:     182848 :   Trace("smt") << "SolverEngine::assertFormula(" << formula << ")" << endl;
     939                 :     182848 :   Node f = formula;
     940                 :            :   // If we are proof producing and don't permit subtypes, we rewrite now.
     941                 :            :   // Otherwise we will have an assumption with mixed arithmetic which is
     942                 :            :   // not permitted in proofs that cannot be eliminated, and will require a
     943                 :            :   // trust step.
     944                 :            :   // We don't care if we are an internal subsolver, as this rewriting only
     945                 :            :   // impacts having exportable, complete proofs, which is not an issue for
     946                 :            :   // internal subsolvers.
     947 [ +  + ][ +  + ]:     182848 :   if (d_env->isProofProducing() && !d_isInternalSubsolver)
                 [ +  + ]
     948                 :            :   {
     949         [ +  - ]:      89672 :     if (options().proof.proofElimSubtypes)
     950                 :            :     {
     951                 :      89672 :       SubtypeElimNodeConverter senc(d_env->getNodeManager());
     952                 :      89672 :       f = senc.convert(formula);
     953                 :            :       // note we could throw a warning here if formula and f are different,
     954                 :            :       // but currently don't.
     955                 :      89672 :     }
     956                 :            :   }
     957                 :     182848 :   d_smtSolver->getAssertions().assertFormula(f);
     958                 :     182848 : }
     959                 :            : 
     960                 :            : /*
     961                 :            :    --------------------------------------------------------------------------
     962                 :            :     Handling SyGuS commands
     963                 :            :    --------------------------------------------------------------------------
     964                 :            : */
     965                 :            : 
     966                 :       2761 : void SolverEngine::declareSygusVar(Node var)
     967                 :            : {
     968                 :       2761 :   beginCall();
     969                 :       2761 :   d_sygusSolver->declareSygusVar(var);
     970                 :       2761 : }
     971                 :            : 
     972                 :       2635 : void SolverEngine::declareSynthFun(Node func,
     973                 :            :                                    TypeNode sygusType,
     974                 :            :                                    const std::vector<Node>& vars)
     975                 :            : {
     976                 :       2635 :   beginCall();
     977                 :       2637 :   d_sygusSolver->declareSynthFun(func, sygusType, vars);
     978                 :       2633 : }
     979                 :          0 : void SolverEngine::declareSynthFun(Node func, const std::vector<Node>& vars)
     980                 :            : {
     981                 :          0 :   beginCall();
     982                 :            :   // use a null sygus type
     983                 :          0 :   TypeNode sygusType;
     984                 :          0 :   d_sygusSolver->declareSynthFun(func, sygusType, vars);
     985                 :          0 : }
     986                 :            : 
     987                 :       2331 : void SolverEngine::assertSygusConstraint(Node n, bool isAssume)
     988                 :            : {
     989                 :       2331 :   beginCall();
     990                 :       2331 :   d_sygusSolver->assertSygusConstraint(n, isAssume);
     991                 :       2331 : }
     992                 :            : 
     993                 :         63 : std::vector<Node> SolverEngine::getSygusConstraints()
     994                 :            : {
     995                 :         63 :   beginCall();
     996                 :         63 :   return d_sygusSolver->getSygusConstraints();
     997                 :            : }
     998                 :            : 
     999                 :         57 : std::vector<Node> SolverEngine::getSygusAssumptions()
    1000                 :            : {
    1001                 :         57 :   beginCall();
    1002                 :         57 :   return d_sygusSolver->getSygusAssumptions();
    1003                 :            : }
    1004                 :            : 
    1005                 :        123 : void SolverEngine::assertSygusInvConstraint(Node inv,
    1006                 :            :                                             Node pre,
    1007                 :            :                                             Node trans,
    1008                 :            :                                             Node post)
    1009                 :            : {
    1010                 :        123 :   beginCall();
    1011                 :        123 :   d_sygusSolver->assertSygusInvConstraint(inv, pre, trans, post);
    1012                 :        123 : }
    1013                 :            : 
    1014                 :       1191 : SynthResult SolverEngine::checkSynth(bool isNext)
    1015                 :            : {
    1016                 :       1191 :   beginCall();
    1017 [ +  + ][ +  + ]:       1191 :   if (isNext && d_state->getMode() != SmtMode::SYNTH)
                 [ +  + ]
    1018                 :            :   {
    1019                 :          2 :     throw RecoverableModalException(
    1020                 :            :         "Cannot check-synth-next unless immediately preceded by a successful "
    1021                 :          4 :         "call to check-synth(-next).");
    1022                 :            :   }
    1023                 :       1189 :   SynthResult r = d_sygusSolver->checkSynth(isNext);
    1024                 :       1185 :   d_state->notifyCheckSynthResult(r);
    1025                 :       1185 :   return r;
    1026                 :            : }
    1027                 :            : 
    1028                 :         77 : Node SolverEngine::findSynth(modes::FindSynthTarget fst, const TypeNode& gtn)
    1029                 :            : {
    1030         [ +  - ]:         77 :   Trace("smt") << "SolverEngine::findSynth " << fst << std::endl;
    1031                 :         77 :   beginCall(true);
    1032                 :            :   // The grammar(s) we will use. This may be more than one if doing rewrite
    1033                 :            :   // rule synthesis from input or if no grammar is specified, indicating we
    1034                 :            :   // wish to use grammars for each function-to-synthesize.
    1035                 :         77 :   std::vector<TypeNode> gtnu;
    1036         [ +  + ]:         77 :   if (!gtn.isNull())
    1037                 :            :   {
    1038                 :            :     // Must generalize the free symbols in the grammar to variables. Otherwise,
    1039                 :            :     // certain algorithms (e.g. sampling) will fail to treat the free symbols
    1040                 :            :     // of the grammar as inputs to the term to find.
    1041                 :         16 :     TypeNode ggtn = theory::datatypes::utils::generalizeSygusType(gtn);
    1042                 :         16 :     gtnu.push_back(ggtn);
    1043                 :         16 :   }
    1044                 :            :   // if synthesizing rewrite rules from input, we infer the grammar here
    1045         [ +  + ]:         77 :   if (fst == modes::FindSynthTarget::REWRITE_INPUT)
    1046                 :            :   {
    1047         [ -  + ]:         11 :     if (!gtn.isNull())
    1048                 :            :     {
    1049         [ -  - ]:          0 :       Warning() << "Ignoring grammar provided to find-synth :rewrite_input"
    1050                 :          0 :                 << std::endl;
    1051                 :            :     }
    1052                 :         11 :     uint64_t nvars = options().quantifiers.sygusRewSynthInputNVars;
    1053                 :         11 :     std::vector<Node> asserts = getAssertionsInternal();
    1054                 :         22 :     gtnu = preprocessing::passes::SynthRewRulesPass::getGrammarsFrom(
    1055                 :         22 :         *d_env.get(), asserts, nvars);
    1056         [ +  + ]:         11 :     if (gtnu.empty())
    1057                 :            :     {
    1058         [ +  - ]:          1 :       Warning() << "Could not find grammar in find-synth :rewrite_input"
    1059                 :          1 :                 << std::endl;
    1060                 :          1 :       return Node::null();
    1061                 :            :     }
    1062         [ +  + ]:         11 :   }
    1063 [ +  - ][ +  + ]:         76 :   if (d_sygusSolver != nullptr && gtnu.empty())
                 [ +  + ]
    1064                 :            :   {
    1065                 :            :     // if no type provided, and the sygus solver exists,
    1066                 :            :     std::vector<std::pair<Node, TypeNode>> funs =
    1067                 :         50 :         d_sygusSolver->getSynthFunctions();
    1068         [ +  + ]:        100 :     for (const std::pair<Node, TypeNode>& f : funs)
    1069                 :            :     {
    1070         [ +  - ]:         50 :       if (!f.second.isNull())
    1071                 :            :       {
    1072                 :         50 :         gtnu.push_back(f.second);
    1073                 :            :       }
    1074                 :            :     }
    1075                 :         50 :   }
    1076         [ -  + ]:         76 :   if (gtnu.empty())
    1077                 :            :   {
    1078                 :          0 :     throw RecoverableModalException(
    1079                 :            :         "No grammar available in call to find-synth. Either provide one or "
    1080                 :          0 :         "ensure synth-fun has been called.");
    1081                 :            :   }
    1082                 :            :   // initialize find synthesis solver if not done so already
    1083         [ +  + ]:         76 :   if (d_findSynthSolver == nullptr)
    1084                 :            :   {
    1085                 :         64 :     d_findSynthSolver.reset(new FindSynthSolver(*d_env.get()));
    1086                 :            :   }
    1087                 :         76 :   Node ret = d_findSynthSolver->findSynth(fst, gtnu);
    1088                 :         69 :   d_state->notifyFindSynth(!ret.isNull());
    1089                 :         69 :   endCall();
    1090                 :         69 :   return ret;
    1091                 :         77 : }
    1092                 :            : 
    1093                 :         16 : Node SolverEngine::findSynthNext()
    1094                 :            : {
    1095                 :         16 :   beginCall();
    1096         [ -  + ]:         16 :   if (d_state->getMode() != SmtMode::FIND_SYNTH)
    1097                 :            :   {
    1098                 :          0 :     throw RecoverableModalException(
    1099                 :            :         "Cannot find-synth-next unless immediately preceded by a successful "
    1100                 :          0 :         "call to find-synth(-next).");
    1101                 :            :   }
    1102                 :         16 :   Node ret = d_findSynthSolver->findSynthNext();
    1103                 :         16 :   d_state->notifyFindSynth(!ret.isNull());
    1104                 :         16 :   return ret;
    1105                 :          0 : }
    1106                 :            : 
    1107                 :            : /*
    1108                 :            :    --------------------------------------------------------------------------
    1109                 :            :     End of Handling SyGuS commands
    1110                 :            :    --------------------------------------------------------------------------
    1111                 :            : */
    1112                 :            : 
    1113                 :        263 : void SolverEngine::declarePool(const Node& p,
    1114                 :            :                                const std::vector<Node>& initValue)
    1115                 :            : {
    1116                 :        263 :   Assert(p.isVar() && p.getType().isSet());
    1117                 :        263 :   beginCall();
    1118                 :        263 :   QuantifiersEngine* qe = getAvailableQuantifiersEngine("declareTermPool");
    1119                 :        263 :   qe->declarePool(p, initValue);
    1120                 :        263 : }
    1121                 :            : 
    1122                 :        535 : void SolverEngine::declareOracleFun(
    1123                 :            :     Node var, std::function<std::vector<Node>(const std::vector<Node>&)> fn)
    1124                 :            : {
    1125                 :        535 :   beginCall();
    1126                 :        535 :   QuantifiersEngine* qe = getAvailableQuantifiersEngine("declareOracleFun");
    1127                 :        535 :   qe->declareOracleFun(var);
    1128                 :        535 :   NodeManager* nm = d_env->getNodeManager();
    1129                 :        535 :   std::vector<Node> inputs;
    1130                 :        535 :   std::vector<Node> outputs;
    1131                 :        535 :   TypeNode tn = var.getType();
    1132                 :        535 :   Node app;
    1133         [ +  - ]:        535 :   if (tn.isFunction())
    1134                 :            :   {
    1135                 :        535 :     const std::vector<TypeNode>& argTypes = tn.getArgTypes();
    1136         [ +  + ]:       1280 :     for (const TypeNode& t : argTypes)
    1137                 :            :     {
    1138                 :        745 :       inputs.push_back(NodeManager::mkBoundVar(t));
    1139                 :            :     }
    1140                 :        535 :     outputs.push_back(NodeManager::mkBoundVar(tn.getRangeType()));
    1141                 :        535 :     std::vector<Node> appc;
    1142                 :        535 :     appc.push_back(var);
    1143                 :        535 :     appc.insert(appc.end(), inputs.begin(), inputs.end());
    1144                 :        535 :     app = nm->mkNode(Kind::APPLY_UF, appc);
    1145                 :        535 :   }
    1146                 :            :   else
    1147                 :            :   {
    1148                 :          0 :     outputs.push_back(NodeManager::mkBoundVar(tn.getRangeType()));
    1149                 :          0 :     app = var;
    1150                 :            :   }
    1151                 :            :   // makes equality assumption
    1152                 :       1070 :   Node assume = nm->mkNode(Kind::EQUAL, app, outputs[0]);
    1153                 :            :   // no constraints
    1154                 :        535 :   Node constraint = nm->mkConst(true);
    1155                 :            :   // make the oracle constant which carries the method implementation
    1156                 :        535 :   Oracle oracle(fn);
    1157                 :        535 :   Node o = nm->mkOracle(oracle);
    1158                 :            :   // set the attribute, which ensures we remember the method implementation for
    1159                 :            :   // the oracle function
    1160                 :        535 :   var.setAttribute(theory::OracleInterfaceAttribute(), o);
    1161                 :            :   // define the oracle interface
    1162                 :            :   Node q = quantifiers::OracleEngine::mkOracleInterface(
    1163                 :       1070 :       inputs, outputs, assume, constraint, o);
    1164                 :            :   // assert it
    1165                 :        535 :   assertFormula(q);
    1166                 :        535 : }
    1167                 :            : 
    1168                 :         28 : void SolverEngine::addPlugin(Plugin* p)
    1169                 :            : {
    1170         [ -  + ]:         28 :   if (d_state->isFullyInited())
    1171                 :            :   {
    1172                 :          0 :     throw ModalException(
    1173                 :          0 :         "Cannot add plugin after the solver has been fully initialized.");
    1174                 :            :   }
    1175                 :            :   // we do not initialize the solver here.
    1176                 :         28 :   d_env->addPlugin(p);
    1177                 :         28 : }
    1178                 :            : 
    1179                 :       8812 : Node SolverEngine::simplify(const Node& t, bool applySubs)
    1180                 :            : {
    1181                 :       8812 :   beginCall(true);
    1182                 :       8812 :   Node tt = t;
    1183                 :            :   // if we are applying substitutions
    1184         [ +  + ]:       8812 :   if (applySubs)
    1185                 :            :   {
    1186                 :            :     // ensure we've processed assertions
    1187                 :        325 :     d_smtDriver->refreshAssertions();
    1188                 :            :     // apply substitutions
    1189                 :        323 :     tt = d_smtSolver->getPreprocessor()->applySubstitutions(tt);
    1190                 :            :   }
    1191                 :            :   // now rewrite
    1192                 :       8810 :   Node ret = d_env->getRewriter()->rewrite(tt);
    1193                 :            :   // make so that the returned term does not involve arithmetic subtyping
    1194                 :       8810 :   SubtypeElimNodeConverter senc(d_env->getNodeManager());
    1195                 :       8810 :   ret = senc.convert(ret);
    1196                 :       8810 :   endCall();
    1197                 :      17620 :   return ret;
    1198                 :       8812 : }
    1199                 :            : 
    1200                 :      20244 : Node SolverEngine::getValue(const Node& t, bool fromUser)
    1201                 :            : {
    1202                 :      20244 :   ensureWellFormedTerm(t, "get value");
    1203         [ +  - ]:      20244 :   Trace("smt") << "SMT getValue(" << t << ")" << endl;
    1204                 :      20244 :   TypeNode expectedType = t.getType();
    1205                 :            : 
    1206                 :            :   // We must expand definitions here, which replaces certain subterms of t
    1207                 :            :   // by the form that is used internally. This is necessary for some corner
    1208                 :            :   // cases of get-value to be accurate, e.g., when getting the value of
    1209                 :            :   // a division-by-zero term, we require getting the appropriate skolem
    1210                 :            :   // function corresponding to division-by-zero which may have been used during
    1211                 :            :   // the previous satisfiability check.
    1212                 :      20244 :   std::unordered_map<Node, Node> cache;
    1213                 :      20244 :   ExpandDefs expDef(*d_env.get());
    1214                 :            :   // Must apply substitutions first to ensure we expand definitions in the
    1215                 :            :   // solved form of t as well.
    1216                 :      20244 :   Node n = d_smtSolver->getPreprocessor()->applySubstitutions(t);
    1217                 :      20244 :   n = expDef.expandDefinitions(n, cache);
    1218                 :            : 
    1219         [ +  - ]:      20244 :   Trace("smt") << "--- getting value of " << n << endl;
    1220                 :            :   // There are two ways model values for terms are computed (for historical
    1221                 :            :   // reasons).  One way is that used in check-model; the other is that
    1222                 :            :   // used by the Model classes.  It's not clear to me exactly how these
    1223                 :            :   // two are different, but they need to be unified.  This ugly hack here
    1224                 :            :   // is to fix bug 554 until we can revamp boolean-terms and models [MGD]
    1225                 :            : 
    1226                 :            :   // AJR : necessary?
    1227         [ +  + ]:      20244 :   if (!n.getType().isFunction())
    1228                 :            :   {
    1229                 :      19942 :     n = d_env->getRewriter()->rewrite(n);
    1230                 :            :   }
    1231                 :            : 
    1232         [ +  - ]:      20244 :   Trace("smt") << "--- getting value of " << n << endl;
    1233                 :      20244 :   TheoryModel* m = getAvailableModel("get-value");
    1234 [ -  + ][ -  + ]:      20244 :   Assert(m != nullptr);
                 [ -  - ]
    1235                 :      20244 :   Node resultNode = m->getValue(n);
    1236         [ +  - ]:      20244 :   Trace("smt") << "--- got value " << n << " = " << resultNode << endl;
    1237 [ +  - ][ -  + ]:      20244 :   Trace("smt") << "--- type " << resultNode.getType() << endl;
                 [ -  - ]
    1238         [ +  - ]:      20244 :   Trace("smt") << "--- expected type " << expectedType << endl;
    1239                 :            : 
    1240                 :            :   // type-check the result we got
    1241                 :      20244 :   Assert(resultNode.isNull() || resultNode.getType() == expectedType)
    1242                 :          0 :       << "Run with -t smt for details.";
    1243                 :            : 
    1244                 :            :   // Ensure it's a value (constant or const-ish like real algebraic
    1245                 :            :   // numbers), or a lambda (for uninterpreted functions). This assertion only
    1246                 :            :   // holds for models that do not have approximate values.
    1247         [ +  + ]:      20244 :   if (!m->isValue(resultNode))
    1248                 :            :   {
    1249                 :          4 :     bool subSuccess = false;
    1250 [ +  - ][ +  - ]:          4 :     if (fromUser && d_env->getOptions().smt.checkModelSubsolver)
                 [ +  - ]
    1251                 :            :     {
    1252                 :            :       // invoke satisfiability check
    1253                 :            :       // ensure symbols have been substituted
    1254                 :          4 :       resultNode = m->simplify(resultNode);
    1255                 :            :       // Note that we must be a "closed" term, i.e. one that can be
    1256                 :            :       // given in an assertion.
    1257         [ +  - ]:          4 :       if (NonClosedNodeConverter::isClosed(*d_env.get(), resultNode))
    1258                 :            :       {
    1259                 :            :         // set up a resource limit
    1260                 :          4 :         ResourceManager* rm = getResourceManager();
    1261                 :          4 :         rm->beginCall();
    1262                 :          4 :         TypeNode rtn = resultNode.getType();
    1263                 :          4 :         SkolemManager* skm = d_env->getNodeManager()->getSkolemManager();
    1264                 :          4 :         Node k = skm->mkInternalSkolemFunction(
    1265                 :          8 :             InternalSkolemId::GET_VALUE_PURIFY, rtn, {resultNode});
    1266                 :            :         // the query is (k = resultNode)
    1267                 :          4 :         Node checkQuery = resultNode.eqNode(k);
    1268                 :          4 :         Options subOptions;
    1269                 :          4 :         subOptions.copyValues(d_env->getOptions());
    1270                 :          4 :         smt::SetDefaults::disableChecking(subOptions);
    1271                 :            :         // ensure no infinite loop
    1272                 :          4 :         subOptions.write_smt().checkModelSubsolver = false;
    1273                 :          4 :         subOptions.write_smt().modelVarElimUneval = false;
    1274                 :          4 :         subOptions.write_smt().simplificationMode =
    1275                 :            :             options::SimplificationMode::NONE;
    1276                 :            :         // initialize the subsolver
    1277                 :          4 :         SubsolverSetupInfo ssi(*d_env.get(), subOptions);
    1278                 :          4 :         std::unique_ptr<SolverEngine> getValueChecker;
    1279                 :          4 :         initializeSubsolver(d_env->getNodeManager(), getValueChecker, ssi);
    1280                 :            :         // disable all checking options
    1281                 :          4 :         SetDefaults::disableChecking(getValueChecker->getOptions());
    1282                 :          4 :         getValueChecker->assertFormula(checkQuery);
    1283                 :          4 :         Result r = getValueChecker->checkSat();
    1284         [ +  - ]:          4 :         if (r == Result::SAT)
    1285                 :            :         {
    1286                 :            :           // value is the result of getting the value of k
    1287                 :          4 :           resultNode = getValueChecker->getValue(k);
    1288                 :          4 :           subSuccess = m->isValue(resultNode);
    1289                 :            :         }
    1290                 :            :         // end resource limit
    1291                 :          4 :         rm->refresh();
    1292                 :          4 :       }
    1293                 :            :     }
    1294         [ -  + ]:          4 :     if (!subSuccess)
    1295                 :            :     {
    1296                 :          0 :       d_env->warning() << "Could not evaluate " << resultNode << " in getValue."
    1297                 :          0 :                        << std::endl;
    1298                 :            :     }
    1299                 :            :   }
    1300                 :            : 
    1301         [ +  + ]:      20244 :   if (d_env->getOptions().smt.abstractValues)
    1302                 :            :   {
    1303                 :          8 :     TypeNode rtn = resultNode.getType();
    1304         [ +  - ]:          8 :     if (rtn.isArray())
    1305                 :            :     {
    1306                 :            :       // construct the skolem function
    1307                 :          8 :       SkolemManager* skm = d_env->getNodeManager()->getSkolemManager();
    1308                 :          8 :       Node a = skm->mkInternalSkolemFunction(
    1309                 :         16 :           InternalSkolemId::ABSTRACT_VALUE, rtn, {resultNode});
    1310                 :            :       // add to top-level substitutions if applicable
    1311                 :          8 :       theory::TrustSubstitutionMap& tsm = d_env->getTopLevelSubstitutions();
    1312         [ +  + ]:          8 :       if (!tsm.get().hasSubstitution(resultNode))
    1313                 :            :       {
    1314                 :          6 :         tsm.addSubstitution(resultNode, a);
    1315                 :            :       }
    1316                 :          8 :       resultNode = a;
    1317         [ +  - ]:          8 :       Trace("smt") << "--- abstract value >> " << resultNode << endl;
    1318                 :          8 :     }
    1319                 :          8 :   }
    1320                 :      40488 :   return resultNode;
    1321                 :      20244 : }
    1322                 :            : 
    1323                 :          0 : std::vector<Node> SolverEngine::getValues(const std::vector<Node>& exprs,
    1324                 :            :                                           bool fromUser)
    1325                 :            : {
    1326                 :          0 :   std::vector<Node> result;
    1327         [ -  - ]:          0 :   for (const Node& e : exprs)
    1328                 :            :   {
    1329                 :          0 :     result.push_back(getValue(e, fromUser));
    1330                 :            :   }
    1331                 :          0 :   return result;
    1332                 :          0 : }
    1333                 :            : 
    1334                 :        619 : std::vector<Node> SolverEngine::getModelDomainElements(TypeNode tn) const
    1335                 :            : {
    1336 [ -  + ][ -  + ]:        619 :   Assert(tn.isUninterpretedSort());
                 [ -  - ]
    1337                 :        619 :   TheoryModel* m = getAvailableModel("getModelDomainElements");
    1338                 :        619 :   return m->getDomainElements(tn);
    1339                 :            : }
    1340                 :            : 
    1341                 :        585 : bool SolverEngine::isModelCoreSymbol(Node n)
    1342                 :            : {
    1343 [ -  + ][ -  + ]:        585 :   Assert(n.isVar());
                 [ -  - ]
    1344                 :        585 :   const Options& opts = d_env->getOptions();
    1345         [ -  + ]:        585 :   if (opts.smt.modelCoresMode == options::ModelCoresMode::NONE)
    1346                 :            :   {
    1347                 :            :     // if the model core mode is none, we are always a model core symbol
    1348                 :          0 :     return true;
    1349                 :            :   }
    1350                 :        585 :   TheoryModel* tm = getAvailableModel("isModelCoreSymbol");
    1351                 :        585 :   return tm->isModelCoreSymbol(n);
    1352                 :            : }
    1353                 :            : 
    1354                 :        239 : std::string SolverEngine::getModel(const std::vector<TypeNode>& declaredSorts,
    1355                 :            :                                    const std::vector<Node>& declaredFuns)
    1356                 :            : {
    1357                 :            :   // !!! Note that all methods called here should have a version at the API
    1358                 :            :   // level. This is to ensure that the information associated with a model is
    1359                 :            :   // completely accessible by the user. This is currently not rigorously
    1360                 :            :   // enforced. An alternative design would be to have this method implemented
    1361                 :            :   // at the API level, but this makes exceptions in the text interface less
    1362                 :            :   // intuitive.
    1363                 :        239 :   TheoryModel* tm = getAvailableModel("get model");
    1364                 :            :   // use the smt::Model model utility for printing
    1365                 :        239 :   const Options& opts = d_env->getOptions();
    1366                 :        239 :   bool isKnownSat = (d_state->getMode() == SmtMode::SAT);
    1367                 :        239 :   Model m(isKnownSat, opts.driver.filename);
    1368                 :            :   // set the model declarations, which determines what is printed in the model
    1369         [ +  + ]:        439 :   for (const TypeNode& tn : declaredSorts)
    1370                 :            :   {
    1371                 :        200 :     m.addDeclarationSort(tn, getModelDomainElements(tn));
    1372                 :            :   }
    1373                 :        239 :   bool usingModelCores =
    1374                 :        239 :       (opts.smt.modelCoresMode != options::ModelCoresMode::NONE);
    1375         [ +  + ]:        698 :   for (const Node& n : declaredFuns)
    1376                 :            :   {
    1377 [ +  + ][ +  + ]:        459 :     if (usingModelCores && !tm->isModelCoreSymbol(n))
         [ +  + ][ +  + ]
                 [ -  - ]
    1378                 :            :     {
    1379                 :            :       // skip if not in model core
    1380                 :         14 :       continue;
    1381                 :            :     }
    1382                 :        445 :     Node value = tm->getValue(n);
    1383                 :        445 :     m.addDeclarationTerm(n, value);
    1384                 :        445 :   }
    1385                 :            :   // for separation logic
    1386                 :        239 :   TypeNode locT, dataT;
    1387         [ +  + ]:        239 :   if (getSepHeapTypes(locT, dataT))
    1388                 :            :   {
    1389                 :          1 :     std::pair<Node, Node> sh = getSepHeapAndNilExpr();
    1390                 :          1 :     m.setHeapModel(sh.first, sh.second);
    1391                 :          1 :   }
    1392                 :            :   // print the model
    1393                 :        239 :   std::stringstream ssm;
    1394                 :        239 :   ssm << m;
    1395                 :        478 :   return ssm.str();
    1396                 :        239 : }
    1397                 :            : 
    1398                 :        103 : void SolverEngine::blockModel(modes::BlockModelsMode mode)
    1399                 :            : {
    1400         [ +  - ]:        103 :   Trace("smt") << "SMT blockModel()" << endl;
    1401                 :        103 :   TheoryModel* m = getAvailableModel("block model");
    1402                 :            : 
    1403                 :            :   // get expanded assertions
    1404                 :        103 :   std::vector<Node> eassertsProc = getSubstitutedAssertions();
    1405                 :        103 :   ModelBlocker mb(*d_env.get());
    1406                 :        103 :   Node eblocker = mb.getModelBlocker(eassertsProc, m, mode);
    1407         [ +  - ]:        103 :   Trace("smt") << "Block formula: " << eblocker << std::endl;
    1408                 :            : 
    1409                 :            :   // Must begin call now to ensure pops are processed. We cannot call this
    1410                 :            :   // above since we are accessing the model.
    1411                 :        103 :   beginCall();
    1412                 :        103 :   assertFormulaInternal(eblocker);
    1413                 :        103 : }
    1414                 :            : 
    1415                 :        228 : void SolverEngine::blockModelValues(const std::vector<Node>& exprs)
    1416                 :            : {
    1417         [ +  - ]:        228 :   Trace("smt") << "SMT blockModelValues()" << endl;
    1418                 :        228 :   ensureWellFormedTerms(exprs, "block model values");
    1419                 :            : 
    1420                 :        228 :   TheoryModel* m = getAvailableModel("block model values");
    1421                 :            : 
    1422                 :            :   // get expanded assertions
    1423                 :        228 :   std::vector<Node> eassertsProc = getSubstitutedAssertions();
    1424                 :            :   // we always do block model values mode here
    1425                 :        228 :   ModelBlocker mb(*d_env.get());
    1426                 :            :   Node eblocker = mb.getModelBlocker(
    1427                 :        228 :       eassertsProc, m, modes::BlockModelsMode::VALUES, exprs);
    1428                 :            : 
    1429                 :            :   // Call begin call here, for same reasons as above.
    1430                 :        228 :   beginCall();
    1431                 :        228 :   assertFormulaInternal(eblocker);
    1432                 :        228 : }
    1433                 :            : 
    1434                 :        345 : std::pair<Node, Node> SolverEngine::getSepHeapAndNilExpr(void)
    1435                 :            : {
    1436         [ -  + ]:        345 :   if (!getLogicInfo().isTheoryEnabled(THEORY_SEP))
    1437                 :            :   {
    1438                 :          0 :     const char* msg =
    1439                 :            :         "Cannot obtain separation logic expressions if not using the "
    1440                 :            :         "separation logic theory.";
    1441                 :          0 :     throw RecoverableModalException(msg);
    1442                 :            :   }
    1443                 :        345 :   Node heap;
    1444                 :        345 :   Node nil;
    1445                 :        345 :   TheoryModel* tm = getAvailableModel("get separation logic heap and nil");
    1446         [ +  + ]:        345 :   if (!tm->getHeapModel(heap, nil))
    1447                 :            :   {
    1448                 :          4 :     const char* msg =
    1449                 :            :         "Failed to obtain heap/nil "
    1450                 :            :         "expressions from theory model.";
    1451                 :          4 :     throw RecoverableModalException(msg);
    1452                 :            :   }
    1453                 :        682 :   return std::make_pair(heap, nil);
    1454                 :        349 : }
    1455                 :            : 
    1456                 :       1632 : std::vector<Node> SolverEngine::getAssertionsInternal() const
    1457                 :            : {
    1458 [ -  + ][ -  + ]:       1632 :   Assert(d_state->isFullyInited());
                 [ -  - ]
    1459                 :            :   // ensure that global declarations are processed
    1460                 :       1632 :   d_smtSolver->getAssertions().refresh();
    1461                 :       1632 :   const CDList<Node>& al = d_smtSolver->getAssertions().getAssertionList();
    1462                 :       1632 :   std::vector<Node> res;
    1463         [ +  + ]:       3913 :   for (const Node& n : al)
    1464                 :            :   {
    1465                 :       2281 :     res.emplace_back(n);
    1466                 :            :   }
    1467                 :       1632 :   return res;
    1468                 :          0 : }
    1469                 :            : 
    1470                 :     303343 : const Options& SolverEngine::options() const { return d_env->getOptions(); }
    1471                 :            : 
    1472                 :      24938 : bool SolverEngine::isWellFormedTerm(const Node& n) const
    1473                 :            : {
    1474                 :            :   // Well formed if it does not have free variables. Note that n may have
    1475                 :            :   // variable shadowing.
    1476                 :      24938 :   return !expr::hasFreeVar(n);
    1477                 :            : }
    1478                 :            : 
    1479                 :     209246 : void SolverEngine::ensureWellFormedTerm(const Node& n,
    1480                 :            :                                         const std::string& src) const
    1481                 :            : {
    1482         [ +  - ]:     209246 :   if (Configuration::isAssertionBuild())
    1483                 :            :   {
    1484                 :            :     // Don't check for shadowing here, since shadowing may occur from API
    1485                 :            :     // users, including the smt2 parser. We don't need to rewrite since
    1486                 :            :     // getFreeVariables is robust to variable shadowing.
    1487                 :     209246 :     std::unordered_set<internal::Node> fvs;
    1488                 :     209246 :     expr::getFreeVariables(n, fvs);
    1489         [ -  + ]:     209246 :     if (!fvs.empty())
    1490                 :            :     {
    1491                 :          0 :       std::stringstream se;
    1492                 :          0 :       se << "Cannot process term " << n << " with ";
    1493                 :          0 :       se << "free variables: " << fvs;
    1494                 :          0 :       se << " in context " << src << std::endl;
    1495                 :          0 :       throw ModalException(se.str().c_str());
    1496                 :          0 :     }
    1497                 :     209246 :   }
    1498                 :     209246 : }
    1499                 :            : 
    1500                 :      49581 : void SolverEngine::ensureWellFormedTerms(const std::vector<Node>& ns,
    1501                 :            :                                          const std::string& src) const
    1502                 :            : {
    1503         [ +  - ]:      49581 :   if (Configuration::isAssertionBuild())
    1504                 :            :   {
    1505         [ +  + ]:      56066 :     for (const Node& n : ns)
    1506                 :            :     {
    1507                 :       6485 :       ensureWellFormedTerm(n, src);
    1508                 :            :     }
    1509                 :            :   }
    1510                 :      49581 : }
    1511                 :            : 
    1512                 :       6091 : void SolverEngine::printProof(std::ostream& out,
    1513                 :            :                               std::shared_ptr<ProofNode> fp,
    1514                 :            :                               modes::ProofFormat proofFormat,
    1515                 :            :                               const std::map<Node, std::string>& assertionNames)
    1516                 :            : {
    1517                 :       6091 :   out << "(" << std::endl;
    1518                 :            :   // we print in the format based on the proof mode
    1519                 :       6091 :   options::ProofFormatMode mode = options::ProofFormatMode::NONE;
    1520 [ +  + ][ -  + ]:       6091 :   switch (proofFormat)
            [ -  - ][ - ]
    1521                 :            :   {
    1522                 :       5413 :     case modes::ProofFormat::DEFAULT:
    1523                 :       5413 :       mode = options().proof.proofFormatMode;
    1524                 :       5413 :       break;
    1525                 :        252 :     case modes::ProofFormat::NONE: mode = options::ProofFormatMode::NONE; break;
    1526                 :          0 :     case modes::ProofFormat::DOT: mode = options::ProofFormatMode::DOT; break;
    1527                 :        426 :     case modes::ProofFormat::ALETHE:
    1528                 :        426 :       mode = options::ProofFormatMode::ALETHE;
    1529                 :        426 :       break;
    1530                 :          0 :     case modes::ProofFormat::CPC: mode = options::ProofFormatMode::CPC; break;
    1531                 :          0 :     case modes::ProofFormat::LFSC: mode = options::ProofFormatMode::LFSC; break;
    1532                 :            :   }
    1533                 :            : 
    1534                 :       6091 :   d_pfManager->printProof(out,
    1535                 :            :                           fp,
    1536                 :            :                           mode,
    1537                 :            :                           ProofScopeMode::DEFINITIONS_AND_ASSERTIONS,
    1538                 :            :                           assertionNames);
    1539                 :       6091 :   out << ")" << std::endl;
    1540                 :       6091 : }
    1541                 :            : 
    1542                 :        331 : std::vector<Node> SolverEngine::getSubstitutedAssertions()
    1543                 :            : {
    1544                 :        331 :   std::vector<Node> easserts = getAssertions();
    1545                 :            :   // must expand definitions
    1546                 :        331 :   d_smtSolver->getPreprocessor()->applySubstitutions(easserts);
    1547                 :        331 :   return easserts;
    1548                 :          0 : }
    1549                 :            : 
    1550                 :     815428 : Env& SolverEngine::getEnv() { return *d_env.get(); }
    1551                 :            : 
    1552                 :       1072 : void SolverEngine::declareSepHeap(TypeNode locT, TypeNode dataT)
    1553                 :            : {
    1554         [ -  + ]:       1072 :   if (d_state->isFullyInited())
    1555                 :            :   {
    1556                 :          0 :     throw ModalException(
    1557                 :            :         "Cannot set logic in SolverEngine after the engine has "
    1558                 :          0 :         "finished initializing.");
    1559                 :            :   }
    1560         [ -  + ]:       1072 :   if (!getLogicInfo().isTheoryEnabled(THEORY_SEP))
    1561                 :            :   {
    1562                 :          0 :     const char* msg =
    1563                 :            :         "Cannot declare heap if not using the separation logic theory.";
    1564                 :          0 :     throw RecoverableModalException(msg);
    1565                 :            :   }
    1566                 :       1072 :   TypeNode locT2, dataT2;
    1567         [ +  + ]:       1072 :   if (getSepHeapTypes(locT2, dataT2))
    1568                 :            :   {
    1569                 :          3 :     std::stringstream ss;
    1570                 :            :     ss << "ERROR: cannot declare heap types for separation logic more than "
    1571                 :          3 :           "once.  We are declaring heap of type ";
    1572                 :          3 :     ss << locT << " -> " << dataT << ", but we already have ";
    1573                 :          3 :     ss << locT2 << " -> " << dataT2;
    1574                 :          3 :     throw LogicException(ss.str());
    1575                 :          3 :   }
    1576                 :       1069 :   d_env->declareSepHeap(locT, dataT);
    1577                 :       1075 : }
    1578                 :            : 
    1579                 :       1311 : bool SolverEngine::getSepHeapTypes(TypeNode& locT, TypeNode& dataT)
    1580                 :            : {
    1581         [ +  + ]:       1311 :   if (!d_env->hasSepHeap())
    1582                 :            :   {
    1583                 :       1307 :     return false;
    1584                 :            :   }
    1585                 :          4 :   locT = d_env->getSepLocType();
    1586                 :          4 :   dataT = d_env->getSepDataType();
    1587                 :          4 :   return true;
    1588                 :            : }
    1589                 :            : 
    1590                 :        346 : Node SolverEngine::getSepHeapExpr() { return getSepHeapAndNilExpr().first; }
    1591                 :            : 
    1592                 :        338 : Node SolverEngine::getSepNilExpr() { return getSepHeapAndNilExpr().second; }
    1593                 :            : 
    1594                 :        648 : std::vector<Node> SolverEngine::getLearnedLiterals(modes::LearnedLitType t)
    1595                 :            : {
    1596         [ +  - ]:        648 :   Trace("smt") << "SMT getLearnedLiterals()" << std::endl;
    1597                 :            :   // note that the default mode for learned literals is via the prop engine,
    1598                 :            :   // although other modes could use the preprocessor
    1599                 :        648 :   PropEngine* pe = d_smtSolver->getPropEngine();
    1600 [ -  + ][ -  + ]:        648 :   Assert(pe != nullptr);
                 [ -  - ]
    1601                 :        648 :   return pe->getLearnedZeroLevelLiterals(t);
    1602                 :            : }
    1603                 :            : 
    1604                 :       2433 : void SolverEngine::checkProof()
    1605                 :            : {
    1606 [ -  + ][ -  + ]:       2433 :   Assert(d_env->getOptions().smt.produceProofs);
                 [ -  - ]
    1607         [ +  + ]:       2433 :   if (d_env->isSatProofProducing())
    1608                 :            :   {
    1609                 :            :     // internal check the proof
    1610                 :       2427 :     PropEngine* pe = d_smtSolver->getPropEngine();
    1611 [ -  + ][ -  + ]:       2427 :     Assert(pe != nullptr);
                 [ -  - ]
    1612         [ +  + ]:       2427 :     if (d_env->getOptions().proof.proofCheck == options::ProofCheckMode::EAGER)
    1613                 :            :     {
    1614                 :          7 :       pe->checkProof(d_smtSolver->getAssertions().getAssertionList());
    1615                 :            :     }
    1616                 :            :   }
    1617                 :       2433 :   std::shared_ptr<ProofNode> pePfn = getAvailableSatProof();
    1618         [ +  - ]:       2433 :   if (d_env->getOptions().smt.checkProofs)
    1619                 :            :   {
    1620                 :            :     // connect proof to assertions, which will fail if the proof is malformed
    1621                 :       2433 :     d_pfManager->connectProofToAssertions(
    1622                 :            :         pePfn, d_smtSolver->getAssertions(), ProofScopeMode::UNIFIED);
    1623                 :            :     // now check the proof
    1624                 :       2433 :     d_pfManager->checkFinalProof(pePfn);
    1625                 :            :   }
    1626                 :       2433 : }
    1627                 :            : 
    1628                 :     275388 : void SolverEngine::beginCall(bool needsRLlimit)
    1629                 :            : {
    1630                 :            :   // ensure this solver engine has been initialized
    1631                 :     275388 :   finishInit();
    1632                 :            :   // ensure the context is current
    1633                 :     275383 :   d_ctxManager->doPendingPops();
    1634                 :            :   // optionally, ensure the resource manager's state is current
    1635         [ +  + ]:     275383 :   if (needsRLlimit)
    1636                 :            :   {
    1637                 :      60346 :     ResourceManager* rm = getResourceManager();
    1638                 :      60346 :     rm->beginCall();
    1639         [ +  - ]:     120692 :     Trace("limit") << "SolverEngine::beginCall(): cumulative millis "
    1640                 :          0 :                    << rm->getTimeUsage() << ", resources "
    1641                 :      60346 :                    << rm->getResourceUsage() << std::endl;
    1642                 :            :   }
    1643                 :     275383 : }
    1644                 :            : 
    1645                 :      60273 : void SolverEngine::endCall()
    1646                 :            : {
    1647                 :            :   // refresh the resource manager (for stats)
    1648                 :      60273 :   ResourceManager* rm = getResourceManager();
    1649                 :      60273 :   rm->refresh();
    1650         [ +  - ]:     120546 :   Trace("limit") << "SolverEngine::endCall(): cumulative millis "
    1651                 :          0 :                  << rm->getTimeUsage() << ", resources "
    1652                 :      60273 :                  << rm->getResourceUsage() << std::endl;
    1653                 :      60273 : }
    1654                 :            : 
    1655                 :        286 : StatisticsRegistry& SolverEngine::getStatisticsRegistry()
    1656                 :            : {
    1657                 :        286 :   return d_env->getStatisticsRegistry();
    1658                 :            : }
    1659                 :            : 
    1660                 :       4420 : UnsatCore SolverEngine::getUnsatCoreInternal(bool isInternal)
    1661                 :            : {
    1662         [ -  + ]:       4420 :   if (!d_env->getOptions().smt.produceUnsatCores)
    1663                 :            :   {
    1664                 :          0 :     throw ModalException(
    1665                 :            :         "Cannot get an unsat core when produce-unsat-cores or produce-proofs "
    1666                 :          0 :         "option is off.");
    1667                 :            :   }
    1668         [ -  + ]:       4420 :   if (d_state->getMode() != SmtMode::UNSAT)
    1669                 :            :   {
    1670                 :          0 :     throw RecoverableModalException(
    1671                 :            :         "Cannot get an unsat core unless immediately preceded by "
    1672                 :          0 :         "UNSAT response.");
    1673                 :            :   }
    1674                 :       4420 :   std::vector<Node> core = d_ucManager->getUnsatCore(isInternal);
    1675                 :       8840 :   return UnsatCore(core);
    1676                 :       4420 : }
    1677                 :            : 
    1678                 :       2179 : void SolverEngine::checkUnsatCore()
    1679                 :            : {
    1680 [ -  + ][ -  + ]:       2179 :   Assert(d_env->getOptions().smt.produceUnsatCores)
                 [ -  - ]
    1681                 :          0 :       << "cannot check unsat core if unsat cores are turned off";
    1682                 :            : 
    1683                 :       2179 :   d_env->verbose(1) << "SolverEngine::checkUnsatCore(): generating unsat core"
    1684                 :       2179 :                     << std::endl;
    1685                 :       2179 :   UnsatCore core = getUnsatCoreInternal();
    1686                 :            : 
    1687                 :            :   // initialize the core checker
    1688                 :       2179 :   std::unique_ptr<SolverEngine> coreChecker;
    1689                 :       2179 :   initializeSubsolver(coreChecker, *d_env.get());
    1690                 :            :   // disable all proof options
    1691                 :       2179 :   SetDefaults::disableChecking(coreChecker->getOptions());
    1692                 :            : 
    1693                 :       2179 :   d_env->verbose(1) << "SolverEngine::checkUnsatCore(): pushing core assertions"
    1694                 :       2179 :                     << std::endl;
    1695                 :            :   // set up the subsolver
    1696                 :            :   std::unordered_set<Node> adefs =
    1697                 :       2179 :       d_smtSolver->getAssertions().getCurrentAssertionListDefitions();
    1698                 :       2179 :   std::unordered_set<Node> removed;
    1699                 :       2179 :   assertToSubsolver(*coreChecker.get(), core.getCore(), adefs, removed);
    1700                 :       2179 :   Result r;
    1701                 :            :   try
    1702                 :            :   {
    1703                 :       2179 :     r = coreChecker->checkSat();
    1704                 :            :   }
    1705                 :          0 :   catch (...)
    1706                 :            :   {
    1707                 :          0 :     throw;
    1708                 :          0 :   }
    1709                 :       2179 :   d_env->verbose(1) << "SolverEngine::checkUnsatCore(): result is " << r
    1710                 :       2179 :                     << std::endl;
    1711         [ +  + ]:       2179 :   if (r.isUnknown())
    1712                 :            :   {
    1713                 :          2 :     d_env->warning() << "SolverEngine::checkUnsatCore(): could not check core result "
    1714                 :          2 :                  "unknown."
    1715                 :          2 :               << std::endl;
    1716                 :            :   }
    1717         [ -  + ]:       2177 :   else if (r.getStatus() == Result::SAT)
    1718                 :            :   {
    1719                 :          0 :     InternalError()
    1720                 :          0 :         << "SolverEngine::checkUnsatCore(): produced core was satisfiable.";
    1721                 :            :   }
    1722                 :       2179 : }
    1723                 :            : 
    1724                 :       3096 : void SolverEngine::checkModel(bool hardFailure)
    1725                 :            : {
    1726                 :       3096 :   const CDList<Node>& al = d_smtSolver->getAssertions().getAssertionList();
    1727                 :            :   // we always enable the assertion list, so it is able to be checked
    1728                 :            : 
    1729                 :       3096 :   TimerStat::CodeTimer checkModelTimer(d_stats->d_checkModelTime);
    1730                 :            : 
    1731                 :       3096 :   d_env->verbose(1) << "SolverEngine::checkModel(): generating model"
    1732                 :       3096 :                     << std::endl;
    1733                 :       3096 :   TheoryModel* m = getAvailableModel("check model");
    1734 [ -  + ][ -  + ]:       3096 :   Assert(m != nullptr);
                 [ -  - ]
    1735                 :            : 
    1736                 :            :   // check the model with the theory engine for debugging
    1737         [ +  + ]:       3096 :   if (options().smt.debugCheckModels)
    1738                 :            :   {
    1739                 :       2863 :     TheoryEngine* te = d_smtSolver->getTheoryEngine();
    1740 [ -  + ][ -  + ]:       2863 :     Assert(te != nullptr);
                 [ -  - ]
    1741                 :       2863 :     te->checkTheoryAssertionsWithModel(hardFailure);
    1742                 :            :   }
    1743                 :            : 
    1744                 :            :   // check the model with the check models utility
    1745 [ -  + ][ -  + ]:       3096 :   Assert(d_checkModels != nullptr);
                 [ -  - ]
    1746                 :       3096 :   d_checkModels->checkModel(m, al, hardFailure);
    1747                 :       3096 : }
    1748                 :            : 
    1749                 :       1991 : UnsatCore SolverEngine::getUnsatCore()
    1750                 :            : {
    1751         [ +  - ]:       1991 :   Trace("smt") << "SMT getUnsatCore()" << std::endl;
    1752                 :       1991 :   return getUnsatCoreInternal(false);
    1753                 :            : }
    1754                 :            : 
    1755                 :        458 : std::vector<Node> SolverEngine::getUnsatCoreLemmas()
    1756                 :            : {
    1757         [ +  - ]:        458 :   Trace("smt") << "SMT getUnsatCoreLemmas()" << std::endl;
    1758                 :        458 :   finishInit();
    1759         [ -  + ]:        458 :   if (!d_env->getOptions().smt.produceUnsatCores)
    1760                 :            :   {
    1761                 :          0 :     throw ModalException(
    1762                 :            :         "Cannot get lemmas used to derive unsat when produce-unsat-cores is "
    1763                 :          0 :         "off.");
    1764                 :            :   }
    1765         [ -  + ]:        458 :   if (d_state->getMode() != SmtMode::UNSAT)
    1766                 :            :   {
    1767                 :          0 :     throw RecoverableModalException(
    1768                 :            :         "Cannot get lemmas used to derive unsat unless immediately preceded by "
    1769                 :          0 :         "UNSAT response.");
    1770                 :            :   }
    1771                 :        458 :   return d_ucManager->getUnsatCoreLemmas(false);
    1772                 :            : }
    1773                 :            : 
    1774                 :         11 : void SolverEngine::getRelevantQuantTermVectors(
    1775                 :            :     std::map<Node, InstantiationList>& insts,
    1776                 :            :     std::map<Node, std::vector<Node>>& sks,
    1777                 :            :     bool getDebugInfo)
    1778                 :            : {
    1779 [ -  + ][ -  + ]:         11 :   Assert(d_state->getMode() == SmtMode::UNSAT);
                 [ -  - ]
    1780 [ -  + ][ -  + ]:         11 :   Assert(d_env->isTheoryProofProducing());
                 [ -  - ]
    1781                 :            :   // note that we don't have to connect the SAT proof to the input assertions,
    1782                 :            :   // and preprocessing proofs don't impact what instantiations are used
    1783                 :         11 :   d_ucManager->getRelevantQuantTermVectors(insts, sks, getDebugInfo);
    1784                 :         11 : }
    1785                 :            : 
    1786                 :       6590 : std::vector<std::shared_ptr<ProofNode>> SolverEngine::getProof(
    1787                 :            :     modes::ProofComponent c)
    1788                 :            : {
    1789         [ +  - ]:       6590 :   Trace("smt") << "SMT getProof()\n";
    1790                 :       6590 :   const Options& opts = d_env->getOptions();
    1791         [ -  + ]:       6590 :   if (!opts.smt.produceProofs)
    1792                 :            :   {
    1793                 :          0 :     throw ModalException("Cannot get a proof when proof option is off.");
    1794                 :            :   }
    1795         [ +  + ]:       6590 :   if (c == modes::ProofComponent::SAT
    1796         [ +  + ]:       6145 :       || c == modes::ProofComponent::THEORY_LEMMAS
    1797         [ +  + ]:       6142 :       || c == modes::ProofComponent::PREPROCESS)
    1798                 :            :   {
    1799         [ +  + ]:        451 :     if (!d_env->isSatProofProducing())
    1800                 :            :     {
    1801                 :          1 :       throw ModalException(
    1802                 :            :           "Cannot get a proof for this component when SAT solver is not proof "
    1803                 :          2 :           "producing.");
    1804                 :            :     }
    1805                 :            :   }
    1806                 :            :   // The component modes::ProofComponent::PREPROCESS returns
    1807                 :            :   // the proof of all preprocessed assertions. It does not require being in an
    1808                 :            :   // unsat state.
    1809                 :       6589 :   if (c != modes::ProofComponent::RAW_PREPROCESS
    1810 [ +  + ][ -  + ]:       6589 :       && d_state->getMode() != SmtMode::UNSAT)
                 [ -  + ]
    1811                 :            :   {
    1812                 :          0 :     throw RecoverableModalException(
    1813                 :            :         "Cannot get a proof unless immediately preceded by "
    1814                 :          0 :         "UNSAT response.");
    1815                 :            :   }
    1816                 :            :   // determine if we should get the full proof from the SAT solver
    1817                 :       6589 :   PropEngine* pe = d_smtSolver->getPropEngine();
    1818 [ -  + ][ -  + ]:       6589 :   Assert(pe != nullptr);
                 [ -  - ]
    1819                 :       6589 :   std::vector<std::shared_ptr<ProofNode>> ps;
    1820                 :       6589 :   bool connectToPreprocess = false;
    1821                 :       6589 :   bool connectMkOuterScope = false;
    1822         [ +  + ]:       6589 :   if (c == modes::ProofComponent::RAW_PREPROCESS)
    1823                 :            :   {
    1824                 :            :     // use all preprocessed assertions
    1825                 :            :     const context::CDList<Node>& assertions =
    1826                 :          3 :         d_smtSolver->getPreprocessedAssertions();
    1827                 :          3 :     connectToPreprocess = true;
    1828                 :            :     // We start with (ASSUME a) for each preprocessed assertion a. This
    1829                 :            :     // proof will be connected to the proof of preprocessing for a.
    1830                 :          3 :     ProofNodeManager* pnm = d_pfManager->getProofNodeManager();
    1831         [ +  + ]:         27 :     for (const Node& a : assertions)
    1832                 :            :     {
    1833                 :         24 :       ps.push_back(pnm->mkAssume(a));
    1834                 :            :     }
    1835                 :            :   }
    1836         [ +  + ]:       6586 :   else if (c == modes::ProofComponent::SAT)
    1837                 :            :   {
    1838                 :        444 :     ps.push_back(pe->getProof(false));
    1839                 :            :   }
    1840         [ +  + ]:       6142 :   else if (c == modes::ProofComponent::THEORY_LEMMAS
    1841         [ +  + ]:       6139 :            || c == modes::ProofComponent::PREPROCESS)
    1842                 :            :   {
    1843                 :          6 :     ps = pe->getProofLeaves(c);
    1844                 :            :     // connect to preprocess proofs for preprocess mode
    1845                 :          6 :     connectToPreprocess = (c == modes::ProofComponent::PREPROCESS);
    1846                 :            :   }
    1847         [ +  - ]:       6136 :   else if (c == modes::ProofComponent::FULL)
    1848                 :            :   {
    1849                 :       6136 :     ps.push_back(getAvailableSatProof());
    1850                 :       6136 :     connectToPreprocess = true;
    1851                 :       6136 :     connectMkOuterScope = true;
    1852                 :            :   }
    1853                 :            :   else
    1854                 :            :   {
    1855                 :          0 :     std::stringstream ss;
    1856                 :          0 :     ss << "Unknown proof component " << c << std::endl;
    1857                 :          0 :     throw RecoverableModalException(ss.str());
    1858                 :          0 :   }
    1859                 :            : 
    1860 [ -  + ][ -  + ]:       6589 :   Assert(d_pfManager);
                 [ -  - ]
    1861                 :            :   // connect proofs to preprocessing, if specified
    1862         [ +  + ]:       6589 :   if (connectToPreprocess)
    1863                 :            :   {
    1864                 :       6142 :     ProofScopeMode scopeMode = connectMkOuterScope
    1865         [ +  + ]:       6142 :                                    ? ProofScopeMode::DEFINITIONS_AND_ASSERTIONS
    1866                 :            :                                    : ProofScopeMode::NONE;
    1867         [ +  + ]:      12314 :     for (std::shared_ptr<ProofNode>& p : ps)
    1868                 :            :     {
    1869 [ -  + ][ -  + ]:       6172 :       Assert(p != nullptr);
                 [ -  - ]
    1870                 :      12344 :       p = d_pfManager->connectProofToAssertions(
    1871                 :       6172 :           p, d_smtSolver->getAssertions(), scopeMode);
    1872                 :            :     }
    1873                 :            :   }
    1874                 :       6589 :   return ps;
    1875                 :          0 : }
    1876                 :            : 
    1877                 :          0 : void SolverEngine::proofToString(std::ostream& out,
    1878                 :            :                                  std::shared_ptr<ProofNode> fp)
    1879                 :            : {
    1880                 :            :   options::ProofFormatMode format_mode =
    1881                 :          0 :       getOptions().proof.proofFormatMode;
    1882                 :          0 :   d_pfManager->printProof(
    1883                 :            :       out, fp, format_mode, ProofScopeMode::DEFINITIONS_AND_ASSERTIONS);
    1884                 :          0 : }
    1885                 :            : 
    1886                 :         79 : void SolverEngine::printInstantiations(std::ostream& out)
    1887                 :            : {
    1888                 :         79 :   QuantifiersEngine* qe = getAvailableQuantifiersEngine("printInstantiations");
    1889                 :            : 
    1890                 :            :   // First, extract and print the skolemizations
    1891                 :         79 :   bool printed = false;
    1892                 :         79 :   bool reqNames = !d_env->getOptions().quantifiers.printInstFull;
    1893                 :            : 
    1894                 :            :   // Extract the skolemizations and instantiations
    1895                 :         79 :   std::map<Node, std::vector<Node>> sks;
    1896                 :         79 :   std::map<Node, InstantiationList> rinsts;
    1897         [ +  + ]:         87 :   if ((d_env->getOptions().smt.produceProofs && d_env->isTheoryProofProducing())
    1898 [ +  + ][ +  - ]:         87 :       && getSmtMode() == SmtMode::UNSAT)
                 [ +  + ]
    1899                 :            :   {
    1900                 :            :     // minimize skolemizations and instantiations based on proof manager
    1901                 :          4 :     getRelevantQuantTermVectors(
    1902                 :          4 :         rinsts, sks, options().driver.dumpInstantiationsDebug);
    1903                 :            :   }
    1904                 :            :   else
    1905                 :            :   {
    1906                 :            :     // get all skolem term vectors
    1907                 :         75 :     qe->getSkolemTermVectors(sks);
    1908                 :            :     // get all instantiations
    1909                 :         75 :     std::map<Node, std::vector<std::vector<Node>>> insts;
    1910                 :         75 :     qe->getInstantiationTermVectors(insts);
    1911         [ +  + ]:        152 :     for (const std::pair<const Node, std::vector<std::vector<Node>>>& i : insts)
    1912                 :            :     {
    1913                 :            :       // convert to instantiation list
    1914                 :         77 :       Node q = i.first;
    1915                 :         77 :       InstantiationList& ilq = rinsts[q];
    1916                 :         77 :       ilq.initialize(q);
    1917         [ +  + ]:        166 :       for (const std::vector<Node>& ii : i.second)
    1918                 :            :       {
    1919                 :         89 :         ilq.d_inst.push_back(InstantiationVec(ii));
    1920                 :            :       }
    1921                 :         77 :     }
    1922                 :         75 :   }
    1923                 :            :   // only print when in list mode
    1924                 :         79 :   if (d_env->getOptions().quantifiers.printInstMode
    1925         [ +  + ]:         79 :       == options::PrintInstMode::LIST)
    1926                 :            :   {
    1927         [ +  + ]:         82 :     for (const std::pair<const Node, std::vector<Node>>& s : sks)
    1928                 :            :     {
    1929                 :          6 :       Node name;
    1930         [ -  + ]:          6 :       if (!qe->getNameForQuant(s.first, name, reqNames))
    1931                 :            :       {
    1932                 :            :         // did not have a name and we are only printing formulas with names
    1933                 :          0 :         continue;
    1934                 :            :       }
    1935                 :          6 :       SkolemList slist(name, s.second);
    1936                 :          6 :       out << slist;
    1937                 :          6 :       printed = true;
    1938         [ +  - ]:          6 :     }
    1939                 :            :   }
    1940         [ +  + ]:        164 :   for (std::pair<const Node, InstantiationList>& i : rinsts)
    1941                 :            :   {
    1942         [ -  + ]:         85 :     if (i.second.d_inst.empty())
    1943                 :            :     {
    1944                 :            :       // no instantiations, skip
    1945                 :          0 :       continue;
    1946                 :            :     }
    1947                 :         85 :     Node name;
    1948         [ -  + ]:         85 :     if (!qe->getNameForQuant(i.first, name, reqNames))
    1949                 :            :     {
    1950                 :            :       // did not have a name and we are only printing formulas with names
    1951                 :          0 :       continue;
    1952                 :            :     }
    1953                 :            :     // must have a name
    1954                 :         85 :     if (d_env->getOptions().quantifiers.printInstMode
    1955         [ +  + ]:         85 :         == options::PrintInstMode::NUM)
    1956                 :            :     {
    1957                 :         12 :       out << "(num-instantiations " << name << " " << i.second.d_inst.size()
    1958                 :          6 :           << ")" << std::endl;
    1959                 :            :     }
    1960                 :            :     else
    1961                 :            :     {
    1962                 :            :       // take the name
    1963                 :         79 :       i.second.d_quant = name;
    1964 [ -  + ][ -  + ]:         79 :       Assert(d_env->getOptions().quantifiers.printInstMode
                 [ -  - ]
    1965                 :            :              == options::PrintInstMode::LIST);
    1966                 :         79 :       out << i.second;
    1967                 :            :     }
    1968                 :         85 :     printed = true;
    1969         [ +  - ]:         85 :   }
    1970                 :            :   // if we did not print anything, we indicate this
    1971         [ -  + ]:         79 :   if (!printed)
    1972                 :            :   {
    1973                 :          0 :     out << "none" << std::endl;
    1974                 :            :   }
    1975                 :         79 : }
    1976                 :            : 
    1977                 :          0 : void SolverEngine::getInstantiationTermVectors(
    1978                 :            :     std::map<Node, std::vector<std::vector<Node>>>& insts)
    1979                 :            : {
    1980                 :            :   QuantifiersEngine* qe =
    1981                 :          0 :       getAvailableQuantifiersEngine("getInstantiationTermVectors");
    1982                 :            :   // get the list of all instantiations
    1983                 :          0 :   qe->getInstantiationTermVectors(insts);
    1984                 :          0 : }
    1985                 :            : 
    1986                 :        712 : bool SolverEngine::getSynthSolutions(std::map<Node, Node>& solMap)
    1987                 :            : {
    1988         [ -  + ]:        712 :   if (d_sygusSolver == nullptr)
    1989                 :            :   {
    1990                 :          0 :     throw RecoverableModalException(
    1991                 :          0 :         "Cannot get synth solutions in this context.");
    1992                 :            :   }
    1993                 :        712 :   bool ret = d_sygusSolver->getSynthSolutions(solMap);
    1994                 :            :   // we return false if solMap is empty, that is, when we ask for a solution
    1995                 :            :   // when none is available.
    1996 [ +  + ][ +  + ]:        712 :   return ret && !solMap.empty();
    1997                 :            : }
    1998                 :            : 
    1999                 :       1320 : bool SolverEngine::getSubsolverSynthSolutions(std::map<Node, Node>& solMap)
    2000                 :            : {
    2001         [ -  + ]:       1320 :   if (d_sygusSolver == nullptr)
    2002                 :            :   {
    2003                 :          0 :     throw RecoverableModalException(
    2004                 :          0 :         "Cannot get subsolver synth solutions in this context.");
    2005                 :            :   }
    2006                 :       1320 :   bool ret = d_sygusSolver->getSubsolverSynthSolutions(solMap);
    2007                 :            :   // we return false if solMap is empty, that is, when we ask for a solution
    2008                 :            :   // when none is available.
    2009 [ +  + ][ +  + ]:       1320 :   return ret && !solMap.empty();
    2010                 :            : }
    2011                 :            : 
    2012                 :        415 : Node SolverEngine::getQuantifierElimination(Node q, bool doFull)
    2013                 :            : {
    2014                 :        415 :   beginCall(true);
    2015                 :            :   Node result = d_quantElimSolver->getQuantifierElimination(
    2016                 :        419 :       q, doFull, d_isInternalSubsolver);
    2017                 :        411 :   endCall();
    2018                 :        411 :   return result;
    2019                 :          0 : }
    2020                 :            : 
    2021                 :        420 : Node SolverEngine::getInterpolant(const Node& conj, const TypeNode& grammarType)
    2022                 :            : {
    2023                 :        420 :   beginCall(true);
    2024                 :            :   // Analogous to getAbduct, ensure that assertions are current.
    2025                 :        419 :   d_smtDriver->refreshAssertions();
    2026                 :        419 :   std::vector<Node> axioms = getAssertions();
    2027                 :        419 :   Node interpol;
    2028                 :            :   bool success =
    2029                 :        419 :       d_interpolSolver->getInterpolant(axioms, conj, grammarType, interpol);
    2030                 :            :   // notify the state of whether the get-interpolant call was successfuly, which
    2031                 :            :   // impacts the SMT mode.
    2032                 :        419 :   d_state->notifyGetInterpol(success);
    2033                 :        419 :   endCall();
    2034 [ -  + ][ -  + ]:        419 :   Assert(success == !interpol.isNull());
                 [ -  - ]
    2035                 :        838 :   return interpol;
    2036                 :        419 : }
    2037                 :            : 
    2038                 :         94 : Node SolverEngine::getInterpolantNext()
    2039                 :            : {
    2040                 :         94 :   beginCall(true);
    2041         [ -  + ]:         94 :   if (d_state->getMode() != SmtMode::INTERPOL)
    2042                 :            :   {
    2043                 :          0 :     throw RecoverableModalException(
    2044                 :            :         "Cannot get-interpolant-next unless immediately preceded by a "
    2045                 :            :         "successful "
    2046                 :          0 :         "call to get-interpolant(-next).");
    2047                 :            :   }
    2048                 :         94 :   Node interpol;
    2049                 :         94 :   bool success = d_interpolSolver->getInterpolantNext(interpol);
    2050                 :            :   // notify the state of whether the get-interpolantant-next call was successful
    2051                 :         94 :   d_state->notifyGetInterpol(success);
    2052                 :         94 :   endCall();
    2053 [ -  + ][ -  + ]:         94 :   Assert(success == !interpol.isNull());
                 [ -  - ]
    2054                 :         94 :   return interpol;
    2055                 :          0 : }
    2056                 :            : 
    2057                 :        417 : Node SolverEngine::getAbduct(const Node& conj, const TypeNode& grammarType)
    2058                 :            : {
    2059                 :        417 :   beginCall(true);
    2060                 :            :   // ensure that assertions are current
    2061                 :        416 :   d_smtDriver->refreshAssertions();
    2062                 :        416 :   std::vector<Node> axioms = getAssertions();
    2063                 :            :   // expand definitions in the conjecture as well
    2064                 :        416 :   Node abd;
    2065                 :        416 :   bool success = d_abductSolver->getAbduct(axioms, conj, grammarType, abd);
    2066                 :            :   // notify the state of whether the get-abduct call was successful, which
    2067                 :            :   // impacts the SMT mode.
    2068                 :        412 :   d_state->notifyGetAbduct(success);
    2069                 :        412 :   endCall();
    2070 [ -  + ][ -  + ]:        412 :   Assert(success == !abd.isNull());
                 [ -  - ]
    2071                 :        824 :   return abd;
    2072                 :        420 : }
    2073                 :            : 
    2074                 :         92 : Node SolverEngine::getAbductNext()
    2075                 :            : {
    2076                 :         92 :   beginCall(true);
    2077         [ -  + ]:         92 :   if (d_state->getMode() != SmtMode::ABDUCT)
    2078                 :            :   {
    2079                 :          0 :     throw RecoverableModalException(
    2080                 :            :         "Cannot get-abduct-next unless immediately preceded by a successful "
    2081                 :          0 :         "call to get-abduct(-next).");
    2082                 :            :   }
    2083                 :         92 :   Node abd;
    2084                 :         92 :   bool success = d_abductSolver->getAbductNext(abd);
    2085                 :            :   // notify the state of whether the get-abduct-next call was successful
    2086                 :         92 :   d_state->notifyGetAbduct(success);
    2087                 :         92 :   endCall();
    2088 [ -  + ][ -  + ]:         92 :   Assert(success == !abd.isNull());
                 [ -  - ]
    2089                 :         92 :   return abd;
    2090                 :          0 : }
    2091                 :            : 
    2092                 :         68 : void SolverEngine::getInstantiatedQuantifiedFormulas(std::vector<Node>& qs)
    2093                 :            : {
    2094                 :            :   QuantifiersEngine* qe =
    2095                 :         68 :       getAvailableQuantifiersEngine("getInstantiatedQuantifiedFormulas");
    2096                 :         68 :   qe->getInstantiatedQuantifiedFormulas(qs);
    2097                 :         68 : }
    2098                 :            : 
    2099                 :         68 : void SolverEngine::getInstantiationTermVectors(
    2100                 :            :     Node q, std::vector<std::vector<Node>>& tvecs)
    2101                 :            : {
    2102                 :            :   QuantifiersEngine* qe =
    2103                 :         68 :       getAvailableQuantifiersEngine("getInstantiationTermVectors");
    2104                 :         68 :   qe->getInstantiationTermVectors(q, tvecs);
    2105                 :         68 : }
    2106                 :            : 
    2107                 :       1419 : std::vector<Node> SolverEngine::getAssertions()
    2108                 :            : {
    2109                 :            :   // ensure this solver engine has been initialized
    2110                 :       1419 :   finishInit();
    2111         [ +  - ]:       1419 :   Trace("smt") << "SMT getAssertions()" << endl;
    2112                 :            :   // note we always enable assertions, so it is available here
    2113                 :       1419 :   return getAssertionsInternal();
    2114                 :            : }
    2115                 :            : 
    2116                 :        456 : void SolverEngine::getDifficultyMap(std::map<Node, Node>& dmap)
    2117                 :            : {
    2118         [ +  - ]:        456 :   Trace("smt") << "SMT getDifficultyMap()\n";
    2119                 :            :   // ensure this solver engine has been initialized
    2120                 :        456 :   finishInit();
    2121         [ +  + ]:        456 :   if (!d_env->getOptions().smt.produceDifficulty)
    2122                 :            :   {
    2123                 :          2 :     throw ModalException(
    2124                 :          4 :         "Cannot get difficulty when difficulty option is off.");
    2125                 :            :   }
    2126                 :            :   // the prop engine has the proof of false
    2127 [ -  + ][ -  + ]:        454 :   Assert(d_pfManager);
                 [ -  - ]
    2128                 :            :   // get difficulty map from theory engine first
    2129                 :        454 :   TheoryEngine* te = d_smtSolver->getTheoryEngine();
    2130                 :            :   // do not include lemmas
    2131                 :        454 :   te->getDifficultyMap(dmap, false);
    2132                 :            :   // then ask proof manager to translate dmap in terms of the input
    2133                 :        454 :   d_pfManager->translateDifficultyMap(dmap, d_smtSolver->getAssertions());
    2134                 :        454 : }
    2135                 :            : 
    2136                 :       5079 : void SolverEngine::push()
    2137                 :            : {
    2138                 :       5079 :   beginCall();
    2139         [ +  - ]:       5079 :   Trace("smt") << "SMT push()" << endl;
    2140                 :       5079 :   d_smtDriver->refreshAssertions();
    2141                 :       5079 :   d_ctxManager->userPush();
    2142                 :       5079 : }
    2143                 :            : 
    2144                 :       3750 : void SolverEngine::pop()
    2145                 :            : {
    2146                 :       3750 :   beginCall();
    2147         [ +  - ]:       3750 :   Trace("smt") << "SMT pop()" << endl;
    2148                 :       3750 :   d_ctxManager->userPop();
    2149                 :            : 
    2150                 :            :   // clear the learned literals from the preprocessor
    2151                 :       3750 :   d_smtSolver->getPreprocessor()->clearLearnedLiterals();
    2152                 :            : 
    2153         [ +  - ]:       7500 :   Trace("userpushpop") << "SolverEngine: popped to level "
    2154                 :       3750 :                        << d_env->getUserContext()->getLevel() << endl;
    2155                 :            :   // should we reset d_status here?
    2156                 :            :   // SMT-LIBv2 spec seems to imply no, but it would make sense to..
    2157                 :       3750 : }
    2158                 :            : 
    2159                 :        691 : void SolverEngine::resetAssertions()
    2160                 :            : {
    2161         [ +  + ]:        691 :   if (!d_state->isFullyInited())
    2162                 :            :   {
    2163                 :            :     // We're still in Start Mode, nothing asserted yet, do nothing.
    2164                 :            :     // (see solver execution modes in the SMT-LIB standard)
    2165 [ -  + ][ -  + ]:          4 :     Assert(d_env->getContext()->getLevel() == 0);
                 [ -  - ]
    2166 [ -  + ][ -  + ]:          4 :     Assert(d_env->getUserContext()->getLevel() == 0);
                 [ -  - ]
    2167                 :          4 :     return;
    2168                 :            :   }
    2169                 :            : 
    2170         [ +  - ]:        687 :   Trace("smt") << "SMT resetAssertions()" << endl;
    2171                 :            : 
    2172                 :        687 :   d_ctxManager->notifyResetAssertions();
    2173                 :            : 
    2174                 :            :   // reset SmtSolver, which will construct a new prop engine
    2175                 :        687 :   d_smtSolver->resetAssertions();
    2176                 :            : }
    2177                 :            : 
    2178                 :     155868 : void SolverEngine::interrupt()
    2179                 :            : {
    2180         [ -  + ]:     155868 :   if (!d_state->isFullyInited())
    2181                 :            :   {
    2182                 :          0 :     return;
    2183                 :            :   }
    2184                 :     155868 :   d_smtSolver->interrupt();
    2185                 :            : }
    2186                 :            : 
    2187                 :          0 : void SolverEngine::setResourceLimit(uint64_t units, bool cumulative)
    2188                 :            : {
    2189         [ -  - ]:          0 :   if (cumulative)
    2190                 :            :   {
    2191                 :          0 :     d_env->d_options.write_base().cumulativeResourceLimit = units;
    2192                 :            :   }
    2193                 :            :   else
    2194                 :            :   {
    2195                 :          0 :     d_env->d_options.write_base().perCallResourceLimit = units;
    2196                 :            :   }
    2197                 :          0 : }
    2198                 :       2651 : void SolverEngine::setTimeLimit(uint64_t millis)
    2199                 :            : {
    2200                 :       2651 :   d_env->d_options.write_base().perCallMillisecondLimit = millis;
    2201                 :       2651 : }
    2202                 :            : 
    2203                 :          0 : unsigned long SolverEngine::getResourceUsage() const
    2204                 :            : {
    2205                 :          0 :   return getResourceManager()->getResourceUsage();
    2206                 :            : }
    2207                 :            : 
    2208                 :          0 : unsigned long SolverEngine::getTimeUsage() const
    2209                 :            : {
    2210                 :          0 :   return getResourceManager()->getTimeUsage();
    2211                 :            : }
    2212                 :            : 
    2213                 :          0 : unsigned long SolverEngine::getResourceRemaining() const
    2214                 :            : {
    2215                 :          0 :   return getResourceManager()->getResourceRemaining();
    2216                 :            : }
    2217                 :            : 
    2218                 :         13 : void SolverEngine::printStatisticsSafe(int fd) const
    2219                 :            : {
    2220                 :         13 :   d_env->getStatisticsRegistry().printSafe(fd);
    2221                 :         13 : }
    2222                 :            : 
    2223                 :          0 : void SolverEngine::printStatisticsDiff() const
    2224                 :            : {
    2225                 :          0 :   d_env->getStatisticsRegistry().printDiff(*d_env->getOptions().base.err);
    2226                 :          0 :   d_env->getStatisticsRegistry().storeSnapshot();
    2227                 :          0 : }
    2228                 :            : 
    2229                 :     256436 : void SolverEngine::setOption(const std::string& key,
    2230                 :            :                              const std::string& value,
    2231                 :            :                              bool fromUser)
    2232                 :            : {
    2233 [ +  + ][ +  + ]:     256436 :   if (fromUser && options().base.safeMode != options::SafeMode::UNRESTRICTED)
                 [ +  + ]
    2234                 :            :   {
    2235                 :            :     // Note that the text "in safe mode" must appear in the error messages or
    2236                 :            :     // CI will fail, as it searches for this text.
    2237         [ -  + ]:         74 :     if (key == "trace")
    2238                 :            :     {
    2239                 :          0 :       throw FatalOptionException("cannot use trace messages in safe mode");
    2240                 :            :     }
    2241                 :            :     // verify its a regular option
    2242                 :         74 :     options::OptionInfo oinfo = options::getInfo(getOptions(), key);
    2243         [ +  + ]:         74 :     if (oinfo.category == options::OptionInfo::Category::EXPERT)
    2244                 :            :     {
    2245                 :            :       // option exception
    2246                 :          4 :       std::stringstream ss;
    2247                 :            :       ss << "expert option " << key
    2248                 :          4 :          << " cannot be set in safe mode.";
    2249                 :            :       // If we are setting to a default value, the exception can be avoided
    2250                 :            :       // by omitting the expert option.
    2251         [ +  + ]:          4 :       if (getOption(key) == value)
    2252                 :            :       {
    2253                 :            :         // note this is not the case for options which safe mode explicitly
    2254                 :            :         // disables.
    2255                 :            :         ss << " The value for " << key << " is already its current value ("
    2256                 :          1 :            << value << "). Omitting this option may avoid this exception.";
    2257                 :            :       }
    2258                 :          4 :       throw FatalOptionException(ss.str());
    2259                 :          4 :     }
    2260         [ +  + ]:         70 :     else if (oinfo.category == options::OptionInfo::Category::REGULAR)
    2261                 :            :     {
    2262 [ +  - ][ -  + ]:          2 :       if (options().base.safeMode == options::SafeMode::SAFE && !oinfo.noSupports.empty())
                 [ -  + ]
    2263                 :            :       {
    2264                 :          0 :         std::stringstream ss;
    2265                 :            :         ss << "cannot set option " << key
    2266                 :          0 :            << " in safe mode, as this option does not support ";
    2267                 :          0 :         bool firstTime = true;
    2268         [ -  - ]:          0 :         for (const std::string& s : oinfo.noSupports)
    2269                 :            :         {
    2270         [ -  - ]:          0 :           if (!firstTime)
    2271                 :            :           {
    2272                 :          0 :             ss << ", ";
    2273                 :            :           }
    2274                 :            :           else
    2275                 :            :           {
    2276                 :          0 :             firstTime = false;
    2277                 :            :           }
    2278                 :          0 :           ss << s;
    2279                 :            :         }
    2280                 :          0 :         throw FatalOptionException(ss.str());
    2281                 :          0 :       }
    2282         [ +  - ]:          2 :       if (!d_safeOptsSetRegularOption)
    2283                 :            :       {
    2284                 :          2 :         d_safeOptsSetRegularOption = true;
    2285                 :          2 :         d_safeOptsRegularOption = key;
    2286                 :          2 :         d_safeOptsRegularOptionValue = value;
    2287                 :          2 :         d_safeOptsSetRegularOptionToDefault = (getOption(key) == value);
    2288                 :            :       }
    2289                 :            :       else
    2290                 :            :       {
    2291                 :            :         // option exception
    2292                 :          0 :         std::stringstream ss;
    2293                 :          0 :         ss << "cannot set two regular options (" << d_safeOptsRegularOption
    2294                 :          0 :            << " and " << key << ") in safe mode.";
    2295                 :            :         // similar to above, if setting to default value for either of the
    2296                 :            :         // regular options.
    2297         [ -  - ]:          0 :         for (size_t i = 0; i < 2; i++)
    2298                 :            :         {
    2299         [ -  - ]:          0 :           const std::string& rkey = i == 0 ? d_safeOptsRegularOption : key;
    2300         [ -  - ]:          0 :           const std::string& rvalue = i == 0 ? d_safeOptsRegularOptionValue : value;
    2301         [ -  - ]:          0 :           bool isDefault = i == 0 ? d_safeOptsSetRegularOptionToDefault
    2302                 :          0 :                                   : (getOption(key) == value);
    2303         [ -  - ]:          0 :           if (isDefault)
    2304                 :            :           {
    2305                 :            :             // note this is not the case for options which safe mode
    2306                 :            :             // explicitly disables.
    2307                 :            :             ss << " The value for " << rkey << " is already its current value ("
    2308                 :          0 :                << rvalue << "). Omitting this option may avoid this exception.";
    2309                 :            :           }
    2310                 :            :         }
    2311                 :          0 :         throw FatalOptionException(ss.str());
    2312                 :          0 :       }
    2313                 :            :     }
    2314                 :         74 :   }
    2315         [ +  - ]:     256432 :   Trace("smt") << "SMT setOption(" << key << ", " << value << ")" << endl;
    2316                 :     256432 :   options::set(getOptions(), key, value);
    2317                 :     245340 : }
    2318                 :            : 
    2319                 :      15352 : void SolverEngine::setIsInternalSubsolver() { d_isInternalSubsolver = true; }
    2320                 :            : 
    2321                 :          0 : bool SolverEngine::isInternalSubsolver() const { return d_isInternalSubsolver; }
    2322                 :            : 
    2323                 :    1263154 : std::string SolverEngine::getOption(const std::string& key) const
    2324                 :            : {
    2325         [ +  - ]:    1263154 :   Trace("smt") << "SMT getOption(" << key << ")" << endl;
    2326                 :    1263154 :   return options::get(getOptions(), key);
    2327                 :            : }
    2328                 :            : 
    2329                 :    2027605 : Options& SolverEngine::getOptions() { return d_env->d_options; }
    2330                 :            : 
    2331                 :    1263154 : const Options& SolverEngine::getOptions() const { return d_env->getOptions(); }
    2332                 :            : 
    2333                 :     247292 : ResourceManager* SolverEngine::getResourceManager() const
    2334                 :            : {
    2335                 :     247292 :   return d_env->getResourceManager();
    2336                 :            : }
    2337                 :            : 
    2338                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14