GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/quant_conflict_find.cpp Lines: 1159 1397 83.0 %
Date: 2021-08-14 Branches: 2464 5417 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
32
using namespace cvc5::kind;
33
using namespace std;
34
35
namespace cvc5 {
36
namespace theory {
37
namespace quantifiers {
38
39
21984
QuantInfo::QuantInfo()
40
21984
    : d_unassigned_nvar(0), d_una_index(0), d_parent(nullptr), d_mg(nullptr)
41
{
42
21984
}
43
44
43968
QuantInfo::~QuantInfo() {
45
21984
  delete d_mg;
46
101908
  for(std::map< int, MatchGen * >::iterator i = d_var_mg.begin(),
47
21984
          iend=d_var_mg.end(); i != iend; ++i) {
48
79924
    MatchGen* currentMatchGenerator = (*i).second;
49
79924
    delete currentMatchGenerator;
50
  }
51
21984
  d_var_mg.clear();
52
21984
}
53
54
89737
QuantifiersInferenceManager& QuantInfo::getInferenceManager()
55
{
56
89737
  Assert(d_parent != nullptr);
57
89737
  return d_parent->getInferenceManager();
58
}
59
60
21984
void QuantInfo::initialize( QuantConflictFind * p, Node q, Node qn ) {
61
21984
  d_parent = p;
62
21984
  d_q = q;
63
21984
  d_extra_var.clear();
64
73735
  for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
65
51751
    d_match.push_back( TNode::null() );
66
51751
    d_match_term.push_back( TNode::null() );
67
  }
68
69
  //register the variables
70
73735
  for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
71
51751
    d_var_num[q[0][i]] = i;
72
51751
    d_vars.push_back( q[0][i] );
73
51751
    d_var_types.push_back( q[0][i].getType() );
74
  }
75
76
21984
  registerNode( qn, true, true );
77
78
79
21984
  Trace("qcf-qregister") << "- Make match gen structure..." << std::endl;
80
21984
  d_mg = new MatchGen( this, qn );
81
82
21984
  if( d_mg->isValid() ){
83
    /*
84
    for( unsigned j=0; j<q[0].getNumChildren(); j++ ){
85
      if( d_inMatchConstraint.find( q[0][j] )==d_inMatchConstraint.end() ){
86
        Trace("qcf-invalid") << "QCF invalid : variable " << q[0][j] << " does not exist in a matching constraint." << std::endl;
87
        d_mg->setInvalid();
88
        break;
89
      }
90
    }
91
    */
92
102462
    for( unsigned j=q[0].getNumChildren(); j<d_vars.size(); j++ ){
93
85312
      if( d_vars[j].getKind()!=BOUND_VARIABLE ){
94
79924
        d_var_mg[j] = NULL;
95
79924
        bool is_tsym = false;
96
79924
        if( !MatchGen::isHandledUfTerm( d_vars[j] ) && d_vars[j].getKind()!=ITE ){
97
832
          is_tsym = true;
98
832
          d_tsym_vars.push_back( j );
99
        }
100
79924
        if( !is_tsym || options::qcfTConstraint() ){
101
79471
          d_var_mg[j] = new MatchGen( this, d_vars[j], true );
102
        }
103
79924
        if( !d_var_mg[j] || !d_var_mg[j]->isValid() ){
104
1565
          Trace("qcf-invalid") << "QCF invalid : cannot match for " << d_vars[j] << std::endl;
105
1565
          d_mg->setInvalid();
106
1565
          break;
107
        }else{
108
156718
          std::vector< int > bvars;
109
78359
          d_var_mg[j]->determineVariableOrder( this, bvars );
110
        }
111
      }
112
    }
113
18715
    if( d_mg->isValid() ){
114
34300
      std::vector< int > bvars;
115
17150
      d_mg->determineVariableOrder( this, bvars );
116
    }
117
  }else{
118
3269
    Trace("qcf-invalid") << "QCF invalid : body of formula cannot be processed." << std::endl;
119
  }
120
21984
  Trace("qcf-qregister-summary") << "QCF register : " << ( d_mg->isValid() ? "VALID " : "INVALID" ) << " : " << q << std::endl;
121
122
21984
  if( d_mg->isValid() && options::qcfEagerCheckRd() ){
123
    //optimization : record variable argument positions for terms that must be matched
124
34300
    std::vector< TNode > vars;
125
    //TODO: revisit this, makes QCF faster, but misses conflicts due to caring about paths that may not be relevant (starExec jobs 14136/14137)
126
17150
    if( options::qcfSkipRd() ){
127
      for( unsigned j=q[0].getNumChildren(); j<d_vars.size(); j++ ){
128
        vars.push_back( d_vars[j] );
129
      }
130
    }else{
131
      //get all variables that are always relevant
132
34300
      std::map< TNode, bool > visited;
133
17150
      getPropagateVars( p, vars, q[1], false, visited );
134
    }
135
97607
    for( unsigned j=0; j<vars.size(); j++ ){
136
160914
      Node v = vars[j];
137
160914
      TNode f = p->getTermDatabase()->getMatchOperator( v );
138
80457
      if( !f.isNull() ){
139
48677
        Trace("qcf-opt") << "Record variable argument positions in " << v << ", op=" << f << "..." << std::endl;
140
158448
        for( unsigned k=0; k<v.getNumChildren(); k++ ){
141
219542
          Node n = v[k];
142
109771
          std::map< TNode, int >::iterator itv = d_var_num.find( n );
143
109771
          if( itv!=d_var_num.end() ){
144
96469
            Trace("qcf-opt") << "  arg " << k << " is var #" << itv->second << std::endl;
145
96469
            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() ){
146
91279
              d_var_rel_dom[itv->second][f].push_back( k );
147
            }
148
          }
149
        }
150
      }
151
    }
152
  }
153
21984
}
154
155
206371
void QuantInfo::getPropagateVars( QuantConflictFind * p, std::vector< TNode >& vars, TNode n, bool pol, std::map< TNode, bool >& visited ){
156
206371
  std::map< TNode, bool >::iterator itv = visited.find( n );
157
206371
  if( itv==visited.end() ){
158
150024
    visited[n] = true;
159
150024
    bool rec = true;
160
150024
    bool newPol = pol;
161
150024
    if( d_var_num.find( n )!=d_var_num.end() ){
162
80457
      Assert(std::find(vars.begin(), vars.end(), n) == vars.end());
163
80457
      vars.push_back( n );
164
160914
      TNode f = p->getTermDatabase()->getMatchOperator( n );
165
80457
      if( !f.isNull() ){
166
48677
        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() ){
167
37793
          p->d_func_rel_dom[f].push_back( d_q );
168
        }
169
      }
170
69567
    }else if( MatchGen::isHandledBoolConnective( n ) ){
171
28297
      Assert(n.getKind() != IMPLIES);
172
28297
      QuantPhaseReq::getEntailPolarity( n, 0, true, pol, rec, newPol );
173
    }
174
150024
    Trace("qcf-opt-debug") << "getPropagateVars " << n << ", pol = " << pol << ", rec = " << rec << std::endl;
175
150024
    if( rec ){
176
333101
      for( unsigned i=0; i<n.getNumChildren(); i++ ){
177
189221
        getPropagateVars( p, vars, n[i], pol, visited );
178
      }
179
    }
180
  }
