1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Andrew Reynolds, Mathias Preiner, 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 |
|
* Inst match generator class. |
14 |
|
*/ |
15 |
|
|
16 |
|
#include "cvc5_private.h" |
17 |
|
|
18 |
|
#ifndef CVC5__THEORY__QUANTIFIERS__INST_MATCH_GENERATOR_H |
19 |
|
#define CVC5__THEORY__QUANTIFIERS__INST_MATCH_GENERATOR_H |
20 |
|
|
21 |
|
#include <map> |
22 |
|
#include "expr/node.h" |
23 |
|
#include "theory/quantifiers/inst_match.h" |
24 |
|
#include "theory/quantifiers/ematching/im_generator.h" |
25 |
|
|
26 |
|
namespace cvc5 { |
27 |
|
namespace theory { |
28 |
|
namespace quantifiers { |
29 |
|
namespace inst { |
30 |
|
|
31 |
|
class CandidateGenerator; |
32 |
|
|
33 |
|
/** InstMatchGenerator class |
34 |
|
* |
35 |
|
* This is the default generator class for non-simple single triggers, that is, |
36 |
|
* triggers composed of a single term with nested term applications. |
37 |
|
* For example, { f( y, f( x, a ) ) } and { f( g( x ), a ) } are non-simple |
38 |
|
* triggers. |
39 |
|
* |
40 |
|
* Handling non-simple triggers is done by constructing a linked list of |
41 |
|
* InstMatchGenerator classes (see mkInstMatchGenerator), where each |
42 |
|
* InstMatchGenerator has a "d_next" pointer. If d_next is NULL, |
43 |
|
* then this is the end of the InstMatchGenerator and the last |
44 |
|
* InstMatchGenerator is responsible for finalizing the instantiation. |
45 |
|
* |
46 |
|
* For (EX1), for the trigger f( y, f( x, a ) ), we construct the linked list: |
47 |
|
* |
48 |
|
* [ f( y, f( x, a ) ) ] -> [ f( x, a ) ] -> NULL |
49 |
|
* |
50 |
|
* In a call to getNextMatch, |
51 |
|
* if we match against a ground term f( b, c ), then the first |
52 |
|
* InstMatchGenerator in this list binds y to b, and tells the |
53 |
|
* InstMatchGenerator [ f( x, a ) ] to match f-applications in the equivalence |
54 |
|
* class of c. |
55 |
|
* |
56 |
|
* cvc5 employs techniques that ensure that the number of instantiations |
57 |
|
* is worst-case polynomial wrt the number of ground terms. |
58 |
|
* Consider the axiom/pattern/context (EX2) : |
59 |
|
* |
60 |
|
* axiom : forall x1 x2 x3 x4. F[ x1...x4 ] |
61 |
|
* |
62 |
|
* trigger : P( f( x1 ), f( x2 ), f( x3 ), f( x4 ) ) |
63 |
|
* |
64 |
|
* ground context : ~P( a, a, a, a ), a = f( c_1 ) = ... = f( c_100 ) |
65 |
|
* |
66 |
|
* If E-matching were applied exhaustively, then x1, x2, x3, x4 would be |
67 |
|
* instantiated with all combinations of c_1, ... c_100, giving 100^4 |
68 |
|
* instantiations. |
69 |
|
* |
70 |
|
* Instead, we enforce that at most 1 instantiation is produced for a |
71 |
|
* ( pattern, ground term ) pair per round. Meaning, only one instantiation is |
72 |
|
* generated when matching P( a, a, a, a ) against the generator |
73 |
|
* [P( f( x1 ), f( x2 ), f( x3 ), f( x4 ) )]. For details, see Section 3 of |
74 |
|
* Reynolds, Vampire 2016. |
75 |
|
* |
76 |
|
* To enforce these policies, we use a flag "d_active_add" which dictates the |
77 |
|
* behavior of the last element in the linked list. If d_active_add is |
78 |
|
* true -> a call to getNextMatch(...) returns 1 only if adding the |
79 |
|
* instantiation via a call to IMGenerator::sendInstantiation(...) |
80 |
|
* successfully enqueues a lemma via a call to |
81 |
|
* Instantiate::addInstantiation(...). This call may fail e.g. if we |
82 |
|
* have already added the instantiation, or the instantiation is |
83 |
|
* entailed. |
84 |
|
* false -> a call to getNextMatch(...) returns 1 whenever an m is |
85 |
|
* constructed, where typically the caller would use m. |
86 |
|
* This is important since a return value >0 signals that the current matched |
87 |
|
* terms should be flushed. Consider the above example (EX1), where |
88 |
|
* [ f(y,f(x,a)) ] is being matched against f(b,c), |
89 |
|
* [ f(x,a) ] is being matched against f(d,a) where c=f(d,a) |
90 |
|
* A successfully added instantiation { x->d, y->b } here signals we should |
91 |
|
* not produce further instantiations that match f(y,f(x,a)) with f(b,c). |
92 |
|
* |
93 |
|
* A number of special cases of triggers are covered by this generator (see |
94 |
|
* implementation of initialize), including : |
95 |
|
* Literal triggers, e.g. x >= a, ~x = y |
96 |
|
* Selector triggers, e.g. head( x ) |
97 |
|
* Triggers with invertible subterms, e.g. f( x+1 ) |
98 |
|
* Variable triggers, e.g. x |
99 |
|
* |
100 |
|
* All triggers above can be in the context of an equality, e.g. |
101 |
|
* { f( y, f( x, a ) ) = b } is a trigger that matches f( y, f( x, a ) ) to |
102 |
|
* ground terms in the equivalence class of b. |
103 |
|
* { ~f( y, f( x, a ) ) = b } is a trigger that matches f( y, f( x, a ) ) to any |
104 |
|
* ground terms not in the equivalence class of b. |
105 |
|
*/ |
106 |
|
class InstMatchGenerator : public IMGenerator { |
107 |
|
public: |
108 |
|
/** destructor */ |
109 |
|
~InstMatchGenerator() override; |
110 |
|
|
111 |
|
/** Reset instantiation round. */ |
112 |
|
void resetInstantiationRound() override; |
113 |
|
/** Reset. */ |
114 |
|
bool reset(Node eqc) override; |
115 |
|
/** Get the next match. */ |
116 |
|
int getNextMatch(Node q, InstMatch& m) override; |
117 |
|
/** Add instantiations. */ |
118 |
|
uint64_t addInstantiations(Node q) override; |
119 |
|
|
120 |
|
/** set active add flag (true by default) |
121 |
|
* |
122 |
|
* If active add is true, we call sendInstantiation in calls to getNextMatch, |
123 |
|
* instead of returning the match. This is necessary so that we can ensure |
124 |
|
* policies that are dependent upon knowing when instantiations are |
125 |
|
* successfully added to the output channel through |
126 |
|
* Instantiate::addInstantiation(...). |
127 |
|
*/ |
128 |
|
void setActiveAdd(bool val); |
129 |
|
/** Get active score for this inst match generator |
130 |
|
* |
131 |
|
* See Trigger::getActiveScore for details. |
132 |
|
*/ |
133 |
|
int getActiveScore() override; |
134 |
|
/** exclude match |
135 |
|
* |
136 |
|
* Exclude matching d_match_pattern with Node n on subsequent calls to |
137 |
|
* getNextMatch. |
138 |
|
*/ |
139 |
7737 |
void excludeMatch(Node n) { d_curr_exclude_match[n] = true; } |
140 |
|
/** Get current match. |
141 |
|
* Returns the term we are currently matching. |
142 |
|
*/ |
143 |
7737 |
Node getCurrentMatch() { return d_curr_matched; } |
144 |
|
/** set that this match generator is independent |
145 |
|
* |
146 |
|
* A match generator is indepndent when this generator fails to produce a |
147 |
|
* match in a call to getNextMatch, the overall matching fails. |
148 |
|
*/ |
149 |
1266 |
void setIndependent() { d_independent_gen = true; } |
150 |
|
//-------------------------------construction of inst match generators |
151 |
|
/** mkInstMatchGenerator for single triggers, calls the method below */ |
152 |
|
static InstMatchGenerator* mkInstMatchGenerator(Trigger* tparent, |
153 |
|
Node q, |
154 |
|
Node pat); |
155 |
|
/** mkInstMatchGenerator for the multi trigger case |
156 |
|
* |
157 |
|
* This linked list of InstMatchGenerator classes with one |
158 |
|
* InstMatchGeneratorMultiLinear at the head and a list of trailing |
159 |
|
* InstMatchGenerators corresponding to each unique subterm of pats with |
160 |
|
* free variables. |
161 |
|
*/ |
162 |
|
static InstMatchGenerator* mkInstMatchGeneratorMulti(Trigger* tparent, |
163 |
|
Node q, |
164 |
|
std::vector<Node>& pats); |
165 |
|
/** mkInstMatchGenerator |
166 |
|
* |
167 |
|
* This generates a linked list of InstMatchGenerators for each unique |
168 |
|
* subterm of pats with free variables. |
169 |
|
* |
170 |
|
* q is the quantified formula associated with the generator we are making |
171 |
|
* pats is a set of terms we are making InstMatchGenerator nodes for |
172 |
|
* qe is a pointer to the quantifiers engine (used for querying necessary |
173 |
|
* information during initialization) pat_map_init maps from terms to |
174 |
|
* generators we have already made for them. |
175 |
|
* |
176 |
|
* It calls initialize(...) for all InstMatchGenerators generated by this call. |
177 |
|
*/ |
178 |
|
static InstMatchGenerator* mkInstMatchGenerator( |
179 |
|
Trigger* tparent, |
180 |
|
Node q, |
181 |
|
std::vector<Node>& pats, |
182 |
|
std::map<Node, InstMatchGenerator*>& pat_map_init); |
183 |
|
//-------------------------------end construction of inst match generators |
184 |
|
|
185 |
|
protected: |
186 |
|
/** constructors |
187 |
|
* |
188 |
|
* These are intentionally private, and are called during linked list |
189 |
|
* construction in mkInstMatchGenerator. |
190 |
|
*/ |
191 |
|
InstMatchGenerator(Trigger* tparent, Node pat); |
192 |
|
/** The pattern we are producing matches for. |
193 |
|
* |
194 |
|
* This term and d_match_pattern can be different since this |
195 |
|
* term may involve information regarding phase and (dis)equality entailment, |
196 |
|
* or other special cases of Triggers. |
197 |
|
* |
198 |
|
* For example, for the trigger for P( x ) = false, which matches P( x ) with |
199 |
|
* P( t ) in the equivalence class of false, |
200 |
|
* P( x ) = false is d_pattern |
201 |
|
* P( x ) is d_match_pattern |
202 |
|
* Another example, for pure theory triggers like head( x ), we have |
203 |
|
* head( x ) is d_pattern |
204 |
|
* x is d_match_pattern |
205 |
|
* since head( x ) can match any (List) datatype term x. |
206 |
|
* |
207 |
|
* If null, this is a multi trigger that is merging matches from d_children, |
208 |
|
* which is used in InstMatchGeneratorMulti. |
209 |
|
*/ |
210 |
|
Node d_pattern; |
211 |
|
/** The match pattern |
212 |
|
* This is the term that is matched against ground terms, |
213 |
|
* see examples above. |
214 |
|
*/ |
215 |
|
Node d_match_pattern; |
216 |
|
/** The current term we are matching. */ |
217 |
|
Node d_curr_matched; |
218 |
|
/** do we need to call reset on this generator? */ |
219 |
|
bool d_needsReset; |
220 |
|
/** candidate generator |
221 |
|
* This is the back-end utility for InstMatchGenerator. |
222 |
|
* It generates a stream of candidate terms to match against d_match_pattern |
223 |
|
* below, dependending upon what kind of term we are matching |
224 |
|
* (e.g. a matchable term, a variable, a relation, etc.). |
225 |
|
*/ |
226 |
|
CandidateGenerator* d_cg; |
227 |
|
/** children generators |
228 |
|
* These match generators correspond to the children of the term |
229 |
|
* we are matching with this generator. |
230 |
|
* For example [ f( x, a ) ] is a child of [ f( y, f( x, a ) ) ] |
231 |
|
* in the example (EX1) above. |
232 |
|
*/ |
233 |
|
std::vector<InstMatchGenerator*> d_children; |
234 |
|
/** for each child, the index in the term |
235 |
|
* For example [ f( x, a ) ] has index 1 in [ f( y, f( x, a ) ) ] |
236 |
|
* in the example (EX1) above, indicating it is the 2nd child |
237 |
|
* of the term. |
238 |
|
*/ |
239 |
|
std::vector<size_t> d_children_index; |
240 |
|
/** children types |
241 |
|
* |
242 |
|
* If d_match_pattern is an instantiation constant, then this is a singleton |
243 |
|
* vector containing the variable number of the d_match_pattern itself. |
244 |
|
* If d_match_patterm is a term of the form f( t1, ..., tn ), then for each |
245 |
|
* index i, d_children[i] stores the type of node ti is, where: |
246 |
|
* >= 0 : variable (indicates its number), |
247 |
|
* -1 : ground term, |
248 |
|
* -2 : child term. |
249 |
|
*/ |
250 |
|
std::vector<int64_t> d_children_types; |
251 |
|
/** The next generator in the linked list |
252 |
|
* that this generator is a part of. |
253 |
|
*/ |
254 |
|
InstMatchGenerator* d_next; |
255 |
|
/** The equivalence class we are currently matching in. */ |
256 |
|
Node d_eq_class; |
257 |
|
/** If non-null, then this is a relational trigger of the form x ~ |
258 |
|
* d_eq_class_rel. */ |
259 |
|
Node d_eq_class_rel; |
260 |
|
/** Excluded matches |
261 |
|
* Stores the terms we are not allowed to match. |
262 |
|
* These can for instance be specified by the smt2 |
263 |
|
* extended syntax (! ... :no-pattern). |
264 |
|
*/ |
265 |
|
std::map<Node, bool> d_curr_exclude_match; |
266 |
|
/** Current first candidate |
267 |
|
* Used in a key fail-quickly optimization which generates |
268 |
|
* the first candidate term to match during reset(). |
269 |
|
*/ |
270 |
|
Node d_curr_first_candidate; |
271 |
|
/** Indepdendent generate |
272 |
|
* If this flag is true, failures to match should be cached. |
273 |
|
*/ |
274 |
|
bool d_independent_gen; |
275 |
|
/** active add flag, described above. */ |
276 |
|
bool d_active_add; |
277 |
|
/** cached value of d_match_pattern.getType() */ |
278 |
|
TypeNode d_match_pattern_type; |
279 |
|
/** the match operator for d_match_pattern |
280 |
|
* |
281 |
|
* See TermDatabase::getMatchOperator for details on match operators. |
282 |
|
*/ |
283 |
|
Node d_match_pattern_op; |
284 |
|
/** get the match against ground term or formula t. |
285 |
|
* |
286 |
|
* d_match_pattern and t should have the same shape, that is, |
287 |
|
* their match operator (see TermDatabase::getMatchOperator) is the same. |
288 |
|
* only valid for use where !d_match_pattern.isNull(). |
289 |
|
*/ |
290 |
|
int getMatch(Node q, Node t, InstMatch& m); |
291 |
|
/** Initialize this generator. |
292 |
|
* |
293 |
|
* q is the quantified formula associated with this generator. |
294 |
|
* |
295 |
|
* This constructs the appropriate information about what |
296 |
|
* patterns we are matching and children generators. |
297 |
|
* |
298 |
|
* It may construct new (child) generators needed to implement |
299 |
|
* the matching algorithm for this term. For each new generator |
300 |
|
* constructed in this way, it adds them to gens. |
301 |
|
*/ |
302 |
|
void initialize(Node q, |
303 |
|
std::vector<InstMatchGenerator*>& gens); |
304 |
|
/** Continue next match |
305 |
|
* |
306 |
|
* This is called during getNextMatch when the current generator in the linked |
307 |
|
* list succesfully satisfies its matching constraint. This function either |
308 |
|
* calls getNextMatch of the next element in the linked list, or finalizes the |
309 |
|
* match (calling sendInstantiation(...) if active add is true, or returning a |
310 |
|
* value >0 if active add is false). Its return value has the same semantics |
311 |
|
* as getNextMatch. |
312 |
|
*/ |
313 |
|
int continueNextMatch(Node q, |
314 |
|
InstMatch& m, |
315 |
|
InferenceId id); |
316 |
|
/** Get inst match generator |
317 |
|
* |
318 |
|
* Gets the InstMatchGenerator that implements the |
319 |
|
* appropriate matching algorithm for n within q |
320 |
|
* within a linked list of InstMatchGenerators. |
321 |
|
*/ |
322 |
|
static InstMatchGenerator* getInstMatchGenerator(Trigger* tparent, |
323 |
|
Node q, |
324 |
|
Node n); |
325 |
|
};/* class InstMatchGenerator */ |
326 |
|
|
327 |
|
} // namespace inst |
328 |
|
} |
329 |
|
} |
330 |
|
} // namespace cvc5 |
331 |
|
|
332 |
|
#endif |