1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Andrew Reynolds, Morgan Deters, Dejan Jovanovic |
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 |
|
* Base of the theory interface. |
14 |
|
*/ |
15 |
|
|
16 |
|
#include "cvc5_private.h" |
17 |
|
|
18 |
|
#ifndef CVC5__THEORY__THEORY_H |
19 |
|
#define CVC5__THEORY__THEORY_H |
20 |
|
|
21 |
|
#include <iosfwd> |
22 |
|
#include <set> |
23 |
|
#include <string> |
24 |
|
#include <unordered_set> |
25 |
|
|
26 |
|
#include "context/cdlist.h" |
27 |
|
#include "context/cdo.h" |
28 |
|
#include "context/context.h" |
29 |
|
#include "expr/node.h" |
30 |
|
#include "options/theory_options.h" |
31 |
|
#include "theory/assertion.h" |
32 |
|
#include "theory/care_graph.h" |
33 |
|
#include "theory/logic_info.h" |
34 |
|
#include "theory/skolem_lemma.h" |
35 |
|
#include "theory/theory_id.h" |
36 |
|
#include "theory/trust_node.h" |
37 |
|
#include "theory/valuation.h" |
38 |
|
#include "util/statistics_stats.h" |
39 |
|
|
40 |
|
namespace cvc5 { |
41 |
|
|
42 |
|
class ProofNodeManager; |
43 |
|
class TheoryEngine; |
44 |
|
class ProofRuleChecker; |
45 |
|
|
46 |
|
namespace theory { |
47 |
|
|
48 |
|
class DecisionManager; |
49 |
|
struct EeSetupInfo; |
50 |
|
class OutputChannel; |
51 |
|
class QuantifiersEngine; |
52 |
|
class TheoryInferenceManager; |
53 |
|
class TheoryModel; |
54 |
|
class TheoryRewriter; |
55 |
|
class TheoryState; |
56 |
|
class TrustSubstitutionMap; |
57 |
|
|
58 |
|
namespace eq { |
59 |
|
class EqualityEngine; |
60 |
|
} // namespace eq |
61 |
|
|
62 |
|
/** |
63 |
|
* Base class for T-solvers. Abstract DPLL(T). |
64 |
|
* |
65 |
|
* This is essentially an interface class. The TheoryEngine has |
66 |
|
* pointers to Theory. Note that only one specific Theory type (e.g., |
67 |
|
* TheoryUF) can exist per NodeManager, because of how the |
68 |
|
* RegisteredAttr works. (If you need multiple instances of the same |
69 |
|
* theory, you'll have to write a multiplexed theory that dispatches |
70 |
|
* all calls to them.) |
71 |
|
* |
72 |
|
* NOTE: A Theory has a special way of being initialized. The owner of a Theory |
73 |
|
* is either: |
74 |
|
* |
75 |
|
* (A) Using Theory as a standalone object, not associated with a TheoryEngine. |
76 |
|
* In this case, simply call the public initialization method |
77 |
|
* (Theory::finishInitStandalone). |
78 |
|
* |
79 |
|
* (B) TheoryEngine, which determines how the Theory acts in accordance with |
80 |
|
* its theory combination policy. We require the following steps in order: |
81 |
|
* (B.1) Get information about whether the theory wishes to use an equality |
82 |
|
* eninge, and more specifically which equality engine notifications the Theory |
83 |
|
* would like to be notified of (Theory::needsEqualityEngine). |
84 |
|
* (B.2) Set the equality engine of the theory (Theory::setEqualityEngine), |
85 |
|
* which we refer to as the "official equality engine" of this Theory. The |
86 |
|
* equality engine passed to the theory must respect the contract(s) specified |
87 |
|
* by the equality engine setup information (EeSetupInfo) returned in the |
88 |
|
* previous step. |
89 |
|
* (B.3) Set the other required utilities including setQuantifiersEngine and |
90 |
|
* setDecisionManager. |
91 |
|
* (B.4) Call the private initialization method (Theory::finishInit). |
92 |
|
* |
93 |
|
* Initialization of the second form happens during TheoryEngine::finishInit, |
94 |
|
* after the quantifiers engine and model objects have been set up. |
95 |
|
*/ |
96 |
|
class Theory { |
97 |
|
friend class ::cvc5::TheoryEngine; |
98 |
|
|
99 |
|
private: |
100 |
|
// Disallow default construction, copy, assignment. |
101 |
|
Theory() = delete; |
102 |
|
Theory(const Theory&) = delete; |
103 |
|
Theory& operator=(const Theory&) = delete; |
104 |
|
|
105 |
|
/** An integer identifying the type of the theory. */ |
106 |
|
TheoryId d_id; |
107 |
|
|
108 |
|
/** The SAT search context for the Theory. */ |
109 |
|
context::Context* d_satContext; |
110 |
|
|
111 |
|
/** The user level assertion context for the Theory. */ |
112 |
|
context::UserContext* d_userContext; |
113 |
|
|
114 |
|
/** Information about the logic we're operating within. */ |
115 |
|
const LogicInfo& d_logicInfo; |
116 |
|
|
117 |
|
/** |
118 |
|
* The assertFact() queue. |
119 |
|
* |
120 |
|
* These can not be TNodes as some atoms (such as equalities) are sent |
121 |
|
* across theories without being stored in a global map. |
122 |
|
*/ |
123 |
|
context::CDList<Assertion> d_facts; |
124 |
|
|
125 |
|
/** Index into the head of the facts list */ |
126 |
|
context::CDO<unsigned> d_factsHead; |
127 |
|
|
128 |
|
/** Indices for splitting on the shared terms. */ |
129 |
|
context::CDO<unsigned> d_sharedTermsIndex; |
130 |
|
|
131 |
|
/** The care graph the theory will use during combination. */ |
132 |
|
CareGraph* d_careGraph; |
133 |
|
|
134 |
|
/** Pointer to the decision manager. */ |
135 |
|
DecisionManager* d_decManager; |
136 |
|
|
137 |
|
protected: |
138 |
|
/** Name of this theory instance. Along with the TheoryId this should provide |
139 |
|
* an unique string identifier for each instance of a Theory class. We need |
140 |
|
* this to ensure unique statistics names over multiple theory instances. */ |
141 |
|
std::string d_instanceName; |
142 |
|
|
143 |
|
// === STATISTICS === |
144 |
|
/** time spent in check calls */ |
145 |
|
TimerStat d_checkTime; |
146 |
|
/** time spent in theory combination */ |
147 |
|
TimerStat d_computeCareGraphTime; |
148 |
|
|
149 |
|
/** |
150 |
|
* The only method to add suff to the care graph. |
151 |
|
*/ |
152 |
|
void addCarePair(TNode t1, TNode t2); |
153 |
|
|
154 |
|
/** |
155 |
|
* The function should compute the care graph over the shared terms. |
156 |
|
* The default function returns all the pairs among the shared variables. |
157 |
|
*/ |
158 |
|
virtual void computeCareGraph(); |
159 |
|
|
160 |
|
/** |
161 |
|
* A list of shared terms that the theory has. |
162 |
|
*/ |
163 |
|
context::CDList<TNode> d_sharedTerms; |
164 |
|
|
165 |
|
/** |
166 |
|
* Construct a Theory. |
167 |
|
* |
168 |
|
* The pair <id, instance> is assumed to uniquely identify this Theory |
169 |
|
* w.r.t. the SmtEngine. |
170 |
|
*/ |
171 |
|
Theory(TheoryId id, |
172 |
|
context::Context* satContext, |
173 |
|
context::UserContext* userContext, |
174 |
|
OutputChannel& out, |
175 |
|
Valuation valuation, |
176 |
|
const LogicInfo& logicInfo, |
177 |
|
ProofNodeManager* pnm, |
178 |
|
std::string instance = ""); // taking : No default. |
179 |
|
|
180 |
|
/** |
181 |
|
* This is called at shutdown time by the TheoryEngine, just before |
182 |
|
* destruction. It is important because there are destruction |
183 |
|
* ordering issues between PropEngine and Theory (based on what |
184 |
|
* hard-links to Nodes are outstanding). As the fact queue might be |
185 |
|
* nonempty, we ensure here that it's clear. If you overload this, |
186 |
|
* you must make an explicit call here to this->Theory::shutdown() |
187 |
|
* too. |
188 |
|
*/ |
189 |
75654 |
virtual void shutdown() { } |
190 |
|
|
191 |
|
/** |
192 |
|
* The output channel for the Theory. |
193 |
|
*/ |
194 |
|
OutputChannel* d_out; |
195 |
|
|
196 |
|
/** |
197 |
|
* The valuation proxy for the Theory to communicate back with the |
198 |
|
* theory engine (and other theories). |
199 |
|
*/ |
200 |
|
Valuation d_valuation; |
201 |
|
/** |
202 |
|
* Pointer to the official equality engine of this theory, which is owned by |
203 |
|
* the equality engine manager of TheoryEngine. |
204 |
|
*/ |
205 |
|
eq::EqualityEngine* d_equalityEngine; |
206 |
|
/** |
207 |
|
* The official equality engine, if we allocated it. |
208 |
|
*/ |
209 |
|
std::unique_ptr<eq::EqualityEngine> d_allocEqualityEngine; |
210 |
|
/** |
211 |
|
* The theory state, which contains contexts, valuation, and equality engine. |
212 |
|
* Notice the theory is responsible for memory management of this class. |
213 |
|
*/ |
214 |
|
TheoryState* d_theoryState; |
215 |
|
/** |
216 |
|
* The theory inference manager. This is a wrapper around the equality |
217 |
|
* engine and the output channel. It ensures that the output channel and |
218 |
|
* the equality engine are used properly. |
219 |
|
*/ |
220 |
|
TheoryInferenceManager* d_inferManager; |
221 |
|
|
222 |
|
/** |
223 |
|
* Pointer to the quantifiers engine (or NULL, if quantifiers are not |
224 |
|
* supported or not enabled). Not owned by the theory. |
225 |
|
*/ |
226 |
|
QuantifiersEngine* d_quantEngine; |
227 |
|
|
228 |
|
/** Pointer to proof node manager */ |
229 |
|
ProofNodeManager* d_pnm; |
230 |
|
|
231 |
|
/** |
232 |
|
* Are proofs enabled? |
233 |
|
* |
234 |
|
* They are considered enabled if the ProofNodeManager is non-null. |
235 |
|
*/ |
236 |
|
bool proofsEnabled() const; |
237 |
|
|
238 |
|
/** |
239 |
|
* Returns the next assertion in the assertFact() queue. |
240 |
|
* |
241 |
|
* @return the next assertion in the assertFact() queue |
242 |
|
*/ |
243 |
|
inline Assertion get(); |
244 |
|
|
245 |
177143 |
const LogicInfo& getLogicInfo() const { |
246 |
177143 |
return d_logicInfo; |
247 |
|
} |
248 |
|
|
249 |
|
/** |
250 |
|
* Set separation logic heap. This is called when the location and data |
251 |
|
* types for separation logic are determined. This should be called at |
252 |
|
* most once, before solving. |
253 |
|
* |
254 |
|
* This currently should be overridden by the separation logic theory only. |
255 |
|
*/ |
256 |
1444 |
virtual void declareSepHeap(TypeNode locT, TypeNode dataT) {} |
257 |
|
|
258 |
|
/** |
259 |
|
* The theory that owns the uninterpreted sort. |
260 |
|
*/ |
261 |
|
static TheoryId s_uninterpretedSortOwner; |
262 |
|
|
263 |
|
void printFacts(std::ostream& os) const; |
264 |
|
void debugPrintFacts() const; |
265 |
|
|
266 |
|
/** is legal elimination |
267 |
|
* |
268 |
|
* Returns true if x -> val is a legal elimination of variable x. This is |
269 |
|
* useful for ppAssert, when x = val is an entailed equality. This function |
270 |
|
* determines whether indeed x can be eliminated from the problem via the |
271 |
|
* substituion x -> val. |
272 |
|
* |
273 |
|
* The following criteria imply that x -> val is *not* a legal elimination: |
274 |
|
* (1) If x is contained in val, |
275 |
|
* (2) If the type of val is not a subtype of the type of x, |
276 |
|
* (3) If val contains an operator that cannot be evaluated, and produceModels |
277 |
|
* is true. For example, x -> sqrt(2) is not a legal elimination if we |
278 |
|
* are producing models. This is because we care about the value of x, and |
279 |
|
* its value must be computed (approximated) by the non-linear solver. |
280 |
|
*/ |
281 |
|
bool isLegalElimination(TNode x, TNode val); |
282 |
|
//--------------------------------- private initialization |
283 |
|
/** |
284 |
|
* Called to set the official equality engine. This should be done by |
285 |
|
* TheoryEngine only. |
286 |
|
*/ |
287 |
|
void setEqualityEngine(eq::EqualityEngine* ee); |
288 |
|
/** Called to set the quantifiers engine. */ |
289 |
|
void setQuantifiersEngine(QuantifiersEngine* qe); |
290 |
|
/** Called to set the decision manager. */ |
291 |
|
void setDecisionManager(DecisionManager* dm); |
292 |
|
/** |
293 |
|
* Finish theory initialization. At this point, options and the logic |
294 |
|
* setting are final, the master equality engine and quantifiers |
295 |
|
* engine (if any) are initialized, and the official equality engine of this |
296 |
|
* theory has been assigned. This base class implementation |
297 |
|
* does nothing. This should be called by TheoryEngine only. |
298 |
|
*/ |
299 |
9459 |
virtual void finishInit() {} |
300 |
|
//--------------------------------- end private initialization |
301 |
|
|
302 |
|
/** |
303 |
|
* This method is called to notify a theory that the node n should |
304 |
|
* be considered a "shared term" by this theory. This does anything |
305 |
|
* theory-specific concerning the fact that n is now marked as a shared |
306 |
|
* term, which is done in addition to explicitly storing n as a shared |
307 |
|
* term and adding it as a trigger term in the equality engine of this |
308 |
|
* class (see addSharedTerm). |
309 |
|
*/ |
310 |
|
virtual void notifySharedTerm(TNode n); |
311 |
|
|
312 |
|
public: |
313 |
|
//--------------------------------- initialization |
314 |
|
/** |
315 |
|
* @return The theory rewriter associated with this theory. |
316 |
|
*/ |
317 |
|
virtual TheoryRewriter* getTheoryRewriter() = 0; |
318 |
|
/** |
319 |
|
* @return The proof checker associated with this theory. |
320 |
|
*/ |
321 |
|
virtual ProofRuleChecker* getProofChecker() = 0; |
322 |
|
/** |
323 |
|
* Returns true if this theory needs an equality engine for checking |
324 |
|
* satisfiability. |
325 |
|
* |
326 |
|
* If this method returns true, then the equality engine manager will |
327 |
|
* initialize its equality engine field via setEqualityEngine above during |
328 |
|
* TheoryEngine::finishInit, prior to calling finishInit for this theory. |
329 |
|
* |
330 |
|
* Additionally, if this method returns true, then this method is required to |
331 |
|
* update the argument esi with instructions for initializing and setting up |
332 |
|
* notifications from its equality engine, which is commonly done with |
333 |
|
* a notifications class (eq::EqualityEngineNotify). |
334 |
|
*/ |
335 |
|
virtual bool needsEqualityEngine(EeSetupInfo& esi); |
336 |
|
/** |
337 |
|
* Finish theory initialization, standalone version. This is used to |
338 |
|
* initialize this class if it is not associated with a theory engine. |
339 |
|
* This allocates the official equality engine of this Theory and then |
340 |
|
* calls the finishInit method above. |
341 |
|
*/ |
342 |
|
void finishInitStandalone(); |
343 |
|
//--------------------------------- end initialization |
344 |
|
|
345 |
|
/** |
346 |
|
* Return the ID of the theory responsible for the given type. |
347 |
|
*/ |
348 |
47635981 |
static inline TheoryId theoryOf(TypeNode typeNode) { |
349 |
47635981 |
Trace("theory::internal") << "theoryOf(" << typeNode << ")" << std::endl; |
350 |
|
TheoryId id; |
351 |
47635981 |
if (typeNode.getKind() == kind::TYPE_CONSTANT) { |
352 |
32797604 |
id = typeConstantToTheoryId(typeNode.getConst<TypeConstant>()); |
353 |
|
} else { |
354 |
14838377 |
id = kindToTheoryId(typeNode.getKind()); |
355 |
|
} |
356 |
47635981 |
if (id == THEORY_BUILTIN) { |
357 |
2954070 |
Trace("theory::internal") << "theoryOf(" << typeNode << ") == " << s_uninterpretedSortOwner << std::endl; |
358 |
2954070 |
return s_uninterpretedSortOwner; |
359 |
|
} |
360 |
44681911 |
return id; |
361 |
|
} |
362 |
|
|
363 |
|
/** |
364 |
|
* Returns the ID of the theory responsible for the given node. |
365 |
|
*/ |
366 |
|
static TheoryId theoryOf(options::TheoryOfMode mode, TNode node); |
367 |
|
|
368 |
|
/** |
369 |
|
* Returns the ID of the theory responsible for the given node. |
370 |
|
*/ |
371 |
158355378 |
static inline TheoryId theoryOf(TNode node) { |
372 |
316721955 |
return theoryOf(options::theoryOfMode(), node); |
373 |
|
} |
374 |
|
|
375 |
|
/** |
376 |
|
* Set the owner of the uninterpreted sort. |
377 |
|
*/ |
378 |
9459 |
static void setUninterpretedSortOwner(TheoryId theory) { |
379 |
9459 |
s_uninterpretedSortOwner = theory; |
380 |
9459 |
} |
381 |
|
|
382 |
|
/** |
383 |
|
* Get the owner of the uninterpreted sort. |
384 |
|
*/ |
385 |
|
static TheoryId getUninterpretedSortOwner() { |
386 |
|
return s_uninterpretedSortOwner; |
387 |
|
} |
388 |
|
|
389 |
|
/** |
390 |
|
* Checks if the node is a leaf node of this theory |
391 |
|
*/ |
392 |
350098 |
inline bool isLeaf(TNode node) const { |
393 |
350098 |
return node.getNumChildren() == 0 || theoryOf(node) != d_id; |
394 |
|
} |
395 |
|
|
396 |
|
/** |
397 |
|
* Checks if the node is a leaf node of a theory. |
398 |
|
*/ |
399 |
198427899 |
inline static bool isLeafOf(TNode node, TheoryId theoryId) { |
400 |
198427899 |
return node.getNumChildren() == 0 || theoryOf(node) != theoryId; |
401 |
|
} |
402 |
|
|
403 |
|
/** Returns true if the assertFact queue is empty*/ |
404 |
40858345 |
bool done() const { return d_factsHead == d_facts.size(); } |
405 |
|
/** |
406 |
|
* Destructs a Theory. |
407 |
|
*/ |
408 |
|
virtual ~Theory(); |
409 |
|
|
410 |
|
/** |
411 |
|
* Subclasses of Theory may add additional efforts. DO NOT CHECK |
412 |
|
* equality with one of these values (e.g. if STANDARD xxx) but |
413 |
|
* rather use range checks (or use the helper functions below). |
414 |
|
* Normally we call QUICK_CHECK or STANDARD; at the leaves we call |
415 |
|
* with FULL_EFFORT. |
416 |
|
*/ |
417 |
|
enum Effort |
418 |
|
{ |
419 |
|
/** |
420 |
|
* Standard effort where theory need not do anything |
421 |
|
*/ |
422 |
|
EFFORT_STANDARD = 50, |
423 |
|
/** |
424 |
|
* Full effort requires the theory make sure its assertions are satisfiable |
425 |
|
* or not |
426 |
|
*/ |
427 |
|
EFFORT_FULL = 100, |
428 |
|
/** |
429 |
|
* Last call effort, called after theory combination has completed with |
430 |
|
* no lemmas and a model is available. |
431 |
|
*/ |
432 |
|
EFFORT_LAST_CALL = 200 |
433 |
|
}; /* enum Effort */ |
434 |
|
|
435 |
4 |
static inline bool standardEffortOrMore(Effort e) CVC5_CONST_FUNCTION |
436 |
|
{ |
437 |
4 |
return e >= EFFORT_STANDARD; } |
438 |
4 |
static inline bool standardEffortOnly(Effort e) CVC5_CONST_FUNCTION |
439 |
|
{ |
440 |
4 |
return e >= EFFORT_STANDARD && e < EFFORT_FULL; } |
441 |
26589248 |
static inline bool fullEffort(Effort e) CVC5_CONST_FUNCTION |
442 |
|
{ |
443 |
26589248 |
return e == EFFORT_FULL; } |
444 |
|
|
445 |
|
/** |
446 |
|
* Get the id for this Theory. |
447 |
|
*/ |
448 |
16091496 |
TheoryId getId() const { |
449 |
16091496 |
return d_id; |
450 |
|
} |
451 |
|
|
452 |
|
/** |
453 |
|
* Get the SAT context associated to this Theory. |
454 |
|
*/ |
455 |
3412662 |
context::Context* getSatContext() const { |
456 |
3412662 |
return d_satContext; |
457 |
|
} |
458 |
|
|
459 |
|
/** |
460 |
|
* Get the context associated to this Theory. |
461 |
|
*/ |
462 |
147000 |
context::UserContext* getUserContext() const { |
463 |
147000 |
return d_userContext; |
464 |
|
} |
465 |
|
|
466 |
|
/** |
467 |
|
* Get the output channel associated to this theory. |
468 |
|
*/ |
469 |
124507 |
OutputChannel& getOutputChannel() { |
470 |
124507 |
return *d_out; |
471 |
|
} |
472 |
|
|
473 |
|
/** |
474 |
|
* Get the valuation associated to this theory. |
475 |
|
*/ |
476 |
36587 |
Valuation& getValuation() { |
477 |
36587 |
return d_valuation; |
478 |
|
} |
479 |
|
|
480 |
|
/** Get the equality engine being used by this theory. */ |
481 |
|
eq::EqualityEngine* getEqualityEngine(); |
482 |
|
|
483 |
|
/** |
484 |
|
* Get the quantifiers engine associated to this theory. |
485 |
|
*/ |
486 |
299060 |
QuantifiersEngine* getQuantifiersEngine() { |
487 |
299060 |
return d_quantEngine; |
488 |
|
} |
489 |
|
|
490 |
|
/** |
491 |
|
* @return The theory state associated with this theory. |
492 |
|
*/ |
493 |
|
TheoryState* getTheoryState() { return d_theoryState; } |
494 |
|
|
495 |
|
/** |
496 |
|
* @return The theory inference manager associated with this theory. |
497 |
|
*/ |
498 |
|
TheoryInferenceManager* getInferenceManager() { return d_inferManager; } |
499 |
|
|
500 |
|
/** |
501 |
|
* Pre-register a term. Done one time for a Node per SAT context level. |
502 |
|
*/ |
503 |
|
virtual void preRegisterTerm(TNode); |
504 |
|
|
505 |
|
/** |
506 |
|
* Assert a fact in the current context. |
507 |
|
*/ |
508 |
12458166 |
void assertFact(TNode assertion, bool isPreregistered) { |
509 |
24916332 |
Trace("theory") << "Theory<" << getId() << ">::assertFact[" |
510 |
24916332 |
<< d_satContext->getLevel() << "](" << assertion << ", " |
511 |
12458166 |
<< (isPreregistered ? "true" : "false") << ")" << std::endl; |
512 |
12458166 |
d_facts.push_back(Assertion(assertion, isPreregistered)); |
513 |
12458166 |
} |
514 |
|
|
515 |
|
/** Add shared term to the theory. */ |
516 |
|
void addSharedTerm(TNode node); |
517 |
|
|
518 |
|
/** |
519 |
|
* Return the current theory care graph. Theories should overload |
520 |
|
* computeCareGraph to do the actual computation, and use addCarePair to add |
521 |
|
* pairs to the care graph. |
522 |
|
*/ |
523 |
|
void getCareGraph(CareGraph* careGraph); |
524 |
|
|
525 |
|
/** |
526 |
|
* Return the status of two terms in the current context. Should be |
527 |
|
* implemented in sub-theories to enable more efficient theory-combination. |
528 |
|
*/ |
529 |
|
virtual EqualityStatus getEqualityStatus(TNode a, TNode b); |
530 |
|
|
531 |
|
/** |
532 |
|
* Return the model value of the give shared term (or null if not available). |
533 |
|
* |
534 |
|
* TODO (project #39): this method is likely to become deprecated. |
535 |
|
*/ |
536 |
1726 |
virtual Node getModelValue(TNode var) { return Node::null(); } |
537 |
|
|
538 |
|
/** T-propagate new literal assignments in the current context. */ |
539 |
|
virtual void propagate(Effort level = EFFORT_FULL) {} |
540 |
|
|
541 |
|
/** |
542 |
|
* Return an explanation for the literal represented by parameter n |
543 |
|
* (which was previously propagated by this theory). |
544 |
|
*/ |
545 |
|
virtual TrustNode explain(TNode n) |
546 |
|
{ |
547 |
|
Unimplemented() << "Theory " << identify() |
548 |
|
<< " propagated a node but doesn't implement the " |
549 |
|
"Theory::explain() interface!"; |
550 |
|
return TrustNode::null(); |
551 |
|
} |
552 |
|
|
553 |
|
//--------------------------------- check |
554 |
|
/** |
555 |
|
* Does this theory wish to be called to check at last call effort? This is |
556 |
|
* the case for any theory that wishes to run when a model is available. |
557 |
|
*/ |
558 |
56509 |
virtual bool needsCheckLastEffort() { return false; } |
559 |
|
/** |
560 |
|
* Check the current assignment's consistency. |
561 |
|
* |
562 |
|
* An implementation of check() is required to either: |
563 |
|
* - return a conflict on the output channel, |
564 |
|
* - be interrupted, |
565 |
|
* - throw an exception |
566 |
|
* - or call get() until done() is true. |
567 |
|
* |
568 |
|
* The standard method for check consists of a loop that processes the entire |
569 |
|
* fact queue when preCheck returns false. It makes four theory-specific |
570 |
|
* callbacks, (preCheck, postCheck, preNotifyFact, notifyFact) as described |
571 |
|
* below. It asserts each fact to the official equality engine when |
572 |
|
* preNotifyFact returns false. |
573 |
|
* |
574 |
|
* Theories that use this check method must use an official theory |
575 |
|
* state object (d_theoryState). |
576 |
|
*/ |
577 |
|
void check(Effort level = EFFORT_FULL); |
578 |
|
/** |
579 |
|
* Pre-check, called before the fact queue of the theory is processed. |
580 |
|
* If this method returns false, then the theory will process its fact |
581 |
|
* queue. If this method returns true, then the theory has indicated |
582 |
|
* its check method should finish immediately. |
583 |
|
*/ |
584 |
|
virtual bool preCheck(Effort level = EFFORT_FULL); |
585 |
|
/** |
586 |
|
* Post-check, called after the fact queue of the theory is processed. |
587 |
|
*/ |
588 |
|
virtual void postCheck(Effort level = EFFORT_FULL); |
589 |
|
/** |
590 |
|
* Pre-notify fact, return true if the theory processed it. If this |
591 |
|
* method returns false, then the atom will be added to the equality engine |
592 |
|
* of the theory and notifyFact will be called with isInternal=false. |
593 |
|
* |
594 |
|
* Theories that implement check but do not use official equality |
595 |
|
* engines should always return true for this method. |
596 |
|
* |
597 |
|
* @param atom The atom |
598 |
|
* @param polarity Its polarity |
599 |
|
* @param fact The original literal that was asserted |
600 |
|
* @param isPrereg Whether the assertion is preregistered |
601 |
|
* @param isInternal Whether the origin of the fact was internal. If this |
602 |
|
* is false, the fact was asserted via the fact queue of the theory. |
603 |
|
* @return true if the theory completely processed this fact, i.e. it does |
604 |
|
* not need to assert the fact to its equality engine. |
605 |
|
*/ |
606 |
|
virtual bool preNotifyFact( |
607 |
|
TNode atom, bool pol, TNode fact, bool isPrereg, bool isInternal); |
608 |
|
/** |
609 |
|
* Notify fact, called immediately after the fact was pushed into the |
610 |
|
* equality engine. |
611 |
|
* |
612 |
|
* @param atom The atom |
613 |
|
* @param polarity Its polarity |
614 |
|
* @param fact The original literal that was asserted. |
615 |
|
* @param isInternal Whether the origin of the fact was internal. If this |
616 |
|
* is false, the fact was asserted via the fact queue of the theory. |
617 |
|
*/ |
618 |
|
virtual void notifyFact(TNode atom, bool pol, TNode fact, bool isInternal); |
619 |
|
//--------------------------------- end check |
620 |
|
|
621 |
|
//--------------------------------- collect model info |
622 |
|
/** |
623 |
|
* Get all relevant information in this theory regarding the current |
624 |
|
* model. This should be called after a call to check( FULL_EFFORT ) |
625 |
|
* for all theories with no conflicts and no lemmas added. |
626 |
|
* |
627 |
|
* This method returns true if and only if the equality engine of m is |
628 |
|
* consistent as a result of this call. |
629 |
|
* |
630 |
|
* The standard method for collectModelInfo computes the relevant terms, |
631 |
|
* asserts the theory's equality engine to the model (if necessary) and |
632 |
|
* then calls computeModelValues. |
633 |
|
* |
634 |
|
* TODO (project #39): this method should be non-virtual, once all theories |
635 |
|
* conform to the new standard, delete, move to model manager distributed. |
636 |
|
*/ |
637 |
|
virtual bool collectModelInfo(TheoryModel* m, const std::set<Node>& termSet); |
638 |
|
/** |
639 |
|
* Compute terms that are not necessarily part of the assertions or |
640 |
|
* shared terms that should be considered relevant, add them to termSet. |
641 |
|
*/ |
642 |
|
virtual void computeRelevantTerms(std::set<Node>& termSet); |
643 |
|
/** |
644 |
|
* Collect model values, after equality information is added to the model. |
645 |
|
* The argument termSet is the set of relevant terms returned by |
646 |
|
* computeRelevantTerms. |
647 |
|
*/ |
648 |
|
virtual bool collectModelValues(TheoryModel* m, |
649 |
|
const std::set<Node>& termSet); |
650 |
|
/** if theories want to do something with model after building, do it here */ |
651 |
10164 |
virtual void postProcessModel( TheoryModel* m ){ } |
652 |
|
//--------------------------------- end collect model info |
653 |
|
|
654 |
|
//--------------------------------- preprocessing |
655 |
|
/** |
656 |
|
* Statically learn from assertion "in," which has been asserted |
657 |
|
* true at the top level. The theory should only add (via |
658 |
|
* ::operator<< or ::append()) to the "learned" builder---it should |
659 |
|
* *never* clear it. It is a conjunction to add to the formula at |
660 |
|
* the top-level and may contain other theories' contributions. |
661 |
|
*/ |
662 |
|
virtual void ppStaticLearn(TNode in, NodeBuilder& learned) {} |
663 |
|
|
664 |
|
enum PPAssertStatus { |
665 |
|
/** Atom has been solved */ |
666 |
|
PP_ASSERT_STATUS_SOLVED, |
667 |
|
/** Atom has not been solved */ |
668 |
|
PP_ASSERT_STATUS_UNSOLVED, |
669 |
|
/** Atom is inconsistent */ |
670 |
|
PP_ASSERT_STATUS_CONFLICT |
671 |
|
}; |
672 |
|
|
673 |
|
/** |
674 |
|
* Given a literal and its proof generator (encapsulated by trust node tin), |
675 |
|
* add the solved substitutions to the map, if any. The method should return |
676 |
|
* true if the literal can be safely removed from the input problem. |
677 |
|
* |
678 |
|
* Note that tin has trude node kind LEMMA. Its proof generator should be |
679 |
|
* take into account when adding a substitution to outSubstitutions when |
680 |
|
* proofs are enabled. |
681 |
|
*/ |
682 |
|
virtual PPAssertStatus ppAssert(TrustNode tin, |
683 |
|
TrustSubstitutionMap& outSubstitutions); |
684 |
|
|
685 |
|
/** |
686 |
|
* Given a term of the theory coming from the input formula or |
687 |
|
* from a lemma generated during solving, this method can be overridden in a |
688 |
|
* theory implementation to rewrite the term into an equivalent form. |
689 |
|
* |
690 |
|
* This method returns a TrustNode of kind TrustNodeKind::REWRITE, which |
691 |
|
* carries information about the proof generator for the rewrite, which can |
692 |
|
* be the null TrustNode if n is unchanged. |
693 |
|
* |
694 |
|
* Notice this method is used both in the "theory rewrite equalities" |
695 |
|
* preprocessing pass, where n is an equality from the input formula, |
696 |
|
* and in theory preprocessing, where n is a (non-equality) term occurring |
697 |
|
* in the input or generated in a lemma. |
698 |
|
* |
699 |
|
* @param n the node to preprocess-rewrite. |
700 |
|
* @param lems a set of lemmas that should be added as a consequence of |
701 |
|
* preprocessing n. These are in the form of "skolem lemmas". For example, |
702 |
|
* calling this method on (div x n), we return a trust node proving: |
703 |
|
* (= (div x n) k_div) |
704 |
|
* for fresh skolem k, and add the skolem lemma for k that indicates that |
705 |
|
* it is the division of x and n. |
706 |
|
* |
707 |
|
* Note that ppRewrite should not return WITNESS terms, since the internal |
708 |
|
* calculus works in "original forms" and not "witness forms". |
709 |
|
*/ |
710 |
118650 |
virtual TrustNode ppRewrite(TNode n, std::vector<SkolemLemma>& lems) |
711 |
|
{ |
712 |
118650 |
return TrustNode::null(); |
713 |
|
} |
714 |
|
|
715 |
|
/** |
716 |
|
* Notify preprocessed assertions. Called on new assertions after |
717 |
|
* preprocessing before they are asserted to theory engine. |
718 |
|
*/ |
719 |
141614 |
virtual void ppNotifyAssertions(const std::vector<Node>& assertions) {} |
720 |
|
//--------------------------------- end preprocessing |
721 |
|
|
722 |
|
/** |
723 |
|
* A Theory is called with presolve exactly one time per user |
724 |
|
* check-sat. presolve() is called after preregistration, |
725 |
|
* rewriting, and Boolean propagation, (other theories' |
726 |
|
* propagation?), but the notified Theory has not yet had its |
727 |
|
* check() or propagate() method called. A Theory may empty its |
728 |
|
* assertFact() queue using get(). A Theory can raise conflicts, |
729 |
|
* add lemmas, and propagate literals during presolve(). |
730 |
|
* |
731 |
|
* NOTE: The presolve property must be added to the kinds file for |
732 |
|
* the theory. |
733 |
|
*/ |
734 |
|
virtual void presolve() { } |
735 |
|
|
736 |
|
/** |
737 |
|
* A Theory is called with postsolve exactly one time per user |
738 |
|
* check-sat. postsolve() is called after the query has completed |
739 |
|
* (regardless of whether sat, unsat, or unknown), and after any |
740 |
|
* model-querying related to the query has been performed. |
741 |
|
* After this call, the theory will not get another check() or |
742 |
|
* propagate() call until presolve() is called again. A Theory |
743 |
|
* cannot raise conflicts, add lemmas, or propagate literals during |
744 |
|
* postsolve(). |
745 |
|
*/ |
746 |
|
virtual void postsolve() { } |
747 |
|
|
748 |
|
/** |
749 |
|
* Notification sent to the theory wheneven the search restarts. |
750 |
|
* Serves as a good time to do some clean-up work, and you can |
751 |
|
* assume you're at DL 0 for the purposes of Contexts. This function |
752 |
|
* should not use the output channel. |
753 |
|
*/ |
754 |
|
virtual void notifyRestart() { } |
755 |
|
|
756 |
|
/** |
757 |
|
* Identify this theory (for debugging, dynamic configuration, |
758 |
|
* etc..) |
759 |
|
*/ |
760 |
|
virtual std::string identify() const = 0; |
761 |
|
|
762 |
|
/** Set user attribute |
763 |
|
* This function is called when an attribute is set by a user. In SMT-LIBv2 this is done |
764 |
|
* via the syntax (! n :attr) |
765 |
|
*/ |
766 |
|
virtual void setUserAttribute(const std::string& attr, Node n, std::vector<Node> node_values, std::string str_value) { |
767 |
|
Unimplemented() << "Theory " << identify() |
768 |
|
<< " doesn't support Theory::setUserAttribute interface"; |
769 |
|
} |
770 |
|
|
771 |
|
typedef context::CDList<Assertion>::const_iterator assertions_iterator; |
772 |
|
|
773 |
|
/** |
774 |
|
* Provides access to the facts queue, primarily intended for theory |
775 |
|
* debugging purposes. |
776 |
|
* |
777 |
|
* @return the iterator to the beginning of the fact queue |
778 |
|
*/ |
779 |
149446 |
assertions_iterator facts_begin() const { |
780 |
149446 |
return d_facts.begin(); |
781 |
|
} |
782 |
|
|
783 |
|
/** |
784 |
|
* Provides access to the facts queue, primarily intended for theory |
785 |
|
* debugging purposes. |
786 |
|
* |
787 |
|
* @return the iterator to the end of the fact queue |
788 |
|
*/ |
789 |
816710 |
assertions_iterator facts_end() const { |
790 |
816710 |
return d_facts.end(); |
791 |
|
} |
792 |
|
/** |
793 |
|
* Whether facts have been asserted to this theory. |
794 |
|
* |
795 |
|
* @return true iff facts have been asserted to this theory. |
796 |
|
*/ |
797 |
5480 |
bool hasFacts() { return !d_facts.empty(); } |
798 |
|
|
799 |
|
/** Return total number of facts asserted to this theory */ |
800 |
42494 |
size_t numAssertions() { |
801 |
42494 |
return d_facts.size(); |
802 |
|
} |
803 |
|
|
804 |
|
typedef context::CDList<TNode>::const_iterator shared_terms_iterator; |
805 |
|
|
806 |
|
/** |
807 |
|
* Provides access to the shared terms, primarily intended for theory |
808 |
|
* debugging purposes. |
809 |
|
* |
810 |
|
* @return the iterator to the beginning of the shared terms list |
811 |
|
*/ |
812 |
140893 |
shared_terms_iterator shared_terms_begin() const { |
813 |
140893 |
return d_sharedTerms.begin(); |
814 |
|
} |
815 |
|
|
816 |
|
/** |
817 |
|
* Provides access to the facts queue, primarily intended for theory |
818 |
|
* debugging purposes. |
819 |
|
* |
820 |
|
* @return the iterator to the end of the shared terms list |
821 |
|
*/ |
822 |
155943 |
shared_terms_iterator shared_terms_end() const { |
823 |
155943 |
return d_sharedTerms.end(); |
824 |
|
} |
825 |
|
|
826 |
|
|
827 |
|
/** |
828 |
|
* This is a utility function for constructing a copy of the currently shared terms |
829 |
|
* in a queriable form. As this is |
830 |
|
*/ |
831 |
|
std::unordered_set<TNode> currentlySharedTerms() const; |
832 |
|
|
833 |
|
/** |
834 |
|
* This allows the theory to be queried for whether a literal, lit, is |
835 |
|
* entailed by the theory. This returns a pair of a Boolean and a node E. |
836 |
|
* |
837 |
|
* If the Boolean is true, then E is a formula that entails lit and E is propositionally |
838 |
|
* entailed by the assertions to the theory. |
839 |
|
* |
840 |
|
* If the Boolean is false, it is "unknown" if lit is entailed and E may be |
841 |
|
* any node. |
842 |
|
* |
843 |
|
* The literal lit is either an atom a or (not a), which must belong to the theory: |
844 |
|
* There is some TheoryOfMode m s.t. Theory::theoryOf(m, a) == this->getId(). |
845 |
|
* |
846 |
|
* There are NO assumptions that a or the subterms of a have been |
847 |
|
* preprocessed in any form. This includes ppRewrite, rewriting, |
848 |
|
* preregistering, registering, definition expansion or ITE removal! |
849 |
|
* |
850 |
|
* Theories are free to limit the amount of effort they use and so may |
851 |
|
* always opt to return "unknown". Both "unknown" and "not entailed", |
852 |
|
* may return for E a non-boolean Node (e.g. Node::null()). (There is no explicit output |
853 |
|
* for the negation of lit is entailed.) |
854 |
|
* |
855 |
|
* If lit is theory valid, the return result may be the Boolean constant |
856 |
|
* true for E. |
857 |
|
* |
858 |
|
* If lit is entailed by multiple assertions on the theory's getFact() |
859 |
|
* queue, a_1, a_2, ... and a_k, this may return E=(and a_1 a_2 ... a_k) or |
860 |
|
* another theory entailed explanation E=(and (and a_1 a_2) (and a3 a_4) ... a_k) |
861 |
|
* |
862 |
|
* If lit is entailed by a single assertion on the theory's getFact() |
863 |
|
* queue, say a, this may return E=a. |
864 |
|
* |
865 |
|
* The theory may always return false! |
866 |
|
* |
867 |
|
* Theories may not touch their output stream during an entailment check. |
868 |
|
* |
869 |
|
* @param lit a literal belonging to the theory. |
870 |
|
* @return a pair <b,E> s.t. if b is true, then a formula E such that |
871 |
|
* E |= lit in the theory. |
872 |
|
*/ |
873 |
|
virtual std::pair<bool, Node> entailmentCheck(TNode lit); |
874 |
|
};/* class Theory */ |
875 |
|
|
876 |
|
std::ostream& operator<<(std::ostream& os, theory::Theory::Effort level); |
877 |
|
|
878 |
|
|
879 |
12119598 |
inline theory::Assertion Theory::get() { |
880 |
12119598 |
Assert(!done()) << "Theory::get() called with assertion queue empty!"; |
881 |
|
|
882 |
|
// Get the assertion |
883 |
12119598 |
Assertion fact = d_facts[d_factsHead]; |
884 |
12119598 |
d_factsHead = d_factsHead + 1; |
885 |
|
|
886 |
12119598 |
Trace("theory") << "Theory::get() => " << fact << " (" << d_facts.size() - d_factsHead << " left)" << std::endl; |
887 |
|
|
888 |
12119598 |
return fact; |
889 |
|
} |
890 |
|
|
891 |
|
inline std::ostream& operator<<(std::ostream& out, |
892 |
|
const cvc5::theory::Theory& theory) |
893 |
|
{ |
894 |
|
return out << theory.identify(); |
895 |
|
} |
896 |
|
|
897 |
|
inline std::ostream& operator << (std::ostream& out, theory::Theory::PPAssertStatus status) { |
898 |
|
switch (status) { |
899 |
|
case theory::Theory::PP_ASSERT_STATUS_SOLVED: |
900 |
|
out << "SOLVE_STATUS_SOLVED"; break; |
901 |
|
case theory::Theory::PP_ASSERT_STATUS_UNSOLVED: |
902 |
|
out << "SOLVE_STATUS_UNSOLVED"; break; |
903 |
|
case theory::Theory::PP_ASSERT_STATUS_CONFLICT: |
904 |
|
out << "SOLVE_STATUS_CONFLICT"; break; |
905 |
|
default: |
906 |
|
Unhandled(); |
907 |
|
} |
908 |
|
return out; |
909 |
|
} |
910 |
|
|
911 |
|
} // namespace theory |
912 |
|
} // namespace cvc5 |
913 |
|
|
914 |
|
#endif /* CVC5__THEORY__THEORY_H */ |