GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/quant_conflict_find.cpp Lines: 1159 1397 83.0 %
Date: 2021-09-29 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
#include "util/rational.h"
32
33
using namespace cvc5::kind;
34
using namespace std;
35
36
namespace cvc5 {
37
namespace theory {
38
namespace quantifiers {
39
40
8633
QuantInfo::QuantInfo()
41
8633
    : d_unassigned_nvar(0), d_una_index(0), d_parent(nullptr), d_mg(nullptr)
42
{
43
8633
}
44
45
17266
QuantInfo::~QuantInfo() {
46
8633
  delete d_mg;
47
40026
  for(std::map< int, MatchGen * >::iterator i = d_var_mg.begin(),
48
8633
          iend=d_var_mg.end(); i != iend; ++i) {
49
31393
    MatchGen* currentMatchGenerator = (*i).second;
50
31393
    delete currentMatchGenerator;
51
  }
52
8633
  d_var_mg.clear();
53
8633
}
54
55
31408
QuantifiersInferenceManager& QuantInfo::getInferenceManager()
56
{
57
31408
  Assert(d_parent != nullptr);
58
31408
  return d_parent->getInferenceManager();
59
}
60
61
8633
void QuantInfo::initialize( QuantConflictFind * p, Node q, Node qn ) {
62
8633
  d_parent = p;
63
8633
  d_q = q;
64
8633
  d_extra_var.clear();
65
28405
  for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
66
19772
    d_match.push_back( TNode::null() );
67
19772
    d_match_term.push_back( TNode::null() );
68
  }
69
70
  //register the variables
71
28405
  for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
72
19772
    d_var_num[q[0][i]] = i;
73
19772
    d_vars.push_back( q[0][i] );
74
19772
    d_var_types.push_back( q[0][i].getType() );
75
  }
76
77
8633
  registerNode( qn, true, true );
78
79
80
8633
  Trace("qcf-qregister") << "- Make match gen structure..." << std::endl;
81
8633
  d_mg = new MatchGen( this, qn );
82
83
8633
  if( d_mg->isValid() ){
84
    /*
85
    for( unsigned j=0; j<q[0].getNumChildren(); j++ ){
86
      if( d_inMatchConstraint.find( q[0][j] )==d_inMatchConstraint.end() ){
87
        Trace("qcf-invalid") << "QCF invalid : variable " << q[0][j] << " does not exist in a matching constraint." << std::endl;
88
        d_mg->setInvalid();
89
        break;
90
      }
91
    }
92
    */
93
40435
    for( unsigned j=q[0].getNumChildren(); j<d_vars.size(); j++ ){
94
33834
      if( d_vars[j].getKind()!=BOUND_VARIABLE ){
95
31393
        d_var_mg[j] = NULL;
96
31393
        bool is_tsym = false;
97
31393
        if( !MatchGen::isHandledUfTerm( d_vars[j] ) && d_vars[j].getKind()!=ITE ){
98
291
          is_tsym = true;
99
291
          d_tsym_vars.push_back( j );
100
        }
101
31393
        if( !is_tsym || options::qcfTConstraint() ){
102
31226
          d_var_mg[j] = new MatchGen( this, d_vars[j], true );
103
        }
104
31393
        if( !d_var_mg[j] || !d_var_mg[j]->isValid() ){
105
726
          Trace("qcf-invalid") << "QCF invalid : cannot match for " << d_vars[j] << std::endl;
106
726
          d_mg->setInvalid();
107
726
          break;
108
        }else{
109
61334
          std::vector< int > bvars;
110
30667
          d_var_mg[j]->determineVariableOrder( this, bvars );
111
        }
112
      }
113
    }
114
7327
    if( d_mg->isValid() ){
115
13202
      std::vector< int > bvars;
116
6601
      d_mg->determineVariableOrder( this, bvars );
117
    }
118
  }else{
119
1306
    Trace("qcf-invalid") << "QCF invalid : body of formula cannot be processed." << std::endl;
120
  }
121
8633
  Trace("qcf-qregister-summary") << "QCF register : " << ( d_mg->isValid() ? "VALID " : "INVALID" ) << " : " << q << std::endl;
122
123
8633
  if( d_mg->isValid() && options::qcfEagerCheckRd() ){
124
    //optimization : record variable argument positions for terms that must be matched
125
13202
    std::vector< TNode > vars;
126
    //TODO: revisit this, makes QCF faster, but misses conflicts due to caring about paths that may not be relevant (starExec jobs 14136/14137)
127
6601
    if( options::qcfSkipRd() ){
128
      for( unsigned j=q[0].getNumChildren(); j<d_vars.size(); j++ ){
129
        vars.push_back( d_vars[j] );
130
      }
131
    }else{
132
      //get all variables that are always relevant
133
13202
      std::map< TNode, bool > visited;
134
6601
      getPropagateVars( p, vars, q[1], false, visited );
135
    }
136
37164
    for( unsigned j=0; j<vars.size(); j++ ){
137
61126
      Node v = vars[j];
138
61126
      TNode f = p->getTermDatabase()->getMatchOperator( v );
139
30563
      if( !f.isNull() ){
140
18610
        Trace("qcf-opt") << "Record variable argument positions in " << v << ", op=" << f << "..." << std::endl;
141
58936
        for( unsigned k=0; k<v.getNumChildren(); k++ ){
142
80652
          Node n = v[k];
143
40326
          std::map< TNode, int >::iterator itv = d_var_num.find( n );
144
40326
          if( itv!=d_var_num.end() ){
145
34735
            Trace("qcf-opt") << "  arg " << k << " is var #" << itv->second << std::endl;
146
34735
            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() ){
147
32723
              d_var_rel_dom[itv->second][f].push_back( k );
148
            }
149
          }
150
        }
151
      }
152
    }
153
  }
154
8633
}
155
156
76789
void QuantInfo::getPropagateVars( QuantConflictFind * p, std::vector< TNode >& vars, TNode n, bool pol, std::map< TNode, bool >& visited ){
157
76789
  std::map< TNode, bool >::iterator itv = visited.find( n );
158
76789
  if( itv==visited.end() ){
159
57809
    visited[n] = true;
160
57809
    bool rec = true;
161
57809
    bool newPol = pol;
162
57809
    if( d_var_num.find( n )!=d_var_num.end() ){
163
30563
      Assert(std::find(vars.begin(), vars.end(), n) == vars.end());
164
30563
      vars.push_back( n );
165
61126
      TNode f = p->getTermDatabase()->getMatchOperator( n );
166
30563
      if( !f.isNull() ){
167
18610
        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() ){
168
14388
          p->d_func_rel_dom[f].push_back( d_q );
169
        }
170
      }
171
27246
    }else if( MatchGen::isHandledBoolConnective( n ) ){
172
10929
      Assert(n.getKind() != IMPLIES);
173
10929
      QuantPhaseReq::getEntailPolarity( n, 0, true, pol, rec, newPol );
174
    }
175
57809
    Trace("qcf-opt-debug") << "getPropagateVars " << n << ", pol = " << pol << ", rec = " << rec << std::endl;
176
57809
    if( rec ){
177
125503
      for( unsigned i=0; i<n.getNumChildren(); i++ ){
178
70188
        getPropagateVars( p, vars, n[i], pol, visited );
179
      }
180
    }
181
  }
