GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/quantifiers_rewriter.cpp Lines: 915 1187 77.1 %
Date: 2021-09-07 Branches: 2059 5059 40.7 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Morgan Deters, Haniel Barbosa
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 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/bound_var_manager.h"
19
#include "expr/dtype.h"
20
#include "expr/dtype_cons.h"
21
#include "expr/node_algorithm.h"
22
#include "expr/skolem_manager.h"
23
#include "options/quantifiers_options.h"
24
#include "theory/arith/arith_msum.h"
25
#include "theory/datatypes/theory_datatypes_utils.h"
26
#include "theory/quantifiers/bv_inverter.h"
27
#include "theory/quantifiers/ematching/trigger.h"
28
#include "theory/quantifiers/extended_rewrite.h"
29
#include "theory/quantifiers/quantifiers_attributes.h"
30
#include "theory/quantifiers/skolemize.h"
31
#include "theory/quantifiers/term_database.h"
32
#include "theory/quantifiers/term_util.h"
33
#include "theory/rewriter.h"
34
#include "theory/strings/theory_strings_utils.h"
35
#include "util/rational.h"
36
37
using namespace std;
38
using namespace cvc5::kind;
39
using namespace cvc5::context;
40
41
namespace cvc5 {
42
namespace theory {
43
namespace quantifiers {
44
45
/**
46
 * Attributes used for constructing bound variables in a canonical way. These
47
 * are attributes that map to bound variable, introduced for the following
48
 * purposes:
49
 * - QRewPrenexAttribute: cached on (v, body) where we are prenexing bound
50
 * variable v in a nested quantified formula within the given body.
51
 * - QRewMiniscopeAttribute: cached on (v, q, i) where q is being miniscoped
52
 * for F_i in its body (and F_1 ... F_n), and v is one of the bound variables
53
 * that q binds.
54
 * - QRewDtExpandAttribute: cached on (F, lit, a) where lit is the tested
55
 * literal used for expanding a quantified datatype variable in quantified
56
 * formula with body F, and a is the rational corresponding to the argument
57
 * position of the variable, e.g. lit is ((_ is C) x) and x is
58
 * replaced by (C y1 ... yn), where the argument position of yi is i.
59
 */
60
struct QRewPrenexAttributeId
61
{
62
};
63
typedef expr::Attribute<QRewPrenexAttributeId, Node> QRewPrenexAttribute;
64
struct QRewMiniscopeAttributeId
65
{
66
};
67
typedef expr::Attribute<QRewMiniscopeAttributeId, Node> QRewMiniscopeAttribute;
68
struct QRewDtExpandAttributeId
69
{
70
};
71
typedef expr::Attribute<QRewDtExpandAttributeId, Node> QRewDtExpandAttribute;
72
73
std::ostream& operator<<(std::ostream& out, RewriteStep s)
74
{
75
  switch (s)
76
  {
77
    case COMPUTE_ELIM_SYMBOLS: out << "COMPUTE_ELIM_SYMBOLS"; break;
78
    case COMPUTE_MINISCOPING: out << "COMPUTE_MINISCOPING"; break;
79
    case COMPUTE_AGGRESSIVE_MINISCOPING:
80
      out << "COMPUTE_AGGRESSIVE_MINISCOPING";
81
      break;
82
    case COMPUTE_EXT_REWRITE: out << "COMPUTE_EXT_REWRITE"; break;
83
    case COMPUTE_PROCESS_TERMS: out << "COMPUTE_PROCESS_TERMS"; break;
84
    case COMPUTE_PRENEX: out << "COMPUTE_PRENEX"; break;
85
    case COMPUTE_VAR_ELIMINATION: out << "COMPUTE_VAR_ELIMINATION"; break;
86
    case COMPUTE_COND_SPLIT: out << "COMPUTE_COND_SPLIT"; break;
87
    default: out << "UnknownRewriteStep"; break;
88
  }
89
  return out;
90
}
91
92
14995
bool QuantifiersRewriter::isLiteral( Node n ){
93
14995
  switch( n.getKind() ){
94
  case NOT:
95
    return n[0].getKind()!=NOT && isLiteral( n[0] );
96
    break;
97
  case OR:
98
  case AND:
99
  case IMPLIES:
100
  case XOR:
101
  case ITE:
102
    return false;
103
    break;
104
8993
  case EQUAL:
105
    //for boolean terms
106
8993
    return !n[0].getType().isBoolean();
107
    break;
108
6002
  default:
109
6002
    break;
110
  }
111
6002
  return true;
112
}
113
114
void QuantifiersRewriter::addNodeToOrBuilder(Node n, NodeBuilder& t)
115
{
116
  if( n.getKind()==OR ){
117
    for( int i=0; i<(int)n.getNumChildren(); i++ ){
118
      t << n[i];
119
    }
120
  }else{
121
    t << n;
122
  }
123
}
124
125
4912942
void QuantifiersRewriter::computeArgs(const std::vector<Node>& args,
126
                                      std::map<Node, bool>& activeMap,
127
                                      Node n,
128
                                      std::map<Node, bool>& visited)
129
{
130
4912942
  if( visited.find( n )==visited.end() ){
131
3522251
    visited[n] = true;
132
3522251
    if( n.getKind()==BOUND_VARIABLE ){
133
591431
      if( std::find( args.begin(), args.end(), n )!=args.end() ){
134
485388
        activeMap[ n ] = true;
135
      }
136
    }else{
137
2930820
      if (n.hasOperator())
138
      {
139
1539783
        computeArgs(args, activeMap, n.getOperator(), visited);
140
      }
141
6015206
      for( int i=0; i<(int)n.getNumChildren(); i++ ){
142
3084386
        computeArgs( args, activeMap, n[i], visited );
143
      }
144
    }
145
  }
146
4912942
}
147
148
151653
void QuantifiersRewriter::computeArgVec(const std::vector<Node>& args,
149
                                        std::vector<Node>& activeArgs,
150
                                        Node n)
151
{
152
151653
  Assert(activeArgs.empty());
153
303306
  std::map< Node, bool > activeMap;
154
303306
  std::map< Node, bool > visited;
155
151653
  computeArgs( args, activeMap, n, visited );
156
151653
  if( !activeMap.empty() ){
157
2426983
    for( unsigned i=0; i<args.size(); i++ ){
158
2276973
      if( activeMap.find( args[i] )!=activeMap.end() ){
159
347422
        activeArgs.push_back( args[i] );
160
      }
161
    }
162
  }
163
151653
}
164
165
68672
void QuantifiersRewriter::computeArgVec2(const std::vector<Node>& args,
166
                                         std::vector<Node>& activeArgs,
167
                                         Node n,
168
                                         Node ipl)
169
{
170
68672
  Assert(activeArgs.empty());
171
137344
  std::map< Node, bool > activeMap;
172
137344
  std::map< Node, bool > visited;
173
68672
  computeArgs( args, activeMap, n, visited );
174
68672
  if( !activeMap.empty() ){
175
    //collect variables in inst pattern list only if we cannot eliminate quantifier
176
68448
    computeArgs( args, activeMap, ipl, visited );
177
207431
    for( unsigned i=0; i<args.size(); i++ ){
178
138983
      if( activeMap.find( args[i] )!=activeMap.end() ){
179
137966
        activeArgs.push_back( args[i] );
180
      }
181
    }
182
  }
183
68672
}
184
185
135369
RewriteResponse QuantifiersRewriter::preRewrite(TNode in) {
186
135369
  if( in.getKind()==kind::EXISTS || in.getKind()==kind::FORALL ){
187
79498
    Trace("quantifiers-rewrite-debug") << "pre-rewriting " << in << std::endl;
188
157207
    std::vector< Node > args;
189
157207
    Node body = in;
190
79498
    bool doRewrite = false;
191
93820
    while( body.getNumChildren()==2 && body.getKind()==body[1].getKind() ){
192
14381
      for( unsigned i=0; i<body[0].getNumChildren(); i++ ){
193
7220
        args.push_back( body[0][i] );
194
      }
195
7161
      body = body[1];
196
7161
      doRewrite = true;
197
    }
198
79498
    if( doRewrite ){
199
3578
      std::vector< Node > children;
200
3618
      for( unsigned i=0; i<body[0].getNumChildren(); i++ ){
201
1829
        args.push_back( body[0][i] );
202
      }
203
1789
      children.push_back( NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST,args) );
204
1789
      children.push_back( body[1] );
205
1789
      if( body.getNumChildren()==3 ){
206
48
        children.push_back( body[2] );
207
      }
208
3578
      Node n = NodeManager::currentNM()->mkNode( in.getKind(), children );
209
1789
      if( in!=n ){
210
1789
        Trace("quantifiers-pre-rewrite") << "*** pre-rewrite " << in << std::endl;
211
1789
        Trace("quantifiers-pre-rewrite") << " to " << std::endl;
212
1789
        Trace("quantifiers-pre-rewrite") << n << std::endl;
213
      }
214
1789
      return RewriteResponse(REWRITE_DONE, n);
215
    }
216
  }
217
133580
  return RewriteResponse(REWRITE_DONE, in);
218
}
219
220
247506
RewriteResponse QuantifiersRewriter::postRewrite(TNode in) {
221
247506
  Trace("quantifiers-rewrite-debug") << "post-rewriting " << in << std::endl;
222
247506
  RewriteStatus status = REWRITE_DONE;
223
495012
  Node ret = in;
224
247506
  RewriteStep rew_op = COMPUTE_LAST;
225
  //get the body
226
247506
  if( in.getKind()==EXISTS ){
227
5514
    std::vector< Node > children;
228
2757
    children.push_back( in[0] );
229
2757
    children.push_back( in[1].negate() );
230
2757
    if( in.getNumChildren()==3 ){
231
43
      children.push_back( in[2] );
232
    }
233
2757
    ret = NodeManager::currentNM()->mkNode( FORALL, children );
234
2757
    ret = ret.negate();
235
2757
    status = REWRITE_AGAIN_FULL;
236
244749
  }else if( in.getKind()==FORALL ){
237
133295
    if( in[1].isConst() && in.getNumChildren()==2 ){
238
855
      return RewriteResponse( status, in[1] );
239
    }else{
240
      //compute attributes
241
264880
      QAttributes qa;
242
132440
      QuantAttributes::computeQuantAttributes( in, qa );
243
1065301
      for (unsigned i = 0; i < COMPUTE_LAST; ++i)
244
      {
245
951321
        RewriteStep op = static_cast<RewriteStep>(i);
246
951321
        if( doOperation( in, op, qa ) ){
247
702933
          ret = computeOperation( in, op, qa );
248
702933
          if( ret!=in ){
249
18460
            rew_op = op;
250
18460
            status = REWRITE_AGAIN_FULL;
251
18460
            break;
252
          }
253
        }
254
      }
255
    }
256
  }
257
  //print if changed
258
246651
  if( in!=ret ){
259
21217
    Trace("quantifiers-rewrite") << "*** rewrite (op=" << rew_op << ") " << in << std::endl;
260
21217
    Trace("quantifiers-rewrite") << " to " << std::endl;
261
21217
    Trace("quantifiers-rewrite") << ret << std::endl;
262
  }
263
246651
  return RewriteResponse( status, ret );
264
}
265
266
797015
bool QuantifiersRewriter::addCheckElimChild( std::vector< Node >& children, Node c, Kind k, std::map< Node, bool >& lit_pol, bool& childrenChanged ){
267
797015
  if( ( k==OR || k==AND ) && options::elimTautQuant() ){
268
1272696
    Node lit = c.getKind()==NOT ? c[0] : c;
269
636459
    bool pol = c.getKind()!=NOT;
270
636459
    std::map< Node, bool >::iterator it = lit_pol.find( lit );
271
636459
    if( it==lit_pol.end() ){
272
635545
      lit_pol[lit] = pol;
273
635545
      children.push_back( c );
274
    }else{
275
914
      childrenChanged = true;
276
914
      if( it->second!=pol ){
277
222
        return false;
278
      }
279
    }
280
  }else{
281
160556
    children.push_back( c );
282
  }
283
796793
  return true;
284
}
285
286
// eliminates IMPLIES/XOR, removes duplicates/infers tautologies of AND/OR, and computes NNF
287
915136
Node QuantifiersRewriter::computeElimSymbols( Node body ) {
288
915136
  Kind ok = body.getKind();
289
915136
  Kind k = ok;
290
915136
  bool negAllCh = false;
291
915136
  bool negCh1 = false;
292
915136
  if( ok==IMPLIES ){
293
11821
    k = OR;
294
11821
    negCh1 = true;
295
903315
  }else if( ok==XOR ){
296
767
    k = EQUAL;
297
767
    negCh1 = true;
298
902548
  }else if( ok==NOT ){
299
367574
    if( body[0].getKind()==NOT ){
300
      return computeElimSymbols( body[0][0] );
301
367574
    }else if( body[0].getKind()==OR || body[0].getKind()==IMPLIES ){
302
1691
      k = AND;
303
1691
      negAllCh = true;
304
1691
      negCh1 = body[0].getKind()==IMPLIES;
305
1691
      body = body[0];
306
365883
    }else if( body[0].getKind()==AND ){
307
5653
      k = OR;
308
5653
      negAllCh = true;
309
5653
      body = body[0];
310
360230
    }else if( body[0].getKind()==XOR || ( body[0].getKind()==EQUAL && body[0][0].getType().isBoolean() ) ){
311
2732
      k = EQUAL;
312
2732
      negCh1 = ( body[0].getKind()==EQUAL );
313
2732
      body = body[0];
314
357498
    }else if( body[0].getKind()==ITE ){
315
87
      k = body[0].getKind();
316
87
      negAllCh = true;
317
87
      negCh1 = true;
318
87
      body = body[0];
319
    }else{
320
357411
      return body;
321
    }
322
534974
  }else if( ( ok!=EQUAL || !body[0].getType().isBoolean() ) && ok!=ITE && ok!=AND && ok!=OR ){
323
    //a literal
324
319542
    return body;
325
  }
326
238183
  bool childrenChanged = false;
327
476366
  std::vector< Node > children;
328
476366
  std::map< Node, bool > lit_pol;
329
1020657
  for( unsigned i=0; i<body.getNumChildren(); i++ ){
330
1565170
    Node c = computeElimSymbols( ( i==0 && negCh1 )!=negAllCh ? body[i].negate() : body[i] );
331
782696
    bool success = true;
332
782696
    if( c.getKind()==k && ( k==OR || k==AND ) ){
333
      //flatten
334
5564
      childrenChanged = true;
335
25446
      for( unsigned j=0; j<c.getNumChildren(); j++ ){
336
19883
        if( !addCheckElimChild( children, c[j], k, lit_pol, childrenChanged ) ){
337
1
          success = false;
338
1
          break;
339
        }
340
      }
341
    }else{
342
777132
      success = addCheckElimChild( children, c, k, lit_pol, childrenChanged );
343
    }
344
782696
    if( !success ){
345
      // tautology
346
222
      Assert(k == OR || k == AND);
347
222
      return NodeManager::currentNM()->mkConst( k==OR );
348
    }
349
782474
    childrenChanged = childrenChanged || c!=body[i];
350
  }
351
237961
  if( childrenChanged || k!=ok ){
352
26501
    return ( children.size()==1 && k!=NOT ) ? children[0] : NodeManager::currentNM()->mkNode( k, children );
353
  }else{
354
211460
    return body;
355
  }
356
}
357
358
void QuantifiersRewriter::computeDtTesterIteSplit( Node n, std::map< Node, Node >& pcons, std::map< Node, std::map< int, Node > >& ncons,
359
                                                   std::vector< Node >& conj ){
360
  if( n.getKind()==ITE && n[0].getKind()==APPLY_TESTER && n[1].getType().isBoolean() ){
361
    Trace("quantifiers-rewrite-ite-debug") << "Split tester condition : " << n << std::endl;
362
    Node x = n[0][0];
363
    std::map< Node, Node >::iterator itp = pcons.find( x );
364
    if( itp!=pcons.end() ){
365
      Trace("quantifiers-rewrite-ite-debug") << "...condition already set " << itp->second << std::endl;
366
      computeDtTesterIteSplit( n[ itp->second==n[0] ? 1 : 2 ], pcons, ncons, conj );
367
    }else{
368
      Node tester = n[0].getOperator();
369
      int index = datatypes::utils::indexOf(tester);
370
      std::map< int, Node >::iterator itn = ncons[x].find( index );
371
      if( itn!=ncons[x].end() ){
372
        Trace("quantifiers-rewrite-ite-debug") << "...condition negated " << itn->second << std::endl;
373
        computeDtTesterIteSplit( n[ 2 ], pcons, ncons, conj );
374
      }else{
375
        for( unsigned i=0; i<2; i++ ){
376
          if( i==0 ){
377
            pcons[x] = n[0];
378
          }else{
379
            pcons.erase( x );
380
            ncons[x][index] = n[0].negate();
381
          }
382
          computeDtTesterIteSplit( n[i+1], pcons, ncons, conj );
383
        }
384
        ncons[x].erase( index );
385
      }
386
    }
387
  }else{
388
    NodeManager* nm = NodeManager::currentNM();
389
    Trace("quantifiers-rewrite-ite-debug") << "Return value : " << n << std::endl;
390
    std::vector< Node > children;
391
    children.push_back( n );
392
    std::vector< Node > vars;
393
    //add all positive testers
394
    for( std::map< Node, Node >::iterator it = pcons.begin(); it != pcons.end(); ++it ){
395
      children.push_back( it->second.negate() );
396
      vars.push_back( it->first );
397
    }
398
    //add all negative testers
399
    for( std::map< Node, std::map< int, Node > >::iterator it = ncons.begin(); it != ncons.end(); ++it ){
400
      Node x = it->first;
401
      //only if we haven't settled on a positive tester
402
      if( std::find( vars.begin(), vars.end(), x )==vars.end() ){
403
        //check if we have exhausted all options but one
404
        const DType& dt = x.getType().getDType();
405
        std::vector< Node > nchildren;
406
        int pos_cons = -1;
407
        for( int i=0; i<(int)dt.getNumConstructors(); i++ ){
408
          std::map< int, Node >::iterator itt = it->second.find( i );
409
          if( itt==it->second.end() ){
410
            pos_cons = pos_cons==-1 ? i : -2;
411
          }else{
412
            nchildren.push_back( itt->second.negate() );
413
          }
414
        }
415
        if( pos_cons>=0 ){
416
          Node tester = dt[pos_cons].getTester();
417
          children.push_back(nm->mkNode(APPLY_TESTER, tester, x).negate());
418
        }else{
419
          children.insert( children.end(), nchildren.begin(), nchildren.end() );
420
        }
421
      }
422
    }
423
    //make condition/output pair
424
    Node c = children.size()==1 ? children[0] : NodeManager::currentNM()->mkNode( OR, children );
425
    conj.push_back( c );
426
  }
427
}
428
429
114275
Node QuantifiersRewriter::computeProcessTerms( Node body, std::vector< Node >& new_vars, std::vector< Node >& new_conds, Node q, QAttributes& qa ){
430
228550
  std::map< Node, Node > cache;
431
114275
  if( qa.isFunDef() ){
432
    Node h = QuantAttributes::getFunDefHead( q );
433
    Assert(!h.isNull());
434
    // if it is a function definition, rewrite the body independently
435
    Node fbody = QuantAttributes::getFunDefBody( q );
436
    Trace("quantifiers-rewrite-debug") << "Decompose " << h << " / " << fbody << " as function definition for " << q << "." << std::endl;
437
    if (!fbody.isNull())
438
    {
439
      Node r = computeProcessTerms2(fbody, cache, new_vars, new_conds);
440
      Assert(new_vars.size() == h.getNumChildren());
441
      return Rewriter::rewrite(NodeManager::currentNM()->mkNode(EQUAL, h, r));
442
    }
443
    // It can happen that we can't infer the shape of the function definition,
444
    // for example: forall xy. f( x, y ) = 1 + f( x, y ), this is rewritten to
445
    // forall xy. false.
446
  }
447
114275
  return computeProcessTerms2(body, cache, new_vars, new_conds);
448
}
449
450
2931431
Node QuantifiersRewriter::computeProcessTerms2(Node body,
451
                                               std::map<Node, Node>& cache,
452
                                               std::vector<Node>& new_vars,
453
                                               std::vector<Node>& new_conds)
454
{
455
2931431
  NodeManager* nm = NodeManager::currentNM();
456
5862862
  Trace("quantifiers-rewrite-term-debug2")
457
2931431
      << "computeProcessTerms " << body << std::endl;
458
2931431
  std::map< Node, Node >::iterator iti = cache.find( body );
459
2931431
  if( iti!=cache.end() ){
460
954301
    return iti->second;
461
  }
462
1977130
  bool changed = false;
463
3954260
  std::vector<Node> children;
464
4794286
  for (size_t i = 0; i < body.getNumChildren(); i++)
465
  {
466
    // do the recursive call on children
467
5634312
    Node nn = computeProcessTerms2(body[i], cache, new_vars, new_conds);
468
2817156
    children.push_back(nn);
469
2817156
    changed = changed || nn != body[i];
470
  }
471
472
  // make return value
473
3954260
  Node ret;
474
1977130
  if (changed)
475
  {
476
5153
    if (body.getMetaKind() == kind::metakind::PARAMETERIZED)
477
    {
478
194
      children.insert(children.begin(), body.getOperator());
479
    }
480
5153
    ret = nm->mkNode(body.getKind(), children);
481
  }
482
  else
483
  {
484
1971977
    ret = body;
485
  }
486
487
3954260
  Trace("quantifiers-rewrite-term-debug2")
488
1977130
      << "Returning " << ret << " for " << body << std::endl;
489
  // do context-independent rewriting
490
3954260
  if (ret.getKind() == EQUAL
491
1977130
      && options::iteLiftQuant() != options::IteLiftQuantMode::NONE)
492
  {
493
693832
    for (size_t i = 0; i < 2; i++)
494
    {
495
462949
      if (ret[i].getKind() == ITE)
496
      {
497
20989
        Node no = i == 0 ? ret[1] : ret[0];
498
10925
        if (no.getKind() != ITE)
499
        {
500
          bool doRewrite =
501
9593
              options::iteLiftQuant() == options::IteLiftQuantMode::ALL;
502
18325
          std::vector<Node> childrenIte;
503
9593
          childrenIte.push_back(ret[i][0]);
504
28779
          for (size_t j = 1; j <= 2; j++)
505
          {
506
            // check if it rewrites to a constant
507
38372
            Node nn = nm->mkNode(EQUAL, no, ret[i][j]);
508
19186
            nn = Rewriter::rewrite(nn);
509
19186
            childrenIte.push_back(nn);
510
19186
            if (nn.isConst())
511
            {
512
1198
              doRewrite = true;
513
            }
514
          }
515
9593
          if (doRewrite)
516
          {
517
861
            ret = nm->mkNode(ITE, childrenIte);
518
861
            break;
519
          }
520
        }
521
      }
522
    }
523
  }
524
1745386
  else if (ret.getKind() == SELECT && ret[0].getKind() == STORE)
525
  {
526
184
    Node st = ret[0];
527
184
    Node index = ret[1];
528
184
    std::vector<Node> iconds;
529
184
    std::vector<Node> elements;
530
550
    while (st.getKind() == STORE)
531
    {
532
229
      iconds.push_back(index.eqNode(st[1]));
533
229
      elements.push_back(st[2]);
534
229
      st = st[0];
535
    }
536
92
    ret = nm->mkNode(SELECT, st, index);
537
    // conditions
538
321
    for (int i = (iconds.size() - 1); i >= 0; i--)
539
    {
540
229
      ret = nm->mkNode(ITE, iconds[i], elements[i], ret);
541
    }
542
  }
543
1977130
  cache[body] = ret;
544
1977130
  return ret;
545
}
546
547
25
Node QuantifiersRewriter::computeExtendedRewrite(Node q)
548
{
549
50
  Node body = q[1];
550
  // apply extended rewriter
551
50
  ExtendedRewriter er;
552
50
  Node bodyr = er.extendedRewrite(body);
553
25
  if (body != bodyr)
554
  {
555
24
    std::vector<Node> children;
556
12
    children.push_back(q[0]);
557
12
    children.push_back(bodyr);
558
12
    if (q.getNumChildren() == 3)
559
    {
560
      children.push_back(q[2]);
561
    }
562
12
    return NodeManager::currentNM()->mkNode(FORALL, children);
563
  }
564
13
  return q;
565
}
566
567
114151
Node QuantifiersRewriter::computeCondSplit(Node body,
568
                                           const std::vector<Node>& args,
569
                                           QAttributes& qa)
570
{
571
114151
  NodeManager* nm = NodeManager::currentNM();
572
114151
  Kind bk = body.getKind();
573
228660
  if (options::iteDtTesterSplitQuant() && bk == ITE
574
228310
      && body[0].getKind() == APPLY_TESTER)
575
  {
576
    Trace("quantifiers-rewrite-ite-debug") << "DTT split : " << body << std::endl;
577
    std::map< Node, Node > pcons;
578
    std::map< Node, std::map< int, Node > > ncons;
579
    std::vector< Node > conj;
580
    computeDtTesterIteSplit( body, pcons, ncons, conj );
581
    Assert(!conj.empty());
582
    if( conj.size()>1 ){
583
      Trace("quantifiers-rewrite-ite") << "*** Split ITE (datatype tester) " << body << " into : " << std::endl;
584
      for( unsigned i=0; i<conj.size(); i++ ){
585
        Trace("quantifiers-rewrite-ite") << "   " << conj[i] << std::endl;
586
      }
587
      return nm->mkNode(AND, conj);
588
    }
589
  }
590
114151
  if (!options::condVarSplitQuant())
591
  {
592
    return body;
593
  }
594
228302
  Trace("cond-var-split-debug")
595
114151
      << "Conditional var elim split " << body << "?" << std::endl;
596
597
114151
  if (bk == ITE
598
114343
      || (bk == EQUAL && body[0].getType().isBoolean()
599
24432
          && options::condVarSplitQuantAgg()))
600
  {
601
192
    Assert(!qa.isFunDef());
602
192
    bool do_split = false;
603
192
    unsigned index_max = bk == ITE ? 0 : 1;
604
354
    std::vector<Node> tmpArgs = args;
605
354
    for (unsigned index = 0; index <= index_max; index++)
606
    {
607
576
      if (hasVarElim(body[index], true, tmpArgs)
608
576
          || hasVarElim(body[index], false, tmpArgs))
609
      {
610
30
        do_split = true;
611
30
        break;
612
      }
613
    }
614
192
    if (do_split)
615
    {
616
60
      Node pos;
617
60
      Node neg;
618
30
      if (bk == ITE)
619
      {
620
30
        pos = nm->mkNode(OR, body[0].negate(), body[1]);
621
30
        neg = nm->mkNode(OR, body[0], body[2]);
622
      }
623
      else
624
      {
625
        pos = nm->mkNode(OR, body[0].negate(), body[1]);
626
        neg = nm->mkNode(OR, body[0], body[1].negate());
627
      }
628
60
      Trace("cond-var-split-debug") << "*** Split (conditional variable eq) "
629
30
                                    << body << " into : " << std::endl;
630
30
      Trace("cond-var-split-debug") << "   " << pos << std::endl;
631
30
      Trace("cond-var-split-debug") << "   " << neg << std::endl;
632
30
      return nm->mkNode(AND, pos, neg);
633
    }
634
  }
635
636
114121
  if (bk == OR)
637
  {
638
45955
    unsigned size = body.getNumChildren();
639
45955
    bool do_split = false;
640
45955
    unsigned split_index = 0;
641
185723
    for (unsigned i = 0; i < size; i++)
642
    {
643
      // check if this child is a (conditional) variable elimination
644
279677
      Node b = body[i];
645
139909
      if (b.getKind() == AND)
646
      {
647
17114
        std::vector<Node> vars;
648
17114
        std::vector<Node> subs;
649
17114
        std::vector<Node> tmpArgs = args;
650
33174
        for (unsigned j = 0, bsize = b.getNumChildren(); j < bsize; j++)
651
        {
652
24758
          if (getVarElimLit(body, b[j], false, tmpArgs, vars, subs))
653
          {
654
4926
            Trace("cond-var-split-debug") << "Variable elimination in child #"
655
2463
                                          << j << " under " << i << std::endl;
656
            // Figure out if we should split
657
            // Currently we split if the aggressive option is set, or
658
            // if the top-level OR is binary.
659
2463
            if (options::condVarSplitQuantAgg() || size == 2)
660
            {
661
141
              do_split = true;
662
            }
663
            // other splitting criteria go here
664
665
2463
            if (do_split)
666
            {
667
141
              split_index = i;
668
141
              break;
669
            }
670
2322
            vars.clear();
671
2322
            subs.clear();
672
2322
            tmpArgs = args;
673
          }
674
        }
675
      }
676
139909
      if (do_split)
677
      {
678
141
        break;
679
      }
680
    }
681
45955
    if (do_split)
682
    {
683
282
      std::vector<Node> children;
684
423
      for (TNode bc : body)
685
      {
686
282
        children.push_back(bc);
687
      }
688
282
      std::vector<Node> split_children;
689
570
      for (TNode bci : body[split_index])
690
      {
691
429
        children[split_index] = bci;
692
429
        split_children.push_back(nm->mkNode(OR, children));
693
      }
694
      // split the AND child, for example:
695
      //  ( x!=a ^ P(x) ) V Q(x) ---> ( x!=a V Q(x) ) ^ ( P(x) V Q(x) )
696
141
      return nm->mkNode(AND, split_children);
697
    }
698
  }
699
700
113980
  return body;
701
}
702
703
6171
bool QuantifiersRewriter::isVarElim(Node v, Node s)
704
{
705
6171
  Assert(v.getKind() == BOUND_VARIABLE);
706
6171
  return !expr::hasSubterm(s, v) && s.getType().isSubtypeOf(v.getType());
707
}
708
709
38091
Node QuantifiersRewriter::getVarElimEq(Node lit,
710
                                       const std::vector<Node>& args,
711
                                       Node& var)
712
{
713
38091
  Assert(lit.getKind() == EQUAL);
714
38091
  Node slv;
715
76182
  TypeNode tt = lit[0].getType();
716
38091
  if (tt.isReal())
717
  {
718
15825
    slv = getVarElimEqReal(lit, args, var);
719
  }
720
22266
  else if (tt.isBitVector())
721
  {
722
731
    slv = getVarElimEqBv(lit, args, var);
723
  }
724
21535
  else if (tt.isStringLike())
725
  {
726
242
    slv = getVarElimEqString(lit, args, var);
727
  }
728
76182
  return slv;
729
}
730
731
15825
Node QuantifiersRewriter::getVarElimEqReal(Node lit,
732
                                           const std::vector<Node>& args,
733
                                           Node& var)
734
{
735
  // for arithmetic, solve the equality
736
31650
  std::map<Node, Node> msum;
737
15825
  if (!ArithMSum::getMonomialSumLit(lit, msum))
738
  {
739
    return Node::null();
740
  }
741
15825
  std::vector<Node>::const_iterator ita;
742
48066
  for (std::map<Node, Node>::iterator itm = msum.begin(); itm != msum.end();
743
       ++itm)
744
  {
745
32437
    if (itm->first.isNull())
746
    {
747
3255
      continue;
748
    }
749
29182
    ita = std::find(args.begin(), args.end(), itm->first);
750
29182
    if (ita != args.end())
751
    {
752
916
      Node veq_c;
753
916
      Node val;
754
556
      int ires = ArithMSum::isolate(itm->first, msum, veq_c, val, EQUAL);
755
556
      if (ires != 0 && veq_c.isNull() && isVarElim(itm->first, val))
756
      {
757
196
        var = itm->first;
758
196
        return val;
759
      }
760
    }
761
  }
762
15629
  return Node::null();
763
}
764
765
731
Node QuantifiersRewriter::getVarElimEqBv(Node lit,
766
                                         const std::vector<Node>& args,
767
                                         Node& var)
768
{
769
731
  if (Trace.isOn("quant-velim-bv"))
770
  {
771
    Trace("quant-velim-bv") << "Bv-Elim : " << lit << " varList = { ";
772
    for (const Node& v : args)
773
    {
774
      Trace("quant-velim-bv") << v << " ";
775
    }
776
    Trace("quant-velim-bv") << "} ?" << std::endl;
777
  }
778
731
  Assert(lit.getKind() == EQUAL);
779
  // TODO (#1494) : linearize the literal using utility
780
781
  // compute a subset active_args of the bound variables args that occur in lit
782
1462
  std::vector<Node> active_args;
783
731
  computeArgVec(args, active_args, lit);
784
785
1462
  BvInverter binv;
786
1546
  for (const Node& cvar : active_args)
787
  {
788
    // solve for the variable on this path using the inverter
789
1668
    std::vector<unsigned> path;
790
1668
    Node slit = binv.getPathToPv(lit, cvar, path);
791
853
    if (!slit.isNull())
792
    {
793
814
      Node slv = binv.solveBvLit(cvar, lit, path, nullptr);
794
426
      Trace("quant-velim-bv") << "...solution : " << slv << std::endl;
795
426
      if (!slv.isNull())
796
      {
797
66
        var = cvar;
798
        // if this is a proper variable elimination, that is, var = slv where
799
        // var is not in the free variables of slv, then we can return this
800
        // as the variable elimination for lit.
801
66
        if (isVarElim(var, slv))
802
        {
803
38
          return slv;
804
        }
805
      }
806
    }
807
    else
808
    {
809
427
      Trace("quant-velim-bv") << "...non-invertible path." << std::endl;
810
    }
811
  }
812
813
693
  return Node::null();
814
}
815
816
242
Node QuantifiersRewriter::getVarElimEqString(Node lit,
817
                                             const std::vector<Node>& args,
818
                                             Node& var)
819
{
820
242
  Assert(lit.getKind() == EQUAL);
821
242
  NodeManager* nm = NodeManager::currentNM();
822
722
  for (unsigned i = 0; i < 2; i++)
823
  {
824
484
    if (lit[i].getKind() == STRING_CONCAT)
825
    {
826
12
      TypeNode stype = lit[i].getType();
827
20
      for (unsigned j = 0, nchildren = lit[i].getNumChildren(); j < nchildren;
828
           j++)
829
      {
830
16
        if (std::find(args.begin(), args.end(), lit[i][j]) != args.end())
831
        {
832
12
          var = lit[i][j];
833
20
          Node slv = lit[1 - i];
834
20
          std::vector<Node> preL(lit[i].begin(), lit[i].begin() + j);
835
20
          std::vector<Node> postL(lit[i].begin() + j + 1, lit[i].end());
836
20
          Node tpre = strings::utils::mkConcat(preL, stype);
837
20
          Node tpost = strings::utils::mkConcat(postL, stype);
838
20
          Node slvL = nm->mkNode(STRING_LENGTH, slv);
839
20
          Node tpreL = nm->mkNode(STRING_LENGTH, tpre);
840
20
          Node tpostL = nm->mkNode(STRING_LENGTH, tpost);
841
12
          slv = nm->mkNode(
842
              STRING_SUBSTR,
843
              slv,
844
              tpreL,
845
24
              nm->mkNode(MINUS, slvL, nm->mkNode(PLUS, tpreL, tpostL)));
846
          // forall x. r ++ x ++ t = s => P( x )
847
          //   is equivalent to
848
          // r ++ s' ++ t = s => P( s' ) where
849
          // s' = substr( s, |r|, |s|-(|t|+|r|) ).
850
          // We apply this only if r,t,s do not contain free variables.
851
12
          if (!expr::hasFreeVar(slv))
852
          {
853
4
            return slv;
854
          }
855
        }
856
      }
857
    }
858
  }
859
860
238
  return Node::null();
861
}
862
863
238413
bool QuantifiersRewriter::getVarElimLit(Node body,
864
                                        Node lit,
865
                                        bool pol,
866
                                        std::vector<Node>& args,
867
                                        std::vector<Node>& vars,
868
                                        std::vector<Node>& subs)
869
{
870
238413
  if (lit.getKind() == NOT)
871
  {
872
6713
    lit = lit[0];
873
6713
    pol = !pol;
874
6713
    Assert(lit.getKind() != NOT);
875
  }
876
238413
  NodeManager* nm = NodeManager::currentNM();
877
476826
  Trace("var-elim-quant-debug")
878
238413
      << "Eliminate : " << lit << ", pol = " << pol << "?" << std::endl;
879
477626
  if (lit.getKind() == APPLY_TESTER && pol && lit[0].getKind() == BOUND_VARIABLE
880
476870
      && options::dtVarExpandQuant())
881
  {
882
88
    Trace("var-elim-dt") << "Expand datatype variable based on : " << lit
883
44
                         << std::endl;
884
    std::vector<Node>::iterator ita =
885
44
        std::find(args.begin(), args.end(), lit[0]);
886
44
    if (ita != args.end())
887
    {
888
44
      vars.push_back(lit[0]);
889
88
      Node tester = lit.getOperator();
890
44
      int index = datatypes::utils::indexOf(tester);
891
44
      const DType& dt = datatypes::utils::datatypeOf(tester);
892
44
      const DTypeConstructor& c = dt[index];
893
88
      std::vector<Node> newChildren;
894
44
      newChildren.push_back(c.getConstructor());
895
88
      std::vector<Node> newVars;
896
44
      BoundVarManager* bvm = nm->getBoundVarManager();
897
107
      for (unsigned j = 0, nargs = c.getNumArgs(); j < nargs; j++)
898
      {
899
126
        TypeNode tn = c[j].getRangeType();
900
126
        Node rn = nm->mkConst(Rational(j));
901
126
        Node cacheVal = BoundVarManager::getCacheValue(body, lit, rn);
902
126
        Node v = bvm->mkBoundVar<QRewDtExpandAttribute>(cacheVal, tn);
903
63
        newChildren.push_back(v);
904
63
        newVars.push_back(v);
905
      }
906
44
      subs.push_back(nm->mkNode(APPLY_CONSTRUCTOR, newChildren));
907
88
      Trace("var-elim-dt") << "...apply substitution " << subs[0] << "/"
908
44
                           << vars[0] << std::endl;
909
44
      args.erase(ita);
910
44
      args.insert(args.end(), newVars.begin(), newVars.end());
911
44
      return true;
912
    }
913
  }
914
  // all eliminations below guarded by varElimQuant()
915
238369
  if (!options::varElimQuant())
916
  {
917
    return false;
918
  }
919
920
238369
  if (lit.getKind() == EQUAL)
921
  {
922
133684
    if (pol || lit[0].getType().isBoolean())
923
    {
924
197669
      for (unsigned i = 0; i < 2; i++)
925
      {
926
133936
        bool tpol = pol;
927
262572
        Node v_slv = lit[i];
928
133936
        if (v_slv.getKind() == NOT)
929
        {
930
5548
          v_slv = v_slv[0];
931
5548
          tpol = !tpol;
932
        }
933
        std::vector<Node>::iterator ita =
934
133936
            std::find(args.begin(), args.end(), v_slv);
935
133936
        if (ita != args.end())
936
        {
937
5741
          if (isVarElim(v_slv, lit[1 - i]))
938
          {
939
10600
            Node slv = lit[1 - i];
940
5300
            if (!tpol)
941
            {
942
652
              Assert(slv.getType().isBoolean());
943
652
              slv = slv.negate();
944
            }
945
10600
            Trace("var-elim-quant")
946
5300
                << "Variable eliminate based on equality : " << v_slv << " -> "
947
5300
                << slv << std::endl;
948
5300
            vars.push_back(v_slv);
949
5300
            subs.push_back(slv);
950
5300
            args.erase(ita);
951
5300
            return true;
952
          }
953
        }
954
      }
955
    }
956
  }
957
233069
  if (lit.getKind() == BOUND_VARIABLE)
958
  {
959
1451
    std::vector< Node >::iterator ita = std::find( args.begin(), args.end(), lit );
960
1451
    if( ita!=args.end() ){
961
1449
      Trace("var-elim-bool") << "Variable eliminate : " << lit << std::endl;
962
1449
      vars.push_back( lit );
963
1449
      subs.push_back( NodeManager::currentNM()->mkConst( pol ) );
964
1449
      args.erase( ita );
965
1449
      return true;
966
    }
967
  }
968
231620
  if (lit.getKind() == EQUAL && pol)
969
  {
970
75944
    Node var;
971
75944
    Node slv = getVarElimEq(lit, args, var);
972
38091
    if (!slv.isNull())
973
    {
974
238
      Assert(!var.isNull());
975
      std::vector<Node>::iterator ita =
976
238
          std::find(args.begin(), args.end(), var);
977
238
      Assert(ita != args.end());
978
476
      Trace("var-elim-quant")
979
238
          << "Variable eliminate based on theory-specific solving : " << var
980
238
          << " -> " << slv << std::endl;
981
238
      Assert(!expr::hasSubterm(slv, var));
982
238
      Assert(slv.getType().isSubtypeOf(var.getType()));
983
238
      vars.push_back(var);
984
238
      subs.push_back(slv);
985
238
      args.erase(ita);
986
238
      return true;
987
    }
988
  }
989
231382
  return false;
990
}
991
992
117106
bool QuantifiersRewriter::getVarElim(Node body,
993
                                     std::vector<Node>& args,
994
                                     std::vector<Node>& vars,
995
                                     std::vector<Node>& subs)
996
{
997
117106
  return getVarElimInternal(body, body, false, args, vars, subs);
998
}
999
1000
263234
bool QuantifiersRewriter::getVarElimInternal(Node body,
1001
                                             Node n,
1002
                                             bool pol,
1003
                                             std::vector<Node>& args,
1004
                                             std::vector<Node>& vars,
1005
                                             std::vector<Node>& subs)
1006
{
1007
263234
  Kind nk = n.getKind();
1008
263234
  if (nk == NOT)
1009
  {
1010
92063
    n = n[0];
1011
92063
    pol = !pol;
1012
92063
    nk = n.getKind();
1013
92063
    Assert(nk != NOT);
1014
  }
1015
263234
  if ((nk == AND && pol) || (nk == OR && !pol))
1016
  {
1017
191145
    for (const Node& cn : n)
1018
    {
1019
145774
      if (getVarElimInternal(body, cn, pol, args, vars, subs))
1020
      {
1021
4208
        return true;
1022
      }
1023
    }
1024
45371
    return false;
1025
  }
1026
213655
  return getVarElimLit(body, n, pol, args, vars, subs);
1027
}
1028
1029
354
bool QuantifiersRewriter::hasVarElim(Node n, bool pol, std::vector<Node>& args)
1030
{
1031
708
  std::vector< Node > vars;
1032
708
  std::vector< Node > subs;
1033
708
  return getVarElimInternal(n, n, pol, args, vars, subs);
1034
}
1035
1036
112466
bool QuantifiersRewriter::getVarElimIneq(Node body,
1037
                                         std::vector<Node>& args,
1038
                                         std::vector<Node>& bounds,
1039
                                         std::vector<Node>& subs,
1040
                                         QAttributes& qa)
1041
{
1042
112466
  Trace("var-elim-quant-debug") << "getVarElimIneq " << body << std::endl;
1043
  // For each variable v, we compute a set of implied bounds in the body
1044
  // of the quantified formula.
1045
  //   num_bounds[x][-1] stores the entailed lower bounds for x
1046
  //   num_bounds[x][1] stores the entailed upper bounds for x
1047
  //   num_bounds[x][0] stores the entailed disequalities for x
1048
  // These bounds are stored in a map that maps the literal for the bound to
1049
  // its required polarity. For example, for quantified formula
1050
  //   (forall ((x Int)) (or (= x 0) (>= x a)))
1051
  // we have:
1052
  //   num_bounds[x][0] contains { x -> { (= x 0) -> false } }
1053
  //   num_bounds[x][-1] contains { x -> { (>= x a) -> false } }
1054
  // This method succeeds in eliminating x if its only occurrences are in
1055
  // entailed disequalities, and one kind of bound. This is the case for the
1056
  // above quantified formula, which can be rewritten to false. The reason
1057
  // is that we can always chose a value for x that is arbitrarily large (resp.
1058
  // small) to satisfy all disequalities and inequalities for x.
1059
224932
  std::map<Node, std::map<int, std::map<Node, bool>>> num_bounds;
1060
  // The set of variables that we know we can not eliminate
1061
224932
  std::unordered_set<Node> ineligVars;
1062
  // compute the entailed literals
1063
224932
  QuantPhaseReq qpr(body);
1064
  // map to track which literals we have already processed, and hence can be
1065
  // excluded from the free variables check in the latter half of this method.
1066
224932
  std::map<Node, int> processed;
1067
308212
  for (const std::pair<const Node, bool>& pr : qpr.d_phase_reqs)
1068
  {
1069
    // an inequality that is entailed with a given polarity
1070
235891
    Node lit = pr.first;
1071
195746
    bool pol = pr.second;
1072
391492
    Trace("var-elim-quant-debug") << "Process inequality bounds : " << lit
1073
195746
                                  << ", pol = " << pol << "..." << std::endl;
1074
    bool canSolve =
1075
195746
        lit.getKind() == GEQ
1076
391492
        || (lit.getKind() == EQUAL && lit[0].getType().isReal() && !pol);
1077
195746
    if (!canSolve)
1078
    {
1079
155601
      continue;
1080
    }
1081
    // solve the inequality
1082
80290
    std::map<Node, Node> msum;
1083
40145
    if (!ArithMSum::getMonomialSumLit(lit, msum))
1084
    {
1085
      // not an inequality, cannot use
1086
      continue;
1087
    }
1088
40145
    processed[lit] = pol ? -1 : 1;
1089
124516
    for (const std::pair<const Node, Node>& m : msum)
1090
    {
1091
84371
      if (!m.first.isNull() && ineligVars.find(m.first) == ineligVars.end())
1092
      {
1093
        std::vector<Node>::iterator ita =
1094
68566
            std::find(args.begin(), args.end(), m.first);
1095
68566
        if (ita != args.end())
1096
        {
1097
          // store that this literal is upper/lower bound for itm->first
1098
61854
          Node veq_c;
1099
61854
          Node val;
1100
          int ires =
1101
30927
              ArithMSum::isolate(m.first, msum, veq_c, val, lit.getKind());
1102
30927
          if (ires != 0 && veq_c.isNull())
1103
          {
1104
30638
            if (lit.getKind() == GEQ)
1105
            {
1106
19244
              bool is_upper = pol != (ires == 1);
1107
38488
              Trace("var-elim-ineq-debug")
1108
19244
                  << lit << " is a " << (is_upper ? "upper" : "lower")
1109
19244
                  << " bound for " << m.first << std::endl;
1110
38488
              Trace("var-elim-ineq-debug")
1111
19244
                  << "  pol/ires = " << pol << " " << ires << std::endl;
1112
19244
              num_bounds[m.first][is_upper ? 1 : -1][lit] = pol;
1113
            }
1114
            else
1115
            {
1116
22788
              Trace("var-elim-ineq-debug")
1117
11394
                  << lit << " is a disequality for " << m.first << std::endl;
1118
11394
              num_bounds[m.first][0][lit] = pol;
1119
            }
1120
          }
1121
          else
1122
          {
1123
578
            Trace("var-elim-ineq-debug")
1124
289
                << "...ineligible " << m.first
1125
289
                << " since it cannot be solved for (" << ires << ", " << veq_c
1126
289
                << ")." << std::endl;
1127
289
            num_bounds.erase(m.first);
1128
289
            ineligVars.insert(m.first);
1129
          }
1130
        }
1131
        else
1132
        {
1133
          // compute variables in itm->first, these are not eligible for
1134
          // elimination
1135
75278
          std::unordered_set<Node> fvs;
1136
37639
          expr::getFreeVariables(m.first, fvs);
1137
78783
          for (const Node& v : fvs)
1138
          {
1139
82288
            Trace("var-elim-ineq-debug")
1140
41144
                << "...ineligible " << v
1141
41144
                << " since it is contained in monomial." << std::endl;
1142
41144
            num_bounds.erase(v);
1143
41144
            ineligVars.insert(v);
1144
          }
1145
        }
1146
      }
1147
    }
1148
  }
1149
1150
  // collect all variables that have only upper/lower bounds
1151
224932
  std::map<Node, bool> elig_vars;
1152
14863
  for (const std::pair<const Node, std::map<int, std::map<Node, bool>>>& nb :
1153
112466
       num_bounds)
1154
  {
1155
14863
    if (nb.second.find(1) == nb.second.end())
1156
    {
1157
16902
      Trace("var-elim-ineq-debug")
1158
8451
          << "Variable " << nb.first << " has only lower bounds." << std::endl;
1159
8451
      elig_vars[nb.first] = false;
1160
    }
1161
6412
    else if (nb.second.find(-1) == nb.second.end())
1162
    {
1163
4274
      Trace("var-elim-ineq-debug")
1164
2137
          << "Variable " << nb.first << " has only upper bounds." << std::endl;
1165
2137
      elig_vars[nb.first] = true;
1166
    }
1167
  }
1168
112466
  if (elig_vars.empty())
1169
  {
1170
103340
    return false;
1171
  }
1172
18252
  std::vector<Node> inactive_vars;
1173
18252
  std::map<Node, std::map<int, bool> > visited;
1174
  // traverse the body, invalidate variables if they occur in places other than
1175
  // the bounds they occur in
1176
18252
  std::unordered_map<TNode, std::unordered_set<int>> evisited;
1177
18252
  std::vector<TNode> evisit;
1178
18252
  std::vector<int> evisit_pol;
1179
18252
  TNode ecur;
1180
  int ecur_pol;
1181
9126
  evisit.push_back(body);
1182
9126
  evisit_pol.push_back(1);
1183
9126
  if (!qa.d_ipl.isNull())
1184
  {
1185
    // do not eliminate variables that occur in the annotation
1186
1424
    evisit.push_back(qa.d_ipl);
1187
1424
    evisit_pol.push_back(0);
1188
  }
1189
62916
  do
1190
  {
1191
72042
    ecur = evisit.back();
1192
72042
    evisit.pop_back();
1193
72042
    ecur_pol = evisit_pol.back();
1194
72042
    evisit_pol.pop_back();
1195
72042
    std::unordered_set<int>& epp = evisited[ecur];
1196
72042
    if (epp.find(ecur_pol) == epp.end())
1197
    {
1198
70529
      epp.insert(ecur_pol);
1199
70529
      if (elig_vars.find(ecur) != elig_vars.end())
1200
      {
1201
        // variable contained in a place apart from bounds, no longer eligible
1202
        // for elimination
1203
10156
        elig_vars.erase(ecur);
1204
20312
        Trace("var-elim-ineq-debug") << "...found occurrence of " << ecur
1205
10156
                                     << ", mark ineligible" << std::endl;
1206
      }
1207
      else
1208
      {
1209
60373
        bool rec = true;
1210
60373
        bool pol = ecur_pol >= 0;
1211
60373
        bool hasPol = ecur_pol != 0;
1212
60373
        if (hasPol)
1213
        {
1214
31676
          std::map<Node, int>::iterator itx = processed.find(ecur);
1215
31676
          if (itx != processed.end() && itx->second == ecur_pol)
1216
          {
1217
            // already processed this literal as a bound
1218
4981
            rec = false;
1219
          }
1220
        }
1221
60373
        if (rec)
1222
        {
1223
143478
          for (unsigned j = 0, size = ecur.getNumChildren(); j < size; j++)
1224
          {
1225
            bool newHasPol;
1226
            bool newPol;
1227
88086
            QuantPhaseReq::getPolarity(ecur, j, hasPol, pol, newHasPol, newPol);
1228
88086
            evisit.push_back(ecur[j]);
1229
88086
            evisit_pol.push_back(newHasPol ? (newPol ? 1 : -1) : 0);
1230
          }
1231
        }
1232
      }
1233
    }
1234
72042
  } while (!evisit.empty() && !elig_vars.empty());
1235
1236
9126
  bool ret = false;
1237
9126
  NodeManager* nm = NodeManager::currentNM();
1238
9558
  for (const std::pair<const Node, bool>& ev : elig_vars)
1239
  {
1240
864
    Node v = ev.first;
1241
864
    Trace("var-elim-ineq-debug")
1242
432
        << v << " is eligible for elimination." << std::endl;
1243
    // do substitution corresponding to infinite projection, all literals
1244
    // involving unbounded variable go to true/false
1245
    // disequalities of eligible variables are also eliminated
1246
432
    std::map<int, std::map<Node, bool>>& nbv = num_bounds[v];
1247
1296
    for (size_t i = 0; i < 2; i++)
1248
    {
1249
864
      size_t nindex = i == 0 ? (elig_vars[v] ? 1 : -1) : 0;
1250
1435
      for (const std::pair<const Node, bool>& nb : nbv[nindex])
1251
      {
1252
1142
        Trace("var-elim-ineq-debug")
1253
571
            << "  subs : " << nb.first << " -> " << nb.second << std::endl;
1254
571
        bounds.push_back(nb.first);
1255
571
        subs.push_back(nm->mkConst(nb.second));
1256
      }
1257
    }
1258
    // eliminate from args
1259
432
    std::vector<Node>::iterator ita = std::find(args.begin(), args.end(), v);
1260
432
    Assert(ita != args.end());
1261
432
    args.erase(ita);
1262
432
    ret = true;
1263
  }
1264
9126
  return ret;
1265
}
1266
1267
112876
Node QuantifiersRewriter::computeVarElimination( Node body, std::vector< Node >& args, QAttributes& qa ){
1268
225752
  if (!options::varElimQuant() && !options::dtVarExpandQuant()
1269
112876
      && !options::varIneqElimQuant())
1270
  {
1271
    return body;
1272
  }
1273
225752
  Trace("var-elim-quant-debug")
1274
112876
      << "computeVarElimination " << body << std::endl;
1275
225752
  Node prev;
1276
346874
  while (prev != body && !args.empty())
1277
  {
1278
116999
    prev = body;
1279
1280
233998
    std::vector<Node> vars;
1281
233998
    std::vector<Node> subs;
1282
    // standard variable elimination
1283
116999
    if (options::varElimQuant())
1284
    {
1285
116999
      getVarElim(body, args, vars, subs);
1286
    }
1287
    // variable elimination based on one-direction inequalities
1288
116999
    if (vars.empty() && options::varIneqElimQuant())
1289
    {
1290
112466
      getVarElimIneq(body, args, vars, subs, qa);
1291
    }
1292
    // if we eliminated a variable, update body and reprocess
1293
116999
    if (!vars.empty())
1294
    {
1295
9760
      Trace("var-elim-quant-debug")
1296
4880
          << "VE " << vars.size() << "/" << args.size() << std::endl;
1297
4880
      Assert(vars.size() == subs.size());
1298
      // remake with eliminated nodes
1299
4880
      body =
1300
9760
          body.substitute(vars.begin(), vars.end(), subs.begin(), subs.end());
1301
4880
      body = Rewriter::rewrite(body);
1302
4880
      if (!qa.d_ipl.isNull())
1303
      {
1304
52
        qa.d_ipl = qa.d_ipl.substitute(
1305
26
            vars.begin(), vars.end(), subs.begin(), subs.end());
1306
      }
1307
4880
      Trace("var-elim-quant") << "Return " << body << std::endl;
1308
    }
1309
  }
1310
112876
  return body;
1311
}
1312
1313
448311
Node QuantifiersRewriter::computePrenex(Node q,
1314
                                        Node body,
1315
                                        std::unordered_set<Node>& args,
1316
                                        std::unordered_set<Node>& nargs,
1317
                                        bool pol,
1318
                                        bool prenexAgg)
1319
{
1320
448311
  NodeManager* nm = NodeManager::currentNM();
1321
448311
  Kind k = body.getKind();
1322
448311
  if (k == FORALL)
1323
  {
1324
26856
    if ((pol || prenexAgg)
1325
15378
        && (options::prenexQuantUser() || !QuantAttributes::hasPattern(body)))
1326
    {
1327
2284
      std::vector< Node > terms;
1328
2284
      std::vector< Node > subs;
1329
1142
      BoundVarManager* bvm = nm->getBoundVarManager();
1330
      //for doing prenexing of same-signed quantifiers
1331
      //must rename each variable that already exists
1332
2917
      for (const Node& v : body[0])
1333
      {
1334
1775
        terms.push_back(v);
1335
3550
        TypeNode vt = v.getType();
1336
3550
        Node vv;
1337
1775
        if (!q.isNull())
1338
        {
1339
          // We cache based on the original quantified formula, the subformula
1340
          // that we are pulling variables from (body), and the variable v.
1341
          // The argument body is required since in rare cases, two subformulas
1342
          // may share the same variables. This is the case for define-fun
1343
          // or inferred substitutions that contain quantified formulas.
1344
3550
          Node cacheVal = BoundVarManager::getCacheValue(q, body, v);
1345
1775
          vv = bvm->mkBoundVar<QRewPrenexAttribute>(cacheVal, vt);
1346
        }
1347
        else
1348
        {
1349
          // not specific to a quantified formula, use normal
1350
          vv = nm->mkBoundVar(vt);
1351
        }
1352
1775
        subs.push_back(vv);
1353
      }
1354
1142
      if (pol)
1355
      {
1356
1142
        args.insert(subs.begin(), subs.end());
1357
      }
1358
      else
1359
      {
1360
        nargs.insert(subs.begin(), subs.end());
1361
      }
1362
2284
      Node newBody = body[1];
1363
1142
      newBody = newBody.substitute( terms.begin(), terms.end(), subs.begin(), subs.end() );
1364
1142
      return newBody;
1365
    }
1366
  //must remove structure
1367
  }
1368
434233
  else if (prenexAgg && k == ITE && body.getType().isBoolean())
1369
  {
1370
    Node nn = nm->mkNode(AND,
1371
                         nm->mkNode(OR, body[0].notNode(), body[1]),
1372
                         nm->mkNode(OR, body[0], body[2]));
1373
    return computePrenex(q, nn, args, nargs, pol, prenexAgg);
1374
  }
1375
434233
  else if (prenexAgg && k == EQUAL && body[0].getType().isBoolean())
1376
  {
1377
    Node nn = nm->mkNode(AND,
1378
                         nm->mkNode(OR, body[0].notNode(), body[1]),
1379
                         nm->mkNode(OR, body[0], body[1].notNode()));
1380
    return computePrenex(q, nn, args, nargs, pol, prenexAgg);
1381
434233
  }else if( body.getType().isBoolean() ){
1382
434233
    Assert(k != EXISTS);
1383
434233
    bool childrenChanged = false;
1384
867275
    std::vector< Node > newChildren;
1385
1326425
    for (size_t i = 0, nchild = body.getNumChildren(); i < nchild; i++)
1386
    {
1387
      bool newHasPol;
1388
      bool newPol;
1389
892192
      QuantPhaseReq::getPolarity( body, i, true, pol, newHasPol, newPol );
1390
1449161
      if (!newHasPol)
1391
      {
1392
556969
        newChildren.push_back( body[i] );
1393
556969
        continue;
1394
      }
1395
670446
      Node n = computePrenex(q, body[i], args, nargs, newPol, prenexAgg);
1396
335223
      newChildren.push_back(n);
1397
335223
      childrenChanged = n != body[i] || childrenChanged;
1398
    }
1399
434233
    if( childrenChanged ){
1400
1191
      if (k == NOT && newChildren[0].getKind() == NOT)
1401
      {
1402
        return newChildren[0][0];
1403
      }
1404
1191
      return nm->mkNode(k, newChildren);
1405
    }
1406
  }
1407
445978
  return body;
1408
}
1409
1410
Node QuantifiersRewriter::computePrenexAgg(Node n,
1411
                                           std::map<Node, Node>& visited)
1412
{
1413
  std::map< Node, Node >::iterator itv = visited.find( n );
1414
  if( itv!=visited.end() ){
1415
    return itv->second;
1416
  }
1417
  if (!expr::hasClosure(n))
1418
  {
1419
    // trivial
1420
    return n;
1421
  }
1422
  NodeManager* nm = NodeManager::currentNM();
1423
  Node ret = n;
1424
  if (n.getKind() == NOT)
1425
  {
1426
    ret = computePrenexAgg(n[0], visited).negate();
1427
  }
1428
  else if (n.getKind() == FORALL)
1429
  {
1430
    std::vector<Node> children;
1431
    children.push_back(computePrenexAgg(n[1], visited));
1432
    std::vector<Node> args;
1433
    args.insert(args.end(), n[0].begin(), n[0].end());
1434
    // for each child, strip top level quant
1435
    for (unsigned i = 0; i < children.size(); i++)
1436
    {
1437
      if (children[i].getKind() == FORALL)
1438
      {
1439
        args.insert(args.end(), children[i][0].begin(), children[i][0].end());
1440
        children[i] = children[i][1];
1441
      }
1442
    }
1443
    // keep the pattern
1444
    std::vector<Node> iplc;
1445
    if (n.getNumChildren() == 3)
1446
    {
1447
      iplc.insert(iplc.end(), n[2].begin(), n[2].end());
1448
    }
1449
    Node nb = children.size() == 1 ? children[0] : nm->mkNode(OR, children);
1450
    ret = mkForall(args, nb, iplc, true);
1451
  }
1452
  else
1453
  {
1454
    std::unordered_set<Node> argsSet;
1455
    std::unordered_set<Node> nargsSet;
1456
    Node q;
1457
    Node nn = computePrenex(q, n, argsSet, nargsSet, true, true);
1458
    Assert(n != nn || argsSet.empty());
1459
    Assert(n != nn || nargsSet.empty());
1460
    if (n != nn)
1461
    {
1462
      Node nnn = computePrenexAgg(nn, visited);
1463
      // merge prenex
1464
      if (nnn.getKind() == FORALL)
1465
      {
1466
        argsSet.insert(nnn[0].begin(), nnn[0].end());
1467
        nnn = nnn[1];
1468
        // pos polarity variables are inner
1469
        if (!argsSet.empty())
1470
        {
1471
          nnn = mkForall({argsSet.begin(), argsSet.end()}, nnn, true);
1472
        }
1473
        argsSet.clear();
1474
      }
1475
      else if (nnn.getKind() == NOT && nnn[0].getKind() == FORALL)
1476
      {
1477
        nargsSet.insert(nnn[0][0].begin(), nnn[0][0].end());
1478
        nnn = nnn[0][1].negate();
1479
      }
1480
      if (!nargsSet.empty())
1481
      {
1482
        nnn = mkForall({nargsSet.begin(), nargsSet.end()}, nnn.negate(), true)
1483
                  .negate();
1484
      }
1485
      if (!argsSet.empty())
1486
      {
1487
        nnn = mkForall({argsSet.begin(), argsSet.end()}, nnn, true);
1488
      }
1489
      ret = nnn;
1490
    }
1491
  }
1492
  visited[n] = ret;
1493
  return ret;
1494
}
1495
1496
46625
Node QuantifiersRewriter::computeSplit( std::vector< Node >& args, Node body, QAttributes& qa ) {
1497
46625
  Assert(body.getKind() == OR);
1498
46625
  size_t var_found_count = 0;
1499
46625
  size_t eqc_count = 0;
1500
46625
  size_t eqc_active = 0;
1501
93250
  std::map< Node, int > var_to_eqc;
1502
93250
  std::map< int, std::vector< Node > > eqc_to_var;
1503
93250
  std::map< int, std::vector< Node > > eqc_to_lit;
1504
1505
93250
  std::vector<Node> lits;
1506
1507
197547
  for( unsigned i=0; i<body.getNumChildren(); i++ ){
1508
    //get variables contained in the literal
1509
301844
    Node n = body[i];
1510
301844
    std::vector< Node > lit_args;
1511
150922
    computeArgVec( args, lit_args, n );
1512
150922
    if( lit_args.empty() ){
1513
1639
      lits.push_back( n );
1514
    }else {
1515
      //collect the equivalence classes this literal belongs to, and the new variables it contributes
1516
298566
      std::vector< int > eqcs;
1517
298566
      std::vector< Node > lit_new_args;
1518
      //for each variable in literal
1519
495834
      for( unsigned j=0; j<lit_args.size(); j++) {
1520
        //see if the variable has already been found
1521
346551
        if (var_to_eqc.find(lit_args[j])!=var_to_eqc.end()) {
1522
230127
          int eqc = var_to_eqc[lit_args[j]];
1523
230127
          if (std::find(eqcs.begin(), eqcs.end(), eqc)==eqcs.end()) {
1524
102390
            eqcs.push_back(eqc);
1525
          }
1526
        }else{
1527
116424
          var_found_count++;
1528
116424
          lit_new_args.push_back(lit_args[j]);
1529
        }
1530
      }
1531
149283
      if (eqcs.empty()) {
1532
53474
        eqcs.push_back(eqc_count);
1533
53474
        eqc_count++;
1534
53474
        eqc_active++;
1535
      }
1536
1537
149283
      int eqcz = eqcs[0];
1538
      //merge equivalence classes with eqcz
1539
155864
      for (unsigned j=1; j<eqcs.size(); j++) {
1540
6581
        int eqc = eqcs[j];
1541
        //move all variables from equivalence class
1542
31558
        for (unsigned k=0; k<eqc_to_var[eqc].size(); k++) {
1543
49954
          Node v = eqc_to_var[eqc][k];
1544
24977
          var_to_eqc[v] = eqcz;
1545
24977
          eqc_to_var[eqcz].push_back(v);
1546
        }
1547
6581
        eqc_to_var.erase(eqc);
1548
        //move all literals from equivalence class
1549
30229
        for (unsigned k=0; k<eqc_to_lit[eqc].size(); k++) {
1550
47296
          Node l = eqc_to_lit[eqc][k];
1551
23648
          eqc_to_lit[eqcz].push_back(l);
1552
        }
1553
6581
        eqc_to_lit.erase(eqc);
1554
6581
        eqc_active--;
1555
      }
1556
      //add variables to equivalence class
1557
265707
      for (unsigned j=0; j<lit_new_args.size(); j++) {
1558
116424
        var_to_eqc[lit_new_args[j]] = eqcz;
1559
116424
        eqc_to_var[eqcz].push_back(lit_new_args[j]);
1560
      }
1561
      //add literal to equivalence class
1562
149283
      eqc_to_lit[eqcz].push_back(n);
1563
    }
1564
  }
1565
46625
  if ( eqc_active>1 || !lits.empty() || var_to_eqc.size()!=args.size() ){
1566
601
    NodeManager* nm = NodeManager::currentNM();
1567
601
    Trace("clause-split-debug") << "Split quantified formula with body " << body << std::endl;
1568
601
    Trace("clause-split-debug") << "   Ground literals: " << std::endl;
1569
2240
    for( size_t i=0; i<lits.size(); i++) {
1570
1639
      Trace("clause-split-debug") << "      " << lits[i] << std::endl;
1571
    }
1572
601
    Trace("clause-split-debug") << std::endl;
1573
601
    Trace("clause-split-debug") << "Equivalence classes: " << std::endl;
1574
1470
    for (std::map< int, std::vector< Node > >::iterator it = eqc_to_lit.begin(); it != eqc_to_lit.end(); ++it ){
1575
869
      Trace("clause-split-debug") << "   Literals: " << std::endl;
1576
4074
      for (size_t i=0; i<it->second.size(); i++) {
1577
3205
        Trace("clause-split-debug") << "      " << it->second[i] << std::endl;
1578
      }
1579
869
      int eqc = it->first;
1580
869
      Trace("clause-split-debug") << "   Variables: " << std::endl;
1581
3707
      for (size_t i=0; i<eqc_to_var[eqc].size(); i++) {
1582
2838
        Trace("clause-split-debug") << "      " << eqc_to_var[eqc][i] << std::endl;
1583
      }
1584
869
      Trace("clause-split-debug") << std::endl;
1585
1738
      Node bvl = NodeManager::currentNM()->mkNode( BOUND_VAR_LIST, eqc_to_var[eqc]);
1586
      Node bd =
1587
1738
          it->second.size() == 1 ? it->second[0] : nm->mkNode(OR, it->second);
1588
1738
      Node fa = nm->mkNode(FORALL, bvl, bd);
1589
869
      lits.push_back(fa);
1590
    }
1591
601
    Assert(!lits.empty());
1592
1202
    Node nf = lits.size()==1 ? lits[0] : NodeManager::currentNM()->mkNode(OR,lits);
1593
601
    Trace("clause-split-debug") << "Made node : " << nf << std::endl;
1594
601
    return nf;
1595
  }else{
1596
46024
    return mkForAll( args, body, qa );
1597
  }
1598
}
1599
1600
114726
Node QuantifiersRewriter::mkForAll(const std::vector<Node>& args,
1601
                                   Node body,
1602
                                   QAttributes& qa)
1603
{
1604
114726
  if (args.empty())
1605
  {
1606
224
    return body;
1607
  }
1608
114502
  NodeManager* nm = NodeManager::currentNM();
1609
229004
  std::vector<Node> children;
1610
114502
  children.push_back(nm->mkNode(kind::BOUND_VAR_LIST, args));
1611
114502
  children.push_back(body);
1612
114502
  if (!qa.d_ipl.isNull())
1613
  {
1614
14670
    children.push_back(qa.d_ipl);
1615
  }
1616
114502
  return nm->mkNode(kind::FORALL, children);
1617
}
1618
1619
Node QuantifiersRewriter::mkForall(const std::vector<Node>& args,
1620
                                   Node body,
1621
                                   bool marked)
1622
{
1623
  std::vector< Node > iplc;
1624
  return mkForall( args, body, iplc, marked );
1625
}
1626
1627
Node QuantifiersRewriter::mkForall(const std::vector<Node>& args,
1628
                                   Node body,
1629
                                   std::vector<Node>& iplc,
1630
                                   bool marked)
1631
{
1632
  if (args.empty())
1633
  {
1634
    return body;
1635
  }
1636
  NodeManager* nm = NodeManager::currentNM();
1637
  std::vector<Node> children;
1638
  children.push_back(nm->mkNode(kind::BOUND_VAR_LIST, args));
1639
  children.push_back(body);
1640
  if (marked)
1641
  {
1642
    SkolemManager* sm = nm->getSkolemManager();
1643
    Node avar = sm->mkDummySkolem("id", nm->booleanType());
1644
    QuantIdNumAttribute ida;
1645
    avar.setAttribute(ida, 0);
1646
    iplc.push_back(nm->mkNode(kind::INST_ATTRIBUTE, avar));
1647
  }
1648
  if (!iplc.empty())
1649
  {
1650
    children.push_back(nm->mkNode(kind::INST_PATTERN_LIST, iplc));
1651
  }
1652
  return nm->mkNode(kind::FORALL, children);
1653
}
1654
1655
//computes miniscoping, also eliminates variables that do not occur free in body
1656
116064
Node QuantifiersRewriter::computeMiniscoping(Node q, QAttributes& qa)
1657
{
1658
116064
  NodeManager* nm = NodeManager::currentNM();
1659
232128
  std::vector<Node> args(q[0].begin(), q[0].end());
1660
232128
  Node body = q[1];
1661
116064
  if( body.getKind()==FORALL ){
1662
    //combine prenex
1663
32
    std::vector< Node > newArgs;
1664
16
    newArgs.insert(newArgs.end(), q[0].begin(), q[0].end());
1665
33
    for( unsigned i=0; i<body[0].getNumChildren(); i++ ){
1666
17
      newArgs.push_back( body[0][i] );
1667
    }
1668
16
    return mkForAll( newArgs, body[1], qa );
1669
116048
  }else if( body.getKind()==AND ){
1670
    // aggressive miniscoping implies that structural miniscoping should
1671
    // be applied first
1672
1400
    if (options::miniscopeQuant() || options::aggressiveMiniscopeQuant())
1673
    {
1674
751
      BoundVarManager* bvm = nm->getBoundVarManager();
1675
      // Break apart the quantifed formula
1676
      // forall x. P1 ^ ... ^ Pn ---> forall x. P1 ^ ... ^ forall x. Pn
1677
1502
      NodeBuilder t(kind::AND);
1678
1502
      std::vector<Node> argsc;
1679
4020
      for (size_t i = 0, nchild = body.getNumChildren(); i < nchild; i++)
1680
      {
1681
3269
        if (argsc.empty())
1682
        {
1683
          // If not done so, we must create fresh copy of args. This is to
1684
          // ensure that quantified formulas do not reuse variables.
1685
7076
          for (const Node& v : q[0])
1686
          {
1687
10482
            TypeNode vt = v.getType();
1688
10482
            Node cacheVal = BoundVarManager::getCacheValue(q, v, i);
1689
10482
            Node vv = bvm->mkBoundVar<QRewMiniscopeAttribute>(cacheVal, vt);
1690
5241
            argsc.push_back(vv);
1691
          }
1692
        }
1693
6538
        Node b = body[i];
1694
        Node bodyc =
1695
6538
            b.substitute(args.begin(), args.end(), argsc.begin(), argsc.end());
1696
3269
        if (b == bodyc)
1697
        {
1698
          // Did not contain variables in args, thus it is ground. Since we did
1699
          // not use them, we keep the variables argsc for the next child.
1700
1468
          t << b;
1701
        }
1702
        else
1703
        {
1704
          // make the miniscoped quantified formula
1705
3602
          Node cbvl = nm->mkNode(BOUND_VAR_LIST, argsc);
1706
3602
          Node qq = nm->mkNode(FORALL, cbvl, bodyc);
1707
1801
          t << qq;
1708
          // We used argsc, clear so we will construct a fresh copy above.
1709
1801
          argsc.clear();
1710
        }
1711
      }
1712
1502
      Node retVal = t;
1713
751
      return retVal;
1714
    }
1715
114648
  }else if( body.getKind()==OR ){
1716
47860
    if( options::quantSplit() ){
1717
      //splitting subsumes free variable miniscoping, apply it with higher priority
1718
46625
      return computeSplit( args, body, qa );
1719
    }
1720
2470
    else if (options::miniscopeQuantFreeVar()
1721
1235
             || options::aggressiveMiniscopeQuant())
1722
    {
1723
      // aggressive miniscoping implies that free variable miniscoping should
1724
      // be applied first
1725
4
      Node newBody = body;
1726
4
      NodeBuilder body_split(kind::OR);
1727
4
      NodeBuilder tb(kind::OR);
1728
12
      for (const Node& trm : body)
1729
      {
1730
8
        if (expr::hasSubterm(trm, args))
1731
        {
1732
4
          tb << trm;
1733
        }else{
1734
4
          body_split << trm;
1735
        }
1736
      }
1737
4
      if( tb.getNumChildren()==0 ){
1738
        return body_split;
1739
4
      }else if( body_split.getNumChildren()>0 ){
1740
4
        newBody = tb.getNumChildren()==1 ? tb.getChild( 0 ) : tb;
1741
8
        std::vector< Node > activeArgs;
1742
4
        computeArgVec2( args, activeArgs, newBody, qa.d_ipl );
1743
4
        body_split << mkForAll( activeArgs, newBody, qa );
1744
4
        return body_split.getNumChildren()==1 ? body_split.getChild( 0 ) : body_split;
1745
      }
1746
    }
1747
66788
  }else if( body.getKind()==NOT ){
1748
14995
    Assert(isLiteral(body[0]));
1749
  }
1750
  //remove variables that don't occur
1751
137336
  std::vector< Node > activeArgs;
1752
68668
  computeArgVec2( args, activeArgs, body, qa.d_ipl );
1753
68668
  return mkForAll( activeArgs, body, qa );
1754
}
1755
1756
14
Node QuantifiersRewriter::computeAggressiveMiniscoping( std::vector< Node >& args, Node body ){
1757
28
  std::map<Node, std::vector<Node> > varLits;
1758
28
  std::map<Node, std::vector<Node> > litVars;
1759
14
  if (body.getKind() == OR) {
1760
    Trace("ag-miniscope") << "compute aggressive miniscoping on " << body << std::endl;
1761
    for (size_t i = 0; i < body.getNumChildren(); i++) {
1762
      std::vector<Node> activeArgs;
1763
      computeArgVec(args, activeArgs, body[i]);
1764
      for (unsigned j = 0; j < activeArgs.size(); j++) {
1765
        varLits[activeArgs[j]].push_back(body[i]);
1766
      }
1767
      std::vector<Node>& lit_body_i = litVars[body[i]];
1768
      std::vector<Node>::iterator lit_body_i_begin = lit_body_i.begin();
1769
      std::vector<Node>::const_iterator active_begin = activeArgs.begin();
1770
      std::vector<Node>::const_iterator active_end = activeArgs.end();
1771
      lit_body_i.insert(lit_body_i_begin, active_begin, active_end);
1772
    }
1773
    //find the variable in the least number of literals
1774
    Node bestVar;
1775
    for( std::map< Node, std::vector<Node> >::iterator it = varLits.begin(); it != varLits.end(); ++it ){
1776
      if( bestVar.isNull() || varLits[bestVar].size()>it->second.size() ){
1777
        bestVar = it->first;
1778
      }
1779
    }
1780
    Trace("ag-miniscope-debug") << "Best variable " << bestVar << " occurs in " << varLits[bestVar].size() << "/ " << body.getNumChildren() << " literals." << std::endl;
1781
    if( !bestVar.isNull() && varLits[bestVar].size()<body.getNumChildren() ){
1782
      //we can miniscope
1783
      Trace("ag-miniscope") << "Miniscope on " << bestVar << std::endl;
1784
      //make the bodies
1785
      std::vector<Node> qlit1;
1786
      qlit1.insert( qlit1.begin(), varLits[bestVar].begin(), varLits[bestVar].end() );
1787
      std::vector<Node> qlitt;
1788
      //for all literals not containing bestVar
1789
      for( size_t i=0; i<body.getNumChildren(); i++ ){
1790
        if( std::find( qlit1.begin(), qlit1.end(), body[i] )==qlit1.end() ){
1791
          qlitt.push_back( body[i] );
1792
        }
1793
      }
1794
      //make the variable lists
1795
      std::vector<Node> qvl1;
1796
      std::vector<Node> qvl2;
1797
      std::vector<Node> qvsh;
1798
      for( unsigned i=0; i<args.size(); i++ ){
1799
        bool found1 = false;
1800
        bool found2 = false;
1801
        for( size_t j=0; j<varLits[args[i]].size(); j++ ){
1802
          if( !found1 && std::find( qlit1.begin(), qlit1.end(), varLits[args[i]][j] )!=qlit1.end() ){
1803
            found1 = true;
1804
          }else if( !found2 && std::find( qlitt.begin(), qlitt.end(), varLits[args[i]][j] )!=qlitt.end() ){
1805
            found2 = true;
1806
          }
1807
          if( found1 && found2 ){
1808
            break;
1809
          }
1810
        }
1811
        if( found1 ){
1812
          if( found2 ){
1813
            qvsh.push_back( args[i] );
1814
          }else{
1815
            qvl1.push_back( args[i] );
1816
          }
1817
        }else{
1818
          Assert(found2);
1819
          qvl2.push_back( args[i] );
1820
        }
1821
      }
1822
      Assert(!qvl1.empty());
1823
      //check for literals that only contain shared variables
1824
      std::vector<Node> qlitsh;
1825
      std::vector<Node> qlit2;
1826
      for( size_t i=0; i<qlitt.size(); i++ ){
1827
        bool hasVar2 = false;
1828
        for( size_t j=0; j<litVars[qlitt[i]].size(); j++ ){
1829
          if( std::find( qvl2.begin(), qvl2.end(), litVars[qlitt[i]][j] )!=qvl2.end() ){
1830
            hasVar2 = true;
1831
            break;
1832
          }
1833
        }
1834
        if( hasVar2 ){
1835
          qlit2.push_back( qlitt[i] );
1836
        }else{
1837
          qlitsh.push_back( qlitt[i] );
1838
        }
1839
      }
1840
      varLits.clear();
1841
      litVars.clear();
1842
      Trace("ag-miniscope-debug") << "Split into literals : " << qlit1.size() << " / " << qlit2.size() << " / " << qlitsh.size();
1843
      Trace("ag-miniscope-debug") << ", variables : " << qvl1.size() << " / " << qvl2.size() << " / " << qvsh.size() << std::endl;
1844
      Node n1 = qlit1.size()==1 ? qlit1[0] : NodeManager::currentNM()->mkNode( OR, qlit1 );
1845
      n1 = computeAggressiveMiniscoping( qvl1, n1 );
1846
      qlitsh.push_back( n1 );
1847
      if( !qlit2.empty() ){
1848
        Node n2 = qlit2.size()==1 ? qlit2[0] : NodeManager::currentNM()->mkNode( OR, qlit2 );
1849
        n2 = computeAggressiveMiniscoping( qvl2, n2 );
1850
        qlitsh.push_back( n2 );
1851
      }
1852
      Node n = NodeManager::currentNM()->mkNode( OR, qlitsh );
1853
      if( !qvsh.empty() ){
1854
        Node bvl = NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST, qvsh);
1855
        n = NodeManager::currentNM()->mkNode( FORALL, bvl, n );
1856
      }
1857
      Trace("ag-miniscope") << "Return " << n << " for " << body << std::endl;
1858
      return n;
1859
    }
1860
  }
1861
28
  QAttributes qa;
1862
14
  return mkForAll( args, body, qa );
1863
}
1864
1865
951321
bool QuantifiersRewriter::doOperation(Node q,
1866
                                      RewriteStep computeOption,
1867
                                      QAttributes& qa)
1868
{
1869
  bool is_strict_trigger =
1870
951321
      qa.d_hasPattern
1871
951321
      && options::userPatternsQuant() == options::UserPatMode::STRICT;
1872
951321
  bool is_std = qa.isStandard() && !is_strict_trigger;
1873
951321
  if (computeOption == COMPUTE_ELIM_SYMBOLS)
1874
  {
1875
132440
    return true;
1876
  }
1877
818881
  else if (computeOption == COMPUTE_MINISCOPING)
1878
  {
1879
119248
    return is_std;
1880
  }
1881
699633
  else if (computeOption == COMPUTE_AGGRESSIVE_MINISCOPING)
1882
  {
1883
117471
    return options::aggressiveMiniscopeQuant() && is_std;
1884
  }
1885
582162
  else if (computeOption == COMPUTE_EXT_REWRITE)
1886
  {
1887
117471
    return options::extRewriteQuant();
1888
  }
1889
464691
  else if (computeOption == COMPUTE_PROCESS_TERMS)
1890
  {
1891
117459
    return is_std && options::iteLiftQuant() != options::IteLiftQuantMode::NONE;
1892
  }
1893
347232
  else if (computeOption == COMPUTE_COND_SPLIT)
1894
  {
1895
227944
    return (options::iteDtTesterSplitQuant() || options::condVarSplitQuant())
1896
228302
           && !is_strict_trigger;
1897
  }
1898
233081
  else if (computeOption == COMPUTE_PRENEX)
1899
  {
1900
117021
    return options::prenexQuant() != options::PrenexQuantMode::NONE
1901
117021
           && !options::aggressiveMiniscopeQuant() && is_std;
1902
  }
1903
116060
  else if (computeOption == COMPUTE_VAR_ELIMINATION)
1904
  {
1905
116060
    return (options::varElimQuant() || options::dtVarExpandQuant()) && is_std;
1906
  }
1907
  else
1908
  {
1909
    return false;
1910
  }
1911
}
1912
1913
//general method for computing various rewrites
1914
702933
Node QuantifiersRewriter::computeOperation(Node f,
1915
                                           RewriteStep computeOption,
1916
                                           QAttributes& qa)
1917
{
1918
702933
  Trace("quantifiers-rewrite-debug") << "Compute operation " << computeOption << " on " << f << " " << qa.d_qid_num << std::endl;
1919
702933
  if (computeOption == COMPUTE_MINISCOPING)
1920
  {
1921
116064
    if (options::prenexQuant() == options::PrenexQuantMode::NORMAL)
1922
    {
1923
      if( !qa.d_qid_num.isNull() ){
1924
        //already processed this, return self
1925
        return f;
1926
      }
1927
    }
1928
    //return directly
1929
116064
    return computeMiniscoping(f, qa);
1930
  }
1931
1173738
  std::vector<Node> args(f[0].begin(), f[0].end());
1932
1173738
  Node n = f[1];
1933
586869
  if (computeOption == COMPUTE_ELIM_SYMBOLS)
1934
  {
1935
132440
    n = computeElimSymbols(n);
1936
454429
  }else if( computeOption==COMPUTE_AGGRESSIVE_MINISCOPING ){
1937
14
    return computeAggressiveMiniscoping( args, n );
1938
  }
1939
454415
  else if (computeOption == COMPUTE_EXT_REWRITE)
1940
  {
1941
25
    return computeExtendedRewrite(f);
1942
  }
1943
454390
  else if (computeOption == COMPUTE_PROCESS_TERMS)
1944
  {
1945
228550
    std::vector< Node > new_conds;
1946
114275
    n = computeProcessTerms( n, args, new_conds, f, qa );
1947
114275
    if( !new_conds.empty() ){
1948
      new_conds.push_back( n );
1949
      n = NodeManager::currentNM()->mkNode( OR, new_conds );
1950
    }
1951
  }
1952
340115
  else if (computeOption == COMPUTE_COND_SPLIT)
1953
  {
1954
114151
    n = computeCondSplit(n, args, qa);
1955
  }
1956
225964
  else if (computeOption == COMPUTE_PRENEX)
1957
  {
1958
113088
    if (options::prenexQuant() == options::PrenexQuantMode::NORMAL)
1959
    {
1960
      //will rewrite at preprocess time
1961
      return f;
1962
    }
1963
    else
1964
    {
1965
226176
      std::unordered_set<Node> argsSet, nargsSet;
1966
113088
      n = computePrenex(f, n, argsSet, nargsSet, true, false);
1967
113088
      Assert(nargsSet.empty());
1968
113088
      args.insert(args.end(), argsSet.begin(), argsSet.end());
1969
    }
1970
  }
1971
112876
  else if (computeOption == COMPUTE_VAR_ELIMINATION)
1972
  {
1973
112876
    n = computeVarElimination( n, args, qa );
1974
  }
1975
586830
  Trace("quantifiers-rewrite-debug") << "Compute Operation: return " << n << ", " << args.size() << std::endl;
1976
586830
  if( f[1]==n && args.size()==f[0].getNumChildren() ){
1977
570159
    return f;
1978
  }else{
1979
16671
    if( args.empty() ){
1980
757
      return n;
1981
    }else{
1982
31828
      std::vector< Node > children;
1983
15914
      children.push_back( NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST, args ) );
1984
15914
      children.push_back( n );
1985
15914
      if( !qa.d_ipl.isNull() && args.size()==f[0].getNumChildren() ){
1986
2371
        children.push_back( qa.d_ipl );
1987
      }
1988
15914
      return NodeManager::currentNM()->mkNode(kind::FORALL, children );
1989
    }
1990
  }
1991
}
1992
1993
bool QuantifiersRewriter::isPrenexNormalForm( Node n ) {
1994
  if( n.getKind()==FORALL ){
1995
    return n[1].getKind()!=FORALL && isPrenexNormalForm( n[1] );
1996
  }else if( n.getKind()==NOT ){
1997
    return n[0].getKind()!=NOT && isPrenexNormalForm( n[0] );
1998
  }else{
1999
    return !expr::hasClosure(n);
2000
  }
2001
}
2002
2003
766
Node QuantifiersRewriter::preSkolemizeQuantifiers( Node n, bool polarity, std::vector< TypeNode >& fvTypes, std::vector< TNode >& fvs ){
2004
766
  Trace("pre-sk") << "Pre-skolem " << n << " " << polarity << " " << fvs.size() << endl;
2005
766
  if( n.getKind()==kind::NOT ){
2006
248
    Node nn = preSkolemizeQuantifiers( n[0], !polarity, fvTypes, fvs );
2007
124
    return nn.negate();
2008
642
  }else if( n.getKind()==kind::FORALL ){
2009
174
    if (n.getNumChildren() == 3)
2010
    {
2011
      // Do not pre-skolemize quantified formulas with three children.
2012
      // This includes non-standard quantified formulas
2013
      // like recursive function definitions, or sygus conjectures, and
2014
      // quantified formulas with triggers.
2015
88
      return n;
2016
    }
2017
86
    else if (polarity)
2018
    {
2019
62
      if( options::preSkolemQuant() && options::preSkolemQuantNested() ){
2020
96
        vector< Node > children;
2021
48
        children.push_back( n[0] );
2022
        //add children to current scope
2023
96
        std::vector< TypeNode > fvt;
2024
96
        std::vector< TNode > fvss;
2025
48
        fvt.insert( fvt.begin(), fvTypes.begin(), fvTypes.end() );
2026
48
        fvss.insert( fvss.begin(), fvs.begin(), fvs.end() );
2027
110
        for( int i=0; i<(int)n[0].getNumChildren(); i++ ){
2028
62
          fvt.push_back( n[0][i].getType() );
2029
62
          fvss.push_back( n[0][i] );
2030
        }
2031
        //process body
2032
48
        children.push_back( preSkolemizeQuantifiers( n[1], polarity, fvt, fvss ) );
2033
        //return processed quantifier
2034
48
        return NodeManager::currentNM()->mkNode( kind::FORALL, children );
2035
      }
2036
    }else{
2037
      //process body
2038
48
      Node nn = preSkolemizeQuantifiers( n[1], polarity, fvTypes, fvs );
2039
48
      std::vector< Node > sk;
2040
48
      Node sub;
2041
48
      std::vector< unsigned > sub_vars;
2042
      //return skolemized body
2043
      return Skolemize::mkSkolemizedBody(
2044
24
          n, nn, fvTypes, fvs, sk, sub, sub_vars);
2045
    }
2046
  }else{
2047
    //check if it contains a quantifier as a subterm
2048
    //if so, we will write this node
2049
468
    if (expr::hasClosure(n))
2050
    {
2051
74
      if( ( n.getKind()==kind::ITE && n.getType().isBoolean() ) || ( n.getKind()==kind::EQUAL && n[0].getType().isBoolean() ) ){
2052
14
        if( options::preSkolemQuantAgg() ){
2053
28
          Node nn;
2054
          //must remove structure
2055
14
          if( n.getKind()==kind::ITE ){
2056
            nn = NodeManager::currentNM()->mkNode( kind::AND,
2057
                  NodeManager::currentNM()->mkNode( kind::OR, n[0].notNode(), n[1] ),
2058
                  NodeManager::currentNM()->mkNode( kind::OR, n[0], n[2] ) );
2059
14
          }else if( n.getKind()==kind::EQUAL ){
2060
56
            nn = NodeManager::currentNM()->mkNode( kind::AND,
2061
28
                  NodeManager::currentNM()->mkNode( kind::OR, n[0].notNode(), n.getKind()==kind::XOR ? n[1].notNode() : n[1] ),
2062
28
                  NodeManager::currentNM()->mkNode( kind::OR, n[0], n.getKind()==kind::XOR ? n[1] : n[1].notNode() ) );
2063
          }
2064
14
          return preSkolemizeQuantifiers( nn, polarity, fvTypes, fvs );
2065
        }
2066
60
      }else if( n.getKind()==kind::AND || n.getKind()==kind::OR ){
2067
116
        vector< Node > children;
2068
174
        for( int i=0; i<(int)n.getNumChildren(); i++ ){
2069
116
          children.push_back( preSkolemizeQuantifiers( n[i], polarity, fvTypes, fvs ) );
2070
        }
2071
58
        return NodeManager::currentNM()->mkNode( n.getKind(), children );
2072
      }
2073
    }
2074
  }
2075
410
  return n;
2076
}
2077
2078
92445
TrustNode QuantifiersRewriter::preprocess(Node n, bool isInst)
2079
{
2080
184890
  Node prev = n;
2081
2082
92445
  if( options::preSkolemQuant() ){
2083
496
    if( !isInst || !options::preSkolemQuantNested() ){
2084
440
      Trace("quantifiers-preprocess-debug") << "Pre-skolemize " << n << "..." << std::endl;
2085
      //apply pre-skolemization to existential quantifiers
2086
880
      std::vector< TypeNode > fvTypes;
2087
880
      std::vector< TNode > fvs;
2088
440
      n = preSkolemizeQuantifiers( prev, true, fvTypes, fvs );
2089
    }
2090
  }
2091
  //pull all quantifiers globally
2092
92445
  if (options::prenexQuant() == options::PrenexQuantMode::NORMAL)
2093
  {
2094
    Trace("quantifiers-prenex") << "Prenexing : " << n << std::endl;
2095
    std::map<Node, Node> visited;
2096
    n = computePrenexAgg(n, visited);
2097
    n = Rewriter::rewrite( n );
2098
    Trace("quantifiers-prenex") << "Prenexing returned : " << n << std::endl;
2099
    //Assert( isPrenexNormalForm( n ) );
2100
  }
2101
92445
  if( n!=prev ){
2102
16
    Trace("quantifiers-preprocess") << "Preprocess " << prev << std::endl;
2103
16
    Trace("quantifiers-preprocess") << "..returned " << n << std::endl;
2104
16
    return TrustNode::mkTrustRewrite(prev, n, nullptr);
2105
  }
2106
92429
  return TrustNode::null();
2107
}
2108
2109
}  // namespace quantifiers
2110
}  // namespace theory
2111
29502
}  // namespace cvc5