GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/ematching/instantiation_engine.cpp Lines: 115 128 89.8 %
Date: 2021-09-10 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
6562
InstantiationEngine::InstantiationEngine(Env& env,
36
                                         QuantifiersState& qs,
37
                                         QuantifiersInferenceManager& qim,
38
                                         QuantifiersRegistry& qr,
39
6562
                                         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(qs, qim, qr, tr),
46
6562
      d_quant_rel(nullptr)
47
{
48
6562
  if (options::relevantTriggers())
49
  {
50
4
    d_quant_rel.reset(new quantifiers::QuantRelevance(env));
51
  }
52
6562
  if (options::eMatching()) {
53
    // these are the instantiation strategies for E-matching
54
    // user-provided patterns
55
6560
    if (options::userPatternsQuant() != options::UserPatMode::IGNORE)
56
    {
57
6560
      d_isup.reset(new InstStrategyUserPatterns(d_trdb, qs, qim, qr, tr));
58
6560
      d_instStrategies.push_back(d_isup.get());
59
    }
60
61
    // auto-generated patterns
62
13120
    d_i_ag.reset(new InstStrategyAutoGenTriggers(
63
6560
        d_trdb, qs, qim, qr, tr, d_quant_rel.get()));
64
6560
    d_instStrategies.push_back(d_i_ag.get());
65
  }
66
6562
}
67
68
13118
InstantiationEngine::~InstantiationEngine() {}
69
70
7886
void InstantiationEngine::presolve() {
71
23654
  for( unsigned i=0; i<d_instStrategies.size(); ++i ){
72
15768
    d_instStrategies[i]->presolve();
73
  }
74
7886
}
75
76
2285
void InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
77
2285
  size_t lastWaiting = d_qim.numPendingLemmas();
78
  //iterate over an internal effort level e
79
2285
  int e = 0;
80
2285
  int eLimit = effort==Theory::EFFORT_LAST_CALL ? 10 : 2;
81
2285
  bool finished = false;
82
  //while unfinished, try effort level=0,1,2....
83
11425
  while( !finished && e<=eLimit ){
84
4570
    Debug("inst-engine") << "IE: Prepare instantiation (" << e << ")." << std::endl;
85
4570
    finished = true;
86
    //instantiate each quantifier
87
88432
    for( unsigned i=0; i<d_quants.size(); i++ ){
88
167724
      Node q = d_quants[i];
89
83862
      Debug("inst-engine-debug") << "IE: Instantiate " << q << "..." << std::endl;
90
      //int e_use = d_quantEngine->getRelevance( q )==-1 ? e - 1 : e;
91
83862
      int e_use = e;
92
83862
      if( e_use>=0 ){
93
83862
        Trace("inst-engine-debug") << "inst-engine : " << q << std::endl;
94
        //check each instantiation strategy
95
251586
        for( unsigned j=0; j<d_instStrategies.size(); j++ ){
96
167724
          InstStrategy* is = d_instStrategies[j];
97
167724
          Trace("inst-engine-debug") << "Do " << is->identify() << " " << e_use << std::endl;
98
167724
          InstStrategyStatus quantStatus = is->process(q, effort, e_use);
99
335448
          Trace("inst-engine-debug")
100
167724
              << " -> unfinished= "
101
335448
              << (quantStatus == InstStrategyStatus::STATUS_UNFINISHED)
102
167724
              << ", conflict=" << d_qstate.isInConflict() << std::endl;
103
167724
          if (d_qstate.isInConflict())
104
          {
105
            return;
106
          }
107
167724
          else if (quantStatus == InstStrategyStatus::STATUS_UNFINISHED)
108
          {
109
70408
            finished = false;
110
          }
111
        }
112
      }
113
    }
114
    //do not consider another level if already added lemma at this level
115
4570
    if (d_qim.numPendingLemmas() > lastWaiting)
116
    {
117
1180
      finished = true;
118
    }
119
4570
    e++;
120
  }
121
}
122
123
66762
bool InstantiationEngine::needsCheck( Theory::Effort e ){
124
66762
  return d_qstate.getInstWhenNeedsCheck(e);
125
}
126
127
23883
void InstantiationEngine::reset_round( Theory::Effort e ){
128
  //if not, proceed to instantiation round
129
  //reset the instantiation strategies
130
71643
  for( unsigned i=0; i<d_instStrategies.size(); ++i ){
131
47760
    InstStrategy* is = d_instStrategies[i];
132
47760
    is->processResetInstantiationRound( e );
133
  }
134
23883
}
135
136
36424
void InstantiationEngine::check(Theory::Effort e, QEffort quant_e)
137
{
138
48961
  CodeTimer codeTimer(d_qstate.getStats().d_ematching_time);
139
36424
  if (quant_e != QEFFORT_STANDARD)
140
  {
141
23887
    return;
142
  }
143
12537
  double clSet = 0;
144
12537
  if (Trace.isOn("inst-engine"))
145
  {
146
    clSet = double(clock()) / double(CLOCKS_PER_SEC);
147
    Trace("inst-engine") << "---Instantiation Engine Round, effort = " << e
148
                         << "---" << std::endl;
149
  }
150
  // collect all active quantified formulas belonging to this
151
12537
  bool quantActive = false;
152
12537
  d_quants.clear();
153
12537
  FirstOrderModel* m = d_treg.getModel();
154
12537
  size_t nquant = m->getNumAssertedQuantifiers();
155
70941
  for (size_t i = 0; i < nquant; i++)
156
  {
157
116808
    Node q = m->getAssertedQuantifier(i, true);
158
58404
    if (shouldProcess(q) && m->isQuantifierActive(q))
159
    {
160
41931
      quantActive = true;
161
41931
      d_quants.push_back(q);
162
    }
163
  }
164
25074
  Trace("inst-engine-debug")
165
12537
      << "InstEngine: check: # asserted quantifiers " << d_quants.size() << "/";
166
12537
  Trace("inst-engine-debug") << nquant << " " << quantActive << std::endl;
167
12537
  if (quantActive)
168
  {
169
2285
    size_t lastWaiting = d_qim.numPendingLemmas();
170
2285
    doInstantiationRound(e);
171
2285
    if (d_qstate.isInConflict())
172
    {
173
      Assert(d_qim.numPendingLemmas() > lastWaiting);
174
      Trace("inst-engine") << "Conflict, added lemmas = "
175
                           << (d_qim.numPendingLemmas() - lastWaiting)
176
                           << std::endl;
177
    }
178
2285
    else if (d_qim.hasPendingLemma())
179
    {
180
2360
      Trace("inst-engine") << "Added lemmas = "
181
2360
                           << (d_qim.numPendingLemmas() - lastWaiting)
182
1180
                           << std::endl;
183
    }
184
  }
185
  else
186
  {
187
10252
    d_quants.clear();
188
  }
189
12537
  if (Trace.isOn("inst-engine"))
190
  {
191
    double clSet2 = double(clock()) / double(CLOCKS_PER_SEC);
192
    Trace("inst-engine") << "Finished instantiation engine, time = "
193
                         << (clSet2 - clSet) << std::endl;
194
  }
195
}
196
197
576
bool InstantiationEngine::checkCompleteFor( Node q ) {
198
  //TODO?
199
576
  return false;
200
}
201
202
22839
void InstantiationEngine::checkOwnership(Node q)
203
{
204
45678
  if (options::userPatternsQuant() == options::UserPatMode::STRICT
205
22839
      && q.getNumChildren() == 3)
206
  {
207
    //if strict triggers, take ownership of this quantified formula
208
    if (QuantAttributes::hasPattern(q))
209
    {
210
      d_qreg.setOwner(q, this, 1);
211
    }
212
  }
213
22839
}
214
215
22839
void InstantiationEngine::registerQuantifier(Node q)
216
{
217
22839
  if (!shouldProcess(q))
218
  {
219
3420
    return;
220
  }
221
19419
  if (d_quant_rel)
222
  {
223
344
    d_quant_rel->registerQuantifier(q);
224
  }
225
  // take into account user patterns
226
19419
  if (q.getNumChildren() == 3)
227
  {
228
7906
    Node subsPat = d_qreg.substituteBoundVariablesToInstConstants(q[2], q);
229
    // add patterns
230
8338
    for (const Node& p : subsPat)
231
    {
232
4385
      if (p.getKind() == INST_PATTERN)
233
      {
234
3884
        addUserPattern(q, p);
235
      }
236
501
      else if (p.getKind() == INST_NO_PATTERN)
237
      {
238
8
        addUserNoPattern(q, p);
239
      }
240
    }
241
  }
242
}
243
244
3884
void InstantiationEngine::addUserPattern(Node q, Node pat) {
245
3884
  if (d_isup) {
246
3884
    d_isup->addUserPattern(q, pat);
247
  }
248
3884
}
249
250
8
void InstantiationEngine::addUserNoPattern(Node q, Node pat) {
251
8
  if (d_i_ag) {
252
8
    d_i_ag->addUserNoPattern(q, pat);
253
  }
254
8
}
255
256
81243
bool InstantiationEngine::shouldProcess(Node q)
257
{
258
81243
  if (!d_qreg.hasOwnership(q, this))
259
  {
260
16449
    return false;
261
  }
262
  // also ignore internal quantifiers
263
64794
  QuantAttributes& qattr = d_qreg.getQuantAttributes();
264
64794
  if (qattr.isInternal(q))
265
  {
266
3402
    return false;
267
  }
268
61392
  return true;
269
}
270
271
}  // namespace quantifiers
272
}  // namespace theory
273
29502
}  // namespace cvc5