LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/theory/quantifiers - quantifiers_rewriter.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1204 1287 93.6 %
Date: 2025-02-09 13:32:29 Functions: 39 41 95.1 %
Branches: 900 1238 72.7 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * Top contributors (to current version):
       3                 :            :  *   Andrew Reynolds, Aina Niemetz, Morgan Deters
       4                 :            :  *
       5                 :            :  * This file is part of the cvc5 project.
       6                 :            :  *
       7                 :            :  * Copyright (c) 2009-2025 by the authors listed in the file AUTHORS
       8                 :            :  * in the top-level source directory and their institutional affiliations.
       9                 :            :  * All rights reserved.  See the file COPYING in the top-level source
      10                 :            :  * directory for licensing information.
      11                 :            :  * ****************************************************************************
      12                 :            :  *
      13                 :            :  * Implementation of QuantifiersRewriter class.
      14                 :            :  */
      15                 :            : 
      16                 :            : #include "theory/quantifiers/quantifiers_rewriter.h"
      17                 :            : 
      18                 :            : #include "expr/ascription_type.h"
      19                 :            : #include "expr/bound_var_manager.h"
      20                 :            : #include "expr/dtype.h"
      21                 :            : #include "expr/dtype_cons.h"
      22                 :            : #include "expr/elim_shadow_converter.h"
      23                 :            : #include "expr/node_algorithm.h"
      24                 :            : #include "expr/skolem_manager.h"
      25                 :            : #include "options/quantifiers_options.h"
      26                 :            : #include "proof/conv_proof_generator.h"
      27                 :            : #include "theory/arith/arith_msum.h"
      28                 :            : #include "theory/booleans/theory_bool_rewriter.h"
      29                 :            : #include "theory/datatypes/theory_datatypes_utils.h"
      30                 :            : #include "theory/quantifiers/bv_inverter.h"
      31                 :            : #include "theory/quantifiers/ematching/trigger.h"
      32                 :            : #include "theory/quantifiers/extended_rewrite.h"
      33                 :            : #include "theory/quantifiers/quant_split.h"
      34                 :            : #include "theory/quantifiers/quantifiers_attributes.h"
      35                 :            : #include "theory/quantifiers/skolemize.h"
      36                 :            : #include "theory/quantifiers/term_database.h"
      37                 :            : #include "theory/quantifiers/term_util.h"
      38                 :            : #include "theory/rewriter.h"
      39                 :            : #include "theory/strings/theory_strings_utils.h"
      40                 :            : #include "theory/uf/theory_uf_rewriter.h"
      41                 :            : #include "util/rational.h"
      42                 :            : 
      43                 :            : using namespace std;
      44                 :            : using namespace cvc5::internal::kind;
      45                 :            : using namespace cvc5::context;
      46                 :            : 
      47                 :            : namespace cvc5::internal {
      48                 :            : namespace theory {
      49                 :            : namespace quantifiers {
      50                 :            : 
      51                 :            : /**
      52                 :            :  * Attributes used for constructing bound variables in a canonical way. These
      53                 :            :  * are attributes that map to bound variable, introduced for the following
      54                 :            :  * purposes:
      55                 :            :  * - QRewPrenexAttribute: cached on (v, body) where we are prenexing bound
      56                 :            :  * variable v in a nested quantified formula within the given body.
      57                 :            :  * - QRewMiniscopeAttribute: cached on (v, q, i) where q is being miniscoped
      58                 :            :  * for F_i in its body (and F_1 ... F_n), and v is one of the bound variables
      59                 :            :  * that q binds.
      60                 :            :  * - QRewDtExpandAttribute: cached on (F, lit, a) where lit is the tested
      61                 :            :  * literal used for expanding a quantified datatype variable in quantified
      62                 :            :  * formula with body F, and a is the rational corresponding to the argument
      63                 :            :  * position of the variable, e.g. lit is ((_ is C) x) and x is
      64                 :            :  * replaced by (C y1 ... yn), where the argument position of yi is i.
      65                 :            :  */
      66                 :            : struct QRewPrenexAttributeId
      67                 :            : {
      68                 :            : };
      69                 :            : using QRewPrenexAttribute = expr::Attribute<QRewPrenexAttributeId, Node>;
      70                 :            : struct QRewMiniscopeAttributeId
      71                 :            : {
      72                 :            : };
      73                 :            : using QRewMiniscopeAttribute = expr::Attribute<QRewMiniscopeAttributeId, Node>;
      74                 :            : struct QRewDtExpandAttributeId
      75                 :            : {
      76                 :            : };
      77                 :            : using QRewDtExpandAttribute = expr::Attribute<QRewDtExpandAttributeId, Node>;
      78                 :            : 
      79                 :          0 : std::ostream& operator<<(std::ostream& out, RewriteStep s)
      80                 :            : {
      81 [ -  - ][ -  - ]:          0 :   switch (s)
         [ -  - ][ -  - ]
                    [ - ]
      82                 :            :   {
      83                 :          0 :     case COMPUTE_ELIM_SYMBOLS: out << "COMPUTE_ELIM_SYMBOLS"; break;
      84                 :          0 :     case COMPUTE_MINISCOPING: out << "COMPUTE_MINISCOPING"; break;
      85                 :          0 :     case COMPUTE_AGGRESSIVE_MINISCOPING:
      86                 :          0 :       out << "COMPUTE_AGGRESSIVE_MINISCOPING";
      87                 :          0 :       break;
      88                 :          0 :     case COMPUTE_PROCESS_TERMS: out << "COMPUTE_PROCESS_TERMS"; break;
      89                 :          0 :     case COMPUTE_PRENEX: out << "COMPUTE_PRENEX"; break;
      90                 :          0 :     case COMPUTE_VAR_ELIMINATION: out << "COMPUTE_VAR_ELIMINATION"; break;
      91                 :          0 :     case COMPUTE_COND_SPLIT: out << "COMPUTE_COND_SPLIT"; break;
      92                 :          0 :     case COMPUTE_EXT_REWRITE: out << "COMPUTE_EXT_REWRITE"; break;
      93                 :          0 :     default: out << "UnknownRewriteStep"; break;
      94                 :            :   }
      95                 :          0 :   return out;
      96                 :            : }
      97                 :            : 
      98                 :     134633 : QuantifiersRewriter::QuantifiersRewriter(NodeManager* nm,
      99                 :            :                                          Rewriter* r,
     100                 :     134633 :                                          const Options& opts)
     101                 :     134633 :     : TheoryRewriter(nm), d_rewriter(r), d_opts(opts)
     102                 :            : {
     103                 :     134633 :   registerProofRewriteRule(ProofRewriteRule::EXISTS_ELIM,
     104                 :            :                            TheoryRewriteCtx::PRE_DSL);
     105                 :     134633 :   registerProofRewriteRule(ProofRewriteRule::QUANT_UNUSED_VARS,
     106                 :            :                            TheoryRewriteCtx::PRE_DSL);
     107                 :            :   // QUANT_MERGE_PRENEX is part of the reconstruction for
     108                 :            :   // MACRO_QUANT_MERGE_PRENEX
     109                 :     134633 :   registerProofRewriteRule(ProofRewriteRule::MACRO_QUANT_MERGE_PRENEX,
     110                 :            :                            TheoryRewriteCtx::PRE_DSL);
     111                 :     134633 :   registerProofRewriteRule(ProofRewriteRule::MACRO_QUANT_PRENEX,
     112                 :            :                            TheoryRewriteCtx::PRE_DSL);
     113                 :     134633 :   registerProofRewriteRule(ProofRewriteRule::MACRO_QUANT_MINISCOPE,
     114                 :            :                            TheoryRewriteCtx::PRE_DSL);
     115                 :            :   // QUANT_MINISCOPE_OR is part of the reconstruction for MACRO_QUANT_MINISCOPE
     116                 :     134633 :   registerProofRewriteRule(ProofRewriteRule::MACRO_QUANT_PARTITION_CONNECTED_FV,
     117                 :            :                            TheoryRewriteCtx::PRE_DSL);
     118                 :            :   // note ProofRewriteRule::QUANT_DT_SPLIT is done by a module dynamically with
     119                 :            :   // manual proof generation thus not registered here.
     120                 :     134633 :   registerProofRewriteRule(ProofRewriteRule::MACRO_QUANT_VAR_ELIM_EQ,
     121                 :            :                            TheoryRewriteCtx::PRE_DSL);
     122                 :     134633 :   registerProofRewriteRule(ProofRewriteRule::MACRO_QUANT_VAR_ELIM_INEQ,
     123                 :            :                            TheoryRewriteCtx::PRE_DSL);
     124                 :     134633 :   registerProofRewriteRule(ProofRewriteRule::MACRO_QUANT_REWRITE_BODY,
     125                 :            :                            TheoryRewriteCtx::PRE_DSL);
     126                 :     134633 : }
     127                 :            : 
     128                 :      40330 : Node QuantifiersRewriter::rewriteViaRule(ProofRewriteRule id, const Node& n)
     129                 :            : {
     130 [ +  + ][ +  + ]:      40330 :   switch (id)
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
                    [ - ]
     131                 :            :   {
     132                 :       5665 :     case ProofRewriteRule::EXISTS_ELIM:
     133                 :            :     {
     134         [ +  + ]:       5665 :       if (n.getKind() != Kind::EXISTS)
     135                 :            :       {
     136                 :       4481 :         return Node::null();
     137                 :            :       }
     138                 :       1184 :       std::vector<Node> fchildren;
     139                 :       1184 :       fchildren.push_back(n[0]);
     140                 :       1184 :       fchildren.push_back(n[1].notNode());
     141         [ +  + ]:       1184 :       if (n.getNumChildren() == 3)
     142                 :            :       {
     143                 :          5 :         fchildren.push_back(n[2]);
     144                 :            :       }
     145                 :       1184 :       return d_nm->mkNode(Kind::NOT, d_nm->mkNode(Kind::FORALL, fchildren));
     146                 :            :     }
     147                 :       5244 :     case ProofRewriteRule::QUANT_UNUSED_VARS:
     148                 :            :     {
     149         [ -  + ]:       5244 :       if (!n.isClosure())
     150                 :            :       {
     151                 :        990 :         return Node::null();
     152                 :            :       }
     153                 :      10488 :       std::vector<Node> vars(n[0].begin(), n[0].end());
     154                 :       5244 :       std::vector<Node> activeVars;
     155                 :       5244 :       computeArgVec(vars, activeVars, n[1]);
     156         [ +  + ]:       5244 :       if (activeVars.size() < vars.size())
     157                 :            :       {
     158         [ +  + ]:        990 :         if (activeVars.empty())
     159                 :            :         {
     160                 :        699 :           return n[1];
     161                 :            :         }
     162                 :            :         return d_nm->mkNode(
     163                 :        291 :             n.getKind(), d_nm->mkNode(Kind::BOUND_VAR_LIST, activeVars), n[1]);
     164                 :            :       }
     165                 :            :     }
     166                 :       4254 :     break;
     167                 :       4983 :     case ProofRewriteRule::MACRO_QUANT_MERGE_PRENEX:
     168                 :            :     case ProofRewriteRule::QUANT_MERGE_PRENEX:
     169                 :            :     {
     170         [ -  + ]:       4983 :       if (!n.isClosure())
     171                 :            :       {
     172                 :        801 :         return Node::null();
     173                 :            :       }
     174                 :            :       // Don't check standard here, which can't be replicated in a proof checker
     175                 :            :       // without modelling the patterns.
     176                 :            :       // We remove duplicates if the macro version.
     177                 :            :       Node q = mergePrenex(
     178                 :       4983 :           n, false, id == ProofRewriteRule::MACRO_QUANT_MERGE_PRENEX);
     179         [ +  + ]:       4983 :       if (q != n)
     180                 :            :       {
     181                 :        801 :         return q;
     182                 :            :       }
     183                 :            :     }
     184                 :       4182 :     break;
     185                 :       4355 :     case ProofRewriteRule::MACRO_QUANT_PRENEX:
     186                 :            :     {
     187         [ +  - ]:       4355 :       if (n.getKind() == Kind::FORALL)
     188                 :            :       {
     189                 :       4355 :         std::vector<Node> args, nargs;
     190                 :       8710 :         Node nn = computePrenex(n, n[1], args, nargs, true, false);
     191 [ -  + ][ -  + ]:       4355 :         Assert(nargs.empty());
                 [ -  - ]
     192         [ +  + ]:       4355 :         if (!args.empty())
     193                 :            :         {
     194                 :       2088 :           std::vector<Node> qargs(n[0].begin(), n[0].end());
     195                 :        696 :           qargs.insert(qargs.end(), args.begin(), args.end());
     196                 :        696 :           Node bvl = d_nm->mkNode(Kind::BOUND_VAR_LIST, qargs);
     197                 :        696 :           return d_nm->mkNode(Kind::FORALL, bvl, nn);
     198                 :            :         }
     199                 :            :       }
     200                 :            :     }
     201                 :       3659 :     break;
     202                 :       4172 :     case ProofRewriteRule::MACRO_QUANT_MINISCOPE:
     203                 :            :     {
     204         [ -  + ]:       4172 :       if (n.getKind() != Kind::FORALL)
     205                 :            :       {
     206                 :       4148 :         return Node::null();
     207                 :            :       }
     208                 :       4172 :       Kind k = n[1].getKind();
     209 [ +  + ][ +  + ]:       4172 :       if (k != Kind::AND && k != Kind::ITE)
     210                 :            :       {
     211                 :       3803 :         return Node::null();
     212                 :            :       }
     213                 :            :       // note that qa is not needed; moreover external proofs should be agnostic
     214                 :            :       // to it
     215                 :        369 :       QAttributes qa;
     216                 :        369 :       QuantAttributes::computeQuantAttributes(n, qa);
     217                 :        369 :       Node nret = computeMiniscoping(n, qa, true, false);
     218         [ +  + ]:        369 :       if (nret != n)
     219                 :            :       {
     220                 :        345 :         return nret;
     221                 :            :       }
     222                 :            :     }
     223                 :         24 :     break;
     224                 :        275 :     case ProofRewriteRule::QUANT_MINISCOPE_AND:
     225                 :            :     {
     226 [ +  - ][ -  + ]:        275 :       if (n.getKind() != Kind::FORALL || n[1].getKind() != Kind::AND)
         [ +  - ][ -  + ]
                 [ -  - ]
     227                 :            :       {
     228                 :          0 :         return Node::null();
     229                 :            :       }
     230                 :        550 :       std::vector<Node> conj;
     231         [ +  + ]:       1165 :       for (const Node& nc : n[1])
     232                 :            :       {
     233                 :        890 :         conj.push_back(d_nm->mkNode(Kind::FORALL, n[0], nc));
     234                 :            :       }
     235                 :        275 :       return d_nm->mkAnd(conj);
     236                 :            :     }
     237                 :            :     break;
     238                 :       4057 :     case ProofRewriteRule::MACRO_QUANT_PARTITION_CONNECTED_FV:
     239                 :            :     {
     240 [ +  - ][ +  + ]:       4057 :       if (n.getKind() != Kind::FORALL || n[1].getKind() != Kind::OR)
         [ +  - ][ +  + ]
                 [ -  - ]
     241                 :            :       {
     242                 :       5768 :         return Node::null();
     243                 :            :       }
     244                 :            :       // note that qa is not needed; moreover external proofs should be agnostic
     245                 :            :       // to it
     246                 :       1385 :       QAttributes qa;
     247                 :       1385 :       QuantAttributes::computeQuantAttributes(n, qa);
     248                 :       2770 :       std::vector<Node> vars(n[0].begin(), n[0].end());
     249                 :       1385 :       Node body = n[1];
     250                 :       1385 :       Node nret = computeSplit(vars, body, qa);
     251         [ +  + ]:       1385 :       if (!nret.isNull())
     252                 :            :       {
     253                 :            :         // only do this rule if it is a proper split; otherwise it will be
     254                 :            :         // subsumed by QUANT_UNUSED_VARS.
     255         [ +  + ]:        432 :         if (nret.getKind() == Kind::OR)
     256                 :            :         {
     257                 :        424 :           return nret;
     258                 :            :         }
     259                 :            :       }
     260                 :            :     }
     261                 :        961 :     break;
     262                 :        394 :     case ProofRewriteRule::QUANT_MINISCOPE_OR:
     263                 :            :     {
     264 [ +  - ][ -  + ]:        394 :       if (n.getKind() != Kind::FORALL || n[1].getKind() != Kind::OR)
         [ +  - ][ -  + ]
                 [ -  - ]
     265                 :            :       {
     266                 :          0 :         return Node::null();
     267                 :            :       }
     268                 :        394 :       size_t nvars = n[0].getNumChildren();
     269                 :        788 :       std::vector<Node> disj;
     270                 :        788 :       std::unordered_set<Node> varsUsed;
     271                 :        394 :       size_t varIndex = 0;
     272         [ +  + ]:       1629 :       for (const Node& d : n[1])
     273                 :            :       {
     274                 :            :         // Note that we may apply to a nested quantified formula, in which
     275                 :            :         // case some variables in fvs may not be bound by this quantified
     276                 :            :         // formula.
     277                 :       1235 :         std::unordered_set<Node> fvs;
     278                 :       1235 :         expr::getFreeVariables(d, fvs);
     279                 :       1235 :         size_t prevVarIndex = varIndex;
     280                 :       2203 :         while (varIndex < nvars && fvs.find(n[0][varIndex]) != fvs.end())
     281                 :            :         {
     282                 :            :           // cannot have shadowing
     283         [ -  + ]:        968 :           if (varsUsed.find(n[0][varIndex]) != varsUsed.end())
     284                 :            :           {
     285                 :          0 :             return Node::null();
     286                 :            :           }
     287                 :        968 :           varsUsed.insert(n[0][varIndex]);
     288                 :        968 :           varIndex++;
     289                 :            :         }
     290                 :       2470 :         std::vector<Node> dvs(n[0].begin() + prevVarIndex,
     291                 :       4940 :                               n[0].begin() + varIndex);
     292         [ +  + ]:       1235 :         if (dvs.empty())
     293                 :            :         {
     294                 :        732 :           disj.emplace_back(d);
     295                 :            :         }
     296                 :            :         else
     297                 :            :         {
     298                 :        503 :           Node bvl = d_nm->mkNode(Kind::BOUND_VAR_LIST, dvs);
     299                 :        503 :           disj.emplace_back(d_nm->mkNode(Kind::FORALL, bvl, d));
     300                 :            :         }
     301                 :            :       }
     302                 :            :       // must consume all variables
     303         [ +  + ]:        394 :       if (varIndex != nvars)
     304                 :            :       {
     305                 :         18 :         return Node::null();
     306                 :            :       }
     307                 :        752 :       Node ret = d_nm->mkOr(disj);
     308                 :            :       // go back and ensure all variables are bound
     309                 :        752 :       std::unordered_set<Node> fvs;
     310                 :        376 :       expr::getFreeVariables(ret, fvs);
     311         [ +  + ]:       1344 :       for (const Node& v : n[0])
     312                 :            :       {
     313         [ -  + ]:        968 :         if (fvs.find(v) != fvs.end())
     314                 :            :         {
     315                 :          0 :           return Node::null();
     316                 :            :         }
     317                 :            :       }
     318                 :        376 :       return ret;
     319                 :            :     }
     320                 :            :     break;
     321                 :         54 :     case ProofRewriteRule::QUANT_MINISCOPE_ITE:
     322                 :            :     {
     323 [ +  - ][ -  + ]:         54 :       if (n.getKind() != Kind::FORALL || n[1].getKind() != Kind::ITE)
         [ +  - ][ -  + ]
                 [ -  - ]
     324                 :            :       {
     325                 :         54 :         return Node::null();
     326                 :            :       }
     327                 :        108 :       std::vector<Node> args(n[0].begin(), n[0].end());
     328                 :         54 :       Node body = n[1];
     329         [ +  - ]:         54 :       if (!expr::hasSubterm(body[0], args))
     330                 :            :       {
     331                 :            :         return d_nm->mkNode(Kind::ITE,
     332                 :            :                             body[0],
     333                 :        108 :                             d_nm->mkNode(Kind::FORALL, n[0], body[1]),
     334                 :        162 :                             d_nm->mkNode(Kind::FORALL, n[0], body[2]));
     335                 :            :       }
     336                 :            :     }
     337                 :          0 :     break;
     338                 :         21 :     case ProofRewriteRule::QUANT_DT_SPLIT:
     339                 :            :     {
     340                 :            :       // always runs split utility on the first variable
     341                 :         21 :       if (n.getKind() != Kind::FORALL || !n[0][0].getType().isDatatype())
     342                 :            :       {
     343                 :          0 :         return Node::null();
     344                 :            :       }
     345                 :         21 :       return QuantDSplit::split(nodeManager(), n, 0);
     346                 :            :     }
     347                 :            :     break;
     348                 :       7565 :     case ProofRewriteRule::MACRO_QUANT_VAR_ELIM_EQ:
     349                 :            :     case ProofRewriteRule::QUANT_VAR_ELIM_EQ:
     350                 :            :     case ProofRewriteRule::MACRO_QUANT_VAR_ELIM_INEQ:
     351                 :            :     {
     352 [ +  - ][ +  + ]:       7565 :       if (n.getKind() != Kind::FORALL || n.getNumChildren() != 2)
                 [ +  + ]
     353                 :            :       {
     354                 :       1204 :         return Node::null();
     355                 :            :       }
     356                 :      15010 :       std::vector<Node> args(n[0].begin(), n[0].end());
     357                 :       7505 :       std::vector<Node> vars;
     358                 :       7505 :       std::vector<Node> subs;
     359                 :       7505 :       Node body = n[1];
     360         [ +  + ]:       7505 :       if (id == ProofRewriteRule::MACRO_QUANT_VAR_ELIM_EQ)
     361                 :            :       {
     362                 :       3954 :         std::vector<Node> lits;
     363                 :       3954 :         getVarElim(body, args, vars, subs, lits);
     364                 :            :       }
     365         [ +  + ]:       3551 :       else if (id == ProofRewriteRule::QUANT_VAR_ELIM_EQ)
     366                 :            :       {
     367         [ -  + ]:        148 :         if (args.size() != 1)
     368                 :            :         {
     369                 :          0 :           return Node::null();
     370                 :            :         }
     371                 :        148 :         std::vector<Node> lits;
     372         [ +  - ]:        148 :         if (body.getKind() == Kind::OR)
     373                 :            :         {
     374                 :        148 :           lits.insert(lits.end(), body.begin(), body.end());
     375                 :            :         }
     376                 :            :         else
     377                 :            :         {
     378                 :          0 :           lits.push_back(body);
     379                 :            :         }
     380                 :        148 :         if (lits[0].getKind() != Kind::NOT
     381 [ +  - ][ -  + ]:        296 :             || lits[0][0].getKind() != Kind::EQUAL)
         [ +  - ][ -  + ]
                 [ -  - ]
     382                 :            :         {
     383                 :          0 :           return Node::null();
     384                 :            :         }
     385                 :        148 :         Node eq = lits[0][0];
     386                 :        148 :         if (eq[0] != args[0] || expr::hasSubterm(eq[1], eq[0]))
     387                 :            :         {
     388                 :          0 :           return Node::null();
     389                 :            :         }
     390                 :        148 :         vars.push_back(eq[0]);
     391                 :        148 :         subs.push_back(eq[1]);
     392                 :        148 :         args.clear();
     393                 :        148 :         std::vector<Node> remLits(lits.begin() + 1, lits.end());
     394                 :        148 :         body = d_nm->mkOr(remLits);
     395                 :            :       }
     396                 :            :       else
     397                 :            :       {
     398                 :            :         // assume empty attribute
     399                 :       3403 :         QAttributes qa;
     400                 :       3403 :         getVarElimIneq(n[1], args, vars, subs, qa);
     401                 :            :       }
     402                 :            :       // if we eliminated a variable, update body and reprocess
     403         [ +  + ]:       7505 :       if (!vars.empty())
     404                 :            :       {
     405 [ -  + ][ -  + ]:       1084 :         Assert(vars.size() == subs.size());
                 [ -  - ]
     406                 :       2168 :         std::vector<Node> qc(n.begin(), n.end());
     407                 :       1084 :         qc[1] =
     408                 :       2168 :             body.substitute(vars.begin(), vars.end(), subs.begin(), subs.end());
     409         [ +  + ]:       1084 :         if (args.empty())
     410                 :            :         {
     411                 :        596 :           return qc[1];
     412                 :            :         }
     413                 :        488 :         qc[0] = d_nm->mkNode(Kind::BOUND_VAR_LIST, args);
     414                 :        488 :         return d_nm->mkNode(Kind::FORALL, qc);
     415                 :            :       }
     416                 :            :     }
     417                 :       6421 :     break;
     418                 :       3545 :     case ProofRewriteRule::MACRO_QUANT_REWRITE_BODY:
     419                 :            :     {
     420         [ -  + ]:       3545 :       if (n.getKind() != Kind::FORALL)
     421                 :            :       {
     422                 :       1189 :         return Node::null();
     423                 :            :       }
     424                 :       3545 :       Node nr = computeRewriteBody(n);
     425         [ +  + ]:       3545 :       if (nr != n)
     426                 :            :       {
     427                 :       1189 :         return nr;
     428                 :            :       }
     429                 :            :     }
     430                 :       2356 :     break;
     431                 :          0 :     default: break;
     432                 :            :   }
     433                 :      21857 :   return Node::null();
     434                 :            : }
     435                 :            : 
     436                 :      40375 : bool QuantifiersRewriter::isLiteral( Node n ){
     437 [ -  - ][ +  + ]:      40375 :   switch( n.getKind() ){
     438                 :          0 :     case Kind::NOT:
     439                 :          0 :       return n[0].getKind() != Kind::NOT && isLiteral(n[0]);
     440                 :            :       break;
     441                 :          0 :     case Kind::OR:
     442                 :            :     case Kind::AND:
     443                 :            :     case Kind::IMPLIES:
     444                 :            :     case Kind::XOR:
     445                 :          0 :     case Kind::ITE: return false; break;
     446                 :      19704 :     case Kind::EQUAL:
     447                 :            :       // for boolean terms
     448                 :      19704 :       return !n[0].getType().isBoolean();
     449                 :            :       break;
     450                 :      20671 :     default: break;
     451                 :            :   }
     452                 :      20671 :   return true;
     453                 :            : }
     454                 :            : 
     455                 :   27812900 : void QuantifiersRewriter::computeArgs(const std::vector<Node>& args,
     456                 :            :                                       std::map<Node, bool>& activeMap,
     457                 :            :                                       Node n,
     458                 :            :                                       std::map<Node, bool>& visited)
     459                 :            : {
     460         [ +  + ]:   27812900 :   if( visited.find( n )==visited.end() ){
     461                 :   18749800 :     visited[n] = true;
     462         [ +  + ]:   18749800 :     if (n.getKind() == Kind::BOUND_VARIABLE)
     463                 :            :     {
     464         [ +  + ]:    3924490 :       if( std::find( args.begin(), args.end(), n )!=args.end() ){
     465                 :    3206870 :         activeMap[ n ] = true;
     466                 :            :       }
     467                 :            :     }
     468                 :            :     else
     469                 :            :     {
     470         [ +  + ]:   14825300 :       if (n.hasOperator())
     471                 :            :       {
     472                 :    8844820 :         computeArgs(args, activeMap, n.getOperator(), visited);
     473                 :            :       }
     474         [ +  + ]:   32396400 :       for( int i=0; i<(int)n.getNumChildren(); i++ ){
     475                 :   17571100 :         computeArgs( args, activeMap, n[i], visited );
     476                 :            :       }
     477                 :            :     }
     478                 :            :   }
     479                 :   27812900 : }
     480                 :            : 
     481                 :     784929 : void QuantifiersRewriter::computeArgVec(const std::vector<Node>& args,
     482                 :            :                                         std::vector<Node>& activeArgs,
     483                 :            :                                         Node n)
     484                 :            : {
     485 [ -  + ][ -  + ]:     784929 :   Assert(activeArgs.empty());
                 [ -  - ]
     486                 :    1569860 :   std::map< Node, bool > activeMap;
     487                 :    1569860 :   std::map< Node, bool > visited;
     488                 :     784929 :   computeArgs( args, activeMap, n, visited );
     489         [ +  + ]:     784929 :   if( !activeMap.empty() ){
     490                 :     778608 :     std::map<Node, bool>::iterator it;
     491         [ +  + ]:   74018400 :     for (const Node& v : args)
     492                 :            :     {
     493                 :   73239800 :       it = activeMap.find(v);
     494         [ +  + ]:   73239800 :       if (it != activeMap.end())
     495                 :            :       {
     496                 :    2166110 :         activeArgs.emplace_back(v);
     497                 :            :         // no longer active, which accounts for deleting duplicates
     498                 :    2166110 :         activeMap.erase(it);
     499                 :            :       }
     500                 :            :     }
     501                 :            :   }
     502                 :     784929 : }
     503                 :            : 
     504                 :     306361 : void QuantifiersRewriter::computeArgVec2(const std::vector<Node>& args,
     505                 :            :                                          std::vector<Node>& activeArgs,
     506                 :            :                                          Node n,
     507                 :            :                                          Node ipl)
     508                 :            : {
     509 [ -  + ][ -  + ]:     306361 :   Assert(activeArgs.empty());
                 [ -  - ]
     510                 :     612722 :   std::map< Node, bool > activeMap;
     511                 :     612722 :   std::map< Node, bool > visited;
     512                 :     306361 :   computeArgs( args, activeMap, n, visited );
     513                 :            :   // Collect variables in inst pattern list only if we cannot eliminate
     514                 :            :   // quantifier, or if we have an add-to-pool annotation.
     515                 :     306361 :   bool varComputePatList = !activeMap.empty();
     516         [ +  + ]:     307502 :   for (const Node& ip : ipl)
     517                 :            :   {
     518                 :       1141 :     Kind k = ip.getKind();
     519 [ +  - ][ -  + ]:       1141 :     if (k == Kind::INST_ADD_TO_POOL || k == Kind::SKOLEM_ADD_TO_POOL)
     520                 :            :     {
     521                 :          0 :       varComputePatList = true;
     522                 :          0 :       break;
     523                 :            :     }
     524                 :            :   }
     525         [ +  + ]:     306361 :   if (varComputePatList)
     526                 :            :   {
     527                 :     305706 :     computeArgs( args, activeMap, ipl, visited );
     528                 :            :   }
     529         [ +  + ]:     306361 :   if (!activeMap.empty())
     530                 :            :   {
     531         [ +  + ]:    1347880 :     for (const Node& a : args)
     532                 :            :     {
     533         [ +  + ]:    1042170 :       if (activeMap.find(a) != activeMap.end())
     534                 :            :       {
     535                 :    1040760 :         activeArgs.push_back(a);
     536                 :            :       }
     537                 :            :     }
     538                 :            :   }
     539                 :     306361 : }
     540                 :            : 
     541                 :     750328 : RewriteResponse QuantifiersRewriter::preRewrite(TNode q)
     542                 :            : {
     543                 :     750328 :   Kind k = q.getKind();
     544 [ +  + ][ +  + ]:     750328 :   if (k == Kind::FORALL || k == Kind::EXISTS)
     545                 :            :   {
     546                 :            :     // Do prenex merging now, since this may impact trigger selection.
     547                 :            :     // In particular consider:
     548                 :            :     //   (forall ((x Int)) (forall ((y Int)) (! (P x) :pattern ((f x)))))
     549                 :            :     // If we wait until post-rewrite, we would rewrite the inner quantified
     550                 :            :     // formula, dropping the pattern, so the entire formula becomes:
     551                 :            :     //   (forall ((x Int)) (P x))
     552                 :            :     // Instead, we merge to:
     553                 :            :     //   (forall ((x Int) (y Int)) (! (P x) :pattern ((f x))))
     554                 :            :     // eagerly here, where after we would drop y to obtain:
     555                 :            :     //   (forall ((x Int)) (! (P x) :pattern ((f x))))
     556                 :            :     // See issue #10303.
     557                 :     493876 :     Node qm = mergePrenex(q, true, true);
     558         [ +  + ]:     493876 :     if (q != qm)
     559                 :            :     {
     560                 :       3824 :       return RewriteResponse(REWRITE_AGAIN_FULL, qm);
     561                 :            :     }
     562                 :            :   }
     563                 :     746504 :   return RewriteResponse(REWRITE_DONE, q);
     564                 :            : }
     565                 :            : 
     566                 :     667140 : RewriteResponse QuantifiersRewriter::postRewrite(TNode in)
     567                 :            : {
     568         [ +  - ]:     667140 :   Trace("quantifiers-rewrite-debug") << "post-rewriting " << in << std::endl;
     569                 :     667140 :   RewriteStatus status = REWRITE_DONE;
     570                 :    1334280 :   Node ret = in;
     571                 :     667140 :   RewriteStep rew_op = COMPUTE_LAST;
     572                 :            :   // get the body
     573         [ +  + ]:     667140 :   if (in.getKind() == Kind::EXISTS)
     574                 :            :   {
     575                 :       9308 :     std::vector<Node> children;
     576                 :       9308 :     children.push_back(in[0]);
     577                 :       9308 :     children.push_back(in[1].notNode());
     578         [ +  + ]:       9308 :     if (in.getNumChildren() == 3)
     579                 :            :     {
     580                 :         79 :       children.push_back(in[2]);
     581                 :            :     }
     582                 :       9308 :     ret = nodeManager()->mkNode(Kind::FORALL, children);
     583                 :       9308 :     ret = ret.negate();
     584                 :       9308 :     status = REWRITE_AGAIN_FULL;
     585                 :            :   }
     586         [ +  + ]:     657832 :   else if (in.getKind() == Kind::FORALL)
     587                 :            :   {
     588                 :            :     // do prenex merging
     589                 :     401380 :     ret = mergePrenex(in, true, true);
     590         [ +  + ]:     401380 :     if (ret != in)
     591                 :            :     {
     592                 :         60 :       status = REWRITE_AGAIN_FULL;
     593                 :            :     }
     594 [ +  + ][ +  + ]:     401320 :     else if (in[1].isConst() && in.getNumChildren() == 2)
         [ +  - ][ +  + ]
                 [ -  - ]
     595                 :            :     {
     596                 :       2045 :       return RewriteResponse( status, in[1] );
     597                 :            :     }
     598                 :            :     else
     599                 :            :     {
     600                 :            :       //compute attributes
     601                 :     798550 :       QAttributes qa;
     602                 :     399275 :       QuantAttributes::computeQuantAttributes( in, qa );
     603         [ +  + ]:    3188480 :       for (unsigned i = 0; i < COMPUTE_LAST; ++i)
     604                 :            :       {
     605                 :    2851680 :         RewriteStep op = static_cast<RewriteStep>(i);
     606         [ +  + ]:    2851680 :         if( doOperation( in, op, qa ) ){
     607                 :    2031070 :           ret = computeOperation( in, op, qa );
     608         [ +  + ]:    2031070 :           if( ret!=in ){
     609                 :      62475 :             rew_op = op;
     610                 :      62475 :             status = REWRITE_AGAIN_FULL;
     611                 :      62475 :             break;
     612                 :            :           }
     613                 :            :         }
     614                 :            :       }
     615                 :            :     }
     616                 :            :   }
     617                 :            :   //print if changed
     618         [ +  + ]:     665095 :   if( in!=ret ){
     619         [ +  - ]:      71843 :     Trace("quantifiers-rewrite") << "*** rewrite (op=" << rew_op << ") " << in << std::endl;
     620         [ +  - ]:      71843 :     Trace("quantifiers-rewrite") << " to " << std::endl;
     621         [ +  - ]:      71843 :     Trace("quantifiers-rewrite") << ret << std::endl;
     622                 :            :   }
     623                 :     665095 :   return RewriteResponse( status, ret );
     624                 :            : }
     625                 :            : 
     626                 :     900239 : Node QuantifiersRewriter::mergePrenex(const Node& q, bool checkStd, bool rmDup)
     627                 :            : {
     628 [ +  + ][ -  + ]:     900239 :   Assert(q.getKind() == Kind::FORALL || q.getKind() == Kind::EXISTS);
         [ -  + ][ -  - ]
     629                 :     900239 :   Kind k = q.getKind();
     630                 :    1800480 :   std::vector<Node> boundVars;
     631                 :    1800480 :   Node body = q;
     632                 :     900239 :   bool combineQuantifiers = false;
     633                 :     900239 :   bool continueCombine = false;
     634         [ +  + ]:     915128 :   do
     635                 :            :   {
     636         [ +  + ]:     915128 :     if (rmDup)
     637                 :            :     {
     638         [ +  + ]:    4201030 :       for (const Node& v : body[0])
     639                 :            :       {
     640         [ +  + ]:    3287220 :         if (std::find(boundVars.begin(), boundVars.end(), v) == boundVars.end())
     641                 :            :         {
     642                 :    3287080 :           boundVars.push_back(v);
     643                 :            :         }
     644                 :            :         else
     645                 :            :         {
     646                 :            :           // if duplicate variable due to shadowing, we must rewrite
     647                 :        141 :           combineQuantifiers = true;
     648                 :            :         }
     649                 :            :       }
     650                 :            :     }
     651                 :            :     else
     652                 :            :     {
     653                 :       1318 :       boundVars.insert(boundVars.end(), body[0].begin(), body[0].end());
     654                 :            :     }
     655                 :     915128 :     continueCombine = false;
     656 [ +  + ][ +  + ]:     915128 :     if (body.getNumChildren() == 2 && body[1].getKind() == k)
         [ +  + ][ +  + ]
                 [ -  - ]
     657                 :            :     {
     658                 :      14889 :       bool process = true;
     659         [ +  + ]:      14889 :       if (checkStd)
     660                 :            :       {
     661                 :            :         // Should never combine a quantified formula with a pool or
     662                 :            :         // non-standard quantified formula here.
     663                 :            :         // Note that we technically should check
     664                 :            :         // doOperation(body[1], COMPUTE_PRENEX, qa) here, although this
     665                 :            :         // is too restrictive, as sometimes nested patterns should just be
     666                 :            :         // applied to the top level, for example:
     667                 :            :         // (forall ((x Int)) (forall ((y Int)) (! P :pattern ((f x y)))))
     668                 :            :         // should be a pattern for the top-level quantifier here.
     669                 :      13484 :         QAttributes qa;
     670                 :      13484 :         QuantAttributes::computeQuantAttributes(body[1], qa);
     671                 :      13484 :         process = qa.isStandard();
     672                 :            :       }
     673         [ +  - ]:      14889 :       if (process)
     674                 :            :       {
     675                 :      14889 :         body = body[1];
     676                 :      14889 :         continueCombine = true;
     677                 :      14889 :         combineQuantifiers = true;
     678                 :            :       }
     679                 :            :     }
     680                 :            :   } while (continueCombine);
     681         [ +  + ]:     900239 :   if (combineQuantifiers)
     682                 :            :   {
     683                 :       4685 :     NodeManager* nm = nodeManager();
     684                 :       9370 :     std::vector<Node> children;
     685                 :       4685 :     children.push_back(nm->mkNode(Kind::BOUND_VAR_LIST, boundVars));
     686                 :       4685 :     children.push_back(body[1]);
     687         [ +  + ]:       4685 :     if (body.getNumChildren() == 3)
     688                 :            :     {
     689                 :        224 :       children.push_back(body[2]);
     690                 :            :     }
     691                 :       4685 :     return nm->mkNode(k, children);
     692                 :            :   }
     693                 :     895554 :   return q;
     694                 :            : }
     695                 :            : 
     696                 :         71 : void QuantifiersRewriter::computeDtTesterIteSplit(
     697                 :            :     Node n,
     698                 :            :     std::map<Node, Node>& pcons,
     699                 :            :     std::map<Node, std::map<int, Node>>& ncons,
     700                 :            :     std::vector<Node>& conj) const
     701                 :            : {
     702 [ +  - ][ +  + ]:         97 :   if (n.getKind() == Kind::ITE && n[0].getKind() == Kind::APPLY_TESTER
                 [ -  - ]
     703                 :         97 :       && n[1].getType().isBoolean())
     704                 :            :   {
     705         [ +  - ]:         26 :     Trace("quantifiers-rewrite-ite-debug") << "Split tester condition : " << n << std::endl;
     706                 :         52 :     Node x = n[0][0];
     707                 :         26 :     std::map< Node, Node >::iterator itp = pcons.find( x );
     708         [ -  + ]:         26 :     if( itp!=pcons.end() ){
     709         [ -  - ]:          0 :       Trace("quantifiers-rewrite-ite-debug") << "...condition already set " << itp->second << std::endl;
     710         [ -  - ]:          0 :       computeDtTesterIteSplit( n[ itp->second==n[0] ? 1 : 2 ], pcons, ncons, conj );
     711                 :            :     }else{
     712                 :         52 :       Node tester = n[0].getOperator();
     713                 :         26 :       int index = datatypes::utils::indexOf(tester);
     714                 :         26 :       std::map< int, Node >::iterator itn = ncons[x].find( index );
     715         [ -  + ]:         26 :       if( itn!=ncons[x].end() ){
     716         [ -  - ]:          0 :         Trace("quantifiers-rewrite-ite-debug") << "...condition negated " << itn->second << std::endl;
     717                 :          0 :         computeDtTesterIteSplit( n[ 2 ], pcons, ncons, conj );
     718                 :            :       }else{
     719         [ +  + ]:         78 :         for( unsigned i=0; i<2; i++ ){
     720         [ +  + ]:         52 :           if( i==0 ){
     721                 :         26 :             pcons[x] = n[0];
     722                 :            :           }else{
     723                 :         26 :             pcons.erase( x );
     724                 :         26 :             ncons[x][index] = n[0].negate();
     725                 :            :           }
     726                 :         52 :           computeDtTesterIteSplit( n[i+1], pcons, ncons, conj );
     727                 :            :         }
     728                 :         26 :         ncons[x].erase( index );
     729                 :            :       }
     730                 :            :     }
     731                 :            :   }
     732                 :            :   else
     733                 :            :   {
     734                 :         45 :     NodeManager* nm = nodeManager();
     735         [ +  - ]:         45 :     Trace("quantifiers-rewrite-ite-debug") << "Return value : " << n << std::endl;
     736                 :         90 :     std::vector< Node > children;
     737                 :         45 :     children.push_back( n );
     738                 :         90 :     std::vector< Node > vars;
     739                 :            :     //add all positive testers
     740         [ +  + ]:         71 :     for( std::map< Node, Node >::iterator it = pcons.begin(); it != pcons.end(); ++it ){
     741                 :         26 :       children.push_back( it->second.negate() );
     742                 :         26 :       vars.push_back( it->first );
     743                 :            :     }
     744                 :            :     //add all negative testers
     745         [ +  + ]:        104 :     for( std::map< Node, std::map< int, Node > >::iterator it = ncons.begin(); it != ncons.end(); ++it ){
     746                 :        118 :       Node x = it->first;
     747                 :            :       //only if we haven't settled on a positive tester
     748         [ +  + ]:         59 :       if( std::find( vars.begin(), vars.end(), x )==vars.end() ){
     749                 :            :         //check if we have exhausted all options but one
     750                 :         33 :         const DType& dt = x.getType().getDType();
     751                 :         66 :         std::vector< Node > nchildren;
     752                 :         33 :         int pos_cons = -1;
     753         [ +  + ]:         99 :         for( int i=0; i<(int)dt.getNumConstructors(); i++ ){
     754                 :         66 :           std::map< int, Node >::iterator itt = it->second.find( i );
     755         [ +  + ]:         66 :           if( itt==it->second.end() ){
     756         [ +  - ]:         33 :             pos_cons = pos_cons==-1 ? i : -2;
     757                 :            :           }else{
     758                 :         33 :             nchildren.push_back( itt->second.negate() );
     759                 :            :           }
     760                 :            :         }
     761         [ +  - ]:         33 :         if( pos_cons>=0 ){
     762                 :         33 :           Node tester = dt[pos_cons].getTester();
     763                 :         33 :           children.push_back(
     764                 :         66 :               nm->mkNode(Kind::APPLY_TESTER, tester, x).negate());
     765                 :            :         }else{
     766                 :          0 :           children.insert( children.end(), nchildren.begin(), nchildren.end() );
     767                 :            :         }
     768                 :            :       }
     769                 :            :     }
     770                 :            :     //make condition/output pair
     771                 :         45 :     Node c = children.size() == 1 ? children[0]
     772         [ -  + ]:         90 :                                   : nodeManager()->mkNode(Kind::OR, children);
     773                 :         45 :     conj.push_back( c );
     774                 :            :   }
     775                 :         71 : }
     776                 :            : 
     777                 :     362418 : Node QuantifiersRewriter::computeProcessTerms(const Node& q,
     778                 :            :                                               const std::vector<Node>& args,
     779                 :            :                                               Node body,
     780                 :            :                                               QAttributes& qa,
     781                 :            :                                               TConvProofGenerator* pg) const
     782                 :            : {
     783                 :     362418 :   options::IteLiftQuantMode iteLiftMode = options::IteLiftQuantMode::NONE;
     784         [ +  + ]:     362418 :   if (qa.isStandard())
     785                 :            :   {
     786                 :     345802 :     iteLiftMode = d_opts.quantifiers.iteLiftQuant;
     787                 :            :   }
     788                 :     362418 :   std::map<Node, Node> cache;
     789                 :     724836 :   return computeProcessTerms2(q, args, body, cache, iteLiftMode, pg);
     790                 :            : }
     791                 :            : 
     792                 :   11220700 : Node QuantifiersRewriter::computeProcessTerms2(
     793                 :            :     const Node& q,
     794                 :            :     const std::vector<Node>& args,
     795                 :            :     Node body,
     796                 :            :     std::map<Node, Node>& cache,
     797                 :            :     options::IteLiftQuantMode iteLiftMode,
     798                 :            :     TConvProofGenerator* pg) const
     799                 :            : {
     800                 :   11220700 :   NodeManager* nm = nodeManager();
     801         [ +  - ]:   22441300 :   Trace("quantifiers-rewrite-term-debug2")
     802                 :   11220700 :       << "computeProcessTerms " << body << std::endl;
     803                 :   11220700 :   std::map< Node, Node >::iterator iti = cache.find( body );
     804         [ +  + ]:   11220700 :   if( iti!=cache.end() ){
     805                 :    3459940 :     return iti->second;
     806                 :            :   }
     807                 :    7760720 :   bool changed = false;
     808                 :   15521400 :   std::vector<Node> children;
     809         [ +  + ]:   18619000 :   for (const Node& bc : body)
     810                 :            :   {
     811                 :            :     // do the recursive call on children
     812                 :   10858200 :     Node nn = computeProcessTerms2(q, args, bc, cache, iteLiftMode, pg);
     813                 :   10858200 :     children.push_back(nn);
     814 [ +  + ][ +  + ]:   10858200 :     changed = changed || nn != bc;
     815                 :            :   }
     816                 :            : 
     817                 :            :   // make return value
     818                 :   15521400 :   Node ret;
     819         [ +  + ]:    7760720 :   if (changed)
     820                 :            :   {
     821         [ +  + ]:      35360 :     if (body.getMetaKind() == kind::metakind::PARAMETERIZED)
     822                 :            :     {
     823                 :        888 :       children.insert(children.begin(), body.getOperator());
     824                 :            :     }
     825                 :      35360 :     ret = nm->mkNode(body.getKind(), children);
     826                 :            :   }
     827                 :            :   else
     828                 :            :   {
     829                 :    7725360 :     ret = body;
     830                 :            :   }
     831                 :            : 
     832                 :   15521400 :   Node retOrig = ret;
     833         [ +  - ]:   15521400 :   Trace("quantifiers-rewrite-term-debug2")
     834                 :    7760720 :       << "Returning " << ret << " for " << body << std::endl;
     835                 :            :   // do context-independent rewriting
     836         [ +  + ]:    7760720 :   if (ret.isClosure())
     837                 :            :   {
     838                 :            :     // Ensure no shadowing. If this term is a closure quantifying a variable
     839                 :            :     // in args, then we introduce fresh variable(s) and replace this closure
     840                 :            :     // to be over the fresh variables instead.
     841                 :     186130 :     std::vector<Node> oldVars;
     842                 :     186130 :     std::vector<Node> newVars;
     843         [ +  + ]:     227057 :     for (size_t i = 0, nvars = ret[0].getNumChildren(); i < nvars; i++)
     844                 :            :     {
     845                 :     267984 :       const Node& v = ret[0][i];
     846         [ +  + ]:     133992 :       if (std::find(args.begin(), args.end(), v) != args.end())
     847                 :            :       {
     848         [ +  - ]:        278 :         Trace("quantifiers-rewrite-unshadow")
     849                 :        139 :             << "Found shadowed variable " << v << " in " << q << std::endl;
     850                 :        139 :         oldVars.push_back(v);
     851                 :        278 :         Node nv = ElimShadowNodeConverter::getElimShadowVar(q, ret, i);
     852                 :        139 :         newVars.push_back(nv);
     853                 :            :       }
     854                 :            :     }
     855         [ +  + ]:      93065 :     if (!oldVars.empty())
     856                 :            :     {
     857 [ -  + ][ -  + ]:        139 :       Assert(oldVars.size() == newVars.size());
                 [ -  - ]
     858                 :            :       Node sbody = ret.substitute(
     859                 :        278 :           oldVars.begin(), oldVars.end(), newVars.begin(), newVars.end());
     860                 :        139 :       ret = sbody;
     861                 :            :     }
     862                 :            :   }
     863                 :    7667660 :   else if (ret.getKind() == Kind::EQUAL
     864 [ +  + ][ +  + ]:    7667660 :            && iteLiftMode != options::IteLiftQuantMode::NONE)
                 [ +  + ]
     865                 :            :   {
     866         [ +  + ]:    3565100 :     for (size_t i = 0; i < 2; i++)
     867                 :            :     {
     868         [ +  + ]:    2377440 :       if (ret[i].getKind() == Kind::ITE)
     869                 :            :       {
     870         [ +  + ]:      74456 :         Node no = i == 0 ? ret[1] : ret[0];
     871         [ +  + ]:      74456 :         if (no.getKind() != Kind::ITE)
     872                 :            :         {
     873                 :      68086 :           bool doRewrite = (iteLiftMode == options::IteLiftQuantMode::ALL);
     874                 :      68086 :           std::vector<Node> childrenIte;
     875                 :      68086 :           childrenIte.push_back(ret[i][0]);
     876         [ +  + ]:     204258 :           for (size_t j = 1; j <= 2; j++)
     877                 :            :           {
     878                 :            :             // check if it rewrites to a constant
     879                 :     408516 :             Node nn = nm->mkNode(Kind::EQUAL, no, ret[i][j]);
     880                 :     136172 :             childrenIte.push_back(nn);
     881                 :            :             // check if it will rewrite to a constant
     882                 :     136172 :             if (no == ret[i][j] || (no.isConst() && ret[i][j].isConst()))
     883                 :            :             {
     884                 :       1674 :               doRewrite = true;
     885                 :            :             }
     886                 :            :           }
     887         [ +  + ]:      68086 :           if (doRewrite)
     888                 :            :           {
     889                 :       1276 :             ret = nm->mkNode(Kind::ITE, childrenIte);
     890                 :       1276 :             break;
     891                 :            :           }
     892                 :            :         }
     893                 :            :       }
     894                 :            :     }
     895                 :            :   }
     896 [ +  + ][ +  + ]:    6478720 :   else if (ret.getKind() == Kind::SELECT && ret[0].getKind() == Kind::STORE)
         [ +  + ][ +  + ]
                 [ -  - ]
     897                 :            :   {
     898                 :        716 :     Node st = ret[0];
     899                 :        716 :     Node index = ret[1];
     900                 :        716 :     std::vector<Node> iconds;
     901                 :        716 :     std::vector<Node> elements;
     902         [ +  + ]:       1328 :     while (st.getKind() == Kind::STORE)
     903                 :            :     {
     904                 :        970 :       iconds.push_back(index.eqNode(st[1]));
     905                 :        970 :       elements.push_back(st[2]);
     906                 :        970 :       st = st[0];
     907                 :            :     }
     908                 :        358 :     ret = nm->mkNode(Kind::SELECT, st, index);
     909                 :            :     // conditions
     910         [ +  + ]:       1328 :     for (int i = (iconds.size() - 1); i >= 0; i--)
     911                 :            :     {
     912                 :        970 :       ret = nm->mkNode(Kind::ITE, iconds[i], elements[i], ret);
     913                 :            :     }
     914                 :            :   }
     915 [ +  + ][ +  + ]:    6478370 :   else if (ret.getKind() == Kind::HO_APPLY && !ret.getType().isFunction())
         [ +  + ][ +  + ]
                 [ -  - ]
     916                 :            :   {
     917                 :            :     // fully applied functions are converted to APPLY_UF here.
     918                 :      46442 :     Node fullApp = uf::TheoryUfRewriter::getApplyUfForHoApply(ret);
     919                 :            :     // it may not be possible to convert e.g. if the head is not a variable
     920         [ +  - ]:      23221 :     if (!fullApp.isNull())
     921                 :            :     {
     922                 :      23221 :       ret = fullApp;
     923                 :            :     }
     924                 :            :   }
     925         [ +  + ]:    7760720 :   if (pg != nullptr)
     926                 :            :   {
     927         [ +  + ]:       5995 :     if (retOrig != ret)
     928                 :            :     {
     929                 :        777 :       pg->addRewriteStep(retOrig,
     930                 :            :                          ret,
     931                 :            :                          nullptr,
     932                 :            :                          false,
     933                 :            :                          TrustId::MACRO_THEORY_REWRITE_RCONS_SIMPLE);
     934                 :            :     }
     935                 :            :   }
     936                 :    7760720 :   cache[body] = ret;
     937                 :    7760720 :   return ret;
     938                 :            : }
     939                 :            : 
     940                 :         28 : Node QuantifiersRewriter::computeExtendedRewrite(TNode q,
     941                 :            :                                                  const QAttributes& qa) const
     942                 :            : {
     943                 :            :   // do not apply to recursive functions
     944         [ +  + ]:         28 :   if (qa.isFunDef())
     945                 :            :   {
     946                 :          8 :     return q;
     947                 :            :   }
     948                 :         40 :   Node body = q[1];
     949                 :            :   // apply extended rewriter
     950                 :         40 :   Node bodyr = d_rewriter->extendedRewrite(body);
     951         [ +  + ]:         20 :   if (body != bodyr)
     952                 :            :   {
     953                 :         12 :     std::vector<Node> children;
     954                 :          6 :     children.push_back(q[0]);
     955                 :          6 :     children.push_back(bodyr);
     956         [ -  + ]:          6 :     if (q.getNumChildren() == 3)
     957                 :            :     {
     958                 :          0 :       children.push_back(q[2]);
     959                 :            :     }
     960                 :          6 :     return nodeManager()->mkNode(Kind::FORALL, children);
     961                 :            :   }
     962                 :         14 :   return q;
     963                 :            : }
     964                 :            : 
     965                 :     337418 : Node QuantifiersRewriter::computeCondSplit(Node body,
     966                 :            :                                            const std::vector<Node>& args,
     967                 :            :                                            QAttributes& qa) const
     968                 :            : {
     969                 :     337418 :   NodeManager* nm = nodeManager();
     970                 :     337418 :   Kind bk = body.getKind();
     971         [ +  + ]:       5329 :   if (d_opts.quantifiers.iteDtTesterSplitQuant && bk == Kind::ITE
     972 [ +  + ][ +  + ]:     342747 :       && body[0].getKind() == Kind::APPLY_TESTER)
         [ +  + ][ +  + ]
                 [ -  - ]
     973                 :            :   {
     974         [ +  - ]:         19 :     Trace("quantifiers-rewrite-ite-debug") << "DTT split : " << body << std::endl;
     975                 :         19 :     std::map< Node, Node > pcons;
     976                 :         19 :     std::map< Node, std::map< int, Node > > ncons;
     977                 :         19 :     std::vector< Node > conj;
     978                 :         19 :     computeDtTesterIteSplit( body, pcons, ncons, conj );
     979 [ -  + ][ -  + ]:         19 :     Assert(!conj.empty());
                 [ -  - ]
     980         [ +  - ]:         19 :     if( conj.size()>1 ){
     981         [ +  - ]:         19 :       Trace("quantifiers-rewrite-ite") << "*** Split ITE (datatype tester) " << body << " into : " << std::endl;
     982         [ +  + ]:         64 :       for( unsigned i=0; i<conj.size(); i++ ){
     983         [ +  - ]:         45 :         Trace("quantifiers-rewrite-ite") << "   " << conj[i] << std::endl;
     984                 :            :       }
     985                 :         19 :       return nm->mkNode(Kind::AND, conj);
     986                 :            :     }
     987                 :            :   }
     988         [ -  + ]:     337399 :   if (d_opts.quantifiers.condVarSplitQuant
     989                 :            :       == options::CondVarSplitQuantMode::OFF)
     990                 :            :   {
     991                 :          0 :     return body;
     992                 :            :   }
     993         [ +  - ]:     674798 :   Trace("cond-var-split-debug")
     994                 :     337399 :       << "Conditional var elim split " << body << "?" << std::endl;
     995                 :            :   // we only do this splitting if miniscoping is enabled, as this is
     996                 :            :   // required to eliminate variables in conjuncts below. We also never
     997                 :            :   // miniscope non-standard quantifiers, so this is also guarded here.
     998 [ +  + ][ +  + ]:     337399 :   if (!doMiniscopeConj(d_opts) || !qa.isStandard())
                 [ +  + ]
     999                 :            :   {
    1000                 :      26146 :     return body;
    1001                 :            :   }
    1002                 :            : 
    1003                 :     311253 :   bool aggCondSplit = (d_opts.quantifiers.condVarSplitQuant
    1004                 :            :                        == options::CondVarSplitQuantMode::AGG);
    1005                 :     311253 :   if (bk == Kind::ITE
    1006                 :     311253 :       || (bk == Kind::EQUAL && body[0].getType().isBoolean() && aggCondSplit))
    1007                 :            :   {
    1008 [ -  + ][ -  + ]:        445 :     Assert(!qa.isFunDef());
                 [ -  - ]
    1009                 :        445 :     bool do_split = false;
    1010                 :        445 :     unsigned index_max = bk == Kind::ITE ? 0 : 1;
    1011                 :        445 :     std::vector<Node> tmpArgs = args;
    1012         [ +  + ]:        759 :     for (unsigned index = 0; index <= index_max; index++)
    1013                 :            :     {
    1014 [ +  + ][ -  - ]:        445 :       if (hasVarElim(body[index], true, tmpArgs)
    1015 [ +  + ][ -  + ]:        445 :           || hasVarElim(body[index], false, tmpArgs))
         [ +  + ][ +  - ]
                 [ -  - ]
    1016                 :            :       {
    1017                 :        131 :         do_split = true;
    1018                 :        131 :         break;
    1019                 :            :       }
    1020                 :            :     }
    1021         [ +  + ]:        445 :     if (do_split)
    1022                 :            :     {
    1023                 :        262 :       Node pos;
    1024                 :        131 :       Node neg;
    1025         [ +  - ]:        131 :       if (bk == Kind::ITE)
    1026                 :            :       {
    1027                 :        131 :         pos = nm->mkNode(Kind::OR, body[0].negate(), body[1]);
    1028                 :        131 :         neg = nm->mkNode(Kind::OR, body[0], body[2]);
    1029                 :            :       }
    1030                 :            :       else
    1031                 :            :       {
    1032                 :          0 :         pos = nm->mkNode(Kind::OR, body[0].negate(), body[1]);
    1033                 :          0 :         neg = nm->mkNode(Kind::OR, body[0], body[1].negate());
    1034                 :            :       }
    1035         [ +  - ]:        262 :       Trace("cond-var-split-debug") << "*** Split (conditional variable eq) "
    1036                 :        131 :                                     << body << " into : " << std::endl;
    1037         [ +  - ]:        131 :       Trace("cond-var-split-debug") << "   " << pos << std::endl;
    1038         [ +  - ]:        131 :       Trace("cond-var-split-debug") << "   " << neg << std::endl;
    1039                 :        131 :       return nm->mkNode(Kind::AND, pos, neg);
    1040                 :            :     }
    1041                 :            :   }
    1042                 :            : 
    1043         [ +  + ]:     311122 :   if (bk == Kind::OR)
    1044                 :            :   {
    1045                 :     130194 :     unsigned size = body.getNumChildren();
    1046                 :     130194 :     bool do_split = false;
    1047                 :     130194 :     unsigned split_index = 0;
    1048         [ +  + ]:     514644 :     for (unsigned i = 0; i < size; i++)
    1049                 :            :     {
    1050                 :            :       // check if this child is a (conditional) variable elimination
    1051                 :     384956 :       Node b = body[i];
    1052         [ +  + ]:     384956 :       if (b.getKind() == Kind::AND)
    1053                 :            :       {
    1054                 :      44004 :         std::vector<Node> vars;
    1055                 :      44004 :         std::vector<Node> subs;
    1056                 :      44004 :         std::vector<Node> tmpArgs = args;
    1057         [ +  + ]:      80255 :         for (unsigned j = 0, bsize = b.getNumChildren(); j < bsize; j++)
    1058                 :            :         {
    1059         [ +  + ]:      58759 :           if (getVarElimLit(body, b[j], false, tmpArgs, vars, subs))
    1060                 :            :           {
    1061         [ +  - ]:      13048 :             Trace("cond-var-split-debug") << "Variable elimination in child #"
    1062                 :       6524 :                                           << j << " under " << i << std::endl;
    1063                 :            :             // Figure out if we should split
    1064                 :            :             // Currently we split if the aggressive option is set, or
    1065                 :            :             // if the top-level OR is binary.
    1066 [ +  - ][ +  + ]:       6524 :             if (aggCondSplit || size == 2)
    1067                 :            :             {
    1068                 :        506 :               do_split = true;
    1069                 :            :             }
    1070                 :            :             // other splitting criteria go here
    1071                 :            : 
    1072         [ +  + ]:       6524 :             if (do_split)
    1073                 :            :             {
    1074                 :        506 :               split_index = i;
    1075                 :        506 :               break;
    1076                 :            :             }
    1077                 :       6018 :             vars.clear();
    1078                 :       6018 :             subs.clear();
    1079                 :       6018 :             tmpArgs = args;
    1080                 :            :           }
    1081                 :            :         }
    1082                 :            :       }
    1083         [ +  + ]:     384956 :       if (do_split)
    1084                 :            :       {
    1085                 :        506 :         break;
    1086                 :            :       }
    1087                 :            :     }
    1088         [ +  + ]:     130194 :     if (do_split)
    1089                 :            :     {
    1090                 :            :       // For the sake of proofs, if we are not splitting the first child,
    1091                 :            :       // we first rearrange so that it is first, which can be proven by
    1092                 :            :       // ACI_NORM.
    1093                 :       1012 :       std::vector<Node> splitChildren;
    1094         [ +  + ]:        506 :       if (split_index != 0)
    1095                 :            :       {
    1096                 :        132 :         splitChildren.push_back(body[split_index]);
    1097         [ +  + ]:        396 :         for (size_t i = 0; i < size; i++)
    1098                 :            :         {
    1099         [ +  + ]:        264 :           if (i != split_index)
    1100                 :            :           {
    1101                 :        132 :             splitChildren.push_back(body[i]);
    1102                 :            :           }
    1103                 :            :         }
    1104                 :        132 :         return nm->mkNode(Kind::OR, splitChildren);
    1105                 :            :       }
    1106                 :            :       // This is expected to be proven by the RARE rule bool-or-and-distrib.
    1107                 :        748 :       std::vector<Node> children;
    1108         [ +  + ]:       1122 :       for (TNode bc : body)
    1109                 :            :       {
    1110                 :        748 :         children.push_back(bc);
    1111                 :            :       }
    1112         [ +  + ]:       1495 :       for (TNode bci : body[split_index])
    1113                 :            :       {
    1114                 :       1121 :         children[split_index] = bci;
    1115                 :       1121 :         splitChildren.push_back(nm->mkNode(Kind::OR, children));
    1116                 :            :       }
    1117                 :            :       // split the AND child, for example:
    1118                 :            :       //  ( x!=a ^ P(x) ) V Q(x) ---> ( x!=a V Q(x) ) ^ ( P(x) V Q(x) )
    1119                 :        374 :       return nm->mkNode(Kind::AND, splitChildren);
    1120                 :            :     }
    1121                 :            :   }
    1122                 :            : 
    1123                 :     310616 :   return body;
    1124                 :            : }
    1125                 :            : 
    1126                 :      14796 : bool QuantifiersRewriter::isVarElim(Node v, Node s)
    1127                 :            : {
    1128 [ -  + ][ -  + ]:      14796 :   Assert(v.getKind() == Kind::BOUND_VARIABLE);
                 [ -  - ]
    1129                 :      14796 :   return !expr::hasSubterm(s, v) && s.getType() == v.getType();
    1130                 :            : }
    1131                 :            : 
    1132                 :     100251 : Node QuantifiersRewriter::getVarElimEq(Node lit,
    1133                 :            :                                        const std::vector<Node>& args,
    1134                 :            :                                        Node& var) const
    1135                 :            : {
    1136 [ -  + ][ -  + ]:     100251 :   Assert(lit.getKind() == Kind::EQUAL);
                 [ -  - ]
    1137                 :     100251 :   Node slv;
    1138                 :     200502 :   TypeNode tt = lit[0].getType();
    1139         [ +  + ]:     100251 :   if (tt.isRealOrInt())
    1140                 :            :   {
    1141                 :      50838 :     slv = getVarElimEqReal(lit, args, var);
    1142                 :            :   }
    1143         [ +  + ]:      49413 :   else if (tt.isBitVector())
    1144                 :            :   {
    1145                 :       1679 :     slv = getVarElimEqBv(lit, args, var);
    1146                 :            :   }
    1147         [ +  + ]:      47734 :   else if (tt.isStringLike())
    1148                 :            :   {
    1149                 :        221 :     slv = getVarElimEqString(lit, args, var);
    1150                 :            :   }
    1151                 :     200502 :   return slv;
    1152                 :            : }
    1153                 :            : 
    1154                 :      50838 : Node QuantifiersRewriter::getVarElimEqReal(Node lit,
    1155                 :            :                                            const std::vector<Node>& args,
    1156                 :            :                                            Node& var) const
    1157                 :            : {
    1158                 :            :   // for arithmetic, solve the equality
    1159                 :     101676 :   std::map<Node, Node> msum;
    1160         [ -  + ]:      50838 :   if (!ArithMSum::getMonomialSumLit(lit, msum))
    1161                 :            :   {
    1162                 :          0 :     return Node::null();
    1163                 :            :   }
    1164                 :      50838 :   std::vector<Node>::const_iterator ita;
    1165         [ +  + ]:     153183 :   for (std::map<Node, Node>::iterator itm = msum.begin(); itm != msum.end();
    1166                 :     102345 :        ++itm)
    1167                 :            :   {
    1168         [ +  + ]:     103033 :     if (itm->first.isNull())
    1169                 :            :     {
    1170                 :      10024 :       continue;
    1171                 :            :     }
    1172                 :      93009 :     ita = std::find(args.begin(), args.end(), itm->first);
    1173         [ +  + ]:      93009 :     if (ita != args.end())
    1174                 :            :     {
    1175                 :       1586 :       Node veq_c;
    1176                 :       1586 :       Node val;
    1177                 :       1586 :       int ires = ArithMSum::isolate(itm->first, msum, veq_c, val, Kind::EQUAL);
    1178                 :       1586 :       if (ires != 0 && veq_c.isNull() && isVarElim(itm->first, val))
    1179                 :            :       {
    1180                 :        688 :         var = itm->first;
    1181                 :        688 :         return val;
    1182                 :            :       }
    1183                 :            :     }
    1184                 :            :   }
    1185                 :      50150 :   return Node::null();
    1186                 :            : }
    1187                 :            : 
    1188                 :       1679 : Node QuantifiersRewriter::getVarElimEqBv(Node lit,
    1189                 :            :                                          const std::vector<Node>& args,
    1190                 :            :                                          Node& var) const
    1191                 :            : {
    1192         [ -  + ]:       1679 :   if (TraceIsOn("quant-velim-bv"))
    1193                 :            :   {
    1194         [ -  - ]:          0 :     Trace("quant-velim-bv") << "Bv-Elim : " << lit << " varList = { ";
    1195         [ -  - ]:          0 :     for (const Node& v : args)
    1196                 :            :     {
    1197         [ -  - ]:          0 :       Trace("quant-velim-bv") << v << " ";
    1198                 :            :     }
    1199         [ -  - ]:          0 :     Trace("quant-velim-bv") << "} ?" << std::endl;
    1200                 :            :   }
    1201 [ -  + ][ -  + ]:       1679 :   Assert(lit.getKind() == Kind::EQUAL);
                 [ -  - ]
    1202                 :            :   // TODO (#1494) : linearize the literal using utility
    1203                 :            : 
    1204                 :            :   // compute a subset active_args of the bound variables args that occur in lit
    1205                 :       3358 :   std::vector<Node> active_args;
    1206                 :       1679 :   computeArgVec(args, active_args, lit);
    1207                 :            : 
    1208                 :       3358 :   BvInverter binv(d_opts);
    1209         [ +  + ]:       3573 :   for (const Node& cvar : active_args)
    1210                 :            :   {
    1211                 :            :     // solve for the variable on this path using the inverter
    1212                 :       2019 :     std::vector<unsigned> path;
    1213                 :       4038 :     Node slit = binv.getPathToPv(lit, cvar, path);
    1214         [ +  + ]:       2019 :     if (!slit.isNull())
    1215                 :            :     {
    1216                 :       1856 :       Node slv = binv.solveBvLit(cvar, lit, path, nullptr);
    1217         [ +  - ]:        928 :       Trace("quant-velim-bv") << "...solution : " << slv << std::endl;
    1218         [ +  + ]:        928 :       if (!slv.isNull())
    1219                 :            :       {
    1220                 :        375 :         var = cvar;
    1221                 :            :         // if this is a proper variable elimination, that is, var = slv where
    1222                 :            :         // var is not in the free variables of slv, then we can return this
    1223                 :            :         // as the variable elimination for lit.
    1224         [ +  + ]:        375 :         if (isVarElim(var, slv))
    1225                 :            :         {
    1226                 :        125 :           return slv;
    1227                 :            :         }
    1228                 :            :       }
    1229                 :            :     }
    1230                 :            :     else
    1231                 :            :     {
    1232         [ +  - ]:       1091 :       Trace("quant-velim-bv") << "...non-invertible path." << std::endl;
    1233                 :            :     }
    1234                 :            :   }
    1235                 :            : 
    1236                 :       1554 :   return Node::null();
    1237                 :            : }
    1238                 :            : 
    1239                 :        221 : Node QuantifiersRewriter::getVarElimEqString(Node lit,
    1240                 :            :                                              const std::vector<Node>& args,
    1241                 :            :                                              Node& var) const
    1242                 :            : {
    1243 [ -  + ][ -  + ]:        221 :   Assert(lit.getKind() == Kind::EQUAL);
                 [ -  - ]
    1244                 :            :   // The reasoning below involves equality entailment as
    1245                 :            :   // (= (str.++ s x t) r) entails (= x (str.substr r (str.len s) _)),
    1246                 :            :   // but these equalities are not equivalent.
    1247         [ +  + ]:        221 :   if (!d_opts.quantifiers.varEntEqElimQuant)
    1248                 :            :   {
    1249                 :        184 :     return Node::null();
    1250                 :            :   }
    1251                 :         37 :   NodeManager* nm = nodeManager();
    1252         [ +  + ]:         92 :   for (unsigned i = 0; i < 2; i++)
    1253                 :            :   {
    1254         [ +  + ]:         74 :     if (lit[i].getKind() == Kind::STRING_CONCAT)
    1255                 :            :     {
    1256                 :         37 :       TypeNode stype = lit[i].getType();
    1257         [ +  + ]:         92 :       for (unsigned j = 0, nchildren = lit[i].getNumChildren(); j < nchildren;
    1258                 :            :            j++)
    1259                 :            :       {
    1260         [ +  + ]:         74 :         if (std::find(args.begin(), args.end(), lit[i][j]) != args.end())
    1261                 :            :         {
    1262                 :         55 :           var = lit[i][j];
    1263                 :         55 :           Node slv = lit[1 - i];
    1264                 :        110 :           std::vector<Node> preL(lit[i].begin(), lit[i].begin() + j);
    1265                 :         55 :           std::vector<Node> postL(lit[i].begin() + j + 1, lit[i].end());
    1266                 :         55 :           Node tpre = strings::utils::mkConcat(preL, stype);
    1267                 :         55 :           Node tpost = strings::utils::mkConcat(postL, stype);
    1268                 :         55 :           Node slvL = nm->mkNode(Kind::STRING_LENGTH, slv);
    1269                 :         55 :           Node tpreL = nm->mkNode(Kind::STRING_LENGTH, tpre);
    1270                 :         55 :           Node tpostL = nm->mkNode(Kind::STRING_LENGTH, tpost);
    1271                 :        110 :           slv = nm->mkNode(
    1272                 :            :               Kind::STRING_SUBSTR,
    1273                 :            :               slv,
    1274                 :            :               tpreL,
    1275                 :        110 :               nm->mkNode(
    1276                 :        165 :                   Kind::SUB, slvL, nm->mkNode(Kind::ADD, tpreL, tpostL)));
    1277                 :            :           // forall x. r ++ x ++ t = s => P( x )
    1278                 :            :           //   is equivalent to
    1279                 :            :           // r ++ s' ++ t = s => P( s' ) where
    1280                 :            :           // s' = substr( s, |r|, |s|-(|t|+|r|) ).
    1281                 :            :           // We apply this only if r,t,s do not contain free variables.
    1282         [ +  + ]:         55 :           if (!expr::hasFreeVar(slv))
    1283                 :            :           {
    1284                 :         19 :             return slv;
    1285                 :            :           }
    1286                 :            :         }
    1287                 :            :       }
    1288                 :            :     }
    1289                 :            :   }
    1290                 :            : 
    1291                 :         18 :   return Node::null();
    1292                 :            : }
    1293                 :            : 
    1294                 :     671653 : bool QuantifiersRewriter::getVarElimLit(Node body,
    1295                 :            :                                         Node lit,
    1296                 :            :                                         bool pol,
    1297                 :            :                                         std::vector<Node>& args,
    1298                 :            :                                         std::vector<Node>& vars,
    1299                 :            :                                         std::vector<Node>& subs) const
    1300                 :            : {
    1301         [ +  + ]:     671653 :   if (lit.getKind() == Kind::NOT)
    1302                 :            :   {
    1303                 :      17730 :     lit = lit[0];
    1304                 :      17730 :     pol = !pol;
    1305 [ -  + ][ -  + ]:      17730 :     Assert(lit.getKind() != Kind::NOT);
                 [ -  - ]
    1306                 :            :   }
    1307                 :     671653 :   NodeManager* nm = nodeManager();
    1308         [ +  - ]:    1343310 :   Trace("var-elim-quant-debug")
    1309                 :     671653 :       << "Eliminate : " << lit << ", pol = " << pol << "?" << std::endl;
    1310         [ +  + ]:       1559 :   if (lit.getKind() == Kind::APPLY_TESTER && pol
    1311 [ +  + ][ +  + ]:     672638 :       && lit[0].getKind() == Kind::BOUND_VARIABLE
                 [ -  - ]
    1312 [ +  + ][ +  - ]:     673212 :       && d_opts.quantifiers.dtVarExpandQuant)
                 [ +  + ]
    1313                 :            :   {
    1314         [ +  - ]:        358 :     Trace("var-elim-dt") << "Expand datatype variable based on : " << lit
    1315                 :        179 :                          << std::endl;
    1316                 :            :     std::vector<Node>::iterator ita =
    1317                 :        179 :         std::find(args.begin(), args.end(), lit[0]);
    1318         [ +  - ]:        179 :     if (ita != args.end())
    1319                 :            :     {
    1320                 :        179 :       vars.push_back(lit[0]);
    1321                 :        358 :       Node tester = lit.getOperator();
    1322                 :        179 :       int index = datatypes::utils::indexOf(tester);
    1323                 :        179 :       const DType& dt = datatypes::utils::datatypeOf(tester);
    1324                 :        179 :       const DTypeConstructor& c = dt[index];
    1325                 :        358 :       std::vector<Node> newChildren;
    1326                 :        358 :       Node cons = c.getConstructor();
    1327                 :        358 :       TypeNode tspec;
    1328                 :            :       // take into account if parametric
    1329         [ +  + ]:        179 :       if (dt.isParametric())
    1330                 :            :       {
    1331                 :          2 :         TypeNode ltn = lit[0].getType();
    1332                 :          2 :         tspec = c.getInstantiatedConstructorType(ltn);
    1333                 :          2 :         cons = c.getInstantiatedConstructor(ltn);
    1334                 :            :       }
    1335                 :            :       else
    1336                 :            :       {
    1337                 :        177 :         tspec = cons.getType();
    1338                 :            :       }
    1339                 :        179 :       newChildren.push_back(cons);
    1340                 :        179 :       std::vector<Node> newVars;
    1341                 :        179 :       BoundVarManager* bvm = nm->getBoundVarManager();
    1342         [ +  + ]:        483 :       for (size_t j = 0, nargs = c.getNumArgs(); j < nargs; j++)
    1343                 :            :       {
    1344                 :        608 :         TypeNode tn = tspec[j];
    1345                 :        608 :         Node rn = nm->mkConstInt(Rational(j));
    1346                 :        912 :         Node cacheVal = BoundVarManager::getCacheValue(body, lit, rn);
    1347                 :        912 :         Node v = bvm->mkBoundVar<QRewDtExpandAttribute>(cacheVal, tn);
    1348                 :        304 :         newChildren.push_back(v);
    1349                 :        304 :         newVars.push_back(v);
    1350                 :            :       }
    1351                 :        179 :       subs.push_back(nm->mkNode(Kind::APPLY_CONSTRUCTOR, newChildren));
    1352         [ +  - ]:        358 :       Trace("var-elim-dt") << "...apply substitution " << subs[0] << "/"
    1353                 :        179 :                            << vars[0] << std::endl;
    1354                 :        179 :       args.erase(ita);
    1355                 :        179 :       args.insert(args.end(), newVars.begin(), newVars.end());
    1356                 :        179 :       return true;
    1357                 :            :     }
    1358                 :            :   }
    1359                 :            :   // all eliminations below guarded by varElimQuant()
    1360         [ +  + ]:     671474 :   if (!d_opts.quantifiers.varElimQuant)
    1361                 :            :   {
    1362                 :         18 :     return false;
    1363                 :            :   }
    1364                 :            : 
    1365         [ +  + ]:     671456 :   if (lit.getKind() == Kind::EQUAL)
    1366                 :            :   {
    1367                 :     360589 :     if (pol || lit[0].getType().isBoolean())
    1368                 :            :     {
    1369         [ +  + ]:     527858 :       for (unsigned i = 0; i < 2; i++)
    1370                 :            :       {
    1371                 :     357141 :         bool tpol = pol;
    1372                 :     357141 :         Node v_slv = lit[i];
    1373         [ +  + ]:     357141 :         if (v_slv.getKind() == Kind::NOT)
    1374                 :            :         {
    1375                 :      13530 :           v_slv = v_slv[0];
    1376                 :      13530 :           tpol = !tpol;
    1377                 :            :         }
    1378                 :            :         std::vector<Node>::iterator ita =
    1379                 :     357141 :             std::find(args.begin(), args.end(), v_slv);
    1380         [ +  + ]:     357141 :         if (ita != args.end())
    1381                 :            :         {
    1382         [ +  + ]:      13313 :           if (isVarElim(v_slv, lit[1 - i]))
    1383                 :            :           {
    1384                 :      11993 :             Node slv = lit[1 - i];
    1385         [ +  + ]:      11993 :             if (!tpol)
    1386                 :            :             {
    1387 [ -  + ][ -  + ]:        956 :               Assert(slv.getType().isBoolean());
                 [ -  - ]
    1388                 :        956 :               slv = slv.negate();
    1389                 :            :             }
    1390         [ +  - ]:      23986 :             Trace("var-elim-quant")
    1391                 :          0 :                 << "Variable eliminate based on equality : " << v_slv << " -> "
    1392                 :      11993 :                 << slv << std::endl;
    1393                 :      11993 :             vars.push_back(v_slv);
    1394                 :      11993 :             subs.push_back(slv);
    1395                 :      11993 :             args.erase(ita);
    1396                 :      11993 :             return true;
    1397                 :            :           }
    1398                 :            :         }
    1399                 :            :       }
    1400                 :            :     }
    1401                 :            :   }
    1402         [ +  + ]:     659463 :   if (lit.getKind() == Kind::BOUND_VARIABLE)
    1403                 :            :   {
    1404                 :       2895 :     std::vector< Node >::iterator ita = std::find( args.begin(), args.end(), lit );
    1405         [ +  + ]:       2895 :     if( ita!=args.end() ){
    1406         [ +  - ]:       2886 :       Trace("var-elim-bool") << "Variable eliminate : " << lit << std::endl;
    1407                 :       2886 :       vars.push_back( lit );
    1408                 :       2886 :       subs.push_back(nodeManager()->mkConst(pol));
    1409                 :       2886 :       args.erase( ita );
    1410                 :       2886 :       return true;
    1411                 :            :     }
    1412                 :            :   }
    1413 [ +  + ][ +  + ]:     656577 :   if (lit.getKind() == Kind::EQUAL && pol)
                 [ +  + ]
    1414                 :            :   {
    1415                 :     100251 :     Node var;
    1416                 :     100251 :     Node slv = getVarElimEq(lit, args, var);
    1417         [ +  + ]:     100251 :     if (!slv.isNull())
    1418                 :            :     {
    1419 [ -  + ][ -  + ]:        832 :       Assert(!var.isNull());
                 [ -  - ]
    1420                 :            :       std::vector<Node>::iterator ita =
    1421                 :        832 :           std::find(args.begin(), args.end(), var);
    1422 [ -  + ][ -  + ]:        832 :       Assert(ita != args.end());
                 [ -  - ]
    1423         [ +  - ]:       1664 :       Trace("var-elim-quant")
    1424                 :          0 :           << "Variable eliminate based on theory-specific solving : " << var
    1425                 :        832 :           << " -> " << slv << std::endl;
    1426 [ -  + ][ -  + ]:        832 :       Assert(!expr::hasSubterm(slv, var));
                 [ -  - ]
    1427 [ -  + ][ -  + ]:        832 :       Assert(slv.getType() == var.getType());
                 [ -  - ]
    1428                 :        832 :       vars.push_back(var);
    1429                 :        832 :       subs.push_back(slv);
    1430                 :        832 :       args.erase(ita);
    1431                 :        832 :       return true;
    1432                 :            :     }
    1433                 :            :   }
    1434                 :     655745 :   return false;
    1435                 :            : }
    1436                 :            : 
    1437                 :     334889 : bool QuantifiersRewriter::getVarElim(Node body,
    1438                 :            :                                      std::vector<Node>& args,
    1439                 :            :                                      std::vector<Node>& vars,
    1440                 :            :                                      std::vector<Node>& subs,
    1441                 :            :                                      std::vector<Node>& lits) const
    1442                 :            : {
    1443                 :     334889 :   return getVarElimInternal(body, body, false, args, vars, subs, lits);
    1444                 :            : }
    1445                 :            : 
    1446                 :     757835 : bool QuantifiersRewriter::getVarElimInternal(Node body,
    1447                 :            :                                              Node n,
    1448                 :            :                                              bool pol,
    1449                 :            :                                              std::vector<Node>& args,
    1450                 :            :                                              std::vector<Node>& vars,
    1451                 :            :                                              std::vector<Node>& subs,
    1452                 :            :                                              std::vector<Node>& lits) const
    1453                 :            : {
    1454                 :     757835 :   Kind nk = n.getKind();
    1455         [ +  + ]:    1026270 :   while (nk == Kind::NOT)
    1456                 :            :   {
    1457                 :     268435 :     n = n[0];
    1458                 :     268435 :     pol = !pol;
    1459                 :     268435 :     nk = n.getKind();
    1460                 :            :   }
    1461 [ +  + ][ +  + ]:     757835 :   if ((nk == Kind::AND && pol) || (nk == Kind::OR && !pol))
         [ +  + ][ +  + ]
    1462                 :            :   {
    1463         [ +  + ]:     558930 :     for (const Node& cn : n)
    1464                 :            :     {
    1465         [ +  + ]:     422187 :       if (getVarElimInternal(body, cn, pol, args, vars, subs, lits))
    1466                 :            :       {
    1467                 :       8198 :         return true;
    1468                 :            :       }
    1469                 :            :     }
    1470                 :     136743 :     return false;
    1471                 :            :   }
    1472         [ +  + ]:     612894 :   if (getVarElimLit(body, n, pol, args, vars, subs))
    1473                 :            :   {
    1474         [ +  + ]:       9366 :     lits.emplace_back(pol ? n : n.notNode());
    1475                 :       9366 :     return true;
    1476                 :            :   }
    1477                 :     603528 :   return false;
    1478                 :            : }
    1479                 :            : 
    1480                 :        759 : bool QuantifiersRewriter::hasVarElim(Node n,
    1481                 :            :                                      bool pol,
    1482                 :            :                                      std::vector<Node>& args) const
    1483                 :            : {
    1484                 :       1518 :   std::vector< Node > vars;
    1485                 :       1518 :   std::vector< Node > subs;
    1486                 :        759 :   std::vector<Node> lits;
    1487                 :       1518 :   return getVarElimInternal(n, n, pol, args, vars, subs, lits);
    1488                 :            : }
    1489                 :            : 
    1490                 :     325947 : bool QuantifiersRewriter::getVarElimIneq(Node body,
    1491                 :            :                                          std::vector<Node>& args,
    1492                 :            :                                          std::vector<Node>& bounds,
    1493                 :            :                                          std::vector<Node>& subs,
    1494                 :            :                                          QAttributes& qa) const
    1495                 :            : {
    1496         [ +  - ]:     325947 :   Trace("var-elim-quant-debug") << "getVarElimIneq " << body << std::endl;
    1497                 :            :   // For each variable v, we compute a set of implied bounds in the body
    1498                 :            :   // of the quantified formula.
    1499                 :            :   //   num_bounds[x][-1] stores the entailed lower bounds for x
    1500                 :            :   //   num_bounds[x][1] stores the entailed upper bounds for x
    1501                 :            :   //   num_bounds[x][0] stores the entailed disequalities for x
    1502                 :            :   // These bounds are stored in a map that maps the literal for the bound to
    1503                 :            :   // its required polarity. For example, for quantified formula
    1504                 :            :   //   (forall ((x Int)) (or (= x 0) (>= x a)))
    1505                 :            :   // we have:
    1506                 :            :   //   num_bounds[x][0] contains { x -> { (= x 0) -> false } }
    1507                 :            :   //   num_bounds[x][-1] contains { x -> { (>= x a) -> false } }
    1508                 :            :   // This method succeeds in eliminating x if its only occurrences are in
    1509                 :            :   // entailed disequalities, and one kind of bound. This is the case for the
    1510                 :            :   // above quantified formula, which can be rewritten to false. The reason
    1511                 :            :   // is that we can always chose a value for x that is arbitrarily large (resp.
    1512                 :            :   // small) to satisfy all disequalities and inequalities for x.
    1513                 :     651894 :   std::map<Node, std::map<int, std::map<Node, bool>>> num_bounds;
    1514                 :            :   // The set of variables that we know we can not eliminate
    1515                 :     651894 :   std::unordered_set<Node> ineligVars;
    1516                 :            :   // compute the entailed literals
    1517                 :     651894 :   QuantPhaseReq qpr(body);
    1518                 :            :   // map to track which literals we have already processed, and hence can be
    1519                 :            :   // excluded from the free variables check in the latter half of this method.
    1520                 :     651894 :   std::map<Node, int> processed;
    1521         [ +  + ]:     897739 :   for (const std::pair<const Node, bool>& pr : qpr.d_phase_reqs)
    1522                 :            :   {
    1523                 :            :     // an inequality that is entailed with a given polarity
    1524                 :     571792 :     Node lit = pr.first;
    1525                 :     571792 :     bool pol = pr.second;
    1526         [ +  - ]:    1143580 :     Trace("var-elim-quant-debug") << "Process inequality bounds : " << lit
    1527                 :     571792 :                                   << ", pol = " << pol << "..." << std::endl;
    1528                 :    1143580 :     bool canSolve = lit.getKind() == Kind::GEQ
    1529 [ +  + ][ +  + ]:     901058 :                     || (lit.getKind() == Kind::EQUAL
    1530                 :     901058 :                         && lit[0].getType().isRealOrInt() && !pol);
    1531         [ +  + ]:     571792 :     if (!canSolve)
    1532                 :            :     {
    1533                 :     449912 :       continue;
    1534                 :            :     }
    1535                 :            :     // solve the inequality
    1536                 :     121880 :     std::map<Node, Node> msum;
    1537         [ -  + ]:     121880 :     if (!ArithMSum::getMonomialSumLit(lit, msum))
    1538                 :            :     {
    1539                 :            :       // not an inequality, cannot use
    1540                 :          0 :       continue;
    1541                 :            :     }
    1542         [ +  + ]:     121880 :     processed[lit] = pol ? -1 : 1;
    1543         [ +  + ]:     377110 :     for (const std::pair<const Node, Node>& m : msum)
    1544                 :            :     {
    1545 [ +  + ][ +  + ]:     255230 :       if (!m.first.isNull() && ineligVars.find(m.first) == ineligVars.end())
                 [ +  + ]
    1546                 :            :       {
    1547                 :            :         std::vector<Node>::iterator ita =
    1548                 :     203741 :             std::find(args.begin(), args.end(), m.first);
    1549         [ +  + ]:     203741 :         if (ita != args.end())
    1550                 :            :         {
    1551                 :            :           // store that this literal is upper/lower bound for itm->first
    1552                 :     188588 :           Node veq_c;
    1553                 :     188588 :           Node val;
    1554                 :            :           int ires =
    1555                 :      94294 :               ArithMSum::isolate(m.first, msum, veq_c, val, lit.getKind());
    1556 [ +  - ][ +  + ]:      94294 :           if (ires != 0 && veq_c.isNull())
                 [ +  + ]
    1557                 :            :           {
    1558         [ +  + ]:      93560 :             if (lit.getKind() == Kind::GEQ)
    1559                 :            :             {
    1560                 :      58969 :               bool is_upper = pol != (ires == 1);
    1561         [ +  - ]:     117938 :               Trace("var-elim-ineq-debug")
    1562         [ -  - ]:          0 :                   << lit << " is a " << (is_upper ? "upper" : "lower")
    1563                 :      58969 :                   << " bound for " << m.first << std::endl;
    1564         [ +  - ]:     117938 :               Trace("var-elim-ineq-debug")
    1565                 :      58969 :                   << "  pol/ires = " << pol << " " << ires << std::endl;
    1566         [ +  + ]:      58969 :               num_bounds[m.first][is_upper ? 1 : -1][lit] = pol;
    1567                 :            :             }
    1568                 :            :             else
    1569                 :            :             {
    1570         [ +  - ]:      69182 :               Trace("var-elim-ineq-debug")
    1571                 :      34591 :                   << lit << " is a disequality for " << m.first << std::endl;
    1572                 :      34591 :               num_bounds[m.first][0][lit] = pol;
    1573                 :            :             }
    1574                 :            :           }
    1575                 :            :           else
    1576                 :            :           {
    1577         [ +  - ]:       1468 :             Trace("var-elim-ineq-debug")
    1578                 :          0 :                 << "...ineligible " << m.first
    1579                 :          0 :                 << " since it cannot be solved for (" << ires << ", " << veq_c
    1580                 :        734 :                 << ")." << std::endl;
    1581                 :        734 :             num_bounds.erase(m.first);
    1582                 :        734 :             ineligVars.insert(m.first);
    1583                 :            :           }
    1584                 :            :         }
    1585                 :            :         else
    1586                 :            :         {
    1587                 :            :           // compute variables in itm->first, these are not eligible for
    1588                 :            :           // elimination
    1589                 :     218894 :           std::unordered_set<Node> fvs;
    1590                 :     109447 :           expr::getFreeVariables(m.first, fvs);
    1591         [ +  + ]:     230303 :           for (const Node& v : fvs)
    1592                 :            :           {
    1593         [ +  - ]:     241712 :             Trace("var-elim-ineq-debug")
    1594                 :          0 :                 << "...ineligible " << v
    1595                 :     120856 :                 << " since it is contained in monomial." << std::endl;
    1596                 :     120856 :             num_bounds.erase(v);
    1597                 :     120856 :             ineligVars.insert(v);
    1598                 :            :           }
    1599                 :            :         }
    1600                 :            :       }
    1601                 :            :     }
    1602                 :            :   }
    1603                 :            : 
    1604                 :            :   // collect all variables that have only upper/lower bounds
    1605                 :     651894 :   std::map<Node, bool> elig_vars;
    1606                 :      50511 :   for (const std::pair<const Node, std::map<int, std::map<Node, bool>>>& nb :
    1607         [ +  + ]:     426969 :        num_bounds)
    1608                 :            :   {
    1609         [ +  + ]:      50511 :     if (nb.second.find(1) == nb.second.end())
    1610                 :            :     {
    1611         [ +  - ]:      60566 :       Trace("var-elim-ineq-debug")
    1612                 :      30283 :           << "Variable " << nb.first << " has only lower bounds." << std::endl;
    1613                 :      30283 :       elig_vars[nb.first] = false;
    1614                 :            :     }
    1615         [ +  + ]:      20228 :     else if (nb.second.find(-1) == nb.second.end())
    1616                 :            :     {
    1617         [ +  - ]:      18860 :       Trace("var-elim-ineq-debug")
    1618                 :       9430 :           << "Variable " << nb.first << " has only upper bounds." << std::endl;
    1619                 :       9430 :       elig_vars[nb.first] = true;
    1620                 :            :     }
    1621                 :            :   }
    1622         [ +  + ]:     325947 :   if (elig_vars.empty())
    1623                 :            :   {
    1624                 :     293688 :     return false;
    1625                 :            :   }
    1626                 :      64518 :   std::vector<Node> inactive_vars;
    1627                 :      64518 :   std::map<Node, std::map<int, bool> > visited;
    1628                 :            :   // traverse the body, invalidate variables if they occur in places other than
    1629                 :            :   // the bounds they occur in
    1630                 :      64518 :   std::unordered_map<TNode, std::unordered_set<int>> evisited;
    1631                 :      64518 :   std::vector<TNode> evisit;
    1632                 :      64518 :   std::vector<int> evisit_pol;
    1633                 :      32259 :   TNode ecur;
    1634                 :            :   int ecur_pol;
    1635                 :      32259 :   evisit.push_back(body);
    1636                 :      32259 :   evisit_pol.push_back(1);
    1637         [ +  + ]:      32259 :   if (!qa.d_ipl.isNull())
    1638                 :            :   {
    1639                 :            :     // do not eliminate variables that occur in the annotation
    1640                 :       4168 :     evisit.push_back(qa.d_ipl);
    1641                 :       4168 :     evisit_pol.push_back(0);
    1642                 :            :   }
    1643                 :     270337 :   do
    1644                 :            :   {
    1645                 :     302596 :     ecur = evisit.back();
    1646                 :     302596 :     evisit.pop_back();
    1647                 :     302596 :     ecur_pol = evisit_pol.back();
    1648                 :     302596 :     evisit_pol.pop_back();
    1649                 :     302596 :     std::unordered_set<int>& epp = evisited[ecur];
    1650         [ +  + ]:     302596 :     if (epp.find(ecur_pol) == epp.end())
    1651                 :            :     {
    1652                 :     278039 :       epp.insert(ecur_pol);
    1653         [ +  + ]:     278039 :       if (elig_vars.find(ecur) != elig_vars.end())
    1654                 :            :       {
    1655                 :            :         // variable contained in a place apart from bounds, no longer eligible
    1656                 :            :         // for elimination
    1657                 :      37351 :         elig_vars.erase(ecur);
    1658         [ +  - ]:      74702 :         Trace("var-elim-ineq-debug") << "...found occurrence of " << ecur
    1659                 :      37351 :                                      << ", mark ineligible" << std::endl;
    1660                 :            :       }
    1661                 :            :       else
    1662                 :            :       {
    1663                 :     240688 :         bool rec = true;
    1664                 :     240688 :         bool pol = ecur_pol >= 0;
    1665                 :     240688 :         bool hasPol = ecur_pol != 0;
    1666         [ +  + ]:     240688 :         if (hasPol)
    1667                 :            :         {
    1668                 :     126171 :           std::map<Node, int>::iterator itx = processed.find(ecur);
    1669 [ +  + ][ +  + ]:     126171 :           if (itx != processed.end() && itx->second == ecur_pol)
                 [ +  + ]
    1670                 :            :           {
    1671                 :            :             // already processed this literal as a bound
    1672                 :      17086 :             rec = false;
    1673                 :            :           }
    1674                 :            :         }
    1675         [ +  + ]:     240688 :         if (rec)
    1676                 :            :         {
    1677         [ +  + ]:     578115 :           for (unsigned j = 0, size = ecur.getNumChildren(); j < size; j++)
    1678                 :            :           {
    1679                 :            :             bool newHasPol;
    1680                 :            :             bool newPol;
    1681                 :     354513 :             QuantPhaseReq::getPolarity(ecur, j, hasPol, pol, newHasPol, newPol);
    1682                 :     354513 :             evisit.push_back(ecur[j]);
    1683 [ +  + ][ +  + ]:     354513 :             evisit_pol.push_back(newHasPol ? (newPol ? 1 : -1) : 0);
    1684                 :            :           }
    1685                 :            :         }
    1686                 :            :       }
    1687                 :            :     }
    1688 [ +  + ][ +  + ]:     302596 :   } while (!evisit.empty() && !elig_vars.empty());
                 [ +  + ]
    1689                 :            : 
    1690                 :      32259 :   bool ret = false;
    1691                 :      32259 :   NodeManager* nm = nodeManager();
    1692         [ +  + ]:      34621 :   for (const std::pair<const Node, bool>& ev : elig_vars)
    1693                 :            :   {
    1694                 :       2362 :     Node v = ev.first;
    1695         [ +  - ]:       4724 :     Trace("var-elim-ineq-debug")
    1696                 :       2362 :         << v << " is eligible for elimination." << std::endl;
    1697                 :            :     // do substitution corresponding to infinite projection, all literals
    1698                 :            :     // involving unbounded variable go to true/false
    1699                 :            :     // disequalities of eligible variables are also eliminated
    1700                 :       2362 :     std::map<int, std::map<Node, bool>>& nbv = num_bounds[v];
    1701         [ +  + ]:       7086 :     for (size_t i = 0; i < 2; i++)
    1702                 :            :     {
    1703 [ +  + ][ +  + ]:       4724 :       size_t nindex = i == 0 ? (elig_vars[v] ? 1 : -1) : 0;
    1704         [ +  + ]:       7428 :       for (const std::pair<const Node, bool>& nb : nbv[nindex])
    1705                 :            :       {
    1706         [ +  - ]:       5408 :         Trace("var-elim-ineq-debug")
    1707                 :       2704 :             << "  subs : " << nb.first << " -> " << nb.second << std::endl;
    1708                 :       2704 :         bounds.push_back(nb.first);
    1709                 :       2704 :         subs.push_back(nm->mkConst(nb.second));
    1710                 :            :       }
    1711                 :            :     }
    1712                 :            :     // eliminate from args
    1713                 :       2362 :     std::vector<Node>::iterator ita = std::find(args.begin(), args.end(), v);
    1714 [ -  + ][ -  + ]:       2362 :     Assert(ita != args.end());
                 [ -  - ]
    1715                 :       2362 :     args.erase(ita);
    1716                 :       2362 :     ret = true;
    1717                 :            :   }
    1718                 :      32259 :   return ret;
    1719                 :            : }
    1720                 :            : 
    1721                 :     330688 : Node QuantifiersRewriter::computeVarElimination(Node body,
    1722                 :            :                                                 std::vector<Node>& args,
    1723                 :            :                                                 QAttributes& qa) const
    1724                 :            : {
    1725 [ +  + ][ -  + ]:     330688 :   if (!d_opts.quantifiers.varElimQuant && !d_opts.quantifiers.dtVarExpandQuant
    1726         [ -  - ]:          0 :       && !d_opts.quantifiers.varIneqElimQuant)
    1727                 :            :   {
    1728                 :          0 :     return body;
    1729                 :            :   }
    1730         [ +  - ]:     661376 :   Trace("var-elim-quant-debug")
    1731                 :     330688 :       << "computeVarElimination " << body << std::endl;
    1732                 :     661376 :   std::vector<Node> vars;
    1733                 :     661376 :   std::vector<Node> subs;
    1734                 :            :   // standard variable elimination
    1735         [ +  + ]:     330688 :   if (d_opts.quantifiers.varElimQuant)
    1736                 :            :   {
    1737                 :     330418 :     std::vector<Node> lits;
    1738                 :     330418 :     getVarElim(body, args, vars, subs, lits);
    1739                 :            :   }
    1740                 :            :   // variable elimination based on one-direction inequalities
    1741 [ +  + ][ +  + ]:     330688 :   if (vars.empty() && d_opts.quantifiers.varIneqElimQuant)
                 [ +  + ]
    1742                 :            :   {
    1743                 :     322544 :     getVarElimIneq(body, args, vars, subs, qa);
    1744                 :            :   }
    1745                 :            :   // if we eliminated a variable, update body and reprocess
    1746         [ +  + ]:     330688 :   if (!vars.empty())
    1747                 :            :   {
    1748         [ +  - ]:      19652 :     Trace("var-elim-quant-debug")
    1749                 :       9826 :         << "VE " << vars.size() << "/" << args.size() << std::endl;
    1750 [ -  + ][ -  + ]:       9826 :     Assert(vars.size() == subs.size());
                 [ -  - ]
    1751                 :            :     // remake with eliminated nodes
    1752                 :       9826 :     body = body.substitute(vars.begin(), vars.end(), subs.begin(), subs.end());
    1753         [ +  + ]:       9826 :     if (!qa.d_ipl.isNull())
    1754                 :            :     {
    1755                 :        152 :       qa.d_ipl = qa.d_ipl.substitute(
    1756                 :         76 :           vars.begin(), vars.end(), subs.begin(), subs.end());
    1757                 :            :     }
    1758         [ +  - ]:       9826 :     Trace("var-elim-quant") << "Return " << body << std::endl;
    1759                 :            :   }
    1760                 :     330688 :   return body;
    1761                 :            : }
    1762                 :            : 
    1763                 :    2293020 : Node QuantifiersRewriter::computePrenex(Node q,
    1764                 :            :                                         Node body,
    1765                 :            :                                         std::vector<Node>& args,
    1766                 :            :                                         std::vector<Node>& nargs,
    1767                 :            :                                         bool pol,
    1768                 :            :                                         bool prenexAgg) const
    1769                 :            : {
    1770                 :    2293020 :   NodeManager* nm = nodeManager();
    1771                 :    2293020 :   Kind k = body.getKind();
    1772         [ +  + ]:    2293020 :   if (k == Kind::FORALL)
    1773                 :            :   {
    1774         [ -  + ]:      48210 :     if ((pol || prenexAgg)
    1775 [ +  + ][ +  - ]:     104840 :         && (d_opts.quantifiers.prenexQuantUser
    1776 [ +  + ][ +  + ]:      56630 :             || !QuantAttributes::hasPattern(body)))
         [ +  + ][ -  - ]
    1777                 :            :     {
    1778                 :       8304 :       std::vector< Node > terms;
    1779                 :       8304 :       std::vector< Node > subs;
    1780                 :       4152 :       BoundVarManager* bvm = nm->getBoundVarManager();
    1781         [ +  - ]:       4152 :       std::vector<Node>& argVec = pol ? args : nargs;
    1782                 :            :       //for doing prenexing of same-signed quantifiers
    1783                 :            :       //must rename each variable that already exists
    1784         [ +  + ]:      11187 :       for (const Node& v : body[0])
    1785                 :            :       {
    1786                 :       7035 :         terms.push_back(v);
    1787                 :      14070 :         TypeNode vt = v.getType();
    1788                 :      14070 :         Node vv;
    1789         [ +  + ]:       7035 :         if (!q.isNull())
    1790                 :            :         {
    1791                 :            :           // We cache based on the original quantified formula, the subformula
    1792                 :            :           // that we are pulling variables from (body), the variable v and an
    1793                 :            :           // index ii.
    1794                 :            :           // The argument body is required since in rare cases, two subformulas
    1795                 :            :           // may share the same variables. This is the case for define-fun
    1796                 :            :           // or inferred substitutions that contain quantified formulas.
    1797                 :            :           // The argument ii is required in case we are prenexing the same
    1798                 :            :           // subformula multiple times, e.g.
    1799                 :            :           // forall x. (forall y. P(y) or forall y. P(y)) --->
    1800                 :            :           // forall x z w. (P(z) or P(w)).
    1801                 :       7034 :           size_t index = 0;
    1802                 :         64 :           do
    1803                 :            :           {
    1804                 :      14196 :             Node ii = nm->mkConstInt(index);
    1805                 :      35490 :             Node cacheVal = nm->mkNode(Kind::SEXPR, {q, body, v, ii});
    1806                 :       7098 :             vv = bvm->mkBoundVar<QRewPrenexAttribute>(cacheVal, vt);
    1807                 :       7098 :             index++;
    1808         [ +  + ]:       7098 :           } while (std::find(argVec.begin(), argVec.end(), vv) != argVec.end());
    1809                 :            :         }
    1810                 :            :         else
    1811                 :            :         {
    1812                 :            :           // not specific to a quantified formula, use normal
    1813                 :          1 :           vv = NodeManager::mkBoundVar(vt);
    1814                 :            :         }
    1815                 :       7035 :         subs.push_back(vv);
    1816                 :            :       }
    1817                 :       4152 :       argVec.insert(argVec.end(), subs.begin(), subs.end());
    1818                 :       8304 :       Node newBody = body[1];
    1819                 :       4152 :       newBody = newBody.substitute( terms.begin(), terms.end(), subs.begin(), subs.end() );
    1820                 :       4152 :       return newBody;
    1821                 :            :     }
    1822                 :            :   //must remove structure
    1823                 :            :   }
    1824 [ +  + ][ -  + ]:    2240600 :   else if (prenexAgg && k == Kind::ITE && body.getType().isBoolean())
         [ -  - ][ -  + ]
         [ -  + ][ -  - ]
    1825                 :            :   {
    1826                 :            :     Node nn = nm->mkNode(Kind::AND,
    1827                 :          0 :                          nm->mkNode(Kind::OR, body[0].notNode(), body[1]),
    1828                 :          0 :                          nm->mkNode(Kind::OR, body[0], body[2]));
    1829                 :          0 :     return computePrenex(q, nn, args, nargs, pol, prenexAgg);
    1830                 :            :   }
    1831                 :    2240600 :   else if (prenexAgg && k == Kind::EQUAL && body[0].getType().isBoolean())
    1832                 :            :   {
    1833                 :            :     Node nn = nm->mkNode(Kind::AND,
    1834                 :          0 :                          nm->mkNode(Kind::OR, body[0].notNode(), body[1]),
    1835                 :          0 :                          nm->mkNode(Kind::OR, body[0], body[1].notNode()));
    1836                 :          0 :     return computePrenex(q, nn, args, nargs, pol, prenexAgg);
    1837         [ +  - ]:    2240600 :   }else if( body.getType().isBoolean() ){
    1838 [ -  + ][ -  + ]:    2240600 :     Assert(k != Kind::EXISTS);
                 [ -  - ]
    1839                 :    2240600 :     bool childrenChanged = false;
    1840                 :    2240600 :     std::vector< Node > newChildren;
    1841         [ +  + ]:    6546790 :     for (size_t i = 0, nchild = body.getNumChildren(); i < nchild; i++)
    1842                 :            :     {
    1843                 :            :       bool newHasPol;
    1844                 :            :       bool newPol;
    1845                 :    4306180 :       QuantPhaseReq::getPolarity( body, i, true, pol, newHasPol, newPol );
    1846         [ +  + ]:    4306180 :       if (!newHasPol)
    1847                 :            :       {
    1848                 :    2311850 :         newChildren.push_back( body[i] );
    1849                 :    2311850 :         continue;
    1850                 :            :       }
    1851                 :    3988670 :       Node n = computePrenex(q, body[i], args, nargs, newPol, prenexAgg);
    1852                 :    1994330 :       newChildren.push_back(n);
    1853 [ +  + ][ +  + ]:    1994330 :       childrenChanged = n != body[i] || childrenChanged;
         [ +  - ][ -  - ]
    1854                 :            :     }
    1855         [ +  + ]:    2240600 :     if( childrenChanged ){
    1856 [ +  + ][ +  + ]:       4313 :       if (k == Kind::NOT && newChildren[0].getKind() == Kind::NOT)
                 [ +  + ]
    1857                 :            :       {
    1858                 :        140 :         return newChildren[0][0];
    1859                 :            :       }
    1860                 :       4173 :       return nm->mkNode(k, newChildren);
    1861                 :            :     }
    1862                 :            :   }
    1863                 :    2284560 :   return body;
    1864                 :            : }
    1865                 :            : 
    1866                 :     132784 : Node QuantifiersRewriter::computeSplit(std::vector<Node>& args,
    1867                 :            :                                        Node body,
    1868                 :            :                                        QAttributes& qa) const
    1869                 :            : {
    1870 [ -  + ][ -  + ]:     132784 :   Assert(body.getKind() == Kind::OR);
                 [ -  - ]
    1871                 :     132784 :   size_t eqc_count = 0;
    1872                 :     132784 :   size_t eqc_active = 0;
    1873                 :     265568 :   std::map< Node, int > var_to_eqc;
    1874                 :     265568 :   std::map< int, std::vector< Node > > eqc_to_var;
    1875                 :     265568 :   std::map< int, std::vector< Node > > eqc_to_lit;
    1876                 :            : 
    1877                 :     265568 :   std::vector<Node> lits;
    1878                 :            : 
    1879         [ +  + ]:     910578 :   for( unsigned i=0; i<body.getNumChildren(); i++ ){
    1880                 :            :     //get variables contained in the literal
    1881                 :    1555590 :     Node n = body[i];
    1882                 :    1555590 :     std::vector< Node > lit_args;
    1883                 :     777794 :     computeArgVec( args, lit_args, n );
    1884         [ +  + ]:     777794 :     if( lit_args.empty() ){
    1885                 :       5622 :       lits.push_back( n );
    1886                 :            :     }else {
    1887                 :            :       //collect the equivalence classes this literal belongs to, and the new variables it contributes
    1888                 :    1544340 :       std::vector< int > eqcs;
    1889                 :    1544340 :       std::vector< Node > lit_new_args;
    1890                 :            :       //for each variable in literal
    1891         [ +  + ]:    2924940 :       for( unsigned j=0; j<lit_args.size(); j++) {
    1892                 :            :         //see if the variable has already been found
    1893         [ +  + ]:    2152770 :         if (var_to_eqc.find(lit_args[j])!=var_to_eqc.end()) {
    1894                 :    1417440 :           int eqc = var_to_eqc[lit_args[j]];
    1895         [ +  + ]:    1417440 :           if (std::find(eqcs.begin(), eqcs.end(), eqc)==eqcs.end()) {
    1896                 :     638701 :             eqcs.push_back(eqc);
    1897                 :            :           }
    1898                 :            :         }else{
    1899                 :     735325 :           lit_new_args.push_back(lit_args[j]);
    1900                 :            :         }
    1901                 :            :       }
    1902         [ +  + ]:     772172 :       if (eqcs.empty()) {
    1903                 :     257529 :         eqcs.push_back(eqc_count);
    1904                 :     257529 :         eqc_count++;
    1905                 :     257529 :         eqc_active++;
    1906                 :            :       }
    1907                 :            : 
    1908                 :     772172 :       int eqcz = eqcs[0];
    1909                 :            :       //merge equivalence classes with eqcz
    1910         [ +  + ]:     896230 :       for (unsigned j=1; j<eqcs.size(); j++) {
    1911                 :     124058 :         int eqc = eqcs[j];
    1912                 :            :         //move all variables from equivalence class
    1913         [ +  + ]:     583636 :         for (unsigned k=0; k<eqc_to_var[eqc].size(); k++) {
    1914                 :     919156 :           Node v = eqc_to_var[eqc][k];
    1915                 :     459578 :           var_to_eqc[v] = eqcz;
    1916                 :     459578 :           eqc_to_var[eqcz].push_back(v);
    1917                 :            :         }
    1918                 :     124058 :         eqc_to_var.erase(eqc);
    1919                 :            :         //move all literals from equivalence class
    1920         [ +  + ]:     519042 :         for (unsigned k=0; k<eqc_to_lit[eqc].size(); k++) {
    1921                 :     789968 :           Node l = eqc_to_lit[eqc][k];
    1922                 :     394984 :           eqc_to_lit[eqcz].push_back(l);
    1923                 :            :         }
    1924                 :     124058 :         eqc_to_lit.erase(eqc);
    1925                 :     124058 :         eqc_active--;
    1926                 :            :       }
    1927                 :            :       //add variables to equivalence class
    1928         [ +  + ]:    1507500 :       for (unsigned j=0; j<lit_new_args.size(); j++) {
    1929                 :     735325 :         var_to_eqc[lit_new_args[j]] = eqcz;
    1930                 :     735325 :         eqc_to_var[eqcz].push_back(lit_new_args[j]);
    1931                 :            :       }
    1932                 :            :       //add literal to equivalence class
    1933                 :     772172 :       eqc_to_lit[eqcz].push_back(n);
    1934                 :            :     }
    1935                 :            :   }
    1936 [ +  + ][ +  + ]:     132784 :   if ( eqc_active>1 || !lits.empty() || var_to_eqc.size()!=args.size() ){
         [ +  + ][ +  + ]
    1937                 :       2679 :     NodeManager* nm = nodeManager();
    1938         [ -  + ]:       2679 :     if (TraceIsOn("clause-split-debug"))
    1939                 :            :     {
    1940         [ -  - ]:          0 :       Trace("clause-split-debug")
    1941                 :          0 :           << "Split quantified formula with body " << body << std::endl;
    1942         [ -  - ]:          0 :       Trace("clause-split-debug") << "   Ground literals: " << std::endl;
    1943         [ -  - ]:          0 :       for (size_t i = 0; i < lits.size(); i++)
    1944                 :            :       {
    1945         [ -  - ]:          0 :         Trace("clause-split-debug") << "      " << lits[i] << std::endl;
    1946                 :            :       }
    1947         [ -  - ]:          0 :       Trace("clause-split-debug") << std::endl;
    1948         [ -  - ]:          0 :       Trace("clause-split-debug") << "Equivalence classes: " << std::endl;
    1949                 :            :     }
    1950         [ +  + ]:       6045 :     for (std::map< int, std::vector< Node > >::iterator it = eqc_to_lit.begin(); it != eqc_to_lit.end(); ++it ){
    1951                 :       3366 :       int eqc = it->first;
    1952         [ -  + ]:       3366 :       if (TraceIsOn("clause-split-debug"))
    1953                 :            :       {
    1954         [ -  - ]:          0 :         Trace("clause-split-debug") << "   Literals: " << std::endl;
    1955         [ -  - ]:          0 :         for (size_t i = 0; i < it->second.size(); i++)
    1956                 :            :         {
    1957         [ -  - ]:          0 :           Trace("clause-split-debug") << "      " << it->second[i] << std::endl;
    1958                 :            :         }
    1959         [ -  - ]:          0 :         Trace("clause-split-debug") << "   Variables: " << std::endl;
    1960         [ -  - ]:          0 :         for (size_t i = 0; i < eqc_to_var[eqc].size(); i++)
    1961                 :            :         {
    1962         [ -  - ]:          0 :           Trace("clause-split-debug")
    1963                 :          0 :               << "      " << eqc_to_var[eqc][i] << std::endl;
    1964                 :            :         }
    1965         [ -  - ]:          0 :         Trace("clause-split-debug") << std::endl;
    1966                 :            :       }
    1967                 :       3366 :       std::vector<Node>& evars = eqc_to_var[eqc];
    1968                 :            :       // for the sake of proofs, we provide the variables in the order
    1969                 :            :       // they appear in the original quantified formula
    1970                 :       6732 :       std::vector<Node> ovars;
    1971         [ +  + ]:      71893 :       for (const Node& v : args)
    1972                 :            :       {
    1973         [ +  + ]:      68527 :         if (std::find(evars.begin(), evars.end(), v) != evars.end())
    1974                 :            :         {
    1975                 :      29608 :           ovars.emplace_back(v);
    1976                 :            :         }
    1977                 :            :       }
    1978                 :       6732 :       Node bvl = nodeManager()->mkNode(Kind::BOUND_VAR_LIST, ovars);
    1979                 :       4863 :       Node bd = it->second.size() == 1 ? it->second[0]
    1980         [ +  + ]:       8229 :                                        : nm->mkNode(Kind::OR, it->second);
    1981                 :      10098 :       Node fa = nm->mkNode(Kind::FORALL, bvl, bd);
    1982                 :       3366 :       lits.push_back(fa);
    1983                 :            :     }
    1984 [ -  + ][ -  + ]:       2679 :     Assert(!lits.empty());
                 [ -  - ]
    1985                 :       5358 :     Node nf = nodeManager()->mkOr(lits);
    1986         [ +  - ]:       2679 :     Trace("clause-split-debug") << "Made node : " << nf << std::endl;
    1987                 :       2679 :     return nf;
    1988                 :            :   }
    1989                 :     130105 :   return Node::null();
    1990                 :            : }
    1991                 :            : 
    1992                 :     306681 : Node QuantifiersRewriter::mkForAll(const std::vector<Node>& args,
    1993                 :            :                                    Node body,
    1994                 :            :                                    QAttributes& qa) const
    1995                 :            : {
    1996         [ +  + ]:     306681 :   if (args.empty())
    1997                 :            :   {
    1998                 :        655 :     return body;
    1999                 :            :   }
    2000                 :     306026 :   NodeManager* nm = nodeManager();
    2001                 :     612052 :   std::vector<Node> children;
    2002                 :     306026 :   children.push_back(nm->mkNode(Kind::BOUND_VAR_LIST, args));
    2003                 :     306026 :   children.push_back(body);
    2004         [ +  + ]:     306026 :   if (!qa.d_ipl.isNull())
    2005                 :            :   {
    2006                 :        833 :     children.push_back(qa.d_ipl);
    2007                 :            :   }
    2008                 :     306026 :   return nm->mkNode(Kind::FORALL, children);
    2009                 :            : }
    2010                 :            : 
    2011                 :          2 : Node QuantifiersRewriter::mkForall(const std::vector<Node>& args,
    2012                 :            :                                    Node body,
    2013                 :            :                                    bool marked) const
    2014                 :            : {
    2015                 :          2 :   std::vector< Node > iplc;
    2016                 :          4 :   return mkForall( args, body, iplc, marked );
    2017                 :            : }
    2018                 :            : 
    2019                 :          5 : Node QuantifiersRewriter::mkForall(const std::vector<Node>& args,
    2020                 :            :                                    Node body,
    2021                 :            :                                    std::vector<Node>& iplc,
    2022                 :            :                                    bool marked) const
    2023                 :            : {
    2024         [ -  + ]:          5 :   if (args.empty())
    2025                 :            :   {
    2026                 :          0 :     return body;
    2027                 :            :   }
    2028                 :          5 :   NodeManager* nm = nodeManager();
    2029                 :         10 :   std::vector<Node> children;
    2030                 :          5 :   children.push_back(nm->mkNode(Kind::BOUND_VAR_LIST, args));
    2031                 :          5 :   children.push_back(body);
    2032         [ +  - ]:          5 :   if (marked)
    2033                 :            :   {
    2034                 :         10 :     Node avar = NodeManager::mkDummySkolem("id", nm->booleanType());
    2035                 :            :     QuantIdNumAttribute ida;
    2036                 :          5 :     avar.setAttribute(ida, 0);
    2037                 :          5 :     iplc.push_back(nm->mkNode(Kind::INST_ATTRIBUTE, avar));
    2038                 :            :   }
    2039         [ +  - ]:          5 :   if (!iplc.empty())
    2040                 :            :   {
    2041                 :          5 :     children.push_back(nm->mkNode(Kind::INST_PATTERN_LIST, iplc));
    2042                 :            :   }
    2043                 :          5 :   return nm->mkNode(Kind::FORALL, children);
    2044                 :            : }
    2045                 :            : 
    2046                 :            : //computes miniscoping, also eliminates variables that do not occur free in body
    2047                 :     310770 : Node QuantifiersRewriter::computeMiniscoping(Node q,
    2048                 :            :                                              QAttributes& qa,
    2049                 :            :                                              bool miniscopeConj,
    2050                 :            :                                              bool miniscopeFv) const
    2051                 :            : {
    2052                 :     310770 :   NodeManager* nm = nodeManager();
    2053                 :     932310 :   std::vector<Node> args(q[0].begin(), q[0].end());
    2054                 :     621540 :   Node body = q[1];
    2055                 :     310770 :   Kind k = body.getKind();
    2056 [ +  + ][ +  + ]:     310770 :   if (k == Kind::AND || k == Kind::ITE)
    2057                 :            :   {
    2058                 :       5374 :     bool doRewrite = miniscopeConj;
    2059         [ +  + ]:       5374 :     if (k == Kind::ITE)
    2060                 :            :     {
    2061                 :            :       // ITE miniscoping is only valid if condition contains no variables
    2062         [ +  + ]:        455 :       if (expr::hasSubterm(body[0], args))
    2063                 :            :       {
    2064                 :        437 :         doRewrite = false;
    2065                 :            :       }
    2066                 :            :     }
    2067                 :            :     // aggressive miniscoping implies that structural miniscoping should
    2068                 :            :     // be applied first
    2069         [ +  + ]:       5374 :     if (doRewrite)
    2070                 :            :     {
    2071                 :       2162 :       BoundVarManager* bvm = nm->getBoundVarManager();
    2072                 :            :       // Break apart the quantifed formula
    2073                 :            :       // forall x. P1 ^ ... ^ Pn ---> forall x. P1 ^ ... ^ forall x. Pn
    2074                 :       4324 :       NodeBuilder t(nm, k);
    2075                 :       4324 :       std::vector<Node> argsc;
    2076         [ +  + ]:      10387 :       for (size_t i = 0, nchild = body.getNumChildren(); i < nchild; i++)
    2077                 :            :       {
    2078         [ +  + ]:       8225 :         if (argsc.empty())
    2079                 :            :         {
    2080                 :            :           // If not done so, we must create fresh copy of args. This is to
    2081                 :            :           // ensure that quantified formulas do not reuse variables.
    2082         [ +  + ]:      15787 :           for (const Node& v : q[0])
    2083                 :            :           {
    2084                 :      21516 :             TypeNode vt = v.getType();
    2085                 :      32274 :             Node cacheVal = BoundVarManager::getCacheValue(q, v, i);
    2086                 :      32274 :             Node vv = bvm->mkBoundVar<QRewMiniscopeAttribute>(cacheVal, vt);
    2087                 :      10758 :             argsc.push_back(vv);
    2088                 :            :           }
    2089                 :            :         }
    2090                 :      16450 :         Node b = body[i];
    2091                 :            :         Node bodyc =
    2092                 :      16450 :             b.substitute(args.begin(), args.end(), argsc.begin(), argsc.end());
    2093         [ +  + ]:       8225 :         if (b == bodyc)
    2094                 :            :         {
    2095                 :            :           // Did not contain variables in args, thus it is ground. Since we did
    2096                 :            :           // not use them, we keep the variables argsc for the next child.
    2097                 :       3362 :           t << b;
    2098                 :            :         }
    2099                 :            :         else
    2100                 :            :         {
    2101                 :            :           // make the miniscoped quantified formula
    2102                 :       9726 :           Node cbvl = nm->mkNode(Kind::BOUND_VAR_LIST, argsc);
    2103                 :      14589 :           Node qq = nm->mkNode(Kind::FORALL, cbvl, bodyc);
    2104                 :       4863 :           t << qq;
    2105                 :            :           // We used argsc, clear so we will construct a fresh copy above.
    2106                 :       4863 :           argsc.clear();
    2107                 :            :         }
    2108                 :            :       }
    2109                 :       4324 :       Node retVal = t;
    2110                 :       2162 :       return retVal;
    2111                 :       3212 :     }
    2112                 :            :   }
    2113         [ +  + ]:     305396 :   else if (body.getKind() == Kind::OR)
    2114                 :            :   {
    2115         [ +  + ]:     137791 :     if (miniscopeFv)
    2116                 :            :     {
    2117                 :            :       //splitting subsumes free variable miniscoping, apply it with higher priority
    2118                 :     131399 :       Node ret = computeSplit(args, body, qa);
    2119         [ +  + ]:     131399 :       if (!ret.isNull())
    2120                 :            :       {
    2121                 :       2247 :         return ret;
    2122                 :            :       }
    2123                 :            :     }
    2124                 :            :   }
    2125         [ +  + ]:     167605 :   else if (body.getKind() == Kind::NOT)
    2126                 :            :   {
    2127 [ -  + ][ -  + ]:      40375 :     Assert(isLiteral(body[0]));
                 [ -  - ]
    2128                 :            :   }
    2129                 :            :   //remove variables that don't occur
    2130                 :     306361 :   std::vector< Node > activeArgs;
    2131                 :     306361 :   computeArgVec2( args, activeArgs, body, qa.d_ipl );
    2132                 :     306361 :   return mkForAll( activeArgs, body, qa );
    2133                 :            : }
    2134                 :            : 
    2135                 :        346 : Node QuantifiersRewriter::computeAggressiveMiniscoping(std::vector<Node>& args,
    2136                 :            :                                                        Node body) const
    2137                 :            : {
    2138                 :        692 :   std::map<Node, std::vector<Node> > varLits;
    2139                 :        692 :   std::map<Node, std::vector<Node> > litVars;
    2140         [ +  + ]:        346 :   if (body.getKind() == Kind::OR)
    2141                 :            :   {
    2142         [ +  - ]:        100 :     Trace("ag-miniscope") << "compute aggressive miniscoping on " << body << std::endl;
    2143         [ +  + ]:        312 :     for (size_t i = 0; i < body.getNumChildren(); i++) {
    2144                 :        212 :       std::vector<Node> activeArgs;
    2145                 :        212 :       computeArgVec(args, activeArgs, body[i]);
    2146         [ +  + ]:        476 :       for (unsigned j = 0; j < activeArgs.size(); j++) {
    2147                 :        264 :         varLits[activeArgs[j]].push_back(body[i]);
    2148                 :            :       }
    2149                 :        212 :       std::vector<Node>& lit_body_i = litVars[body[i]];
    2150                 :        212 :       std::vector<Node>::iterator lit_body_i_begin = lit_body_i.begin();
    2151                 :        212 :       std::vector<Node>::const_iterator active_begin = activeArgs.begin();
    2152                 :        212 :       std::vector<Node>::const_iterator active_end = activeArgs.end();
    2153                 :        212 :       lit_body_i.insert(lit_body_i_begin, active_begin, active_end);
    2154                 :            :     }
    2155                 :            :     //find the variable in the least number of literals
    2156                 :        100 :     Node bestVar;
    2157         [ +  + ]:        252 :     for( std::map< Node, std::vector<Node> >::iterator it = varLits.begin(); it != varLits.end(); ++it ){
    2158 [ +  + ][ +  + ]:        152 :       if( bestVar.isNull() || varLits[bestVar].size()>it->second.size() ){
                 [ +  + ]
    2159                 :        124 :         bestVar = it->first;
    2160                 :            :       }
    2161                 :            :     }
    2162         [ +  - ]:        100 :     Trace("ag-miniscope-debug") << "Best variable " << bestVar << " occurs in " << varLits[bestVar].size() << "/ " << body.getNumChildren() << " literals." << std::endl;
    2163 [ +  - ][ +  + ]:        100 :     if( !bestVar.isNull() && varLits[bestVar].size()<body.getNumChildren() ){
                 [ +  + ]
    2164                 :            :       //we can miniscope
    2165         [ +  - ]:         26 :       Trace("ag-miniscope") << "Miniscope on " << bestVar << std::endl;
    2166                 :            :       //make the bodies
    2167                 :         52 :       std::vector<Node> qlit1;
    2168                 :         26 :       qlit1.insert( qlit1.begin(), varLits[bestVar].begin(), varLits[bestVar].end() );
    2169                 :         52 :       std::vector<Node> qlitt;
    2170                 :            :       //for all literals not containing bestVar
    2171         [ +  + ]:         90 :       for( size_t i=0; i<body.getNumChildren(); i++ ){
    2172         [ +  + ]:         64 :         if( std::find( qlit1.begin(), qlit1.end(), body[i] )==qlit1.end() ){
    2173                 :         38 :           qlitt.push_back( body[i] );
    2174                 :            :         }
    2175                 :            :       }
    2176                 :            :       //make the variable lists
    2177                 :         52 :       std::vector<Node> qvl1;
    2178                 :         52 :       std::vector<Node> qvl2;
    2179                 :         52 :       std::vector<Node> qvsh;
    2180         [ +  + ]:        104 :       for( unsigned i=0; i<args.size(); i++ ){
    2181                 :         78 :         bool found1 = false;
    2182                 :         78 :         bool found2 = false;
    2183         [ +  + ]:        168 :         for( size_t j=0; j<varLits[args[i]].size(); j++ ){
    2184 [ +  + ][ +  + ]:        116 :           if( !found1 && std::find( qlit1.begin(), qlit1.end(), varLits[args[i]][j] )!=qlit1.end() ){
                 [ +  + ]
    2185                 :         52 :             found1 = true;
    2186 [ +  + ][ +  - ]:         64 :           }else if( !found2 && std::find( qlitt.begin(), qlitt.end(), varLits[args[i]][j] )!=qlitt.end() ){
                 [ +  + ]
    2187                 :         52 :             found2 = true;
    2188                 :            :           }
    2189 [ +  + ][ +  + ]:        116 :           if( found1 && found2 ){
    2190                 :         26 :             break;
    2191                 :            :           }
    2192                 :            :         }
    2193         [ +  + ]:         78 :         if( found1 ){
    2194         [ +  + ]:         52 :           if( found2 ){
    2195                 :         26 :             qvsh.push_back( args[i] );
    2196                 :            :           }else{
    2197                 :         26 :             qvl1.push_back( args[i] );
    2198                 :            :           }
    2199                 :            :         }else{
    2200 [ -  + ][ -  + ]:         26 :           Assert(found2);
                 [ -  - ]
    2201                 :         26 :           qvl2.push_back( args[i] );
    2202                 :            :         }
    2203                 :            :       }
    2204 [ -  + ][ -  + ]:         26 :       Assert(!qvl1.empty());
                 [ -  - ]
    2205                 :            :       //check for literals that only contain shared variables
    2206                 :         52 :       std::vector<Node> qlitsh;
    2207                 :         52 :       std::vector<Node> qlit2;
    2208         [ +  + ]:         64 :       for( size_t i=0; i<qlitt.size(); i++ ){
    2209                 :         38 :         bool hasVar2 = false;
    2210         [ +  + ]:         52 :         for( size_t j=0; j<litVars[qlitt[i]].size(); j++ ){
    2211         [ +  + ]:         40 :           if( std::find( qvl2.begin(), qvl2.end(), litVars[qlitt[i]][j] )!=qvl2.end() ){
    2212                 :         26 :             hasVar2 = true;
    2213                 :         26 :             break;
    2214                 :            :           }
    2215                 :            :         }
    2216         [ +  + ]:         38 :         if( hasVar2 ){
    2217                 :         26 :           qlit2.push_back( qlitt[i] );
    2218                 :            :         }else{
    2219                 :         12 :           qlitsh.push_back( qlitt[i] );
    2220                 :            :         }
    2221                 :            :       }
    2222                 :         26 :       varLits.clear();
    2223                 :         26 :       litVars.clear();
    2224         [ +  - ]:         26 :       Trace("ag-miniscope-debug") << "Split into literals : " << qlit1.size() << " / " << qlit2.size() << " / " << qlitsh.size();
    2225         [ +  - ]:         26 :       Trace("ag-miniscope-debug") << ", variables : " << qvl1.size() << " / " << qvl2.size() << " / " << qvsh.size() << std::endl;
    2226                 :            :       Node n1 =
    2227         [ +  - ]:         52 :           qlit1.size() == 1 ? qlit1[0] : nodeManager()->mkNode(Kind::OR, qlit1);
    2228                 :         26 :       n1 = computeAggressiveMiniscoping( qvl1, n1 );
    2229                 :         26 :       qlitsh.push_back( n1 );
    2230         [ +  + ]:         26 :       if( !qlit2.empty() ){
    2231                 :         16 :         Node n2 = qlit2.size() == 1 ? qlit2[0]
    2232         [ +  + ]:         30 :                                     : nodeManager()->mkNode(Kind::OR, qlit2);
    2233                 :         14 :         n2 = computeAggressiveMiniscoping( qvl2, n2 );
    2234                 :         14 :         qlitsh.push_back( n2 );
    2235                 :            :       }
    2236                 :         52 :       Node n = nodeManager()->mkNode(Kind::OR, qlitsh);
    2237         [ +  - ]:         26 :       if( !qvsh.empty() ){
    2238                 :         26 :         Node bvl = nodeManager()->mkNode(Kind::BOUND_VAR_LIST, qvsh);
    2239                 :         26 :         n = nodeManager()->mkNode(Kind::FORALL, bvl, n);
    2240                 :            :       }
    2241         [ +  - ]:         26 :       Trace("ag-miniscope") << "Return " << n << " for " << body << std::endl;
    2242                 :         26 :       return n;
    2243                 :            :     }
    2244                 :            :   }
    2245                 :        320 :   QAttributes qa;
    2246                 :        320 :   return mkForAll( args, body, qa );
    2247                 :            : }
    2248                 :            : 
    2249                 :          3 : bool QuantifiersRewriter::isStandard(const Node& q, const Options& opts)
    2250                 :            : {
    2251                 :          6 :   QAttributes qa;
    2252                 :          3 :   QuantAttributes::computeQuantAttributes(q, qa);
    2253                 :          6 :   return isStandard(qa, opts);
    2254                 :            : }
    2255                 :            : 
    2256                 :    2851680 : bool QuantifiersRewriter::isStandard(QAttributes& qa, const Options& opts)
    2257                 :            : {
    2258                 :    2851680 :   bool is_strict_trigger =
    2259                 :    2851680 :       qa.d_hasPattern
    2260 [ +  + ][ +  + ]:    2851680 :       && opts.quantifiers.userPatternsQuant == options::UserPatMode::STRICT;
    2261 [ +  + ][ +  - ]:    2851680 :   return qa.isStandard() && !is_strict_trigger;
    2262                 :            : }
    2263                 :            : 
    2264                 :       3865 : Node QuantifiersRewriter::computeRewriteBody(const Node& n,
    2265                 :            :                                              TConvProofGenerator* pg) const
    2266                 :            : {
    2267 [ -  + ][ -  + ]:       3865 :   Assert(n.getKind() == Kind::FORALL);
                 [ -  - ]
    2268                 :       7730 :   QAttributes qa;
    2269                 :       3865 :   QuantAttributes::computeQuantAttributes(n, qa);
    2270                 :      11595 :   std::vector<Node> args(n[0].begin(), n[0].end());
    2271                 :       7730 :   Node body = computeProcessTerms(n, args, n[1], qa, pg);
    2272         [ +  + ]:       3865 :   if (body != n[1])
    2273                 :            :   {
    2274                 :       3018 :     std::vector<Node> children;
    2275                 :       1509 :     children.push_back(n[0]);
    2276                 :       1509 :     children.push_back(body);
    2277         [ +  + ]:       1509 :     if (n.getNumChildren() == 3)
    2278                 :            :     {
    2279                 :         18 :       children.push_back(n[2]);
    2280                 :            :     }
    2281                 :       1509 :     return d_nm->mkNode(Kind::FORALL, children);
    2282                 :            :   }
    2283                 :       2356 :   return n;
    2284                 :            : }
    2285                 :            : 
    2286                 :    2851680 : bool QuantifiersRewriter::doOperation(Node q,
    2287                 :            :                                       RewriteStep computeOption,
    2288                 :            :                                       QAttributes& qa) const
    2289                 :            : {
    2290                 :    2851680 :   bool is_strict_trigger =
    2291                 :    2851680 :       qa.d_hasPattern
    2292 [ +  + ][ +  + ]:    2851680 :       && d_opts.quantifiers.userPatternsQuant == options::UserPatMode::STRICT;
    2293                 :    2851680 :   bool is_std = isStandard(qa, d_opts);
    2294         [ +  + ]:    2851680 :   if (computeOption == COMPUTE_ELIM_SYMBOLS)
    2295                 :            :   {
    2296                 :     399275 :     return true;
    2297                 :            :   }
    2298         [ +  + ]:    2452400 :   else if (computeOption == COMPUTE_MINISCOPING
    2299         [ +  + ]:    2088410 :            || computeOption == COMPUTE_AGGRESSIVE_MINISCOPING)
    2300                 :            :   {
    2301                 :            :     // in the rare case the body is ground, we always eliminate unless it
    2302                 :            :     // is truly a non-standard quantified formula (e.g. one for QE).
    2303         [ +  + ]:     722563 :     if (!expr::hasBoundVar(q[1]))
    2304                 :            :     {
    2305                 :            :       // This returns true if q is a non-standard quantified formula. Note that
    2306                 :            :       // is_std is additionally true if user-pat is strict and q has user
    2307                 :            :       // patterns.
    2308                 :       3198 :       return qa.isStandard();
    2309                 :            :     }
    2310         [ +  + ]:     719365 :     if (!is_std)
    2311                 :            :     {
    2312                 :      30560 :       return false;
    2313                 :            :     }
    2314                 :            :     // do not miniscope if we have user patterns unless option is set
    2315 [ +  - ][ +  + ]:     688805 :     if (!d_opts.quantifiers.miniscopeQuantUser && qa.d_hasPattern)
    2316                 :            :     {
    2317                 :      73916 :       return false;
    2318                 :            :     }
    2319         [ +  + ]:     614889 :     if (computeOption == COMPUTE_AGGRESSIVE_MINISCOPING)
    2320                 :            :     {
    2321                 :     305007 :       return d_opts.quantifiers.miniscopeQuant
    2322                 :     305007 :              == options::MiniscopeQuantMode::AGG;
    2323                 :            :     }
    2324                 :     309882 :     return true;
    2325                 :            :   }
    2326         [ +  + ]:    1729840 :   else if (computeOption == COMPUTE_EXT_REWRITE)
    2327                 :            :   {
    2328                 :     336806 :     return d_opts.quantifiers.extRewriteQuant;
    2329                 :            :   }
    2330         [ +  + ]:    1393030 :   else if (computeOption == COMPUTE_PROCESS_TERMS)
    2331                 :            :   {
    2332                 :     358553 :     return true;
    2333                 :            :   }
    2334         [ +  + ]:    1034480 :   else if (computeOption == COMPUTE_COND_SPLIT)
    2335                 :            :   {
    2336                 :     337462 :     return (d_opts.quantifiers.iteDtTesterSplitQuant
    2337         [ +  - ]:     332133 :             || d_opts.quantifiers.condVarSplitQuant
    2338                 :            :                    != options::CondVarSplitQuantMode::OFF)
    2339 [ +  + ][ +  + ]:     669595 :            && !is_strict_trigger;
    2340                 :            :   }
    2341         [ +  + ]:     697016 :   else if (computeOption == COMPUTE_PRENEX)
    2342                 :            :   {
    2343                 :            :     // do not prenex to pull variables into those with user patterns
    2344 [ +  + ][ +  + ]:     349728 :     if (!d_opts.quantifiers.prenexQuantUser && qa.d_hasPattern)
    2345                 :            :     {
    2346                 :      36959 :       return false;
    2347                 :            :     }
    2348         [ +  + ]:     312769 :     if (qa.d_hasPool)
    2349                 :            :     {
    2350                 :        328 :       return false;
    2351                 :            :     }
    2352                 :     312441 :     return d_opts.quantifiers.prenexQuant != options::PrenexQuantMode::NONE
    2353         [ +  + ]:     310688 :            && d_opts.quantifiers.miniscopeQuant
    2354                 :            :                   != options::MiniscopeQuantMode::AGG
    2355 [ +  + ][ +  + ]:     623129 :            && is_std;
    2356                 :            :   }
    2357         [ +  - ]:     347288 :   else if (computeOption == COMPUTE_VAR_ELIMINATION)
    2358                 :            :   {
    2359                 :     347288 :     return (d_opts.quantifiers.varElimQuant
    2360         [ +  - ]:        270 :             || d_opts.quantifiers.dtVarExpandQuant)
    2361 [ +  + ][ +  + ]:     347558 :            && is_std && !is_strict_trigger;
                 [ +  - ]
    2362                 :            :   }
    2363                 :            :   else
    2364                 :            :   {
    2365                 :          0 :     return false;
    2366                 :            :   }
    2367                 :            : }
    2368                 :            : 
    2369                 :            : //general method for computing various rewrites
    2370                 :    2031070 : Node QuantifiersRewriter::computeOperation(Node f,
    2371                 :            :                                            RewriteStep computeOption,
    2372                 :            :                                            QAttributes& qa) const
    2373                 :            : {
    2374         [ +  - ]:    2031070 :   Trace("quantifiers-rewrite-debug") << "Compute operation " << computeOption << " on " << f << " " << qa.d_qid_num << std::endl;
    2375         [ +  + ]:    2031070 :   if (computeOption == COMPUTE_MINISCOPING)
    2376                 :            :   {
    2377         [ +  + ]:     310434 :     if (d_opts.quantifiers.prenexQuant == options::PrenexQuantMode::NORMAL)
    2378                 :            :     {
    2379         [ +  + ]:         35 :       if( !qa.d_qid_num.isNull() ){
    2380                 :            :         //already processed this, return self
    2381                 :         33 :         return f;
    2382                 :            :       }
    2383                 :            :     }
    2384                 :     310401 :     bool miniscopeConj = doMiniscopeConj(d_opts);
    2385                 :     310401 :     bool miniscopeFv = doMiniscopeFv(d_opts);
    2386                 :            :     //return directly
    2387                 :     310401 :     return computeMiniscoping(f, qa, miniscopeConj, miniscopeFv);
    2388                 :            :   }
    2389                 :    5161900 :   std::vector<Node> args(f[0].begin(), f[0].end());
    2390                 :    3441270 :   Node n = f[1];
    2391         [ +  + ]:    1720630 :   if (computeOption == COMPUTE_ELIM_SYMBOLS)
    2392                 :            :   {
    2393                 :            :     // relies on external utility
    2394                 :     399275 :     n = booleans::TheoryBoolRewriter::computeNnfNorm(nodeManager(), n);
    2395                 :            :   }
    2396         [ +  + ]:    1321360 :   else if (computeOption == COMPUTE_AGGRESSIVE_MINISCOPING)
    2397                 :            :   {
    2398                 :        306 :     return computeAggressiveMiniscoping( args, n );
    2399                 :            :   }
    2400         [ +  + ]:    1321050 :   else if (computeOption == COMPUTE_EXT_REWRITE)
    2401                 :            :   {
    2402                 :         28 :     return computeExtendedRewrite(f, qa);
    2403                 :            :   }
    2404         [ +  + ]:    1321020 :   else if (computeOption == COMPUTE_PROCESS_TERMS)
    2405                 :            :   {
    2406                 :     358553 :     n = computeProcessTerms(f, args, n, qa);
    2407                 :            :   }
    2408         [ +  + ]:     962472 :   else if (computeOption == COMPUTE_COND_SPLIT)
    2409                 :            :   {
    2410                 :     337418 :     n = computeCondSplit(n, args, qa);
    2411                 :            :   }
    2412         [ +  + ]:     625054 :   else if (computeOption == COMPUTE_PRENEX)
    2413                 :            :   {
    2414         [ +  + ]:     294366 :     if (d_opts.quantifiers.prenexQuant == options::PrenexQuantMode::NORMAL)
    2415                 :            :     {
    2416                 :            :       //will rewrite at preprocess time
    2417                 :         32 :       return f;
    2418                 :            :     }
    2419                 :            :     else
    2420                 :            :     {
    2421                 :     588668 :       std::vector<Node> argsSet, nargsSet;
    2422                 :     294334 :       n = computePrenex(f, n, argsSet, nargsSet, true, false);
    2423 [ -  + ][ -  + ]:     294334 :       Assert(nargsSet.empty());
                 [ -  - ]
    2424                 :     294334 :       args.insert(args.end(), argsSet.begin(), argsSet.end());
    2425                 :            :     }
    2426                 :            :   }
    2427         [ +  - ]:     330688 :   else if (computeOption == COMPUTE_VAR_ELIMINATION)
    2428                 :            :   {
    2429                 :     330688 :     n = computeVarElimination( n, args, qa );
    2430                 :            :   }
    2431         [ +  - ]:    1720270 :   Trace("quantifiers-rewrite-debug") << "Compute Operation: return " << n << ", " << args.size() << std::endl;
    2432                 :    1720270 :   if( f[1]==n && args.size()==f[0].getNumChildren() ){
    2433                 :    1663240 :     return f;
    2434                 :            :   }else{
    2435         [ +  + ]:      57028 :     if( args.empty() ){
    2436                 :       2676 :       return n;
    2437                 :            :     }else{
    2438                 :     108704 :       std::vector< Node > children;
    2439                 :      54352 :       children.push_back(nodeManager()->mkNode(Kind::BOUND_VAR_LIST, args));
    2440                 :      54352 :       children.push_back( n );
    2441 [ +  + ][ +  + ]:      54352 :       if( !qa.d_ipl.isNull() && args.size()==f[0].getNumChildren() ){
         [ +  + ][ +  + ]
                 [ -  - ]
    2442                 :       5736 :         children.push_back( qa.d_ipl );
    2443                 :            :       }
    2444                 :      54352 :       return nodeManager()->mkNode(Kind::FORALL, children);
    2445                 :            :     }
    2446                 :            :   }
    2447                 :            : }
    2448                 :     647800 : bool QuantifiersRewriter::doMiniscopeConj(const Options& opts)
    2449                 :            : {
    2450                 :     647800 :   options::MiniscopeQuantMode mqm = opts.quantifiers.miniscopeQuant;
    2451                 :            :   return mqm == options::MiniscopeQuantMode::CONJ_AND_FV
    2452         [ +  - ]:      28769 :          || mqm == options::MiniscopeQuantMode::CONJ
    2453 [ +  + ][ +  + ]:     676569 :          || mqm == options::MiniscopeQuantMode::AGG;
    2454                 :            : }
    2455                 :            : 
    2456                 :     310401 : bool QuantifiersRewriter::doMiniscopeFv(const Options& opts)
    2457                 :            : {
    2458                 :     310401 :   options::MiniscopeQuantMode mqm = opts.quantifiers.miniscopeQuant;
    2459                 :            :   return mqm == options::MiniscopeQuantMode::CONJ_AND_FV
    2460         [ +  + ]:      12373 :          || mqm == options::MiniscopeQuantMode::FV
    2461 [ +  + ][ +  + ]:     322774 :          || mqm == options::MiniscopeQuantMode::AGG;
    2462                 :            : }
    2463                 :            : 
    2464                 :          0 : bool QuantifiersRewriter::isPrenexNormalForm( Node n ) {
    2465         [ -  - ]:          0 :   if (n.getKind() == Kind::FORALL)
    2466                 :            :   {
    2467                 :          0 :     return n[1].getKind() != Kind::FORALL && isPrenexNormalForm(n[1]);
    2468                 :            :   }
    2469         [ -  - ]:          0 :   else if (n.getKind() == Kind::NOT)
    2470                 :            :   {
    2471                 :          0 :     return n[0].getKind() != Kind::NOT && isPrenexNormalForm(n[0]);
    2472                 :            :   }
    2473                 :            :   else
    2474                 :            :   {
    2475                 :          0 :     return !expr::hasClosure(n);
    2476                 :            :   }
    2477                 :            : }
    2478                 :            : 
    2479                 :            : }  // namespace quantifiers
    2480                 :            : }  // namespace theory
    2481                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14