GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/first_order_model.cpp Lines: 161 180 89.4 %
Date: 2021-09-09 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
9928
FirstOrderModel::FirstOrderModel(Env& env,
46
                                 QuantifiersState& qs,
47
                                 QuantifiersRegistry& qr,
48
9928
                                 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
9928
      d_forallRlvComputed(false)
55
{
56
9928
}
57
58
6839
void FirstOrderModel::finishInit(TheoryModel* m) { d_model = m; }
59
60
129671
Node FirstOrderModel::getValue(TNode n) const { return d_model->getValue(n); }
61
8578
bool FirstOrderModel::hasTerm(TNode a) { return d_model->hasTerm(a); }
62
237804
Node FirstOrderModel::getRepresentative(TNode a)
63
{
64
237804
  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
169003
const RepSet* FirstOrderModel::getRepSet() const
79
{
80
169003
  return d_model->getRepSet();
81
}
82
11247
RepSet* FirstOrderModel::getRepSetPtr() { return d_model->getRepSetPtr(); }
83
TheoryModel* FirstOrderModel::getTheoryModel() { return d_model; }
84
85
76309
Node FirstOrderModel::getInternalRepresentative(Node a, Node q, size_t index)
86
{
87
76309
  return d_eq_query.getInternalRepresentative(a, q, index);
88
}
89
90
69049
void FirstOrderModel::assertQuantifier( Node n ){
91
69049
  if( n.getKind()==FORALL ){
92
69049
    d_forall_asserts.push_back( n );
93
  }else if( n.getKind()==NOT ){
94
    Assert(n[0].getKind() == FORALL);
95
  }
96
69049
}
97
98
102433
size_t FirstOrderModel::getNumAssertedQuantifiers() const
99
{
100
102433
  return d_forall_asserts.size();
101
}
102
103
698563
Node FirstOrderModel::getAssertedQuantifier( unsigned i, bool ordered ) {
104
698563
  if( !ordered || !d_forallRlvComputed ){
105
462690
    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
235873
  Assert(d_forall_rlv_assert.size() == d_forall_asserts.size());
110
235873
  return d_forall_rlv_assert[i];
111
}
112
113
2046
void FirstOrderModel::initialize() {
114
2046
  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
11211
  for( unsigned i=0; i<getNumAssertedQuantifiers(); i++ ){
118
18330
    Node f = getAssertedQuantifier( i );
119
9165
    if( d_quant_var_id.find( f )==d_quant_var_id.end() ){
120
3705
      for(unsigned j=0; j<f[0].getNumChildren(); j++){
121
2205
        d_quant_var_id[f][f[0][j]] = j;
122
      }
123
    }
124
9165
    processInitializeQuantifier( f );
125
    //initialize relevant models within bodies of all quantifiers
126
18330
    std::map< Node, bool > visited;
127
9165
    initializeModelForTerm( f[1], visited );
128
  }
129
2046
  processInitialize( false );
130
2046
}
131
132
220271
void FirstOrderModel::initializeModelForTerm( Node n, std::map< Node, bool >& visited ){
133
220271
  if( visited.find( n )==visited.end() ){
134
159333
    visited[n] = true;
135
159333
    processInitializeModelForTerm( n );
136
370439
    for( int i=0; i<(int)n.getNumChildren(); i++ ){
137
211106
      initializeModelForTerm( n[i], visited );
138
    }
139
  }
140
220271
}
141
142
3534
Node FirstOrderModel::getSomeDomainElement(TypeNode tn){
143
  //check if there is even any domain elements at all
144
3534
  RepSet* rs = d_model->getRepSetPtr();
145
3534
  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
3534
  return rs->getRepresentative(tn, 0);
154
}
155
156
7488
bool FirstOrderModel::initializeRepresentativesForType(TypeNode tn)
157
{
158
7488
  RepSet* rs = d_model->getRepSetPtr();
159
7488
  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
5676
    if (d_qreg.getQuantifiersBoundInference().mayComplete(tn))
178
    {
179
4260
      Trace("fm-debug") << "  do complete, since cardinality is small ("
180
2130
                        << tn.getCardinality() << ")..." << std::endl;
181
2130
      rs->complete(tn);
182
      // must have succeeded
183
2130
      Assert(rs->hasType(tn));
184
2130
      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
9928
EqualityQuery* FirstOrderModel::getEqualityQuery() { return &d_eq_query; }
197
198
/** needs check */
199
102668
bool FirstOrderModel::checkNeeded() {
200
102668
  return d_forall_asserts.size()>0;
201
}
202
203
28439
void FirstOrderModel::reset_round() {
204
28439
  d_quant_active.clear();
205
206
  // compute which quantified formulas are asserted if necessary
207
56878
  std::map<Node, bool> qassert;
208
28439
  if (!d_forall_rlv_vec.empty())
209
  {
210
6346
    Trace("fm-relevant-debug")
211
3173
        << "Mark asserted quantified formulas..." << std::endl;
212
150671
    for (const Node& q : d_forall_asserts)
213
    {
214
147498
      qassert[q] = true;
215
    }
216
  }
217
  //order the quantified formulas
218
28439
  d_forall_rlv_assert.clear();
219
28439
  d_forallRlvComputed = false;
220
28439
  if( !d_forall_rlv_vec.empty() ){
221
3173
    d_forallRlvComputed = true;
222
3173
    Trace("fm-relevant") << "Build sorted relevant list..." << std::endl;
223
3173
    Trace("fm-relevant-debug") << "Add relevant asserted formulas..." << std::endl;
224
3173
    std::map<Node, bool>::iterator ita;
225
10990
    for( int i=(int)(d_forall_rlv_vec.size()-1); i>=0; i-- ){
226
15634
      Node q = d_forall_rlv_vec[i];
227
7817
      ita = qassert.find(q);
228
7817
      if (ita != qassert.end())
229
      {
230
7483
        Trace("fm-relevant") << "   " << q << std::endl;
231
7483
        d_forall_rlv_assert.push_back( q );
232
7483
        qassert.erase(ita);
233
      }
234
    }
235
3173
    Trace("fm-relevant-debug") << "Add remaining asserted formulas..." << std::endl;
236
150671
    for (const Node& q : d_forall_asserts)
237
    {
238
      // if we didn't include it above
239
147498
      if (qassert.find(q) != qassert.end())
240
      {
241
140015
        d_forall_rlv_assert.push_back( q );
242
      }else{
243
7483
        Trace("fm-relevant-debug") << "...already included " << q << std::endl;
244
      }
245
    }
246
3173
    Trace("fm-relevant-debug") << "Sizes : " << d_forall_rlv_assert.size() << " " << d_forall_asserts.size() << std::endl;
247
3173
    Assert(d_forall_rlv_assert.size() == d_forall_asserts.size());
248
  }
249
28439
}
250
251
2287
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
2287
  if( q!=d_last_forall_rlv ){
255
1104
    Trace("fm-relevant") << "Mark relevant : " << q << std::endl;
256
    std::vector<Node>::iterator itr =
257
1104
        std::find(d_forall_rlv_vec.begin(), d_forall_rlv_vec.end(), q);
258
1104
    if (itr != d_forall_rlv_vec.end())
259
    {
260
139
      d_forall_rlv_vec.erase(itr, itr + 1);
261
    }
262
1104
    d_forall_rlv_vec.push_back(q);
263
1104
    d_last_forall_rlv = q;
264
  }
265
2287
}
266
267
1525
void FirstOrderModel::setQuantifierActive( TNode q, bool active ) {
268
1525
  d_quant_active[q] = active;
269
1525
}
270
271
320014
bool FirstOrderModel::isQuantifierActive(TNode q) const
272
{
273
320014
  std::map<TNode, bool>::const_iterator it = d_quant_active.find(q);
274
320014
  if( it==d_quant_active.end() ){
275
319853
    return true;
276
  }
277
161
  return it->second;
278
}
279
280
27633
bool FirstOrderModel::isQuantifierAsserted(TNode q) const
281
{
282
27633
  return std::find( d_forall_asserts.begin(), d_forall_asserts.end(), q )!=d_forall_asserts.end();
283
}
284
285
87930
Node FirstOrderModel::getModelBasisTerm(TypeNode tn)
286
{
287
87930
  if (d_model_basis_term.find(tn) == d_model_basis_term.end())
288
  {
289
2160
    Node mbt;
290
1080
    if (tn.isClosedEnumerable())
291
    {
292
562
      mbt = d_treg.getTermEnumeration()->getEnumerateTerm(tn, 0);
293
    }
294
    else
295
    {
296
518
      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
518
        mbt = d_treg.getTermDatabase()->getOrMakeTypeGroundTerm(tn, true);
307
      }
308
    }
309
    ModelBasisAttribute mba;
310
1080
    mbt.setAttribute(mba, true);
311
1080
    d_model_basis_term[tn] = mbt;
312
2160
    Trace("model-basis-term") << "Choose " << mbt << " as model basis term for "
313
1080
                              << tn << std::endl;
314
  }
315
87930
  return d_model_basis_term[tn];
316
}
317
318
75030
bool FirstOrderModel::isModelBasisTerm(Node n)
319
{
320
75030
  return n == getModelBasisTerm(n.getType());
321
}
322
323
11232
Node FirstOrderModel::getModelBasisOpTerm(Node op)
324
{
325
11232
  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
11232
  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
24405
void FirstOrderModel::computeModelBasisArgAttribute(Node n)
362
{
363
24405
  if (!n.hasAttribute(ModelBasisArgAttribute()))
364
  {
365
    // ensure that the model basis terms have been defined
366
4011
    if (n.getKind() == APPLY_UF)
367
    {
368
4011
      getModelBasisOpTerm(n.getOperator());
369
    }
370
4011
    uint64_t val = 0;
371
    // determine if it has model basis attribute
372
11097
    for (unsigned j = 0, nchild = n.getNumChildren(); j < nchild; j++)
373
    {
374
7086
      if (n[j].getAttribute(ModelBasisAttribute()))
375
      {
376
908
        val++;
377
      }
378
    }
379
    ModelBasisArgAttribute mbaa;
380
4011
    n.setAttribute(mbaa, val);
381
  }
382
24405
}
383
384
24405
unsigned FirstOrderModel::getModelBasisArg(Node n)
385
{
386
24405
  computeModelBasisArgAttribute(n);
387
24405
  return n.getAttribute(ModelBasisArgAttribute());
388
}
389
390
}  // namespace quantifiers
391
}  // namespace theory
392
29505
}  // namespace cvc5