GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/quantifiers_rewriter.cpp Lines: 900 1172 76.8 %
Date: 2021-08-20 Branches: 2006 4971 40.4 %

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
36
using namespace std;
37
using namespace cvc5::kind;
38
using namespace cvc5::context;
39
40
namespace cvc5 {
41
namespace theory {
42
namespace quantifiers {
43
44
/**
45
 * Attributes used for constructing bound variables in a canonical way. These
46
 * are attributes that map to bound variable, introduced for the following
47
 * purposes:
48
 * - QRewPrenexAttribute: cached on (v, body) where we are prenexing bound
49
 * variable v in a nested quantified formula within the given body.
50
 * - QRewMiniscopeAttribute: cached on (v, q, i) where q is being miniscoped
51
 * for F_i in its body (and F_1 ... F_n), and v is one of the bound variables
52
 * that q binds.
53
 * - QRewDtExpandAttribute: cached on
54
 */
55
struct QRewPrenexAttributeId
56
{
57
};
58
typedef expr::Attribute<QRewPrenexAttributeId, Node> QRewPrenexAttribute;
59
struct QRewMiniscopeAttributeId
60
{
61
};
62
typedef expr::Attribute<QRewMiniscopeAttributeId, Node> QRewMiniscopeAttribute;
63
struct QRewDtExpandAttributeId
64
{
65
};
66
typedef expr::Attribute<QRewDtExpandAttributeId, Node> QRewDtExpandAttribute;
67
68
std::ostream& operator<<(std::ostream& out, RewriteStep s)
69
{
70
  switch (s)
71
  {
72
    case COMPUTE_ELIM_SYMBOLS: out << "COMPUTE_ELIM_SYMBOLS"; break;
73
    case COMPUTE_MINISCOPING: out << "COMPUTE_MINISCOPING"; break;
74
    case COMPUTE_AGGRESSIVE_MINISCOPING:
75
      out << "COMPUTE_AGGRESSIVE_MINISCOPING";
76
      break;
77
    case COMPUTE_EXT_REWRITE: out << "COMPUTE_EXT_REWRITE"; break;
78
    case COMPUTE_PROCESS_TERMS: out << "COMPUTE_PROCESS_TERMS"; break;
79
    case COMPUTE_PRENEX: out << "COMPUTE_PRENEX"; break;
80
    case COMPUTE_VAR_ELIMINATION: out << "COMPUTE_VAR_ELIMINATION"; break;
81
    case COMPUTE_COND_SPLIT: out << "COMPUTE_COND_SPLIT"; break;
82
    default: out << "UnknownRewriteStep"; break;
83
  }
84
  return out;
85
}
86
87
14996
bool QuantifiersRewriter::isLiteral( Node n ){
88
14996
  switch( n.getKind() ){
89
  case NOT:
90
    return n[0].getKind()!=NOT && isLiteral( n[0] );
91
    break;
92
  case OR:
93
  case AND:
94
  case IMPLIES:
95
  case XOR:
96
  case ITE:
97
    return false;
98
    break;
99
8999
  case EQUAL:
100
    //for boolean terms
101
8999
    return !n[0].getType().isBoolean();
102
    break;
103
5997
  default:
104
5997
    break;
105
  }
106
5997
  return true;
107
}
108
109
void QuantifiersRewriter::addNodeToOrBuilder(Node n, NodeBuilder& t)
110
{
111
  if( n.getKind()==OR ){
112
    for( int i=0; i<(int)n.getNumChildren(); i++ ){
113
      t << n[i];
114
    }
115
  }else{
116
    t << n;
117
  }
118
}
119
120
4913664
void QuantifiersRewriter::computeArgs(const std::vector<Node>& args,
121
                                      std::map<Node, bool>& activeMap,
122
                                      Node n,
123
                                      std::map<Node, bool>& visited)
124
{
125
4913664
  if( visited.find( n )==visited.end() ){
126
3523353
    visited[n] = true;
127
3523353
    if( n.getKind()==BOUND_VARIABLE ){
128
591801
      if( std::find( args.begin(), args.end(), n )!=args.end() ){
129
485485
        activeMap[ n ] = true;
130
      }
131
    }else{
132
2931552
      if (n.hasOperator())
133
      {
134
1540387
        computeArgs(args, activeMap, n.getOperator(), visited);
135
      }
136
6015925
      for( int i=0; i<(int)n.getNumChildren(); i++ ){
137
3084373
        computeArgs( args, activeMap, n[i], visited );
138
      }
139
    }
140
  }
141
4913664
}
142
143
151778
void QuantifiersRewriter::computeArgVec(const std::vector<Node>& args,
144
                                        std::vector<Node>& activeArgs,
145
                                        Node n)
146
{
147
151778
  Assert(activeArgs.empty());
148
303556
  std::map< Node, bool > activeMap;
149
303556
  std::map< Node, bool > visited;
150
151778
  computeArgs( args, activeMap, n, visited );
151
151778
  if( !activeMap.empty() ){
152
2427751
    for( unsigned i=0; i<args.size(); i++ ){
153
2277624
      if( activeMap.find( args[i] )!=activeMap.end() ){
154
347559
        activeArgs.push_back( args[i] );
155
      }
156
    }
157
  }
158
151778
}
159
160
68674
void QuantifiersRewriter::computeArgVec2(const std::vector<Node>& args,
161
                                         std::vector<Node>& activeArgs,
162
                                         Node n,
163
                                         Node ipl)
164
{
165
68674
  Assert(activeArgs.empty());
166
137348
  std::map< Node, bool > activeMap;
167
137348
  std::map< Node, bool > visited;
168
68674
  computeArgs( args, activeMap, n, visited );
169
68674
  if( !activeMap.empty() ){
170
    //collect variables in inst pattern list only if we cannot eliminate quantifier
171
68452
    computeArgs( args, activeMap, ipl, visited );
172
207395
    for( unsigned i=0; i<args.size(); i++ ){
173
138943
      if( activeMap.find( args[i] )!=activeMap.end() ){
174
137926
        activeArgs.push_back( args[i] );
175
      }
176
    }
177
  }
178
68674
}
179
180
135582
RewriteResponse QuantifiersRewriter::preRewrite(TNode in) {
181
135582
  if( in.getKind()==kind::EXISTS || in.getKind()==kind::FORALL ){
182
79799
    Trace("quantifiers-rewrite-debug") << "pre-rewriting " << in << std::endl;
183
157809
    std::vector< Node > args;
184
157809
    Node body = in;
185
79799
    bool doRewrite = false;
186
94121
    while( body.getNumChildren()==2 && body.getKind()==body[1].getKind() ){
187
14381
      for( unsigned i=0; i<body[0].getNumChildren(); i++ ){
188
7220
        args.push_back( body[0][i] );
189
      }
190
7161
      body = body[1];
191
7161
      doRewrite = true;
192
    }
193
79799
    if( doRewrite ){
194
3578
      std::vector< Node > children;
195
3618
      for( unsigned i=0; i<body[0].getNumChildren(); i++ ){
196
1829
        args.push_back( body[0][i] );
197
      }
198
1789
      children.push_back( NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST,args) );
199
1789
      children.push_back( body[1] );
200
1789
      if( body.getNumChildren()==3 ){
201
48
        children.push_back( body[2] );
202
      }
203
3578
      Node n = NodeManager::currentNM()->mkNode( in.getKind(), children );
204
1789
      if( in!=n ){
205
1789
        Trace("quantifiers-pre-rewrite") << "*** pre-rewrite " << in << std::endl;
206
1789
        Trace("quantifiers-pre-rewrite") << " to " << std::endl;
207
1789
        Trace("quantifiers-pre-rewrite") << n << std::endl;
208
      }
209
1789
      return RewriteResponse(REWRITE_DONE, n);
210
    }
211
  }
212
133793
  return RewriteResponse(REWRITE_DONE, in);
213
}
214
215
247279
RewriteResponse QuantifiersRewriter::postRewrite(TNode in) {
216
247279
  Trace("quantifiers-rewrite-debug") << "post-rewriting " << in << std::endl;
217
247279
  RewriteStatus status = REWRITE_DONE;
218
494558
  Node ret = in;
219
247279
  RewriteStep rew_op = COMPUTE_LAST;
220
  //get the body
221
247279
  if( in.getKind()==EXISTS ){
222
5512
    std::vector< Node > children;
223
2756
    children.push_back( in[0] );
224
2756
    children.push_back( in[1].negate() );
225
2756
    if( in.getNumChildren()==3 ){
226
43
      children.push_back( in[2] );
227
    }
228
2756
    ret = NodeManager::currentNM()->mkNode( FORALL, children );
229
2756
    ret = ret.negate();
230
2756
    status = REWRITE_AGAIN_FULL;
231
244523
  }else if( in.getKind()==FORALL ){
232
133251
    if( in[1].isConst() && in.getNumChildren()==2 ){
233
852
      return RewriteResponse( status, in[1] );
234
    }else{
235
      //compute attributes
236
264798
      QAttributes qa;
237
132399
      QuantAttributes::computeQuantAttributes( in, qa );
238
1065241
      for (unsigned i = 0; i < COMPUTE_LAST; ++i)
239
      {
240
951221
        RewriteStep op = static_cast<RewriteStep>(i);
241
951221
        if( doOperation( in, op, qa ) ){
242
703139
          ret = computeOperation( in, op, qa );
243
703139
          if( ret!=in ){
244
18379
            rew_op = op;
245
18379
            status = REWRITE_AGAIN_FULL;
246
18379
            break;
247
          }
248
        }
249
      }
250
    }
251
  }
252
  //print if changed
253
246427
  if( in!=ret ){
254
21135
    Trace("quantifiers-rewrite") << "*** rewrite (op=" << rew_op << ") " << in << std::endl;
255
21135
    Trace("quantifiers-rewrite") << " to " << std::endl;
256
21135
    Trace("quantifiers-rewrite") << ret << std::endl;
257
  }
258
246427
  return RewriteResponse( status, ret );
259
}
260
261
796459
bool QuantifiersRewriter::addCheckElimChild( std::vector< Node >& children, Node c, Kind k, std::map< Node, bool >& lit_pol, bool& childrenChanged ){
262
796459
  if( ( k==OR || k==AND ) && options::elimTautQuant() ){
263
1271439
    Node lit = c.getKind()==NOT ? c[0] : c;
264
635830
    bool pol = c.getKind()!=NOT;
265
635830
    std::map< Node, bool >::iterator it = lit_pol.find( lit );
266
635830
    if( it==lit_pol.end() ){
267
634917
      lit_pol[lit] = pol;
268
634917
      children.push_back( c );
269
    }else{
270
913
      childrenChanged = true;
271
913
      if( it->second!=pol ){
272
221
        return false;
273
      }
274
    }
275
  }else{
276
160629
    children.push_back( c );
277
  }
278
796238
  return true;
279
}
280
281
// eliminates IMPLIES/XOR, removes duplicates/infers tautologies of AND/OR, and computes NNF
282
914558
Node QuantifiersRewriter::computeElimSymbols( Node body ) {
283
914558
  Kind ok = body.getKind();
284
914558
  Kind k = ok;
285
914558
  bool negAllCh = false;
286
914558
  bool negCh1 = false;
287
914558
  if( ok==IMPLIES ){
288
11820
    k = OR;
289
11820
    negCh1 = true;
290
902738
  }else if( ok==XOR ){
291
767
    k = EQUAL;
292
767
    negCh1 = true;
293
901971
  }else if( ok==NOT ){
294
367376
    if( body[0].getKind()==NOT ){
295
      return computeElimSymbols( body[0][0] );
296
367376
    }else if( body[0].getKind()==OR || body[0].getKind()==IMPLIES ){
297
1695
      k = AND;
298
1695
      negAllCh = true;
299
1695
      negCh1 = body[0].getKind()==IMPLIES;
300
1695
      body = body[0];
301
365681
    }else if( body[0].getKind()==AND ){
302
5620
      k = OR;
303
5620
      negAllCh = true;
304
5620
      body = body[0];
305
360061
    }else if( body[0].getKind()==XOR || ( body[0].getKind()==EQUAL && body[0][0].getType().isBoolean() ) ){
306
2732
      k = EQUAL;
307
2732
      negCh1 = ( body[0].getKind()==EQUAL );
308
2732
      body = body[0];
309
357329
    }else if( body[0].getKind()==ITE ){
310
87
      k = body[0].getKind();
311
87
      negAllCh = true;
312
87
      negCh1 = true;
313
87
      body = body[0];
314
    }else{
315
357242
      return body;
316
    }
317
534595
  }else if( ( ok!=EQUAL || !body[0].getType().isBoolean() ) && ok!=ITE && ok!=AND && ok!=OR ){
318
    //a literal
319
319298
    return body;
320
  }
321
238018
  bool childrenChanged = false;
322
476036
  std::vector< Node > children;
323
476036
  std::map< Node, bool > lit_pol;
324
1019956
  for( unsigned i=0; i<body.getNumChildren(); i++ ){
325
1564097
    Node c = computeElimSymbols( ( i==0 && negCh1 )!=negAllCh ? body[i].negate() : body[i] );
326
782159
    bool success = true;
327
782159
    if( c.getKind()==k && ( k==OR || k==AND ) ){
328
      //flatten
329
5545
      childrenChanged = true;
330
25389
      for( unsigned j=0; j<c.getNumChildren(); j++ ){
331
19845
        if( !addCheckElimChild( children, c[j], k, lit_pol, childrenChanged ) ){
332
1
          success = false;
333
1
          break;
334
        }
335
      }
336
    }else{
337
776614
      success = addCheckElimChild( children, c, k, lit_pol, childrenChanged );
338
    }
339
782159
    if( !success ){
340
      // tautology
341
221
      Assert(k == OR || k == AND);
342
221
      return NodeManager::currentNM()->mkConst( k==OR );
343
    }
344
781938
    childrenChanged = childrenChanged || c!=body[i];
345
  }
346
237797
  if( childrenChanged || k!=ok ){
347
26454
    return ( children.size()==1 && k!=NOT ) ? children[0] : NodeManager::currentNM()->mkNode( k, children );
348
  }else{
349
211343
    return body;
350
  }
351
}
352
353
void QuantifiersRewriter::computeDtTesterIteSplit( Node n, std::map< Node, Node >& pcons, std::map< Node, std::map< int, Node > >& ncons,
354
                                                   std::vector< Node >& conj ){
355
  if( n.getKind()==ITE && n[0].getKind()==APPLY_TESTER && n[1].getType().isBoolean() ){
356
    Trace("quantifiers-rewrite-ite-debug") << "Split tester condition : " << n << std::endl;
357
    Node x = n[0][0];
358
    std::map< Node, Node >::iterator itp = pcons.find( x );
359
    if( itp!=pcons.end() ){
360
      Trace("quantifiers-rewrite-ite-debug") << "...condition already set " << itp->second << std::endl;
361
      computeDtTesterIteSplit( n[ itp->second==n[0] ? 1 : 2 ], pcons, ncons, conj );
362
    }else{
363
      Node tester = n[0].getOperator();
364
      int index = datatypes::utils::indexOf(tester);
365
      std::map< int, Node >::iterator itn = ncons[x].find( index );
366
      if( itn!=ncons[x].end() ){
367
        Trace("quantifiers-rewrite-ite-debug") << "...condition negated " << itn->second << std::endl;
368
        computeDtTesterIteSplit( n[ 2 ], pcons, ncons, conj );
369
      }else{
370
        for( unsigned i=0; i<2; i++ ){
371
          if( i==0 ){
372
            pcons[x] = n[0];
373
          }else{
374
            pcons.erase( x );
375
            ncons[x][index] = n[0].negate();
376
          }
377
          computeDtTesterIteSplit( n[i+1], pcons, ncons, conj );
378
        }
379
        ncons[x].erase( index );
380
      }
381
    }
382
  }else{
383
    NodeManager* nm = NodeManager::currentNM();
384
    Trace("quantifiers-rewrite-ite-debug") << "Return value : " << n << std::endl;
385
    std::vector< Node > children;
386
    children.push_back( n );
387
    std::vector< Node > vars;
388
    //add all positive testers
389
    for( std::map< Node, Node >::iterator it = pcons.begin(); it != pcons.end(); ++it ){
390
      children.push_back( it->second.negate() );
391
      vars.push_back( it->first );
392
    }
393
    //add all negative testers
394
    for( std::map< Node, std::map< int, Node > >::iterator it = ncons.begin(); it != ncons.end(); ++it ){
395
      Node x = it->first;
396
      //only if we haven't settled on a positive tester
397
      if( std::find( vars.begin(), vars.end(), x )==vars.end() ){
398
        //check if we have exhausted all options but one
399
        const DType& dt = x.getType().getDType();
400
        std::vector< Node > nchildren;
401
        int pos_cons = -1;
402
        for( int i=0; i<(int)dt.getNumConstructors(); i++ ){
403
          std::map< int, Node >::iterator itt = it->second.find( i );
404
          if( itt==it->second.end() ){
405
            pos_cons = pos_cons==-1 ? i : -2;
406
          }else{
407
            nchildren.push_back( itt->second.negate() );
408
          }
409
        }
410
        if( pos_cons>=0 ){
411
          Node tester = dt[pos_cons].getTester();
412
          children.push_back(nm->mkNode(APPLY_TESTER, tester, x).negate());
413
        }else{
414
          children.insert( children.end(), nchildren.begin(), nchildren.end() );
415
        }
416
      }
417
    }
418
    //make condition/output pair
419
    Node c = children.size()==1 ? children[0] : NodeManager::currentNM()->mkNode( OR, children );
420
    conj.push_back( c );
421
  }
422
}
423
424
114316
Node QuantifiersRewriter::computeProcessTerms( Node body, std::vector< Node >& new_vars, std::vector< Node >& new_conds, Node q, QAttributes& qa ){
425
228632
  std::map< Node, Node > cache;
426
114316
  if( qa.isFunDef() ){
427
    Node h = QuantAttributes::getFunDefHead( q );
428
    Assert(!h.isNull());
429
    // if it is a function definition, rewrite the body independently
430
    Node fbody = QuantAttributes::getFunDefBody( q );
431
    Trace("quantifiers-rewrite-debug") << "Decompose " << h << " / " << fbody << " as function definition for " << q << "." << std::endl;
432
    if (!fbody.isNull())
433
    {
434
      Node r = computeProcessTerms2(fbody, cache, new_vars, new_conds);
435
      Assert(new_vars.size() == h.getNumChildren());
436
      return Rewriter::rewrite(NodeManager::currentNM()->mkNode(EQUAL, h, r));
437
    }
438
    // It can happen that we can't infer the shape of the function definition,
439
    // for example: forall xy. f( x, y ) = 1 + f( x, y ), this is rewritten to
440
    // forall xy. false.
441
  }
442
114316
  return computeProcessTerms2(body, cache, new_vars, new_conds);
443
}
444
445
2931467
Node QuantifiersRewriter::computeProcessTerms2(Node body,
446
                                               std::map<Node, Node>& cache,
447
                                               std::vector<Node>& new_vars,
448
                                               std::vector<Node>& new_conds)
449
{
450
2931467
  NodeManager* nm = NodeManager::currentNM();
451
5862934
  Trace("quantifiers-rewrite-term-debug2")
452
2931467
      << "computeProcessTerms " << body << std::endl;
453
2931467
  std::map< Node, Node >::iterator iti = cache.find( body );
454
2931467
  if( iti!=cache.end() ){
455
954008
    return iti->second;
456
  }
457
1977459
  bool changed = false;
458
3954918
  std::vector<Node> children;
459
4794610
  for (size_t i = 0; i < body.getNumChildren(); i++)
460
  {
461
    // do the recursive call on children
462
5634302
    Node nn = computeProcessTerms2(body[i], cache, new_vars, new_conds);
463
2817151
    children.push_back(nn);
464
2817151
    changed = changed || nn != body[i];
465
  }
466
467
  // make return value
468
3954918
  Node ret;
469
1977459
  if (changed)
470
  {
471
5103
    if (body.getMetaKind() == kind::metakind::PARAMETERIZED)
472
    {
473
194
      children.insert(children.begin(), body.getOperator());
474
    }
475
5103
    ret = nm->mkNode(body.getKind(), children);
476
  }
477
  else
478
  {
479
1972356
    ret = body;
480
  }
481
482
3954918
  Trace("quantifiers-rewrite-term-debug2")
483
1977459
      << "Returning " << ret << " for " << body << std::endl;
484
  // do context-independent rewriting
485
3954918
  if (ret.getKind() == EQUAL
486
1977459
      && options::iteLiftQuant() != options::IteLiftQuantMode::NONE)
487
  {
488
694085
    for (size_t i = 0; i < 2; i++)
489
    {
490
463117
      if (ret[i].getKind() == ITE)
491
      {
492
20933
        Node no = i == 0 ? ret[1] : ret[0];
493
10896
        if (no.getKind() != ITE)
494
        {
495
          bool doRewrite =
496
9588
              options::iteLiftQuant() == options::IteLiftQuantMode::ALL;
497
18317
          std::vector<Node> childrenIte;
498
9588
          childrenIte.push_back(ret[i][0]);
499
28764
          for (size_t j = 1; j <= 2; j++)
500
          {
501
            // check if it rewrites to a constant
502
38352
            Node nn = nm->mkNode(EQUAL, no, ret[i][j]);
503
19176
            nn = Rewriter::rewrite(nn);
504
19176
            childrenIte.push_back(nn);
505
19176
            if (nn.isConst())
506
            {
507
1194
              doRewrite = true;
508
            }
509
          }
510
9588
          if (doRewrite)
511
          {
512
859
            ret = nm->mkNode(ITE, childrenIte);
513
859
            break;
514
          }
515
        }
516
      }
517
    }
518
  }
519
1745632
  else if (ret.getKind() == SELECT && ret[0].getKind() == STORE)
520
  {
521
184
    Node st = ret[0];
522
184
    Node index = ret[1];
523
184
    std::vector<Node> iconds;
524
184
    std::vector<Node> elements;
525
550
    while (st.getKind() == STORE)
526
    {
527
229
      iconds.push_back(index.eqNode(st[1]));
528
229
      elements.push_back(st[2]);
529
229
      st = st[0];
530
    }
531
92
    ret = nm->mkNode(SELECT, st, index);
532
    // conditions
533
321
    for (int i = (iconds.size() - 1); i >= 0; i--)
534
    {
535
229
      ret = nm->mkNode(ITE, iconds[i], elements[i], ret);
536
    }
537
  }
538
1977459
  cache[body] = ret;
539
1977459
  return ret;
540
}
541
542
29
Node QuantifiersRewriter::computeExtendedRewrite(Node q)
543
{
544
58
  Node body = q[1];
545
  // apply extended rewriter
546
58
  ExtendedRewriter er;
547
58
  Node bodyr = er.extendedRewrite(body);
548
29
  if (body != bodyr)
549
  {
550
24
    std::vector<Node> children;
551
12
    children.push_back(q[0]);
552
12
    children.push_back(bodyr);
553
12
    if (q.getNumChildren() == 3)
554
    {
555
      children.push_back(q[2]);
556
    }
557
12
    return NodeManager::currentNM()->mkNode(FORALL, children);
558
  }
559
17
  return q;
560
}
561
562
114195
Node QuantifiersRewriter::computeCondSplit(Node body,
563
                                           const std::vector<Node>& args,
564
                                           QAttributes& qa)
565
{
566
114195
  NodeManager* nm = NodeManager::currentNM();
567
114195
  Kind bk = body.getKind();
568
228748
  if (options::iteDtTesterSplitQuant() && bk == ITE
569
228398
      && body[0].getKind() == APPLY_TESTER)
570
  {
571
    Trace("quantifiers-rewrite-ite-debug") << "DTT split : " << body << std::endl;
572
    std::map< Node, Node > pcons;
573
    std::map< Node, std::map< int, Node > > ncons;
574
    std::vector< Node > conj;
575
    computeDtTesterIteSplit( body, pcons, ncons, conj );
576
    Assert(!conj.empty());
577
    if( conj.size()>1 ){
578
      Trace("quantifiers-rewrite-ite") << "*** Split ITE (datatype tester) " << body << " into : " << std::endl;
579
      for( unsigned i=0; i<conj.size(); i++ ){
580
        Trace("quantifiers-rewrite-ite") << "   " << conj[i] << std::endl;
581
      }
582
      return nm->mkNode(AND, conj);
583
    }
584
  }
585
114195
  if (!options::condVarSplitQuant())
586
  {
587
    return body;
588
  }
589
228390
  Trace("cond-var-split-debug")
590
114195
      << "Conditional var elim split " << body << "?" << std::endl;
591
592
114195
  if (bk == ITE
593
114405
      || (bk == EQUAL && body[0].getType().isBoolean()
594
24430
          && options::condVarSplitQuantAgg()))
595
  {
596
210
    Assert(!qa.isFunDef());
597
210
    bool do_split = false;
598
210
    unsigned index_max = bk == ITE ? 0 : 1;
599
390
    std::vector<Node> tmpArgs = args;
600
390
    for (unsigned index = 0; index <= index_max; index++)
601
    {
602
630
      if (hasVarElim(body[index], true, tmpArgs)
603
630
          || hasVarElim(body[index], false, tmpArgs))
604
      {
605
30
        do_split = true;
606
30
        break;
607
      }
608
    }
609
210
    if (do_split)
610
    {
611
60
      Node pos;
612
60
      Node neg;
613
30
      if (bk == ITE)
614
      {
615
30
        pos = nm->mkNode(OR, body[0].negate(), body[1]);
616
30
        neg = nm->mkNode(OR, body[0], body[2]);
617
      }
618
      else
619
      {
620
        pos = nm->mkNode(OR, body[0].negate(), body[1]);
621
        neg = nm->mkNode(OR, body[0], body[1].negate());
622
      }
623
60
      Trace("cond-var-split-debug") << "*** Split (conditional variable eq) "
624
30
                                    << body << " into : " << std::endl;
625
30
      Trace("cond-var-split-debug") << "   " << pos << std::endl;
626
30
      Trace("cond-var-split-debug") << "   " << neg << std::endl;
627
30
      return nm->mkNode(AND, pos, neg);
628
    }
629
  }
630
631
114165
  if (bk == OR)
632
  {
633
45955
    unsigned size = body.getNumChildren();
634
45955
    bool do_split = false;
635
45955
    unsigned split_index = 0;
636
185741
    for (unsigned i = 0; i < size; i++)
637
    {
638
      // check if this child is a (conditional) variable elimination
639
279717
      Node b = body[i];
640
139931
      if (b.getKind() == AND)
641
      {
642
17030
        std::vector<Node> vars;
643
17030
        std::vector<Node> subs;
644
17030
        std::vector<Node> tmpArgs = args;
645
32944
        for (unsigned j = 0, bsize = b.getNumChildren(); j < bsize; j++)
646
        {
647
24574
          if (getVarElimLit(b[j], false, tmpArgs, vars, subs))
648
          {
649
4958
            Trace("cond-var-split-debug") << "Variable elimination in child #"
650
2479
                                          << j << " under " << i << std::endl;
651
            // Figure out if we should split
652
            // Currently we split if the aggressive option is set, or
653
            // if the top-level OR is binary.
654
2479
            if (options::condVarSplitQuantAgg() || size == 2)
655
            {
656
145
              do_split = true;
657
            }
658
            // other splitting criteria go here
659
660
2479
            if (do_split)
661
            {
662
145
              split_index = i;
663
145
              break;
664
            }
665
2334
            vars.clear();
666
2334
            subs.clear();
667
2334
            tmpArgs = args;
668
          }
669
        }
670
      }
671
139931
      if (do_split)
672
      {
673
145
        break;
674
      }
675
    }
676
45955
    if (do_split)
677
    {
678
290
      std::vector<Node> children;
679
435
      for (TNode bc : body)
680
      {
681
290
        children.push_back(bc);
682
      }
683
290
      std::vector<Node> split_children;
684
582
      for (TNode bci : body[split_index])
685
      {
686
437
        children[split_index] = bci;
687
437
        split_children.push_back(nm->mkNode(OR, children));
688
      }
689
      // split the AND child, for example:
690
      //  ( x!=a ^ P(x) ) V Q(x) ---> ( x!=a V Q(x) ) ^ ( P(x) V Q(x) )
691
145
      return nm->mkNode(AND, split_children);
692
    }
693
  }
694
695
114020
  return body;
696
}
697
698
6196
bool QuantifiersRewriter::isVarElim(Node v, Node s)
699
{
700
6196
  Assert(v.getKind() == BOUND_VARIABLE);
701
6196
  return !expr::hasSubterm(s, v) && s.getType().isSubtypeOf(v.getType());
702
}
703
704
38132
Node QuantifiersRewriter::getVarElimEq(Node lit,
705
                                       const std::vector<Node>& args,
706
                                       Node& var)
707
{
708
38132
  Assert(lit.getKind() == EQUAL);
709
38132
  Node slv;
710
76264
  TypeNode tt = lit[0].getType();
711
38132
  if (tt.isReal())
712
  {
713
15874
    slv = getVarElimEqReal(lit, args, var);
714
  }
715
22258
  else if (tt.isBitVector())
716
  {
717
731
    slv = getVarElimEqBv(lit, args, var);
718
  }
719
21527
  else if (tt.isStringLike())
720
  {
721
234
    slv = getVarElimEqString(lit, args, var);
722
  }
723
76264
  return slv;
724
}
725
726
15874
Node QuantifiersRewriter::getVarElimEqReal(Node lit,
727
                                           const std::vector<Node>& args,
728
                                           Node& var)
729
{
730
  // for arithmetic, solve the equality
731
31748
  std::map<Node, Node> msum;
732
15874
  if (!ArithMSum::getMonomialSumLit(lit, msum))
733
  {
734
    return Node::null();
735
  }
736
15874
  std::vector<Node>::const_iterator ita;
737
48218
  for (std::map<Node, Node>::iterator itm = msum.begin(); itm != msum.end();
738
       ++itm)
739
  {
740
32546
    if (itm->first.isNull())
741
    {
742
3266
      continue;
743
    }
744
29280
    ita = std::find(args.begin(), args.end(), itm->first);
745
29280
    if (ita != args.end())
746
    {
747
926
      Node veq_c;
748
926
      Node val;
749
564
      int ires = ArithMSum::isolate(itm->first, msum, veq_c, val, EQUAL);
750
564
      if (ires != 0 && veq_c.isNull() && isVarElim(itm->first, val))
751
      {
752
202
        var = itm->first;
753
202
        return val;
754
      }
755
    }
756
  }
757
15672
  return Node::null();
758
}
759
760
731
Node QuantifiersRewriter::getVarElimEqBv(Node lit,
761
                                         const std::vector<Node>& args,
762
                                         Node& var)
763
{
764
731
  if (Trace.isOn("quant-velim-bv"))
765
  {
766
    Trace("quant-velim-bv") << "Bv-Elim : " << lit << " varList = { ";
767
    for (const Node& v : args)
768
    {
769
      Trace("quant-velim-bv") << v << " ";
770
    }
771
    Trace("quant-velim-bv") << "} ?" << std::endl;
772
  }
773
731
  Assert(lit.getKind() == EQUAL);
774
  // TODO (#1494) : linearize the literal using utility
775
776
  // compute a subset active_args of the bound variables args that occur in lit
777
1462
  std::vector<Node> active_args;
778
731
  computeArgVec(args, active_args, lit);
779
780
1462
  BvInverter binv;
781
1546
  for (const Node& cvar : active_args)
782
  {
783
    // solve for the variable on this path using the inverter
784
1668
    std::vector<unsigned> path;
785
1668
    Node slit = binv.getPathToPv(lit, cvar, path);
786
853
    if (!slit.isNull())
787
    {
788
814
      Node slv = binv.solveBvLit(cvar, lit, path, nullptr);
789
426
      Trace("quant-velim-bv") << "...solution : " << slv << std::endl;
790
426
      if (!slv.isNull())
791
      {
792
66
        var = cvar;
793
        // if this is a proper variable elimination, that is, var = slv where
794
        // var is not in the free variables of slv, then we can return this
795
        // as the variable elimination for lit.
796
66
        if (isVarElim(var, slv))
797
        {
798
38
          return slv;
799
        }
800
      }
801
    }
802
    else
803
    {
804
427
      Trace("quant-velim-bv") << "...non-invertible path." << std::endl;
805
    }
806
  }
807
808
693
  return Node::null();
809
}
810
811
234
Node QuantifiersRewriter::getVarElimEqString(Node lit,
812
                                             const std::vector<Node>& args,
813
                                             Node& var)
814
{
815
234
  Assert(lit.getKind() == EQUAL);
816
234
  NodeManager* nm = NodeManager::currentNM();
817
698
  for (unsigned i = 0; i < 2; i++)
818
  {
819
468
    if (lit[i].getKind() == STRING_CONCAT)
820
    {
821
12
      TypeNode stype = lit[i].getType();
822
20
      for (unsigned j = 0, nchildren = lit[i].getNumChildren(); j < nchildren;
823
           j++)
824
      {
825
16
        if (std::find(args.begin(), args.end(), lit[i][j]) != args.end())
826
        {
827
12
          var = lit[i][j];
828
20
          Node slv = lit[1 - i];
829
20
          std::vector<Node> preL(lit[i].begin(), lit[i].begin() + j);
830
20
          std::vector<Node> postL(lit[i].begin() + j + 1, lit[i].end());
831
20
          Node tpre = strings::utils::mkConcat(preL, stype);
832
20
          Node tpost = strings::utils::mkConcat(postL, stype);
833
20
          Node slvL = nm->mkNode(STRING_LENGTH, slv);
834
20
          Node tpreL = nm->mkNode(STRING_LENGTH, tpre);
835
20
          Node tpostL = nm->mkNode(STRING_LENGTH, tpost);
836
12
          slv = nm->mkNode(
837
              STRING_SUBSTR,
838
              slv,
839
              tpreL,
840
24
              nm->mkNode(MINUS, slvL, nm->mkNode(PLUS, tpreL, tpostL)));
841
          // forall x. r ++ x ++ t = s => P( x )
842
          //   is equivalent to
843
          // r ++ s' ++ t = s => P( s' ) where
844
          // s' = substr( s, |r|, |s|-(|t|+|r|) ).
845
          // We apply this only if r,t,s do not contain free variables.
846
12
          if (!expr::hasFreeVar(slv))
847
          {
848
4
            return slv;
849
          }
850
        }
851
      }
852
    }
853
  }
854
855
230
  return Node::null();
856
}
857
858
238420
bool QuantifiersRewriter::getVarElimLit(Node lit,
859
                                        bool pol,
860
                                        std::vector<Node>& args,
861
                                        std::vector<Node>& vars,
862
                                        std::vector<Node>& subs)
863
{
864
238420
  if (lit.getKind() == NOT)
865
  {
866
6657
    lit = lit[0];
867
6657
    pol = !pol;
868
6657
    Assert(lit.getKind() != NOT);
869
  }
870
238420
  NodeManager* nm = NodeManager::currentNM();
871
476840
  Trace("var-elim-quant-debug")
872
238420
      << "Eliminate : " << lit << ", pol = " << pol << "?" << std::endl;
873
477643
  if (lit.getKind() == APPLY_TESTER && pol && lit[0].getKind() == BOUND_VARIABLE
874
476885
      && options::dtVarExpandQuant())
875
  {
876
90
    Trace("var-elim-dt") << "Expand datatype variable based on : " << lit
877
45
                         << std::endl;
878
    std::vector<Node>::iterator ita =
879
45
        std::find(args.begin(), args.end(), lit[0]);
880
45
    if (ita != args.end())
881
    {
882
45
      vars.push_back(lit[0]);
883
90
      Node tester = lit.getOperator();
884
45
      int index = datatypes::utils::indexOf(tester);
885
45
      const DType& dt = datatypes::utils::datatypeOf(tester);
886
45
      const DTypeConstructor& c = dt[index];
887
90
      std::vector<Node> newChildren;
888
45
      newChildren.push_back(c.getConstructor());
889
90
      std::vector<Node> newVars;
890
110
      for (unsigned j = 0, nargs = c.getNumArgs(); j < nargs; j++)
891
      {
892
130
        TypeNode tn = c[j].getRangeType();
893
130
        Node v = nm->mkBoundVar(tn);
894
65
        newChildren.push_back(v);
895
65
        newVars.push_back(v);
896
      }
897
45
      subs.push_back(nm->mkNode(APPLY_CONSTRUCTOR, newChildren));
898
90
      Trace("var-elim-dt") << "...apply substitution " << subs[0] << "/"
899
45
                           << vars[0] << std::endl;
900
45
      args.erase(ita);
901
45
      args.insert(args.end(), newVars.begin(), newVars.end());
902
45
      return true;
903
    }
904
  }
905
  // all eliminations below guarded by varElimQuant()
906
238375
  if (!options::varElimQuant())
907
  {
908
    return false;
909
  }
910
911
238375
  if (lit.getKind() == EQUAL)
912
  {
913
133738
    if (pol || lit[0].getType().isBoolean())
914
    {
915
197802
      for (unsigned i = 0; i < 2; i++)
916
      {
917
134030
        bool tpol = pol;
918
262745
        Node v_slv = lit[i];
919
134030
        if (v_slv.getKind() == NOT)
920
        {
921
5546
          v_slv = v_slv[0];
922
5546
          tpol = !tpol;
923
        }
924
        std::vector<Node>::iterator ita =
925
134030
            std::find(args.begin(), args.end(), v_slv);
926
134030
        if (ita != args.end())
927
        {
928
5758
          if (isVarElim(v_slv, lit[1 - i]))
929
          {
930
10630
            Node slv = lit[1 - i];
931
5315
            if (!tpol)
932
            {
933
652
              Assert(slv.getType().isBoolean());
934
652
              slv = slv.negate();
935
            }
936
10630
            Trace("var-elim-quant")
937
5315
                << "Variable eliminate based on equality : " << v_slv << " -> "
938
5315
                << slv << std::endl;
939
5315
            vars.push_back(v_slv);
940
5315
            subs.push_back(slv);
941
5315
            args.erase(ita);
942
5315
            return true;
943
          }
944
        }
945
      }
946
    }
947
  }
948
233060
  if (lit.getKind() == BOUND_VARIABLE)
949
  {
950
1446
    std::vector< Node >::iterator ita = std::find( args.begin(), args.end(), lit );
951
1446
    if( ita!=args.end() ){
952
1444
      Trace("var-elim-bool") << "Variable eliminate : " << lit << std::endl;
953
1444
      vars.push_back( lit );
954
1444
      subs.push_back( NodeManager::currentNM()->mkConst( pol ) );
955
1444
      args.erase( ita );
956
1444
      return true;
957
    }
958
  }
959
231616
  if (lit.getKind() == EQUAL && pol)
960
  {
961
76020
    Node var;
962
76020
    Node slv = getVarElimEq(lit, args, var);
963
38132
    if (!slv.isNull())
964
    {
965
244
      Assert(!var.isNull());
966
      std::vector<Node>::iterator ita =
967
244
          std::find(args.begin(), args.end(), var);
968
244
      Assert(ita != args.end());
969
488
      Trace("var-elim-quant")
970
244
          << "Variable eliminate based on theory-specific solving : " << var
971
244
          << " -> " << slv << std::endl;
972
244
      Assert(!expr::hasSubterm(slv, var));
973
244
      Assert(slv.getType().isSubtypeOf(var.getType()));
974
244
      vars.push_back(var);
975
244
      subs.push_back(slv);
976
244
      args.erase(ita);
977
244
      return true;
978
    }
979
  }
980
231372
  return false;
981
}
982
983
263471
bool QuantifiersRewriter::getVarElim(Node n,
984
                                     bool pol,
985
                                     std::vector<Node>& args,
986
                                     std::vector<Node>& vars,
987
                                     std::vector<Node>& subs)
988
{
989
263471
  Kind nk = n.getKind();
990
263471
  if (nk == NOT)
991
  {
992
92182
    n = n[0];
993
92182
    pol = !pol;
994
92182
    nk = n.getKind();
995
92182
    Assert(nk != NOT);
996
  }
997
263471
  if ((nk == AND && pol) || (nk == OR && !pol))
998
  {
999
191334
    for (const Node& cn : n)
1000
    {
1001
145922
      if (getVarElim(cn, pol, args, vars, subs))
1002
      {
1003
4213
        return true;
1004
      }
1005
    }
1006
45412
    return false;
1007
  }
1008
213846
  return getVarElimLit(n, pol, args, vars, subs);
1009
}
1010
1011
390
bool QuantifiersRewriter::hasVarElim(Node n, bool pol, std::vector<Node>& args)
1012
{
1013
780
  std::vector< Node > vars;
1014
780
  std::vector< Node > subs;
1015
780
  return getVarElim(n, pol, args, vars, subs);
1016
}
1017
1018
112516
bool QuantifiersRewriter::getVarElimIneq(Node body,
1019
                                         std::vector<Node>& args,
1020
                                         std::vector<Node>& bounds,
1021
                                         std::vector<Node>& subs,
1022
                                         QAttributes& qa)
1023
{
1024
  // elimination based on inequalities
1025
225032
  std::map<Node, std::map<bool, std::map<Node, bool> > > num_bounds;
1026
225032
  QuantPhaseReq qpr(body);
1027
308418
  for (const std::pair<const Node, bool>& pr : qpr.d_phase_reqs)
1028
  {
1029
    // an inequality that is entailed with a given polarity
1030
216233
    Node lit = pr.first;
1031
195902
    if (lit.getKind() != GEQ)
1032
    {
1033
175571
      continue;
1034
    }
1035
20331
    bool pol = pr.second;
1036
40662
    Trace("var-elim-quant-debug") << "Process inequality bounds : " << lit
1037
20331
                                  << ", pol = " << pol << "..." << std::endl;
1038
    // solve the inequality
1039
40662
    std::map<Node, Node> msum;
1040
20331
    if (!ArithMSum::getMonomialSumLit(lit, msum))
1041
    {
1042
      // not an inequality, cannot use
1043
      continue;
1044
    }
1045
63837
    for (const std::pair<const Node, Node>& m : msum)
1046
    {
1047
43506
      if (!m.first.isNull())
1048
      {
1049
        std::vector<Node>::iterator ita =
1050
32428
            std::find(args.begin(), args.end(), m.first);
1051
32428
        if (ita != args.end())
1052
        {
1053
          // store that this literal is upper/lower bound for itm->first
1054
41102
          Node veq_c;
1055
41102
          Node val;
1056
          int ires =
1057
20551
              ArithMSum::isolate(m.first, msum, veq_c, val, lit.getKind());
1058
20551
          if (ires != 0 && veq_c.isNull())
1059
          {
1060
20222
            bool is_upper = pol != (ires == 1);
1061
40444
            Trace("var-elim-ineq-debug")
1062
20222
                << lit << " is a " << (is_upper ? "upper" : "lower")
1063
20222
                << " bound for " << m.first << std::endl;
1064
40444
            Trace("var-elim-ineq-debug")
1065
20222
                << "  pol/ires = " << pol << " " << ires << std::endl;
1066
20222
            num_bounds[m.first][is_upper][lit] = pol;
1067
          }
1068
          else
1069
          {
1070
658
            Trace("var-elim-ineq-debug")
1071
329
                << "...ineligible " << m.first
1072
329
                << " since it cannot be solved for (" << ires << ", " << veq_c
1073
329
                << ")." << std::endl;
1074
329
            num_bounds[m.first][true].clear();
1075
329
            num_bounds[m.first][false].clear();
1076
          }
1077
        }
1078
        else
1079
        {
1080
          // compute variables in itm->first, these are not eligible for
1081
          // elimination
1082
23754
          std::unordered_set<Node> fvs;
1083
11877
          expr::getFreeVariables(m.first, fvs);
1084
22227
          for (const Node& v : fvs)
1085
          {
1086
20700
            Trace("var-elim-ineq-debug")
1087
10350
                << "...ineligible " << v
1088
10350
                << " since it is contained in monomial." << std::endl;
1089
10350
            num_bounds[v][true].clear();
1090
10350
            num_bounds[v][false].clear();
1091
          }
1092
        }
1093
      }
1094
    }
1095
  }
1096
1097
  // collect all variables that have only upper/lower bounds
1098
225032
  std::map<Node, bool> elig_vars;
1099
19397
  for (const std::pair<const Node, std::map<bool, std::map<Node, bool> > >& nb :
1100
112516
       num_bounds)
1101
  {
1102
19397
    if (nb.second.find(true) == nb.second.end())
1103
    {
1104
5928
      Trace("var-elim-ineq-debug")
1105
2964
          << "Variable " << nb.first << " has only lower bounds." << std::endl;
1106
2964
      elig_vars[nb.first] = false;
1107
    }
1108
16433
    else if (nb.second.find(false) == nb.second.end())
1109
    {
1110
4662
      Trace("var-elim-ineq-debug")
1111
2331
          << "Variable " << nb.first << " has only upper bounds." << std::endl;
1112
2331
      elig_vars[nb.first] = true;
1113
    }
1114
  }
1115
112516
  if (elig_vars.empty())
1116
  {
1117
108612
    return false;
1118
  }
1119
7808
  std::vector<Node> inactive_vars;
1120
7808
  std::map<Node, std::map<int, bool> > visited;
1121
7808
  std::map<Node, int> exclude;
1122
14538
  for (const std::pair<const Node, bool>& pr : qpr.d_phase_reqs)
1123
  {
1124
10634
    if (pr.first.getKind() == GEQ)
1125
    {
1126
6344
      exclude[pr.first] = pr.second ? -1 : 1;
1127
12688
      Trace("var-elim-ineq-debug")
1128
6344
          << "...exclude " << pr.first << " at polarity " << exclude[pr.first]
1129
6344
          << std::endl;
1130
    }
1131
  }
1132
  // traverse the body, invalidate variables if they occur in places other than
1133
  // the bounds they occur in
1134
7808
  std::unordered_map<TNode, std::unordered_set<int>> evisited;
1135
7808
  std::vector<TNode> evisit;
1136
7808
  std::vector<int> evisit_pol;
1137
7808
  TNode ecur;
1138
  int ecur_pol;
1139
3904
  evisit.push_back(body);
1140
3904
  evisit_pol.push_back(1);
1141
3904
  if (!qa.d_ipl.isNull())
1142
  {
1143
    // do not eliminate variables that occur in the annotation
1144
424
    evisit.push_back(qa.d_ipl);
1145
424
    evisit_pol.push_back(0);
1146
  }
1147
37773
  do
1148
  {
1149
41677
    ecur = evisit.back();
1150
41677
    evisit.pop_back();
1151
41677
    ecur_pol = evisit_pol.back();
1152
41677
    evisit_pol.pop_back();
1153
41677
    std::unordered_set<int>& epp = evisited[ecur];
1154
41677
    if (epp.find(ecur_pol) == epp.end())
1155
    {
1156
39374
      epp.insert(ecur_pol);
1157
39374
      if (elig_vars.find(ecur) != elig_vars.end())
1158
      {
1159
        // variable contained in a place apart from bounds, no longer eligible
1160
        // for elimination
1161
4914
        elig_vars.erase(ecur);
1162
9828
        Trace("var-elim-ineq-debug") << "...found occurrence of " << ecur
1163
4914
                                     << ", mark ineligible" << std::endl;
1164
      }
1165
      else
1166
      {
1167
34460
        bool rec = true;
1168
34460
        bool pol = ecur_pol >= 0;
1169
34460
        bool hasPol = ecur_pol != 0;
1170
34460
        if (hasPol)
1171
        {
1172
15676
          std::map<Node, int>::iterator itx = exclude.find(ecur);
1173
15676
          if (itx != exclude.end() && itx->second == ecur_pol)
1174
          {
1175
            // already processed this literal as a bound
1176
2777
            rec = false;
1177
          }
1178
        }
1179
34460
        if (rec)
1180
        {
1181
81899
          for (unsigned j = 0, size = ecur.getNumChildren(); j < size; j++)
1182
          {
1183
            bool newHasPol;
1184
            bool newPol;
1185
50216
            QuantPhaseReq::getPolarity(ecur, j, hasPol, pol, newHasPol, newPol);
1186
50216
            evisit.push_back(ecur[j]);
1187
50216
            evisit_pol.push_back(newHasPol ? (newPol ? 1 : -1) : 0);
1188
          }
1189
        }
1190
      }
1191
    }
1192
41677
  } while (!evisit.empty() && !elig_vars.empty());
1193
1194
3904
  bool ret = false;
1195
4285
  for (const std::pair<const Node, bool>& ev : elig_vars)
1196
  {
1197
762
    Node v = ev.first;
1198
762
    Trace("var-elim-ineq-debug")
1199
381
        << v << " is eligible for elimination." << std::endl;
1200
    // do substitution corresponding to infinite projection, all literals
1201
    // involving unbounded variable go to true/false
1202
894
    for (const std::pair<const Node, bool>& nb : num_bounds[v][elig_vars[v]])
1203
    {
1204
1026
      Trace("var-elim-ineq-debug")
1205
513
          << "  subs : " << nb.first << " -> " << nb.second << std::endl;
1206
513
      bounds.push_back(nb.first);
1207
513
      subs.push_back(NodeManager::currentNM()->mkConst(nb.second));
1208
    }
1209
    // eliminate from args
1210
381
    std::vector<Node>::iterator ita = std::find(args.begin(), args.end(), v);
1211
381
    Assert(ita != args.end());
1212
381
    args.erase(ita);
1213
381
    ret = true;
1214
  }
1215
3904
  return ret;
1216
}
1217
1218
112935
Node QuantifiersRewriter::computeVarElimination( Node body, std::vector< Node >& args, QAttributes& qa ){
1219
225870
  if (!options::varElimQuant() && !options::dtVarExpandQuant()
1220
112935
      && !options::varIneqElimQuant())
1221
  {
1222
    return body;
1223
  }
1224
225870
  Node prev;
1225
347031
  while (prev != body && !args.empty())
1226
  {
1227
117048
    prev = body;
1228
1229
234096
    std::vector<Node> vars;
1230
234096
    std::vector<Node> subs;
1231
    // standard variable elimination
1232
117048
    if (options::varElimQuant())
1233
    {
1234
117048
      getVarElim(body, false, args, vars, subs);
1235
    }
1236
    // variable elimination based on one-direction inequalities
1237
117048
    if (vars.empty() && options::varIneqElimQuant())
1238
    {
1239
112516
      getVarElimIneq(body, args, vars, subs, qa);
1240
    }
1241
    // if we eliminated a variable, update body and reprocess
1242
117048
    if (!vars.empty())
1243
    {
1244
9660
      Trace("var-elim-quant-debug")
1245
4830
          << "VE " << vars.size() << "/" << args.size() << std::endl;
1246
4830
      Assert(vars.size() == subs.size());
1247
      // remake with eliminated nodes
1248
4830
      body =
1249
9660
          body.substitute(vars.begin(), vars.end(), subs.begin(), subs.end());
1250
4830
      body = Rewriter::rewrite(body);
1251
4830
      if (!qa.d_ipl.isNull())
1252
      {
1253
52
        qa.d_ipl = qa.d_ipl.substitute(
1254
26
            vars.begin(), vars.end(), subs.begin(), subs.end());
1255
      }
1256
4830
      Trace("var-elim-quant") << "Return " << body << std::endl;
1257
    }
1258
  }
1259
112935
  return body;
1260
}
1261
1262
448087
Node QuantifiersRewriter::computePrenex(Node q,
1263
                                        Node body,
1264
                                        std::unordered_set<Node>& args,
1265
                                        std::unordered_set<Node>& nargs,
1266
                                        bool pol,
1267
                                        bool prenexAgg)
1268
{
1269
448087
  NodeManager* nm = NodeManager::currentNM();
1270
448087
  Kind k = body.getKind();
1271
448087
  if (k == FORALL)
1272
  {
1273
14152
    if( ( pol || prenexAgg ) && ( options::prenexQuantUser() || body.getNumChildren()==2 ) ){
1274
2252
      std::vector< Node > terms;
1275
2252
      std::vector< Node > subs;
1276
1126
      BoundVarManager* bvm = nm->getBoundVarManager();
1277
      //for doing prenexing of same-signed quantifiers
1278
      //must rename each variable that already exists
1279
2885
      for (const Node& v : body[0])
1280
      {
1281
1759
        terms.push_back(v);
1282
3518
        TypeNode vt = v.getType();
1283
3518
        Node vv;
1284
1759
        if (!q.isNull())
1285
        {
1286
          // We cache based on the original quantified formula, the subformula
1287
          // that we are pulling variables from (body), and the variable v.
1288
          // The argument body is required since in rare cases, two subformulas
1289
          // may share the same variables. This is the case for define-fun
1290
          // or inferred substitutions that contain quantified formulas.
1291
3518
          Node cacheVal = BoundVarManager::getCacheValue(q, body, v);
1292
1759
          vv = bvm->mkBoundVar<QRewPrenexAttribute>(cacheVal, vt);
1293
        }
1294
        else
1295
        {
1296
          // not specific to a quantified formula, use normal
1297
          vv = nm->mkBoundVar(vt);
1298
        }
1299
1759
        subs.push_back(vv);
1300
      }
1301
1126
      if (pol)
1302
      {
1303
1126
        args.insert(subs.begin(), subs.end());
1304
      }
1305
      else
1306
      {
1307
        nargs.insert(subs.begin(), subs.end());
1308
      }
1309
2252
      Node newBody = body[1];
1310
1126
      newBody = newBody.substitute( terms.begin(), terms.end(), subs.begin(), subs.end() );
1311
1126
      return newBody;
1312
    }
1313
  //must remove structure
1314
  }
1315
433935
  else if (prenexAgg && k == ITE && body.getType().isBoolean())
1316
  {
1317
    Node nn = nm->mkNode(AND,
1318
                         nm->mkNode(OR, body[0].notNode(), body[1]),
1319
                         nm->mkNode(OR, body[0], body[2]));
1320
    return computePrenex(q, nn, args, nargs, pol, prenexAgg);
1321
  }
1322
433935
  else if (prenexAgg && k == EQUAL && body[0].getType().isBoolean())
1323
  {
1324
    Node nn = nm->mkNode(AND,
1325
                         nm->mkNode(OR, body[0].notNode(), body[1]),
1326
                         nm->mkNode(OR, body[0], body[1].notNode()));
1327
    return computePrenex(q, nn, args, nargs, pol, prenexAgg);
1328
433935
  }else if( body.getType().isBoolean() ){
1329
433935
    Assert(k != EXISTS);
1330
433935
    bool childrenChanged = false;
1331
866707
    std::vector< Node > newChildren;
1332
1325505
    for (size_t i = 0, nchild = body.getNumChildren(); i < nchild; i++)
1333
    {
1334
      bool newHasPol;
1335
      bool newPol;
1336
891570
      QuantPhaseReq::getPolarity( body, i, true, pol, newHasPol, newPol );
1337
1448184
      if (!newHasPol)
1338
      {
1339
556614
        newChildren.push_back( body[i] );
1340
556614
        continue;
1341
      }
1342
669912
      Node n = computePrenex(q, body[i], args, nargs, newPol, prenexAgg);
1343
334956
      newChildren.push_back(n);
1344
334956
      childrenChanged = n != body[i] || childrenChanged;
1345
    }
1346
433935
    if( childrenChanged ){
1347
1163
      if (k == NOT && newChildren[0].getKind() == NOT)
1348
      {
1349
        return newChildren[0][0];
1350
      }
1351
1163
      return nm->mkNode(k, newChildren);
1352
    }
1353
  }
1354
445798
  return body;
1355
}
1356
1357
Node QuantifiersRewriter::computePrenexAgg(Node n,
1358
                                           std::map<Node, Node>& visited)
1359
{
1360
  std::map< Node, Node >::iterator itv = visited.find( n );
1361
  if( itv!=visited.end() ){
1362
    return itv->second;
1363
  }
1364
  if (!expr::hasClosure(n))
1365
  {
1366
    // trivial
1367
    return n;
1368
  }
1369
  NodeManager* nm = NodeManager::currentNM();
1370
  Node ret = n;
1371
  if (n.getKind() == NOT)
1372
  {
1373
    ret = computePrenexAgg(n[0], visited).negate();
1374
  }
1375
  else if (n.getKind() == FORALL)
1376
  {
1377
    std::vector<Node> children;
1378
    children.push_back(computePrenexAgg(n[1], visited));
1379
    std::vector<Node> args;
1380
    args.insert(args.end(), n[0].begin(), n[0].end());
1381
    // for each child, strip top level quant
1382
    for (unsigned i = 0; i < children.size(); i++)
1383
    {
1384
      if (children[i].getKind() == FORALL)
1385
      {
1386
        args.insert(args.end(), children[i][0].begin(), children[i][0].end());
1387
        children[i] = children[i][1];
1388
      }
1389
    }
1390
    // keep the pattern
1391
    std::vector<Node> iplc;
1392
    if (n.getNumChildren() == 3)
1393
    {
1394
      iplc.insert(iplc.end(), n[2].begin(), n[2].end());
1395
    }
1396
    Node nb = children.size() == 1 ? children[0] : nm->mkNode(OR, children);
1397
    ret = mkForall(args, nb, iplc, true);
1398
  }
1399
  else
1400
  {
1401
    std::unordered_set<Node> argsSet;
1402
    std::unordered_set<Node> nargsSet;
1403
    Node q;
1404
    Node nn = computePrenex(q, n, argsSet, nargsSet, true, true);
1405
    Assert(n != nn || argsSet.empty());
1406
    Assert(n != nn || nargsSet.empty());
1407
    if (n != nn)
1408
    {
1409
      Node nnn = computePrenexAgg(nn, visited);
1410
      // merge prenex
1411
      if (nnn.getKind() == FORALL)
1412
      {
1413
        argsSet.insert(nnn[0].begin(), nnn[0].end());
1414
        nnn = nnn[1];
1415
        // pos polarity variables are inner
1416
        if (!argsSet.empty())
1417
        {
1418
          nnn = mkForall({argsSet.begin(), argsSet.end()}, nnn, true);
1419
        }
1420
        argsSet.clear();
1421
      }
1422
      else if (nnn.getKind() == NOT && nnn[0].getKind() == FORALL)
1423
      {
1424
        nargsSet.insert(nnn[0][0].begin(), nnn[0][0].end());
1425
        nnn = nnn[0][1].negate();
1426
      }
1427
      if (!nargsSet.empty())
1428
      {
1429
        nnn = mkForall({nargsSet.begin(), nargsSet.end()}, nnn.negate(), true)
1430
                  .negate();
1431
      }
1432
      if (!argsSet.empty())
1433
      {
1434
        nnn = mkForall({argsSet.begin(), argsSet.end()}, nnn, true);
1435
      }
1436
      ret = nnn;
1437
    }
1438
  }
1439
  visited[n] = ret;
1440
  return ret;
1441
}
1442
1443
46666
Node QuantifiersRewriter::computeSplit( std::vector< Node >& args, Node body, QAttributes& qa ) {
1444
46666
  Assert(body.getKind() == OR);
1445
46666
  size_t var_found_count = 0;
1446
46666
  size_t eqc_count = 0;
1447
46666
  size_t eqc_active = 0;
1448
93332
  std::map< Node, int > var_to_eqc;
1449
93332
  std::map< int, std::vector< Node > > eqc_to_var;
1450
93332
  std::map< int, std::vector< Node > > eqc_to_lit;
1451
1452
93332
  std::vector<Node> lits;
1453
1454
197713
  for( unsigned i=0; i<body.getNumChildren(); i++ ){
1455
    //get variables contained in the literal
1456
302094
    Node n = body[i];
1457
302094
    std::vector< Node > lit_args;
1458
151047
    computeArgVec( args, lit_args, n );
1459
151047
    if( lit_args.empty() ){
1460
1647
      lits.push_back( n );
1461
    }else {
1462
      //collect the equivalence classes this literal belongs to, and the new variables it contributes
1463
298800
      std::vector< int > eqcs;
1464
298800
      std::vector< Node > lit_new_args;
1465
      //for each variable in literal
1466
496088
      for( unsigned j=0; j<lit_args.size(); j++) {
1467
        //see if the variable has already been found
1468
346688
        if (var_to_eqc.find(lit_args[j])!=var_to_eqc.end()) {
1469
230197
          int eqc = var_to_eqc[lit_args[j]];
1470
230197
          if (std::find(eqcs.begin(), eqcs.end(), eqc)==eqcs.end()) {
1471
102466
            eqcs.push_back(eqc);
1472
          }
1473
        }else{
1474
116491
          var_found_count++;
1475
116491
          lit_new_args.push_back(lit_args[j]);
1476
        }
1477
      }
1478
149400
      if (eqcs.empty()) {
1479
53519
        eqcs.push_back(eqc_count);
1480
53519
        eqc_count++;
1481
53519
        eqc_active++;
1482
      }
1483
1484
149400
      int eqcz = eqcs[0];
1485
      //merge equivalence classes with eqcz
1486
155985
      for (unsigned j=1; j<eqcs.size(); j++) {
1487
6585
        int eqc = eqcs[j];
1488
        //move all variables from equivalence class
1489
31598
        for (unsigned k=0; k<eqc_to_var[eqc].size(); k++) {
1490
50026
          Node v = eqc_to_var[eqc][k];
1491
25013
          var_to_eqc[v] = eqcz;
1492
25013
          eqc_to_var[eqcz].push_back(v);
1493
        }
1494
6585
        eqc_to_var.erase(eqc);
1495
        //move all literals from equivalence class
1496
30245
        for (unsigned k=0; k<eqc_to_lit[eqc].size(); k++) {
1497
47320
          Node l = eqc_to_lit[eqc][k];
1498
23660
          eqc_to_lit[eqcz].push_back(l);
1499
        }
1500
6585
        eqc_to_lit.erase(eqc);
1501
6585
        eqc_active--;
1502
      }
1503
      //add variables to equivalence class
1504
265891
      for (unsigned j=0; j<lit_new_args.size(); j++) {
1505
116491
        var_to_eqc[lit_new_args[j]] = eqcz;
1506
116491
        eqc_to_var[eqcz].push_back(lit_new_args[j]);
1507
      }
1508
      //add literal to equivalence class
1509
149400
      eqc_to_lit[eqcz].push_back(n);
1510
    }
1511
  }
1512
46666
  if ( eqc_active>1 || !lits.empty() || var_to_eqc.size()!=args.size() ){
1513
605
    NodeManager* nm = NodeManager::currentNM();
1514
605
    Trace("clause-split-debug") << "Split quantified formula with body " << body << std::endl;
1515
605
    Trace("clause-split-debug") << "   Ground literals: " << std::endl;
1516
2252
    for( size_t i=0; i<lits.size(); i++) {
1517
1647
      Trace("clause-split-debug") << "      " << lits[i] << std::endl;
1518
    }
1519
605
    Trace("clause-split-debug") << std::endl;
1520
605
    Trace("clause-split-debug") << "Equivalence classes: " << std::endl;
1521
1478
    for (std::map< int, std::vector< Node > >::iterator it = eqc_to_lit.begin(); it != eqc_to_lit.end(); ++it ){
1522
873
      Trace("clause-split-debug") << "   Literals: " << std::endl;
1523
4082
      for (size_t i=0; i<it->second.size(); i++) {
1524
3209
        Trace("clause-split-debug") << "      " << it->second[i] << std::endl;
1525
      }
1526
873
      int eqc = it->first;
1527
873
      Trace("clause-split-debug") << "   Variables: " << std::endl;
1528
3715
      for (size_t i=0; i<eqc_to_var[eqc].size(); i++) {
1529
2842
        Trace("clause-split-debug") << "      " << eqc_to_var[eqc][i] << std::endl;
1530
      }
1531
873
      Trace("clause-split-debug") << std::endl;
1532
1746
      Node bvl = NodeManager::currentNM()->mkNode( BOUND_VAR_LIST, eqc_to_var[eqc]);
1533
      Node bd =
1534
1746
          it->second.size() == 1 ? it->second[0] : nm->mkNode(OR, it->second);
1535
1746
      Node fa = nm->mkNode(FORALL, bvl, bd);
1536
873
      lits.push_back(fa);
1537
    }
1538
605
    Assert(!lits.empty());
1539
1210
    Node nf = lits.size()==1 ? lits[0] : NodeManager::currentNM()->mkNode(OR,lits);
1540
605
    Trace("clause-split-debug") << "Made node : " << nf << std::endl;
1541
605
    return nf;
1542
  }else{
1543
46061
    return mkForAll( args, body, qa );
1544
  }
1545
}
1546
1547
114765
Node QuantifiersRewriter::mkForAll(const std::vector<Node>& args,
1548
                                   Node body,
1549
                                   QAttributes& qa)
1550
{
1551
114765
  if (args.empty())
1552
  {
1553
222
    return body;
1554
  }
1555
114543
  NodeManager* nm = NodeManager::currentNM();
1556
229086
  std::vector<Node> children;
1557
114543
  children.push_back(nm->mkNode(kind::BOUND_VAR_LIST, args));
1558
114543
  children.push_back(body);
1559
114543
  if (!qa.d_ipl.isNull())
1560
  {
1561
14728
    children.push_back(qa.d_ipl);
1562
  }
1563
114543
  return nm->mkNode(kind::FORALL, children);
1564
}
1565
1566
Node QuantifiersRewriter::mkForall(const std::vector<Node>& args,
1567
                                   Node body,
1568
                                   bool marked)
1569
{
1570
  std::vector< Node > iplc;
1571
  return mkForall( args, body, iplc, marked );
1572
}
1573
1574
Node QuantifiersRewriter::mkForall(const std::vector<Node>& args,
1575
                                   Node body,
1576
                                   std::vector<Node>& iplc,
1577
                                   bool marked)
1578
{
1579
  if (args.empty())
1580
  {
1581
    return body;
1582
  }
1583
  NodeManager* nm = NodeManager::currentNM();
1584
  std::vector<Node> children;
1585
  children.push_back(nm->mkNode(kind::BOUND_VAR_LIST, args));
1586
  children.push_back(body);
1587
  if (marked)
1588
  {
1589
    SkolemManager* sm = nm->getSkolemManager();
1590
    Node avar = sm->mkDummySkolem("id", nm->booleanType());
1591
    QuantIdNumAttribute ida;
1592
    avar.setAttribute(ida, 0);
1593
    iplc.push_back(nm->mkNode(kind::INST_ATTRIBUTE, avar));
1594
  }
1595
  if (!iplc.empty())
1596
  {
1597
    children.push_back(nm->mkNode(kind::INST_PATTERN_LIST, iplc));
1598
  }
1599
  return nm->mkNode(kind::FORALL, children);
1600
}
1601
1602
//computes miniscoping, also eliminates variables that do not occur free in body
1603
116120
Node QuantifiersRewriter::computeMiniscoping(Node q, QAttributes& qa)
1604
{
1605
116120
  NodeManager* nm = NodeManager::currentNM();
1606
232240
  std::vector<Node> args(q[0].begin(), q[0].end());
1607
232240
  Node body = q[1];
1608
116120
  if( body.getKind()==FORALL ){
1609
    //combine prenex
1610
32
    std::vector< Node > newArgs;
1611
16
    newArgs.insert(newArgs.end(), q[0].begin(), q[0].end());
1612
33
    for( unsigned i=0; i<body[0].getNumChildren(); i++ ){
1613
17
      newArgs.push_back( body[0][i] );
1614
    }
1615
16
    return mkForAll( newArgs, body[1], qa );
1616
116104
  }else if( body.getKind()==AND ){
1617
    // aggressive miniscoping implies that structural miniscoping should
1618
    // be applied first
1619
1408
    if (options::miniscopeQuant() || options::aggressiveMiniscopeQuant())
1620
    {
1621
764
      BoundVarManager* bvm = nm->getBoundVarManager();
1622
      // Break apart the quantifed formula
1623
      // forall x. P1 ^ ... ^ Pn ---> forall x. P1 ^ ... ^ forall x. Pn
1624
1528
      NodeBuilder t(kind::AND);
1625
1528
      std::vector<Node> argsc;
1626
4120
      for (size_t i = 0, nchild = body.getNumChildren(); i < nchild; i++)
1627
      {
1628
3356
        if (argsc.empty())
1629
        {
1630
          // If not done so, we must create fresh copy of args. This is to
1631
          // ensure that quantified formulas do not reuse variables.
1632
7119
          for (const Node& v : q[0])
1633
          {
1634
10526
            TypeNode vt = v.getType();
1635
10526
            Node cacheVal = BoundVarManager::getCacheValue(q, v, i);
1636
10526
            Node vv = bvm->mkBoundVar<QRewMiniscopeAttribute>(cacheVal, vt);
1637
5263
            argsc.push_back(vv);
1638
          }
1639
        }
1640
6712
        Node b = body[i];
1641
        Node bodyc =
1642
6712
            b.substitute(args.begin(), args.end(), argsc.begin(), argsc.end());
1643
3356
        if (b == bodyc)
1644
        {
1645
          // Did not contain variables in args, thus it is ground. Since we did
1646
          // not use them, we keep the variables argsc for the next child.
1647
1539
          t << b;
1648
        }
1649
        else
1650
        {
1651
          // make the miniscoped quantified formula
1652
3634
          Node cbvl = nm->mkNode(BOUND_VAR_LIST, argsc);
1653
3634
          Node qq = nm->mkNode(FORALL, cbvl, bodyc);
1654
1817
          t << qq;
1655
          // We used argsc, clear so we will construct a fresh copy above.
1656
1817
          argsc.clear();
1657
        }
1658
      }
1659
1528
      Node retVal = t;
1660
764
      return retVal;
1661
    }
1662
114696
  }else if( body.getKind()==OR ){
1663
47894
    if( options::quantSplit() ){
1664
      //splitting subsumes free variable miniscoping, apply it with higher priority
1665
46666
      return computeSplit( args, body, qa );
1666
    }
1667
2456
    else if (options::miniscopeQuantFreeVar()
1668
1228
             || options::aggressiveMiniscopeQuant())
1669
    {
1670
      // aggressive miniscoping implies that free variable miniscoping should
1671
      // be applied first
1672
4
      Node newBody = body;
1673
4
      NodeBuilder body_split(kind::OR);
1674
4
      NodeBuilder tb(kind::OR);
1675
12
      for (const Node& trm : body)
1676
      {
1677
8
        if (expr::hasSubterm(trm, args))
1678
        {
1679
4
          tb << trm;
1680
        }else{
1681
4
          body_split << trm;
1682
        }
1683
      }
1684
4
      if( tb.getNumChildren()==0 ){
1685
        return body_split;
1686
4
      }else if( body_split.getNumChildren()>0 ){
1687
4
        newBody = tb.getNumChildren()==1 ? tb.getChild( 0 ) : tb;
1688
8
        std::vector< Node > activeArgs;
1689
4
        computeArgVec2( args, activeArgs, newBody, qa.d_ipl );
1690
4
        body_split << mkForAll( activeArgs, newBody, qa );
1691
4
        return body_split.getNumChildren()==1 ? body_split.getChild( 0 ) : body_split;
1692
      }
1693
    }
1694
66802
  }else if( body.getKind()==NOT ){
1695
14996
    Assert(isLiteral(body[0]));
1696
  }
1697
  //remove variables that don't occur
1698
137340
  std::vector< Node > activeArgs;
1699
68670
  computeArgVec2( args, activeArgs, body, qa.d_ipl );
1700
68670
  return mkForAll( activeArgs, body, qa );
1701
}
1702
1703
14
Node QuantifiersRewriter::computeAggressiveMiniscoping( std::vector< Node >& args, Node body ){
1704
28
  std::map<Node, std::vector<Node> > varLits;
1705
28
  std::map<Node, std::vector<Node> > litVars;
1706
14
  if (body.getKind() == OR) {
1707
    Trace("ag-miniscope") << "compute aggressive miniscoping on " << body << std::endl;
1708
    for (size_t i = 0; i < body.getNumChildren(); i++) {
1709
      std::vector<Node> activeArgs;
1710
      computeArgVec(args, activeArgs, body[i]);
1711
      for (unsigned j = 0; j < activeArgs.size(); j++) {
1712
        varLits[activeArgs[j]].push_back(body[i]);
1713
      }
1714
      std::vector<Node>& lit_body_i = litVars[body[i]];
1715
      std::vector<Node>::iterator lit_body_i_begin = lit_body_i.begin();
1716
      std::vector<Node>::const_iterator active_begin = activeArgs.begin();
1717
      std::vector<Node>::const_iterator active_end = activeArgs.end();
1718
      lit_body_i.insert(lit_body_i_begin, active_begin, active_end);
1719
    }
1720
    //find the variable in the least number of literals
1721
    Node bestVar;
1722
    for( std::map< Node, std::vector<Node> >::iterator it = varLits.begin(); it != varLits.end(); ++it ){
1723
      if( bestVar.isNull() || varLits[bestVar].size()>it->second.size() ){
1724
        bestVar = it->first;
1725
      }
1726
    }
1727
    Trace("ag-miniscope-debug") << "Best variable " << bestVar << " occurs in " << varLits[bestVar].size() << "/ " << body.getNumChildren() << " literals." << std::endl;
1728
    if( !bestVar.isNull() && varLits[bestVar].size()<body.getNumChildren() ){
1729
      //we can miniscope
1730
      Trace("ag-miniscope") << "Miniscope on " << bestVar << std::endl;
1731
      //make the bodies
1732
      std::vector<Node> qlit1;
1733
      qlit1.insert( qlit1.begin(), varLits[bestVar].begin(), varLits[bestVar].end() );
1734
      std::vector<Node> qlitt;
1735
      //for all literals not containing bestVar
1736
      for( size_t i=0; i<body.getNumChildren(); i++ ){
1737
        if( std::find( qlit1.begin(), qlit1.end(), body[i] )==qlit1.end() ){
1738
          qlitt.push_back( body[i] );
1739
        }
1740
      }
1741
      //make the variable lists
1742
      std::vector<Node> qvl1;
1743
      std::vector<Node> qvl2;
1744
      std::vector<Node> qvsh;
1745
      for( unsigned i=0; i<args.size(); i++ ){
1746
        bool found1 = false;
1747
        bool found2 = false;
1748
        for( size_t j=0; j<varLits[args[i]].size(); j++ ){
1749
          if( !found1 && std::find( qlit1.begin(), qlit1.end(), varLits[args[i]][j] )!=qlit1.end() ){
1750
            found1 = true;
1751
          }else if( !found2 && std::find( qlitt.begin(), qlitt.end(), varLits[args[i]][j] )!=qlitt.end() ){
1752
            found2 = true;
1753
          }
1754
          if( found1 && found2 ){
1755
            break;
1756
          }
1757
        }
1758
        if( found1 ){
1759
          if( found2 ){
1760
            qvsh.push_back( args[i] );
1761
          }else{
1762
            qvl1.push_back( args[i] );
1763
          }
1764
        }else{
1765
          Assert(found2);
1766
          qvl2.push_back( args[i] );
1767
        }
1768
      }
1769
      Assert(!qvl1.empty());
1770
      //check for literals that only contain shared variables
1771
      std::vector<Node> qlitsh;
1772
      std::vector<Node> qlit2;
1773
      for( size_t i=0; i<qlitt.size(); i++ ){
1774
        bool hasVar2 = false;
1775
        for( size_t j=0; j<litVars[qlitt[i]].size(); j++ ){
1776
          if( std::find( qvl2.begin(), qvl2.end(), litVars[qlitt[i]][j] )!=qvl2.end() ){
1777
            hasVar2 = true;
1778
            break;
1779
          }
1780
        }
1781
        if( hasVar2 ){
1782
          qlit2.push_back( qlitt[i] );
1783
        }else{
1784
          qlitsh.push_back( qlitt[i] );
1785
        }
1786
      }
1787
      varLits.clear();
1788
      litVars.clear();
1789
      Trace("ag-miniscope-debug") << "Split into literals : " << qlit1.size() << " / " << qlit2.size() << " / " << qlitsh.size();
1790
      Trace("ag-miniscope-debug") << ", variables : " << qvl1.size() << " / " << qvl2.size() << " / " << qvsh.size() << std::endl;
1791
      Node n1 = qlit1.size()==1 ? qlit1[0] : NodeManager::currentNM()->mkNode( OR, qlit1 );
1792
      n1 = computeAggressiveMiniscoping( qvl1, n1 );
1793
      qlitsh.push_back( n1 );
1794
      if( !qlit2.empty() ){
1795
        Node n2 = qlit2.size()==1 ? qlit2[0] : NodeManager::currentNM()->mkNode( OR, qlit2 );
1796
        n2 = computeAggressiveMiniscoping( qvl2, n2 );
1797
        qlitsh.push_back( n2 );
1798
      }
1799
      Node n = NodeManager::currentNM()->mkNode( OR, qlitsh );
1800
      if( !qvsh.empty() ){
1801
        Node bvl = NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST, qvsh);
1802
        n = NodeManager::currentNM()->mkNode( FORALL, bvl, n );
1803
      }
1804
      Trace("ag-miniscope") << "Return " << n << " for " << body << std::endl;
1805
      return n;
1806
    }
1807
  }
1808
28
  QAttributes qa;
1809
14
  return mkForAll( args, body, qa );
1810
}
1811
1812
951221
bool QuantifiersRewriter::doOperation(Node q,
1813
                                      RewriteStep computeOption,
1814
                                      QAttributes& qa)
1815
{
1816
  bool is_strict_trigger =
1817
951221
      qa.d_hasPattern
1818
951221
      && options::userPatternsQuant() == options::UserPatMode::STRICT;
1819
951221
  bool is_std = qa.isStandard() && !is_strict_trigger;
1820
951221
  if (computeOption == COMPUTE_ELIM_SYMBOLS)
1821
  {
1822
132399
    return true;
1823
  }
1824
818822
  else if (computeOption == COMPUTE_MINISCOPING)
1825
  {
1826
119240
    return is_std;
1827
  }
1828
699582
  else if (computeOption == COMPUTE_AGGRESSIVE_MINISCOPING)
1829
  {
1830
117448
    return options::aggressiveMiniscopeQuant() && is_std;
1831
  }
1832
582134
  else if (computeOption == COMPUTE_EXT_REWRITE)
1833
  {
1834
117448
    return options::extRewriteQuant();
1835
  }
1836
464686
  else if (computeOption == COMPUTE_PROCESS_TERMS)
1837
  {
1838
117436
    return is_std && options::iteLiftQuant() != options::IteLiftQuantMode::NONE;
1839
  }
1840
347250
  else if (computeOption == COMPUTE_COND_SPLIT)
1841
  {
1842
228032
    return (options::iteDtTesterSplitQuant() || options::condVarSplitQuant())
1843
228390
           && !is_strict_trigger;
1844
  }
1845
233055
  else if (computeOption == COMPUTE_PRENEX)
1846
  {
1847
117000
    return options::prenexQuant() != options::PrenexQuantMode::NONE
1848
117000
           && !options::aggressiveMiniscopeQuant() && is_std;
1849
  }
1850
116055
  else if (computeOption == COMPUTE_VAR_ELIMINATION)
1851
  {
1852
116055
    return (options::varElimQuant() || options::dtVarExpandQuant()) && is_std;
1853
  }
1854
  else
1855
  {
1856
    return false;
1857
  }
1858
}
1859
1860
//general method for computing various rewrites
1861
703139
Node QuantifiersRewriter::computeOperation(Node f,
1862
                                           RewriteStep computeOption,
1863
                                           QAttributes& qa)
1864
{
1865
703139
  Trace("quantifiers-rewrite-debug") << "Compute operation " << computeOption << " on " << f << " " << qa.d_qid_num << std::endl;
1866
703139
  if (computeOption == COMPUTE_MINISCOPING)
1867
  {
1868
116120
    if (options::prenexQuant() == options::PrenexQuantMode::NORMAL)
1869
    {
1870
      if( !qa.d_qid_num.isNull() ){
1871
        //already processed this, return self
1872
        return f;
1873
      }
1874
    }
1875
    //return directly
1876
116120
    return computeMiniscoping(f, qa);
1877
  }
1878
1174038
  std::vector<Node> args(f[0].begin(), f[0].end());
1879
1174038
  Node n = f[1];
1880
587019
  if (computeOption == COMPUTE_ELIM_SYMBOLS)
1881
  {
1882
132399
    n = computeElimSymbols(n);
1883
454620
  }else if( computeOption==COMPUTE_AGGRESSIVE_MINISCOPING ){
1884
14
    return computeAggressiveMiniscoping( args, n );
1885
  }
1886
454606
  else if (computeOption == COMPUTE_EXT_REWRITE)
1887
  {
1888
29
    return computeExtendedRewrite(f);
1889
  }
1890
454577
  else if (computeOption == COMPUTE_PROCESS_TERMS)
1891
  {
1892
228632
    std::vector< Node > new_conds;
1893
114316
    n = computeProcessTerms( n, args, new_conds, f, qa );
1894
114316
    if( !new_conds.empty() ){
1895
      new_conds.push_back( n );
1896
      n = NodeManager::currentNM()->mkNode( OR, new_conds );
1897
    }
1898
  }
1899
340261
  else if (computeOption == COMPUTE_COND_SPLIT)
1900
  {
1901
114195
    n = computeCondSplit(n, args, qa);
1902
  }
1903
226066
  else if (computeOption == COMPUTE_PRENEX)
1904
  {
1905
113131
    if (options::prenexQuant() == options::PrenexQuantMode::NORMAL)
1906
    {
1907
      //will rewrite at preprocess time
1908
      return f;
1909
    }
1910
    else
1911
    {
1912
226262
      std::unordered_set<Node> argsSet, nargsSet;
1913
113131
      n = computePrenex(f, n, argsSet, nargsSet, true, false);
1914
113131
      Assert(nargsSet.empty());
1915
113131
      args.insert(args.end(), argsSet.begin(), argsSet.end());
1916
    }
1917
  }
1918
112935
  else if (computeOption == COMPUTE_VAR_ELIMINATION)
1919
  {
1920
112935
    n = computeVarElimination( n, args, qa );
1921
  }
1922
586976
  Trace("quantifiers-rewrite-debug") << "Compute Operation: return " << n << ", " << args.size() << std::endl;
1923
586976
  if( f[1]==n && args.size()==f[0].getNumChildren() ){
1924
570401
    return f;
1925
  }else{
1926
16575
    if( args.empty() ){
1927
717
      return n;
1928
    }else{
1929
31716
      std::vector< Node > children;
1930
15858
      children.push_back( NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST, args ) );
1931
15858
      children.push_back( n );
1932
15858
      if( !qa.d_ipl.isNull() && args.size()==f[0].getNumChildren() ){
1933
2341
        children.push_back( qa.d_ipl );
1934
      }
1935
15858
      return NodeManager::currentNM()->mkNode(kind::FORALL, children );
1936
    }
1937
  }
1938
}
1939
1940
bool QuantifiersRewriter::isPrenexNormalForm( Node n ) {
1941
  if( n.getKind()==FORALL ){
1942
    return n[1].getKind()!=FORALL && isPrenexNormalForm( n[1] );
1943
  }else if( n.getKind()==NOT ){
1944
    return n[0].getKind()!=NOT && isPrenexNormalForm( n[0] );
1945
  }else{
1946
    return !expr::hasClosure(n);
1947
  }
1948
}
1949
1950
783
Node QuantifiersRewriter::preSkolemizeQuantifiers( Node n, bool polarity, std::vector< TypeNode >& fvTypes, std::vector< TNode >& fvs ){
1951
783
  Trace("pre-sk") << "Pre-skolem " << n << " " << polarity << " " << fvs.size() << endl;
1952
783
  if( n.getKind()==kind::NOT ){
1953
252
    Node nn = preSkolemizeQuantifiers( n[0], !polarity, fvTypes, fvs );
1954
126
    return nn.negate();
1955
657
  }else if( n.getKind()==kind::FORALL ){
1956
182
    if (n.getNumChildren() == 3)
1957
    {
1958
      // Do not pre-skolemize quantified formulas with three children.
1959
      // This includes non-standard quantified formulas
1960
      // like recursive function definitions, or sygus conjectures, and
1961
      // quantified formulas with triggers.
1962
90
      return n;
1963
    }
1964
92
    else if (polarity)
1965
    {
1966
68
      if( options::preSkolemQuant() && options::preSkolemQuantNested() ){
1967
100
        vector< Node > children;
1968
50
        children.push_back( n[0] );
1969
        //add children to current scope
1970
100
        std::vector< TypeNode > fvt;
1971
100
        std::vector< TNode > fvss;
1972
50
        fvt.insert( fvt.begin(), fvTypes.begin(), fvTypes.end() );
1973
50
        fvss.insert( fvss.begin(), fvs.begin(), fvs.end() );
1974
114
        for( int i=0; i<(int)n[0].getNumChildren(); i++ ){
1975
64
          fvt.push_back( n[0][i].getType() );
1976
64
          fvss.push_back( n[0][i] );
1977
        }
1978
        //process body
1979
50
        children.push_back( preSkolemizeQuantifiers( n[1], polarity, fvt, fvss ) );
1980
        //return processed quantifier
1981
50
        return NodeManager::currentNM()->mkNode( kind::FORALL, children );
1982
      }
1983
    }else{
1984
      //process body
1985
48
      Node nn = preSkolemizeQuantifiers( n[1], polarity, fvTypes, fvs );
1986
48
      std::vector< Node > sk;
1987
48
      Node sub;
1988
48
      std::vector< unsigned > sub_vars;
1989
      //return skolemized body
1990
      return Skolemize::mkSkolemizedBody(
1991
24
          n, nn, fvTypes, fvs, sk, sub, sub_vars);
1992
    }
1993
  }else{
1994
    //check if it contains a quantifier as a subterm
1995
    //if so, we will write this node
1996
475
    if (expr::hasClosure(n))
1997
    {
1998
74
      if( ( n.getKind()==kind::ITE && n.getType().isBoolean() ) || ( n.getKind()==kind::EQUAL && n[0].getType().isBoolean() ) ){
1999
14
        if( options::preSkolemQuantAgg() ){
2000
28
          Node nn;
2001
          //must remove structure
2002
14
          if( n.getKind()==kind::ITE ){
2003
            nn = NodeManager::currentNM()->mkNode( kind::AND,
2004
                  NodeManager::currentNM()->mkNode( kind::OR, n[0].notNode(), n[1] ),
2005
                  NodeManager::currentNM()->mkNode( kind::OR, n[0], n[2] ) );
2006
14
          }else if( n.getKind()==kind::EQUAL ){
2007
56
            nn = NodeManager::currentNM()->mkNode( kind::AND,
2008
28
                  NodeManager::currentNM()->mkNode( kind::OR, n[0].notNode(), n.getKind()==kind::XOR ? n[1].notNode() : n[1] ),
2009
28
                  NodeManager::currentNM()->mkNode( kind::OR, n[0], n.getKind()==kind::XOR ? n[1] : n[1].notNode() ) );
2010
          }
2011
14
          return preSkolemizeQuantifiers( nn, polarity, fvTypes, fvs );
2012
        }
2013
60
      }else if( n.getKind()==kind::AND || n.getKind()==kind::OR ){
2014
116
        vector< Node > children;
2015
174
        for( int i=0; i<(int)n.getNumChildren(); i++ ){
2016
116
          children.push_back( preSkolemizeQuantifiers( n[i], polarity, fvTypes, fvs ) );
2017
        }
2018
58
        return NodeManager::currentNM()->mkNode( n.getKind(), children );
2019
      }
2020
    }
2021
  }
2022
421
  return n;
2023
}
2024
2025
92083
TrustNode QuantifiersRewriter::preprocess(Node n, bool isInst)
2026
{
2027
184166
  Node prev = n;
2028
2029
92083
  if( options::preSkolemQuant() ){
2030
515
    if( !isInst || !options::preSkolemQuantNested() ){
2031
453
      Trace("quantifiers-preprocess-debug") << "Pre-skolemize " << n << "..." << std::endl;
2032
      //apply pre-skolemization to existential quantifiers
2033
906
      std::vector< TypeNode > fvTypes;
2034
906
      std::vector< TNode > fvs;
2035
453
      n = preSkolemizeQuantifiers( prev, true, fvTypes, fvs );
2036
    }
2037
  }
2038
  //pull all quantifiers globally
2039
92083
  if (options::prenexQuant() == options::PrenexQuantMode::NORMAL)
2040
  {
2041
    Trace("quantifiers-prenex") << "Prenexing : " << n << std::endl;
2042
    std::map<Node, Node> visited;
2043
    n = computePrenexAgg(n, visited);
2044
    n = Rewriter::rewrite( n );
2045
    Trace("quantifiers-prenex") << "Prenexing returned : " << n << std::endl;
2046
    //Assert( isPrenexNormalForm( n ) );
2047
  }
2048
92083
  if( n!=prev ){
2049
16
    Trace("quantifiers-preprocess") << "Preprocess " << prev << std::endl;
2050
16
    Trace("quantifiers-preprocess") << "..returned " << n << std::endl;
2051
16
    return TrustNode::mkTrustRewrite(prev, n, nullptr);
2052
  }
2053
92067
  return TrustNode::null();
2054
}
2055
2056
}  // namespace quantifiers
2057
}  // namespace theory
2058
29358
}  // namespace cvc5