GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/ematching/inst_match_generator.h Lines: 3 3 100.0 %
Date: 2021-05-22 Branches: 0 0 0.0 %

Line Exec Source
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