GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/first_order_model.cpp Lines: 161 180 89.4 %
Date: 2021-08-14 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
9853
FirstOrderModel::FirstOrderModel(QuantifiersState& qs,
46
                                 QuantifiersRegistry& qr,
47
9853
                                 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
9853
      d_forallRlvComputed(false)
54
{
55
9853
}
56
57
6763
void FirstOrderModel::finishInit(TheoryModel* m) { d_model = m; }
58
59
125486
Node FirstOrderModel::getValue(TNode n) const { return d_model->getValue(n); }
60
7842
bool FirstOrderModel::hasTerm(TNode a) { return d_model->hasTerm(a); }
61
232768
Node FirstOrderModel::getRepresentative(TNode a)
62
{
63
232768
  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
167968
const RepSet* FirstOrderModel::getRepSet() const
78
{
79
167968
  return d_model->getRepSet();
80
}
81
10907
RepSet* FirstOrderModel::getRepSetPtr() { return d_model->getRepSetPtr(); }
82
TheoryModel* FirstOrderModel::getTheoryModel() { return d_model; }
83
84
73134
Node FirstOrderModel::getInternalRepresentative(Node a, Node q, size_t index)
85
{
86
73134
  return d_eq_query.getInternalRepresentative(a, q, index);
87
}
88
89
67840
void FirstOrderModel::assertQuantifier( Node n ){
90
67840
  if( n.getKind()==FORALL ){
91
67840
    d_forall_asserts.push_back( n );
92
  }else if( n.getKind()==NOT ){
93
    Assert(n[0].getKind() == FORALL);
94
  }
95
67840
}
96
97
101532
size_t FirstOrderModel::getNumAssertedQuantifiers() const
98
{
99
101532
  return d_forall_asserts.size();
100
}
101
102
682509
Node FirstOrderModel::getAssertedQuantifier( unsigned i, bool ordered ) {
103
682509
  if( !ordered || !d_forallRlvComputed ){
104
446881
    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
235628
  Assert(d_forall_rlv_assert.size() == d_forall_asserts.size());
109
235628
  return d_forall_rlv_assert[i];
110
}
111
112
1979
void FirstOrderModel::initialize() {
113
1979
  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
10830
  for( unsigned i=0; i<getNumAssertedQuantifiers(); i++ ){
117
17702
    Node f = getAssertedQuantifier( i );
118
8851
    if( d_quant_var_id.find( f )==d_quant_var_id.end() ){
119
3633
      for(unsigned j=0; j<f[0].getNumChildren(); j++){
120
2168
        d_quant_var_id[f][f[0][j]] = j;
121
      }
122
    }
123
8851
    processInitializeQuantifier( f );
124
    //initialize relevant models within bodies of all quantifiers
125
17702
    std::map< Node, bool > visited;
126
8851
    initializeModelForTerm( f[1], visited );
127
  }
128
1979
  processInitialize( false );
129
1979
}
130
131
211963
void FirstOrderModel::initializeModelForTerm( Node n, std::map< Node, bool >& visited ){
132
211963
  if( visited.find( n )==visited.end() ){
133
152971
    visited[n] = true;
134
152971
    processInitializeModelForTerm( n );
135
356083
    for( int i=0; i<(int)n.getNumChildren(); i++ ){
136
203112
      initializeModelForTerm( n[i], visited );
137
    }
138
  }
139
211963
}
140
141
3526
Node FirstOrderModel::getSomeDomainElement(TypeNode tn){
142
  //check if there is even any domain elements at all
143
3526
  RepSet* rs = d_model->getRepSetPtr();
144
3526
  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
3526
  return rs->getRepresentative(tn, 0);
153
}
154
155
6910
bool FirstOrderModel::initializeRepresentativesForType(TypeNode tn)
156
{
157
6910
  RepSet* rs = d_model->getRepSetPtr();
158
6910
  if (tn.isSort())
159
  {
160
    // must ensure uninterpreted type is non-empty.
161
1795
    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
1795
    return true;
172
  }
173
  else
174
  {
175
    // can we complete it?
176
5115
    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
2985
    Trace("fm-debug") << "  variable cannot be bounded." << std::endl;
186
2985
    return false;
187
  }
188
}
189
190
bool FirstOrderModel::isModelBasis(TNode n)
191
{
192
  return n.getAttribute(ModelBasisAttribute());
193
}
194
195
9853
EqualityQuery* FirstOrderModel::getEqualityQuery() { return &d_eq_query; }
196
197
/** needs check */
198
100491
bool FirstOrderModel::checkNeeded() {
199
100491
  return d_forall_asserts.size()>0;
200
}
201
202
28528
void FirstOrderModel::reset_round() {
203
28528
  d_quant_active.clear();
204
205
  // compute which quantified formulas are asserted if necessary
206
57056
  std::map<Node, bool> qassert;
207
28528
  if (!d_forall_rlv_vec.empty())
208
  {
209
6266
    Trace("fm-relevant-debug")
210
3133
        << "Mark asserted quantified formulas..." << std::endl;
211
149765
    for (const Node& q : d_forall_asserts)
212
    {
213
146632
      qassert[q] = true;
214
    }
215
  }
216
  //order the quantified formulas
217
28528
  d_forall_rlv_assert.clear();
218
28528
  d_forallRlvComputed = false;
219
28528
  if( !d_forall_rlv_vec.empty() ){
220
3133
    d_forallRlvComputed = true;
221
3133
    Trace("fm-relevant") << "Build sorted relevant list..." << std::endl;
222
3133
    Trace("fm-relevant-debug") << "Add relevant asserted formulas..." << std::endl;
223
3133
    std::map<Node, bool>::iterator ita;
224
11003
    for( int i=(int)(d_forall_rlv_vec.size()-1); i>=0; i-- ){
225
15740
      Node q = d_forall_rlv_vec[i];
226
7870
      ita = qassert.find(q);
227
7870
      if (ita != qassert.end())
228
      {
229
7536
        Trace("fm-relevant") << "   " << q << std::endl;
230
7536
        d_forall_rlv_assert.push_back( q );
231
7536
        qassert.erase(ita);
232
      }
233
    }
234
3133
    Trace("fm-relevant-debug") << "Add remaining asserted formulas..." << std::endl;
235
149765
    for (const Node& q : d_forall_asserts)
236
    {
237
      // if we didn't include it above
238
146632
      if (qassert.find(q) != qassert.end())
239
      {
240
139096
        d_forall_rlv_assert.push_back( q );
241
      }else{
242
7536
        Trace("fm-relevant-debug") << "...already included " << q << std::endl;
243
      }
244
    }
245
3133
    Trace("fm-relevant-debug") << "Sizes : " << d_forall_rlv_assert.size() << " " << d_forall_asserts.size() << std::endl;
246
3133
    Assert(d_forall_rlv_assert.size() == d_forall_asserts.size());
247
  }
248
28528
}
249
250
2279
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
2279
  if( q!=d_last_forall_rlv ){
254
1096
    Trace("fm-relevant") << "Mark relevant : " << q << std::endl;
255
    std::vector<Node>::iterator itr =
256
1096
        std::find(d_forall_rlv_vec.begin(), d_forall_rlv_vec.end(), q);
257
1096
    if (itr != d_forall_rlv_vec.end())
258
    {
259
143
      d_forall_rlv_vec.erase(itr, itr + 1);
260
    }
261
1096
    d_forall_rlv_vec.push_back(q);
262
1096
    d_last_forall_rlv = q;
263
  }
264
2279
}
265
266
1508
void FirstOrderModel::setQuantifierActive( TNode q, bool active ) {
267
1508
  d_quant_active[q] = active;
268
1508
}
269
270
310801
bool FirstOrderModel::isQuantifierActive(TNode q) const
271
{
272
310801
  std::map<TNode, bool>::const_iterator it = d_quant_active.find(q);
273
310801
  if( it==d_quant_active.end() ){
274
310671
    return true;
275
  }
276
130
  return it->second;
277
}
278
279
25559
bool FirstOrderModel::isQuantifierAsserted(TNode q) const
280
{
281
25559
  return std::find( d_forall_asserts.begin(), d_forall_asserts.end(), q )!=d_forall_asserts.end();
282
}
283
284
87028
Node FirstOrderModel::getModelBasisTerm(TypeNode tn)
285
{
286
87028
  if (d_model_basis_term.find(tn) == d_model_basis_term.end())
287
  {
288
2144
    Node mbt;
289
1072
    if (tn.isClosedEnumerable())
290
    {
291
556
      mbt = d_treg.getTermEnumeration()->getEnumerateTerm(tn, 0);
292
    }
293
    else
294
    {
295
516
      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
516
        mbt = d_treg.getTermDatabase()->getOrMakeTypeGroundTerm(tn, true);
306
      }
307
    }
308
    ModelBasisAttribute mba;
309
1072
    mbt.setAttribute(mba, true);
310
1072
    d_model_basis_term[tn] = mbt;
311
2144
    Trace("model-basis-term") << "Choose " << mbt << " as model basis term for "
312
1072
                              << tn << std::endl;
313
  }
314
87028
  return d_model_basis_term[tn];
315
}
316
317
74545
bool FirstOrderModel::isModelBasisTerm(Node n)
318
{
319
74545
  return n == getModelBasisTerm(n.getType());
320
}
321
322
11078
Node FirstOrderModel::getModelBasisOpTerm(Node op)
323
{
324
11078
  if (d_model_basis_op_term.find(op) == d_model_basis_op_term.end())
325
  {
326
2090
    TypeNode t = op.getType();
327
2090
    std::vector<Node> children;
328
1045
    children.push_back(op);
329
2605
    for (int i = 0; i < (int)(t.getNumChildren() - 1); i++)
330
    {
331
1560
      children.push_back(getModelBasisTerm(t[i]));
332
    }
333
1045
    if (children.size() == 1)
334
    {
335
      d_model_basis_op_term[op] = op;
336
    }
337
    else
338
    {
339
1045
      d_model_basis_op_term[op] =
340
2090
          NodeManager::currentNM()->mkNode(APPLY_UF, children);
341
    }
342
  }
343
11078
  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
24149
void FirstOrderModel::computeModelBasisArgAttribute(Node n)
361
{
362
24149
  if (!n.hasAttribute(ModelBasisArgAttribute()))
363
  {
364
    // ensure that the model basis terms have been defined
365
3949
    if (n.getKind() == APPLY_UF)
366
    {
367
3949
      getModelBasisOpTerm(n.getOperator());
368
    }
369
3949
    uint64_t val = 0;
370
    // determine if it has model basis attribute
371
10973
    for (unsigned j = 0, nchild = n.getNumChildren(); j < nchild; j++)
372
    {
373
7024
      if (n[j].getAttribute(ModelBasisAttribute()))
374
      {
375
883
        val++;
376
      }
377
    }
378
    ModelBasisArgAttribute mbaa;
379
3949
    n.setAttribute(mbaa, val);
380
  }
381
24149
}
382
383
24149
unsigned FirstOrderModel::getModelBasisArg(Node n)
384
{
385
24149
  computeModelBasisArgAttribute(n);
386
24149
  return n.getAttribute(ModelBasisArgAttribute());
387
}
388
389
}  // namespace quantifiers
390
}  // namespace theory
391
29340
}  // namespace cvc5