GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/quant_conflict_find.cpp Lines: 1159 1397 83.0 %
Date: 2021-09-17 Branches: 2464 5417 45.5 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Tim King, Andres Noetzli
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8
 * in the top-level source directory and their institutional affiliations.
9
 * All rights reserved.  See the file COPYING in the top-level source
10
 * directory for licensing information.
11
 * ****************************************************************************
12
 *
13
 * Implements conflict-based instantiation (Reynolds et al FMCAD 2014).
14
 */
15
16
#include "theory/quantifiers/quant_conflict_find.h"
17
18
#include "base/configuration.h"
19
#include "expr/node_algorithm.h"
20
#include "options/quantifiers_options.h"
21
#include "options/theory_options.h"
22
#include "options/uf_options.h"
23
#include "smt/smt_statistics_registry.h"
24
#include "theory/quantifiers/ematching/trigger_term_info.h"
25
#include "theory/quantifiers/first_order_model.h"
26
#include "theory/quantifiers/instantiate.h"
27
#include "theory/quantifiers/quant_util.h"
28
#include "theory/quantifiers/term_database.h"
29
#include "theory/quantifiers/term_util.h"
30
#include "theory/rewriter.h"
31
32
using namespace cvc5::kind;
33
using namespace std;
34
35
namespace cvc5 {
36
namespace theory {
37
namespace quantifiers {
38
39
22094
QuantInfo::QuantInfo()
40
22094
    : d_unassigned_nvar(0), d_una_index(0), d_parent(nullptr), d_mg(nullptr)
41
{
42
22094
}
43
44
44188
QuantInfo::~QuantInfo() {
45
22094
  delete d_mg;
46
102634
  for(std::map< int, MatchGen * >::iterator i = d_var_mg.begin(),
47
22094
          iend=d_var_mg.end(); i != iend; ++i) {
48
80540
    MatchGen* currentMatchGenerator = (*i).second;
49
80540
    delete currentMatchGenerator;
50
  }
51
22094
  d_var_mg.clear();
52
22094
}
53
54
93294
QuantifiersInferenceManager& QuantInfo::getInferenceManager()
55
{
56
93294
  Assert(d_parent != nullptr);
57
93294
  return d_parent->getInferenceManager();
58
}
59
60
22094
void QuantInfo::initialize( QuantConflictFind * p, Node q, Node qn ) {
61
22094
  d_parent = p;
62
22094
  d_q = q;
63
22094
  d_extra_var.clear();
64
74418
  for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
65
52324
    d_match.push_back( TNode::null() );
66
52324
    d_match_term.push_back( TNode::null() );
67
  }
68
69
  //register the variables
70
74418
  for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
71
52324
    d_var_num[q[0][i]] = i;
72
52324
    d_vars.push_back( q[0][i] );
73
52324
    d_var_types.push_back( q[0][i].getType() );
74
  }
75
76
22094
  registerNode( qn, true, true );
77
78
79
22094
  Trace("qcf-qregister") << "- Make match gen structure..." << std::endl;
80
22094
  d_mg = new MatchGen( this, qn );
81
82
22094
  if( d_mg->isValid() ){
83
    /*
84
    for( unsigned j=0; j<q[0].getNumChildren(); j++ ){
85
      if( d_inMatchConstraint.find( q[0][j] )==d_inMatchConstraint.end() ){
86
        Trace("qcf-invalid") << "QCF invalid : variable " << q[0][j] << " does not exist in a matching constraint." << std::endl;
87
        d_mg->setInvalid();
88
        break;
89
      }
90
    }
91
    */
92
103195
    for( unsigned j=q[0].getNumChildren(); j<d_vars.size(); j++ ){
93
85904
      if( d_vars[j].getKind()!=BOUND_VARIABLE ){
94
80540
        d_var_mg[j] = NULL;
95
80540
        bool is_tsym = false;
96
80540
        if( !MatchGen::isHandledUfTerm( d_vars[j] ) && d_vars[j].getKind()!=ITE ){
97
832
          is_tsym = true;
98
832
          d_tsym_vars.push_back( j );
99
        }
100
80540
        if( !is_tsym || options::qcfTConstraint() ){
101
80087
          d_var_mg[j] = new MatchGen( this, d_vars[j], true );
102
        }
103
80540
        if( !d_var_mg[j] || !d_var_mg[j]->isValid() ){
104
1567
          Trace("qcf-invalid") << "QCF invalid : cannot match for " << d_vars[j] << std::endl;
105
1567
          d_mg->setInvalid();
106
1567
          break;
107
        }else{
108
157946
          std::vector< int > bvars;
109
78973
          d_var_mg[j]->determineVariableOrder( this, bvars );
110
        }
111
      }
112
    }
113
18858
    if( d_mg->isValid() ){
114
34582
      std::vector< int > bvars;
115
17291
      d_mg->determineVariableOrder( this, bvars );
116
    }
117
  }else{
118
3236
    Trace("qcf-invalid") << "QCF invalid : body of formula cannot be processed." << std::endl;
119
  }
120
22094
  Trace("qcf-qregister-summary") << "QCF register : " << ( d_mg->isValid() ? "VALID " : "INVALID" ) << " : " << q << std::endl;
121
122
22094
  if( d_mg->isValid() && options::qcfEagerCheckRd() ){
123
    //optimization : record variable argument positions for terms that must be matched
124
34582
    std::vector< TNode > vars;
125
    //TODO: revisit this, makes QCF faster, but misses conflicts due to caring about paths that may not be relevant (starExec jobs 14136/14137)
126
17291
    if( options::qcfSkipRd() ){
127
      for( unsigned j=q[0].getNumChildren(); j<d_vars.size(); j++ ){
128
        vars.push_back( d_vars[j] );
129
      }
130
    }else{
131
      //get all variables that are always relevant
132
34582
      std::map< TNode, bool > visited;
133
17291
      getPropagateVars( p, vars, q[1], false, visited );
134
    }
135
98774
    for( unsigned j=0; j<vars.size(); j++ ){
136
162966
      Node v = vars[j];
137
162966
      TNode f = p->getTermDatabase()->getMatchOperator( v );
138
81483
      if( !f.isNull() ){
139
49225
        Trace("qcf-opt") << "Record variable argument positions in " << v << ", op=" << f << "..." << std::endl;
140
159963
        for( unsigned k=0; k<v.getNumChildren(); k++ ){
141
221476
          Node n = v[k];
142
110738
          std::map< TNode, int >::iterator itv = d_var_num.find( n );
143
110738
          if( itv!=d_var_num.end() ){
144
97311
            Trace("qcf-opt") << "  arg " << k << " is var #" << itv->second << std::endl;
145
97311
            if( std::find( d_var_rel_dom[itv->second][f].begin(), d_var_rel_dom[itv->second][f].end(), k )==d_var_rel_dom[itv->second][f].end() ){
146
92113
              d_var_rel_dom[itv->second][f].push_back( k );
147
            }
148
          }
149
        }
150
      }
151
    }
152
  }
153
22094
}
154
155
207971
void QuantInfo::getPropagateVars( QuantConflictFind * p, std::vector< TNode >& vars, TNode n, bool pol, std::map< TNode, bool >& visited ){
156
207971
  std::map< TNode, bool >::iterator itv = visited.find( n );
157
207971
  if( itv==visited.end() ){
158
151511
    visited[n] = true;
159
151511
    bool rec = true;
160
151511
    bool newPol = pol;
161
151511
    if( d_var_num.find( n )!=d_var_num.end() ){
162
81483
      Assert(std::find(vars.begin(), vars.end(), n) == vars.end());
163
81483
      vars.push_back( n );
164
162966
      TNode f = p->getTermDatabase()->getMatchOperator( n );
165
81483
      if( !f.isNull() ){
166
49225
        if( std::find( p->d_func_rel_dom[f].begin(), p->d_func_rel_dom[f].end(), d_q )==p->d_func_rel_dom[f].end() ){
167
38241
          p->d_func_rel_dom[f].push_back( d_q );
168
        }
169
      }
170
70028
    }else if( MatchGen::isHandledBoolConnective( n ) ){
171
28383
      Assert(n.getKind() != IMPLIES);
172
28383
      QuantPhaseReq::getEntailPolarity( n, 0, true, pol, rec, newPol );
173
    }
174
151511
    Trace("qcf-opt-debug") << "getPropagateVars " << n << ", pol = " << pol << ", rec = " << rec << std::endl;
175
151511
    if( rec ){
176
336051
      for( unsigned i=0; i<n.getNumChildren(); i++ ){
177
190680
        getPropagateVars( p, vars, n[i], pol, visited );
178
      }
179
    }
180
  }
181
207971
}
182
183
1839331
bool QuantInfo::isBaseMatchComplete() {
184
1839331
  return d_vars_set.size()==(d_q[0].getNumChildren()+d_extra_var.size());
185
}
186
187
116737
void QuantInfo::registerNode( Node n, bool hasPol, bool pol, bool beneathQuant ) {
188
116737
  Trace("qcf-qregister-debug2") << "Register : " << n << std::endl;
189
116737
  if( n.getKind()==FORALL ){
190
4373
    registerNode( n[1], hasPol, pol, true );
191
  }else{
192
112364
    if( !MatchGen::isHandledBoolConnective( n ) ){
193
62024
      if (expr::hasBoundVar(n))
194
      {
195
        // literals
196
61906
        if (n.getKind() == EQUAL)
197
        {
198
101109
          for (unsigned i = 0; i < n.getNumChildren(); i++)
199
          {
200
67406
            flatten(n[i], beneathQuant);
201
          }
202
        }
203
28203
        else if (MatchGen::isHandledUfTerm(n))
204
        {
205
19119
          flatten(n, beneathQuant);
206
        }
207
9084
        else if (n.getKind() == ITE)
208
        {
209
3972
          for (unsigned i = 1; i <= 2; i++)
210
          {
211
2648
            flatten(n[i], beneathQuant);
212
          }
213
1324
          registerNode(n[0], false, pol, beneathQuant);
214
        }
215
7760
        else if (options::qcfTConstraint())
216
        {
217
          // a theory-specific predicate
218
1014
          for (unsigned i = 0; i < n.getNumChildren(); i++)
219
          {
220
676
            flatten(n[i], beneathQuant);
221
          }
222
        }
223
      }
224
    }else{
225
137962
      for( unsigned i=0; i<n.getNumChildren(); i++ ){
226
        bool newHasPol;
227
        bool newPol;
228
87622
        QuantPhaseReq::getPolarity( n, i, hasPol, pol, newHasPol, newPol );
229
        //QcfNode * qcfc = new QcfNode( d_c );
230
        //qcfc->d_parent = qcf;
231
        //qcf->d_child[i] = qcfc;
232
87622
        registerNode( n[i], newHasPol, newPol, beneathQuant );
233
      }
234
    }
235
  }
236
116737
}
237
238
289707
void QuantInfo::flatten( Node n, bool beneathQuant ) {
239
289707
  Trace("qcf-qregister-debug2") << "Flatten : " << n << std::endl;
240
289707
  if (expr::hasBoundVar(n))
241
  {
242
244042
    if( n.getKind()==BOUND_VARIABLE ){
243
126617
      d_inMatchConstraint[n] = true;
244
    }
245
244042
    if( d_var_num.find( n )==d_var_num.end() ){
246
104446
      Trace("qcf-qregister-debug2") << "Add FLATTEN VAR : " << n << std::endl;
247
104446
      d_var_num[n] = d_vars.size();
248
104446
      d_vars.push_back( n );
249
104446
      d_var_types.push_back( n.getType() );
250
104446
      d_match.push_back( TNode::null() );
251
104446
      d_match_term.push_back( TNode::null() );
252
104446
      if( n.getKind()==ITE ){
253
1324
        registerNode( n, false, false );
254
103122
      }else if( n.getKind()==BOUND_VARIABLE ){
255
6313
        d_extra_var.push_back( n );
256
      }else{
257
296667
        for( unsigned i=0; i<n.getNumChildren(); i++ ){
258
199858
          flatten( n[i], beneathQuant );
259
        }
260
      }
261
    }else{
262
139596
      Trace("qcf-qregister-debug2") << "...already processed" << std::endl;
263
    }
264
  }else{
265
45665
    Trace("qcf-qregister-debug2") << "...is ground." << std::endl;
266
  }
267
289707
}
268
269
270
119747
bool QuantInfo::reset_round( QuantConflictFind * p ) {
271
957922
  for( unsigned i=0; i<d_match.size(); i++ ){
272
838175
    d_match[i] = TNode::null();
273
838175
    d_match_term[i] = TNode::null();
274
  }
275
119747
  d_vars_set.clear();
276
119747
  d_curr_var_deq.clear();
277
119747
  d_tconstraints.clear();
278
279
119747
  d_mg->reset_round( p );
280
626017
  for( std::map< int, MatchGen * >::iterator it = d_var_mg.begin(); it != d_var_mg.end(); ++it ){
281
506270
    if (!it->second->reset_round(p))
282
    {
283
      return false;
284
    }
285
  }
286
  //now, reset for matching
287
119747
  d_mg->reset( p, false, this );
288
119747
  return true;
289
}
290
291
5873507
int QuantInfo::getCurrentRepVar( int v ) {
292
5873507
  if( v!=-1 && !d_match[v].isNull() ){
293
3120328
    int vn = getVarNum( d_match[v] );
294
3120328
    if( vn!=-1 ){
295
      //int vr = getCurrentRepVar( vn );
296
      //d_match[v] = d_vars[vr];
297
      //return vr;
298
21651
      return getCurrentRepVar( vn );
299
    }
300
  }
301
5851856
  return v;
302
}
303
304
3070164
TNode QuantInfo::getCurrentValue( TNode n ) {
305
3070164
  int v = getVarNum( n );
306
3070164
  if( v==-1 ){
307
1639414
    return n;
308
  }else{
309
1430750
    if( d_match[v].isNull() ){
310
1325616
      return n;
311
    }else{
312
105134
      Assert(getVarNum(d_match[v]) != v);
313
105134
      return getCurrentValue( d_match[v] );
314
    }
315
  }
316
}
317
318
4
TNode QuantInfo::getCurrentExpValue( TNode n ) {
319
4
  int v = getVarNum( n );
320
4
  if( v==-1 ){
321
    return n;
322
  }else{
323
4
    if( d_match[v].isNull() ){
324
      return n;
325
    }else{
326
4
      Assert(getVarNum(d_match[v]) != v);
327
4
      if( d_match_term[v].isNull() ){
328
4
        return getCurrentValue( d_match[v] );
329
      }else{
330
        return d_match_term[v];
331
      }
332
    }
333
  }
334
}
335
336
4844974
bool QuantInfo::getCurrentCanBeEqual( QuantConflictFind * p, int v, TNode n, bool chDiseq ) {
337
  //check disequalities
338
4844974
  std::map< int, std::map< TNode, int > >::iterator itd = d_curr_var_deq.find( v );
339
4844974
  if( itd!=d_curr_var_deq.end() ){
340
5799065
    for( std::map< TNode, int >::iterator it = itd->second.begin(); it != itd->second.end(); ++it ){
341
2644157
      Node cv = getCurrentValue( it->first );
342
1366081
      Debug("qcf-ccbe") << "compare " << cv << " " << n << std::endl;
343
1366081
      if( cv==n ){
344
64436
        return false;
345
1301645
      }else if( chDiseq && !isVar( n ) && !isVar( cv ) ){
346
        //they must actually be disequal if we are looking for conflicts
347
45244
        if( !p->areDisequal( n, cv ) ){
348
          //TODO : check for entailed disequal
349
350
23569
          return false;
351
        }
352
      }
353
    }
354
  }
355
4756969
  return true;
356
}
357
358
int QuantInfo::addConstraint( QuantConflictFind * p, int v, TNode n, bool polarity ) {
359
  v = getCurrentRepVar( v );
360
  int vn = getVarNum( n );
361
  vn = vn==-1 ? -1 : getCurrentRepVar( vn );
362
  n = getCurrentValue( n );
363
  return addConstraint( p, v, n, vn, polarity, false );
364
}
365
366
698471
int QuantInfo::addConstraint( QuantConflictFind * p, int v, TNode n, int vn, bool polarity, bool doRemove ) {
367
  //for handling equalities between variables, and disequalities involving variables
368
698471
  Debug("qcf-match-debug") << "- " << (doRemove ? "un" : "" ) << "constrain : " << v << " -> " << n << " (cv=" << getCurrentValue( n ) << ")";
369
698471
  Debug("qcf-match-debug") << ", (vn=" << vn << "), polarity = " << polarity << std::endl;
370
698471
  Assert(doRemove || n == getCurrentValue(n));
371
698471
  Assert(doRemove || v == getCurrentRepVar(v));
372
698471
  Assert(doRemove || vn == getCurrentRepVar(getVarNum(n)));
373
698471
  if( polarity ){
374
485923
    if( vn!=v ){
375
485923
      if( doRemove ){
376
242176
        if( vn!=-1 ){
377
          //if set to this in the opposite direction, clean up opposite instead
378
          //          std::map< int, TNode >::iterator itmn = d_match.find( vn );
379
17308
          if( d_match[vn]==d_vars[v] ){
380
            return addConstraint( p, vn, d_vars[v], v, true, true );
381
          }else{
382
            //unsetting variables equal
383
17308
            std::map< int, std::map< TNode, int > >::iterator itd = d_curr_var_deq.find( vn );
384
17308
            if( itd!=d_curr_var_deq.end() ){
385
              //remove disequalities owned by this
386
20100
              std::vector< TNode > remDeq;
387
10196
              for( std::map< TNode, int >::iterator it = itd->second.begin(); it != itd->second.end(); ++it ){
388
146
                if( it->second==v ){
389
146
                  remDeq.push_back( it->first );
390
                }
391
              }
392
10196
              for( unsigned i=0; i<remDeq.size(); i++ ){
393
146
                d_curr_var_deq[vn].erase( remDeq[i] );
394
              }
395
            }
396
          }
397
        }
398
242176
        unsetMatch( p, v );
399
242176
        return 1;
400
      }else{
401
        //std::map< int, TNode >::iterator itm = d_match.find( v );
402
243747
        bool isGroundRep = false;
403
243747
        bool isGround = false;
404
243747
        if( vn!=-1 ){
405
17519
          Debug("qcf-match-debug") << "  ...Variable bound to variable" << std::endl;
406
          //std::map< int, TNode >::iterator itmn = d_match.find( vn );
407
17519
          if( d_match[v].isNull() ){
408
            //setting variables equal
409
17519
            bool alreadySet = false;
410
17519
            if( !d_match[vn].isNull() ){
411
              alreadySet = true;
412
              Assert(!isVar(d_match[vn]));
413
            }
414
415
            //copy or check disequalities
416
17519
            std::map< int, std::map< TNode, int > >::iterator itd = d_curr_var_deq.find( v );
417
17519
            if( itd!=d_curr_var_deq.end() ){
418
12049
              for( std::map< TNode, int >::iterator it = itd->second.begin(); it != itd->second.end(); ++it ){
419
292
                Node dv = getCurrentValue( it->first );
420
146
                if( !alreadySet ){
421
146
                  if( d_curr_var_deq[vn].find( dv )==d_curr_var_deq[vn].end() ){
422
146
                    d_curr_var_deq[vn][dv] = v;
423
                  }
424
                }else{
425
                  if( !p->areMatchDisequal( d_match[vn], dv ) ){
426
                    Debug("qcf-match-debug") << "  -> fail, conflicting disequality" << std::endl;
427
                    return -1;
428
                  }
429
                }
430
              }
431
            }
432
17519
            if( alreadySet ){
433
              n = getCurrentValue( n );
434
            }
435
          }else{
436
            if( d_match[vn].isNull() ){
437
              Debug("qcf-match-debug") << " ...Reverse direction" << std::endl;
438
              //set the opposite direction
439
              return addConstraint( p, vn, d_vars[v], v, true, false );
440
            }else{
441
              Debug("qcf-match-debug") << "  -> Both variables bound, compare" << std::endl;
442
              //are they currently equal
443
              return p->areMatchEqual( d_match[v], d_match[vn] ) ? 0 : -1;
444
            }
445
          }
446
        }else{
447
226228
          Debug("qcf-match-debug") << "  ...Variable bound to ground" << std::endl;
448
226228
          if( d_match[v].isNull() ){
449
            //isGroundRep = true;   ??
450
226228
            isGround = true;
451
          }else{
452
            //compare ground values
453
            Debug("qcf-match-debug") << "  -> Ground value, compare " << d_match[v] << " "<< n << std::endl;
454
            return p->areMatchEqual( d_match[v], n ) ? 0 : -1;
455
          }
456
        }
457
243747
        if( setMatch( p, v, n, isGroundRep, isGround ) ){
458
243719
          Debug("qcf-match-debug") << "  -> success" << std::endl;
459
243719
          return 1;
460
        }else{
461
28
          Debug("qcf-match-debug") << "  -> fail, conflicting disequality" << std::endl;
462
28
          return -1;
463
        }
464
      }
465
    }else{
466
      Debug("qcf-match-debug") << "  -> redundant, variable identity" << std::endl;
467
      return 0;
468
    }
469
  }else{
470
212548
    if( vn==v ){
471
      Debug("qcf-match-debug") << "  -> fail, variable identity" << std::endl;
472
      return -1;
473
    }else{
474
212548
      if( doRemove ){
475
105941
        Assert(d_curr_var_deq[v].find(n) != d_curr_var_deq[v].end());
476
105941
        d_curr_var_deq[v].erase( n );
477
105941
        return 1;
478
      }else{
479
106607
        if( d_curr_var_deq[v].find( n )==d_curr_var_deq[v].end() ){
480
          //check if it respects equality
481
          //std::map< int, TNode >::iterator itm = d_match.find( v );
482
106503
          if( !d_match[v].isNull() ){
483
            TNode nv = getCurrentValue( n );
484
            if( !p->areMatchDisequal( nv, d_match[v] ) ){
485
              Debug("qcf-match-debug") << "  -> fail, conflicting disequality" << std::endl;
486
              return -1;
487
            }
488
          }
489
106503
          d_curr_var_deq[v][n] = v;
490
106503
          Debug("qcf-match-debug") << "  -> success" << std::endl;
491
106503
          return 1;
492
        }else{
493
104
          Debug("qcf-match-debug") << "  -> redundant disequality" << std::endl;
494
104
          return 0;
495
        }
496
      }
497
    }
498
  }
499
}
500
501
88
bool QuantInfo::isConstrainedVar( int v ) {
502
88
  if( d_curr_var_deq.find( v )!=d_curr_var_deq.end() && !d_curr_var_deq[v].empty() ){
503
    return true;
504
  }else{
505
176
    Node vv = getVar( v );
506
    //for( std::map< int, TNode >::iterator it = d_match.begin(); it != d_match.end(); ++it ){
507
1200
    for( unsigned i=0; i<d_match.size(); i++ ){
508
1112
      if( d_match[i]==vv ){
509
        return true;
510
      }
511
    }
512
616
    for( std::map< int, std::map< TNode, int > >::iterator it = d_curr_var_deq.begin(); it != d_curr_var_deq.end(); ++it ){
513
592
      for( std::map< TNode, int >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
514
64
        if( it2->first==vv ){
515
          return true;
516
        }
517
      }
518
    }
519
88
    return false;
520
  }
521
}
522
523
3740820
bool QuantInfo::setMatch( QuantConflictFind * p, int v, TNode n, bool isGroundRep, bool isGround ) {
524
3740820
  if( getCurrentCanBeEqual( p, v, n ) ){
525
3698620
    if( isGroundRep ){
526
      //fail if n does not exist in the relevant domain of each of the argument positions
527
3453219
      std::map< int, std::map< TNode, std::vector< unsigned > > >::iterator it = d_var_rel_dom.find( v );
528
3453219
      if( it!=d_var_rel_dom.end() ){
529
3349723
        for( std::map< TNode, std::vector< unsigned > >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
530
4096824
          for( unsigned j=0; j<it2->second.size(); j++ ){
531
2181832
            Debug("qcf-match-debug2") << n << " in relevant domain " <<  it2->first << "." << it2->second[j] << "?" << std::endl;
532
2181832
            if( !p->getTermDatabase()->inRelevantDomain( it2->first, it2->second[j], n ) ){
533
174128
              Debug("qcf-match-debug") << "  -> fail, since " << n << " is not in relevant domain of " << it2->first << "." << it2->second[j] << std::endl;
534
174128
              return false;
535
            }
536
          }
537
        }
538
      }
539
    }
540
3524492
    Debug("qcf-match-debug") << "-- bind : " << v << " -> " << n << ", checked " <<  d_curr_var_deq[v].size() << " disequalities" << std::endl;
541
3524492
    if( isGround ){
542
3506973
      if( d_vars[v].getKind()==BOUND_VARIABLE ){
543
1478073
        d_vars_set[v] = true;
544
1478073
        Debug("qcf-match-debug") << "---- now bound " << d_vars_set.size() << " / " << d_q[0].getNumChildren() << " base variables." << std::endl;
545
      }
546
    }
547
3524492
    d_match[v] = n;
548
3524492
    return true;
549
  }else{
550
42200
    return false;
551
  }
552
}
553
554
2370020
void QuantInfo::unsetMatch( QuantConflictFind * p, int v ) {
555
2370020
  Debug("qcf-match-debug") << "-- unbind : " << v << std::endl;
556
2370020
  if( d_vars[v].getKind()==BOUND_VARIABLE && d_vars_set.find( v )!=d_vars_set.end() ){
557
845938
    d_vars_set.erase( v );
558
  }
559
2370020
  d_match[ v ] = TNode::null();
560
2370020
}
561
562
244734
bool QuantInfo::isMatchSpurious( QuantConflictFind * p ) {
563
1686563
  for( int i=0; i<getNumVars(); i++ ){
564
    //std::map< int, TNode >::iterator it = d_match.find( i );
565
1487634
    if( !d_match[i].isNull() ){
566
1104154
      if (!getCurrentCanBeEqual(p, i, d_match[i], p->atConflictEffort())) {
567
45805
        return true;
568
      }
569
    }
570
  }
571
198929
  return false;
572
}
573
574
198741
bool QuantInfo::isTConstraintSpurious(QuantConflictFind* p,
575
                                      std::vector<Node>& terms)
576
{
577
198741
  if( options::qcfEagerTest() ){
578
    //check whether the instantiation evaluates as expected
579
198741
    if (p->atConflictEffort()) {
580
105447
      Trace("qcf-instance-check") << "Possible conflict instance for " << d_q << " : " << std::endl;
581
106399
      std::map< TNode, TNode > subs;
582
404725
      for( unsigned i=0; i<terms.size(); i++ ){
583
299278
        Trace("qcf-instance-check") << "  " << terms[i] << std::endl;
584
299278
        subs[d_q[0][i]] = terms[i];
585
      }
586
105447
      TermDb* tdb = p->getTermDatabase();
587
105451
      for( unsigned i=0; i<d_extra_var.size(); i++ ){
588
8
        Node n = getCurrentExpValue( d_extra_var[i] );
589
4
        Trace("qcf-instance-check") << "  " << d_extra_var[i] << " -> " << n << std::endl;
590
4
        subs[d_extra_var[i]] = n;
591
      }
592
105447
      if (!tdb->isEntailed(d_q[1], subs, false, false))
593
      {
594
104495
        Trace("qcf-instance-check") << "...not entailed to be false." << std::endl;
595
104495
        return true;
596
      }
597
    }else{
598
      Node inst =
599
95023
          getInferenceManager().getInstantiate()->getInstantiation(d_q, terms);
600
93294
      inst = Rewriter::rewrite(inst);
601
      Node inst_eval = p->getTermDatabase()->evaluateTerm(
602
95023
          inst, options::qcfTConstraint(), true);
603
93294
      if( Trace.isOn("qcf-instance-check") ){
604
        Trace("qcf-instance-check") << "Possible propagating instance for " << d_q << " : " << std::endl;
605
        for( unsigned i=0; i<terms.size(); i++ ){
606
          Trace("qcf-instance-check") << "  " << terms[i] << std::endl;
607
        }
608
        Trace("qcf-instance-check") << "...evaluates to " << inst_eval << std::endl;
609
      }
610
186588
      if (inst_eval.isNull()
611
93294
          || (inst_eval.isConst() && inst_eval.getConst<bool>()))
612
      {
613
91565
        Trace("qcf-instance-check") << "...spurious." << std::endl;
614
91565
        return true;
615
      }else{
616
1729
        if (Configuration::isDebugBuild())
617
        {
618
1729
          if (!p->isPropagatingInstance(inst_eval))
619
          {
620
            // Notice that this can happen in cases where:
621
            // (1) x = -1*y is rewritten to y = -1*x, and
622
            // (2) -1*y is a term in the master equality engine but -1*x is not.
623
            // In other words, we determined that x = -1*y is a relevant
624
            // equality to propagate since it involves two known terms, but
625
            // after rewriting, the equality y = -1*x involves an unknown term
626
            // -1*x. In this case, the equality is still relevant to propagate,
627
            // despite the above function not being precise enough to realize
628
            // it. We output a warning in debug for this. See #2993.
629
            Trace("qcf-instance-check")
630
                << "WARNING: not propagating." << std::endl;
631
          }
632
        }
633
1729
        Trace("qcf-instance-check") << "...not spurious." << std::endl;
634
      }
635
    }
636
  }
637
2681
  if( !d_tconstraints.empty() ){
638
    //check constraints
639
28
    for( std::map< Node, bool >::iterator it = d_tconstraints.begin(); it != d_tconstraints.end(); ++it ){
640
      //apply substitution to the tconstraint
641
16
      Node cons = p->getQuantifiersRegistry().substituteBoundVariables(
642
32
          it->first, d_q, terms);
643
16
      cons = it->second ? cons : cons.negate();
644
16
      if (!entailmentTest(p, cons, p->atConflictEffort())) {
645
        return true;
646
      }
647
    }
648
  }
649
  // spurious if quantifiers engine is in conflict
650
2681
  return p->d_qstate.isInConflict();
651
}
652
653
16
bool QuantInfo::entailmentTest( QuantConflictFind * p, Node lit, bool chEnt ) {
654
16
  Trace("qcf-tconstraint-debug") << "Check : " << lit << std::endl;
655
32
  Node rew = Rewriter::rewrite( lit );
656
16
  if (rew.isConst())
657
  {
658
8
    Trace("qcf-tconstraint-debug") << "...constraint " << lit << " rewrites to "
659
4
                                   << rew << "." << std::endl;
660
4
    return rew.getConst<bool>();
661
  }
662
  // if checking for conflicts, we must be sure that the (negation of)
663
  // constraint is (not) entailed
664
12
  if (!chEnt)
665
  {
666
12
    rew = Rewriter::rewrite(rew.negate());
667
  }
668
  // check if it is entailed
669
24
  Trace("qcf-tconstraint-debug")
670
12
      << "Check entailment of " << rew << "..." << std::endl;
671
12
  std::pair<bool, Node> et = p->getState().getValuation().entailmentCheck(
672
24
      options::TheoryOfMode::THEORY_OF_TYPE_BASED, rew);
673
12
  ++(p->d_statistics.d_entailment_checks);
674
24
  Trace("qcf-tconstraint-debug")
675
12
      << "ET result : " << et.first << " " << et.second << std::endl;
676
12
  if (!et.first)
677
  {
678
24
    Trace("qcf-tconstraint-debug")
679
12
        << "...cannot show entailment of " << rew << "." << std::endl;
680
12
    return !chEnt;
681
  }
682
  return chEnt;
683
}
684
685
198873
bool QuantInfo::completeMatch( QuantConflictFind * p, std::vector< int >& assigned, bool doContinue ) {
686
  //assign values for variables that were unassigned (usually not necessary, but handles corner cases)
687
198873
  bool doFail = false;
688
198873
  bool success = true;
689
198873
  if( doContinue ){
690
    doFail = true;
691
    success = false;
692
  }else{
693
198873
    if( isBaseMatchComplete() && options::qcfEagerTest() ){
694
198680
      return true;
695
    }
696
    //solve for interpreted symbol matches
697
    //   this breaks the invariant that all introduced constraints are over existing terms
698
201
    for( int i=(int)(d_tsym_vars.size()-1); i>=0; i-- ){
699
8
      int index = d_tsym_vars[i];
700
16
      TNode v = getCurrentValue( d_vars[index] );
701
8
      int slv_v = -1;
702
8
      if( v==d_vars[index] ){
703
8
        slv_v = index;
704
      }
705
8
      Trace("qcf-tconstraint-debug") << "Solve " << d_vars[index] << " = " << v << " " << d_vars[index].getKind() << std::endl;
706
8
      if( d_vars[index].getKind()==PLUS || d_vars[index].getKind()==MULT ){
707
8
        Kind k = d_vars[index].getKind();
708
16
        std::vector< TNode > children;
709
24
        for( unsigned j=0; j<d_vars[index].getNumChildren(); j++ ){
710
16
          int vn = getVarNum( d_vars[index][j] );
711
16
          if( vn!=-1 ){
712
24
            TNode vv = getCurrentValue( d_vars[index][j] );
713
12
            if( vv==d_vars[index][j] ){
714
              //we will assign this
715
8
              if( slv_v==-1 ){
716
                Trace("qcf-tconstraint-debug") << "...will solve for var #" << vn << std::endl;
717
                slv_v = vn;
718
                if (!p->atConflictEffort()) {
719
                  break;
720
                }
721
              }else{
722
16
                Node z = p->getZero( k );
723
8
                if( !z.isNull() ){
724
4
                  Trace("qcf-tconstraint-debug") << "...set " << d_vars[vn] << " = " << z << std::endl;
725
4
                  assigned.push_back( vn );
726
4
                  if( !setMatch( p, vn, z, false, true ) ){
727
                    success = false;
728
                    break;
729
                  }
730
                }
731
              }
732
            }else{
733
4
              Trace("qcf-tconstraint-debug") << "...sum value " << vv << std::endl;
734
4
              children.push_back( vv );
735
            }
736
          }else{
737
4
            Trace("qcf-tconstraint-debug") << "...sum " << d_vars[index][j] << std::endl;
738
4
            children.push_back( d_vars[index][j] );
739
          }
740
        }
741
8
        if( success ){
742
8
          if( slv_v!=-1 ){
743
16
            Node lhs;
744
8
            if( children.empty() ){
745
              lhs = p->getZero( k );
746
8
            }else if( children.size()==1 ){
747
8
              lhs = children[0];
748
            }else{
749
              lhs = NodeManager::currentNM()->mkNode( k, children );
750
            }
751
16
            Node sum;
752
8
            if( v==d_vars[index] ){
753
8
              sum = lhs;
754
            }else{
755
              if (p->atConflictEffort()) {
756
                Kind kn = k;
757
                if( d_vars[index].getKind()==PLUS ){
758
                  kn = MINUS;
759
                }
760
                if( kn!=k ){
761
                  sum = NodeManager::currentNM()->mkNode( kn, v, lhs );
762
                }
763
              }
764
            }
765
8
            if( !sum.isNull() ){
766
8
              assigned.push_back( slv_v );
767
8
              Trace("qcf-tconstraint-debug") << "...set " << d_vars[slv_v] << " = " << sum << std::endl;
768
8
              if( !setMatch( p, slv_v, sum, false, true ) ){
769
                success = false;
770
              }
771
8
              p->d_tempCache.push_back( sum );
772
            }
773
          }else{
774
            //must show that constraint is met
775
            Node sum = NodeManager::currentNM()->mkNode( k, children );
776
            Node eq = sum.eqNode( v );
777
            if( !entailmentTest( p, eq ) ){
778
              success = false;
779
            }
780
            p->d_tempCache.push_back( sum );
781
          }
782
        }
783
      }
784
785
8
      if( !success ){
786
        break;
787
      }
788
    }
789
193
    if( success ){
790
      //check what is left to assign
791
193
      d_unassigned.clear();
792
193
      d_unassigned_tn.clear();
793
386
      std::vector< int > unassigned[2];
794
386
      std::vector< TypeNode > unassigned_tn[2];
795
593
      for( int i=0; i<getNumVars(); i++ ){
796
400
        if( d_match[i].isNull() ){
797
322
          int rindex = d_var_mg.find( i )==d_var_mg.end() ? 1 : 0;
798
322
          unassigned[rindex].push_back( i );
799
322
          unassigned_tn[rindex].push_back( getVar( i ).getType() );
800
322
          assigned.push_back( i );
801
        }
802
      }
803
193
      d_unassigned_nvar = unassigned[0].size();
804
579
      for( unsigned i=0; i<2; i++ ){
805
386
        d_unassigned.insert( d_unassigned.end(), unassigned[i].begin(), unassigned[i].end() );
806
386
        d_unassigned_tn.insert( d_unassigned_tn.end(), unassigned_tn[i].begin(), unassigned_tn[i].end() );
807
      }
808
193
      d_una_eqc_count.clear();
809
193
      d_una_index = 0;
810
    }
811
  }
812
813
193
  if( !d_unassigned.empty() && ( success || doContinue ) ){
814
188
    Trace("qcf-check") << "Assign to unassigned (" << d_unassigned.size() << ")..." << std::endl;
815
182
    do {
816
370
      if( doFail ){
817
182
        Trace("qcf-check-unassign") << "Failure, try again..." << std::endl;
818
      }
819
370
      bool invalidMatch = false;
820
2810
      while( ( d_una_index>=0 && (int)d_una_index<(int)d_unassigned.size() ) || invalidMatch || doFail ){
821
1220
        invalidMatch = false;
822
1220
        if( !doFail && d_una_index==(int)d_una_eqc_count.size() ){
823
          //check if it has now been assigned
824
324
          if( d_una_index<d_unassigned_nvar ){
825
44
            if( !isConstrainedVar( d_unassigned[d_una_index] ) ){
826
44
              d_una_eqc_count.push_back( -1 );
827
            }else{
828
              d_var_mg[ d_unassigned[d_una_index] ]->reset( p, true, this );
829
              d_una_eqc_count.push_back( 0 );
830
            }
831
          }else{
832
280
            d_una_eqc_count.push_back( 0 );
833
          }
834
        }else{
835
896
          bool failed = false;
836
896
          if( !doFail ){
837
714
            if( d_una_index<d_unassigned_nvar ){
838
44
              if( !isConstrainedVar( d_unassigned[d_una_index] ) ){
839
44
                Trace("qcf-check-unassign") << "Succeeded, variable unconstrained at " << d_una_index << std::endl;
840
44
                d_una_index++;
841
              }else if( d_var_mg[d_unassigned[d_una_index]]->getNextMatch( p, this ) ){
842
                Trace("qcf-check-unassign") << "Succeeded match with mg at " << d_una_index << std::endl;
843
                d_una_index++;
844
              }else{
845
                failed = true;
846
                Trace("qcf-check-unassign") << "Failed match with mg at " << d_una_index << std::endl;
847
              }
848
            }else{
849
670
              Assert(doFail || d_una_index == (int)d_una_eqc_count.size() - 1);
850
670
              if( d_una_eqc_count[d_una_index]<(int)p->d_eqcs[d_unassigned_tn[d_una_index]].size() ){
851
467
                int currIndex = d_una_eqc_count[d_una_index];
852
467
                d_una_eqc_count[d_una_index]++;
853
467
                Trace("qcf-check-unassign") << d_unassigned[d_una_index] << "->" << p->d_eqcs[d_unassigned_tn[d_una_index]][currIndex] << std::endl;
854
467
                if( setMatch( p, d_unassigned[d_una_index], p->d_eqcs[d_unassigned_tn[d_una_index]][currIndex], true, true ) ){
855
330
                  d_match_term[d_unassigned[d_una_index]] = TNode::null();
856
330
                  Trace("qcf-check-unassign") << "Succeeded match " << d_una_index << std::endl;
857
330
                  d_una_index++;
858
                }else{
859
137
                  Trace("qcf-check-unassign") << "Failed match " << d_una_index << std::endl;
860
137
                  invalidMatch = true;
861
                }
862
              }else{
863
203
                failed = true;
864
203
                Trace("qcf-check-unassign") << "No more matches " << d_una_index << std::endl;
865
              }
866
            }
867
          }
868
896
          if( doFail || failed ){
869
            do{
870
385
              if( !doFail ){
871
203
                d_una_eqc_count.pop_back();
872
              }else{
873
182
                doFail = false;
874
              }
875
385
              d_una_index--;
876
385
            }while( d_una_index>=0 && d_una_eqc_count[d_una_index]==-1 );
877
          }
878
        }
879
      }
880
370
      success = d_una_index>=0;
881
370
      if( success ){
882
238
        doFail = true;
883
238
        Trace("qcf-check-unassign") << "  Try: " << std::endl;
884
674
        for( unsigned i=0; i<d_unassigned.size(); i++ ){
885
436
          int ui = d_unassigned[i];
886
436
          if( !d_match[ui].isNull() ){
887
392
            Trace("qcf-check-unassign") << "  Assigned #" << ui << " : " << d_vars[ui] << " -> " << d_match[ui] << std::endl;
888
          }
889
        }
890
      }
891
370
    }while( success && isMatchSpurious( p ) );
892
188
    Trace("qcf-check") << "done assigning." << std::endl;
893
  }
894
193
  if( success ){
895
182
    for( unsigned i=0; i<d_unassigned.size(); i++ ){
896
121
      int ui = d_unassigned[i];
897
121
      if( !d_match[ui].isNull() ){
898
77
        Trace("qcf-check") << "  Assigned #" << ui << " : " << d_vars[ui] << " -> " << d_match[ui] << std::endl;
899
      }
900
    }
901
61
    return true;
902
  }else{
903
132
    revertMatch( p, assigned );
904
132
    assigned.clear();
905
132
    return false;
906
  }
907
}
908
909
198741
void QuantInfo::getMatch( std::vector< Node >& terms ){
910
759633
  for( unsigned i=0; i<d_q[0].getNumChildren(); i++ ){
911
    //Node cv = qi->getCurrentValue( qi->d_match[i] );
912
560892
    int repVar = getCurrentRepVar( i );
913
1121784
    Node cv;
914
    //std::map< int, TNode >::iterator itmt = qi->d_match_term.find( repVar );
915
560892
    if( !d_match_term[repVar].isNull() ){
916
555427
      cv = d_match_term[repVar];
917
    }else{
918
5465
      cv = d_match[repVar];
919
    }
920
560892
    Debug("qcf-check-inst") << "INST : " << i << " -> " << cv << ", from " << d_match[i] << std::endl;
921
560892
    terms.push_back( cv );
922
  }
923
198741
}
924
925
197723
void QuantInfo::revertMatch( QuantConflictFind * p, std::vector< int >& assigned ) {
926
198013
  for( unsigned i=0; i<assigned.size(); i++ ){
927
290
    unsetMatch( p, assigned[i] );
928
  }
929
197723
}
930
931
void QuantInfo::debugPrintMatch( const char * c ) {
932
  for( int i=0; i<getNumVars(); i++ ){
933
    Trace(c) << "  " << d_vars[i] << " -> ";
934
    if( !d_match[i].isNull() ){
935
      Trace(c) << d_match[i];
936
    }else{
937
      Trace(c) << "(unassigned) ";
938
    }
939
    if( !d_curr_var_deq[i].empty() ){
940
      Trace(c) << ", DEQ{ ";
941
      for( std::map< TNode, int >::iterator it = d_curr_var_deq[i].begin(); it != d_curr_var_deq[i].end(); ++it ){
942
        Trace(c) << it->first << " ";
943
      }
944
      Trace(c) << "}";
945
    }
946
    if( !d_match_term[i].isNull() && d_match_term[i]!=d_match[i] ){
947
      Trace(c) << ", EXP : " << d_match_term[i];
948
    }
949
    Trace(c) <<  std::endl;
950
  }
951
  if( !d_tconstraints.empty() ){
952
    Trace(c) << "ADDITIONAL CONSTRAINTS : " << std::endl;
953
    for( std::map< Node, bool >::iterator it = d_tconstraints.begin(); it != d_tconstraints.end(); ++it ){
954
      Trace(c) << "   " << it->first << " -> " << it->second << std::endl;
955
    }
956
  }
957
}
958
959
MatchGen::MatchGen()
960
  : d_matched_basis(),
961
    d_binding(),
962
    d_tgt(),
963
    d_tgt_orig(),
964
    d_wasSet(),
965
    d_n(),
966
    d_type( typ_invalid ),
967
    d_type_not()
968
{
969
  d_qni_size = 0;
970
  d_child_counter = -1;
971
  d_use_children = true;
972
}
973
974
975
157775
MatchGen::MatchGen( QuantInfo * qi, Node n, bool isVar )
976
  : d_matched_basis(),
977
    d_binding(),
978
    d_tgt(),
979
    d_tgt_orig(),
980
    d_wasSet(),
981
    d_n(),
982
    d_type(),
983
157775
    d_type_not()
984
{
985
  //initialize temporary
986
157775
  d_child_counter = -1;
987
157775
  d_use_children = true;
988
989
157775
  Trace("qcf-qregister-debug") << "Make match gen for " << n << ", isVar = " << isVar << std::endl;
990
315550
  std::vector< Node > qni_apps;
991
157775
  d_qni_size = 0;
992
157775
  if( isVar ){
993
80087
    Assert(qi->d_var_num.find(n) != qi->d_var_num.end());
994
    // rare case where we have a free variable in an operator, we are invalid
995
160174
    if (n.getKind() == ITE
996
161288
        || (options::ufHo() && n.getKind() == APPLY_UF
997
92282
            && expr::hasFreeVar(n.getOperator())))
998
    {
999
1114
      d_type = typ_invalid;
1000
    }else{
1001
78973
      d_type = isHandledUfTerm( n ) ? typ_var : typ_tsym;
1002
78973
      d_qni_var_num[0] = qi->getVarNum( n );
1003
78973
      d_qni_size++;
1004
78973
      d_type_not = false;
1005
78973
      d_n = n;
1006
      //Node f = getMatchOperator( n );
1007
246203
      for( unsigned j=0; j<d_n.getNumChildren(); j++ ){
1008
334460
        Node nn = d_n[j];
1009
167230
        Trace("qcf-qregister-debug") << "  " << d_qni_size;
1010
167230
        if( qi->isVar( nn ) ){
1011
145934
          int v = qi->d_var_num[nn];
1012
145934
          Trace("qcf-qregister-debug") << " is var #" << v << std::endl;
1013
145934
          d_qni_var_num[d_qni_size] = v;
1014
          //qi->addFuncParent( v, f, j );
1015
        }else{
1016
21296
          Trace("qcf-qregister-debug") << " is gterm " << nn << std::endl;
1017
21296
          d_qni_gterm[d_qni_size] = nn;
1018
        }
1019
167230
        d_qni_size++;
1020
      }
1021
    }
1022
  }else{
1023
77688
    if (expr::hasBoundVar(n))
1024
    {
1025
77603
      d_type_not = false;
1026
77603
      d_n = n;
1027
77603
      if( d_n.getKind()==NOT ){
1028
24836
        d_n = d_n[0];
1029
24836
        d_type_not = !d_type_not;
1030
      }
1031
1032
77603
      if( isHandledBoolConnective( d_n ) ){
1033
        //non-literals
1034
25666
        d_type = typ_formula;
1035
81329
        for( unsigned i=0; i<d_n.getNumChildren(); i++ ){
1036
59843
          if( d_n.getKind()!=FORALL || i==1 ){
1037
55594
            d_children.push_back( MatchGen( qi, d_n[i], false ) );
1038
55594
            if( !d_children[d_children.size()-1].isValid() ){
1039
4180
              setInvalid();
1040
4180
              break;
1041
            }
1042
          }
1043
        }
1044
      }else{
1045
51937
        d_type = typ_invalid;
1046
        //literals
1047
51937
        if( isHandledUfTerm( d_n ) ){
1048
18059
          Assert(qi->isVar(d_n));
1049
18059
          d_type = typ_pred;
1050
33878
        }else if( d_n.getKind()==BOUND_VARIABLE ){
1051
164
          Assert(d_n.getType().isBoolean());
1052
164
          d_type = typ_bool_var;
1053
33714
        }else if( d_n.getKind()==EQUAL || options::qcfTConstraint() ){
1054
91434
          for (unsigned i = 0; i < d_n.getNumChildren(); i++)
1055
          {
1056
60956
            if (expr::hasBoundVar(d_n[i]))
1057
            {
1058
45127
              if (!qi->isVar(d_n[i]))
1059
              {
1060
                Trace("qcf-qregister-debug")
1061
                    << "ERROR : not var " << d_n[i] << std::endl;
1062
              }
1063
45127
              Assert(qi->isVar(d_n[i]));
1064
45127
              if (d_n.getKind() != EQUAL && qi->isVar(d_n[i]))
1065
              {
1066
338
                d_qni_var_num[i + 1] = qi->d_var_num[d_n[i]];
1067
              }
1068
            }
1069
            else
1070
            {
1071
15829
              d_qni_gterm[i] = d_n[i];
1072
            }
1073
          }
1074
30478
          d_type = d_n.getKind() == EQUAL ? typ_eq : typ_tconstraint;
1075
30478
          Trace("qcf-tconstraint") << "T-Constraint : " << d_n << std::endl;
1076
        }
1077
      }
1078
    }else{
1079
      //we will just evaluate
1080
85
      d_n = n;
1081
85
      d_type = typ_ground;
1082
    }
1083
  }
1084
157775
  Trace("qcf-qregister-debug")  << "Done make match gen " << n << ", type = ";
1085
157775
  debugPrintType( "qcf-qregister-debug", d_type, true );
1086
157775
  Trace("qcf-qregister-debug") << std::endl;
1087
  //Assert( d_children.size()==d_children_order.size() );
1088
1089
157775
}
1090
1091
470854
void MatchGen::collectBoundVar( QuantInfo * qi, Node n, std::vector< int >& cbvars, std::map< Node, bool >& visited, bool& hasNested ) {
1092
470854
  if( visited.find( n )==visited.end() ){
1093
403898
    visited[n] = true;
1094
403898
    if( n.getKind()==FORALL ){
1095
3549
      hasNested = true;
1096
    }
1097
403898
    int v = qi->getVarNum( n );
1098
403898
    if( v!=-1 && std::find( cbvars.begin(), cbvars.end(), v )==cbvars.end() ){
1099
262206
      cbvars.push_back( v );
1100
    }
1101
830415
    for( unsigned i=0; i<n.getNumChildren(); i++ ){
1102
426517
      collectBoundVar( qi, n[i], cbvars, visited, hasNested );
1103
    }
1104
  }
1105
470854
}
1106
1107
140601
void MatchGen::determineVariableOrder( QuantInfo * qi, std::vector< int >& bvars ) {
1108
140601
  Trace("qcf-qregister-debug") << "Determine variable order " << d_n << ", #bvars = " << bvars.size() << std::endl;
1109
140601
  bool isComm = d_type==typ_formula && ( d_n.getKind()==OR || d_n.getKind()==AND || d_n.getKind()==EQUAL );
1110
140601
  if( isComm ){
1111
31690
    std::map< int, std::vector< int > > c_to_vars;
1112
31690
    std::map< int, std::vector< int > > vars_to_c;
1113
31690
    std::map< int, int > vb_count;
1114
31690
    std::map< int, int > vu_count;
1115
31690
    std::map< int, bool > has_nested;
1116
31690
    std::vector< bool > assigned;
1117
15845
    Trace("qcf-qregister-debug") << "Calculate bound variables..." << std::endl;
1118
56190
    for( unsigned i=0; i<d_children.size(); i++ ){
1119
80690
      std::map< Node, bool > visited;
1120
40345
      has_nested[i] = false;
1121
40345
      collectBoundVar( qi, d_children[i].d_n, c_to_vars[i], visited, has_nested[i] );
1122
40345
      assigned.push_back( false );
1123
40345
      vb_count[i] = 0;
1124
40345
      vu_count[i] = 0;
1125
249026
      for( unsigned j=0; j<c_to_vars[i].size(); j++ ){
1126
208681
        int v = c_to_vars[i][j];
1127
208681
        vars_to_c[v].push_back( i );
1128
208681
        if( std::find( bvars.begin(), bvars.end(), v )==bvars.end() ){
1129
190184
          vu_count[i]++;
1130
        }else{
1131
18497
          vb_count[i]++;
1132
        }
1133
      }
1134
    }
1135
    //children that bind no unbound variable, then the most number of bound, unbound variables go first
1136
15845
    Trace("qcf-qregister-vo") << "Variable order for " << d_n << " : " << std::endl;
1137
24500
    do {
1138
40345
      int min_score0 = -1;
1139
40345
      int min_score = -1;
1140
40345
      int min_score_index = -1;
1141
749008
      for( unsigned i=0; i<d_children.size(); i++ ){
1142
708663
        if( !assigned[i] ){
1143
374504
          Trace("qcf-qregister-debug2") << "Child " << i << " has b/ub : " << vb_count[i] << "/" << vu_count[i] << std::endl;
1144
374504
          int score0 = 0;//has_nested[i] ? 0 : 1;
1145
          int score;
1146
374504
          if( !options::qcfVoExp() ){
1147
374504
            score = vu_count[i];
1148
          }else{
1149
            score =  vu_count[i]==0 ? 0 : ( 1 + qi->d_vars.size()*( qi->d_vars.size() - vb_count[i] ) + ( qi->d_vars.size() - vu_count[i] )  );
1150
          }
1151
374504
          if( min_score==-1 || score0<min_score0 || ( score0==min_score0 && score<min_score ) ){
1152
68356
            min_score0 = score0;
1153
68356
            min_score = score;
1154
68356
            min_score_index = i;
1155
          }
1156
        }
1157
      }
1158
40345
      Trace("qcf-qregister-vo") << "  " << d_children_order.size()+1 << ": " << d_children[min_score_index].d_n << " : ";
1159
40345
      Trace("qcf-qregister-vo") << vu_count[min_score_index] << " " << vb_count[min_score_index] << " " << has_nested[min_score_index] << std::endl;
1160
40345
      Trace("qcf-qregister-debug") << "...assign child " << min_score_index << std::endl;
1161
40345
      Trace("qcf-qregister-debug") << "...score : " << min_score << std::endl;
1162
40345
      Assert(min_score_index != -1);
1163
      //add to children order
1164
40345
      d_children_order.push_back( min_score_index );
1165
40345
      assigned[min_score_index] = true;
1166
      //determine order internal to children
1167
40345
      d_children[min_score_index].determineVariableOrder( qi, bvars );
1168
40345
      Trace("qcf-qregister-debug")  << "...bind variables" << std::endl;
1169
      //now, make it a bound variable
1170
40345
      if( vu_count[min_score_index]>0 ){
1171
229223
        for( unsigned i=0; i<c_to_vars[min_score_index].size(); i++ ){
1172
191304
          int v = c_to_vars[min_score_index][i];
1173
191304
          if( std::find( bvars.begin(), bvars.end(), v )==bvars.end() ){
1174
243101
            for( unsigned j=0; j<vars_to_c[v].size(); j++ ){
1175
158750
              int vc = vars_to_c[v][j];
1176
158750
              vu_count[vc]--;
1177
158750
              vb_count[vc]++;
1178
            }
1179
84351
            bvars.push_back( v );
1180
          }
1181
        }
1182
      }
1183
40345
      Trace("qcf-qregister-debug") << "...done assign child " << min_score_index << std::endl;
1184
40345
    }while( d_children_order.size()!=d_children.size() );
1185
15845
    Trace("qcf-qregister-debug") << "Done assign variable ordering for " << d_n << std::endl;
1186
  }else{
1187
128748
    for( unsigned i=0; i<d_children.size(); i++ ){
1188
3992
      d_children_order.push_back( i );
1189
3992
      d_children[i].determineVariableOrder( qi, bvars );
1190
      //now add to bvars
1191
7984
      std::map< Node, bool > visited;
1192
7984
      std::vector< int > cvars;
1193
3992
      bool has_nested = false;
1194
3992
      collectBoundVar( qi, d_children[i].d_n, cvars, visited, has_nested );
1195
57517
      for( unsigned j=0; j<cvars.size(); j++ ){
1196
53525
        if( std::find( bvars.begin(), bvars.end(), cvars[j] )==bvars.end() ){
1197
6292
          bvars.push_back( cvars[j] );
1198
        }
1199
      }
1200
    }
1201
  }
1202
140601
}
1203
1204
980917
bool MatchGen::reset_round(QuantConflictFind* p)
1205
{
1206
980917
  d_wasSet = false;
1207
1335817
  for( unsigned i=0; i<d_children.size(); i++ ){
1208
354900
    if (!d_children[i].reset_round(p))
1209
    {
1210
      return false;
1211
    }
1212
  }
1213
980917
  if( d_type==typ_ground ){
1214
    // int e = p->evaluate( d_n );
1215
    // if( e==1 ){
1216
    //  d_ground_eval[0] = p->d_true;
1217
    //}else if( e==-1 ){
1218
    //  d_ground_eval[0] = p->d_false;
1219
    //}
1220
    // modified
1221
772
    TermDb* tdb = p->getTermDatabase();
1222
772
    QuantifiersState& qs = p->getState();
1223
2316
    for (unsigned i = 0; i < 2; i++)
1224
    {
1225
1544
      if (tdb->isEntailed(d_n, i == 0))
1226
      {
1227
68
        d_ground_eval[0] = i==0 ? p->d_true : p->d_false;
1228
      }
1229
1544
      if (qs.isInConflict())
1230
      {
1231
        return false;
1232
      }
1233
    }
1234
980145
  }else if( d_type==typ_eq ){
1235
163648
    TermDb* tdb = p->getTermDatabase();
1236
163648
    QuantifiersState& qs = p->getState();
1237
490944
    for (unsigned i = 0, size = d_n.getNumChildren(); i < size; i++)
1238
    {
1239
327296
      if (!expr::hasBoundVar(d_n[i]))
1240
      {
1241
173810
        TNode t = tdb->getEntailedTerm(d_n[i]);
1242
86905
        if (qs.isInConflict())
1243
        {
1244
          return false;
1245
        }
1246
86905
        if (t.isNull())
1247
        {
1248
1641
          d_ground_eval[i] = d_n[i];
1249
        }
1250
        else
1251
        {
1252
85264
          d_ground_eval[i] = t;
1253
        }
1254
      }
1255
    }
1256
  }
1257
980917
  d_qni_bound_cons.clear();
1258
980917
  d_qni_bound_cons_var.clear();
1259
980917
  d_qni_bound.clear();
1260
980917
  return true;
1261
}
1262
1263
1640696
void MatchGen::reset( QuantConflictFind * p, bool tgt, QuantInfo * qi ) {
1264
1640696
  d_tgt = d_type_not ? !tgt : tgt;
1265
1640696
  Debug("qcf-match") << "     Reset for : " << d_n << ", type : ";
1266
1640696
  debugPrintType( "qcf-match", d_type );
1267
1640696
  Debug("qcf-match") << ", tgt = " << d_tgt << ", children = " << d_children.size() << " " << d_children_order.size() << std::endl;
1268
1640696
  d_qn.clear();
1269
1640696
  d_qni.clear();
1270
1640696
  d_qni_bound.clear();
1271
1640696
  d_child_counter = -1;
1272
1640696
  d_use_children = true;
1273
1640696
  d_tgt_orig = d_tgt;
1274
1275
  //set up processing matches
1276
1640696
  if( d_type==typ_invalid ){
1277
    d_use_children = false;
1278
1640696
  }else if( d_type==typ_ground ){
1279
238
    d_use_children = false;
1280
238
    if( d_ground_eval[0]==( d_tgt ? p->d_true : p->d_false ) ){
1281
20
      d_child_counter = 0;
1282
    }
1283
1640458
  }else if( qi->isBaseMatchComplete() && options::qcfEagerTest() ){
1284
248892
    d_use_children = false;
1285
248892
    d_child_counter = 0;
1286
1391566
  }else if( d_type==typ_bool_var ){
1287
    //get current value of the variable
1288
3340
    TNode n = qi->getCurrentValue( d_n );
1289
1670
    int vn = qi->getCurrentRepVar( qi->getVarNum( n ) );
1290
1670
    if( vn==-1 ){
1291
      //evaluate the value, see if it is compatible
1292
      //int e = p->evaluate( n );
1293
      //if( ( e==1 && d_tgt ) || ( e==0 && !d_tgt ) ){
1294
      //  d_child_counter = 0;
1295
      //}
1296
      //modified
1297
      if( p->getTermDatabase()->isEntailed( n, d_tgt ) ){
1298
        d_child_counter = 0;
1299
      }
1300
    }else{
1301
      //unassigned, set match to true/false
1302
1670
      d_qni_bound[0] = vn;
1303
1670
      qi->setMatch( p, vn, d_tgt ? p->d_true : p->d_false, false, true );
1304
1670
      d_child_counter = 0;
1305
    }
1306
1670
    if( d_child_counter==0 ){
1307
1670
      d_qn.push_back( NULL );
1308
    }
1309
1389896
  }else if( d_type==typ_var ){
1310
901450
    Assert(isHandledUfTerm(d_n));
1311
1802900
    TNode f = getMatchOperator( p, d_n );
1312
901450
    Debug("qcf-match-debug") << "       reset: Var will match operators of " << f << std::endl;
1313
901450
    TNodeTrie* qni = p->getTermDatabase()->getTermArgTrie(Node::null(), f);
1314
901450
    if (qni == nullptr || qni->empty())
1315
    {
1316
      //inform irrelevant quantifiers
1317
127016
      p->setIrrelevantFunction( f );
1318
    }
1319
    else
1320
    {
1321
774434
      d_qn.push_back(qni);
1322
    }
1323
901450
    d_matched_basis = false;
1324
488446
  }else if( d_type==typ_tsym || d_type==typ_tconstraint ){
1325
3248
    for( std::map< int, int >::iterator it = d_qni_var_num.begin(); it != d_qni_var_num.end(); ++it ){
1326
1938
      int repVar = qi->getCurrentRepVar( it->second );
1327
1938
      if( qi->d_match[repVar].isNull() ){
1328
1872
        Debug("qcf-match-debug") << "Force matching on child #" << it->first << ", which is var #" << repVar << std::endl;
1329
1872
        d_qni_bound[it->first] = repVar;
1330
      }
1331
    }
1332
1310
    d_qn.push_back( NULL );
1333
487136
  }else if( d_type==typ_pred || d_type==typ_eq ){
1334
    //add initial constraint
1335
701736
    Node nn[2];
1336
    int vn[2];
1337
350868
    if( d_type==typ_pred ){
1338
153452
      nn[0] = qi->getCurrentValue( d_n );
1339
153452
      vn[0] = qi->getCurrentRepVar( qi->getVarNum( nn[0] ) );
1340
153452
      nn[1] = d_tgt ? p->d_true : p->d_false;
1341
153452
      vn[1] = -1;
1342
153452
      d_tgt = true;
1343
    }else{
1344
592248
      for( unsigned i=0; i<2; i++ ){
1345
789664
        TNode nc;
1346
394832
        std::map<int, TNode>::iterator it = d_qni_gterm.find(i);
1347
394832
        if (it != d_qni_gterm.end())
1348
        {
1349
127569
          nc = it->second;
1350
        }else{
1351
267263
          nc = d_n[i];
1352
        }
1353
394832
        nn[i] = qi->getCurrentValue( nc );
1354
394832
        vn[i] = qi->getCurrentRepVar( qi->getVarNum( nn[i] ) );
1355
      }
1356
    }
1357
    bool success;
1358
350868
    if( vn[0]==-1 && vn[1]==-1 ){
1359
      //Trace("qcf-explain") << "    reset : " << d_n << " check ground values " << nn[0] << " " << nn[1] << " (tgt=" << d_tgt << ")" << std::endl;
1360
514
      Debug("qcf-match-debug") << "       reset: check ground values " << nn[0] << " " << nn[1] << " (" << d_tgt << ")" << std::endl;
1361
      //just compare values
1362
1028
      if( d_tgt ){
1363
482
        success = p->areMatchEqual( nn[0], nn[1] );
1364
      }else{
1365
32
        if (p->atConflictEffort()) {
1366
17
          success = p->areDisequal( nn[0], nn[1] );
1367
        }else{
1368
15
          success = p->areMatchDisequal( nn[0], nn[1] );
1369
        }
1370
      }
1371
    }else{
1372
      //otherwise, add a constraint to a variable  TODO: this may be over-eager at effort > conflict, since equality may be a propagation
1373
350354
      if( vn[1]!=-1 && vn[0]==-1 ){
1374
        //swap
1375
154426
        Node t = nn[1];
1376
77213
        nn[1] = nn[0];
1377
77213
        nn[0] = t;
1378
77213
        vn[0] = vn[1];
1379
77213
        vn[1] = -1;
1380
      }
1381
350354
      Debug("qcf-match-debug") << "       reset: add constraint " << vn[0] << " -> " << nn[1] << " (vn=" << vn[1] << ")" << std::endl;
1382
      //add some constraint
1383
350354
      int addc = qi->addConstraint( p, vn[0], nn[1], vn[1], d_tgt, false );
1384
350354
      success = addc!=-1;
1385
      //if successful and non-redundant, store that we need to cleanup this
1386
350354
      if( addc==1 ){
1387
        //Trace("qcf-explain") << "       reset: " << d_n << " add constraint " << vn[0] << " -> " << nn[1] << " (vn=" << vn[1] << ")" << ", d_tgt = " << d_tgt << std::endl;
1388
1050666
        for( unsigned i=0; i<2; i++ ){
1389
700444
          if( vn[i]!=-1 && std::find( d_qni_bound_except.begin(), d_qni_bound_except.end(), i )==d_qni_bound_except.end() ){
1390
415431
            d_qni_bound[vn[i]] = vn[i];
1391
          }
1392
        }
1393
350222
        d_qni_bound_cons[vn[0]] = nn[1];
1394
350222
        d_qni_bound_cons_var[vn[0]] = vn[1];
1395
      }
1396
    }
1397
    //if successful, we will bind values to variables
1398
350868
    if( success ){
1399
350411
      d_qn.push_back( NULL );
1400
350868
    }
1401
  }else{
1402
136268
    if( d_children.empty() ){
1403
      //add dummy
1404
      d_qn.push_back( NULL );
1405
    }else{
1406
136268
      if( d_tgt && d_n.getKind()==FORALL ){
1407
        //fail
1408
118680
      } else if (d_n.getKind() == FORALL && p->atConflictEffort() &&
1409
3401
                 !options::qcfNestedConflict()) {
1410
        //fail
1411
      }else{
1412
        //reset the first child to d_tgt
1413
111878
        d_child_counter = 0;
1414
111878
        getChild( d_child_counter )->reset( p, d_tgt, qi );
1415
      }
1416
    }
1417
  }
1418
1640696
  d_binding = false;
1419
1640696
  d_wasSet = true;
1420
1640696
  Debug("qcf-match") << "     reset: Finished reset for " << d_n << ", success = " << ( !d_qn.empty() || d_child_counter!=-1 ) << std::endl;
1421
1640696
}
1422
1423
3127073
bool MatchGen::getNextMatch( QuantConflictFind * p, QuantInfo * qi ) {
1424
3127073
  Debug("qcf-match") << "     Get next match for : " << d_n << ", type = ";
1425
3127073
  debugPrintType( "qcf-match", d_type );
1426
3127073
  Debug("qcf-match") << ", children = " << d_children.size() << ", binding = " << d_binding << std::endl;
1427
3127073
  if( !d_use_children ){
1428
497286
    if( d_child_counter==0 ){
1429
248912
      d_child_counter = -1;
1430
248912
      return true;
1431
    }else{
1432
248374
      d_wasSet = false;
1433
248374
      return false;
1434
    }
1435
2629787
  }else if( d_type==typ_var || d_type==typ_eq || d_type==typ_pred || d_type==typ_bool_var || d_type==typ_tconstraint || d_type==typ_tsym ){
1436
2246007
    bool success = false;
1437
2246007
    bool terminate = false;
1438
1337034
    do {
1439
3583041
      bool doReset = false;
1440
3583041
      bool doFail = false;
1441
3583041
      if( !d_binding ){
1442
2596591
        if( doMatching( p, qi ) ){
1443
1345986
          Debug("qcf-match-debug") << "     - Matching succeeded" << std::endl;
1444
1345986
          d_binding = true;
1445
1345986
          d_binding_it = d_qni_bound.begin();
1446
1345986
          doReset = true;
1447
          //for tconstraint, add constraint
1448
1345986
          if( d_type==typ_tconstraint ){
1449
883
            std::map< Node, bool >::iterator it = qi->d_tconstraints.find( d_n );
1450
883
            if( it==qi->d_tconstraints.end() ){
1451
883
              qi->d_tconstraints[d_n] = d_tgt;
1452
              //store that we added this constraint
1453
883
              d_qni_bound_cons[0] = d_n;
1454
            }else if( d_tgt!=it->second ){
1455
              success = false;
1456
              terminate = true;
1457
            }
1458
          }
1459
        }else{
1460
1250605
          Debug("qcf-match-debug") << "     - Matching failed" << std::endl;
1461
1250605
          success = false;
1462
1250605
          terminate = true;
1463
        }
1464
      }else{
1465
986450
        doFail = true;
1466
      }
1467
3583041
      if( d_binding ){
1468
        //also need to create match for each variable we bound
1469
2332436
        success = true;
1470
2332436
        Debug("qcf-match-debug") << "     Produce matches for bound variables by " << d_n << ", type = ";
1471
2332436
        debugPrintType( "qcf-match-debug", d_type );
1472
2332436
        Debug("qcf-match-debug") << "..." << std::endl;
1473
1474
10165154
        while( ( success && d_binding_it!=d_qni_bound.end() ) || doFail ){
1475
3916359
          QuantInfo::VarMgMap::const_iterator itm;
1476
3916359
          if( !doFail ){
1477
2929909
            Debug("qcf-match-debug") << "       check variable " << d_binding_it->second << std::endl;
1478
2929909
            itm = qi->var_mg_find( d_binding_it->second );
1479
          }
1480
3916359
          if( doFail || ( d_binding_it->first!=0 && itm != qi->var_mg_end() ) ){
1481
2618269
            Debug("qcf-match-debug") << "       we had bound variable " << d_binding_it->second << ", reset = " << doReset << std::endl;
1482
2618269
            if( doReset ){
1483
992574
              itm->second->reset( p, true, qi );
1484
            }
1485
2618269
            if( doFail || !itm->second->getNextMatch( p, qi ) ){
1486
1294109
              do {
1487
3270388
                if( d_binding_it==d_qni_bound.begin() ){
1488
1337034
                  Debug("qcf-match-debug") << "       failed." << std::endl;
1489
1337034
                  success = false;
1490
                }else{
1491
1933354
                  --d_binding_it;
1492
1933354
                  Debug("qcf-match-debug") << "       decrement..." << std::endl;
1493
                }
1494
6497851
              }while( success &&
1495
3368612
                      ( d_binding_it->first==0 ||
1496
1435258
                        (!qi->containsVarMg(d_binding_it->second))));
1497
1976279
              doReset = false;
1498
1976279
              doFail = false;
1499
            }else{
1500
641990
              Debug("qcf-match-debug") << "       increment..." << std::endl;
1501
641990
              ++d_binding_it;
1502
641990
              doReset = true;
1503
            }
1504
          }else{
1505
1298090
            Debug("qcf-match-debug") << "       skip..." << d_binding_it->second << std::endl;
1506
1298090
            ++d_binding_it;
1507
1298090
            doReset = true;
1508
          }
1509
        }
1510
2332436
        if( !success ){
1511
1337034
          d_binding = false;
1512
        }else{
1513
995402
          terminate = true;
1514
995402
          if( d_binding_it==d_qni_bound.begin() ){
1515
4319
            d_binding = false;
1516
          }
1517
        }
1518
      }
1519
3583041
    }while( !terminate );
1520
    //if not successful, clean up the variables you bound
1521
2246007
    if( !success ){
1522
1250605
      if( d_type==typ_eq || d_type==typ_pred ){
1523
        //clean up the constraints you added
1524
696872
        for( std::map< int, TNode >::iterator it = d_qni_bound_cons.begin(); it != d_qni_bound_cons.end(); ++it ){
1525
348117
          if( !it->second.isNull() ){
1526
348117
            Debug("qcf-match") << "       Clean up bound var " << it->first << (d_tgt ? "!" : "") << " = " << it->second << std::endl;
1527
348117
            std::map< int, int >::iterator itb = d_qni_bound_cons_var.find( it->first );
1528
348117
            int vn = itb!=d_qni_bound_cons_var.end() ? itb->second : -1;
1529
            //Trace("qcf-explain") << "       cleanup: " << d_n << " remove constraint " << it->first << " -> " << it->second << " (vn=" << vn << ")" << ", d_tgt = " << d_tgt << std::endl;
1530
348117
            qi->addConstraint( p, it->first, it->second, vn, d_tgt, true );
1531
          }
1532
        }
1533
348755
        d_qni_bound_cons.clear();
1534
348755
        d_qni_bound_cons_var.clear();
1535
348755
        d_qni_bound.clear();
1536
      }else{
1537
        //clean up the matches you set
1538
1532857
        for( std::map< int, int >::iterator it = d_qni_bound.begin(); it != d_qni_bound.end(); ++it ){
1539
631007
          Debug("qcf-match") << "       Clean up bound var " << it->second << std::endl;
1540
631007
          Assert(it->second < qi->getNumVars());
1541
631007
          qi->unsetMatch( p, it->second );
1542
631007
          qi->d_match_term[ it->second ] = TNode::null();
1543
        }
1544
901850
        d_qni_bound.clear();
1545
      }
1546
1250605
      if( d_type==typ_tconstraint ){
1547
        //remove constraint if applicable
1548
875
        if( d_qni_bound_cons.find( 0 )!=d_qni_bound_cons.end() ){
1549
875
          qi->d_tconstraints.erase( d_n );
1550
875
          d_qni_bound_cons.clear();
1551
        }
1552
      }
1553
    }
1554
2246007
    Debug("qcf-match") << "    ...finished matching for " << d_n << ", success = " << success << std::endl;
1555
2246007
    d_wasSet = success;
1556
2246007
    return success;
1557
  }
1558
383780
  else if (d_type == typ_formula)
1559
  {
1560
383780
    bool success = false;
1561
383780
    if( d_child_counter<0 ){
1562
24390
      if( d_child_counter<-1 ){
1563
        success = true;
1564
        d_child_counter = -1;
1565
      }
1566
    }else{
1567
2410064
      while( !success && d_child_counter>=0 ){
1568
        //transition system based on d_child_counter
1569
1025337
        if( d_n.getKind()==OR || d_n.getKind()==AND ){
1570
759774
          if( (d_n.getKind()==AND)==d_tgt ){
1571
            //all children must match simultaneously
1572
712032
            if( getChild( d_child_counter )->getNextMatch( p, qi ) ){
1573
408474
              if( d_child_counter<(int)(getNumChildren()-1) ){
1574
250996
                d_child_counter++;
1575
250996
                Debug("qcf-match-debug") << "       Reset child " << d_child_counter << " of " << d_n << std::endl;
1576
250996
                getChild( d_child_counter )->reset( p, d_tgt, qi );
1577
              }else{
1578
157478
                success = true;
1579
              }
1580
            }else{
1581
              //if( std::find( d_independent.begin(), d_independent.end(), d_child_counter )!=d_independent.end() ){
1582
              //  d_child_counter--;
1583
              //}else{
1584
303558
              d_child_counter--;
1585
              //}
1586
            }
1587
          }else{
1588
            //one child must match
1589
47742
            if( !getChild( d_child_counter )->getNextMatch( p, qi ) ){
1590
23624
              if( d_child_counter<(int)(getNumChildren()-1) ){
1591
13268
                d_child_counter++;
1592
13268
                Debug("qcf-match-debug") << "       Reset child " << d_child_counter << " of " << d_n << ", one match" << std::endl;
1593
13268
                getChild( d_child_counter )->reset( p, d_tgt, qi );
1594
              }else{
1595
10356
                d_child_counter = -1;
1596
              }
1597
            }else{
1598
24118
              success = true;
1599
            }
1600
          }
1601
265563
        }else if( d_n.getKind()==EQUAL ){
1602
          //construct match based on both children
1603
232611
          if( d_child_counter%2==0 ){
1604
176828
            if( getChild( 0 )->getNextMatch( p, qi ) ){
1605
92871
              d_child_counter++;
1606
92871
              getChild( 1 )->reset( p, d_child_counter==1, qi );
1607
            }else{
1608
83957
              if( d_child_counter==0 ){
1609
42029
                d_child_counter = 2;
1610
42029
                getChild( 0 )->reset( p, !d_tgt, qi );
1611
              }else{
1612
41928
                d_child_counter = -1;
1613
              }
1614
            }
1615
          }
1616
232611
          if( d_child_counter>=0 && d_child_counter%2==1 ){
1617
148654
            if( getChild( 1 )->getNextMatch( p, qi ) ){
1618
56012
              success = true;
1619
            }else{
1620
92642
              d_child_counter--;
1621
            }
1622
          }
1623
32952
        }else if( d_n.getKind()==ITE ){
1624
29683
          if( d_child_counter%2==0 ){
1625
19015
            int index1 = d_child_counter==4 ? 1 : 0;
1626
19015
            if( getChild( index1 )->getNextMatch( p, qi ) ){
1627
13953
              d_child_counter++;
1628
13953
              getChild( d_child_counter==5 ? 2 : (d_tgt==(d_child_counter==1) ? 1 : 2) )->reset( p, d_tgt, qi );
1629
            }else{
1630
5062
              if (d_child_counter == 4)
1631
              {
1632
1682
                d_child_counter = -1;
1633
              }else{
1634
3380
                d_child_counter +=2;
1635
3380
                getChild( d_child_counter==2 ? 0 : 1 )->reset( p, d_child_counter==2 ? !d_tgt : d_tgt, qi );
1636
              }
1637
            }
1638
          }
1639
29683
          if( d_child_counter>=0 && d_child_counter%2==1 ){
1640
24621
            int index2 = d_child_counter==5 ? 2 : (d_tgt==(d_child_counter==1) ? 1 : 2);
1641
24621
            if( getChild( index2 )->getNextMatch( p, qi ) ){
1642
10730
              success = true;
1643
            }else{
1644
13891
              d_child_counter--;
1645
            }
1646
          }
1647
3269
        }else if( d_n.getKind()==FORALL ){
1648
3269
          if( getChild( d_child_counter )->getNextMatch( p, qi ) ){
1649
321
            success = true;
1650
          }else{
1651
2948
            d_child_counter = -1;
1652
          }
1653
        }
1654
      }
1655
359390
        d_wasSet = success;
1656
359390
      Debug("qcf-match") << "    ...finished construct match for " << d_n << ", success = " << success << std::endl;
1657
359390
      return success;
1658
    }
1659
  }
1660
24390
  Debug("qcf-match") << "    ...already finished for " << d_n << std::endl;
1661
24390
  return false;
1662
}
1663
1664
2596591
bool MatchGen::doMatching( QuantConflictFind * p, QuantInfo * qi ) {
1665
2596591
  if( !d_qn.empty() ){
1666
2117848
    if( d_qn[0]==NULL ){
1667
353391
      d_qn.clear();
1668
353391
      return true;
1669
    }else{
1670
1764457
      Assert(d_type == typ_var);
1671
1764457
      Assert(d_qni_size > 0);
1672
      bool invalidMatch;
1673
7302417
      do {
1674
9066874
        invalidMatch = false;
1675
9066874
        Debug("qcf-match-debug") << "       Do matching " << d_n << " " << d_qn.size() << " " << d_qni.size() << std::endl;
1676
9066874
        if( d_qn.size()==d_qni.size()+1 ) {
1677
4321394
          int index = (int)d_qni.size();
1678
          //initialize
1679
8642788
          TNode val;
1680
4321394
          std::map< int, int >::iterator itv = d_qni_var_num.find( index );
1681
4321394
          if( itv!=d_qni_var_num.end() ){
1682
            //get the representative variable this variable is equal to
1683
4038364
            int repVar = qi->getCurrentRepVar( itv->second );
1684
4038364
            Debug("qcf-match-debug") << "       Match " << index << " is a variable " << itv->second << ", which is repVar " << repVar << std::endl;
1685
            //get the value the rep variable
1686
            //std::map< int, TNode >::iterator itm = qi->d_match.find( repVar );
1687
4038364
            if( !qi->d_match[repVar].isNull() ){
1688
2537719
              val = qi->d_match[repVar];
1689
2537719
              Debug("qcf-match-debug") << "       Variable is already bound to " << val << std::endl;
1690
            }else{
1691
              //binding a variable
1692
1500645
              d_qni_bound[index] = repVar;
1693
              std::map<TNode, TNodeTrie>::iterator it =
1694
1500645
                  d_qn[index]->d_data.begin();
1695
1500645
              if( it != d_qn[index]->d_data.end() ) {
1696
1500645
                d_qni.push_back( it );
1697
                //set the match
1698
1500645
                if( it->first.getType().isComparableTo( qi->d_var_types[repVar] ) && qi->setMatch( p, d_qni_bound[index], it->first, true, true ) ){
1699
1375600
                  Debug("qcf-match-debug") << "       Binding variable" << std::endl;
1700
1375600
                  if( d_qn.size()<d_qni_size ){
1701
644401
                    d_qn.push_back( &it->second );
1702
                  }
1703
                }else{
1704
125045
                  Debug("qcf-match") << "       Binding variable, currently fail." << std::endl;
1705
125045
                  invalidMatch = true;
1706
                }
1707
              }else{
1708
                Debug("qcf-match-debug") << "       Binding variable, fail, no more variables to bind" << std::endl;
1709
                d_qn.pop_back();
1710
              }
1711
            }
1712
          }else{
1713
283030
            Debug("qcf-match-debug") << "       Match " << index << " is ground term" << std::endl;
1714
283030
            Assert(d_qni_gterm.find(index) != d_qni_gterm.end());
1715
283030
            val = d_qni_gterm[index];
1716
283030
            Assert(!val.isNull());
1717
          }
1718
4321394
          if( !val.isNull() ){
1719
5641498
            Node valr = p->getRepresentative(val);
1720
            //constrained by val
1721
            std::map<TNode, TNodeTrie>::iterator it =
1722
2820749
                d_qn[index]->d_data.find(valr);
1723
2820749
            if( it!=d_qn[index]->d_data.end() ){
1724
1260794
              Debug("qcf-match-debug") << "       Match" << std::endl;
1725
1260794
              d_qni.push_back( it );
1726
1260794
              if( d_qn.size()<d_qni_size ){
1727
1166913
                d_qn.push_back( &it->second );
1728
              }
1729
            }else{
1730
1559955
              Debug("qcf-match-debug") << "       Failed to match" << std::endl;
1731
1559955
              d_qn.pop_back();
1732
            }
1733
          }
1734
        }else{
1735
4745480
          Assert(d_qn.size() == d_qni.size());
1736
4745480
          int index = d_qni.size()-1;
1737
          //increment if binding this variable
1738
4745480
          bool success = false;
1739
4745480
          std::map< int, int >::iterator itb = d_qni_bound.find( index );
1740
4745480
          if( itb!=d_qni_bound.end() ){
1741
3490826
            d_qni[index]++;
1742
3490826
            if( d_qni[index]!=d_qn[index]->d_data.end() ){
1743
1994279
              success = true;
1744
1994279
              if( qi->setMatch( p, itb->second, d_qni[index]->first, true, true ) ){
1745
1903161
                Debug("qcf-match-debug") << "       Bind next variable" << std::endl;
1746
1903161
                if( d_qn.size()<d_qni_size ){
1747
1735646
                  d_qn.push_back( &d_qni[index]->second );
1748
                }
1749
              }else{
1750
91118
                Debug("qcf-match-debug") << "       Bind next variable, currently fail" << std::endl;
1751
91118
                invalidMatch = true;
1752
              }
1753
            }else{
1754
1496547
              qi->unsetMatch( p, itb->second );
1755
1496547
              qi->d_match_term[ itb->second ] = TNode::null();
1756
1496547
              Debug("qcf-match-debug") << "       Bind next variable, no more variables to bind" << std::endl;
1757
            }
1758
          }else{
1759
            //TODO : if it equal to something else, also try that
1760
          }
1761
          //if not incrementing, move to next
1762
4745480
          if( !success ){
1763
2751201
            d_qn.pop_back();
1764
2751201
            d_qni.pop_back();
1765
          }
1766
        }
1767
9066874
      }while( ( !d_qn.empty() && d_qni.size()!=d_qni_size ) || invalidMatch );
1768
1764457
      if( d_qni.size()==d_qni_size ){
1769
        //Assert( !d_qni[d_qni.size()-1]->second.d_data.empty() );
1770
        //Debug("qcf-match-debug") << "       We matched " << d_qni[d_qni.size()-1]->second.d_children.begin()->first << std::endl;
1771
992595
        Assert(!d_qni[d_qni.size() - 1]->second.d_data.empty());
1772
1985190
        TNode t = d_qni[d_qni.size()-1]->second.d_data.begin()->first;
1773
992595
        Debug("qcf-match-debug") << "       " << d_n << " matched " << t << std::endl;
1774
992595
        qi->d_match_term[d_qni_var_num[0]] = t;
1775
        //set the match terms
1776
2996403
        for( std::map< int, int >::iterator it = d_qni_bound.begin(); it != d_qni_bound.end(); ++it ){
1777
2003808
          Debug("qcf-match-debug") << "       position " << it->first << " bounded " << it->second << " / " << qi->d_q[0].getNumChildren() << std::endl;
1778
          //if( it->second<(int)qi->d_q[0].getNumChildren() ){   //if it is an actual variable, we are interested in knowing the actual term
1779
2003808
          if( it->first>0 ){
1780
1548646
            Assert(!qi->d_match[it->second].isNull());
1781
1548646
            Assert(p->areEqual(t[it->first - 1], qi->d_match[it->second]));
1782
1548646
            qi->d_match_term[it->second] = t[it->first-1];
1783
          }
1784
          //}
1785
        }
1786
      }
1787
    }
1788
  }
1789
2243200
  return !d_qn.empty();
1790
}
1791
1792
7257980
void MatchGen::debugPrintType( const char * c, short typ, bool isTrace ) {
1793
7257980
  if( isTrace ){
1794
157775
    switch( typ ){
1795
8530
    case typ_invalid: Trace(c) << "invalid";break;
1796
85
    case typ_ground: Trace(c) << "ground";break;
1797
30140
    case typ_eq: Trace(c) << "eq";break;
1798
18059
    case typ_pred: Trace(c) << "pred";break;
1799
21486
    case typ_formula: Trace(c) << "formula";break;
1800
78594
    case typ_var: Trace(c) << "var";break;
1801
164
    case typ_bool_var: Trace(c) << "bool_var";break;
1802
    }
1803
  }else{
1804
7100205
    switch( typ ){
1805
    case typ_invalid: Debug(c) << "invalid";break;
1806
496
    case typ_ground: Debug(c) << "ground";break;
1807
1413303
    case typ_eq: Debug(c) << "eq";break;
1808
935702
    case typ_pred: Debug(c) << "pred";break;
1809
575944
    case typ_formula: Debug(c) << "formula";break;
1810
4160457
    case typ_var: Debug(c) << "var";break;
1811
8350
    case typ_bool_var: Debug(c) << "bool_var";break;
1812
    }
1813
  }
1814
7257980
}
1815
1816
5747
void MatchGen::setInvalid() {
1817
5747
  d_type = typ_invalid;
1818
5747
  d_children.clear();
1819
5747
}
1820
1821
259995
bool MatchGen::isHandledBoolConnective( TNode n ) {
1822
259995
  return TermUtil::isBoolConnectiveTerm( n ) && n.getKind()!=SEP_STAR;
1823
}
1824
1825
2042553
bool MatchGen::isHandledUfTerm( TNode n ) {
1826
  //return n.getKind()==APPLY_UF || n.getKind()==STORE || n.getKind()==SELECT ||
1827
  //       n.getKind()==APPLY_CONSTRUCTOR || n.getKind()==APPLY_SELECTOR_TOTAL || n.getKind()==APPLY_TESTER;
1828
  //TODO : treat APPLY_TESTER as a T-constraint instead of matching (currently leads to overabundance of instantiations)
1829
  //return inst::Trigger::isAtomicTriggerKind( n.getKind() ) && ( !options::qcfTConstraint() || n.getKind()!=APPLY_TESTER );
1830
2042553
  return inst::TriggerTermInfo::isAtomicTriggerKind(n.getKind());
1831
}
1832
1833
901450
Node MatchGen::getMatchOperator( QuantConflictFind * p, Node n ) {
1834
901450
  if( isHandledUfTerm( n ) ){
1835
901450
    return p->getTermDatabase()->getMatchOperator( n );
1836
  }else{
1837
    return Node::null();
1838
  }
1839
}
1840
1841
bool MatchGen::isHandled( TNode n ) {
1842
  if (n.getKind() != BOUND_VARIABLE && expr::hasBoundVar(n))
1843
  {
1844
    if( !isHandledBoolConnective( n ) && !isHandledUfTerm( n ) && n.getKind()!=EQUAL && n.getKind()!=ITE ){
1845
      return false;
1846
    }
1847
    for( unsigned i=0; i<n.getNumChildren(); i++ ){
1848
      if( !isHandled( n[i] ) ){
1849
        return false;
1850
      }
1851
    }
1852
  }
1853
  return true;
1854
}
1855
1856
4965
QuantConflictFind::QuantConflictFind(Env& env,
1857
                                     QuantifiersState& qs,
1858
                                     QuantifiersInferenceManager& qim,
1859
                                     QuantifiersRegistry& qr,
1860
4965
                                     TermRegistry& tr)
1861
    : QuantifiersModule(env, qs, qim, qr, tr),
1862
      d_conflict(context(), false),
1863
      d_true(NodeManager::currentNM()->mkConst<bool>(true)),
1864
      d_false(NodeManager::currentNM()->mkConst<bool>(false)),
1865
4965
      d_effort(EFFORT_INVALID)
1866
{
1867
4965
}
1868
1869
//-------------------------------------------------- registration
1870
1871
23741
void QuantConflictFind::registerQuantifier( Node q ) {
1872
23741
  if (d_qreg.hasOwnership(q, this))
1873
  {
1874
22094
    d_quants.push_back( q );
1875
22094
    d_quant_id[q] = d_quants.size();
1876
22094
    if( Trace.isOn("qcf-qregister") ){
1877
      Trace("qcf-qregister") << "Register ";
1878
      debugPrintQuant( "qcf-qregister", q );
1879
      Trace("qcf-qregister") << " : " << q << std::endl;
1880
    }
1881
    //make QcfNode structure
1882
22094
    Trace("qcf-qregister") << "- Get relevant equality/disequality pairs, calculate flattening..." << std::endl;
1883
22094
    d_qinfo[q].initialize( this, q, q[1] );
1884
1885
    //debug print
1886
22094
    if( Trace.isOn("qcf-qregister") ){
1887
      Trace("qcf-qregister") << "- Flattened structure is :" << std::endl;
1888
      Trace("qcf-qregister") << "    ";
1889
      debugPrintQuantBody( "qcf-qregister", q, q[1] );
1890
      Trace("qcf-qregister") << std::endl;
1891
      if( d_qinfo[q].d_vars.size()>q[0].getNumChildren() ){
1892
        Trace("qcf-qregister") << "  with additional constraints : " << std::endl;
1893
        for( unsigned j=q[0].getNumChildren(); j<d_qinfo[q].d_vars.size(); j++ ){
1894
          Trace("qcf-qregister") << "    ?x" << j << " = ";
1895
          debugPrintQuantBody( "qcf-qregister", q, d_qinfo[q].d_vars[j], false );
1896
          Trace("qcf-qregister") << std::endl;
1897
        }
1898
      }
1899
      Trace("qcf-qregister") << "Done registering quantifier." << std::endl;
1900
    }
1901
  }
1902
23741
}
1903
1904
482
bool QuantConflictFind::areMatchEqual( TNode n1, TNode n2 ) {
1905
  //if( d_effort==QuantConflictFind::effort_mc ){
1906
  //  return n1==n2 || !areDisequal( n1, n2 );
1907
  //}else{
1908
482
  return n1==n2;
1909
  //}
1910
}
1911
1912
15
bool QuantConflictFind::areMatchDisequal( TNode n1, TNode n2 ) {
1913
  // if( d_effort==QuantConflictFind::Effort::Conflict ){
1914
  //  return areDisequal( n1, n2 );
1915
  //}else{
1916
15
  return n1!=n2;
1917
  //}
1918
}
1919
1920
//-------------------------------------------------- check function
1921
1922
60405
bool QuantConflictFind::needsCheck( Theory::Effort level ) {
1923
60405
  bool performCheck = false;
1924
60405
  if( options::quantConflictFind() && !d_conflict ){
1925
60401
    if( level==Theory::EFFORT_LAST_CALL ){
1926
4198
      performCheck = options::qcfWhenMode() == options::QcfWhenMode::LAST_CALL;
1927
56203
    }else if( level==Theory::EFFORT_FULL ){
1928
16724
      performCheck = options::qcfWhenMode() == options::QcfWhenMode::DEFAULT;
1929
39479
    }else if( level==Theory::EFFORT_STANDARD ){
1930
39479
      performCheck = options::qcfWhenMode() == options::QcfWhenMode::STD;
1931
    }
1932
  }
1933
60405
  return performCheck;
1934
}
1935
1936
20924
void QuantConflictFind::reset_round( Theory::Effort level ) {
1937
20924
  Trace("qcf-check") << "QuantConflictFind::reset_round" << std::endl;
1938
20924
  Trace("qcf-check") << "Compute relevant equivalence classes..." << std::endl;
1939
20924
  d_eqcs.clear();
1940
1941
20924
  eq::EqClassesIterator eqcs_i = eq::EqClassesIterator(getEqualityEngine());
1942
20924
  TermDb* tdb = getTermDatabase();
1943
2342656
  while (!eqcs_i.isFinished())
1944
  {
1945
2321732
    Node r = (*eqcs_i);
1946
1160866
    if (tdb->hasTermCurrent(r))
1947
    {
1948
2321732
      TypeNode rtn = r.getType();
1949
1160866
      if (!options::cegqi() || !TermUtil::hasInstConstAttr(r))
1950
      {
1951
1106187
        d_eqcs[rtn].push_back(r);
1952
      }
1953
    }
1954
1160866
    ++eqcs_i;
1955
  }
1956
20924
}
1957
1958
127016
void QuantConflictFind::setIrrelevantFunction( TNode f ) {
1959
127016
  if( d_irr_func.find( f )==d_irr_func.end() ){
1960
19067
    d_irr_func[f] = true;
1961
19067
    std::map< TNode, std::vector< Node > >::iterator it = d_func_rel_dom.find( f );
1962
19067
    if( it != d_func_rel_dom.end()){
1963
76242
      for( unsigned j=0; j<it->second.size(); j++ ){
1964
61866
        d_irr_quant[it->second[j]] = true;
1965
      }
1966
    }
1967
  }
1968
127016
}
1969
1970
namespace {
1971
1972
// Returns the beginning of a range of efforts. The range can be iterated
1973
// through as unsigned using operator++.
1974
16724
inline QuantConflictFind::Effort QcfEffortStart() {
1975
16724
  return QuantConflictFind::EFFORT_CONFLICT;
1976
}
1977
1978
// Returns the beginning of a range of efforts. The value returned is included
1979
// in the range.
1980
16724
inline QuantConflictFind::Effort QcfEffortEnd() {
1981
16724
  return options::qcfMode() == options::QcfMode::PROP_EQ
1982
16724
             ? QuantConflictFind::EFFORT_PROP_EQ
1983
16724
             : QuantConflictFind::EFFORT_CONFLICT;
1984
}
1985
1986
}  // namespace
1987
1988
/** check */
1989
61641
void QuantConflictFind::check(Theory::Effort level, QEffort quant_e)
1990
{
1991
78365
  CodeTimer codeTimer(d_qstate.getStats().d_qcf_time);
1992
61641
  if (quant_e != QEFFORT_CONFLICT)
1993
  {
1994
44917
    return;
1995
  }
1996
16724
  Trace("qcf-check") << "QCF : check : " << level << std::endl;
1997
16724
  if (d_conflict)
1998
  {
1999
    Trace("qcf-check2") << "QCF : finished check : already in conflict."
2000
                        << std::endl;
2001
    if (level >= Theory::EFFORT_FULL)
2002
    {
2003
      Trace("qcf-warn") << "ALREADY IN CONFLICT? " << level << std::endl;
2004
    }
2005
    return;
2006
  }
2007
16724
  unsigned addedLemmas = 0;
2008
16724
  ++(d_statistics.d_inst_rounds);
2009
16724
  double clSet = 0;
2010
16724
  int prevEt = 0;
2011
16724
  if (Trace.isOn("qcf-engine"))
2012
  {
2013
    prevEt = d_statistics.d_entailment_checks.get();
2014
    clSet = double(clock()) / double(CLOCKS_PER_SEC);
2015
    Trace("qcf-engine") << "---Conflict Find Engine Round, effort = " << level
2016
                        << "---" << std::endl;
2017
  }
2018
2019
  // reset the round-specific information
2020
16724
  d_irr_func.clear();
2021
16724
  d_irr_quant.clear();
2022
2023
16724
  if (Trace.isOn("qcf-debug"))
2024
  {
2025
    Trace("qcf-debug") << std::endl;
2026
    debugPrint("qcf-debug");
2027
    Trace("qcf-debug") << std::endl;
2028
  }
2029
16724
  bool isConflict = false;
2030
16724
  FirstOrderModel* fm = d_treg.getModel();
2031
16724
  unsigned nquant = fm->getNumAssertedQuantifiers();
2032
  // for each effort level (find conflict, find propagating)
2033
47933
  for (unsigned e = QcfEffortStart(), end = QcfEffortEnd(); e <= end; ++e)
2034
  {
2035
    // set the effort (data member for convienence of access)
2036
32563
    d_effort = static_cast<Effort>(e);
2037
65126
    Trace("qcf-check") << "Checking quantified formulas at effort " << e
2038
32563
                       << "..." << std::endl;
2039
    // for each quantified formula
2040
358237
    for (unsigned i = 0; i < nquant; i++)
2041
    {
2042
652233
      Node q = fm->getAssertedQuantifier(i, true);
2043
979677
      if (d_qreg.hasOwnership(q, this)
2044
624262
          && d_irr_quant.find(q) == d_irr_quant.end()
2045
1205472
          && fm->isQuantifierActive(q))
2046
      {
2047
        // check this quantified formula
2048
225743
        checkQuantifiedFormula(q, isConflict, addedLemmas);
2049
225743
        if (d_conflict || d_qstate.isInConflict())
2050
        {
2051
885
          break;
2052
        }
2053
      }
2054
    }
2055
    // We are done if we added a lemma, or discovered a conflict in another
2056
    // way. An example of the latter case is when two disequal congruent terms
2057
    // are discovered during term indexing.
2058
32563
    if (addedLemmas > 0 || d_qstate.isInConflict())
2059
    {
2060
1354
      break;
2061
    }
2062
  }
2063
16724
  if (isConflict)
2064
  {
2065
    d_conflict.set(true);
2066
  }
2067
16724
  if (Trace.isOn("qcf-engine"))
2068
  {
2069
    double clSet2 = double(clock()) / double(CLOCKS_PER_SEC);
2070
    Trace("qcf-engine") << "Finished conflict find engine, time = "
2071
                        << (clSet2 - clSet);
2072
    if (addedLemmas > 0)
2073
    {
2074
      Trace("qcf-engine") << ", effort = "
2075
                          << (d_effort == EFFORT_CONFLICT
2076
                                  ? "conflict"
2077
                                  : (d_effort == EFFORT_PROP_EQ ? "prop_eq"
2078
                                                                : "mc"));
2079
      Trace("qcf-engine") << ", addedLemmas = " << addedLemmas;
2080
    }
2081
    Trace("qcf-engine") << std::endl;
2082
    int currEt = d_statistics.d_entailment_checks.get();
2083
    if (currEt != prevEt)
2084
    {
2085
      Trace("qcf-engine") << "  Entailment checks = " << (currEt - prevEt)
2086
                          << std::endl;
2087
    }
2088
  }
2089
16724
  Trace("qcf-check2") << "QCF : finished check : " << level << std::endl;
2090
}
2091
2092
225743
void QuantConflictFind::checkQuantifiedFormula(Node q,
2093
                                               bool& isConflict,
2094
                                               unsigned& addedLemmas)
2095
{
2096
225743
  QuantInfo* qi = &d_qinfo[q];
2097
225743
  Assert(d_qinfo.find(q) != d_qinfo.end());
2098
225743
  if (!qi->matchGeneratorIsValid())
2099
  {
2100
    // quantified formula is not properly set up for matching
2101
105996
    return;
2102
  }
2103
119747
  if (Trace.isOn("qcf-check"))
2104
  {
2105
    Trace("qcf-check") << "Check quantified formula ";
2106
    debugPrintQuant("qcf-check", q);
2107
    Trace("qcf-check") << " : " << q << "..." << std::endl;
2108
  }
2109
2110
119747
  Trace("qcf-check-debug") << "Reset round..." << std::endl;
2111
119747
  if (!qi->reset_round(this))
2112
  {
2113
    // it is typically the case that another conflict (e.g. in the term
2114
    // database) was discovered if we fail here.
2115
    return;
2116
  }
2117
  // try to make a matches making the body false or propagating
2118
119747
  Trace("qcf-check-debug") << "Get next match..." << std::endl;
2119
119747
  Instantiate* qinst = d_qim.getInstantiate();
2120
606439
  while (qi->getNextMatch(this))
2121
  {
2122
244504
    if (d_qstate.isInConflict())
2123
    {
2124
8
      Trace("qcf-check") << "   ... Quantifiers engine discovered conflict, ";
2125
16
      Trace("qcf-check") << "probably related to disequal congruent terms in "
2126
8
                            "master equality engine"
2127
8
                         << std::endl;
2128
1166
      return;
2129
    }
2130
244496
    if (Trace.isOn("qcf-inst"))
2131
    {
2132
      Trace("qcf-inst") << "*** Produced match at effort " << d_effort << " : "
2133
                        << std::endl;
2134
      qi->debugPrintMatch("qcf-inst");
2135
      Trace("qcf-inst") << std::endl;
2136
    }
2137
    // check whether internal match constraints are satisfied
2138
290119
    if (qi->isMatchSpurious(this))
2139
    {
2140
91246
      Trace("qcf-inst") << "   ... Spurious (match is inconsistent)"
2141
45623
                        << std::endl;
2142
91378
      continue;
2143
    }
2144
    // check whether match can be completed
2145
396464
    std::vector<int> assigned;
2146
199005
    if (!qi->completeMatch(this, assigned))
2147
    {
2148
264
      Trace("qcf-inst") << "   ... Spurious (cannot assign unassigned vars)"
2149
132
                        << std::endl;
2150
132
      continue;
2151
    }
2152
    // check whether the match is spurious according to (T-)entailment checks
2153
396332
    std::vector<Node> terms;
2154
198741
    qi->getMatch(terms);
2155
198741
    bool tcs = qi->isTConstraintSpurious(this, terms);
2156
198741
    if (tcs)
2157
    {
2158
392124
      Trace("qcf-inst") << "   ... Spurious (match is T-inconsistent)"
2159
196062
                        << std::endl;
2160
    }
2161
    else
2162
    {
2163
      // otherwise, we have a conflict/propagating instance
2164
      // for debugging
2165
2679
      if (Debug.isOn("qcf-check-inst"))
2166
      {
2167
        Node inst = qinst->getInstantiation(q, terms);
2168
        Debug("qcf-check-inst")
2169
            << "Check instantiation " << inst << "..." << std::endl;
2170
        Assert(!getTermDatabase()->isEntailed(inst, true));
2171
        Assert(getTermDatabase()->isEntailed(inst, false)
2172
               || d_effort > EFFORT_CONFLICT);
2173
      }
2174
      // Process the lemma: either add an instantiation or specific lemmas
2175
      // constructed during the isTConstraintSpurious call, or both.
2176
5358
      InferenceId id = (d_effort == EFFORT_CONFLICT
2177
2679
                            ? InferenceId::QUANTIFIERS_INST_CBQI_CONFLICT
2178
                            : InferenceId::QUANTIFIERS_INST_CBQI_PROP);
2179
2679
      if (!qinst->addInstantiation(q, terms, id))
2180
      {
2181
276
        Trace("qcf-inst") << "   ... Failed to add instantiation" << std::endl;
2182
        // This should only happen if the algorithm generates the same
2183
        // propagating instance twice this round. In this case, return
2184
        // to avoid exponential behavior.
2185
276
        return;
2186
      }
2187
2403
      Trace("qcf-check") << "   ... Added instantiation" << std::endl;
2188
2403
      if (Trace.isOn("qcf-inst"))
2189
      {
2190
        Trace("qcf-inst") << "*** Was from effort " << d_effort << " : "
2191
                          << std::endl;
2192
        qi->debugPrintMatch("qcf-inst");
2193
        Trace("qcf-inst") << std::endl;
2194
      }
2195
2403
      ++addedLemmas;
2196
2403
      if (d_effort == EFFORT_CONFLICT)
2197
      {
2198
        // mark relevant: this ensures that quantified formula q is
2199
        // checked first on the next round. This is an optimization to
2200
        // ensure that quantified formulas that are more likely to have
2201
        // conflicting instances are checked earlier.
2202
874
        d_treg.getModel()->markRelevant(q);
2203
874
        if (options::qcfAllConflict())
2204
        {
2205
          isConflict = true;
2206
        }
2207
        else
2208
        {
2209
874
          d_conflict.set(true);
2210
        }
2211
874
        return;
2212
      }
2213
1529
      else if (d_effort == EFFORT_PROP_EQ)
2214
      {
2215
1529
        d_treg.getModel()->markRelevant(q);
2216
      }
2217
    }
2218
    // clean up assigned
2219
197591
    qi->revertMatch(this, assigned);
2220
197591
    d_tempCache.clear();
2221
  }
2222
118589
  Trace("qcf-check") << "Done, conflict = " << d_conflict << std::endl;
2223
}
2224
2225
//-------------------------------------------------- debugging
2226
2227
void QuantConflictFind::debugPrint( const char * c ) {
2228
  //print the equivalance classes
2229
  Trace(c) << "----------EQ classes" << std::endl;
2230
  eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( getEqualityEngine() );
2231
  while( !eqcs_i.isFinished() ){
2232
    Node n = (*eqcs_i);
2233
    //if( !n.getType().isInteger() ){
2234
    Trace(c) << "  - " << n << " : {";
2235
    eq::EqClassIterator eqc_i = eq::EqClassIterator( n, getEqualityEngine() );
2236
    bool pr = false;
2237
    while( !eqc_i.isFinished() ){
2238
      Node nn = (*eqc_i);
2239
      if( nn.getKind()!=EQUAL && nn!=n ){
2240
        Trace(c) << (pr ? "," : "" ) << " " << nn;
2241
        pr = true;
2242
      }
2243
      ++eqc_i;
2244
    }
2245
    Trace(c) << (pr ? " " : "" ) << "}" << std::endl;
2246
    ++eqcs_i;
2247
  }
2248
}
2249
2250
void QuantConflictFind::debugPrintQuant( const char * c, Node q ) {
2251
  Trace(c) << "Q" << d_quant_id[q];
2252
}
2253
2254
void QuantConflictFind::debugPrintQuantBody( const char * c, Node q, Node n, bool doVarNum ) {
2255
  if( n.getNumChildren()==0 ){
2256
    Trace(c) << n;
2257
  }else if( doVarNum && d_qinfo[q].d_var_num.find( n )!=d_qinfo[q].d_var_num.end() ){
2258
    Trace(c) << "?x" << d_qinfo[q].d_var_num[n];
2259
  }else{
2260
    Trace(c) << "(";
2261
    if( n.getKind()==APPLY_UF ){
2262
      Trace(c) << n.getOperator();
2263
    }else{
2264
      Trace(c) << n.getKind();
2265
    }
2266
    for( unsigned i=0; i<n.getNumChildren(); i++ ){
2267
      Trace(c) << " ";
2268
      debugPrintQuantBody( c, q, n[i] );
2269
    }
2270
    Trace(c) << ")";
2271
  }
2272
}
2273
2274
4965
QuantConflictFind::Statistics::Statistics()
2275
    : d_inst_rounds(
2276
9930
        smtStatisticsRegistry().registerInt("QuantConflictFind::Inst_Rounds")),
2277
4965
      d_entailment_checks(smtStatisticsRegistry().registerInt(
2278
9930
          "QuantConflictFind::Entailment_Checks"))
2279
{
2280
4965
}
2281
2282
8
TNode QuantConflictFind::getZero( Kind k ) {
2283
8
  std::map< Kind, Node >::iterator it = d_zero.find( k );
2284
8
  if( it==d_zero.end() ){
2285
16
    Node nn;
2286
8
    if( k==PLUS ){
2287
4
      nn = NodeManager::currentNM()->mkConst( Rational(0) );
2288
    }
2289
8
    d_zero[k] = nn;
2290
8
    return nn;
2291
  }else{
2292
    return it->second;
2293
  }
2294
}
2295
2296
std::ostream& operator<<(std::ostream& os, const QuantConflictFind::Effort& e) {
2297
  switch (e) {
2298
    case QuantConflictFind::EFFORT_INVALID:
2299
      os << "Invalid";
2300
      break;
2301
    case QuantConflictFind::EFFORT_CONFLICT:
2302
      os << "Conflict";
2303
      break;
2304
    case QuantConflictFind::EFFORT_PROP_EQ:
2305
      os << "PropEq";
2306
      break;
2307
  }
2308
  return os;
2309
}
2310
2311
1729
bool QuantConflictFind::isPropagatingInstance(Node n) const
2312
{
2313
3458
  std::unordered_set<TNode> visited;
2314
3458
  std::vector<TNode> visit;
2315
3458
  TNode cur;
2316
1729
  visit.push_back(n);
2317
3823
  do
2318
  {
2319
5552
    cur = visit.back();
2320
5552
    visit.pop_back();
2321
5552
    if (visited.find(cur) == visited.end())
2322
    {
2323
5499
      visited.insert(cur);
2324
5499
      Kind ck = cur.getKind();
2325
5499
      if (ck == FORALL)
2326
      {
2327
        // do nothing
2328
      }
2329
5400
      else if (TermUtil::isBoolConnective(ck))
2330
      {
2331
5827
        for (TNode cc : cur)
2332
        {
2333
3823
          visit.push_back(cc);
2334
        }
2335
      }
2336
3396
      else if (!getEqualityEngine()->hasTerm(cur))
2337
      {
2338
        Trace("qcf-instance-check-debug")
2339
            << "...not propagating instance because of " << cur << " " << ck
2340
            << std::endl;
2341
        return false;
2342
      }
2343
    }
2344
5552
  } while (!visit.empty());
2345
1729
  return true;
2346
}
2347
2348
}  // namespace quantifiers
2349
}  // namespace theory
2350
29577
}  // namespace cvc5