summaryrefslogtreecommitdiff
path: root/src/theory/quantifiers/instantiate.h
blob: 2fdb494e97c533b06d239326a491c3cc3fed7eba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
/*********************                                                        */
/*! \file instantiate.h
 ** \verbatim
 ** Top contributors (to current version):
 **   Andrew Reynolds, Mathias Preiner, Morgan Deters
 ** This file is part of the CVC4 project.
 ** Copyright (c) 2009-2019 by the authors listed in the file AUTHORS
 ** in the top-level source directory) and their institutional affiliations.
 ** All rights reserved.  See the file COPYING in the top-level source
 ** directory for licensing information.\endverbatim
 **
 ** \brief instantiate
 **/

#include "cvc4_private.h"

#ifndef CVC4__THEORY__QUANTIFIERS__INSTANTIATE_H
#define CVC4__THEORY__QUANTIFIERS__INSTANTIATE_H

#include <map>

#include "expr/node.h"
#include "theory/quantifiers/inst_match_trie.h"
#include "theory/quantifiers/quant_util.h"
#include "theory/quantifiers_engine.h"
#include "util/statistics_registry.h"

namespace CVC4 {
namespace theory {
namespace quantifiers {

class TermDb;
class TermUtil;

/** instantiation notify
 *
 * This class is a listener for all instantiations generated with quantifiers.
 * By default, no notify classes are used. For an example of an instantiation
 * notify class, see quantifiers/inst_propagate.h, which has a notify class
 * that recognizes when the set of enqueued instantiations form a conflict.
 */
class InstantiationNotify
{
 public:
  InstantiationNotify() {}
  virtual ~InstantiationNotify() {}
  /** notify instantiation
   *
   * This is called when an instantiation of quantified formula q is
   * instantiated by a substitution whose range is terms at quantifier effort
   * quant_e. Furthermore:
   *   body is the substituted, preprocessed body of the quantified formula,
   *   lem is the instantiation lemma ( ~q V body ) after rewriting.
   */
  virtual bool notifyInstantiation(QuantifiersModule::QEffort quant_e,
                                   Node q,
                                   Node lem,
                                   std::vector<Node>& terms,
                                   Node body) = 0;
  /** filter instantiations
   *
   * This is called just before the quantifiers engine flushes its lemmas to the
   * output channel. During this call, the instantiation notify object may
   * call, e.g. QuantifiersEngine::getInstantiate()->removeInstantiation
   * to remove instantiations that should not be sent on the output channel.
   */
  virtual void filterInstantiations() = 0;
};

/** Instantiate
 *
 * This class is used for generating instantiation lemmas.  It maintains an
 * instantiation trie, which is represented by a different data structure
 * depending on whether incremental solving is enabled (see d_inst_match_trie
 * and d_c_inst_match_trie).
 *
 * Below, we say an instantiation lemma for q = forall x. F under substitution
 * { x -> t } is the formula:
 *   ( ~forall x. F V F * { x -> t } )
 * where * is application of substitution.
 *
 * Its main interface is ::addInstantiation(...), which is called by many of
 * the quantifiers modules, which enqueues instantiation lemmas in quantifiers
 * engine via calls to QuantifiersEngine::addLemma.
 *
 * It also has utilities for constructing instantiations, and interfaces for
 * getting the results of the instantiations produced during check-sat calls.
 */
class Instantiate : public QuantifiersUtil
{
 public:
  Instantiate(QuantifiersEngine* qe, context::UserContext* u);
  ~Instantiate();

  /** reset */
  bool reset(Theory::Effort e) override;
  /** register quantifier */
  void registerQuantifier(Node q) override;
  /** identify */
  std::string identify() const override { return "Instantiate"; }
  /** check incomplete */
  bool checkComplete() override;

  //--------------------------------------notify objects
  /** add instantiation notify
   *
   * Adds an instantiation notify class to listen to the instantiations reported
   * to this class.
   */
  void addNotify(InstantiationNotify* in);
  /** get number of instantiation notify added to this class */
  bool hasNotify() const { return !d_inst_notify.empty(); }
  /** notify flush lemmas
   *
   * This is called just before the quantifiers engine flushes its lemmas to
   * the output channel.
   */
  void notifyFlushLemmas();
  //--------------------------------------end notify objects

