GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/ematching/instantiation_engine.cpp Lines: 116 129 89.9 %
Date: 2021-11-07 Branches: 177 364 48.6 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Morgan Deters, Tim King
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 instantiation engine class
14
 */
15
16
#include "theory/quantifiers/ematching/instantiation_engine.h"
17
18
#include "options/quantifiers_options.h"
19
#include "theory/quantifiers/ematching/inst_strategy_e_matching.h"
20
#include "theory/quantifiers/ematching/inst_strategy_e_matching_user.h"
21
#include "theory/quantifiers/ematching/trigger.h"
22
#include "theory/quantifiers/first_order_model.h"
23
#include "theory/quantifiers/quantifiers_attributes.h"
24
#include "theory/quantifiers/term_database.h"
25
#include "theory/quantifiers/term_util.h"
26
27
using namespace cvc5::kind;
28
using namespace cvc5::context;
29
using namespace cvc5::theory::quantifiers::inst;
30
31
namespace cvc5 {
32
namespace theory {
33
namespace quantifiers {
34
35
11880
InstantiationEngine::InstantiationEngine(Env& env,
36
                                         QuantifiersState& qs,
37
                                         QuantifiersInferenceManager& qim,
38
                                         QuantifiersRegistry& qr,
39
11880
                                         TermRegistry& tr)
40
    : QuantifiersModule(env, qs, qim, qr, tr),
41
      d_instStrategies(),
42
      d_isup(),
43
      d_i_ag(),
44
      d_quants(),
45
      d_trdb(d_env, qs, qim, qr, tr),
46
11880
      d_quant_rel(nullptr)
47
{
48
11880
  if (options().quantifiers.relevantTriggers)
49
  {
50
4
    d_quant_rel.reset(new quantifiers::QuantRelevance(env));
51
  }
52
11880
  if (options().quantifiers.eMatching)
53
  {
54
    // these are the instantiation strategies for E-matching
55
    // user-provided patterns
56
11877
    if (options().quantifiers.userPatternsQuant != options::UserPatMode::IGNORE)
57
    {
58
23754
      d_isup.reset(
59
11877
          new InstStrategyUserPatterns(d_env, d_trdb, qs, qim, qr, tr));
60
11877
      d_instStrategies.push_back(d_isup.get());
61
    }
62
63
    // auto-generated patterns
64
23754
    d_i_ag.reset(new InstStrategyAutoGenTriggers(
65
11877
        d_env, d_trdb, qs, qim, qr, tr, d_quant_rel.get()));
66
11877
    d_instStrategies.push_back(d_i_ag.get());
67
  }
68
11880
}
69
70
23750
InstantiationEngine::~InstantiationEngine() {}
71
72
13147
void InstantiationEngine::presolve() {
73
39435
  for( unsigned i=0; i<d_instStrategies.size(); ++i ){
74
26288
    d_instStrategies[i]->presolve();
75
  }
76
13147
}
77
78
2301
void InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
79
2301
  size_t lastWaiting = d_qim.numPendingLemmas();
80
  //iterate over an internal effort level e
81
2301
  int e = 0;
82
2301
  int eLimit = effort==Theory::EFFORT_LAST_CALL ? 10 : 2;
83
2301
  bool finished = false;
84
  //while unfinished, try effort level=0,1,2....
85
11513
  while( !finished && e<=eLimit ){
86
4606
    Debug("inst-engine") << "IE: Prepare instantiation (" << e << ")." << std::endl;
87
4606
    finished = true;
88
    //instantiate each quantifier
89
91064
    for( unsigned i=0; i<d_quants.size(); i++ ){
90
172916
      Node q = d_quants[i];
91
86458
      Debug("inst-engine-debug") << "IE: Instantiate " << q << "..." << std::endl;
92
      //int e_use = d_quantEngine->getRelevance( q )==-1 ? e - 1 : e;
93
86458
      int e_use = e;
94
86458
      if( e_use>=0 ){
95
86458
        Trace("inst-engine-debug") << "inst-engine : " << q << std::endl;
96
        //check each instantiation strategy
97
259374
        for( unsigned j=0; j<d_instStrategies.size(); j++ ){
98
172916
          InstStrategy* is = d_instStrategies[j];
99
172916
          Trace("inst-engine-debug") << "Do " << is->identify() << " " << e_use << std::endl;
100
172916
          InstStrategyStatus quantStatus = is->process(q, effort, e_use);
101
345832
          Trace("inst-engine-debug")
102
172916
              << " -> unfinished= "
103
345832
              << (quantStatus == InstStrategyStatus::STATUS_UNFINISHED)
104
172916
              << ", conflict=" << d_qstate.isInConflict() << std::endl;
105
172916
          if (d_qstate.isInConflict())
106
          {
107
            return;
108
          }
109
172916
          else if (quantStatus == InstStrategyStatus::STATUS_UNFINISHED)
110
          {
111
72853
            finished = false;
112
          }
113
        }
114
      }
115
    }
116
    //do not consider another level if already added lemma at this level
117
4606
    if (d_qim.numPendingLemmas() > lastWaiting)
118
    {
119
1335
      finished = true;
120
    }
121
4606
    e++;
122
  }
123
}
124
125
82235
bool InstantiationEngine::needsCheck( Theory::Effort e ){
126
82235
  return d_qstate.getInstWhenNeedsCheck(e);
127
}
128
129
30680
void InstantiationEngine::reset_round( Theory::Effort e ){
130
  //if not, proceed to instantiation round
131
  //reset the instantiation strategies
132
92028
  for( unsigned i=0; i<d_instStrategies.size(); ++i ){
133
61348
    InstStrategy* is = d_instStrategies[i];
134
61348
    is->processResetInstantiationRound( e );
135
  }
136
30680
}
137
138
58888
void InstantiationEngine::check(Theory::Effort e, QEffort quant_e)
139
{
140
77976
  CodeTimer codeTimer(d_qstate.getStats().d_ematching_time);
141
58888
  if (quant_e != QEFFORT_STANDARD)
142
  {
143
39800
    return;
144
  }
145
19088
  double clSet = 0;
146
19088
  if (Trace.isOn("inst-engine"))
147
  {
148
    clSet = double(clock()) / double(CLOCKS_PER_SEC);
149
    Trace("inst-engine") << "---Instantiation Engine Round, effort = " << e
150
                         << "---" << std::endl;
151
  }
152
  // collect all active quantified formulas belonging to this
153
19088
  bool quantActive = false;
154
19088
  d_quants.clear();
155
19088
  FirstOrderModel* m = d_treg.getModel();
156
19088
  size_t nquant = m->getNumAssertedQuantifiers();
157
85264
  for (size_t i = 0; i < nquant; i++)
158
  {
159
132352
    Node q = m->getAssertedQuantifier(i, true);
160
66176
    if (shouldProcess(q) && m->isQuantifierActive(q))
161
    {
162
43227
      quantActive = true;
163
43227
      d_quants.push_back(q);
164
    }
165
  }
166
38176
  Trace("inst-engine-debug")
167
19088
      << "InstEngine: check: # asserted quantifiers " << d_quants.size() << "/";
168
19088
  Trace("inst-engine-debug") << nquant << " " << quantActive << std::endl;
169
19088
  if (quantActive)
170
  {
171
2301
    size_t lastWaiting = d_qim.numPendingLemmas();
172
2301
    doInstantiationRound(e);
173
2301
    if (d_qstate.isInConflict())
174
    {
175
      Assert(d_qim.numPendingLemmas() > lastWaiting);
176
      Trace("inst-engine") << "Conflict, added lemmas = "
177
                           << (d_qim.numPendingLemmas() - lastWaiting)
178
                           << std::endl;
179
    }
180
2301
    else if (d_qim.hasPendingLemma())
181
    {
182
2670
      Trace("inst-engine") << "Added lemmas = "
183
2670
                           << (d_qim.numPendingLemmas() - lastWaiting)
184
1335
                           << std::endl;
185
    }
186
  }
187
  else
188
  {
189
16787
    d_quants.clear();
190
  }
191
19088
  if (Trace.isOn("inst-engine"))
192
  {
193
    double clSet2 = double(clock()) / double(CLOCKS_PER_SEC);
194
    Trace("inst-engine") << "Finished instantiation engine, time = "
195
                         << (clSet2 - clSet) << std::endl;
196
  }
197
}
198
199
652
bool InstantiationEngine::checkCompleteFor( Node q ) {
200
  //TODO?
201
652
  return false;
202
}
203
204
23848
void InstantiationEngine::checkOwnership(Node q)
205
{
206
47696
  if (options().quantifiers.userPatternsQuant == options::UserPatMode::STRICT
207
23848
      && q.getNumChildren() == 3)
208
  {
209
    //if strict triggers, take ownership of this quantified formula
210
    if (QuantAttributes::hasPattern(q))
211
    {
212
      d_qreg.setOwner(q, this, 1);
213
    }
214
  }
215
23848
}
216
217
23848
void InstantiationEngine::registerQuantifier(Node q)
218
{
219
23848
  if (!shouldProcess(q))
220
  {
221
3965
    return;
222
  }
223
19883
  if (d_quant_rel)
224
  {
225
344
    d_quant_rel->registerQuantifier(q);
226
  }
227
  // take into account user patterns
228
19883
  if (q.getNumChildren() == 3)
229
  {
230
8000
    Node subsPat = d_qreg.substituteBoundVariablesToInstConstants(q[2], q);
231
    // add patterns
232
8436
    for (const Node& p : subsPat)
233
    {
234
4436
      if (p.getKind() == INST_PATTERN)
235
      {
236
3904
        addUserPattern(q, p);
237
      }
238
532
      else if (p.getKind() == INST_NO_PATTERN)
239
      {
240
8
        addUserNoPattern(q, p);
241
      }
242
    }
243
  }
244
}
245
246
3904
void InstantiationEngine::addUserPattern(Node q, Node pat) {
247
3904
  if (d_isup) {
248
3904
    d_isup->addUserPattern(q, pat);
249
  }
250
3904
}
251
252
8
void InstantiationEngine::addUserNoPattern(Node q, Node pat) {
253
8
  if (d_i_ag) {
254
8
    d_i_ag->addUserNoPattern(q, pat);
255
  }
256
8
}
257
258
90024
bool InstantiationEngine::shouldProcess(Node q)
259
{
260
90024
  if (!d_qreg.hasOwnership(q, this))
261
  {
262
23453
    return false;
263
  }
264
  // also ignore internal quantifiers
265
66571
  QuantAttributes& qattr = d_qreg.getQuantAttributes();
266
66571
  if (qattr.isQuantBounded(q))
267
  {
268
3444
    return false;
269
  }
270
63127
  return true;
271
}
272
273
}  // namespace quantifiers
274
}  // namespace theory
275
31137
}  // namespace cvc5