181
206371
}
182
183
1841331
bool QuantInfo::isBaseMatchComplete() {
184
1841331
  return d_vars_set.size()==(d_q[0].getNumChildren()+d_extra_var.size());
185
}
186
187
116505
void QuantInfo::registerNode( Node n, bool hasPol, bool pol, bool beneathQuant ) {
188
116505
  Trace("qcf-qregister-debug2") << "Register : " << n << std::endl;
189
116505
  if( n.getKind()==FORALL ){
190
4381
    registerNode( n[1], hasPol, pol, true );
191
  }else{
192
112124
    if( !MatchGen::isHandledBoolConnective( n ) ){
193
61829
      if (expr::hasBoundVar(n))
194
      {
195
        // literals
196
61670
        if (n.getKind() == EQUAL)
197
        {
198
101166
          for (unsigned i = 0; i < n.getNumChildren(); i++)
199
          {
200
67444
            flatten(n[i], beneathQuant);
201
          }
202
        }
203
27948
        else if (MatchGen::isHandledUfTerm(n))
204
        {
205
18930
          flatten(n, beneathQuant);
206
        }
207
9018
        else if (n.getKind() == ITE)
208
        {
209
3930
          for (unsigned i = 1; i <= 2; i++)
210
          {
211
2620
            flatten(n[i], beneathQuant);
212
          }
213
1310
          registerNode(n[0], false, pol, beneathQuant);
214
        }
215
7708
        else if (options::qcfTConstraint())
216
        {
217
          // a theory-specific predicate
218
1014
          for (unsigned i = 0; i < n.getNumChildren(); i++)
219
          {
220
676
            flatten(n[i], beneathQuant);
221
          }
222
        }
223
      }
224
    }else{
225
137815
      for( unsigned i=0; i<n.getNumChildren(); i++ ){
226
        bool newHasPol;
227
        bool newPol;
228
87520
        QuantPhaseReq::getPolarity( n, i, hasPol, pol, newHasPol, newPol );
229
        //QcfNode * qcfc = new QcfNode( d_c );
230
        //qcfc->d_parent = qcf;
231
        //qcf->d_child[i] = qcfc;
232
87520
        registerNode( n[i], newHasPol, newPol, beneathQuant );
233
      }
234
    }
235
  }
236
116505
}
237
238
288281
void QuantInfo::flatten( Node n, bool beneathQuant ) {
239
288281
  Trace("qcf-qregister-debug2") << "Flatten : " << n << std::endl;
240
288281
  if (expr::hasBoundVar(n))
241
  {
242
242571
    if( n.getKind()==BOUND_VARIABLE ){
243
125898
      d_inMatchConstraint[n] = true;
244
    }
245
242571
    if( d_var_num.find( n )==d_var_num.end() ){
246
103777
      Trace("qcf-qregister-debug2") << "Add FLATTEN VAR : " << n << std::endl;
247
103777
      d_var_num[n] = d_vars.size();
248
103777
      d_vars.push_back( n );
249
103777
      d_var_types.push_back( n.getType() );
250
103777
      d_match.push_back( TNode::null() );
251
103777
      d_match_term.push_back( TNode::null() );
252
103777
      if( n.getKind()==ITE ){
253
1310
        registerNode( n, false, false );
254
102467
      }else if( n.getKind()==BOUND_VARIABLE ){
255
6327
        d_extra_var.push_back( n );
256
      }else{
257
294751
        for( unsigned i=0; i<n.getNumChildren(); i++ ){
258
198611
          flatten( n[i], beneathQuant );
259
        }
260
      }
261
    }else{
262
138794
      Trace("qcf-qregister-debug2") << "...already processed" << std::endl;
263
    }
264
  }else{
265
45710
    Trace("qcf-qregister-debug2") << "...is ground." << std::endl;
266
  }
267
288281
}
268
269
270
120602
bool QuantInfo::reset_round( QuantConflictFind * p ) {
271
959153
  for( unsigned i=0; i<d_match.size(); i++ ){
272
838551
    d_match[i] = TNode::null();
273
838551
    d_match_term[i] = TNode::null();
274
  }
275
120602
  d_vars_set.clear();
276
120602
  d_curr_var_deq.clear();
277
120602
  d_tconstraints.clear();
278
279
120602
  d_mg->reset_round( p );
280
626087
  for( std::map< int, MatchGen * >::iterator it = d_var_mg.begin(); it != d_var_mg.end(); ++it ){
281
505485
    if (!it->second->reset_round(p))
282
    {
283
      return false;
284
    }
285
  }
286
  //now, reset for matching
287
120602
  d_mg->reset( p, false, this );
288
120602
  return true;
289
}
290
291
5975607
int QuantInfo::getCurrentRepVar( int v ) {
292
5975607
  if( v!=-1 && !d_match[v].isNull() ){
293
3171657
    int vn = getVarNum( d_match[v] );
294
3171657
    if( vn!=-1 ){
295
      //int vr = getCurrentRepVar( vn );
296
      //d_match[v] = d_vars[vr];
297
      //return vr;
298
21657
      return getCurrentRepVar( vn );
299
    }
300
  }
301
5953950
  return v;
302
}
303
304
3059814
TNode QuantInfo::getCurrentValue( TNode n ) {
305
3059814
  int v = getVarNum( n );
306
3059814
  if( v==-1 ){
307
1631472
    return n;
308
  }else{
309
1428342
    if( d_match[v].isNull() ){
310
1320360
      return n;
311
    }else{
312
107982
      Assert(getVarNum(d_match[v]) != v);
313
107982
      return getCurrentValue( d_match[v] );
314
    }
315
  }
316
}
317
318
4
TNode QuantInfo::getCurrentExpValue( TNode n ) {
319
4
  int v = getVarNum( n );
320
4
  if( v==-1 ){
321
    return n;
322
  }else{
323
4
    if( d_match[v].isNull() ){
324
      return n;
325
    }else{
326
4
      Assert(getVarNum(d_match[v]) != v);
327
4
      if( d_match_term[v].isNull() ){
328
4
        return getCurrentValue( d_match[v] );
329
      }else{
330
        return d_match_term[v];
331
      }
332
    }
333
  }
334
}
335
336
4918304
bool QuantInfo::getCurrentCanBeEqual( QuantConflictFind * p, int v, TNode n, bool chDiseq ) {
337
  //check disequalities
338
4918304
  std::map< int, std::map< TNode, int > >::iterator itd = d_curr_var_deq.find( v );
339
4918304
  if( itd!=d_curr_var_deq.end() ){
340
5843110
    for( std::map< TNode, int >::iterator it = itd->second.begin(); it != itd->second.end(); ++it ){
341
2599484
      Node cv = getCurrentValue( it->first );
342
1346570
      Debug("qcf-ccbe") << "compare " << cv << " " << n << std::endl;
343
1346570
      if( cv==n ){
344
67265
        return false;
345
1279305
      }else if( chDiseq && !isVar( n ) && !isVar( cv ) ){
346
        //they must actually be disequal if we are looking for conflicts
347
44443
        if( !p->areDisequal( n, cv ) ){
348
          //TODO : check for entailed disequal
349
350
26391
          return false;
351
        }
352
      }
353
    }
354
  }
355
4824648
  return true;
356
}
357
358
int QuantInfo::addConstraint( QuantConflictFind * p, int v, TNode n, bool polarity ) {
359
  v = getCurrentRepVar( v );
360
  int vn = getVarNum( n );
361
  vn = vn==-1 ? -1 : getCurrentRepVar( vn );
362
  n = getCurrentValue( n );
363
  return addConstraint( p, v, n, vn, polarity, false );
364
}
365
366
701117
int QuantInfo::addConstraint( QuantConflictFind * p, int v, TNode n, int vn, bool polarity, bool doRemove ) {
367
  //for handling equalities between variables, and disequalities involving variables
368
701117
  Debug("qcf-match-debug") << "- " << (doRemove ? "un" : "" ) << "constrain : " << v << " -> " << n << " (cv=" << getCurrentValue( n ) << ")";
369
701117
  Debug("qcf-match-debug") << ", (vn=" << vn << "), polarity = " << polarity << std::endl;
370
701117
  Assert(doRemove || n == getCurrentValue(n));
371
701117
  Assert(doRemove || v == getCurrentRepVar(v));
372
701117
  Assert(doRemove || vn == getCurrentRepVar(getVarNum(n)));
373
701117
  if( polarity ){
374
487323
    if( vn!=v ){
375
487323
      if( doRemove ){
376
242963
        if( vn!=-1 ){
377
          //if set to this in the opposite direction, clean up opposite instead
378
          //          std::map< int, TNode >::iterator itmn = d_match.find( vn );
379
17562
          if( d_match[vn]==d_vars[v] ){
380
            return addConstraint( p, vn, d_vars[v], v, true, true );
381
          }else{
382
            //unsetting variables equal
383
17562
            std::map< int, std::map< TNode, int > >::iterator itd = d_curr_var_deq.find( vn );
384
17562
            if( itd!=d_curr_var_deq.end() ){
385
              //remove disequalities owned by this
386
20324
              std::vector< TNode > remDeq;
387
10310
              for( std::map< TNode, int >::iterator it = itd->second.begin(); it != itd->second.end(); ++it ){
388
148
                if( it->second==v ){
389
148
                  remDeq.push_back( it->first );
390
                }
391
              }
392
10310
              for( unsigned i=0; i<remDeq.size(); i++ ){
393
148
                d_curr_var_deq[vn].erase( remDeq[i] );
394
              }
395
            }
396
          }
397
        }
398
242963
        unsetMatch( p, v );
399
242963
        return 1;
400
      }else{
401
        //std::map< int, TNode >::iterator itm = d_match.find( v );
402
244360
        bool isGroundRep = false;
403
244360
        bool isGround = false;
404
244360
        if( vn!=-1 ){
405
17773
          Debug("qcf-match-debug") << "  ...Variable bound to variable" << std::endl;
406
          //std::map< int, TNode >::iterator itmn = d_match.find( vn );
407
17773
          if( d_match[v].isNull() ){
408
            //setting variables equal
409
17773
            bool alreadySet = false;
410
17773
            if( !d_match[vn].isNull() ){
411
              alreadySet = true;
412
              Assert(!isVar(d_match[vn]));
413
            }
414
415
            //copy or check disequalities
416
17773
            std::map< int, std::map< TNode, int > >::iterator itd = d_curr_var_deq.find( v );
417
17773
            if( itd!=d_curr_var_deq.end() ){
418
12113
              for( std::map< TNode, int >::iterator it = itd->second.begin(); it != itd->second.end(); ++it ){
419
296
                Node dv = getCurrentValue( it->first );
420
148
                if( !alreadySet ){
421
148
                  if( d_curr_var_deq[vn].find( dv )==d_curr_var_deq[vn].end() ){
422
148
                    d_curr_var_deq[vn][dv] = v;
423
                  }
424
                }else{
425
                  if( !p->areMatchDisequal( d_match[vn], dv ) ){
426
                    Debug("qcf-match-debug") << "  -> fail, conflicting disequality" << std::endl;
427
                    return -1;
428
                  }
429
                }
430
              }
431
            }
432
17773
            if( alreadySet ){
433
              n = getCurrentValue( n );
434
            }
435
          }else{
436
            if( d_match[vn].isNull() ){
437
              Debug("qcf-match-debug") << " ...Reverse direction" << std::endl;
438
              //set the opposite direction
439
              return addConstraint( p, vn, d_vars[v], v, true, false );
440
            }else{
441
              Debug("qcf-match-debug") << "  -> Both variables bound, compare" << std::endl;
442
              //are they currently equal
443
              return p->areMatchEqual( d_match[v], d_match[vn] ) ? 0 : -1;
444
            }
445
          }
446
        }else{
447
226587
          Debug("qcf-match-debug") << "  ...Variable bound to ground" << std::endl;
448
226587
          if( d_match[v].isNull() ){
449
            //isGroundRep = true;   ??
450
226587
            isGround = true;
451
          }else{
452
            //compare ground values
453
            Debug("qcf-match-debug") << "  -> Ground value, compare " << d_match[v] << " "<< n << std::endl;
454
            return p->areMatchEqual( d_match[v], n ) ? 0 : -1;
455
          }
456
        }
457
244360
        if( setMatch( p, v, n, isGroundRep, isGround ) ){
458
244332
          Debug("qcf-match-debug") << "  -> success" << std::endl;
459
244332
          return 1;
460
        }else{
461
28
          Debug("qcf-match-debug") << "  -> fail, conflicting disequality" << std::endl;
462
28
          return -1;
463
        }
464
      }
465
    }else{
466
      Debug("qcf-match-debug") << "  -> redundant, variable identity" << std::endl;
467
      return 0;
468
    }
469
  }else{
470
213794
    if( vn==v ){
471
      Debug("qcf-match-debug") << "  -> fail, variable identity" << std::endl;
472
      return -1;
473
    }else{
474
213794
      if( doRemove ){
475
106562
        Assert(d_curr_var_deq[v].find(n) != d_curr_var_deq[v].end());
476
106562
        d_curr_var_deq[v].erase( n );
477
106562
        return 1;
478
      }else{
479
107232
        if( d_curr_var_deq[v].find( n )==d_curr_var_deq[v].end() ){
480
          //check if it respects equality
481
          //std::map< int, TNode >::iterator itm = d_match.find( v );
482
107128
          if( !d_match[v].isNull() ){
483
            TNode nv = getCurrentValue( n );
484
            if( !p->areMatchDisequal( nv, d_match[v] ) ){
485
              Debug("qcf-match-debug") << "  -> fail, conflicting disequality" << std::endl;
486
              return -1;
487
            }
488
          }
489
107128
          d_curr_var_deq[v][n] = v;
490
107128
          Debug("qcf-match-debug") << "  -> success" << std::endl;
491
107128
          return 1;
492
        }else{
493
104
          Debug("qcf-match-debug") << "  -> redundant disequality" << std::endl;
494
104
          return 0;
495
        }
496
      }
497
    }
498
  }
499
}
500
501
88
bool QuantInfo::isConstrainedVar( int v ) {
502
88
  if( d_curr_var_deq.find( v )!=d_curr_var_deq.end() && !d_curr_var_deq[v].empty() ){
503
    return true;
504
  }else{
505
176
    Node vv = getVar( v );
506
    //for( std::map< int, TNode >::iterator it = d_match.begin(); it != d_match.end(); ++it ){
507
1200
    for( unsigned i=0; i<d_match.size(); i++ ){
508
1112
      if( d_match[i]==vv ){
509
        return true;
510
      }
511
    }
512
616
    for( std::map< int, std::map< TNode, int > >::iterator it = d_curr_var_deq.begin(); it != d_curr_var_deq.end(); ++it ){
513
592
      for( std::map< TNode, int >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
514
64
        if( it2->first==vv ){
515
          return true;
516
        }
517
      }
518
    }
519
88
    return false;
520
  }
521
}
522
523
3847722
bool QuantInfo::setMatch( QuantConflictFind * p, int v, TNode n, bool isGroundRep, bool isGround ) {
524
3847722
  if( getCurrentCanBeEqual( p, v, n ) ){
525
3805155
    if( isGroundRep ){
526
      //fail if n does not exist in the relevant domain of each of the argument positions
527
3559181
      std::map< int, std::map< TNode, std::vector< unsigned > > >::iterator it = d_var_rel_dom.find( v );
528
3559181
      if( it!=d_var_rel_dom.end() ){
529
3440093
        for( std::map< TNode, std::vector< unsigned > >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
530
4181751
          for( unsigned j=0; j<it2->second.size(); j++ ){
531
2216873
            Debug("qcf-match-debug2") << n << " in relevant domain " <<  it2->first << "." << it2->second[j] << "?" << std::endl;
532
2216873
            if( !p->getTermDatabase()->inRelevantDomain( it2->first, it2->second[j], n ) ){
533
174831
              Debug("qcf-match-debug") << "  -> fail, since " << n << " is not in relevant domain of " << it2->first << "." << it2->second[j] << std::endl;
534
174831
              return false;
535
            }
536
          }
537
        }
538
      }
539
    }
540
3630324
    Debug("qcf-match-debug") << "-- bind : " << v << " -> " << n << ", checked " <<  d_curr_var_deq[v].size() << " disequalities" << std::endl;
541
3630324
    if( isGround ){
542
3612551
      if( d_vars[v].getKind()==BOUND_VARIABLE ){
543
1470795
        d_vars_set[v] = true;
544
1470795
        Debug("qcf-match-debug") << "---- now bound " << d_vars_set.size() << " / " << d_q[0].getNumChildren() << " base variables." << std::endl;
545
      }
546
    }
547
3630324
    d_match[v] = n;
548
3630324
    return true;
549
  }else{
550
42567
    return false;
551
  }
552
}
553
554
2422267
void QuantInfo::unsetMatch( QuantConflictFind * p, int v ) {
555
2422267
  Debug("qcf-match-debug") << "-- unbind : " << v << std::endl;
556
2422267
  if( d_vars[v].getKind()==BOUND_VARIABLE && d_vars_set.find( v )!=d_vars_set.end() ){
557
843595
    d_vars_set.erase( v );
558
  }
559
2422267
  d_match[ v ] = TNode::null();
560
2422267
}
561
562
239089
bool QuantInfo::isMatchSpurious( QuantConflictFind * p ) {
563
1615379
  for( int i=0; i<getNumVars(); i++ ){
564
    //std::map< int, TNode >::iterator it = d_match.find( i );
565
1427379
    if( !d_match[i].isNull() ){
566
1070582
      if (!getCurrentCanBeEqual(p, i, d_match[i], p->atConflictEffort())) {
567
51089
        return true;
568
      }
569
    }
570
  }
571
188000
  return false;
572
}
573
574
187814
bool QuantInfo::isTConstraintSpurious(QuantConflictFind* p,
575
                                      std::vector<Node>& terms)
