GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/ematching/inst_match_generator_multi.cpp Lines: 132 140 94.3 %
Date: 2021-09-16 Branches: 207 392 52.8 %

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
 * Multi inst match generator class.
14
 */
15
16
#include "theory/quantifiers/ematching/inst_match_generator_multi.h"
17
18
#include "theory/quantifiers/quantifiers_state.h"
19
#include "theory/quantifiers/term_util.h"
20
#include "theory/uf/equality_engine_iterator.h"
21
22
using namespace cvc5::kind;
23
24
namespace cvc5 {
25
namespace theory {
26
namespace quantifiers {
27
namespace inst {
28
29
10
InstMatchGeneratorMulti::InstMatchGeneratorMulti(Trigger* tparent,
30
                                                 Node q,
31
10
                                                 std::vector<Node>& pats)
32
10
    : IMGenerator(tparent), d_quant(q)
33
{
34
20
  Trace("multi-trigger-cache")
35
10
      << "Making smart multi-trigger for " << q << std::endl;
36
20
  std::map<Node, std::vector<Node> > var_contains;
37
33
  for (const Node& pat : pats)
38
  {
39
23
    TermUtil::computeInstConstContainsForQuant(q, pat, var_contains[pat]);
40
  }
41
  // convert to indicies
42
33
  for (std::pair<const Node, std::vector<Node> >& vc : var_contains)
43
  {
44
23
    Trace("multi-trigger-cache") << "Pattern " << vc.first << " contains: ";
45
111
    for (const Node& vcn : vc.second)
46
    {
47
88
      Trace("multi-trigger-cache") << vcn << " ";
48
88
      uint64_t index = vcn.getAttribute(InstVarNumAttribute());
49
88
      d_var_contains[vc.first].push_back(index);
50
88
      d_var_to_node[index].push_back(vc.first);
51
    }
52
23
    Trace("multi-trigger-cache") << std::endl;
53
  }
54
10
  size_t patsSize = pats.size();
55
33
  for (size_t i = 0; i < patsSize; i++)
56
  {
57
46
    Node n = pats[i];
58
    // make the match generator
59
    InstMatchGenerator* img =
60
23
        InstMatchGenerator::mkInstMatchGenerator(tparent, q, n);
61
23
    img->setActiveAdd(false);
62
23
    d_children.push_back(img);
63
    // compute unique/shared variables
64
46
    std::vector<uint64_t> unique_vars;
65
46
    std::map<uint64_t, bool> shared_vars;
66
23
    unsigned numSharedVars = 0;
67
23
    std::vector<uint64_t>& vctn = d_var_contains[n];
68
111
    for (size_t j = 0, vctnSize = vctn.size(); j < vctnSize; j++)
69
    {
70
88
      if (d_var_to_node[vctn[j]].size() == 1)
71
      {
72
118
        Trace("multi-trigger-cache")
73
59
            << "Var " << vctn[j] << " is unique to " << pats[i] << std::endl;
74
59
        unique_vars.push_back(vctn[j]);
75
      }
76
      else
77
      {
78
29
        shared_vars[vctn[j]] = true;
79
29
        numSharedVars++;
80
      }
81
    }
82
    // we use the latest shared variables, then unique variables
83
46
    std::vector<uint64_t> vars;
84
23
    size_t index = i == 0 ? pats.size() - 1 : (i - 1);
85
75
    while (numSharedVars > 0 && index != i)
86
    {
87
61
      for (std::pair<const uint64_t, bool>& sv : shared_vars)
88
      {
89
35
        if (sv.second)
90
        {
91
32
          std::vector<uint64_t>& vctni = d_var_contains[pats[index]];
92
32
          if (std::find(vctni.begin(), vctni.end(), sv.first) != vctni.end())
93
          {
94
29
            vars.push_back(sv.first);
95
29
            shared_vars[sv.first] = false;
96
29
            numSharedVars--;
97
          }
98
        }
99
      }
100
26
      index = index == 0 ? patsSize - 1 : (index - 1);
101
    }
102
23
    vars.insert(vars.end(), unique_vars.begin(), unique_vars.end());
103
23
    if (Trace.isOn("multi-trigger-cache"))
104
    {
105
      Trace("multi-trigger-cache") << "   Index[" << i << "]: ";
106
      for (uint64_t v : vars)
107
      {
108
        Trace("multi-trigger-cache") << v << " ";
109
      }
110
      Trace("multi-trigger-cache") << std::endl;
111
    }
112
    // make ordered inst match trie
113
23
    d_imtio[i] = new InstMatchTrie::ImtIndexOrder;
114
46
    d_imtio[i]->d_order.insert(
115
46
        d_imtio[i]->d_order.begin(), vars.begin(), vars.end());
116
23
    d_children_trie.push_back(InstMatchTrieOrdered(d_imtio[i]));
117
  }
118
10
}
119
120
30
InstMatchGeneratorMulti::~InstMatchGeneratorMulti()
121
{
122
33
  for (size_t i = 0, csize = d_children.size(); i < csize; i++)
123
  {
124
23
    delete d_children[i];
125
  }
126
33
  for (std::pair<const size_t, InstMatchTrie::ImtIndexOrder*>& i : d_imtio)
127
  {
128
23
    delete i.second;
129
  }
130
20
}
131
132
/** reset instantiation round (call this whenever equivalence classes have
133
 * changed) */
134
54
void InstMatchGeneratorMulti::resetInstantiationRound()
135
{
136
171
  for (InstMatchGenerator* c : d_children)
137
  {
138
117
    c->resetInstantiationRound();
139
  }
140
54
}
141
142
/** reset, eqc is the equivalence class to search in (any if eqc=null) */
143
54
bool InstMatchGeneratorMulti::reset(Node eqc)
144
{
145
171
  for (InstMatchGenerator* c : d_children)
146
  {
147
117
    if (!c->reset(eqc))
148
    {
149
      // do not return false here
150
    }
151
  }
152
54
  return true;
153
}
154
155
32
uint64_t InstMatchGeneratorMulti::addInstantiations(Node q)
156
{
157
32
  uint64_t addedLemmas = 0;
158
32
  Trace("multi-trigger-cache") << "Process smart multi trigger" << std::endl;
159
102
  for (size_t i = 0, csize = d_children.size(); i < csize; i++)
160
  {
161
70
    Trace("multi-trigger-cache") << "Calculate matches " << i << std::endl;
162
140
    std::vector<InstMatch> newMatches;
163
140
    InstMatch m(q);
164
686
    while (d_children[i]->getNextMatch(q, m) > 0)
165
    {
166
      // m.makeRepresentative( qe );
167
308
      newMatches.push_back(InstMatch(&m));
168
308
      m.clear();
169
    }
170
140
    Trace("multi-trigger-cache") << "Made " << newMatches.size()
171
70
                                 << " new matches for index " << i << std::endl;
172
378
    for (size_t j = 0, nmatches = newMatches.size(); j < nmatches; j++)
173
    {
174
616
      Trace("multi-trigger-cache2")
175
616
          << "...processing " << j << " / " << newMatches.size()
176
308
          << ", #lemmas = " << addedLemmas << std::endl;
177
308
      processNewMatch(newMatches[j], i, addedLemmas);
178
308
      if (d_qstate.isInConflict())
179
      {
180
        return addedLemmas;
181
      }
182
    }
183
  }
184
32
  return addedLemmas;
185
}
186
187
308
void InstMatchGeneratorMulti::processNewMatch(InstMatch& m,
188
                                              size_t fromChildIndex,
189
                                              uint64_t& addedLemmas)
190
{
191
  // see if these produce new matches
192
308
  d_children_trie[fromChildIndex].addInstMatch(d_qstate, d_quant, m.d_vals);
193
  // possibly only do the following if we know that new matches will be
194
  // produced? the issue is that instantiations are filtered in quantifiers
195
  // engine, and so there is no guarentee that
196
  // we can safely skip the following lines, even when we have already produced
197
  // this match.
198
616
  Trace("multi-trigger-cache-debug")
199
308
      << "Child " << fromChildIndex << " produced match " << m << std::endl;
200
  // process new instantiations
201
308
  size_t childIndex = (fromChildIndex + 1) % d_children.size();
202
616
  processNewInstantiations(m,
203
                           addedLemmas,
204
308
                           d_children_trie[childIndex].getTrie(),
205
                           0,
206
                           childIndex,
207
                           fromChildIndex,
208
                           true);
209
308
}
210
211
3236
void InstMatchGeneratorMulti::processNewInstantiations(InstMatch& m,
212
                                                       uint64_t& addedLemmas,
213
                                                       InstMatchTrie* tr,
214
                                                       size_t trieIndex,
215
                                                       size_t childIndex,
216
                                                       size_t endChildIndex,
217
                                                       bool modEq)
218
{
219
3236
  Assert(!d_qstate.isInConflict());
220
3236
  if (childIndex == endChildIndex)
221
  {
222
    // m is an instantiation
223
953
    if (sendInstantiation(m, InferenceId::QUANTIFIERS_INST_E_MATCHING_MT))
224
    {
225
404
      addedLemmas++;
226
808
      Trace("multi-trigger-cache-debug")
227
404
          << "-> Produced instantiation " << m << std::endl;
228
    }
229
953
    return;
230
  }
231
2283
  InstMatchTrie::ImtIndexOrder* iio = d_children_trie[childIndex].getOrdering();
232
2283
  if (trieIndex < iio->d_order.size())
233
  {
234
1165
    size_t curr_index = iio->d_order[trieIndex];
235
1803
    Node n = m.get(curr_index);
236
1165
    if (n.isNull())
237
    {
238
      // add to InstMatch
239
1916
      for (std::pair<const Node, InstMatchTrie>& d : tr->d_data)
240
      {
241
2778
        InstMatch mn(&m);
242
1389
        mn.setValue(curr_index, d.first);
243
1389
        processNewInstantiations(mn,
244
                                 addedLemmas,
245
                                 &(d.second),
246
                                 trieIndex + 1,
247
                                 childIndex,
248
                                 endChildIndex,
249
                                 modEq);
250
1389
        if (d_qstate.isInConflict())
251
        {
252
          break;
253
        }
254
      }
255
    }
256
    // shared and set variable, try to merge
257
1165
    std::map<Node, InstMatchTrie>::iterator it = tr->d_data.find(n);
258
1165
    if (it != tr->d_data.end())
259
    {
260
722
      processNewInstantiations(m,
261
                               addedLemmas,
262
361
                               &(it->second),
263
                               trieIndex + 1,
264
                               childIndex,
265
                               endChildIndex,
266
                               modEq);
267
    }
268
1165
    if (!modEq)
269
    {
270
      return;
271
    }
272
1165
    QuantifiersState& qs = d_qstate;
273
    // check modulo equality for other possible instantiations
274
1165
    if (!qs.hasTerm(n))
275
    {
276
527
      return;
277
    }
278
638
    eq::EqClassIterator eqc(qs.getRepresentative(n), qs.getEqualityEngine());
279
2834
    while (!eqc.isFinished())
280
    {
281
2196
      Node en = (*eqc);
282
1098
      if (en != n)
283
      {
284
460
        std::map<Node, InstMatchTrie>::iterator itc = tr->d_data.find(en);
285
460
        if (itc != tr->d_data.end())
286
        {
287
120
          processNewInstantiations(m,
288
                                   addedLemmas,
289
60
                                   &(itc->second),
290
                                   trieIndex + 1,
291
                                   childIndex,
292
                                   endChildIndex,
293
                                   modEq);
294
60
          if (d_qstate.isInConflict())
295
          {
296
            break;
297
          }
298
        }
299
      }
300
1098
      ++eqc;
301
    }
302
  }
303
  else
304
  {
305
1118
    size_t newChildIndex = (childIndex + 1) % d_children.size();
306
2236
    processNewInstantiations(m,
307
                             addedLemmas,
308
1118
                             d_children_trie[newChildIndex].getTrie(),
309
                             0,
310
                             newChildIndex,
311
                             endChildIndex,
312
                             modEq);
313
  }
314
}
315
316
}  // namespace inst
317
}  // namespace quantifiers
318
}  // namespace theory
319
29577
}  // namespace cvc5