182
76789
}
183
184
646101
bool QuantInfo::isBaseMatchComplete() {
185
646101
  return d_vars_set.size()==(d_q[0].getNumChildren()+d_extra_var.size());
186
}
187
188
46014
void QuantInfo::registerNode( Node n, bool hasPol, bool pol, bool beneathQuant ) {
189
46014
  Trace("qcf-qregister-debug2") << "Register : " << n << std::endl;
190
46014
  if( n.getKind()==FORALL ){
191
2064
    registerNode( n[1], hasPol, pol, true );
192
  }else{
193
43950
    if( !MatchGen::isHandledBoolConnective( n ) ){
194
24104
      if (expr::hasBoundVar(n))
195
      {
196
        // literals
197
24047
        if (n.getKind() == EQUAL)
198
        {
199
36966
          for (unsigned i = 0; i < n.getNumChildren(); i++)
200
          {
201
24644
            flatten(n[i], beneathQuant);
202
          }
203
        }
204
11725
        else if (MatchGen::isHandledUfTerm(n))
205
        {
206
7695
          flatten(n, beneathQuant);
207
        }
208
4030
        else if (n.getKind() == ITE)
209
        {
210
2073
          for (unsigned i = 1; i <= 2; i++)
211
          {
212
1382
            flatten(n[i], beneathQuant);
213
          }
214
691
          registerNode(n[0], false, pol, beneathQuant);
215
        }
216
3339
        else if (options::qcfTConstraint())
217
        {
218
          // a theory-specific predicate
219
330
          for (unsigned i = 0; i < n.getNumChildren(); i++)
220
          {
221
220
            flatten(n[i], beneathQuant);
222
          }
223
        }
224
      }
225
    }else{
226
53781
      for( unsigned i=0; i<n.getNumChildren(); i++ ){
227
        bool newHasPol;
228
        bool newPol;
229
33935
        QuantPhaseReq::getPolarity( n, i, hasPol, pol, newHasPol, newPol );
230
        //QcfNode * qcfc = new QcfNode( d_c );
231
        //qcfc->d_parent = qcf;
232
        //qcf->d_child[i] = qcfc;
233
33935
        registerNode( n[i], newHasPol, newPol, beneathQuant );
234
      }
235
    }
236
  }
237
46014
}
238
239
110397
void QuantInfo::flatten( Node n, bool beneathQuant ) {
240
110397
  Trace("qcf-qregister-debug2") << "Flatten : " << n << std::endl;
241
110397
  if (expr::hasBoundVar(n))
242
  {
243
92040
    if( n.getKind()==BOUND_VARIABLE ){
244
47218
      d_inMatchConstraint[n] = true;
245
    }
246
92040
    if( d_var_num.find( n )==d_var_num.end() ){
247
41047
      Trace("qcf-qregister-debug2") << "Add FLATTEN VAR : " << n << std::endl;
248
41047
      d_var_num[n] = d_vars.size();
249
41047
      d_vars.push_back( n );
250
41047
      d_var_types.push_back( n.getType() );
251
41047
      d_match.push_back( TNode::null() );
252
41047
      d_match_term.push_back( TNode::null() );
253
41047
      if( n.getKind()==ITE ){
254
691
        registerNode( n, false, false );
255
40356
      }else if( n.getKind()==BOUND_VARIABLE ){
256
2768
        d_extra_var.push_back( n );
257
      }else{
258
114044
        for( unsigned i=0; i<n.getNumChildren(); i++ ){
259
76456
          flatten( n[i], beneathQuant );
260
        }
261
      }
262
    }else{
263
50993
      Trace("qcf-qregister-debug2") << "...already processed" << std::endl;
264
    }
265
  }else{
266
18357
    Trace("qcf-qregister-debug2") << "...is ground." << std::endl;
267
  }
268
110397
}
269
270
271
50507
bool QuantInfo::reset_round( QuantConflictFind * p ) {
272
375893
  for( unsigned i=0; i<d_match.size(); i++ ){
273
325386
    d_match[i] = TNode::null();
274
325386
    d_match_term[i] = TNode::null();
275
  }
276
50507
  d_vars_set.clear();
277
50507
  d_curr_var_deq.clear();
278
50507
  d_tconstraints.clear();
279
280
50507
  d_mg->reset_round( p );
281
245173
  for( std::map< int, MatchGen * >::iterator it = d_var_mg.begin(); it != d_var_mg.end(); ++it ){
282
194666
    if (!it->second->reset_round(p))
283
    {
284
      return false;
285
    }
286
  }
287
  //now, reset for matching
288
50507
  d_mg->reset( p, false, this );
289
50507
  return true;
290
}
291
292
2052360
int QuantInfo::getCurrentRepVar( int v ) {
293
2052360
  if( v!=-1 && !d_match[v].isNull() ){
294
1060059
    int vn = getVarNum( d_match[v] );
295
1060059
    if( vn!=-1 ){
296
      //int vr = getCurrentRepVar( vn );
297
      //d_match[v] = d_vars[vr];
298
      //return vr;
299
9833
      return getCurrentRepVar( vn );
300
    }
301
  }
302
2042527
  return v;
303
}
304
305
1098328
TNode QuantInfo::getCurrentValue( TNode n ) {
306
1098328
  int v = getVarNum( n );
307
1098328
  if( v==-1 ){
308
608368
    return n;
309
  }else{
310
489960
    if( d_match[v].isNull() ){
311
456935
      return n;
312
    }else{
313
33025
      Assert(getVarNum(d_match[v]) != v);
314
33025
      return getCurrentValue( d_match[v] );
315
    }
316
  }
317
}
318
319
1
TNode QuantInfo::getCurrentExpValue( TNode n ) {
320
1
  int v = getVarNum( n );
321
1
  if( v==-1 ){
322
    return n;
323
  }else{
324
1
    if( d_match[v].isNull() ){
325
      return n;
326
    }else{
327
1
      Assert(getVarNum(d_match[v]) != v);
328
1
      if( d_match_term[v].isNull() ){
329
1
        return getCurrentValue( d_match[v] );
330
      }else{
331
        return d_match_term[v];
332
      }
333
    }
334
  }
335
}
336
337
1640181
bool QuantInfo::getCurrentCanBeEqual( QuantConflictFind * p, int v, TNode n, bool chDiseq ) {
338
  //check disequalities
339
1640181
  std::map< int, std::map< TNode, int > >::iterator itd = d_curr_var_deq.find( v );
340
1640181
  if( itd!=d_curr_var_deq.end() ){
341
1931991
    for( std::map< TNode, int >::iterator it = itd->second.begin(); it != itd->second.end(); ++it ){
342
867301
      Node cv = getCurrentValue( it->first );
343
451208
      Debug("qcf-ccbe") << "compare " << cv << " " << n << std::endl;
344
451208
      if( cv==n ){
345
24916
        return false;
346
426292
      }else if( chDiseq && !isVar( n ) && !isVar( cv ) ){
347
        //they must actually be disequal if we are looking for conflicts
348
17800
        if( !p->areDisequal( n, cv ) ){
349
          //TODO : check for entailed disequal
350
351
10199
          return false;
352
        }
353
      }
354
    }
355
  }
356
1605066
  return true;
357
}
358
359
int QuantInfo::addConstraint( QuantConflictFind * p, int v, TNode n, bool polarity ) {
360
  v = getCurrentRepVar( v );
361
  int vn = getVarNum( n );
362
  vn = vn==-1 ? -1 : getCurrentRepVar( vn );
363
  n = getCurrentValue( n );
364
  return addConstraint( p, v, n, vn, polarity, false );
365
}
366
367
267791
int QuantInfo::addConstraint( QuantConflictFind * p, int v, TNode n, int vn, bool polarity, bool doRemove ) {
368
  //for handling equalities between variables, and disequalities involving variables
369
267791
  Debug("qcf-match-debug") << "- " << (doRemove ? "un" : "" ) << "constrain : " << v << " -> " << n << " (cv=" << getCurrentValue( n ) << ")";
370
267791
  Debug("qcf-match-debug") << ", (vn=" << vn << "), polarity = " << polarity << std::endl;
371
267791
  Assert(doRemove || n == getCurrentValue(n));
372
267791
  Assert(doRemove || v == getCurrentRepVar(v));
373
267791
  Assert(doRemove || vn == getCurrentRepVar(getVarNum(n)));
374
267791
  if( polarity ){
375
185889
    if( vn!=v ){
376
185889
      if( doRemove ){
377
92611
        if( vn!=-1 ){
378
          //if set to this in the opposite direction, clean up opposite instead
379
          //          std::map< int, TNode >::iterator itmn = d_match.find( vn );
380
8394
          if( d_match[vn]==d_vars[v] ){
381
            return addConstraint( p, vn, d_vars[v], v, true, true );
382
          }else{
383
            //unsetting variables equal
384
8394
            std::map< int, std::map< TNode, int > >::iterator itd = d_curr_var_deq.find( vn );
385
8394
            if( itd!=d_curr_var_deq.end() ){
386
              //remove disequalities owned by this
387
11262
              std::vector< TNode > remDeq;
388
5668
              for( std::map< TNode, int >::iterator it = itd->second.begin(); it != itd->second.end(); ++it ){
389
37
                if( it->second==v ){
390
37
                  remDeq.push_back( it->first );
391
                }
392
              }
393
5668
              for( unsigned i=0; i<remDeq.size(); i++ ){
394
37
                d_curr_var_deq[vn].erase( remDeq[i] );
395
              }
396
            }
397
          }
398
        }
399
92611
        unsetMatch( p, v );
400
92611
        return 1;
401
      }else{
402
        //std::map< int, TNode >::iterator itm = d_match.find( v );
403
93278
        bool isGroundRep = false;
404
93278
        bool isGround = false;
405
93278
        if( vn!=-1 ){
406
8534
          Debug("qcf-match-debug") << "  ...Variable bound to variable" << std::endl;
407
          //std::map< int, TNode >::iterator itmn = d_match.find( vn );
408
8534
          if( d_match[v].isNull() ){
409
            //setting variables equal
410
8534
            bool alreadySet = false;
411
8534
            if( !d_match[vn].isNull() ){
412
              alreadySet = true;
413
              Assert(!isVar(d_match[vn]));
414
            }
415
416
            //copy or check disequalities
417
8534
            std::map< int, std::map< TNode, int > >::iterator itd = d_curr_var_deq.find( v );
418
8534
            if( itd!=d_curr_var_deq.end() ){
419
5998
              for( std::map< TNode, int >::iterator it = itd->second.begin(); it != itd->second.end(); ++it ){
420
74
                Node dv = getCurrentValue( it->first );
421
37
                if( !alreadySet ){
422
37
                  if( d_curr_var_deq[vn].find( dv )==d_curr_var_deq[vn].end() ){
423
37
                    d_curr_var_deq[vn][dv] = v;
424
                  }
425
                }else{
426
                  if( !p->areMatchDisequal( d_match[vn], dv ) ){
427
                    Debug("qcf-match-debug") << "  -> fail, conflicting disequality" << std::endl;
428
                    return -1;
429
                  }
430
                }
431
              }
432
            }
433
8534
            if( alreadySet ){
434
              n = getCurrentValue( n );
435
            }
436
          }else{
437
            if( d_match[vn].isNull() ){
438
              Debug("qcf-match-debug") << " ...Reverse direction" << std::endl;
439
              //set the opposite direction
440
              return addConstraint( p, vn, d_vars[v], v, true, false );
441
            }else{
442
              Debug("qcf-match-debug") << "  -> Both variables bound, compare" << std::endl;
443
              //are they currently equal
444
              return p->areMatchEqual( d_match[v], d_match[vn] ) ? 0 : -1;
445
            }
446
          }
447
        }else{
448
84744
          Debug("qcf-match-debug") << "  ...Variable bound to ground" << std::endl;
449
84744
          if( d_match[v].isNull() ){
450
            //isGroundRep = true;   ??
451
84744
            isGround = true;
452
          }else{
453
            //compare ground values
454
            Debug("qcf-match-debug") << "  -> Ground value, compare " << d_match[v] << " "<< n << std::endl;
455
            return p->areMatchEqual( d_match[v], n ) ? 0 : -1;
456
          }
457
        }
458
93278
        if( setMatch( p, v, n, isGroundRep, isGround ) ){
459
93271
          Debug("qcf-match-debug") << "  -> success" << std::endl;
460
93271
          return 1;
461
        }else{
462
7
          Debug("qcf-match-debug") << "  -> fail, conflicting disequality" << std::endl;
463
7
          return -1;
464
        }
465
      }
466
    }else{
467
      Debug("qcf-match-debug") << "  -> redundant, variable identity" << std::endl;
468
      return 0;
469
    }
470
  }else{
471
81902
    if( vn==v ){
472
      Debug("qcf-match-debug") << "  -> fail, variable identity" << std::endl;
473
      return -1;
474
    }else{
475
81902
      if( doRemove ){
476
40816
        Assert(d_curr_var_deq[v].find(n) != d_curr_var_deq[v].end());
477
40816
        d_curr_var_deq[v].erase( n );
478
40816
        return 1;
479
      }else{
480
41086
        if( d_curr_var_deq[v].find( n )==d_curr_var_deq[v].end() ){
481
          //check if it respects equality
482
          //std::map< int, TNode >::iterator itm = d_match.find( v );
483
41034
          if( !d_match[v].isNull() ){
484
            TNode nv = getCurrentValue( n );
485
            if( !p->areMatchDisequal( nv, d_match[v] ) ){
486
              Debug("qcf-match-debug") << "  -> fail, conflicting disequality" << std::endl;
487
              return -1;
488
            }
489
          }
490
41034
          d_curr_var_deq[v][n] = v;
491
41034
          Debug("qcf-match-debug") << "  -> success" << std::endl;
492
41034
          return 1;
493
        }else{
494
52
          Debug("qcf-match-debug") << "  -> redundant disequality" << std::endl;
495
52
          return 0;
496
        }
497
      }
498
    }
499
  }
500
}
501
502
70
bool QuantInfo::isConstrainedVar( int v ) {
503
70
  if( d_curr_var_deq.find( v )!=d_curr_var_deq.end() && !d_curr_var_deq[v].empty() ){
504
    return true;
505
  }else{
506
140
    Node vv = getVar( v );
507
    //for( std::map< int, TNode >::iterator it = d_match.begin(); it != d_match.end(); ++it ){
508
1020
    for( unsigned i=0; i<d_match.size(); i++ ){
509
950
      if( d_match[i]==vv ){
510
        return true;
511
      }
512
    }
513
490
    for( std::map< int, std::map< TNode, int > >::iterator it = d_curr_var_deq.begin(); it != d_curr_var_deq.end(); ++it ){
514
484
      for( std::map< TNode, int >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
515
64
        if( it2->first==vv ){
516
          return true;
517
        }
518
      }
519
    }
520
70
    return false;
521
  }
522
}
523
524
1260198
bool QuantInfo::setMatch( QuantConflictFind * p, int v, TNode n, bool isGroundRep, bool isGround ) {
525
1260198
  if( getCurrentCanBeEqual( p, v, n ) ){
526
1243326
    if( isGroundRep ){
527
      //fail if n does not exist in the relevant domain of each of the argument positions
528
1149448
      std::map< int, std::map< TNode, std::vector< unsigned > > >::iterator it = d_var_rel_dom.find( v );
529
1149448
      if( it!=d_var_rel_dom.end() ){
530
1052023
        for( std::map< TNode, std::vector< unsigned > >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
531
1286789
          for( unsigned j=0; j<it2->second.size(); j++ ){
532
680907
            Debug("qcf-match-debug2") << n << " in relevant domain " <<  it2->first << "." << it2->second[j] << "?" << std::endl;
533
680907
            if( !p->getTermDatabase()->inRelevantDomain( it2->first, it2->second[j], n ) ){
534
50334
              Debug("qcf-match-debug") << "  -> fail, since " << n << " is not in relevant domain of " << it2->first << "." << it2->second[j] << std::endl;
535
50334
              return false;
536
            }
537
          }
538
        }
539
      }
540
    }
541
1192992
    Debug("qcf-match-debug") << "-- bind : " << v << " -> " << n << ", checked " <<  d_curr_var_deq[v].size() << " disequalities" << std::endl;
542
1192992
    if( isGround ){
543
1184458
      if( d_vars[v].getKind()==BOUND_VARIABLE ){
544
495958
        d_vars_set[v] = true;
545
495958
        Debug("qcf-match-debug") << "---- now bound " << d_vars_set.size() << " / " << d_q[0].getNumChildren() << " base variables." << std::endl;
546
      }
547
    }
548
1192992
    d_match[v] = n;
549
1192992
    return true;
550
  }else{
551
16872
    return false;
552
  }
553
}
554
555
827885
void QuantInfo::unsetMatch( QuantConflictFind * p, int v ) {
556
827885
  Debug("qcf-match-debug") << "-- unbind : " << v << std::endl;
557
827885
  if( d_vars[v].getKind()==BOUND_VARIABLE && d_vars_set.find( v )!=d_vars_set.end() ){
558
293363
    d_vars_set.erase( v );
559
  }
560
827885
  d_match[ v ] = TNode::null();
561
827885
}
562
563
84150
bool QuantInfo::isMatchSpurious( QuantConflictFind * p ) {
564
568278
  for( int i=0; i<getNumVars(); i++ ){
565
    //std::map< int, TNode >::iterator it = d_match.find( i );
566
502371
    if( !d_match[i].isNull() ){
567
379983
      if (!getCurrentCanBeEqual(p, i, d_match[i], p->atConflictEffort())) {
568
18243
        return true;
569
      }
570
    }
571
  }
572
65907
  return false;
573
}
574
575
65811
bool QuantInfo::isTConstraintSpurious(QuantConflictFind* p,
576
                                      std::vector<Node>& terms)
