GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/theory_model.h Lines: 4 4 100.0 %
Date: 2021-08-01 Branches: 1 2 50.0 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Clark Barrett, 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
 * Model class.
14
 */
15
16
#include "cvc5_private.h"
17
18
#ifndef CVC5__THEORY__THEORY_MODEL_H
19
#define CVC5__THEORY__THEORY_MODEL_H
20
21
#include <unordered_map>
22
#include <unordered_set>
23
24
#include "theory/ee_setup_info.h"
25
#include "theory/rep_set.h"
26
#include "theory/type_enumerator.h"
27
#include "theory/type_set.h"
28
#include "theory/uf/equality_engine.h"
29
#include "util/cardinality.h"
30
31
namespace cvc5 {
32
33
class Env;
34
35
namespace theory {
36
37
/** Theory Model class.
38
 *
39
 * This class represents a model produced by the TheoryEngine.
40
 * The data structures used to represent a model are:
41
 * (1) d_equalityEngine : an equality engine object, which stores
42
 *     an equivalence relation over all terms that exist in
43
 *     the current set of assertions.
44
 * (2) d_reps : a map from equivalence class representatives of
45
 *     the equality engine to the (constant) representatives
46
 *     assigned to that equivalence class.
47
 * (3) d_uf_models : a map from uninterpreted functions to their
48
 *     lambda representation.
49
 * (4) d_rep_set : a data structure that allows interpretations
50
 *     for types to be represented as terms. This is useful for
51
 *     finite model finding.
52
 * Additionally, models are dependent on top-level substitutions stored in the
53
 * d_env class.
54
 *
55
 * These data structures are built after a full effort check with
56
 * no lemmas sent, within a call to:
57
 *    TheoryEngineModelBuilder::buildModel(...)
58
 * which includes subcalls to TheoryX::collectModelInfo(...) calls.
59
 *
60
 * These calls may modify the model object using the interface
61
 * functions below, including:
62
 * - assertEquality, assertPredicate, assertSkeleton,
63
 *   assertEqualityEngine.
64
 * - assignFunctionDefinition
65
 *
66
 * This class provides several interface functions:
67
 * - hasTerm, getRepresentative, areEqual, areDisequal
68
 * - getEqualityEngine
69
 * - getRepSet
70
 * - hasAssignedFunctionDefinition, getFunctionsToAssign
71
 * - getValue
72
 *
73
 * The above functions can be used for a model m after it has been
74
 * successfully built, i.e. when m->isBuiltSuccess() returns true.
75
 *
76
 * Additionally, all of the above functions, with the exception of getValue,
77
 * can be used during step (5) of TheoryEngineModelBuilder::buildModel, as
78
 * documented in theory_model_builder.h. In particular, we make calls to the
79
 * above functions such as getRepresentative() when assigning total
80
 * interpretations for uninterpreted functions.
81
 */
82
class TheoryModel
83
{
84
  friend class TheoryEngineModelBuilder;
85
86
 public:
87
  TheoryModel(Env& env, std::string name, bool enableFuncModels);
88
  virtual ~TheoryModel();
89
  /**
90
   * Finish init, where ee is the equality engine the model should use.
91
   */
92
  void finishInit(eq::EqualityEngine* ee);
93
94
  /** reset the model */
95
  virtual void reset();
96
  //---------------------------- for building the model
97
  /** assert equality holds in the model
98
   *
99
   * This method returns true if and only if the equality engine of this model
100
   * is consistent after asserting the equality to this model.
101
   */
102
  bool assertEquality(TNode a, TNode b, bool polarity);
103
  /** assert predicate holds in the model
104
   *
105
   * This method returns true if and only if the equality engine of this model
106
   * is consistent after asserting the predicate to this model.
107
   */
108
  bool assertPredicate(TNode a, bool polarity);
109
  /** assert all equalities/predicates in equality engine hold in the model
110
   *
111
   * This method returns true if and only if the equality engine of this model
112
   * is consistent after asserting the equality engine to this model.
113
   */
114
  bool assertEqualityEngine(const eq::EqualityEngine* ee,
115
                            const std::set<Node>* termSet = NULL);
116
  /** assert skeleton
117
   *
118
   * This method gives a "skeleton" for the model value of the equivalence
119
   * class containing n. This should be an application of interpreted function
120
   * (e.g. datatype constructor, array store, set union chain). The subterms of
121
   * this term that are variables or terms that belong to other theories will
122
   * be filled in with model values.
123
   *
124
   * For example, if we call assertSkeleton on (C x y) where C is a datatype
125
   * constructor and x and y are variables, then the equivalence class of
126
   * (C x y) will be interpreted in m as (C x^m y^m) where
127
   * x^m = m->getValue( x ) and y^m = m->getValue( y ).
128
   *
129
   * It should be called during model generation, before final representatives
130
   * are chosen. In the case of TheoryEngineModelBuilder, it should be called
131
   * during Theory's collectModelInfo( ... ) functions.
132
   */
133
  void assertSkeleton(TNode n);
134
  /** set assignment exclusion set
135
   *
136
   * This method sets the "assignment exclusion set" for term n. This is a
137
   * set of terms whose value n must be distinct from in the model.
138
   *
139
   * This method should be used sparingly, and in a way such that model
140
   * building is still guaranteed to succeed. Term n is intended to be an
141
   * assignable term, typically of finite type. Thus, for example, this method
142
   * should not be called with a vector eset that is greater than the
143
   * cardinality of the type of n. Additionally, this method should not be
144
   * called in a way that introduces cyclic dependencies on the assignment order
145
   * of terms in the model. For example, providing { y } as the assignment
146
   * exclusion set of x and { x } as the assignment exclusion set of y will
147
   * cause model building to fail.
148
   *
149
   * The vector eset should contain only terms that occur in the model, or
150
   * are constants.
151
   *
152
   * Additionally, we (currently) require that an assignment exclusion set
153
   * should not be set for two terms in the same equivalence class, or to
154
   * equivalence classes with an assignable term. Otherwise an
155
   * assertion will be thrown by TheoryEngineModelBuilder during model building.
156
   */
157
  void setAssignmentExclusionSet(TNode n, const std::vector<Node>& eset);
158
  /** set assignment exclusion set group
159
   *
160
   * Given group = { x_1, ..., x_n }, this is semantically equivalent to calling
161
   * the above method on the following pairs of arguments:
162
   *   x1, eset
163
   *   x2, eset + { x_1 }
164
   *   ...
165
   *   xn, eset + { x_1, ..., x_{n-1} }
166
   * Similar restrictions should be considered as above when applying this
167
   * method to ensure that model building will succeed. Notice that for
168
   * efficiency, the implementation of how the above information is stored
169
   * may avoid constructing n copies of eset.
170
   */
171
  void setAssignmentExclusionSetGroup(const std::vector<TNode>& group,
172
                                      const std::vector<Node>& eset);
173
  /** get assignment exclusion set for term n
174
   *
175
   * If n has been given an assignment exclusion set, then this method returns
176
   * true and the set is added to eset. Otherwise, the method returns false.
177
   *
178
   * Additionally, if n was assigned an assignment exclusion set via a call to
179
   * setAssignmentExclusionSetGroup, it adds all members that were passed
180
   * in the first argument of that call to the vector group. Otherwise, it
181
   * adds n itself to group.
182
   */
183
  bool getAssignmentExclusionSet(TNode n,
184
                                 std::vector<Node>& group,
185
                                 std::vector<Node>& eset);
186
  /** have any assignment exclusion sets been created? */
187
  bool hasAssignmentExclusionSets() const;
188
  /** record approximation
189
   *
190
   * This notifies this model that the value of n was approximated in this
191
   * model such that the predicate pred (involving n) holds. For example,
192
   * for transcendental functions, we may determine an error bound on the
193
   * value of a transcendental function, say c-e <= y <= c+e where
194
   * c and e are constants. We call this function with n set to sin( x ) and
195
   * pred set to c-e <= sin( x ) <= c+e.
196
   *
197
   * If recordApproximation is called at least once during the model
198
   * construction process, then check-model is not guaranteed to succeed.
199
   * However, there are cases where we can establish the input is satisfiable
200
   * without constructing an exact model. For example, if x=.77, sin(x)=.7, and
201
   * say we have computed c=.7 and e=.01 as an approximation in the above
202
   * example, then we may reason that the set of assertions { sin(x)>.6 } is
203
   * satisfiable, albiet without establishing an exact (irrational) value for
204
   * sin(x).
205
   *
206
   * This function is simply for bookkeeping, it does not affect the model
207
   * construction process.
208
   */
209
  void recordApproximation(TNode n, TNode pred);
210
  /**
211
   * Same as above, but with a witness constant. This ensures that the
212
   * approximation predicate is of the form (or (= n witness) pred). This
213
   * is useful if the user wants to know a possible concrete value in
214
   * the range of the predicate.
215
   */
216
  void recordApproximation(TNode n, TNode pred, Node witness);
217
  /** set unevaluate/semi-evaluated kind
218
   *
219
   * This informs this model how it should interpret applications of terms with
220
   * kind k in getModelValue. We distinguish four categories of kinds:
221
   *
222
   * [1] "Evaluated"
223
   * This includes (standard) interpreted symbols like NOT, PLUS, UNION, etc.
224
   * These operators can be characterized by the invariant that they are
225
   * "evaluatable". That is, if they are applied to only constants, the rewriter
226
   * is guaranteed to rewrite the application to a constant. When getting
227
   * the model value of <k>( t1...tn ) where k is a kind of this category, we
228
   * compute the (constant) value of t1...tn, say this returns c1...cn, we
229
   * return the (constant) result of rewriting <k>( c1...cn ).
230
   *
231
   * [2] "Unevaluated"
232
   * This includes interpreted symbols like FORALL, EXISTS,
233
   * CARDINALITY_CONSTRAINT, that are not evaluatable. When getting a model
234
   * value for a term <k>( t1...tn ) where k is a kind of this category, we
235
   * check whether <k>( t1...tn ) exists in the equality engine of this model.
236
   * If it does, we return its representative, otherwise we return the term
237
   * itself.
238
   *
239
   * [3] "Semi-evaluated"
240
   * This includes kinds like BITVECTOR_ACKERMANNIZE_UDIV and others, typically
241
   * those that correspond to abstractions. Like unevaluated kinds, these
242
   * kinds do not have an evaluator. In contrast to unevaluated kinds, we
243
   * interpret a term <k>( t1...tn ) not appearing in the equality engine as an
244
   * arbitrary value instead of the term itself.
245
   *
246
   * [4] APPLY_UF, where getting the model value depends on an internally
247
   * constructed representation of a lambda model value (d_uf_models).
248
   * It is optional whether this kind is "evaluated" or "semi-evaluated".
249
   * In the case that it is "evaluated", get model rewrites the application
250
   * of the lambda model value of its operator to its evaluated arguments.
251
   *
252
   * By default, all kinds are considered "evaluated". The following methods
253
   * change the interpretation of various (non-APPLY_UF) kinds to one of the
254
   * above categories and should be called by the theories that own the kind
255
   * during Theory::finishInit. We set APPLY_UF to be semi-interpreted when
256
   * this model does not enabled function values (this is the case for the model
257
   * of TheoryEngine when the option assignFunctionValues is set to false).
258
   */
259
  void setUnevaluatedKind(Kind k);
260
  void setSemiEvaluatedKind(Kind k);
261
  /**
262
   * Set irrelevant kind. These kinds do not impact model generation, that is,
263
   * registered terms in theories of this kind do not need to be sent to
264
   * the model. An example is APPLY_TESTER.
265
   */
266
  void setIrrelevantKind(Kind k);
267
  /**
268
   * Get the set of irrelevant kinds that have been registered by the above
269
   * method.
270
   */
271
  const std::set<Kind>& getIrrelevantKinds() const;
272
  /** is legal elimination
273
   *
274
   * Returns true if x -> val is a legal elimination of variable x.
275
   * In particular, this ensures that val does not have any subterms that
276
   * are of unevaluated kinds.
277
   */
278
  bool isLegalElimination(TNode x, TNode val);
279
  //---------------------------- end building the model
280
281
  // ------------------- general equality queries
282
  /** does the equality engine of this model have term a? */
283
  bool hasTerm(TNode a);
284
  /** get the representative of a in the equality engine of this model */
285
  Node getRepresentative(TNode a);
286
  /** are a and b equal in the equality engine of this model? */
287
  bool areEqual(TNode a, TNode b);
288
  /** are a and b disequal in the equality engine of this model? */
289
  bool areDisequal(TNode a, TNode b);
290
  /** get the equality engine for this model */
291
7053
  eq::EqualityEngine* getEqualityEngine() { return d_equalityEngine; }
292
  // ------------------- end general equality queries
293
294
  /** Get value function.
295
   * This should be called only after a ModelBuilder
296
   * has called buildModel(...) on this model.
297
   */
298
  Node getValue(TNode n) const;
299
  /** get comments */
300
  void getComments(std::ostream& out) const;
301
302
  //---------------------------- separation logic
303
  /** set the heap and value sep.nil is equal to */
304
  void setHeapModel(Node h, Node neq);
305
  /** get the heap and value sep.nil is equal to */
306
  bool getHeapModel(Node& h, Node& neq) const;
307
  //---------------------------- end separation logic
308
309
  /** is the list of approximations non-empty? */
310
  bool hasApproximations() const;
311
  /** get approximations */
312
  std::vector<std::pair<Node, Node> > getApproximations() const;
313
  /** get domain elements for uninterpreted sort t */
314
  std::vector<Node> getDomainElements(TypeNode t) const;
315
  /** get the representative set object */
316
171302
  const RepSet* getRepSet() const { return &d_rep_set; }
317
  /** get the representative set object (FIXME: remove this, see #1199) */
318
24836
  RepSet* getRepSetPtr() { return &d_rep_set; }
319
320
  //---------------------------- model cores
321
  /** set using model core */
322
  void setUsingModelCore();
323
  /** record model core symbol */
324
  void recordModelCoreSymbol(Node sym);
325
  /** Return whether symbol expr is in the model core. */
326
  bool isModelCoreSymbol(Node sym) const;
327
  //---------------------------- end model cores
328
329
  /** get cardinality for sort */
330
  Cardinality getCardinality(TypeNode t) const;
331
332
  //---------------------------- function values
333
  /** Does this model have terms for the given uninterpreted function? */
334
  bool hasUfTerms(Node f) const;
335
  /** Get the terms for uninterpreted function f */
336
  const std::vector<Node>& getUfTerms(Node f) const;
337
  /** are function values enabled? */
338
  bool areFunctionValuesEnabled() const;
339
  /** assign function value f to definition f_def */
340
  void assignFunctionDefinition( Node f, Node f_def );
341
  /** have we assigned function f? */
342
12518
  bool hasAssignedFunctionDefinition( Node f ) const { return d_uf_models.find( f )!=d_uf_models.end(); }
343
  /** get the list of functions to assign.
344
  * This list will contain all terms of function type that are terms in d_equalityEngine.
345
  * If higher-order is enabled, we ensure that this list is sorted by type size.
346
  * This allows us to assign functions T -> T before ( T x T ) -> T and before ( T -> T ) -> T,
347
  * which is required for "dag form" model construction (see TheoryModelBuilder::assignHoFunction).
348
  */
349
  std::vector< Node > getFunctionsToAssign();
350
  //---------------------------- end function values
351
  /** Get the name of this model */
352
  const std::string& getName() const;
353
  /**
354
   * For debugging, print the equivalence classes of the underlying equality
355
   * engine.
356
   */
357
  std::string debugPrintModelEqc() const;
358
359
 protected:
360
  /** Reference to the environmanet */
361
  Env& d_env;
362
  /** Unique name of this model */
363
  std::string d_name;
364
  /** equality engine containing all known equalities/disequalities */
365
  eq::EqualityEngine* d_equalityEngine;
366
  /** approximations (see recordApproximation) */
367
  std::map<Node, Node> d_approximations;
368
  /** list of all approximations */
369
  std::vector<std::pair<Node, Node> > d_approx_list;
370
  /** a set of kinds that are unevaluated */
371
  std::unordered_set<Kind, kind::KindHashFunction> d_unevaluated_kinds;
372
  /** a set of kinds that are semi-evaluated */
373
  std::unordered_set<Kind, kind::KindHashFunction> d_semi_evaluated_kinds;
374
  /** The set of irrelevant kinds */
375
  std::set<Kind> d_irrKinds;
376
  /**
377
   * Map of representatives of equality engine to used representatives in
378
   * representative set
379
   */
380
  std::map<Node, Node> d_reps;
381
  /** Map of terms to their assignment exclusion set. */
382
  std::map<Node, std::vector<Node> > d_assignExcSet;
383
  /**
384
   * Map of terms to their "assignment exclusion set master". After a call to
385
   * setAssignmentExclusionSetGroup, the master of each term in group
386
   * (except group[0]) is set to group[0], which stores the assignment
387
   * exclusion set for that group in the above map.
388
   */
389
  std::map<Node, Node> d_aesMaster;
390
  /** Reverse of the above map */
391
  std::map<Node, std::vector<Node> > d_aesSlaves;
392
  /** stores set of representatives for each type */
393
  RepSet d_rep_set;
394
  /** true/false nodes */
395
  Node d_true;
396
  Node d_false;
397
  /** comment stream to include in printing */
398
  std::stringstream d_comment_str;
399
  /** are we using model cores? */
400
  bool d_using_model_core;
401
  /** symbols that are in the model core */
402
  std::unordered_set<Node> d_model_core;
403
  /** Get model value function.
404
   *
405
   * This function is a helper function for getValue.
406
   */
407
  Node getModelValue(TNode n) const;
408
  /** add term internal
409
   *
410
   * This will do any model-specific processing necessary for n,
411
   * such as constraining the interpretation of uninterpreted functions.
412
   * This is called once for all terms in the equality engine, just before
413
   * a model builder constructs this model.
414
   */
415
  virtual void addTermInternal(TNode n);
416
 private:
417
  /** cache for getModelValue */
418
  mutable std::unordered_map<Node, Node> d_modelCache;
419
420
  //---------------------------- separation logic
421
  /** the value of the heap */
422
  Node d_sep_heap;
423
  /** the value of the nil element */
424
  Node d_sep_nil_eq;
425
  //---------------------------- end separation logic
426
427
  //---------------------------- function values
428
  /** a map from functions f to a list of all APPLY_UF terms with operator f */
429
  std::map<Node, std::vector<Node> > d_uf_terms;
430
  /** a map from functions f to a list of all HO_APPLY terms with first argument
431
   * f */
432
  std::map<Node, std::vector<Node> > d_ho_uf_terms;
433
  /** whether function models are enabled */
434
  bool d_enableFuncModels;
435
  /** map from function terms to the (lambda) definitions
436
  * After the model is built, the domain of this map is all terms of function
437
  * type that appear as terms in d_equalityEngine.
438
  */
439
  std::map<Node, Node> d_uf_models;
440
  //---------------------------- end function values
441
};/* class TheoryModel */
442
443
}  // namespace theory
444
}  // namespace cvc5
445
446
#endif /* CVC5__THEORY__THEORY_MODEL_H */