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: 819 991 82.6 %
Date: 2025-02-08 13:33:28 Functions: 57 61 93.4 %
Branches: 696 1150 60.5 %

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

Generated by: LCOV version 1.14