GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/fmf/full_model_check.cpp Lines: 749 799 93.7 %
Date: 2021-05-22 Branches: 1631 3239 50.4 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Mathias Preiner, Aina Niemetz
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8
 * in the top-level source directory and their institutional affiliations.
9
 * All rights reserved.  See the file COPYING in the top-level source
10
 * directory for licensing information.
11
 * ****************************************************************************
12
 *
13
 * Implementation of full model check class.
14
 */
15
16
#include "theory/quantifiers/fmf/full_model_check.h"
17
18
#include "expr/skolem_manager.h"
19
#include "options/quantifiers_options.h"
20
#include "options/theory_options.h"
21
#include "options/uf_options.h"
22
#include "theory/quantifiers/first_order_model.h"
23
#include "theory/quantifiers/fmf/bounded_integers.h"
24
#include "theory/quantifiers/instantiate.h"
25
#include "theory/quantifiers/quant_rep_bound_ext.h"
26
#include "theory/quantifiers/quantifiers_inference_manager.h"
27
#include "theory/quantifiers/quantifiers_registry.h"
28
#include "theory/quantifiers/quantifiers_state.h"
29
#include "theory/quantifiers/term_database.h"
30
#include "theory/quantifiers/term_util.h"
31
#include "theory/rewriter.h"
32
33
using namespace cvc5::kind;
34
using namespace cvc5::context;
35
36
namespace cvc5 {
37
namespace theory {
38
namespace quantifiers {
39
namespace fmcheck {
40
41
202362
struct ModelBasisArgSort
42
{
43
  std::vector< Node > d_terms;
44
  // number of arguments that are model-basis terms
45
  std::unordered_map<Node, unsigned> d_mba_count;
46
63131
  bool operator() (int i,int j) {
47
63131
    return (d_mba_count[d_terms[i]] < d_mba_count[d_terms[j]]);
48
  }
49
};
50
51
434613
bool EntryTrie::hasGeneralization( FirstOrderModelFmc * m, Node c, int index ) {
52
434613
  if (index==(int)c.getNumChildren()) {
53
19136
    return d_data!=-1;
54
  }else{
55
830954
    TypeNode tn = c[index].getType();
56
830954
    Node st = m->getStar(tn);
57
415477
    if(d_child.find(st)!=d_child.end()) {
58
42057
      if( d_child[st].hasGeneralization(m, c, index+1) ){
59
17215
        return true;
60
      }
61
    }
62
398262
    if( c[index]!=st && d_child.find( c[index] )!=d_child.end() ){
63
57753
      if( d_child[ c[index] ].hasGeneralization(m, c, index+1) ){
64
22940
        return true;
65
      }
66
    }
67
375322
    if( c[index].getType().isSort() ){
68
      //for star: check if all children are defined and have generalizations
69
322836
      if( c[index]==st ){     ///options::fmfFmcCoverSimplify()
70
        //check if all children exist and are complete
71
        unsigned num_child_def =
72
184460
            d_child.size() - (d_child.find(st) != d_child.end() ? 1 : 0);
73
184460
        if (num_child_def == m->getRepSet()->getNumRepresentatives(tn))
74
        {
75
8939
          bool complete = true;
76
15425
          for ( std::map<Node,EntryTrie>::iterator it = d_child.begin(); it != d_child.end(); ++it ){
77
12896
            if( !m->isStar(it->first) ){
78
12408
              if( !it->second.hasGeneralization(m, c, index+1) ){
79
6410
                complete = false;
80
6410
                break;
81
              }
82
            }
83
          }
84
8939
          if( complete ){
85
2529
            return true;
86
          }
87
        }
88
      }
89
    }
90
91
372793
    return false;
92
  }
93
}
94
95
132124
int EntryTrie::getGeneralizationIndex( FirstOrderModelFmc * m, std::vector<Node> & inst, int index ) {
96
132124
  Debug("fmc-entry-trie") << "Get generalization index " << inst.size() << " " << index << std::endl;
97
132124
  if (index==(int)inst.size()) {
98
38020
    return d_data;
99
  }else{
100
94104
    int minIndex = -1;
101
188208
    Node st = m->getStar(inst[index].getType());
102
94104
    if (d_child.find(st) != d_child.end())
103
    {
104
87528
      minIndex = d_child[st].getGeneralizationIndex(m, inst, index + 1);
105
    }
106
188208
    Node cc = inst[index];
107
94104
    if (cc != st && d_child.find(cc) != d_child.end())
108
    {
109
12984
      int gindex = d_child[cc].getGeneralizationIndex(m, inst, index + 1);
110
12984
      if (minIndex == -1 || (gindex != -1 && gindex < minIndex))
111
      {
112
8937
        minIndex = gindex;
113
      }
114
    }
115
94104
    return minIndex;
116
  }
117
}
118
119
801058
void EntryTrie::addEntry( FirstOrderModelFmc * m, Node c, Node v, int data, int index ) {
120
801058
  if (index==(int)c.getNumChildren()) {
121
306728
    if(d_data==-1) {
122
306728
      d_data = data;
123
    }
124
  }
125
  else {
126
494330
    d_child[ c[index] ].addEntry(m,c,v,data,index+1);
127
494330
    if( d_complete==0 ){
128
      d_complete = -1;
129
    }
130
  }
131
801058
}
132
133
349558
void EntryTrie::getEntries( FirstOrderModelFmc * m, Node c, std::vector<int> & compat, std::vector<int> & gen, int index, bool is_gen ) {
134
349558
  if (index==(int)c.getNumChildren()) {
135
84017
    if( d_data!=-1) {
136
84017
      if( is_gen ){
137
78271
        gen.push_back(d_data);
138
      }
139
84017
      compat.push_back(d_data);
140
    }
141
  }else{
142
265541
    if (m->isStar(c[index])) {
143
273559
      for ( std::map<Node,EntryTrie>::iterator it = d_child.begin(); it != d_child.end(); ++it ){
144
125596
        it->second.getEntries(m, c, compat, gen, index+1, is_gen );
145
      }
146
    }else{
147
235156
      Node st = m->getStar(c[index].getType());
148
117578
      if(d_child.find(st)!=d_child.end()) {
149
7464
        d_child[st].getEntries(m, c, compat, gen, index+1, false);
150
      }
151
117578
      if( d_child.find( c[index] )!=d_child.end() ){
152
29749
        d_child[ c[index] ].getEntries(m, c, compat, gen, index+1, is_gen);
153
      }
154
    }
155
156
  }
157
349558
}
158
159
322395
bool Def::addEntry( FirstOrderModelFmc * m, Node c, Node v) {
160
322395
  if (d_et.hasGeneralization(m, c)) {
161
15667
    Trace("fmc-debug") << "Already has generalization, skip." << std::endl;
162
15667
    return false;
163
  }
164
306728
  int newIndex = (int)d_cond.size();
165
306728
  if (!d_has_simplified) {
166
373498
    std::vector<int> compat;
167
373498
    std::vector<int> gen;
168
186749
    d_et.getEntries(m, c, compat, gen);
169
270766
    for( unsigned i=0; i<compat.size(); i++) {
170
84017
      if( d_status[compat[i]]==status_unk ){
171
75317
        if( d_value[compat[i]]!=v ){
172
47827
          d_status[compat[i]] = status_non_redundant;
173
        }
174
      }
175
    }
176
265020
    for( unsigned i=0; i<gen.size(); i++) {
177
78271
      if( d_status[gen[i]]==status_unk ){
178
23840
        if( d_value[gen[i]]==v ){
179
23840
          d_status[gen[i]] = status_redundant;
180
        }
181
      }
182
    }
183
186749
    d_status.push_back( status_unk );
184
  }
185
306728
  d_et.addEntry(m, c, v, newIndex);
186
306728
  d_cond.push_back(c);
187
306728
  d_value.push_back(v);
188
306728
  return true;
189
}
190
191
2147
Node Def::evaluate( FirstOrderModelFmc * m, std::vector<Node>& inst ) {
192
2147
  int gindex = d_et.getGeneralizationIndex(m, inst);
193
2147
  if (gindex!=-1) {
194
2143
    return d_value[gindex];
195
  }else{
196
4
    Trace("fmc-warn") << "Warning : evaluation came up null!" << std::endl;
197
4
    return Node::null();
198
  }
199
}
200
201
29465
int Def::getGeneralizationIndex( FirstOrderModelFmc * m, std::vector<Node>& inst ) {
202
29465
  return d_et.getGeneralizationIndex(m, inst);
203
}
204
205
66179
void Def::basic_simplify( FirstOrderModelFmc * m ) {
206
66179
  d_has_simplified = true;
207
132358
  std::vector< Node > cond;
208
66179
  cond.insert( cond.end(), d_cond.begin(), d_cond.end() );
209
66179
  d_cond.clear();
210
132358
  std::vector< Node > value;
211
66179
  value.insert( value.end(), d_value.begin(), d_value.end() );
212
66179
  d_value.clear();
213
66179
  d_et.reset();
214
209998
  for (unsigned i=0; i<d_status.size(); i++) {
215
143819
    if( d_status[i]!=status_redundant ){
216
119979
      addEntry(m, cond[i], value[i]);
217
    }
218
  }
219
66179
  d_status.clear();
220
66179
}
221
222
59531
void Def::simplify(FullModelChecker * mc, FirstOrderModelFmc * m) {
223
59531
  Trace("fmc-simplify") << "Simplify definition, #cond = " << d_cond.size() << std::endl;
224
59531
  basic_simplify( m );
225
59531
  Trace("fmc-simplify") << "post-basic simplify, #cond = " << d_cond.size() << std::endl;
226
227
  //check if the last entry is not all star, if so, we can make the last entry all stars
228
59531
  if( !d_cond.empty() ){
229
59531
    bool last_all_stars = true;
230
119062
    Node cc = d_cond[d_cond.size()-1];
231
139439
    for( unsigned i=0; i<cc.getNumChildren(); i++ ){
232
86556
      if (!m->isStar(cc[i]))
233
      {
234
6648
        last_all_stars = false;
235
6648
        break;
236
      }
237
    }
238
59531
    if( !last_all_stars ){
239
6648
      Trace("fmc-cover-simplify") << "Need to modify last entry to be all stars." << std::endl;
240
6648
      Trace("fmc-cover-simplify") << "Before: " << std::endl;
241
6648
      debugPrint("fmc-cover-simplify",Node::null(), mc);
242
6648
      Trace("fmc-cover-simplify") << std::endl;
243
13296
      std::vector< Node > cond;
244
6648
      cond.insert( cond.end(), d_cond.begin(), d_cond.end() );
245
6648
      d_cond.clear();
246
13296
      std::vector< Node > value;
247
6648
      value.insert( value.end(), d_value.begin(), d_value.end() );
248
6648
      d_value.clear();
249
6648
      d_et.reset();
250
6648
      d_has_simplified = false;
251
      //change the last to all star
252
13296
      std::vector< Node > nc;
253
6648
      nc.push_back( cc.getOperator() );
254
17756
      for( unsigned j=0; j< cc.getNumChildren(); j++){
255
11108
        nc.push_back(m->getStar(cc[j].getType()));
256
      }
257
6648
      cond[cond.size()-1] = NodeManager::currentNM()->mkNode( APPLY_UF, nc );
258
      //re-add the entries
259
19401
      for (unsigned i=0; i<cond.size(); i++) {
260
12753
        addEntry(m, cond[i], value[i]);
261
      }
262
6648
      Trace("fmc-cover-simplify") << "Finished re-adding entries." << std::endl;
263
6648
      basic_simplify( m );
264
6648
      Trace("fmc-cover-simplify") << "After: " << std::endl;
265
6648
      debugPrint("fmc-cover-simplify",Node::null(), mc);
266
6648
      Trace("fmc-cover-simplify") << std::endl;
267
    }
268
  }
269
59531
  Trace("fmc-simplify") << "finish simplify, #cond = " << d_cond.size() << std::endl;
270
59531
}
271
272
213084
void Def::debugPrint(const char * tr, Node op, FullModelChecker * m) {
273
213084
  if (!op.isNull()) {
274
42673
    Trace(tr) << "Model for " << op << " : " << std::endl;
275
  }
276
609150
  for( unsigned i=0; i<d_cond.size(); i++) {
277
    //print the condition
278
396066
    if (!op.isNull()) {
279
123513
      Trace(tr) << op;
280
    }
281
396066
    m->debugPrintCond(tr, d_cond[i], true);
282
396066
    Trace(tr) << " -> ";
283
396066
    m->debugPrint(tr, d_value[i]);
284
396066
    Trace(tr) << std::endl;
285
  }
286
213084
}
287
288
1341
FullModelChecker::FullModelChecker(QuantifiersState& qs,
289
                                   QuantifiersInferenceManager& qim,
290
                                   QuantifiersRegistry& qr,
291
1341
                                   TermRegistry& tr)
292
1341
    : QModelBuilder(qs, qim, qr, tr), d_fm(new FirstOrderModelFmc(qs, qr, tr))
293
{
294
1341
  d_true = NodeManager::currentNM()->mkConst(true);
295
1341
  d_false = NodeManager::currentNM()->mkConst(false);
296
1341
}
297
298
1341
void FullModelChecker::finishInit() { d_model = d_fm.get(); }
299
300
1945
bool FullModelChecker::preProcessBuildModel(TheoryModel* m) {
301
  //standard pre-process
302
1945
  if( !preProcessBuildModelStd( m ) ){
303
    return false;
304
  }
305
306
1945
  Trace("fmc") << "---Full Model Check preprocess() " << std::endl;
307
1945
  d_preinitialized_eqc.clear();
308
1945
  d_preinitialized_types.clear();
309
  //traverse equality engine
310
1945
  eq::EqClassesIterator eqcs_i = eq::EqClassesIterator(m->getEqualityEngine());
311
103039
  while( !eqcs_i.isFinished() ){
312
101094
    Node r = *eqcs_i;
313
101094
    TypeNode tr = r.getType();
314
50547
    d_preinitialized_eqc[tr] = r;
315
50547
    ++eqcs_i;
316
  }
317
318
  //must ensure model basis terms exists in model for each relevant type
319
1945
  Trace("fmc") << "preInitialize types..." << std::endl;
320
1945
  d_fm->initialize();
321
9638
  for (std::pair<const Node, Def*>& mp : d_fm->d_models)
322
  {
323
15386
    Node op = mp.first;
324
7693
    Trace("fmc") << "preInitialize types for " << op << std::endl;
325
15386
    TypeNode tno = op.getType();
326
27965
    for( unsigned i=0; i<tno.getNumChildren(); i++) {
327
20272
      Trace("fmc") << "preInitializeType " << tno[i] << std::endl;
328
20272
      preInitializeType(m, tno[i]);
329
20272
      Trace("fmc") << "finished preInitializeType " << tno[i] << std::endl;
330
    }
331
  }
332
1945
  Trace("fmc") << "Finish preInitialize types" << std::endl;
333
  //do not have to introduce terms for sorts of domains of quantified formulas if we are allowed to assume empty sorts
334
11912
  for (unsigned i = 0, nquant = d_fm->getNumAssertedQuantifiers(); i < nquant;
335
       i++)
336
  {
337
19823
    Node q = d_fm->getAssertedQuantifier(i);
338
9967
    registerQuantifiedFormula(q);
339
9967
    if (!isHandled(q))
340
    {
341
111
      continue;
342
    }
343
    // make sure all types are set
344
24614
    for (const Node& v : q[0])
345
    {
346
14758
      preInitializeType(m, v.getType());
347
    }
348
  }
349
1945
  return true;
350
}
351
352
1945
bool FullModelChecker::processBuildModel(TheoryModel* m){
353
1945
  if (!m->areFunctionValuesEnabled())
354
  {
355
    // nothing to do if no functions
356
    return true;
357
  }
358
1945
  FirstOrderModelFmc* fm = d_fm.get();
359
1945
  Trace("fmc") << "---Full Model Check reset() " << std::endl;
360
1945
  d_quant_models.clear();
361
1945
  d_rep_ids.clear();
362
1945
  d_star_insts.clear();
363
  //process representatives
364
1945
  RepSet* rs = m->getRepSetPtr();
365
8965
  for (std::map<TypeNode, std::vector<Node> >::iterator it =
366
1945
           rs->d_type_reps.begin();
367
10910
       it != rs->d_type_reps.end();
368
       ++it)
369
  {
370
8965
    if( it->first.isSort() ){
371
2355
      Trace("fmc") << "Cardinality( " << it->first << " )" << " = " << it->second.size() << std::endl;
372
6923
      for( size_t a=0; a<it->second.size(); a++ ){
373
9136
        Node r = m->getRepresentative(it->second[a]);
374
4568
        if( Trace.isOn("fmc-model-debug") ){
375
          std::vector< Node > eqc;
376
          d_qstate.getEquivalenceClass(r, eqc);
377
          Trace("fmc-model-debug") << "   " << (it->second[a]==r);
378
          Trace("fmc-model-debug") << " : " << it->second[a] << " : " << r << " : ";
379
          //Trace("fmc-model-debug") << r2 << " : " << ir << " : ";
380
          Trace("fmc-model-debug") << " {";
381
          for( size_t i=0; i<eqc.size(); i++ ){
382
            Trace("fmc-model-debug") << eqc[i] << ", ";
383
          }
384
          Trace("fmc-model-debug") << "}" << std::endl;
385
        }
386
4568
        d_rep_ids[it->first][r] = (int)a;
387
      }
388
2355
      Trace("fmc-model-debug") << std::endl;
389
    }
390
  }
391
392
  //now, make models
393
9638
  for (std::pair<const Node, Def*>& fmm : d_fm->d_models)
394
  {
395
15386
    Node op = fmm.first;
396
    //reset the model
397
7693
    d_fm->d_models[op]->reset();
398
399
15386
    std::vector< Node > add_conds;
400
15386
    std::vector< Node > add_values;
401
7693
    bool needsDefault = true;
402
7693
    if (m->hasUfTerms(op))
403
    {
404
6212
      const std::vector<Node>& uft = m->getUfTerms(op);
405
12424
      Trace("fmc-model-debug")
406
6212
          << uft.size() << " model values for " << op << " ... " << std::endl;
407
45489
      for (const Node& n : uft)
408
      {
409
        // only consider unique up to congruence (in model equality engine)?
410
39277
        add_conds.push_back( n );
411
39277
        add_values.push_back( n );
412
78554
        Node r = m->getRepresentative(n);
413
39277
        Trace("fmc-model-debug") << n << " -> " << r << std::endl;
414
      }
415
    }else{
416
1481
      Trace("fmc-model-debug") << "No model values for " << op << " ... " << std::endl;
417
    }
418
7693
    Trace("fmc-model-debug") << std::endl;
419
    //possibly get default
420
7693
    if( needsDefault ){
421
15386
      Node nmb = d_fm->getModelBasisOpTerm(op);
422
      //add default value if necessary
423
7693
      if (m->hasTerm(nmb))
424
      {
425
4257
        Trace("fmc-model-debug") << "Add default " << nmb << std::endl;
426
4257
        add_conds.push_back( nmb );
427
4257
        add_values.push_back( nmb );
428
      }else{
429
6872
        Node vmb = getSomeDomainElement(d_fm.get(), nmb.getType());
430
3436
        Trace("fmc-model-debug") << "Add default to default representative " << nmb << " ";
431
6872
        Trace("fmc-model-debug")
432
6872
            << m->getRepSet()->getNumRepresentatives(nmb.getType())
433
3436
            << std::endl;
434
3436
        add_conds.push_back( nmb );
435
3436
        add_values.push_back( vmb );
436
      }
437
    }
438
439
15386
    std::vector< Node > conds;
440
15386
    std::vector< Node > values;
441
15386
    std::vector< Node > entry_conds;
442
    //get the entries for the model
443
54663
    for( size_t i=0; i<add_conds.size(); i++ ){
444
93940
      Node c = add_conds[i];
445
93940
      Node v = add_values[i];
446
93940
      Trace("fmc-model-debug")
447
46970
          << "Add cond/value : " << c << " -> " << v << std::endl;
448
93940
      std::vector< Node > children;
449
93940
      std::vector< Node > entry_children;
450
46970
      children.push_back(op);
451
46970
      entry_children.push_back(op);
452
46970
      bool hasNonStar = false;
453
130327
      for (const Node& ci : c)
454
      {
455
166714
        Node ri = fm->getRepresentative(ci);
456
83357
        children.push_back(ri);
457
83357
        bool isStar = false;
458
83357
        if (fm->isModelBasisTerm(ri))
459
        {
460
22187
          ri = fm->getStar(ri.getType());
461
22187
          isStar = true;
462
        }
463
        else
464
        {
465
61170
          hasNonStar = true;
466
        }
467
83357
        if( !isStar && !ri.isConst() ){
468
          Trace("fmc-warn") << "Warning : model for " << op
469
                            << " has non-constant argument in model " << ri
470
                            << " (from " << ci << ")" << std::endl;
471
          Assert(false);
472
        }
473
83357
        entry_children.push_back(ri);
474
      }
475
93940
      Node n = NodeManager::currentNM()->mkNode( APPLY_UF, children );
476
93940
      Node nv = fm->getRepresentative( v );
477
93940
      Trace("fmc-model-debug")
478
46970
          << "Representative of " << v << " is " << nv << std::endl;
479
46970
      if( !nv.isConst() ){
480
        Trace("fmc-warn") << "Warning : model for " << op << " has non-constant value in model " << nv << std::endl;
481
        Assert(false);
482
      }
483
93940
      Node en = (useSimpleModels() && hasNonStar) ? n : NodeManager::currentNM()->mkNode( APPLY_UF, entry_children );
484
46970
      if( std::find(conds.begin(), conds.end(), n )==conds.end() ){
485
27073
        Trace("fmc-model-debug") << "- add " << n << " -> " << nv << " (entry is " << en << ")" << std::endl;
486
27073
        conds.push_back(n);
487
27073
        values.push_back(nv);
488
27073
        entry_conds.push_back(en);
489
      }
490
      else {
491
19897
        Trace("fmc-model-debug") << "Already have entry for : " << n << " -> " << nv << " (entry is " << en << ")" << std::endl;
492
      }
493
    }
494
495
496
    //sort based on # default arguments
497
15386
    std::vector< int > indices;
498
15386
    ModelBasisArgSort mbas;
499
34766
    for (int i=0; i<(int)conds.size(); i++) {
500
27073
      mbas.d_terms.push_back(conds[i]);
501
27073
      mbas.d_mba_count[conds[i]] = fm->getModelBasisArg(conds[i]);
502
27073
      indices.push_back(i);
503
    }
504
7693
    std::sort( indices.begin(), indices.end(), mbas );
505
506
34766
    for (int i=0; i<(int)indices.size(); i++) {
507
27073
      fm->d_models[op]->addEntry(fm, entry_conds[indices[i]], values[indices[i]]);
508
    }
509
510
7693
    Trace("fmc-model-simplify") << "Before simplification : " << std::endl;
511
7693
    fm->d_models[op]->debugPrint("fmc-model-simplify", op, this);
512
7693
    Trace("fmc-model-simplify") << std::endl;
513
514
7693
    Trace("fmc-model-simplify") << "Simplifying " << op << "..." << std::endl;
515
7693
    fm->d_models[op]->simplify( this, fm );
516
517
7693
    fm->d_models[op]->debugPrint("fmc-model", op, this);
518
7693
    Trace("fmc-model") << std::endl;
519
520
    //for debugging
521
    /*
522
    for( size_t i=0; i<fm->d_uf_terms[op].size(); i++ ){
523
      std::vector< Node > inst;
524
      for( unsigned j=0; j<fm->d_uf_terms[op][i].getNumChildren(); j++ ){
525
        Node r = fm->getRepresentative( fm->d_uf_terms[op][i][j] );
526
        inst.push_back( r );
527
      }
528
      Node ev = fm->d_models[op]->evaluate( fm, inst );
529
      Trace("fmc-model-debug") << ".....Checking eval( " <<
530
    fm->d_uf_terms[op][i] << " ) = " << ev << std::endl; AlwaysAssert(
531
    fm->areEqual( ev, fm->d_uf_terms[op][i] ) );
532
    }
533
    */
534
  }
535
1945
  Assert(d_addedLemmas == 0);
536
537
  //make function values
538
9638
  for( std::map<Node, Def * >::iterator it = fm->d_models.begin(); it != fm->d_models.end(); ++it ){
539
15386
    Node f_def = getFunctionValue( fm, it->first, "$x" );
540
7693
    m->assignFunctionDefinition( it->first, f_def );
541
  }
542
1945
  return TheoryEngineModelBuilder::processBuildModel( m );
543
}
544
545
35030
void FullModelChecker::preInitializeType(TheoryModel* m, TypeNode tn)
546
{
547
35030
  if( d_preinitialized_types.find( tn )==d_preinitialized_types.end() ){
548
5238
    d_preinitialized_types[tn] = true;
549
5238
    if (tn.isFirstClass())
550
    {
551
5232
      Trace("fmc") << "Get model basis term " << tn << "..." << std::endl;
552
10464
      Node mb = d_fm->getModelBasisTerm(tn);
553
5232
      Trace("fmc") << "...return " << mb << std::endl;
554
      // if the model basis term does not exist in the model,
555
      // either add it directly to the model's equality engine if no other terms
556
      // of this type exist, or otherwise assert that it is equal to the first
557
      // equivalence class of its type.
558
5232
      if (!m->hasTerm(mb) && !mb.isConst())
559
      {
560
549
        std::map<TypeNode, Node>::iterator itpe = d_preinitialized_eqc.find(tn);
561
549
        if (itpe == d_preinitialized_eqc.end())
562
        {
563
406
          Trace("fmc") << "...add model basis term to EE of model " << mb << " "
564
203
                       << tn << std::endl;
565
203
          m->getEqualityEngine()->addTerm(mb);
566
        }
567
        else
568
        {
569
692
          Trace("fmc") << "...add model basis eqc equality to model " << mb
570
346
                       << " == " << itpe->second << " " << tn << std::endl;
571
346
          bool ret = m->assertEquality(mb, itpe->second, true);
572
346
          AlwaysAssert(ret);
573
        }
574
      }
575
    }
576
  }
577
35030
}
578
579
400134
void FullModelChecker::debugPrintCond(const char * tr, Node n, bool dispStar) {
580
400134
  Trace(tr) << "(";
581
1018893
  for( unsigned j=0; j<n.getNumChildren(); j++) {
582
618759
    if( j>0 ) Trace(tr) << ", ";
583
618759
    debugPrint(tr, n[j], dispStar);
584
  }
585
400134
  Trace(tr) << ")";
586
400134
}
587
588
1558443
void FullModelChecker::debugPrint(const char * tr, Node n, bool dispStar) {
589
1558443
  if( n.isNull() ){
590
14750
    Trace(tr) << "null";
591
  }
592
1543693
  else if (FirstOrderModelFmc::isStar(n) && dispStar)
593
  {
594
693612
    Trace(tr) << "*";
595
  }
596
  else
597
  {
598
1700162
    TypeNode tn = n.getType();
599
850081
    if( tn.isSort() && d_rep_ids.find(tn)!=d_rep_ids.end() ){
600
418571
      if (d_rep_ids[tn].find(n)!=d_rep_ids[tn].end()) {
601
393585
        Trace(tr) << d_rep_ids[tn][n];
602
      }else{
603
24986
        Trace(tr) << n;
604
      }
605
    }else{
606
431510
      Trace(tr) << n;
607
    }
608
  }
609
1558443
}
610
611
612
11989
int FullModelChecker::doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort ) {
613
11989
  Trace("fmc") << "Full model check " << f << ", effort = " << effort << "..." << std::endl;
614
  // register the quantifier
615
11989
  registerQuantifiedFormula(f);
616
11989
  Assert(!d_qstate.isInConflict());
617
  // we do not do model-based quantifier instantiation if the option
618
  // disables it, or if the quantified formula has an unhandled type.
619
11989
  if (!optUseModel() || !isHandled(f))
620
  {
621
    return 0;
622
  }
623
11989
  FirstOrderModelFmc* fmfmc = static_cast<FirstOrderModelFmc*>(fm);
624
11989
  if (effort == 0)
625
  {
626
9578
    if (options::mbqiMode() == options::MbqiMode::NONE)
627
    {
628
      // just exhaustive instantiate
629
6356
      Node c = mkCondDefault(fmfmc, f);
630
3178
      d_quant_models[f].addEntry(fmfmc, c, d_false);
631
3178
      if (!exhaustiveInstantiate(fmfmc, f, c))
632
      {
633
22
        return 0;
634
      }
635
3156
      return 1;
636
    }
637
    // model check the quantifier
638
6400
    doCheck(fmfmc, f, d_quant_models[f], f[1]);
639
6400
    std::vector<Node>& mcond = d_quant_models[f].d_cond;
640
6400
    Trace("fmc") << "Definition for quantifier " << f << " is : " << std::endl;
641
6400
    Assert(!mcond.empty());
642
6400
    d_quant_models[f].debugPrint("fmc", Node::null(), this);
643
6400
    Trace("fmc") << std::endl;
644
645
    // consider all entries going to non-true
646
6400
    Instantiate* instq = d_qim.getInstantiate();
647
14842
    for (unsigned i = 0, msize = mcond.size(); i < msize; i++)
648
    {
649
8442
      if (d_quant_models[f].d_value[i] == d_true)
650
      {
651
        // already satisfied
652
11877
        continue;
653
      }
654
5016
      Trace("fmc-inst") << "Instantiate based on " << mcond[i] << "..."
655
2508
                        << std::endl;
656
2508
      bool hasStar = false;
657
5007
      std::vector<Node> inst;
658
6611
      for (unsigned j = 0, nchild = mcond[i].getNumChildren(); j < nchild; j++)
659
      {
660
4103
        if (fmfmc->isStar(mcond[i][j]))
661
        {
662
3140
          hasStar = true;
663
3140
          inst.push_back(fmfmc->getModelBasisTerm(mcond[i][j].getType()));
664
        }
665
        else
666
        {
667
963
          inst.push_back(mcond[i][j]);
668
        }
669
      }
670
2508
      bool addInst = true;
671
2508
      if (hasStar)
672
      {
673
        // try obvious (specified by inst)
674
4294
        Node ev = d_quant_models[f].evaluate(fmfmc, inst);
675
2147
        if (ev == d_true)
676
        {
677
9
          addInst = false;
678
18
          Trace("fmc-debug")
679
9
              << "...do not instantiate, evaluation was " << ev << std::endl;
680
        }
681
      }
682
      else
683
      {
684
        // for debugging
685
361
        if (Trace.isOn("fmc-test-inst"))
686
        {
687
          Node ev = d_quant_models[f].evaluate(fmfmc, inst);
688
          if (ev == d_true)
689
          {
690
            CVC5Message() << "WARNING: instantiation was true! " << f << " "
691
                          << mcond[i] << std::endl;
692
            AlwaysAssert(false);
693
          }
694
          else
695
          {
696
            Trace("fmc-test-inst")
697
                << "...instantiation evaluated to false." << std::endl;
698
          }
699
        }
700
      }
701
2517
      if (!addInst)
702
      {
703
18
        Trace("fmc-debug-inst")
704
9
            << "** Instantiation was already true." << std::endl;
705
        // might try it next effort level
706
9
        d_star_insts[f].push_back(i);
707
9
        continue;
708
      }
709
2499
      if (options::fmfBound())
710
      {
711
        std::vector<Node> cond;
712
        cond.push_back(d_quant_cond[f]);
713
        cond.insert(cond.end(), inst.begin(), inst.end());
714
        // need to do exhaustive instantiate algorithm to set things properly
715
        // (should only add one instance)
716
        Node c = mkCond(cond);
717
        unsigned prevInst = d_addedLemmas;
718
        exhaustiveInstantiate(fmfmc, f, c);
719
        if (d_addedLemmas == prevInst)
720
        {
721
          d_star_insts[f].push_back(i);
722
        }
723
        continue;
724
      }
725
      // just add the instance
726
2499
      d_triedLemmas++;
727
2499
      if (instq->addInstantiation(
728
              f, inst, InferenceId::QUANTIFIERS_INST_FMF_FMC, true))
729
      {
730
785
        Trace("fmc-debug-inst") << "** Added instantiation." << std::endl;
731
785
        d_addedLemmas++;
732
6707
        if (d_qstate.isInConflict() || options::fmfOneInstPerRound())
733
        {
734
          break;
735
        }
736
      }
737
      else
738
      {
739
3428
        Trace("fmc-debug-inst")
740
1714
            << "** Instantiation was duplicate." << std::endl;
741
        // might try it next effort level
742
1714
        d_star_insts[f].push_back(i);
743
      }
744
    }
745
6400
    return 1;
746
  }
747
  // Get the list of instantiation regions (described by "star entries" in the
748
  // definition) that were not tried at the previous effort level. For each
749
  // of these, we add one instantiation.
750
2411
  std::vector<Node>& mcond = d_quant_models[f].d_cond;
751
2411
  if (!d_star_insts[f].empty())
752
  {
753
807
    if (Trace.isOn("fmc-exh"))
754
    {
755
      Trace("fmc-exh") << "Exhaustive instantiate " << f << std::endl;
756
      Trace("fmc-exh") << "Definition was : " << std::endl;
757
      d_quant_models[f].debugPrint("fmc-exh", Node::null(), this);
758
      Trace("fmc-exh") << std::endl;
759
    }
760
1612
    Def temp;
761
    // simplify the exceptions?
762
1727
    for (int i = (d_star_insts[f].size() - 1); i >= 0; i--)
763
    {
764
      // get witness for d_star_insts[f][i]
765
922
      int j = d_star_insts[f][i];
766
922
      if (temp.addEntry(fmfmc, mcond[j], d_quant_models[f].d_value[j]))
767
      {
768
890
        if (!exhaustiveInstantiate(fmfmc, f, mcond[j]))
769
        {
770
          // something went wrong, resort to exhaustive instantiation
771
2
          return 0;
772
        }
773
      }
774
    }
775
  }
776
2409
  return 1;
777
}
778
779
/** Representative bound fmc entry
780
 *
781
 * This bound information corresponds to one
782
 * entry in a term definition (see terminology in
783
 * Chapter 5 of Finite Model Finding for
784
 * Satisfiability Modulo Theories thesis).
785
 * For example, a term definition for the body
786
 * of a quantified formula:
787
 *   forall xyz. P( x, y, z )
788
 * may be:
789
 *   ( 0, 0, 0 ) -> false
790
 *   ( *, 1, 2 ) -> false
791
 *   ( *, *, * ) -> true
792
 * Indicating that the quantified formula evaluates
793
 * to false in the current model for x=0, y=0, z=0,
794
 * or y=1, z=2 for any x, and evaluates to true
795
 * otherwise.
796
 * This class is used if we wish
797
 * to iterate over all values corresponding to one
798
 * of these entries. For example, for the second entry:
799
 *   (*, 1, 2 )
800
 * we iterate over all values of x, but only {1}
801
 * for y and {2} for z.
802
 */
803
class RepBoundFmcEntry : public QRepBoundExt
804
{
805
 public:
806
4068
  RepBoundFmcEntry(QuantifiersBoundInference& qbi,
807
                   Node e,
808
                   FirstOrderModelFmc* f)
809
4068
      : QRepBoundExt(qbi, f), d_entry(e), d_fm(f)
810
  {
811
4068
  }
812
4068
  ~RepBoundFmcEntry() {}
813
  /** set bound */
814
5683
  virtual RsiEnumType setBound(Node owner,
815
                               unsigned i,
816
                               std::vector<Node>& elements) override
817
  {
818
5683
    if (!d_fm->isStar(d_entry[i]))
819
    {
820
      // only need to consider the single point
821
276
      elements.push_back(d_entry[i]);
822
276
      return ENUM_DEFAULT;
823
    }
824
5407
    return QRepBoundExt::setBound(owner, i, elements);
825
  }
826
827
 private:
828
  /** the entry for this bound */
829
  Node d_entry;
830
  /** the model builder associated with this bound */
831
  FirstOrderModelFmc* d_fm;
832
};
833
834
4068
bool FullModelChecker::exhaustiveInstantiate(FirstOrderModelFmc* fm,
835
                                             Node f,
836
                                             Node c)
837
{
838
4068
  Trace("fmc-exh") << "----Exhaustive instantiate based on " << c << " ";
839
4068
  debugPrintCond("fmc-exh", c, true);
840
4068
  Trace("fmc-exh")<< std::endl;
841
4068
  QuantifiersBoundInference& qbi = d_qreg.getQuantifiersBoundInference();
842
8136
  RepBoundFmcEntry rbfe(qbi, c, fm);
843
8136
  RepSetIterator riter(fm->getRepSet(), &rbfe);
844
4068
  Trace("fmc-exh-debug") << "Set quantifier..." << std::endl;
845
  //initialize
846
4068
  if (riter.setQuantifier(f))
847
  {
848
4068
    Trace("fmc-exh-debug") << "Set element domains..." << std::endl;
849
4068
    int addedLemmas = 0;
850
    //now do full iteration
851
4068
    Instantiate* ie = d_qim.getInstantiate();
852
62998
    while( !riter.isFinished() ){
853
29465
      d_triedLemmas++;
854
29465
      Trace("fmc-exh-debug") << "Inst : ";
855
58930
      std::vector< Node > ev_inst;
856
58930
      std::vector< Node > inst;
857
103940
      for (unsigned i = 0; i < riter.getNumTerms(); i++)
858
      {
859
148950
        TypeNode tn = riter.getTypeOf(i);
860
        // if the type is not closed enumerable (see
861
        // TypeNode::isClosedEnumerable), then we must ensure that we are
862
        // using a term and not a value. This ensures that e.g. uninterpreted
863
        // constants do not appear in instantiations.
864
148950
        Node rr = riter.getCurrentTerm(i, !tn.isClosedEnumerable());
865
148950
        Node r = fm->getRepresentative(rr);
866
74475
        debugPrint("fmc-exh-debug", r);
867
74475
        Trace("fmc-exh-debug") << " (term : " << rr << ")";
868
74475
        ev_inst.push_back( r );
869
74475
        inst.push_back( rr );
870
      }
871
29465
      int ev_index = d_quant_models[f].getGeneralizationIndex(fm, ev_inst);
872
29465
      Trace("fmc-exh-debug") << ", index = " << ev_index << " / " << d_quant_models[f].d_value.size();
873
58930
      Node ev = ev_index==-1 ? Node::null() : d_quant_models[f].d_value[ev_index];
874
29465
      if (ev!=d_true) {
875
26647
        Trace("fmc-exh-debug") << ", add!";
876
        //add as instantiation
877
26647
        if (ie->addInstantiation(
878
                f, inst, InferenceId::QUANTIFIERS_INST_FMF_FMC_EXH, true))
879
        {
880
4869
          Trace("fmc-exh-debug")  << " ...success.";
881
4869
          addedLemmas++;
882
4869
          if (d_qstate.isInConflict() || options::fmfOneInstPerRound())
883
          {
884
            break;
885
          }
886
        }else{
887
21778
          Trace("fmc-exh-debug") << ", failed.";
888
        }
889
      }else{
890
2818
        Trace("fmc-exh-debug") << ", already true";
891
      }
892
29465
      Trace("fmc-exh-debug") << std::endl;
893
29465
      int index = riter.increment();
894
29465
      Trace("fmc-exh-debug") << "Incremented index " << index << std::endl;
895
29465
      if( !riter.isFinished() ){
896
78885
        if (index >= 0 && riter.d_index[index] > 0 && addedLemmas > 0
897
32876
            && riter.d_enum_type[index] == ENUM_CUSTOM)
898
        {
899
2816
          Trace("fmc-exh-debug")
900
1408
              << "Since this is a custom enumeration, skip to the next..."
901
1408
              << std::endl;
902
1408
          riter.incrementAtIndex(index - 1);
903
        }
904
      }
905
    }
906
4068
    d_addedLemmas += addedLemmas;
907
4068
    Trace("fmc-exh") << "----Finished Exhaustive instantiate, lemmas = " << addedLemmas << ", incomplete=" << riter.isIncomplete() << std::endl;
908
4068
    return addedLemmas>0 || !riter.isIncomplete();
909
  }else{
910
    Trace("fmc-exh") << "----Finished Exhaustive instantiate, failed." << std::endl;
911
    return !riter.isIncomplete();
912
  }
913
}
914
915
98877
void FullModelChecker::doCheck(FirstOrderModelFmc * fm, Node f, Def & d, Node n ) {
916
98877
  Trace("fmc-debug") << "Check " << n << " " << n.getKind() << std::endl;
917
  //first check if it is a bounding literal
918
98877
  if( n.hasAttribute(BoundIntLitAttribute()) ){
919
    Trace("fmc-debug") << "It is a bounding literal, polarity = " << n.getAttribute(BoundIntLitAttribute()) << std::endl;
920
    d.addEntry(fm, mkCondDefault(fm, f), n.getAttribute(BoundIntLitAttribute())==1 ? d_false : d_true );
921
98877
  }else if( n.getKind() == kind::BOUND_VARIABLE ){
922
25026
    Trace("fmc-debug") << "Add default entry..." << std::endl;
923
25026
    d.addEntry(fm, mkCondDefault(fm, f), n);
924
  }
925
73851
  else if( n.getKind() == kind::NOT ){
926
    //just do directly
927
8177
    doCheck( fm, f, d, n[0] );
928
8177
    doNegate( d );
929
  }
930
65674
  else if( n.getKind() == kind::FORALL ){
931
2975
    d.addEntry(fm, mkCondDefault(fm, f), Node::null());
932
  }
933
62699
  else if( n.getType().isArray() ){
934
    //Trace("fmc-warn") << "WARNING : ARRAYS : Can't process base array " << r << std::endl;
935
    //Trace("fmc-warn") << "          Default value was : " << odefaultValue << std::endl;
936
    //Trace("fmc-debug") << "Can't process base array " << r << std::endl;
937
    //can't process this array
938
452
    d.reset();
939
452
    d.addEntry(fm, mkCondDefault(fm, f), Node::null());
940
  }
941
62247
  else if( n.getNumChildren()==0 ){
942
20818
    Node r = n;
943
10409
    if( !n.isConst() ){
944
6043
      if( !fm->hasTerm(n) ){
945
203
        r = getSomeDomainElement(fm, n.getType() );
946
      }
947
6043
      r = fm->getRepresentative( r );
948
    }
949
10409
    Trace("fmc-debug") << "Add constant entry..." << std::endl;
950
10409
    d.addEntry(fm, mkCondDefault(fm, f), r);
951
  }
952
  else{
953
103676
    std::vector< int > var_ch;
954
103676
    std::vector< Def > children;
955
136138
    for( int i=0; i<(int)n.getNumChildren(); i++) {
956
168600
      Def dc;
957
84300
      doCheck(fm, f, dc, n[i]);
958
84300
      children.push_back(dc);
959
84300
      if( n[i].getKind() == kind::BOUND_VARIABLE ){
960
25022
        var_ch.push_back(i);
961
      }
962
    }
963
964
51838
    if( n.getKind()==APPLY_UF ){
965
27287
      Trace("fmc-debug") << "Do uninterpreted compose " << n << std::endl;
966
      //uninterpreted compose
967
27287
      doUninterpretedCompose( fm, f, d, n.getOperator(), children );
968
      /*
969
    } else if( n.getKind()==SELECT ){
970
      Trace("fmc-debug") << "Do select compose " << n << std::endl;
971
      std::vector< Def > children2;
972
      children2.push_back( children[1] );
973
      std::vector< Node > cond;
974
      mkCondDefaultVec(fm, f, cond);
975
      std::vector< Node > val;
976
      doUninterpretedCompose(fm, f, d, children[0], children2, 0, cond, val );
977
      */
978
    } else {
979
24551
      if( !var_ch.empty() ){
980
1441
        if( n.getKind()==EQUAL && !n[0].getType().isBoolean() ){
981
818
          if( var_ch.size()==2 ){
982
364
            Trace("fmc-debug") << "Do variable equality " << n << std::endl;
983
364
            doVariableEquality( fm, f, d, n );
984
          }else{
985
454
            Trace("fmc-debug") << "Do variable relation " << n << std::endl;
986
454
            doVariableRelation( fm, f, d, var_ch[0]==0 ? children[1] : children[0], var_ch[0]==0 ? n[0] : n[1] );
987
          }
988
        }else{
989
623
          Trace("fmc-warn") << "Don't know how to check " << n << std::endl;
990
623
          d.addEntry(fm, mkCondDefault(fm, f), Node::null());
991
        }
992
      }else{
993
23110
        Trace("fmc-debug") << "Do interpreted compose " << n << std::endl;
994
46220
        std::vector< Node > cond;
995
23110
        mkCondDefaultVec(fm, f, cond);
996
46220
        std::vector< Node > val;
997
        //interpreted compose
998
23110
        doInterpretedCompose( fm, f, d, n, children, 0, cond, val );
999
      }
1000
    }
1001
51838
    Trace("fmc-debug") << "Simplify the definition..." << std::endl;
1002
51838
    d.debugPrint("fmc-debug", Node::null(), this);
1003
51838
    d.simplify(this, fm);
1004
51838
    Trace("fmc-debug") << "Done simplifying" << std::endl;
1005
  }
1006
98877
  Trace("fmc-debug") << "Definition for " << n << " is : " << std::endl;
1007
98877
  d.debugPrint("fmc-debug", Node::null(), this);
1008
98877
  Trace("fmc-debug") << std::endl;
1009
98877
}
1010
1011
8177
void FullModelChecker::doNegate( Def & dc ) {
1012
19077
  for (unsigned i=0; i<dc.d_cond.size(); i++) {
1013
21800
    Node v = dc.d_value[i];
1014
10900
    if (!v.isNull())
1015
    {
1016
      // In the case that the value is not-constant, we cannot reason about
1017
      // its value (since the range of this must be a constant or variable).
1018
      // In particular, returning null here is important if we have (not x)
1019
      // where x is a bound variable.
1020
7835
      dc.d_value[i] =
1021
15670
          v == d_true ? d_false : (v == d_false ? d_true : Node::null());
1022
    }
1023
  }
1024
8177
}
1025
1026
364
void FullModelChecker::doVariableEquality( FirstOrderModelFmc * fm, Node f, Def & d, Node eq ) {
1027
728
  std::vector<Node> cond;
1028
364
  mkCondDefaultVec(fm, f, cond);
1029
364
  if (eq[0]==eq[1]){
1030
    d.addEntry(fm, mkCond(cond), d_true);
1031
  }else{
1032
728
    TypeNode tn = eq[0].getType();
1033
364
    if( tn.isSort() ){
1034
364
      int j = fm->getVariableId(f, eq[0]);
1035
364
      int k = fm->getVariableId(f, eq[1]);
1036
364
      const RepSet* rs = fm->getRepSet();
1037
364
      if (!rs->hasType(tn))
1038
      {
1039
        getSomeDomainElement( fm, tn );  //to verify the type is initialized
1040
      }
1041
364
      unsigned nreps = rs->getNumRepresentatives(tn);
1042
1004
      for (unsigned i = 0; i < nreps; i++)
1043
      {
1044
1280
        Node r = fm->getRepresentative(rs->getRepresentative(tn, i));
1045
640
        cond[j+1] = r;
1046
640
        cond[k+1] = r;
1047
640
        d.addEntry( fm, mkCond(cond), d_true);
1048
      }
1049
364
      d.addEntry( fm, mkCondDefault(fm, f), d_false);
1050
    }else{
1051
      d.addEntry( fm, mkCondDefault(fm, f), Node::null());
1052
    }
1053
  }
1054
364
}
1055
1056
454
void FullModelChecker::doVariableRelation( FirstOrderModelFmc * fm, Node f, Def & d, Def & dc, Node v) {
1057
454
  int j = fm->getVariableId(f, v);
1058
1038
  for (unsigned i=0; i<dc.d_cond.size(); i++) {
1059
1168
    Node val = dc.d_value[i];
1060
584
    if( val.isNull() ){
1061
9
      d.addEntry( fm, dc.d_cond[i], val);
1062
    }else{
1063
575
      if( dc.d_cond[i][j]!=val ){
1064
453
        if (fm->isStar(dc.d_cond[i][j])) {
1065
890
          std::vector<Node> cond;
1066
445
          mkCondVec(dc.d_cond[i],cond);
1067
445
          cond[j+1] = val;
1068
445
          d.addEntry(fm, mkCond(cond), d_true);
1069
445
          cond[j+1] = fm->getStar(val.getType());
1070
445
          d.addEntry(fm, mkCond(cond), d_false);
1071
        }else{
1072
8
          d.addEntry( fm, dc.d_cond[i], d_false);
1073
        }
1074
      }else{
1075
122
        d.addEntry( fm, dc.d_cond[i], d_true);
1076
      }
1077
    }
1078
  }
1079
454
}
1080
1081
27287
void FullModelChecker::doUninterpretedCompose( FirstOrderModelFmc * fm, Node f, Def & d, Node op, std::vector< Def > & dc ) {
1082
27287
  Trace("fmc-uf-debug") << "Definition : " << std::endl;
1083
27287
  fm->d_models[op]->debugPrint("fmc-uf-debug", op, this);
1084
27287
  Trace("fmc-uf-debug") << std::endl;
1085
1086
54574
  std::vector< Node > cond;
1087
27287
  mkCondDefaultVec(fm, f, cond);
1088
54574
  std::vector< Node > val;
1089
27287
  doUninterpretedCompose( fm, f, d, *fm->d_models[op], dc, 0, cond, val);
1090
27287
}
1091
1092
74339
void FullModelChecker::doUninterpretedCompose( FirstOrderModelFmc * fm, Node f, Def & d,
1093
                                               Def & df, std::vector< Def > & dc, int index,
1094
                                               std::vector< Node > & cond, std::vector<Node> & val ) {
1095
74339
  Trace("fmc-uf-process") << "process at " << index << std::endl;
1096
201183
  for( unsigned i=1; i<cond.size(); i++) {
1097
126844
    debugPrint("fmc-uf-process", cond[i], true);
1098
126844
    Trace("fmc-uf-process") << " ";
1099
  }
1100
74339
  Trace("fmc-uf-process") << std::endl;
1101
74339
  if (index==(int)dc.size()) {
1102
    //we have an entry, now do actual compose
1103
69462
    std::map< int, Node > entries;
1104
34731
    doUninterpretedCompose2( fm, f, entries, 0, cond, val, df.d_et);
1105
34731
    if( entries.empty() ){
1106
189
      d.addEntry(fm, mkCond(cond), Node::null());
1107
    }else{
1108
      //add them to the definition
1109
132183
      for( unsigned e=0; e<df.d_cond.size(); e++ ){
1110
97641
        if ( entries.find(e)!=entries.end() ){
1111
60579
          Trace("fmf-uf-process-debug") << "Add entry..." << std::endl;
1112
60579
          d.addEntry(fm, entries[e], df.d_value[e] );
1113
60579
          Trace("fmf-uf-process-debug") << "Done add entry." << std::endl;
1114
        }
1115
      }
1116
    }
1117
  }else{
1118
92542
    for (unsigned i=0; i<dc[index].d_cond.size(); i++) {
1119
52934
      if (isCompat(fm, cond, dc[index].d_cond[i])!=0) {
1120
94104
        std::vector< Node > new_cond;
1121
47052
        new_cond.insert(new_cond.end(), cond.begin(), cond.end());
1122
47052
        if( doMeet(fm, new_cond, dc[index].d_cond[i]) ){
1123
47052
          Trace("fmc-uf-process") << "index " << i << " succeeded meet." << std::endl;
1124
47052
          val.push_back(dc[index].d_value[i]);
1125
47052
          doUninterpretedCompose(fm, f, d, df, dc, index+1, new_cond, val);
1126
47052
          val.pop_back();
1127
        }else{
1128
          Trace("fmc-uf-process") << "index " << i << " failed meet." << std::endl;
1129
        }
1130
      }
1131
    }
1132
  }
1133
74339
}
1134
1135
117318
void FullModelChecker::doUninterpretedCompose2( FirstOrderModelFmc * fm, Node f,
1136
                                                std::map< int, Node > & entries, int index,
1137
                                                std::vector< Node > & cond, std::vector< Node > & val,
1138
                                                EntryTrie & curr ) {
1139
117318
  Trace("fmc-uf-process") << "compose " << index << " / " << val.size() << std::endl;
1140
313306
  for( unsigned i=1; i<cond.size(); i++) {
1141
195988
    debugPrint("fmc-uf-process", cond[i], true);
1142
195988
    Trace("fmc-uf-process") << " ";
1143
  }
1144
117318
  Trace("fmc-uf-process") << std::endl;
1145
117318
  if (index==(int)val.size()) {
1146
121158
    Node c = mkCond(cond);
1147
60579
    Trace("fmc-uf-entry") << "Entry : " << c << " -> index[" << curr.d_data << "]" << std::endl;
1148
60579
    entries[curr.d_data] = c;
1149
  }else{
1150
113478
    Node v = val[index];
1151
56739
    Trace("fmc-uf-process") << "Process " << v << std::endl;
1152
56739
    bool bind_var = false;
1153
56739
    if( !v.isNull() && v.getKind()==kind::BOUND_VARIABLE ){
1154
26703
      int j = fm->getVariableId(f, v);
1155
26703
      Trace("fmc-uf-process") << v << " is variable #" << j << std::endl;
1156
26703
      if (!fm->isStar(cond[j + 1]))
1157
      {
1158
38
        v = cond[j+1];
1159
      }else{
1160
26665
        bind_var = true;
1161
      }
1162
    }
1163
56739
    if (bind_var) {
1164
26665
      Trace("fmc-uf-process") << "bind variable..." << std::endl;
1165
26665
      int j = fm->getVariableId(f, v);
1166
26665
      Assert(fm->isStar(cond[j + 1]));
1167
73886
      for (std::map<Node, EntryTrie>::iterator it = curr.d_child.begin();
1168
73886
           it != curr.d_child.end();
1169
           ++it)
1170
      {
1171
47221
        cond[j + 1] = it->first;
1172
47221
        doUninterpretedCompose2(
1173
47221
            fm, f, entries, index + 1, cond, val, it->second);
1174
      }
1175
26665
      cond[j + 1] = fm->getStar(v.getType());
1176
    }else{
1177
30074
      if( !v.isNull() ){
1178
29876
        if (curr.d_child.find(v) != curr.d_child.end())
1179
        {
1180
9496
          Trace("fmc-uf-process") << "follow value..." << std::endl;
1181
9496
          doUninterpretedCompose2(
1182
9496
              fm, f, entries, index + 1, cond, val, curr.d_child[v]);
1183
        }
1184
59752
        Node st = fm->getStar(v.getType());
1185
29876
        if (curr.d_child.find(st) != curr.d_child.end())
1186
        {
1187
25870
          Trace("fmc-uf-process") << "follow star..." << std::endl;
1188
25870
          doUninterpretedCompose2(
1189
25870
              fm, f, entries, index + 1, cond, val, curr.d_child[st]);
1190
        }
1191
      }
1192
    }
1193
  }
1194
117318
}
1195
1196
102756
void FullModelChecker::doInterpretedCompose( FirstOrderModelFmc * fm, Node f, Def & d, Node n,
1197
                                             std::vector< Def > & dc, int index,
1198
                                             std::vector< Node > & cond, std::vector<Node> & val ) {
1199
102756
  Trace("fmc-if-process") << "int compose " << index << " / " << dc.size() << std::endl;
1200
249067
  for( unsigned i=1; i<cond.size(); i++) {
1201
146311
    debugPrint("fmc-if-process", cond[i], true);
1202
146311
    Trace("fmc-if-process") << " ";
1203
  }
1204
102756
  Trace("fmc-if-process") << std::endl;
1205
102756
  if ( index==(int)dc.size() ){
1206
96214
    Node c = mkCond(cond);
1207
96214
    Node v = evaluateInterpreted(n, val);
1208
48107
    d.addEntry(fm, c, v);
1209
  }
1210
  else {
1211
109298
    TypeNode vtn = n.getType();
1212
154356
    for (unsigned i=0; i<dc[index].d_cond.size(); i++) {
1213
99707
      if (isCompat(fm, cond, dc[index].d_cond[i])!=0) {
1214
175486
        std::vector< Node > new_cond;
1215
87743
        new_cond.insert(new_cond.end(), cond.begin(), cond.end());
1216
87743
        if( doMeet(fm, new_cond, dc[index].d_cond[i]) ){
1217
87743
          bool process = true;
1218
87743
          if (vtn.isBoolean()) {
1219
            //short circuit
1220
130125
            if( (n.getKind()==OR && dc[index].d_value[i]==d_true) ||
1221
61264
                (n.getKind()==AND && dc[index].d_value[i]==d_false) ){
1222
16194
              Node c = mkCond(new_cond);
1223
8097
              d.addEntry(fm, c, dc[index].d_value[i]);
1224
8097
              process = false;
1225
            }
1226
          }
1227
87743
          if (process) {
1228
79646
            val.push_back(dc[index].d_value[i]);
1229
79646
            doInterpretedCompose(fm, f, d, n, dc, index+1, new_cond, val);
1230
79646
            val.pop_back();
1231
          }
1232
        }
1233
      }
1234
    }
1235
  }
1236
102756
}
1237
1238
152641
int FullModelChecker::isCompat( FirstOrderModelFmc * fm, std::vector< Node > & cond, Node c ) {
1239
152641
  Trace("fmc-debug3") << "isCompat " << c << std::endl;
1240
152641
  Assert(cond.size() == c.getNumChildren() + 1);
1241
388870
  for (unsigned i=1; i<cond.size(); i++) {
1242
254075
    if (cond[i] != c[i - 1] && !fm->isStar(cond[i]) && !fm->isStar(c[i - 1]))
1243
    {
1244
17846
      return 0;
1245
    }
1246
  }
1247
134795
  return 1;
1248
}
1249
1250
134795
bool FullModelChecker::doMeet( FirstOrderModelFmc * fm, std::vector< Node > & cond, Node c ) {
1251
134795
  Trace("fmc-debug3") << "doMeet " << c << std::endl;
1252
134795
  Assert(cond.size() == c.getNumChildren() + 1);
1253
356310
  for (unsigned i=1; i<cond.size(); i++) {
1254
221515
    if( cond[i]!=c[i-1] ) {
1255
74178
      if (fm->isStar(cond[i]))
1256
      {
1257
43491
        cond[i] = c[i - 1];
1258
      }
1259
30687
      else if (!fm->isStar(c[i - 1]))
1260
      {
1261
        return false;
1262
      }
1263
    }
1264
  }
1265
134795
  return true;
1266
}
1267
1268
161529
Node FullModelChecker::mkCond( std::vector< Node > & cond ) {
1269
161529
  return NodeManager::currentNM()->mkNode(APPLY_UF, cond);
1270
}
1271
1272
43027
Node FullModelChecker::mkCondDefault( FirstOrderModelFmc * fm, Node f) {
1273
86054
  std::vector< Node > cond;
1274
43027
  mkCondDefaultVec(fm, f, cond);
1275
86054
  return mkCond(cond);
1276
}
1277
1278
93788
void FullModelChecker::mkCondDefaultVec( FirstOrderModelFmc * fm, Node f, std::vector< Node > & cond ) {
1279
93788
  Trace("fmc-debug") << "Make default vec" << std::endl;
1280
  //get function symbol for f
1281
93788
  cond.push_back(d_quant_cond[f]);
1282
244389
  for (unsigned i=0; i<f[0].getNumChildren(); i++) {
1283
301202
    Node ts = fm->getStar(f[0][i].getType());
1284
150601
    Assert(ts.getType() == f[0][i].getType());
1285
150601
    cond.push_back(ts);
1286
  }
1287
93788
}
1288
1289
445
void FullModelChecker::mkCondVec( Node n, std::vector< Node > & cond ) {
1290
445
  cond.push_back(n.getOperator());
1291
1026
  for( unsigned i=0; i<n.getNumChildren(); i++ ){
1292
581
    cond.push_back( n[i] );
1293
  }
1294
445
}
1295
1296
48107
Node FullModelChecker::evaluateInterpreted( Node n, std::vector< Node > & vals ) {
1297
48107
  if( n.getKind()==EQUAL && !n[0].getType().isBoolean() ){
1298
12671
    if (!vals[0].isNull() && !vals[1].isNull()) {
1299
12369
      return vals[0]==vals[1] ? d_true : d_false;
1300
    }else{
1301
302
      return Node::null();
1302
    }
1303
35436
  }else if( n.getKind()==ITE ){
1304
6291
    if( vals[0]==d_true ){
1305
2789
      return vals[1];
1306
3502
    }else if( vals[0]==d_false ){
1307
3458
      return vals[2];
1308
    }else{
1309
44
      return vals[1]==vals[2] ? vals[1] : Node::null();
1310
    }
1311
29145
  }else if( n.getKind()==AND || n.getKind()==OR ){
1312
4951
    bool isNull = false;
1313
17647
    for (unsigned i=0; i<vals.size(); i++) {
1314
12696
      if((vals[i]==d_true && n.getKind()==OR) || (vals[i]==d_false && n.getKind()==AND)) {
1315
        return vals[i];
1316
12696
      }else if( vals[i].isNull() ){
1317
2547
        isNull = true;
1318
      }
1319
    }
1320
4951
    return isNull ? Node::null() : vals[0];
1321
  }else{
1322
48388
    std::vector<Node> children;
1323
24194
    if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){
1324
15227
      children.push_back( n.getOperator() );
1325
    }
1326
58559
    for (unsigned i=0; i<vals.size(); i++) {
1327
34645
      if( vals[i].isNull() ){
1328
280
        return Node::null();
1329
      }else{
1330
34365
        children.push_back( vals[i] );
1331
      }
1332
    }
1333
47828
    Node nc = NodeManager::currentNM()->mkNode(n.getKind(), children);
1334
23914
    Trace("fmc-eval") << "Evaluate " << nc << " to ";
1335
23914
    nc = Rewriter::rewrite(nc);
1336
23914
    Trace("fmc-eval") << nc << std::endl;
1337
23914
    return nc;
1338
  }
1339
}
1340
1341
3639
Node FullModelChecker::getSomeDomainElement( FirstOrderModelFmc * fm, TypeNode tn ) {
1342
3639
  bool addRepId = !fm->getRepSet()->hasType(tn);
1343
3639
  Node de = fm->getSomeDomainElement(tn);
1344
3639
  if( addRepId ){
1345
106
    d_rep_ids[tn][de] = 0;
1346
  }
1347
3639
  return de;
1348
}
1349
1350
7693
Node FullModelChecker::getFunctionValue(FirstOrderModelFmc * fm, Node op, const char* argPrefix ) {
1351
7693
  return fm->getFunctionValue(op, argPrefix);
1352
}
1353
1354
1355
46970
bool FullModelChecker::useSimpleModels() {
1356
93940
  return options::fmfFmcSimple();
1357
}
1358
21956
void FullModelChecker::registerQuantifiedFormula(Node q)
1359
{
1360
21956
  if (d_quant_cond.find(q) != d_quant_cond.end())
1361
  {
1362
20605
    return;
1363
  }
1364
1351
  NodeManager* nm = NodeManager::currentNM();
1365
1351
  SkolemManager* sm = nm->getSkolemManager();
1366
2702
  std::vector<TypeNode> types;
1367
3327
  for (const Node& v : q[0])
1368
  {
1369
3952
    TypeNode tn = v.getType();
1370
1976
    if (tn.isFunction())
1371
    {
1372
      // we will not use model-based quantifier instantiation for q, since
1373
      // the model-based instantiation algorithm does not handle (universally
1374
      // quantified) functions
1375
24
      d_unhandledQuant.insert(q);
1376
    }
1377
1976
    types.push_back(tn);
1378
  }
1379
2702
  TypeNode typ = nm->mkFunctionType(types, nm->booleanType());
1380
2702
  Node op = sm->mkDummySkolem("qfmc", typ, "op for full-model checking");
1381
1351
  d_quant_cond[q] = op;
1382
}
1383
1384
21956
bool FullModelChecker::isHandled(Node q) const
1385
{
1386
21956
  return d_unhandledQuant.find(q) == d_unhandledQuant.end();
1387
}
1388
1389
}  // namespace fmcheck
1390
}  // namespace quantifiers
1391
}  // namespace theory
1392
81086
}  // namespace cvc5