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 */ |