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 |
4587 |
TriggerDatabase::TriggerDatabase(Env& env, |
28 |
|
QuantifiersState& qs, |
29 |
|
QuantifiersInferenceManager& qim, |
30 |
|
QuantifiersRegistry& qr, |
31 |
4587 |
TermRegistry& tr) |
32 |
4587 |
: EnvObj(env), d_qs(qs), d_qim(qim), d_qreg(qr), d_treg(tr) |
33 |
|
{ |
34 |
4587 |
} |
35 |
4584 |
TriggerDatabase::~TriggerDatabase() {} |
36 |
|
|
37 |
6197 |
Trigger* TriggerDatabase::mkTrigger(Node q, |
38 |
|
const std::vector<Node>& nodes, |
39 |
|
bool keepAll, |
40 |
|
int trOption, |
41 |
|
size_t useNVars) |
42 |
|
{ |
43 |
12394 |
std::vector<Node> trNodes; |
44 |
6197 |
if (!keepAll) |
45 |
|
{ |
46 |
4980 |
size_t nvars = useNVars == 0 ? q[0].getNumChildren() : useNVars; |
47 |
4980 |
if (!mkTriggerTerms(q, nodes, nvars, trNodes)) |
48 |
|
{ |
49 |
|
return nullptr; |
50 |
|
} |
51 |
|
} |
52 |
|
else |
53 |
|
{ |
54 |
1217 |
trNodes.insert(trNodes.begin(), nodes.begin(), nodes.end()); |
55 |
|
} |
56 |
|
|
57 |
|
// check for duplicate? |
58 |
6197 |
if (trOption != TR_MAKE_NEW) |
59 |
|
{ |
60 |
4980 |
Trigger* t = d_trie.getTrigger(trNodes); |
61 |
4980 |
if (t) |
62 |
|
{ |
63 |
25 |
if (trOption == TR_GET_OLD) |
64 |
|
{ |
65 |
|
// just return old trigger |
66 |
25 |
return t; |
67 |
|
} |
68 |
|
return nullptr; |
69 |
|
} |
70 |
|
} |
71 |
|
|
72 |
|
// check if higher-order |
73 |
12344 |
Trace("trigger-debug") << "Collect higher-order variable triggers..." |
74 |
6172 |
<< std::endl; |
75 |
12344 |
std::map<Node, std::vector<Node> > hoApps; |
76 |
6172 |
HigherOrderTrigger::collectHoVarApplyTerms(q, trNodes, hoApps); |
77 |
12344 |
Trace("trigger-debug") << "...got " << hoApps.size() |
78 |
6172 |
<< " higher-order applications." << std::endl; |
79 |
|
Trigger* t; |
80 |
6172 |
if (!hoApps.empty()) |
81 |
|
{ |
82 |
16 |
t = new HigherOrderTrigger( |
83 |
8 |
d_env, d_qs, d_qim, d_qreg, d_treg, q, trNodes, hoApps); |
84 |
|
} |
85 |
|
else |
86 |
|
{ |
87 |
6164 |
t = new Trigger(d_env, d_qs, d_qim, d_qreg, d_treg, q, trNodes); |
88 |
|
} |
89 |
6172 |
d_trie.addTrigger(trNodes, t); |
90 |
6172 |
return t; |
91 |
|
} |
92 |
|
|
93 |
4562 |
Trigger* TriggerDatabase::mkTrigger( |
94 |
|
Node q, Node n, bool keepAll, int trOption, size_t useNVars) |
95 |
|
{ |
96 |
9124 |
std::vector<Node> nodes; |
97 |
4562 |
nodes.push_back(n); |
98 |
9124 |
return mkTrigger(q, nodes, keepAll, trOption, useNVars); |
99 |
|
} |
100 |
|
|
101 |
4980 |
bool TriggerDatabase::mkTriggerTerms(Node q, |
102 |
|
const std::vector<Node>& nodes, |
103 |
|
size_t nvars, |
104 |
|
std::vector<Node>& trNodes) |
105 |
|
{ |
106 |
|
// only take nodes that contribute variables to the trigger when added |
107 |
9960 |
std::map<Node, bool> vars; |
108 |
9960 |
std::map<Node, std::vector<Node> > patterns; |
109 |
4980 |
size_t varCount = 0; |
110 |
9960 |
std::map<Node, std::vector<Node> > varContains; |
111 |
11592 |
for (const Node& pat : nodes) |
112 |
|
{ |
113 |
6612 |
TermUtil::computeInstConstContainsForQuant(q, pat, varContains[pat]); |
114 |
|
} |
115 |
6110 |
for (const Node& t : nodes) |
116 |
|
{ |
117 |
6110 |
const std::vector<Node>& vct = varContains[t]; |
118 |
6110 |
bool foundVar = false; |
119 |
20344 |
for (const Node& v : vct) |
120 |
|
{ |
121 |
14234 |
Assert(TermUtil::getInstConstAttr(v) == q); |
122 |
14234 |
if (vars.find(v) == vars.end()) |
123 |
|
{ |
124 |
13052 |
varCount++; |
125 |
13052 |
vars[v] = true; |
126 |
13052 |
foundVar = true; |
127 |
|
} |
128 |
|
} |
129 |
6110 |
if (foundVar) |
130 |
|
{ |
131 |
5934 |
trNodes.push_back(t); |
132 |
19760 |
for (const Node& v : vct) |
133 |
|
{ |
134 |
13826 |
patterns[v].push_back(t); |
135 |
|
} |
136 |
|
} |
137 |
6110 |
if (varCount == nvars) |
138 |
|
{ |
139 |
4980 |
break; |
140 |
|
} |
141 |
|
} |
142 |
4980 |
if (varCount < nvars) |
143 |
|
{ |
144 |
|
Trace("trigger-debug") << "Don't consider trigger since it does not " |
145 |
|
"contain specified number of variables." |
146 |
|
<< std::endl; |
147 |
|
Trace("trigger-debug") << nodes << std::endl; |
148 |
|
// do not generate multi-trigger if it does not contain all variables |
149 |
|
return false; |
150 |
|
} |
151 |
|
// now, minimize the trigger |
152 |
11349 |
for (size_t i = 0, tsize = trNodes.size(); i < tsize; i++) |
153 |
|
{ |
154 |
6369 |
bool keepPattern = false; |
155 |
12738 |
Node n = trNodes[i]; |
156 |
6369 |
const std::vector<Node>& vcn = varContains[n]; |
157 |
7044 |
for (const Node& v : vcn) |
158 |
|
{ |
159 |
6609 |
if (patterns[v].size() == 1) |
160 |
|
{ |
161 |
5934 |
keepPattern = true; |
162 |
5934 |
break; |
163 |
|
} |
164 |
|
} |
165 |
6369 |
if (!keepPattern) |
166 |
|
{ |
167 |
|
// remove from pattern vector |
168 |
1011 |
for (const Node& v : vcn) |
169 |
|
{ |
170 |
576 |
std::vector<Node>& pv = patterns[v]; |
171 |
598 |
for (size_t k = 0, pvsize = pv.size(); k < pvsize; k++) |
172 |
|
{ |
173 |
598 |
if (pv[k] == n) |
174 |
|
{ |
175 |
576 |
pv.erase(pv.begin() + k, pv.begin() + k + 1); |
176 |
576 |
break; |
177 |
|
} |
178 |
|
} |
179 |
|
} |
180 |
|
// remove from trigger nodes |
181 |
435 |
trNodes.erase(trNodes.begin() + i, trNodes.begin() + i + 1); |
182 |
435 |
i--; |
183 |
|
} |
184 |
|
} |
185 |
4980 |
return true; |
186 |
|
} |
187 |
|
|
188 |
|
} // namespace inst |
189 |
|
} // namespace quantifiers |
190 |
|
} // namespace theory |
191 |
22755 |
} // namespace cvc5 |