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