577
{
578
65811
  if( options::qcfEagerTest() ){
579
    //check whether the instantiation evaluates as expected
580
65811
    if (p->atConflictEffort()) {
581
34403
      Trace("qcf-instance-check") << "Possible conflict instance for " << d_q << " : " << std::endl;
582
34799
      std::map< TNode, TNode > subs;
583
134041
      for( unsigned i=0; i<terms.size(); i++ ){
584
99638
        Trace("qcf-instance-check") << "  " << terms[i] << std::endl;
585
99638
        subs[d_q[0][i]] = terms[i];
586
      }
587
34403
      TermDb* tdb = p->getTermDatabase();
588
34404
      for( unsigned i=0; i<d_extra_var.size(); i++ ){
589
2
        Node n = getCurrentExpValue( d_extra_var[i] );
590
1
        Trace("qcf-instance-check") << "  " << d_extra_var[i] << " -> " << n << std::endl;
591
1
        subs[d_extra_var[i]] = n;
592
      }
593
34403
      if (!tdb->isEntailed(d_q[1], subs, false, false))
594
      {
595
34007
        Trace("qcf-instance-check") << "...not entailed to be false." << std::endl;
596
34007
        return true;
597
      }
598
    }else{
599
      Node inst =
600
32031
          getInferenceManager().getInstantiate()->getInstantiation(d_q, terms);
601
31408
      inst = Rewriter::rewrite(inst);
602
      Node inst_eval = p->getTermDatabase()->evaluateTerm(
603
32031
          inst, options::qcfTConstraint(), true);
604
31408
      if( Trace.isOn("qcf-instance-check") ){
605
        Trace("qcf-instance-check") << "Possible propagating instance for " << d_q << " : " << std::endl;
606
        for( unsigned i=0; i<terms.size(); i++ ){
607
          Trace("qcf-instance-check") << "  " << terms[i] << std::endl;
608
        }
609
        Trace("qcf-instance-check") << "...evaluates to " << inst_eval << std::endl;
610
      }
611
62816
      if (inst_eval.isNull()
612
31408
          || (inst_eval.isConst() && inst_eval.getConst<bool>()))
613
      {
614
30785
        Trace("qcf-instance-check") << "...spurious." << std::endl;
615
30785
        return true;
616
      }else{
617
623
        if (Configuration::isDebugBuild())
618
        {
619
623
          if (!p->isPropagatingInstance(inst_eval))
620
          {
621
            // Notice that this can happen in cases where:
622
            // (1) x = -1*y is rewritten to y = -1*x, and
623
            // (2) -1*y is a term in the master equality engine but -1*x is not.
624
            // In other words, we determined that x = -1*y is a relevant
625
            // equality to propagate since it involves two known terms, but
626
            // after rewriting, the equality y = -1*x involves an unknown term
627
            // -1*x. In this case, the equality is still relevant to propagate,
628
            // despite the above function not being precise enough to realize
629
            // it. We output a warning in debug for this. See #2993.
630
            Trace("qcf-instance-check")
631
                << "WARNING: not propagating." << std::endl;
632
          }
633
        }
634
623
        Trace("qcf-instance-check") << "...not spurious." << std::endl;
635
      }
636
    }
637
  }
638
1019
  if( !d_tconstraints.empty() ){
639
    //check constraints
640
7
    for( std::map< Node, bool >::iterator it = d_tconstraints.begin(); it != d_tconstraints.end(); ++it ){
641
      //apply substitution to the tconstraint
642
4
      Node cons = p->getQuantifiersRegistry().substituteBoundVariables(
643
8
          it->first, d_q, terms);
644
4
      cons = it->second ? cons : cons.negate();
645
4
      if (!entailmentTest(p, cons, p->atConflictEffort())) {
646
        return true;
647
      }
648
    }
649
  }
650
  // spurious if quantifiers engine is in conflict
651
1019
  return p->d_qstate.isInConflict();
652
}
653
654
4
bool QuantInfo::entailmentTest( QuantConflictFind * p, Node lit, bool chEnt ) {
655
4
  Trace("qcf-tconstraint-debug") << "Check : " << lit << std::endl;
656
8
  Node rew = Rewriter::rewrite( lit );
657
4
  if (rew.isConst())
658
  {
659
2
    Trace("qcf-tconstraint-debug") << "...constraint " << lit << " rewrites to "
660
1
                                   << rew << "." << std::endl;
661
1
    return rew.getConst<bool>();
662
  }
663
  // if checking for conflicts, we must be sure that the (negation of)
664
  // constraint is (not) entailed
665
3
  if (!chEnt)
666
  {
667
3
    rew = Rewriter::rewrite(rew.negate());
668
  }
669
  // check if it is entailed
670
6
  Trace("qcf-tconstraint-debug")
671
3
      << "Check entailment of " << rew << "..." << std::endl;
672
3
  std::pair<bool, Node> et = p->getState().getValuation().entailmentCheck(
673
6
      options::TheoryOfMode::THEORY_OF_TYPE_BASED, rew);
674
3
  ++(p->d_statistics.d_entailment_checks);
675
6
  Trace("qcf-tconstraint-debug")
676
3
      << "ET result : " << et.first << " " << et.second << std::endl;
677
3
  if (!et.first)
678
  {
679
6
    Trace("qcf-tconstraint-debug")
680
3
        << "...cannot show entailment of " << rew << "." << std::endl;
681
3
    return !chEnt;
682
  }
683
  return chEnt;
684
}
685
686
65882
bool QuantInfo::completeMatch( QuantConflictFind * p, std::vector< int >& assigned, bool doContinue ) {
687
  //assign values for variables that were unassigned (usually not necessary, but handles corner cases)
688
65882
  bool doFail = false;
689
65882
  bool success = true;
690
65882
  if( doContinue ){
691
    doFail = true;
692
    success = false;
693
  }else{
694
65882
    if( isBaseMatchComplete() && options::qcfEagerTest() ){
695
65783
      return true;
696
    }
697
    //solve for interpreted symbol matches
698
    //   this breaks the invariant that all introduced constraints are over existing terms
699
101
    for( int i=(int)(d_tsym_vars.size()-1); i>=0; i-- ){
700
2
      int index = d_tsym_vars[i];
701
4
      TNode v = getCurrentValue( d_vars[index] );
702
2
      int slv_v = -1;
703
2
      if( v==d_vars[index] ){
704
2
        slv_v = index;
705
      }
706
2
      Trace("qcf-tconstraint-debug") << "Solve " << d_vars[index] << " = " << v << " " << d_vars[index].getKind() << std::endl;
707
2
      if( d_vars[index].getKind()==PLUS || d_vars[index].getKind()==MULT ){
708
2
        Kind k = d_vars[index].getKind();
709
4
        std::vector< TNode > children;
710
6
        for( unsigned j=0; j<d_vars[index].getNumChildren(); j++ ){
711
4
          int vn = getVarNum( d_vars[index][j] );
712
4
          if( vn!=-1 ){
713
6
            TNode vv = getCurrentValue( d_vars[index][j] );
714
3
            if( vv==d_vars[index][j] ){
715
              //we will assign this
716
2
              if( slv_v==-1 ){
717
                Trace("qcf-tconstraint-debug") << "...will solve for var #" << vn << std::endl;
718
                slv_v = vn;
719
                if (!p->atConflictEffort()) {
720
                  break;
721
                }
722
              }else{
723
4
                Node z = p->getZero( k );
724
2
                if( !z.isNull() ){
725
1
                  Trace("qcf-tconstraint-debug") << "...set " << d_vars[vn] << " = " << z << std::endl;
726
1
                  assigned.push_back( vn );
727
1
                  if( !setMatch( p, vn, z, false, true ) ){
728
                    success = false;
729
                    break;
730
                  }
731
                }
732
              }
733
            }else{
734
1
              Trace("qcf-tconstraint-debug") << "...sum value " << vv << std::endl;
735
1
              children.push_back( vv );
736
            }
737
          }else{
738
1
            Trace("qcf-tconstraint-debug") << "...sum " << d_vars[index][j] << std::endl;
739
1
            children.push_back( d_vars[index][j] );
740
          }
741
        }
742
2
        if( success ){
743
2
          if( slv_v!=-1 ){
744
4
            Node lhs;
745
2
            if( children.empty() ){
746
              lhs = p->getZero( k );
747
2
            }else if( children.size()==1 ){
748
2
              lhs = children[0];
749
            }else{
750
              lhs = NodeManager::currentNM()->mkNode( k, children );
751
            }
752
4
            Node sum;
753
2
            if( v==d_vars[index] ){
754
2
              sum = lhs;
755
            }else{
756
              if (p->atConflictEffort()) {
757
                Kind kn = k;
758
                if( d_vars[index].getKind()==PLUS ){
759
                  kn = MINUS;
760
                }
761
                if( kn!=k ){
762
                  sum = NodeManager::currentNM()->mkNode( kn, v, lhs );
763
                }
764
              }
765
            }
766
2
            if( !sum.isNull() ){
767
2
              assigned.push_back( slv_v );
768
2
              Trace("qcf-tconstraint-debug") << "...set " << d_vars[slv_v] << " = " << sum << std::endl;
769
2
              if( !setMatch( p, slv_v, sum, false, true ) ){
770
                success = false;
771
              }
772
2
              p->d_tempCache.push_back( sum );
773
            }
774
          }else{
775
            //must show that constraint is met
776
            Node sum = NodeManager::currentNM()->mkNode( k, children );
777
            Node eq = sum.eqNode( v );
778
            if( !entailmentTest( p, eq ) ){
779
              success = false;
780
            }
781
            p->d_tempCache.push_back( sum );
782
          }
783
        }
784
      }
785
786
2
      if( !success ){
787
        break;
788
      }
789
    }
790
99
    if( success ){
791
      //check what is left to assign
792
99
      d_unassigned.clear();
793
99
      d_unassigned_tn.clear();
794
198
      std::vector< int > unassigned[2];
795
198
      std::vector< TypeNode > unassigned_tn[2];
796
339
      for( int i=0; i<getNumVars(); i++ ){
797
240
        if( d_match[i].isNull() ){
798
196
          int rindex = d_var_mg.find( i )==d_var_mg.end() ? 1 : 0;
799
196
          unassigned[rindex].push_back( i );
800
196
          unassigned_tn[rindex].push_back( getVar( i ).getType() );
801
196
          assigned.push_back( i );
802
        }
803
      }
804
99
      d_unassigned_nvar = unassigned[0].size();
805
297
      for( unsigned i=0; i<2; i++ ){
806
198
        d_unassigned.insert( d_unassigned.end(), unassigned[i].begin(), unassigned[i].end() );
807
198
        d_unassigned_tn.insert( d_unassigned_tn.end(), unassigned_tn[i].begin(), unassigned_tn[i].end() );
808
      }
809
99
      d_una_eqc_count.clear();
810
99
      d_una_index = 0;
811
    }
812
  }
813
814
99
  if( !d_unassigned.empty() && ( success || doContinue ) ){
815
96
    Trace("qcf-check") << "Assign to unassigned (" << d_unassigned.size() << ")..." << std::endl;
816
81
    do {
817
177
      if( doFail ){
818
81
        Trace("qcf-check-unassign") << "Failure, try again..." << std::endl;
819
      }
820
177
      bool invalidMatch = false;
821
1501
      while( ( d_una_index>=0 && (int)d_una_index<(int)d_unassigned.size() ) || invalidMatch || doFail ){
822
662
        invalidMatch = false;
823
662
        if( !doFail && d_una_index==(int)d_una_eqc_count.size() ){
824
          //check if it has now been assigned
825
193
          if( d_una_index<d_unassigned_nvar ){
826
35
            if( !isConstrainedVar( d_unassigned[d_una_index] ) ){
827
35
              d_una_eqc_count.push_back( -1 );
828
            }else{
829
              d_var_mg[ d_unassigned[d_una_index] ]->reset( p, true, this );
830
              d_una_eqc_count.push_back( 0 );
831
            }
832
          }else{
833
158
            d_una_eqc_count.push_back( 0 );
834
          }
835
        }else{
836
469
          bool failed = false;
837
469
          if( !doFail ){
838
388
            if( d_una_index<d_unassigned_nvar ){
839
35
              if( !isConstrainedVar( d_unassigned[d_una_index] ) ){
840
35
                Trace("qcf-check-unassign") << "Succeeded, variable unconstrained at " << d_una_index << std::endl;
841
35
                d_una_index++;
842
              }else if( d_var_mg[d_unassigned[d_una_index]]->getNextMatch( p, this ) ){
843
                Trace("qcf-check-unassign") << "Succeeded match with mg at " << d_una_index << std::endl;
844
                d_una_index++;
845
              }else{
846
                failed = true;
847
                Trace("qcf-check-unassign") << "Failed match with mg at " << d_una_index << std::endl;
848
              }
849
            }else{
850
353
              Assert(doFail || d_una_index == (int)d_una_eqc_count.size() - 1);
851
353
              if( d_una_eqc_count[d_una_index]<(int)p->d_eqcs[d_unassigned_tn[d_una_index]].size() ){
852
233
                int currIndex = d_una_eqc_count[d_una_index];
853
233
                d_una_eqc_count[d_una_index]++;
854
233
                Trace("qcf-check-unassign") << d_unassigned[d_una_index] << "->" << p->d_eqcs[d_unassigned_tn[d_una_index]][currIndex] << std::endl;
855
233
                if( setMatch( p, d_unassigned[d_una_index], p->d_eqcs[d_unassigned_tn[d_una_index]][currIndex], true, true ) ){
856
168
                  d_match_term[d_unassigned[d_una_index]] = TNode::null();
857
168
                  Trace("qcf-check-unassign") << "Succeeded match " << d_una_index << std::endl;
858
168
                  d_una_index++;
859
                }else{
860
65
                  Trace("qcf-check-unassign") << "Failed match " << d_una_index << std::endl;
861
65
                  invalidMatch = true;
862
                }
863
              }else{
864
120
                failed = true;
865
120
                Trace("qcf-check-unassign") << "No more matches " << d_una_index << std::endl;
866
              }
867
            }
868
          }
869
469
          if( doFail || failed ){
870
            do{
871
201
              if( !doFail ){
872
120
                d_una_eqc_count.pop_back();
873
              }else{
874
81
                doFail = false;
875
              }
876
201
              d_una_index--;
877
201
            }while( d_una_index>=0 && d_una_eqc_count[d_una_index]==-1 );
878
          }
879
        }
880
      }
881
177
      success = d_una_index>=0;
882
177
      if( success ){
883
106
        doFail = true;
884
106
        Trace("qcf-check-unassign") << "  Try: " << std::endl;
885
328
        for( unsigned i=0; i<d_unassigned.size(); i++ ){
886
222
          int ui = d_unassigned[i];
887
222
          if( !d_match[ui].isNull() ){
888
187
            Trace("qcf-check-unassign") << "  Assigned #" << ui << " : " << d_vars[ui] << " -> " << d_match[ui] << std::endl;
889
          }
890
        }
891
      }
892
177
    }while( success && isMatchSpurious( p ) );
893
96
    Trace("qcf-check") << "done assigning." << std::endl;
894
  }
895
99
  if( success ){
896
101
    for( unsigned i=0; i<d_unassigned.size(); i++ ){
897
73
      int ui = d_unassigned[i];
898
73
      if( !d_match[ui].isNull() ){
899
38
        Trace("qcf-check") << "  Assigned #" << ui << " : " << d_vars[ui] << " -> " << d_match[ui] << std::endl;
900
      }
901
    }
902
28
    return true;
903
  }else{
904
71
    revertMatch( p, assigned );
905
71
    assigned.clear();
906
71
    return false;
907
  }
908
}
909
910
65811
void QuantInfo::getMatch( std::vector< Node >& terms ){
911
251801
  for( unsigned i=0; i<d_q[0].getNumChildren(); i++ ){
912
    //Node cv = qi->getCurrentValue( qi->d_match[i] );
913
185990
    int repVar = getCurrentRepVar( i );
914
371980
    Node cv;
915
    //std::map< int, TNode >::iterator itmt = qi->d_match_term.find( repVar );
916
185990
    if( !d_match_term[repVar].isNull() ){
917
183908
      cv = d_match_term[repVar];
918
    }else{
919
2082
      cv = d_match[repVar];
920
    }
921
185990
    Debug("qcf-check-inst") << "INST : " << i << " -> " << cv << ", from " << d_match[i] << std::endl;
922
185990
    terms.push_back( cv );
923
  }
924
65811
}
925
926
65386
void QuantInfo::revertMatch( QuantConflictFind * p, std::vector< int >& assigned ) {
927
65574
  for( unsigned i=0; i<assigned.size(); i++ ){
928
188
    unsetMatch( p, assigned[i] );
929
  }
930
65386
}
931
932
void QuantInfo::debugPrintMatch( const char * c ) {
933
  for( int i=0; i<getNumVars(); i++ ){
934
    Trace(c) << "  " << d_vars[i] << " -> ";
935
    if( !d_match[i].isNull() ){
936
      Trace(c) << d_match[i];
937
    }else{
938
      Trace(c) << "(unassigned) ";
939
    }
940
    if( !d_curr_var_deq[i].empty() ){
941
      Trace(c) << ", DEQ{ ";
942
      for( std::map< TNode, int >::iterator it = d_curr_var_deq[i].begin(); it != d_curr_var_deq[i].end(); ++it ){
943
        Trace(c) << it->first << " ";
944
      }
945
      Trace(c) << "}";
946
    }
947
    if( !d_match_term[i].isNull() && d_match_term[i]!=d_match[i] ){
948
      Trace(c) << ", EXP : " << d_match_term[i];
949
    }
950
    Trace(c) <<  std::endl;
951
  }
952
  if( !d_tconstraints.empty() ){
953
    Trace(c) << "ADDITIONAL CONSTRAINTS : " << std::endl;
954
    for( std::map< Node, bool >::iterator it = d_tconstraints.begin(); it != d_tconstraints.end(); ++it ){
955
      Trace(c) << "   " << it->first << " -> " << it->second << std::endl;
956
    }
957
  }
958
}
959
960
MatchGen::MatchGen()
961
  : d_matched_basis(),
