LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/theory - theory.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 286 328 87.2 %
Date: 2026-03-03 11:42:59 Functions: 33 40 82.5 %
Branches: 201 325 61.8 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * This file is part of the cvc5 project.
       3                 :            :  *
       4                 :            :  * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS
       5                 :            :  * in the top-level source directory and their institutional affiliations.
       6                 :            :  * All rights reserved.  See the file COPYING in the top-level source
       7                 :            :  * directory for licensing information.
       8                 :            :  * ****************************************************************************
       9                 :            :  *
      10                 :            :  * Base for theory interface.
      11                 :            :  */
      12                 :            : 
      13                 :            : #include "theory/theory.h"
      14                 :            : 
      15                 :            : #include <iostream>
      16                 :            : #include <sstream>
      17                 :            : #include <string>
      18                 :            : #include <vector>
      19                 :            : 
      20                 :            : #include "base/check.h"
      21                 :            : #include "expr/node_algorithm.h"
      22                 :            : #include "expr/skolem_manager.h"
      23                 :            : #include "options/arith_options.h"
      24                 :            : #include "options/smt_options.h"
      25                 :            : #include "options/theory_options.h"
      26                 :            : #include "theory/ee_setup_info.h"
      27                 :            : #include "theory/ext_theory.h"
      28                 :            : #include "theory/output_channel.h"
      29                 :            : #include "theory/quantifiers_engine.h"
      30                 :            : #include "theory/substitutions.h"
      31                 :            : #include "theory/theory_inference_manager.h"
      32                 :            : #include "theory/theory_model.h"
      33                 :            : #include "theory/theory_rewriter.h"
      34                 :            : #include "theory/theory_state.h"
      35                 :            : #include "theory/trust_substitutions.h"
      36                 :            : 
      37                 :            : using namespace std;
      38                 :            : 
      39                 :            : namespace cvc5::internal {
      40                 :            : namespace theory {
      41                 :            : 
      42                 :          0 : std::ostream& operator<<(std::ostream& os, Theory::Effort level){
      43 [ -  - ][ -  - ]:          0 :   switch(level){
      44                 :          0 :   case Theory::EFFORT_STANDARD:
      45                 :          0 :     os << "EFFORT_STANDARD"; break;
      46                 :          0 :   case Theory::EFFORT_FULL:
      47                 :          0 :     os << "EFFORT_FULL"; break;
      48                 :          0 :   case Theory::EFFORT_LAST_CALL:
      49                 :          0 :     os << "EFFORT_LAST_CALL"; break;
      50                 :          0 :   default:
      51                 :          0 :       Unreachable();
      52                 :            :   }
      53                 :          0 :   return os;
      54                 :            : }/* ostream& operator<<(ostream&, Theory::Effort) */
      55                 :            : 
      56                 :     699419 : Theory::Theory(TheoryId id,
      57                 :            :                Env& env,
      58                 :            :                OutputChannel& out,
      59                 :            :                Valuation valuation,
      60                 :     699419 :                std::string name)
      61                 :            :     : EnvObj(env),
      62                 :     699419 :       d_instanceName(name),
      63                 :    2098257 :       d_checkTime(statisticsRegistry().registerTimer(getStatsPrefix(id) + name
      64                 :    1398838 :                                                      + "checkTime")),
      65                 :    1398838 :       d_computeCareGraphTime(statisticsRegistry().registerTimer(
      66                 :    1398838 :           getStatsPrefix(id) + name + "computeCareGraphTime")),
      67                 :     699419 :       d_out(&out),
      68                 :     699419 :       d_valuation(valuation),
      69                 :     699419 :       d_equalityEngine(nullptr),
      70                 :     699419 :       d_allocEqualityEngine(nullptr),
      71                 :     699419 :       d_theoryState(nullptr),
      72                 :     699419 :       d_inferManager(nullptr),
      73                 :     699419 :       d_quantEngine(nullptr),
      74         [ +  + ]:     699419 :       d_pnm(d_env.isTheoryProofProducing() ? d_env.getProofNodeManager()
      75                 :            :                                            : nullptr),
      76                 :     699419 :       d_id(id),
      77                 :     699419 :       d_facts(d_env.getContext()),
      78                 :     699419 :       d_factsHead(d_env.getContext(), 0),
      79                 :     699419 :       d_careGraph(nullptr)
      80                 :            : {
      81                 :     699419 : }
      82                 :            : 
      83                 :     694589 : Theory::~Theory() {
      84                 :     694589 : }
      85                 :            : 
      86                 :      99914 : bool Theory::needsEqualityEngine(CVC5_UNUSED EeSetupInfo& esi)
      87                 :            : {
      88                 :            :   // by default, this theory does not use an (official) equality engine
      89                 :      99914 :   return false;
      90                 :            : }
      91                 :            : 
      92                 :     699398 : void Theory::setEqualityEngine(eq::EqualityEngine* ee)
      93                 :            : {
      94                 :            :   // set the equality engine pointer
      95                 :     699398 :   d_equalityEngine = ee;
      96         [ +  + ]:     699398 :   if (d_theoryState != nullptr)
      97                 :            :   {
      98                 :     649441 :     d_theoryState->setEqualityEngine(ee);
      99                 :            :   }
     100         [ +  + ]:     699398 :   if (d_inferManager != nullptr)
     101                 :            :   {
     102                 :     649441 :     d_inferManager->setEqualityEngine(ee);
     103                 :            :   }
     104                 :     699398 : }
     105                 :            : 
     106                 :     699398 : void Theory::setQuantifiersEngine(QuantifiersEngine* qe)
     107                 :            : {
     108                 :            :   // quantifiers engine may be null if not in quantified logic
     109                 :     699398 :   d_quantEngine = qe;
     110                 :     699398 : }
     111                 :            : 
     112                 :     699398 : void Theory::setDecisionManager(DecisionManager* dm)
     113                 :            : {
     114 [ -  + ][ -  + ]:     699398 :   Assert(dm != nullptr);
                 [ -  - ]
     115         [ +  + ]:     699398 :   if (d_inferManager != nullptr)
     116                 :            :   {
     117                 :     649441 :     d_inferManager->setDecisionManager(dm);
     118                 :            :   }
     119                 :     699398 : }
     120                 :            : 
     121                 :          0 : void Theory::finishInitStandalone()
     122                 :            : {
     123                 :          0 :   EeSetupInfo esi;
     124         [ -  - ]:          0 :   if (needsEqualityEngine(esi))
     125                 :            :   {
     126                 :            :     // always associated with the same SAT context as the theory
     127                 :            :     d_allocEqualityEngine =
     128                 :          0 :         std::make_unique<eq::EqualityEngine>(d_env,
     129                 :          0 :                                              context(),
     130                 :          0 :                                              *esi.d_notify,
     131                 :            :                                              esi.d_name,
     132                 :          0 :                                              esi.d_constantsAreTriggers);
     133                 :            :     // use it as the official equality engine
     134                 :          0 :     setEqualityEngine(d_allocEqualityEngine.get());
     135                 :            :   }
     136                 :          0 :   finishInit();
     137                 :          0 : }
     138                 :            : 
     139                 :  274344886 : TheoryId Theory::theoryOf(TNode node,
     140                 :            :                           options::TheoryOfMode mode,
     141                 :            :                           TheoryId usortOwner)
     142                 :            : {
     143                 :  274344886 :   TheoryId tid = THEORY_BUILTIN;
     144    [ +  + ][ - ]:  274344886 :   switch(mode) {
     145                 :  195495183 :     case options::TheoryOfMode::THEORY_OF_TYPE_BASED:
     146                 :            :       // Constants, variables, 0-ary constructors
     147         [ +  + ]:  195495183 :       if (node.isVar())
     148                 :            :       {
     149                 :   10809282 :         tid = theoryOf(node.getType(), usortOwner);
     150                 :            :       }
     151         [ +  + ]:  184685901 :       else if (node.getKind() == Kind::EQUAL)
     152                 :            :       {
     153                 :            :         // Equality is owned by the theory that owns the domain
     154                 :   15490227 :         tid = theoryOf(node[0].getType(), usortOwner);
     155                 :            :       }
     156                 :            :       else
     157                 :            :       {
     158                 :            :         // Regular nodes are owned by the kind. Notice that constants are a
     159                 :            :         // special case here, where the theory of the kind of a constant
     160                 :            :         // always coincides with the type of that constant.
     161                 :  169195674 :         tid = kindToTheoryId(node.getKind());
     162                 :            :       }
     163                 :  195495183 :       break;
     164                 :   78849703 :     case options::TheoryOfMode::THEORY_OF_TERM_BASED:
     165                 :            :       // Variables
     166         [ +  + ]:   78849703 :       if (node.isVar())
     167                 :            :       {
     168         [ +  + ]:   10250492 :         if (theoryOf(node.getType(), usortOwner) != theory::THEORY_BOOL)
     169                 :            :         {
     170                 :            :           // We treat the variables as uninterpreted
     171                 :   10101948 :           tid = THEORY_UF;
     172                 :            :         }
     173                 :            :         else
     174                 :            :         {
     175                 :            :           // Other Boolean variables are Bool
     176                 :     148544 :           tid = THEORY_BOOL;
     177                 :            :         }
     178                 :            :       }
     179         [ +  + ]:   68599211 :       else if (node.getKind() == Kind::EQUAL)
     180                 :            :       {  // Equality
     181                 :   10976473 :         TNode l = node[0];
     182                 :   10976473 :         TNode r = node[1];
     183                 :   10976473 :         TypeNode ltype = l.getType();
     184                 :   10976473 :         TypeNode rtype = r.getType();
     185                 :            :         // If the types are different, we must assign based on type due
     186                 :            :         // to handling subtypes (limited to arithmetic). Also, if we are
     187                 :            :         // a Boolean equality, we must assign THEORY_BOOL.
     188 [ +  - ][ +  + ]:   10976473 :         if (ltype != rtype || ltype.isBoolean())
                 [ +  + ]
     189                 :            :         {
     190                 :      17145 :           tid = theoryOf(ltype, usortOwner);
     191                 :            :         }
     192                 :            :         else
     193                 :            :         {
     194                 :            :           // If both sides belong to the same theory the choice is easy
     195                 :   10959328 :           TheoryId T1 = theoryOf(l, mode, usortOwner);
     196                 :   10959328 :           TheoryId T2 = theoryOf(r, mode, usortOwner);
     197         [ +  + ]:   10959328 :           if (T1 == T2)
     198                 :            :           {
     199                 :    6726798 :             tid = T1;
     200                 :            :           }
     201                 :            :           else
     202                 :            :           {
     203                 :    4232530 :             TheoryId T3 = theoryOf(ltype, usortOwner);
     204                 :            :             // This is a case of
     205                 :            :             // * x*y = f(z) -> UF
     206                 :            :             // * x = c      -> UF
     207                 :            :             // * f(x) = read(a, y) -> either UF or ARRAY
     208                 :            :             // at least one of the theories has to be parametric, i.e. theory
     209                 :            :             // of the type is different from the theory of the term
     210         [ +  + ]:    4232530 :             if (T1 == T3)
     211                 :            :             {
     212                 :     594986 :               tid = T2;
     213                 :            :             }
     214         [ +  + ]:    3637544 :             else if (T2 == T3)
     215                 :            :             {
     216                 :    3565366 :               tid = T1;
     217                 :            :             }
     218                 :            :             else
     219                 :            :             {
     220                 :            :               // If both are parametric, we take the smaller one (arbitrary)
     221         [ +  + ]:      72178 :               tid = T1 < T2 ? T1 : T2;
     222                 :            :             }
     223                 :            :           }
     224                 :            :         }
     225                 :   10976473 :       }
     226                 :            :       else
     227                 :            :       {
     228                 :            :         // Regular nodes are owned by the kind, which includes constants as a
     229                 :            :         // special case.
     230                 :   57622738 :         tid = kindToTheoryId(node.getKind());
     231                 :            :       }
     232                 :   78849703 :     break;
     233                 :          0 :   default:
     234                 :          0 :     Unreachable();
     235                 :            :   }
     236                 :  274344886 :   return tid;
     237                 :            : }
     238                 :            : 
     239                 :    1962720 : void Theory::notifySharedTerm(CVC5_UNUSED TNode n)
     240                 :            : {
     241                 :            :   // do nothing
     242                 :    1962720 : }
     243                 :            : 
     244                 :    5283222 : void Theory::notifyInConflict()
     245                 :            : {
     246         [ +  + ]:    5283222 :   if (d_inferManager != nullptr)
     247                 :            :   {
     248                 :    4905849 :     d_inferManager->notifyInConflict();
     249                 :            :   }
     250                 :    5283222 : }
     251                 :            : 
     252                 :      53084 : void Theory::computeCareGraph()
     253                 :            : {
     254 [ -  + ][ -  + ]:      53084 :   Assert(d_theoryState != nullptr);
                 [ -  - ]
     255         [ +  - ]:      53084 :   Trace("sharing") << "Theory::computeCareGraph<" << getId() << ">()" << endl;
     256                 :      53084 :   const context::CDList<TNode>& sharedTerms = d_theoryState->getSharedTerms();
     257                 :      53084 :   size_t ssize = sharedTerms.size();
     258         [ +  + ]:      61393 :   for (size_t i = 0; i < ssize; ++i)
     259                 :            :   {
     260                 :       8309 :     TNode a = sharedTerms[i];
     261                 :       8309 :     TypeNode aType = a.getType();
     262         [ +  + ]:      26512 :     for (size_t j = i + 1; j < ssize; ++j)
     263                 :            :     {
     264                 :      18203 :       TNode b = sharedTerms[j];
     265         [ +  + ]:      18203 :       if (b.getType() != aType)
     266                 :            :       {
     267                 :            :         // We don't care about the terms of different types
     268                 :       6228 :         continue;
     269                 :            :       }
     270         [ +  + ]:      11975 :       switch (d_valuation.getEqualityStatus(a, b)) {
     271                 :       7784 :       case EQUALITY_TRUE_AND_PROPAGATED:
     272                 :            :       case EQUALITY_FALSE_AND_PROPAGATED:
     273                 :            :         // If we know about it, we should have propagated it, so we can skip
     274                 :       7784 :         break;
     275                 :       4191 :       default:
     276                 :            :         // Let's split on it
     277                 :       4191 :         addCarePair(a, b);
     278                 :       4191 :         break;
     279                 :            :       }
     280         [ +  + ]:      18203 :     }
     281                 :       8309 :   }
     282                 :      53084 : }
     283                 :            : 
     284                 :          0 : void Theory::printFacts(std::ostream& os) const {
     285                 :          0 :   unsigned i, n = d_facts.size();
     286         [ -  - ]:          0 :   for(i = 0; i < n; i++){
     287                 :          0 :     const Assertion& a_i = d_facts[i];
     288                 :          0 :     Node assertion  = a_i;
     289                 :          0 :     os << d_id << '[' << i << ']' << " " << assertion << endl;
     290                 :          0 :   }
     291                 :          0 : }
     292                 :            : 
     293                 :          0 : void Theory::debugPrintFacts() const{
     294                 :          0 :   TraceChannel.getStream() << "Theory::debugPrintFacts()" << endl;
     295                 :          0 :   printFacts(TraceChannel.getStream());
     296                 :          0 : }
     297                 :            : 
     298                 :     188062 : bool Theory::collectModelInfo(TheoryModel* m, const std::set<Node>& termSet)
     299                 :            : {
     300                 :            :   // if we are using an equality engine, assert it to the model
     301 [ +  + ][ +  + ]:     188062 :   if (d_equalityEngine != nullptr && !termSet.empty())
                 [ +  + ]
     302                 :            :   {
     303         [ +  - ]:     132458 :     Trace("model-builder") << "Assert Equality engine for " << d_id
     304                 :      66229 :                            << std::endl;
     305         [ -  + ]:      66229 :     if (!m->assertEqualityEngine(d_equalityEngine, &termSet))
     306                 :            :     {
     307                 :          0 :       return false;
     308                 :            :     }
     309                 :            :   }
     310         [ +  - ]:     188062 :   Trace("model-builder") << "Collect Model values for " << d_id << std::endl;
     311                 :            :   // now, collect theory-specific value assigments
     312                 :     188062 :   return collectModelValues(m, termSet);
     313                 :            : }
     314                 :            : 
     315                 :     271455 : void Theory::computeRelevantTerms(CVC5_UNUSED std::set<Node>& termSet)
     316                 :            : {
     317                 :            :   // by default, there are no additional relevant terms
     318                 :     271455 : }
     319                 :            : 
     320                 :     500130 : void Theory::collectAssertedTerms(std::set<Node>& termSet,
     321                 :            :                                   bool includeShared,
     322                 :            :                                   const std::set<Kind>& irrKinds) const
     323                 :            : {
     324                 :            :   // Collect all terms appearing in assertions
     325                 :     500130 :   context::CDList<Assertion>::const_iterator assert_it = facts_begin(),
     326                 :     500130 :                                              assert_it_end = facts_end();
     327         [ +  + ]:   25640935 :   for (; assert_it != assert_it_end; ++assert_it)
     328                 :            :   {
     329                 :   25140805 :     collectTerms(*assert_it, termSet, irrKinds);
     330                 :            :   }
     331                 :            : 
     332         [ +  - ]:     500130 :   if (includeShared)
     333                 :            :   {
     334 [ -  + ][ -  + ]:     500130 :     Assert(d_theoryState != nullptr);
                 [ -  - ]
     335                 :            :     // Add terms that are shared terms
     336                 :            :     context::CDList<TNode>::const_iterator
     337                 :     500130 :         shared_it = d_theoryState->shared_terms_begin(),
     338                 :     500130 :         shared_it_end = d_theoryState->shared_terms_end();
     339         [ +  + ]:    8215202 :     for (; shared_it != shared_it_end; ++shared_it)
     340                 :            :     {
     341                 :    7715072 :       collectTerms(*shared_it, termSet, irrKinds);
     342                 :            :     }
     343                 :            :   }
     344                 :     500130 : }
     345                 :     373732 : void Theory::collectAssertedTermsForModel(std::set<Node>& termSet,
     346                 :            :                                           bool includeShared) const
     347                 :            : {
     348                 :            :   // use the irrelevant model kinds from the theory state
     349                 :            :   const std::set<Kind>& irrKinds =
     350                 :     373732 :       d_theoryState->getModel()->getIrrelevantKinds();
     351                 :     373732 :   collectAssertedTerms(termSet, includeShared, irrKinds);
     352                 :     373732 : }
     353                 :            : 
     354                 :   32855877 : void Theory::collectTerms(TNode n,
     355                 :            :                           std::set<Node>& termSet,
     356                 :            :                           const std::set<Kind>& irrKinds) const
     357                 :            : {
     358                 :   32855877 :   std::vector<TNode> visit;
     359                 :   32855877 :   TNode cur;
     360                 :   32855877 :   visit.push_back(n);
     361                 :            :   do
     362                 :            :   {
     363                 :  113261133 :     cur = visit.back();
     364                 :  113261133 :     visit.pop_back();
     365         [ +  + ]:  113261133 :     if (termSet.find(cur) != termSet.end())
     366                 :            :     {
     367                 :            :       // already visited
     368                 :   58701443 :       continue;
     369                 :            :     }
     370                 :   54559690 :     Kind k = cur.getKind();
     371                 :            :     // only add to term set if a relevant kind
     372         [ +  + ]:   54559690 :     if (irrKinds.find(k) == irrKinds.end())
     373                 :            :     {
     374                 :   32435457 :       termSet.insert(cur);
     375                 :            :     }
     376                 :            :     // traverse owned terms, don't go under quantifiers
     377 [ +  + ][ +  + ]:   97470158 :     if ((k == Kind::NOT || k == Kind::EQUAL || d_env.theoryOf(cur) == d_id)
         [ +  + ][ -  - ]
     378 [ +  + ][ +  + ]:   97470158 :         && !cur.isClosure())
                 [ +  + ]
     379                 :            :     {
     380                 :   49931966 :       visit.insert(visit.end(), cur.begin(), cur.end());
     381                 :            :     }
     382         [ +  + ]:  113261133 :   } while (!visit.empty());
     383                 :   32855877 : }
     384                 :            : 
     385                 :      13350 : bool Theory::collectModelValues(CVC5_UNUSED TheoryModel* m,
     386                 :            :                                 CVC5_UNUSED const std::set<Node>& termSet)
     387                 :            : {
     388                 :      13350 :   return true;
     389                 :            : }
     390                 :            : 
     391                 :      87169 : bool Theory::ppAssert(TrustNode tin, TrustSubstitutionMap& outSubstitutions)
     392                 :            : {
     393 [ -  + ][ -  + ]:      87169 :   Assert(tin.getKind() == TrustNodeKind::LEMMA);
                 [ -  - ]
     394                 :      87169 :   TNode in = tin.getNode();
     395         [ +  + ]:      87169 :   if (in.getKind() == Kind::EQUAL)
     396                 :            :   {
     397                 :            :     // (and (= x t) phi) can be replaced by phi[x/t] if
     398                 :            :     // 1) x is a variable
     399                 :            :     // 2) x is not in the term t
     400                 :            :     // 3) x : T and t : S, then S <: T
     401                 :      64228 :     if (in[0].isVar() && d_valuation.isLegalElimination(in[0], in[1]))
     402                 :            :     {
     403                 :      33038 :       outSubstitutions.addSubstitutionSolved(in[0], in[1], tin);
     404                 :      33038 :       return true;
     405                 :            :     }
     406                 :      31190 :     if (in[1].isVar() && d_valuation.isLegalElimination(in[1], in[0]))
     407                 :            :     {
     408                 :       1056 :       outSubstitutions.addSubstitutionSolved(in[1], in[0], tin);
     409                 :       1056 :       return true;
     410                 :            :     }
     411                 :            :   }
     412                 :            : 
     413                 :      53075 :   return false;
     414                 :      87169 : }
     415                 :            : 
     416                 :          0 : std::pair<bool, Node> Theory::entailmentCheck(CVC5_UNUSED TNode lit)
     417                 :            : {
     418                 :          0 :   return make_pair(false, Node::null());
     419                 :            : }
     420                 :            : 
     421                 :     116873 : void Theory::addCarePair(TNode t1, TNode t2) {
     422 [ -  + ][ -  + ]:     116873 :   Assert(d_careGraph != nullptr);
                 [ -  - ]
     423         [ +  - ]:     233746 :   Trace("sharing") << "Theory::addCarePair: add pair " << d_id << " " << t1
     424                 :     116873 :                    << " " << t2 << std::endl;
     425                 :     116873 :   d_careGraph->insert(CarePair(t1, t2, d_id));
     426                 :     116873 : }
     427                 :     391169 : void Theory::addCarePairArgs(TNode a, TNode b)
     428                 :            : {
     429 [ -  + ][ -  + ]:     391169 :   Assert(d_careGraph != nullptr);
                 [ -  - ]
     430 [ -  + ][ -  + ]:     391169 :   Assert(d_equalityEngine != nullptr);
                 [ -  - ]
     431 [ +  - ][ +  - ]:     391169 :   Assert(a.hasOperator() && b.hasOperator());
         [ -  + ][ -  + ]
                 [ -  - ]
     432 [ -  + ][ -  + ]:     391169 :   Assert(a.getOperator() == b.getOperator());
                 [ -  - ]
     433 [ -  + ][ -  + ]:     391169 :   Assert(a.getNumChildren() == b.getNumChildren());
                 [ -  - ]
     434         [ +  - ]:     782338 :   Trace("sharing") << "Theory::addCarePairArgs: checking function " << d_id
     435                 :     391169 :                    << " " << a << " " << b << std::endl;
     436         [ +  + ]:    1098429 :   for (size_t k = 0, nchildren = a.getNumChildren(); k < nchildren; ++k)
     437                 :            :   {
     438                 :     707260 :     TNode x = a[k];
     439                 :     707260 :     TNode y = b[k];
     440 [ +  + ][ -  - ]:     707260 :     if (d_equalityEngine->isTriggerTerm(x, d_id)
     441 [ +  + ][ +  - ]:    1130806 :         && d_equalityEngine->isTriggerTerm(y, d_id)
                 [ -  - ]
     442                 :    1130806 :         && !d_equalityEngine->areEqual(x, y))
     443                 :            :     {
     444                 :     104061 :       TNode x_shared = d_equalityEngine->getTriggerTermRepresentative(x, d_id);
     445                 :     104061 :       TNode y_shared = d_equalityEngine->getTriggerTermRepresentative(y, d_id);
     446                 :     104061 :       addCarePair(x_shared, y_shared);
     447                 :     104061 :     }
     448                 :     707260 :   }
     449                 :     391169 : }
     450                 :            : 
     451                 :      43366 : void Theory::processCarePairArgs(TNode a, TNode b)
     452                 :            : {
     453                 :            :   // if a and b are already equal, we ignore this pair
     454         [ +  + ]:      43366 :   if (d_theoryState->areEqual(a, b))
     455                 :            :   {
     456                 :       1429 :     return;
     457                 :            :   }
     458                 :            :   // otherwise, we add pairs for each of their arguments
     459                 :      41937 :   addCarePairArgs(a, b);
     460                 :            : }
     461                 :            : 
     462                 :     196401 : bool Theory::areCareDisequal(TNode x, TNode y)
     463                 :            : {
     464 [ -  + ][ -  + ]:     196401 :   Assert(d_equalityEngine != nullptr);
                 [ -  - ]
     465 [ -  + ][ -  + ]:     196401 :   Assert(d_equalityEngine->hasTerm(x));
                 [ -  - ]
     466 [ -  + ][ -  + ]:     196401 :   Assert(d_equalityEngine->hasTerm(y));
                 [ -  - ]
     467 [ -  + ][ -  + ]:     196401 :   Assert(x != y);
                 [ -  - ]
     468 [ +  + ][ +  - ]:     196401 :   Assert(!x.isConst() || !y.isConst());
         [ -  + ][ -  + ]
                 [ -  - ]
     469                 :            :   // first just check if they are disequal, which is sufficient for
     470                 :            :   // non-shared terms.
     471         [ +  + ]:     196401 :   if (d_equalityEngine->areDisequal(x, y, false))
     472                 :            :   {
     473                 :      21454 :     return true;
     474                 :            :   }
     475                 :            :   // if we aren't shared, we are not disequal
     476 [ +  + ][ -  - ]:     174947 :   if (!d_equalityEngine->isTriggerTerm(x, d_id)
     477 [ +  + ][ +  + ]:     174947 :       || !d_equalityEngine->isTriggerTerm(y, d_id))
         [ +  + ][ +  - ]
                 [ -  - ]
     478                 :            :   {
     479                 :      56776 :     return false;
     480                 :            :   }
     481                 :            :   // otherwise use getEqualityStatus to ask the appropriate theory whether
     482                 :            :   // x and y are disequal.
     483                 :     118171 :   TNode x_shared = d_equalityEngine->getTriggerTermRepresentative(x, d_id);
     484                 :     118171 :   TNode y_shared = d_equalityEngine->getTriggerTermRepresentative(y, d_id);
     485                 :     118171 :   EqualityStatus eqStatus = d_valuation.getEqualityStatus(x_shared, y_shared);
     486 [ +  - ][ +  - ]:     118171 :   if (eqStatus == EQUALITY_FALSE_AND_PROPAGATED || eqStatus == EQUALITY_FALSE
     487         [ +  + ]:     118171 :       || eqStatus == EQUALITY_FALSE_IN_MODEL)
     488                 :            :   {
     489                 :     107701 :     return true;
     490                 :            :   }
     491                 :      10470 :   return false;
     492                 :     118171 : }
     493                 :            : 
     494                 :     271296 : void Theory::getCareGraph(CareGraph* careGraph) {
     495 [ -  + ][ -  + ]:     271296 :   Assert(careGraph != nullptr);
                 [ -  - ]
     496                 :            : 
     497         [ +  - ]:     271296 :   Trace("sharing") << "Theory<" << getId() << ">::getCareGraph()" << std::endl;
     498                 :     271296 :   TimerStat::CodeTimer computeCareGraphTime(d_computeCareGraphTime);
     499                 :     271296 :   d_careGraph = careGraph;
     500                 :     271296 :   computeCareGraph();
     501                 :     271296 :   d_careGraph = nullptr;
     502                 :     271296 : }
     503                 :            : 
     504                 :          0 : bool Theory::proofsEnabled() const
     505                 :            : {
     506                 :          0 :   return d_env.getProofNodeManager() != nullptr;
     507                 :            : }
     508                 :            : 
     509                 :      16701 : EqualityStatus Theory::getEqualityStatus(TNode a, TNode b)
     510                 :            : {
     511                 :            :   // if not using an equality engine, then by default we don't know the status
     512         [ +  + ]:      16701 :   if (d_equalityEngine == nullptr)
     513                 :            :   {
     514                 :        178 :     return EQUALITY_UNKNOWN;
     515                 :            :   }
     516         [ +  - ]:      16523 :   Trace("sharing") << "Theory<" << getId() << ">::getEqualityStatus(" << a << ", " << b << ")" << std::endl;
     517                 :      16523 :   Assert(d_equalityEngine->hasTerm(a) && d_equalityEngine->hasTerm(b));
     518                 :            : 
     519                 :            :   // Check for equality (simplest)
     520         [ +  + ]:      16523 :   if (d_equalityEngine->areEqual(a, b))
     521                 :            :   {
     522                 :            :     // The terms are implied to be equal
     523                 :       6839 :     return EQUALITY_TRUE;
     524                 :            :   }
     525                 :            : 
     526                 :            :   // Check for disequality
     527         [ +  + ]:       9684 :   if (d_equalityEngine->areDisequal(a, b, false))
     528                 :            :   {
     529                 :            :     // The terms are implied to be dis-equal
     530                 :       2698 :     return EQUALITY_FALSE;
     531                 :            :   }
     532                 :            : 
     533                 :            :   // All other terms are unknown, which is conservative. A theory may override
     534                 :            :   // this method if it knows more information.
     535                 :       6986 :   return EQUALITY_UNKNOWN;
     536                 :            : }
     537                 :            : 
     538                 :   35827373 : void Theory::check(Effort level)
     539                 :            : {
     540                 :            :   // see if we are already done (as an optimization)
     541 [ +  + ][ +  + ]:   35827373 :   if (done() && level < EFFORT_FULL)
                 [ +  + ]
     542                 :            :   {
     543                 :   23922644 :     return;
     544                 :            :   }
     545 [ -  + ][ -  + ]:   11904729 :   Assert(d_theoryState!=nullptr);
                 [ -  - ]
     546                 :            :   // standard calls for resource, stats
     547                 :   11904729 :   d_out->spendResource(Resource::TheoryCheckStep);
     548                 :   11904729 :   TimerStat::CodeTimer checkTimer(d_checkTime);
     549         [ +  - ]:   23809458 :   Trace("theory-check") << "Theory::preCheck " << level << " " << d_id
     550                 :   11904729 :                         << std::endl;
     551                 :            :   // pre-check at level
     552         [ -  + ]:   11904729 :   if (preCheck(level))
     553                 :            :   {
     554                 :            :     // check aborted for a theory-specific reason
     555                 :          0 :     return;
     556                 :            :   }
     557         [ +  - ]:   11904729 :   Trace("theory-check") << "Theory::process fact queue " << d_id << std::endl;
     558                 :            :   // process the pending fact queue
     559 [ +  + ][ +  + ]:   45451800 :   while (!done() && !d_theoryState->isInConflict())
                 [ +  + ]
     560                 :            :   {
     561                 :            :     // Get the next assertion from the fact queue
     562                 :   33547074 :     Assertion assertion = get();
     563                 :   33547074 :     TNode fact = assertion.d_assertion;
     564         [ +  - ]:   67094148 :     Trace("theory-check") << "Theory::preNotifyFact " << fact << " " << d_id
     565                 :   33547074 :                           << std::endl;
     566                 :   33547074 :     bool polarity = fact.getKind() != Kind::NOT;
     567         [ +  + ]:   33547074 :     TNode atom = polarity ? fact : fact[0];
     568                 :            :     // call the pre-notify method
     569         [ +  + ]:   33547074 :     if (preNotifyFact(atom, polarity, fact, assertion.d_isPreregistered, false))
     570                 :            :     {
     571                 :            :       // handled in theory-specific way that doesn't involve equality engine
     572                 :   11937234 :       continue;
     573                 :            :     }
     574         [ +  - ]:   43219680 :     Trace("theory-check") << "Theory::assert " << fact << " " << d_id
     575                 :   21609840 :                           << std::endl;
     576                 :            :     // Theories that don't have an equality engine should always return true
     577                 :            :     // for preNotifyFact
     578 [ -  + ][ -  + ]:   21609840 :     Assert(d_equalityEngine != nullptr);
                 [ -  - ]
     579                 :            :     // assert to the equality engine
     580         [ +  + ]:   21609840 :     if (atom.getKind() == Kind::EQUAL)
     581                 :            :     {
     582                 :   14419571 :       d_equalityEngine->assertEquality(atom, polarity, fact);
     583                 :            :     }
     584                 :            :     else
     585                 :            :     {
     586                 :    7190275 :       d_equalityEngine->assertPredicate(atom, polarity, fact);
     587                 :            :     }
     588         [ +  - ]:   43219674 :     Trace("theory-check") << "Theory::notifyFact " << fact << " " << d_id
     589                 :   21609837 :                           << std::endl;
     590                 :            :     // notify the theory of the new fact, which is not internal
     591                 :   21609837 :     notifyFact(atom, polarity, fact, false);
     592 [ +  + ][ +  + ]:   57421548 :   }
                 [ +  + ]
     593         [ +  - ]:   11904726 :   Trace("theory-check") << "Theory::postCheck " << d_id << std::endl;
     594                 :            :   // post-check at level
     595                 :   11904726 :   postCheck(level);
     596         [ +  - ]:   11904725 :   Trace("theory-check") << "Theory::finish check " << d_id << std::endl;
     597         [ +  - ]:   11904729 : }
     598                 :            : 
     599                 :    4494824 : bool Theory::preCheck(CVC5_UNUSED Effort level) { return false; }
     600                 :            : 
     601                 :          1 : void Theory::postCheck(CVC5_UNUSED Effort level) {}
     602                 :            : 
     603                 :   11043211 : bool Theory::preNotifyFact(CVC5_UNUSED TNode atom,
     604                 :            :                            CVC5_UNUSED bool polarity,
     605                 :            :                            CVC5_UNUSED TNode fact,
     606                 :            :                            CVC5_UNUSED bool isPrereg,
     607                 :            :                            CVC5_UNUSED bool isInternal)
     608                 :            : {
     609                 :   11043211 :   return false;
     610                 :            : }
     611                 :            : 
     612                 :      12959 : void Theory::notifyFact(CVC5_UNUSED TNode atom,
     613                 :            :                         CVC5_UNUSED bool polarity,
     614                 :            :                         CVC5_UNUSED TNode fact,
     615                 :            :                         CVC5_UNUSED bool isInternal)
     616                 :            : {
     617                 :      12959 : }
     618                 :            : 
     619                 :      68134 : void Theory::preRegisterTerm(CVC5_UNUSED TNode node) {}
     620                 :            : 
     621                 :    3535692 : void Theory::addSharedTerm(TNode n)
     622                 :            : {
     623         [ +  - ]:    7071384 :   Trace("sharing") << "Theory::addSharedTerm<" << getId() << ">(" << n << ")"
     624                 :    3535692 :                    << std::endl;
     625         [ +  - ]:    7071384 :   Trace("theory::assertions")
     626                 :    3535692 :       << "Theory::addSharedTerm<" << getId() << ">(" << n << ")" << std::endl;
     627         [ +  + ]:    3535692 :   if (d_theoryState != nullptr)
     628                 :            :   {
     629                 :    3524368 :     d_theoryState->addSharedTerm(n);
     630                 :            :   }
     631                 :            :   // now call theory-specific method notifySharedTerm
     632                 :    3535693 :   notifySharedTerm(n);
     633                 :            :   // if we have an equality engine, add the trigger term
     634         [ +  + ]:    3535691 :   if (d_equalityEngine != nullptr)
     635                 :            :   {
     636                 :    3524367 :     d_equalityEngine->addTriggerTerm(n, d_id);
     637                 :            :   }
     638                 :    3535691 : }
     639                 :            : 
     640                 :     602637 : eq::EqualityEngine* Theory::getEqualityEngine()
     641                 :            : {
     642                 :            :   // get the assigned equality engine, which is a pointer stored in this class
     643                 :     602637 :   return d_equalityEngine;
     644                 :            : }
     645                 :            : 
     646                 :      22122 : bool Theory::expUsingCentralEqualityEngine(TheoryId id)
     647                 :            : {
     648 [ +  + ][ +  + ]:      22122 :   return id != THEORY_ARITH && id != THEORY_ARRAYS;
     649                 :            : }
     650                 :            : 
     651                 :   33547074 : theory::Assertion Theory::get()
     652                 :            : {
     653 [ -  + ][ -  + ]:   33547074 :   Assert(!done()) << "Theory::get() called with assertion queue empty!";
                 [ -  - ]
     654                 :            : 
     655                 :            :   // Get the assertion
     656                 :   33547074 :   Assertion fact = d_facts[d_factsHead];
     657                 :   33547074 :   d_factsHead = d_factsHead + 1;
     658                 :            : 
     659         [ +  - ]:   67094148 :   Trace("theory") << "Theory::get() => " << fact << " ("
     660                 :   33547074 :                   << d_facts.size() - d_factsHead << " left)" << std::endl;
     661                 :            : 
     662                 :   33547074 :   return fact;
     663                 :          0 : }
     664                 :            : 
     665                 :            : }  // namespace theory
     666                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14