  /** do instantiation specified by m
   *
   * This function returns true if the instantiation lemma for quantified
   * formula q for the substitution specified by m is successfully enqueued
   * via a call to QuantifiersEngine::addLemma.
   *   mkRep : whether to take the representatives of the terms in the range of
   *           the substitution m,
   *   modEq : whether to check for duplication modulo equality in instantiation
   *           tries (for performance),
   *   doVts : whether we must apply virtual term substitution to the
   *           instantiation lemma.
   *
   * This call may fail if it can be determined that the instantiation is not
   * relevant or legal in the current context. This happens if:
   * (1) The substitution is not well-typed,
   * (2) The substitution involves terms whose instantiation level is above the
   *     allowed limit,
   * (3) The resulting instantiation is entailed in the current context using a
   *     fast entailment check (see TermDb::isEntailed),
   * (4) The range of the substitution is a duplicate of that of a previously
   *     added instantiation,
   * (5) The instantiation lemma is a duplicate of previously added lemma.
   *
   */
  bool addInstantiation(Node q,
                        InstMatch& m,
                        bool mkRep = false,
                        bool modEq = false,
                        bool doVts = false);
  /** add instantiation
   *
   * Same as above, but the substitution we are considering maps the variables
   * of q to the vector terms, in order.
   */
  bool addInstantiation(Node q,
                        std::vector<Node>& terms,
                        bool mkRep = false,
                        bool modEq = false,
                        bool doVts = false);
  /** remove pending instantiation
   *
   * Removes the instantiation lemma lem from the instantiation trie.
   */
  bool removeInstantiation(Node q, Node lem, std::vector<Node>& terms);
  /** record instantiation
   *
   * Explicitly record that q has been instantiated with terms. This is the
   * same as addInstantiation, but does not enqueue an instantiation lemma.
   */
  bool recordInstantiation(Node q,
                           std::vector<Node>& terms,
                           bool modEq = false,
                           bool addedLem = true);
  /** exists instantiation
   *
   * Returns true if and only if the instantiation already was added or
   * recorded by this class.
   *   modEq : whether to check for duplication modulo equality
   */
  bool existsInstantiation(Node q,
                           std::vector<Node>& terms,
                           bool modEq = false);
  //--------------------------------------general utilities
  /** get instantiation
   *
   * Returns the instantiation lemma for q under substitution { vars -> terms }.
   * doVts is whether to apply virtual term substitution to its body.
   */
  Node getInstantiation(Node q,
                        std::vector<Node>& vars,
                        std::vector<Node>& terms,
                        bool doVts = false);
  /** get instantiation
   *
   * Same as above, but with vars/terms specified by InstMatch m.
   */
  Node getInstantiation(Node q, InstMatch& m, bool doVts = false);
  /** get instantiation
   *
   * Same as above but with vars equal to the bound variables of q.
   */
  Node getInstantiation(Node q, std::vector<Node>& terms, bool doVts = false);
  /** get term for type
   *
   * This returns an arbitrary term for type tn.
   * This term is chosen heuristically to be the best
   * term for instantiation. Currently, this
   * heuristic enumerates the first term of the
   * type if the type is closed enumerable, otherwise
   * an existing ground term from the term database if
   * one exists, or otherwise a fresh variable.
   */
  Node getTermForType(TypeNode tn);
  //--------------------------------------end general utilities

  /** debug print, called once per instantiation round. */
  void debugPrint();
  /** debug print model, called once, before we terminate with sat/unknown. */
  void debugPrintModel();