962
    d_binding(),
963
    d_tgt(),
964
    d_tgt_orig(),
965
    d_wasSet(),
966
    d_n(),
967
    d_type( typ_invalid ),
968
    d_type_not()
969
{
970
  d_qni_size = 0;
971
  d_child_counter = -1;
972
  d_use_children = true;
973
}
974
975
976
60825
MatchGen::MatchGen( QuantInfo * qi, Node n, bool isVar )
977
  : d_matched_basis(),
978
    d_binding(),
979
    d_tgt(),
980
    d_tgt_orig(),
981
    d_wasSet(),
982
    d_n(),
983
    d_type(),
984
60825
    d_type_not()
985
{
986
  //initialize temporary
987
60825
  d_child_counter = -1;
988
60825
  d_use_children = true;
989
990
60825
  Trace("qcf-qregister-debug") << "Make match gen for " << n << ", isVar = " << isVar << std::endl;
991
121650
  std::vector< Node > qni_apps;
992
60825
  d_qni_size = 0;
993
60825
  if( isVar ){
994
31226
    Assert(qi->d_var_num.find(n) != qi->d_var_num.end());
995
    // rare case where we have a free variable in an operator, we are invalid
996
62452
    if (n.getKind() == ITE
997
63011
        || (options::ufHo() && n.getKind() == APPLY_UF
998
39362
            && expr::hasFreeVar(n.getOperator())))
999
    {
1000
559
      d_type = typ_invalid;
1001
    }else{
1002
30667
      d_type = isHandledUfTerm( n ) ? typ_var : typ_tsym;
1003
30667
      d_qni_var_num[0] = qi->getVarNum( n );
1004
30667
      d_qni_size++;
1005
30667
      d_type_not = false;
1006
30667
      d_n = n;
1007
      //Node f = getMatchOperator( n );
1008
94065
      for( unsigned j=0; j<d_n.getNumChildren(); j++ ){
1009
126796
        Node nn = d_n[j];
1010
63398
        Trace("qcf-qregister-debug") << "  " << d_qni_size;
1011
63398
        if( qi->isVar( nn ) ){
1012
54447
          int v = qi->d_var_num[nn];
1013
54447
          Trace("qcf-qregister-debug") << " is var #" << v << std::endl;
1014
54447
          d_qni_var_num[d_qni_size] = v;
1015
          //qi->addFuncParent( v, f, j );
1016
        }else{
1017
8951
          Trace("qcf-qregister-debug") << " is gterm " << nn << std::endl;
1018
8951
          d_qni_gterm[d_qni_size] = nn;
1019
        }
1020
63398
        d_qni_size++;
1021
      }
1022
    }
1023
  }else{
1024
29599
    if (expr::hasBoundVar(n))
1025
    {
1026
29565
      d_type_not = false;
1027
29565
      d_n = n;
1028
29565
      if( d_n.getKind()==NOT ){
1029
9599
        d_n = d_n[0];
1030
9599
        d_type_not = !d_type_not;
1031
      }
1032
1033
29565
      if( isHandledBoolConnective( d_n ) ){
1034
        //non-literals
1035
10269
        d_type = typ_formula;
1036
31545
        for( unsigned i=0; i<d_n.getNumChildren(); i++ ){
1037
22962
          if( d_n.getKind()!=FORALL || i==1 ){
1038
20966
            d_children.push_back( MatchGen( qi, d_n[i], false ) );
1039
20966
            if( !d_children[d_children.size()-1].isValid() ){
1040
1686
              setInvalid();
1041
1686
              break;
1042
            }
1043
          }
1044
        }
1045
      }else{
1046
19296
        d_type = typ_invalid;
1047
        //literals
1048
19296
        if( isHandledUfTerm( d_n ) ){
1049
7228
          Assert(qi->isVar(d_n));
1050
7228
          d_type = typ_pred;
1051
12068
        }else if( d_n.getKind()==BOUND_VARIABLE ){
1052
89
          Assert(d_n.getType().isBoolean());
1053
89
          d_type = typ_bool_var;
1054
11979
        }else if( d_n.getKind()==EQUAL || options::qcfTConstraint() ){
1055
32019
          for (unsigned i = 0; i < d_n.getNumChildren(); i++)
1056
          {
1057
21346
            if (expr::hasBoundVar(d_n[i]))
1058
            {
1059
16061
              if (!qi->isVar(d_n[i]))
1060
              {
1061
                Trace("qcf-qregister-debug")
1062
                    << "ERROR : not var " << d_n[i] << std::endl;
1063
              }
1064
16061
              Assert(qi->isVar(d_n[i]));
1065
16061
              if (d_n.getKind() != EQUAL && qi->isVar(d_n[i]))
1066
              {
1067
110
                d_qni_var_num[i + 1] = qi->d_var_num[d_n[i]];
1068
              }
1069
            }
1070
            else
1071
            {
1072
5285
              d_qni_gterm[i] = d_n[i];
1073
            }
1074
          }
1075
10673
          d_type = d_n.getKind() == EQUAL ? typ_eq : typ_tconstraint;
1076
10673
          Trace("qcf-tconstraint") << "T-Constraint : " << d_n << std::endl;
1077
        }
1078
      }
1079
    }else{
1080
      //we will just evaluate
1081
34
      d_n = n;
1082
34
      d_type = typ_ground;
1083
    }
1084
  }
1085
60825
  Trace("qcf-qregister-debug")  << "Done make match gen " << n << ", type = ";
1086
60825
  debugPrintType( "qcf-qregister-debug", d_type, true );
1087
60825
  Trace("qcf-qregister-debug") << std::endl;
1088
  //Assert( d_children.size()==d_children_order.size() );
1089
1090
60825
}
1091
1092
168901
void MatchGen::collectBoundVar( QuantInfo * qi, Node n, std::vector< int >& cbvars, std::map< Node, bool >& visited, bool& hasNested ) {
1093
168901
  if( visited.find( n )==visited.end() ){
1094
146331
    visited[n] = true;
1095
146331
    if( n.getKind()==FORALL ){
1096
1522
      hasNested = true;
1097
    }
1098
146331
    int v = qi->getVarNum( n );
1099
146331
    if( v!=-1 && std::find( cbvars.begin(), cbvars.end(), v )==cbvars.end() ){
1100
94405
      cbvars.push_back( v );
1101
    }
1102
298466
    for( unsigned i=0; i<n.getNumChildren(); i++ ){
1103
152135
      collectBoundVar( qi, n[i], cbvars, visited, hasNested );
1104
    }
1105
  }
1106
168901
}
1107
1108
54034
void MatchGen::determineVariableOrder( QuantInfo * qi, std::vector< int >& bvars ) {
1109
54034
  Trace("qcf-qregister-debug") << "Determine variable order " << d_n << ", #bvars = " << bvars.size() << std::endl;
1110
54034
  bool isComm = d_type==typ_formula && ( d_n.getKind()==OR || d_n.getKind()==AND || d_n.getKind()==EQUAL );
1111
54034
  if( isComm ){
1112
12208
    std::map< int, std::vector< int > > c_to_vars;
1113
12208
    std::map< int, std::vector< int > > vars_to_c;
1114
12208
    std::map< int, int > vb_count;
1115
12208
    std::map< int, int > vu_count;
1116
12208
    std::map< int, bool > has_nested;
1117
12208
    std::vector< bool > assigned;
1118
6104
    Trace("qcf-qregister-debug") << "Calculate bound variables..." << std::endl;
1119
21231
    for( unsigned i=0; i<d_children.size(); i++ ){
1120
30254
      std::map< Node, bool > visited;
1121
15127
      has_nested[i] = false;
1122
15127
      collectBoundVar( qi, d_children[i].d_n, c_to_vars[i], visited, has_nested[i] );
1123
15127
      assigned.push_back( false );
1124
15127
      vb_count[i] = 0;
1125
15127
      vu_count[i] = 0;
1126
91523
      for( unsigned j=0; j<c_to_vars[i].size(); j++ ){
1127
76396
        int v = c_to_vars[i][j];
1128
76396
        vars_to_c[v].push_back( i );
1129
76396
        if( std::find( bvars.begin(), bvars.end(), v )==bvars.end() ){
1130
69690
          vu_count[i]++;
1131
        }else{
1132
6706
          vb_count[i]++;
1133
        }
1134
      }
1135
    }
1136
    //children that bind no unbound variable, then the most number of bound, unbound variables go first
1137
6104
    Trace("qcf-qregister-vo") << "Variable order for " << d_n << " : " << std::endl;
1138
9023
    do {
1139
15127
      int min_score0 = -1;
1140
15127
      int min_score = -1;
1141
15127
      int min_score_index = -1;
1142
207480
      for( unsigned i=0; i<d_children.size(); i++ ){
1143
192353
        if( !assigned[i] ){
1144
103740
          Trace("qcf-qregister-debug2") << "Child " << i << " has b/ub : " << vb_count[i] << "/" << vu_count[i] << std::endl;
1145
103740
          int score0 = 0;//has_nested[i] ? 0 : 1;
1146
          int score;
1147
103740
          if( !options::qcfVoExp() ){
1148
103740
            score = vu_count[i];
1149
          }else{
1150
            score =  vu_count[i]==0 ? 0 : ( 1 + qi->d_vars.size()*( qi->d_vars.size() - vb_count[i] ) + ( qi->d_vars.size() - vu_count[i] )  );
1151
          }
1152
103740
          if( min_score==-1 || score0<min_score0 || ( score0==min_score0 && score<min_score ) ){
1153
24127
            min_score0 = score0;
1154
24127
            min_score = score;
1155
24127
            min_score_index = i;
1156
          }
1157
        }
1158
      }
1159
15127
      Trace("qcf-qregister-vo") << "  " << d_children_order.size()+1 << ": " << d_children[min_score_index].d_n << " : ";
1160
15127
      Trace("qcf-qregister-vo") << vu_count[min_score_index] << " " << vb_count[min_score_index] << " " << has_nested[min_score_index] << std::endl;
1161
15127
      Trace("qcf-qregister-debug") << "...assign child " << min_score_index << std::endl;
1162
15127
      Trace("qcf-qregister-debug") << "...score : " << min_score << std::endl;
1163
15127
      Assert(min_score_index != -1);
1164
      //add to children order
1165
15127
      d_children_order.push_back( min_score_index );
1166
15127
      assigned[min_score_index] = true;
1167
      //determine order internal to children
1168
15127
      d_children[min_score_index].determineVariableOrder( qi, bvars );
1169
15127
      Trace("qcf-qregister-debug")  << "...bind variables" << std::endl;
1170
      //now, make it a bound variable
1171
15127
      if( vu_count[min_score_index]>0 ){
1172
86236
        for( unsigned i=0; i<c_to_vars[min_score_index].size(); i++ ){
1173
71813
          int v = c_to_vars[min_score_index][i];
1174
71813
          if( std::find( bvars.begin(), bvars.end(), v )==bvars.end() ){
1175
89308
            for( unsigned j=0; j<vars_to_c[v].size(); j++ ){
1176
56738
              int vc = vars_to_c[v][j];
1177
56738
              vu_count[vc]--;
1178
56738
              vb_count[vc]++;
1179
            }
1180
32570
            bvars.push_back( v );
1181
          }
1182
        }
1183
      }
1184
15127
      Trace("qcf-qregister-debug") << "...done assign child " << min_score_index << std::endl;
1185
15127
    }while( d_children_order.size()!=d_children.size() );
1186
6104
    Trace("qcf-qregister-debug") << "Done assign variable ordering for " << d_n << std::endl;
1187
  }else{
1188
49569
    for( unsigned i=0; i<d_children.size(); i++ ){
1189
1639
      d_children_order.push_back( i );
1190
1639
      d_children[i].determineVariableOrder( qi, bvars );
1191
      //now add to bvars
1192
3278
      std::map< Node, bool > visited;
1193
3278
      std::vector< int > cvars;
1194
1639
      bool has_nested = false;
1195
1639
      collectBoundVar( qi, d_children[i].d_n, cvars, visited, has_nested );
1196
19648
      for( unsigned j=0; j<cvars.size(); j++ ){
1197
18009
        if( std::find( bvars.begin(), bvars.end(), cvars[j] )==bvars.end() ){
1198
2736
          bvars.push_back( cvars[j] );
1199
        }
1200
      }
1201
    }
1202
  }
1203
54034
}
1204
1205
379799
bool MatchGen::reset_round(QuantConflictFind* p)
1206
{
1207
379799
  d_wasSet = false;
1208
514425
  for( unsigned i=0; i<d_children.size(); i++ ){
1209
134626
    if (!d_children[i].reset_round(p))
1210
    {
1211
      return false;
1212
    }
1213
  }
1214
379799
  if( d_type==typ_ground ){
1215
    // int e = p->evaluate( d_n );
1216
    // if( e==1 ){
1217
    //  d_ground_eval[0] = p->d_true;
1218
    //}else if( e==-1 ){
1219
    //  d_ground_eval[0] = p->d_false;
1220
    //}
1221
    // modified
1222
198
    TermDb* tdb = p->getTermDatabase();
1223
198
    QuantifiersState& qs = p->getState();
1224
594
    for (unsigned i = 0; i < 2; i++)
1225
    {
1226
396
      if (tdb->isEntailed(d_n, i == 0))
1227
      {
1228
8
        d_ground_eval[0] = i==0 ? p->d_true : p->d_false;
1229
      }
1230
396
      if (qs.isInConflict())
1231
      {
1232
        return false;
1233
      }
1234
    }
1235
379601
  }else if( d_type==typ_eq ){
1236
63682
    TermDb* tdb = p->getTermDatabase();
1237
63682
    QuantifiersState& qs = p->getState();
1238
191046
    for (unsigned i = 0, size = d_n.getNumChildren(); i < size; i++)
1239
    {
1240
127364
      if (!expr::hasBoundVar(d_n[i]))
1241
      {
1242
69608
        TNode t = tdb->getEntailedTerm(d_n[i]);
1243
34804
        if (qs.isInConflict())
1244
        {
1245
          return false;
1246
        }
1247
34804
        if (t.isNull())
1248
        {
1249
974
          d_ground_eval[i] = d_n[i];
1250
        }
1251
        else
1252
        {
1253
33830
          d_ground_eval[i] = t;
1254
        }
1255
      }
1256
    }
1257
  }
1258
379799
  d_qni_bound_cons.clear();
1259
379799
  d_qni_bound_cons_var.clear();
1260
379799
  d_qni_bound.clear();
1261
379799
  return true;
1262
}
1263
1264
580295
void MatchGen::reset( QuantConflictFind * p, bool tgt, QuantInfo * qi ) {
1265
580295
  d_tgt = d_type_not ? !tgt : tgt;
1266
580295
  Debug("qcf-match") << "     Reset for : " << d_n << ", type : ";
1267
580295
  debugPrintType( "qcf-match", d_type );
1268
580295
  Debug("qcf-match") << ", tgt = " << d_tgt << ", children = " << d_children.size() << " " << d_children_order.size() << std::endl;
1269
580295
  d_qn.clear();
1270
580295
  d_qni.clear();
1271
580295
  d_qni_bound.clear();
1272
580295
  d_child_counter = -1;
1273
580295
  d_use_children = true;
1274
580295
  d_tgt_orig = d_tgt;
1275
1276
  //set up processing matches
1277
580295
  if( d_type==typ_invalid ){
1278
    d_use_children = false;
1279
580295
  }else if( d_type==typ_ground ){
1280
76
    d_use_children = false;
1281
76
    if( d_ground_eval[0]==( d_tgt ? p->d_true : p->d_false ) ){
1282
6
      d_child_counter = 0;
1283
    }
1284
580219
  }else if( qi->isBaseMatchComplete() && options::qcfEagerTest() ){
1285
84228
    d_use_children = false;
1286
84228
    d_child_counter = 0;
1287
495991
  }else if( d_type==typ_bool_var ){
1288
    //get current value of the variable
1289
1208
    TNode n = qi->getCurrentValue( d_n );
1290
604
    int vn = qi->getCurrentRepVar( qi->getVarNum( n ) );
1291
604
    if( vn==-1 ){
1292
      //evaluate the value, see if it is compatible
1293
      //int e = p->evaluate( n );
1294
      //if( ( e==1 && d_tgt ) || ( e==0 && !d_tgt ) ){
1295
      //  d_child_counter = 0;
1296
      //}
1297
      //modified
1298
      if( p->getTermDatabase()->isEntailed( n, d_tgt ) ){
1299
        d_child_counter = 0;
1300
      }
1301
    }else{
1302
      //unassigned, set match to true/false
1303
604
      d_qni_bound[0] = vn;
1304
604
      qi->setMatch( p, vn, d_tgt ? p->d_true : p->d_false, false, true );
1305
604
      d_child_counter = 0;
1306
    }
1307
604
    if( d_child_counter==0 ){
1308
604
      d_qn.push_back( NULL );
1309
    }
1310
495387
  }else if( d_type==typ_var ){
1311
306549
    Assert(isHandledUfTerm(d_n));
1312
613098
    TNode f = getMatchOperator( p, d_n );
1313
306549
    Debug("qcf-match-debug") << "       reset: Var will match operators of " << f << std::endl;
1314
306549
    TNodeTrie* qni = p->getTermDatabase()->getTermArgTrie(Node::null(), f);
1315
306549
    if (qni == nullptr || qni->empty())
1316
    {
1317
      //inform irrelevant quantifiers
1318
35176
      p->setIrrelevantFunction( f );
1319
    }
1320
    else
1321
    {
1322
271373
      d_qn.push_back(qni);
1323
    }
1324
306549
    d_matched_basis = false;
1325
188838
  }else if( d_type==typ_tsym || d_type==typ_tconstraint ){
1326
1065
    for( std::map< int, int >::iterator it = d_qni_var_num.begin(); it != d_qni_var_num.end(); ++it ){
1327
636
      int repVar = qi->getCurrentRepVar( it->second );
1328
636
      if( qi->d_match[repVar].isNull() ){
1329
614
        Debug("qcf-match-debug") << "Force matching on child #" << it->first << ", which is var #" << repVar << std::endl;
1330
614
        d_qni_bound[it->first] = repVar;
1331
      }
1332
    }
1333
429
    d_qn.push_back( NULL );
1334
188409
  }else if( d_type==typ_pred || d_type==typ_eq ){
1335
    //add initial constraint
1336
269298
    Node nn[2];
1337
    int vn[2];
1338
134649
    if( d_type==typ_pred ){
1339
58005
      nn[0] = qi->getCurrentValue( d_n );
1340
58005
      vn[0] = qi->getCurrentRepVar( qi->getVarNum( nn[0] ) );
1341
58005
      nn[1] = d_tgt ? p->d_true : p->d_false;
1342
58005
      vn[1] = -1;
1343
58005
      d_tgt = true;
1344
    }else{
1345
229932
      for( unsigned i=0; i<2; i++ ){
1346
306576
        TNode nc;
1347
153288
        std::map<int, TNode>::iterator it = d_qni_gterm.find(i);
1348
153288
        if (it != d_qni_gterm.end())
1349
        {
1350
49138
          nc = it->second;
1351
        }else{
1352
104150
          nc = d_n[i];
1353
        }
1354
153288
        nn[i] = qi->getCurrentValue( nc );
1355
153288
        vn[i] = qi->getCurrentRepVar( qi->getVarNum( nn[i] ) );
1356
      }
1357
    }
1358
    bool success;
1359
134649
    if( vn[0]==-1 && vn[1]==-1 ){
1360
      //Trace("qcf-explain") << "    reset : " << d_n << " check ground values " << nn[0] << " " << nn[1] << " (tgt=" << d_tgt << ")" << std::endl;
1361
285
      Debug("qcf-match-debug") << "       reset: check ground values " << nn[0] << " " << nn[1] << " (" << d_tgt << ")" << std::endl;
1362
      //just compare values
1363
570
      if( d_tgt ){
1364
258
        success = p->areMatchEqual( nn[0], nn[1] );
1365
      }else{
1366
27
        if (p->atConflictEffort()) {
1367
14
          success = p->areDisequal( nn[0], nn[1] );
1368
        }else{
1369
13
          success = p->areMatchDisequal( nn[0], nn[1] );
1370
        }
1371
      }
1372
    }else{
1373
      //otherwise, add a constraint to a variable  TODO: this may be over-eager at effort > conflict, since equality may be a propagation
1374
134364
      if( vn[1]!=-1 && vn[0]==-1 ){
1375
        //swap
1376
44838
        Node t = nn[1];
1377
22419
        nn[1] = nn[0];
1378
22419
        nn[0] = t;
1379
22419
        vn[0] = vn[1];
1380
22419
        vn[1] = -1;
1381
      }
1382
134364
      Debug("qcf-match-debug") << "       reset: add constraint " << vn[0] << " -> " << nn[1] << " (vn=" << vn[1] << ")" << std::endl;
1383
      //add some constraint
1384
134364
      int addc = qi->addConstraint( p, vn[0], nn[1], vn[1], d_tgt, false );
1385
134364
      success = addc!=-1;
1386
      //if successful and non-redundant, store that we need to cleanup this
1387
134364
      if( addc==1 ){
1388
        //Trace("qcf-explain") << "       reset: " << d_n << " add constraint " << vn[0] << " -> " << nn[1] << " (vn=" << vn[1] << ")" << ", d_tgt = " << d_tgt << std::endl;
1389
402915
        for( unsigned i=0; i<2; i++ ){
1390
268610
          if( vn[i]!=-1 && std::find( d_qni_bound_except.begin(), d_qni_bound_except.end(), i )==d_qni_bound_except.end() ){
1391
160463
            d_qni_bound[vn[i]] = vn[i];
1392
          }
1393
        }
1394
134305
        d_qni_bound_cons[vn[0]] = nn[1];
1395
134305
        d_qni_bound_cons_var[vn[0]] = vn[1];
1396
      }
1397
    }
1398
    //if successful, we will bind values to variables
1399
134649
    if( success ){
1400
134419
      d_qn.push_back( NULL );
1401
134649
    }
1402
  }else{
1403
53760
    if( d_children.empty() ){
1404
      //add dummy
1405
      d_qn.push_back( NULL );
1406
    }else{
1407
53760
      if( d_tgt && d_n.getKind()==FORALL ){
1408
        //fail
1409
46835
      } else if (d_n.getKind() == FORALL && p->atConflictEffort() &&
1410
1239
                 !options::qcfNestedConflict()) {
1411
        //fail
1412
      }else{
1413
        //reset the first child to d_tgt
1414
44357
        d_child_counter = 0;
1415
44357
        getChild( d_child_counter )->reset( p, d_tgt, qi );
1416
      }
1417
    }
1418
  }
1419
580295
  d_binding = false;
1420
580295
  d_wasSet = true;
1421
580295
  Debug("qcf-match") << "     reset: Finished reset for " << d_n << ", success = " << ( !d_qn.empty() || d_child_counter!=-1 ) << std::endl;
1422
580295
}
1423
1424
1106380
bool MatchGen::getNextMatch( QuantConflictFind * p, QuantInfo * qi ) {
1425
1106380
  Debug("qcf-match") << "     Get next match for : " << d_n << ", type = ";
1426
1106380
  debugPrintType( "qcf-match", d_type );
1427
1106380
  Debug("qcf-match") << ", children = " << d_children.size() << ", binding = " << d_binding << std::endl;
1428
1106380
  if( !d_use_children ){
1429
168193
    if( d_child_counter==0 ){
1430
84234
      d_child_counter = -1;
1431
84234
      return true;
1432
    }else{
1433
83959
      d_wasSet = false;
1434
83959
      return false;
1435
    }
1436
938187
  }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 ){
1437
791319
    bool success = false;
1438
791319
    bool terminate = false;
1439
460169
    do {
1440
1251488
      bool doReset = false;
1441
1251488
      bool doFail = false;
1442
1251488
      if( !d_binding ){
1443
904204
        if( doMatching( p, qi ) ){
1444
463972
          Debug("qcf-match-debug") << "     - Matching succeeded" << std::endl;
1445
463972
          d_binding = true;
1446
463972
          d_binding_it = d_qni_bound.begin();
1447
463972
          doReset = true;
1448
          //for tconstraint, add constraint
1449
463972
          if( d_type==typ_tconstraint ){
1450
289
            std::map< Node, bool >::iterator it = qi->d_tconstraints.find( d_n );
1451
289
            if( it==qi->d_tconstraints.end() ){
1452
289
              qi->d_tconstraints[d_n] = d_tgt;
1453
              //store that we added this constraint
1454
289
              d_qni_bound_cons[0] = d_n;
1455
            }else if( d_tgt!=it->second ){
1456
              success = false;
1457
              terminate = true;
1458
            }
1459
          }
1460
        }else{
1461
440232
          Debug("qcf-match-debug") << "     - Matching failed" << std::endl;
1462
440232
          success = false;
1463
440232
          terminate = true;
1464
        }
1465
      }else{
1466
347284
        doFail = true;
1467
      }
1468
1251488
      if( d_binding ){
1469
        //also need to create match for each variable we bound
1470
811256
        success = true;
1471
811256
        Debug("qcf-match-debug") << "     Produce matches for bound variables by " << d_n << ", type = ";
1472
811256
        debugPrintType( "qcf-match-debug", d_type );
1473
811256
        Debug("qcf-match-debug") << "..." << std::endl;
1474
1475
3485880
        while( ( success && d_binding_it!=d_qni_bound.end() ) || doFail ){
1476
1337312
          QuantInfo::VarMgMap::const_iterator itm;
1477
1337312
          if( !doFail ){
1478
990028
            Debug("qcf-match-debug") << "       check variable " << d_binding_it->second << std::endl;
1479
990028
            itm = qi->var_mg_find( d_binding_it->second );
1480
          }
1481
1337312
          if( doFail || ( d_binding_it->first!=0 && itm != qi->var_mg_end() ) ){
1482
899074
            Debug("qcf-match-debug") << "       we had bound variable " << d_binding_it->second << ", reset = " << doReset << std::endl;
1483
899074
            if( doReset ){
1484
332926
              itm->second->reset( p, true, qi );
1485
            }
1486
899074
            if( doFail || !itm->second->getNextMatch( p, qi ) ){
1487
436438
              do {
1488
1115471
                if( d_binding_it==d_qni_bound.begin() ){
1489
460169
                  Debug("qcf-match-debug") << "       failed." << std::endl;
1490
460169
                  success = false;
1491
                }else{
1492
655302
                  --d_binding_it;
1493
655302
                  Debug("qcf-match-debug") << "       decrement..." << std::endl;
1494
                }
1495
2207211
              }while( success &&
1496
1147714
                      ( d_binding_it->first==0 ||
1497
492412
                        (!qi->containsVarMg(d_binding_it->second))));
1498
679033
              doReset = false;
1499
679033
              doFail = false;
1500
            }else{
1501
220041
              Debug("qcf-match-debug") << "       increment..." << std::endl;
1502
220041
              ++d_binding_it;
1503
220041
              doReset = true;
1504
            }
1505
          }else{
1506
438238
            Debug("qcf-match-debug") << "       skip..." << d_binding_it->second << std::endl;
1507
438238
            ++d_binding_it;
1508
438238
            doReset = true;
1509
          }
1510
        }
1511
811256
        if( !success ){
1512
460169
          d_binding = false;
1513
        }else{
1514
351087
          terminate = true;
1515
351087
          if( d_binding_it==d_qni_bound.begin() ){
1516
1824
            d_binding = false;
1517
          }
1518
        }
1519
      }
1520
1251488
    }while( !terminate );
1521
    //if not successful, clean up the variables you bound
1522
791319
    if( !success ){
1523
440232
      if( d_type==typ_eq || d_type==typ_pred ){
1524
        //clean up the constraints you added
1525
267195
        for( std::map< int, TNode >::iterator it = d_qni_bound_cons.begin(); it != d_qni_bound_cons.end(); ++it ){
1526
133427
          if( !it->second.isNull() ){
1527
133427
            Debug("qcf-match") << "       Clean up bound var " << it->first << (d_tgt ? "!" : "") << " = " << it->second << std::endl;
1528
133427
            std::map< int, int >::iterator itb = d_qni_bound_cons_var.find( it->first );
1529
133427
            int vn = itb!=d_qni_bound_cons_var.end() ? itb->second : -1;
1530
            //Trace("qcf-explain") << "       cleanup: " << d_n << " remove constraint " << it->first << " -> " << it->second << " (vn=" << vn << ")" << ", d_tgt = " << d_tgt << std::endl;
1531
133427
            qi->addConstraint( p, it->first, it->second, vn, d_tgt, true );
1532
          }
1533
        }
1534
133768
        d_qni_bound_cons.clear();
1535
133768
        d_qni_bound_cons_var.clear();
1536
133768
        d_qni_bound.clear();
1537
      }else{
1538
        //clean up the matches you set
1539
532339
        for( std::map< int, int >::iterator it = d_qni_bound.begin(); it != d_qni_bound.end(); ++it ){
1540
225875
          Debug("qcf-match") << "       Clean up bound var " << it->second << std::endl;
1541
225875
          Assert(it->second < qi->getNumVars());
1542
225875
          qi->unsetMatch( p, it->second );
1543
225875
          qi->d_match_term[ it->second ] = TNode::null();
1544
        }
1545
306464
        d_qni_bound.clear();
1546
      }
1547
440232
      if( d_type==typ_tconstraint ){
1548
        //remove constraint if applicable
1549
287
        if( d_qni_bound_cons.find( 0 )!=d_qni_bound_cons.end() ){
1550
287
          qi->d_tconstraints.erase( d_n );
1551
287
          d_qni_bound_cons.clear();
1552
        }
1553
      }
1554
    }
1555
791319
    Debug("qcf-match") << "    ...finished matching for " << d_n << ", success = " << success << std::endl;
1556
791319
    d_wasSet = success;
1557
791319
    return success;
1558
  }
