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: 940 1116 84.2 %
Date: 2026-02-15 11:43:36 Functions: 104 116 89.7 %
Branches: 434 710 61.1 %

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

Generated by: LCOV version 1.14