GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/ematching/trigger_database.cpp Lines: 73 80 91.3 %
Date: 2021-09-15 Branches: 89 180 49.4 %

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
6577
TriggerDatabase::TriggerDatabase(QuantifiersState& qs,
28
                                 QuantifiersInferenceManager& qim,
29
                                 QuantifiersRegistry& qr,
30
6577
                                 TermRegistry& tr)
31
6577
    : d_qs(qs), d_qim(qim), d_qreg(qr), d_treg(tr)
32
{
33
6577
}
34
6574
TriggerDatabase::~TriggerDatabase() {}
35
36
17130
Trigger* TriggerDatabase::mkTrigger(Node q,
37
                                    const std::vector<Node>& nodes,
38
                                    bool keepAll,
39
                                    int trOption,
40
                                    size_t useNVars)
41
{
42
34260
  std::vector<Node> trNodes;
43
17130
  if (!keepAll)
44
  {
45
13269
    size_t nvars = useNVars == 0 ? q[0].getNumChildren() : useNVars;
46
13269
    if (!mkTriggerTerms(q, nodes, nvars, trNodes))
47
    {
48
      return nullptr;
49
    }
50
  }
51
  else
52
  {
53
3861
    trNodes.insert(trNodes.begin(), nodes.begin(), nodes.end());
54
  }
55
56
  // check for duplicate?
57
17130
  if (trOption != TR_MAKE_NEW)
58
  {
59
13269
    Trigger* t = d_trie.getTrigger(trNodes);
60
13269
    if (t)
61
    {
62
95
      if (trOption == TR_GET_OLD)
63
      {
64
        // just return old trigger
65
95
        return t;
66
      }
67
      return nullptr;
68
    }
69
  }
70
71
  // check if higher-order
72
34070
  Trace("trigger-debug") << "Collect higher-order variable triggers..."
73
17035
                         << std::endl;
74
34070
  std::map<Node, std::vector<Node> > hoApps;
75
17035
  HigherOrderTrigger::collectHoVarApplyTerms(q, trNodes, hoApps);
76
34070
  Trace("trigger-debug") << "...got " << hoApps.size()
77
17035
                         << " higher-order applications." << std::endl;
78
  Trigger* t;
79
17035
  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
16999
    t = new Trigger(d_qs, d_qim, d_qreg, d_treg, q, trNodes);
86
  }
87
17035
  d_trie.addTrigger(trNodes, t);
88
17035
  return t;
89
}
90
91
12120
Trigger* TriggerDatabase::mkTrigger(
92
    Node q, Node n, bool keepAll, int trOption, size_t useNVars)
93
{
94
24240
  std::vector<Node> nodes;
95
12120
  nodes.push_back(n);
96
24240
  return mkTrigger(q, nodes, keepAll, trOption, useNVars);
97
}
98
99
13269
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
26538
  std::map<Node, bool> vars;
106
26538
  std::map<Node, std::vector<Node> > patterns;
107
13269
  size_t varCount = 0;
108
26538
  std::map<Node, std::vector<Node> > varContains;
109
30927
  for (const Node& pat : nodes)
110
  {
111
17658
    TermUtil::computeInstConstContainsForQuant(q, pat, varContains[pat]);
112
  }
113
16320
  for (const Node& t : nodes)
114
  {
115
16320
    const std::vector<Node>& vct = varContains[t];
116
16320
    bool foundVar = false;
117
54912
    for (const Node& v : vct)
118
    {
119
38592
      Assert(TermUtil::getInstConstAttr(v) == q);
120
38592
      if (vars.find(v) == vars.end())
121
      {
122
35362
        varCount++;
123
35362
        vars[v] = true;
124
35362
        foundVar = true;
125
      }
126
    }
127
16320
    if (foundVar)
128
    {
129
15840
      trNodes.push_back(t);
130
53317
      for (const Node& v : vct)
131
      {
132
37477
        patterns[v].push_back(t);
133
      }
134
    }
135
16320
    if (varCount == nvars)
136
    {
137
13269
      break;
138
    }
139
  }
140
13269
  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
30262
  for (size_t i = 0, tsize = trNodes.size(); i < tsize; i++)
151
  {
152
16993
    bool keepPattern = false;
153
33986
    Node n = trNodes[i];
154
16993
    const std::vector<Node>& vcn = varContains[n];
155
18820
    for (const Node& v : vcn)
156
    {
157
17667
      if (patterns[v].size() == 1)
158
      {
159
15840
        keepPattern = true;
160
15840
        break;
161
      }
162
    }
163
16993
    if (!keepPattern)
164
    {
165
      // remove from pattern vector
166
2694
      for (const Node& v : vcn)
167
      {
168
1541
        std::vector<Node>& pv = patterns[v];
169
1603
        for (size_t k = 0, pvsize = pv.size(); k < pvsize; k++)
170
        {
171
1603
          if (pv[k] == n)
172
          {
173
1541
            pv.erase(pv.begin() + k, pv.begin() + k + 1);
174
1541
            break;
175
          }
176
        }
177
      }
178
      // remove from trigger nodes
179
1153
      trNodes.erase(trNodes.begin() + i, trNodes.begin() + i + 1);
180
1153
      i--;
181
    }
182
  }
183
13269
  return true;
184
}
185
186
}  // namespace inst
187
}  // namespace quantifiers
188
}  // namespace theory
189
29577
}  // namespace cvc5