GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/fmf/full_model_check.cpp Lines: 763 802 95.1 %
Date: 2021-11-07 Branches: 1664 3241 51.3 %

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/strings_options.h"
21
#include "options/theory_options.h"
22
#include "options/uf_options.h"
23
#include "theory/quantifiers/first_order_model.h"
24
#include "theory/quantifiers/fmf/bounded_integers.h"
25
#include "theory/quantifiers/instantiate.h"
26
#include "theory/quantifiers/quant_rep_bound_ext.h"
27
#include "theory/quantifiers/quantifiers_inference_manager.h"
28
#include "theory/quantifiers/quantifiers_registry.h"
29
#include "theory/quantifiers/quantifiers_state.h"
30
#include "theory/quantifiers/term_database.h"
31
#include "theory/quantifiers/term_util.h"
32
#include "theory/rewriter.h"
33
34
using namespace cvc5::kind;
35
using namespace cvc5::context;
36
37
namespace cvc5 {
38
namespace theory {
39
namespace quantifiers {
40
namespace fmcheck {
41
42
186724
struct ModelBasisArgSort
43
{
44
  std::vector< Node > d_terms;
45
  // number of arguments that are model-basis terms
46
  std::unordered_map<Node, unsigned> d_mba_count;
47
57320
  bool operator() (int i,int j) {
48
57320
    return (d_mba_count[d_terms[i]] < d_mba_count[d_terms[j]]);
49
  }
50
};
51
52
421664
bool EntryTrie::hasGeneralization( FirstOrderModelFmc * m, Node c, int index ) {
53
421664
  if (index==(int)c.getNumChildren()) {
54
15828
    return d_data!=-1;
55
  }else{
56
811672
    TypeNode tn = c[index].getType();
57
811672
    Node st = m->getStar(tn);
58
405836
    if(d_child.find(st)!=d_child.end()) {
59
40474
      if( d_child[st].hasGeneralization(m, c, index+1) ){
60
15172
        return true;
61
      }
62
    }
63
390664
    if( c[index]!=st && d_child.find( c[index] )!=d_child.end() ){
64
56736
      if( d_child[ c[index] ].hasGeneralization(m, c, index+1) ){
65
21768
        return true;
66
      }
67
    }
68
368896
    if( c[index].getType().isSort() ){
69
      //for star: check if all children are defined and have generalizations
70
267604
      if( c[index]==st ){     ///options::fmfFmcCoverSimplify()
71
        //check if all children exist and are complete
72
        unsigned num_child_def =
73
155080
            d_child.size() - (d_child.find(st) != d_child.end() ? 1 : 0);
74
155080
        if (num_child_def == m->getRepSet()->getNumRepresentatives(tn))
75
        {
76
8573
          bool complete = true;
77
13993
          for ( std::map<Node,EntryTrie>::iterator it = d_child.begin(); it != d_child.end(); ++it ){
78
11760
            if( !m->isStar(it->first) ){
79
11258
              if( !it->second.hasGeneralization(m, c, index+1) ){
80
6340
                complete = false;
81
6340
                break;
82
              }
83
            }
84
          }
85
8573
          if( complete ){
86
2233
            return true;
87
          }
88
        }
89
      }
90
    }
91
92
366663
    return false;
93
  }
94
}
95
96
136797
int EntryTrie::getGeneralizationIndex( FirstOrderModelFmc * m, std::vector<Node> & inst, int index ) {
97
136797
  Debug("fmc-entry-trie") << "Get generalization index " << inst.size() << " " << index << std::endl;
98
136797
  if (index==(int)inst.size()) {
99
40192
    return d_data;
100
  }else{
101
96605
    int minIndex = -1;
102
193210
    Node st = m->getStar(inst[index].getType());
103
96605
    if (d_child.find(st) != d_child.end())
104
    {
105
90135
      minIndex = d_child[st].getGeneralizationIndex(m, inst, index + 1);
106
    }
107
193210
    Node cc = inst[index];
108
96605
    if (cc != st && d_child.find(cc) != d_child.end())
109
    {
110
12834
      int gindex = d_child[cc].getGeneralizationIndex(m, inst, index + 1);
111
12834
      if (minIndex == -1 || (gindex != -1 && gindex < minIndex))
112
      {
113
8807
        minIndex = gindex;
114
      }
115
    }
116
96605
    return minIndex;
117
  }
118
}
119
120
784028
void EntryTrie::addEntry( FirstOrderModelFmc * m, Node c, Node v, int data, int index ) {
121
784028
  if (index==(int)c.getNumChildren()) {
122
300053
    if(d_data==-1) {
123
300053
      d_data = data;
124
    }
125
  }
126
  else {
127
483975
    d_child[ c[index] ].addEntry(m,c,v,data,index+1);
128
483975
    if( d_complete==0 ){
129
      d_complete = -1;
130
    }
131
  }
132
784028
}
133
134
337178
void EntryTrie::getEntries( FirstOrderModelFmc * m, Node c, std::vector<int> & compat, std::vector<int> & gen, int index, bool is_gen ) {
135
337178
  if (index==(int)c.getNumChildren()) {
136
70689
    if( d_data!=-1) {
137
70689
      if( is_gen ){
138
64897
        gen.push_back(d_data);
139
      }
140
70689
      compat.push_back(d_data);
141
    }
142
  }else{
143
266489
    if (m->isStar(c[index])) {
144
274870
      for ( std::map<Node,EntryTrie>::iterator it = d_child.begin(); it != d_child.end(); ++it ){
145
111736
        it->second.getEntries(m, c, compat, gen, index+1, is_gen );
146
      }
147
    }else{
148
206710
      Node st = m->getStar(c[index].getType());
149
103355
      if(d_child.find(st)!=d_child.end()) {
150
7748
        d_child[st].getEntries(m, c, compat, gen, index+1, false);
151
      }
152
103355
      if( d_child.find( c[index] )!=d_child.end() ){
153
30194
        d_child[ c[index] ].getEntries(m, c, compat, gen, index+1, is_gen);
154
      }
155
    }
156
157
  }
158
337178
}
159
160
313196
bool Def::addEntry( FirstOrderModelFmc * m, Node c, Node v) {
161
313196
  if (d_et.hasGeneralization(m, c)) {
162
13143
    Trace("fmc-debug") << "Already has generalization, skip." << std::endl;
163
13143
    return false;
164
  }
165
300053
  int newIndex = (int)d_cond.size();
166
300053
  if (!d_has_simplified) {
167
375000
    std::vector<int> compat;
168
375000
    std::vector<int> gen;
169
187500
    d_et.getEntries(m, c, compat, gen);
170
258189
    for( unsigned i=0; i<compat.size(); i++) {
171
70689
      if( d_status[compat[i]]==status_unk ){
172
61777
        if( d_value[compat[i]]!=v ){
173
38816
          d_status[compat[i]] = status_non_redundant;
174
        }
175
      }
176
    }
177
252397
    for( unsigned i=0; i<gen.size(); i++) {
178
64897
      if( d_status[gen[i]]==status_unk ){
179
19297
        if( d_value[gen[i]]==v ){
180
19297
          d_status[gen[i]] = status_redundant;
181
        }
182
      }
183
    }
184
187500
    d_status.push_back( status_unk );
185
  }
186
300053
  d_et.addEntry(m, c, v, newIndex);
187
300053
  d_cond.push_back(c);
188
300053
  d_value.push_back(v);
189
300053
  return true;
190
}
191
192
3286
Node Def::evaluate( FirstOrderModelFmc * m, std::vector<Node>& inst ) {
193
3286
  int gindex = d_et.getGeneralizationIndex(m, inst);
194
3286
  if (gindex!=-1) {
195
3282
    return d_value[gindex];
196
  }else{
197
4
    Trace("fmc-warn") << "Warning : evaluation came up null!" << std::endl;
198
4
    return Node::null();
199
  }
200
}
201
202
30542
int Def::getGeneralizationIndex( FirstOrderModelFmc * m, std::vector<Node>& inst ) {
203
30542
  return d_et.getGeneralizationIndex(m, inst);
204
}
205
206
68653
void Def::basic_simplify( FirstOrderModelFmc * m ) {
207
68653
  d_has_simplified = true;
208
137306
  std::vector< Node > cond;
209
68653
  cond.insert( cond.end(), d_cond.begin(), d_cond.end() );
210
68653
  d_cond.clear();
211
137306
  std::vector< Node > value;
212
68653
  value.insert( value.end(), d_value.begin(), d_value.end() );
213
68653
  d_value.clear();
214
68653
  d_et.reset();
215
200503
  for (unsigned i=0; i<d_status.size(); i++) {
216
131850
    if( d_status[i]!=status_redundant ){
217
112553
      addEntry(m, cond[i], value[i]);
218
    }
219
  }
220
68653
  d_status.clear();
221
68653
}
222
223
62592
void Def::simplify(FullModelChecker * mc, FirstOrderModelFmc * m) {
224
62592
  Trace("fmc-simplify") << "Simplify definition, #cond = " << d_cond.size() << std::endl;
225
62592
  basic_simplify( m );
226
62592
  Trace("fmc-simplify") << "post-basic simplify, #cond = " << d_cond.size() << std::endl;
227
228
  //check if the last entry is not all star, if so, we can make the last entry all stars
229
62592
  if( !d_cond.empty() ){
230
62592
    bool last_all_stars = true;
231
125184
    Node cc = d_cond[d_cond.size()-1];
232
145993
    for( unsigned i=0; i<cc.getNumChildren(); i++ ){
233
89462
      if (!m->isStar(cc[i]))
234
      {
235
6061
        last_all_stars = false;
236
6061
        break;
237
      }
238
    }
239
62592
    if( !last_all_stars ){
240
6061
      Trace("fmc-cover-simplify") << "Need to modify last entry to be all stars." << std::endl;
241
6061
      Trace("fmc-cover-simplify") << "Before: " << std::endl;
242
6061
      debugPrint("fmc-cover-simplify",Node::null(), mc);
243
6061
      Trace("fmc-cover-simplify") << std::endl;
244
12122
      std::vector< Node > cond;
245
6061
      cond.insert( cond.end(), d_cond.begin(), d_cond.end() );
246
6061
      d_cond.clear();
247
12122
      std::vector< Node > value;
248
6061
      value.insert( value.end(), d_value.begin(), d_value.end() );
249
6061
      d_value.clear();
250
6061
      d_et.reset();
251
6061
      d_has_simplified = false;
252
      //change the last to all star
253
12122
      std::vector< Node > nc;
254
6061
      nc.push_back( cc.getOperator() );
255
15926
      for( unsigned j=0; j< cc.getNumChildren(); j++){
256
9865
        nc.push_back(m->getStar(cc[j].getType()));
257
      }
258
6061
      cond[cond.size()-1] = NodeManager::currentNM()->mkNode( APPLY_UF, nc );
259
      //re-add the entries
260
17314
      for (unsigned i=0; i<cond.size(); i++) {
261
11253
        addEntry(m, cond[i], value[i]);
262
      }
263
6061
      Trace("fmc-cover-simplify") << "Finished re-adding entries." << std::endl;
264
6061
      basic_simplify( m );
265
6061
      Trace("fmc-cover-simplify") << "After: " << std::endl;
266
6061
      debugPrint("fmc-cover-simplify",Node::null(), mc);
267
6061
      Trace("fmc-cover-simplify") << std::endl;
268
    }
269
  }
270
62592
  Trace("fmc-simplify") << "finish simplify, #cond = " << d_cond.size() << std::endl;
271
62592
}
272
273
229047
void Def::debugPrint(const char * tr, Node op, FullModelChecker * m) {
274
229047
  if (!op.isNull()) {
275
38937
    Trace(tr) << "Model for " << op << " : " << std::endl;
276
  }
277
598295
  for( unsigned i=0; i<d_cond.size(); i++) {
278
    //print the condition
279
369248
    if (!op.isNull()) {
280
96893
      Trace(tr) << op;
281
    }
282
369248
    m->debugPrintCond(tr, d_cond[i], true);
283
369248
    Trace(tr) << " -> ";
284
369248
    m->debugPrint(tr, d_value[i]);
285
369248
    Trace(tr) << std::endl;
286
  }
287
229047
}
288
289
1559
FullModelChecker::FullModelChecker(Env& env,
290
                                   QuantifiersState& qs,
291
                                   QuantifiersInferenceManager& qim,
292
                                   QuantifiersRegistry& qr,
293
1559
                                   TermRegistry& tr)
294
    : QModelBuilder(env, qs, qim, qr, tr),
295
1559
      d_fm(new FirstOrderModelFmc(env, qs, qr, tr))
296
{
297
1559
  d_true = NodeManager::currentNM()->mkConst(true);
298
1559
  d_false = NodeManager::currentNM()->mkConst(false);
299
1559
}
300
301
1559
void FullModelChecker::finishInit() { d_model = d_fm.get(); }
302
303
2121
bool FullModelChecker::preProcessBuildModel(TheoryModel* m) {
304
  //standard pre-process
305
2121
  if( !preProcessBuildModelStd( m ) ){
306
    return false;
307
  }
308
309
2121
  Trace("fmc") << "---Full Model Check preprocess() " << std::endl;
310
2121
  d_preinitialized_eqc.clear();
311
2121
  d_preinitialized_types.clear();
312
  //traverse equality engine
313
2121
  eq::EqClassesIterator eqcs_i = eq::EqClassesIterator(m->getEqualityEngine());
314
83719
  while( !eqcs_i.isFinished() ){
315
81598
    Node r = *eqcs_i;
316
81598
    TypeNode tr = r.getType();
317
40799
    d_preinitialized_eqc[tr] = r;
318
40799
    ++eqcs_i;
319
  }
320
321
  //must ensure model basis terms exists in model for each relevant type
322
2121
  Trace("fmc") << "preInitialize types..." << std::endl;
323
2121
  d_fm->initialize();
324
9407
  for (std::pair<const Node, Def*>& mp : d_fm->d_models)
325
  {
326
14572
    Node op = mp.first;
327
7286
    Trace("fmc") << "preInitialize types for " << op << std::endl;
328
14572
    TypeNode tno = op.getType();
329
26689
    for( unsigned i=0; i<tno.getNumChildren(); i++) {
330
19403
      Trace("fmc") << "preInitializeType " << tno[i] << std::endl;
331
19403
      preInitializeType(m, tno[i]);
332
19403
      Trace("fmc") << "finished preInitializeType " << tno[i] << std::endl;
333
    }
334
  }
335
2121
  Trace("fmc") << "Finish preInitialize types" << std::endl;
336
  //do not have to introduce terms for sorts of domains of quantified formulas if we are allowed to assume empty sorts
337
11380
  for (unsigned i = 0, nquant = d_fm->getNumAssertedQuantifiers(); i < nquant;
338
       i++)
339
  {
340
18386
    Node q = d_fm->getAssertedQuantifier(i);
341
9259
    registerQuantifiedFormula(q);
342
9259
    if (!isHandled(q))
343
    {
344
132
      continue;
345
    }
346
    // make sure all types are set
347
23177
    for (const Node& v : q[0])
348
    {
349
14050
      preInitializeType(m, v.getType());
350
    }
351
  }
352
2121
  return true;
353
}
354
355
2121
bool FullModelChecker::processBuildModel(TheoryModel* m){
356
2121
  if (!m->areFunctionValuesEnabled())
357
  {
358
    // nothing to do if no functions
359
    return true;
360
  }
361
2121
  FirstOrderModelFmc* fm = d_fm.get();
362
2121
  Trace("fmc") << "---Full Model Check reset() " << std::endl;
363
2121
  d_quant_models.clear();
364
2121
  d_rep_ids.clear();
365
2121
  d_star_insts.clear();
366
  //process representatives
367
2121
  RepSet* rs = m->getRepSetPtr();
368
8557
  for (std::map<TypeNode, std::vector<Node> >::iterator it =
369
2121
           rs->d_type_reps.begin();
370
10678
       it != rs->d_type_reps.end();
371
       ++it)
372
  {
373
8557
    if( it->first.isSort() ){
374
1982
      Trace("fmc") << "Cardinality( " << it->first << " )" << " = " << it->second.size() << std::endl;
375
5730
      for( size_t a=0; a<it->second.size(); a++ ){
376
7496
        Node r = m->getRepresentative(it->second[a]);
377
3748
        if( Trace.isOn("fmc-model-debug") ){
378
          std::vector< Node > eqc;
379
          d_qstate.getEquivalenceClass(r, eqc);
380
          Trace("fmc-model-debug") << "   " << (it->second[a]==r);
381
          Trace("fmc-model-debug") << " : " << it->second[a] << " : " << r << " : ";
382
          //Trace("fmc-model-debug") << r2 << " : " << ir << " : ";
383
          Trace("fmc-model-debug") << " {";
384
          for( size_t i=0; i<eqc.size(); i++ ){
385
            Trace("fmc-model-debug") << eqc[i] << ", ";
386
          }
387
          Trace("fmc-model-debug") << "}" << std::endl;
388
        }
389
3748
        d_rep_ids[it->first][r] = (int)a;
390
      }
391
1982
      Trace("fmc-model-debug") << std::endl;
392
    }
393
  }
394
395
  //now, make models
396
9407
  for (std::pair<const Node, Def*>& fmm : d_fm->d_models)
397
  {
398
14572
    Node op = fmm.first;
399
    //reset the model
400
7286
    d_fm->d_models[op]->reset();
401
402
14572
    std::vector< Node > add_conds;
403
14572
    std::vector< Node > add_values;
404
7286
    bool needsDefault = true;
405
7286
    if (m->hasUfTerms(op))
406
    {
407
5528
      const std::vector<Node>& uft = m->getUfTerms(op);
408
11056
      Trace("fmc-model-debug")
409
5528
          << uft.size() << " model values for " << op << " ... " << std::endl;
410
37175
      for (const Node& n : uft)
411
      {
412
        // only consider unique up to congruence (in model equality engine)?
413
31647
        add_conds.push_back( n );
414
31647
        add_values.push_back( n );
415
63294
        Node r = m->getRepresentative(n);
416
31647
        Trace("fmc-model-debug") << n << " -> " << r << std::endl;
417
      }
418
    }else{
419
1758
      Trace("fmc-model-debug") << "No model values for " << op << " ... " << std::endl;
420
    }
421
7286
    Trace("fmc-model-debug") << std::endl;
422
    //possibly get default
423
7286
    if( needsDefault ){
424
14572
      Node nmb = d_fm->getModelBasisOpTerm(op);
425
      //add default value if necessary
426
7286
      if (m->hasTerm(nmb))
427
      {
428
3870
        Trace("fmc-model-debug") << "Add default " << nmb << std::endl;
429
3870
        add_conds.push_back( nmb );
430
3870
        add_values.push_back( nmb );
431
      }else{
432
6832
        Node vmb = getSomeDomainElement(d_fm.get(), nmb.getType());
433
3416
        Trace("fmc-model-debug") << "Add default to default representative " << nmb << " ";
434
6832
        Trace("fmc-model-debug")
435
6832
            << m->getRepSet()->getNumRepresentatives(nmb.getType())
436
3416
            << std::endl;
437
3416
        add_conds.push_back( nmb );
438
3416
        add_values.push_back( vmb );
439
      }
440
    }
441
442
14572
    std::vector< Node > conds;
443
14572
    std::vector< Node > values;
444
14572
    std::vector< Node > entry_conds;
445
    //get the entries for the model
446
46219
    for( size_t i=0; i<add_conds.size(); i++ ){
447
77866
      Node c = add_conds[i];
448
77866
      Node v = add_values[i];
449
77866
      Trace("fmc-model-debug")
450
38933
          << "Add cond/value : " << c << " -> " << v << std::endl;
451
77866
      std::vector< Node > children;
452
77866
      std::vector< Node > entry_children;
453
38933
      children.push_back(op);
454
38933
      entry_children.push_back(op);
455
38933
      bool hasNonStar = false;
456
114127
      for (const Node& ci : c)
457
      {
458
150388
        Node ri = fm->getRepresentative(ci);
459
75194
        children.push_back(ri);
460
75194
        bool isStar = false;
461
75194
        if (fm->isModelBasisTerm(ri))
462
        {
463
21529
          ri = fm->getStar(ri.getType());
464
21529
          isStar = true;
465
        }
466
        else
467
        {
468
53665
          hasNonStar = true;
469
        }
470
75194
        if( !isStar && !ri.isConst() ){
471
          Trace("fmc-warn") << "Warning : model for " << op
472
                            << " has non-constant argument in model " << ri
473
                            << " (from " << ci << ")" << std::endl;
474
          Assert(false);
475
        }
476
75194
        entry_children.push_back(ri);
477
      }
478
77866
      Node n = NodeManager::currentNM()->mkNode( APPLY_UF, children );
479
77866
      Node nv = fm->getRepresentative( v );
480
77866
      Trace("fmc-model-debug")
481
38933
          << "Representative of " << v << " is " << nv << std::endl;
482
38933
      if( !nv.isConst() ){
483
        Trace("fmc-warn") << "Warning : model for " << op << " has non-constant value in model " << nv << std::endl;
484
        Assert(false);
485
      }
486
77866
      Node en = (useSimpleModels() && hasNonStar) ? n : NodeManager::currentNM()->mkNode( APPLY_UF, entry_children );
487
38933
      if( std::find(conds.begin(), conds.end(), n )==conds.end() ){
488
24531
        Trace("fmc-model-debug") << "- add " << n << " -> " << nv << " (entry is " << en << ")" << std::endl;
489
24531
        conds.push_back(n);
490
24531
        values.push_back(nv);
491
24531
        entry_conds.push_back(en);
492
      }
493
      else {
494
14402
        Trace("fmc-model-debug") << "Already have entry for : " << n << " -> " << nv << " (entry is " << en << ")" << std::endl;
495
      }
496
    }
497
498
499
    //sort based on # default arguments
500
14572
    std::vector< int > indices;
501
14572
    ModelBasisArgSort mbas;
502
31817
    for (int i=0; i<(int)conds.size(); i++) {
503
24531
      mbas.d_terms.push_back(conds[i]);
504
24531
      mbas.d_mba_count[conds[i]] = fm->getModelBasisArg(conds[i]);
505
24531
      indices.push_back(i);
506
    }
507
7286
    std::sort( indices.begin(), indices.end(), mbas );
508
509
31817
    for (int i=0; i<(int)indices.size(); i++) {
510
24531
      fm->d_models[op]->addEntry(fm, entry_conds[indices[i]], values[indices[i]]);
511
    }
512
513
7286
    Trace("fmc-model-simplify") << "Before simplification : " << std::endl;
514
7286
    fm->d_models[op]->debugPrint("fmc-model-simplify", op, this);
515
7286
    Trace("fmc-model-simplify") << std::endl;
516
517
7286
    Trace("fmc-model-simplify") << "Simplifying " << op << "..." << std::endl;
518
7286
    fm->d_models[op]->simplify( this, fm );
519
520
7286
    fm->d_models[op]->debugPrint("fmc-model", op, this);
521
7286
    Trace("fmc-model") << std::endl;
522
523
    //for debugging
524
    /*
525
    for( size_t i=0; i<fm->d_uf_terms[op].size(); i++ ){
526
      std::vector< Node > inst;
527
      for( unsigned j=0; j<fm->d_uf_terms[op][i].getNumChildren(); j++ ){
528
        Node r = fm->getRepresentative( fm->d_uf_terms[op][i][j] );
529
        inst.push_back( r );
530
      }
531
      Node ev = fm->d_models[op]->evaluate( fm, inst );
532
      Trace("fmc-model-debug") << ".....Checking eval( " <<
533
    fm->d_uf_terms[op][i] << " ) = " << ev << std::endl; AlwaysAssert(
534
    fm->areEqual( ev, fm->d_uf_terms[op][i] ) );
535
    }
536
    */
537
  }
538
2121
  Assert(d_addedLemmas == 0);
539
540
  //make function values
541
9407
  for( std::map<Node, Def * >::iterator it = fm->d_models.begin(); it != fm->d_models.end(); ++it ){
542
14572
    Node f_def = getFunctionValue( fm, it->first, "$x" );
543
7286
    m->assignFunctionDefinition( it->first, f_def );
544
  }
545
2121
  return TheoryEngineModelBuilder::processBuildModel( m );
546
}
547
548
33453
void FullModelChecker::preInitializeType(TheoryModel* m, TypeNode tn)
549
{
550
33453
  if( d_preinitialized_types.find( tn )==d_preinitialized_types.end() ){
551
4957
    d_preinitialized_types[tn] = true;
552
4957
    if (tn.isFirstClass())
553
    {
554
4945
      Trace("fmc") << "Get model basis term " << tn << "..." << std::endl;
555
9890
      Node mb = d_fm->getModelBasisTerm(tn);
556
4945
      Trace("fmc") << "...return " << mb << std::endl;
557
      // if the model basis term does not exist in the model,
558
      // either add it directly to the model's equality engine if no other terms
559
      // of this type exist, or otherwise assert that it is equal to the first
560
      // equivalence class of its type.
561
4945
      if (!m->hasTerm(mb) && !mb.isConst())
562
      {
563
671
        std::map<TypeNode, Node>::iterator itpe = d_preinitialized_eqc.find(tn);
564
671
        if (itpe == d_preinitialized_eqc.end())
565
        {
566
664
          Trace("fmc") << "...add model basis term to EE of model " << mb << " "
567
332
                       << tn << std::endl;
568
332
          m->getEqualityEngine()->addTerm(mb);
569
        }
570
        else
571
        {
572
678
          Trace("fmc") << "...add model basis eqc equality to model " << mb
573
339
                       << " == " << itpe->second << " " << tn << std::endl;
574
339
          bool ret = m->assertEquality(mb, itpe->second, true);
575
339
          AlwaysAssert(ret);
576
        }
577
      }
578
    }
579
  }
580
33453
}
581
582
374497
void FullModelChecker::debugPrintCond(const char * tr, Node n, bool dispStar) {
583
374497
  Trace(tr) << "(";
584
965095
  for( unsigned j=0; j<n.getNumChildren(); j++) {
585
590598
    if( j>0 ) Trace(tr) << ", ";
586
590598
    debugPrint(tr, n[j], dispStar);
587
  }
588
374497
  Trace(tr) << ")";
589
374497
}
590
591
1482055
void FullModelChecker::debugPrint(const char * tr, Node n, bool dispStar) {
592
1482055
  if( n.isNull() ){
593
33477
    Trace(tr) << "null";
594
  }
595
1448578
  else if (FirstOrderModelFmc::isStar(n) && dispStar)
596
  {
597
703939
    Trace(tr) << "*";
598
  }
599
  else
600
  {
601
1489278
    TypeNode tn = n.getType();
602
744639
    if( tn.isSort() && d_rep_ids.find(tn)!=d_rep_ids.end() ){
603
350194
      if (d_rep_ids[tn].find(n)!=d_rep_ids[tn].end()) {
604
327804
        Trace(tr) << d_rep_ids[tn][n];
605
      }else{
606
22390
        Trace(tr) << n;
607
      }
608
    }else{
609
394445
      Trace(tr) << n;
610
    }
611
  }
612
1482055
}
613
614
615
11673
int FullModelChecker::doExhaustiveInstantiation( FirstOrderModel * fm, Node f, int effort ) {
616
11673
  Trace("fmc") << "Full model check " << f << ", effort = " << effort << "..." << std::endl;
617
  // register the quantifier
618
11673
  registerQuantifiedFormula(f);
619
11673
  Assert(!d_qstate.isInConflict());
620
  // we do not do model-based quantifier instantiation if the option
621
  // disables it, or if the quantified formula has an unhandled type.
622
11673
  if (!optUseModel() || !isHandled(f))
623
  {
624
    return 0;
625
  }
626
11673
  FirstOrderModelFmc* fmfmc = static_cast<FirstOrderModelFmc*>(fm);
627
11673
  if (effort == 0)
628
  {
629
8848
    if (options::mbqiMode() == options::MbqiMode::NONE)
630
    {
631
      // just exhaustive instantiate
632
4372
      Node c = mkCondDefault(fmfmc, f);
633
2186
      d_quant_models[f].addEntry(fmfmc, c, d_false);
634
2186
      if (!exhaustiveInstantiate(fmfmc, f, c))
635
      {
636
22
        return 0;
637
      }
638
2164
      return 1;
639
    }
640
    // model check the quantifier
641
6662
    doCheck(fmfmc, f, d_quant_models[f], f[1]);
642
6662
    std::vector<Node>& mcond = d_quant_models[f].d_cond;
643
6662
    Trace("fmc") << "Definition for quantifier " << f << " is : " << std::endl;
644
6662
    Assert(!mcond.empty());
645
6662
    d_quant_models[f].debugPrint("fmc", Node::null(), this);
646
6662
    Trace("fmc") << std::endl;
647
648
    // consider all entries going to non-true
649
6662
    Instantiate* instq = d_qim.getInstantiate();
650
15305
    for (unsigned i = 0, msize = mcond.size(); i < msize; i++)
651
    {
652
8643
      if (d_quant_models[f].d_value[i] == d_true)
653
      {
654
        // already satisfied
655
11314
        continue;
656
      }
657
7336
      Trace("fmc-inst") << "Instantiate based on " << mcond[i] << "..."
658
3668
                        << std::endl;
659
3668
      bool hasStar = false;
660
5972
      std::vector<Node> inst;
661
9129
      for (unsigned j = 0, nchild = mcond[i].getNumChildren(); j < nchild; j++)
662
      {
663
5461
        if (fmfmc->isStar(mcond[i][j]))
664
        {
665
4470
          hasStar = true;
666
4470
          inst.push_back(fmfmc->getModelBasisTerm(mcond[i][j].getType()));
667
        }
668
        else
669
        {
670
991
          inst.push_back(mcond[i][j]);
671
        }
672
      }
673
3668
      bool addInst = true;
674
3668
      if (hasStar)
675
      {
676
        // try obvious (specified by inst)
677
6572
        Node ev = d_quant_models[f].evaluate(fmfmc, inst);
678
3286
        if (ev == d_true)
679
        {
680
9
          addInst = false;
681
18
          Trace("fmc-debug")
682
9
              << "...do not instantiate, evaluation was " << ev << std::endl;
683
        }
684
      }
685
      else
686
      {
687
        // for debugging
688
382
        if (Trace.isOn("fmc-test-inst"))
689
        {
690
          Node ev = d_quant_models[f].evaluate(fmfmc, inst);
691
          if (ev == d_true)
692
          {
693
            CVC5Message() << "WARNING: instantiation was true! " << f << " "
694
                          << mcond[i] << std::endl;
695
            AlwaysAssert(false);
696
          }
697
          else
698
          {
699
            Trace("fmc-test-inst")
700
                << "...instantiation evaluated to false." << std::endl;
701
          }
702
        }
703
      }
704
3677
      if (!addInst)
705
      {
706
18
        Trace("fmc-debug-inst")
707
9
            << "** Instantiation was already true." << std::endl;
708
        // might try it next effort level
709
9
        d_star_insts[f].push_back(i);
710
9
        continue;
711
      }
712
3659
      if (options::fmfBound() || options::stringExp())
713
      {
714
2710
        std::vector<Node> cond;
715
1355
        cond.push_back(d_quant_cond[f]);
716
1355
        cond.insert(cond.end(), inst.begin(), inst.end());
717
        // need to do exhaustive instantiate algorithm to set things properly
718
        // (should only add one instance)
719
2710
        Node c = mkCond(cond);
720
1355
        unsigned prevInst = d_addedLemmas;
721
1355
        exhaustiveInstantiate(fmfmc, f, c);
722
1355
        if (d_addedLemmas == prevInst)
723
        {
724
1032
          d_star_insts[f].push_back(i);
725
        }
726
1355
        continue;
727
      }
728
      // just add the instance
729
2304
      d_triedLemmas++;
730
4608
      if (instq->addInstantiation(f,
731
                                  inst,
732
                                  InferenceId::QUANTIFIERS_INST_FMF_FMC,
733
4608
                                  Node::null(),
734
                                  true))
735
      {
736
767
        Trace("fmc-debug-inst") << "** Added instantiation." << std::endl;
737
767
        d_addedLemmas++;
738
767
        if (d_qstate.isInConflict() || options::fmfOneInstPerRound())
739
        {
740
          break;
741
        }
742
      }
743
      else
744
      {
745
3074
        Trace("fmc-debug-inst")
746
1537
            << "** Instantiation was duplicate." << std::endl;
747
        // might try it next effort level
748
1537
        d_star_insts[f].push_back(i);
749
      }
750
    }
751
6662
    return 1;
752
  }
753
  // Get the list of instantiation regions (described by "star entries" in the
754
  // definition) that were not tried at the previous effort level. For each
755
  // of these, we add one instantiation.
756
2825
  std::vector<Node>& mcond = d_quant_models[f].d_cond;
757
2825
  if (!d_star_insts[f].empty())
758
  {
759
1633
    if (Trace.isOn("fmc-exh"))
760
    {
761
      Trace("fmc-exh") << "Exhaustive instantiate " << f << std::endl;
762
      Trace("fmc-exh") << "Definition was : " << std::endl;
763
      d_quant_models[f].debugPrint("fmc-exh", Node::null(), this);
764
      Trace("fmc-exh") << std::endl;
765
    }
766
3233
    Def temp;
767
    // simplify the exceptions?
768
3362
    for (int i = (d_star_insts[f].size() - 1); i >= 0; i--)
769
    {
770
      // get witness for d_star_insts[f][i]
771
1762
      int j = d_star_insts[f][i];
772
1762
      if (temp.addEntry(fmfmc, mcond[j], d_quant_models[f].d_value[j]))
773
      {
774
1708
        if (!exhaustiveInstantiate(fmfmc, f, mcond[j]))
775
        {
776
          // something went wrong, resort to exhaustive instantiation
777
33
          return 0;
778
        }
779
      }
780
    }
781
  }
782
2792
  return 1;
783
}
784
785
/** Representative bound fmc entry
786
 *
787
 * This bound information corresponds to one
788
 * entry in a term definition (see terminology in
789
 * Chapter 5 of Finite Model Finding for
790
 * Satisfiability Modulo Theories thesis).
791
 * For example, a term definition for the body
792
 * of a quantified formula:
793
 *   forall xyz. P( x, y, z )
794
 * may be:
795
 *   ( 0, 0, 0 ) -> false
796
 *   ( *, 1, 2 ) -> false
797
 *   ( *, *, * ) -> true
798
 * Indicating that the quantified formula evaluates
799
 * to false in the current model for x=0, y=0, z=0,
800
 * or y=1, z=2 for any x, and evaluates to true
801
 * otherwise.
802
 * This class is used if we wish
803
 * to iterate over all values corresponding to one
804
 * of these entries. For example, for the second entry:
805
 *   (*, 1, 2 )
806
 * we iterate over all values of x, but only {1}
807
 * for y and {2} for z.
808
 */
809
class RepBoundFmcEntry : public QRepBoundExt
810
{
811
 public:
812
5249
  RepBoundFmcEntry(QuantifiersBoundInference& qbi,
813
                   Node e,
814
                   FirstOrderModelFmc* f)
815
5249
      : QRepBoundExt(qbi, f), d_entry(e), d_fm(f)
816
  {
817
5249
  }
818
5249
  ~RepBoundFmcEntry() {}
819
  /** set bound */
820
7118
  virtual RsiEnumType setBound(Node owner,
821
                               unsigned i,
822
                               std::vector<Node>& elements) override
823
  {
824
7118
    if (!d_fm->isStar(d_entry[i]))
825
    {
826
      // only need to consider the single point
827
1768
      elements.push_back(d_entry[i]);
828
1768
      return ENUM_DEFAULT;
829
    }
830
5350
    return QRepBoundExt::setBound(owner, i, elements);
831
  }
832
833
 private:
834
  /** the entry for this bound */
835
  Node d_entry;
836
  /** the model builder associated with this bound */
837
  FirstOrderModelFmc* d_fm;
838
};
839
840
5249
bool FullModelChecker::exhaustiveInstantiate(FirstOrderModelFmc* fm,
841
                                             Node f,
842
                                             Node c)
843
{
844
5249
  Trace("fmc-exh") << "----Exhaustive instantiate based on " << c << " ";
845
5249
  debugPrintCond("fmc-exh", c, true);
846
5249
  Trace("fmc-exh")<< std::endl;
847
5249
  QuantifiersBoundInference& qbi = d_qreg.getQuantifiersBoundInference();
848
10498
  RepBoundFmcEntry rbfe(qbi, c, fm);
849
10498
  RepSetIterator riter(fm->getRepSet(), &rbfe);
850
5249
  Trace("fmc-exh-debug") << "Set quantifier..." << std::endl;
851
  //initialize
852
5249
  if (riter.setQuantifier(f))
853
  {
854
5249
    Trace("fmc-exh-debug") << "Set element domains..." << std::endl;
855
5249
    int addedLemmas = 0;
856
    //now do full iteration
857
5249
    Instantiate* ie = d_qim.getInstantiate();
858
66333
    while( !riter.isFinished() ){
859
30542
      d_triedLemmas++;
860
30542
      Trace("fmc-exh-debug") << "Inst : ";
861
61084
      std::vector< Node > ev_inst;
862
61084
      std::vector< Node > inst;
863
106338
      for (unsigned i = 0; i < riter.getNumTerms(); i++)
864
      {
865
151592
        TypeNode tn = riter.getTypeOf(i);
866
        // if the type is not closed enumerable (see
867
        // TypeNode::isClosedEnumerable), then we must ensure that we are
868
        // using a term and not a value. This ensures that e.g. uninterpreted
869
        // constants do not appear in instantiations.
870
151592
        Node rr = riter.getCurrentTerm(i, !tn.isClosedEnumerable());
871
151592
        Node r = fm->getRepresentative(rr);
872
75796
        debugPrint("fmc-exh-debug", r);
873
75796
        Trace("fmc-exh-debug") << " (term : " << rr << ")";
874
75796
        ev_inst.push_back( r );
875
75796
        inst.push_back( rr );
876
      }
877
30542
      int ev_index = d_quant_models[f].getGeneralizationIndex(fm, ev_inst);
878
30542
      Trace("fmc-exh-debug") << ", index = " << ev_index << " / " << d_quant_models[f].d_value.size();
879
61084
      Node ev = ev_index==-1 ? Node::null() : d_quant_models[f].d_value[ev_index];
880
30542
      if (ev!=d_true) {
881
27816
        Trace("fmc-exh-debug") << ", add!";
882
        //add as instantiation
883
55632
        if (ie->addInstantiation(f,
884
                                 inst,
885
                                 InferenceId::QUANTIFIERS_INST_FMF_FMC_EXH,
886
55632
                                 Node::null(),
887
                                 true))
888
        {
889
4946
          Trace("fmc-exh-debug")  << " ...success.";
890
4946
          addedLemmas++;
891
4946
          if (d_qstate.isInConflict() || options::fmfOneInstPerRound())
892
          {
893
            break;
894
          }
895
        }else{
896
22870
          Trace("fmc-exh-debug") << ", failed.";
897
        }
898
      }else{
899
2726
        Trace("fmc-exh-debug") << ", already true";
900
      }
901
30542
      Trace("fmc-exh-debug") << std::endl;
902
30542
      int index = riter.increment();
903
30542
      Trace("fmc-exh-debug") << "Incremented index " << index << std::endl;
904
30542
      if( !riter.isFinished() ){
905
78789
        if (index >= 0 && riter.d_index[index] > 0 && addedLemmas > 0
906
32941
            && riter.d_enum_type[index] == ENUM_CUSTOM)
907
        {
908
2776
          Trace("fmc-exh-debug")
909
1388
              << "Since this is a custom enumeration, skip to the next..."
910
1388
              << std::endl;
911
1388
          riter.incrementAtIndex(index - 1);
912
        }
913
      }
914
    }
915
5249
    d_addedLemmas += addedLemmas;
916
5249
    Trace("fmc-exh") << "----Finished Exhaustive instantiate, lemmas = " << addedLemmas << ", incomplete=" << riter.isIncomplete() << std::endl;
917
5249
    return addedLemmas>0 || !riter.isIncomplete();
918
  }else{
919
    Trace("fmc-exh") << "----Finished Exhaustive instantiate, failed." << std::endl;
920
    return !riter.isIncomplete();
921
  }
922
}
923
924
116020
void FullModelChecker::doCheck(FirstOrderModelFmc * fm, Node f, Def & d, Node n ) {
925
116020
  Trace("fmc-debug") << "Check " << n << " " << n.getKind() << std::endl;
926
  //first check if it is a bounding literal
927
116020
  if( n.hasAttribute(BoundIntLitAttribute()) ){
928
2836
    Trace("fmc-debug") << "It is a bounding literal, polarity = " << n.getAttribute(BoundIntLitAttribute()) << std::endl;
929
2836
    d.addEntry(fm, mkCondDefault(fm, f), n.getAttribute(BoundIntLitAttribute())==1 ? d_false : d_true );
930
113184
  }else if( n.getKind() == kind::BOUND_VARIABLE ){
931
26110
    Trace("fmc-debug") << "Add default entry..." << std::endl;
932
26110
    d.addEntry(fm, mkCondDefault(fm, f), n);
933
  }
934
87074
  else if( n.getKind() == kind::NOT ){
935
    //just do directly
936
8958
    doCheck( fm, f, d, n[0] );
937
8958
    doNegate( d );
938
  }
939
78116
  else if( n.getKind() == kind::FORALL ){
940
2009
    d.addEntry(fm, mkCondDefault(fm, f), Node::null());
941
  }
942
76107
  else if( n.getType().isArray() ){
943
    //Trace("fmc-warn") << "WARNING : ARRAYS : Can't process base array " << r << std::endl;
944
    //Trace("fmc-warn") << "          Default value was : " << odefaultValue << std::endl;
945
    //Trace("fmc-debug") << "Can't process base array " << r << std::endl;
946
    //can't process this array
947
436
    d.reset();
948
436
    d.addEntry(fm, mkCondDefault(fm, f), Node::null());
949
  }
950
75671
  else if( n.getNumChildren()==0 ){
951
40730
    Node r = n;
952
20365
    if( !n.isConst() ){
953
17622
      TypeNode tn = n.getType();
954
8811
      if (!fm->hasTerm(n) && tn.isFirstClass())
955
      {
956
        // if the term is unknown, we do not assume any value for it
957
168
        r = Node::null();
958
      }
959
      else
960
      {
961
8643
        r = fm->getRepresentative(r);
962
      }
963
    }
964
20365
    Trace("fmc-debug") << "Add constant entry..." << std::endl;
965
20365
    d.addEntry(fm, mkCondDefault(fm, f), r);
966
  }
967
  else{
968
110612
    std::vector< int > var_ch;
969
110612
    std::vector< Def > children;
970
155706
    for( int i=0; i<(int)n.getNumChildren(); i++) {
971
200800
      Def dc;
972
100400
      doCheck(fm, f, dc, n[i]);
973
100400
      children.push_back(dc);
974
100400
      if( n[i].getKind() == kind::BOUND_VARIABLE ){
975
26102
        var_ch.push_back(i);
976
      }
977
    }
978
979
55306
    if( n.getKind()==APPLY_UF ){
980
24365
      Trace("fmc-debug") << "Do uninterpreted compose " << n << std::endl;
981
      //uninterpreted compose
982
24365
      doUninterpretedCompose( fm, f, d, n.getOperator(), children );
983
      /*
984
    } else if( n.getKind()==SELECT ){
985
      Trace("fmc-debug") << "Do select compose " << n << std::endl;
986
      std::vector< Def > children2;
987
      children2.push_back( children[1] );
988
      std::vector< Node > cond;
989
      mkCondDefaultVec(fm, f, cond);
990
      std::vector< Node > val;
991
      doUninterpretedCompose(fm, f, d, children[0], children2, 0, cond, val );
992
      */
993
    } else {
994
30941
      if( !var_ch.empty() ){
995
4209
        if( n.getKind()==EQUAL && !n[0].getType().isBoolean() ){
996
808
          if( var_ch.size()==2 ){
997
318
            Trace("fmc-debug") << "Do variable equality " << n << std::endl;
998
318
            doVariableEquality( fm, f, d, n );
999
          }else{
1000
490
            Trace("fmc-debug") << "Do variable relation " << n << std::endl;
1001
490
            doVariableRelation( fm, f, d, var_ch[0]==0 ? children[1] : children[0], var_ch[0]==0 ? n[0] : n[1] );
1002
          }
1003
        }else{
1004
3401
          Trace("fmc-warn") << "Don't know how to check " << n << std::endl;
1005
3401
          d.addEntry(fm, mkCondDefault(fm, f), Node::null());
1006
        }
1007
      }else{
1008
26732
        Trace("fmc-debug") << "Do interpreted compose " << n << std::endl;
1009
53464
        std::vector< Node > cond;
1010
26732
        mkCondDefaultVec(fm, f, cond);
1011
53464
        std::vector< Node > val;
1012
        //interpreted compose
1013
26732
        doInterpretedCompose( fm, f, d, n, children, 0, cond, val );
1014
      }
1015
    }
1016
55306
    Trace("fmc-debug") << "Simplify the definition..." << std::endl;
1017
55306
    d.debugPrint("fmc-debug", Node::null(), this);
1018
55306
    d.simplify(this, fm);
1019
55306
    Trace("fmc-debug") << "Done simplifying" << std::endl;
1020
  }
1021
116020
  Trace("fmc-debug") << "Definition for " << n << " is : " << std::endl;
1022
116020
  d.debugPrint("fmc-debug", Node::null(), this);
1023
116020
  Trace("fmc-debug") << std::endl;
1024
116020
}
1025
1026
8958
void FullModelChecker::doNegate( Def & dc ) {
1027
20512
  for (unsigned i=0; i<dc.d_cond.size(); i++) {
1028
23108
    Node v = dc.d_value[i];
1029
11554
    if (!v.isNull())
1030
    {
1031
      // In the case that the value is not-constant, we cannot reason about
1032
      // its value (since the range of this must be a constant or variable).
1033
      // In particular, returning null here is important if we have (not x)
1034
      // where x is a bound variable.
1035
8303
      dc.d_value[i] =
1036
16606
          v == d_true ? d_false : (v == d_false ? d_true : Node::null());
1037
    }
1038
  }
1039
8958
}
1040
1041
318
void FullModelChecker::doVariableEquality( FirstOrderModelFmc * fm, Node f, Def & d, Node eq ) {
1042
636
  std::vector<Node> cond;
1043
318
  mkCondDefaultVec(fm, f, cond);
1044
318
  if (eq[0]==eq[1]){
1045
    d.addEntry(fm, mkCond(cond), d_true);
1046
  }else{
1047
636
    TypeNode tn = eq[0].getType();
1048
318
    if( tn.isSort() ){
1049
318
      int j = fm->getVariableId(f, eq[0]);
1050
318
      int k = fm->getVariableId(f, eq[1]);
1051
318
      const RepSet* rs = fm->getRepSet();
1052
318
      if (!rs->hasType(tn))
1053
      {
1054
        getSomeDomainElement( fm, tn );  //to verify the type is initialized
1055
      }
1056
318
      unsigned nreps = rs->getNumRepresentatives(tn);
1057
912
      for (unsigned i = 0; i < nreps; i++)
1058
      {
1059
1188
        Node r = fm->getRepresentative(rs->getRepresentative(tn, i));
1060
594
        cond[j+1] = r;
1061
594
        cond[k+1] = r;
1062
594
        d.addEntry( fm, mkCond(cond), d_true);
1063
      }
1064
318
      d.addEntry( fm, mkCondDefault(fm, f), d_false);
1065
    }else{
1066
      d.addEntry( fm, mkCondDefault(fm, f), Node::null());
1067
    }
1068
  }
1069
318
}
1070
1071
490
void FullModelChecker::doVariableRelation( FirstOrderModelFmc * fm, Node f, Def & d, Def & dc, Node v) {
1072
490
  int j = fm->getVariableId(f, v);
1073
1114
  for (unsigned i=0; i<dc.d_cond.size(); i++) {
1074
1248
    Node val = dc.d_value[i];
1075
624
    if( val.isNull() ){
1076
33
      d.addEntry( fm, dc.d_cond[i], val);
1077
    }else{
1078
591
      if( dc.d_cond[i][j]!=val ){
1079
469
        if (fm->isStar(dc.d_cond[i][j])) {
1080
914
          std::vector<Node> cond;
1081
457
          mkCondVec(dc.d_cond[i],cond);
1082
457
          cond[j+1] = val;
1083
457
          d.addEntry(fm, mkCond(cond), d_true);
1084
457
          cond[j+1] = fm->getStar(val.getType());
1085
457
          d.addEntry(fm, mkCond(cond), d_false);
1086
        }else{
1087
12
          d.addEntry( fm, dc.d_cond[i], d_false);
1088
        }
1089
      }else{
1090
122
        d.addEntry( fm, dc.d_cond[i], d_true);
1091
      }
1092
    }
1093
  }
1094
490
}
1095
1096
24365
void FullModelChecker::doUninterpretedCompose( FirstOrderModelFmc * fm, Node f, Def & d, Node op, std::vector< Def > & dc ) {
1097
24365
  Trace("fmc-uf-debug") << "Definition : " << std::endl;
1098
24365
  fm->d_models[op]->debugPrint("fmc-uf-debug", op, this);
1099
24365
  Trace("fmc-uf-debug") << std::endl;
1100
1101
48730
  std::vector< Node > cond;
1102
24365
  mkCondDefaultVec(fm, f, cond);
1103
48730
  std::vector< Node > val;
1104
24365
  doUninterpretedCompose( fm, f, d, *fm->d_models[op], dc, 0, cond, val);
1105
24365
}
1106
1107
67476
void FullModelChecker::doUninterpretedCompose( FirstOrderModelFmc * fm, Node f, Def & d,
1108
                                               Def & df, std::vector< Def > & dc, int index,
1109
                                               std::vector< Node > & cond, std::vector<Node> & val ) {
1110
67476
  Trace("fmc-uf-process") << "process at " << index << std::endl;
1111
184241
  for( unsigned i=1; i<cond.size(); i++) {
1112
116765
    debugPrint("fmc-uf-process", cond[i], true);
1113
116765
    Trace("fmc-uf-process") << " ";
1114
  }
1115
67476
  Trace("fmc-uf-process") << std::endl;
1116
67476
  if (index==(int)dc.size()) {
1117
    //we have an entry, now do actual compose
1118
60914
    std::map< int, Node > entries;
1119
30457
    doUninterpretedCompose2( fm, f, entries, 0, cond, val, df.d_et);
1120
30457
    if( entries.empty() ){
1121
1196
      d.addEntry(fm, mkCond(cond), Node::null());
1122
    }else{
1123
      //add them to the definition
1124
96952
      for( unsigned e=0; e<df.d_cond.size(); e++ ){
1125
67691
        if ( entries.find(e)!=entries.end() ){
1126
48617
          Trace("fmf-uf-process-debug") << "Add entry..." << std::endl;
1127
48617
          d.addEntry(fm, entries[e], df.d_value[e] );
1128
48617
          Trace("fmf-uf-process-debug") << "Done add entry." << std::endl;
1129
        }
1130
      }
1131
    }
1132
  }else{
1133
85948
    for (unsigned i=0; i<dc[index].d_cond.size(); i++) {
1134
48929
      if (isCompat(fm, cond, dc[index].d_cond[i])!=0) {
1135
86222
        std::vector< Node > new_cond;
1136
43111
        new_cond.insert(new_cond.end(), cond.begin(), cond.end());
1137
43111
        if( doMeet(fm, new_cond, dc[index].d_cond[i]) ){
1138
43111
          Trace("fmc-uf-process") << "index " << i << " succeeded meet." << std::endl;
1139
43111
          val.push_back(dc[index].d_value[i]);
1140
43111
          doUninterpretedCompose(fm, f, d, df, dc, index+1, new_cond, val);
1141
43111
          val.pop_back();
1142
        }else{
1143
          Trace("fmc-uf-process") << "index " << i << " failed meet." << std::endl;
1144
        }
1145
      }
1146
    }
1147
  }
1148
67476
}
1149
1150
101468
void FullModelChecker::doUninterpretedCompose2( FirstOrderModelFmc * fm, Node f,
1151
                                                std::map< int, Node > & entries, int index,
1152
                                                std::vector< Node > & cond, std::vector< Node > & val,
1153
                                                EntryTrie & curr ) {
1154
101468
  Trace("fmc-uf-process") << "compose " << index << " / " << val.size() << std::endl;
1155
276242
  for( unsigned i=1; i<cond.size(); i++) {
1156
174774
    debugPrint("fmc-uf-process", cond[i], true);
1157
174774
    Trace("fmc-uf-process") << " ";
1158
  }
1159
101468
  Trace("fmc-uf-process") << std::endl;
1160
101468
  if (index==(int)val.size()) {
1161
97234
    Node c = mkCond(cond);
1162
48617
    Trace("fmc-uf-entry") << "Entry : " << c << " -> index[" << curr.d_data << "]" << std::endl;
1163
48617
    entries[curr.d_data] = c;
1164
  }else{
1165
105702
    Node v = val[index];
1166
52851
    Trace("fmc-uf-process") << "Process " << v << std::endl;
1167
52851
    bool bind_var = false;
1168
52851
    if( !v.isNull() && v.getKind()==kind::BOUND_VARIABLE ){
1169
24591
      int j = fm->getVariableId(f, v);
1170
24591
      Trace("fmc-uf-process") << v << " is variable #" << j << std::endl;
1171
24591
      if (!fm->isStar(cond[j + 1]))
1172
      {
1173
38
        v = cond[j+1];
1174
      }else{
1175
24553
        bind_var = true;
1176
      }
1177
    }
1178
52851
    if (bind_var) {
1179
24553
      Trace("fmc-uf-process") << "bind variable..." << std::endl;
1180
24553
      int j = fm->getVariableId(f, v);
1181
24553
      Assert(fm->isStar(cond[j + 1]));
1182
64554
      for (std::map<Node, EntryTrie>::iterator it = curr.d_child.begin();
1183
64554
           it != curr.d_child.end();
1184
           ++it)
1185
      {
1186
40001
        cond[j + 1] = it->first;
1187
40001
        doUninterpretedCompose2(
1188
40001
            fm, f, entries, index + 1, cond, val, it->second);
1189
      }
1190
24553
      cond[j + 1] = fm->getStar(v.getType());
1191
    }else{
1192
28298
      if( !v.isNull() ){
1193
27093
        if (curr.d_child.find(v) != curr.d_child.end())
1194
        {
1195
8067
          Trace("fmc-uf-process") << "follow value..." << std::endl;
1196
8067
          doUninterpretedCompose2(
1197
8067
              fm, f, entries, index + 1, cond, val, curr.d_child[v]);
1198
        }
1199
54186
        Node st = fm->getStar(v.getType());
1200
27093
        if (curr.d_child.find(st) != curr.d_child.end())
1201
        {
1202
22943
          Trace("fmc-uf-process") << "follow star..." << std::endl;
1203
22943
          doUninterpretedCompose2(
1204
22943
              fm, f, entries, index + 1, cond, val, curr.d_child[st]);
1205
        }
1206
      }
1207
    }
1208
  }
1209
101468
}
1210
1211
109943
void FullModelChecker::doInterpretedCompose( FirstOrderModelFmc * fm, Node f, Def & d, Node n,
1212
                                             std::vector< Def > & dc, int index,
1213
                                             std::vector< Node > & cond, std::vector<Node> & val ) {
1214
109943
  Trace("fmc-if-process") << "int compose " << index << " / " << dc.size() << std::endl;
1215
264817
  for( unsigned i=1; i<cond.size(); i++) {
1216
154874
    debugPrint("fmc-if-process", cond[i], true);
1217
154874
    Trace("fmc-if-process") << " ";
1218
  }
1219
109943
  Trace("fmc-if-process") << std::endl;
1220
109943
  if ( index==(int)dc.size() ){
1221
92752
    Node c = mkCond(cond);
1222
92752
    Node v = evaluateInterpreted(n, val);
1223
46376
    d.addEntry(fm, c, v);
1224
  }
1225
  else {
1226
127134
    TypeNode vtn = n.getType();
1227
165826
    for (unsigned i=0; i<dc[index].d_cond.size(); i++) {
1228
102259
      if (isCompat(fm, cond, dc[index].d_cond[i])!=0) {
1229
181566
        std::vector< Node > new_cond;
1230
90783
        new_cond.insert(new_cond.end(), cond.begin(), cond.end());
1231
90783
        if( doMeet(fm, new_cond, dc[index].d_cond[i]) ){
1232
90783
          bool process = true;
1233
90783
          if (vtn.isBoolean()) {
1234
            //short circuit
1235
116763
            if( (n.getKind()==OR && dc[index].d_value[i]==d_true) ||
1236
55011
                (n.getKind()==AND && dc[index].d_value[i]==d_false) ){
1237
15144
              Node c = mkCond(new_cond);
1238
7572
              d.addEntry(fm, c, dc[index].d_value[i]);
1239
7572
              process = false;
1240
            }
1241
          }
1242
90783
          if (process) {
1243
83211
            val.push_back(dc[index].d_value[i]);
1244
83211
            doInterpretedCompose(fm, f, d, n, dc, index+1, new_cond, val);
1245
83211
            val.pop_back();
1246
          }
1247
        }
1248
      }
1249
    }
1250
  }
1251
109943
}
1252
1253
151188
int FullModelChecker::isCompat( FirstOrderModelFmc * fm, std::vector< Node > & cond, Node c ) {
1254
151188
  Trace("fmc-debug3") << "isCompat " << c << std::endl;
1255
151188
  Assert(cond.size() == c.getNumChildren() + 1);
1256
386114
  for (unsigned i=1; i<cond.size(); i++) {
1257
252220
    if (cond[i] != c[i - 1] && !fm->isStar(cond[i]) && !fm->isStar(c[i - 1]))
1258
    {
1259
17294
      return 0;
1260
    }
1261
  }
1262
133894
  return 1;
1263
}
1264
1265
133894
bool FullModelChecker::doMeet( FirstOrderModelFmc * fm, std::vector< Node > & cond, Node c ) {
1266
133894
  Trace("fmc-debug3") << "doMeet " << c << std::endl;
1267
133894
  Assert(cond.size() == c.getNumChildren() + 1);
1268
353488
  for (unsigned i=1; i<cond.size(); i++) {
1269
219594
    if( cond[i]!=c[i-1] ) {
1270
64815
      if (fm->isStar(cond[i]))
1271
      {
1272
36625
        cond[i] = c[i - 1];
1273
      }
1274
28190
      else if (!fm->isStar(c[i - 1]))
1275
      {
1276
        return false;
1277
      }
1278
    }
1279
  }
1280
133894
  return true;
1281
}
1282
1283
164285
Node FullModelChecker::mkCond( std::vector< Node > & cond ) {
1284
164285
  return NodeManager::currentNM()->mkNode(APPLY_UF, cond);
1285
}
1286
1287
57661
Node FullModelChecker::mkCondDefault( FirstOrderModelFmc * fm, Node f) {
1288
115322
  std::vector< Node > cond;
1289
57661
  mkCondDefaultVec(fm, f, cond);
1290
115322
  return mkCond(cond);
1291
}
1292
1293
109076
void FullModelChecker::mkCondDefaultVec( FirstOrderModelFmc * fm, Node f, std::vector< Node > & cond ) {
1294
109076
  Trace("fmc-debug") << "Make default vec" << std::endl;
1295
  //get function symbol for f
1296
109076
  cond.push_back(d_quant_cond[f]);
1297
274262
  for (unsigned i=0; i<f[0].getNumChildren(); i++) {
1298
330372
    Node ts = fm->getStar(f[0][i].getType());
1299
165186
    Assert(ts.getType() == f[0][i].getType());
1300
165186
    cond.push_back(ts);
1301
  }
1302
109076
}
1303
1304
457
void FullModelChecker::mkCondVec( Node n, std::vector< Node > & cond ) {
1305
457
  cond.push_back(n.getOperator());
1306
1034
  for( unsigned i=0; i<n.getNumChildren(); i++ ){
1307
577
    cond.push_back( n[i] );
1308
  }
1309
457
}
1310
1311
46376
Node FullModelChecker::evaluateInterpreted( Node n, std::vector< Node > & vals ) {
1312
46376
  if( n.getKind()==EQUAL && !n[0].getType().isBoolean() ){
1313
11505
    if (!vals[0].isNull() && !vals[1].isNull()) {
1314
9706
      return vals[0]==vals[1] ? d_true : d_false;
1315
    }else{
1316
1799
      return Node::null();
1317
    }
1318
34871
  }else if( n.getKind()==ITE ){
1319
3832
    if( vals[0]==d_true ){
1320
1704
      return vals[1];
1321
2128
    }else if( vals[0]==d_false ){
1322
2040
      return vals[2];
1323
    }else{
1324
88
      return vals[1]==vals[2] ? vals[1] : Node::null();
1325
    }
1326
31039
  }else if( n.getKind()==AND || n.getKind()==OR ){
1327
5841
    bool isNull = false;
1328
22497
    for (unsigned i=0; i<vals.size(); i++) {
1329
16656
      if((vals[i]==d_true && n.getKind()==OR) || (vals[i]==d_false && n.getKind()==AND)) {
1330
        return vals[i];
1331
16656
      }else if( vals[i].isNull() ){
1332
4152
        isNull = true;
1333
      }
1334
    }
1335
5841
    return isNull ? Node::null() : vals[0];
1336
  }else{
1337
50396
    std::vector<Node> children;
1338
25198
    if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){
1339
7865
      children.push_back( n.getOperator() );
1340
    }
1341
64051
    for (unsigned i=0; i<vals.size(); i++) {
1342
42380
      if( vals[i].isNull() ){
1343
3527
        return Node::null();
1344
      }else{
1345
38853
        children.push_back( vals[i] );
1346
      }
1347
    }
1348
43342
    Node nc = NodeManager::currentNM()->mkNode(n.getKind(), children);
1349
21671
    Trace("fmc-eval") << "Evaluate " << nc << " to ";
1350
21671
    nc = rewrite(nc);
1351
21671
    Trace("fmc-eval") << nc << std::endl;
1352
21671
    return nc;
1353
  }
1354
}
1355
1356
3416
Node FullModelChecker::getSomeDomainElement( FirstOrderModelFmc * fm, TypeNode tn ) {
1357
3416
  bool addRepId = !fm->getRepSet()->hasType(tn);
1358
3416
  Node de = fm->getSomeDomainElement(tn);
1359
3416
  if( addRepId ){
1360
122
    d_rep_ids[tn][de] = 0;
1361
  }
1362
3416
  return de;
1363
}
1364
1365
7286
Node FullModelChecker::getFunctionValue(FirstOrderModelFmc * fm, Node op, const char* argPrefix ) {
1366
7286
  return fm->getFunctionValue(op, argPrefix);
1367
}
1368
1369
1370
38933
bool FullModelChecker::useSimpleModels() {
1371
38933
  return options::fmfFmcSimple();
1372
}
1373
20932
void FullModelChecker::registerQuantifiedFormula(Node q)
1374
{
1375
20932
  if (d_quant_cond.find(q) != d_quant_cond.end())
1376
  {
1377
19386
    return;
1378
  }
1379
1546
  NodeManager* nm = NodeManager::currentNM();
1380
1546
  SkolemManager* sm = nm->getSkolemManager();
1381
3092
  std::vector<TypeNode> types;
1382
3805
  for (const Node& v : q[0])
1383
  {
1384
4518
    TypeNode tn = v.getType();
1385
2259
    if (tn.isFunction())
1386
    {
1387
      // we will not use model-based quantifier instantiation for q, since
1388
      // the model-based instantiation algorithm does not handle (universally
1389
      // quantified) functions
1390
42
      d_unhandledQuant.insert(q);
1391
    }
1392
2259
    types.push_back(tn);
1393
  }
1394
3092
  TypeNode typ = nm->mkFunctionType(types, nm->booleanType());
1395
3092
  Node op = sm->mkDummySkolem("qfmc", typ, "op for full-model checking");
1396
1546
  d_quant_cond[q] = op;
1397
}
1398
1399
20932
bool FullModelChecker::isHandled(Node q) const
1400
{
1401
20932
  return d_unhandledQuant.find(q) == d_unhandledQuant.end();
1402
}
1403
1404
}  // namespace fmcheck
1405
}  // namespace quantifiers
1406
}  // namespace theory
1407
31137
}  // namespace cvc5