  //--------------------------------------user-level interface utilities
  /** print instantiations
   *
   * Print all instantiations for all quantified formulas on out,
   * returns true if at least one instantiation was printed.
   */
  bool printInstantiations(std::ostream& out);
  /** get instantiated quantified formulas
   *
   * Get the list of quantified formulas that were instantiated in the current
   * user context, store them in qs.
   */
  void getInstantiatedQuantifiedFormulas(std::vector<Node>& qs);
  /** get instantiations
   *
   * Get the body of all instantiation lemmas added in the current user context
   * for quantified formula q, store them in insts.
   */
  void getInstantiations(Node q, std::vector<Node>& insts);
  /** get instantiations
   *
   * Get the body of all instantiation lemmas added in the current user context
   * for all quantified formulas stored in the domain of insts, store them in
   * the range of insts.
   */
  void getInstantiations(std::map<Node, std::vector<Node> >& insts);
  /** get instantiation term vectors
   *
   * Get term vectors corresponding to for all instantiations lemmas added in
   * the current user context for quantified formula q, store them in tvecs.
   */
  void getInstantiationTermVectors(Node q,
                                   std::vector<std::vector<Node> >& tvecs);
  /** get instantiation term vectors
   *
   * Get term vectors for all instantiations lemmas added in the current user
   * context for quantified formula q, store them in tvecs.
   */
  void getInstantiationTermVectors(
      std::map<Node, std::vector<std::vector<Node> > >& insts);
  /** get instantiated conjunction
   *
   * This gets a conjunction of the bodies of instantiation lemmas added in the
   * current user context for quantified formula q.  For example, if we added:
   *   ~forall x. P( x ) V P( a )
   *   ~forall x. P( x ) V P( b )
   * Then, this method returns P( a ) ^ P( b ).
   */
  Node getInstantiatedConjunction(Node q);
  /** get unsat core lemmas
   *
   * If this method returns true, then it appends to active_lemmas all lemmas
   * that are in the unsat core that originated from the theory of quantifiers.
   * This method returns false if the unsat core is not available.
   */
  bool getUnsatCoreLemmas(std::vector<Node>& active_lemmas);
  /** get unsat core lemmas
   *
   * If this method returns true, then it appends to active_lemmas all lemmas
   * that are in the unsat core that originated from the theory of quantifiers.
   * This method returns false if the unsat core is not available.
   *
   * It also computes a weak implicant for each of these lemmas. For each lemma
   * L in active_lemmas, this is a formula L' such that:
   *   L => L'
   * and replacing L by L' in the unsat core results in a set that is still
   * unsatisfiable. The map weak_imp stores this formula for each formula in
   * active_lemmas.
   */
  bool getUnsatCoreLemmas(std::vector<Node>& active_lemmas,
                          std::map<Node, Node>& weak_imp);
  /** get explanation for instantiation lemmas
   *
   *
   */
  void getExplanationForInstLemmas(const std::vector<Node>& lems,
                                   std::map<Node, Node>& quant,
                                   std::map<Node, std::vector<Node> >& tvec);
  //--------------------------------------end user-level interface utilities

  /** statistics class
   *
   * This tracks statistics on the number of instantiations successfully
   * enqueued on the quantifiers output channel, and the number of redundant
   * instantiations encountered by various criteria.
   */
  class Statistics
  {
   public:
    IntStat d_instantiations;
    IntStat d_inst_duplicate;
    IntStat d_inst_duplicate_eq;
    IntStat d_inst_duplicate_ent;
    IntStat d_inst_duplicate_model_true;
    Statistics();
    ~Statistics();
  }; /* class Instantiate::Statistics */
  Statistics d_statistics;

 private:
  /** record instantiation, return true if it was not a duplicate
   *
   * addedLem : whether an instantiation lemma was added for the vector we are
   *            recording. If this is false, we bookkeep the vector.
   * modEq : whether to check for duplication modulo equality in instantiation
   *         tries (for performance),
   */
  bool recordInstantiationInternal(Node q,
                                   std::vector<Node>& terms,
                                   bool modEq = false,
                                   bool addedLem = true);
  /** remove instantiation from the cache */
  bool removeInstantiationInternal(Node q, std::vector<Node>& terms);

  /** pointer to the quantifiers engine */
  QuantifiersEngine* d_qe;
  /** cache of term database for quantifiers engine */
  TermDb* d_term_db;
  /** cache of term util for quantifiers engine */
  TermUtil* d_term_util;
  /** instantiation notify classes */
  std::vector<InstantiationNotify*> d_inst_notify;

  /** statistics for debugging total instantiation */
  int d_total_inst_count_debug;
  /** statistics for debugging total instantiations per quantifier */
  std::map<Node, int> d_total_inst_debug;
  /** statistics for debugging total instantiations per quantifier per round */
  std::map<Node, int> d_temp_inst_debug;

  /** list of all instantiations produced for each quantifier
   *
   * We store context (dependent, independent) versions. If incremental solving
   * is disabled, we use d_inst_match_trie for performance reasons.
   */
  std::map<Node, inst::InstMatchTrie> d_inst_match_trie;
  std::map<Node, inst::CDInstMatchTrie*> d_c_inst_match_trie;
  /**
   * The list of quantified formulas for which the domain of d_c_inst_match_trie
   * is valid.
   */
  context::CDHashSet<Node, NodeHashFunction> d_c_inst_match_trie_dom;

  /** explicitly recorded instantiations
   *
   * Sometimes an instantiation is recorded internally but not sent out as a
   * lemma, for instance, for partial quantifier elimination. This is a map
   * of these instantiations, for each quantified formula.
   */
  std::vector<std::pair<Node, std::vector<Node> > > d_recorded_inst;
};

} /* CVC4::theory::quantifiers namespace */
} /* CVC4::theory namespace */
} /* CVC4 namespace */

#endif /* CVC4__THEORY__QUANTIFIERS__INSTANTIATE_H */
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback