GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/instantiate.h Lines: 5 5 100.0 %
Date: 2021-05-22 Branches: 2 4 50.0 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Mathias Preiner, 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
 * instantiate
14
 */
15
16
#include "cvc5_private.h"
17
18
#ifndef CVC5__THEORY__QUANTIFIERS__INSTANTIATE_H
19
#define CVC5__THEORY__QUANTIFIERS__INSTANTIATE_H
20
21
#include <map>
22
23
#include "context/cdhashset.h"
24
#include "expr/node.h"
25
#include "expr/proof.h"
26
#include "theory/inference_id.h"
27
#include "theory/quantifiers/inst_match_trie.h"
28
#include "theory/quantifiers/quant_util.h"
29
#include "util/statistics_stats.h"
30
31
namespace cvc5 {
32
33
class LazyCDProof;
34
35
namespace theory {
36
namespace quantifiers {
37
38
class TermRegistry;
39
class QuantifiersState;
40
class QuantifiersInferenceManager;
41
class QuantifiersRegistry;
42
class FirstOrderModel;
43
44
/** Instantiation rewriter
45
 *
46
 * This class is used for cases where instantiation lemmas can be rewritten by
47
 * external utilities. Examples of this include virtual term substitution and
48
 * nested quantifier elimination techniques.
49
 */
50
class InstantiationRewriter
51
{
52
 public:
53
6323
  InstantiationRewriter() {}
54
6323
  virtual ~InstantiationRewriter() {}
55
56
  /** rewrite instantiation
57
   *
58
   * The node inst is the instantiation of quantified formula q for terms.
59
   * This method returns the rewritten form of the instantiation.
60
   *
61
   * The flag doVts is whether we must apply virtual term substitution to the
62
   * instantiation.
63
   *
64
   * Returns a TrustNode of kind REWRITE, corresponding to the rewrite of inst
65
   * and its proof generator.
66
   */
67
  virtual TrustNode rewriteInstantiation(Node q,
68
                                         std::vector<Node>& terms,
69
                                         Node inst,
70
                                         bool doVts) = 0;
71
};
72
73
/** Context-dependent list of nodes */
74
5897
class InstLemmaList
75
{
76
 public:
77
5897
  InstLemmaList(context::Context* c) : d_list(c) {}
78
  /** The list */
79
  context::CDList<Node> d_list;
80
};
81
82
/** Instantiate
83
 *
84
 * This class is used for generating instantiation lemmas.  It maintains an
85
 * instantiation trie, which is represented by a different data structure
86
 * depending on whether incremental solving is enabled (see d_inst_match_trie
87
 * and d_c_inst_match_trie).
88
 *
89
 * Below, we say an instantiation lemma for q = forall x. F under substitution
90
 * { x -> t } is the formula:
91
 *   ( ~forall x. F V F * { x -> t } )
92
 * where * is application of substitution.
93
 *
94
 * Its main interface is ::addInstantiation(...), which is called by many of
95
 * the quantifiers modules, which enqueues instantiation lemmas in quantifiers
96
 * engine via calls to QuantifiersInferenceManager::addPendingLemma.
97
 *
98
 * It also has utilities for constructing instantiations, and interfaces for
99
 * getting the results of the instantiations produced during check-sat calls.
100
 */
101
class Instantiate : public QuantifiersUtil
102
{
103
  using NodeInstListMap =
104
      context::CDHashMap<Node, std::shared_ptr<InstLemmaList>>;
105
106
 public:
107
  Instantiate(QuantifiersState& qs,
108
              QuantifiersInferenceManager& qim,
109
              QuantifiersRegistry& qr,
110
              TermRegistry& tr,
111
              ProofNodeManager* pnm = nullptr);
112
  ~Instantiate();
113
114
  /** reset */
115
  bool reset(Theory::Effort e) override;
116
  /** register quantifier */
117
  void registerQuantifier(Node q) override;
118
  /** identify */
119
24826
  std::string identify() const override { return "Instantiate"; }
120
  /** check incomplete */
121
  bool checkComplete(IncompleteId& incId) override;
122
123
  //--------------------------------------rewrite objects
124
  /** add instantiation rewriter */
125
  void addRewriter(InstantiationRewriter* ir);
126
  /** notify flush lemmas
127
   *
128
   * This is called just before the quantifiers engine flushes its lemmas to
129
   * the output channel.
130
   */
131
  void notifyFlushLemmas();
132
  //--------------------------------------end rewrite objects
133
134
  /** do instantiation specified by m
135
   *
136
   * This function returns true if the instantiation lemma for quantified
137
   * formula q for the substitution specified by terms is successfully enqueued
138
   * via a call to QuantifiersInferenceManager::addPendingLemma.
139
   * @param q the quantified formula to instantiate
140
   * @param terms the terms to instantiate with
141
   * @param id the identifier of the instantiation lemma sent via the inference
142
   * manager
143
   * @param mkRep whether to take the representatives of the terms in the
144
   * range of the substitution m,
145
   * @param modEq whether to check for duplication modulo equality in
146
   * instantiation tries (for performance),
147
   * @param doVts whether we must apply virtual term substitution to the
148
   * instantiation lemma.
149
   *
150
   * This call may fail if it can be determined that the instantiation is not
151
   * relevant or legal in the current context. This happens if:
152
   * (1) The substitution is not well-typed,
153
   * (2) The substitution involves terms whose instantiation level is above the
154
   *     allowed limit,
155
   * (3) The resulting instantiation is entailed in the current context using a
156
   *     fast entailment check (see TermDb::isEntailed),
157
   * (4) The range of the substitution is a duplicate of that of a previously
158
   *     added instantiation,
159
   * (5) The instantiation lemma is a duplicate of previously added lemma.
160
   *
161
   */
162
  bool addInstantiation(Node q,
163
                        std::vector<Node>& terms,
164
                        InferenceId id,
165
                        bool mkRep = false,
166
                        bool modEq = false,
167
                        bool doVts = false);
168
  /**
169
   * Same as above, but we also compute a vector failMask indicating which
170
   * values in terms led to the instantiation not being added when this method
171
   * returns false.  For example, if q is the formula
172
   *   forall xy. x>5 => P(x,y)
173
   * If terms = { 4, 0 }, then this method will return false since
174
   *   4>5 => P(4,0)
175
   * is entailed true based on rewriting. This method may additionally set
176
   * failMask to "10", indicating that x's value was critical, but y's value
177
   * was not. In other words, all instantiations including { x -> 4 } will also
178
   * lead to this method returning false.
179
   *
180
   * The bits of failMask are computed in a greedy fashion, in reverse order.
181
   * That is, we check whether each variable is critical one at a time, starting
182
   * from the end.
183
   *
184
   * The parameter expFull is whether try to set all bits of the fail mask to
185
   * 0. If this argument is true, then we only try to set a suffix of the
186
   * bits in failMask to false. The motivation for expFull=false is for callers
187
   * of this method that are enumerating tuples in lexiocographic order. The
188
   * number of false bits in the suffix of failMask tells the caller how many
189
   * "decimal" places to increment their iterator.
190
   */
191
  bool addInstantiationExpFail(Node q,
192
                               std::vector<Node>& terms,
193
                               std::vector<bool>& failMask,
194
                               InferenceId id,
195
                               bool mkRep = false,
196
                               bool modEq = false,
197
                               bool doVts = false,
198
                               bool expFull = true);
199
  /** record instantiation
200
   *
201
   * Explicitly record that q has been instantiated with terms, with virtual
202
   * term substitution if doVts is true. This is the same as addInstantiation,
203
   * but does not enqueue an instantiation lemma.
204
   */
205
  void recordInstantiation(Node q,
206
                           std::vector<Node>& terms,
207
                           bool doVts = false);
208
  /** exists instantiation
209
   *
210
   * Returns true if and only if the instantiation already was added or
211
   * recorded by this class.
212
   *   modEq : whether to check for duplication modulo equality
213
   */
214
  bool existsInstantiation(Node q,
215
                           std::vector<Node>& terms,
216
                           bool modEq = false);
217
  //--------------------------------------general utilities
218
  /** get instantiation
219
   *
220
   * Returns the instantiation lemma for q under substitution { vars -> terms }.
221
   * doVts is whether to apply virtual term substitution to its body.
222
   *
223
   * If provided, pf is a lazy proof for which we store a proof of the
224
   * returned formula with free assumption q. This typically stores a
225
   * single INSTANTIATE step concluding the instantiated body of q from q.
226
   */
227
  Node getInstantiation(Node q,
228
                        std::vector<Node>& vars,
229
                        std::vector<Node>& terms,
230
                        bool doVts = false,
231
                        LazyCDProof* pf = nullptr);
232
  /** get instantiation
233
   *
234
   * Same as above but with vars equal to the bound variables of q.
235
   */
236
  Node getInstantiation(Node q, std::vector<Node>& terms, bool doVts = false);
237
  //--------------------------------------end general utilities
238
239
  /**
240
   * Debug print, called once per instantiation round. This prints
241
   * instantiations added this round to trace inst-per-quant-round, if
242
   * applicable, and prints to out if the option debug-inst is enabled.
243
   */
244
  void debugPrint(std::ostream& out);
245
  /** debug print model, called once, before we terminate with sat/unknown. */
246
  void debugPrintModel();
247
248
  //--------------------------------------user-level interface utilities
249
  /** get instantiated quantified formulas
250
   *
251
   * Get the list of quantified formulas that were instantiated in the current
252
   * user context, store them in qs.
253
   */
254
  void getInstantiatedQuantifiedFormulas(std::vector<Node>& qs) const;
255
  /** get instantiation term vectors
256
   *
257
   * Get term vectors corresponding to for all instantiations lemmas added in
258
   * the current user context for quantified formula q, store them in tvecs.
259
   */
260
  void getInstantiationTermVectors(Node q,
261
                                   std::vector<std::vector<Node> >& tvecs);
262
  /** get instantiation term vectors
263
   *
264
   * Get term vectors for all instantiations lemmas added in the current user
265
   * context for quantified formula q, store them in tvecs.
266
   */
267
  void getInstantiationTermVectors(
268
      std::map<Node, std::vector<std::vector<Node> > >& insts);
269
  /**
270
   * Get instantiations for quantified formula q. If q is (forall ((x T)) (P
271
   * x)), this is a list of the form (P t1) ... (P tn) for ground terms ti.
272
   */
273
  void getInstantiations(Node q, std::vector<Node>& insts);
274
  //--------------------------------------end user-level interface utilities
275
276
  /** Are proofs enabled for this object? */
277
  bool isProofEnabled() const;
278
279
  /** statistics class
280
   *
281
   * This tracks statistics on the number of instantiations successfully
282
   * enqueued on the quantifiers output channel, and the number of redundant
283
   * instantiations encountered by various criteria.
284
   */
285
  class Statistics
286
  {
287
   public:
288
    IntStat d_instantiations;
289
    IntStat d_inst_duplicate;
290
    IntStat d_inst_duplicate_eq;
291
    IntStat d_inst_duplicate_ent;
292
    Statistics();
293
  }; /* class Instantiate::Statistics */
294
  Statistics d_statistics;
295
296
 private:
297
  /** record instantiation, return true if it was not a duplicate
298
   *
299
   * modEq : whether to check for duplication modulo equality in instantiation
300
   *         tries (for performance),
301
   */
302
  bool recordInstantiationInternal(Node q,
303
                                   std::vector<Node>& terms,
304
                                   bool modEq = false);
305
  /** remove instantiation from the cache */
306
  bool removeInstantiationInternal(Node q, std::vector<Node>& terms);
307
  /**
308
   * Ensure that n has type tn, return a term equivalent to it for that type
309
   * if possible.
310
   */
311
  static Node ensureType(Node n, TypeNode tn);
312
  /** Get or make the instantiation list for quantified formula q */
313
  InstLemmaList* getOrMkInstLemmaList(TNode q);
314
315
  /** Reference to the quantifiers state */
316
  QuantifiersState& d_qstate;
317
  /** Reference to the quantifiers inference manager */
318
  QuantifiersInferenceManager& d_qim;
319
  /** The quantifiers registry */
320
  QuantifiersRegistry& d_qreg;
321
  /** Reference to the term registry */
322
  TermRegistry& d_treg;
323
  /** pointer to the proof node manager */
324
  ProofNodeManager* d_pnm;
325
  /** instantiation rewriter classes */
326
  std::vector<InstantiationRewriter*> d_instRewrite;
327
328
  /**
329
   * The list of all instantiation lemma bodies per quantifier. This is used
330
   * for debugging and for quantifier elimination.
331
   */
332
  NodeInstListMap d_insts;
333
  /** explicitly recorded instantiations
334
   *
335
   * Sometimes an instantiation is recorded internally but not sent out as a
336
   * lemma, for instance, for partial quantifier elimination. This is a map
337
   * of these instantiations, for each quantified formula. This map is cleared
338
   * on presolve, e.g. it is local to a check-sat call.
339
   */
340
  std::map<Node, std::vector<Node> > d_recordedInst;
341
  /** statistics for debugging total instantiations per quantifier per round */
342
  std::map<Node, uint32_t> d_temp_inst_debug;
343
344
  /** list of all instantiations produced for each quantifier
345
   *
346
   * We store context (dependent, independent) versions. If incremental solving
347
   * is disabled, we use d_inst_match_trie for performance reasons.
348
   */
349
  std::map<Node, InstMatchTrie> d_inst_match_trie;
350
  std::map<Node, CDInstMatchTrie*> d_c_inst_match_trie;
351
  /**
352
   * The list of quantified formulas for which the domain of d_c_inst_match_trie
353
   * is valid.
354
   */
355
  context::CDHashSet<Node> d_c_inst_match_trie_dom;
356
  /**
357
   * A CDProof storing instantiation steps.
358
   */
359
  std::unique_ptr<CDProof> d_pfInst;
360
};
361
362
}  // namespace quantifiers
363
}  // namespace theory
364
}  // namespace cvc5
365
366
#endif /* CVC5__THEORY__QUANTIFIERS__INSTANTIATE_H */