GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/first_order_model.cpp Lines: 161 180 89.4 %
Date: 2021-09-10 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
9913
FirstOrderModel::FirstOrderModel(Env& env,
46
                                 QuantifiersState& qs,
47
                                 QuantifiersRegistry& qr,
48
9913
                                 TermRegistry& tr)
49
    : d_model(nullptr),
50
      d_qreg(qr),
51
      d_treg(tr),
52
      d_eq_query(env, qs, this),
53
      d_forall_asserts(qs.getSatContext()),
54
9913
      d_forallRlvComputed(false)
55
{
56
9913
}
57
58
6824
void FirstOrderModel::finishInit(TheoryModel* m) { d_model = m; }
59
60
129339
Node FirstOrderModel::getValue(TNode n) const { return d_model->getValue(n); }
61
8512
bool FirstOrderModel::hasTerm(TNode a) { return d_model->hasTerm(a); }
62
237486
Node FirstOrderModel::getRepresentative(TNode a)
63
{
64
237486
  return d_model->getRepresentative(a);
65
}
66
bool FirstOrderModel::areEqual(TNode a, TNode b)
67
{
68
  return d_model->areEqual(a, b);
69
}
70
bool FirstOrderModel::areDisequal(TNode a, TNode b)
71
{
72
  return d_model->areDisequal(a, b);
73
}
74
eq::EqualityEngine* FirstOrderModel::getEqualityEngine()
75
{
76
  return d_model->getEqualityEngine();
77
}
78
168061
const RepSet* FirstOrderModel::getRepSet() const
79
{
80
168061
  return d_model->getRepSet();
81
}
82
11193
RepSet* FirstOrderModel::getRepSetPtr() { return d_model->getRepSetPtr(); }
83
TheoryModel* FirstOrderModel::getTheoryModel() { return d_model; }
84
85
76405
Node FirstOrderModel::getInternalRepresentative(Node a, Node q, size_t index)
86
{
87
76405
  return d_eq_query.getInternalRepresentative(a, q, index);
88
}
89
90
68177
void FirstOrderModel::assertQuantifier( Node n ){
91
68177
  if( n.getKind()==FORALL ){
92
68177
    d_forall_asserts.push_back( n );
93
  }else if( n.getKind()==NOT ){
94
    Assert(n[0].getKind() == FORALL);
95
  }
96
68177
}
97
98
101470
size_t FirstOrderModel::getNumAssertedQuantifiers() const
99
{
100
101470
  return d_forall_asserts.size();
101
}
102
103
695203
Node FirstOrderModel::getAssertedQuantifier( unsigned i, bool ordered ) {
104
695203
  if( !ordered || !d_forallRlvComputed ){
105
461786
    return d_forall_asserts[i];
106
  }
107
  // If we computed the relevant forall assertion vector, in reset_round,
108
  // then it should have the same size as the default assertion vector.
109
233417
  Assert(d_forall_rlv_assert.size() == d_forall_asserts.size());
110
233417
  return d_forall_rlv_assert[i];
111
}
112
113
2038
void FirstOrderModel::initialize() {
114
2038
  processInitialize( true );
115
  //this is called after representatives have been chosen and the equality engine has been built
116
  //for each quantifier, collect all operators we care about
117
11159
  for( unsigned i=0; i<getNumAssertedQuantifiers(); i++ ){
118
18242
    Node f = getAssertedQuantifier( i );
119
9121
    if( d_quant_var_id.find( f )==d_quant_var_id.end() ){
120
3677
      for(unsigned j=0; j<f[0].getNumChildren(); j++){
121
2191
        d_quant_var_id[f][f[0][j]] = j;
122
      }
123
    }
124
9121
    processInitializeQuantifier( f );
125
    //initialize relevant models within bodies of all quantifiers
126
18242
    std::map< Node, bool > visited;
127
9121
    initializeModelForTerm( f[1], visited );
128
  }
129
2038
  processInitialize( false );
130
2038
}
131
132
219613
void FirstOrderModel::initializeModelForTerm( Node n, std::map< Node, bool >& visited ){
133
219613
  if( visited.find( n )==visited.end() ){
134
158755
    visited[n] = true;
135
158755
    processInitializeModelForTerm( n );
136
369247
    for( int i=0; i<(int)n.getNumChildren(); i++ ){
137
210492
      initializeModelForTerm( n[i], visited );
138
    }
139
  }
140
219613
}
141
142
3562
Node FirstOrderModel::getSomeDomainElement(TypeNode tn){
143
  //check if there is even any domain elements at all
144
3562
  RepSet* rs = d_model->getRepSetPtr();
145
3562
  if (!rs->hasType(tn) || rs->getNumRepresentatives(tn) == 0)
146
  {
147
246
    Trace("fm-debug") << "Must create domain element for " << tn << "..."
148
123
                      << std::endl;
149
246
    Node mbt = getModelBasisTerm(tn);
150
123
    Trace("fm-debug") << "Add to representative set..." << std::endl;
151
123
    rs->add(tn, mbt);
152
  }
153
3562
  return rs->getRepresentative(tn, 0);
154
}
155
156
7490
bool FirstOrderModel::initializeRepresentativesForType(TypeNode tn)
157
{
158
7490
  RepSet* rs = d_model->getRepSetPtr();
159
7490
  if (tn.isSort())
160
  {
161
    // must ensure uninterpreted type is non-empty.
162
1812
    if (!rs->hasType(tn))
163
    {
164
      // terms in rep_set are now constants which mapped to terms through
165
      // TheoryModel. Thus, should introduce a constant and a term.
166
      // For now, we just add an arbitrary term.
167
14
      Node var = getSomeDomainElement(tn);
168
14
      Trace("mkVar") << "RepSetIterator:: Make variable " << var << " : " << tn
169
7
                     << std::endl;
170
7
      rs->add(tn, var);
171
    }
172
1812
    return true;
173
  }
174
  else
175
  {
176
    // can we complete it?
177
5678
    if (d_qreg.getQuantifiersBoundInference().mayComplete(tn))
178
    {
179
4264
      Trace("fm-debug") << "  do complete, since cardinality is small ("
180
2132
                        << tn.getCardinality() << ")..." << std::endl;
181
2132
      rs->complete(tn);
182
      // must have succeeded
183
2132
      Assert(rs->hasType(tn));
184
2132
      return true;
185
    }
186
3546
    Trace("fm-debug") << "  variable cannot be bounded." << std::endl;
187
3546
    return false;
188
  }
189
}
190
191
bool FirstOrderModel::isModelBasis(TNode n)
192
{
193
  return n.getAttribute(ModelBasisAttribute());
194
}
195
196
9913
EqualityQuery* FirstOrderModel::getEqualityQuery() { return &d_eq_query; }
197
198
/** needs check */
199
101665
bool FirstOrderModel::checkNeeded() {
200
101665
  return d_forall_asserts.size()>0;
201
}
202
203
28088
void FirstOrderModel::reset_round() {
204
28088
  d_quant_active.clear();
205
206
  // compute which quantified formulas are asserted if necessary
207
56176
  std::map<Node, bool> qassert;
208
28088
  if (!d_forall_rlv_vec.empty())
209
  {
210
6536
    Trace("fm-relevant-debug")
211
3268
        << "Mark asserted quantified formulas..." << std::endl;
212
151542
    for (const Node& q : d_forall_asserts)
213
    {
214
148274
      qassert[q] = true;
215
    }
216
  }
217
  //order the quantified formulas
218
28088
  d_forall_rlv_assert.clear();
219
28088
  d_forallRlvComputed = false;
220
28088
  if( !d_forall_rlv_vec.empty() ){
221
3268
    d_forallRlvComputed = true;
222
3268
    Trace("fm-relevant") << "Build sorted relevant list..." << std::endl;
223
3268
    Trace("fm-relevant-debug") << "Add relevant asserted formulas..." << std::endl;
224
3268
    std::map<Node, bool>::iterator ita;
225
11508
    for( int i=(int)(d_forall_rlv_vec.size()-1); i>=0; i-- ){
226
16480
      Node q = d_forall_rlv_vec[i];
227
8240
      ita = qassert.find(q);
228
8240
      if (ita != qassert.end())
229
      {
230
7652
        Trace("fm-relevant") << "   " << q << std::endl;
231
7652
        d_forall_rlv_assert.push_back( q );
232
7652
        qassert.erase(ita);
233
      }
234
    }
235
3268
    Trace("fm-relevant-debug") << "Add remaining asserted formulas..." << std::endl;
236
151542
    for (const Node& q : d_forall_asserts)
237
    {
238
      // if we didn't include it above
239
148274
      if (qassert.find(q) != qassert.end())
240
      {
241
140622
        d_forall_rlv_assert.push_back( q );
242
      }else{
243
7652
        Trace("fm-relevant-debug") << "...already included " << q << std::endl;
244
      }
245
    }
246
3268
    Trace("fm-relevant-debug") << "Sizes : " << d_forall_rlv_assert.size() << " " << d_forall_asserts.size() << std::endl;
247
3268
    Assert(d_forall_rlv_assert.size() == d_forall_asserts.size());
248
  }
249
28088
}
250
251
2405
void FirstOrderModel::markRelevant( Node q ) {
252
  // Put q on the back of the vector d_forall_rlv_vec.
253
  // If we were the last quantifier marked relevant, this is a no-op, return.
254
2405
  if( q!=d_last_forall_rlv ){
255
1148
    Trace("fm-relevant") << "Mark relevant : " << q << std::endl;
256
    std::vector<Node>::iterator itr =
257
1148
        std::find(d_forall_rlv_vec.begin(), d_forall_rlv_vec.end(), q);
258
1148
    if (itr != d_forall_rlv_vec.end())
259
    {
260
147
      d_forall_rlv_vec.erase(itr, itr + 1);
261
    }
262
1148
    d_forall_rlv_vec.push_back(q);
263
1148
    d_last_forall_rlv = q;
264
  }
265
2405
}
266
267
1525
void FirstOrderModel::setQuantifierActive( TNode q, bool active ) {
268
1525
  d_quant_active[q] = active;
269
1525
}
270
271
318318
bool FirstOrderModel::isQuantifierActive(TNode q) const
272
{
273
318318
  std::map<TNode, bool>::const_iterator it = d_quant_active.find(q);
274
318318
  if( it==d_quant_active.end() ){
275
318157
    return true;
276
  }
277
161
  return it->second;
278
}
279
280
27385
bool FirstOrderModel::isQuantifierAsserted(TNode q) const
281
{
282
27385
  return std::find( d_forall_asserts.begin(), d_forall_asserts.end(), q )!=d_forall_asserts.end();
283
}
284
285
87630
Node FirstOrderModel::getModelBasisTerm(TypeNode tn)
286
{
287
87630
  if (d_model_basis_term.find(tn) == d_model_basis_term.end())
288
  {
289
2144
    Node mbt;
290
1072
    if (tn.isClosedEnumerable())
291
    {
292
562
      mbt = d_treg.getTermEnumeration()->getEnumerateTerm(tn, 0);
293
    }
294
    else
295
    {
296
510
      if (options::fmfFreshDistConst())
297
      {
298
        mbt = d_treg.getTermDatabase()->getOrMakeTypeFreshVariable(tn);
299
      }
300
      else
301
      {
302
        // The model basis term cannot be an interpreted function, or else we
303
        // may produce an inconsistent model by choosing an arbitrary
304
        // equivalence class for it. Hence, we require that it be an existing or
305
        // fresh variable.
306
510
        mbt = d_treg.getTermDatabase()->getOrMakeTypeGroundTerm(tn, true);
307
      }
308
    }
309
    ModelBasisAttribute mba;
310
1072
    mbt.setAttribute(mba, true);
311
1072
    d_model_basis_term[tn] = mbt;
312
2144
    Trace("model-basis-term") << "Choose " << mbt << " as model basis term for "
313
1072
                              << tn << std::endl;
314
  }
315
87630
  return d_model_basis_term[tn];
316
}
317
318
74784
bool FirstOrderModel::isModelBasisTerm(Node n)
319
{
320
74784
  return n == getModelBasisTerm(n.getType());
321
}
322
323
11211
Node FirstOrderModel::getModelBasisOpTerm(Node op)
324
{
325
11211
  if (d_model_basis_op_term.find(op) == d_model_basis_op_term.end())
326
  {
327
2140
    TypeNode t = op.getType();
328
2140
    std::vector<Node> children;
329
1070
    children.push_back(op);
330
2655
    for (int i = 0; i < (int)(t.getNumChildren() - 1); i++)
331
    {
332
1585
      children.push_back(getModelBasisTerm(t[i]));
333
    }
334
1070
    if (children.size() == 1)
335
    {
336
      d_model_basis_op_term[op] = op;
337
    }
338
    else
339
    {
340
1070
      d_model_basis_op_term[op] =
341
2140
          NodeManager::currentNM()->mkNode(APPLY_UF, children);
342
    }
343
  }
344
11211
  return d_model_basis_op_term[op];
345
}
346
347
Node FirstOrderModel::getModelBasis(Node q, Node n)
348
{
349
  // make model basis
350
  if (d_model_basis_terms.find(q) == d_model_basis_terms.end())
351
  {
352
    for (unsigned j = 0; j < q[0].getNumChildren(); j++)
353
    {
354
      d_model_basis_terms[q].push_back(getModelBasisTerm(q[0][j].getType()));
355
    }
356
  }
357
  Node gn = d_qreg.substituteInstConstants(n, q, d_model_basis_terms[q]);
358
  return gn;
359
}
360
361
24387
void FirstOrderModel::computeModelBasisArgAttribute(Node n)
362
{
363
24387
  if (!n.hasAttribute(ModelBasisArgAttribute()))
364
  {
365
    // ensure that the model basis terms have been defined
366
4004
    if (n.getKind() == APPLY_UF)
367
    {
368
4004
      getModelBasisOpTerm(n.getOperator());
369
    }
370
4004
    uint64_t val = 0;
371
    // determine if it has model basis attribute
372
11080
    for (unsigned j = 0, nchild = n.getNumChildren(); j < nchild; j++)
373
    {
374
7076
      if (n[j].getAttribute(ModelBasisAttribute()))
375
      {
376
908
        val++;
377
      }
378
    }
379
    ModelBasisArgAttribute mbaa;
380
4004
    n.setAttribute(mbaa, val);
381
  }
382
24387
}
383
384
24387
unsigned FirstOrderModel::getModelBasisArg(Node n)
385
{
386
24387
  computeModelBasisArgAttribute(n);
387
24387
  return n.getAttribute(ModelBasisArgAttribute());
388
}
389
390
}  // namespace quantifiers
391
}  // namespace theory
392
29502
}  // namespace cvc5