1559
146868
  else if (d_type == typ_formula)
1560
  {
1561
146868
    bool success = false;
1562
146868
    if( d_child_counter<0 ){
1563
9403
      if( d_child_counter<-1 ){
1564
        success = true;
1565
        d_child_counter = -1;
1566
      }
1567
    }else{
1568
890231
      while( !success && d_child_counter>=0 ){
1569
        //transition system based on d_child_counter
1570
376383
        if( d_n.getKind()==OR || d_n.getKind()==AND ){
1571
271749
          if( (d_n.getKind()==AND)==d_tgt ){
1572
            //all children must match simultaneously
1573
252811
            if( getChild( d_child_counter )->getNextMatch( p, qi ) ){
1574
143232
              if( d_child_counter<(int)(getNumChildren()-1) ){
1575
87079
                d_child_counter++;
1576
87079
                Debug("qcf-match-debug") << "       Reset child " << d_child_counter << " of " << d_n << std::endl;
1577
87079
                getChild( d_child_counter )->reset( p, d_tgt, qi );
1578
              }else{
1579
56153
                success = true;
1580
              }
1581
            }else{
1582
              //if( std::find( d_independent.begin(), d_independent.end(), d_child_counter )!=d_independent.end() ){
1583
              //  d_child_counter--;
1584
              //}else{
1585
109579
              d_child_counter--;
1586
              //}
1587
            }
1588
          }else{
1589
            //one child must match
1590
18938
            if( !getChild( d_child_counter )->getNextMatch( p, qi ) ){
1591
8507
              if( d_child_counter<(int)(getNumChildren()-1) ){
1592
4782
                d_child_counter++;
1593
4782
                Debug("qcf-match-debug") << "       Reset child " << d_child_counter << " of " << d_n << ", one match" << std::endl;
1594
4782
                getChild( d_child_counter )->reset( p, d_tgt, qi );
1595
              }else{
1596
3725
                d_child_counter = -1;
1597
              }
1598
            }else{
1599
10431
              success = true;
1600
            }
1601
          }
1602
104634
        }else if( d_n.getKind()==EQUAL ){
1603
          //construct match based on both children
1604
95471
          if( d_child_counter%2==0 ){
1605
71294
            if( getChild( 0 )->getNextMatch( p, qi ) ){
1606
40119
              d_child_counter++;
1607
40119
              getChild( 1 )->reset( p, d_child_counter==1, qi );
1608
            }else{
1609
31175
              if( d_child_counter==0 ){
1610
15608
                d_child_counter = 2;
1611
15608
                getChild( 0 )->reset( p, !d_tgt, qi );
1612
              }else{
1613
15567
                d_child_counter = -1;
1614
              }
1615
            }
1616
          }
1617
95471
          if( d_child_counter>=0 && d_child_counter%2==1 ){
1618
64296
            if( getChild( 1 )->getNextMatch( p, qi ) ){
1619
24287
              success = true;
1620
            }else{
1621
40009
              d_child_counter--;
1622
            }
1623
          }
1624
9163
        }else if( d_n.getKind()==ITE ){
1625
7980
          if( d_child_counter%2==0 ){
1626
5356
            int index1 = d_child_counter==4 ? 1 : 0;
1627
5356
            if( getChild( index1 )->getNextMatch( p, qi ) ){
1628
4033
              d_child_counter++;
1629
4033
              getChild( d_child_counter==5 ? 2 : (d_tgt==(d_child_counter==1) ? 1 : 2) )->reset( p, d_tgt, qi );
1630
            }else{
1631
1323
              if (d_child_counter == 4)
1632
              {
1633
439
                d_child_counter = -1;
1634
              }else{
1635
884
                d_child_counter +=2;
1636
884
                getChild( d_child_counter==2 ? 0 : 1 )->reset( p, d_child_counter==2 ? !d_tgt : d_tgt, qi );
1637
              }
1638
            }
1639
          }
1640
7980
          if( d_child_counter>=0 && d_child_counter%2==1 ){
1641
6657
            int index2 = d_child_counter==5 ? 2 : (d_tgt==(d_child_counter==1) ? 1 : 2);
1642
6657
            if( getChild( index2 )->getNextMatch( p, qi ) ){
1643
2654
              success = true;
1644
            }else{
1645
4003
              d_child_counter--;
1646
            }
1647
          }
1648
1183
        }else if( d_n.getKind()==FORALL ){
1649
1183
          if( getChild( d_child_counter )->getNextMatch( p, qi ) ){
1650
120
            success = true;
1651
          }else{
1652
1063
            d_child_counter = -1;
1653
          }
1654
        }
1655
      }
1656
137465
        d_wasSet = success;
1657
137465
      Debug("qcf-match") << "    ...finished construct match for " << d_n << ", success = " << success << std::endl;
1658
137465
      return success;
1659
    }
1660
  }