576
{
577
187814
  if( options::qcfEagerTest() ){
578
    //check whether the instantiation evaluates as expected
579
187814
    if (p->atConflictEffort()) {
580
98077
      Trace("qcf-instance-check") << "Possible conflict instance for " << d_q << " : " << std::endl;
581
98917
      std::map< TNode, TNode > subs;
582
375862
      for( unsigned i=0; i<terms.size(); i++ ){
583
277785
        Trace("qcf-instance-check") << "  " << terms[i] << std::endl;
584
277785
        subs[d_q[0][i]] = terms[i];
585
      }
586
98077
      TermDb* tdb = p->getTermDatabase();
587
98081
      for( unsigned i=0; i<d_extra_var.size(); i++ ){
588
8
        Node n = getCurrentExpValue( d_extra_var[i] );
589
4
        Trace("qcf-instance-check") << "  " << d_extra_var[i] << " -> " << n << std::endl;
590
4
        subs[d_extra_var[i]] = n;
591
      }
592
98077
      if (!tdb->isEntailed(d_q[1], subs, false, false))
593
      {
594
97237
        Trace("qcf-instance-check") << "...not entailed to be false." << std::endl;
595
97237
        return true;
596
      }
597
    }else{
598
      Node inst =
599
91352
          getInferenceManager().getInstantiate()->getInstantiation(d_q, terms);
600
89737
      inst = Rewriter::rewrite(inst);
601
      Node inst_eval = p->getTermDatabase()->evaluateTerm(
602
91352
          inst, options::qcfTConstraint(), true);
603
89737
      if( Trace.isOn("qcf-instance-check") ){
604
        Trace("qcf-instance-check") << "Possible propagating instance for " << d_q << " : " << std::endl;
605
        for( unsigned i=0; i<terms.size(); i++ ){
606
          Trace("qcf-instance-check") << "  " << terms[i] << std::endl;
607
        }
608
        Trace("qcf-instance-check") << "...evaluates to " << inst_eval << std::endl;
609
      }
610
179474
      if (inst_eval.isNull()
611
89737
          || (inst_eval.isConst() && inst_eval.getConst<bool>()))
612
      {
613
88122
        Trace("qcf-instance-check") << "...spurious." << std::endl;
614
88122
        return true;
615
      }else{
616
1615
        if (Configuration::isDebugBuild())
617
        {
618
1615
          if (!p->isPropagatingInstance(inst_eval))
619
          {
620
            // Notice that this can happen in cases where:
621
            // (1) x = -1*y is rewritten to y = -1*x, and
622
            // (2) -1*y is a term in the master equality engine but -1*x is not.
623
            // In other words, we determined that x = -1*y is a relevant
624
            // equality to propagate since it involves two known terms, but
625
            // after rewriting, the equality y = -1*x involves an unknown term
626
            // -1*x. In this case, the equality is still relevant to propagate,
627
            // despite the above function not being precise enough to realize
628
            // it. We output a warning in debug for this. See #2993.
629
            Trace("qcf-instance-check")
630
                << "WARNING: not propagating." << std::endl;
631
          }
632
        }
633
1615
        Trace("qcf-instance-check") << "...not spurious." << std::endl;
634
      }
635
    }
636
  }
637
2455
  if( !d_tconstraints.empty() ){
638
    //check constraints
639
28
    for( std::map< Node, bool >::iterator it = d_tconstraints.begin(); it != d_tconstraints.end(); ++it ){
640
      //apply substitution to the tconstraint
641
16
      Node cons = p->getQuantifiersRegistry().substituteBoundVariables(
642
32
          it->first, d_q, terms);
643
16
      cons = it->second ? cons : cons.negate();
644
16
      if (!entailmentTest(p, cons, p->atConflictEffort())) {
645
        return true;
646
      }
647
    }
648
  }
649
  // spurious if quantifiers engine is in conflict
650
2455
  return p->d_qstate.isInConflict();
651
}
652
653
16
bool QuantInfo::entailmentTest( QuantConflictFind * p, Node lit, bool chEnt ) {
654
16
  Trace("qcf-tconstraint-debug") << "Check : " << lit << std::endl;
655
32
  Node rew = Rewriter::rewrite( lit );
656
16
  if (rew.isConst())
657
  {
658
8
    Trace("qcf-tconstraint-debug") << "...constraint " << lit << " rewrites to "
659
4
                                   << rew << "." << std::endl;
660
4
    return rew.getConst<bool>();
661
  }
662
  // if checking for conflicts, we must be sure that the (negation of)
663
  // constraint is (not) entailed
664
12
  if (!chEnt)
665
  {
666
12
    rew = Rewriter::rewrite(rew.negate());
667
  }
668
  // check if it is entailed
669
24
  Trace("qcf-tconstraint-debug")
670
12
      << "Check entailment of " << rew << "..." << std::endl;
671
12
  std::pair<bool, Node> et = p->getState().getValuation().entailmentCheck(
672
24
      options::TheoryOfMode::THEORY_OF_TYPE_BASED, rew);
673
12
  ++(p->d_statistics.d_entailment_checks);
674
24
  Trace("qcf-tconstraint-debug")
675
12
      << "ET result : " << et.first << " " << et.second << std::endl;
676
12
  if (!et.first)
677
  {
678
24
    Trace("qcf-tconstraint-debug")
679
12
        << "...cannot show entailment of " << rew << "." << std::endl;
680
12
    return !chEnt;
681
  }
682
  return chEnt;
683
}
684
685
187944
bool QuantInfo::completeMatch( QuantConflictFind * p, std::vector< int >& assigned, bool doContinue ) {
686
  //assign values for variables that were unassigned (usually not necessary, but handles corner cases)
687
187944
  bool doFail = false;
688
187944
  bool success = true;
689
187944
  if( doContinue ){
690
    doFail = true;
691
    success = false;
692
  }else{
693
187944
    if( isBaseMatchComplete() && options::qcfEagerTest() ){
694
187753
      return true;
695
    }
696
    //solve for interpreted symbol matches
697
    //   this breaks the invariant that all introduced constraints are over existing terms
698
199
    for( int i=(int)(d_tsym_vars.size()-1); i>=0; i-- ){
699
8
      int index = d_tsym_vars[i];
700
16
      TNode v = getCurrentValue( d_vars[index] );
701
8
      int slv_v = -1;
702
8
      if( v==d_vars[index] ){
703
8
        slv_v = index;
704
      }
705
8
      Trace("qcf-tconstraint-debug") << "Solve " << d_vars[index] << " = " << v << " " << d_vars[index].getKind() << std::endl;
706
8
      if( d_vars[index].getKind()==PLUS || d_vars[index].getKind()==MULT ){
707
8
        Kind k = d_vars[index].getKind();
708
16
        std::vector< TNode > children;
709
24
        for( unsigned j=0; j<d_vars[index].getNumChildren(); j++ ){
710
16
          int vn = getVarNum( d_vars[index][j] );
711
16
          if( vn!=-1 ){
712
24
            TNode vv = getCurrentValue( d_vars[index][j] );
713
12
            if( vv==d_vars[index][j] ){
714
              //we will assign this
715
8
              if( slv_v==-1 ){
716
                Trace("qcf-tconstraint-debug") << "...will solve for var #" << vn << std::endl;
717
                slv_v = vn;
718
                if (!p->atConflictEffort()) {
719
                  break;
720
                }
721
              }else{
722
16
                Node z = p->getZero( k );
723
8
                if( !z.isNull() ){
724
4
                  Trace("qcf-tconstraint-debug") << "...set " << d_vars[vn] << " = " << z << std::endl;
725
4
                  assigned.push_back( vn );
726
4
                  if( !setMatch( p, vn, z, false, true ) ){
727
                    success = false;
728
                    break;
729
                  }
730
                }
731
              }
732
            }else{
733
4
              Trace("qcf-tconstraint-debug") << "...sum value " << vv << std::endl;
734
4
              children.push_back( vv );
735
            }
736
          }else{
737
4
            Trace("qcf-tconstraint-debug") << "...sum " << d_vars[index][j] << std::endl;
738
4
            children.push_back( d_vars[index][j] );
739
          }
740
        }
741
8
        if( success ){
742
8
          if( slv_v!=-1 ){
743
16
            Node lhs;
744
8
            if( children.empty() ){
745
              lhs = p->getZero( k );
746
8
            }else if( children.size()==1 ){
747
8
              lhs = children[0];
748
            }else{
749
              lhs = NodeManager::currentNM()->mkNode( k, children );
750
            }
751
16
            Node sum;
752
8
            if( v==d_vars[index] ){
753
8
              sum = lhs;
754
            }else{
755
              if (p->atConflictEffort()) {
756
                Kind kn = k;
757
                if( d_vars[index].getKind()==PLUS ){
758
                  kn = MINUS;
759
                }
760
                if( kn!=k ){
761
                  sum = NodeManager::currentNM()->mkNode( kn, v, lhs );
762
                }
763
              }
764
            }
765
8
            if( !sum.isNull() ){
766
8
              assigned.push_back( slv_v );
767
8
              Trace("qcf-tconstraint-debug") << "...set " << d_vars[slv_v] << " = " << sum << std::endl;
768
8
              if( !setMatch( p, slv_v, sum, false, true ) ){
769
                success = false;
770
              }
771
8
              p->d_tempCache.push_back( sum );
772
            }
773
          }else{
774
            //must show that constraint is met
775
            Node sum = NodeManager::currentNM()->mkNode( k, children );
776
            Node eq = sum.eqNode( v );
777
            if( !entailmentTest( p, eq ) ){
778
              success = false;
779
            }
780
            p->d_tempCache.push_back( sum );
781
          }
782
        }
783
      }
784
785
8
      if( !success ){
786
        break;
787
      }
788
    }
789
191
    if( success ){
790
      //check what is left to assign
791
191
      d_unassigned.clear();
792
191
      d_unassigned_tn.clear();
793
382
      std::vector< int > unassigned[2];
794
382
      std::vector< TypeNode > unassigned_tn[2];
795
587
      for( int i=0; i<getNumVars(); i++ ){
796
396
        if( d_match[i].isNull() ){
797
318
          int rindex = d_var_mg.find( i )==d_var_mg.end() ? 1 : 0;
798
318
          unassigned[rindex].push_back( i );
799
318
          unassigned_tn[rindex].push_back( getVar( i ).getType() );
800
318
          assigned.push_back( i );
801
        }
802
      }
803
191
      d_unassigned_nvar = unassigned[0].size();
804
573
      for( unsigned i=0; i<2; i++ ){
805
382
        d_unassigned.insert( d_unassigned.end(), unassigned[i].begin(), unassigned[i].end() );
806
382
        d_unassigned_tn.insert( d_unassigned_tn.end(), unassigned_tn[i].begin(), unassigned_tn[i].end() );
807
      }
808
191
      d_una_eqc_count.clear();
809
191
      d_una_index = 0;
810
    }
811
  }
812
813
191
  if( !d_unassigned.empty() && ( success || doContinue ) ){
814
186
    Trace("qcf-check") << "Assign to unassigned (" << d_unassigned.size() << ")..." << std::endl;
815
184
    do {
816
370
      if( doFail ){
817
184
        Trace("qcf-check-unassign") << "Failure, try again..." << std::endl;
818
      }
819
370
      bool invalidMatch = false;
820
2822
      while( ( d_una_index>=0 && (int)d_una_index<(int)d_unassigned.size() ) || invalidMatch || doFail ){
821
1226
        invalidMatch = false;
822
1226
        if( !doFail && d_una_index==(int)d_una_eqc_count.size() ){
823
          //check if it has now been assigned
824
324
          if( d_una_index<d_unassigned_nvar ){
825
44
            if( !isConstrainedVar( d_unassigned[d_una_index] ) ){
826
44
              d_una_eqc_count.push_back( -1 );
827
            }else{
828
              d_var_mg[ d_unassigned[d_una_index] ]->reset( p, true, this );
829
              d_una_eqc_count.push_back( 0 );
830
            }
831
          }else{
832
280
            d_una_eqc_count.push_back( 0 );
833
          }
834
        }else{
835
902
          bool failed = false;
836
902
          if( !doFail ){
837
718
            if( d_una_index<d_unassigned_nvar ){
838
44
              if( !isConstrainedVar( d_unassigned[d_una_index] ) ){
839
44
                Trace("qcf-check-unassign") << "Succeeded, variable unconstrained at " << d_una_index << std::endl;
840
44
                d_una_index++;
841
              }else if( d_var_mg[d_unassigned[d_una_index]]->getNextMatch( p, this ) ){
842
                Trace("qcf-check-unassign") << "Succeeded match with mg at " << d_una_index << std::endl;
843
                d_una_index++;
844
              }else{
845
                failed = true;
846
                Trace("qcf-check-unassign") << "Failed match with mg at " << d_una_index << std::endl;
847
              }
848
            }else{
849
674
              Assert(doFail || d_una_index == (int)d_una_eqc_count.size() - 1);
850
674
              if( d_una_eqc_count[d_una_index]<(int)p->d_eqcs[d_unassigned_tn[d_una_index]].size() ){
851
471
                int currIndex = d_una_eqc_count[d_una_index];
852
471
                d_una_eqc_count[d_una_index]++;
853
471
                Trace("qcf-check-unassign") << d_unassigned[d_una_index] << "->" << p->d_eqcs[d_unassigned_tn[d_una_index]][currIndex] << std::endl;
854
471
                if( setMatch( p, d_unassigned[d_una_index], p->d_eqcs[d_unassigned_tn[d_una_index]][currIndex], true, true ) ){
855
334
                  d_match_term[d_unassigned[d_una_index]] = TNode::null();
856
334
                  Trace("qcf-check-unassign") << "Succeeded match " << d_una_index << std::endl;
857
334
                  d_una_index++;
858
                }else{
859
137
                  Trace("qcf-check-unassign") << "Failed match " << d_una_index << std::endl;
860
137
                  invalidMatch = true;
861
                }
862
              }else{
863
203
                failed = true;
864
203
                Trace("qcf-check-unassign") << "No more matches " << d_una_index << std::endl;
865
              }
866
            }
867
          }
868
902
          if( doFail || failed ){
869
            do{
870
387
              if( !doFail ){
871
203
                d_una_eqc_count.pop_back();
872
              }else{
873
184
                doFail = false;
874
              }
875
387
              d_una_index--;
876
387
            }while( d_una_index>=0 && d_una_eqc_count[d_una_index]==-1 );
877
          }
878
        }
879
      }
880
370
      success = d_una_index>=0;
881
370
      if( success ){
882
240
        doFail = true;
883
240
        Trace("qcf-check-unassign") << "  Try: " << std::endl;
884
680
        for( unsigned i=0; i<d_unassigned.size(); i++ ){
885
440
          int ui = d_unassigned[i];
886
440
          if( !d_match[ui].isNull() ){
887
396
            Trace("qcf-check-unassign") << "  Assigned #" << ui << " : " << d_vars[ui] << " -> " << d_match[ui] << std::endl;
888
          }
889
        }
890
      }
891
370
    }while( success && isMatchSpurious( p ) );
892
186
    Trace("qcf-check") << "done assigning." << std::endl;
893
  }
894
191
  if( success ){
895
182
    for( unsigned i=0; i<d_unassigned.size(); i++ ){
896
121
      int ui = d_unassigned[i];
897
121
      if( !d_match[ui].isNull() ){
898
77
        Trace("qcf-check") << "  Assigned #" << ui << " : " << d_vars[ui] << " -> " << d_match[ui] << std::endl;
899
      }
900
    }
901
61
    return true;
902
  }else{
903
130
    revertMatch( p, assigned );
904
130
    assigned.clear();
905
130
    return false;
906
  }
907
}
908
909
187814
void QuantInfo::getMatch( std::vector< Node >& terms ){
910
714046
  for( unsigned i=0; i<d_q[0].getNumChildren(); i++ ){
911
    //Node cv = qi->getCurrentValue( qi->d_match[i] );
912
526232
    int repVar = getCurrentRepVar( i );
913
1052464
    Node cv;
914
    //std::map< int, TNode >::iterator itmt = qi->d_match_term.find( repVar );
915
526232
    if( !d_match_term[repVar].isNull() ){
916
520583
      cv = d_match_term[repVar];
917
    }else{
918
5649
      cv = d_match[repVar];
919
    }
920
526232
    Debug("qcf-check-inst") << "INST : " << i << " -> " << cv << ", from " << d_match[i] << std::endl;
921
526232
    terms.push_back( cv );
922
  }
923
187814
}
924
925
186942
void QuantInfo::revertMatch( QuantConflictFind * p, std::vector< int >& assigned ) {
926
187228
  for( unsigned i=0; i<assigned.size(); i++ ){
927
286
    unsetMatch( p, assigned[i] );
928
  }
929
186942
}
930
931
void QuantInfo::debugPrintMatch( const char * c ) {
932
  for( int i=0; i<getNumVars(); i++ ){
933
    Trace(c) << "  " << d_vars[i] << " -> ";
934
    if( !d_match[i].isNull() ){
935
      Trace(c) << d_match[i];
936
    }else{
937
      Trace(c) << "(unassigned) ";
938
    }
939
    if( !d_curr_var_deq[i].empty() ){
940
      Trace(c) << ", DEQ{ ";
941
      for( std::map< TNode, int >::iterator it = d_curr_var_deq[i].begin(); it != d_curr_var_deq[i].end(); ++it ){
942
        Trace(c) << it->first << " ";
943
      }
944
      Trace(c) << "}";
945
    }
946
    if( !d_match_term[i].isNull() && d_match_term[i]!=d_match[i] ){
947
      Trace(c) << ", EXP : " << d_match_term[i];
948
    }
949
    Trace(c) <<  std::endl;
950
  }
951
  if( !d_tconstraints.empty() ){
952
    Trace(c) << "ADDITIONAL CONSTRAINTS : " << std::endl;
953
    for( std::map< Node, bool >::iterator it = d_tconstraints.begin(); it != d_tconstraints.end(); ++it ){
954
      Trace(c) << "   " << it->first << " -> " << it->second << std::endl;
955
    }
956
  }
957
}
958
959
MatchGen::MatchGen()
960
  : d_matched_basis(),
