GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/first_order_model.cpp Lines: 161 180 89.4 %
Date: 2021-05-21 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
8954
FirstOrderModel::FirstOrderModel(QuantifiersState& qs,
46
                                 QuantifiersRegistry& qr,
47
8954
                                 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
8954
      d_forallRlvComputed(false)
54
{
55
8954
}
56
57
6286
void FirstOrderModel::finishInit(TheoryModel* m) { d_model = m; }
58
59
63801
Node FirstOrderModel::getValue(TNode n) const { return d_model->getValue(n); }
60
5966
bool FirstOrderModel::hasTerm(TNode a) { return d_model->hasTerm(a); }
61
253895
Node FirstOrderModel::getRepresentative(TNode a)
62
{
63
253895
  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
197710
const RepSet* FirstOrderModel::getRepSet() const
78
{
79
197710
  return d_model->getRepSet();
80
}
81
11167
RepSet* FirstOrderModel::getRepSetPtr() { return d_model->getRepSetPtr(); }
82
TheoryModel* FirstOrderModel::getTheoryModel() { return d_model; }
83
84
75798
Node FirstOrderModel::getInternalRepresentative(Node a, Node q, size_t index)
85
{
86
75798
  return d_eq_query.getInternalRepresentative(a, q, index);
87
}
88
89
74801
void FirstOrderModel::assertQuantifier( Node n ){
90
74801
  if( n.getKind()==FORALL ){
91
74801
    d_forall_asserts.push_back( n );
92
  }else if( n.getKind()==NOT ){
93
    Assert(n[0].getKind() == FORALL);
94
  }
95
74801
}
96
97
93319
size_t FirstOrderModel::getNumAssertedQuantifiers() const
98
{
99
93319
  return d_forall_asserts.size();
100
}
101
102
701756
Node FirstOrderModel::getAssertedQuantifier( unsigned i, bool ordered ) {
103
701756
  if( !ordered || !d_forallRlvComputed ){
104
455985
    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
245771
  Assert(d_forall_rlv_assert.size() == d_forall_asserts.size());
109
245771
  return d_forall_rlv_assert[i];
110
}
111
112
1913
void FirstOrderModel::initialize() {
113
1913
  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
11774
  for( unsigned i=0; i<getNumAssertedQuantifiers(); i++ ){
117
19722
    Node f = getAssertedQuantifier( i );
118
9861
    if( d_quant_var_id.find( f )==d_quant_var_id.end() ){
119
3258
      for(unsigned j=0; j<f[0].getNumChildren(); j++){
120
1942
        d_quant_var_id[f][f[0][j]] = j;
121
      }
122
    }
123
9861
    processInitializeQuantifier( f );
124
    //initialize relevant models within bodies of all quantifiers
125
19722
    std::map< Node, bool > visited;
126
9861
    initializeModelForTerm( f[1], visited );
127
  }
128
1913
  processInitialize( false );
129
1913
}
130
131
228710
void FirstOrderModel::initializeModelForTerm( Node n, std::map< Node, bool >& visited ){
132
228710
  if( visited.find( n )==visited.end() ){
133
168481
    visited[n] = true;
134
168481
    processInitializeModelForTerm( n );
135
387330
    for( int i=0; i<(int)n.getNumChildren(); i++ ){
136
218849
      initializeModelForTerm( n[i], visited );
137
    }
138
  }
139
228710
}
140
141
3584
Node FirstOrderModel::getSomeDomainElement(TypeNode tn){
142
  //check if there is even any domain elements at all
143
3584
  RepSet* rs = d_model->getRepSetPtr();
144
3584
  if (!rs->hasType(tn) || rs->getNumRepresentatives(tn) == 0)
145
  {
146
222
    Trace("fm-debug") << "Must create domain element for " << tn << "..."
147
111
                      << std::endl;
148
222
    Node mbt = getModelBasisTerm(tn);
149
111
    Trace("fm-debug") << "Add to representative set..." << std::endl;
150
111
    rs->add(tn, mbt);
151
  }
152
3584
  return rs->getRepresentative(tn, 0);
153
}
154
155
5992
bool FirstOrderModel::initializeRepresentativesForType(TypeNode tn)
156
{
157
5992
  RepSet* rs = d_model->getRepSetPtr();
158
5992
  if (tn.isSort())
159
  {
160
    // must ensure uninterpreted type is non-empty.
161
2098
    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
2098
    return true;
172
  }
173
  else
174
  {
175
    // can we complete it?
176
3894
    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
1768
    Trace("fm-debug") << "  variable cannot be bounded." << std::endl;
186
1768
    return false;
187
  }
188
}
189
190
bool FirstOrderModel::isModelBasis(TNode n)
191
{
192
  return n.getAttribute(ModelBasisAttribute());
193
}
194
195
8954
EqualityQuery* FirstOrderModel::getEqualityQuery() { return &d_eq_query; }
196
197
/** needs check */
198
107240
bool FirstOrderModel::checkNeeded() {
199
107240
  return d_forall_asserts.size()>0;
200
}
201
202
24335
void FirstOrderModel::reset_round() {
203
24335
  d_quant_active.clear();
204
205
  // compute which quantified formulas are asserted if necessary
206
48670
  std::map<Node, bool> qassert;
207
24335
  if (!d_forall_rlv_vec.empty())
208
  {
209
5998
    Trace("fm-relevant-debug")
210
2999
        << "Mark asserted quantified formulas..." << std::endl;
211
157458
    for (const Node& q : d_forall_asserts)
212
    {
213
154459
      qassert[q] = true;
214
    }
215
  }
216
  //order the quantified formulas
217
24335
  d_forall_rlv_assert.clear();
218
24335
  d_forallRlvComputed = false;
219
24335
  if( !d_forall_rlv_vec.empty() ){
220
2999
    d_forallRlvComputed = true;
221
2999
    Trace("fm-relevant") << "Build sorted relevant list..." << std::endl;
222
2999
    Trace("fm-relevant-debug") << "Add relevant asserted formulas..." << std::endl;
223
2999
    std::map<Node, bool>::iterator ita;
224
10726
    for( int i=(int)(d_forall_rlv_vec.size()-1); i>=0; i-- ){
225
15454
      Node q = d_forall_rlv_vec[i];
226
7727
      ita = qassert.find(q);
227
7727
      if (ita != qassert.end())
228
      {
229
7489
        Trace("fm-relevant") << "   " << q << std::endl;
230
7489
        d_forall_rlv_assert.push_back( q );
231
7489
        qassert.erase(ita);
232
      }
233
    }
234
2999
    Trace("fm-relevant-debug") << "Add remaining asserted formulas..." << std::endl;
235
157458
    for (const Node& q : d_forall_asserts)
236
    {
237
      // if we didn't include it above
238
154459
      if (qassert.find(q) != qassert.end())
239
      {
240
146970
        d_forall_rlv_assert.push_back( q );
241
      }else{
242
7489
        Trace("fm-relevant-debug") << "...already included " << q << std::endl;
243
      }
244
    }
245
2999
    Trace("fm-relevant-debug") << "Sizes : " << d_forall_rlv_assert.size() << " " << d_forall_asserts.size() << std::endl;
246
2999
    Assert(d_forall_rlv_assert.size() == d_forall_asserts.size());
247
  }
248
24335
}
249
250
2018
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
2018
  if( q!=d_last_forall_rlv ){
254
1079
    Trace("fm-relevant") << "Mark relevant : " << q << std::endl;
255
    std::vector<Node>::iterator itr =
256
1079
        std::find(d_forall_rlv_vec.begin(), d_forall_rlv_vec.end(), q);
257
1079
    if (itr != d_forall_rlv_vec.end())
258
    {
259
142
      d_forall_rlv_vec.erase(itr, itr + 1);
260
    }
261
1079
    d_forall_rlv_vec.push_back(q);
262
1079
    d_last_forall_rlv = q;
263
  }
264
2018
}
265
266
1544
void FirstOrderModel::setQuantifierActive( TNode q, bool active ) {
267
1544
  d_quant_active[q] = active;
268
1544
}
269
270
312350
bool FirstOrderModel::isQuantifierActive(TNode q) const
271
{
272
312350
  std::map<TNode, bool>::const_iterator it = d_quant_active.find(q);
273
312350
  if( it==d_quant_active.end() ){
274
312264
    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
95098
Node FirstOrderModel::getModelBasisTerm(TypeNode tn)
285
{
286
95098
  if (d_model_basis_term.find(tn) == d_model_basis_term.end())
287
  {
288
1900
    Node mbt;
289
950
    if (tn.isClosedEnumerable())
290
    {
291
441
      mbt = d_treg.getTermEnumeration()->getEnumerateTerm(tn, 0);
292
    }
293
    else
294
    {
295
1018
      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
509
        mbt = d_treg.getTermDatabase()->getOrMakeTypeGroundTerm(tn, true);
306
      }
307
    }
308
    ModelBasisAttribute mba;
309
950
    mbt.setAttribute(mba, true);
310
950
    d_model_basis_term[tn] = mbt;
311
1900
    Trace("model-basis-term") << "Choose " << mbt << " as model basis term for "
312
950
                              << tn << std::endl;
313
  }
314
95098
  return d_model_basis_term[tn];
315
}
316
317
82993
bool FirstOrderModel::isModelBasisTerm(Node n)
318
{
319
82993
  return n == getModelBasisTerm(n.getType());
320
}
321
322
11409
Node FirstOrderModel::getModelBasisOpTerm(Node op)
323
{
324
11409
  if (d_model_basis_op_term.find(op) == d_model_basis_op_term.end())
325
  {
326
1900
    TypeNode t = op.getType();
327
1900
    std::vector<Node> children;
328
950
    children.push_back(op);
329
2375
    for (int i = 0; i < (int)(t.getNumChildren() - 1); i++)
330
    {
331
1425
      children.push_back(getModelBasisTerm(t[i]));
332
    }
333
950
    if (children.size() == 1)
334
    {
335
      d_model_basis_op_term[op] = op;
336
    }
337
    else
338
    {
339
950
      d_model_basis_op_term[op] =
340
1900
          NodeManager::currentNM()->mkNode(APPLY_UF, children);
341
    }
342
  }
343
11409
  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
26873
void FirstOrderModel::computeModelBasisArgAttribute(Node n)
361
{
362
26873
  if (!n.hasAttribute(ModelBasisArgAttribute()))
363
  {
364
    // ensure that the model basis terms have been defined
365
3828
    if (n.getKind() == APPLY_UF)
366
    {
367
3828
      getModelBasisOpTerm(n.getOperator());
368
    }
369
3828
    uint64_t val = 0;
370
    // determine if it has model basis attribute
371
10681
    for (unsigned j = 0, nchild = n.getNumChildren(); j < nchild; j++)
372
    {
373
6853
      if (n[j].getAttribute(ModelBasisAttribute()))
374
      {
375
812
        val++;
376
      }
377
    }
378
    ModelBasisArgAttribute mbaa;
379
3828
    n.setAttribute(mbaa, val);
380
  }
381
26873
}
382
383
26873
unsigned FirstOrderModel::getModelBasisArg(Node n)
384
{
385
26873
  computeModelBasisArgAttribute(n);
386
26873
  return n.getAttribute(ModelBasisArgAttribute());
387
}
388
389
}  // namespace quantifiers
390
}  // namespace theory
391
28244
}  // namespace cvc5