GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/first_order_model.cpp Lines: 161 180 89.4 %
Date: 2021-09-07 Branches: 246 534 46.1 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, 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 model engine model class.
14
 */
15
16
#include "theory/quantifiers/first_order_model.h"
17
#include "options/base_options.h"
18
#include "options/quantifiers_options.h"
19
#include "theory/quantifiers/fmf/bounded_integers.h"
20
#include "theory/quantifiers/fmf/model_engine.h"
21
#include "theory/quantifiers/quantifiers_attributes.h"
22
#include "theory/quantifiers/term_database.h"
23
#include "theory/quantifiers/term_enumeration.h"
24
#include "theory/quantifiers/term_registry.h"
25
#include "theory/quantifiers/term_util.h"
26
27
using namespace cvc5::kind;
28
using namespace cvc5::context;
29
30
namespace cvc5 {
31
namespace theory {
32
namespace quantifiers {
33
34
struct ModelBasisAttributeId
35
{
36
};
37
using ModelBasisAttribute = expr::Attribute<ModelBasisAttributeId, bool>;
38
// for APPLY_UF terms, 1 : term has direct child with model basis attribute,
39
//                     0 : term has no direct child with model basis attribute.
40
struct ModelBasisArgAttributeId
41
{
42
};
43
using ModelBasisArgAttribute = expr::Attribute<ModelBasisArgAttributeId, uint64_t>;
44
45
9926
FirstOrderModel::FirstOrderModel(QuantifiersState& qs,
46
                                 QuantifiersRegistry& qr,
47
9926
                                 TermRegistry& tr)
48
    : d_model(nullptr),
49
      d_qreg(qr),
50
      d_treg(tr),
51
      d_eq_query(qs, this),
52
      d_forall_asserts(qs.getSatContext()),
53
9926
      d_forallRlvComputed(false)
54
{
55
9926
}
56
57
6835
void FirstOrderModel::finishInit(TheoryModel* m) { d_model = m; }
58
59
131965
Node FirstOrderModel::getValue(TNode n) const { return d_model->getValue(n); }
60
8578
bool FirstOrderModel::hasTerm(TNode a) { return d_model->hasTerm(a); }
61
237804
Node FirstOrderModel::getRepresentative(TNode a)
62
{
63
237804
  return d_model->getRepresentative(a);
64
}
65
bool FirstOrderModel::areEqual(TNode a, TNode b)
66
{
67
  return d_model->areEqual(a, b);
68
}
69
bool FirstOrderModel::areDisequal(TNode a, TNode b)
70
{
71
  return d_model->areDisequal(a, b);
72
}
73
eq::EqualityEngine* FirstOrderModel::getEqualityEngine()
74
{
75
  return d_model->getEqualityEngine();
76
}
77
169003
const RepSet* FirstOrderModel::getRepSet() const
78
{
79
169003
  return d_model->getRepSet();
80
}
81
11247
RepSet* FirstOrderModel::getRepSetPtr() { return d_model->getRepSetPtr(); }
82
TheoryModel* FirstOrderModel::getTheoryModel() { return d_model; }
83
84
76309
Node FirstOrderModel::getInternalRepresentative(Node a, Node q, size_t index)
85
{
86
76309
  return d_eq_query.getInternalRepresentative(a, q, index);
87
}
88
89
69004
void FirstOrderModel::assertQuantifier( Node n ){
90
69004
  if( n.getKind()==FORALL ){
91
69004
    d_forall_asserts.push_back( n );
92
  }else if( n.getKind()==NOT ){
93
    Assert(n[0].getKind() == FORALL);
94
  }
95
69004
}
96
97
102588
size_t FirstOrderModel::getNumAssertedQuantifiers() const
98
{
99
102588
  return d_forall_asserts.size();
100
}
101
102
698564
Node FirstOrderModel::getAssertedQuantifier( unsigned i, bool ordered ) {
103
698564
  if( !ordered || !d_forallRlvComputed ){
104
462739
    return d_forall_asserts[i];
105
  }
106
  // If we computed the relevant forall assertion vector, in reset_round,
107
  // then it should have the same size as the default assertion vector.
108
235825
  Assert(d_forall_rlv_assert.size() == d_forall_asserts.size());
109
235825
  return d_forall_rlv_assert[i];
110
}
111
112
2046
void FirstOrderModel::initialize() {
113
2046
  processInitialize( true );
114
  //this is called after representatives have been chosen and the equality engine has been built
115
  //for each quantifier, collect all operators we care about
116
11211
  for( unsigned i=0; i<getNumAssertedQuantifiers(); i++ ){
117
18330
    Node f = getAssertedQuantifier( i );
118
9165
    if( d_quant_var_id.find( f )==d_quant_var_id.end() ){
119
3705
      for(unsigned j=0; j<f[0].getNumChildren(); j++){
120
2205
        d_quant_var_id[f][f[0][j]] = j;
121
      }
122
    }
123
9165
    processInitializeQuantifier( f );
124
    //initialize relevant models within bodies of all quantifiers
125
18330
    std::map< Node, bool > visited;
126
9165
    initializeModelForTerm( f[1], visited );
127
  }
128
2046
  processInitialize( false );
129
2046
}
130
131
220271
void FirstOrderModel::initializeModelForTerm( Node n, std::map< Node, bool >& visited ){
132
220271
  if( visited.find( n )==visited.end() ){
133
159333
    visited[n] = true;
134
159333
    processInitializeModelForTerm( n );
135
370439
    for( int i=0; i<(int)n.getNumChildren(); i++ ){
136
211106
      initializeModelForTerm( n[i], visited );
137
    }
138
  }
139
220271
}
140
141
3534
Node FirstOrderModel::getSomeDomainElement(TypeNode tn){
142
  //check if there is even any domain elements at all
143
3534
  RepSet* rs = d_model->getRepSetPtr();
144
3534
  if (!rs->hasType(tn) || rs->getNumRepresentatives(tn) == 0)
145
  {
146
246
    Trace("fm-debug") << "Must create domain element for " << tn << "..."
147
123
                      << std::endl;
148
246
    Node mbt = getModelBasisTerm(tn);
149
123
    Trace("fm-debug") << "Add to representative set..." << std::endl;
150
123
    rs->add(tn, mbt);
151
  }
152
3534
  return rs->getRepresentative(tn, 0);
153
}
154
155
7488
bool FirstOrderModel::initializeRepresentativesForType(TypeNode tn)
156
{
157
7488
  RepSet* rs = d_model->getRepSetPtr();
158
7488
  if (tn.isSort())
159
  {
160
    // must ensure uninterpreted type is non-empty.
161
1812
    if (!rs->hasType(tn))
162
    {
163
      // terms in rep_set are now constants which mapped to terms through
164
      // TheoryModel. Thus, should introduce a constant and a term.
165
      // For now, we just add an arbitrary term.
166
14
      Node var = getSomeDomainElement(tn);
167
14
      Trace("mkVar") << "RepSetIterator:: Make variable " << var << " : " << tn
168
7
                     << std::endl;
169
7
      rs->add(tn, var);
170
    }
171
1812
    return true;
172
  }
173
  else
174
  {
175
    // can we complete it?
176
5676
    if (d_qreg.getQuantifiersBoundInference().mayComplete(tn))
177
    {
178
4260
      Trace("fm-debug") << "  do complete, since cardinality is small ("
179
2130
                        << tn.getCardinality() << ")..." << std::endl;
180
2130
      rs->complete(tn);
181
      // must have succeeded
182
2130
      Assert(rs->hasType(tn));
183
2130
      return true;
184
    }
185
3546
    Trace("fm-debug") << "  variable cannot be bounded." << std::endl;
186
3546
    return false;
187
  }
188
}
189
190
bool FirstOrderModel::isModelBasis(TNode n)
191
{
192
  return n.getAttribute(ModelBasisAttribute());
193
}
194
195
9926
EqualityQuery* FirstOrderModel::getEqualityQuery() { return &d_eq_query; }
196
197
/** needs check */
198
102741
bool FirstOrderModel::checkNeeded() {
199
102741
  return d_forall_asserts.size()>0;
200
}
201
202
28464
void FirstOrderModel::reset_round() {
203
28464
  d_quant_active.clear();
204
205
  // compute which quantified formulas are asserted if necessary
206
56928
  std::map<Node, bool> qassert;
207
28464
  if (!d_forall_rlv_vec.empty())
208
  {
209
6342
    Trace("fm-relevant-debug")
210
3171
        << "Mark asserted quantified formulas..." << std::endl;
211
150621
    for (const Node& q : d_forall_asserts)
212
    {
213
147450
      qassert[q] = true;
214
    }
215
  }
216
  //order the quantified formulas
217
28464
  d_forall_rlv_assert.clear();
218
28464
  d_forallRlvComputed = false;
219
28464
  if( !d_forall_rlv_vec.empty() ){
220
3171
    d_forallRlvComputed = true;
221
3171
    Trace("fm-relevant") << "Build sorted relevant list..." << std::endl;
222
3171
    Trace("fm-relevant-debug") << "Add relevant asserted formulas..." << std::endl;
223
3171
    std::map<Node, bool>::iterator ita;
224
10981
    for( int i=(int)(d_forall_rlv_vec.size()-1); i>=0; i-- ){
225
15620
      Node q = d_forall_rlv_vec[i];
226
7810
      ita = qassert.find(q);
227
7810
      if (ita != qassert.end())
228
      {
229
7476
        Trace("fm-relevant") << "   " << q << std::endl;
230
7476
        d_forall_rlv_assert.push_back( q );
231
7476
        qassert.erase(ita);
232
      }
233
    }
234
3171
    Trace("fm-relevant-debug") << "Add remaining asserted formulas..." << std::endl;
235
150621
    for (const Node& q : d_forall_asserts)
236
    {
237
      // if we didn't include it above
238
147450
      if (qassert.find(q) != qassert.end())
239
      {
240
139974
        d_forall_rlv_assert.push_back( q );
241
      }else{
242
7476
        Trace("fm-relevant-debug") << "...already included " << q << std::endl;
243
      }
244
    }
245
3171
    Trace("fm-relevant-debug") << "Sizes : " << d_forall_rlv_assert.size() << " " << d_forall_asserts.size() << std::endl;
246
3171
    Assert(d_forall_rlv_assert.size() == d_forall_asserts.size());
247
  }
248
28464
}
249
250
2285
void FirstOrderModel::markRelevant( Node q ) {
251
  // Put q on the back of the vector d_forall_rlv_vec.
252
  // If we were the last quantifier marked relevant, this is a no-op, return.
253
2285
  if( q!=d_last_forall_rlv ){
254
1103
    Trace("fm-relevant") << "Mark relevant : " << q << std::endl;
255
    std::vector<Node>::iterator itr =
256
1103
        std::find(d_forall_rlv_vec.begin(), d_forall_rlv_vec.end(), q);
257
1103
    if (itr != d_forall_rlv_vec.end())
258
    {
259
139
      d_forall_rlv_vec.erase(itr, itr + 1);
260
    }
261
1103
    d_forall_rlv_vec.push_back(q);
262
1103
    d_last_forall_rlv = q;
263
  }
264
2285
}
265
266
1522
void FirstOrderModel::setQuantifierActive( TNode q, bool active ) {
267
1522
  d_quant_active[q] = active;
268
1522
}
269
270
319908
bool FirstOrderModel::isQuantifierActive(TNode q) const
271
{
272
319908
  std::map<TNode, bool>::const_iterator it = d_quant_active.find(q);
273
319908
  if( it==d_quant_active.end() ){
274
319747
    return true;
275
  }
276
161
  return it->second;
277
}
278
279
27543
bool FirstOrderModel::isQuantifierAsserted(TNode q) const
280
{
281
27543
  return std::find( d_forall_asserts.begin(), d_forall_asserts.end(), q )!=d_forall_asserts.end();
282
}
283
284
87930
Node FirstOrderModel::getModelBasisTerm(TypeNode tn)
285
{
286
87930
  if (d_model_basis_term.find(tn) == d_model_basis_term.end())
287
  {
288
2160
    Node mbt;
289
1080
    if (tn.isClosedEnumerable())
290
    {
291
562
      mbt = d_treg.getTermEnumeration()->getEnumerateTerm(tn, 0);
292
    }
293
    else
294
    {
295
518
      if (options::fmfFreshDistConst())
296
      {
297
        mbt = d_treg.getTermDatabase()->getOrMakeTypeFreshVariable(tn);
298
      }
299
      else
300
      {
301
        // The model basis term cannot be an interpreted function, or else we
302
        // may produce an inconsistent model by choosing an arbitrary
303
        // equivalence class for it. Hence, we require that it be an existing or
304
        // fresh variable.
305
518
        mbt = d_treg.getTermDatabase()->getOrMakeTypeGroundTerm(tn, true);
306
      }
307
    }
308
    ModelBasisAttribute mba;
309
1080
    mbt.setAttribute(mba, true);
310
1080
    d_model_basis_term[tn] = mbt;
311
2160
    Trace("model-basis-term") << "Choose " << mbt << " as model basis term for "
312
1080
                              << tn << std::endl;
313
  }
314
87930
  return d_model_basis_term[tn];
315
}
316
317
75030
bool FirstOrderModel::isModelBasisTerm(Node n)
318
{
319
75030
  return n == getModelBasisTerm(n.getType());
320
}
321
322
11232
Node FirstOrderModel::getModelBasisOpTerm(Node op)
323
{
324
11232
  if (d_model_basis_op_term.find(op) == d_model_basis_op_term.end())
325
  {
326
2140
    TypeNode t = op.getType();
327
2140
    std::vector<Node> children;
328
1070
    children.push_back(op);
329
2655
    for (int i = 0; i < (int)(t.getNumChildren() - 1); i++)
330
    {
331
1585
      children.push_back(getModelBasisTerm(t[i]));
332
    }
333
1070
    if (children.size() == 1)
334
    {
335
      d_model_basis_op_term[op] = op;
336
    }
337
    else
338
    {
339
1070
      d_model_basis_op_term[op] =
340
2140
          NodeManager::currentNM()->mkNode(APPLY_UF, children);
341
    }
342
  }
343
11232
  return d_model_basis_op_term[op];
344
}
345
346
Node FirstOrderModel::getModelBasis(Node q, Node n)
347
{
348
  // make model basis
349
  if (d_model_basis_terms.find(q) == d_model_basis_terms.end())
350
  {
351
    for (unsigned j = 0; j < q[0].getNumChildren(); j++)
352
    {
353
      d_model_basis_terms[q].push_back(getModelBasisTerm(q[0][j].getType()));
354
    }
355
  }
356
  Node gn = d_qreg.substituteInstConstants(n, q, d_model_basis_terms[q]);
357
  return gn;
358
}
359
360
24405
void FirstOrderModel::computeModelBasisArgAttribute(Node n)
361
{
362
24405
  if (!n.hasAttribute(ModelBasisArgAttribute()))
363
  {
364
    // ensure that the model basis terms have been defined
365
4011
    if (n.getKind() == APPLY_UF)
366
    {
367
4011
      getModelBasisOpTerm(n.getOperator());
368
    }
369
4011
    uint64_t val = 0;
370
    // determine if it has model basis attribute
371
11097
    for (unsigned j = 0, nchild = n.getNumChildren(); j < nchild; j++)
372
    {
373
7086
      if (n[j].getAttribute(ModelBasisAttribute()))
374
      {
375
908
        val++;
376
      }
377
    }
378
    ModelBasisArgAttribute mbaa;
379
4011
    n.setAttribute(mbaa, val);
380
  }
381
24405
}
382
383
24405
unsigned FirstOrderModel::getModelBasisArg(Node n)
384
{
385
24405
  computeModelBasisArgAttribute(n);
386
24405
  return n.getAttribute(ModelBasisArgAttribute());
387
}
388
389
}  // namespace quantifiers
390
}  // namespace theory
391
29502
}  // namespace cvc5