961
    d_binding(),
962
    d_tgt(),
963
    d_tgt_orig(),
964
    d_wasSet(),
965
    d_n(),
966
    d_type( typ_invalid ),
967
    d_type_not()
968
{
969
  d_qni_size = 0;
970
  d_child_counter = -1;
971
  d_use_children = true;
972
}
973
974
975
157154
MatchGen::MatchGen( QuantInfo * qi, Node n, bool isVar )
976
  : d_matched_basis(),
977
    d_binding(),
978
    d_tgt(),
979
    d_tgt_orig(),
980
    d_wasSet(),
981
    d_n(),
982
    d_type(),
983
157154
    d_type_not()
984
{
985
  //initialize temporary
986
157154
  d_child_counter = -1;
987
157154
  d_use_children = true;
988
989
157154
  Trace("qcf-qregister-debug") << "Make match gen for " << n << ", isVar = " << isVar << std::endl;
990
314308
  std::vector< Node > qni_apps;
991
157154
  d_qni_size = 0;
992
157154
  if( isVar ){
993
79471
    Assert(qi->d_var_num.find(n) != qi->d_var_num.end());
994
    // rare case where we have a free variable in an operator, we are invalid
995
158942
    if (n.getKind() == ITE
996
160054
        || (options::ufHo() && n.getKind() == APPLY_UF
997
91662
            && expr::hasFreeVar(n.getOperator())))
998
    {
999
1112
      d_type = typ_invalid;
1000
    }else{
1001
78359
      d_type = isHandledUfTerm( n ) ? typ_var : typ_tsym;
1002
78359
      d_qni_var_num[0] = qi->getVarNum( n );
1003
78359
      d_qni_size++;
1004
78359
      d_type_not = false;
1005
78359
      d_n = n;
1006
      //Node f = getMatchOperator( n );
1007
244451
      for( unsigned j=0; j<d_n.getNumChildren(); j++ ){
1008
332184
        Node nn = d_n[j];
1009
166092
        Trace("qcf-qregister-debug") << "  " << d_qni_size;
1010
166092
        if( qi->isVar( nn ) ){
1011
144866
          int v = qi->d_var_num[nn];
1012
144866
          Trace("qcf-qregister-debug") << " is var #" << v << std::endl;
1013
144866
          d_qni_var_num[d_qni_size] = v;
1014
          //qi->addFuncParent( v, f, j );
1015
        }else{
1016
21226
          Trace("qcf-qregister-debug") << " is gterm " << nn << std::endl;
1017
21226
          d_qni_gterm[d_qni_size] = nn;
1018
        }
1019
166092
        d_qni_size++;
1020
      }
1021
    }
1022
  }else{
1023
77683
    if (expr::hasBoundVar(n))
1024
    {
1025
77557
      d_type_not = false;
1026
77557
      d_n = n;
1027
77557
      if( d_n.getKind()==NOT ){
1028
24746
        d_n = d_n[0];
1029
24746
        d_type_not = !d_type_not;
1030
      }
1031
1032
77557
      if( isHandledBoolConnective( d_n ) ){
1033
        //non-literals
1034
25805
        d_type = typ_formula;
1035
81452
        for( unsigned i=0; i<d_n.getNumChildren(); i++ ){
1036
59950
          if( d_n.getKind()!=FORALL || i==1 ){
1037
55699
            d_children.push_back( MatchGen( qi, d_n[i], false ) );
1038
55699
            if( !d_children[d_children.size()-1].isValid() ){
1039
4303
              setInvalid();
1040
4303
              break;
1041
            }
1042
          }
1043
        }
1044
      }else{
1045
51752
        d_type = typ_invalid;
1046
        //literals
1047
51752
        if( isHandledUfTerm( d_n ) ){
1048
17856
          Assert(qi->isVar(d_n));
1049
17856
          d_type = typ_pred;
1050
33896
        }else if( d_n.getKind()==BOUND_VARIABLE ){
1051
164
          Assert(d_n.getType().isBoolean());
1052
164
          d_type = typ_bool_var;
1053
33732
        }else if( d_n.getKind()==EQUAL || options::qcfTConstraint() ){
1054
91389
          for (unsigned i = 0; i < d_n.getNumChildren(); i++)
1055
          {
1056
60926
            if (expr::hasBoundVar(d_n[i]))
1057
            {
1058
45091
              if (!qi->isVar(d_n[i]))
1059
              {
1060
                Trace("qcf-qregister-debug")
1061
                    << "ERROR : not var " << d_n[i] << std::endl;
1062
              }
1063
45091
              Assert(qi->isVar(d_n[i]));
1064
45091
              if (d_n.getKind() != EQUAL && qi->isVar(d_n[i]))
1065
              {
1066
338
                d_qni_var_num[i + 1] = qi->d_var_num[d_n[i]];
1067
              }
1068
            }
1069
            else
1070
            {
1071
15835
              d_qni_gterm[i] = d_n[i];
1072
            }
1073
          }
1074
30463
          d_type = d_n.getKind() == EQUAL ? typ_eq : typ_tconstraint;
1075
30463
          Trace("qcf-tconstraint") << "T-Constraint : " << d_n << std::endl;
1076
        }
1077
      }
1078
    }else{
1079
      //we will just evaluate
1080
126
      d_n = n;
1081
126
      d_type = typ_ground;
1082
    }
1083
  }
1084
157154
  Trace("qcf-qregister-debug")  << "Done make match gen " << n << ", type = ";
1085
157154
  debugPrintType( "qcf-qregister-debug", d_type, true );
1086
157154
  Trace("qcf-qregister-debug") << std::endl;
1087
  //Assert( d_children.size()==d_children_order.size() );
1088
1089
157154
}
1090
1091
473028
void MatchGen::collectBoundVar( QuantInfo * qi, Node n, std::vector< int >& cbvars, std::map< Node, bool >& visited, bool& hasNested ) {
1092
473028
  if( visited.find( n )==visited.end() ){
1093
405005
    visited[n] = true;
1094
405005
    if( n.getKind()==FORALL ){
1095
3603
      hasNested = true;
1096
    }
1097
405005
    int v = qi->getVarNum( n );
1098
405005
    if( v!=-1 && std::find( cbvars.begin(), cbvars.end(), v )==cbvars.end() ){
1099
261701
      cbvars.push_back( v );
1100
    }
1101
833713
    for( unsigned i=0; i<n.getNumChildren(); i++ ){
1102
428708
      collectBoundVar( qi, n[i], cbvars, visited, hasNested );
1103
    }
1104
  }
1105
473028
}
1106
1107
139829
void MatchGen::determineVariableOrder( QuantInfo * qi, std::vector< int >& bvars ) {
1108
139829
  Trace("qcf-qregister-debug") << "Determine variable order " << d_n << ", #bvars = " << bvars.size() << std::endl;
1109
139829
  bool isComm = d_type==typ_formula && ( d_n.getKind()==OR || d_n.getKind()==AND || d_n.getKind()==EQUAL );
1110
139829
  if( isComm ){
1111
31700
    std::map< int, std::vector< int > > c_to_vars;
1112
31700
    std::map< int, std::vector< int > > vars_to_c;
1113
31700
    std::map< int, int > vb_count;
1114
31700
    std::map< int, int > vu_count;
1115
31700
    std::map< int, bool > has_nested;
1116
31700
    std::vector< bool > assigned;
1117
15850
    Trace("qcf-qregister-debug") << "Calculate bound variables..." << std::endl;
1118
56160
    for( unsigned i=0; i<d_children.size(); i++ ){
1119
80620
      std::map< Node, bool > visited;
1120
40310
      has_nested[i] = false;
1121
40310
      collectBoundVar( qi, d_children[i].d_n, c_to_vars[i], visited, has_nested[i] );
1122
40310
      assigned.push_back( false );
1123
40310
      vb_count[i] = 0;
1124
40310
      vu_count[i] = 0;
1125
248186
      for( unsigned j=0; j<c_to_vars[i].size(); j++ ){
1126
207876
        int v = c_to_vars[i][j];
1127
207876
        vars_to_c[v].push_back( i );
1128
207876
        if( std::find( bvars.begin(), bvars.end(), v )==bvars.end() ){
1129
189626
          vu_count[i]++;
1130
        }else{
1131
18250
          vb_count[i]++;
1132
        }
1133
      }
1134
    }
1135
    //children that bind no unbound variable, then the most number of bound, unbound variables go first
1136
15850
    Trace("qcf-qregister-vo") << "Variable order for " << d_n << " : " << std::endl;
1137
24460
    do {
1138
40310
      int min_score0 = -1;
1139
40310
      int min_score = -1;
1140
40310
      int min_score_index = -1;
1141
748534
      for( unsigned i=0; i<d_children.size(); i++ ){
1142
708224
        if( !assigned[i] ){
1143
374267
          Trace("qcf-qregister-debug2") << "Child " << i << " has b/ub : " << vb_count[i] << "/" << vu_count[i] << std::endl;
1144
374267
          int score0 = 0;//has_nested[i] ? 0 : 1;
1145
          int score;
1146
374267
          if( !options::qcfVoExp() ){
1147
374267
            score = vu_count[i];
1148
          }else{
1149
            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] )  );
1150
          }
1151
374267
          if( min_score==-1 || score0<min_score0 || ( score0==min_score0 && score<min_score ) ){
1152
68294
            min_score0 = score0;
1153
68294
            min_score = score;
1154
68294
            min_score_index = i;
1155
          }
1156
        }
1157
      }
1158
40310
      Trace("qcf-qregister-vo") << "  " << d_children_order.size()+1 << ": " << d_children[min_score_index].d_n << " : ";
1159
40310
      Trace("qcf-qregister-vo") << vu_count[min_score_index] << " " << vb_count[min_score_index] << " " << has_nested[min_score_index] << std::endl;
1160
40310
      Trace("qcf-qregister-debug") << "...assign child " << min_score_index << std::endl;
1161
40310
      Trace("qcf-qregister-debug") << "...score : " << min_score << std::endl;
1162
40310
      Assert(min_score_index != -1);
1163
      //add to children order
1164
40310
      d_children_order.push_back( min_score_index );
1165
40310
      assigned[min_score_index] = true;
1166
      //determine order internal to children
1167
40310
      d_children[min_score_index].determineVariableOrder( qi, bvars );
1168
40310
      Trace("qcf-qregister-debug")  << "...bind variables" << std::endl;
1169
      //now, make it a bound variable
1170
40310
      if( vu_count[min_score_index]>0 ){
1171
228371
        for( unsigned i=0; i<c_to_vars[min_score_index].size(); i++ ){
1172
190491
          int v = c_to_vars[min_score_index][i];
1173
190491
          if( std::find( bvars.begin(), bvars.end(), v )==bvars.end() ){
1174
241987
            for( unsigned j=0; j<vars_to_c[v].size(); j++ ){
1175
158064
              int vc = vars_to_c[v][j];
1176
158064
              vu_count[vc]--;
1177
158064
              vb_count[vc]++;
1178
            }
1179
83923
            bvars.push_back( v );
1180
          }
1181
        }
1182
      }
1183
40310
      Trace("qcf-qregister-debug") << "...done assign child " << min_score_index << std::endl;
1184
40310
    }while( d_children_order.size()!=d_children.size() );
1185
15850
    Trace("qcf-qregister-debug") << "Done assign variable ordering for " << d_n << std::endl;
1186
  }else{
1187
127989
    for( unsigned i=0; i<d_children.size(); i++ ){
1188
4010
      d_children_order.push_back( i );
1189
4010
      d_children[i].determineVariableOrder( qi, bvars );
1190
      //now add to bvars
1191
8020
      std::map< Node, bool > visited;
1192
8020
      std::vector< int > cvars;
1193
4010
      bool has_nested = false;
1194
4010
      collectBoundVar( qi, d_children[i].d_n, cvars, visited, has_nested );
1195
57835
      for( unsigned j=0; j<cvars.size(); j++ ){
1196
53825
        if( std::find( bvars.begin(), bvars.end(), cvars[j] )==bvars.end() ){
1197
6259
          bvars.push_back( cvars[j] );
1198
        }
1199
      }
1200
    }
1201
  }
