LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/preprocessing/util - ite_utilities.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 437 977 44.7 %
Date: 2024-11-18 12:41:18 Functions: 47 74 63.5 %
Branches: 258 599 43.1 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * Top contributors (to current version):
       3                 :            :  *   Tim King, Aina Niemetz, Clark Barrett
       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                 :            :  * Simplifications for ITE expressions.
      14                 :            :  *
      15                 :            :  * This module implements preprocessing phases designed to simplify ITE
      16                 :            :  * expressions.  Based on:
      17                 :            :  * Kim, Somenzi, Jin.  Efficient Term-ITE Conversion for SMT.  FMCAD 2009.
      18                 :            :  * Burch, Jerry.  Techniques for Verifying Superscalar Microprocessors.  DAC
      19                 :            :  *'96
      20                 :            :  */
      21                 :            : #include "preprocessing/util/ite_utilities.h"
      22                 :            : 
      23                 :            : #include <utility>
      24                 :            : 
      25                 :            : #include "expr/skolem_manager.h"
      26                 :            : #include "preprocessing/assertion_pipeline.h"
      27                 :            : #include "preprocessing/passes/rewrite.h"
      28                 :            : #include "theory/theory.h"
      29                 :            : #include "util/rational.h"
      30                 :            : 
      31                 :            : using namespace std;
      32                 :            : namespace cvc5::internal {
      33                 :            : namespace preprocessing {
      34                 :            : namespace util {
      35                 :            : 
      36                 :            : namespace ite {
      37                 :            : 
      38                 :     110732 : inline static bool isTermITE(TNode e)
      39                 :            : {
      40 [ +  + ][ +  + ]:     110732 :   return (e.getKind() == Kind::ITE && !e.getType().isBoolean());
         [ +  + ][ -  - ]
      41                 :            : }
      42                 :            : 
      43                 :     188185 : inline static bool triviallyContainsNoTermITEs(TNode e)
      44                 :            : {
      45 [ +  + ][ +  + ]:     188185 :   return e.isConst() || e.isVar();
      46                 :            : }
      47                 :            : 
      48                 :       5258 : static bool isTheoryAtom(TNode a)
      49                 :            : {
      50                 :            :   using namespace kind;
      51 [ +  - ][ +  + ]:       5258 :   switch (a.getKind())
      52                 :            :   {
      53                 :        109 :     case Kind::EQUAL:
      54                 :        109 :     case Kind::DISTINCT: return !(a[0].getType().isBoolean());
      55                 :            : 
      56                 :            :     /* from uf */
      57                 :          0 :     case Kind::APPLY_UF: return a.getType().isBoolean();
      58                 :         44 :     case Kind::CARDINALITY_CONSTRAINT:
      59                 :            :     case Kind::DIVISIBLE:
      60                 :            :     case Kind::LT:
      61                 :            :     case Kind::LEQ:
      62                 :            :     case Kind::GT:
      63                 :            :     case Kind::GEQ:
      64                 :            :     case Kind::IS_INTEGER:
      65                 :            :     case Kind::BITVECTOR_COMP:
      66                 :            :     case Kind::BITVECTOR_ULT:
      67                 :            :     case Kind::BITVECTOR_ULE:
      68                 :            :     case Kind::BITVECTOR_UGT:
      69                 :            :     case Kind::BITVECTOR_UGE:
      70                 :            :     case Kind::BITVECTOR_SLT:
      71                 :            :     case Kind::BITVECTOR_SLE:
      72                 :            :     case Kind::BITVECTOR_SGT:
      73                 :         44 :     case Kind::BITVECTOR_SGE: return true;
      74                 :       5105 :     default: return false;
      75                 :            :   }
      76                 :            : }
      77                 :            : 
      78                 :            : struct CTIVStackElement
      79                 :            : {
      80                 :            :   TNode curr;
      81                 :            :   unsigned pos;
      82                 :            :   CTIVStackElement() : curr(), pos(0) {}
      83                 :      89245 :   CTIVStackElement(TNode c) : curr(c), pos(0) {}
      84                 :            : }; /* CTIVStackElement */
      85                 :            : 
      86                 :            : }  // namespace ite
      87                 :            : 
      88                 :      50436 : ITEUtilities::ITEUtilities(Env& env)
      89                 :            :     : EnvObj(env),
      90                 :      50436 :       d_containsVisitor(new ContainsTermITEVisitor()),
      91                 :            :       d_compressor(NULL),
      92                 :            :       d_simplifier(NULL),
      93                 :     100872 :       d_careSimp(NULL)
      94                 :            : {
      95 [ -  + ][ -  + ]:      50436 :   Assert(d_containsVisitor != NULL);
                 [ -  - ]
      96                 :      50436 : }
      97                 :            : 
      98                 :      50180 : ITEUtilities::~ITEUtilities()
      99                 :            : {
     100         [ +  + ]:      50180 :   if (d_simplifier != NULL)
     101                 :            :   {
     102         [ +  - ]:          1 :     delete d_simplifier;
     103                 :            :   }
     104         [ +  + ]:      50180 :   if (d_compressor != NULL)
     105                 :            :   {
     106         [ +  - ]:          1 :     delete d_compressor;
     107                 :            :   }
     108         [ -  + ]:      50180 :   if (d_careSimp != NULL)
     109                 :            :   {
     110         [ -  - ]:          0 :     delete d_careSimp;
     111                 :            :   }
     112                 :      50180 : }
     113                 :            : 
     114                 :          1 : Node ITEUtilities::simpITE(TNode assertion)
     115                 :            : {
     116         [ +  - ]:          1 :   if (d_simplifier == NULL)
     117                 :            :   {
     118                 :          1 :     d_simplifier = new ITESimplifier(d_env, d_containsVisitor.get());
     119                 :            :   }
     120                 :          1 :   return d_simplifier->simpITE(assertion);
     121                 :            : }
     122                 :            : 
     123                 :          5 : bool ITEUtilities::simpIteDidALotOfWorkHeuristic() const
     124                 :            : {
     125         [ +  + ]:          5 :   if (d_simplifier == NULL)
     126                 :            :   {
     127                 :          4 :     return false;
     128                 :            :   }
     129                 :            :   else
     130                 :            :   {
     131                 :          1 :     return d_simplifier->doneALotOfWorkHeuristic();
     132                 :            :   }
     133                 :            : }
     134                 :            : 
     135                 :            : /* returns false if an assertion is discovered to be equal to false. */
     136                 :          1 : bool ITEUtilities::compress(AssertionPipeline* assertionsToPreprocess)
     137                 :            : {
     138         [ +  - ]:          1 :   if (d_compressor == NULL)
     139                 :            :   {
     140                 :          1 :     d_compressor = new ITECompressor(d_env, d_containsVisitor.get());
     141                 :            :   }
     142                 :          1 :   return d_compressor->compress(assertionsToPreprocess);
     143                 :            : }
     144                 :            : 
     145                 :          0 : Node ITEUtilities::simplifyWithCare(TNode e)
     146                 :            : {
     147         [ -  - ]:          0 :   if (d_careSimp == NULL)
     148                 :            :   {
     149                 :          0 :     d_careSimp = new ITECareSimplifier(nodeManager());
     150                 :            :   }
     151                 :          0 :   return d_careSimp->simplifyWithCare(e);
     152                 :            : }
     153                 :            : 
     154                 :          0 : void ITEUtilities::clear()
     155                 :            : {
     156         [ -  - ]:          0 :   if (d_simplifier != NULL)
     157                 :            :   {
     158                 :          0 :     d_simplifier->clearSimpITECaches();
     159                 :            :   }
     160         [ -  - ]:          0 :   if (d_compressor != NULL)
     161                 :            :   {
     162                 :          0 :     d_compressor->garbageCollect();
     163                 :            :   }
     164         [ -  - ]:          0 :   if (d_careSimp != NULL)
     165                 :            :   {
     166                 :          0 :     d_careSimp->clear();
     167                 :            :   }
     168                 :          0 :   d_containsVisitor->garbageCollect();
     169                 :          0 : }
     170                 :            : 
     171                 :            : /** ContainsTermITEVisitor. */
     172                 :      81852 : ContainsTermITEVisitor::ContainsTermITEVisitor() : d_cache() {}
     173                 :      81596 : ContainsTermITEVisitor::~ContainsTermITEVisitor() {}
     174                 :      34212 : bool ContainsTermITEVisitor::containsTermITE(TNode e)
     175                 :            : {
     176                 :            :   /* throughout execution skip through NOT nodes. */
     177         [ -  + ]:      34212 :   e = (e.getKind() == Kind::NOT) ? e[0] : e;
     178         [ +  + ]:      34212 :   if (ite::triviallyContainsNoTermITEs(e))
     179                 :            :   {
     180                 :      10533 :     return false;
     181                 :            :   }
     182                 :            : 
     183                 :      23679 :   NodeBoolMap::const_iterator end = d_cache.end();
     184                 :      23679 :   NodeBoolMap::const_iterator tmp_it = d_cache.find(e);
     185         [ +  + ]:      23679 :   if (tmp_it != end)
     186                 :            :   {
     187                 :       1178 :     return (*tmp_it).second;
     188                 :            :   }
     189                 :            : 
     190                 :      22501 :   bool foundTermIte = false;
     191                 :      22501 :   std::vector<ite::CTIVStackElement> stack;
     192                 :      22501 :   stack.push_back(ite::CTIVStackElement(e));
     193 [ +  + ][ +  + ]:     263734 :   while (!foundTermIte && !stack.empty())
                 [ +  + ]
     194                 :            :   {
     195                 :     241233 :     ite::CTIVStackElement& top = stack.back();
     196                 :     482466 :     TNode curr = top.curr;
     197         [ +  + ]:     241233 :     if (top.pos >= curr.getNumChildren())
     198                 :            :     {
     199                 :            :       // all of the children have been visited
     200                 :            :       // no term ites were found
     201                 :      87260 :       d_cache[curr] = false;
     202                 :      87260 :       stack.pop_back();
     203                 :            :     }
     204                 :            :     else
     205                 :            :     {
     206                 :            :       // this is someone's child
     207                 :     307946 :       TNode child = curr[top.pos];
     208         [ +  + ]:     153973 :       child = (child.getKind() == Kind::NOT) ? child[0] : child;
     209                 :     153973 :       ++top.pos;
     210         [ +  + ]:     153973 :       if (ite::triviallyContainsNoTermITEs(child))
     211                 :            :       {
     212                 :            :         // skip
     213                 :            :       }
     214                 :            :       else
     215                 :            :       {
     216                 :      68033 :         tmp_it = d_cache.find(child);
     217         [ +  + ]:      68033 :         if (tmp_it != end)
     218                 :            :         {
     219                 :       1289 :           foundTermIte = (*tmp_it).second;
     220                 :            :         }
     221                 :            :         else
     222                 :            :         {
     223                 :      66744 :           stack.push_back(ite::CTIVStackElement(child));
     224                 :      66744 :           foundTermIte = ite::isTermITE(child);
     225                 :            :         }
     226                 :            :       }
     227                 :            :     }
     228                 :            :   }
     229         [ +  + ]:      22501 :   if (foundTermIte)
     230                 :            :   {
     231         [ +  + ]:       3512 :     while (!stack.empty())
     232                 :            :     {
     233                 :       1985 :       TNode curr = stack.back().curr;
     234                 :       1985 :       stack.pop_back();
     235                 :       1985 :       d_cache[curr] = true;
     236                 :            :     }
     237                 :            :   }
     238                 :      22501 :   return foundTermIte;
     239                 :            : }
     240                 :          0 : void ContainsTermITEVisitor::garbageCollect() { d_cache.clear(); }
     241                 :            : 
     242                 :            : /** IncomingArcCounter. */
     243                 :          1 : IncomingArcCounter::IncomingArcCounter(bool skipVars, bool skipConstants)
     244                 :          1 :     : d_reachCount(), d_skipVariables(skipVars), d_skipConstants(skipConstants)
     245                 :            : {
     246                 :          1 : }
     247                 :          1 : IncomingArcCounter::~IncomingArcCounter() {}
     248                 :            : 
     249                 :          1 : void IncomingArcCounter::computeReachability(
     250                 :            :     const std::vector<Node>& assertions)
     251                 :            : {
     252                 :          3 :   std::vector<TNode> tovisit(assertions.begin(), assertions.end());
     253                 :            : 
     254         [ +  + ]:     114525 :   while (!tovisit.empty())
     255                 :            :   {
     256                 :     114524 :     TNode back = tovisit.back();
     257                 :     114524 :     tovisit.pop_back();
     258                 :            : 
     259                 :     114524 :     bool skip = false;
     260    [ +  + ][ + ]:     114524 :     switch (back.getMetaKind())
     261                 :            :     {
     262                 :        306 :       case kind::metakind::CONSTANT: skip = d_skipConstants; break;
     263                 :        210 :       case kind::metakind::VARIABLE: skip = d_skipVariables; break;
     264                 :     114008 :       default: break;
     265                 :            :     }
     266                 :            : 
     267         [ +  + ]:     114524 :     if (skip)
     268                 :            :     {
     269                 :        516 :       continue;
     270                 :            :     }
     271         [ +  + ]:     114008 :     if (d_reachCount.find(back) != d_reachCount.end())
     272                 :            :     {
     273                 :     106422 :       d_reachCount[back] = 1 + d_reachCount[back];
     274                 :            :     }
     275                 :            :     else
     276                 :            :     {
     277                 :       7586 :       d_reachCount[back] = 1;
     278         [ +  + ]:     122106 :       for (TNode::iterator cit = back.begin(), end = back.end(); cit != end;
     279                 :     114520 :            ++cit)
     280                 :            :       {
     281                 :     114520 :         tovisit.push_back(*cit);
     282                 :            :       }
     283                 :            :     }
     284                 :            :   }
     285                 :          1 : }
     286                 :            : 
     287                 :          2 : void IncomingArcCounter::clear() { d_reachCount.clear(); }
     288                 :            : 
     289                 :            : /** ITECompressor. */
     290                 :          1 : ITECompressor::ITECompressor(Env& env, ContainsTermITEVisitor* contains)
     291                 :            :     : EnvObj(env),
     292                 :            :       d_contains(contains),
     293                 :            :       d_assertions(NULL),
     294                 :            :       d_incoming(true, true),
     295                 :          1 :       d_statistics(env.getStatisticsRegistry())
     296                 :            : {
     297 [ -  + ][ -  + ]:          1 :   Assert(d_contains != NULL);
                 [ -  - ]
     298                 :            : 
     299                 :          1 :   d_true = nodeManager()->mkConst<bool>(true);
     300                 :          1 :   d_false = nodeManager()->mkConst<bool>(false);
     301                 :          1 : }
     302                 :            : 
     303                 :          2 : ITECompressor::~ITECompressor() { reset(); }
     304                 :            : 
     305                 :          2 : void ITECompressor::reset()
     306                 :            : {
     307                 :          2 :   d_incoming.clear();
     308                 :          2 :   d_compressed.clear();
     309                 :          2 : }
     310                 :            : 
     311                 :          0 : void ITECompressor::garbageCollect() { reset(); }
     312                 :            : 
     313                 :          1 : ITECompressor::Statistics::Statistics(StatisticsRegistry& reg)
     314                 :          1 :     : d_compressCalls(reg.registerInt("ite-simp::compressCalls")),
     315                 :          1 :       d_skolemsAdded(reg.registerInt("ite-simp::skolems"))
     316                 :            : {
     317                 :          1 : }
     318                 :            : 
     319                 :       1720 : Node ITECompressor::push_back_boolean(Node original, Node compressed)
     320                 :            : {
     321                 :       3440 :   Node rewritten = rewrite(compressed);
     322                 :            :   // There is a bug if the rewritter takes a pure boolean expression
     323                 :            :   // and changes its theory
     324         [ -  + ]:       1720 :   if (rewritten.isConst())
     325                 :            :   {
     326                 :          0 :     d_compressed[compressed] = rewritten;
     327                 :          0 :     d_compressed[original] = rewritten;
     328                 :          0 :     d_compressed[rewritten] = rewritten;
     329                 :          0 :     return rewritten;
     330                 :            :   }
     331         [ -  + ]:       1720 :   else if (d_compressed.find(rewritten) != d_compressed.end())
     332                 :            :   {
     333                 :          0 :     Node res = d_compressed[rewritten];
     334                 :          0 :     d_compressed[original] = res;
     335                 :          0 :     d_compressed[compressed] = res;
     336                 :          0 :     return res;
     337                 :            :   }
     338                 :       5160 :   else if (rewritten.isVar()
     339 [ +  - ][ +  + ]:       1720 :            || (rewritten.getKind() == Kind::NOT && rewritten[0].isVar()))
         [ +  + ][ +  + ]
         [ +  + ][ -  - ]
     340                 :            :   {
     341                 :        511 :     d_compressed[original] = rewritten;
     342                 :        511 :     d_compressed[compressed] = rewritten;
     343                 :        511 :     d_compressed[rewritten] = rewritten;
     344                 :        511 :     return rewritten;
     345                 :            :   }
     346                 :            :   else
     347                 :            :   {
     348                 :       1209 :     NodeManager* nm = nodeManager();
     349                 :       1209 :     SkolemManager* sm = nm->getSkolemManager();
     350                 :       3627 :     Node skolem = sm->mkDummySkolem("compress", nm->booleanType());
     351                 :       1209 :     d_compressed[rewritten] = skolem;
     352                 :       1209 :     d_compressed[original] = skolem;
     353                 :       1209 :     d_compressed[compressed] = skolem;
     354                 :            : 
     355                 :       2418 :     Node iff = skolem.eqNode(rewritten);
     356                 :       1209 :     d_assertions->push_back(iff);
     357                 :       1209 :     ++(d_statistics.d_skolemsAdded);
     358                 :       1209 :     return skolem;
     359                 :            :   }
     360                 :            : }
     361                 :            : 
     362                 :       7109 : bool ITECompressor::multipleParents(TNode c)
     363                 :            : {
     364                 :       7109 :   return d_incoming.lookupIncoming(c) >= 2;
     365                 :            : }
     366                 :            : 
     367                 :       1920 : Node ITECompressor::compressBooleanITEs(Node toCompress)
     368                 :            : {
     369 [ -  + ][ -  + ]:       1920 :   Assert(toCompress.getKind() == Kind::ITE);
                 [ -  - ]
     370 [ -  + ][ -  + ]:       1920 :   Assert(toCompress.getType().isBoolean());
                 [ -  - ]
     371                 :            : 
     372                 :       1920 :   if (!(toCompress[1] == d_false || toCompress[2] == d_false))
     373                 :            :   {
     374                 :       3840 :     Node cmpCnd = compressBoolean(toCompress[0]);
     375         [ -  + ]:       1920 :     if (cmpCnd.isConst())
     376                 :            :     {
     377         [ -  - ]:          0 :       Node branch = (cmpCnd == d_true) ? toCompress[1] : toCompress[2];
     378                 :          0 :       Node res = compressBoolean(branch);
     379                 :          0 :       d_compressed[toCompress] = res;
     380                 :          0 :       return res;
     381                 :            :     }
     382                 :            :     else
     383                 :            :     {
     384                 :       3840 :       Node cmpThen = compressBoolean(toCompress[1]);
     385                 :       3840 :       Node cmpElse = compressBoolean(toCompress[2]);
     386                 :       3840 :       Node newIte = cmpCnd.iteNode(cmpThen, cmpElse);
     387         [ +  + ]:       1920 :       if (multipleParents(toCompress))
     388                 :            :       {
     389                 :        534 :         return push_back_boolean(toCompress, newIte);
     390                 :            :       }
     391                 :            :       else
     392                 :            :       {
     393                 :       1386 :         return newIte;
     394                 :            :       }
     395                 :            :     }
     396                 :            :   }
     397                 :            : 
     398                 :          0 :   NodeBuilder nb(Kind::AND);
     399                 :          0 :   Node curr = toCompress;
     400                 :          0 :   while (curr.getKind() == Kind::ITE
     401                 :          0 :          && (curr[1] == d_false || curr[2] == d_false)
     402                 :          0 :          && (!multipleParents(curr) || curr == toCompress))
     403                 :            :   {
     404                 :          0 :     bool negateCnd = (curr[1] == d_false);
     405                 :          0 :     Node compressCnd = compressBoolean(curr[0]);
     406         [ -  - ]:          0 :     if (compressCnd.isConst())
     407                 :            :     {
     408         [ -  - ]:          0 :       if (compressCnd.getConst<bool>() == negateCnd)
     409                 :            :       {
     410                 :          0 :         return push_back_boolean(toCompress, d_false);
     411                 :            :       }
     412                 :            :       else
     413                 :            :       {
     414                 :            :         // equivalent to true don't push back
     415                 :            :       }
     416                 :            :     }
     417                 :            :     else
     418                 :            :     {
     419         [ -  - ]:          0 :       Node pb = negateCnd ? compressCnd.notNode() : compressCnd;
     420                 :          0 :       nb << pb;
     421                 :            :     }
     422         [ -  - ]:          0 :     curr = negateCnd ? curr[2] : curr[1];
     423                 :            :   }
     424                 :          0 :   Assert(toCompress != curr);
     425                 :            : 
     426                 :          0 :   nb << compressBoolean(curr);
     427         [ -  - ]:          0 :   Node res = nb.getNumChildren() == 1 ? nb[0] : (Node)nb;
     428                 :          0 :   return push_back_boolean(toCompress, res);
     429                 :            : }
     430                 :            : 
     431                 :       1122 : Node ITECompressor::compressTerm(Node toCompress)
     432                 :            : {
     433 [ +  + ][ +  + ]:       1122 :   if (toCompress.isConst() || toCompress.isVar())
                 [ +  + ]
     434                 :            :   {
     435                 :        513 :     return toCompress;
     436                 :            :   }
     437                 :            : 
     438         [ +  + ]:        609 :   if (d_compressed.find(toCompress) != d_compressed.end())
     439                 :            :   {
     440                 :        201 :     return d_compressed[toCompress];
     441                 :            :   }
     442         [ +  + ]:        408 :   if (toCompress.getKind() == Kind::ITE)
     443                 :            :   {
     444                 :        648 :     Node cmpCnd = compressBoolean(toCompress[0]);
     445         [ -  + ]:        324 :     if (cmpCnd.isConst())
     446                 :            :     {
     447         [ -  - ]:          0 :       Node branch = (cmpCnd == d_true) ? toCompress[1] : toCompress[2];
     448                 :          0 :       Node res = compressTerm(branch);
     449                 :          0 :       d_compressed[toCompress] = res;
     450                 :          0 :       return res;
     451                 :            :     }
     452                 :            :     else
     453                 :            :     {
     454                 :        648 :       Node cmpThen = compressTerm(toCompress[1]);
     455                 :        648 :       Node cmpElse = compressTerm(toCompress[2]);
     456                 :        648 :       Node newIte = cmpCnd.iteNode(cmpThen, cmpElse);
     457                 :        324 :       d_compressed[toCompress] = newIte;
     458                 :        324 :       return newIte;
     459                 :            :     }
     460                 :            :   }
     461                 :            : 
     462                 :        168 :   NodeBuilder nb(toCompress.getKind());
     463                 :            : 
     464         [ -  + ]:         84 :   if (toCompress.getMetaKind() == kind::metakind::PARAMETERIZED)
     465                 :            :   {
     466                 :          0 :     nb << (toCompress.getOperator());
     467                 :            :   }
     468                 :        252 :   for (Node::iterator it = toCompress.begin(), end = toCompress.end();
     469         [ +  + ]:        252 :        it != end;
     470                 :        168 :        ++it)
     471                 :            :   {
     472                 :        168 :     nb << compressTerm(*it);
     473                 :            :   }
     474                 :        168 :   Node compressed = (Node)nb;
     475         [ +  + ]:         84 :   if (multipleParents(toCompress))
     476                 :            :   {
     477                 :         13 :     d_compressed[toCompress] = compressed;
     478                 :            :   }
     479                 :         84 :   return compressed;
     480                 :            : }
     481                 :            : 
     482                 :     113402 : Node ITECompressor::compressBoolean(Node toCompress)
     483                 :            : {
     484 [ +  + ][ -  + ]:     113402 :   if (toCompress.isConst() || toCompress.isVar())
                 [ +  + ]
     485                 :            :   {
     486                 :          3 :     return toCompress;
     487                 :            :   }
     488         [ +  + ]:     113399 :   if (d_compressed.find(toCompress) != d_compressed.end())
     489                 :            :   {
     490                 :     106221 :     return d_compressed[toCompress];
     491                 :            :   }
     492         [ +  + ]:       7178 :   else if (toCompress.getKind() == Kind::ITE)
     493                 :            :   {
     494                 :       1920 :     return compressBooleanITEs(toCompress);
     495                 :            :   }
     496                 :            :   else
     497                 :            :   {
     498                 :       5258 :     bool ta = ite::isTheoryAtom(toCompress);
     499                 :      10516 :     NodeBuilder nb(toCompress.getKind());
     500         [ -  + ]:       5258 :     if (toCompress.getMetaKind() == kind::metakind::PARAMETERIZED)
     501                 :            :     {
     502                 :          0 :       nb << (toCompress.getOperator());
     503                 :            :     }
     504                 :     112878 :     for (Node::iterator it = toCompress.begin(), end = toCompress.end();
     505         [ +  + ]:     112878 :          it != end;
     506                 :     107620 :          ++it)
     507                 :            :     {
     508                 :     214934 :       Node pb = (ta) ? compressTerm(*it) : compressBoolean(*it);
     509                 :     107620 :       nb << pb;
     510                 :            :     }
     511                 :      10516 :     Node compressed = nb;
     512 [ +  + ][ +  + ]:       5258 :     if (ta || multipleParents(toCompress))
         [ +  + ][ +  + ]
                 [ -  - ]
     513                 :            :     {
     514                 :       1186 :       return push_back_boolean(toCompress, compressed);
     515                 :            :     }
     516                 :            :     else
     517                 :            :     {
     518                 :       4072 :       return compressed;
     519                 :            :     }
     520                 :            :   }
     521                 :            : }
     522                 :            : 
     523                 :          1 : bool ITECompressor::compress(AssertionPipeline* assertionsToPreprocess)
     524                 :            : {
     525                 :          1 :   reset();
     526                 :            : 
     527                 :          1 :   d_assertions = assertionsToPreprocess;
     528                 :          1 :   d_incoming.computeReachability(assertionsToPreprocess->ref());
     529                 :            : 
     530                 :          1 :   ++(d_statistics.d_compressCalls);
     531                 :          1 :   verbose(2) << "Computed reachability" << endl;
     532                 :            : 
     533                 :          1 :   bool nofalses = true;
     534                 :          1 :   const std::vector<Node>& assertions = assertionsToPreprocess->ref();
     535                 :          1 :   size_t original_size = assertions.size();
     536                 :          1 :   verbose(2) << "compressing " << original_size << endl;
     537 [ +  + ][ +  - ]:          5 :   for (size_t i = 0; i < original_size && nofalses; ++i)
     538                 :            :   {
     539                 :          8 :     Node assertion = assertions[i];
     540                 :          8 :     Node compressed = compressBoolean(assertion);
     541                 :          4 :     Node rewritten = rewrite(compressed);
     542                 :            :     // replace
     543                 :          4 :     assertionsToPreprocess->replace(i, rewritten);
     544 [ -  + ][ -  + ]:          4 :     Assert(!d_contains->containsTermITE(rewritten));
                 [ -  - ]
     545                 :            : 
     546                 :          4 :     nofalses = (rewritten != d_false);
     547                 :            :   }
     548                 :            : 
     549                 :          1 :   d_assertions = NULL;
     550                 :            : 
     551                 :          1 :   return nofalses;
     552                 :            : }
     553                 :            : 
     554                 :          1 : TermITEHeightCounter::TermITEHeightCounter() : d_termITEHeight() {}
     555                 :            : 
     556                 :          1 : TermITEHeightCounter::~TermITEHeightCounter() {}
     557                 :            : 
     558                 :          1 : void TermITEHeightCounter::clear() { d_termITEHeight.clear(); }
     559                 :            : 
     560                 :          0 : size_t TermITEHeightCounter::cache_size() const
     561                 :            : {
     562                 :          0 :   return d_termITEHeight.size();
     563                 :            : }
     564                 :            : 
     565                 :            : namespace ite {
     566                 :            : struct TITEHStackElement
     567                 :            : {
     568                 :            :   TNode curr;
     569                 :            :   unsigned pos;
     570                 :            :   uint32_t maxChildHeight;
     571                 :            :   TITEHStackElement() : curr(), pos(0), maxChildHeight(0) {}
     572                 :          0 :   TITEHStackElement(TNode c) : curr(c), pos(0), maxChildHeight(0) {}
     573                 :            : };
     574                 :            : } /* namespace ite */
     575                 :            : 
     576                 :          0 : uint32_t TermITEHeightCounter::termITEHeight(TNode e)
     577                 :            : {
     578         [ -  - ]:          0 :   if (ite::triviallyContainsNoTermITEs(e))
     579                 :            :   {
     580                 :          0 :     return 0;
     581                 :            :   }
     582                 :            : 
     583                 :          0 :   NodeCountMap::const_iterator end = d_termITEHeight.end();
     584                 :          0 :   NodeCountMap::const_iterator tmp_it = d_termITEHeight.find(e);
     585         [ -  - ]:          0 :   if (tmp_it != end)
     586                 :            :   {
     587                 :          0 :     return (*tmp_it).second;
     588                 :            :   }
     589                 :            : 
     590                 :          0 :   uint32_t returnValue = 0;
     591                 :            :   // This is initially 0 as the very first call this is included in the max,
     592                 :            :   // but this has no effect.
     593                 :          0 :   std::vector<ite::TITEHStackElement> stack;
     594                 :          0 :   stack.push_back(ite::TITEHStackElement(e));
     595         [ -  - ]:          0 :   while (!stack.empty())
     596                 :            :   {
     597                 :          0 :     ite::TITEHStackElement& top = stack.back();
     598                 :          0 :     top.maxChildHeight = std::max(top.maxChildHeight, returnValue);
     599                 :          0 :     TNode curr = top.curr;
     600         [ -  - ]:          0 :     if (top.pos >= curr.getNumChildren())
     601                 :            :     {
     602                 :            :       // done with the current node
     603         [ -  - ]:          0 :       returnValue = top.maxChildHeight + (ite::isTermITE(curr) ? 1 : 0);
     604                 :          0 :       d_termITEHeight[curr] = returnValue;
     605                 :          0 :       stack.pop_back();
     606                 :          0 :       continue;
     607                 :            :     }
     608                 :            :     else
     609                 :            :     {
     610                 :          0 :       if (top.pos == 0 && curr.getKind() == Kind::ITE)
     611                 :            :       {
     612                 :          0 :         ++top.pos;
     613                 :          0 :         returnValue = 0;
     614                 :          0 :         continue;
     615                 :            :       }
     616                 :            :       // this is someone's child
     617                 :          0 :       TNode child = curr[top.pos];
     618                 :          0 :       ++top.pos;
     619         [ -  - ]:          0 :       if (ite::triviallyContainsNoTermITEs(child))
     620                 :            :       {
     621                 :          0 :         returnValue = 0;
     622                 :            :       }
     623                 :            :       else
     624                 :            :       {
     625                 :          0 :         tmp_it = d_termITEHeight.find(child);
     626         [ -  - ]:          0 :         if (tmp_it != end)
     627                 :            :         {
     628                 :          0 :           returnValue = (*tmp_it).second;
     629                 :            :         }
     630                 :            :         else
     631                 :            :         {
     632                 :          0 :           stack.push_back(ite::TITEHStackElement(child));
     633                 :            :         }
     634                 :            :       }
     635                 :            :     }
     636                 :            :   }
     637                 :          0 :   return returnValue;
     638                 :            : }
     639                 :            : 
     640                 :          1 : ITESimplifier::ITESimplifier(Env& env, ContainsTermITEVisitor* contains)
     641                 :            :     : EnvObj(env),
     642                 :            :       d_containsVisitor(contains),
     643                 :            :       d_termITEHeight(),
     644                 :            :       d_constantLeaves(),
     645                 :            :       d_allocatedConstantLeaves(),
     646                 :            :       d_citeEqConstApplications(0),
     647                 :            :       d_constantIteEqualsConstantCache(),
     648                 :            :       d_replaceOverCache(),
     649                 :            :       d_replaceOverTermIteCache(),
     650                 :            :       d_leavesConstCache(),
     651                 :            :       d_simpConstCache(),
     652                 :            :       d_simpContextCache(),
     653                 :            :       d_simpITECache(),
     654                 :          1 :       d_statistics(env.getStatisticsRegistry())
     655                 :            : {
     656 [ -  + ][ -  + ]:          1 :   Assert(d_containsVisitor != NULL);
                 [ -  - ]
     657                 :          1 :   d_true = nodeManager()->mkConst<bool>(true);
     658                 :          1 :   d_false = nodeManager()->mkConst<bool>(false);
     659                 :          1 : }
     660                 :            : 
     661                 :          2 : ITESimplifier::~ITESimplifier()
     662                 :            : {
     663                 :          1 :   clearSimpITECaches();
     664 [ -  + ][ -  + ]:          1 :   Assert(d_constantLeaves.empty());
     665 [ -  + ][ -  + ]:          1 :   Assert(d_allocatedConstantLeaves.empty());
     666                 :          2 : }
     667                 :            : 
     668                 :        156 : bool ITESimplifier::leavesAreConst(TNode e)
     669                 :            : {
     670                 :        156 :   return leavesAreConst(e, d_env.theoryOf(e));
     671                 :            : }
     672                 :            : 
     673                 :          1 : void ITESimplifier::clearSimpITECaches()
     674                 :            : {
     675                 :          1 :   verbose(2) << "clear ite caches " << endl;
     676         [ +  + ]:        756 :   for (size_t i = 0, N = d_allocatedConstantLeaves.size(); i < N; ++i)
     677                 :            :   {
     678                 :        755 :     NodeVec* curr = d_allocatedConstantLeaves[i];
     679         [ +  - ]:        755 :     delete curr;
     680                 :            :   }
     681                 :          1 :   d_citeEqConstApplications = 0;
     682                 :          1 :   d_constantLeaves.clear();
     683                 :          1 :   d_allocatedConstantLeaves.clear();
     684                 :          1 :   d_termITEHeight.clear();
     685                 :          1 :   d_constantIteEqualsConstantCache.clear();
     686                 :          1 :   d_replaceOverCache.clear();
     687                 :          1 :   d_replaceOverTermIteCache.clear();
     688                 :          1 :   d_simpITECache.clear();
     689                 :          1 :   d_simpVars.clear();
     690                 :          1 :   d_simpConstCache.clear();
     691                 :          1 :   d_leavesConstCache.clear();
     692                 :          1 :   d_simpContextCache.clear();
     693                 :          1 : }
     694                 :            : 
     695                 :          1 : bool ITESimplifier::doneALotOfWorkHeuristic() const
     696                 :            : {
     697                 :            :   static const size_t SIZE_BOUND = 1000;
     698                 :          1 :   verbose(2) << "d_citeEqConstApplications size " << d_citeEqConstApplications
     699                 :          1 :          << endl;
     700                 :          1 :   return (d_citeEqConstApplications > SIZE_BOUND);
     701                 :            : }
     702                 :            : 
     703                 :          1 : ITESimplifier::Statistics::Statistics(StatisticsRegistry& reg)
     704                 :            :     : d_maxNonConstantsFolded(
     705                 :          1 :         reg.registerInt("ite-simp::maxNonConstantsFolded")),
     706                 :          1 :       d_unexpected(reg.registerInt("ite-simp::unexpected")),
     707                 :          1 :       d_unsimplified(reg.registerInt("ite-simp::unsimplified")),
     708                 :          1 :       d_exactMatchFold(reg.registerInt("ite-simp::exactMatchFold")),
     709                 :          1 :       d_binaryPredFold(reg.registerInt("ite-simp::binaryPredFold")),
     710                 :          1 :       d_specialEqualityFolds(reg.registerInt("ite-simp::specialEqualityFolds")),
     711                 :          1 :       d_simpITEVisits(reg.registerInt("ite-simp::simpITE.visits")),
     712                 :          1 :       d_inSmaller(reg.registerHistogram<uint32_t>("ite-simp::inSmaller"))
     713                 :            : {
     714                 :          1 : }
     715                 :            : 
     716                 :       1253 : bool ITESimplifier::isConstantIte(TNode e)
     717                 :            : {
     718         [ +  + ]:       1253 :   if (e.isConst())
     719                 :            :   {
     720                 :        573 :     return true;
     721                 :            :   }
     722         [ +  - ]:        680 :   else if (ite::isTermITE(e))
     723                 :            :   {
     724                 :        680 :     NodeVec* constants = computeConstantLeaves(e);
     725                 :        680 :     return constants != NULL;
     726                 :            :   }
     727                 :            :   else
     728                 :            :   {
     729                 :          0 :     return false;
     730                 :            :   }
     731                 :            : }
     732                 :            : 
     733                 :      43308 : ITESimplifier::NodeVec* ITESimplifier::computeConstantLeaves(TNode ite)
     734                 :            : {
     735 [ -  + ][ -  + ]:      43308 :   Assert(ite::isTermITE(ite));
                 [ -  - ]
     736                 :      43308 :   ConstantLeavesMap::const_iterator it = d_constantLeaves.find(ite);
     737                 :      43308 :   ConstantLeavesMap::const_iterator end = d_constantLeaves.end();
     738         [ +  + ]:      43308 :   if (it != end)
     739                 :            :   {
     740                 :      42446 :     return (*it).second;
     741                 :            :   }
     742                 :       1724 :   TNode thenB = ite[1];
     743                 :       1724 :   TNode elseB = ite[2];
     744                 :            : 
     745                 :            :   // special case 2 constant children
     746 [ +  + ][ +  + ]:        862 :   if (thenB.isConst() && elseB.isConst())
                 [ +  + ]
     747                 :            :   {
     748                 :        152 :     NodeVec* pair = new NodeVec(2);
     749                 :        152 :     d_allocatedConstantLeaves.push_back(pair);
     750                 :            : 
     751                 :        152 :     (*pair)[0] = std::min(thenB, elseB);
     752                 :        152 :     (*pair)[1] = std::max(thenB, elseB);
     753                 :        152 :     d_constantLeaves[ite] = pair;
     754                 :        152 :     return pair;
     755                 :            :   }
     756                 :            :   // At least 1 is an ITE
     757         [ +  + ]:       1029 :   if (!(thenB.isConst() || thenB.getKind() == Kind::ITE)
     758 [ +  + ][ +  + ]:       1029 :       || !(elseB.isConst() || elseB.getKind() == Kind::ITE))
         [ +  + ][ +  + ]
     759                 :            :   {
     760                 :            :     // Cannot be a termITE tree
     761                 :        107 :     d_constantLeaves[ite] = NULL;
     762                 :        107 :     return NULL;
     763                 :            :   }
     764                 :            : 
     765                 :            :   // At least 1 is not a constant
     766         [ +  + ]:       1206 :   TNode definitelyITE = thenB.isConst() ? elseB : thenB;
     767         [ +  + ]:       1206 :   TNode maybeITE = thenB.isConst() ? thenB : elseB;
     768                 :            : 
     769                 :        603 :   NodeVec* defChildren = computeConstantLeaves(definitelyITE);
     770         [ -  + ]:        603 :   if (defChildren == NULL)
     771                 :            :   {
     772                 :          0 :     d_constantLeaves[ite] = NULL;
     773                 :          0 :     return NULL;
     774                 :            :   }
     775                 :            : 
     776                 :       1206 :   NodeVec scratch;
     777                 :        603 :   NodeVec* maybeChildren = NULL;
     778         [ +  + ]:        603 :   if (maybeITE.getKind() == Kind::ITE)
     779                 :            :   {
     780                 :        192 :     maybeChildren = computeConstantLeaves(maybeITE);
     781                 :            :   }
     782                 :            :   else
     783                 :            :   {
     784                 :        411 :     scratch.push_back(maybeITE);
     785                 :        411 :     maybeChildren = &scratch;
     786                 :            :   }
     787         [ -  + ]:        603 :   if (maybeChildren == NULL)
     788                 :            :   {
     789                 :          0 :     d_constantLeaves[ite] = NULL;
     790                 :          0 :     return NULL;
     791                 :            :   }
     792                 :            : 
     793                 :        603 :   NodeVec* both = new NodeVec(defChildren->size() + maybeChildren->size());
     794                 :        603 :   d_allocatedConstantLeaves.push_back(both);
     795                 :        603 :   NodeVec::iterator newEnd;
     796                 :            :   newEnd = std::set_union(defChildren->begin(),
     797                 :            :                           defChildren->end(),
     798                 :            :                           maybeChildren->begin(),
     799                 :            :                           maybeChildren->end(),
     800                 :        603 :                           both->begin());
     801                 :        603 :   both->resize(newEnd - both->begin());
     802                 :        603 :   d_constantLeaves[ite] = both;
     803                 :        603 :   return both;
     804                 :            : }
     805                 :            : 
     806                 :            : // This is uncached! Better for protoyping or getting limited size examples
     807                 :            : struct IteTreeSearchData
     808                 :            : {
     809                 :            :   set<Node> visited;
     810                 :            :   set<Node> constants;
     811                 :            :   set<Node> nonConstants;
     812                 :            :   int maxConstants;
     813                 :            :   int maxNonconstants;
     814                 :            :   int maxDepth;
     815                 :            :   bool failure;
     816                 :          0 :   IteTreeSearchData()
     817                 :          0 :       : maxConstants(-1), maxNonconstants(-1), maxDepth(-1), failure(false)
     818                 :            :   {
     819                 :          0 :   }
     820                 :            : };
     821                 :          0 : void iteTreeSearch(Node e, int depth, IteTreeSearchData& search)
     822                 :            : {
     823 [ -  - ][ -  - ]:          0 :   if (search.maxDepth >= 0 && depth > search.maxDepth)
     824                 :            :   {
     825                 :          0 :     search.failure = true;
     826                 :            :   }
     827         [ -  - ]:          0 :   if (search.failure)
     828                 :            :   {
     829                 :          0 :     return;
     830                 :            :   }
     831         [ -  - ]:          0 :   if (search.visited.find(e) != search.visited.end())
     832                 :            :   {
     833                 :          0 :     return;
     834                 :            :   }
     835                 :            :   else
     836                 :            :   {
     837                 :          0 :     search.visited.insert(e);
     838                 :            :   }
     839                 :            : 
     840         [ -  - ]:          0 :   if (e.isConst())
     841                 :            :   {
     842                 :          0 :     search.constants.insert(e);
     843                 :          0 :     if (search.maxConstants >= 0
     844 [ -  - ][ -  - ]:          0 :         && search.constants.size() > (unsigned)search.maxConstants)
                 [ -  - ]
     845                 :            :     {
     846                 :          0 :       search.failure = true;
     847                 :            :     }
     848                 :            :   }
     849         [ -  - ]:          0 :   else if (e.getKind() == Kind::ITE)
     850                 :            :   {
     851                 :          0 :     iteTreeSearch(e[1], depth + 1, search);
     852                 :          0 :     iteTreeSearch(e[2], depth + 1, search);
     853                 :            :   }
     854                 :            :   else
     855                 :            :   {
     856                 :          0 :     search.nonConstants.insert(e);
     857                 :          0 :     if (search.maxNonconstants >= 0
     858 [ -  - ][ -  - ]:          0 :         && search.nonConstants.size() > (unsigned)search.maxNonconstants)
                 [ -  - ]
     859                 :            :     {
     860                 :          0 :       search.failure = true;
     861                 :            :     }
     862                 :            :   }
     863                 :            : }
     864                 :            : 
     865                 :          0 : Node ITESimplifier::replaceOver(Node n, Node replaceWith, Node simpVar)
     866                 :            : {
     867         [ -  - ]:          0 :   if (n == simpVar)
     868                 :            :   {
     869                 :          0 :     return replaceWith;
     870                 :            :   }
     871         [ -  - ]:          0 :   else if (n.getNumChildren() == 0)
     872                 :            :   {
     873                 :          0 :     return n;
     874                 :            :   }
     875                 :          0 :   Assert(n.getNumChildren() > 0);
     876                 :          0 :   Assert(!n.isVar());
     877                 :            : 
     878                 :          0 :   pair<Node, Node> p = make_pair(n, replaceWith);
     879         [ -  - ]:          0 :   if (d_replaceOverCache.find(p) != d_replaceOverCache.end())
     880                 :            :   {
     881                 :          0 :     return d_replaceOverCache[p];
     882                 :            :   }
     883                 :            : 
     884                 :          0 :   NodeBuilder builder(n.getKind());
     885         [ -  - ]:          0 :   if (n.getMetaKind() == kind::metakind::PARAMETERIZED)
     886                 :            :   {
     887                 :          0 :     builder << n.getOperator();
     888                 :            :   }
     889                 :          0 :   unsigned i = 0;
     890         [ -  - ]:          0 :   for (; i < n.getNumChildren(); ++i)
     891                 :            :   {
     892                 :          0 :     Node newChild = replaceOver(n[i], replaceWith, simpVar);
     893                 :          0 :     builder << newChild;
     894                 :            :   }
     895                 :            :   // Mark the substitution and continue
     896                 :          0 :   Node result = builder;
     897                 :          0 :   d_replaceOverCache[p] = result;
     898                 :          0 :   return result;
     899                 :            : }
     900                 :            : 
     901                 :          0 : Node ITESimplifier::replaceOverTermIte(Node e, Node simpAtom, Node simpVar)
     902                 :            : {
     903         [ -  - ]:          0 :   if (e.getKind() == Kind::ITE)
     904                 :            :   {
     905                 :          0 :     pair<Node, Node> p = make_pair(e, simpAtom);
     906         [ -  - ]:          0 :     if (d_replaceOverTermIteCache.find(p) != d_replaceOverTermIteCache.end())
     907                 :            :     {
     908                 :          0 :       return d_replaceOverTermIteCache[p];
     909                 :            :     }
     910                 :          0 :     Assert(!e.getType().isBoolean());
     911                 :          0 :     Node cnd = e[0];
     912                 :          0 :     Node newThen = replaceOverTermIte(e[1], simpAtom, simpVar);
     913                 :          0 :     Node newElse = replaceOverTermIte(e[2], simpAtom, simpVar);
     914                 :          0 :     Node newIte = cnd.iteNode(newThen, newElse);
     915                 :          0 :     d_replaceOverTermIteCache[p] = newIte;
     916                 :          0 :     return newIte;
     917                 :            :   }
     918                 :            :   else
     919                 :            :   {
     920                 :          0 :     return replaceOver(simpAtom, e, simpVar);
     921                 :            :   }
     922                 :            : }
     923                 :            : 
     924                 :          0 : Node ITESimplifier::attemptLiftEquality(TNode atom)
     925                 :            : {
     926         [ -  - ]:          0 :   if (atom.getKind() == Kind::EQUAL)
     927                 :            :   {
     928                 :          0 :     TNode left = atom[0];
     929                 :          0 :     TNode right = atom[1];
     930         [ -  - ]:          0 :     if ((left.getKind() == Kind::ITE || right.getKind() == Kind::ITE)
     931                 :          0 :         && !(left.getKind() == Kind::ITE && right.getKind() == Kind::ITE))
     932                 :            :     {
     933                 :            :       // exactly 1 is an ite
     934         [ -  - ]:          0 :       TNode ite = left.getKind() == Kind::ITE ? left : right;
     935         [ -  - ]:          0 :       TNode notIte = left.getKind() == Kind::ITE ? right : left;
     936                 :            : 
     937         [ -  - ]:          0 :       if (notIte == ite[1])
     938                 :            :       {
     939                 :          0 :         ++(d_statistics.d_exactMatchFold);
     940                 :          0 :         return ite[0].iteNode(d_true, notIte.eqNode(ite[2]));
     941                 :            :       }
     942         [ -  - ]:          0 :       else if (notIte == ite[2])
     943                 :            :       {
     944                 :          0 :         ++(d_statistics.d_exactMatchFold);
     945                 :          0 :         return ite[0].iteNode(notIte.eqNode(ite[1]), d_true);
     946                 :            :       }
     947                 :          0 :       if (notIte.isConst() && (ite[1].isConst() || ite[2].isConst()))
     948                 :            :       {
     949                 :          0 :         ++(d_statistics.d_exactMatchFold);
     950                 :          0 :         return ite[0].iteNode(notIte.eqNode(ite[1]), notIte.eqNode(ite[2]));
     951                 :            :       }
     952                 :            :     }
     953                 :            :   }
     954                 :            : 
     955                 :            :   // try a similar more relaxed version for non-equality operators
     956                 :          0 :   if (atom.getMetaKind() == kind::metakind::OPERATOR
     957                 :          0 :       && atom.getNumChildren() == 2 && !atom[1].getType().isBoolean())
     958                 :            :   {
     959                 :          0 :     TNode left = atom[0];
     960                 :          0 :     TNode right = atom[1];
     961         [ -  - ]:          0 :     if ((left.getKind() == Kind::ITE || right.getKind() == Kind::ITE)
     962                 :          0 :         && !(left.getKind() == Kind::ITE && right.getKind() == Kind::ITE))
     963                 :            :     {
     964                 :            :       // exactly 1 is an ite
     965                 :          0 :       bool leftIsIte = left.getKind() == Kind::ITE;
     966         [ -  - ]:          0 :       Node ite = leftIsIte ? left : right;
     967         [ -  - ]:          0 :       Node notIte = leftIsIte ? right : left;
     968                 :            : 
     969         [ -  - ]:          0 :       if (notIte.isConst())
     970                 :            :       {
     971                 :          0 :         IteTreeSearchData search;
     972                 :          0 :         search.maxNonconstants = 2;
     973                 :          0 :         iteTreeSearch(ite, 0, search);
     974         [ -  - ]:          0 :         if (!search.failure)
     975                 :            :         {
     976                 :          0 :           d_statistics.d_maxNonConstantsFolded.maxAssign(
     977                 :          0 :               search.nonConstants.size());
     978         [ -  - ]:          0 :           Trace("ite::simpite") << "used " << search.nonConstants.size()
     979                 :          0 :                                 << " nonconstants" << endl;
     980                 :          0 :           NodeManager* nm = nodeManager();
     981                 :          0 :           Node simpVar = getSimpVar(notIte.getType());
     982         [ -  - ]:          0 :           TNode newLeft = leftIsIte ? simpVar : notIte;
     983         [ -  - ]:          0 :           TNode newRight = leftIsIte ? notIte : simpVar;
     984                 :          0 :           Node newAtom = nm->mkNode(atom.getKind(), newLeft, newRight);
     985                 :            : 
     986                 :          0 :           ++(d_statistics.d_binaryPredFold);
     987                 :          0 :           return replaceOverTermIte(ite, newAtom, simpVar);
     988                 :            :         }
     989                 :            :       }
     990                 :            :     }
     991                 :            :   }
     992                 :            : 
     993                 :            :   // TODO "This is way too tailored. Must generalize!"
     994         [ -  - ]:          0 :   if (atom.getKind() == Kind::EQUAL && atom.getNumChildren() == 2
     995                 :          0 :       && ite::isTermITE(atom[0]) && atom[1].getKind() == Kind::MULT
     996                 :          0 :       && atom[1].getNumChildren() == 2 && atom[1][0].isConst()
     997                 :          0 :       && atom[1][0].getConst<Rational>().isNegativeOne()
     998                 :          0 :       && ite::isTermITE(atom[1][1])
     999                 :          0 :       && d_termITEHeight.termITEHeight(atom[0]) == 1
    1000                 :          0 :       && d_termITEHeight.termITEHeight(atom[1][1]) == 1
    1001                 :          0 :       && (atom[0][1].isConst() || atom[0][2].isConst())
    1002                 :          0 :       && (atom[1][1][1].isConst() || atom[1][1][2].isConst()))
    1003                 :            :   {
    1004                 :            :     // expand all 4 cases
    1005                 :            : 
    1006                 :          0 :     Node negOne = atom[1][0];
    1007                 :            : 
    1008                 :          0 :     Node lite = atom[0];
    1009                 :          0 :     Node lC = lite[0];
    1010                 :          0 :     Node lT = lite[1];
    1011                 :          0 :     Node lE = lite[2];
    1012                 :            : 
    1013                 :          0 :     NodeManager* nm = nodeManager();
    1014                 :          0 :     Node negRite = atom[1][1];
    1015                 :          0 :     Node rC = negRite[0];
    1016                 :          0 :     Node rT = nm->mkNode(Kind::MULT, negOne, negRite[1]);
    1017                 :          0 :     Node rE = nm->mkNode(Kind::MULT, negOne, negRite[2]);
    1018                 :            : 
    1019                 :            :     // (ite lC lT lE) = (ite rC rT rE)
    1020                 :            :     // (ite lc (= lT (ite rC rT rE) (= lE (ite rC rT rE))))
    1021                 :            :     // (ite lc (ite rC (= lT rT) (= lT rE))
    1022                 :            :     //         (ite rC (= lE rT) (= lE rE)))
    1023                 :            : 
    1024                 :          0 :     Node eqTT = lT.eqNode(rT);
    1025                 :          0 :     Node eqTE = lT.eqNode(rE);
    1026                 :          0 :     Node eqET = lE.eqNode(rT);
    1027                 :          0 :     Node eqEE = lE.eqNode(rE);
    1028                 :          0 :     Node thenLC = rC.iteNode(eqTT, eqTE);
    1029                 :          0 :     Node elseLC = rC.iteNode(eqET, eqEE);
    1030                 :          0 :     Node newIte = lC.iteNode(thenLC, elseLC);
    1031                 :            : 
    1032                 :          0 :     ++(d_statistics.d_specialEqualityFolds);
    1033                 :          0 :     return newIte;
    1034                 :            :   }
    1035                 :          0 :   return Node::null();
    1036                 :            : }
    1037                 :            : 
    1038                 :            : // Interesting classes of atoms:
    1039                 :            : // 2. Contains constants and 1 constant term ite
    1040                 :            : // 3. Contains 2 constant term ites
    1041                 :        729 : Node ITESimplifier::transformAtom(TNode atom)
    1042                 :            : {
    1043         [ -  + ]:        729 :   if (!d_containsVisitor->containsTermITE(atom))
    1044                 :            :   {
    1045                 :          0 :     if (atom.getKind() == Kind::EQUAL && atom[0].isConst() && atom[1].isConst())
    1046                 :            :     {
    1047                 :            :       // constant equality
    1048                 :          0 :       return nodeManager()->mkConst<bool>(atom[0] == atom[1]);
    1049                 :            :     }
    1050                 :          0 :     return Node::null();
    1051                 :            :   }
    1052                 :            :   else
    1053                 :            :   {
    1054                 :       1458 :     Node acr = attemptConstantRemoval(atom);
    1055         [ +  + ]:        729 :     if (!acr.isNull())
    1056                 :            :     {
    1057                 :        573 :       return acr;
    1058                 :            :     }
    1059                 :            :     // Node ale = attemptLiftEquality(atom);
    1060                 :            :     // if(!ale.isNull()){
    1061                 :            :     //   //return ale;
    1062                 :            :     // }
    1063                 :        156 :     return Node::null();
    1064                 :            :   }
    1065                 :            : }
    1066                 :            : 
    1067                 :            : static unsigned numBranches = 0;
    1068                 :            : static unsigned numFalseBranches = 0;
    1069                 :            : static unsigned itesMade = 0;
    1070                 :            : 
    1071                 :      67339 : Node ITESimplifier::constantIteEqualsConstant(TNode cite, TNode constant)
    1072                 :            : {
    1073                 :            :   static int instance = 0;
    1074                 :      67339 :   ++instance;
    1075         [ +  - ]:     134678 :   Trace("ite::constantIteEqualsConstant")
    1076                 :          0 :       << instance << "constantIteEqualsConstant(" << cite << ", " << constant
    1077                 :      67339 :       << ")" << endl;
    1078         [ +  + ]:      67339 :   if (cite.isConst())
    1079                 :            :   {
    1080         [ +  + ]:      45678 :     Node res = (cite == constant) ? d_true : d_false;
    1081         [ +  - ]:      22839 :     Trace("ite::constantIteEqualsConstant") << instance << "->" << res << endl;
    1082                 :      22839 :     return res;
    1083                 :            :   }
    1084                 :      89000 :   std::pair<Node, Node> pair = make_pair(cite, constant);
    1085                 :            : 
    1086                 :            :   NodePairMap::const_iterator eq_pos =
    1087                 :      44500 :       d_constantIteEqualsConstantCache.find(pair);
    1088         [ +  + ]:      44500 :   if (eq_pos != d_constantIteEqualsConstantCache.end())
    1089                 :            :   {
    1090         [ +  - ]:       5334 :     Trace("ite::constantIteEqualsConstant")
    1091                 :       2667 :         << instance << "->" << (*eq_pos).second << endl;
    1092                 :       2667 :     return (*eq_pos).second;
    1093                 :            :   }
    1094                 :            : 
    1095                 :      41833 :   ++d_citeEqConstApplications;
    1096                 :            : 
    1097                 :      41833 :   NodeVec* leaves = computeConstantLeaves(cite);
    1098 [ -  + ][ -  + ]:      41833 :   Assert(leaves != NULL);
                 [ -  - ]
    1099         [ +  + ]:      41833 :   if (std::binary_search(leaves->begin(), leaves->end(), constant))
    1100                 :            :   {
    1101         [ -  + ]:      33383 :     if (leaves->size() == 1)
    1102                 :            :     {
    1103                 :            :       // probably unreachable
    1104                 :          0 :       d_constantIteEqualsConstantCache[pair] = d_true;
    1105         [ -  - ]:          0 :       Trace("ite::constantIteEqualsConstant")
    1106                 :          0 :           << instance << "->" << d_true << endl;
    1107                 :          0 :       return d_true;
    1108                 :            :     }
    1109                 :            :     else
    1110                 :            :     {
    1111 [ -  + ][ -  + ]:      33383 :       Assert(cite.getKind() == Kind::ITE);
                 [ -  - ]
    1112                 :      66766 :       TNode cnd = cite[0];
    1113                 :      66766 :       TNode tB = cite[1];
    1114                 :      66766 :       TNode fB = cite[2];
    1115                 :     100149 :       Node tEqs = constantIteEqualsConstant(tB, constant);
    1116                 :     100149 :       Node fEqs = constantIteEqualsConstant(fB, constant);
    1117                 :      66766 :       Node boolIte = cnd.iteNode(tEqs, fEqs);
    1118 [ +  + ][ +  + ]:      33383 :       if (!(tEqs.isConst() || fEqs.isConst()))
                 [ +  + ]
    1119                 :            :       {
    1120                 :       1924 :         ++numBranches;
    1121                 :            :       }
    1122 [ +  + ][ +  + ]:      33383 :       if (!(tEqs == d_false || fEqs == d_false))
                 [ +  + ]
    1123                 :            :       {
    1124                 :       2211 :         ++numFalseBranches;
    1125                 :            :       }
    1126                 :      33383 :       ++itesMade;
    1127                 :      33383 :       d_constantIteEqualsConstantCache[pair] = boolIte;
    1128                 :            :       // Trace("ite::constantIteEqualsConstant") << instance << "->" << boolIte
    1129                 :            :       // << endl;
    1130                 :      33383 :       return boolIte;
    1131                 :            :     }
    1132                 :            :   }
    1133                 :            :   else
    1134                 :            :   {
    1135                 :       8450 :     d_constantIteEqualsConstantCache[pair] = d_false;
    1136         [ +  - ]:      16900 :     Trace("ite::constantIteEqualsConstant")
    1137                 :       8450 :         << instance << "->" << d_false << endl;
    1138                 :       8450 :     return d_false;
    1139                 :            :   }
    1140                 :            : }
    1141                 :            : 
    1142                 :        573 : Node ITESimplifier::intersectConstantIte(TNode lcite, TNode rcite)
    1143                 :            : {
    1144                 :            :   // intersect the constant ite trees lcite and rcite
    1145                 :            : 
    1146 [ +  - ][ +  - ]:        573 :   if (lcite.isConst() || rcite.isConst())
                 [ +  - ]
    1147                 :            :   {
    1148                 :        573 :     bool lIsConst = lcite.isConst();
    1149         [ -  + ]:       1146 :     TNode constant = lIsConst ? lcite : rcite;
    1150         [ -  + ]:       1146 :     TNode cite = lIsConst ? rcite : lcite;
    1151                 :            : 
    1152                 :        573 :     (d_statistics.d_inSmaller) << 1;
    1153                 :        573 :     unsigned preItesMade = itesMade;
    1154                 :        573 :     unsigned preNumBranches = numBranches;
    1155                 :        573 :     unsigned preNumFalseBranches = numFalseBranches;
    1156                 :       1719 :     Node bterm = constantIteEqualsConstant(cite, constant);
    1157         [ +  - ]:       1146 :     Trace("intersectConstantIte") << (numBranches - preNumBranches) << " "
    1158                 :          0 :                                   << (numFalseBranches - preNumFalseBranches)
    1159                 :        573 :                                   << " " << (itesMade - preItesMade) << endl;
    1160                 :        573 :     return bterm;
    1161                 :            :   }
    1162                 :          0 :   Assert(lcite.getKind() == Kind::ITE);
    1163                 :          0 :   Assert(rcite.getKind() == Kind::ITE);
    1164                 :            : 
    1165                 :          0 :   NodeVec* leftValues = computeConstantLeaves(lcite);
    1166                 :          0 :   NodeVec* rightValues = computeConstantLeaves(rcite);
    1167                 :            : 
    1168                 :          0 :   uint32_t smaller = std::min(leftValues->size(), rightValues->size());
    1169                 :            : 
    1170                 :          0 :   (d_statistics.d_inSmaller) << smaller;
    1171                 :          0 :   NodeVec intersection(smaller, Node::null());
    1172                 :          0 :   NodeVec::iterator newEnd;
    1173                 :            :   newEnd = std::set_intersection(leftValues->begin(),
    1174                 :            :                                  leftValues->end(),
    1175                 :            :                                  rightValues->begin(),
    1176                 :            :                                  rightValues->end(),
    1177                 :          0 :                                  intersection.begin());
    1178                 :          0 :   intersection.resize(newEnd - intersection.begin());
    1179         [ -  - ]:          0 :   if (intersection.empty())
    1180                 :            :   {
    1181                 :          0 :     return d_false;
    1182                 :            :   }
    1183                 :            :   else
    1184                 :            :   {
    1185                 :          0 :     NodeBuilder nb(Kind::OR);
    1186                 :          0 :     NodeVec::const_iterator it = intersection.begin(), end = intersection.end();
    1187         [ -  - ]:          0 :     for (; it != end; ++it)
    1188                 :            :     {
    1189                 :          0 :       Node inBoth = *it;
    1190                 :          0 :       Node lefteq = constantIteEqualsConstant(lcite, inBoth);
    1191                 :          0 :       Node righteq = constantIteEqualsConstant(rcite, inBoth);
    1192                 :          0 :       Node bothHold = lefteq.andNode(righteq);
    1193                 :          0 :       nb << bothHold;
    1194                 :            :     }
    1195         [ -  - ]:          0 :     Node result = (nb.getNumChildren() > 1) ? (Node)nb : nb[0];
    1196                 :          0 :     return result;
    1197                 :            :   }
    1198                 :            : }
    1199                 :            : 
    1200                 :          0 : Node ITESimplifier::attemptEagerRemoval(TNode atom)
    1201                 :            : {
    1202         [ -  - ]:          0 :   if (atom.getKind() == Kind::EQUAL)
    1203                 :            :   {
    1204                 :          0 :     TNode left = atom[0];
    1205                 :          0 :     TNode right = atom[1];
    1206                 :          0 :     if ((left.isConst() && right.getKind() == Kind::ITE && isConstantIte(right))
    1207                 :          0 :         || (right.isConst() && left.getKind() == Kind::ITE
    1208                 :          0 :             && isConstantIte(left)))
    1209                 :            :     {
    1210         [ -  - ]:          0 :       TNode constant = left.isConst() ? left : right;
    1211         [ -  - ]:          0 :       TNode cite = left.isConst() ? right : left;
    1212                 :            : 
    1213                 :          0 :       std::pair<Node, Node> pair = make_pair(cite, constant);
    1214                 :            :       NodePairMap::const_iterator eq_pos =
    1215                 :          0 :           d_constantIteEqualsConstantCache.find(pair);
    1216         [ -  - ]:          0 :       if (eq_pos != d_constantIteEqualsConstantCache.end())
    1217                 :            :       {
    1218                 :          0 :         Node ret = (*eq_pos).second;
    1219         [ -  - ]:          0 :         if (ret.isConst())
    1220                 :            :         {
    1221                 :          0 :           return ret;
    1222                 :            :         }
    1223                 :            :         else
    1224                 :            :         {
    1225                 :          0 :           return Node::null();
    1226                 :            :         }
    1227                 :            :       }
    1228                 :            : 
    1229                 :          0 :       NodeVec* leaves = computeConstantLeaves(cite);
    1230                 :          0 :       Assert(leaves != NULL);
    1231         [ -  - ]:          0 :       if (!std::binary_search(leaves->begin(), leaves->end(), constant))
    1232                 :            :       {
    1233                 :          0 :         d_constantIteEqualsConstantCache[pair] = d_false;
    1234                 :          0 :         return d_false;
    1235                 :            :       }
    1236                 :            :     }
    1237                 :            :   }
    1238                 :          0 :   return Node::null();
    1239                 :            : }
    1240                 :            : 
    1241                 :        729 : Node ITESimplifier::attemptConstantRemoval(TNode atom)
    1242                 :            : {
    1243         [ +  + ]:        729 :   if (atom.getKind() == Kind::EQUAL)
    1244                 :            :   {
    1245                 :        680 :     TNode left = atom[0];
    1246                 :        680 :     TNode right = atom[1];
    1247                 :        680 :     if (isConstantIte(left) && isConstantIte(right))
    1248                 :            :     {
    1249                 :        573 :       return intersectConstantIte(left, right);
    1250                 :            :     }
    1251                 :            :   }
    1252                 :        156 :   return Node::null();
    1253                 :            : }
    1254                 :            : 
    1255                 :        550 : bool ITESimplifier::leavesAreConst(TNode e, theory::TheoryId tid)
    1256                 :            : {
    1257                 :        731 :   Assert((e.getKind() == Kind::ITE && !e.getType().isBoolean())
    1258                 :            :          || d_env.theoryOf(e) != theory::THEORY_BOOL);
    1259         [ +  + ]:        550 :   if (e.isConst())
    1260                 :            :   {
    1261                 :         27 :     return true;
    1262                 :            :   }
    1263                 :            : 
    1264                 :        523 :   unordered_map<Node, bool>::iterator it;
    1265                 :        523 :   it = d_leavesConstCache.find(e);
    1266         [ +  + ]:        523 :   if (it != d_leavesConstCache.end())
    1267                 :            :   {
    1268                 :        122 :     return (*it).second;
    1269                 :            :   }
    1270                 :            : 
    1271                 :        401 :   if (!containsTermITE(e) && theory::Theory::isLeafOf(e, tid))
    1272                 :            :   {
    1273                 :         34 :     d_leavesConstCache[e] = false;
    1274                 :         34 :     return false;
    1275                 :            :   }
    1276                 :            : 
    1277 [ -  + ][ -  + ]:        367 :   Assert(e.getNumChildren() > 0);
                 [ -  - ]
    1278                 :        367 :   size_t k = 0, sz = e.getNumChildren();
    1279                 :            : 
    1280         [ +  + ]:        367 :   if (e.getKind() == Kind::ITE)
    1281                 :            :   {
    1282                 :        161 :     k = 1;
    1283                 :            :   }
    1284                 :            : 
    1285         [ +  - ]:        394 :   for (; k < sz; ++k)
    1286                 :            :   {
    1287         [ +  + ]:        394 :     if (!leavesAreConst(e[k], tid))
    1288                 :            :     {
    1289                 :        367 :       d_leavesConstCache[e] = false;
    1290                 :        367 :       return false;
    1291                 :            :     }
    1292                 :            :   }
    1293                 :          0 :   d_leavesConstCache[e] = true;
    1294                 :          0 :   return true;
    1295                 :            : }
    1296                 :            : 
    1297                 :          0 : Node ITESimplifier::simpConstants(TNode simpContext,
    1298                 :            :                                   TNode iteNode,
    1299                 :            :                                   TNode simpVar)
    1300                 :            : {
    1301                 :          0 :   NodePairMap::iterator it;
    1302                 :          0 :   it = d_simpConstCache.find(pair<Node, Node>(simpContext, iteNode));
    1303         [ -  - ]:          0 :   if (it != d_simpConstCache.end())
    1304                 :            :   {
    1305                 :          0 :     return (*it).second;
    1306                 :            :   }
    1307                 :            : 
    1308         [ -  - ]:          0 :   if (iteNode.getKind() == Kind::ITE)
    1309                 :            :   {
    1310                 :          0 :     NodeBuilder builder(Kind::ITE);
    1311                 :          0 :     builder << iteNode[0];
    1312                 :          0 :     unsigned i = 1;
    1313         [ -  - ]:          0 :     for (; i < iteNode.getNumChildren(); ++i)
    1314                 :            :     {
    1315                 :          0 :       Node n = simpConstants(simpContext, iteNode[i], simpVar);
    1316         [ -  - ]:          0 :       if (n.isNull())
    1317                 :            :       {
    1318                 :          0 :         return n;
    1319                 :            :       }
    1320                 :          0 :       builder << n;
    1321                 :            :     }
    1322                 :            :     // Mark the substitution and continue
    1323                 :          0 :     Node result = builder;
    1324                 :          0 :     result = rewrite(result);
    1325                 :          0 :     d_simpConstCache[pair<Node, Node>(simpContext, iteNode)] = result;
    1326                 :          0 :     return result;
    1327                 :            :   }
    1328                 :            : 
    1329         [ -  - ]:          0 :   if (!containsTermITE(iteNode))
    1330                 :            :   {
    1331                 :          0 :     Node n = rewrite(simpContext.substitute(simpVar, iteNode));
    1332                 :          0 :     d_simpConstCache[pair<Node, Node>(simpContext, iteNode)] = n;
    1333                 :          0 :     return n;
    1334                 :            :   }
    1335                 :            : 
    1336                 :          0 :   Node iteNode2;
    1337                 :          0 :   Node simpVar2;
    1338                 :          0 :   d_simpContextCache.clear();
    1339                 :          0 :   Node simpContext2 = createSimpContext(iteNode, iteNode2, simpVar2);
    1340         [ -  - ]:          0 :   if (!simpContext2.isNull())
    1341                 :            :   {
    1342                 :          0 :     Assert(!iteNode2.isNull());
    1343                 :          0 :     simpContext2 = simpContext.substitute(simpVar, simpContext2);
    1344                 :          0 :     Node n = simpConstants(simpContext2, iteNode2, simpVar2);
    1345         [ -  - ]:          0 :     if (n.isNull())
    1346                 :            :     {
    1347                 :          0 :       return n;
    1348                 :            :     }
    1349                 :          0 :     d_simpConstCache[pair<Node, Node>(simpContext, iteNode)] = n;
    1350                 :          0 :     return n;
    1351                 :            :   }
    1352                 :          0 :   return Node();
    1353                 :            : }
    1354                 :            : 
    1355                 :          0 : Node ITESimplifier::getSimpVar(TypeNode t)
    1356                 :            : {
    1357                 :          0 :   std::unordered_map<TypeNode, Node>::iterator it;
    1358                 :          0 :   it = d_simpVars.find(t);
    1359         [ -  - ]:          0 :   if (it != d_simpVars.end())
    1360                 :            :   {
    1361                 :          0 :     return (*it).second;
    1362                 :            :   }
    1363                 :          0 :   SkolemManager* sm = nodeManager()->getSkolemManager();
    1364                 :            :   Node var = sm->mkDummySkolem(
    1365                 :          0 :       "iteSimp", t, "is a variable resulting from ITE simplification");
    1366                 :          0 :   d_simpVars[t] = var;
    1367                 :          0 :   return var;
    1368                 :            : }
    1369                 :            : 
    1370                 :          0 : Node ITESimplifier::createSimpContext(TNode c, Node& iteNode, Node& simpVar)
    1371                 :            : {
    1372                 :          0 :   NodeMap::iterator it;
    1373                 :          0 :   it = d_simpContextCache.find(c);
    1374         [ -  - ]:          0 :   if (it != d_simpContextCache.end())
    1375                 :            :   {
    1376                 :          0 :     return (*it).second;
    1377                 :            :   }
    1378                 :            : 
    1379         [ -  - ]:          0 :   if (!containsTermITE(c))
    1380                 :            :   {
    1381                 :          0 :     d_simpContextCache[c] = c;
    1382                 :          0 :     return c;
    1383                 :            :   }
    1384                 :            : 
    1385                 :          0 :   if (c.getKind() == Kind::ITE && !c.getType().isBoolean())
    1386                 :            :   {
    1387                 :            :     // Currently only support one ite node in a simp context
    1388                 :            :     // Return Null if more than one is found
    1389         [ -  - ]:          0 :     if (!iteNode.isNull())
    1390                 :            :     {
    1391                 :          0 :       return Node();
    1392                 :            :     }
    1393                 :          0 :     simpVar = getSimpVar(c.getType());
    1394         [ -  - ]:          0 :     if (simpVar.isNull())
    1395                 :            :     {
    1396                 :          0 :       return Node();
    1397                 :            :     }
    1398                 :          0 :     d_simpContextCache[c] = simpVar;
    1399                 :          0 :     iteNode = c;
    1400                 :          0 :     return simpVar;
    1401                 :            :   }
    1402                 :            : 
    1403                 :          0 :   NodeBuilder builder(c.getKind());
    1404         [ -  - ]:          0 :   if (c.getMetaKind() == kind::metakind::PARAMETERIZED)
    1405                 :            :   {
    1406                 :          0 :     builder << c.getOperator();
    1407                 :            :   }
    1408                 :          0 :   unsigned i = 0;
    1409         [ -  - ]:          0 :   for (; i < c.getNumChildren(); ++i)
    1410                 :            :   {
    1411                 :          0 :     Node newChild = createSimpContext(c[i], iteNode, simpVar);
    1412         [ -  - ]:          0 :     if (newChild.isNull())
    1413                 :            :     {
    1414                 :          0 :       return newChild;
    1415                 :            :     }
    1416                 :          0 :     builder << newChild;
    1417                 :            :   }
    1418                 :            :   // Mark the substitution and continue
    1419                 :          0 :   Node result = builder;
    1420                 :          0 :   d_simpContextCache[c] = result;
    1421                 :          0 :   return result;
    1422                 :            : }
    1423                 :            : typedef std::unordered_set<Node> NodeSet;
    1424                 :          0 : void countReachable_(Node x, Kind k, NodeSet& visited, uint32_t& reached)
    1425                 :            : {
    1426         [ -  - ]:          0 :   if (visited.find(x) != visited.end())
    1427                 :            :   {
    1428                 :          0 :     return;
    1429                 :            :   }
    1430                 :          0 :   visited.insert(x);
    1431         [ -  - ]:          0 :   if (x.getKind() == k)
    1432                 :            :   {
    1433                 :          0 :     ++reached;
    1434                 :            :   }
    1435         [ -  - ]:          0 :   for (unsigned i = 0, N = x.getNumChildren(); i < N; ++i)
    1436                 :            :   {
    1437                 :          0 :     countReachable_(x[i], k, visited, reached);
    1438                 :            :   }
    1439                 :            : }
    1440                 :            : 
    1441                 :          0 : uint32_t countReachable(TNode x, Kind k)
    1442                 :            : {
    1443                 :          0 :   NodeSet visited;
    1444                 :          0 :   uint32_t reached = 0;
    1445                 :          0 :   countReachable_(x, k, visited, reached);
    1446                 :          0 :   return reached;
    1447                 :            : }
    1448                 :            : 
    1449                 :        729 : Node ITESimplifier::simpITEAtom(TNode atom)
    1450                 :            : {
    1451                 :            :   CVC5_UNUSED static int instance = 0;
    1452         [ +  - ]:        729 :   Trace("ite::atom") << "still simplifying " << (++instance) << endl;
    1453                 :       1458 :   Node attempt = transformAtom(atom);
    1454         [ +  - ]:        729 :   Trace("ite::atom") << "  finished " << instance << endl;
    1455         [ +  + ]:        729 :   if (!attempt.isNull())
    1456                 :            :   {
    1457                 :       1146 :     Node rewritten = rewrite(attempt);
    1458         [ +  - ]:       1146 :     Trace("ite::print-success")
    1459                 :          0 :         << instance << " "
    1460         [ -  - ]:        573 :         << "rewriting " << countReachable(rewritten, Kind::ITE) << " from "
    1461 [ -  + ][ -  + ]:        573 :         << countReachable(atom, Kind::ITE) << endl
                 [ -  - ]
    1462                 :          0 :         << "\t rewritten " << rewritten << endl
    1463                 :        573 :         << "\t input " << atom << endl;
    1464                 :        573 :     return rewritten;
    1465                 :            :   }
    1466                 :            : 
    1467         [ -  + ]:        156 :   if (leavesAreConst(atom))
    1468                 :            :   {
    1469                 :          0 :     Node iteNode;
    1470                 :          0 :     Node simpVar;
    1471                 :          0 :     d_simpContextCache.clear();
    1472                 :          0 :     Node simpContext = createSimpContext(atom, iteNode, simpVar);
    1473         [ -  - ]:          0 :     if (!simpContext.isNull())
    1474                 :            :     {
    1475         [ -  - ]:          0 :       if (iteNode.isNull())
    1476                 :            :       {
    1477                 :          0 :         Assert(leavesAreConst(simpContext) && !containsTermITE(simpContext));
    1478                 :          0 :         ++(d_statistics.d_unexpected);
    1479         [ -  - ]:          0 :         Trace("ite::simpite") << instance << " "
    1480                 :          0 :                               << "how about?" << atom << endl;
    1481         [ -  - ]:          0 :         Trace("ite::simpite") << instance << " "
    1482                 :          0 :                               << "\t" << simpContext << endl;
    1483                 :          0 :         return rewrite(simpContext);
    1484                 :            :       }
    1485                 :          0 :       Node n = simpConstants(simpContext, iteNode, simpVar);
    1486         [ -  - ]:          0 :       if (!n.isNull())
    1487                 :            :       {
    1488                 :          0 :         ++(d_statistics.d_unexpected);
    1489         [ -  - ]:          0 :         Trace("ite::simpite") << instance << " "
    1490                 :          0 :                               << "here?" << atom << endl;
    1491         [ -  - ]:          0 :         Trace("ite::simpite") << instance << " "
    1492                 :          0 :                               << "\t" << n << endl;
    1493                 :          0 :         return n;
    1494                 :            :       }
    1495                 :            :     }
    1496                 :            :   }
    1497         [ -  + ]:        156 :   if (TraceIsOn("ite::simpite"))
    1498                 :            :   {
    1499         [ -  - ]:          0 :     if (countReachable(atom, Kind::ITE) > 0)
    1500                 :            :     {
    1501         [ -  - ]:          0 :       Trace("ite::simpite") << instance << " "
    1502                 :          0 :                             << "remaining " << atom << endl;
    1503                 :            :     }
    1504                 :            :   }
    1505                 :        156 :   ++(d_statistics.d_unsimplified);
    1506                 :        156 :   return atom;
    1507                 :            : }
    1508                 :            : 
    1509                 :            : struct preprocess_stack_element
    1510                 :            : {
    1511                 :            :   TNode d_node;
    1512                 :            :   bool d_children_added;
    1513                 :       2454 :   preprocess_stack_element(TNode node) : d_node(node), d_children_added(false)
    1514                 :            :   {
    1515                 :       2454 :   }
    1516                 :            : }; /* struct preprocess_stack_element */
    1517                 :            : 
    1518                 :          1 : Node ITESimplifier::simpITE(TNode assertion)
    1519                 :            : {
    1520                 :            :   // Do a topological sort of the subexpressions and substitute them
    1521                 :          1 :   vector<preprocess_stack_element> toVisit;
    1522                 :          1 :   toVisit.push_back(assertion);
    1523                 :            : 
    1524         [ +  + ]:       4373 :   while (!toVisit.empty())
    1525                 :            :   {
    1526                 :            :     // cout << "call  " << call << " : " << iteration << endl;
    1527                 :            :     // The current node we are processing
    1528                 :       4372 :     preprocess_stack_element& stackHead = toVisit.back();
    1529                 :       4372 :     TNode current = stackHead.d_node;
    1530                 :            : 
    1531                 :            :     // If node has no ITE's or already in the cache we're done, pop from the
    1532                 :            :     // stack
    1533                 :      13641 :     if (current.getNumChildren() == 0
    1534 [ +  + ][ +  + ]:      10386 :         || (d_env.theoryOf(current) != theory::THEORY_BOOL
         [ +  + ][ -  - ]
    1535 [ +  + ][ +  + ]:       6014 :             && !containsTermITE(current)))
         [ +  + ][ -  - ]
    1536                 :            :     {
    1537                 :        525 :       d_simpITECache[current] = current;
    1538                 :        525 :       ++(d_statistics.d_simpITEVisits);
    1539                 :        525 :       toVisit.pop_back();
    1540                 :        525 :       continue;
    1541                 :            :     }
    1542                 :            : 
    1543                 :       3847 :     NodeMap::iterator find = d_simpITECache.find(current);
    1544         [ +  + ]:       3847 :     if (find != d_simpITECache.end())
    1545                 :            :     {
    1546                 :         11 :       toVisit.pop_back();
    1547                 :         11 :       continue;
    1548                 :            :     }
    1549                 :            : 
    1550                 :            :     // Not yet substituted, so process
    1551         [ +  + ]:       3836 :     if (stackHead.d_children_added)
    1552                 :            :     {
    1553                 :            :       // Children have been processed, so substitute
    1554                 :       3836 :       NodeBuilder builder(current.getKind());
    1555         [ -  + ]:       1918 :       if (current.getMetaKind() == kind::metakind::PARAMETERIZED)
    1556                 :            :       {
    1557                 :          0 :         builder << current.getOperator();
    1558                 :            :       }
    1559         [ +  + ]:       6869 :       for (unsigned i = 0; i < current.getNumChildren(); ++i)
    1560                 :            :       {
    1561 [ -  + ][ -  + ]:       4951 :         Assert(d_simpITECache.find(current[i]) != d_simpITECache.end());
                 [ -  - ]
    1562                 :       9902 :         Node child = current[i];
    1563                 :       9902 :         Node childRes = d_simpITECache[current[i]];
    1564                 :       4951 :         builder << childRes;
    1565                 :            :       }
    1566                 :            :       // Mark the substitution and continue
    1567                 :       3836 :       Node result = builder;
    1568                 :            : 
    1569                 :            :       // If this is an atom, we process it
    1570 [ +  + ][ -  - ]:       1918 :       if (d_env.theoryOf(result) != theory::THEORY_BOOL
    1571 [ +  + ][ +  + ]:       1918 :           && result.getType().isBoolean())
         [ +  + ][ +  - ]
                 [ -  - ]
    1572                 :            :       {
    1573                 :        729 :         result = simpITEAtom(result);
    1574                 :            :       }
    1575                 :            : 
    1576                 :            :       // if(current != result && result.isConst()){
    1577                 :            :       //   static int instance = 0;
    1578                 :            :       //   //cout << instance << " " << result << current << endl;
    1579                 :            :       // }
    1580                 :            : 
    1581                 :       1918 :       result = rewrite(result);
    1582                 :       1918 :       d_simpITECache[current] = result;
    1583                 :       1918 :       ++(d_statistics.d_simpITEVisits);
    1584                 :       1918 :       toVisit.pop_back();
    1585                 :            :     }
    1586                 :            :     else
    1587                 :            :     {
    1588                 :            :       // Mark that we have added the children if any
    1589         [ +  - ]:       1918 :       if (current.getNumChildren() > 0)
    1590                 :            :       {
    1591                 :       1918 :         stackHead.d_children_added = true;
    1592                 :            :         // We need to add the children
    1593                 :       6869 :         for (TNode::iterator child_it = current.begin();
    1594         [ +  + ]:       6869 :              child_it != current.end();
    1595                 :       4951 :              ++child_it)
    1596                 :            :         {
    1597                 :       9902 :           TNode childNode = *child_it;
    1598                 :       4951 :           NodeMap::iterator childFind = d_simpITECache.find(childNode);
    1599         [ +  + ]:       4951 :           if (childFind == d_simpITECache.end())
    1600                 :            :           {
    1601                 :       2453 :             toVisit.push_back(childNode);
    1602                 :            :           }
    1603                 :            :         }
    1604                 :            :       }
    1605                 :            :       else
    1606                 :            :       {
    1607                 :            :         // No children, so we're done
    1608                 :          0 :         d_simpITECache[current] = current;
    1609                 :          0 :         ++(d_statistics.d_simpITEVisits);
    1610                 :          0 :         toVisit.pop_back();
    1611                 :            :       }
    1612                 :            :     }
    1613                 :            :   }
    1614                 :          2 :   return d_simpITECache[assertion];
    1615                 :            : }
    1616                 :            : 
    1617                 :          0 : ITECareSimplifier::ITECareSimplifier(NodeManager* nm) : d_careSetsOutstanding(0), d_usedSets()
    1618                 :            : {
    1619                 :          0 :   d_true = nm->mkConst<bool>(true);
    1620                 :          0 :   d_false = nm->mkConst<bool>(false);
    1621                 :          0 : }
    1622                 :            : 
    1623                 :          0 : ITECareSimplifier::~ITECareSimplifier()
    1624                 :            : {
    1625 [ -  - ][ -  - ]:          0 :   Assert(d_usedSets.empty());
    1626 [ -  - ][ -  - ]:          0 :   Assert(d_careSetsOutstanding == 0);
    1627                 :          0 : }
    1628                 :            : 
    1629                 :          0 : void ITECareSimplifier::clear()
    1630                 :            : {
    1631                 :          0 :   Assert(d_usedSets.empty());
    1632                 :          0 :   Assert(d_careSetsOutstanding == 0);
    1633                 :          0 : }
    1634                 :            : 
    1635                 :          0 : ITECareSimplifier::CareSetPtr ITECareSimplifier::getNewSet()
    1636                 :            : {
    1637         [ -  - ]:          0 :   if (d_usedSets.empty())
    1638                 :            :   {
    1639                 :          0 :     d_careSetsOutstanding++;
    1640                 :          0 :     return ITECareSimplifier::CareSetPtr::mkNew(*this);
    1641                 :            :   }
    1642                 :            :   else
    1643                 :            :   {
    1644                 :            :     ITECareSimplifier::CareSetPtr cs =
    1645                 :          0 :         ITECareSimplifier::CareSetPtr::recycle(d_usedSets.back());
    1646                 :          0 :     cs.getCareSet().clear();
    1647                 :          0 :     d_usedSets.pop_back();
    1648                 :          0 :     return cs;
    1649                 :            :   }
    1650                 :            : }
    1651                 :            : 
    1652                 :          0 : void ITECareSimplifier::updateQueue(CareMap& queue,
    1653                 :            :                                     TNode e,
    1654                 :            :                                     ITECareSimplifier::CareSetPtr& careSet)
    1655                 :            : {
    1656                 :          0 :   CareMap::iterator it = queue.find(e), iend = queue.end();
    1657         [ -  - ]:          0 :   if (it != iend)
    1658                 :            :   {
    1659                 :          0 :     set<Node>& cs2 = (*it).second.getCareSet();
    1660                 :          0 :     ITECareSimplifier::CareSetPtr csNew = getNewSet();
    1661                 :          0 :     set_intersection(careSet.getCareSet().begin(),
    1662                 :          0 :                      careSet.getCareSet().end(),
    1663                 :            :                      cs2.begin(),
    1664                 :            :                      cs2.end(),
    1665                 :          0 :                      inserter(csNew.getCareSet(), csNew.getCareSet().begin()));
    1666                 :          0 :     (*it).second = csNew;
    1667                 :            :   }
    1668                 :            :   else
    1669                 :            :   {
    1670                 :          0 :     queue[e] = careSet;
    1671                 :            :   }
    1672                 :          0 : }
    1673                 :            : 
    1674                 :          0 : Node ITECareSimplifier::substitute(TNode e,
    1675                 :            :                                    TNodeMap& substTable,
    1676                 :            :                                    TNodeMap& cache)
    1677                 :            : {
    1678                 :          0 :   TNodeMap::iterator it = cache.find(e), iend = cache.end();
    1679         [ -  - ]:          0 :   if (it != iend)
    1680                 :            :   {
    1681                 :          0 :     return it->second;
    1682                 :            :   }
    1683                 :            : 
    1684                 :            :   // do substitution?
    1685                 :          0 :   it = substTable.find(e);
    1686                 :          0 :   iend = substTable.end();
    1687         [ -  - ]:          0 :   if (it != iend)
    1688                 :            :   {
    1689                 :          0 :     Node result = substitute(it->second, substTable, cache);
    1690                 :          0 :     cache[e] = result;
    1691                 :          0 :     return result;
    1692                 :            :   }
    1693                 :            : 
    1694                 :          0 :   size_t sz = e.getNumChildren();
    1695         [ -  - ]:          0 :   if (sz == 0)
    1696                 :            :   {
    1697                 :          0 :     cache[e] = e;
    1698                 :          0 :     return e;
    1699                 :            :   }
    1700                 :            : 
    1701                 :          0 :   NodeBuilder builder(e.getKind());
    1702         [ -  - ]:          0 :   if (e.getMetaKind() == kind::metakind::PARAMETERIZED)
    1703                 :            :   {
    1704                 :          0 :     builder << e.getOperator();
    1705                 :            :   }
    1706         [ -  - ]:          0 :   for (unsigned i = 0; i < e.getNumChildren(); ++i)
    1707                 :            :   {
    1708                 :          0 :     builder << substitute(e[i], substTable, cache);
    1709                 :            :   }
    1710                 :            : 
    1711                 :          0 :   Node result = builder;
    1712                 :            :   // it = substTable.find(result);
    1713                 :            :   // if (it != iend) {
    1714                 :            :   //   result = substitute(it->second, substTable, cache);
    1715                 :            :   // }
    1716                 :          0 :   cache[e] = result;
    1717                 :          0 :   return result;
    1718                 :            : }
    1719                 :            : 
    1720                 :          0 : Node ITECareSimplifier::simplifyWithCare(TNode e)
    1721                 :            : {
    1722                 :          0 :   TNodeMap substTable;
    1723                 :            : 
    1724                 :            :   /* This extra block is to trigger the destructors for cs and cs2
    1725                 :            :    * before starting garbage collection.
    1726                 :            :    */
    1727                 :            :   {
    1728                 :          0 :     CareMap queue;
    1729                 :          0 :     CareMap::iterator it;
    1730                 :          0 :     ITECareSimplifier::CareSetPtr cs = getNewSet();
    1731                 :          0 :     ITECareSimplifier::CareSetPtr cs2;
    1732                 :          0 :     queue[e] = cs;
    1733                 :            : 
    1734                 :          0 :     TNode v;
    1735                 :            :     bool done;
    1736                 :            :     unsigned i;
    1737                 :            : 
    1738         [ -  - ]:          0 :     while (!queue.empty())
    1739                 :            :     {
    1740                 :          0 :       it = queue.end();
    1741                 :          0 :       --it;
    1742                 :          0 :       v = it->first;
    1743                 :          0 :       cs = it->second;
    1744                 :          0 :       set<Node>& css = cs.getCareSet();
    1745                 :          0 :       queue.erase(v);
    1746                 :            : 
    1747                 :          0 :       done = false;
    1748                 :          0 :       set<Node>::iterator iCare, iCareEnd = css.end();
    1749                 :            : 
    1750                 :          0 :       switch (v.getKind())
    1751                 :            :       {
    1752                 :          0 :         case Kind::ITE:
    1753                 :            :         {
    1754                 :          0 :           iCare = css.find(v[0]);
    1755         [ -  - ]:          0 :           if (iCare != iCareEnd)
    1756                 :            :           {
    1757                 :          0 :             Assert(substTable.find(v) == substTable.end());
    1758                 :          0 :             substTable[v] = v[1];
    1759                 :          0 :             updateQueue(queue, v[1], cs);
    1760                 :          0 :             done = true;
    1761                 :          0 :             break;
    1762                 :            :           }
    1763                 :            :           else
    1764                 :            :           {
    1765                 :          0 :             iCare = css.find(v[0].negate());
    1766         [ -  - ]:          0 :             if (iCare != iCareEnd)
    1767                 :            :             {
    1768                 :          0 :               Assert(substTable.find(v) == substTable.end());
    1769                 :          0 :               substTable[v] = v[2];
    1770                 :          0 :               updateQueue(queue, v[2], cs);
    1771                 :          0 :               done = true;
    1772                 :          0 :               break;
    1773                 :            :             }
    1774                 :            :           }
    1775                 :          0 :           updateQueue(queue, v[0], cs);
    1776                 :          0 :           cs2 = getNewSet();
    1777                 :          0 :           cs2.getCareSet() = css;
    1778                 :          0 :           cs2.getCareSet().insert(v[0]);
    1779                 :          0 :           updateQueue(queue, v[1], cs2);
    1780                 :          0 :           cs2 = getNewSet();
    1781                 :          0 :           cs2.getCareSet() = css;
    1782                 :          0 :           cs2.getCareSet().insert(v[0].negate());
    1783                 :          0 :           updateQueue(queue, v[2], cs2);
    1784                 :          0 :           done = true;
    1785                 :          0 :           break;
    1786                 :            :         }
    1787                 :          0 :         case Kind::AND:
    1788                 :            :         {
    1789         [ -  - ]:          0 :           for (i = 0; i < v.getNumChildren(); ++i)
    1790                 :            :           {
    1791                 :          0 :             iCare = css.find(v[i].negate());
    1792         [ -  - ]:          0 :             if (iCare != iCareEnd)
    1793                 :            :             {
    1794                 :          0 :               Assert(substTable.find(v) == substTable.end());
    1795                 :          0 :               substTable[v] = d_false;
    1796                 :          0 :               done = true;
    1797                 :          0 :               break;
    1798                 :            :             }
    1799                 :            :           }
    1800         [ -  - ]:          0 :           if (done) break;
    1801                 :            : 
    1802                 :          0 :           Assert(v.getNumChildren() > 1);
    1803                 :          0 :           updateQueue(queue, v[0], cs);
    1804                 :          0 :           cs2 = getNewSet();
    1805                 :          0 :           cs2.getCareSet() = css;
    1806                 :          0 :           cs2.getCareSet().insert(v[0]);
    1807         [ -  - ]:          0 :           for (i = 1; i < v.getNumChildren(); ++i)
    1808                 :            :           {
    1809                 :          0 :             updateQueue(queue, v[i], cs2);
    1810                 :            :           }
    1811                 :          0 :           done = true;
    1812                 :          0 :           break;
    1813                 :            :         }
    1814                 :          0 :         case Kind::OR:
    1815                 :            :         {
    1816         [ -  - ]:          0 :           for (i = 0; i < v.getNumChildren(); ++i)
    1817                 :            :           {
    1818                 :          0 :             iCare = css.find(v[i]);
    1819         [ -  - ]:          0 :             if (iCare != iCareEnd)
    1820                 :            :             {
    1821                 :          0 :               Assert(substTable.find(v) == substTable.end());
    1822                 :          0 :               substTable[v] = d_true;
    1823                 :          0 :               done = true;
    1824                 :          0 :               break;
    1825                 :            :             }
    1826                 :            :           }
    1827         [ -  - ]:          0 :           if (done) break;
    1828                 :            : 
    1829                 :          0 :           Assert(v.getNumChildren() > 1);
    1830                 :          0 :           updateQueue(queue, v[0], cs);
    1831                 :          0 :           cs2 = getNewSet();
    1832                 :          0 :           cs2.getCareSet() = css;
    1833                 :          0 :           cs2.getCareSet().insert(v[0].negate());
    1834         [ -  - ]:          0 :           for (i = 1; i < v.getNumChildren(); ++i)
    1835                 :            :           {
    1836                 :          0 :             updateQueue(queue, v[i], cs2);
    1837                 :            :           }
    1838                 :          0 :           done = true;
    1839                 :          0 :           break;
    1840                 :            :         }
    1841                 :          0 :         default: break;
    1842                 :            :       }
    1843                 :            : 
    1844         [ -  - ]:          0 :       if (done)
    1845                 :            :       {
    1846                 :          0 :         continue;
    1847                 :            :       }
    1848                 :            : 
    1849         [ -  - ]:          0 :       for (i = 0; i < v.getNumChildren(); ++i)
    1850                 :            :       {
    1851                 :          0 :         updateQueue(queue, v[i], cs);
    1852                 :            :       }
    1853                 :            :     }
    1854                 :            :   }
    1855                 :            :   /* Perform garbage collection. */
    1856         [ -  - ]:          0 :   while (!d_usedSets.empty())
    1857                 :            :   {
    1858                 :          0 :     CareSetPtrVal* used = d_usedSets.back();
    1859                 :          0 :     d_usedSets.pop_back();
    1860                 :          0 :     Assert(used->safeToGarbageCollect());
    1861         [ -  - ]:          0 :     delete used;
    1862                 :          0 :     Assert(d_careSetsOutstanding > 0);
    1863                 :          0 :     d_careSetsOutstanding--;
    1864                 :            :   }
    1865                 :            : 
    1866                 :          0 :   TNodeMap cache;
    1867                 :          0 :   return substitute(e, substTable, cache);
    1868                 :            : }
    1869                 :            : 
    1870                 :          0 : ITECareSimplifier::CareSetPtr ITECareSimplifier::CareSetPtr::mkNew(
    1871                 :            :     ITECareSimplifier& simp)
    1872                 :            : {
    1873                 :          0 :   CareSetPtrVal* val = new CareSetPtrVal(simp);
    1874                 :          0 :   return CareSetPtr(val);
    1875                 :            : }
    1876                 :            : 
    1877                 :            : }  // namespace util
    1878                 :            : }  // namespace preprocessing
    1879                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14