1661
9403
  Debug("qcf-match") << "    ...already finished for " << d_n << std::endl;
1662
9403
  return false;
1663
}
1664
1665
904204
bool MatchGen::doMatching( QuantConflictFind * p, QuantInfo * qi ) {
1666
904204
  if( !d_qn.empty() ){
1667
734229
    if( d_qn[0]==NULL ){
1668
135452
      d_qn.clear();
1669
135452
      return true;
1670
    }else{
1671
598777
      Assert(d_type == typ_var);
1672
598777
      Assert(d_qni_size > 0);
1673
      bool invalidMatch;
1674
2474560
      do {
1675
3073337
        invalidMatch = false;
1676
3073337
        Debug("qcf-match-debug") << "       Do matching " << d_n << " " << d_qn.size() << " " << d_qni.size() << std::endl;
1677
3073337
        if( d_qn.size()==d_qni.size()+1 ) {
1678
1476583
          int index = (int)d_qni.size();
1679
          //initialize
1680
2953166
          TNode val;
1681
1476583
          std::map< int, int >::iterator itv = d_qni_var_num.find( index );
1682
1476583
          if( itv!=d_qni_var_num.end() ){
1683
            //get the representative variable this variable is equal to
1684
1375276
            int repVar = qi->getCurrentRepVar( itv->second );
1685
1375276
            Debug("qcf-match-debug") << "       Match " << index << " is a variable " << itv->second << ", which is repVar " << repVar << std::endl;
1686
            //get the value the rep variable
1687
            //std::map< int, TNode >::iterator itm = qi->d_match.find( repVar );
1688
1375276
            if( !qi->d_match[repVar].isNull() ){
1689
864214
              val = qi->d_match[repVar];
1690
864214
              Debug("qcf-match-debug") << "       Variable is already bound to " << val << std::endl;
1691
            }else{
1692
              //binding a variable
1693
511062
              d_qni_bound[index] = repVar;
1694
              std::map<TNode, TNodeTrie>::iterator it =
1695
511062
                  d_qn[index]->d_data.begin();
1696
511062
              if( it != d_qn[index]->d_data.end() ) {
1697
511062
                d_qni.push_back( it );
1698
                //set the match
1699
511062
                if( it->first.getType().isComparableTo( qi->d_var_types[repVar] ) && qi->setMatch( p, d_qni_bound[index], it->first, true, true ) ){
1700
470886
                  Debug("qcf-match-debug") << "       Binding variable" << std::endl;
1701
470886
                  if( d_qn.size()<d_qni_size ){
1702
234144
                    d_qn.push_back( &it->second );
1703
                  }
1704
                }else{
1705
40176
                  Debug("qcf-match") << "       Binding variable, currently fail." << std::endl;
1706
40176
                  invalidMatch = true;
1707
                }
1708
              }else{
1709
                Debug("qcf-match-debug") << "       Binding variable, fail, no more variables to bind" << std::endl;
1710
                d_qn.pop_back();
1711
              }
1712
            }
1713
          }else{
1714
101307
            Debug("qcf-match-debug") << "       Match " << index << " is ground term" << std::endl;
1715
101307
            Assert(d_qni_gterm.find(index) != d_qni_gterm.end());
1716
101307
            val = d_qni_gterm[index];
1717
101307
            Assert(!val.isNull());
1718
          }
1719
1476583
          if( !val.isNull() ){
1720
1931042
            Node valr = p->getRepresentative(val);
1721
            //constrained by val
1722
            std::map<TNode, TNodeTrie>::iterator it =
1723
965521
                d_qn[index]->d_data.find(valr);
1724
965521
            if( it!=d_qn[index]->d_data.end() ){
1725
434784
              Debug("qcf-match-debug") << "       Match" << std::endl;
1726
434784
              d_qni.push_back( it );
1727
434784
              if( d_qn.size()<d_qni_size ){
1728
395873
                d_qn.push_back( &it->second );
1729
              }
1730
            }else{
1731
530737
              Debug("qcf-match-debug") << "       Failed to match" << std::endl;
1732
530737
              d_qn.pop_back();
1733
            }
1734
          }
1735
        }else{
1736
1596754
          Assert(d_qn.size() == d_qni.size());
1737
1596754
          int index = d_qni.size()-1;
1738
          //increment if binding this variable
1739
1596754
          bool success = false;
1740
1596754
          std::map< int, int >::iterator itb = d_qni_bound.find( index );
1741
1596754
          if( itb!=d_qni_bound.end() ){
1742
1164229
            d_qni[index]++;
1743
1164229
            if( d_qni[index]!=d_qn[index]->d_data.end() ){
1744
655018
              success = true;
1745
655018
              if( qi->setMatch( p, itb->second, d_qni[index]->first, true, true ) ){
1746
628060
                Debug("qcf-match-debug") << "       Bind next variable" << std::endl;
1747
628060
                if( d_qn.size()<d_qni_size ){
1748
575193
                  d_qn.push_back( &d_qni[index]->second );
1749
                }
1750
              }else{
1751
26958
                Debug("qcf-match-debug") << "       Bind next variable, currently fail" << std::endl;
1752
26958
                invalidMatch = true;
1753
              }
1754
            }else{
1755
509211
              qi->unsetMatch( p, itb->second );
1756
509211
              qi->d_match_term[ itb->second ] = TNode::null();
1757
509211
              Debug("qcf-match-debug") << "       Bind next variable, no more variables to bind" << std::endl;
1758
            }
1759
          }else{
1760
            //TODO : if it equal to something else, also try that
1761
          }
1762
          //if not incrementing, move to next
1763
1596754
          if( !success ){
1764
941736
            d_qn.pop_back();
1765
941736
            d_qni.pop_back();
1766
          }
1767
        }
1768
3073337
      }while( ( !d_qn.empty() && d_qni.size()!=d_qni_size ) || invalidMatch );
1769
598777
      if( d_qni.size()==d_qni_size ){
1770
        //Assert( !d_qni[d_qni.size()-1]->second.d_data.empty() );
1771
        //Debug("qcf-match-debug") << "       We matched " << d_qni[d_qni.size()-1]->second.d_children.begin()->first << std::endl;
1772
328520
        Assert(!d_qni[d_qni.size() - 1]->second.d_data.empty());
1773
657040
        TNode t = d_qni[d_qni.size()-1]->second.d_data.begin()->first;
1774
328520
        Debug("qcf-match-debug") << "       " << d_n << " matched " << t << std::endl;
1775
328520
        qi->d_match_term[d_qni_var_num[0]] = t;
1776
        //set the match terms
1777
970308
        for( std::map< int, int >::iterator it = d_qni_bound.begin(); it != d_qni_bound.end(); ++it ){
1778
641788
          Debug("qcf-match-debug") << "       position " << it->first << " bounded " << it->second << " / " << qi->d_q[0].getNumChildren() << std::endl;
1779
          //if( it->second<(int)qi->d_q[0].getNumChildren() ){   //if it is an actual variable, we are interested in knowing the actual term
1780
641788
          if( it->first>0 ){
1781
496662
            Assert(!qi->d_match[it->second].isNull());
1782
496662
            Assert(p->areEqual(t[it->first - 1], qi->d_match[it->second]));
1783
496662
            qi->d_match_term[it->second] = t[it->first-1];
1784
          }
1785
          //}
1786
        }
1787
      }
1788
    }
1789
  }
1790
768752
  return !d_qn.empty();
1791
}
1792
1793
2558756
void MatchGen::debugPrintType( const char * c, short typ, bool isTrace ) {
1794
2558756
  if( isTrace ){
1795
60825
    switch( typ ){
1796
3551
    case typ_invalid: Trace(c) << "invalid";break;
1797
34
    case typ_ground: Trace(c) << "ground";break;
1798
10563
    case typ_eq: Trace(c) << "eq";break;
1799
7228
    case typ_pred: Trace(c) << "pred";break;
1800
8583
    case typ_formula: Trace(c) << "formula";break;
1801
30543
    case typ_var: Trace(c) << "var";break;
1802
89
    case typ_bool_var: Trace(c) << "bool_var";break;
1803
    }
1804
  }else{
1805
2497931
    switch( typ ){
1806
    case typ_invalid: Debug(c) << "invalid";break;
1807
158
    case typ_ground: Debug(c) << "ground";break;
1808
532915
    case typ_eq: Debug(c) << "eq";break;
1809
340496
    case typ_pred: Debug(c) << "pred";break;
1810
215547
    case typ_formula: Debug(c) << "formula";break;
1811
1403849
    case typ_var: Debug(c) << "var";break;
1812
3020
    case typ_bool_var: Debug(c) << "bool_var";break;
1813
    }
1814
  }
1815
2558756
}
1816
1817
2412
void MatchGen::setInvalid() {
1818
2412
  d_type = typ_invalid;
1819
2412
  d_children.clear();
1820
2412
}
1821
1822
100761
bool MatchGen::isHandledBoolConnective( TNode n ) {
1823
100761
  return TermUtil::isBoolConnectiveTerm( n ) && n.getKind()!=SEP_STAR;
1824
}
1825
1826
706179
bool MatchGen::isHandledUfTerm( TNode n ) {
1827
  //return n.getKind()==APPLY_UF || n.getKind()==STORE || n.getKind()==SELECT ||
1828
  //       n.getKind()==APPLY_CONSTRUCTOR || n.getKind()==APPLY_SELECTOR_TOTAL || n.getKind()==APPLY_TESTER;
1829
  //TODO : treat APPLY_TESTER as a T-constraint instead of matching (currently leads to overabundance of instantiations)
1830
  //return inst::Trigger::isAtomicTriggerKind( n.getKind() ) && ( !options::qcfTConstraint() || n.getKind()!=APPLY_TESTER );
1831
706179
  return inst::TriggerTermInfo::isAtomicTriggerKind(n.getKind());
1832
}
1833
1834
306549
Node MatchGen::getMatchOperator( QuantConflictFind * p, Node n ) {
1835
306549
  if( isHandledUfTerm( n ) ){
1836
306549
    return p->getTermDatabase()->getMatchOperator( n );
1837
  }else{
1838
    return Node::null();
1839
  }
1840
}
1841
1842
bool MatchGen::isHandled( TNode n ) {
1843
  if (n.getKind() != BOUND_VARIABLE && expr::hasBoundVar(n))
1844
  {
1845
    if( !isHandledBoolConnective( n ) && !isHandledUfTerm( n ) && n.getKind()!=EQUAL && n.getKind()!=ITE ){
1846
      return false;
1847
    }
1848
    for( unsigned i=0; i<n.getNumChildren(); i++ ){
1849
      if( !isHandled( n[i] ) ){
1850
        return false;
1851
      }
1852
    }
1853
  }
1854
  return true;
1855
}
1856
1857
3050
QuantConflictFind::QuantConflictFind(Env& env,
1858
                                     QuantifiersState& qs,
1859
                                     QuantifiersInferenceManager& qim,
1860
                                     QuantifiersRegistry& qr,
1861
3050
                                     TermRegistry& tr)