1202
139829
}
1203
1204
979732
bool MatchGen::reset_round(QuantConflictFind* p)
1205
{
1206
979732
  d_wasSet = false;
1207
1333377
  for( unsigned i=0; i<d_children.size(); i++ ){
1208
353645
    if (!d_children[i].reset_round(p))
1209
    {
1210
      return false;
1211
    }
1212
  }
1213
979732
  if( d_type==typ_ground ){
1214
    // int e = p->evaluate( d_n );
1215
    // if( e==1 ){
1216
    //  d_ground_eval[0] = p->d_true;
1217
    //}else if( e==-1 ){
1218
    //  d_ground_eval[0] = p->d_false;
1219
    //}
1220
    // modified
1221
1722
    TermDb* tdb = p->getTermDatabase();
1222
1722
    QuantifiersState& qs = p->getState();
1223
5166
    for (unsigned i = 0; i < 2; i++)
1224
    {
1225
3444
      if (tdb->isEntailed(d_n, i == 0))
1226
      {
1227
68
        d_ground_eval[0] = i==0 ? p->d_true : p->d_false;
1228
      }
1229
3444
      if (qs.isInConflict())
1230
      {
1231
        return false;
1232
      }
1233
    }
1234
978010
  }else if( d_type==typ_eq ){
1235
164717
    TermDb* tdb = p->getTermDatabase();
1236
164717
    QuantifiersState& qs = p->getState();
1237
494151
    for (unsigned i = 0, size = d_n.getNumChildren(); i < size; i++)
1238
    {
1239
329434
      if (!expr::hasBoundVar(d_n[i]))
1240
      {
1241
175322
        TNode t = tdb->getEntailedTerm(d_n[i]);
1242
87661
        if (qs.isInConflict())
1243
        {
1244
          return false;
1245
        }
1246
87661
        if (t.isNull())
1247
        {
1248
2769
          d_ground_eval[i] = d_n[i];
1249
        }
1250
        else
1251
        {
1252
84892
          d_ground_eval[i] = t;
1253
        }
1254
      }
1255
    }
1256
  }
1257
979732
  d_qni_bound_cons.clear();
1258
979732
  d_qni_bound_cons_var.clear();
1259
979732
  d_qni_bound.clear();
1260
979732
  return true;
1261
}
1262
1263
1654515
void MatchGen::reset( QuantConflictFind * p, bool tgt, QuantInfo * qi ) {
1264
1654515
  d_tgt = d_type_not ? !tgt : tgt;
1265
1654515
  Debug("qcf-match") << "     Reset for : " << d_n << ", type : ";
1266
1654515
  debugPrintType( "qcf-match", d_type );
1267
1654515
  Debug("qcf-match") << ", tgt = " << d_tgt << ", children = " << d_children.size() << " " << d_children_order.size() << std::endl;
1268
1654515
  d_qn.clear();
1269
1654515
  d_qni.clear();
1270
1654515
  d_qni_bound.clear();
1271
1654515
  d_child_counter = -1;
1272
1654515
  d_use_children = true;
1273
1654515
  d_tgt_orig = d_tgt;
1274
1275
  //set up processing matches
1276
1654515
  if( d_type==typ_invalid ){
1277
    d_use_children = false;
1278
1654515
  }else if( d_type==typ_ground ){
1279
1128
    d_use_children = false;
1280
1128
    if( d_ground_eval[0]==( d_tgt ? p->d_true : p->d_false ) ){
1281
28
      d_child_counter = 0;
1282
    }
1283
1653387
  }else if( qi->isBaseMatchComplete() && options::qcfEagerTest() ){
1284
239199
    d_use_children = false;
1285
239199
    d_child_counter = 0;
1286
1414188
  }else if( d_type==typ_bool_var ){
1287
    //get current value of the variable
1288
3260
    TNode n = qi->getCurrentValue( d_n );
1289
1630
    int vn = qi->getCurrentRepVar( qi->getVarNum( n ) );
1290
1630
    if( vn==-1 ){
1291
      //evaluate the value, see if it is compatible
1292
      //int e = p->evaluate( n );
1293
      //if( ( e==1 && d_tgt ) || ( e==0 && !d_tgt ) ){
1294
      //  d_child_counter = 0;
1295
      //}
1296
      //modified
1297
      if( p->getTermDatabase()->isEntailed( n, d_tgt ) ){
1298
        d_child_counter = 0;
1299
      }
1300
    }else{
1301
      //unassigned, set match to true/false
1302
1630
      d_qni_bound[0] = vn;
1303
1630
      qi->setMatch( p, vn, d_tgt ? p->d_true : p->d_false, false, true );
1304
1630
      d_child_counter = 0;
1305
    }
1306
1630
    if( d_child_counter==0 ){
1307
1630
      d_qn.push_back( NULL );
1308
    }
1309
1412558
  }else if( d_type==typ_var ){
1310
921040
    Assert(isHandledUfTerm(d_n));
1311
1842080
    TNode f = getMatchOperator( p, d_n );
1312
921040
    Debug("qcf-match-debug") << "       reset: Var will match operators of " << f << std::endl;
1313
921040
    TNodeTrie* qni = p->getTermDatabase()->getTermArgTrie(Node::null(), f);
1314
921040
    if (qni == nullptr || qni->empty())
1315
    {
1316
      //inform irrelevant quantifiers
1317
128477
      p->setIrrelevantFunction( f );
1318
    }
1319
    else
1320
    {
1321
792563
      d_qn.push_back(qni);
1322
    }
1323
921040
    d_matched_basis = false;
1324
491518
  }else if( d_type==typ_tsym || d_type==typ_tconstraint ){
1325
3248
    for( std::map< int, int >::iterator it = d_qni_var_num.begin(); it != d_qni_var_num.end(); ++it ){
1326
1938
      int repVar = qi->getCurrentRepVar( it->second );
1327
1938
      if( qi->d_match[repVar].isNull() ){
1328
1872
        Debug("qcf-match-debug") << "Force matching on child #" << it->first << ", which is var #" << repVar << std::endl;
1329
1872
        d_qni_bound[it->first] = repVar;
1330
      }
1331
    }
1332
1310
    d_qn.push_back( NULL );
1333
490208
  }else if( d_type==typ_pred || d_type==typ_eq ){
1334
    //add initial constraint
1335
704010
    Node nn[2];
1336
    int vn[2];
1337
352005
    if( d_type==typ_pred ){
1338
153259
      nn[0] = qi->getCurrentValue( d_n );
1339
153259
      vn[0] = qi->getCurrentRepVar( qi->getVarNum( nn[0] ) );
1340
153259
      nn[1] = d_tgt ? p->d_true : p->d_false;
1341
153259
      vn[1] = -1;
1342
153259
      d_tgt = true;
1343
    }else{
1344
596238
      for( unsigned i=0; i<2; i++ ){
1345
794984
        TNode nc;
1346
397492
        std::map<int, TNode>::iterator it = d_qni_gterm.find(i);
1347
397492
        if (it != d_qni_gterm.end())
1348
        {
1349
127684
          nc = it->second;
1350
        }else{
1351
269808
          nc = d_n[i];
1352
        }
1353
397492
        nn[i] = qi->getCurrentValue( nc );
1354
397492
        vn[i] = qi->getCurrentRepVar( qi->getVarNum( nn[i] ) );
1355
      }
1356
    }
1357
    bool success;
1358
352005
    if( vn[0]==-1 && vn[1]==-1 ){
1359
      //Trace("qcf-explain") << "    reset : " << d_n << " check ground values " << nn[0] << " " << nn[1] << " (tgt=" << d_tgt << ")" << std::endl;
1360
413
      Debug("qcf-match-debug") << "       reset: check ground values " << nn[0] << " " << nn[1] << " (" << d_tgt << ")" << std::endl;
1361
      //just compare values
1362
826
      if( d_tgt ){
1363
381
        success = p->areMatchEqual( nn[0], nn[1] );
1364
      }else{
1365
32
        if (p->atConflictEffort()) {
1366
17
          success = p->areDisequal( nn[0], nn[1] );
1367
        }else{
1368
15
          success = p->areMatchDisequal( nn[0], nn[1] );
1369
        }
1370
      }
1371
    }else{
1372
      //otherwise, add a constraint to a variable  TODO: this may be over-eager at effort > conflict, since equality may be a propagation
1373
351592
      if( vn[1]!=-1 && vn[0]==-1 ){
1374
        //swap
1375
154370
        Node t = nn[1];
1376
77185
        nn[1] = nn[0];
1377
77185
        nn[0] = t;
1378
77185
        vn[0] = vn[1];
1379
77185
        vn[1] = -1;
1380
      }
1381
351592
      Debug("qcf-match-debug") << "       reset: add constraint " << vn[0] << " -> " << nn[1] << " (vn=" << vn[1] << ")" << std::endl;
1382
      //add some constraint
1383
351592
      int addc = qi->addConstraint( p, vn[0], nn[1], vn[1], d_tgt, false );
1384
351592
      success = addc!=-1;
1385
      //if successful and non-redundant, store that we need to cleanup this
1386
351592
      if( addc==1 ){
1387
        //Trace("qcf-explain") << "       reset: " << d_n << " add constraint " << vn[0] << " -> " << nn[1] << " (vn=" << vn[1] << ")" << ", d_tgt = " << d_tgt << std::endl;
1388
1054380
        for( unsigned i=0; i<2; i++ ){
1389
702920
          if( vn[i]!=-1 && std::find( d_qni_bound_except.begin(), d_qni_bound_except.end(), i )==d_qni_bound_except.end() ){
1390
417866
            d_qni_bound[vn[i]] = vn[i];
1391
          }
1392
        }
1393
351460
        d_qni_bound_cons[vn[0]] = nn[1];
1394
351460
        d_qni_bound_cons_var[vn[0]] = vn[1];
1395
      }
1396
    }
1397
    //if successful, we will bind values to variables
1398
352005
    if( success ){
1399
351583
      d_qn.push_back( NULL );
1400
352005
    }
1401
  }else{
1402
138203
    if( d_children.empty() ){
1403
      //add dummy
1404
      d_qn.push_back( NULL );
1405
    }else{
1406
138203
      if( d_tgt && d_n.getKind()==FORALL ){
1407
        //fail
1408
120017
      } else if (d_n.getKind() == FORALL && p->atConflictEffort() &&
1409
3503
                 !options::qcfNestedConflict()) {
1410
        //fail
1411
      }else{
1412
        //reset the first child to d_tgt
1413
113011
        d_child_counter = 0;
1414
113011
        getChild( d_child_counter )->reset( p, d_tgt, qi );
1415
      }
1416
    }
1417
  }
1418
1654515
  d_binding = false;
1419
1654515
  d_wasSet = true;
1420
1654515
  Debug("qcf-match") << "     reset: Finished reset for " << d_n << ", success = " << ( !d_qn.empty() || d_child_counter!=-1 ) << std::endl;
1421
1654515
}
1422
1423
3121380
bool MatchGen::getNextMatch( QuantConflictFind * p, QuantInfo * qi ) {
1424
3121380
  Debug("qcf-match") << "     Get next match for : " << d_n << ", type = ";
1425
3121380
  debugPrintType( "qcf-match", d_type );
1426
3121380
  Debug("qcf-match") << ", children = " << d_children.size() << ", binding = " << d_binding << std::endl;
1427
3121380
  if( !d_use_children ){
1428
478996
    if( d_child_counter==0 ){
1429
239227
      d_child_counter = -1;
1430
239227
      return true;
1431
    }else{
1432
239769
      d_wasSet = false;
1433
239769
      return false;
1434
    }
1435
2642384
  }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 ){
1436
2252930
    bool success = false;
1437
2252930
    bool terminate = false;
1438
1352818
    do {
1439
3605748
      bool doReset = false;
1440
3605748
      bool doFail = false;
1441
3605748
      if( !d_binding ){
1442
2632934
        if( doMatching( p, qi ) ){
1443
1361371
          Debug("qcf-match-debug") << "     - Matching succeeded" << std::endl;
1444
1361371
          d_binding = true;
1445
1361371
          d_binding_it = d_qni_bound.begin();
1446
1361371
          doReset = true;
1447
          //for tconstraint, add constraint
1448
1361371
          if( d_type==typ_tconstraint ){
1449
883
            std::map< Node, bool >::iterator it = qi->d_tconstraints.find( d_n );
1450
883
            if( it==qi->d_tconstraints.end() ){
1451
883
              qi->d_tconstraints[d_n] = d_tgt;
1452
              //store that we added this constraint
1453
883
              d_qni_bound_cons[0] = d_n;
1454
            }else if( d_tgt!=it->second ){
1455
              success = false;
1456
              terminate = true;
1457
            }
1458
          }
1459
        }else{
1460
1271563
          Debug("qcf-match-debug") << "     - Matching failed" << std::endl;
1461
1271563
          success = false;
1462
1271563
          terminate = true;
1463
        }
1464
      }else{
1465
972814
        doFail = true;
1466
      }
1467
3605748
      if( d_binding ){
1468
        //also need to create match for each variable we bound
1469
2334185
        success = true;
1470
2334185
        Debug("qcf-match-debug") << "     Produce matches for bound variables by " << d_n << ", type = ";
1471
2334185
        debugPrintType( "qcf-match-debug", d_type );
1472
2334185
        Debug("qcf-match-debug") << "..." << std::endl;
1473
1474
10143465
        while( ( success && d_binding_it!=d_qni_bound.end() ) || doFail ){
1475
3904640
          QuantInfo::VarMgMap::const_iterator itm;
1476
3904640
          if( !doFail ){
1477
2931826
            Debug("qcf-match-debug") << "       check variable " << d_binding_it->second << std::endl;
1478
2931826
            itm = qi->var_mg_find( d_binding_it->second );
1479
          }
1480
3904640
          if( doFail || ( d_binding_it->first!=0 && itm != qi->var_mg_end() ) ){
1481
2598392
            Debug("qcf-match-debug") << "       we had bound variable " << d_binding_it->second << ", reset = " << doReset << std::endl;
1482
2598392
            if( doReset ){
1483
1004109
              itm->second->reset( p, true, qi );
1484
            }
1485
2598392
            if( doFail || !itm->second->getNextMatch( p, qi ) ){
1486
1302310
              do {
1487
3276597
                if( d_binding_it==d_qni_bound.begin() ){
1488
1352818
                  Debug("qcf-match-debug") << "       failed." << std::endl;
1489
1352818
                  success = false;
1490
                }else{
1491
1923779
                  --d_binding_it;
1492
1923779
                  Debug("qcf-match-debug") << "       decrement..." << std::endl;
1493
                }
1494
6502686
              }while( success &&
1495
3330771
                      ( d_binding_it->first==0 ||
1496
1406992
                        (!qi->containsVarMg(d_binding_it->second))));
1497
1974287
              doReset = false;
1498
1974287
              doFail = false;
1499
            }else{
1500
624105
              Debug("qcf-match-debug") << "       increment..." << std::endl;
1501
624105
              ++d_binding_it;
1502
624105
              doReset = true;
1503
            }
1504
          }else{
1505
1306248
            Debug("qcf-match-debug") << "       skip..." << d_binding_it->second << std::endl;
1506
1306248
            ++d_binding_it;
1507
1306248
            doReset = true;
1508
          }
1509
        }
1510
2334185
        if( !success ){
1511
1352818
          d_binding = false;
1512
        }else{
1513
981367
          terminate = true;
1514
981367
          if( d_binding_it==d_qni_bound.begin() ){
1515
4191
            d_binding = false;
1516
          }
1517
        }
1518
      }
1519
3605748
    }while( !terminate );
1520
    //if not successful, clean up the variables you bound
1521
2252930
    if( !success ){
1522
1271563
      if( d_type==typ_eq || d_type==typ_pred ){
1523
        //clean up the constraints you added
1524
699587
        for( std::map< int, TNode >::iterator it = d_qni_bound_cons.begin(); it != d_qni_bound_cons.end(); ++it ){
1525
349525
          if( !it->second.isNull() ){
1526
349525
            Debug("qcf-match") << "       Clean up bound var " << it->first << (d_tgt ? "!" : "") << " = " << it->second << std::endl;
1527
349525
            std::map< int, int >::iterator itb = d_qni_bound_cons_var.find( it->first );
1528
349525
            int vn = itb!=d_qni_bound_cons_var.end() ? itb->second : -1;
1529
            //Trace("qcf-explain") << "       cleanup: " << d_n << " remove constraint " << it->first << " -> " << it->second << " (vn=" << vn << ")" << ", d_tgt = " << d_tgt << std::endl;
1530
349525
            qi->addConstraint( p, it->first, it->second, vn, d_tgt, true );
1531
          }
1532
        }
1533
350062
        d_qni_bound_cons.clear();
1534
350062
        d_qni_bound_cons_var.clear();
1535
350062
        d_qni_bound.clear();
1536
      }else{
1537
        //clean up the matches you set
1538
1558103
        for( std::map< int, int >::iterator it = d_qni_bound.begin(); it != d_qni_bound.end(); ++it ){
1539
636602
          Debug("qcf-match") << "       Clean up bound var " << it->second << std::endl;
1540
636602
          Assert(it->second < qi->getNumVars());
1541
636602
          qi->unsetMatch( p, it->second );
1542
636602
          qi->d_match_term[ it->second ] = TNode::null();
1543
        }
1544
921501
        d_qni_bound.clear();
1545
      }
1546
1271563
      if( d_type==typ_tconstraint ){
1547
        //remove constraint if applicable
1548
875
        if( d_qni_bound_cons.find( 0 )!=d_qni_bound_cons.end() ){
1549
875
          qi->d_tconstraints.erase( d_n );
1550
875
          d_qni_bound_cons.clear();
1551
        }
1552
      }
1553
    }
1554
2252930
    Debug("qcf-match") << "    ...finished matching for " << d_n << ", success = " << success << std::endl;
1555
2252930
    d_wasSet = success;
1556
2252930
    return success;
1557
  }
