GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/first_order_model.cpp Lines: 161 180 89.4 %
Date: 2021-05-24 Branches: 248 542 45.8 %

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
9459
FirstOrderModel::FirstOrderModel(QuantifiersState& qs,
46
                                 QuantifiersRegistry& qr,
47
9459
                                 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
9459
      d_forallRlvComputed(false)
54
{
55
9459
}
56
57
6413
void FirstOrderModel::finishInit(TheoryModel* m) { d_model = m; }
58
59
64044
Node FirstOrderModel::getValue(TNode n) const { return d_model->getValue(n); }
60
6043
bool FirstOrderModel::hasTerm(TNode a) { return d_model->hasTerm(a); }
61
254547
Node FirstOrderModel::getRepresentative(TNode a)
62
{
63
254547
  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
198977
const RepSet* FirstOrderModel::getRepSet() const
78
{
79
198977
  return d_model->getRepSet();
80
}
81
11271
RepSet* FirstOrderModel::getRepSetPtr() { return d_model->getRepSetPtr(); }
82
TheoryModel* FirstOrderModel::getTheoryModel() { return d_model; }
83
84
75906
Node FirstOrderModel::getInternalRepresentative(Node a, Node q, size_t index)
85
{
86
75906
  return d_eq_query.getInternalRepresentative(a, q, index);
87
}
88
89
75427
void FirstOrderModel::assertQuantifier( Node n ){
90
75427
  if( n.getKind()==FORALL ){
91
75427
    d_forall_asserts.push_back( n );
92
  }else if( n.getKind()==NOT ){
93
    Assert(n[0].getKind() == FORALL);
94
  }
95
75427
}
96
97
93918
size_t FirstOrderModel::getNumAssertedQuantifiers() const
98
{
99
93918
  return d_forall_asserts.size();
100
}
101
102
703202
Node FirstOrderModel::getAssertedQuantifier( unsigned i, bool ordered ) {
103
703202
  if( !ordered || !d_forallRlvComputed ){
104
456939
    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
246263
  Assert(d_forall_rlv_assert.size() == d_forall_asserts.size());
109
246263
  return d_forall_rlv_assert[i];
110
}
111
112
1934
void FirstOrderModel::initialize() {
113
1934
  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
11881
  for( unsigned i=0; i<getNumAssertedQuantifiers(); i++ ){
117
19894
    Node f = getAssertedQuantifier( i );
118
9947
    if( d_quant_var_id.find( f )==d_quant_var_id.end() ){
119
3317
      for(unsigned j=0; j<f[0].getNumChildren(); j++){
120
1971
        d_quant_var_id[f][f[0][j]] = j;
121
      }
122
    }
123
9947
    processInitializeQuantifier( f );
124
    //initialize relevant models within bodies of all quantifiers
125
19894
    std::map< Node, bool > visited;
126
9947
    initializeModelForTerm( f[1], visited );
127
  }
128
1934
  processInitialize( false );
129
1934
}
130
131
229569
void FirstOrderModel::initializeModelForTerm( Node n, std::map< Node, bool >& visited ){
132
229569
  if( visited.find( n )==visited.end() ){
133
169182
    visited[n] = true;
134
169182
    processInitializeModelForTerm( n );
135
388804
    for( int i=0; i<(int)n.getNumChildren(); i++ ){
136
219622
      initializeModelForTerm( n[i], visited );
137
    }
138
  }
139
229569
}
140
141
3626
Node FirstOrderModel::getSomeDomainElement(TypeNode tn){
142
  //check if there is even any domain elements at all
143
3626
  RepSet* rs = d_model->getRepSetPtr();
144
3626
  if (!rs->hasType(tn) || rs->getNumRepresentatives(tn) == 0)
145
  {
146
226
    Trace("fm-debug") << "Must create domain element for " << tn << "..."
147
113
                      << std::endl;
148
226
    Node mbt = getModelBasisTerm(tn);
149
113
    Trace("fm-debug") << "Add to representative set..." << std::endl;
150
113
    rs->add(tn, mbt);
151
  }
152
3626
  return rs->getRepresentative(tn, 0);
153
}
154
155
6010
bool FirstOrderModel::initializeRepresentativesForType(TypeNode tn)
156
{
157
6010
  RepSet* rs = d_model->getRepSetPtr();
158
6010
  if (tn.isSort())
159
  {
160
    // must ensure uninterpreted type is non-empty.
161
2114
    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
2114
    return true;
172
  }
173
  else
174
  {
175
    // can we complete it?
176
3896
    if (d_qreg.getQuantifiersBoundInference().mayComplete(tn))
177
    {
178
4252
      Trace("fm-debug") << "  do complete, since cardinality is small ("
179
2126
                        << tn.getCardinality() << ")..." << std::endl;
180
2126
      rs->complete(tn);
181
      // must have succeeded
182
2126
      Assert(rs->hasType(tn));
183
2126
      return true;
184
    }
185
1770
    Trace("fm-debug") << "  variable cannot be bounded." << std::endl;
186
1770
    return false;
187
  }
188
}
189
190
bool FirstOrderModel::isModelBasis(TNode n)
191
{
192
  return n.getAttribute(ModelBasisAttribute());
193
}
194
195
9459
EqualityQuery* FirstOrderModel::getEqualityQuery() { return &d_eq_query; }
196
197
/** needs check */
198
108632
bool FirstOrderModel::checkNeeded() {
199
108632
  return d_forall_asserts.size()>0;
200
}
201
202
24502
void FirstOrderModel::reset_round() {
203
24502
  d_quant_active.clear();
204
205
  // compute which quantified formulas are asserted if necessary
206
49004
  std::map<Node, bool> qassert;
207
24502
  if (!d_forall_rlv_vec.empty())
208
  {
209
6120
    Trace("fm-relevant-debug")
210
3060
        << "Mark asserted quantified formulas..." << std::endl;
211
157855
    for (const Node& q : d_forall_asserts)
212
    {
213
154795
      qassert[q] = true;
214
    }
215
  }
216
  //order the quantified formulas
217
24502
  d_forall_rlv_assert.clear();
218
24502
  d_forallRlvComputed = false;
219
24502
  if( !d_forall_rlv_vec.empty() ){
220
3060
    d_forallRlvComputed = true;
221
3060
    Trace("fm-relevant") << "Build sorted relevant list..." << std::endl;
222
3060
    Trace("fm-relevant-debug") << "Add relevant asserted formulas..." << std::endl;
223
3060
    std::map<Node, bool>::iterator ita;
224
10928
    for( int i=(int)(d_forall_rlv_vec.size()-1); i>=0; i-- ){
225
15736
      Node q = d_forall_rlv_vec[i];
226
7868
      ita = qassert.find(q);
227
7868
      if (ita != qassert.end())
228
      {
229
7596
        Trace("fm-relevant") << "   " << q << std::endl;
230
7596
        d_forall_rlv_assert.push_back( q );
231
7596
        qassert.erase(ita);
232
      }
233
    }
234
3060
    Trace("fm-relevant-debug") << "Add remaining asserted formulas..." << std::endl;
235
157855
    for (const Node& q : d_forall_asserts)
236
    {
237
      // if we didn't include it above
238
154795
      if (qassert.find(q) != qassert.end())
239
      {
240
147199
        d_forall_rlv_assert.push_back( q );
241
      }else{
242
7596
        Trace("fm-relevant-debug") << "...already included " << q << std::endl;
243
      }
244
    }
245
3060
    Trace("fm-relevant-debug") << "Sizes : " << d_forall_rlv_assert.size() << " " << d_forall_asserts.size() << std::endl;
246
3060
    Assert(d_forall_rlv_assert.size() == d_forall_asserts.size());
247
  }
248
24502
}
249
250
2070
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
2070
  if( q!=d_last_forall_rlv ){
254
1105
    Trace("fm-relevant") << "Mark relevant : " << q << std::endl;
255
    std::vector<Node>::iterator itr =
256
1105
        std::find(d_forall_rlv_vec.begin(), d_forall_rlv_vec.end(), q);
257
1105
    if (itr != d_forall_rlv_vec.end())
258
    {
259
136
      d_forall_rlv_vec.erase(itr, itr + 1);
260
    }
261
1105
    d_forall_rlv_vec.push_back(q);
262
1105
    d_last_forall_rlv = q;
263
  }
264
2070
}
265
266
1544
void FirstOrderModel::setQuantifierActive( TNode q, bool active ) {
267
1544
  d_quant_active[q] = active;
268
1544
}
269
270
313174
bool FirstOrderModel::isQuantifierActive(TNode q) const
271
{
272
313174
  std::map<TNode, bool>::const_iterator it = d_quant_active.find(q);
273
313174
  if( it==d_quant_active.end() ){
274
313088
    return true;
275
  }
276
86
  return it->second;
277
}
278
279
25243
bool FirstOrderModel::isQuantifierAsserted(TNode q) const
280
{
281
25243
  return std::find( d_forall_asserts.begin(), d_forall_asserts.end(), q )!=d_forall_asserts.end();
282
}
283
284
95478
Node FirstOrderModel::getModelBasisTerm(TypeNode tn)
285
{
286
95478
  if (d_model_basis_term.find(tn) == d_model_basis_term.end())
287
  {
288
1938
    Node mbt;
289
969
    if (tn.isClosedEnumerable())
290
    {
291
452
      mbt = d_treg.getTermEnumeration()->getEnumerateTerm(tn, 0);
292
    }
293
    else
294
    {
295
1034
      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
517
        mbt = d_treg.getTermDatabase()->getOrMakeTypeGroundTerm(tn, true);
306
      }
307
    }
308
    ModelBasisAttribute mba;
309
969
    mbt.setAttribute(mba, true);
310
969
    d_model_basis_term[tn] = mbt;
311
1938
    Trace("model-basis-term") << "Choose " << mbt << " as model basis term for "
312
969
                              << tn << std::endl;
313
  }
314
95478
  return d_model_basis_term[tn];
315
}
316
317
83236
bool FirstOrderModel::isModelBasisTerm(Node n)
318
{
319
83236
  return n == getModelBasisTerm(n.getType());
320
}
321
322
11516
Node FirstOrderModel::getModelBasisOpTerm(Node op)
323
{
324
11516
  if (d_model_basis_op_term.find(op) == d_model_basis_op_term.end())
325
  {
326
1944
    TypeNode t = op.getType();
327
1944
    std::vector<Node> children;
328
972
    children.push_back(op);
329
2425
    for (int i = 0; i < (int)(t.getNumChildren() - 1); i++)
330
    {
331
1453
      children.push_back(getModelBasisTerm(t[i]));
332
    }
333
972
    if (children.size() == 1)
334
    {
335
      d_model_basis_op_term[op] = op;
336
    }
337
    else
338
    {
339
972
      d_model_basis_op_term[op] =
340
1944
          NodeManager::currentNM()->mkNode(APPLY_UF, children);
341
    }
342
  }
343
11516
  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
26994
void FirstOrderModel::computeModelBasisArgAttribute(Node n)
361
{
362
26994
  if (!n.hasAttribute(ModelBasisArgAttribute()))
363
  {
364
    // ensure that the model basis terms have been defined
365
3871
    if (n.getKind() == APPLY_UF)
366
    {
367
3871
      getModelBasisOpTerm(n.getOperator());
368
    }
369
3871
    uint64_t val = 0;
370
    // determine if it has model basis attribute
371
10789
    for (unsigned j = 0, nchild = n.getNumChildren(); j < nchild; j++)
372
    {
373
6918
      if (n[j].getAttribute(ModelBasisAttribute()))
374
      {
375
817
        val++;
376
      }
377
    }
378
    ModelBasisArgAttribute mbaa;
379
3871
    n.setAttribute(mbaa, val);
380
  }
381
26994
}
382
383
26994
unsigned FirstOrderModel::getModelBasisArg(Node n)
384
{
385
26994
  computeModelBasisArgAttribute(n);
386
26994
  return n.getAttribute(ModelBasisArgAttribute());
387
}
388
389
}  // namespace quantifiers
390
}  // namespace theory
391
28708
}  // namespace cvc5