LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/theory - ext_theory.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 197 221 89.1 %
Date: 2025-01-05 12:38:24 Functions: 19 24 79.2 %
Branches: 126 173 72.8 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * Top contributors (to current version):
       3                 :            :  *   Andrew Reynolds, Tim King, Gereon Kremer
       4                 :            :  *
       5                 :            :  * This file is part of the cvc5 project.
       6                 :            :  *
       7                 :            :  * Copyright (c) 2009-2024 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                 :            :  * Extended theory interface.
      14                 :            :  *
      15                 :            :  * This implements a generic module, used by theory solvers, for performing
      16                 :            :  * "context-dependent simplification", as described in Reynolds et al
      17                 :            :  * "Designing Theory Solvers with Extensions", FroCoS 2017.
      18                 :            :  */
      19                 :            : 
      20                 :            : #include "theory/ext_theory.h"
      21                 :            : 
      22                 :            : #include "base/check.h"
      23                 :            : #include "proof/proof_checker.h"
      24                 :            : #include "proof/proof_node_manager.h"
      25                 :            : #include "theory/output_channel.h"
      26                 :            : #include "theory/quantifiers_engine.h"
      27                 :            : #include "theory/rewriter.h"
      28                 :            : #include "theory/substitutions.h"
      29                 :            : 
      30                 :            : using namespace std;
      31                 :            : 
      32                 :            : namespace cvc5::internal {
      33                 :            : namespace theory {
      34                 :            : 
      35                 :         15 : const char* toString(ExtReducedId id)
      36                 :            : {
      37 [ +  + ][ +  + ]:         15 :   switch (id)
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  - ]
                    [ - ]
      38                 :            :   {
      39                 :          1 :     case ExtReducedId::NONE: return "NONE";
      40                 :          1 :     case ExtReducedId::SR_CONST: return "SR_CONST";
      41                 :          1 :     case ExtReducedId::REDUCTION: return "REDUCTION";
      42                 :          1 :     case ExtReducedId::ARITH_SR_ZERO: return "ARITH_SR_ZERO";
      43                 :          1 :     case ExtReducedId::ARITH_SR_LINEAR: return "ARITH_SR_LINEAR";
      44                 :          1 :     case ExtReducedId::STRINGS_SR_CONST: return "STRINGS_SR_CONST";
      45                 :          1 :     case ExtReducedId::STRINGS_NEG_CTN_DEQ: return "STRINGS_NEG_CTN_DEQ";
      46                 :          1 :     case ExtReducedId::STRINGS_CTN_DECOMPOSE: return "STRINGS_CTN_DECOMPOSE";
      47                 :          1 :     case ExtReducedId::STRINGS_REGEXP_INTER: return "STRINGS_REGEXP_INTER";
      48                 :          1 :     case ExtReducedId::STRINGS_REGEXP_INTER_SUBSUME:
      49                 :          1 :       return "STRINGS_REGEXP_INTER_SUBSUME";
      50                 :          1 :     case ExtReducedId::STRINGS_REGEXP_INCLUDE: return "STRINGS_REGEXP_INCLUDE";
      51                 :          1 :     case ExtReducedId::STRINGS_REGEXP_INCLUDE_NEG:
      52                 :          1 :       return "STRINGS_REGEXP_INCLUDE_NEG";
      53                 :          1 :     case ExtReducedId::STRINGS_REGEXP_RE_SYM_NF:
      54                 :          1 :       return "STRINGS_REGEXP_RE_SYM_NF";
      55                 :          1 :     case ExtReducedId::STRINGS_REGEXP_PDERIVATIVE:
      56                 :          1 :       return "STRINGS_REGEXP_PDERIVATIVE";
      57                 :          1 :     case ExtReducedId::STRINGS_NTH_REV: return "STRINGS_NTH_REV";
      58                 :          0 :     case ExtReducedId::UNKNOWN: return "?";
      59                 :          0 :     default: Unreachable(); return "?ExtReducedId?";
      60                 :            :   }
      61                 :            : }
      62                 :            : 
      63                 :         15 : std::ostream& operator<<(std::ostream& out, ExtReducedId id)
      64                 :            : {
      65                 :         15 :   out << toString(id);
      66                 :         15 :   return out;
      67                 :            : }
      68                 :            : 
      69                 :          0 : bool ExtTheoryCallback::getCurrentSubstitution(
      70                 :            :     int effort,
      71                 :            :     const std::vector<Node>& vars,
      72                 :            :     std::vector<Node>& subs,
      73                 :            :     std::map<Node, std::vector<Node> >& exp)
      74                 :            : {
      75                 :          0 :   return false;
      76                 :            : }
      77                 :          0 : bool ExtTheoryCallback::isExtfReduced(
      78                 :            :     int effort, Node n, Node on, std::vector<Node>& exp, ExtReducedId& id)
      79                 :            : {
      80                 :          0 :   id = ExtReducedId::SR_CONST;
      81                 :          0 :   return n.isConst();
      82                 :            : }
      83                 :          0 : bool ExtTheoryCallback::getReduction(int effort,
      84                 :            :                                     Node n,
      85                 :            :                                     Node& nr,
      86                 :            :                                     bool& isSatDep)
      87                 :            : {
      88                 :          0 :   return false;
      89                 :            : }
      90                 :            : 
      91                 :      82380 : ExtTheory::ExtTheory(Env& env, ExtTheoryCallback& p, TheoryInferenceManager& im)
      92                 :            :     : EnvObj(env),
      93                 :            :       d_parent(p),
      94                 :            :       d_im(im),
      95                 :            :       d_ext_func_terms(context()),
      96                 :            :       d_extfExtReducedIdMap(context()),
      97                 :     164760 :       d_ci_inactive(userContext()),
      98                 :            :       d_has_extf(context()),
      99                 :      82380 :       d_lemmas(userContext())
     100                 :            : {
     101                 :      82380 :   d_true = nodeManager()->mkConst(true);
     102                 :      82380 : }
     103                 :            : 
     104                 :            : // Gets all leaf terms in n.
     105                 :      35080 : std::vector<Node> ExtTheory::collectVars(Node n)
     106                 :            : {
     107                 :      35080 :   std::vector<Node> vars;
     108                 :      70160 :   std::set<Node> visited;
     109                 :      70160 :   std::vector<Node> worklist;
     110                 :      35080 :   worklist.push_back(n);
     111         [ +  + ]:     228748 :   while (!worklist.empty())
     112                 :            :   {
     113                 :     193668 :     Node current = worklist.back();
     114                 :     193668 :     worklist.pop_back();
     115 [ +  + ][ +  + ]:     193668 :     if (current.isConst() || visited.count(current) > 0)
                 [ +  + ]
     116                 :            :     {
     117                 :      59718 :       continue;
     118                 :            :     }
     119                 :     133950 :     visited.insert(current);
     120                 :            :     // Treat terms not belonging to this theory as leaf
     121                 :            :     // note : chould include terms not belonging to this theory
     122                 :            :     // (commented below)
     123         [ +  + ]:     133950 :     if (current.getNumChildren() > 0)
     124                 :            :     {
     125                 :      78918 :       worklist.insert(worklist.end(), current.begin(), current.end());
     126                 :            :     }
     127                 :            :     else
     128                 :            :     {
     129                 :      55032 :       vars.push_back(current);
     130                 :            :     }
     131                 :            :   }
     132                 :      70160 :   return vars;
     133                 :            : }
     134                 :            : 
     135                 :            : // do inferences
     136                 :      74812 : void ExtTheory::getSubstitutedTerms(int effort,
     137                 :            :                                     const std::vector<Node>& terms,
     138                 :            :                                     std::vector<Node>& sterms,
     139                 :            :                                     std::vector<std::vector<Node> >& exp)
     140                 :            : {
     141         [ +  - ]:     149624 :   Trace("extt-debug") << "getSubstitutedTerms for " << terms.size() << " / "
     142                 :      74812 :                       << d_ext_func_terms.size() << " extended functions."
     143                 :      74812 :                       << std::endl;
     144         [ +  + ]:      74812 :   if (!terms.empty())
     145                 :            :   {
     146                 :            :     // all variables we need to find a substitution for
     147                 :      22374 :     std::vector<Node> vars;
     148                 :      22374 :     std::vector<Node> sub;
     149                 :      22374 :     std::map<Node, std::vector<Node> > expc;
     150         [ +  + ]:      61059 :     for (const Node& n : terms)
     151                 :            :     {
     152                 :            :       // do substitution, rewrite
     153                 :      49872 :       std::map<Node, ExtfInfo>::iterator iti = d_extf_info.find(n);
     154 [ -  + ][ -  + ]:      49872 :       Assert(iti != d_extf_info.end());
                 [ -  - ]
     155         [ +  + ]:     135056 :       for (const Node& v : iti->second.d_vars)
     156                 :            :       {
     157         [ +  + ]:      85184 :         if (std::find(vars.begin(), vars.end(), v) == vars.end())
     158                 :            :         {
     159                 :      45933 :           vars.push_back(v);
     160                 :            :         }
     161                 :            :       }
     162                 :            :     }
     163                 :      11187 :     bool useSubs = d_parent.getCurrentSubstitution(effort, vars, sub, expc);
     164                 :            :     // get the current substitution for all variables
     165 [ +  + ][ -  + ]:      11187 :     Assert(!useSubs || vars.size() == sub.size());
         [ -  + ][ -  - ]
     166         [ +  + ]:      61059 :     for (const Node& n : terms)
     167                 :            :     {
     168                 :      99744 :       Node ns = n;
     169                 :      99744 :       std::vector<Node> expn;
     170         [ +  + ]:      49872 :       if (useSubs)
     171                 :            :       {
     172                 :            :         // do substitution
     173                 :      26270 :         ns = n.substitute(vars.begin(), vars.end(), sub.begin(), sub.end());
     174         [ +  + ]:      26270 :         if (ns != n)
     175                 :            :         {
     176                 :            :           // build explanation: explanation vars = sub for each vars in FV(n)
     177                 :      11976 :           std::map<Node, ExtfInfo>::iterator iti = d_extf_info.find(n);
     178 [ -  + ][ -  + ]:      11976 :           Assert(iti != d_extf_info.end());
                 [ -  - ]
     179         [ +  + ]:      34708 :           for (const Node& v : iti->second.d_vars)
     180                 :            :           {
     181                 :      22732 :             std::map<Node, std::vector<Node> >::iterator itx = expc.find(v);
     182         [ +  + ]:      22732 :             if (itx != expc.end())
     183                 :            :             {
     184         [ +  + ]:      27292 :               for (const Node& e : itx->second)
     185                 :            :               {
     186         [ +  - ]:      13646 :                 if (std::find(expn.begin(), expn.end(), e) == expn.end())
     187                 :            :                 {
     188                 :      13646 :                   expn.push_back(e);
     189                 :            :                 }
     190                 :            :               }
     191                 :            :             }
     192                 :            :           }
     193                 :            :         }
     194         [ +  - ]:      52540 :         Trace("extt-debug") << "  have " << n << " == " << ns
     195                 :      26270 :                             << ", exp size=" << expn.size() << "." << std::endl;
     196                 :            :       }
     197                 :            :       // add to vector
     198                 :      49872 :       sterms.push_back(ns);
     199                 :      49872 :       exp.push_back(expn);
     200                 :            :     }
     201                 :            :   }
     202                 :      74812 : }
     203                 :            : 
     204                 :      74812 : bool ExtTheory::doInferencesInternal(int effort,
     205                 :            :                                      const std::vector<Node>& terms,
     206                 :            :                                      std::vector<Node>& nred)
     207                 :            : {
     208                 :      74812 :   bool addedLemma = false;
     209                 :     149624 :   std::vector<Node> sterms;
     210                 :      74812 :   std::vector<std::vector<Node> > exp;
     211                 :      74812 :   getSubstitutedTerms(effort, terms, sterms, exp);
     212                 :      74812 :   NodeManager* nm = nodeManager();
     213         [ +  + ]:     124684 :   for (unsigned i = 0, size = terms.size(); i < size; i++)
     214                 :            :   {
     215                 :      49872 :     bool processed = false;
     216                 :            :     // if the substitution applied to terms[i] changed it
     217         [ +  + ]:      49872 :     if (sterms[i] != terms[i])
     218                 :            :     {
     219                 :      23952 :       Node sr = rewrite(sterms[i]);
     220                 :            :       // ask the theory if this term is reduced, e.g. is it constant or it
     221                 :            :       // is a non-extf term.
     222                 :            :       ExtReducedId id;
     223         [ +  + ]:      11976 :       if (d_parent.isExtfReduced(effort, sr, terms[i], exp[i], id))
     224                 :            :       {
     225                 :       8602 :         processed = true;
     226                 :       8602 :         markInactive(terms[i], id);
     227                 :            :         // We have exp[i] => terms[i] = sr
     228                 :      17204 :         Node eq = terms[i].eqNode(sr);
     229                 :      17204 :         Node lem = eq;
     230         [ +  - ]:       8602 :         if (!exp[i].empty())
     231                 :            :         {
     232                 :       8602 :           Node antec = nm->mkAnd(exp[i]);
     233                 :       8602 :           lem = nm->mkNode(Kind::IMPLIES, antec, eq);
     234                 :            :         }
     235                 :            :         // will be able to generate a proof for this
     236                 :      17204 :         TrustNode trn = TrustNode::mkTrustLemma(lem, this);
     237                 :            : 
     238         [ +  - ]:      17204 :         Trace("extt-debug") << "ExtTheory::doInferences : infer : " << eq
     239                 :       8602 :                             << " by " << exp[i] << std::endl;
     240         [ +  - ]:       8602 :         Trace("extt-debug") << "...send lemma " << lem << std::endl;
     241         [ +  + ]:       8602 :         if (sendLemma(trn, InferenceId::EXTT_SIMPLIFY))
     242                 :            :         {
     243         [ +  - ]:       6066 :           Trace("extt-lemma")
     244                 :          0 :               << "ExtTheory : substitution + rewrite lemma : " << lem
     245                 :       3033 :               << std::endl;
     246                 :       3033 :           addedLemma = true;
     247                 :            :         }
     248                 :            :       }
     249                 :            :       else
     250                 :            :       {
     251                 :            :         // note : can add (non-reducing) lemma :
     252                 :            :         //   exp[j] ^ exp[i] => sterms[i] = sterms[j]
     253                 :            :         // if there are any duplicates, but we do not do this currently.
     254         [ +  - ]:       3374 :         Trace("extt-nred") << "Non-reduced term : " << sr << std::endl;
     255                 :            :       }
     256                 :            :     }
     257                 :            :     else
     258                 :            :     {
     259         [ +  - ]:      37896 :       Trace("extt-nred") << "Non-reduced term : " << sterms[i] << std::endl;
     260                 :            :     }
     261         [ +  + ]:      49872 :     if (!processed)
     262                 :            :     {
     263                 :      41270 :       nred.push_back(terms[i]);
     264                 :            :     }
     265                 :            :   }
     266                 :            : 
     267                 :     149624 :   return addedLemma;
     268                 :            : }
     269                 :            : 
     270                 :       8602 : bool ExtTheory::sendLemma(TrustNode lem, InferenceId id)
     271                 :            : {
     272                 :      17204 :   const Node& n = lem.getProven();
     273         [ +  + ]:       8602 :   if (d_lemmas.find(n) == d_lemmas.end())
     274                 :            :   {
     275         [ +  + ]:       3514 :     if (d_im.trustedLemma(lem, id))
     276                 :            :     {
     277                 :       3033 :       d_lemmas.insert(n);
     278                 :       3033 :       return true;
     279                 :            :     }
     280                 :            :   }
     281                 :       5569 :   return false;
     282                 :            : }
     283                 :            : 
     284                 :          0 : bool ExtTheory::doInferences(int effort,
     285                 :            :                              const std::vector<Node>& terms,
     286                 :            :                              std::vector<Node>& nred)
     287                 :            : {
     288         [ -  - ]:          0 :   if (!terms.empty())
     289                 :            :   {
     290                 :          0 :     return doInferencesInternal(effort, terms, nred);
     291                 :            :   }
     292                 :          0 :   return false;
     293                 :            : }
     294                 :            : 
     295                 :      74812 : bool ExtTheory::doInferences(int effort, std::vector<Node>& nred)
     296                 :            : {
     297                 :     149624 :   std::vector<Node> terms = getActive();
     298                 :     149624 :   return doInferencesInternal(effort, terms, nred);
     299                 :            : }
     300                 :            : 
     301                 :            : // Register term.
     302                 :     440866 : void ExtTheory::registerTerm(Node n)
     303                 :            : {
     304         [ +  + ]:     440866 :   if (d_extf_kind.find(n.getKind()) != d_extf_kind.end())
     305                 :            :   {
     306         [ +  + ]:     143523 :     if (d_ext_func_terms.find(n) == d_ext_func_terms.end())
     307                 :            :     {
     308         [ +  - ]:      35080 :       Trace("extt-debug") << "Found extended function : " << n << std::endl;
     309                 :      35080 :       d_ext_func_terms[n] = true;
     310                 :      35080 :       d_has_extf = n;
     311                 :      35080 :       d_extf_info[n].d_vars = collectVars(n);
     312                 :            :     }
     313                 :            :   }
     314                 :     440866 : }
     315                 :            : 
     316                 :            : // mark reduced
     317                 :     108443 : void ExtTheory::markInactive(Node n, ExtReducedId rid, bool satDep)
     318                 :            : {
     319         [ +  - ]:     108443 :   Trace("extt-debug") << "Mark reduced " << n << std::endl;
     320                 :     108443 :   registerTerm(n);
     321 [ -  + ][ -  + ]:     108443 :   Assert(d_ext_func_terms.find(n) != d_ext_func_terms.end());
                 [ -  - ]
     322                 :     108443 :   d_ext_func_terms[n] = false;
     323                 :     108443 :   d_extfExtReducedIdMap[n] = rid;
     324         [ -  + ]:     108443 :   if (!satDep)
     325                 :            :   {
     326                 :          0 :     d_ci_inactive[n] = rid;
     327                 :            :   }
     328                 :            : 
     329                 :            :   // update has_extf
     330         [ +  + ]:     108443 :   if (d_has_extf.get() == n)
     331                 :            :   {
     332                 :     180935 :     for (NodeBoolMap::iterator it = d_ext_func_terms.begin();
     333         [ +  + ]:     180935 :          it != d_ext_func_terms.end();
     334                 :     167932 :          ++it)
     335                 :            :     {
     336                 :            :       // if not already reduced
     337 [ +  + ][ +  - ]:     167932 :       if ((*it).second && !isContextIndependentInactive((*it).first))
         [ +  + ][ +  + ]
                 [ -  - ]
     338                 :            :       {
     339                 :      79752 :         d_has_extf = (*it).first;
     340                 :            :       }
     341                 :            :     }
     342                 :            :   }
     343                 :     108443 : }
     344                 :            : 
     345                 :    1244620 : bool ExtTheory::isContextIndependentInactive(Node n) const
     346                 :            : {
     347                 :    1244620 :   ExtReducedId rid = ExtReducedId::UNKNOWN;
     348                 :    1244620 :   return isContextIndependentInactive(n, rid);
     349                 :            : }
     350                 :            : 
     351                 :    1842900 : bool ExtTheory::isContextIndependentInactive(Node n, ExtReducedId& rid) const
     352                 :            : {
     353                 :    1842900 :   NodeExtReducedIdMap::iterator it = d_ci_inactive.find(n);
     354         [ -  + ]:    1842900 :   if (it != d_ci_inactive.end())
     355                 :            :   {
     356                 :          0 :     rid = it->second;
     357                 :          0 :     return true;
     358                 :            :   }
     359                 :    1842900 :   return false;
     360                 :            : }
     361                 :            : 
     362                 :      11307 : void ExtTheory::getTerms(std::vector<Node>& terms)
     363                 :            : {
     364                 :      63672 :   for (NodeBoolMap::iterator it = d_ext_func_terms.begin();
     365         [ +  + ]:      63672 :        it != d_ext_func_terms.end();
     366                 :      52365 :        ++it)
     367                 :            :   {
     368                 :      52365 :     terms.push_back((*it).first);
     369                 :            :   }
     370                 :      11307 : }
     371                 :            : 
     372                 :          0 : bool ExtTheory::hasActiveTerm() const { return !d_has_extf.get().isNull(); }
     373                 :            : 
     374                 :     598281 : bool ExtTheory::isActive(Node n) const
     375                 :            : {
     376                 :     598281 :   ExtReducedId rid = ExtReducedId::UNKNOWN;
     377                 :     598281 :   return isActive(n, rid);
     378                 :            : }
     379                 :            : 
     380                 :     598281 : bool ExtTheory::isActive(Node n, ExtReducedId& rid) const
     381                 :            : {
     382                 :     598281 :   NodeBoolMap::const_iterator it = d_ext_func_terms.find(n);
     383         [ +  - ]:     598281 :   if (it != d_ext_func_terms.end())
     384                 :            :   {
     385         [ +  - ]:     598281 :     if ((*it).second)
     386                 :            :     {
     387                 :     598281 :       return !isContextIndependentInactive(n, rid);
     388                 :            :     }
     389                 :          0 :     NodeExtReducedIdMap::const_iterator itr = d_extfExtReducedIdMap.find(n);
     390                 :          0 :     Assert(itr != d_extfExtReducedIdMap.end());
     391                 :          0 :     rid = itr->second;
     392                 :          0 :     return false;
     393                 :            :   }
     394                 :          0 :   return false;
     395                 :            : }
     396                 :            : 
     397                 :            : // get active
     398                 :     269212 : std::vector<Node> ExtTheory::getActive() const
     399                 :            : {
     400                 :     269212 :   std::vector<Node> active;
     401                 :    1685630 :   for (NodeBoolMap::iterator it = d_ext_func_terms.begin();
     402         [ +  + ]:    1685630 :        it != d_ext_func_terms.end();
     403                 :    1416420 :        ++it)
     404                 :            :   {
     405                 :            :     // if not already reduced
     406 [ +  + ][ +  - ]:    1416420 :     if ((*it).second && !isContextIndependentInactive((*it).first))
         [ +  + ][ +  + ]
                 [ -  - ]
     407                 :            :     {
     408                 :    1161160 :       active.push_back((*it).first);
     409                 :            :     }
     410                 :            :   }
     411                 :     269212 :   return active;
     412                 :            : }
     413                 :            : 
     414                 :      32040 : std::vector<Node> ExtTheory::getActive(Kind k) const
     415                 :            : {
     416                 :      32040 :   std::vector<Node> active;
     417                 :      82392 :   for (NodeBoolMap::iterator it = d_ext_func_terms.begin();
     418         [ +  + ]:      82392 :        it != d_ext_func_terms.end();
     419                 :      50352 :        ++it)
     420                 :            :   {
     421                 :            :     // if not already reduced
     422         [ +  + ]:      59952 :     if ((*it).first.getKind() == k && (*it).second
     423 [ +  + ][ +  - ]:     110304 :         && !isContextIndependentInactive((*it).first))
         [ +  + ][ +  + ]
                 [ -  - ]
     424                 :            :     {
     425                 :       3707 :       active.push_back((*it).first);
     426                 :            :     }
     427                 :            :   }
     428                 :      32040 :   return active;
     429                 :            : }
     430                 :            : 
     431                 :        522 : std::shared_ptr<ProofNode> ExtTheory::getProofFor(Node fact)
     432                 :            : {
     433                 :       1566 :   CDProof proof(d_env);
     434                 :       1044 :   std::vector<Node> antec;
     435                 :       1044 :   Node conc = fact;
     436         [ +  - ]:        522 :   if (conc.getKind() == Kind::IMPLIES)
     437                 :            :   {
     438         [ +  + ]:        522 :     if (conc[0].getKind() == Kind::AND)
     439                 :            :     {
     440                 :         72 :       antec.insert(antec.end(), conc[0].begin(), conc[0].end());
     441                 :            :     }
     442                 :            :     else
     443                 :            :     {
     444                 :        450 :       antec.push_back(conc[0]);
     445                 :            :     }
     446                 :        522 :     conc = conc[1];
     447                 :            :   }
     448                 :        522 :   ProofChecker* pc = d_env.getProofNodeManager()->getChecker();
     449                 :            :   Node res =
     450                 :       2088 :       pc->checkDebug(ProofRule::MACRO_SR_PRED_INTRO, antec, {conc}, conc);
     451         [ -  + ]:        522 :   if (res.isNull())
     452                 :            :   {
     453                 :          0 :     Assert(false) << "ExtTheory failed to prove " << fact;
     454                 :            :     return nullptr;
     455                 :            :   }
     456                 :       1044 :   proof.addStep(conc, ProofRule::MACRO_SR_PRED_INTRO, antec, {conc});
     457         [ +  - ]:        522 :   if (!antec.empty())
     458                 :            :   {
     459                 :       1044 :     proof.addStep(fact, ProofRule::SCOPE, {conc}, antec);
     460                 :            :   }
     461                 :            :   // t1 = s1 ... tn = sn
     462                 :            :   // -------------------- MACRO_SR_PRED_INTRO {t}
     463                 :            :   // t = s
     464                 :            :   // ----------------------------------- SCOPE {t1 = s1 ... tn = sn}
     465                 :            :   // (t1 = s1 ^ ... ^ tn = sn) => (t = s).
     466                 :        522 :   return proof.getProofFor(fact);
     467                 :            : }
     468                 :            : 
     469                 :        189 : std::string ExtTheory::identify() const { return "ExtTheory"; }
     470                 :            : 
     471                 :            : }  // namespace theory
     472                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14