1558
389454
  else if (d_type == typ_formula)
1559
  {
1560
389454
    bool success = false;
1561
389454
    if( d_child_counter<0 ){
1562
25192
      if( d_child_counter<-1 ){
1563
        success = true;
1564
        d_child_counter = -1;
1565
      }
1566
    }else{
1567
2422498
      while( !success && d_child_counter>=0 ){
1568
        //transition system based on d_child_counter
1569
1029118
        if( d_n.getKind()==OR || d_n.getKind()==AND ){
1570
764322
          if( (d_n.getKind()==AND)==d_tgt ){
1571
            //all children must match simultaneously
1572
709049
            if( getChild( d_child_counter )->getNextMatch( p, qi ) ){
1573
405665
              if( d_child_counter<(int)(getNumChildren()-1) ){
1574
249396
                d_child_counter++;
1575
249396
                Debug("qcf-match-debug") << "       Reset child " << d_child_counter << " of " << d_n << std::endl;
1576
249396
                getChild( d_child_counter )->reset( p, d_tgt, qi );
1577
              }else{
1578
156269
                success = true;
1579
              }
1580
            }else{
1581
              //if( std::find( d_independent.begin(), d_independent.end(), d_child_counter )!=d_independent.end() ){
1582
              //  d_child_counter--;
1583
              //}else{
1584
303384
              d_child_counter--;
1585
              //}
1586
            }
1587
          }else{
1588
            //one child must match
1589
55273
            if( !getChild( d_child_counter )->getNextMatch( p, qi ) ){
1590
26608
              if( d_child_counter<(int)(getNumChildren()-1) ){
1591
14986
                d_child_counter++;
1592
14986
                Debug("qcf-match-debug") << "       Reset child " << d_child_counter << " of " << d_n << ", one match" << std::endl;
1593
14986
                getChild( d_child_counter )->reset( p, d_tgt, qi );
1594
              }else{
1595
11622
                d_child_counter = -1;
1596
              }
1597
            }else{
1598
28665
              success = true;
1599
            }
1600
          }
1601
264796
        }else if( d_n.getKind()==EQUAL ){
1602
          //construct match based on both children
1603
231783
          if( d_child_counter%2==0 ){
1604
175858
            if( getChild( 0 )->getNextMatch( p, qi ) ){
1605
94320
              d_child_counter++;
1606
94320
              getChild( 1 )->reset( p, d_child_counter==1, qi );
1607
            }else{
1608
81538
              if( d_child_counter==0 ){
1609
40820
                d_child_counter = 2;
1610
40820
                getChild( 0 )->reset( p, !d_tgt, qi );
1611
              }else{
1612
40718
                d_child_counter = -1;
1613
              }
1614
            }
1615
          }
1616
231783
          if( d_child_counter>=0 && d_child_counter%2==1 ){
1617
150245
            if( getChild( 1 )->getNextMatch( p, qi ) ){
1618
56158
              success = true;
1619
            }else{
1620
94087
              d_child_counter--;
1621
            }
1622
          }
1623
33013
        }else if( d_n.getKind()==ITE ){
1624
29609
          if( d_child_counter%2==0 ){
1625
18941
            int index1 = d_child_counter==4 ? 1 : 0;
1626
18941
            if( getChild( index1 )->getNextMatch( p, qi ) ){
1627
13915
              d_child_counter++;
1628
13915
              getChild( d_child_counter==5 ? 2 : (d_tgt==(d_child_counter==1) ? 1 : 2) )->reset( p, d_tgt, qi );
1629
            }else{
1630
5026
              if (d_child_counter == 4)
1631
              {
1632
1670
                d_child_counter = -1;
1633
              }else{
1634
3356
                d_child_counter +=2;
1635
3356
                getChild( d_child_counter==2 ? 0 : 1 )->reset( p, d_child_counter==2 ? !d_tgt : d_tgt, qi );
1636
              }
1637
            }
1638
          }
1639
29609
          if( d_child_counter>=0 && d_child_counter%2==1 ){
1640
24583
            int index2 = d_child_counter==5 ? 2 : (d_tgt==(d_child_counter==1) ? 1 : 2);
1641
24583
            if( getChild( index2 )->getNextMatch( p, qi ) ){
1642
10730
              success = true;
1643
            }else{
1644
13853
              d_child_counter--;
1645
            }
1646
          }
1647
3404
        }else if( d_n.getKind()==FORALL ){
1648
3404
          if( getChild( d_child_counter )->getNextMatch( p, qi ) ){
1649
390
            success = true;
1650
          }else{
1651
3014
            d_child_counter = -1;
1652
          }
1653
        }
1654
      }
1655
364262
        d_wasSet = success;
1656
364262
      Debug("qcf-match") << "    ...finished construct match for " << d_n << ", success = " << success << std::endl;
1657
364262
      return success;
1658
    }
1659
  }
1660
25192
  Debug("qcf-match") << "    ...already finished for " << d_n << std::endl;
1661
25192
  return false;