1862
    : QuantifiersModule(env, qs, qim, qr, tr),
1863
      d_conflict(context(), false),
1864
      d_true(NodeManager::currentNM()->mkConst<bool>(true)),
1865
      d_false(NodeManager::currentNM()->mkConst<bool>(false)),
1866
3050
      d_effort(EFFORT_INVALID)
1867
{
1868
3050
}
1869
1870
//-------------------------------------------------- registration
1871
1872
9538
void QuantConflictFind::registerQuantifier( Node q ) {
1873
9538
  if (d_qreg.hasOwnership(q, this))
1874
  {
1875
8633
    d_quants.push_back( q );
1876
8633
    d_quant_id[q] = d_quants.size();
1877
8633
    if( Trace.isOn("qcf-qregister") ){
1878
      Trace("qcf-qregister") << "Register ";
1879
      debugPrintQuant( "qcf-qregister", q );
1880
      Trace("qcf-qregister") << " : " << q << std::endl;
1881
    }
1882
    //make QcfNode structure
1883
8633
    Trace("qcf-qregister") << "- Get relevant equality/disequality pairs, calculate flattening..." << std::endl;
1884
8633
    d_qinfo[q].initialize( this, q, q[1] );
1885
1886
    //debug print
1887
8633
    if( Trace.isOn("qcf-qregister") ){
1888
      Trace("qcf-qregister") << "- Flattened structure is :" << std::endl;
1889
      Trace("qcf-qregister") << "    ";
1890
      debugPrintQuantBody( "qcf-qregister", q, q[1] );
1891
      Trace("qcf-qregister") << std::endl;
1892
      if( d_qinfo[q].d_vars.size()>q[0].getNumChildren() ){
1893
        Trace("qcf-qregister") << "  with additional constraints : " << std::endl;
1894
        for( unsigned j=q[0].getNumChildren(); j<d_qinfo[q].d_vars.size(); j++ ){
1895
          Trace("qcf-qregister") << "    ?x" << j << " = ";
1896
          debugPrintQuantBody( "qcf-qregister", q, d_qinfo[q].d_vars[j], false );
1897
          Trace("qcf-qregister") << std::endl;
1898
        }
1899
      }
1900
      Trace("qcf-qregister") << "Done registering quantifier." << std::endl;
1901
    }
1902
  }
1903
9538
}
1904
1905
258
bool QuantConflictFind::areMatchEqual( TNode n1, TNode n2 ) {
1906
  //if( d_effort==QuantConflictFind::effort_mc ){
1907
  //  return n1==n2 || !areDisequal( n1, n2 );
1908
  //}else{
1909
258
  return n1==n2;
1910
  //}
1911
}
1912
1913
13
bool QuantConflictFind::areMatchDisequal( TNode n1, TNode n2 ) {
1914
  // if( d_effort==QuantConflictFind::Effort::Conflict ){
1915
  //  return areDisequal( n1, n2 );
1916
  //}else{
1917
13
  return n1!=n2;
1918
  //}
1919
}
1920
1921
//-------------------------------------------------- check function
1922
1923
21282
bool QuantConflictFind::needsCheck( Theory::Effort level ) {
1924
21282
  bool performCheck = false;
1925
21282
  if( options::quantConflictFind() && !d_conflict ){
1926
21278
    if( level==Theory::EFFORT_LAST_CALL ){
1927
2992
      performCheck = options::qcfWhenMode() == options::QcfWhenMode::LAST_CALL;
1928
18286
    }else if( level==Theory::EFFORT_FULL ){
1929
10717
      performCheck = options::qcfWhenMode() == options::QcfWhenMode::DEFAULT;
1930
7569
    }else if( level==Theory::EFFORT_STANDARD ){
1931
7569
      performCheck = options::qcfWhenMode() == options::QcfWhenMode::STD;
1932
    }
1933
  }
1934
21282
  return performCheck;
1935
}
1936
1937
13711
void QuantConflictFind::reset_round( Theory::Effort level ) {
1938
13711
  Trace("qcf-check") << "QuantConflictFind::reset_round" << std::endl;
1939
13711
  Trace("qcf-check") << "Compute relevant equivalence classes..." << std::endl;
1940
13711
  d_eqcs.clear();
1941
1942
13711
  eq::EqClassesIterator eqcs_i = eq::EqClassesIterator(getEqualityEngine());
1943
13711
  TermDb* tdb = getTermDatabase();
1944
1325657
  while (!eqcs_i.isFinished())
1945
  {
1946
1311946
    Node r = (*eqcs_i);
1947
655973
    if (tdb->hasTermCurrent(r))
1948
    {
1949
1311946
      TypeNode rtn = r.getType();
1950
655973
      if (!options::cegqi() || !TermUtil::hasInstConstAttr(r))
1951
      {
1952
638589
        d_eqcs[rtn].push_back(r);
1953
      }
1954
    }
1955
655973
    ++eqcs_i;
1956
  }
1957
13711
}
1958
1959
35176
void QuantConflictFind::setIrrelevantFunction( TNode f ) {
1960
35176
  if( d_irr_func.find( f )==d_irr_func.end() ){
1961
6881
    d_irr_func[f] = true;
1962
6881
    std::map< TNode, std::vector< Node > >::iterator it = d_func_rel_dom.find( f );
1963
6881
    if( it != d_func_rel_dom.end()){
1964
28005
      for( unsigned j=0; j<it->second.size(); j++ ){
1965
22677
        d_irr_quant[it->second[j]] = true;
1966
      }
1967
    }
1968
  }
1969
35176
}
1970
1971
namespace {
1972
1973
// Returns the beginning of a range of efforts. The range can be iterated
1974
// through as unsigned using operator++.
1975
10717
inline QuantConflictFind::Effort QcfEffortStart() {
1976
10717
  return QuantConflictFind::EFFORT_CONFLICT;
1977
}
1978
1979
// Returns the beginning of a range of efforts. The value returned is included
1980
// in the range.
1981
10717
inline QuantConflictFind::Effort QcfEffortEnd() {
1982
10717
  return options::qcfMode() == options::QcfMode::PROP_EQ
1983
10717
             ? QuantConflictFind::EFFORT_PROP_EQ
1984
10717
             : QuantConflictFind::EFFORT_CONFLICT;
1985
}
1986
1987
}  // namespace
1988
1989
/** check */
1990
40873
void QuantConflictFind::check(Theory::Effort level, QEffort quant_e)
1991
{
1992
51590
  CodeTimer codeTimer(d_qstate.getStats().d_qcf_time);
1993
40873
  if (quant_e != QEFFORT_CONFLICT)
1994
  {
1995
30156
    return;
1996
  }
1997
10717
  Trace("qcf-check") << "QCF : check : " << level << std::endl;
1998
10717
  if (d_conflict)
1999
  {
2000
    Trace("qcf-check2") << "QCF : finished check : already in conflict."
2001
                        << std::endl;
2002
    if (level >= Theory::EFFORT_FULL)
2003
    {
2004
      Trace("qcf-warn") << "ALREADY IN CONFLICT? " << level << std::endl;
2005
    }
2006
    return;
2007
  }
2008
10717
  unsigned addedLemmas = 0;
2009
10717
  ++(d_statistics.d_inst_rounds);
2010
10717
  double clSet = 0;
2011
10717
  int prevEt = 0;
2012
10717
  if (Trace.isOn("qcf-engine"))
2013
  {
2014
    prevEt = d_statistics.d_entailment_checks.get();
2015
    clSet = double(clock()) / double(CLOCKS_PER_SEC);
2016
    Trace("qcf-engine") << "---Conflict Find Engine Round, effort = " << level
2017
                        << "---" << std::endl;
2018
  }
2019
2020
  // reset the round-specific information
2021
10717
  d_irr_func.clear();
2022
10717
  d_irr_quant.clear();
2023
2024
10717
  if (Trace.isOn("qcf-debug"))
2025
  {
2026
    Trace("qcf-debug") << std::endl;
2027
    debugPrint("qcf-debug");
2028
    Trace("qcf-debug") << std::endl;
2029
  }
2030
10717
  bool isConflict = false;
2031
10717
  FirstOrderModel* fm = d_treg.getModel();
2032
10717
  unsigned nquant = fm->getNumAssertedQuantifiers();
2033
  // for each effort level (find conflict, find propagating)
2034
31262
  for (unsigned e = QcfEffortStart(), end = QcfEffortEnd(); e <= end; ++e)
2035
  {
2036
    // set the effort (data member for convienence of access)
2037
21083
    d_effort = static_cast<Effort>(e);
2038
42166
    Trace("qcf-check") << "Checking quantified formulas at effort " << e
2039
21083
                       << "..." << std::endl;
2040
    // for each quantified formula
2041
175307
    for (unsigned i = 0; i < nquant; i++)
2042
    {
2043
308799
      Node q = fm->getAssertedQuantifier(i, true);
2044
463725
      if (d_qreg.hasOwnership(q, this)
2045
297938
          && d_irr_quant.find(q) == d_irr_quant.end()
2046
580716
          && fm->isQuantifierActive(q))
2047
      {
2048
        // check this quantified formula
2049
116939
        checkQuantifiedFormula(q, isConflict, addedLemmas);
2050
116939
        if (d_conflict || d_qstate.isInConflict())
2051
        {
2052
351
          break;
2053
        }
2054
      }
2055
    }
2056
    // We are done if we added a lemma, or discovered a conflict in another
2057
    // way. An example of the latter case is when two disequal congruent terms
2058
    // are discovered during term indexing.
2059
21083
    if (addedLemmas > 0 || d_qstate.isInConflict())
2060
    {
2061
538
      break;
2062
    }
2063
  }
2064
10717
  if (isConflict)
2065
  {
2066
    d_conflict.set(true);
2067
  }
2068
10717
  if (Trace.isOn("qcf-engine"))
2069
  {
2070
    double clSet2 = double(clock()) / double(CLOCKS_PER_SEC);
2071
    Trace("qcf-engine") << "Finished conflict find engine, time = "
2072
                        << (clSet2 - clSet);
2073
    if (addedLemmas > 0)
2074
    {
2075
      Trace("qcf-engine") << ", effort = "
2076
                          << (d_effort == EFFORT_CONFLICT
2077
                                  ? "conflict"
2078
                                  : (d_effort == EFFORT_PROP_EQ ? "prop_eq"
2079
                                                                : "mc"));
2080
      Trace("qcf-engine") << ", addedLemmas = " << addedLemmas;
2081
    }
2082
    Trace("qcf-engine") << std::endl;
2083
    int currEt = d_statistics.d_entailment_checks.get();
2084
    if (currEt != prevEt)
2085
    {
2086
      Trace("qcf-engine") << "  Entailment checks = " << (currEt - prevEt)
2087
                          << std::endl;
2088
    }
2089
  }
2090
10717
  Trace("qcf-check2") << "QCF : finished check : " << level << std::endl;
2091
}
2092
2093
116939
void QuantConflictFind::checkQuantifiedFormula(Node q,
2094
                                               bool& isConflict,
2095
                                               unsigned& addedLemmas)
