GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/term_database.h Lines: 3 3 100.0 %
Date: 2021-11-07 Branches: 2 4 50.0 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Mathias Preiner
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
 * Term database class.
14
 */
15
16
#include "cvc5_private.h"
17
18
#ifndef CVC5__THEORY__QUANTIFIERS__TERM_DATABASE_H
19
#define CVC5__THEORY__QUANTIFIERS__TERM_DATABASE_H
20
21
#include <map>
22
#include <unordered_map>
23
24
#include "context/cdhashmap.h"
25
#include "context/cdhashset.h"
26
#include "expr/attribute.h"
27
#include "expr/node_trie.h"
28
#include "theory/quantifiers/quant_util.h"
29
#include "theory/theory.h"
30
#include "theory/type_enumerator.h"
31
32
namespace cvc5 {
33
namespace theory {
34
namespace quantifiers {
35
36
class QuantifiersState;
37
class QuantifiersInferenceManager;
38
class QuantifiersRegistry;
39
40
/** Context-dependent list of nodes */
41
181609
class DbList
42
{
43
 public:
44
181609
  DbList(context::Context* c) : d_list(c) {}
45
  /** The list */
46
  context::CDList<Node> d_list;
47
};
48
49
/** Term Database
50
 *
51
 * This class is a key utility used by
52
 * a number of approaches for quantifier instantiation,
53
 * including E-matching, conflict-based instantiation,
54
 * and model-based instantiation.
55
 *
56
 * The primary responsibilities for this class are to :
57
 * (1) Maintain a list of all ground terms that exist in the quantifier-free
58
 *     solvers, as notified through the master equality engine.
59
 * (2) Build TNodeTrie objects that index all ground terms, per operator.
60
 *
61
 * Like other utilities, its reset(...) function is called
62
 * at the beginning of full or last call effort checks.
63
 * This initializes the database for the round. However,
64
 * notice that TNodeTrie objects are computed
65
 * lazily for performance reasons.
66
 */
67
class TermDb : public QuantifiersUtil {
68
  using NodeBoolMap = context::CDHashMap<Node, bool>;
69
  using NodeList = context::CDList<Node>;
70
  using NodeSet = context::CDHashSet<Node>;
71
  using TypeNodeDbListMap =
72
      context::CDHashMap<TypeNode, std::shared_ptr<DbList>>;
73
  using NodeDbListMap = context::CDHashMap<Node, std::shared_ptr<DbList>>;
74
75
 public:
76
  TermDb(Env& env, QuantifiersState& qs, QuantifiersRegistry& qr);
77
  virtual ~TermDb();
78
  /** Finish init, which sets the inference manager */
79
  void finishInit(QuantifiersInferenceManager* qim);
80
  /** presolve (called once per user check-sat) */
81
  void presolve() override;
82
  /** reset (calculate which terms are active) */
83
  bool reset(Theory::Effort effort) override;
84
  /** register quantified formula */
85
  void registerQuantifier(Node q) override;
86
  /** identify */
87
34025
  std::string identify() const override { return "TermDb"; }
88
  /** get number of operators */
89
  size_t getNumOperators() const;
90
  /** get operator at index i */
91
  Node getOperator(size_t i) const;
92
  /** ground terms for operator
93
  * Get the number of ground terms with operator f that have been added to the
94
  * database
95
  */
96
  size_t getNumGroundTerms(Node f) const;
97
  /** get ground term for operator
98
  * Get the i^th ground term with operator f that has been added to the database
99
  */
100
  Node getGroundTerm(Node f, size_t i) const;
101
  /** get num type terms
102
  * Get the number of ground terms of tn that have been added to the database
103
  */
104
  size_t getNumTypeGroundTerms(TypeNode tn) const;
105
  /** get type ground term
106
  * Returns the i^th ground term of type tn
107
  */
108
  Node getTypeGroundTerm(TypeNode tn, size_t i) const;
109
  /** get or make ground term
110
   *
111
   * Returns the first ground term of type tn, or makes one if none exist. If
112
   * reqVar is true, then the ground term must be a variable.
113
   */
114
  Node getOrMakeTypeGroundTerm(TypeNode tn, bool reqVar = false);
115
  /** make fresh variable
116
  * Returns a fresh variable of type tn.
117
  * This will return only a single fresh
118
  * variable per type.
119
  */
120
  Node getOrMakeTypeFreshVariable(TypeNode tn);
121
  /**
122
   * Add a term to the database, which registers it as a term that may be
123
   * matched with via E-matching, and can be used in entailment tests below.
124
   */
125
  void addTerm(Node n);
126
  /** Get the currently added ground terms of the given type */
127
  DbList* getOrMkDbListForType(TypeNode tn);
128
  /** Get the currently added ground terms for the given operator */
129
  DbList* getOrMkDbListForOp(TNode op);
130
  /** get match operator for term n
131
  *
132
  * If n has a kind that we index, this function will
133
  * typically return n.getOperator().
134
  *
135
  * However, for parametric operators f, the match operator is an arbitrary
136
  * chosen f-application.  For example, consider array select:
137
  * A : (Array Int Int)
138
  * B : (Array Bool Int)
139
  * We require that terms like (select A 1) and (select B 2) are indexed in
140
  * separate
141
  * data structures despite the fact that
142
  *    (select A 1).getOperator()==(select B 2).getOperator().
143
  * Hence, for the above terms, we may return:
144
  * getMatchOperator( (select A 1) ) = (select A 1), and
145
  * getMatchOperator( (select B 2) ) = (select B 2).
146
  * The match operator is the first instance of an application of the parametric
147
  * operator of its type.
148
  *
149
  * If n has a kind that we do not index (like PLUS),
150
  * then this function returns Node::null().
151
  */
152
  Node getMatchOperator(Node n);
153
  /** get term arg index for all f-applications in the current context */
154
  TNodeTrie* getTermArgTrie(Node f);
155
  /** get the term arg trie for f-applications in the equivalence class of eqc.
156
   */
157
  TNodeTrie* getTermArgTrie(Node eqc, Node f);
158
  /** get congruent term
159
  * If possible, returns a term t such that:
160
  * (1) t is a term that is currently indexed by this database,
161
  * (2) t is of the form f( t1, ..., tk ) and n is of the form f( s1, ..., sk ),
162
  *     where ti is in the equivalence class of si for i=1...k.
163
  */
164
  TNode getCongruentTerm(Node f, Node n);
165
  /** get congruent term
166
  * If possible, returns a term t such that:
167
  * (1) t is a term that is currently indexed by this database,
168
  * (2) t is of the form f( t1, ..., tk ) where ti is in the
169
  *     equivalence class of args[i] for i=1...k.
170
  */
171
  TNode getCongruentTerm(Node f, std::vector<TNode>& args);
172
  /** in relevant domain
173
  * Returns true if there is at least one term t such that:
174
  * (1) t is a term that is currently indexed by this database,
175
  * (2) t is of the form f( t1, ..., tk ) and ti is in the
176
  *     equivalence class of r.
177
  */
178
  bool inRelevantDomain(TNode f, unsigned i, TNode r);
179
  /** is the term n active in the current context?
180
   *
181
  * By default, all terms are active. A term is inactive if:
182
  * (1) it is congruent to another term
183
  * (2) it is irrelevant based on the term database mode. This includes terms
184
  * that only appear in literals that are not relevant.
185
  * (3) it contains instantiation constants (used for CEGQI and cannot be used
186
  * in instantiation).
187
  * (4) it is explicitly set inactive by a call to setTermInactive(...).
188
  * We store whether a term is inactive in a SAT-context-dependent map.
189
  */
190
  bool isTermActive(Node n);
191
  /** set that term n is inactive in this context. */
192
  void setTermInactive(Node n);
193
  /** has term current
194
   *
195
   * This function is used in cases where we restrict which terms appear in the
196
   * database, such as for heuristics used in local theory extensions
197
   * and for --term-db-mode=relevant.
198
   * It returns whether the term n should be indexed in the current context.
199
   *
200
   * If the argument useMode is true, then this method returns a value based on
201
   * the option options::termDbMode().
202
   * Otherwise, it returns the lookup in the map d_has_map.
203
   */
204
  bool hasTermCurrent(Node n, bool useMode = true);
205
  /** is term eligble for instantiation? */
206
  bool isTermEligibleForInstantiation(TNode n, TNode f);
207
  /** get eligible term in equivalence class of r */
208
  Node getEligibleTermInEqc(TNode r);
209
210
 protected:
211
  /** The quantifiers state object */
212
  QuantifiersState& d_qstate;
213
  /** Pointer to the quantifiers inference manager */
214
  QuantifiersInferenceManager* d_qim;
215
  /** The quantifiers registry */
216
  QuantifiersRegistry& d_qreg;
217
  /** A context for the data structures below, when not context-dependent */
218
  context::Context d_termsContext;
219
  /** The context we are using for the data structures below */
220
  context::Context* d_termsContextUse;
221
  /** terms processed */
222
  NodeSet d_processed;
223
  /** map from types to ground terms for that type */
224
  TypeNodeDbListMap d_typeMap;
225
  /** list of all operators */
226
  NodeList d_ops;
227
  /** map from operators to ground terms for that operator */
228
  NodeDbListMap d_opMap;
229
  /** select op map */
230
  std::map< Node, std::map< TypeNode, Node > > d_par_op_map;
231
  /** whether master equality engine is UF-inconsistent */
232
  bool d_consistent_ee;
233
  /** boolean terms */
234
  Node d_true;
235
  Node d_false;
236
  /** map from type nodes to a fresh variable we introduced */
237
  std::unordered_map<TypeNode, Node> d_type_fv;
238
  /** inactive map */
239
  NodeBoolMap d_inactive_map;
240
  /** count of the number of non-redundant ground terms per operator */
241
  std::map< Node, int > d_op_nonred_count;
242
  /** mapping from terms to representatives of their arguments */
243
  std::map< TNode, std::vector< TNode > > d_arg_reps;
244
  /** map from operators to trie */
245
  std::map<Node, TNodeTrie> d_func_map_trie;
246
  std::map<Node, TNodeTrie> d_func_map_eqc_trie;
247
  /** mapping from operators to their representative relevant domains */
248
  std::map< Node, std::map< unsigned, std::vector< Node > > > d_func_map_rel_dom;
249
  /** has map */
250
  std::map< Node, bool > d_has_map;
251
  /** map from reps to a term in eqc in d_has_map */
252
  std::map<Node, Node> d_term_elig_eqc;
253
  /**
254
   * Dummy predicate that states terms should be considered first-class members
255
   * of equality engine (for higher-order).
256
   */
257
  std::map<TypeNode, Node> d_ho_type_match_pred;
258
  //----------------------------- implementation-specific
259
  /**
260
   * Reset internal, called when reset(e) is called. Returning false will cause
261
   * the overall reset to terminate early, returning false.
262
   */
263
  virtual bool resetInternal(Theory::Effort e);
264
  /**
265
   * Finish reset internal, called at the end of reset(e). Returning false will
266
   * cause the overall reset to return false.
267
   */
268
  virtual bool finishResetInternal(Theory::Effort e);
269
  /** Add term internal, called when addTerm(n) is called */
270
  virtual void addTermInternal(Node n);
271
  /** Get operators that we know are equivalent to f, typically only f itself */
272
  virtual void getOperatorsFor(TNode f, std::vector<TNode>& ops);
273
  /** get the chosen representative for operator op */
274
  virtual Node getOperatorRepresentative(TNode op) const;
275
  /**
276
   * This method is called when terms a and b are indexed by the same operator,
277
   * and have equivalent arguments. This method checks if we are in conflict,
278
   * which is the case if a and b are disequal in the equality engine.
279
   * If so, it adds the set of literals that are implied but do not hold, e.g.
280
   * the equality (= a b).
281
   */
282
  virtual bool checkCongruentDisequal(TNode a, TNode b, std::vector<Node>& exp);
283
  //----------------------------- end implementation-specific
284
  /** set has term */
285
  void setHasTerm( Node n );
286
  /** compute uf eqc terms :
287
  * Ensure entries for f are in d_func_map_eqc_trie for all equivalence classes
288
  */
289
  void computeUfEqcTerms( TNode f );
290
  /** compute uf terms
291
  * Ensure that an entry for f is in d_func_map_trie
292
  */
293
  void computeUfTerms( TNode f );
294
  /** compute arg reps
295
  * Ensure that an entry for n is in d_arg_reps
296
  */
297
  void computeArgReps(TNode n);
298
};/* class TermDb */
299
300
}  // namespace quantifiers
301
}  // namespace theory
302
}  // namespace cvc5
303
304
#endif /* CVC5__THEORY__QUANTIFIERS__TERM_DATABASE_H */