1662
}
1663
1664
2632934
bool MatchGen::doMatching( QuantConflictFind * p, QuantInfo * qi ) {
1665
2632934
  if( !d_qn.empty() ){
1666
2151463
    if( d_qn[0]==NULL ){
1667
354523
      d_qn.clear();
1668
354523
      return true;
1669
    }else{
1670
1796940
      Assert(d_type == typ_var);
1671
1796940
      Assert(d_qni_size > 0);
1672
      bool invalidMatch;
1673
7536379
      do {
1674
9333319
        invalidMatch = false;
1675
9333319
        Debug("qcf-match-debug") << "       Do matching " << d_n << " " << d_qn.size() << " " << d_qni.size() << std::endl;
1676
9333319
        if( d_qn.size()==d_qni.size()+1 ) {
1677
4455959
          int index = (int)d_qni.size();
1678
          //initialize
1679
8911918
          TNode val;
1680
4455959
          std::map< int, int >::iterator itv = d_qni_var_num.find( index );
1681
4455959
          if( itv!=d_qni_var_num.end() ){
1682
            //get the representative variable this variable is equal to
1683
4170215
            int repVar = qi->getCurrentRepVar( itv->second );
1684
4170215
            Debug("qcf-match-debug") << "       Match " << index << " is a variable " << itv->second << ", which is repVar " << repVar << std::endl;
1685
            //get the value the rep variable
1686
            //std::map< int, TNode >::iterator itm = qi->d_match.find( repVar );
1687
4170215
            if( !qi->d_match[repVar].isNull() ){
1688
2623702
              val = qi->d_match[repVar];
1689
2623702
              Debug("qcf-match-debug") << "       Variable is already bound to " << val << std::endl;
1690
            }else{
1691
              //binding a variable
1692
1546513
              d_qni_bound[index] = repVar;
1693
              std::map<TNode, TNodeTrie>::iterator it =
1694
1546513
                  d_qn[index]->d_data.begin();
1695
1546513
              if( it != d_qn[index]->d_data.end() ) {
1696
1546513
                d_qni.push_back( it );
1697
                //set the match
1698
1546513
                if( it->first.getType().isComparableTo( qi->d_var_types[repVar] ) && qi->setMatch( p, d_qni_bound[index], it->first, true, true ) ){
1699
1415055
                  Debug("qcf-match-debug") << "       Binding variable" << std::endl;
1700
1415055
                  if( d_qn.size()<d_qni_size ){
1701
687092
                    d_qn.push_back( &it->second );
1702
                  }
1703
                }else{
1704
131458
                  Debug("qcf-match") << "       Binding variable, currently fail." << std::endl;
1705
131458
                  invalidMatch = true;
1706
                }
1707
              }else{
1708
                Debug("qcf-match-debug") << "       Binding variable, fail, no more variables to bind" << std::endl;
1709
                d_qn.pop_back();
1710
              }
1711
            }
1712
          }else{
1713
285744
            Debug("qcf-match-debug") << "       Match " << index << " is ground term" << std::endl;
1714
285744
            Assert(d_qni_gterm.find(index) != d_qni_gterm.end());
1715
285744
            val = d_qni_gterm[index];
1716
285744
            Assert(!val.isNull());
1717
          }
1718
4455959
          if( !val.isNull() ){
1719
5818892
            Node valr = p->getRepresentative(val);
1720
            //constrained by val
1721
            std::map<TNode, TNodeTrie>::iterator it =
1722
2909446
                d_qn[index]->d_data.find(valr);
1723
2909446
            if( it!=d_qn[index]->d_data.end() ){
1724
1286228
              Debug("qcf-match-debug") << "       Match" << std::endl;
1725
1286228
              d_qni.push_back( it );
1726
1286228
              if( d_qn.size()<d_qni_size ){
1727
1173393
                d_qn.push_back( &it->second );
1728
              }
1729
            }else{
1730
1623218
              Debug("qcf-match-debug") << "       Failed to match" << std::endl;
1731
1623218
              d_qn.pop_back();
1732
            }
1733
          }
1734
        }else{
1735
4877360
          Assert(d_qn.size() == d_qni.size());
1736
4877360
          int index = d_qni.size()-1;
1737
          //increment if binding this variable
1738
4877360
          bool success = false;
1739
4877360
          std::map< int, int >::iterator itb = d_qni_bound.find( index );
1740
4877360
          if( itb!=d_qni_bound.end() ){
1741
3597152
            d_qni[index]++;
1742
3597152
            if( d_qni[index]!=d_qn[index]->d_data.end() ){
1743
2054736
              success = true;
1744
2054736
              if( qi->setMatch( p, itb->second, d_qni[index]->first, true, true ) ){
1745
1968961
                Debug("qcf-match-debug") << "       Bind next variable" << std::endl;
1746
1968961
                if( d_qn.size()<d_qni_size ){
1747
1802911
                  d_qn.push_back( &d_qni[index]->second );
1748
                }
1749
              }else{
1750
85775
                Debug("qcf-match-debug") << "       Bind next variable, currently fail" << std::endl;
1751
85775
                invalidMatch = true;
1752
              }
1753
            }else{
1754
1542416
              qi->unsetMatch( p, itb->second );
1755
1542416
              qi->d_match_term[ itb->second ] = TNode::null();
1756
1542416
              Debug("qcf-match-debug") << "       Bind next variable, no more variables to bind" << std::endl;
1757
            }
1758
          }else{
1759
            //TODO : if it equal to something else, also try that
1760
          }
1761
          //if not incrementing, move to next
1762
4877360
          if( !success ){
1763
2822624
            d_qn.pop_back();
1764
2822624
            d_qni.pop_back();
1765
          }
1766
        }
1767
9333319
      }while( ( !d_qn.empty() && d_qni.size()!=d_qni_size ) || invalidMatch );
1768
1796940
      if( d_qni.size()==d_qni_size ){
1769
        //Assert( !d_qni[d_qni.size()-1]->second.d_data.empty() );
1770
        //Debug("qcf-match-debug") << "       We matched " << d_qni[d_qni.size()-1]->second.d_children.begin()->first << std::endl;
1771
1006848
        Assert(!d_qni[d_qni.size() - 1]->second.d_data.empty());
1772
2013696
        TNode t = d_qni[d_qni.size()-1]->second.d_data.begin()->first;
1773
1006848
        Debug("qcf-match-debug") << "       " << d_n << " matched " << t << std::endl;
1774
1006848
        qi->d_match_term[d_qni_var_num[0]] = t;
1775
        //set the match terms
1776
3039790
        for( std::map< int, int >::iterator it = d_qni_bound.begin(); it != d_qni_bound.end(); ++it ){
1777
2032942
          Debug("qcf-match-debug") << "       position " << it->first << " bounded " << it->second << " / " << qi->d_q[0].getNumChildren() << std::endl;
1778
          //if( it->second<(int)qi->d_q[0].getNumChildren() ){   //if it is an actual variable, we are interested in knowing the actual term
1779
2032942
          if( it->first>0 ){
1780
1559146
            Assert(!qi->d_match[it->second].isNull());
1781
1559146
            Assert(p->areEqual(t[it->first - 1], qi->d_match[it->second]));
1782
1559146
            qi->d_match_term[it->second] = t[it->first-1];
1783
          }
1784
          //}
1785
        }
1786
      }
1787
    }
1788
  }
1789
2278411
  return !d_qn.empty();
1790
}
1791
1792
7267234
void MatchGen::debugPrintType( const char * c, short typ, bool isTrace ) {
1793
7267234
  if( isTrace ){
1794
157154
    switch( typ ){
1795
8684
    case typ_invalid: Trace(c) << "invalid";break;
1796
126
    case typ_ground: Trace(c) << "ground";break;
1797
30125
    case typ_eq: Trace(c) << "eq";break;
1798
17856
    case typ_pred: Trace(c) << "pred";break;
1799
21502
    case typ_formula: Trace(c) << "formula";break;
1800
77980
    case typ_var: Trace(c) << "var";break;
1801
164
    case typ_bool_var: Trace(c) << "bool_var";break;
1802
    }
1803
  }else{
1804
7110080
    switch( typ ){
1805
    case typ_invalid: Debug(c) << "invalid";break;
1806
2284
    case typ_ground: Debug(c) << "ground";break;
1807
1404114
    case typ_eq: Debug(c) << "eq";break;
1808
938608
    case typ_pred: Debug(c) << "pred";break;
1809
580634
    case typ_formula: Debug(c) << "formula";break;
1810
4170337
    case typ_var: Debug(c) << "var";break;
1811
8150
    case typ_bool_var: Debug(c) << "bool_var";break;
1812
    }
1813
  }
1814
7267234
}
1815
1816
5868
void MatchGen::setInvalid() {
1817
5868
  d_type = typ_invalid;
1818
5868
  d_children.clear();
1819
5868
}
1820
1821
259248
bool MatchGen::isHandledBoolConnective( TNode n ) {
1822
259248
  return TermUtil::isBoolConnectiveTerm( n ) && n.getKind()!=SEP_STAR;
1823
}
1824
1825
2080063
bool MatchGen::isHandledUfTerm( TNode n ) {
1826
  //return n.getKind()==APPLY_UF || n.getKind()==STORE || n.getKind()==SELECT ||
1827
  //       n.getKind()==APPLY_CONSTRUCTOR || n.getKind()==APPLY_SELECTOR_TOTAL || n.getKind()==APPLY_TESTER;
1828
  //TODO : treat APPLY_TESTER as a T-constraint instead of matching (currently leads to overabundance of instantiations)
1829
  //return inst::Trigger::isAtomicTriggerKind( n.getKind() ) && ( !options::qcfTConstraint() || n.getKind()!=APPLY_TESTER );
1830
2080063
  return inst::TriggerTermInfo::isAtomicTriggerKind(n.getKind());
1831
}
1832
1833
921040
Node MatchGen::getMatchOperator( QuantConflictFind * p, Node n ) {
1834
921040
  if( isHandledUfTerm( n ) ){
1835
921040
    return p->getTermDatabase()->getMatchOperator( n );
1836
  }else{
1837
    return Node::null();
1838
  }
1839
}
1840
1841
bool MatchGen::isHandled( TNode n ) {
1842
  if (n.getKind() != BOUND_VARIABLE && expr::hasBoundVar(n))
1843
  {
1844
    if( !isHandledBoolConnective( n ) && !isHandledUfTerm( n ) && n.getKind()!=EQUAL && n.getKind()!=ITE ){
1845
      return false;
1846
    }
1847
    for( unsigned i=0; i<n.getNumChildren(); i++ ){
1848
      if( !isHandled( n[i] ) ){
1849
        return false;
1850
      }
1851
    }
1852
  }
1853
  return true;
1854
}
1855
1856
4928
QuantConflictFind::QuantConflictFind(QuantifiersState& qs,
1857
                                     QuantifiersInferenceManager& qim,
1858
                                     QuantifiersRegistry& qr,
1859
4928
                                     TermRegistry& tr)
1860
    : QuantifiersModule(qs, qim, qr, tr),
1861
      d_conflict(qs.getSatContext(), false),
1862
      d_true(NodeManager::currentNM()->mkConst<bool>(true)),
1863
      d_false(NodeManager::currentNM()->mkConst<bool>(false)),
1864
4928
      d_effort(EFFORT_INVALID)
1865
{
1866
4928
}
1867
1868
//-------------------------------------------------- registration
1869
1870
23679
void QuantConflictFind::registerQuantifier( Node q ) {
1871
23679
  if (d_qreg.hasOwnership(q, this))
1872
  {
1873
21984
    d_quants.push_back( q );
1874
21984
    d_quant_id[q] = d_quants.size();
1875
21984
    if( Trace.isOn("qcf-qregister") ){
1876
      Trace("qcf-qregister") << "Register ";
1877
      debugPrintQuant( "qcf-qregister", q );
1878
      Trace("qcf-qregister") << " : " << q << std::endl;
1879
    }
1880
    //make QcfNode structure
1881
21984
    Trace("qcf-qregister") << "- Get relevant equality/disequality pairs, calculate flattening..." << std::endl;
1882
21984
    d_qinfo[q].initialize( this, q, q[1] );
1883
1884
    //debug print
1885
21984
    if( Trace.isOn("qcf-qregister") ){
1886
      Trace("qcf-qregister") << "- Flattened structure is :" << std::endl;
1887
      Trace("qcf-qregister") << "    ";
1888
      debugPrintQuantBody( "qcf-qregister", q, q[1] );
1889
      Trace("qcf-qregister") << std::endl;
1890
      if( d_qinfo[q].d_vars.size()>q[0].getNumChildren() ){
1891
        Trace("qcf-qregister") << "  with additional constraints : " << std::endl;
1892
        for( unsigned j=q[0].getNumChildren(); j<d_qinfo[q].d_vars.size(); j++ ){
1893
          Trace("qcf-qregister") << "    ?x" << j << " = ";
1894
          debugPrintQuantBody( "qcf-qregister", q, d_qinfo[q].d_vars[j], false );
1895
          Trace("qcf-qregister") << std::endl;
1896
        }
1897
      }
1898
      Trace("qcf-qregister") << "Done registering quantifier." << std::endl;
1899
    }
1900
  }
1901
23679
}
1902
1903
381
bool QuantConflictFind::areMatchEqual( TNode n1, TNode n2 ) {
1904
  //if( d_effort==QuantConflictFind::effort_mc ){
1905
  //  return n1==n2 || !areDisequal( n1, n2 );
1906
  //}else{
1907
381
  return n1==n2;
1908
  //}
1909
}
1910
1911
15
bool QuantConflictFind::areMatchDisequal( TNode n1, TNode n2 ) {
1912
  // if( d_effort==QuantConflictFind::Effort::Conflict ){
1913
  //  return areDisequal( n1, n2 );
1914
  //}else{
1915
15
  return n1!=n2;
1916
  //}
1917
}
1918
1919
//-------------------------------------------------- check function
1920
1921
60242
bool QuantConflictFind::needsCheck( Theory::Effort level ) {
1922
60242
  bool performCheck = false;
1923
60242
  if( options::quantConflictFind() && !d_conflict ){
1924
60238
    if( level==Theory::EFFORT_LAST_CALL ){
1925
4275
      performCheck = options::qcfWhenMode() == options::QcfWhenMode::LAST_CALL;
1926
55963
    }else if( level==Theory::EFFORT_FULL ){
1927
16471
      performCheck = options::qcfWhenMode() == options::QcfWhenMode::DEFAULT;
1928
39492
    }else if( level==Theory::EFFORT_STANDARD ){
1929
39492
      performCheck = options::qcfWhenMode() == options::QcfWhenMode::STD;
1930
    }
1931
  }
1932
60242
  return performCheck;
1933
}
1934
1935
20748
void QuantConflictFind::reset_round( Theory::Effort level ) {
1936
20748
  Trace("qcf-check") << "QuantConflictFind::reset_round" << std::endl;
1937
20748
  Trace("qcf-check") << "Compute relevant equivalence classes..." << std::endl;
1938
20748
  d_eqcs.clear();
1939
1940
20748
  eq::EqClassesIterator eqcs_i = eq::EqClassesIterator(getEqualityEngine());
1941
20748
  TermDb* tdb = getTermDatabase();
1942
2288830
  while (!eqcs_i.isFinished())
1943
  {
1944
2268082
    Node r = (*eqcs_i);
1945
1134041
    if (tdb->hasTermCurrent(r))
1946
    {
1947
2268082
      TypeNode rtn = r.getType();
1948
1134041
      if (!options::cegqi() || !TermUtil::hasInstConstAttr(r))
1949
      {
1950
1077760
        d_eqcs[rtn].push_back(r);
1951
      }
1952
    }
1953
1134041
    ++eqcs_i;
1954
  }
1955
20748
}
1956
1957
128477
void QuantConflictFind::setIrrelevantFunction( TNode f ) {
1958
128477
  if( d_irr_func.find( f )==d_irr_func.end() ){
1959
19220
    d_irr_func[f] = true;
1960
19220
    std::map< TNode, std::vector< Node > >::iterator it = d_func_rel_dom.find( f );
1961
19220
    if( it != d_func_rel_dom.end()){
1962
76608
      for( unsigned j=0; j<it->second.size(); j++ ){
1963
62128
        d_irr_quant[it->second[j]] = true;
1964
      }
1965
    }
1966
  }
1967
128477
}
1968
1969
namespace {
1970
1971
// Returns the beginning of a range of efforts. The range can be iterated
1972
// through as unsigned using operator++.
1973
16471
inline QuantConflictFind::Effort QcfEffortStart() {
1974
16471
  return QuantConflictFind::EFFORT_CONFLICT;
1975
}
1976
1977
// Returns the beginning of a range of efforts. The value returned is included
1978
// in the range.
1979
16471
inline QuantConflictFind::Effort QcfEffortEnd() {
1980
16471
  return options::qcfMode() == options::QcfMode::PROP_EQ
1981
16471
             ? QuantConflictFind::EFFORT_PROP_EQ
1982
16471
             : QuantConflictFind::EFFORT_CONFLICT;
1983
}
1984
1985
}  // namespace
1986
1987
/** check */
1988
60841
void QuantConflictFind::check(Theory::Effort level, QEffort quant_e)
1989
{
1990
77312
  CodeTimer codeTimer(d_qstate.getStats().d_qcf_time);
1991
60841
  if (quant_e != QEFFORT_CONFLICT)
1992
  {
1993
44370
    return;
1994
  }
1995
16471
  Trace("qcf-check") << "QCF : check : " << level << std::endl;
1996
16471
  if (d_conflict)
1997
  {
1998
    Trace("qcf-check2") << "QCF : finished check : already in conflict."
1999
                        << std::endl;
2000
    if (level >= Theory::EFFORT_FULL)
2001
    {
2002
      Trace("qcf-warn") << "ALREADY IN CONFLICT? " << level << std::endl;
2003
    }
2004
    return;
2005
  }
2006
16471
  unsigned addedLemmas = 0;
2007
16471
  ++(d_statistics.d_inst_rounds);
2008
16471
  double clSet = 0;
2009
16471
  int prevEt = 0;
2010
16471
  if (Trace.isOn("qcf-engine"))
2011
  {
2012
    prevEt = d_statistics.d_entailment_checks.get();
2013
    clSet = double(clock()) / double(CLOCKS_PER_SEC);
2014
    Trace("qcf-engine") << "---Conflict Find Engine Round, effort = " << level
2015
                        << "---" << std::endl;
2016
  }
2017
2018
  // reset the round-specific information
2019
16471
  d_irr_func.clear();
2020
16471
  d_irr_quant.clear();
2021
2022
16471
  if (Trace.isOn("qcf-debug"))
2023
  {
2024
    Trace("qcf-debug") << std::endl;
2025
    debugPrint("qcf-debug");
2026
    Trace("qcf-debug") << std::endl;
2027
  }
2028
16471
  bool isConflict = false;
2029
16471
  FirstOrderModel* fm = d_treg.getModel();
2030
16471
  unsigned nquant = fm->getNumAssertedQuantifiers();
2031
  // for each effort level (find conflict, find propagating)
2032
47269
  for (unsigned e = QcfEffortStart(), end = QcfEffortEnd(); e <= end; ++e)
2033
  {
2034
    // set the effort (data member for convienence of access)
2035
32103
    d_effort = static_cast<Effort>(e);
2036
64206
    Trace("qcf-check") << "Checking quantified formulas at effort " << e
2037
32103
                       << "..." << std::endl;
2038
    // for each quantified formula
2039
354294
    for (unsigned i = 0; i < nquant; i++)
2040
    {
2041
645221
      Node q = fm->getAssertedQuantifier(i, true);
2042
969090
      if (d_qreg.hasOwnership(q, this)
2043
616536
          && d_irr_quant.find(q) == d_irr_quant.end()
2044
1191536
          && fm->isQuantifierActive(q))
2045
      {
2046
        // check this quantified formula
2047
222394
        checkQuantifiedFormula(q, isConflict, addedLemmas);
2048
222394
        if (d_conflict || d_qstate.isInConflict())
2049
        {
2050
839
          break;
2051
        }
2052
      }
2053
    }
2054
    // We are done if we added a lemma, or discovered a conflict in another
2055
    // way. An example of the latter case is when two disequal congruent terms
2056
    // are discovered during term indexing.
2057
32103
    if (addedLemmas > 0 || d_qstate.isInConflict())
2058
    {
2059
1305
      break;
2060
    }
2061
  }
2062
16471
  if (isConflict)
2063
  {
2064
    d_conflict.set(true);
2065
  }
2066
16471
  if (Trace.isOn("qcf-engine"))
2067
  {
2068
    double clSet2 = double(clock()) / double(CLOCKS_PER_SEC);
2069
    Trace("qcf-engine") << "Finished conflict find engine, time = "
2070
                        << (clSet2 - clSet);
2071
    if (addedLemmas > 0)
2072
    {
2073
      Trace("qcf-engine") << ", effort = "
2074
                          << (d_effort == EFFORT_CONFLICT
2075
                                  ? "conflict"
2076
                                  : (d_effort == EFFORT_PROP_EQ ? "prop_eq"
2077
                                                                : "mc"));
2078
      Trace("qcf-engine") << ", addedLemmas = " << addedLemmas;
2079
    }
2080
    Trace("qcf-engine") << std::endl;
2081
    int currEt = d_statistics.d_entailment_checks.get();
2082
    if (currEt != prevEt)
2083
    {
2084
      Trace("qcf-engine") << "  Entailment checks = " << (currEt - prevEt)
2085
                          << std::endl;
2086
    }
2087
  }
2088
16471
  Trace("qcf-check2") << "QCF : finished check : " << level << std::endl;
2089
}
2090
2091
222394
void QuantConflictFind::checkQuantifiedFormula(Node q,
2092
                                               bool& isConflict,
2093
                                               unsigned& addedLemmas)
