GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/ematching/trigger_database.cpp Lines: 73 80 91.3 %
Date: 2021-05-22 Branches: 89 182 48.9 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Morgan Deters
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
 * Trigger database class.
14
 */
15
16
#include "theory/quantifiers/ematching/trigger_database.h"
17
18
#include "theory/quantifiers/ematching/ho_trigger.h"
19
#include "theory/quantifiers/ematching/trigger.h"
20
#include "theory/quantifiers/term_util.h"
21
22
namespace cvc5 {
23
namespace theory {
24
namespace quantifiers {
25
namespace inst {
26
27
6158
TriggerDatabase::TriggerDatabase(QuantifiersState& qs,
28
                                 QuantifiersInferenceManager& qim,
29
                                 QuantifiersRegistry& qr,
30
6158
                                 TermRegistry& tr)
31
6158
    : d_qs(qs), d_qim(qim), d_qreg(qr), d_treg(tr)
32
{
33
6158
}
34
6158
TriggerDatabase::~TriggerDatabase() {}
35
36
17298
Trigger* TriggerDatabase::mkTrigger(Node q,
37
                                    const std::vector<Node>& nodes,
38
                                    bool keepAll,
39
                                    int trOption,
40
                                    size_t useNVars)
41
{
42
34596
  std::vector<Node> trNodes;
43
17298
  if (!keepAll)
44
  {
45
13265
    size_t nvars = useNVars == 0 ? q[0].getNumChildren() : useNVars;
46
13265
    if (!mkTriggerTerms(q, nodes, nvars, trNodes))
47
    {
48
      return nullptr;
49
    }
50
  }
51
  else
52
  {
53
4033
    trNodes.insert(trNodes.begin(), nodes.begin(), nodes.end());
54
  }
55
56
  // check for duplicate?
57
17298
  if (trOption != TR_MAKE_NEW)
58
  {
59
13265
    Trigger* t = d_trie.getTrigger(trNodes);
60
13265
    if (t)
61
    {
62
37
      if (trOption == TR_GET_OLD)
63
      {
64
        // just return old trigger
65
37
        return t;
66
      }
67
      return nullptr;
68
    }
69
  }
70
71
  // check if higher-order
72
34522
  Trace("trigger-debug") << "Collect higher-order variable triggers..."
73
17261
                         << std::endl;
74
34522
  std::map<Node, std::vector<Node> > hoApps;
75
17261
  HigherOrderTrigger::collectHoVarApplyTerms(q, trNodes, hoApps);
76
34522
  Trace("trigger-debug") << "...got " << hoApps.size()
77
17261
                         << " higher-order applications." << std::endl;
78
  Trigger* t;
79
17261
  if (!hoApps.empty())
80
  {
81
36
    t = new HigherOrderTrigger(d_qs, d_qim, d_qreg, d_treg, q, trNodes, hoApps);
82
  }
83
  else
84
  {
85
17225
    t = new Trigger(d_qs, d_qim, d_qreg, d_treg, q, trNodes);
86
  }
87
17261
  d_trie.addTrigger(trNodes, t);
88
17261
  return t;
89
}
90
91
12173
Trigger* TriggerDatabase::mkTrigger(
92
    Node q, Node n, bool keepAll, int trOption, size_t useNVars)
93
{
94
24346
  std::vector<Node> nodes;
95
12173
  nodes.push_back(n);
96
24346
  return mkTrigger(q, nodes, keepAll, trOption, useNVars);
97
}
98
99
13265
bool TriggerDatabase::mkTriggerTerms(Node q,
100
                                     const std::vector<Node>& nodes,
101
                                     size_t nvars,
102
                                     std::vector<Node>& trNodes)
103
{
104
  // only take nodes that contribute variables to the trigger when added
105
26530
  std::map<Node, bool> vars;
106
26530
  std::map<Node, std::vector<Node> > patterns;
107
13265
  size_t varCount = 0;
108
26530
  std::map<Node, std::vector<Node> > varContains;
109
30709
  for (const Node& pat : nodes)
110
  {
111
17444
    TermUtil::computeInstConstContainsForQuant(q, pat, varContains[pat]);
112
  }
113
16287
  for (const Node& t : nodes)
114
  {
115
16287
    const std::vector<Node>& vct = varContains[t];
116
16287
    bool foundVar = false;
117
54737
    for (const Node& v : vct)
118
    {
119
38450
      Assert(TermUtil::getInstConstAttr(v) == q);
120
38450
      if (vars.find(v) == vars.end())
121
      {
122
35258
        varCount++;
123
35258
        vars[v] = true;
124
35258
        foundVar = true;
125
      }
126
    }
127
16287
    if (foundVar)
128
    {
129
15789
      trNodes.push_back(t);
130
53081
      for (const Node& v : vct)
131
      {
132
37292
        patterns[v].push_back(t);
133
      }
134
    }
135
16287
    if (varCount == nvars)
136
    {
137
13265
      break;
138
    }
139
  }
140
13265
  if (varCount < nvars)
141
  {
142
    Trace("trigger-debug") << "Don't consider trigger since it does not "
143
                              "contain specified number of variables."
144
                           << std::endl;
145
    Trace("trigger-debug") << nodes << std::endl;
146
    // do not generate multi-trigger if it does not contain all variables
147
    return false;
148
  }
149
  // now, minimize the trigger
150
30189
  for (size_t i = 0, tsize = trNodes.size(); i < tsize; i++)
151
  {
152
16924
    bool keepPattern = false;
153
33848
    Node n = trNodes[i];
154
16924
    const std::vector<Node>& vcn = varContains[n];
155
18732
    for (const Node& v : vcn)
156
    {
157
17597
      if (patterns[v].size() == 1)
158
      {
159
15789
        keepPattern = true;
160
15789
        break;
161
      }
162
    }
163
16924
    if (!keepPattern)
164
    {
165
      // remove from pattern vector
166
2640
      for (const Node& v : vcn)
167
      {
168
1505
        std::vector<Node>& pv = patterns[v];
169
1565
        for (size_t k = 0, pvsize = pv.size(); k < pvsize; k++)
170
        {
171
1565
          if (pv[k] == n)
172
          {
173
1505
            pv.erase(pv.begin() + k, pv.begin() + k + 1);
174
1505
            break;
175
          }
176
        }
177
      }
178
      // remove from trigger nodes
179
1135
      trNodes.erase(trNodes.begin() + i, trNodes.begin() + i + 1);
180
1135
      i--;
181
    }
182
  }
183
13265
  return true;
184
}
185
186
}  // namespace inst
187
}  // namespace quantifiers
188
}  // namespace theory
189
28194
}  // namespace cvc5