LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/theory - theory_engine.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 885 1057 83.7 %
Date: 2026-03-03 11:42:59 Functions: 57 61 93.4 %
Branches: 725 1200 60.4 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * This file is part of the cvc5 project.
       3                 :            :  *
       4                 :            :  * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS
       5                 :            :  * in the top-level source directory and their institutional affiliations.
       6                 :            :  * All rights reserved.  See the file COPYING in the top-level source
       7                 :            :  * directory for licensing information.
       8                 :            :  * ****************************************************************************
       9                 :            :  *
      10                 :            :  * The theory engine.
      11                 :            :  */
      12                 :            : 
      13                 :            : #include "theory/theory_engine.h"
      14                 :            : 
      15                 :            : #include <sstream>
      16                 :            : 
      17                 :            : #include "base/map_util.h"
      18                 :            : #include "decision/decision_engine.h"
      19                 :            : #include "expr/attribute.h"
      20                 :            : #include "expr/node_builder.h"
      21                 :            : #include "expr/node_visitor.h"
      22                 :            : #include "options/parallel_options.h"
      23                 :            : #include "options/quantifiers_options.h"
      24                 :            : #include "options/smt_options.h"
      25                 :            : #include "options/theory_options.h"
      26                 :            : #include "printer/printer.h"
      27                 :            : #include "proof/lazy_proof.h"
      28                 :            : #include "proof/proof_checker.h"
      29                 :            : #include "proof/proof_ensure_closed.h"
      30                 :            : #include "prop/prop_engine.h"
      31                 :            : #include "smt/env.h"
      32                 :            : #include "smt/logic_exception.h"
      33                 :            : #include "smt/solver_engine_state.h"
      34                 :            : #include "theory/combination_care_graph.h"
      35                 :            : #include "theory/conflict_processor.h"
      36                 :            : #include "theory/decision_manager.h"
      37                 :            : #include "theory/ee_manager_central.h"
      38                 :            : #include "theory/partition_generator.h"
      39                 :            : #include "theory/plugin_module.h"
      40                 :            : #include "theory/quantifiers/first_order_model.h"
      41                 :            : #include "theory/quantifiers_engine.h"
      42                 :            : #include "theory/relevance_manager.h"
      43                 :            : #include "theory/rewriter.h"
      44                 :            : #include "theory/shared_solver.h"
      45                 :            : #include "theory/theory.h"
      46                 :            : #include "theory/theory_engine_proof_generator.h"
      47                 :            : #include "theory/theory_id.h"
      48                 :            : #include "theory/theory_model.h"
      49                 :            : #include "theory/theory_traits.h"
      50                 :            : #include "theory/uf/equality_engine.h"
      51                 :            : #include "util/resource_manager.h"
      52                 :            : 
      53                 :            : using namespace std;
      54                 :            : 
      55                 :            : using namespace cvc5::internal::theory;
      56                 :            : 
      57                 :            : namespace cvc5::internal {
      58                 :            : 
      59                 :            : /* -------------------------------------------------------------------------- */
      60                 :            : 
      61                 :            : namespace theory {
      62                 :            : 
      63                 :            : /**
      64                 :            :  * IMPORTANT: The order of the theories is important. For example, strings
      65                 :            :  *            depends on arith, quantifiers needs to come as the very last.
      66                 :            :  *            Do not change this order.
      67                 :            :  */
      68                 :            : 
      69                 :            : #define CVC5_FOR_EACH_THEORY                                     \
      70                 :            :   CVC5_FOR_EACH_THEORY_STATEMENT(cvc5::internal::theory::THEORY_BUILTIN)   \
      71                 :            :   CVC5_FOR_EACH_THEORY_STATEMENT(cvc5::internal::theory::THEORY_BOOL)      \
      72                 :            :   CVC5_FOR_EACH_THEORY_STATEMENT(cvc5::internal::theory::THEORY_UF)        \
      73                 :            :   CVC5_FOR_EACH_THEORY_STATEMENT(cvc5::internal::theory::THEORY_ARITH)     \
      74                 :            :   CVC5_FOR_EACH_THEORY_STATEMENT(cvc5::internal::theory::THEORY_BV)        \
      75                 :            :   CVC5_FOR_EACH_THEORY_STATEMENT(cvc5::internal::theory::THEORY_FF)        \
      76                 :            :   CVC5_FOR_EACH_THEORY_STATEMENT(cvc5::internal::theory::THEORY_FP)        \
      77                 :            :   CVC5_FOR_EACH_THEORY_STATEMENT(cvc5::internal::theory::THEORY_ARRAYS)    \
      78                 :            :   CVC5_FOR_EACH_THEORY_STATEMENT(cvc5::internal::theory::THEORY_DATATYPES) \
      79                 :            :   CVC5_FOR_EACH_THEORY_STATEMENT(cvc5::internal::theory::THEORY_SEP)       \
      80                 :            :   CVC5_FOR_EACH_THEORY_STATEMENT(cvc5::internal::theory::THEORY_SETS)      \
      81                 :            :   CVC5_FOR_EACH_THEORY_STATEMENT(cvc5::internal::theory::THEORY_BAGS)      \
      82                 :            :   CVC5_FOR_EACH_THEORY_STATEMENT(cvc5::internal::theory::THEORY_STRINGS)   \
      83                 :            :   CVC5_FOR_EACH_THEORY_STATEMENT(cvc5::internal::theory::THEORY_QUANTIFIERS)
      84                 :            : 
      85                 :            : }  // namespace theory
      86                 :            : 
      87                 :            : /* -------------------------------------------------------------------------- */
      88                 :            : 
      89                 :            : /**
      90                 :            :  * Compute the string for a given theory id. In this module, we use
      91                 :            :  * THEORY_SAT_SOLVER as an id, which is not a normal id but maps to
      92                 :            :  * THEORY_LAST. Thus, we need our own string conversion here.
      93                 :            :  *
      94                 :            :  * @param id The theory id
      95                 :            :  * @return The string corresponding to the theory id
      96                 :            :  */
      97                 :          0 : std::string getTheoryString(theory::TheoryId id)
      98                 :            : {
      99         [ -  - ]:          0 :   if (id == theory::THEORY_SAT_SOLVER)
     100                 :            :   {
     101                 :          0 :     return "THEORY_SAT_SOLVER";
     102                 :            :   }
     103                 :            :   else
     104                 :            :   {
     105                 :          0 :     std::stringstream ss;
     106                 :          0 :     ss << id;
     107                 :          0 :     return ss.str();
     108                 :          0 :   }
     109                 :            : }
     110                 :            : 
     111                 :      49957 : void TheoryEngine::finishInit()
     112                 :            : {
     113                 :      49957 :   d_modules.clear();
     114         [ +  - ]:      49957 :   Trace("theory") << "Begin TheoryEngine::finishInit" << std::endl;
     115                 :            :   // NOTE: This seems to be required since
     116                 :            :   // theory::TheoryTraits<THEORY>::isParametric cannot be accessed without
     117                 :            :   // using the CVC5_FOR_EACH_THEORY_STATEMENT macro. -AJR
     118                 :      49957 :   std::vector<theory::Theory*> paraTheories;
     119                 :            : #ifdef CVC5_FOR_EACH_THEORY_STATEMENT
     120                 :            : #undef CVC5_FOR_EACH_THEORY_STATEMENT
     121                 :            : #endif
     122                 :            : #define CVC5_FOR_EACH_THEORY_STATEMENT(THEORY)   \
     123                 :            :   if (theory::TheoryTraits<THEORY>::isParametric \
     124                 :            :       && isTheoryEnabled(THEORY))    \
     125                 :            :   {                                              \
     126                 :            :     paraTheories.push_back(theoryOf(THEORY));    \
     127                 :            :   }
     128                 :            :   // Collect the parametric theories, which are given to the theory combination
     129                 :            :   // manager below
     130 [ +  + ][ +  + ]:      49957 :   CVC5_FOR_EACH_THEORY;
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
     131                 :            : 
     132                 :            :   // Initialize the theory combination architecture
     133         [ +  - ]:      49957 :   if (options().theory.tcMode == options::TcMode::CARE_GRAPH)
     134                 :            :   {
     135                 :      49957 :     d_tc.reset(new CombinationCareGraph(d_env, *this, paraTheories));
     136                 :            :   }
     137                 :            :   else
     138                 :            :   {
     139                 :          0 :     Unimplemented() << "TheoryEngine::finishInit: theory combination mode "
     140                 :          0 :                     << options().theory.tcMode << " not supported";
     141                 :            :   }
     142                 :            :   // create the relevance filter if any option requires it
     143 [ +  + ][ +  + ]:      49957 :   if (options().theory.relevanceFilter || options().smt.produceDifficulty)
                 [ +  + ]
     144                 :            :   {
     145                 :        486 :     d_relManager.reset(new RelevanceManager(d_env, this));
     146                 :        486 :     d_modules.push_back(d_relManager.get());
     147                 :            :   }
     148                 :            : 
     149                 :            :   // initialize the quantifiers engine
     150         [ +  + ]:      49957 :   if (logicInfo().isQuantified())
     151                 :            :   {
     152                 :            :     // get the quantifiers engine, which is initialized by the quantifiers
     153                 :            :     // theory
     154                 :      43219 :     d_quantEngine = d_theoryTable[THEORY_QUANTIFIERS]->getQuantifiersEngine();
     155 [ -  + ][ -  + ]:      43219 :     Assert(d_quantEngine != nullptr);
                 [ -  - ]
     156                 :            :   }
     157                 :            :   // finish initializing the quantifiers engine, which must come before
     158                 :            :   // initializing theory combination, since quantifiers engine may have a
     159                 :            :   // special model builder object
     160         [ +  + ]:      49957 :   if (logicInfo().isQuantified())
     161                 :            :   {
     162                 :      43219 :     d_quantEngine->finishInit(this);
     163                 :            :   }
     164                 :            :   // initialize the theory combination manager, which decides and allocates the
     165                 :            :   // equality engines to use for all theories.
     166                 :      49957 :   d_tc->finishInit();
     167                 :            :   // get pointer to the shared solver
     168                 :      49957 :   d_sharedSolver = d_tc->getSharedSolver();
     169                 :            : 
     170                 :            :   // finish initializing the theories by linking them with the appropriate
     171                 :            :   // utilities and then calling their finishInit method.
     172         [ +  + ]:     749355 :   for(TheoryId theoryId = theory::THEORY_FIRST; theoryId != theory::THEORY_LAST; ++ theoryId) {
     173                 :     699398 :     Theory* t = d_theoryTable[theoryId];
     174         [ -  + ]:     699398 :     if (t == nullptr)
     175                 :            :     {
     176                 :          0 :       continue;
     177                 :            :     }
     178                 :            :     // setup the pointers to the utilities
     179                 :     699398 :     const EeTheoryInfo* eeti = d_tc->getEeTheoryInfo(theoryId);
     180 [ -  + ][ -  + ]:     699398 :     Assert(eeti != nullptr);
                 [ -  - ]
     181                 :            :     // the theory's official equality engine is the one specified by the
     182                 :            :     // equality engine manager
     183                 :     699398 :     t->setEqualityEngine(eeti->d_usedEe);
     184                 :            :     // set the quantifiers engine
     185                 :     699398 :     t->setQuantifiersEngine(d_quantEngine);
     186                 :            :     // set the decision manager for the theory
     187                 :     699398 :     t->setDecisionManager(d_decManager.get());
     188                 :            :     // finish initializing the theory
     189                 :     699398 :     t->finishInit();
     190                 :            :   }
     191                 :            : 
     192         [ -  + ]:      49957 :   if (options().parallel.computePartitions > 1)
     193                 :            :   {
     194                 :            :     d_partitionGen =
     195                 :          0 :         std::make_unique<PartitionGenerator>(d_env, this, getPropEngine());
     196                 :          0 :     d_modules.push_back(d_partitionGen.get());
     197                 :            :   }
     198                 :            : 
     199                 :            :   // add user-provided plugins
     200                 :      49957 :   const std::vector<Plugin*> plugins = d_env.getPlugins();
     201         [ +  - ]:      99914 :   Trace("theory") << "initialize with " << plugins.size()
     202                 :      49957 :                   << " user-provided plugins" << std::endl;
     203         [ +  + ]:      49985 :   for (Plugin* p : plugins)
     204                 :            :   {
     205                 :         28 :     d_userPlugins.push_back(
     206                 :         56 :         std::unique_ptr<PluginModule>(new PluginModule(d_env, this, p)));
     207                 :         28 :     d_modules.push_back(d_userPlugins.back().get());
     208                 :            :   }
     209         [ +  - ]:      49957 :   Trace("theory") << "End TheoryEngine::finishInit" << std::endl;
     210                 :      49957 : }
     211                 :            : 
     212                 :      49957 : TheoryEngine::TheoryEngine(Env& env)
     213                 :            :     : EnvObj(env),
     214                 :      49957 :       d_propEngine(nullptr),
     215                 :      60120 :       d_lazyProof(
     216         [ +  + ]:      49957 :           env.isTheoryProofProducing()
     217                 :            :               ? new LazyCDProof(
     218                 :      20326 :                     env, nullptr, userContext(), "TheoryEngine::LazyCDProof")
     219                 :            :               : nullptr),
     220                 :      49957 :       d_tepg(new TheoryEngineProofGenerator(env, userContext())),
     221                 :      49957 :       d_tc(nullptr),
     222                 :      49957 :       d_sharedSolver(nullptr),
     223                 :      49957 :       d_quantEngine(nullptr),
     224                 :      49957 :       d_decManager(new DecisionManager(userContext())),
     225                 :      49957 :       d_relManager(nullptr),
     226                 :      49957 :       d_inConflict(context(), false),
     227                 :      49957 :       d_modelUnsound(context(), false),
     228                 :      49957 :       d_modelUnsoundTheory(context(), THEORY_BUILTIN),
     229                 :      49957 :       d_modelUnsoundId(context(), IncompleteId::UNKNOWN),
     230                 :      49957 :       d_refutationUnsound(userContext(), false),
     231                 :      49957 :       d_refutationUnsoundTheory(userContext(), THEORY_BUILTIN),
     232                 :      49957 :       d_refutationUnsoundId(userContext(), IncompleteId::UNKNOWN),
     233                 :      49957 :       d_propagationMap(context()),
     234                 :      49957 :       d_propagationMapTimestamp(context(), 0),
     235                 :      49957 :       d_propagatedLiterals(context()),
     236                 :      49957 :       d_propagatedLiteralsIndex(context(), 0),
     237                 :      49957 :       d_atomRequests(context()),
     238                 :      49957 :       d_stats(statisticsRegistry()),
     239                 :      49957 :       d_true(),
     240                 :      49957 :       d_false(),
     241                 :      49957 :       d_interrupted(false),
     242                 :      49957 :       d_inPreregister(false),
     243                 :      49957 :       d_factsAsserted(context(), false),
     244                 :     199828 :       d_cp(nullptr)
     245                 :            : {
     246         [ +  + ]:     749355 :   for(TheoryId theoryId = theory::THEORY_FIRST; theoryId != theory::THEORY_LAST;
     247                 :     699398 :       ++ theoryId)
     248                 :            :   {
     249                 :     699398 :     d_theoryTable[theoryId] = NULL;
     250                 :     699398 :     d_theoryOut[theoryId] = NULL;
     251                 :            :   }
     252                 :            : 
     253         [ +  + ]:      49957 :   if (options().smt.sortInference)
     254                 :            :   {
     255                 :         33 :     d_sortInfer.reset(new SortInference(env));
     256                 :            :   }
     257                 :      49957 :   if (options().theory.conflictProcessMode
     258         [ +  + ]:      49957 :       != options::ConflictProcessMode::NONE)
     259                 :            :   {
     260                 :          7 :     bool useExtRewriter = (options().theory.conflictProcessMode
     261                 :          7 :                            == options::ConflictProcessMode::MINIMIZE_EXT);
     262                 :          7 :     d_cp.reset(new ConflictProcessor(env, useExtRewriter));
     263                 :            :   }
     264                 :            : 
     265                 :      49957 :   d_true = nodeManager()->mkConst<bool>(true);
     266                 :      49957 :   d_false = nodeManager()->mkConst<bool>(false);
     267                 :      49957 : }
     268                 :            : 
     269                 :      99224 : TheoryEngine::~TheoryEngine() {
     270                 :            : 
     271         [ +  + ]:     744180 :   for(TheoryId theoryId = theory::THEORY_FIRST; theoryId != theory::THEORY_LAST; ++ theoryId) {
     272         [ +  + ]:     694568 :     if(d_theoryTable[theoryId] != NULL) {
     273         [ +  - ]:     694541 :       delete d_theoryTable[theoryId];
     274         [ +  - ]:     694541 :       delete d_theoryOut[theoryId];
     275                 :            :     }
     276                 :            :   }
     277                 :      99224 : }
     278                 :            : 
     279                 :     123745 : void TheoryEngine::interrupt() { d_interrupted = true; }
     280                 :    2153388 : void TheoryEngine::preRegister(TNode preprocessed) {
     281         [ +  - ]:    4306776 :   Trace("theory") << "TheoryEngine::preRegister( " << preprocessed << ")"
     282                 :    2153388 :                   << std::endl;
     283                 :    2153388 :   d_preregisterQueue.push(preprocessed);
     284                 :            : 
     285         [ +  + ]:    2153388 :   if (!d_inPreregister) {
     286                 :            :     // We're in pre-register
     287                 :    2005068 :     d_inPreregister = true;
     288                 :            : 
     289                 :            :     // Process the pre-registration queue
     290         [ +  + ]:    4158440 :     while (!d_preregisterQueue.empty()) {
     291                 :            :       // Get the next atom to pre-register
     292                 :    2153388 :       preprocessed = d_preregisterQueue.front();
     293                 :    2153388 :       d_preregisterQueue.pop();
     294                 :            : 
     295                 :            :       // the atom should not have free variables
     296         [ +  - ]:    4306776 :       Trace("theory") << "TheoryEngine::preRegister: " << preprocessed
     297                 :    2153388 :                       << std::endl;
     298         [ +  - ]:    2153388 :       if (Configuration::isAssertionBuild())
     299                 :            :       {
     300                 :    2153388 :         std::unordered_set<Node> fvs;
     301                 :    2153388 :         expr::getFreeVariables(preprocessed, fvs);
     302         [ -  + ]:    2153388 :         if (!fvs.empty())
     303                 :            :         {
     304                 :          0 :           Unhandled() << "Preregistered term with free variable: "
     305                 :          0 :                       << preprocessed << ", fv=" << *fvs.begin();
     306                 :            :         }
     307                 :    2153388 :       }
     308                 :            :       // should not have witness
     309 [ -  + ][ -  + ]:    2153388 :       Assert(!expr::hasSubtermKind(Kind::WITNESS, preprocessed));
                 [ -  - ]
     310                 :            : 
     311                 :            :       // pre-register with the shared solver, which handles
     312                 :            :       // calling prepregister on individual theories, adding shared terms,
     313                 :            :       // and setting up equalities to propagate in the shared term database.
     314 [ -  + ][ -  + ]:    2153388 :       Assert(d_sharedSolver != nullptr);
                 [ -  - ]
     315                 :    2153388 :       d_sharedSolver->preRegister(preprocessed);
     316                 :            :     }
     317                 :            : 
     318                 :            :     // Leaving pre-register
     319                 :    2005052 :     d_inPreregister = false;
     320                 :            :   }
     321                 :    2153372 : }
     322                 :            : 
     323                 :          0 : void TheoryEngine::printAssertions(const char* tag) {
     324         [ -  - ]:          0 :   if (TraceIsOn(tag)) {
     325                 :            : 
     326         [ -  - ]:          0 :     for (TheoryId theoryId = THEORY_FIRST; theoryId < THEORY_LAST; ++theoryId) {
     327                 :          0 :       Theory* theory = d_theoryTable[theoryId];
     328                 :          0 :       if (theory && isTheoryEnabled(theoryId))
     329                 :            :       {
     330         [ -  - ]:          0 :         Trace(tag) << "--------------------------------------------" << endl;
     331         [ -  - ]:          0 :         Trace(tag) << "Assertions of " << theory->getId() << ": " << endl;
     332                 :            :         {
     333                 :          0 :           context::CDList<Assertion>::const_iterator it = theory->facts_begin(),
     334                 :            :                                                      it_end =
     335                 :          0 :                                                          theory->facts_end();
     336         [ -  - ]:          0 :           for (unsigned i = 0; it != it_end; ++it, ++i)
     337                 :            :           {
     338         [ -  - ]:          0 :             if ((*it).d_isPreregistered)
     339                 :            :             {
     340         [ -  - ]:          0 :               Trace(tag) << "[" << i << "]: ";
     341                 :            :             }
     342                 :            :             else
     343                 :            :             {
     344         [ -  - ]:          0 :               Trace(tag) << "(" << i << "): ";
     345                 :            :             }
     346         [ -  - ]:          0 :             Trace(tag) << (*it).d_assertion << endl;
     347                 :            :           }
     348                 :            :         }
     349                 :            : 
     350         [ -  - ]:          0 :         if (logicInfo().isSharingEnabled())
     351                 :            :         {
     352                 :          0 :           TheoryState* state = theory->getTheoryState();
     353         [ -  - ]:          0 :           if (state != nullptr)
     354                 :            :           {
     355         [ -  - ]:          0 :             Trace(tag) << "Shared terms of " << theory->getId() << ": " << endl;
     356                 :            :             context::CDList<TNode>::const_iterator
     357                 :          0 :                 it = state->shared_terms_begin(),
     358                 :          0 :                 it_end = state->shared_terms_end();
     359         [ -  - ]:          0 :             for (unsigned i = 0; it != it_end; ++it, ++i)
     360                 :            :             {
     361         [ -  - ]:          0 :               Trace(tag) << "[" << i << "]: " << (*it) << endl;
     362                 :            :             }
     363                 :            :           }
     364                 :            :         }
     365                 :            :       }
     366                 :            :     }
     367                 :            :   }
     368                 :          0 : }
     369                 :            : 
     370                 :            : /**
     371                 :            :  * Check all (currently-active) theories for conflicts.
     372                 :            :  * @param effort the effort level to use
     373                 :            :  */
     374                 :   10974256 : void TheoryEngine::check(Theory::Effort effort) {
     375                 :            :   // spendResource();
     376                 :            : 
     377                 :            :   // Reset the interrupt flag
     378                 :   10974256 :   d_interrupted = false;
     379                 :            : 
     380                 :            : #ifdef CVC5_FOR_EACH_THEORY_STATEMENT
     381                 :            : #undef CVC5_FOR_EACH_THEORY_STATEMENT
     382                 :            : #endif
     383                 :            : #define CVC5_FOR_EACH_THEORY_STATEMENT(THEORY)                           \
     384                 :            :   if (theory::TheoryTraits<THEORY>::hasCheck && isTheoryEnabled(THEORY)) \
     385                 :            :   {                                                                      \
     386                 :            :     theoryOf(THEORY)->check(effort);                                     \
     387                 :            :     if (d_inConflict)                                                    \
     388                 :            :     {                                                                    \
     389                 :            :       Trace("conflict") << THEORY << " in conflict. " << std::endl;      \
     390                 :            :       break;                                                             \
     391                 :            :     }                                                                    \
     392                 :            :     if (rm->out())                                                       \
     393                 :            :     {                                                                    \
     394                 :            :       interrupt();                                                       \
     395                 :            :       return;                                                            \
     396                 :            :     }                                                                    \
     397                 :            :   }
     398                 :            : 
     399                 :            :   // Do the checking
     400                 :            :   try {
     401                 :            : 
     402                 :            :     // Mark the output channel unused (if this is FULL_EFFORT, and nothing
     403                 :            :     // is done by the theories, no additional check will be needed)
     404                 :   10974256 :     d_outputChannelUsed = false;
     405                 :            : 
     406                 :            :     // Mark the lemmas flag (no lemmas added)
     407                 :   10974256 :     d_lemmasAdded = false;
     408                 :            : 
     409 [ +  - ][ -  - ]:   10974256 :     Trace("theory") << "TheoryEngine::check(" << effort << "): d_factsAsserted = " << (d_factsAsserted ? "true" : "false") << endl;
     410                 :            : 
     411                 :            :     // If in full effort, we have a fake new assertion just to jumpstart the checking
     412         [ +  + ]:   10974256 :     if (Theory::fullEffort(effort)) {
     413                 :     169527 :       spendResource(Resource::TheoryFullCheckStep);
     414                 :     169527 :       d_factsAsserted = true;
     415                 :     169527 :       d_tc->resetRound();
     416                 :            :     }
     417                 :            : 
     418                 :            :     // check with the theory modules
     419         [ +  + ]:   10976084 :     for (TheoryEngineModule* tem : d_modules)
     420                 :            :     {
     421                 :       1828 :       tem->check(effort);
     422                 :            :     }
     423                 :            : 
     424                 :   10974256 :     auto rm = d_env.getResourceManager();
     425                 :            : 
     426                 :            :     // Check until done
     427 [ +  + ][ +  + ]:   19544081 :     while (d_factsAsserted && !d_inConflict && !d_lemmasAdded) {
         [ +  + ][ +  + ]
     428                 :            : 
     429         [ +  - ]:    8870523 :       Trace("theory") << "TheoryEngine::check(" << effort << "): running check" << endl;
     430                 :            : 
     431         [ +  - ]:    8870523 :       Trace("theory::assertions") << endl;
     432         [ -  + ]:    8870523 :       if (TraceIsOn("theory::assertions")) {
     433                 :          0 :         printAssertions("theory::assertions");
     434                 :            :       }
     435                 :            : 
     436         [ +  + ]:    8870523 :       if(Theory::fullEffort(effort)) {
     437         [ +  - ]:     184123 :         Trace("theory::assertions::fulleffort") << endl;
     438         [ -  + ]:     184123 :         if (TraceIsOn("theory::assertions::fulleffort")) {
     439                 :          0 :           printAssertions("theory::assertions::fulleffort");
     440                 :            :         }
     441                 :            :       }
     442                 :            : 
     443                 :            :       // Note that we've discharged all the facts
     444                 :    8870523 :       d_factsAsserted = false;
     445                 :            : 
     446                 :            :       // Do the checking
     447 [ +  + ][ +  + ]:    8870523 :       CVC5_FOR_EACH_THEORY;
         [ +  - ][ +  + ]
         [ +  + ][ +  + ]
         [ +  - ][ +  + ]
         [ +  + ][ +  + ]
         [ +  - ][ -  + ]
         [ +  + ][ +  + ]
         [ +  - ][ +  + ]
         [ +  + ][ +  + ]
         [ +  - ][ -  + ]
         [ +  + ][ +  + ]
         [ +  - ][ -  + ]
         [ +  + ][ +  + ]
         [ +  - ][ -  + ]
         [ +  + ][ +  + ]
         [ +  - ][ -  + ]
         [ +  + ][ +  + ]
         [ +  - ][ -  + ]
         [ +  + ][ +  + ]
         [ +  - ][ -  + ]
         [ +  + ][ +  + ]
         [ +  - ][ -  + ]
         [ +  + ][ -  + ]
         [ -  - ][ -  + ]
     448                 :            : 
     449         [ +  - ]:    8569825 :       Trace("theory") << "TheoryEngine::check(" << effort << "): running propagation after the initial check" << endl;
     450                 :            : 
     451                 :            :       // We are still satisfiable, propagate as much as possible
     452                 :    8569825 :       propagate(effort);
     453                 :            : 
     454                 :            :       // Interrupt in case we reached a resource limit.
     455         [ -  + ]:    8569825 :       if (rm->out())
     456                 :            :       {
     457                 :          0 :         interrupt();
     458                 :          0 :         return;
     459                 :            :       }
     460                 :            : 
     461         [ +  + ]:    8569825 :       if (Theory::fullEffort(effort))
     462                 :            :       {
     463                 :     139202 :         d_stats.d_fullEffortChecks++;
     464                 :            :         // We do combination if all has been processed and we are in fullcheck
     465 [ +  + ][ +  + ]:     269645 :         if (logicInfo().isSharingEnabled() && !d_factsAsserted && !needCheck()
     466 [ +  + ][ +  - ]:     269645 :             && !d_inConflict)
                 [ +  + ]
     467                 :            :         {
     468                 :      65714 :           d_stats.d_combineTheoriesCalls++;
     469                 :            :           // Do the combination
     470         [ +  - ]:     131428 :           Trace("theory") << "TheoryEngine::check(" << effort
     471                 :      65714 :                           << "): running combination" << endl;
     472                 :            :           {
     473                 :            :             TimerStat::CodeTimer combineTheoriesTimer(
     474                 :      65714 :                 d_stats.d_combineTheoriesTime);
     475                 :      65714 :             d_tc->combineTheories();
     476                 :      65714 :           }
     477         [ +  + ]:      65714 :           if (logicInfo().isQuantified())
     478                 :            :           {
     479                 :      46923 :             d_quantEngine->notifyCombineTheories();
     480                 :            :           }
     481                 :            :         }
     482                 :            :       }
     483                 :            :       else
     484                 :            :       {
     485 [ -  + ][ -  + ]:    8430623 :         Assert(effort == Theory::EFFORT_STANDARD);
                 [ -  - ]
     486                 :    8430623 :         d_stats.d_stdEffortChecks++;
     487                 :            :       }
     488                 :            : 
     489                 :            :       // Interrupt in case we reached a resource limit.
     490         [ -  + ]:    8569825 :       if (rm->out())
     491                 :            :       {
     492                 :          0 :         interrupt();
     493                 :          0 :         return;
     494                 :            :       }
     495                 :            :     }
     496                 :            : 
     497                 :            :     // Must consult quantifiers theory for last call to ensure sat, or otherwise add a lemma
     498 [ +  + ][ +  + ]:   10974237 :     if( Theory::fullEffort(effort) && ! d_inConflict && ! needCheck() ) {
         [ +  + ][ +  + ]
     499                 :      56840 :       d_stats.d_lcEffortChecks++;
     500         [ +  - ]:      56840 :       Trace("theory::assertions-model") << endl;
     501         [ -  + ]:      56840 :       if (TraceIsOn("theory::assertions-model")) {
     502                 :          0 :         printAssertions("theory::assertions-model");
     503                 :            :       }
     504                 :            :       // reset the model in the combination engine
     505                 :      56840 :       d_tc->resetModel();
     506                 :            :       //checks for theories requiring the model go at last call
     507         [ +  + ]:     852600 :       for (TheoryId theoryId = THEORY_FIRST; theoryId < THEORY_LAST; ++theoryId)
     508                 :            :       {
     509         [ +  + ]:     795760 :         if (theoryId != THEORY_QUANTIFIERS)
     510                 :            :         {
     511                 :     738920 :           Theory* theory = d_theoryTable[theoryId];
     512 [ +  - ][ +  + ]:     738920 :           if (theory && isTheoryEnabled(theoryId))
                 [ +  + ]
     513                 :            :           {
     514         [ +  + ]:     455588 :             if (theory->needsCheckLastEffort())
     515                 :            :             {
     516         [ +  + ]:      20875 :               if (!d_tc->buildModel())
     517                 :            :               {
     518                 :            :                 // We don't check if the model building fails, but for
     519                 :            :                 // uniformity ask all theories needsCheckLastEffort method.
     520                 :        160 :                 continue;
     521                 :            :               }
     522                 :      20715 :               theory->check(Theory::EFFORT_LAST_CALL);
     523                 :            :             }
     524                 :            :           }
     525                 :            :         }
     526                 :            :       }
     527         [ +  - ]:      56840 :       if (!d_inConflict)
     528                 :            :       {
     529         [ +  + ]:      56840 :         if (logicInfo().isQuantified())
     530                 :            :         {
     531                 :            :           // quantifiers engine must check at last call effort
     532                 :      47430 :           d_quantEngine->check(Theory::EFFORT_LAST_CALL);
     533                 :            :         }
     534                 :            :         // notify the theory modules of the model
     535         [ +  + ]:      57250 :         for (TheoryEngineModule* tem : d_modules)
     536                 :            :         {
     537         [ +  + ]:        417 :           if (!tem->needsCandidateModel())
     538                 :            :           {
     539                 :            :             // module does not need candidate model
     540                 :        393 :             continue;
     541                 :            :           }
     542         [ -  + ]:         24 :           if (!d_tc->buildModel())
     543                 :            :           {
     544                 :            :             // model failed to build, we are done
     545                 :          0 :             break;
     546                 :            :           }
     547                 :         24 :           tem->notifyCandidateModel(getModel());
     548                 :            :         }
     549                 :            :       }
     550                 :            :     }
     551                 :            : 
     552                 :   10974230 :     Trace("theory") << "TheoryEngine::check(" << effort << "): done, we are " << (d_inConflict ? "unsat" : "sat") << (d_lemmasAdded ? " with new lemmas" : " with no new lemmas");
     553 [ +  - ][ -  - ]:   10974230 :     Trace("theory") << ", need check = " << (needCheck() ? "YES" : "NO") << endl;
     554                 :            : 
     555                 :            :     // post check with the theory modules
     556         [ +  + ]:   10976058 :     for (TheoryEngineModule* tem : d_modules)
     557                 :            :     {
     558                 :       1828 :       tem->postCheck(effort);
     559                 :            :     }
     560         [ +  + ]:   10974230 :     if (Theory::fullEffort(effort))
     561                 :            :     {
     562 [ +  + ][ +  + ]:     169517 :       if (!d_inConflict && !needCheck())
                 [ +  + ]
     563                 :            :       {
     564                 :            :         // if some theory believes there is a conflict, but it is was not
     565                 :            :         // processed, we mark incomplete.
     566         [ +  + ]:     357990 :         for (TheoryId theoryId = THEORY_FIRST; theoryId < THEORY_LAST;
     567                 :     334124 :              ++theoryId)
     568                 :            :         {
     569                 :     334124 :           Theory* theory = d_theoryTable[theoryId];
     570 [ +  - ][ +  + ]:     334124 :           if (theory && theory->getTheoryState() != nullptr)
                 [ +  + ]
     571                 :            :           {
     572         [ -  + ]:     310258 :             if (theory->getTheoryState()->isInConflict())
     573                 :            :             {
     574                 :          0 :               setModelUnsound(theoryId,
     575                 :            :                               IncompleteId::UNPROCESSED_THEORY_CONFLICT);
     576                 :          0 :               DebugUnhandled() << "Unprocessed theory conflict from " << theoryId;
     577                 :            :               break;
     578                 :            :             }
     579                 :            :           }
     580                 :            :         }
     581                 :            :         // Do post-processing of model from the theories (e.g. used for
     582                 :            :         // THEORY_SEP to construct heap model)
     583                 :      23866 :         d_tc->postProcessModel(d_modelUnsound.get());
     584                 :            :       }
     585                 :            :     }
     586         [ -  - ]:          0 :   } catch(const theory::Interrupted&) {
     587         [ -  - ]:          0 :     Trace("theory") << "TheoryEngine::check() => interrupted" << endl;
     588                 :          0 :   }
     589                 :            : }
     590                 :            : 
     591                 :    8569825 : void TheoryEngine::propagate(Theory::Effort effort)
     592                 :            : {
     593                 :            :   // Reset the interrupt flag
     594                 :    8569825 :   d_interrupted = false;
     595                 :            : 
     596                 :            :   // Definition of the statement that is to be run by every theory
     597                 :            : #ifdef CVC5_FOR_EACH_THEORY_STATEMENT
     598                 :            : #undef CVC5_FOR_EACH_THEORY_STATEMENT
     599                 :            : #endif
     600                 :            : #define CVC5_FOR_EACH_THEORY_STATEMENT(THEORY)   \
     601                 :            :   if (theory::TheoryTraits<THEORY>::hasPropagate \
     602                 :            :       && isTheoryEnabled(THEORY))    \
     603                 :            :   {                                              \
     604                 :            :     theoryOf(THEORY)->propagate(effort);         \
     605                 :            :   }
     606                 :            : 
     607                 :            :   // Reset the interrupt flag
     608                 :    8569825 :   d_interrupted = false;
     609                 :            : 
     610                 :            :   // Propagate for each theory using the statement above
     611 [ +  + ][ +  + ]:    8569825 :   CVC5_FOR_EACH_THEORY;
     612                 :    8569825 : }
     613                 :            : 
     614                 :    7178610 : Node TheoryEngine::getNextDecisionRequest()
     615                 :            : {
     616                 :    7178610 :   return d_decManager->getNextDecisionRequest();
     617                 :            : }
     618                 :            : 
     619                 :     197643 : bool TheoryEngine::properConflict(TNode conflict) const {
     620                 :            :   bool value;
     621         [ +  + ]:     197643 :   if (conflict.getKind() == Kind::AND)
     622                 :            :   {
     623         [ +  + ]:    2374490 :     for (unsigned i = 0; i < conflict.getNumChildren(); ++ i) {
     624         [ -  + ]:    2178268 :       if (! getPropEngine()->hasValue(conflict[i], value)) {
     625         [ -  - ]:          0 :         Trace("properConflict") << "Bad conflict is due to unassigned atom: "
     626                 :          0 :                                 << conflict[i] << endl;
     627                 :          0 :         return false;
     628                 :            :       }
     629         [ -  + ]:    2178268 :       if (! value) {
     630         [ -  - ]:          0 :         Trace("properConflict") << "Bad conflict is due to false atom: "
     631                 :          0 :                                 << conflict[i] << endl;
     632                 :          0 :         return false;
     633                 :            :       }
     634         [ -  + ]:    2178268 :       if (conflict[i] != rewrite(conflict[i]))
     635                 :            :       {
     636         [ -  - ]:          0 :         Trace("properConflict")
     637         [ -  - ]:          0 :             << "Bad conflict is due to atom not in normal form: " << conflict[i]
     638                 :          0 :             << " vs " << rewrite(conflict[i]) << endl;
     639                 :          0 :         return false;
     640                 :            :       }
     641                 :            :     }
     642                 :            :   }
     643                 :            :   else
     644                 :            :   {
     645         [ -  + ]:       1421 :     if (! getPropEngine()->hasValue(conflict, value)) {
     646         [ -  - ]:          0 :       Trace("properConflict") << "Bad conflict is due to unassigned atom: "
     647                 :          0 :                               << conflict << endl;
     648                 :          0 :       return false;
     649                 :            :     }
     650         [ -  + ]:       1421 :     if(! value) {
     651         [ -  - ]:          0 :       Trace("properConflict") << "Bad conflict is due to false atom: "
     652                 :          0 :                               << conflict << endl;
     653                 :          0 :       return false;
     654                 :            :     }
     655         [ -  + ]:       1421 :     if (conflict != rewrite(conflict))
     656                 :            :     {
     657         [ -  - ]:          0 :       Trace("properConflict")
     658                 :          0 :           << "Bad conflict is due to atom not in normal form: " << conflict
     659                 :          0 :           << " vs " << rewrite(conflict) << endl;
     660                 :          0 :       return false;
     661                 :            :     }
     662                 :            :   }
     663                 :     197643 :   return true;
     664                 :            : }
     665                 :            : 
     666                 :    1818815 : TheoryModel* TheoryEngine::getModel()
     667                 :            : {
     668 [ -  + ][ -  + ]:    1818815 :   Assert(d_tc != nullptr);
                 [ -  - ]
     669                 :    1818815 :   TheoryModel* m = d_tc->getModel();
     670 [ -  + ][ -  + ]:    1818815 :   Assert(m != nullptr);
                 [ -  - ]
     671                 :    1818815 :   return m;
     672                 :            : }
     673                 :            : 
     674                 :      22575 : TheoryModel* TheoryEngine::getBuiltModel()
     675                 :            : {
     676 [ -  + ][ -  + ]:      22575 :   Assert(d_tc != nullptr);
                 [ -  - ]
     677                 :            :   // If this method was called, produceModels should be true.
     678 [ -  + ][ -  + ]:      22575 :   AlwaysAssert(options().smt.produceModels);
                 [ -  - ]
     679                 :            :   // we must build model at this point
     680         [ -  + ]:      22575 :   if (!d_tc->buildModel())
     681                 :            :   {
     682                 :          0 :     return nullptr;
     683                 :            :   }
     684                 :      22575 :   return d_tc->getModel();
     685                 :            : }
     686                 :            : 
     687                 :      24176 : bool TheoryEngine::buildModel()
     688                 :            : {
     689 [ -  + ][ -  + ]:      24176 :   Assert(d_tc != nullptr);
                 [ -  - ]
     690                 :      24176 :   return d_tc->buildModel();
     691                 :            : }
     692                 :            : 
     693                 :  192362386 : bool TheoryEngine::isTheoryEnabled(theory::TheoryId theoryId) const
     694                 :            : {
     695                 :  192362386 :   return logicInfo().isTheoryEnabled(theoryId);
     696                 :            : }
     697                 :            : 
     698                 :   68837033 : theory::TheoryId TheoryEngine::theoryExpPropagation(theory::TheoryId tid) const
     699                 :            : {
     700         [ +  + ]:   68837033 :   if (options().theory.eeMode == options::EqEngineMode::CENTRAL)
     701                 :            :   {
     702                 :      32955 :     if (EqEngineManagerCentral::usesCentralEqualityEngine(options(), tid)
     703 [ +  + ][ +  + ]:      32955 :         && Theory::expUsingCentralEqualityEngine(tid))
                 [ +  + ]
     704                 :            :     {
     705                 :      12762 :       return THEORY_BUILTIN;
     706                 :            :     }
     707                 :            :   }
     708                 :   68824271 :   return tid;
     709                 :            : }
     710                 :            : 
     711                 :      49384 : bool TheoryEngine::presolve() {
     712                 :            :   // Reset the interrupt flag
     713                 :      49384 :   d_interrupted = false;
     714                 :            : 
     715                 :            :   // Reset the decision manager. This clears its decision strategies that are
     716                 :            :   // no longer valid in this user context.
     717                 :      49384 :   d_decManager->presolve();
     718                 :            : 
     719                 :            :   try {
     720                 :            :     // Definition of the statement that is to be run by every theory
     721                 :            : #ifdef CVC5_FOR_EACH_THEORY_STATEMENT
     722                 :            : #undef CVC5_FOR_EACH_THEORY_STATEMENT
     723                 :            : #endif
     724                 :            : #define CVC5_FOR_EACH_THEORY_STATEMENT(THEORY)   \
     725                 :            :   if (theory::TheoryTraits<THEORY>::hasPresolve) \
     726                 :            :   {                                              \
     727                 :            :     theoryOf(THEORY)->presolve();                \
     728                 :            :     if (d_inConflict)                            \
     729                 :            :     {                                            \
     730                 :            :       return true;                               \
     731                 :            :     }                                            \
     732                 :            :   }
     733                 :            : 
     734                 :            :     // Presolve for each theory using the statement above
     735 [ -  + ][ -  + ]:      49384 :     CVC5_FOR_EACH_THEORY;
         [ -  + ][ -  + ]
         [ -  + ][ -  + ]
         [ -  + ][ -  + ]
                 [ -  + ]
     736         [ -  - ]:          0 :   } catch(const theory::Interrupted&) {
     737         [ -  - ]:          0 :     Trace("theory") << "TheoryEngine::presolve() => interrupted" << endl;
     738                 :          0 :   }
     739                 :            :   // presolve with the theory engine modules as well
     740         [ +  + ]:      49895 :   for (TheoryEngineModule* tem : d_modules)
     741                 :            :   {
     742                 :        511 :     tem->presolve();
     743                 :            :   }
     744                 :            : 
     745                 :            :   // return whether we have a conflict
     746                 :      49384 :   return false;
     747                 :            : }/* TheoryEngine::presolve() */
     748                 :            : 
     749                 :      49368 : void TheoryEngine::postsolve(prop::SatValue result)
     750                 :            : {
     751                 :            :   // postsolve with the theory engine modules as well
     752         [ +  + ]:      49879 :   for (TheoryEngineModule* tem : d_modules)
     753                 :            :   {
     754                 :        511 :     tem->postsolve(result);
     755                 :            :   }
     756                 :            : 
     757                 :            :   // Reset the interrupt flag
     758                 :      49368 :   d_interrupted = false;
     759                 :      49368 : }
     760                 :            : 
     761                 :       4994 : void TheoryEngine::notifyRestart() {
     762                 :            :   // Reset the interrupt flag
     763                 :       4994 :   d_interrupted = false;
     764                 :            : 
     765                 :            :   // Definition of the statement that is to be run by every theory
     766                 :            : #ifdef CVC5_FOR_EACH_THEORY_STATEMENT
     767                 :            : #undef CVC5_FOR_EACH_THEORY_STATEMENT
     768                 :            : #endif
     769                 :            : #define CVC5_FOR_EACH_THEORY_STATEMENT(THEORY)       \
     770                 :            :   if (theory::TheoryTraits<THEORY>::hasNotifyRestart \
     771                 :            :       && isTheoryEnabled(THEORY))        \
     772                 :            :   {                                                  \
     773                 :            :     theoryOf(THEORY)->notifyRestart();               \
     774                 :            :   }
     775                 :            : 
     776                 :            :   // notify each theory using the statement above
     777         [ +  + ]:       4994 :   CVC5_FOR_EACH_THEORY;
     778                 :       4994 : }
     779                 :            : 
     780                 :     341710 : void TheoryEngine::ppStaticLearn(TNode in, std::vector<TrustNode>& learned)
     781                 :            : {
     782                 :            :   // Reset the interrupt flag
     783                 :     341710 :   d_interrupted = false;
     784                 :            : 
     785                 :            :   // Definition of the statement that is to be run by every theory
     786                 :            : #ifdef CVC5_FOR_EACH_THEORY_STATEMENT
     787                 :            : #undef CVC5_FOR_EACH_THEORY_STATEMENT
     788                 :            : #endif
     789                 :            : #define CVC5_FOR_EACH_THEORY_STATEMENT(THEORY)        \
     790                 :            :   if (theory::TheoryTraits<THEORY>::hasPpStaticLearn) \
     791                 :            :   {                                                   \
     792                 :            :     theoryOf(THEORY)->ppStaticLearn(in, learned);     \
     793                 :            :   }
     794                 :            : 
     795                 :            :   // static learning for each theory using the statement above
     796                 :     341710 :   CVC5_FOR_EACH_THEORY;
     797                 :     341710 : }
     798                 :            : 
     799                 :     322329 : bool TheoryEngine::hasSatValue(TNode n, bool& value) const
     800                 :            : {
     801         [ +  + ]:     322329 :   if (d_propEngine->isSatLiteral(n))
     802                 :            :   {
     803                 :     322196 :     return d_propEngine->hasValue(n, value);
     804                 :            :   }
     805                 :        133 :   return false;
     806                 :            : }
     807                 :            : 
     808                 :    1826655 : bool TheoryEngine::hasSatValue(TNode n) const
     809                 :            : {
     810         [ +  + ]:    1826655 :   if (d_propEngine->isSatLiteral(n))
     811                 :            :   {
     812                 :            :     bool value;
     813                 :    1825743 :     return d_propEngine->hasValue(n, value);
     814                 :            :   }
     815                 :        912 :   return false;
     816                 :            : }
     817                 :            : 
     818                 :       1726 : bool TheoryEngine::isRelevant(Node lit) const
     819                 :            : {
     820         [ +  - ]:       1726 :   if (d_relManager != nullptr)
     821                 :            :   {
     822                 :       1726 :     return d_relManager->isRelevant(lit);
     823                 :            :   }
     824                 :            :   // otherwise must assume its relevant
     825                 :          0 :   return true;
     826                 :            : }
     827                 :            : 
     828                 :      52657 : bool TheoryEngine::isLegalElimination(TNode x, TNode val)
     829                 :            : {
     830 [ -  + ][ -  + ]:      52657 :   Assert(x.isVar());
                 [ -  - ]
     831         [ +  + ]:      52657 :   if (expr::hasSubterm(val, x))
     832                 :            :   {
     833                 :      13087 :     return false;
     834                 :            :   }
     835         [ -  + ]:      39570 :   if (val.getType() != x.getType())
     836                 :            :   {
     837                 :          0 :     return false;
     838                 :            :   }
     839 [ +  + ][ +  + ]:      39570 :   if (!options().smt.produceModels || options().smt.modelVarElimUneval)
                 [ +  + ]
     840                 :            :   {
     841                 :            :     // Don't care about the model, or we allow variables to be eliminated by
     842                 :            :     // unevaluatable terms, we can eliminate. Notice that when
     843                 :            :     // options().smt.modelVarElimUneval is true, val may contain unevaluatable
     844                 :            :     // kinds. This means that e.g. a Boolean variable may be eliminated based on
     845                 :            :     // an equality (= b (forall ((x)) (P x))), where its model value is (forall
     846                 :            :     // ((x)) (P x)).
     847                 :      39566 :     return true;
     848                 :            :   }
     849                 :            :   // If models are enabled, then it depends on whether the term contains any
     850                 :            :   // unevaluable operators like FORALL, SINE, etc. Having such operators makes
     851                 :            :   // model construction contain non-constant values for variables, which is
     852                 :            :   // not ideal from a user perspective.
     853                 :            :   // We also insist on this check since the term to eliminate should never
     854                 :            :   // contain quantifiers, or else variable shadowing issues may arise.
     855                 :            :   // there should be a model object
     856                 :          4 :   TheoryModel* tm = getModel();
     857 [ -  + ][ -  + ]:          4 :   Assert(tm != nullptr);
                 [ -  - ]
     858                 :          4 :   return tm->isLegalElimination(val);
     859                 :            : }
     860                 :            : 
     861                 :     211267 : bool TheoryEngine::solve(TrustNode tliteral,
     862                 :            :                          TrustSubstitutionMap& substitutionOut)
     863                 :            : {
     864 [ -  + ][ -  + ]:     211267 :   Assert(tliteral.getKind() == TrustNodeKind::LEMMA);
                 [ -  - ]
     865                 :            :   // Reset the interrupt flag
     866                 :     211267 :   d_interrupted = false;
     867                 :            : 
     868                 :     211267 :   TNode literal = tliteral.getNode();
     869         [ +  + ]:     211267 :   TNode atom = literal.getKind() == Kind::NOT ? literal[0] : literal;
     870 [ +  - ][ -  + ]:     211267 :   Trace("theory::solve") << "TheoryEngine::solve(" << literal << "): solving with " << theoryOf(atom)->getId() << endl;
                 [ -  - ]
     871                 :            : 
     872                 :     211267 :   TheoryId tid = d_env.theoryOf(atom);
     873                 :            :   // Note that ppAssert is called before ppRewrite.
     874 [ +  + ][ +  - ]:     211267 :   if (!isTheoryEnabled(tid) && tid != THEORY_SAT_SOLVER)
                 [ +  + ]
     875                 :            :   {
     876                 :            :     // don't throw an exception yet
     877                 :            :     // Instead ppStaticRewrite will be called on atom, which may throw an
     878                 :            :     // exception if the term is not rewritten.
     879                 :         12 :     return false;
     880                 :            :   }
     881                 :            : 
     882                 :     211255 :   bool solveStatus = d_theoryTable[tid]->ppAssert(tliteral, substitutionOut);
     883         [ +  - ]:     211255 :   Trace("theory::solve") << "TheoryEngine::solve(" << literal << ") => " << solveStatus << endl;
     884                 :     211255 :   return solveStatus;
     885                 :     211267 : }
     886                 :            : 
     887                 :    4623392 : TrustNode TheoryEngine::ppRewrite(TNode term,
     888                 :            :                                   std::vector<theory::SkolemLemma>& lems)
     889                 :            : {
     890 [ -  + ][ -  + ]:    4623392 :   Assert(lems.empty());
                 [ -  - ]
     891                 :    4623392 :   TheoryId tid = d_env.theoryOf(term);
     892                 :            :   // We check whether the theory is enabled here (instead of only during solve),
     893                 :            :   // since there are corner cases where facts may involve terms that belong
     894                 :            :   // to other theories, e.g. equalities between variables belong to UF when
     895                 :            :   // theoryof-mode is `term`.
     896 [ -  + ][ -  - ]:    4623392 :   if (!isTheoryEnabled(tid) && tid != THEORY_SAT_SOLVER)
                 [ -  + ]
     897                 :            :   {
     898                 :          0 :     stringstream ss;
     899                 :          0 :     ss << "The logic was specified as " << logicInfo().getLogicString()
     900                 :          0 :        << ", which doesn't include " << tid
     901                 :          0 :        << ", but got a term for that theory during solving." << std::endl
     902                 :          0 :        << "The term:" << std::endl
     903                 :          0 :        << term;
     904                 :          0 :     throw LogicException(ss.str());
     905                 :          0 :   }
     906                 :    4623401 :   TrustNode trn = d_theoryTable[tid]->ppRewrite(term, lems);
     907                 :            :   // should never introduce a skolem to eliminate an equality
     908 [ +  + ][ +  - ]:    4623383 :   Assert(lems.empty() || term.getKind() != Kind::EQUAL);
         [ -  + ][ -  + ]
                 [ -  - ]
     909         [ +  + ]:    4623383 :   if (!isProofEnabled())
     910                 :            :   {
     911                 :    2627628 :     return trn;
     912                 :            :   }
     913 [ -  + ][ -  + ]:    1995755 :   Assert(d_lazyProof != nullptr);
                 [ -  - ]
     914                 :            :   // if proofs are enabled, must ensure we have proofs for all the skolem lemmas
     915         [ +  + ]:    1998933 :   for (SkolemLemma& skl : lems)
     916                 :            :   {
     917                 :       3178 :     TrustNode tskl = skl.d_lemma;
     918 [ -  + ][ -  + ]:       3178 :     Assert(tskl.getKind() == TrustNodeKind::LEMMA);
                 [ -  - ]
     919         [ +  + ]:       3178 :     if (tskl.getGenerator() == nullptr)
     920                 :            :     {
     921                 :       1062 :       Node proven = tskl.getProven();
     922                 :            :       Node tidn =
     923                 :       1062 :           builtin::BuiltinProofRuleChecker::mkTheoryIdNode(nodeManager(), tid);
     924                 :       2124 :       d_lazyProof->addTrustedStep(
     925                 :            :           proven, TrustId::THEORY_PREPROCESS_LEMMA, {}, {tidn});
     926         [ +  - ]:       1062 :       skl.d_lemma = TrustNode::mkTrustLemma(proven, d_lazyProof.get());
     927                 :       1062 :     }
     928                 :       3178 :   }
     929                 :            :   // notice that we don't ensure proofs are processed for the returned (rewrite)
     930                 :            :   // trust node, this is the responsibility of the caller, i.e. theory
     931                 :            :   // preprocessor.
     932                 :    1995755 :   return trn;
     933                 :          0 : }
     934                 :            : 
     935                 :    3678762 : TrustNode TheoryEngine::ppStaticRewrite(TNode term)
     936                 :            : {
     937                 :    3678762 :   TheoryId tid = d_env.theoryOf(term);
     938 [ +  + ][ +  - ]:    3678762 :   if (!isTheoryEnabled(tid) && tid != THEORY_SAT_SOLVER)
                 [ +  + ]
     939                 :            :   {
     940                 :            :     // If the theory is not enabled, then we require eliminating the term
     941                 :            :     // here.
     942                 :         11 :     TrustNode tret = d_theoryTable[THEORY_BUILTIN]->ppStaticRewrite(term);
     943         [ +  + ]:         11 :     if (!tret.isNull())
     944                 :            :     {
     945                 :          8 :       return tret;
     946                 :            :     }
     947                 :          3 :     stringstream ss;
     948                 :          3 :     ss << "The logic was specified as " << logicInfo().getLogicString()
     949                 :          6 :        << ", which doesn't include " << tid
     950                 :          3 :        << ", but got a preprocessing-time term for that theory."
     951                 :          3 :        << std::endl
     952                 :          3 :        << "The term:" << std::endl
     953                 :          3 :        << term;
     954                 :          3 :     throw LogicException(ss.str());
     955                 :         14 :   }
     956                 :    3678751 :   return d_theoryTable[tid]->ppStaticRewrite(term);
     957                 :            : }
     958                 :            : 
     959                 :      64521 : void TheoryEngine::notifyPreprocessedAssertions(
     960                 :            :     const std::vector<Node>& assertions) {
     961                 :            :   // call all the theories
     962         [ +  + ]:     967815 :   for (TheoryId theoryId = theory::THEORY_FIRST; theoryId < theory::THEORY_LAST;
     963                 :     903294 :        ++theoryId) {
     964         [ +  - ]:     903294 :     if (d_theoryTable[theoryId]) {
     965                 :     903294 :       theoryOf(theoryId)->ppNotifyAssertions(assertions);
     966                 :            :     }
     967                 :            :   }
     968         [ +  + ]:      64521 :   if (d_relManager != nullptr)
     969                 :            :   {
     970                 :        483 :     d_relManager->notifyPreprocessedAssertions(assertions, true);
     971                 :            :   }
     972                 :      64521 : }
     973                 :            : 
     974                 :   68494636 : bool TheoryEngine::markPropagation(TNode assertion, TNode originalAssertion, theory::TheoryId toTheoryId, theory::TheoryId fromTheoryId) {
     975                 :            :   // What and where we are asserting
     976                 :   68494636 :   NodeTheoryPair toAssert(assertion, toTheoryId, d_propagationMapTimestamp);
     977                 :            :   // What and where it came from
     978                 :   68494636 :   NodeTheoryPair toExplain(originalAssertion, fromTheoryId, d_propagationMapTimestamp);
     979                 :            : 
     980                 :            :   // See if the theory already got this literal
     981                 :   68494636 :   PropagationMap::const_iterator find = d_propagationMap.find(toAssert);
     982         [ +  + ]:   68494636 :   if (find != d_propagationMap.end()) {
     983                 :            :     // The theory already knows this
     984         [ +  - ]:   19646169 :     Trace("theory::assertToTheory") << "TheoryEngine::markPropagation(): already there" << endl;
     985                 :   19646169 :     return false;
     986                 :            :   }
     987                 :            : 
     988         [ +  - ]:   48848467 :   Trace("theory::assertToTheory") << "TheoryEngine::markPropagation(): marking [" << d_propagationMapTimestamp << "] " << assertion << ", " << toTheoryId << " from " << originalAssertion << ", " << fromTheoryId << endl;
     989                 :            : 
     990                 :            :   // Mark the propagation
     991                 :   48848467 :   d_propagationMap[toAssert] = toExplain;
     992                 :   48848467 :   d_propagationMapTimestamp = d_propagationMapTimestamp + 1;
     993                 :            : 
     994                 :   48848467 :   return true;
     995                 :   68494636 : }
     996                 :            : 
     997                 :            : 
     998                 :   84677428 : void TheoryEngine::assertToTheory(TNode assertion, TNode originalAssertion, theory::TheoryId toTheoryId, theory::TheoryId fromTheoryId) {
     999         [ +  - ]:   84677428 :   Trace("theory::assertToTheory") << "TheoryEngine::assertToTheory(" << assertion << ", " << originalAssertion << "," << toTheoryId << ", " << fromTheoryId << ")" << endl;
    1000                 :            : 
    1001 [ -  + ][ -  + ]:   84677428 :   Assert(toTheoryId != fromTheoryId);
                 [ -  - ]
    1002                 :  169354856 :   if (toTheoryId != THEORY_SAT_SOLVER
    1003 [ +  + ][ -  + ]:   84677428 :       && !isTheoryEnabled(toTheoryId))
                 [ -  + ]
    1004                 :            :   {
    1005                 :          0 :     stringstream ss;
    1006                 :          0 :     ss << "The logic was specified as " << logicInfo().getLogicString()
    1007                 :          0 :        << ", which doesn't include " << toTheoryId
    1008                 :          0 :        << ", but got an asserted fact to that theory." << endl
    1009                 :          0 :        << "The fact:" << endl
    1010                 :          0 :        << assertion;
    1011                 :          0 :     throw LogicException(ss.str());
    1012                 :          0 :   }
    1013                 :            : 
    1014         [ +  + ]:   84677428 :   if (d_inConflict) {
    1015                 :     194624 :     return;
    1016                 :            :   }
    1017                 :            : 
    1018                 :            :   // If sharing is disabled, things are easy
    1019         [ +  + ]:   84482804 :   if (!logicInfo().isSharingEnabled())
    1020                 :            :   {
    1021 [ -  + ][ -  + ]:   15988168 :     Assert(assertion == originalAssertion);
                 [ -  - ]
    1022         [ +  + ]:   15988168 :     if (fromTheoryId == THEORY_SAT_SOLVER) {
    1023                 :            :       // Send to the apropriate theory
    1024                 :   11629725 :       theory::Theory* toTheory = theoryOf(toTheoryId);
    1025                 :            :       // We assert it, and we know it's preregistereed
    1026                 :   11629725 :       toTheory->assertFact(assertion, true);
    1027                 :            :       // Mark that we have more information
    1028                 :   11629725 :       d_factsAsserted = true;
    1029                 :            :     } else {
    1030 [ -  + ][ -  + ]:    4358443 :       Assert(toTheoryId == THEORY_SAT_SOLVER);
                 [ -  - ]
    1031                 :            :       // Check for propositional conflict
    1032                 :            :       bool value;
    1033         [ +  + ]:    4358443 :       if (d_propEngine->hasValue(assertion, value)) {
    1034         [ +  + ]:    3167426 :         if (!value) {
    1035         [ +  - ]:      65652 :           Trace("theory::propagate") << "TheoryEngine::assertToTheory(" << assertion << ", " << toTheoryId << ", " << fromTheoryId << "): conflict (no sharing)" << endl;
    1036         [ +  - ]:     131304 :           Trace("dtview::conflict")
    1037                 :      65652 :               << ":THEORY-CONFLICT: " << assertion << std::endl;
    1038                 :      65652 :           markInConflict();
    1039                 :            :         } else {
    1040                 :    3101774 :           return;
    1041                 :            :         }
    1042                 :            :       }
    1043                 :    1256669 :       d_propagatedLiterals.push_back(assertion);
    1044                 :            :     }
    1045                 :   12886394 :     return;
    1046                 :            :   }
    1047                 :            : 
    1048                 :            :   // determine the actual theory that will process/explain the fact, which is
    1049                 :            :   // THEORY_BUILTIN if the theory uses the central equality engine
    1050                 :   68494636 :   TheoryId toTheoryIdProp = theoryExpPropagation(toTheoryId);
    1051                 :            :   // If sending to the shared solver, it's also simple
    1052         [ +  + ]:   68494636 :   if (toTheoryId == THEORY_BUILTIN) {
    1053         [ +  + ]:   22372226 :     if (markPropagation(
    1054                 :            :             assertion, originalAssertion, toTheoryIdProp, fromTheoryId))
    1055                 :            :     {
    1056                 :            :       // assert to the shared solver
    1057                 :   12410606 :       bool polarity = assertion.getKind() != Kind::NOT;
    1058         [ +  + ]:   12410606 :       TNode atom = polarity ? assertion : assertion[0];
    1059                 :   12410606 :       d_sharedSolver->assertShared(atom, polarity, assertion);
    1060                 :   12410606 :     }
    1061                 :   22372226 :     return;
    1062                 :            :   }
    1063                 :            : 
    1064                 :            :   // Things from the SAT solver are already normalized, so they go
    1065                 :            :   // directly to the apropriate theory
    1066         [ +  + ]:   46122410 :   if (fromTheoryId == THEORY_SAT_SOLVER) {
    1067                 :            :     // We know that this is normalized, so just send it off to the theory
    1068         [ +  + ]:   16716144 :     if (markPropagation(
    1069                 :            :             assertion, originalAssertion, toTheoryIdProp, fromTheoryId))
    1070                 :            :     {
    1071                 :            :       // Is it preregistered
    1072         [ -  - ]:   16572945 :       bool preregistered = d_propEngine->isSatLiteral(assertion)
    1073 [ +  + ][ +  + ]:   16572945 :                            && d_env.theoryOf(assertion) == toTheoryId;
         [ +  + ][ +  - ]
                 [ -  - ]
    1074                 :            :       // We assert it
    1075                 :   16572945 :       theoryOf(toTheoryId)->assertFact(assertion, preregistered);
    1076                 :            :       // Mark that we have more information
    1077                 :   16572945 :       d_factsAsserted = true;
    1078                 :            :     }
    1079                 :   16716144 :     return;
    1080                 :            :   }
    1081                 :            : 
    1082                 :            :   // Propagations to the SAT solver are just enqueued for pickup by
    1083                 :            :   // the SAT solver later
    1084         [ +  + ]:   29406266 :   if (toTheoryId == THEORY_SAT_SOLVER) {
    1085 [ -  + ][ -  + ]:   22576147 :     Assert(toTheoryIdProp == toTheoryId);
                 [ -  - ]
    1086         [ +  + ]:   22576147 :     if (markPropagation(assertion, originalAssertion, toTheoryId, fromTheoryId)) {
    1087                 :            :       // Enqueue for propagation to the SAT solver
    1088                 :   13667857 :       d_propagatedLiterals.push_back(assertion);
    1089                 :            :       // Check for propositional conflicts
    1090                 :            :       bool value;
    1091 [ +  + ][ +  + ]:   13667857 :       if (d_propEngine->hasValue(assertion, value) && !value) {
         [ +  - ][ +  + ]
                 [ -  - ]
    1092         [ +  - ]:     228156 :         Trace("theory::propagate")
    1093                 :          0 :             << "TheoryEngine::assertToTheory(" << assertion << ", "
    1094                 :          0 :             << toTheoryId << ", " << fromTheoryId << "): conflict (sharing)"
    1095                 :     114078 :             << endl;
    1096         [ +  - ]:     228156 :         Trace("dtview::conflict")
    1097                 :     114078 :             << ":THEORY-CONFLICT: " << assertion << std::endl;
    1098                 :     114078 :         markInConflict();
    1099                 :            :       }
    1100                 :            :     }
    1101                 :   22576147 :     return;
    1102                 :            :   }
    1103                 :            : 
    1104                 :    6830119 :   Assert(assertion.getKind() == Kind::EQUAL
    1105                 :            :          || (assertion.getKind() == Kind::NOT
    1106                 :            :              && assertion[0].getKind() == Kind::EQUAL));
    1107                 :            : 
    1108                 :            :   // Normalize
    1109                 :    6830119 :   Node normalizedLiteral = rewrite(assertion);
    1110                 :            : 
    1111                 :            :   // See if it rewrites false directly -> conflict
    1112         [ +  + ]:    6830119 :   if (normalizedLiteral.isConst()) {
    1113         [ +  + ]:      45524 :     if (!normalizedLiteral.getConst<bool>()) {
    1114                 :            :       // Mark the propagation for explanations
    1115         [ +  - ]:        984 :       if (markPropagation(normalizedLiteral,
    1116                 :            :                           originalAssertion,
    1117                 :            :                           toTheoryIdProp,
    1118                 :            :                           fromTheoryId))
    1119                 :            :       {
    1120                 :            :         // special case, trust node has no proof generator
    1121                 :        984 :         TrustNode trnn = TrustNode::mkTrustConflict(normalizedLiteral);
    1122                 :            :         // Get the explanation (conflict will figure out where it came from)
    1123                 :        984 :         conflict(trnn, InferenceId::CONFLICT_REWRITE_LIT, toTheoryId);
    1124                 :        984 :       } else {
    1125                 :          0 :         Unreachable();
    1126                 :            :       }
    1127                 :        984 :       return;
    1128                 :            :     }
    1129                 :            :   }
    1130                 :            : 
    1131                 :            :   // Try and assert (note that we assert the non-normalized one)
    1132         [ +  + ]:    6829135 :   if (markPropagation(
    1133                 :            :           assertion, originalAssertion, toTheoryIdProp, fromTheoryId))
    1134                 :            :   {
    1135                 :            :     // Check if has been pre-registered with the theory
    1136         [ -  - ]:    6196075 :     bool preregistered = d_propEngine->isSatLiteral(assertion)
    1137 [ +  + ][ +  + ]:    6196075 :                          && d_env.theoryOf(assertion) == toTheoryId;
         [ +  + ][ +  - ]
                 [ -  - ]
    1138                 :            :     // Assert away
    1139                 :    6196075 :     theoryOf(toTheoryId)->assertFact(assertion, preregistered);
    1140                 :    6196075 :     d_factsAsserted = true;
    1141                 :            :   }
    1142                 :            : 
    1143                 :    6829135 :   return;
    1144                 :    6830119 : }
    1145                 :            : 
    1146                 :   28283136 : void TheoryEngine::assertFact(TNode literal)
    1147                 :            : {
    1148         [ +  - ]:   28283136 :   Trace("theory") << "TheoryEngine::assertFact(" << literal << ")" << endl;
    1149                 :            : 
    1150                 :            :   // spendResource();
    1151                 :            : 
    1152                 :            :   // If we're in conflict, nothing to do
    1153         [ +  + ]:   28283136 :   if (d_inConflict) {
    1154                 :      43195 :     return;
    1155                 :            :   }
    1156                 :            : 
    1157                 :            :   // Get the atom
    1158                 :   28239941 :   bool polarity = literal.getKind() != Kind::NOT;
    1159         [ +  + ]:   28239941 :   TNode atom = polarity ? literal : literal[0];
    1160                 :            : 
    1161         [ +  + ]:   28239941 :   if (logicInfo().isSharingEnabled())
    1162                 :            :   {
    1163                 :            :     // If any shared terms, it's time to do sharing work
    1164                 :   16610217 :     d_sharedSolver->preNotifySharedFact(atom);
    1165                 :            : 
    1166                 :            :     // If it's an equality, assert it to the shared term manager, even though the terms are not
    1167                 :            :     // yet shared. As the terms become shared later, the shared terms manager will then add them
    1168                 :            :     // to the assert the equality to the interested theories
    1169         [ +  + ]:   16610215 :     if (atom.getKind() == Kind::EQUAL)
    1170                 :            :     {
    1171                 :            :       // Assert it to the the owning theory
    1172                 :    9168986 :       assertToTheory(literal,
    1173                 :            :                      literal,
    1174                 :    9168986 :                      /* to */ d_env.theoryOf(atom),
    1175                 :            :                      /* from */ THEORY_SAT_SOLVER);
    1176                 :            :       // Shared terms manager will assert to interested theories directly, as
    1177                 :            :       // the terms become shared
    1178                 :    9168986 :       assertToTheory(literal, literal, /* to */ THEORY_BUILTIN, /* from */ THEORY_SAT_SOLVER);
    1179                 :            : 
    1180                 :            :       // Now, let's check for any atom triggers from lemmas
    1181                 :    9168986 :       AtomRequests::atom_iterator it = d_atomRequests.getAtomIterator(atom);
    1182         [ +  + ]:    9211128 :       while (!it.done()) {
    1183                 :      42142 :         const AtomRequests::Request& request = it.get();
    1184                 :            :         Node toAssert =
    1185         [ +  + ]:      42142 :             polarity ? (Node)request.d_atom : request.d_atom.notNode();
    1186         [ +  - ]:      84284 :         Trace("theory::atoms") << "TheoryEngine::assertFact(" << literal
    1187                 :      42142 :                                << "): sending requested " << toAssert << endl;
    1188                 :      42142 :         assertToTheory(
    1189                 :      42142 :             toAssert, literal, request.d_toTheory, THEORY_SAT_SOLVER);
    1190         [ +  + ]:      42142 :         if (options().theory.eeMode == options::EqEngineMode::CENTRAL)
    1191                 :            :         {
    1192                 :            :           // Also send to THEORY_BUILTIN, similar to above
    1193                 :         48 :           assertToTheory(toAssert,
    1194                 :            :                         literal,
    1195                 :            :                         /* to */ THEORY_BUILTIN,
    1196                 :            :                         /* from */ THEORY_SAT_SOLVER);
    1197                 :            :         }
    1198                 :      42142 :         it.next();
    1199                 :      42142 :       }
    1200                 :            :     }
    1201                 :            :     else
    1202                 :            :     {
    1203                 :            :       // Not an equality, just assert to the appropriate theory
    1204                 :    7441229 :       assertToTheory(literal,
    1205                 :            :                      literal,
    1206                 :    7441229 :                      /* to */ d_env.theoryOf(atom),
    1207                 :            :                      /* from */ THEORY_SAT_SOLVER);
    1208                 :            :     }
    1209                 :            :   }
    1210                 :            :   else
    1211                 :            :   {
    1212                 :            :     // Assert the fact to the appropriate theory directly
    1213                 :   11629725 :     assertToTheory(literal,
    1214                 :            :                    literal,
    1215                 :   11629725 :                    /* to */ d_env.theoryOf(atom),
    1216                 :            :                    /* from */ THEORY_SAT_SOLVER);
    1217                 :            :   }
    1218                 :   28239941 : }
    1219                 :            : 
    1220                 :   31321425 : bool TheoryEngine::propagate(TNode literal, theory::TheoryId theory) {
    1221         [ +  - ]:   62642850 :   Trace("theory::propagate")
    1222                 :   31321425 :       << "TheoryEngine::propagate(" << literal << ", " << theory << ")" << endl;
    1223                 :            : 
    1224                 :   62642850 :   Trace("dtview::prop") << std::string(context()->getLevel(), ' ')
    1225                 :   31321425 :                         << ":THEORY-PROP: " << literal << endl;
    1226                 :            : 
    1227                 :            :   // spendResource();
    1228                 :            : 
    1229                 :            :   // Get the atom
    1230                 :   31321425 :   bool polarity = literal.getKind() != Kind::NOT;
    1231         [ +  + ]:   31321425 :   TNode atom = polarity ? literal : literal[0];
    1232                 :            : 
    1233 [ +  + ][ +  + ]:   31321425 :   if (logicInfo().isSharingEnabled() && atom.getKind() == Kind::EQUAL)
                 [ +  + ]
    1234                 :            :   {
    1235         [ +  + ]:   22959767 :     if (d_propEngine->isSatLiteral(literal)) {
    1236                 :            :       // We propagate SAT literals to SAT
    1237                 :   18670045 :       assertToTheory(literal, literal, /* to */ THEORY_SAT_SOLVER, /* from */ theory);
    1238                 :            :     }
    1239         [ +  + ]:   22959767 :     if (theory != THEORY_BUILTIN) {
    1240                 :            :       // Assert to the shared terms database
    1241                 :   13291613 :       assertToTheory(literal, literal, /* to */ THEORY_BUILTIN, /* from */ theory);
    1242                 :            :     }
    1243                 :            :   }
    1244                 :            :   else
    1245                 :            :   {
    1246                 :            :     // Just send off to the SAT solver
    1247 [ -  + ][ -  + ]:    8361658 :     Assert(d_propEngine->isSatLiteral(literal));
                 [ -  - ]
    1248                 :    8361658 :     assertToTheory(literal, literal, /* to */ THEORY_SAT_SOLVER, /* from */ theory);
    1249                 :            :   }
    1250                 :            : 
    1251                 :   62642850 :   return !d_inConflict;
    1252                 :   31321425 : }
    1253                 :            : 
    1254                 :    2070676 : theory::EqualityStatus TheoryEngine::getEqualityStatus(TNode a, TNode b)
    1255                 :            : {
    1256 [ -  + ][ -  + ]:    2070676 :   Assert(a.getType() == b.getType());
                 [ -  - ]
    1257                 :    2070676 :   return d_sharedSolver->getEqualityStatus(a, b);
    1258                 :            : }
    1259                 :            : 
    1260                 :        454 : void TheoryEngine::getDifficultyMap(std::map<Node, Node>& dmap,
    1261                 :            :                                     bool includeLemmas)
    1262                 :            : {
    1263 [ -  + ][ -  + ]:        454 :   Assert(d_relManager != nullptr);
                 [ -  - ]
    1264                 :        454 :   d_relManager->getDifficultyMap(dmap, includeLemmas);
    1265                 :        454 : }
    1266                 :            : 
    1267                 :       1758 : theory::IncompleteId TheoryEngine::getModelUnsoundId() const
    1268                 :            : {
    1269                 :       1758 :   return d_modelUnsoundId.get();
    1270                 :            : }
    1271                 :         15 : theory::IncompleteId TheoryEngine::getRefutationUnsoundId() const
    1272                 :            : {
    1273                 :         15 :   return d_refutationUnsoundId.get();
    1274                 :            : }
    1275                 :            : 
    1276                 :      13344 : Node TheoryEngine::getCandidateModelValue(TNode var)
    1277                 :            : {
    1278         [ +  + ]:      13344 :   if (var.isConst())
    1279                 :            :   {
    1280                 :            :     // the model value of a constant must be itself
    1281                 :         18 :     return var;
    1282                 :            :   }
    1283 [ -  + ][ -  - ]:      26652 :   Assert(d_sharedSolver->isShared(var))
    1284 [ -  + ][ -  + ]:      13326 :       << "node " << var << " is not shared" << std::endl;
                 [ -  - ]
    1285                 :      13326 :   return theoryOf(d_env.theoryOf(var.getType()))->getCandidateModelValue(var);
    1286                 :            : }
    1287                 :            : 
    1288                 :          0 : std::unordered_set<TNode> TheoryEngine::getRelevantAssertions(bool& success)
    1289                 :            : {
    1290                 :            :   // if there is no relevance manager, we fail
    1291         [ -  - ]:          0 :   if (d_relManager == nullptr)
    1292                 :            :   {
    1293                 :          0 :     success = false;
    1294                 :            :     // return empty set
    1295                 :          0 :     return std::unordered_set<TNode>();
    1296                 :            :   }
    1297                 :          0 :   return d_relManager->getRelevantAssertions(success);
    1298                 :            : }
    1299                 :            : 
    1300                 :     266180 : TrustNode TheoryEngine::getExplanation(TNode node)
    1301                 :            : {
    1302         [ +  - ]:     532360 :   Trace("theory::explain") << "TheoryEngine::getExplanation(" << node
    1303                 :          0 :                            << "): current propagation index = "
    1304                 :     266180 :                            << d_propagationMapTimestamp << endl;
    1305                 :     266180 :   bool polarity = node.getKind() != Kind::NOT;
    1306         [ +  + ]:     266180 :   TNode atom = polarity ? node : node[0];
    1307                 :            : 
    1308                 :            :   // If we're not in shared mode, explanations are simple
    1309                 :     266180 :   TrustNode texplanation;
    1310         [ +  + ]:     266180 :   if (!logicInfo().isSharingEnabled())
    1311                 :            :   {
    1312         [ +  - ]:     169186 :     Trace("theory::explain")
    1313                 :          0 :         << "TheoryEngine::getExplanation: sharing is NOT enabled. "
    1314 [ -  + ][ -  - ]:      84593 :         << " Responsible theory is: " << theoryOf(atom)->getId() << std::endl;
    1315                 :            : 
    1316                 :      84593 :     texplanation = theoryOf(atom)->explain(node);
    1317                 :      84593 :     Node explanation = texplanation.getNode();
    1318         [ +  - ]:     169186 :     Trace("theory::explain") << "TheoryEngine::getExplanation(" << node
    1319                 :      84593 :                              << ") => " << explanation << endl;
    1320         [ +  + ]:      84593 :     if (isProofEnabled())
    1321                 :            :     {
    1322                 :      39984 :       texplanation.debugCheckClosed(
    1323                 :            :           options(), "te-proof-exp", "texplanation no share", false);
    1324                 :            :       // check if no generator, if so, add THEORY_LEMMA
    1325         [ -  + ]:      39984 :       if (texplanation.getGenerator() == nullptr)
    1326                 :            :       {
    1327                 :          0 :         Node proven = texplanation.getProven();
    1328                 :          0 :         TheoryId tid = theoryOf(atom)->getId();
    1329                 :            :         Node tidn = builtin::BuiltinProofRuleChecker::mkTheoryIdNode(
    1330                 :          0 :             nodeManager(), tid);
    1331                 :          0 :         d_lazyProof->addTrustedStep(proven, TrustId::THEORY_LEMMA, {}, {tidn});
    1332                 :            :         texplanation =
    1333         [ -  - ]:          0 :             TrustNode::mkTrustPropExp(node, explanation, d_lazyProof.get());
    1334                 :          0 :       }
    1335                 :            :     }
    1336                 :      84593 :   }
    1337                 :            :   else
    1338                 :            :   {
    1339         [ +  - ]:     363174 :     Trace("theory::explain")
    1340                 :     181587 :         << "TheoryEngine::getExplanation: sharing IS enabled" << std::endl;
    1341                 :            : 
    1342                 :            :     // Initial thing to explain
    1343                 :            :     NodeTheoryPair toExplain(
    1344                 :     181587 :         node, THEORY_SAT_SOLVER, d_propagationMapTimestamp);
    1345 [ -  + ][ -  + ]:     181587 :     Assert(d_propagationMap.find(toExplain) != d_propagationMap.end());
                 [ -  - ]
    1346                 :            : 
    1347                 :     181587 :     NodeTheoryPair nodeExplainerPair = d_propagationMap[toExplain];
    1348         [ +  - ]:     363174 :     Trace("theory::explain")
    1349                 :          0 :         << "TheoryEngine::getExplanation: explainer for node "
    1350                 :          0 :         << nodeExplainerPair.d_node
    1351                 :     181587 :         << " is theory: " << nodeExplainerPair.d_theory << std::endl;
    1352                 :            : 
    1353                 :            :     // Create the workplace for explanations
    1354                 :     544761 :     std::vector<NodeTheoryPair> vec{d_propagationMap[toExplain]};
    1355                 :            :     // Process the explanation
    1356                 :     181587 :     texplanation = getExplanation(vec);
    1357         [ +  - ]:     363174 :     Trace("theory::explain") << "TheoryEngine::getExplanation(" << node
    1358 [ -  + ][ -  - ]:     181587 :                              << ") => " << texplanation.getNode() << endl;
    1359                 :     181587 :   }
    1360                 :            :   // notify the conflict as a lemma
    1361         [ +  + ]:     266216 :   for (TheoryEngineModule* tem : d_modules)
    1362                 :            :   {
    1363                 :         36 :     tem->notifyLemma(texplanation.getProven(),
    1364                 :            :                      InferenceId::EXPLAINED_PROPAGATION,
    1365                 :            :                      LemmaProperty::NONE,
    1366                 :            :                      {},
    1367                 :            :                      {});
    1368                 :            :   }
    1369                 :     532360 :   return texplanation;
    1370                 :     266180 : }
    1371                 :            : 
    1372                 :            : struct AtomsCollect {
    1373                 :            : 
    1374                 :            :   std::vector<TNode> d_atoms;
    1375                 :            :   std::unordered_set<TNode> d_visited;
    1376                 :            : 
    1377                 :            :  public:
    1378                 :            :   typedef void return_type;
    1379                 :            : 
    1380                 :    1007720 :   bool alreadyVisited(TNode current, CVC5_UNUSED TNode parent)
    1381                 :            :   {
    1382                 :            :     // Check if already visited
    1383         [ +  + ]:    1007720 :     if (d_visited.find(current) != d_visited.end()) return true;
    1384                 :            :     // Don't visit non-boolean
    1385         [ +  + ]:     925254 :     if (!current.getType().isBoolean()) return true;
    1386                 :            :     // New node
    1387                 :     756446 :     return false;
    1388                 :            :   }
    1389                 :            : 
    1390                 :     252582 :   void visit(TNode current, CVC5_UNUSED TNode parent)
    1391                 :            :   {
    1392         [ +  + ]:     252582 :     if (Theory::theoryOf(current) != theory::THEORY_BOOL) {
    1393                 :      86344 :       d_atoms.push_back(current);
    1394                 :            :     }
    1395                 :     252582 :     d_visited.insert(current);
    1396                 :     252582 :   }
    1397                 :            : 
    1398                 :      83766 :   void start(CVC5_UNUSED TNode node) {}
    1399                 :      83766 :   void done(CVC5_UNUSED TNode node) {}
    1400                 :            : 
    1401                 :      83766 :   std::vector<TNode> getAtoms() const {
    1402                 :      83766 :     return d_atoms;
    1403                 :            :   }
    1404                 :            : };
    1405                 :            : 
    1406                 :      83766 : void TheoryEngine::ensureLemmaAtoms(TNode n, theory::TheoryId atomsTo)
    1407                 :            : {
    1408 [ -  + ][ -  + ]:      83766 :   Assert(atomsTo != THEORY_LAST);
                 [ -  - ]
    1409         [ +  - ]:     167532 :   Trace("theory::atoms") << "TheoryEngine::ensureLemmaAtoms(" << n << ", "
    1410                 :      83766 :                          << atomsTo << ")" << endl;
    1411                 :      83766 :   AtomsCollect collectAtoms;
    1412                 :      83766 :   NodeVisitor<AtomsCollect>::run(collectAtoms, n);
    1413                 :      83766 :   ensureLemmaAtoms(collectAtoms.getAtoms(), atomsTo);
    1414                 :      83766 : }
    1415                 :            : 
    1416                 :      83766 : void TheoryEngine::ensureLemmaAtoms(const std::vector<TNode>& atoms, theory::TheoryId atomsTo) {
    1417         [ +  + ]:     170110 :   for (unsigned i = 0; i < atoms.size(); ++ i) {
    1418                 :            : 
    1419                 :            :     // Non-equality atoms are either owned by theory or they don't make sense
    1420         [ +  + ]:      86344 :     if (atoms[i].getKind() != Kind::EQUAL)
    1421                 :            :     {
    1422                 :      71106 :       continue;
    1423                 :            :     }
    1424                 :            : 
    1425                 :            :     // The equality
    1426                 :      82464 :     Node eq = atoms[i];
    1427                 :            :     // Simple normalization to not repeat stuff
    1428         [ -  + ]:      82464 :     if (eq[0] > eq[1]) {
    1429                 :          0 :       eq = eq[1].eqNode(eq[0]);
    1430                 :            :     }
    1431                 :            : 
    1432                 :            :     // Rewrite the equality
    1433                 :      82464 :     Node eqNormalized = rewrite(atoms[i]);
    1434                 :            : 
    1435         [ +  - ]:     164928 :     Trace("theory::atoms") << "TheoryEngine::ensureLemmaAtoms(): " << eq
    1436                 :      82464 :                            << " with nf " << eqNormalized << endl;
    1437                 :            : 
    1438                 :            :     // If the equality is a boolean constant, we send immediately
    1439         [ +  + ]:      82464 :     if (eqNormalized.isConst()) {
    1440         [ -  + ]:          2 :       if (eqNormalized.getConst<bool>()) {
    1441                 :          0 :         assertToTheory(eq, eqNormalized, /** to */ atomsTo, /** Sat solver */ theory::THEORY_SAT_SOLVER);
    1442                 :            :       } else {
    1443                 :          2 :         assertToTheory(eq.notNode(), eqNormalized.notNode(), /** to */ atomsTo, /** Sat solver */ theory::THEORY_SAT_SOLVER);
    1444                 :            :       }
    1445                 :          2 :       continue;
    1446                 :            :     }
    1447         [ -  + ]:      82462 :     else if (eqNormalized.getKind() != Kind::EQUAL)
    1448                 :            :     {
    1449                 :          0 :       Assert(eqNormalized.getKind() == Kind::SKOLEM
    1450                 :            :              || (eqNormalized.getKind() == Kind::NOT
    1451                 :            :                  && eqNormalized[0].getKind() == Kind::SKOLEM));
    1452                 :            :       // this happens for Boolean term equalities V = true that are rewritten to V, we should skip
    1453                 :            :       //  TODO : revisit this
    1454                 :          0 :       continue;
    1455                 :            :     }
    1456                 :            : 
    1457                 :            :     // If the normalization did the just flips, keep the flip
    1458                 :      82462 :     if (eqNormalized[0] == eq[1] && eqNormalized[1] == eq[0]) {
    1459                 :       1535 :       eq = eqNormalized;
    1460                 :            :     }
    1461                 :            : 
    1462                 :            :     // Check if the equality is already known by the sat solver
    1463         [ +  + ]:      82462 :     if (d_propEngine->isSatLiteral(eqNormalized)) {
    1464                 :            :       bool value;
    1465         [ +  + ]:      69351 :       if (d_propEngine->hasValue(eqNormalized, value)) {
    1466         [ +  + ]:      67224 :         if (value) {
    1467                 :      66419 :           assertToTheory(eq, eqNormalized, atomsTo, theory::THEORY_SAT_SOLVER);
    1468                 :      67224 :           continue;
    1469                 :            :         } else {
    1470                 :        805 :           assertToTheory(eq.notNode(), eqNormalized.notNode(), atomsTo, theory::THEORY_SAT_SOLVER);
    1471                 :        805 :           continue;
    1472                 :            :         }
    1473                 :            :       }
    1474                 :            :     }
    1475                 :            : 
    1476                 :            :     // If the theory is asking about a different form, or the form is ok but if will go to a different theory
    1477                 :            :     // then we must figure it out
    1478 [ +  + ][ +  + ]:      15238 :     if (eqNormalized != eq || d_env.theoryOf(eq) != atomsTo)
         [ +  + ][ +  + ]
                 [ -  - ]
    1479                 :            :     {
    1480                 :            :       // If you get eqNormalized, send atoms[i] to atomsTo
    1481                 :      12551 :       d_atomRequests.add(eqNormalized, eq, atomsTo);
    1482                 :            :     }
    1483 [ +  + ][ +  + ]:     149690 :   }
    1484                 :      83766 : }
    1485                 :            : 
    1486                 :     896906 : void TheoryEngine::lemma(TrustNode tlemma,
    1487                 :            :                          InferenceId id,
    1488                 :            :                          LemmaProperty p,
    1489                 :            :                          TheoryId from)
    1490                 :            : {
    1491                 :            :   // For resource-limiting (also does a time check).
    1492                 :            :   // spendResource();
    1493 [ +  + ][ +  - ]:     896906 :   Assert(tlemma.getKind() == TrustNodeKind::LEMMA
         [ -  + ][ -  + ]
                 [ -  - ]
    1494                 :            :          || tlemma.getKind() == TrustNodeKind::CONFLICT);
    1495                 :            : 
    1496                 :            :   // minimize or generalize conflict
    1497         [ +  + ]:     896906 :   if (d_cp)
    1498                 :            :   {
    1499                 :        135 :     TrustNode tproc = d_cp->processLemma(tlemma);
    1500         [ +  + ]:        135 :     if (!tproc.isNull())
    1501                 :            :     {
    1502                 :          7 :       tlemma = tproc;
    1503                 :            :     }
    1504                 :        135 :   }
    1505                 :            : 
    1506                 :            :   // get the node
    1507                 :     896906 :   Node node = tlemma.getNode();
    1508                 :     896906 :   Node lemma = tlemma.getProven();
    1509                 :            : 
    1510                 :            :   // must rewrite when checking here since we may have shadowing in rare cases,
    1511                 :            :   // e.g. lazy lambda lifting lemmas
    1512 [ -  + ][ -  - ]:    1793812 :   Assert(!expr::hasFreeVar(rewrite(lemma)))
    1513 [ -  + ][ -  + ]:     896906 :       << "Lemma " << lemma << " from " << from << " has a free variable";
                 [ -  - ]
    1514                 :            : 
    1515                 :            :   // when proofs are enabled, we ensure the trust node has a generator by
    1516                 :            :   // adding a trust step to the lazy proof maintained by this class
    1517         [ +  + ]:     896906 :   if (isProofEnabled())
    1518                 :            :   {
    1519                 :            :     // ensure proof: set THEORY_LEMMA if no generator is provided
    1520         [ +  + ]:     385612 :     if (tlemma.getGenerator() == nullptr)
    1521                 :            :     {
    1522                 :            :       // add theory lemma step to proof
    1523                 :            :       Node tidn =
    1524                 :      46766 :           builtin::BuiltinProofRuleChecker::mkTheoryIdNode(nodeManager(), from);
    1525                 :      93532 :       d_lazyProof->addTrustedStep(lemma, TrustId::THEORY_LEMMA, {}, {tidn});
    1526                 :            :       // update the trust node
    1527         [ +  - ]:      46766 :       tlemma = TrustNode::mkTrustLemma(lemma, d_lazyProof.get());
    1528                 :      46766 :     }
    1529                 :            :     // ensure closed
    1530                 :     385612 :     tlemma.debugCheckClosed(
    1531                 :            :         options(), "te-proof-debug", "TheoryEngine::lemma_initial");
    1532                 :            :   }
    1533                 :            : 
    1534                 :            :   // assert the lemma
    1535                 :     896907 :   d_propEngine->assertLemma(id, tlemma, p);
    1536                 :            : 
    1537                 :            :   // If specified, we must add this lemma to the set of those that need to be
    1538                 :            :   // justified, where note we pass all auxiliary lemmas in skAsserts as well,
    1539                 :            :   // since these by extension must be justified as well.
    1540         [ +  + ]:     896905 :   if (!d_modules.empty())
    1541                 :            :   {
    1542                 :        963 :     std::vector<Node> skAsserts;
    1543                 :        963 :     std::vector<Node> sks;
    1544                 :            :     Node retLemma =
    1545                 :       1926 :         d_propEngine->getPreprocessedTerm(tlemma.getProven(), skAsserts, sks);
    1546                 :            : 
    1547                 :            :     // notify the modules of the lemma
    1548         [ +  + ]:       1926 :     for (TheoryEngineModule* tem : d_modules)
    1549                 :            :     {
    1550                 :            :       // don't notify theory modules of their own lemmas
    1551         [ +  + ]:        963 :       if (tem->getId() != from)
    1552                 :            :       {
    1553                 :        950 :         tem->notifyLemma(retLemma, id, p, skAsserts, sks);
    1554                 :            :       }
    1555                 :            :     }
    1556                 :        963 :   }
    1557                 :            : 
    1558                 :            :   // Mark that we added some lemmas
    1559                 :     896905 :   d_lemmasAdded = true;
    1560                 :     896907 : }
    1561                 :            : 
    1562                 :     377373 : void TheoryEngine::markInConflict()
    1563                 :            : {
    1564                 :            : #ifdef CVC5_FOR_EACH_THEORY_STATEMENT
    1565                 :            : #undef CVC5_FOR_EACH_THEORY_STATEMENT
    1566                 :            : #endif
    1567                 :            : #define CVC5_FOR_EACH_THEORY_STATEMENT(THEORY) \
    1568                 :            :   theoryOf(THEORY)->notifyInConflict();
    1569                 :     377373 :   CVC5_FOR_EACH_THEORY;
    1570                 :     377373 :   d_inConflict = true;
    1571                 :     377373 : }
    1572                 :            : 
    1573                 :     197643 : void TheoryEngine::conflict(TrustNode tconflict,
    1574                 :            :                             InferenceId id,
    1575                 :            :                             TheoryId theoryId)
    1576                 :            : {
    1577 [ -  + ][ -  + ]:     197643 :   Assert(tconflict.getKind() == TrustNodeKind::CONFLICT);
                 [ -  - ]
    1578                 :            : 
    1579                 :     197643 :   TNode conflict = tconflict.getNode();
    1580         [ +  - ]:     395286 :   Trace("theory::conflict") << "TheoryEngine::conflict(" << conflict << ", "
    1581                 :     197643 :                             << id << ", " << theoryId << ")" << endl;
    1582         [ +  - ]:     197643 :   Trace("te-proof-debug") << "Check closed conflict" << std::endl;
    1583                 :            :   // doesn't require proof generator, yet, since THEORY_LEMMA is added below
    1584                 :     197643 :   tconflict.debugCheckClosed(
    1585                 :            :       options(), "te-proof-debug", "TheoryEngine::conflict_initial", false);
    1586                 :            : 
    1587         [ +  - ]:     197643 :   Trace("dtview::conflict") << ":THEORY-CONFLICT: " << conflict << std::endl;
    1588                 :            : 
    1589                 :            :   // Mark that we are in conflict
    1590                 :     197643 :   markInConflict();
    1591                 :            : 
    1592                 :            :   // In the multiple-theories case, we need to reconstruct the conflict
    1593         [ +  + ]:     197643 :   if (logicInfo().isSharingEnabled())
    1594                 :            :   {
    1595                 :            :     // Create the workplace for explanations
    1596                 :     160810 :     std::vector<NodeTheoryPair> vec;
    1597                 :     160810 :     vec.push_back(
    1598                 :     321620 :         NodeTheoryPair(conflict, theoryId, d_propagationMapTimestamp));
    1599                 :            : 
    1600                 :            :     // Process the explanation
    1601                 :     160810 :     TrustNode tncExp = getExplanation(vec);
    1602                 :     160810 :     Node fullConflict = tncExp.getNode();
    1603                 :            : 
    1604         [ +  + ]:     160810 :     if (isProofEnabled())
    1605                 :            :     {
    1606         [ +  - ]:     135070 :       Trace("te-proof-debug")
    1607                 :      67535 :           << "Check closed conflict explained with sharing" << std::endl;
    1608                 :      67535 :       tncExp.debugCheckClosed(options(),
    1609                 :            :                               "te-proof-debug",
    1610                 :            :                               "TheoryEngine::conflict_explained_sharing");
    1611         [ +  - ]:      67535 :       Trace("te-proof-debug") << "Process conflict: " << conflict << std::endl;
    1612         [ +  - ]:     135070 :       Trace("te-proof-debug") << "Conflict " << tconflict << " from "
    1613 [ -  + ][ -  - ]:      67535 :                               << tconflict.identifyGenerator() << std::endl;
    1614         [ +  - ]:     135070 :       Trace("te-proof-debug") << "Explanation " << tncExp << " from "
    1615 [ -  + ][ -  - ]:      67535 :                               << tncExp.identifyGenerator() << std::endl;
    1616 [ -  + ][ -  + ]:      67535 :       Assert(d_lazyProof != nullptr);
                 [ -  - ]
    1617         [ +  + ]:      67535 :       if (tconflict.getGenerator() != nullptr)
    1618                 :            :       {
    1619                 :      66257 :         d_lazyProof->addLazyStep(tconflict.getProven(),
    1620                 :            :                                  tconflict.getGenerator());
    1621                 :            :       }
    1622                 :            :       else
    1623                 :            :       {
    1624                 :            :         // add theory lemma step
    1625                 :            :         Node tidn = builtin::BuiltinProofRuleChecker::mkTheoryIdNode(
    1626                 :       1278 :             nodeManager(), theoryId);
    1627                 :       1278 :         Node conf = tconflict.getProven();
    1628                 :       2556 :         d_lazyProof->addTrustedStep(conf, TrustId::THEORY_LEMMA, {}, {tidn});
    1629                 :       1278 :       }
    1630                 :            :       // store the explicit step, which should come from a different
    1631                 :            :       // generator, e.g. d_tepg.
    1632                 :      67535 :       Node proven = tncExp.getProven();
    1633 [ +  - ][ -  + ]:      67535 :       Assert(tncExp.getGenerator() != d_lazyProof.get());
         [ -  + ][ -  - ]
    1634 [ +  - ][ -  + ]:     135070 :       Trace("te-proof-debug") << "add lazy step " << tncExp.identifyGenerator()
                 [ -  - ]
    1635                 :      67535 :                               << " for " << proven << std::endl;
    1636                 :      67535 :       d_lazyProof->addLazyStep(proven, tncExp.getGenerator());
    1637         [ +  - ]:      67535 :       pfgEnsureClosed(options(),
    1638                 :            :                       proven,
    1639                 :      67535 :                       d_lazyProof.get(),
    1640                 :            :                       "te-proof-debug",
    1641                 :            :                       "TheoryEngine::conflict_during");
    1642                 :      67535 :       Node fullConflictNeg = fullConflict.notNode();
    1643                 :      67535 :       std::vector<Node> children;
    1644                 :      67535 :       children.push_back(proven);
    1645                 :      67535 :       std::vector<Node> args;
    1646                 :      67535 :       args.push_back(fullConflictNeg);
    1647         [ +  + ]:      67535 :       if (conflict == d_false)
    1648                 :            :       {
    1649 [ -  + ][ -  + ]:        554 :         AlwaysAssert(proven == fullConflictNeg);
                 [ -  - ]
    1650                 :            :       }
    1651                 :            :       else
    1652                 :            :       {
    1653         [ +  + ]:      66981 :         if (!CDProof::isSame(fullConflict, conflict))
    1654                 :            :         {
    1655                 :            :           // ------------------------- explained  
    1656                 :            :           // fullConflict => conflict             
    1657                 :            :           // ------------------------- IMPLIES_ELIM  ---------- from theory
    1658                 :            :           // ~fullConflict V conflict                ~conflict
    1659                 :            :           // -------------------------------------------------- RESOLUTION
    1660                 :            :           // ~fullConflict
    1661                 :     126786 :           Node provenOr = nodeManager()->mkNode(Kind::OR, proven[0].notNode(), proven[1]);
    1662                 :     126786 :           d_lazyProof->addStep(provenOr,
    1663                 :            :                                ProofRule::IMPLIES_ELIM,
    1664                 :            :                                {proven},
    1665                 :            :                                {});
    1666                 :     380358 :           d_lazyProof->addStep(fullConflictNeg,
    1667                 :            :                                ProofRule::RESOLUTION,
    1668                 :            :                                {provenOr, conflict.notNode()},
    1669                 :      63393 :                                {d_true, conflict});
    1670                 :      63393 :         }
    1671                 :            :       }
    1672                 :      67535 :     }
    1673                 :            :     // pass the processed trust node
    1674                 :            :     TrustNode tconf =
    1675         [ +  + ]:     160810 :         TrustNode::mkTrustConflict(fullConflict, d_lazyProof.get());
    1676         [ +  - ]:     321620 :     Trace("theory::conflict")
    1677                 :          0 :         << "TheoryEngine::conflict(" << conflict << ", " << theoryId
    1678                 :     160810 :         << "): full = " << fullConflict << endl;
    1679 [ -  + ][ -  + ]:     160810 :     Assert(properConflict(fullConflict));
                 [ -  - ]
    1680         [ +  - ]:     321620 :     Trace("te-proof-debug")
    1681                 :     160810 :         << "Check closed conflict with sharing" << std::endl;
    1682         [ +  + ]:     160810 :     if (isProofEnabled())
    1683                 :            :     {
    1684                 :      67535 :       tconf.debugCheckClosed(
    1685                 :            :           options(), "te-proof-debug", "TheoryEngine::conflict:sharing");
    1686                 :            :     }
    1687                 :     160810 :     lemma(tconf, id, LemmaProperty::NONE, theoryId);
    1688                 :     160810 :   }
    1689                 :            :   else
    1690                 :            :   {
    1691                 :            :     // When only one theory, the conflict should need no processing
    1692 [ -  + ][ -  + ]:      36833 :     Assert(properConflict(conflict));
                 [ -  - ]
    1693                 :            :     // pass the trust node that was sent from the theory
    1694                 :      36833 :     lemma(tconflict, id, LemmaProperty::NONE, theoryId);
    1695                 :            :   }
    1696                 :     197643 : }
    1697                 :            : 
    1698                 :          0 : void TheoryEngine::setModelUnsound(theory::IncompleteId id)
    1699                 :            : {
    1700                 :          0 :   setModelUnsound(TheoryId::THEORY_NONE, id);
    1701                 :          0 : }
    1702                 :            : 
    1703                 :         42 : void TheoryEngine::setRefutationUnsound(theory::IncompleteId id)
    1704                 :            : {
    1705                 :         42 :   setRefutationUnsound(TheoryId::THEORY_NONE, id);
    1706                 :         42 : }
    1707                 :            : 
    1708                 :       7980 : void TheoryEngine::setModelUnsound(theory::TheoryId theory,
    1709                 :            :                                    theory::IncompleteId id)
    1710                 :            : {
    1711                 :       7980 :   d_modelUnsound = true;
    1712                 :       7980 :   d_modelUnsoundTheory = theory;
    1713                 :       7980 :   d_modelUnsoundId = id;
    1714                 :       7980 : }
    1715                 :            : 
    1716                 :        169 : void TheoryEngine::setRefutationUnsound(theory::TheoryId theory,
    1717                 :            :                                         theory::IncompleteId id)
    1718                 :            : {
    1719                 :        169 :   d_refutationUnsound = true;
    1720                 :        169 :   d_refutationUnsoundTheory = theory;
    1721                 :        169 :   d_refutationUnsoundId = id;
    1722                 :        169 : }
    1723                 :            : 
    1724                 :     342397 : TrustNode TheoryEngine::getExplanation(
    1725                 :            :     std::vector<NodeTheoryPair>& explanationVector)
    1726                 :            : {
    1727 [ -  + ][ -  + ]:     342397 :   Assert(explanationVector.size() == 1);
                 [ -  - ]
    1728                 :     342397 :   Node conclusion = explanationVector[0].d_node;
    1729                 :            :   // if the theory explains using the central equality engine, we always start
    1730                 :            :   // with THEORY_BUILTIN.
    1731                 :     684794 :   explanationVector[0].d_theory =
    1732                 :     342397 :       theoryExpPropagation(explanationVector[0].d_theory);
    1733                 :     342397 :   std::shared_ptr<LazyCDProof> lcp;
    1734         [ +  + ]:     342397 :   if (isProofEnabled())
    1735                 :            :   {
    1736         [ +  - ]:     270516 :     Trace("te-proof-exp") << "=== TheoryEngine::getExplanation " << conclusion
    1737                 :     135258 :                           << std::endl;
    1738                 :            :     // We do not use auto-symmetry in this proof, since in very rare cases, it
    1739                 :            :     // is possible that the proof of explanations is cyclic when considering
    1740                 :            :     // (dis)equalities modulo symmetry, where such a proof looks like:
    1741                 :            :     // x = y
    1742                 :            :     // -----
    1743                 :            :     //   A    ...
    1744                 :            :     // ----------
    1745                 :            :     //   y = x
    1746                 :            :     // Notice that this complication arises since propagations consider
    1747                 :            :     // equalities that are not in rewritten form. This complication would not
    1748                 :            :     // exist otherwise. It is the shared term database that introduces these
    1749                 :            :     // unrewritten equalities; it must do so since theory combination requires
    1750                 :            :     // communicating arrangements between shared terms, and the rewriter
    1751                 :            :     // for arithmetic equalities does not preserve terms, e.g. x=y may become
    1752                 :            :     // x+-1*y=0.
    1753                 :     270516 :     lcp.reset(new LazyCDProof(d_env,
    1754                 :            :                               nullptr,
    1755                 :            :                               nullptr,
    1756                 :            :                               "TheoryEngine::LazyCDProof::getExplanation",
    1757                 :     135258 :                               false));
    1758                 :            :   }
    1759                 :     342397 :   unsigned i = 0; // Index of the current literal we are processing
    1760                 :            : 
    1761                 :     342397 :   std::unique_ptr<std::set<Node>> inputAssertions = nullptr;
    1762                 :            :   // the overall explanation
    1763                 :     342397 :   std::set<TNode> exp;
    1764                 :            :   // vector of trust nodes to explain at the end
    1765                 :     342397 :   std::vector<std::pair<TheoryId, TrustNode>> texplains;
    1766                 :            :   // cache of nodes we have already explained by some theory
    1767                 :     342397 :   std::unordered_map<Node, size_t> cache;
    1768                 :            : 
    1769         [ +  + ]:    9240586 :   while (i < explanationVector.size()) {
    1770                 :            :     // Get the current literal to explain
    1771                 :    8898189 :     NodeTheoryPair toExplain = explanationVector[i];
    1772                 :            : 
    1773         [ +  - ]:   17796378 :     Trace("theory::explain")
    1774                 :          0 :         << "[i=" << i << "] TheoryEngine::explain(): processing ["
    1775                 :          0 :         << toExplain.d_timestamp << "] " << toExplain.d_node << " sent from "
    1776                 :    8898189 :         << toExplain.d_theory << endl;
    1777                 :            : 
    1778                 :    8898189 :     if (cache.find(toExplain.d_node) != cache.end()
    1779 [ +  + ][ +  + ]:    8898189 :         && cache[toExplain.d_node] < toExplain.d_timestamp)
                 [ +  + ]
    1780                 :            :     {
    1781                 :     277468 :       ++i;
    1782                 :     277468 :       continue;
    1783                 :            :     }
    1784                 :    8620721 :     cache[toExplain.d_node] = toExplain.d_timestamp;
    1785                 :            : 
    1786                 :            :     // If a true constant or a negation of a false constant we can ignore it
    1787         [ +  + ]:      30791 :     if ((toExplain.d_node.isConst() && toExplain.d_node.getConst<bool>())
    1788 [ +  + ][ +  + ]:    9325606 :         || (toExplain.d_node.getKind() == Kind::NOT
    1789 [ -  + ][ +  + ]:    9294815 :             && toExplain.d_node[0].isConst()
                 [ -  - ]
    1790 [ -  - ][ -  + ]:    8620721 :             && !toExplain.d_node[0].getConst<bool>()))
         [ +  + ][ -  - ]
    1791                 :            :     {
    1792                 :      29807 :       ++ i;
    1793                 :            :       // if we are building a proof
    1794         [ +  + ]:      29807 :       if (lcp != nullptr)
    1795                 :            :       {
    1796         [ +  - ]:       6402 :         Trace("te-proof-exp")
    1797                 :       3201 :             << "- explain " << toExplain.d_node << " trivially..." << std::endl;
    1798                 :            :         // ------------------MACRO_SR_PRED_INTRO
    1799                 :            :         // toExplain.d_node
    1800                 :       3201 :         std::vector<Node> children;
    1801                 :       3201 :         std::vector<Node> args;
    1802                 :       3201 :         args.push_back(toExplain.d_node);
    1803                 :       3201 :         lcp->addStep(
    1804                 :            :             toExplain.d_node, ProofRule::MACRO_SR_PRED_INTRO, children, args);
    1805                 :       3201 :       }
    1806                 :      29807 :       continue;
    1807                 :      29807 :     }
    1808                 :            : 
    1809                 :            :     // If from the SAT solver, keep it
    1810         [ +  + ]:    8590914 :     if (toExplain.d_theory == THEORY_SAT_SOLVER)
    1811                 :            :     {
    1812         [ +  - ]:    6389146 :       Trace("theory::explain")
    1813                 :    3194573 :           << "\tLiteral came from THEORY_SAT_SOLVER. Keeping it." << endl;
    1814                 :    3194573 :       exp.insert(explanationVector[i++].d_node);
    1815                 :            :       // it will be a free assumption in the proof
    1816         [ +  - ]:    3194573 :       Trace("te-proof-exp") << "- keep " << toExplain.d_node << std::endl;
    1817                 :    3194573 :       continue;
    1818                 :            :     }
    1819                 :            : 
    1820                 :            :     // If an and, expand it
    1821         [ +  + ]:    5396341 :     if (toExplain.d_node.getKind() == Kind::AND)
    1822                 :            :     {
    1823         [ +  - ]:    1416882 :       Trace("theory::explain")
    1824                 :          0 :           << "TheoryEngine::explain(): expanding " << toExplain.d_node
    1825                 :     708441 :           << " got from " << toExplain.d_theory << endl;
    1826                 :     708441 :       size_t nchild = toExplain.d_node.getNumChildren();
    1827         [ +  + ]:    4576333 :       for (size_t k = 0; k < nchild; ++k)
    1828                 :            :       {
    1829                 :            :         NodeTheoryPair newExplain(
    1830                 :    7735784 :             toExplain.d_node[k], toExplain.d_theory, toExplain.d_timestamp);
    1831                 :    3867892 :         explanationVector.push_back(newExplain);
    1832                 :    3867892 :       }
    1833         [ +  + ]:     708441 :       if (lcp != nullptr)
    1834                 :            :       {
    1835         [ +  - ]:     594070 :         Trace("te-proof-exp")
    1836                 :     297035 :             << "- AND expand " << toExplain.d_node << std::endl;
    1837                 :            :         // delay explanation, use a dummy trust node
    1838                 :            :         TrustNode tnAndExp = TrustNode::mkTrustPropExp(
    1839                 :     594070 :             toExplain.d_node, toExplain.d_node, nullptr);
    1840                 :     297035 :         texplains.push_back(
    1841                 :     594070 :             std::pair<TheoryId, TrustNode>(THEORY_LAST, tnAndExp));
    1842                 :     297035 :       }
    1843                 :     708441 :       ++ i;
    1844                 :     708441 :       continue;
    1845                 :     708441 :     }
    1846                 :            : 
    1847                 :            :     // See if it was sent to the theory by another theory
    1848                 :    4687900 :     PropagationMap::const_iterator find = d_propagationMap.find(toExplain);
    1849         [ +  + ]:    4687900 :     if (find != d_propagationMap.end()) {
    1850         [ +  - ]:    8912616 :       Trace("theory::explain")
    1851                 :          0 :           << "\tTerm was propagated by another theory (theory = "
    1852 [ -  + ][ -  - ]:    4456308 :           << getTheoryString((*find).second.d_theory) << ")" << std::endl;
    1853                 :            :       // There is some propagation, check if its a timely one
    1854         [ +  + ]:    4456308 :       if ((*find).second.d_timestamp < toExplain.d_timestamp)
    1855                 :            :       {
    1856         [ +  - ]:    8041974 :         Trace("theory::explain")
    1857                 :          0 :             << "\tRelevant timetsamp, pushing " << (*find).second.d_node
    1858                 :    4020987 :             << "to index = " << explanationVector.size() << std::endl;
    1859                 :    4020987 :         explanationVector.push_back((*find).second);
    1860                 :    4020987 :         ++i;
    1861                 :            : 
    1862         [ +  + ]:    4020987 :         if (lcp != nullptr)
    1863                 :            :         {
    1864         [ +  + ]:    1803383 :           if (toExplain.d_node != (*find).second.d_node)
    1865                 :            :           {
    1866         [ +  - ]:      22880 :             Trace("te-proof-exp")
    1867                 :          0 :                 << "- t-explained cached: " << toExplain.d_node << " by "
    1868                 :      11440 :                 << (*find).second.d_node << std::endl;
    1869                 :            :             // delay explanation, use a dummy trust node that says that
    1870                 :            :             // (*find).second.d_node explains toExplain.d_node.
    1871                 :            :             TrustNode tnRewExp = TrustNode::mkTrustPropExp(
    1872                 :      22880 :                 toExplain.d_node, (*find).second.d_node, nullptr);
    1873                 :      11440 :             texplains.push_back(
    1874                 :      22880 :                 std::pair<TheoryId, TrustNode>(THEORY_LAST, tnRewExp));
    1875                 :      11440 :           }
    1876                 :            :         }
    1877                 :    4020987 :         continue;
    1878                 :    4020987 :       }
    1879                 :            :     }
    1880                 :            :     // It was produced by the theory, so ask for an explanation
    1881                 :            :     TrustNode texplanation =
    1882                 :     666913 :         d_sharedSolver->explain(toExplain.d_node, toExplain.d_theory);
    1883         [ +  + ]:     666913 :     if (lcp != nullptr)
    1884                 :            :     {
    1885                 :     283727 :       texplanation.debugCheckClosed(
    1886                 :            :           options(), "te-proof-exp", "texplanation", false);
    1887         [ +  - ]:     567454 :       Trace("te-proof-exp")
    1888                 :          0 :           << "- t-explained[" << toExplain.d_theory << "]: " << toExplain.d_node
    1889 [ -  + ][ -  - ]:     283727 :           << " by " << texplanation.getNode() << std::endl;
    1890                 :            :       // should prove the propagation we asked for
    1891                 :     283727 :       Assert(texplanation.getKind() == TrustNodeKind::PROP_EXP
    1892                 :            :              && texplanation.getProven()[1] == toExplain.d_node);
    1893                 :            :       // We add it to the list of theory explanations, to be processed at
    1894                 :            :       // the end of this method. We wait to explain here because it may
    1895                 :            :       // be that a later explanation may preempt the need for proving this
    1896                 :            :       // step. For instance, if the conclusion lit is later added as an
    1897                 :            :       // assumption in the final explanation. This avoids cyclic proofs.
    1898                 :     283727 :       texplains.push_back(
    1899                 :     567454 :           std::pair<TheoryId, TrustNode>(toExplain.d_theory, texplanation));
    1900                 :            :     }
    1901                 :     666913 :     Node explanation = texplanation.getNode();
    1902                 :            : 
    1903         [ +  - ]:    1333826 :     Trace("theory::explain")
    1904                 :          0 :         << "TheoryEngine::explain(): got explanation " << explanation
    1905                 :     666913 :         << " got from " << toExplain.d_theory << endl;
    1906                 :     666913 :     Assert(explanation != toExplain.d_node)
    1907                 :            :         << "wasn't sent to you, so why are you explaining it trivially, for "
    1908                 :          0 :            "fact "
    1909                 :            :         << explanation;
    1910                 :            :     // Mark the explanation
    1911                 :            :     NodeTheoryPair newExplain(
    1912                 :     666913 :         explanation, toExplain.d_theory, toExplain.d_timestamp);
    1913                 :     666913 :     explanationVector.push_back(newExplain);
    1914                 :            : 
    1915                 :     666913 :     ++ i;
    1916         [ +  + ]:    8898189 :   }
    1917                 :            : 
    1918                 :            :   // make the explanation node
    1919                 :     342397 :   Node expNode;
    1920         [ +  + ]:     342397 :   if (exp.size() == 0)
    1921                 :            :   {
    1922                 :            :     // Normalize to true
    1923                 :         72 :     expNode = nodeManager()->mkConst<bool>(true);
    1924                 :            :   }
    1925         [ +  + ]:     342325 :   else if (exp.size() == 1)
    1926                 :            :   {
    1927                 :            :     // All the same, or just one
    1928                 :      11887 :     expNode = *exp.begin();
    1929                 :            :   }
    1930                 :            :   else
    1931                 :            :   {
    1932                 :     330438 :     NodeBuilder conjunction(nodeManager(), Kind::AND);
    1933                 :     330438 :     std::set<TNode>::const_iterator it = exp.begin();
    1934                 :     330438 :     std::set<TNode>::const_iterator it_end = exp.end();
    1935         [ +  + ]:    3431666 :     while (it != it_end)
    1936                 :            :     {
    1937                 :    3101228 :       conjunction << *it;
    1938                 :    3101228 :       ++it;
    1939                 :            :     }
    1940                 :     330438 :     expNode = conjunction;
    1941                 :     330438 :   }
    1942                 :            :   // if we are building a proof, go back through the explanations and
    1943                 :            :   // build the proof
    1944         [ +  + ]:     342397 :   if (lcp != nullptr)
    1945                 :            :   {
    1946         [ -  + ]:     135258 :     if (TraceIsOn("te-proof-exp"))
    1947                 :            :     {
    1948         [ -  - ]:          0 :       Trace("te-proof-exp") << "Explanation is:" << std::endl;
    1949         [ -  - ]:          0 :       for (TNode e : exp)
    1950                 :            :       {
    1951         [ -  - ]:          0 :         Trace("te-proof-exp") << "  " << e << std::endl;
    1952                 :          0 :       }
    1953         [ -  - ]:          0 :       Trace("te-proof-exp") << "=== Replay explanations..." << std::endl;
    1954                 :            :     }
    1955                 :            :     // Now, go back and add the necessary steps of theory explanations, i.e.
    1956                 :            :     // add those that prove things that aren't in the final explanation. We
    1957                 :            :     // iterate in reverse order so that most recent steps take priority. This
    1958                 :            :     // avoids cyclic proofs in the lazy proof we are building (lcp).
    1959                 :     135258 :     for (std::vector<std::pair<TheoryId, TrustNode>>::reverse_iterator
    1960                 :     135258 :              it = texplains.rbegin(),
    1961                 :     135258 :              itEnd = texplains.rend();
    1962         [ +  + ]:     727460 :          it != itEnd;
    1963                 :     592202 :          ++it)
    1964                 :            :     {
    1965                 :     592202 :       TrustNode trn = it->second;
    1966 [ -  + ][ -  + ]:     592202 :       Assert(trn.getKind() == TrustNodeKind::PROP_EXP);
                 [ -  - ]
    1967                 :     592202 :       Node proven = trn.getProven();
    1968 [ -  + ][ -  + ]:     592202 :       Assert(proven.getKind() == Kind::IMPLIES);
                 [ -  - ]
    1969                 :     592202 :       Node tConc = proven[1];
    1970         [ +  - ]:     592202 :       Trace("te-proof-exp") << "- Process " << trn << std::endl;
    1971         [ +  + ]:     592202 :       if (exp.find(tConc) != exp.end())
    1972                 :            :       {
    1973                 :            :         // already added to proof
    1974         [ +  - ]:      20278 :         Trace("te-proof-exp") << "...already added" << std::endl;
    1975                 :      20278 :         continue;
    1976                 :            :       }
    1977                 :            :       // remember that we've explained this formula, to avoid cycles in lcp
    1978                 :     571924 :       exp.insert(tConc);
    1979                 :     571924 :       TheoryId ttid = it->first;
    1980                 :     571924 :       Node tExp = proven[0];
    1981         [ +  + ]:     571924 :       if (ttid == THEORY_LAST)
    1982                 :            :       {
    1983         [ +  + ]:     297830 :         if (tConc == tExp)
    1984                 :            :         {
    1985                 :            :           // dummy trust node, do AND expansion
    1986 [ -  + ][ -  + ]:     289978 :           Assert(tConc.getKind() == Kind::AND);
                 [ -  - ]
    1987                 :            :           // tConc[0] ... tConc[n]
    1988                 :            :           // ---------------------- AND_INTRO
    1989                 :            :           // tConc
    1990                 :     289978 :           std::vector<Node> pfChildren;
    1991                 :     289978 :           pfChildren.insert(pfChildren.end(), tConc.begin(), tConc.end());
    1992                 :     289978 :           lcp->addStep(tConc, ProofRule::AND_INTRO, pfChildren, {});
    1993         [ +  - ]:     289978 :           Trace("te-proof-exp") << "...via AND_INTRO" << std::endl;
    1994                 :     289978 :           continue;
    1995                 :     289978 :         }
    1996                 :            :         // otherwise should hold by rewriting
    1997 [ -  + ][ -  + ]:       7852 :         Assert(rewrite(tConc) == rewrite(tExp));
                 [ -  - ]
    1998                 :            :         // tExp
    1999                 :            :         // ---- MACRO_SR_PRED_TRANSFORM
    2000                 :            :         // tConc
    2001                 :      23556 :         lcp->addStep(
    2002                 :            :             tConc, ProofRule::MACRO_SR_PRED_TRANSFORM, {tExp}, {tConc});
    2003         [ +  - ]:       7852 :         Trace("te-proof-exp") << "...via MACRO_SR_PRED_TRANSFORM" << std::endl;
    2004                 :       7852 :         continue;
    2005                 :       7852 :       }
    2006         [ -  + ]:     274094 :       if (tExp == tConc)
    2007                 :            :       {
    2008                 :            :         // trivial
    2009         [ -  - ]:          0 :         Trace("te-proof-exp") << "...trivial" << std::endl;
    2010                 :          0 :         continue;
    2011                 :            :       }
    2012                 :            :       //       ------------- Via theory
    2013                 :            :       // tExp  tExp => tConc
    2014                 :            :       // ---------------------------------MODUS_PONENS
    2015                 :            :       // tConc
    2016         [ +  - ]:     274094 :       if (trn.getGenerator() != nullptr)
    2017                 :            :       {
    2018         [ +  - ]:     274094 :         Trace("te-proof-exp") << "...via theory generator" << std::endl;
    2019                 :     274094 :         lcp->addLazyStep(proven, trn.getGenerator());
    2020                 :            :       }
    2021                 :            :       else
    2022                 :            :       {
    2023         [ -  - ]:          0 :         Trace("te-proof-exp") << "...via trust THEORY_LEMMA" << std::endl;
    2024                 :            :         // otherwise, trusted theory lemma
    2025                 :            :         Node tidn = builtin::BuiltinProofRuleChecker::mkTheoryIdNode(
    2026                 :          0 :             nodeManager(), ttid);
    2027                 :          0 :         lcp->addTrustedStep(proven, TrustId::THEORY_LEMMA, {}, {tidn});
    2028                 :          0 :       }
    2029                 :     274094 :       std::vector<Node> pfChildren;
    2030                 :     274094 :       pfChildren.push_back(trn.getNode());
    2031                 :     274094 :       pfChildren.push_back(proven);
    2032                 :     274094 :       lcp->addStep(tConc, ProofRule::MODUS_PONENS, pfChildren, {});
    2033 [ +  + ][ +  + ]:    1526248 :     }
         [ +  + ][ +  + ]
    2034                 :            :     // If we don't have a step and the conclusion is not part of the
    2035                 :            :     // explanation (for unit T-conflicts), it must be by symmetry. We must do
    2036                 :            :     // this manually since lcp does not have auto-symmetry enabled due to the
    2037                 :            :     // complication mentioned above.
    2038                 :     135258 :     if (!lcp->hasStep(conclusion) && exp.find(conclusion) == exp.end())
    2039                 :            :     {
    2040                 :          0 :       Node sconc = CDProof::getSymmFact(conclusion);
    2041         [ -  - ]:          0 :       if (!sconc.isNull())
    2042                 :            :       {
    2043                 :          0 :         lcp->addStep(conclusion, ProofRule::SYMM, {sconc}, {});
    2044                 :            :       }
    2045                 :            :       else
    2046                 :            :       {
    2047                 :          0 :         DebugUnhandled()
    2048                 :          0 :             << "TheoryEngine::getExplanation: no step found for conclusion "
    2049                 :            :             << conclusion;
    2050                 :            :       }
    2051                 :          0 :     }
    2052                 :            :     // store in the proof generator
    2053                 :     270516 :     TrustNode trn = d_tepg->mkTrustExplain(conclusion, expNode, lcp);
    2054                 :            :     // return the trust node
    2055                 :     135258 :     return trn;
    2056                 :     135258 :   }
    2057                 :            : 
    2058                 :     207139 :   return TrustNode::mkTrustPropExp(conclusion, expNode, nullptr);
    2059                 :     342397 : }
    2060                 :            : 
    2061                 :    6268899 : bool TheoryEngine::isProofEnabled() const
    2062                 :            : {
    2063                 :    6268899 :   return d_env.isTheoryProofProducing();
    2064                 :            : }
    2065                 :            : 
    2066                 :       2847 : void TheoryEngine::checkTheoryAssertionsWithModel(bool hardFailure) {
    2067                 :       2847 :   bool hasFailure = false;
    2068                 :       2847 :   std::stringstream serror;
    2069                 :            :   // If possible, get the list of relevant assertions. Those that are not
    2070                 :            :   // relevant will be skipped.
    2071                 :       2847 :   std::unordered_set<TNode> relevantAssertions;
    2072                 :       2847 :   bool hasRelevantAssertions = false;
    2073         [ +  + ]:       2847 :   if (d_relManager != nullptr)
    2074                 :            :   {
    2075                 :            :     relevantAssertions =
    2076                 :         11 :         d_relManager->getRelevantAssertions(hasRelevantAssertions);
    2077                 :            :   }
    2078         [ +  + ]:      42705 :   for(TheoryId theoryId = THEORY_FIRST; theoryId < THEORY_LAST; ++theoryId) {
    2079                 :      39858 :     Theory* theory = d_theoryTable[theoryId];
    2080 [ +  - ][ +  + ]:      39858 :     if (theory && isTheoryEnabled(theoryId))
                 [ +  + ]
    2081                 :            :     {
    2082                 :      20820 :       for (context::CDList<Assertion>::const_iterator
    2083                 :      20820 :                it = theory->facts_begin(),
    2084                 :      20820 :                it_end = theory->facts_end();
    2085         [ +  + ]:     156188 :            it != it_end;
    2086                 :     135368 :            ++it)
    2087                 :            :       {
    2088                 :     135368 :         Node assertion = (*it).d_assertion;
    2089                 :     135603 :         if (hasRelevantAssertions
    2090 [ +  + ][ +  + ]:     135368 :             && relevantAssertions.find(assertion) == relevantAssertions.end())
         [ +  + ][ +  + ]
                 [ -  - ]
    2091                 :            :         {
    2092                 :            :           // not relevant, skip
    2093                 :        235 :           continue;
    2094                 :            :         }
    2095                 :     135133 :         Node val = d_tc->getModel()->getValue(assertion);
    2096         [ +  + ]:     135133 :         if (val != d_true)
    2097                 :            :         {
    2098                 :        355 :           std::stringstream ss;
    2099         [ +  + ]:        926 :           for (Node child : assertion)
    2100                 :            :           {
    2101                 :        571 :             Node value = d_tc->getModel()->getValue(child);
    2102                 :        571 :             ss << "getValue(" << child << "): " << value << std::endl;
    2103                 :        571 :           }
    2104                 :        355 :           ss << " " << theoryId << " has an asserted fact that";
    2105         [ -  + ]:        355 :           if (val == d_false)
    2106                 :            :           {
    2107                 :          0 :             ss << " the model doesn't satisfy." << std::endl;
    2108                 :            :           }
    2109                 :            :           else
    2110                 :            :           {
    2111                 :        355 :             ss << " the model may not satisfy." << std::endl;
    2112                 :            :           }
    2113                 :        355 :           ss << "The fact: " << assertion << std::endl
    2114                 :        355 :              << "Model value: " << val << std::endl;
    2115         [ +  - ]:        355 :           if (hardFailure)
    2116                 :            :           {
    2117         [ -  + ]:        355 :             if (val == d_false)
    2118                 :            :             {
    2119                 :            :               // Always an error if it is false
    2120                 :          0 :               hasFailure = true;
    2121                 :          0 :               serror << ss.str();
    2122                 :            :             }
    2123                 :            :             else
    2124                 :            :             {
    2125                 :            :               // Otherwise just a warning. Notice this case may happen for
    2126                 :            :               // assertions with unevaluable operators, e.g. transcendental
    2127                 :            :               // functions. It also may happen for separation logic, where
    2128                 :            :               // check-model support is limited.
    2129                 :        355 :               warning() << ss.str();
    2130                 :            :             }
    2131                 :            :           }
    2132                 :        355 :         }
    2133         [ +  + ]:     135368 :       }
    2134                 :            :     }
    2135                 :            :   }
    2136         [ -  + ]:       2847 :   if (hasFailure)
    2137                 :            :   {
    2138                 :          0 :     InternalError() << serror.str();
    2139                 :            :   }
    2140                 :       2847 : }
    2141                 :            : 
    2142                 :      11533 : std::pair<bool, Node> TheoryEngine::entailmentCheck(options::TheoryOfMode mode,
    2143                 :            :                                                     TNode lit)
    2144                 :            : {
    2145         [ +  + ]:      11533 :   TNode atom = (lit.getKind() == Kind::NOT) ? lit[0] : lit;
    2146         [ +  + ]:      23062 :   if (atom.getKind() == Kind::AND || atom.getKind() == Kind::OR
    2147 [ +  + ][ +  + ]:      23062 :       || atom.getKind() == Kind::IMPLIES)
                 [ +  + ]
    2148                 :            :   {
    2149                 :            :     //Boolean connective, recurse
    2150                 :         18 :     std::vector< Node > children;
    2151                 :         18 :     bool pol = (lit.getKind() != Kind::NOT);
    2152                 :         18 :     bool is_conjunction = pol == (lit.getKind() == Kind::AND);
    2153         [ +  - ]:         18 :     for( unsigned i=0; i<atom.getNumChildren(); i++ ){
    2154                 :         18 :       Node ch = atom[i];
    2155 [ -  + ][ -  - ]:         18 :       if (pol == (lit.getKind() == Kind::IMPLIES && i == 0))
                 [ +  - ]
    2156                 :            :       {
    2157                 :         18 :         ch = atom[i].negate();
    2158                 :            :       }
    2159                 :         18 :       std::pair<bool, Node> chres = entailmentCheck(mode, ch);
    2160         [ -  + ]:         18 :       if( chres.first ){
    2161         [ -  - ]:          0 :         if( !is_conjunction ){
    2162                 :          0 :           return chres;
    2163                 :            :         }else{
    2164                 :          0 :           children.push_back( chres.second );
    2165                 :            :         }
    2166 [ +  - ][ +  - ]:         18 :       }else if( !chres.first && is_conjunction ){
    2167                 :         18 :         return std::pair<bool, Node>(false, Node::null());
    2168                 :            :       }
    2169 [ -  + ][ -  + ]:         36 :     }
    2170         [ -  - ]:          0 :     if( is_conjunction ){
    2171                 :            :       return std::pair<bool, Node>(
    2172                 :          0 :           true, nodeManager()->mkNode(Kind::AND, children));
    2173                 :            :     }else{
    2174                 :          0 :       return std::pair<bool, Node>(false, Node::null());
    2175                 :            :     }
    2176                 :         18 :   }
    2177                 :      34545 :   else if (atom.getKind() == Kind::ITE
    2178                 :      11515 :            || (atom.getKind() == Kind::EQUAL && atom[0].getType().isBoolean()))
    2179                 :            :   {
    2180                 :          0 :     bool pol = (lit.getKind() != Kind::NOT);
    2181         [ -  - ]:          0 :     for( unsigned r=0; r<2; r++ ){
    2182                 :          0 :       Node ch = atom[0];
    2183         [ -  - ]:          0 :       if( r==1 ){
    2184                 :          0 :         ch = ch.negate();
    2185                 :            :       }
    2186                 :          0 :       std::pair<bool, Node> chres = entailmentCheck(mode, ch);
    2187         [ -  - ]:          0 :       if( chres.first ){
    2188         [ -  - ]:          0 :         Node ch2 = atom[atom.getKind() == Kind::ITE ? r + 1 : 1];
    2189                 :          0 :         if (pol == (atom.getKind() == Kind::ITE ? true : r == 1))
    2190                 :            :         {
    2191                 :          0 :           ch2 = ch2.negate();
    2192                 :            :         }
    2193                 :          0 :         std::pair<bool, Node> chres2 = entailmentCheck(mode, ch2);
    2194         [ -  - ]:          0 :         if( chres2.first ){
    2195                 :            :           return std::pair<bool, Node>(
    2196                 :            :               true,
    2197                 :          0 :               NodeManager::mkNode(Kind::AND, chres.second, chres2.second));
    2198                 :            :         }else{
    2199                 :          0 :           break;
    2200                 :            :         }
    2201 [ -  - ][ -  - ]:          0 :       }
    2202 [ -  - ][ -  - ]:          0 :     }
                 [ -  - ]
    2203                 :          0 :     return std::pair<bool, Node>(false, Node::null());
    2204                 :            :   }
    2205                 :            :   else
    2206                 :            :   {
    2207                 :            :     //it is a theory atom
    2208                 :      11515 :     theory::TheoryId tid = Theory::theoryOf(atom, mode);
    2209                 :      11515 :     theory::Theory* th = theoryOf(tid);
    2210                 :            : 
    2211 [ -  + ][ -  + ]:      11515 :     Assert(th != NULL);
                 [ -  - ]
    2212         [ +  - ]:      11515 :     Trace("theory-engine-entc") << "Entailment check : " << lit << std::endl;
    2213                 :            : 
    2214                 :      11515 :     std::pair<bool, Node> chres = th->entailmentCheck(lit);
    2215                 :      11515 :     return chres;
    2216                 :      11515 :   }
    2217                 :      11533 : }
    2218                 :            : 
    2219                 :   21881955 : void TheoryEngine::spendResource(Resource r)
    2220                 :            : {
    2221                 :   21881955 :   d_env.getResourceManager()->spendResource(r);
    2222                 :   21881955 : }
    2223                 :            : 
    2224                 :      18895 : void TheoryEngine::initializeProofChecker(ProofChecker* pc)
    2225                 :            : {
    2226         [ +  + ]:     283425 :   for (theory::TheoryId id = theory::THEORY_FIRST; id < theory::THEORY_LAST;
    2227                 :     264530 :        ++id)
    2228                 :            :   {
    2229                 :     264530 :     ProofRuleChecker* prc = d_theoryTable[id]->getProofChecker();
    2230         [ +  + ]:     264530 :     if (prc)
    2231                 :            :     {
    2232                 :     188950 :       prc->registerTo(pc);
    2233                 :            :     }
    2234                 :            :   }
    2235                 :      18895 : }
    2236                 :            : 
    2237                 :     699416 : theory::Rewriter* TheoryEngine::getRewriter() { return d_env.getRewriter(); }
    2238                 :            : 
    2239                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14