2094
{
2095
222394
  QuantInfo* qi = &d_qinfo[q];
2096
222394
  Assert(d_qinfo.find(q) != d_qinfo.end());
2097
222394
  if (!qi->matchGeneratorIsValid())
2098
  {
2099
    // quantified formula is not properly set up for matching
2100
101792
    return;
2101
  }
2102
120602
  if (Trace.isOn("qcf-check"))
2103
  {
2104
    Trace("qcf-check") << "Check quantified formula ";
2105
    debugPrintQuant("qcf-check", q);
2106
    Trace("qcf-check") << " : " << q << "..." << std::endl;
2107
  }
2108
2109
120602
  Trace("qcf-check-debug") << "Reset round..." << std::endl;
2110
120602
  if (!qi->reset_round(this))
2111
  {
2112
    // it is typically the case that another conflict (e.g. in the term
2113
    // database) was discovered if we fail here.
2114
    return;
2115
  }
2116
  // try to make a matches making the body false or propagating
2117
120602
  Trace("qcf-check-debug") << "Get next match..." << std::endl;
2118
120602
  Instantiate* qinst = d_qim.getInstantiate();
2119
596296
  while (qi->getNextMatch(this))
2120
  {
2121
238858
    if (d_qstate.isInConflict())
2122
    {
2123
9
      Trace("qcf-check") << "   ... Quantifiers engine discovered conflict, ";
2124
18
      Trace("qcf-check") << "probably related to disequal congruent terms in "
2125
9
                            "master equality engine"
2126
9
                         << std::endl;
2127
1020
      return;
2128
    }
2129
238849
    if (Trace.isOn("qcf-inst"))
2130
    {
2131
      Trace("qcf-inst") << "*** Produced match at effort " << d_effort << " : "
2132
                        << std::endl;
2133
      qi->debugPrintMatch("qcf-inst");
2134
      Trace("qcf-inst") << std::endl;
2135
    }
2136
    // check whether internal match constraints are satisfied
2137
289754
    if (qi->isMatchSpurious(this))
2138
    {
2139
101810
      Trace("qcf-inst") << "   ... Spurious (match is inconsistent)"
2140
50905
                        << std::endl;
2141
101940
      continue;
2142
    }
2143
    // check whether match can be completed
2144
374756
    std::vector<int> assigned;
2145
188074
    if (!qi->completeMatch(this, assigned))
2146
    {
2147
260
      Trace("qcf-inst") << "   ... Spurious (cannot assign unassigned vars)"
2148
130
                        << std::endl;
2149
130
      continue;
2150
    }
2151
    // check whether the match is spurious according to (T-)entailment checks
2152
374626
    std::vector<Node> terms;
2153
187814
    qi->getMatch(terms);
2154
187814
    bool tcs = qi->isTConstraintSpurious(this, terms);
2155
187814
    if (tcs)
2156
    {
2157
370722
      Trace("qcf-inst") << "   ... Spurious (match is T-inconsistent)"
2158
185361
                        << std::endl;
2159
    }
2160
    else
2161
    {
2162
      // otherwise, we have a conflict/propagating instance
2163
      // for debugging
2164
2453
      if (Debug.isOn("qcf-check-inst"))
2165
      {
2166
        Node inst = qinst->getInstantiation(q, terms);
2167
        Debug("qcf-check-inst")
2168
            << "Check instantiation " << inst << "..." << std::endl;
2169
        Assert(!getTermDatabase()->isEntailed(inst, true));
2170
        Assert(getTermDatabase()->isEntailed(inst, false)
2171
               || d_effort > EFFORT_CONFLICT);
2172
      }
2173
      // Process the lemma: either add an instantiation or specific lemmas
2174
      // constructed during the isTConstraintSpurious call, or both.
2175
4906
      InferenceId id = (d_effort == EFFORT_CONFLICT
2176
2453
                            ? InferenceId::QUANTIFIERS_INST_CBQI_CONFLICT
2177
                            : InferenceId::QUANTIFIERS_INST_CBQI_PROP);
2178
2453
      if (!qinst->addInstantiation(q, terms, id))
2179
      {
2180
174
        Trace("qcf-inst") << "   ... Failed to add instantiation" << std::endl;
2181
        // This should only happen if the algorithm generates the same
2182
        // propagating instance twice this round. In this case, return
2183
        // to avoid exponential behavior.
2184
174
        return;
2185
      }
2186
2279
      Trace("qcf-check") << "   ... Added instantiation" << std::endl;
2187
2279
      if (Trace.isOn("qcf-inst"))
2188
      {
2189
        Trace("qcf-inst") << "*** Was from effort " << d_effort << " : "
2190
                          << std::endl;
2191
        qi->debugPrintMatch("qcf-inst");
2192
        Trace("qcf-inst") << std::endl;
2193
      }
2194
2279
      ++addedLemmas;
2195
2279
      if (d_effort == EFFORT_CONFLICT)
2196
      {
2197
        // mark relevant: this ensures that quantified formula q is
2198
        // checked first on the next round. This is an optimization to
2199
        // ensure that quantified formulas that are more likely to have
2200
        // conflicting instances are checked earlier.
2201
828
        d_treg.getModel()->markRelevant(q);
2202
828
        if (options::qcfAllConflict())
2203
        {
2204
          isConflict = true;
2205
        }
2206
        else
2207
        {
2208
828
          d_conflict.set(true);
2209
        }
2210
828
        return;
2211
      }
2212
1451
      else if (d_effort == EFFORT_PROP_EQ)
2213
      {
2214
1451
        d_treg.getModel()->markRelevant(q);
2215
      }
2216
    }
2217
    // clean up assigned
2218
186812
    qi->revertMatch(this, assigned);
2219
186812
    d_tempCache.clear();
2220
  }
2221
119591
  Trace("qcf-check") << "Done, conflict = " << d_conflict << std::endl;
2222
}
2223
2224
//-------------------------------------------------- debugging
2225
2226
void QuantConflictFind::debugPrint( const char * c ) {
2227
  //print the equivalance classes
2228
  Trace(c) << "----------EQ classes" << std::endl;
2229
  eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( getEqualityEngine() );
2230
  while( !eqcs_i.isFinished() ){
2231
    Node n = (*eqcs_i);
2232
    //if( !n.getType().isInteger() ){
2233
    Trace(c) << "  - " << n << " : {";
2234
    eq::EqClassIterator eqc_i = eq::EqClassIterator( n, getEqualityEngine() );
2235
    bool pr = false;
2236
    while( !eqc_i.isFinished() ){
2237
      Node nn = (*eqc_i);
2238
      if( nn.getKind()!=EQUAL && nn!=n ){
2239
        Trace(c) << (pr ? "," : "" ) << " " << nn;
2240
        pr = true;
2241
      }
2242
      ++eqc_i;
2243
    }
2244
    Trace(c) << (pr ? " " : "" ) << "}" << std::endl;
2245
    ++eqcs_i;
2246
  }
2247
}
2248
2249
void QuantConflictFind::debugPrintQuant( const char * c, Node q ) {
2250
  Trace(c) << "Q" << d_quant_id[q];
2251
}
2252
2253
void QuantConflictFind::debugPrintQuantBody( const char * c, Node q, Node n, bool doVarNum ) {
2254
  if( n.getNumChildren()==0 ){
2255
    Trace(c) << n;
2256
  }else if( doVarNum && d_qinfo[q].d_var_num.find( n )!=d_qinfo[q].d_var_num.end() ){
2257
    Trace(c) << "?x" << d_qinfo[q].d_var_num[n];
2258
  }else{
2259
    Trace(c) << "(";
2260
    if( n.getKind()==APPLY_UF ){
2261
      Trace(c) << n.getOperator();
2262
    }else{
2263
      Trace(c) << n.getKind();
2264
    }
2265
    for( unsigned i=0; i<n.getNumChildren(); i++ ){
2266
      Trace(c) << " ";
2267
      debugPrintQuantBody( c, q, n[i] );
2268
    }
2269
    Trace(c) << ")";
2270
  }
2271
}
2272
2273
4928
QuantConflictFind::Statistics::Statistics()
2274
    : d_inst_rounds(
2275
9856
        smtStatisticsRegistry().registerInt("QuantConflictFind::Inst_Rounds")),
2276
4928
      d_entailment_checks(smtStatisticsRegistry().registerInt(
2277
9856
          "QuantConflictFind::Entailment_Checks"))
2278
{
2279
4928
}
2280
2281
8
TNode QuantConflictFind::getZero( Kind k ) {
2282
8
  std::map< Kind, Node >::iterator it = d_zero.find( k );
2283
8
  if( it==d_zero.end() ){
2284
16
    Node nn;
2285
8
    if( k==PLUS ){
2286
4
      nn = NodeManager::currentNM()->mkConst( Rational(0) );
2287
    }
2288
8
    d_zero[k] = nn;
2289
8
    return nn;
2290
  }else{
2291
    return it->second;
2292
  }
2293
}
2294
2295
std::ostream& operator<<(std::ostream& os, const QuantConflictFind::Effort& e) {
2296
  switch (e) {
2297
    case QuantConflictFind::EFFORT_INVALID:
2298
      os << "Invalid";
2299
      break;
2300
    case QuantConflictFind::EFFORT_CONFLICT:
2301
      os << "Conflict";
2302
      break;
2303
    case QuantConflictFind::EFFORT_PROP_EQ:
2304
      os << "PropEq";
2305
      break;
2306
  }
2307
  return os;
2308
}
2309
2310
1615
bool QuantConflictFind::isPropagatingInstance(Node n) const
2311
{
2312
3230
  std::unordered_set<TNode> visited;
2313
3230
  std::vector<TNode> visit;
2314
3230
  TNode cur;
2315
1615
  visit.push_back(n);
2316
3284
  do
2317
  {
2318
4899
    cur = visit.back();
2319
4899
    visit.pop_back();
2320
4899
    if (visited.find(cur) == visited.end())
2321
    {
2322
4849
      visited.insert(cur);
2323
4849
      Kind ck = cur.getKind();
2324
4849
      if (ck == FORALL)
2325
      {
2326
        // do nothing
2327
      }
2328
4747
      else if (TermUtil::isBoolConnective(ck))
2329
      {
2330
4993
        for (TNode cc : cur)
2331
        {
2332
3284
          visit.push_back(cc);
2333
        }
2334
      }
2335
3038
      else if (!getEqualityEngine()->hasTerm(cur))
2336
      {
2337
        Trace("qcf-instance-check-debug")
2338
            << "...not propagating instance because of " << cur << " " << ck
2339
            << std::endl;
2340
        return false;
2341
      }
2342
    }
2343
4899
  } while (!visit.empty());
2344
1615
  return true;
2345
}
2346
2347
}  // namespace quantifiers
2348
}  // namespace theory
2349
29340
}  // namespace cvc5