2096
{
2097
116939
  QuantInfo* qi = &d_qinfo[q];
2098
116939
  Assert(d_qinfo.find(q) != d_qinfo.end());
2099
116939
  if (!qi->matchGeneratorIsValid())
2100
  {
2101
    // quantified formula is not properly set up for matching
2102
66432
    return;
2103
  }
2104
50507
  if (Trace.isOn("qcf-check"))
2105
  {
2106
    Trace("qcf-check") << "Check quantified formula ";
2107
    debugPrintQuant("qcf-check", q);
2108
    Trace("qcf-check") << " : " << q << "..." << std::endl;
2109
  }
2110
2111
50507
  Trace("qcf-check-debug") << "Reset round..." << std::endl;
2112
50507
  if (!qi->reset_round(this))
2113
  {
2114
    // it is typically the case that another conflict (e.g. in the term
2115
    // database) was discovered if we fail here.
2116
    return;
2117
  }
2118
  // try to make a matches making the body false or propagating
2119
50507
  Trace("qcf-check-debug") << "Get next match..." << std::endl;
2120
50507
  Instantiate* qinst = d_qim.getInstantiate();
2121
217603
  while (qi->getNextMatch(this))
2122
  {
2123
84049
    if (d_qstate.isInConflict())
2124
    {
2125
5
      Trace("qcf-check") << "   ... Quantifiers engine discovered conflict, ";
2126
10
      Trace("qcf-check") << "probably related to disequal congruent terms in "
2127
5
                            "master equality engine"
2128
5
                         << std::endl;
2129
506
      return;
2130
    }
2131
84044
    if (Trace.isOn("qcf-inst"))
2132
    {
2133
      Trace("qcf-inst") << "*** Produced match at effort " << d_effort << " : "
2134
                        << std::endl;
2135
      qi->debugPrintMatch("qcf-inst");
2136
      Trace("qcf-inst") << std::endl;
2137
    }
2138
    // check whether internal match constraints are satisfied
2139
102206
    if (qi->isMatchSpurious(this))
2140
    {
2141
36324
      Trace("qcf-inst") << "   ... Spurious (match is inconsistent)"
2142
18162
                        << std::endl;
2143
36395
      continue;
2144
    }
2145
    // check whether match can be completed
2146
131197
    std::vector<int> assigned;
2147
65953
    if (!qi->completeMatch(this, assigned))
2148
    {
2149
142
      Trace("qcf-inst") << "   ... Spurious (cannot assign unassigned vars)"
2150
71
                        << std::endl;
2151
71
      continue;
2152
    }
2153
    // check whether the match is spurious according to (T-)entailment checks
2154
131126
    std::vector<Node> terms;
2155
65811
    qi->getMatch(terms);
2156
65811
    bool tcs = qi->isTConstraintSpurious(this, terms);
2157
65811
    if (tcs)
2158
    {
2159
129586
      Trace("qcf-inst") << "   ... Spurious (match is T-inconsistent)"
2160
64793
                        << std::endl;
2161
    }
2162
    else
2163
    {
2164
      // otherwise, we have a conflict/propagating instance
2165
      // for debugging
2166
1018
      if (Debug.isOn("qcf-check-inst"))
2167
      {
2168
        Node inst = qinst->getInstantiation(q, terms);
2169
        Debug("qcf-check-inst")
2170
            << "Check instantiation " << inst << "..." << std::endl;
2171
        Assert(!getTermDatabase()->isEntailed(inst, true));
2172
        Assert(getTermDatabase()->isEntailed(inst, false)
2173
               || d_effort > EFFORT_CONFLICT);
2174
      }
2175
      // Process the lemma: either add an instantiation or specific lemmas
2176
      // constructed during the isTConstraintSpurious call, or both.
2177
2036
      InferenceId id = (d_effort == EFFORT_CONFLICT
2178
1018
                            ? InferenceId::QUANTIFIERS_INST_CBQI_CONFLICT
2179
                            : InferenceId::QUANTIFIERS_INST_CBQI_PROP);
2180
1018
      if (!qinst->addInstantiation(q, terms, id))
2181
      {
2182
151
        Trace("qcf-inst") << "   ... Failed to add instantiation" << std::endl;
2183
        // This should only happen if the algorithm generates the same
2184
        // propagating instance twice this round. In this case, return
2185
        // to avoid exponential behavior.
2186
151
        return;
2187
      }
2188
867
      Trace("qcf-check") << "   ... Added instantiation" << std::endl;
2189
867
      if (Trace.isOn("qcf-inst"))
2190
      {
2191
        Trace("qcf-inst") << "*** Was from effort " << d_effort << " : "
2192
                          << std::endl;
2193
        qi->debugPrintMatch("qcf-inst");
2194
        Trace("qcf-inst") << std::endl;
2195
      }
2196
867
      ++addedLemmas;
2197
867
      if (d_effort == EFFORT_CONFLICT)
2198
      {
2199
        // mark relevant: this ensures that quantified formula q is
2200
        // checked first on the next round. This is an optimization to
2201
        // ensure that quantified formulas that are more likely to have
2202
        // conflicting instances are checked earlier.
2203
345
        d_treg.getModel()->markRelevant(q);
2204
345
        if (options::qcfAllConflict())
2205
        {
2206
          isConflict = true;
2207
        }
2208
        else
2209
        {
2210
345
          d_conflict.set(true);
2211
        }
2212
345
        return;
2213
      }
2214
522
      else if (d_effort == EFFORT_PROP_EQ)
2215
      {
2216
522
        d_treg.getModel()->markRelevant(q);
2217
      }
2218
    }
2219
    // clean up assigned
2220
65315
    qi->revertMatch(this, assigned);
2221
65315
    d_tempCache.clear();
2222
  }
2223
50006
  Trace("qcf-check") << "Done, conflict = " << d_conflict << std::endl;
2224
}
2225
2226
//-------------------------------------------------- debugging
2227
2228
void QuantConflictFind::debugPrint( const char * c ) {
2229
  //print the equivalance classes
2230
  Trace(c) << "----------EQ classes" << std::endl;
2231
  eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( getEqualityEngine() );
2232
  while( !eqcs_i.isFinished() ){
2233
    Node n = (*eqcs_i);
2234
    //if( !n.getType().isInteger() ){
2235
    Trace(c) << "  - " << n << " : {";
2236
    eq::EqClassIterator eqc_i = eq::EqClassIterator( n, getEqualityEngine() );
2237
    bool pr = false;
2238
    while( !eqc_i.isFinished() ){
2239
      Node nn = (*eqc_i);
2240
      if( nn.getKind()!=EQUAL && nn!=n ){
2241
        Trace(c) << (pr ? "," : "" ) << " " << nn;
2242
        pr = true;
2243
      }
2244
      ++eqc_i;
2245
    }
2246
    Trace(c) << (pr ? " " : "" ) << "}" << std::endl;
2247
    ++eqcs_i;
2248
  }
2249
}
2250
2251
void QuantConflictFind::debugPrintQuant( const char * c, Node q ) {
2252
  Trace(c) << "Q" << d_quant_id[q];
2253
}
2254
2255
void QuantConflictFind::debugPrintQuantBody( const char * c, Node q, Node n, bool doVarNum ) {
2256
  if( n.getNumChildren()==0 ){
2257
    Trace(c) << n;
2258
  }else if( doVarNum && d_qinfo[q].d_var_num.find( n )!=d_qinfo[q].d_var_num.end() ){
2259
    Trace(c) << "?x" << d_qinfo[q].d_var_num[n];
2260
  }else{
2261
    Trace(c) << "(";
2262
    if( n.getKind()==APPLY_UF ){
2263
      Trace(c) << n.getOperator();
2264
    }else{
2265
      Trace(c) << n.getKind();
2266
    }
2267
    for( unsigned i=0; i<n.getNumChildren(); i++ ){
2268
      Trace(c) << " ";
2269
      debugPrintQuantBody( c, q, n[i] );
2270
    }
2271
    Trace(c) << ")";
2272
  }
2273
}
2274
2275
3050
QuantConflictFind::Statistics::Statistics()
2276
    : d_inst_rounds(
2277
6100
        smtStatisticsRegistry().registerInt("QuantConflictFind::Inst_Rounds")),
2278
3050
      d_entailment_checks(smtStatisticsRegistry().registerInt(
2279
6100
          "QuantConflictFind::Entailment_Checks"))
2280
{
2281
3050
}
2282
2283
2
TNode QuantConflictFind::getZero( Kind k ) {
2284
2
  std::map< Kind, Node >::iterator it = d_zero.find( k );
2285
2
  if( it==d_zero.end() ){
2286
4
    Node nn;
2287
2
    if( k==PLUS ){
2288
1
      nn = NodeManager::currentNM()->mkConst( Rational(0) );
2289
    }
2290
2
    d_zero[k] = nn;
2291
2
    return nn;
2292
  }else{
2293
    return it->second;
2294
  }
2295
}
2296
2297
std::ostream& operator<<(std::ostream& os, const QuantConflictFind::Effort& e) {
2298
  switch (e) {
2299
    case QuantConflictFind::EFFORT_INVALID:
2300
      os << "Invalid";
2301
      break;
2302
    case QuantConflictFind::EFFORT_CONFLICT:
2303
      os << "Conflict";
2304
      break;
2305
    case QuantConflictFind::EFFORT_PROP_EQ:
2306
      os << "PropEq";
2307
      break;
2308
  }
2309
  return os;
2310
}
2311
2312
623
bool QuantConflictFind::isPropagatingInstance(Node n) const
2313
{
2314
1246
  std::unordered_set<TNode> visited;
2315
1246
  std::vector<TNode> visit;
2316
1246
  TNode cur;
2317
623
  visit.push_back(n);
2318
1322
  do
2319
  {
2320
1945
    cur = visit.back();
2321
1945
    visit.pop_back();
2322
1945
    if (visited.find(cur) == visited.end())
2323
    {
2324
1905
      visited.insert(cur);
2325
1905
      Kind ck = cur.getKind();
2326
1905
      if (ck == FORALL)
2327
      {
2328
        // do nothing
2329
      }
2330
1859
      else if (TermUtil::isBoolConnective(ck))
2331
      {
2332
2010
        for (TNode cc : cur)
2333
        {
2334
1322
          visit.push_back(cc);
2335
        }
2336
      }
2337
1171
      else if (!getEqualityEngine()->hasTerm(cur))
2338
      {
2339
        Trace("qcf-instance-check-debug")
2340
            << "...not propagating instance because of " << cur << " " << ck
2341
            << std::endl;
2342
        return false;
2343
      }
2344
    }
2345
1945
  } while (!visit.empty());
2346
623
  return true;
2347
}
2348
2349
}  // namespace quantifiers
2350
}  // namespace theory
2351
22746
}  // namespace cvc5