GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/quant_conflict_find.cpp Lines: 1158 1393 83.1 %
Date: 2021-11-07 Branches: 2453 5389 45.5 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Tim King, Andres Noetzli
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
 * Implements conflict-based instantiation (Reynolds et al FMCAD 2014).
14
 */
15
16
#include "theory/quantifiers/quant_conflict_find.h"
17
18
#include "base/configuration.h"
19
#include "expr/node_algorithm.h"
20
#include "options/quantifiers_options.h"
21
#include "options/theory_options.h"
22
#include "options/uf_options.h"
23
#include "smt/smt_statistics_registry.h"
24
#include "theory/quantifiers/ematching/trigger_term_info.h"
25
#include "theory/quantifiers/first_order_model.h"
26
#include "theory/quantifiers/instantiate.h"
27
#include "theory/quantifiers/quant_util.h"
28
#include "theory/quantifiers/term_database.h"
29
#include "theory/quantifiers/term_util.h"
30
#include "theory/rewriter.h"
31
#include "util/rational.h"
32
33
using namespace cvc5::kind;
34
using namespace std;
35
36
namespace cvc5 {
37
namespace theory {
38
namespace quantifiers {
39
40
22553
QuantInfo::QuantInfo()
41
22553
    : d_unassigned_nvar(0), d_una_index(0), d_parent(nullptr), d_mg(nullptr)
42
{
43
22553
}
44
45
45106
QuantInfo::~QuantInfo() {
46
22553
  delete d_mg;
47
104422
  for(std::map< int, MatchGen * >::iterator i = d_var_mg.begin(),
48
22553
          iend=d_var_mg.end(); i != iend; ++i) {
49
81869
    MatchGen* currentMatchGenerator = (*i).second;
50
81869
    delete currentMatchGenerator;
51
  }
52
22553
  d_var_mg.clear();
53
22553
}
54
55
22553
void QuantInfo::initialize( QuantConflictFind * p, Node q, Node qn ) {
56
22553
  d_parent = p;
57
22553
  d_q = q;
58
22553
  d_extra_var.clear();
59
75733
  for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
60
53180
    d_match.push_back( TNode::null() );
61
53180
    d_match_term.push_back( TNode::null() );
62
  }
63
64
  //register the variables
65
75733
  for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
66
53180
    d_var_num[q[0][i]] = i;
67
53180
    d_vars.push_back( q[0][i] );
68
53180
    d_var_types.push_back( q[0][i].getType() );
69
  }
70
71
22553
  registerNode( qn, true, true );
72
73
74
22553
  Trace("qcf-qregister") << "- Make match gen structure..." << std::endl;
75
22553
  d_mg = new MatchGen( this, qn );
76
77
22553
  if( d_mg->isValid() ){
78
    /*
79
    for( unsigned j=0; j<q[0].getNumChildren(); j++ ){
80
      if( d_inMatchConstraint.find( q[0][j] )==d_inMatchConstraint.end() ){
81
        Trace("qcf-invalid") << "QCF invalid : variable " << q[0][j] << " does not exist in a matching constraint." << std::endl;
82
        d_mg->setInvalid();
83
        break;
84
      }
85
    }
86
    */
87
104987
    for( unsigned j=q[0].getNumChildren(); j<d_vars.size(); j++ ){
88
87335
      if( d_vars[j].getKind()!=BOUND_VARIABLE ){
89
81869
        d_var_mg[j] = NULL;
90
81869
        bool is_tsym = false;
91
81869
        if( !MatchGen::isHandledUfTerm( d_vars[j] ) && d_vars[j].getKind()!=ITE ){
92
836
          is_tsym = true;
93
836
          d_tsym_vars.push_back( j );
94
        }
95
81869
        if( !is_tsym || options::qcfTConstraint() ){
96
81412
          d_var_mg[j] = new MatchGen( this, d_vars[j], true );
97
        }
98
81869
        if( !d_var_mg[j] || !d_var_mg[j]->isValid() ){
99
1614
          Trace("qcf-invalid") << "QCF invalid : cannot match for " << d_vars[j] << std::endl;
100
1614
          d_mg->setInvalid();
101
1614
          break;
102
        }else{
103
160510
          std::vector< int > bvars;
104
80255
          d_var_mg[j]->determineVariableOrder( this, bvars );
105
        }
106
      }
107
    }
108
19266
    if( d_mg->isValid() ){
109
35304
      std::vector< int > bvars;
110
17652
      d_mg->determineVariableOrder( this, bvars );
111
    }
112
  }else{
113
3287
    Trace("qcf-invalid") << "QCF invalid : body of formula cannot be processed." << std::endl;
114
  }
115
22553
  Trace("qcf-qregister-summary") << "QCF register : " << ( d_mg->isValid() ? "VALID " : "INVALID" ) << " : " << q << std::endl;
116
117
22553
  if( d_mg->isValid() && options::qcfEagerCheckRd() ){
118
    //optimization : record variable argument positions for terms that must be matched
119
35304
    std::vector< TNode > vars;
120
    //TODO: revisit this, makes QCF faster, but misses conflicts due to caring about paths that may not be relevant (starExec jobs 14136/14137)
121
17652
    if( options::qcfSkipRd() ){
122
      for( unsigned j=q[0].getNumChildren(); j<d_vars.size(); j++ ){
123
        vars.push_back( d_vars[j] );
124
      }
125
    }else{
126
      //get all variables that are always relevant
127
35304
      std::map< TNode, bool > visited;
128
17652
      getPropagateVars( p, vars, q[1], false, visited );
129
    }
130
100678
    for( unsigned j=0; j<vars.size(); j++ ){
131
166052
      Node v = vars[j];
132
166052
      TNode f = p->getTermDatabase()->getMatchOperator( v );
133
83026
      if( !f.isNull() ){
134
50155
        Trace("qcf-opt") << "Record variable argument positions in " << v << ", op=" << f << "..." << std::endl;
135
162455
        for( unsigned k=0; k<v.getNumChildren(); k++ ){
136
224600
          Node n = v[k];
137
112300
          std::map< TNode, int >::iterator itv = d_var_num.find( n );
138
112300
          if( itv!=d_var_num.end() ){
139
98776
            Trace("qcf-opt") << "  arg " << k << " is var #" << itv->second << std::endl;
140
98776
            if( std::find( d_var_rel_dom[itv->second][f].begin(), d_var_rel_dom[itv->second][f].end(), k )==d_var_rel_dom[itv->second][f].end() ){
141
93462
              d_var_rel_dom[itv->second][f].push_back( k );
142
            }
143
          }
144
        }
145
      }
146
    }
147
  }
148
22553
}
149
150
210636
void QuantInfo::getPropagateVars( QuantConflictFind * p, std::vector< TNode >& vars, TNode n, bool pol, std::map< TNode, bool >& visited ){
151
210636
  std::map< TNode, bool >::iterator itv = visited.find( n );
152
210636
  if( itv==visited.end() ){
153
153714
    visited[n] = true;
154
153714
    bool rec = true;
155
153714
    bool newPol = pol;
156
153714
    if( d_var_num.find( n )!=d_var_num.end() ){
157
83026
      Assert(std::find(vars.begin(), vars.end(), n) == vars.end());
158
83026
      vars.push_back( n );
159
166052
      TNode f = p->getTermDatabase()->getMatchOperator( n );
160
83026
      if( !f.isNull() ){
161
50155
        if( std::find( p->d_func_rel_dom[f].begin(), p->d_func_rel_dom[f].end(), d_q )==p->d_func_rel_dom[f].end() ){
162
39029
          p->d_func_rel_dom[f].push_back( d_q );
163
        }
164
      }
165
70688
    }else if( MatchGen::isHandledBoolConnective( n ) ){
166
28632
      Assert(n.getKind() != IMPLIES);
167
28632
      QuantPhaseReq::getEntailPolarity( n, 0, true, pol, rec, newPol );
168
    }
169
153714
    Trace("qcf-opt-debug") << "getPropagateVars " << n << ", pol = " << pol << ", rec = " << rec << std::endl;
170
153714
    if( rec ){
171
340449
      for( unsigned i=0; i<n.getNumChildren(); i++ ){
172
192984
        getPropagateVars( p, vars, n[i], pol, visited );
173
      }
174
    }
175
  }
176
210636
}
177
178
2104886
bool QuantInfo::isBaseMatchComplete() {
179
2104886
  return d_vars_set.size()==(d_q[0].getNumChildren()+d_extra_var.size());
180
}
181
182
118320
void QuantInfo::registerNode( Node n, bool hasPol, bool pol, bool beneathQuant ) {
183
118320
  Trace("qcf-qregister-debug2") << "Register : " << n << std::endl;
184
118320
  if( n.getKind()==FORALL ){
185
4480
    registerNode( n[1], hasPol, pol, true );
186
  }else{
187
113840
    if( !MatchGen::isHandledBoolConnective( n ) ){
188
62968
      if (expr::hasBoundVar(n))
189
      {
190
        // literals
191
62806
        if (n.getKind() == EQUAL)
192
        {
193
102477
          for (unsigned i = 0; i < n.getNumChildren(); i++)
194
          {
195
68318
            flatten(n[i], beneathQuant);
196
          }
197
        }
198
28647
        else if (MatchGen::isHandledUfTerm(n))
199
        {
200
19387
          flatten(n, beneathQuant);
201
        }
202
9260
        else if (n.getKind() == ITE)
203
        {
204
4140
          for (unsigned i = 1; i <= 2; i++)
205
          {
206
2760
            flatten(n[i], beneathQuant);
207
          }
208
1380
          registerNode(n[0], false, pol, beneathQuant);
209
        }
210
7880
        else if (options::qcfTConstraint())
211
        {
212
          // a theory-specific predicate
213
1014
          for (unsigned i = 0; i < n.getNumChildren(); i++)
214
          {
215
676
            flatten(n[i], beneathQuant);
216
          }
217
        }
218
      }
219
    }else{
220
139399
      for( unsigned i=0; i<n.getNumChildren(); i++ ){
221
        bool newHasPol;
222
        bool newPol;
223
88527
        QuantPhaseReq::getPolarity( n, i, hasPol, pol, newHasPol, newPol );
224
        //QcfNode * qcfc = new QcfNode( d_c );
225
        //qcfc->d_parent = qcf;
226
        //qcf->d_child[i] = qcfc;
227
88527
        registerNode( n[i], newHasPol, newPol, beneathQuant );
228
      }
229
    }
230
  }
231
118320
}
232
233
293605
void QuantInfo::flatten( Node n, bool beneathQuant ) {
234
293605
  Trace("qcf-qregister-debug2") << "Flatten : " << n << std::endl;
235
293605
  if (expr::hasBoundVar(n))
236
  {
237
247481
    if( n.getKind()==BOUND_VARIABLE ){
238
128452
      d_inMatchConstraint[n] = true;
239
    }
240
247481
    if( d_var_num.find( n )==d_var_num.end() ){
241
106092
      Trace("qcf-qregister-debug2") << "Add FLATTEN VAR : " << n << std::endl;
242
106092
      d_var_num[n] = d_vars.size();
243
106092
      d_vars.push_back( n );
244
106092
      d_var_types.push_back( n.getType() );
245
106092
      d_match.push_back( TNode::null() );
246
106092
      d_match_term.push_back( TNode::null() );
247
106092
      if( n.getKind()==ITE ){
248
1380
        registerNode( n, false, false );
249
104712
      }else if( n.getKind()==BOUND_VARIABLE ){
250
6421
        d_extra_var.push_back( n );
251
      }else{
252
300755
        for( unsigned i=0; i<n.getNumChildren(); i++ ){
253
202464
          flatten( n[i], beneathQuant );
254
        }
255
      }
256
    }else{
257
141389
      Trace("qcf-qregister-debug2") << "...already processed" << std::endl;
258
    }
259
  }else{
260
46124
    Trace("qcf-qregister-debug2") << "...is ground." << std::endl;
261
  }
262
293605
}
263
264
265
121152
bool QuantInfo::reset_round( QuantConflictFind * p ) {
266
967575
  for( unsigned i=0; i<d_match.size(); i++ ){
267
846423
    d_match[i] = TNode::null();
268
846423
    d_match_term[i] = TNode::null();
269
  }
270
121152
  d_vars_set.clear();
271
121152
  d_curr_var_deq.clear();
272
121152
  d_tconstraints.clear();
273
274
121152
  d_mg->reset_round( p );
275
632316
  for( std::map< int, MatchGen * >::iterator it = d_var_mg.begin(); it != d_var_mg.end(); ++it ){
276
511164
    if (!it->second->reset_round(p))
277
    {
278
      return false;
279
    }
280
  }
281
  //now, reset for matching
282
121152
  d_mg->reset( p, false, this );
283
121152
  return true;
284
}
285
286
6498792
int QuantInfo::getCurrentRepVar( int v ) {
287
6498792
  if( v!=-1 && !d_match[v].isNull() ){
288
3615898
    int vn = getVarNum( d_match[v] );
289
3615898
    if( vn!=-1 ){
290
      //int vr = getCurrentRepVar( vn );
291
      //d_match[v] = d_vars[vr];
292
      //return vr;
293
21847
      return getCurrentRepVar( vn );
294
    }
295
  }
296
6476945
  return v;
297
}
298
299
3115872
TNode QuantInfo::getCurrentValue( TNode n ) {
300
3115872
  int v = getVarNum( n );
301
3115872
  if( v==-1 ){
302
1662656
    return n;
303
  }else{
304
1453216
    if( d_match[v].isNull() ){
305
1347815
      return n;
306
    }else{
307
105401
      Assert(getVarNum(d_match[v]) != v);
308
105401
      return getCurrentValue( d_match[v] );
309
    }
310
  }
311
}
312
313
181
TNode QuantInfo::getCurrentExpValue( TNode n ) {
314
181
  int v = getVarNum( n );
315
181
  if( v==-1 ){
316
    return n;
317
  }else{
318
181
    if( d_match[v].isNull() ){
319
      return n;
320
    }else{
321
181
      Assert(getVarNum(d_match[v]) != v);
322
181
      if( d_match_term[v].isNull() ){
323
8
        return getCurrentValue( d_match[v] );
324
      }else{
325
173
        return d_match_term[v];
326
      }
327
    }
328
  }
329
}
330
331
5696513
bool QuantInfo::getCurrentCanBeEqual( QuantConflictFind * p, int v, TNode n, bool chDiseq ) {
332
  //check disequalities
333
5696513
  std::map< int, std::map< TNode, int > >::iterator itd = d_curr_var_deq.find( v );
334
5696513
  if( itd!=d_curr_var_deq.end() ){
335
6654670
    for( std::map< TNode, int >::iterator it = itd->second.begin(); it != itd->second.end(); ++it ){
336
2659419
      Node cv = getCurrentValue( it->first );
337
1374097
      Debug("qcf-ccbe") << "compare " << cv << " " << n << std::endl;
338
1374097
      if( cv==n ){
339
65109
        return false;
340
1308988
      }else if( chDiseq && !isVar( n ) && !isVar( cv ) ){
341
        //they must actually be disequal if we are looking for conflicts
342
45723
        if( !p->areDisequal( n, cv ) ){
343
          //TODO : check for entailed disequal
344
345
23666
          return false;
346
        }
347
      }
348
    }
349
  }
350
5607738
  return true;
351
}
352
353
int QuantInfo::addConstraint( QuantConflictFind * p, int v, TNode n, bool polarity ) {
354
  v = getCurrentRepVar( v );
355
  int vn = getVarNum( n );
356
  vn = vn==-1 ? -1 : getCurrentRepVar( vn );
357
  n = getCurrentValue( n );
358
  return addConstraint( p, v, n, vn, polarity, false );
359
}
360
361
716268
int QuantInfo::addConstraint( QuantConflictFind * p, int v, TNode n, int vn, bool polarity, bool doRemove ) {
362
  //for handling equalities between variables, and disequalities involving variables
363
716268
  Debug("qcf-match-debug") << "- " << (doRemove ? "un" : "" ) << "constrain : " << v << " -> " << n << " (cv=" << getCurrentValue( n ) << ")";
364
716268
  Debug("qcf-match-debug") << ", (vn=" << vn << "), polarity = " << polarity << std::endl;
365
716268
  Assert(doRemove || n == getCurrentValue(n));
366
716268
  Assert(doRemove || v == getCurrentRepVar(v));
367
716268
  Assert(doRemove || vn == getCurrentRepVar(getVarNum(n)));
368
716268
  if( polarity ){
369
500859
    if( vn!=v ){
370
500859
      if( doRemove ){
371
249639
        if( vn!=-1 ){
372
          //if set to this in the opposite direction, clean up opposite instead
373
          //          std::map< int, TNode >::iterator itmn = d_match.find( vn );
374
17656
          if( d_match[vn]==d_vars[v] ){
375
            return addConstraint( p, vn, d_vars[v], v, true, true );
376
          }else{
377
            //unsetting variables equal
378
17656
            std::map< int, std::map< TNode, int > >::iterator itd = d_curr_var_deq.find( vn );
379
17656
            if( itd!=d_curr_var_deq.end() ){
380
              //remove disequalities owned by this
381
20528
              std::vector< TNode > remDeq;
382
10410
              for( std::map< TNode, int >::iterator it = itd->second.begin(); it != itd->second.end(); ++it ){
383
146
                if( it->second==v ){
384
146
                  remDeq.push_back( it->first );
385
                }
386
              }
387
10410
              for( unsigned i=0; i<remDeq.size(); i++ ){
388
146
                d_curr_var_deq[vn].erase( remDeq[i] );
389
              }
390
            }
391
          }
392
        }
393
249639
        unsetMatch( p, v );
394
249639
        return 1;
395
      }else{
396
        //std::map< int, TNode >::iterator itm = d_match.find( v );
397
251220
        bool isGroundRep = false;
398
251220
        bool isGround = false;
399
251220
        if( vn!=-1 ){
400
17863
          Debug("qcf-match-debug") << "  ...Variable bound to variable" << std::endl;
401
          //std::map< int, TNode >::iterator itmn = d_match.find( vn );
402
17863
          if( d_match[v].isNull() ){
403
            //setting variables equal
404
17863
            bool alreadySet = false;
405
17863
            if( !d_match[vn].isNull() ){
406
              alreadySet = true;
407
              Assert(!isVar(d_match[vn]));
408
            }
409
410
            //copy or check disequalities
411
17863
            std::map< int, std::map< TNode, int > >::iterator itd = d_curr_var_deq.find( v );
412
17863
            if( itd!=d_curr_var_deq.end() ){
413
12391
              for( std::map< TNode, int >::iterator it = itd->second.begin(); it != itd->second.end(); ++it ){
414
292
                Node dv = getCurrentValue( it->first );
415
146
                if( !alreadySet ){
416
146
                  if( d_curr_var_deq[vn].find( dv )==d_curr_var_deq[vn].end() ){
417
146
                    d_curr_var_deq[vn][dv] = v;
418
                  }
419
                }else{
420
                  if( !p->areMatchDisequal( d_match[vn], dv ) ){
421
                    Debug("qcf-match-debug") << "  -> fail, conflicting disequality" << std::endl;
422
                    return -1;
423
                  }
424
                }
425
              }
426
            }
427
17863
            if( alreadySet ){
428
              n = getCurrentValue( n );
429
            }
430
          }else{
431
            if( d_match[vn].isNull() ){
432
              Debug("qcf-match-debug") << " ...Reverse direction" << std::endl;
433
              //set the opposite direction
434
              return addConstraint( p, vn, d_vars[v], v, true, false );
435
            }else{
436
              Debug("qcf-match-debug") << "  -> Both variables bound, compare" << std::endl;
437
              //are they currently equal
438
              return p->areMatchEqual( d_match[v], d_match[vn] ) ? 0 : -1;
439
            }
440
          }
441
        }else{
442
233357
          Debug("qcf-match-debug") << "  ...Variable bound to ground" << std::endl;
443
233357
          if( d_match[v].isNull() ){
444
            //isGroundRep = true;   ??
445
233357
            isGround = true;
446
          }else{
447
            //compare ground values
448
            Debug("qcf-match-debug") << "  -> Ground value, compare " << d_match[v] << " "<< n << std::endl;
449
            return p->areMatchEqual( d_match[v], n ) ? 0 : -1;
450
          }
451
        }
452
251220
        if( setMatch( p, v, n, isGroundRep, isGround ) ){
453
251192
          Debug("qcf-match-debug") << "  -> success" << std::endl;
454
251192
          return 1;
455
        }else{
456
28
          Debug("qcf-match-debug") << "  -> fail, conflicting disequality" << std::endl;
457
28
          return -1;
458
        }
459
      }
460
    }else{
461
      Debug("qcf-match-debug") << "  -> redundant, variable identity" << std::endl;
462
      return 0;
463
    }
464
  }else{
465
215409
    if( vn==v ){
466
      Debug("qcf-match-debug") << "  -> fail, variable identity" << std::endl;
467
      return -1;
468
    }else{
469
215409
      if( doRemove ){
470
107396
        Assert(d_curr_var_deq[v].find(n) != d_curr_var_deq[v].end());
471
107396
        d_curr_var_deq[v].erase( n );
472
107396
        return 1;
473
      }else{
474
108013
        if( d_curr_var_deq[v].find( n )==d_curr_var_deq[v].end() ){
475
          //check if it respects equality
476
          //std::map< int, TNode >::iterator itm = d_match.find( v );
477
107909
          if( !d_match[v].isNull() ){
478
            TNode nv = getCurrentValue( n );
479
            if( !p->areMatchDisequal( nv, d_match[v] ) ){
480
              Debug("qcf-match-debug") << "  -> fail, conflicting disequality" << std::endl;
481
              return -1;
482
            }
483
          }
484
107909
          d_curr_var_deq[v][n] = v;
485
107909
          Debug("qcf-match-debug") << "  -> success" << std::endl;
486
107909
          return 1;
487
        }else{
488
104
          Debug("qcf-match-debug") << "  -> redundant disequality" << std::endl;
489
104
          return 0;
490
        }
491
      }
492
    }
493
  }
494
}
495
496
88
bool QuantInfo::isConstrainedVar( int v ) {
497
88
  if( d_curr_var_deq.find( v )!=d_curr_var_deq.end() && !d_curr_var_deq[v].empty() ){
498
    return true;
499
  }else{
500
176
    Node vv = getVar( v );
501
    //for( std::map< int, TNode >::iterator it = d_match.begin(); it != d_match.end(); ++it ){
502
1200
    for( unsigned i=0; i<d_match.size(); i++ ){
503
1112
      if( d_match[i]==vv ){
504
        return true;
505
      }
506
    }
507
616
    for( std::map< int, std::map< TNode, int > >::iterator it = d_curr_var_deq.begin(); it != d_curr_var_deq.end(); ++it ){
508
592
      for( std::map< TNode, int >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
509
64
        if( it2->first==vv ){
510
          return true;
511
        }
512
      }
513
    }
514
88
    return false;
515
  }
516
}
517
518
4065972
bool QuantInfo::setMatch( QuantConflictFind * p, int v, TNode n, bool isGroundRep, bool isGround ) {
519
4065972
  if( getCurrentCanBeEqual( p, v, n ) ){
520
4023488
    if( isGroundRep ){
521
      //fail if n does not exist in the relevant domain of each of the argument positions
522
3770640
      std::map< int, std::map< TNode, std::vector< unsigned > > >::iterator it = d_var_rel_dom.find( v );
523
3770640
      if( it!=d_var_rel_dom.end() ){
524
3432170
        for( std::map< TNode, std::vector< unsigned > >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
525
4177896
          for( unsigned j=0; j<it2->second.size(); j++ ){
526
2221328
            Debug("qcf-match-debug2") << n << " in relevant domain " <<  it2->first << "." << it2->second[j] << "?" << std::endl;
527
2221328
            if( !p->getTermDatabase()->inRelevantDomain( it2->first, it2->second[j], n ) ){
528
172428
              Debug("qcf-match-debug") << "  -> fail, since " << n << " is not in relevant domain of " << it2->first << "." << it2->second[j] << std::endl;
529
172428
              return false;
530
            }
531
          }
532
        }
533
      }
534
    }
535
3851060
    Debug("qcf-match-debug") << "-- bind : " << v << " -> " << n << ", checked " <<  d_curr_var_deq[v].size() << " disequalities" << std::endl;
536
3851060
    if( isGround ){
537
3833197
      if( d_vars[v].getKind()==BOUND_VARIABLE ){
538
1633068
        d_vars_set[v] = true;
539
1633068
        Debug("qcf-match-debug") << "---- now bound " << d_vars_set.size() << " / " << d_q[0].getNumChildren() << " base variables." << std::endl;
540
      }
541
    }
542
3851060
    d_match[v] = n;
543
3851060
    return true;
544
  }else{
545
42484
    return false;
546
  }
547
}
548
549
2535754
void QuantInfo::unsetMatch( QuantConflictFind * p, int v ) {
550
2535754
  Debug("qcf-match-debug") << "-- unbind : " << v << std::endl;
551
2535754
  if( d_vars[v].getKind()==BOUND_VARIABLE && d_vars_set.find( v )!=d_vars_set.end() ){
552
919400
    d_vars_set.erase( v );
553
  }
554
2535754
  d_match[ v ] = TNode::null();
555
2535754
}
556
557
333224
bool QuantInfo::isMatchSpurious( QuantConflictFind * p ) {
558
2466290
  for( int i=0; i<getNumVars(); i++ ){
559
    //std::map< int, TNode >::iterator it = d_match.find( i );
560
2179357
    if( !d_match[i].isNull() ){
561
1630541
      if (!getCurrentCanBeEqual(p, i, d_match[i], p->atConflictEffort())) {
562
46291
        return true;
563
      }
564
    }
565
  }
566
286933
  return false;
567
}
568
569
286729
bool QuantInfo::isTConstraintSpurious(QuantConflictFind* p,
570
                                      std::vector<Node>& terms)
571
{
572
286729
  if( options::qcfEagerTest() ){
573
    //check whether the instantiation evaluates as expected
574
286729
    EntailmentCheck* echeck = p->getTermRegistry().getEntailmentCheck();
575
289467
    std::map<TNode, TNode> subs;
576
1105292
    for (size_t i = 0, tsize = terms.size(); i < tsize; i++)
577
    {
578
818563
      Trace("qcf-instance-check") << "  " << terms[i] << std::endl;
579
818563
      subs[d_q[0][i]] = terms[i];
580
    }
581
286910
    for (size_t i = 0, evsize = d_extra_var.size(); i < evsize; i++)
582
    {
583
362
      Node n = getCurrentExpValue(d_extra_var[i]);
584
362
      Trace("qcf-instance-check")
585
181
          << "  " << d_extra_var[i] << " -> " << n << std::endl;
586
181
      subs[d_extra_var[i]] = n;
587
    }
588
286729
    if (p->atConflictEffort()) {
589
157888
      Trace("qcf-instance-check") << "Possible conflict instance for " << d_q << " : " << std::endl;
590
157888
      if (!echeck->isEntailed(d_q[1], subs, false, false))
591
      {
592
156915
        Trace("qcf-instance-check") << "...not entailed to be false." << std::endl;
593
156915
        return true;
594
      }
595
    }else{
596
      // see if the body of the quantified formula evaluates to a Boolean
597
      // combination of known terms under the current substitution. We use
598
      // the helper method evaluateTerm from the entailment check utility.
599
      Node inst_eval = echeck->evaluateTerm(
600
130606
          d_q[1], subs, false, options::qcfTConstraint(), true);
601
128841
      if( Trace.isOn("qcf-instance-check") ){
602
        Trace("qcf-instance-check") << "Possible propagating instance for " << d_q << " : " << std::endl;
603
        for( unsigned i=0; i<terms.size(); i++ ){
604
          Trace("qcf-instance-check") << "  " << terms[i] << std::endl;
605
        }
606
        Trace("qcf-instance-check") << "...evaluates to " << inst_eval << std::endl;
607
      }
608
      // If it is the case that instantiation can be rewritten to a Boolean
609
      // combination of terms that exist in the current context, then inst_eval
610
      // is non-null. Moreover, we insist that inst_eval is not true, or else
611
      // the instantiation is trivially entailed and hence is spurious.
612
257682
      if (inst_eval.isNull()
613
128841
          || (inst_eval.isConst() && inst_eval.getConst<bool>()))
614
      {
615
127076
        Trace("qcf-instance-check") << "...spurious." << std::endl;
616
127076
        return true;
617
      }else{
618
1765
        if (Configuration::isDebugBuild())
619
        {
620
1765
          if (!p->isPropagatingInstance(inst_eval))
621
          {
622
            // Notice that this can happen in cases where:
623
            // (1) x = -1*y is rewritten to y = -1*x, and
624
            // (2) -1*y is a term in the master equality engine but -1*x is not.
625
            // In other words, we determined that x = -1*y is a relevant
626
            // equality to propagate since it involves two known terms, but
627
            // after rewriting, the equality y = -1*x involves an unknown term
628
            // -1*x. In this case, the equality is still relevant to propagate,
629
            // despite the above function not being precise enough to realize
630
            // it. We output a warning in debug for this. See #2993.
631
90
            Trace("qcf-instance-check")
632
45
                << "WARNING: not propagating." << std::endl;
633
          }
634
        }
635
1765
        Trace("qcf-instance-check") << "...not spurious." << std::endl;
636
      }
637
    }
638
  }
639
2738
  if( !d_tconstraints.empty() ){
640
    //check constraints
641
8
    for( std::map< Node, bool >::iterator it = d_tconstraints.begin(); it != d_tconstraints.end(); ++it ){
642
      //apply substitution to the tconstraint
643
4
      Node cons = p->getQuantifiersRegistry().substituteBoundVariables(
644
8
          it->first, d_q, terms);
645
4
      cons = it->second ? cons : cons.negate();
646
4
      if (!entailmentTest(p, cons, p->atConflictEffort())) {
647
        return true;
648
      }
649
    }
650
  }
651
  // spurious if quantifiers engine is in conflict
652
2738
  return p->d_qstate.isInConflict();
653
}
654
655
4
bool QuantInfo::entailmentTest( QuantConflictFind * p, Node lit, bool chEnt ) {
656
4
  Trace("qcf-tconstraint-debug") << "Check : " << lit << std::endl;
657
8
  Node rew = Rewriter::rewrite(lit);
658
4
  if (rew.isConst())
659
  {
660
    Trace("qcf-tconstraint-debug") << "...constraint " << lit << " rewrites to "
661
                                   << rew << "." << std::endl;
662
    return rew.getConst<bool>();
663
  }
664
  // if checking for conflicts, we must be sure that the (negation of)
665
  // constraint is (not) entailed
666
4
  if (!chEnt)
667
  {
668
4
    rew = Rewriter::rewrite(rew.negate());
669
  }
670
  // check if it is entailed
671
8
  Trace("qcf-tconstraint-debug")
672
4
      << "Check entailment of " << rew << "..." << std::endl;
673
4
  std::pair<bool, Node> et = p->getState().getValuation().entailmentCheck(
674
8
      options::TheoryOfMode::THEORY_OF_TYPE_BASED, rew);
675
4
  ++(p->d_statistics.d_entailment_checks);
676
8
  Trace("qcf-tconstraint-debug")
677
4
      << "ET result : " << et.first << " " << et.second << std::endl;
678
4
  if (!et.first)
679
  {
680
8
    Trace("qcf-tconstraint-debug")
681
4
        << "...cannot show entailment of " << rew << "." << std::endl;
682
4
    return !chEnt;
683
  }
684
  return chEnt;
685
}
686
687
286865
bool QuantInfo::completeMatch( QuantConflictFind * p, std::vector< int >& assigned, bool doContinue ) {
688
  //assign values for variables that were unassigned (usually not necessary, but handles corner cases)
689
286865
  bool doFail = false;
690
286865
  bool success = true;
691
286865
  if( doContinue ){
692
    doFail = true;
693
    success = false;
694
  }else{
695
286865
    if( isBaseMatchComplete() && options::qcfEagerTest() ){
696
286656
      return true;
697
    }
698
    //solve for interpreted symbol matches
699
    //   this breaks the invariant that all introduced constraints are over existing terms
700
217
    for( int i=(int)(d_tsym_vars.size()-1); i>=0; i-- ){
701
8
      int index = d_tsym_vars[i];
702
16
      TNode v = getCurrentValue( d_vars[index] );
703
8
      int slv_v = -1;
704
8
      if( v==d_vars[index] ){
705
8
        slv_v = index;
706
      }
707
8
      Trace("qcf-tconstraint-debug") << "Solve " << d_vars[index] << " = " << v << " " << d_vars[index].getKind() << std::endl;
708
8
      if( d_vars[index].getKind()==PLUS || d_vars[index].getKind()==MULT ){
709
8
        Kind k = d_vars[index].getKind();
710
16
        std::vector< TNode > children;
711
24
        for( unsigned j=0; j<d_vars[index].getNumChildren(); j++ ){
712
16
          int vn = getVarNum( d_vars[index][j] );
713
16
          if( vn!=-1 ){
714
24
            TNode vv = getCurrentValue( d_vars[index][j] );
715
12
            if( vv==d_vars[index][j] ){
716
              //we will assign this
717
8
              if( slv_v==-1 ){
718
                Trace("qcf-tconstraint-debug") << "...will solve for var #" << vn << std::endl;
719
                slv_v = vn;
720
                if (!p->atConflictEffort()) {
721
                  break;
722
                }
723
              }else{
724
16
                Node z = p->getZero( k );
725
8
                if( !z.isNull() ){
726
4
                  Trace("qcf-tconstraint-debug") << "...set " << d_vars[vn] << " = " << z << std::endl;
727
4
                  assigned.push_back( vn );
728
4
                  if( !setMatch( p, vn, z, false, true ) ){
729
                    success = false;
730
                    break;
731
                  }
732
                }
733
              }
734
            }else{
735
4
              Trace("qcf-tconstraint-debug") << "...sum value " << vv << std::endl;
736
4
              children.push_back( vv );
737
            }
738
          }else{
739
4
            Trace("qcf-tconstraint-debug") << "...sum " << d_vars[index][j] << std::endl;
740
4
            children.push_back( d_vars[index][j] );
741
          }
742
        }
743
8
        if( success ){
744
8
          if( slv_v!=-1 ){
745
16
            Node lhs;
746
8
            if( children.empty() ){
747
              lhs = p->getZero( k );
748
8
            }else if( children.size()==1 ){
749
8
              lhs = children[0];
750
            }else{
751
              lhs = NodeManager::currentNM()->mkNode( k, children );
752
            }
753
16
            Node sum;
754
8
            if( v==d_vars[index] ){
755
8
              sum = lhs;
756
            }else{
757
              if (p->atConflictEffort()) {
758
                Kind kn = k;
759
                if( d_vars[index].getKind()==PLUS ){
760
                  kn = MINUS;
761
                }
762
                if( kn!=k ){
763
                  sum = NodeManager::currentNM()->mkNode( kn, v, lhs );
764
                }
765
              }
766
            }
767
8
            if( !sum.isNull() ){
768
8
              assigned.push_back( slv_v );
769
8
              Trace("qcf-tconstraint-debug") << "...set " << d_vars[slv_v] << " = " << sum << std::endl;
770
8
              if( !setMatch( p, slv_v, sum, false, true ) ){
771
                success = false;
772
              }
773
8
              p->d_tempCache.push_back( sum );
774
            }
775
          }else{
776
            //must show that constraint is met
777
            Node sum = NodeManager::currentNM()->mkNode( k, children );
778
            Node eq = sum.eqNode( v );
779
            if( !entailmentTest( p, eq ) ){
780
              success = false;
781
            }
782
            p->d_tempCache.push_back( sum );
783
          }
784
        }
785
      }
786
787
8
      if( !success ){
788
        break;
789
      }
790
    }
791
209
    if( success ){
792
      //check what is left to assign
793
209
      d_unassigned.clear();
794
209
      d_unassigned_tn.clear();
795
418
      std::vector< int > unassigned[2];
796
418
      std::vector< TypeNode > unassigned_tn[2];
797
673
      for( int i=0; i<getNumVars(); i++ ){
798
464
        if( d_match[i].isNull() ){
799
338
          int rindex = d_var_mg.find( i )==d_var_mg.end() ? 1 : 0;
800
338
          unassigned[rindex].push_back( i );
801
338
          unassigned_tn[rindex].push_back( getVar( i ).getType() );
802
338
          assigned.push_back( i );
803
        }
804
      }
805
209
      d_unassigned_nvar = unassigned[0].size();
806
627
      for( unsigned i=0; i<2; i++ ){
807
418
        d_unassigned.insert( d_unassigned.end(), unassigned[i].begin(), unassigned[i].end() );
808
418
        d_unassigned_tn.insert( d_unassigned_tn.end(), unassigned_tn[i].begin(), unassigned_tn[i].end() );
809
      }
810
209
      d_una_eqc_count.clear();
811
209
      d_una_index = 0;
812
    }
813
  }
814
815
209
  if( !d_unassigned.empty() && ( success || doContinue ) ){
816
204
    Trace("qcf-check") << "Assign to unassigned (" << d_unassigned.size() << ")..." << std::endl;
817
202
    do {
818
406
      if( doFail ){
819
202
        Trace("qcf-check-unassign") << "Failure, try again..." << std::endl;
820
      }
821
406
      bool invalidMatch = false;
822
3014
      while( ( d_una_index>=0 && (int)d_una_index<(int)d_unassigned.size() ) || invalidMatch || doFail ){
823
1304
        invalidMatch = false;
824
1304
        if( !doFail && d_una_index==(int)d_una_eqc_count.size() ){
825
          //check if it has now been assigned
826
340
          if( d_una_index<d_unassigned_nvar ){
827
44
            if( !isConstrainedVar( d_unassigned[d_una_index] ) ){
828
44
              d_una_eqc_count.push_back( -1 );
829
            }else{
830
              d_var_mg[ d_unassigned[d_una_index] ]->reset( p, true, this );
831
              d_una_eqc_count.push_back( 0 );
832
            }
833
          }else{
834
296
            d_una_eqc_count.push_back( 0 );
835
          }
836
        }else{
837
964
          bool failed = false;
838
964
          if( !doFail ){
839
762
            if( d_una_index<d_unassigned_nvar ){
840
44
              if( !isConstrainedVar( d_unassigned[d_una_index] ) ){
841
44
                Trace("qcf-check-unassign") << "Succeeded, variable unconstrained at " << d_una_index << std::endl;
842
44
                d_una_index++;
843
              }else if( d_var_mg[d_unassigned[d_una_index]]->getNextMatch( p, this ) ){
844
                Trace("qcf-check-unassign") << "Succeeded match with mg at " << d_una_index << std::endl;
845
                d_una_index++;
846
              }else{
847
                failed = true;
848
                Trace("qcf-check-unassign") << "Failed match with mg at " << d_una_index << std::endl;
849
              }
850
            }else{
851
718
              Assert(doFail || d_una_index == (int)d_una_eqc_count.size() - 1);
852
718
              if( d_una_eqc_count[d_una_index]<(int)p->d_eqcs[d_unassigned_tn[d_una_index]].size() ){
853
511
                int currIndex = d_una_eqc_count[d_una_index];
854
511
                d_una_eqc_count[d_una_index]++;
855
511
                Trace("qcf-check-unassign") << d_unassigned[d_una_index] << "->" << p->d_eqcs[d_unassigned_tn[d_una_index]][currIndex] << std::endl;
856
511
                if( setMatch( p, d_unassigned[d_una_index], p->d_eqcs[d_unassigned_tn[d_una_index]][currIndex], true, true ) ){
857
362
                  d_match_term[d_unassigned[d_una_index]] = TNode::null();
858
362
                  Trace("qcf-check-unassign") << "Succeeded match " << d_una_index << std::endl;
859
362
                  d_una_index++;
860
                }else{
861
149
                  Trace("qcf-check-unassign") << "Failed match " << d_una_index << std::endl;
862
149
                  invalidMatch = true;
863
                }
864
              }else{
865
207
                failed = true;
866
207
                Trace("qcf-check-unassign") << "No more matches " << d_una_index << std::endl;
867
              }
868
            }
869
          }
870
964
          if( doFail || failed ){
871
            do{
872
409
              if( !doFail ){
873
207
                d_una_eqc_count.pop_back();
874
              }else{
875
202
                doFail = false;
876
              }
877
409
              d_una_index--;
878
409
            }while( d_una_index>=0 && d_una_eqc_count[d_una_index]==-1 );
879
          }
880
        }
881
      }
882
406
      success = d_una_index>=0;
883
406
      if( success ){
884
270
        doFail = true;
885
270
        Trace("qcf-check-unassign") << "  Try: " << std::endl;
886
738
        for( unsigned i=0; i<d_unassigned.size(); i++ ){
887
468
          int ui = d_unassigned[i];
888
468
          if( !d_match[ui].isNull() ){
889
424
            Trace("qcf-check-unassign") << "  Assigned #" << ui << " : " << d_vars[ui] << " -> " << d_match[ui] << std::endl;
890
          }
891
        }
892
      }
893
406
    }while( success && isMatchSpurious( p ) );
894
204
    Trace("qcf-check") << "done assigning." << std::endl;
895
  }
896
209
  if( success ){
897
206
    for( unsigned i=0; i<d_unassigned.size(); i++ ){
898
133
      int ui = d_unassigned[i];
899
133
      if( !d_match[ui].isNull() ){
900
89
        Trace("qcf-check") << "  Assigned #" << ui << " : " << d_vars[ui] << " -> " << d_match[ui] << std::endl;
901
      }
902
    }
903
73
    return true;
904
  }else{
905
136
    revertMatch( p, assigned );
906
136
    assigned.clear();
907
136
    return false;
908
  }
909
}
910
911
286729
void QuantInfo::getMatch( std::vector< Node >& terms ){
912
1105292
  for( unsigned i=0; i<d_q[0].getNumChildren(); i++ ){
913
    //Node cv = qi->getCurrentValue( qi->d_match[i] );
914
818563
    int repVar = getCurrentRepVar( i );
915
1637126
    Node cv;
916
    //std::map< int, TNode >::iterator itmt = qi->d_match_term.find( repVar );
917
818563
    if( !d_match_term[repVar].isNull() ){
918
812822
      cv = d_match_term[repVar];
919
    }else{
920
5741
      cv = d_match[repVar];
921
    }
922
818563
    Debug("qcf-check-inst") << "INST : " << i << " -> " << cv << ", from " << d_match[i] << std::endl;
923
818563
    terms.push_back( cv );
924
  }
925
286729
}
926
927
285677
void QuantInfo::revertMatch( QuantConflictFind * p, std::vector< int >& assigned ) {
928
285975
  for( unsigned i=0; i<assigned.size(); i++ ){
929
298
    unsetMatch( p, assigned[i] );
930
  }
931
285677
}
932
933
void QuantInfo::debugPrintMatch( const char * c ) {
934
  for( int i=0; i<getNumVars(); i++ ){
935
    Trace(c) << "  " << d_vars[i] << " -> ";
936
    if( !d_match[i].isNull() ){
937
      Trace(c) << d_match[i];
938
    }else{
939
      Trace(c) << "(unassigned) ";
940
    }
941
    if( !d_curr_var_deq[i].empty() ){
942
      Trace(c) << ", DEQ{ ";
943
      for( std::map< TNode, int >::iterator it = d_curr_var_deq[i].begin(); it != d_curr_var_deq[i].end(); ++it ){
944
        Trace(c) << it->first << " ";
945
      }
946
      Trace(c) << "}";
947
    }
948
    if( !d_match_term[i].isNull() && d_match_term[i]!=d_match[i] ){
949
      Trace(c) << ", EXP : " << d_match_term[i];
950
    }
951
    Trace(c) <<  std::endl;
952
  }
953
  if( !d_tconstraints.empty() ){
954
    Trace(c) << "ADDITIONAL CONSTRAINTS : " << std::endl;
955
    for( std::map< Node, bool >::iterator it = d_tconstraints.begin(); it != d_tconstraints.end(); ++it ){
956
      Trace(c) << "   " << it->first << " -> " << it->second << std::endl;
957
    }
958
  }
959
}
960
961
MatchGen::MatchGen()
962
  : d_matched_basis(),
963
    d_binding(),
964
    d_tgt(),
965
    d_tgt_orig(),
966
    d_wasSet(),
967
    d_n(),
968
    d_type( typ_invalid ),
969
    d_type_not()
970
{
971
  d_qni_size = 0;
972
  d_child_counter = -1;
973
  d_use_children = true;
974
}
975
976
977
160149
MatchGen::MatchGen( QuantInfo * qi, Node n, bool isVar )
978
  : d_matched_basis(),
979
    d_binding(),
980
    d_tgt(),
981
    d_tgt_orig(),
982
    d_wasSet(),
983
    d_n(),
984
    d_type(),
985
160149
    d_type_not()
986
{
987
  //initialize temporary
988
160149
  d_child_counter = -1;
989
160149
  d_use_children = true;
990
991
160149
  Trace("qcf-qregister-debug") << "Make match gen for " << n << ", isVar = " << isVar << std::endl;
992
320298
  std::vector< Node > qni_apps;
993
160149
  d_qni_size = 0;
994
160149
  if( isVar ){
995
81412
    Assert(qi->d_var_num.find(n) != qi->d_var_num.end());
996
    // rare case where we have a free variable in an operator, we are invalid
997
162824
    if (n.getKind() == ITE
998
162824
        || (n.getKind() == APPLY_UF && expr::hasFreeVar(n.getOperator())))
999
    {
1000
1157
      d_type = typ_invalid;
1001
    }else{
1002
80255
      d_type = isHandledUfTerm( n ) ? typ_var : typ_tsym;
1003
80255
      d_qni_var_num[0] = qi->getVarNum( n );
1004
80255
      d_qni_size++;
1005
80255
      d_type_not = false;
1006
80255
      d_n = n;
1007
      //Node f = getMatchOperator( n );
1008
249717
      for( unsigned j=0; j<d_n.getNumChildren(); j++ ){
1009
338924
        Node nn = d_n[j];
1010
169462
        Trace("qcf-qregister-debug") << "  " << d_qni_size;
1011
169462
        if( qi->isVar( nn ) ){
1012
148015
          int v = qi->d_var_num[nn];
1013
148015
          Trace("qcf-qregister-debug") << " is var #" << v << std::endl;
1014
148015
          d_qni_var_num[d_qni_size] = v;
1015
          //qi->addFuncParent( v, f, j );
1016
        }else{
1017
21447
          Trace("qcf-qregister-debug") << " is gterm " << nn << std::endl;
1018
21447
          d_qni_gterm[d_qni_size] = nn;
1019
        }
1020
169462
        d_qni_size++;
1021
      }
1022
    }
1023
  }else{
1024
78737
    if (expr::hasBoundVar(n))
1025
    {
1026
78616
      d_type_not = false;
1027
78616
      d_n = n;
1028
78616
      if( d_n.getKind()==NOT ){
1029
25046
        d_n = d_n[0];
1030
25046
        d_type_not = !d_type_not;
1031
      }
1032
1033
78616
      if( isHandledBoolConnective( d_n ) ){
1034
        //non-literals
1035
26006
        d_type = typ_formula;
1036
82313
        for( unsigned i=0; i<d_n.getNumChildren(); i++ ){
1037
60536
          if( d_n.getKind()!=FORALL || i==1 ){
1038
56184
            d_children.push_back( MatchGen( qi, d_n[i], false ) );
1039
56184
            if( !d_children[d_children.size()-1].isValid() ){
1040
4229
              setInvalid();
1041
4229
              break;
1042
            }
1043
          }
1044
        }
1045
      }else{
1046
52610
        d_type = typ_invalid;
1047
        //literals
1048
52610
        if( isHandledUfTerm( d_n ) ){
1049
18320
          Assert(qi->isVar(d_n));
1050
18320
          d_type = typ_pred;
1051
34290
        }else if( d_n.getKind()==BOUND_VARIABLE ){
1052
167
          Assert(d_n.getType().isBoolean());
1053
167
          d_type = typ_bool_var;
1054
34123
        }else if( d_n.getKind()==EQUAL || options::qcfTConstraint() ){
1055
92508
          for (unsigned i = 0; i < d_n.getNumChildren(); i++)
1056
          {
1057
61672
            if (expr::hasBoundVar(d_n[i]))
1058
            {
1059
45803
              if (!qi->isVar(d_n[i]))
1060
              {
1061
                Trace("qcf-qregister-debug")
1062
                    << "ERROR : not var " << d_n[i] << std::endl;
1063
              }
1064
45803
              Assert(qi->isVar(d_n[i]));
1065
45803
              if (d_n.getKind() != EQUAL && qi->isVar(d_n[i]))
1066
              {
1067
338
                d_qni_var_num[i + 1] = qi->d_var_num[d_n[i]];
1068
              }
1069
            }
1070
            else
1071
            {
1072
15869
              d_qni_gterm[i] = d_n[i];
1073
            }
1074
          }
1075
30836
          d_type = d_n.getKind() == EQUAL ? typ_eq : typ_tconstraint;
1076
30836
          Trace("qcf-tconstraint") << "T-Constraint : " << d_n << std::endl;
1077
        }
1078
      }
1079
    }else{
1080
      //we will just evaluate
1081
121
      d_n = n;
1082
121
      d_type = typ_ground;
1083
    }
1084
  }
1085
160149
  Trace("qcf-qregister-debug")  << "Done make match gen " << n << ", type = ";
1086
160149
  debugPrintType( "qcf-qregister-debug", d_type, true );
1087
160149
  Trace("qcf-qregister-debug") << std::endl;
1088
  //Assert( d_children.size()==d_children_order.size() );
1089
1090
160149
}
1091
1092
474086
void MatchGen::collectBoundVar( QuantInfo * qi, Node n, std::vector< int >& cbvars, std::map< Node, bool >& visited, bool& hasNested ) {
1093
474086
  if( visited.find( n )==visited.end() ){
1094
406845
    visited[n] = true;
1095
406845
    if( n.getKind()==FORALL ){
1096
3612
      hasNested = true;
1097
    }
1098
406845
    int v = qi->getVarNum( n );
1099
406845
    if( v!=-1 && std::find( cbvars.begin(), cbvars.end(), v )==cbvars.end() ){
1100
264245
      cbvars.push_back( v );
1101
    }
1102
836094
    for( unsigned i=0; i<n.getNumChildren(); i++ ){
1103
429249
      collectBoundVar( qi, n[i], cbvars, visited, hasNested );
1104
    }
1105
  }
1106
474086
}
1107
1108
142744
void MatchGen::determineVariableOrder( QuantInfo * qi, std::vector< int >& bvars ) {
1109
142744
  Trace("qcf-qregister-debug") << "Determine variable order " << d_n << ", #bvars = " << bvars.size() << std::endl;
1110
142744
  bool isComm = d_type==typ_formula && ( d_n.getKind()==OR || d_n.getKind()==AND || d_n.getKind()==EQUAL );
1111
142744
  if( isComm ){
1112
32026
    std::map< int, std::vector< int > > c_to_vars;
1113
32026
    std::map< int, std::vector< int > > vars_to_c;
1114
32026
    std::map< int, int > vb_count;
1115
32026
    std::map< int, int > vu_count;
1116
32026
    std::map< int, bool > has_nested;
1117
32026
    std::vector< bool > assigned;
1118
16013
    Trace("qcf-qregister-debug") << "Calculate bound variables..." << std::endl;
1119
56725
    for( unsigned i=0; i<d_children.size(); i++ ){
1120
81424
      std::map< Node, bool > visited;
1121
40712
      has_nested[i] = false;
1122
40712
      collectBoundVar( qi, d_children[i].d_n, c_to_vars[i], visited, has_nested[i] );
1123
40712
      assigned.push_back( false );
1124
40712
      vb_count[i] = 0;
1125
40712
      vu_count[i] = 0;
1126
250876
      for( unsigned j=0; j<c_to_vars[i].size(); j++ ){
1127
210164
        int v = c_to_vars[i][j];
1128
210164
        vars_to_c[v].push_back( i );
1129
210164
        if( std::find( bvars.begin(), bvars.end(), v )==bvars.end() ){
1130
191565
          vu_count[i]++;
1131
        }else{
1132
18599
          vb_count[i]++;
1133
        }
1134
      }
1135
    }
1136
    //children that bind no unbound variable, then the most number of bound, unbound variables go first
1137
16013
    Trace("qcf-qregister-vo") << "Variable order for " << d_n << " : " << std::endl;
1138
24699
    do {
1139
40712
      int min_score0 = -1;
1140
40712
      int min_score = -1;
1141
40712
      int min_score_index = -1;
1142
750202
      for( unsigned i=0; i<d_children.size(); i++ ){
1143
709490
        if( !assigned[i] ){
1144
375101
          Trace("qcf-qregister-debug2") << "Child " << i << " has b/ub : " << vb_count[i] << "/" << vu_count[i] << std::endl;
1145
375101
          int score0 = 0;//has_nested[i] ? 0 : 1;
1146
          int score;
1147
375101
          if( !options::qcfVoExp() ){
1148
375101
            score = vu_count[i];
1149
          }else{
1150
            score =  vu_count[i]==0 ? 0 : ( 1 + qi->d_vars.size()*( qi->d_vars.size() - vb_count[i] ) + ( qi->d_vars.size() - vu_count[i] )  );
1151
          }
1152
375101
          if( min_score==-1 || score0<min_score0 || ( score0==min_score0 && score<min_score ) ){
1153
68793
            min_score0 = score0;
1154
68793
            min_score = score;
1155
68793
            min_score_index = i;
1156
          }
1157
        }
1158
      }
1159
40712
      Trace("qcf-qregister-vo") << "  " << d_children_order.size()+1 << ": " << d_children[min_score_index].d_n << " : ";
1160
40712
      Trace("qcf-qregister-vo") << vu_count[min_score_index] << " " << vb_count[min_score_index] << " " << has_nested[min_score_index] << std::endl;
1161
40712
      Trace("qcf-qregister-debug") << "...assign child " << min_score_index << std::endl;
1162
40712
      Trace("qcf-qregister-debug") << "...score : " << min_score << std::endl;
1163
40712
      Assert(min_score_index != -1);
1164
      //add to children order
1165
40712
      d_children_order.push_back( min_score_index );
1166
40712
      assigned[min_score_index] = true;
1167
      //determine order internal to children
1168
40712
      d_children[min_score_index].determineVariableOrder( qi, bvars );
1169
40712
      Trace("qcf-qregister-debug")  << "...bind variables" << std::endl;
1170
      //now, make it a bound variable
1171
40712
      if( vu_count[min_score_index]>0 ){
1172
231047
        for( unsigned i=0; i<c_to_vars[min_score_index].size(); i++ ){
1173
192779
          int v = c_to_vars[min_score_index][i];
1174
192779
          if( std::find( bvars.begin(), bvars.end(), v )==bvars.end() ){
1175
244812
            for( unsigned j=0; j<vars_to_c[v].size(); j++ ){
1176
159747
              int vc = vars_to_c[v][j];
1177
159747
              vu_count[vc]--;
1178
159747
              vb_count[vc]++;
1179
            }
1180
85065
            bvars.push_back( v );
1181
          }
1182
        }
1183
      }
1184
40712
      Trace("qcf-qregister-debug") << "...done assign child " << min_score_index << std::endl;
1185
40712
    }while( d_children_order.size()!=d_children.size() );
1186
16013
    Trace("qcf-qregister-debug") << "Done assign variable ordering for " << d_n << std::endl;
1187
  }else{
1188
130856
    for( unsigned i=0; i<d_children.size(); i++ ){
1189
4125
      d_children_order.push_back( i );
1190
4125
      d_children[i].determineVariableOrder( qi, bvars );
1191
      //now add to bvars
1192
8250
      std::map< Node, bool > visited;
1193
8250
      std::vector< int > cvars;
1194
4125
      bool has_nested = false;
1195
4125
      collectBoundVar( qi, d_children[i].d_n, cvars, visited, has_nested );
1196
58206
      for( unsigned j=0; j<cvars.size(); j++ ){
1197
54081
        if( std::find( bvars.begin(), bvars.end(), cvars[j] )==bvars.end() ){
1198
6466
          bvars.push_back( cvars[j] );
1199
        }
1200
      }
1201
    }
1202
  }
1203
142744
}
1204
1205
989479
bool MatchGen::reset_round(QuantConflictFind* p)
1206
{
1207
989479
  d_wasSet = false;
1208
1346642
  for( unsigned i=0; i<d_children.size(); i++ ){
1209
357163
    if (!d_children[i].reset_round(p))
1210
    {
1211
      return false;
1212
    }
1213
  }
1214
989479
  if( d_type==typ_ground ){
1215
    // int e = p->evaluate( d_n );
1216
    // if( e==1 ){
1217
    //  d_ground_eval[0] = p->d_true;
1218
    //}else if( e==-1 ){
1219
    //  d_ground_eval[0] = p->d_false;
1220
    //}
1221
    // modified
1222
1116
    EntailmentCheck* echeck = p->getTermRegistry().getEntailmentCheck();
1223
1116
    QuantifiersState& qs = p->getState();
1224
3348
    for (unsigned i = 0; i < 2; i++)
1225
    {
1226
2232
      if (echeck->isEntailed(d_n, i == 0))
1227
      {
1228
380
        d_ground_eval[0] = i==0 ? p->d_true : p->d_false;
1229
      }
1230
2232
      if (qs.isInConflict())
1231
      {
1232
        return false;
1233
      }
1234
    }
1235
988363
  }else if( d_type==typ_eq ){
1236
164865
    EntailmentCheck* echeck = p->getTermRegistry().getEntailmentCheck();
1237
164865
    QuantifiersState& qs = p->getState();
1238
494595
    for (unsigned i = 0, size = d_n.getNumChildren(); i < size; i++)
1239
    {
1240
329730
      if (!expr::hasBoundVar(d_n[i]))
1241
      {
1242
173302
        TNode t = echeck->getEntailedTerm(d_n[i]);
1243
86651
        if (qs.isInConflict())
1244
        {
1245
          return false;
1246
        }
1247
86651
        if (t.isNull())
1248
        {
1249
1688
          d_ground_eval[i] = d_n[i];
1250
        }
1251
        else
1252
        {
1253
84963
          d_ground_eval[i] = t;
1254
        }
1255
      }
1256
    }
1257
  }
1258
989479
  d_qni_bound_cons.clear();
1259
989479
  d_qni_bound_cons_var.clear();
1260
989479
  d_qni_bound.clear();
1261
989479
  return true;
1262
}
1263
1264
1819539
void MatchGen::reset( QuantConflictFind * p, bool tgt, QuantInfo * qi ) {
1265
1819539
  d_tgt = d_type_not ? !tgt : tgt;
1266
1819539
  Debug("qcf-match") << "     Reset for : " << d_n << ", type : ";
1267
1819539
  debugPrintType( "qcf-match", d_type );
1268
1819539
  Debug("qcf-match") << ", tgt = " << d_tgt << ", children = " << d_children.size() << " " << d_children_order.size() << std::endl;
1269
1819539
  d_qn.clear();
1270
1819539
  d_qni.clear();
1271
1819539
  d_qni_bound.clear();
1272
1819539
  d_child_counter = -1;
1273
1819539
  d_use_children = true;
1274
1819539
  d_tgt_orig = d_tgt;
1275
1276
  //set up processing matches
1277
1819539
  if( d_type==typ_invalid ){
1278
    d_use_children = false;
1279
1819539
  }else if( d_type==typ_ground ){
1280
1518
    d_use_children = false;
1281
1518
    if( d_ground_eval[0]==( d_tgt ? p->d_true : p->d_false ) ){
1282
644
      d_child_counter = 0;
1283
    }
1284
1818021
  }else if( qi->isBaseMatchComplete() && options::qcfEagerTest() ){
1285
337257
    d_use_children = false;
1286
337257
    d_child_counter = 0;
1287
1480764
  }else if( d_type==typ_bool_var ){
1288
    //get current value of the variable
1289
3288
    TNode n = qi->getCurrentValue( d_n );
1290
1644
    int vn = qi->getCurrentRepVar( qi->getVarNum( n ) );
1291
1644
    if( vn==-1 ){
1292
      EntailmentCheck* echeck = p->getTermRegistry().getEntailmentCheck();
1293
      if (echeck->isEntailed(n, d_tgt))
1294
      {
1295
        d_child_counter = 0;
1296
      }
1297
    }else{
1298
      //unassigned, set match to true/false
1299
1644
      d_qni_bound[0] = vn;
1300
1644
      qi->setMatch( p, vn, d_tgt ? p->d_true : p->d_false, false, true );
1301
1644
      d_child_counter = 0;
1302
    }
1303
1644
    if( d_child_counter==0 ){
1304
1644
      d_qn.push_back( NULL );
1305
    }
1306
1479120
  }else if( d_type==typ_var ){
1307
981174
    Assert(isHandledUfTerm(d_n));
1308
1962348
    TNode f = getMatchOperator( p, d_n );
1309
981174
    Debug("qcf-match-debug") << "       reset: Var will match operators of " << f << std::endl;
1310
981174
    TNodeTrie* qni = p->getTermDatabase()->getTermArgTrie(Node::null(), f);
1311
981174
    if (qni == nullptr || qni->empty())
1312
    {
1313
      //inform irrelevant quantifiers
1314
126480
      p->setIrrelevantFunction( f );
1315
    }
1316
    else
1317
    {
1318
854694
      d_qn.push_back(qni);
1319
    }
1320
981174
    d_matched_basis = false;
1321
497946
  }else if( d_type==typ_tsym || d_type==typ_tconstraint ){
1322
949
    for( std::map< int, int >::iterator it = d_qni_var_num.begin(); it != d_qni_var_num.end(); ++it ){
1323
558
      int repVar = qi->getCurrentRepVar( it->second );
1324
558
      if( qi->d_match[repVar].isNull() ){
1325
552
        Debug("qcf-match-debug") << "Force matching on child #" << it->first << ", which is var #" << repVar << std::endl;
1326
552
        d_qni_bound[it->first] = repVar;
1327
      }
1328
    }
1329
391
    d_qn.push_back( NULL );
1330
497555
  }else if( d_type==typ_pred || d_type==typ_eq ){
1331
    //add initial constraint
1332
719450
    Node nn[2];
1333
    int vn[2];
1334
359725
    if( d_type==typ_pred ){
1335
160395
      nn[0] = qi->getCurrentValue( d_n );
1336
160395
      vn[0] = qi->getCurrentRepVar( qi->getVarNum( nn[0] ) );
1337
160395
      nn[1] = d_tgt ? p->d_true : p->d_false;
1338
160395
      vn[1] = -1;
1339
160395
      d_tgt = true;
1340
    }else{
1341
597990
      for( unsigned i=0; i<2; i++ ){
1342
797320
        TNode nc;
1343
398660
        std::map<int, TNode>::iterator it = d_qni_gterm.find(i);
1344
398660
        if (it != d_qni_gterm.end())
1345
        {
1346
127689
          nc = it->second;
1347
        }else{
1348
270971
          nc = d_n[i];
1349
        }
1350
398660
        nn[i] = qi->getCurrentValue( nc );
1351
398660
        vn[i] = qi->getCurrentRepVar( qi->getVarNum( nn[i] ) );
1352
      }
1353
    }
1354
    bool success;
1355
359725
    if( vn[0]==-1 && vn[1]==-1 ){
1356
      //Trace("qcf-explain") << "    reset : " << d_n << " check ground values " << nn[0] << " " << nn[1] << " (tgt=" << d_tgt << ")" << std::endl;
1357
492
      Debug("qcf-match-debug") << "       reset: check ground values " << nn[0] << " " << nn[1] << " (" << d_tgt << ")" << std::endl;
1358
      //just compare values
1359
984
      if( d_tgt ){
1360
460
        success = p->areMatchEqual( nn[0], nn[1] );
1361
      }else{
1362
32
        if (p->atConflictEffort()) {
1363
17
          success = p->areDisequal( nn[0], nn[1] );
1364
        }else{
1365
15
          success = p->areMatchDisequal( nn[0], nn[1] );
1366
        }
1367
      }
1368
    }else{
1369
      //otherwise, add a constraint to a variable  TODO: this may be over-eager at effort > conflict, since equality may be a propagation
1370
359233
      if( vn[1]!=-1 && vn[0]==-1 ){
1371
        //swap
1372
152380
        Node t = nn[1];
1373
76190
        nn[1] = nn[0];
1374
76190
        nn[0] = t;
1375
76190
        vn[0] = vn[1];
1376
76190
        vn[1] = -1;
1377
      }
1378
359233
      Debug("qcf-match-debug") << "       reset: add constraint " << vn[0] << " -> " << nn[1] << " (vn=" << vn[1] << ")" << std::endl;
1379
      //add some constraint
1380
359233
      int addc = qi->addConstraint( p, vn[0], nn[1], vn[1], d_tgt, false );
1381
359233
      success = addc!=-1;
1382
      //if successful and non-redundant, store that we need to cleanup this
1383
359233
      if( addc==1 ){
1384
        //Trace("qcf-explain") << "       reset: " << d_n << " add constraint " << vn[0] << " -> " << nn[1] << " (vn=" << vn[1] << ")" << ", d_tgt = " << d_tgt << std::endl;
1385
1077303
        for( unsigned i=0; i<2; i++ ){
1386
718202
          if( vn[i]!=-1 && std::find( d_qni_bound_except.begin(), d_qni_bound_except.end(), i )==d_qni_bound_except.end() ){
1387
426104
            d_qni_bound[vn[i]] = vn[i];
1388
          }
1389
        }
1390
359101
        d_qni_bound_cons[vn[0]] = nn[1];
1391
359101
        d_qni_bound_cons_var[vn[0]] = vn[1];
1392
      }
1393
    }
1394
    //if successful, we will bind values to variables
1395
359725
    if( success ){
1396
359290
      d_qn.push_back( NULL );
1397
359725
    }
1398
  }else{
1399
137830
    if( d_children.empty() ){
1400
      //add dummy
1401
      d_qn.push_back( NULL );
1402
    }else{
1403
137830
      if( d_tgt && d_n.getKind()==FORALL ){
1404
        //fail
1405
119881
      } else if (d_n.getKind() == FORALL && p->atConflictEffort() &&
1406
3434
                 !options::qcfNestedConflict()) {
1407
        //fail
1408
      }else{
1409
        //reset the first child to d_tgt
1410
113013
        d_child_counter = 0;
1411
113013
        getChild( d_child_counter )->reset( p, d_tgt, qi );
1412
      }
1413
    }
1414
  }
1415
1819539
  d_binding = false;
1416
1819539
  d_wasSet = true;
1417
1819539
  Debug("qcf-match") << "     reset: Finished reset for " << d_n << ", success = " << ( !d_qn.empty() || d_child_counter!=-1 ) << std::endl;
1418
1819539
}
1419
1420
3763238
bool MatchGen::getNextMatch( QuantConflictFind * p, QuantInfo * qi ) {
1421
3763238
  Debug("qcf-match") << "     Get next match for : " << d_n << ", type = ";
1422
3763238
  debugPrintType( "qcf-match", d_type );
1423
3763238
  Debug("qcf-match") << ", children = " << d_children.size() << ", binding = " << d_binding << std::endl;
1424
3763238
  if( !d_use_children ){
1425
675963
    if( d_child_counter==0 ){
1426
337901
      d_child_counter = -1;
1427
337901
      return true;
1428
    }else{
1429
338062
      d_wasSet = false;
1430
338062
      return false;
1431
    }
1432
3087275
  }else if( d_type==typ_var || d_type==typ_eq || d_type==typ_pred || d_type==typ_bool_var || d_type==typ_tconstraint || d_type==typ_tsym ){
1433
2574801
    bool success = false;
1434
2574801
    bool terminate = false;
1435
1510943
    do {
1436
4085744
      bool doReset = false;
1437
4085744
      bool doFail = false;
1438
4085744
      if( !d_binding ){
1439
2858192
        if( doMatching( p, qi ) ){
1440
1520077
          Debug("qcf-match-debug") << "     - Matching succeeded" << std::endl;
1441
1520077
          d_binding = true;
1442
1520077
          d_binding_it = d_qni_bound.begin();
1443
1520077
          doReset = true;
1444
          //for tconstraint, add constraint
1445
1520077
          if( d_type==typ_tconstraint ){
1446
278
            std::map< Node, bool >::iterator it = qi->d_tconstraints.find( d_n );
1447
278
            if( it==qi->d_tconstraints.end() ){
1448
278
              qi->d_tconstraints[d_n] = d_tgt;
1449
              //store that we added this constraint
1450
278
              d_qni_bound_cons[0] = d_n;
1451
            }else if( d_tgt!=it->second ){
1452
              success = false;
1453
              terminate = true;
1454
            }
1455
          }
1456
        }else{
1457
1338115
          Debug("qcf-match-debug") << "     - Matching failed" << std::endl;
1458
1338115
          success = false;
1459
1338115
          terminate = true;
1460
        }
1461
      }else{
1462
1227552
        doFail = true;
1463
      }
1464
4085744
      if( d_binding ){
1465
        //also need to create match for each variable we bound
1466
2747629
        success = true;
1467
2747629
        Debug("qcf-match-debug") << "     Produce matches for bound variables by " << d_n << ", type = ";
1468
2747629
        debugPrintType( "qcf-match-debug", d_type );
1469
2747629
        Debug("qcf-match-debug") << "..." << std::endl;
1470
1471
11972827
        while( ( success && d_binding_it!=d_qni_bound.end() ) || doFail ){
1472
4612599
          QuantInfo::VarMgMap::const_iterator itm;
1473
4612599
          if( !doFail ){
1474
3385047
            Debug("qcf-match-debug") << "       check variable " << d_binding_it->second << std::endl;
1475
3385047
            itm = qi->var_mg_find( d_binding_it->second );
1476
          }
1477
4612599
          if( doFail || ( d_binding_it->first!=0 && itm != qi->var_mg_end() ) ){
1478
3182616
            Debug("qcf-match-debug") << "       we had bound variable " << d_binding_it->second << ", reset = " << doReset << std::endl;
1479
3182616
            if( doReset ){
1480
1120694
              itm->second->reset( p, true, qi );
1481
            }
1482
3182616
            if( doFail || !itm->second->getNextMatch( p, qi ) ){
1483
1425949
              do {
1484
3771262
                if( d_binding_it==d_qni_bound.begin() ){
1485
1510943
                  Debug("qcf-match-debug") << "       failed." << std::endl;
1486
1510943
                  success = false;
1487
                }else{
1488
2260319
                  --d_binding_it;
1489
2260319
                  Debug("qcf-match-debug") << "       decrement..." << std::endl;
1490
                }
1491
7457530
              }while( success &&
1492
3998861
                      ( d_binding_it->first==0 ||
1493
1738542
                        (!qi->containsVarMg(d_binding_it->second))));
1494
2345313
              doReset = false;
1495
2345313
              doFail = false;
1496
            }else{
1497
837303
              Debug("qcf-match-debug") << "       increment..." << std::endl;
1498
837303
              ++d_binding_it;
1499
837303
              doReset = true;
1500
            }
1501
          }else{
1502
1429983
            Debug("qcf-match-debug") << "       skip..." << d_binding_it->second << std::endl;
1503
1429983
            ++d_binding_it;
1504
1429983
            doReset = true;
1505
          }
1506
        }
1507
2747629
        if( !success ){
1508
1510943
          d_binding = false;
1509
        }else{
1510
1236686
          terminate = true;
1511
1236686
          if( d_binding_it==d_qni_bound.begin() ){
1512
4375
            d_binding = false;
1513
          }
1514
        }
1515
      }
1516
4085744
    }while( !terminate );
1517
    //if not successful, clean up the variables you bound
1518
2574801
    if( !success ){
1519
1338115
      if( d_type==typ_eq || d_type==typ_pred ){
1520
        //clean up the constraints you added
1521
714686
        for( std::map< int, TNode >::iterator it = d_qni_bound_cons.begin(); it != d_qni_bound_cons.end(); ++it ){
1522
357035
          if( !it->second.isNull() ){
1523
357035
            Debug("qcf-match") << "       Clean up bound var " << it->first << (d_tgt ? "!" : "") << " = " << it->second << std::endl;
1524
357035
            std::map< int, int >::iterator itb = d_qni_bound_cons_var.find( it->first );
1525
357035
            int vn = itb!=d_qni_bound_cons_var.end() ? itb->second : -1;
1526
            //Trace("qcf-explain") << "       cleanup: " << d_n << " remove constraint " << it->first << " -> " << it->second << " (vn=" << vn << ")" << ", d_tgt = " << d_tgt << std::endl;
1527
357035
            qi->addConstraint( p, it->first, it->second, vn, d_tgt, true );
1528
          }
1529
        }
1530
357651
        d_qni_bound_cons.clear();
1531
357651
        d_qni_bound_cons_var.clear();
1532
357651
        d_qni_bound.clear();
1533
      }else{
1534
        //clean up the matches you set
1535
1667432
        for( std::map< int, int >::iterator it = d_qni_bound.begin(); it != d_qni_bound.end(); ++it ){
1536
686968
          Debug("qcf-match") << "       Clean up bound var " << it->second << std::endl;
1537
686968
          Assert(it->second < qi->getNumVars());
1538
686968
          qi->unsetMatch( p, it->second );
1539
686968
          qi->d_match_term[ it->second ] = TNode::null();
1540
        }
1541
980464
        d_qni_bound.clear();
1542
      }
1543
1338115
      if( d_type==typ_tconstraint ){
1544
        //remove constraint if applicable
1545
274
        if( d_qni_bound_cons.find( 0 )!=d_qni_bound_cons.end() ){
1546
274
          qi->d_tconstraints.erase( d_n );
1547
274
          d_qni_bound_cons.clear();
1548
        }
1549
      }
1550
    }
1551
2574801
    Debug("qcf-match") << "    ...finished matching for " << d_n << ", success = " << success << std::endl;
1552
2574801
    d_wasSet = success;
1553
2574801
    return success;
1554
  }
1555
512474
  else if (d_type == typ_formula)
1556
  {
1557
512474
    bool success = false;
1558
512474
    if( d_child_counter<0 ){
1559
24817
      if( d_child_counter<-1 ){
1560
        success = true;
1561
        d_child_counter = -1;
1562
      }
1563
    }else{
1564
2895931
      while( !success && d_child_counter>=0 ){
1565
        //transition system based on d_child_counter
1566
1204137
        if( d_n.getKind()==OR || d_n.getKind()==AND ){
1567
802659
          if( (d_n.getKind()==AND)==d_tgt ){
1568
            //all children must match simultaneously
1569
751471
            if( getChild( d_child_counter )->getNextMatch( p, qi ) ){
1570
445395
              if( d_child_counter<(int)(getNumChildren()-1) ){
1571
253203
                d_child_counter++;
1572
253203
                Debug("qcf-match-debug") << "       Reset child " << d_child_counter << " of " << d_n << std::endl;
1573
253203
                getChild( d_child_counter )->reset( p, d_tgt, qi );
1574
              }else{
1575
192192
                success = true;
1576
              }
1577
            }else{
1578
              //if( std::find( d_independent.begin(), d_independent.end(), d_child_counter )!=d_independent.end() ){
1579
              //  d_child_counter--;
1580
              //}else{
1581
306076
              d_child_counter--;
1582
              //}
1583
            }
1584
          }else{
1585
            //one child must match
1586
51188
            if( !getChild( d_child_counter )->getNextMatch( p, qi ) ){
1587
23737
              if( d_child_counter<(int)(getNumChildren()-1) ){
1588
13343
                d_child_counter++;
1589
13343
                Debug("qcf-match-debug") << "       Reset child " << d_child_counter << " of " << d_n << ", one match" << std::endl;
1590
13343
                getChild( d_child_counter )->reset( p, d_tgt, qi );
1591
              }else{
1592
10394
                d_child_counter = -1;
1593
              }
1594
            }else{
1595
27451
              success = true;
1596
            }
1597
          }
1598
401478
        }else if( d_n.getKind()==EQUAL ){
1599
          //construct match based on both children
1600
361706
          if( d_child_counter%2==0 ){
1601
219967
            if( getChild( 0 )->getNextMatch( p, qi ) ){
1602
135520
              d_child_counter++;
1603
135520
              getChild( 1 )->reset( p, d_child_counter==1, qi );
1604
            }else{
1605
84447
              if( d_child_counter==0 ){
1606
42279
                d_child_counter = 2;
1607
42279
                getChild( 0 )->reset( p, !d_tgt, qi );
1608
              }else{
1609
42168
                d_child_counter = -1;
1610
              }
1611
            }
1612
          }
1613
361706
          if( d_child_counter>=0 && d_child_counter%2==1 ){
1614
277259
            if( getChild( 1 )->getNextMatch( p, qi ) ){
1615
141952
              success = true;
1616
            }else{
1617
135307
              d_child_counter--;
1618
            }
1619
          }
1620
39772
        }else if( d_n.getKind()==ITE ){
1621
36433
          if( d_child_counter%2==0 ){
1622
22697
            int index1 = d_child_counter==4 ? 1 : 0;
1623
22697
            if( getChild( index1 )->getNextMatch( p, qi ) ){
1624
15599
              d_child_counter++;
1625
15599
              getChild( d_child_counter==5 ? 2 : (d_tgt==(d_child_counter==1) ? 1 : 2) )->reset( p, d_tgt, qi );
1626
            }else{
1627
7098
              if (d_child_counter == 4)
1628
              {
1629
2362
                d_child_counter = -1;
1630
              }else{
1631
4736
                d_child_counter +=2;
1632
4736
                getChild( d_child_counter==2 ? 0 : 1 )->reset( p, d_child_counter==2 ? !d_tgt : d_tgt, qi );
1633
              }
1634
            }
1635
          }
1636
36433
          if( d_child_counter>=0 && d_child_counter%2==1 ){
1637
29335
            int index2 = d_child_counter==5 ? 2 : (d_tgt==(d_child_counter==1) ? 1 : 2);
1638
29335
            if( getChild( index2 )->getNextMatch( p, qi ) ){
1639
13742
              success = true;
1640
            }else{
1641
15593
              d_child_counter--;
1642
            }
1643
          }
1644
3339
        }else if( d_n.getKind()==FORALL ){
1645
3339
          if( getChild( d_child_counter )->getNextMatch( p, qi ) ){
1646
347
            success = true;
1647
          }else{
1648
2992
            d_child_counter = -1;
1649
          }
1650
        }
1651
      }
1652
487657
        d_wasSet = success;
1653
487657
      Debug("qcf-match") << "    ...finished construct match for " << d_n << ", success = " << success << std::endl;
1654
487657
      return success;
1655
    }
1656
  }
1657
24817
  Debug("qcf-match") << "    ...already finished for " << d_n << std::endl;
1658
24817
  return false;
1659
}
1660
1661
2858192
bool MatchGen::doMatching( QuantConflictFind * p, QuantInfo * qi ) {
1662
2858192
  if( !d_qn.empty() ){
1663
2372030
    if( d_qn[0]==NULL ){
1664
361325
      d_qn.clear();
1665
361325
      return true;
1666
    }else{
1667
2010705
      Assert(d_type == typ_var);
1668
2010705
      Assert(d_qni_size > 0);
1669
      bool invalidMatch;
1670
7837108
      do {
1671
9847813
        invalidMatch = false;
1672
9847813
        Debug("qcf-match-debug") << "       Do matching " << d_n << " " << d_qn.size() << " " << d_qni.size() << std::endl;
1673
9847813
        if( d_qn.size()==d_qni.size()+1 ) {
1674
4669833
          int index = (int)d_qni.size();
1675
          //initialize
1676
9339666
          TNode val;
1677
4669833
          std::map< int, int >::iterator itv = d_qni_var_num.find( index );
1678
4669833
          if( itv!=d_qni_var_num.end() ){
1679
            //get the representative variable this variable is equal to
1680
4378659
            int repVar = qi->getCurrentRepVar( itv->second );
1681
4378659
            Debug("qcf-match-debug") << "       Match " << index << " is a variable " << itv->second << ", which is repVar " << repVar << std::endl;
1682
            //get the value the rep variable
1683
            //std::map< int, TNode >::iterator itm = qi->d_match.find( repVar );
1684
4378659
            if( !qi->d_match[repVar].isNull() ){
1685
2775482
              val = qi->d_match[repVar];
1686
2775482
              Debug("qcf-match-debug") << "       Variable is already bound to " << val << std::endl;
1687
            }else{
1688
              //binding a variable
1689
1603177
              d_qni_bound[index] = repVar;
1690
              std::map<TNode, TNodeTrie>::iterator it =
1691
1603177
                  d_qn[index]->d_data.begin();
1692
1603177
              if( it != d_qn[index]->d_data.end() ) {
1693
1603177
                d_qni.push_back( it );
1694
                //set the match
1695
1603177
                if( it->first.getType().isComparableTo( qi->d_var_types[repVar] ) && qi->setMatch( p, d_qni_bound[index], it->first, true, true ) ){
1696
1478904
                  Debug("qcf-match-debug") << "       Binding variable" << std::endl;
1697
1478904
                  if( d_qn.size()<d_qni_size ){
1698
686030
                    d_qn.push_back( &it->second );
1699
                  }
1700
                }else{
1701
124273
                  Debug("qcf-match") << "       Binding variable, currently fail." << std::endl;
1702
124273
                  invalidMatch = true;
1703
                }
1704
              }else{
1705
                Debug("qcf-match-debug") << "       Binding variable, fail, no more variables to bind" << std::endl;
1706
                d_qn.pop_back();
1707
              }
1708
            }
1709
          }else{
1710
291174
            Debug("qcf-match-debug") << "       Match " << index << " is ground term" << std::endl;
1711
291174
            Assert(d_qni_gterm.find(index) != d_qni_gterm.end());
1712
291174
            val = d_qni_gterm[index];
1713
291174
            Assert(!val.isNull());
1714
          }
1715
4669833
          if( !val.isNull() ){
1716
6133312
            Node valr = p->getRepresentative(val);
1717
            //constrained by val
1718
            std::map<TNode, TNodeTrie>::iterator it =
1719
3066656
                d_qn[index]->d_data.find(valr);
1720
3066656
            if( it!=d_qn[index]->d_data.end() ){
1721
1376041
              Debug("qcf-match-debug") << "       Match" << std::endl;
1722
1376041
              d_qni.push_back( it );
1723
1376041
              if( d_qn.size()<d_qni_size ){
1724
1218685
                d_qn.push_back( &it->second );
1725
              }
1726
            }else{
1727
1690615
              Debug("qcf-match-debug") << "       Failed to match" << std::endl;
1728
1690615
              d_qn.pop_back();
1729
            }
1730
          }
1731
        }else{
1732
5177980
          Assert(d_qn.size() == d_qni.size());
1733
5177980
          int index = d_qni.size()-1;
1734
          //increment if binding this variable
1735
5177980
          bool success = false;
1736
5177980
          std::map< int, int >::iterator itb = d_qni_bound.find( index );
1737
5177980
          if( itb!=d_qni_bound.end() ){
1738
3808257
            d_qni[index]++;
1739
3808257
            if( d_qni[index]!=d_qn[index]->d_data.end() ){
1740
2209408
              success = true;
1741
2209408
              if( qi->setMatch( p, itb->second, d_qni[index]->first, true, true ) ){
1742
2118946
                Debug("qcf-match-debug") << "       Bind next variable" << std::endl;
1743
2118946
                if( d_qn.size()<d_qni_size ){
1744
1910424
                  d_qn.push_back( &d_qni[index]->second );
1745
                }
1746
              }else{
1747
90462
                Debug("qcf-match-debug") << "       Bind next variable, currently fail" << std::endl;
1748
90462
                invalidMatch = true;
1749
              }
1750
            }else{
1751
1598849
              qi->unsetMatch( p, itb->second );
1752
1598849
              qi->d_match_term[ itb->second ] = TNode::null();
1753
1598849
              Debug("qcf-match-debug") << "       Bind next variable, no more variables to bind" << std::endl;
1754
            }
1755
          }else{
1756
            //TODO : if it equal to something else, also try that
1757
          }
1758
          //if not incrementing, move to next
1759
5177980
          if( !success ){
1760
2968572
            d_qn.pop_back();
1761
2968572
            d_qni.pop_back();
1762
          }
1763
        }
1764
9847813
      }while( ( !d_qn.empty() && d_qni.size()!=d_qni_size ) || invalidMatch );
1765
2010705
      if( d_qni.size()==d_qni_size ){
1766
        //Assert( !d_qni[d_qni.size()-1]->second.d_data.empty() );
1767
        //Debug("qcf-match-debug") << "       We matched " << d_qni[d_qni.size()-1]->second.d_children.begin()->first << std::endl;
1768
1158752
        Assert(!d_qni[d_qni.size() - 1]->second.d_data.empty());
1769
2317504
        TNode t = d_qni[d_qni.size()-1]->second.d_data.begin()->first;
1770
1158752
        Debug("qcf-match-debug") << "       " << d_n << " matched " << t << std::endl;
1771
1158752
        qi->d_match_term[d_qni_var_num[0]] = t;
1772
        //set the match terms
1773
3430101
        for( std::map< int, int >::iterator it = d_qni_bound.begin(); it != d_qni_bound.end(); ++it ){
1774
2271349
          Debug("qcf-match-debug") << "       position " << it->first << " bounded " << it->second << " / " << qi->d_q[0].getNumChildren() << std::endl;
1775
          //if( it->second<(int)qi->d_q[0].getNumChildren() ){   //if it is an actual variable, we are interested in knowing the actual term
1776
2271349
          if( it->first>0 ){
1777
1793359
            Assert(!qi->d_match[it->second].isNull());
1778
1793359
            Assert(p->areEqual(t[it->first - 1], qi->d_match[it->second]));
1779
1793359
            qi->d_match_term[it->second] = t[it->first-1];
1780
          }
1781
          //}
1782
        }
1783
      }
1784
    }
1785
  }
1786
2496867
  return !d_qn.empty();
1787
}
1788
1789
8490555
void MatchGen::debugPrintType( const char * c, short typ, bool isTrace ) {
1790
8490555
  if( isTrace ){
1791
160149
    switch( typ ){
1792
8673
    case typ_invalid: Trace(c) << "invalid";break;
1793
121
    case typ_ground: Trace(c) << "ground";break;
1794
30498
    case typ_eq: Trace(c) << "eq";break;
1795
18320
    case typ_pred: Trace(c) << "pred";break;
1796
21777
    case typ_formula: Trace(c) << "formula";break;
1797
79876
    case typ_var: Trace(c) << "var";break;
1798
167
    case typ_bool_var: Trace(c) << "bool_var";break;
1799
    }
1800
  }else{
1801
8330406
    switch( typ ){
1802
    case typ_invalid: Debug(c) << "invalid";break;
1803
3680
    case typ_ground: Debug(c) << "ground";break;
1804
1429155
    case typ_eq: Debug(c) << "eq";break;
1805
1251004
    case typ_pred: Debug(c) << "pred";break;
1806
711445
    case typ_formula: Debug(c) << "formula";break;
1807
4925265
    case typ_var: Debug(c) << "var";break;
1808
8220
    case typ_bool_var: Debug(c) << "bool_var";break;
1809
    }
1810
  }
1811
8490555
}
1812
1813
5843
void MatchGen::setInvalid() {
1814
5843
  d_type = typ_invalid;
1815
5843
  d_children.clear();
1816
5843
}
1817
1818
263144
bool MatchGen::isHandledBoolConnective( TNode n ) {
1819
263144
  return TermUtil::isBoolConnectiveTerm( n ) && n.getKind()!=SEP_STAR;
1820
}
1821
1822
2205729
bool MatchGen::isHandledUfTerm( TNode n ) {
1823
  //return n.getKind()==APPLY_UF || n.getKind()==STORE || n.getKind()==SELECT ||
1824
  //       n.getKind()==APPLY_CONSTRUCTOR || n.getKind()==APPLY_SELECTOR_TOTAL || n.getKind()==APPLY_TESTER;
1825
  //TODO : treat APPLY_TESTER as a T-constraint instead of matching (currently leads to overabundance of instantiations)
1826
  //return inst::Trigger::isAtomicTriggerKind( n.getKind() ) && ( !options::qcfTConstraint() || n.getKind()!=APPLY_TESTER );
1827
2205729
  return inst::TriggerTermInfo::isAtomicTriggerKind(n.getKind());
1828
}
1829
1830
981174
Node MatchGen::getMatchOperator( QuantConflictFind * p, Node n ) {
1831
981174
  if( isHandledUfTerm( n ) ){
1832
981174
    return p->getTermDatabase()->getMatchOperator( n );
1833
  }else{
1834
    return Node::null();
1835
  }
1836
}
1837
1838
bool MatchGen::isHandled( TNode n ) {
1839
  if (n.getKind() != BOUND_VARIABLE && expr::hasBoundVar(n))
1840
  {
1841
    if( !isHandledBoolConnective( n ) && !isHandledUfTerm( n ) && n.getKind()!=EQUAL && n.getKind()!=ITE ){
1842
      return false;
1843
    }
1844
    for( unsigned i=0; i<n.getNumChildren(); i++ ){
1845
      if( !isHandled( n[i] ) ){
1846
        return false;
1847
      }
1848
    }
1849
  }
1850
  return true;
1851
}
1852
1853
9244
QuantConflictFind::QuantConflictFind(Env& env,
1854
                                     QuantifiersState& qs,
1855
                                     QuantifiersInferenceManager& qim,
1856
                                     QuantifiersRegistry& qr,
1857
9244
                                     TermRegistry& tr)
1858
    : QuantifiersModule(env, qs, qim, qr, tr),
1859
      d_conflict(context(), false),
1860
      d_true(NodeManager::currentNM()->mkConst<bool>(true)),
1861
      d_false(NodeManager::currentNM()->mkConst<bool>(false)),
1862
9244
      d_effort(EFFORT_INVALID)
1863
{
1864
9244
}
1865
1866
//-------------------------------------------------- registration
1867
1868
24253
void QuantConflictFind::registerQuantifier( Node q ) {
1869
24253
  if (d_qreg.hasOwnership(q, this))
1870
  {
1871
22553
    d_quants.push_back( q );
1872
22553
    d_quant_id[q] = d_quants.size();
1873
22553
    if( Trace.isOn("qcf-qregister") ){
1874
      Trace("qcf-qregister") << "Register ";
1875
      debugPrintQuant( "qcf-qregister", q );
1876
      Trace("qcf-qregister") << " : " << q << std::endl;
1877
    }
1878
    //make QcfNode structure
1879
22553
    Trace("qcf-qregister") << "- Get relevant equality/disequality pairs, calculate flattening..." << std::endl;
1880
22553
    d_qinfo[q].initialize( this, q, q[1] );
1881
1882
    //debug print
1883
22553
    if( Trace.isOn("qcf-qregister") ){
1884
      Trace("qcf-qregister") << "- Flattened structure is :" << std::endl;
1885
      Trace("qcf-qregister") << "    ";
1886
      debugPrintQuantBody( "qcf-qregister", q, q[1] );
1887
      Trace("qcf-qregister") << std::endl;
1888
      if( d_qinfo[q].d_vars.size()>q[0].getNumChildren() ){
1889
        Trace("qcf-qregister") << "  with additional constraints : " << std::endl;
1890
        for( unsigned j=q[0].getNumChildren(); j<d_qinfo[q].d_vars.size(); j++ ){
1891
          Trace("qcf-qregister") << "    ?x" << j << " = ";
1892
          debugPrintQuantBody( "qcf-qregister", q, d_qinfo[q].d_vars[j], false );
1893
          Trace("qcf-qregister") << std::endl;
1894
        }
1895
      }
1896
      Trace("qcf-qregister") << "Done registering quantifier." << std::endl;
1897
    }
1898
  }
1899
24253
}
1900
1901
460
bool QuantConflictFind::areMatchEqual( TNode n1, TNode n2 ) {
1902
  //if( d_effort==QuantConflictFind::effort_mc ){
1903
  //  return n1==n2 || !areDisequal( n1, n2 );
1904
  //}else{
1905
460
  return n1==n2;
1906
  //}
1907
}
1908
1909
15
bool QuantConflictFind::areMatchDisequal( TNode n1, TNode n2 ) {
1910
  // if( d_effort==QuantConflictFind::Effort::Conflict ){
1911
  //  return areDisequal( n1, n2 );
1912
  //}else{
1913
15
  return n1!=n2;
1914
  //}
1915
}
1916
1917
//-------------------------------------------------- check function
1918
1919
62508
bool QuantConflictFind::needsCheck( Theory::Effort level ) {
1920
62508
  bool performCheck = false;
1921
62508
  if( options::quantConflictFind() && !d_conflict ){
1922
62504
    if( level==Theory::EFFORT_LAST_CALL ){
1923
4433
      performCheck = options::qcfWhenMode() == options::QcfWhenMode::LAST_CALL;
1924
58071
    }else if( level==Theory::EFFORT_FULL ){
1925
17196
      performCheck = options::qcfWhenMode() == options::QcfWhenMode::DEFAULT;
1926
40875
    }else if( level==Theory::EFFORT_STANDARD ){
1927
40875
      performCheck = options::qcfWhenMode() == options::QcfWhenMode::STD;
1928
    }
1929
  }
1930
62508
  return performCheck;
1931
}
1932
1933
21631
void QuantConflictFind::reset_round( Theory::Effort level ) {
1934
21631
  Trace("qcf-check") << "QuantConflictFind::reset_round" << std::endl;
1935
21631
  Trace("qcf-check") << "Compute relevant equivalence classes..." << std::endl;
1936
21631
  d_eqcs.clear();
1937
1938
21631
  eq::EqClassesIterator eqcs_i = eq::EqClassesIterator(getEqualityEngine());
1939
21631
  TermDb* tdb = getTermDatabase();
1940
2326127
  while (!eqcs_i.isFinished())
1941
  {
1942
2304496
    Node r = (*eqcs_i);
1943
1152248
    if (tdb->hasTermCurrent(r))
1944
    {
1945
2304496
      TypeNode rtn = r.getType();
1946
1152248
      if (!options::cegqi() || !TermUtil::hasInstConstAttr(r))
1947
      {
1948
1097247
        d_eqcs[rtn].push_back(r);
1949
      }
1950
    }
1951
1152248
    ++eqcs_i;
1952
  }
1953
21631
}
1954
1955
126480
void QuantConflictFind::setIrrelevantFunction( TNode f ) {
1956
126480
  if( d_irr_func.find( f )==d_irr_func.end() ){
1957
19078
    d_irr_func[f] = true;
1958
19078
    std::map< TNode, std::vector< Node > >::iterator it = d_func_rel_dom.find( f );
1959
19078
    if( it != d_func_rel_dom.end()){
1960
77608
      for( unsigned j=0; j<it->second.size(); j++ ){
1961
62995
        d_irr_quant[it->second[j]] = true;
1962
      }
1963
    }
1964
  }
1965
126480
}
1966
1967
namespace {
1968
1969
// Returns the beginning of a range of efforts. The range can be iterated
1970
// through as unsigned using operator++.
1971
17196
inline QuantConflictFind::Effort QcfEffortStart() {
1972
17196
  return QuantConflictFind::EFFORT_CONFLICT;
1973
}
1974
1975
// Returns the beginning of a range of efforts. The value returned is included
1976
// in the range.
1977
17196
inline QuantConflictFind::Effort QcfEffortEnd() {
1978
17196
  return options::qcfMode() == options::QcfMode::PROP_EQ
1979
17196
             ? QuantConflictFind::EFFORT_PROP_EQ
1980
17196
             : QuantConflictFind::EFFORT_CONFLICT;
1981
}
1982
1983
}  // namespace
1984
1985
/** check */
1986
63389
void QuantConflictFind::check(Theory::Effort level, QEffort quant_e)
1987
{
1988
80585
  CodeTimer codeTimer(d_qstate.getStats().d_qcf_time);
1989
63389
  if (quant_e != QEFFORT_CONFLICT)
1990
  {
1991
46193
    return;
1992
  }
1993
17196
  Trace("qcf-check") << "QCF : check : " << level << std::endl;
1994
17196
  if (d_conflict)
1995
  {
1996
    Trace("qcf-check2") << "QCF : finished check : already in conflict."
1997
                        << std::endl;
1998
    if (level >= Theory::EFFORT_FULL)
1999
    {
2000
      Trace("qcf-warn") << "ALREADY IN CONFLICT? " << level << std::endl;
2001
    }
2002
    return;
2003
  }
2004
17196
  unsigned addedLemmas = 0;
2005
17196
  ++(d_statistics.d_inst_rounds);
2006
17196
  double clSet = 0;
2007
17196
  int prevEt = 0;
2008
17196
  if (Trace.isOn("qcf-engine"))
2009
  {
2010
    prevEt = d_statistics.d_entailment_checks.get();
2011
    clSet = double(clock()) / double(CLOCKS_PER_SEC);
2012
    Trace("qcf-engine") << "---Conflict Find Engine Round, effort = " << level
2013
                        << "---" << std::endl;
2014
  }
2015
2016
  // reset the round-specific information
2017
17196
  d_irr_func.clear();
2018
17196
  d_irr_quant.clear();
2019
2020
17196
  if (Trace.isOn("qcf-debug"))
2021
  {
2022
    Trace("qcf-debug") << std::endl;
2023
    debugPrint("qcf-debug");
2024
    Trace("qcf-debug") << std::endl;
2025
  }
2026
17196
  bool isConflict = false;
2027
17196
  FirstOrderModel* fm = d_treg.getModel();
2028
17196
  unsigned nquant = fm->getNumAssertedQuantifiers();
2029
  // for each effort level (find conflict, find propagating)
2030
49298
  for (unsigned e = QcfEffortStart(), end = QcfEffortEnd(); e <= end; ++e)
2031
  {
2032
    // set the effort (data member for convienence of access)
2033
33486
    d_effort = static_cast<Effort>(e);
2034
66972
    Trace("qcf-check") << "Checking quantified formulas at effort " << e
2035
33486
                       << "..." << std::endl;
2036
    // for each quantified formula
2037
363150
    for (unsigned i = 0; i < nquant; i++)
2038
    {
2039
660234
      Node q = fm->getAssertedQuantifier(i, true);
2040
991710
      if (d_qreg.hasOwnership(q, this)
2041
631690
          && d_irr_quant.find(q) == d_irr_quant.end()
2042
1219935
          && fm->isQuantifierActive(q))
2043
      {
2044
        // check this quantified formula
2045
228197
        checkQuantifiedFormula(q, isConflict, addedLemmas);
2046
228197
        if (d_conflict || d_qstate.isInConflict())
2047
        {
2048
906
          break;
2049
        }
2050
      }
2051
    }
2052
    // We are done if we added a lemma, or discovered a conflict in another
2053
    // way. An example of the latter case is when two disequal congruent terms
2054
    // are discovered during term indexing.
2055
33486
    if (addedLemmas > 0 || d_qstate.isInConflict())
2056
    {
2057
1384
      break;
2058
    }
2059
  }
2060
17196
  if (isConflict)
2061
  {
2062
    d_conflict.set(true);
2063
  }
2064
17196
  if (Trace.isOn("qcf-engine"))
2065
  {
2066
    double clSet2 = double(clock()) / double(CLOCKS_PER_SEC);
2067
    Trace("qcf-engine") << "Finished conflict find engine, time = "
2068
                        << (clSet2 - clSet);
2069
    if (addedLemmas > 0)
2070
    {
2071
      Trace("qcf-engine") << ", effort = "
2072
                          << (d_effort == EFFORT_CONFLICT
2073
                                  ? "conflict"
2074
                                  : (d_effort == EFFORT_PROP_EQ ? "prop_eq"
2075
                                                                : "mc"));
2076
      Trace("qcf-engine") << ", addedLemmas = " << addedLemmas;
2077
    }
2078
    Trace("qcf-engine") << std::endl;
2079
    int currEt = d_statistics.d_entailment_checks.get();
2080
    if (currEt != prevEt)
2081
    {
2082
      Trace("qcf-engine") << "  Entailment checks = " << (currEt - prevEt)
2083
                          << std::endl;
2084
    }
2085
  }
2086
17196
  Trace("qcf-check2") << "QCF : finished check : " << level << std::endl;
2087
}
2088
2089
228197
void QuantConflictFind::checkQuantifiedFormula(Node q,
2090
                                               bool& isConflict,
2091
                                               unsigned& addedLemmas)
2092
{
2093
228197
  QuantInfo* qi = &d_qinfo[q];
2094
228197
  Assert(d_qinfo.find(q) != d_qinfo.end());
2095
228197
  if (!qi->matchGeneratorIsValid())
2096
  {
2097
    // quantified formula is not properly set up for matching
2098
107045
    return;
2099
  }
2100
121152
  if (Trace.isOn("qcf-check"))
2101
  {
2102
    Trace("qcf-check") << "Check quantified formula ";
2103
    debugPrintQuant("qcf-check", q);
2104
    Trace("qcf-check") << " : " << q << "..." << std::endl;
2105
  }
2106
2107
121152
  Trace("qcf-check-debug") << "Reset round..." << std::endl;
2108
121152
  if (!qi->reset_round(this))
2109
  {
2110
    // it is typically the case that another conflict (e.g. in the term
2111
    // database) was discovered if we fail here.
2112
    return;
2113
  }
2114
  // try to make a matches making the body false or propagating
2115
121152
  Trace("qcf-check-debug") << "Get next match..." << std::endl;
2116
121152
  Instantiate* qinst = d_qim.getInstantiate();
2117
784684
  while (qi->getNextMatch(this))
2118
  {
2119
332962
    if (d_qstate.isInConflict())
2120
    {
2121
8
      Trace("qcf-check") << "   ... Quantifiers engine discovered conflict, ";
2122
16
      Trace("qcf-check") << "probably related to disequal congruent terms in "
2123
8
                            "master equality engine"
2124
8
                         << std::endl;
2125
1204
      return;
2126
    }
2127
332954
    if (Trace.isOn("qcf-inst"))
2128
    {
2129
      Trace("qcf-inst") << "*** Produced match at effort " << d_effort << " : "
2130
                        << std::endl;
2131
      qi->debugPrintMatch("qcf-inst");
2132
      Trace("qcf-inst") << std::endl;
2133
    }
2134
    // check whether internal match constraints are satisfied
2135
379043
    if (qi->isMatchSpurious(this))
2136
    {
2137
92178
      Trace("qcf-inst") << "   ... Spurious (match is inconsistent)"
2138
46089
                        << std::endl;
2139
92314
      continue;
2140
    }
2141
    // check whether match can be completed
2142
572406
    std::vector<int> assigned;
2143
287001
    if (!qi->completeMatch(this, assigned))
2144
    {
2145
272
      Trace("qcf-inst") << "   ... Spurious (cannot assign unassigned vars)"
2146
136
                        << std::endl;
2147
136
      continue;
2148
    }
2149
    // check whether the match is spurious according to (T-)entailment checks
2150
572270
    std::vector<Node> terms;
2151
286729
    qi->getMatch(terms);
2152
286729
    bool tcs = qi->isTConstraintSpurious(this, terms);
2153
286729
    if (tcs)
2154
    {
2155
567986
      Trace("qcf-inst") << "   ... Spurious (match is T-inconsistent)"
2156
283993
                        << std::endl;
2157
    }
2158
    else
2159
    {
2160
      // otherwise, we have a conflict/propagating instance
2161
      // for debugging
2162
2736
      if (Debug.isOn("qcf-check-inst"))
2163
      {
2164
        Node inst = qinst->getInstantiation(q, terms);
2165
        Debug("qcf-check-inst")
2166
            << "Check instantiation " << inst << "..." << std::endl;
2167
        Assert(!getTermRegistry().getEntailmentCheck()->isEntailed(inst, true));
2168
        Assert(getTermRegistry().getEntailmentCheck()->isEntailed(inst, false)
2169
               || d_effort > EFFORT_CONFLICT);
2170
      }
2171
      // Process the lemma: either add an instantiation or specific lemmas
2172
      // constructed during the isTConstraintSpurious call, or both.
2173
5472
      InferenceId id = (d_effort == EFFORT_CONFLICT
2174
2736
                            ? InferenceId::QUANTIFIERS_INST_CBQI_CONFLICT
2175
                            : InferenceId::QUANTIFIERS_INST_CBQI_PROP);
2176
2736
      if (!qinst->addInstantiation(q, terms, id))
2177
      {
2178
293
        Trace("qcf-inst") << "   ... Failed to add instantiation" << std::endl;
2179
        // This should only happen if the algorithm generates the same
2180
        // propagating instance twice this round. In this case, return
2181
        // to avoid exponential behavior.
2182
293
        return;
2183
      }
2184
2443
      Trace("qcf-check") << "   ... Added instantiation" << std::endl;
2185
2443
      if (Trace.isOn("qcf-inst"))
2186
      {
2187
        Trace("qcf-inst") << "*** Was from effort " << d_effort << " : "
2188
                          << std::endl;
2189
        qi->debugPrintMatch("qcf-inst");
2190
        Trace("qcf-inst") << std::endl;
2191
      }
2192
2443
      ++addedLemmas;
2193
2443
      if (d_effort == EFFORT_CONFLICT)
2194
      {
2195
        // mark relevant: this ensures that quantified formula q is
2196
        // checked first on the next round. This is an optimization to
2197
        // ensure that quantified formulas that are more likely to have
2198
        // conflicting instances are checked earlier.
2199
895
        d_treg.getModel()->markRelevant(q);
2200
895
        if (options::qcfAllConflict())
2201
        {
2202
          isConflict = true;
2203
        }
2204
        else
2205
        {
2206
895
          d_conflict.set(true);
2207
        }
2208
895
        return;
2209
      }
2210
1548
      else if (d_effort == EFFORT_PROP_EQ)
2211
      {
2212
1548
        d_treg.getModel()->markRelevant(q);
2213
      }
2214
    }
2215
    // clean up assigned
2216
285541
    qi->revertMatch(this, assigned);
2217
285541
    d_tempCache.clear();
2218
  }
2219
119956
  Trace("qcf-check") << "Done, conflict = " << d_conflict << std::endl;
2220
}
2221
2222
//-------------------------------------------------- debugging
2223
2224
void QuantConflictFind::debugPrint( const char * c ) {
2225
  //print the equivalance classes
2226
  Trace(c) << "----------EQ classes" << std::endl;
2227
  eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( getEqualityEngine() );
2228
  while( !eqcs_i.isFinished() ){
2229
    Node n = (*eqcs_i);
2230
    //if( !n.getType().isInteger() ){
2231
    Trace(c) << "  - " << n << " : {";
2232
    eq::EqClassIterator eqc_i = eq::EqClassIterator( n, getEqualityEngine() );
2233
    bool pr = false;
2234
    while( !eqc_i.isFinished() ){
2235
      Node nn = (*eqc_i);
2236
      if( nn.getKind()!=EQUAL && nn!=n ){
2237
        Trace(c) << (pr ? "," : "" ) << " " << nn;
2238
        pr = true;
2239
      }
2240
      ++eqc_i;
2241
    }
2242
    Trace(c) << (pr ? " " : "" ) << "}" << std::endl;
2243
    ++eqcs_i;
2244
  }
2245
}
2246
2247
void QuantConflictFind::debugPrintQuant( const char * c, Node q ) {
2248
  Trace(c) << "Q" << d_quant_id[q];
2249
}
2250
2251
void QuantConflictFind::debugPrintQuantBody( const char * c, Node q, Node n, bool doVarNum ) {
2252
  if( n.getNumChildren()==0 ){
2253
    Trace(c) << n;
2254
  }else if( doVarNum && d_qinfo[q].d_var_num.find( n )!=d_qinfo[q].d_var_num.end() ){
2255
    Trace(c) << "?x" << d_qinfo[q].d_var_num[n];
2256
  }else{
2257
    Trace(c) << "(";
2258
    if( n.getKind()==APPLY_UF ){
2259
      Trace(c) << n.getOperator();
2260
    }else{
2261
      Trace(c) << n.getKind();
2262
    }
2263
    for( unsigned i=0; i<n.getNumChildren(); i++ ){
2264
      Trace(c) << " ";
2265
      debugPrintQuantBody( c, q, n[i] );
2266
    }
2267
    Trace(c) << ")";
2268
  }
2269
}
2270
2271
9244
QuantConflictFind::Statistics::Statistics()
2272
    : d_inst_rounds(
2273
18488
        smtStatisticsRegistry().registerInt("QuantConflictFind::Inst_Rounds")),
2274
9244
      d_entailment_checks(smtStatisticsRegistry().registerInt(
2275
18488
          "QuantConflictFind::Entailment_Checks"))
2276
{
2277
9244
}
2278
2279
8
TNode QuantConflictFind::getZero( Kind k ) {
2280
8
  std::map< Kind, Node >::iterator it = d_zero.find( k );
2281
8
  if( it==d_zero.end() ){
2282
16
    Node nn;
2283
8
    if( k==PLUS ){
2284
4
      nn = NodeManager::currentNM()->mkConst( Rational(0) );
2285
    }
2286
8
    d_zero[k] = nn;
2287
8
    return nn;
2288
  }else{
2289
    return it->second;
2290
  }
2291
}
2292
2293
std::ostream& operator<<(std::ostream& os, const QuantConflictFind::Effort& e) {
2294
  switch (e) {
2295
    case QuantConflictFind::EFFORT_INVALID:
2296
      os << "Invalid";
2297
      break;
2298
    case QuantConflictFind::EFFORT_CONFLICT:
2299
      os << "Conflict";
2300
      break;
2301
    case QuantConflictFind::EFFORT_PROP_EQ:
2302
      os << "PropEq";
2303
      break;
2304
  }
2305
  return os;
2306
}
2307
2308
1765
bool QuantConflictFind::isPropagatingInstance(Node n) const
2309
{
2310
3530
  std::unordered_set<TNode> visited;
2311
3530
  std::vector<TNode> visit;
2312
3530
  TNode cur;
2313
1765
  visit.push_back(n);
2314
3712
  do
2315
  {
2316
5477
    cur = visit.back();
2317
5477
    visit.pop_back();
2318
5477
    if (visited.find(cur) == visited.end())
2319
    {
2320
5419
      visited.insert(cur);
2321
5419
      Kind ck = cur.getKind();
2322
5419
      if (ck == FORALL)
2323
      {
2324
        // do nothing
2325
      }
2326
5315
      else if (TermUtil::isBoolConnective(ck))
2327
      {
2328
5707
        for (TNode cc : cur)
2329
        {
2330
3757
          visit.push_back(cc);
2331
        }
2332
      }
2333
3365
      else if (!getEqualityEngine()->hasTerm(cur))
2334
      {
2335
90
        Trace("qcf-instance-check-debug")
2336
45
            << "...not propagating instance because of " << cur << " " << ck
2337
45
            << std::endl;
2338
45
        return false;
2339
      }
2340
    }
2341
5432
  } while (!visit.empty());
2342
1720
  return true;
2343
}
2344
2345
}  // namespace quantifiers
2346
}  // namespace theory
2347
31137
}  // namespace cvc5